Files

28 KiB
Raw Permalink Blame History

opencatd-open 重构计划

本文档是重构过程的唯一进度记录,每完成一个阶段立即更新「阶段状态」与「执行记录」。 前后端同仓库,本期(第一期)只重构前端 + 前端相关的构建脚本;后端代码不在本期范围。

  • 计划创建时间:2026-08-29
  • 当前分支:team(按约定不提交,所有改动留在工作区,由维护者回来后审查)
  • 项目根目录:/Users/cjun/Code/Go/src/opencatd-open
  • 前端目录:frontend/(构建产物 dist/ 由 Go 通过 //go:embed dist/* 嵌入 cmd/openteam)

一、背景与现状

项 现状 问题
技术栈 Vue 3.5 + Vite 6 + JavaScript,无 TS 依赖偏旧;无类型约束
UI 库 Element Plus 与 daisyUI/Tailwind 3 两套并存 9 个视图使用 el-* 组件,风格割裂、包体冗余
目录结构 components/views 仅按 dashboard 简单分层 组件分类不规范,无 api/layouts/types 分层
构建脚本 Dockerfile 三阶段,node 阶段未指定 $BUILDPLATFORM 多架构构建时前端被 QEMU 模拟重复编译,极慢
依赖声明 pinia、@iconify/vue 误放 devDependencies 分类错误
Dockerfile 杂项 存在无效的 CMD ["go mod tidy","go mod download"];node:20 基础镜像 需清理/升级
杂项 根目录 web/(仅 dist + node_modules,未跟踪) 疑似误构建产物,暂不动,仅记录

二、已确认的决策(2026-08-29,维护者离开前确认)

  1. 迁移到 TypeScript(全量,含 vue-tsc 类型检查)。
  2. UI 统一到 Tailwind/daisyUI,移除 Element Plus,el-* 组件全部重写;接受外观变化。
  3. 不提交:所有改动留在工作区,按阶段推进,不做 git commit。

其余由执行者自行决定的默认约定:

  • 依赖一律升到当前最新稳定版(含 Tailwind 4 / daisyUI 5 / Vite 7+ / Pinia 3 等大版本跨越)。
  • Element Plus 在被移除前不再投入升级成本(Phase 4 直接删除)。
  • 每阶段验收标准:pnpm build(后期含 vue-tsc)通过 + 页面路由/交互逻辑与重构前等价。
  • 计划文档放项目根目录 REFACTOR_PLAN.md。

三、阶段计划

阶段 内容 状态
Phase 0 创建本计划文档 ✅ 完成
Phase 1 依赖全部升级到最新版(Tailwind 4 / daisyUI 5 迁移、pinia 归位 dependencies) ✅ 完成
Phase 2 TypeScript 迁移(tsconfig、vue-tsc、全量 .ts/.vue 改写) ✅ 完成
Phase 3 目录结构规范化(api / components / composables / layouts / types / views 分层) ✅ 完成
Phase 4 移除 Element Plus,统一 Tailwind/daisyUI 重写全部组件 ✅ 完成
Phase 5 Docker / makefile 构建脚本更新(前端 $BUILDPLATFORM 单次编译) ✅ 完成
Phase 6 最终验证(前端 build + Go embed 编译),收尾文档 ✅ 完成

四、各阶段详细方案

Phase 1 — 依赖升级

  • vite、@vitejs/plugin-vue、@vitejs/plugin-basic-ssl、vue、vue-router、axios、lucide-vue-next、qrcode.vue、@simplewebauthn/browser、@iconify/vue、@iconify-json/* → 最新。
  • pinia → v3 并移入 dependencies;@iconify/vue 移入 dependencies。
  • Tailwind 3 → 4:改用 @tailwindcss/vite 插件,删除 postcss.config.js/autoprefixer/tailwind.config.js,style.css 改为 @import "tailwindcss" + @plugin "daisyui" + @theme 定义原有 daisyUI 主题集合(light/dark/cupcake/emerald/pastel)。
  • daisyui → v5。
  • element-plus 保持现状(Phase 4 删除)。
  • 验收:pnpm build 通过。

Phase 2 — TypeScript 迁移

  • 新增 tsconfig.json(bundler 解析策略 + @ 别名路径映射)、src/vite-env.d.ts、env.d.ts(import.meta.env 类型)。
  • vite.config.js → vite.config.ts;src/**/*.js(router/stores/utils/main)→ .ts。
  • 全部 .vue 改 <script setup lang="ts">,props/emits/响应式数据补类型。
  • build 脚本加 vue-tsc --noEmit 类型检查。
  • 验收:pnpm build(含 vue-tsc)通过。

Phase 3 — 目录结构规范化

src/
├── api/              # axios 实例 + 各业务接口封装(由 utils/request.js 演进)
├── assets/           # 图片/图标(不变)
├── components/
│   ├── common/       # 通用组件(Toast、Pagination、QRCodeCard、LineSegmentFlow)
│   └── dashboard/    # 仪表盘布局组件(Sidebar、BreadcrumbHeader)
├── composables/      # 组合式函数(useToast 等从 provide/inject 演进)
├── layouts/          # 布局(DashboardLayout 等,如适用)
├── router/           # 路由
├── stores/           # pinia stores
├── styles/           # 全局样式
├── types/            # 共享 TS 类型(API 响应、业务实体)
├── utils/            # 纯工具函数(格式化日期等)
└── views/
    ├── auth/         # Login、Signup
    ├── error/        # 404
    └── dashboard/    # Overview、Keys、Tokens、Users、Settings、Profile 等
  • vite.config 的 manualChunks 别名同步更新。
  • 验收:pnpm build 通过,无悬空 import。

Phase 4 — UI 统一到 Tailwind/daisyUI

  • 移除 element-plus 依赖与 main.ts 全局注册。
  • 重写以下 9 个视图中的 el-* 组件(table/dialog/form/select/input/switch/message 等用 daisyUI 组件类 + 自实现交互): Login、Signup、dashboard/{UserView、Settings、KeyView、Profile、TokenNew、KeyNew、UserNew}。
  • 顺带规范既有自研组件(Toast、Pagination 等)使用 daisyUI 类。
  • 保留既有业务逻辑、字段、接口调用不变。
  • 验收:pnpm build 通过;grep el-/element-plus 无残留。

Phase 5 — Docker / makefile 构建脚本

  • deploy/docker/Dockerfile:
    • 前端阶段 FROM --platform=$BUILDPLATFORM node:22-alpine AS frontend(多架构下只原生编译一次)。
    • 后端阶段同样 $BUILDPLATFORM + CGO_ENABLED=0 GOOS=linux GOARCH=$TARGETARCH 交叉编译(go.mod 使用纯 Go 的 glebarez/sqlite,可关闭 CGO);如遇阻塞则后端阶段回退为按目标平台编译,仅保留前端优化。
    • 删除无效 CMD 行;runner 阶段瘦身。
  • makefile:web 目标改用 pnpm(不强制全局安装 pnpm),构建产物位置与 embed 路径核对。
  • 同步更新 Dockerfile.cn(国内镜像版)保持一致。
  • 验收:docker build 本地单架构通过(多架构如环境不允许则用 --platform 模拟检查语法与目标参数)。

Phase 6 — 最终验证与收尾

  • frontend: pnpm build(含 vue-tsc)。
  • 把 frontend/dist 放入 cmd/openteam/dist 后执行 go build ./cmd/openteam,确认 embed 成功。
  • 更新本文档所有阶段状态与执行记录,列出遗留问题(如 web/ 目录处置、外观回归点)。

五、执行记录(每阶段完成后追加)

Phase 0 — 计划文档创建(2026-08-29)

  • 已确认三项决策:TS 迁移 / 统一 Tailwind-daisyUI / 不提交。
  • 摸底结论:前端约 4700 行 Vue;Element Plus 用于 9 个视图;pinia、@iconify/vue 在 devDependencies;glebarez/sqlite 为纯 Go 驱动(Docker 交叉编译可行);本地 Node v25.2.1 / pnpm 10.25.0。
  • 发现根目录未跟踪的 web/ 目录仅含 dist 与 node_modules,疑似误产物,本期不动。

Phase 1 — 依赖升级(2026-08-29)✅

  • 升级结果(均为当前最新稳定版):
    • dependencies:vue 3.5.42、vue-router 5.3.0(大版本 4→5)、pinia 4.0.3(大版本 2→4,并移入 dependencies)、axios 1.20.0、qrcode.vue 3.10.0、@simplewebauthn/browser 13.3.0、@iconify/vue 5.0.1(移入 dependencies)、@lucide/vue 1.37.0(替代已废弃的 lucide-vue-next)。
    • devDependencies:vite 8.2.2(大版本 6→8,构建器为 rolldown)、@vitejs/plugin-vue 6.0.8、@vitejs/plugin-basic-ssl 2.3.0、tailwindcss 4.3.3(大版本 3→4)、@tailwindcss/vite 4.3.3、daisyui 5.7.22(大版本 4→5)、@iconify-json/* 升级。
    • 移除:autoprefixer、postcss、tailwind.config.js、postcss.config.js(Tailwind 4 改为 CSS-first 配置)。
  • 迁移要点:
    • style.css 改为 @import "tailwindcss" + @plugin "daisyui",主题集合保持 light(默认)/dark/cupcake/emerald/pastel。
    • vite.config.js 加入 @tailwindcss/vite 插件;__dirname 改为 import.meta.dirname(消除 Vite 8 警告)。
    • package.json 改名为 opencatd-open-frontend;新增 pnpm.onlyBuiltDependencies: [esbuild, vue-demi] 放行构建脚本。
  • 代码适配:新版 Lucide 移除品牌图标,Profile.vue 的 <Github> 图标改为项目内已有的 <img src="/assets/github.svg">(与 Keys/KeyNew/KeyView 用法一致)。
  • 验收:pnpm build 通过(4.8s,rolldown 构建)。
  • 备注:element-plus 2.9.7 保持旧版未升级(Phase 4 将整体移除);当前 components chunk 406KB 主要来自 Element Plus,Phase 4 后预计大幅缩小。

Phase 2 — TypeScript 迁移(2026-08-29)✅

  • 工具链:typescript 6.0.3 + vue-tsc 3.3.11 + @types/node 26.4.0。
    • 注:最初装了 typescript 7.0.2(tsgo 原生版),但 vue-tsc 依赖 typescript/lib/tsc 导出而 TS7 已移除,故回落到 6.x(当前最新 JS 版)。
    • tsconfig:strict 模式、bundler 解析、@ 别名(TS6 弃用 baseUrl,改用相对 paths)、types 含 vite/client + node。
  • 全量转换:vite.config.ts、src/main.ts、router/stores/utils 共 9 个 JS→TS;19 个 .vue 全部 <script setup lang="ts">。
  • 类型设计:
    • src/types/index.ts:UserInfo / TokenInfo / ApiKey / PasskeyInfo 及各请求 Payload 类型(宽松可选字段 + 索引签名兼容后端松散返回)。
    • src/composables/toast.ts:类型安全的 provide/inject(InjectionKey),替代各视图裸 inject('toast')。
    • vue-router RouteMeta 模块扩展(title/icon/showInSidebar/requiresAuth 等);MenuItem 为可辨识联合。
  • package.json:新增 typecheck 脚本;build 改为 vue-tsc --noEmit && vite build。
  • 顺带修复的存量 bug(均记录在案):
    1. Keys.vue toggleSelectAll 引用了不存在的 users(应为 keys)——运行时全选会抛错。
    2. Settings.vue updateUser 引用了未定义的 userStore/userId(复制粘贴残留),提交表单必抛错——改为经 authStore.updateProfile 更新当前用户。
    3. store 的 catch 中 throw error 抛出的是 Ref 对象,Login.vue 会把 Ref 显示为 [object Object]——加了 errMsg() 取值辅助。
    4. KeyNew.vue 模板绑定了不存在的 togglePasswordVisibility(点击报 TypeError)——移除死绑定。
    5. User/Keys/UserNew/KeyNew 里 res.error 恒为 undefined(AxiosResponse 无此字段)——改为 res.data?.error。
    6. TokenNew.vue 初始 user_id: user.user_id(ComputedRef 上取值恒 undefined)——改为 user.value?.user_id。
    7. Login.vue rember 记住密码存入布尔被 localStorage 转字符串('true'),统一 String() 存储。
  • 验收:pnpm build(含 vue-tsc 严格检查)通过。

Phase 3 — 目录结构规范化(2026-08-29)✅

  • 最终结构:
    • src/api/client.ts ← utils/request.ts(axios 实例与拦截器;业务接口调用仍保留在 stores 中,作为轻量 API 层,避免无谓 churn,后续可按需下沉到 api/ 各模块)
    • src/components/common/ ← Toast / Pagination / QRCodeCard / LineSegmentFlow
    • src/components/dashboard/ 保持(Sidebar / BreadcrumbHeader)
    • src/layouts/DashboardLayout.vue ← views/DashBoard.vue(本质是布局组件,归位 layouts 层)
    • src/styles/main.css ← src/style.css
    • src/views/auth/ ← Login / Signup;src/views/error/NotFound.vue ← views/404.vue
    • src/views/Home.vue、src/views/dashboard/* 保持
  • 全部相对路径 import 统一为 @/ 别名;模板内相对资源路径(../assets/...)统一为 @/assets/...。
  • vite.config.ts 的 manualChunks 分包规则按新目录核对(components / views-dashboard / stores 三组仍有效)。
  • 验收:pnpm build 通过,无悬空 import。

Phase 4 — UI 统一到 Tailwind/daisyUI(2026-08-29)✅

  • 摸底修正:Element Plus 实际仅在 3 处使用(main.ts 全局注册 + KeyNew/KeyView 的 el-input-tag),其余视图本就以 daisyUI 为主。
  • 变更:
    • main.ts 移除 Element Plus 注册与样式;pnpm remove element-plus。
    • 新增 src/components/common/TagInput.vue(daisyUI 风格,Enter 添加/逐个删除/Backspace 删末尾/可清空),替换 KeyNew/KeyView 中的 el-input-tag。
    • 全库 grep 确认无 element-plus / el-* 组件残留。
  • 收益(构建产物对比):
    • 主 CSS:489.6KB → 163.4KB(-67%,主要为 Element Plus 全量样式)
    • components JS:405.7KB → 194.7KB(-52%)
    • 入口 index JS:617.8KB → 1.3KB(Element Plus 运行时原本在入口包)
  • 验收:pnpm build(含类型检查)通过。

Phase 5 — Docker / makefile 构建脚本(2026-08-29)✅

  • deploy/docker/Dockerfile 重写:
    • 前端阶段 FROM --platform=$BUILDPLATFORM node:22-alpine:多架构构建时前端只在构建机原生平台编译一次(原先会被 QEMU 模拟在每个目标平台各跑一遍)。
    • 后端阶段同样 $BUILDPLATFORM + CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH 交叉编译(glebarez/sqlite 纯 Go 驱动,已验证可行),全程零 QEMU。
    • 删除了无效且写法错误的 CMD ["go mod tidy","go mod download"];pnpm 固定 @10.25.0;pnpm install --frozen-lockfile;runner 阶段补充 ca-certificates;修正 LABEL anther→author;移除不再需要的 cmake。
    • Dockerfile.cn(国内源版)同步更新。
  • 新增根目录 .dockerignore(原先缺失:node_modules、dist、.git、web/ 等全部会被拷进构建上下文)。
  • makefile:
    • web 目标:pnpm 按需安装 + --frozen-lockfile,产物干净替换到 cmd/openteam/dist(原 mv dist ../cmd/openteam/ 在目标已存在时会错误嵌套一层)。
    • build 目标:加 CGO_ENABLED=0;upx 改为可选(本机未装时跳过,不再中断)。
  • package.json 增加 "packageManager": "pnpm@10.25.0":新版 pnpm 默认启用供应链策略(拒装 24h 内发布的包)并不再读取 package.json 的 pnpm 字段,钉住版本保证容器内外行为一致、可重现。
  • 验证:
    • docker build --target frontend 通过,dist 产物完整。
    • docker buildx build --platform linux/amd64,linux/arm64(xbuilder)通过;日志确认 frontend 仅在原生平台执行一次,arm64 后端为交叉编译,无 QEMU。
    • 本机 CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build 产出静态 ELF(含嵌入前端)。
    • make web、make build 通过。

Phase 6 — 最终验证与收尾(2026-08-29)✅

  • pnpm build(vue-tsc 严格类型检查 + vite 构建)通过。
  • .gitignore 补充 cmd/openteam/dist/(构建产物)与 web/(误生成目录,未跟踪)。
  • 遗留事项(供维护者决策,均不影响本期交付):
    1. frontend/src/utils/format-date.ts、Overview.vue 内部仍各自实现了一份 formatDateTime,可合并到 utils 统一导入(行为无差异,纯清理)。
    2. CI workflow(.github/workflows/)引用的 ./docker/Dockerfile 路径早已失效(现为 deploy/docker/Dockerfile),且 checkout 的还是 @v3 旧 action——后端/CI 不在本期范围,未改动。
    3. 依赖升级中未逐项验证运行时 UI 细节(如 daisyUI 4→5 的个别类名行为差异、vue-router 4→5),建议维护者回来后 make web && make build 或 pnpm dev 过一遍登录/令牌/密钥/用户管理页面。
    4. web/ 目录(仅 dist + node_modules)疑似误构建产物,已加入 .gitignore,确认无用后可删除。

六、后续增量(2026-08-29,维护者返程前追加)

增量 1 — 本地开发体验优化(前后端分离联调)✅

背景:前端构建产物经 //go:embed 嵌入 Go 二进制,本地每改一次前端都要 make web + make build,且没有热更新。

  • frontend/vite.config.ts:dev server 增加 server.proxy,/api 代理到本地 Go 后端(默认 http://localhost:8080,VITE_DEV_API_TARGET 可覆盖)。开发时前端跑在 Vite 上(HMR),接口走代理到后端,无跨域问题。
    • dev server 默认改为 HTTP(localhost 属浏览器安全上下文,clipboard/Passkey 均可用);需要自签名 HTTPS 时设 VITE_DEV_HTTPS=true 恢复 basicSsl。
  • cmd/openteam/main.go://go:embed dist/* → //go:embed all:dist,配合 cmd/openteam/dist/.gitkeep 占位(已跟踪),dist 没有真实产物时 go run ./cmd/openteam 也能编译启动——克隆后可直接起后端联调,不必先构建前端。make web 移入产物后会补回 .gitkeep。
  • makefile 新增:
    • make dev-backend:PORT=8080 go run ./cmd/openteam(数据库 ./db/openteam.db)
    • make dev-frontend:cd frontend && pnpm dev(5173)
    • make dev:$(MAKE) -j2 并行启动两者,Ctrl+C 一起退出
  • frontend/README.md 补充开发文档(启动方式、环境变量表)。
  • 验证:后端 8080 + Vite 5173 同时运行,curl http://localhost:5173/ 返回 SPA 页面;经 5173 代理的 POST /api/auth/login 返回后端真实校验 JSON、GET /api/auth/passkey/begin 返回 200,代理链路完整。
  • 说明:这是构建基础设施改动,触及 cmd/openteam/main.go 一行 embed 指令;后端业务逻辑零改动。生产构建流程不受影响(Docker 内 dist 由前端阶段提供)。

增量 2 — 全站 UI/UX 重设计(web-design-guidelines)✅

依据:Vercel Web Interface Guidelines(~/.agents/skills/web-design-guidelines 拉取的最新规则集)。先对全部页面截图建立基线,再逐页重写模板;业务逻辑、接口调用、路由全部未动。

  • 设计系统基础(styles/main.css + index.html):
    • 深浅色 color-scheme 跟随主题;<meta name="theme-color">;内联脚本恢复上次主题(不再每次刷新回 emerald)。
    • 全局 :focus-visible 焦点环、touch-action: manipulation、prefers-reduced-motion 全局降级、.modal-box 防滚动穿透。
    • 覆写 emerald 主题圆角令牌(默认 selector 圆角 1rem 使小复选框渲染成正圆的 bug)。
  • 壳层:侧栏启用 daisyUI 5 menu-active 高亮 + sticky;顶栏重排(侧栏开关带 aria-pressed、主题切换持久化 localStorage、用户菜单头像+用户名);主区限宽 max-w-6xl。
  • 页面模式统一:面包屑 + 大标题 → 描述 + 主操作 → 卡片内容;列表页统一工具栏/表格/空状态/分页(空数据隐藏分页);表单统一分区标题、label/控件绑定、required 标记、示例占位符、提交按钮 spinner。
  • 主要变更:
    • Overview:深色渐变横幅改为品牌 primary→secondary 渐变;信息卡由 badge 滥用改为 dl 键值布局(仅角色/状态保留 badge);时间 tabular-nums。
    • Tokens/Keys/Users 列表:空状态(图标+文案+CTA)、行操作按钮 aria-label、状态筛选改为带计数的下拉、移除两个死的 Filter 输入框、批量操作菜单重排。
    • 弹窗表单(TokenNew/KeyNew/UserNew):去掉 min-h-screen 包裹,适配弹窗容器。
    • 详情页(KeyView/UserView):头像+徽章头部、分区表单、tokens 表格;加载态明确。
    • Profile/Settings:分区卡片(基本信息/密码/Passkeys/关联账号),提交加 spinner。
    • Login/Signup:实体主按钮、内联错误 alert(role=alert)、autocomplete(username/current-password/new-password)、死链"Forgot password?"移除、密码不一致内联提示。
    • Home:导航栏 Star 徽标 + Open Dashboard 主 CTA,hero 文案重写,endpoint 复制组加 label,图片补尺寸。
    • 404:品牌化布局 + 具体文案("doesn't exist or has been moved")。
    • Toast:aria-live="polite" + toast-top/end 定位;Pagination:join 样式 + Showing x–y of z + tabular-nums。
  • 顺带修复:DashboardLayout if (!userInfo) 恒真导致刷新后头部用户名丢失(改为 !authStore.user)。
  • 验证:pnpm build(vue-tsc 严格检查)通过;本地起前后端后逐页浏览器截图回归(Users/Overview/Tokens/新建弹窗/Keys 空状态/Profile/404/Home/Login)视觉与交互正常;复选框圆角修复经计算样式确认(16px→8px)。
  • 已知取舍:破坏性操作沿用原生 confirm()(满足"需确认"要求,后续可换主题化 modal);列表筛选/分页尚未同步到 URL query(指南建议,列为后续项);"Forgot password?" 为死链已移除。
  • 补充(维护者反馈):Overview 横幅恢复随时间段变化的配色(原版行为),四段式与新版式协调——深夜 slate-900→indigo-950、早晨 sky-600→amber-400、白天 blue-600→cyan-400、夜晚 slate-900→indigo-950;白色文字置于渐变左侧深色端保证对比度。顺带修复原版问候语 bug:0-6 点原显示"早上好",现对齐四段为"夜深了"。

增量 3 — 主题切换(浅色 / 深色 / 自动)✅

  • 新增 src/composables/theme.ts:偏好三态 light | dark | auto(浅色映射品牌 emerald 主题),localStorage 持久化(key theme),auto 模式监听 prefers-color-scheme 实时跟随系统切换;模块级单例状态,主页与仪表盘共享。
  • index.html 内联脚本同步三态逻辑(含 auto 解析),首屏不闪烁。
  • 主页导航栏与仪表盘顶栏均提供主题下拉(太阳/月亮/显示器图标随当前偏好变化,当前项 menu-active 高亮);仪表盘原先的二态硬切换按钮升级为同一三选下拉,避免两套主题逻辑互相覆盖。
  • 默认偏好为 auto(首次访问跟随系统);旧存储值 emerald 不再有效,自动回落 auto。
  • 验证:pnpm build 通过;浏览器实测浅色↔深色↔自动即时生效、data-theme 与 localStorage 值正确、刷新后保持、auto 按系统深色解析为 dark;主页与仪表盘主题共享一致。

增量 4 — 导航栏按角色分区重设计(参考维护者提供的双栏设计稿)✅

  • 信息架构对齐设计稿:导航拆为控制台(所有用户:仪表盘 / API 密钥 / 账户设置)与管理后台(role ≥ 10:用户管理 / 渠道管理)两个区域,按当前路由区域(/dashboard/manager/*)切换显示;底部互切入口——控制台区显示「管理后台 →」(仅管理员),后台区显示「← 返回控制台」。
  • router_menu.ts 重写:弃用递归菜单生成器,改为显式两套菜单数组;路由 meta 标题中文化(仪表盘 / API 密钥 / 用户管理 / 渠道管理 / 账户设置等)。
  • BreadcrumbHeader 增加路由路径→中文标题映射,面包屑与页面标题随之中文化(此前按英文路径段拼接)。
  • 与设计稿的差异(页面对应关系):API 密钥→个人 Tokens 页;渠道管理→上游 Provider Keys 页;设计稿中的用量明细/用量统计/模型定价/系统配置暂无对应页面,未做死链,留作后续功能。
  • 验证:pnpm build 通过;浏览器实测 admin 视角(控制台菜单 + 底部管理后台入口 → 后台菜单 + 返回控制台,高亮正确)与普通用户视角(注册 member 账号实测:仅控制台菜单,管理后台入口数量为 0);中文面包屑生效。
  • 补充(维护者反馈):「API 密钥」菜单项与页面标题改名为 API Keys;面包屑重设计——废弃路径段拼接,改为按路由名显式定义层级:顶级页面(仪表盘/API Keys/账户设置)不显示面包屑仅保留标题,管理后台列表页显示「管理后台」一级,详情页显示「管理后台 / 列表页」两级(末级为当前页标题),标题统一取自定义 title 或路由 meta.title。
  • 补充(交互收尾):移动端抽屉在路由切换后自动收起(router.afterEach);顶栏主题/个人下拉为焦点展开型,选择后主动移除焦点收起菜单,个人菜单按钮补 aria-expanded 语义。注:DashboardLayout 模板含维护者手动增强的个人菜单(身份信息头 + 管理后台入口),脚本已按模板对齐(handleMenuAction / isAdminUser)。

增量 5 — 个人下拉修复与触屏可用性(维护者反馈)✅

  • 问题 1(内容不对):身份信息行的 email || '@username' 回退会显示伪社交句柄,且已在管理后台时仍显示「管理后台」入口。修复:第二行仅在存在邮箱时显示邮箱、有显示名时显示 @用户名、否则不显示;名称行追加角色徽章(Root/Admin/User);「管理后台」入口在后台区域隐藏(isAdminUser && !isAdminArea)。
  • 问题 2(手机点退出无反应):daisyUI CSS 下拉依赖焦点展开,触屏点击菜单项时按钮失焦、下拉先于 click 关闭导致点击落空。修复:主题与个人下拉改为状态驱动(dropdown-open class + v-if 遮罩点击关闭 + Escape 关闭 + 路由切换关闭),互斥打开;主页主题下拉同步修复。
  • 验证:pnpm build 通过;桌面实测下拉内容(root + Root 徽章 + @admin,菜单项完整);移动端 390px 实测点「退出登录」成功跳转 /login 且 token 清除;随后已恢复 admin 会话与桌面视口。
  • 补充(维护者反馈):个人下拉内的 <hr> 分割线被 daisyUI menu 的通用子元素样式选中(cursor: pointer + hover 背景,可点击),已为其 li 加 pointer-events-none select-none,实测恢复默认光标且不可交互。

增量 6 — 主按钮统一黑白配色(维护者反馈)✅

  • 背景:daisyUI dark 主题的 primary 为紫色,普通主按钮(btn-primary)在深色模式下显示为紫底。
  • 方案:main.css 覆写 .btn-primary 的 daisyUI 颜色变量(--btn-color / --btn-fg)——浅色主题黑底白字(#171717/#fff,hover 纯黑)、深色主题白底黑字(#fff/#171717,hover 浅灰)。仅影响 btn-primary;success/error/warning/outline/ghost 等特殊按钮与链接、开关、焦点环均保持原样。
  • 验证:pnpm build 通过;浏览器实测深色(白底黑字 New Token)与浅色(黑底白字 Log In)两种主题,特殊按钮未受影响;已恢复维护者的 auto 主题偏好与 admin 会话。

增量 7 — Toast 重写:多实例堆叠(维护者反馈)✅

  • 背景:原实现为串行队列(processQueue 一次展示一条),连续操作时提示互相阻塞。
  • daisyUI 的 toast 组件本身只负责定位与堆叠(容器内多个 alert 自动纵向排列),队列/自动消失/动画需应用层实现——已按此重写:
    • composables/toast.ts:模块级响应式 toasts 列表,setToast(message, type?, duration?) 推入带唯一 id 的条目并定时自动移除(默认 3s);useToast() 签名不变,13 个调用视图零改动;移除原 provide/inject 方案。
    • Toast.vue:daisyUI toast toast-top toast-end 容器 + TransitionGroup 进出场动画(仅 transform/opacity,配合全局 reduced-motion 降级)、每条带关闭按钮(aria-label)、容器 aria-live="polite"。
  • 验证:pnpm build 通过;浏览器实测连续触发两条 toast 同时堆叠展示、3s 后全部自动消失。

增量 8 — dev 镜像构建脚本(多平台)✅

  • 新增 deploy/docker/build-dev.sh + make image-dev:
    • 默认多平台 linux/amd64,linux/arm64 构建并推送(自动创建缺失的 buildx 容器构建器);PUSH=0 退化为本机架构构建并 --load 到本地。
    • 标签:dev、dev-<短SHA>、dev-<YYYYMMDD>(REGISTRY_IMAGE / PLATFORMS / BUILDER / DOCKERFILE 均可用环境变量覆盖)。
    • 推送时附带 registry inline cache(--cache-from/--cache-to type=inline)加速后续 dev 构建。
  • 验证:PUSH=0 端到端实测通过(容器内前端构建 + Go 交叉编译 + upx 压缩 31.7MB→11.8MB + 本地加载);镜像冒烟测试 /:200、/api/*:200。