feat: ship v1.1.0 writer toolkit with templates, import, export, and inspiration capture

Implement chapter templates, txt/md/docx import, submission export presets, and global inspiration shortcut. Split import handlers into a separate main bundle and fix EditorLayout setTarget loop that broke E2E.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-08 13:53:22 +08:00
parent ea4819847f
commit adf877861d
49 changed files with 2450 additions and 87 deletions
@@ -1,6 +1,6 @@
# 笔临 v1.1 作家日更工具包 Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [x]`) syntax for tracking.
**Goal:** 交付 v1.1.0:§10 章节模板 + 快速新建、§11.1 txt/md/docx 导入、§20.2 投稿预设单章导出、§20.6 全局灵感捕获增强。
@@ -60,7 +60,7 @@
- Modify: `src/main/services/global-settings.ts`
- Modify: `src/renderer/stores/useSettingsStore.ts`
- [ ] **Step 1: 扩展 types**
- [x] **Step 1: 扩展 types**
```typescript
export interface ChapterTemplate {
@@ -109,7 +109,7 @@ submissionPresets?: SubmissionPreset[]
defaultSubmissionPresetId?: string
```
- [ ] **Step 2: builtin-templates.ts**
- [x] **Step 2: builtin-templates.ts**
```typescript
import type { ChapterTemplate, SubmissionPreset } from './types'
@@ -149,13 +149,13 @@ export function mergeSubmissionPresets(custom: SubmissionPreset[] = []): Submiss
}
```
- [ ] **Step 3: global-settings defaults**
- [x] **Step 3: global-settings defaults**
`defaults()` 追加 `chapterTemplates: []`, `submissionPresets: []`, `defaultSubmissionPresetId: 'builtin-webnovel'`
- [ ] **Step 4: useSettingsStore 初始字段对齐**
- [x] **Step 4: useSettingsStore 初始字段对齐**
- [ ] **Step 5: build**
- [x] **Step 5: build**
```bash
npm run build
@@ -169,7 +169,7 @@ npm run build
- Create: `src/renderer/lib/chapter-template.ts`
- Create: `tests/main/chapter-template.test.ts`
- [ ] **Step 1: 实现 replaceChapterTemplate**
- [x] **Step 1: 实现 replaceChapterTemplate**
```typescript
export interface TemplateContext {
@@ -204,7 +204,7 @@ export function plainTextToEditorHtml(text: string): string {
}
```
- [ ] **Step 2: UT-TEMPL-01~03**
- [x] **Step 2: UT-TEMPL-01~03**
```typescript
it('UT-TEMPL-01: replaces chapterNumber and chapterTitle', () => {
@@ -217,7 +217,7 @@ it('UT-TEMPL-01: replaces chapterNumber and chapterTitle', () => {
})
```
- [ ] **Step 3: 运行**
- [x] **Step 3: 运行**
```bash
npm run test -- tests/main/chapter-template.test.ts
@@ -231,7 +231,7 @@ npm run test -- tests/main/chapter-template.test.ts
- Create: `src/renderer/components/chapter/TemplateQuickCreateModal.tsx`
- Modify: `src/renderer/components/layout/EditorLayout.tsx`
- [ ] **Step 1: TemplateQuickCreateModal**
- [x] **Step 1: TemplateQuickCreateModal**
- `data-testid="chapter-quick-new"` 打开模态
-`useSettingsStore` + `mergeChapterTemplates` 展示模板卡片
@@ -239,11 +239,11 @@ npm run test -- tests/main/chapter-template.test.ts
- 若模板 `defaultStatus` 设置则 `chapter.update({ status })`
- `switchTarget` 到新章
- [ ] **Step 2: EditorLayout**
- [x] **Step 2: EditorLayout**
在章节面板底部保留原「+ 新章」按钮,新增「模板新建」按钮 `data-testid="chapter-quick-new"`
- [ ] **Step 3: build**
- [x] **Step 3: build**
```bash
npm run build
@@ -257,18 +257,18 @@ npm run build
- Create: `src/renderer/components/settings/TemplateSettingsTab.tsx`
- Modify: `src/renderer/components/settings/SettingsPage.tsx`
- [ ] **Step 1: TemplateSettingsTab**
- [x] **Step 1: TemplateSettingsTab**
- `data-testid="settings-chapter-templates"`
- 内置模板只读展示
- 自定义:`setting-template-add` 新建;编辑 name/body;删除(uuid id
- 保存:`settings.update({ chapterTemplates: customOnly })`
- [ ] **Step 2: SettingsPage 导航**
- [x] **Step 2: SettingsPage 导航**
新增 section `'templates'`,侧栏项 `settings.templates`
- [ ] **Step 3: build**
- [x] **Step 3: build**
```bash
npm run build
@@ -282,7 +282,7 @@ npm run build
- Create: `src/main/lib/submission-formatter.ts`
- Create: `tests/main/submission-formatter.test.ts`
- [ ] **Step 1: 实现**
- [x] **Step 1: 实现**
```typescript
import { stripHtml } from '../services/word-count'
@@ -312,9 +312,9 @@ export function formatChapterForSubmission(input: FormatChapterInput): string {
}
```
- [ ] **Step 2: UT-EXPORT-01 / UT-EXPORT-02**
- [x] **Step 2: UT-EXPORT-01 / UT-EXPORT-02**
- [ ] **Step 3: 运行**
- [x] **Step 3: 运行**
```bash
npm run test -- tests/main/submission-formatter.test.ts
@@ -332,7 +332,7 @@ npm run test -- tests/main/submission-formatter.test.ts
- Modify: `src/preload/index.ts`
- Modify: `src/shared/electron-api.d.ts`
- [ ] **Step 1: ExportService**
- [x] **Step 1: ExportService**
```typescript
export class ExportService {
@@ -371,7 +371,7 @@ export class ExportService {
}
```
- [ ] **Step 2: export.handler + register + preload**
- [x] **Step 2: export.handler + register + preload**
```typescript
EXPORT_FORMAT_CHAPTER: 'export:formatChapter',
@@ -379,7 +379,7 @@ EXPORT_COPY_CLIPBOARD: 'export:copyClipboard',
EXPORT_SAVE_TXT: 'export:saveTxt',
```
- [ ] **Step 3: build**
- [x] **Step 3: build**
```bash
npm run build
@@ -396,19 +396,19 @@ npm run build
- Modify: `src/renderer/components/layout/EditorLayout.tsx`
- Modify: `src/renderer/App.tsx`
- [ ] **Step 1: ExportModal**
- [x] **Step 1: ExportModal**
- `data-testid="export-modal"`
- `export-preset-select` 下拉(mergeSubmissionPresets
- 预览区:调用 `export.formatChapter` 显示前 500 字
- `export-copy-clipboard` / `export-save-txt`
- [ ] **Step 2: SubmissionPresetTab**
- [x] **Step 2: SubmissionPresetTab**
- `data-testid="settings-submission-presets"`
- CRUD 自定义预设(不可删 builtin-webnovel
- [ ] **Step 3: EditorLayout 工具栏 + App exportBook 快捷键**
- [x] **Step 3: EditorLayout 工具栏 + App exportBook 快捷键**
```typescript
if (action === 'exportBook') {
@@ -420,7 +420,7 @@ if (action === 'exportBook') {
创建 `useExportStore`open/close,类似 useGraphStore)。
- [ ] **Step 4: build**
- [x] **Step 4: build**
```bash
npm run build
@@ -435,7 +435,7 @@ npm run build
- Modify: `src/renderer/App.tsx`
- Modify: `src/renderer/styles/layout.css`
- [ ] **Step 1: App.tsx 移除 view 限制**
- [x] **Step 1: App.tsx 移除 view 限制**
```typescript
if (action === 'captureInspiration') {
@@ -444,13 +444,13 @@ if (action === 'captureInspiration') {
}
```
- [ ] **Step 2: InspirationModal**
- [x] **Step 2: InspirationModal**
-`bookId` 时显示 `inspiration-book-select``useBookStore.books``lastOpenedAt` 排序)
- `handleSave` 删除 `switchTarget` / `setSidebarPanel`;改为 `showToast(t('inspiration.saved'))`
- 添加 `inspiration-modal--capture` class
- [ ] **Step 3: E2E 预备 build**
- [x] **Step 3: E2E 预备 build**
```bash
npm run build
@@ -464,7 +464,7 @@ npm run build
- Create: `src/main/lib/chapter-splitter.ts`
- Create: `tests/main/chapter-splitter.test.ts`
- [ ] **Step 1: splitPlainText**
- [x] **Step 1: splitPlainText**
```typescript
export function splitPlainText(
@@ -478,9 +478,9 @@ export function splitPlainText(
}
```
- [ ] **Step 2: UT-IMPORT-01** — 样本文本 3 章标题
- [x] **Step 2: UT-IMPORT-01** — 样本文本 3 章标题
- [ ] **Step 3: 运行**
- [x] **Step 3: 运行**
```bash
npm run test -- tests/main/chapter-splitter.test.ts
@@ -498,14 +498,14 @@ npm run test -- tests/main/chapter-splitter.test.ts
- Modify: `src/preload/index.ts`
- Create: `tests/main/import.service.test.ts`
- [ ] **Step 1: 安装依赖**
- [x] **Step 1: 安装依赖**
```bash
npm install mammoth marked --legacy-peer-deps
npm install -D @types/marked --legacy-peer-deps
```
- [ ] **Step 2: ImportService**
- [x] **Step 2: ImportService**
```typescript
export class ImportService {
@@ -543,14 +543,14 @@ export class ImportService {
}
```
- [ ] **Step 3: import.handler**
- [x] **Step 3: import.handler**
- `IMPORT_PICK_FILE` / `IMPORT_PREVIEW` / `IMPORT_EXECUTE`
- progress`BrowserWindow.getAllWindows()[0]?.webContents.send(IPC.IMPORT_PROGRESS, { current, total })`
- [ ] **Step 4: IT-IMPORT-01**
- [x] **Step 4: IT-IMPORT-01**
- [ ] **Step 5: 运行**
- [x] **Step 5: 运行**
```bash
npm run test -- tests/main/import.service.test.ts
@@ -565,7 +565,7 @@ npm run test -- tests/main/import.service.test.ts
- Modify: `src/renderer/components/home/HomePage.tsx`
- Modify: `src/renderer/App.tsx`(挂载 ImportBookModal
- [ ] **Step 1: ImportBookModal**
- [x] **Step 1: ImportBookModal**
- `data-testid="import-book-modal"`
- 浏览 → `import.pickFile`
@@ -575,13 +575,13 @@ npm run test -- tests/main/import.service.test.ts
- 执行 → 监听 `onImportProgress``import-progress-bar`
- 成功 → `openBook(bookId)` + 切 editor
- [ ] **Step 2: HomePage 替换 comingSoon**
- [x] **Step 2: HomePage 替换 comingSoon**
```typescript
onClick={() => setImportOpen(true)}
```
- [ ] **Step 3: build**
- [x] **Step 3: build**
```bash
npm run build
@@ -603,9 +603,9 @@ npm run build
- Modify: `README.md`
- Modify: `src/renderer/components/settings/SettingsPage.tsx`(关于页版本)
- [ ] **Step 1: i18n 键**spec §8 全部)
- [x] **Step 1: i18n 键**spec §8 全部)
- [ ] **Step 2: CSS**
- [x] **Step 2: CSS**
```css
.template-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 10px; }
@@ -614,7 +614,7 @@ npm run build
.inspiration-modal--capture { z-index: 10000; }
```
- [ ] **Step 3: E2E**
- [x] **Step 3: E2E**
```typescript
// E2E-TEMPL-01: 模板新建章 → ProseMirror 含模板正文
@@ -623,7 +623,7 @@ npm run build
// E2E-INSP-01: 主页 Ctrl+Shift+I → toast,仍在 home
```
- [ ] **Step 4: 全量验证**
- [x] **Step 4: 全量验证**
```bash
npm run build
@@ -631,11 +631,11 @@ npm run test
npm run test:e2e -- e2e/chapter-template.spec.ts e2e/import-book.spec.ts e2e/export-submission.spec.ts e2e/inspiration-capture.spec.ts
```
- [ ] **Step 5: 版本 1.1.0**
- [x] **Step 5: 版本 1.1.0**
`package.json` / `README.md` / Settings 关于页 → `v1.1.0`
- [ ] **Step 6: 勾选本 plan 全部 checkbox**
- [x] **Step 6: 勾选本 plan 全部 checkbox**
---