# 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` 应走设计系统变量，避免散落硬编码色值
