小程序迁移 静态页面完成!!!

This commit is contained in:
Neo
2026-03-18 05:14:35 +08:00
parent 72bb11b34f
commit 075caf067f
124 changed files with 10407 additions and 2738 deletions

View File

@@ -103,6 +103,11 @@ H5 静态原型页面,用于小程序 UI 设计参考。
| 路径 | 内容 |
|------|------|
| `README.md` | 入口索引快速导航、目录结构、Power 依赖、关联资源 |
| `design-system/VI-DESIGN-SYSTEM.md` | VI 设计系统:任务/客户/等级配色、AI 图标、CSS 变量速查 |
| `design-system/DATETIME-DISPLAY-STANDARD.md` | 日期时间展示规范:由近及远 6 级展示规则、边界处理、JS 实现参考 |
| `design-system/DISPLAY-STANDARDS.md` | 前端展示规范第1-6章金额 / 课时 / 计数 / 空值 / 百分比 / 等级文案 |
| `design-system/DISPLAY-STANDARDS-2.md` | 前端展示规范第7-9章截止日期 / 评分星级 / Mock 数据规范 + 工具函数总表 |
| `API-OUTPUT-SPEC.md` | 后端接口输出规范DS-API-OUTPUT-001字段类型约定 / 枚举值 / 各页面接口字段对照表 |
| `01-orchestration/batch-auto-playbook.md` | 批量自动模式89 单元编排 + 4 代理流水线 |
| `01-orchestration/user-guided-playbook.md` | 半自动模式:对话触发 + 按需执行 |
| `01-orchestration/new-page-playbook.md` | 新页面开发:有原型 / 无原型两条路径 |

View File

@@ -88,32 +88,34 @@
<div class="p-4 space-y-4">
<!-- AI 智能洞察(客户全貌总结) -->
<div class="rounded-2xl overflow-hidden shadow-sm">
<div class="bg-gradient-to-br from-[#667eea] to-[#764ba2] p-5 text-white">
<div class="flex items-center gap-2 mb-3">
<div class="w-6 h-6 bg-white/20 rounded-lg flex items-center justify-center">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none"><rect x="5" y="7" width="14" height="12" rx="4" fill="white"/><path d="M12 7V4" stroke="white" stroke-width="2" stroke-linecap="round"/><circle cx="12" cy="3" r="1.5" fill="white"/><circle cx="9" cy="11.5" r="2" fill="#667eea"/><circle cx="15" cy="11.5" r="2" fill="#667eea"/><circle cx="9.5" cy="11" r="0.7" fill="white"/><circle cx="15.5" cy="11" r="0.7" fill="white"/><path d="M9.5 15C10 16 14 16 14.5 15" stroke="#667eea" stroke-width="1.5" stroke-linecap="round"/><circle cx="7" cy="13.5" r="1" fill="#f5a0c0" opacity="0.6"/><circle cx="17" cy="13.5" r="1" fill="#f5a0c0" opacity="0.6"/><rect x="3" y="10" width="2" height="4" rx="1" fill="white"/><rect x="19" y="10" width="2" height="4" rx="1" fill="white"/></svg>
</div>
<span class="text-sm font-medium text-white/90">AI 智能洞察</span>
<div class="rounded-2xl overflow-hidden shadow-sm bg-gradient-to-br from-[#667eea] to-[#764ba2] p-5 text-white">
<div class="flex items-center gap-2 mb-4">
<div class="w-6 h-6 bg-white/20 rounded-lg flex items-center justify-center">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none"><rect x="5" y="7" width="14" height="12" rx="4" fill="white"/><path d="M12 7V4" stroke="white" stroke-width="2" stroke-linecap="round"/><circle cx="12" cy="3" r="1.5" fill="white"/><circle cx="9" cy="11.5" r="2" fill="#667eea"/><circle cx="15" cy="11.5" r="2" fill="#667eea"/><circle cx="9.5" cy="11" r="0.7" fill="white"/><circle cx="15.5" cy="11" r="0.7" fill="white"/><path d="M9.5 15C10 16 14 16 14.5 15" stroke="#667eea" stroke-width="1.5" stroke-linecap="round"/><circle cx="7" cy="13.5" r="1" fill="#f5a0c0" opacity="0.6"/><circle cx="17" cy="13.5" r="1" fill="#f5a0c0" opacity="0.6"/><rect x="3" y="10" width="2" height="4" rx="1" fill="white"/><rect x="19" y="10" width="2" height="4" rx="1" fill="white"/></svg>
</div>
<!-- 客户画像总结 -->
<p class="text-sm text-white/90 leading-relaxed mb-3">高价值 VIP 客户,月均到店 4-5 次,偏好夜场中式台球,近期对斯诺克产生兴趣。社交属性强,常带固定球搭子,有拉新能力。储值余额充足,对促销活动响应积极。</p>
<!-- 营销策略建议 -->
<div class="bg-white/10 rounded-xl p-3 backdrop-blur-sm">
<p class="text-xs text-white/60 mb-2">📋 当前推荐策略</p>
<div class="space-y-1.5">
<div class="flex items-start gap-2">
<span class="shrink-0 w-1.5 h-1.5 bg-emerald-300 rounded-full mt-1.5"></span>
<p class="text-xs text-white/85 leading-relaxed">最后到店距今 12 天,超出理想间隔 7 天,建议尽快安排助教小燕主动联系召回</p>
</div>
<div class="flex items-start gap-2">
<span class="shrink-0 w-1.5 h-1.5 bg-amber-300 rounded-full mt-1.5"></span>
<p class="text-xs text-white/85 leading-relaxed">客户提到想练斯诺克走位,可推荐斯诺克专项课程包,结合储值优惠提升客单价</p>
</div>
<div class="flex items-start gap-2">
<span class="shrink-0 w-1.5 h-1.5 bg-pink-300 rounded-full mt-1.5"></span>
<p class="text-xs text-white/85 leading-relaxed">社交属性强,可邀请参加门店球友赛事活动,带动球搭子到店消费</p>
</div>
<span class="text-sm font-medium text-white/90">AI 智能洞察</span>
</div>
<!-- 客户画像总结 -->
<div class="mb-4 pb-4 border-b border-white/20">
<p class="text-sm text-white/90 leading-relaxed">高价值 VIP 客户,月均到店 4-5 次,偏好夜场中式台球,近期对斯诺克产生兴趣。社交属性强,常带固定球搭子,有拉新能力。储值余额充足,对促销活动响应积极。</p>
</div>
<!-- 营销策略建议 -->
<div class="bg-black/20 rounded-lg p-3 -mx-5 -mb-5 px-5 py-3">
<p class="text-sm text-white/60 mb-3">📋 当前推荐策略</p>
<div class="space-y-0">
<div class="flex items-start gap-3 py-2.5 pl-3 border-l-2 border-emerald-300 border-b border-white/10">
<span class="shrink-0 w-1.5 h-1.5 bg-emerald-300 rounded-full mt-1.5"></span>
<p class="text-sm text-white/85 leading-relaxed">最后到店距今 12 天,超出理想间隔 7 天,建议尽快安排助教小燕主动联系召回</p>
</div>
<div class="flex items-start gap-3 py-2.5 pl-3 border-l-2 border-amber-300 border-b border-white/10">
<span class="shrink-0 w-1.5 h-1.5 bg-amber-300 rounded-full mt-1.5"></span>
<p class="text-sm text-white/85 leading-relaxed">客户提到想练斯诺克走位,可推荐斯诺克专项课程包,结合储值优惠提升客单价</p>
</div>
<div class="flex items-start gap-3 py-2.5 pl-3 border-l-2 border-pink-300">
<span class="shrink-0 w-1.5 h-1.5 bg-pink-300 rounded-full mt-1.5"></span>
<p class="text-sm text-white/85 leading-relaxed">社交属性强,可邀请参加门店球友赛事活动,带动球搭子到店消费</p>
</div>
</div>
</div>

View File

@@ -0,0 +1,545 @@
# 小程序后端接口输出规范
> **文档编号**DS-API-OUTPUT-001
> **版本**v1.0.0
> **适用范围**NeoZQYY 小程序所有后端接口HTTP JSON 响应体)
> **最后更新**2026-03-18
> **关联文档**
> - [DISPLAY-STANDARDS.md](./design-system/DISPLAY-STANDARDS.md) — 前端展示规范第 16 章
> - [DISPLAY-STANDARDS-2.md](./design-system/DISPLAY-STANDARDS-2.md) — 第 79 章(截止日期 / 评分 / Mock
> - [DATETIME-DISPLAY-STANDARD.md](./design-system/DATETIME-DISPLAY-STANDARD.md) — 时间展示规范
---
## 目录
1. [总体约定](#1-总体约定)
2. [响应体结构](#2-响应体结构)
3. [字段类型规范(核心规则)](#3-字段类型规范核心规则)
4. [各业务字段细则](#4-各业务字段细则)
5. [枚举值规范](#5-枚举值规范)
6. [分页规范](#6-分页规范)
7. [接口端点命名规范](#7-接口端点命名规范)
8. [各页面接口字段对照表](#8-各页面接口字段对照表)
9. [禁止事项速查](#9-禁止事项速查)
---
## 1. 总体约定
| 项目 | 规范 |
|------|------|
| 协议 | HTTPS REST JSON |
| 编码 | UTF-8 |
| Content-Type | `application/json` |
| 时区 | **后端统一输出 UTC前端负责本地化展示** |
| 数值精度 | 金额为整数(元),课时为 0.5 步长浮点 |
| 空值 | 字段不存在时输出 `null`**不得省略字段** |
| 布尔值 | `true` / `false`,不用 `0/1` |
| 字符串编码格式 | 纯数据,**不含展示单位**¥、h、%、笔等) |
---
## 2. 响应体结构
### 2.1 成功响应
```json
{
"code": 0,
"message": "success",
"data": { ... }
}
```
### 2.2 失败响应
```json
{
"code": 40001,
"message": "参数错误:缺少 customerId",
"data": null
}
```
### 2.3 分页列表响应
```json
{
"code": 0,
"message": "success",
"data": {
"list": [ ... ],
"total": 32,
"page": 1,
"pageSize": 20,
"hasMore": true
}
}
```
---
## 3. 字段类型规范(核心规则)
> **核心原则:后端输出原始语义数值,前端负责格式化展示。**
> 后端不拼接 `¥`、`h`、`%`、`笔` 等展示字符,也不做千分位格式化。
### 3.1 类型对照表
| 字段类型 | 后端输出类型 | 示例 | 前端处理函数 | 禁止输出 |
|----------|-------------|------|-------------|----------|
| **金额** | `number`(元,整数) | `12680` | `formatMoney()` | `"¥12,680"` `"12680.00"` |
| **课时** | `number`小时0.5步长) | `2.5` | `formatHours()` | `"2.5h"` `"2h30min"` |
| **计数** | `number`(整数) | `32` | `formatCount()` | `"32笔"` `"32次"` |
| **百分比** | `number`0100整数或1位小数 | `85.5` | `formatPercent()` | `"85.5%"` `"0.855"` |
| **日期** | `string``YYYY-MM-DD` | `"2026-03-18"` | `formatDeadline()` | `"2026/03/18"` `1742256000000` |
| **时间戳** | `string`ISO 8601含时区 | `"2026-03-18T08:30:00+08:00"` | `formatRelativeTime()` | Unix 毫秒整数 |
| **等级 key** | `string`(英文 key | `"star"` | 查 `LEVEL_MAP` | `"星级"` `"gold"` |
| **状态 key** | `string`(英文 key | `"pending"` | 查枚举映射 | `"待处理"` |
| **评分** | `number`0100.5步长) | `8.5` | `scoreToHalfStar()` | `"8.5分"` `4` (5分制) |
| **布尔** | `boolean` | `true` | 直接使用 | `1` `"true"` |
| **空值** | `null` | `null` | 展示 `--` | `""` `0`(有语义时除外) |
---
## 4. 各业务字段细则
### 4.1 金额字段
```json
// 正确
{ "balance": 2000, "income": 510, "salary": 12680 }
// 错误
{ "balance": "¥2,000", "income": "¥510", "salary": "¥12,680" }
```
- 统一以「元」为单位,**不含分**
- 负数直接输出负整数:`-368`
- 零值输出 `0`,不输出 `null`
- 前端调用 `formatMoney(value)` 展示
### 4.2 课时字段
```json
// 正确
{ "hours": 2.5, "hoursRaw": 3.0 }
// 错误
{ "hours": "2.5h", "deduct": "(折0.5h)" }
```
| 字段 | 类型 | 说明 |
|------|------|------|
| `hours` | `number` | 折算后实际计入课时(小时) |
| `hoursRaw` | `number \| null` | 折算前原始小时数;无折算时输出 `null` |
- 前端仅在 `hoursRaw !== null && hoursRaw !== hours` 时展示折算备注
- 步长为 0.5,如 `1.0``1.5``2.0``2.5`
### 4.3 计数字段
```json
// 正确
{ "totalCount": 32, "serviceCount": 18 }
// 错误
{ "totalCount": "32笔", "serviceCount": "18次" }
```
- 前端调用 `formatCount(value, '笔')` 展示,单位由页面层决定
### 4.4 百分比字段
```json
// 正确(进度/完成率)
{ "filledPct": 85, "completionRate": 72.5 }
// 错误
{ "filledPct": "85%", "completionRate": 0.725 }
```
- 统一 0100 整数或1位小数**不用小数形式**
- 允许超过 100如完成率 120%
### 4.5 日期与时间
| 场景 | 格式 | 示例 |
|------|------|------|
| 纯日期(截止日、生日等) | `YYYY-MM-DD` | `"2026-03-18"` |
| 精确时间(备注时间、服务记录) | ISO 8601 含时区 | `"2026-03-18T08:30:00+08:00"` |
| 时间区间service timeRange | 直接拼接字符串 | `"20:00-22:00"` |
- **禁止** 输出 Unix 毫秒时间戳整数
- **禁止** 输出 `YYYY/MM/DD` 格式
- 前端截止日期调用 `formatDeadline(date)` 语义化
- 前端相对时间调用 `formatRelativeTime(iso)` 展示
### 4.6 评分字段
```json
// 正确
{ "heartScore": 8.5, "noteScore": 7.0 }
// 错误
{ "heartScore": 4, "noteScore": "7.5分" }
```
- 统一使用 **010 分制**0.5 步长
- 0 表示「未评分」,前端展示 `--`
- 前端调用 `scoreToHalfStar(score)` 转换为 05 星展示
### 4.7 等级字段
```json
// 正确
{ "level": "star" }
// 错误
{ "level": "星级" }
```
| 后端 key | 前端展示 |
|----------|----------|
| `star` | 星级助教 |
| `senior` | 高级助教 |
| `middle` | 中级助教 |
| `junior` | 初级助教 |
### 4.8 天数字段
```json
// 正确
{ "lastVisitDays": 23, "daysAbsent": 23 }
// 错误
{ "lastVisitDays": "23天前", "daysAbsent": "23天" }
```
- 统一输出整数天数,不含「天」「天前」等汉字
- 前端拼接文案时自行添加单位
---
## 5. 枚举值规范
所有枚举字段统一使用英文下划线 key前端维护映射表。
### 5.1 任务类型 `taskType`
| key | 展示文案 |
|-----|----------|
| `callback` | 回访 |
| `priority_recall` | 优先召回 |
| `high_priority` | 高优先召回 |
| `relationship` | 关系构建 |
### 5.2 任务状态 `status`
| key | 展示文案 |
|-----|----------|
| `pending` | 待处理 |
| `completed` | 已完成 |
| `abandoned` | 已放弃 |
### 5.3 助教等级 `level`
| key | 展示文案 |
|-----|----------|
| `star` | 星级助教 |
| `senior` | 高级助教 |
| `middle` | 中级助教 |
| `junior` | 初级助教 |
### 5.4 课程类型 `courseType`
| key | 展示文案 | 样式 key |
|-----|----------|----------|
| `basic` | 基础课 | `tag-basic` |
| `vip` | 包厢课 | `tag-vip` |
| `tip` | 打赏课 | `tag-tip` |
| `recharge` | 充值 | `tag-recharge` |
| `incentive` | 激励 | `tag-incentive` |
### 5.5 线索来源 `source`
| key | 展示文案 |
|-----|----------|
| `manual` | 助教手动录入 |
| `ai_consumption` | 系统自动(消费分析) |
| `ai_note` | 系统自动(备注分析) |
### 5.6 线索分类 `category`
| key | 展示文案 |
|-----|----------|
| `customer_basic` | 客户基础 |
| `consumption` | 消费习惯 |
| `play_pref` | 玩法偏好 |
| `promo_pref` | 促销偏好 |
| `social` | 社交偏好 |
| `feedback` | 重要反馈 |
### 5.7 截止日期语义化(前端计算,非接口字段)
后端只输出 `deadline: "YYYY-MM-DD"`,前端调用 `formatDeadline()` 计算:
| diff | 展示文案 | 样式 |
|------|----------|------|
| < 0 | `逾期 N 天` | `danger`(红) |
| = 0 | `今天到期` | `warning`(橙) |
| 17 | `还剩 N 天` | `normal` |
| > 7 | `MM-DD` | `muted`(灰) |
| null | `--` | `muted` |
---
## 6. 分页规范
```json
{
"list": [],
"total": 100,
"page": 1,
"pageSize": 20,
"hasMore": true
}
```
- `page` 从 1 开始计数
- `hasMore` 由后端根据 `total` 和当前 `page * pageSize` 计算
- `total` 为全量数据总条数(不是当前页条数)
---
## 7. 接口端点命名规范
```
GET /api/xcx/tasks 任务列表
GET /api/xcx/tasks/:id 任务详情
GET /api/xcx/tasks/:id/notes 任务备注列表
POST /api/xcx/tasks/:id/notes 新增备注
GET /api/xcx/tasks/:id/service-records 近期服务记录
GET /api/xcx/coaches 助教看板列表
GET /api/xcx/coaches/:id 助教详情
GET /api/xcx/performance 绩效概览
GET /api/xcx/performance/records 绩效记录列表(支持月份分页)
GET /api/xcx/retention-clues/:customerId 维客线索
```
- 资源名用复数小写连字符
- 路径参数用 `:id`,不用查询参数代替
- 月份筛选用 `?year=2026&month=2`
---
## 8. 各页面接口字段对照表
### 8.1 任务列表页 `GET /api/xcx/tasks`
```json
{
"id": "task-001",
"customerName": "王先生",
"taskType": "high_priority",
"taskTypeLabel": "高优先召回",
"deadline": "2026-03-20",
"heartScore": 8.5,
"isPinned": true,
"hasNote": true,
"status": "pending",
"lastVisitDays": 23,
"balance": 2000,
"filledPct": 85,
"aiSuggestion": "建议本周内回访,余额即将到期"
}
```
**说明:**
- `lastVisitDays`integer距上次到店天数null 表示从未到店
- `balance`integer余额null 表示无储值
- `filledPct`integer0100关系进度百分比
- `deadline``YYYY-MM-DD`,前端调用 `formatDeadline()` 语义化
- `aiSuggestion`stringAI 摘要文案,后端生成,前端直接展示
### 8.2 任务详情页 `GET /api/xcx/tasks/:id`
```json
{
"id": "task-001",
"customerName": "王先生",
"taskType": "high_priority",
"taskTypeLabel": "高优先召回",
"status": "pending",
"deadline": "2026-03-20",
"heartScore": 8.5,
"phone": "138****5678",
"lastVisitDate": "2026-03-01",
"lastSpendAmount": 380,
"daysAbsent": 23,
"callbackReason": "上次体验课后未续费,需跟进意向",
"churnRisk": "high",
"spendTrend": "down",
"aiAnalysis": {
"summary": "最近 3 个月每周均有 1-2 次课程互动",
"suggestions": ["询问近期是否有空", "告知会员专属活动"]
},
"talkingPoints": ["王哥好久不见..."],
"notes": [
{
"id": "note-001",
"content": "已通过微信联系王先生...",
"tagType": "customer",
"tagLabel": "客户:王先生",
"createdAt": "2026-03-10T16:30:00+08:00",
"score": 8.5
}
],
"serviceRecords": [
{
"table": "A12号台",
"type": "基础课",
"typeClass": "basic",
"recordType": "course",
"hours": 2.5,
"hoursRaw": 3.0,
"income": 200,
"isEstimate": true,
"drinks": "百威x2 红牛x1",
"date": "2026-02-07T21:30:00+08:00"
}
],
"serviceSummary": {
"totalHours": 6.0,
"totalIncome": 510,
"avgIncome": 170
}
}
```
**说明:**
- `phone`:后端已做脱敏处理(`138****5678`),或根据权限返回明文
- `score`010 分制0 表示未评分
- `serviceRecords.hours``hoursRaw`number小时前端调用 `formatHours()`
- `serviceRecords.income``serviceSummary.*`integer前端调用 `formatMoney()`
- `isEstimate`booleantrue 时前端展示「预估」标注
### 8.3 助教看板页 `GET /api/xcx/coaches`
```json
{
"id": "coach-001",
"name": "小燕",
"level": "star",
"storeName": "朗朗桌球",
"customerCount": 28,
"monthHours": 86.0,
"monthIncome": 18600,
"svAmount": 5000,
"filledPct": 92,
"taskCount": 6,
"urgentTaskCount": 2,
"aiSuggestion": "本月表现优秀,建议重点跟进 2 位高风险流失客户"
}
```
**说明:**
- `level`:英文 key前端查 `LEVEL_MAP` 展示中文
- `monthHours`number小时前端调用 `formatHours()`
- `monthIncome``svAmount`integer前端调用 `formatMoney()`
- `filledPct`integer0100前端调用 `formatPercent()``toProgressWidth()`
- `customerCount``taskCount``urgentTaskCount`integer前端调用 `formatCount()`
### 8.4 绩效记录页 `GET /api/xcx/performance/records`
请求参数:`?year=2026&month=2&page=1&pageSize=20`
```json
{
"summary": {
"totalCount": 32,
"totalHours": 59.0,
"totalIncome": 4720
},
"dateGroups": [
{
"date": "2026-02-07",
"totalHours": 6.0,
"totalIncome": 510,
"records": [
{
"id": "r1",
"customerName": "王先生",
"timeRange": "20:00-22:00",
"hours": 2.0,
"hoursRaw": null,
"courseType": "basic",
"location": "3号台",
"income": 160
}
]
}
],
"hasMore": false,
"page": 1,
"pageSize": 20
}
```
**说明:**
- `date``YYYY-MM-DD`前端格式化为「2月7日」
- `summary.*``dateGroups.totalIncome``records.income`integer
- `summary.totalHours``dateGroups.totalHours``records.hours`number小时
- `hoursRaw`null 表示无折算,有值时前端展示折算备注
- `courseType`:英文 key`basic`/`vip`/`tip`/`recharge`/`incentive`
### 8.5 备注接口 `GET /api/xcx/tasks/:id/notes`
```json
[
{
"id": "note-001",
"content": "已通过微信联系王先生...",
"tagType": "customer",
"tagLabel": "客户:王先生",
"createdAt": "2026-03-10T16:30:00+08:00",
"score": 8.5
}
]
```
- `tagType``customer` / `coach` / `system`
- `score`0 表示未评分0.5 步长,前端调用 `scoreToHalfStar()` 转 5 星制
- `createdAt`ISO 8601前端调用 `formatRelativeTime()` 展示相对时间
---
## 9. 禁止事项速查
| 禁止行为 | 正确做法 |
|----------|----------|
| 输出 `"¥12,680"` | 输出 `12680` |
| 输出 `"2.5h"` | 输出 `2.5` |
| 输出 `"32笔"` | 输出 `32` |
| 输出 `"85%"` | 输出 `85` |
| 输出 `"星级"` 作为等级 | 输出 `"star"` |
| 输出 `"待处理"` 作为状态 | 输出 `"pending"` |
| 省略值为 null 的字段 | 显式输出 `null` |
| 用 `0` 代替 `null` 表示「无」 | 用 `null`0 保留给有意义的零值) |
| 输出 Unix 毫秒时间戳 | 输出 ISO 8601 字符串 |
| 输出 `YYYY/MM/DD` 日期格式 | 输出 `YYYY-MM-DD` |
| 后端做 `toLocaleString()` 格式化 | 后端输出原始数值,前端格式化 |
| `hoursRaw` 输出 `"(折0.5h)"` | 输出 `3.0`(原始小时数) |
---
## 关联文档
- [DISPLAY-STANDARDS.md](./design-system/DISPLAY-STANDARDS.md) — 前端格式化规范
- [DISPLAY-STANDARDS-2.md](./design-system/DISPLAY-STANDARDS-2.md) — 截止日期 / 评分 / Mock 规范
- [DATETIME-DISPLAY-STANDARD.md](./design-system/DATETIME-DISPLAY-STANDARD.md) — 时间展示规范
- `utils/money.ts``formatMoney` / `formatCount` / `formatPercent` / `toProgressWidth`
- `utils/time.ts``formatHours` / `formatDeadline` / `formatRelativeTime`
- `utils/rating.ts``scoreToHalfStar` / `isUnrated`
- `utils/mock-data.ts` — Mock 数据(字段结构与接口保持一致)

View File

@@ -0,0 +1,209 @@
# H5→MP 迁移快速参考
> **用途**AI 代码生成时的快速查阅手册
> **更新**2026-03-17
> **范围**:单位换算、颜色映射、类名对应、常见模式
---
## 📌 核心决策
| 项目 | 规则 |
|------|------|
| **框架** | 微信原生小程序WXML + WXSS + JS |
| **单位** | rpx 为主布局、间距px 为辅(发丝线、阴影) |
| **交互** | 数据驱动(禁用 DOM API |
| **验收宽度** | 412 CSS px |
| **能力分级** | A类直迁、B类条件迁、C类禁迁 |
---
## 🎨 颜色映射速查
### 任务分类
| 类型 | 颜色 | 渐变 |
|------|------|------|
| 高优先召回 | #dc2626 | #b91c1c#dc2626 |
| 优先召回 | #f97316 | #ea580c#f97316 |
| 客户回访 | #14b8a6 | #0d9488#14b8a6 |
| 关系构建 | #f472b6 | #ec4899#f472b6 |
### 客户标签
| 标签 | 字体色 | 背景色 |
|------|--------|--------|
| 客户基础 | #0052d9 | #ecf2fe |
| 消费习惯 | #00a870 | #e6f7f0 |
| 玩法偏好 | #ed7b2f | #fff3e6 |
| 促销偏好 | #d4a017 | #fffbeb |
| 社交关系 | #764ba2 | #f3e8ff |
| 重要反馈 | #e34d59 | #ffe6e8 |
### 关系等级
| 等级 | 渐变 | 分数 |
|------|------|------|
| 很好 | #e91e63#f472b6 | > 8.5 |
| 良好 | #ea580c#fb923c | 6-8.5 |
| 一般 | #eab308#fbbf24 | 3.5-6 |
| 待发展 | #64748b#94a3b8 | < 3.5 |
### AI 图标配色
| 配色 | 主色 | 浅色 | 深色 |
|------|------|------|------|
| Red | #e74c3c | #f39c9c | #c0392b |
| Orange | #e67e22 | #f5c77e | #ca6c17 |
| Yellow | #d4a017 | #f7dc6f | #b8860b |
| Blue | #2980b9 | #7ec8e3 | #1a5276 |
| Indigo | #667eea | #a78bfa | #4a5fc7 |
| Purple | #764ba2 | #c084fc | #5b3080 |
---
## 📏 单位换算速查
### 公式
```
rpx = px × 1.8204
px = rpx ÷ 1.8204
```
### 常用换算
| px | rpx | 用途 |
|----|----|------|
| 4 | 7 | 发丝线、极小间距 |
| 8 | 15 | 小间距 |
| 12 | 22 | 标签、小组件 |
| 16 | 29 | 标准间距 |
| 24 | 44 | 卡片间距 |
| 32 | 58 | 大间距 |
| 48 | 87 | 区块间距 |
### 字号换算
| px | rpx | 用途 |
|----|----|------|
| 12 | 22 | 辅助文字 |
| 14 | 26 | 小文字 |
| 16 | 29 | 正文 |
| 18 | 33 | 标题 |
| 20 | 36 | 大标题 |
---
## 🏷️ 类名映射速查
### 任务卡片
```css
.task-card--high_priority { border-left-color: #dc2626; }
.task-card--priority_recall { border-left-color: #f97316; }
.task-card--callback { border-left-color: #14b8a6; }
.task-card--relationship { border-left-color: #f472b6; }
.task-card--pinned { box-shadow: 0 5rpx 7rpx rgba(245,158,11,0.12), 0 0 0 8rpx rgba(245,158,11,0.08); }
.task-card--abandoned { border-left-color: #d1d5db; opacity: 0.55; }
```
### 客户标签
```css
.clue-tag-primary { color: #0052d9; background: rgba(0,82,217,0.1); }
.clue-tag-success { color: #00a870; background: rgba(0,168,112,0.1); }
.clue-tag-orange { color: #ed7b2f; background: rgba(237,123,47,0.1); }
.clue-tag-gold { color: #d4a017; background: rgba(212,160,23,0.1); }
.clue-tag-purple { color: #764ba2; background: rgba(118,75,162,0.1); }
.clue-tag-error { color: #e34d59; background: rgba(227,77,89,0.1); }
```
### 关系等级
```css
.rel-level-excellent { background: linear-gradient(135deg, #e91e63, #f472b6); }
.rel-level-good { background: linear-gradient(135deg, #ea580c, #fb923c); }
.rel-level-normal { background: linear-gradient(135deg, #eab308, #fbbf24); }
.rel-level-poor { background: linear-gradient(135deg, #64748b, #94a3b8); }
```
### 助教等级
```css
.coach-level-junior { color: #0052d9; background: #ecf2fe; }
.coach-level-middle { color: #ed7b2f; background: #fff3e6; }
.coach-level-senior { color: #e91e63; background: #ffe6e8; }
.coach-level-star { color: #fbbf24; background: #fffef0; }
```
---
## 🔄 常见迁移模式
### 模式1Tailwind → WXSS
```
Tailwind: class="flex items-center gap-2 p-4"
WXSS: display: flex; align-items: center; gap: 15rpx; padding: 29rpx;
```
### 模式2DOM 交互 → 数据驱动
```javascript
// ❌ H5 写法(禁止)
document.querySelector('.btn').classList.add('active');
// ✅ 小程序写法
this.setData({ isActive: true });
```
### 模式3line-height 处理
```wxml
<!-- ❌ 错误:直接在 text 上设置 -->
<text style="line-height: 1.5;">文字</text>
<!-- ✅ 正确:在外层 view 上设置 -->
<view style="line-height: 1.5;">
<text>文字</text>
</view>
```
### 模式4页面跳转
```javascript
// ❌ 错误:使用 history
history.push('/pages/detail');
// ✅ 正确:使用 wx.navigateTo
wx.navigateTo({ url: '/pages/detail/detail' });
// ✅ TabBar 页面用 switchTab
wx.switchTab({ url: '/pages/task-list/task-list' });
```
---
## ⚠️ 能力分级
### A 类(可直迁)
- flex、grid基础、positionrelative/absolute
- transition、animation
- border、box-shadow、border-radius
- opacity、transform
### B 类(条件迁)
- position: sticky → 用 scroll-view 的 sticky-section
- grid复杂布局→ 改为 flex
- backdrop-filter → 用半透明背景替代
- CSS 变量 → 改为 WXSS 变量或 JS 常量
### C 类(禁迁)
- document.*、window.*、localStorage
- DOM 操作classList、innerHTML、appendChild
- 浏览器事件resize、scroll 等)
- 第三方 JS 库jQuery、lodash 等)
---
## 📖 详细文档位置
| 需求 | 查阅文档 |
|------|---------|
| 完整迁移规范 | `h5-migration/h5-to-mp-bridge.md` |
| Spacing 详细字典 | `h5-migration/appendix/spacing-dictionary.md` |
| 字体/排版详细字典 | `h5-migration/appendix/typography-dictionary.md` |
| 颜色详细字典 | `h5-migration/appendix/color-dictionary.md` |
| 布局类详细字典 | `h5-migration/appendix/layout-dictionary.md` |
| VI 设计系统完整版 | `design-system/VI-DESIGN-SYSTEM.md` |
| VI 可视化指南 | `design-system/vi-guide.html` |
---
**版本**1.0 | **最后更新**2026-03-17

View File

@@ -1,153 +0,0 @@
# H5→微信小程序迁移文档结构说明
## 📚 文档体系
### 主规范文档1个
**`docs/miniprogram-dev/h5-to-mp-bridge-v3.md`** - 主规范 v3.0(合并版)
- **第一部分§1-4**:执行规程
- 输入输出契约
- 项目级强制决策
- 能力分级A/B/C 类)
- Tailwind CSS 行为说明
- **第二部分§5-9**:技术换算
- Spacing 换算表
- 字号与行高换算(含 line-height 关键发现)
- 颜色映射
- 布局类映射
- 装饰类映射
- **第三部分§10-12**:交互改造
- HTML→WXML 映射
- DOM 操作→数据驱动
- 浏览器 API→小程序 API
- **第四部分§13-14**:执行流程
- 10 步标准流程
- 附录文档索引
### 附录文档5个
位于 `docs/miniprogram-dev/New/`
1. **`h5_to_wechat_miniprogram_migration_bridge_appendix_index_v3.md`** - 附录索引v3.1
2. **`appendix_a_spacing_and_sizing_dictionary_v3.md`** - 附录 ASpacing 与尺寸字典
3. **`appendix_b_typography_and_text_dictionary_v3.md`** - 附录 B字体与文本字典v3.1
4. **`appendix_c_color_dictionary_v3.md`** - 附录 C颜色字典
5. **`appendix_d_layout_class_mapping_dictionary_v3.md`** - 附录 D布局类映射字典
---
## 🎯 使用指南
### 对于 AI
**加载顺序**
1. 加载主规范 `h5-to-mp-bridge-v3.md`(完整规范)
2. 加载附录索引 `h5_to_wechat_miniprogram_migration_bridge_appendix_index_v3.md`
3. 按需加载具体附录A/B/C/D
**执行流程**
1. 按 §13 的 10 步标准流程执行迁移
2. 查表时参考 §5-9 和附录 A/B/C/D
3. 交互改造时参考 §10-12
4. 确保输出符合 §1.2 的要求
### 对于开发者
**快速上手**
1. 先读主规范 §1-4 了解规则和决策
2. 需要时查阅 §5-12 的换算表和附录
3. 按 §13 的流程逐步完成迁移
4. 问题排查时回到对应章节
---
## 🔑 核心要点
### 1. 单位策略
- **rpx 为主**:布局、容器、间距
- **px 为辅**:发丝线、阴影、小图标
- **换算公式**`rpx = px × 1.8204`
### 2. line-height 关键发现 ⚠️
- 微信小程序的 `<text>` 组件不能直接设置 `line-height`
- 必须在外层 `<view>` 上设置text 会自动继承
- 详见主规范 §2.6 和 §6.2
### 3. 数据驱动
- 禁止使用 DOM 操作(`document.*``element.classList.*`
- 所有交互改为 `setData` + 条件渲染
- 详见主规范 §11
### 4. 能力分级
- **A 类**可直接使用flex、transition、animation 等)
- **B 类**有条件使用sticky、grid、backdrop-filter 等)
- **C 类**禁止直迁DOM API、浏览器 API 等)
- 详见主规范 §3
---
## 📝 版本历史
### v3.02026-03-14
- 合并 v1.0 技术换算基础和 v2.0 执行规范
- 补充 line-height 关键发现
- 统一文档结构,便于 AI 和开发者使用
### v2.0
- 执行规范,强化输入输出契约和能力分级
### v1.0
- 技术换算基础,建立完整的映射表
---
## 🗂️ 旧版文档(已归档)
以下文档已被 v3.0 主规范替代,保留作为参考:
- `docs/miniprogram-dev/h5-to-mp-bridge.md` - v1.0 技术换算基础
- `docs/prd/H5到微信小程序迁移桥接规范_可执行版_v2.md` - v2.0 执行规范
**建议**:新的迁移工作请使用 v3.0 主规范。
---
## 📊 文档统计
- **主规范**:约 1000+ 行,包含完整的执行规程、技术换算、交互改造、执行流程
- **附录 A**181 行Spacing 与尺寸字典
- **附录 B**267 行,字体与文本字典(含 line-height 规则)
- **附录 C**199 行,颜色字典
- **附录 D**205 行,布局类映射字典
---
## 🚀 快速开始
### 第一次使用
1. 阅读主规范 `h5-to-mp-bridge-v3.md` 的 §1-4
2. 了解输入输出契约和强制决策
3. 查看 §13 的 10 步标准流程
### 执行迁移
1. 按 §13 的流程逐步执行
2. 查表时参考 §5-9 和附录
3. 交互改造时参考 §10-12
4. 验证输出符合 §1.2 的要求
### 问题排查
1. Y 轴高度不对 → 检查 line-height§2.6、§6.2
2. 交互不工作 → 检查是否改为数据驱动§11
3. 样式不对 → 检查单位换算§2.3、§5-9
4. 页面跳转失败 → 检查 TabBar 页面是否用 switchTab§11.7
---
**文档完整,可以开始迁移!** 🎉

View File

@@ -0,0 +1,187 @@
# 微信小程序开发文档
> H5 → 微信小程序迁移规范 + VI 设计系统
> 最后更新2026-03-17
---
## 📚 文档导航
### 🚀 快速开始
**首次使用?** 从这里开始:
1. **AI 代码生成**:查阅 [`QUICK-REFERENCE.md`](./QUICK-REFERENCE.md)
- 颜色速查表、单位换算、类名映射、常见模式
- 精简版,适合快速查询
2. **完整迁移规范**:查阅 [`h5-migration/h5-to-mp-bridge.md`](./h5-migration/h5-to-mp-bridge.md)
- 执行规程、技术换算、交互改造、10步标准流程
- 详细版,适合深入理解
3. **VI 设计系统**:查阅 [`design-system/VI-DESIGN-SYSTEM.md`](./design-system/VI-DESIGN-SYSTEM.md)
- 颜色系统、组件规范、配色建议
- 设计师和开发者参考
---
## 📂 文档结构
```
docs/miniprogram-dev/
├── README.md ← 你在这里
├── QUICK-REFERENCE.md ← AI 快速参考(推荐首选)
├── h5-migration/ ← H5 迁移文档
│ ├── h5-to-mp-bridge.md ← 完整迁移规范1081行
│ ├── README.md ← 迁移文档说明
│ └── appendix/ ← 详细字典
│ ├── index.md ← 附录索引
│ ├── spacing-dictionary.md ← Spacing 与尺寸字典
│ ├── typography-dictionary.md ← 字体与文本字典
│ ├── color-dictionary.md ← 颜色字典
│ └── layout-dictionary.md ← 布局类映射字典
└── design-system/ ← VI 设计系统
├── VI-DESIGN-SYSTEM.md ← 完整设计系统规范397行
├── vi-guide.html ← 可视化指南(设计师用)
└── QUICK-REFERENCE.md ← 颜色速查表
```
---
## 🎯 按场景查阅
### 场景1AI 代码生成迁移页面
**推荐流程**
1. 打开 [`QUICK-REFERENCE.md`](./QUICK-REFERENCE.md)
2. 查阅颜色、单位、类名速查表
3. 参考常见迁移模式
4. 需要详细说明时,查阅 [`h5-migration/h5-to-mp-bridge.md`](./h5-migration/h5-to-mp-bridge.md)
**关键文件**
- `QUICK-REFERENCE.md` - 核心参考
- `h5-migration/h5-to-mp-bridge.md` - 完整规范
- `h5-migration/appendix/` - 详细字典
---
### 场景2前端开发手工迁移
**推荐流程**
1. 阅读 [`h5-migration/h5-to-mp-bridge.md`](./h5-migration/h5-to-mp-bridge.md) 的 §1-4执行规程
2. 了解输入输出契约和强制决策
3. 按 §13 的 10 步标准流程执行
4. 查表时参考 §5-9 和附录 A/B/C/D
**关键文件**
- `h5-migration/h5-to-mp-bridge.md` - 完整规范
- `h5-migration/appendix/` - 详细字典
---
### 场景3设计师查看配色规范
**推荐流程**
1. 打开 [`design-system/vi-guide.html`](./design-system/vi-guide.html)(可视化指南)
2. 查看各个模块的颜色预览
3. 需要详细说明时,查阅 [`design-system/VI-DESIGN-SYSTEM.md`](./design-system/VI-DESIGN-SYSTEM.md)
**关键文件**
- `design-system/vi-guide.html` - 可视化指南
- `design-system/VI-DESIGN-SYSTEM.md` - 完整规范
---
### 场景4查询特定内容
| 需要查询 | 查阅文件 |
|---------|---------|
| 颜色值 | `QUICK-REFERENCE.md``h5-migration/appendix/color-dictionary.md` |
| 单位换算 | `QUICK-REFERENCE.md``h5-migration/appendix/spacing-dictionary.md` |
| 字号/行高 | `h5-migration/appendix/typography-dictionary.md` |
| 布局类名 | `h5-migration/appendix/layout-dictionary.md` |
| 迁移流程 | `h5-migration/h5-to-mp-bridge.md` §13 |
| 能力分级 | `h5-migration/h5-to-mp-bridge.md` §3 |
| VI 规范 | `design-system/VI-DESIGN-SYSTEM.md` |
---
## 📊 文档统计
| 文档 | 行数 | 用途 |
|------|------|------|
| QUICK-REFERENCE.md | 210 | AI 快速参考 |
| h5-to-mp-bridge.md | 1081 | 完整迁移规范 |
| spacing-dictionary.md | 181 | Spacing 字典 |
| typography-dictionary.md | 267 | 字体字典 |
| color-dictionary.md | 199 | 颜色字典 |
| layout-dictionary.md | 205 | 布局字典 |
| VI-DESIGN-SYSTEM.md | 397 | VI 设计系统 |
| **总计** | **2740** | - |
---
## 🔑 核心概念速览
### 单位策略
- **rpx 为主**:布局、容器、间距(换算公式:`rpx = px × 1.8204`
- **px 为辅**:发丝线、阴影、小图标
### 交互改造
- **禁止 DOM 操作**`document.*``classList.*`
- **改为数据驱动**`setData` + 条件渲染
### 能力分级
- **A 类**可直迁flex、transition、animation 等)
- **B 类**条件迁sticky、grid、backdrop-filter 等)
- **C 类**禁迁DOM API、浏览器 API 等)
### 颜色系统
- **任务分类**4 种(高优先、优先、回访、关系)
- **客户标签**6 种(基础、消费、玩法、促销、社交、反馈)
- **关系等级**4 种(很好、良好、一般、待发展)
- **AI 图标**6 种配色Red、Orange、Yellow、Blue、Indigo、Purple
---
## ⚠️ 常见问题
### Q: 我应该从哪个文档开始?
**A**:
- 如果是 AI 代码生成:`QUICK-REFERENCE.md`
- 如果是手工迁移:`h5-migration/h5-to-mp-bridge.md`
- 如果是查颜色:`design-system/VI-DESIGN-SYSTEM.md`
### Q: 文档太多了,怎么快速找到我需要的?
**A**: 使用上面的"按场景查阅"表格,或者用 Ctrl+F 搜索关键词。
### Q: 为什么要分这么多文件?
**A**: 为了避免超大文件导致 AI 处理时超过 token 限制。每个文件都是独立的,可以按需加载。
### Q: 旧文档在哪里?
**A**: 已归档。新的迁移工作请使用本文档体系。
---
## 📝 版本历史
### v1.02026-03-17
- 整理文档结构
- 创建 QUICK-REFERENCE.mdAI 快速参考)
- 统一 README.md 作为总索引
- 分类 h5-migration 和 design-system
---
## 🚀 快速链接
- [AI 快速参考](./QUICK-REFERENCE.md) - 颜色、单位、类名速查
- [完整迁移规范](./h5-migration/h5-to-mp-bridge.md) - 详细执行规程
- [VI 设计系统](./design-system/VI-DESIGN-SYSTEM.md) - 颜色和组件规范
- [可视化指南](./design-system/vi-guide.html) - 设计师参考
---
**需要帮助?** 查阅对应的文档,或按"按场景查阅"表格找到你需要的内容。

View File

@@ -1,173 +0,0 @@
# AI 图标配色系统
> 文档版本2026-03-14
> 对应 H5 原型:`docs/h5_ui/css/ai-icons.css`
> 小程序实现:`app.wxss`(全局样式)+ 2 个标准组件
---
## 一、概览
AI 图标系统包含 **2 个标准组件** × **6 种配色**,共 12 种组合。
| 组件 | 路径 | 用途 | 图标文件 |
|------|------|------|----------|
| `ai-inline-icon` | `/components/ai-inline-icon/` | 卡片行首小图标30rpx 容器) | `ai-robot-inline.svg` |
| `ai-title-badge` | `/components/ai-title-badge/` | 标题行右侧徽章(胶囊形态) | `ai-robot-sm.svg` |
| 配色值 | 主色 | 辅色 | 深色(文字) | 适用场景 |
|--------|------|------|-------------|----------|
| `red` | #e74c3c | #f39c9c | #c0392b | 高优先召回 |
| `orange` | #e67e22 | #f5c77e | #ca6c17 | 优先召回 |
| `yellow` | #d4a017 | #f7dc6f | #b8860b | 激励/奖励 |
| `blue` | #2980b9 | #7ec8e3 | #1a5276 | 信息/数据 |
| `indigo` | #667eea | #a78bfa | #4a5fc7 | 默认/通用AI 标准色) |
| `purple` | #764ba2 | #c084fc | #5b3080 | 关系构建 |
---
## 二、组件注册
在页面的 `.json` 文件中按需注册:
```json
{
"usingComponents": {
"ai-inline-icon": "/components/ai-inline-icon/ai-inline-icon",
"ai-title-badge": "/components/ai-title-badge/ai-title-badge"
}
}
```
---
## 三、ai-inline-icon行首嵌入小图标
### 外观
- 尺寸30rpx × 30rpx圆角 6rpx
- 背景:淡色渐变(主色 ~8% 透明度)
- 内部图标:`ai-robot-inline.svg`(白色机身)
- 动效微光扫过12s 周期)
### WXML 用法
```wxml
<!-- 固定配色 —— indigo默认 -->
<ai-inline-icon />
<!-- 固定配色 —— orange -->
<ai-inline-icon color="orange" />
<!-- 页面随机配色(推荐) -->
<ai-inline-icon color="{{aiColor}}" />
```
### 属性
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `color` | String | `indigo` | 配色:`red` \| `orange` \| `yellow` \| `blue` \| `indigo` \| `purple` |
### 典型场景
- 任务卡片第三行 AI 建议文字行首(`task-list`
- 话术气泡行首标识(`task-detail`
---
## 四、ai-title-badge标题行 AI 徽章)
### 外观
- 形态:胶囊,`padding: 4rpx 14rpx 4rpx 6rpx`,圆角 18rpx
- 背景:主色 ~8% 透明度渐变 + 主色 35% 边框
- 文字深色主色20rpxfont-weight 500
- 动效呼吸脉冲3s+ 高光扫过14s
### WXML 用法
```wxml
<!-- 默认配色 + 默认文字「AI智能洞察」 -->
<ai-title-badge />
<!-- 指定配色 -->
<ai-title-badge color="blue" />
<!-- 自定义文字 -->
<ai-title-badge color="orange" label="AI 建议" />
<!-- 页面随机配色(推荐) -->
<ai-title-badge color="{{aiColor}}" />
```
### 属性
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `color` | String | `indigo` | 配色:`red` \| `orange` \| `yellow` \| `blue` \| `indigo` \| `purple` |
| `label` | String | `AI智能洞察` | 徽章文字 |
### 典型场景
- 任务详情各区块标题右侧(`task-detail`
- 业绩分析区块标题(`performance`
---
## 五、页面随机配色方案(推荐)
每个页面在 `onLoad` 时随机选取一种配色,全页所有 AI 图标统一使用同一配色。
### TS 实现(复制到各页面)
```typescript
const AI_COLORS = ['red', 'orange', 'yellow', 'blue', 'indigo', 'purple'] as const
type AiColor = typeof AI_COLORS[number]
Page({
data: {
aiColor: 'indigo' as AiColor,
},
onLoad() {
const aiColor = AI_COLORS[Math.floor(Math.random() * AI_COLORS.length)]
this.setData({ aiColor })
},
})
```
### WXML 绑定
```wxml
<!-- 行首图标 -->
<ai-inline-icon color="{{aiColor}}" />
<!-- 标题徽章 -->
<ai-title-badge color="{{aiColor}}" />
```
---
## 六、各页面配色建议(可选固定配色)
如不使用随机方案,可按以下建议固定配色:
| 页面 | 建议配色 | 原因 |
|------|---------|------|
| `task-list` | 随机 | 每日新鲜感 |
| `task-detail` | `indigo` | 通用默认 |
| `task-detail-callback` | `orange` | 与 banner 主题色呼应 |
| `task-detail-relationship` | `purple` | 与 banner 粉色系呼应 |
| `performance` | `blue` | 数据分析感 |
| `customer-detail` | `yellow` | 黑金页面,黄色点缀 |
| `coach-detail` | `red` | coral banner 配红色 AI |
---
## 七、文件索引
| 文件 | 说明 |
|------|------|
| `app.wxss` | 全局样式:`.ai-inline-icon``.ai-title-badge``.ai-color-*` |
| `components/ai-inline-icon/` | 行首图标标准组件 |
| `components/ai-title-badge/` | 标题徽章标准组件 |
| `assets/icons/ai-robot-inline.svg` | 行首图标 SVG白色 |
| `assets/icons/ai-robot-sm.svg` | 徽章图标 SVG |
| `docs/h5_ui/css/ai-icons.css` | H5 原型参考源文件 |

View File

@@ -0,0 +1,218 @@
# 日期时间展示规范(小程序前端)
> **文档编号**DS-DATETIME-001
> **版本**v1.1.0
> **适用范围**NeoZQYY 小程序所有前端页面
> **最后更新**2026-03-18
---
## 一、设计原则
- **就近优先**:越近的时间用越自然的语言表达,减少认知负担。
- **精度递减**:随时间距离增大,展示精度逐步降低(秒 → 分 → 时 → 天 → 日期)。
- **一致性**:全端统一规则,禁止页面间自行实现差异逻辑。
- **可读性优先**:格式选择以用户直觉理解为准,而非技术精确。
---
## 二、展示规则总表
| 时间距当前的范围 | 展示格式 | 示例 |
|---|---|---|
| 0 秒 119 秒(不足 2 分钟) | `刚刚` | 刚刚 |
| 2 分钟 59 分钟 | `N分钟前` | 2分钟前 / 59分钟前 |
| 1 小时 23 小时 59 分 | `N小时前` | 1小时前 / 23小时前 |
| 24 小时 71 小时 59 分1天3天内 | `N天前` | 1天前 / 3天前 |
| 超过 72 小时3天前以上 | `YYYY-MM-DD` | 2026-03-10 |
> **注**:所有时间差计算以**服务端返回的 UTC 时间戳**为基准,前端根据设备本地时区渲染,不得使用客户端本地时间作为「当前时间」基准。
---
## 三、逐级规则详解
### 3.1 刚刚0 119 秒)
- **触发条件**`now - timestamp < 120 秒`
- **展示文案**`刚刚`
- **说明**2 分钟内的时间差对用户无感知意义,统一收敛为「刚刚」,不展示具体秒数或分钟数。
```
示例:发布于 5 秒前 → 刚刚
发布于 90 秒前 → 刚刚
发布于 119 秒前 → 刚刚
```
---
### 3.2 N 分钟前2 59 分钟)
- **触发条件**`120 秒 ≤ now - timestamp < 3600 秒`
- **展示格式**`Math.floor(diff / 60) + '分钟前'`
- **最小值**2分钟前
- **最大值**59分钟前
```
示例:
diff = 120s → 2分钟前
diff = 3540s → 59分钟前
```
> **不得** 展示「1分钟前」119 秒内均为「刚刚」);**不得** 展示「60分钟前」3600 秒起跳进入「小时」维度。
---
### 3.3 N 小时前1 23 小时)
- **触发条件**`3600 秒 ≤ now - timestamp < 86400 秒`
- **展示格式**`Math.floor(diff / 3600) + '小时前'`
- **最小值**1小时前
- **最大值**23小时前
```
示例:
diff = 3600s → 1小时前
diff = 82800s → 23小时前
```
> **不得** 展示「24小时前」86400 秒起跳进入「天」维度。
---
### 3.4 N 天前1 3 天)
- **触发条件**`86400 秒 ≤ now - timestamp < 259200 秒`(即 1 天 不足 72 小时)
- **展示格式**`Math.floor(diff / 86400) + '天前'`
- **最小值**1天前
- **最大值**3天前
```
示例:
diff = 86400s → 1天前
diff = 259199s → 3天前
```
> **临界说明**72小时259200秒整数点即 diff ≥ 259200 秒,切换为日期格式。
---
### 3.5 日期展示(超过 3 天)
- **触发条件**`now - timestamp ≥ 259200 秒`(≥ 72 小时)
- **展示格式**
- **同年**`MM-DD`(省略年份,如 `03-10`
- **跨年**`YYYY-MM-DD`(保留年份,如 `2025-08-21`
- **分隔符**:使用连字符 `-`,不使用斜杠 `/` 或中文「年月日」
- **不展示时分秒**:日期维度下不展示具体时刻。
```
示例(当前日期 2026-03-18
时间戳 2026-03-10 → 03-10
时间戳 2025-08-21 → 2025-08-21跨年展示完整年份
```
---
## 四、判断流程图
```
输入:服务端时间戳 timestamp
diff = now - timestamp单位
┌─────┴───────┐
│ diff < 120 │──► 刚刚
└─────┬───────┘
┌─────┴──────────┐
│ diff < 3600 │──► N分钟前N = floor(diff/60)2≤N≤59
└─────┬──────────┘
┌─────┴──────────┐
│ diff < 86400 │──► N小时前N = floor(diff/3600)1≤N≤23
└─────┬──────────┘
┌─────┴──────────┐
│ diff < 259200 │──► N天前N = floor(diff/86400)1≤N≤3
└─────┬──────────┘
日期格式同年MM-DD / 跨年YYYY-MM-DD
```
---
## 五、前端实现参考JavaScript
```javascript
/**
* 格式化时间展示
* @param {number} timestamp - 服务端返回的 Unix 时间戳(毫秒)
* @returns {string} 格式化后的时间文案
*/
function formatRelativeTime(timestamp) {
const now = Date.now();
const diff = Math.floor((now - timestamp) / 1000); // 转换为秒
if (diff < 120) {
return '刚刚';
}
if (diff < 3600) {
return `${Math.floor(diff / 60)}分钟前`;
}
if (diff < 86400) {
return `${Math.floor(diff / 3600)}小时前`;
}
if (diff < 259200) { // 72小时 = 3天
return `${Math.floor(diff / 86400)}天前`;
}
// 超过3天展示日期
const date = new Date(timestamp);
const nowDate = new Date(now);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
if (year === nowDate.getFullYear()) {
return `${month}-${day}`; // 同年省略年份
}
return `${year}-${month}-${day}`; // 跨年显示完整年份
}
```
> **微信小程序说明**:可直接将此函数挂载到 `utils/time.js`,在 WXML 中通过 `wxs` 模块或 `Page.data` 绑定使用。
---
## 六、边界与特殊情况处理
| 场景 | 处理方式 |
|---|---|
| `timestamp` 为空 / undefined | 展示 `--`,不报错 |
| `timestamp` 为未来时间(服务端时钟偏差) | 统一展示 `刚刚`diff < 0 时按 0 处理) |
| 用户设备时区异常 | 以服务端返回的格式化日期字段fallback为准 |
| 时间戳单位(秒 vs 毫秒) | 统一由服务端约定为**毫秒**,前端不做猜测 |
---
## 七、禁止事项
- ❌ 禁止展示「1分钟前」「60分钟前」「24小时前」「0分钟前」等临界歧义文案2分钟内统一展示「刚刚」
- ❌ 禁止在「天」维度之后继续展示相对文案如「7天前」「30天前」
- ❌ 禁止使用中文「年月日」格式如「2026年3月10日」统一使用 `-` 分隔符
- ❌ 禁止在超3天后展示时分秒
- ❌ 禁止各页面自行定义时间格式化函数,必须引用 `utils/time.js` 统一工具
---
## 八、关联文档
- [VI 设计规范](./VI-DESIGN-SYSTEM.md)
- [组件库规范](../components/)
- `apps/miniprogram/miniprogram/utils/time.js`(工具函数实现位置)

View File

@@ -0,0 +1,168 @@
# 前端展示规范总表(续)— 第 79 章及附录
> 本文件为 [DISPLAY-STANDARDS.md](./DISPLAY-STANDARDS.md) 的续篇。
---
## 7. 任务截止日期展示规范
### 7.1 规则总表
| 距今时间 | 展示格式 | 样式 |
|---|---|---|
| 今天到期diff = 0 | `今天到期` | 橙色警示 |
| 未来 1 7 天 | `还剩 N 天` | 正常色 |
| 未来 > 7 天 | `MM-DD` | 灰色 |
| 已逾期diff < 0 | `逾期 N 天` | 红色高亮 |
| 空值 | `--` | 灰色 |
### 7.2 计算规则
- 以自然日为单位,当天到期 diff = 0
- `diff = floor((deadline零点 - 今天零点) / 86400000)`
- 不受时分秒影响
### 7.3 实现参考(追加至 `utils/time.ts`
```typescript
export function formatDeadline(deadline: string | null | undefined): {
text: string
style: 'normal' | 'warning' | 'danger' | 'muted'
} {
if (!deadline) return { text: '--', style: 'muted' }
const now = new Date()
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate())
const target = new Date(deadline)
const targetDay = new Date(target.getFullYear(), target.getMonth(), target.getDate())
const diff = Math.round((targetDay.getTime() - today.getTime()) / 86400000)
if (diff < 0) return { text: `逾期 ${Math.abs(diff)}`, style: 'danger' }
if (diff === 0) return { text: '今天到期', style: 'warning' }
if (diff <= 7) return { text: `还剩 ${diff}`, style: 'normal' }
const m = String(target.getMonth() + 1).padStart(2, '0')
const d = String(target.getDate()).padStart(2, '0')
return { text: `${m}-${d}`, style: 'muted' }
}
```
### 7.4 当前涉及位置(待统一)
| 文件 | 问题 |
|---|---|
| `pages/task-list/task-list.wxml` | `deadline` 直接绑定展示,无语义化处理 |
| `utils/mock-data.ts` | `deadline: '2026-03-10'` 格式正确,无需改动 |
---
## 8. 评分与星级展示规范
### 8.1 分制约定
| 来源 | 分制 | 说明 |
|---|---|---|
| 后端 API / Mock | 0 10 分 | heartScore、备注 score 等均用 0-10 |
| UI 星级图标 | 0 5 星(支持半星) | 由 `scoreToStar()` 转换 |
| 手动打分 | 1 5整星 | 用户手动点击打分 |
### 8.2 展示场景规则
| 场景 | 展示方式 |
|---|---|
| 任务卡片关系分 | 星级图标(半星精度) |
| 任务详情关系分 | 星级图标 + 原始分(如 `8.5` |
| 备注满意度评分 | 星级图标(半星精度) |
| 关系等级文字 | 纯文字(从 `RELATIONSHIP_LEVELS` 读取) |
| 未评分score 为 null/undefined/0 | 展示 `--` 替代星星 |
### 8.3 半星映射规则
后端给分四舍五入到最近 0.5 星:
```typescript
// 追加至 utils/rating.ts
export function scoreToHalfStar(score: number): number {
return Math.round(score / 2 * 2) / 2
}
// score=7 → 3.5星score=8 → 4星score=9 → 4.5星
export function isUnrated(score: number | null | undefined): boolean {
return score === null || score === undefined || score === 0
}
```
### 8.4 当前涉及位置(待统一)
| 文件 | 问题 |
|---|---|
| `pages/task-detail/task-detail.wxml` | `fmt.toFixed(detail.heartScore, 1)` 直接格式化,无语义 |
| `utils/mock-data.ts` mockNotes | `score: 7.5` 混用小数,需统一为 0.5 步长整数 |
| `components/star-rating` | 需确认 `score=0` 未评分态是否已处理 |
---
## 9. Mock 数据规范
### 9.1 目标
将各页面内联的 Mock 数据统一迁移至 `utils/mock-data.ts`,方便后端联调时统一替换。
### 9.2 字段类型规范
| 字段类型 | Mock 类型 | 说明 |
|---|---|---|
| 金额 | `number`(元,整数) | 不含 `¥` 前缀 |
| 课时 | `number`小时0.5步长) | 不含 `h` 后缀 |
| 计数 | `number` | 不含单位 |
| 时间戳 | ISO 8601 字符串 | 统一 UTC |
| 日期 | `YYYY-MM-DD` 字符串 | 纯日期 |
| 等级 | 英文 key | `junior/middle/senior/star` |
| 百分比 | `number`0100 | 不含 `%` 符号 |
### 9.3 各页面内联 Mock 待迁移清单
| 页面 | 内联 Mock 内容 | 迁移目标 |
|---|---|---|
| `pages/task-detail/task-detail.ts` | mockNotes、serviceRecords、talkingPoints、retentionClues | `mock-data.ts` |
| `pages/performance-records/performance-records.ts` | dateGroups约30条 | `mock-data.ts` |
| `pages/board-coach/board-coach.ts` | MOCK_COACHES6条 | `mock-data.ts` |
| `pages/task-list/task-list.ts` | buildPerfData() 业绩进度数据 | `mock-data.ts` |
| `pages/customer-service-records/customer-service-records.ts` | 记录转换逻辑 | `mock-data.ts` |
### 9.4 迁移原则
- 迁移后页面 `.ts` 只保留视图逻辑,不再包含业务数据定义
- 每个 Mock 数据对象须有注释标注对应的真实 API 端点(`// TODO: GET /api/xcx/...`
- Mock 字段名与接口文档字段名保持一致,避免联调时大量重命名
- 金额、课时、计数字段统一为 `number` 类型(见 9.2
---
## 附录:工具函数归属总表
| 函数 | 文件 | 状态 |
|---|---|---|
| `formatRelativeTime` | `utils/time.ts` | ✅ 已实现 |
| `formatDeadline` | `utils/time.ts` | 待新增 |
| `formatHours` | `utils/time.ts` | 待新增 |
| `formatMoney` | `utils/money.ts` | 待新建文件 |
| `formatCount` | `utils/money.ts` | 待新建文件 |
| `formatPercent` | `utils/money.ts` | 待新建文件 |
| `toProgressWidth` | `utils/money.ts` | 待新建文件 |
| `scoreToStar` | `utils/rating.ts` | ✅ 已实现 |
| `scoreToHalfStar` | `utils/rating.ts` | 待新增 |
| `isUnrated` | `utils/rating.ts` | 待新增 |
| `getRelationshipLevel` | `utils/vi-colors.ts` | ✅ 已实现 |
| `relativeTime` (WXS) | `utils/time.wxs` | ✅ 已实现 |
| `safe` (WXS) | `utils/format.wxs` | 待新增 |
---
## 关联文档
- [DISPLAY-STANDARDS.md](./DISPLAY-STANDARDS.md) — 第 16 章
- [DATETIME-DISPLAY-STANDARD.md](./DATETIME-DISPLAY-STANDARD.md)
- [VI-DESIGN-SYSTEM.md](./VI-DESIGN-SYSTEM.md)
- `utils/time.ts` — 时间 / 课时 / 截止日期格式化
- `utils/money.ts` — 金额 / 计数 / 百分比格式化(待新建)
- `utils/rating.ts` — 评分 / 星级转换
- `utils/vi-colors.ts` — 等级常量与颜色映射
- `utils/mock-data.ts` — 统一 Mock 数据源

View File

@@ -0,0 +1,292 @@
# 前端展示规范总表(小程序)
> **文档编号**DS-DISPLAY-001
> **版本**v1.0.0
> **适用范围**NeoZQYY 小程序所有前端页面
> **最后更新**2026-03-18
> **关联文档**[日期时间展示规范](./DATETIME-DISPLAY-STANDARD.md)
---
## 目录
1. [金额展示规范](#1-金额展示规范)
2. [课时与时长展示规范](#2-课时与时长展示规范)
3. [数字与计数展示规范](#3-数字与计数展示规范)
4. [空值与缺失值规范](#4-空值与缺失值规范)
5. [百分比展示规范](#5-百分比展示规范)
6. [等级文案规范](#6-等级文案规范)
7. [任务截止日期展示规范](#7-任务截止日期展示规范)
8. [评分与星级展示规范](#8-评分与星级展示规范)
9. [Mock 数据规范](#9-mock-数据规范)
---
## 1. 金额展示规范
### 1.1 规则总表
| 场景 | 格式 | 示例 |
|---|---|---|
| 正常金额 | `¥N,NNN`(千分位逗号,无小数) | `¥12,680` |
| 负数金额 | `-¥N,NNN`(负号在 ¥ 前) | `-¥368` |
| 零值 | `¥0` | `¥0` |
| 空值 / undefined | `--` | `--` |
| 大额金额 | 不简写,保留完整数字 | `¥120,000` |
### 1.2 禁止事项
- ❌ 禁止 `¥-368`(负号位置错误)
- ❌ 禁止 `¥0.00`(零值不保留小数)
- ❌ 禁止 `¥12万`(不做大额简写)
- ❌ 禁止 `toLocaleString()` 直接用于展示(各设备行为不一致)
- ❌ Mock 数据中金额字段统一为 `number` 类型,不含 `¥` 前缀,由格式化层统一添加
### 1.3 实现参考(`utils/money.ts`,待新建)
```typescript
export function formatMoney(value: number | null | undefined): string {
if (value === null || value === undefined) return '--'
if (value === 0) return '¥0'
const abs = Math.round(Math.abs(value))
const formatted = abs.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')
return value < 0 ? `${formatted}` : `¥${formatted}`
}
```
### 1.4 当前涉及位置(待统一)
| 文件 | 问题 |
|---|---|
| `pages/task-list/task-list.ts` | `perf.customerBalance.toLocaleString()` 裸调 |
| `pages/performance-records/performance-records.ts` | Mock 字符串硬编码 `¥510``¥280` 等 |
| `pages/task-detail/task-detail.ts` | `serviceRecords.income` 硬编码 `¥200` 等 |
| `pages/board-coach/board-coach.ts` | `salary``svAmount` 硬编码 `¥12,680` 等 |
---
## 2. 课时与时长展示规范
### 2.1 规则总表
| 场景 | 格式 | 示例 |
|---|---|---|
| 整数小时 | `Nh` | `2h` |
| 非整数小时保留1位 | `N.Nh` | `2.5h` |
| 带折算备注 | `实际h折后 原始h` | `2.0h(折后 2.5h` |
| 零值 | `0h` | `0h` |
| 空值 | `--` | `--` |
### 2.2 实现参考(追加至 `utils/time.ts`
```typescript
export function formatHours(hours: number | null | undefined): string {
if (hours === null || hours === undefined) return '--'
if (hours === 0) return '0h'
return hours % 1 === 0 ? `${hours}h` : `${hours.toFixed(1)}h`
}
```
### 2.3 折算标注字段约定
- `hours`:折算后实际计入课时(`number`
- `hoursRaw`:折算前原始小时数(`number | undefined`
- 仅当 `hoursRaw` 存在且与 `hours` 不同时展示括号备注
- WXML 示例:`{{item.hours}}h{{item.hoursRaw ? '(折后 ' + item.hoursRaw + 'h' : ''}}`
### 2.4 当前使用折算标注的位置(待统一)
| 文件 | 当前写法 | 目标写法 |
|---|---|---|
| `pages/performance-records/performance-records.ts` r7 | `deduct: '(折0.5h)'` 字符串 | `hours: 2, hoursRaw: 2.5`number |
| `pages/performance-records/performance-records.ts` r16 | 同上 | 同上 |
| `pages/performance-records/performance-records.ts` r21 | 同上 | 同上 |
| `pages/performance-records/performance-records.ts` r27 | 同上 | 同上 |
| `pages/task-detail/task-detail.ts` serviceRecords r1 | `durationRaw: '3.0h'` 字符串 | 改为 `number` 类型 |
| `components/service-record-card` | `hours-raw` prop 字符串 | 对齐 `number` 类型后格式化 |
---
## 3. 数字与计数展示规范
### 3.1 规则总表
| 场景 | 规则 | 示例 |
|---|---|---|
| 计数类(笔/次/人) | Mock 只存 `number`,单位由前端模板拼接 | API 返回 `32`WXML 展示 `32笔` |
| 大数字(≥ 1000 | 千分位逗号 | `1,280` |
| 零值 | `--` | `--` |
| 空值 / undefined | `--` | `--` |
### 3.2 单位映射表
| 字段语义 | 单位 |
|---|---|
| 服务记录数 / 交易笔数 | `笔` |
| 到店次数 / 服务次数 | `次` |
| 客户数 / 人数 | `人` |
| 任务数 | `个` |
| 工龄 | `年` |
### 3.3 实现参考(追加至 `utils/money.ts`
```typescript
export function formatCount(
value: number | null | undefined,
unit: string
): string {
if (value === null || value === undefined || value === 0) return '--'
const n = value >= 1000
? value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')
: String(value)
return `${n}${unit}`
}
```
### 3.4 当前涉及位置(待统一)
| 文件 | 问题 |
|---|---|
| `pages/performance-records/performance-records.ts` | `totalCount: '32笔'` 字符串硬编码单位 |
| `pages/customer-service-records/customer-service-records.ts` | `monthCount: '6次'` 字符串硬编码单位 |
| `pages/board-coach/board-coach.ts` | `svCustomerCount: '18'` 裸字符串无单位 |
---
## 4. 空值与缺失值规范
### 4.1 统一占位符:`--`
| 场景 | 处理方式 |
|---|---|
| 数值型字段缺失(金额/课时/评分) | 展示 `--` |
| 文本型字段缺失(名称/备注/标签) | 展示 `--` |
| 列表为空 | 空态组件 `<t-empty />`,不用 `--` |
| 图片加载失败 | 默认占位图,不用 `--` |
### 4.2 禁止事项
- ❌ 禁止向用户展示 `undefined``null``NaN`、空字符串
- ❌ 禁止使用 `暂无``无``N/A``-` 等其他占位符
- ❌ 禁止直接绑定可能为 `undefined` 的字段而不加兜底
### 4.3 WXS 兜底函数(追加至 `utils/format.wxs`
```javascript
function safe(val) {
if (val === undefined || val === null || val === '') return '--'
return val
}
// WXML 用法:{{fmt.safe(item.someField)}}
```
---
## 5. 百分比展示规范
### 5.1 规则总表
| 场景 | 格式 | 示例 |
|---|---|---|
| 展示文字 | 保留1位小数 + `%` | `58.3%``120.0%` |
| 进度条 CSS 宽度 | 保留1位小数截断至100防溢出 | `width:58.3%` |
| 超过100%的展示文字 | 正常展示,不截断 | `120.0%` |
| 零值 | `0%` | `0%` |
| 空值 | `--` | `--` |
### 5.2 实现参考(追加至 `utils/money.ts`
```typescript
export function formatPercent(value: number | null | undefined): string {
if (value === null || value === undefined) return '--'
if (value === 0) return '0%'
return `${value.toFixed(1)}%`
}
export function toProgressWidth(value: number): string {
return `${Math.min(100, Math.max(0, value)).toFixed(1)}%`
}
```
### 5.3 当前涉及位置(待统一)
| 文件 | 问题 |
|---|---|
| `pages/task-list/task-list.ts` | `filledPct` 计算用 `Math.round(*1000)/10`,精度逻辑分散 |
| `pages/task-list/task-list.wxml` | `width: {{perfData.tierProgress}}%` 无小数位 |
---
## 6. 等级文案规范
### 6.1 助教等级
**英文 Key 标准(单一数据源:`vi-colors.ts` `COACH_LEVEL_COLORS`**
| 英文 Key | 中文展示文案 |
|---|---|
| `junior` | 初级 |
| `middle` | 中级 |
| `senior` | 高级 |
| `star` | ⭐ 星级 |
**规范要求:**
- API / Mock 统一返回英文 key
- 所有组件、页面、常量统一使用英文 key中文文案只在渲染层转换
- `coach-level-tag` 组件的 `LEVEL_MAP` 改为英文 key当前为中文 key
**当前待统一的位置:**
| 文件 | 问题 |
|---|---|
| `components/coach-level-tag/coach-level-tag.ts` | `LEVEL_MAP` key 为中文,需改为英文 |
| `pages/board-coach/board-coach.ts` | `level: '星级'` 等直接使用中文字符串 |
| `pages/board-coach/board-coach.ts` `LEVEL_CLASS` | key 为中文,需改为英文 |
| `utils/mock-data.ts` | 助教相关 Mock `level` 字段使用中文 |
### 6.2 关系等级
**英文 Key 标准(单一数据源:`vi-colors.ts` `RELATIONSHIP_LEVELS`**
| 英文 Key | 中文展示文案 | 分数范围 |
|---|---|---|
| `excellent` | 很好 | `> 8.5` |
| `good` | 良好 | `6 ~ 8.5` |
| `normal` | 一般 | `3.5 ~ 6` |
| `poor` | 待发展 | `< 3.5` |
**规范要求:**
- `task-detail.ts` 中的 `updateRelationshipDisplay` 应调用 `vi-colors.ts``getRelationshipLevel()`,不得重复维护判断逻辑
- 中文文案统一从 `RELATIONSHIP_LEVELS[key].name` 读取
**当前待统一的位置:**
| 文件 | 问题 |
|---|---|
| `pages/task-detail/task-detail.ts` | `updateRelationshipDisplay` 内联等级判断逻辑,与 `vi-colors.ts` 重复 |
### 6.3 客户标签类别
**英文 Key 标准(`vi-colors.ts` `CUSTOMER_TAG_COLORS`**
| 英文 Key | 中文展示文案 |
|---|---|
| `basic_info` | 客户基础 |
| `consumption` | 消费习惯 |
| `play_pref` | 玩法偏好 |
| `promo_pref` | 促销偏好 |
| `social` | 社交关系 |
| `feedback` | 重要反馈 |
**规范要求:**
- `CUSTOMER_TAG_COLORS` 的 key 从中文改为英文
- Mock 数据中 `category` 字段统一使用英文 key
**当前待统一的位置:**
| 文件 | 问题 |
|---|---|
| `utils/vi-colors.ts` `CUSTOMER_TAG_COLORS` | key 为中文,需改为英文 |
| `utils/mock-data.ts` `mockRetentionClues` | `category` 字段已是英文,保持不变 |
> 第 79 章及附录见:[DISPLAY-STANDARDS-2.md](./DISPLAY-STANDARDS-2.md)

View File

@@ -0,0 +1,509 @@
# 微信小程序 VI 设计系统
> 最后更新2026-03-17
> 适用范围:台球门店小程序前端所有页面
> 面向对象设计师、前端开发、AI 代码生成
---
## 📋 目录
1. [任务分类配色](#1-任务分类配色)
2. [客户标签配色](#2-客户标签配色)
3. [关系等级配色](#3-关系等级配色)
4. [置顶/放弃状态](#4-置顶放弃状态)
5. [助教等级配色](#5-助教等级配色)
6. [AI 图标配色系统](#6-ai-图标配色系统)
7. [CSS 变量速查表](#7-css-变量速查表)
---
## 1. 任务分类配色
### 1.1 四种任务类型
| 任务类型 | 优先级 | 边框色 | 标签渐变色 | 用途 |
|---------|--------|--------|-----------|------|
| 高优先召回 | 0 | `#dc2626` | `#b91c1c → #dc2626` | max(WBI,NCI) > 7 |
| 优先召回 | 0 | `#f97316` | `#ea580c → #f97316` | max(WBI,NCI) > 5 |
| 客户回访 | 1 | `#14b8a6` | `#0d9488 → #14b8a6` | 完成召回后未备注 |
| 关系构建 | 2 | `#f472b6` | `#ec4899 → #f472b6` | RS < 6 |
### 1.2 WXSS 类名映射
```css
/* 卡片边框 */
.task-card--high_priority { border-left-color: #dc2626; }
.task-card--priority_recall { border-left-color: #f97316; }
.task-card--callback { border-left-color: #14b8a6; }
.task-card--relationship { border-left-color: #f472b6; }
/* 标签渐变 */
.task-type-tag--high_priority { background: linear-gradient(135deg, #b91c1c 0%, #dc2626 100%); }
.task-type-tag--priority_recall { background: linear-gradient(135deg, #ea580c 0%, #f97316 100%); }
.task-type-tag--callback { background: linear-gradient(135deg, #0d9488 0%, #14b8a6 100%); }
.task-type-tag--relationship { background: linear-gradient(135deg, #ec4899 0%, #f472b6 100%); }
```
### 1.3 TypeScript 常量
```typescript
export const TASK_TYPE_COLORS = {
high_priority: {
borderColor: '#dc2626',
gradientFrom: '#b91c1c',
gradientTo: '#dc2626',
label: '高优先召回',
},
priority_recall: {
borderColor: '#f97316',
gradientFrom: '#ea580c',
gradientTo: '#f97316',
label: '优先召回',
},
callback: {
borderColor: '#14b8a6',
gradientFrom: '#0d9488',
gradientTo: '#14b8a6',
label: '客户回访',
},
relationship: {
borderColor: '#f472b6',
gradientFrom: '#ec4899',
gradientTo: '#f472b6',
label: '关系构建',
},
};
```
---
## 2. 客户标签配色
### 2.1 六种客户分类标签
| 标签名 | 字体色 | 背景色 | 心理学依据 | 用途 |
|--------|--------|--------|-----------|------|
| 客户基础 | `#0052d9` | `#ecf2fe` | 蓝色 - 信任、基础信息 | 基本信息、生日、性别等 |
| 消费习惯 | `#00a870` | `#e6f7f0` | 绿色 - 增长、消费行为 | 消费频率、金额、时段 |
| 玩法偏好 | `#ed7b2f` | `#fff3e6` | 橙色 - 活力、娱乐偏好 | 游戏类型、时长偏好 |
| 促销偏好 | `#d4a017` | `#fffbeb` | 金色 - 价值、优惠敏感度 | 对促销活动的反应 |
| 社交关系 | `#764ba2` | `#f3e8ff` | 紫色 - 社交、人脉关系 | 推荐、介绍、社交属性 |
| 重要反馈 | `#e34d59` | `#ffe6e8` | 红色 - 警示、关键信息 | 投诉、建议、重要反馈 |
### 2.2 WXSS 类名映射
```css
.clue-tag-primary { background: rgba(0, 82, 217, 0.1); color: #0052d9; }
.clue-tag-success { background: rgba(0, 168, 112, 0.1); color: #00a870; }
.clue-tag-orange { background: rgba(237, 123, 47, 0.1); color: #ed7b2f; }
.clue-tag-gold { background: rgba(212, 160, 23, 0.1); color: #d4a017; }
.clue-tag-purple { background: rgba(118, 75, 162, 0.1); color: #764ba2; }
.clue-tag-error { background: rgba(227, 77, 89, 0.1); color: #e34d59; }
```
---
## 3. 关系等级配色
### 3.1 四个关系等级
| 关系等级 | 爱心Icon | 分数范围 | 背景渐变 | 文字色 | 用途 |
|---------|---------|---------|---------|--------|------|
| 很好(非常好) | 💖 | > 8.5 | `#e91e63 → #f472b6` | `#fff` | 优质客户 |
| 良好 | 🧡 | 6-8.5 | `#ea580c → #fb923c` | `#fff` | 稳定客户 |
| 一般 | 💛 | 3.5-6 | `#eab308 → #fbbf24` | `#fff` | 普通客户 |
| 待发展 | 💙 | < 3.5 | `#64748b → #94a3b8` | `#fff` | 需维护客户 |
### 3.2 WXSS 类名映射
```css
.rel-level-excellent { background: linear-gradient(135deg, #e91e63, #f472b6); box-shadow: 0 4rpx 12rpx rgba(233,30,99,0.30); }
.rel-level-good { background: linear-gradient(135deg, #ea580c, #fb923c); box-shadow: 0 4rpx 12rpx rgba(234,88,12,0.30); }
.rel-level-normal { background: linear-gradient(135deg, #eab308, #fbbf24); box-shadow: 0 4rpx 12rpx rgba(234,179,8,0.30); }
.rel-level-poor { background: linear-gradient(135deg, #64748b, #94a3b8); box-shadow: 0 4rpx 12rpx rgba(100,116,139,0.30); }
```
---
## 4. 置顶/放弃状态
### 4.1 置顶状态
**视觉处理**:金色边框光晕效果
```css
.task-card--pinned {
box-shadow: 0 5rpx 7rpx rgba(245, 158, 11, 0.12), 0 0 0 8rpx rgba(245, 158, 11, 0.08);
}
```
**颜色值**
- 光晕色:`#f59e0b`(琥珀色)
- 透明度12% + 8%
### 4.2 放弃状态
**视觉处理**:灰化 + 降低透明度
```css
.task-card--abandoned {
border-left-color: #d1d5db !important;
opacity: 0.55;
}
.task-type-tag--abandoned {
background: #d1d5db !important;
}
.customer-name--abandoned {
color: #9ca3af;
}
```
**颜色值**
- 边框色:`#d1d5db`(灰色)
- 文字色:`#9ca3af`(浅灰)
- 透明度55%
---
## 5. 助教等级配色
### 5.1 四级 + 星级
| 等级 | 字体色 | 背景色 | 说明 |
|------|--------|--------|------|
| 初级 | `#0052d9` | `#ecf2fe` | 蓝色 - 信任、基础 |
| 中级 | `#ed7b2f` | `#fff3e6` | 橙色 - 活力、进阶 |
| 高级 | `#e91e63` | `#ffe6e8` | 粉色 - 优雅、资深 |
| ⭐ 星级 | `#fbbf24` | `#fffef0` | 金黄色 - 价值、顶级 |
### 5.2 WXSS 类名映射
```css
.coach-level-junior { color: #0052d9; background: #ecf2fe; }
.coach-level-middle { color: #ed7b2f; background: #fff3e6; }
.coach-level-senior { color: #e91e63; background: #ffe6e8; }
.coach-level-star { color: #fbbf24; background: #fffef0; }
```
---
## 6. AI 图标配色系统
### 6.1 概览
AI 图标系统包含 **2 个标准组件** × **6 种配色**,共 12 种组合。
| 组件 | 路径 | 用途 | 图标文件 |
|------|------|------|----------|
| `ai-inline-icon` | `/components/ai-inline-icon/` | 卡片行首小图标30rpx 容器) | `ai-robot-inline.svg` |
| `ai-title-badge` | `/components/ai-title-badge/` | 标题行右侧徽章(胶囊形态) | `ai-robot-sm.svg` |
### 6.2 六种配色
| 配色名 | 主色 | 浅色 | 深色 | 用途 |
|--------|------|------|------|------|
| Red | `#e74c3c` | `#f39c9c` | `#c0392b` | 警示、重要 |
| Orange | `#e67e22` | `#f5c77e` | `#ca6c17` | 活力、推荐 |
| Yellow | `#d4a017` | `#f7dc6f` | `#b8860b` | 价值、优化 |
| Blue | `#2980b9` | `#7ec8e3` | `#1a5276` | 信息、分析 |
| Indigo | `#667eea` | `#a78bfa` | `#4a5fc7` | 默认、通用 |
| Purple | `#764ba2` | `#c084fc` | `#5b3080` | 创意、特殊 |
### 6.3 组件注册
在页面的 `.json` 文件中按需注册:
```json
{
"usingComponents": {
"ai-inline-icon": "/components/ai-inline-icon/ai-inline-icon",
"ai-title-badge": "/components/ai-title-badge/ai-title-badge"
}
}
```
### 6.4 ai-inline-icon行首嵌入小图标
**外观**
- 尺寸30rpx × 30rpx圆角 6rpx
- 背景:淡色渐变(主色 ~8% 透明度)
- 内部图标:`ai-robot-inline.svg`(白色机身)
- 动效微光扫过12s 周期)
**WXML 用法**
```wxml
<!-- 固定配色 —— indigo默认 -->
<ai-inline-icon />
<!-- 固定配色 —— orange -->
<ai-inline-icon color="orange" />
<!-- 页面随机配色(推荐) -->
<ai-inline-icon color="{{aiColor}}" />
```
**属性**
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `color` | String | `indigo` | 配色:`red` \| `orange` \| `yellow` \| `blue` \| `indigo` \| `purple` |
### 6.5 ai-title-badge标题行 AI 徽章)
**外观**
- 形态:胶囊,`padding: 4rpx 14rpx 4rpx 6rpx`,圆角 18rpx
- 背景:主色 ~8% 透明度渐变 + 主色 35% 边框
- 文字深色主色20rpxfont-weight 500
- 动效呼吸脉冲3s+ 高光扫过14s
**WXML 用法**
```wxml
<!-- 默认配色 + 默认文字「AI智能洞察」 -->
<ai-title-badge />
<!-- 指定配色 -->
<ai-title-badge color="blue" />
<!-- 自定义文字 -->
<ai-title-badge color="orange" label="AI 建议" />
<!-- 页面随机配色(推荐) -->
<ai-title-badge color="{{aiColor}}" />
```
**属性**
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `color` | String | `indigo` | 配色:`red` \| `orange` \| `yellow` \| `blue` \| `indigo` \| `purple` |
| `label` | String | `AI智能洞察` | 徽章文字 |
### 6.6 页面随机配色方案(推荐)
每个页面在 `onLoad` 时随机选取一种配色,全页所有 AI 图标统一使用同一配色。
**TS 实现**
```typescript
const AI_COLORS = ['red', 'orange', 'yellow', 'blue', 'indigo', 'purple'] as const
type AiColor = typeof AI_COLORS[number]
Page({
data: {
aiColor: 'indigo' as AiColor,
},
onLoad() {
const aiColor = AI_COLORS[Math.floor(Math.random() * AI_COLORS.length)]
this.setData({ aiColor })
},
})
```
**WXML 绑定**
```wxml
<!-- 行首图标 -->
<ai-inline-icon color="{{aiColor}}" />
<!-- 标题徽章 -->
<ai-title-badge color="{{aiColor}}" />
```
### 6.7 各页面配色建议(可选固定配色)
如不使用随机方案,可按以下建议固定配色:
| 页面 | 建议配色 | 原因 |
|------|---------|------|
| `task-list` | 随机 | 每日新鲜感 |
| `task-detail` | `indigo` | 通用默认 |
| `task-detail-callback` | `orange` | 与 banner 主题色呼应 |
| `task-detail-relationship` | `purple` | 与 banner 粉色系呼应 |
| `performance` | `blue` | 数据分析感 |
| `customer-detail` | `yellow` | 黑金页面,黄色点缀 |
| `coach-detail` | `red` | coral banner 配红色 AI |
---
## 7. CSS 变量速查表
### 7.1 全局颜色变量app.wxss
```css
page {
/* 主色系 */
--color-primary: #0052d9;
--color-primary-light: #ecf2fe;
--color-success: #00a870;
--color-warning: #ed7b2f;
--color-error: #e34d59;
/* 灰度系13级 */
--color-gray-1: #f3f3f3;
--color-gray-2: #eeeeee;
--color-gray-3: #e7e7e7;
--color-gray-4: #dcdcdc;
--color-gray-5: #c5c5c5;
--color-gray-6: #a6a6a6;
--color-gray-7: #8b8b8b;
--color-gray-8: #777777;
--color-gray-9: #5e5e5e;
--color-gray-10: #4b4b4b;
--color-gray-11: #393939;
--color-gray-12: #2c2c2c;
--color-gray-13: #242424;
}
```
### 7.2 快速查询
**任务类型边框色**
- 高优先召回:`#dc2626`
- 优先召回:`#f97316`
- 客户回访:`#14b8a6`
- 关系构建:`#f472b6`
**客户标签字体色**
- 客户基础:`#0052d9`
- 消费习惯:`#00a870`
- 玩法偏好:`#ed7b2f`
- 促销偏好:`#d4a017`
- 社交关系:`#764ba2`
- 重要反馈:`#e34d59`
**关系等级渐变**
- 很好:`#e91e63 → #f472b6`
- 良好:`#ea580c → #fb923c`
- 一般:`#eab308 → #fbbf24`
- 待发展:`#64748b → #94a3b8`
**助教等级**
- 初级:`#0052d9` / `#ecf2fe`
- 中级:`#ed7b2f` / `#fff3e6`
- 高级:`#e91e63` / `#ffe6e8`
- ⭐ 星级:`#fbbf24` / `#fffef0`
---
## 8. 头像颜色系统
### 8.1 概览
所有客户头像、助教头像统一使用本色板,共 **24 种**渐变色。
全局 WXSS 类名格式:`.avatar-{key}`,定义在 `app.wxss`
TS 工具函数:`nameToAvatarColor(name)` 位于 `utils/avatar-color.ts`
### 8.2 24 色标准色板
| Key | 渐变起点 | 渐变终点 | 视觉风格 |
|-----|---------|---------|--------|
| `blue` | `#60a5fa` | `#3b82f6` | 经典蓝 |
| `indigo` | `#818cf8` | `#4f46e5` | 靛蓝 |
| `violet` | `#a78bfa` | `#7c3aed` | 紫罗兰 |
| `purple` | `#c084fc` | `#9333ea` | 紫色 |
| `fuchsia` | `#bd58c8` | `#7a1486` | 紫红 |
| `pink` | `#d44d96` | `#b83077` | 粉色 |
| `rose` | `#d05060` | `#aa1535` | 玫瑰红 |
| `red` | `#c85050` | `#a81c1c` | 红色 |
| `orange` | `#cc6e22` | `#b04208` | 橙色 |
| `amber` | `#fbbf24` | `#d97706` | 琥珀 |
| `yellow` | `#facc15` | `#ca8a04` | 黄色 |
| `lime` | `#a3e635` | `#65a30d` | 黄绿 |
| `green` | `#4ade80` | `#16a34a` | 绿色 |
| `emerald` | `#34d399` | `#059669` | 翡翠绿 |
| `teal` | `#2dd4bf` | `#0d9488` | 青绿 |
| `cyan` | `#22d3ee` | `#0891b2` | 青色 |
| `sky` | `#38bdf8` | `#0284c7` | 天蓝 |
| `slate` | `#94a3b8` | `#475569` | 石板灰 |
| `coral` | `#cc6245` | `#ad3512` | 珊瑚 |
| `mint` | `#67e8f9` | `#0891b2` | 薄荷 |
| `lavender` | `#c4b5fd` | `#7c3aed` | 薰衣草 |
| `gold` | `#fcd34d` | `#b45309` | 金色 |
| `crimson` | `#c42844` | `#750d28` | 深红 |
| `ocean` | `#38bdf8` | `#1d4ed8` | 海洋蓝 |
### 8.3 WXSS 类名(全局,定义在 app.wxss
```css
.avatar-blue { background: linear-gradient(135deg, #60a5fa, #3b82f6); }
.avatar-indigo { background: linear-gradient(135deg, #818cf8, #4f46e5); }
.avatar-violet { background: linear-gradient(135deg, #a78bfa, #7c3aed); }
.avatar-purple { background: linear-gradient(135deg, #c084fc, #9333ea); }
.avatar-fuchsia { background: linear-gradient(135deg, #bd58c8, #7a1486); }
.avatar-pink { background: linear-gradient(135deg, #d44d96, #b83077); }
.avatar-rose { background: linear-gradient(135deg, #d05060, #aa1535); }
.avatar-red { background: linear-gradient(135deg, #c85050, #a81c1c); }
.avatar-orange { background: linear-gradient(135deg, #cc6e22, #b04208); }
.avatar-amber { background: linear-gradient(135deg, #fbbf24, #d97706); }
.avatar-yellow { background: linear-gradient(135deg, #facc15, #ca8a04); }
.avatar-lime { background: linear-gradient(135deg, #a3e635, #65a30d); }
.avatar-green { background: linear-gradient(135deg, #4ade80, #16a34a); }
.avatar-emerald { background: linear-gradient(135deg, #34d399, #059669); }
.avatar-teal { background: linear-gradient(135deg, #2dd4bf, #0d9488); }
.avatar-cyan { background: linear-gradient(135deg, #22d3ee, #0891b2); }
.avatar-sky { background: linear-gradient(135deg, #38bdf8, #0284c7); }
.avatar-slate { background: linear-gradient(135deg, #94a3b8, #475569); }
.avatar-coral { background: linear-gradient(135deg, #cc6245, #ad3512); }
.avatar-mint { background: linear-gradient(135deg, #67e8f9, #0891b2); }
.avatar-lavender { background: linear-gradient(135deg, #c4b5fd, #7c3aed); }
.avatar-gold { background: linear-gradient(135deg, #fcd34d, #b45309); }
.avatar-crimson { background: linear-gradient(135deg, #c42844, #750d28); }
.avatar-ocean { background: linear-gradient(135deg, #38bdf8, #1d4ed8); }
```
### 8.4 TypeScript 工具utils/avatar-color.ts
```typescript
import { nameToAvatarColor } from '../../utils/avatar-color'
// 根据姓名首字稳定映射颜色(相同输入永远返回相同结果)
const color = nameToAvatarColor('王先生') // => 'blue'
```
### 8.5 WXML 用法
```wxml
<!-- 客户/助教头像 -->
<view class="record-avatar avatar-{{item.avatarColor}}">
<text>{{item.avatarChar}}</text>
</view>
```
### 8.6 迁移说明
各页面原有的散乱类名统一替换为 `.avatar-{key}`
| 旧类名 | 新类名 | 页面 |
|--------|--------|------|
| `.avatar-from-blue` | `.avatar-blue` | performance, performance-records |
| `.avatar-from-pink` | `.avatar-pink` | performance, performance-records |
| `.avatar-from-teal` | `.avatar-teal` | performance, performance-records |
| `.avatar-from-green` | `.avatar-green` | performance, performance-records |
| `.avatar-from-orange` | `.avatar-orange` | performance, performance-records |
| `.avatar-from-purple` | `.avatar-purple` | performance, performance-records |
| `.avatar-from-violet` | `.avatar-violet` | performance, performance-records |
| `.avatar-from-amber` | `.avatar-amber` | performance, performance-records |
| `.avatar-gradient-pink` | `.avatar-pink` | coach-detail |
| `.avatar-gradient-amber` | `.avatar-amber` | coach-detail |
| `.avatar-gradient-green` | `.avatar-green` | coach-detail |
| `.avatar-gradient-blue` | `.avatar-blue` | coach-detail |
| `.avatar-gradient-purple` | `.avatar-violet` | coach-detail |
| `.avatar-gradient-teal` | `.avatar-teal` | coach-detail |
| `.avatar--blue` | `.avatar-blue` | board-coach |
| `.avatar--green` | `.avatar-green` | board-coach |
| `.avatar--pink` | `.avatar-pink` | board-coach |
| `.avatar--amber` | `.avatar-amber` | board-coach |
| `.avatar--purple` | `.avatar-violet` | board-coach |
| `.avatar--cyan` | `.avatar-cyan` | board-coach |
---
**版本:** 1.1
**最后更新:** 2026-03-17
**维护者:** 设计系统团队

View File

@@ -0,0 +1,119 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>VI 设计系统 - 完整指南</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', sans-serif; background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); padding: 40px 20px; line-height: 1.6; color: #333; }
.container { max-width: 1200px; margin: 0 auto; background: white; border-radius: 12px; box-shadow: 0 20px 60px rgba(0,0,0,0.15); overflow: hidden; }
header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 60px 40px; text-align: center; }
header h1 { font-size: 48px; margin-bottom: 10px; font-weight: 700; }
.content { padding: 60px 40px; }
.section { margin-bottom: 80px; }
.section h2 { font-size: 32px; color: #667eea; margin-bottom: 30px; padding-bottom: 15px; border-bottom: 3px solid #667eea; }
table { width: 100%; border-collapse: collapse; margin-bottom: 30px; font-size: 14px; }
table th { background: #f5f5f5; padding: 15px; text-align: left; font-weight: 600; color: #333; border-bottom: 2px solid #ddd; }
table td { padding: 15px; border-bottom: 1px solid #eee; }
.badge { display: inline-block; background: #667eea; color: white; padding: 4px 12px; border-radius: 20px; font-size: 12px; font-weight: 600; }
.color-code { font-family: monospace; background: #f0f0f0; padding: 4px 8px; border-radius: 4px; font-size: 12px; color: #d63384; }
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 15px; }
.color-box { border-radius: 8px; padding: 15px; color: white; text-align: center; font-size: 12px; }
footer { background: #f5f5f5; padding: 30px 40px; text-align: center; font-size: 13px; color: #999; border-top: 1px solid #eee; }
</style>
</head>
<body>
<div class="container">
<header>
<h1>🎨 VI 设计系统 - 完整指南</h1>
<p>台球门店小程序前端设计系统</p>
</header>
<div class="content">
<div class="section">
<h2>1⃣ 任务分类配色</h2>
<table>
<tr><th>任务类型</th><th>边框色</th><th>渐变</th><th>触发条件</th></tr>
<tr><td><span class="badge" style="background: #dc2626;">高优先召回</span></td><td><code class="color-code">#dc2626</code></td><td>#b91c1c → #dc2626</td><td>max(WBI,NCI) > 7</td></tr>
<tr><td><span class="badge" style="background: #f97316;">优先召回</span></td><td><code class="color-code">#f97316</code></td><td>#ea580c → #f97316</td><td>max(WBI,NCI) > 5</td></tr>
<tr><td><span class="badge" style="background: #14b8a6;">客户回访</span></td><td><code class="color-code">#14b8a6</code></td><td>#0d9488 → #14b8a6</td><td>完成召回后未备注</td></tr>
<tr><td><span class="badge" style="background: #f472b6;">关系构建</span></td><td><code class="color-code">#f472b6</code></td><td>#ec4899 → #f472b6</td><td>RS < 6</td></tr>
</table>
</div>
<div class="section">
<h2>2⃣ 客户标签配色6种</h2>
<table>
<tr><th>标签</th><th>字体色</th><th>背景色</th><th>心理学</th></tr>
<tr><td>客户基础</td><td><code class="color-code">#0052d9</code></td><td>#ecf2fe</td><td>蓝色-信任</td></tr>
<tr><td>消费习惯</td><td><code class="color-code">#00a870</code></td><td>#e6f7f0</td><td>绿色-增长</td></tr>
<tr><td>玩法偏好</td><td><code class="color-code">#ed7b2f</code></td><td>#fff3e6</td><td>橙色-活力</td></tr>
<tr><td>促销偏好</td><td><code class="color-code">#d4a017</code></td><td>#fffbeb</td><td>金色-价值</td></tr>
<tr><td>社交关系</td><td><code class="color-code">#764ba2</code></td><td>#f3e8ff</td><td>紫色-社交</td></tr>
<tr><td>重要反馈</td><td><code class="color-code">#e34d59</code></td><td>#ffe6e8</td><td>红色-警示</td></tr>
</table>
</div>
<div class="section">
<h2>3⃣ 关系等级配色</h2>
<table>
<tr><th>等级</th><th>Icon</th><th>分数</th><th>渐变</th></tr>
<tr><td>很好</td><td>💖</td><td>> 8.5</td><td>#e91e63 → #f472b6</td></tr>
<tr><td>良好</td><td>🧡</td><td>6-8.5</td><td>#ea580c → #fb923c</td></tr>
<tr><td>一般</td><td>💛</td><td>3.5-6</td><td>#eab308 → #fbbf24</td></tr>
<tr><td>待发展</td><td>💙</td><td>< 3.5</td><td>#64748b → #94a3b8</td></tr>
</table>
</div>
<div class="section">
<h2>4⃣ 置顶/放弃状态</h2>
<table>
<tr><th>状态</th><th>边框色</th><th>文字色</th><th>透明度</th></tr>
<tr><td>✨ 置顶</td><td>#f59e0b</td><td>-</td><td>金色光晕</td></tr>
<tr><td>❌ 放弃</td><td>#d1d5db</td><td>#9ca3af</td><td>55%</td></tr>
</table>
</div>
<div class="section">
<h2>5⃣ 助教等级配色4级+星级)</h2>
<table>
<tr><th>等级</th><th>字体色</th><th>背景色</th><th>说明</th></tr>
<tr><td>初级</td><td><code class="color-code">#0052d9</code></td><td>#ecf2fe</td><td>蓝色-基础</td></tr>
<tr><td>中级</td><td><code class="color-code">#ed7b2f</code></td><td>#fff3e6</td><td>橙色-进阶</td></tr>
<tr><td>高级</td><td><code class="color-code">#e91e63</code></td><td>#ffe6e8</td><td>粉色-资深</td></tr>
<tr><td>⭐ 星级</td><td><code class="color-code">#fbbf24</code></td><td>#fffef0</td><td>金黄-顶级</td></tr>
</table>
</div>
<div class="section">
<h2>6⃣ AI 图标配色系统</h2>
<h3>标准组件</h3>
<table>
<tr><th>组件</th><th>用途</th><th>路径</th></tr>
<tr><td>ai-inline-icon</td><td>卡片行首小图标</td><td>/components/ai-inline-icon/</td></tr>
<tr><td>ai-title-badge</td><td>标题行徽章</td><td>/components/ai-title-badge/</td></tr>
</table>
<h3>六种配色</h3>
<div class="grid">
<div class="color-box" style="background: linear-gradient(135deg, #e74c3c, #f39c9c);">Red<br>#e74c3c</div>
<div class="color-box" style="background: linear-gradient(135deg, #e67e22, #f5c77e);">Orange<br>#e67e22</div>
<div class="color-box" style="background: linear-gradient(135deg, #d4a017, #f7dc6f);">Yellow<br>#d4a017</div>
<div class="color-box" style="background: linear-gradient(135deg, #2980b9, #7ec8e3);">Blue<br>#2980b9</div>
<div class="color-box" style="background: linear-gradient(135deg, #667eea, #a78bfa);">Indigo<br>#667eea</div>
<div class="color-box" style="background: linear-gradient(135deg, #764ba2, #c084fc);">Purple<br>#764ba2</div>
</div>
</div>
<div class="section">
<h2>7⃣ 全局颜色变量</h2>
<h3>主色系</h3>
<div class="grid">
<div class="color-box" style="background: #0052d9;">Primary<br>#0052d9</div>
<div class="color-box" style="background: #00a870;">Success<br>#00a870</div>
<div class="color-box" style="background: #ed7b2f;">Warning<br>#ed7b2f</div>
<div class="color-box" style="background: #e34d59;">Error<br>#e34d59</div>
<div class="color-box" style="background: #ecf2fe; color: #0052d9;">Primary Light<br>#ecf2fe</div>
</div>
</div>
</div>
<footer>
<p>VI 设计系统 | 完整指南 | 最后更新2026-03-17</p>
<p style="margin-top: 10px;">📄 <a href="VI-DESIGN-SYSTEM.md" style="color: #667eea; text-decoration: none;">查看完整文档</a></p>
</footer>
</div>
</body>
</html>

View File

@@ -0,0 +1,87 @@
# H5 → 微信小程序迁移文档
> 完整的迁移规范、技术换算、交互改造指南
> 最后更新2026-03-17
---
## 📚 文档结构
### 主规范文档
**[`h5-to-mp-bridge.md`](./h5-to-mp-bridge.md)** - 完整迁移规范1081行
包含:
- **§1-4**:执行规程(输入输出、强制决策、能力分级)
- **§5-9**技术换算Spacing、字号、颜色、布局、装饰
- **§10-12**交互改造WXML映射、数据驱动、API替换
- **§13**10步标准流程
- **§14**:附录索引
### 附录文档
**[`appendix/`](./appendix/)** - 详细字典
- [`index.md`](./appendix/index.md) - 附录索引
- [`spacing-dictionary.md`](./appendix/spacing-dictionary.md) - Spacing与尺寸字典181行
- [`typography-dictionary.md`](./appendix/typography-dictionary.md) - 字体与文本字典267行
- [`color-dictionary.md`](./appendix/color-dictionary.md) - 颜色字典199行
- [`layout-dictionary.md`](./appendix/layout-dictionary.md) - 布局类映射字典205行
---
## 🎯 使用指南
### 对于 AI 代码生成
**推荐流程**
1. 先查阅 [`../QUICK-REFERENCE.md`](../QUICK-REFERENCE.md)(快速参考)
2. 需要详细说明时,加载本文档 [`h5-to-mp-bridge.md`](./h5-to-mp-bridge.md)
3. 查表时参考 [`appendix/`](./appendix/) 中的详细字典
### 对于开发者
**推荐流程**
1. 阅读 [`h5-to-mp-bridge.md`](./h5-to-mp-bridge.md) 的 §1-4执行规程
2. 了解输入输出契约和强制决策
3. 按 §13 的 10 步标准流程执行
4. 查表时参考 §5-9 和 [`appendix/`](./appendix/)
---
## 🔑 核心要点
### 1. 单位策略
- **rpx 为主**:布局、容器、间距
- **px 为辅**:发丝线、阴影、小图标
- **换算公式**`rpx = px × 1.8204`
### 2. line-height 关键发现 ⚠️
- 微信小程序的 `<text>` 组件不能直接设置 `line-height`
- 必须在外层 `<view>` 上设置text 会自动继承
- 详见主规范 §2.6 和 §6.2
### 3. 数据驱动
- 禁止使用 DOM 操作(`document.*``element.classList.*`
- 所有交互改为 `setData` + 条件渲染
- 详见主规范 §11
### 4. 能力分级
- **A 类**可直接使用flex、transition、animation 等)
- **B 类**有条件使用sticky、grid、backdrop-filter 等)
- **C 类**禁止直迁DOM API、浏览器 API 等)
- 详见主规范 §3
---
## 📖 快速链接
- [完整迁移规范](./h5-to-mp-bridge.md)
- [附录索引](./appendix/index.md)
- [Spacing 字典](./appendix/spacing-dictionary.md)
- [字体字典](./appendix/typography-dictionary.md)
- [颜色字典](./appendix/color-dictionary.md)
- [布局字典](./appendix/layout-dictionary.md)
- [返回总索引](../README.md)
---
**版本**v3.0 | **最后更新**2026-03-17