@musnows/scriverse 0.5.4 → 0.5.6
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/dist/ai.js +837 -96
- package/dist/ai.js.map +1 -1
- package/dist/app.js +170 -58
- package/dist/app.js.map +1 -1
- package/dist/collaboration-presence.js +18 -7
- package/dist/collaboration-presence.js.map +1 -1
- package/dist/database.js +148 -0
- package/dist/database.js.map +1 -1
- package/dist/public/ai-usage.d.ts +20 -0
- package/dist/public/ai-usage.js +75 -0
- package/dist/public/app.js +1648 -116
- package/dist/public/background-task-center.d.ts +28 -0
- package/dist/public/background-task-center.js +30 -0
- package/dist/public/index.html +109 -5
- package/dist/public/page-route.js +2 -2
- package/dist/public/race-hierarchy.js +35 -0
- package/dist/public/styles.css +289 -10
- package/dist/public/theme-init.js +2 -2
- package/dist/relationship-search.js +8 -1
- package/dist/relationship-search.js.map +1 -1
- package/dist/store.js +560 -105
- package/dist/store.js.map +1 -1
- package/dist/user-auth.js +18 -3
- package/dist/user-auth.js.map +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export type BackgroundTaskSummary = {
|
|
2
|
+
id?: unknown;
|
|
3
|
+
status?: unknown;
|
|
4
|
+
taskType?: unknown;
|
|
5
|
+
[key: string]: unknown;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export type BackgroundTaskTransition = {
|
|
9
|
+
task: BackgroundTaskSummary;
|
|
10
|
+
previousStatus: string;
|
|
11
|
+
status: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export function backgroundTaskActivityCount(
|
|
15
|
+
taskPage: { stats?: { pendingCount?: unknown; runningCount?: unknown } } | null | undefined,
|
|
16
|
+
relationshipIndex: { status?: unknown; queuedSourceCount?: unknown } | null | undefined
|
|
17
|
+
): number;
|
|
18
|
+
|
|
19
|
+
export function collectBackgroundTaskTransitions(
|
|
20
|
+
previousSnapshots: Map<string, string>,
|
|
21
|
+
tasks: BackgroundTaskSummary[] | null | undefined,
|
|
22
|
+
initialized: boolean
|
|
23
|
+
): {
|
|
24
|
+
snapshots: Map<string, string>;
|
|
25
|
+
transitions: BackgroundTaskTransition[];
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export function backgroundTaskPollDelay(activityCount: unknown, dialogOpen?: boolean): number;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
const activeTaskStatuses = new Set(["pending", "running"]);
|
|
2
|
+
const terminalTaskStatuses = new Set(["review", "completed", "partial", "expired", "cancelled"]);
|
|
3
|
+
|
|
4
|
+
export function backgroundTaskActivityCount(taskPage, relationshipIndex) {
|
|
5
|
+
const pendingCount = Number(taskPage?.stats?.pendingCount ?? 0);
|
|
6
|
+
const runningCount = Number(taskPage?.stats?.runningCount ?? 0);
|
|
7
|
+
const indexActive = ["queued", "building"].includes(String(relationshipIndex?.status))
|
|
8
|
+
|| Number(relationshipIndex?.queuedSourceCount ?? 0) > 0;
|
|
9
|
+
return Math.max(0, pendingCount) + Math.max(0, runningCount) + (indexActive ? 1 : 0);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function collectBackgroundTaskTransitions(previousSnapshots, tasks, initialized) {
|
|
13
|
+
const snapshots = new Map(previousSnapshots instanceof Map ? previousSnapshots : []);
|
|
14
|
+
const transitions = [];
|
|
15
|
+
for (const task of Array.isArray(tasks) ? tasks : []) {
|
|
16
|
+
const taskId = String(task?.id ?? "");
|
|
17
|
+
if (!taskId) continue;
|
|
18
|
+
const status = String(task?.status ?? "");
|
|
19
|
+
const previousStatus = snapshots.get(taskId);
|
|
20
|
+
if (initialized && activeTaskStatuses.has(previousStatus) && terminalTaskStatuses.has(status)) {
|
|
21
|
+
transitions.push({ task, previousStatus, status });
|
|
22
|
+
}
|
|
23
|
+
snapshots.set(taskId, status);
|
|
24
|
+
}
|
|
25
|
+
return { snapshots, transitions };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function backgroundTaskPollDelay(activityCount, dialogOpen = false) {
|
|
29
|
+
return dialogOpen || Number(activityCount) > 0 ? 5_000 : 15_000;
|
|
30
|
+
}
|
package/dist/public/index.html
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
<link rel="icon" href="/icon.svg?v=20260712" type="image/svg+xml">
|
|
11
11
|
<link rel="manifest" href="/site.webmanifest">
|
|
12
12
|
<link rel="stylesheet" href="/vendor/vditor/dist/index.css?v=3.11.2">
|
|
13
|
-
<link rel="stylesheet" href="/styles.css?v=
|
|
13
|
+
<link rel="stylesheet" href="/styles.css?v=20260727-integrated-authoring-v1">
|
|
14
14
|
</head>
|
|
15
15
|
<body class="auth-pending">
|
|
16
16
|
<section id="auth-view" class="auth-view hidden" aria-labelledby="auth-title">
|
|
@@ -88,6 +88,10 @@
|
|
|
88
88
|
<button id="account-settings-button" type="button" role="menuitem">账户设置</button>
|
|
89
89
|
<button id="logout-button" type="button" role="menuitem">退出登录</button>
|
|
90
90
|
</div>
|
|
91
|
+
<button id="background-task-button" class="topbar-icon-button background-task-button hidden" type="button" aria-label="后台任务中心" title="后台任务中心" aria-haspopup="dialog" aria-controls="background-task-dialog">
|
|
92
|
+
<svg class="topbar-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M4 7.5h16M4 12h16M4 16.5h10"/><circle cx="18" cy="16.5" r="2.5"/></svg>
|
|
93
|
+
<span id="background-task-count" class="background-task-count hidden" aria-hidden="true">0</span>
|
|
94
|
+
</button>
|
|
91
95
|
<button id="top-search-button" class="topbar-icon-button" type="button" aria-label="全文检索" title="全文检索(Command/Ctrl+F)" disabled>
|
|
92
96
|
<svg class="topbar-icon" viewBox="0 0 24 24" aria-hidden="true"><circle cx="11" cy="11" r="6.5"/><path d="m16.2 16.2 4.3 4.3"/></svg>
|
|
93
97
|
</button>
|
|
@@ -136,6 +140,7 @@
|
|
|
136
140
|
<span>作品目录</span>
|
|
137
141
|
<div class="panel-heading-actions">
|
|
138
142
|
<span id="chapter-count">0 章</span>
|
|
143
|
+
<button id="chapter-batch-button" class="chapter-batch-button" type="button">批量管理</button>
|
|
139
144
|
<button id="new-volume-button" class="add-button" type="button" aria-label="新建分卷" title="新建分卷">+</button>
|
|
140
145
|
</div>
|
|
141
146
|
</div>
|
|
@@ -167,6 +172,17 @@
|
|
|
167
172
|
<div id="platform-ai-content" class="module-content"></div>
|
|
168
173
|
</section>
|
|
169
174
|
|
|
175
|
+
<section id="platform-usage-view" class="shelf-view hidden" aria-labelledby="platform-usage-title">
|
|
176
|
+
<div class="shelf-header">
|
|
177
|
+
<div><span class="eyebrow">平台统计</span><h1 id="platform-usage-title">Token 用量</h1><p>查看工作台迄今的 AI Token 消耗、缓存命中率与各作品用量。</p></div>
|
|
178
|
+
<div class="settings-detail-actions">
|
|
179
|
+
<button id="platform-usage-return" class="ghost-button settings-parent-button" type="button">返回设置</button>
|
|
180
|
+
<button id="platform-usage-refresh" class="ghost-button" type="button">刷新</button>
|
|
181
|
+
</div>
|
|
182
|
+
</div>
|
|
183
|
+
<div id="platform-usage-content" class="module-content usage-page-content"></div>
|
|
184
|
+
</section>
|
|
185
|
+
|
|
170
186
|
<section id="settings-hub-view" class="shelf-view hidden" aria-labelledby="settings-hub-title">
|
|
171
187
|
<div class="shelf-header settings-hub-header">
|
|
172
188
|
<div><span class="eyebrow">工作台配置</span><h1 id="settings-hub-title">设置</h1><p>集中管理 AI、显示偏好、内容检索与作品导出。</p></div>
|
|
@@ -174,9 +190,12 @@
|
|
|
174
190
|
</div>
|
|
175
191
|
<div class="settings-hub-grid">
|
|
176
192
|
<button id="platform-ai-button" class="settings-hub-card hidden" type="button" data-settings-action="ai"><span class="settings-card-mark">AI</span><strong>AI 管理</strong><small>供应商、模型、上下文与全局提示词</small></button>
|
|
193
|
+
<button id="platform-usage-button" class="settings-hub-card hidden" type="button"><span class="settings-card-mark">T</span><strong>Token 用量</strong><small>总消耗、缓存命中率、每日网格与作品明细</small></button>
|
|
177
194
|
<button id="user-management-button" class="settings-hub-card hidden" type="button"><span class="settings-card-mark">人</span><strong>用户管理</strong><small>管理员、普通用户与账户状态</small></button>
|
|
178
195
|
<button id="platform-ui-settings-button" class="settings-hub-card hidden" type="button"><span class="settings-card-mark">界</span><strong>界面与分页</strong><small>设置通知位置及各模块的单页数量</small></button>
|
|
179
196
|
<button id="collaboration-button" class="settings-hub-card" type="button"><span class="settings-card-mark">协</span><strong>作品协作</strong><small>邀请注册用户共同编辑当前作品</small></button>
|
|
197
|
+
<button id="writing-progress-button" class="settings-hub-card" type="button"><span class="settings-card-mark">字</span><strong>写作目标</strong><small>每日目标、总字数目标与近 30 天趋势</small></button>
|
|
198
|
+
<button id="work-audit-button" class="settings-hub-card" type="button"><span class="settings-card-mark">录</span><strong>操作记录</strong><small>查看作品修改、操作者、对象与时间</small></button>
|
|
180
199
|
<button id="appearance-button" class="settings-hub-card" type="button" data-settings-action="appearance"><span class="settings-card-mark">Aa</span><strong>显示设置</strong><small>中文字体、等宽英文字体、字号与行距</small></button>
|
|
181
200
|
<button id="export-button" class="settings-hub-card" type="button" data-settings-action="export"><span class="settings-card-mark">MD</span><strong>导出作品</strong><small>将当前作品安全导出为 Markdown</small></button>
|
|
182
201
|
</div>
|
|
@@ -205,15 +224,16 @@
|
|
|
205
224
|
<input id="chapter-title" class="chapter-title" aria-label="章节标题" placeholder="章节标题">
|
|
206
225
|
<div class="editor-actions">
|
|
207
226
|
<span id="chapter-stats" class="chapter-stats">0 字 · v0</span>
|
|
208
|
-
<button id="insight-button" class="ghost-button" type="button">章节概览</button>
|
|
227
|
+
<button id="insight-button" class="ghost-button" type="button" aria-controls="chapter-insight-toast" aria-expanded="false">章节概览</button>
|
|
209
228
|
<button id="versions-button" class="ghost-button" type="button">版本</button>
|
|
229
|
+
<button id="chapter-annotations-button" class="ghost-button" type="button">批注与待办</button>
|
|
230
|
+
<button id="chapter-delete-button" class="danger-button" type="button">删除章节</button>
|
|
210
231
|
<button id="chapter-edit-button" class="primary-button hidden" type="button">编辑</button>
|
|
211
232
|
<button id="tidy-blank-lines-button" class="ghost-button" type="button">整理空行</button>
|
|
212
233
|
<button id="save-button" class="primary-button" type="button">保存正文</button>
|
|
213
234
|
</div>
|
|
214
235
|
</div>
|
|
215
236
|
<div class="editor-body">
|
|
216
|
-
<div id="chapter-insight" class="chapter-insight hidden"></div>
|
|
217
237
|
<div class="chapter-editor-frame">
|
|
218
238
|
<aside id="chapter-line-numbers" class="chapter-line-numbers" aria-label="正文行号,可拖拽引用多行"><div id="chapter-line-numbers-inner"></div></aside>
|
|
219
239
|
<textarea id="chapter-content" class="chapter-content" aria-label="章节正文" placeholder="在这里开始你的故事……"></textarea>
|
|
@@ -297,23 +317,41 @@
|
|
|
297
317
|
</div>
|
|
298
318
|
|
|
299
319
|
<div id="toast-region" class="toast-region" data-position="bottom-right" aria-live="polite" popover="manual"></div>
|
|
300
|
-
<div id="chapter-type-menu" class="chapter-type-menu hidden" role="menu" aria-label="
|
|
320
|
+
<div id="chapter-type-menu" class="chapter-type-menu hidden" role="menu" aria-label="章节操作" data-testid="chapter-type-menu">
|
|
301
321
|
<strong>标记章节</strong>
|
|
302
322
|
<div>
|
|
303
323
|
<button type="button" role="menuitemradio" data-chapter-type="正文">正文</button>
|
|
304
324
|
<button type="button" role="menuitemradio" data-chapter-type="设定">设定</button>
|
|
305
325
|
<button type="button" role="menuitemradio" data-chapter-type="作者的话">作者的话</button>
|
|
306
326
|
<button type="button" role="menuitemradio" data-chapter-type="其他">其他</button>
|
|
327
|
+
<button class="danger-button" type="button" role="menuitem" data-delete-chapter>删除章节</button>
|
|
307
328
|
</div>
|
|
308
329
|
</div>
|
|
309
330
|
<div id="line-citation-menu" class="line-citation-menu hidden" role="menu" aria-label="正文行引用操作">
|
|
310
331
|
<strong id="line-citation-label">已选择正文</strong>
|
|
311
332
|
<button id="add-line-citation" type="button" role="menuitem">添加到创作助手引用</button>
|
|
333
|
+
<button id="add-line-annotation" type="button" role="menuitem">添加批注</button>
|
|
334
|
+
<button id="add-line-todo" type="button" role="menuitem">添加待办</button>
|
|
312
335
|
</div>
|
|
313
336
|
<input id="new-import-file" class="hidden" type="file" accept=".txt,.docx">
|
|
314
337
|
<input id="cover-file" class="hidden" type="file" accept="image/png,image/jpeg,image/webp">
|
|
315
338
|
<input id="avatar-file" class="hidden" type="file" accept="image/png,image/jpeg,image/webp">
|
|
316
339
|
|
|
340
|
+
<dialog id="background-task-dialog" class="dialog wide-dialog background-task-dialog" aria-labelledby="background-task-dialog-title">
|
|
341
|
+
<form method="dialog">
|
|
342
|
+
<div class="dialog-header">
|
|
343
|
+
<div><span class="eyebrow">全局进度</span><h2 id="background-task-dialog-title">后台任务中心</h2><p id="background-task-dialog-meta" class="dialog-header-meta">当前作品的分析任务与索引队列</p></div>
|
|
344
|
+
<button class="dialog-close" value="cancel" aria-label="关闭后台任务中心" type="submit">×</button>
|
|
345
|
+
</div>
|
|
346
|
+
<div id="background-task-content" class="background-task-content" role="region" aria-label="后台任务状态"></div>
|
|
347
|
+
<div class="dialog-actions background-task-actions">
|
|
348
|
+
<button id="background-task-open-analysis" class="ghost-button" type="button">前往 AI 分析中心</button>
|
|
349
|
+
<button id="background-task-refresh" class="primary-button" type="button">刷新状态</button>
|
|
350
|
+
<button class="ghost-button" value="cancel" type="submit">关闭</button>
|
|
351
|
+
</div>
|
|
352
|
+
</form>
|
|
353
|
+
</dialog>
|
|
354
|
+
|
|
317
355
|
<dialog id="onboarding-dialog" class="onboarding-dialog" aria-labelledby="onboarding-dialog-title" aria-describedby="onboarding-dialog-description" data-testid="first-use-onboarding">
|
|
318
356
|
<div id="onboarding-spotlight" class="onboarding-spotlight" aria-hidden="true"></div>
|
|
319
357
|
<section id="onboarding-popover" class="onboarding-popover" data-placement="bottom">
|
|
@@ -351,6 +389,30 @@
|
|
|
351
389
|
</form>
|
|
352
390
|
</dialog>
|
|
353
391
|
|
|
392
|
+
<dialog id="chapter-batch-dialog" class="dialog chapter-batch-dialog" aria-labelledby="chapter-batch-title">
|
|
393
|
+
<form id="chapter-batch-form">
|
|
394
|
+
<div class="dialog-header">
|
|
395
|
+
<div><span class="eyebrow">正文工具</span><h2 id="chapter-batch-title">章节批量管理</h2><p class="dialog-header-meta">选择多个章节后统一移动、修改属性或软删除。</p></div>
|
|
396
|
+
<button id="chapter-batch-close" class="dialog-close" type="button" aria-label="关闭章节批量管理">×</button>
|
|
397
|
+
</div>
|
|
398
|
+
<div class="chapter-batch-toolbar">
|
|
399
|
+
<button id="chapter-batch-select-all" class="ghost-button" type="button">全选</button>
|
|
400
|
+
<button id="chapter-batch-clear" class="ghost-button" type="button">清空</button>
|
|
401
|
+
<output id="chapter-batch-count">已选择 0 章</output>
|
|
402
|
+
</div>
|
|
403
|
+
<div id="chapter-batch-list" class="chapter-batch-list"></div>
|
|
404
|
+
<div class="chapter-batch-controls">
|
|
405
|
+
<label>批量操作<select id="chapter-batch-action"><option value="move">移动到分卷</option><option value="setType">修改章节类型</option><option value="exclude">排除 AI 分析</option><option value="include">纳入 AI 分析</option><option value="delete">软删除章节</option></select></label>
|
|
406
|
+
<label id="chapter-batch-volume-field">目标分卷<select id="chapter-batch-volume"></select></label>
|
|
407
|
+
<label id="chapter-batch-type-field" class="hidden">章节类型<select id="chapter-batch-type"><option value="正文">正文</option><option value="设定">设定</option><option value="作者的话">作者的话</option><option value="其他">其他</option></select></label>
|
|
408
|
+
</div>
|
|
409
|
+
<div class="dialog-actions">
|
|
410
|
+
<button id="chapter-batch-cancel" class="ghost-button" type="button">取消</button>
|
|
411
|
+
<button id="chapter-batch-apply" class="primary-button" type="submit" disabled>应用到所选章节</button>
|
|
412
|
+
</div>
|
|
413
|
+
</form>
|
|
414
|
+
</dialog>
|
|
415
|
+
|
|
354
416
|
<dialog id="import-mode-dialog" class="dialog import-mode-dialog" aria-labelledby="import-mode-dialog-title" aria-describedby="import-mode-dialog-description" data-testid="import-mode-dialog">
|
|
355
417
|
<form method="dialog">
|
|
356
418
|
<div class="dialog-header">
|
|
@@ -577,6 +639,17 @@
|
|
|
577
639
|
</div>
|
|
578
640
|
</dialog>
|
|
579
641
|
|
|
642
|
+
<dialog id="chapter-recycle-bin-dialog" class="dialog wide-dialog" aria-labelledby="chapter-recycle-bin-title" aria-describedby="chapter-recycle-bin-description">
|
|
643
|
+
<div class="dialog-header">
|
|
644
|
+
<div><span class="eyebrow">正文安全</span><h2 id="chapter-recycle-bin-title">章节回收站</h2></div>
|
|
645
|
+
<button id="chapter-recycle-bin-close" class="dialog-close" aria-label="关闭章节回收站" type="button">×</button>
|
|
646
|
+
</div>
|
|
647
|
+
<div class="import-history-body">
|
|
648
|
+
<p id="chapter-recycle-bin-description" class="import-history-note">软删除的章节会保留正文、版本和关联资料。恢复后章节将重新出现在原分卷中。</p>
|
|
649
|
+
<div id="chapter-recycle-bin-list" class="entity-history-list" aria-live="polite"></div>
|
|
650
|
+
</div>
|
|
651
|
+
</dialog>
|
|
652
|
+
|
|
580
653
|
<dialog id="users-dialog" class="dialog wide-dialog" aria-labelledby="users-dialog-title">
|
|
581
654
|
<div class="dialog-header"><div><span class="eyebrow">系统管理员</span><h2 id="users-dialog-title">用户管理</h2></div><div class="settings-dialog-header-actions"><button id="users-settings-return" class="ghost-button settings-parent-button" type="button">返回设置</button><button id="users-dialog-close" class="dialog-close" aria-label="关闭" type="button">×</button></div></div>
|
|
582
655
|
<div class="access-dialog-body">
|
|
@@ -584,6 +657,30 @@
|
|
|
584
657
|
</div>
|
|
585
658
|
</dialog>
|
|
586
659
|
|
|
660
|
+
<dialog id="chapter-annotations-dialog" class="dialog wide-dialog chapter-annotations-dialog" aria-labelledby="chapter-annotations-title">
|
|
661
|
+
<div class="dialog-header"><div><span class="eyebrow">正文协作</span><h2 id="chapter-annotations-title">批注与待办</h2><p id="chapter-annotations-meta" class="dialog-header-meta">选择正文行后可添加批注或待办。</p></div><button id="chapter-annotations-close" class="dialog-close" aria-label="关闭批注与待办" type="button">×</button></div>
|
|
662
|
+
<div id="chapter-annotations-list" class="chapter-annotations-list"></div>
|
|
663
|
+
<div class="dialog-actions"><button id="chapter-annotations-refresh" class="ghost-button" type="button">刷新</button><button id="chapter-annotations-done" class="primary-button" type="button">完成</button></div>
|
|
664
|
+
</dialog>
|
|
665
|
+
|
|
666
|
+
<dialog id="writing-progress-dialog" class="dialog wide-dialog writing-progress-dialog" aria-labelledby="writing-progress-title">
|
|
667
|
+
<form id="writing-goal-form">
|
|
668
|
+
<div class="dialog-header"><div><span class="eyebrow">创作节奏</span><h2 id="writing-progress-title">写作目标与字数趋势</h2><p class="dialog-header-meta">趋势根据正文版本历史重建,软删除章节不会继续计入。</p></div><button id="writing-progress-close" class="dialog-close" aria-label="关闭写作目标" type="button">×</button></div>
|
|
669
|
+
<div class="writing-progress-body">
|
|
670
|
+
<div class="writing-progress-stats"><article><small>当前总字数</small><strong id="writing-current-words">0</strong></article><article><small>今日新增</small><strong id="writing-today-words">0</strong></article><article><small>每日目标完成</small><strong id="writing-daily-completion">0%</strong></article><article><small>总目标完成</small><strong id="writing-total-completion">0%</strong></article></div>
|
|
671
|
+
<div id="writing-trend-chart" class="writing-trend-chart" role="img" aria-label="近 30 天作品字数趋势"></div>
|
|
672
|
+
<div class="writing-goal-fields"><label>每日目标字数<input id="writing-daily-goal" type="number" min="0" max="1000000" required></label><label>总字数目标<input id="writing-total-goal" type="number" min="0" max="100000000" required></label><label>计划完成日期<input id="writing-deadline" type="date"></label></div>
|
|
673
|
+
</div>
|
|
674
|
+
<div class="dialog-actions"><button id="writing-progress-refresh" class="ghost-button" type="button">刷新趋势</button><button id="writing-goal-save" class="primary-button" type="submit">保存目标</button></div>
|
|
675
|
+
</form>
|
|
676
|
+
</dialog>
|
|
677
|
+
|
|
678
|
+
<dialog id="work-audit-dialog" class="dialog wide-dialog work-audit-dialog" aria-labelledby="work-audit-title">
|
|
679
|
+
<div class="dialog-header"><div><span class="eyebrow">作品安全</span><h2 id="work-audit-title">操作记录</h2><p class="dialog-header-meta">按时间倒序展示当前作品的写入与管理操作。</p></div><div class="settings-dialog-header-actions"><button id="work-audit-settings-return" class="ghost-button settings-parent-button" type="button">返回设置</button><button id="work-audit-close" class="dialog-close" aria-label="关闭操作记录" type="button">×</button></div></div>
|
|
680
|
+
<div id="work-audit-list" class="work-audit-list"></div>
|
|
681
|
+
<div class="dialog-actions"><button id="work-audit-refresh" class="ghost-button" type="button">刷新</button><button id="work-audit-load-more" class="primary-button hidden" type="button">加载更多</button></div>
|
|
682
|
+
</dialog>
|
|
683
|
+
|
|
587
684
|
<dialog id="platform-ui-settings-dialog" class="dialog" aria-labelledby="platform-ui-settings-title">
|
|
588
685
|
<div class="dialog-header"><div><span class="eyebrow">系统管理员</span><h2 id="platform-ui-settings-title">界面与分页</h2></div><div class="settings-dialog-header-actions"><button id="platform-ui-settings-return" class="ghost-button settings-parent-button" type="button">返回设置</button><button id="platform-ui-settings-close" class="dialog-close" aria-label="关闭" type="button">×</button></div></div>
|
|
589
686
|
<form id="platform-ui-settings-form">
|
|
@@ -594,7 +691,14 @@
|
|
|
594
691
|
<legend>各模块单页数量</legend>
|
|
595
692
|
<small>每个模块独立设置,允许 10–100 条;默认均为 30 条。</small>
|
|
596
693
|
<div class="pagination-settings-grid">
|
|
694
|
+
<label>设定库<input id="page-size-settings" name="pageSizeSettings" type="number" min="10" max="100" step="1" required aria-label="设定库单页数量"></label>
|
|
597
695
|
<label>角色列表<input id="page-size-characters" name="pageSizeCharacters" type="number" min="10" max="100" step="1" required aria-label="角色列表单页数量"></label>
|
|
696
|
+
<label>种族列表<input id="page-size-races" name="pageSizeRaces" type="number" min="10" max="100" step="1" required aria-label="种族列表单页数量"></label>
|
|
697
|
+
<label>组织列表<input id="page-size-organizations" name="pageSizeOrganizations" type="number" min="10" max="100" step="1" required aria-label="组织列表单页数量"></label>
|
|
698
|
+
<label>时间线事件<input id="page-size-timeline" name="pageSizeTimeline" type="number" min="10" max="100" step="1" required aria-label="时间线事件单页数量"></label>
|
|
699
|
+
<label>大纲与伏笔<input id="page-size-outlines" name="pageSizeOutlines" type="number" min="10" max="100" step="1" required aria-label="大纲与伏笔单页数量"></label>
|
|
700
|
+
<label>人物关系列表<input id="page-size-relationships" name="pageSizeRelationships" type="number" min="10" max="100" step="1" required aria-label="人物关系列表单页数量"></label>
|
|
701
|
+
<label>审核列表<input id="page-size-reviews" name="pageSizeReviews" type="number" min="10" max="100" step="1" required aria-label="审核列表单页数量"></label>
|
|
598
702
|
<label>AI 分析任务<input id="page-size-analysis-tasks" name="pageSizeAnalysisTasks" type="number" min="10" max="100" step="1" required aria-label="AI 分析任务单页数量"></label>
|
|
599
703
|
<label>正文导入历史<input id="page-size-file-versions" name="pageSizeFileVersions" type="number" min="10" max="100" step="1" required aria-label="正文导入历史单页数量"></label>
|
|
600
704
|
</div>
|
|
@@ -751,6 +855,6 @@
|
|
|
751
855
|
<div id="auth-loading" class="auth-loading" role="status" aria-label="正在载入工作台"></div>
|
|
752
856
|
<script id="vditorIconScript" src="/vendor/vditor/dist/js/icons/ant.js?v=3.11.2"></script>
|
|
753
857
|
<script src="/vendor/vditor/dist/index.min.js?v=3.11.2"></script>
|
|
754
|
-
<script type="module" src="/app.js?v=
|
|
858
|
+
<script type="module" src="/app.js?v=20260727-integrated-authoring-v1"></script>
|
|
755
859
|
</body>
|
|
756
860
|
</html>
|
|
@@ -51,7 +51,7 @@ export function serializePageRoute(route = {}) {
|
|
|
51
51
|
} else if (view === "welcome" && workId) {
|
|
52
52
|
params.set("view", "welcome");
|
|
53
53
|
params.set("work", workId);
|
|
54
|
-
} else if (view === "settings" || view === "platform-ai") {
|
|
54
|
+
} else if (view === "settings" || view === "platform-ai" || view === "platform-usage") {
|
|
55
55
|
params.set("view", view);
|
|
56
56
|
if (workId) params.set("work", workId);
|
|
57
57
|
appendReturnContext(params, route);
|
|
@@ -85,7 +85,7 @@ export function parsePageRoute(hash = "") {
|
|
|
85
85
|
return { view, workId, entity, entityId: entityId || null, entityMode };
|
|
86
86
|
}
|
|
87
87
|
if (view === "welcome" && workId) return { view, workId };
|
|
88
|
-
if (view === "settings" || view === "platform-ai") {
|
|
88
|
+
if (view === "settings" || view === "platform-ai" || view === "platform-usage") {
|
|
89
89
|
const route = { view, workId: workId || null };
|
|
90
90
|
const returnView = value(params, "from");
|
|
91
91
|
if (returnViewSet.has(returnView)) route.returnView = returnView;
|
|
@@ -83,3 +83,38 @@ export function buildRaceForest(races) {
|
|
|
83
83
|
};
|
|
84
84
|
return sort(roots);
|
|
85
85
|
}
|
|
86
|
+
|
|
87
|
+
export function paginateRaceForest(races, page, limit) {
|
|
88
|
+
const safeLimit = Math.max(1, Math.floor(Number(limit) || 1));
|
|
89
|
+
const forest = buildRaceForest(races);
|
|
90
|
+
const pages = [];
|
|
91
|
+
let currentItems = [];
|
|
92
|
+
let currentItemCount = 0;
|
|
93
|
+
const subtreeSize = (node) => 1 + node.children.reduce((total, child) => total + subtreeSize(child), 0);
|
|
94
|
+
|
|
95
|
+
for (const root of forest) {
|
|
96
|
+
const rootItemCount = subtreeSize(root);
|
|
97
|
+
if (currentItems.length && currentItemCount + rootItemCount > safeLimit) {
|
|
98
|
+
pages.push({ items: currentItems, itemCount: currentItemCount });
|
|
99
|
+
currentItems = [];
|
|
100
|
+
currentItemCount = 0;
|
|
101
|
+
}
|
|
102
|
+
currentItems.push(root);
|
|
103
|
+
currentItemCount += rootItemCount;
|
|
104
|
+
}
|
|
105
|
+
if (currentItems.length || !pages.length) pages.push({ items: currentItems, itemCount: currentItemCount });
|
|
106
|
+
|
|
107
|
+
const pageCount = pages.length;
|
|
108
|
+
const safePage = Math.min(Math.max(1, Number(page) || 1), pageCount);
|
|
109
|
+
const selectedPage = pages[safePage - 1];
|
|
110
|
+
return {
|
|
111
|
+
items: selectedPage.items,
|
|
112
|
+
itemCount: selectedPage.itemCount,
|
|
113
|
+
page: safePage,
|
|
114
|
+
limit: safeLimit,
|
|
115
|
+
total: races.length,
|
|
116
|
+
pageCount,
|
|
117
|
+
hasMore: safePage < pageCount,
|
|
118
|
+
nextPage: safePage < pageCount ? safePage + 1 : null
|
|
119
|
+
};
|
|
120
|
+
}
|