fe6e411d2c
Wire .novel/.novel-all export-import through modals, settings backup, and home bulk export with progress IPC. Co-authored-by: Cursor <cursoragent@cursor.com>
158 lines
5.8 KiB
Markdown
158 lines
5.8 KiB
Markdown
# 笔临 Wave 2 项目包 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.
|
||
|
||
**Goal:** 交付 v1.3.0:`.novel` 单书项目包与 `.novel-all` 批量包导入导出,主页/设置/导出模态接入,大文件进度与取消。
|
||
|
||
**Architecture:** `pack-bootstrap` 独立 chunk 动态 `import('archiver')`;`PackService` 读写 ZIP + `manifest.json` v1;导出复制 `book.sqlite` + `meta.json` + 可选 `attachments/`;导入默认新 UUID 注册;`PACK_PROGRESS` IPC 推送进度;>500MB 导出前确认。
|
||
|
||
**Tech Stack:** Electron 36、archiver、node:fs、TypeScript、Vitest、Playwright
|
||
|
||
**Spec:** `docs/superpowers/specs/2026-07-08-bilin-master-completion-design.md` §4.6、§6
|
||
|
||
**Master Program:** Wave 2/5 → v1.3.0
|
||
|
||
---
|
||
|
||
## File Map
|
||
|
||
| 文件 | 职责 |
|
||
|------|------|
|
||
| `src/shared/novel-pack.ts` | manifest v1 类型、formatVersion 常量 |
|
||
| `src/main/pack-bootstrap.ts` | 延迟加载 archiver,注册 pack IPC |
|
||
| `src/main/services/pack.service.ts` | exportBook/importBook/exportAll/importAll |
|
||
| `src/main/ipc/handlers/pack.handler.ts` | PACK_* IPC |
|
||
| `src/shared/ipc-channels.ts` | PACK_EXPORT_BOOK 等 |
|
||
| `src/shared/types.ts` | PackProgressEvent、PackImportReport |
|
||
| `src/preload/index.ts` + `electron-api.d.ts` | pack.export/import API |
|
||
| `src/renderer/components/export/ExportAllModal.tsx` | 主页导出全部 |
|
||
| `src/renderer/components/import/ImportBookModal.tsx` | 支持 .novel/.novel-all |
|
||
| `src/renderer/components/export/ExportModal.tsx` | 增加 .novel 选项 |
|
||
| `src/renderer/components/home/HomePage.tsx` | 导出全部入口 |
|
||
| `src/renderer/components/settings/BackupSettingsTab.tsx` | 设置页备份区 |
|
||
| `electron.vite.config.ts` | pack-bootstrap 入口 |
|
||
| `tests/main/pack.service.test.ts` | IT-ALL-02 等 |
|
||
| `e2e/pack-export-import.spec.ts` | 单书 .novel E2E |
|
||
| `e2e/pack-export-all.spec.ts` | E2E-ALL-03 |
|
||
|
||
---
|
||
|
||
## Task 1: 依赖 + 类型 + pack-bootstrap
|
||
|
||
**Files:**
|
||
- Modify: `package.json`
|
||
- Create: `src/shared/novel-pack.ts`
|
||
- Create: `src/main/pack-bootstrap.ts`
|
||
- Modify: `electron.vite.config.ts`
|
||
|
||
- [x] **Step 1:** `npm install archiver` + dev `@types/archiver`
|
||
- [x] **Step 2:** `novel-pack.ts` — `NOVEL_FORMAT_VERSION = 1`,`NovelManifest`、`NovelAllManifest`
|
||
- [x] **Step 3:** `pack-bootstrap.ts` — 导出 `bootstrapPackHandlers(registry, settings)`
|
||
- [x] **Step 4:** `electron.vite.config.ts` — 增加 `pack-bootstrap` input,`external: ['archiver']`
|
||
- [x] **Step 5:** `npm run build` 通过
|
||
|
||
---
|
||
|
||
## Task 2: PackService 单书导出/导入
|
||
|
||
**Files:**
|
||
- Create: `src/main/services/pack.service.ts`
|
||
- Modify: `src/main/services/book-registry.ts` — `importFromDb(meta, sqlitePath)` 辅助
|
||
|
||
- [x] **Step 1:** `exportBook(bookId, destPath)` — ZIP: manifest + meta + book.sqlite + attachments
|
||
- [x] **Step 2:** `importBook(filePath)` — 校验 formatVersion,新 UUID,注册 meta,复制 sqlite
|
||
- [x] **Step 3:** 名称冲突时追加后缀 `(2)`
|
||
- [x] **Step 4:** UT `tests/main/pack.service.test.ts` — 导出再导入章节数一致
|
||
|
||
---
|
||
|
||
## Task 3: exportAll / importAll + 进度
|
||
|
||
**Files:**
|
||
- Modify: `src/main/services/pack.service.ts`
|
||
- Modify: `src/shared/types.ts`
|
||
|
||
- [x] **Step 1:** `exportAll(destPath)` — global_settings + books/{id}/
|
||
- [x] **Step 2:** `importAll(filePath, strategy)` — skip/overwrite/new
|
||
- [x] **Step 3:** `onProgress` 回调 + `PACK_PROGRESS` 广播
|
||
- [x] **Step 4:** `estimateSize` + >500MB 确认标志
|
||
- [x] **Step 5:** AbortController 取消支持
|
||
- [x] **Step 6:** UT IT-ALL-02 — 3 书导出删库再导入
|
||
|
||
---
|
||
|
||
## Task 4: IPC + preload
|
||
|
||
**Files:**
|
||
- Create: `src/main/ipc/handlers/pack.handler.ts`
|
||
- Modify: `src/main/pack-bootstrap.ts`
|
||
- Modify: `src/main/index.ts`
|
||
- Modify: `src/preload/index.ts`、`electron-api.d.ts`
|
||
|
||
- [x] **Step 1:** IPC 常量与 handler 注册
|
||
- [x] **Step 2:** preload `pack.exportBook/importBook/exportAll/importAll/pickFile`
|
||
- [x] **Step 3:** `onPackProgress` 事件订阅
|
||
|
||
---
|
||
|
||
## Task 5: ExportModal + ImportBookModal
|
||
|
||
**Files:**
|
||
- Modify: `src/renderer/components/export/ExportModal.tsx`
|
||
- Modify: `src/renderer/components/import/ImportBookModal.tsx`
|
||
- Modify: `public/locales/*/translation.json`
|
||
|
||
- [x] **Step 1:** ExportModal 增加「笔临项目包 (.novel)」
|
||
- [x] **Step 2:** ImportBookModal 文件过滤含 `.novel`/`.novel-all`
|
||
- [x] **Step 3:** `.novel` 直接导入;`.novel-all` 打开策略选择 + 进度条
|
||
|
||
---
|
||
|
||
## Task 6: ExportAllModal + HomePage
|
||
|
||
**Files:**
|
||
- Create: `src/renderer/components/export/ExportAllModal.tsx`
|
||
- Modify: `src/renderer/components/home/HomePage.tsx`
|
||
- Modify: `src/renderer/stores/useAppStore.ts`(可选 modal 状态)
|
||
|
||
- [x] **Step 1:** `ExportAllModal` — 选路径、大小确认、进度、取消
|
||
- [x] **Step 2:** HomePage「导出所有书籍」启用并打开 modal
|
||
|
||
---
|
||
|
||
## Task 7: 设置页备份区
|
||
|
||
**Files:**
|
||
- Create: `src/renderer/components/settings/BackupSettingsTab.tsx`
|
||
- Modify: `src/renderer/components/settings/SettingsPage.tsx`
|
||
|
||
- [x] **Step 1:** 导出当前书 / 导出全部按钮
|
||
- [x] **Step 2:** i18n `backup.*`
|
||
|
||
---
|
||
|
||
## Task 8: E2E + v1.3.0
|
||
|
||
**Files:**
|
||
- Create: `e2e/pack-export-import.spec.ts`
|
||
- Create: `e2e/pack-export-all.spec.ts`
|
||
- Modify: `e2e/helpers.ts`
|
||
- Modify: `package.json`、`README.md`、`SettingsPage.tsx`
|
||
|
||
- [x] **Step 1:** E2E 单书 .novel 导出再导入
|
||
- [x] **Step 2:** E2E-ALL-03 主页导出全部
|
||
- [x] **Step 3:** 全量 `npm run test` + 相关 E2E
|
||
- [x] **Step 4:** 版本 **v1.3.0**
|
||
- [x] **Step 5:** 勾选本 plan 全部 checkbox
|
||
|
||
---
|
||
|
||
## Plan 自检
|
||
|
||
| Spec §6 要求 | Task |
|
||
|-------------|------|
|
||
| PackService 四 API | Task 2–3 |
|
||
| 进度 IPC | Task 3–4 |
|
||
| UI 入口 | Task 5–7 |
|
||
| IT-ALL-02 / E2E | Task 8 |
|