@waterwx/dsh-novel-forge 1.2.1-alpha → 1.3.0-alpha
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 +4 -5
- package/lib/client.js +2470 -858
- package/lib/index.js +2155 -388
- package/lib/types/action-guard.d.ts +1 -1
- package/lib/types/assets.d.ts +7 -7
- package/lib/types/client/api.d.ts +31 -1
- package/lib/types/client/llmLive.d.ts +12 -14
- package/lib/types/client/panel/LiveFeedLog.d.ts +5 -0
- package/lib/types/client/panel/ModelManager.d.ts +2 -2
- package/lib/types/client/panel/PromptSlotsView.d.ts +11 -0
- package/lib/types/client/panel/TensionView.d.ts +14 -0
- package/lib/types/client/panel/TimelineView.d.ts +14 -0
- package/lib/types/engine.d.ts +40 -2
- package/lib/types/index.d.ts +4 -0
- package/lib/types/llm-live.d.ts +65 -34
- package/lib/types/llm-retry.d.ts +38 -0
- package/lib/types/market-radar-sources.d.ts +1 -1
- package/lib/types/prompt-slots.d.ts +57 -0
- package/lib/types/prompting.d.ts +2 -2
- package/lib/types/protocol.d.ts +283 -3
- package/lib/types/snapshots.d.ts +46 -0
- package/lib/types/stage-contract.d.ts +1 -1
- package/lib/types/tension.d.ts +65 -0
- package/lib/types/timeline.d.ts +37 -0
- package/package.json +3 -2
- package/src/action-guard.ts +1 -1
- package/src/assets.ts +300 -268
- package/src/assistant.ts +45 -29
- package/src/client/api.ts +76 -2
- package/src/client/llmLive.ts +26 -16
- package/src/client/panel/AssetsTab.tsx +2 -2
- package/src/client/panel/LiveFeedLog.tsx +204 -67
- package/src/client/panel/ModelManager.tsx +2 -2
- package/src/client/panel/NovelPanel.tsx +127 -13
- package/src/client/panel/PromptSlotsView.tsx +97 -0
- package/src/client/panel/SettingsView.tsx +35 -0
- package/src/client/panel/TensionView.tsx +196 -0
- package/src/client/panel/TimelineView.tsx +192 -0
- package/src/engine.ts +549 -108
- package/src/index.ts +12 -0
- package/src/llm-live.ts +260 -68
- package/src/llm-retry.ts +77 -0
- package/src/market-radar-sources.ts +173 -173
- package/src/prompt-slots.ts +125 -0
- package/src/prompting.ts +8 -8
- package/src/protocol.ts +314 -3
- package/src/routes.ts +325 -6
- package/src/run.ts +4 -0
- package/src/snapshots.ts +174 -0
- package/src/stage-contract.ts +189 -189
- package/src/tension.ts +240 -0
- package/src/timeline.ts +159 -0
package/lib/client.js
CHANGED
|
@@ -36,6 +36,18 @@ window.__ModuleLoader__.load({
|
|
|
36
36
|
director: "/api/dsh-novel-forge/director",
|
|
37
37
|
directorTodos: "/api/dsh-novel-forge/director/todos",
|
|
38
38
|
llmLive: "/api/dsh-novel-forge/llm-live/stream",
|
|
39
|
+
/** 查看某次调用实际发送的 Prompt(按 sessionId)。 */
|
|
40
|
+
llmPrompt: "/api/dsh-novel-forge/llm-live/prompt",
|
|
41
|
+
/** 清零本次运行的用量账本。 */
|
|
42
|
+
usageReset: "/api/dsh-novel-forge/usage/reset",
|
|
43
|
+
/** 章节历史版本(快照)。 */
|
|
44
|
+
snapshot: "/api/dsh-novel-forge/snapshot",
|
|
45
|
+
/** 张力曲线(GET 数据 / POST 设置)。 */
|
|
46
|
+
tension: "/api/dsh-novel-forge/tension",
|
|
47
|
+
/** 提示词槽位(GET 列表 / POST 写入)。 */
|
|
48
|
+
promptSlots: "/api/dsh-novel-forge/prompt-slots",
|
|
49
|
+
/** 故事时间线(GET 列表 / POST 操作)。 */
|
|
50
|
+
timeline: "/api/dsh-novel-forge/timeline",
|
|
39
51
|
marketRadar: "/api/dsh-novel-forge/market-radar",
|
|
40
52
|
marketRadarScan: "/api/dsh-novel-forge/market-radar/scan",
|
|
41
53
|
marketRadarApply: "/api/dsh-novel-forge/market-radar/apply",
|
|
@@ -220,6 +232,24 @@ window.__ModuleLoader__.load({
|
|
|
220
232
|
]
|
|
221
233
|
}
|
|
222
234
|
];
|
|
235
|
+
/** 导出范围全集(宿主校验用;顺序即 UI 展示顺序)。 */
|
|
236
|
+
const EXPORT_SCOPE_VALUES = [
|
|
237
|
+
"book",
|
|
238
|
+
"settings",
|
|
239
|
+
"plan",
|
|
240
|
+
"characters",
|
|
241
|
+
"review",
|
|
242
|
+
"project"
|
|
243
|
+
];
|
|
244
|
+
/** 导出范围的中文标签。 */
|
|
245
|
+
const EXPORT_SCOPE_LABELS = {
|
|
246
|
+
book: "整本正文",
|
|
247
|
+
settings: "项目设定",
|
|
248
|
+
plan: "规划(卷/章节)",
|
|
249
|
+
characters: "角色",
|
|
250
|
+
review: "质检记录",
|
|
251
|
+
project: "项目备份 JSON"
|
|
252
|
+
};
|
|
223
253
|
//#endregion
|
|
224
254
|
//#region src/client/api.ts
|
|
225
255
|
/**
|
|
@@ -333,8 +363,11 @@ window.__ModuleLoader__.load({
|
|
|
333
363
|
async foreshadow(req) {
|
|
334
364
|
return postJson(NOVEL_API.foreshadow, req);
|
|
335
365
|
}
|
|
336
|
-
async exportBook(format) {
|
|
337
|
-
return postJson(NOVEL_API.exportBook, {
|
|
366
|
+
async exportBook(format, scope = "book") {
|
|
367
|
+
return postJson(NOVEL_API.exportBook, {
|
|
368
|
+
format,
|
|
369
|
+
scope
|
|
370
|
+
});
|
|
338
371
|
}
|
|
339
372
|
async chapter(no) {
|
|
340
373
|
return readJson(await fetch(withBookId(`${NOVEL_API.chapter}?no=${no}`)));
|
|
@@ -750,6 +783,90 @@ window.__ModuleLoader__.load({
|
|
|
750
783
|
}
|
|
751
784
|
}
|
|
752
785
|
}
|
|
786
|
+
/** 张力曲线:数据 + 规则核对。 */
|
|
787
|
+
async tension() {
|
|
788
|
+
return readJson(await fetch(withBookId(NOVEL_API.tension)));
|
|
789
|
+
}
|
|
790
|
+
/** 设置张力曲线预设。 */
|
|
791
|
+
async tensionPreset(preset) {
|
|
792
|
+
await postJson(NOVEL_API.tension, {
|
|
793
|
+
op: "preset",
|
|
794
|
+
preset
|
|
795
|
+
});
|
|
796
|
+
}
|
|
797
|
+
/** 设置/清除某一章的目标张力。 */
|
|
798
|
+
async tensionSet(chapterNo, tension) {
|
|
799
|
+
await postJson(NOVEL_API.tension, {
|
|
800
|
+
op: "set",
|
|
801
|
+
chapterNo,
|
|
802
|
+
tension
|
|
803
|
+
});
|
|
804
|
+
}
|
|
805
|
+
/** 提示词槽位:列表。 */
|
|
806
|
+
async promptSlots() {
|
|
807
|
+
return readJson(await fetch(withBookId(NOVEL_API.promptSlots)));
|
|
808
|
+
}
|
|
809
|
+
/** 写入一个提示词槽位(空串 = 清空)。 */
|
|
810
|
+
async promptSlotSet(id, value) {
|
|
811
|
+
await postJson(NOVEL_API.promptSlots, {
|
|
812
|
+
id,
|
|
813
|
+
value
|
|
814
|
+
});
|
|
815
|
+
}
|
|
816
|
+
/** 故事时间线:列表(含规则初筛问题)。 */
|
|
817
|
+
async timeline() {
|
|
818
|
+
return readJson(await fetch(withBookId(NOVEL_API.timeline)));
|
|
819
|
+
}
|
|
820
|
+
/** 抽取某一章的时间线事件。 */
|
|
821
|
+
async timelineExtract(chapterNo) {
|
|
822
|
+
return postJson(NOVEL_API.timeline, {
|
|
823
|
+
op: "extract",
|
|
824
|
+
chapterNo
|
|
825
|
+
});
|
|
826
|
+
}
|
|
827
|
+
/** 检查时间线矛盾(规则初筛 + AI 复核)。 */
|
|
828
|
+
async timelineCheck() {
|
|
829
|
+
return postJson(NOVEL_API.timeline, { op: "check" });
|
|
830
|
+
}
|
|
831
|
+
/** 手工修正一条时间线事件。 */
|
|
832
|
+
async timelineUpdate(event) {
|
|
833
|
+
await postJson(NOVEL_API.timeline, {
|
|
834
|
+
op: "update",
|
|
835
|
+
event
|
|
836
|
+
});
|
|
837
|
+
}
|
|
838
|
+
/** 删除一条时间线事件。 */
|
|
839
|
+
async timelineRemove(id) {
|
|
840
|
+
await postJson(NOVEL_API.timeline, {
|
|
841
|
+
op: "remove",
|
|
842
|
+
id
|
|
843
|
+
});
|
|
844
|
+
}
|
|
845
|
+
/** 章节历史版本列表。 */
|
|
846
|
+
async snapshots() {
|
|
847
|
+
return readJson(await fetch(withBookId(NOVEL_API.snapshot)));
|
|
848
|
+
}
|
|
849
|
+
/** 回滚到某个历史版本。 */
|
|
850
|
+
async snapshotRestore(id) {
|
|
851
|
+
await postJson(NOVEL_API.snapshot, {
|
|
852
|
+
op: "restore",
|
|
853
|
+
id
|
|
854
|
+
});
|
|
855
|
+
}
|
|
856
|
+
/** 给某章手工存档。 */
|
|
857
|
+
async snapshotCreate(chapterNo) {
|
|
858
|
+
await postJson(NOVEL_API.snapshot, {
|
|
859
|
+
op: "create",
|
|
860
|
+
chapterNo
|
|
861
|
+
});
|
|
862
|
+
}
|
|
863
|
+
/** 删除一个历史版本。 */
|
|
864
|
+
async snapshotRemove(id) {
|
|
865
|
+
await postJson(NOVEL_API.snapshot, {
|
|
866
|
+
op: "remove",
|
|
867
|
+
id
|
|
868
|
+
});
|
|
869
|
+
}
|
|
753
870
|
/** Load the persisted assistant conversation. */
|
|
754
871
|
async assistantHistory() {
|
|
755
872
|
return (await readJson(await fetch(withBookId(NOVEL_API.assistantHistory)))).messages;
|
|
@@ -36466,491 +36583,491 @@ window.__ModuleLoader__.load({
|
|
|
36466
36583
|
document.head.appendChild(tag);
|
|
36467
36584
|
}
|
|
36468
36585
|
var panel_module_css_default = {
|
|
36469
|
-
"
|
|
36470
|
-
"
|
|
36471
|
-
"
|
|
36472
|
-
"
|
|
36586
|
+
"readerSeg": "jbF1yq_readerSeg",
|
|
36587
|
+
"chWorkAsideBody": "jbF1yq_chWorkAsideBody",
|
|
36588
|
+
"wfColB": "jbF1yq_wfColB",
|
|
36589
|
+
"subPageBack": "jbF1yq_subPageBack",
|
|
36590
|
+
"wfProgRest": "jbF1yq_wfProgRest",
|
|
36591
|
+
"bookCardCoverFallback": "jbF1yq_bookCardCoverFallback",
|
|
36592
|
+
"dropzoneActive": "jbF1yq_dropzoneActive",
|
|
36593
|
+
"pillNavPill": "jbF1yq_pillNavPill",
|
|
36594
|
+
"wfAct": "jbF1yq_wfAct",
|
|
36595
|
+
"diffTagOld": "jbF1yq_diffTagOld",
|
|
36596
|
+
"panelHead": "jbF1yq_panelHead",
|
|
36597
|
+
"importField": "jbF1yq_importField",
|
|
36598
|
+
"coverPreview": "jbF1yq_coverPreview",
|
|
36599
|
+
"ideaCandidate": "jbF1yq_ideaCandidate",
|
|
36600
|
+
"drawerHead": "jbF1yq_drawerHead",
|
|
36601
|
+
"coverPlaceholder": "jbF1yq_coverPlaceholder",
|
|
36602
|
+
"planTree": "jbF1yq_planTree",
|
|
36603
|
+
"progressLine": "jbF1yq_progressLine",
|
|
36604
|
+
"authorNavBtn": "jbF1yq_authorNavBtn",
|
|
36473
36605
|
"planBeats": "jbF1yq_planBeats",
|
|
36474
|
-
"
|
|
36475
|
-
"
|
|
36476
|
-
"
|
|
36477
|
-
"
|
|
36478
|
-
"lfDot": "jbF1yq_lfDot",
|
|
36479
|
-
"dropzone": "jbF1yq_dropzone",
|
|
36480
|
-
"navGroup": "jbF1yq_navGroup",
|
|
36481
|
-
"readerText": "jbF1yq_readerText",
|
|
36606
|
+
"nfFadeIn": "jbF1yq_nfFadeIn",
|
|
36607
|
+
"nfSkeletonShimmer": "jbF1yq_nfSkeletonShimmer",
|
|
36608
|
+
"switch": "jbF1yq_switch",
|
|
36609
|
+
"bookCard": "jbF1yq_bookCard",
|
|
36482
36610
|
"progress": "jbF1yq_progress",
|
|
36483
|
-
"
|
|
36484
|
-
"
|
|
36485
|
-
"
|
|
36486
|
-
"
|
|
36487
|
-
"
|
|
36488
|
-
"
|
|
36489
|
-
"
|
|
36490
|
-
"
|
|
36491
|
-
"adaptRuleRow": "jbF1yq_adaptRuleRow",
|
|
36492
|
-
"wfCmd": "jbF1yq_wfCmd",
|
|
36493
|
-
"adaptProposal": "jbF1yq_adaptProposal",
|
|
36494
|
-
"nfToastTick": "jbF1yq_nfToastTick",
|
|
36495
|
-
"planTree": "jbF1yq_planTree",
|
|
36496
|
-
"adaptOutlinePre": "jbF1yq_adaptOutlinePre",
|
|
36497
|
-
"wsPreviewText": "jbF1yq_wsPreviewText",
|
|
36498
|
-
"planTreeVol": "jbF1yq_planTreeVol",
|
|
36499
|
-
"wfRsName": "jbF1yq_wfRsName",
|
|
36611
|
+
"readerGroupCount": "jbF1yq_readerGroupCount",
|
|
36612
|
+
"assetCard": "jbF1yq_assetCard",
|
|
36613
|
+
"t2RailBtn": "jbF1yq_t2RailBtn",
|
|
36614
|
+
"badgePending": "jbF1yq_badgePending",
|
|
36615
|
+
"adaptImpacts": "jbF1yq_adaptImpacts",
|
|
36616
|
+
"dropzoneIcon": "jbF1yq_dropzoneIcon",
|
|
36617
|
+
"wfStRev": "jbF1yq_wfStRev",
|
|
36618
|
+
"navGroupLabel": "jbF1yq_navGroupLabel",
|
|
36500
36619
|
"contentDrawer": "jbF1yq_contentDrawer",
|
|
36501
|
-
"
|
|
36502
|
-
"
|
|
36503
|
-
"
|
|
36620
|
+
"chatRole": "jbF1yq_chatRole",
|
|
36621
|
+
"chapterPreview": "jbF1yq_chapterPreview",
|
|
36622
|
+
"readerItemTitle": "jbF1yq_readerItemTitle",
|
|
36623
|
+
"importHint": "jbF1yq_importHint",
|
|
36624
|
+
"planMaster": "jbF1yq_planMaster",
|
|
36625
|
+
"planTreeRowNo": "jbF1yq_planTreeRowNo",
|
|
36626
|
+
"navTab": "jbF1yq_navTab",
|
|
36627
|
+
"settingsDrawer": "jbF1yq_settingsDrawer",
|
|
36504
36628
|
"readerItemBadge": "jbF1yq_readerItemBadge",
|
|
36505
|
-
"
|
|
36506
|
-
"
|
|
36629
|
+
"readerPara": "jbF1yq_readerPara",
|
|
36630
|
+
"diffText": "jbF1yq_diffText",
|
|
36631
|
+
"outlineVolSummary": "jbF1yq_outlineVolSummary",
|
|
36632
|
+
"wfTool": "jbF1yq_wfTool",
|
|
36633
|
+
"wfFeedList": "jbF1yq_wfFeedList",
|
|
36634
|
+
"subPageHead": "jbF1yq_subPageHead",
|
|
36635
|
+
"iconButton": "jbF1yq_iconButton",
|
|
36636
|
+
"wfDot": "jbF1yq_wfDot",
|
|
36637
|
+
"drawerTitle": "jbF1yq_drawerTitle",
|
|
36638
|
+
"brandText": "jbF1yq_brandText",
|
|
36639
|
+
"wfOpsBtnMain": "jbF1yq_wfOpsBtnMain",
|
|
36640
|
+
"onlyChanges": "jbF1yq_onlyChanges",
|
|
36641
|
+
"wsPreviewText": "jbF1yq_wsPreviewText",
|
|
36507
36642
|
"readerItemNo": "jbF1yq_readerItemNo",
|
|
36508
|
-
"
|
|
36509
|
-
"
|
|
36510
|
-
"
|
|
36511
|
-
"
|
|
36643
|
+
"nfToastOut": "jbF1yq_nfToastOut",
|
|
36644
|
+
"cmdEmpty": "jbF1yq_cmdEmpty",
|
|
36645
|
+
"navAboutRow": "jbF1yq_navAboutRow",
|
|
36646
|
+
"assistantFloatBody": "jbF1yq_assistantFloatBody",
|
|
36647
|
+
"ideaToggle": "jbF1yq_ideaToggle",
|
|
36648
|
+
"bookCardActions": "jbF1yq_bookCardActions",
|
|
36649
|
+
"wfPreview": "jbF1yq_wfPreview",
|
|
36650
|
+
"importFileInfo": "jbF1yq_importFileInfo",
|
|
36651
|
+
"chWorkText": "jbF1yq_chWorkText",
|
|
36652
|
+
"chWorkSideHead": "jbF1yq_chWorkSideHead",
|
|
36653
|
+
"bookCardMetaRow": "jbF1yq_bookCardMetaRow",
|
|
36654
|
+
"diffNew": "jbF1yq_diffNew",
|
|
36655
|
+
"importModalActions": "jbF1yq_importModalActions",
|
|
36656
|
+
"adaptProposal": "jbF1yq_adaptProposal",
|
|
36657
|
+
"badgeError": "jbF1yq_badgeError",
|
|
36512
36658
|
"emptyStateTitle": "jbF1yq_emptyStateTitle",
|
|
36513
|
-
"
|
|
36514
|
-
"
|
|
36515
|
-
"input": "jbF1yq_input",
|
|
36516
|
-
"toolStepName": "jbF1yq_toolStepName",
|
|
36517
|
-
"wsSelected": "jbF1yq_wsSelected",
|
|
36518
|
-
"panelNavCollapsed": "jbF1yq_panelNavCollapsed",
|
|
36519
|
-
"aiTag": "jbF1yq_aiTag",
|
|
36520
|
-
"authorHome": "jbF1yq_authorHome",
|
|
36521
|
-
"chWorkAside": "jbF1yq_chWorkAside",
|
|
36522
|
-
"buttonSmall": "jbF1yq_buttonSmall",
|
|
36523
|
-
"readerHeader": "jbF1yq_readerHeader",
|
|
36524
|
-
"authorTopNav": "jbF1yq_authorTopNav",
|
|
36525
|
-
"authorTopTabs": "jbF1yq_authorTopTabs",
|
|
36526
|
-
"chapterFocusPulse": "jbF1yq_chapterFocusPulse",
|
|
36527
|
-
"toolStep": "jbF1yq_toolStep",
|
|
36528
|
-
"authorContent": "jbF1yq_authorContent",
|
|
36659
|
+
"runLogTime": "jbF1yq_runLogTime",
|
|
36660
|
+
"assetCardName": "jbF1yq_assetCardName",
|
|
36529
36661
|
"iconBtn": "jbF1yq_iconBtn",
|
|
36530
|
-
"
|
|
36531
|
-
"
|
|
36532
|
-
"
|
|
36533
|
-
"
|
|
36662
|
+
"subPageActions": "jbF1yq_subPageActions",
|
|
36663
|
+
"busyRow": "jbF1yq_busyRow",
|
|
36664
|
+
"bookCardBody": "jbF1yq_bookCardBody",
|
|
36665
|
+
"assistantStatusBusy": "jbF1yq_assistantStatusBusy",
|
|
36666
|
+
"outlineH1": "jbF1yq_outlineH1",
|
|
36667
|
+
"outlineTocL2": "jbF1yq_outlineTocL2",
|
|
36668
|
+
"pageHeaderSub": "jbF1yq_pageHeaderSub",
|
|
36669
|
+
"toolLive": "jbF1yq_toolLive",
|
|
36534
36670
|
"chatBubbleAssistant": "jbF1yq_chatBubbleAssistant",
|
|
36535
|
-
"
|
|
36536
|
-
"
|
|
36537
|
-
"
|
|
36538
|
-
"
|
|
36539
|
-
"
|
|
36671
|
+
"wfEmpty": "jbF1yq_wfEmpty",
|
|
36672
|
+
"importModalTabs": "jbF1yq_importModalTabs",
|
|
36673
|
+
"wfStFix": "jbF1yq_wfStFix",
|
|
36674
|
+
"nfToast": "jbF1yq_nfToast",
|
|
36675
|
+
"importError": "jbF1yq_importError",
|
|
36676
|
+
"assistantResize": "jbF1yq_assistantResize",
|
|
36677
|
+
"panelBody": "jbF1yq_panelBody",
|
|
36678
|
+
"nfToastHost": "jbF1yq_nfToastHost",
|
|
36679
|
+
"wfBook": "jbF1yq_wfBook",
|
|
36680
|
+
"progressLineError": "jbF1yq_progressLineError",
|
|
36681
|
+
"wfSig": "jbF1yq_wfSig",
|
|
36682
|
+
"outlineHr": "jbF1yq_outlineHr",
|
|
36683
|
+
"importModalOverlay": "jbF1yq_importModalOverlay",
|
|
36684
|
+
"wfSep": "jbF1yq_wfSep",
|
|
36685
|
+
"wfMetrics": "jbF1yq_wfMetrics",
|
|
36686
|
+
"toolStepStatus": "jbF1yq_toolStepStatus",
|
|
36687
|
+
"outlineTocL1": "jbF1yq_outlineTocL1",
|
|
36688
|
+
"diffTagNew": "jbF1yq_diffTagNew",
|
|
36689
|
+
"readerMain": "jbF1yq_readerMain",
|
|
36690
|
+
"wfConOk": "jbF1yq_wfConOk",
|
|
36691
|
+
"adaptTable": "jbF1yq_adaptTable",
|
|
36540
36692
|
"progressBarFill": "jbF1yq_progressBarFill",
|
|
36541
|
-
"
|
|
36542
|
-
"
|
|
36543
|
-
"
|
|
36544
|
-
"runLogLine": "jbF1yq_runLogLine",
|
|
36545
|
-
"wfRs": "jbF1yq_wfRs",
|
|
36546
|
-
"wfCoord": "jbF1yq_wfCoord",
|
|
36547
|
-
"topNavSpacer": "jbF1yq_topNavSpacer",
|
|
36548
|
-
"outlineDoc": "jbF1yq_outlineDoc",
|
|
36549
|
-
"onlyChanges": "jbF1yq_onlyChanges",
|
|
36550
|
-
"progressTotalBar": "jbF1yq_progressTotalBar",
|
|
36551
|
-
"dropzoneActive": "jbF1yq_dropzoneActive",
|
|
36552
|
-
"adaptMatrix": "jbF1yq_adaptMatrix",
|
|
36553
|
-
"diffSame": "jbF1yq_diffSame",
|
|
36554
|
-
"diffTagOld": "jbF1yq_diffTagOld",
|
|
36555
|
-
"assetEditorRow": "jbF1yq_assetEditorRow",
|
|
36693
|
+
"assetCardContent": "jbF1yq_assetCardContent",
|
|
36694
|
+
"toolStepActive": "jbF1yq_toolStepActive",
|
|
36695
|
+
"wfPl": "jbF1yq_wfPl",
|
|
36556
36696
|
"wfConsoleNote": "jbF1yq_wfConsoleNote",
|
|
36557
|
-
"
|
|
36558
|
-
"
|
|
36559
|
-
"
|
|
36560
|
-
"
|
|
36561
|
-
"importError": "jbF1yq_importError",
|
|
36562
|
-
"importFileInfo": "jbF1yq_importFileInfo",
|
|
36563
|
-
"chWorkAsideBody": "jbF1yq_chWorkAsideBody",
|
|
36564
|
-
"assetLabel": "jbF1yq_assetLabel",
|
|
36565
|
-
"topNavBtn": "jbF1yq_topNavBtn",
|
|
36566
|
-
"nfSlideInRight": "jbF1yq_nfSlideInRight",
|
|
36567
|
-
"wfRsNo": "jbF1yq_wfRsNo",
|
|
36568
|
-
"headSpacer": "jbF1yq_headSpacer",
|
|
36569
|
-
"planDetailBar": "jbF1yq_planDetailBar",
|
|
36570
|
-
"wfConTxt": "jbF1yq_wfConTxt",
|
|
36571
|
-
"wfPill": "jbF1yq_wfPill",
|
|
36572
|
-
"readerItemTitle": "jbF1yq_readerItemTitle",
|
|
36573
|
-
"wfFdotErr": "jbF1yq_wfFdotErr",
|
|
36574
|
-
"chatRole": "jbF1yq_chatRole",
|
|
36697
|
+
"topNav": "jbF1yq_topNav",
|
|
36698
|
+
"assistantFloat": "jbF1yq_assistantFloat",
|
|
36699
|
+
"adaptRules": "jbF1yq_adaptRules",
|
|
36700
|
+
"wfEmpty2": "jbF1yq_wfEmpty2",
|
|
36575
36701
|
"bookCardCoverTitle": "jbF1yq_bookCardCoverTitle",
|
|
36576
|
-
"
|
|
36577
|
-
"
|
|
36578
|
-
"
|
|
36579
|
-
"
|
|
36580
|
-
"
|
|
36581
|
-
"
|
|
36582
|
-
"
|
|
36583
|
-
"
|
|
36584
|
-
"
|
|
36585
|
-
"
|
|
36586
|
-
"
|
|
36587
|
-
"
|
|
36588
|
-
"
|
|
36589
|
-
"
|
|
36590
|
-
"
|
|
36591
|
-
"
|
|
36702
|
+
"wfLiveChip": "jbF1yq_wfLiveChip",
|
|
36703
|
+
"wfConTxt": "jbF1yq_wfConTxt",
|
|
36704
|
+
"wbIndexRow": "jbF1yq_wbIndexRow",
|
|
36705
|
+
"assistantStatus": "jbF1yq_assistantStatus",
|
|
36706
|
+
"cmdMask": "jbF1yq_cmdMask",
|
|
36707
|
+
"pageHeaderActions": "jbF1yq_pageHeaderActions",
|
|
36708
|
+
"outlineH2": "jbF1yq_outlineH2",
|
|
36709
|
+
"authorTopTabs": "jbF1yq_authorTopTabs",
|
|
36710
|
+
"panelTitle": "jbF1yq_panelTitle",
|
|
36711
|
+
"drawerSpacer": "jbF1yq_drawerSpacer",
|
|
36712
|
+
"authorPageHeader": "jbF1yq_authorPageHeader",
|
|
36713
|
+
"dimCardSelected": "jbF1yq_dimCardSelected",
|
|
36714
|
+
"importModal": "jbF1yq_importModal",
|
|
36715
|
+
"shelfToolbarExtra": "jbF1yq_shelfToolbarExtra",
|
|
36716
|
+
"tnum": "jbF1yq_tnum",
|
|
36717
|
+
"buttonDanger": "jbF1yq_buttonDanger",
|
|
36718
|
+
"diffChange": "jbF1yq_diffChange",
|
|
36719
|
+
"planDetailBody": "jbF1yq_planDetailBody",
|
|
36720
|
+
"row": "jbF1yq_row",
|
|
36721
|
+
"t2RailHead": "jbF1yq_t2RailHead",
|
|
36722
|
+
"readerFoot": "jbF1yq_readerFoot",
|
|
36723
|
+
"entryLabel": "jbF1yq_entryLabel",
|
|
36724
|
+
"noticeSuccess": "jbF1yq_noticeSuccess",
|
|
36592
36725
|
"wsColumns": "jbF1yq_wsColumns",
|
|
36593
|
-
"
|
|
36594
|
-
"
|
|
36595
|
-
"
|
|
36596
|
-
"
|
|
36597
|
-
"
|
|
36598
|
-
"outlineVolSummary": "jbF1yq_outlineVolSummary",
|
|
36599
|
-
"brand": "jbF1yq_brand",
|
|
36600
|
-
"wfColA": "jbF1yq_wfColA",
|
|
36601
|
-
"t2RailSep": "jbF1yq_t2RailSep",
|
|
36726
|
+
"wbIndexTitle": "jbF1yq_wbIndexTitle",
|
|
36727
|
+
"readerTitle": "jbF1yq_readerTitle",
|
|
36728
|
+
"cmdItem": "jbF1yq_cmdItem",
|
|
36729
|
+
"chWorkActions": "jbF1yq_chWorkActions",
|
|
36730
|
+
"nfToastTick": "jbF1yq_nfToastTick",
|
|
36602
36731
|
"chapter": "jbF1yq_chapter",
|
|
36603
|
-
"
|
|
36604
|
-
"
|
|
36605
|
-
"
|
|
36606
|
-
"
|
|
36607
|
-
"
|
|
36608
|
-
"
|
|
36609
|
-
"
|
|
36610
|
-
"
|
|
36611
|
-
"
|
|
36612
|
-
"
|
|
36613
|
-
"
|
|
36614
|
-
"
|
|
36732
|
+
"aiTag": "jbF1yq_aiTag",
|
|
36733
|
+
"wfPillDot": "jbF1yq_wfPillDot",
|
|
36734
|
+
"wfDrawerBox": "jbF1yq_wfDrawerBox",
|
|
36735
|
+
"pillNavSlider": "jbF1yq_pillNavSlider",
|
|
36736
|
+
"panelContent": "jbF1yq_panelContent",
|
|
36737
|
+
"fileList": "jbF1yq_fileList",
|
|
36738
|
+
"settingsDrawerOverlay": "jbF1yq_settingsDrawerOverlay",
|
|
36739
|
+
"wfToolBlue": "jbF1yq_wfToolBlue",
|
|
36740
|
+
"topNavLabel": "jbF1yq_topNavLabel",
|
|
36741
|
+
"assetGroupHeader": "jbF1yq_assetGroupHeader",
|
|
36742
|
+
"adaptTableScroll": "jbF1yq_adaptTableScroll",
|
|
36743
|
+
"readerGroupTitle": "jbF1yq_readerGroupTitle",
|
|
36744
|
+
"titleBlock": "jbF1yq_titleBlock",
|
|
36745
|
+
"wfCn": "jbF1yq_wfCn",
|
|
36746
|
+
"readerText": "jbF1yq_readerText",
|
|
36747
|
+
"planDot": "jbF1yq_planDot",
|
|
36748
|
+
"outlineP": "jbF1yq_outlineP",
|
|
36749
|
+
"navTitle": "jbF1yq_navTitle",
|
|
36750
|
+
"wfDrawerToggle": "jbF1yq_wfDrawerToggle",
|
|
36751
|
+
"emptyStateIcon": "jbF1yq_emptyStateIcon",
|
|
36752
|
+
"navTitleBook": "jbF1yq_navTitleBook",
|
|
36615
36753
|
"assetEditor": "jbF1yq_assetEditor",
|
|
36616
|
-
"
|
|
36617
|
-
"authorNavBtn": "jbF1yq_authorNavBtn",
|
|
36618
|
-
"outlineTocL2": "jbF1yq_outlineTocL2",
|
|
36619
|
-
"runChipText": "jbF1yq_runChipText",
|
|
36754
|
+
"wfCard2": "jbF1yq_wfCard2",
|
|
36620
36755
|
"wfFeedBox": "jbF1yq_wfFeedBox",
|
|
36621
|
-
"
|
|
36622
|
-
"
|
|
36623
|
-
"
|
|
36624
|
-
"adaptRule": "jbF1yq_adaptRule",
|
|
36625
|
-
"cmdMask": "jbF1yq_cmdMask",
|
|
36626
|
-
"bookCardProgressFill": "jbF1yq_bookCardProgressFill",
|
|
36627
|
-
"topNavNi": "jbF1yq_topNavNi",
|
|
36628
|
-
"adaptImpact": "jbF1yq_adaptImpact",
|
|
36629
|
-
"wsAppliedBanner": "jbF1yq_wsAppliedBanner",
|
|
36630
|
-
"assetFilterChip": "jbF1yq_assetFilterChip",
|
|
36631
|
-
"wfFdotOk": "jbF1yq_wfFdotOk",
|
|
36756
|
+
"headChip": "jbF1yq_headChip",
|
|
36757
|
+
"planTreeVol": "jbF1yq_planTreeVol",
|
|
36758
|
+
"chWorkTitle": "jbF1yq_chWorkTitle",
|
|
36632
36759
|
"progressLineLive": "jbF1yq_progressLineLive",
|
|
36633
|
-
"
|
|
36634
|
-
"
|
|
36635
|
-
"
|
|
36636
|
-
"
|
|
36637
|
-
"
|
|
36638
|
-
"
|
|
36639
|
-
"
|
|
36640
|
-
"
|
|
36641
|
-
"
|
|
36642
|
-
"navTitleName": "jbF1yq_navTitleName",
|
|
36643
|
-
"outlineVol": "jbF1yq_outlineVol",
|
|
36644
|
-
"bookCardCoverFallback": "jbF1yq_bookCardCoverFallback",
|
|
36645
|
-
"assetKind": "jbF1yq_assetKind",
|
|
36646
|
-
"progressLine": "jbF1yq_progressLine",
|
|
36647
|
-
"t2Rail": "jbF1yq_t2Rail",
|
|
36648
|
-
"subPageBack": "jbF1yq_subPageBack",
|
|
36760
|
+
"genreDesc": "jbF1yq_genreDesc",
|
|
36761
|
+
"meta": "jbF1yq_meta",
|
|
36762
|
+
"importModalHead": "jbF1yq_importModalHead",
|
|
36763
|
+
"eyebrow": "jbF1yq_eyebrow",
|
|
36764
|
+
"wfTop": "jbF1yq_wfTop",
|
|
36765
|
+
"progressTotalBar": "jbF1yq_progressTotalBar",
|
|
36766
|
+
"readerGroupArrow": "jbF1yq_readerGroupArrow",
|
|
36767
|
+
"readerError": "jbF1yq_readerError",
|
|
36768
|
+
"docsSurface": "jbF1yq_docsSurface",
|
|
36649
36769
|
"planBeatsLabel": "jbF1yq_planBeatsLabel",
|
|
36650
|
-
"
|
|
36651
|
-
"shelfStatCard": "jbF1yq_shelfStatCard",
|
|
36652
|
-
"busyRow": "jbF1yq_busyRow",
|
|
36653
|
-
"brandText": "jbF1yq_brandText",
|
|
36654
|
-
"adaptTableScroll": "jbF1yq_adaptTableScroll",
|
|
36655
|
-
"panelHidden": "jbF1yq_panelHidden",
|
|
36656
|
-
"bookCardCover": "jbF1yq_bookCardCover",
|
|
36770
|
+
"emptyState": "jbF1yq_emptyState",
|
|
36657
36771
|
"view": "jbF1yq_view",
|
|
36658
|
-
"
|
|
36772
|
+
"settingsDrawerBody": "jbF1yq_settingsDrawerBody",
|
|
36773
|
+
"wfNow": "jbF1yq_wfNow",
|
|
36659
36774
|
"chapterFocus": "jbF1yq_chapterFocus",
|
|
36660
|
-
"
|
|
36661
|
-
"pillNavSliding": "jbF1yq_pillNavSliding",
|
|
36775
|
+
"wsColumn": "jbF1yq_wsColumn",
|
|
36662
36776
|
"shelfEmptyIcon": "jbF1yq_shelfEmptyIcon",
|
|
36663
|
-
"
|
|
36664
|
-
"
|
|
36665
|
-
"
|
|
36666
|
-
"
|
|
36777
|
+
"progressLineDone": "jbF1yq_progressLineDone",
|
|
36778
|
+
"wfRow": "jbF1yq_wfRow",
|
|
36779
|
+
"buttonPrimary": "jbF1yq_buttonPrimary",
|
|
36780
|
+
"chWorkMain": "jbF1yq_chWorkMain",
|
|
36781
|
+
"wfDrawerList": "jbF1yq_wfDrawerList",
|
|
36782
|
+
"reviewBox": "jbF1yq_reviewBox",
|
|
36783
|
+
"cmdList": "jbF1yq_cmdList",
|
|
36784
|
+
"wfLiveMark": "jbF1yq_wfLiveMark",
|
|
36785
|
+
"cmdIcon": "jbF1yq_cmdIcon",
|
|
36786
|
+
"shelfHero": "jbF1yq_shelfHero",
|
|
36787
|
+
"chapterMain": "jbF1yq_chapterMain",
|
|
36788
|
+
"chWorkToolActions": "jbF1yq_chWorkToolActions",
|
|
36789
|
+
"topNavBadge": "jbF1yq_topNavBadge",
|
|
36790
|
+
"nfViewIn": "jbF1yq_nfViewIn",
|
|
36791
|
+
"wfPoolBar": "jbF1yq_wfPoolBar",
|
|
36792
|
+
"wfDlDi": "jbF1yq_wfDlDi",
|
|
36793
|
+
"outlineDoc": "jbF1yq_outlineDoc",
|
|
36794
|
+
"wfTopRight": "jbF1yq_wfTopRight",
|
|
36667
36795
|
"pulse": "jbF1yq_pulse",
|
|
36668
|
-
"
|
|
36669
|
-
"
|
|
36670
|
-
"
|
|
36671
|
-
"
|
|
36672
|
-
"
|
|
36673
|
-
"
|
|
36674
|
-
"
|
|
36675
|
-
"
|
|
36676
|
-
"
|
|
36677
|
-
"
|
|
36796
|
+
"segTab": "jbF1yq_segTab",
|
|
36797
|
+
"wfPill": "jbF1yq_wfPill",
|
|
36798
|
+
"statCardDValue": "jbF1yq_statCardDValue",
|
|
36799
|
+
"wfOpsBtn": "jbF1yq_wfOpsBtn",
|
|
36800
|
+
"diffOld": "jbF1yq_diffOld",
|
|
36801
|
+
"importPreview": "jbF1yq_importPreview",
|
|
36802
|
+
"wfSigRight": "jbF1yq_wfSigRight",
|
|
36803
|
+
"wsEditor": "jbF1yq_wsEditor",
|
|
36804
|
+
"wfConsole": "jbF1yq_wfConsole",
|
|
36805
|
+
"bookCardActive": "jbF1yq_bookCardActive",
|
|
36806
|
+
"assetKind": "jbF1yq_assetKind",
|
|
36807
|
+
"wfFt": "jbF1yq_wfFt",
|
|
36808
|
+
"t2Content": "jbF1yq_t2Content",
|
|
36678
36809
|
"chWork": "jbF1yq_chWork",
|
|
36679
|
-
"
|
|
36680
|
-
"subPage": "jbF1yq_subPage",
|
|
36681
|
-
"bookCard": "jbF1yq_bookCard",
|
|
36682
|
-
"brandName": "jbF1yq_brandName",
|
|
36810
|
+
"nfDrawerIn": "jbF1yq_nfDrawerIn",
|
|
36683
36811
|
"toolStepError": "jbF1yq_toolStepError",
|
|
36684
|
-
"
|
|
36685
|
-
"
|
|
36686
|
-
"
|
|
36687
|
-
"
|
|
36688
|
-
"
|
|
36689
|
-
"
|
|
36690
|
-
"
|
|
36691
|
-
"
|
|
36692
|
-
"
|
|
36693
|
-
"
|
|
36694
|
-
"
|
|
36695
|
-
"
|
|
36696
|
-
"
|
|
36697
|
-
"
|
|
36698
|
-
"
|
|
36699
|
-
"wfDlDi": "jbF1yq_wfDlDi",
|
|
36700
|
-
"readerLoading": "jbF1yq_readerLoading",
|
|
36812
|
+
"brandLogo": "jbF1yq_brandLogo",
|
|
36813
|
+
"wfRsName": "jbF1yq_wfRsName",
|
|
36814
|
+
"wfOpsRow": "jbF1yq_wfOpsRow",
|
|
36815
|
+
"bookCardTitleRow": "jbF1yq_bookCardTitleRow",
|
|
36816
|
+
"lfDot": "jbF1yq_lfDot",
|
|
36817
|
+
"runChipText": "jbF1yq_runChipText",
|
|
36818
|
+
"t2RailSep": "jbF1yq_t2RailSep",
|
|
36819
|
+
"wfRs": "jbF1yq_wfRs",
|
|
36820
|
+
"chWorkGrid": "jbF1yq_chWorkGrid",
|
|
36821
|
+
"tabular": "jbF1yq_tabular",
|
|
36822
|
+
"fieldLabel": "jbF1yq_fieldLabel",
|
|
36823
|
+
"settingsDrawerHead": "jbF1yq_settingsDrawerHead",
|
|
36824
|
+
"panelHidden": "jbF1yq_panelHidden",
|
|
36825
|
+
"planTreeVolMeta": "jbF1yq_planTreeVolMeta",
|
|
36826
|
+
"wfAccentAmber": "jbF1yq_wfAccentAmber",
|
|
36701
36827
|
"dimCurrent": "jbF1yq_dimCurrent",
|
|
36702
|
-
"
|
|
36703
|
-
"
|
|
36828
|
+
"wsPage": "jbF1yq_wsPage",
|
|
36829
|
+
"wsSelected": "jbF1yq_wsSelected",
|
|
36704
36830
|
"toolSteps": "jbF1yq_toolSteps",
|
|
36705
|
-
"
|
|
36706
|
-
"wfOpsRow": "jbF1yq_wfOpsRow",
|
|
36707
|
-
"wfConsole": "jbF1yq_wfConsole",
|
|
36708
|
-
"planTreeVolGroup": "jbF1yq_planTreeVolGroup",
|
|
36709
|
-
"wfToolAmber": "jbF1yq_wfToolAmber",
|
|
36710
|
-
"importPreview": "jbF1yq_importPreview",
|
|
36711
|
-
"runLogTime": "jbF1yq_runLogTime",
|
|
36712
|
-
"wfDlName": "jbF1yq_wfDlName",
|
|
36713
|
-
"toolStepDetail": "jbF1yq_toolStepDetail",
|
|
36714
|
-
"chWorkSideBody": "jbF1yq_chWorkSideBody",
|
|
36715
|
-
"cmdBox": "jbF1yq_cmdBox",
|
|
36716
|
-
"coverPlaceholder": "jbF1yq_coverPlaceholder",
|
|
36717
|
-
"readerItem": "jbF1yq_readerItem",
|
|
36718
|
-
"assistantFloat": "jbF1yq_assistantFloat",
|
|
36719
|
-
"titleBlock": "jbF1yq_titleBlock",
|
|
36720
|
-
"wfBook": "jbF1yq_wfBook",
|
|
36721
|
-
"wbIndexTitle": "jbF1yq_wbIndexTitle",
|
|
36722
|
-
"subPageBody": "jbF1yq_subPageBody",
|
|
36723
|
-
"wfBoxH": "jbF1yq_wfBoxH",
|
|
36724
|
-
"wsPageHeader": "jbF1yq_wsPageHeader",
|
|
36725
|
-
"importModalActions": "jbF1yq_importModalActions",
|
|
36726
|
-
"dimEdit": "jbF1yq_dimEdit",
|
|
36727
|
-
"bookCardActions": "jbF1yq_bookCardActions",
|
|
36728
|
-
"progressLineError": "jbF1yq_progressLineError",
|
|
36729
|
-
"topNavActive": "jbF1yq_topNavActive",
|
|
36730
|
-
"bookCardBlurb": "jbF1yq_bookCardBlurb",
|
|
36731
|
-
"wfRow": "jbF1yq_wfRow",
|
|
36732
|
-
"noticeError": "jbF1yq_noticeError",
|
|
36733
|
-
"drawerTitle": "jbF1yq_drawerTitle",
|
|
36734
|
-
"dimTitle": "jbF1yq_dimTitle",
|
|
36735
|
-
"wbIndexRow": "jbF1yq_wbIndexRow",
|
|
36736
|
-
"panelBody": "jbF1yq_panelBody",
|
|
36737
|
-
"brandEn": "jbF1yq_brandEn",
|
|
36738
|
-
"bookCardBody": "jbF1yq_bookCardBody",
|
|
36739
|
-
"planDot": "jbF1yq_planDot",
|
|
36740
|
-
"wfTopRight": "jbF1yq_wfTopRight",
|
|
36741
|
-
"bookCardName": "jbF1yq_bookCardName",
|
|
36742
|
-
"bigProgressBar": "jbF1yq_bigProgressBar",
|
|
36743
|
-
"drawerHead": "jbF1yq_drawerHead",
|
|
36744
|
-
"t2RailMeta": "jbF1yq_t2RailMeta",
|
|
36745
|
-
"readerPara": "jbF1yq_readerPara",
|
|
36746
|
-
"diffColumn": "jbF1yq_diffColumn",
|
|
36747
|
-
"outlineTocL1": "jbF1yq_outlineTocL1",
|
|
36748
|
-
"emptyStateHint": "jbF1yq_emptyStateHint",
|
|
36831
|
+
"input": "jbF1yq_input",
|
|
36749
36832
|
"progressBar": "jbF1yq_progressBar",
|
|
36750
|
-
"
|
|
36751
|
-
"cmdList": "jbF1yq_cmdList",
|
|
36752
|
-
"readerGroup": "jbF1yq_readerGroup",
|
|
36753
|
-
"coverPreview": "jbF1yq_coverPreview",
|
|
36754
|
-
"wfPsN": "jbF1yq_wfPsN",
|
|
36755
|
-
"chWorkGrid": "jbF1yq_chWorkGrid",
|
|
36756
|
-
"segTab": "jbF1yq_segTab",
|
|
36757
|
-
"wfProgBig": "jbF1yq_wfProgBig",
|
|
36758
|
-
"diffList": "jbF1yq_diffList",
|
|
36759
|
-
"legendNew": "jbF1yq_legendNew",
|
|
36760
|
-
"topNavLabel": "jbF1yq_topNavLabel",
|
|
36761
|
-
"readerView": "jbF1yq_readerView",
|
|
36762
|
-
"readerSegBtn": "jbF1yq_readerSegBtn",
|
|
36763
|
-
"wsPage": "jbF1yq_wsPage",
|
|
36764
|
-
"wfColB": "jbF1yq_wfColB",
|
|
36765
|
-
"readerGroupCount": "jbF1yq_readerGroupCount",
|
|
36766
|
-
"brandLogo": "jbF1yq_brandLogo",
|
|
36767
|
-
"planDetailEmpty": "jbF1yq_planDetailEmpty",
|
|
36768
|
-
"adaptRules": "jbF1yq_adaptRules",
|
|
36769
|
-
"cmdHint": "jbF1yq_cmdHint",
|
|
36770
|
-
"button": "jbF1yq_button",
|
|
36771
|
-
"wfEmpty": "jbF1yq_wfEmpty",
|
|
36772
|
-
"shelfToolbarExtra": "jbF1yq_shelfToolbarExtra",
|
|
36833
|
+
"pageHeader": "jbF1yq_pageHeader",
|
|
36773
36834
|
"badgeDone": "jbF1yq_badgeDone",
|
|
36774
|
-
"
|
|
36775
|
-
"readerGroupArrow": "jbF1yq_readerGroupArrow",
|
|
36835
|
+
"t2Rail": "jbF1yq_t2Rail",
|
|
36776
36836
|
"wfConErr": "jbF1yq_wfConErr",
|
|
36837
|
+
"badgeRejected": "jbF1yq_badgeRejected",
|
|
36838
|
+
"t2RailMeta": "jbF1yq_t2RailMeta",
|
|
36839
|
+
"assetGrid": "jbF1yq_assetGrid",
|
|
36840
|
+
"bookCardProgressFill": "jbF1yq_bookCardProgressFill",
|
|
36841
|
+
"buttonSmall": "jbF1yq_buttonSmall",
|
|
36842
|
+
"pageHeaderTitle": "jbF1yq_pageHeaderTitle",
|
|
36843
|
+
"toolStepName": "jbF1yq_toolStepName",
|
|
36844
|
+
"assetEditorRow": "jbF1yq_assetEditorRow",
|
|
36845
|
+
"wfRail": "jbF1yq_wfRail",
|
|
36846
|
+
"badge": "jbF1yq_badge",
|
|
36847
|
+
"readerView": "jbF1yq_readerView",
|
|
36848
|
+
"assetGroup": "jbF1yq_assetGroup",
|
|
36849
|
+
"adaptImpact": "jbF1yq_adaptImpact",
|
|
36850
|
+
"adaptRuleRow": "jbF1yq_adaptRuleRow",
|
|
36851
|
+
"chapterTitle": "jbF1yq_chapterTitle",
|
|
36852
|
+
"bookCardCover": "jbF1yq_bookCardCover",
|
|
36853
|
+
"importModalBody": "jbF1yq_importModalBody",
|
|
36854
|
+
"wfCmdReason": "jbF1yq_wfCmdReason",
|
|
36855
|
+
"navTitleLogo": "jbF1yq_navTitleLogo",
|
|
36856
|
+
"createBookInner": "jbF1yq_createBookInner",
|
|
36857
|
+
"legendOld": "jbF1yq_legendOld",
|
|
36858
|
+
"chWorkPickBtns": "jbF1yq_chWorkPickBtns",
|
|
36859
|
+
"navTitleName": "jbF1yq_navTitleName",
|
|
36860
|
+
"planTreeVolGroup": "jbF1yq_planTreeVolGroup",
|
|
36861
|
+
"drawerScrim": "jbF1yq_drawerScrim",
|
|
36862
|
+
"wfFdot": "jbF1yq_wfFdot",
|
|
36863
|
+
"chWorkAsideTitle": "jbF1yq_chWorkAsideTitle",
|
|
36777
36864
|
"wfAccentBlue": "jbF1yq_wfAccentBlue",
|
|
36778
|
-
"
|
|
36779
|
-
"
|
|
36780
|
-
"
|
|
36781
|
-
"
|
|
36782
|
-
"
|
|
36783
|
-
"
|
|
36784
|
-
"
|
|
36865
|
+
"adaptMatrix": "jbF1yq_adaptMatrix",
|
|
36866
|
+
"wbIndexVol": "jbF1yq_wbIndexVol",
|
|
36867
|
+
"diffColumn": "jbF1yq_diffColumn",
|
|
36868
|
+
"toolStepIcon": "jbF1yq_toolStepIcon",
|
|
36869
|
+
"assetFilterChip": "jbF1yq_assetFilterChip",
|
|
36870
|
+
"outlineH": "jbF1yq_outlineH",
|
|
36871
|
+
"importResult": "jbF1yq_importResult",
|
|
36872
|
+
"wfFi": "jbF1yq_wfFi",
|
|
36873
|
+
"entryIcon": "jbF1yq_entryIcon",
|
|
36874
|
+
"topNavBtn": "jbF1yq_topNavBtn",
|
|
36875
|
+
"navAbout": "jbF1yq_navAbout",
|
|
36876
|
+
"dimCard": "jbF1yq_dimCard",
|
|
36877
|
+
"wfDlDim": "jbF1yq_wfDlDim",
|
|
36878
|
+
"chWorkDraftBar": "jbF1yq_chWorkDraftBar",
|
|
36879
|
+
"chapterList": "jbF1yq_chapterList",
|
|
36880
|
+
"wfHint": "jbF1yq_wfHint",
|
|
36881
|
+
"chWorkAside": "jbF1yq_chWorkAside",
|
|
36882
|
+
"panelNav": "jbF1yq_panelNav",
|
|
36883
|
+
"ideaCard": "jbF1yq_ideaCard",
|
|
36884
|
+
"wfPreviewActs": "jbF1yq_wfPreviewActs",
|
|
36785
36885
|
"navBadgePulse": "jbF1yq_navBadgePulse",
|
|
36786
|
-
"
|
|
36787
|
-
"
|
|
36788
|
-
"
|
|
36789
|
-
"
|
|
36790
|
-
"
|
|
36791
|
-
"
|
|
36792
|
-
"
|
|
36793
|
-
"
|
|
36794
|
-
"
|
|
36795
|
-
"
|
|
36796
|
-
"
|
|
36886
|
+
"noticeError": "jbF1yq_noticeError",
|
|
36887
|
+
"pageHeaderEyebrow": "jbF1yq_pageHeaderEyebrow",
|
|
36888
|
+
"wsPreview": "jbF1yq_wsPreview",
|
|
36889
|
+
"wfStage": "jbF1yq_wfStage",
|
|
36890
|
+
"wfDs": "jbF1yq_wfDs",
|
|
36891
|
+
"diffAdd": "jbF1yq_diffAdd",
|
|
36892
|
+
"nfCmdPop": "jbF1yq_nfCmdPop",
|
|
36893
|
+
"shelfStatGrid": "jbF1yq_shelfStatGrid",
|
|
36894
|
+
"chWorkSideBody": "jbF1yq_chWorkSideBody",
|
|
36895
|
+
"assetTextarea": "jbF1yq_assetTextarea",
|
|
36896
|
+
"wfPreviewLine": "jbF1yq_wfPreviewLine",
|
|
36897
|
+
"topNavActive": "jbF1yq_topNavActive",
|
|
36898
|
+
"outlineTocL3": "jbF1yq_outlineTocL3",
|
|
36899
|
+
"bigProgressBarFill": "jbF1yq_bigProgressBarFill",
|
|
36900
|
+
"fadeIn": "jbF1yq_fadeIn",
|
|
36797
36901
|
"runChipDot": "jbF1yq_runChipDot",
|
|
36798
|
-
"
|
|
36902
|
+
"adaptTextarea": "jbF1yq_adaptTextarea",
|
|
36903
|
+
"brandSub": "jbF1yq_brandSub",
|
|
36904
|
+
"runLogLine": "jbF1yq_runLogLine",
|
|
36905
|
+
"readerSegBtn": "jbF1yq_readerSegBtn",
|
|
36906
|
+
"wfColA": "jbF1yq_wfColA",
|
|
36907
|
+
"wfSt": "jbF1yq_wfSt",
|
|
36908
|
+
"wfFdotOk": "jbF1yq_wfFdotOk",
|
|
36909
|
+
"cmdBox": "jbF1yq_cmdBox",
|
|
36910
|
+
"pillNav": "jbF1yq_pillNav",
|
|
36799
36911
|
"wfPoolWrap": "jbF1yq_wfPoolWrap",
|
|
36800
|
-
"
|
|
36801
|
-
"
|
|
36802
|
-
"
|
|
36803
|
-
"
|
|
36804
|
-
"
|
|
36805
|
-
"
|
|
36806
|
-
"
|
|
36807
|
-
"
|
|
36808
|
-
"
|
|
36809
|
-
"
|
|
36810
|
-
"
|
|
36811
|
-
"
|
|
36812
|
-
"
|
|
36912
|
+
"wfProgBig": "jbF1yq_wfProgBig",
|
|
36913
|
+
"wfDl": "jbF1yq_wfDl",
|
|
36914
|
+
"wfFdotErr": "jbF1yq_wfFdotErr",
|
|
36915
|
+
"readerArticle": "jbF1yq_readerArticle",
|
|
36916
|
+
"nfSlideInRight": "jbF1yq_nfSlideInRight",
|
|
36917
|
+
"brandEn": "jbF1yq_brandEn",
|
|
36918
|
+
"readerLoading": "jbF1yq_readerLoading",
|
|
36919
|
+
"dropzone": "jbF1yq_dropzone",
|
|
36920
|
+
"wfPsLab": "jbF1yq_wfPsLab",
|
|
36921
|
+
"chWorkToolbar": "jbF1yq_chWorkToolbar",
|
|
36922
|
+
"assetLabel": "jbF1yq_assetLabel",
|
|
36923
|
+
"panelTop": "jbF1yq_panelTop",
|
|
36924
|
+
"dimEdit": "jbF1yq_dimEdit",
|
|
36925
|
+
"readerBody": "jbF1yq_readerBody",
|
|
36926
|
+
"badgeWritten": "jbF1yq_badgeWritten",
|
|
36927
|
+
"panelNavCollapsed": "jbF1yq_panelNavCollapsed",
|
|
36928
|
+
"authorContent": "jbF1yq_authorContent",
|
|
36929
|
+
"readerSegActive": "jbF1yq_readerSegActive",
|
|
36930
|
+
"shelfEmptyTitle": "jbF1yq_shelfEmptyTitle",
|
|
36931
|
+
"wfBoxH": "jbF1yq_wfBoxH",
|
|
36932
|
+
"t2Master": "jbF1yq_t2Master",
|
|
36933
|
+
"chatScroll": "jbF1yq_chatScroll",
|
|
36934
|
+
"diffSameBody": "jbF1yq_diffSameBody",
|
|
36813
36935
|
"outlineH4": "jbF1yq_outlineH4",
|
|
36814
|
-
"
|
|
36815
|
-
"wfNow": "jbF1yq_wfNow",
|
|
36816
|
-
"importModal": "jbF1yq_importModal",
|
|
36936
|
+
"shelfStatCard": "jbF1yq_shelfStatCard",
|
|
36817
36937
|
"numSerif": "jbF1yq_numSerif",
|
|
36818
|
-
"
|
|
36819
|
-
"
|
|
36820
|
-
"
|
|
36938
|
+
"adaptResult": "jbF1yq_adaptResult",
|
|
36939
|
+
"pageHeaderMain": "jbF1yq_pageHeaderMain",
|
|
36940
|
+
"wfQtTone": "jbF1yq_wfQtTone",
|
|
36941
|
+
"chWorkSide": "jbF1yq_chWorkSide",
|
|
36942
|
+
"planDetailEmpty": "jbF1yq_planDetailEmpty",
|
|
36943
|
+
"outlineEdit": "jbF1yq_outlineEdit",
|
|
36944
|
+
"active": "jbF1yq_active",
|
|
36945
|
+
"bigProgressBar": "jbF1yq_bigProgressBar",
|
|
36946
|
+
"topNavNi": "jbF1yq_topNavNi",
|
|
36947
|
+
"brand": "jbF1yq_brand",
|
|
36948
|
+
"wfPsN": "jbF1yq_wfPsN",
|
|
36949
|
+
"wfCoordStuck": "jbF1yq_wfCoordStuck",
|
|
36950
|
+
"shelfEmpty": "jbF1yq_shelfEmpty",
|
|
36951
|
+
"wfStFail": "jbF1yq_wfStFail",
|
|
36952
|
+
"outlineH3": "jbF1yq_outlineH3",
|
|
36821
36953
|
"bookCardProgressBar": "jbF1yq_bookCardProgressBar",
|
|
36822
|
-
"
|
|
36823
|
-
"wfPreviewLine": "jbF1yq_wfPreviewLine",
|
|
36824
|
-
"assistantStatusBusy": "jbF1yq_assistantStatusBusy",
|
|
36954
|
+
"wsSelectedText": "jbF1yq_wsSelectedText",
|
|
36825
36955
|
"outlineToc": "jbF1yq_outlineToc",
|
|
36826
|
-
"
|
|
36827
|
-
"
|
|
36828
|
-
"
|
|
36829
|
-
"
|
|
36830
|
-
"
|
|
36831
|
-
"
|
|
36956
|
+
"shelfToolbar": "jbF1yq_shelfToolbar",
|
|
36957
|
+
"adaptInputCard": "jbF1yq_adaptInputCard",
|
|
36958
|
+
"legendNew": "jbF1yq_legendNew",
|
|
36959
|
+
"brandName": "jbF1yq_brandName",
|
|
36960
|
+
"wfSigGood": "jbF1yq_wfSigGood",
|
|
36961
|
+
"wfBody": "jbF1yq_wfBody",
|
|
36832
36962
|
"readerSidebar": "jbF1yq_readerSidebar",
|
|
36833
|
-
"
|
|
36834
|
-
"
|
|
36835
|
-
"
|
|
36836
|
-
"
|
|
36837
|
-
"
|
|
36838
|
-
"
|
|
36839
|
-
"
|
|
36840
|
-
"
|
|
36841
|
-
"
|
|
36842
|
-
"
|
|
36843
|
-
"diffLegend": "jbF1yq_diffLegend",
|
|
36844
|
-
"cmdIcon": "jbF1yq_cmdIcon",
|
|
36845
|
-
"wfSigBad": "jbF1yq_wfSigBad",
|
|
36846
|
-
"planDetailTitle": "jbF1yq_planDetailTitle",
|
|
36847
|
-
"panelNav": "jbF1yq_panelNav",
|
|
36848
|
-
"shelfSearch": "jbF1yq_shelfSearch",
|
|
36849
|
-
"readerSegActive": "jbF1yq_readerSegActive",
|
|
36850
|
-
"reviewBox": "jbF1yq_reviewBox",
|
|
36851
|
-
"readerGroupTitle": "jbF1yq_readerGroupTitle",
|
|
36852
|
-
"statCardDDetail": "jbF1yq_statCardDDetail",
|
|
36963
|
+
"cmdInput": "jbF1yq_cmdInput",
|
|
36964
|
+
"drawerHeadBtn": "jbF1yq_drawerHeadBtn",
|
|
36965
|
+
"navAboutUpdate": "jbF1yq_navAboutUpdate",
|
|
36966
|
+
"assetCardFooter": "jbF1yq_assetCardFooter",
|
|
36967
|
+
"wfBlink": "jbF1yq_wfBlink",
|
|
36968
|
+
"chWorkBar": "jbF1yq_chWorkBar",
|
|
36969
|
+
"cmdHint": "jbF1yq_cmdHint",
|
|
36970
|
+
"subPageTitle": "jbF1yq_subPageTitle",
|
|
36971
|
+
"button": "jbF1yq_button",
|
|
36972
|
+
"wfSignal": "jbF1yq_wfSignal",
|
|
36853
36973
|
"authorNav": "jbF1yq_authorNav",
|
|
36854
|
-
"
|
|
36855
|
-
"
|
|
36856
|
-
"tnum": "jbF1yq_tnum",
|
|
36857
|
-
"settingsDrawerBody": "jbF1yq_settingsDrawerBody",
|
|
36858
|
-
"navAboutRow": "jbF1yq_navAboutRow",
|
|
36859
|
-
"wfFi": "jbF1yq_wfFi",
|
|
36860
|
-
"badgeWritten": "jbF1yq_badgeWritten",
|
|
36861
|
-
"readerItemActive": "jbF1yq_readerItemActive",
|
|
36862
|
-
"diffNew": "jbF1yq_diffNew",
|
|
36863
|
-
"subPageActions": "jbF1yq_subPageActions",
|
|
36864
|
-
"diffSameBody": "jbF1yq_diffSameBody",
|
|
36865
|
-
"subPageHead": "jbF1yq_subPageHead",
|
|
36866
|
-
"assetCardTop": "jbF1yq_assetCardTop",
|
|
36867
|
-
"t2RailHead": "jbF1yq_t2RailHead",
|
|
36868
|
-
"diffText": "jbF1yq_diffText",
|
|
36869
|
-
"nfCmdPop": "jbF1yq_nfCmdPop",
|
|
36870
|
-
"wfPreview": "jbF1yq_wfPreview",
|
|
36871
|
-
"wfCoordStuck": "jbF1yq_wfCoordStuck",
|
|
36872
|
-
"ideaCard": "jbF1yq_ideaCard",
|
|
36873
|
-
"t2Content": "jbF1yq_t2Content",
|
|
36874
|
-
"chWorkMain": "jbF1yq_chWorkMain",
|
|
36875
|
-
"pageHeaderMain": "jbF1yq_pageHeaderMain",
|
|
36876
|
-
"assetGroup": "jbF1yq_assetGroup",
|
|
36877
|
-
"wfProg": "jbF1yq_wfProg",
|
|
36878
|
-
"wfRail": "jbF1yq_wfRail",
|
|
36879
|
-
"wfBody": "jbF1yq_wfBody",
|
|
36880
|
-
"assetCard": "jbF1yq_assetCard",
|
|
36881
|
-
"bookCardMetaRow": "jbF1yq_bookCardMetaRow",
|
|
36882
|
-
"wfSig": "jbF1yq_wfSig",
|
|
36883
|
-
"entryIcon": "jbF1yq_entryIcon",
|
|
36884
|
-
"chWorkSide": "jbF1yq_chWorkSide",
|
|
36885
|
-
"wfDrawerToggle": "jbF1yq_wfDrawerToggle",
|
|
36886
|
-
"navGroupLabel": "jbF1yq_navGroupLabel",
|
|
36887
|
-
"createBookInner": "jbF1yq_createBookInner",
|
|
36888
|
-
"chWorkToolbar": "jbF1yq_chWorkToolbar",
|
|
36974
|
+
"subPage": "jbF1yq_subPage",
|
|
36975
|
+
"textarea": "jbF1yq_textarea",
|
|
36889
36976
|
"adaptOutline": "jbF1yq_adaptOutline",
|
|
36890
|
-
"
|
|
36891
|
-
"
|
|
36892
|
-
"
|
|
36893
|
-
"
|
|
36977
|
+
"planTreeRowTitle": "jbF1yq_planTreeRowTitle",
|
|
36978
|
+
"liveText": "jbF1yq_liveText",
|
|
36979
|
+
"subPageBody": "jbF1yq_subPageBody",
|
|
36980
|
+
"adaptRule": "jbF1yq_adaptRule",
|
|
36981
|
+
"wfSigBad": "jbF1yq_wfSigBad",
|
|
36982
|
+
"subPageMeta": "jbF1yq_subPageMeta",
|
|
36983
|
+
"chapterActions": "jbF1yq_chapterActions",
|
|
36984
|
+
"tab": "jbF1yq_tab",
|
|
36985
|
+
"chapterFocusPulse": "jbF1yq_chapterFocusPulse",
|
|
36986
|
+
"settingsCard": "jbF1yq_settingsCard",
|
|
36987
|
+
"wfSw": "jbF1yq_wfSw",
|
|
36988
|
+
"lfPill": "jbF1yq_lfPill",
|
|
36989
|
+
"diffLegend": "jbF1yq_diffLegend",
|
|
36990
|
+
"nfChipPulse": "jbF1yq_nfChipPulse",
|
|
36991
|
+
"bookCardName": "jbF1yq_bookCardName",
|
|
36992
|
+
"cardTitle": "jbF1yq_cardTitle",
|
|
36993
|
+
"chWorkFootRow": "jbF1yq_chWorkFootRow",
|
|
36994
|
+
"wsPageHeader": "jbF1yq_wsPageHeader",
|
|
36995
|
+
"bookCardBlurb": "jbF1yq_bookCardBlurb",
|
|
36894
36996
|
"shelfGrid": "jbF1yq_shelfGrid",
|
|
36895
|
-
"
|
|
36896
|
-
"
|
|
36897
|
-
"
|
|
36898
|
-
"
|
|
36899
|
-
"
|
|
36900
|
-
"
|
|
36901
|
-
"
|
|
36902
|
-
"
|
|
36903
|
-
"
|
|
36904
|
-
"
|
|
36905
|
-
"
|
|
36906
|
-
"
|
|
36907
|
-
"
|
|
36908
|
-
"
|
|
36909
|
-
"ideaCandidate": "jbF1yq_ideaCandidate",
|
|
36910
|
-
"outlineH3": "jbF1yq_outlineH3",
|
|
36911
|
-
"wfAct": "jbF1yq_wfAct",
|
|
36912
|
-
"adaptResult": "jbF1yq_adaptResult",
|
|
36913
|
-
"t2RailBtn": "jbF1yq_t2RailBtn",
|
|
36914
|
-
"chapterList": "jbF1yq_chapterList",
|
|
36915
|
-
"chapterTitle": "jbF1yq_chapterTitle",
|
|
36916
|
-
"readerFoot": "jbF1yq_readerFoot",
|
|
36997
|
+
"wfToolAmber": "jbF1yq_wfToolAmber",
|
|
36998
|
+
"wfCmdBtn": "jbF1yq_wfCmdBtn",
|
|
36999
|
+
"dimCardHead": "jbF1yq_dimCardHead",
|
|
37000
|
+
"adaptCell": "jbF1yq_adaptCell",
|
|
37001
|
+
"runChip": "jbF1yq_runChip",
|
|
37002
|
+
"emptyStateHint": "jbF1yq_emptyStateHint",
|
|
37003
|
+
"rowEnd": "jbF1yq_rowEnd",
|
|
37004
|
+
"chatBubbleUser": "jbF1yq_chatBubbleUser",
|
|
37005
|
+
"wfRsChk": "jbF1yq_wfRsChk",
|
|
37006
|
+
"authorPageBodyFlow": "jbF1yq_authorPageBodyFlow",
|
|
37007
|
+
"topNavSpacer": "jbF1yq_topNavSpacer",
|
|
37008
|
+
"toolStep": "jbF1yq_toolStep",
|
|
37009
|
+
"wfPreviewName": "jbF1yq_wfPreviewName",
|
|
37010
|
+
"badgeGenerating": "jbF1yq_badgeGenerating",
|
|
36917
37011
|
"nfToastIn": "jbF1yq_nfToastIn",
|
|
36918
|
-
"
|
|
36919
|
-
"
|
|
36920
|
-
"
|
|
36921
|
-
"chWorkActions": "jbF1yq_chWorkActions",
|
|
36922
|
-
"navTab": "jbF1yq_navTab",
|
|
36923
|
-
"progressLineDone": "jbF1yq_progressLineDone",
|
|
36924
|
-
"assetTextarea": "jbF1yq_assetTextarea",
|
|
36925
|
-
"navSpacer": "jbF1yq_navSpacer",
|
|
36926
|
-
"importHint": "jbF1yq_importHint",
|
|
36927
|
-
"panelTitle": "jbF1yq_panelTitle",
|
|
36928
|
-
"shelfHero": "jbF1yq_shelfHero",
|
|
36929
|
-
"wfOpsBtnMain": "jbF1yq_wfOpsBtnMain",
|
|
36930
|
-
"importModalBody": "jbF1yq_importModalBody",
|
|
36931
|
-
"wfBlink": "jbF1yq_wfBlink",
|
|
36932
|
-
"toolStepActive": "jbF1yq_toolStepActive",
|
|
36933
|
-
"outlineP": "jbF1yq_outlineP",
|
|
36934
|
-
"eyebrow": "jbF1yq_eyebrow",
|
|
36935
|
-
"liveText": "jbF1yq_liveText",
|
|
36936
|
-
"bigProgressBarFill": "jbF1yq_bigProgressBarFill",
|
|
36937
|
-
"badgePending": "jbF1yq_badgePending",
|
|
36938
|
-
"readerTitle": "jbF1yq_readerTitle",
|
|
36939
|
-
"wfSt": "jbF1yq_wfSt",
|
|
37012
|
+
"wfDone": "jbF1yq_wfDone",
|
|
37013
|
+
"wfMetric": "jbF1yq_wfMetric",
|
|
37014
|
+
"wsAppliedBanner": "jbF1yq_wsAppliedBanner",
|
|
36940
37015
|
"runLog": "jbF1yq_runLog",
|
|
36941
|
-
"
|
|
36942
|
-
"
|
|
36943
|
-
"
|
|
37016
|
+
"outlineTocItem": "jbF1yq_outlineTocItem",
|
|
37017
|
+
"planDetailTitle": "jbF1yq_planDetailTitle",
|
|
37018
|
+
"navSpacer": "jbF1yq_navSpacer",
|
|
37019
|
+
"wfCmd": "jbF1yq_wfCmd",
|
|
37020
|
+
"drawerMax": "jbF1yq_drawerMax",
|
|
37021
|
+
"importPreviewList": "jbF1yq_importPreviewList",
|
|
37022
|
+
"authorTopNav": "jbF1yq_authorTopNav",
|
|
37023
|
+
"assetGroups": "jbF1yq_assetGroups",
|
|
37024
|
+
"outlineVol": "jbF1yq_outlineVol",
|
|
37025
|
+
"wfRsNo": "jbF1yq_wfRsNo",
|
|
37026
|
+
"assetFilterChipActive": "jbF1yq_assetFilterChipActive",
|
|
37027
|
+
"readerHeader": "jbF1yq_readerHeader",
|
|
37028
|
+
"wfQt": "jbF1yq_wfQt",
|
|
37029
|
+
"headSpacer": "jbF1yq_headSpacer",
|
|
37030
|
+
"bookshelf": "jbF1yq_bookshelf",
|
|
37031
|
+
"toolStepDetail": "jbF1yq_toolStepDetail",
|
|
37032
|
+
"assistantFloatHeader": "jbF1yq_assistantFloatHeader",
|
|
37033
|
+
"readerItemActive": "jbF1yq_readerItemActive",
|
|
37034
|
+
"cardTitleLg": "jbF1yq_cardTitleLg",
|
|
37035
|
+
"chWorkPickBar": "jbF1yq_chWorkPickBar",
|
|
37036
|
+
"diffSame": "jbF1yq_diffSame",
|
|
37037
|
+
"readerGroup": "jbF1yq_readerGroup",
|
|
37038
|
+
"authorHome": "jbF1yq_authorHome",
|
|
37039
|
+
"navGroup": "jbF1yq_navGroup",
|
|
37040
|
+
"shelfSearch": "jbF1yq_shelfSearch",
|
|
37041
|
+
"pillNavSliding": "jbF1yq_pillNavSliding",
|
|
37042
|
+
"wfPsLegend": "jbF1yq_wfPsLegend",
|
|
37043
|
+
"wfCoord": "jbF1yq_wfCoord",
|
|
37044
|
+
"planDetailBar": "jbF1yq_planDetailBar",
|
|
37045
|
+
"wfSmallFoot": "jbF1yq_wfSmallFoot",
|
|
37046
|
+
"field": "jbF1yq_field",
|
|
37047
|
+
"diffList": "jbF1yq_diffList",
|
|
37048
|
+
"card": "jbF1yq_card",
|
|
37049
|
+
"assetCardTop": "jbF1yq_assetCardTop",
|
|
37050
|
+
"planTreeRow": "jbF1yq_planTreeRow",
|
|
37051
|
+
"wfDlName": "jbF1yq_wfDlName",
|
|
37052
|
+
"wfConRow": "jbF1yq_wfConRow",
|
|
37053
|
+
"chWorkSideFoot": "jbF1yq_chWorkSideFoot",
|
|
37054
|
+
"wfProg": "jbF1yq_wfProg",
|
|
37055
|
+
"wfConBar": "jbF1yq_wfConBar",
|
|
37056
|
+
"readerItem": "jbF1yq_readerItem",
|
|
37057
|
+
"diffDel": "jbF1yq_diffDel",
|
|
37058
|
+
"statCardDDetail": "jbF1yq_statCardDDetail",
|
|
37059
|
+
"planTreeSearch": "jbF1yq_planTreeSearch",
|
|
37060
|
+
"dimTitle": "jbF1yq_dimTitle",
|
|
37061
|
+
"wfPs": "jbF1yq_wfPs",
|
|
37062
|
+
"wfBox": "jbF1yq_wfBox",
|
|
36944
37063
|
"readerChapterMeta": "jbF1yq_readerChapterMeta",
|
|
36945
|
-
"
|
|
36946
|
-
"
|
|
36947
|
-
"
|
|
36948
|
-
"
|
|
36949
|
-
"
|
|
36950
|
-
"
|
|
36951
|
-
"
|
|
36952
|
-
"planTreeRowNo": "jbF1yq_planTreeRowNo",
|
|
36953
|
-
"planDetailBody": "jbF1yq_planDetailBody"
|
|
37064
|
+
"contentDrawerBody": "jbF1yq_contentDrawerBody",
|
|
37065
|
+
"entry": "jbF1yq_entry",
|
|
37066
|
+
"readerChapterTitle": "jbF1yq_readerChapterTitle",
|
|
37067
|
+
"adaptOutlinePre": "jbF1yq_adaptOutlinePre",
|
|
37068
|
+
"panel": "jbF1yq_panel",
|
|
37069
|
+
"outlineDocWrap": "jbF1yq_outlineDocWrap",
|
|
37070
|
+
"planDetail": "jbF1yq_planDetail"
|
|
36954
37071
|
};
|
|
36955
37072
|
//#endregion
|
|
36956
37073
|
//#region src/client/panel/ReasoningSection.tsx
|
|
@@ -37052,7 +37169,9 @@ window.__ModuleLoader__.load({
|
|
|
37052
37169
|
preview: "",
|
|
37053
37170
|
totalChars: 0,
|
|
37054
37171
|
startedAt: frame.at,
|
|
37055
|
-
updatedAt: frame.at
|
|
37172
|
+
updatedAt: frame.at,
|
|
37173
|
+
hasPrompt: frame.hasPrompt,
|
|
37174
|
+
promptChars: frame.promptChars
|
|
37056
37175
|
};
|
|
37057
37176
|
next[id] = session;
|
|
37058
37177
|
return next;
|
|
@@ -37091,7 +37210,10 @@ window.__ModuleLoader__.load({
|
|
|
37091
37210
|
phaseMessage: frame.phase === "failed" ? frame.error ?? "调用失败" : "模型结果已准备完成",
|
|
37092
37211
|
totalChars: frame.totalChars ?? session.totalChars,
|
|
37093
37212
|
preview: session.preview || (frame.preview ?? ""),
|
|
37094
|
-
updatedAt: frame.at
|
|
37213
|
+
updatedAt: frame.at,
|
|
37214
|
+
usage: frame.usage ?? session.usage,
|
|
37215
|
+
elapsedMs: frame.elapsedMs ?? session.elapsedMs,
|
|
37216
|
+
firstTokenMs: frame.firstTokenMs ?? session.firstTokenMs
|
|
37095
37217
|
};
|
|
37096
37218
|
next[id] = session;
|
|
37097
37219
|
}
|
|
@@ -37131,9 +37253,33 @@ window.__ModuleLoader__.load({
|
|
|
37131
37253
|
* 「实时调用 / LIVE」—— 内嵌到 AI 进度窗的下半区(详情层),不再独立浮窗。
|
|
37132
37254
|
* 连接 /llm-live/stream,按 LLM 调用分组展示模型实时输出。
|
|
37133
37255
|
*
|
|
37256
|
+
* 除实时输出外,这里还承担两件与「花了多少」有关的事:
|
|
37257
|
+
* 1) 每次调用显示 token 用量(输入↑ / 输出↓ / 思考)与耗时、首字耗时;
|
|
37258
|
+
* 2) 「查看 Prompt」按 sessionId 拉取这次调用**实际发送**的 system / user。
|
|
37259
|
+
* 顶部另有一条「本次运行」累计条(进程内,重启归零)。
|
|
37260
|
+
*
|
|
37134
37261
|
* 状态色全部走 panel.module.css 的 .lfPill / .lfDot(主题令牌 + --nf-streaming),
|
|
37135
37262
|
* 不再内联硬编码色;布局性 inline style 保留(均为令牌引用或动态值)。
|
|
37136
37263
|
*/
|
|
37264
|
+
/** 毫秒 → 紧凑可读(840ms / 1.2s)。 */
|
|
37265
|
+
function fmtMs(ms) {
|
|
37266
|
+
if (ms === void 0 || ms <= 0) return "";
|
|
37267
|
+
return ms < 1e3 ? Math.round(ms) + "ms" : (ms / 1e3).toFixed(1) + "s";
|
|
37268
|
+
}
|
|
37269
|
+
/** token 数 → 紧凑(12.3k)。 */
|
|
37270
|
+
function fmtTokens(n) {
|
|
37271
|
+
if (n === void 0 || n <= 0) return "0";
|
|
37272
|
+
return n < 1e3 ? String(n) : (n / 1e3).toFixed(1) + "k";
|
|
37273
|
+
}
|
|
37274
|
+
/** 一次调用的用量摘要(输入↑ / 输出↓ / 思考 / 缓存)。 */
|
|
37275
|
+
function usageText(s) {
|
|
37276
|
+
const u = s.usage;
|
|
37277
|
+
if (u === void 0) return "用量未上报";
|
|
37278
|
+
const parts = ["↑" + fmtTokens(u.inputTokens), "↓" + fmtTokens(u.outputTokens)];
|
|
37279
|
+
if ((u.reasoningTokens ?? 0) > 0) parts.push("思考 " + fmtTokens(u.reasoningTokens));
|
|
37280
|
+
if ((u.cacheReadTokens ?? 0) > 0) parts.push("缓存 " + fmtTokens(u.cacheReadTokens));
|
|
37281
|
+
return parts.join(" · ");
|
|
37282
|
+
}
|
|
37137
37283
|
function PhasePill({ s }) {
|
|
37138
37284
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
37139
37285
|
className: panel_module_css_default.lfPill,
|
|
@@ -37141,7 +37287,138 @@ window.__ModuleLoader__.load({
|
|
|
37141
37287
|
children: s.phase === "requesting" ? "请求中" : s.phase === "streaming" ? "生成中" : s.phase === "failed" ? "失败" : "完成"
|
|
37142
37288
|
});
|
|
37143
37289
|
}
|
|
37144
|
-
|
|
37290
|
+
/** 「查看 Prompt」弹层:拉取这次调用实际发送的 system + user。 */
|
|
37291
|
+
function PromptDialog({ sessionId, onClose }) {
|
|
37292
|
+
const [record, setRecord] = (0, react.useState)(null);
|
|
37293
|
+
const [error, setError] = (0, react.useState)("");
|
|
37294
|
+
const [tab, setTab] = (0, react.useState)("user");
|
|
37295
|
+
(0, react.useEffect)(() => {
|
|
37296
|
+
let cancelled = false;
|
|
37297
|
+
(async () => {
|
|
37298
|
+
try {
|
|
37299
|
+
const res = await fetch(NOVEL_API.llmPrompt + "?sessionId=" + encodeURIComponent(sessionId));
|
|
37300
|
+
if (!res.ok) {
|
|
37301
|
+
const body = await res.json().catch(() => ({}));
|
|
37302
|
+
throw new Error(body.error ?? "HTTP " + res.status);
|
|
37303
|
+
}
|
|
37304
|
+
const data = await res.json();
|
|
37305
|
+
if (!cancelled) setRecord(data);
|
|
37306
|
+
} catch (err) {
|
|
37307
|
+
if (!cancelled) setError(err.message);
|
|
37308
|
+
}
|
|
37309
|
+
})();
|
|
37310
|
+
return () => {
|
|
37311
|
+
cancelled = true;
|
|
37312
|
+
};
|
|
37313
|
+
}, [sessionId]);
|
|
37314
|
+
const text = record === null ? "" : tab === "user" ? record.user ?? "" : record.system ?? "";
|
|
37315
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
37316
|
+
style: {
|
|
37317
|
+
position: "fixed",
|
|
37318
|
+
inset: 0,
|
|
37319
|
+
background: "rgba(0,0,0,.45)",
|
|
37320
|
+
zIndex: 60,
|
|
37321
|
+
display: "flex",
|
|
37322
|
+
alignItems: "center",
|
|
37323
|
+
justifyContent: "center",
|
|
37324
|
+
padding: 20
|
|
37325
|
+
},
|
|
37326
|
+
onClick: onClose,
|
|
37327
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
37328
|
+
onClick: (e) => e.stopPropagation(),
|
|
37329
|
+
style: {
|
|
37330
|
+
background: "var(--nf-bg)",
|
|
37331
|
+
border: "1px solid var(--nf-border)",
|
|
37332
|
+
borderRadius: 10,
|
|
37333
|
+
width: "min(880px, 96vw)",
|
|
37334
|
+
maxHeight: "86vh",
|
|
37335
|
+
display: "flex",
|
|
37336
|
+
flexDirection: "column",
|
|
37337
|
+
padding: 12,
|
|
37338
|
+
gap: 8
|
|
37339
|
+
},
|
|
37340
|
+
children: [
|
|
37341
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
37342
|
+
style: {
|
|
37343
|
+
display: "flex",
|
|
37344
|
+
alignItems: "center",
|
|
37345
|
+
gap: 8
|
|
37346
|
+
},
|
|
37347
|
+
children: [
|
|
37348
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("b", {
|
|
37349
|
+
style: {
|
|
37350
|
+
flex: 1,
|
|
37351
|
+
fontSize: 13
|
|
37352
|
+
},
|
|
37353
|
+
children: ["实际发送的 Prompt", record?.label !== void 0 ? " · " + record.label : ""]
|
|
37354
|
+
}),
|
|
37355
|
+
record !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
37356
|
+
className: panel_module_css_default.meta,
|
|
37357
|
+
children: [
|
|
37358
|
+
"共 ",
|
|
37359
|
+
record.chars.toLocaleString(),
|
|
37360
|
+
" 字符",
|
|
37361
|
+
record.truncated === true ? "(记录已截断)" : ""
|
|
37362
|
+
]
|
|
37363
|
+
}),
|
|
37364
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
37365
|
+
type: "button",
|
|
37366
|
+
className: panel_module_css_default.iconButton,
|
|
37367
|
+
title: "关闭",
|
|
37368
|
+
onClick: onClose,
|
|
37369
|
+
children: "×"
|
|
37370
|
+
})
|
|
37371
|
+
]
|
|
37372
|
+
}),
|
|
37373
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
37374
|
+
style: {
|
|
37375
|
+
display: "flex",
|
|
37376
|
+
gap: 6
|
|
37377
|
+
},
|
|
37378
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
37379
|
+
type: "button",
|
|
37380
|
+
className: panel_module_css_default.button + (tab === "user" ? " " + panel_module_css_default.buttonPrimary : ""),
|
|
37381
|
+
onClick: () => setTab("user"),
|
|
37382
|
+
children: "User / 输入"
|
|
37383
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
37384
|
+
type: "button",
|
|
37385
|
+
className: panel_module_css_default.button + (tab === "system" ? " " + panel_module_css_default.buttonPrimary : ""),
|
|
37386
|
+
onClick: () => setTab("system"),
|
|
37387
|
+
children: "System / 系统提示"
|
|
37388
|
+
})]
|
|
37389
|
+
}),
|
|
37390
|
+
error !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
37391
|
+
style: {
|
|
37392
|
+
color: "var(--nf-error)",
|
|
37393
|
+
fontSize: 12
|
|
37394
|
+
},
|
|
37395
|
+
children: error
|
|
37396
|
+
}),
|
|
37397
|
+
record === null && error === "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
37398
|
+
className: panel_module_css_default.meta,
|
|
37399
|
+
children: "加载中…"
|
|
37400
|
+
}),
|
|
37401
|
+
record !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
|
|
37402
|
+
style: {
|
|
37403
|
+
flex: 1,
|
|
37404
|
+
minHeight: 0,
|
|
37405
|
+
overflow: "auto",
|
|
37406
|
+
whiteSpace: "pre-wrap",
|
|
37407
|
+
wordBreak: "break-word",
|
|
37408
|
+
fontSize: 11,
|
|
37409
|
+
lineHeight: 1.55,
|
|
37410
|
+
background: "var(--nf-bg-inset)",
|
|
37411
|
+
borderRadius: 8,
|
|
37412
|
+
padding: 8,
|
|
37413
|
+
margin: 0
|
|
37414
|
+
},
|
|
37415
|
+
children: text === "" ? "(空)" : text
|
|
37416
|
+
})
|
|
37417
|
+
]
|
|
37418
|
+
})
|
|
37419
|
+
});
|
|
37420
|
+
}
|
|
37421
|
+
function SessionCard({ s, brief, onShowPrompt }) {
|
|
37145
37422
|
const dotState = s.phase === "requesting" || s.phase === "streaming" ? "streaming" : s.phase;
|
|
37146
37423
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
37147
37424
|
style: {
|
|
@@ -37190,16 +37467,48 @@ window.__ModuleLoader__.load({
|
|
|
37190
37467
|
color: "var(--nf-text-2)",
|
|
37191
37468
|
marginTop: 2,
|
|
37192
37469
|
display: "flex",
|
|
37193
|
-
gap: 8
|
|
37470
|
+
gap: 8,
|
|
37471
|
+
flexWrap: "wrap",
|
|
37472
|
+
alignItems: "center"
|
|
37194
37473
|
},
|
|
37195
|
-
children: [
|
|
37196
|
-
|
|
37197
|
-
|
|
37198
|
-
|
|
37199
|
-
|
|
37200
|
-
},
|
|
37201
|
-
|
|
37202
|
-
|
|
37474
|
+
children: [
|
|
37475
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [s.totalChars, " 字符"] }),
|
|
37476
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
37477
|
+
title: "输入 / 输出 token",
|
|
37478
|
+
children: usageText(s)
|
|
37479
|
+
}),
|
|
37480
|
+
s.elapsedMs !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
37481
|
+
title: "总耗时",
|
|
37482
|
+
children: ["用时 ", fmtMs(s.elapsedMs)]
|
|
37483
|
+
}),
|
|
37484
|
+
s.firstTokenMs !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
37485
|
+
title: "首个字返回耗时",
|
|
37486
|
+
children: ["首字 ", fmtMs(s.firstTokenMs)]
|
|
37487
|
+
}),
|
|
37488
|
+
s.phaseMessage !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
37489
|
+
style: {
|
|
37490
|
+
overflow: "hidden",
|
|
37491
|
+
textOverflow: "ellipsis",
|
|
37492
|
+
whiteSpace: "nowrap"
|
|
37493
|
+
},
|
|
37494
|
+
children: s.phaseMessage
|
|
37495
|
+
}),
|
|
37496
|
+
s.hasPrompt === true && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
37497
|
+
type: "button",
|
|
37498
|
+
title: "查看这次调用实际发送的 Prompt",
|
|
37499
|
+
onClick: () => onShowPrompt(s.sessionId),
|
|
37500
|
+
style: {
|
|
37501
|
+
border: "1px solid var(--nf-border)",
|
|
37502
|
+
background: "var(--nf-bg)",
|
|
37503
|
+
color: "var(--nf-text)",
|
|
37504
|
+
borderRadius: 6,
|
|
37505
|
+
fontSize: 10,
|
|
37506
|
+
padding: "0 5px",
|
|
37507
|
+
cursor: "pointer"
|
|
37508
|
+
},
|
|
37509
|
+
children: "查看 Prompt"
|
|
37510
|
+
})
|
|
37511
|
+
]
|
|
37203
37512
|
}),
|
|
37204
37513
|
!brief && s.preview !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
|
|
37205
37514
|
style: {
|
|
@@ -37222,9 +37531,38 @@ window.__ModuleLoader__.load({
|
|
|
37222
37531
|
function LiveFeedLog() {
|
|
37223
37532
|
const [brief, setBrief] = (0, react.useState)(true);
|
|
37224
37533
|
const [cleared, setCleared] = (0, react.useState)(false);
|
|
37534
|
+
const [promptId, setPromptId] = (0, react.useState)(null);
|
|
37225
37535
|
const { connected, sessions } = useLlmLiveFeed(true);
|
|
37226
37536
|
const active = sessions.filter((s) => s.phase === "requesting" || s.phase === "streaming").length;
|
|
37227
37537
|
const shown = (0, react.useMemo)(() => cleared ? sessions.slice(-8) : sessions, [sessions, cleared]);
|
|
37538
|
+
const [usage, setUsage] = (0, react.useState)(null);
|
|
37539
|
+
const loadUsage = (0, react.useCallback)(async () => {
|
|
37540
|
+
try {
|
|
37541
|
+
const res = await fetch(NOVEL_API.status + "?slim=1");
|
|
37542
|
+
if (!res.ok) return;
|
|
37543
|
+
const data = await res.json();
|
|
37544
|
+
setUsage(data.usage ?? null);
|
|
37545
|
+
} catch {}
|
|
37546
|
+
}, []);
|
|
37547
|
+
(0, react.useEffect)(() => {
|
|
37548
|
+
loadUsage();
|
|
37549
|
+
const timer = window.setInterval(() => {
|
|
37550
|
+
loadUsage();
|
|
37551
|
+
}, 15e3);
|
|
37552
|
+
return () => {
|
|
37553
|
+
window.clearInterval(timer);
|
|
37554
|
+
};
|
|
37555
|
+
}, [loadUsage]);
|
|
37556
|
+
const resetUsage = (0, react.useCallback)(async () => {
|
|
37557
|
+
try {
|
|
37558
|
+
await fetch(NOVEL_API.usageReset, {
|
|
37559
|
+
method: "POST",
|
|
37560
|
+
headers: { "content-type": "application/json" },
|
|
37561
|
+
body: "{}"
|
|
37562
|
+
});
|
|
37563
|
+
await loadUsage();
|
|
37564
|
+
} catch {}
|
|
37565
|
+
}, [loadUsage]);
|
|
37228
37566
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
37229
37567
|
style: {
|
|
37230
37568
|
borderTop: "1px solid var(--nf-border)",
|
|
@@ -37235,80 +37573,136 @@ window.__ModuleLoader__.load({
|
|
|
37235
37573
|
display: "flex",
|
|
37236
37574
|
flexDirection: "column"
|
|
37237
37575
|
},
|
|
37238
|
-
children: [
|
|
37239
|
-
|
|
37240
|
-
display: "flex",
|
|
37241
|
-
alignItems: "center",
|
|
37242
|
-
gap: 8,
|
|
37243
|
-
fontSize: 12,
|
|
37244
|
-
padding: "2px 4px"
|
|
37245
|
-
},
|
|
37246
|
-
children: [
|
|
37247
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
37248
|
-
className: panel_module_css_default.lfDot,
|
|
37249
|
-
"data-size": "lg",
|
|
37250
|
-
"data-state": connected ? "ok" : "idle"
|
|
37251
|
-
}),
|
|
37252
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", {
|
|
37253
|
-
style: { flex: 1 },
|
|
37254
|
-
children: "实时调用 / LIVE"
|
|
37255
|
-
}),
|
|
37256
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
37257
|
-
className: panel_module_css_default.lfPill,
|
|
37258
|
-
"data-phase": active > 0 ? "streaming" : "requesting",
|
|
37259
|
-
children: active > 0 ? `${active} 项进行中` : connected ? "等待生成" : "正在连接"
|
|
37260
|
-
}),
|
|
37261
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
37262
|
-
type: "button",
|
|
37263
|
-
title: brief ? "详细" : "简略",
|
|
37264
|
-
onClick: () => setBrief((b) => !b),
|
|
37265
|
-
style: {
|
|
37266
|
-
border: "1px solid var(--nf-border)",
|
|
37267
|
-
background: "var(--nf-bg)",
|
|
37268
|
-
color: "var(--nf-text)",
|
|
37269
|
-
borderRadius: 6,
|
|
37270
|
-
fontSize: 10,
|
|
37271
|
-
padding: "1px 6px",
|
|
37272
|
-
cursor: "pointer"
|
|
37273
|
-
},
|
|
37274
|
-
children: brief ? "详细" : "简略"
|
|
37275
|
-
}),
|
|
37276
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
37277
|
-
type: "button",
|
|
37278
|
-
title: "清空当前窗口",
|
|
37279
|
-
onClick: () => setCleared(true),
|
|
37280
|
-
style: {
|
|
37281
|
-
border: "1px solid var(--nf-border)",
|
|
37282
|
-
background: "var(--nf-bg)",
|
|
37283
|
-
color: "var(--nf-text)",
|
|
37284
|
-
borderRadius: 6,
|
|
37285
|
-
fontSize: 10,
|
|
37286
|
-
padding: "1px 6px",
|
|
37287
|
-
cursor: "pointer"
|
|
37288
|
-
},
|
|
37289
|
-
children: "清空"
|
|
37290
|
-
})
|
|
37291
|
-
]
|
|
37292
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
37293
|
-
style: {
|
|
37294
|
-
flex: 1,
|
|
37295
|
-
minHeight: 0,
|
|
37296
|
-
overflowY: "auto",
|
|
37297
|
-
display: "flex",
|
|
37298
|
-
flexDirection: "column"
|
|
37299
|
-
},
|
|
37300
|
-
children: shown.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
37576
|
+
children: [
|
|
37577
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
37301
37578
|
style: {
|
|
37302
|
-
|
|
37579
|
+
display: "flex",
|
|
37580
|
+
alignItems: "center",
|
|
37581
|
+
gap: 8,
|
|
37303
37582
|
fontSize: 12,
|
|
37304
|
-
|
|
37583
|
+
padding: "2px 4px"
|
|
37305
37584
|
},
|
|
37306
|
-
children:
|
|
37307
|
-
|
|
37308
|
-
|
|
37309
|
-
|
|
37310
|
-
|
|
37311
|
-
|
|
37585
|
+
children: [
|
|
37586
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
37587
|
+
className: panel_module_css_default.lfDot,
|
|
37588
|
+
"data-size": "lg",
|
|
37589
|
+
"data-state": connected ? "ok" : "idle"
|
|
37590
|
+
}),
|
|
37591
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", {
|
|
37592
|
+
style: { flex: 1 },
|
|
37593
|
+
children: "实时调用 / LIVE"
|
|
37594
|
+
}),
|
|
37595
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
37596
|
+
className: panel_module_css_default.lfPill,
|
|
37597
|
+
"data-phase": active > 0 ? "streaming" : "requesting",
|
|
37598
|
+
children: active > 0 ? `${active} 项进行中` : connected ? "等待生成" : "正在连接"
|
|
37599
|
+
}),
|
|
37600
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
37601
|
+
type: "button",
|
|
37602
|
+
title: brief ? "详细" : "简略",
|
|
37603
|
+
onClick: () => setBrief((b) => !b),
|
|
37604
|
+
style: {
|
|
37605
|
+
border: "1px solid var(--nf-border)",
|
|
37606
|
+
background: "var(--nf-bg)",
|
|
37607
|
+
color: "var(--nf-text)",
|
|
37608
|
+
borderRadius: 6,
|
|
37609
|
+
fontSize: 10,
|
|
37610
|
+
padding: "1px 6px",
|
|
37611
|
+
cursor: "pointer"
|
|
37612
|
+
},
|
|
37613
|
+
children: brief ? "详细" : "简略"
|
|
37614
|
+
}),
|
|
37615
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
37616
|
+
type: "button",
|
|
37617
|
+
title: "清空当前窗口",
|
|
37618
|
+
onClick: () => setCleared(true),
|
|
37619
|
+
style: {
|
|
37620
|
+
border: "1px solid var(--nf-border)",
|
|
37621
|
+
background: "var(--nf-bg)",
|
|
37622
|
+
color: "var(--nf-text)",
|
|
37623
|
+
borderRadius: 6,
|
|
37624
|
+
fontSize: 10,
|
|
37625
|
+
padding: "1px 6px",
|
|
37626
|
+
cursor: "pointer"
|
|
37627
|
+
},
|
|
37628
|
+
children: "清空"
|
|
37629
|
+
})
|
|
37630
|
+
]
|
|
37631
|
+
}),
|
|
37632
|
+
usage !== null && usage.calls > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
37633
|
+
title: "本次运行累计(进程内,重启归零)",
|
|
37634
|
+
style: {
|
|
37635
|
+
display: "flex",
|
|
37636
|
+
alignItems: "center",
|
|
37637
|
+
gap: 10,
|
|
37638
|
+
flexWrap: "wrap",
|
|
37639
|
+
fontSize: 10,
|
|
37640
|
+
color: "var(--nf-text-2)",
|
|
37641
|
+
padding: "3px 4px",
|
|
37642
|
+
borderTop: "1px dashed var(--nf-border)"
|
|
37643
|
+
},
|
|
37644
|
+
children: [
|
|
37645
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
37646
|
+
"本次运行:",
|
|
37647
|
+
usage.calls,
|
|
37648
|
+
" 次调用",
|
|
37649
|
+
usage.failed > 0 ? `(失败 ${usage.failed})` : ""
|
|
37650
|
+
] }),
|
|
37651
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: ["↑", fmtTokens(usage.inputTokens)] }),
|
|
37652
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: ["↓", fmtTokens(usage.outputTokens)] }),
|
|
37653
|
+
usage.reasoningTokens > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: ["思考 ", fmtTokens(usage.reasoningTokens)] }),
|
|
37654
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: ["用时 ", fmtMs(usage.elapsedMs)] }),
|
|
37655
|
+
usage.callsWithoutUsage > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
37656
|
+
"(",
|
|
37657
|
+
usage.callsWithoutUsage,
|
|
37658
|
+
" 次未上报用量)"
|
|
37659
|
+
] }),
|
|
37660
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
37661
|
+
type: "button",
|
|
37662
|
+
title: "清零本次运行用量",
|
|
37663
|
+
onClick: () => {
|
|
37664
|
+
resetUsage();
|
|
37665
|
+
},
|
|
37666
|
+
style: {
|
|
37667
|
+
marginLeft: "auto",
|
|
37668
|
+
border: "1px solid var(--nf-border)",
|
|
37669
|
+
background: "var(--nf-bg)",
|
|
37670
|
+
color: "var(--nf-text)",
|
|
37671
|
+
borderRadius: 6,
|
|
37672
|
+
fontSize: 10,
|
|
37673
|
+
padding: "1px 6px",
|
|
37674
|
+
cursor: "pointer"
|
|
37675
|
+
},
|
|
37676
|
+
children: "重新计数"
|
|
37677
|
+
})
|
|
37678
|
+
]
|
|
37679
|
+
}),
|
|
37680
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
37681
|
+
style: {
|
|
37682
|
+
flex: 1,
|
|
37683
|
+
minHeight: 0,
|
|
37684
|
+
overflowY: "auto",
|
|
37685
|
+
display: "flex",
|
|
37686
|
+
flexDirection: "column"
|
|
37687
|
+
},
|
|
37688
|
+
children: shown.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
37689
|
+
style: {
|
|
37690
|
+
padding: 10,
|
|
37691
|
+
fontSize: 12,
|
|
37692
|
+
color: "var(--nf-text-2)"
|
|
37693
|
+
},
|
|
37694
|
+
children: connected ? "暂无实时调用。开始一次生成/审稿/计划即可看到。" : "正在连接 AI 实况服务…"
|
|
37695
|
+
}) : shown.map((s) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SessionCard, {
|
|
37696
|
+
s,
|
|
37697
|
+
brief,
|
|
37698
|
+
onShowPrompt: setPromptId
|
|
37699
|
+
}, s.sessionId))
|
|
37700
|
+
}),
|
|
37701
|
+
promptId !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PromptDialog, {
|
|
37702
|
+
sessionId: promptId,
|
|
37703
|
+
onClose: () => setPromptId(null)
|
|
37704
|
+
})
|
|
37705
|
+
]
|
|
37312
37706
|
});
|
|
37313
37707
|
}
|
|
37314
37708
|
//#endregion
|
|
@@ -38017,7 +38411,7 @@ window.__ModuleLoader__.load({
|
|
|
38017
38411
|
//#region src/client/panel/AssetsTab.tsx
|
|
38018
38412
|
/**
|
|
38019
38413
|
* 写作资产页签:题材基底库 / 推进模式库 / 反 AI 规则 / 写法引擎。
|
|
38020
|
-
*
|
|
38414
|
+
* 四大资产模块(题材 / 推进模式 / 反 AI 规则 / 叙事风格),注入到生成与审稿提示词中。
|
|
38021
38415
|
*/
|
|
38022
38416
|
/** 渲染题材树(带勾选当前题材)。 */
|
|
38023
38417
|
function GenreTree({ node, selected, onSelect }) {
|
|
@@ -38471,7 +38865,7 @@ window.__ModuleLoader__.load({
|
|
|
38471
38865
|
}),
|
|
38472
38866
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
38473
38867
|
className: panel_module_css_default.meta,
|
|
38474
|
-
children: "从内置 8
|
|
38868
|
+
children: "从内置 8 套叙事风格模板中一键选用,无需样本文本;绑定后生成与润色都遵循该风格。"
|
|
38475
38869
|
}),
|
|
38476
38870
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
38477
38871
|
style: {
|
|
@@ -41355,9 +41749,9 @@ window.__ModuleLoader__.load({
|
|
|
41355
41749
|
* ① 模型(提供方管理):提供方卡片(编辑/删除)+ 添加提供方 / 添加自定义提供方;
|
|
41356
41750
|
* ② 当前写作模型:提供商/模型下拉 + 测试连通 + 推理强度。
|
|
41357
41751
|
*/
|
|
41358
|
-
/**
|
|
41752
|
+
/** 目录不可用时回退的内置预设(对齐当前模型目录)。 */
|
|
41359
41753
|
const FALLBACK_MODEL_PRESETS = [
|
|
41360
|
-
"deepseek-
|
|
41754
|
+
"deepseek-flash",
|
|
41361
41755
|
"deepseek-v4-pro",
|
|
41362
41756
|
"deepseek-chat",
|
|
41363
41757
|
"deepseek-reasoner"
|
|
@@ -42125,6 +42519,8 @@ window.__ModuleLoader__.load({
|
|
|
42125
42519
|
generateModel: configDraft.generateModel,
|
|
42126
42520
|
reviewModel: configDraft.reviewModel,
|
|
42127
42521
|
auditModel: configDraft.auditModel,
|
|
42522
|
+
fallbackModel: configDraft.fallbackModel ?? "",
|
|
42523
|
+
autoTimeline: configDraft.autoTimeline ?? true,
|
|
42128
42524
|
reasoningEffort: configDraft.reasoningEffort ?? "off",
|
|
42129
42525
|
chapterChars: configDraft.chapterChars,
|
|
42130
42526
|
maxTokens: configDraft.maxTokens,
|
|
@@ -42249,41 +42645,108 @@ window.__ModuleLoader__.load({
|
|
|
42249
42645
|
className: panel_module_css_default.meta,
|
|
42250
42646
|
children: notice
|
|
42251
42647
|
}),
|
|
42252
|
-
settingsTab === "model" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
42253
|
-
|
|
42254
|
-
|
|
42255
|
-
|
|
42256
|
-
|
|
42257
|
-
|
|
42258
|
-
|
|
42259
|
-
|
|
42260
|
-
|
|
42261
|
-
|
|
42262
|
-
|
|
42263
|
-
|
|
42264
|
-
|
|
42265
|
-
|
|
42266
|
-
|
|
42267
|
-
|
|
42268
|
-
|
|
42269
|
-
|
|
42270
|
-
|
|
42271
|
-
|
|
42272
|
-
|
|
42273
|
-
|
|
42274
|
-
|
|
42648
|
+
settingsTab === "model" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
42649
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
42650
|
+
className: panel_module_css_default.card + " " + panel_module_css_default.settingsCard,
|
|
42651
|
+
style: { gap: "var(--nf-space-24)" },
|
|
42652
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
42653
|
+
className: panel_module_css_default.cardTitle,
|
|
42654
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(import_lucide_react.Brain, {
|
|
42655
|
+
size: 18,
|
|
42656
|
+
style: { verticalAlign: -3 }
|
|
42657
|
+
}), " 模型与推理"]
|
|
42658
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModelManager, {
|
|
42659
|
+
api,
|
|
42660
|
+
provider: configDraft.provider,
|
|
42661
|
+
model: configDraft.model,
|
|
42662
|
+
savedModels: configDraft.savedModels ?? [],
|
|
42663
|
+
onProvider: (v) => setConfigDraft({
|
|
42664
|
+
...configDraft,
|
|
42665
|
+
provider: v
|
|
42666
|
+
}),
|
|
42667
|
+
onModel: (v) => setConfigDraft({
|
|
42668
|
+
...configDraft,
|
|
42669
|
+
model: v
|
|
42670
|
+
}),
|
|
42671
|
+
onSavedModels: (models) => setConfigDraft({
|
|
42672
|
+
...configDraft,
|
|
42673
|
+
savedModels: models
|
|
42674
|
+
})
|
|
42675
|
+
})]
|
|
42676
|
+
}),
|
|
42677
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
42678
|
+
className: panel_module_css_default.card + " " + panel_module_css_default.settingsCard,
|
|
42679
|
+
style: { gap: "var(--nf-space-12)" },
|
|
42680
|
+
children: [
|
|
42681
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
42682
|
+
className: panel_module_css_default.cardTitle,
|
|
42683
|
+
children: "备用模型(故障自动切换)"
|
|
42684
|
+
}),
|
|
42685
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
42686
|
+
className: panel_module_css_default.field,
|
|
42687
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
|
|
42688
|
+
className: panel_module_css_default.fieldLabel,
|
|
42689
|
+
children: "主模型调用失败(限流 / 超时 / 额度 / 服务不可用)时,自动换它重试一次"
|
|
42690
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
42691
|
+
className: panel_module_css_default.input,
|
|
42692
|
+
value: configDraft.fallbackModel ?? "",
|
|
42693
|
+
onChange: (e) => setConfigDraft({
|
|
42694
|
+
...configDraft,
|
|
42695
|
+
fallbackModel: e.target.value
|
|
42696
|
+
}),
|
|
42697
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
42698
|
+
value: "",
|
|
42699
|
+
children: "不切换(关闭)"
|
|
42700
|
+
}), [.../* @__PURE__ */ new Set([configDraft.model, ...(configDraft.savedModels ?? []).map((m) => m.model)])].filter((m) => m !== "").map((m) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
42701
|
+
value: m,
|
|
42702
|
+
children: m
|
|
42703
|
+
}, m))]
|
|
42704
|
+
})]
|
|
42705
|
+
}),
|
|
42706
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
42707
|
+
className: panel_module_css_default.meta,
|
|
42708
|
+
children: "只对可重试的失败生效:用户取消、参数错误不会切换;正文生成只在「一个字都没产出」时才换模型重试,避免重复生成。"
|
|
42709
|
+
})
|
|
42710
|
+
]
|
|
42711
|
+
}),
|
|
42712
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
42713
|
+
className: panel_module_css_default.card + " " + panel_module_css_default.settingsCard,
|
|
42714
|
+
style: { gap: "var(--nf-space-12)" },
|
|
42715
|
+
children: [
|
|
42716
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
42717
|
+
className: panel_module_css_default.cardTitle,
|
|
42718
|
+
children: "故事时间线"
|
|
42719
|
+
}),
|
|
42720
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
42721
|
+
className: panel_module_css_default.row,
|
|
42722
|
+
style: {
|
|
42723
|
+
gap: "var(--nf-space-8)",
|
|
42724
|
+
alignItems: "center"
|
|
42725
|
+
},
|
|
42726
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
42727
|
+
type: "checkbox",
|
|
42728
|
+
checked: configDraft.autoTimeline ?? true,
|
|
42729
|
+
onChange: (e) => setConfigDraft({
|
|
42730
|
+
...configDraft,
|
|
42731
|
+
autoTimeline: e.target.checked
|
|
42732
|
+
})
|
|
42733
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "出章后自动抽取时间线事件(时间 / 地点 / 在场角色 / 事件)" })]
|
|
42734
|
+
}),
|
|
42735
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
42736
|
+
className: panel_module_css_default.meta,
|
|
42737
|
+
children: "抽取失败不会阻断出章;可在侧柜「故事时间线」里手工抽取、修正,并一键检查时间倒流 / 地点瞬移等矛盾。"
|
|
42738
|
+
})
|
|
42739
|
+
]
|
|
42740
|
+
}),
|
|
42741
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReasoningSection, {
|
|
42742
|
+
reasoningEffort: configDraft.reasoningEffort ?? "off",
|
|
42743
|
+
analysisReasoning: configDraft.analysisReasoning ?? "low",
|
|
42744
|
+
onChange: (patch) => setConfigDraft({
|
|
42275
42745
|
...configDraft,
|
|
42276
|
-
|
|
42746
|
+
...patch
|
|
42277
42747
|
})
|
|
42278
|
-
})]
|
|
42279
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReasoningSection, {
|
|
42280
|
-
reasoningEffort: configDraft.reasoningEffort ?? "off",
|
|
42281
|
-
analysisReasoning: configDraft.analysisReasoning ?? "low",
|
|
42282
|
-
onChange: (patch) => setConfigDraft({
|
|
42283
|
-
...configDraft,
|
|
42284
|
-
...patch
|
|
42285
42748
|
})
|
|
42286
|
-
|
|
42749
|
+
] }),
|
|
42287
42750
|
settingsTab === "files" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
42288
42751
|
className: panel_module_css_default.card + " " + panel_module_css_default.settingsCard,
|
|
42289
42752
|
style: { gap: "var(--nf-space-24)" },
|
|
@@ -43846,7 +44309,7 @@ window.__ModuleLoader__.load({
|
|
|
43846
44309
|
* 作者级首页容器:书架页左侧导航 + 内容区。
|
|
43847
44310
|
* 导航复用工作区 .panelNav 玻璃卡片样式(同款),导航项为作者级:书架/改编/资产库/全局资产库/AI 进度/设置。
|
|
43848
44311
|
*/
|
|
43849
|
-
const PLUGIN_VERSION = "1.
|
|
44312
|
+
const PLUGIN_VERSION = "1.3.0-alpha";
|
|
43850
44313
|
/** GitHub 仓库地址(关于区块点击跳转)。 */
|
|
43851
44314
|
const REPO_URL = "https://github.com/watersxya/dsh-novel-forge";
|
|
43852
44315
|
/** 顶层 tab(横向,墨案:创作 / 灵感策划 / 资产 / 设置)+ 组内二级页。 */
|
|
@@ -47230,322 +47693,1279 @@ window.__ModuleLoader__.load({
|
|
|
47230
47693
|
})]
|
|
47231
47694
|
}, i))
|
|
47232
47695
|
})]
|
|
47233
|
-
})]
|
|
47234
|
-
}),
|
|
47235
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
47236
|
-
className: `${panel_module_css_default.card} ${panel_module_css_default.settingsCard}`,
|
|
47237
|
-
style: { gap: "var(--nf-space-6)" },
|
|
47238
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
47239
|
-
style: {
|
|
47240
|
-
fontSize: "var(--nf-fs-16)",
|
|
47241
|
-
fontWeight: 600
|
|
47242
|
-
},
|
|
47243
|
-
children: " 编辑待办(已采纳)"
|
|
47244
|
-
}), todos.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
47245
|
-
className: panel_module_css_default.meta,
|
|
47246
|
-
children: "还没有。点上面「加入待办」,把风险/修复记到这里,做完勾掉。这些也会出现在工作流主页的「待办队列」。"
|
|
47247
|
-
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
47696
|
+
})]
|
|
47697
|
+
}),
|
|
47698
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
47699
|
+
className: `${panel_module_css_default.card} ${panel_module_css_default.settingsCard}`,
|
|
47700
|
+
style: { gap: "var(--nf-space-6)" },
|
|
47701
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
47702
|
+
style: {
|
|
47703
|
+
fontSize: "var(--nf-fs-16)",
|
|
47704
|
+
fontWeight: 600
|
|
47705
|
+
},
|
|
47706
|
+
children: " 编辑待办(已采纳)"
|
|
47707
|
+
}), todos.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
47708
|
+
className: panel_module_css_default.meta,
|
|
47709
|
+
children: "还没有。点上面「加入待办」,把风险/修复记到这里,做完勾掉。这些也会出现在工作流主页的「待办队列」。"
|
|
47710
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
47711
|
+
style: {
|
|
47712
|
+
margin: 0,
|
|
47713
|
+
paddingLeft: 0,
|
|
47714
|
+
listStyle: "none",
|
|
47715
|
+
display: "grid",
|
|
47716
|
+
gap: "var(--nf-space-6)",
|
|
47717
|
+
fontSize: "var(--nf-fs-14)"
|
|
47718
|
+
},
|
|
47719
|
+
children: todos.map((t) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
|
|
47720
|
+
style: {
|
|
47721
|
+
display: "flex",
|
|
47722
|
+
alignItems: "center",
|
|
47723
|
+
gap: 8
|
|
47724
|
+
},
|
|
47725
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
47726
|
+
style: {
|
|
47727
|
+
display: "flex",
|
|
47728
|
+
alignItems: "center",
|
|
47729
|
+
gap: "var(--nf-space-6)",
|
|
47730
|
+
flex: 1,
|
|
47731
|
+
cursor: "pointer"
|
|
47732
|
+
},
|
|
47733
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
47734
|
+
type: "checkbox",
|
|
47735
|
+
checked: t.done,
|
|
47736
|
+
disabled: todosBusy,
|
|
47737
|
+
onChange: () => {
|
|
47738
|
+
toggleTodo(t.id);
|
|
47739
|
+
}
|
|
47740
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
47741
|
+
style: {
|
|
47742
|
+
textDecoration: t.done ? "line-through" : "none",
|
|
47743
|
+
color: t.done ? "var(--nf-text-2)" : void 0
|
|
47744
|
+
},
|
|
47745
|
+
children: t.text
|
|
47746
|
+
})]
|
|
47747
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
47748
|
+
type: "button",
|
|
47749
|
+
className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
|
|
47750
|
+
title: "删除",
|
|
47751
|
+
onClick: () => {
|
|
47752
|
+
removeTodo(t.id);
|
|
47753
|
+
},
|
|
47754
|
+
children: "×"
|
|
47755
|
+
})]
|
|
47756
|
+
}, t.id))
|
|
47757
|
+
})]
|
|
47758
|
+
})
|
|
47759
|
+
]
|
|
47760
|
+
})
|
|
47761
|
+
]
|
|
47762
|
+
});
|
|
47763
|
+
}
|
|
47764
|
+
//#endregion
|
|
47765
|
+
//#region src/client/panel/KnowledgeBaseView.tsx
|
|
47766
|
+
/**
|
|
47767
|
+
* 书内知识库:添加/删除参考资料,生成/规划时自动检索注入。
|
|
47768
|
+
* T2 主从布局:左列文档列表 + 新建入口,右侧文档详情 / 新建表单。
|
|
47769
|
+
*/
|
|
47770
|
+
function KnowledgeBaseView({ api }) {
|
|
47771
|
+
const [docs, setDocs] = (0, react.useState)([]);
|
|
47772
|
+
const [title, setTitle] = (0, react.useState)("");
|
|
47773
|
+
const [content, setContent] = (0, react.useState)("");
|
|
47774
|
+
const [busy, setBusy] = (0, react.useState)(false);
|
|
47775
|
+
const [notice, setNotice] = (0, react.useState)("");
|
|
47776
|
+
const [error, setError] = (0, react.useState)("");
|
|
47777
|
+
/** 左列选中的文档 id;null 且 addMode=false 时显示空态。 */
|
|
47778
|
+
const [selectedId, setSelectedId] = (0, react.useState)(null);
|
|
47779
|
+
/** 新建模式:右栏显示添加表单。 */
|
|
47780
|
+
const [addMode, setAddMode] = (0, react.useState)(false);
|
|
47781
|
+
const load = async () => {
|
|
47782
|
+
try {
|
|
47783
|
+
const r = await api.knowledgeList();
|
|
47784
|
+
setDocs(r.docs);
|
|
47785
|
+
} catch (e) {
|
|
47786
|
+
setError(e.message);
|
|
47787
|
+
}
|
|
47788
|
+
};
|
|
47789
|
+
(0, react.useEffect)(() => {
|
|
47790
|
+
load();
|
|
47791
|
+
}, []);
|
|
47792
|
+
const add = async () => {
|
|
47793
|
+
if (title.trim() === "") {
|
|
47794
|
+
setError("标题不能为空");
|
|
47795
|
+
return;
|
|
47796
|
+
}
|
|
47797
|
+
setBusy(true);
|
|
47798
|
+
setError("");
|
|
47799
|
+
setNotice("");
|
|
47800
|
+
try {
|
|
47801
|
+
const r = await api.knowledgeAdd({
|
|
47802
|
+
title: title.trim(),
|
|
47803
|
+
content: content.trim()
|
|
47804
|
+
});
|
|
47805
|
+
setDocs(r.docs);
|
|
47806
|
+
setTitle("");
|
|
47807
|
+
setContent("");
|
|
47808
|
+
setNotice(" 已添加");
|
|
47809
|
+
setAddMode(false);
|
|
47810
|
+
const added = r.docs[r.docs.length - 1];
|
|
47811
|
+
if (added !== void 0) setSelectedId(added.id);
|
|
47812
|
+
} catch (e) {
|
|
47813
|
+
setError(e.message);
|
|
47814
|
+
} finally {
|
|
47815
|
+
setBusy(false);
|
|
47816
|
+
}
|
|
47817
|
+
};
|
|
47818
|
+
const remove = async (id) => {
|
|
47819
|
+
setBusy(true);
|
|
47820
|
+
setError("");
|
|
47821
|
+
try {
|
|
47822
|
+
const r = await api.knowledgeRemove(id);
|
|
47823
|
+
setDocs(r.docs);
|
|
47824
|
+
if (selectedId === id) setSelectedId(null);
|
|
47825
|
+
} catch (e) {
|
|
47826
|
+
setError(e.message);
|
|
47827
|
+
} finally {
|
|
47828
|
+
setBusy(false);
|
|
47829
|
+
}
|
|
47830
|
+
};
|
|
47831
|
+
const selected = docs.find((d) => d.id === selectedId);
|
|
47832
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
47833
|
+
className: panel_module_css_default.authorPageBodyFlow,
|
|
47834
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
47835
|
+
className: panel_module_css_default.card,
|
|
47836
|
+
style: {
|
|
47837
|
+
padding: 0,
|
|
47838
|
+
overflow: "hidden"
|
|
47839
|
+
},
|
|
47840
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
47841
|
+
className: panel_module_css_default.t2Master,
|
|
47842
|
+
style: { minHeight: 420 },
|
|
47843
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("aside", {
|
|
47844
|
+
className: panel_module_css_default.t2Rail,
|
|
47845
|
+
"aria-label": "知识库文档",
|
|
47846
|
+
children: [
|
|
47847
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
47848
|
+
className: panel_module_css_default.t2RailHead,
|
|
47849
|
+
children: " 书内知识库"
|
|
47850
|
+
}),
|
|
47851
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
47852
|
+
type: "button",
|
|
47853
|
+
className: panel_module_css_default.t2RailBtn,
|
|
47854
|
+
"data-active": addMode ? "" : void 0,
|
|
47855
|
+
onClick: () => {
|
|
47856
|
+
setAddMode(true);
|
|
47857
|
+
setSelectedId(null);
|
|
47858
|
+
},
|
|
47859
|
+
title: "添加一篇参考文档(生成时按章节检索注入)",
|
|
47860
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
47861
|
+
"aria-hidden": true,
|
|
47862
|
+
children: "+"
|
|
47863
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "新建文档" })]
|
|
47864
|
+
}),
|
|
47865
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: panel_module_css_default.t2RailSep }),
|
|
47866
|
+
docs.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
47867
|
+
className: panel_module_css_default.t2RailMeta,
|
|
47868
|
+
children: "暂无文档"
|
|
47869
|
+
}) : docs.map((d) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
47870
|
+
type: "button",
|
|
47871
|
+
role: "tab",
|
|
47872
|
+
"aria-selected": !addMode && selectedId === d.id,
|
|
47873
|
+
className: panel_module_css_default.t2RailBtn,
|
|
47874
|
+
"data-active": !addMode && selectedId === d.id ? "" : void 0,
|
|
47875
|
+
title: d.content.slice(0, 80),
|
|
47876
|
+
onClick: () => {
|
|
47877
|
+
setAddMode(false);
|
|
47878
|
+
setSelectedId(d.id);
|
|
47879
|
+
},
|
|
47880
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { "aria-hidden": true }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
47881
|
+
style: {
|
|
47882
|
+
flex: 1,
|
|
47883
|
+
minWidth: 0,
|
|
47884
|
+
overflow: "hidden",
|
|
47885
|
+
textOverflow: "ellipsis",
|
|
47886
|
+
whiteSpace: "nowrap"
|
|
47887
|
+
},
|
|
47888
|
+
children: d.title
|
|
47889
|
+
})]
|
|
47890
|
+
}, d.id)),
|
|
47891
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: panel_module_css_default.t2RailSep }),
|
|
47892
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
47893
|
+
className: panel_module_css_default.t2RailMeta,
|
|
47894
|
+
children: [
|
|
47895
|
+
"共 ",
|
|
47896
|
+
docs.length,
|
|
47897
|
+
" 篇 · 正文生成时按当前章节检索注入"
|
|
47898
|
+
]
|
|
47899
|
+
})
|
|
47900
|
+
]
|
|
47901
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
47902
|
+
className: panel_module_css_default.t2Content,
|
|
47903
|
+
children: [addMode ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
47904
|
+
className: panel_module_css_default.cardTitleLg,
|
|
47905
|
+
children: "+ 新建文档"
|
|
47906
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
47907
|
+
style: {
|
|
47908
|
+
display: "flex",
|
|
47909
|
+
flexDirection: "column",
|
|
47910
|
+
gap: "var(--nf-space-6)",
|
|
47911
|
+
maxWidth: "var(--nf-measure, 720px)"
|
|
47912
|
+
},
|
|
47913
|
+
children: [
|
|
47914
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
47915
|
+
className: panel_module_css_default.input,
|
|
47916
|
+
value: title,
|
|
47917
|
+
onChange: (e) => setTitle(e.target.value),
|
|
47918
|
+
placeholder: "标题(如:天机锁设定 / 止水驿关系表)"
|
|
47919
|
+
}),
|
|
47920
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
|
|
47921
|
+
className: panel_module_css_default.input,
|
|
47922
|
+
style: {
|
|
47923
|
+
minHeight: 160,
|
|
47924
|
+
resize: "vertical"
|
|
47925
|
+
},
|
|
47926
|
+
value: content,
|
|
47927
|
+
onChange: (e) => setContent(e.target.value),
|
|
47928
|
+
placeholder: "内容(将被检索注入生成提示)"
|
|
47929
|
+
}),
|
|
47930
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
47931
|
+
style: {
|
|
47932
|
+
display: "flex",
|
|
47933
|
+
alignItems: "center",
|
|
47934
|
+
gap: "var(--nf-space-8)"
|
|
47935
|
+
},
|
|
47936
|
+
children: [
|
|
47937
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
47938
|
+
type: "button",
|
|
47939
|
+
className: `${panel_module_css_default.button} ${panel_module_css_default.buttonPrimary}`,
|
|
47940
|
+
disabled: busy,
|
|
47941
|
+
onClick: () => {
|
|
47942
|
+
add();
|
|
47943
|
+
},
|
|
47944
|
+
children: "添加"
|
|
47945
|
+
}),
|
|
47946
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
47947
|
+
type: "button",
|
|
47948
|
+
className: panel_module_css_default.button,
|
|
47949
|
+
onClick: () => {
|
|
47950
|
+
setAddMode(false);
|
|
47951
|
+
},
|
|
47952
|
+
children: "取消"
|
|
47953
|
+
}),
|
|
47954
|
+
notice !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
47955
|
+
style: {
|
|
47956
|
+
fontSize: "var(--nf-fs-12)",
|
|
47957
|
+
color: "var(--nf-success)"
|
|
47958
|
+
},
|
|
47959
|
+
children: notice
|
|
47960
|
+
})
|
|
47961
|
+
]
|
|
47962
|
+
})
|
|
47963
|
+
]
|
|
47964
|
+
})] }) : selected !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
47965
|
+
className: panel_module_css_default.row,
|
|
47966
|
+
style: {
|
|
47967
|
+
justifyContent: "space-between",
|
|
47968
|
+
flexWrap: "wrap"
|
|
47969
|
+
},
|
|
47970
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
47971
|
+
className: panel_module_css_default.cardTitleLg,
|
|
47972
|
+
children: [" ", selected.title]
|
|
47973
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
47974
|
+
type: "button",
|
|
47975
|
+
className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
|
|
47976
|
+
disabled: busy,
|
|
47977
|
+
onClick: () => {
|
|
47978
|
+
remove(selected.id);
|
|
47979
|
+
},
|
|
47980
|
+
children: "删除"
|
|
47981
|
+
})]
|
|
47982
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
47983
|
+
className: `${panel_module_css_default.planBeats} ${panel_module_css_default.docsSurface}`,
|
|
47984
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
47985
|
+
style: {
|
|
47986
|
+
fontSize: "var(--nf-fs-14)",
|
|
47987
|
+
lineHeight: 1.7,
|
|
47988
|
+
whiteSpace: "pre-wrap"
|
|
47989
|
+
},
|
|
47990
|
+
children: selected.content !== "" ? selected.content : "(空文档)"
|
|
47991
|
+
})
|
|
47992
|
+
})] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
47993
|
+
className: panel_module_css_default.planDetailEmpty,
|
|
47994
|
+
style: { minHeight: 300 },
|
|
47995
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
47996
|
+
className: panel_module_css_default.meta,
|
|
47997
|
+
children: "← 从左侧选择文档,或「+ 新建文档」添加参考资料。"
|
|
47998
|
+
})
|
|
47999
|
+
}), error !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
48000
|
+
style: {
|
|
48001
|
+
color: "var(--nf-error)",
|
|
48002
|
+
fontSize: "var(--nf-fs-14)"
|
|
48003
|
+
},
|
|
48004
|
+
children: [" ", error]
|
|
48005
|
+
})]
|
|
48006
|
+
})]
|
|
48007
|
+
})
|
|
48008
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
48009
|
+
className: panel_module_css_default.meta,
|
|
48010
|
+
children: "自由参考文档:零散设定/资料/碎片放这里;结构化设定(世界观/角色/境界/红线)请放「本书设定」。"
|
|
48011
|
+
})]
|
|
48012
|
+
});
|
|
48013
|
+
}
|
|
48014
|
+
//#endregion
|
|
48015
|
+
//#region src/client/panel/TimelineView.tsx
|
|
48016
|
+
/**
|
|
48017
|
+
* 故事时间线:把逐章抽取的「时间点 / 地点 / 在场角色 / 事件」按章节顺序排开,
|
|
48018
|
+
* 带规则初筛 + AI 复核的矛盾清单,并支持就地修正(手改后标记为 manual)。
|
|
48019
|
+
*
|
|
48020
|
+
* 与「编年录」的分工:编年录记事实状态,这里记**顺序**——专门抓时间倒流、
|
|
48021
|
+
* 地点瞬移、跨度不合理这类长篇最容易崩的地方。
|
|
48022
|
+
*/
|
|
48023
|
+
const SEVERITY_LABEL = {
|
|
48024
|
+
high: "高",
|
|
48025
|
+
medium: "中",
|
|
48026
|
+
low: "低"
|
|
48027
|
+
};
|
|
48028
|
+
function TimelineView({ api, chapters }) {
|
|
48029
|
+
const [events, setEvents] = (0, react.useState)([]);
|
|
48030
|
+
const [issues, setIssues] = (0, react.useState)([]);
|
|
48031
|
+
const [busy, setBusy] = (0, react.useState)(false);
|
|
48032
|
+
const [error, setError] = (0, react.useState)("");
|
|
48033
|
+
const [notice, setNotice] = (0, react.useState)("");
|
|
48034
|
+
const [extractNo, setExtractNo] = (0, react.useState)(chapters[chapters.length - 1] ?? "");
|
|
48035
|
+
const [editing, setEditing] = (0, react.useState)(null);
|
|
48036
|
+
const refresh = (0, react.useCallback)(async (showError = true) => {
|
|
48037
|
+
try {
|
|
48038
|
+
const r = await api.timeline();
|
|
48039
|
+
setEvents(r.events);
|
|
48040
|
+
setIssues(r.issues ?? []);
|
|
48041
|
+
} catch (err) {
|
|
48042
|
+
if (showError) setError(err.message);
|
|
48043
|
+
}
|
|
48044
|
+
}, [api]);
|
|
48045
|
+
(0, react.useEffect)(() => {
|
|
48046
|
+
refresh(false);
|
|
48047
|
+
}, [refresh]);
|
|
48048
|
+
const grouped = (0, react.useMemo)(() => {
|
|
48049
|
+
const map = /* @__PURE__ */ new Map();
|
|
48050
|
+
for (const e of events) {
|
|
48051
|
+
const list = map.get(e.chapterNo) ?? [];
|
|
48052
|
+
list.push(e);
|
|
48053
|
+
map.set(e.chapterNo, list);
|
|
48054
|
+
}
|
|
48055
|
+
return [...map.entries()].sort((a, b) => a[0] - b[0]);
|
|
48056
|
+
}, [events]);
|
|
48057
|
+
const run = (0, react.useCallback)(async (label, fn) => {
|
|
48058
|
+
setBusy(true);
|
|
48059
|
+
setError("");
|
|
48060
|
+
setNotice("");
|
|
48061
|
+
try {
|
|
48062
|
+
await fn();
|
|
48063
|
+
setNotice(label);
|
|
48064
|
+
} catch (err) {
|
|
48065
|
+
setError(err.message);
|
|
48066
|
+
} finally {
|
|
48067
|
+
setBusy(false);
|
|
48068
|
+
}
|
|
48069
|
+
}, []);
|
|
48070
|
+
const handleExtract = () => {
|
|
48071
|
+
if (extractNo === "") return;
|
|
48072
|
+
run(`已抽取第 ${extractNo} 章时间线`, async () => {
|
|
48073
|
+
await api.timelineExtract(Number(extractNo));
|
|
48074
|
+
await refresh();
|
|
48075
|
+
});
|
|
48076
|
+
};
|
|
48077
|
+
const handleCheck = () => {
|
|
48078
|
+
run("时间线检查完成", async () => {
|
|
48079
|
+
const r = await api.timelineCheck();
|
|
48080
|
+
setIssues(r.issues ?? []);
|
|
48081
|
+
});
|
|
48082
|
+
};
|
|
48083
|
+
const handleSaveEdit = () => {
|
|
48084
|
+
if (editing === null) return;
|
|
48085
|
+
run("已保存修改", async () => {
|
|
48086
|
+
await api.timelineUpdate({
|
|
48087
|
+
...editing,
|
|
48088
|
+
source: "manual"
|
|
48089
|
+
});
|
|
48090
|
+
setEditing(null);
|
|
48091
|
+
await refresh();
|
|
48092
|
+
});
|
|
48093
|
+
};
|
|
48094
|
+
const handleRemove = (id) => {
|
|
48095
|
+
run("已删除该事件", async () => {
|
|
48096
|
+
await api.timelineRemove(id);
|
|
48097
|
+
await refresh();
|
|
48098
|
+
});
|
|
48099
|
+
};
|
|
48100
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
48101
|
+
className: panel_module_css_default.card,
|
|
48102
|
+
style: { gap: "var(--nf-space-12)" },
|
|
48103
|
+
children: [
|
|
48104
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
48105
|
+
className: panel_module_css_default.row,
|
|
48106
|
+
style: {
|
|
48107
|
+
justifyContent: "space-between",
|
|
48108
|
+
alignItems: "center",
|
|
48109
|
+
flexWrap: "wrap",
|
|
48110
|
+
gap: "var(--nf-space-8)"
|
|
48111
|
+
},
|
|
48112
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
48113
|
+
className: panel_module_css_default.cardTitle,
|
|
48114
|
+
children: "故事时间线"
|
|
48115
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
48116
|
+
className: panel_module_css_default.meta,
|
|
48117
|
+
children: [
|
|
48118
|
+
events.length,
|
|
48119
|
+
" 条事件 · ",
|
|
48120
|
+
grouped.length,
|
|
48121
|
+
" 章"
|
|
48122
|
+
]
|
|
48123
|
+
})]
|
|
48124
|
+
}),
|
|
48125
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
48126
|
+
className: panel_module_css_default.row,
|
|
48127
|
+
style: {
|
|
48128
|
+
flexWrap: "wrap",
|
|
48129
|
+
gap: "var(--nf-space-8)",
|
|
48130
|
+
alignItems: "center"
|
|
48131
|
+
},
|
|
48132
|
+
children: [
|
|
48133
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
48134
|
+
className: panel_module_css_default.input,
|
|
48135
|
+
value: extractNo,
|
|
48136
|
+
onChange: (e) => setExtractNo(e.target.value === "" ? "" : Number(e.target.value)),
|
|
48137
|
+
title: "选择要抽取时间线的章节",
|
|
48138
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
48139
|
+
value: "",
|
|
48140
|
+
children: "选择章节…"
|
|
48141
|
+
}), chapters.map((no) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("option", {
|
|
48142
|
+
value: no,
|
|
48143
|
+
children: [
|
|
48144
|
+
"第 ",
|
|
48145
|
+
no,
|
|
48146
|
+
" 章"
|
|
48147
|
+
]
|
|
48148
|
+
}, no))]
|
|
48149
|
+
}),
|
|
48150
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
48151
|
+
type: "button",
|
|
48152
|
+
className: panel_module_css_default.button,
|
|
48153
|
+
disabled: busy || extractNo === "",
|
|
48154
|
+
onClick: handleExtract,
|
|
48155
|
+
children: "抽取本章时间线"
|
|
48156
|
+
}),
|
|
48157
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
48158
|
+
type: "button",
|
|
48159
|
+
className: panel_module_css_default.button,
|
|
48160
|
+
disabled: busy || events.length === 0,
|
|
48161
|
+
onClick: handleCheck,
|
|
48162
|
+
children: "检查时间线矛盾"
|
|
48163
|
+
})
|
|
48164
|
+
]
|
|
48165
|
+
}),
|
|
48166
|
+
notice !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
48167
|
+
style: {
|
|
48168
|
+
color: "var(--nf-success)",
|
|
48169
|
+
fontSize: "var(--nf-text-12)"
|
|
48170
|
+
},
|
|
48171
|
+
children: notice
|
|
48172
|
+
}),
|
|
48173
|
+
error !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
48174
|
+
style: {
|
|
48175
|
+
color: "var(--nf-error)",
|
|
48176
|
+
fontSize: "var(--nf-text-12)"
|
|
48177
|
+
},
|
|
48178
|
+
children: error
|
|
48179
|
+
}),
|
|
48180
|
+
issues.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
48181
|
+
style: {
|
|
48182
|
+
border: "1px solid var(--nf-border)",
|
|
48183
|
+
borderRadius: 8,
|
|
48184
|
+
padding: 8,
|
|
48185
|
+
background: "var(--nf-bg-inset)"
|
|
48186
|
+
},
|
|
48187
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("b", {
|
|
48188
|
+
style: { fontSize: "var(--nf-fs-12)" },
|
|
48189
|
+
children: [
|
|
48190
|
+
"发现 ",
|
|
48191
|
+
issues.length,
|
|
48192
|
+
" 处时间线问题"
|
|
48193
|
+
]
|
|
48194
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
48195
|
+
style: {
|
|
48196
|
+
display: "flex",
|
|
48197
|
+
flexDirection: "column",
|
|
48198
|
+
gap: 6,
|
|
48199
|
+
marginTop: 6
|
|
48200
|
+
},
|
|
48201
|
+
children: issues.map((issue, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
48202
|
+
style: { fontSize: "var(--nf-fs-12)" },
|
|
48203
|
+
children: [
|
|
48204
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
48205
|
+
className: panel_module_css_default.lfPill,
|
|
48206
|
+
"data-phase": issue.severity === "high" ? "failed" : "requesting",
|
|
48207
|
+
children: SEVERITY_LABEL[issue.severity]
|
|
48208
|
+
}),
|
|
48209
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
48210
|
+
style: { marginLeft: 6 },
|
|
48211
|
+
children: [issue.chapters.length > 0 ? `第 ${issue.chapters.join("、")} 章:` : "", issue.item]
|
|
48212
|
+
}),
|
|
48213
|
+
issue.suggestion !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
48214
|
+
className: panel_module_css_default.meta,
|
|
48215
|
+
style: { marginLeft: 6 },
|
|
48216
|
+
children: ["建议:", issue.suggestion]
|
|
48217
|
+
})
|
|
48218
|
+
]
|
|
48219
|
+
}, i))
|
|
48220
|
+
})]
|
|
48221
|
+
}),
|
|
48222
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
48223
|
+
style: {
|
|
48224
|
+
display: "flex",
|
|
48225
|
+
flexDirection: "column",
|
|
48226
|
+
gap: 10,
|
|
48227
|
+
overflowY: "auto",
|
|
48228
|
+
maxHeight: "52vh"
|
|
48229
|
+
},
|
|
48230
|
+
children: [events.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
48231
|
+
className: panel_module_css_default.meta,
|
|
48232
|
+
children: "还没有时间线事件。生成章节后会自动抽取,也可以在上面选一章手工抽取。"
|
|
48233
|
+
}), grouped.map(([no, list]) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
48234
|
+
className: panel_module_css_default.meta,
|
|
48235
|
+
style: { marginBottom: 4 },
|
|
48236
|
+
children: [
|
|
48237
|
+
"第 ",
|
|
48238
|
+
no,
|
|
48239
|
+
" 章 · ",
|
|
48240
|
+
list.length,
|
|
48241
|
+
" 条"
|
|
48242
|
+
]
|
|
48243
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
48244
|
+
style: {
|
|
48245
|
+
display: "flex",
|
|
48246
|
+
flexDirection: "column",
|
|
48247
|
+
gap: 4
|
|
48248
|
+
},
|
|
48249
|
+
children: list.map((e) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
48250
|
+
style: {
|
|
48251
|
+
border: "1px solid var(--nf-border)",
|
|
48252
|
+
borderRadius: 8,
|
|
48253
|
+
padding: "6px 8px",
|
|
48254
|
+
fontSize: "var(--nf-fs-12)"
|
|
48255
|
+
},
|
|
48256
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
48257
|
+
style: {
|
|
48258
|
+
display: "flex",
|
|
48259
|
+
gap: 6,
|
|
48260
|
+
alignItems: "baseline",
|
|
48261
|
+
flexWrap: "wrap"
|
|
48262
|
+
},
|
|
48263
|
+
children: [
|
|
48264
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", { children: e.time !== "" ? e.time : "(未标注时间)" }),
|
|
48265
|
+
e.place !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
48266
|
+
className: panel_module_css_default.meta,
|
|
48267
|
+
children: ["@", e.place]
|
|
48268
|
+
}),
|
|
48269
|
+
e.characters.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
48270
|
+
className: panel_module_css_default.meta,
|
|
48271
|
+
children: e.characters.join("、")
|
|
48272
|
+
}),
|
|
48273
|
+
e.source === "manual" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
48274
|
+
className: panel_module_css_default.meta,
|
|
48275
|
+
children: "(手改)"
|
|
48276
|
+
}),
|
|
48277
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
48278
|
+
style: {
|
|
48279
|
+
marginLeft: "auto",
|
|
48280
|
+
display: "flex",
|
|
48281
|
+
gap: 4
|
|
48282
|
+
},
|
|
48283
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
48284
|
+
type: "button",
|
|
48285
|
+
className: panel_module_css_default.iconButton,
|
|
48286
|
+
title: "修正这条事件",
|
|
48287
|
+
onClick: () => setEditing({ ...e }),
|
|
48288
|
+
children: "✎"
|
|
48289
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
48290
|
+
type: "button",
|
|
48291
|
+
className: panel_module_css_default.iconButton,
|
|
48292
|
+
title: "删除这条事件",
|
|
48293
|
+
onClick: () => handleRemove(e.id),
|
|
48294
|
+
children: "×"
|
|
48295
|
+
})]
|
|
48296
|
+
})
|
|
48297
|
+
]
|
|
48298
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
48299
|
+
style: { marginTop: 2 },
|
|
48300
|
+
children: e.event
|
|
48301
|
+
})]
|
|
48302
|
+
}, e.id))
|
|
48303
|
+
})] }, no))]
|
|
48304
|
+
}),
|
|
48305
|
+
editing !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
48306
|
+
style: {
|
|
48307
|
+
position: "fixed",
|
|
48308
|
+
inset: 0,
|
|
48309
|
+
background: "rgba(0,0,0,.45)",
|
|
48310
|
+
zIndex: 60,
|
|
48311
|
+
display: "flex",
|
|
48312
|
+
alignItems: "center",
|
|
48313
|
+
justifyContent: "center",
|
|
48314
|
+
padding: 20
|
|
48315
|
+
},
|
|
48316
|
+
onClick: () => setEditing(null),
|
|
48317
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
48318
|
+
onClick: (ev) => ev.stopPropagation(),
|
|
48319
|
+
style: {
|
|
48320
|
+
background: "var(--nf-bg)",
|
|
48321
|
+
border: "1px solid var(--nf-border)",
|
|
48322
|
+
borderRadius: 10,
|
|
48323
|
+
width: "min(560px, 94vw)",
|
|
48324
|
+
padding: 12,
|
|
48325
|
+
display: "flex",
|
|
48326
|
+
flexDirection: "column",
|
|
48327
|
+
gap: 8
|
|
48328
|
+
},
|
|
48329
|
+
children: [
|
|
48330
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("b", {
|
|
48331
|
+
style: { fontSize: "var(--nf-fs-13)" },
|
|
48332
|
+
children: [
|
|
48333
|
+
"修正时间线事件 · 第 ",
|
|
48334
|
+
editing.chapterNo,
|
|
48335
|
+
" 章"
|
|
48336
|
+
]
|
|
48337
|
+
}),
|
|
48338
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
48339
|
+
className: panel_module_css_default.field,
|
|
48340
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
48341
|
+
className: panel_module_css_default.fieldLabel,
|
|
48342
|
+
children: "故事内时间"
|
|
48343
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
48344
|
+
className: panel_module_css_default.input,
|
|
48345
|
+
value: editing.time,
|
|
48346
|
+
onChange: (e) => setEditing({
|
|
48347
|
+
...editing,
|
|
48348
|
+
time: e.target.value
|
|
48349
|
+
}),
|
|
48350
|
+
placeholder: "如:第三日黄昏 / 入宗三个月后"
|
|
48351
|
+
})]
|
|
48352
|
+
}),
|
|
48353
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
48354
|
+
className: panel_module_css_default.field,
|
|
48355
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
48356
|
+
className: panel_module_css_default.fieldLabel,
|
|
48357
|
+
children: "地点"
|
|
48358
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
48359
|
+
className: panel_module_css_default.input,
|
|
48360
|
+
value: editing.place,
|
|
48361
|
+
onChange: (e) => setEditing({
|
|
48362
|
+
...editing,
|
|
48363
|
+
place: e.target.value
|
|
48364
|
+
})
|
|
48365
|
+
})]
|
|
48366
|
+
}),
|
|
48367
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
48368
|
+
className: panel_module_css_default.field,
|
|
48369
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
48370
|
+
className: panel_module_css_default.fieldLabel,
|
|
48371
|
+
children: "在场角色(顿号或逗号分隔)"
|
|
48372
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
48373
|
+
className: panel_module_css_default.input,
|
|
48374
|
+
value: editing.characters.join("、"),
|
|
48375
|
+
onChange: (e) => setEditing({
|
|
48376
|
+
...editing,
|
|
48377
|
+
characters: e.target.value.split(/[、,,\s]+/).filter(Boolean)
|
|
48378
|
+
})
|
|
48379
|
+
})]
|
|
48380
|
+
}),
|
|
48381
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
48382
|
+
className: panel_module_css_default.field,
|
|
48383
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
48384
|
+
className: panel_module_css_default.fieldLabel,
|
|
48385
|
+
children: "事件"
|
|
48386
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
|
|
48387
|
+
className: panel_module_css_default.textarea,
|
|
48388
|
+
rows: 3,
|
|
48389
|
+
value: editing.event,
|
|
48390
|
+
onChange: (e) => setEditing({
|
|
48391
|
+
...editing,
|
|
48392
|
+
event: e.target.value
|
|
48393
|
+
})
|
|
48394
|
+
})]
|
|
48395
|
+
}),
|
|
48396
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
48397
|
+
className: panel_module_css_default.row,
|
|
48398
|
+
style: {
|
|
48399
|
+
justifyContent: "flex-end",
|
|
48400
|
+
gap: 6
|
|
48401
|
+
},
|
|
48402
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
48403
|
+
type: "button",
|
|
48404
|
+
className: panel_module_css_default.button,
|
|
48405
|
+
onClick: () => setEditing(null),
|
|
48406
|
+
children: "取消"
|
|
48407
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
48408
|
+
type: "button",
|
|
48409
|
+
className: panel_module_css_default.button + " " + panel_module_css_default.buttonPrimary,
|
|
48410
|
+
disabled: busy,
|
|
48411
|
+
onClick: handleSaveEdit,
|
|
48412
|
+
children: "保存"
|
|
48413
|
+
})]
|
|
48414
|
+
})
|
|
48415
|
+
]
|
|
48416
|
+
})
|
|
48417
|
+
})
|
|
48418
|
+
]
|
|
48419
|
+
});
|
|
48420
|
+
}
|
|
48421
|
+
//#endregion
|
|
48422
|
+
//#region src/tension.ts
|
|
48423
|
+
/** 参考曲线的中文标签(面板展示)。 */
|
|
48424
|
+
const TENSION_PRESET_LABELS = {
|
|
48425
|
+
escalation: "递进爬升",
|
|
48426
|
+
suspense: "悬疑加压",
|
|
48427
|
+
wave: "波浪呼吸",
|
|
48428
|
+
frontLoad: "前紧后稳",
|
|
48429
|
+
flat: "平稳推进",
|
|
48430
|
+
custom: "自定义"
|
|
48431
|
+
};
|
|
48432
|
+
//#endregion
|
|
48433
|
+
//#region src/client/panel/TensionView.tsx
|
|
48434
|
+
/**
|
|
48435
|
+
* 张力曲线:把「每章该有多紧」画出来并可逐章调整。
|
|
48436
|
+
*
|
|
48437
|
+
* 图上是三条线:
|
|
48438
|
+
* 参考(虚线,形状预设) / 目标(实线,作者或规划设定) / 实际(散点,审稿打分)。
|
|
48439
|
+
* 下方列出规则核对发现的曲线级问题(连续同值、高位不回落、长期低位、实际偏离目标)。
|
|
48440
|
+
*
|
|
48441
|
+
* 张力只影响写作提示词里的"松紧"指引,不改变任何校验规则。
|
|
48442
|
+
*/
|
|
48443
|
+
const PRESETS = [
|
|
48444
|
+
"escalation",
|
|
48445
|
+
"suspense",
|
|
48446
|
+
"wave",
|
|
48447
|
+
"frontLoad",
|
|
48448
|
+
"flat",
|
|
48449
|
+
"custom"
|
|
48450
|
+
];
|
|
48451
|
+
/** 简易折线图(SVG,无依赖):宽高固定,按章节数均分横轴。 */
|
|
48452
|
+
function CurveChart({ points, onPick }) {
|
|
48453
|
+
const W = 720;
|
|
48454
|
+
const H = 200;
|
|
48455
|
+
const padX = 28;
|
|
48456
|
+
const padY = 16;
|
|
48457
|
+
const n = points.length;
|
|
48458
|
+
const x = (i) => n <= 1 ? W / 2 : padX + i / (n - 1) * (W - padX * 2);
|
|
48459
|
+
const y = (v) => padY + (1 - v / 100) * (H - padY * 2);
|
|
48460
|
+
const line = (pick) => points.map((p, i) => {
|
|
48461
|
+
const v = pick(p);
|
|
48462
|
+
return v === void 0 ? null : `${x(i).toFixed(1)},${y(v).toFixed(1)}`;
|
|
48463
|
+
}).filter((s) => s !== null).join(" ");
|
|
48464
|
+
const refLine = line((p) => p.reference);
|
|
48465
|
+
const targetLine = line((p) => p.target);
|
|
48466
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
|
|
48467
|
+
viewBox: `0 0 ${W} ${H}`,
|
|
48468
|
+
width: "100%",
|
|
48469
|
+
height: H,
|
|
48470
|
+
role: "img",
|
|
48471
|
+
"aria-label": "张力曲线",
|
|
48472
|
+
children: [
|
|
48473
|
+
[
|
|
48474
|
+
0,
|
|
48475
|
+
40,
|
|
48476
|
+
80,
|
|
48477
|
+
100
|
|
48478
|
+
].map((v) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("g", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("line", {
|
|
48479
|
+
x1: padX,
|
|
48480
|
+
x2: W - padX,
|
|
48481
|
+
y1: y(v),
|
|
48482
|
+
y2: y(v),
|
|
48483
|
+
stroke: "var(--nf-border)",
|
|
48484
|
+
strokeWidth: v === 0 || v === 100 ? 1 : .5,
|
|
48485
|
+
strokeDasharray: v === 0 || v === 100 ? "" : "3 4"
|
|
48486
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("text", {
|
|
48487
|
+
x: 4,
|
|
48488
|
+
y: y(v) + 3,
|
|
48489
|
+
fontSize: 9,
|
|
48490
|
+
fill: "var(--nf-text-2)",
|
|
48491
|
+
children: v
|
|
48492
|
+
})] }, v)),
|
|
48493
|
+
refLine !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("polyline", {
|
|
48494
|
+
points: refLine,
|
|
48495
|
+
fill: "none",
|
|
48496
|
+
stroke: "var(--nf-text-2)",
|
|
48497
|
+
strokeWidth: 1,
|
|
48498
|
+
strokeDasharray: "4 4",
|
|
48499
|
+
opacity: .7
|
|
48500
|
+
}),
|
|
48501
|
+
targetLine !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("polyline", {
|
|
48502
|
+
points: targetLine,
|
|
48503
|
+
fill: "none",
|
|
48504
|
+
stroke: "var(--nf-accent)",
|
|
48505
|
+
strokeWidth: 2
|
|
48506
|
+
}),
|
|
48507
|
+
points.map((p, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("g", { children: [
|
|
48508
|
+
p.actual !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("circle", {
|
|
48509
|
+
cx: x(i),
|
|
48510
|
+
cy: y(p.actual),
|
|
48511
|
+
r: 3,
|
|
48512
|
+
fill: "var(--nf-success)"
|
|
48513
|
+
}),
|
|
48514
|
+
p.target !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("circle", {
|
|
48515
|
+
cx: x(i),
|
|
48516
|
+
cy: y(p.target),
|
|
48517
|
+
r: 2.5,
|
|
48518
|
+
fill: "var(--nf-accent)"
|
|
48519
|
+
}),
|
|
48520
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
|
|
48521
|
+
x: x(i) - 6,
|
|
48522
|
+
y: padY,
|
|
48523
|
+
width: 12,
|
|
48524
|
+
height: H - padY * 2,
|
|
48525
|
+
fill: "transparent",
|
|
48526
|
+
style: { cursor: "pointer" },
|
|
48527
|
+
onClick: () => onPick(p.no),
|
|
48528
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("title", { children: `第${p.no}章 ${p.title}|目标 ${p.target ?? "—"}|实际 ${p.actual ?? "—"}|参考 ${p.reference ?? "—"}` })
|
|
48529
|
+
})
|
|
48530
|
+
] }, p.no))
|
|
48531
|
+
]
|
|
48532
|
+
});
|
|
48533
|
+
}
|
|
48534
|
+
function TensionView({ api }) {
|
|
48535
|
+
const [data, setData] = (0, react.useState)(null);
|
|
48536
|
+
const [busy, setBusy] = (0, react.useState)(false);
|
|
48537
|
+
const [error, setError] = (0, react.useState)("");
|
|
48538
|
+
const [notice, setNotice] = (0, react.useState)("");
|
|
48539
|
+
const [editing, setEditing] = (0, react.useState)(null);
|
|
48540
|
+
const [draft, setDraft] = (0, react.useState)(50);
|
|
48541
|
+
const refresh = (0, react.useCallback)(async (showError = true) => {
|
|
48542
|
+
try {
|
|
48543
|
+
setData(await api.tension());
|
|
48544
|
+
} catch (err) {
|
|
48545
|
+
if (showError) setError(err.message);
|
|
48546
|
+
}
|
|
48547
|
+
}, [api]);
|
|
48548
|
+
(0, react.useEffect)(() => {
|
|
48549
|
+
refresh(false);
|
|
48550
|
+
}, [refresh]);
|
|
48551
|
+
const run = (0, react.useCallback)(async (label, fn) => {
|
|
48552
|
+
setBusy(true);
|
|
48553
|
+
setError("");
|
|
48554
|
+
setNotice("");
|
|
48555
|
+
try {
|
|
48556
|
+
await fn();
|
|
48557
|
+
setNotice(label);
|
|
48558
|
+
} catch (err) {
|
|
48559
|
+
setError(err.message);
|
|
48560
|
+
} finally {
|
|
48561
|
+
setBusy(false);
|
|
48562
|
+
}
|
|
48563
|
+
}, []);
|
|
48564
|
+
const changePreset = (preset) => {
|
|
48565
|
+
run(`已切换参考曲线:${TENSION_PRESET_LABELS[preset]}`, async () => {
|
|
48566
|
+
await api.tensionPreset(preset);
|
|
48567
|
+
await refresh();
|
|
48568
|
+
});
|
|
48569
|
+
};
|
|
48570
|
+
const saveEdit = () => {
|
|
48571
|
+
if (editing === null) return;
|
|
48572
|
+
run(`第 ${editing} 章目标张力已设为 ${draft}`, async () => {
|
|
48573
|
+
await api.tensionSet(editing, draft);
|
|
48574
|
+
setEditing(null);
|
|
48575
|
+
await refresh();
|
|
48576
|
+
});
|
|
48577
|
+
};
|
|
48578
|
+
const clearEdit = () => {
|
|
48579
|
+
if (editing === null) return;
|
|
48580
|
+
run(`已清除第 ${editing} 章的目标张力`, async () => {
|
|
48581
|
+
await api.tensionSet(editing);
|
|
48582
|
+
setEditing(null);
|
|
48583
|
+
await refresh();
|
|
48584
|
+
});
|
|
48585
|
+
};
|
|
48586
|
+
const issues = data?.issues ?? [];
|
|
48587
|
+
const points = data?.points ?? [];
|
|
48588
|
+
const stat = (0, react.useMemo)(() => {
|
|
48589
|
+
const targets = points.map((p) => p.target).filter((v) => v !== void 0);
|
|
48590
|
+
const actuals = points.map((p) => p.actual).filter((v) => v !== void 0);
|
|
48591
|
+
const avg = (xs) => xs.length === 0 ? "—" : String(Math.round(xs.reduce((a, b) => a + b, 0) / xs.length));
|
|
48592
|
+
return {
|
|
48593
|
+
targetAvg: avg(targets),
|
|
48594
|
+
actualAvg: avg(actuals),
|
|
48595
|
+
rated: actuals.length,
|
|
48596
|
+
total: points.length
|
|
48597
|
+
};
|
|
48598
|
+
}, [points]);
|
|
48599
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
48600
|
+
className: panel_module_css_default.card,
|
|
48601
|
+
style: { gap: "var(--nf-space-12)" },
|
|
48602
|
+
children: [
|
|
48603
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
48604
|
+
className: panel_module_css_default.row,
|
|
48605
|
+
style: {
|
|
48606
|
+
justifyContent: "space-between",
|
|
48607
|
+
alignItems: "center",
|
|
48608
|
+
flexWrap: "wrap",
|
|
48609
|
+
gap: "var(--nf-space-8)"
|
|
48610
|
+
},
|
|
48611
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
48612
|
+
className: panel_module_css_default.cardTitle,
|
|
48613
|
+
children: "张力曲线"
|
|
48614
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
48615
|
+
className: panel_module_css_default.meta,
|
|
48616
|
+
children: [
|
|
48617
|
+
points.length,
|
|
48618
|
+
" 章 · 已评 ",
|
|
48619
|
+
stat.rated,
|
|
48620
|
+
" 章 · 目标均 ",
|
|
48621
|
+
stat.targetAvg,
|
|
48622
|
+
" / 实际均 ",
|
|
48623
|
+
stat.actualAvg
|
|
48624
|
+
]
|
|
48625
|
+
})]
|
|
48626
|
+
}),
|
|
48627
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
48628
|
+
className: panel_module_css_default.row,
|
|
48629
|
+
style: {
|
|
48630
|
+
gap: "var(--nf-space-8)",
|
|
48631
|
+
alignItems: "center",
|
|
48632
|
+
flexWrap: "wrap"
|
|
48633
|
+
},
|
|
48634
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
|
|
48635
|
+
className: panel_module_css_default.input,
|
|
48636
|
+
value: data?.preset ?? "escalation",
|
|
48637
|
+
disabled: busy,
|
|
48638
|
+
onChange: (e) => changePreset(e.target.value),
|
|
48639
|
+
children: PRESETS.map((p) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
48640
|
+
value: p,
|
|
48641
|
+
children: TENSION_PRESET_LABELS[p]
|
|
48642
|
+
}, p))
|
|
48643
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
48644
|
+
className: panel_module_css_default.meta,
|
|
48645
|
+
children: "虚线=参考曲线形状;实线=目标;绿点=审稿实际。点图中任意一章可改目标张力。"
|
|
48646
|
+
})]
|
|
48647
|
+
}),
|
|
48648
|
+
notice !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
48649
|
+
style: {
|
|
48650
|
+
color: "var(--nf-success)",
|
|
48651
|
+
fontSize: "var(--nf-text-12)"
|
|
48652
|
+
},
|
|
48653
|
+
children: notice
|
|
48654
|
+
}),
|
|
48655
|
+
error !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
48656
|
+
style: {
|
|
48657
|
+
color: "var(--nf-error)",
|
|
48658
|
+
fontSize: "var(--nf-text-12)"
|
|
48659
|
+
},
|
|
48660
|
+
children: error
|
|
48661
|
+
}),
|
|
48662
|
+
points.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
48663
|
+
className: panel_module_css_default.meta,
|
|
48664
|
+
children: "还没有章节计划。先在「总编台 → 卷/章节计划」排出章节,这里才有曲线可看。"
|
|
48665
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CurveChart, {
|
|
48666
|
+
points,
|
|
48667
|
+
onPick: (no) => {
|
|
48668
|
+
const p = points.find((x) => x.no === no);
|
|
48669
|
+
setEditing(no);
|
|
48670
|
+
setDraft(p?.target ?? p?.actual ?? 50);
|
|
48671
|
+
}
|
|
48672
|
+
}),
|
|
48673
|
+
issues.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
48674
|
+
style: {
|
|
48675
|
+
border: "1px solid var(--nf-border)",
|
|
48676
|
+
borderRadius: 8,
|
|
48677
|
+
padding: 8,
|
|
48678
|
+
background: "var(--nf-bg-inset)"
|
|
48679
|
+
},
|
|
48680
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("b", {
|
|
48681
|
+
style: { fontSize: "var(--nf-fs-12)" },
|
|
48682
|
+
children: [
|
|
48683
|
+
"曲线级问题 ",
|
|
48684
|
+
issues.length,
|
|
48685
|
+
" 条"
|
|
48686
|
+
]
|
|
48687
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
48688
|
+
style: {
|
|
48689
|
+
display: "flex",
|
|
48690
|
+
flexDirection: "column",
|
|
48691
|
+
gap: 6,
|
|
48692
|
+
marginTop: 6
|
|
48693
|
+
},
|
|
48694
|
+
children: issues.map((issue, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
48695
|
+
style: { fontSize: "var(--nf-fs-12)" },
|
|
48696
|
+
children: [
|
|
48697
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
48698
|
+
className: panel_module_css_default.lfPill,
|
|
48699
|
+
"data-phase": issue.severity === "high" ? "failed" : "requesting",
|
|
48700
|
+
children: issue.severity === "high" ? "高" : issue.severity === "medium" ? "中" : "低"
|
|
48701
|
+
}),
|
|
48702
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
48703
|
+
style: { marginLeft: 6 },
|
|
48704
|
+
children: [issue.chapters.length > 0 ? `第 ${issue.chapters.join("、")} 章:` : "", issue.item]
|
|
48705
|
+
}),
|
|
48706
|
+
issue.suggestion !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
48707
|
+
className: panel_module_css_default.meta,
|
|
48708
|
+
style: { marginLeft: 6 },
|
|
48709
|
+
children: ["建议:", issue.suggestion]
|
|
48710
|
+
})
|
|
48711
|
+
]
|
|
48712
|
+
}, i))
|
|
48713
|
+
})]
|
|
48714
|
+
}),
|
|
48715
|
+
editing !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
48716
|
+
style: {
|
|
48717
|
+
position: "fixed",
|
|
48718
|
+
inset: 0,
|
|
48719
|
+
background: "rgba(0,0,0,.45)",
|
|
48720
|
+
zIndex: 60,
|
|
48721
|
+
display: "flex",
|
|
48722
|
+
alignItems: "center",
|
|
48723
|
+
justifyContent: "center",
|
|
48724
|
+
padding: 20
|
|
48725
|
+
},
|
|
48726
|
+
onClick: () => setEditing(null),
|
|
48727
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
48728
|
+
onClick: (e) => e.stopPropagation(),
|
|
48729
|
+
style: {
|
|
48730
|
+
background: "var(--nf-bg)",
|
|
48731
|
+
border: "1px solid var(--nf-border)",
|
|
48732
|
+
borderRadius: 10,
|
|
48733
|
+
width: "min(420px, 92vw)",
|
|
48734
|
+
padding: 12,
|
|
48735
|
+
display: "flex",
|
|
48736
|
+
flexDirection: "column",
|
|
48737
|
+
gap: 8
|
|
48738
|
+
},
|
|
48739
|
+
children: [
|
|
48740
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("b", {
|
|
48741
|
+
style: { fontSize: "var(--nf-fs-13)" },
|
|
48742
|
+
children: [
|
|
48743
|
+
"第 ",
|
|
48744
|
+
editing,
|
|
48745
|
+
" 章 · 目标张力"
|
|
48746
|
+
]
|
|
48747
|
+
}),
|
|
48748
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
48749
|
+
type: "range",
|
|
48750
|
+
min: 0,
|
|
48751
|
+
max: 100,
|
|
48752
|
+
value: draft,
|
|
48753
|
+
onChange: (e) => setDraft(Number(e.target.value))
|
|
48754
|
+
}),
|
|
48755
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
48756
|
+
className: panel_module_css_default.row,
|
|
48757
|
+
style: { justifyContent: "space-between" },
|
|
48758
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
48759
|
+
className: panel_module_css_default.meta,
|
|
48760
|
+
children: [
|
|
48761
|
+
draft,
|
|
48762
|
+
" / 100(",
|
|
48763
|
+
draft < 40 ? "偏松:铺垫、日常、消化信息" : draft > 80 ? "偏紧:对抗、揭示、抉择、代价" : "中等:推进为主",
|
|
48764
|
+
")"
|
|
48765
|
+
]
|
|
48766
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
48767
|
+
className: panel_module_css_default.input,
|
|
48768
|
+
style: { width: 72 },
|
|
48769
|
+
type: "number",
|
|
48770
|
+
min: 0,
|
|
48771
|
+
max: 100,
|
|
48772
|
+
value: draft,
|
|
48773
|
+
onChange: (e) => setDraft(Math.max(0, Math.min(100, Number(e.target.value))))
|
|
48774
|
+
})]
|
|
48775
|
+
}),
|
|
48776
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
48777
|
+
className: panel_module_css_default.row,
|
|
47248
48778
|
style: {
|
|
47249
|
-
|
|
47250
|
-
|
|
47251
|
-
listStyle: "none",
|
|
47252
|
-
display: "grid",
|
|
47253
|
-
gap: "var(--nf-space-6)",
|
|
47254
|
-
fontSize: "var(--nf-fs-14)"
|
|
48779
|
+
justifyContent: "flex-end",
|
|
48780
|
+
gap: 6
|
|
47255
48781
|
},
|
|
47256
|
-
children:
|
|
47257
|
-
|
|
47258
|
-
display: "flex",
|
|
47259
|
-
alignItems: "center",
|
|
47260
|
-
gap: 8
|
|
47261
|
-
},
|
|
47262
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
47263
|
-
style: {
|
|
47264
|
-
display: "flex",
|
|
47265
|
-
alignItems: "center",
|
|
47266
|
-
gap: "var(--nf-space-6)",
|
|
47267
|
-
flex: 1,
|
|
47268
|
-
cursor: "pointer"
|
|
47269
|
-
},
|
|
47270
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
47271
|
-
type: "checkbox",
|
|
47272
|
-
checked: t.done,
|
|
47273
|
-
disabled: todosBusy,
|
|
47274
|
-
onChange: () => {
|
|
47275
|
-
toggleTodo(t.id);
|
|
47276
|
-
}
|
|
47277
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
47278
|
-
style: {
|
|
47279
|
-
textDecoration: t.done ? "line-through" : "none",
|
|
47280
|
-
color: t.done ? "var(--nf-text-2)" : void 0
|
|
47281
|
-
},
|
|
47282
|
-
children: t.text
|
|
47283
|
-
})]
|
|
47284
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
48782
|
+
children: [
|
|
48783
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
47285
48784
|
type: "button",
|
|
47286
|
-
className:
|
|
47287
|
-
|
|
47288
|
-
|
|
47289
|
-
|
|
47290
|
-
|
|
47291
|
-
|
|
47292
|
-
|
|
47293
|
-
|
|
47294
|
-
|
|
47295
|
-
|
|
47296
|
-
|
|
48785
|
+
className: panel_module_css_default.button,
|
|
48786
|
+
onClick: clearEdit,
|
|
48787
|
+
disabled: busy,
|
|
48788
|
+
children: "清除"
|
|
48789
|
+
}),
|
|
48790
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
48791
|
+
type: "button",
|
|
48792
|
+
className: panel_module_css_default.button,
|
|
48793
|
+
onClick: () => setEditing(null),
|
|
48794
|
+
children: "取消"
|
|
48795
|
+
}),
|
|
48796
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
48797
|
+
type: "button",
|
|
48798
|
+
className: panel_module_css_default.button + " " + panel_module_css_default.buttonPrimary,
|
|
48799
|
+
onClick: saveEdit,
|
|
48800
|
+
disabled: busy,
|
|
48801
|
+
children: "保存"
|
|
48802
|
+
})
|
|
48803
|
+
]
|
|
48804
|
+
})
|
|
48805
|
+
]
|
|
48806
|
+
})
|
|
47297
48807
|
})
|
|
47298
48808
|
]
|
|
47299
48809
|
});
|
|
47300
48810
|
}
|
|
47301
48811
|
//#endregion
|
|
47302
|
-
//#region src/client/panel/
|
|
48812
|
+
//#region src/client/panel/PromptSlotsView.tsx
|
|
47303
48813
|
/**
|
|
47304
|
-
*
|
|
47305
|
-
*
|
|
48814
|
+
* 提示词槽位:给作者留几个**安全可改**的位置来微调本书表达偏好。
|
|
48815
|
+
*
|
|
48816
|
+
* 边界写在界面上:槽位只**追加偏好**,不能覆盖道藏、写作红线、九条内容合规红线、
|
|
48817
|
+
* 反 AI 规则与阶段契约 —— 这些由宿主锁定。清空即恢复默认。
|
|
47306
48818
|
*/
|
|
47307
|
-
function
|
|
47308
|
-
const [
|
|
47309
|
-
const [
|
|
47310
|
-
const [content, setContent] = (0, react.useState)("");
|
|
48819
|
+
function PromptSlotsView({ api }) {
|
|
48820
|
+
const [slots, setSlots] = (0, react.useState)([]);
|
|
48821
|
+
const [drafts, setDrafts] = (0, react.useState)({});
|
|
47311
48822
|
const [busy, setBusy] = (0, react.useState)(false);
|
|
47312
|
-
const [notice, setNotice] = (0, react.useState)("");
|
|
47313
48823
|
const [error, setError] = (0, react.useState)("");
|
|
47314
|
-
|
|
47315
|
-
const
|
|
47316
|
-
/** 新建模式:右栏显示添加表单。 */
|
|
47317
|
-
const [addMode, setAddMode] = (0, react.useState)(false);
|
|
47318
|
-
const load = async () => {
|
|
48824
|
+
const [notice, setNotice] = (0, react.useState)("");
|
|
48825
|
+
const refresh = (0, react.useCallback)(async (showError = true) => {
|
|
47319
48826
|
try {
|
|
47320
|
-
const r = await api.
|
|
47321
|
-
|
|
47322
|
-
|
|
47323
|
-
|
|
48827
|
+
const r = await api.promptSlots();
|
|
48828
|
+
setSlots(r.slots);
|
|
48829
|
+
setDrafts(Object.fromEntries(r.slots.map((s) => [s.id, s.value])));
|
|
48830
|
+
} catch (err) {
|
|
48831
|
+
if (showError) setError(err.message);
|
|
47324
48832
|
}
|
|
47325
|
-
};
|
|
48833
|
+
}, [api]);
|
|
47326
48834
|
(0, react.useEffect)(() => {
|
|
47327
|
-
|
|
47328
|
-
}, []);
|
|
47329
|
-
const
|
|
47330
|
-
if (title.trim() === "") {
|
|
47331
|
-
setError("标题不能为空");
|
|
47332
|
-
return;
|
|
47333
|
-
}
|
|
48835
|
+
refresh(false);
|
|
48836
|
+
}, [refresh]);
|
|
48837
|
+
const save = (0, react.useCallback)(async (id) => {
|
|
47334
48838
|
setBusy(true);
|
|
47335
48839
|
setError("");
|
|
47336
48840
|
setNotice("");
|
|
47337
48841
|
try {
|
|
47338
|
-
|
|
47339
|
-
|
|
47340
|
-
|
|
47341
|
-
|
|
47342
|
-
|
|
47343
|
-
setTitle("");
|
|
47344
|
-
setContent("");
|
|
47345
|
-
setNotice(" 已添加");
|
|
47346
|
-
setAddMode(false);
|
|
47347
|
-
const added = r.docs[r.docs.length - 1];
|
|
47348
|
-
if (added !== void 0) setSelectedId(added.id);
|
|
47349
|
-
} catch (e) {
|
|
47350
|
-
setError(e.message);
|
|
47351
|
-
} finally {
|
|
47352
|
-
setBusy(false);
|
|
47353
|
-
}
|
|
47354
|
-
};
|
|
47355
|
-
const remove = async (id) => {
|
|
47356
|
-
setBusy(true);
|
|
47357
|
-
setError("");
|
|
47358
|
-
try {
|
|
47359
|
-
const r = await api.knowledgeRemove(id);
|
|
47360
|
-
setDocs(r.docs);
|
|
47361
|
-
if (selectedId === id) setSelectedId(null);
|
|
47362
|
-
} catch (e) {
|
|
47363
|
-
setError(e.message);
|
|
48842
|
+
await api.promptSlotSet(id, drafts[id] ?? "");
|
|
48843
|
+
await refresh();
|
|
48844
|
+
setNotice((drafts[id] ?? "").trim() === "" ? "已清空该槽位(恢复默认)" : "已保存,下一次生成/审稿生效");
|
|
48845
|
+
} catch (err) {
|
|
48846
|
+
setError(err.message);
|
|
47364
48847
|
} finally {
|
|
47365
48848
|
setBusy(false);
|
|
47366
48849
|
}
|
|
47367
|
-
}
|
|
47368
|
-
|
|
48850
|
+
}, [
|
|
48851
|
+
api,
|
|
48852
|
+
drafts,
|
|
48853
|
+
refresh
|
|
48854
|
+
]);
|
|
48855
|
+
const dirty = (slot) => (drafts[slot.id] ?? "") !== slot.value;
|
|
47369
48856
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
47370
|
-
className: panel_module_css_default.
|
|
47371
|
-
|
|
47372
|
-
|
|
47373
|
-
|
|
47374
|
-
|
|
47375
|
-
|
|
47376
|
-
|
|
47377
|
-
|
|
47378
|
-
|
|
47379
|
-
|
|
47380
|
-
|
|
47381
|
-
|
|
47382
|
-
|
|
48857
|
+
className: panel_module_css_default.card,
|
|
48858
|
+
style: { gap: "var(--nf-space-12)" },
|
|
48859
|
+
children: [
|
|
48860
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
48861
|
+
className: panel_module_css_default.row,
|
|
48862
|
+
style: {
|
|
48863
|
+
justifyContent: "space-between",
|
|
48864
|
+
alignItems: "center",
|
|
48865
|
+
flexWrap: "wrap",
|
|
48866
|
+
gap: "var(--nf-space-8)"
|
|
48867
|
+
},
|
|
48868
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
48869
|
+
className: panel_module_css_default.cardTitle,
|
|
48870
|
+
children: "提示词槽位(本书)"
|
|
48871
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
48872
|
+
className: panel_module_css_default.meta,
|
|
48873
|
+
children: "只追加偏好,不覆盖道藏 / 红线 / 合规"
|
|
48874
|
+
})]
|
|
48875
|
+
}),
|
|
48876
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
48877
|
+
className: panel_module_css_default.meta,
|
|
48878
|
+
children: "这里的文字会追加到写作提示词末尾,用来微调表达方式。**规则类内容不可改**: 道藏、写作红线、内容合规红线、反 AI 规则、阶段契约由宿主锁定,槽位碰不到。"
|
|
48879
|
+
}),
|
|
48880
|
+
notice !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
48881
|
+
style: {
|
|
48882
|
+
color: "var(--nf-success)",
|
|
48883
|
+
fontSize: "var(--nf-text-12)"
|
|
48884
|
+
},
|
|
48885
|
+
children: notice
|
|
48886
|
+
}),
|
|
48887
|
+
error !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
48888
|
+
style: {
|
|
48889
|
+
color: "var(--nf-error)",
|
|
48890
|
+
fontSize: "var(--nf-text-12)"
|
|
48891
|
+
},
|
|
48892
|
+
children: error
|
|
48893
|
+
}),
|
|
48894
|
+
slots.map((slot) => {
|
|
48895
|
+
const value = drafts[slot.id] ?? "";
|
|
48896
|
+
const over = value.length > slot.maxChars;
|
|
48897
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
48898
|
+
style: {
|
|
48899
|
+
border: "1px solid var(--nf-border)",
|
|
48900
|
+
borderRadius: 8,
|
|
48901
|
+
padding: 8,
|
|
48902
|
+
display: "flex",
|
|
48903
|
+
flexDirection: "column",
|
|
48904
|
+
gap: 6
|
|
48905
|
+
},
|
|
47383
48906
|
children: [
|
|
47384
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
47385
|
-
className: panel_module_css_default.
|
|
47386
|
-
|
|
47387
|
-
|
|
47388
|
-
|
|
47389
|
-
|
|
47390
|
-
className: panel_module_css_default.t2RailBtn,
|
|
47391
|
-
"data-active": addMode ? "" : void 0,
|
|
47392
|
-
onClick: () => {
|
|
47393
|
-
setAddMode(true);
|
|
47394
|
-
setSelectedId(null);
|
|
48907
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
48908
|
+
className: panel_module_css_default.row,
|
|
48909
|
+
style: {
|
|
48910
|
+
justifyContent: "space-between",
|
|
48911
|
+
alignItems: "baseline",
|
|
48912
|
+
gap: "var(--nf-space-8)"
|
|
47395
48913
|
},
|
|
47396
|
-
|
|
47397
|
-
|
|
47398
|
-
|
|
47399
|
-
|
|
47400
|
-
|
|
48914
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", {
|
|
48915
|
+
style: { fontSize: "var(--nf-fs-12)" },
|
|
48916
|
+
children: slot.label
|
|
48917
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
48918
|
+
className: panel_module_css_default.meta,
|
|
48919
|
+
style: { color: over ? "var(--nf-error)" : void 0 },
|
|
48920
|
+
children: [
|
|
48921
|
+
value.length,
|
|
48922
|
+
" / ",
|
|
48923
|
+
slot.maxChars
|
|
48924
|
+
]
|
|
48925
|
+
})]
|
|
47401
48926
|
}),
|
|
47402
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("
|
|
47403
|
-
|
|
47404
|
-
|
|
47405
|
-
|
|
47406
|
-
|
|
47407
|
-
|
|
47408
|
-
|
|
47409
|
-
|
|
47410
|
-
|
|
47411
|
-
|
|
47412
|
-
|
|
47413
|
-
|
|
47414
|
-
|
|
47415
|
-
|
|
48927
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
48928
|
+
className: panel_module_css_default.meta,
|
|
48929
|
+
children: slot.hint
|
|
48930
|
+
}),
|
|
48931
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
|
|
48932
|
+
className: panel_module_css_default.textarea,
|
|
48933
|
+
rows: 3,
|
|
48934
|
+
value,
|
|
48935
|
+
placeholder: slot.placeholder,
|
|
48936
|
+
onChange: (e) => setDrafts((prev) => ({
|
|
48937
|
+
...prev,
|
|
48938
|
+
[slot.id]: e.target.value
|
|
48939
|
+
}))
|
|
48940
|
+
}),
|
|
48941
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
48942
|
+
className: panel_module_css_default.row,
|
|
48943
|
+
style: {
|
|
48944
|
+
justifyContent: "flex-end",
|
|
48945
|
+
gap: 6
|
|
47416
48946
|
},
|
|
47417
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("
|
|
47418
|
-
|
|
47419
|
-
|
|
47420
|
-
|
|
47421
|
-
|
|
47422
|
-
|
|
47423
|
-
whiteSpace: "nowrap"
|
|
48947
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
48948
|
+
type: "button",
|
|
48949
|
+
className: panel_module_css_default.button,
|
|
48950
|
+
disabled: busy || value === "",
|
|
48951
|
+
onClick: () => {
|
|
48952
|
+
save(slot.id);
|
|
47424
48953
|
},
|
|
47425
|
-
children:
|
|
48954
|
+
children: "清空"
|
|
48955
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
48956
|
+
type: "button",
|
|
48957
|
+
className: panel_module_css_default.button + " " + panel_module_css_default.buttonPrimary,
|
|
48958
|
+
disabled: busy || !dirty(slot),
|
|
48959
|
+
onClick: () => {
|
|
48960
|
+
save(slot.id);
|
|
48961
|
+
},
|
|
48962
|
+
children: "保存"
|
|
47426
48963
|
})]
|
|
47427
|
-
}, d.id)),
|
|
47428
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: panel_module_css_default.t2RailSep }),
|
|
47429
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
47430
|
-
className: panel_module_css_default.t2RailMeta,
|
|
47431
|
-
children: [
|
|
47432
|
-
"共 ",
|
|
47433
|
-
docs.length,
|
|
47434
|
-
" 篇 · 正文生成时按当前章节检索注入"
|
|
47435
|
-
]
|
|
47436
48964
|
})
|
|
47437
48965
|
]
|
|
47438
|
-
}
|
|
47439
|
-
className: panel_module_css_default.t2Content,
|
|
47440
|
-
children: [addMode ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
47441
|
-
className: panel_module_css_default.cardTitleLg,
|
|
47442
|
-
children: "+ 新建文档"
|
|
47443
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
47444
|
-
style: {
|
|
47445
|
-
display: "flex",
|
|
47446
|
-
flexDirection: "column",
|
|
47447
|
-
gap: "var(--nf-space-6)",
|
|
47448
|
-
maxWidth: "var(--nf-measure, 720px)"
|
|
47449
|
-
},
|
|
47450
|
-
children: [
|
|
47451
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
47452
|
-
className: panel_module_css_default.input,
|
|
47453
|
-
value: title,
|
|
47454
|
-
onChange: (e) => setTitle(e.target.value),
|
|
47455
|
-
placeholder: "标题(如:天机锁设定 / 止水驿关系表)"
|
|
47456
|
-
}),
|
|
47457
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
|
|
47458
|
-
className: panel_module_css_default.input,
|
|
47459
|
-
style: {
|
|
47460
|
-
minHeight: 160,
|
|
47461
|
-
resize: "vertical"
|
|
47462
|
-
},
|
|
47463
|
-
value: content,
|
|
47464
|
-
onChange: (e) => setContent(e.target.value),
|
|
47465
|
-
placeholder: "内容(将被检索注入生成提示)"
|
|
47466
|
-
}),
|
|
47467
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
47468
|
-
style: {
|
|
47469
|
-
display: "flex",
|
|
47470
|
-
alignItems: "center",
|
|
47471
|
-
gap: "var(--nf-space-8)"
|
|
47472
|
-
},
|
|
47473
|
-
children: [
|
|
47474
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
47475
|
-
type: "button",
|
|
47476
|
-
className: `${panel_module_css_default.button} ${panel_module_css_default.buttonPrimary}`,
|
|
47477
|
-
disabled: busy,
|
|
47478
|
-
onClick: () => {
|
|
47479
|
-
add();
|
|
47480
|
-
},
|
|
47481
|
-
children: "添加"
|
|
47482
|
-
}),
|
|
47483
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
47484
|
-
type: "button",
|
|
47485
|
-
className: panel_module_css_default.button,
|
|
47486
|
-
onClick: () => {
|
|
47487
|
-
setAddMode(false);
|
|
47488
|
-
},
|
|
47489
|
-
children: "取消"
|
|
47490
|
-
}),
|
|
47491
|
-
notice !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
47492
|
-
style: {
|
|
47493
|
-
fontSize: "var(--nf-fs-12)",
|
|
47494
|
-
color: "var(--nf-success)"
|
|
47495
|
-
},
|
|
47496
|
-
children: notice
|
|
47497
|
-
})
|
|
47498
|
-
]
|
|
47499
|
-
})
|
|
47500
|
-
]
|
|
47501
|
-
})] }) : selected !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
47502
|
-
className: panel_module_css_default.row,
|
|
47503
|
-
style: {
|
|
47504
|
-
justifyContent: "space-between",
|
|
47505
|
-
flexWrap: "wrap"
|
|
47506
|
-
},
|
|
47507
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
47508
|
-
className: panel_module_css_default.cardTitleLg,
|
|
47509
|
-
children: [" ", selected.title]
|
|
47510
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
47511
|
-
type: "button",
|
|
47512
|
-
className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
|
|
47513
|
-
disabled: busy,
|
|
47514
|
-
onClick: () => {
|
|
47515
|
-
remove(selected.id);
|
|
47516
|
-
},
|
|
47517
|
-
children: "删除"
|
|
47518
|
-
})]
|
|
47519
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
47520
|
-
className: `${panel_module_css_default.planBeats} ${panel_module_css_default.docsSurface}`,
|
|
47521
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
47522
|
-
style: {
|
|
47523
|
-
fontSize: "var(--nf-fs-14)",
|
|
47524
|
-
lineHeight: 1.7,
|
|
47525
|
-
whiteSpace: "pre-wrap"
|
|
47526
|
-
},
|
|
47527
|
-
children: selected.content !== "" ? selected.content : "(空文档)"
|
|
47528
|
-
})
|
|
47529
|
-
})] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
47530
|
-
className: panel_module_css_default.planDetailEmpty,
|
|
47531
|
-
style: { minHeight: 300 },
|
|
47532
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
47533
|
-
className: panel_module_css_default.meta,
|
|
47534
|
-
children: "← 从左侧选择文档,或「+ 新建文档」添加参考资料。"
|
|
47535
|
-
})
|
|
47536
|
-
}), error !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
47537
|
-
style: {
|
|
47538
|
-
color: "var(--nf-error)",
|
|
47539
|
-
fontSize: "var(--nf-fs-14)"
|
|
47540
|
-
},
|
|
47541
|
-
children: [" ", error]
|
|
47542
|
-
})]
|
|
47543
|
-
})]
|
|
48966
|
+
}, slot.id);
|
|
47544
48967
|
})
|
|
47545
|
-
|
|
47546
|
-
className: panel_module_css_default.meta,
|
|
47547
|
-
children: "自由参考文档:零散设定/资料/碎片放这里;结构化设定(世界观/角色/境界/红线)请放「本书设定」。"
|
|
47548
|
-
})]
|
|
48968
|
+
]
|
|
47549
48969
|
});
|
|
47550
48970
|
}
|
|
47551
48971
|
//#endregion
|
|
@@ -48187,7 +49607,7 @@ window.__ModuleLoader__.load({
|
|
|
48187
49607
|
run: "run",
|
|
48188
49608
|
breakdown: "breakdown"
|
|
48189
49609
|
};
|
|
48190
|
-
/**
|
|
49610
|
+
/** 侧栏导航分组(按创作阶段归类)。 */
|
|
48191
49611
|
const NAV_GROUPS = [
|
|
48192
49612
|
{
|
|
48193
49613
|
id: "dashboard",
|
|
@@ -48548,7 +49968,7 @@ window.__ModuleLoader__.load({
|
|
|
48548
49968
|
* 章节工作台:**独立全页**(不塞进抽屉或主从布局,内容太重)。
|
|
48549
49969
|
* 三栏并发 —— 左:本章节拍;中:正文;右:对比 / 审稿 / 复盘。
|
|
48550
49970
|
*/
|
|
48551
|
-
function ChapterWorkbench({ chapter, text, draft, fontSize, busy, busyAny, onBack, onWrite, onReview, onApprove, onEdit, onRevisePicked, onReset, onRegenerate, onBackfillAuthor, tab, onTabChange, draftReport, onApplyDraft, onDiscardDraft, onCheckDraft }) {
|
|
49971
|
+
function ChapterWorkbench({ chapter, text, draft, fontSize, busy, busyAny, onBack, onWrite, onReview, onApprove, onEdit, onRevisePicked, onReset, onRegenerate, onBackfillAuthor, tab, onTabChange, draftReport, onApplyDraft, onDiscardDraft, onCheckDraft, snapshots, onRestoreSnapshot, onCreateSnapshot }) {
|
|
48552
49972
|
const badge = statusBadge(chapter);
|
|
48553
49973
|
const review = chapter.review;
|
|
48554
49974
|
const author = chapter.authorReview;
|
|
@@ -48800,6 +50220,10 @@ window.__ModuleLoader__.load({
|
|
|
48800
50220
|
{
|
|
48801
50221
|
id: "author",
|
|
48802
50222
|
label: "复盘"
|
|
50223
|
+
},
|
|
50224
|
+
{
|
|
50225
|
+
id: "versions",
|
|
50226
|
+
label: snapshots.length > 0 ? `历史版本 · ${snapshots.length}` : "历史版本"
|
|
48803
50227
|
}
|
|
48804
50228
|
],
|
|
48805
50229
|
active: tab,
|
|
@@ -48809,6 +50233,71 @@ window.__ModuleLoader__.load({
|
|
|
48809
50233
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
48810
50234
|
className: panel_module_css_default.chWorkSideBody,
|
|
48811
50235
|
children: [
|
|
50236
|
+
tab === "versions" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
50237
|
+
style: {
|
|
50238
|
+
display: "flex",
|
|
50239
|
+
flexDirection: "column",
|
|
50240
|
+
gap: "var(--nf-space-8)"
|
|
50241
|
+
},
|
|
50242
|
+
children: [
|
|
50243
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
50244
|
+
className: panel_module_css_default.row,
|
|
50245
|
+
style: {
|
|
50246
|
+
justifyContent: "space-between",
|
|
50247
|
+
alignItems: "center"
|
|
50248
|
+
},
|
|
50249
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
50250
|
+
className: panel_module_css_default.meta,
|
|
50251
|
+
children: "覆盖写入前会自动留存;回滚也可再撤销。"
|
|
50252
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
50253
|
+
type: "button",
|
|
50254
|
+
className: panel_module_css_default.button,
|
|
50255
|
+
onClick: onCreateSnapshot,
|
|
50256
|
+
children: "存档当前正文"
|
|
50257
|
+
})]
|
|
50258
|
+
}),
|
|
50259
|
+
snapshots.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
50260
|
+
className: panel_module_css_default.meta,
|
|
50261
|
+
children: "这一章还没有历史版本。"
|
|
50262
|
+
}),
|
|
50263
|
+
snapshots.slice().sort((a, b) => b.at.localeCompare(a.at)).map((snapshot) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
50264
|
+
style: {
|
|
50265
|
+
border: "1px solid var(--nf-border)",
|
|
50266
|
+
borderRadius: 8,
|
|
50267
|
+
padding: "6px 8px",
|
|
50268
|
+
fontSize: "var(--nf-fs-12)"
|
|
50269
|
+
},
|
|
50270
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
50271
|
+
style: {
|
|
50272
|
+
display: "flex",
|
|
50273
|
+
gap: 6,
|
|
50274
|
+
alignItems: "baseline",
|
|
50275
|
+
flexWrap: "wrap"
|
|
50276
|
+
},
|
|
50277
|
+
children: [
|
|
50278
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", { children: new Date(snapshot.at).toLocaleString() }),
|
|
50279
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
50280
|
+
className: panel_module_css_default.meta,
|
|
50281
|
+
children: snapshot.reason
|
|
50282
|
+
}),
|
|
50283
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
50284
|
+
className: panel_module_css_default.meta,
|
|
50285
|
+
children: [snapshot.chars, " 字"]
|
|
50286
|
+
}),
|
|
50287
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
50288
|
+
type: "button",
|
|
50289
|
+
className: panel_module_css_default.button,
|
|
50290
|
+
style: { marginLeft: "auto" },
|
|
50291
|
+
disabled: busyAny,
|
|
50292
|
+
onClick: () => onRestoreSnapshot(snapshot.id),
|
|
50293
|
+
title: "用这一版覆盖当前正文(回滚前会先留存当前正文)",
|
|
50294
|
+
children: "回滚到这一版"
|
|
50295
|
+
})
|
|
50296
|
+
]
|
|
50297
|
+
})
|
|
50298
|
+
}, snapshot.id))
|
|
50299
|
+
]
|
|
50300
|
+
}),
|
|
48812
50301
|
tab === "diff" && (hasDraft ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
48813
50302
|
className: panel_module_css_default.chWorkDraftBar,
|
|
48814
50303
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -49062,6 +50551,10 @@ window.__ModuleLoader__.load({
|
|
|
49062
50551
|
* 的聊天记录,而新消息已经发到另一本书里。
|
|
49063
50552
|
*/
|
|
49064
50553
|
const [bookKey, setBookKey] = (0, react.useState)("");
|
|
50554
|
+
/** 导出范围(设置页导出卡片):整本正文 / 设定 / 规划 / 角色 / 质检记录 / 项目备份。 */
|
|
50555
|
+
const [exportScope, setExportScope] = (0, react.useState)("book");
|
|
50556
|
+
/** 章节历史版本(快照):打开工作台时拉取,回滚/存档后刷新。 */
|
|
50557
|
+
const [snapshots, setSnapshots] = (0, react.useState)([]);
|
|
49065
50558
|
const [dragActive, setDragActive] = (0, react.useState)(false);
|
|
49066
50559
|
const fileInputRef = (0, react.useRef)(null);
|
|
49067
50560
|
const [planCount, setPlanCount] = (0, react.useState)(30);
|
|
@@ -49711,6 +51204,9 @@ window.__ModuleLoader__.load({
|
|
|
49711
51204
|
if (status.project?.roleStatus !== void 0) setCharCards(status.project.roleStatus);
|
|
49712
51205
|
else setCharCards(null);
|
|
49713
51206
|
setGeneratedFiles(status.generatedFiles);
|
|
51207
|
+
try {
|
|
51208
|
+
setSnapshots((await api.snapshots()).snapshots);
|
|
51209
|
+
} catch {}
|
|
49714
51210
|
const withDraft = status.project?.chapters.find((c) => c.pendingDraft !== void 0 && c.pendingDraft !== "");
|
|
49715
51211
|
setDraftNo(withDraft?.no ?? null);
|
|
49716
51212
|
const nextOutline = status.project?.outline;
|
|
@@ -51088,11 +52584,47 @@ window.__ModuleLoader__.load({
|
|
|
51088
52584
|
}
|
|
51089
52585
|
};
|
|
51090
52586
|
/** Export the book. */
|
|
51091
|
-
|
|
52587
|
+
/** 刷新章节历史版本列表。 */
|
|
52588
|
+
const refreshSnapshots = async () => {
|
|
52589
|
+
try {
|
|
52590
|
+
setSnapshots((await api.snapshots()).snapshots);
|
|
52591
|
+
} catch {}
|
|
52592
|
+
};
|
|
52593
|
+
/** 回滚到某个历史版本(回滚前宿主会先留存当前正文,所以可撤销)。 */
|
|
52594
|
+
const handleRestoreSnapshot = async (id) => {
|
|
52595
|
+
if (!window.confirm("用这一版覆盖当前正文?回滚前会自动留存当前正文,可以再换回来。")) return;
|
|
52596
|
+
setBusy(true);
|
|
52597
|
+
setError("");
|
|
52598
|
+
try {
|
|
52599
|
+
await api.snapshotRestore(id);
|
|
52600
|
+
await refresh(false, true);
|
|
52601
|
+
await refreshSnapshots();
|
|
52602
|
+
setNotice("已回滚到所选版本");
|
|
52603
|
+
} catch (err) {
|
|
52604
|
+
setError(err.message);
|
|
52605
|
+
} finally {
|
|
52606
|
+
setBusy(false);
|
|
52607
|
+
}
|
|
52608
|
+
};
|
|
52609
|
+
/** 手工给当前章节存档一个历史版本。 */
|
|
52610
|
+
const handleCreateSnapshot = async (no) => {
|
|
52611
|
+
setBusy(true);
|
|
52612
|
+
setError("");
|
|
52613
|
+
try {
|
|
52614
|
+
await api.snapshotCreate(no);
|
|
52615
|
+
await refreshSnapshots();
|
|
52616
|
+
setNotice("已存档当前正文");
|
|
52617
|
+
} catch (err) {
|
|
52618
|
+
setError(err.message);
|
|
52619
|
+
} finally {
|
|
52620
|
+
setBusy(false);
|
|
52621
|
+
}
|
|
52622
|
+
};
|
|
52623
|
+
const handleExport = async (format, scope = "book") => {
|
|
51092
52624
|
setBusy(true);
|
|
51093
52625
|
setError("");
|
|
51094
52626
|
try {
|
|
51095
|
-
const result = await api.exportBook(format);
|
|
52627
|
+
const result = await api.exportBook(format, scope);
|
|
51096
52628
|
setNotice(tt("settings.exported", {
|
|
51097
52629
|
file: result.file,
|
|
51098
52630
|
chars: result.chars,
|
|
@@ -51343,7 +52875,7 @@ window.__ModuleLoader__.load({
|
|
|
51343
52875
|
};
|
|
51344
52876
|
/** 侧栏当前书卡(demo 风格):书架激活书 → 封面首字 / 书名 / 进度。 */
|
|
51345
52877
|
const activeBook = shelf?.books.find((b) => b.id === shelf?.activeBookId) ?? null;
|
|
51346
|
-
/**
|
|
52878
|
+
/** 主行动卡片:同一刻只给作者一个「推荐下一步」。 */
|
|
51347
52879
|
const nextAction = (0, react.useMemo)(() => {
|
|
51348
52880
|
if (project === null) return {
|
|
51349
52881
|
eyebrow: "开始你的第一本书",
|
|
@@ -51526,6 +53058,36 @@ window.__ModuleLoader__.load({
|
|
|
51526
53058
|
openDrawer("run");
|
|
51527
53059
|
}
|
|
51528
53060
|
},
|
|
53061
|
+
{
|
|
53062
|
+
key: "tension",
|
|
53063
|
+
group: "tools",
|
|
53064
|
+
name: "张力曲线",
|
|
53065
|
+
di: chapters.length > 0 ? `● ${chapters.length} 章曲线` : "○ 需先排章节",
|
|
53066
|
+
dim: project === null,
|
|
53067
|
+
go: () => {
|
|
53068
|
+
openDrawer("tension");
|
|
53069
|
+
}
|
|
53070
|
+
},
|
|
53071
|
+
{
|
|
53072
|
+
key: "promptSlots",
|
|
53073
|
+
group: "tools",
|
|
53074
|
+
name: "提示词槽位",
|
|
53075
|
+
di: Object.keys(project?.promptSlots ?? {}).length > 0 ? `● 已设 ${Object.keys(project?.promptSlots ?? {}).length} 项` : "○ 未设置",
|
|
53076
|
+
dim: project === null,
|
|
53077
|
+
go: () => {
|
|
53078
|
+
openDrawer("promptSlots");
|
|
53079
|
+
}
|
|
53080
|
+
},
|
|
53081
|
+
{
|
|
53082
|
+
key: "timeline",
|
|
53083
|
+
group: "tools",
|
|
53084
|
+
name: "故事时间线",
|
|
53085
|
+
di: (project?.timeline ?? []).length > 0 ? `● ${(project?.timeline ?? []).length} 条事件` : "○ 未抽取",
|
|
53086
|
+
dim: project === null,
|
|
53087
|
+
go: () => {
|
|
53088
|
+
openDrawer("timeline");
|
|
53089
|
+
}
|
|
53090
|
+
},
|
|
51529
53091
|
{
|
|
51530
53092
|
key: "knowledge",
|
|
51531
53093
|
group: "tools",
|
|
@@ -51843,6 +53405,13 @@ window.__ModuleLoader__.load({
|
|
|
51843
53405
|
},
|
|
51844
53406
|
onCheckDraft: () => {
|
|
51845
53407
|
handleWbCheckDraft(workbench.no);
|
|
53408
|
+
},
|
|
53409
|
+
snapshots: snapshots.filter((s) => s.chapterNo === workbench.no),
|
|
53410
|
+
onRestoreSnapshot: (id) => {
|
|
53411
|
+
handleRestoreSnapshot(id);
|
|
53412
|
+
},
|
|
53413
|
+
onCreateSnapshot: () => {
|
|
53414
|
+
handleCreateSnapshot(workbench.no);
|
|
51846
53415
|
}
|
|
51847
53416
|
}),
|
|
51848
53417
|
rightDrawer !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -53147,12 +54716,33 @@ window.__ModuleLoader__.load({
|
|
|
53147
54716
|
}),
|
|
53148
54717
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
53149
54718
|
className: panel_module_css_default.row,
|
|
53150
|
-
|
|
54719
|
+
style: {
|
|
54720
|
+
flexWrap: "wrap",
|
|
54721
|
+
gap: "var(--nf-space-8)"
|
|
54722
|
+
},
|
|
54723
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
|
|
54724
|
+
className: panel_module_css_default.input,
|
|
54725
|
+
value: exportScope,
|
|
54726
|
+
onChange: (e) => setExportScope(e.target.value),
|
|
54727
|
+
title: "选择导出范围",
|
|
54728
|
+
children: EXPORT_SCOPE_VALUES.map((scope) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
54729
|
+
value: scope,
|
|
54730
|
+
children: EXPORT_SCOPE_LABELS[scope]
|
|
54731
|
+
}, scope))
|
|
54732
|
+
}), exportScope === "project" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
54733
|
+
type: "button",
|
|
54734
|
+
className: panel_module_css_default.button,
|
|
54735
|
+
disabled: busy,
|
|
54736
|
+
onClick: () => {
|
|
54737
|
+
handleExport("json", "project");
|
|
54738
|
+
},
|
|
54739
|
+
children: "导出项目备份 JSON"
|
|
54740
|
+
}) : exportScope === "book" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
53151
54741
|
type: "button",
|
|
53152
54742
|
className: panel_module_css_default.button,
|
|
53153
54743
|
disabled: busy || chapters.length === 0,
|
|
53154
54744
|
onClick: () => {
|
|
53155
|
-
handleExport("txt");
|
|
54745
|
+
handleExport("txt", "book");
|
|
53156
54746
|
},
|
|
53157
54747
|
children: tt("settings.exportTxt")
|
|
53158
54748
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
@@ -53160,14 +54750,30 @@ window.__ModuleLoader__.load({
|
|
|
53160
54750
|
className: panel_module_css_default.button,
|
|
53161
54751
|
disabled: busy || chapters.length === 0,
|
|
53162
54752
|
onClick: () => {
|
|
53163
|
-
handleExport("md");
|
|
54753
|
+
handleExport("md", "book");
|
|
53164
54754
|
},
|
|
53165
54755
|
children: tt("settings.exportMd")
|
|
53166
|
-
})]
|
|
54756
|
+
})] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
54757
|
+
type: "button",
|
|
54758
|
+
className: panel_module_css_default.button,
|
|
54759
|
+
disabled: busy,
|
|
54760
|
+
onClick: () => {
|
|
54761
|
+
handleExport("txt", exportScope);
|
|
54762
|
+
},
|
|
54763
|
+
children: "导出 TXT"
|
|
54764
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
54765
|
+
type: "button",
|
|
54766
|
+
className: panel_module_css_default.button,
|
|
54767
|
+
disabled: busy,
|
|
54768
|
+
onClick: () => {
|
|
54769
|
+
handleExport("md", exportScope);
|
|
54770
|
+
},
|
|
54771
|
+
children: "导出 Markdown"
|
|
54772
|
+
})] })]
|
|
53167
54773
|
}),
|
|
53168
54774
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
53169
54775
|
className: panel_module_css_default.meta,
|
|
53170
|
-
children: "导出当前书的全部已写章节。"
|
|
54776
|
+
children: exportScope === "project" ? "导出完整项目 JSON(含设定/规划/角色/事实库),用于备份或迁移到其它机器。" : exportScope === "book" ? "导出当前书的全部已写章节。" : `导出「${EXPORT_SCOPE_LABELS[exportScope]}」,不含正文,便于单独存档或交给他人。`
|
|
53171
54777
|
})
|
|
53172
54778
|
]
|
|
53173
54779
|
})
|
|
@@ -53953,6 +55559,12 @@ window.__ModuleLoader__.load({
|
|
|
53953
55559
|
})
|
|
53954
55560
|
}),
|
|
53955
55561
|
rightDrawer === "knowledge" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(KnowledgeBaseView, { api }),
|
|
55562
|
+
rightDrawer === "timeline" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TimelineView, {
|
|
55563
|
+
api,
|
|
55564
|
+
chapters: chapters.map((c) => c.no)
|
|
55565
|
+
}),
|
|
55566
|
+
rightDrawer === "tension" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TensionView, { api }),
|
|
55567
|
+
rightDrawer === "promptSlots" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PromptSlotsView, { api }),
|
|
53956
55568
|
rightDrawer === "run" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RunPanel, {
|
|
53957
55569
|
api,
|
|
53958
55570
|
totalChapters: chapters.length
|