小程序迁移 静态页面完成!!!
This commit is contained in:
218
docs/miniprogram-dev/design-system/DATETIME-DISPLAY-STANDARD.md
Normal file
218
docs/miniprogram-dev/design-system/DATETIME-DISPLAY-STANDARD.md
Normal 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`(工具函数实现位置)
|
||||
168
docs/miniprogram-dev/design-system/DISPLAY-STANDARDS-2.md
Normal file
168
docs/miniprogram-dev/design-system/DISPLAY-STANDARDS-2.md
Normal file
@@ -0,0 +1,168 @@
|
||||
# 前端展示规范总表(续)— 第 7~9 章及附录
|
||||
|
||||
> 本文件为 [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`(0~100) | 不含 `%` 符号 |
|
||||
|
||||
### 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_COACHES(6条) | `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) — 第 1~6 章
|
||||
- [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 数据源
|
||||
292
docs/miniprogram-dev/design-system/DISPLAY-STANDARDS.md
Normal file
292
docs/miniprogram-dev/design-system/DISPLAY-STANDARDS.md
Normal 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` 字段已是英文,保持不变 |
|
||||
|
||||
> 第 7~9 章及附录见:[DISPLAY-STANDARDS-2.md](./DISPLAY-STANDARDS-2.md)
|
||||
509
docs/miniprogram-dev/design-system/VI-DESIGN-SYSTEM.md
Normal file
509
docs/miniprogram-dev/design-system/VI-DESIGN-SYSTEM.md
Normal 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% 边框
|
||||
- 文字:深色主色,20rpx,font-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
|
||||
**维护者:** 设计系统团队
|
||||
119
docs/miniprogram-dev/design-system/vi-guide.html
Normal file
119
docs/miniprogram-dev/design-system/vi-guide.html
Normal 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>
|
||||
Reference in New Issue
Block a user