docs: 添加笔临 P2 设计规格
覆盖大纲/设定/灵感持久化、引用面板、版本历史、全局搜索、地标、用词分析与 P2.0 主题修复;严格对齐 design/readme §5.3.9–§5.6。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,558 @@
|
|||||||
|
# 笔临 P2 设计规格
|
||||||
|
|
||||||
|
**版本**:1.0
|
||||||
|
**日期**:2026-07-06
|
||||||
|
**范围**:第二阶段——内容扩展、引用与检索、版本追溯、主题修复
|
||||||
|
**前置**:P0/P1 已交付(v0.1.0,`011bd6d`)
|
||||||
|
**参考**:`design/readme.md` v1.1 §5.3.9 / §5.4–§5.6 / §5.5、`design/ui_pc.html`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 背景与目标
|
||||||
|
|
||||||
|
### 1.1 阶段定位
|
||||||
|
|
||||||
|
P2 在 P1「纯写作闭环」之上,补齐长篇创作的信息管理能力:大纲/设定/灵感持久化、写作引用、全文检索、版本历史、地标待办、用词分析,并修复浅色主题控件不可见问题。
|
||||||
|
|
||||||
|
### 1.2 已确认决策(Brainstorming 2026-07-06)
|
||||||
|
|
||||||
|
| 维度 | 决策 |
|
||||||
|
|------|------|
|
||||||
|
| 范围 | **完整 P2** + 主题修复 |
|
||||||
|
| 对齐深度 | 严格对齐 `design/readme.md` §5.3.9 / §5.4–§5.6 / §5.5 |
|
||||||
|
| 编辑器 | **完全统一中央 TipTap**(章节/大纲/设定/灵感) |
|
||||||
|
| 搜索 | §5.6.1 全量;§5.6.3 用词分析实装;§5.6.2 AI 命名检查 **占位至 P3** |
|
||||||
|
| 地标 | §5.3.9 **全量** + 纳入全局搜索 |
|
||||||
|
| 主题 | **P2.0 先行**(~3 天),再进入功能开发 |
|
||||||
|
| 实现策略 | **方案 A**:分层基础 + 功能切片 |
|
||||||
|
| 平台 | Windows 优先(延续 P0/P1) |
|
||||||
|
|
||||||
|
### 1.3 P2 验收标准
|
||||||
|
|
||||||
|
用户能完成:
|
||||||
|
|
||||||
|
1. 在左栏四 Tab 中 CRUD 大纲/设定/灵感,并在中央编辑器统一编辑、自动保存、重启恢复
|
||||||
|
2. 打开引用面板,搜索/钉住/拖拽插入设定或大纲内容到正文
|
||||||
|
3. 使用全局搜索(含正则、替换预览)跨章节/大纲/设定/灵感/地标检索并跳转
|
||||||
|
4. 创建/浏览/对比/回滚章节版本历史(自动/手动/持久快照)
|
||||||
|
5. 插入/管理写作地标,通过清单或搜索跳转
|
||||||
|
6. 查看用词分析(高频词、过度用词高亮)并跳转编辑器定位
|
||||||
|
7. 切换 3 套浅色主题,所有关键页面文字清晰可读
|
||||||
|
|
||||||
|
### 1.4 本规格不实现(明确排除)
|
||||||
|
|
||||||
|
| 项 | 归属 |
|
||||||
|
|----|------|
|
||||||
|
| §5.6.2 AI 命名一致性检查 | P3(UI 占位) |
|
||||||
|
| §5.4.1 `ai` 类型快照业务触发 | P3(DB 字段预留) |
|
||||||
|
| 灵感语音输入 | P2.1 占位按钮 |
|
||||||
|
| `ai_sessions` / `knowledge_entries` / `timeline_events` 表 | P3/P5/P6 |
|
||||||
|
| 章节拖拽排序(同卷/跨卷) | P2.1(P2 先用按钮排序) |
|
||||||
|
| TipTap `@提及` 反向跳转 | P2.4 实现 Mention 扩展 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 架构
|
||||||
|
|
||||||
|
### 2.1 进程模型(延续 P0/P1)
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────┐
|
||||||
|
│ 主进程 │
|
||||||
|
│ · node:sqlite(每书 .sqlite,schema v2) │
|
||||||
|
│ · FTS5 虚拟表(search_fts) │
|
||||||
|
│ · SnapshotService(定时/退出快照) │
|
||||||
|
│ · SearchService / WordFreqService │
|
||||||
|
│ · IPC Handlers(IpcResult 信封) │
|
||||||
|
└───────────────────────────┬─────────────────────────────┘
|
||||||
|
│ contextBridge
|
||||||
|
┌───────────────────────────▼─────────────────────────────┐
|
||||||
|
│ 渲染进程 │
|
||||||
|
│ · useEditStore(EditTarget 统一编辑) │
|
||||||
|
│ · Zustand + Jotai(延续 P1) │
|
||||||
|
│ · TipTap(章节完整 / 其他简化模式) │
|
||||||
|
│ · 模态:搜索 / 版本 / 灵感捕获 / 地标清单 │
|
||||||
|
└─────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.2 统一编辑内核(EditSession)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
type EditTarget =
|
||||||
|
| { kind: 'chapter'; id: string }
|
||||||
|
| { kind: 'outline'; id: string }
|
||||||
|
| { kind: 'setting'; id: string }
|
||||||
|
| { kind: 'inspiration'; id: string }
|
||||||
|
```
|
||||||
|
|
||||||
|
**`useEditStore`(Zustand)职责**:
|
||||||
|
|
||||||
|
- 持有 `currentTarget: EditTarget | null`
|
||||||
|
- `switchTarget(next)`:flush 当前 → IPC get → 更新 TipTap 内容与 cursor
|
||||||
|
- 与 `useBookStore.selectedChapterId` 协同:选中章节时 `kind='chapter'`
|
||||||
|
|
||||||
|
**Jotai atoms**(延续并扩展):
|
||||||
|
|
||||||
|
- `editorDirtyAtom` / `editorSavingAtom` / `lastSavedAtAtom` — 所有 target 共用
|
||||||
|
- `wordCountAtom` — 章节时显示卷/章/全书;其他 target 仅条目字数
|
||||||
|
|
||||||
|
**自动保存**:debounce 2s(与 P1 一致);切换 target / 关闭 Tab 前 `flushEditorSave()`
|
||||||
|
|
||||||
|
### 2.3 里程碑
|
||||||
|
|
||||||
|
| 阶段 | 交付 | 周期 |
|
||||||
|
|------|------|------|
|
||||||
|
| **P2.0** | 主题 token 补全、消除硬编码色值、对比度 E2E | ~3 天 |
|
||||||
|
| **P2.1** | schema-v2 迁移、Repository、IPC 扩展 | ~4 天 |
|
||||||
|
| **P2.2** | EditSession + 左栏四 Tab CRUD + 统一编辑 | ~5 天 |
|
||||||
|
| **P2.3** | 大纲对照视图、覆盖度标记/筛选 | ~4 天 |
|
||||||
|
| **P2.4** | 引用面板(Tab/钉住/拖拽/Mention) | ~4 天 |
|
||||||
|
| **P2.5** | 版本历史(快照/diff/回滚) | ~5 天 |
|
||||||
|
| **P2.6** | 全局搜索 FTS5 + 替换 + 地标全量 | ~5 天 |
|
||||||
|
| **P2.7** | 用词分析 + §5.6.2 占位 | ~3 天 |
|
||||||
|
|
||||||
|
**目标版本**:v0.2.0
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 数据模型
|
||||||
|
|
||||||
|
### 3.1 Schema v2 迁移
|
||||||
|
|
||||||
|
`schema_version` 1 → 2。新安装书籍直接应用 v1+v2;已有书籍运行 `migrate.ts` 增量 ALTER。
|
||||||
|
|
||||||
|
**chapters 扩展**:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
ALTER TABLE chapters ADD COLUMN publish_status TEXT NOT NULL DEFAULT 'draft';
|
||||||
|
ALTER TABLE chapters ADD COLUMN pov_character_id TEXT DEFAULT NULL;
|
||||||
|
ALTER TABLE chapters ADD COLUMN summary TEXT DEFAULT '';
|
||||||
|
ALTER TABLE chapters ADD COLUMN story_time TEXT DEFAULT NULL;
|
||||||
|
-- pov_character_id FK → settings(id) 在 v2 表创建后添加
|
||||||
|
```
|
||||||
|
|
||||||
|
**新增表**(对齐 design §19):
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE TABLE outline_items (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
parent_id TEXT,
|
||||||
|
title TEXT NOT NULL,
|
||||||
|
description TEXT DEFAULT '',
|
||||||
|
status TEXT NOT NULL DEFAULT 'pending',
|
||||||
|
expected_word_count INTEGER DEFAULT NULL,
|
||||||
|
chapter_id TEXT,
|
||||||
|
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_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,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
description TEXT DEFAULT '',
|
||||||
|
properties TEXT DEFAULT '{}',
|
||||||
|
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 '[]',
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE snapshots (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
chapter_id TEXT NOT NULL,
|
||||||
|
type TEXT NOT NULL,
|
||||||
|
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 bookmarks (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
chapter_id TEXT NOT NULL,
|
||||||
|
position INTEGER NOT NULL,
|
||||||
|
label TEXT NOT NULL,
|
||||||
|
landmark_type TEXT NOT NULL DEFAULT 'todo',
|
||||||
|
resolved INTEGER NOT NULL DEFAULT 0,
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
FOREIGN KEY (chapter_id) REFERENCES chapters(id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
**FTS5**(每书 DB):
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE VIRTUAL TABLE search_fts USING fts5(
|
||||||
|
source_kind,
|
||||||
|
source_id,
|
||||||
|
title,
|
||||||
|
body,
|
||||||
|
tokenize='unicode61'
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
触发器:chapters / outline_items / settings / inspiration / bookmarks 的 INSERT/UPDATE/DELETE 同步 `search_fts`。迁移完成后执行一次 `rebuildFts(bookId)`。
|
||||||
|
|
||||||
|
### 3.2 枚举值
|
||||||
|
|
||||||
|
| 字段 | 值 |
|
||||||
|
|------|-----|
|
||||||
|
| `outline_items.status` | `pending` / `writing` / `done` / `abandoned` |
|
||||||
|
| `settings.type` | `character` / `location` / `item` / `skill` / `faction` / `custom` |
|
||||||
|
| `snapshots.type` | `auto` / `manual` / `persist` / `ai` |
|
||||||
|
| `bookmarks.landmark_type` | `todo` / `foreshadow` / `research` / `custom` |
|
||||||
|
| `chapters.publish_status` | `draft` / `ready` / `published` |
|
||||||
|
|
||||||
|
### 3.3 global_settings.json 扩展
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface GlobalSettings {
|
||||||
|
// ...P0/P1 字段
|
||||||
|
snapshotIntervalMs: number // 默认 300000(5 分钟)
|
||||||
|
snapshotMaxAuto: number // 默认 20
|
||||||
|
snapshotMaxPersist: number // 默认 3
|
||||||
|
searchHistory: string[] // 最近 10 条
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. IPC 契约
|
||||||
|
|
||||||
|
所有通道返回 `IpcResult<T>`。参数 camelCase,Repository 映射 snake_case。
|
||||||
|
|
||||||
|
### 4.1 新增通道
|
||||||
|
|
||||||
|
| 通道 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| `outline:list` | `{ bookId }` → `OutlineItem[]`(树形扁平化或嵌套) |
|
||||||
|
| `outline:create` | `{ bookId, parentId?, title, sortOrder }` |
|
||||||
|
| `outline:update` | `{ bookId, id, patch }` |
|
||||||
|
| `outline:delete` | `{ bookId, id }`(级联子节点) |
|
||||||
|
| `outline:move` | `{ bookId, id, parentId?, sortOrder }` |
|
||||||
|
| `setting:list` | `{ bookId, type? }` |
|
||||||
|
| `setting:create` | `{ bookId, type, name }` |
|
||||||
|
| `setting:update` | `{ bookId, id, patch }` |
|
||||||
|
| `setting:delete` | `{ bookId, id }` |
|
||||||
|
| `setting:syncRefs` | `{ bookId, id, chapterIds[] }` |
|
||||||
|
| `inspiration:list` | `{ bookId }` |
|
||||||
|
| `inspiration:create` | `{ bookId, title?, content?, tags? }` |
|
||||||
|
| `inspiration:update` | `{ bookId, id, patch }` |
|
||||||
|
| `inspiration:delete` | `{ bookId, id }` |
|
||||||
|
| `inspiration:convert` | `{ bookId, id, targetKind: 'outline' \| 'setting' }` |
|
||||||
|
| `snapshot:list` | `{ bookId, chapterId }` |
|
||||||
|
| `snapshot:create` | `{ bookId, chapterId, type, name? }` |
|
||||||
|
| `snapshot:restore` | `{ bookId, chapterId, snapshotId }` |
|
||||||
|
| `snapshot:delete` | `{ bookId, snapshotId }` |
|
||||||
|
| `bookmark:list` | `{ bookId, chapterId?, resolved? }` |
|
||||||
|
| `bookmark:create` | `{ bookId, chapterId, position, label, landmarkType }` |
|
||||||
|
| `bookmark:update` | `{ bookId, id, patch }` |
|
||||||
|
| `bookmark:resolve` | `{ bookId, id, resolved: boolean }` |
|
||||||
|
| `bookmark:delete` | `{ bookId, id }` |
|
||||||
|
| `search:query` | `{ bookId, query, scope, options }` → `SearchResult[]` |
|
||||||
|
| `search:replace` | `{ bookId, query, replacement, scope, dryRun }` |
|
||||||
|
| `search:getHistory` / `search:saveHistory` | 读写 global_settings.searchHistory |
|
||||||
|
| `wordfreq:analyze` | `{ bookId, scope }` → `{ words: { token, count }[] }` |
|
||||||
|
|
||||||
|
### 4.2 主进程服务
|
||||||
|
|
||||||
|
| 服务 | 职责 |
|
||||||
|
|------|------|
|
||||||
|
| `SnapshotService` | 定时 auto 快照、Ctrl+S/退出 persist 快照、FIFO 淘汰 |
|
||||||
|
| `SearchService` | FTS5 查询;regex 模式 fallback 到 JS 扫描 |
|
||||||
|
| `WordFreqService` | HTML→plainText,CJK 单字 + 拉丁词分词,Top N 统计 |
|
||||||
|
| `FtsSyncService` | CRUD 后增量同步;`rebuildFts` 全量重建 |
|
||||||
|
|
||||||
|
### 4.3 book:open 响应扩展
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface BookOpenResult {
|
||||||
|
meta: BookMeta
|
||||||
|
volumes: Volume[]
|
||||||
|
chapters: Chapter[]
|
||||||
|
outlines: OutlineItem[] // 新增
|
||||||
|
settings: SettingEntry[] // 新增
|
||||||
|
inspirations: InspirationEntry[] // 新增
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. UI 规格
|
||||||
|
|
||||||
|
### 5.1 左栏四 Tab
|
||||||
|
|
||||||
|
| Tab | 组件 | P2 行为 |
|
||||||
|
|-----|------|---------|
|
||||||
|
| 章节 | `ChapterTree` | 双击改标题(已有);status badge |
|
||||||
|
| 大纲 | `OutlineTree` | 无限层级;新建/删除;覆盖度橙色边框;筛选下拉 |
|
||||||
|
| 设定 | `SettingList` | 按 type 分组折叠;新建 |
|
||||||
|
| 灵感 | `InspirationList` | 列表 + 底部新建 |
|
||||||
|
|
||||||
|
各 Tab 底部「+ 新建」;选中条目 → `useEditStore.switchTarget`。
|
||||||
|
|
||||||
|
**大纲覆盖度**(§5.5.2):
|
||||||
|
|
||||||
|
- 无 `chapter_id` 关联 → 橙色左边框 + ⚠ 图标
|
||||||
|
- 筛选:全部 / 未覆盖 / 已覆盖
|
||||||
|
- Tooltip:预期字数 vs 关联章节实际字数,偏差 >20% 标红
|
||||||
|
|
||||||
|
### 5.2 中央编辑器
|
||||||
|
|
||||||
|
| 元素 | 规格 |
|
||||||
|
|------|------|
|
||||||
|
| `DocumentTitle` | 双击 inline 编辑;Enter 确认 / Esc 取消 |
|
||||||
|
| `EditorToolbar` | 加粗/斜体/下划线;引用按钮;版本历史;插入地标 |
|
||||||
|
| `TipTapEditor` | chapter=StarterKit+Underline;其他=simplified(Paragraph+Bold+Italic+Placeholder) |
|
||||||
|
| `StatusBar` | 保存状态 + 字数(章节三维 / 其他单维) |
|
||||||
|
| 粘贴 | 纯文本插入(Shift 保留格式,延续 P1) |
|
||||||
|
|
||||||
|
### 5.3 引用面板(§5.3.8)
|
||||||
|
|
||||||
|
- DOM:`#reference-panel`,宽 240px,`.open` 切换
|
||||||
|
- 与 AI 右栏互斥
|
||||||
|
- Tab:设定 / 大纲 / 灵感;顶部搜索框
|
||||||
|
- 列表项:名称 + 摘要前 40 字;点击展开详情
|
||||||
|
- 钉住 checkbox:切换章节时保持选中条目
|
||||||
|
- 拖拽:插入 plainText 到光标
|
||||||
|
- Mention(P2.4):`@设定名` 高亮,点击跳转设定 EditTarget
|
||||||
|
|
||||||
|
### 5.4 模态层
|
||||||
|
|
||||||
|
| ID | 快捷键 | 功能 |
|
||||||
|
|----|--------|------|
|
||||||
|
| `#searchModal` | Ctrl+Shift+F | 搜索 + 范围 + 高级选项 + 替换预览 |
|
||||||
|
| `#versionModal` | 工具栏 | 版本列表 + diff 双栏 + 回滚 |
|
||||||
|
| `#inspirationModal` | Ctrl+Shift+I | 快速捕获(语音按钮占位) |
|
||||||
|
| `#landmarksModal` | Ctrl+Shift+L | 地标清单,按类型/章节分组 |
|
||||||
|
|
||||||
|
搜索结果:按类型分组;↑↓ 选择 + Enter 跳转;上下文前后 20 字。
|
||||||
|
|
||||||
|
### 5.5 大纲对照视图(§5.5.6)
|
||||||
|
|
||||||
|
- 入口:大纲 Tab「对照模式」
|
||||||
|
- 分屏:左 35% 大纲树,右 65% 关联章节正文(只读)
|
||||||
|
- 底部对比条:预期 vs 实际 vs 偏差%
|
||||||
|
- 无关联:「尚未写作」占位
|
||||||
|
|
||||||
|
### 5.6 版本历史(§5.4)
|
||||||
|
|
||||||
|
| 类型 | 触发 | 上限 |
|
||||||
|
|------|------|------|
|
||||||
|
| auto | 定时(默认 5min)且内容变更 | 20,FIFO |
|
||||||
|
| manual | 用户「创建快照」 | 无上限 |
|
||||||
|
| persist | Ctrl+S / app quit | 3,轮替 |
|
||||||
|
| ai | 预留 | P3 |
|
||||||
|
|
||||||
|
- Diff:`diff-match-patch` 行级对比;绿新增/红删除/黄修改
|
||||||
|
- 回滚:restore 前自动 manual 备份
|
||||||
|
- 列表:版本号、时间、类型、摘要(manual 名称)
|
||||||
|
|
||||||
|
### 5.7 地标(§5.3.9)
|
||||||
|
|
||||||
|
- 插入:编辑器右键 / 工具栏 / Ctrl+Shift+M
|
||||||
|
- 正文行内标记:`[TODO: ...]` 样式(TipTap Mark 或 inline Node)
|
||||||
|
- 不进入导出正文(export 逻辑留 P7,P2 仅存储)
|
||||||
|
- 清单模态:按类型/章节分组;点击跳转章节+position
|
||||||
|
- 完成:勾选 resolved,可选归档
|
||||||
|
|
||||||
|
### 5.8 用词分析(§5.6.3)
|
||||||
|
|
||||||
|
- 入口:右栏「用词」Tab(原占位 → 实装)
|
||||||
|
- 高频词 Top 100,频次降序
|
||||||
|
- 点击词条 → 编辑器跳转并高亮所有出现
|
||||||
|
- 过度用词:每千字 >5 次的非功能词,编辑器淡黄色 Mark
|
||||||
|
- §5.6.2 命名一致性:同面板底部「即将推出(需 AI)」
|
||||||
|
|
||||||
|
### 5.9 主题修复(P2.0)
|
||||||
|
|
||||||
|
**问题根因**:浅色主题 CSS 变量不完整;多处硬编码 `#fff`(含 `ui_pc.html` 移植残留)。
|
||||||
|
|
||||||
|
**修复项**:
|
||||||
|
|
||||||
|
1. 补全 `ricepaper` / `mist` / `teagarden` 全部 token(`--bg-surface`、`--text-dim`、`--accent-glow`、`--border-light` 等)
|
||||||
|
2. 新增语义 token:
|
||||||
|
- `--text-on-accent`:主按钮/激活 Tab 上的文字
|
||||||
|
- `--input-text` / `--input-bg`:表单控件
|
||||||
|
3. 替换 `layout.css`、组件内联 style 中 `color: #fff` → 语义 token
|
||||||
|
4. `select` / `option` / `input` 统一使用 `--input-*` token
|
||||||
|
|
||||||
|
**验收 E2E**(`e2e/themes-contrast.spec.ts`):
|
||||||
|
|
||||||
|
- 主题:`ricepaper`、`mist`、`teagarden`
|
||||||
|
- 页面:主页、编辑器、设置、搜索模态、引用面板
|
||||||
|
- 断言:关键文字元素 `color` 与 `background` 对比度 ≥ 4.5:1(WCAG AA)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 状态管理
|
||||||
|
|
||||||
|
### 6.1 新增 Stores
|
||||||
|
|
||||||
|
| Store | 职责 |
|
||||||
|
|-------|------|
|
||||||
|
| `useEditStore` | EditTarget 切换、flush、load |
|
||||||
|
| `useOutlineStore` | 大纲树、筛选、对照模式 |
|
||||||
|
| `useReferenceStore` | 引用面板 open/pin/activeTab/selectedItem |
|
||||||
|
| `useSearchStore` | 搜索模态、query、results、replacePreview |
|
||||||
|
|
||||||
|
`useBookStore` 扩展:缓存 outlines/settings/inspirations;`openBook` 一次性加载。
|
||||||
|
|
||||||
|
### 6.2 快捷键绑定(P2 实装)
|
||||||
|
|
||||||
|
| 动作 | 默认 | P2 行为 |
|
||||||
|
|------|------|---------|
|
||||||
|
| globalSearch | Ctrl+Shift+F | 打开搜索模态 |
|
||||||
|
| openReference | Ctrl+Shift+P | 切换引用面板 |
|
||||||
|
| insertLandmark | Ctrl+Shift+M | 插入地标 |
|
||||||
|
| openLandmarks | Ctrl+Shift+L | 地标清单 |
|
||||||
|
| captureInspiration | Ctrl+Shift+I | 灵感捕获模态 |
|
||||||
|
| saveChapter | Ctrl+S | 保存 + 创建 persist 快照 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. 测试策略
|
||||||
|
|
||||||
|
### 7.1 单元/集成(Vitest)
|
||||||
|
|
||||||
|
| 模块 | 用例 |
|
||||||
|
|------|------|
|
||||||
|
| `outline.repo` | CRUD、层级、move、覆盖度查询 |
|
||||||
|
| `setting.repo` | CRUD、chapterRefs 同步 |
|
||||||
|
| `inspiration.repo` | CRUD、convert |
|
||||||
|
| `snapshot.repo` | 创建、FIFO 淘汰、restore |
|
||||||
|
| `bookmark.repo` | CRUD、resolve |
|
||||||
|
| `search.service` | FTS 索引、query、replace dryRun |
|
||||||
|
| `wordfreq.service` | CJK/拉丁分词、Top N |
|
||||||
|
| `migrate v1→v2` | 旧库升级后数据完整 |
|
||||||
|
|
||||||
|
### 7.2 E2E(Playwright)
|
||||||
|
|
||||||
|
| ID | 场景 |
|
||||||
|
|----|------|
|
||||||
|
| E2E-P2-OUTLINE-01 | 创建层级大纲 → 重启 → 树结构保留 |
|
||||||
|
| E2E-P2-EDIT-01 | 切换章节→大纲→设定,内容互不覆盖 |
|
||||||
|
| E2E-P2-REF-01 | 引用面板拖拽设定到正文 |
|
||||||
|
| E2E-P2-SEARCH-01 | 全局搜索跨类型 → Enter 跳转 |
|
||||||
|
| E2E-P2-SNAP-01 | 编辑 → 手动快照 → diff → 回滚 |
|
||||||
|
| E2E-P2-LAND-01 | 插入地标 → 清单可见 → 跳转 |
|
||||||
|
| E2E-P2-WORD-01 | 用词分析 Top 词 → 点击跳转高亮 |
|
||||||
|
| E2E-THEME-01 | 3 浅色主题关键页面文字可见 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. 目录结构增量
|
||||||
|
|
||||||
|
```
|
||||||
|
src/main/
|
||||||
|
├── db/
|
||||||
|
│ ├── schema-v2.sql
|
||||||
|
│ ├── migrations/migrate-v2.ts
|
||||||
|
│ └── repositories/
|
||||||
|
│ ├── outline.repo.ts
|
||||||
|
│ ├── setting.repo.ts
|
||||||
|
│ ├── inspiration.repo.ts
|
||||||
|
│ ├── snapshot.repo.ts
|
||||||
|
│ └── bookmark.repo.ts
|
||||||
|
├── services/
|
||||||
|
│ ├── snapshot.service.ts
|
||||||
|
│ ├── search.service.ts
|
||||||
|
│ ├── fts-sync.service.ts
|
||||||
|
│ └── wordfreq.service.ts
|
||||||
|
└── ipc/handlers/
|
||||||
|
├── outline.handler.ts
|
||||||
|
├── setting.handler.ts
|
||||||
|
├── inspiration.handler.ts
|
||||||
|
├── snapshot.handler.ts
|
||||||
|
├── bookmark.handler.ts
|
||||||
|
├── search.handler.ts
|
||||||
|
└── wordfreq.handler.ts
|
||||||
|
|
||||||
|
src/renderer/
|
||||||
|
├── stores/useEditStore.ts
|
||||||
|
├── stores/useOutlineStore.ts
|
||||||
|
├── stores/useReferenceStore.ts
|
||||||
|
├── stores/useSearchStore.ts
|
||||||
|
├── components/
|
||||||
|
│ ├── outline/OutlineTree.tsx
|
||||||
|
│ ├── outline/OutlineCompareView.tsx
|
||||||
|
│ ├── setting/SettingList.tsx
|
||||||
|
│ ├── inspiration/InspirationList.tsx
|
||||||
|
│ ├── reference/ReferencePanel.tsx
|
||||||
|
│ ├── search/SearchModal.tsx
|
||||||
|
│ ├── version/VersionModal.tsx
|
||||||
|
│ ├── landmark/LandmarkModal.tsx
|
||||||
|
│ ├── landmark/LandmarkMark.ts
|
||||||
|
│ └── wordfreq/WordFreqPanel.tsx
|
||||||
|
└── extensions/mention.ts
|
||||||
|
|
||||||
|
e2e/
|
||||||
|
├── themes-contrast.spec.ts
|
||||||
|
├── outline.spec.ts
|
||||||
|
├── search.spec.ts
|
||||||
|
├── snapshot.spec.ts
|
||||||
|
└── landmarks.spec.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. 风险与缓解
|
||||||
|
|
||||||
|
| 风险 | 缓解 |
|
||||||
|
|------|------|
|
||||||
|
| FTS5 在 node:sqlite 不可用 | 启动时检测;fallback JS 全表扫描(性能可接受于单书规模) |
|
||||||
|
| 统一 EditTarget 切换丢数据 | flush 强制 await;E2E 覆盖切换序列 |
|
||||||
|
| 版本 diff 大章节性能 | plainText diff;>100KB 时警告并限制词级粒度 |
|
||||||
|
| P2 范围大、工期膨胀 | 严格按 P2.0–P2.7 里程碑交付;每阶段 E2E 门禁 |
|
||||||
|
| 浅色主题回归 | P2.0 建立 token 规范 + contrast E2E 纳入 CI |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. Definition of Done(v0.2.0)
|
||||||
|
|
||||||
|
- [ ] P2.0–P2.7 全部里程碑完成
|
||||||
|
- [ ] §7 测试全部 PASS
|
||||||
|
- [ ] 3 套浅色主题 contrast E2E PASS
|
||||||
|
- [ ] §5.6.2 AI 命名检查为占位 Toast,不 crash
|
||||||
|
- [ ] `npm run build` 无 error
|
||||||
|
- [ ] Windows 手动验收:§1.3 七项流程
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Spec Self-Review
|
||||||
|
|
||||||
|
| 检查项 | 结果 |
|
||||||
|
|--------|------|
|
||||||
|
| Placeholder 扫描 | §5.6.2 / 语音 / ai 快照 均明确标注归属,无 TBD |
|
||||||
|
| 内部一致性 | EditTarget 统一编辑贯穿 IPC/UI/测试;FTS 与五类 source 对齐 |
|
||||||
|
| 范围 | 单规格可支撑一份 implementation plan;章节拖拽明确 P2.1 |
|
||||||
|
| 歧义 | snapshot 类型 `persist` vs design「退出/手动保存版本」已映射;status 枚举与 design §19 对齐 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 附录:与 P0/P1 规格差异
|
||||||
|
|
||||||
|
| 项 | P0/P1 规格 | 当前/P2 规格 |
|
||||||
|
|----|-----------|-------------|
|
||||||
|
| 数据库 | better-sqlite3 | **node:sqlite**(已迁移) |
|
||||||
|
| P5 地标 | 原归 P5 | **P2 全量**(用户确认) |
|
||||||
|
| P6 用词分析 | 原归 P6 | **P2 实装**(用户确认) |
|
||||||
Reference in New Issue
Block a user