feat: deliver P2 v0.2.0 with unified editor, search, and snapshots

Implement schema v2 migration, outline/setting/inspiration CRUD, unified TipTap editing, reference panel with mentions, FTS global search, chapter version history, writing landmarks, word frequency analysis, light theme contrast fixes, and full unit/E2E test coverage.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-06 14:13:27 +08:00
parent 91c93954df
commit aac51bf183
72 changed files with 5790 additions and 203 deletions
+92
View File
@@ -10,6 +10,15 @@ export type ThemeId =
export type Language = 'zh-CN' | 'en'
export type ChapterStatus = 'draft' | 'review' | 'done'
export type BookStatus = 'draft' | 'ongoing' | 'done'
export type PublishStatus = 'draft' | 'ready' | 'published'
export type OutlineStatus = 'pending' | 'writing' | 'done' | 'abandoned'
export type SettingType = 'character' | 'location' | 'item' | 'skill' | 'faction' | 'custom'
export type SnapshotType = 'auto' | 'manual' | 'persist' | 'ai'
export type LandmarkType = 'todo' | 'foreshadow' | 'research' | 'custom'
export type EditTargetKind = 'chapter' | 'outline' | 'setting' | 'inspiration'
export type EditTarget = { kind: EditTargetKind; id: string }
export type SearchScope = 'all' | 'volume' | 'chapter'
export type SearchSourceKind = 'chapter' | 'outline' | 'setting' | 'inspiration' | 'bookmark'
export type ActionId =
| 'saveChapter'
@@ -47,6 +56,10 @@ export interface GlobalSettings {
language: Language
dailyWordGoal: number
shortcuts: Record<ActionId, string>
snapshotIntervalMs: number
snapshotMaxAuto: number
snapshotMaxPersist: number
searchHistory: string[]
}
export interface BookMeta {
@@ -84,12 +97,91 @@ export interface Chapter {
wordCount: number
sortOrder: number
cursorOffset: number
publishStatus?: PublishStatus
povCharacterId?: string | null
summary?: string
storyTime?: string | null
}
export interface OutlineItem {
id: string
parentId: string | null
title: string
description: string
status: OutlineStatus
expectedWordCount: number | null
chapterId: string | null
sortOrder: number
createdAt: string
updatedAt: string
children?: OutlineItem[]
}
export interface SettingEntry {
id: string
type: SettingType
name: string
description: string
properties: Record<string, unknown>
chapterIds?: string[]
createdAt: string
updatedAt: string
}
export interface InspirationEntry {
id: string
title: string
content: string
tags: string[]
createdAt: string
updatedAt: string
}
export interface Snapshot {
id: string
chapterId: string
type: SnapshotType
name: string
content: string
createdAt: string
}
export interface Bookmark {
id: string
chapterId: string
position: number
label: string
landmarkType: LandmarkType
resolved: boolean
createdAt: string
}
export interface SearchOptions {
regex?: boolean
caseSensitive?: boolean
matchWholeWord?: boolean
}
export interface SearchResult {
kind: SearchSourceKind
id: string
title: string
snippet: string
chapterId?: string
position?: number
}
export interface WordFreqResult {
words: { token: string; count: number }[]
}
export interface BookOpenResult {
meta: BookMeta
volumes: Volume[]
chapters: Chapter[]
outlines: OutlineItem[]
settings: SettingEntry[]
inspirations: InspirationEntry[]
}
export interface UpdateChapterParams {