Skip to content

Commit 4c337fa

Browse files
committed
🦄 refactor: 拆分庞大的函数
1 parent d843add commit 4c337fa

1 file changed

Lines changed: 147 additions & 99 deletions

File tree

src/core/player/PlayModeManager.ts

Lines changed: 147 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -63,32 +63,146 @@ export class PlayModeManager {
6363
}
6464

6565
/**
66-
* 切换随机模式
67-
* @param mode 可选,直接设置目标模式。如果不传则按 Off -> On -> Heartbeat -> Off 顺序轮转
68-
* @param playAction 回调函数,用于在心动模式下触发播放。通常你应该传入 PlayerController.play,或者其他类似的方法
66+
* 中止之前的请求并清除 Loading 消息
67+
* @returns 新的 AbortSignal
6968
*/
70-
public async toggleShuffle(mode?: ShuffleModeType, playAction?: () => Promise<void>) {
69+
private resetCurrentTask(): AbortSignal {
70+
if (this.currentAbortController) {
71+
this.currentAbortController.abort();
72+
}
73+
this.clearLoadingMessage();
74+
this.currentAbortController = new AbortController();
75+
return this.currentAbortController.signal;
76+
}
77+
78+
/**
79+
* 计算下一个随机模式
80+
*/
81+
private calculateNextShuffleMode(
82+
currentMode: ShuffleModeType,
83+
targetMode?: ShuffleModeType,
84+
): ShuffleModeType {
85+
if (targetMode) return targetMode;
86+
if (currentMode === "off") return "on";
87+
if (currentMode === "on") return "heartbeat";
88+
return "off";
89+
}
90+
91+
/**
92+
* 执行开启随机模式的操作
93+
*/
94+
private async applyShuffleOn(signal: AbortSignal) {
7195
const dataStore = useDataStore();
7296
const statusStore = useStatusStore();
7397
const musicStore = useMusicStore();
7498

75-
if (this.currentAbortController) {
76-
this.currentAbortController.abort();
99+
const currentList = [...dataStore.playList];
100+
// 备份原始列表
101+
await dataStore.setOriginalPlayList(currentList);
102+
103+
if (signal.aborted) return;
104+
105+
// 打乱列表
106+
const shuffled = shuffleArray(currentList);
107+
await dataStore.setPlayList(shuffled);
108+
109+
// 修正当前播放索引
110+
const idx = shuffled.findIndex((s) => s.id === musicStore.playSong?.id);
111+
if (idx !== -1) statusStore.playIndex = idx;
112+
}
113+
114+
/**
115+
* 执行开启心动模式的操作
116+
*/
117+
private async applyHeartbeatMode(
118+
signal: AbortSignal,
119+
previousMode: ShuffleModeType,
120+
playAction?: () => Promise<void>,
121+
) {
122+
const statusStore = useStatusStore();
123+
const musicStore = useMusicStore();
124+
const dataStore = useDataStore();
125+
126+
if (isLogin() !== 1) {
127+
// 未登录,回滚状态
128+
statusStore.shuffleMode = previousMode;
129+
if (isLogin() === 0) {
130+
openUserLogin(true);
131+
} else {
132+
window.$message.warning("该登录模式暂不支持该操作");
133+
}
134+
return;
135+
}
136+
137+
if (previousMode === "heartbeat") {
138+
if (playAction) await playAction();
139+
statusStore.showFullPlayer = true;
140+
return;
77141
}
142+
143+
this.loadingMessage = window.$message.loading("心动模式开启中...", {
144+
duration: 0, // 不自动关闭,必须手动 destroy
145+
});
146+
147+
const pid =
148+
musicStore.playPlaylistId || (await dataStore.getUserLikePlaylist())?.detail?.id || 0;
149+
const currentSongId = musicStore.playSong?.id || 0;
150+
151+
if (!currentSongId) throw new Error("无播放歌曲");
152+
153+
const res = await heartRateList(currentSongId, pid, undefined, signal);
154+
if (res.code !== 200) throw new Error("获取推荐失败");
155+
156+
const recList = formatSongsList(res.data);
157+
158+
// 混合列表
159+
const currentList = [...dataStore.playList];
160+
const mixedList = interleaveLists(currentList, recList);
161+
162+
await dataStore.setPlayList(mixedList);
163+
164+
const idx = mixedList.findIndex((s) => s.id === currentSongId);
165+
if (idx !== -1) statusStore.playIndex = idx;
166+
78167
this.clearLoadingMessage();
79-
this.currentAbortController = new AbortController();
80-
const { signal } = this.currentAbortController;
168+
window.$message.success("心动模式已开启");
169+
}
81170

82-
const currentMode = statusStore.shuffleMode;
83-
let nextMode: ShuffleModeType;
171+
/**
172+
* 执行关闭随机模式的操作
173+
*
174+
* 会恢复原始列表 和/或 清理推荐歌曲
175+
*/
176+
private async applyShuffleOff() {
177+
const dataStore = useDataStore();
178+
const statusStore = useStatusStore();
179+
const musicStore = useMusicStore();
84180

85-
if (mode) {
86-
nextMode = mode;
181+
// 恢复原始列表
182+
const original = await dataStore.getOriginalPlayList();
183+
184+
if (original && original.length > 0) {
185+
await dataStore.setPlayList(original);
186+
const idx = original.findIndex((s) => s.id === musicStore.playSong?.id);
187+
statusStore.playIndex = idx !== -1 ? idx : 0;
188+
await dataStore.clearOriginalPlayList();
87189
} else {
88-
if (currentMode === "off") nextMode = "on";
89-
else if (currentMode === "on") nextMode = "heartbeat";
90-
else nextMode = "off";
190+
const cleaned = cleanRecommendations(dataStore.playList);
191+
await dataStore.setPlayList(cleaned);
91192
}
193+
}
194+
195+
/**
196+
* 切换随机模式
197+
* @param mode 可选,直接设置目标模式。如果不传则按 Off -> On -> Heartbeat -> Off 顺序轮转
198+
* @param playAction 回调函数,用于在心动模式下触发播放。通常你应该传入 PlayerController.play,或者其他类似的方法
199+
*/
200+
public async toggleShuffle(mode?: ShuffleModeType, playAction?: () => Promise<void>) {
201+
const statusStore = useStatusStore();
202+
const signal = this.resetCurrentTask();
203+
204+
const currentMode = statusStore.shuffleMode;
205+
const nextMode = this.calculateNextShuffleMode(currentMode, mode);
92206

93207
if (nextMode === currentMode) return;
94208

@@ -99,97 +213,31 @@ export class PlayModeManager {
99213
// 将耗时的数据处理扔到 UI 图标更新后再进行,避免打乱庞大列表导致点击延迟
100214
setTimeout(async () => {
101215
if (signal.aborted) return;
216+
102217
try {
103-
if (nextMode === "on") {
104-
const currentList = [...dataStore.playList];
105-
// 备份原始列表
106-
await dataStore.setOriginalPlayList(currentList);
107-
if (signal.aborted) return;
108-
// 打乱列表
109-
const shuffled = shuffleArray(currentList);
110-
await dataStore.setPlayList(shuffled);
111-
// 修正当前播放索引
112-
const idx = shuffled.findIndex((s) => s.id === musicStore.playSong?.id);
113-
if (idx !== -1) statusStore.playIndex = idx;
114-
} else if (nextMode === "heartbeat") {
115-
const loginStatus = isLogin();
116-
if (loginStatus !== 1) {
117-
// 未登录,回滚状态
118-
statusStore.shuffleMode = previousMode;
119-
if (loginStatus === 0) {
120-
openUserLogin(true);
121-
} else {
122-
window.$message.warning("该登录模式暂不支持该操作");
123-
}
124-
return;
125-
}
126-
127-
if (previousMode === "heartbeat") {
128-
if (playAction) await playAction();
129-
statusStore.showFullPlayer = true;
130-
return;
131-
}
132-
133-
this.loadingMessage = window.$message.loading("心动模式开启中...", {
134-
duration: 0, // 不自动关闭,必须手动 destroy
135-
});
136-
137-
try {
138-
const pid =
139-
musicStore.playPlaylistId || (await dataStore.getUserLikePlaylist())?.detail?.id || 0;
140-
const currentSongId = musicStore.playSong?.id || 0;
141-
142-
if (!currentSongId) throw new Error("无播放歌曲");
143-
144-
const res = await heartRateList(currentSongId, pid, undefined, signal);
145-
if (res.code !== 200) throw new Error("获取推荐失败");
146-
147-
const recList = formatSongsList(res.data);
148-
149-
// 混合列表
150-
const currentList = [...dataStore.playList];
151-
const mixedList = interleaveLists(currentList, recList);
152-
153-
await dataStore.setPlayList(mixedList);
154-
155-
const idx = mixedList.findIndex((s) => s.id === currentSongId);
156-
if (idx !== -1) statusStore.playIndex = idx;
157-
158-
this.clearLoadingMessage();
159-
window.$message.success("心动模式已开启");
160-
} catch (e) {
161-
this.clearLoadingMessage();
162-
163-
if (signal.aborted || axios.isCancel(e)) {
164-
return;
165-
}
166-
167-
console.error(e);
168-
window.$message.error("心动模式开启失败");
169-
// 失败回滚
170-
statusStore.shuffleMode = previousMode;
171-
}
172-
} else {
173-
// 恢复原始列表
174-
const original = await dataStore.getOriginalPlayList();
175-
176-
if (original && original.length > 0) {
177-
await dataStore.setPlayList(original);
178-
const idx = original.findIndex((s) => s.id === musicStore.playSong?.id);
179-
statusStore.playIndex = idx !== -1 ? idx : 0;
180-
await dataStore.clearOriginalPlayList();
181-
} else {
182-
const cleaned = cleanRecommendations(dataStore.playList);
183-
await dataStore.setPlayList(cleaned);
184-
}
218+
switch (nextMode) {
219+
case "on":
220+
await this.applyShuffleOn(signal);
221+
break;
222+
case "heartbeat":
223+
await this.applyHeartbeatMode(signal, previousMode, playAction);
224+
break;
225+
default:
226+
await this.applyShuffleOff();
227+
break;
185228
}
186229
} catch (e) {
187-
if (signal.aborted) return;
230+
if (signal.aborted || axios.isCancel(e)) return;
231+
188232
this.clearLoadingMessage();
233+
189234
console.error("切换模式时发生错误:", e);
235+
190236
// 失败回滚
191237
statusStore.shuffleMode = previousMode;
192-
window.$message.error("模式切换出错");
238+
239+
const errorMsg = (e as Error).message || "模式切换出错";
240+
window.$message.error(errorMsg);
193241
}
194242
}, 10);
195243
}

0 commit comments

Comments
 (0)