update:增加文档模式
This commit is contained in:
141
design/plans/2026-04-14-tool-display-version-none-mode-plan.md
Normal file
141
design/plans/2026-04-14-tool-display-version-none-mode-plan.md
Normal file
@@ -0,0 +1,141 @@
|
||||
# 工具展示版本与无访问模式实施计划
|
||||
|
||||
**目标**:为工具站新增 `Tool.versionOverride` 与 `AccessMode.none`,由服务端统一计算 `displayVersion`,并让后台工具管理、公开列表、公开详情和 launch 语义全部兼容新模型。
|
||||
|
||||
**架构**:采用“数据契约先行”的增量改造。先在 Prisma 和服务端建立稳定的数据模型与返回字段,再分别更新公开站和管理端消费 `displayVersion`,最后用单元测试与 e2e 回归把 `none` 模式的行为闭合。
|
||||
|
||||
**技术栈**:Prisma、SQLite、NestJS、Jest、Supertest、Vue 3、Element Plus、Vitest
|
||||
|
||||
---
|
||||
|
||||
## 文件结构
|
||||
|
||||
### 新建文件
|
||||
|
||||
- `server/prisma/migrations/*_tool-display-version-none-mode/migration.sql` - 由 Prisma 生成 `AccessMode.none` 和 `Tool.versionOverride` 的迁移脚本。注释需求:低。复杂度:低。
|
||||
- `server/src/modules/admin-tools/admin-tools.service.spec.ts` - 覆盖后台工具列表/详情的 `displayVersion` 映射、`versionOverride` 归一化和 `none` 模式输入。注释需求:低。复杂度:中。
|
||||
- `server/src/modules/access/access.service.spec.ts` - 覆盖 `none` 模式 launch 被拒绝、`web/download` 既有行为不回归。注释需求:低。复杂度:中。
|
||||
- `server/src/modules/admin-overview/admin-overview.service.spec.ts` - 覆盖概览统计对 `none` 模式的计数与文案数据。注释需求:低。复杂度:中。
|
||||
- `server/test/tool-launch-none.e2e-spec.ts` - 覆盖公开 launch 接口对 `none` 模式返回 `409`。注释需求:低。复杂度:中。
|
||||
- `client/src/admin/components/ToolFormDialog.spec.js` - 覆盖工具表单展示版本输入项和 `none` 模式可见性。注释需求:低。复杂度:中。
|
||||
- `client/src/admin/components/AccessModeDialog.spec.js` - 覆盖快速切换访问方式时 `none` 模式隐藏 URL 输入。注释需求:低。复杂度:中。
|
||||
- `client/src/admin/components/AdminToolsSection.spec.js` - 覆盖后台工具列表版本列和 `none` 模式标签渲染。注释需求:低。复杂度:中。
|
||||
- `client/src/admin/components/AdminOverviewSection.spec.js` - 覆盖后台概览的 `none` 模式统计展示。注释需求:低。复杂度:中。
|
||||
|
||||
### 修改文件
|
||||
|
||||
- `server/prisma/schema.prisma` - 为 `AccessMode` 增加 `none`,为 `Tool` 增加 `versionOverride`。注释需求:低。复杂度:中。
|
||||
- `server/prisma/seed.ts` - 为种子工具补充展示版本样例,并加入至少一个 `none` 模式工具。注释需求:低。复杂度:中。
|
||||
- `server/src/modules/tools/tools.service.ts` - 公开列表和详情统一输出 `displayVersion`,保留下载工具 `latestVersion` 兼容字段。注释需求:中,新增版本解析 helper 需说明回退顺序。复杂度:高。
|
||||
- `server/src/modules/tools/tools.service.spec.ts` - 增加 `displayVersion` 与 `none` 模式回归断言。注释需求:低。复杂度:中。
|
||||
- `server/test/tools-detail.e2e-spec.ts` - 扩展详情接口断言,验证 `displayVersion` 和 `accessMode=none` 可被公开读取。注释需求:低。复杂度:中。
|
||||
- `server/src/modules/admin-tools/dto/create-tool.dto.ts` - 接收 `versionOverride`,并让 `accessMode` 接受 `none`。注释需求:低。复杂度:中。
|
||||
- `server/src/modules/admin-tools/dto/update-tool.dto.ts` - 继承新增展示版本字段。注释需求:低。复杂度:低。
|
||||
- `server/src/modules/admin-tools/dto/update-access-mode.dto.ts` - 允许切换到 `none`,并明确 URL 仅在 `web/download` 下有意义。注释需求:低。复杂度:中。
|
||||
- `server/src/modules/admin-tools/admin-tools.service.ts` - 统一归一化 `versionOverride`,后台接口输出 `displayVersion` 和 `versionOverride`。注释需求:中,新增映射 helper 需要解释字段语义。复杂度:高。
|
||||
- `server/src/modules/access/access.service.ts` - 对 `none` 模式 launch 返回冲突错误,不生成 ticket,也不返回 actionUrl。注释需求:中。复杂度:中。
|
||||
- `server/src/modules/admin-overview/admin-overview.service.ts` - 新增 `noneToolTotal` 统计,并让模式分布闭合。注释需求:低。复杂度:中。
|
||||
- `client/src/App.vue` - 首页卡片改为展示 `displayVersion`,`none` 模式主按钮跳详情并显示“查看详情”。注释需求:低。复杂度:中。
|
||||
- `client/src/App.spec.js` - 增加 `displayVersion` 与 `none` 模式交互回归。注释需求:低。复杂度:中。
|
||||
- `client/src/pages/ToolDetailPage.vue` - 详情页展示 `displayVersion`,`none` 模式不渲染主操作按钮。注释需求:低。复杂度:中。
|
||||
- `client/src/pages/ToolDetailPage.spec.js` - 增加 `displayVersion` 渲染和 `none` 模式无主按钮断言。注释需求:低。复杂度:中。
|
||||
- `client/src/admin/AdminApp.vue` - 表单状态新增 `versionOverride`,访问方式选项新增“无”,构造 payload 和标签样式兼容 `none`。注释需求:中,构造 payload 的归一化逻辑需要简短说明。复杂度:高。
|
||||
- `client/src/admin/components/ToolFormDialog.vue` - 新增展示版本输入项,按模式调整文案。注释需求:低。复杂度:中。
|
||||
- `client/src/admin/components/AccessModeDialog.vue` - `none` 模式隐藏 URL 输入和无意义的新标签页控制。注释需求:低。复杂度:中。
|
||||
- `client/src/admin/components/AdminToolsSection.vue` - 增加版本列并渲染 `none` 标签文案。注释需求:低。复杂度:中。
|
||||
- `client/src/admin/components/AdminOverviewSection.vue` - 新增或调整模式分布项,显示“无”模式。注释需求:低。复杂度:中。
|
||||
- `client/src/admin/stores/console.js` - 为概览 summary 默认值补充 `noneToolTotal`。注释需求:低。复杂度:低。
|
||||
|
||||
### 测试文件
|
||||
|
||||
- `server/src/modules/tools/tools.service.spec.ts` - 公开服务的 `displayVersion` 计算与详情映射回归。
|
||||
- `server/src/modules/admin-tools/admin-tools.service.spec.ts` - 后台服务的版本覆盖与访问方式回归。
|
||||
- `server/src/modules/access/access.service.spec.ts` - `none` 模式 launch 约束回归。
|
||||
- `server/src/modules/admin-overview/admin-overview.service.spec.ts` - 概览模式分布回归。
|
||||
- `server/test/tools-detail.e2e-spec.ts` - 公开详情接口契约回归。
|
||||
- `server/test/tool-launch-none.e2e-spec.ts` - 公开 launch 接口 `none` 模式回归。
|
||||
- `client/src/App.spec.js` - 首页卡片版本展示和 `none` 模式路由回归。
|
||||
- `client/src/pages/ToolDetailPage.spec.js` - 详情页版本展示和无主按钮回归。
|
||||
- `client/src/admin/components/ToolFormDialog.spec.js` - 后台工具表单版本输入与 `none` 模式渲染回归。
|
||||
- `client/src/admin/components/AccessModeDialog.spec.js` - 后台访问方式对话框 `none` 模式回归。
|
||||
- `client/src/admin/components/AdminToolsSection.spec.js` - 后台列表版本列和模式标签回归。
|
||||
- `client/src/admin/components/AdminOverviewSection.spec.js` - 后台概览模式分布回归。
|
||||
|
||||
---
|
||||
|
||||
## 任务列表
|
||||
|
||||
### 任务 1:先锁定 Prisma 契约和公开接口版本映射
|
||||
|
||||
**文件**:
|
||||
- 修改:`server/prisma/schema.prisma`
|
||||
- 修改:`server/src/modules/tools/tools.service.ts`
|
||||
- 修改:`server/src/modules/tools/tools.service.spec.ts`
|
||||
- 修改:`server/test/tools-detail.e2e-spec.ts`
|
||||
- 创建:`server/prisma/migrations/*_tool-display-version-none-mode/migration.sql`
|
||||
|
||||
- [ ] **步骤 1**:在 `server/src/modules/tools/tools.service.spec.ts` 先补 3 个失败测试,分别覆盖“下载工具无覆盖版本时回退 `latestArtifact.version`”“网页工具使用 `versionOverride`”“`none` 模式详情返回 `displayVersion` 和 `accessMode=none`”。
|
||||
- [ ] **步骤 2**:在 `server/test/tools-detail.e2e-spec.ts` 先补失败断言,执行 `cd server && npm run test -- src/modules/tools/tools.service.spec.ts` 与 `cd server && npm run test:e2e -- test/tools-detail.e2e-spec.ts`,预期出现缺少 `displayVersion`、`none` 枚举未生效或断言失败。
|
||||
- [ ] **步骤 3**:更新 `server/prisma/schema.prisma`,执行 `cd server && npx prisma migrate dev --name tool-display-version-none-mode` 与 `cd server && npm run prisma:generate`,然后在 `server/src/modules/tools/tools.service.ts` 加入统一的 `displayVersion` 解析 helper,并保留下载工具 `latestVersion` 兼容字段。
|
||||
- [ ] **步骤 4**:重新执行 `cd server && npm run test -- src/modules/tools/tools.service.spec.ts` 与 `cd server && npm run test:e2e -- test/tools-detail.e2e-spec.ts`,预期 Jest 与 e2e 通过,公开接口开始稳定返回 `displayVersion`。
|
||||
|
||||
### 任务 2:补齐后台工具服务对 `versionOverride` 和 `none` 的支持
|
||||
|
||||
**文件**:
|
||||
- 修改:`server/prisma/seed.ts`
|
||||
- 修改:`server/src/modules/admin-tools/dto/create-tool.dto.ts`
|
||||
- 修改:`server/src/modules/admin-tools/dto/update-tool.dto.ts`
|
||||
- 修改:`server/src/modules/admin-tools/dto/update-access-mode.dto.ts`
|
||||
- 修改:`server/src/modules/admin-tools/admin-tools.service.ts`
|
||||
- 创建:`server/src/modules/admin-tools/admin-tools.service.spec.ts`
|
||||
|
||||
- [ ] **步骤 1**:创建 `server/src/modules/admin-tools/admin-tools.service.spec.ts`,先写失败测试,覆盖“后台列表/详情同时返回 `displayVersion` 和 `versionOverride`”“下载工具覆盖版本优先于安装包版本”“`none` 模式允许空 `openUrl` 保存”。
|
||||
- [ ] **步骤 2**:执行 `cd server && npm run test -- src/modules/admin-tools/admin-tools.service.spec.ts`,预期因 DTO、服务映射或归一化逻辑缺失而失败。
|
||||
- [ ] **步骤 3**:更新后台 DTO 与 `server/src/modules/admin-tools/admin-tools.service.ts`,为 `versionOverride` 做 trim/null 归一化、为 `none` 模式放开 URL 约束,并在 `server/prisma/seed.ts` 加入带版本覆盖值的 `web`/`none` 示例工具,便于本地人工验证。
|
||||
- [ ] **步骤 4**:执行 `cd server && npm run test -- src/modules/admin-tools/admin-tools.service.spec.ts src/modules/tools/tools.service.spec.ts`,预期后台和公开服务映射同时通过。
|
||||
|
||||
### 任务 3:封闭 `none` 模式的 launch 语义并补齐概览统计
|
||||
|
||||
**文件**:
|
||||
- 修改:`server/src/modules/access/access.service.ts`
|
||||
- 修改:`server/src/modules/admin-overview/admin-overview.service.ts`
|
||||
- 创建:`server/src/modules/access/access.service.spec.ts`
|
||||
- 创建:`server/src/modules/admin-overview/admin-overview.service.spec.ts`
|
||||
- 创建:`server/test/tool-launch-none.e2e-spec.ts`
|
||||
|
||||
- [ ] **步骤 1**:先创建 `server/src/modules/access/access.service.spec.ts` 与 `server/src/modules/admin-overview/admin-overview.service.spec.ts`,分别写失败测试,覆盖“`none` 模式 launch 抛 `409`”“概览 summary 返回 `noneToolTotal` 且模式分布不把 `none` 算进下载模式”;同时创建 `server/test/tool-launch-none.e2e-spec.ts` 作为接口级失败测试。
|
||||
- [ ] **步骤 2**:执行 `cd server && npm run test -- src/modules/access/access.service.spec.ts src/modules/admin-overview/admin-overview.service.spec.ts` 与 `cd server && npm run test:e2e -- test/tool-launch-none.e2e-spec.ts`,预期 launch 与概览相关断言失败。
|
||||
- [ ] **步骤 3**:在 `server/src/modules/access/access.service.ts` 拒绝 `none` 模式 launch,在 `server/src/modules/admin-overview/admin-overview.service.ts` 增加 `noneToolTotal` 和 `none` 统计分支;若复用现有错误码,则统一错误消息语义。
|
||||
- [ ] **步骤 4**:重新执行上述测试命令,预期单元测试和 e2e 都通过,`none` 模式行为在服务端完全闭合。
|
||||
|
||||
### 任务 4:更新公开站首页与详情页,统一消费 `displayVersion`
|
||||
|
||||
**文件**:
|
||||
- 修改:`client/src/App.vue`
|
||||
- 修改:`client/src/App.spec.js`
|
||||
- 修改:`client/src/pages/ToolDetailPage.vue`
|
||||
- 修改:`client/src/pages/ToolDetailPage.spec.js`
|
||||
|
||||
- [ ] **步骤 1**:先在 `client/src/App.spec.js` 与 `client/src/pages/ToolDetailPage.spec.js` 增加失败用例,覆盖“首页优先展示 `displayVersion`”“`none` 模式主按钮文案为‘查看详情’并跳转详情页”“详情页展示 `displayVersion` 且 `none` 模式不渲染主按钮”。
|
||||
- [ ] **步骤 2**:执行 `cd client && npm run test:run -- src/App.spec.js src/pages/ToolDetailPage.spec.js`,预期 Vitest 因页面仍依赖 `latestVersion` 或仍渲染打开/下载按钮而失败。
|
||||
- [ ] **步骤 3**:更新 `client/src/App.vue` 与 `client/src/pages/ToolDetailPage.vue`,将版本展示切换到 `displayVersion`,为 `none` 模式增加详情跳转分支,并移除详情页无意义的主操作按钮。
|
||||
- [ ] **步骤 4**:重新执行 `cd client && npm run test:run -- src/App.spec.js src/pages/ToolDetailPage.spec.js`,预期公开站回归通过。
|
||||
|
||||
### 任务 5:补齐后台表单、列表和概览对新字段的 UI 支持
|
||||
|
||||
**文件**:
|
||||
- 修改:`client/src/admin/AdminApp.vue`
|
||||
- 修改:`client/src/admin/components/ToolFormDialog.vue`
|
||||
- 修改:`client/src/admin/components/AccessModeDialog.vue`
|
||||
- 修改:`client/src/admin/components/AdminToolsSection.vue`
|
||||
- 修改:`client/src/admin/components/AdminOverviewSection.vue`
|
||||
- 修改:`client/src/admin/stores/console.js`
|
||||
- 创建:`client/src/admin/components/ToolFormDialog.spec.js`
|
||||
- 创建:`client/src/admin/components/AccessModeDialog.spec.js`
|
||||
- 创建:`client/src/admin/components/AdminToolsSection.spec.js`
|
||||
- 创建:`client/src/admin/components/AdminOverviewSection.spec.js`
|
||||
|
||||
- [ ] **步骤 1**:先创建 4 个后台组件测试文件,分别写失败测试,覆盖“工具表单存在展示版本输入项并可选择‘无’”“访问方式对话框切换到 `none` 时隐藏 URL 输入”“工具列表显示版本列和 `none` 标签”“概览模式分布显示 `none` 模式统计”。
|
||||
- [ ] **步骤 2**:执行 `cd client && npm run test:run -- src/admin/components/ToolFormDialog.spec.js src/admin/components/AccessModeDialog.spec.js src/admin/components/AdminToolsSection.spec.js src/admin/components/AdminOverviewSection.spec.js`,预期后台组件测试失败。
|
||||
- [ ] **步骤 3**:更新 `client/src/admin/AdminApp.vue`、`ToolFormDialog.vue`、`AccessModeDialog.vue`、`AdminToolsSection.vue`、`AdminOverviewSection.vue` 和 `client/src/admin/stores/console.js`,让后台表单、快速切换、列表和概览统一识别 `versionOverride`、`displayVersion` 与 `noneToolTotal`。
|
||||
- [ ] **步骤 4**:重新执行上面的后台组件测试,并追加执行 `cd client && npm run test:run -- src/App.spec.js src/pages/ToolDetailPage.spec.js` 与 `cd server && npm run test -- src/modules/tools/tools.service.spec.ts src/modules/admin-tools/admin-tools.service.spec.ts src/modules/access/access.service.spec.ts src/modules/admin-overview/admin-overview.service.spec.ts`,预期前后端关键回归全部通过。
|
||||
44
design/session-state-20260413095000.md
Normal file
44
design/session-state-20260413095000.md
Normal file
@@ -0,0 +1,44 @@
|
||||
# 会话状态
|
||||
|
||||
## 基本信息
|
||||
|
||||
- **技能**: executing-plans
|
||||
- **主题**: 用户手册详情页(支持 Markdown)
|
||||
- **开始时间**: 2026-04-11 10:26
|
||||
- **最后更新**: 2026-04-11 11:28
|
||||
|
||||
## 当前状态
|
||||
|
||||
- **阶段**: 阶段 3:完成与报告
|
||||
- **上一步**: 已完成全部 6 个任务,并通过前端测试、客户端构建、服务端单测、服务端 e2e 与服务端构建。
|
||||
- **下一步**: 输出完成报告并结束本轮执行。
|
||||
|
||||
## 已确认内容
|
||||
|
||||
- 2026-04-11 10:26-需求目标是增加一个新的详情页,可显示 Markdown 格式的用户手册。
|
||||
- 2026-04-11 10:26-主站当前没有独立详情页,详情内容以弹窗形式展示。
|
||||
- 2026-04-11 10:26-前端已存在 Markdown 渲染工具,可作为后续方案基础。
|
||||
- 2026-04-11 10:27-详情页主要用户为普通访客。
|
||||
- 2026-04-11 10:31-详情页交互方式为站内路由跳转。
|
||||
- 2026-04-11 10:32-用户手册内容来源先复用现有 `description` 字段承载 Markdown。
|
||||
- 2026-04-11 10:33-旧的详情弹窗将被新详情页替换。
|
||||
- 2026-04-11 10:37-本次实现范围包含详情页空状态、404 状态与返回入口体验。
|
||||
- 2026-04-11 10:39-验收标准为长期可用,要求详情页具备清晰信息结构。
|
||||
- 2026-04-11 10:42-边界情况需覆盖直达路由、空内容、404 及超长 Markdown 阅读体验。
|
||||
- 2026-04-11 10:58-最终方案为基于 `slug` 的详情页路由与详情接口。
|
||||
- 2026-04-11 11:02-规格文档已获批准,开始编写实施计划。
|
||||
- 2026-04-11 11:05-实施计划已保存,包含 6 个按 TDD 拆分的执行任务。
|
||||
- 2026-04-11 11:08-执行前检查发现当前分支为 `master`,按技能规则需用户确认后才能继续。
|
||||
- 2026-04-11 11:09-用户已确认允许在 `master` 分支执行计划,任务 1 开始。
|
||||
- 2026-04-11 11:12-任务 1 完成:前端测试基建建立,`markdown-outline` 工具和测试通过。
|
||||
- 2026-04-11 11:17-任务 2 和任务 3 完成:后端 `slug` 详情服务单测和控制器 e2e 通过。
|
||||
- 2026-04-11 11:28-任务 4、5、6 完成:公开详情页、首页路由跳转、目录阅读体验和后台文案已落地并完成最终验证。
|
||||
|
||||
## 待处理问题
|
||||
|
||||
- [x] 任务 1:前端测试基建和 Markdown 目录工具。
|
||||
- [x] 任务 2:后端按 `slug` 查询详情的服务层能力。
|
||||
- [x] 任务 3:公开详情 `slug` 接口和后端 e2e。
|
||||
- [x] 任务 4:公开详情页路由、API 接入和页面状态。
|
||||
- [x] 任务 5:首页详情弹窗替换为路由跳转。
|
||||
- [x] 任务 6:长文阅读体验、后台提示文案和整体验证。
|
||||
28
design/session-state-20260414181132.md
Normal file
28
design/session-state-20260414181132.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# 会话状态
|
||||
|
||||
## 基本信息
|
||||
|
||||
- **技能**: brainstorming
|
||||
- **主题**: 下载跳转不应修改当前页 URL
|
||||
- **开始时间**: 2026-04-13 09:50
|
||||
- **最后更新**: 2026-04-13 10:02
|
||||
|
||||
## 当前状态
|
||||
|
||||
- **阶段**: 阶段 3:完成与报告
|
||||
- **上一步**: 已完成前后端修复与前端回归测试补充。
|
||||
- **下一步**: 输出修复结果,并说明测试环境依赖缺失导致无法实际执行 Vitest。
|
||||
|
||||
## 已确认内容
|
||||
|
||||
- 2026-04-13 09:46-问题表现为跳转到下载页时,当前访客页 URL 也会被改成下载地址。
|
||||
- 2026-04-13 09:47-根因位于访客端 launch 逻辑和后端 access launch 响应对下载模式的 same_tab 处理。
|
||||
- 2026-04-13 09:49-本次采用最小修复,下载模式统一保持当前页不变,仅在新标签页或新窗口执行下载。
|
||||
- 2026-04-13 09:57-已修改 `AccessService`、首页和详情页 launch 逻辑,并新增前端回归测试用例。
|
||||
- 2026-04-13 10:01-测试执行受阻:本地 `client/node_modules` 不完整,`vitest` 可执行不存在,且 `npx` 因网络/缓存权限失败无法补装。
|
||||
|
||||
## 待处理问题
|
||||
|
||||
- [x] 修改后端 launch 响应,下载模式统一返回 `openIn: new_tab`。
|
||||
- [x] 修改首页与详情页前端逻辑,下载模式不再走 `window.location.assign(...)`。
|
||||
- [x] 增加下载模式回归测试,覆盖当前页 URL 不变的行为。
|
||||
@@ -3,42 +3,70 @@
|
||||
## 基本信息
|
||||
|
||||
- **技能**: executing-plans
|
||||
- **主题**: 用户手册详情页(支持 Markdown)
|
||||
- **开始时间**: 2026-04-11 10:26
|
||||
- **最后更新**: 2026-04-11 11:28
|
||||
- **主题**: 网页工具维护版本字段
|
||||
- **开始时间**: 2026-04-14 18:11
|
||||
- **最后更新**: 2026-04-15 09:50
|
||||
|
||||
## 当前状态
|
||||
|
||||
- **阶段**: 阶段 3:完成与报告
|
||||
- **上一步**: 已完成全部 6 个任务,并通过前端测试、客户端构建、服务端单测、服务端 e2e 与服务端构建。
|
||||
- **下一步**: 输出完成报告并结束本轮执行。
|
||||
- **阶段**: 阶段 2:执行任务
|
||||
- **上一步**: 已完成任务 5,后台表单、列表和概览已补齐 `versionOverride` / `displayVersion` / `none` 模式 UI 支持,并完成前端回归。
|
||||
- **下一步**: 等待用户验收;如继续扩展,可补管理端更高层级交互测试或继续清理构建体积告警。
|
||||
|
||||
## 已确认内容
|
||||
|
||||
- 2026-04-11 10:26-需求目标是增加一个新的详情页,可显示 Markdown 格式的用户手册。
|
||||
- 2026-04-11 10:26-主站当前没有独立详情页,详情内容以弹窗形式展示。
|
||||
- 2026-04-11 10:26-前端已存在 Markdown 渲染工具,可作为后续方案基础。
|
||||
- 2026-04-11 10:27-详情页主要用户为普通访客。
|
||||
- 2026-04-11 10:31-详情页交互方式为站内路由跳转。
|
||||
- 2026-04-11 10:32-用户手册内容来源先复用现有 `description` 字段承载 Markdown。
|
||||
- 2026-04-11 10:33-旧的详情弹窗将被新详情页替换。
|
||||
- 2026-04-11 10:37-本次实现范围包含详情页空状态、404 状态与返回入口体验。
|
||||
- 2026-04-11 10:39-验收标准为长期可用,要求详情页具备清晰信息结构。
|
||||
- 2026-04-11 10:42-边界情况需覆盖直达路由、空内容、404 及超长 Markdown 阅读体验。
|
||||
- 2026-04-11 10:58-最终方案为基于 `slug` 的详情页路由与详情接口。
|
||||
- 2026-04-11 11:02-规格文档已获批准,开始编写实施计划。
|
||||
- 2026-04-11 11:05-实施计划已保存,包含 6 个按 TDD 拆分的执行任务。
|
||||
- 2026-04-11 11:08-执行前检查发现当前分支为 `master`,按技能规则需用户确认后才能继续。
|
||||
- 2026-04-11 11:09-用户已确认允许在 `master` 分支执行计划,任务 1 开始。
|
||||
- 2026-04-11 11:12-任务 1 完成:前端测试基建建立,`markdown-outline` 工具和测试通过。
|
||||
- 2026-04-11 11:17-任务 2 和任务 3 完成:后端 `slug` 详情服务单测和控制器 e2e 通过。
|
||||
- 2026-04-11 11:28-任务 4、5、6 完成:公开详情页、首页路由跳转、目录阅读体验和后台文案已落地并完成最终验证。
|
||||
- 2026-04-14 18:06-项目为 Vue 3 + NestJS + Prisma 的工具站,工具实体区分 `web` 与 `download` 两种访问方式。
|
||||
- 2026-04-14 18:08-下载工具的版本来自 `ToolArtifact.version`,网页工具 `Tool` 本体目前没有独立版本字段。
|
||||
- 2026-04-14 18:10-前台首页和详情页当前都显示“版本”,但仅下载工具会返回 `latestVersion`,网页工具会显示“暂无版本”。
|
||||
- 2026-04-14 18:11-后台新增/编辑工具表单当前没有网页工具版本输入项。
|
||||
- 2026-04-14 18:13-用户确认版本字段采用“后台维护 + 前台展示”方案,需在访客端列表页和详情页展示。
|
||||
- 2026-04-14 18:15-用户选择混合模式:`web` 工具有独立版本字段,`download` 工具默认取 `latestArtifact.version`,并允许单独覆盖展示版本。
|
||||
- 2026-04-14 18:15-访问方式需要新增“无”模式,该模式也要支持维护版本。
|
||||
- 2026-04-14 18:17-关于“无”模式的访客端行为,用户连续回复了 `1` 和 `3`,当前需要进一步确认最终选择。
|
||||
- 2026-04-14 18:18-用户最终确认“无”模式采用详情引导:列表页主按钮为“查看详情”,详情页不提供打开/下载按钮。
|
||||
- 2026-04-14 18:20-用户确认版本字段仅用于展示,不参与发布校验,现有发布规则保持不变。
|
||||
- 2026-04-14 18:21-用户确认完成范围为“常规完整”:后台工具列表也显示版本和访问方式 `none`,相关接口统一返回展示版本。
|
||||
- 2026-04-14 18:24-用户选择方案 2:使用 `Tool.versionOverride` 存储覆盖版本,由服务端统一计算 `displayVersion`。
|
||||
- 2026-04-14 18:29-规格文档已写入 `design/specs/2026-04-14-tool-display-version-none-mode-design.md`。
|
||||
- 2026-04-14 18:43-实施计划已写入 `design/plans/2026-04-14-tool-display-version-none-mode-plan.md`,按单一子系统拆为 5 个任务。
|
||||
- 2026-04-14 18:49-已切换到 `executing-plans` 技能并完成计划审阅;当前分支为 `master`,按执行规范需用户确认后才能继续执行。
|
||||
- 2026-04-14 19:20-用户确认继续在 `master` 上执行;任务 1 已完成,`ToolsService` 与公开详情 e2e 已验证 `displayVersion`,本地数据库已手工应用 `version_override` 列。
|
||||
- 2026-04-14 20:10-任务 2 已完成,后台 DTO、后台工具服务与种子数据已支持 `versionOverride` 和 `accessMode=none`,并通过相关 Jest 用例。
|
||||
- 2026-04-14 20:40-任务 3 已完成,`none` 模式 launch 已在服务端返回 `409`,后台概览已补 `noneToolTotal`,相关单测与 e2e 已通过。
|
||||
- 2026-04-15 09:27-任务 4 已完成,公开站首页与详情页已统一展示 `displayVersion`,`none` 模式按“查看详情/无主按钮”行为闭合,公共前端 Vitest 已通过。
|
||||
- 2026-04-15 09:49-任务 5 已完成,管理端表单新增展示版本输入,访问方式支持“无”,工具列表新增版本列,概览显示 `none` 模式统计;新增 4 个管理端组件测试并通过,前端构建通过。
|
||||
|
||||
## 待处理问题
|
||||
|
||||
- [x] 任务 1:前端测试基建和 Markdown 目录工具。
|
||||
- [x] 任务 2:后端按 `slug` 查询详情的服务层能力。
|
||||
- [x] 任务 3:公开详情 `slug` 接口和后端 e2e。
|
||||
- [x] 任务 4:公开详情页路由、API 接入和页面状态。
|
||||
- [x] 任务 5:首页详情弹窗替换为路由跳转。
|
||||
- [x] 任务 6:长文阅读体验、后台提示文案和整体验证。
|
||||
- [x] 网页工具版本字段的主要使用对象是谁,以及它需要出现在哪些页面或接口里。
|
||||
- [x] 版本字段是否仅适用于 `web` 模式,还是所有工具都应统一维护一个主版本。
|
||||
- [x] 版本字段是否参与发布校验、排序、筛选或审计记录。
|
||||
- [x] “无”访问模式在访客端的按钮、详情页主操作和可见性规则。
|
||||
- [x] 版本字段和“无”模式需要覆盖到哪些后台页面和接口返回。
|
||||
|
||||
## 执行状态
|
||||
|
||||
### 计划信息
|
||||
|
||||
- **计划文档**: `design/plans/2026-04-14-tool-display-version-none-mode-plan.md`
|
||||
- **开始时间**: 2026-04-14 18:49
|
||||
|
||||
### 任务进度
|
||||
|
||||
| 任务 | 状态 | 完成时间 | 备注 |
|
||||
|------|------|----------|------|
|
||||
| 任务1:先锁定 Prisma 契约和公开接口版本映射 | 已完成 | 19:20 | `schema-engine` 被沙箱拦截,改为手工 migration SQL + raw SQL 应用列变更 |
|
||||
| 任务2:补齐后台工具服务对 `versionOverride` 和 `none` 的支持 | 已完成 | 2026-04-14 20:10 | 后台 DTO/服务/seed 已对齐,并通过 Jest 回归 |
|
||||
| 任务3:封闭 `none` 模式的 launch 语义并补齐概览统计 | 已完成 | 2026-04-14 20:40 | `none` launch 返回 `409`,概览统计补齐,单测与 e2e 已通过 |
|
||||
| 任务4:更新公开站首页与详情页,统一消费 `displayVersion` | 已完成 | 2026-04-15 09:27 | 列表/详情统一显示 `displayVersion`,`none` 模式行为闭合,Vitest 通过 |
|
||||
| 任务5:补齐后台表单、列表和概览对新字段的 UI 支持 | 已完成 | 2026-04-15 09:49 | 表单/访问方式/列表/概览已支持 `versionOverride` 与 `none`,组件测试与构建通过 |
|
||||
|
||||
### 遇到的问题
|
||||
|
||||
| 问题 | 解决方案 | 解决时间 |
|
||||
|------|----------|----------|
|
||||
| 当前工作分支为 `master`,执行规范要求先确认是否允许直接在主分支改动 | 用户已明确确认继续在 `master` 上执行 | 19:20 |
|
||||
| `jest` 默认 worker 在沙箱中触发 `spawn EPERM` | 改用 `npx jest --runInBand` 单进程执行测试 | 19:14 |
|
||||
| `prisma migrate dev` 的 `schema-engine` 在沙箱中触发 `spawn EPERM` | 手工创建 migration 文件,并通过 Prisma raw SQL 为本地 SQLite 添加 `version_override` 列 | 19:18 |
|
||||
| `client` 本地缺少 `vitest` 依赖,`npm run test:run` 无法直接执行 | 在 `client` 目录执行 `npm install --no-save vitest@3.2.4` 后,统一使用 `npx vitest run ...` 执行前端测试 | 2026-04-15 09:00 |
|
||||
| Element Plus 的 `dialog/table` 在 jsdom 下不稳定渲染测试文本 | 为管理端组件测试增加轻量 stub,直接覆盖组件分支逻辑,避免把断言绑定到第三方渲染细节 | 2026-04-15 09:46 |
|
||||
|
||||
56
design/specs/2026-04-13-download-launch-url-design.md
Normal file
56
design/specs/2026-04-13-download-launch-url-design.md
Normal file
@@ -0,0 +1,56 @@
|
||||
# 下载跳转 URL 修复设计
|
||||
|
||||
## 概述
|
||||
|
||||
当前访客端在触发下载型工具时,会沿用网页型工具的 `same_tab` 导航分支。若后台将下载工具配置为非新标签页,前端会直接执行 `window.location.assign(actionUrl)`,导致当前 SPA 页面 URL 被改写成下载地址,破坏返回和继续浏览体验。
|
||||
|
||||
本次修复目标是保证下载行为不会修改当前访客页的 URL。下载应在新标签页或浏览器新窗口中完成;当前页继续停留在工具列表页或详情页。
|
||||
|
||||
## 目标定位
|
||||
|
||||
主要用户为访客端普通用户,在浏览工具列表或详情页时点击下载操作。
|
||||
|
||||
## 约束条件
|
||||
|
||||
- 保持现有网页模式 `web` 的同标签/新标签配置能力不变。
|
||||
- 保持已有下载埋点与下载票据逻辑不变。
|
||||
- 变更范围尽量小,优先修复公开访客端入口,不扩展后台交互。
|
||||
|
||||
## 成功标准
|
||||
|
||||
- 下载型工具触发后,当前页 URL 保持不变。
|
||||
- 首页和详情页的下载按钮行为一致。
|
||||
- 网页型工具仍按现有 `openIn` 配置运行。
|
||||
- 新增自动化测试能覆盖下载模式不走当前页跳转。
|
||||
|
||||
## 架构设计
|
||||
|
||||
- 后端 `AccessService.launchTool`:
|
||||
- 对下载模式统一返回 `openIn: 'new_tab'`。
|
||||
- 包括外部下载地址和票据下载两种分支。
|
||||
- 前端 `App.vue` 与 `ToolDetailPage.vue`:
|
||||
- 仅网页模式 `web + same_tab` 执行 `window.location.assign(...)`。
|
||||
- 下载模式始终使用 `window.open(...)`,不再降级到当前页跳转。
|
||||
- 若浏览器阻止弹窗,则提示用户允许新窗口,而不是改写当前页 URL。
|
||||
|
||||
## 数据流
|
||||
|
||||
1. 用户点击下载按钮。
|
||||
2. 前端调用 `/tools/:id/launch`。
|
||||
3. 后端返回 `mode: download` 且 `openIn: new_tab`。
|
||||
4. 前端使用 `window.open(actionUrl, '_blank', 'noopener,noreferrer')` 发起下载。
|
||||
5. 当前 SPA 路由保持原状。
|
||||
|
||||
## 错误处理
|
||||
|
||||
- 若 `actionUrl` 为空,维持现有错误提示。
|
||||
- 若浏览器拦截新窗口,显示明确提示,不执行 `location.assign`。
|
||||
|
||||
## 测试策略
|
||||
|
||||
- 前端单测覆盖首页下载按钮:
|
||||
- `download + same_tab` 输入场景下,断言不会调用 `window.location.assign`。
|
||||
- 断言 `window.open` 被调用并保持当前路由不变。
|
||||
- 前端单测覆盖详情页下载按钮:
|
||||
- 断言下载模式不会调用 `window.location.assign`。
|
||||
- 服务端单测如已有 launch 行为覆盖,则补充下载模式 `openIn` 断言;若当前模块无单测,则至少保证前端回归测试覆盖核心用户路径。
|
||||
152
design/specs/2026-04-14-tool-display-version-none-mode-design.md
Normal file
152
design/specs/2026-04-14-tool-display-version-none-mode-design.md
Normal file
@@ -0,0 +1,152 @@
|
||||
# 工具展示版本与无访问模式设计规格
|
||||
|
||||
## 概述
|
||||
|
||||
当前工具站只区分 `web` 和 `download` 两种访问方式。下载工具的版本来源于 `ToolArtifact.version`,因此访客端首页和详情页中的“版本”信息只对下载工具有效,网页工具长期显示“暂无版本”。与此同时,当前系统没有“仅展示详情、不提供打开或下载入口”的访问模式,无法承载预告型、资料型或人工分发型工具。
|
||||
|
||||
本次设计目标是在现有 `Tool` 模型上补齐“展示版本”和“无访问模式”能力,保持下载包管理逻辑不变,同时让前台和后台统一拿到一个稳定的展示版本字段。具体策略为:数据库新增 `Tool.versionOverride` 作为人工维护的展示版本覆盖值;服务端统一计算 `displayVersion`;访问方式新增 `none`,用于“只展示详情,不执行 launch”的工具。
|
||||
|
||||
## 目标定位
|
||||
|
||||
- **主要用户**:后台管理员、公开站访客
|
||||
- **使用场景**:管理员在新增或编辑工具时维护展示版本,并可将工具设置为 `download`、`web` 或 `none`;访客在首页和详情页查看统一的版本信息,其中 `none` 模式工具只提供“查看详情”入口,不提供打开网页或下载操作
|
||||
|
||||
## 约束条件
|
||||
|
||||
- **技术限制**:前端基于 Vue 3 + Element Plus,服务端基于 NestJS + Prisma + SQLite;本次只做现有模型上的增量改造,不引入新的依赖或新的版本历史表
|
||||
- **时间限制**:本轮只实现版本展示和 `none` 访问模式,不扩展版本历史、发布日期、版本说明等二级能力
|
||||
- **资源限制**:继续复用现有下载包模型、公开列表/详情接口和后台工具管理流程;版本字段仅用于展示,不参与发布校验、不新增额外审核流程
|
||||
|
||||
## 成功标准
|
||||
|
||||
- [ ] Prisma 数据模型支持 `AccessMode.none` 和 `Tool.versionOverride`
|
||||
- [ ] 后台新增/编辑工具表单可以维护“展示版本”,访问方式下拉可选择“无”
|
||||
- [ ] 后台工具列表接口和公开工具列表/详情接口统一返回 `displayVersion`
|
||||
- [ ] 下载工具的 `displayVersion` 计算规则为 `versionOverride || latestArtifact.version || null`
|
||||
- [ ] 网页工具和无访问模式工具的 `displayVersion` 计算规则为 `versionOverride || null`
|
||||
- [ ] 访客端首页和详情页统一展示 `displayVersion`,不再依赖下载模式专属的 `latestVersion`
|
||||
- [ ] `none` 模式在首页主按钮显示“查看详情”,详情页不展示打开/下载主按钮
|
||||
- [ ] 直接调用 `launch` 接口访问 `none` 模式工具时返回明确错误,且不会产生打开/下载计数
|
||||
- [ ] 现有发布约束保持不变:`web` 仍要求 `openUrl`,`download` 仍要求安装包或下载地址,`none` 不因为缺少版本而被阻止发布
|
||||
- [ ] 后台概览和模式标签不再把 `none` 模式误显示为“下载模式”
|
||||
|
||||
## 架构设计
|
||||
|
||||
### 系统结构
|
||||
|
||||
本次改造分为四层:
|
||||
|
||||
1. **数据层**:在 `Tool` 模型中新增 `versionOverride` 字段;在 `AccessMode` 枚举中新增 `none`
|
||||
2. **映射层**:在后台服务和公开服务中统一计算 `displayVersion`,将“原始覆盖值”和“最终展示值”分离
|
||||
3. **行为层**:在 `AccessService` 中显式拒绝 `none` 模式的 launch 行为,保证服务端语义闭合
|
||||
4. **展示层**:后台编辑页维护 `versionOverride`,后台列表和访客端页面统一展示 `displayVersion`
|
||||
|
||||
版本数据的核心原则如下:
|
||||
|
||||
1. `versionOverride` 是管理员手工维护的原始字段,允许为空
|
||||
2. `displayVersion` 是接口返回给前端的最终展示值,不直接持久化
|
||||
3. 对下载工具,若 `versionOverride` 为空,则自动回退到当前 `latestArtifact.version`
|
||||
4. 对网页工具和无访问模式工具,`displayVersion` 只来自 `versionOverride`
|
||||
5. `latestArtifact.version` 继续用于安装包管理;`displayVersion` 用于页面展示
|
||||
|
||||
访问模式的核心原则如下:
|
||||
|
||||
1. 新增枚举值 `none`,内部值固定为 `none`,后台展示文案为“无”
|
||||
2. `none` 模式工具允许存在详情页和展示版本,但不允许执行 launch
|
||||
3. 访客端列表页对 `none` 模式的主按钮改为“查看详情”
|
||||
4. 访客端详情页对 `none` 模式不渲染打开/下载按钮
|
||||
5. 服务端若收到对 `none` 模式的 launch 请求,返回 `409 Conflict`
|
||||
|
||||
### 组件划分
|
||||
|
||||
| 组件 | 职责 | 依赖 |
|
||||
|------|------|------|
|
||||
| `server/prisma/schema.prisma` | 为 `AccessMode` 增加 `none`;为 `Tool` 增加 `versionOverride` 字段 | Prisma |
|
||||
| `server/prisma/seed.ts` | 补齐种子数据中的访问方式和展示版本样例,避免本地初始化后看不到新行为 | Prisma Seed |
|
||||
| `server/src/modules/admin-tools/dto/create-tool.dto.ts` | 接收 `versionOverride`,并允许 `accessMode=none` | `class-validator` |
|
||||
| `server/src/modules/admin-tools/dto/update-tool.dto.ts` | 继承新增字段,支持后台更新展示版本 | `CreateToolDto` |
|
||||
| `server/src/modules/admin-tools/dto/update-access-mode.dto.ts` | 接收 `none` 枚举值,兼容访问方式切换 | `class-validator` |
|
||||
| `server/src/modules/admin-tools/admin-tools.service.ts` | 规范化 `versionOverride`;列表和详情返回 `displayVersion` 与 `versionOverride`;保持发布校验逻辑不因版本字段变化 | Prisma |
|
||||
| `server/src/modules/tools/tools.service.ts` | 公开列表和详情统一返回 `displayVersion`;保留下载工具的 `latestVersion` 作为兼容字段 | Prisma |
|
||||
| `server/src/modules/access/access.service.ts` | 对 `none` 模式返回明确错误,禁止生成 launch 地址或下载票据 | Prisma, ConfigService |
|
||||
| `server/src/modules/admin-overview/admin-overview.service.ts` | 访问方式统计兼容 `none`,避免概览数据遗漏或模式显示错误 | Prisma |
|
||||
| `client/src/admin/components/ToolFormDialog.vue` | 新增“展示版本”输入项;访问方式下拉新增“无”;根据模式调整提示文案 | Element Plus |
|
||||
| `client/src/admin/components/AdminToolsSection.vue` | 列表增加版本列,访问方式标签兼容 `none` 文案 | Element Plus |
|
||||
| `client/src/admin/components/AccessModeDialog.vue` | 快速修改访问方式时允许选择“无”,并在 `none` 模式下隐藏 URL 输入项 | Element Plus |
|
||||
| `client/src/admin/AdminApp.vue` | 表单数据结构新增 `versionOverride`;构造创建/更新 payload;访问模式、标签颜色和模式文案兼容 `none` | Vue 3 |
|
||||
| `client/src/App.vue` | 工具卡片统一显示 `displayVersion`;`none` 模式主按钮改为“查看详情”并直接路由跳转 | `vue-router`, `client/src/api.js` |
|
||||
| `client/src/pages/ToolDetailPage.vue` | 摘要区展示 `displayVersion`;`none` 模式不显示主操作按钮 | `vue-router`, `client/src/api.js` |
|
||||
| `client/src/admin/components/AdminOverviewSection.vue` | 模式统计与 Top 工具模式文案兼容 `none` | Element Plus |
|
||||
|
||||
## 数据流
|
||||
|
||||
### 版本字段维护流
|
||||
|
||||
1. 管理员在新增或编辑工具时填写“展示版本”
|
||||
2. 前端将该值作为 `versionOverride` 提交给后台;空字符串在提交前或服务端落库前统一归一化为 `null`
|
||||
3. 服务端保存 `Tool.versionOverride`
|
||||
4. 当后台列表、后台详情、公开列表或公开详情查询工具时,服务端统一计算 `displayVersion`
|
||||
5. 前端页面一律渲染 `displayVersion`,不再直接依赖下载工具专属的 `latestVersion`
|
||||
|
||||
`displayVersion` 计算规则如下:
|
||||
|
||||
1. 当 `tool.accessMode === 'download'` 时:`displayVersion = tool.versionOverride || tool.latestArtifact?.version || null`
|
||||
2. 当 `tool.accessMode === 'web'` 或 `tool.accessMode === 'none'` 时:`displayVersion = tool.versionOverride || null`
|
||||
|
||||
为降低回归风险,下载工具响应中的 `latestVersion` 字段继续保留,其语义保持为“当前最新安装包版本”;页面展示逻辑统一切换为 `displayVersion`。
|
||||
|
||||
### 访问模式切换流
|
||||
|
||||
1. 管理员在新增/编辑表单或访问方式对话框中选择 `download`、`web` 或 `none`
|
||||
2. 当模式为 `web` 时,沿用现有规则,发布时仍要求 `openUrl`
|
||||
3. 当模式为 `download` 时,沿用现有规则,发布时仍要求活动安装包或外部下载地址
|
||||
4. 当模式为 `none` 时,不生成 launch 目标,不要求 `openUrl`,前端不展示打开/下载按钮
|
||||
5. 当公开站列表遇到 `none` 模式工具时,主按钮直接路由到详情页
|
||||
6. 当公开站详情页遇到 `none` 模式工具时,仅展示内容和版本,不发起 launch 请求
|
||||
7. 若外部调用者直接请求 `POST /api/v1/tools/:id/launch` 且目标工具为 `none` 模式,服务端返回 `409`
|
||||
|
||||
### 前后台显示流
|
||||
|
||||
1. 后台工具列表新增版本列,显示 `row.displayVersion || '-'`
|
||||
2. 公开首页卡片“版本”行显示 `tool.displayVersion || '暂无版本'`
|
||||
3. 公开详情页摘要区显示 `detail.displayVersion || '暂无版本'`
|
||||
4. `none` 模式的卡片副文案和详情摘要不再显示“下载/访问”动词,统一显示“仅详情”
|
||||
5. 概览和模式标签遇到 `none` 时显示“无”,不将其归并到下载模式
|
||||
|
||||
## 错误处理
|
||||
|
||||
| 错误类型 | 处理方式 |
|
||||
|----------|----------|
|
||||
| `versionOverride` 为空字符串 | 前端提交前或服务端保存前统一归一化为 `null`,避免空串污染数据 |
|
||||
| 下载工具没有覆盖版本且没有最新安装包版本 | `displayVersion` 返回 `null`,前端显示“暂无版本”,但不阻止发布之外的页面展示 |
|
||||
| `none` 模式被直接调用 launch 接口 | 服务端返回 `409 Conflict`,建议复用 `TOOL_ACCESS_MODE_MISMATCH` 并提供明确消息,如“tool is not launchable in none mode” |
|
||||
| 访问方式统计遇到 `none` | 后台概览必须显式处理该值,避免统计遗漏或错误文案 |
|
||||
| 旧前端代码仍读取 `latestVersion` | 下载工具继续保留该字段,版本展示迁移到 `displayVersion` 后逐步收敛消费端 |
|
||||
| 管理员把工具切换为 `none` | 页面行为以模式为准,版本仍可展示,但公开站不再允许打开/下载 |
|
||||
|
||||
## 风险评估
|
||||
|
||||
| 风险描述 | 类别 | 影响 | 概率 | 缓解策略 |
|
||||
|----------|------|------|------|----------|
|
||||
| 新增 `none` 枚举后,现有前端分支把未知模式错误地当成下载模式处理 | 集成风险 | 高 | 中 | 全量检查 `accessMode` 条件分支,补齐 `none` 的按钮文案、标签颜色和统计展示 |
|
||||
| 下载工具同时存在 `latestArtifact.version` 和 `versionOverride`,容易出现展示口径不一致 | 技术风险 | 中 | 中 | 服务端统一生成 `displayVersion`,前端禁止自行拼接版本来源 |
|
||||
| 旧接口调用方继续消费 `latestVersion`,导致 web/none 工具仍显示“暂无版本” | 范围风险 | 中 | 中 | 在页面和后台列表统一切到 `displayVersion`,同时短期保留 `latestVersion` 兼容下载工具 |
|
||||
| 增加 `none` 模式后,后台概览和模式统计遗漏该值 | 集成风险 | 中 | 中 | 同步更新概览服务、模式标签和概览页面文案,避免出现统计不闭合 |
|
||||
|
||||
## 测试策略
|
||||
|
||||
- **单元测试**:为服务端新增版本解析逻辑编写测试,覆盖三种场景:下载工具无覆盖值时回退安装包版本、下载工具有覆盖值时优先显示覆盖值、`web/none` 工具只使用覆盖值
|
||||
- **集成测试**:覆盖后台创建/更新工具时提交 `versionOverride` 和 `accessMode=none`;覆盖公开列表和详情接口返回 `displayVersion`;覆盖 `none` 模式 launch 接口返回 `409`
|
||||
- **前端组件测试**:覆盖首页卡片在 `none` 模式下显示“查看详情”;覆盖详情页在 `none` 模式下不渲染主操作按钮;覆盖版本展示优先使用 `displayVersion`
|
||||
- **验收标准**:管理员可维护展示版本;后台工具列表可看到版本;访客端列表与详情都能看到统一版本;下载工具默认继承安装包版本;`none` 模式只可查看详情、不可 launch;后台概览与模式文案不出现错误映射
|
||||
|
||||
## 决策记录
|
||||
|
||||
| 决策 | 理由 | 影响 |
|
||||
|------|------|------|
|
||||
| 使用 `Tool.versionOverride + displayVersion`,而不是为所有工具新建统一版本表 | 当前需求只需要单值展示和少量覆盖能力,不需要版本历史,增量成本最低 | 需要在服务端增加统一映射逻辑 |
|
||||
| `displayVersion` 由服务端计算,不在数据库落地 | 避免前端自行拼接版本来源,减少 download/web/none 三种模式的歧义 | 后台和公开接口都要增加该字段 |
|
||||
| 下载工具保留 `latestVersion`,但页面展示切到 `displayVersion` | 降低旧代码回归风险,同时给新页面一个统一字段 | 服务端响应短期内会同时存在两个版本相关字段 |
|
||||
| 访问方式新增 `none`,而不是用布尔开关控制是否可 launch | 与现有 `AccessMode` 模型保持一致,语义清晰,便于后台筛选和统计 | Prisma 枚举、前后端条件分支和概览统计都需要更新 |
|
||||
| `none` 模式首页主按钮跳详情页,详情页不展示主操作按钮 | 用户已明确选择详情引导型行为,比“禁用按钮”更可用 | 公开站首页和详情页都需增加 `none` 分支 |
|
||||
| 版本字段不参与发布校验 | 用户明确要求版本只作展示,不希望改变当前发布约束 | `assertPublishInput` 和状态流保持现状,只需兼容 `none` 模式 |
|
||||
Reference in New Issue
Block a user