From 3b75bf2d63ae4ac84513c93aa7da1be9cf813ab7 Mon Sep 17 00:00:00 2001 From: leefer Date: Thu, 30 Jul 2026 02:08:20 +0800 Subject: [PATCH] rebuild(stage-4): deliver shared shell and account interfaces --- next/docs/evidence/stage-4/README.md | 78 ++++ .../evidence/stage-4/shell-dark-1920x1080.jpg | Bin 0 -> 59217 bytes .../evidence/stage-4/shell-dark-390x844.jpg | Bin 0 -> 18935 bytes .../stage-4/shell-light-1920x1080.jpg | Bin 0 -> 59053 bytes .../stage-4/system-dark-3840x2160.jpg | Bin 0 -> 120873 bytes next/frontend/index.html | 11 + next/frontend/src/app/App.vue | 31 +- next/frontend/src/app/router.ts | 16 +- next/frontend/src/app/shell/AppShell.vue | 42 +++ .../frontend/src/app/shell/DesktopSidebar.vue | 26 ++ next/frontend/src/app/shell/MarketStrip.vue | 29 ++ next/frontend/src/app/shell/MobileNav.vue | 9 + next/frontend/src/app/shell/StatusBar.vue | 17 + next/frontend/src/app/shell/TopBar.vue | 96 +++++ .../src/app/system/MarketSettingsPanel.vue | 76 ++++ .../src/app/system/MembershipAdminPanel.vue | 104 ++++++ .../src/app/system/ModelPoolPanel.vue | 151 ++++++++ next/frontend/src/app/views/AuthView.vue | 53 +++ next/frontend/src/app/views/BootstrapView.vue | 64 ---- .../src/app/views/SystemManagementView.vue | 33 ++ next/frontend/src/app/views/WorkspaceView.vue | 35 ++ .../src/app/workspaceRegistry.test.ts | 18 + next/frontend/src/app/workspaceRegistry.ts | 34 ++ next/frontend/src/main.ts | 8 + .../src/shared/account/MembershipPanel.vue | 62 ++++ .../src/shared/account/PasswordPanel.vue | 45 +++ .../src/shared/account/ProfilePanel.vue | 109 ++++++ .../src/shared/account/SearchPanel.vue | 19 + next/frontend/src/shared/api/client.test.ts | 19 + next/frontend/src/shared/api/client.ts | 34 +- .../src/shared/components/BaseDialog.vue | 69 ++++ .../src/shared/components/DialogHost.vue | 20 ++ .../src/shared/components/EmptyState.vue | 12 + .../src/shared/components/ToastHost.vue | 11 + next/frontend/src/shared/stores/market.ts | 23 ++ next/frontend/src/shared/stores/session.ts | 72 ++++ next/frontend/src/shared/stores/ui.ts | 53 +++ next/frontend/src/shared/styles/account.css | 137 ++++++++ next/frontend/src/shared/styles/auth.css | 69 ++++ next/frontend/src/shared/styles/base.css | 81 ++++- .../frontend/src/shared/styles/components.css | 332 ++++++++++++++++++ next/frontend/src/shared/styles/mobile.css | 152 ++++++++ next/frontend/src/shared/styles/shell.css | 327 +++++++++++++++++ next/frontend/src/shared/styles/system.css | 206 +++++++++++ next/frontend/src/shared/styles/tokens.css | 210 +++++++++-- next/playwright.config.js | 16 + next/tests/e2e/stage4.spec.js | 132 +++++++ 47 files changed, 3042 insertions(+), 99 deletions(-) create mode 100644 next/docs/evidence/stage-4/README.md create mode 100644 next/docs/evidence/stage-4/shell-dark-1920x1080.jpg create mode 100644 next/docs/evidence/stage-4/shell-dark-390x844.jpg create mode 100644 next/docs/evidence/stage-4/shell-light-1920x1080.jpg create mode 100644 next/docs/evidence/stage-4/system-dark-3840x2160.jpg create mode 100644 next/frontend/src/app/shell/AppShell.vue create mode 100644 next/frontend/src/app/shell/DesktopSidebar.vue create mode 100644 next/frontend/src/app/shell/MarketStrip.vue create mode 100644 next/frontend/src/app/shell/MobileNav.vue create mode 100644 next/frontend/src/app/shell/StatusBar.vue create mode 100644 next/frontend/src/app/shell/TopBar.vue create mode 100644 next/frontend/src/app/system/MarketSettingsPanel.vue create mode 100644 next/frontend/src/app/system/MembershipAdminPanel.vue create mode 100644 next/frontend/src/app/system/ModelPoolPanel.vue create mode 100644 next/frontend/src/app/views/AuthView.vue delete mode 100644 next/frontend/src/app/views/BootstrapView.vue create mode 100644 next/frontend/src/app/views/SystemManagementView.vue create mode 100644 next/frontend/src/app/views/WorkspaceView.vue create mode 100644 next/frontend/src/app/workspaceRegistry.test.ts create mode 100644 next/frontend/src/app/workspaceRegistry.ts create mode 100644 next/frontend/src/shared/account/MembershipPanel.vue create mode 100644 next/frontend/src/shared/account/PasswordPanel.vue create mode 100644 next/frontend/src/shared/account/ProfilePanel.vue create mode 100644 next/frontend/src/shared/account/SearchPanel.vue create mode 100644 next/frontend/src/shared/components/BaseDialog.vue create mode 100644 next/frontend/src/shared/components/DialogHost.vue create mode 100644 next/frontend/src/shared/components/EmptyState.vue create mode 100644 next/frontend/src/shared/components/ToastHost.vue create mode 100644 next/frontend/src/shared/stores/market.ts create mode 100644 next/frontend/src/shared/stores/session.ts create mode 100644 next/frontend/src/shared/stores/ui.ts create mode 100644 next/frontend/src/shared/styles/account.css create mode 100644 next/frontend/src/shared/styles/auth.css create mode 100644 next/frontend/src/shared/styles/components.css create mode 100644 next/frontend/src/shared/styles/mobile.css create mode 100644 next/frontend/src/shared/styles/shell.css create mode 100644 next/frontend/src/shared/styles/system.css create mode 100644 next/playwright.config.js create mode 100644 next/tests/e2e/stage4.spec.js diff --git a/next/docs/evidence/stage-4/README.md b/next/docs/evidence/stage-4/README.md new file mode 100644 index 0000000..863e772 --- /dev/null +++ b/next/docs/evidence/stage-4/README.md @@ -0,0 +1,78 @@ +# 阶段4验收记录 + +## 范围 + +本阶段只验收全局前端基础和阶段3已有业务的前端交互:认证、16项工作区注册表、PC/移动Shell、主题、日期、统一API、统一弹窗与Toast、账户菜单、会员状态、系统凭据、模型池和会员管理。 + +行情摘要真实数据、全局搜索结果、后台刷新任务和16个工作区的业务内容分别属于阶段5及后续阶段。本阶段只提供稳定入口和明确空态,不将这些页面报告为已迁移。 + +## 设计规范第12节自检 + +### 表格 + +- 会员管理表按内容类型分配列宽;每日上限为右对齐等宽数字。 +- 单位写在“每日上限(次)”表头,空到期时间保持为空。 +- 每日上限表头可排序,并显示当前升降方向。 +- 本阶段没有行情图表;图例规则留到实际图表切片验收,未用占位图假装完成。 + +### 间距 + +- Playwright实测PC内容区上内边距14px、左右内边距16px。 +- 侧栏200px、顶栏46px、摘要条收起36px、状态栏30px均来自唯一令牌。 +- 16个工作区共用同一Shell和动态路由,不存在页面专属骨架副本。 + +### 字体 + +- 页面标题17px/800、卡片标题14px/700、正文13px、辅助文字11至12px。 +- 数字使用`tabular-nums`;未使用随视口连续缩放字号或负字距。 + +### 布局 + +- Shell与页面内容分离;4K内容限制最大可读宽度,没有将卡片和字体放大两倍。 +- 1023px及以下进入独立移动Shell,底部保留“行情、选股、问师、问天、复盘”五个入口。 +- 1920×1080、3840×2160和390×844实测无页面横向溢出。 + +### 细节 + +- 顶栏日期固定为`YYYY-MM-DD`,不使用会按Windows区域设置显示斜杠的原生日期外观。 +- 市场数据未接入时保留空值和原因,不展示模拟数字或满屏`--`。 +- 状态栏固定于视口底部;短页面不会把风险提示上移。 +- 日间/夜间在Vue挂载前选择主题,弹窗、表单、表格和空态均使用语义令牌。 +- 弹窗位于视口中心,支持Escape、遮罩关闭、焦点循环和焦点回收;成功反馈只使用自适应Toast。 + +## 权限与交互 + +- 真实注册/登录通过;首个账号显示管理员,普通用户不显示后台刷新和系统管理。 +- 管理员兼会员时前端可同时显示两个标识;管理员未开会员时仍显示真实“普通用户”会员状态。 +- 账户菜单严格包含个人资料、会员状态、修改密码、切换账号、退出五项。 +- 浏览器实际保存并重读个人出生资料;会员状态显示开通状态、到期、剩余时长、今日用量、今日剩余和暂不可用加油包。 +- 普通用户访问智能选股、问师和问天时保留相同页面结构,顶部提示会员限制,内容不可操作。 +- 非管理员直接访问`/system`会被前端送回情绪周期,所有管理API仍由后端独立拒绝。 + +## 减法证据 + +- 16项工作区只在`workspaceRegistry.ts`登记一次,路由和两种导航共同读取。 +- 浏览器请求只经`shared/api/client.ts`,CSRF由该出口统一附加。 +- 全站只存在一个主题Store、一个当前会话Store、一个弹窗Host和一个Toast Host。 +- CSS按令牌、基础、组件、Shell、账户、系统和移动端职责拆分;最长CSS为332行,未复制原型整份样式或增加覆盖补丁层。 +- 组件CSS未出现令牌文件之外的色值;`1023px`仅作为CSS媒体查询不可变量化的语法边界。 + +## 自动验证 + +- Ruff:通过。 +- pytest:40项通过。 +- Vue类型检查:通过。 +- Vitest:2个文件、5项通过。 +- Vite生产构建:通过。 +- Playwright:2项通过,覆盖管理员与普通用户、账户真实写入、三类系统管理、Ctrl+K、主题持久化、弹窗居中、桌面/4K/移动视口、HTTP失败和控制台错误审计。 + +## 截图 + +- [日间Shell 1920×1080](shell-light-1920x1080.jpg) +- [夜间Shell 1920×1080](shell-dark-1920x1080.jpg) +- [夜间系统管理 3840×2160](system-dark-3840x2160.jpg) +- [夜间移动Shell 390×844](shell-dark-390x844.jpg) + +## 后续入口 + +阶段5建立唯一数据网关、交易日期真相、行情快照、搜索和图表基础后,替换当前市场摘要与工作区空态。移动端逐页业务信息重组仍在阶段13完成,不把本阶段的移动Shell当作全部移动页面验收。 diff --git a/next/docs/evidence/stage-4/shell-dark-1920x1080.jpg b/next/docs/evidence/stage-4/shell-dark-1920x1080.jpg new file mode 100644 index 0000000000000000000000000000000000000000..967c40b08ccdb90997ee8fc09e124e5d1e3b6f2a GIT binary patch literal 59217 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 literal 0 HcmV?d00001 diff --git a/next/docs/evidence/stage-4/shell-dark-390x844.jpg b/next/docs/evidence/stage-4/shell-dark-390x844.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1748058f93961bd1a4aac8720479306c1a967a25 GIT binary patch literal 18935 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 literal 0 HcmV?d00001 diff --git a/next/docs/evidence/stage-4/shell-light-1920x1080.jpg b/next/docs/evidence/stage-4/shell-light-1920x1080.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1761c1b19a154d5008ed2db755137a796faf981e GIT binary patch literal 59053 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 literal 0 HcmV?d00001 diff --git a/next/frontend/index.html b/next/frontend/index.html index a2641b8..c0ef21b 100644 --- a/next/frontend/index.html +++ b/next/frontend/index.html @@ -4,6 +4,17 @@ + + 小白复盘 diff --git a/next/frontend/src/app/App.vue b/next/frontend/src/app/App.vue index 7c2aa3f..3baee9f 100644 --- a/next/frontend/src/app/App.vue +++ b/next/frontend/src/app/App.vue @@ -1,3 +1,32 @@ + + diff --git a/next/frontend/src/app/router.ts b/next/frontend/src/app/router.ts index d31e5c9..8571854 100644 --- a/next/frontend/src/app/router.ts +++ b/next/frontend/src/app/router.ts @@ -1,8 +1,20 @@ import { createRouter, createWebHistory } from "vue-router"; -import BootstrapView from "./views/BootstrapView.vue"; +import SystemManagementView from "./views/SystemManagementView.vue"; +import WorkspaceView from "./views/WorkspaceView.vue"; +import { findWorkspace } from "./workspaceRegistry"; export default createRouter({ history: createWebHistory(), - routes: [{ path: "/", name: "bootstrap", component: BootstrapView }], + routes: [ + { path: "/", redirect: "/workspace/emotion" }, + { + path: "/workspace/:workspace", + name: "workspace", + component: WorkspaceView, + beforeEnter: (to) => (findWorkspace(String(to.params.workspace)) ? true : "/workspace/emotion"), + }, + { path: "/system", name: "system", component: SystemManagementView }, + { path: "/:pathMatch(.*)*", redirect: "/workspace/emotion" }, + ], }); diff --git a/next/frontend/src/app/shell/AppShell.vue b/next/frontend/src/app/shell/AppShell.vue new file mode 100644 index 0000000..cac0a86 --- /dev/null +++ b/next/frontend/src/app/shell/AppShell.vue @@ -0,0 +1,42 @@ + + + diff --git a/next/frontend/src/app/shell/DesktopSidebar.vue b/next/frontend/src/app/shell/DesktopSidebar.vue new file mode 100644 index 0000000..11971a8 --- /dev/null +++ b/next/frontend/src/app/shell/DesktopSidebar.vue @@ -0,0 +1,26 @@ + + + diff --git a/next/frontend/src/app/shell/MarketStrip.vue b/next/frontend/src/app/shell/MarketStrip.vue new file mode 100644 index 0000000..ce47dc1 --- /dev/null +++ b/next/frontend/src/app/shell/MarketStrip.vue @@ -0,0 +1,29 @@ + + + diff --git a/next/frontend/src/app/shell/MobileNav.vue b/next/frontend/src/app/shell/MobileNav.vue new file mode 100644 index 0000000..de82f58 --- /dev/null +++ b/next/frontend/src/app/shell/MobileNav.vue @@ -0,0 +1,9 @@ + diff --git a/next/frontend/src/app/shell/StatusBar.vue b/next/frontend/src/app/shell/StatusBar.vue new file mode 100644 index 0000000..b37c3dd --- /dev/null +++ b/next/frontend/src/app/shell/StatusBar.vue @@ -0,0 +1,17 @@ + + + diff --git a/next/frontend/src/app/shell/TopBar.vue b/next/frontend/src/app/shell/TopBar.vue new file mode 100644 index 0000000..869b28c --- /dev/null +++ b/next/frontend/src/app/shell/TopBar.vue @@ -0,0 +1,96 @@ + + + diff --git a/next/frontend/src/app/system/MarketSettingsPanel.vue b/next/frontend/src/app/system/MarketSettingsPanel.vue new file mode 100644 index 0000000..cbc8f89 --- /dev/null +++ b/next/frontend/src/app/system/MarketSettingsPanel.vue @@ -0,0 +1,76 @@ + + + diff --git a/next/frontend/src/app/system/MembershipAdminPanel.vue b/next/frontend/src/app/system/MembershipAdminPanel.vue new file mode 100644 index 0000000..787bfb8 --- /dev/null +++ b/next/frontend/src/app/system/MembershipAdminPanel.vue @@ -0,0 +1,104 @@ + + + diff --git a/next/frontend/src/app/system/ModelPoolPanel.vue b/next/frontend/src/app/system/ModelPoolPanel.vue new file mode 100644 index 0000000..1246ff3 --- /dev/null +++ b/next/frontend/src/app/system/ModelPoolPanel.vue @@ -0,0 +1,151 @@ + + + diff --git a/next/frontend/src/app/views/AuthView.vue b/next/frontend/src/app/views/AuthView.vue new file mode 100644 index 0000000..6940fb5 --- /dev/null +++ b/next/frontend/src/app/views/AuthView.vue @@ -0,0 +1,53 @@ + + + diff --git a/next/frontend/src/app/views/BootstrapView.vue b/next/frontend/src/app/views/BootstrapView.vue deleted file mode 100644 index 3ef6162..0000000 --- a/next/frontend/src/app/views/BootstrapView.vue +++ /dev/null @@ -1,64 +0,0 @@ - - - - - diff --git a/next/frontend/src/app/views/SystemManagementView.vue b/next/frontend/src/app/views/SystemManagementView.vue new file mode 100644 index 0000000..beb5f47 --- /dev/null +++ b/next/frontend/src/app/views/SystemManagementView.vue @@ -0,0 +1,33 @@ + + + diff --git a/next/frontend/src/app/views/WorkspaceView.vue b/next/frontend/src/app/views/WorkspaceView.vue new file mode 100644 index 0000000..d4ebb95 --- /dev/null +++ b/next/frontend/src/app/views/WorkspaceView.vue @@ -0,0 +1,35 @@ + + + diff --git a/next/frontend/src/app/workspaceRegistry.test.ts b/next/frontend/src/app/workspaceRegistry.test.ts new file mode 100644 index 0000000..bd1b56e --- /dev/null +++ b/next/frontend/src/app/workspaceRegistry.test.ts @@ -0,0 +1,18 @@ +import { describe, expect, it } from "vitest"; + +import { findWorkspace, workspaceGroups, workspaces } from "./workspaceRegistry"; + +describe("workspace registry", () => { + it("contains the sixteen ordered product workspaces without duplicate routes", () => { + expect(workspaces).toHaveLength(16); + expect(workspaces[0]?.key).toBe("emotion"); + expect(workspaces.at(-1)?.key).toBe("review"); + expect(new Set(workspaces.map((item) => item.key)).size).toBe(16); + expect(workspaceGroups).toEqual(["市场复盘", "智能工具", "个人"]); + }); + + it("resolves registered workspaces only", () => { + expect(findWorkspace("heaven")?.title).toBe("问天"); + expect(findWorkspace("unknown")).toBeUndefined(); + }); +}); diff --git a/next/frontend/src/app/workspaceRegistry.ts b/next/frontend/src/app/workspaceRegistry.ts new file mode 100644 index 0000000..6fec275 --- /dev/null +++ b/next/frontend/src/app/workspaceRegistry.ts @@ -0,0 +1,34 @@ +export type WorkspaceGroup = "市场复盘" | "智能工具" | "个人"; + +export type Workspace = { + key: string; + title: string; + mark: string; + group: WorkspaceGroup; + description: string; +}; + +export const workspaces: readonly Workspace[] = [ + { key: "emotion", title: "情绪周期", mark: "情", group: "市场复盘", description: "全市场情绪温度与阶段" }, + { key: "pool", title: "涨停池", mark: "涨", group: "市场复盘", description: "当日封板股票与结构" }, + { key: "broken", title: "炸板池", mark: "炸", group: "市场复盘", description: "触板未封股票与原因" }, + { key: "limit-down", title: "跌停板", mark: "跌", group: "市场复盘", description: "跌停风险与聚集" }, + { key: "yesterday", title: "昨日涨停", mark: "昨", group: "市场复盘", description: "昨日涨停次日反馈" }, + { key: "performance", title: "涨停表现", mark: "表", group: "市场复盘", description: "晋级、兑现与断板" }, + { key: "ladder", title: "市场天梯", mark: "梯", group: "市场复盘", description: "连板梯队与市场高度" }, + { key: "rotation", title: "板块轮动", mark: "转", group: "市场复盘", description: "热点迁移与板块成分" }, + { key: "auction", title: "集合竞价", mark: "竞", group: "市场复盘", description: "题材承接与竞价异动" }, + { key: "themes", title: "题材库", mark: "题", group: "市场复盘", description: "题材排行与成分股" }, + { key: "popularity", title: "人气热榜", mark: "热", group: "市场复盘", description: "双平台人气与共识" }, + { key: "dragon-list", title: "龙虎榜", mark: "榜", group: "市场复盘", description: "上榜明细与活跃席位" }, + { key: "screener", title: "智能选股", mark: "选", group: "智能工具", description: "阶段、策略与自定义选股" }, + { key: "mentor", title: "问师", mark: "师", group: "智能工具", description: "思维模型复盘对话" }, + { key: "heaven", title: "问天", mark: "天", group: "智能工具", description: "观势、观气与观心" }, + { key: "review", title: "我的复盘", mark: "复", group: "个人", description: "自选、日志与每日复盘" }, +] as const; + +export const workspaceGroups: readonly WorkspaceGroup[] = ["市场复盘", "智能工具", "个人"]; + +export function findWorkspace(key: string): Workspace | undefined { + return workspaces.find((workspace) => workspace.key === key); +} diff --git a/next/frontend/src/main.ts b/next/frontend/src/main.ts index c1c1735..d79efdb 100644 --- a/next/frontend/src/main.ts +++ b/next/frontend/src/main.ts @@ -3,7 +3,15 @@ import { createApp } from "vue"; import App from "./app/App.vue"; import router from "./app/router"; +import { applyTheme, preferredTheme } from "./shared/stores/ui"; import "./shared/styles/tokens.css"; import "./shared/styles/base.css"; +import "./shared/styles/components.css"; +import "./shared/styles/shell.css"; +import "./shared/styles/auth.css"; +import "./shared/styles/account.css"; +import "./shared/styles/system.css"; +import "./shared/styles/mobile.css"; +applyTheme(preferredTheme()); createApp(App).use(createPinia()).use(router).mount("#app"); diff --git a/next/frontend/src/shared/account/MembershipPanel.vue b/next/frontend/src/shared/account/MembershipPanel.vue new file mode 100644 index 0000000..4b23076 --- /dev/null +++ b/next/frontend/src/shared/account/MembershipPanel.vue @@ -0,0 +1,62 @@ + + + diff --git a/next/frontend/src/shared/account/PasswordPanel.vue b/next/frontend/src/shared/account/PasswordPanel.vue new file mode 100644 index 0000000..9ffa8c9 --- /dev/null +++ b/next/frontend/src/shared/account/PasswordPanel.vue @@ -0,0 +1,45 @@ + + + diff --git a/next/frontend/src/shared/account/ProfilePanel.vue b/next/frontend/src/shared/account/ProfilePanel.vue new file mode 100644 index 0000000..9a22aee --- /dev/null +++ b/next/frontend/src/shared/account/ProfilePanel.vue @@ -0,0 +1,109 @@ + + + diff --git a/next/frontend/src/shared/account/SearchPanel.vue b/next/frontend/src/shared/account/SearchPanel.vue new file mode 100644 index 0000000..4628670 --- /dev/null +++ b/next/frontend/src/shared/account/SearchPanel.vue @@ -0,0 +1,19 @@ + + + diff --git a/next/frontend/src/shared/api/client.test.ts b/next/frontend/src/shared/api/client.test.ts index cb4b89b..2801bc5 100644 --- a/next/frontend/src/shared/api/client.test.ts +++ b/next/frontend/src/shared/api/client.test.ts @@ -45,4 +45,23 @@ describe("api client", () => { requestId: "abc", }); }); + + it("adds the readable CSRF cookie to write requests", async () => { + vi.stubGlobal("document", { cookie: "xiaobai_csrf=csrf-token-123" }); + const fetchMock = vi.fn().mockResolvedValue( + new Response(JSON.stringify({ message: "ok" }), { + status: 200, + headers: { "Content-Type": "application/json" }, + }), + ); + vi.stubGlobal("fetch", fetchMock); + + await api.patch("/account/password", { value: "changed" }); + + const request = fetchMock.mock.calls[0]?.[1] as RequestInit; + const headers = request.headers as Headers; + expect(request.method).toBe("PATCH"); + expect(headers.get("X-CSRF-Token")).toBe("csrf-token-123"); + expect(headers.get("Content-Type")).toBe("application/json"); + }); }); diff --git a/next/frontend/src/shared/api/client.ts b/next/frontend/src/shared/api/client.ts index b938504..971d9e8 100644 --- a/next/frontend/src/shared/api/client.ts +++ b/next/frontend/src/shared/api/client.ts @@ -18,10 +18,19 @@ export class ApiError extends Error { } async function request(path: string, init?: RequestInit): Promise { + const csrfToken = readCookie("xiaobai_csrf"); + const headers = new Headers(init?.headers); + headers.set("Accept", "application/json"); + if (init?.body) { + headers.set("Content-Type", "application/json"); + } + if (init?.method && init.method !== "GET" && csrfToken) { + headers.set("X-CSRF-Token", csrfToken); + } const response = await fetch(`/api${path}`, { credentials: "same-origin", - headers: { Accept: "application/json", ...init?.headers }, ...init, + headers, }); const payload = (await response.json().catch(() => ({}))) as T & ApiErrorPayload; if (!response.ok) { @@ -35,8 +44,31 @@ async function request(path: string, init?: RequestInit): Promise { return payload; } +function readCookie(name: string): string | undefined { + if (typeof document === "undefined") return undefined; + const prefix = `${encodeURIComponent(name)}=`; + const item = document.cookie.split("; ").find((value) => value.startsWith(prefix)); + return item ? decodeURIComponent(item.slice(prefix.length)) : undefined; +} + +function json(method: string, body?: unknown): RequestInit { + return { method, body: body === undefined ? undefined : JSON.stringify(body) }; +} + export const api = { get(path: string): Promise { return request(path); }, + post(path: string, body?: unknown): Promise { + return request(path, json("POST", body)); + }, + put(path: string, body?: unknown): Promise { + return request(path, json("PUT", body)); + }, + patch(path: string, body?: unknown): Promise { + return request(path, json("PATCH", body)); + }, + delete(path: string): Promise { + return request(path, json("DELETE")); + }, }; diff --git a/next/frontend/src/shared/components/BaseDialog.vue b/next/frontend/src/shared/components/BaseDialog.vue new file mode 100644 index 0000000..397d47b --- /dev/null +++ b/next/frontend/src/shared/components/BaseDialog.vue @@ -0,0 +1,69 @@ + + + diff --git a/next/frontend/src/shared/components/DialogHost.vue b/next/frontend/src/shared/components/DialogHost.vue new file mode 100644 index 0000000..06dc5b3 --- /dev/null +++ b/next/frontend/src/shared/components/DialogHost.vue @@ -0,0 +1,20 @@ + + + diff --git a/next/frontend/src/shared/components/EmptyState.vue b/next/frontend/src/shared/components/EmptyState.vue new file mode 100644 index 0000000..9f5d1ba --- /dev/null +++ b/next/frontend/src/shared/components/EmptyState.vue @@ -0,0 +1,12 @@ + + + diff --git a/next/frontend/src/shared/components/ToastHost.vue b/next/frontend/src/shared/components/ToastHost.vue new file mode 100644 index 0000000..1b38922 --- /dev/null +++ b/next/frontend/src/shared/components/ToastHost.vue @@ -0,0 +1,11 @@ + + + diff --git a/next/frontend/src/shared/stores/market.ts b/next/frontend/src/shared/stores/market.ts new file mode 100644 index 0000000..0d54eb1 --- /dev/null +++ b/next/frontend/src/shared/stores/market.ts @@ -0,0 +1,23 @@ +import { defineStore } from "pinia"; +import { ref } from "vue"; + +function shanghaiDate(): string { + return new Intl.DateTimeFormat("en-CA", { + timeZone: "Asia/Shanghai", + year: "numeric", + month: "2-digit", + day: "2-digit", + }).format(new Date()); +} + +export const useMarketStore = defineStore("market", () => { + const selectedDate = ref(shanghaiDate()); + + function moveDate(offset: number): void { + const date = new Date(`${selectedDate.value}T12:00:00+08:00`); + date.setUTCDate(date.getUTCDate() + offset); + selectedDate.value = date.toISOString().slice(0, 10); + } + + return { selectedDate, moveDate }; +}); diff --git a/next/frontend/src/shared/stores/session.ts b/next/frontend/src/shared/stores/session.ts new file mode 100644 index 0000000..74aebf0 --- /dev/null +++ b/next/frontend/src/shared/stores/session.ts @@ -0,0 +1,72 @@ +import { defineStore } from "pinia"; +import { computed, ref } from "vue"; + +import { api, ApiError } from "../api/client"; + +export type AccountIdentity = { + id: number; + username: string; + is_admin: boolean; + membership_status: string; + membership_active: boolean; + smart_access: boolean; + badges: string[]; +}; + +type AuthResponse = { + account: AccountIdentity; + csrf_token: string; +}; + +export const useSessionStore = defineStore("session", () => { + const account = ref(null); + const initialized = ref(false); + const busy = ref(false); + + const isAdmin = computed(() => account.value?.is_admin === true); + const isMember = computed(() => account.value?.membership_active === true); + + async function restore(): Promise { + try { + account.value = await api.get("/auth/session"); + } catch (error) { + if (!(error instanceof ApiError) || error.status !== 401) { + throw error; + } + account.value = null; + } finally { + initialized.value = true; + } + } + + async function authenticate(mode: "login" | "register", username: string, password: string) { + busy.value = true; + try { + const response = await api.post(`/auth/${mode}`, { username, password }); + account.value = response.account; + } finally { + busy.value = false; + } + } + + async function endSession(action: "logout" | "switch-account"): Promise { + await api.post(`/auth/${action}`); + account.value = null; + } + + async function refreshIdentity(): Promise { + account.value = await api.get("/auth/session"); + } + + return { + account, + initialized, + busy, + isAdmin, + isMember, + restore, + authenticate, + endSession, + refreshIdentity, + }; +}); diff --git a/next/frontend/src/shared/stores/ui.ts b/next/frontend/src/shared/stores/ui.ts new file mode 100644 index 0000000..e0f75c5 --- /dev/null +++ b/next/frontend/src/shared/stores/ui.ts @@ -0,0 +1,53 @@ +import { defineStore } from "pinia"; +import { ref } from "vue"; + +export type DialogName = "profile" | "membership" | "password" | "search" | null; +export type Theme = "light" | "dark"; + +const THEME_KEY = "xiaobai-theme"; + +export function preferredTheme(): Theme { + const stored = localStorage.getItem(THEME_KEY); + if (stored === "light" || stored === "dark") return stored; + return matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"; +} + +export function applyTheme(theme: Theme): void { + document.documentElement.dataset.theme = theme; + document.documentElement.style.colorScheme = theme; +} + +export const useUiStore = defineStore("ui", () => { + const theme = ref(preferredTheme()); + const dialog = ref(null); + const toast = ref(""); + let toastTimer: ReturnType | undefined; + + function setTheme(next: Theme): void { + theme.value = next; + localStorage.setItem(THEME_KEY, next); + applyTheme(next); + } + + function toggleTheme(): void { + setTheme(theme.value === "light" ? "dark" : "light"); + } + + function openDialog(name: Exclude): void { + dialog.value = name; + } + + function closeDialog(): void { + dialog.value = null; + } + + function showToast(message: string): void { + toast.value = message; + if (toastTimer) clearTimeout(toastTimer); + toastTimer = setTimeout(() => { + toast.value = ""; + }, 2200); + } + + return { theme, dialog, toast, setTheme, toggleTheme, openDialog, closeDialog, showToast }; +}); diff --git a/next/frontend/src/shared/styles/account.css b/next/frontend/src/shared/styles/account.css new file mode 100644 index 0000000..03eba08 --- /dev/null +++ b/next/frontend/src/shared/styles/account.css @@ -0,0 +1,137 @@ +.panel-loading { + padding: var(--s-22) 0; + text-align: center; +} + +.panel-form { + padding-top: var(--s-14); +} + +.membership-panel { + display: grid; + gap: var(--s-14); +} + +.status-grid { + display: grid; + grid-template-columns: repeat(5, minmax(0, 1fr)); + gap: var(--s-1); + margin: 0; + overflow: hidden; + border: var(--s-1) solid var(--color-border); + border-radius: var(--control-radius); + background: var(--color-divider); +} + +.status-grid > div { + padding: var(--s-10) var(--s-12); + background: var(--color-surface); +} + +.status-grid dt { + color: var(--color-text-faint); + font-size: var(--font-11); +} + +.status-grid dd { + margin: var(--s-4) 0 0; + font-size: var(--font-14); + font-weight: var(--weight-700); +} + +.comparison-table { + overflow: hidden; + border: var(--s-1) solid var(--color-border); + border-radius: var(--control-radius); +} + +.comparison-row { + display: grid; + grid-template-columns: minmax(0, 1fr) var(--s-200) var(--s-200); + border-bottom: var(--s-1) solid var(--color-divider); +} + +.comparison-row:last-child { + border-bottom: 0; +} + +.comparison-row span { + padding: var(--s-8) var(--s-12); + font-size: var(--font-12-5); +} + +.comparison-row span:not(:first-child) { + text-align: center; +} + +.comparison-head { + color: var(--color-text-secondary); + background: var(--color-surface-muted); + font-size: var(--font-12); + font-weight: var(--weight-600); +} + +.usage-package { + display: flex; + align-items: center; + gap: var(--s-12); + padding: var(--s-12); + border: var(--s-1) solid var(--color-border); + border-radius: var(--control-radius); +} + +.usage-package div { + flex: 1; +} + +.usage-package strong { + font-size: var(--font-13); +} + +.usage-package p, +.password-hint { + margin-top: var(--s-4); + font-size: var(--font-11-5); +} + +.search-panel { + display: grid; + gap: var(--s-12); +} + +.search-input { + min-height: var(--s-44); +} + +.search-categories { + display: flex; + gap: var(--s-8); + padding-bottom: var(--s-10); + border-bottom: var(--s-1) solid var(--color-divider); +} + +.search-categories span { + padding: var(--s-4) var(--s-9); + border-radius: var(--tag-radius); + color: var(--color-text-secondary); + background: var(--color-surface-muted); + font-size: var(--font-11); +} + +.search-empty { + min-height: var(--s-200); + display: grid; + align-content: center; + justify-items: center; + gap: var(--s-8); + color: var(--color-text-secondary); + font-size: var(--font-12); +} + +.search-empty span { + padding: var(--s-2) var(--s-6); + border: var(--s-1) solid var(--color-border); + border-radius: var(--radius-4); + color: var(--color-text-faint); + font-size: var(--font-11); +} diff --git a/next/frontend/src/shared/styles/auth.css b/next/frontend/src/shared/styles/auth.css new file mode 100644 index 0000000..dfe0baf --- /dev/null +++ b/next/frontend/src/shared/styles/auth.css @@ -0,0 +1,69 @@ +.auth-view { + min-height: 100vh; + display: grid; + place-items: center; + padding: var(--s-16); + background: var(--color-canvas); +} + +.auth-panel { + width: min(100%, var(--s-400)); + overflow: hidden; +} + +.auth-brand { + display: flex; + align-items: center; + gap: var(--s-12); + padding: var(--s-22) var(--s-26) var(--s-16); +} + +.auth-brand h1 { + font-size: var(--font-17); + font-weight: var(--weight-800); +} + +.auth-brand p { + margin-top: var(--s-4); + color: var(--color-text-secondary); + font-size: var(--font-12); +} + +.auth-tabs { + display: flex; + padding: 0 var(--s-26); + border-bottom: var(--s-1) solid var(--color-divider); +} + +.auth-tabs button { + flex: 1; + padding: var(--s-10) var(--s-14); + border-bottom: var(--s-2) solid var(--c-transparent); + color: var(--color-text-secondary); + background: var(--c-transparent); +} + +.auth-tabs button.active { + color: var(--color-primary); + border-bottom-color: var(--color-primary); + font-weight: var(--weight-600); +} + +.auth-form { + display: grid; + gap: var(--s-14); + padding: var(--s-22) var(--s-26) var(--s-16); +} + +.auth-submit { + width: 100%; + margin-top: var(--s-4); +} + +.auth-risk { + padding: 0 var(--s-26) var(--s-22); + color: var(--color-text-faint); + font-size: var(--font-11); + line-height: var(--s-18); + text-align: center; +} diff --git a/next/frontend/src/shared/styles/base.css b/next/frontend/src/shared/styles/base.css index da524e4..4633c04 100644 --- a/next/frontend/src/shared/styles/base.css +++ b/next/frontend/src/shared/styles/base.css @@ -5,20 +5,95 @@ html, body, #app { - min-width: 320px; + min-width: var(--s-320); min-height: 100%; margin: 0; } +html { + background: var(--color-canvas); +} + body { min-height: 100vh; - color: var(--text-primary); - background: var(--canvas); + overflow-x: hidden; + color: var(--color-text); + background: var(--color-canvas); + font-family: var(--font-sans); + font-size: var(--font-13); + font-weight: var(--weight-400); + letter-spacing: 0; } button, input, select, textarea { + color: inherit; font: inherit; + letter-spacing: 0; +} + +button, +a, +input, +select, +textarea { + outline: none; +} + +button:focus-visible, +a:focus-visible, +input:focus-visible, +select:focus-visible, +textarea:focus-visible { + box-shadow: var(--focus-ring); +} + +button { + border: 0; + cursor: pointer; +} + +button:disabled { + cursor: not-allowed; +} + +a { + color: inherit; + text-decoration: none; +} + +h1, +h2, +h3, +p { + margin: 0; +} + +.sr-only { + position: absolute; + width: var(--s-1); + height: var(--s-1); + padding: 0; + margin: calc(var(--s-1) * -1); + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} + +.numeric { + font-variant-numeric: tabular-nums; +} + +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + scroll-behavior: auto !important; + animation-duration: var(--s-1) !important; + animation-iteration-count: 1 !important; + transition-duration: var(--s-1) !important; + } } diff --git a/next/frontend/src/shared/styles/components.css b/next/frontend/src/shared/styles/components.css new file mode 100644 index 0000000..fade93f --- /dev/null +++ b/next/frontend/src/shared/styles/components.css @@ -0,0 +1,332 @@ +.btn { + min-height: var(--control-height); + display: inline-flex; + align-items: center; + justify-content: center; + gap: var(--s-6); + padding: var(--s-6) var(--s-13); + border: var(--s-1) solid var(--color-border); + border-radius: var(--control-radius); + color: var(--color-text); + background: var(--color-surface); + font-size: var(--font-13); + font-weight: var(--weight-500); + transition: color var(--duration-fast) var(--ease-standard), + background var(--duration-fast) var(--ease-standard), + border-color var(--duration-fast) var(--ease-standard); +} + +.btn:hover:not(:disabled) { + color: var(--color-primary); + border-color: var(--color-primary-border); +} + +.btn-primary { + color: var(--c-gray-050); + border-color: var(--color-primary); + background: var(--color-primary); +} + +.btn-primary:hover:not(:disabled) { + color: var(--c-gray-050); + border-color: var(--color-primary-hover); + background: var(--color-primary-hover); +} + +.btn-ghost { + border-color: var(--c-transparent); + background: var(--c-transparent); +} + +.btn-small { + min-height: var(--s-28); + padding: var(--s-4) var(--s-9); + font-size: var(--font-12); +} + +.btn:disabled, +.is-disabled { + opacity: var(--opacity-disabled); +} + +.icon-button { + width: var(--s-32); + height: var(--s-32); + display: inline-grid; + place-items: center; + padding: 0; + border: var(--s-1) solid var(--color-border); + border-radius: var(--control-radius); + color: var(--color-text-secondary); + background: var(--color-surface); + font-size: var(--font-14); + transition: color var(--duration-fast) var(--ease-standard), + background var(--duration-fast) var(--ease-standard), + border-color var(--duration-fast) var(--ease-standard); +} + +.icon-button:hover { + color: var(--color-primary); + border-color: var(--color-primary-border); + background: var(--color-primary-soft); +} + +.card { + border: var(--s-1) solid var(--color-border); + border-radius: var(--card-radius); + background: var(--color-surface); + box-shadow: var(--shadow-card); +} + +.card-header { + min-height: var(--s-40); + display: flex; + align-items: center; + gap: var(--s-8); + padding: var(--s-11) var(--s-14); + border-bottom: var(--s-1) solid var(--color-divider); +} + +.card-header h2, +.card-header h3 { + font-size: var(--font-14); + font-weight: var(--weight-700); +} + +.card-body { + padding: var(--s-14) var(--s-16); +} + +.muted { + color: var(--color-text-secondary); +} + +.faint { + color: var(--color-text-faint); +} + +.up { + color: var(--color-up); +} + +.down { + color: var(--color-down); +} + +.warning { + color: var(--color-warning); +} + +.tag { + display: inline-flex; + align-items: center; + min-height: var(--s-20); + padding: var(--s-1) var(--s-7); + border: var(--s-1) solid var(--color-border); + border-radius: var(--tag-radius); + color: var(--color-text-secondary); + background: var(--color-surface-muted); + font-size: var(--font-11); +} + +.tag-admin { + color: var(--color-warning); + border-color: var(--color-warning); + background: var(--color-warning-soft); +} + +.tag-vip { + color: var(--color-warning); + border-color: var(--color-warning); + background: var(--color-warning-soft); + font-weight: var(--weight-800); +} + +.field { + display: grid; + gap: var(--s-6); +} + +.field label, +.field-label { + color: var(--color-text-secondary); + font-size: var(--font-12); + font-weight: var(--weight-600); +} + +.input, +.select, +.textarea { + width: 100%; + min-height: var(--s-36); + padding: var(--s-8) var(--s-12); + border: var(--s-1) solid var(--color-border); + border-radius: var(--control-radius); + color: var(--color-text); + background: var(--color-surface); + font-size: var(--font-13); +} + +.textarea { + min-height: var(--s-64); + resize: vertical; +} + +.input::placeholder, +.textarea::placeholder { + color: var(--color-text-faint); +} + +.input:hover, +.select:hover, +.textarea:hover { + border-color: var(--color-primary-border); +} + +.form-grid { + display: grid; + gap: var(--s-12); +} + +.form-actions { + display: flex; + justify-content: flex-end; + gap: var(--s-8); + padding-top: var(--s-4); +} + +.field-error { + color: var(--color-up); + font-size: var(--font-11-5); +} + +.notice { + padding: var(--s-10) var(--s-12); + border: var(--s-1) solid var(--color-primary-border); + border-radius: var(--control-radius); + color: var(--color-text-secondary); + background: var(--color-primary-soft); + font-size: var(--font-12); + line-height: var(--s-18); +} + +.notice-warning { + color: var(--color-warning); + border-color: var(--color-warning); + background: var(--color-warning-soft); +} + +.membership-lock { + display: flex; + align-items: center; + gap: var(--s-12); + margin-bottom: var(--s-12); +} + +.membership-lock span { + flex: 1; +} + +.locked-content { + pointer-events: none; + opacity: var(--opacity-muted); +} + +.dialog-backdrop { + position: fixed; + inset: 0; + z-index: var(--z-dialog); + display: grid; + place-items: center; + padding: var(--s-16); + background: var(--color-overlay); +} + +.dialog { + width: min(100%, var(--s-dialog)); + max-height: calc(100vh - var(--s-34)); + display: grid; + grid-template-rows: auto minmax(0, 1fr); + overflow: hidden; + border: var(--s-1) solid var(--color-border); + border-radius: var(--card-radius); + background: var(--color-surface-raised); + box-shadow: var(--shadow-float); +} + +.dialog-wide { + width: min(100%, var(--s-dialog-wide)); +} + +.dialog-header { + min-height: var(--s-46); + display: flex; + align-items: center; + gap: var(--s-8); + padding: var(--s-10) var(--s-14); + border-bottom: var(--s-1) solid var(--color-divider); +} + +.dialog-title { + font-size: var(--font-14); + font-weight: var(--weight-700); +} + +.dialog-close { + margin-left: auto; +} + +.dialog-body { + overflow: auto; + padding: var(--s-14) var(--s-16) var(--s-16); +} + +.toast { + position: fixed; + left: 50%; + bottom: var(--s-64); + z-index: var(--z-toast); + max-width: min(var(--s-400), calc(100vw - var(--s-32))); + padding: var(--s-10) var(--s-14); + border: var(--s-1) solid var(--color-border); + border-radius: var(--control-radius); + color: var(--color-text); + background: var(--color-surface-raised); + box-shadow: var(--shadow-float); + font-size: var(--font-12-5); + transform: translateX(-50%); +} + +.empty-state { + min-height: var(--s-200); + display: grid; + align-content: center; + justify-items: center; + gap: var(--s-8); + padding: var(--s-44) var(--s-16); + text-align: center; +} + +.empty-mark { + width: var(--s-30); + height: var(--s-30); + display: grid; + place-items: center; + border: var(--s-1) solid var(--color-border); + border-radius: var(--radius-round); + color: var(--color-text-faint); + background: var(--color-surface-muted); +} + +.empty-state h2 { + color: var(--color-text-secondary); + font-size: var(--font-14); + font-weight: var(--weight-600); +} + +.empty-state p { + max-width: var(--s-400); + color: var(--color-text-secondary); + font-size: var(--font-12); + line-height: var(--s-18); +} diff --git a/next/frontend/src/shared/styles/mobile.css b/next/frontend/src/shared/styles/mobile.css new file mode 100644 index 0000000..4bf7057 --- /dev/null +++ b/next/frontend/src/shared/styles/mobile.css @@ -0,0 +1,152 @@ +@media (max-width: 1023px) { + .dialog-backdrop { + align-items: end; + padding: 0; + } + + .dialog, + .dialog-wide { + width: 100%; + max-height: calc(100vh - var(--s-44)); + border-radius: var(--card-radius) var(--card-radius) 0 0; + } + + .btn, + .icon-button { + min-height: var(--touch-height); + } + + .icon-button { + width: var(--touch-height); + } + + .membership-lock { + align-items: stretch; + flex-direction: column; + } + + .app-shell { + padding-left: 0; + padding-bottom: var(--shell-mobile-nav-height); + } + + .sidebar, + .statusbar, + .desktop-only, + .market-details { + display: none; + } + + .topbar { + gap: var(--s-8); + padding: 0 var(--s-10); + } + + .topbar-title { + font-size: var(--font-13); + } + + .identity-cluster .tag, + .account-name, + .date-control .icon-button { + display: none; + } + + .mobile-account-label { + display: inline; + } + + .market-strip-row { + gap: var(--s-12); + overflow-x: auto; + padding-right: var(--s-10); + padding-left: var(--s-10); + white-space: nowrap; + } + + .market-toggle { + display: none; + } + + .page-frame { + min-height: calc(100vh - var(--shell-topbar-height) - var(--shell-summary-height) - var(--shell-mobile-nav-height)); + padding: var(--s-12) var(--s-10); + } + + .page-header { + align-items: flex-start; + gap: var(--s-4); + flex-direction: column; + } + + .mobile-nav { + position: fixed; + right: 0; + bottom: 0; + left: 0; + z-index: var(--z-mobile-nav); + height: var(--shell-mobile-nav-height); + display: grid; + grid-template-columns: repeat(5, 1fr); + padding-bottom: env(safe-area-inset-bottom); + border-top: var(--s-1) solid var(--color-border); + background: var(--color-surface); + } + + .mobile-nav-item { + min-width: 0; + display: grid; + place-items: center; + color: var(--color-text-secondary); + font-size: var(--font-11); + } + + .mobile-nav-item.router-link-active { + color: var(--color-primary); + font-weight: var(--weight-600); + } + + .status-grid { + grid-template-columns: 1fr 1fr; + } + + .comparison-row { + grid-template-columns: minmax(0, 1fr) var(--s-64) var(--s-64); + } + + .auth-view { + align-items: start; + padding-top: var(--s-34); + } + + .auth-panel { + box-shadow: none; + } + + .system-header, + .system-header > div:first-child { + align-items: flex-start; + flex-direction: column; + } + + .system-tabs { + width: 100%; + margin-left: 0; + overflow-x: auto; + } + + .system-grid, + .model-grid { + grid-template-columns: 1fr; + } + + .credential-row, + .selection-grid { + grid-template-columns: 1fr; + align-items: stretch; + } + + .member-editor { + position: static; + } +} diff --git a/next/frontend/src/shared/styles/shell.css b/next/frontend/src/shared/styles/shell.css new file mode 100644 index 0000000..5cab0ac --- /dev/null +++ b/next/frontend/src/shared/styles/shell.css @@ -0,0 +1,327 @@ +.app-loading { + min-height: 100vh; + display: grid; + place-items: center; + color: var(--color-text-secondary); + background: var(--color-canvas); +} + +.loading-stack { + display: grid; + justify-items: center; + gap: var(--s-12); +} + +.app-shell { + min-height: 100vh; + padding-left: var(--shell-sidebar-width); + padding-bottom: var(--shell-status-height); + background: var(--color-canvas); +} + +.sidebar { + position: fixed; + inset: 0 auto 0 0; + z-index: var(--z-sidebar); + width: var(--shell-sidebar-width); + display: flex; + flex-direction: column; + border-right: var(--s-1) solid var(--color-border); + background: var(--color-surface); +} + +.brand { + height: var(--shell-topbar-height); + display: flex; + align-items: center; + gap: var(--s-8); + padding: 0 var(--s-16); + border-bottom: var(--s-1) solid var(--color-divider); +} + +.brand-mark { + width: var(--s-26); + height: var(--s-26); + display: grid; + place-items: center; + border-radius: var(--control-radius); + color: var(--c-gray-050); + background: var(--color-primary); + font-size: var(--font-14); + font-weight: var(--weight-700); +} + +.brand-name { + font-size: var(--font-15); + font-weight: var(--weight-700); +} + +.sidebar-nav { + flex: 1; + overflow-y: auto; + padding: var(--s-8); +} + +.nav-group-label { + padding: var(--s-12) var(--s-10) var(--s-4); + color: var(--color-text-faint); + font-size: var(--font-11); +} + +.nav-item { + min-height: var(--s-32); + display: flex; + align-items: center; + gap: var(--s-8); + margin-bottom: var(--s-1); + padding: var(--s-6) var(--s-10); + border-radius: var(--control-radius); + color: var(--color-text-secondary); + font-size: var(--font-13); + transition: color var(--duration-fast) var(--ease-standard), + background var(--duration-fast) var(--ease-standard); +} + +.nav-item:hover { + color: var(--color-text); + background: var(--color-surface-muted); +} + +.nav-item.router-link-active { + color: var(--color-primary); + background: var(--color-primary-soft); + font-weight: var(--weight-600); +} + +.nav-mark { + width: var(--s-20); + color: var(--color-text-faint); + font-size: var(--font-11); + text-align: center; +} + +.nav-item.router-link-active .nav-mark { + color: var(--color-primary); +} + +.shell-main { + min-width: 0; +} + +.topbar { + position: sticky; + top: 0; + z-index: var(--z-topbar); + height: var(--shell-topbar-height); + display: flex; + align-items: center; + gap: var(--s-10); + padding: 0 var(--s-16); + border-bottom: var(--s-1) solid var(--color-border); + background: var(--color-surface); +} + +.topbar-title { + min-width: 0; + font-size: var(--font-14); + font-weight: var(--weight-700); + white-space: nowrap; +} + +.topbar-spacer { + flex: 1; +} + +.date-control { + display: inline-flex; + align-items: center; + gap: var(--s-4); +} + +.date-input { + height: var(--s-32); + padding: var(--s-4) var(--s-8); + border: var(--s-1) solid var(--color-border); + border-radius: var(--control-radius); + color: var(--color-text); + background: var(--color-surface); + font-size: var(--font-12); + font-variant-numeric: tabular-nums; +} + +.identity-cluster { + display: inline-flex; + align-items: center; + gap: var(--s-6); +} + +.account-menu-wrap { + position: relative; +} + +.account-trigger { + max-width: var(--s-200); +} + +.account-name { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.mobile-account-label { + display: none; +} + +.account-menu { + position: absolute; + top: calc(100% + var(--s-8)); + right: 0; + z-index: var(--z-popover); + width: var(--s-200); + padding: var(--s-6); + border: var(--s-1) solid var(--color-border); + border-radius: var(--control-radius); + background: var(--color-surface-raised); + box-shadow: var(--shadow-float); +} + +.account-menu button { + width: 100%; + min-height: var(--s-32); + padding: var(--s-6) var(--s-10); + border-radius: var(--radius-5); + color: var(--color-text-secondary); + background: var(--c-transparent); + text-align: left; +} + +.account-menu button:hover { + color: var(--color-text); + background: var(--color-surface-muted); +} + +.market-strip { + border-bottom: var(--s-1) solid var(--color-border); + background: var(--color-surface); +} + +.market-strip-row { + min-height: var(--shell-summary-height); + display: flex; + align-items: center; + gap: var(--s-18); + padding: var(--s-6) var(--s-16); + color: var(--color-text-secondary); + font-size: var(--font-12); +} + +.market-emotion { + display: inline-flex; + align-items: center; + gap: var(--s-6); + color: var(--color-text-secondary); +} + +.emotion-dot { + width: var(--s-8); + height: var(--s-8); + border-radius: var(--radius-round); + background: var(--color-text-faint); + animation: emotion-pulse 2.2s var(--ease-standard) infinite; +} + +@keyframes emotion-pulse { + 50% { + opacity: var(--opacity-muted); + transform: scale(var(--scale-pulse)); + } +} + +.market-toggle { + margin-left: auto; + color: var(--color-primary); + background: var(--c-transparent); + font-size: var(--font-12); +} + +.market-details { + display: grid; + grid-template-columns: repeat(7, minmax(0, 1fr)); + border-top: var(--s-1) solid var(--color-divider); + background: var(--color-divider); + gap: var(--s-1); +} + +.market-cell { + min-height: var(--s-64); + padding: var(--s-10) var(--s-16); + background: var(--color-surface); +} + +.market-cell-label { + color: var(--color-text-faint); + font-size: var(--font-11); +} + +.market-cell-value { + min-height: var(--s-24); + padding-top: var(--s-4); + font-size: var(--font-18); + font-weight: var(--weight-700); + font-variant-numeric: tabular-nums; +} + +.page-frame { + width: min(100%, var(--s-content-max)); + min-height: calc(100vh - var(--shell-topbar-height) - var(--shell-summary-height) - var(--shell-status-height)); + margin: 0 auto; + padding: var(--page-padding-y) var(--page-padding-x); +} + +.page-header { + display: flex; + align-items: baseline; + gap: var(--s-12); + margin-bottom: var(--s-12); +} + +.page-header h1 { + font-size: var(--font-17); + font-weight: var(--weight-800); +} + +.page-subtitle { + color: var(--color-text-faint); + font-size: var(--font-12); +} + +.statusbar { + position: fixed; + right: 0; + bottom: 0; + left: var(--shell-sidebar-width); + z-index: var(--z-status); + height: var(--shell-status-height); + display: grid; + grid-template-columns: 1fr auto 1fr; + align-items: center; + gap: var(--s-12); + padding: 0 var(--s-16); + border-top: var(--s-1) solid var(--color-border); + color: var(--color-text-faint); + background: var(--color-surface); + font-size: var(--font-11); +} + +.statusbar-center { + color: var(--color-text-secondary); +} + +.statusbar-right { + text-align: right; +} + +.mobile-nav { + display: none; +} diff --git a/next/frontend/src/shared/styles/system.css b/next/frontend/src/shared/styles/system.css new file mode 100644 index 0000000..adc90c3 --- /dev/null +++ b/next/frontend/src/shared/styles/system.css @@ -0,0 +1,206 @@ +.system-header { + align-items: center; +} + +.system-header > div:first-child { + display: flex; + align-items: baseline; + gap: var(--s-12); +} + +.system-tabs { + display: flex; + align-self: stretch; + margin-left: auto; + border-bottom: var(--s-1) solid var(--color-divider); +} + +.system-tabs button { + padding: var(--s-10) var(--s-14); + border-bottom: var(--s-2) solid var(--c-transparent); + color: var(--color-text-secondary); + background: var(--c-transparent); + font-size: var(--font-13); +} + +.system-tabs button.active { + color: var(--color-primary); + border-bottom-color: var(--color-primary); + font-weight: var(--weight-600); +} + +.system-stack { + display: grid; + gap: var(--layout-gap); +} + +.system-grid { + display: grid; + grid-template-columns: minmax(0, 1fr) var(--s-360); + align-items: start; + gap: var(--layout-gap); +} + +.model-grid { + grid-template-columns: var(--s-360) minmax(0, 1fr); +} + +.credential-list { + display: grid; + gap: var(--s-12); +} + +.credential-row { + display: grid; + grid-template-columns: var(--s-200) minmax(0, 1fr) auto; + align-items: end; + gap: var(--s-10); +} + +.credential-meta { + display: grid; + gap: var(--s-4); +} + +.credential-meta strong { + font-size: var(--font-13); +} + +.credential-meta span { + font-size: var(--font-11); +} + +.disabled-row, +.selected-account { + display: flex; + align-items: center; + gap: var(--s-12); +} + +.disabled-row p, +.selected-account strong { + flex: 1; +} + +.model-list { + max-height: calc(100vh - var(--s-260)); + overflow: auto; + padding: var(--s-6); +} + +.model-row { + width: 100%; + min-height: var(--s-44); + display: flex; + align-items: center; + gap: var(--s-8); + padding: var(--s-8) var(--s-10); + border-radius: var(--control-radius); + color: var(--color-text); + background: var(--c-transparent); + text-align: left; +} + +.model-row:hover, +.model-row.active { + background: var(--color-primary-soft); +} + +.model-row > span:first-child { + min-width: 0; + display: grid; + gap: var(--s-2); + flex: 1; +} + +.model-row strong { + overflow: hidden; + font-size: var(--font-13); + text-overflow: ellipsis; + white-space: nowrap; +} + +.model-row small { + overflow: hidden; + color: var(--color-text-faint); + font-size: var(--font-11); + text-overflow: ellipsis; + white-space: nowrap; +} + +.model-tags { + display: flex; + gap: var(--s-4); +} + +.selection-grid { + display: grid; + grid-template-columns: 1fr 1fr auto; + align-items: end; + gap: var(--s-10); +} + +.table-wrap { + overflow: auto; +} + +.data-table { + width: 100%; + border-collapse: collapse; + font-size: var(--font-12-5); +} + +.data-table th { + position: sticky; + top: 0; + z-index: var(--z-table); + padding: var(--s-8) var(--s-12); + border-bottom: var(--s-1) solid var(--color-border); + color: var(--color-text-secondary); + background: var(--color-surface-muted); + font-size: var(--font-12); + font-weight: var(--weight-600); + text-align: left; + white-space: nowrap; +} + +.data-table td { + padding: var(--s-9) var(--s-12); + border-bottom: var(--s-1) solid var(--color-divider); + white-space: nowrap; +} + +.data-table th.num, +.data-table td.num { + text-align: right; +} + +.sort-button { + padding: 0; + color: inherit; + background: var(--c-transparent); + font: inherit; +} + +.sort-button span { + color: var(--color-primary); +} + +.data-table tbody tr { + cursor: pointer; +} + +.data-table tbody tr:hover, +.data-table tbody tr.selected { + background: var(--color-primary-soft); +} + +.name-cell { + font-size: var(--font-13); + font-weight: var(--weight-700); +} + +.member-editor { + position: sticky; + top: calc(var(--shell-topbar-height) + var(--shell-summary-height) + var(--s-14)); +} diff --git a/next/frontend/src/shared/styles/tokens.css b/next/frontend/src/shared/styles/tokens.css index b8e08c1..31fecbb 100644 --- a/next/frontend/src/shared/styles/tokens.css +++ b/next/frontend/src/shared/styles/tokens.css @@ -1,37 +1,191 @@ :root { color-scheme: light; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif; - font-size: 13px; - color: #1f2937; - background: #f4f5f7; - --canvas: #f4f5f7; - --surface: #ffffff; - --border: #e5e7eb; - --text-primary: #1f2937; - --text-secondary: #6b7280; - --primary: #2563eb; - --warning: #b45309; + /* Primitive color tokens */ + --c-blue-600: #2563eb; + --c-blue-700: #1d4ed8; + --c-blue-050: #eff4ff; + --c-blue-200: #c7d8fb; + --c-red-600: #e04536; + --c-red-050: #fdecea; + --c-green-600: #16a34a; + --c-green-050: #e9f7ee; + --c-amber-700: #b45309; + --c-amber-050: #fdf3e3; + --c-gray-950: #121416; + --c-gray-900: #1b1e21; + --c-gray-850: #202428; + --c-gray-800: #24282d; + --c-gray-700: #343a40; + --c-gray-650: #474f57; + --c-gray-100: #f4f5f7; + --c-gray-075: #f8fafc; + --c-gray-050: #ffffff; + --c-text-900: #1f2937; + --c-text-700: #374151; + --c-text-600: #4b5563; + --c-text-500: #6b7280; + --c-text-400: #9ca3af; + --c-line-200: #e5e7eb; + --c-line-100: #eef0f3; + --c-night-text-900: #e8eaed; + --c-night-text-600: #adb5bd; + --c-night-text-400: #7f8993; + --c-night-blue: #6ca8e8; + --c-night-blue-hover: #8bbcf0; + --c-night-blue-soft: #23364a; + --c-night-red: #f06d73; + --c-night-red-soft: #40262a; + --c-night-green: #43bc8a; + --c-night-green-soft: #1d382f; + --c-night-amber: #e2ad58; + --c-night-amber-soft: #3d3220; + --c-transparent: transparent; - --space-8: 8px; - --space-16: 16px; - --space-22: 22px; - --radius-card: 10px; - --font-page-title: 17px; - --shadow-card: 0 1px 2px rgba(16, 24, 40, 0.05); + /* Primitive dimensions */ + --s-1: 1px; + --s-2: 2px; + --s-4: 4px; + --s-6: 6px; + --s-7: 7px; + --s-8: 8px; + --s-9: 9px; + --s-10: 10px; + --s-11: 11px; + --s-12: 12px; + --s-13: 13px; + --s-14: 14px; + --s-16: 16px; + --s-18: 18px; + --s-20: 20px; + --s-22: 22px; + --s-24: 24px; + --s-26: 26px; + --s-28: 28px; + --s-30: 30px; + --s-32: 32px; + --s-34: 34px; + --s-36: 36px; + --s-40: 40px; + --s-44: 44px; + --s-46: 46px; + --s-56: 56px; + --s-64: 64px; + --s-200: 200px; + --s-260: 260px; + --s-320: 320px; + --s-360: 360px; + --s-400: 400px; + --s-dialog: 512px; + --s-dialog-wide: 768px; + --s-content-max: 2200px; + --s-field: 340px; + + /* Primitive typography */ + --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif; + --font-serif: "Kaiti SC", "STKaiti", "KaiTi", "STSong", "SimSun", serif; + --font-10-5: 10.5px; + --font-11: 11px; + --font-11-5: 11.5px; + --font-12: 12px; + --font-12-5: 12.5px; + --font-13: 13px; + --font-14: 14px; + --font-15: 15px; + --font-17: 17px; + --font-18: 18px; + --weight-400: 400; + --weight-500: 500; + --weight-600: 600; + --weight-700: 700; + --weight-800: 800; + + /* Primitive effects */ + --radius-4: 4px; + --radius-5: 5px; + --radius-6: 6px; + --radius-7: 7px; + --radius-10: 10px; + --radius-round: 999px; + --shadow-card-light: 0 1px 2px rgba(16, 24, 40, 0.05); + --shadow-card-dark: 0 1px 2px rgba(0, 0, 0, 0.28); + --shadow-float: 0 12px 32px rgba(0, 0, 0, 0.18); + --duration-fast: 160ms; + --duration-normal: 220ms; + --ease-standard: ease; + --opacity-disabled: 0.52; + --opacity-muted: 0.72; + --scale-pulse: 0.84; + --z-table: 2; + --z-topbar: 50; + --z-status: 55; + --z-sidebar: 60; + --z-mobile-nav: 70; + --z-popover: 100; + --z-dialog: 200; + --z-toast: 240; + + /* Semantic tokens */ + --color-canvas: var(--c-gray-100); + --color-surface: var(--c-gray-050); + --color-surface-muted: var(--c-gray-075); + --color-surface-raised: var(--c-gray-050); + --color-text: var(--c-text-900); + --color-text-secondary: var(--c-text-500); + --color-text-faint: var(--c-text-400); + --color-border: var(--c-line-200); + --color-divider: var(--c-line-100); + --color-primary: var(--c-blue-600); + --color-primary-hover: var(--c-blue-700); + --color-primary-soft: var(--c-blue-050); + --color-primary-border: var(--c-blue-200); + --color-up: var(--c-red-600); + --color-up-soft: var(--c-red-050); + --color-down: var(--c-green-600); + --color-down-soft: var(--c-green-050); + --color-warning: var(--c-amber-700); + --color-warning-soft: var(--c-amber-050); + --color-overlay: rgba(18, 20, 22, 0.46); + --shadow-card: var(--shadow-card-light); + + /* Component tokens */ + --shell-sidebar-width: var(--s-200); + --shell-topbar-height: var(--s-46); + --shell-summary-height: var(--s-36); + --shell-status-height: var(--s-30); + --shell-mobile-nav-height: var(--s-56); + --page-padding-y: var(--s-14); + --page-padding-x: var(--s-16); + --layout-gap: var(--s-12); + --control-height: var(--s-32); + --touch-height: var(--s-44); + --card-radius: var(--radius-10); + --control-radius: var(--radius-7); + --tag-radius: var(--radius-5); + --focus-ring: 0 0 0 var(--s-2) var(--color-canvas), 0 0 0 var(--s-4) var(--color-primary); } :root[data-theme="dark"] { color-scheme: dark; - color: #e8eaed; - background: #121416; - - --canvas: #121416; - --surface: #1b1e21; - --border: #343a40; - --text-primary: #e8eaed; - --text-secondary: #adb5bd; - --primary: #6ca8e8; - --warning: #e2ad58; - --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.28); + --color-canvas: var(--c-gray-950); + --color-surface: var(--c-gray-900); + --color-surface-muted: var(--c-gray-850); + --color-surface-raised: var(--c-gray-800); + --color-text: var(--c-night-text-900); + --color-text-secondary: var(--c-night-text-600); + --color-text-faint: var(--c-night-text-400); + --color-border: var(--c-gray-700); + --color-divider: var(--c-gray-700); + --color-primary: var(--c-night-blue); + --color-primary-hover: var(--c-night-blue-hover); + --color-primary-soft: var(--c-night-blue-soft); + --color-primary-border: var(--c-gray-650); + --color-up: var(--c-night-red); + --color-up-soft: var(--c-night-red-soft); + --color-down: var(--c-night-green); + --color-down-soft: var(--c-night-green-soft); + --color-warning: var(--c-night-amber); + --color-warning-soft: var(--c-night-amber-soft); + --color-overlay: rgba(0, 0, 0, 0.64); + --shadow-card: var(--shadow-card-dark); } diff --git a/next/playwright.config.js b/next/playwright.config.js new file mode 100644 index 0000000..7abb2df --- /dev/null +++ b/next/playwright.config.js @@ -0,0 +1,16 @@ +const { defineConfig } = require("@playwright/test"); + +module.exports = defineConfig({ + testDir: "./tests/e2e", + outputDir: "./data/playwright", + timeout: 30_000, + fullyParallel: false, + reporter: "line", + use: { + baseURL: "http://127.0.0.1:5173", + channel: "msedge", + headless: true, + viewport: { width: 1920, height: 1080 }, + trace: "retain-on-failure", + }, +}); diff --git a/next/tests/e2e/stage4.spec.js b/next/tests/e2e/stage4.spec.js new file mode 100644 index 0000000..13f00f9 --- /dev/null +++ b/next/tests/e2e/stage4.spec.js @@ -0,0 +1,132 @@ +const fs = require("node:fs"); +const path = require("node:path"); + +const { expect, test } = require("@playwright/test"); + +const evidence = path.resolve(__dirname, "../../docs/evidence/stage-4"); + +test.beforeAll(() => fs.mkdirSync(evidence, { recursive: true })); + +async function authenticate(page, username, password) { + await page.goto("/"); + await expect(page.getByRole("heading", { name: "小白复盘" })).toBeVisible(); + await page.getByLabel("账号名").fill(username); + await page.getByLabel("密码").fill(password); + await page.getByRole("button", { name: "登录", exact: true }).click(); + await expect(page.locator(".sidebar, .field-error")).toBeVisible(); + if (!(await page.locator(".sidebar").isVisible())) { + await page.getByRole("tab", { name: "注册" }).click(); + await page.getByRole("button", { name: "注册并登录" }).click(); + } + await expect(page.getByRole("navigation", { name: "主导航", exact: true })).toBeVisible(); +} + +test("authentication, shell, dialogs, theme and responsive structure", async ({ page }) => { + const consoleErrors = []; + const unexpectedResponses = []; + page.on("console", (message) => { + if (message.type() === "error" && !message.text().includes("401 (Unauthorized)")) { + consoleErrors.push(message.text()); + } + }); + page.on("response", (response) => { + const expectedAnonymousProbe = response.status() === 401 && response.url().endsWith("/api/auth/session"); + if (response.status() >= 400 && !expectedAnonymousProbe) { + unexpectedResponses.push(`${response.status()} ${response.url()}`); + } + }); + + await authenticate(page, "stage4admin", "Stage4-pass-123!"); + await expect(page.getByText("管理员", { exact: true })).toBeVisible(); + await expect(page.getByRole("button", { name: "系统管理" })).toBeVisible(); + await expect(page.locator(".nav-item")).toHaveCount(16); + + await page.getByRole("button", { name: /stage4admin/ }).click(); + const accountMenu = page.locator(".account-menu"); + await expect(accountMenu.getByRole("button")).toHaveCount(5); + await accountMenu.getByRole("button", { name: "个人资料" }).click(); + const profileDialog = page.getByRole("dialog", { name: "个人资料" }); + await expect(profileDialog).toBeVisible(); + await profileDialog.getByLabel("出生日期").fill("1990-03-08"); + await profileDialog.getByLabel("出生时间").fill("08:30"); + await profileDialog.getByLabel("性别").selectOption("male"); + await profileDialog.getByRole("button", { name: "保存", exact: true }).click(); + await expect(page.getByRole("status")).toContainText("个人资料已保存"); + await page.getByLabel("关闭").click(); + + await page.getByRole("button", { name: "普通用户" }).click(); + await expect(page.getByRole("dialog", { name: "会员状态" })).toContainText("智能选股、问师、问天、复盘助手"); + await page.getByLabel("关闭").click(); + + await page.getByRole("button", { name: /stage4admin/ }).click(); + await page.locator(".account-menu").getByRole("button", { name: "修改密码" }).click(); + const passwordDialog = page.getByRole("dialog", { name: "修改密码" }); + await expect(passwordDialog.getByLabel("当前密码")).toBeVisible(); + await expect(passwordDialog.getByLabel("确认新密码")).toBeVisible(); + await page.getByLabel("关闭").click(); + + await page.keyboard.press("Control+K"); + const searchDialog = page.getByRole("dialog", { name: "全局搜索" }); + await expect(searchDialog).toBeVisible(); + const dialogBox = await searchDialog.boundingBox(); + expect(dialogBox).not.toBeNull(); + expect(Math.abs(dialogBox.x + dialogBox.width / 2 - 960)).toBeLessThan(2); + await page.keyboard.press("Escape"); + + const desktopMetrics = await page.evaluate(() => ({ + topbar: document.querySelector(".topbar")?.getBoundingClientRect().height, + sidebar: document.querySelector(".sidebar")?.getBoundingClientRect().width, + paddingTop: getComputedStyle(document.querySelector(".page-frame")).paddingTop, + paddingLeft: getComputedStyle(document.querySelector(".page-frame")).paddingLeft, + overflow: document.documentElement.scrollWidth - window.innerWidth, + })); + expect(desktopMetrics).toEqual({ topbar: 46, sidebar: 200, paddingTop: "14px", paddingLeft: "16px", overflow: 0 }); + await page.screenshot({ path: path.join(evidence, "shell-light-1920x1080.jpg"), type: "jpeg", quality: 82 }); + + await page.getByRole("button", { name: "夜间" }).click(); + await expect(page.locator("html")).toHaveAttribute("data-theme", "dark"); + await page.reload(); + await expect(page.locator("html")).toHaveAttribute("data-theme", "dark"); + await expect(page.getByRole("button", { name: "日间" })).toBeVisible(); + await page.screenshot({ path: path.join(evidence, "shell-dark-1920x1080.jpg"), type: "jpeg", quality: 82 }); + + await page.getByRole("button", { name: "系统管理" }).click(); + await expect(page.getByRole("heading", { name: "系统管理" })).toBeVisible(); + await expect(page.getByRole("tab")).toHaveCount(0); + await expect(page.getByRole("button", { name: "行情管理" })).toBeVisible(); + await expect(page.getByRole("button", { name: "模型池" })).toBeVisible(); + await expect(page.getByRole("button", { name: "会员管理" })).toBeVisible(); + await page.getByRole("button", { name: "模型池" }).click(); + await expect(page.getByRole("heading", { name: "添加模型" })).toBeVisible(); + await page.getByRole("button", { name: "会员管理" }).click(); + await expect(page.getByRole("heading", { name: "账号会员状态" })).toBeVisible(); + await page.getByRole("button", { name: "行情管理" }).click(); + + await page.setViewportSize({ width: 3840, height: 2160 }); + expect(await page.evaluate(() => document.documentElement.scrollWidth - window.innerWidth)).toBe(0); + await page.screenshot({ path: path.join(evidence, "system-dark-3840x2160.jpg"), type: "jpeg", quality: 72 }); + + await page.goto("/workspace/emotion"); + await page.setViewportSize({ width: 390, height: 844 }); + await expect(page.getByRole("navigation", { name: "移动端主导航" })).toBeVisible(); + await expect(page.getByRole("navigation", { name: "主导航", exact: true })).toBeHidden(); + expect(await page.evaluate(() => document.documentElement.scrollWidth - window.innerWidth)).toBe(0); + await page.screenshot({ path: path.join(evidence, "shell-dark-390x844.jpg"), type: "jpeg", quality: 82 }); + + expect(consoleErrors).toEqual([]); + expect(unexpectedResponses).toEqual([]); +}); + +test("regular users do not receive administrator controls and see intelligent locks", async ({ page }) => { + await authenticate(page, "stage4user", "Stage4-user-123!"); + await expect(page.getByText("管理员", { exact: true })).toHaveCount(0); + await expect(page.getByRole("button", { name: "系统管理" })).toHaveCount(0); + await expect(page.getByRole("button", { name: "后台刷新" })).toHaveCount(0); + + await page.goto("/system"); + await expect(page).toHaveURL(/\/workspace\/emotion$/); + + await page.goto("/workspace/screener"); + await expect(page.getByText("智能选股仅对会员开放")).toBeVisible(); + await expect(page.getByRole("button", { name: "查看会员状态" })).toBeVisible(); +});