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,207 @@
# board-coach 页面数据来源排查
> 排查日期2026-03-18
> 页面路径pages/board-coach/board-coach
> 排查范围board-coach.ts / board-coach.wxml / board-coach.wxss / board-coach.json + 引用工具函数
## 概览
| 分类 | 数量 | 说明 |
|------|------|------|
| A. Mock 数据 | 1 组6 条记录,含 ~20 个字段/条) | 页面内联 `MOCK_COACHES` 数组,未引用 `utils/mock-data.ts` |
| B. 硬编码数据 | 6 组常量 + 3 个默认值 | 排序/技能/时间选项、等级/技能样式映射、默认筛选值 |
| C. 已对接 API | 0 | 全部数据来自 Mock无任何 `wx.request` / service 调用 |
| D. 前端计算/派生数据 | 10 个派生字段 | `loadData()` 中通过 `formatMoney`/`formatHours`/`formatCount` 生成展示标签 |
| E. 路由参数 | 0 | `onLoad()` 未读取任何 query 参数 |
| F. WXML 硬编码文案 | 14 处 | Tab 标签、状态提示、维度标签等 |
---
## 一、Mock 数据
### 1.1 页面内联 Mock`MOCK_COACHES`board-coach.ts L82-L161
页面顶部定义了 `const MOCK_COACHES: CoachItem[]`,包含 6 位助教的完整数据。`loadData()` 通过 `setTimeout(400ms)` 模拟异步加载后直接使用该数组。
**未引用** `utils/mock-data.ts` 中的 `mockCoaches`(该文件有独立的 `CoachCard` 接口和 3 条记录,字段结构不同)。
| Mock 字段 | 类型 | 示例值 | 联调时应替换为 |
|-----------|------|--------|---------------|
| `id` | string | `'c1'` | API 返回的助教 ID |
| `name` | string | `'小燕'` | 助教姓名 |
| `initial` | string | `'小'` | 前端根据 name 首字计算,或 API 返回头像 URL |
| `avatarGradient` | string | `'blue'` | API 返回头像 URL 后可移除,改用真实头像 |
| `level` | string | `'star'` | 助教等级API`star/senior/middle/junior` |
| `skills` | Array | `[{text:'🎱', cls:'skill--chinese'}]` | API 返回技能列表,前端映射 cls |
| `topCustomers` | string[] | `['💖 王先生','💖 李女士']` | API 返回 top 客户列表(含亲密度标记) |
| `perfHours` | number | `86.2` | 定档业绩课时API 聚合) |
| `perfHoursBefore` | number? | `92.0` | 折前课时API 聚合) |
| `perfGap` | string? | `'距升档 13.8h'` | 可由前端计算或 API 直接返回 |
| `perfReached` | boolean | `false` | 是否已达标API 或前端判断) |
| `salary` | number | `12680` | 预估工资API 聚合) |
| `salaryPerfHours` | number | `86.2` | 工资维度-定档课时 |
| `salaryPerfBefore` | number? | `92.0` | 工资维度-折前课时 |
| `svAmount` | number | `45200` | 客源储值金额API 聚合) |
| `svCustomerCount` | number | `18` | 储值客户数 |
| `svConsume` | number | `8600` | 储值消耗金额 |
| `taskRecall` | number | `18` | 召回任务完成数 |
| `taskCallback` | number | `14` | 回访任务完成数 |
**联调替换目标 API**(待后端提供):
```
GET /api/v1/board/coach/list
Query: sort={selectedSort}&skill={selectedSkill}&time={selectedTime}
Response: { coaches: CoachItem[] }
```
---
## 二、硬编码数据
### 2.1 筛选选项常量board-coach.ts L14-L50
| 常量名 | 字段数 | 风险 | 说明 |
|--------|--------|------|------|
| `SORT_OPTIONS` | 6 项 | 🟡 中 | 排序维度选项value/text 写死。若后端新增排序维度需同步修改 |
| `SKILL_OPTIONS` | 5 项 | 🟡 中 | 技能筛选选项,含 emoji。若门店技能类型可配置则需改为 API 获取 |
| `TIME_OPTIONS` | 6 项 | 🟢 低 | 时间范围选项,纯前端逻辑,变动概率低 |
| `SORT_TO_DIM` | 6 项映射 | 🟢 低 | 排序值→维度类型映射,纯前端 UI 逻辑 |
### 2.2 样式映射常量board-coach.ts L53-L68
| 常量名 | 风险 | 说明 |
|--------|------|------|
| `LEVEL_CLASS` | 🟢 低 | 等级→CSS 类映射,含中英文 key 兼容。纯前端样式逻辑 |
| `SKILL_CLASS` | 🟢 低 | 技能 emoji→CSS 类映射。纯前端样式逻辑 |
### 2.3 data 对象默认值board-coach.ts L165-L180
| 字段 | 硬编码值 | 风险 | 说明 |
|------|----------|------|------|
| `selectedSort` | `'perf_desc'` | 🟢 低 | 默认排序,合理默认值 |
| `selectedSkill` | `'all'` | 🟢 低 | 默认不限技能 |
| `selectedTime` | `'month'` | 🟢 低 | 默认本月 |
| `dimType` | `'perf'` | 🟢 低 | 默认维度类型,与 selectedSort 联动 |
| `filterBarVisible` | `true` | 🟢 低 | 筛选栏初始可见 |
| `pageState` | `'loading'` | 🟢 低 | 页面初始状态 |
| `activeTab` | `'coach'` | 🟢 低 | 当前 Tab 标识 |
### 2.4 `loadData()` 中的模拟延迟board-coach.ts L195
```typescript
setTimeout(() => { ... }, 400) // 🔴 高风险:联调时必须替换为真实 API 调用
```
### 2.5 `onPullDownRefresh` 中的延迟board-coach.ts L192
```typescript
setTimeout(() => wx.stopPullDownRefresh(), 500) // 🟡 中风险:联调后应在 API 回调中停止
```
---
## 三、已对接 API
**无。** 当前页面 0 个 API 调用,全部数据来自页面内联 Mock。
页面中存在的导航跳转(非数据 API
- `wx.switchTab({ url: '/pages/board-finance/board-finance' })` — Tab 切换
- `wx.navigateTo({ url: '/pages/board-customer/board-customer' })` — Tab 切换
- `wx.navigateTo({ url: '/pages/coach-detail/coach-detail?id=' + id })` — 助教详情跳转
---
## 四、前端计算/派生数据
### 4.1 `loadData()` 中的格式化派生字段board-coach.ts L197-L208
| 派生字段 | 源字段 | 格式化函数 | 输出示例 |
|----------|--------|-----------|----------|
| `perfHoursLabel` | `perfHours` | `formatHours()` | `'86.2h'` |
| `perfHoursBeforeLabel` | `perfHoursBefore` | `formatHours()` | `'92h'` |
| `salaryLabel` | `salary` | `formatMoney()` | `'¥12,680'` |
| `salaryPerfHoursLabel` | `salaryPerfHours` | `formatHours()` | `'86.2h'` |
| `salaryPerfBeforeLabel` | `salaryPerfBefore` | `formatHours()` | `'92h'` |
| `svAmountLabel` | `svAmount` | `formatMoney()` | `'¥45,200'` |
| `svCustomerCountLabel` | `svCustomerCount` | `formatCount(n,'人')` | `'18人'` |
| `svConsumeLabel` | `svConsume` | `formatMoney()` | `'¥8,600'` |
| `taskRecallLabel` | `taskRecall` | `formatCount(n,'次')` | `'18次'` |
| `taskCallbackLabel` | `taskCallback` | `formatCount(n,'次')` | `'14次'` |
### 4.2 维度类型切换board-coach.ts L218-L222
`onSortChange` 根据 `SORT_TO_DIM` 映射计算 `dimType`,控制 WXML 中四种卡片模板的条件渲染。
### 4.3 滚动隐藏/显示筛选栏board-coach.ts L196-L215 `onPageScroll`
纯前端交互逻辑:累积滚动距离超过阈值(上滑 12px / 下滑 24px时切换 `filterBarVisible`
---
## 五、路由参数
**无。** `onLoad()` 未接收任何 `options` 参数。
---
## 六、WXML 硬编码文案
| 位置 | 硬编码文案 | 风险 | 建议 |
|------|-----------|------|------|
| 加载态 | `加载中...` | 🟢 低 | 通用文案,可保留 |
| 空状态 | `暂无助教数据` | 🟢 低 | 可保留 |
| 错误态 | `加载失败` | 🟢 低 | 可保留 |
| 重试按钮 | `点击重试` | 🟢 低 | 可保留 |
| Tab-财务 | `财务` | 🟢 低 | 固定 Tab 文案 |
| Tab-客户 | `客户` | 🟢 低 | 固定 Tab 文案 |
| Tab-助教 | `助教` | 🟢 低 | 固定 Tab 文案 |
| 定档维度标签 | `定档` / `折前` | 🟢 低 | 业务术语,可保留 |
| 工资维度标签 | `预估` | 🟢 低 | 业务术语 |
| 储值维度标签 | `储值` | 🟢 低 | 业务术语 |
| 召回维度标签 | `召回` | 🟢 低 | 业务术语 |
| 达标标记 | `✅ 已达标` | 🟢 低 | 可保留 |
| 工资底部 | `定档` / `折前` | 🟢 低 | 同上 |
| 储值底部 | `客户` / `消耗` / `\|` 分隔符 | 🟢 低 | 业务术语 |
| 任务底部 | `回访` | 🟢 低 | 业务术语 |
| 导航栏标题 | `助教看板`board-coach.json | 🟢 低 | 固定页面标题 |
---
## 七、引用组件清单
| 组件 | 来源 | 数据依赖 |
|------|------|----------|
| `coach-level-tag` | 自定义组件 | 接收 `level` 属性 |
| `filter-dropdown` | 自定义组件 | 接收 `label`/`options`/`value`,触发 `change` 事件 |
| `ai-float-button` | 自定义组件 | 无数据依赖 |
| `board-tab-bar` | 自定义 Tab Bar | 接收 `active="board"` |
| `t-loading` / `t-empty` | TDesign 组件 | 无业务数据依赖 |
| `dev-fab` | 开发调试组件 | `wx:if="{{false}}"` 已禁用 |
---
## 八、联调 TODO
### 🔴 P0 — 必须完成
- [ ] **替换 `MOCK_COACHES` 为 API 调用**:移除页面内联 Mock 数组,`loadData()` 改为调用后端接口
- 需后端提供:助教列表接口(含排序/技能/时间筛选参数)
- 接口需返回四种维度的全部字段perf/salary/sv/task
- 错误处理API 失败时 `setData({ pageState: 'error' })`
- [ ] **移除 `setTimeout(400ms)` 模拟延迟**:替换为真实异步请求
- [ ] **`onPullDownRefresh` 改为 API 回调中停止**`wx.stopPullDownRefresh()` 应在请求完成后调用
### 🟡 P1 — 建议完成
- [ ] **筛选联动 API**:当前 `onSortChange`/`onSkillChange`/`onTimeChange` 仅更新本地状态,未触发重新请求。联调时需在筛选变更后重新调用 API
- [ ] **头像方案确认**:当前使用 `initial`(首字)+ `avatarGradient`(渐变色)模拟头像。确认是否改为真实头像 URL
- [ ] **`perfGap` 字段来源确认**:当前为 Mock 字符串(如 `'距升档 13.8h'`),确认由后端计算还是前端根据阈值计算
- [ ] **`topCustomers` 格式确认**:当前含 emoji 亲密度标记(💖/💛),确认 API 返回格式
### 🟢 P2 — 可后续优化
- [ ] **`SKILL_OPTIONS` 是否需要动态获取**:若门店技能类型可配置,应改为 API 获取
- [ ] **`SORT_OPTIONS` / `TIME_OPTIONS` 是否需要后端控制**:当前写死,若需动态调整需改为配置化
- [ ] **清理 `utils/mock-data.ts` 中的 `CoachCard` 接口**:与页面内联 `CoachItem` 接口不一致,联调完成后统一或移除
- [ ] **`levelClass` 字段**:当前在 Mock 中预计算,联调后应由前端根据 `level` 字段通过 `LEVEL_CLASS` 映射生成