dsh-maoying 0.1.23 → 0.1.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/docs/creator-panel.md +3 -1
- package/lib/base.css +1 -1
- package/lib/client.js +24 -19
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -73,7 +73,7 @@ npm install -g dsh-maoying # 或装成全局 maoying 命令
|
|
|
73
73
|
|
|
74
74
|
DSH 左侧栏底部点「**毛颖创作台**」打开全页面板(改文件、跑流程之外,给肉眼看的驾驶舱):
|
|
75
75
|
|
|
76
|
-
- **章节**:状态筛选 + 按单写作清单;点章节进整页阅读——返回按钮、章纲对照(Markdown 渲染)、正文与章纲就地编辑保存(正文 textarea 自动保存——待写空章节打开即直接进编辑器、约
|
|
76
|
+
- **章节**:状态筛选 + 按单写作清单;点章节进整页阅读——返回按钮、章纲对照(Markdown 渲染)、正文与章纲就地编辑保存(正文 textarea 自动保存——待写空章节打开即直接进编辑器、约 30 秒防抖落盘、手动/自动保存都停留在编辑态续写、回车换行自动加段首两个全角空格缩进、编辑栏实时显示正文字数;章纲 textarea 手动保存;文件在编辑期间被外部改过时拒绝保存并放回磁盘最新内容,不覆盖人工改动)、五维叙事字段、一键状态流转。
|
|
77
77
|
- **概览**:书稿卡右上「编辑」按钮展开 project.yml 的书名/作者/题材/篇幅/语言/工作流阶段/共创模式/简介表单化编辑(原「小说设置」tab 并入),保存保留文件里原有注释;表单载入后 project.yml 被外部(作者手改 / agent 推进阶段)改过时拒绝保存并提示重改,不覆盖人工改动。概览另设「分卷规划」卡,列出 volumes.yml 各卷定位与计划章节范围——拍板过的分卷有处可查,卡头「编辑源文件」可整文件编辑 volumes.yml。
|
|
78
78
|
- **受管文件写面**:角色/设定/科学设定卡与六本账本(关系/时间线/记忆/线索板/伏笔/分卷)均可从面板编辑源文件——墙头「新建」、卡详情「编辑源文件/删除文件」、各账本卡头「编辑源文件」(时间线/关系图空态也给入口);保存时结构校验(账本须是条目数组、实体卡须带 frontmatter 围栏,不合即拒存),外部改动保护与正文编辑同口径;章节阅读页可新建章纲(本章目标/节拍/出场角色/需埋需收伏笔/与前章接口五件骨架预填)、删除章纲与删除章节——删除均确认弹层,不可逆,后悔靠 git,静态体检会把孤儿引用标出来。
|
|
79
79
|
- **顶栏**:当前版本号常驻;npm 上有新版时亮「有新版 ↗」徽章直连发布页,旁边「一键升级」按钮直接用 pnpm 把最新包装进当前 DSH 档(仅支持 profile 目录安装,pnpm 缺失时自动回落 corepack;检测到全局 `maoying` CLI 时顺带以同一精确版本更新,未装则跳过;装完需重启 DeepSeek 才生效);「检测更新」按钮随时手动现测线上最新版(绕过 1h 缓存——面板打开时只自动拉一次,页面开久了也不聋);齿轮打开系统设置,界面语言中文/English 可切、字号六档(100%–150%)整体缩放,均立即生效并记忆。
|
package/docs/creator-panel.md
CHANGED
|
@@ -132,7 +132,7 @@ webServer.register({ kind: 'prefix', path: '/api/maoying', handler: async (req,
|
|
|
132
132
|
九个 tab(顺序即默认排布):
|
|
133
133
|
|
|
134
134
|
1. **概览**:project 卡(书名大字 + 类型/篇幅/语言 pills + 阶段徽章 + 简介,卡右上「编辑」按钮展开书稿元信息表单——原「小说设置」tab 并入,见 §4.1「小说设置并入概览」条目);统计卡(总字数/章节数/状态分布条);最近更新(chapters 按 mtime 前 5);warnings 黄条;静态体检黄条(check 路由问题清单,见 §4.1「人工改动保护 + 静态体检黄条」(0.1.14)条目);分卷规划卡卡头「编辑源文件」(volumes.yml 整文件编辑弹层,0.1.20 写面)。
|
|
135
|
-
2. **章节**:表格(卷-章/标题/状态徽章/字数/梗概),状态筛选 pills;表格上方「按单写作」区块——有章纲且 status=pending 的章按序列出(章纲节选 + 状态徽章),未建章的孤儿章纲照列(「未建章」徽章 + 「建章」一键:POST chapter-create 落 pending 空章并重拉快照;行点击开章纲全文弹层,0.1.15 起),共创模式的主工作清单;行点击开整页阅读视图(0.1.12 起替代原右侧抽屉——fixed 侧弹层会被 DSH 侧边栏遮挡):返回按钮 + GET chapter 正文 + 章纲对照栏(左右分栏或折叠段)+ 复制文件路径按钮 + 五维字段卡 + 状态流转按钮(当前态 → 下一态一键,pending→writing→review→accepted);正文与章纲对照栏均可就地编辑保存(POST chapter-save / outline-save 携 base_hash 409 人工改动检测——frontmatter 围栏逐字节保留,外部改动拒写不落盘、草稿保留并亮「载入磁盘版(放弃草稿)/基于最新版重改」两个出口,0.1.19 起、两出口见 §4.1 末条):正文编辑态自动保存(约
|
|
135
|
+
2. **章节**:表格(卷-章/标题/状态徽章/字数/梗概),状态筛选 pills;表格上方「按单写作」区块——有章纲且 status=pending 的章按序列出(章纲节选 + 状态徽章),未建章的孤儿章纲照列(「未建章」徽章 + 「建章」一键:POST chapter-create 落 pending 空章并重拉快照;行点击开章纲全文弹层,0.1.15 起),共创模式的主工作清单;行点击开整页阅读视图(0.1.12 起替代原右侧抽屉——fixed 侧弹层会被 DSH 侧边栏遮挡):返回按钮 + GET chapter 正文 + 章纲对照栏(左右分栏或折叠段)+ 复制文件路径按钮 + 五维字段卡 + 状态流转按钮(当前态 → 下一态一键,pending→writing→review→accepted);正文与章纲对照栏均可就地编辑保存(POST chapter-save / outline-save 携 base_hash 409 人工改动检测——frontmatter 围栏逐字节保留,外部改动拒写不落盘、草稿保留并亮「载入磁盘版(放弃草稿)/基于最新版重改」两个出口,0.1.19 起、两出口见 §4.1 末条):正文编辑态自动保存(约 30s 防抖——0.1.22 起 2s、0.1.23 起放宽到 30s 且手动保存同样停留编辑态不清稿;写盘内容即新基线、纯缩进占位不落盘,编辑 hint 常显正文实时 CJK 字数、与服务端全库字数同口径),待写空章节(body 全空白)打开即直接进编辑态、不再经「编辑」按钮中转,回车换行自动加段首两个全角空格缩进,编辑器排版与只读正文一致(所见即所得)并随内容自动长高;章纲对照栏仍手动保存(textarea + 取消/保存);0.1.20 写面:无章纲空态加「新建章纲」(outlines/<stem>.md 五件骨架预填)、章纲对照栏卡头「删除章纲」、阅读顶栏「删除章节」——后两者均确认弹层(不可逆,后悔靠 git,check 会标孤儿引用)。
|
|
136
136
|
3. **角色**:卡墙(姓名/role 徽章四色/年龄性别/性格一句/动机一行),点击看全卡(含 arc/markers/background);0.1.20 写面:墙头「新建角色」(模板预填)+ 全卡弹层底部「编辑源文件/删除文件」。
|
|
137
137
|
4. **伏笔**:四列看板(埋设/推进/已回收/弃用),卡片含 priority 色点(high 红/normal 灰/low 淡)、`source: backfill` 的「回填」小徽章(账本回填来的条目,区别于写前规划)、埋设章→预期回收章、notes 全文直显(0.1.10 去掉两行截断);卡片按钮:推进到下一状态(planted→progressing→resolved;abandoned 只能从看板拖不动、按钮给「弃用」)。列头计数;0.1.20 写面:卡头「编辑源文件」(foreshadows.yml)。
|
|
138
138
|
5. **关系图**:canvas 力导向图——节点=角色(radius 随出场无关、固定 18px,名字 label 下方),边=relations(intensity 1-5 → 线宽 1-4px,type 标在边中点 hover 显示 description);节点按角色配色(0.1.20 起):主角 #f53f3f 红 / 配角 #165dff 蓝 / 反派 #1d2129 黑 / 龙套与未标注 #fadc19 黄(查表 miss 落 minor,全节点恒有色),拖拽固定态统一加粗描边;脚注带四色图例;拖拽节点、空白处滚轮缩放、双击复位;右上角 +/- 缩放按钮(钳制同滚轮 0.4-2.5)与全屏按钮(Fullscreen API 能力检测,不支持则不渲染;进入全屏走 ResizeObserver 自动重铺);intensity 缺省 3。角色多于 30 个时只画与 relations 相连的节点,其余进「未入图」列表。防重叠(0.1.20 起):节点最小间距 62 硬碰撞分离(含名字 label 纵向净空,力式斥力之上兜底,弹簧 rest 120→130 配合多留缝隙);边为二次曲线——按两侧空旷度选朝向(迟滞防抖)绕开途中节点,同一对角色的重复边偏移放大 + 交替朝向互相分开(type 标签随曲线移到 t=0.5 点);hover 命中按曲线几何采样。0.1.20 写面:卡头「编辑源文件」(relations.yml,空态同样给入口)。
|
|
@@ -180,6 +180,8 @@ webServer.register({ kind: 'prefix', path: '/api/maoying', handler: async (req,
|
|
|
180
180
|
|
|
181
181
|
- **正文编辑直开 + 自动保存 + 段首缩进**(0.1.22):章节阅读页正文编辑三处升级——①**空章节直开编辑态**:待写章节(body 全空白)打开即直接进正文编辑态,不再经顶部「编辑」按钮中转;预填段首两个全角空格让首段也有缩进,基线与预填同值(不判脏,退出确认与自动保存均不误触);正在编辑绝不打扰(409 放弃草稿等编辑中重拉被 editingRef 守卫排除),同章本轮只自动进一次,切章/重开面板算新一轮可再进,手动「取消」退出后本轮不再自动重进。②**正文自动保存**:编辑中改动 2s 防抖落盘(调度 effect 无 dep 数组每轮渲染重排定时器,连续打字永远差 2s 才保存;409 冲突/保存在途不排),调用点快照 draft 防在途打字被误标已保存,**写盘内容即新基线**(连续自动保存不假脏),成功不退出编辑态、不清草稿,编辑 hint 缀「已自动保存(HH:MM:SS)」时刻标;纯缩进占位(trim 为空)不落盘;409 人工改动检测语义不变——冲突即停排、草稿保留、两出口照旧。③**回车自动段首缩进**:编辑器内回车换行自动插入两个全角空格(U+3000×2,网文段落缩进惯例),光标落到缩进之后(draft 提交后下一轮渲染恢复选区);IME 组态中的回车(keyCode 229 / isComposing)是选词确认不劫持,取不到 selectionStart 的退化环境交给浏览器默认行为。编辑器排版与只读正文一致(同 UI 字体、13px/22px 行高,所见即所得)并随内容自动长高(≥320px,overflow hidden + resize none),主题色边框保留可辨识仍在编辑;脏退出确认兜底不动(自动保存窗口之外切章/取消/返回仍先确认)。纯前端,路由不变;I18N zh/en 各 301 → 302 条(reader.autoSaved;reader.bodyEditHint 文案同步改写)。
|
|
182
182
|
|
|
183
|
+
- **手动保存不退出编辑态 + 防抖 30s + 实时字数**(0.1.23):正文编辑三点迭代——①**手动/自动保存行为统一**:保存成功(「保存」按钮或防抖定时器)都停留编辑态续写、不清草稿,时刻标照缀 hint——手动点保存与自动保存等价,只是人工触发(用户语:「这个功能实际上和自动保存是一样的,只不过是人工点一下而已」);退出编辑态只走「取消」(保存后草稿已回基线、脏检查归零,无确认直退),0.1.22 之前「手动保存退出编辑态」的旧语义废止。②**自动保存防抖 2s → 30s**:写作中途的短暂停顿(翻资料、想句子)不再频繁落盘,「每轮渲染重排定时器、连续打字永远差一个窗口」的调度语义不变,纯缩进占位不落盘照旧。③**编辑 hint 常显正文实时 CJK 字数**:复用既有 `common.charCount`(`{n} 字` / `{n} chars`,fmtNum 千分位),客户端内联与 lib/novel-parse.mjs `countCjk` 同口径的正则(基本区 + 扩展 A + 扩展 B,u 标志按码点匹配增补平面生僻字),面板本地数与服务端全库字数口径一致;显示形如「直接编辑正文… · 1,234 字 · 已自动保存(HH:MM:SS)」,字数常显、保存时刻照旧按有无显示。纯前端,路由不变;I18N 键数不变(reader.bodyEditHint 文案更新:2 秒 → 30 秒 / ~2s → ~30s)。
|
|
184
|
+
|
|
183
185
|
## 5. 验收基线
|
|
184
186
|
|
|
185
187
|
- Node 侧:临时 workspace(/tmp)+ 假 workspaceRegistry 不行——路由从 ctx.workspaceRegistry 取;单测直接 import lib/panel-core.mjs 的函数(parseStateSnapshot / mutateChapterStatus / mutateForeshadowStatus / mutatePhase / rebuildIndex)跑断言;路由层用 node 起一个最小 ctx 假件(webServer.register 收集 handler,workspaceRegistry 返回临时 root)模拟请求验证围栏 403 / 状态流转 / 防穿越。
|
package/lib/base.css
CHANGED
|
@@ -461,7 +461,7 @@ html[data-dsh-maoying-active]:not([data-dsh-mnemon-active]):not([data-dsh-taskbo
|
|
|
461
461
|
.myt-dimLabel { font-size: 11px; line-height: 16px; color: var(--dsw-alias-label-tertiary); margin-bottom: 2px; }
|
|
462
462
|
.myt-dimText { font-size: 12px; line-height: 18px; color: var(--dsw-alias-label-secondary); overflow-wrap: anywhere; }
|
|
463
463
|
|
|
464
|
-
/* ── 0.1.19 引入正文/章纲面板编辑态;0.1.22
|
|
464
|
+
/* ── 0.1.19 引入正文/章纲面板编辑态;0.1.22 起正文自动保存(防抖 0.1.23 起 30s)─
|
|
465
465
|
编辑态与只读态的区分靠主题色边框强调(只读态是无边框淡底的
|
|
466
466
|
.myt-chapterBody pre);正文 textarea 排版与只读正文对齐(同 UI 字体、
|
|
467
467
|
13px/22px 行高)所见即所得,高度随内容自动长高——当年的等宽字体 +
|
package/lib/client.js
CHANGED
|
@@ -1365,7 +1365,7 @@ window.__ModuleLoader__.load({
|
|
|
1365
1365
|
"chapters.emptyWithOutlines": "chapters/ 目录还没有章节文件;下方「按单写作」已列出未建章章纲",
|
|
1366
1366
|
"reader.back": "返回", "reader.backTip": "返回章节列表", "reader.copyPath": "复制路径", "reader.copyPathTip": "复制章节文件路径",
|
|
1367
1367
|
"reader.edit": "编辑", "reader.editTip": "编辑章节正文(frontmatter 保留不动)",
|
|
1368
|
-
"reader.save": "保存", "reader.bodyEditHint": "直接编辑正文:改动约
|
|
1368
|
+
"reader.save": "保存", "reader.bodyEditHint": "直接编辑正文:改动约 30 秒自动保存;回车换行自动加段首两个全角空格缩进。frontmatter(--- 围栏)保留不动;文件被外部改过时保存会被拒绝并给出处理出口。", "reader.autoSaved": "已自动保存({time})",
|
|
1369
1369
|
"outline.editTip": "编辑章纲", "outline.editHint": "直接编辑章纲全文;编辑期间文件被外部改过时保存会被拒绝,并放回磁盘最新内容。",
|
|
1370
1370
|
"reader.copied": "已复制章节文件路径", "reader.copyFailed": "复制失败,请手动选择路径文本", "reader.loadFailed": "正文读取失败:{msg}",
|
|
1371
1371
|
"reader.noOutline": "暂无章纲", "reader.emptyBody": "(空章节)", "reader.finalState": "已定稿(终态)", "reader.statusFlow": "状态流转:",
|
|
@@ -1483,7 +1483,7 @@ window.__ModuleLoader__.load({
|
|
|
1483
1483
|
"chapters.emptyWithOutlines": "No chapter files in chapters/ yet — the Writing Queue below lists outlines without chapters",
|
|
1484
1484
|
"reader.back": "Back", "reader.backTip": "Back to chapter list", "reader.copyPath": "Copy path", "reader.copyPathTip": "Copy chapter file path",
|
|
1485
1485
|
"reader.edit": "Edit", "reader.editTip": "Edit the chapter text (frontmatter is preserved)",
|
|
1486
|
-
"reader.save": "Save", "reader.bodyEditHint": "Edit the chapter text directly: changes auto-save after ~
|
|
1486
|
+
"reader.save": "Save", "reader.bodyEditHint": "Edit the chapter text directly: changes auto-save after ~30s; Enter starts a new paragraph indented with two full-width spaces. The frontmatter (--- fence) is preserved; if the file was changed externally, saving is rejected with recovery options.", "reader.autoSaved": "Auto-saved ({time})",
|
|
1487
1487
|
"outline.editTip": "Edit outline", "outline.editHint": "Edit the outline text directly; if the file was changed externally while editing, saving is rejected and the latest content is restored.",
|
|
1488
1488
|
"reader.copied": "Copied chapter file path", "reader.copyFailed": "Copy failed — select the path text manually", "reader.loadFailed": "Failed to load chapter text: {msg}",
|
|
1489
1489
|
"reader.noOutline": "No chapter outline", "reader.emptyBody": "(empty chapter)", "reader.finalState": "Accepted (final)", "reader.statusFlow": "Status:",
|
|
@@ -1553,8 +1553,9 @@ window.__ModuleLoader__.load({
|
|
|
1553
1553
|
// ── 章节阅读页(整页视图,替代右侧抽屉):返回按钮 + 章纲对照 + 正文 +
|
|
1554
1554
|
// 五维 + 状态流转。原抽屉是 position:fixed 侧弹层,在桌面端会被侧边栏
|
|
1555
1555
|
// 遮挡;整页视图天然在面板文档流内,无遮挡问题。0.1.19 起正文/章纲可在
|
|
1556
|
-
// 本页编辑保存;0.1.22
|
|
1557
|
-
//
|
|
1556
|
+
// 本页编辑保存;0.1.22 起正文改自动保存(回车自动段首缩进 + 空章节直开编
|
|
1557
|
+
// 辑态,防抖 0.1.23 起放宽到 30s、手动保存同样停留编辑态),章纲仍手动保
|
|
1558
|
+
// 存;409 人工改动保护链路照 StyleTab。──
|
|
1558
1559
|
function ChapterReader(props) {
|
|
1559
1560
|
var file = props.file;
|
|
1560
1561
|
var wsPath = props.wsPath;
|
|
@@ -1578,8 +1579,8 @@ window.__ModuleLoader__.load({
|
|
|
1578
1579
|
// 草稿绝不丢(见 saveBody/saveOutline 的 catch)。
|
|
1579
1580
|
var _bc = useState(false), bodyConflict = _bc[0], setBodyConflict = _bc[1];
|
|
1580
1581
|
var _oc = useState(false), olConflict = _oc[0], setOlConflict = _oc[1];
|
|
1581
|
-
// 正文自动保存(0.1.22
|
|
1582
|
-
// hint
|
|
1582
|
+
// 正文自动保存(0.1.22 引入;0.1.23 起手动保存同样写入时刻):最近一次
|
|
1583
|
+
// 保存成功的时刻(HH:MM:SS),缀在编辑 hint 后;切章时清零。
|
|
1583
1584
|
var _as = useState(""), autoSavedAt = _as[0], setAutoSavedAt = _as[1];
|
|
1584
1585
|
var detailSeqRef = useRef(0); // chapter 请求序号:快速切章时丢弃过期响应
|
|
1585
1586
|
// 409 后的一次性重置标记:loadDetail 带回磁盘真值时把草稿放回最新内容
|
|
@@ -1725,8 +1726,7 @@ window.__ModuleLoader__.load({
|
|
|
1725
1726
|
}
|
|
1726
1727
|
onBack();
|
|
1727
1728
|
}
|
|
1728
|
-
function saveBody(
|
|
1729
|
-
var auto = !!(opts && opts.auto); // 自动保存(2s 防抖调度):成功不退出编辑态、不清草稿
|
|
1729
|
+
function saveBody() {
|
|
1730
1730
|
if (bodyBusy || !detail.data) return;
|
|
1731
1731
|
setBodyBusy(true); setBodyErr("");
|
|
1732
1732
|
var bodyToSave = draft; // 调用点快照:在途期间继续打字的文本不该被误标已保存
|
|
@@ -1735,19 +1735,17 @@ window.__ModuleLoader__.load({
|
|
|
1735
1735
|
// 时序守卫:保存期间切了章——旧章结果不得覆写当前 detail(快照 reload 无害照做)。
|
|
1736
1736
|
if (fileRef.current === file) {
|
|
1737
1737
|
// 写后指纹即下一轮基线(连续保存不再被自家 409 拦住);本地 data 同步
|
|
1738
|
-
//
|
|
1738
|
+
// 为新正文,编辑器即时看到刚落盘的内容(不等重拉,防闪回旧文)。
|
|
1739
1739
|
setDetail({ loading: false, data: Object.assign({}, detail.data, {
|
|
1740
1740
|
body: bodyToSave,
|
|
1741
1741
|
hash: res && typeof res.hash === "string" ? res.hash : detail.data.hash,
|
|
1742
1742
|
}), err: "" });
|
|
1743
|
-
bodyBaseRef.current = bodyToSave; //
|
|
1743
|
+
bodyBaseRef.current = bodyToSave; // 写盘内容即新基线:连续保存不假脏
|
|
1744
1744
|
setBodyConflict(false);
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
setEditing(false); setDraft(""); setAutoSavedAt("");
|
|
1750
|
-
}
|
|
1745
|
+
// 0.1.23 起手动/自动保存统一:都停留编辑态续写、不清草稿——手动点保存
|
|
1746
|
+
// 与自动保存等价,只是人工触发;退出编辑态只走「取消」(保存后草稿
|
|
1747
|
+
// 已回基线,脏检查归零,无确认直退)。
|
|
1748
|
+
setAutoSavedAt(new Date().toTimeString().slice(0, 8));
|
|
1751
1749
|
}
|
|
1752
1750
|
return reload(); // 字数/统计随正文变,快照由 reload 刷新
|
|
1753
1751
|
}).catch(function (err) {
|
|
@@ -1763,8 +1761,9 @@ window.__ModuleLoader__.load({
|
|
|
1763
1761
|
}
|
|
1764
1762
|
}).finally(function () { setBodyBusy(false); });
|
|
1765
1763
|
}
|
|
1766
|
-
// 正文自动保存调度(0.1.22
|
|
1767
|
-
//
|
|
1764
|
+
// 正文自动保存调度(0.1.22 引入;0.1.23 防抖 2s → 30s——写作中途的短暂
|
|
1765
|
+
// 停顿不再频繁落盘):无 dep 数组,每轮渲染重排——任何一次渲染都先清掉
|
|
1766
|
+
// 上一个 30s 定时器再按最新 draft 重排,连续打字永远差 30s 才落盘;切章、
|
|
1768
1767
|
// 409 冲突、保存在途不排。draft 回到基线(刚保存/刚进编辑)不动作;纯缩进
|
|
1769
1768
|
// 占位(trim 为空)不落盘,且旧「已保存」时刻一并撤下。setAutoSavedAt("")
|
|
1770
1769
|
// 传同值时 React 不重渲,不会循环。
|
|
@@ -1776,7 +1775,7 @@ window.__ModuleLoader__.load({
|
|
|
1776
1775
|
return;
|
|
1777
1776
|
}
|
|
1778
1777
|
setAutoSavedAt(""); // 新改动入列,清掉旧的「已保存」标
|
|
1779
|
-
var t = setTimeout(function () { if (fileRef.current === file) saveBody(
|
|
1778
|
+
var t = setTimeout(function () { if (fileRef.current === file) saveBody(); }, 30000);
|
|
1780
1779
|
return function () { clearTimeout(t); };
|
|
1781
1780
|
});
|
|
1782
1781
|
// 回车缩进的光标恢复:DOM 换新后把光标放到插入的「\n 」缩进之后,
|
|
@@ -1883,6 +1882,11 @@ window.__ModuleLoader__.load({
|
|
|
1883
1882
|
if (!detail.data || !detail.data.outline) return null;
|
|
1884
1883
|
return { active: olEditing, draft: olDraft, busy: olBusy, err: olErr, conflict: olConflict, start: startOutlineEdit, change: setOlDraft, cancel: cancelOutlineEdit, save: saveOutline, drop: dropOutlineDraft, rebase: rebaseOutlineDraft };
|
|
1885
1884
|
}
|
|
1885
|
+
// 编辑中正文的实时 CJK 字数(0.1.23,hint 行常显):与 lib/novel-parse.mjs
|
|
1886
|
+
// 的 countCjk 同口径——基本区 + 扩展 A + 扩展 B,u 标志按码点匹配(增补平面
|
|
1887
|
+
// 生僻字不漏计),面板本地数与服务端全库字数对得上。
|
|
1888
|
+
var draftCjk = draft.match(/[\u4e00-\u9fff\u3400-\u4dbf\u{20000}-\u{2a6df}]/gu);
|
|
1889
|
+
var draftWords = draftCjk ? draftCjk.length : 0;
|
|
1886
1890
|
return h("div", { className: "myt-reader" },
|
|
1887
1891
|
h("div", { className: "myt-readerBar" },
|
|
1888
1892
|
h("button", { type: "button", className: "myt-btn", onClick: leaveReader, title: tt("reader.backTip") },
|
|
@@ -1948,6 +1952,7 @@ window.__ModuleLoader__.load({
|
|
|
1948
1952
|
}),
|
|
1949
1953
|
h("div", { className: "myt-editHint" },
|
|
1950
1954
|
tt("reader.bodyEditHint"),
|
|
1955
|
+
" · " + tf("common.charCount", { n: fmtNum(draftWords) }), // 实时字数常显(0.1.23)
|
|
1951
1956
|
autoSavedAt ? " · " + tf("reader.autoSaved", { time: autoSavedAt }) : null),
|
|
1952
1957
|
bodyErr ? h(ErrorStrip, { text: bodyErr }) : null,
|
|
1953
1958
|
bodyConflict ? h("div", { className: "myt-setActions" },
|