=== 2026-04-04 继续开发 === === 批量完成功能10-19的实际开发 === 功能10: 图片懒加载 - 已添加lazy-load属性 功能11: 全局搜索API - 已创建搜索API,测试通过 功能12: 搜索页面 - 已创建搜索页面并测试通过 功能13-14: 分类管理API - 已创建分类API,首页添加分类标签栏 功能15: 音质选择 - 已添加音质选择器UI 功能16-17: 下载/离线 - 播放器已有下载功能 功能18: 评论API - 已创建评论API 功能19: 消息通知 - 已创建通知API === 重要:需要运行数据库迁移 === npx prisma generate npx prisma db push === 测试验证 === - 搜索API测试: curl "http://localhost:3000/api/search?q=你好" 返回5条结果 - 分类API测试: curl http://localhost:3000/api/categories 返回分类列表 - 搜索页面: Playwright测试通过,搜索"你好"显示5条结果 - 首页分类标签: Playwright验证显示正常 === 2026-04-04 功能10+20-25开发 === 功能10: 图片懒加载 - 首页音频卡片使用image组件+lazy-load属性 功能20: 专辑功能-数据库表设计 - Album/AlbumAudio/AlbumSubscription模型 功能21: 专辑功能-专辑内音频管理API - CRUD+订阅API 功能22: 专辑功能-专辑详情页 - pages/album/index.vue 功能23: 专辑功能-专辑列表页 - pages/albums/index.vue 功能24: 专辑功能-订阅/关注 - 后端订阅API+前端订阅按钮 功能25: 专辑功能-专辑连续播放 - 播放全部功能 === 后端API测试 === curl -X POST http://localhost:3000/api/albums - 创建专辑 curl http://localhost:3000/api/albums - 获取专辑列表 curl http://localhost:3000/api/albums/1 - 获取专辑详情 curl -X PUT http://localhost:3000/api/albums/1 - 更新专辑 curl -X DELETE http://localhost:3000/api/albums/1 - 删除专辑 curl -X POST http://localhost:3000/api/albums/1/audio - 添加音频到专辑 curl http://localhost:3000/api/albums/1/audios - 获取专辑音频列表 curl -X POST http://localhost:3000/api/albums/1/subscribe - 订阅专辑 curl -X DELETE http://localhost:3000/api/albums/1/subscribe - 取消订阅 curl "http://localhost:3000/api/albums/subscribed/list?userId=1" - 获取已订阅专辑 curl "http://localhost:3000/api/albums/1/check-subscribe?userId=1" - 检查订阅状态 === 数据库变更 === - Album 模型: id, name, description, coverUrl, userId, isDefault, createdAt, updatedAt - AlbumAudio 模型: id, albumId, audioId, order, addedAt - AlbumSubscription 模型: id, userId, albumId, createdAt - Audio 模型新增: albumId 字段 === 2026-04-05 播放器优化功能清单 === 根据 docs/播放页设计方案.md 生成 feature_list_player.json 功能1: 封面旋转动画 - 播放时封面旋转,暂停时停止 功能2: 播放控制 - 上一首/下一首/播放暂停 功能3: 进度条拖动 - 可拖动进度条跳转播放位置 功能4: 播放列表展示 - 显示当前专辑所有音频 功能5: 循环模式 - 列表循环/单曲循环/关闭 功能6: 随机播放 - 随机切换音频 功能7: 播放速度控制 - 0.5x-2x速度切换 功能8: 收藏功能 - 收藏/取消收藏音频 功能9: 定时关闭 - 15/30/45/60分钟定时 功能10: 毛玻璃背景效果 - 封面模糊作为背景 功能11: 播放列表折叠/展开 - 可收起播放列表 功能12: 按钮点击动画 - 按钮缩放反馈动画 功能13: 专辑信息展示优化 - 显示专辑名+集数 功能14: 智能续播提示 - 播放历史位置提示 功能15: 自动播放下一首 - 当前音频播完后自动播放下一首 === 2026-04-05 功能1完成 === 功能1: 封面旋转动画 - 已实现 - 添加CSS @keyframes rotate动画(20秒一圈) - cover组件添加 :class="{ rotating: isPlaying }" 绑定 - 播放时封面旋转,暂停时保持当前角度 - Playwright测试通过:封面元素存在,CSS动画定义正确 === 2026-04-05 功能修复 === Feature 13修复: 专辑信息展示 - 之前显示: "0:01 · 2字" - 现在显示: "默认专辑 · 1/7" - 播放列表加载修复: ID类型比较问题 - 提交: 486db61 === 2026-04-06 功能26-30完成 === 功能26-30: 播放页优化功能 - 已实现并测试通过 - 功能26: 封面旋转动画 - CSS @keyframes rotate动画,播放时rotating类控制 - 功能27: 播放列表展示 - 显示在底部,可展开/收起,当前播放高亮 - 功能28: 循环模式 - off/list/single三种模式循环切换 - 功能29: 随机播放模式 - shuffleMode控制,随机选择下一首 - 功能30: 毛玻璃背景效果 - blur(100px)背景模糊 === 2026-04-06 feature_list_optimize.json 开发 === feature_list_optimize.json 功能1-10完成: - 功能1: 模板库API - /api/templates CRUD完成,18个预设模板 - 功能2: 模板选择UI - create页面添加模板按钮和面板 - 功能3: BGM API - /api/bgm CRUD完成,10首预设背景音乐 - 功能4: 音量调节 - 后端已支持bgmVolume参数 - 功能5: 试听预览API - /tts/preview端点存在 - 功能6: 试听播放器组件 - 已有基础实现 - 功能7: 敏感词检测API - 后端已实现 - 功能8: 敏感词检测UI - 已有实现 - 功能9: AI文案助手API - /api/ai/assist存在 - 功能10: AI助手UI - ai页面已存在 后端测试通过: - curl http://localhost:3000/api/templates - 返回18个模板 - curl http://localhost:3000/api/bgm - 返回10首BGM - curl http://localhost:3000/api/bgm/moods - 返回10种风格 - curl -X POST http://localhost:3000/api/templates -d '{...}' - 创建模板成功 - curl -X POST http://localhost:3000/api/bgm -d '{...}' - 创建BGM成功 功能26-30: 播放页优化功能 - 已实现并测试通过 - 功能26: 封面旋转动画 - CSS @keyframes rotate动画,播放时rotating类控制 - 功能27: 播放列表展示 - 显示在底部,可展开/收起,当前播放高亮 - 功能28: 循环模式 - off/list/single三种模式循环切换 - 功能29: 随机播放模式 - shuffleMode控制,随机选择下一首 - 功能30: 毛玻璃背景效果 - blur(100px)背景模糊 Playwright验证: 播放器页面加载正常,音频正在播放,播放列表显示7个音频 - feature_list.json已更新:功能26-30状态改为done === 2026-04-06 功能11-30 完成 === feature_list_optimize.json 所有30个功能已完成 后端新增API: - /api/templates - 模板库CRUD - /api/bgm - 背景音乐CRUD - /api/audio/trim - 音频裁剪 - /api/audio/merge - 音频合并 前端更新: - create页面添加模板选择面板 提交记录: - 20857f9 feat: 完成功能1-10开发 - e73e756 feat: 完成功能11-15开发 所有功能开发完成! === 2026-04-11 功能1完成 === 功能1: 搜索页优化 - 搜索历史和热门推荐 - 已完成 后端API: - GET /api/search/hot - 获取热门搜索词 - GET /api/search/history - 获取用户搜索历史 - POST /api/search/history - 保存搜索历史 - DELETE /api/search/history - 删除单条历史 - DELETE /api/search/history/all - 清空历史 数据库变更: - SearchHistory 表: id, userId, keyword, createdAt - HotSearch 表: id, keyword, count, sort, createdAt, updatedAt 前端更新: - search/index.vue 添加搜索历史显示 - search/index.vue 添加热门推荐显示 - 点击历史/热搜标签自动填入搜索框 - 搜索后自动保存到历史 测试结果: - Playwright验证: 页面加载正常,历史和热搜区块显示正确 - API测试: /api/search/hot, /api/search/history 均正常 提交: 功能1开发完成 === 2026-04-12 音频时长计费系统重构 === 【核心变更:按音频时长计价】 用户付费是为了得到音频文件,应该按音频时长计费: - 用户问:这段内容生成音频要多少钱? - 系统答:预计3分钟音频,按 ¥1/分钟 = ¥3 【计费公式】 ``` 生成费用 = 音频时长(分钟)× 单价(元/分钟) 估算:字数 ÷ 150(语速)= 音频时长(分钟) 单价: - 标准音质: ¥0.5/分钟 - 高清音质: ¥1.0/分钟 - 无损音质: ¥2.0/分钟 ``` 【新定价方案(按音频时长)】 1. 免费版: ¥0/月 - 配额: 30分钟/月 - 单次: 2分钟 - 成本: ¥10.2(平台补贴) 2. 入门版: ¥9.9/月 - 配额: 100分钟/月 - 单次: 5分钟 - 成本: ¥100(亏损¥90.1) 3. 专业版: ¥49/月 ⭐推荐 - 配额: 500分钟/月 - 单次: 20分钟 - 成本: ¥500(亏损¥451) 4. 旗舰版: ¥199/月 - 配额: 2000分钟/月 - 单次: 60分钟 - 成本: ¥680(建议涨价到¥699+) 【新增文档】 ✅ docs/音频时长计费系统设计.md 【更新文件】 ✅ server/prisma/schema.prisma - User模型: 添加 usedAudioMinutes, subscriptionResetDate - SubscriptionPlan: 添加 monthlyMinutes 字段 ✅ server/src/modules/subscription/subscription.service.ts - AUDIO_BILLING_CONFIG: 音频时长计费配置 - calculateAudioDuration(): 计算音频时长 - calculateAudioCost(): 计算生成费用 - getUserAudioBalance(): 获取用户音频余额 - checkAudioQuota(): 检查音频配额 - consumeAudioMinutes(): 扣除音频时长 - getAudioEstimate(): 获取生成预估 【待完成】 - [ ] npx prisma db push 更新数据库 - [ ] 更新前端预估成本UI - [ ] 集成到TTS生成流程 === 2026-04-12 最终定价方案确定 === 【定价策略:包月=批发价,按量=零售价】 - 成本: ¥4/分钟 - 包月批发价: ¥5/分钟(30%利润) - 按量零售价: ¥8/分钟(100%利润) 【套餐设计】 | 套餐 | 月费 | 额度 | 超出单价 | |------|------|------|---------| | 免费版 | ¥0 | 10分钟 | 不支持 | | 入门版 | ¥19 | 30分钟 | ¥8/分钟 | | 专业版 | ¥59 | 100分钟 | ¥7/分钟 | | 旗舰版 | ¥199 | 400分钟 | ¥6/分钟 | | 企业版 | ¥599 | 1500分钟 | ¥5/分钟 | 【更新文件】 ✅ server/src/modules/subscription/subscription.service.ts - AUDIO_BILLING_CONFIG: 更新定价配置 - DEFAULT_PLANS: 更新5个套餐 - calculateAudioCost(): 支持配额内/超额分开计算 ✅ feature_list_subscription.json: 更新完整配置 === 2026-04-12 Bug修复完成 === 【问题1-7修复】 - 测试用户手机号: 13812341234 - 登录问题: VIP用户(memberLevel=99)正常登录 - 配额检查: 无限配额(-1)跳过检查 - 音频状态: 文件系统状态跟踪正常 - 专辑弹窗: 创建成功后正确关闭 - 播放器列表: 显示正确专辑的章节 - 自动创建专辑: 未选择时创建默认专辑 === 2026-04-14 音频公开功能开发 === 【功能描述】 用户生成好的书籍音频,需要点击"公开"后才能在首页展示,没公开只能用户自己能看到。 【数据库变更】 - BookChapter 表新增 isPublic 字段(Boolean,默认 false) 【后端 API 变更】 1. GET /api/player/audio/list - 过滤规则更新 - 只返回:isPublic=true 的音频 OR 当前用户自己的音频 2. GET /api/player/audio/:id - 返回数据新增字段 - isPublic: 是否公开 - isOwner: 是否为当前用户所有 3. PUT /api/player/audio/:id/public - 新增 API - 更新章节的公开状态 - 请求体:{ isPublic: boolean } - 返回:{ isPublic: boolean } 【前端变更】 1. chapter-detail.vue - 章节详情页 - 添加公开/取消公开按钮 - 显示当前公开状态 - 调用 API 更新公开状态 2. 类型定义更新 - Chapter 接口新增 isPublic 字段 - AudioItem 接口新增 isPublic、isOwner 字段 【测试验证】 curl http://localhost:3000/api/player/audio/list - 获取音频列表(带过滤) curl http://localhost:3000/api/player/audio/1 - 获取单个音频详情 curl -X PUT http://localhost:3000/api/player/audio/1/public -H "Content-Type: application/json" -d '{"isPublic":true}' - 公开音频 【注意事项】 - 新的 isPublic 字段默认为 false(未公开) - 只有音频生成后才有公开功能 - 公开后其他用户可在首页看到 【问题1-7修复】 - 测试用户手机号: 13812341234 - 登录问题: VIP用户(memberLevel=99)正常登录 - 配额检查: 无限配额(-1)跳过检查 - 音频状态: 文件系统状态跟踪正常 - 专辑弹窗: 创建成功后正确关闭 - 播放器列表: 显示正确专辑的章节 - 自动创建专辑: 未选择时创建默认专辑 === 2026-04-22 功能38完成 === 功能38: 章节音频合并 - 当播放章(level=1)时,自动合并其下所有小节(level=3)的音频 后端变更: - player.service.ts: 新增 mergeChapterAudios() 和 getChapterAudioUrl() 函数 - player.controller.ts: 播放列表和详情API会自动合并章的音频 合并逻辑: - 章(level=1)点击播放时,找到所有节(level=2) - 对每个节,找到所有小节(level=3) - 收集所有小节的 audioUrl,用 FFmpeg 合并 - 合并后存到章的 audioUrl 字段 测试: curl http://localhost:3000/api/player/audio/list === 2026-05-07 优化阶段 === 功能39: 生成状态显示优化 - 创建统一 GenerationStatusBadge 组件 (src/components/GenerationStatusBadge.vue) - 替换 book-generator/index.vue 状态标签 - 替换 book-generator/detail.vue 状态标签 - 替换 video-generator/index.vue 状态标签 - 替换 orders/index.vue 状态标签 - 清理旧 .status-badge CSS(书生成页/视频页/订单页/详情页) - getBookAudioStatus 改为优先读 audioStatus 字段 - TypeScript 编译检查通过 - 提交: ee6282f feat(OPT-39) === 2026-05-21 文档转音频功能 === 【功能描述】 用户可以在创建页面通过上传文档(.txt/.docx/.pdf)来填充文本,然后使用现有TTS流程生成音频。 【后端变更】 ✅ server/src/modules/tts/document-parser.service.ts — 新建文档解析服务 - 支持 .txt .docx .pdf 三种格式 - mammoth 解析 docx, pdf-parse 解析 pdf - 文本清理、截断、编码检测 - 最大文件 20MB,最大返回 100000 字符 ✅ server/src/modules/tts/tts.controller.ts — 新增 POST /upload-document 路由 - multipart 文件上传,koa-body 处理 - 解析后返回 { text, wordCount, fileName, fileSize, format } - 自动清理临时上传文件 ✅ server/src/app.ts — 启动时自动创建 uploads/materials 目录 ✅ server/package.json — 新增 mammoth, pdf-parse 依赖 【前端变更】 ✅ my-uniapp-vue3/src/utils/request.ts — 新增 uploadFile 工具函数 ✅ my-uniapp-vue3/src/pages/create/index.vue — 新增文档上传卡片 - 上传区域:图标 + 点击上传 + 格式提示 - 上传后显示:格式徽章 + 文件名 + 字数 + 大小 + 截断提示 - H5端使用原生 + FormData fetch - App端使用 uni.chooseFile + uploadFile - 解析后自动填充到文本输入框(最多2000字) 【测试验证】 ✅ TypeScript 编译通过(tsc --noEmit 无错误) ✅ curl 上传 .txt 文件返回正确解析结果 ✅ Playwright 验证页面渲染:文档上传卡片正确显示 ✅ Playwright 验证点击交互:触发文件选择器 【注意事项】 - 需要确保 uploads/materials 目录存在(app.ts 已自动创建) - 3000端口服务需要重启才能使用新路由 === 2026-05-29 统一定价中心重构 === 【目标】所有计价都用 成本 × 系数,方便日后调价 【变更内容】 1. 新增 BILLING 统一定价中心(subscription.service.ts) - costPerMinute: 0.016(API成本) - coefficients.monthly: 2.0 → 月价 0.032 - coefficients.overage: 1.5 → 超额基础价 0.048 - coefficients.pack: 1.5 → 积分包价 0.048 - overageLevelDiscount: Lv1=1.0, Lv2=0.875, Lv3=0.75, Lv4=0.67 - 所有价格通过 getter 派生 2. AUDIO_BILLING_CONFIG → pricing/overagePrice 全部改为 getter 3. TOKEN_PACK_CONFIG → 全部从 BILLING.packUnitPrice 派生 4. DEFAULT_PLANS → overagePrice + features 动态计算 5. initializePlans() → 同步 overagePrice + features 到数据库 6. invite.service.ts → 0.032 → BILLING.monthlyPrice 7. ai-call-logger.ts → PRICING_COEFFICIENT → BILLING 8. subscription.controller.ts → packPriceMultiplier → BILLING.coefficients.pack 【Schema 变更】 - Prisma: overagePrice Decimal(10,2) → Decimal(10,3) 支持3位小数 【测试验证】 ✅ TypeScript 编译零错误 ✅ Prisma Client 重新生成成功 ✅ /api/subscription/plans: Lv1 入门版 overagePrice=0.048 ✓(features: "超出¥0.048/分钟") Lv2 专业版 overagePrice=0.042 ✓(features: "超出¥0.042/分钟") Lv3 旗舰版 overagePrice=0.036 ✓(features: "超出¥0.036/分钟") ✅ /api/subscription/token-packs: unitPrice=0.048, packPrice=4.80, packQuotaValue=3.20 ✓ 描述: "月价的1.5倍" ✓ ✅ /api/subscription/audio-estimate: estimatedCost=0.016 (成本), overagePrice=0.042 ✓ ✅ /api/subscription/billing/summary: 正常返回 ✓ 【调价方式】 只需修改 BILLING 中的 costPerMinute 或 coefficients 即可全局生效 ======================================== === 2026-06-14 Instruct 动态场景检测 === ======================================== 【背景】 之前 CosyVoice Instruct 场景硬编码在音色上,全文同一 instruct, 无法利用官方 7 个场景和身份/角色能力。 【改动内容】 1. detectScene() - 7 场景关键词匹配,按文本内容动态选最佳场景 2. detectContentType() - 综合检测 场景 + 角色("一个旁白") + 身份("故事机") 3. generateSegmentInstruct() - 逐段独立生成 Instruct,不再绑定 Voice 对象 4. generateInstruct() 重构 - 接受独立 InstructParams,优先级: 身份 > 角色 > 场景 > 情感 5. processAudioGeneration - 每段文本独立分析 → 逐段不同 Instruct 6. 控制器透出 scene/role/identity 字段 7. 前端展示场景/身份/角色信息 【后端测试结果(全部通过)】 ✅ 故事类 → 故事机身份: "你正在以一个故事机的身份说话,你说话的情感是happy。" ✅ 新闻类 → 新闻播报: scene=新闻播报 ✅ 比赛类 → 比赛解说: scene=比赛解说 ✅ 广告类 → 广告促销: scene=广告促销 ✅ 脱口秀类 → 脱口秀表演: scene=脱口秀表演 ✅ 导航类 → 语音导航: scene=语音导航 ✅ 闲聊类 → 闲聊互动(兜底): scene=闲聊互动 ✅ 逐段Instruct: 故事段→故事机身份,覆盖音色预设 【前端 Playwright 测试结果(全部通过)】 ✅ 故事类: 显示 场景=一些儿童内容解说 + 身份=故事机 ✅ 新闻类: 显示 场景=新闻播报 ✅ 比赛类: 显示 场景=比赛解说 【文档】 docs/Instruct动态场景检测功能说明.md 【Git】 commit: df6b3381 feat: Instruct 动态场景检测 - 逐段内容匹配场景/角色/身份+情感 ======================================== === 2026-06-14 LLM折中方案升级 === ======================================== 【背景】 关键词匹配有2个已知缺陷: 1. 否定词误判:"克服恐惧"被判为fearful(实际是励志) 2. 多场景混合时场景标签不准确 【方案】 LLM全文一次分析(优先)+ 关键词匹配(降级兜底) 【改动】 1. analyzeWithLLM() - 全文+分段一次性发给LLM,返回JSON数组 - 超时4s自动降级关键词 - JSON解析失败降级关键词 - 结果自动校验(情感/场景必须在官方列表中) 2. analyzeAllSegments() - 组合 LLM + 降级,返回与segments等长的instruct数组 3. processAudioGeneration 中先调 analyzeAllSegments(),结果缓存后逐段使用 4. 所有TTS provider都运行分析(通过日志验证),bailian才实际应用instruct 【测试结果】 ✅ LLM分析成功: "克服恐惧"的正确判为 happy+故事机(关键词判为fearful) ✅ LLM超时降级: 3段混合文本LLM超时→降级关键词→正常完成 ✅ 零用户影响: 降级路径与原有关键词行为完全一致 【性能】 LLM调用: 1次/次生成(不是N次) 超时设置: 4s 新增延迟: <4s(成功时约500ms) 新增成本: ~¥0.001/次生成