mirror of
https://github.com/atdunbg/Nekosonic-Music.git
synced 2026-06-22 00:58:51 +08:00
refactor: 拆分 App.vue 为独立组件,修复多项敷衍方案
- 提取 TitleBar、Sidebar、RoamDrawer、CloseModal 四个组件 - App.vue 从 676 行精简至 238 行,职责更清晰 - 修复评论点赞无限+1:改为基于服务端 liked 字段切换 - 修复评论点赞无防重复:添加 likingSet 锁 - 修复评论点赞用本地缓存:likedIds 改为从服务端 likelist API 同步 - 删除 likedIds 写 localStorage 的 watch - 播放失败/FM加载失败/减少推荐失败添加 showToast 用户提示 - 抽屉遮罩下标题栏按钮保持原色(z-10 提升至遮罩之上)
This commit is contained in:
@ -1,32 +1,34 @@
|
||||
<template>
|
||||
<div class="bg-subtle rounded-xl p-3" ref="scrollContainer">
|
||||
<div v-if="loading" class="py-8 text-center text-content-2 text-sm">加载中...</div>
|
||||
<div v-if="loading" class="py-8 text-center text-sm" :class="darkMode ? 'text-white/60' : 'text-content-2'">加载中...</div>
|
||||
|
||||
<div v-else-if="comments.length === 0" class="py-8 text-center">
|
||||
<IconMessageSquare class="mx-auto mb-2 text-content-3 w-10 h-10" />
|
||||
<p class="text-content-3 text-sm">暂无评论</p>
|
||||
<IconMessageSquare class="mx-auto mb-2 w-10 h-10" :class="darkMode ? 'text-white/40' : 'text-content-3'" />
|
||||
<p class="text-sm" :class="darkMode ? 'text-white/40' : 'text-content-3'">暂无评论</p>
|
||||
</div>
|
||||
|
||||
<div v-else class="space-y-3">
|
||||
<div
|
||||
v-for="comment in comments"
|
||||
:key="comment.commentId"
|
||||
class="p-3 rounded-xl bg-surface/50"
|
||||
class="p-3 rounded-xl"
|
||||
:class="darkMode ? 'bg-white/8' : 'bg-surface/50'"
|
||||
>
|
||||
<div class="flex items-center gap-3">
|
||||
<img :src="comment.user.avatarUrl" class="w-8 h-8 rounded-full object-cover flex-shrink-0" />
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="text-sm font-medium text-content truncate">{{ comment.user.nickname }}</p>
|
||||
<p class="text-xs text-content-3">{{ new Date(comment.time).toLocaleDateString('zh-CN') }}</p>
|
||||
<p class="text-sm font-medium truncate" :class="darkMode ? 'text-white/90' : 'text-content'">{{ comment.user.nickname }}</p>
|
||||
<p class="text-xs" :class="darkMode ? 'text-white/40' : 'text-content-3'">{{ new Date(comment.time).toLocaleDateString('zh-CN') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<p class="mt-2 text-sm text-content-2 leading-relaxed">{{ comment.content }}</p>
|
||||
<p class="mt-2 text-sm leading-relaxed" :class="darkMode ? 'text-white/70' : 'text-content-2'">{{ comment.content }}</p>
|
||||
<div class="mt-2 flex justify-end">
|
||||
<button
|
||||
@click="likeComment(comment.commentId)"
|
||||
class="flex items-center gap-1 text-content-3 hover:text-danger transition text-xs"
|
||||
class="flex items-center gap-1 transition text-xs"
|
||||
:class="comment.liked ? 'text-danger' : (darkMode ? 'text-white/40 hover:text-danger' : 'text-content-3 hover:text-danger')"
|
||||
>
|
||||
<IconHeart style="font-size: 14px" />
|
||||
<IconHeart style="font-size: 14px" :class="comment.liked ? '[&>path]:fill-current [&>path]:stroke-0' : ''" />
|
||||
<span>{{ comment.likedCount }}</span>
|
||||
</button>
|
||||
</div>
|
||||
@ -34,7 +36,7 @@
|
||||
<div ref="sentinel" class="h-1"></div>
|
||||
</div>
|
||||
|
||||
<div v-if="loadingMore" class="py-4 text-center text-content-3 text-sm">加载中...</div>
|
||||
<div v-if="loadingMore" class="py-4 text-center text-sm" :class="darkMode ? 'text-white/40' : 'text-content-3'">加载中...</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -47,6 +49,7 @@ import IconHeart from '~icons/lucide/heart'
|
||||
const props = defineProps<{
|
||||
type: number
|
||||
id: number
|
||||
darkMode?: boolean
|
||||
}>()
|
||||
|
||||
const comments = ref<any[]>([])
|
||||
@ -104,22 +107,29 @@ function loadMore() {
|
||||
fetchComments()
|
||||
}
|
||||
|
||||
const likingSet = ref(new Set<number>())
|
||||
|
||||
async function likeComment(cid: number) {
|
||||
if (likingSet.value.has(cid)) return
|
||||
const target = comments.value.find(c => c.commentId === cid)
|
||||
if (!target) return
|
||||
const liked = !!target.liked
|
||||
likingSet.value.add(cid)
|
||||
try {
|
||||
await invoke('comment_like', {
|
||||
query: {
|
||||
t: 1,
|
||||
t: liked ? 0 : 1,
|
||||
type: props.type,
|
||||
id: props.id,
|
||||
cid
|
||||
}
|
||||
})
|
||||
const target = comments.value.find(c => c.commentId === cid)
|
||||
if (target) {
|
||||
target.likedCount++
|
||||
}
|
||||
target.liked = !liked
|
||||
target.likedCount += liked ? -1 : 1
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
} finally {
|
||||
likingSet.value.delete(cid)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user