From 5511652b079148cc623705c998bee7fe752dd6fb Mon Sep 17 00:00:00 2001 From: Conner512 <51692123+Conner512@users.noreply.github.com> Date: Mon, 21 Sep 2026 14:20:51 +0800 Subject: [PATCH] ui: align console and OAuth screens with Layout A Polish the shared desktop shell, four-column overview and 40/60 auth layout. Add local SVG presentation helpers and functional theme preview cards while preserving account-scoped preferences, read-only APIs, CSRF forms and CSP. Keep metrics source-backed and add presentation regression tests. --- services/oauth/test/console-layout-a.test.mjs | 88 +++++++ web/console/app.mjs | 14 +- web/console/appearance.mjs | 52 ++-- web/console/catalog.mjs | 39 +++ web/console/render.mjs | 29 ++- web/console/styles.css | 242 +++++++++++++++++- web/console/visuals.mjs | 54 ++++ 7 files changed, 484 insertions(+), 34 deletions(-) create mode 100644 services/oauth/test/console-layout-a.test.mjs create mode 100644 web/console/visuals.mjs diff --git a/services/oauth/test/console-layout-a.test.mjs b/services/oauth/test/console-layout-a.test.mjs new file mode 100644 index 0000000..ee6e7ac --- /dev/null +++ b/services/oauth/test/console-layout-a.test.mjs @@ -0,0 +1,88 @@ +// Presentation regressions; these do not replace authentication or isolation suites. +import test from 'node:test'; +import assert from 'node:assert/strict'; +import fs from 'node:fs'; +import {renderPage,sendPage,serveAsset,pages} from '../../../web/console/render.mjs'; +import {overviewView,appearanceView,icon} from '../../../web/console/visuals.mjs'; +import {text,catalog} from '../../../web/console/catalog.mjs'; + +const view = (data={}) => overviewView(data,{t:text,memoryRows:()=>'
'}); +const response = () => ({writeHead(status,headers){this.status=status;this.headers=headers;},end(body){this.body=body;}}); + +test('Layout A: overview uses source-backed counts, not demo trends or connection claims',()=>{ + const html=view({counts:{memories:42,sources:68,summaries:7,jobs:3}}); + for(const value of [42,68,7,3])assert.ok(html.includes(`${value}`)); + assert.equal((html.match(/class="card metric"/g)||[]).length,4); + assert.match(html,/class="processing-card|class="card processing-card/); + assert.match(html,/class="synthetic-row"/); + assert.doesNotMatch(html,/1,248|24\s*\/\s*24|已连接|已完成|