From d87c8a02078f315d6fbf6685d310900e148758cc Mon Sep 17 00:00:00 2001 From: bielie Date: Fri, 30 Jan 2026 00:55:04 +0800 Subject: [PATCH] Refine story summary prompts and vector sync --- modules/story-summary/generate/llm.js | 7 +- modules/story-summary/generate/prompt.js | 12 +- modules/story-summary/story-summary-ui.js | 123 ++- modules/story-summary/story-summary.css | 634 ++++++++++++++-- modules/story-summary/story-summary.html | 706 ++++++++++-------- modules/story-summary/story-summary.js | 117 ++- modules/story-summary/vector/chunk-builder.js | 7 + 7 files changed, 1174 insertions(+), 432 deletions(-) diff --git a/modules/story-summary/generate/llm.js b/modules/story-summary/generate/llm.js index 57b16f0..a528005 100644 --- a/modules/story-summary/generate/llm.js +++ b/modules/story-summary/generate/llm.js @@ -36,7 +36,7 @@ Incremental_Summary_Requirements: - 转折: 改变某条线走向 - 点睛: 有细节不影响主线 - 氛围: 纯粹氛围片段 - - Causal_Chain: 为每个新事件标注直接前因事件ID(causedBy),0-2个。只填 evt-数字 形式,必须指向“已存在事件”或“本次新输出事件”。不要写解释文字。 + - Causal_Chain: 为每个新事件标注直接前因事件ID(causedBy)。仅在因果关系明确(直接导致/明确动机/承接后果)时填写;不明确时填[]完全正常。0-2个,只填 evt-数字,指向已存在或本次新输出事件。 - Character_Dynamics: 识别新角色,追踪关系趋势(破裂/厌恶/反感/陌生/投缘/亲密/交融) - Arc_Tracking: 更新角色弧光轨迹与成长进度(0.0-1.0) - World_State_Tracking: 维护当前世界的硬性约束。解决"什么不能违反"。采用 KV 覆盖模型,追踪生死、物品归属、秘密知情、关系状态、环境规则等不可违背的事实。(覆盖式更新) @@ -215,10 +215,7 @@ Before generating, observe the USER and analyze carefully: - events.id 从 evt-{nextEventId} 开始编号 - 仅输出【增量】内容,已有事件绝不重复 - keywords 是全局关键词,综合已有+新增 -- causedBy 规则: - - 数组,最多2个;无前因则 [] - - 只能填 evt-数字(例如 evt-12) - - 必须引用“已存在事件”或“本次新输出事件”(允许引用本次 JSON 内较早出现的事件) +- causedBy 仅在因果明确时填写,允许为[],0-2个,详见上方 Causal_Chain 规则 - worldUpdate 可为空数组 - 合法JSON,字符串值内部避免英文双引号 - 用朴实、白描、有烟火气的笔触记录,避免比喻和意象 diff --git a/modules/story-summary/generate/prompt.js b/modules/story-summary/generate/prompt.js index c4040a0..d3bcb8f 100644 --- a/modules/story-summary/generate/prompt.js +++ b/modules/story-summary/generate/prompt.js @@ -91,11 +91,11 @@ function cleanSummary(summary) { function buildSystemPreamble() { return [ "以上内容为因上下文窗口限制保留的可见历史", - "【剧情记忆】为对以上可见、不可见历史的总结", - "1) 【世界状态】属于硬约束", - "2) 【事件/证据/碎片/人物弧光】可用于补全上下文与动机。", + "以下【剧情记忆】是对可见与不可见历史的总结:", + "• 【世界约束】记录着已确立的事实", + "• 其余部分是过往经历的回忆碎片", "", - "请阅读并内化以下剧情记忆:", + "请内化这些记忆:", ].join("\n"); } @@ -275,7 +275,7 @@ function buildNonVectorPrompt(store) { if (data.world?.length) { const lines = formatWorldLines(data.world); - sections.push(`[世界约束] 规则手册,请严格遵守\n${lines.join("\n")}`); + sections.push(`[世界约束] 已确立的事实\n${lines.join("\n")}`); } if (data.events?.length) { @@ -602,7 +602,7 @@ async function buildVectorPrompt(store, recallResult, causalById, queryEntities // 1. 世界约束 if (assembled.world.lines.length) { - sections.push(`[世界约束] 规则手册,请严格遵守\n${assembled.world.lines.join("\n")}`); + sections.push(`[世界约束] 已确立的事实\n${assembled.world.lines.join("\n")}`); } // 2. 核心经历 diff --git a/modules/story-summary/story-summary-ui.js b/modules/story-summary/story-summary-ui.js index 23e077b..39def8d 100644 --- a/modules/story-summary/story-summary-ui.js +++ b/modules/story-summary/story-summary-ui.js @@ -1,7 +1,7 @@ // story-summary-ui.js // iframe 内 UI 逻辑 -(function() { +(function () { 'use strict'; // ═══════════════════════════════════════════════════════════════════════════ @@ -10,7 +10,7 @@ const $ = id => document.getElementById(id); const $$ = sel => document.querySelectorAll(sel); - const h = v => String(v ?? '').replace(/[&<>"']/g, c => + const h = v => String(v ?? '').replace(/[&<>"']/g, c => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' })[c] ); const setHtml = (el, html) => { @@ -43,7 +43,7 @@ // ═══════════════════════════════════════════════════════════════════════════ const PARENT_ORIGIN = (() => { - try { return new URL(document.referrer).origin; } + try { return new URL(document.referrer).origin; } catch { return window.location.origin; } })(); @@ -154,7 +154,7 @@ saveConfig(); } } - } catch {} + } catch { } } function applyConfig(cfg) { @@ -299,16 +299,18 @@ const items = rules?.length ? rules : []; setHtml(list, items.map((r, i) => ` -
- - - - +
+
+ + + +
+
`).join('')); // 绑定删除 - list.querySelectorAll('.filter-rule-del').forEach(btn => { + list.querySelectorAll('.btn-del-rule').forEach(btn => { btn.onclick = () => { btn.closest('.filter-rule-item')?.remove(); }; @@ -338,14 +340,15 @@ const div = document.createElement('div'); div.className = 'filter-rule-item'; div.dataset.idx = idx; - div.style.cssText = 'display:flex;gap:6px;align-items:center'; setHtml(div, ` - - - - +
+ + + +
+ `); - div.querySelector('.filter-rule-del').onclick = () => div.remove(); + div.querySelector('.btn-del-rule').onclick = () => div.remove(); list.appendChild(div); } @@ -550,7 +553,24 @@ updateProviderUI(config.api.provider); if (config.vector) loadVectorConfig(config.vector); + // Initialize sub-options visibility + const autoSummaryOptions = $('auto-summary-options'); + if (autoSummaryOptions) { + autoSummaryOptions.classList.toggle('hidden', !config.trigger.enabled); + } + const insertWrapperOptions = $('insert-wrapper-options'); + if (insertWrapperOptions) { + insertWrapperOptions.classList.toggle('hidden', !config.trigger.forceInsertAtEnd); + } + $('settings-modal').classList.add('active'); + + // Default to first tab + $$('.settings-tab').forEach(t => t.classList.remove('active')); + $$('.settings-tab[data-tab="tab-summary"]').forEach(t => t.classList.add('active')); + $$('.tab-pane').forEach(p => p.classList.remove('active')); + $('tab-summary').classList.add('active'); + postMsg('SETTINGS_OPENED'); } @@ -1202,17 +1222,6 @@ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860", "--workers", " } } - function openRecallLog() { - updateRecallLogDisplay(); - $('recall-log-modal').classList.add('active'); - postMsg('FULLSCREEN_OPENED'); - } - - function closeRecallLog() { - $('recall-log-modal').classList.remove('active'); - postMsg('FULLSCREEN_CLOSED'); - } - // ═══════════════════════════════════════════════════════════════════════════ // Editor // ═══════════════════════════════════════════════════════════════════════════ @@ -1578,7 +1587,7 @@ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860", "--workers", " renderTimeline([]); renderRelations(null); renderArcs([]); - renderWorldState([]); + renderWorldState([]); break; } @@ -1666,6 +1675,27 @@ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860", "--workers", " $('settings-cancel').onclick = () => closeSettings(false); $('settings-save').onclick = () => closeSettings(true); + // Settings tabs + $$('.settings-tab').forEach(tab => { + tab.onclick = () => { + const targetId = tab.dataset.tab; + if (!targetId) return; + + // Update tab active state + $$('.settings-tab').forEach(t => t.classList.remove('active')); + tab.classList.add('active'); + + // Update pane active state + $$('.tab-pane').forEach(p => p.classList.remove('active')); + $(targetId).classList.add('active'); + + // If switching to debug tab, refresh log + if (targetId === 'tab-debug') { + postMsg('REQUEST_RECALL_LOG'); + } + }; + }); + // API provider change $('api-provider').onchange = e => { const pv = PROVIDER_DEFAULTS[e.target.value]; @@ -1729,11 +1759,6 @@ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860", "--workers", " $('hf-guide-backdrop').onclick = closeHfGuide; $('hf-guide-close').onclick = closeHfGuide; - // Recall log - $('btn-recall').onclick = openRecallLog; - $('recall-log-backdrop').onclick = closeRecallLog; - $('recall-log-close').onclick = closeRecallLog; - // Character selector $('char-sel-trigger').onclick = e => { e.stopPropagation(); @@ -1748,6 +1773,36 @@ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860", "--workers", " // Vector UI initVectorUI(); + // Gen params collapsible + const genParamsToggle = $('gen-params-toggle'); + const genParamsContent = $('gen-params-content'); + if (genParamsToggle && genParamsContent) { + genParamsToggle.onclick = () => { + const collapse = genParamsToggle.closest('.settings-collapse'); + collapse.classList.toggle('open'); + genParamsContent.classList.toggle('hidden'); + }; + } + + // Auto summary sub-options toggle + const triggerEnabled = $('trigger-enabled'); + const autoSummaryOptions = $('auto-summary-options'); + if (triggerEnabled && autoSummaryOptions) { + triggerEnabled.onchange = () => { + autoSummaryOptions.classList.toggle('hidden', !triggerEnabled.checked); + }; + } + + // Force insert sub-options toggle + const triggerInsertAtEnd = $('trigger-insert-at-end'); + const insertWrapperOptions = $('insert-wrapper-options'); + if (triggerInsertAtEnd && insertWrapperOptions) { + triggerInsertAtEnd.onchange = () => { + insertWrapperOptions.classList.toggle('hidden', !triggerInsertAtEnd.checked); + }; + } + + // Resize window.onresize = () => { relationChart?.resize(); @@ -1833,7 +1888,7 @@ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860", "--workers", " `).join('')}
`; - }).join(''); + }).join(''); setHtml(container, html || '
暂无世界状态
'); } diff --git a/modules/story-summary/story-summary.css b/modules/story-summary/story-summary.css index 6dff2a5..375c39c 100644 --- a/modules/story-summary/story-summary.css +++ b/modules/story-summary/story-summary.css @@ -59,7 +59,8 @@ main { min-height: 0; } -.left, .right { +.left, +.right { display: flex; flex-direction: column; gap: 24px; @@ -67,9 +68,11 @@ main { } /* 关键词卡片:固定高度 */ -.left > .card:first-child { - flex: 0 0 auto; /* 关键词:不伸缩 */ +.left>.card:first-child { + flex: 0 0 auto; + /* 关键词:不伸缩 */ } + /* ═══════════════════════════════════════════════════════════════════════════ Typography ═══════════════════════════════════════════════════════════════════════════ */ @@ -153,9 +156,9 @@ h1 span { display: flex; align-items: center; gap: 8px; - padding: 8px 16px; - background: var(--bg3); - border: 1px solid var(--bdr); + padding: 4px 0; + background: transparent; + border: none; font-size: .8125rem; color: var(--txt2); cursor: pointer; @@ -163,7 +166,7 @@ h1 span { } .chk-label:hover { - border-color: var(--acc); + color: var(--txt); } .chk-label input { @@ -290,33 +293,25 @@ h1 span { padding: 10px 14px; } -.btn-recall { - background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); - color: #fff; - border-color: #667eea; - position: relative; - overflow: hidden; +.btn-debug { + background: var(--bg2); + color: var(--txt2); + border: 1px solid var(--bdr); + display: flex; + align-items: center; + gap: 6px; + justify-content: center; } -.btn-recall:hover { - background: linear-gradient(135deg, #5a67d8 0%, #6b46a1 100%); - border-color: #5a67d8; +.btn-debug svg { + width: 14px; + height: 14px; } -.btn-recall::after { - content: ''; - position: absolute; - top: -50%; - left: -50%; - width: 200%; - height: 200%; - background: linear-gradient(45deg, transparent 40%, rgba(255,255,255,.15) 50%, transparent 60%); - animation: shimmer 3s infinite; -} - -@keyframes shimmer { - 0% { transform: translateX(-100%) rotate(45deg); } - 100% { transform: translateX(100%) rotate(45deg); } +.btn-debug:hover { + background: var(--bg3); + border-color: var(--acc); + color: var(--txt); } /* ═══════════════════════════════════════════════════════════════════════════ @@ -700,13 +695,40 @@ h1 span { white-space: nowrap; } -.trend-broken { background: rgba(68, 68, 68, .15); color: #444; } -.trend-hate { background: rgba(139, 0, 0, .15); color: #8b0000; } -.trend-dislike { background: rgba(205, 92, 92, .15); color: #cd5c5c; } -.trend-stranger { background: rgba(136, 136, 136, .15); color: #888; } -.trend-click { background: rgba(102, 205, 170, .15); color: #4a9a7e; } -.trend-close { background: rgba(235, 106, 106, .15); color: var(--hl); } -.trend-merge { background: rgba(199, 21, 133, .2); color: #c71585; } +.trend-broken { + background: rgba(68, 68, 68, .15); + color: #444; +} + +.trend-hate { + background: rgba(139, 0, 0, .15); + color: #8b0000; +} + +.trend-dislike { + background: rgba(205, 92, 92, .15); + color: #cd5c5c; +} + +.trend-stranger { + background: rgba(136, 136, 136, .15); + color: #888; +} + +.trend-click { + background: rgba(102, 205, 170, .15); + color: #4a9a7e; +} + +.trend-close { + background: rgba(235, 106, 106, .15); + color: var(--hl); +} + +.trend-merge { + background: rgba(199, 21, 133, .2); + color: #c71585; +} /* ═══════════════════════════════════════════════════════════════════════════ Custom Select @@ -787,8 +809,15 @@ h1 span { } @keyframes fadeIn { - from { opacity: 0; transform: translateY(-4px); } - to { opacity: 1; transform: translateY(0); } + from { + opacity: 0; + transform: translateY(-4px); + } + + to { + opacity: 1; + transform: translateY(0); + } } /* ═══════════════════════════════════════════════════════════════════════════ @@ -1041,8 +1070,10 @@ h1 span { letter-spacing: .05em; } -.settings-field input, +.settings-field input:not([type="checkbox"]):not([type="radio"]), .settings-field select { + width: 100%; + max-width: 100%; padding: 10px 14px; background: var(--bg3); border: 1px solid var(--bdr); @@ -1050,6 +1081,22 @@ h1 span { color: var(--txt); outline: none; transition: border-color .2s; + box-sizing: border-box; +} + +.settings-field input[type="checkbox"], +.settings-field input[type="radio"] { + width: auto; + height: auto; +} + +.settings-field select { + appearance: none; + -webkit-appearance: none; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23666' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='3 4.5 6 7.5 9 4.5'%3E%3C/polyline%3E%3C/svg%3E"); + background-repeat: no-repeat; + background-position: right 12px center; + padding-right: 32px; } .settings-field input:focus, @@ -1113,6 +1160,10 @@ h1 span { .engine-option input { accent-color: var(--hl); + width: 18px; + height: 18px; + margin: 0; + cursor: pointer; } .engine-area { @@ -1132,19 +1183,35 @@ h1 span { margin-bottom: 4px; } -.engine-card-desc { - font-size: .75rem; - color: var(--txt3); - margin-bottom: 12px; +.engine-status-row { + display: flex; + justify-content: space-between; + align-items: center; + gap: 12px; + margin-top: 12px; } .engine-status { display: flex; align-items: center; - justify-content: center; gap: 6px; font-size: .8125rem; - margin-bottom: 12px; + color: var(--txt3); + flex: 1; + /* 占 1/3 */ +} + +.engine-actions { + display: flex; + gap: 8px; + justify-content: flex-end; + flex: 2; + /* 占 2/3 */ +} + +/* 针对在线测试连接按钮的特殊处理 */ +#btn-test-vector-api { + flex: 2; } .status-dot { @@ -1154,15 +1221,37 @@ h1 span { background: var(--txt3); } -.status-dot.ready { background: #22c55e; } -.status-dot.cached { background: #3b82f6; } -.status-dot.downloading { background: #f59e0b; animation: pulse 1s infinite; } -.status-dot.error { background: #ef4444; } -.status-dot.success { background: #22c55e; } +.status-dot.ready { + background: #22c55e; +} + +.status-dot.cached { + background: #3b82f6; +} + +.status-dot.downloading { + background: #f59e0b; + animation: pulse 1s infinite; +} + +.status-dot.error { + background: #ef4444; +} + +.status-dot.success { + background: #22c55e; +} @keyframes pulse { - 0%, 100% { opacity: 1; } - 50% { opacity: .5; } + + 0%, + 100% { + opacity: 1; + } + + 50% { + opacity: .5; + } } .engine-progress { @@ -1195,8 +1284,8 @@ h1 span { .engine-actions { display: flex; gap: 8px; - justify-content: center; - flex-wrap: wrap; + justify-content: flex-end; + flex: 2; } .model-select-row { @@ -1218,8 +1307,8 @@ h1 span { .model-desc { font-size: .75rem; color: var(--txt3); - text-align: center; - margin-bottom: 12px; + text-align: left; + margin-bottom: 4px; } .vector-stats { @@ -1343,8 +1432,8 @@ h1 span { } .hf-intro { - background: linear-gradient(135deg, rgba(102,126,234,.08), rgba(118,75,162,.08)); - border: 1px solid rgba(102,126,234,.2); + background: linear-gradient(135deg, rgba(102, 126, 234, .08), rgba(118, 75, 162, .08)); + border: 1px solid rgba(102, 126, 234, .2); border-radius: 8px; padding: 20px; text-align: center; @@ -1495,8 +1584,8 @@ h1 span { right: 8px; top: 8px; padding: 4px 10px; - background: rgba(255,255,255,.1); - border: 1px solid rgba(255,255,255,.2); + background: rgba(255, 255, 255, .1); + border: 1px solid rgba(255, 255, 255, .2); color: #999; font-size: .6875rem; cursor: pointer; @@ -1505,14 +1594,14 @@ h1 span { } .hf-code .copy-btn:hover { - background: rgba(255,255,255,.2); + background: rgba(255, 255, 255, .2); color: #fff; } .hf-status-badge { display: inline-block; padding: 2px 10px; - background: rgba(34,197,94,.15); + background: rgba(34, 197, 94, .15); color: #22c55e; border-radius: 10px; font-size: .75rem; @@ -1684,8 +1773,7 @@ h1 span { .btn-group { width: 100%; - display: grid; - grid-template-columns: repeat(4, 1fr); + display: flex; gap: 6px; } @@ -1714,7 +1802,8 @@ h1 span { gap: 16px; } - .left, .right { + .left, + .right { gap: 16px; } @@ -1882,7 +1971,9 @@ h1 span { font-size: .6875rem; } - main, .left, .right { + main, + .left, + .right { gap: 12px; } @@ -2177,3 +2268,412 @@ h1 span { padding: 6px 8px; } } + +/* ═══════════════════════════════════════════════════════════════════════════ + New Settings Styles + ═══════════════════════════════════════════════════════════════════════════ */ + +.settings-modal-box { + max-width: 680px; +} + +/* Collapsible Section */ +.settings-collapse { + margin-top: 20px; + border-radius: 8px; + overflow: hidden; +} + +.settings-collapse-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 12px 16px; + cursor: pointer; + font-size: .8125rem; + font-weight: 500; + color: var(--txt2); + transition: all .2s; +} + +.settings-collapse-header:hover { + background: var(--bdr); +} + +.collapse-icon { + width: 16px; + height: 16px; + transition: transform .2s; +} + +.settings-collapse.open .collapse-icon { + transform: rotate(180deg); +} + +.settings-collapse-content { + padding: 16px; + border-top: 1px solid var(--bdr); +} + +/* Checkbox Group */ +.settings-checkbox-group { + margin-bottom: 20px; + padding: 0; + background: transparent; + border: none; +} + +.settings-checkbox-group:last-child { + margin-bottom: 0; +} + +.settings-checkbox { + display: flex; + align-items: center; + gap: 10px; + cursor: pointer; + user-select: none; +} + +.settings-checkbox input[type="checkbox"] { + display: none; +} + +.checkbox-mark { + width: 20px; + height: 20px; + border: 2px solid var(--bdr); + border-radius: 4px; + background: var(--bg2); + position: relative; + transition: all .2s; + flex-shrink: 0; +} + +.settings-checkbox input:checked+.checkbox-mark { + background: var(--acc); + border-color: var(--acc); +} + +.settings-checkbox input:checked+.checkbox-mark::after { + content: ''; + position: absolute; + left: 6px; + top: 2px; + width: 5px; + height: 10px; + border: solid #fff; + border-width: 0 2px 2px 0; + transform: rotate(45deg); +} + +.checkbox-label { + font-size: .875rem; + color: var(--txt); +} + +.settings-checkbox-group .settings-hint { + margin-left: 30px; + margin-top: 4px; +} + +/* Sub Options */ +.settings-sub-options { + margin-top: 12px; + padding-top: 12px; + border-top: 1px dashed var(--bdr); +} + +/* Filter Rules */ +.filter-rules-section { + margin-top: 20px; + padding: 16px; + background: var(--bg3); + border: 1px solid var(--bdr); + border-radius: 8px; +} + +.filter-rules-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 8px; + gap: 12px; +} + +.filter-rules-header label { + font-size: .75rem; + color: var(--txt3); + text-transform: uppercase; + letter-spacing: .05em; + font-weight: 600; + flex: 1; + /* 1/3 */ +} + +.btn-add { + flex: 2; + /* 2/3 */ + justify-content: center; + display: flex; + align-items: center; + gap: 4px; + padding: 6px 12px; +} + +.filter-rules-list { + display: flex; + flex-direction: column; + gap: 8px; + margin-top: 12px; +} + +.filter-rule-item { + display: flex; + gap: 8px; + align-items: flex-start; + padding: 10px 12px; + background: var(--bg2); + border: 1px solid var(--bdr2); + border-radius: 6px; +} + +.filter-rule-inputs { + display: flex; + flex-direction: column; + align-items: center; + gap: 4px; + flex: 1; +} + +.filter-rule-item input { + width: 100%; + padding: 8px 10px; + background: var(--bg3); + border: 1px solid var(--bdr); + font-size: .8125rem; + color: var(--txt); + border-radius: 4px; +} + +.filter-rule-item input:focus { + border-color: var(--acc); + outline: none; +} + +.filter-rule-item .rule-arrow { + color: var(--txt3); + font-size: .875rem; + flex-shrink: 0; + padding: 2px 0; +} + +.filter-rule-item .btn-del-rule { + padding: 6px 10px; + background: transparent; + border: 1px solid var(--hl); + color: var(--hl); + cursor: pointer; + border-radius: 4px; + font-size: .75rem; + transition: all .2s; + flex-shrink: 0; + align-self: center; +} + +.filter-rule-item .btn-del-rule:hover { + background: var(--hl-soft); +} + +/* Vector Stats - Original horizontal layout */ +.vector-stats { + display: flex; + flex-wrap: wrap; + align-items: flex-start; + gap: 16px; + font-size: .875rem; + color: var(--txt2); + margin-top: 8px; +} + +.vector-stat-col { + display: flex; + flex-direction: column; + align-items: center; + gap: 2px; +} + +.vector-stat-label { + font-size: .75rem; + color: var(--txt3); +} + +.vector-stat-value { + color: var(--txt2); +} + +.vector-stat-value strong { + color: var(--hl); +} + +.vector-stat-sep { + color: var(--txt3); + align-self: center; +} + +.vector-io-section { + border-top: 1px solid var(--bdr); + padding-top: 16px; + margin-top: 16px; +} + +/* Mobile Settings Responsive */ +@media (max-width: 768px) { + .settings-modal-box { + max-width: 100%; + } + + .settings-collapse-header { + padding: 14px 16px; + } + + .settings-checkbox-group { + padding: 14px; + } + + .checkbox-label { + font-size: .8125rem; + } + + .vector-stats { + gap: 8px; + } + + .vector-stat-sep { + display: none; + } + + .vector-stat-col { + flex-direction: row; + gap: 4px; + } + + .settings-field { + min-width: 100px; + } +} + +@media (max-width: 480px) { + .settings-checkbox-group { + padding: 12px; + } + + .checkbox-mark { + width: 18px; + height: 18px; + } + + .settings-checkbox input:checked+.checkbox-mark::after { + left: 5px; + top: 1px; + width: 4px; + height: 9px; + } + + .filter-rules-section { + padding: 12px; + } + + .filter-rule-item { + padding: 8px 10px; + } + + .filter-rule-item .btn-del-rule { + padding: 4px 8px; + } + + .settings-sub-options .settings-row { + flex-direction: column; + } +} + +/* Settings Tabs */ +.settings-tabs { + display: flex; + gap: 24px; + align-self: flex-end; + /* 使底部边框与 header 底部对齐 */ + margin-bottom: -20px; + /* 抵消 modal-head 的 padding,让边框贴合底部 */ +} + +.settings-tab { + font-size: .875rem; + color: var(--txt3); + cursor: pointer; + padding-bottom: 20px; + /* 增加内边距使点击区域更大且贴合底部 */ + border-bottom: 2px solid transparent; + transition: all .2s; + user-select: none; + text-transform: uppercase; + letter-spacing: .1em; + font-weight: 500; +} + +.settings-tab:hover { + color: var(--txt); +} + +.settings-tab.active { + color: var(--hl); + border-bottom-color: var(--hl); + font-weight: 600; +} + +.tab-pane { + display: none; +} + +.tab-pane.active { + display: block; + animation: fadeIn .3s ease; +} + +.debug-log-header { + margin-bottom: 12px; + padding-bottom: 8px; + border-bottom: 1px dashed var(--bdr2); +} + +.debug-title { + font-size: .875rem; + font-weight: 600; + color: var(--txt); + margin-bottom: 4px; +} + +.debug-log-viewer { + width: 100%; + height: 400px; + background: var(--bg3); + border: 1px solid var(--bdr); + border-radius: 6px; + padding: 12px; + font-family: 'SF Mono', Monaco, Consolas, 'Courier New', monospace; + font-size: 11px; + line-height: 1.5; + color: var(--txt2); + overflow-y: auto; + white-space: pre-wrap; + margin: 0; +} + +.recall-empty { + color: var(--txt3); + text-align: center; + padding: 40px; + font-style: italic; + font-size: .8125rem; + line-height: 1.8; +} diff --git a/modules/story-summary/story-summary.html b/modules/story-summary/story-summary.html index 404748c..3397874 100644 --- a/modules/story-summary/story-summary.html +++ b/modules/story-summary/story-summary.html @@ -1,6 +1,7 @@ + @@ -8,6 +9,7 @@ 剧情总结 · Story Summary +
@@ -37,18 +39,19 @@
-
@@ -92,8 +95,10 @@
人物关系
@@ -132,7 +137,8 @@

编辑

@@ -152,319 +158,398 @@