"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const router_1 = __importDefault(require("@koa/router")); const PlayerService = __importStar(require("./player.service")); const errorHandler_1 = require("../../middleware/errorHandler"); const auth_1 = require("../../middleware/auth"); const models_1 = require("../../models"); // 测试用户ID(开发环境使用) const TEST_USER_ID = '1'; const router = new router_1.default(); // 获取播放进度列表 router.get('/progress', auth_1.optionalAuth, async (ctx) => { // 开发环境使用测试用户ID const userId = ctx.state.user?.userId || TEST_USER_ID; const { audioId } = ctx.query; const records = await PlayerService.getPlayProgress(userId, audioId ? parseInt(audioId) : undefined); ctx.body = { code: 0, message: 'success', data: records, }; }); // 保存播放进度 router.post('/progress', auth_1.optionalAuth, async (ctx) => { // 开发环境使用测试用户ID const userId = ctx.state.user?.userId || TEST_USER_ID; const body = ctx.request.body; const { audioId, progress, duration } = body; if (!audioId || typeof progress !== 'number' || typeof duration !== 'number') { throw new errorHandler_1.BadRequestError('参数错误'); } const record = await PlayerService.savePlayProgress(userId, audioId, progress, duration); ctx.body = { code: 0, message: 'success', data: record, }; }); // 更新播放进度 (在 DELETE 路由之前定义) router.put('/progress/:audioId', auth_1.optionalAuth, async (ctx) => { // 开发环境使用测试用户ID const userId = ctx.state.user?.userId || TEST_USER_ID; const audioId = parseInt(ctx.params.audioId); const body = ctx.request.body; const { progress, duration } = body; if (typeof progress !== 'number') { throw new errorHandler_1.BadRequestError('进度参数错误'); } const record = await PlayerService.updatePlayProgress(userId, audioId, progress, duration); ctx.body = { code: 0, message: 'success', data: record, }; }); // 删除播放记录 router.delete('/progress/:audioId', auth_1.optionalAuth, async (ctx) => { // 开发环境使用测试用户ID const userId = ctx.state.user?.userId || TEST_USER_ID; const audioId = parseInt(ctx.params.audioId); await PlayerService.deletePlayRecord(userId, audioId); ctx.body = { code: 0, message: '删除成功', }; }); // ============ 临时 API:为播放器页面适配书籍章节音频 ============ // 获取播放列表(适配旧播放器)- 必须放在 /:id 之前 router.get('/audio/list', async (ctx) => { const { page = '1', pageSize = '100' } = ctx.query; // 获取所有有音频的章节 const chapters = await models_1.prisma.bookChapter.findMany({ where: { audioUrl: { not: null, }, AND: [ { audioUrl: { not: '' } } ] }, include: { book: true }, orderBy: [ { bookId: 'asc' }, { number: 'asc' }, ], skip: (parseInt(page) - 1) * parseInt(pageSize), take: parseInt(pageSize), }); const total = await models_1.prisma.bookChapter.count({ where: { audioUrl: { not: null, }, AND: [ { audioUrl: { not: '' } } ] }, }); const list = chapters.map((chapter) => ({ id: chapter.id, _id: chapter.id, title: chapter.title, summary: chapter.summary || '', text: chapter.content || '', audioUrl: chapter.audioUrl || '', audioDuration: chapter.audioDuration || 0, wordCount: chapter.wordCount || 0, albumId: chapter.bookId, albumName: chapter.book?.title || '默认专辑', isFavorite: false, })); ctx.body = { code: 0, message: 'success', data: { list, total, page: parseInt(page), pageSize: parseInt(pageSize) }, }; }); // 获取章节音频详情(适配旧播放器) router.get('/audio/:id', async (ctx) => { const chapterId = parseInt(ctx.params.id); if (isNaN(chapterId)) { ctx.status = 400; ctx.body = { code: 1, message: '无效的音频ID' }; return; } const chapter = await models_1.prisma.bookChapter.findUnique({ where: { id: chapterId }, include: { book: true }, }); if (!chapter) { ctx.status = 404; ctx.body = { code: 1, message: '音频不存在' }; return; } // 适配旧的 AudioItem 格式 const audioItem = { id: chapter.id, _id: chapter.id, title: chapter.title, summary: chapter.summary || '', text: chapter.content || '', audioUrl: chapter.audioUrl || '', audioDuration: chapter.audioDuration || 0, wordCount: chapter.wordCount || 0, albumId: chapter.bookId, albumName: chapter.book?.title || '默认专辑', isFavorite: false, }; ctx.body = { code: 0, message: 'success', data: audioItem, }; }); exports.default = router;