feat: 统一品牌标识、关于页面三卡片布局与版本诊断功能
- 统一品牌为 Nex:侧边栏、托盘 tooltip、HTML 标题、favicon (PNG 替代 SVG) - 重构关于页面为三卡片布局(品牌/版本/链接),版本状态 Tag 绝对定位右上角 - 新增 GET /api/version 后端接口,返回 version/commit/build_time - 新增前端版本一致性诊断:匹配/不匹配/不可判断三种状态 - 同步 delta specs 到主 specs 并归档变更
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-05-04
|
||||
@@ -0,0 +1,105 @@
|
||||
## 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 以绝对定位浮动在卡片右上角;下部链接卡片展示外部链接入口。
|
||||
|
||||
布局示意:
|
||||
|
||||
```text
|
||||
┌─────────────────────────────────────────────┐
|
||||
│ 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 优先作为新的明确规则。
|
||||
- 版本不一致提示可能被误解为严重故障 → 文案应说明该状态用于部署诊断,不影响当前功能使用。
|
||||
@@ -0,0 +1,34 @@
|
||||
## Why
|
||||
|
||||
当前前端侧边栏仍显示旧的 `AI Gateway` 文案,折叠后品牌区域为空;About 页面信息展示较简陋,无法展示和判断前后端构建版本是否匹配。同时前端 public 图标资源与仓库统一的 `assets/icon.png` 不一致,并存在未使用的 SVG 图标资源,增加了品牌和资源维护成本。
|
||||
|
||||
## What Changes
|
||||
|
||||
- 将前端侧边栏品牌统一为 `Nex`,展开时显示统一图标和应用名称,折叠时仍显示图标。
|
||||
- 将前端 favicon/public 图标统一复用仓库 `assets/icon.png`,运行时统一使用 `/icon.png`;替换当前 `/favicon.svg` 引用并清理未使用的 `frontend/public/icons.svg` 资源。
|
||||
- 将前端 HTML 标题等用户可见应用名称同步为 `Nex`,保留 `AI Gateway` 作为产品描述。
|
||||
- 重新设计 About 页面信息结构,使用三个独立卡片分别展示品牌、版本信息和外部链接,版本状态 Tag 浮动在版本信息卡片右上角。
|
||||
- 新增后端管理接口 `GET /api/version`,暴露构建注入的 `version`、`commit`、`build_time`,供前端判断前后端版本一致性。
|
||||
- 在 server 和 desktop 两种启动模式下都注册版本接口,并确保 desktop 静态资源路由支持新的 PNG 图标路径。
|
||||
- 明确前端样式优先级:TDesign 组件 props 优先,其次使用 TDesign tokens,最后才在无法通过前两者表达时使用 SCSS,并同步更新 README。
|
||||
- 为菜单品牌、About 页面、版本接口、版本匹配状态和资源清理补充测试。
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
无。
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- `frontend`: 侧边栏品牌标识、折叠态 logo、HTML 标题、前端样式优先级和 public 图标资源使用规则发生变化。
|
||||
- `about-page`: About 页面从简单品牌信息扩展为现代化信息面板,并展示前后端版本与匹配状态。
|
||||
- `repository-versioning`: 后端需要通过管理接口暴露构建版本信息,前端需要使用构建注入版本与后端版本进行一致性判断。
|
||||
- `desktop-app`: desktop 模式需要支持新的 PNG 图标静态资源路径,保证版本接口作为 API 路由处理,并同步现有 `Nex` 托盘 tooltip 规范。
|
||||
|
||||
## Impact
|
||||
|
||||
- 前端:`frontend/src/components/AppLayout`、`frontend/src/pages/About`、`frontend/src/api`、`frontend/src/hooks`、`frontend/src/types`、`frontend/index.html`、`frontend/public`、前端测试和 E2E 测试。
|
||||
- 后端:`backend/internal/handler`、`backend/cmd/server`、`backend/cmd/desktop`、后端测试。
|
||||
- 文档与规范:根 `README.md`、`frontend/README.md`、`backend/README.md`、相关 OpenSpec specs。
|
||||
- API:新增 `GET /api/version` 管理接口;不引入新依赖。
|
||||
@@ -0,0 +1,78 @@
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: 关于页面
|
||||
|
||||
前端 SHALL 提供现代化关于页面,使用 TDesign 组件展示项目品牌信息、项目链接、前端版本、后端版本和版本匹配状态。
|
||||
|
||||
#### Scenario: 显示关于页面
|
||||
|
||||
- **WHEN** 用户访问 `/about` 路径
|
||||
- **THEN** 前端 SHALL 显示关于页面
|
||||
- **THEN** 页面 SHALL 展示应用名称 `Nex`
|
||||
- **THEN** 页面 SHALL 展示应用描述 `AI Gateway - 统一的大模型 API 网关`
|
||||
- **THEN** 页面 SHALL 展示项目链接 `https://github.com/nex/gateway`
|
||||
|
||||
#### Scenario: 页面布局
|
||||
|
||||
- **WHEN** 渲染关于页面
|
||||
- **THEN** 页面 SHALL 使用三个独立 TDesign Card 组件分别承载品牌区、版本信息区和链接区
|
||||
- **THEN** 三个 Card SHALL 使用 grid 布局垂直排列
|
||||
- **THEN** 每个 Card SHALL 设置 `bordered={false}` 和 `hoverShadow`
|
||||
- **THEN** Card SHALL 使用 TDesign 组件 props 和 tokens 完成主要视觉效果
|
||||
|
||||
#### Scenario: 品牌卡片
|
||||
|
||||
- **WHEN** 渲染品牌卡片
|
||||
- **THEN** 卡片 SHALL 展示应用图标、应用名称 `Nex` 和产品描述
|
||||
|
||||
#### Scenario: 版本信息卡片
|
||||
|
||||
- **WHEN** 渲染版本信息卡片
|
||||
- **THEN** 版本状态 Tag SHALL 以绝对定位浮动在卡片右上角,不占据内容布局空间
|
||||
- **THEN** 版本状态 Tag SHALL 使用 TDesign Tag 的 `theme`、`variant`、`shape` props
|
||||
- **THEN** 卡片 SHALL 展示前端版本、后端版本、后端提交和后端构建时间
|
||||
|
||||
#### Scenario: 链接卡片
|
||||
|
||||
- **WHEN** 渲染链接卡片
|
||||
- **THEN** 卡片 SHALL 展示项目外部链接
|
||||
|
||||
#### Scenario: 展示前端版本
|
||||
|
||||
- **WHEN** 渲染关于页面
|
||||
- **THEN** 页面 SHALL 显示前端版本号
|
||||
- **THEN** 前端版本号 SHALL 来源于构建注入的 `VITE_APP_VERSION`
|
||||
- **THEN** 当前端版本号缺失时页面 SHALL 显示开发或未知版本状态
|
||||
|
||||
#### Scenario: 展示后端版本
|
||||
|
||||
- **WHEN** 渲染关于页面且后端版本接口请求成功
|
||||
- **THEN** 页面 SHALL 显示后端 `version`
|
||||
- **THEN** 页面 SHALL 显示后端 `commit`
|
||||
- **THEN** 页面 SHALL 显示后端 `build_time`
|
||||
|
||||
#### Scenario: 判断版本一致
|
||||
|
||||
- **WHEN** 前端版本号与后端版本号相同
|
||||
- **THEN** 页面 SHALL 显示版本一致状态
|
||||
- **THEN** 版本状态 SHALL 使用 TDesign Tag 展示成功语义
|
||||
|
||||
#### Scenario: 判断版本不一致
|
||||
|
||||
- **WHEN** 前端版本号与后端版本号不同且两者均为可判断的发布版本
|
||||
- **THEN** 页面 SHALL 显示版本不一致状态
|
||||
- **THEN** 页面 SHALL 展示提示信息说明该状态用于部署诊断
|
||||
- **THEN** 页面 SHALL NOT 阻断用户使用其他功能
|
||||
|
||||
#### Scenario: 后端版本无法判断
|
||||
|
||||
- **WHEN** 后端版本号为 `dev`、`unknown` 或空值
|
||||
- **THEN** 页面 SHALL 显示开发构建或无法判断状态
|
||||
- **THEN** 页面 SHALL NOT 将该状态显示为版本错误
|
||||
|
||||
#### Scenario: 后端版本获取失败
|
||||
|
||||
- **WHEN** 请求后端版本接口失败
|
||||
- **THEN** 页面 SHALL 显示无法获取后端版本的状态
|
||||
- **THEN** 页面 SHALL 保留前端版本信息
|
||||
- **THEN** 页面 SHALL NOT 因版本接口失败而崩溃
|
||||
@@ -0,0 +1,91 @@
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: 系统托盘
|
||||
|
||||
系统 SHALL 提供跨平台系统托盘功能,支持托盘图标和菜单。图标格式 SHALL 根据平台自动选择。
|
||||
|
||||
#### Scenario: 托盘图标显示
|
||||
|
||||
- **WHEN** 桌面应用启动成功
|
||||
- **THEN** 系统根据平台加载正确的图标格式
|
||||
- **AND** 在 Windows 上加载 ICO 格式图标(`assets/icon.ico`)
|
||||
- **AND** 在 macOS 和 Linux 上加载 PNG 格式图标(`assets/icon.png`)
|
||||
- **AND** 托盘图标 tooltip 显示 `Nex`
|
||||
|
||||
#### Scenario: 托盘菜单显示
|
||||
|
||||
- **WHEN** 用户点击托盘图标(左键或右键)
|
||||
- **THEN** 显示托盘菜单
|
||||
- **AND** 菜单包含"打开管理界面"选项
|
||||
- **AND** 菜单包含"状态: 运行中"选项(禁用状态)
|
||||
- **AND** 菜单包含"端口: 9826"选项(禁用状态)
|
||||
- **AND** 菜单包含"退出"选项
|
||||
|
||||
#### Scenario: 打开管理界面
|
||||
|
||||
- **WHEN** 用户点击托盘菜单"打开管理界面"
|
||||
- **THEN** 系统在浏览器中打开 `http://localhost:9826`
|
||||
|
||||
#### Scenario: 浏览器打开失败
|
||||
|
||||
- **WHEN** 系统无法打开浏览器(浏览器未安装等)
|
||||
- **THEN** 托盘菜单仍可正常使用
|
||||
- **AND** 用户可手动访问 `http://localhost:9826`
|
||||
|
||||
#### Scenario: 退出应用
|
||||
|
||||
- **WHEN** 用户点击托盘菜单"退出"
|
||||
- **THEN** 系统优雅关闭后端服务
|
||||
- **AND** 托盘图标消失
|
||||
- **AND** 应用进程退出
|
||||
|
||||
### Requirement: 静态文件服务
|
||||
|
||||
系统 SHALL 通过 Gin 同时服务 API、协议代理和前端静态资源。
|
||||
|
||||
#### Scenario: API 请求路由
|
||||
|
||||
- **WHEN** 请求路径以 `/api/` 或 `/health` 开头
|
||||
- **THEN** 请求由现有业务 handler 处理或返回 API 风格 404
|
||||
|
||||
#### Scenario: 版本接口路由
|
||||
|
||||
- **WHEN** desktop 模式收到 `GET /api/version` 请求
|
||||
- **THEN** 请求 SHALL 由版本信息 handler 处理
|
||||
- **THEN** 响应 SHALL 为 API JSON 响应
|
||||
- **THEN** 请求 SHALL NOT 返回前端 `index.html`
|
||||
|
||||
#### Scenario: 协议代理请求路由
|
||||
|
||||
- **WHEN** 请求路径以 `/openai/` 或 `/anthropic/` 开头
|
||||
- **THEN** 请求 SHALL 被视为协议代理请求或返回 API 风格 404
|
||||
- **THEN** 请求 SHALL NOT 返回前端 `index.html`
|
||||
|
||||
#### Scenario: OpenAI 代理路由
|
||||
|
||||
- **WHEN** desktop 模式收到 `/openai/v1/chat/completions` 请求
|
||||
- **THEN** 请求 SHALL 进入 ProxyHandler
|
||||
- **THEN** ProxyHandler SHALL 获取 clientProtocol 为 `openai`
|
||||
|
||||
#### Scenario: Anthropic 代理路由
|
||||
|
||||
- **WHEN** desktop 模式收到 `/anthropic/v1/messages` 请求
|
||||
- **THEN** 请求 SHALL 进入 ProxyHandler
|
||||
- **THEN** ProxyHandler SHALL 获取 clientProtocol 为 `anthropic`
|
||||
|
||||
#### Scenario: 静态资源路由
|
||||
|
||||
- **WHEN** 请求路径为 `/assets/*`
|
||||
- **THEN** 返回嵌入的前端静态资源文件
|
||||
- **THEN** 请求 SHALL NOT 被协议代理路由处理
|
||||
|
||||
#### Scenario: PNG Favicon 路由
|
||||
|
||||
- **WHEN** 请求路径为 `/icon.png`
|
||||
- **THEN** 返回来源于统一应用图标的 PNG favicon 资源
|
||||
- **THEN** 请求 SHALL NOT 被协议代理路由处理
|
||||
|
||||
#### Scenario: SPA 路由回退
|
||||
|
||||
- **WHEN** 请求路径不匹配任何 API、协议代理或静态资源路由
|
||||
- **THEN** 返回 `index.html`(支持前端 SPA 路由)
|
||||
@@ -0,0 +1,121 @@
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: 样式体系
|
||||
|
||||
前端样式 SHALL 优先使用 TDesign 组件 props,其次使用 TDesign tokens,最后在前两者无法表达所需效果时使用 SCSS 作为补充工具。
|
||||
|
||||
#### Scenario: TDesign 组件 Props 优先
|
||||
|
||||
- **WHEN** 实现组件视觉效果
|
||||
- **THEN** 前端 SHALL 优先使用 TDesign 组件的视觉增强 Props(如 color、trend、hoverShadow、stripe、variant、shape、headerBordered、gutter 等)
|
||||
- **THEN** 前端 SHALL NOT 通过 CSS 类名覆盖组件内部样式
|
||||
|
||||
#### Scenario: TDesign Tokens 作为第二优先级
|
||||
|
||||
- **WHEN** 组件 props 无法完整表达颜色、边框、背景、间距等视觉细节
|
||||
- **THEN** 前端 SHALL 使用 TDesign CSS Token 引用(`var(--td-*)`)表达样式
|
||||
- **THEN** 前端 SHALL NOT 在布局样式中硬编码 `#fff`、`#e7e7e7`、`#999` 等颜色值
|
||||
|
||||
#### Scenario: CSS Variables 主题微调
|
||||
|
||||
- **WHEN** 需要调整全局视觉风格
|
||||
- **THEN** 前端 SHALL 通过 `:root` 中声明 TDesign CSS Variables(`--td-*`)进行覆盖
|
||||
- **THEN** 前端 SHALL NOT 使用 `!important` 或高优先级选择器覆盖组件样式
|
||||
|
||||
#### Scenario: SCSS 兜底使用
|
||||
|
||||
- **WHEN** TDesign 组件 props 和 TDesign tokens 均无法满足布局、响应式或品牌视觉需求
|
||||
- **THEN** 前端 MAY 使用 SCSS 作为补充
|
||||
- **THEN** SCSS SHALL 只承载必要的补充样式
|
||||
- **THEN** 前端 SHALL NOT 使用纯 CSS 文件(*.css)
|
||||
|
||||
### Requirement: 提供响应式布局
|
||||
|
||||
前端 SHALL 使用 TDesign Layout 提供侧边栏导航布局。
|
||||
|
||||
#### Scenario: 桌面布局
|
||||
|
||||
- **WHEN** 在桌面屏幕上查看前端
|
||||
- **THEN** 布局 SHALL 使用 TDesign `Layout.Aside` + `Menu`
|
||||
- **THEN** 侧边栏 SHALL 显示导航菜单,包含图标和文字标签
|
||||
- **THEN** 侧边栏 SHALL 使用固定宽度 232px
|
||||
- **THEN** Menu 组件 SHALL 使用 `logo` prop 显示品牌标识
|
||||
- **THEN** Menu 组件 SHALL 使用 `operations` prop 在底部显示操作区域
|
||||
- **THEN** Menu 组件 SHALL 支持 `collapsed` 折叠功能
|
||||
|
||||
#### Scenario: 侧边栏折叠布局
|
||||
|
||||
- **WHEN** 用户折叠侧边栏
|
||||
- **THEN** 侧边栏 SHALL 使用折叠宽度 64px
|
||||
- **THEN** Menu logo 区域 SHALL 保留应用图标
|
||||
- **THEN** Menu logo 区域 SHALL 隐藏应用名称文字
|
||||
- **THEN** Menu logo 区域 SHALL NOT 显示为空白
|
||||
|
||||
#### Scenario: 页面内容区域
|
||||
|
||||
- **WHEN** 显示页面内容
|
||||
- **THEN** 内容区域 SHALL 在 `Layout.Content` 中渲染
|
||||
- **THEN** 页面之间 SHALL 通过 React Router Outlet 渲染
|
||||
|
||||
#### Scenario: Header 区域
|
||||
|
||||
- **WHEN** 渲染页面 Header
|
||||
- **THEN** Header SHALL 仅显示当前页面标题
|
||||
- **THEN** Header SHALL 不包含导航菜单
|
||||
- **THEN** Header 背景色 SHALL 使用 `var(--td-bg-color-container)` Token
|
||||
- **THEN** Header 底部分割线 SHALL 使用 `var(--td-component-stroke)` Token
|
||||
|
||||
### Requirement: 提供侧边栏导航
|
||||
|
||||
前端 SHALL 使用 TDesign `Layout.Aside` 提供侧边栏导航。
|
||||
|
||||
#### Scenario: 侧边栏内容
|
||||
|
||||
- **WHEN** 渲染侧边栏
|
||||
- **THEN** 侧边栏顶部 SHALL 显示统一应用图标和应用名称 `Nex`
|
||||
- **THEN** 侧边栏 SHALL NOT 显示旧品牌文字 `AI Gateway` 作为应用名称
|
||||
- **THEN** 侧边栏 SHALL 包含导航菜单
|
||||
- **THEN** 导航菜单项 SHALL 包含:供应商管理(ServerIcon 图标)、用量统计(ChartLineIcon 图标)、设置(SettingIcon 图标)、关于(InfoCircleIcon 图标)
|
||||
|
||||
#### Scenario: 侧边栏折叠品牌显示
|
||||
|
||||
- **WHEN** 侧边栏处于折叠状态
|
||||
- **THEN** 侧边栏顶部 SHALL 显示统一应用图标
|
||||
- **THEN** 侧边栏顶部 SHALL 隐藏 `Nex` 文案
|
||||
- **THEN** 侧边栏顶部 SHALL NOT 为空白
|
||||
|
||||
#### Scenario: 导航菜单交互
|
||||
|
||||
- **WHEN** 用户点击导航中的"供应商管理"
|
||||
- **THEN** 前端 SHALL 导航到 `/providers` 并高亮当前菜单项
|
||||
- **WHEN** 用户点击导航中的"用量统计"
|
||||
- **THEN** 前端 SHALL 导航到 `/stats` 并高亮当前菜单项
|
||||
- **WHEN** 用户点击导航中的"设置"
|
||||
- **THEN** 前端 SHALL 导航到 `/settings` 并高亮当前菜单项
|
||||
- **WHEN** 用户点击导航中的"关于"
|
||||
- **THEN** 前端 SHALL 导航到 `/about` 并高亮当前菜单项
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 统一 public 图标资源
|
||||
|
||||
前端 SHALL 使用仓库统一应用图标作为 public favicon 和品牌图标来源。
|
||||
|
||||
#### Scenario: 使用 PNG favicon
|
||||
|
||||
- **WHEN** 前端页面加载 HTML 入口
|
||||
- **THEN** 页面 SHALL 使用 `/icon.png` 作为 PNG favicon 路径
|
||||
- **THEN** `frontend/public/icon.png` SHALL 来源于仓库根目录 `assets/icon.png`
|
||||
- **THEN** 页面 SHALL NOT 引用独立维护的 SVG favicon
|
||||
|
||||
#### Scenario: HTML 标题使用统一应用名称
|
||||
|
||||
- **WHEN** 前端页面加载 HTML 入口
|
||||
- **THEN** 页面标题 SHALL 使用 `Nex` 作为应用名称
|
||||
- **THEN** 页面标题 SHALL NOT 使用旧应用名称 `AI Gateway`
|
||||
|
||||
#### Scenario: 清理未使用 public SVG 图标
|
||||
|
||||
- **WHEN** public 目录中的 SVG 图标资源没有被前端代码、HTML 或 desktop 静态服务引用
|
||||
- **THEN** 前端 SHALL 删除该未使用 SVG 图标资源
|
||||
- **THEN** 前端 SHALL NOT 保留未使用的 `frontend/public/icons.svg`
|
||||
@@ -0,0 +1,54 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 后端运行时版本查询
|
||||
|
||||
系统 SHALL 通过管理接口暴露后端运行时构建版本信息,供前端和用户诊断前后端版本一致性。
|
||||
|
||||
#### Scenario: 查询后端版本信息
|
||||
|
||||
- **WHEN** 客户端请求 `GET /api/version`
|
||||
- **THEN** 后端 SHALL 返回 HTTP 200
|
||||
- **THEN** 响应 JSON SHALL 包含 `version` 字段
|
||||
- **THEN** 响应 JSON SHALL 包含 `commit` 字段
|
||||
- **THEN** 响应 JSON SHALL 包含 `build_time` 字段
|
||||
|
||||
#### Scenario: 版本信息来源于构建注入
|
||||
|
||||
- **WHEN** 后端返回版本信息
|
||||
- **THEN** `version` SHALL 来源于 `buildinfo.Version()`
|
||||
- **THEN** `commit` SHALL 来源于 `buildinfo.Commit()`
|
||||
- **THEN** `build_time` SHALL 来源于 `buildinfo.BuildTime()`
|
||||
- **THEN** 后端 SHALL NOT 在运行时读取仓库 `VERSION` 文件作为接口响应来源
|
||||
|
||||
#### Scenario: 本地开发构建降级值
|
||||
|
||||
- **WHEN** 后端未通过构建参数注入版本元数据
|
||||
- **THEN** 后端版本接口 SHALL 返回 buildinfo 的默认降级值
|
||||
- **THEN** 前端 SHALL 能够展示该降级值而不崩溃
|
||||
|
||||
### Requirement: 前后端版本一致性诊断
|
||||
|
||||
系统 SHALL 支持前端使用自身构建版本和后端运行时版本进行一致性诊断。
|
||||
|
||||
#### Scenario: 前端读取构建版本
|
||||
|
||||
- **WHEN** 前端渲染版本信息
|
||||
- **THEN** 前端 SHALL 使用 `VITE_APP_VERSION` 作为前端版本号
|
||||
- **THEN** `VITE_APP_VERSION` SHALL 继续由版本同步流程保持与 `VERSION` 一致
|
||||
|
||||
#### Scenario: 诊断版本匹配
|
||||
|
||||
- **WHEN** 前端版本号和后端版本号均可判断且完全相同
|
||||
- **THEN** 前端 SHALL 将版本状态判定为一致
|
||||
|
||||
#### Scenario: 诊断版本不匹配
|
||||
|
||||
- **WHEN** 前端版本号和后端版本号均可判断且不相同
|
||||
- **THEN** 前端 SHALL 将版本状态判定为不一致
|
||||
- **THEN** 前端 SHALL 将该状态作为诊断提示展示
|
||||
|
||||
#### Scenario: 诊断版本不可判断
|
||||
|
||||
- **WHEN** 任一版本号为空、`dev` 或 `unknown`
|
||||
- **THEN** 前端 SHALL 将版本状态判定为无法判断
|
||||
- **THEN** 前端 SHALL NOT 将该状态判定为版本不一致
|
||||
@@ -0,0 +1,57 @@
|
||||
## 1. 后端版本接口
|
||||
|
||||
- [x] 1.1 新增后端版本信息 handler,响应 `version`、`commit`、`build_time` 并复用 `buildinfo`
|
||||
- [x] 1.2 在 server 入口注册 `GET /api/version`
|
||||
- [x] 1.3 在 desktop 入口注册 `GET /api/version`
|
||||
- [x] 1.4 为版本 handler 增加单元测试覆盖响应字段和默认降级值
|
||||
- [x] 1.5 为 server 路由增加测试覆盖 `GET /api/version`
|
||||
- [x] 1.6 为 desktop 路由增加测试覆盖 `GET /api/version` 不落入 SPA fallback
|
||||
|
||||
## 2. 前端版本 API 与状态判断
|
||||
|
||||
- [x] 2.1 新增前端版本信息类型定义,包含后端 `version`、`commit`、`buildTime`
|
||||
- [x] 2.2 新增前端版本 API 调用 `GET /api/version`
|
||||
- [x] 2.3 新增 TanStack Query hook 获取后端版本信息
|
||||
- [x] 2.4 集中定义前端 `APP_NAME`、产品描述和 `VITE_APP_VERSION` 降级值
|
||||
- [x] 2.5 实现前后端版本状态判断逻辑,覆盖一致、不一致、无法判断和请求失败
|
||||
- [x] 2.6 为版本 API 和版本状态判断增加前端单元测试
|
||||
|
||||
## 3. 品牌与图标资源
|
||||
|
||||
- [x] 3.1 将侧边栏品牌名称从 `AI Gateway` 替换为 `Nex`
|
||||
- [x] 3.2 使用统一应用图标渲染侧边栏 logo,折叠态保留图标并隐藏文字
|
||||
- [x] 3.3 为侧边栏折叠按钮补充清晰的无障碍标签
|
||||
- [x] 3.4 将根目录 `assets/icon.png` 复制为 `frontend/public/icon.png`
|
||||
- [x] 3.5 将前端 HTML favicon 路径改为 `/icon.png` 并将 HTML title 改为 `Nex`
|
||||
- [x] 3.6 将 desktop 静态文件服务的 `/favicon.svg` 路由替换为 `/icon.png` 路由
|
||||
- [x] 3.7 删除未使用的 `frontend/public/icons.svg` 和旧 SVG favicon 资源
|
||||
- [x] 3.8 全文确认不存在未处理的 `icons.svg`、`favicon.svg` 引用
|
||||
- [x] 3.9 更新 AppLayout 组件测试覆盖展开态 `Nex`、折叠态图标和 About 菜单项
|
||||
- [x] 3.10 更新导航 E2E 中旧 `AI Gateway` 品牌断言为 `Nex`
|
||||
|
||||
## 4. About 页面改造
|
||||
|
||||
- [x] 4.1 重构 About 页面为品牌卡片、版本信息卡片和链接卡片三卡布局
|
||||
- [x] 4.2 使用 TDesign Card、Tag、Descriptions、Alert、Row/Col 等组件 props 完成主要视觉结构
|
||||
- [x] 4.3 在 About 页面展示前端版本、后端版本、commit 和 build_time
|
||||
- [x] 4.4 在 About 页面展示版本一致、不一致、无法判断和请求失败状态
|
||||
- [x] 4.5 确保版本不一致或接口失败时 About 页面不崩溃且不阻断其他功能
|
||||
- [x] 4.6 为 About 页面增加组件测试覆盖布局、版本展示和所有版本状态
|
||||
- [x] 4.7 为 About 页面补充必要的 E2E 导航与版本区域可见性测试
|
||||
|
||||
## 5. 文档同步
|
||||
|
||||
- [x] 5.1 更新根 README 的管理接口列表,加入 `GET /api/version`
|
||||
- [x] 5.2 更新根 README 的前端样式技术栈说明,体现 TDesign props、TDesign tokens、SCSS 优先级
|
||||
- [x] 5.3 更新 backend README 的管理接口文档,说明版本响应字段来源
|
||||
- [x] 5.4 更新 frontend README 的环境变量说明,加入 `VITE_APP_VERSION`
|
||||
- [x] 5.5 更新 frontend README 的样式优先级为 TDesign props、TDesign tokens、SCSS
|
||||
- [x] 5.6 更新 frontend README 的项目结构、About 页面说明和 public 图标来源说明
|
||||
- [x] 5.7 更新 desktop 相关文档说明 PNG favicon、`/icon.png` 静态路由和 API 版本接口路由
|
||||
|
||||
## 6. 验证
|
||||
|
||||
- [x] 6.1 运行后端测试,确保 handler、server 和 desktop 路由测试通过
|
||||
- [x] 6.2 运行前端测试,确保 API、hook、AppLayout 和 About 页面测试通过
|
||||
- [x] 6.3 运行前端检查和构建,确保 Bun/Vite 构建能加载 PNG favicon
|
||||
- [x] 6.4 运行 OpenSpec 校验,确保 proposal、design、specs 和 tasks 状态可实施
|
||||
@@ -8,7 +8,7 @@ context: |
|
||||
- 新增代码优先复用已有组件、工具、依赖库,不引入新依赖
|
||||
- 新增的逻辑必须编写完善的测试,并保证测试的正确性,不允许跳过任何测试
|
||||
- backend是使用go开发的后端,阅读backend/README.md了解项目架构,优先使用公共组件实现功能逻辑(优先级:官方库>主流三方库>项目公共工具>自行实现)
|
||||
- frontend是基于bun+vite+typescript开发的前端,使用bun作为唯一包管理器,严禁使用pnpm、npm
|
||||
- frontend是基于bun+vite+typescript开发的前端,使用bun作为唯一包管理器,严禁使用pnpm、npm,使用bunx运行工具,严禁使用npx、pnpx
|
||||
- Git提交: 仅中文; 格式"类型: 简短描述", 类型: feat/fix/refactor/docs/style/test/chore; 多行描述空行后写详细说明
|
||||
- 禁止创建git操作task
|
||||
- 积极使用subagents精心设计并行任务,节省上下文空间,加速任务执行
|
||||
|
||||
@@ -2,25 +2,83 @@
|
||||
|
||||
## Purpose
|
||||
|
||||
TBD - 提供关于页面展示项目品牌信息
|
||||
TBD - 提供关于页面展示项目品牌信息、版本信息和外部链接
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: 关于页面
|
||||
|
||||
前端 SHALL 提供关于页面,使用 TDesign Card 组件居中展示项目品牌信息(应用名称、描述、项目链接)。
|
||||
前端 SHALL 提供现代化关于页面,使用 TDesign 组件展示项目品牌信息、项目链接、前端版本、后端版本和版本匹配状态。
|
||||
|
||||
#### Scenario: 显示关于页面
|
||||
|
||||
- **WHEN** 用户访问 `/about` 路径
|
||||
- **THEN** 前端 SHALL 显示关于页面
|
||||
- **THEN** 页面 SHALL 展示应用名称"Nex"
|
||||
- **THEN** 页面 SHALL 展示应用描述"AI Gateway - 统一的大模型 API 网关"
|
||||
- **THEN** 页面 SHALL 展示项目链接"https://github.com/nex/gateway"
|
||||
- **THEN** 页面 SHALL 展示应用名称 `Nex`
|
||||
- **THEN** 页面 SHALL 展示应用描述 `AI Gateway - 统一的大模型 API 网关`
|
||||
- **THEN** 页面 SHALL 展示项目链接 `https://github.com/nex/gateway`
|
||||
|
||||
#### Scenario: 页面布局
|
||||
|
||||
- **WHEN** 渲染关于页面
|
||||
- **THEN** 页面 SHALL 使用 TDesign Card 组件作为容器
|
||||
- **THEN** Card SHALL 设置 `bordered={false}`
|
||||
- **THEN** 内容 SHALL 居中展示
|
||||
- **THEN** 页面 SHALL 使用三个独立 TDesign Card 组件分别承载品牌区、版本信息区和链接区
|
||||
- **THEN** 三个 Card SHALL 使用 grid 布局垂直排列
|
||||
- **THEN** 每个 Card SHALL 设置 `bordered={false}` 和 `hoverShadow`
|
||||
- **THEN** Card SHALL 使用 TDesign 组件 props 和 tokens 完成主要视觉效果
|
||||
|
||||
#### Scenario: 品牌卡片
|
||||
|
||||
- **WHEN** 渲染品牌卡片
|
||||
- **THEN** 卡片 SHALL 展示应用图标、应用名称 `Nex` 和产品描述
|
||||
|
||||
#### Scenario: 版本信息卡片
|
||||
|
||||
- **WHEN** 渲染版本信息卡片
|
||||
- **THEN** 版本状态 Tag SHALL 以绝对定位浮动在卡片右上角,不占据内容布局空间
|
||||
- **THEN** 版本状态 Tag SHALL 使用 TDesign Tag 的 `theme`、`variant`、`shape` props
|
||||
- **THEN** 卡片 SHALL 展示前端版本、后端版本、后端提交和后端构建时间
|
||||
|
||||
#### Scenario: 链接卡片
|
||||
|
||||
- **WHEN** 渲染链接卡片
|
||||
- **THEN** 卡片 SHALL 展示项目外部链接
|
||||
|
||||
#### Scenario: 展示前端版本
|
||||
|
||||
- **WHEN** 渲染关于页面
|
||||
- **THEN** 页面 SHALL 显示前端版本号
|
||||
- **THEN** 前端版本号 SHALL 来源于构建注入的 `VITE_APP_VERSION`
|
||||
- **THEN** 当前端版本号缺失时页面 SHALL 显示开发或未知版本状态
|
||||
|
||||
#### Scenario: 展示后端版本
|
||||
|
||||
- **WHEN** 渲染关于页面且后端版本接口请求成功
|
||||
- **THEN** 页面 SHALL 显示后端 `version`
|
||||
- **THEN** 页面 SHALL 显示后端 `commit`
|
||||
- **THEN** 页面 SHALL 显示后端 `build_time`
|
||||
|
||||
#### Scenario: 判断版本一致
|
||||
|
||||
- **WHEN** 前端版本号与后端版本号相同
|
||||
- **THEN** 页面 SHALL 显示版本一致状态
|
||||
- **THEN** 版本状态 SHALL 使用 TDesign Tag 展示成功语义
|
||||
|
||||
#### Scenario: 判断版本不一致
|
||||
|
||||
- **WHEN** 前端版本号与后端版本号不同且两者均为可判断的发布版本
|
||||
- **THEN** 页面 SHALL 显示版本不一致状态
|
||||
- **THEN** 页面 SHALL 展示提示信息说明该状态用于部署诊断
|
||||
- **THEN** 页面 SHALL NOT 阻断用户使用其他功能
|
||||
|
||||
#### Scenario: 后端版本无法判断
|
||||
|
||||
- **WHEN** 后端版本号为 `dev`、`unknown` 或空值
|
||||
- **THEN** 页面 SHALL 显示开发构建或无法判断状态
|
||||
- **THEN** 页面 SHALL NOT 将该状态显示为版本错误
|
||||
|
||||
#### Scenario: 后端版本获取失败
|
||||
|
||||
- **WHEN** 请求后端版本接口失败
|
||||
- **THEN** 页面 SHALL 显示无法获取后端版本的状态
|
||||
- **THEN** 页面 SHALL 保留前端版本信息
|
||||
- **THEN** 页面 SHALL NOT 因版本接口失败而崩溃
|
||||
|
||||
@@ -42,7 +42,7 @@ TBD - 提供跨平台桌面应用支持,将后端服务与前端静态资源
|
||||
- **THEN** 系统根据平台加载正确的图标格式
|
||||
- **AND** 在 Windows 上加载 ICO 格式图标(`assets/icon.ico`)
|
||||
- **AND** 在 macOS 和 Linux 上加载 PNG 格式图标(`assets/icon.png`)
|
||||
- **AND** 托盘图标 tooltip 显示"AI Gateway"
|
||||
- **AND** 托盘图标 tooltip 显示 `Nex`
|
||||
|
||||
#### Scenario: 托盘菜单显示
|
||||
|
||||
@@ -80,6 +80,13 @@ TBD - 提供跨平台桌面应用支持,将后端服务与前端静态资源
|
||||
- **WHEN** 请求路径以 `/api/` 或 `/health` 开头
|
||||
- **THEN** 请求由现有业务 handler 处理或返回 API 风格 404
|
||||
|
||||
#### Scenario: 版本接口路由
|
||||
|
||||
- **WHEN** desktop 模式收到 `GET /api/version` 请求
|
||||
- **THEN** 请求 SHALL 由版本信息 handler 处理
|
||||
- **THEN** 响应 SHALL 为 API JSON 响应
|
||||
- **THEN** 请求 SHALL NOT 返回前端 `index.html`
|
||||
|
||||
#### Scenario: 协议代理请求路由
|
||||
|
||||
- **WHEN** 请求路径以 `/openai/` 或 `/anthropic/` 开头
|
||||
@@ -104,10 +111,10 @@ TBD - 提供跨平台桌面应用支持,将后端服务与前端静态资源
|
||||
- **THEN** 返回嵌入的前端静态资源文件
|
||||
- **THEN** 请求 SHALL NOT 被协议代理路由处理
|
||||
|
||||
#### Scenario: Favicon 路由
|
||||
#### Scenario: PNG Favicon 路由
|
||||
|
||||
- **WHEN** 请求路径为 `/favicon.svg`
|
||||
- **THEN** 返回嵌入的前端 favicon 资源
|
||||
- **WHEN** 请求路径为 `/icon.png`
|
||||
- **THEN** 返回来源于统一应用图标的 PNG favicon 资源
|
||||
- **THEN** 请求 SHALL NOT 被协议代理路由处理
|
||||
|
||||
#### Scenario: SPA 路由回退
|
||||
|
||||
@@ -8,31 +8,31 @@ TBD - 提供供应商、模型配置和用量统计的前端管理界面
|
||||
|
||||
### Requirement: 样式体系
|
||||
|
||||
前端样式 SHALL 优先使用 TDesign 样式体系,SCSS 作为补充工具。
|
||||
前端样式 SHALL 优先使用 TDesign 组件 props,其次使用 TDesign tokens,最后在前两者无法表达所需效果时使用 SCSS 作为补充工具。
|
||||
|
||||
#### Scenario: TDesign 组件 Props 优先
|
||||
|
||||
- **WHEN** 实现组件视觉效果
|
||||
- **THEN** 前端 SHALL 优先使用 TDesign 组件的视觉增强 Props(如 color、trend、hoverShadow、stripe、variant、shape 等)
|
||||
- **THEN** 前端 SHALL 优先使用 TDesign 组件的视觉增强 Props(如 color、trend、hoverShadow、stripe、variant、shape、headerBordered、gutter 等)
|
||||
- **THEN** 前端 SHALL NOT 通过 CSS 类名覆盖组件内部样式
|
||||
|
||||
#### Scenario: TDesign Tokens 作为第二优先级
|
||||
|
||||
- **WHEN** 组件 props 无法完整表达颜色、边框、背景、间距等视觉细节
|
||||
- **THEN** 前端 SHALL 使用 TDesign CSS Token 引用(`var(--td-*)`)表达样式
|
||||
- **THEN** 前端 SHALL NOT 在布局样式中硬编码 `#fff`、`#e7e7e7`、`#999` 等颜色值
|
||||
|
||||
#### Scenario: CSS Variables 主题微调
|
||||
|
||||
- **WHEN** 需要调整全局视觉风格
|
||||
- **THEN** 前端 SHALL 通过 \`:root\` 中声明 TDesign CSS Variables(\`--td-*\`)进行覆盖
|
||||
- **THEN** 前端 SHALL NOT 使用 \`!important\` 或高优先级选择器覆盖组件样式
|
||||
- **THEN** 前端 SHALL 通过 `:root` 中声明 TDesign CSS Variables(`--td-*`)进行覆盖
|
||||
- **THEN** 前端 SHALL NOT 使用 `!important` 或高优先级选择器覆盖组件样式
|
||||
|
||||
#### Scenario: 布局样式 Token 化
|
||||
#### Scenario: SCSS 兜底使用
|
||||
|
||||
- **WHEN** 编写布局级 inline style
|
||||
- **THEN** 前端 SHALL 使用 TDesign CSS Token 引用(\`var(--td-*)\`)替代硬编码颜色值
|
||||
- **THEN** 前端 SHALL NOT 在布局样式中硬编码 \`#fff\`、\`#e7e7e7\`、\`#999\` 等颜色值
|
||||
|
||||
#### Scenario: SCSS 补充使用
|
||||
|
||||
- **WHEN** TDesign 样式体系无法满足需求
|
||||
- **WHEN** TDesign 组件 props 和 TDesign tokens 均无法满足布局、响应式或品牌视觉需求
|
||||
- **THEN** 前端 MAY 使用 SCSS 作为补充
|
||||
- **THEN** SCSS 文件 SHALL 仅用于 \`:root\` 级别的 CSS Variables 声明和全局 reset
|
||||
- **THEN** SCSS SHALL 只承载必要的补充样式
|
||||
- **THEN** 前端 SHALL NOT 使用纯 CSS 文件(*.css)
|
||||
|
||||
|
||||
@@ -231,12 +231,20 @@ TBD - 提供供应商、模型配置和用量统计的前端管理界面
|
||||
#### Scenario: 桌面布局
|
||||
|
||||
- **WHEN** 在桌面屏幕上查看前端
|
||||
- **THEN** 布局 SHALL 使用 TDesign \`Layout.Aside\` + \`Menu\`
|
||||
- **THEN** 布局 SHALL 使用 TDesign `Layout.Aside` + `Menu`
|
||||
- **THEN** 侧边栏 SHALL 显示导航菜单,包含图标和文字标签
|
||||
- **THEN** 侧边栏 SHALL 使用固定宽度 232px
|
||||
- **THEN** Menu 组件 SHALL 使用 \`logo\` prop 显示品牌标识
|
||||
- **THEN** Menu 组件 SHALL 使用 \`operations\` prop 在底部显示操作区域
|
||||
- **THEN** Menu 组件 SHALL 支持 \`collapsed\` 折叠功能
|
||||
- **THEN** Menu 组件 SHALL 使用 `logo` prop 显示品牌标识
|
||||
- **THEN** Menu 组件 SHALL 使用 `operations` prop 在底部显示操作区域
|
||||
- **THEN** Menu 组件 SHALL 支持 `collapsed` 折叠功能
|
||||
|
||||
#### Scenario: 侧边栏折叠布局
|
||||
|
||||
- **WHEN** 用户折叠侧边栏
|
||||
- **THEN** 侧边栏 SHALL 使用折叠宽度 64px
|
||||
- **THEN** Menu logo 区域 SHALL 保留应用图标
|
||||
- **THEN** Menu logo 区域 SHALL 隐藏应用名称文字
|
||||
- **THEN** Menu logo 区域 SHALL NOT 显示为空白
|
||||
|
||||
#### Scenario: 页面内容区域
|
||||
|
||||
@@ -402,21 +410,29 @@ TBD - 提供供应商、模型配置和用量统计的前端管理界面
|
||||
|
||||
### Requirement: 提供侧边栏导航
|
||||
|
||||
前端 SHALL 使用 TDesign \`Layout.Aside\` 提供侧边栏导航。
|
||||
前端 SHALL 使用 TDesign `Layout.Aside` 提供侧边栏导航。
|
||||
|
||||
#### Scenario: 侧边栏内容
|
||||
|
||||
- **WHEN** 渲染侧边栏
|
||||
- **THEN** 侧边栏顶部 SHALL 显示应用名称/Logo
|
||||
- **THEN** 侧边栏顶部 SHALL 显示统一应用图标和应用名称 `Nex`
|
||||
- **THEN** 侧边栏 SHALL NOT 显示旧品牌文字 `AI Gateway` 作为应用名称
|
||||
- **THEN** 侧边栏 SHALL 包含导航菜单
|
||||
- **THEN** 导航菜单项 SHALL 包含:供应商管理(ServerIcon 图标)、用量统计(ChartLineIcon 图标)、设置(SettingIcon 图标)、关于(InfoCircleIcon 图标)
|
||||
|
||||
#### Scenario: 侧边栏折叠品牌显示
|
||||
|
||||
- **WHEN** 侧边栏处于折叠状态
|
||||
- **THEN** 侧边栏顶部 SHALL 显示统一应用图标
|
||||
- **THEN** 侧边栏顶部 SHALL 隐藏 `Nex` 文案
|
||||
- **THEN** 侧边栏顶部 SHALL NOT 为空白
|
||||
|
||||
#### Scenario: 导航菜单交互
|
||||
|
||||
- **WHEN** 用户点击导航中的"供应商管理"
|
||||
- **THEN** 前端 SHALL 导航到 \`/providers\` 并高亮当前菜单项
|
||||
- **THEN** 前端 SHALL 导航到 `/providers` 并高亮当前菜单项
|
||||
- **WHEN** 用户点击导航中的"用量统计"
|
||||
- **THEN** 前端 SHALL 导航到 \`/stats\` 并高亮当前菜单项
|
||||
- **THEN** 前端 SHALL 导航到 `/stats` 并高亮当前菜单项
|
||||
- **WHEN** 用户点击导航中的"设置"
|
||||
- **THEN** 前端 SHALL 导航到 `/settings` 并高亮当前菜单项
|
||||
- **WHEN** 用户点击导航中的"关于"
|
||||
@@ -583,3 +599,26 @@ TBD - 提供供应商、模型配置和用量统计的前端管理界面
|
||||
- **THEN** 前端 SHALL 显示全局错误提示
|
||||
- **THEN** 错误消息 SHALL 具有描述性
|
||||
|
||||
### Requirement: 统一 public 图标资源
|
||||
|
||||
前端 SHALL 使用仓库统一应用图标作为 public favicon 和品牌图标来源。
|
||||
|
||||
#### Scenario: 使用 PNG favicon
|
||||
|
||||
- **WHEN** 前端页面加载 HTML 入口
|
||||
- **THEN** 页面 SHALL 使用 `/icon.png` 作为 PNG favicon 路径
|
||||
- **THEN** `frontend/public/icon.png` SHALL 来源于仓库根目录 `assets/icon.png`
|
||||
- **THEN** 页面 SHALL NOT 引用独立维护的 SVG favicon
|
||||
|
||||
#### Scenario: HTML 标题使用统一应用名称
|
||||
|
||||
- **WHEN** 前端页面加载 HTML 入口
|
||||
- **THEN** 页面标题 SHALL 使用 `Nex` 作为应用名称
|
||||
- **THEN** 页面标题 SHALL NOT 使用旧应用名称 `AI Gateway`
|
||||
|
||||
#### Scenario: 清理未使用 public SVG 图标
|
||||
|
||||
- **WHEN** public 目录中的 SVG 图标资源没有被前端代码、HTML 或 desktop 静态服务引用
|
||||
- **THEN** 前端 SHALL 删除该未使用 SVG 图标资源
|
||||
- **THEN** 前端 SHALL NOT 保留未使用的 `frontend/public/icons.svg`
|
||||
|
||||
|
||||
@@ -66,3 +66,56 @@
|
||||
- **WHEN** 执行前端生产构建
|
||||
- **THEN** 构建流程 SHALL 注入 `VITE_APP_VERSION`
|
||||
- **AND** 该值 SHALL 等于 `VERSION` 中的版本号
|
||||
|
||||
### Requirement: 后端运行时版本查询
|
||||
|
||||
系统 SHALL 通过管理接口暴露后端运行时构建版本信息,供前端和用户诊断前后端版本一致性。
|
||||
|
||||
#### Scenario: 查询后端版本信息
|
||||
|
||||
- **WHEN** 客户端请求 `GET /api/version`
|
||||
- **THEN** 后端 SHALL 返回 HTTP 200
|
||||
- **THEN** 响应 JSON SHALL 包含 `version` 字段
|
||||
- **THEN** 响应 JSON SHALL 包含 `commit` 字段
|
||||
- **THEN** 响应 JSON SHALL 包含 `build_time` 字段
|
||||
|
||||
#### Scenario: 版本信息来源于构建注入
|
||||
|
||||
- **WHEN** 后端返回版本信息
|
||||
- **THEN** `version` SHALL 来源于 `buildinfo.Version()`
|
||||
- **THEN** `commit` SHALL 来源于 `buildinfo.Commit()`
|
||||
- **THEN** `build_time` SHALL 来源于 `buildinfo.BuildTime()`
|
||||
- **THEN** 后端 SHALL NOT 在运行时读取仓库 `VERSION` 文件作为接口响应来源
|
||||
|
||||
#### Scenario: 本地开发构建降级值
|
||||
|
||||
- **WHEN** 后端未通过构建参数注入版本元数据
|
||||
- **THEN** 后端版本接口 SHALL 返回 buildinfo 的默认降级值
|
||||
- **THEN** 前端 SHALL 能够展示该降级值而不崩溃
|
||||
|
||||
### Requirement: 前后端版本一致性诊断
|
||||
|
||||
系统 SHALL 支持前端使用自身构建版本和后端运行时版本进行一致性诊断。
|
||||
|
||||
#### Scenario: 前端读取构建版本
|
||||
|
||||
- **WHEN** 前端渲染版本信息
|
||||
- **THEN** 前端 SHALL 使用 `VITE_APP_VERSION` 作为前端版本号
|
||||
- **THEN** `VITE_APP_VERSION` SHALL 继续由版本同步流程保持与 `VERSION` 一致
|
||||
|
||||
#### Scenario: 诊断版本匹配
|
||||
|
||||
- **WHEN** 前端版本号和后端版本号均可判断且完全相同
|
||||
- **THEN** 前端 SHALL 将版本状态判定为一致
|
||||
|
||||
#### Scenario: 诊断版本不匹配
|
||||
|
||||
- **WHEN** 前端版本号和后端版本号均可判断且不相同
|
||||
- **THEN** 前端 SHALL 将版本状态判定为不一致
|
||||
- **THEN** 前端 SHALL 将该状态作为诊断提示展示
|
||||
|
||||
#### Scenario: 诊断版本不可判断
|
||||
|
||||
- **WHEN** 任一版本号为空、`dev` 或 `unknown`
|
||||
- **THEN** 前端 SHALL 将版本状态判定为无法判断
|
||||
- **THEN** 前端 SHALL NOT 将该状态判定为版本不一致
|
||||
|
||||
Reference in New Issue
Block a user