Capture chapter templates, txt/md/docx import, submission presets, and global inspiration capture for the daily writing workflow release. Co-authored-by: Cursor <cursoragent@cursor.com>
16 KiB
笔临 v1.1 作家日更工具包 设计规格
版本:1.0
日期:2026-07-08
范围:§10 章节模板 + §11.1 书籍导入(txt/md/docx)+ §20.2 投稿导出预设 + §20.6 全局灵感捕获增强
前置:v1.0.0 已交付(4adafa1:P7 角色关系图谱 + P9 写作分析)
参考:design/readme.md v1.1 §10 / §11.1 / §20.2 / §20.6、design/ui_pc.html #templateModal / #importModal / #exportModal / #inspirationModal
目标版本:v1.1.0
1. 背景与目标
1.1 阶段定位
v1.0.0 已完成「看数据」能力(关系图谱、写作分析、POV)。design/readme.md §20.7 审查清单仍有多项 有 UI 原型、无真实实现 的作家刚需:
- 主页「导入书籍」为
comingSoon - 章节模板 / 快速新建章仅有
#templateModal静态原型 - 导出模态「复制到剪贴板(网文投稿格式)」无后端
- 灵感捕获
Ctrl+Shift+I仅编辑器内可用,保存后会跳转侧栏打断心流
本阶段(v1.1.0)交付 作家日更工具包,形成「写得更快 → 发得更顺 → 灵感不漏」闭环。
1.2 已确认决策(Brainstorming 2026-07-08)
| 维度 | 决策 |
|---|---|
| 方向 | 方案 B:作家日更工具包 |
| MVP 边界 | 方案 A(完整四模块):模板 + txt/md/docx 导入 + 投稿预设 + 灵感增强 |
| 模板存储 | GlobalSettings.chapterTemplates[];内置模板代码常量合并展示 |
| 模板解析 | 渲染进程 chapter-template.ts 替换变量后 chapter.create + chapter.update |
| docx 解析 | mammoth(docx → HTML,保留 bold/italic) |
| md 解析 | marked(md → HTML) |
| 导入分章 | 自动正则 / 双换行 / 自定义正则 三档 |
| 大文件 | >20MB 导入前二次确认;进度条 IPC 事件 |
| 投稿导出 | 单章复制剪贴板 + 另存 .txt;内置「通用网文」预设 |
| 投稿预设存储 | GlobalSettings.submissionPresets[] |
| 灵感增强 | 快捷键全局可用;未开书时模态内选书;保存后仅 toast、不跳转 |
| 置顶 | 灵感模态最高 z-index;不新建独立 BrowserWindow |
1.3 验收标准
用户能完成:
- 在章节列表点击「快速新建」,选择模板并输入标题,创建章节且编辑器自动填入模板正文(含变量替换)
- 在设置页创建/编辑/删除自定义章节模板;内置模板只读展示
- 主页「导入书籍」选择
.txt/.md/.docx,预览分章结果,确认后创建新书并导入全部章节 - 导入 >20MB 文件前看到确认提示;导入过程显示进度
- 编辑器内
Ctrl+Shift+E打开导出模态,选择「通用网文」预设,复制到剪贴板 得到段首空两格 +# 第N章 标题格式纯文本 - 设置页自定义投稿预设(标题格式、段首缩进、段落间距),导出时应用
- 在主页按
Ctrl+Shift+I唤起灵感捕获,选择书籍后保存,仅 toast 确认、焦点不打断原界面 - 编辑器内灵感捕获行为与 7 一致(不再自动跳转灵感面板)
1.4 本规格不实现(明确排除)
| 项 | 归属 |
|---|---|
.novel / .novel-all 项目包导入导出 |
v1.2+ |
| PDF / Word 全书导出、分卷批量投稿复制 | v1.2+ |
| §11.2 完整导出矩阵(docx 目录、PDF 排版) | v1.2+ |
| §20.5 敏感词合规、预设内敏感词替换规则 | v1.2+ |
| §20.3 角色弧线简报 | v1.2+(图谱深化线) |
| §5.7 故事时间线、§5.8 连续阅读模式 | v1.2+ |
导入 .novel 包 |
v1.2+ |
| 平台 API 直连投稿 | 永久 YAGNI |
模板变量 {outlineItem} 自动关联当前章大纲 |
v1.1 留空字符串(无关联时);手动关联后续 |
2. 架构
2.1 进程模型
┌─────────────────────────────────────────────────────────────────────┐
│ 渲染进程 │
│ · TemplateQuickCreateModal / TemplateSettingsTab │
│ · ImportBookModal │
│ · ExportModal + SubmissionPresetSettingsTab │
│ · InspirationModal(增强:全局唤起、选书、无跳转) │
│ · chapter-template.ts / submission-formatter.ts(纯函数) │
└──────────────────────────────┬──────────────────────────────────────┘
│ IPC
┌────────────────────────────▼────────────────────────────────────────┐
│ 主进程 │
│ · ImportService(读文件、分章、创建书+卷+章批量写入) │
│ · ExportService(HTML→纯文本、应用投稿预设、写剪贴板/文件) │
│ · BookRegistryService(已有 create/open) │
│ · GlobalSettingsService(扩展 chapterTemplates / submissionPresets)│
│ · dialog.showOpenDialog / clipboard │
└─────────────────────────────────────────────────────────────────────┘
2.2 模块边界
| 模块 | 职责 | 依赖 |
|---|---|---|
chapter-template.ts |
变量替换、章节号计算 | GlobalSettings, 书籍 volumes/chapters/settings |
ImportService |
解析文件、分章、创建书 | BookRegistry, ChapterRepository, mammoth, marked |
ExportService |
单章格式化、剪贴板、存盘 | ChapterRepository, GlobalSettings |
SubmissionFormatter |
HTML 剥离、段首缩进、标题行 | 纯函数,主/渲染均可调用 |
TemplateQuickCreateModal |
选模板 → IPC 创建章 | chapter.create/update |
ImportBookModal |
选文件 → preview → execute | import.* |
ExportModal |
选预设 → 复制/存盘 | export.* |
原则:
- 导入/导出重 IO 与解析放主进程;模板变量替换可在渲染进程(减少 IPC 往返)
- 导入失败整事务回滚:书未创建或创建后写章失败则
registry.delete(bookId) - 剪贴板写入仅主进程(Electron
clipboardAPI)
3. 数据模型
3.1 GlobalSettings 扩展
export interface ChapterTemplate {
id: string
name: string
body: string
defaultStatus?: ChapterStatus
builtin?: boolean
}
export interface SubmissionPreset {
id: string
name: string
titleFormat: string // 默认 "# 第{chapterNumber}章 {chapterTitle}"
indentParagraphs: boolean // 段首两全角空格
includeAuthorsNote: boolean // 保留「作者的话」段(检测 —— 分隔)
paragraphGap: 'single' | 'double'
}
// GlobalSettings 追加:
chapterTemplates?: ChapterTemplate[]
submissionPresets?: SubmissionPreset[]
defaultSubmissionPresetId?: string
内置模板(src/shared/builtin-templates.ts,不写入 JSON):
| id | name | body 摘要 |
|---|---|---|
builtin-generic |
通用模板 | ## 第{chapterNumber}章 {chapterTitle}\n\n |
builtin-webnovel |
网文常用 | 正文 + \n\n——\n作者的话:\n |
内置投稿预设:
| id | name | 规则 |
|---|---|---|
builtin-webnovel |
通用网文 | titleFormat: "# 第{chapterNumber}章 {chapterTitle}", indentParagraphs: true, paragraphGap: 'double' |
GlobalSettingsService 读取时合并内置项;用户不可删除内置项。
3.2 模板变量
| 变量 | 来源 |
|---|---|
{chapterNumber} |
目标卷 chapters.length + 1 |
{chapterTitle} |
用户输入 |
{penName} |
settings.penName |
{date} |
localDateString() |
{volumeName} |
当前卷 name |
{previousChapterTitle} |
同卷上一章 title,首章 "" |
{outlineItem} |
v1.1 固定 ""(章节创建时无 outline 关联) |
{characterList} |
当前卷内 settings.type=character 且 chapterIds 与卷内任一章有交集的 name,逗号连接 |
3.3 导入分章
export type ImportSplitMode = 'auto' | 'paragraph' | 'regex'
export interface ImportChapterPreview {
title: string
contentHtml: string
wordCount: number
}
export interface ImportPreviewResult {
fileName: string
fileSizeBytes: number
chapters: ImportChapterPreview[]
warnings: string[]
}
export interface ImportExecuteParams {
filePath: string
bookName: string
category: string
splitMode: ImportSplitMode
customRegex?: string
}
自动分章正则(依次尝试,命中即用):
/^#\s*第.+章[^\n]*/gm(Markdown 标题)/^第[一二三四五六七八九十百千零〇\d]+章[^\n]*/gm(纯文本章标题行)
paragraph 模式:按 \n\s*\n 分段;标题取段首非空行,截断 50 字。
首章前导内容:合并入第一章 warnings 提示,不丢弃。
4. IPC
4.1 通道
IMPORT_PICK_FILE: 'import:pickFile'
IMPORT_PREVIEW: 'import:preview'
IMPORT_EXECUTE: 'import:execute'
IMPORT_PROGRESS: 'import:progress' // main → renderer event
EXPORT_FORMAT_CHAPTER: 'export:formatChapter'
EXPORT_COPY_CLIPBOARD: 'export:copyClipboard'
EXPORT_SAVE_TXT: 'export:saveTxt'
4.2 载荷
// import:pickFile → { canceled, filePath? }
// import:preview → { filePath, splitMode, customRegex? } → ImportPreviewResult
// import:execute → ImportExecuteParams → { bookId }
// import:progress → { phase: 'parsing'|'writing', current, total }
// export:formatChapter → { bookId, chapterId, presetId } → { text }
// export:copyClipboard → { text } → void
// export:saveTxt → { text, defaultName } → { savedPath? }
5. UI 规格
5.1 TemplateQuickCreateModal
- 入口:章节列表底部
data-testid="chapter-quick-new" - 布局:参考
#templateModal卡片网格 + 标题输入 - 流程:选模板 → 输入标题 → 创建 →
switchTarget到新章
5.2 设置页 — 章节模板 Tab
data-testid="settings-chapter-templates"- 列表:内置 + 自定义;自定义可编辑 body(textarea)、删除
- 新建:
setting-template-add
5.3 ImportBookModal
- 入口:主页
home.importBook(替换 comingSoon) data-testid="import-book-modal"- 字段:文件路径(浏览)、书名、分类、分章规则下拉、自定义正则输入(regex 模式显示)
- 预览区:章数 + 前 5 章标题列表
-
20MB:
import-large-file-confirm对话框 - 进度:
import-progress-bar
5.4 ExportModal
- 入口:编辑器工具栏
data-testid="export-chapter"+ 快捷键exportBook data-testid="export-modal"- 折叠区「投稿预设」:
export-preset-select - 操作:
export-copy-clipboard/export-save-txt - 预览:格式化后前 500 字纯文本
5.5 设置页 — 投稿预设 Tab
data-testid="settings-submission-presets"- 字段:名称、标题格式、段首缩进 checkbox、段落间距 select
5.6 InspirationModal 增强
App.tsx:captureInspiration移除view !== 'editor'限制- 未开书:显示
inspiration-book-select(书籍列表下拉,默认lastOpenedAt最新) - 保存后:删除
switchTarget+setSidebarPanel('inspiration');仅showToast+setOpen(false) - 样式:
inspiration-modal--capture提升 z-index(高于 TopBar)
6. 依赖
| 包 | 用途 |
|---|---|
mammoth |
docx → HTML |
marked |
md → HTML |
均在主进程 ImportService 使用;electron-vite 打包时 external 或 bundle 按现有惯例。
7. 测试
| 用例 ID | 层级 | 场景 | 预期 |
|---|---|---|---|
| UT-TEMPL-01 | 单元 | 解析含 {chapterNumber} {chapterTitle} |
正确替换 |
| UT-TEMPL-02 | 单元 | {volumeName} 替换 |
卷名正确 |
| UT-TEMPL-03 | 单元 | {characterList} 卷内角色 |
逗号列表 |
| IT-TEMPL-01 | 集成 | 模板快速新建写入 DB | content 含替换后正文 |
| UT-IMPORT-01 | 单元 | txt 自动分章 3 章 | chapters.length === 3 |
| UT-IMPORT-02 | 单元 | md 转 HTML | 含 <p> |
| UT-IMPORT-03 | 单元 | docx mammoth | 非空 HTML |
| IT-IMPORT-01 | 集成 | execute 创建书+章 | registry.open 章数匹配 |
| UT-EXPORT-01 | 单元 | 段首空两格 | 每段 前缀 |
| UT-EXPORT-02 | 单元 | 标题格式 | # 第1章 标题 |
| IT-EXPORT-01 | 集成 | copyClipboard | 剪贴板非空 |
| E2E-TEMPL-01 | E2E | 快速新建章 | 编辑器有模板内容 |
| E2E-IMPORT-01 | E2E | 导入 txt | 新书可见多章 |
| E2E-EXPORT-01 | E2E | 复制投稿格式 | 剪贴板含章标题 |
| E2E-INSP-01 | E2E | 主页 Ctrl+Shift+I 保存 | toast,不跳编辑器 |
8. i18n 键(节选)
"template.title": "章节模板",
"template.quickNew": "模板新建章",
"template.builtin": "内置",
"template.custom": "自定义",
"import.title": "导入书籍",
"import.pickFile": "浏览文件",
"import.splitAuto": "自动识别章节",
"import.splitParagraph": "双换行分段",
"import.splitRegex": "自定义正则",
"import.largeFileConfirm": "文件较大({{size}}),导入可能需要 30 秒至 2 分钟,是否继续?",
"import.progress": "正在导入 {{current}}/{{total}}",
"export.title": "导出章节",
"export.submissionPresets": "投稿预设",
"export.copyClipboard": "复制到剪贴板",
"export.saveTxt": "另存为文本",
"export.copied": "已复制到剪贴板",
"submission.title": "投稿预设",
"submission.titleFormat": "标题格式",
"submission.indent": "段首空两格",
"inspiration.selectBook": "关联书籍",
"inspiration.saved": "灵感已保存"
9. 文件清单
| 文件 | 职责 |
|---|---|
src/shared/types.ts |
ChapterTemplate, SubmissionPreset, Import/Export DTO |
src/shared/builtin-templates.ts |
内置模板与投稿预设 |
src/shared/ipc-channels.ts |
import.* / export.* |
src/main/services/import.service.ts |
解析 + 分章 + 创建书 |
src/main/services/export.service.ts |
格式化 + 剪贴板/存盘 |
src/main/lib/submission-formatter.ts |
HTML → 投稿纯文本 |
src/main/lib/chapter-splitter.ts |
分章逻辑 |
src/main/ipc/handlers/import.handler.ts |
导入 IPC |
src/main/ipc/handlers/export.handler.ts |
导出 IPC |
src/renderer/lib/chapter-template.ts |
模板变量替换 |
src/renderer/components/chapter/TemplateQuickCreateModal.tsx |
快速新建 |
src/renderer/components/import/ImportBookModal.tsx |
导入 UI |
src/renderer/components/export/ExportModal.tsx |
导出 UI |
src/renderer/components/settings/TemplateSettingsTab.tsx |
模板管理 |
src/renderer/components/settings/SubmissionPresetTab.tsx |
投稿预设管理 |
src/renderer/components/inspiration/InspirationModal.tsx |
增强 |
src/renderer/components/home/HomePage.tsx |
接入导入 |
src/renderer/components/layout/EditorLayout.tsx |
导出入口 |
tests/main/chapter-template.test.ts |
UT-TEMPL-* |
tests/main/chapter-splitter.test.ts |
UT-IMPORT-01 |
tests/main/submission-formatter.test.ts |
UT-EXPORT-* |
tests/main/import.service.test.ts |
IT-IMPORT-01 |
e2e/chapter-template.spec.ts |
E2E-TEMPL-01 |
e2e/import-book.spec.ts |
E2E-IMPORT-01 |
e2e/export-submission.spec.ts |
E2E-EXPORT-01 |
e2e/inspiration-capture.spec.ts |
E2E-INSP-01 |
10. 实现顺序建议
- 类型 + 内置常量 +
chapter-template.ts+ 快速新建 UI SubmissionFormatter+ ExportService + ExportModal + 设置 Tab- InspirationModal 增强(独立、改动小)
- ImportService + ImportBookModal(依赖 mammoth/marked,放最后)
目标版本号:实现完成后 package.json / README / 关于页 → v1.1.0
11. Spec 自检
| 检查项 | 状态 |
|---|---|
| 无 TBD/TODO 占位 | ✅ |
| 与方案 A 四模块一致 | ✅ |
.novel 明确排除 |
✅ |
| 单章投稿导出范围明确 | ✅ |
| IPC/数据模型无矛盾 | ✅ |
| 测试用例覆盖四模块 | ✅ |