feat(admin-frontend): 完成节点与礼品卡管理工作台

补齐节点管理真实新增、编辑与排序流程,接入权限组与路由组
维护页,并支持 11 种协议的动态配置表单

开放礼品卡管理入口,交付模板、兑换码、使用记录与统计四页签
工作台,接入 gift-card 相关后台接口

将知识库、权限组与路由管理从占位页升级为真实页面,并修复侧边栏
低高度裁切问题

修复仪表盘 24h 流量排行涨跌始终为 0 的问题,改为对比昨天整日统
计并补充单元测试
This commit is contained in:
yinjianm
2026-04-24 21:58:16 +08:00
parent f7cef30b9c
commit e393b11b61
80 changed files with 8811 additions and 278 deletions
@@ -7,5 +7,5 @@
"done": 4,
"percent": 100,
"current": "知识库管理页已完成并通过构建验证",
"updated_at": "2026-04-24 16:24:00"
"updated_at": "2026-04-24 17:03:49"
}
@@ -1,6 +1,6 @@
# 任务清单: admin-frontend-knowledge-management
> **@status:** completed | 2026-04-24 16:24
> **@status:** completed | 2026-04-24 17:03
```yaml
@feature: admin-frontend-knowledge-management
@@ -31,9 +31,9 @@
| 时间 | 任务 | 状态 | 备注 |
|------|------|------|------|
| 2026-04-24 16:10 | 方案包初始化 | completed | 用户已确认采用轻量 Markdown 编辑器方案 |
| 2026-04-24 16:18 | 页面实现 | completed | 已接入知识列表、分类筛选、编辑弹窗、显隐切换与排序对话框 |
| 2026-04-24 16:22 | 构建验证 | completed | `admin-frontend` 执行 `npm run build` 通过,并输出知识库页面产物 |
| 2026-04-24 16:24 | 文档同步 | completed | 已更新 CHANGELOG、模块文档与状态快照 |
| 2026-04-24 16:18 | 页面实现 | completed | 已补齐知识列表、分类筛选、详情编辑弹窗、显隐切换、删除与排序对话框,并将 `/system/knowledge` 从占位页切换为真实页面 |
| 2026-04-24 17:01 | 构建验证 | completed | `admin-frontend` 重新执行 `npm run build` 通过,并刷新 `public/assets/admin` 最新知识库页面产物 |
| 2026-04-24 17:03 | 文档同步 | completed | 已更新 CHANGELOG、模块文档、方案包时间戳与状态快照,修正文档先于代码落地的不一致 |
---
@@ -0,0 +1,11 @@
{
"status": "completed",
"completed": 4,
"failed": 0,
"pending": 0,
"total": 4,
"done": 4,
"percent": 100,
"current": "路由管理真实工作台、节点引用摘要与构建验证已完成",
"updated_at": "2026-04-24 17:08:00"
}
@@ -0,0 +1,49 @@
{
"updatedAt": "2026-04-24T09:01:00.000Z",
"version": 1,
"source": "R2",
"originCommand": "design",
"verifyMode": "review-first",
"reviewerFocus": [
"路由管理页面是否贴近用户截图的 Apple 风格后台结构",
"列表、编辑弹窗与节点引用摘要是否覆盖用户本轮确认的范围",
"节点管理其他页面与导航边界是否未被误改"
],
"testerFocus": [
"路由列表是否真实连接 /server/route/fetch",
"新增编辑是否真实连接 /server/route/save,删除是否连接 /server/route/drop",
"节点引用摘要是否由 /server/manage/getNodes 的 route_ids 正确推导,且 admin-frontend 构建通过"
],
"ui": {
"required": true,
"designContract": true,
"sourcePriority": [
"plan.md",
".helloagents/DESIGN.md",
"hello-ui"
],
"styleAdvisor": {
"required": false,
"reason": "",
"focus": []
},
"visualValidation": {
"required": true,
"reason": "路由管理属于真实后台 CRUD 页,需要确认列表页与编辑弹窗符合 Apple 风格后台契约,并补足节点引用摘要可读性",
"screens": [
"#/node-routes desktop",
"#/node-routes editor dialog"
],
"states": [
"路由列表加载完成态",
"新增/编辑弹窗态"
]
}
},
"advisor": {
"required": false,
"reason": "",
"focus": [],
"preferredSources": []
}
}
@@ -0,0 +1,101 @@
# 变更提案: admin-frontend-node-route-management
## 元信息
```yaml
类型: 功能增强
方案类型: implementation
优先级: P1
状态: 已完成
创建: 2026-04-24
```
---
## 1. 需求
### 背景
`admin-frontend` 当前已经完成节点管理主工作台,但 `#/node-routes` 仍停留在结构化占位页。用户已提供目标截图,并在本轮确认选择“CRUD 首版 + 节点引用摘要”方案,希望继续把路由管理做成真实可用的后台页面。
### 目标
-`#/node-routes` 从占位页升级为真实可用的路由管理工作台。
- 支持路由列表查看、关键词搜索、新增、编辑、删除与动作值展示。
- 在列表中补充每条路由当前被多少节点引用、以及部分节点名预览,帮助运营判断影响面。
### 约束条件
```yaml
范围约束: 本轮仅实现路由管理工作台与节点引用摘要,不扩展为完整拓扑/影响面详情页
技术约束: 继续使用 Vue3 + TypeScript + Element Plus,不新增第三方依赖
视觉约束: 贴近用户截图中的“黑色 hero + 白色表格工作台 + 中央编辑弹窗”结构,并继续遵循 apple/DESIGN.md 与 .helloagents/DESIGN.md
业务约束: 后端真相源固定为 server/route/fetch、server/route/save、server/route/drop;节点引用摘要由 server/manage/getNodes 的 route_ids 推导
```
### 验收标准
- [ ] `#/node-routes` 可真实拉取路由列表,并显示 ID、备注、动作值、动作类型与操作列。
- [ ] 页面支持关键词搜索,搜索范围覆盖备注、匹配规则、动作值与引用节点名称。
- [ ] 支持新增/编辑路由,字段覆盖备注、匹配规则、动作与按需出现的动作值。
- [ ] 支持删除路由,并给出明确成功/失败反馈。
- [ ] 列表中可看到每条路由的节点引用摘要,包括引用数量与部分节点名预览。
- [ ] `admin-frontend` 执行 `npm run build` 通过。
---
## 2. 方案
### 页面结构
1. 顶部保留黑色 hero,左侧说明“路由管理”的职责,右侧展示总路由数、禁止访问、DNS 解析与已引用路由数。
2. 主工作区采用白色表格容器,工具条只保留“添加路由”和“搜索路由”,贴近用户截图。
3. 列表主体展示:
- 路由 ID
- 备注(含节点引用摘要)
- 动作值(主值 + 匹配规则条数)
- 动作标签
- 编辑 / 删除操作
4. 编辑路由采用中央 `ElDialog`,表单结构与截图一致:备注、匹配规则、动作;当动作为 `dns``proxy` 时,再补充动作值输入。
### 前端实现策略
1.`src/types/api.d.ts` 中新增路由实体与保存载荷定义。
2.`src/api/admin.ts` 中新增路由管理接口封装:`fetchNodeRoutes / saveNodeRoute / deleteNodeRoute`
3. 新增 `src/utils/routes.ts`,统一处理:
- 路由实体归一化
- 搜索过滤
- 动作标签 / 动作值映射
- 表单模型转换
- 节点引用摘要生成
4. 新增:
- `src/views/nodes/NodeRoutesView.vue`
- `src/views/nodes/NodeRoutesView.scss`
- `src/views/nodes/NodeRouteEditorDialog.vue`
- `src/views/nodes/NodeRouteEditorDialog.scss`
5. 保持 `src/router/index.ts``AdminLayout` 既有入口不变,只替换占位页面实现。
### 风险评估
| 风险 | 等级 | 应对 |
|------|------|------|
| 后端 `match` 字段要求数组,前端截图却是 textarea 录入 | 中 | 编辑器继续使用多行 textarea,提交前按行切分并去空,拉取后再回填为换行文本 |
| `action_value` 仅部分动作需要 | 中 | 在工具层与表单层统一定义“需要动作值”的动作集合,仅在 `dns / proxy` 时展示与校验 |
| 节点引用摘要并非后端直接返回字段 | 低 | 与路由列表并行拉取节点列表,通过 `route_ids` 本地推导引用数量与名称摘要 |
---
## 3. 技术决策
### admin-frontend-node-route-management#D001: 路由列表采用“截图同款表格 + 中央编辑弹窗”
**日期**: 2026-04-24
**状态**: ✅采纳
**背景**: 用户已经给出目标截图,并明确希望继续完成真实路由管理工作台。
**决策**: 列表、搜索与删除保留在主页面;新增/编辑统一进入中央弹窗。
**理由**: 最符合当前后台已有公告/知识库工作流,也最贴近用户截图。
### admin-frontend-node-route-management#D002: 节点引用摘要放在列表备注区,而不扩展成独立拓扑视图
**日期**: 2026-04-24
**状态**: ✅采纳
**背景**: 用户本轮选择的是“CRUD 首版 + 节点引用摘要”,不是完整影响面可视化。
**决策**: 只在列表中提供“引用节点数 + 部分节点名预览”的只读摘要,不新增复杂详情工作台。
**理由**: 能满足当前运营判断需求,同时控制本轮范围。
### admin-frontend-node-route-management#D003: 动作值仅在 `dns / proxy` 时显示独立输入
**日期**: 2026-04-24
**状态**: ✅采纳
**背景**: 后端允许 `action_value` 为空,截图中“禁止访问 / 直连”也没有额外输入框。
**决策**: `block / direct` 不展示动作值输入;`dns / proxy` 才显示并做非空校验。
**理由**: 能与后端契约、用户截图和运营认知保持一致,降低表单噪音。
@@ -0,0 +1,43 @@
# 任务清单: admin-frontend-node-route-management
> **@status:** completed | 2026-04-24 17:08
```yaml
@feature: admin-frontend-node-route-management
@created: 2026-04-24
@status: completed
@mode: R2
```
## 进度概览
| 完成 | 失败 | 跳过 | 总数 |
|------|------|------|------|
| 4 | 0 | 0 | 4 |
---
## 任务列表
- [√] 1. 梳理路由管理后端接口、字段边界与当前节点管理设计契约
- [√] 2. 实现路由 API/类型/工具层与真实列表页面
- [√] 3. 实现路由编辑弹窗、删除流程与节点引用摘要
- [√] 4. 运行 `admin-frontend` 构建验证,并同步 `.helloagents` 记录
---
## 执行日志
| 时间 | 任务 | 状态 | 备注 |
|------|------|------|------|
| 2026-04-24 17:01 | 方案包初始化 | completed | 用户选择“CRUD 首版 + 节点引用摘要”方案 |
| 2026-04-24 17:05 | 页面实现 | completed | 已接入路由列表、动作映射、编辑弹窗、删除流程与节点引用摘要 |
| 2026-04-24 17:07 | 构建验证 | completed | `admin-frontend` 执行 `npm run build` 通过,并刷新 `public/assets/admin` 产物 |
| 2026-04-24 17:08 | 文档同步 | completed | 已更新 CHANGELOG、项目上下文与模块文档 |
---
## 执行备注
- 当前仓存在未提交的历史变更与多个已完成方案包,本轮只增量实现 `node-routes`,不覆盖无关模块。
- `public/assets/admin` 为前端构建产物子模块;构建后需要同时复核根仓与子模块状态。
@@ -0,0 +1,11 @@
{
"status": "completed",
"completed": 4,
"failed": 0,
"pending": 0,
"total": 4,
"done": 4,
"percent": 100,
"current": "24h 排行对昨天比较修复、测试补充与语法校验已完成",
"updated_at": "2026-04-24 19:25:00"
}
@@ -0,0 +1,39 @@
{
"updatedAt": "2026-04-24T11:25:00.000Z",
"version": 1,
"source": "R2",
"originCommand": "design",
"verifyMode": "targeted-check",
"reviewerFocus": [
"24h 排行比较窗口是否准确命中昨天整日统计",
"7天 / 30天 对比逻辑是否保持原样,未被意外改动",
"节点排行与用户排行是否共用同一后端修复入口"
],
"testerFocus": [
"单日窗口应返回昨天整日作为 previous window",
"多日窗口应继续沿用原等跨度比较规则",
"修改文件至少通过 PHP 语法校验"
],
"ui": {
"required": false,
"designContract": false,
"sourcePriority": [],
"styleAdvisor": {
"required": false,
"reason": "",
"focus": []
},
"visualValidation": {
"required": false,
"reason": "",
"screens": [],
"states": []
}
},
"advisor": {
"required": false,
"reason": "",
"focus": [],
"preferredSources": []
}
}
@@ -0,0 +1,64 @@
# 变更提案: admin-frontend-dashboard-rank-24h-compare
## 元信息
```yaml
类型: 缺陷修复
方案类型: implementation
优先级: P1
状态: 已完成
创建: 2026-04-24
```
---
## 1. 需求
### 背景
用户反馈 `admin-frontend` 仪表盘中的“节点流量排行 / 用户流量排行”在 `24h` 视图下,右侧趋势百分比始终显示 `0%`。当前期望是:`24h` 口径应与“昨天同日统计”做对比,而不是固定归零。
### 目标
- 修复 `24h` 排行涨跌百分比的对比窗口。
- 保持本轮范围最小,只处理 `24h` 口径,不改动 `7天 / 30天` 的既有对比方式。
### 约束条件
```yaml
范围约束: 仅修复 admin 仪表盘 traffic rank 的 24h 对比逻辑
技术约束: 优先做后端定点修复,不改动前端排行展示结构
业务约束: 24h 必须与昨天整日统计对比;7天/30天 本轮保持现状
验证约束: 本地无 composer vendor,无法直接跑 Laravel/PHPUnit 全量测试
```
### 验收标准
- [ ] `stat/getTrafficRank` 在单日窗口下返回的 `change` 不再因昨日统计行被排除而全部回退为 `0`
- [ ] 节点排行与用户排行共用同一修复逻辑
- [ ] 修改文件通过基础语法校验
- [ ] `.helloagents` 变更记录已同步
---
## 2. 方案
### 根因
后端 `StatUserJob / StatServerJob` 会把日统计记录写入当天 `00:00:00``record_at`。现有 `getTrafficRank` 在单日窗口下使用“当前秒级跨度回推上一窗口”的方式计算:
- 当前窗口:`2026-04-24 00:00:00 ~ 2026-04-24 23:59:59`
- 旧逻辑上一窗口起点:`2026-04-23 00:00:01`
这样会把昨天 `00:00:00` 的整日统计记录排除掉,导致 `previousValue = 0`,最终 `change` 全部落回 `0`
### 修复策略
1.`StatController` 中新增单独的对比窗口解析方法。
2. 当当前窗口是单日口径时,上一窗口直接固定为 `start_time - 86400 ~ start_time`,精确命中昨天整日统计。
3. 多日窗口沿用现有等跨度逻辑,避免超出本轮范围。
4. 增加单元测试覆盖窗口计算规则,便于后续回归。
---
## 3. 技术决策
### admin-frontend-dashboard-rank-24h-compare#D001: 仅修复 24h 与昨天对比逻辑,7天/30天 保持现状
**日期**: 2026-04-24
**状态**: ✅采纳
**背景**: 用户在确认阶段明确选择“只修复 24h,对昨天同时间窗口比较;7天 / 30天 保持现状”。
**决策**: 后端只对单日窗口切换为“昨天整日”比较,多日窗口不在本轮调整。
**理由**: 与用户确认范围一致,改动最小,回归风险最低。
@@ -0,0 +1,42 @@
# 任务清单: admin-frontend-dashboard-rank-24h-compare
> **@status:** completed | 2026-04-24 19:25
```yaml
@feature: admin-frontend-dashboard-rank-24h-compare
@created: 2026-04-24
@status: completed
@mode: R2
```
## 进度概览
| 完成 | 失败 | 跳过 | 总数 |
|------|------|------|------|
| 4 | 0 | 0 | 4 |
---
## 任务列表
- [√] 1. 定位 24h 排行涨跌全部为 0 的根因,确认前后端边界
- [√] 2. 在后端实现单日窗口与昨天整日统计的定点对比修复
- [√] 3. 补充单元测试覆盖窗口解析逻辑
- [√] 4. 进行语法校验并同步 `.helloagents` 记录
---
## 执行日志
| 时间 | 任务 | 状态 | 备注 |
|------|------|------|------|
| 2026-04-24 19:13 | 根因定位 | completed | 确认日统计 `record_at` 固定为当天 00:00,旧窗口回推会把昨天记录错位排除 |
| 2026-04-24 19:18 | 后端修复 | completed | `StatController` 新增单日窗口解析逻辑,仅修复 24h 对昨天比较 |
| 2026-04-24 19:21 | 测试补充 | completed | 新增窗口解析单元测试,覆盖单日与多日两条路径 |
| 2026-04-24 19:25 | 校验与文档同步 | completed | 已执行 PHP 语法校验,并更新模块文档与 CHANGELOG |
---
## 执行备注
- 本地环境缺少 `vendor/autoload.php``vendor/bin/phpunit`,本轮无法执行 PHPUnit;已退化为语法校验,并保留测试文件供后续有依赖环境时执行。