@waterwx/dsh-novel-forge 1.1.1 → 1.1.2

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/lib/client.js CHANGED
@@ -469,6 +469,8 @@ window.__ModuleLoader__.load({
469
469
  "settings.chapterChars": "每章目标字数",
470
470
  "settings.maxTokens": "单章最大输出 tokens",
471
471
  "settings.reviewPassScore": "审稿通过分数(0-100)",
472
+ "settings.editorFontSize": "编辑器字号(仅编辑页显示)",
473
+ "settings.editorFontSizeHint": "存于浏览器本地,不影响其他设备",
472
474
  "settings.autoReview": "生成后自动审稿",
473
475
  "settings.save": "保存设置",
474
476
  "settings.saved": "设置已保存",
@@ -600,6 +602,8 @@ window.__ModuleLoader__.load({
600
602
  "settings.chapterChars": "Chars per chapter",
601
603
  "settings.maxTokens": "Max output tokens",
602
604
  "settings.reviewPassScore": "Review pass score (0-100)",
605
+ "settings.editorFontSize": "Editor font size (workspace only)",
606
+ "settings.editorFontSizeHint": "Stored in browser localStorage; display-only",
603
607
  "settings.autoReview": "Auto-review after writing",
604
608
  "settings.save": "Save settings",
605
609
  "settings.saved": "Settings saved",
@@ -641,7 +645,7 @@ window.__ModuleLoader__.load({
641
645
  }
642
646
  //#endregion
643
647
  //#region \0dsh-css:C:\Users\Ryan\Desktop\111\novel-forge\src\client\panel\panel.module.css.mjs
644
- const css = ".CUIYUW_entry{width:100%;color:var(--dsw-alias-label-primary,#1f1f23);cursor:pointer;text-align:left;background:0 0;border:none;border-radius:6px;align-items:center;gap:8px;padding:8px 12px;font-size:13px;transition:background .15s;display:flex}body[data-ds-dark-theme] .CUIYUW_entry{color:var(--dsw-alias-label-primary,#ececf1)}.CUIYUW_entry:hover{background:var(--dsw-alias-interactive-bg-hover,#7f7f7f1f)}.CUIYUW_entry[data-active]{background:var(--dsw-alias-interactive-bg-active,#7f7f7f33)}.CUIYUW_entryIcon{flex-shrink:0;justify-content:center;align-items:center;display:inline-flex}.CUIYUW_entryLabel{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}[data-pane=conversation]{position:relative}.CUIYUW_view{z-index:60;color-scheme:light;--nf-bg:#f2f2f7db;--nf-bg-raise:#ffffffb8;--nf-bg-inset:#7676801f;--nf-border:#3c3c4329;--nf-border-strong:#3c3c4352;--nf-text:#1c1c1e;--nf-text-2:#3c3c43;--nf-text-2-alpha:#3c3c43ad;--nf-text-3:#8e8e93;--nf-accent:#007aff;--nf-accent-hover:#0071e3;--nf-accent-soft:#007aff1f;--nf-accent-fg:#fff;--nf-hover:#0000000d;--nf-success:#34c759;--nf-error:#ff3b30;--nf-warn:#ff9500;--nf-info:#5856d6;--nf-shadow:0 1px 3px #0000000f, 0 12px 32px #00000014;--nf-shadow-lg:0 4px 12px #00000012, 0 20px 48px #0000001f;background:var(--nf-bg);backdrop-filter:blur(32px)saturate(180%);color:var(--nf-text);font-family:-apple-system,BlinkMacSystemFont,SF Pro Text,SF Pro SC,PingFang SC,Segoe UI,Roboto,Helvetica Neue,sans-serif;display:none;position:absolute;inset:0;overflow:auto}body[data-ds-dark-theme] .CUIYUW_view{color-scheme:dark;--nf-bg:#000000b8;--nf-bg-raise:#1c1c1ec7;--nf-bg-inset:#7676802e;--nf-border:#ffffff1f;--nf-border-strong:#ffffff47;--nf-text:#f2f2f7;--nf-text-2:#d1d1d6;--nf-text-2-alpha:#d1d1d6b8;--nf-text-3:#8e8e93;--nf-accent:#0a84ff;--nf-accent-hover:#3a9bff;--nf-accent-soft:#0a84ff33;--nf-accent-fg:#fff;--nf-hover:#ffffff17;--nf-success:#30d158;--nf-error:#ff453a;--nf-warn:#ff9f0a;--nf-info:#bf5af2;--nf-shadow:0 1px 2px #00000059, 0 10px 30px #0006;--nf-shadow-lg:0 4px 12px #0006, 0 20px 48px #0000008c}html[data-dsh-novelforge-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-active]) .CUIYUW_view{display:block}.CUIYUW_panel{flex-direction:column;min-width:0;height:100%;font-size:14px;line-height:1.6;display:flex;position:relative}.CUIYUW_panelHeader{border-bottom:1px solid var(--nf-border);background:var(--nf-bg-raise);backdrop-filter:blur(24px)saturate(180%);z-index:5;flex-shrink:0;justify-content:space-between;align-items:center;padding:12px 18px;display:flex;position:sticky;top:0}.CUIYUW_panelTitle{letter-spacing:.2px;align-items:center;gap:8px;margin:0;font-size:16px;font-weight:700;display:flex}.CUIYUW_panelTitle:before{content:\"\";background:linear-gradient(180deg, var(--nf-accent), var(--nf-info));border-radius:2px;width:4px;height:16px}.CUIYUW_iconButton{cursor:pointer;color:var(--nf-text-2);background:0 0;border:none;border-radius:8px;padding:4px 9px;font-size:16px;transition:background .15s,color .15s}.CUIYUW_iconButton:hover{background:var(--nf-hover);color:var(--nf-text)}.CUIYUW_tabBar{border-bottom:1px solid var(--nf-border);background:var(--nf-bg-raise);z-index:4;flex-shrink:0;gap:2px;padding:8px 14px 0;display:flex;position:sticky;top:45px}.CUIYUW_tab{cursor:pointer;color:var(--nf-text-2);background:0 0;border:none;border-radius:8px 8px 0 0;padding:7px 13px;font-size:13.5px;font-weight:500;transition:color .15s,background .15s;position:relative}.CUIYUW_tab:hover{color:var(--nf-text);background:var(--nf-hover)}.CUIYUW_tab[data-active]{color:var(--nf-accent);font-weight:600}.CUIYUW_tab[data-active]:after{content:\"\";background:var(--nf-accent);border-radius:2px 2px 0 0;height:2.5px;position:absolute;bottom:-1px;left:10px;right:10px}.CUIYUW_panelContent{flex-direction:column;flex:1;gap:14px;padding:16px 18px 20px;display:flex;overflow:auto}.CUIYUW_panelBody{flex:1;min-height:0;display:flex}.CUIYUW_panelNav{border-right:1px solid var(--nf-border);background:var(--nf-bg-raise);backdrop-filter:blur(24px)saturate(180%);flex-direction:column;flex:none;gap:2px;width:142px;padding:10px 8px;transition:width .18s;display:flex;overflow-y:auto}.CUIYUW_panelNavCollapsed{width:52px;padding:10px 6px}.CUIYUW_navGroup{flex-direction:column;gap:2px;display:flex}.CUIYUW_navGroupLabel{letter-spacing:.6px;text-transform:uppercase;color:var(--nf-text-3);user-select:none;padding:6px 10px 2px;font-size:10.5px;font-weight:600}.CUIYUW_navGroupSep{background:var(--nf-border);height:1px;margin:6px 8px 4px}.CUIYUW_navSpacer{flex:1;min-height:8px}.CUIYUW_navAbout{border-top:1px solid var(--nf-border);flex-direction:column;flex:none;gap:4px;margin-top:4px;padding:8px 6px 4px;display:flex}.CUIYUW_navAboutRow{cursor:pointer;color:var(--nf-text-3);text-align:left;white-space:nowrap;background:0 0;border:none;border-radius:8px;justify-content:space-between;align-items:center;gap:4px;padding:4px 6px;font-size:11px;transition:color .15s,background .15s;display:flex}.CUIYUW_navAboutRow:hover{color:var(--nf-text);background:var(--nf-hover)}.CUIYUW_navAboutUpdate{background:var(--nf-accent-soft);color:var(--nf-accent);cursor:pointer;text-align:left;white-space:nowrap;border:none;border-radius:8px;padding:4px 6px;font-size:10.5px;font-weight:600}.CUIYUW_navAboutUpdate:hover{color:var(--nf-accent-hover)}.CUIYUW_panelNavCollapsed .CUIYUW_navAbout{align-items:center;padding:6px 2px 2px}.CUIYUW_panelNavCollapsed .CUIYUW_navAboutRow{justify-content:center;width:100%;padding:4px 0}.CUIYUW_navTabBadge{background:var(--nf-accent);color:#fff;text-align:center;border-radius:999px;flex:none;min-width:18px;height:18px;margin-left:auto;padding:0 5px;font-size:10.5px;font-weight:700;line-height:18px;display:inline-block}.CUIYUW_panelNavCollapsed .CUIYUW_navTabBadge{min-width:14px;height:14px;padding:0 3px;font-size:9px;line-height:14px;position:absolute;top:2px;right:2px}.CUIYUW_navTabBadgeDanger{background:var(--nf-error)}.CUIYUW_navTabBadgeWarn{background:var(--nf-warn)}.CUIYUW_navTabBadgeDone{background:var(--nf-success)}.CUIYUW_navTab{cursor:pointer;width:100%;color:var(--nf-text-2-alpha,var(--nf-text-2));text-align:left;white-space:nowrap;background:0 0;border:none;border-radius:12px;align-items:center;gap:8px;padding:8px 10px;font-size:13px;font-weight:500;transition:color .15s,background .15s;display:flex;position:relative}.CUIYUW_panelNavCollapsed .CUIYUW_navTab{justify-content:center;padding:8px 0}.CUIYUW_navTab:hover{color:var(--nf-text);background:var(--nf-hover)}.CUIYUW_navTab[data-active]{color:var(--nf-accent);background:var(--nf-accent-soft);font-weight:600}.CUIYUW_navTab[data-active]:before{content:\"\";background:var(--nf-accent);border-radius:999px;width:3px;position:absolute;top:20%;bottom:20%;left:-8px}.CUIYUW_panelNavCollapsed .CUIYUW_navTab[data-active]:before{left:-6px}.CUIYUW_navTabIcon{flex:none;font-size:15px;line-height:1}.CUIYUW_navTabLabel{text-overflow:ellipsis;overflow:hidden}.CUIYUW_headerProgress{color:var(--nf-text-2);white-space:nowrap;align-items:center;gap:6px;margin-left:4px;font-size:12px;font-weight:400;display:inline-flex}.CUIYUW_headerProgress b{color:var(--nf-accent);font-weight:700}.CUIYUW_headerProgressDot{background:var(--nf-border-strong,var(--nf-text-3));border-radius:50%;width:3px;height:3px;display:inline-block}.CUIYUW_card{border:1px solid var(--nf-border);background:var(--nf-bg-raise);box-shadow:var(--nf-shadow);backdrop-filter:blur(24px)saturate(180%);border-radius:20px;flex-direction:column;gap:10px;padding:16px 18px;transition:border-color .2s,box-shadow .2s;display:flex}.CUIYUW_cardTitle{color:var(--nf-text);align-items:center;gap:8px;margin:0;font-size:14px;font-weight:650;display:flex}.CUIYUW_button{border:1px solid var(--nf-border-strong);background:var(--nf-bg-inset);color:var(--nf-text);cursor:pointer;white-space:nowrap;border-radius:12px;padding:6px 14px;font-size:13px;font-weight:500;transition:background .15s,border-color .15s,transform .1s,box-shadow .15s}.CUIYUW_button:hover:not([disabled]){background:var(--nf-hover);border-color:var(--nf-border-strong)}.CUIYUW_button:active:not([disabled]){transform:scale(.96)}.CUIYUW_button[disabled]{opacity:.45;cursor:not-allowed}.CUIYUW_buttonPrimary{background:linear-gradient(180deg, color-mix(in srgb, var(--nf-accent) 88%, #fff), var(--nf-accent));color:var(--nf-accent-fg);box-shadow:0 2px 8px color-mix(in srgb, var(--nf-accent) 35%, transparent);border-color:#0000}.CUIYUW_buttonPrimary:hover:not([disabled]){background:linear-gradient(180deg, var(--nf-accent-hover), color-mix(in srgb, var(--nf-accent-hover) 85%, #000));border-color:#0000}.CUIYUW_buttonDanger{border-color:var(--nf-error);color:var(--nf-error)}.CUIYUW_buttonDanger:hover:not([disabled]){background:#ff3b301a}.CUIYUW_buttonSmall{border-radius:9px;padding:3px 10px;font-size:12px}.CUIYUW_field{flex-direction:column;gap:5px;display:flex}.CUIYUW_fieldLabel{color:var(--nf-text-2);font-size:12px;font-weight:500}.CUIYUW_input{border:1px solid var(--nf-border-strong);background:var(--nf-bg-inset);color:var(--nf-text);box-sizing:border-box;border-radius:12px;width:100%;padding:7px 11px;font-size:13px;transition:border-color .15s,box-shadow .15s}.CUIYUW_input:focus,.CUIYUW_textarea:focus{border-color:var(--nf-accent);box-shadow:0 0 0 3px var(--nf-accent-soft);outline:none}.CUIYUW_input::placeholder,.CUIYUW_textarea::placeholder{color:var(--nf-text-3)}.CUIYUW_textarea{border:1px solid var(--nf-border-strong);background:var(--nf-bg-inset);color:var(--nf-text);box-sizing:border-box;resize:vertical;border-radius:12px;width:100%;min-height:200px;padding:9px 11px;font-family:inherit;font-size:13px;line-height:1.7;transition:border-color .15s,box-shadow .15s}.CUIYUW_row{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.CUIYUW_spaceBetween{justify-content:space-between}.CUIYUW_chapterList{flex-direction:column;gap:8px;display:flex}.CUIYUW_volumeGroup{flex-direction:column;gap:6px;display:flex}.CUIYUW_volumeGroupHeader{background:var(--nf-bg-inset);border:1px solid var(--nf-border);cursor:pointer;user-select:none;border-radius:10px;align-items:center;gap:8px;padding:6px 10px;font-size:13px;transition:border-color .15s;display:flex}.CUIYUW_volumeGroupHeader:hover{border-color:var(--nf-accent)}.CUIYUW_volumeGroupToggle{color:var(--nf-text-2);flex:none;font-size:11px}.CUIYUW_chapter{border:1px solid var(--nf-border);background:var(--nf-bg);border-radius:10px;align-items:center;gap:10px;padding:9px 12px;transition:border-color .15s,box-shadow .15s,transform .1s;display:flex}.CUIYUW_chapter:hover{border-color:var(--nf-border-strong);box-shadow:var(--nf-shadow)}.CUIYUW_chapterNum{background:var(--nf-bg-inset);border:1px solid var(--nf-border);min-width:28px;height:28px;color:var(--nf-text-2);border-radius:8px;flex-shrink:0;justify-content:center;align-items:center;padding:0 8px;font-size:12px;font-weight:700;display:inline-flex}.CUIYUW_chapterMain{flex:1;min-width:0}.CUIYUW_chapterTitle{color:var(--nf-text);align-items:center;gap:8px;font-size:13px;font-weight:600;display:flex}.CUIYUW_chapterBeats{color:var(--nf-text-2);opacity:.85;text-overflow:ellipsis;white-space:nowrap;font-size:12px;overflow:hidden}.CUIYUW_chapterActions{opacity:.85;flex-shrink:0;gap:4px;transition:opacity .15s;display:flex}.CUIYUW_chapter:hover .CUIYUW_chapterActions{opacity:1}.CUIYUW_badge{white-space:nowrap;letter-spacing:.2px;border:1px solid;border-radius:999px;padding:2px 9px;font-size:11px;font-weight:600}.CUIYUW_badgePending{color:var(--nf-info);border-color:var(--nf-info);background:color-mix(in srgb, var(--nf-info) 10%, transparent)}.CUIYUW_badgeGenerating{color:var(--nf-accent);border-color:var(--nf-accent);background:color-mix(in srgb, var(--nf-accent) 12%, transparent);animation:1.2s ease-in-out infinite CUIYUW_pulse}.CUIYUW_badgeWritten{color:var(--nf-warn);border-color:var(--nf-warn);background:color-mix(in srgb, var(--nf-warn) 10%, transparent)}.CUIYUW_badgeRejected{color:var(--nf-error);border-color:var(--nf-error);background:color-mix(in srgb, var(--nf-error) 10%, transparent)}.CUIYUW_badgeDone{color:var(--nf-success);border-color:var(--nf-success);background:color-mix(in srgb, var(--nf-success) 10%, transparent)}.CUIYUW_badgeError{color:var(--nf-error);border-color:var(--nf-error);background:color-mix(in srgb, var(--nf-error) 10%, transparent)}.CUIYUW_reviewBox{border:1px solid var(--nf-border);background:var(--nf-bg-inset);border-radius:10px;flex-direction:column;gap:6px;padding:10px 12px;font-size:12.5px;display:flex}.CUIYUW_chapterPreview{white-space:pre-wrap;word-break:break-all;max-height:320px;color:var(--nf-text);background:var(--nf-bg-inset);border:1px solid var(--nf-border);border-radius:10px;margin:0;padding:10px 12px;font-family:inherit;font-size:12.5px;line-height:1.8;overflow:auto}.CUIYUW_chatScroll{border:1px solid var(--nf-border);background:var(--nf-bg-inset);border-radius:12px;flex-direction:column;flex:1;gap:10px;min-height:240px;max-height:480px;padding:14px;display:flex;overflow-y:auto}.CUIYUW_chatBubbleUser{background:linear-gradient(180deg, var(--nf-accent), var(--nf-accent-hover));max-width:90%;color:var(--nf-accent-fg);border-radius:14px 14px 4px;align-self:flex-end;padding:9px 14px;font-size:13px;box-shadow:0 2px 6px #4d6bfe33}.CUIYUW_chatBubbleAssistant{background:var(--nf-bg-raise);max-width:92%;color:var(--nf-text);border:1px solid var(--nf-border);box-shadow:var(--nf-shadow);border-radius:14px 14px 14px 4px;align-self:flex-start;padding:9px 14px;font-size:13px}.CUIYUW_chatRole{color:var(--nf-text-3);margin-bottom:3px;font-size:11px;font-weight:600}.CUIYUW_toolLive{background:var(--nf-bg-inset);border:1px dashed var(--nf-border-strong);white-space:pre-wrap;word-break:break-all;color:var(--nf-text-2);border-radius:8px;max-height:180px;margin-top:6px;padding:8px 10px;font-size:12px;line-height:1.7;overflow-y:auto}.CUIYUW_assistantStatus{color:var(--nf-text-2);background:var(--nf-bg-inset);border:1px solid var(--nf-border);border-radius:999px;flex:none;align-items:center;gap:6px;margin-top:6px;padding:6px 12px;font-size:12px;display:flex}.CUIYUW_assistantStatusBusy{color:var(--nf-accent);border-color:var(--nf-accent);background:var(--nf-accent-soft);font-weight:600}.CUIYUW_toolSteps{flex-direction:column;gap:4px;margin-top:6px;display:flex}.CUIYUW_toolStep{background:var(--nf-bg-inset);border:1px solid var(--nf-border);border-radius:8px;align-items:center;gap:8px;padding:5px 10px;font-size:12px;display:flex}.CUIYUW_toolStepActive{border-color:var(--nf-accent);background:var(--nf-accent-soft)}.CUIYUW_toolStepError{border-color:var(--nf-error);background:color-mix(in srgb, var(--nf-error) 8%, transparent)}.CUIYUW_toolStepIcon{flex:none;font-size:13px}.CUIYUW_toolStepName{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;font-weight:600;overflow:hidden}.CUIYUW_toolStepStatus{color:var(--nf-text-2);flex:none;font-size:11px}.CUIYUW_toolStepActive .CUIYUW_toolStepStatus{color:var(--nf-accent)}.CUIYUW_toolStepError .CUIYUW_toolStepStatus{color:var(--nf-error)}.CUIYUW_toolStepDetail{width:100%;color:var(--nf-error);word-break:break-all;font-size:11px}.CUIYUW_progress{border:1px solid var(--nf-border);white-space:pre-wrap;word-break:break-all;min-height:60px;max-height:220px;color:var(--nf-text-2);background:var(--nf-bg-inset);border-radius:10px;padding:10px 14px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px;line-height:1.8;overflow:auto}.CUIYUW_progressLine{color:var(--nf-text-2);opacity:.9}.CUIYUW_progressLineLive{color:var(--nf-accent);align-items:center;gap:8px;font-weight:600;display:flex}.CUIYUW_progressBar{background:var(--nf-border);border-radius:999px;flex:none;width:110px;height:6px;display:inline-block;overflow:hidden}.CUIYUW_progressBarFill{background:var(--nf-accent);border-radius:3px;height:100%;transition:width .3s;display:block}.CUIYUW_busyRow{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:12px;display:flex}.CUIYUW_liveText{font-variant-numeric:tabular-nums;color:var(--nf-text-2);font-size:12px}.CUIYUW_bigProgressBar{background:var(--nf-border);border-radius:999px;height:8px;margin-top:10px;overflow:hidden}.CUIYUW_bigProgressBarFill{background:linear-gradient(90deg, var(--nf-accent), var(--nf-accent-2,var(--nf-accent)));border-radius:999px;height:100%;transition:width .3s;display:block}.CUIYUW_diffLegend{flex-wrap:wrap;align-items:center;gap:14px;margin:6px 0 8px;font-size:12px;display:flex}.CUIYUW_legendOld{color:var(--nf-error);font-weight:700}.CUIYUW_legendNew{color:var(--nf-success);font-weight:700}.CUIYUW_onlyChanges{color:var(--nf-text-2);cursor:pointer;align-items:center;gap:4px;margin-left:auto;display:inline-flex}.CUIYUW_diffList{border:1px solid var(--nf-border);background:var(--nf-bg-inset);border-radius:8px;flex-direction:column;gap:8px;max-height:460px;padding:10px 12px;font-size:13px;line-height:1.7;display:flex;overflow-y:auto}.CUIYUW_diffSame{border:1px dashed var(--nf-border);color:var(--nf-text-2);opacity:.85;border-radius:6px;padding:6px 10px}.CUIYUW_diffSame summary{cursor:pointer;user-select:none;font-size:12px}.CUIYUW_diffSameBody{white-space:pre-wrap;margin-top:6px}.CUIYUW_diffChange{border:1px solid var(--nf-border);border-radius:8px;grid-template-columns:1fr 1fr;display:grid;overflow:hidden}.CUIYUW_diffColumn{flex-direction:column;gap:6px;min-width:0;padding:8px 10px;display:flex}.CUIYUW_diffColumn:first-child{border-right:1px solid var(--nf-border)}.CUIYUW_diffTagOld,.CUIYUW_diffTagNew{letter-spacing:.5px;border-radius:4px;flex:none;align-self:flex-start;padding:1px 7px;font-size:11px;font-weight:700}.CUIYUW_diffTagOld{color:var(--nf-error);background:color-mix(in srgb, var(--nf-error) 16%, transparent);border:1px solid color-mix(in srgb, var(--nf-error) 45%, transparent)}.CUIYUW_diffTagNew{color:var(--nf-success);background:color-mix(in srgb, var(--nf-success) 16%, transparent);border:1px solid color-mix(in srgb, var(--nf-success) 45%, transparent)}.CUIYUW_diffOld{color:var(--nf-error);white-space:pre-wrap;text-decoration:line-through;text-decoration-color:color-mix(in srgb, var(--nf-error) 55%, transparent)}.CUIYUW_diffNew{color:var(--nf-success);white-space:pre-wrap;font-weight:500}.CUIYUW_diffDel{border:1px solid color-mix(in srgb, var(--nf-error) 35%, transparent);background:color-mix(in srgb, var(--nf-error) 7%, transparent);border-radius:6px;flex-direction:column;gap:4px;padding:6px 10px;display:flex}.CUIYUW_diffAdd{border:1px solid color-mix(in srgb, var(--nf-success) 35%, transparent);background:color-mix(in srgb, var(--nf-success) 7%, transparent);border-radius:6px;flex-direction:column;gap:4px;padding:6px 10px;display:flex}.CUIYUW_diffText{white-space:pre-wrap}.CUIYUW_diffDel .CUIYUW_diffText{color:var(--nf-error);text-decoration:line-through;text-decoration-color:color-mix(in srgb, var(--nf-error) 50%, transparent)}.CUIYUW_diffAdd .CUIYUW_diffText{color:var(--nf-success)}.CUIYUW_wsColumns{grid-template-columns:minmax(0,3fr) minmax(0,2fr);gap:14px;display:grid}.CUIYUW_wsColumn{flex-direction:column;gap:8px;min-width:0;display:flex}.CUIYUW_wsEditor{resize:vertical;white-space:pre-wrap;flex:1;min-height:340px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:13px;line-height:1.75}.CUIYUW_wsSelected{border:1px solid var(--nf-accent);background:color-mix(in srgb, var(--nf-accent) 8%, transparent);border-radius:6px;max-height:120px;padding:6px 10px;overflow:auto}.CUIYUW_wsSelectedText{color:var(--nf-text-2);white-space:pre-wrap;margin-top:4px;font-size:12px}.CUIYUW_wsPreview{border:1px solid var(--nf-border);background:var(--nf-bg-inset);border-radius:8px;flex-direction:column;gap:8px;padding:8px 10px;display:flex}.CUIYUW_wsPreviewText{white-space:pre-wrap;max-height:320px;color:var(--nf-text);margin:0;font-size:13px;line-height:1.7;overflow:auto}.CUIYUW_assetGrid{grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px;display:grid}.CUIYUW_assetStat{border:1px solid var(--nf-border);background:var(--nf-bg-inset);border-radius:10px;flex-direction:column;gap:4px;padding:10px 12px;display:flex}.CUIYUW_assetStatLabel{color:var(--nf-text-2);opacity:.9;font-size:11px}.CUIYUW_assetStatValue{color:var(--nf-text);font-size:15px;font-weight:700;line-height:1.2}.CUIYUW_assetStatDetail{color:var(--nf-text-2);opacity:.85;text-overflow:ellipsis;white-space:nowrap;font-size:11px;overflow:hidden}.CUIYUW_dashHero{border:1px solid var(--nf-border);background:radial-gradient(1200px 400px at 110% -60%, color-mix(in srgb, var(--nf-accent) 16%, transparent), transparent 60%), linear-gradient(135deg, var(--nf-bg-raise), color-mix(in srgb, var(--nf-accent) 5%, var(--nf-bg-raise)));box-shadow:var(--nf-shadow);border-radius:16px;flex-direction:column;gap:14px;padding:18px 20px;display:flex}.CUIYUW_dashHeroEyebrow{color:var(--nf-accent);align-items:center;gap:6px;font-size:13px;font-weight:600;display:inline-flex}.CUIYUW_dashHeroSparkle{font-size:14px}.CUIYUW_dashHeroTitle{flex-direction:column;gap:2px;display:flex}.CUIYUW_dashHeroBook{letter-spacing:-.3px;margin:0;font-size:24px;font-weight:700;line-height:1.25}.CUIYUW_dashHeroAction{border:1px solid var(--nf-border);background:color-mix(in srgb, var(--nf-bg-base) 65%, transparent);border-radius:12px;align-items:center;gap:12px;padding:10px 14px;display:flex}.CUIYUW_dashHeroArrow{background:var(--nf-accent);color:#fff;border-radius:50%;flex:none;justify-content:center;align-items:center;width:28px;height:28px;font-size:14px;display:inline-flex}.CUIYUW_dashHeroActionBody{flex-direction:column;flex:1;gap:2px;min-width:0;display:flex}.CUIYUW_dashHeroActionTitle{font-size:14px;font-weight:600}.CUIYUW_dashJourney{flex-direction:column;gap:6px;display:flex}.CUIYUW_dashJourneyBar{background:var(--nf-border);border-radius:999px;height:6px;overflow:hidden}.CUIYUW_dashJourneyFill{background:linear-gradient(90deg, var(--nf-info), var(--nf-accent));border-radius:999px;height:100%;transition:width .4s;display:block}.CUIYUW_dashJourneyStages{grid-template-columns:repeat(6,minmax(0,1fr));gap:4px;display:grid}.CUIYUW_dashStage{color:var(--nf-text-3);text-align:center;white-space:nowrap;flex-direction:column;align-items:center;gap:3px;font-size:11px;display:flex}.CUIYUW_dashStageDot{border:1px solid var(--nf-border-strong,var(--nf-text-3));background:var(--nf-bg-base);border-radius:50%;justify-content:center;align-items:center;width:18px;height:18px;font-size:10px;display:inline-flex}.CUIYUW_dashStageDone{color:var(--nf-text-2)}.CUIYUW_dashStageDone .CUIYUW_dashStageDot{background:var(--nf-success);border-color:var(--nf-success);color:#fff}.CUIYUW_dashStageCurrent{color:var(--nf-accent);font-weight:600}.CUIYUW_dashStageCurrent .CUIYUW_dashStageDot{border-color:var(--nf-accent);color:var(--nf-accent);box-shadow:0 0 0 3px color-mix(in srgb, var(--nf-accent) 18%, transparent)}.CUIYUW_dashFacts{border-top:1px solid var(--nf-border);grid-template-columns:repeat(4,minmax(0,1fr));gap:8px;padding-top:12px;display:grid}.CUIYUW_dashFact{flex-direction:column;gap:2px;min-width:0;display:flex}.CUIYUW_dashFact b{white-space:nowrap;text-overflow:ellipsis;font-size:13px;overflow:hidden}.CUIYUW_dashGrid{grid-template-columns:minmax(0,3fr) minmax(0,2fr);align-items:start;gap:14px;display:grid}.CUIYUW_todoItem{border:1px solid var(--nf-border);border-radius:8px;align-items:center;gap:10px;padding:8px 12px;font-size:12.5px;display:flex}.CUIYUW_todoDanger{border-color:color-mix(in srgb, var(--nf-error) 40%, transparent);background:color-mix(in srgb, var(--nf-error) 8%, transparent)}.CUIYUW_todoWarning{border-color:color-mix(in srgb, var(--nf-warn) 40%, transparent);background:color-mix(in srgb, var(--nf-warn) 8%, transparent)}.CUIYUW_todoInfo{border-color:color-mix(in srgb, var(--nf-info) 40%, transparent);background:color-mix(in srgb, var(--nf-info) 7%, transparent)}.CUIYUW_todoText{flex-direction:column;flex:1;gap:2px;min-width:0;display:flex}.CUIYUW_outlineReadonly{border:1px solid var(--nf-border);background:var(--nf-bg-inset);white-space:pre-wrap;user-select:text;border-radius:12px;max-height:480px;margin:0;padding:12px 14px;font-size:12.5px;line-height:1.8;overflow:auto}.CUIYUW_bookCreateOutline{flex-direction:column;align-items:flex-start;gap:6px;display:flex}.CUIYUW_assistantFloat{z-index:80;border:1px solid var(--nf-border);background:var(--nf-bg-raise);backdrop-filter:blur(24px)saturate(180%);box-shadow:var(--nf-shadow-lg);border-radius:16px;flex-direction:column;min-width:320px;min-height:220px;display:flex;position:absolute;overflow:hidden}.CUIYUW_assistantFloatHeader{cursor:grab;user-select:none;border-bottom:1px solid var(--nf-border);background:var(--nf-bg-inset);flex:none;justify-content:space-between;align-items:center;gap:8px;padding:8px 10px 8px 14px;font-size:13px;font-weight:600;display:flex}.CUIYUW_assistantFloatHeader:active{cursor:grabbing}.CUIYUW_assistantFloatBody{flex:1;min-height:0;padding:10px;display:flex;overflow:hidden}.CUIYUW_assistantFloatBody>*{flex:1;min-width:0}.CUIYUW_assistantResize{cursor:nwse-resize;background:linear-gradient(135deg, transparent 0 55%, var(--nf-border-strong) 55% 62%, transparent 62%) no-repeat 4px 4px / 12px 12px;width:20px;height:20px;position:absolute;bottom:0;right:0}.CUIYUW_coverPreview{border:1px solid var(--nf-border);background:var(--nf-bg-inset);border-radius:12px;flex:none;justify-content:center;align-items:center;width:150px;height:200px;display:flex;overflow:hidden}.CUIYUW_coverPreview img{object-fit:contain;width:100%;height:100%;display:block}.CUIYUW_coverPlaceholder{color:var(--nf-text-3);font-size:12px}.CUIYUW_shelfView{flex-direction:column;flex:1;gap:16px;min-height:0;padding:18px;display:flex;overflow:auto}.CUIYUW_shelfHeader{flex-direction:column;gap:2px;display:flex}.CUIYUW_shelfGrid{grid-template-columns:repeat(auto-fill,minmax(190px,1fr));align-content:start;gap:14px;display:grid}.CUIYUW_bookCard{border:1px solid var(--nf-border);background:var(--nf-bg-raise);backdrop-filter:blur(24px)saturate(180%);box-shadow:var(--nf-shadow);cursor:pointer;border-radius:16px;flex-direction:column;gap:8px;padding:12px;transition:border-color .15s,transform .1s,box-shadow .15s;display:flex}.CUIYUW_bookCard:hover{border-color:var(--nf-accent);box-shadow:var(--nf-shadow-lg);transform:translateY(-2px)}.CUIYUW_bookCardActive{border-color:var(--nf-accent);box-shadow:0 0 0 3px var(--nf-accent-soft)}.CUIYUW_bookCardCover{aspect-ratio:3/4;background:var(--nf-bg-inset);border:1px solid var(--nf-border);border-radius:12px;flex:none;justify-content:center;align-items:center;display:flex;overflow:hidden}.CUIYUW_bookCardCover img{object-fit:contain;width:100%;height:100%;display:block}.CUIYUW_bookCardCoverFallback{background:radial-gradient(400px 200px at 80% -20%, color-mix(in srgb, var(--nf-accent) 25%, transparent), transparent 70%), linear-gradient(155deg, var(--nf-bg-inset), color-mix(in srgb, var(--nf-accent) 10%, var(--nf-bg-inset)));flex-direction:column;justify-content:center;align-items:center;gap:6px;width:100%;height:100%;display:flex}.CUIYUW_bookCardCoverTitle{color:var(--nf-accent);letter-spacing:2px;font-size:22px;font-weight:800}.CUIYUW_bookCardBody{flex-direction:column;gap:5px;min-width:0;display:flex}.CUIYUW_bookCardTitleRow{justify-content:space-between;align-items:center;gap:6px;display:flex}.CUIYUW_bookCardName{text-overflow:ellipsis;white-space:nowrap;font-size:13.5px;font-weight:700;overflow:hidden}.CUIYUW_bookCardBlurb{-webkit-line-clamp:2;-webkit-box-orient:vertical;min-height:34px;display:-webkit-box;overflow:hidden}.CUIYUW_bookCardProgressBar{background:var(--nf-border);border-radius:999px;height:5px;overflow:hidden}.CUIYUW_bookCardProgressFill{background:linear-gradient(90deg, var(--nf-info), var(--nf-accent));border-radius:999px;height:100%;transition:width .3s;display:block}.CUIYUW_bookAddCard{text-align:center;color:var(--nf-text-2);border-style:dashed;justify-content:center;align-items:center;gap:8px;min-height:260px}.CUIYUW_bookAddCard:hover{color:var(--nf-accent)}.CUIYUW_bookAddIcon{color:var(--nf-accent);font-size:34px;line-height:1}.CUIYUW_bookCreateCard{border-color:var(--nf-accent);min-height:260px}.CUIYUW_createBookView{flex-direction:column;flex:1;gap:14px;min-height:0;padding:14px 18px 24px;display:flex;overflow:auto}.CUIYUW_createBookTop{align-items:center;display:flex}.CUIYUW_createBookCard{border:1px solid var(--nf-border);background:var(--nf-bg-raise);backdrop-filter:blur(24px)saturate(180%);width:min(520px,100%);box-shadow:var(--nf-shadow-lg);border-radius:20px;flex-direction:column;align-self:center;gap:12px;padding:26px 28px;display:flex}.CUIYUW_createBookIcon{font-size:34px;line-height:1}.CUIYUW_createBookTitle{letter-spacing:-.3px;margin:0;font-size:22px;font-weight:800}.CUIYUW_progressLineDone{color:var(--nf-success);font-weight:600}.CUIYUW_progressLineError{color:var(--nf-error);font-weight:600}.CUIYUW_meta{color:var(--nf-text-2);opacity:.9;font-size:12px}.CUIYUW_genreDesc{-webkit-line-clamp:2;-webkit-box-orient:vertical;max-width:560px;display:-webkit-box;overflow:hidden}.CUIYUW_fileList{color:var(--nf-text-2);opacity:.9;word-break:break-all;flex-direction:column;gap:3px;font-size:12px;display:flex}.CUIYUW_panelContent::-webkit-scrollbar,.CUIYUW_chatScroll::-webkit-scrollbar,.CUIYUW_chapterPreview::-webkit-scrollbar,.CUIYUW_progress::-webkit-scrollbar,.CUIYUW_toolLive::-webkit-scrollbar{width:8px;height:8px}.CUIYUW_panelContent::-webkit-scrollbar-thumb,.CUIYUW_chatScroll::-webkit-scrollbar-thumb,.CUIYUW_chapterPreview::-webkit-scrollbar-thumb,.CUIYUW_progress::-webkit-scrollbar-thumb,.CUIYUW_toolLive::-webkit-scrollbar-thumb{background:var(--nf-border-strong);border-radius:4px}.CUIYUW_panelContent::-webkit-scrollbar-thumb:hover,.CUIYUW_chatScroll::-webkit-scrollbar-thumb:hover,.CUIYUW_chapterPreview::-webkit-scrollbar-thumb:hover,.CUIYUW_progress::-webkit-scrollbar-thumb:hover,.CUIYUW_toolLive::-webkit-scrollbar-thumb:hover{background:var(--nf-text-3)}.CUIYUW_workflowList{flex-direction:column;gap:0;display:flex}.CUIYUW_workflowRow{align-items:flex-start;gap:12px;padding:8px 4px;display:flex;position:relative}.CUIYUW_workflowRow:before{content:\"\";background:var(--nf-border);width:2px;position:absolute;top:34px;bottom:-8px;left:13px}.CUIYUW_workflowRow:last-child:before{display:none}.CUIYUW_workflowDot{border:2px solid var(--nf-border-strong);background:var(--nf-bg-raise);width:28px;height:28px;color:var(--nf-text-2);z-index:1;border-radius:50%;flex-shrink:0;justify-content:center;align-items:center;font-size:12px;font-weight:700;display:inline-flex}.CUIYUW_workflowDotDone{border-color:var(--nf-success);background:color-mix(in srgb, var(--nf-success) 15%, var(--nf-bg-raise));color:var(--nf-success)}.CUIYUW_workflowDotActive{border-color:var(--nf-accent);background:var(--nf-accent);color:var(--nf-accent-fg);box-shadow:0 0 0 4px var(--nf-accent-soft)}.CUIYUW_workflowBody{flex-direction:column;flex:1;gap:4px;min-width:0;padding-top:2px;display:flex}.CUIYUW_workflowLabel{color:var(--nf-text);font-size:13px;font-weight:600}.CUIYUW_workflowHint{color:var(--nf-text-2);font-size:12px}@keyframes CUIYUW_pulse{0%,to{opacity:1}50%{opacity:.45}}@keyframes CUIYUW_fadeIn{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}.CUIYUW_card{animation:.2s CUIYUW_fadeIn}.CUIYUW_bookshelf{border-bottom:1px solid var(--nf-border);background:var(--nf-bg-raise);flex-wrap:wrap;flex-shrink:0;align-items:center;gap:10px;padding:8px 18px;display:flex}.CUIYUW_bookshelfLabel{color:var(--nf-text-3);letter-spacing:1px;flex-shrink:0;font-size:12px;font-weight:700}.CUIYUW_bookshelfList{flex-wrap:wrap;flex:1;align-items:center;gap:6px;min-width:0;display:flex}.CUIYUW_bookChip{border:1px solid var(--nf-border);background:var(--nf-bg-inset);cursor:pointer;border-radius:999px;align-items:center;gap:6px;max-width:220px;padding:4px 8px 4px 10px;font-size:12px;transition:border-color .15s,background .15s;display:flex}.CUIYUW_bookChip:hover{border-color:var(--nf-border-strong)}.CUIYUW_bookChipActive{border-color:var(--nf-accent);background:var(--nf-accent-soft);color:var(--nf-accent)}.CUIYUW_bookChipName{text-overflow:ellipsis;white-space:nowrap;font-weight:600;overflow:hidden}.CUIYUW_bookChipMeta{opacity:.7;white-space:nowrap;font-size:11px}.CUIYUW_bookChipRemove{color:var(--nf-text-3);cursor:pointer;background:0 0;border:none;border-radius:4px;padding:0 2px;font-size:13px;line-height:1}.CUIYUW_bookChipRemove:hover{color:var(--nf-error)}.CUIYUW_bookAdd{border:1px dashed var(--nf-border-strong);color:var(--nf-text-2);cursor:pointer;background:0 0;border-radius:999px;padding:4px 12px;font-size:12px;transition:border-color .15s,color .15s}.CUIYUW_bookAdd:hover{border-color:var(--nf-accent);color:var(--nf-accent)}.CUIYUW_bookCreateForm{align-items:center;gap:6px;display:flex}.CUIYUW_dropzone{border:2px dashed var(--nf-border-strong);text-align:center;color:var(--nf-text-2);cursor:pointer;border-radius:10px;flex-direction:column;align-items:center;gap:6px;padding:18px 14px;font-size:13px;transition:border-color .15s,background .15s;display:flex}.CUIYUW_dropzone:hover,.CUIYUW_dropzoneActive{border-color:var(--nf-accent);background:var(--nf-accent-soft);color:var(--nf-accent)}.CUIYUW_dropzoneIcon{font-size:22px;line-height:1}";
648
+ const css = ".CUIYUW_entry{width:100%;color:var(--dsw-alias-label-primary,#1f1f23);cursor:pointer;text-align:left;background:0 0;border:none;border-radius:6px;align-items:center;gap:8px;padding:8px 12px;font-size:13px;transition:background .15s;display:flex}body[data-ds-dark-theme] .CUIYUW_entry{color:var(--dsw-alias-label-primary,#ececf1)}.CUIYUW_entry:hover{background:var(--dsw-alias-interactive-bg-hover,#7f7f7f1f)}.CUIYUW_entry[data-active]{background:var(--dsw-alias-interactive-bg-active,#7f7f7f33)}.CUIYUW_entryIcon{flex-shrink:0;justify-content:center;align-items:center;display:inline-flex}.CUIYUW_entryLabel{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}[data-pane=conversation]{position:relative}.CUIYUW_view{z-index:60;color-scheme:light;--nf-bg:#f2f2f7db;--nf-bg-raise:#ffffffb8;--nf-bg-inset:#7676801f;--nf-border:#3c3c4329;--nf-border-strong:#3c3c4352;--nf-text:#1c1c1e;--nf-text-2:#3c3c43;--nf-text-2-alpha:#3c3c43ad;--nf-text-3:#8e8e93;--nf-accent:#007aff;--nf-accent-hover:#0071e3;--nf-accent-soft:#007aff1f;--nf-accent-fg:#fff;--nf-hover:#0000000d;--nf-success:#34c759;--nf-error:#ff3b30;--nf-warn:#ff9500;--nf-info:#5856d6;--nf-shadow:0 1px 3px #0000000f, 0 12px 32px #00000014;--nf-shadow-lg:0 4px 12px #00000012, 0 20px 48px #0000001f;background:var(--nf-bg);backdrop-filter:blur(32px)saturate(180%);color:var(--nf-text);font-family:-apple-system,BlinkMacSystemFont,SF Pro Text,SF Pro SC,PingFang SC,Segoe UI,Roboto,Helvetica Neue,sans-serif;display:none;position:absolute;inset:0;overflow:auto}body[data-ds-dark-theme] .CUIYUW_view{color-scheme:dark;--nf-bg:#000000b8;--nf-bg-raise:#1c1c1ec7;--nf-bg-inset:#7676802e;--nf-border:#ffffff1f;--nf-border-strong:#ffffff47;--nf-text:#f2f2f7;--nf-text-2:#d1d1d6;--nf-text-2-alpha:#d1d1d6b8;--nf-text-3:#8e8e93;--nf-accent:#0a84ff;--nf-accent-hover:#3a9bff;--nf-accent-soft:#0a84ff33;--nf-accent-fg:#fff;--nf-hover:#ffffff17;--nf-success:#30d158;--nf-error:#ff453a;--nf-warn:#ff9f0a;--nf-info:#bf5af2;--nf-shadow:0 1px 2px #00000059, 0 10px 30px #0006;--nf-shadow-lg:0 4px 12px #0006, 0 20px 48px #0000008c}html[data-dsh-novelforge-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-active]) .CUIYUW_view{display:block}.CUIYUW_panel{flex-direction:column;min-width:0;height:100%;font-size:14px;line-height:1.6;display:flex;position:relative}.CUIYUW_panelHeader{border-bottom:1px solid var(--nf-border);background:var(--nf-bg-raise);backdrop-filter:blur(24px)saturate(180%);z-index:5;flex-shrink:0;justify-content:space-between;align-items:center;padding:12px 18px;display:flex;position:sticky;top:0}.CUIYUW_panelTitle{letter-spacing:.2px;align-items:center;gap:8px;margin:0;font-size:16px;font-weight:700;display:flex}.CUIYUW_panelTitle:before{content:\"\";background:linear-gradient(180deg, var(--nf-accent), var(--nf-info));border-radius:2px;width:4px;height:16px}.CUIYUW_iconButton{cursor:pointer;color:var(--nf-text-2);background:0 0;border:none;border-radius:8px;padding:4px 9px;font-size:16px;transition:background .15s,color .15s}.CUIYUW_iconButton:hover{background:var(--nf-hover);color:var(--nf-text)}.CUIYUW_tabBar{border-bottom:1px solid var(--nf-border);background:var(--nf-bg-raise);z-index:4;flex-shrink:0;gap:2px;padding:8px 14px 0;display:flex;position:sticky;top:45px}.CUIYUW_tab{cursor:pointer;color:var(--nf-text-2);background:0 0;border:none;border-radius:8px 8px 0 0;padding:7px 13px;font-size:13.5px;font-weight:500;transition:color .15s,background .15s;position:relative}.CUIYUW_tab:hover{color:var(--nf-text);background:var(--nf-hover)}.CUIYUW_tab[data-active]{color:var(--nf-accent);font-weight:600}.CUIYUW_tab[data-active]:after{content:\"\";background:var(--nf-accent);border-radius:2px 2px 0 0;height:2.5px;position:absolute;bottom:-1px;left:10px;right:10px}.CUIYUW_panelContent{flex-direction:column;flex:1;gap:14px;padding:16px 18px 20px;display:flex;overflow:auto}.CUIYUW_panelBody{flex:1;min-height:0;display:flex}.CUIYUW_panelNav{border-right:1px solid var(--nf-border);background:var(--nf-bg-raise);backdrop-filter:blur(24px)saturate(180%);flex-direction:column;flex:none;gap:2px;width:142px;padding:10px 8px;transition:width .18s;display:flex;overflow-y:auto}.CUIYUW_panelNavCollapsed{width:52px;padding:10px 6px}.CUIYUW_navGroup{flex-direction:column;gap:2px;display:flex}.CUIYUW_navGroupLabel{letter-spacing:.6px;text-transform:uppercase;color:var(--nf-text-3);user-select:none;padding:6px 10px 2px;font-size:10.5px;font-weight:600}.CUIYUW_navGroupSep{background:var(--nf-border);height:1px;margin:6px 8px 4px}.CUIYUW_navSpacer{flex:1;min-height:8px}.CUIYUW_navAbout{border-top:1px solid var(--nf-border);flex-direction:column;flex:none;gap:4px;margin-top:4px;padding:8px 6px 4px;display:flex}.CUIYUW_navAboutRow{cursor:pointer;color:var(--nf-text-3);text-align:left;white-space:nowrap;background:0 0;border:none;border-radius:8px;justify-content:space-between;align-items:center;gap:4px;padding:4px 6px;font-size:11px;transition:color .15s,background .15s;display:flex}.CUIYUW_navAboutRow:hover{color:var(--nf-text);background:var(--nf-hover)}.CUIYUW_navAboutUpdate{background:var(--nf-accent-soft);color:var(--nf-accent);cursor:pointer;text-align:left;white-space:nowrap;border:none;border-radius:8px;padding:4px 6px;font-size:10.5px;font-weight:600}.CUIYUW_navAboutUpdate:hover{color:var(--nf-accent-hover)}.CUIYUW_panelNavCollapsed .CUIYUW_navAbout{align-items:center;padding:6px 2px 2px}.CUIYUW_panelNavCollapsed .CUIYUW_navAboutRow{justify-content:center;width:100%;padding:4px 0}.CUIYUW_navTabBadge{background:var(--nf-accent);color:#fff;text-align:center;border-radius:999px;flex:none;min-width:18px;height:18px;margin-left:auto;padding:0 5px;font-size:10.5px;font-weight:700;line-height:18px;display:inline-block}.CUIYUW_panelNavCollapsed .CUIYUW_navTabBadge{min-width:14px;height:14px;padding:0 3px;font-size:9px;line-height:14px;position:absolute;top:2px;right:2px}.CUIYUW_navTabBadgeDanger{background:var(--nf-error)}.CUIYUW_navTabBadgeWarn{background:var(--nf-warn)}.CUIYUW_navTabBadgeDone{background:var(--nf-success)}.CUIYUW_navTab{cursor:pointer;width:100%;color:var(--nf-text-2-alpha,var(--nf-text-2));text-align:left;white-space:nowrap;background:0 0;border:none;border-radius:12px;align-items:center;gap:8px;padding:8px 10px;font-size:13px;font-weight:500;transition:color .15s,background .15s;display:flex;position:relative}.CUIYUW_panelNavCollapsed .CUIYUW_navTab{justify-content:center;padding:8px 0}.CUIYUW_navTab:hover{color:var(--nf-text);background:var(--nf-hover)}.CUIYUW_navTab[data-active]{color:var(--nf-accent);background:var(--nf-accent-soft);font-weight:600}.CUIYUW_navTab[data-active]:before{content:\"\";background:var(--nf-accent);border-radius:999px;width:3px;position:absolute;top:20%;bottom:20%;left:-8px}.CUIYUW_panelNavCollapsed .CUIYUW_navTab[data-active]:before{left:-6px}.CUIYUW_navTabIcon{flex:none;font-size:15px;line-height:1}.CUIYUW_navTabLabel{text-overflow:ellipsis;overflow:hidden}.CUIYUW_headerProgress{color:var(--nf-text-2);white-space:nowrap;align-items:center;gap:6px;margin-left:4px;font-size:12px;font-weight:400;display:inline-flex}.CUIYUW_headerProgress b{color:var(--nf-accent);font-weight:700}.CUIYUW_headerProgressDot{background:var(--nf-border-strong,var(--nf-text-3));border-radius:50%;width:3px;height:3px;display:inline-block}.CUIYUW_card{border:1px solid var(--nf-border);background:var(--nf-bg-raise);box-shadow:var(--nf-shadow);backdrop-filter:blur(24px)saturate(180%);border-radius:20px;flex-direction:column;gap:10px;padding:16px 18px;transition:border-color .2s,box-shadow .2s;display:flex}.CUIYUW_cardTitle{color:var(--nf-text);align-items:center;gap:8px;margin:0;font-size:14px;font-weight:650;display:flex}.CUIYUW_button{border:1px solid var(--nf-border-strong);background:var(--nf-bg-inset);color:var(--nf-text);cursor:pointer;white-space:nowrap;border-radius:12px;padding:6px 14px;font-size:13px;font-weight:500;transition:background .15s,border-color .15s,transform .1s,box-shadow .15s}.CUIYUW_button:hover:not([disabled]){background:var(--nf-hover);border-color:var(--nf-border-strong)}.CUIYUW_button:active:not([disabled]){transform:scale(.96)}.CUIYUW_button[disabled]{opacity:.45;cursor:not-allowed}.CUIYUW_buttonPrimary{background:linear-gradient(180deg, color-mix(in srgb, var(--nf-accent) 88%, #fff), var(--nf-accent));color:var(--nf-accent-fg);box-shadow:0 2px 8px color-mix(in srgb, var(--nf-accent) 35%, transparent);border-color:#0000}.CUIYUW_buttonPrimary:hover:not([disabled]){background:linear-gradient(180deg, var(--nf-accent-hover), color-mix(in srgb, var(--nf-accent-hover) 85%, #000));border-color:#0000}.CUIYUW_buttonDanger{border-color:var(--nf-error);color:var(--nf-error)}.CUIYUW_buttonDanger:hover:not([disabled]){background:#ff3b301a}.CUIYUW_buttonSmall{border-radius:9px;padding:3px 10px;font-size:12px}.CUIYUW_field{flex-direction:column;gap:5px;display:flex}.CUIYUW_fieldLabel{color:var(--nf-text-2);font-size:12px;font-weight:500}.CUIYUW_input{border:1px solid var(--nf-border-strong);background:var(--nf-bg-inset);color:var(--nf-text);box-sizing:border-box;border-radius:12px;width:100%;padding:7px 11px;font-size:13px;transition:border-color .15s,box-shadow .15s}.CUIYUW_input:focus,.CUIYUW_textarea:focus{border-color:var(--nf-accent);box-shadow:0 0 0 3px var(--nf-accent-soft);outline:none}.CUIYUW_input::placeholder,.CUIYUW_textarea::placeholder{color:var(--nf-text-3)}.CUIYUW_textarea{border:1px solid var(--nf-border-strong);background:var(--nf-bg-inset);color:var(--nf-text);box-sizing:border-box;resize:vertical;border-radius:12px;width:100%;min-height:200px;padding:9px 11px;font-family:inherit;font-size:13px;line-height:1.7;transition:border-color .15s,box-shadow .15s}.CUIYUW_row{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.CUIYUW_spaceBetween{justify-content:space-between}.CUIYUW_chapterList{flex-direction:column;gap:8px;display:flex}.CUIYUW_volumeGroup{flex-direction:column;gap:6px;display:flex}.CUIYUW_volumeGroupHeader{background:var(--nf-bg-inset);border:1px solid var(--nf-border);cursor:pointer;user-select:none;border-radius:10px;align-items:center;gap:8px;padding:6px 10px;font-size:13px;transition:border-color .15s;display:flex}.CUIYUW_volumeGroupHeader:hover{border-color:var(--nf-accent)}.CUIYUW_volumeGroupToggle{color:var(--nf-text-2);flex:none;font-size:11px}.CUIYUW_chapter{border:1px solid var(--nf-border);background:var(--nf-bg);border-radius:10px;align-items:center;gap:10px;padding:9px 12px;transition:border-color .15s,box-shadow .15s,transform .1s;display:flex}.CUIYUW_chapter:hover{border-color:var(--nf-border-strong);box-shadow:var(--nf-shadow)}.CUIYUW_chapterNum{background:var(--nf-bg-inset);border:1px solid var(--nf-border);min-width:28px;height:28px;color:var(--nf-text-2);border-radius:8px;flex-shrink:0;justify-content:center;align-items:center;padding:0 8px;font-size:12px;font-weight:700;display:inline-flex}.CUIYUW_chapterMain{flex:1;min-width:0}.CUIYUW_chapterTitle{color:var(--nf-text);align-items:center;gap:8px;font-size:13px;font-weight:600;display:flex}.CUIYUW_chapterBeats{color:var(--nf-text-2);opacity:.85;text-overflow:ellipsis;white-space:nowrap;font-size:12px;overflow:hidden}.CUIYUW_chapterActions{opacity:.85;flex-shrink:0;gap:4px;transition:opacity .15s;display:flex}.CUIYUW_chapter:hover .CUIYUW_chapterActions{opacity:1}.CUIYUW_badge{white-space:nowrap;letter-spacing:.2px;border:1px solid;border-radius:999px;padding:2px 9px;font-size:11px;font-weight:600}.CUIYUW_badgePending{color:var(--nf-info);border-color:var(--nf-info);background:color-mix(in srgb, var(--nf-info) 10%, transparent)}.CUIYUW_badgeGenerating{color:var(--nf-accent);border-color:var(--nf-accent);background:color-mix(in srgb, var(--nf-accent) 12%, transparent);animation:1.2s ease-in-out infinite CUIYUW_pulse}.CUIYUW_badgeWritten{color:var(--nf-warn);border-color:var(--nf-warn);background:color-mix(in srgb, var(--nf-warn) 10%, transparent)}.CUIYUW_badgeRejected{color:var(--nf-error);border-color:var(--nf-error);background:color-mix(in srgb, var(--nf-error) 10%, transparent)}.CUIYUW_badgeDone{color:var(--nf-success);border-color:var(--nf-success);background:color-mix(in srgb, var(--nf-success) 10%, transparent)}.CUIYUW_badgeError{color:var(--nf-error);border-color:var(--nf-error);background:color-mix(in srgb, var(--nf-error) 10%, transparent)}.CUIYUW_reviewBox{border:1px solid var(--nf-border);background:var(--nf-bg-inset);border-radius:10px;flex-direction:column;gap:6px;padding:10px 12px;font-size:12.5px;display:flex}.CUIYUW_chapterPreview{white-space:pre-wrap;word-break:break-all;max-height:320px;color:var(--nf-text);background:var(--nf-bg-inset);border:1px solid var(--nf-border);border-radius:10px;margin:0;padding:10px 12px;font-family:inherit;font-size:12.5px;line-height:1.8;overflow:auto}.CUIYUW_chatScroll{border:1px solid var(--nf-border);background:var(--nf-bg-inset);border-radius:12px;flex-direction:column;flex:1;gap:10px;min-height:240px;max-height:480px;padding:14px;display:flex;overflow-y:auto}.CUIYUW_chatBubbleUser{background:linear-gradient(180deg, var(--nf-accent), var(--nf-accent-hover));max-width:90%;color:var(--nf-accent-fg);border-radius:14px 14px 4px;align-self:flex-end;padding:9px 14px;font-size:13px;box-shadow:0 2px 6px #4d6bfe33}.CUIYUW_chatBubbleAssistant{background:var(--nf-bg-raise);max-width:92%;color:var(--nf-text);border:1px solid var(--nf-border);box-shadow:var(--nf-shadow);border-radius:14px 14px 14px 4px;align-self:flex-start;padding:9px 14px;font-size:13px}.CUIYUW_chatRole{color:var(--nf-text-3);margin-bottom:3px;font-size:11px;font-weight:600}.CUIYUW_toolLive{background:var(--nf-bg-inset);border:1px dashed var(--nf-border-strong);white-space:pre-wrap;word-break:break-all;color:var(--nf-text-2);border-radius:8px;max-height:180px;margin-top:6px;padding:8px 10px;font-size:12px;line-height:1.7;overflow-y:auto}.CUIYUW_assistantStatus{color:var(--nf-text-2);background:var(--nf-bg-inset);border:1px solid var(--nf-border);border-radius:999px;flex:none;align-items:center;gap:6px;margin-top:6px;padding:6px 12px;font-size:12px;display:flex}.CUIYUW_assistantStatusBusy{color:var(--nf-accent);border-color:var(--nf-accent);background:var(--nf-accent-soft);font-weight:600}.CUIYUW_toolSteps{flex-direction:column;gap:4px;margin-top:6px;display:flex}.CUIYUW_toolStep{background:var(--nf-bg-inset);border:1px solid var(--nf-border);border-radius:8px;align-items:center;gap:8px;padding:5px 10px;font-size:12px;display:flex}.CUIYUW_toolStepActive{border-color:var(--nf-accent);background:var(--nf-accent-soft)}.CUIYUW_toolStepError{border-color:var(--nf-error);background:color-mix(in srgb, var(--nf-error) 8%, transparent)}.CUIYUW_toolStepIcon{flex:none;font-size:13px}.CUIYUW_toolStepName{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;font-weight:600;overflow:hidden}.CUIYUW_toolStepStatus{color:var(--nf-text-2);flex:none;font-size:11px}.CUIYUW_toolStepActive .CUIYUW_toolStepStatus{color:var(--nf-accent)}.CUIYUW_toolStepError .CUIYUW_toolStepStatus{color:var(--nf-error)}.CUIYUW_toolStepDetail{width:100%;color:var(--nf-error);word-break:break-all;font-size:11px}.CUIYUW_progress{border:1px solid var(--nf-border);white-space:pre-wrap;word-break:break-all;min-height:60px;max-height:220px;color:var(--nf-text-2);background:var(--nf-bg-inset);border-radius:10px;padding:10px 14px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px;line-height:1.8;overflow:auto}.CUIYUW_progressLine{color:var(--nf-text-2);opacity:.9}.CUIYUW_progressLineLive{color:var(--nf-accent);align-items:center;gap:8px;font-weight:600;display:flex}.CUIYUW_progressBar{background:var(--nf-border);border-radius:999px;flex:none;width:110px;height:6px;display:inline-block;overflow:hidden}.CUIYUW_progressBarFill{background:var(--nf-accent);border-radius:3px;height:100%;transition:width .3s;display:block}.CUIYUW_busyRow{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:12px;display:flex}.CUIYUW_liveText{font-variant-numeric:tabular-nums;color:var(--nf-text-2);font-size:12px}.CUIYUW_bigProgressBar{background:var(--nf-border);border-radius:999px;height:8px;margin-top:10px;overflow:hidden}.CUIYUW_bigProgressBarFill{background:linear-gradient(90deg, var(--nf-accent), var(--nf-accent-2,var(--nf-accent)));border-radius:999px;height:100%;transition:width .3s;display:block}.CUIYUW_diffLegend{flex-wrap:wrap;align-items:center;gap:14px;margin:6px 0 8px;font-size:12px;display:flex}.CUIYUW_legendOld{color:var(--nf-error);font-weight:700}.CUIYUW_legendNew{color:var(--nf-success);font-weight:700}.CUIYUW_onlyChanges{color:var(--nf-text-2);cursor:pointer;align-items:center;gap:4px;margin-left:auto;display:inline-flex}.CUIYUW_diffList{border:1px solid var(--nf-border);background:var(--nf-bg-inset);border-radius:8px;flex-direction:column;gap:8px;max-height:70vh;padding:10px 12px;font-size:13px;line-height:1.7;display:flex;overflow-y:auto}.CUIYUW_diffSame{border:1px dashed var(--nf-border);color:var(--nf-text-2);opacity:.85;border-radius:6px;padding:6px 10px}.CUIYUW_diffSame summary{cursor:pointer;user-select:none;font-size:12px}.CUIYUW_diffSameBody{white-space:pre-wrap;margin-top:6px}.CUIYUW_diffChange{border:1px solid var(--nf-border);border-radius:8px;grid-template-columns:1fr 1fr;display:grid;overflow:hidden}.CUIYUW_diffColumn{flex-direction:column;gap:6px;min-width:0;padding:8px 10px;display:flex}.CUIYUW_diffColumn:first-child{border-right:1px solid var(--nf-border)}.CUIYUW_diffTagOld,.CUIYUW_diffTagNew{letter-spacing:.5px;border-radius:4px;flex:none;align-self:flex-start;padding:1px 7px;font-size:11px;font-weight:700}.CUIYUW_diffTagOld{color:var(--nf-error);background:color-mix(in srgb, var(--nf-error) 16%, transparent);border:1px solid color-mix(in srgb, var(--nf-error) 45%, transparent)}.CUIYUW_diffTagNew{color:var(--nf-success);background:color-mix(in srgb, var(--nf-success) 16%, transparent);border:1px solid color-mix(in srgb, var(--nf-success) 45%, transparent)}.CUIYUW_diffOld{color:var(--nf-error);white-space:pre-wrap;text-decoration:line-through;text-decoration-color:color-mix(in srgb, var(--nf-error) 55%, transparent)}.CUIYUW_diffNew{color:var(--nf-success);white-space:pre-wrap;font-weight:500}.CUIYUW_diffDel{border:1px solid color-mix(in srgb, var(--nf-error) 35%, transparent);background:color-mix(in srgb, var(--nf-error) 7%, transparent);border-radius:6px;flex-direction:column;gap:4px;padding:6px 10px;display:flex}.CUIYUW_diffAdd{border:1px solid color-mix(in srgb, var(--nf-success) 35%, transparent);background:color-mix(in srgb, var(--nf-success) 7%, transparent);border-radius:6px;flex-direction:column;gap:4px;padding:6px 10px;display:flex}.CUIYUW_diffText{white-space:pre-wrap}.CUIYUW_diffDel .CUIYUW_diffText{color:var(--nf-error);text-decoration:line-through;text-decoration-color:color-mix(in srgb, var(--nf-error) 50%, transparent)}.CUIYUW_diffAdd .CUIYUW_diffText{color:var(--nf-success)}.CUIYUW_wsColumns{grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:14px;display:grid}.CUIYUW_wsColumn{flex-direction:column;gap:8px;min-width:0;display:flex}.CUIYUW_wsEditor{resize:vertical;white-space:pre-wrap;flex:1;min-height:50vh;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:13px;line-height:1.75}.CUIYUW_wsSelected{border:1px solid var(--nf-accent);background:color-mix(in srgb, var(--nf-accent) 8%, transparent);border-radius:6px;max-height:120px;padding:6px 10px;overflow:auto}.CUIYUW_wsSelectedText{color:var(--nf-text-2);white-space:pre-wrap;margin-top:4px;font-size:12px}.CUIYUW_wsPreview{border:1px solid var(--nf-border);background:var(--nf-bg-inset);border-radius:8px;flex-direction:column;gap:8px;padding:8px 10px;display:flex}.CUIYUW_wsPreviewText{white-space:pre-wrap;max-height:55vh;color:var(--nf-text);margin:0;font-size:13px;line-height:1.7;overflow:auto}.CUIYUW_assetGrid{grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px;display:grid}.CUIYUW_assetStat{border:1px solid var(--nf-border);background:var(--nf-bg-inset);border-radius:10px;flex-direction:column;gap:4px;padding:10px 12px;display:flex}.CUIYUW_assetStatLabel{color:var(--nf-text-2);opacity:.9;font-size:11px}.CUIYUW_assetStatValue{color:var(--nf-text);font-size:15px;font-weight:700;line-height:1.2}.CUIYUW_assetStatDetail{color:var(--nf-text-2);opacity:.85;text-overflow:ellipsis;white-space:nowrap;font-size:11px;overflow:hidden}.CUIYUW_dashHero{border:1px solid var(--nf-border);background:radial-gradient(1200px 400px at 110% -60%, color-mix(in srgb, var(--nf-accent) 16%, transparent), transparent 60%), linear-gradient(135deg, var(--nf-bg-raise), color-mix(in srgb, var(--nf-accent) 5%, var(--nf-bg-raise)));box-shadow:var(--nf-shadow);border-radius:16px;flex-direction:column;gap:14px;padding:18px 20px;display:flex}.CUIYUW_dashHeroEyebrow{color:var(--nf-accent);align-items:center;gap:6px;font-size:13px;font-weight:600;display:inline-flex}.CUIYUW_dashHeroSparkle{font-size:14px}.CUIYUW_dashHeroTitle{flex-direction:column;gap:2px;display:flex}.CUIYUW_dashHeroBook{letter-spacing:-.3px;margin:0;font-size:24px;font-weight:700;line-height:1.25}.CUIYUW_dashHeroAction{border:1px solid var(--nf-border);background:color-mix(in srgb, var(--nf-bg-base) 65%, transparent);border-radius:12px;align-items:center;gap:12px;padding:10px 14px;display:flex}.CUIYUW_dashHeroArrow{background:var(--nf-accent);color:#fff;border-radius:50%;flex:none;justify-content:center;align-items:center;width:28px;height:28px;font-size:14px;display:inline-flex}.CUIYUW_dashHeroActionBody{flex-direction:column;flex:1;gap:2px;min-width:0;display:flex}.CUIYUW_dashHeroActionTitle{font-size:14px;font-weight:600}.CUIYUW_dashJourney{flex-direction:column;gap:6px;display:flex}.CUIYUW_dashJourneyBar{background:var(--nf-border);border-radius:999px;height:6px;overflow:hidden}.CUIYUW_dashJourneyFill{background:linear-gradient(90deg, var(--nf-info), var(--nf-accent));border-radius:999px;height:100%;transition:width .4s;display:block}.CUIYUW_dashJourneyStages{grid-template-columns:repeat(6,minmax(0,1fr));gap:4px;display:grid}.CUIYUW_dashStage{color:var(--nf-text-3);text-align:center;white-space:nowrap;flex-direction:column;align-items:center;gap:3px;font-size:11px;display:flex}.CUIYUW_dashStageDot{border:1px solid var(--nf-border-strong,var(--nf-text-3));background:var(--nf-bg-base);border-radius:50%;justify-content:center;align-items:center;width:18px;height:18px;font-size:10px;display:inline-flex}.CUIYUW_dashStageDone{color:var(--nf-text-2)}.CUIYUW_dashStageDone .CUIYUW_dashStageDot{background:var(--nf-success);border-color:var(--nf-success);color:#fff}.CUIYUW_dashStageCurrent{color:var(--nf-accent);font-weight:600}.CUIYUW_dashStageCurrent .CUIYUW_dashStageDot{border-color:var(--nf-accent);color:var(--nf-accent);box-shadow:0 0 0 3px color-mix(in srgb, var(--nf-accent) 18%, transparent)}.CUIYUW_dashFacts{border-top:1px solid var(--nf-border);grid-template-columns:repeat(4,minmax(0,1fr));gap:8px;padding-top:12px;display:grid}.CUIYUW_dashFact{flex-direction:column;gap:2px;min-width:0;display:flex}.CUIYUW_dashFact b{white-space:nowrap;text-overflow:ellipsis;font-size:13px;overflow:hidden}.CUIYUW_dashGrid{grid-template-columns:minmax(0,3fr) minmax(0,2fr);align-items:start;gap:14px;display:grid}.CUIYUW_todoItem{border:1px solid var(--nf-border);border-radius:8px;align-items:center;gap:10px;padding:8px 12px;font-size:12.5px;display:flex}.CUIYUW_todoDanger{border-color:color-mix(in srgb, var(--nf-error) 40%, transparent);background:color-mix(in srgb, var(--nf-error) 8%, transparent)}.CUIYUW_todoWarning{border-color:color-mix(in srgb, var(--nf-warn) 40%, transparent);background:color-mix(in srgb, var(--nf-warn) 8%, transparent)}.CUIYUW_todoInfo{border-color:color-mix(in srgb, var(--nf-info) 40%, transparent);background:color-mix(in srgb, var(--nf-info) 7%, transparent)}.CUIYUW_todoText{flex-direction:column;flex:1;gap:2px;min-width:0;display:flex}.CUIYUW_outlineReadonly{border:1px solid var(--nf-border);background:var(--nf-bg-inset);white-space:pre-wrap;user-select:text;border-radius:12px;max-height:480px;margin:0;padding:12px 14px;font-size:12.5px;line-height:1.8;overflow:auto}.CUIYUW_bookCreateOutline{flex-direction:column;align-items:flex-start;gap:6px;display:flex}.CUIYUW_assistantFloat{z-index:80;border:1px solid var(--nf-border);background:var(--nf-bg-raise);backdrop-filter:blur(24px)saturate(180%);box-shadow:var(--nf-shadow-lg);border-radius:16px;flex-direction:column;min-width:320px;min-height:220px;display:flex;position:absolute;overflow:hidden}.CUIYUW_assistantFloatHeader{cursor:grab;user-select:none;border-bottom:1px solid var(--nf-border);background:var(--nf-bg-inset);flex:none;justify-content:space-between;align-items:center;gap:8px;padding:8px 10px 8px 14px;font-size:13px;font-weight:600;display:flex}.CUIYUW_assistantFloatHeader:active{cursor:grabbing}.CUIYUW_assistantFloatBody{flex:1;min-height:0;padding:10px;display:flex;overflow:hidden}.CUIYUW_assistantFloatBody>*{flex:1;min-width:0}.CUIYUW_assistantResize{cursor:nwse-resize;background:linear-gradient(135deg, transparent 0 55%, var(--nf-border-strong) 55% 62%, transparent 62%) no-repeat 4px 4px / 12px 12px;width:20px;height:20px;position:absolute;bottom:0;right:0}.CUIYUW_coverPreview{border:1px solid var(--nf-border);background:var(--nf-bg-inset);border-radius:12px;flex:none;justify-content:center;align-items:center;width:150px;height:200px;display:flex;overflow:hidden}.CUIYUW_coverPreview img{object-fit:contain;width:100%;height:100%;display:block}.CUIYUW_coverPlaceholder{color:var(--nf-text-3);font-size:12px}.CUIYUW_shelfView{flex-direction:column;flex:1;gap:16px;min-height:0;padding:18px;display:flex;overflow:auto}.CUIYUW_shelfHeader{flex-direction:column;gap:2px;display:flex}.CUIYUW_shelfGrid{grid-template-columns:repeat(auto-fill,minmax(190px,1fr));align-content:start;gap:14px;display:grid}.CUIYUW_bookCard{border:1px solid var(--nf-border);background:var(--nf-bg-raise);backdrop-filter:blur(24px)saturate(180%);box-shadow:var(--nf-shadow);cursor:pointer;border-radius:16px;flex-direction:column;gap:8px;padding:12px;transition:border-color .15s,transform .1s,box-shadow .15s;display:flex}.CUIYUW_bookCard:hover{border-color:var(--nf-accent);box-shadow:var(--nf-shadow-lg);transform:translateY(-2px)}.CUIYUW_bookCardActive{border-color:var(--nf-accent);box-shadow:0 0 0 3px var(--nf-accent-soft)}.CUIYUW_bookCardCover{aspect-ratio:3/4;background:var(--nf-bg-inset);border:1px solid var(--nf-border);border-radius:12px;flex:none;justify-content:center;align-items:center;display:flex;overflow:hidden}.CUIYUW_bookCardCover img{object-fit:contain;width:100%;height:100%;display:block}.CUIYUW_bookCardCoverFallback{background:radial-gradient(400px 200px at 80% -20%, color-mix(in srgb, var(--nf-accent) 25%, transparent), transparent 70%), linear-gradient(155deg, var(--nf-bg-inset), color-mix(in srgb, var(--nf-accent) 10%, var(--nf-bg-inset)));flex-direction:column;justify-content:center;align-items:center;gap:6px;width:100%;height:100%;display:flex}.CUIYUW_bookCardCoverTitle{color:var(--nf-accent);letter-spacing:2px;font-size:22px;font-weight:800}.CUIYUW_bookCardBody{flex-direction:column;gap:5px;min-width:0;display:flex}.CUIYUW_bookCardTitleRow{justify-content:space-between;align-items:center;gap:6px;display:flex}.CUIYUW_bookCardName{text-overflow:ellipsis;white-space:nowrap;font-size:13.5px;font-weight:700;overflow:hidden}.CUIYUW_bookCardBlurb{-webkit-line-clamp:2;-webkit-box-orient:vertical;min-height:34px;display:-webkit-box;overflow:hidden}.CUIYUW_bookCardProgressBar{background:var(--nf-border);border-radius:999px;height:5px;overflow:hidden}.CUIYUW_bookCardProgressFill{background:linear-gradient(90deg, var(--nf-info), var(--nf-accent));border-radius:999px;height:100%;transition:width .3s;display:block}.CUIYUW_bookAddCard{text-align:center;color:var(--nf-text-2);border-style:dashed;justify-content:center;align-items:center;gap:8px;min-height:260px}.CUIYUW_bookAddCard:hover{color:var(--nf-accent)}.CUIYUW_bookAddIcon{color:var(--nf-accent);font-size:34px;line-height:1}.CUIYUW_bookCreateCard{border-color:var(--nf-accent);min-height:260px}.CUIYUW_createBookView{flex-direction:column;flex:1;gap:14px;min-height:0;padding:14px 18px 24px;display:flex;overflow:auto}.CUIYUW_createBookTop{align-items:center;display:flex}.CUIYUW_createBookCard{border:1px solid var(--nf-border);background:var(--nf-bg-raise);backdrop-filter:blur(24px)saturate(180%);width:min(520px,100%);box-shadow:var(--nf-shadow-lg);border-radius:20px;flex-direction:column;align-self:center;gap:12px;padding:26px 28px;display:flex}.CUIYUW_createBookIcon{font-size:34px;line-height:1}.CUIYUW_createBookTitle{letter-spacing:-.3px;margin:0;font-size:22px;font-weight:800}.CUIYUW_progressLineDone{color:var(--nf-success);font-weight:600}.CUIYUW_progressLineError{color:var(--nf-error);font-weight:600}.CUIYUW_meta{color:var(--nf-text-2);opacity:.9;font-size:12px}.CUIYUW_genreDesc{-webkit-line-clamp:2;-webkit-box-orient:vertical;max-width:560px;display:-webkit-box;overflow:hidden}.CUIYUW_fileList{color:var(--nf-text-2);opacity:.9;word-break:break-all;flex-direction:column;gap:3px;font-size:12px;display:flex}.CUIYUW_panelContent::-webkit-scrollbar,.CUIYUW_chatScroll::-webkit-scrollbar,.CUIYUW_chapterPreview::-webkit-scrollbar,.CUIYUW_progress::-webkit-scrollbar,.CUIYUW_toolLive::-webkit-scrollbar{width:8px;height:8px}.CUIYUW_panelContent::-webkit-scrollbar-thumb,.CUIYUW_chatScroll::-webkit-scrollbar-thumb,.CUIYUW_chapterPreview::-webkit-scrollbar-thumb,.CUIYUW_progress::-webkit-scrollbar-thumb,.CUIYUW_toolLive::-webkit-scrollbar-thumb{background:var(--nf-border-strong);border-radius:4px}.CUIYUW_panelContent::-webkit-scrollbar-thumb:hover,.CUIYUW_chatScroll::-webkit-scrollbar-thumb:hover,.CUIYUW_chapterPreview::-webkit-scrollbar-thumb:hover,.CUIYUW_progress::-webkit-scrollbar-thumb:hover,.CUIYUW_toolLive::-webkit-scrollbar-thumb:hover{background:var(--nf-text-3)}.CUIYUW_workflowList{flex-direction:column;gap:0;display:flex}.CUIYUW_workflowRow{align-items:flex-start;gap:12px;padding:8px 4px;display:flex;position:relative}.CUIYUW_workflowRow:before{content:\"\";background:var(--nf-border);width:2px;position:absolute;top:34px;bottom:-8px;left:13px}.CUIYUW_workflowRow:last-child:before{display:none}.CUIYUW_workflowDot{border:2px solid var(--nf-border-strong);background:var(--nf-bg-raise);width:28px;height:28px;color:var(--nf-text-2);z-index:1;border-radius:50%;flex-shrink:0;justify-content:center;align-items:center;font-size:12px;font-weight:700;display:inline-flex}.CUIYUW_workflowDotDone{border-color:var(--nf-success);background:color-mix(in srgb, var(--nf-success) 15%, var(--nf-bg-raise));color:var(--nf-success)}.CUIYUW_workflowDotActive{border-color:var(--nf-accent);background:var(--nf-accent);color:var(--nf-accent-fg);box-shadow:0 0 0 4px var(--nf-accent-soft)}.CUIYUW_workflowBody{flex-direction:column;flex:1;gap:4px;min-width:0;padding-top:2px;display:flex}.CUIYUW_workflowLabel{color:var(--nf-text);font-size:13px;font-weight:600}.CUIYUW_workflowHint{color:var(--nf-text-2);font-size:12px}@keyframes CUIYUW_pulse{0%,to{opacity:1}50%{opacity:.45}}@keyframes CUIYUW_fadeIn{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}.CUIYUW_card{animation:.2s CUIYUW_fadeIn}.CUIYUW_bookshelf{border-bottom:1px solid var(--nf-border);background:var(--nf-bg-raise);flex-wrap:wrap;flex-shrink:0;align-items:center;gap:10px;padding:8px 18px;display:flex}.CUIYUW_bookshelfLabel{color:var(--nf-text-3);letter-spacing:1px;flex-shrink:0;font-size:12px;font-weight:700}.CUIYUW_bookshelfList{flex-wrap:wrap;flex:1;align-items:center;gap:6px;min-width:0;display:flex}.CUIYUW_bookChip{border:1px solid var(--nf-border);background:var(--nf-bg-inset);cursor:pointer;border-radius:999px;align-items:center;gap:6px;max-width:220px;padding:4px 8px 4px 10px;font-size:12px;transition:border-color .15s,background .15s;display:flex}.CUIYUW_bookChip:hover{border-color:var(--nf-border-strong)}.CUIYUW_bookChipActive{border-color:var(--nf-accent);background:var(--nf-accent-soft);color:var(--nf-accent)}.CUIYUW_bookChipName{text-overflow:ellipsis;white-space:nowrap;font-weight:600;overflow:hidden}.CUIYUW_bookChipMeta{opacity:.7;white-space:nowrap;font-size:11px}.CUIYUW_bookChipRemove{color:var(--nf-text-3);cursor:pointer;background:0 0;border:none;border-radius:4px;padding:0 2px;font-size:13px;line-height:1}.CUIYUW_bookChipRemove:hover{color:var(--nf-error)}.CUIYUW_bookAdd{border:1px dashed var(--nf-border-strong);color:var(--nf-text-2);cursor:pointer;background:0 0;border-radius:999px;padding:4px 12px;font-size:12px;transition:border-color .15s,color .15s}.CUIYUW_bookAdd:hover{border-color:var(--nf-accent);color:var(--nf-accent)}.CUIYUW_bookCreateForm{align-items:center;gap:6px;display:flex}.CUIYUW_dropzone{border:2px dashed var(--nf-border-strong);text-align:center;color:var(--nf-text-2);cursor:pointer;border-radius:10px;flex-direction:column;align-items:center;gap:6px;padding:18px 14px;font-size:13px;transition:border-color .15s,background .15s;display:flex}.CUIYUW_dropzone:hover,.CUIYUW_dropzoneActive{border-color:var(--nf-accent);background:var(--nf-accent-soft);color:var(--nf-accent)}.CUIYUW_dropzoneIcon{font-size:22px;line-height:1}";
645
649
  const tagId = "@waterwx/dsh-novel-forge/panel.module.css";
646
650
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
647
651
  const tag = document.createElement("style");
@@ -651,202 +655,202 @@ window.__ModuleLoader__.load({
651
655
  document.head.appendChild(tag);
652
656
  }
653
657
  var panel_module_css_default = {
654
- "workflowRow": "CUIYUW_workflowRow",
655
- "navTab": "CUIYUW_navTab",
656
- "dropzone": "CUIYUW_dropzone",
657
- "dashHeroBook": "CUIYUW_dashHeroBook",
658
- "bookCardActive": "CUIYUW_bookCardActive",
659
- "pulse": "CUIYUW_pulse",
660
- "dashStageDot": "CUIYUW_dashStageDot",
661
- "diffSame": "CUIYUW_diffSame",
658
+ "diffNew": "CUIYUW_diffNew",
659
+ "dashHeroArrow": "CUIYUW_dashHeroArrow",
662
660
  "workflowDotActive": "CUIYUW_workflowDotActive",
663
- "badgeError": "CUIYUW_badgeError",
664
- "bookCard": "CUIYUW_bookCard",
665
- "wsPreviewText": "CUIYUW_wsPreviewText",
666
- "entryIcon": "CUIYUW_entryIcon",
667
- "button": "CUIYUW_button",
668
- "bookAddIcon": "CUIYUW_bookAddIcon",
669
- "buttonDanger": "CUIYUW_buttonDanger",
670
- "dashHeroSparkle": "CUIYUW_dashHeroSparkle",
671
- "todoItem": "CUIYUW_todoItem",
672
- "bookshelf": "CUIYUW_bookshelf",
673
- "panelNav": "CUIYUW_panelNav",
661
+ "bookCreateForm": "CUIYUW_bookCreateForm",
662
+ "progress": "CUIYUW_progress",
663
+ "fileList": "CUIYUW_fileList",
674
664
  "toolStep": "CUIYUW_toolStep",
675
- "progressBar": "CUIYUW_progressBar",
676
- "bigProgressBarFill": "CUIYUW_bigProgressBarFill",
677
- "panelContent": "CUIYUW_panelContent",
678
- "workflowBody": "CUIYUW_workflowBody",
679
- "badgeGenerating": "CUIYUW_badgeGenerating",
680
- "progressLineLive": "CUIYUW_progressLineLive",
681
- "chapterPreview": "CUIYUW_chapterPreview",
682
- "dashHeroArrow": "CUIYUW_dashHeroArrow",
683
- "wsSelected": "CUIYUW_wsSelected",
684
- "diffTagOld": "CUIYUW_diffTagOld",
685
- "genreDesc": "CUIYUW_genreDesc",
686
- "workflowLabel": "CUIYUW_workflowLabel",
687
- "toolStepName": "CUIYUW_toolStepName",
688
- "assistantFloatBody": "CUIYUW_assistantFloatBody",
689
- "createBookCard": "CUIYUW_createBookCard",
690
- "workflowDot": "CUIYUW_workflowDot",
691
- "spaceBetween": "CUIYUW_spaceBetween",
665
+ "workflowHint": "CUIYUW_workflowHint",
666
+ "panelNav": "CUIYUW_panelNav",
667
+ "assistantFloat": "CUIYUW_assistantFloat",
668
+ "diffColumn": "CUIYUW_diffColumn",
669
+ "buttonSmall": "CUIYUW_buttonSmall",
670
+ "progressLineError": "CUIYUW_progressLineError",
671
+ "chapterBeats": "CUIYUW_chapterBeats",
672
+ "bookCardName": "CUIYUW_bookCardName",
673
+ "toolLive": "CUIYUW_toolLive",
674
+ "dropzone": "CUIYUW_dropzone",
692
675
  "toolSteps": "CUIYUW_toolSteps",
693
- "workflowDotDone": "CUIYUW_workflowDotDone",
694
- "navTabLabel": "CUIYUW_navTabLabel",
695
- "input": "CUIYUW_input",
676
+ "chapter": "CUIYUW_chapter",
677
+ "diffList": "CUIYUW_diffList",
678
+ "assistantFloatHeader": "CUIYUW_assistantFloatHeader",
679
+ "cardTitle": "CUIYUW_cardTitle",
680
+ "dashJourneyBar": "CUIYUW_dashJourneyBar",
696
681
  "bookCreateCard": "CUIYUW_bookCreateCard",
697
- "bookChipName": "CUIYUW_bookChipName",
698
- "bookCardBody": "CUIYUW_bookCardBody",
699
- "view": "CUIYUW_view",
700
- "diffChange": "CUIYUW_diffChange",
701
- "chatBubbleUser": "CUIYUW_chatBubbleUser",
702
- "diffAdd": "CUIYUW_diffAdd",
703
- "assetGrid": "CUIYUW_assetGrid",
704
- "chapterTitle": "CUIYUW_chapterTitle",
705
- "assetStatDetail": "CUIYUW_assetStatDetail",
682
+ "assetStatLabel": "CUIYUW_assetStatLabel",
706
683
  "dashHeroAction": "CUIYUW_dashHeroAction",
707
- "dashStageDone": "CUIYUW_dashStageDone",
708
- "bookCardCover": "CUIYUW_bookCardCover",
709
- "shelfHeader": "CUIYUW_shelfHeader",
710
- "buttonPrimary": "CUIYUW_buttonPrimary",
711
- "bigProgressBar": "CUIYUW_bigProgressBar",
712
- "bookAddCard": "CUIYUW_bookAddCard",
684
+ "navGroupLabel": "CUIYUW_navGroupLabel",
685
+ "liveText": "CUIYUW_liveText",
686
+ "busyRow": "CUIYUW_busyRow",
687
+ "badgeRejected": "CUIYUW_badgeRejected",
688
+ "bookCardBlurb": "CUIYUW_bookCardBlurb",
689
+ "createBookView": "CUIYUW_createBookView",
690
+ "dashGrid": "CUIYUW_dashGrid",
691
+ "panelTitle": "CUIYUW_panelTitle",
692
+ "createBookIcon": "CUIYUW_createBookIcon",
693
+ "chapterMain": "CUIYUW_chapterMain",
694
+ "genreDesc": "CUIYUW_genreDesc",
695
+ "dashJourneyFill": "CUIYUW_dashJourneyFill",
696
+ "wsColumns": "CUIYUW_wsColumns",
697
+ "progressBarFill": "CUIYUW_progressBarFill",
698
+ "dashHeroTitle": "CUIYUW_dashHeroTitle",
699
+ "bookCardActive": "CUIYUW_bookCardActive",
700
+ "badgePending": "CUIYUW_badgePending",
701
+ "toolStepActive": "CUIYUW_toolStepActive",
702
+ "toolStepIcon": "CUIYUW_toolStepIcon",
703
+ "navTabBadge": "CUIYUW_navTabBadge",
704
+ "workflowBody": "CUIYUW_workflowBody",
705
+ "bookshelfLabel": "CUIYUW_bookshelfLabel",
706
+ "assistantFloatBody": "CUIYUW_assistantFloatBody",
707
+ "tabBar": "CUIYUW_tabBar",
708
+ "progressLineLive": "CUIYUW_progressLineLive",
709
+ "navTabBadgeDanger": "CUIYUW_navTabBadgeDanger",
710
+ "dashJourney": "CUIYUW_dashJourney",
711
+ "textarea": "CUIYUW_textarea",
712
+ "dashHeroActionTitle": "CUIYUW_dashHeroActionTitle",
713
+ "bookAddIcon": "CUIYUW_bookAddIcon",
714
+ "todoWarning": "CUIYUW_todoWarning",
715
+ "chatBubbleAssistant": "CUIYUW_chatBubbleAssistant",
716
+ "navAboutUpdate": "CUIYUW_navAboutUpdate",
717
+ "wsEditor": "CUIYUW_wsEditor",
718
+ "navGroup": "CUIYUW_navGroup",
719
+ "navGroupSep": "CUIYUW_navGroupSep",
720
+ "buttonDanger": "CUIYUW_buttonDanger",
713
721
  "panelHeader": "CUIYUW_panelHeader",
714
- "headerProgress": "CUIYUW_headerProgress",
715
- "assetStat": "CUIYUW_assetStat",
722
+ "volumeGroup": "CUIYUW_volumeGroup",
723
+ "diffTagOld": "CUIYUW_diffTagOld",
724
+ "wsPreviewText": "CUIYUW_wsPreviewText",
725
+ "assetGrid": "CUIYUW_assetGrid",
726
+ "diffSame": "CUIYUW_diffSame",
716
727
  "assistantStatusBusy": "CUIYUW_assistantStatusBusy",
717
- "wsPreview": "CUIYUW_wsPreview",
718
- "meta": "CUIYUW_meta",
719
- "wsSelectedText": "CUIYUW_wsSelectedText",
720
- "dashJourney": "CUIYUW_dashJourney",
728
+ "bigProgressBarFill": "CUIYUW_bigProgressBarFill",
729
+ "badgeDone": "CUIYUW_badgeDone",
721
730
  "entry": "CUIYUW_entry",
722
- "chatScroll": "CUIYUW_chatScroll",
723
- "dashJourneyBar": "CUIYUW_dashJourneyBar",
724
- "liveText": "CUIYUW_liveText",
731
+ "diffAdd": "CUIYUW_diffAdd",
732
+ "dashStageCurrent": "CUIYUW_dashStageCurrent",
733
+ "meta": "CUIYUW_meta",
734
+ "toolStepName": "CUIYUW_toolStepName",
735
+ "entryLabel": "CUIYUW_entryLabel",
736
+ "dashFacts": "CUIYUW_dashFacts",
737
+ "bookChipMeta": "CUIYUW_bookChipMeta",
738
+ "fieldLabel": "CUIYUW_fieldLabel",
739
+ "chatRole": "CUIYUW_chatRole",
740
+ "diffOld": "CUIYUW_diffOld",
741
+ "card": "CUIYUW_card",
742
+ "dashStage": "CUIYUW_dashStage",
725
743
  "bookCardCoverTitle": "CUIYUW_bookCardCoverTitle",
726
744
  "bookshelfList": "CUIYUW_bookshelfList",
727
- "buttonSmall": "CUIYUW_buttonSmall",
745
+ "badgeWritten": "CUIYUW_badgeWritten",
746
+ "toolStepStatus": "CUIYUW_toolStepStatus",
747
+ "dashFact": "CUIYUW_dashFact",
748
+ "workflowLabel": "CUIYUW_workflowLabel",
749
+ "navTabBadgeDone": "CUIYUW_navTabBadgeDone",
750
+ "badgeGenerating": "CUIYUW_badgeGenerating",
751
+ "workflowDot": "CUIYUW_workflowDot",
752
+ "input": "CUIYUW_input",
753
+ "badge": "CUIYUW_badge",
754
+ "coverPreview": "CUIYUW_coverPreview",
755
+ "workflowRow": "CUIYUW_workflowRow",
756
+ "chapterList": "CUIYUW_chapterList",
757
+ "diffChange": "CUIYUW_diffChange",
758
+ "wsPreview": "CUIYUW_wsPreview",
759
+ "entryIcon": "CUIYUW_entryIcon",
760
+ "progressBar": "CUIYUW_progressBar",
728
761
  "navAboutRow": "CUIYUW_navAboutRow",
729
- "bookChip": "CUIYUW_bookChip",
730
- "toolStepActive": "CUIYUW_toolStepActive",
731
- "diffColumn": "CUIYUW_diffColumn",
732
- "assetStatLabel": "CUIYUW_assetStatLabel",
733
- "bookChipMeta": "CUIYUW_bookChipMeta",
734
- "field": "CUIYUW_field",
762
+ "wsColumn": "CUIYUW_wsColumn",
763
+ "dashHero": "CUIYUW_dashHero",
764
+ "iconButton": "CUIYUW_iconButton",
765
+ "headerProgress": "CUIYUW_headerProgress",
735
766
  "chapterNum": "CUIYUW_chapterNum",
736
- "dashHeroActionBody": "CUIYUW_dashHeroActionBody",
737
- "dashStageCurrent": "CUIYUW_dashStageCurrent",
738
- "todoDanger": "CUIYUW_todoDanger",
739
- "dropzoneActive": "CUIYUW_dropzoneActive",
740
- "toolStepDetail": "CUIYUW_toolStepDetail",
741
- "chapter": "CUIYUW_chapter",
742
- "panelBody": "CUIYUW_panelBody",
743
- "assistantFloat": "CUIYUW_assistantFloat",
744
- "coverPreview": "CUIYUW_coverPreview",
745
- "createBookTitle": "CUIYUW_createBookTitle",
746
- "headerProgressDot": "CUIYUW_headerProgressDot",
747
- "bookAdd": "CUIYUW_bookAdd",
748
- "badge": "CUIYUW_badge",
749
- "dashFact": "CUIYUW_dashFact",
750
- "shelfGrid": "CUIYUW_shelfGrid",
767
+ "coverPlaceholder": "CUIYUW_coverPlaceholder",
768
+ "bookCardCover": "CUIYUW_bookCardCover",
769
+ "assetStatValue": "CUIYUW_assetStatValue",
751
770
  "toolStepError": "CUIYUW_toolStepError",
752
- "wsEditor": "CUIYUW_wsEditor",
753
- "panelTitle": "CUIYUW_panelTitle",
754
- "chatBubbleAssistant": "CUIYUW_chatBubbleAssistant",
755
- "chapterActions": "CUIYUW_chapterActions",
756
- "bookCardProgressBar": "CUIYUW_bookCardProgressBar",
757
- "bookCardBlurb": "CUIYUW_bookCardBlurb",
758
- "navGroupLabel": "CUIYUW_navGroupLabel",
759
- "progressLineDone": "CUIYUW_progressLineDone",
760
- "volumeGroup": "CUIYUW_volumeGroup",
761
- "assistantStatus": "CUIYUW_assistantStatus",
762
- "diffLegend": "CUIYUW_diffLegend",
763
- "diffList": "CUIYUW_diffList",
764
- "diffText": "CUIYUW_diffText",
765
- "textarea": "CUIYUW_textarea",
766
- "workflowHint": "CUIYUW_workflowHint",
767
- "dashJourneyStages": "CUIYUW_dashJourneyStages",
768
- "dashGrid": "CUIYUW_dashGrid",
769
- "progressBarFill": "CUIYUW_progressBarFill",
771
+ "pulse": "CUIYUW_pulse",
772
+ "diffSameBody": "CUIYUW_diffSameBody",
773
+ "todoItem": "CUIYUW_todoItem",
774
+ "wsSelected": "CUIYUW_wsSelected",
775
+ "bookCardCoverFallback": "CUIYUW_bookCardCoverFallback",
770
776
  "navTabIcon": "CUIYUW_navTabIcon",
771
- "navAboutUpdate": "CUIYUW_navAboutUpdate",
772
- "navTabBadgeDanger": "CUIYUW_navTabBadgeDanger",
773
- "card": "CUIYUW_card",
774
- "navSpacer": "CUIYUW_navSpacer",
775
- "busyRow": "CUIYUW_busyRow",
777
+ "badgeError": "CUIYUW_badgeError",
778
+ "dropzoneActive": "CUIYUW_dropzoneActive",
779
+ "todoInfo": "CUIYUW_todoInfo",
780
+ "headerProgressDot": "CUIYUW_headerProgressDot",
781
+ "diffTagNew": "CUIYUW_diffTagNew",
782
+ "createBookCard": "CUIYUW_createBookCard",
783
+ "dashHeroBook": "CUIYUW_dashHeroBook",
776
784
  "navAbout": "CUIYUW_navAbout",
777
- "iconButton": "CUIYUW_iconButton",
778
- "fadeIn": "CUIYUW_fadeIn",
779
- "bookChipRemove": "CUIYUW_bookChipRemove",
780
- "bookCardProgressFill": "CUIYUW_bookCardProgressFill",
781
- "createBookIcon": "CUIYUW_createBookIcon",
782
- "tab": "CUIYUW_tab",
783
- "badgeWritten": "CUIYUW_badgeWritten",
784
- "badgeRejected": "CUIYUW_badgeRejected",
785
- "wsColumn": "CUIYUW_wsColumn",
786
- "todoText": "CUIYUW_todoText",
787
- "bookChipActive": "CUIYUW_bookChipActive",
788
- "navTabBadge": "CUIYUW_navTabBadge",
789
- "navGroupSep": "CUIYUW_navGroupSep",
790
- "dashHeroEyebrow": "CUIYUW_dashHeroEyebrow",
791
- "dashHeroTitle": "CUIYUW_dashHeroTitle",
792
- "chapterList": "CUIYUW_chapterList",
793
- "dashStage": "CUIYUW_dashStage",
794
- "badgePending": "CUIYUW_badgePending",
795
- "assetStatValue": "CUIYUW_assetStatValue",
785
+ "bigProgressBar": "CUIYUW_bigProgressBar",
796
786
  "legendOld": "CUIYUW_legendOld",
797
- "wsColumns": "CUIYUW_wsColumns",
798
- "bookCreateOutline": "CUIYUW_bookCreateOutline",
799
- "entryLabel": "CUIYUW_entryLabel",
800
- "navTabBadgeDone": "CUIYUW_navTabBadgeDone",
801
- "navGroup": "CUIYUW_navGroup",
802
- "chapterBeats": "CUIYUW_chapterBeats",
803
- "todoWarning": "CUIYUW_todoWarning",
787
+ "navSpacer": "CUIYUW_navSpacer",
788
+ "todoDanger": "CUIYUW_todoDanger",
789
+ "todoText": "CUIYUW_todoText",
804
790
  "assistantResize": "CUIYUW_assistantResize",
805
- "bookCardCoverFallback": "CUIYUW_bookCardCoverFallback",
791
+ "shelfGrid": "CUIYUW_shelfGrid",
792
+ "panel": "CUIYUW_panel",
793
+ "onlyChanges": "CUIYUW_onlyChanges",
806
794
  "createBookTop": "CUIYUW_createBookTop",
807
- "bookCardName": "CUIYUW_bookCardName",
808
- "dashJourneyFill": "CUIYUW_dashJourneyFill",
809
- "dashHero": "CUIYUW_dashHero",
810
- "cardTitle": "CUIYUW_cardTitle",
811
- "fieldLabel": "CUIYUW_fieldLabel",
812
- "chapterMain": "CUIYUW_chapterMain",
813
- "legendNew": "CUIYUW_legendNew",
814
- "diffNew": "CUIYUW_diffNew",
815
- "assistantFloatHeader": "CUIYUW_assistantFloatHeader",
816
- "diffSameBody": "CUIYUW_diffSameBody",
817
- "toolStepStatus": "CUIYUW_toolStepStatus",
818
- "bookshelfLabel": "CUIYUW_bookshelfLabel",
819
- "volumeGroupToggle": "CUIYUW_volumeGroupToggle",
820
- "toolLive": "CUIYUW_toolLive",
821
- "bookCreateForm": "CUIYUW_bookCreateForm",
822
- "bookCardTitleRow": "CUIYUW_bookCardTitleRow",
823
- "progressLineError": "CUIYUW_progressLineError",
795
+ "spaceBetween": "CUIYUW_spaceBetween",
796
+ "dashHeroSparkle": "CUIYUW_dashHeroSparkle",
797
+ "navTabBadgeWarn": "CUIYUW_navTabBadgeWarn",
798
+ "navTab": "CUIYUW_navTab",
799
+ "diffDel": "CUIYUW_diffDel",
800
+ "bookChipName": "CUIYUW_bookChipName",
824
801
  "workflowList": "CUIYUW_workflowList",
825
- "dashHeroActionTitle": "CUIYUW_dashHeroActionTitle",
826
- "dropzoneIcon": "CUIYUW_dropzoneIcon",
827
- "todoInfo": "CUIYUW_todoInfo",
828
- "createBookView": "CUIYUW_createBookView",
802
+ "buttonPrimary": "CUIYUW_buttonPrimary",
803
+ "legendNew": "CUIYUW_legendNew",
804
+ "assistantStatus": "CUIYUW_assistantStatus",
805
+ "outlineReadonly": "CUIYUW_outlineReadonly",
829
806
  "reviewBox": "CUIYUW_reviewBox",
830
- "tabBar": "CUIYUW_tabBar",
807
+ "diffText": "CUIYUW_diffText",
808
+ "dashStageDone": "CUIYUW_dashStageDone",
809
+ "tab": "CUIYUW_tab",
810
+ "bookAdd": "CUIYUW_bookAdd",
831
811
  "row": "CUIYUW_row",
832
- "outlineReadonly": "CUIYUW_outlineReadonly",
833
- "fileList": "CUIYUW_fileList",
834
- "panel": "CUIYUW_panel",
812
+ "button": "CUIYUW_button",
813
+ "dashStageDot": "CUIYUW_dashStageDot",
814
+ "assetStatDetail": "CUIYUW_assetStatDetail",
815
+ "chatScroll": "CUIYUW_chatScroll",
816
+ "bookChip": "CUIYUW_bookChip",
817
+ "wsSelectedText": "CUIYUW_wsSelectedText",
818
+ "field": "CUIYUW_field",
819
+ "bookAddCard": "CUIYUW_bookAddCard",
820
+ "bookshelf": "CUIYUW_bookshelf",
821
+ "shelfView": "CUIYUW_shelfView",
822
+ "progressLine": "CUIYUW_progressLine",
823
+ "assetStat": "CUIYUW_assetStat",
824
+ "createBookTitle": "CUIYUW_createBookTitle",
825
+ "bookCreateOutline": "CUIYUW_bookCreateOutline",
826
+ "bookCardProgressBar": "CUIYUW_bookCardProgressBar",
827
+ "chatBubbleUser": "CUIYUW_chatBubbleUser",
828
+ "diffLegend": "CUIYUW_diffLegend",
829
+ "view": "CUIYUW_view",
835
830
  "panelNavCollapsed": "CUIYUW_panelNavCollapsed",
836
- "dashFacts": "CUIYUW_dashFacts",
837
- "coverPlaceholder": "CUIYUW_coverPlaceholder",
838
- "badgeDone": "CUIYUW_badgeDone",
839
- "onlyChanges": "CUIYUW_onlyChanges",
831
+ "chapterTitle": "CUIYUW_chapterTitle",
832
+ "chapterPreview": "CUIYUW_chapterPreview",
833
+ "panelBody": "CUIYUW_panelBody",
834
+ "volumeGroupToggle": "CUIYUW_volumeGroupToggle",
835
+ "toolStepDetail": "CUIYUW_toolStepDetail",
836
+ "bookCard": "CUIYUW_bookCard",
837
+ "fadeIn": "CUIYUW_fadeIn",
838
+ "bookChipActive": "CUIYUW_bookChipActive",
839
+ "bookCardBody": "CUIYUW_bookCardBody",
840
+ "dropzoneIcon": "CUIYUW_dropzoneIcon",
841
+ "dashHeroActionBody": "CUIYUW_dashHeroActionBody",
842
+ "shelfHeader": "CUIYUW_shelfHeader",
843
+ "bookChipRemove": "CUIYUW_bookChipRemove",
844
+ "panelContent": "CUIYUW_panelContent",
845
+ "bookCardTitleRow": "CUIYUW_bookCardTitleRow",
846
+ "navTabLabel": "CUIYUW_navTabLabel",
847
+ "chapterActions": "CUIYUW_chapterActions",
848
+ "dashHeroEyebrow": "CUIYUW_dashHeroEyebrow",
849
+ "dashJourneyStages": "CUIYUW_dashJourneyStages",
850
+ "bookCardProgressFill": "CUIYUW_bookCardProgressFill",
840
851
  "volumeGroupHeader": "CUIYUW_volumeGroupHeader",
841
- "chatRole": "CUIYUW_chatRole",
842
- "progressLine": "CUIYUW_progressLine",
843
- "progress": "CUIYUW_progress",
844
- "toolStepIcon": "CUIYUW_toolStepIcon",
845
- "diffOld": "CUIYUW_diffOld",
846
- "diffTagNew": "CUIYUW_diffTagNew",
847
- "shelfView": "CUIYUW_shelfView",
848
- "diffDel": "CUIYUW_diffDel",
849
- "navTabBadgeWarn": "CUIYUW_navTabBadgeWarn"
852
+ "progressLineDone": "CUIYUW_progressLineDone",
853
+ "workflowDotDone": "CUIYUW_workflowDotDone"
850
854
  };
851
855
  //#endregion
852
856
  //#region src/client/panel/AssistantTab.tsx
@@ -3347,7 +3351,7 @@ window.__ModuleLoader__.load({
3347
3351
  label: tt("tab.settings"),
3348
3352
  icon: "⚙️"
3349
3353
  };
3350
- const PLUGIN_VERSION = "1.1.1";
3354
+ const PLUGIN_VERSION = "1.1.2";
3351
3355
  /** GitHub 仓库地址(关于区块点击跳转)。 */
3352
3356
  const REPO_URL = "https://github.com/watersxya/dsh-novel-forge";
3353
3357
  /** Whether any chapter is being generated right now. */
@@ -3491,7 +3495,7 @@ window.__ModuleLoader__.load({
3491
3495
  });
3492
3496
  }
3493
3497
  /** The diff list of a draft-vs-original comparison (scrollable). */
3494
- function DiffList({ original, draft }) {
3498
+ function DiffList({ original, draft, fontSize }) {
3495
3499
  const rows = (0, react.useMemo)(() => paragraphDiff(original, draft), [original, draft]);
3496
3500
  const changed = rows.filter((r) => r.kind === "change").length;
3497
3501
  const added = rows.filter((r) => r.kind === "add").length;
@@ -3537,6 +3541,7 @@ window.__ModuleLoader__.load({
3537
3541
  ]
3538
3542
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3539
3543
  className: panel_module_css_default.diffList,
3544
+ style: fontSize !== void 0 ? { fontSize } : void 0,
3540
3545
  children: shown.map((row, idx) => {
3541
3546
  if (row.kind === "same") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
3542
3547
  className: panel_module_css_default.diffSame,
@@ -3635,6 +3640,24 @@ window.__ModuleLoader__.load({
3635
3640
  const wsEditorRef = (0, react.useRef)(null);
3636
3641
  /** 工作区:手动编辑后的 AI 审查结果(不落盘)。 */
3637
3642
  const [wsCheckReport, setWsCheckReport] = (0, react.useState)(null);
3643
+ /** 手动审查结果中作者勾选要修复的问题(issue 下标)。 */
3644
+ const [wsChecked, setWsChecked] = (0, react.useState)([]);
3645
+ /** 编辑页字号(localStorage 记忆,仅影响显示)。 */
3646
+ const [editorFontSize, setEditorFontSize] = (0, react.useState)(() => {
3647
+ try {
3648
+ const v = Number(window.localStorage.getItem("dsh-novel-forge.editor.fontSize"));
3649
+ return v >= 12 && v <= 24 ? v : 14;
3650
+ } catch {
3651
+ return 14;
3652
+ }
3653
+ });
3654
+ const changeEditorFontSize = (next) => {
3655
+ const v = Math.min(24, Math.max(12, next));
3656
+ setEditorFontSize(v);
3657
+ try {
3658
+ window.localStorage.setItem("dsh-novel-forge.editor.fontSize", String(v));
3659
+ } catch {}
3660
+ };
3638
3661
  /** 有未采纳草稿的章节号(refresh 后检测到遗留草稿时提示)。 */
3639
3662
  const [draftNo, setDraftNo] = (0, react.useState)(null);
3640
3663
  /** 大纲页「更新大纲」编辑区是否展开。 */
@@ -4054,6 +4077,15 @@ window.__ModuleLoader__.load({
4054
4077
  try {
4055
4078
  const result = await api.chapterCheck(workspace.no, workspace.original);
4056
4079
  setWsCheckReport(result.report);
4080
+ const highIdx = result.report.issues.map((it, i) => ({
4081
+ it,
4082
+ i
4083
+ })).filter((x) => x.it.severity === "high").map((x) => x.i);
4084
+ const mediumIdx = result.report.issues.map((it, i) => ({
4085
+ it,
4086
+ i
4087
+ })).filter((x) => x.it.severity === "medium").map((x) => x.i);
4088
+ setWsChecked(highIdx.length > 0 ? highIdx : mediumIdx);
4057
4089
  pushProgress(`审查完成:${result.report.score} 分 — ${result.report.verdict}`, result.report.passed ? "done" : "error");
4058
4090
  } catch (err) {
4059
4091
  setError(err.message);
@@ -4078,6 +4110,7 @@ window.__ModuleLoader__.load({
4078
4110
  setWorkspace(null);
4079
4111
  setDraftNo(null);
4080
4112
  setWsCheckReport(null);
4113
+ setWsChecked([]);
4081
4114
  if (report !== void 0) pushProgress(`已保存并审稿:${report.score} 分 — ${report.verdict}(${report.passed ? "通过" : "未通过"})`, report.passed ? "done" : "error");
4082
4115
  else pushProgress(`已保存第 ${workspace.no} 章编辑(${result.chars} 字,原稿已备份 .bak)`, "done");
4083
4116
  } catch (err) {
@@ -4225,7 +4258,9 @@ window.__ModuleLoader__.load({
4225
4258
  draft: chapter.pendingDraft !== void 0 && chapter.pendingDraft !== "" ? chapter.pendingDraft : null
4226
4259
  });
4227
4260
  setWsSelected("");
4228
- setWsShowDiff(false);
4261
+ setWsShowDiff(true);
4262
+ setWsCheckReport(null);
4263
+ setWsChecked([]);
4229
4264
  } catch {}
4230
4265
  }, [api]);
4231
4266
  /** 捕获工作区原文 textarea 中选中的文字(局部修订目标)。 */
@@ -4257,14 +4292,15 @@ window.__ModuleLoader__.load({
4257
4292
  }
4258
4293
  };
4259
4294
  /** 工作区:按指令修订(whole=true 整章,false 仅修订选中片段)。 */
4260
- const handleWsRewrite = async (whole) => {
4295
+ const handleWsRewrite = async (whole, overrideInstruction) => {
4261
4296
  if (workspace === null) return;
4262
4297
  const target = whole ? "" : wsSelected;
4298
+ const instruction = overrideInstruction ?? workspace.instruction;
4263
4299
  setBusy(true);
4264
4300
  setBusyLabel(`${tt("plan.rewrite")} 第${workspace.no}章`);
4265
4301
  setError("");
4266
4302
  try {
4267
- await api.rewrite(workspace.no, workspace.instruction, target, (frame) => {
4303
+ await api.rewrite(workspace.no, instruction, target, (frame) => {
4268
4304
  applyJobFrame(frame, (n) => tt("progress.rewriting", { no: n }));
4269
4305
  });
4270
4306
  } catch (err) {
@@ -4276,6 +4312,18 @@ window.__ModuleLoader__.load({
4276
4312
  await refresh(false);
4277
4313
  }
4278
4314
  };
4315
+ /** 工作区:按审查报告中勾选的问题一键修订(预填指令 + 立即整章修订到草稿)。 */
4316
+ const handleWsReviseByReport = async () => {
4317
+ if (workspace === null || wsCheckReport === null) return;
4318
+ const picked = wsChecked.map((i) => wsCheckReport.issues[i]).filter((it) => it !== void 0).slice(0, 5);
4319
+ if (picked.length === 0) return;
4320
+ const instruction = "按审稿意见修订(优先处理):\n" + picked.map((i) => `[${i.severity}] ${i.item} → ${i.suggestion}`).join("\n");
4321
+ setWorkspace({
4322
+ ...workspace,
4323
+ instruction
4324
+ });
4325
+ await handleWsRewrite(true, instruction);
4326
+ };
4279
4327
  /** 采纳草稿:覆盖正文文件并刷新。 */
4280
4328
  const handleDraftApply = async (no) => {
4281
4329
  setBusy(true);
@@ -5125,25 +5173,79 @@ window.__ModuleLoader__.load({
5125
5173
  style: { borderColor: "var(--nf-accent)" },
5126
5174
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5127
5175
  className: panel_module_css_default.busyRow,
5128
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5129
- className: panel_module_css_default.cardTitle,
5130
- children: [
5131
- "第 ",
5132
- workspace.no,
5133
- " 章《",
5134
- workspace.title,
5135
- "》润色/修订"
5136
- ]
5137
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5138
- type: "button",
5139
- className: panel_module_css_default.iconButton,
5140
- title: "关闭工作区",
5141
- "aria-label": "关闭工作区",
5142
- onClick: () => {
5143
- setWorkspace(null);
5144
- },
5145
- children: "×"
5146
- })]
5176
+ style: {
5177
+ flexWrap: "wrap",
5178
+ gap: 8
5179
+ },
5180
+ children: [
5181
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5182
+ type: "button",
5183
+ className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
5184
+ onClick: () => {
5185
+ setWorkspace(null);
5186
+ },
5187
+ title: "返回章节列表(草稿不丢失)",
5188
+ children: "← 返回"
5189
+ }),
5190
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5191
+ className: panel_module_css_default.cardTitle,
5192
+ children: [
5193
+ "第 ",
5194
+ workspace.no,
5195
+ " 章《",
5196
+ workspace.title,
5197
+ "》"
5198
+ ]
5199
+ }),
5200
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5201
+ className: panel_module_css_default.meta,
5202
+ children: [workspace.original.length, " 字"]
5203
+ }),
5204
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5205
+ style: {
5206
+ display: "flex",
5207
+ gap: 4,
5208
+ alignItems: "center",
5209
+ marginLeft: "auto"
5210
+ },
5211
+ children: [
5212
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5213
+ type: "button",
5214
+ className: panel_module_css_default.iconButton,
5215
+ title: "减小字号",
5216
+ "aria-label": "减小字号",
5217
+ onClick: () => {
5218
+ changeEditorFontSize(editorFontSize - 1);
5219
+ },
5220
+ children: "A−"
5221
+ }),
5222
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5223
+ className: panel_module_css_default.meta,
5224
+ children: [editorFontSize, "px"]
5225
+ }),
5226
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5227
+ type: "button",
5228
+ className: panel_module_css_default.iconButton,
5229
+ title: "增大字号",
5230
+ "aria-label": "增大字号",
5231
+ onClick: () => {
5232
+ changeEditorFontSize(editorFontSize + 1);
5233
+ },
5234
+ children: "A+"
5235
+ }),
5236
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5237
+ type: "button",
5238
+ className: panel_module_css_default.iconButton,
5239
+ title: "关闭工作区",
5240
+ "aria-label": "关闭工作区",
5241
+ onClick: () => {
5242
+ setWorkspace(null);
5243
+ },
5244
+ children: "×"
5245
+ })
5246
+ ]
5247
+ })
5248
+ ]
5147
5249
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5148
5250
  className: panel_module_css_default.wsColumns,
5149
5251
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -5158,6 +5260,7 @@ window.__ModuleLoader__.load({
5158
5260
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
5159
5261
  ref: wsEditorRef,
5160
5262
  className: `${panel_module_css_default.textarea} ${panel_module_css_default.wsEditor}`,
5263
+ style: { fontSize: editorFontSize },
5161
5264
  value: workspace.original,
5162
5265
  onChange: (e) => {
5163
5266
  setWorkspace({
@@ -5207,7 +5310,7 @@ window.__ModuleLoader__.load({
5207
5310
  className: panel_module_css_default.row,
5208
5311
  style: { flexWrap: "wrap" },
5209
5312
  children: [
5210
- workspace.instruction.startsWith("按审稿意见修订") && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5313
+ workspace.instruction.includes("按审稿意见修订") && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5211
5314
  type: "button",
5212
5315
  className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall} ${panel_module_css_default.buttonPrimary}`,
5213
5316
  disabled: busy,
@@ -5291,14 +5394,29 @@ window.__ModuleLoader__.load({
5291
5394
  style: {
5292
5395
  margin: 0,
5293
5396
  paddingLeft: 16,
5294
- fontSize: 12,
5295
5397
  display: "flex",
5296
5398
  flexDirection: "column",
5297
- gap: 3
5399
+ gap: 3,
5400
+ fontSize: editorFontSize - 1,
5401
+ maxHeight: "45vh",
5402
+ overflowY: "auto"
5298
5403
  },
5299
5404
  children: wsCheckReport.issues.map((issue, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
5300
- style: { color: severityColor(issue.severity) },
5301
- children: [
5405
+ style: {
5406
+ color: severityColor(issue.severity),
5407
+ display: "flex",
5408
+ gap: 6,
5409
+ alignItems: "flex-start"
5410
+ },
5411
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
5412
+ type: "checkbox",
5413
+ style: { marginTop: 1 },
5414
+ checked: wsChecked.includes(i),
5415
+ onChange: (e) => {
5416
+ setWsChecked((prev) => e.target.checked ? [...prev, i] : prev.filter((x) => x !== i));
5417
+ },
5418
+ title: "勾选后可由「修复所选问题」一起修订"
5419
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
5302
5420
  "[",
5303
5421
  issue.severity,
5304
5422
  "] ",
@@ -5307,12 +5425,29 @@ window.__ModuleLoader__.load({
5307
5425
  style: { color: "var(--nf-text-2)" },
5308
5426
  children: [" → ", issue.suggestion]
5309
5427
  })
5310
- ]
5428
+ ] })]
5311
5429
  }, i))
5312
5430
  }),
5313
5431
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5314
5432
  className: panel_module_css_default.meta,
5315
- children: "审查只读不落盘;改完点「💾 保存为正文」才写入文件(原稿自动备份 .bak)。"
5433
+ children: "审查只读不落盘;勾选要修的问题,点下方按钮一键修订;改完点「💾 保存为正文」才写入文件(原稿自动备份 .bak)。"
5434
+ }),
5435
+ wsCheckReport.issues.length > 0 && wsChecked.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5436
+ style: { marginTop: 8 },
5437
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
5438
+ type: "button",
5439
+ className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall} ${panel_module_css_default.buttonPrimary}`,
5440
+ disabled: busy,
5441
+ onClick: () => {
5442
+ handleWsReviseByReport();
5443
+ },
5444
+ title: "自动按勾选的问题修订整章,产出草稿预览(不落盘),对比后应用或放弃",
5445
+ children: [
5446
+ "🔧 修复所选问题(",
5447
+ wsChecked.length,
5448
+ ")"
5449
+ ]
5450
+ })
5316
5451
  })
5317
5452
  ]
5318
5453
  }),
@@ -5363,9 +5498,11 @@ window.__ModuleLoader__.load({
5363
5498
  })]
5364
5499
  }), wsShowDiff ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DiffList, {
5365
5500
  original: workspace.original,
5366
- draft: workspace.draft
5501
+ draft: workspace.draft,
5502
+ fontSize: editorFontSize
5367
5503
  }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
5368
5504
  className: panel_module_css_default.wsPreviewText,
5505
+ style: { fontSize: editorFontSize },
5369
5506
  children: workspace.draft
5370
5507
  })]
5371
5508
  })
@@ -5373,1760 +5510,1800 @@ window.__ModuleLoader__.load({
5373
5510
  })]
5374
5511
  })]
5375
5512
  }),
5376
- activeTab === "workflow" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
5377
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5378
- className: panel_module_css_default.dashHero,
5379
- children: [
5380
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5381
- className: panel_module_css_default.dashHeroEyebrow,
5382
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5383
- className: panel_module_css_default.dashHeroSparkle,
5384
- children: "✨"
5385
- }), nextAction?.eyebrow ?? "开始"]
5386
- }),
5387
- project !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5388
- className: panel_module_css_default.dashHeroTitle,
5389
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5390
- className: panel_module_css_default.meta,
5391
- children: "正在创作"
5392
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("h3", {
5393
- className: panel_module_css_default.dashHeroBook,
5513
+ workspace === null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
5514
+ activeTab === "workflow" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
5515
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5516
+ className: panel_module_css_default.dashHero,
5517
+ children: [
5518
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5519
+ className: panel_module_css_default.dashHeroEyebrow,
5520
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5521
+ className: panel_module_css_default.dashHeroSparkle,
5522
+ children: "✨"
5523
+ }), nextAction?.eyebrow ?? "开始"]
5524
+ }),
5525
+ project !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5526
+ className: panel_module_css_default.dashHeroTitle,
5527
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5528
+ className: panel_module_css_default.meta,
5529
+ children: "正在创作"
5530
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("h3", {
5531
+ className: panel_module_css_default.dashHeroBook,
5532
+ children: [
5533
+ "《",
5534
+ project.bookName,
5535
+ "》"
5536
+ ]
5537
+ })]
5538
+ }),
5539
+ nextAction !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5540
+ className: panel_module_css_default.dashHeroAction,
5394
5541
  children: [
5395
- "《",
5396
- project.bookName,
5397
- "》"
5542
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5543
+ className: panel_module_css_default.dashHeroArrow,
5544
+ children: "→"
5545
+ }),
5546
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5547
+ className: panel_module_css_default.dashHeroActionBody,
5548
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5549
+ className: panel_module_css_default.dashHeroActionTitle,
5550
+ children: nextAction.title
5551
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5552
+ className: panel_module_css_default.meta,
5553
+ children: nextAction.reason
5554
+ })]
5555
+ }),
5556
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5557
+ type: "button",
5558
+ className: `${panel_module_css_default.button} ${panel_module_css_default.buttonPrimary}`,
5559
+ disabled: busy,
5560
+ onClick: () => {
5561
+ nextAction.onClick();
5562
+ },
5563
+ children: nextAction.actionLabel
5564
+ })
5398
5565
  ]
5399
- })]
5400
- }),
5401
- nextAction !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5402
- className: panel_module_css_default.dashHeroAction,
5403
- children: [
5404
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5405
- className: panel_module_css_default.dashHeroArrow,
5406
- children: "→"
5407
- }),
5408
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5409
- className: panel_module_css_default.dashHeroActionBody,
5410
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5411
- className: panel_module_css_default.dashHeroActionTitle,
5412
- children: nextAction.title
5413
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5414
- className: panel_module_css_default.meta,
5415
- children: nextAction.reason
5416
- })]
5417
- }),
5418
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5419
- type: "button",
5420
- className: `${panel_module_css_default.button} ${panel_module_css_default.buttonPrimary}`,
5421
- disabled: busy,
5422
- onClick: () => {
5423
- nextAction.onClick();
5424
- },
5425
- children: nextAction.actionLabel
5426
- })
5427
- ]
5428
- }),
5429
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5430
- className: panel_module_css_default.dashJourney,
5431
- children: [
5432
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5433
- className: panel_module_css_default.busyRow,
5434
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5435
- className: panel_module_css_default.meta,
5436
- style: { fontWeight: 600 },
5437
- children: "创作旅程"
5438
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5439
- className: panel_module_css_default.meta,
5440
- children: [
5441
- journeyPercent,
5442
- "% · 已完成 ",
5443
- journeyDoneCount,
5444
- "/",
5445
- journeyStages.length,
5446
- " 步"
5447
- ]
5448
- })]
5449
- }),
5450
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5451
- className: panel_module_css_default.dashJourneyBar,
5452
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5453
- className: panel_module_css_default.dashJourneyFill,
5454
- style: { width: `${journeyPercent}%` }
5566
+ }),
5567
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5568
+ className: panel_module_css_default.dashJourney,
5569
+ children: [
5570
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5571
+ className: panel_module_css_default.busyRow,
5572
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5573
+ className: panel_module_css_default.meta,
5574
+ style: { fontWeight: 600 },
5575
+ children: "创作旅程"
5576
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5577
+ className: panel_module_css_default.meta,
5578
+ children: [
5579
+ journeyPercent,
5580
+ "% · 已完成 ",
5581
+ journeyDoneCount,
5582
+ "/",
5583
+ journeyStages.length,
5584
+ " 步"
5585
+ ]
5586
+ })]
5587
+ }),
5588
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5589
+ className: panel_module_css_default.dashJourneyBar,
5590
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5591
+ className: panel_module_css_default.dashJourneyFill,
5592
+ style: { width: `${journeyPercent}%` }
5593
+ })
5594
+ }),
5595
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5596
+ className: panel_module_css_default.dashJourneyStages,
5597
+ children: journeyStages.map((stage) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5598
+ className: `${panel_module_css_default.dashStage} ${stage.done ? panel_module_css_default.dashStageDone : stage.id === currentStageId ? panel_module_css_default.dashStageCurrent : ""}`,
5599
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5600
+ className: panel_module_css_default.dashStageDot,
5601
+ children: stage.done ? "✓" : stage.id === currentStageId ? "●" : "○"
5602
+ }), stage.label]
5603
+ }, stage.id))
5455
5604
  })
5456
- }),
5457
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5458
- className: panel_module_css_default.dashJourneyStages,
5459
- children: journeyStages.map((stage) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5460
- className: `${panel_module_css_default.dashStage} ${stage.done ? panel_module_css_default.dashStageDone : stage.id === currentStageId ? panel_module_css_default.dashStageCurrent : ""}`,
5605
+ ]
5606
+ }),
5607
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5608
+ className: panel_module_css_default.dashFacts,
5609
+ children: [
5610
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5611
+ className: panel_module_css_default.dashFact,
5461
5612
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5462
- className: panel_module_css_default.dashStageDot,
5463
- children: stage.done ? "✓" : stage.id === currentStageId ? "●" : "○"
5464
- }), stage.label]
5465
- }, stage.id))
5466
- })
5467
- ]
5468
- }),
5469
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5470
- className: panel_module_css_default.dashFacts,
5471
- children: [
5472
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5473
- className: panel_module_css_default.dashFact,
5474
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5475
- className: panel_module_css_default.meta,
5476
- children: "已沉淀章节"
5477
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("b", { children: [doneCount, " 章"] })]
5478
- }),
5479
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5480
- className: panel_module_css_default.dashFact,
5481
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5482
- className: panel_module_css_default.meta,
5483
- children: "累计字数"
5484
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("b", { children: [totalChars, " 字"] })]
5485
- }),
5486
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5487
- className: panel_module_css_default.dashFact,
5488
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5489
- className: panel_module_css_default.meta,
5490
- children: "当前卷"
5491
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", { children: currentVolumeName })]
5492
- }),
5493
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5494
- className: panel_module_css_default.dashFact,
5495
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5496
- className: panel_module_css_default.meta,
5497
- children: "最近创作"
5498
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", { children: lastUpdated })]
5499
- })
5500
- ]
5501
- })
5502
- ]
5503
- }),
5504
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5505
- className: panel_module_css_default.assetGrid,
5506
- children: [
5507
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5508
- className: panel_module_css_default.assetStat,
5509
- children: [
5510
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5511
- className: panel_module_css_default.assetStatLabel,
5512
- children: "已通过审稿"
5513
- }),
5514
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5515
- className: panel_module_css_default.assetStatValue,
5516
- style: { color: approvedCount > 0 ? "var(--nf-success)" : void 0 },
5517
- children: approvedCount
5518
- }),
5519
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5520
- className: panel_module_css_default.assetStatDetail,
5521
- children: "章节已 approved"
5522
- })
5523
- ]
5524
- }),
5525
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5526
- className: panel_module_css_default.assetStat,
5527
- children: [
5528
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5529
- className: panel_module_css_default.assetStatLabel,
5530
- children: "待生成"
5531
- }),
5532
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5533
- className: panel_module_css_default.assetStatValue,
5534
- style: { color: pendingCount > 0 ? "var(--nf-warn)" : void 0 },
5535
- children: pendingCount
5536
- }),
5537
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5538
- className: panel_module_css_default.assetStatDetail,
5539
- children: "pending + error"
5540
- })
5541
- ]
5542
- }),
5543
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5544
- className: panel_module_css_default.assetStat,
5545
- children: [
5546
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5547
- className: panel_module_css_default.assetStatLabel,
5548
- children: "待审稿"
5549
- }),
5550
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5551
- className: panel_module_css_default.assetStatValue,
5552
- style: { color: reviewPendingCount > 0 ? "var(--nf-info)" : void 0 },
5553
- children: reviewPendingCount
5554
- }),
5555
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5556
- className: panel_module_css_default.assetStatDetail,
5557
- children: "written + rejected"
5558
- })
5559
- ]
5560
- }),
5561
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5562
- className: panel_module_css_default.assetStat,
5563
- children: [
5564
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5565
- className: panel_module_css_default.assetStatLabel,
5566
- children: "总字数"
5567
- }),
5568
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5569
- className: panel_module_css_default.assetStatValue,
5570
- children: totalChars
5571
- }),
5572
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5573
- className: panel_module_css_default.assetStatDetail,
5574
- children: "已生成正文累计"
5575
- })
5576
- ]
5577
- })
5578
- ]
5579
- }),
5580
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5581
- className: panel_module_css_default.dashGrid,
5582
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5583
- className: panel_module_css_default.card,
5584
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5585
- className: panel_module_css_default.cardTitle,
5586
- children: "待办队列"
5587
- }), todos.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5588
- className: panel_module_css_default.meta,
5589
- children: "🎉 暂无待办,一切顺畅"
5590
- }) : todos.map((todo, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5591
- className: `${panel_module_css_default.todoItem} ${todo.tone === "danger" ? panel_module_css_default.todoDanger : todo.tone === "warning" ? panel_module_css_default.todoWarning : panel_module_css_default.todoInfo}`,
5592
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5593
- className: panel_module_css_default.todoText,
5594
- children: [todo.title, todo.description !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5595
- className: panel_module_css_default.meta,
5596
- children: [" — ", todo.description]
5597
- })]
5598
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5599
- type: "button",
5600
- className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
5601
- disabled: busy,
5602
- onClick: () => {
5603
- todo.onClick();
5604
- },
5605
- children: todo.actionLabel
5606
- })]
5607
- }, i))]
5608
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5609
- className: panel_module_css_default.card,
5610
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5611
- className: panel_module_css_default.row,
5612
- style: { justifyContent: "space-between" },
5613
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5614
- className: panel_module_css_default.cardTitle,
5615
- children: "资产健康"
5616
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5617
- type: "button",
5618
- className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
5619
- disabled: busy || doneCount === 0,
5620
- onClick: () => {
5621
- handleAudit();
5622
- },
5623
- title: "LLM 扫描全本已生成章节,检查人名/境界/资源/时间线矛盾",
5624
- children: "🔍 全书质检"
5625
- })]
5626
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5627
- className: panel_module_css_default.assetGrid,
5628
- children: [
5629
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5630
- className: panel_module_css_default.assetStat,
5631
- children: [
5632
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5633
- className: panel_module_css_default.assetStatLabel,
5634
- children: "道藏"
5635
- }),
5636
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5637
- className: panel_module_css_default.assetStatValue,
5638
- style: { color: bible !== void 0 ? "var(--nf-success)" : "var(--nf-text-3)" },
5639
- children: bible !== void 0 ? `✓ ${bible.worldRules.length} 条规则` : "未生成"
5640
- }),
5641
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5642
- className: panel_module_css_default.assetStatDetail,
5643
- children: bible !== void 0 ? `${bible.characters.length} 人物 · ${bible.redLines.length} 红线` : "提炼人设 / 世界观 / 金手指"
5644
- })
5645
- ]
5646
- }),
5647
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5648
- className: panel_module_css_default.assetStat,
5649
- children: [
5650
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5651
- className: panel_module_css_default.assetStatLabel,
5652
- children: "卷计划"
5653
- }),
5654
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5655
- className: panel_module_css_default.assetStatValue,
5656
- style: { color: volumes !== void 0 ? "var(--nf-success)" : "var(--nf-text-3)" },
5657
- children: volumes !== void 0 ? `${volumes.length} 卷` : "未生成"
5658
- }),
5659
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5660
- className: panel_module_css_default.assetStatDetail,
5661
- title: volumes?.map((v) => v.title).join(" / "),
5662
- children: volumes !== void 0 ? volumes.map((v) => v.title).join(" / ") : "按剧情弧线划分全书"
5663
- })
5664
- ]
5665
- }),
5666
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5667
- className: panel_module_css_default.assetStat,
5668
- children: [
5669
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5670
- className: panel_module_css_default.assetStatLabel,
5671
- children: "写作资产"
5672
- }),
5673
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5674
- className: panel_module_css_default.assetStatValue,
5675
- style: { color: assetCount > 0 ? "var(--nf-success)" : "var(--nf-text-3)" },
5676
- children: [assetCount, " 项"]
5677
- }),
5678
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5679
- className: panel_module_css_default.assetStatDetail,
5680
- title: assetSummary,
5681
- children: assetSummary
5682
- })
5683
- ]
5684
- }),
5685
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5686
- className: panel_module_css_default.assetStat,
5687
- children: [
5688
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5689
- className: panel_module_css_default.assetStatLabel,
5690
- children: "伏笔"
5691
- }),
5692
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5693
- className: panel_module_css_default.assetStatValue,
5694
- children: [foreshadows.length, " 条"]
5695
- }),
5696
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5697
- className: panel_module_css_default.assetStatDetail,
5698
- children: [
5699
- foreshadows.filter((f) => f.status === "planned").length,
5700
- " 待埋 · ",
5701
- foreshadows.filter((f) => f.status === "resolved").length,
5702
- " 已回收"
5703
- ]
5704
- })
5705
- ]
5706
- })
5707
- ]
5708
- })]
5709
- })]
5710
- }),
5711
- auditIssues !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5712
- className: panel_module_css_default.card,
5713
- style: { borderColor: auditIssues.length > 0 ? "var(--nf-error)" : "var(--nf-success)" },
5714
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5715
- className: panel_module_css_default.row,
5716
- style: { justifyContent: "space-between" },
5717
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5718
- className: panel_module_css_default.cardTitle,
5719
- children: ["🔍 全书质检", auditIssues.length === 0 ? ":未发现矛盾 🎉" : `:${auditIssues.length} 处疑似矛盾`]
5720
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5721
- type: "button",
5722
- className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
5723
- onClick: () => {
5724
- setAuditIssues(null);
5725
- },
5726
- children: "收起"
5727
- })]
5728
- }), auditIssues.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5729
- style: {
5730
- display: "flex",
5731
- flexDirection: "column",
5732
- gap: 6
5733
- },
5734
- children: auditIssues.map((issue, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5735
- className: `${panel_module_css_default.todoItem} ${issue.severity === "high" ? panel_module_css_default.todoDanger : issue.severity === "medium" ? panel_module_css_default.todoWarning : panel_module_css_default.todoInfo}`,
5736
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5737
- className: panel_module_css_default.todoText,
5738
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
5739
- issue.chapterNo > 0 ? `第 ${issue.chapterNo} 章` : "未定位章节",
5740
- " · [",
5741
- issue.severity,
5742
- "] ",
5743
- issue.item
5744
- ] }), issue.suggestion !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5745
- className: panel_module_css_default.meta,
5746
- children: ["建议:", issue.suggestion]
5747
- })]
5748
- }), issue.chapterNo > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5749
- type: "button",
5750
- className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
5751
- disabled: busy,
5752
- onClick: () => {
5753
- openWorkspace(issue.chapterNo, `按质检意见修订:${issue.item}(建议:${issue.suggestion})`);
5754
- },
5755
- children: "去修订"
5756
- })]
5757
- }, i))
5758
- })]
5759
- })
5760
- ] }),
5761
- activeTab === "overview" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5762
- className: panel_module_css_default.card,
5763
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5764
- className: panel_module_css_default.row,
5765
- style: { justifyContent: "space-between" },
5766
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5767
- className: panel_module_css_default.cardTitle,
5768
- children: tt("tab.overview")
5769
- }), project !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5770
- className: panel_module_css_default.row,
5771
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5772
- className: panel_module_css_default.meta,
5773
- children: [
5774
- tt("overview.bookName"),
5775
- ": ",
5776
- project.bookName,
5777
- " · ",
5778
- project.outline.length,
5779
- " 字",
5780
- project.outlinePath !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [" · ", project.outlinePath] })
5781
- ]
5782
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5783
- type: "button",
5784
- className: panel_module_css_default.button,
5785
- disabled: busy,
5786
- onClick: () => {
5787
- handleToggleUpdateOutline();
5788
- },
5789
- children: updatingOutline ? "收起" : "更新大纲"
5790
- })]
5791
- })]
5792
- }), project === null ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
5613
+ className: panel_module_css_default.meta,
5614
+ children: "已沉淀章节"
5615
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("b", { children: [doneCount, " 章"] })]
5616
+ }),
5617
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5618
+ className: panel_module_css_default.dashFact,
5619
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5620
+ className: panel_module_css_default.meta,
5621
+ children: "累计字数"
5622
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("b", { children: [totalChars, " 字"] })]
5623
+ }),
5624
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5625
+ className: panel_module_css_default.dashFact,
5626
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5627
+ className: panel_module_css_default.meta,
5628
+ children: "当前卷"
5629
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", { children: currentVolumeName })]
5630
+ }),
5631
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5632
+ className: panel_module_css_default.dashFact,
5633
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5634
+ className: panel_module_css_default.meta,
5635
+ children: "最近创作"
5636
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", { children: lastUpdated })]
5637
+ })
5638
+ ]
5639
+ })
5640
+ ]
5641
+ }),
5793
5642
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5794
- className: `${panel_module_css_default.dropzone} ${dragActive ? panel_module_css_default.dropzoneActive : ""}`,
5795
- onClick: () => {
5796
- fileInputRef.current?.click();
5797
- },
5798
- onDragOver: (e) => {
5799
- e.preventDefault();
5800
- setDragActive(true);
5801
- },
5802
- onDragLeave: () => {
5803
- setDragActive(false);
5804
- },
5805
- onDrop: (e) => {
5806
- e.preventDefault();
5807
- setDragActive(false);
5808
- const file = e.dataTransfer.files?.[0];
5809
- if (file !== void 0) handleDocxFile(file);
5810
- },
5643
+ className: panel_module_css_default.assetGrid,
5811
5644
  children: [
5812
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5813
- className: panel_module_css_default.dropzoneIcon,
5814
- children: "📄"
5645
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5646
+ className: panel_module_css_default.assetStat,
5647
+ children: [
5648
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5649
+ className: panel_module_css_default.assetStatLabel,
5650
+ children: "已通过审稿"
5651
+ }),
5652
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5653
+ className: panel_module_css_default.assetStatValue,
5654
+ style: { color: approvedCount > 0 ? "var(--nf-success)" : void 0 },
5655
+ children: approvedCount
5656
+ }),
5657
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5658
+ className: panel_module_css_default.assetStatDetail,
5659
+ children: "章节已 approved"
5660
+ })
5661
+ ]
5815
5662
  }),
5816
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "点击选择本机 docx 大纲,或将文件拖到这里" }),
5817
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5818
- className: panel_module_css_default.meta,
5819
- children: "也支持粘贴文本到下方编辑区"
5663
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5664
+ className: panel_module_css_default.assetStat,
5665
+ children: [
5666
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5667
+ className: panel_module_css_default.assetStatLabel,
5668
+ children: "待生成"
5669
+ }),
5670
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5671
+ className: panel_module_css_default.assetStatValue,
5672
+ style: { color: pendingCount > 0 ? "var(--nf-warn)" : void 0 },
5673
+ children: pendingCount
5674
+ }),
5675
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5676
+ className: panel_module_css_default.assetStatDetail,
5677
+ children: "pending + error"
5678
+ })
5679
+ ]
5820
5680
  }),
5821
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
5822
- ref: fileInputRef,
5823
- type: "file",
5824
- accept: ".docx,application/vnd.openxmlformats-officedocument.wordprocessingml.document",
5825
- style: { display: "none" },
5826
- onChange: (e) => {
5827
- const file = e.target.files?.[0];
5828
- if (file !== void 0) handleDocxFile(file);
5829
- e.target.value = "";
5830
- }
5681
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5682
+ className: panel_module_css_default.assetStat,
5683
+ children: [
5684
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5685
+ className: panel_module_css_default.assetStatLabel,
5686
+ children: "待审稿"
5687
+ }),
5688
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5689
+ className: panel_module_css_default.assetStatValue,
5690
+ style: { color: reviewPendingCount > 0 ? "var(--nf-info)" : void 0 },
5691
+ children: reviewPendingCount
5692
+ }),
5693
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5694
+ className: panel_module_css_default.assetStatDetail,
5695
+ children: "written + rejected"
5696
+ })
5697
+ ]
5698
+ }),
5699
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5700
+ className: panel_module_css_default.assetStat,
5701
+ children: [
5702
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5703
+ className: panel_module_css_default.assetStatLabel,
5704
+ children: "总字数"
5705
+ }),
5706
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5707
+ className: panel_module_css_default.assetStatValue,
5708
+ children: totalChars
5709
+ }),
5710
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5711
+ className: panel_module_css_default.assetStatDetail,
5712
+ children: "已生成正文累计"
5713
+ })
5714
+ ]
5831
5715
  })
5832
5716
  ]
5833
5717
  }),
5834
5718
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5835
- className: panel_module_css_default.row,
5836
- style: { justifyContent: "space-between" },
5837
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5838
- className: panel_module_css_default.meta,
5839
- children: [
5840
- tt("overview.outlineChars"),
5841
- ": ",
5842
- outlineText.length
5843
- ]
5844
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5845
- type: "button",
5846
- className: panel_module_css_default.button,
5847
- disabled: busy || outlineText.length < 50,
5848
- onClick: () => {
5849
- handleSaveOutline();
5719
+ className: panel_module_css_default.dashGrid,
5720
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5721
+ className: panel_module_css_default.card,
5722
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5723
+ className: panel_module_css_default.cardTitle,
5724
+ children: "待办队列"
5725
+ }), todos.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5726
+ className: panel_module_css_default.meta,
5727
+ children: "🎉 暂无待办,一切顺畅"
5728
+ }) : todos.map((todo, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5729
+ className: `${panel_module_css_default.todoItem} ${todo.tone === "danger" ? panel_module_css_default.todoDanger : todo.tone === "warning" ? panel_module_css_default.todoWarning : panel_module_css_default.todoInfo}`,
5730
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5731
+ className: panel_module_css_default.todoText,
5732
+ children: [todo.title, todo.description !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5733
+ className: panel_module_css_default.meta,
5734
+ children: [" — ", todo.description]
5735
+ })]
5736
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5737
+ type: "button",
5738
+ className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
5739
+ disabled: busy,
5740
+ onClick: () => {
5741
+ todo.onClick();
5742
+ },
5743
+ children: todo.actionLabel
5744
+ })]
5745
+ }, i))]
5746
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5747
+ className: panel_module_css_default.card,
5748
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5749
+ className: panel_module_css_default.row,
5750
+ style: { justifyContent: "space-between" },
5751
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5752
+ className: panel_module_css_default.cardTitle,
5753
+ children: "资产健康"
5754
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5755
+ type: "button",
5756
+ className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
5757
+ disabled: busy || doneCount === 0,
5758
+ onClick: () => {
5759
+ handleAudit();
5760
+ },
5761
+ title: "LLM 扫描全本已生成章节,检查人名/境界/资源/时间线矛盾",
5762
+ children: "🔍 全书质检"
5763
+ })]
5764
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5765
+ className: panel_module_css_default.assetGrid,
5766
+ children: [
5767
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5768
+ className: panel_module_css_default.assetStat,
5769
+ children: [
5770
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5771
+ className: panel_module_css_default.assetStatLabel,
5772
+ children: "道藏"
5773
+ }),
5774
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5775
+ className: panel_module_css_default.assetStatValue,
5776
+ style: { color: bible !== void 0 ? "var(--nf-success)" : "var(--nf-text-3)" },
5777
+ children: bible !== void 0 ? `✓ ${bible.worldRules.length} 条规则` : "未生成"
5778
+ }),
5779
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5780
+ className: panel_module_css_default.assetStatDetail,
5781
+ children: bible !== void 0 ? `${bible.characters.length} 人物 · ${bible.redLines.length} 红线` : "提炼人设 / 世界观 / 金手指"
5782
+ })
5783
+ ]
5784
+ }),
5785
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5786
+ className: panel_module_css_default.assetStat,
5787
+ children: [
5788
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5789
+ className: panel_module_css_default.assetStatLabel,
5790
+ children: "卷计划"
5791
+ }),
5792
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5793
+ className: panel_module_css_default.assetStatValue,
5794
+ style: { color: volumes !== void 0 ? "var(--nf-success)" : "var(--nf-text-3)" },
5795
+ children: volumes !== void 0 ? `${volumes.length} 卷` : "未生成"
5796
+ }),
5797
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5798
+ className: panel_module_css_default.assetStatDetail,
5799
+ title: volumes?.map((v) => v.title).join(" / "),
5800
+ children: volumes !== void 0 ? volumes.map((v) => v.title).join(" / ") : "按剧情弧线划分全书"
5801
+ })
5802
+ ]
5803
+ }),
5804
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5805
+ className: panel_module_css_default.assetStat,
5806
+ children: [
5807
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5808
+ className: panel_module_css_default.assetStatLabel,
5809
+ children: "写作资产"
5810
+ }),
5811
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5812
+ className: panel_module_css_default.assetStatValue,
5813
+ style: { color: assetCount > 0 ? "var(--nf-success)" : "var(--nf-text-3)" },
5814
+ children: [assetCount, " 项"]
5815
+ }),
5816
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5817
+ className: panel_module_css_default.assetStatDetail,
5818
+ title: assetSummary,
5819
+ children: assetSummary
5820
+ })
5821
+ ]
5822
+ }),
5823
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5824
+ className: panel_module_css_default.assetStat,
5825
+ children: [
5826
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5827
+ className: panel_module_css_default.assetStatLabel,
5828
+ children: "伏笔"
5829
+ }),
5830
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5831
+ className: panel_module_css_default.assetStatValue,
5832
+ children: [foreshadows.length, " 条"]
5833
+ }),
5834
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5835
+ className: panel_module_css_default.assetStatDetail,
5836
+ children: [
5837
+ foreshadows.filter((f) => f.status === "planned").length,
5838
+ " 待埋 · ",
5839
+ foreshadows.filter((f) => f.status === "resolved").length,
5840
+ " 已回收"
5841
+ ]
5842
+ })
5843
+ ]
5844
+ })
5845
+ ]
5846
+ })]
5847
+ })]
5848
+ }),
5849
+ auditIssues !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5850
+ className: panel_module_css_default.card,
5851
+ style: { borderColor: auditIssues.length > 0 ? "var(--nf-error)" : "var(--nf-success)" },
5852
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5853
+ className: panel_module_css_default.row,
5854
+ style: { justifyContent: "space-between" },
5855
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5856
+ className: panel_module_css_default.cardTitle,
5857
+ children: ["🔍 全书质检", auditIssues.length === 0 ? ":未发现矛盾 🎉" : `:${auditIssues.length} 处疑似矛盾`]
5858
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5859
+ type: "button",
5860
+ className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
5861
+ onClick: () => {
5862
+ setAuditIssues(null);
5863
+ },
5864
+ children: "收起"
5865
+ })]
5866
+ }), auditIssues.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5867
+ style: {
5868
+ display: "flex",
5869
+ flexDirection: "column",
5870
+ gap: 6
5850
5871
  },
5851
- children: tt("overview.saveOutline")
5872
+ children: auditIssues.map((issue, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5873
+ className: `${panel_module_css_default.todoItem} ${issue.severity === "high" ? panel_module_css_default.todoDanger : issue.severity === "medium" ? panel_module_css_default.todoWarning : panel_module_css_default.todoInfo}`,
5874
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5875
+ className: panel_module_css_default.todoText,
5876
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
5877
+ issue.chapterNo > 0 ? `第 ${issue.chapterNo} 章` : "未定位章节",
5878
+ " · [",
5879
+ issue.severity,
5880
+ "] ",
5881
+ issue.item
5882
+ ] }), issue.suggestion !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5883
+ className: panel_module_css_default.meta,
5884
+ children: ["建议:", issue.suggestion]
5885
+ })]
5886
+ }), issue.chapterNo > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5887
+ type: "button",
5888
+ className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
5889
+ disabled: busy,
5890
+ onClick: () => {
5891
+ openWorkspace(issue.chapterNo, `按质检意见修订:${issue.item}(建议:${issue.suggestion})`);
5892
+ },
5893
+ children: "去修订"
5894
+ })]
5895
+ }, i))
5852
5896
  })]
5853
- }),
5854
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
5855
- className: panel_module_css_default.textarea,
5856
- value: outlineText,
5857
- placeholder: tt("overview.outlineHint"),
5858
- onChange: (e) => {
5859
- setOutlineText(e.target.value);
5860
- },
5861
- spellCheck: false
5862
5897
  })
5863
- ] }) : updatingOutline ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
5864
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5865
- className: panel_module_css_default.meta,
5866
- children: [
5867
- "大纲是本书的「出生证明」。更新时请二选一:",
5868
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", { children: "仅更新文本" }),
5869
- "(保留设定/章节/正文全部进度),或",
5870
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", { children: "重置项目" }),
5871
- "(从新总纲重新开始,清空道藏/卷/章节/正文/暗线/资产/编年录,不可恢复)。"
5872
- ]
5873
- }),
5874
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
5875
- className: panel_module_css_default.textarea,
5876
- value: outlineText,
5877
- placeholder: "粘贴新版大纲文本…",
5878
- onChange: (e) => {
5879
- setOutlineText(e.target.value);
5880
- },
5881
- spellCheck: false
5882
- }),
5883
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5898
+ ] }),
5899
+ activeTab === "overview" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5900
+ className: panel_module_css_default.card,
5901
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5884
5902
  className: panel_module_css_default.row,
5885
- children: [
5886
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5903
+ style: { justifyContent: "space-between" },
5904
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5905
+ className: panel_module_css_default.cardTitle,
5906
+ children: tt("tab.overview")
5907
+ }), project !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5908
+ className: panel_module_css_default.row,
5909
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5910
+ className: panel_module_css_default.meta,
5911
+ children: [
5912
+ tt("overview.bookName"),
5913
+ ": ",
5914
+ project.bookName,
5915
+ " · ",
5916
+ project.outline.length,
5917
+ " 字",
5918
+ project.outlinePath !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [" · ", project.outlinePath] })
5919
+ ]
5920
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5887
5921
  type: "button",
5888
- className: `${panel_module_css_default.button} ${panel_module_css_default.buttonPrimary}`,
5889
- disabled: busy || outlineText.length < 50,
5922
+ className: panel_module_css_default.button,
5923
+ disabled: busy,
5890
5924
  onClick: () => {
5891
- handleSaveOutline();
5925
+ handleToggleUpdateOutline();
5892
5926
  },
5893
- children: "仅更新文本(保留进度)"
5894
- }),
5895
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5927
+ children: updatingOutline ? "收起" : "更新大纲"
5928
+ })]
5929
+ })]
5930
+ }), project === null ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
5931
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5932
+ className: `${panel_module_css_default.dropzone} ${dragActive ? panel_module_css_default.dropzoneActive : ""}`,
5933
+ onClick: () => {
5934
+ fileInputRef.current?.click();
5935
+ },
5936
+ onDragOver: (e) => {
5937
+ e.preventDefault();
5938
+ setDragActive(true);
5939
+ },
5940
+ onDragLeave: () => {
5941
+ setDragActive(false);
5942
+ },
5943
+ onDrop: (e) => {
5944
+ e.preventDefault();
5945
+ setDragActive(false);
5946
+ const file = e.dataTransfer.files?.[0];
5947
+ if (file !== void 0) handleDocxFile(file);
5948
+ },
5949
+ children: [
5950
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5951
+ className: panel_module_css_default.dropzoneIcon,
5952
+ children: "📄"
5953
+ }),
5954
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "点击选择本机 docx 大纲,或将文件拖到这里" }),
5955
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5956
+ className: panel_module_css_default.meta,
5957
+ children: "也支持粘贴文本到下方编辑区"
5958
+ }),
5959
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
5960
+ ref: fileInputRef,
5961
+ type: "file",
5962
+ accept: ".docx,application/vnd.openxmlformats-officedocument.wordprocessingml.document",
5963
+ style: { display: "none" },
5964
+ onChange: (e) => {
5965
+ const file = e.target.files?.[0];
5966
+ if (file !== void 0) handleDocxFile(file);
5967
+ e.target.value = "";
5968
+ }
5969
+ })
5970
+ ]
5971
+ }),
5972
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5973
+ className: panel_module_css_default.row,
5974
+ style: { justifyContent: "space-between" },
5975
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5976
+ className: panel_module_css_default.meta,
5977
+ children: [
5978
+ tt("overview.outlineChars"),
5979
+ ": ",
5980
+ outlineText.length
5981
+ ]
5982
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5896
5983
  type: "button",
5897
- className: `${panel_module_css_default.button} ${panel_module_css_default.buttonDanger}`,
5984
+ className: panel_module_css_default.button,
5898
5985
  disabled: busy || outlineText.length < 50,
5899
5986
  onClick: () => {
5900
- handleResetProject();
5987
+ handleSaveOutline();
5901
5988
  },
5902
- children: "重置项目并更新(清空进度)"
5903
- }),
5904
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5905
- className: panel_module_css_default.meta,
5906
- children: [outlineText.length, " 字"]
5907
- })
5908
- ]
5909
- })
5910
- ] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
5911
- className: panel_module_css_default.outlineReadonly,
5912
- children: project.outline
5913
- })]
5914
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5915
- className: panel_module_css_default.card,
5916
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5917
- className: panel_module_css_default.cardTitle,
5918
- children: [
5919
- tt("status.files"),
5920
- "(",
5921
- generatedFiles.length,
5922
- ")"
5923
- ]
5924
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5925
- className: panel_module_css_default.fileList,
5926
- children: [generatedFiles.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: tt("status.projectNone") }), generatedFiles.map((file) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: file }, file))]
5927
- })]
5928
- })] }),
5929
- activeTab === "blurb" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5930
- className: panel_module_css_default.card,
5931
- children: [
5932
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5933
- className: panel_module_css_default.row,
5934
- style: { justifyContent: "space-between" },
5935
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5936
- className: panel_module_css_default.cardTitle,
5937
- children: "卷首语"
5938
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5989
+ children: tt("overview.saveOutline")
5990
+ })]
5991
+ }),
5992
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
5993
+ className: panel_module_css_default.textarea,
5994
+ value: outlineText,
5995
+ placeholder: tt("overview.outlineHint"),
5996
+ onChange: (e) => {
5997
+ setOutlineText(e.target.value);
5998
+ },
5999
+ spellCheck: false
6000
+ })
6001
+ ] }) : updatingOutline ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
6002
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6003
+ className: panel_module_css_default.meta,
6004
+ children: [
6005
+ "大纲是本书的「出生证明」。更新时请二选一:",
6006
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", { children: "仅更新文本" }),
6007
+ "(保留设定/章节/正文全部进度),或",
6008
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", { children: "重置项目" }),
6009
+ "(从新总纲重新开始,清空道藏/卷/章节/正文/暗线/资产/编年录,不可恢复)。"
6010
+ ]
6011
+ }),
6012
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
6013
+ className: panel_module_css_default.textarea,
6014
+ value: outlineText,
6015
+ placeholder: "粘贴新版大纲文本…",
6016
+ onChange: (e) => {
6017
+ setOutlineText(e.target.value);
6018
+ },
6019
+ spellCheck: false
6020
+ }),
6021
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5939
6022
  className: panel_module_css_default.row,
5940
6023
  children: [
5941
6024
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5942
6025
  type: "button",
5943
- className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall} ${panel_module_css_default.buttonPrimary}`,
5944
- disabled: busy || project === null,
6026
+ className: `${panel_module_css_default.button} ${panel_module_css_default.buttonPrimary}`,
6027
+ disabled: busy || outlineText.length < 50,
5945
6028
  onClick: () => {
5946
- handleBlurbGenerate();
6029
+ handleSaveOutline();
5947
6030
  },
5948
- children: "✨ AI 生成"
6031
+ children: "仅更新文本(保留进度)"
5949
6032
  }),
5950
6033
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5951
6034
  type: "button",
5952
- className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
5953
- disabled: busy || project === null || blurbDraft.trim() === "",
6035
+ className: `${panel_module_css_default.button} ${panel_module_css_default.buttonDanger}`,
6036
+ disabled: busy || outlineText.length < 50,
5954
6037
  onClick: () => {
5955
- handleBlurbComplete();
6038
+ handleResetProject();
5956
6039
  },
5957
- children: "✍️ AI 补全"
6040
+ children: "重置项目并更新(清空进度)"
5958
6041
  }),
5959
- project?.blurb !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5960
- type: "button",
5961
- className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
5962
- disabled: busy || project === null,
5963
- onClick: () => {
5964
- if (window.confirm("重新生成会覆盖当前简介(可先复制保存),确定?")) handleBlurbGenerate();
5965
- },
5966
- children: "🔄 重新生成"
6042
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
6043
+ className: panel_module_css_default.meta,
6044
+ children: [outlineText.length, " 字"]
5967
6045
  })
5968
6046
  ]
5969
- })]
5970
- }),
5971
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5972
- className: panel_module_css_default.row,
5973
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
5974
- className: panel_module_css_default.input,
6047
+ })
6048
+ ] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
6049
+ className: panel_module_css_default.outlineReadonly,
6050
+ children: project.outline
6051
+ })]
6052
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6053
+ className: panel_module_css_default.card,
6054
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
6055
+ className: panel_module_css_default.cardTitle,
6056
+ children: [
6057
+ tt("status.files"),
6058
+ "(",
6059
+ generatedFiles.length,
6060
+ ")"
6061
+ ]
6062
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6063
+ className: panel_module_css_default.fileList,
6064
+ children: [generatedFiles.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: tt("status.projectNone") }), generatedFiles.map((file) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: file }, file))]
6065
+ })]
6066
+ })] }),
6067
+ activeTab === "blurb" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6068
+ className: panel_module_css_default.card,
6069
+ children: [
6070
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6071
+ className: panel_module_css_default.row,
6072
+ style: { justifyContent: "space-between" },
6073
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6074
+ className: panel_module_css_default.cardTitle,
6075
+ children: "卷首语"
6076
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6077
+ className: panel_module_css_default.row,
6078
+ children: [
6079
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6080
+ type: "button",
6081
+ className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall} ${panel_module_css_default.buttonPrimary}`,
6082
+ disabled: busy || project === null,
6083
+ onClick: () => {
6084
+ handleBlurbGenerate();
6085
+ },
6086
+ children: "✨ AI 生成"
6087
+ }),
6088
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6089
+ type: "button",
6090
+ className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
6091
+ disabled: busy || project === null || blurbDraft.trim() === "",
6092
+ onClick: () => {
6093
+ handleBlurbComplete();
6094
+ },
6095
+ children: "✍️ AI 补全"
6096
+ }),
6097
+ project?.blurb !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6098
+ type: "button",
6099
+ className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
6100
+ disabled: busy || project === null,
6101
+ onClick: () => {
6102
+ if (window.confirm("重新生成会覆盖当前简介(可先复制保存),确定?")) handleBlurbGenerate();
6103
+ },
6104
+ children: "🔄 重新生成"
6105
+ })
6106
+ ]
6107
+ })]
6108
+ }),
6109
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6110
+ className: panel_module_css_default.row,
6111
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
6112
+ className: panel_module_css_default.input,
6113
+ style: {
6114
+ flex: 1,
6115
+ maxWidth: 320
6116
+ },
6117
+ placeholder: "书名",
6118
+ value: bookNameDraft,
6119
+ onChange: (e) => {
6120
+ setBookNameDraft(e.target.value);
6121
+ },
6122
+ onKeyDown: (e) => {
6123
+ if (e.key === "Enter") handleRename();
6124
+ }
6125
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6126
+ type: "button",
6127
+ className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
6128
+ disabled: busy || bookNameDraft.trim() === "" || bookNameDraft.trim() === project?.bookName,
6129
+ onClick: () => {
6130
+ handleRename();
6131
+ },
6132
+ children: "💾 改书名"
6133
+ })]
6134
+ }),
6135
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6136
+ className: panel_module_css_default.row,
5975
6137
  style: {
5976
- flex: 1,
5977
- maxWidth: 320
6138
+ alignItems: "flex-start",
6139
+ gap: 14
5978
6140
  },
5979
- placeholder: "书名",
5980
- value: bookNameDraft,
6141
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6142
+ className: panel_module_css_default.coverPreview,
6143
+ children: coverDataUrl !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
6144
+ src: coverDataUrl,
6145
+ alt: "封面"
6146
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6147
+ className: panel_module_css_default.coverPlaceholder,
6148
+ children: "暂无封面"
6149
+ })
6150
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6151
+ style: {
6152
+ display: "flex",
6153
+ flexDirection: "column",
6154
+ gap: 8
6155
+ },
6156
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6157
+ className: panel_module_css_default.row,
6158
+ children: [
6159
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6160
+ type: "button",
6161
+ className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
6162
+ disabled: busy || project === null,
6163
+ onClick: () => {
6164
+ coverFileRef.current?.click();
6165
+ },
6166
+ children: "📤 上传封面"
6167
+ }),
6168
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
6169
+ ref: coverFileRef,
6170
+ type: "file",
6171
+ accept: "image/png,image/jpeg,image/webp",
6172
+ style: { display: "none" },
6173
+ onChange: (e) => {
6174
+ handleCoverUpload(e.target.files?.[0]);
6175
+ e.target.value = "";
6176
+ }
6177
+ }),
6178
+ coverDataUrl !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6179
+ type: "button",
6180
+ className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
6181
+ disabled: busy,
6182
+ onClick: () => {
6183
+ handleCoverRemove();
6184
+ },
6185
+ children: "🗑️ 移除"
6186
+ })
6187
+ ]
6188
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6189
+ className: panel_module_css_default.meta,
6190
+ children: "支持 PNG / JPG / WebP,建议 3:4 竖版;保存于输出目录 cover.*。"
6191
+ })]
6192
+ })]
6193
+ }),
6194
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6195
+ className: panel_module_css_default.meta,
6196
+ children: "面向读者的作品门面(120-250 字):突出核心卖点与开局钩子,不剧透。点击 ✨AI 生成全量生成;或先写几句再点 ✍️AI 补全续写完整;不满意可 🔄 重新生成。"
6197
+ }),
6198
+ project === null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6199
+ className: panel_module_css_default.meta,
6200
+ children: "请先在大纲页导入大纲建立项目。"
6201
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
6202
+ className: panel_module_css_default.textarea,
6203
+ style: { minHeight: 140 },
6204
+ placeholder: "点击 ✨AI 生成,或先写下开头几句,再点 ✍️AI 补全…",
6205
+ value: blurbDraft,
5981
6206
  onChange: (e) => {
5982
- setBookNameDraft(e.target.value);
5983
- },
5984
- onKeyDown: (e) => {
5985
- if (e.key === "Enter") handleRename();
5986
- }
5987
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5988
- type: "button",
5989
- className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
5990
- disabled: busy || bookNameDraft.trim() === "" || bookNameDraft.trim() === project?.bookName,
5991
- onClick: () => {
5992
- handleRename();
6207
+ setBlurbDraft(e.target.value);
5993
6208
  },
5994
- children: "💾 改书名"
5995
- })]
5996
- }),
5997
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5998
- className: panel_module_css_default.row,
5999
- style: {
6000
- alignItems: "flex-start",
6001
- gap: 14
6002
- },
6003
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6004
- className: panel_module_css_default.coverPreview,
6005
- children: coverDataUrl !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
6006
- src: coverDataUrl,
6007
- alt: "封面"
6008
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6009
- className: panel_module_css_default.coverPlaceholder,
6010
- children: "暂无封面"
6011
- })
6209
+ spellCheck: false
6012
6210
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6013
- style: {
6014
- display: "flex",
6015
- flexDirection: "column",
6016
- gap: 8
6017
- },
6018
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6211
+ className: panel_module_css_default.row,
6212
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6213
+ type: "button",
6214
+ className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
6215
+ disabled: busy || blurbDraft.trim() === "",
6216
+ onClick: () => {
6217
+ handleBlurbSave();
6218
+ },
6219
+ children: "💾 保存简介"
6220
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
6221
+ className: panel_module_css_default.meta,
6222
+ children: [
6223
+ blurbDraft.length,
6224
+ " 字 · 已保存:",
6225
+ project.blurb !== void 0 ? `${project.blurb.length} 字` : "无"
6226
+ ]
6227
+ })]
6228
+ })] })
6229
+ ]
6230
+ }),
6231
+ activeTab === "plan" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
6232
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6233
+ className: panel_module_css_default.card,
6234
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6235
+ className: panel_module_css_default.row,
6236
+ style: { justifyContent: "space-between" },
6237
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6238
+ className: panel_module_css_default.cardTitle,
6239
+ children: tt("tab.plan")
6240
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6019
6241
  className: panel_module_css_default.row,
6020
6242
  children: [
6021
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6022
- type: "button",
6023
- className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
6024
- disabled: busy || project === null,
6025
- onClick: () => {
6026
- coverFileRef.current?.click();
6027
- },
6028
- children: "📤 上传封面"
6243
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6244
+ className: panel_module_css_default.meta,
6245
+ children: tt("plan.generateHint")
6029
6246
  }),
6030
6247
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
6031
- ref: coverFileRef,
6032
- type: "file",
6033
- accept: "image/png,image/jpeg,image/webp",
6034
- style: { display: "none" },
6248
+ className: panel_module_css_default.input,
6249
+ style: { width: 72 },
6250
+ type: "number",
6251
+ min: 1,
6252
+ max: 200,
6253
+ value: planCount,
6035
6254
  onChange: (e) => {
6036
- handleCoverUpload(e.target.files?.[0]);
6037
- e.target.value = "";
6255
+ const v = Number(e.target.value);
6256
+ if (Number.isInteger(v)) setPlanCount(v);
6038
6257
  }
6039
6258
  }),
6040
- coverDataUrl !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6259
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6260
+ className: panel_module_css_default.meta,
6261
+ children: tt("plan.count")
6262
+ }),
6263
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6041
6264
  type: "button",
6042
- className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
6043
- disabled: busy,
6265
+ className: `${panel_module_css_default.button} ${panel_module_css_default.buttonPrimary}`,
6266
+ disabled: busy || outlineText.length < 50,
6044
6267
  onClick: () => {
6045
- handleCoverRemove();
6268
+ handlePlan();
6046
6269
  },
6047
- children: "🗑️ 移除"
6270
+ children: tt("plan.generate")
6048
6271
  })
6049
6272
  ]
6050
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6051
- className: panel_module_css_default.meta,
6052
- children: "支持 PNG / JPG / WebP,建议 3:4 竖版;保存于输出目录 cover.*。"
6053
6273
  })]
6274
+ }), volumes !== void 0 && volumes.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6275
+ className: panel_module_css_default.row,
6276
+ children: volumes.map((v) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
6277
+ className: panel_module_css_default.badge,
6278
+ style: {
6279
+ borderColor: "var(--nf-accent)",
6280
+ color: "var(--nf-accent)"
6281
+ },
6282
+ children: [
6283
+ v.no,
6284
+ ". ",
6285
+ v.title,
6286
+ "(",
6287
+ v.chapterStart,
6288
+ "-",
6289
+ v.chapterEnd,
6290
+ ")"
6291
+ ]
6292
+ }, v.no))
6054
6293
  })]
6055
6294
  }),
6056
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6057
- className: panel_module_css_default.meta,
6058
- children: "面向读者的作品门面(120-250 字):突出核心卖点与开局钩子,不剧透。点击 ✨AI 生成全量生成;或先写几句再点 ✍️AI 补全续写完整;不满意可 🔄 重新生成。"
6059
- }),
6060
- project === null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6061
- className: panel_module_css_default.meta,
6062
- children: "请先在大纲页导入大纲建立项目。"
6063
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
6064
- className: panel_module_css_default.textarea,
6065
- style: { minHeight: 140 },
6066
- placeholder: "点击 ✨AI 生成,或先写下开头几句,再点 ✍️AI 补全…",
6067
- value: blurbDraft,
6068
- onChange: (e) => {
6069
- setBlurbDraft(e.target.value);
6070
- },
6071
- spellCheck: false
6072
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6073
- className: panel_module_css_default.row,
6074
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6075
- type: "button",
6076
- className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
6077
- disabled: busy || blurbDraft.trim() === "",
6078
- onClick: () => {
6079
- handleBlurbSave();
6080
- },
6081
- children: "💾 保存简介"
6082
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
6083
- className: panel_module_css_default.meta,
6084
- children: [
6085
- blurbDraft.length,
6086
- " 字 · 已保存:",
6087
- project.blurb !== void 0 ? `${project.blurb.length} 字` : "无"
6088
- ]
6089
- })]
6090
- })] })
6091
- ]
6092
- }),
6093
- activeTab === "plan" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
6094
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6095
- className: panel_module_css_default.card,
6096
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6097
- className: panel_module_css_default.row,
6098
- style: { justifyContent: "space-between" },
6099
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6100
- className: panel_module_css_default.cardTitle,
6101
- children: tt("tab.plan")
6102
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6295
+ chapters.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6296
+ className: panel_module_css_default.card,
6297
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6103
6298
  className: panel_module_css_default.row,
6104
- children: [
6105
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6106
- className: panel_module_css_default.meta,
6107
- children: tt("plan.generateHint")
6108
- }),
6109
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
6110
- className: panel_module_css_default.input,
6111
- style: { width: 72 },
6112
- type: "number",
6113
- min: 1,
6114
- max: 200,
6115
- value: planCount,
6116
- onChange: (e) => {
6117
- const v = Number(e.target.value);
6118
- if (Number.isInteger(v)) setPlanCount(v);
6119
- }
6120
- }),
6121
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6122
- className: panel_module_css_default.meta,
6123
- children: tt("plan.count")
6124
- }),
6125
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6126
- type: "button",
6127
- className: `${panel_module_css_default.button} ${panel_module_css_default.buttonPrimary}`,
6128
- disabled: busy || outlineText.length < 50,
6129
- onClick: () => {
6130
- handlePlan();
6131
- },
6132
- children: tt("plan.generate")
6133
- })
6134
- ]
6135
- })]
6136
- }), volumes !== void 0 && volumes.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6137
- className: panel_module_css_default.row,
6138
- children: volumes.map((v) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
6139
- className: panel_module_css_default.badge,
6140
- style: {
6141
- borderColor: "var(--nf-accent)",
6142
- color: "var(--nf-accent)"
6143
- },
6144
- children: [
6145
- v.no,
6146
- ". ",
6147
- v.title,
6148
- "(",
6149
- v.chapterStart,
6150
- "-",
6151
- v.chapterEnd,
6152
- ")"
6153
- ]
6154
- }, v.no))
6155
- })]
6156
- }),
6157
- chapters.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6158
- className: panel_module_css_default.card,
6159
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6160
- className: panel_module_css_default.row,
6161
- style: { justifyContent: "space-between" },
6162
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
6163
- className: panel_module_css_default.meta,
6164
- children: [
6165
- "共 ",
6166
- chapters.length,
6167
- " 章 · 已完成 ",
6168
- doneCount,
6169
- " · 待生成 ",
6170
- pendingCount
6171
- ]
6172
- }), pendingCount > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
6173
- type: "button",
6174
- className: `${panel_module_css_default.button} ${panel_module_css_default.buttonPrimary}`,
6175
- disabled: busy,
6176
- onClick: () => {
6177
- handleWriteAll();
6178
- },
6179
- children: [
6180
- tt("plan.writeAllPending"),
6181
- "(",
6182
- pendingCount,
6183
- ")"
6184
- ]
6185
- })]
6186
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6187
- className: panel_module_css_default.chapterList,
6188
- children: chapterGroups.map((group) => {
6189
- const collapsed = group.no !== 0 && collapsedVolumes.includes(group.no);
6190
- const groupDone = group.chapters.filter((c) => c.status === "approved" || c.status === "written" || c.status === "rejected").length;
6191
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6192
- className: panel_module_css_default.volumeGroup,
6193
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6194
- className: panel_module_css_default.volumeGroupHeader,
6195
- onClick: () => {
6196
- if (group.no !== 0) setCollapsedVolumes((prev) => prev.includes(group.no) ? prev.filter((x) => x !== group.no) : [...prev, group.no]);
6197
- },
6198
- children: [
6199
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6200
- className: panel_module_css_default.volumeGroupToggle,
6201
- children: group.no !== 0 ? collapsed ? "▸" : "▾" : "📖"
6202
- }),
6203
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", { children: group.title }),
6204
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
6205
- className: panel_module_css_default.meta,
6206
- children: [
6207
- "(",
6208
- group.chapters.length,
6209
- " 章 · 已完成 ",
6210
- groupDone,
6211
- ")"
6212
- ]
6213
- })
6214
- ]
6215
- }), !collapsed && group.chapters.map((chapter) => {
6216
- const badge = statusBadge(chapter);
6217
- const expanded = expandedChapter === chapter.no;
6218
- const review = chapter.review;
6219
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6220
- className: panel_module_css_default.chapter,
6299
+ style: { justifyContent: "space-between" },
6300
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
6301
+ className: panel_module_css_default.meta,
6302
+ children: [
6303
+ "共 ",
6304
+ chapters.length,
6305
+ " 章 · 已完成 ",
6306
+ doneCount,
6307
+ " · 待生成 ",
6308
+ pendingCount
6309
+ ]
6310
+ }), pendingCount > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
6311
+ type: "button",
6312
+ className: `${panel_module_css_default.button} ${panel_module_css_default.buttonPrimary}`,
6313
+ disabled: busy,
6314
+ onClick: () => {
6315
+ handleWriteAll();
6316
+ },
6317
+ children: [
6318
+ tt("plan.writeAllPending"),
6319
+ "(",
6320
+ pendingCount,
6321
+ ")"
6322
+ ]
6323
+ })]
6324
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6325
+ className: panel_module_css_default.chapterList,
6326
+ children: chapterGroups.map((group) => {
6327
+ const collapsed = group.no !== 0 && collapsedVolumes.includes(group.no);
6328
+ const groupDone = group.chapters.filter((c) => c.status === "approved" || c.status === "written" || c.status === "rejected").length;
6329
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6330
+ className: panel_module_css_default.volumeGroup,
6331
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6332
+ className: panel_module_css_default.volumeGroupHeader,
6333
+ onClick: () => {
6334
+ if (group.no !== 0) setCollapsedVolumes((prev) => prev.includes(group.no) ? prev.filter((x) => x !== group.no) : [...prev, group.no]);
6335
+ },
6221
6336
  children: [
6222
6337
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6223
- className: panel_module_css_default.chapterNum,
6224
- children: chapter.no
6338
+ className: panel_module_css_default.volumeGroupToggle,
6339
+ children: group.no !== 0 ? collapsed ? "▸" : "▾" : "📖"
6225
6340
  }),
6226
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6227
- className: panel_module_css_default.chapterMain,
6341
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", { children: group.title }),
6342
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
6343
+ className: panel_module_css_default.meta,
6228
6344
  children: [
6229
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6230
- className: panel_module_css_default.chapterTitle,
6231
- children: [
6232
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6233
- type: "button",
6234
- className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
6235
- style: { padding: "1px 6px" },
6236
- onClick: () => {
6237
- handleToggleChapter(chapter.no);
6238
- },
6239
- children: expanded ? "−" : "+"
6240
- }),
6241
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: chapter.title }),
6242
- chapter.status === "approved" && chapter.chars !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
6243
- className: panel_module_css_default.meta,
6244
- children: [chapter.chars, tt("common.chars")]
6245
- }),
6246
- chapter.volume > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
6247
- className: panel_module_css_default.meta,
6248
- children: [tt("plan.volumes"), chapter.volume]
6249
- })
6250
- ]
6251
- }),
6252
- !expanded && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6253
- className: panel_module_css_default.chapterBeats,
6254
- title: chapter.beats,
6255
- children: chapter.beats
6256
- }),
6257
- expanded && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6258
- style: {
6259
- display: "flex",
6260
- flexDirection: "column",
6261
- gap: 6
6262
- },
6263
- children: [
6264
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6265
- className: panel_module_css_default.meta,
6266
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("b", { children: [tt("plan.beats"), ":"] })
6267
- }),
6268
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6269
- className: panel_module_css_default.meta,
6270
- children: renderBeats(chapter.beats)
6271
- }),
6272
- chapter.summary !== void 0 && chapter.summary !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6273
- className: panel_module_css_default.meta,
6274
- children: [
6275
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("b", { children: [tt("plan.summary"), ":"] }),
6276
- " ",
6277
- chapter.summary
6278
- ]
6279
- }),
6280
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
6281
- className: panel_module_css_default.chapterPreview,
6282
- children: chapterText || `(${tt("common.loading")})`
6283
- }),
6284
- review !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6285
- className: panel_module_css_default.reviewBox,
6286
- children: [
6287
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6288
- className: panel_module_css_default.row,
6289
- style: { justifyContent: "space-between" },
6290
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", { children: tt("plan.reviewReport") }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
6291
- style: { color: review.passed ? "var(--nf-success)" : "var(--nf-error)" },
6345
+ "(",
6346
+ group.chapters.length,
6347
+ " 章 · 已完成 ",
6348
+ groupDone,
6349
+ ")"
6350
+ ]
6351
+ })
6352
+ ]
6353
+ }), !collapsed && group.chapters.map((chapter) => {
6354
+ const badge = statusBadge(chapter);
6355
+ const expanded = expandedChapter === chapter.no;
6356
+ const review = chapter.review;
6357
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6358
+ className: panel_module_css_default.chapter,
6359
+ children: [
6360
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6361
+ className: panel_module_css_default.chapterNum,
6362
+ children: chapter.no
6363
+ }),
6364
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6365
+ className: panel_module_css_default.chapterMain,
6366
+ children: [
6367
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6368
+ className: panel_module_css_default.chapterTitle,
6369
+ children: [
6370
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6371
+ type: "button",
6372
+ className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
6373
+ style: { padding: "1px 6px" },
6374
+ onClick: () => {
6375
+ handleToggleChapter(chapter.no);
6376
+ },
6377
+ children: expanded ? "−" : "+"
6378
+ }),
6379
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: chapter.title }),
6380
+ chapter.status === "approved" && chapter.chars !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
6381
+ className: panel_module_css_default.meta,
6382
+ children: [chapter.chars, tt("common.chars")]
6383
+ }),
6384
+ chapter.volume > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
6385
+ className: panel_module_css_default.meta,
6386
+ children: [tt("plan.volumes"), chapter.volume]
6387
+ })
6388
+ ]
6389
+ }),
6390
+ !expanded && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6391
+ className: panel_module_css_default.chapterBeats,
6392
+ title: chapter.beats,
6393
+ children: chapter.beats
6394
+ }),
6395
+ expanded && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6396
+ style: {
6397
+ display: "flex",
6398
+ flexDirection: "column",
6399
+ gap: 6
6400
+ },
6401
+ children: [
6402
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6403
+ className: panel_module_css_default.meta,
6404
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("b", { children: [tt("plan.beats"), ":"] })
6405
+ }),
6406
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6407
+ className: panel_module_css_default.meta,
6408
+ children: renderBeats(chapter.beats)
6409
+ }),
6410
+ chapter.summary !== void 0 && chapter.summary !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6411
+ className: panel_module_css_default.meta,
6412
+ children: [
6413
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("b", { children: [tt("plan.summary"), ":"] }),
6414
+ " ",
6415
+ chapter.summary
6416
+ ]
6417
+ }),
6418
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
6419
+ className: panel_module_css_default.chapterPreview,
6420
+ children: chapterText || `(${tt("common.loading")})`
6421
+ }),
6422
+ review !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6423
+ className: panel_module_css_default.reviewBox,
6424
+ children: [
6425
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6426
+ className: panel_module_css_default.row,
6427
+ style: { justifyContent: "space-between" },
6428
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", { children: tt("plan.reviewReport") }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
6429
+ style: { color: review.passed ? "var(--nf-success)" : "var(--nf-error)" },
6430
+ children: [
6431
+ tt("plan.reviewScore"),
6432
+ ": ",
6433
+ review.score,
6434
+ " — ",
6435
+ review.passed ? tt("plan.reviewPass") : tt("plan.reviewFail")
6436
+ ]
6437
+ })]
6438
+ }),
6439
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6440
+ className: panel_module_css_default.meta,
6292
6441
  children: [
6293
- tt("plan.reviewScore"),
6294
- ": ",
6295
- review.score,
6296
- " — ",
6297
- review.passed ? tt("plan.reviewPass") : tt("plan.reviewFail")
6442
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("b", { children: [tt("plan.reviewVerdict"), ":"] }),
6443
+ " ",
6444
+ review.verdict
6298
6445
  ]
6299
- })]
6300
- }),
6301
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6446
+ }),
6447
+ review.issues.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
6448
+ style: {
6449
+ margin: 0,
6450
+ paddingLeft: 18,
6451
+ fontSize: 12
6452
+ },
6453
+ children: review.issues.map((issue, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
6454
+ style: { color: severityColor(issue.severity) },
6455
+ children: [
6456
+ "[",
6457
+ issue.severity,
6458
+ "] ",
6459
+ issue.item,
6460
+ " → ",
6461
+ issue.suggestion
6462
+ ]
6463
+ }, i))
6464
+ })
6465
+ ]
6466
+ }),
6467
+ (chapter.status === "rejected" || chapter.status === "written" || chapter.status === "approved") && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6468
+ style: {
6469
+ display: "flex",
6470
+ flexDirection: "column",
6471
+ gap: 6
6472
+ },
6473
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6302
6474
  className: panel_module_css_default.meta,
6303
- children: [
6304
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("b", { children: [tt("plan.reviewVerdict"), ":"] }),
6305
- " ",
6306
- review.verdict
6307
- ]
6308
- }),
6309
- review.issues.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
6310
- style: {
6311
- margin: 0,
6312
- paddingLeft: 18,
6313
- fontSize: 12
6314
- },
6315
- children: review.issues.map((issue, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
6316
- style: { color: severityColor(issue.severity) },
6475
+ style: { fontWeight: 600 },
6476
+ children: "润色 / 修订 — 在右上角打开工作区:左栏原文可直接选中文字做局部修订,右栏输入指令后预览,确认后再应用(未应用不改动原稿)"
6477
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6478
+ className: panel_module_css_default.row,
6479
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
6480
+ type: "button",
6481
+ className: `${panel_module_css_default.button} ${panel_module_css_default.buttonPrimary}`,
6482
+ disabled: busy || busyAny,
6483
+ onClick: () => {
6484
+ openWorkspace(chapter.no);
6485
+ },
6317
6486
  children: [
6318
- "[",
6319
- issue.severity,
6320
- "] ",
6321
- issue.item,
6322
- " → ",
6323
- issue.suggestion
6487
+ tt("plan.rewrite"),
6488
+ " / ",
6489
+ tt("plan.polish")
6324
6490
  ]
6325
- }, i))
6326
- })
6327
- ]
6328
- }),
6329
- (chapter.status === "rejected" || chapter.status === "written" || chapter.status === "approved") && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6330
- style: {
6331
- display: "flex",
6332
- flexDirection: "column",
6333
- gap: 6
6334
- },
6335
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6336
- className: panel_module_css_default.meta,
6337
- style: { fontWeight: 600 },
6338
- children: "润色 / 修订 — 在右上角打开工作区:左栏原文可直接选中文字做局部修订,右栏输入指令后预览,确认后再应用(未应用不改动原稿)"
6339
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6340
- className: panel_module_css_default.row,
6341
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
6342
- type: "button",
6343
- className: `${panel_module_css_default.button} ${panel_module_css_default.buttonPrimary}`,
6344
- disabled: busy || busyAny,
6345
- onClick: () => {
6346
- openWorkspace(chapter.no);
6347
- },
6348
- children: [
6349
- tt("plan.rewrite"),
6350
- " / ",
6351
- tt("plan.polish")
6352
- ]
6353
- })
6354
- })]
6355
- })
6356
- ]
6357
- })
6358
- ]
6359
- }),
6360
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6361
- className: `${panel_module_css_default.badge} ${badge.cls}`,
6362
- children: badge.label
6363
- }),
6364
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6365
- className: panel_module_css_default.chapterActions,
6366
- children: [
6367
- (chapter.status === "pending" || chapter.status === "error") && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6368
- type: "button",
6369
- className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall} ${panel_module_css_default.buttonPrimary}`,
6370
- disabled: busy || busyAny,
6371
- onClick: () => {
6372
- handleWriteChapter(chapter.no, true);
6373
- },
6374
- children: tt("plan.write")
6375
- }),
6376
- (chapter.status === "written" || chapter.status === "rejected") && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6377
- type: "button",
6378
- className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
6379
- disabled: busy || busyAny,
6380
- onClick: () => {
6381
- handleReview(chapter.no);
6382
- },
6383
- children: tt("plan.review")
6384
- }),
6385
- chapter.status === "written" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6386
- type: "button",
6387
- className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
6388
- disabled: busy || busyAny,
6389
- onClick: () => {
6390
- handleApprove(chapter.no);
6391
- },
6392
- children: tt("plan.approve")
6393
- }),
6394
- (chapter.status === "written" || chapter.status === "rejected" || chapter.status === "approved") && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6395
- type: "button",
6396
- className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
6397
- disabled: busy || busyAny,
6398
- onClick: () => {
6399
- openWorkspace(chapter.no);
6400
- },
6401
- title: "手动编辑正文 → AI 审查 → 保存",
6402
- children: "✏️ 编辑"
6403
- }),
6404
- (chapter.status === "written" || chapter.status === "rejected" || chapter.status === "approved") && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6405
- type: "button",
6406
- className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
6407
- disabled: busy || busyAny,
6408
- onClick: () => {
6409
- openWorkspace(chapter.no);
6410
- },
6411
- children: tt("plan.polish")
6412
- }),
6413
- chapter.status === "rejected" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6414
- type: "button",
6415
- className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
6416
- disabled: busy || busyAny,
6417
- onClick: () => {
6418
- openWorkspace(chapter.no);
6419
- },
6420
- title: "按审稿意见修订(自动带入意见)",
6421
- children: "按意见修订"
6422
- }),
6423
- chapter.status === "rejected" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6424
- type: "button",
6425
- className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
6426
- disabled: busy || busyAny,
6427
- onClick: () => {
6428
- handleWriteChapter(chapter.no, true);
6429
- },
6430
- title: "整章重新生成",
6431
- children: "重新生成"
6432
- })
6433
- ]
6434
- })
6435
- ]
6436
- }, chapter.no);
6437
- })]
6438
- }, group.no);
6439
- })
6440
- })]
6441
- }),
6442
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6443
- className: panel_module_css_default.card,
6444
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6445
- className: panel_module_css_default.cardTitle,
6446
- children: tt("plan.progress")
6447
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6448
- className: panel_module_css_default.progress,
6449
- children: [progress.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6450
- className: panel_module_css_default.meta,
6451
- children: tt("progress.empty")
6452
- }), progress.map((line) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6453
- className: line.kind === "done" ? panel_module_css_default.progressLineDone : line.kind === "error" ? panel_module_css_default.progressLineError : line.live === true ? panel_module_css_default.progressLineLive : panel_module_css_default.progressLine,
6454
- children: [line.live === true && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6455
- className: panel_module_css_default.progressBar,
6456
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6457
- className: panel_module_css_default.progressBarFill,
6458
- style: { width: `${Math.round((line.ratio ?? 0) * 100)}%` }
6459
- })
6460
- }), line.text]
6461
- }, line.id))]
6462
- })]
6463
- })
6464
- ] }),
6465
- activeTab === "bible" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6466
- className: panel_module_css_default.card,
6467
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6468
- className: panel_module_css_default.row,
6469
- style: { justifyContent: "space-between" },
6470
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6471
- className: panel_module_css_default.cardTitle,
6472
- children: tt("bible.title")
6473
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6474
- type: "button",
6475
- className: `${panel_module_css_default.button} ${panel_module_css_default.buttonPrimary}`,
6476
- disabled: busy,
6477
- onClick: () => {
6478
- handleBible();
6479
- },
6480
- children: tt("bible.gen")
6481
- })]
6482
- }), bible === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6483
- className: panel_module_css_default.meta,
6484
- children: tt("bible.none")
6485
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6486
- style: {
6487
- display: "flex",
6488
- flexDirection: "column",
6489
- gap: 10
6490
- },
6491
- children: [
6492
- bible.genre !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [
6493
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("b", { children: [tt("bible.genre"), ":"] }),
6494
- " ",
6495
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6496
- className: panel_module_css_default.meta,
6497
- children: bible.genre
6498
- })
6499
- ] }),
6500
- bible.worldRules.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6501
- style: {
6502
- border: "1px solid var(--nf-border)",
6503
- borderRadius: 10,
6504
- padding: "8px 10px"
6505
- },
6506
- children: [
6507
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6508
- className: panel_module_css_default.row,
6509
- style: { justifyContent: "space-between" },
6510
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("b", { children: [
6511
- tt("bible.worldRules"),
6512
- "(",
6513
- bible.worldRules.length,
6514
- ")"
6515
- ] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6516
- type: "button",
6517
- className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
6518
- onClick: () => {
6519
- setWorldRulesDraft(bible.worldRules.join("\n"));
6520
- },
6521
- children: "编辑"
6522
- })]
6523
- }),
6524
- worldRulesDraft !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6525
- style: {
6526
- display: "flex",
6527
- flexDirection: "column",
6528
- gap: 6,
6529
- marginTop: 6
6530
- },
6531
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
6532
- className: panel_module_css_default.textarea,
6533
- style: { minHeight: 120 },
6534
- value: worldRulesDraft,
6535
- onChange: (e) => {
6536
- setWorldRulesDraft(e.target.value);
6537
- },
6538
- placeholder: "每条规则一行…"
6539
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6540
- className: panel_module_css_default.row,
6541
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6542
- type: "button",
6543
- className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall} ${panel_module_css_default.buttonPrimary}`,
6544
- disabled: busy,
6545
- onClick: () => {
6546
- handleSaveWorldRules();
6547
- },
6548
- children: "保存规则"
6549
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6550
- type: "button",
6551
- className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
6552
- onClick: () => {
6553
- setWorldRulesDraft("");
6554
- },
6555
- children: "取消"
6556
- })]
6491
+ })
6492
+ })]
6493
+ })
6494
+ ]
6495
+ })
6496
+ ]
6497
+ }),
6498
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6499
+ className: `${panel_module_css_default.badge} ${badge.cls}`,
6500
+ children: badge.label
6501
+ }),
6502
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6503
+ className: panel_module_css_default.chapterActions,
6504
+ children: [
6505
+ (chapter.status === "pending" || chapter.status === "error") && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6506
+ type: "button",
6507
+ className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall} ${panel_module_css_default.buttonPrimary}`,
6508
+ disabled: busy || busyAny,
6509
+ onClick: () => {
6510
+ handleWriteChapter(chapter.no, true);
6511
+ },
6512
+ children: tt("plan.write")
6513
+ }),
6514
+ (chapter.status === "written" || chapter.status === "rejected") && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6515
+ type: "button",
6516
+ className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
6517
+ disabled: busy || busyAny,
6518
+ onClick: () => {
6519
+ handleReview(chapter.no);
6520
+ },
6521
+ children: tt("plan.review")
6522
+ }),
6523
+ chapter.status === "written" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6524
+ type: "button",
6525
+ className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
6526
+ disabled: busy || busyAny,
6527
+ onClick: () => {
6528
+ handleApprove(chapter.no);
6529
+ },
6530
+ children: tt("plan.approve")
6531
+ }),
6532
+ (chapter.status === "written" || chapter.status === "rejected" || chapter.status === "approved") && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6533
+ type: "button",
6534
+ className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
6535
+ disabled: busy || busyAny,
6536
+ onClick: () => {
6537
+ openWorkspace(chapter.no);
6538
+ },
6539
+ title: "手动编辑正文 → AI 审查 → 保存",
6540
+ children: "✏️ 编辑"
6541
+ }),
6542
+ (chapter.status === "written" || chapter.status === "rejected" || chapter.status === "approved") && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6543
+ type: "button",
6544
+ className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
6545
+ disabled: busy || busyAny,
6546
+ onClick: () => {
6547
+ openWorkspace(chapter.no);
6548
+ },
6549
+ children: tt("plan.polish")
6550
+ }),
6551
+ chapter.status === "rejected" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6552
+ type: "button",
6553
+ className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
6554
+ disabled: busy || busyAny,
6555
+ onClick: () => {
6556
+ openWorkspace(chapter.no);
6557
+ },
6558
+ title: "按审稿意见修订(自动带入意见)",
6559
+ children: "按意见修订"
6560
+ }),
6561
+ chapter.status === "rejected" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6562
+ type: "button",
6563
+ className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
6564
+ disabled: busy || busyAny,
6565
+ onClick: () => {
6566
+ handleWriteChapter(chapter.no, true);
6567
+ },
6568
+ title: "整章重新生成",
6569
+ children: "重新生成"
6570
+ })
6571
+ ]
6572
+ })
6573
+ ]
6574
+ }, chapter.no);
6557
6575
  })]
6558
- }),
6559
- worldRulesDraft === "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
6560
- style: {
6561
- margin: "4px 0 0",
6562
- paddingLeft: 18,
6563
- fontSize: 12
6564
- },
6565
- children: bible.worldRules.map((r, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: r }, i))
6566
- })
6567
- ]
6568
- }),
6569
- bible.characters.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("b", { children: [
6570
- tt("bible.characters"),
6571
- "(",
6572
- bible.characters.length,
6573
- ")"
6574
- ] }), bible.characters.map((card) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6575
- style: {
6576
- marginTop: 4,
6577
- fontSize: 12
6578
- },
6579
- children: [
6580
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", { children: card.name }),
6581
- " ",
6582
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
6583
- className: panel_module_css_default.meta,
6584
- children: [
6585
- "[",
6586
- card.role,
6587
- "] ",
6588
- card.traits.join("、")
6589
- ]
6590
- }),
6591
- card.goals !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6592
- className: panel_module_css_default.meta,
6593
- children: ["目标:", card.goals]
6594
- }),
6595
- card.relations !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6596
- className: panel_module_css_default.meta,
6597
- children: ["关系:", card.relations]
6598
- })
6599
- ]
6600
- }, card.name))] }),
6601
- bible.redLines.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("b", { children: [
6602
- tt("bible.redLines"),
6603
- "(",
6604
- bible.redLines.length,
6605
- ")"
6606
- ] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
6607
- style: {
6608
- margin: 0,
6609
- paddingLeft: 18,
6610
- fontSize: 12,
6611
- color: "var(--nf-error)"
6612
- },
6613
- children: bible.redLines.map((r, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: r }, i))
6614
- })] }),
6615
- bible.style.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("b", { children: [
6616
- tt("bible.style"),
6617
- "(",
6618
- bible.style.length,
6619
- ")"
6620
- ] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
6621
- style: {
6622
- margin: 0,
6623
- paddingLeft: 18,
6624
- fontSize: 12
6625
- },
6626
- children: bible.style.map((r, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: r }, i))
6627
- })] })
6628
- ]
6629
- })]
6630
- }) }),
6631
- activeTab === "world" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(WorldTab, {
6632
- api,
6633
- world: project?.world,
6634
- onChanged: (w) => {
6635
- setProject((prev) => prev === null ? prev : {
6636
- ...prev,
6637
- world: w,
6638
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
6639
- });
6640
- pushProgress(`大世界已保存:${w.realms.length} 境界 · ${w.regions.length} 区域 · ${w.factions.length} 势力`, "done");
6641
- }
6642
- }),
6643
- activeTab === "characters" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6644
- className: panel_module_css_default.card,
6645
- children: [
6576
+ }, group.no);
6577
+ })
6578
+ })]
6579
+ }),
6646
6580
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6581
+ className: panel_module_css_default.card,
6582
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6583
+ className: panel_module_css_default.cardTitle,
6584
+ children: tt("plan.progress")
6585
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6586
+ className: panel_module_css_default.progress,
6587
+ children: [progress.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6588
+ className: panel_module_css_default.meta,
6589
+ children: tt("progress.empty")
6590
+ }), progress.map((line) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6591
+ className: line.kind === "done" ? panel_module_css_default.progressLineDone : line.kind === "error" ? panel_module_css_default.progressLineError : line.live === true ? panel_module_css_default.progressLineLive : panel_module_css_default.progressLine,
6592
+ children: [line.live === true && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6593
+ className: panel_module_css_default.progressBar,
6594
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6595
+ className: panel_module_css_default.progressBarFill,
6596
+ style: { width: `${Math.round((line.ratio ?? 0) * 100)}%` }
6597
+ })
6598
+ }), line.text]
6599
+ }, line.id))]
6600
+ })]
6601
+ })
6602
+ ] }),
6603
+ activeTab === "bible" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6604
+ className: panel_module_css_default.card,
6605
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6647
6606
  className: panel_module_css_default.row,
6648
6607
  style: { justifyContent: "space-between" },
6649
6608
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6650
6609
  className: panel_module_css_default.cardTitle,
6651
- children: "人物志(当前状态)"
6652
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6653
- className: panel_module_css_default.row,
6654
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6655
- type: "button",
6656
- className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
6657
- disabled: busy || doneCount === 0,
6658
- onClick: () => {
6659
- handleFactsBackfill();
6660
- },
6661
- title: "历史章节(编年录功能上线前生成的)批量抽取事实",
6662
- children: "📥 回填编年录"
6663
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6664
- type: "button",
6665
- className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall} ${panel_module_css_default.buttonPrimary}`,
6666
- disabled: busy || (project?.facts ?? []).length === 0,
6667
- onClick: () => {
6668
- handleCharactersRefresh();
6669
- },
6670
- children: "↻ 从编年录刷新"
6671
- })]
6610
+ children: tt("bible.title")
6611
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6612
+ type: "button",
6613
+ className: `${panel_module_css_default.button} ${panel_module_css_default.buttonPrimary}`,
6614
+ disabled: busy,
6615
+ onClick: () => {
6616
+ handleBible();
6617
+ },
6618
+ children: tt("bible.gen")
6672
6619
  })]
6673
- }),
6674
- charCards === null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6675
- className: panel_module_css_default.meta,
6676
- children: (project?.facts ?? []).length === 0 ? "暂无编年录(生成章节后自动积累人物状态/境界/资源/关系等事实),刷新按钮将在有事实后可用。" : "点击「从编年录刷新」聚合各人物当前状态(境界/资源/伤势/心境)。"
6677
- }) : charCards.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6620
+ }), bible === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6678
6621
  className: panel_module_css_default.meta,
6679
- children: "未识别到人物信息。"
6680
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6622
+ children: tt("bible.none")
6623
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6681
6624
  style: {
6682
6625
  display: "flex",
6683
6626
  flexDirection: "column",
6684
- gap: 6
6627
+ gap: 10
6685
6628
  },
6686
- children: charCards.map((card) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6687
- style: {
6688
- border: "1px solid var(--nf-border)",
6689
- borderRadius: 8,
6690
- padding: "6px 10px",
6691
- fontSize: 12
6692
- },
6693
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6694
- className: panel_module_css_default.row,
6695
- style: { justifyContent: "space-between" },
6696
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", { children: card.name }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
6697
- className: panel_module_css_default.meta,
6698
- children: [
6699
- card.role === "protagonist" ? "主角" : card.role === "supporting" ? "配角" : card.role === "antagonist" ? "反派" : "其他",
6700
- " · 出场 ",
6701
- card.appearances,
6702
- " 次 · 最近 第 ",
6703
- card.lastChapter,
6704
- " 章"
6705
- ]
6706
- })]
6707
- }), card.status !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6708
- className: panel_module_css_default.meta,
6709
- children: ["状态:", card.status]
6710
- })]
6711
- }, card.name))
6712
- }),
6713
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6714
- className: panel_module_css_default.meta,
6715
- children: "人物志由「道藏」人物名单 + 「编年录」聚合而来,随章节生成自动保持最新。"
6716
- })
6717
- ]
6718
- }),
6719
- activeTab === "assetsGenre" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AssetsTab, {
6720
- api,
6721
- initialTab: "genre"
6722
- }),
6723
- activeTab === "assetsProgression" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AssetsTab, {
6724
- api,
6725
- initialTab: "progression"
6726
- }),
6727
- activeTab === "assetsTemplates" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AssetsTab, {
6728
- api,
6729
- initialTab: "templates"
6730
- }),
6731
- activeTab === "assetsRules" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AssetsTab, {
6732
- api,
6733
- initialTab: "rules"
6734
- }),
6735
- activeTab === "assetsStyle" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AssetsTab, {
6736
- api,
6737
- initialTab: "style"
6738
- }),
6739
- activeTab === "foreshadow" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6740
- className: panel_module_css_default.card,
6741
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6742
- className: panel_module_css_default.row,
6743
- style: { justifyContent: "space-between" },
6744
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
6745
- className: panel_module_css_default.cardTitle,
6746
6629
  children: [
6747
- tt("foreshadow.title"),
6748
- "(",
6749
- foreshadows.length,
6750
- ")"
6751
- ]
6752
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6753
- type: "button",
6754
- className: `${panel_module_css_default.button} ${panel_module_css_default.buttonPrimary}`,
6755
- disabled: busy,
6756
- onClick: () => {
6757
- handleSuggestForeshadows();
6758
- },
6759
- children: tt("foreshadow.suggest")
6760
- })]
6761
- }), foreshadows.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6762
- className: panel_module_css_default.meta,
6763
- children: tt("foreshadow.none")
6764
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6765
- className: panel_module_css_default.chapterList,
6766
- children: foreshadows.map((f) => {
6767
- const statusLabel = {
6768
- planned: tt("foreshadow.planned"),
6769
- planted: tt("foreshadow.planted"),
6770
- progressing: tt("foreshadow.progressing"),
6771
- resolved: tt("foreshadow.resolved"),
6772
- abandoned: tt("foreshadow.abandoned")
6773
- }[f.status];
6774
- const statusColor = f.status === "resolved" ? "var(--nf-success)" : f.status === "planted" || f.status === "progressing" ? "var(--nf-accent)" : f.status === "abandoned" ? "var(--nf-text-3)" : "var(--nf-info)";
6775
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6776
- className: panel_module_css_default.chapter,
6777
- children: [
6778
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6779
- className: panel_module_css_default.chapterMain,
6780
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6781
- className: panel_module_css_default.chapterTitle,
6782
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: f.description })
6783
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6630
+ bible.genre !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [
6631
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("b", { children: [tt("bible.genre"), ":"] }),
6632
+ " ",
6633
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6634
+ className: panel_module_css_default.meta,
6635
+ children: bible.genre
6636
+ })
6637
+ ] }),
6638
+ bible.worldRules.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6639
+ style: {
6640
+ border: "1px solid var(--nf-border)",
6641
+ borderRadius: 10,
6642
+ padding: "8px 10px"
6643
+ },
6644
+ children: [
6645
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6646
+ className: panel_module_css_default.row,
6647
+ style: { justifyContent: "space-between" },
6648
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("b", { children: [
6649
+ tt("bible.worldRules"),
6650
+ "(",
6651
+ bible.worldRules.length,
6652
+ ")"
6653
+ ] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6654
+ type: "button",
6655
+ className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
6656
+ onClick: () => {
6657
+ setWorldRulesDraft(bible.worldRules.join("\n"));
6658
+ },
6659
+ children: "编辑"
6660
+ })]
6661
+ }),
6662
+ worldRulesDraft !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6663
+ style: {
6664
+ display: "flex",
6665
+ flexDirection: "column",
6666
+ gap: 6,
6667
+ marginTop: 6
6668
+ },
6669
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
6670
+ className: panel_module_css_default.textarea,
6671
+ style: { minHeight: 120 },
6672
+ value: worldRulesDraft,
6673
+ onChange: (e) => {
6674
+ setWorldRulesDraft(e.target.value);
6675
+ },
6676
+ placeholder: "每条规则一行…"
6677
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6678
+ className: panel_module_css_default.row,
6679
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6680
+ type: "button",
6681
+ className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall} ${panel_module_css_default.buttonPrimary}`,
6682
+ disabled: busy,
6683
+ onClick: () => {
6684
+ handleSaveWorldRules();
6685
+ },
6686
+ children: "保存规则"
6687
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6688
+ type: "button",
6689
+ className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
6690
+ onClick: () => {
6691
+ setWorldRulesDraft("");
6692
+ },
6693
+ children: "取消"
6694
+ })]
6695
+ })]
6696
+ }),
6697
+ worldRulesDraft === "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
6698
+ style: {
6699
+ margin: "4px 0 0",
6700
+ paddingLeft: 18,
6701
+ fontSize: 12
6702
+ },
6703
+ children: bible.worldRules.map((r, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: r }, i))
6704
+ })
6705
+ ]
6706
+ }),
6707
+ bible.characters.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("b", { children: [
6708
+ tt("bible.characters"),
6709
+ "(",
6710
+ bible.characters.length,
6711
+ ")"
6712
+ ] }), bible.characters.map((card) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6713
+ style: {
6714
+ marginTop: 4,
6715
+ fontSize: 12
6716
+ },
6717
+ children: [
6718
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", { children: card.name }),
6719
+ " ",
6720
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
6784
6721
  className: panel_module_css_default.meta,
6785
6722
  children: [
6786
- f.plantedChapter !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
6787
- tt("foreshadow.plantedAt"),
6788
- " 第",
6789
- f.plantedChapter,
6790
- "章 · "
6791
- ] }),
6792
- f.targetChapter !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
6793
- tt("foreshadow.target"),
6794
- " 第",
6795
- f.targetChapter,
6796
- "章 · "
6797
- ] }),
6798
- f.resolvedNote !== void 0 && f.resolvedNote !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
6799
- "回收:",
6800
- f.resolvedNote,
6801
- " · "
6802
- ] })
6723
+ "[",
6724
+ card.role,
6725
+ "] ",
6726
+ card.traits.join("、")
6803
6727
  ]
6804
- })]
6805
- }),
6806
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6807
- className: panel_module_css_default.badge,
6808
- style: {
6809
- borderColor: statusColor,
6810
- color: statusColor
6728
+ }),
6729
+ card.goals !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6730
+ className: panel_module_css_default.meta,
6731
+ children: ["目标:", card.goals]
6732
+ }),
6733
+ card.relations !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6734
+ className: panel_module_css_default.meta,
6735
+ children: ["关系:", card.relations]
6736
+ })
6737
+ ]
6738
+ }, card.name))] }),
6739
+ bible.redLines.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("b", { children: [
6740
+ tt("bible.redLines"),
6741
+ "(",
6742
+ bible.redLines.length,
6743
+ ")"
6744
+ ] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
6745
+ style: {
6746
+ margin: 0,
6747
+ paddingLeft: 18,
6748
+ fontSize: 12,
6749
+ color: "var(--nf-error)"
6750
+ },
6751
+ children: bible.redLines.map((r, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: r }, i))
6752
+ })] }),
6753
+ bible.style.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("b", { children: [
6754
+ tt("bible.style"),
6755
+ "(",
6756
+ bible.style.length,
6757
+ ")"
6758
+ ] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
6759
+ style: {
6760
+ margin: 0,
6761
+ paddingLeft: 18,
6762
+ fontSize: 12
6763
+ },
6764
+ children: bible.style.map((r, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: r }, i))
6765
+ })] })
6766
+ ]
6767
+ })]
6768
+ }) }),
6769
+ activeTab === "world" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(WorldTab, {
6770
+ api,
6771
+ world: project?.world,
6772
+ onChanged: (w) => {
6773
+ setProject((prev) => prev === null ? prev : {
6774
+ ...prev,
6775
+ world: w,
6776
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
6777
+ });
6778
+ pushProgress(`大世界已保存:${w.realms.length} 境界 · ${w.regions.length} 区域 · ${w.factions.length} 势力`, "done");
6779
+ }
6780
+ }),
6781
+ activeTab === "characters" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6782
+ className: panel_module_css_default.card,
6783
+ children: [
6784
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6785
+ className: panel_module_css_default.row,
6786
+ style: { justifyContent: "space-between" },
6787
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6788
+ className: panel_module_css_default.cardTitle,
6789
+ children: "人物志(当前状态)"
6790
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6791
+ className: panel_module_css_default.row,
6792
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6793
+ type: "button",
6794
+ className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
6795
+ disabled: busy || doneCount === 0,
6796
+ onClick: () => {
6797
+ handleFactsBackfill();
6811
6798
  },
6812
- children: statusLabel
6813
- }),
6814
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6799
+ title: "历史章节(编年录功能上线前生成的)批量抽取事实",
6800
+ children: "📥 回填编年录"
6801
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6802
+ type: "button",
6803
+ className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall} ${panel_module_css_default.buttonPrimary}`,
6804
+ disabled: busy || (project?.facts ?? []).length === 0,
6805
+ onClick: () => {
6806
+ handleCharactersRefresh();
6807
+ },
6808
+ children: "↻ 从编年录刷新"
6809
+ })]
6810
+ })]
6811
+ }),
6812
+ charCards === null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6813
+ className: panel_module_css_default.meta,
6814
+ children: (project?.facts ?? []).length === 0 ? "暂无编年录(生成章节后自动积累人物状态/境界/资源/关系等事实),刷新按钮将在有事实后可用。" : "点击「从编年录刷新」聚合各人物当前状态(境界/资源/伤势/心境)。"
6815
+ }) : charCards.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6816
+ className: panel_module_css_default.meta,
6817
+ children: "未识别到人物信息。"
6818
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6819
+ style: {
6820
+ display: "flex",
6821
+ flexDirection: "column",
6822
+ gap: 6
6823
+ },
6824
+ children: charCards.map((card) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6825
+ style: {
6826
+ border: "1px solid var(--nf-border)",
6827
+ borderRadius: 8,
6828
+ padding: "6px 10px",
6829
+ fontSize: 12
6830
+ },
6831
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6815
6832
  className: panel_module_css_default.row,
6816
- style: { gap: 4 },
6817
- children: [f.status === "planned" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6818
- type: "button",
6819
- className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
6820
- disabled: busy,
6821
- onClick: () => {
6822
- api.foreshadow({
6823
- id: f.id,
6824
- status: "planted",
6825
- plantedChapter: doneCount + 1
6826
- }).then((r) => setProject((prev) => prev === null ? prev : {
6827
- ...prev,
6828
- foreshadows: r.foreshadows
6829
- }));
6830
- },
6831
- children: tt("foreshadow.setPlanted")
6832
- }), (f.status === "planted" || f.status === "progressing") && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6833
- type: "button",
6834
- className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
6835
- disabled: busy,
6836
- onClick: () => {
6837
- api.foreshadow({
6838
- id: f.id,
6839
- status: "resolved",
6840
- resolvedNote: `第${doneCount}章回收`
6841
- }).then((r) => setProject((prev) => prev === null ? prev : {
6842
- ...prev,
6843
- foreshadows: r.foreshadows
6844
- }));
6845
- },
6846
- children: tt("foreshadow.setResolved")
6833
+ style: { justifyContent: "space-between" },
6834
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", { children: card.name }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
6835
+ className: panel_module_css_default.meta,
6836
+ children: [
6837
+ card.role === "protagonist" ? "主角" : card.role === "supporting" ? "配角" : card.role === "antagonist" ? "反派" : "其他",
6838
+ " · 出场 ",
6839
+ card.appearances,
6840
+ " 次 · 最近 第 ",
6841
+ card.lastChapter,
6842
+ " 章"
6843
+ ]
6847
6844
  })]
6848
- })
6849
- ]
6850
- }, f.id);
6851
- })
6852
- })]
6853
- }),
6854
- activeTab === "settings" && configDraft !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6855
- className: panel_module_css_default.card,
6856
- children: [
6857
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6858
- className: panel_module_css_default.cardTitle,
6859
- children: tt("settings.title")
6860
- }),
6861
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6862
- className: panel_module_css_default.field,
6863
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
6864
- className: panel_module_css_default.fieldLabel,
6865
- children: tt("settings.outlinePath")
6866
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
6867
- className: panel_module_css_default.input,
6868
- value: configDraft.outlinePath,
6869
- onChange: (e) => {
6870
- setConfigDraft({
6871
- ...configDraft,
6872
- outlinePath: e.target.value
6873
- });
6874
- }
6875
- })]
6876
- }),
6877
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6878
- className: panel_module_css_default.field,
6879
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
6880
- className: panel_module_css_default.fieldLabel,
6881
- children: tt("settings.outputDir")
6882
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
6883
- className: panel_module_css_default.input,
6884
- value: configDraft.outputDir,
6885
- onChange: (e) => {
6886
- setConfigDraft({
6887
- ...configDraft,
6888
- outputDir: e.target.value
6889
- });
6890
- }
6891
- })]
6892
- }),
6893
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6845
+ }), card.status !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6846
+ className: panel_module_css_default.meta,
6847
+ children: ["状态:", card.status]
6848
+ })]
6849
+ }, card.name))
6850
+ }),
6851
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6852
+ className: panel_module_css_default.meta,
6853
+ children: "人物志由「道藏」人物名单 + 「编年录」聚合而来,随章节生成自动保持最新。"
6854
+ })
6855
+ ]
6856
+ }),
6857
+ activeTab === "assetsGenre" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AssetsTab, {
6858
+ api,
6859
+ initialTab: "genre"
6860
+ }),
6861
+ activeTab === "assetsProgression" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AssetsTab, {
6862
+ api,
6863
+ initialTab: "progression"
6864
+ }),
6865
+ activeTab === "assetsTemplates" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AssetsTab, {
6866
+ api,
6867
+ initialTab: "templates"
6868
+ }),
6869
+ activeTab === "assetsRules" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AssetsTab, {
6870
+ api,
6871
+ initialTab: "rules"
6872
+ }),
6873
+ activeTab === "assetsStyle" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AssetsTab, {
6874
+ api,
6875
+ initialTab: "style"
6876
+ }),
6877
+ activeTab === "foreshadow" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6878
+ className: panel_module_css_default.card,
6879
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6894
6880
  className: panel_module_css_default.row,
6895
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6896
- className: panel_module_css_default.field,
6897
- style: { flex: 1 },
6898
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
6899
- className: panel_module_css_default.fieldLabel,
6900
- children: tt("settings.provider")
6901
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
6902
- className: panel_module_css_default.input,
6903
- value: configDraft.provider,
6904
- onChange: (e) => {
6905
- setConfigDraft({
6906
- ...configDraft,
6907
- provider: e.target.value
6908
- });
6909
- }
6910
- })]
6911
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6912
- className: panel_module_css_default.field,
6913
- style: { flex: 1 },
6914
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
6915
- className: panel_module_css_default.fieldLabel,
6916
- children: tt("settings.model")
6917
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
6918
- className: panel_module_css_default.input,
6919
- value: configDraft.model,
6920
- onChange: (e) => {
6921
- setConfigDraft({
6922
- ...configDraft,
6923
- model: e.target.value
6924
- });
6925
- }
6926
- })]
6881
+ style: { justifyContent: "space-between" },
6882
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
6883
+ className: panel_module_css_default.cardTitle,
6884
+ children: [
6885
+ tt("foreshadow.title"),
6886
+ "(",
6887
+ foreshadows.length,
6888
+ ")"
6889
+ ]
6890
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6891
+ type: "button",
6892
+ className: `${panel_module_css_default.button} ${panel_module_css_default.buttonPrimary}`,
6893
+ disabled: busy,
6894
+ onClick: () => {
6895
+ handleSuggestForeshadows();
6896
+ },
6897
+ children: tt("foreshadow.suggest")
6927
6898
  })]
6928
- }),
6929
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6930
- className: panel_module_css_default.row,
6931
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6899
+ }), foreshadows.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6900
+ className: panel_module_css_default.meta,
6901
+ children: tt("foreshadow.none")
6902
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6903
+ className: panel_module_css_default.chapterList,
6904
+ children: foreshadows.map((f) => {
6905
+ const statusLabel = {
6906
+ planned: tt("foreshadow.planned"),
6907
+ planted: tt("foreshadow.planted"),
6908
+ progressing: tt("foreshadow.progressing"),
6909
+ resolved: tt("foreshadow.resolved"),
6910
+ abandoned: tt("foreshadow.abandoned")
6911
+ }[f.status];
6912
+ const statusColor = f.status === "resolved" ? "var(--nf-success)" : f.status === "planted" || f.status === "progressing" ? "var(--nf-accent)" : f.status === "abandoned" ? "var(--nf-text-3)" : "var(--nf-info)";
6913
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6914
+ className: panel_module_css_default.chapter,
6915
+ children: [
6916
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6917
+ className: panel_module_css_default.chapterMain,
6918
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6919
+ className: panel_module_css_default.chapterTitle,
6920
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: f.description })
6921
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6922
+ className: panel_module_css_default.meta,
6923
+ children: [
6924
+ f.plantedChapter !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
6925
+ tt("foreshadow.plantedAt"),
6926
+ " 第",
6927
+ f.plantedChapter,
6928
+ "章 · "
6929
+ ] }),
6930
+ f.targetChapter !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
6931
+ tt("foreshadow.target"),
6932
+ " 第",
6933
+ f.targetChapter,
6934
+ "章 · "
6935
+ ] }),
6936
+ f.resolvedNote !== void 0 && f.resolvedNote !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
6937
+ "回收:",
6938
+ f.resolvedNote,
6939
+ " · "
6940
+ ] })
6941
+ ]
6942
+ })]
6943
+ }),
6944
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6945
+ className: panel_module_css_default.badge,
6946
+ style: {
6947
+ borderColor: statusColor,
6948
+ color: statusColor
6949
+ },
6950
+ children: statusLabel
6951
+ }),
6952
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6953
+ className: panel_module_css_default.row,
6954
+ style: { gap: 4 },
6955
+ children: [f.status === "planned" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6956
+ type: "button",
6957
+ className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
6958
+ disabled: busy,
6959
+ onClick: () => {
6960
+ api.foreshadow({
6961
+ id: f.id,
6962
+ status: "planted",
6963
+ plantedChapter: doneCount + 1
6964
+ }).then((r) => setProject((prev) => prev === null ? prev : {
6965
+ ...prev,
6966
+ foreshadows: r.foreshadows
6967
+ }));
6968
+ },
6969
+ children: tt("foreshadow.setPlanted")
6970
+ }), (f.status === "planted" || f.status === "progressing") && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6971
+ type: "button",
6972
+ className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
6973
+ disabled: busy,
6974
+ onClick: () => {
6975
+ api.foreshadow({
6976
+ id: f.id,
6977
+ status: "resolved",
6978
+ resolvedNote: `第${doneCount}章回收`
6979
+ }).then((r) => setProject((prev) => prev === null ? prev : {
6980
+ ...prev,
6981
+ foreshadows: r.foreshadows
6982
+ }));
6983
+ },
6984
+ children: tt("foreshadow.setResolved")
6985
+ })]
6986
+ })
6987
+ ]
6988
+ }, f.id);
6989
+ })
6990
+ })]
6991
+ }),
6992
+ activeTab === "settings" && configDraft !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6993
+ className: panel_module_css_default.card,
6994
+ children: [
6995
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6996
+ className: panel_module_css_default.cardTitle,
6997
+ children: tt("settings.title")
6998
+ }),
6999
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6932
7000
  className: panel_module_css_default.field,
6933
- style: { flex: 1 },
6934
7001
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
6935
7002
  className: panel_module_css_default.fieldLabel,
6936
- children: tt("settings.chapterChars")
7003
+ children: tt("settings.outlinePath")
6937
7004
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
6938
7005
  className: panel_module_css_default.input,
6939
- type: "number",
6940
- min: 1e3,
6941
- max: 2e4,
6942
- value: configDraft.chapterChars,
7006
+ value: configDraft.outlinePath,
6943
7007
  onChange: (e) => {
6944
7008
  setConfigDraft({
6945
7009
  ...configDraft,
6946
- chapterChars: Number(e.target.value)
7010
+ outlinePath: e.target.value
6947
7011
  });
6948
7012
  }
6949
7013
  })]
6950
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7014
+ }),
7015
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6951
7016
  className: panel_module_css_default.field,
6952
- style: { flex: 1 },
6953
7017
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
6954
7018
  className: panel_module_css_default.fieldLabel,
6955
- children: tt("settings.maxTokens")
7019
+ children: tt("settings.outputDir")
6956
7020
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
6957
7021
  className: panel_module_css_default.input,
6958
- type: "number",
6959
- min: 2e3,
6960
- max: 64e3,
6961
- value: configDraft.maxTokens,
7022
+ value: configDraft.outputDir,
6962
7023
  onChange: (e) => {
6963
7024
  setConfigDraft({
6964
7025
  ...configDraft,
6965
- maxTokens: Number(e.target.value)
7026
+ outputDir: e.target.value
6966
7027
  });
6967
7028
  }
6968
7029
  })]
6969
- })]
6970
- }),
6971
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6972
- className: panel_module_css_default.row,
6973
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6974
- className: panel_module_css_default.field,
6975
- style: { flex: 1 },
6976
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
6977
- className: panel_module_css_default.fieldLabel,
6978
- children: tt("settings.reviewPassScore")
6979
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
6980
- className: panel_module_css_default.input,
6981
- type: "number",
6982
- min: 0,
6983
- max: 100,
6984
- value: configDraft.reviewPassScore,
6985
- onChange: (e) => {
6986
- setConfigDraft({
6987
- ...configDraft,
6988
- reviewPassScore: Number(e.target.value)
6989
- });
6990
- }
7030
+ }),
7031
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7032
+ className: panel_module_css_default.row,
7033
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7034
+ className: panel_module_css_default.field,
7035
+ style: { flex: 1 },
7036
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
7037
+ className: panel_module_css_default.fieldLabel,
7038
+ children: tt("settings.provider")
7039
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
7040
+ className: panel_module_css_default.input,
7041
+ value: configDraft.provider,
7042
+ onChange: (e) => {
7043
+ setConfigDraft({
7044
+ ...configDraft,
7045
+ provider: e.target.value
7046
+ });
7047
+ }
7048
+ })]
7049
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7050
+ className: panel_module_css_default.field,
7051
+ style: { flex: 1 },
7052
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
7053
+ className: panel_module_css_default.fieldLabel,
7054
+ children: tt("settings.model")
7055
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
7056
+ className: panel_module_css_default.input,
7057
+ value: configDraft.model,
7058
+ onChange: (e) => {
7059
+ setConfigDraft({
7060
+ ...configDraft,
7061
+ model: e.target.value
7062
+ });
7063
+ }
7064
+ })]
6991
7065
  })]
6992
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6993
- className: panel_module_css_default.field,
6994
- style: { flex: 1 },
6995
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
6996
- className: panel_module_css_default.fieldLabel,
6997
- children: tt("settings.autoReview")
6998
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
6999
- className: panel_module_css_default.input,
7000
- value: configDraft.autoReview ? "1" : "0",
7001
- onChange: (e) => {
7002
- setConfigDraft({
7003
- ...configDraft,
7004
- autoReview: e.target.value === "1"
7005
- });
7006
- },
7007
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
7008
- value: "1",
7009
- children: "✓ 是"
7010
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
7011
- value: "0",
7012
- children: "✗ 否"
7066
+ }),
7067
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7068
+ className: panel_module_css_default.row,
7069
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7070
+ className: panel_module_css_default.field,
7071
+ style: { flex: 1 },
7072
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
7073
+ className: panel_module_css_default.fieldLabel,
7074
+ children: tt("settings.chapterChars")
7075
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
7076
+ className: panel_module_css_default.input,
7077
+ type: "number",
7078
+ min: 1e3,
7079
+ max: 2e4,
7080
+ value: configDraft.chapterChars,
7081
+ onChange: (e) => {
7082
+ setConfigDraft({
7083
+ ...configDraft,
7084
+ chapterChars: Number(e.target.value)
7085
+ });
7086
+ }
7087
+ })]
7088
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7089
+ className: panel_module_css_default.field,
7090
+ style: { flex: 1 },
7091
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
7092
+ className: panel_module_css_default.fieldLabel,
7093
+ children: tt("settings.maxTokens")
7094
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
7095
+ className: panel_module_css_default.input,
7096
+ type: "number",
7097
+ min: 2e3,
7098
+ max: 64e3,
7099
+ value: configDraft.maxTokens,
7100
+ onChange: (e) => {
7101
+ setConfigDraft({
7102
+ ...configDraft,
7103
+ maxTokens: Number(e.target.value)
7104
+ });
7105
+ }
7013
7106
  })]
7014
7107
  })]
7015
- })]
7016
- }),
7017
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7018
- className: panel_module_css_default.row,
7019
- children: [
7020
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
7021
- type: "button",
7022
- className: `${panel_module_css_default.button} ${panel_module_css_default.buttonPrimary}`,
7023
- disabled: busy,
7024
- onClick: () => {
7025
- handleSaveConfig();
7026
- },
7027
- children: tt("settings.save")
7028
- }),
7029
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
7030
- type: "button",
7031
- className: panel_module_css_default.button,
7032
- onClick: () => {
7033
- api.openFolder();
7034
- },
7035
- children: tt("settings.openFolder")
7036
- }),
7037
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
7038
- className: panel_module_css_default.meta,
7039
- children: [
7040
- "当前:",
7041
- config?.provider,
7042
- " / ",
7043
- config?.model,
7044
- " · ",
7045
- config?.outputDir
7046
- ]
7047
- })
7048
- ]
7049
- }),
7050
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7051
- className: panel_module_css_default.row,
7052
- children: [
7053
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7054
- className: panel_module_css_default.cardTitle,
7055
- children: tt("settings.export")
7056
- }),
7057
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
7058
- type: "button",
7059
- className: panel_module_css_default.button,
7060
- disabled: busy || chapters.length === 0,
7061
- onClick: () => {
7062
- handleExport("txt");
7063
- },
7064
- children: tt("settings.exportTxt")
7065
- }),
7066
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
7067
- type: "button",
7068
- className: panel_module_css_default.button,
7069
- disabled: busy || chapters.length === 0,
7070
- onClick: () => {
7071
- handleExport("md");
7072
- },
7073
- children: tt("settings.exportMd")
7074
- })
7075
- ]
7076
- }),
7077
- (project?.facts ?? []).length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7078
- className: panel_module_css_default.card,
7079
- children: [
7080
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
7081
- className: panel_module_css_default.cardTitle,
7082
- children: [
7083
- "编年录 / 时间线(",
7084
- (project?.facts ?? []).length,
7085
- " 条)"
7086
- ]
7087
- }),
7088
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7089
- className: panel_module_css_default.meta,
7090
- children: "每章生成后自动抽取「已确立事实」(人物状态/境界资源/关系变化/伏笔落地),最近 20 条注入后续章节生成,保证长期一致。"
7091
- }),
7092
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7093
- style: {
7094
- display: "flex",
7095
- flexDirection: "column",
7096
- gap: 4,
7097
- maxHeight: 300,
7098
- overflowY: "auto",
7099
- fontSize: 12
7100
- },
7101
- children: [...project?.facts ?? []].reverse().slice(0, 60).map((fact, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7108
+ }),
7109
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7110
+ className: panel_module_css_default.row,
7111
+ children: [
7112
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7113
+ className: panel_module_css_default.field,
7114
+ style: { flex: 1 },
7115
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
7116
+ className: panel_module_css_default.fieldLabel,
7117
+ children: tt("settings.reviewPassScore")
7118
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
7119
+ className: panel_module_css_default.input,
7120
+ type: "number",
7121
+ min: 0,
7122
+ max: 100,
7123
+ value: configDraft.reviewPassScore,
7124
+ onChange: (e) => {
7125
+ setConfigDraft({
7126
+ ...configDraft,
7127
+ reviewPassScore: Number(e.target.value)
7128
+ });
7129
+ }
7130
+ })]
7131
+ }),
7132
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7133
+ className: panel_module_css_default.field,
7134
+ style: { flex: 1 },
7135
+ children: [
7136
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
7137
+ className: panel_module_css_default.fieldLabel,
7138
+ children: tt("settings.editorFontSize")
7139
+ }),
7140
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
7141
+ className: panel_module_css_default.input,
7142
+ value: editorFontSize,
7143
+ onChange: (e) => {
7144
+ changeEditorFontSize(Number(e.target.value));
7145
+ },
7146
+ children: [
7147
+ 12,
7148
+ 13,
7149
+ 14,
7150
+ 15,
7151
+ 16,
7152
+ 18,
7153
+ 20,
7154
+ 22,
7155
+ 24
7156
+ ].map((v) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("option", {
7157
+ value: v,
7158
+ children: [v, "px"]
7159
+ }, v))
7160
+ }),
7161
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7162
+ className: panel_module_css_default.meta,
7163
+ children: tt("settings.editorFontSizeHint")
7164
+ })
7165
+ ]
7166
+ }),
7167
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7168
+ className: panel_module_css_default.field,
7169
+ style: { flex: 1 },
7170
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
7171
+ className: panel_module_css_default.fieldLabel,
7172
+ children: tt("settings.autoReview")
7173
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
7174
+ className: panel_module_css_default.input,
7175
+ value: configDraft.autoReview ? "1" : "0",
7176
+ onChange: (e) => {
7177
+ setConfigDraft({
7178
+ ...configDraft,
7179
+ autoReview: e.target.value === "1"
7180
+ });
7181
+ },
7182
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
7183
+ value: "1",
7184
+ children: "✓ 是"
7185
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
7186
+ value: "0",
7187
+ children: "✗ 否"
7188
+ })]
7189
+ })]
7190
+ })
7191
+ ]
7192
+ }),
7193
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7194
+ className: panel_module_css_default.row,
7195
+ children: [
7196
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
7197
+ type: "button",
7198
+ className: `${panel_module_css_default.button} ${panel_module_css_default.buttonPrimary}`,
7199
+ disabled: busy,
7200
+ onClick: () => {
7201
+ handleSaveConfig();
7202
+ },
7203
+ children: tt("settings.save")
7204
+ }),
7205
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
7206
+ type: "button",
7207
+ className: panel_module_css_default.button,
7208
+ onClick: () => {
7209
+ api.openFolder();
7210
+ },
7211
+ children: tt("settings.openFolder")
7212
+ }),
7213
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
7214
+ className: panel_module_css_default.meta,
7215
+ children: [
7216
+ "当前:",
7217
+ config?.provider,
7218
+ " / ",
7219
+ config?.model,
7220
+ " · ",
7221
+ config?.outputDir
7222
+ ]
7223
+ })
7224
+ ]
7225
+ }),
7226
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7227
+ className: panel_module_css_default.row,
7228
+ children: [
7229
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7230
+ className: panel_module_css_default.cardTitle,
7231
+ children: tt("settings.export")
7232
+ }),
7233
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
7234
+ type: "button",
7235
+ className: panel_module_css_default.button,
7236
+ disabled: busy || chapters.length === 0,
7237
+ onClick: () => {
7238
+ handleExport("txt");
7239
+ },
7240
+ children: tt("settings.exportTxt")
7241
+ }),
7242
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
7243
+ type: "button",
7244
+ className: panel_module_css_default.button,
7245
+ disabled: busy || chapters.length === 0,
7246
+ onClick: () => {
7247
+ handleExport("md");
7248
+ },
7249
+ children: tt("settings.exportMd")
7250
+ })
7251
+ ]
7252
+ }),
7253
+ (project?.facts ?? []).length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7254
+ className: panel_module_css_default.card,
7255
+ children: [
7256
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
7257
+ className: panel_module_css_default.cardTitle,
7258
+ children: [
7259
+ "编年录 / 时间线(",
7260
+ (project?.facts ?? []).length,
7261
+ " 条)"
7262
+ ]
7263
+ }),
7264
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7265
+ className: panel_module_css_default.meta,
7266
+ children: "每章生成后自动抽取「已确立事实」(人物状态/境界资源/关系变化/伏笔落地),最近 20 条注入后续章节生成,保证长期一致。"
7267
+ }),
7268
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7102
7269
  style: {
7103
7270
  display: "flex",
7104
- gap: 8,
7105
- alignItems: "flex-start"
7271
+ flexDirection: "column",
7272
+ gap: 4,
7273
+ maxHeight: 300,
7274
+ overflowY: "auto",
7275
+ fontSize: 12
7106
7276
  },
7107
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
7108
- className: panel_module_css_default.badge,
7277
+ children: [...project?.facts ?? []].reverse().slice(0, 60).map((fact, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7109
7278
  style: {
7110
- borderColor: "var(--nf-text-3)",
7111
- color: "var(--nf-text-3)",
7112
- flex: "none",
7113
- marginTop: 1
7279
+ display: "flex",
7280
+ gap: 8,
7281
+ alignItems: "flex-start"
7114
7282
  },
7115
- children: [
7116
- "第 ",
7117
- fact.chapterNo,
7118
- " 章"
7119
- ]
7120
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7121
- className: panel_module_css_default.meta,
7122
- children: fact.text
7123
- })]
7124
- }, i))
7125
- })
7126
- ]
7127
- })
7128
- ]
7129
- })
7283
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
7284
+ className: panel_module_css_default.badge,
7285
+ style: {
7286
+ borderColor: "var(--nf-text-3)",
7287
+ color: "var(--nf-text-3)",
7288
+ flex: "none",
7289
+ marginTop: 1
7290
+ },
7291
+ children: [
7292
+ "第 ",
7293
+ fact.chapterNo,
7294
+ " 章"
7295
+ ]
7296
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7297
+ className: panel_module_css_default.meta,
7298
+ children: fact.text
7299
+ })]
7300
+ }, i))
7301
+ })
7302
+ ]
7303
+ })
7304
+ ]
7305
+ })
7306
+ ] })
7130
7307
  ]
7131
7308
  })]
7132
7309
  })] }), assistantOpen && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {