Compare commits

...

4 Commits

Author SHA1 Message Date
imsyy
8866996e5b 🐞 fix: 再次修复过慢的歌词请求 2025-11-20 23:23:33 +08:00
imsyy
5d21709c58 🌈 style: 简介改为弹窗 & 优化简介换行 2025-11-20 21:58:12 +08:00
底层用户
54d77d08eb Merge pull request #583 from MoYingJi/fix
fix(playlist): 歌单描述有换行时并没有正确换行
2025-11-20 20:37:10 +08:00
MoYingJi
bd25a8fe2e fix(playlist): 歌单描述有换行时并没有正确换行 2025-11-20 20:30:14 +08:00
6 changed files with 88 additions and 70 deletions

View File

@@ -115,8 +115,8 @@ class LyricManager {
if (!lines.length) return;
result.yrcData = lines;
ttmlAdopted = true;
} catch {
/* empty */
} catch (err) {
throw err;
}
};
// 处理 LRC 歌词
@@ -152,8 +152,11 @@ class LyricManager {
if (!result.yrcData.length && yrcLines.length) {
result.yrcData = yrcLines;
}
} catch {
/* empty */
// 先返回一次,避免 TTML 请求过慢
const lyricData = this.handleLyricExclude(result);
this.setFinalLyric(lyricData, req);
} catch (err) {
throw err;
}
};
// 设置 TTML
@@ -284,13 +287,42 @@ class LyricManager {
: lyricData.yrcData || [],
};
}
/**
* 设置最终歌词
* @param lyricData 歌词数据
* @param req 当前歌词请求
*/
private setFinalLyric(lyricData: SongLyric, req: number) {
const musicStore = useMusicStore();
const statusStore = useStatusStore();
// 若非本次
if (this.activeLyricReq !== req) return;
// 如果只有逐字歌词
if (lyricData.lrcData.length === 0 && lyricData.yrcData.length > 0) {
// 构成普通歌词
lyricData.lrcData = lyricData.yrcData.map((line) => ({
...line,
words: [
{
word: line.words?.map((w) => w.word)?.join("") || "",
startTime: line.startTime || 0,
endTime: line.endTime || 0,
romanWord: line.words?.map((w) => w.romanWord)?.join("") || "",
},
],
}));
}
// 设置歌词
musicStore.setSongLyric(lyricData, true);
// 结束加载状态
statusStore.lyricLoading = false;
}
/**
* 处理歌词
* @param id 歌曲 ID
* @param path 本地歌词路径(可选)
*/
public async handleLyric(id: number, path?: string) {
const musicStore = useMusicStore();
const statusStore = useStatusStore();
const settingStore = useSettingStore();
// 标记当前歌词请求(避免旧请求覆盖新请求)
@@ -326,36 +358,12 @@ class LyricManager {
// 排除内容
lyricData = this.handleLyricExclude(lyricData);
}
// 仅当请求未过期时才更新
if (this.activeLyricReq === req) {
// 如果只有逐字歌词
if (lyricData.lrcData.length === 0 && lyricData.yrcData.length > 0) {
// 构成普通歌词
lyricData.lrcData = lyricData.yrcData.map((line) => ({
...line,
words: [
{
word: line.words?.map((w) => w.word)?.join("") || "",
startTime: line.startTime || 0,
endTime: line.endTime || 0,
romanWord: line.words?.map((w) => w.romanWord)?.join("") || "",
},
],
}));
}
// 设置歌词
musicStore.setSongLyric(lyricData, true);
console.log("最终歌词数据", lyricData);
}
console.log("最终歌词数据", lyricData);
this.setFinalLyric(lyricData, req);
} catch (error) {
console.error("❌ 处理歌词失败:", error);
// 重置歌词
this.resetSongLyric();
} finally {
// 只有当这个请求是最新的时候,才关闭加载状态
if (req === this.activeLyricReq) {
statusStore.lyricLoading = false;
}
}
}
/**

View File

@@ -20,6 +20,7 @@ import ExcludeLyrics from "@/components/Modal/ExcludeLyrics.vue";
import ChangeRate from "@/components/Modal/ChangeRate.vue";
import AutoClose from "@/components/Modal/AutoClose.vue";
import Equalizer from "@/components/Modal/Equalizer.vue";
import { NScrollbar } from "naive-ui";
// 用户协议
export const openUserAgreement = () => {
@@ -294,3 +295,27 @@ export const openEqualizer = () => {
},
});
};
/**
* 打开简介弹窗
* @param content 简介内容
*/
export const openDescModal = (content: string, title: string = "歌单简介") => {
window.$modal.create({
preset: "card",
transformOrigin: "center",
autoFocus: false,
style: { width: "600px" },
title,
content: () => {
return h(
NScrollbar,
{ style: { maxHeight: "400px" } },
{
default: () =>
h("div", { style: { whiteSpace: "pre-wrap" } }, { default: () => content }),
},
);
},
});
};

View File

@@ -34,17 +34,13 @@
</n-h2>
<n-collapse-transition :show="!listScrolling" class="collapse">
<!-- 简介 -->
<n-ellipsis
<n-text
v-if="albumDetailData.description"
:line-clamp="1"
:tooltip="{
trigger: 'click',
placement: 'bottom',
width: 'trigger',
}"
class="description text-hidden"
@click="openDescModal(albumDetailData.description, '专辑简介')"
>
{{ albumDetailData.description }}
</n-ellipsis>
</n-text>
<!-- 信息 -->
<n-flex class="meta">
<div class="item">
@@ -184,7 +180,7 @@ import { renderToolbar } from "@/utils/meta";
import { useDataStore, useStatusStore } from "@/stores";
import { debounce } from "lodash-es";
import { formatTimestamp } from "@/utils/time";
import { openJumpArtist } from "@/utils/modal";
import { openDescModal, openJumpArtist } from "@/utils/modal";
import player from "@/utils/player";
import { toLikeAlbum } from "@/utils/auth";
@@ -379,7 +375,7 @@ onMounted(() => {
border-radius: 8px;
height: 32px;
}
:deep(.n-ellipsis) {
.description {
margin-bottom: 8px;
cursor: pointer;
}

View File

@@ -37,17 +37,13 @@
<n-h2 class="name text-hidden"> 我喜欢的音乐 </n-h2>
<n-collapse-transition :show="!listScrolling" class="collapse">
<!-- 简介 -->
<n-ellipsis
<n-text
v-if="playlistDetailData.description"
:line-clamp="1"
:tooltip="{
trigger: 'click',
placement: 'bottom',
width: 'trigger',
}"
class="description text-hidden"
@click="openDescModal(playlistDetailData.description)"
>
{{ playlistDetailData.description }}
</n-ellipsis>
</n-text>
<!-- 信息 -->
<n-flex class="meta">
<div class="item">
@@ -177,7 +173,7 @@ import { coverLoaded, formatNumber, fuzzySearch, renderIcon } from "@/utils/help
import { renderToolbar } from "@/utils/meta";
import { debounce, isObject, uniqBy } from "lodash-es";
import { useDataStore, useStatusStore } from "@/stores";
import { openBatchList, openUpdatePlaylist } from "@/utils/modal";
import { openBatchList, openDescModal, openUpdatePlaylist } from "@/utils/modal";
import { formatTimestamp } from "@/utils/time";
import { isLogin, updateUserLikePlaylist } from "@/utils/auth";
import player from "@/utils/player";
@@ -541,7 +537,7 @@ onMounted(async () => {
border-radius: 8px;
height: 32px;
}
:deep(.n-ellipsis) {
.description {
margin-bottom: 8px;
cursor: pointer;
}

View File

@@ -50,17 +50,13 @@
</n-h2>
<n-collapse-transition :show="!listScrolling" class="collapse">
<!-- 简介 -->
<n-ellipsis
<n-text
v-if="playlistDetailData.description"
:line-clamp="1"
:tooltip="{
trigger: 'click',
placement: 'bottom',
width: 'trigger',
}"
class="description text-hidden"
@click.stop="openDescModal(playlistDetailData.description)"
>
{{ playlistDetailData.description }}
</n-ellipsis>
</n-text>
<!-- 信息 -->
<n-flex class="meta">
<div class="item">
@@ -228,7 +224,7 @@ import { renderToolbar } from "@/utils/meta";
import { isLogin, toLikePlaylist, updateUserLikePlaylist } from "@/utils/auth";
import { debounce } from "lodash-es";
import { useDataStore, useStatusStore } from "@/stores";
import { openBatchList, openUpdatePlaylist } from "@/utils/modal";
import { openBatchList, openDescModal, openUpdatePlaylist } from "@/utils/modal";
import { formatTimestamp } from "@/utils/time";
import player from "@/utils/player";
@@ -632,7 +628,7 @@ onMounted(() => getPlaylistDetail(playlistId.value));
border-radius: 8px;
height: 32px;
}
:deep(.n-ellipsis) {
.description {
margin-bottom: 8px;
cursor: pointer;
}

View File

@@ -32,17 +32,13 @@
</n-h2>
<n-collapse-transition :show="!listScrolling" class="collapse">
<!-- 简介 -->
<n-ellipsis
<n-text
v-if="radioDetailData.description"
:line-clamp="1"
:tooltip="{
trigger: 'click',
placement: 'bottom',
width: 'trigger',
}"
class="description text-hidden"
@click="openDescModal(radioDetailData.description, '节目简介')"
>
{{ radioDetailData.description }}
</n-ellipsis>
</n-text>
<!-- 信息 -->
<n-flex class="meta">
<div class="item">
@@ -186,6 +182,7 @@ import { radioAllProgram, radioDetail } from "@/api/radio";
import player from "@/utils/player";
import { formatTimestamp } from "@/utils/time";
import { toSubRadio } from "@/utils/auth";
import { openDescModal } from "@/utils/modal";
const router = useRouter();
const dataStore = useDataStore();
@@ -457,7 +454,7 @@ onMounted(() => getRadioDetail(radioId.value));
border-radius: 8px;
height: 32px;
}
:deep(.n-ellipsis) {
.description {
margin-bottom: 8px;
cursor: pointer;
}