From 993b6b968c2c833f1cdd73c813ab39c25f492bca Mon Sep 17 00:00:00 2001 From: Jack Date: Mon, 19 Oct 2026 15:23:01 +0800 Subject: [PATCH] give the pages the CYBER shell they were missing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The token swap made every control dark, but the pages themselves kept their Arco defaults — bare `padding: 20px` with components laid straight on the background. That is why the running app still read as "not the prototype" no matter how many variables were replaced: the prototype's page structure (panel / panel-h / panel-b / kv / tabs) was never built. Rather than restate that shell in each of the 25 views, it now lives in global.scss as .cy-view / .cy-panel / .cy-panel-h / .cy-panel-b / .cy-kv / .cy-tabs / .cy-tab / .cy-stack / .cy-sec-t, and the settings components share a global .settings-section + .section-title so all nine panes pick up the mono section headers at once. The per-component duplicates of those two rules were deleted. Settings is converted as the reference case: Arco's a-tabs/a-tab-pane became the underline tab strip, and the pane body sits in a panel. The URL-query sync moved to a watcher on activeTab so pane order and deep links still hold. Pane order is a contract, so it is asserted. Two tests lock the shell in place — one for the global classes and the cyan underline selected state, one for the settings structure and pane order. Without them the next edit easily slides back to bare Arco. --- .../hermes/settings/AccountSettings.vue | 5 +- .../hermes/settings/AgentSettings.vue | 3 - .../hermes/settings/CompressionSettings.vue | 4 - .../hermes/settings/DisplaySettings.vue | 4 - .../settings/GatewayAutoStartSettings.vue | 14 +- .../hermes/settings/MemorySettings.vue | 4 - .../hermes/settings/ModelSettings.vue | 4 - .../hermes/settings/PlatformSettings.vue | 4 - .../hermes/settings/PrivacySettings.vue | 3 - .../hermes/settings/ProxySettings.vue | 15 +- .../hermes/settings/SessionSettings.vue | 3 - .../components/hermes/settings/SettingRow.vue | 28 ++- .../settings/UserManagementSettings.vue | 6 +- packages/client/src/i18n/locales/en.ts | 1 + packages/client/src/i18n/locales/zh.ts | 1 + packages/client/src/styles/global.scss | 189 ++++++++++++++++++ .../client/src/views/hermes/SettingsView.vue | 121 +++++++---- tests/client/style-system.test.ts | 32 +++ 18 files changed, 346 insertions(+), 95 deletions(-) diff --git a/packages/client/src/components/hermes/settings/AccountSettings.vue b/packages/client/src/components/hermes/settings/AccountSettings.vue index c251dc6..2109331 100644 --- a/packages/client/src/components/hermes/settings/AccountSettings.vue +++ b/packages/client/src/components/hermes/settings/AccountSettings.vue @@ -392,10 +392,7 @@ onMounted(() => { loadLockedIps(); }); } .section-title { - font-size: 15px; - font-weight: 600; - color: $text-primary; - margin: 0 0 16px; + margin: 0 0 12px; } .locked-list { diff --git a/packages/client/src/components/hermes/settings/AgentSettings.vue b/packages/client/src/components/hermes/settings/AgentSettings.vue index e60d115..54017e2 100644 --- a/packages/client/src/components/hermes/settings/AgentSettings.vue +++ b/packages/client/src/components/hermes/settings/AgentSettings.vue @@ -81,7 +81,4 @@ function debouncedSave(key: string, value: any) { diff --git a/packages/client/src/components/hermes/settings/CompressionSettings.vue b/packages/client/src/components/hermes/settings/CompressionSettings.vue index af9991f..0cd80a7 100644 --- a/packages/client/src/components/hermes/settings/CompressionSettings.vue +++ b/packages/client/src/components/hermes/settings/CompressionSettings.vue @@ -99,8 +99,4 @@ function debouncedSave(key: string, value: any) { diff --git a/packages/client/src/components/hermes/settings/DisplaySettings.vue b/packages/client/src/components/hermes/settings/DisplaySettings.vue index 0bcb479..d11613b 100644 --- a/packages/client/src/components/hermes/settings/DisplaySettings.vue +++ b/packages/client/src/components/hermes/settings/DisplaySettings.vue @@ -128,10 +128,6 @@ async function testCompletionNotification() { diff --git a/packages/client/src/components/hermes/settings/ModelSettings.vue b/packages/client/src/components/hermes/settings/ModelSettings.vue index 693d1ce..7c61006 100644 --- a/packages/client/src/components/hermes/settings/ModelSettings.vue +++ b/packages/client/src/components/hermes/settings/ModelSettings.vue @@ -126,10 +126,6 @@ async function handleSaveCustom(providerKey: string) { diff --git a/packages/client/src/components/hermes/settings/ProxySettings.vue b/packages/client/src/components/hermes/settings/ProxySettings.vue index 05d65e4..ba2f0e0 100644 --- a/packages/client/src/components/hermes/settings/ProxySettings.vue +++ b/packages/client/src/components/hermes/settings/ProxySettings.vue @@ -75,14 +75,21 @@ async function save() { } .section-title { - margin: 0 0 6px; - font-size: 18px; + margin: 0 0 8px; + padding-bottom: 8px; + border-bottom: 1px solid $border-light; + font-family: $font-code; + font-size: 12.5px; + font-weight: 600; + letter-spacing: 0.04em; + color: $text-primary; } .section-hint { - margin: 0 0 16px; + margin: 0 0 14px; color: $text-muted; - font-size: 13px; + font-size: 12.5px; + line-height: 1.6; } .input-lg { diff --git a/packages/client/src/components/hermes/settings/SessionSettings.vue b/packages/client/src/components/hermes/settings/SessionSettings.vue index 75e6e32..cc29d1c 100644 --- a/packages/client/src/components/hermes/settings/SessionSettings.vue +++ b/packages/client/src/components/hermes/settings/SessionSettings.vue @@ -145,7 +145,4 @@ async function toggleWriteApproval(section: "memory" | "skills", value: boolean) diff --git a/packages/client/src/components/hermes/settings/SettingRow.vue b/packages/client/src/components/hermes/settings/SettingRow.vue index c0dfe4d..970c9e1 100644 --- a/packages/client/src/components/hermes/settings/SettingRow.vue +++ b/packages/client/src/components/hermes/settings/SettingRow.vue @@ -20,37 +20,53 @@ defineProps<{ diff --git a/tests/client/style-system.test.ts b/tests/client/style-system.test.ts index 89703ce..ba308ac 100644 --- a/tests/client/style-system.test.ts +++ b/tests/client/style-system.test.ts @@ -57,6 +57,38 @@ describe('client style system', () => { expect(source).not.toMatch(/localStorage\.getItem\(['"]hermes_(brightness|style)/) }) + it('exposes the CYBER page shell so pages stop falling back to bare Arco layouts', () => { + // 原型里每个页面都是 panel / panel-h / panel-b / kv / tabs 这套外壳。 + // 25 个页面各写一遍同样的框会漂移,所以抽成全局类并在这里锁住。 + const globalStyles = readClientFile('styles/global.scss') + + for (const cls of ['.cy-view', '.cy-panel', '.cy-panel-h', '.cy-panel-b', '.cy-kv', '.cy-tabs', '.cy-tab']) { + expect(globalStyles).toContain(cls) + } + + // 选中态必须是霓虹青 + 发丝下划线,不是胶囊底色。 + const onRule = globalStyles.slice(globalStyles.indexOf('&.on {'), globalStyles.indexOf('&.dis {')) + expect(onRule).toContain('color: $accent-primary;') + expect(onRule).toContain('border-bottom-color: $accent-primary;') + }) + + it('keeps the settings shell on the shared page header baseline', () => { + // 设置页是唯一有 11 个 pane 的页面,最容易退回 Arco 的 a-tabs 默认外观。 + const settingsView = readClientFile('views/hermes/SettingsView.vue') + + expect(settingsView).toContain('cy-tabs') + expect(settingsView).toContain('cy-panel') + // 不再依赖 a-tabs / a-tab-pane。 + expect(settingsView).not.toContain(' settingsView.indexOf(`key: "${key}"`)) + expect(positions.every(p => p > 0)).toBe(true) + expect([...positions].sort((a, b) => a - b)).toEqual(positions) + }) + it('keeps mobile inputs at 16px so iOS does not zoom on focus', () => { const globalStyles = readClientFile('styles/global.scss')