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:
2026-05-29 21:13:14 +08:00
parent 57aa9dae61
commit 68f29c8ea8
7 changed files with 594 additions and 468 deletions
+43
View File
@@ -0,0 +1,43 @@
<template>
<div
data-tauri-drag-region
class="h-10 flex items-center justify-between px-4 flex-shrink-0 select-none relative z-10"
:class="darkMode ? '' : 'bg-surface/90 backdrop-blur'"
>
<slot name="left">
<span v-if="!darkMode" class="text-xs text-content-3 font-medium ml-2">Nekosonic Music</span>
</slot>
<div class="flex items-center gap-1.5">
<button @click="minimizeWindow" class="w-3 h-3 rounded-full bg-yellow-500 hover:bg-yellow-400 transition" title="最小化"></button>
<button @click="toggleMaximize" class="w-3 h-3 rounded-full bg-green-500 hover:bg-green-400 transition" title="最大化/还原"></button>
<button @click="$emit('close')" class="w-3 h-3 rounded-full bg-red-500 hover:bg-red-400 transition" title="关闭"></button>
</div>
</div>
</template>
<script setup lang="ts">
import { getCurrentWindow } from '@tauri-apps/api/window';
defineProps<{
darkMode?: boolean;
}>();
defineEmits<{
close: [];
}>();
const currentWindow = getCurrentWindow();
function minimizeWindow() {
currentWindow.minimize();
}
async function toggleMaximize() {
const isMaximized = await currentWindow.isMaximized();
if (isMaximized) {
currentWindow.unmaximize();
} else {
currentWindow.maximize();
}
}
</script>