Compare commits

...

2 Commits

Author SHA1 Message Date
imsyy
58e3c6e21c 🐞 fix: 修复本地歌词覆盖失效 2025-11-10 17:07:43 +08:00
imsyy
68756f2502 🐞 fix: 修复进度条点击及拖拽问题 #535 2025-11-10 14:37:52 +08:00
6 changed files with 118 additions and 48 deletions

2
components.d.ts vendored
View File

@@ -101,7 +101,6 @@ declare module 'vue' {
NQrCode: typeof import('naive-ui')['NQrCode']
NRadio: typeof import('naive-ui')['NRadio']
NRadioGroup: typeof import('naive-ui')['NRadioGroup']
NResult: typeof import('naive-ui')['NResult']
NScrollbar: typeof import('naive-ui')['NScrollbar']
NSelect: typeof import('naive-ui')['NSelect']
NSkeleton: typeof import('naive-ui')['NSkeleton']
@@ -124,6 +123,7 @@ declare module 'vue' {
PlayerData: typeof import('./src/components/Player/PlayerData.vue')['default']
PlayerMenu: typeof import('./src/components/Player/PlayerMenu.vue')['default']
PlayerRightMenu: typeof import('./src/components/Player/PlayerRightMenu.vue')['default']
PlayerSlider: typeof import('./src/components/Player/PlayerSlider.vue')['default']
PlayerSpectrum: typeof import('./src/components/Player/PlayerSpectrum.vue')['default']
PlaylistAdd: typeof import('./src/components/Modal/PlaylistAdd.vue')['default']
PlaySetting: typeof import('./src/components/Setting/PlaySetting.vue')['default']

View File

@@ -8,17 +8,7 @@
]"
>
<!-- 进度条 -->
<n-slider
v-model:value="statusStore.progress"
:step="0.01"
:min="0"
:max="100"
:tooltip="false"
:keyboard="false"
class="player-slider"
@dragstart="player.pause(false)"
@dragend="sliderDragend"
/>
<PlayerSlider />
<!-- 信息 -->
<div class="play-data">
<!-- 封面 -->
@@ -199,7 +189,7 @@
<script setup lang="ts">
import type { DropdownOption } from "naive-ui";
import { useMusicStore, useStatusStore, useDataStore, useSettingStore } from "@/stores";
import { secondsToTime, calculateCurrentTime, convertSecondsToTime } from "@/utils/time";
import { secondsToTime, convertSecondsToTime } from "@/utils/time";
import { renderIcon, coverLoaded } from "@/utils/helper";
import { toLikeSong } from "@/utils/auth";
import {
@@ -267,15 +257,6 @@ const songMoreOptions = computed<DropdownOption[]>(() => {
];
});
// 进度条拖拽结束
const sliderDragend = () => {
const seek = calculateCurrentTime(statusStore.progress, statusStore.duration);
statusStore.playStatus = true;
// 调整进度
player.setSeek(seek);
player.play();
};
// 是否展示歌词
const isShowLyrics = computed(() => {
const isHasLrc = musicStore.isHasLrc;

View File

@@ -77,17 +77,7 @@
<!-- 进度条 -->
<div class="slider">
<span>{{ secondsToTime(statusStore.currentTime) }}</span>
<n-slider
v-model:value="statusStore.progress"
:step="0.01"
:min="0"
:max="100"
:tooltip="false"
:keyboard="false"
class="player-slider"
@dragstart="player.pause(false)"
@dragend="sliderDragend"
/>
<PlayerSlider :show-tooltip="false" />
<span>{{ secondsToTime(statusStore.duration) }}</span>
</div>
</div>
@@ -102,7 +92,7 @@
<script setup lang="ts">
import { useMusicStore, useStatusStore, useDataStore } from "@/stores";
import { secondsToTime, calculateCurrentTime } from "@/utils/time";
import { secondsToTime } from "@/utils/time";
import { openDownloadSong, openPlaylistAdd } from "@/utils/modal";
import { toLikeSong } from "@/utils/auth";
import player from "@/utils/player";
@@ -110,15 +100,6 @@ import player from "@/utils/player";
const dataStore = useDataStore();
const musicStore = useMusicStore();
const statusStore = useStatusStore();
// 进度条拖拽结束
const sliderDragend = () => {
const seek = calculateCurrentTime(statusStore.progress, statusStore.duration);
statusStore.playStatus = true;
// 调整进度
player.setSeek(seek);
player.play();
};
</script>
<style lang="scss" scoped>

View File

@@ -0,0 +1,77 @@
<template>
<n-slider
v-model:value="sliderProgress"
:step="0.01"
:min="0"
:max="statusStore.duration"
:keyboard="false"
:format-tooltip="formatTooltip"
:tooltip="showTooltip"
:show-tooltip="showSliderTooltip"
class="player-slider"
@mouseenter="showSliderTooltip = true"
@mouseleave="showSliderTooltip = false"
@dragstart="startDrag"
@dragend="endDrag"
/>
</template>
<script setup lang="ts">
import { useStatusStore } from "@/stores";
import player from "@/utils/player";
import { secondsToTime } from "@/utils/time";
withDefaults(defineProps<{ showTooltip?: boolean }>(), { showTooltip: true });
const statusStore = useStatusStore();
// 拖动时的临时值
const dragValue = ref(0);
// 是否拖动
const isDragging = ref(false);
// 是否显示提示
const showSliderTooltip = ref(false);
// 实时进度
const sliderProgress = computed({
// 获取进度
get: () => (isDragging.value ? dragValue.value : statusStore.currentTime),
// 设置进度
set: (value) => {
// 若为拖动中
if (isDragging.value) {
dragValue.value = value;
return;
}
// 结束或者为点击
useThrottleFn((value: number) => {
player.setSeek(value);
}, 30);
},
});
// 开始拖拽
const startDrag = () => {
isDragging.value = true;
// 立即赋值当前时间
dragValue.value = statusStore.currentTime;
};
// 结束拖拽
const endDrag = () => {
isDragging.value = false;
// 直接更改进度
player.setSeek(dragValue.value);
};
// 格式化提示
const formatTooltip = (value: number) => {
return `${secondsToTime(value)} / ${secondsToTime(statusStore.duration)}`;
};
</script>
<style scoped lang="scss">
.player-slider {
width: 100%;
}
</style>

View File

@@ -1,5 +1,11 @@
import { useMusicStore, useSettingStore, useStatusStore } from "@/stores";
import { parsedLyricsData, parseTTMLToAMLL, parseTTMLToYrc, resetSongLyric } from "../lyric";
import {
parsedLyricsData,
parseLocalLyric,
parseTTMLToAMLL,
parseTTMLToYrc,
resetSongLyric,
} from "../lyric";
import { songLyric, songLyricTTML } from "@/api/song";
import { parseTTML } from "@applemusic-like-lyrics/lyric";
import { LyricLine } from "@applemusic-like-lyrics/core";
@@ -26,6 +32,7 @@ export const getLyricData = async (id: number) => {
try {
// 检测本地歌词覆盖
const getLyric = getLyricFun(settingStore.localLyricPath, id);
// 并发请求:如果 TTML 先到并且有效,则直接采用 TTML不再等待或覆盖为 LRC
const lrcPromise = getLyric("lrc", songLyric);
const ttmlPromise = settingStore.enableTTMLLyric ? getLyric("ttml", songLyricTTML) : null;
@@ -44,6 +51,19 @@ export const getLyricData = async (id: number) => {
statusStore.usingTTMLLyric = false;
return;
}
// 本地 TTML 使用 parseLocalLyric在线 TTML 使用原有解析方式
if (ttmlLocal) {
parseLocalLyric(ttmlContent, "ttml");
statusStore.usingTTMLLyric = true;
ttmlAdopted = true;
if (!settled) {
statusStore.lyricLoading = false;
settled = true;
}
console.log("✅ TTML lyrics adopted (prefer TTML)");
return;
}
// 在线 TTML 解析
const parsedResult = parseTTML(ttmlContent);
if (!parsedResult?.lines?.length) {
statusStore.usingTTMLLyric = false;
@@ -99,7 +119,14 @@ export const getLyricData = async (id: number) => {
const { lyric: lyricRes, isLocal: lyricLocal } = await lrcPromise;
// 如果 TTML 已采用,则忽略 LRC
if (ttmlAdopted) return;
parsedLyricsData(lyricRes, lyricLocal && !settingStore.enableExcludeLocalLyrics);
// 如果没有歌词内容,直接返回
if (!lyricRes) return;
// 本地歌词使用 parseLocalLyric在线歌词使用 parsedLyricsData
if (lyricLocal) {
parseLocalLyric(lyricRes, "lrc");
} else {
parsedLyricsData(lyricRes, !settingStore.enableExcludeLocalLyrics);
}
statusStore.usingTTMLLyric = false;
if (!settled) {
statusStore.lyricLoading = false;

View File

@@ -637,6 +637,7 @@ onBeforeUnmount(() => {
.lyric-container {
height: 100%;
padding: 0 8px;
cursor: move;
.lyric-line {
width: 100%;
line-height: normal;
@@ -756,15 +757,18 @@ onBeforeUnmount(() => {
}
&.locked {
cursor: default;
.song-name,
.menu-btn,
.lyric-container {
pointer-events: none;
}
&:hover {
.lock-btn {
opacity: 1;
pointer-events: auto;
}
}
}
.lyric-container {
cursor: move;
}
}
</style>