update
This commit is contained in:
83
design/context/project-context.md
Normal file
83
design/context/project-context.md
Normal file
@@ -0,0 +1,83 @@
|
||||
# 项目上下文
|
||||
|
||||
## 基本信息
|
||||
|
||||
| 字段 | 内容 |
|
||||
|------|------|
|
||||
| **项目名称** | Tools Show |
|
||||
| **技术栈** | Vue 3、vue-router、Vite、Vitest、NestJS、Prisma、Jest、SQLite |
|
||||
| **创建日期** | 2026-04-11 |
|
||||
| **最后更新** | 2026-04-11 |
|
||||
| **项目阶段** | 开发中 |
|
||||
|
||||
## 已完成功能
|
||||
|
||||
| 功能 | 描述 | 完成日期 | 状态 |
|
||||
|------|------|---------|------|
|
||||
| 访客端工具列表与筛选 | 首页支持搜索、分类、排序、分页和站点概览弹窗 | 2026-04-11 | 稳定 |
|
||||
| 工具用户手册详情页 | 新增基于 `slug` 的访客端详情页,支持 Markdown 手册、空状态、404、返回入口和长文目录导航 | 2026-04-11 | 稳定 |
|
||||
| 公开详情 `slug` 接口 | 服务端新增按 `slug` 查询已发布工具详情的公开接口,并保留原有按 `id` 查询能力 | 2026-04-11 | 稳定 |
|
||||
| 前端测试基建 | 客户端补充 `Vitest + Vue Test Utils + jsdom`,覆盖首页跳转、详情页和 Markdown 目录工具 | 2026-04-11 | 稳定 |
|
||||
|
||||
## 项目结构
|
||||
|
||||
### 目录结构
|
||||
|
||||
```text
|
||||
/
|
||||
├── client/ # Vue 前端与管理端
|
||||
├── server/ # NestJS 后端
|
||||
├── docs/ # 项目文档
|
||||
├── design/ # 需求、规格、计划与上下文
|
||||
└── docker/ # 运行环境脚本
|
||||
```
|
||||
|
||||
### 模块划分
|
||||
|
||||
| 模块 | 职责 | 依赖关系 |
|
||||
|------|------|---------|
|
||||
| `client/src/App.vue` | 访客端工具列表、筛选和概览入口 | `client/src/api.js` |
|
||||
| `client/src/pages/ToolDetailPage.vue` | 访客端工具详情与 Markdown 手册阅读 | `client/src/api.js`, `client/src/utils/markdown.js`, `client/src/utils/markdown-outline.js` |
|
||||
| `client/src/admin/*` | 后台工具、分类和审计管理 | `client/src/admin/api.js` |
|
||||
| `server/src/modules/tools/*` | 公开工具列表与详情查询 | Prisma |
|
||||
| `server/src/modules/access/*` | 网页打开与下载行为 | `server/src/modules/tools/*` |
|
||||
|
||||
## 架构决策记录
|
||||
|
||||
| 日期 | 决策 | 理由 | 影响 |
|
||||
|------|------|------|------|
|
||||
| 2026-04-11 | 访客端详情页使用 `slug` 路由 | 链接可读、适合长期分享和直达访问 | 前后端同步支持 `/tools/:slug` |
|
||||
| 2026-04-11 | 继续复用 `Tool.description` 作为用户手册源 | 避免新增数据模型和后台复杂度 | 后台只需优化说明文案 |
|
||||
| 2026-04-11 | 保留按 `id` 获取详情接口,同时新增按 `slug` 接口 | 降低回归风险,兼容既有调用 | `ToolsService` 维护共享详情映射 |
|
||||
| 2026-04-11 | 客户端引入 `Vitest + Vue Test Utils + jsdom` | 详情页和路由改造需要前端自动化回归 | `client/package.json` 和锁文件更新 |
|
||||
|
||||
## 依赖管理
|
||||
|
||||
### 项目依赖
|
||||
|
||||
| 依赖名称 | 版本 | 用途 | 来源 |
|
||||
|---------|------|------|------|
|
||||
| `vitest` | `^3.2.4` | 客户端单元测试 | npm |
|
||||
| `@vue/test-utils` | `^2.4.6` | Vue 组件测试挂载 | npm |
|
||||
| `jsdom` | `^26.1.0` | 客户端测试 DOM 环境 | npm |
|
||||
| `marked` | `^17.0.5` | Markdown 解析 | npm |
|
||||
| `dompurify` | `^3.3.3` | Markdown HTML 安全净化 | npm |
|
||||
|
||||
### 外部服务
|
||||
|
||||
| 服务 | 用途 | 配置位置 |
|
||||
|------|------|---------|
|
||||
| SQLite | 工具、分类与访问数据存储 | `server/prisma/schema.prisma` |
|
||||
|
||||
## 技术债务
|
||||
|
||||
| 债务 | 影响 | 优先级 | 备注 |
|
||||
|------|------|-------|------|
|
||||
| 客户端构建产物单 chunk 体积较大 | Vite 构建有 chunk size warning | 中 | 后续可考虑按公开页/管理页拆分 chunk |
|
||||
| 首页与详情页存在重复的 launch 行为逻辑 | 后续维护动作文案或追踪逻辑时需双处同步 | 中 | 可考虑抽成共享 composable |
|
||||
|
||||
## 更新历史
|
||||
|
||||
| 日期 | 更新内容 | 触发来源 |
|
||||
|------|---------|---------|
|
||||
| 2026-04-11 | 初始创建,记录访客端详情页与前端测试基建落地情况 | executing-plans 完成 |
|
||||
56
design/context/user-profile.md
Normal file
56
design/context/user-profile.md
Normal file
@@ -0,0 +1,56 @@
|
||||
# 用户画像
|
||||
|
||||
## 基本信息
|
||||
|
||||
| 字段 | 内容 | 更新日期 |
|
||||
|------|------|---------|
|
||||
| 用户定位 | 高级开发者 | 2026-04-11 |
|
||||
| 技术背景 | Vue / Node.js 全栈开发,能直接指定页面与交互改动 | 2026-04-11 |
|
||||
| 首次记录 | 2026-04-11 | 2026-04-11 |
|
||||
| 最后更新 | 2026-04-11 | 2026-04-11 |
|
||||
|
||||
## 技术偏好
|
||||
|
||||
| 类型 | 偏好 | 备注 |
|
||||
|------|------|------|
|
||||
| 前端框架 | Vue | 当前项目直接基于 Vue 页面提出功能修改 |
|
||||
| 后端语言 | Node.js | 当前项目服务端为 NestJS |
|
||||
| 代码风格 | 简洁直接 | 偏向明确需求,不需要冗长解释 |
|
||||
|
||||
## 决策倾向
|
||||
|
||||
| 场景 | 倾向 | 表现 |
|
||||
|------|------|------|
|
||||
| 常规开发 | 偏质量优先 | 在可控范围内倾向补齐完整体验,如空状态和 404 |
|
||||
| 紧急情况 | 效率优先 | 倾向直接说明要加什么功能 |
|
||||
| 重构场景 | 中步迭代 | 先做增量功能,而不是整体推翻 |
|
||||
|
||||
## 风险偏好
|
||||
|
||||
- **技术选型**:适中
|
||||
- **重构决策**:中步迭代
|
||||
- **依赖引入**:最小依赖
|
||||
|
||||
## 交互风格
|
||||
|
||||
| 方面 | 偏好 | 说明 |
|
||||
|------|------|------|
|
||||
| 详细程度 | 简洁 | 更偏向短句和明确结论 |
|
||||
| 反馈频率 | 关键节点 | 适合在决策点确认 |
|
||||
| 解释深度 | 概要说明 | 不需要铺垫式解释 |
|
||||
| 问题形式 | 选择题 | 当前对话对数字选项响应直接 |
|
||||
|
||||
## 能力评估
|
||||
|
||||
| 能力领域 | 自评等级 | 备注 |
|
||||
|---------|---------|------|
|
||||
| 前端开发 | 高级 | 能明确提出页面形态与交互需求 |
|
||||
| 后端开发 | 中级 | 当前尚未直接表达更强偏好 |
|
||||
| 架构设计 | 中级 | 关注功能增量落地 |
|
||||
| 性能优化 | 中级 | 当前未体现特殊关注点 |
|
||||
|
||||
## 更新历史
|
||||
|
||||
| 日期 | 更新内容 | 触发场景 |
|
||||
|------|---------|---------|
|
||||
| 2026-04-11 | 初始创建,记录为高级开发者,偏好简洁和选择题沟通 | brainstorming 初次激活 |
|
||||
189
design/plans/2026-04-11-tool-manual-detail-page-plan.md
Normal file
189
design/plans/2026-04-11-tool-manual-detail-page-plan.md
Normal file
@@ -0,0 +1,189 @@
|
||||
# 用户手册详情页实施计划
|
||||
|
||||
**目标**:将访客端原有详情弹窗替换为基于 `slug` 的独立详情页,使 `description` 可以长期作为 Markdown 用户手册展示,并补齐直达访问、空内容、404 和长文阅读体验。
|
||||
|
||||
**架构**:本次为单一功能子系统改造,不创建纲领文件。后端先补齐按 `slug` 查询已发布工具的公开详情能力,再由前端新增公开详情页路由和页面组件,最后替换首页详情入口并完善长文阅读样式与测试。前端测试基建当前缺失,因此计划第一步先补齐 `Vitest + Vue Test Utils + jsdom`,确保后续页面改造遵循测试优先。
|
||||
|
||||
**技术栈**:Vue 3、vue-router、Vite、Vitest、Vue Test Utils、NestJS、Prisma、Jest、Supertest、marked、DOMPurify
|
||||
|
||||
---
|
||||
|
||||
## 文件结构
|
||||
|
||||
### 新建文件
|
||||
|
||||
- `client/vitest.config.js` - 前端测试配置,提供 Vue SFC 和 `jsdom` 运行环境
|
||||
注释需求:低优先级,配置项仅在非直观处补简短说明
|
||||
复杂度:低
|
||||
|
||||
- `client/src/test/setup.js` - 前端测试初始化,挂载全局匹配器、滚动和路由相关基础 mock
|
||||
注释需求:中优先级,需要说明全局 mock 的用途
|
||||
复杂度:中
|
||||
|
||||
- `client/src/utils/markdown-outline.js` - 提取 Markdown 标题、生成稳定锚点和目录结构
|
||||
注释需求:高优先级,需要为重复标题去重和锚点规范化逻辑添加说明
|
||||
复杂度:中
|
||||
|
||||
- `client/src/utils/markdown-outline.spec.js` - 验证目录提取、标题去重和无标题场景
|
||||
注释需求:低优先级
|
||||
复杂度:中
|
||||
|
||||
- `client/src/pages/ToolDetailPage.vue` - 公开详情页,负责按 `slug` 拉取详情、渲染摘要和 Markdown 手册、处理空状态/404/返回入口
|
||||
注释需求:高优先级,需要在状态流转和 launch 复用入口处补说明
|
||||
复杂度:高
|
||||
|
||||
- `client/src/pages/ToolDetailPage.spec.js` - 详情页组件测试,覆盖加载态、404、空内容、目录和主操作按钮
|
||||
注释需求:低优先级
|
||||
复杂度:高
|
||||
|
||||
- `client/src/App.spec.js` - 首页交互测试,覆盖详情按钮跳转和旧弹窗移除
|
||||
注释需求:低优先级
|
||||
复杂度:中
|
||||
|
||||
- `server/src/modules/tools/tools.service.spec.ts` - 后端服务单测,覆盖按 `slug` 查询详情的业务规则
|
||||
注释需求:低优先级
|
||||
复杂度:中
|
||||
|
||||
- `server/test/tools-detail.e2e-spec.ts` - 公开详情接口 e2e,覆盖成功命中和 404
|
||||
注释需求:中优先级,需要说明测试数据准备和清理
|
||||
复杂度:中
|
||||
|
||||
### 修改文件
|
||||
|
||||
- `client/package.json` - 增加前端测试脚本和测试依赖声明
|
||||
注释需求:低优先级
|
||||
复杂度:低
|
||||
|
||||
- `client/package-lock.json` - 锁定前端测试依赖版本
|
||||
注释需求:无
|
||||
复杂度:低
|
||||
|
||||
- `client/src/api.js` - 新增按 `slug` 获取详情的方法,复用现有错误和 launch 行为
|
||||
注释需求:中优先级,需要说明新接口和旧按 `id` 接口的职责差异
|
||||
复杂度:中
|
||||
|
||||
- `client/src/admin/router.js` - 增加公开详情页路由 `/tools/:slug`
|
||||
注释需求:低优先级
|
||||
复杂度:低
|
||||
|
||||
- `client/src/App.vue` - 移除详情弹窗状态和模板,将详情入口改为路由跳转
|
||||
注释需求:中优先级,需要说明首页仅负责列表和跳转,不再持有详情状态
|
||||
复杂度:高
|
||||
|
||||
- `client/src/style.scss` - 增加详情页布局、目录、空状态、404 和长文阅读样式
|
||||
注释需求:低优先级
|
||||
复杂度:高
|
||||
|
||||
- `client/src/admin/components/ToolFormDialog.vue` - 微调“工具简介”提示文案,明确其可承载 Markdown 手册内容
|
||||
注释需求:低优先级
|
||||
复杂度:低
|
||||
|
||||
- `server/src/modules/tools/tools.service.ts` - 抽出详情映射逻辑,新增按 `slug` 查询已发布工具详情的方法
|
||||
注释需求:高优先级,需要说明 `id` 与 `slug` 两套公开查询入口的职责分层
|
||||
复杂度:中
|
||||
|
||||
- `server/src/modules/tools/tools.controller.ts` - 新增按 `slug` 获取公开详情的接口
|
||||
注释需求:低优先级
|
||||
复杂度:低
|
||||
|
||||
### 测试文件
|
||||
|
||||
- `client/src/utils/markdown-outline.spec.js` - 验证 Markdown 目录提取和锚点生成规则
|
||||
- `client/src/pages/ToolDetailPage.spec.js` - 验证详情页数据状态和长文阅读体验
|
||||
- `client/src/App.spec.js` - 验证首页详情入口从弹窗切为路由跳转
|
||||
- `server/src/modules/tools/tools.service.spec.ts` - 验证按 `slug` 查询的业务规则
|
||||
- `server/test/tools-detail.e2e-spec.ts` - 验证公开详情接口路由行为
|
||||
|
||||
---
|
||||
|
||||
## 任务列表
|
||||
|
||||
### 任务 1:建立前端测试基建和 Markdown 目录工具
|
||||
|
||||
**文件**:
|
||||
- 创建:`client/vitest.config.js`
|
||||
- 创建:`client/src/test/setup.js`
|
||||
- 创建:`client/src/utils/markdown-outline.js`
|
||||
- 测试:`client/src/utils/markdown-outline.spec.js`
|
||||
- 修改:`client/package.json`
|
||||
- 修改:`client/package-lock.json`
|
||||
|
||||
- [ ] **步骤 1**:在 `client/package.json` 中增加 `test`、`test:run` 脚本和 `vitest`、`@vue/test-utils`、`jsdom` 等依赖声明;创建 `client/vitest.config.js`、`client/src/test/setup.js`;编写 `client/src/utils/markdown-outline.spec.js`,先描述标题提取、重复标题去重、无标题返回空目录的失败用例。
|
||||
- [ ] **步骤 2**:运行 `npm --prefix client install`;随后运行 `npm --prefix client run test:run -- client/src/utils/markdown-outline.spec.js`,预期输出为测试失败,原因是 `markdown-outline.js` 尚未实现或断言不满足。
|
||||
- [ ] **步骤 3**:创建 `client/src/utils/markdown-outline.js`,实现 `extractMarkdownOutline` 和稳定锚点生成逻辑,保证只提取正文标题并对重复标题追加序号。
|
||||
- [ ] **步骤 4**:再次运行 `npm --prefix client run test:run -- client/src/utils/markdown-outline.spec.js`,预期输出 `1 passed`,前端测试基建可用。
|
||||
|
||||
### 任务 2:实现后端按 `slug` 查询详情的服务层能力
|
||||
|
||||
**文件**:
|
||||
- 创建:`server/src/modules/tools/tools.service.spec.ts`
|
||||
- 修改:`server/src/modules/tools/tools.service.ts`
|
||||
|
||||
- [ ] **步骤 1**:编写 `server/src/modules/tools/tools.service.spec.ts`,覆盖已发布工具可按 `slug` 查询、未发布工具不可见、缺失工具抛出 404、详情映射字段与现有按 `id` 详情保持一致的失败测试。
|
||||
- [ ] **步骤 2**:运行 `npm --prefix server test -- --runTestsByPath src/modules/tools/tools.service.spec.ts`,预期输出为编译失败或测试失败,因为 `getToolDetailBySlug` 及共享映射尚未存在。
|
||||
- [ ] **步骤 3**:在 `server/src/modules/tools/tools.service.ts` 中抽出详情映射方法,新增 `getToolDetailBySlug(slug: string)`,查询条件限定为 `status=published`、`isDeleted=false`,并复用现有详情返回结构。
|
||||
- [ ] **步骤 4**:再次运行 `npm --prefix server test -- --runTestsByPath src/modules/tools/tools.service.spec.ts`,预期输出 `Test Suites: 1 passed`。
|
||||
|
||||
### 任务 3:补齐公开详情 `slug` 接口和后端 e2e
|
||||
|
||||
**文件**:
|
||||
- 创建:`server/test/tools-detail.e2e-spec.ts`
|
||||
- 修改:`server/src/modules/tools/tools.controller.ts`
|
||||
|
||||
- [ ] **步骤 1**:编写 `server/test/tools-detail.e2e-spec.ts`,准备一条已发布工具测试数据,定义 `GET /tools/slug/:slug` 成功返回详情和未知 `slug` 返回 404 的失败测试。
|
||||
- [ ] **步骤 2**:运行 `npm --prefix server run test:e2e -- --runTestsByPath test/tools-detail.e2e-spec.ts`,预期输出为 404 或断言失败,因为控制器路由尚未暴露该接口。
|
||||
- [ ] **步骤 3**:在 `server/src/modules/tools/tools.controller.ts` 中新增 `GET /tools/slug/:slug` 路由,调用 `toolsService.getToolDetailBySlug`;按需要调整 e2e 中的测试数据清理,避免污染现有数据。
|
||||
- [ ] **步骤 4**:再次运行 `npm --prefix server run test:e2e -- --runTestsByPath test/tools-detail.e2e-spec.ts`,预期输出 `1 passed` 或 `2 passed`,接口直达行为稳定。
|
||||
|
||||
### 任务 4:新增公开详情页路由、API 接入和页面状态
|
||||
|
||||
**文件**:
|
||||
- 创建:`client/src/pages/ToolDetailPage.vue`
|
||||
- 测试:`client/src/pages/ToolDetailPage.spec.js`
|
||||
- 修改:`client/src/api.js`
|
||||
- 修改:`client/src/admin/router.js`
|
||||
|
||||
- [ ] **步骤 1**:编写 `client/src/pages/ToolDetailPage.spec.js`,覆盖按路由 `slug` 拉取详情、加载态、404 提示、空内容提示、返回首页入口以及主操作按钮展示的失败测试。
|
||||
- [ ] **步骤 2**:运行 `npm --prefix client run test:run -- client/src/pages/ToolDetailPage.spec.js`,预期输出为模块不存在或多个断言失败,因为详情页组件、路由和新 API 方法尚未实现。
|
||||
- [ ] **步骤 3**:在 `client/src/api.js` 中新增 `fetchToolDetailBySlug(slug)`;在 `client/src/admin/router.js` 中增加公开路由 `/tools/:slug`;创建 `client/src/pages/ToolDetailPage.vue`,完成按 `slug` 加载数据、页面级加载/错误/404/空内容状态和返回入口,并复用现有 launch 行为。
|
||||
- [ ] **步骤 4**:再次运行 `npm --prefix client run test:run -- client/src/pages/ToolDetailPage.spec.js`,预期输出 `1 passed`,详情页基础行为成立。
|
||||
|
||||
### 任务 5:替换首页详情弹窗为路由跳转
|
||||
|
||||
**文件**:
|
||||
- 创建:`client/src/App.spec.js`
|
||||
- 修改:`client/src/App.vue`
|
||||
|
||||
- [ ] **步骤 1**:编写 `client/src/App.spec.js`,覆盖“详情”按钮改为跳转到 `/tools/:slug`、旧详情弹窗 DOM 不再渲染、首页仍保留概览弹窗的失败测试。
|
||||
- [ ] **步骤 2**:运行 `npm --prefix client run test:run -- client/src/App.spec.js`,预期输出为断言失败,因为首页仍然保留 `openDetailModal` 流程和旧弹窗模板。
|
||||
- [ ] **步骤 3**:修改 `client/src/App.vue`,移除 `detailModalOpen/detailLoading/detailError/detail` 等状态及弹窗模板,将详情按钮改为 `router.push` 或 `RouterLink` 跳转,并保留列表、筛选和概览弹窗逻辑不变。
|
||||
- [ ] **步骤 4**:再次运行 `npm --prefix client run test:run -- client/src/App.spec.js client/src/pages/ToolDetailPage.spec.js`,预期输出全部通过,首页到详情页的主链路打通。
|
||||
|
||||
### 任务 6:完善长文阅读体验、后台提示文案和整体验证
|
||||
|
||||
**文件**:
|
||||
- 修改:`client/src/style.scss`
|
||||
- 修改:`client/src/pages/ToolDetailPage.vue`
|
||||
- 修改:`client/src/pages/ToolDetailPage.spec.js`
|
||||
- 修改:`client/src/admin/components/ToolFormDialog.vue`
|
||||
|
||||
- [ ] **步骤 1**:扩展 `client/src/pages/ToolDetailPage.spec.js`,新增目录渲染、无标题时不显示目录、长文时保留清晰段落层级和返回入口的失败测试。
|
||||
- [ ] **步骤 2**:运行 `npm --prefix client run test:run -- client/src/pages/ToolDetailPage.spec.js`,预期输出为目录相关断言失败,因为页面尚未接入目录工具和阅读态样式。
|
||||
- [ ] **步骤 3**:修改 `client/src/pages/ToolDetailPage.vue` 和 `client/src/style.scss`,接入 `extractMarkdownOutline`、渲染目录导航、优化正文宽度/标题层级/锚点区块;同步修改 `client/src/admin/components/ToolFormDialog.vue` 的简介提示文案,明确其支持 Markdown 手册内容。
|
||||
- [ ] **步骤 4**:依次运行 `npm --prefix client run test:run -- client/src/utils/markdown-outline.spec.js client/src/pages/ToolDetailPage.spec.js client/src/App.spec.js`、`npm --prefix client run build`、`npm --prefix server test -- --runTestsByPath src/modules/tools/tools.service.spec.ts`、`npm --prefix server run test:e2e -- --runTestsByPath test/tools-detail.e2e-spec.ts`,预期输出均为通过,且客户端构建成功无报错。
|
||||
|
||||
---
|
||||
|
||||
## 执行顺序说明
|
||||
|
||||
1. 先补前端测试基建,否则后续页面任务无法按 TDD 执行。
|
||||
2. 后端先做服务层,再做控制器和 e2e,可减少路由级调试成本。
|
||||
3. 前端先完成详情页自身状态,再替换首页入口,避免“按钮先改了但页面未就绪”。
|
||||
4. 长文阅读体验放在最后收口,避免样式和目录逻辑反复返工。
|
||||
|
||||
## 风险提示
|
||||
|
||||
- 前端当前没有测试依赖,任务 1 会同时引入测试脚手架和锁文件变更。
|
||||
- `App.vue` 体量较大,任务 5 需要谨慎删除旧弹窗状态,避免误伤概览弹窗和列表筛选逻辑。
|
||||
- `slug` 接口与按 `id` 接口将同时存在,任务 2 和任务 3 需要确保两者返回结构一致,避免前端出现双标准。
|
||||
- e2e 测试需要自行准备和清理工具数据,避免依赖现有 seed 内容导致测试不稳定。
|
||||
44
design/session-state.md
Normal file
44
design/session-state.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:长文阅读体验、后台提示文案和整体验证。
|
||||
100
design/specs/2026-04-11-tool-manual-detail-page-design.md
Normal file
100
design/specs/2026-04-11-tool-manual-detail-page-design.md
Normal file
@@ -0,0 +1,100 @@
|
||||
# 用户手册详情页设计规格
|
||||
|
||||
## 概述
|
||||
|
||||
当前访客端首页通过弹窗展示工具详情,适合快速浏览,但不适合作为稳定的用户手册阅读入口。现有工具数据中的 `description` 字段已经支持 Markdown 渲染,因此可以直接复用它承载用户手册内容,无需新增数据库字段。
|
||||
|
||||
本次设计目标是在现有公开站点中增加一个正式的详情页入口,替换原有弹窗。详情页使用工具的 `slug` 作为公开访问标识,支持站内路由直达、长篇 Markdown 阅读、空内容状态、404 状态和明确的返回入口,使其可以长期承担“工具介绍 + 用户手册”的双重职责。
|
||||
|
||||
## 目标定位
|
||||
|
||||
- **主要用户**:普通访客
|
||||
- **使用场景**:访客从工具列表点击“详情”进入独立页面,阅读工具说明、能力介绍和 Markdown 格式的用户手册;也支持用户直接访问详情页链接
|
||||
|
||||
## 约束条件
|
||||
|
||||
- **技术限制**:前端基于 Vue 3 + vue-router,主站与管理端共用同一路由实例;后端基于 NestJS + Prisma;Markdown 渲染复用现有 `marked + DOMPurify` 能力;用户手册内容先复用 `Tool.description`
|
||||
- **时间限制**:本轮以增量改造为主,不引入新的内容模型,不重做管理端工具编辑流程
|
||||
- **资源限制**:仅在现有项目代码结构内完成,避免增加新依赖或引入第二套公开站点入口
|
||||
|
||||
## 成功标准
|
||||
|
||||
- [ ] 访客在首页点击“详情”后进入新的站内详情页,不再弹出旧弹窗
|
||||
- [ ] 详情页路由使用 `slug`,可通过 URL 直达访问
|
||||
- [ ] 详情页能够稳定展示 `description` Markdown、基础元信息和功能点,适合作为长期手册页面
|
||||
- [ ] 当工具不存在时展示明确的 404 状态;当 `description` 为空时展示清晰的空内容提示
|
||||
- [ ] 对于较长 Markdown 内容,页面具备目录感和良好的阅读体验,用户可以快速回到列表或继续执行“打开网页/下载”操作
|
||||
|
||||
## 架构设计
|
||||
|
||||
### 系统结构
|
||||
|
||||
本次改造保持单一公开站点结构不变,在现有 `vue-router` 中新增公开详情路由。前端首页仍负责列表、筛选和跳转;详情页负责根据 `slug` 拉取数据并渲染完整内容。后端在保留现有按 `id` 获取详情接口的前提下,新增按 `slug` 查询的公开详情接口,避免影响既有逻辑,并为长期公开链接提供稳定入口。
|
||||
|
||||
详情页信息结构分为三层:
|
||||
|
||||
1. 页面顶部:返回列表、工具名称、分类、更新时间、主操作按钮
|
||||
2. 信息摘要区:评分、访问方式、下载/访问次数、版本、标签、核心能力
|
||||
3. 手册正文区:将 `description` 作为 Markdown 正文渲染,并为长文提供标题导航或可跳转的章节锚点
|
||||
|
||||
### 组件划分
|
||||
|
||||
| 组件 | 职责 | 依赖 |
|
||||
|------|------|------|
|
||||
| `client/src/App.vue` | 保留首页列表、筛选和分页;将“详情”按钮改为路由跳转;移除旧详情弹窗状态与模板 | `vue-router`, `client/src/api.js` |
|
||||
| `client/src/pages/ToolDetailPage.vue` | 详情页容器;根据 `slug` 拉取详情数据;处理加载、404、空内容、长文阅读与返回入口 | `vue-router`, `client/src/api.js`, `client/src/utils/markdown.js` |
|
||||
| `client/src/api.js` | 新增按 `slug` 获取详情的方法;复用已有错误处理与启动行为 | Axios |
|
||||
| `client/src/utils/markdown.js` | 继续负责安全渲染 Markdown;可扩展标题提取或锚点处理,支持长文目录体验 | `marked`, `DOMPurify` |
|
||||
| `client/src/admin/components/ToolFormDialog.vue` | 保持数据录入入口不变;若实施时顺手优化文案,可将简介提示改为更明确的“支持手册 Markdown” | Element Plus |
|
||||
| `server/src/modules/tools/tools.controller.ts` | 新增按 `slug` 获取公开详情的接口 | `ToolsService` |
|
||||
| `server/src/modules/tools/tools.service.ts` | 新增按 `slug` 查询已发布工具详情的方法,并复用现有详情映射逻辑 | Prisma |
|
||||
|
||||
## 数据流
|
||||
|
||||
首页进入详情页的数据流如下:
|
||||
|
||||
1. 首页加载工具列表,列表项已带有 `id` 和 `slug`
|
||||
2. 用户点击“详情”按钮
|
||||
3. 前端通过路由跳转到 `/tools/:slug`
|
||||
4. 详情页组件从路由参数读取 `slug`
|
||||
5. 前端调用新的公开接口,例如 `GET /api/v1/tools/slug/:slug`
|
||||
6. 后端按 `slug + status=published + isDeleted=false` 查询工具
|
||||
7. 查询成功后返回详情数据,包括 `description`、`features`、分类、评分、访问方式、访问量/下载量、版本等
|
||||
8. 前端渲染详情页摘要区和 Markdown 正文;若正文存在标题,则生成目录锚点或章节导航
|
||||
9. 用户可从详情页返回首页,或继续点击“打开网页/下载”执行现有 launch 流程
|
||||
|
||||
长文阅读的数据处理建议如下:
|
||||
|
||||
1. 详情页获取 Markdown 原文
|
||||
2. 使用现有 Markdown 解析能力渲染 HTML
|
||||
3. 在渲染前或渲染时提取标题层级,生成页面内目录
|
||||
4. 为标题生成稳定锚点,支持目录点击跳转
|
||||
5. 若正文无标题,则不显示目录,保留清晰的文章排版和回顶能力
|
||||
|
||||
## 错误处理
|
||||
|
||||
| 错误类型 | 处理方式 |
|
||||
|----------|----------|
|
||||
| 详情接口加载中 | 展示页面级骨架或加载态,不显示旧弹窗 |
|
||||
| `slug` 对应工具不存在 | 展示 404 状态页,包含返回首页入口 |
|
||||
| 工具存在但 `description` 为空 | 展示“暂未提供用户手册”空状态,同时仍保留工具摘要信息和主操作按钮 |
|
||||
| 接口请求失败 | 展示页面级错误提示,提供重试操作和返回首页入口 |
|
||||
| Markdown 内容很长 | 启用目录/锚点导航、限制正文宽度、保证标题层级和段落间距,避免整页难以浏览 |
|
||||
| 从详情页执行打开或下载失败 | 复用现有 `launchTool` 和错误提示逻辑,不在详情页定义第二套行为 |
|
||||
|
||||
## 测试策略
|
||||
|
||||
- **单元测试**:校验按 `slug` 查询详情的服务方法;校验 Markdown 标题提取或目录生成逻辑;校验空内容和 404 的状态判断
|
||||
- **集成测试**:覆盖公开详情接口按 `slug` 返回已发布工具;覆盖不存在 `slug` 时返回 404;覆盖详情页直达访问、列表跳转访问和返回行为
|
||||
- **验收标准**:从首页点击“详情”可稳定进入 `/tools/:slug`;直达链接可用;长篇 Markdown 有清晰阅读结构;空内容、404、请求失败均有明确页面反馈;旧详情弹窗已移除
|
||||
|
||||
## 决策记录
|
||||
|
||||
| 决策 | 理由 | 影响 |
|
||||
|------|------|------|
|
||||
| 详情页采用站内路由而不是新标签页 | 用户明确要求站内跳转,且可形成连续阅读路径 | 前端需新增公开详情路由 |
|
||||
| 详情页公开地址使用 `slug` | `slug` 已存在且唯一,适合长期公开链接和分享 | 后端需新增按 `slug` 查询接口,前端详情页按 `slug` 加载 |
|
||||
| 用户手册先复用 `description` 字段 | 当前已支持 Markdown,避免新增数据库字段和后台复杂度 | 本轮不做数据模型迁移 |
|
||||
| 旧弹窗详情被新详情页替换 | 用户希望详情入口统一,避免双入口维护 | 首页需移除弹窗模板和相关状态 |
|
||||
| 长文阅读加入目录感设计 | 用户明确要求处理超长 Markdown 的阅读体验 | 详情页和 Markdown 工具层需要支持标题导航或锚点 |
|
||||
| 现有按 `id` 的详情接口保留,新增长期用的 `slug` 接口 | 兼容已有内部调用,减少回归风险 | 后端存在两个公开详情查询入口,但职责清晰 |
|
||||
Reference in New Issue
Block a user