feat: 优化随机播放问题 & 播放页字体抖动效果优化

This commit is contained in:
底层用户
2025-08-20 11:35:07 +08:00
parent 201186bab2
commit b2ddb9f4e2
5 changed files with 96 additions and 22 deletions

View File

@@ -324,6 +324,7 @@ onBeforeUnmount(() => {
padding: 10px 16px;
transform: scale(0.86);
transform-origin: left center;
will-change: filter, opacity, transform;
transition:
filter 0.35s,
opacity 0.35s,

View File

@@ -15,6 +15,7 @@ import { formatCategoryList } from "@/utils/format";
interface ListState {
playList: SongType[];
originalPlayList: SongType[];
historyList: SongType[];
cloudPlayList: SongType[];
searchHistory: string[];
@@ -54,6 +55,8 @@ export const useDataStore = defineStore("data", {
state: (): ListState => ({
// 播放列表
playList: [],
// 原始播放列表
originalPlayList: [],
// 播放历史
historyList: [],
// 搜索历史
@@ -157,6 +160,29 @@ export const useDataStore = defineStore("data", {
throw error;
}
},
// 保存原始播放列表
async setOriginalPlayList(data: SongType[]): Promise<void> {
const snapshot = cloneDeep(data);
this.originalPlayList = snapshot;
await musicDB.setItem("originalPlayList", snapshot);
},
// 获取原始播放列表
async getOriginalPlayList(): Promise<SongType[] | null> {
if (Array.isArray(this.originalPlayList) && this.originalPlayList.length > 0) {
return this.originalPlayList;
}
const data = (await musicDB.getItem("originalPlayList")) as SongType[] | null;
if (Array.isArray(data) && data.length > 0) {
this.originalPlayList = data;
return data;
}
return null;
},
// 清除原始播放列表
async clearOriginalPlayList(): Promise<void> {
this.originalPlayList = [];
await musicDB.setItem("originalPlayList", []);
},
// 新增下一首播放歌曲
async setNextPlaySong(song: SongType, index: number): Promise<number> {
// 若为空,则直接添加

View File

@@ -40,6 +40,17 @@ class Player {
// 初始化媒体会话
this.initMediaSession();
}
/**
* 洗牌数组Fisher-Yates
*/
private shuffleArray<T>(arr: T[]): T[] {
const copy = arr.slice();
for (let i = copy.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[copy[i], copy[j]] = [copy[j], copy[i]];
}
return copy;
}
/**
* 重置状态
*/
@@ -667,19 +678,15 @@ class Player {
this.setSeek(0);
await this.play();
}
// 列表循环或处于心动模式
if (playSongMode === "repeat" || playHeartbeatMode || playSong.type === "radio") {
// 列表循环或处于心动模式或随机模式
if (
playSongMode === "repeat" ||
playSongMode === "shuffle" ||
playHeartbeatMode ||
playSong.type === "radio"
) {
statusStore.playIndex += type === "next" ? 1 : -1;
}
// 随机播放
else if (playSongMode === "shuffle") {
let newIndex: number;
// 确保不会随机到同一首
do {
newIndex = Math.floor(Math.random() * playListLength);
} while (newIndex === statusStore.playIndex);
statusStore.playIndex = newIndex;
}
// 单曲循环
else if (playSongMode === "repeat-once") {
statusStore.lyricIndex = -1;
@@ -708,28 +715,65 @@ class Player {
* 切换播放模式
* @param mode 播放模式 repeat / repeat-once / shuffle
*/
togglePlayMode(mode: PlayModeType | false) {
async togglePlayMode(mode: PlayModeType | false) {
const statusStore = useStatusStore();
const dataStore = useDataStore();
const musicStore = useMusicStore();
// 退出心动模式
if (statusStore.playHeartbeatMode) this.toggleHeartMode(false);
// 若传入了指定模式
// 计算目标模式
let targetMode: PlayModeType;
if (mode) {
statusStore.playSongMode = mode;
targetMode = mode;
} else {
switch (statusStore.playSongMode) {
case "repeat":
statusStore.playSongMode = "repeat-once";
targetMode = "repeat-once";
break;
case "shuffle":
statusStore.playSongMode = "repeat";
targetMode = "repeat";
break;
case "repeat-once":
statusStore.playSongMode = "shuffle";
targetMode = "shuffle";
break;
default:
statusStore.playSongMode = "repeat";
targetMode = "repeat";
}
}
// 进入随机模式:保存原顺序并打乱当前歌单
if (targetMode === "shuffle" && statusStore.playSongMode !== "shuffle") {
const currentList = dataStore.playList;
if (currentList && currentList.length > 1) {
const currentSongId = musicStore.playSong?.id;
await dataStore.setOriginalPlayList(currentList);
const shuffled = this.shuffleArray(currentList);
await dataStore.setPlayList(shuffled);
if (currentSongId) {
const newIndex = shuffled.findIndex((s: any) => s?.id === currentSongId);
if (newIndex !== -1) useStatusStore().playIndex = newIndex;
}
}
}
// 离开随机模式:恢复到原顺序
if (
statusStore.playSongMode === "shuffle" &&
(targetMode === "repeat" || targetMode === "repeat-once")
) {
const original = await dataStore.getOriginalPlayList();
if (original && original.length) {
const currentSongId = musicStore.playSong?.id;
await dataStore.setPlayList(original);
if (currentSongId) {
const origIndex = original.findIndex((s: any) => s?.id === currentSongId);
useStatusStore().playIndex = origIndex !== -1 ? origIndex : 0;
} else {
useStatusStore().playIndex = 0;
}
await dataStore.clearOriginalPlayList();
}
}
// 应用模式
statusStore.playSongMode = targetMode;
this.playModeSyncIpc();
}
/**

View File

@@ -9,8 +9,9 @@
"electron/main/utils.ts",
"electron/main/index.d.ts",
"electron/preload/index.d.ts",
"electron/preload/index.ts"
, "dist/lastfm.ts" ],
"electron/preload/index.ts",
"dist/lastfm.ts"
],
"compilerOptions": {
"composite": true,
"types": ["electron-vite/node"]

View File

@@ -5,10 +5,12 @@
"src/**/*",
"src/**/*.vue",
"electron/main/index.d.ts",
"electron/preload/index.d.ts"
, "dist/lastfm.ts" ],
"electron/preload/index.d.ts",
"dist/lastfm.ts"
],
"compilerOptions": {
"composite": true,
"esModuleInterop": true,
"maxNodeModuleJsDepth": 2,
"baseUrl": ".",
"paths": {