- 统一品牌为 Nex:侧边栏、托盘 tooltip、HTML 标题、favicon (PNG 替代 SVG) - 重构关于页面为三卡片布局(品牌/版本/链接),版本状态 Tag 绝对定位右上角 - 新增 GET /api/version 后端接口,返回 version/commit/build_time - 新增前端版本一致性诊断:匹配/不匹配/不可判断三种状态 - 同步 delta specs 到主 specs 并归档变更
9.2 KiB
Context
Nex 已经具备统一版本源:仓库根目录 VERSION 是权威版本,versionctl sync 会同步 frontend/package.json 和前端 .env.* 中的 VITE_APP_VERSION,Go 二进制构建通过 -ldflags 注入 backend/pkg/buildinfo。当前缺口在运行时可见性:前端只能知道自身构建版本,无法从后端获取 server/desktop 二进制版本,也无法判断前后端是否来自同一版本。
前端侧边栏当前在 AppLayout 中以 AI Gateway 作为品牌文字,折叠后 logo 区域为空,HTML title 也仍为 AI Gateway。About 页面只展示名称、描述和链接,缺少版本、构建信息、状态反馈和现代化信息层次。图标资源方面,前端 public 目录维护独立 SVG favicon 和未使用的 icons.svg,而桌面托盘和打包资源已经使用仓库 assets/icon.png、assets/icon.ico、assets/icon.icns。desktop 代码中的 appName/appTooltip 已经是 Nex,但现有 desktop-app spec 仍保留旧 tooltip 文案,需要借本次 change 同步。
本变更跨越前端页面、前端 API、后端管理接口、desktop 静态资源服务、README 和 OpenSpec,因此需要先固定实现边界,避免实现阶段出现多个版本来源或重复图标资源。
Goals / Non-Goals
Goals:
- 统一用户可见应用名称为
Nex,覆盖前端侧边栏、HTML title 和相关测试断言,AI Gateway作为产品描述保留。 - 侧边栏展开态显示统一图标和
Nex,折叠态仍显示统一图标。 - 前端 favicon/public 图标复用仓库
assets/icon.png,清理不再使用的 SVG public 图标资源。 - About 页面展示前端版本、后端版本、后端 commit、后端 build_time 和版本匹配状态。
- 后端在 server 和 desktop 模式下都提供
GET /api/version。 - 明确并落地前端样式优先级:TDesign 组件 props、TDesign tokens、SCSS。
- 补充单元测试、组件测试、后端路由测试和必要的 E2E 覆盖。
- 同步更新根 README、frontend README、backend README。
Non-Goals:
- 不改变版本权威来源,仍以根目录
VERSION为唯一版本源。 - 不新增前端或后端依赖。
- 不引入用户认证、权限控制或配置项开关。
- 不让 About 页面阻断业务功能;版本不一致仅提示,不禁止使用。
- 不重构所有已有内联样式,只处理本次触达的品牌和 About 页面相关样式。
Decisions
Decision: 后端版本信息复用 buildinfo 并通过 /api/version 暴露
后端 SHALL 新增 GET /api/version 管理接口,响应字段为 version、commit、build_time,字段值来自 buildinfo.Version()、buildinfo.Commit()、buildinfo.BuildTime()。
选择 /api/version 的原因:管理接口已经统一使用 /api/*,前端 API 客户端也以该路径族访问后端;/health 应保持存活检查语义,不混入构建元数据。选择 buildinfo 的原因:Makefile 已在 server 和 desktop 构建中注入版本、commit 和 buildTime,运行时读取 VERSION 会破坏发布产物独立性。
备选方案:扩展 /health。放弃原因是健康检查会被监控系统频繁调用,混入构建信息容易模糊职责,并且前端语义上需要的是管理信息而不是存活探针。
Decision: server 和 desktop 分别注册同一个版本接口
server 和 desktop 当前拥有独立 setupRoutes,因此两个入口都 MUST 注册 GET /api/version。desktop 还需要确保该路径不会落入 SPA fallback 或协议代理路由。
备选方案:只在 server 注册。放弃原因是桌面应用使用独立路由装配和静态资源服务,用户在 desktop 模式下同样需要 About 页面展示后端版本。
Decision: 前端版本使用 VITE_APP_VERSION,不运行时读取 package.json
前端 SHALL 使用 import.meta.env.VITE_APP_VERSION 作为自身版本,缺失时降级为 dev 或 unknown 显示。该值由版本同步工具写入 .env.*,符合现有构建版本注入规则。
备选方案:在前端运行时请求或打包 package.json。放弃原因是会产生第二个版本读取路径,并可能在 desktop 嵌入构建、生产构建和测试环境中产生不一致。
Decision: About 页面只提示版本一致性,不阻断功能
About 页面 SHALL 根据前端版本和后端版本显示状态:一致、不一致、开发构建无法判断、后端版本获取失败。状态通过 TDesign Tag 和必要时的 Alert 展示。
判断规则:前端版本等于后端版本时为一致;任一版本为 dev、unknown、空值时为无法判断;请求失败时为后端版本获取失败;其余不相等时为不一致。
备选方案:版本不一致时阻断或弹窗提示。放弃原因是版本检查用于部署诊断,不能影响现有配置和代理能力。
Decision: 图标资源统一到 assets/icon.png 并固定运行时路径
前端 public 图标 SHALL 由仓库 assets/icon.png 派生,实施时将根目录 assets/icon.png 复制为 frontend/public/icon.png,前端入口 SHALL 使用 /icon.png 作为 PNG favicon 路径。frontend/public/favicon.svg 不再作为 favicon 来源,frontend/public/icons.svg 经确认未被引用后 SHALL 删除。
Vite 会将 frontend/public/icon.png 输出到 dist 根目录,因此 desktop 静态服务 SHALL 显式服务 /icon.png 并读取嵌入 dist 中的 icon.png。README SHALL 标注 frontend/public/icon.png 来源于根目录 assets/icon.png,后续更新应用图标时应以根目录资源为准并同步 public 镜像。
备选方案:继续保留 SVG favicon。放弃原因是会继续存在两套应用图标来源,与用户要求的统一资源方向不一致。
Decision: 前端样式优先级写入 README 并指导实现
实现视觉效果时,前端 SHALL 优先使用 TDesign 组件 props,例如 Card 的 bordered、hoverShadow、headerBordered,Tag 的 theme、variant、shape,Row/Col 的响应式 props。组件 props 不足时使用 TDesign tokens,例如 var(--td-text-color-secondary)、var(--td-brand-color)。只有 props 和 tokens 无法表达布局、响应式或品牌细节时才使用 SCSS。
备选方案:直接新增 SCSS Modules 完成全部视觉。放弃原因是项目已经在 OpenSpec 中要求优先使用 TDesign 样式体系,过多 SCSS 会增加覆盖组件内部样式的风险。
Decision: About 页面采用信息面板布局
About 页面 SHALL 以三个独立 Card 垂直排列呈现:顶部品牌卡片展示图标、Nex、产品描述;中部版本信息卡片展示前端版本、后端版本、commit、build_time,版本状态 Tag 以绝对定位浮动在卡片右上角;下部链接卡片展示外部链接入口。
布局示意:
┌─────────────────────────────────────────────┐
│ Icon Nex │
│ AI Gateway - 统一的大模型 API 网关 │
└─────────────────────────────────────────────┘
┌─────────────────────────────────────────────┐
│ 前端版本 后端版本 构建信息 [Tag] │
│ v0.1.0 v0.1.0 commit/time │
└─────────────────────────────────────────────┘
┌─────────────────────────────────────────────┐
│ GitHub / 文档 / License │
└─────────────────────────────────────────────┘
Decision: desktop-app spec 同步现有 Nex tooltip
desktop 代码已经通过 appName = "Nex" 和 appTooltip = appName 使用统一应用名称,现有 desktop-app spec 中 tooltip 仍写 AI Gateway。本次 change 已触达 desktop-app capability,因此 delta spec SHALL 同步修正托盘 tooltip 要求为 Nex,避免归档后主 spec 与当前代码继续漂移。
Risks / Trade-offs
/api/version在未通过 Makefile 运行的本地 Go 进程中可能返回dev/unknown/unknown→ About 页面将其视为开发构建,显示“无法判断”而不是错误。- desktop 与 server 路由重复维护,可能漏注册 → 任务中明确分别添加路由测试,覆盖两个入口。
- 前端 public PNG 与根
assets/icon.png可能漂移 → README 明确来源;实现阶段复制assets/icon.png到frontend/public/icon.png,并通过构建验证确认/icon.png可用。 - 删除
frontend/public/icons.svg可能影响隐藏引用 → 已通过全文搜索未发现引用;实现阶段删除前再次全文确认,删除后运行前端测试和构建验证。 - 样式优先级与现有 README “SCSS Modules” 表述可能冲突 → 本变更同步更新 README,以 TDesign props/tokens 优先作为新的明确规则。
- 版本不一致提示可能被误解为严重故障 → 文案应说明该状态用于部署诊断,不影响当前功能使用。