# apps/miniprogram — 微信小程序

<!-- AI_CHANGELOG
- 2026-03-28 02:03:11 | Prompt: 登录落地页修复 | 认证流程章节补充权限码驱动登录跳转说明（落地页优先级、/me 降级策略）
- 2026-03-27 19:07:51 | Prompt: board-finance 双重格式化修复 | board-finance.ts 移除 formatMoney() 预格式化，
  金额字段传原始数字（?? 0），格式化统一由 WXS 完成；添加 checkPageAccess 权限守卫；
  区域筛选从 7→9 项；新增 isCurrentMonth 预估标记和 aiInsights 字段。
- 2026-03-20 23:41:47 | Prompt: ai-prompt-refinement spec 验证 | board-coach.ts Mock 数据从 6 位助教精简为 2 个空骨架项，
  用于字段覆盖排查；页面结构和逻辑不变。
- 2026-03-20 | Prompt: 小程序文档过期检查与落盘 | 页面路由表从 13→19 条（同步 app.json），
  移除已删除的 mvp/index/logs；目录结构补充 services/、assets/、utils 22 个文件；
  新增组件清单（18 个）；API 端点表补充 me/tasks/{id}/performance/customers/coaches 等；
  Roadmap 更新已完成项；移除已废弃的 MVP 页面章节。
-->

微信小程序前端项目，基于 Donut 多端框架 + TDesign 组件库，为台球门店会员提供移动端服务入口。

## 技术栈

- 微信小程序原生 + Donut 多端（`projectArchitecture: multiPlatform`）
- TDesign 小程序版（`tdesign-miniprogram ^1.12.2`）
- TypeScript
- 类型定义：`miniprogram-api-typings`

## 目录结构

```
apps/miniprogram/
├── miniprogram/              # 小程序主体代码
│   ├── app.ts                # 应用入口（检查登录状态 → 路由分发）
│   ├── app.json              # 全局配置（页面路由、TabBar、窗口样式）
│   ├── app.wxss              # 全局样式（CSS 变量系统、头像色板）
│   ├── pages/                # 页面目录（19 个，详见「页面路由」）
│   ├── components/           # 可复用组件（18 个，详见「组件清单」）
│   ├── services/             # 数据请求层
│   │   └── api.ts            # 统一 API 入口（封装所有后端调用）
│   ├── utils/                # 工具函数（22 个）
│   │   ├── config.ts         # 环境配置（API 地址自动切换）
│   │   ├── request.ts        # HTTP 请求封装（JWT 自动注入、刷新）
│   │   ├── router.ts         # 页面跳转工具
│   │   ├── vi-colors.ts      # VI 颜色常量
│   │   ├── ai-color-manager.ts # AI 配色管理器
│   │   ├── avatar-color.ts   # 头像颜色映射（姓名 → 24 色）
│   │   ├── task-config.ts    # 任务类型配置
│   │   ├── mock-data.ts      # Mock 数据（开发调试用）
│   │   └── ...               # format.wxs、time.wxs、money.ts 等
│   ├── assets/               # 静态资源
│   │   ├── icons/            # 图标文件
│   │   └── images/           # 图片文件
│   ├── miniprogram_npm/      # 构建后的 npm 包（TDesign 组件）
│   ├── i18n/                 # 国际化资源
│   └── miniapp/              # Donut 多端原生资源
├── typings/                  # TypeScript 类型定义
├── project.config.json       # 微信开发者工具项目配置
├── project.miniapp.json      # Donut 多端配置
├── tsconfig.json             # TypeScript 编译配置
├── package.json              # npm 依赖声明
└── README.md
```

## 开发指南

### 环境准备

1. 安装微信开发者工具
2. 打开本目录（`apps/miniprogram/`）
3. 首次打开后，在工具中执行"构建 npm"以生成 `miniprogram_npm/`
4. AppID：`wx7c07793d82732921`

### 页面路由

当前注册页面（`app.json`，共 19 个）：

| 路径 | 说明 | TabBar |
|------|------|:------:|
| `pages/login/login` | 登录页（首页，微信授权登录） | |
| `pages/apply/apply` | 入驻申请页 | |
| `pages/reviewing/reviewing` | 审核中等待页 | |
| `pages/no-permission/no-permission` | 无权限 / 账号禁用提示页 | |
| `pages/task-list/task-list` | 任务列表页（四种任务类型分组、置顶/放弃、备注弹窗） | ✅ 任务 |
| `pages/task-detail/task-detail` | 任务详情页（维客线索、服务记录、AI 分析、备注） | |
| `pages/notes/notes` | 备注管理页（备注 CRUD + 关联任务上下文） | |
| `pages/board-finance/board-finance` | 财务看板页（6 大板块 + 环比开关） | ✅ 看板 |
| `pages/board-coach/board-coach` | 助教看板页（排序×技能×时间三重筛选） | |
| `pages/board-customer/board-customer` | 客户看板页（维度×项目筛选 + 分页） | |
| `pages/my-profile/my-profile` | 个人中心页 | ✅ 我的 |
| `pages/performance/performance` | 绩效概览页（档位进度、收入明细、新客/常客） | |
| `pages/performance-records/performance-records` | 绩效明细页（按日期分组的服务记录） | |
| `pages/customer-detail/customer-detail` | 客户详情页（完整档案 + AI 洞察 + 维客线索） | |
| `pages/customer-service-records/customer-service-records` | 客户服务记录页（按日期分组的消费记录） | |
| `pages/coach-detail/coach-detail` | 助教详情页（业绩数据 + 客户列表） | |
| `pages/coach-service-records/coach-service-records` | 助教业绩明细页（管理者视角，查看指定助教的业绩明细） | |
| `pages/chat/chat` | AI 对话页（SSE 流式输出，按上下文进入对话） | |
| `pages/chat-history/chat-history` | 对话历史列表页 | |
| `pages/dev-tools/dev-tools` | 开发调试面板（仅 develop 环境，通过 dev-fab 浮动按钮进入） | |

## 组件清单

可复用组件（`miniprogram/components/`，共 18 个）：

| 组件 | 路径 | 说明 |
|------|------|------|
| abandon-modal | `components/abandon-modal/` | 放弃任务确认弹窗 |
| ai-float-button | `components/ai-float-button/` | 页面底部 AI 助手浮动入口 |
| ai-inline-icon | `components/ai-inline-icon/` | 行内 AI 小图标（30rpx，6 种配色） |
| ai-title-badge | `components/ai-title-badge/` | 标题行 AI 胶囊徽章（6 种配色） |
| banner | `components/banner/` | 页面顶部用户信息条 |
| board-tab-bar | `components/board-tab-bar/` | 看板页面标签切换栏 |
| clue-card | `components/clue-card/` | 维客线索单项卡片 |
| clue-list | `components/clue-list/` | 维客线索列表容器 |
| coach-level-tag | `components/coach-level-tag/` | 助教等级徽章（初级/中级/高级/星级） |
| dev-fab | `components/dev-fab/` | 开发调试浮动按钮（仅 develop 环境） |
| filter-dropdown | `components/filter-dropdown/` | 看板筛选下拉菜单 |
| heart-icon | `components/heart-icon/` | 关系指数心形图标（4 级渐变） |
| hobby-tag | `components/hobby-tag/` | 客户爱好标签 |
| metric-card | `components/metric-card/` | 数据指标展示卡片 |
| note-modal | `components/note-modal/` | 备注编辑弹窗 |
| perf-progress-bar | `components/perf-progress-bar/` | 业绩档位进度条 |
| service-record-card | `components/service-record-card/` | 服务记录单项卡片 |
| star-rating | `components/star-rating/` | 星级评分组件 |

## 业绩明细双视角

业绩明细存在两个严格隔离的页面，职责互不交叉：

- `performance-records`（助教自查）
  - 视角：当前登录用户（无需 coachId）
  - 权限：无需额外守卫
  - 点击单条记录：跳 `task-detail?taskId=xxx`（关注任务）
- `coach-service-records`（管理者查看）
  - 视角：指定助教，coachId 必传（来自 URL query）
  - 权限：`view_board_coach`
  - 点击单条记录：跳 `customer-detail?memberId=xxx`（关注客户）

coach-service-records 页面约定：

- 入口：`coach-detail` 页面的"查看更多"按钮
- `onShow` 必须通过 `checkPageAccess('view_board_coach')` 守卫
- 数据源：
  - Banner：`fetchCoachBanner(coachId)` 轻量接口
  - 记录：`fetchPerformanceRecords({ year, month, coachId, page, pageSize })`
- 源码：`miniprogram/pages/coach-service-records/*`

## 共享工具

业绩进度条动画参数与计算逻辑的单一源头：`miniprogram/utils/perf-progress.ts`。被 `task-list.ts` 与 `coach-detail.ts` 共同使用，避免双份漂移。

导出清单：

- 常量：`SHINE_SPEED`、`SPARK_DELAY_MS`、`SPARK_DUR_MS`、`NEXT_LOOP_DELAY_MS`、`SHINE_WIDTH_RPX`
- 类型：`TickItem` 接口
- 函数：`calcShineDur`、`buildTicks`、`buildProgressBarData`

新建同类动画参数或档位刻度逻辑时，统一落在此文件，禁止在页面脚本内就地写常量。

## 数据规范

### 散客标记（isScattered）

后端判定规则：`member_id <= 0` 时在响应字段上标记 `isScattered = true`，标识该条记录为散客（无会员档案）。

涉及页面：`coach-detail`、`performance-records`、`coach-service-records`、`customer-detail`。

前端渲染约定：为承载散客信息的节点追加 CSS 类 `--scattered`，以置灰方式区分于实名会员；散客条目不提供跳转到 `customer-detail` 的入口。

## 后端 API 集成

### API 地址配置

`utils/config.ts` 根据小程序运行环境自动切换 API 地址：

| 环境 | API 地址 |
|------|----------|
| develop（开发版） | `http://127.0.0.1:8000` |
| trial（体验版） | `https://api.langlangzhuoqiu.cn` |
| release（正式版） | `https://api.langlangzhuoqiu.cn` |

### 认证流程

小程序用户的完整生命周期：

```
wx.login() 获取 code
       ↓
POST /api/xcx-auth/login  →  获取 JWT（受限令牌，status=new）
       ↓
POST /api/xcx-auth/apply  →  提交入驻申请（球房ID + 身份 + 手机号，status → pending）
       ↓
管理员在后台审批
       ↓
GET /api/xcx-auth/status  →  查询审批结果
       ↓
POST /api/xcx-auth/login  →  重新登录获取完整令牌（含 site_id + roles）
       ↓
正常使用业务功能
```

用户状态流转：
- `new`：新用户，尚未提交申请
- `pending`：已提交申请，等待审批
- `approved`：审批通过，可正常使用
- `rejected`：审批拒绝，可重新申请
- `disabled`：账号禁用

登录落地页（approved 用户）：
- 登录成功后额外请求 `/api/xcx/me` 获取 `permissions[]` 权限码
- 调用 `syncPermissions()` 设置 tab 可见性，`getPermissionHome()` 计算落地页
- 落地页优先级：board-finance > board-customer > board-coach > task-list > my-profile
- `/me` 请求失败时降级到 my-profile，后续 `checkAuthStatus` 补偿

令牌类型：
- 受限令牌（`limited=True`）：new/pending/rejected 用户，仅可访问申请和状态查询端点
- 完整令牌：approved 用户，包含 `user_id` + `site_id` + `roles`

### 开发模式

后端支持开发模式（`WX_DEV_MODE=true`），提供 mock 登录端点跳过微信 code2Session：

| 端点 | 方法 | 说明 |
|------|------|------|
| `/api/xcx-auth/dev-login` | POST | 开发模式 mock 登录（仅开发环境） |

参数：
- `openid`：模拟的微信 openid
- `status`：可选，指定用户状态（new/pending/approved/rejected）

### 关键 API 端点

| 端点 | 方法 | 说明 |
|------|------|------|
| `/api/xcx-auth/login` | POST | 微信登录（code → JWT） |
| `/api/xcx-auth/dev-login` | POST | 开发模式 mock 登录（仅开发环境） |
| `/api/xcx-auth/apply` | POST | 提交入驻申请 |
| `/api/xcx-auth/status` | GET | 查询用户状态和申请记录 |
| `/api/xcx-auth/sites` | GET | 获取关联门店列表 |
| `/api/xcx-auth/switch-site` | POST | 切换当前门店 |
| `/api/xcx-auth/refresh` | POST | 刷新令牌 |
| `/api/xcx/me` | GET | 查询当前用户信息 |
| `/api/xcx/tasks` | GET | 获取任务列表（含绩效概览） |
| `/api/xcx/tasks/{task_id}` | GET | 获取任务详情（维客线索、服务记录、AI 分析） |
| `/api/xcx/tasks/{task_id}/pin` | POST | 置顶/取消置顶任务 |
| `/api/xcx/tasks/{task_id}/abandon` | POST | 放弃任务 |
| `/api/xcx/tasks/{task_id}/restore` | POST | 取消放弃任务 |
| `/api/xcx/notes` | GET/POST/DELETE | 备注 CRUD |
| `/api/xcx/performance` | GET | 绩效概览（档位、收入、新客/常客） |
| `/api/xcx/performance/records` | GET | 绩效明细（按日期分组） |
| `/api/xcx/customers/{id}` | GET | 客户详情（完整档案 + AI 洞察） |
| `/api/xcx/coaches/{id}` | GET | 助教详情 |
| `/api/xcx/config/skill-types` | GET | 项目类型筛选器配置 |
| `/api/xcx/board/coaches` | GET | 助教看板（排序×技能×时间筛选） |
| `/api/xcx/board/customers` | GET | 客户看板（维度×项目筛选 + 分页） |
| `/api/xcx/board/finance` | GET | 财务看板（6 大板块 + 环比开关） |
| `/api/xcx/chat/history` | GET | 对话历史列表 |
| `/api/xcx/chat/{chat_id}/messages` | GET/POST | 查看/发送消息 |
| `/api/xcx/chat/messages` | GET | 通过上下文查消息 |
| `/api/xcx/chat/stream` | POST | SSE 流式对话 |

### services/api.ts 近期新增

- `fetchCoachBanner(coachId: number)` — 轻量助教 banner 数据，供 `coach-service-records` 顶部卡片复用
- `fetchPerformanceRecords({ year, month, page, pageSize, coachId? })` — 新增可选 `coachId` 参数；不传为助教自查视角（后端以当前登录用户过滤），传入则为管理者查看视角（后端按权限码 `view_board_coach` 分流校验）

> 完整接口契约见 [`docs/miniprogram-dev/API-contract.md`](../../docs/miniprogram-dev/API-contract.md)
> 后端 API 参考见 [`apps/backend/docs/API-REFERENCE.md`](../backend/docs/API-REFERENCE.md)

## 权限模型

小程序用户通过 RBAC 模型控制功能访问：

| 角色 | 可见功能 |
|------|----------|
| coach（助教） | 查看任务、助教看板 |
| staff（员工） | 查看任务、数据看板 |
| site_admin（店铺管理员） | 全部看板 |
| tenant_admin（租户管理员） | 全部权限 |

多门店支持：用户可关联多个门店，通过 `/api/xcx-auth/switch-site` 切换。

## 与 Monorepo 的关系

- 本项目为独立前端工程，不参与 Python uv workspace
- 通过 FastAPI 后端（`apps/backend/`）与数据层交互
- H5 原型设计稿位于 `docs/h5_ui/`
- 认证数据存储在 `zqyy_app` 数据库的 `auth` Schema

## 开发调试面板（dev-tools）

仅在 develop 环境可用的调试工具，通过页面底部浮动按钮（dev-fab 组件）进入。

功能：
- 展示当前用户上下文（角色、权限、绑定关系、门店信息）
- 一键切换角色（coach / staff / site_admin / tenant_admin），后端真实修改 `user_site_roles` 并重签 token
- 一键切换用户状态（new / pending / approved / rejected / disabled），后端真实修改 `users.status` 并重签 token
- 页面跳转列表，点击可跳转到任意已注册页面

安全保障：
- dev-fab 组件通过 `wx.getAccountInfoSync().miniProgram.envVersion` 判断环境，仅 `develop` 时渲染
- 后端 dev 端点仅在 `WX_DEV_MODE=true` 时注册路由，生产环境不可访问

依赖的后端端点（均需 JWT）：

| 端点 | 方法 | 说明 |
|------|------|------|
| `/api/xcx/dev-context` | GET | 获取当前用户调试上下文 |
| `/api/xcx/dev-switch-role` | POST | 切换角色 |
| `/api/xcx/dev-switch-status` | POST | 切换用户状态 |
| `/api/xcx/dev-switch-binding` | POST | 切换绑定关系 |

## Roadmap

- [x] 认证流程页面（登录 → 申请 → 等待审批 → 首页）
- [x] 任务列表页面（task-list，四种任务类型分组、上下文菜单、备注弹窗）
- [x] 任务详情页面（task-detail，维客线索、服务记录、AI 分析）
- [x] 数据看板页面（助教/客户/财务三大看板）
- [x] 绩效页面（performance，档位进度、收入明细、新客/常客）
- [x] 客户详情页面（customer-detail，完整档案 + AI 洞察）
- [x] 助教详情页面（coach-detail，业绩数据 + 客户列表）
- [x] AI 对话页面（chat，SSE 流式输出 + 8 个 AI App）
- [x] 个人中心页面（my-profile）
- [x] VI 颜色系统统一（24 色头像色板、AI 配色系统）
- [ ] 前后端联调（services/api.ts 当前为 mock 模式，待恢复真实 API 调用）
- [ ] 多门店切换 UI
- [ ] 消息通知（微信订阅消息）
- [ ] CI/CD（代码检查、自动上传体验版）
