# apps/miniprogram — 微信小程序 微信小程序前端项目,基于 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(代码检查、自动上传体验版)