Files
bilin/desigin/readme.md
T
2026-07-02 16:00:48 +08:00

1333 lines
59 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 笔临——长篇创作智能协作平台 完整设计文档
**版本**1.0
**更新日期**2026年6月25日
**定位**:跨平台长篇小说写作系统,以“人本创作”为核心,通过深度上下文感知与创作流优化,解决AI辅助写作中“难用、不敢用、割裂”的痛点。
---
## 1. 项目概述
### 1.1 产品定位
跨平台长篇小说写作系统,以"人本创作"为核心,通过深度上下文感知与创作流优化,解决AI辅助写作中"难用、不敢用、割裂"的痛点。
### 1.2 产品目标
为网文作者、类型小说家提供从灵感到完稿的一站式创作环境,深度融合智能辅助,同时保障作者对创作主权的绝对控制。核心解决三大问题:
- 写作过程管理混乱(章节、设定、大纲、灵感碎片散落)
- AI辅助与真实创作流脱节(上下文凝固、无法迭代、缺乏细粒度控制)
- 长篇小说规模带来的信息检索与一致性维护成本极高
### 1.3 用户角色
- **长篇连载作者**(主要用户):每日写作,多书并行,需要精细大纲和设定管理,对AI有畏惧和强控制欲。
- **精修型作者**:反复修改,严重依赖版本历史、对比和标注。
- **探索型新人**:通过向导式AI辅助完成第一部作品。
### 1.4 技术选型概要
| 层次 | 技术 | 说明 |
|------|------|------|
| 桌面框架 | Electron | 跨平台(Windows / macOS / Linux |
| 前端框架 | React 18+ | 搭配 TypeScript |
| 编辑器 | TipTap (ProseMirror) | 富文本编辑,支持自定义扩展 |
| 数据库 | SQLite (better-sqlite3) | 本地持久化,每本书一个独立数据库 |
| 国际化 | i18next + react-i18next | 支持 zh-CN / en |
| AI 集成 | 可插拔后端(OpenAI / Anthropic / Ollama 本地) | — |
| 图表/图谱 | Cytoscape.js | 角色关系力导向图 |
| 打包/更新 | electron-builder + electron-updater | — |
| 日志 | electron-log | 按天滚动,保留 7 天 |
| 压缩 | archiver (zip) | 全量导出 |
---
## 2. 全局设计原则
- **本地优先,隐私至上**:所有核心数据存储在本地,AI学习与推理可配置纯本地模式,明文告知数据用途。
- **心流不打断**:任何强制性阻断(如字数锁死、自动弹出提示)均改为软性、可忽略的提醒。
- **所见即所信**:AI的上下文、学习到的风格特征,均对用户可视化且可手动调整。
- **项目即生态**:书籍、设定、对话、版本历史等作为整体"项目包"管理,可一键打包迁移。
- **渐进式复杂度**:新手可用向导快速上手,深度用户可访问所有高级控制(正则搜索、风格权重调节等)。
- **无障可用**:所有交互需支持键盘导航、ARIA 标签、屏幕阅读器友好,确保不同能力用户均可顺畅使用。
---
## 3. UI/UX 系统
### 3.1 全局主题系统
#### 3.1.1 设计原则
- 以**舒适、易用**为主旨,所有主题均经过对比度与视觉疲劳测试。
- 基于 CSS 变量驱动,切换即时生效,无需重启。
- 与阅读模式的字体主题统一管理(见 5.8 连续阅读模式),同一 session 内记忆用户选择。
#### 3.1.2 七套内置主题
| 主题名称 | 类型 | 主背景色 | 主文字色 | 强调色 | 适用场景 |
|----------|------|----------|----------|--------|----------|
| **暗夜黑** | 深色 | `#1a1a2e` | `#e0e0e0` | `#6c63ff` | 夜间长时间写作 |
| **深海蓝** | 深色 | `#0d1b2a` | `#c5d5e8` | `#4ea8de` | 沉浸式创作 |
| **石墨灰** | 深色 | `#2d2d2d` | `#cccccc` | `#ff6b6b` | 中性低调偏好 |
| **暖米纸** | 浅色 | `#f5f0e8` | `#3a3a3a` | `#b8860b` | 模拟纸质书写作 |
| **冷瓷白** | 浅色 | `#fafafa` | `#2c2c2c` | `#2563eb` | 日间清爽写作 |
| **护眼绿** | 护眼 | `#e8f0e0` | `#2d3a2d` | `#4a7c59` | 缓解视疲劳 |
| **琥珀暮色** | 特殊 | `#2b1f1a` | `#e8d5c0` | `#d4a574` | 温暖怀旧氛围 |
#### 3.1.3 CSS 变量体系
```css
:root {
/* 由主题切换动态设置 */
--bg-primary: #...; /* 主背景 */
--bg-secondary: #...; /* 面板/卡片背景 */
--bg-tertiary: #...; /* 悬停/选中态 */
--text-primary: #...; /* 主文字 */
--text-secondary: #...; /* 次级文字 */
--text-muted: #...; /* 辅助/禁用文字 */
--accent: #...; /* 强调色 */
--accent-hover: #...; /* 强调色悬停 */
--border: #...; /* 边框 */
--divider: #...; /* 分割线 */
--shadow: #...; /* 阴影 */
--editor-bg: #...; /* 编辑器背景 */
--editor-text: #...; /* 编辑器文字 */
--scrollbar: #...; /* 滚动条 */
}
```
#### 3.1.4 测试要求
| 用例ID | 层级 | 场景 | 预期结果 |
|--------|------|------|----------|
| E2E-THEME-01 | E2E | 依次切换7个主题 | 所有UI元素颜色正确切换,CSS变量生效 |
| E2E-THEME-02 | E2E | 切换主题后进入阅读模式再退出 | 主题保持,不与阅读模式字体主题冲突 |
| E2E-THEME-03 | E2E | 重启应用 | 主题选择持久化,恢复为上次所选 |
---
### 3.2 多语言支持
#### 3.2.1 功能描述
- 首版支持 **简体中文****English** 两种语言。
- 所有用户可见文本(菜单、按钮、标签、提示、错误消息)必须使用 `i18next` 提供的 `t()` 函数包裹,不得出现硬编码字符串。
- 切换语言后,整个界面即时刷新,无需重启应用。
- 语言选择在全局设置页的"通用"中,默认跟随系统语言,若系统语言非中文或英文则默认中文。
- **强制约束**:在选定语言下,UI 中不得出现任何其他语言的文本(如中文界面出现英文单词,除非是专有名词或用户自行输入的内容)。
#### 3.2.2 技术要点
- 使用 `i18next` + `react-i18next`
- 翻译文件分别位于 `public/locales/zh-CN/translation.json``public/locales/en/translation.json`
- 所有 TipTap 编辑器内的默认占位文本、AI 快捷命令标签等也需国际化。
- 确保数字格式、日期格式随语言调整(中文显示"3,000字",英文显示"3,000 words")。
#### 3.2.3 测试要求
| 用例ID | 层级 | 场景 | 预期结果 |
|--------|------|------|----------|
| UT-I18N-01 | 单元 | 切换语言后,`t('welcome')` 返回对应语言文本 | 文本正确 |
| IT-I18N-02 | 集成 | 设置中切换为 English,检查主页按钮文本 | 变为英文,无中文残留 |
| E2E-I18N-03 | E2E | 从中文切换英文,再切回中文,检查编辑器内占位符和按钮 | 完全恢复中文,无混杂 |
---
### 3.3 首次启动引导
#### 3.3.1 功能描述
应用首次启动(或无任何本地数据)时,按以下步骤展示引导向导:
1. **欢迎页**:笔临 Logo、名称、简短介绍("你的智能长篇创作伙伴")。
2. **功能概览**2-3 页轮播):
- 第一页:章节管理与版本历史。
- 第二页:AI 辅助写作与剧情建议。
- 第三页:知识库与伏笔追踪。
- 每页配有插图和简要说明。
3. **设置笔名**:输入框要求用户输入笔名(必填,至少2个字符)。此笔名将保存在全局设置中,并可在后续章节模板中使用。
4. **完成**:点击"开始创作"按钮,进入主页,并自动创建一本名为"我的第一本书"的示例书籍(可选,根据用户勾选)。
引导过程中允许"跳过"直接进入主页,但强制输入笔名(若跳过则默认使用"未命名作者")。向导窗口模态显示,不可关闭。
#### 3.3.2 技术要点
- 全局设置中存储 `onboardingCompleted` 布尔值,首次启动为 false。
- 笔名存储于 `global_settings``penName` 字段。
- 向导 UI 使用 React 组件,支持淡入淡出动画。
#### 3.3.3 测试要求
| 用例ID | 层级 | 场景 | 预期结果 |
|--------|------|------|----------|
| UT-ONBOARD-01 | 单元 | 未完成引导时,`onboardingCompleted` 为 false | 主页不显示,显示引导弹窗 |
| E2E-ONBOARD-02 | E2E | 首次启动,完成引导输入笔名"山海",跳转主页 | 主页显示,设置中笔名保存为"山海" |
| E2E-ONBOARD-03 | E2E | 引导中点击跳过 | 笔名默认"未命名作者",主页正常显示 |
---
### 3.4 快捷键体系与自定义
#### 3.4.1 默认快捷键列表
| 功能 | 默认快捷键 | 可配置 |
|------|------------|--------|
| 保存当前章节 | `Ctrl+S` | 是 |
| 聚焦AI输入框 | `Ctrl+K` | 是 |
| 新建章节 | `Ctrl+Shift+N` | 是 |
| 切换专注模式 | `Ctrl+Alt+F` | 是 |
| 全局搜索 | `Ctrl+Shift+F` | 是 |
| 快照保存 | `Ctrl+Alt+S` | 是 |
| 弹出灵感快速捕获窗 | `Ctrl+Shift+I` | 是 |
| 导出当前书籍 | `Ctrl+Shift+E` | 是 |
| 关闭当前标签 | `Ctrl+W` | 是 |
| 朗读(播放/暂停) | `Ctrl+Shift+R` | 是 |
#### 3.4.2 自定义方式
在设置页"快捷键"选项卡中,展示所有可配置操作,每个操作显示当前绑定的组合键,点击后可录制新组合键(监听按键后保存)。冲突检测并提示。
#### 3.4.3 技术要点
- 使用 `electron-localshortcut` 或主进程 `globalShortcut` 注册,但需避免与系统/浏览器冲突。
- 自定义快捷键配置存储于 `global_settings``shortcuts` 对象。
- 渲染进程通过 IPC 通知主进程更新注册的快捷键。
#### 3.4.4 测试要求
| 用例ID | 层级 | 场景 | 预期结果 |
|--------|------|------|----------|
| UT-KEY-01 | 单元 | 触发自定义快捷键动作,调用对应处理函数 | 函数被调用 |
| E2E-KEY-02 | E2E | 在编辑器按 `Ctrl+Shift+N` | 侧边栏新增章节 |
| E2E-KEY-03 | E2E | 打开快捷键设置,修改"新建章节"为 `Ctrl+N`,返回编辑器测试 | 原快捷键失效,新快捷键生效 |
---
### 3.5 无障碍设计
#### 3.5.1 ARIA 标签规范
- 所有交互元素(按钮、输入框、菜单、对话框)必须设置 `aria-label``aria-labelledby`
- 动态内容区域设置 `aria-live` 属性(如字数统计使用 `aria-live="polite"`,错误提示使用 `aria-live="assertive"`)。
- 章节树、大纲树使用 `role="tree"` + `role="treeitem"` 结构。
- 模态窗口使用 `role="dialog"` + `aria-modal="true"`
#### 3.5.2 焦点管理
- 打开对话框/模态时,焦点自动移至对话框第一个可聚焦元素。
- 关闭对话框时,焦点回到触发元素。
- Tab 键导航顺序与视觉布局一致,使用 `tabindex` 控制。
- 编辑器与侧边面板之间可通过 `Ctrl+[` / `Ctrl+]` 切换焦点。
#### 3.5.3 键盘导航路径
| 路径 | 快捷键 | 目标 |
|------|--------|------|
| 全局导航栏 | `Alt+1~6` | 书籍/大纲/设定/灵感/AI/设置 |
| 章节列表 | `↑` `↓` | 移动焦点 |
| 章节列表 | `Enter` | 打开章节 |
| 编辑器→侧栏 | `Ctrl+]` | 焦点移至右侧面板 |
| 侧栏→编辑器 | `Ctrl+[` | 焦点回编辑器 |
| 菜单栏 | `Alt` | 激活菜单栏 |
#### 3.5.4 屏幕阅读器支持
- 所有图标按钮提供文字替代(`aria-label`)。
- 图表/图谱提供等效文字描述(`aria-describedby`)。
- 通知/toast 消息使用 `role="alert"``role="status"`
#### 3.5.5 测试要求
| 用例ID | 层级 | 场景 | 预期结果 |
|--------|------|------|----------|
| E2E-A11Y-01 | E2E | 仅使用 Tab 键完成:打开书籍→选章节→编辑→保存 | 全程无需鼠标可完成 |
| E2E-A11Y-02 | E2E | 使用屏幕阅读器浏览章节列表 | 每个章节项被正确读出 |
---
### 3.6 高 DPI 支持
#### 3.6.1 功能描述
- 所有 UI 元素使用相对单位(rem/em),图标使用矢量 SVG。
- 在 Electron 的 `BrowserWindow` 选项中启用 `enablePreferredSizeMode: true` 和正确的 `devicePixelRatio` 处理。
- 自定义标题栏和所有组件需在高缩放比(125%、150%、200%)下保持清晰、不模糊、不错位。
#### 3.6.2 测试要求
| 用例ID | 层级 | 场景 | 预期结果 |
|--------|------|------|----------|
| E2E-DPI-01 | E2E | 设置系统缩放为 150%,启动应用,检查标题栏和编辑器 | 文本清晰,按钮无重叠 |
---
## 4. 书籍与项目管理
### 4.1 多书籍支持
- 支持同时创建/打开多本书籍,以选项卡方式管理,书籍名作为选项卡标题,可拖拽排序、关闭。
- 每本书拥有独立的:章节、分卷、大纲、设定、灵感、AI对话会话、知识库、统计信息。
### 4.2 书籍创建与属性
- **创建时必选**:书名、本地存储路径、目标读者分类(可修改)。
- **分类管理**:系统内置主流网文/出版分类(玄幻、言情、科幻等),用户创建时可多选作为标签;创建后可在书籍属性中随时增删修改。
- **项目封面与简介**:可选,用于个人识别。
- **全书字数目标准**:可选设定总目标字数,用于进度推算。
### 4.3 项目驾驶舱(首页)
打开书籍后首先进入仪表盘视图,展示:
- **写作日历热力图**:记录每日写作字数,空白日灰色显示。
- **核心统计卡片**:今日字数、本周字数、全书总字数、距目标字数、预计完本日期(基于近30天日均速度估算)。
- **结构速览**:各卷字数占比饼图,可点击下钻。
- **伏笔/角色状态摘要**:已埋伏笔数、已回收数、处于"遗忘"状态的伏笔数(超过20章未提及且未标记已回收)。
- **快速入口**:"回到上次编辑位置"、"处理被遗忘的伏笔"、"查看近期新增设定"、"今日大纲任务"。
---
## 5. 分卷与章节管理
### 5.1 分卷
- 支持创建、重命名、排序(拖拽)、删除分卷(卷内章节可跟随删除或移入未分类)。
- 分卷可设置简述(非正文,仅用于大纲级说明)。
- 统计分卷字数、章节数。
### 5.2 章节管理
#### 5.2.1 章节列表
- **树状展示**:卷→章,可折叠;支持拖拽排序(同卷及跨卷移动)。拖拽移动后若章节绑定大纲,询问是否更新大纲关联。
- **章节标记系统**:用户可创建自定义标签(如"高潮""需大修""女主主场"),并给章节打标。列表支持按标签筛选和颜色标识。
- **章节预览**:鼠标悬停显示首段内容及自定义摘要。
- **章节状态**:可手动标注"草稿/润色中/定稿"等状态,不同状态图标区分。
- **章节字数提醒**
- 用户可为每章或分卷统一设置字数提醒阈值(如3000字)。
- 达到阈值时状态栏数字变色(如绿色→橙色),超出部分无阻断,仅通过底色微变提示。
- 显示当前章节字数与本书所有章节平均字数的对比条,辅助节奏把控。
- **快速定位**
- 书签/地标系统:在正文任意位置插入地标(如`TODO: 前文补伏笔`),地标全局列表可查看所有待办,点击一键跳转。
- 章节导航支持关键字搜索定位。
#### 5.2.2 章节批量操作
- 章节列表支持多选:`Ctrl+点击` 选择不连续章节,`Shift+点击` 选择连续范围。
- 选中后显示批量操作工具栏,支持:
- 批量修改状态(草稿/润色中/定稿)
- 批量打标签/去标签
- 批量移动至分卷
- 批量导出(.txt / .docx / .md
- 批量删除(需二次确认,并自动生成备份快照)
- 批量操作进度以非阻塞 toast 提示。
#### 5.2.3 测试要求
| 用例ID | 层级 | 场景 | 预期结果 |
|--------|------|------|----------|
| E2E-BATCH-01 | E2E | Ctrl+点击选择第2、4、7章,批量改为"定稿" | 三章状态同步更新为定稿 |
| E2E-BATCH-02 | E2E | Shift+点击选择5章,批量导出为 .txt | 生成包含5章内容的 .txt 文件 |
---
### 5.3 章节编辑器
#### 5.3.1 基础编辑
- 富文本,支持加粗、斜体、下划线、分割线、缩进、对齐。
- 选择性粘贴:默认`Ctrl+V`粘贴为纯文本,`Ctrl+Shift+V`保留原格式。
- 撤销独立:每个章节维护独立的撤销堆栈,切换章节不影响各自的撤销/重做。
- 引用面板/分屏:写作时可侧栏呼出设定、大纲或灵感条目,支持钉住、搜索、拖拽文本片段到正文。
- 字数统计:实时更新本章、本卷、全书字数,位于状态栏。
#### 5.3.2 撤销堆栈生命周期
- 每个章节的撤销堆栈**持久化到磁盘**,关闭书籍或应用后重新打开仍可撤销上次编辑。
- 每个章节最多保留最近 **50 条**撤销记录,超出后自动移除最早的记录,避免数据库膨胀。
- 手动快照(见 5.4.1)不受此 50 条限制,独立管理。
#### 5.3.3 专注模式
- 全屏隐藏界面边框、工具栏、状态栏(鼠标移至边缘渐现)。
- 可选功能:
- 打字机滚动(当前行始终居中)
- 段落聚焦(除当前段落外变暗)
- 背景音效(见下方 5.3.4
- 实时显示打字速度(字/分钟),退出专注时显示该次写作的速度曲线。
- 快捷键:`Ctrl+Alt+F` 进入/退出。
#### 5.3.4 专注模式背景音效
- **内置音效库**
- 雨声(小雨 / 中雨 / 雷雨)
- 键盘打字声(机械键盘 / 静音键盘)
- 咖啡馆环境音
- 篝火声
- 森林鸟鸣
- 白噪音 / 粉噪音
- 海浪声
- **自定义音频**:用户可上传本地音频文件(mp3 / wav / ogg),添加到音效库。
- 音量独立控制,可与系统音量分离。
- 支持定时关闭(如播放 30 分钟后渐弱消失)。
#### 5.3.5 拼写检查
- 基于开源拼写检查库(如 Hunspell + 中文词典),提供基础拼写/语法提示。
- 初期侧重中文常见错别字提示(如"在/再"、"的/地/得"等),以蓝色波浪下划线标识。
- 右键点击标识文字可查看建议替换词,支持一键替换或"添加到个人词典"。
- 拼写检查可在编辑器工具栏中开关,状态持久化到书籍设置。
#### 5.3.6 TTS 朗读
- 编辑器工具栏 + 阅读模式均提供"朗读"按钮(`Ctrl+Shift+R` 播放/暂停)。
- 使用系统 TTS 引擎或 Web Speech API
- **播放控制**:播放 / 暂停 / 停止
- **速度调节**0.5x / 0.75x / 1x / 1.25x / 1.5x / 2x
- **音色选择**:使用系统可用语音包
- **起点选择**:从光标位置开始朗读,或选中文本朗读
- 朗读时当前句子高亮显示,自动滚动跟随。
#### 5.3.7 测试要求
| 用例ID | 层级 | 场景 | 预期结果 |
|--------|------|------|----------|
| E2E-UNDO-01 | E2E | 编辑章节后关闭书籍,重新打开 | Ctrl+Z 可撤销上次编辑 |
| E2E-SOUND-01 | E2E | 专注模式中选择"雨声"音效 | 播放雨声,退出专注后停止 |
| E2E-SPELL-01 | E2E | 输入"他在在看书",开启拼写检查 | "在在"以蓝色波浪线标识 |
| E2E-TTS-01 | E2E | 点击朗读按钮 | 从光标位置开始朗读,当前句高亮,再次点击暂停 |
---
### 5.4 版本历史与内容追溯
#### 5.4.1 版本保存机制
- **自动快照**
- 可配置时间间隔(默认5分钟),自动保存一个带时间戳的临时版本。
- 临时版本上限(默认20个),超过后合并旧版本或按规则删除。
- **手动快照**:用户可随时生成命名快照(如"删男二戏份前"),不受上限限制。
- **退出/手动保存版本**:应用退出或用户手动触发"保存"时,生成一个持久版本,按照默认3个上限轮替(可配置)。
- **AI相关版本**:AI生成章节被视为初稿,用户修改后自动产生版本历史;重新生成保存当前版本为一个历史版本,重新生成的内容作为章节内容。
#### 5.4.2 版本浏览与对比
- 章节版本列表:显示版本号、时间、类型(自动/手动/AI生成)、摘要(手动快照的命名)。
- **版本对比视图**:双栏并排显示,增删改内容高亮(绿色新增、红色删除+删除线、黄色修改),支持跳转到下一处差异。
- **版本回滚**:可将任意历史版本恢复为当前内容,恢复前自动生成一个备份版本。
#### 5.4.3 章节内容变更追踪
- 在章节列表或编辑器中,对"被人工修改过的AI生成章节"、"有多个AI版本"等给出明显图标标识。
---
### 5.5 大纲、设定与灵感管理
#### 5.5.1 大纲系统
- **层级大纲编辑器**:支持无限层级的树状大纲,可拖拽排序、缩进/提升层级。
- **大纲条目属性**
- 执行状态:待写、写作中(关联章节开始编辑自动标记)、已完成(章节定稿自动标记)、已废弃。
- 预期字数(可选)。
- 关联章节(手动绑定或AI自动匹配)。
- **大纲-正文对照视图**:分屏显示,左侧大纲条目,右侧对应的正文文本段,并展示字数差异。
- **大纲视图过滤**:按状态、关联卷、标签过滤显示。
#### 5.5.2 大纲覆盖度管理
- 大纲树中未关联章节的条目以**橙色左边框 + 警告图标**标记。
- 筛选下拉:全部 / 未覆盖 / 已覆盖。
- 悬停 tooltip 显示:预期字数(如有设定)vs 关联章节实际字数,偏差 > 20% 红色标记。
- `outline_items` 表新增 `expectedWordCount` 可选字段。
#### 5.5.3 测试要求
| 用例ID | 层级 | 场景 | 预期结果 |
|--------|------|------|----------|
| E2E-COV-01 | E2E | 创建大纲条目不关联章节,查看大纲面板 | 条目显示橙色边框和警告图标 |
| E2E-COV-02 | E2E | 筛选"未覆盖" | 仅显示未关联章节的大纲条目 |
#### 5.5.4 设定管理
- 分类组织:角色、地点、物品、技能、势力、自定义类别。
- 每个设定条目:名称、描述、属性字段(可自定义)、关联章节列表(自动记录提及该设定的章节,点击跳转)。
- **写作时引用**:编辑器侧栏可调出设定面板,快速查看并拖拽内容。
- **反向链接**:设定条目页显示"提及章节"和"被AI用作上下文注入的轮次"。
#### 5.5.5 灵感碎片
- **快速捕获**:全局快捷键(`Ctrl+Shift+I`)呼出小窗,立即记录想法;支持语音输入转文字。
- **灵感条目**:标题、内容、创建时间、标签(自定义)。
- **整理模式**:可全览所有灵感,拖拽归类、合并,可一键转为大纲条目或设定条目。
- **提醒与回顾**:可定期(如每周)推送未处理灵感摘要。
---
### 5.6 搜索与一致性工具
#### 5.6.1 全局搜索
- 支持跨章节、大纲、设定、灵感全文搜索。
- 搜索结果:按类型分组,每条结果显示所在位置、前后20字上下文。
- 高级搜索:正则表达式支持、区分大小写、全词匹配。
- 替换功能:支持单次替换、批量替换,批量替换前展示预览列表并需确认。
#### 5.6.2 命名一致性检查(AI驱动)
- 一键扫描全书,识别疑似不一致的专有名词(如"林月/林悦"、"玄火掌/焰火掌"),按置信度排序。
- 用户逐条确认后,可批量替换或忽略。
- 可自定义忽略词库。
#### 5.6.3 用词分析
- **高频词统计**:统计全书的词汇频率(分词后),展示 Top 100 高频词及出现次数。
- **过度用词高亮**:在编辑器中,对出现频率超出阈值(如每千字 > 5 次)的非功能词以淡黄色高亮提示。
- **高频短语**:提取反复出现的 2-4 字短语(如"微微一笑"、"冷哼一声")。
- **分析报告**:生成可导出的用词分析报告,包含词频曲线、重复度评分和改进建议。
- 用词分析面板可在编辑器侧栏或独立窗口打开。
#### 5.6.4 测试要求
| 用例ID | 层级 | 场景 | 预期结果 |
|--------|------|------|----------|
| E2E-WORD-01 | E2E | 打开用词分析面板 | 显示高频词列表,按频次降序排列 |
| E2E-WORD-02 | E2E | 点击某高频词,编辑器跳转到该词位置 | 光标定位并高亮该词所有出现 |
---
### 5.7 故事时间线
#### 5.7.1 功能描述
- 提供独立的"故事时间线"视图,以时间轴方式展示:
- 所有章节及其在故事内的时间标记
- 关键事件(用户手动标注或 AI 自动提取)
- 角色年龄变化(基于角色设定中的出生日期/年龄推算)
- **时间标记方式**
- 每章可设定"故事时间"(如"大陆历 732 年 3 月"、"第一卷 / 第 3 天")。
- 支持相对时间("距上一章 +2 天")和绝对时间两种模式。
- **交互功能**
- 拖拽调整事件顺序
- 缩放时间轴粒度(按章 / 按天 / 按月 / 按年)
- 点击事件/章节跳转到编辑器
- 筛选:按分卷、角色、事件类型过滤
- **角色年龄追踪**:设定角色出生时间点后,时间轴自动计算并显示该角色在每个章节/事件时的年龄。
- **时间冲突检测**:AI 辅助检测时间线上的矛盾(如角色 A 在第 3 章 20 岁,第 5 章(距上章 +1 年)却显示 20 岁)。
#### 5.7.2 技术要点
- 时间轴数据存储于数据库新表 `timeline_events`
- 可视化使用自研 Canvas 组件或轻量时间轴库。
- 与角色设定表联动读取出生日期/年龄字段。
#### 5.7.3 测试要求
| 用例ID | 层级 | 场景 | 预期结果 |
|--------|------|------|----------|
| E2E-TL-01 | E2E | 打开故事时间线 | 显示所有章节按时间排列的时间轴 |
| E2E-TL-02 | E2E | 设置角色出生日,创建章节标记时间,查看 | 角色年龄随章节推进正确变化 |
| E2E-TL-03 | E2E | 检测到时间冲突 | 冲突处标记红色警告提示 |
---
### 5.8 连续阅读模式
#### 5.8.1 功能描述
- 提供独立的全屏阅读模式,将选定卷的所有章节纯文本拼合展示。
- **翻页**:支持键盘(方向键/PageUp/PageDown)和点击翻页,CSS scroll-snap 平滑过渡。
- **设备宽度模拟**:切换按钮——手机(360px) / 平板(768px) / 桌面(100%),通过 max-width 控制。
- **字体主题**:预置 3 套——衬线(serif) / 无衬线(sans-serif) / 护眼(暖米色背景)CSS 变量切换,同 session 内记忆。
- 字体主题与全局主题系统独立,进入阅读模式后覆盖全局主题。
- **虚拟加载**:每次最多渲染 3 章(前一章/当前章/后一章),滚动边界自动预加载。
- 入口:章节列表工具栏按钮 + 分卷右键菜单"阅读模式"。Esc 或关闭按钮退出。
- 阅读模式中同样支持 TTS 朗读(见 5.3.6)。
#### 5.8.2 测试要求
| 用例ID | 层级 | 场景 | 预期结果 |
|--------|------|------|----------|
| E2E-READ-01 | E2E | 选择分卷,点击"阅读模式" | 全屏显示拼合后的章节内容 |
| E2E-READ-02 | E2E | 切换设备宽度为"手机" | 内容区 max-width 变为 360px |
| E2E-READ-03 | E2E | 切换字体主题为"护眼"→退出→重新进入 | 主题保持为护眼模式 |
---
## 6. AI 智能写作系统
### 6.1 会话管理
- **独立会话**:每本书拥有独立的多个会话,支持新建、重命名、归档、导出(导出为`.txt``.md`对话记录)。
- **会话列表**:显示会话摘要(模型、创建时间、最后活跃时间),归档会话折叠。
- **上下文管理**
- **上下文源**:当前书籍的章节(可勾选范围)、大纲(可勾选条目)、设定(可勾选条目)、灵感(可勾选条目)、附件。
- **上下文注入策略**:创建会话时,根据勾选内容初始化;**提供"更新上下文"按钮**,点击后重新提取截至最新的章节摘要、大纲、设定,注入会话。在每轮对话前,系统自动检索最高重要度的知识条目(角色、伏笔等)注入,而非一次性凝固。
- **上下文预览与编辑**:在输入框上方,点击可展开此次实际携带的上下文摘要列表,用户可临时删减某一条目。
### 6.2 快捷命令
- 内置命令:`/续写``/扩写``/润色`(可指定位数和风格)、`/总结`(提供摘要)、`/纠错`
- 命令可搭配自定义要求,如`/续写 紧张节奏,200字`
- 支持用户自定义快捷命令模板。
### 6.3 文风记忆与风格控制
- **文风学习**:开启后,系统分析用户选定范围章节(可设:前N万字/特定卷/全书),提取文风特征(平均句长、对话占比、修饰词偏好、高频词等)。
- **风格控制面板**
- 特征以可视化滑杆呈现,可手动调整权重或禁用某项特征(如"禁用'冷笑'")。
- 支持保存多个风格预设,可针对不同章节切换。
- **学习范围与重置**:可随时更改学习范围,重置学习数据。
- **隐私保障**:承诺数据仅用于当前书籍增强,不上传训练基础模型;提供纯本地推理选项。
### 6.4 Skill/MCP 扩展
- 系统内置多套风格Skill(如"玄幻热血"、"悬疑深沉"等),用户可在设置中查看、启用、修改。
- 支持导入社区或自定义Skill文件。
- 提供MCP连接器接口,允许接入外部工具(需用户授权)。
### 6.5 AI 写作模式
#### 6.5.1 交互式写作
- **启动条件**:需存在至少1章已完成章节,或有大纲/设定内容,否则引导用户先创建。
- **流程(以场景为单位循环)**
1. **上下文注入确认**:AI展示将使用的关键上下文条目,用户可勾选调整。
2. **剧情走向建议**:AI基于上下文提供3个剧情走向,每条附带50字以上简要说明,重点描述剧情转折和影响。
3. **用户选择**:可单选走向,也可混合选择并补充指令。
4. **场景生成**:AI根据选定走向生成一个场景(通常600-1500字)。生成过程中如遇到需要命名的元素(角色、技能、地点等),AI暂停并给出5个命名选项,附带简短解析,用户可选用或自行输入。
5. **场景确认与微调**:生成后展示,用户可在该轮直接输入修改指令(如"让林月的回应更有敌意"),AI针对此场景修改,不重写全章。
6. **循环**:一个场景满意后,AI继续提供下一场景的剧情走向,直至用户点击"结束本章"。
- **章节成文**:交互完成后,所有场景整合为完整章节,自动存入章节列表,标记为AI初稿。
#### 6.5.2 自动写作
- **需设定章节目标**:用户指定本章需达成的剧情点(可点选大纲条目或手写),设定目标字数范围。
- **流程**:AI全自动规划场景顺序,连续写作,达到章节目标时自动停止,生成完整章节。
- **用户干预**:可随时暂停,转入交互模式继续或中止。
#### 6.5.3 向导式写作(为新手设计)
- **分步引导**
1. 确认本章目标(从大纲选取或输入)。
2. 选择本章节奏(舒缓/紧张/混合)和风格偏好(临时覆盖全局)。
3. 选择视角人物。
4. 确认注入的知识条目与伏笔清单。
5. 预览生成策略——AI 展示:"我将以[视角人物]视角,用[紧张]节奏,写一段达成[目标]的剧情,重点回收[伏笔A],发展[关系B]。" 用户确认后开始生成。
- 生成后进入交互微调模式。
### 6.6 AI 大纲展开为章节骨架
#### 6.6.1 功能描述
- 右键大纲条目 → "生成章节骨架" → AI 基于大纲条目标题+描述生成 300-500 字章节开头。
- 生成后自动创建关联章节,状态设为"AI初稿",编辑器自动打开。
- **可降级**:有本地模型可用本地,离线+无本地模型时菜单项灰显"需要AI服务"。
- 超时处理:默认 60 秒超时,可在全局设置调整。
- 生成失败:错误 toast,章节保留(内容为空)。
#### 6.6.2 测试要求
| 用例ID | 层级 | 场景 | 预期结果 |
|--------|------|------|----------|
| IT-SKEL-01 | 集成 | 右键大纲条目→生成骨架 | 新章节创建,内容为AI生成的骨架文本,状态"AI初稿" |
| E2E-SKEL-02 | E2E | 离线无本地模型时右键大纲 | "生成章节骨架"灰显,tooltip"需要AI服务" |
### 6.7 知识抽取与管理(核心)
- **每章生成后自动抽取**:角色状态变化、新埋伏笔、人际关系演变、新出现地点、关键事实。
- **抽取条目人工审核**:在"知识库面板"展示所有抽取项,用户可编辑、合并、删除、打回重抽。
- **重要度标注**:用户可为每条知识打1-5星重要度,影响后续检索注入的优先级。
- **知识库全局视图**
- 角色维度:当前状态、装备、关系网络(简易图谱)。
- 伏笔维度:状态(已埋/部分揭示/已回收/疑似遗忘),关联章节,重要性。
- 地点/物品维度:出现章节、描述演变。
- **下一章生成前自动检索**:根据章节目标和上下文,高重要度相关知识自动注入(用户可在预览中确认)。
### 6.8 离线 AI 功能降级
#### 6.8.1 功能描述
- 应用启动时检测网络状态,并持续监听 `online/offline` 事件。
- 在 AI 聊天界面,若当前配置的 AI 后端为**云端 API**(非本地模型),且网络断开,则:
- 输入框禁用,显示提示文本:"当前网络不可用,已切换为离线模式。请在设置中配置本地模型或连接网络后使用AI功能。"
- 快捷命令按钮变灰。
- 已有历史消息仍可查看。
- 若用户已在设置中启用了本地模型(如 Ollama),即使离线也可正常使用,无需任何提示。
- 网络恢复后,自动恢复 AI 输入功能,并给予短暂提示"网络已恢复"。
#### 6.8.2 技术要点
- 渲染进程通过 `window.electronAPI.onNetworkStatus(callback)` 接收主进程推送的网络状态变更。
- 主进程使用 `net.request` 或轮询一个已知服务来检测真实网络连通性。
- 设置中存储 `aiBackend` 字段(`cloud``local`)。
#### 6.8.3 测试要求
| 用例ID | 层级 | 场景 | 预期结果 |
|--------|------|------|----------|
| UT-AIOFF-01 | 单元 | 模拟离线状态,AI面板组件渲染 | 输入框禁用,提示文字显示 |
| IT-AIOFF-02 | 集成 | 主进程推送 `offline` 状态,渲染进程更新 store | `aiStore.disabled` 为 true |
| E2E-AIOFF-03 | E2E | 断开网络,打开AI助手,尝试输入 | 输入框无法聚焦,提示可见;恢复网络后输入框重新可用 |
### 6.9 AI 配置许可提示
#### 6.9.1 功能描述
在全局设置 → AI配置页面,当用户选择云端模型并输入 API 密钥的区域下方,增加醒目文本:
> "使用云端 AI 服务将受到相应模型提供商的许可协议约束。请在使用前阅读并同意 [OpenAI 服务条款](https://openai.com/policies/terms-of-use) / [Anthropic 服务条款](https://www.anthropic.com/legal/terms) 等。"
此文本为纯提示,无强制勾选框,但作为 UI 一部分显示。
#### 6.9.2 测试要求
| 用例ID | 层级 | 场景 | 预期结果 |
|--------|------|------|----------|
| E2E-LIC-01 | E2E | 打开AI配置,选择云端模型 | 文本区域出现并包含链接 |
### 6.10 附件上传
- 支持上传图片、文档等作为上下文参考(由底层AI引擎能力决定是否启用图文识别)。
- 上传文件仅在当前会话可见,不会自动成为全局设定。
---
## 7. 角色关系图谱
### 7.1 功能描述
- 基于 Cytoscape.js 的力导向图,全屏模态视图。
- 节点 = 角色(名称标签),边 = 关系(描述 + 亲密度 1-5 颜色映射:蓝→绿→黄→橙→红)。
- 数据来源:`settings` 表 type='character' 条目 + `customFields.relationships` JSON。
- 交互:拖拽节点、缩放平移、点击节点→侧栏编辑角色详情、点击边→编辑关系。
- 布局选项:默认 cose-bilkent 力导向、可选 grid / circle。
- 性能约束:节点上限 100,超出时提示筛选。
### 7.2 关系创建的三种方式
1. **角色详情页手动添加**:在角色编辑面板的"关系"区域,从下拉列表选择目标角色,设置关系描述(如"师徒"、"暗恋"),调整亲密度(1-5),保存后自动更新图谱。
2. **图谱中拖拽连线**:在图谱视图中,右键点击源角色节点,选择"连线",再点击目标角色节点,弹出关系编辑弹窗,填写描述和亲密度后确认。
3. **AI 章节分析后自动建议**:AI 分析当前章节后可识别潜在角色关系变更(如"林月对张三的态度从冷漠转为感激"),在知识抽取面板中展示为"关系建议",用户可一键添加或忽略。
### 7.3 测试要求
| 用例ID | 层级 | 场景 | 预期结果 |
|--------|------|------|----------|
| E2E-GRAPH-01 | E2E | 打开角色关系图谱 | 显示力导向图,角色为节点,关系为边 |
| E2E-GRAPH-02 | E2E | 点击角色节点 | 侧栏显示角色详情,可编辑 |
| E2E-GRAPH-03 | E2E | 切换布局为"圆形" | 节点重新排列为圆形 |
| E2E-GRAPH-04 | E2E | 图谱中拖拽连线创建关系 | 新边出现,亲密度颜色正确 |
---
## 8. 写作目标与打卡系统
### 8.1 功能描述
- **日更目标**`settings_global.dailyWordGoal`(默认 0 = 不启用),状态栏实时进度条(绿≥100%, 橙≥80%)。
- **连更追踪**`writing_logs` 表记录每日字数,连续达标天数计数器,达标通知。
- **日历热力图**:Canvas 自绘组件,365 天,颜色深浅反映字数,今天高亮。
- **里程碑庆祝**:7/30/100 天连更通知 + 徽章展示。
- **番茄钟**:25 分钟倒计时,开始/暂停/取消,完成时通知 + 显示该次新增字数。
- `writing_logs` 表结构:`(date TEXT, bookId TEXT, wordCount INTEGER, PRIMARY KEY (date, bookId))`
### 8.2 测试要求
| 用例ID | 层级 | 场景 | 预期结果 |
|--------|------|------|----------|
| E2E-GOAL-01 | E2E | 设定日更目标 3000 字,写 3500 字 | 进度条变绿,显示达标通知 |
| E2E-GOAL-02 | E2E | 连续 7 天达标 | 显示 7 天里程碑徽章 |
| E2E-GOAL-03 | E2E | 启动番茄钟,25分钟后查看 | 番茄钟完成通知,显示该次写作字数 |
---
## 9. 个人写作分析
- **写作速度仪表盘**:按小时统计平均写作速度,展示效率曲线和每日时段热力图。
- **习惯追踪**:连续写作天数、平均每次写作时长、最喜欢写作的时段。
- **字数分布**:按卷、按人物视角章节字数统计。
---
## 10. 章节模板系统
### 10.1 内置模板
- **通用模板**`## 第{n}章 {标题}`n 自动递增,标题可手动输入)。
- **网文常用**:包含"正文"和"作者的话"两段,格式固定。
### 10.2 自定义模板
- 用户可在"书籍设置" → "章节模板"中创建新模板。
- 模板内容可包含变量:
| 变量 | 说明 |
|------|------|
| `{chapterNumber}` | 自动递增的章节数字 |
| `{chapterTitle}` | 新建时弹窗输入 |
| `{penName}` | 笔名 |
| `{date}` | 日期 |
| `{volumeName}` | 当前分卷名称|
| `{previousChapterTitle}` | 上一章标题,首章为空字符串 |
| `{outlineItem}` | 关联大纲条目名称,无关联则为空 |
| `{characterList}` | 当前卷出场角色列表,逗号分隔 |
- 模板可设置默认状态(草稿/定稿等)。
### 10.3 快速新建章
- 在章节列表底部提供"快速新建"按钮,点击后弹出小窗:选择模板 → 输入标题 → 确定,立即创建章节并自动应用模板内容到编辑器。
- 如果当前卷下已有章节,自动增加章节号。
### 10.4 技术要点
- 模板数据存储在 `global_settings``chapterTemplates` 数组中。
- 快速新建弹窗使用 Radix Dialog。
- 模板解析在渲染进程完成,替换变量后调用创建章节 API。
### 10.5 测试要求
| 用例ID | 层级 | 场景 | 预期结果 |
|--------|------|------|----------|
| UT-TEMPL-01 | 单元 | 解析模板 `"第{chapterNumber}章 {title}"`,传入 `number=5, title='觉醒'` | 输出"第5章 觉醒" |
| UT-TEMPL-02 | 单元 | 模板含 `{volumeName}`,当前卷名"第一卷 觉醒" | 替换为"第一卷 觉醒" |
| IT-TEMPL-03 | 集成 | 使用自定义模板快速新建章节,检查数据库内容 | 章节内容符合模板格式,编号正确 |
| E2E-TEMPL-04 | E2E | 创建新模板,然后快速新建章节,观察编辑器内容 | 编辑器自动填入模板文本 |
| E2E-TEMPL-05 | E2E | 使用含 `{characterList}` 的模板新建章节 | 模板中替换为出场角色列表 |
---
## 11. 导入导出
### 11.1 导入
- 支持 `.txt``.docx``.md` 及笔临专用 `.novel` 项目包。
- 导入时自动识别章节分隔标记(如`# 第.*章`)并分章;`.docx`保留加粗、斜体等基本格式。
#### 11.1.1 超大文件导入提示
- 主进程先读取文件大小。
- 若文件大于 20MB,在导入前弹出确认框:"检测到文件较大,导入可能需要较长时间(约 30 秒至 2 分钟),是否继续?"
- 导入过程中显示进度条,完成后提示成功。
#### 11.1.2 测试要求
| 用例ID | 层级 | 场景 | 预期结果 |
|--------|------|------|----------|
| IT-LARGE-01 | 集成 | 模拟导入一个 50MB 的 txt 文件 | 弹出确认框,确认后进度条显示,最终导入成功 |
| E2E-LARGE-02 | E2E | 尝试导入一个大文件,取消操作 | 文件未被导入 |
### 11.2 导出
#### 11.2.1 常规导出
- 单章/分卷/全书导出为 `.txt``.docx`(自动生成目录)、`.md`、**.pdf**。
- **项目打包导出**:整书所有数据(章节全部版本、设定、大纲、对话、知识库、配置)打包为 `.novel` 文件,用于完整迁移或备份。
- **导出选项**:是否包含批注、是否附带AI生成标注、是否还原历史版本到独立文件。
#### 11.2.2 PDF 导出
- 支持排版模板:
- **纸张尺寸**A4 / 信纸 (Letter)
- **页眉**:书名(左) + 章节名(中) + 页码(右)
- **页脚**:笔名(左) + 导出日期(右)
- 支持字体选择(系统已安装字体),默认使用衬线字体。
- 支持行间距、段落间距调整。
- 导出前预览排版效果。
- 技术方案:使用 Puppeteer 渲染 HTML 后生成 PDF,或使用 pdf-lib 直接构建。
#### 11.2.3 全量导出所有书籍
- 在主页(或设置页的"备份与同步"中)提供"导出所有书籍"按钮。
- 点击后弹出文件保存对话框,用户选择存储路径,将**所有书籍**的数据打包为一个单独的 `.novel-all` 归档文件。
- 打包格式为 ZIP 压缩包,内部结构清晰:每个书籍一个子文件夹,包含其 SQLite 数据库副本及附件(若有),以及一个全局设置文件 `global_settings.json`
- 导出进度以模态窗口展示(百分比/进度条),大数据量时不阻塞界面。
- 支持取消操作。
- 导出前估算总大小,如过大(>500MB)提示用户,并提供分段导出或压缩选项。
#### 11.2.4 测试要求
| 用例ID | 层级 | 场景 | 预期结果 |
|--------|------|------|----------|
| UT-ALL-01 | 单元 | `exportAllBooks` 成功生成压缩包 | ZIP 文件存在,结构正确 |
| IT-ALL-02 | 集成 | 导出 3 本书,删除全部数据后重新导入全量包 | 所有书籍及内部数据完全恢复,包括版本历史 |
| E2E-ALL-03 | E2E | 点击"导出所有书籍",选择路径,等待完成,检查文件 | 生成 `.novel-all` 文件,解压后包含各书籍数据库 |
| E2E-PDF-01 | E2E | 导出单章为 PDF(A4模板) | 生成 PDF,页眉含书名+章节名+页码 |
---
## 12. 数据与存储
### 12.1 数据库选型与 Schema 迁移
#### 12.1.1 数据库选型
- 采用 **SQLite**(通过 `better-sqlite3` 同步访问),每本书一个独立的 `.sqlite` 数据库文件。
- 全局设置存储在 `userData/global_settings.json` 中,不进入书籍数据库。
- 选型理由:零配置、无需服务进程、文件即数据库便于打包迁移、与 Electron 深度兼容。
#### 12.1.2 Schema 版本管理
- 每个数据库文件包含一个 `schema_version` 表:
```sql
CREATE TABLE IF NOT EXISTS schema_version (
version INTEGER PRIMARY KEY,
applied_at TEXT NOT NULL DEFAULT (datetime('now')),
description TEXT
);
```
- 应用启动时检查数据库版本,若低于当前应用版本,按序执行迁移脚本。
- 迁移脚本存放于 `src/main/db/migrations/`,命名格式 `NNN_description.sql`(如 `002_add_expected_word_count.sql`)。
- 迁移在事务中执行,失败则回滚并提示用户备份当前数据。
- 禁止在迁移中删除列或表——仅允许新增列/表、创建索引,确保向前兼容。
#### 12.1.3 测试要求
| 用例ID | 层级 | 场景 | 预期结果 |
|--------|------|------|----------|
| UT-DB-01 | 单元 | 创建新数据库 | `schema_version` 表存在,version 为当前最新 |
| IT-DB-02 | 集成 | 使用旧版数据库(version=1)启动新版应用(version=2 | 自动执行迁移,version 更新为 2,数据无损 |
---
### 12.2 撤销堆栈持久化
- 每个章节维护独立的撤销/重做堆栈,最多保留 **50 条**记录。
- 堆栈持久化到章节所在书籍数据库的 `undo_stack` 表:
```sql
CREATE TABLE undo_stack (
id INTEGER PRIMARY KEY AUTOINCREMENT,
chapter_id TEXT NOT NULL,
operation TEXT NOT NULL, -- JSON: 操作类型及数据
timestamp TEXT NOT NULL DEFAULT (datetime('now')),
FOREIGN KEY (chapter_id) REFERENCES chapters(id) ON DELETE CASCADE
);
```
- 超出 50 条时,删除该章节最早的记录。
- 手动快照不受此 50 条限制,走独立的 `snapshots` 表。
---
### 12.3 云同步
#### 12.3.1 功能描述
- 用户可在"设置 → 备份与同步"中配置云同步:
- **同步方式**:WebDAV / 本地云盘目录路径(如 Dropbox 文件夹、OneDrive 文件夹)。
- **同步内容**`.novel` 项目包(整书打包)。
- **同步模式**
- 手动同步:点击"立即同步"按钮。
- 定时同步:可配置间隔(每小时 / 每天 / 每周),后台静默执行。
- **数据始终加密**:同步前使用 AES-256-GCM 加密 `.novel` 包,密钥由用户设定的同步密码派生(PBKDF2),不存储明文密钥。
- 同步冲突检测:若远程和本地均有更新,提示用户选择保留版本或合并。
- 首次配置时引导用户设置同步密码(至少 8 位)。
#### 12.3.2 技术要点
- 主进程负责同步调度,使用 `cron``node-cron` 定时触发。
- 加密使用 Node.js `crypto` 模块。
- 同步状态在状态栏显示图标(已同步/同步中/同步失败)。
#### 12.3.3 测试要求
| 用例ID | 层级 | 场景 | 预期结果 |
|--------|------|------|----------|
| IT-SYNC-01 | 集成 | 配置 WebDAV,点击"立即同步" | `.novel` 加密后上传到 WebDAV 服务器 |
| E2E-SYNC-02 | E2E | 两台设备配置同一 WebDAV,A 同步后 B 同步 | B 获取到 A 的数据,可正常打开 |
---
### 12.4 数据安全与备份
- **自动保存草稿**:编辑器内任何停顿超过2秒,当前片段自动存入本地临时数据库,防止意外丢失。
- **项目包备份**:支持手动和定时自动打包为`.novel`文件,可存储于本地或云盘。
- **本地数据库加密**:可选项,使用 SQLCipher 加密 SQLite 数据库,保护隐私。
---
## 13. 崩溃报告与日志
### 13.1 功能描述
- 主进程和渲染进程的未捕获异常通过 `electron-log` 记录到本地文件。
- 日志文件路径:`{userData}/logs/bilin.log`,按天滚动(保留最近7天)。
- 崩溃后下次启动时,检测上次是否异常退出,询问用户是否发送崩溃报告(匿名)。
- 发送报告功能调用后端 API(暂不实现,但保留按钮和接口)。
- 日志级别:error、warn、info,生产环境默认记录 error 和 warn。
### 13.2 技术要点
- 主进程全局捕获 `uncaughtException`,渲染进程可通过 `window.onerror``unhandledrejection` 捕获。
- 崩溃报告包含:堆栈跟踪、应用版本、操作系统、CPU/内存信息(脱敏)。
### 13.3 测试要求
| 用例ID | 层级 | 场景 | 预期结果 |
|--------|------|------|----------|
| UT-LOG-01 | 单元 | 手动触发一个错误,检查日志文件是否写入 | 日志文件新增错误条目 |
| E2E-LOG-02 | E2E | 模拟渲染进程崩溃(比如抛出未处理错误),重启应用 | 显示"上次异常退出"提示 |
---
## 14. 自动更新机制
### 14.1 功能描述
- 集成 `electron-updater`,基于 GitHub Releases 或自定义更新服务器。
- 启动后静默检查更新,有新版时在状态栏或顶栏显示"新版本可用"通知,点击可查看更新日志并选择立即更新或稍后提醒。
- 下载进度在通知中显示,下载完成后提示用户重启应用以安装。
- 支持 Windows/macOS 的代码签名验证(暂时不实施签名,但保留渠道接口)。
### 14.2 技术要点
- 主进程 `autoUpdater` 配置 `feedURL`
- 通过 IPC 向渲染进程发送 `update-available``download-progress``update-downloaded` 事件。
- 在开发环境中禁用更新检查。
### 14.3 测试要求
| 用例ID | 层级 | 场景 | 预期结果 |
|--------|------|------|----------|
| IT-UPDATE-01 | 集成 | 模拟有新版本推送,渲染进程收到事件 | 界面出现更新提示 |
| E2E-UPDATE-02 | E2E | 点击"立即更新",下载进度变化,完成后提示重启 | 重启后版本号更新(需模拟) |
---
## 15. 扩展 API 架构
### 15.1 设计目标
为第三方开发者提供标准化接口,允许扩展编辑器的功能面板、导入导出格式、AI 后端、自定义 Skill 等。初期不实现完整插件系统,但预留架构接口并文档化。
### 15.2 扩展点
| 扩展点 | 类型 | 说明 |
|--------|------|------|
| **侧边栏面板** | UI 扩展 | 注册自定义面板到编辑器侧栏,获取当前书籍/章节上下文 |
| **导入格式** | 数据处理 | 注册文件扩展名 + 解析器,将自定义格式转为内部章节结构 |
| **导出格式** | 数据处理 | 注册文件扩展名 + 渲染器,将章节内容输出为自定义格式 |
| **AI 后端** | 服务扩展 | 实现标准接口(`chat`, `stream`, `abort`),注册为可选 AI 引擎 |
| **Skill** | AI 扩展 | 在现有 Skill 机制中加入自定义 skill |
| **编辑器插件** | TipTap 扩展 | 注册 TipTap 节点/标记/命令 |
| **菜单项** | UI 扩展 | 在右键菜单/工具栏注册自定义操作 |
### 15.3 接口规范(概要)
```typescript
// 扩展清单 - package.json 中的笔临扩展申明
interface BilinExtension {
name: string;
version: string;
description: string;
main: string; // 入口文件
permissions: string[]; // 所需权限
contributes: {
sidePanels?: SidePanelConfig[];
importers?: ImporterConfig[];
exporters?: ExporterConfig[];
aiBackends?: AIBackendConfig[];
skills?: SkillConfig[];
editorExtensions?: EditorExtensionConfig[];
menuItems?: MenuItemConfig[];
};
}
```
### 15.4 安全约束
- 所有扩展默认沙箱运行,需声明权限。
- 敏感权限(文件系统写入、网络访问)需用户在设置中显式授权。
- 扩展只能通过笔临提供的 API 与核心交互,不可直接访问 Electron 主进程。
---
## 16. IPC 错误协议统一
### 16.1 功能描述
- 所有 IPC 返回值统一为 `IpcResult<T>` 信封:
```typescript
type IpcResult<T> =
| { ok: true; data: T }
| { ok: false; error: IpcError };
interface IpcError {
code: ErrorCode;
message: string;
recoverable: boolean;
}
enum ErrorCode {
DB_READ_FAILED = 'DB_READ_FAILED',
DB_WRITE_FAILED = 'DB_WRITE_FAILED',
FILE_NOT_FOUND = 'FILE_NOT_FOUND',
FILE_TOO_LARGE = 'FILE_TOO_LARGE',
AI_TIMEOUT = 'AI_TIMEOUT',
AI_NETWORK = 'AI_NETWORK',
AI_RATE_LIMITED = 'AI_RATE_LIMITED',
EXPORT_FAILED = 'EXPORT_FAILED',
IMPORT_INVALID = 'IMPORT_INVALID',
UNKNOWN = 'UNKNOWN',
}
```
- `recoverable: true` → 渲染进程显示"重试"按钮;`false` → 仅提示。
- 主进程崩溃检测:`win.on('crashed')` + 下次启动检测异常退出标志 → 弹窗恢复草稿。
### 16.2 测试要求
| 用例ID | 层级 | 场景 | 预期结果 |
|--------|------|------|----------|
| IT-IPC-01 | 集成 | 模拟 DB 写入失败,调用章节保存 | 返回 `{ ok: false, error: { code: "DB_WRITE_FAILED", recoverable: true } }` |
| E2E-IPC-02 | E2E | 触发可恢复错误,点击重试 | 重新调用 IPC,成功完成 |
---
## 17. 非功能需求
### 17.1 性能
- **大书加载**:章节列表和正文采用虚拟滚动/分页加载,百万字书籍流畅运行。
- **实时统计**:字数统计采用增量更新机制,避免全盘扫描。
- **异步保存**:所有写入操作后台进行,不阻塞界面交互。
### 17.2 跨平台
- 支持 Windows、macOS、Linux 主流桌面系统。
- 未来考虑移动端(阅读与灵感捕获),需保证数据格式兼容同步。
### 17.3 易用性
- 向导式创作5分钟内可完成首章;高级功能通过右键菜单、快捷键暴露。
### 17.4 可扩展性
- Skill 和 MCP 接口文档化,鼓励社区生态。
- 扩展 API 文档化(见第 15 章)。
### 17.5 隐私承诺
- 在应用中明确展示数据流向,提供纯本地处理选项,敏感操作二次确认。
- 云端同步数据始终 AES-256-GCM 加密,密钥不离开用户设备。
### 17.6 国际化
- 首版支持简体中文和英文,界面框架可扩展更多语言。
---
## 18. 系统架构总览
```mermaid
graph TB
subgraph "Electron Main Process"
DB[SQLite 数据库<br/>每书一个 .sqlite]
FS[文件系统<br/>导入/导出/日志]
UPD[自动更新<br/>electron-updater]
SYNC[云同步<br/>WebDAV/AES加密]
IPC_M[IPC 主进程<br/>IpcResult 信封]
end
subgraph "Electron Renderer Process"
REACT[React 18+ 应用]
EDITOR[TipTap 编辑器]
STORE[状态管理<br/>Zustand / Jotai]
I18N[i18next 国际化]
THEME[CSS变量主题系统<br/>7套主题]
end
subgraph "AI 层"
AI_LOCAL[本地模型<br/>Ollama]
AI_CLOUD[云端 API<br/>OpenAI / Anthropic]
AI_MCP[MCP 连接器]
end
subgraph "扩展层"
EXT_API[扩展 API<br/>Phase 0 架构预留]
SKILL[Skill 系统]
end
REACT --> EDITOR
REACT --> STORE
REACT --> I18N
REACT --> THEME
IPC_M <--> REACT
DB --> IPC_M
FS --> IPC_M
UPD --> IPC_M
SYNC --> IPC_M
AI_LOCAL --> IPC_M
AI_CLOUD --> IPC_M
AI_MCP --> IPC_M
EXT_API --> REACT
SKILL --> AI_LOCAL
SKILL --> AI_CLOUD
```
---
## 19. 数据库核心 Schema
```sql
-- 全局设置(JSON 文件,非SQLite
-- global_settings.json
{
"penName": "string",
"onboardingCompleted": false,
"theme": "暗夜黑",
"language": "zh-CN",
"dailyWordGoal": 0,
"shortcuts": {},
"aiBackend": "cloud",
"aiTimeout": 60,
"syncConfig": {},
"chapterTemplates": []
}
-- 每本书的 SQLite 数据库
CREATE TABLE schema_version (
version INTEGER PRIMARY KEY,
applied_at TEXT NOT NULL DEFAULT (datetime('now')),
description TEXT
);
CREATE TABLE volumes (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
description TEXT DEFAULT '',
sort_order INTEGER NOT NULL DEFAULT 0,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE chapters (
id TEXT PRIMARY KEY,
volume_id TEXT,
title TEXT NOT NULL DEFAULT '',
content TEXT NOT NULL DEFAULT '',
status TEXT NOT NULL DEFAULT 'draft', -- draft/reviewing/final
word_count INTEGER NOT NULL DEFAULT 0,
sort_order INTEGER NOT NULL DEFAULT 0,
summary TEXT DEFAULT '',
story_time TEXT DEFAULT NULL, -- 故事时间标记(V2.0新增)
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
FOREIGN KEY (volume_id) REFERENCES volumes(id) ON DELETE SET NULL
);
CREATE TABLE chapter_tags (
chapter_id TEXT NOT NULL,
tag TEXT NOT NULL,
color TEXT DEFAULT '',
PRIMARY KEY (chapter_id, tag),
FOREIGN KEY (chapter_id) REFERENCES chapters(id) ON DELETE CASCADE
);
CREATE TABLE bookmarks (
id TEXT PRIMARY KEY,
chapter_id TEXT NOT NULL,
position INTEGER NOT NULL, -- 字符偏移
label TEXT NOT NULL,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
FOREIGN KEY (chapter_id) REFERENCES chapters(id) ON DELETE CASCADE
);
CREATE TABLE snapshots (
id TEXT PRIMARY KEY,
chapter_id TEXT NOT NULL,
type TEXT NOT NULL, -- auto/manual/ai
name TEXT DEFAULT '',
content TEXT NOT NULL,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
FOREIGN KEY (chapter_id) REFERENCES chapters(id) ON DELETE CASCADE
);
CREATE TABLE undo_stack (
id INTEGER PRIMARY KEY AUTOINCREMENT,
chapter_id TEXT NOT NULL,
operation TEXT NOT NULL, -- JSON
timestamp TEXT NOT NULL DEFAULT (datetime('now')),
FOREIGN KEY (chapter_id) REFERENCES chapters(id) ON DELETE CASCADE
);
CREATE TABLE outline_items (
id TEXT PRIMARY KEY,
parent_id TEXT,
title TEXT NOT NULL,
description TEXT DEFAULT '',
status TEXT NOT NULL DEFAULT 'pending', -- pending/writing/done/abandoned
expected_word_count INTEGER DEFAULT NULL,
chapter_id TEXT, -- 关联章节
sort_order INTEGER NOT NULL DEFAULT 0,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
FOREIGN KEY (parent_id) REFERENCES outline_items(id) ON DELETE CASCADE,
FOREIGN KEY (chapter_id) REFERENCES chapters(id) ON DELETE SET NULL
);
CREATE TABLE settings (
id TEXT PRIMARY KEY,
type TEXT NOT NULL, -- character/location/item/skill/faction/custom
name TEXT NOT NULL,
description TEXT DEFAULT '',
properties TEXT DEFAULT '{}', -- JSON: 自定义属性
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE setting_chapter_refs (
setting_id TEXT NOT NULL,
chapter_id TEXT NOT NULL,
PRIMARY KEY (setting_id, chapter_id),
FOREIGN KEY (setting_id) REFERENCES settings(id) ON DELETE CASCADE,
FOREIGN KEY (chapter_id) REFERENCES chapters(id) ON DELETE CASCADE
);
CREATE TABLE inspiration (
id TEXT PRIMARY KEY,
title TEXT NOT NULL DEFAULT '',
content TEXT NOT NULL DEFAULT '',
tags TEXT DEFAULT '[]', -- JSON数组
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE ai_sessions (
id TEXT PRIMARY KEY,
name TEXT NOT NULL DEFAULT '',
model TEXT NOT NULL DEFAULT '',
archived INTEGER NOT NULL DEFAULT 0,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
last_active TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE writing_logs (
date TEXT NOT NULL,
book_id TEXT NOT NULL,
word_count INTEGER NOT NULL DEFAULT 0,
PRIMARY KEY (date, book_id)
);
-- V2.0新增
CREATE TABLE timeline_events (
id TEXT PRIMARY KEY,
chapter_id TEXT,
title TEXT NOT NULL,
description TEXT DEFAULT '',
event_type TEXT NOT NULL DEFAULT 'general', -- general/character_age/plot_twist/...
story_time TEXT NOT NULL, -- 故事内时间
sort_order INTEGER NOT NULL DEFAULT 0,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
FOREIGN KEY (chapter_id) REFERENCES chapters(id) ON DELETE SET NULL
);
```
---