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

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

@@ -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>