diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..9291011 --- /dev/null +++ b/.npmrc @@ -0,0 +1,3 @@ +registry=https://registry.npmmirror.com +electron_mirror=https://npmmirror.com/mirrors/electron/ +electron_builder_binaries_mirror=https://npmmirror.com/mirrors/electron-builder-binaries/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..d2779fc --- /dev/null +++ b/README.md @@ -0,0 +1,26 @@ +# 笔临 (Bilin) + +长篇创作智能协作平台 — Electron 桌面客户端 v0.1.0(P0/P1) + +## 开发 + +```bash +npm install --legacy-peer-deps +npm run dev +``` + +数据库使用 Node.js 内置 `node:sqlite`(无需原生模块编译)。 + +## 测试 + +```bash +npm run test # 单元测试 6/6 +npm run test:e2e # E2E 测试(需先 build) +npm run build +``` + +## 文档 + +- 设计规格:`docs/superpowers/specs/2026-07-05-bilin-p0-p1-design.md` +- 实现计划:`docs/superpowers/plans/2026-07-05-bilin-p0-p1.md` +- UI 原型:`design/ui_pc.html` diff --git a/desigin/readme.md b/design/readme.md similarity index 98% rename from desigin/readme.md rename to design/readme.md index d1dd7bb..ab6abd2 100644 --- a/desigin/readme.md +++ b/design/readme.md @@ -315,7 +315,10 @@ #### 5.2.1 章节列表 -- **树状展示**:卷→章,可折叠;支持拖拽排序(同卷及跨卷移动)。拖拽移动后若章节绑定大纲,询问是否更新大纲关联。 +- **树状展示**:卷→章,可折叠;点击卷标题▶箭头可单独折叠/展开;支持拖拽排序(同卷及跨卷移动)。拖拽移动后若章节绑定大纲,询问是否更新大纲关联。 +- **分卷记忆**:点击分卷标题时,自动展开该卷并选中该卷**上次打开的章节**;若该卷尚无打开记录,则选中第一章。当前分卷高亮显示。 +- **按卷新建章节**:「新章」按钮在**当前选中分卷**内创建章节并立即在编辑器中打开。 +- **双击改标题**:章节名支持双击原地编辑;修改后同步更新编辑器上方标题栏。 - **章节标记系统**:用户可创建自定义标签(如"高潮""需大修""女主主场"),并给章节打标。列表支持按标签筛选和颜色标识。 - **章节预览**:鼠标悬停显示首段内容及自定义摘要。 - **章节状态**:可手动标注"草稿/润色中/定稿"等状态,不同状态图标区分。 @@ -476,6 +479,11 @@ ### 5.5 大纲、设定与灵感管理 +- **统一编辑体验**:章节、大纲、设定、灵感条目均在中央内容编辑器中直接编辑;切换条目时自动保存当前内容。 +- **侧栏新建入口**:大纲 / 设定 / 灵感面板底部提供「新建」按钮;章节面板底部保留「新章」按钮。 +- **新建即打开**:新建章节、大纲、设定或灵感后,立即在编辑器中打开该条目,光标定位至文末,可直接输入。 +- **双击改标题**:侧栏章节名、大纲/设定/灵感标题,以及编辑器上方文档标题,均支持**双击原地变为输入框**修改(无弹窗);Enter 确认、Esc 取消、点击其他区域自动保存。 + #### 5.5.1 大纲系统 - **层级大纲编辑器**:支持无限层级的树状大纲,可拖拽排序、缩进/提升层级。 diff --git a/desigin/ui_pc.html b/design/ui_pc.html similarity index 82% rename from desigin/ui_pc.html rename to design/ui_pc.html index 6c5d6cf..f114055 100644 --- a/desigin/ui_pc.html +++ b/design/ui_pc.html @@ -505,7 +505,12 @@ } .vol-header:hover { background: var(--bg-hover); - color: #fff; + color: var(--text-primary); + } + .vol-header.active { + background: var(--bg-active); + color: var(--text-primary); + border-left: 3px solid var(--accent); } .vol-header .vol-arrow { font-size: 9px; @@ -554,6 +559,74 @@ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; + cursor: text; + } + .chapter-item .ch-title:hover, + .setting-entry .entry-name:hover, + .outline-item .item-title:hover, + .inspiration-item .item-title:hover { + color: var(--accent-light); + } + .inline-title-input { + width: 100%; + min-width: 0; + padding: 2px 6px; + border-radius: 3px; + border: 1px solid var(--accent); + background: var(--bg-surface); + color: var(--text-primary); + font-size: inherit; + font-family: inherit; + font-weight: inherit; + outline: none; + box-shadow: 0 0 0 2px var(--accent-glow); + } + #editor-toolbar .ch-label { + font-size: 11px; + color: var(--text-muted); + margin-left: 8px; + font-weight: 500; + cursor: text; + max-width: 280px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + #editor-toolbar .ch-label:hover { color: var(--text-primary); } + #editor-toolbar .inline-title-input.editor-label-input { + max-width: 240px; + font-size: 11px; + font-weight: 500; + } + .outline-item .item-prefix { + flex-shrink: 0; + margin-right: 4px; + } + .outline-item .item-title { + flex: 1; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + cursor: text; + } + .outline-item .item-meta { + flex-shrink: 0; + font-size: 10px; + color: var(--text-muted); + margin-left: 4px; + } + .outline-item[data-status="writing"] .item-title { color: var(--accent-light); } + .outline-item[data-status="done"] .item-title { color: var(--green); } + .inspiration-item .item-title { + display: block; + cursor: text; + } + .setting-entry .entry-name { + flex: 1; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + cursor: text; } .chapter-item .ch-badge { font-size: 9px; @@ -657,12 +730,6 @@ background: rgba(91, 156, 245, 0.2); color: var(--blue); } - .setting-entry .entry-name { - flex: 1; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } .setting-entry .entry-count { font-size: 10px; color: var(--text-muted); @@ -711,12 +778,6 @@ background: var(--border); margin: 0 6px; } - #editor-toolbar .ch-label { - font-size: 11px; - color: var(--text-muted); - margin-left: 8px; - font-weight: 500; - } #editor-toolbar .word-count-display { font-size: 11px; color: var(--accent-light); @@ -1069,10 +1130,10 @@ } .settings-sidebar .settings-nav-item:hover { background: var(--bg-hover); - color: #fff; + color: var(--text-primary); } .settings-sidebar .settings-nav-item.active { - color: #fff; + color: var(--text-primary); background: var(--bg-tertiary); border-left-color: var(--accent); font-weight: 600; @@ -1091,7 +1152,7 @@ } .settings-content h2 { font-size: 20px; - color: #fff; + color: var(--text-primary); margin-bottom: 20px; font-weight: 700; } @@ -1115,6 +1176,7 @@ margin-bottom: 6px; font-size: 13px; gap: 12px; + color: var(--text-secondary); } .settings-content .setting-item .setting-label { flex: 1; @@ -1126,12 +1188,13 @@ } .settings-content input[type="text"], .settings-content input[type="number"], + .settings-content input[type="password"], .settings-content select { padding: 6px 10px; border-radius: 4px; border: 1px solid var(--border); background: var(--bg-surface); - color: #fff; + color: var(--text-primary); font-size: 12px; font-family: var(--font-sans); } @@ -1501,7 +1564,7 @@ border-radius: var(--radius-sm); border: 1px solid var(--border); background: var(--bg-tertiary); - color: #fff; + color: var(--text-primary); font-size: 13px; font-family: var(--font-sans); outline: none; @@ -1535,7 +1598,8 @@ #batchToolbar button { padding:3px 8px;border-radius:3px;border:1px solid rgba(255,255,255,0.2);background:transparent;color:#fff;cursor:pointer;font-size:10px;transition:var(--transition); } #batchToolbar button:hover { background:rgba(255,255,255,0.15); } .outline-item { display:flex;align-items:center;padding:6px 8px 6px 18px;cursor:pointer;border-radius:4px;font-size:12px;color:var(--text-secondary);border-left:3px solid transparent;margin:1px 4px;gap:6px;transition:var(--transition); } - .outline-item:hover { background:var(--bg-hover);color:#fff; } + .outline-item:hover { background:var(--bg-hover);color:var(--text-primary); } + .outline-item.active { background:var(--bg-active);color:var(--text-primary);font-weight:600; } .outline-item.uncovered { border-left-color:var(--orange); } .outline-item.uncovered::after { content:'\26A0';font-size:10px;color:var(--orange);margin-left:auto; } #editor-toolbar .tool-btn.active { color:var(--accent-light);background:var(--bg-active); } @@ -1625,6 +1689,36 @@ .vol-header:hover .vol-menu-btn { opacity:1; } .vol-header .vol-menu-btn:hover { background:var(--bg-active);color:#fff; } .setting-cat .add-btn { color:var(--accent-light);cursor:pointer;font-weight:400; } + .setting-entry.active { + background: var(--bg-active); + border-left: 3px solid var(--accent); + } + .setting-entry.active .entry-name { + color: var(--text-primary); + } + .inspiration-item { + padding: 6px 8px; + cursor: pointer; + border-radius: 4px; + font-size: 12px; + color: var(--text-secondary); + background: var(--bg-tertiary); + margin: 2px 0; + transition: var(--transition); + border-left: 3px solid transparent; + } + .inspiration-item:hover { background: var(--bg-hover); color: var(--text-primary); } + .inspiration-item.active { background: var(--bg-active); color: var(--text-primary); border-left-color: var(--accent); font-weight: 600; } + .panel-list-body { flex: 1; overflow-y: auto; min-height: 0; } + #left-sidebar .sidebar-footer button.primary-new { + flex: 1; + color: var(--accent-light); + border-color: var(--accent-dark); + } + #left-sidebar .sidebar-footer button.primary-new:hover { + background: var(--accent-glow); + color: var(--accent-light); + } .retry-btn { display:none;padding:4px 10px;border-radius:10px;border:1px solid var(--orange);background:rgba(232,144,80,0.15);color:var(--orange);cursor:pointer;font-size:10px; } .retry-btn.show { display:inline-block; } .settings-content .shortcut-key { display:inline-block;padding:2px 8px;border-radius:3px;background:var(--bg-active);font-family:var(--font-mono);font-size:11px;border:1px solid var(--border);cursor:pointer;min-width:80px;text-align:center; } @@ -1740,45 +1834,45 @@
-
-
- 第一卷·青云之始 +
+
+ 第一卷·青云之始 12章 · 3.8万字
- 第1章山村少年定稿 + 第1章山村少年定稿
- 第2章意外觉醒定稿 + 第2章意外觉醒定稿
- 第3章入门考验AI初稿 + 第3章入门考验AI初稿
- 第4章灵根测试草稿 + 第4章灵根测试草稿
- 第5章初次修炼需修 + 第5章初次修炼需修
-
-
- 第二卷·宗门风云 +
+
+ 第二卷·宗门风云 8章 · 2.4万字
@@ -1800,52 +1894,66 @@
-
大纲树(拖拽排序 · 点击关联章节)
-
⚠ 第一卷核心剧情线
-
⚠ 林远觉醒三纹灵根
-
▶ 入门考验(写作中 — 第3章)
-
✓ 拜入青云宗(第13章 · 2,100字)
-
右键大纲条目 → "生成章节骨架"
+
+
大纲树(拖拽排序 · 点击编辑)
+
第一卷核心剧情线
+
林远觉醒三纹灵根
+
入门考验(写作中 — 第3章)
+
拜入青云宗(第13章 · 2,100字)
+
+