feat(admin+server): 酷狗对接 - 扫码绑定管理员账号 / 按排期自动创建酷狗日歌单 + 同步歌曲

数据模型:SystemSettings 新增 kugouApiBaseUrl / kugouAdminCookie / kugouAdminToken / kugouAdminUser / kugouAdminBoundAt 5 字段;新建 KuGouPlaylistSync 同步历史表(12 字段 + playDate 倒序索引)。迁移脚本:app/drizzle/migrations/20260919143000_add_kugou_integration.sql

后端 Server:新增 server/services/kugouService.ts 封装 KuGouMusicApi sidecar 转发(自动拼 Cookie / Token header);新增 6 个 admin/kugou 路由:status / qr-create / qr-check / unbind / sync-schedule-playlists / sync-history。同步核心:逐日出非草稿排期 → kgHash 直取优先 → 失败用 cloudsearch/search 按标题+歌手三级召回 → /playlist/create + /playlist/tracks op=add 每 100 首分批;写同步历史(status、added/missing、歌单 URL)。

后台 UI:新建 Admin/KuGouImporter.client.vue 三栏布局——左栏 sidecar 健康卡+部署说明+扫码绑定/解绑弹窗;中栏多选排期日期+逐日出排期预览卡+按日同步;下栏最近 100 条同步历史(7 种状态 badge + 歌单链接跳转)。dashboard.vue L105 playlist-card 挂载点由 PlaylistCardPage 替换为 KuGouImporter;权限 permissions.js 5 个 ADMIN 族角色开放 playlist-card 页面访问(接口内部绑定/同步再强校验 ADMIN/SUPER_ADMIN)。

侧car要求:部署 KuGouMusicApi(参考文档 https://kugoumusicapi-docs.4everland.app),默认本机 http://127.0.0.1:3000,可通过 SystemSettings.kugouApiBaseUrl 或环境变量 KUGOU_API_BASE 覆盖。
This commit is contained in:
2026-09-19 11:57:02 +08:00
parent 573e168702
commit a0184fdeb0
12 changed files with 1255 additions and 8 deletions
+51
View File
@@ -0,0 +1,51 @@
import { db } from '~/drizzle/db'
import { systemSettings } from '~/drizzle/schema'
import { kuGouFetch } from '~~/server/services/kugouService'
export default defineEventHandler(async (event) => {
const user = event.context.user
if (!user) throw createError({ statusCode: 401, message: '未登录' })
if (!['ADMIN', 'SUPER_ADMIN'].includes(user.role))
throw createError({ statusCode: 403, message: '仅管理员可访问' })
const query = getQuery(event)
const base = String(query.baseUrl || '').trim()
if (base && !/^https?:\/\//i.test(base)) {
throw createError({ statusCode: 400, message: 'baseUrl 需要是合法的 http(s) URL' })
}
const rows = await db.select().from(systemSettings).limit(1)
const settings = rows[0] as any
const usedBase = base || settings?.kugouApiBaseUrl || process.env.KUGOU_API_BASE || 'http://127.0.0.1:3000'
let serviceOk: boolean
let serviceMessage: string
let loginStatus: any = null
try {
const r = await kuGouFetch('/login/status', { timestamp: Date.now() })
loginStatus = r
serviceOk = Number((r as any)?.status ?? 0) === 1 || !!((r as any)?.data?.profile || (r as any)?.data?.account)
serviceMessage = serviceOk ? '服务在线,且账号已绑定登录' : 'sidecar 在线,但酷狗账号未登录'
} catch (e: any) {
serviceOk = false
serviceMessage =
'无法连接 sidecar (' + usedBase + '):' + (e?.message || String(e))
}
return {
ok: true,
service: {
baseUrl: usedBase,
serviceOk,
serviceMessage,
loginStatus,
},
bound: {
hasToken: !!settings?.kugouAdminToken,
hasCookie: !!settings?.kugouAdminCookie,
boundAt: settings?.kugouAdminBoundAt || null,
user: settings?.kugouAdminUser || null,
},
}
})