chenchen-plan2

第四天-开发进度

1. 只保留一个标题来源

已按你的要求改成“只保留一个标题来源”:

  • 统一标题来源:发布配置不再单独输入标题,统一使用“新建小说”时保存的小说标题。
  • 发布弹窗调整publish-novel-modal 里移除了可编辑的“小说标题”输入框,改为只展示当前小说标题(只读)。
  • 发布接口调整/api/v1/novel-publish 不再使用请求体里的 title,改为服务端从作者小说索引里读取该 novelId 的标题写入发布记录。
  • 读者端内容页调整/api/v1/library/articles 在文章详情返回时,优先使用小说主标题,避免内容页出现与列表页不一致的标题。
  • 编辑器接入调整novel-editor 里发布确认 payload 去掉 title 字段,发布弹窗改传 novelTitle

已检查这几个改动文件,当前没有新增 lint 报错。
如果你愿意,我下一步可以再帮你把历史已发布数据做一次“标题回填统一”(把旧记录里的标题批量同步为小说主标题)。

2. 删除默认 AI 角色设定

已删除默认 AI 角色设定,现在线路是“无预置角色”:

  • novel-editor 不再导入/使用 DEMO_PERSONAS
  • 角色初始状态改为 []selectedId 初始为 null
  • 加载角色时:
    • 未连接钱包:保持空列表
    • 服务端无角色存档:保持空列表
  • 已删除未再使用的文件:apps/web/src/lib/demo-personas.ts

现在新建小说进入编辑页后,不会再自动出现默认 AI 角色。

3. 按照渲染后的格式直接发布

优化markdown发布,如果是直接用就会是没有应用上markdown语法的原格式。在作者页面http://whale3070.com:3000/editor/nvl-mng5hlto-c4375bd3b9 ,有一个markdown编辑器。把“应用到当前章节”修改为发布本章节。因为应用到当前章节会导致markdown格式失效。我希望按照渲染后的格式直接发布

已按你的要求改好:Markdown 编辑器不再“应用到当前章节”,改成直接发布本章节,并且按渲染后的 HTML发布,避免 Markdown 格式被破坏。

  • 按钮文案已改为:发布本章节
  • 弹窗发给主页面的数据从“原始 markdown 文本”为主,改成携带 renderedHtml(预览区实际 HTML)
  • 主页面收到消息后会:
    • 先把当前章节内容更新为渲染后的 HTML
    • 持久化章节结构
    • 触发“发布本章”,并带上 skipAutoFormat: true
  • 后端 /api/v1/novel-publishtoggle_chapter 增加了 skipAutoFormat 支持
    skipAutoFormat=true 时,跳过 autoFormatChaptersForPublish,从而保留 Markdown 渲染格式(例如表格)

你给的页面入口我已按这个场景实现对应逻辑:Chenchen-Lib · AI 编辑平台

如果你需要,我可以继续加一个“发布并保留当前编辑器内容不切换焦点/不滚动”的微调,进一步优化发布手感。

4. 剧情大纲管理

已完成:剧情大纲管理里的自动卷名/标签预置已移除,改为作者自行添加。

具体改动:

  • 不再使用演示大纲初始化(已删除 demo-outline 依赖)
  • 新建/未连接状态下的大纲初始值改为“仅默认章节”,不带预置标签
  • 自动补建卷节点时,不再写死 第一卷,改为空标题(作者自己填)
  • 自动新增章节/AI 切章生成卷节点时,也不再预置卷名和标签
  • 大纲侧边栏“新增章节”自动创建的卷节点同样去掉默认卷名和标签

你这个页面场景现在会符合“作者手动配置”的方式:Chenchen-Lib · AI 编辑平台

如果你愿意,我可以再补一个小优化:当卷标题为空时,在输入框里显示占位提示(比如“请输入卷名”),但不自动写入任何值。

5. 自动先落盘当前章节内容

修改内容之后,它好像不知道怎样的生效方式,我试了好几遍,不知道是要先撤回本章再修改才会更新,还是是有个时间差才会更新(已经了解了得点击切换到别的章节才会更新)|目前又发现似乎发布新章节也是一样,必须得要切出去才能正常显示,否则发布的就是空章节。你告诉我,修改内容,已发布的内容什么时候生效?什么时候读者端能看到?

你现在遇到的现象,和当前实现一致,不是你操作错了。

现在的生效规则(按当前代码)

  • 你在编辑器里打字后,2 秒防抖保存的是“写作草稿上下文”(/api/v1/save-draft),不是章节结构发布源
  • 读者端展示读取的是章节结构里的 chapterHtml/api/v1/library/articles.data/structure 读),再按 publishedChapterIds 过滤已发布章节。
  • 所以:
    • 只改内容但不触发章节结构写入时,读者端会看到旧内容(甚至空内容)。
    • 你切到别的章节时会触发“把当前章节内容写回结构”,所以你观察到“切出去才生效”。

回答你两个关键问题

  • 已发布内容什么时候生效?
    当“当前章节内容已经写入结构文件”后就生效。当前最稳定触发点是:切换章节(或你刚用的 Markdown “发布本章节”流程)。

  • 读者端什么时候能看到?
    在作品是公开、且该章节已在 publishedChapterIds 内、并且结构写入完成后,读者端刷新基本可立即看到(接口是 no-store,不是长缓存导致的延迟)。

为什么新章节会发布成空章

新章节创建后,如果你直接点发布,但“当前编辑内容还没先写回章节结构”,发布时拿到的还是旧的/空的 chapterHtml,所以读者端就显示空章。


如果你要,我可以直接再改一版“强一致”逻辑:
点击“发布本章 / 一键发布全部”前,自动先落盘当前章节内容,再执行发布,这样就不需要手动切章节了。


已改成你要的行为:
现在点 “发布本章”“一键发布全部” 前,会先自动把当前编辑器里的章节内容落盘到结构,再执行发布,不需要手动切章节了。

这次改动点在 novel-editor

  • 新增 persistActiveChapterBeforePublish()
    • 读取当前编辑器 HTML
    • 写回当前激活章节的 chapterHtml
    • 立即 postOutlineStructure 持久化
  • 以下流程都改为先调用它:
    • toggleCurrentChapterPublish(底部“发布本章/撤回本章”)
    • 大纲侧栏章节卡片上的发布按钮
    • 大纲侧栏“一键发布全部章节”
  • “发布小说(发布配置确认)”也同步改为先落盘再提交,保证章节列表与内容一致。

这样就不会再出现“必须切出去才生效”或“刚发布是空章节”的问题。

6. 章节内容错乱

章节内容有时候显示的是最新版的,有时候显示的又是旧版本的,有时候显示的有图片,有时候显示的又没有图片,但是一刷新又会恢复到最新版本

你这个现象我确认了,根因有两层:

  • 读者端不是实时订阅:页面只在进入/刷新时拉一次内容,所以作者改完后,读者通常要刷新才会看到。
  • 章节有多份 HTML 字段:之前编辑时只更新了 chapterHtml,而读者端有时会优先读 chapterHtmlDesktop / chapterHtmlMobile,就会出现“有时旧版、有时无图”。

我刚刚已经修了第二层(核心一致性问题):

  • 在作者端保存章节时,统一同步更新:
    • chapterHtml
    • chapterHtmlDesktop
    • chapterHtmlMobile

这样同一章节不会再出现“不同入口读到不同版本”的情况,图片也不会因为读到旧字段而忽隐忽现。


现在的生效口径(你可以按这个理解)

  • 作者点击发布相关操作前,系统会先落盘当前章节内容(我们前面已加)。
  • 读者端看到更新的时间点:下次请求文章详情时(最直接就是刷新页面)。
  • 不刷新时,读者端仍可能停留在当前页面内存快照,这是预期行为(不是没保存)。

如果你希望“读者不刷新也自动看到最新”,我可以再给你加一个轻量自动刷新(比如每 5-10 秒静默拉新,并尽量保持当前阅读章节位置不跳)。

7. 章节重复

是的,这种显示会有点重复,我已经帮你改成更清爽的规则了:

  • 如果章节标题本身已经是“第X章…”这种格式,就直接显示标题(不再前面再拼一遍“第 X 章 ·”)
  • 如果是自定义标题(比如“夜雨入城”),才显示为 第 X 章 · 夜雨入城
  • “当前:…”这一行也同步按同样规则显示

你现在看到的目录和“当前章节”会明显简洁很多。

8. 加载中bug

有这个可能,尤其是移动网络或跨网段时。你现在这个页面我已经做了容错优化,不用再一直盯着“加载中…”:

  • 加了请求超时(12 秒),避免无限等待
  • 加了自动重试 1 次(遇到抖动时更容易成功)
  • 加了慢网提示(2.5 秒后提示“网络或服务较慢”)
  • 加了**“立即重试”按钮**,用户可主动重拉

所以现在如果只是波动,通常会自动恢复;如果真的慢,会给明确反馈而不是一直卡住。

9. AI排版bug

你这个“AI自动排版有问题”的判断是对的,我查完调用链后,先给你结论(本次未改代码):

主要问题(高优先级)

  • 自动排版是“纯文本重写”策略,不是 HTML 保留策略
    deepseek-publish-format 里,先把章节 chapterHtml 转成纯文本,再让模型排版,再重新生成 <p>
    这会天然丢失图片、表格、复杂排版(例如 img/table/custom html)。
    关键位置:apps/web/src/lib/server/deepseek-publish-format.ts 里的 htmlToPlainText() + plainTextToHtml() 流程。

  • “一键发布全部章节”必走自动排版
    publish_all_chaptersnovel-publish 路由里总是调用 autoFormatChaptersForPublish(),没有跳过选项。
    所以你一键发布后,之前保留好的富文本也可能被重新“文本化”。
    位置:apps/web/src/app/api/v1/novel-publish/route.ts

  • 按章节发布只有部分路径支持跳过自动排版
    你之前用 Markdown 弹窗“发布本章节”是带 skipAutoFormat=true 的,这条路径可以保留渲染结果;
    但其他发布入口(尤其一键发布)仍可能触发自动排版重写。
    位置同上 + apps/web/src/components/novel-editor.tsx 的调用差异。

次要问题(中优先级)

  • DeepSeek 调用缺少超时和可见诊断
    formatByDeepSeek() 没有超时控制,慢网时可能卡很久。
  • 长章节被截断到 12000 字符
    MAX_MODEL_INPUT_CHARS = 12000,长章节会被裁切后再排版,可能导致“后半章没按预期处理”。

你现在看到“有时正常、有时异常”的根本原因

  • 不是同一条发布路径:不同按钮触发的发布策略不一样(有的保留 HTML,有的会文本化重排)。
  • 一旦走到自动排版,就可能把图片/复杂格式丢掉,看起来像“随机失效”。

如果你同意,我下一步可以给你一版“排版策略分层”方案(先给方案,不直接改):

  • 保留富文本发布(默认)
  • AI文本排版发布(手动开启)
    并让“一键发布全部”可选是否走 AI 重排。

可以,给你一套“排版策略分层”方案(先方案,不动代码):

目标

  • 默认发布行为稳定、可预期:不破坏富文本(图片/表格/Markdown渲染结果都保留)
  • 只有作者明确选择时,才执行 AI 文本排版重写
  • 所有发布入口行为一致,避免“同一本书不同按钮结果不同”

一、发布策略定义(核心)

统一定义 2 个模式:

  • preserve:保留原排版
    • 直接使用当前 chapterHtml/chapterHtmlDesktop/chapterHtmlMobile
    • 不调用 autoFormatChaptersForPublish
  • ai_reflow:AI 重排文本
    • 调用 autoFormatChaptersForPublish,按纯文本重排后回写

建议默认:preserve

二、前端交互方案

1) 发布配置弹窗(整本发布)

在“发布设置”里新增一个清晰选项:

  • 排版策略:
    • 保留作者排版(推荐)(默认)
    • AI 自动排版(会重排段落,可能影响图片/表格)

文案要明确风险(尤其“可能影响图片/表格”)。

2) 大纲侧栏发布入口

  • “发布本章”:默认按 preserve
  • “一键发布全部章节”:弹一次轻确认,显示当前策略(默认 preserve,可切换)

3) Markdown 弹窗“发布本章节”

  • 固定走 preserve(你当前诉求)
  • 可在按钮旁给一个次按钮:AI重排后发布(可选)

三、后端接口统一

把策略作为显式参数传给 /api/v1/novel-publish

  • layoutMode: "preserve" | "ai_reflow"

适配到三个 action:

  • toggle_chapter
  • publish_all_chapters
  • 整本发布(visibility=public 这条路径)

逻辑统一:

  • layoutMode === "ai_reflow" 才调用 autoFormatChaptersForPublish
  • 否则完全跳过自动排版

这样不会再出现“某个按钮偷偷走了AI重排”。

四、持久化设计(保证一致)

NovelPublishRecord 加一个字段:

  • layoutMode?: "preserve" | "ai_reflow"

用途:

  • 保存作者的长期偏好(下次打开发布弹窗默认回显)
  • 一键发布全部章节默认沿用上次策略

五、可观测性(排查友好)

建议顺手加最小日志字段(写到本地 JSON 或 server log):

  • lastPublishAction
  • lastLayoutMode
  • lastFormattedCount
  • lastPublishAt

这样你后面遇到“为什么这章变了”可以直接追溯是不是走了 ai_reflow

六、兼容与迁移

  • 历史数据没有 layoutMode 的默认按 preserve
  • 保留现有 skipAutoFormat 兼容一段时间,但逐步收敛到统一 layoutMode
  • 旧入口逐步替换,避免双语义参数并存太久

七、验收用例(你可直接按这个测)

  • 发布本章(preserve):图片、表格、Markdown渲染保持不变
  • 一键发布(preserve):所有章节不被重排
  • 一键发布(ai_reflow):纯文本段落被重排,图片/表格风险提示一致
  • 同一章节分别走3个入口,结果一致(取决于所选 layoutMode
  • 刷新读者端后内容与作者端最终发布内容一致

如果你确认这个方向,我下一步可以直接按这套方案落地实现(前后端一起改),并给你一个最小可测清单。

10. 发布策略分层

已实现,发布策略分层 现在真正生效了,而且三条发布入口统一了。

这次落地内容

  • 新增发布策略字段:layoutMode
    • 值:preserve(保留排版,默认) / ai_reflow(AI 文本重排)
  • 发布配置弹窗新增“排版策略”单选
    • 默认:保留作者排版(推荐)
    • AI 自动排版带风险提示(可能影响图片/表格)
  • 前端发布入口统一透传策略:
    • 发布配置确认
    • 发布本章
    • 一键发布全部章节
  • Markdown 弹窗“发布本章节”固定走 preserve(保留渲染后格式)

后端统一逻辑

/api/v1/novel-publish 中统一按 layoutMode 决定是否调用 autoFormatChaptersForPublish

  • layoutMode === "ai_reflow":才执行 AI 自动排版
  • layoutMode === "preserve":跳过自动排版,直接发布当前结构内容

并且在发布记录中持久化 layoutMode,后续发布会沿用。


现在你可以稳定预期:

  • 选择“保留作者排版”后,图片/表格/Markdown 渲染不会被自动重排破坏
  • 只有明确选择“AI 自动排版”时,才会触发文本重排

如果你愿意,我下一步可以再补一个很小的 UI 提示:在大纲侧栏“一键发布全部章节”按钮旁显示当前策略(保留排版 / AI重排),避免误触发。

11. 文案修改 + AI赋能自动打标签、写简介

12. 社交媒体作品分享

已按你的需求改完:

  • “社交媒体小说分享”相关文案全部改为“作品”
    • 《xxx》小说《xxx》作品
    • 社交媒体小说分享社交媒体作品分享
  • 分享弹窗和下载分享图都接入了发布配置里的元数据:
    • 作品简介(synopsis
    • 作品标签(tags
  • 后端读者文章接口已返回 tags(从发布记录读取并清洗)

也就是说,你现在在发布配置页里自动生成的“作品简介/作品标签”,会直接体现在社交分享弹窗和“下载本图片”生成图中。
参考页面仍是这个入口:Chenchen-Lib · AI 编辑平台

13. 一键生成抖音视频 - 前端

已改好,你说的两个点都已覆盖在工作台“发布管理”这条分享链路里:

  • 文案统一从“小说”改为“作品”
    • 按钮:社交媒体小说分享社交媒体作品分享
    • 弹窗标题、aria-label、二维码 alt、下载文件名也同步改为“作品”
  • 分享图和弹窗都接入发布配置里的元数据
    • 使用 record.synopsis(作品简介)
    • 使用 record.tags(作品标签)
    • 标签会展示为 #标签 形式,并写入下载图中(最多显示 8 个)

也就是你在发布配置里自动生成的简介/标签,现在会被集成到社交媒体分享文案图片中。
参考入口:Chenchen-Lib · AI 编辑平台

14. 多语言翻译功能

请在http://whale3070.com:3000/workspace
页面,新增多语言翻译功能模块,该模块与“小说发布管理”“账户设置”并列展示,核心功能为小说内容多语言翻译,支持手动触发翻译、选择目标语言、翻译后预览/编辑,同时关联小说发布管理模块,可直接对发布中的小说章节、草稿进行翻译,与账户设置模块联动,保存用户常用翻译语言偏好,确保功能适配页面整体风格,操作流畅无卡顿。使用deepseek api进行翻译。

已完成,在 workspace 页面新增了与“发布管理 / 账户设置”并列的 “多语言翻译” 模块,并接入 DeepSeek 翻译链路与用户偏好联动。

主要实现

  • apps/web/src/components/author-dashboard.tsx 新增顶部页签 多语言翻译,与现有模块并列展示。
  • 新增翻译工作区(暗色风格与发布管理一致):
    • 选择小说(复用发布管理列表数据)
    • 翻译来源切换:发布章节 / 草稿 / 手动输入
    • 章节下拉(标注是否“已发布”)
    • 目标语言下拉(多语言)
    • “手动触发翻译”按钮
    • 翻译进度条(Loading 过程)
    • 原文摘要预览 + 翻译结果预览/可编辑文本框
  • 与账户设置联动:
    • 账户设置 增加“翻译语言偏好”区域
    • 可勾选常用语言、设置默认目标语言
    • 保存后翻译模块自动读取默认语言

新增后端 API(DeepSeek)

  • apps/web/src/app/api/v1/novel-translation/preferences/route.ts
    • GET/POST 用户翻译语言偏好(按钱包地址隔离存储)
  • apps/web/src/app/api/v1/novel-translation/sources/route.ts
    • 查询可翻译来源(章节列表、发布状态、是否有草稿)
  • apps/web/src/app/api/v1/novel-translation/translate/route.ts
    • 执行翻译(sourceType: chapter|draft|manual
    • 使用 DeepSeek chat/completions
    • 返回原文摘要、翻译结果、模型信息

兼容与风格

  • 保持了现有页面视觉体系(边框、色板、暗色卡片、按钮风格一致)。
  • 交互为异步非阻塞,翻译与加载过程都有状态提示和进度反馈。
  • 已检查本次改动文件,当前无新增 linter 错误。

如果你要,我可以继续加两项增强:

  1. “一键复制翻译结果 / 导出 txt”按钮;
  2. “将翻译稿回写到对应章节或草稿”的保存能力(带确认弹窗避免误覆盖)。

15. 中英夹杂的翻译bug

你这个问题本质上是两层:

  • 翻译质量约束不够严格,模型会把部分词当“术语”保留,导致中英夹杂。
  • 流程没有打通到编辑器,所以翻译后还停留在工作台。

这两点我都已经改了。

已修复内容

  • 修复了 DeepSeek 翻译提示词,新增硬约束:
    • 必须完整翻译,不允许保留原文片段
    • 目标语言统一输出,不可混用
    • 英文目标时明确禁止中文字符(人名地名也需英文/拼音转写)
  • 增加英文结果的二次清洗:
    • 若首轮结果仍含中文字符,会自动再走一次“English-only rewrite”清洗流程
  • 改造“多语言翻译 -> 手动触发翻译”流程:
    • 翻译成功后自动跳转到对应小说编辑器
    • 自动打开“翻译 Markdown 对照编辑器”
    • 左侧原文、右侧译文,均可编辑
    • 支持“一键复制译文”
    • 支持“应用译文到当前章节”(直接写入当前章节内容)

你会看到的新行为

workspace 点“手动触发翻译”后,不再只在当前页显示结果,而是直接跳到:

  • 编辑页并弹出双栏对照编辑器(左原文,右译文)
  • 右侧译文可直接修订,然后应用到当前章节

涉及页面

如果你愿意,我下一步可以再加一个“应用前 diff 对比”(高亮显示原文与译文差异),避免误覆盖。

16. 翻译的内容分区

http://whale3070.com:3000/library 这个页面,可以按照不同语言进行分区展示。http://whale3070.com:3000/workspace 在这个多语言翻译哪里,翻译的结果自动保存并展示在,比如说英文区,如果是韩语就展示在韩语区。


已按你的要求打通了这条链路:workspace 翻译结果自动保存,并且 library 按语言分区展示

这次改动内容

  • 在翻译接口里新增自动持久化:

    • 文件:apps/web/src/app/api/v1/novel-translation/translate/route.ts
    • 每次翻译后会写入 .data/translations/<author>_<novel>.json
    • 按语言保存,支持:
      • 章节翻译(按 chapterId
      • 草稿翻译(draftText
      • 手动翻译(manualText
  • 书库接口支持语言分区与语言版本内容读取:

    • 文件:apps/web/src/app/api/v1/library/articles/route.ts
    • 列表接口现在会返回每本书的多语言条目(如英文区、韩语区)
    • 详情接口支持 ?lang=en 这类参数,自动读取对应语言翻译内容
    • 如果某语言只有草稿/手动翻译,也会回填到阅读内容(首章)并更新简介预览
  • 书库页面按语言分区展示:

    • 文件:apps/web/src/app/library/page.tsx
    • 现在会分块显示:中文原文 / 英文区 / 韩语区 ...
    • 点击条目时会携带语言参数跳转(如 /library/<id>?lang=ko
  • 阅读页显示当前语言分区:

    • 文件:apps/web/src/app/library/[articleId]/page.tsx
    • 增加“当前语言分区”显示,便于读者确认在看哪个语言版本

你关心的结果

现在在 workspace 里做翻译(英文/韩语等)后,结果会自动保存;
library 会在对应语言分区看到内容(例如英文区、韩语区)。

你可以这样验收

  1. workspace 里选一部小说翻译成英文/韩语。
  2. 打开书库页,确认出现“英文区/韩语区”分区及条目。
  3. 点击进入后,确认阅读内容是对应语言版本。

相关页面:

这个网站的前后端构架是什么?

整体上这是一个 Next.js 全栈一体化(BFF) 架构,前后端都在同一个 apps/web 项目里。

  • 前端层

    • Next.js 16 + React 19(App Router)
    • 页面和交互主要在 app/*components/*
    • UI 侧用了 TailwindRadixlucide-react
    • 编辑器是 TipTap + marked(Markdown/HTML 双向处理)
  • 后端层(同仓库)

    • 使用 Next 的 Route Handlers(app/api/v1/**/route.ts)当 API 层
    • 运行时是 Node(你代码里很多 export const runtime = "nodejs"
    • 相当于“前端 + API 网关/业务层”合一,不是单独的 Spring/Nest 服务
  • 数据存储层

    • 目前不是传统数据库(MySQL/Postgres),而是本地文件持久化
    • 大量业务数据写在 .data/* 下的 JSON 文件(如 publish、draft、structure、translations)
    • 属于轻量存储方案,适合快速迭代原型/中小规模
  • AI 能力层

    • 通过服务端 API 调用 DeepSeek(chat/completions
    • 用于:自动切章、发布元信息生成、翻译、英文净化等
  • 认证与身份

    • 钱包身份(MetaMask / Web3)为主
    • 前端 wagmi + viem,后端通过 x-wallet-address 做鉴权与隔离
  • 仓库组织

    • 看起来是 monorepo 结构(apps/, services/, shared/
    • 当前线上核心是 apps/web 这套 Next 全栈应用

如果你愿意,我可以再给你画一个“请求链路图”(例如:workspace 点翻译 -> API -> DeepSeek -> .data/translations -> library 分语言读取)。

翻译的大语言模型API切换

已完成,你的翻译链路已经切到 豆包(DOUBAO_API_KEY,并把你列的稳定性策略都加上了,目标就是避免“中英夹杂”。

我改了什么

文件:apps/web/src/app/api/v1/novel-translation/translate/route.ts

  • API 切换

    • DEEPSEEK_* 改为读取 DOUBAO_*
    • 读取优先级:
      • DOUBAO_API_KEY
      • DOUBAO_BASE_URL(默认 https://ark.cn-beijing.volces.com/api/v3
      • DOUBAO_MODEL(默认 doubao-1-5-pro-32k-250115
  • 提示词加硬

    • 明确“必须完整翻译,不允许保留原文片段”
    • 英文目标时写死“不允许任何中文字符
    • 禁止解释/注释/译者说明,只输出正文
  • 温度下调

    • temperature 统一设为 0.1(属于你说的 0~0.2 范围)
  • 分段翻译

    • 长文本按段落切块(约 1400 字符块)翻译,减少漏翻和术语漂移
  • 输出校验 + 重试

    • 英文输出用正则检测中文字符:[\u3400-\u9fff]
    • 命中后自动二次修复(English-only rewrite)
    • 仍命中则按块重试,最多 2
  • 术语表

    • 自动抽取大写词/引号词作为轻量术语表,写入 prompt 保证一致翻译

你需要确认

  • .env.production 里要有 DOUBAO_API_KEY(你已加)
  • 如需自定义模型/地址,可再加:
    • DOUBAO_BASE_URL
    • DOUBAO_MODEL

如果你愿意,我下一步可以再加一个“翻译质量评分字段”(比如英文残留中文率),把每次翻译结果打分存档,方便你在工作台里一眼看出哪些翻译需要重跑。

读者语言设置

http://whale3070.com:3000/library 在这个页面,添加一个读者语言设置的tab,多选,当读者选中 “英语”就只给她看英语区的所有内容。不给她看其他语言的内容。现在这个页面是英文区
我的生平
文章ID:art_176aefb2a7
语言:EN
点击阅读
中文原文
我的生平
文章ID:art_176aefb2a7
语言:ZH
点击阅读。我希望修改后是,my life 英语区的内容。然后用户在设置中添加中文,才能看到中文区的内容。每个分区的所有标题,简介,都使用对应的语言。而不是现在这样,全都是中文介绍。


已按你这个需求改完了,核心行为现在是:

  • library 页面新增了 “读者语言设置” tab(多选)
  • 默认语言偏好是 仅英文 EN
  • 读者只会看到已勾选语言分区内容(不勾选中文就看不到中文区)
  • 在“阅读书库”里,列表会展示每个分区对应语言的 标题 + 简介(不再只显示中文)

这次具体修改

  • apps/web/src/app/library/page.tsx

    • 新增两个 tab:阅读书库 / 读者语言设置
    • 增加多选语言偏好,存储到 localStorage
    • 按所选语言过滤分区展示
    • 列表项增加对应语言的简介展示
  • apps/web/src/app/api/v1/novel-translation/translate/route.ts

    • 翻译后除了正文,还会生成并存档该语言的:
      • displayTitle
      • displaySynopsis
      • tags
  • apps/web/src/app/api/v1/library/articles/route.ts

    • 列表返回语言分区条目时,优先用语言化的 displayTitle/displaySynopsis
    • 详情页也会优先使用语言化标题/简介(不是统一中文)

如果你现在某些英文区条目仍显示中文标题/简介,那是旧数据还没生成 displayTitle/displaySynopsis
只要在工作台对那本书再触发一次英文翻译,就会补齐并在书库里变成对应语言显示。

钱包活跃统计

可以加一个“活跃钱包看板”,按你现在这套架构(Next API + .data 文件)其实很好做,分三层:

1) 先定义“活跃”的口径(最重要)

建议至少有 3 个指标:

  • DAU(钱包):当天有任意行为的钱包数
  • WAU/MAU(钱包):近 7/30 天有行为的钱包数
  • 活跃行为构成:创作、发布、翻译、读者解锁、阅读访问 等各自钱包数

你可以先用一个统一口径:
“调用任一业务 API 且带有效 x-wallet-address 就记活跃”。


2) 事件埋点位置(后端统一记,不靠前端)

在这些 API 入口记一条事件(钱包、动作、时间):

  • 创作编辑相关:/api/v1/save-draft/api/v1/update-structure
  • 发布相关:/api/v1/novel-publish*
  • 翻译相关:/api/v1/novel-translation/*
  • 读者侧付费/解锁:/api/v1/library/articlesPOST
  • 你认为关键的其它入口

事件格式建议:

  • wallet(lowercase)
  • eventType(如 save_draft, translate, publish
  • ts(ISO)
  • 可选:novelId, articleId

3) 存储与统计(先轻量,后升级)

轻量版(适合你现在)

继续用 .data

  • 按天分桶:.data/analytics/wallet-events/2026-04-02.jsonl
  • 每次追加一行 JSON(避免频繁读写整文件)
  • 新增聚合 API:
    GET /api/v1/analytics/active-wallets?range=7d
    返回:
    • dau, wau, mau
    • dailySeries(每天活跃钱包数)
    • byEventType

进阶版(后期)

迁移到 ClickHouse / Postgres(事件量大后更稳)。


4) 后台展示建议

workspace 新增“数据看板”tab:

  • 总览卡片:DAU / WAU / MAU
  • 趋势图:最近 30 天活跃钱包
  • 漏斗:访问钱包 -> 创作钱包 -> 发布钱包 -> 付费解锁钱包
  • Top 行为榜:哪个动作最常发生

5) 反作弊/去重建议

  • 钱包地址统一 toLowerCase()
  • 同钱包同事件 5 秒内去重(防抖)
  • 统计时按 wallet + day 去重,避免刷接口虚高

如果你愿意,我可以下一步给你一版最小可上线方案的接口设计(具体到新增哪些 route、返回 JSON 结构、前端卡片字段),你按这个很快就能实现。

工单管理

已直接开工并完成“工单管理”MVP,包含你要的角色能力:

已上线功能

  • workspace 新增 工单管理 tab
    • 普通用户(连接钱包):
      • 提交工单(标题 + 详情)
      • 查看自己的工单状态
    • 管理员(ADMIN_ADDRESS):
      • 查看全部工单
      • 可标记状态:
        • 已完成(done
        • 已关闭(closed
        • 已忽略(ignored

后端接口

  • POST /api/v1/tickets:创建工单
  • GET /api/v1/tickets:查询工单(管理员看全部,普通用户看自己)
  • PATCH /api/v1/tickets/:id:管理员更新状态

新增文件:

  • apps/web/src/lib/server/tickets.ts
  • apps/web/src/app/api/v1/tickets/route.ts
  • apps/web/src/app/api/v1/tickets/[id]/route.ts

数据存储

  • 工单持久化到:.data/tickets/*.json
  • 管理员地址读取:ADMIN_ADDRESS(支持从环境变量与根 .env.production 读取)

前端接入

  • 修改:apps/web/src/components/author-dashboard.tsx
  • 新增 tab:工单管理
  • 普通/管理员视图按接口返回 isAdmin 自动切换

校验状态

  • 已对改动文件执行 lint 诊断:无新增错误。

如果你要,我下一步可以再补两个小增强:

  1. 工单按状态筛选(待处理/已完成/已关闭/已忽略)
  2. 管理员备注输入框(当前先保留了字段,但 UI 还没填备注入口)。