feat: batch update - gift card breakdown spec, backend APIs, miniprogram pages, ETL finance recharge, docs & migrations

This commit is contained in:
Neo
2026-03-20 01:43:48 +08:00
parent 075caf067f
commit 79f9a0e1da
437 changed files with 118603 additions and 976 deletions

View File

@@ -0,0 +1,147 @@
# notes 页面数据来源排查
> 排查日期2026-03-18
> 页面路径pages/notes/notes
> 源文件notes.ts / notes.wxml / notes.wxss / notes.json
## 概览
| 分类 | 数量 | 说明 |
|------|------|------|
| Mock 数据 | 6 个字段 | 全部列表数据来自 `mockNotes`,无真实 API |
| 硬编码数据 | 5 处 | `statusBarHeight` 默认值、`setTimeout` 延迟、Modal 文案等 |
| 已对接 API | 0 个接口 | 页面尚未对接任何后端 API |
| 前端计算/派生 | 3 个字段 | `pageState``timeLabel``NoteDisplay` 扩展 |
| 路由参数 | 0 个 | `onLoad` 未读取 `options` |
| WXML 硬编码文案 | 5 处 | 加载/错误/空态/底部提示等 UI 文案 |
---
## 一、Mock 数据
### 1.1 数据源:`mockNotes`mock-data.ts
| 序号 | 字段 | 类型 | 说明 | 联调替换 API |
|------|------|------|------|-------------|
| 1 | `id` | `string` | 备注唯一 ID | `GET /api/xcx/notes` 返回 |
| 2 | `content` | `string` | 备注正文 | 同上 |
| 3 | `tagType` | `'customer' \| 'coach'` | 标签类型(客户/助教) | 同上 |
| 4 | `tagLabel` | `string` | 标签文案,如"客户:王先生" | 同上 |
| 5 | `createdAt` | `string` | 创建时间,格式 `YYYY-MM-DD HH:mm` | 同上 |
| 6 | `score` | `number \| undefined` | 满意度评分 0-10类型定义存在但 mock 数据未使用) | 同上 |
- 引用方式:`import { mockNotes } from '../../utils/mock-data'`notes.ts 第 1 行)
- mock 数据共 12 条,模拟 H5 原型 `notes.html` 中的备注列表
- `Note` 接口在 mock-data.ts 中被定义了两次(第 2 次覆盖第 1 次),第 2 次定义不含 `score` 字段
### 1.2 Mock 调用链
```
notes.ts → loadData()
→ mockNotes.map(n => ({ ...n, timeLabel: formatRelativeTime(n.createdAt) }))
→ setData({ notes, pageState })
```
`setTimeout(…, 400)` 模拟网络延迟notes.ts 第 28 行)。
---
## 二、硬编码数据
| 序号 | 字段/值 | 当前值 | 应改为 | 风险 | 所在位置 |
|------|---------|--------|--------|------|----------|
| 1 | `statusBarHeight` | `20`(默认值) | `wx.getWindowInfo().statusBarHeight` 已在 `onLoad` 中获取20 仅为 fallback | 🟢 低 | notes.ts 第 17 行 |
| 2 | `setTimeout` 延迟 | `400` ms | 删除,改为真实 API 异步调用 | 🟡 中 | notes.ts 第 28 行 |
| 3 | Modal `title` | `'删除备注'` | 可保留UI 文案),或走 i18n | 🟢 低 | notes.ts 第 56 行 |
| 4 | Modal `content` | `'确定要删除这条备注吗?删除后无法恢复。'` | 可保留UI 文案),或走 i18n | 🟢 低 | notes.ts 第 57 行 |
| 5 | Modal `confirmColor` | `'#e34d59'` | 应统一走设计系统色值变量 | 🟢 低 | notes.ts 第 58 行 |
---
## 三、已对接 API
**无。** 页面当前 0 个真实 API 调用。
代码中的 TODO 注释notes.ts 第 30 行):
```
// TODO: 替换为真实 API 调用 GET /api/xcx/notes
```
### 需要对接的 API 清单
| 序号 | 操作 | 预期 API | 方法 | 说明 |
|------|------|----------|------|------|
| 1 | 加载备注列表 | `GET /api/xcx/notes` | GET | 替换 `mockNotes`,支持分页 |
| 2 | 删除备注 | `DELETE /api/xcx/notes/{noteId}` | DELETE | 当前仅前端 filter 删除,未持久化 |
| 3 | 下拉刷新 | 同接口 1 | GET | `onPullDownRefresh` 已有骨架 |
---
## 四、前端计算/派生数据
| 序号 | 字段 | 计算逻辑 | 所在位置 |
|------|------|----------|----------|
| 1 | `pageState` | 根据数据加载结果派生:`'loading'``'normal'` / `'empty'` / `'error'` | notes.ts 第 16/27/33/37 行 |
| 2 | `timeLabel` | `formatRelativeTime(n.createdAt)` — 将 ISO 时间转为相对时间文案(刚刚/N分钟前/MM-DD 等) | notes.ts 第 32 行 |
| 3 | `NoteDisplay` | 扩展 `Note` 接口,附加 `timeLabel: string` | notes.ts 第 8-10 行 |
### `formatRelativeTime` 规则utils/time.ts
| 时间差 | 输出 |
|--------|------|
| < 120s | 刚刚 |
| 2min ~ 59min | N分钟前 |
| 1h ~ 23h | N小时前 |
| 1d ~ 3d | N天前 |
| > 3d 同年 | MM-DD |
| > 3d 跨年 | YYYY-MM-DD |
---
## 五、路由参数
`onLoad()` 未读取任何 `options` 参数。
当前页面作为独立备注列表页,不依赖路由传参。联调时需确认:
- 是否需要按客户 ID 过滤备注(`?customerId=xxx`
- 是否需要按任务 ID 过滤备注(`?taskId=xxx`
---
## 六、WXML 硬编码文案
| 序号 | 文案 | 位置 | 建议 |
|------|------|------|------|
| 1 | `加载中...` | `g-toast-loading-text`wxml 第 6 行) | 全局加载组件文案,可保留 |
| 2 | `😵` | `error-icon`wxml 第 12 行) | emoji 作为错误图标 |
| 3 | `加载失败,请重试` | `error-text`wxml 第 13 行) | 可保留 |
| 4 | `重新加载` | `retry-btn-text`wxml 第 15 行) | 可保留 |
| 5 | `暂无备注记录` | `t-empty description`wxml 第 22 行) | 可保留 |
| 6 | `— 已加载全部记录 —` | `footer-text`wxml 第 40 行) | 联调后需改为分页加载逻辑,此文案需动态化 |
---
## 七、组件依赖
| 组件 | 来源 | 说明 |
|------|------|------|
| `t-icon` | tdesign-miniprogram | 删除图标 |
| `t-loading` | tdesign-miniprogram | 加载动画 |
| `t-empty` | tdesign-miniprogram | 空态占位 |
| `ai-float-button` | `/components/ai-float-button/` | AI 悬浮按钮(仅正常态显示) |
| `dev-fab` | `/components/dev-fab/` | 开发调试按钮(全局) |
---
## 八、联调 TODO
- [ ] **对接备注列表 API**`GET /api/xcx/notes` 替换 `mockNotes`,移除 `import { mockNotes } from '../../utils/mock-data'`
- [ ] **对接删除 API**`DELETE /api/xcx/notes/{noteId}` 替换前端 filter 逻辑,增加失败回滚
- [ ] **移除 `setTimeout` 模拟延迟**:改为真实异步请求
- [ ] **确认路由参数**:是否需要 `customerId` / `taskId` 过滤
- [ ] **分页支持**:当前一次性加载全部,联调时需确认是否需要分页/无限滚动
- [ ] **底部文案动态化**`— 已加载全部记录 —` 需根据分页状态切换为"加载更多"/"已加载全部"
- [ ] **删除确认交互**:当前仅前端删除 + Toast需确认后端删除成功后再更新 UI
- [ ] **错误处理增强**`loadData` 的 catch 仅设置 `pageState: 'error'`,需增加具体错误提示
- [ ] **清理 mock-data.ts 中 `Note` 重复定义**:接口定义了两次,联调时统一为后端返回类型
- [ ] **`confirmColor` 统一**`#e34d59` 应走设计系统变量,避免散落硬编码色值