From a9c0e20b754b28ef2e6ae230969f8f24ed8e39c1 Mon Sep 17 00:00:00 2001 From: ethan su Date: Wed, 17 Jun 2026 18:31:16 +0800 Subject: [PATCH 1/2] feat: typography alignment with system font baseline MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Consolidate font stack: remove GA Lexend/Noto Sans, use system sans (SF Pro/Segoe UI) - Reduce CSS font variables from 6 to 3 (--font-sans, --font-mono, --font-brand) - Converge font-weights to match reference spec (700→600 headings, 600→500 labels) - Add explicit font-family to pre/code blocks - Compact nav-item: 28px height, 8px padding, 16px icons - Remove 'token' from all UI copy, simplify to 'Usage'/'用量' - Add cache-buster to fonts.css link --- frontends/desktop/static/app.js | 47 +++- .../desktop/static/assets/fonts/fonts.css | 18 -- frontends/desktop/static/index.html | 2 +- frontends/desktop/static/styles.css | 260 ++++++++++-------- 4 files changed, 173 insertions(+), 154 deletions(-) diff --git a/frontends/desktop/static/app.js b/frontends/desktop/static/app.js index dfd72cc2..268a9a0b 100644 --- a/frontends/desktop/static/app.js +++ b/frontends/desktop/static/app.js @@ -253,7 +253,7 @@ const I18N = { 'app.title': 'GenericAgent 桌面版', 'brand.sub': '桌面终端', 'nav.chat': '聊天', 'nav.services': '后台服务', 'nav.channels': '消息通道', 'nav.status': '状态面板', - 'nav.collab': '指挥家', 'nav.token': 'Token 统计', + 'nav.collab': '指挥家', 'nav.token': '用量', 'foot.settings': '配置', 'foot.ver': 'GenericAgent · 桌面版', 'chat.startTitle': '开始对话', 'chat.startSub': '直接输入,或点预设功能一键启动', 'preset.butler.t': '指挥家', 'preset.butler.d': '复杂任务自动拆解,只需查看进度和简报', @@ -264,7 +264,7 @@ const I18N = { 'preset.review.t': '深度复核', 'preset.review.d': '挑刺式质量把关', 'preset.mine.t': '我的·周报', 'preset.mine.d': '自定义:抓本周提交并写周报', 'preset.add.t': '自定义', 'preset.add.d': '任意一句话存为功能', - 'composer.placeholder': '输入消息… (Enter 发送, Shift+Enter 换行)', + 'composer.placeholder': 'GA 能帮你做些什么?', 'search.placeholder': '搜索会话…', 'conv.new': '新对话', 'ctx.pin': '置顶', 'ctx.unpin': '取消置顶', 'ctx.rename': '重命名', 'ctx.del': '删除', 'common.close': '关闭', 'common.more': '更多', 'common.optional': '选填', 'common.save': '保存', @@ -336,7 +336,7 @@ const I18N = { 'collab.timeMin': '{n} 分钟前', 'collab.timeHr': '{n} 小时前', 'collab.timeDay': '{n} 天前', - 'page.token.title': 'Token 统计', 'page.token.sub': '每会话与累计的 token 用量及缓存率', + 'page.token.title': '用量', 'page.token.sub': '每会话与累计用量及缓存率', 'status.connecting': '连接中…', 'status.ready': '就绪', 'status.running': '运行中', 'status.disconnected': '未连接', 'status.stopped': '已停止', 'status.idle': '空闲', 'conv.emptyList': '暂无会话,点「+ 新对话」开始', 'conv.defaultTitle': '新对话', @@ -393,7 +393,7 @@ const I18N = { 'proc.imbotWechat': 'imbot · 微信', 'proc.imbotDing': 'imbot · 钉钉', 'proc.scheduler': '定时任务调度', 'cm.scheduling': '调度中', 'cm.running': '执行中', 'cm.idleSt': '空闲', 'cm.master': '已派 3 子任务', 'cm.w1': '子任务:抓取数据', 'cm.w2': '子任务:复核结果', 'cm.sub': '等待派单', - 'tok.total': '累计 token', 'tok.cost': '缓存率', 'tok.today': '今日 token', 'tok.tabAll': '聊天', 'tok.tabConductor': '指挥家', 'tok.condTotal': '指挥家累计', 'tok.condCurrent': '指挥家本次', 'tok.condTip': '指挥家消耗的 token 不计入聊天累计 token 中', 'tok.condOffline': '无法连接指挥家(8900)', 'tok.disclaimer': '不同 API 网站的计费价格可能会有差异,请以实际网站为准。', 'tok.chartToggle': '趋势图', + 'tok.total': '累计', 'tok.cost': '缓存率', 'tok.today': '今日', 'tok.tabAll': '聊天', 'tok.tabConductor': '指挥家', 'tok.condTotal': '指挥家累计', 'tok.condCurrent': '指挥家本次', 'tok.condTip': '指挥家消耗不计入聊天累计', 'tok.condOffline': '无法连接指挥家(8900)', 'tok.disclaimer': '不同 API 网站的计费价格可能会有差异,请以实际网站为准。', 'tok.chartToggle': '趋势图', 'tok.colSession': '会话', 'tok.colIn': '输入', 'tok.colOut': '输出', 'tok.colCacheW': '缓存写入', 'tok.colCache': '缓存读取', 'tok.colCost': '成本', 'tok.from': '从', 'tok.to': '到', 'tok.reset': '重置', 'tok.noData': '暂无记录', 'tok.deleted': '此会话已删除', 'tok.pricingUnknown': '⚠ 此模型计费规则尚未明确,按默认估算', @@ -413,7 +413,7 @@ const I18N = { 'app.title': 'GenericAgent Desktop', 'brand.sub': 'Desktop terminal', 'nav.chat': 'Chat', 'nav.services': 'Services', 'nav.channels': 'Channels', 'nav.status': 'Status', - 'nav.collab': 'Conductor', 'nav.token': 'Token usage', + 'nav.collab': 'Conductor', 'nav.token': 'Usage', 'foot.settings': 'Settings', 'foot.ver': 'GenericAgent · Desktop', 'chat.startTitle': 'Start a conversation', 'chat.startSub': 'Type a message, or pick a preset', 'preset.butler.t': 'Conductor', 'preset.butler.d': 'Auto-decompose complex tasks; just check progress and briefings', @@ -424,7 +424,7 @@ const I18N = { 'preset.review.t': 'Deep review', 'preset.review.d': 'Strict quality check', 'preset.mine.t': 'My · Weekly', 'preset.mine.d': 'Custom: weekly report from commits', 'preset.add.t': 'Custom', 'preset.add.d': 'Save any prompt as a function', - 'composer.placeholder': 'Type a message… (Enter to send, Shift+Enter for newline)', + 'composer.placeholder': 'What can GA do for you?', 'search.placeholder': 'Search chats…', 'conv.new': 'New chat', 'ctx.pin': 'Pin', 'ctx.unpin': 'Unpin', 'ctx.rename': 'Rename', 'ctx.del': 'Delete', 'common.close': 'Close', 'common.more': 'More', 'common.optional': 'Optional', 'common.save': 'Save', @@ -496,7 +496,7 @@ const I18N = { 'collab.timeMin': '{n}m ago', 'collab.timeHr': '{n}h ago', 'collab.timeDay': '{n}d ago', - 'page.token.title': 'Token usage', 'page.token.sub': 'Per-session and total token usage & cache rate', + 'page.token.title': 'Usage', 'page.token.sub': 'Per-session and total usage & cache rate', 'status.connecting': 'Connecting…', 'status.ready': 'Ready', 'status.running': 'Running', 'status.disconnected': 'Disconnected', 'status.stopped': 'Stopped', 'status.idle': 'Idle', 'conv.emptyList': 'No chats yet — click “+ New chat”', 'conv.defaultTitle': 'New chat', @@ -553,7 +553,7 @@ const I18N = { 'proc.imbotWechat': 'imbot · WeChat', 'proc.imbotDing': 'imbot · DingTalk', 'proc.scheduler': 'Scheduler', 'cm.scheduling': 'Scheduling', 'cm.running': 'Running', 'cm.idleSt': 'Idle', 'cm.master': 'Dispatched 3 subtasks', 'cm.w1': 'Subtask: fetch data', 'cm.w2': 'Subtask: review results', 'cm.sub': 'Waiting for tasks', - 'tok.total': 'Total tokens', 'tok.cost': 'Cache rate', 'tok.today': 'Today tokens', 'tok.tabAll': 'Chat', 'tok.tabConductor': 'Conductor', 'tok.condTotal': 'Conductor Total', 'tok.condCurrent': 'Conductor Current', 'tok.condTip': 'Conductor tokens are not included in chat totals', 'tok.condOffline': 'Cannot reach Conductor (8900)', 'tok.disclaimer': 'Pricing may vary by API provider. Please refer to the actual website.', 'tok.chartToggle': 'Trend', + 'tok.total': 'Total', 'tok.cost': 'Cache rate', 'tok.today': 'Today', 'tok.tabAll': 'Chat', 'tok.tabConductor': 'Conductor', 'tok.condTotal': 'Conductor Total', 'tok.condCurrent': 'Conductor Current', 'tok.condTip': 'Conductor usage is not included in chat totals', 'tok.condOffline': 'Cannot reach Conductor (8900)', 'tok.disclaimer': 'Pricing may vary by API provider. Please refer to the actual website.', 'tok.chartToggle': 'Trend', 'tok.colSession': 'Session', 'tok.colIn': 'Input', 'tok.colOut': 'Output', 'tok.colCacheW': 'Cache write', 'tok.colCache': 'Cache read', 'tok.colCost': 'Cost', 'tok.from': 'From', 'tok.to': 'To', 'tok.reset': 'Reset', 'tok.noData': 'No records', 'tok.deleted': 'Session deleted', 'tok.pricingUnknown': '⚠ Pricing not confirmed, using defaults', @@ -4007,7 +4007,7 @@ window.ga.onBridgeClosed(() => { chatStatus.setDisconnected(); }); -/* ═══════════════ Token 统计页 ═══════════════ */ +/* ═══════════════ Token 用量页 ═══════════════ */ const tokTbody = document.getElementById('tok-tbody'); const tokPager = document.getElementById('tok-pager'); const tokSince = document.getElementById('tok-since'); @@ -4051,10 +4051,10 @@ function modelPriceTip(model) { const cacheWriteRate = isClaudeOrDS ? 1.25 : 1.0; const lines = []; if (!known) lines.push(t('tok.pricingUnknown')); - lines.push(t('tok.priceInput') + p[0] + ' /M tokens'); - lines.push(t('tok.priceOutput') + p[1] + ' /M tokens'); - lines.push(t('tok.priceCacheW') + (p[0] * cacheWriteRate).toFixed(2) + ' /M tokens'); - lines.push(t('tok.priceCacheR') + (p[0] * cacheReadRate).toFixed(2) + ' /M tokens'); + lines.push(t('tok.priceInput') + p[0] + ' /M'); + lines.push(t('tok.priceOutput') + p[1] + ' /M'); + lines.push(t('tok.priceCacheW') + (p[0] * cacheWriteRate).toFixed(2) + ' /M'); + lines.push(t('tok.priceCacheR') + (p[0] * cacheReadRate).toFixed(2) + ' /M'); return lines.join('\n'); } @@ -5650,4 +5650,25 @@ function bindComposerInRoot(root, opts) { }; window.collabFocus = () => window.collabComposer?.focus?.(); window.collabRetranslate = () => { renderWorkers(); syncMessages(); setConnUi(); }; +})(); + +/* ═══════════════ Composer layout: inline / stacked ═══════════════ */ +(function initComposerLayout() { + const BREAKPOINT = 480; + const SINGLE_LINE = 36; + + document.querySelectorAll('.composer-inset').forEach(inset => { + const input = inset.querySelector('.input'); + if (!input) return; + + function update() { + const wide = inset.offsetWidth >= BREAKPOINT; + const single = input.scrollHeight <= SINGLE_LINE; + inset.classList.toggle('is-inline', wide && single); + } + + new ResizeObserver(update).observe(inset); + input.addEventListener('input', update); + update(); + }); })(); \ No newline at end of file diff --git a/frontends/desktop/static/assets/fonts/fonts.css b/frontends/desktop/static/assets/fonts/fonts.css index 3ac460c1..8103b351 100644 --- a/frontends/desktop/static/assets/fonts/fonts.css +++ b/frontends/desktop/static/assets/fonts/fonts.css @@ -11,24 +11,6 @@ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+20AC, U+2122, U+2212, U+FEFF, U+FFFD; } -@font-face { - font-family: "GA Lexend"; - src: url("./lexend-latin.woff2") format("woff2"); - font-style: normal; - font-weight: 300 700; - font-display: swap; - unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; -} - -@font-face { - font-family: "GA Noto Sans"; - src: url("./noto-sans-latin.woff2") format("woff2"); - font-style: normal; - font-weight: 400 700; - font-display: swap; - unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; -} - @font-face { font-family: "GA JetBrains Mono"; src: url("./jetbrains-mono-latin.woff2") format("woff2"); diff --git a/frontends/desktop/static/index.html b/frontends/desktop/static/index.html index 186f0e70..ec7dab11 100644 --- a/frontends/desktop/static/index.html +++ b/frontends/desktop/static/index.html @@ -3,7 +3,7 @@ GenericAgent - + diff --git a/frontends/desktop/static/styles.css b/frontends/desktop/static/styles.css index 4a15eb8b..89cf350d 100644 --- a/frontends/desktop/static/styles.css +++ b/frontends/desktop/static/styles.css @@ -14,12 +14,10 @@ ::-webkit-scrollbar-corner{ background:transparent; } :root{ - --font-ui:-apple-system,BlinkMacSystemFont,"Segoe UI Variable","Segoe UI","PingFang SC","Hiragino Sans GB","Microsoft YaHei UI","Microsoft YaHei",system-ui,sans-serif; - --font-brand:"GA Azonix",var(--font-ui); - --font-title-en:"GA Lexend",var(--font-ui); - --font-body-en:"GA Noto Sans",var(--font-ui); - --font-config-mono:"GA JetBrains Mono",ui-monospace,"SFMono-Regular",Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace; - --font-num:var(--font-config-mono); + --font-sans:-apple-system,BlinkMacSystemFont,system-ui,"Segoe UI Variable","Segoe UI","PingFang SC","Hiragino Sans GB","Microsoft YaHei UI","Microsoft YaHei",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Noto Color Emoji",emoji; + --font-brand:"GA Azonix",var(--font-sans); + --font-mono:"GA JetBrains Mono",ui-monospace,"SFMono-Regular",Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace; + --font-num:var(--font-mono); --font-num-variant:lining-nums tabular-nums; --chat-col-w:760px; /* —— 基础面 —— */ @@ -90,7 +88,6 @@ --shadow-modal:0 18px 50px #14192847; --radius:4px; --radius-sm:2px; - font-family:var(--font-body-en); /* —— 折叠块 —— */ --fold-thinking-border:#d4c090; --fold-thinking-bg:#fefbf3; @@ -174,7 +171,7 @@ html[data-appearance="dark"][data-theme]{ html,body{ height:100%; } html{ --chat-font:14px; } -body{ background:var(--bg); color:var(--txt); font-size:13px; overflow:hidden; font-family:var(--font-body-en); } +body{ background:var(--bg); color:var(--txt); font-size:13px; overflow:hidden; font-family:var(--font-sans); } #app{ width:100vw; height:100vh; background:var(--bg); @@ -206,7 +203,7 @@ body{ background:var(--bg); color:var(--txt); font-size:13px; overflow:hidden; f display:flex; align-items:center; justify-content:space-between; padding:16px 18px; border-bottom:1px solid var(--line-soft); } -.modal-title{ font-size:15px; font-weight:700; color:var(--txt-strong); } +.modal-title{ font-size:15px; font-weight:600; color:var(--txt-strong); } .modal-x{ width:28px; height:28px; border:none; background:transparent; cursor:pointer; color:var(--muted); border-radius:4px; display:flex; align-items:center; justify-content:center; @@ -219,7 +216,7 @@ body{ background:var(--bg); color:var(--txt); font-size:13px; overflow:hidden; f .set-body{ min-height:0; padding:18px; display:flex; flex-direction:column; gap:22px; } .set-block{ display:flex; flex-direction:column; gap:0; } .preset-pop{ min-height:0; padding:18px; display:flex; flex-direction:column; gap:14px; } -.set-sec-t{ font-size:12px; font-weight:700; color:var(--txt-2); margin-bottom:10px; } +.set-sec-t{ font-size:12px; font-weight:500; color:var(--txt-2); margin-bottom:10px; } /* 外观:mac 式预览卡片 */ .appear-cards{ display:grid; grid-template-columns:1fr 1fr; gap:10px; } @@ -252,7 +249,7 @@ body{ background:var(--bg); color:var(--txt); font-size:13px; overflow:hidden; f content:''; position:absolute; left:10%; top:52%; width:55%; height:7px; border-radius:4px; background:var(--sample-dark-line); } -.appear-name{ font-size:12px; font-weight:600; color:var(--txt-2); font-family:var(--font-title-en); } +.appear-name{ font-size:12px; font-weight:500; color:var(--txt-2); font-family:var(--font-sans); } .appear-card.sel .appear-name{ color:var(--accent); } /* 素色:mac/iOS 设置行 + Toggle Switch */ @@ -262,7 +259,7 @@ body{ background:var(--bg); color:var(--txt); font-size:13px; overflow:hidden; f border:1px solid var(--line); border-radius:4px; background:var(--field-bg); } .set-toggle-row[hidden]{ display:none; } -.set-toggle-label{ font-size:13px; font-weight:600; color:var(--txt-2); font-family:var(--font-title-en); } +.set-toggle-label{ font-size:13px; font-weight:500; color:var(--txt-2); font-family:var(--font-sans); } .set-switch{ position:relative; flex:0 0 auto; width:44px; height:26px; border:none; border-radius:999px; background:var(--switch-off); @@ -288,7 +285,7 @@ body{ background:var(--bg); color:var(--txt); font-size:13px; overflow:hidden; f .chat-font-stepper{ grid-column:1; grid-row:1; cursor:pointer; touch-action:none; border-radius:4px; } .chat-font-value{ grid-column:2; grid-row:1 / 3; align-self:center; - font-size:13px; font-weight:600; color:var(--txt-strong); + font-size:13px; font-weight:500; color:var(--txt-strong); font-variant-numeric:var(--font-num-variant); text-align:right; line-height:1; padding-left:14px; border-left:1px solid var(--line); min-width:42px; } @@ -326,7 +323,7 @@ body{ background:var(--bg); color:var(--txt); font-size:13px; overflow:hidden; f cursor:pointer; font-size:13px; color:var(--txt-2); transition:.12s; } .model-row:hover{ background:var(--line-soft); border-color:var(--line-strong); } -.model-row.sel{ background:var(--accent-bg); border-color:var(--accent); color:var(--accent); font-weight:600; } +.model-row.sel{ background:var(--accent-bg); border-color:var(--accent); color:var(--accent); font-weight:500; } .model-row input{ accent-color:var(--accent); flex:0 0 auto; pointer-events:none; } .flag{ width:20px; height:14px; flex:0 0 auto; border-radius:2px; box-shadow:0 0 0 1px var(--line); display:inline-block; } .model-row-name{ flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; } @@ -347,7 +344,7 @@ body{ background:var(--bg); color:var(--txt); font-size:13px; overflow:hidden; f .set-btn{ width:100%; display:flex; align-items:center; gap:8px; border:1px solid var(--line); background:var(--card); color:var(--txt-2); - border-radius:4px; padding:10px 12px; font-size:13px; font-weight:600; + border-radius:4px; padding:10px 12px; font-size:13px; font-weight:500; font-family:inherit; cursor:pointer; transition:.12s; } .set-btn svg{ width:15px; height:15px; flex:0 0 auto; color:var(--accent); } @@ -357,9 +354,9 @@ body{ background:var(--bg); color:var(--txt); font-size:13px; overflow:hidden; f .set-btn.ghost{ background:transparent; } .model-form-body{ min-height:0; } .model-form{ padding:18px; display:flex; flex-direction:column; gap:12px; } -.model-form label{ display:flex; flex-direction:column; gap:5px; font-size:12px; font-weight:600; color:var(--txt-2); } -.field-label{ display:inline-flex; align-items:center; gap:2px; font-family:var(--font-title-en); } -.field-req{ color:var(--danger-text); font-weight:700; line-height:1; } +.model-form label{ display:flex; flex-direction:column; gap:5px; font-size:12px; font-weight:500; color:var(--txt-2); } +.field-label{ display:inline-flex; align-items:center; gap:2px; font-family:var(--font-sans); } +.field-req{ color:var(--danger-text); font-weight:500; line-height:1; } .model-form input{ border:1px solid var(--line); border-radius:4px; padding:8px 10px; font-size:13px; font-family:inherit; background:var(--field-bg); color:var(--txt); @@ -368,7 +365,7 @@ body{ background:var(--bg); color:var(--txt); font-size:13px; overflow:hidden; f .model-form input::placeholder{ color:var(--placeholder); opacity:1; } /* 协议选择:分段控件(替代 native dropdown,样式可控)*/ -.model-form-field{ display:flex; flex-direction:column; gap:5px; font-size:12px; font-weight:600; color:var(--txt-2); } +.model-form-field{ display:flex; flex-direction:column; gap:5px; font-size:12px; font-weight:500; color:var(--txt-2); } .seg-group{ display:flex; gap:4px; padding:3px; border:1px solid var(--line); border-radius:4px; background:var(--field-bg); @@ -376,22 +373,22 @@ body{ background:var(--bg); color:var(--txt); font-size:13px; overflow:hidden; f .seg-opt{ flex:1; display:flex; align-items:center; justify-content:center; padding:7px 10px; border-radius:4px; cursor:pointer; - font-size:12px; font-weight:600; color:var(--txt-2); font-family:var(--font-title-en); + font-size:12px; font-weight:500; color:var(--txt-2); font-family:var(--font-sans); transition:background .12s, color .12s; user-select:none; } .seg-opt input{ position:absolute; opacity:0; pointer-events:none; } .seg-opt:hover{ background:var(--line-soft); color:var(--txt); } .seg-opt:has(input:checked){ background:var(--accent); color:var(--on-accent); } .seg-opt:has(input:checked):hover{ background:var(--accent); color:var(--on-accent); } -.model-form .field-hint{ font-size:11px; font-weight:400; color:var(--muted); line-height:1.45; margin-top:2px; } +.model-form .field-hint{ font-size:11px; font-weight:400; color:var(--muted); line-height:1.35; margin-top:2px; } #add-model-form .model-form-row{ display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:8px; width:100%; } #add-model-form .model-form-mini{ - gap:4px; font-size:11px; font-weight:600; font-family:var(--font-title-en); + gap:4px; font-size:11px; font-weight:500; font-family:var(--font-sans); } #add-model-form .model-form-mini input[type="number"]{ - padding:5px 6px; font-size:12px; line-height:1.2; height:30px; + padding:5px 6px; font-size:12px; line-height:1; height:30px; border:1px solid var(--line); border-radius:4px; background:var(--field-bg); color:var(--txt); font-family:inherit; } @@ -448,13 +445,12 @@ body{ background:var(--bg); color:var(--txt); font-size:13px; overflow:hidden; f font-family:var(--font-brand); font-weight:400; font-size:15px; - letter-spacing:.02em; line-height:1; white-space:nowrap; } .brand-sub{ font-size:10px; color:var(--muted); margin-top:1px; - line-height:1.1; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; + line-height:1; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; } .ga-num{ @@ -469,18 +465,18 @@ body{ background:var(--bg); color:var(--txt); font-size:13px; overflow:hidden; f box-sizing:border-box; } .nav-item{ - display:flex; align-items:center; gap:10px; padding:9px 10px; - border-radius:var(--radius-sm); color:var(--txt-2); cursor:pointer; - font-size:13px; user-select:none; font-family:var(--font-title-en); + display:flex; align-items:center; gap:8px; padding:0 8px; + height:28px; border-radius:var(--radius-sm); color:var(--txt-2); cursor:pointer; + font-size:13px; user-select:none; font-family:var(--font-sans); } -.ic{ width:18px; height:18px; flex:0 0 auto; } +.ic{ width:16px; height:16px; flex:0 0 auto; } .nav-item .ic{ opacity:.85; } -.fr-l{ display:flex; align-items:center; gap:10px; } +.fr-l{ display:flex; align-items:center; gap:8px; } .nav-item:hover{ background:var(--line-soft); } -.nav-item.active{ background:var(--accent-bg); color:var(--accent); font-weight:600; } +.nav-item.active{ background:var(--accent-bg); color:var(--accent); font-weight:500; } .beta{ - margin-left:auto; font-size:9px; font-weight:700; color:var(--accent); - background:var(--accent-soft); padding:1px 6px; border-radius:10px; letter-spacing:.3px; + margin-left:auto; font-size:9px; font-weight:500; color:var(--accent); + background:var(--accent-soft); padding:1px 6px; border-radius:10px; } .nav-item.active .beta{ background:var(--card); } @@ -490,7 +486,7 @@ body{ background:var(--bg); color:var(--txt); font-size:13px; overflow:hidden; f .foot-row{ display:flex; justify-content:space-between; align-items:center; padding:14px 10px; border-radius:var(--radius-sm); color:var(--txt-2); cursor:pointer; - font-family:var(--font-title-en); + font-family:var(--font-sans); } .foot-row:hover{ background:var(--line-soft); } .chev{ width:14px; height:14px; color:var(--muted2); flex:0 0 auto; } @@ -509,7 +505,7 @@ body{ background:var(--bg); color:var(--txt); font-size:13px; overflow:hidden; f .pq-head{ display:flex; justify-content:space-between; align-items:center; padding:14px 10px; border-radius:var(--radius-sm); color:var(--txt-2); cursor:pointer; - font-family:var(--font-title-en); user-select:none; + font-family:var(--font-sans); user-select:none; } .pq-head:hover{ background:var(--line-soft); } .pq-collapse{ transition:transform .18s; } @@ -532,8 +528,8 @@ body{ background:var(--bg); color:var(--txt); font-size:13px; overflow:hidden; f } .pq-logo svg{ width:16px; height:16px; } .pq-btn-text{ flex:1; min-width:0; display:flex; flex-direction:column; gap:1px; } -.pq-btn-name{ font-size:12px; font-weight:600; color:var(--txt); line-height:1.2; } -.pq-btn-desc{ font-size:10px; color:var(--muted); line-height:1.2; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; } +.pq-btn-name{ font-size:12px; font-weight:500; color:var(--txt); line-height:1.35; } +.pq-btn-desc{ font-size:10px; color:var(--muted); line-height:1; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; } .pq-arrow{ flex:0 0 auto; width:13px; height:13px; color:var(--muted2); transition:transform .15s, color .15s; } .pq-btn:hover .pq-arrow{ color:var(--accent); transform:translateX(2px); } @@ -549,12 +545,12 @@ body{ background:var(--bg); color:var(--txt); font-size:13px; overflow:hidden; f display:flex; align-items:center; justify-content:center; } .model-guide-logo svg{ width:15px; height:15px; } -.model-guide-name{ font-size:13px; font-weight:700; color:var(--txt-strong); } +.model-guide-name{ font-size:13px; font-weight:600; color:var(--txt-strong); } .model-guide-steps{ margin:0 0 8px; padding-left:18px; display:flex; flex-direction:column; gap:3px; } -.model-guide-steps li{ font-size:12px; color:var(--txt-2); line-height:1.45; } +.model-guide-steps li{ font-size:12px; color:var(--txt-2); line-height:1.55; } .model-guide-link-row{ display:flex; align-items:center; gap:6px; } .model-guide-link{ - flex:1; min-width:0; font-size:12px; font-weight:600; color:var(--accent); + flex:1; min-width:0; font-size:12px; font-weight:500; color:var(--accent); text-decoration:none; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; } .model-guide-link:hover{ text-decoration:underline; } @@ -564,7 +560,7 @@ body{ background:var(--bg); color:var(--txt); font-size:13px; overflow:hidden; f display:flex; align-items:center; justify-content:center; cursor:pointer; } .model-guide-copy:hover{ color:var(--accent); border-color:var(--accent); } -.model-guide-tip{ margin:8px 0 0; font-size:11px; color:var(--muted); line-height:1.4; } +.model-guide-tip{ margin:8px 0 0; font-size:11px; color:var(--muted); line-height:1.35; } /* ============ 中间主区 ============ */ .main{ @@ -620,7 +616,7 @@ body{ background:var(--bg); color:var(--txt); font-size:13px; overflow:hidden; f /* 纯状态展示组件(不可点):就绪/运行中=绿,未连接=红,连接中=灰 */ .run-state{ display:flex; align-items:center; gap:9px; height:30px; color:var(--ok); - font-weight:600; font-size:12px; border:none; background:transparent; + font-weight:500; font-size:12px; border:none; background:transparent; padding:0; font-family:inherit; cursor:default; line-height:1; } .run-state .dot{ @@ -701,7 +697,7 @@ body{ background:var(--bg); color:var(--txt); font-size:13px; overflow:hidden; f .page{ display:none; flex:1; min-height:0; flex-direction:column; min-width:0; } .page.active{ display:flex; } .page-pad{ flex:1; overflow:auto; padding:26px 30px; } -.page-title{ font-size:18px; font-weight:700; color:var(--txt-strong); font-family:var(--font-title-en); } +.page-title{ font-size:18px; font-weight:600; color:var(--txt-strong); font-family:var(--font-sans); } .page-sub{ font-size:12px; color:var(--muted); margin-top:5px; margin-bottom:16px; } /* 聊天 / Conductor 共用对话布局(page--chat-ui) */ @@ -751,6 +747,9 @@ body{ background:var(--bg); color:var(--txt); font-size:13px; overflow:hidden; f margin:0; background:transparent; } +.page.page--chat-ui .composer{ + padding:10px 0 0; +} .page.page--chat-ui .composer-inset{ border:1px solid var(--line); border-radius:var(--radius); @@ -778,7 +777,7 @@ body{ background:var(--bg); color:var(--txt); font-size:13px; overflow:hidden; f position:absolute; inset:0; z-index:25; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:10px; background:color-mix(in srgb, var(--panel) 88%, transparent); - font-size:13px; font-weight:600; color:var(--txt-2); + font-size:13px; font-weight:500; color:var(--txt-2); pointer-events:none; } .session-loading[hidden]{ display:none !important; } @@ -792,7 +791,7 @@ body{ background:var(--bg); color:var(--txt); font-size:13px; overflow:hidden; f border-radius:999px; background:var(--card); border:1px solid color-mix(in srgb, var(--accent) 35%, var(--line)); box-shadow:var(--shadow-pop); - font-size:13px; font-weight:600; color:var(--txt); + font-size:13px; font-weight:500; color:var(--txt); pointer-events:none; } .msg-loading[hidden]{ display:none !important; } @@ -819,7 +818,7 @@ body{ background:var(--bg); color:var(--txt); font-size:13px; overflow:hidden; f .msg.system{ justify-content:center; } .bubble{ max-width:80%; padding:10px 14px; border-radius:6px; font-size:var(--chat-font); - line-height:1.6; white-space:pre-wrap; word-break:break-word; + line-height:1.55; white-space:pre-wrap; word-break:break-word; background:var(--accent-bg); color:var(--txt-strong); } .bubble.md{ white-space:normal; background:transparent; color:var(--txt); max-width:100%; width:100%; border-radius:4px; } @@ -831,9 +830,9 @@ body{ background:var(--bg); color:var(--txt); font-size:13px; overflow:hidden; f .code-block-head{ display:flex; align-items:center; justify-content:space-between; padding:4px 12px; background:var(--field-bg); border-bottom:1px solid var(--line); - font-family:var(--font-config-mono); font-size:.75em; color:var(--muted); + font-family:var(--font-mono); font-size:.75em; color:var(--muted); } -.code-block-lang{ text-transform:uppercase; letter-spacing:.5px; font-weight:600; } +.code-block-lang{ text-transform:uppercase; letter-spacing:.5px; font-weight:500; } .code-block-copy{ background:none; border:none; color:var(--muted); cursor:pointer; font-size:1.1em; padding:2px 4px; border-radius:3px; line-height:1; @@ -841,10 +840,11 @@ body{ background:var(--bg); color:var(--txt); font-size:13px; overflow:hidden; f } .code-block-copy:hover{ color:var(--txt); background:var(--hover-dim); } .code-block pre{ margin:0; border:none; border-radius:0; } -.bubble.md pre{ background:var(--field-bg); border:1px solid var(--line); border-radius:4px; padding:10px 12px; overflow:auto; font-size:.86em; } +.bubble.md pre{ background:var(--field-bg); border:1px solid var(--line); border-radius:4px; padding:10px 12px; overflow:auto; font-size:.86em; font-family:var(--font-mono); } +.bubble.md pre code{ font-family:var(--font-mono); } .bubble.md .code-block pre{ background:var(--field-bg); border:none; border-radius:0; padding:12px 14px; overflow:auto; font-size:.86em; margin:0; } .bubble.md .code-block{ border:1px solid var(--line); } -.bubble.md :not(pre) > code{ background:var(--field-bg); border-radius:4px; padding:1px 5px; font-size:.86em; } +.bubble.md :not(pre) > code{ background:var(--field-bg); border-radius:4px; padding:1px 5px; font-size:.86em; font-family:var(--font-mono); } .bubble.md a{ color:var(--accent); } .bubble.md ul,.bubble.md ol{ margin:0 0 8px; padding-left:20px; } .bubble.md blockquote{ @@ -888,7 +888,7 @@ html[data-boot-has-sessions] .chat-start{ display:none !important; } .fcard:hover{ border-color:var(--accent); box-shadow:var(--shadow); transform:translateY(-1px); } .fcard.add{ border-style:dashed; background:var(--accent-soft); } .fc-ic{ width:26px; height:26px; color:var(--txt-strong); } -.fc-t{ font-weight:600; font-size:13px; margin-top:10px; font-family:var(--font-title-en); } +.fc-t{ font-weight:500; font-size:13px; margin-top:10px; font-family:var(--font-sans); } .fc-d{ font-size:11px; color:var(--muted); margin-top:3px; } /* 后台服务页 — 下划线 Tab(消息通道 / 状态面板)。margin 与 .tok-tabs 对齐 @@ -899,7 +899,7 @@ html[data-boot-has-sessions] .chat-start{ display:none !important; } } .svc-tab{ padding:12px 0 10px; margin-bottom:-1px; - font-size:14px; font-weight:600; border:none; background:transparent; + font-size:14px; font-weight:500; border:none; background:transparent; color:var(--muted); cursor:pointer; border-bottom:2px solid transparent; transition:color .15s, border-color .15s; } @@ -919,7 +919,7 @@ html[data-boot-has-sessions] .chat-start{ display:none !important; } .lr-ic{ width:18px; height:18px; color:var(--muted); flex:0 0 auto; } .grow{ flex:1; } .kv{ color:var(--muted); font-size:12px; min-width:54px; text-align:right; } -.lr-st{ font-size:11px; padding:2px 8px; border-radius:10px; font-weight:600; } +.lr-st{ font-size:11px; padding:2px 8px; border-radius:10px; font-weight:500; } .lr-st.on{ color:var(--ok-strong); background:var(--ok-bg); } .lr-st.off{ color:var(--muted); background:var(--off-bg); } .lr-st.err{ color:var(--danger-text); background:var(--danger-bg); } @@ -946,7 +946,7 @@ html[data-boot-has-sessions] .chat-start{ display:none !important; } } .toast{ padding:12px 20px; border-radius:var(--radius-sm); - font-size:13px; line-height:1.45; + font-size:13px; line-height:1.35; box-shadow:var(--shadow-pop); opacity:0; transform:translateY(-8px); transition:opacity .28s ease, transform .28s ease; pointer-events:auto; text-align:center; min-width:200px; @@ -962,7 +962,7 @@ html[data-boot-has-sessions] .chat-start{ display:none !important; } color:var(--muted); background:var(--card); border:1px solid var(--line); box-shadow:var(--shadow); padding:6px 12px; min-width:0; font-size:12px; } -.toast-title{ font-weight:600; display:block; margin-bottom:2px; } +.toast-title{ font-weight:500; display:block; margin-bottom:2px; } .toast-detail{ font-size:12px; opacity:.88; display:block; word-break:break-word; } .toast-info .toast-title{ font-weight:500; margin-bottom:0; } .composer.is-locked{ @@ -973,7 +973,7 @@ html[data-boot-has-sessions] .chat-start{ display:none !important; } } .chan-log-pre{ max-height:360px; overflow:auto; margin:0; - font-family:var(--font-config-mono); font-variant-numeric:var(--font-num-variant); font-size:13px; line-height:1.5; + font-family:var(--font-mono); font-variant-numeric:var(--font-num-variant); font-size:13px; line-height:1.55; color:var(--txt-2); background:var(--field-bg); border:1px solid var(--line); border-radius:var(--radius-sm); padding:14px 16px; white-space:pre-wrap; word-break:break-word; @@ -987,7 +987,7 @@ html[data-boot-has-sessions] .chat-start{ display:none !important; } .mykey-editor{ flex:1; min-height:420px; width:100%; padding:0; margin:0; - font-family:var(--font-config-mono); font-variant-numeric:var(--font-num-variant); font-size:13px; line-height:1.5; + font-family:var(--font-mono); font-variant-numeric:var(--font-num-variant); font-size:13px; line-height:1.55; color:var(--txt); background:var(--card); border:none; border-radius:0; resize:vertical; outline:none; } @@ -997,20 +997,20 @@ html[data-boot-has-sessions] .chat-start{ display:none !important; } } .chan-config-save{ border:1px solid var(--line); background:var(--card); color:var(--txt-2); - border-radius:6px; padding:5px 12px; font-size:12px; font-weight:600; + border-radius:6px; padding:5px 12px; font-size:12px; font-weight:500; font-family:inherit; cursor:pointer; } .chan-config-save:hover{ background:var(--hover-2); } .chan-config-save:disabled{ opacity:.45; cursor:not-allowed; } .chan-meta{ display:flex; flex-direction:column; gap:2px; min-width:0; } .chan-meta .chan-name{ font-size:14px; } -.chan-meta .chan-path{ font-size:11px; color:var(--muted); font-family:var(--font-config-mono); font-variant-numeric:var(--font-num-variant); } +.chan-meta .chan-path{ font-size:11px; color:var(--muted); font-family:var(--font-mono); font-variant-numeric:var(--font-num-variant); } /* 协作动态卡片 */ .card-row{ display:grid; grid-template-columns:repeat(auto-fill,minmax(150px,1fr)); gap:12px; margin:14px 0; } .card-mini{ border:1px solid var(--line); border-radius:var(--radius-sm); background:var(--card); padding:14px; } .card-mini b{ font-size:13px; } -.cm-st{ font-size:11px; font-weight:600; margin-top:8px; } +.cm-st{ font-size:11px; font-weight:500; margin-top:8px; } .cm-st.on{ color:var(--ok-strong); } .cm-st.idle{ color:var(--muted); } .cm-d{ font-size:11px; color:var(--muted); margin-top:4px; } @@ -1021,7 +1021,7 @@ html[data-boot-has-sessions] .chat-start{ display:none !important; } } .tok-tab{ padding:12px 0 10px; margin-bottom:-1px; - font-size:14px; font-weight:600; border:none; background:transparent; + font-size:14px; font-weight:500; border:none; background:transparent; color:var(--muted); cursor:pointer; border-bottom:2px solid transparent; transition:color .15s, border-color .15s; } @@ -1053,9 +1053,9 @@ html[data-boot-has-sessions] .chat-start{ display:none !important; } box-shadow:var(--shadow-pop) !important; font-family:inherit !important; font-size:13px !important; } .flatpickr-months .flatpickr-month, -.flatpickr-current-month{ color:var(--txt) !important; fill:var(--txt) !important; font-weight:600 !important; } +.flatpickr-current-month{ color:var(--txt) !important; fill:var(--txt) !important; font-weight:500 !important; } .flatpickr-current-month .flatpickr-monthDropdown-months, -.flatpickr-current-month input.cur-year{ color:var(--txt) !important; background:var(--field-bg) !important; font-weight:600 !important; font-size:13px !important; } +.flatpickr-current-month input.cur-year{ color:var(--txt) !important; background:var(--field-bg) !important; font-weight:500 !important; font-size:13px !important; } .flatpickr-weekdays{ background:var(--field-bg) !important; } span.flatpickr-weekday{ color:var(--muted) !important; font-size:11px; } .flatpickr-day{ @@ -1083,11 +1083,11 @@ span.flatpickr-weekday{ color:var(--muted) !important; font-size:11px; } /* 固定列宽:数字列按 fmtTok 最长输出"123.45M"宽度估算固定 px, 第一列(会话名/指挥家累计 等)拿剩余空间,过长用省略号 + title tooltip */ .tok-table{ width:100%; border-collapse:collapse; margin-top:14px; font-size:13px; table-layout:fixed; } -.tok-table th{ text-align:left; padding:8px 12px; font-size:11px; color:var(--muted); background:var(--line-soft); font-weight:600; } +.tok-table th{ text-align:left; padding:8px 12px; font-size:11px; color:var(--muted); background:var(--line-soft); font-weight:500; } .tok-table th:not(:first-child){ text-align:right; } .tok-table td{ padding:9px 12px; border-bottom:1px solid var(--line-soft); } .tok-table td:not(:first-child){ text-align:right; color:var(--muted); font-size:12px; font-family:var(--font-num); font-variant-numeric:var(--font-num-variant); } -.tok-table td:first-child{ font-weight:600; color:var(--txt-strong); } +.tok-table td:first-child{ font-weight:500; color:var(--txt-strong); } /* 第一列自动占剩余宽度,溢出省略 */ .tok-table th:first-child, .tok-table td:first-child{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; @@ -1120,7 +1120,7 @@ span.flatpickr-weekday{ color:var(--muted) !important; font-size:11px; } .tok-deleted{ margin-left:6px; font-size:10px; font-weight:400; color:var(--muted2); background:var(--line-soft); border-radius:3px; padding:1px 5px; } .stat-row{ display:flex; gap:12px; margin:14px 0; } .stat{ flex:1; border:1px solid var(--line); border-radius:var(--radius); background:var(--card); padding:16px; text-align:center; } -.s-n{ font-size:20px; font-weight:700; color:var(--txt-strong); font-family:var(--font-num); font-variant-numeric:var(--font-num-variant); } +.s-n{ font-size:20px; font-weight:600; color:var(--txt-strong); font-family:var(--font-num); font-variant-numeric:var(--font-num-variant); } .s-l{ font-size:11px; color:var(--muted); margin-top:4px; } .composer{ @@ -1130,18 +1130,17 @@ span.flatpickr-weekday{ color:var(--muted) !important; font-size:11px; } } .chip{ border:1px solid var(--line); background:transparent; border-radius:0; - padding:0 11px; min-height:30px; font-size:12px; font-weight:700; color:var(--txt-2); cursor:pointer; - font-family:var(--font-body-en); + padding:0 11px; min-height:30px; font-size:12px; font-weight:500; color:var(--txt-2); cursor:pointer; + font-family:var(--font-sans); display:inline-flex; align-items:center; gap:5px; } .chip.sm{ padding:0 12px; min-height:32px; - font-family:var(--font-body-en); + font-family:var(--font-sans); font-size:14px; - font-weight:800; + font-weight:700; line-height:1; - letter-spacing:.12em; text-transform:uppercase; color:var(--txt-strong); background:var(--field-bg); @@ -1164,22 +1163,39 @@ span.flatpickr-weekday{ color:var(--muted) !important; font-size:11px; } width:100%; border:1px solid var(--line); border-radius:var(--radius); background:var(--card); + display:grid; + grid-template-columns:1fr; } -.composer-inset:focus-within{ border-color:var(--accent); } .composer-inset .thumb-strip{ padding:8px 12px 0; } +.composer-inset.is-inline{ + grid-template-columns:1fr auto; +} +.composer-inset.is-inline .thumb-strip{ grid-column:1 / -1; } +.composer-inset.is-inline .input{ grid-column:1; } +.composer-inset.is-inline .composer-bot{ + grid-column:2; + padding:0 8px 0 0; + align-self:end; +} +.composer-inset.is-inline .composer-bot .spacer{ display:none; } +.composer-inset:focus-within{ + border-color:var(--accent); + box-shadow:0 0 0 3px color-mix(in srgb, var(--accent) 12%, transparent); +} .composer-inset .input{ - width:100%; min-height:58px; max-height:200px; overflow-y:auto; + width:100%; min-height:38px; max-height:160px; overflow-y:auto; border:none; border-radius:0; background:transparent; - padding:12px 14px 8px; font-size:var(--chat-font); line-height:1.5; outline:none; + padding:10px 12px; font-size:15px; line-height:1.55; outline:none; font-family:inherit; color:var(--txt); white-space:pre-wrap; word-break:break-word; } /* contenteditable 空提示(textarea 的 placeholder 等价物)*/ .composer-inset .input:empty::before{ content:attr(data-ph); color:var(--muted); pointer-events:none; + font-size:15px; font-weight:400; } .composer-inset .composer-bot{ - margin-top:0; padding:0 10px 10px; justify-content:flex-start; + margin-top:0; padding:2px 10px 8px; justify-content:flex-start; } .composer-inset .composer-bot .spacer{ flex:1; } .composer-plus-wrap{ position:relative; flex:0 0 auto; } @@ -1303,8 +1319,8 @@ span.flatpickr-weekday{ color:var(--muted) !important; font-size:11px; } width:100%; box-sizing:border-box; border:1px solid var(--line); background:var(--line-soft); border-radius:4px; - padding:0 12px; font-size:13px; color:var(--txt-2); cursor:pointer; font-weight:600; - display:flex; align-items:center; justify-content:center; gap:7px; font-family:var(--font-title-en); + padding:0 12px; font-size:13px; color:var(--txt-2); cursor:pointer; font-weight:500; + display:flex; align-items:center; justify-content:center; gap:7px; font-family:var(--font-sans); } .new-conv svg{ width:14px; height:14px; } .new-conv:hover{ background:var(--hover-2); } @@ -1327,9 +1343,9 @@ span.flatpickr-weekday{ color:var(--muted) !important; font-size:11px; } .ci-dot{ width:7px; height:7px; border-radius:50%; background:var(--ok); flex:0 0 auto; } .conv-item.idle .ci-dot{ background:var(--dot-idle); } .ci-main{ flex:1; min-width:0; } -.ci-title{ font-size:13px; font-weight:600; color:var(--txt-strong); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; } +.ci-title{ font-size:13px; font-weight:500; color:var(--txt-strong); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; } .ci-rename-input{ - font-size:13px; font-weight:600; color:var(--txt-strong); width:100%; + font-size:13px; font-weight:500; color:var(--txt-strong); width:100%; border:1px solid var(--accent); border-radius:4px; padding:1px 4px; background:var(--field-bg); outline:none; } @@ -1386,7 +1402,7 @@ span.flatpickr-weekday{ color:var(--muted) !important; font-size:11px; } max-width:100%; box-sizing:border-box; font-size:12px; - line-height:1.45; + line-height:1.35; color:var(--txt); pointer-events:auto; } @@ -1438,7 +1454,7 @@ span.flatpickr-weekday{ color:var(--muted) !important; font-size:11px; } } .plan-title{ flex:1 1 auto; - font-weight:700; + font-weight:600; font-size:12px; color:var(--txt-strong); min-width:0; @@ -1448,7 +1464,7 @@ span.flatpickr-weekday{ color:var(--muted) !important; font-size:11px; } } .plan-progress{ flex:0 0 auto; - font-weight:700; + font-weight:600; font-size:12px; color:var(--accent); font-family:var(--font-num); @@ -1466,11 +1482,11 @@ span.flatpickr-weekday{ color:var(--muted) !important; font-size:11px; } background:transparent; padding:2px 6px; font-size:11px; - font-weight:600; + font-weight:500; color:var(--accent); cursor:pointer; border-radius:var(--radius-sm); - font-family:var(--font-body-en); + font-family:var(--font-sans); } .plan-btn:hover{ background:var(--accent-soft); } .plan-current{ @@ -1488,7 +1504,7 @@ span.flatpickr-weekday{ color:var(--muted) !important; font-size:11px; } .plan-current-text{ flex:1 1 auto; color:var(--accent); - font-weight:600; + font-weight:500; word-break:break-word; } .plan-card--complete .plan-current-text{ color:var(--success); } @@ -1512,7 +1528,7 @@ span.flatpickr-weekday{ color:var(--muted) !important; font-size:11px; } flex:0 0 auto; width:1.1em; text-align:center; - line-height:1.45; + line-height:1.35; } .plan-item-text{ flex:1 1 auto; @@ -1525,7 +1541,7 @@ span.flatpickr-weekday{ color:var(--muted) !important; font-size:11px; } } .plan-item--done .plan-item-text{ text-decoration:line-through; } .plan-item--current .plan-item-mark{ color:var(--accent); } -.plan-item--current .plan-item-text{ color:var(--accent); font-weight:600; } +.plan-item--current .plan-item-text{ color:var(--accent); font-weight:500; } .plan-item--pending .plan-item-mark, .plan-item--pending .plan-item-text{ color:var(--muted); } .plan-item--error .plan-item-mark, @@ -1561,10 +1577,10 @@ html[data-appearance="dark"] .plan-item--warn .plan-item-text{ color:#f0a020; } background:var(--card); cursor:pointer; font-size:12px; - font-weight:600; + font-weight:500; color:var(--txt); box-shadow:var(--shadow); - font-family:var(--font-body-en); + font-family:var(--font-sans); } .plan-capsule:hover{ border-color:var(--line-strong); background:var(--field-bg); } .plan-capsule-text{ @@ -1577,7 +1593,7 @@ html[data-appearance="dark"] .plan-item--warn .plan-item-text{ color:#f0a020; } .plan-capsule-text em{ font-style:normal; color:var(--accent); - font-weight:700; + font-weight:600; } .plan-card--complete .plan-capsule{ border-left-color:var(--success); } .plan-card--complete .plan-capsule-text em{ color:var(--success); } @@ -1587,7 +1603,7 @@ html[data-appearance="dark"] .plan-item--warn .plan-item-text{ color:#f0a020; } background:var(--accent); color:var(--on-accent); border-color:var(--accent); - font-weight:800; + font-weight:700; } /* 组内 .cb-left .chip.sm 的底色/字色优先级(0,3,0)高于 .chip.on(0,2,0),会把开态盖掉, 导致根本看不出开/关;这里用 (0,4,0) 覆盖:开态 = 主题色实底高亮,一眼可辨 */ @@ -1619,7 +1635,7 @@ html[data-appearance="dark"] .plan-item--warn .plan-item-text{ color:#f0a020; } font:inherit; color:var(--txt-2); cursor:pointer; - font-family:var(--font-config-mono); + font-family:var(--font-mono); font-variant-numeric:var(--font-num-variant); } .ga-menu-item:hover{ background:var(--hover-2); } @@ -1662,7 +1678,7 @@ html[data-appearance="dark"] .plan-item--warn .plan-item-text{ color:#f0a020; } background:var(--card); color:var(--txt-2); font-size:11px; - line-height:14px; + line-height:1; cursor:pointer; display:flex; align-items:center; @@ -1747,11 +1763,11 @@ html[data-appearance="dark"] .plan-item--warn .plan-item-text{ color:#f0a020; } .thumb-strip .file-chip.pending .fc-meta{ display:flex; flex-direction:column; min-width:0; - line-height:1.25; + line-height:1.35; } .thumb-strip .file-chip.pending .fc-name{ font-size:12px; - font-weight:600; + font-weight:500; color:var(--txt-strong); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; } @@ -1771,7 +1787,7 @@ html[data-appearance="dark"] .plan-item--warn .plan-item-text{ color:#f0a020; } color:var(--accent); border:2px dashed var(--accent); border-radius:0; - font-size:15px; font-weight:600; + font-size:15px; font-weight:500; pointer-events:none; z-index:50; } @@ -1829,11 +1845,11 @@ html[data-appearance="dark"] .plan-item--warn .plan-item-text{ color:#f0a020; } .user-files .file-chip .fc-meta{ display:flex; flex-direction:column; min-width:0; - line-height:1.25; + line-height:1.35; } .user-files .file-chip .fc-name{ font-size:13px; - font-weight:600; + font-weight:500; color:var(--txt-strong); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; } @@ -1937,7 +1953,7 @@ html[data-appearance="dark"] .plan-item--warn .plan-item-text{ color:#f0a020; } .modal-title, .set-sec-t{ - font-family:var(--font-title-en); + font-family:var(--font-sans); } .model-row-name, @@ -1946,7 +1962,7 @@ html[data-appearance="dark"] .plan-item--warn .plan-item-text{ color:#f0a020; } #add-model-form .model-form-mini input[type="number"], .chat-font-value, .kv{ - font-family:var(--font-config-mono); + font-family:var(--font-mono); font-variant-numeric:var(--font-num-variant); } @@ -1957,7 +1973,7 @@ html[data-appearance="dark"] .plan-item--warn .plan-item-text{ color:#f0a020; } .fold.fold-tool-live > summary{ opacity:.85; font-style:italic; } .fold.fold-result{ border:none; background:transparent; } .fold.fold-turn{ border-color:var(--fold-turn-border); background:var(--fold-turn-bg); } -.fold.fold-turn > summary{ font-weight:600; color:var(--txt-2); white-space:nowrap; overflow:hidden; } +.fold.fold-turn > summary{ font-weight:500; color:var(--txt-2); white-space:nowrap; overflow:hidden; } .fold.fold-retry{ border-color:var(--fold-retry-border); background:var(--fold-retry-bg); border-style:dashed; } .fold.fold-retry > summary{ font-size:11px; color:var(--muted2); font-weight:400; } .fold.fold-retry pre{ font-size:11px; color:var(--muted); } @@ -2052,10 +2068,10 @@ html[data-appearance="dark"] .bubble.md pre code{ color:var(--txt-2); } display:flex; align-items:baseline; flex-wrap:wrap; gap:4px 6px; margin-bottom:8px; - line-height:1.4; + line-height:1.35; } .ask-user-banner-text{ - font-size:13px; font-weight:700; + font-size:13px; font-weight:600; color:var(--txt-strong); } .ask-user-notice.is-active .ask-user-banner-text{ @@ -2073,7 +2089,7 @@ html[data-appearance="dark"] .bubble.md pre code{ color:var(--txt-2); } } .ask-user-body{ font-size:14px; line-height:1.55; color:var(--txt); - font-weight:600; margin:0; + font-weight:500; margin:0; } .ask-user-body strong{ color:var(--txt-strong); } .ask-user-body code{ @@ -2116,7 +2132,7 @@ html[data-appearance="dark"] .bubble.md pre code{ color:var(--txt-2); } } .bubble.md .ask-user-notice .ask-user-body ol > li::before{ content:counter(ask-ol) ". "; - font-weight:600; + font-weight:500; color:color-mix(in srgb, var(--txt) 38%, var(--muted)); } .bubble.md .ask-user-notice .ask-user-body ol > li > p{ @@ -2134,7 +2150,7 @@ html[data-appearance="dark"] .bubble.md pre code{ color:var(--txt-2); } font-size:14px; line-height:1.55; color:var(--txt); } .ask-candidate-key{ - font-weight:600; + font-weight:500; color:color-mix(in srgb, var(--txt) 38%, var(--muted)); } .ask-user-notice.is-active .ask-candidate-key{ @@ -2150,7 +2166,7 @@ html[data-appearance="dark"] .bubble.md pre code{ color:var(--txt-2); } /* —— 消息计时 badge —— */ .task-elapsed{ display:block; font-size:11px; color:var(--muted); - line-height:18px; min-height:18px; + line-height:1; min-height:18px; padding:0 6px; margin-bottom:2px; border-radius:var(--radius-sm); } @@ -2184,7 +2200,7 @@ html[data-appearance="dark"] .bubble.md pre code{ color:var(--txt-2); } content:attr(data-drop-hint); position:absolute; inset:8px; z-index:20; pointer-events:none; display:flex; align-items:center; justify-content:center; border-radius:var(--radius); border:2px dashed var(--accent); background:color-mix(in srgb, var(--accent) 8%, var(--panel)); - font-size:13px; color:var(--accent); font-weight:600; + font-size:13px; color:var(--accent); font-weight:500; } .collab-rail{ position:absolute; left:0; top:50%; z-index:14; @@ -2211,7 +2227,7 @@ html[data-appearance="dark"] .bubble.md pre code{ color:var(--txt-2); } .page.page--chat-ui[data-page="collab"].collab-prog-open .collab-rail-chev{ transform:rotate(180deg); } .collab-rail-badge{ display:flex; flex-direction:column; align-items:center; gap:2px; - font-size:10px; font-weight:700; line-height:1; + font-size:10px; font-weight:500; line-height:1; font-family:var(--font-num); font-variant-numeric:var(--font-num-variant); } .collab-rail-badge.pulse{ animation:collab-rail-pulse .55s ease-out; } @@ -2252,7 +2268,7 @@ html[data-appearance="dark"] .bubble.md pre code{ color:var(--txt-2); } .collab-prog-panel-head{ flex:0 0 auto; display:flex; align-items:center; justify-content:space-between; gap:6px; padding:8px 8px 4px 12px; - font-size:13px; font-weight:700; color:var(--txt-strong); + font-size:13px; font-weight:600; color:var(--txt-strong); } .collab-prog-panel-head .ic-btn{ width:26px; height:26px; } .collab-prog-panel-head .ic-btn svg{ width:14px; height:14px; } @@ -2262,17 +2278,17 @@ html[data-appearance="dark"] .bubble.md pre code{ color:var(--txt-2); } } .collab-stat{ display:inline-flex; align-items:center; gap:4px; - font-size:10px; font-weight:600; padding:2px 7px; border-radius:4px; - line-height:1.2; + font-size:10px; font-weight:500; padding:2px 7px; border-radius:4px; + line-height:1.35; } .collab-stat--running{ color:var(--ok); background:color-mix(in srgb, var(--ok) 10%, var(--panel)); } .collab-stat--done{ color:var(--muted); background:color-mix(in srgb, var(--muted) 10%, var(--panel)); } .collab-prog-stats .ga-status-breathe--sm{ --breathe-box:8px; } .collab-prog-stats .collab-rail-dot{ width:5px; height:5px; } .collab-stat--done .collab-rail-dot{ background:var(--muted2); } -.collab-stat .n{ font-family:var(--font-num); font-variant-numeric:var(--font-num-variant); font-weight:700; font-size:10px; } +.collab-stat .n{ font-family:var(--font-num); font-variant-numeric:var(--font-num-variant); font-weight:500; font-size:10px; } .collab-progress-empty{ - flex:0 0 auto; font-size:12px; color:var(--muted); line-height:1.45; + flex:0 0 auto; font-size:12px; color:var(--muted); line-height:1.35; padding:4px 10px 2px; } #collab-workers{ @@ -2294,13 +2310,13 @@ html[data-appearance="dark"] .bubble.md pre code{ color:var(--txt-2); } .collab-card--terminated{ --collab-st:var(--line-strong); } .collab-card-st{ display:flex; align-items:center; gap:5px; font-size:11px; color:var(--muted); margin-bottom:4px; flex-wrap:wrap; } .collab-dot{ width:7px; height:7px; border-radius:50%; background:var(--collab-st); flex:0 0 auto; } -.collab-st-ic{ display:inline-flex; align-items:center; justify-content:center; width:14px; height:14px; font-size:10px; font-weight:700; flex:0 0 auto; } +.collab-st-ic{ display:inline-flex; align-items:center; justify-content:center; width:14px; height:14px; font-size:10px; font-weight:500; flex:0 0 auto; } .collab-st-ic--ok{ color:var(--ok); } .collab-st-ic--done{ color:var(--muted); } .collab-st-ic--warn{ color:var(--danger); } .collab-st-ic--pause,.collab-st-ic--off{ color:var(--muted); } .collab-card-time{ margin-left:auto; font-size:10px; color:var(--muted); opacity:.85; } -.collab-card-title{ font-size:13px; font-weight:600; color:var(--txt-strong); margin-bottom:3px; line-height:1.3; } +.collab-card-title{ font-size:13px; font-weight:500; color:var(--txt-strong); margin-bottom:3px; line-height:1.35; } .collab-card-sum{ font-size:11px; color:var(--muted); line-height:1.35; cursor:pointer; } .collab-drawer-wrap{ position:fixed; inset:0; z-index:550; display:flex; } .collab-drawer-backdrop{ position:absolute; inset:0; background:var(--overlay); } @@ -2315,9 +2331,9 @@ html[data-appearance="dark"] .bubble.md pre code{ color:var(--txt-2); } display:flex; align-items:center; justify-content:space-between; padding:14px 16px; border-bottom:1px solid var(--line-soft); } -.collab-drawer-title{ font-size:14px; font-weight:700; color:var(--txt-strong); } +.collab-drawer-title{ font-size:14px; font-weight:600; color:var(--txt-strong); } .collab-drawer-body{ - flex:1; overflow-y:auto; padding:16px; font-size:13px; line-height:1.6; color:var(--txt); + flex:1; overflow-y:auto; padding:16px; font-size:13px; line-height:1.55; color:var(--txt); } .collab-drawer-body p,.collab-drawer-body ul,.collab-drawer-body ol,.collab-drawer-body pre{ margin:0 0 .5em; } .collab-drawer-body code{ font-size:12px; background:var(--field-bg); padding:1px 4px; border-radius:4px; } @@ -2345,7 +2361,7 @@ html[data-appearance="dark"] .bubble.md pre code{ color:var(--txt-2); } .collab-guide{ width:100%; max-width:var(--chat-col-w); margin:0 auto; } .collab-guide .feature-head{ text-align:center; margin-bottom:22px; } .collab-guide .page-title{ font-size:20px; line-height:1.35; margin-bottom:2px; } -.collab-guide .page-sub{ font-size:13px; line-height:1.6; margin-top:10px; margin-bottom:0; } +.collab-guide .page-sub{ font-size:13px; line-height:1.55; margin-top:10px; margin-bottom:0; } .collab-guide-steps{ display:grid; grid-template-columns:repeat(4, minmax(0, 1fr)); gap:48px 56px; margin:0 0 8px; align-items:start; @@ -2363,11 +2379,11 @@ html[data-appearance="dark"] .bubble.md pre code{ color:var(--txt-2); } } .collab-guide-ic svg{ width:24px; height:24px; } .collab-guide-txt{ display:flex; flex-direction:column; gap:12px; width:100%; } -.collab-guide-label{ font-size:14px; font-weight:600; color:var(--txt-strong); line-height:1.45; letter-spacing:.01em; } -.collab-guide-desc{ font-size:12px; font-weight:400; font-style:italic; color:var(--muted); line-height:1.7; } +.collab-guide-label{ font-size:14px; font-weight:500; color:var(--txt-strong); line-height:1.35; } +.collab-guide-desc{ font-size:12px; font-weight:400; font-style:italic; color:var(--muted); line-height:1.55; } .collab-nav-badge{ margin-left:auto; min-width:18px; height:18px; padding:0 5px; border-radius:999px; - background:var(--ok); color:#fff; font-size:10px; font-weight:700; line-height:18px; text-align:center; + background:var(--ok); color:#fff; font-size:10px; font-weight:500; line-height:1; text-align:center; } .page.page--chat-ui[data-page="collab"] > .chat-shell > .chat-panel > .collab-quick{ flex:0 0 auto; From a34d3df0111db647741ef386f35146b1f6893ffb Mon Sep 17 00:00:00 2001 From: dd3xp Date: Wed, 17 Jun 2026 21:13:26 +0800 Subject: [PATCH 2/2] =?UTF-8?q?feat(desktop):=20collab=20offline=20UI=20?= =?UTF-8?q?=E2=80=94=20replace=20banner=20with=20topbar=20status=20+=20ref?= =?UTF-8?q?resh=20icon?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous collab page showed a wide banner with the long offline message plus a "重试" chip button across the top, which looked clunky. Move both into the existing page-top status bar: - Drop .collab-offline and .collab-reconnect
banners entirely (HTML, CSS rules, and JS show/hide logic). - Wrap .run-state and a new .collab-retry-btn in a .page-top-center flex container (grid-column:2 of the page-top grid). - Topbar text replaces "未连接" with the new collab.offlineShort string ("无法连接 Conductor(8900)" / "Cannot reach Conductor (8900)") via collabStatus.set(longer, 'offline'). - The retry button is a 24×24 button styled like .new-conv (var(--line-soft) bg + 1px border + 4px radius, hover var(--hover-2)), holding a 14×14 inline SVG refresh-cw icon. Hidden by default, shown only when offline AND no auto-reconnect is in progress. - setConnUi simplified to just toggle the retry icon's [hidden] attribute. - Existing click handler on #collab-retry preserved (id unchanged). --- frontends/desktop/static/app.js | 15 ++++++--------- frontends/desktop/static/index.html | 20 ++++++++++---------- frontends/desktop/static/styles.css | 25 ++++++++++++++++--------- 3 files changed, 32 insertions(+), 28 deletions(-) diff --git a/frontends/desktop/static/app.js b/frontends/desktop/static/app.js index 268a9a0b..ebb12f1e 100644 --- a/frontends/desktop/static/app.js +++ b/frontends/desktop/static/app.js @@ -324,6 +324,7 @@ const I18N = { 'collab.switchMode': '切换模式', 'collab.typing': '指挥家正在处理', 'collab.offline': '无法连接 Conductor(8900)。请确认服务已启动且本地已穿透 8900 端口。', + 'collab.offlineShort': '无法连接 Conductor(8900)', 'collab.retry': '重试', 'collab.reconnect': '连接断开,正在重连… 已保留上次任务进度。', 'collab.reconnectIn': '{n} 秒后重试', @@ -484,6 +485,7 @@ const I18N = { 'collab.switchMode': 'Switch mode', 'collab.typing': 'Conductor is working', 'collab.offline': 'Cannot reach Conductor (8900). Start the service and forward port 8900.', + 'collab.offlineShort': 'Cannot reach Conductor (8900)', 'collab.retry': 'Retry', 'collab.reconnect': 'Disconnected — reconnecting… Your last progress is kept.', 'collab.reconnectIn': 'Retry in {n}s', @@ -5382,20 +5384,15 @@ function bindComposerInRoot(root, opts) { if (S.conductorTyping && S.serviceAvailable) collabStatus.setBusy(t('status.running')); else if (S.serviceAvailable) collabStatus.setReady(); else if (S.reconnecting || (!S.everConnected && S.failCount < FAIL_MAX)) collabStatus.setConnecting(); - else collabStatus.setDisconnected(); + else collabStatus.set(t('collab.offlineShort'), 'offline'); // 顶栏直接显示"无法连接 Conductor(8900)"取代"未连接" } function setConnUi() { - const off = $('collab-offline'), recon = $('collab-reconnect'); + const retry = $('collab-retry'); const avail = S.serviceAvailable; const trying = !avail && !S.everConnected && S.failCount < FAIL_MAX; - if (off) off.hidden = avail || S.reconnecting || trying; - if (recon) { - recon.hidden = !S.reconnecting; - recon.textContent = S.reconnecting && S.reconnectAt > Date.now() - ? t('collab.reconnect') + ' ' + t('collab.reconnectIn').replace('{n}', Math.ceil((S.reconnectAt - Date.now()) / 1000)) - : t('collab.reconnect'); - } + // 只有"真离线且不在自动重连"才显示刷新图标(右边的手动重试入口) + if (retry) retry.hidden = avail || S.reconnecting || trying; window.collabComposer?.setEnabled?.(avail); syncCollabStatus(); syncDraft(); diff --git a/frontends/desktop/static/index.html b/frontends/desktop/static/index.html index ec7dab11..deaf6afe 100644 --- a/frontends/desktop/static/index.html +++ b/frontends/desktop/static/index.html @@ -4,7 +4,7 @@ GenericAgent - + @@ -226,18 +226,18 @@
- -
- +
+ + +
@@ -638,6 +638,6 @@ - + diff --git a/frontends/desktop/static/styles.css b/frontends/desktop/static/styles.css index 89cf350d..a5e2837e 100644 --- a/frontends/desktop/static/styles.css +++ b/frontends/desktop/static/styles.css @@ -2171,17 +2171,24 @@ html[data-appearance="dark"] .bubble.md pre code{ color:var(--txt-2); } border-radius:var(--radius-sm); } -/* ---- Conductor(仅保留与主聊天不同的部分,布局见 .page--chat-ui) ---- */ -.collab-offline,.collab-reconnect{ - flex:0 0 auto; padding:10px 16px; font-size:13px; text-align:center; - background:color-mix(in srgb, var(--amber) 12%, var(--panel)); - border-bottom:1px solid var(--line); align-items:center; justify-content:center; gap:10px; -} -.collab-offline[hidden], .collab-reconnect[hidden], #collab-welcome[hidden], .collab-msgs .msgs[hidden], +/* ---- Conductor(仅保留与主聊天不同的部分,布局见 .page--chat-ui) ---- */ +#collab-welcome[hidden], .collab-msgs .msgs[hidden], .collab-rail[hidden], .collab-prog-stats[hidden], .collab-rail-run[hidden], .collab-rail-done[hidden], .collab-rail-issue[hidden]{ display:none !important; } -.collab-offline:not([hidden]), .collab-reconnect:not([hidden]){ display:flex; } -.collab-reconnect{ background:color-mix(in srgb, var(--accent) 10%, var(--panel)); } +/* 顶栏中央:状态栏 + 离线时的刷新图标按钮(取代原本的 banner+重试) */ +.page > .page-top .page-top-center{ + grid-column:2; display:flex; align-items:center; justify-content:center; gap:6px; + min-width:0; +} +/* 收尾按钮:跟 .new-conv 同款带底色,长得像 button 而不是 icon */ +.collab-retry-btn{ + width:24px; height:24px; + border:1px solid var(--line); background:var(--line-soft); border-radius:4px; + opacity:1; color:var(--txt-2); +} +.collab-retry-btn:hover{ background:var(--hover-2); color:var(--txt); opacity:1; } +.collab-retry-btn svg{ width:14px; height:14px; } +.collab-retry-btn[hidden]{ display:none !important; } .page.page--chat-ui[data-page="collab"] .msg-area.collab-msgs{ overflow:hidden; padding:0; } .page.page--chat-ui[data-page="collab"] .collab-scroll{ flex:1 1 0; min-height:0; overflow:auto;