Files
Neo-ZQYY/docs/miniprogram-dev/design-system/DISPLAY-STANDARDS.md

293 lines
9.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 前端展示规范总表(小程序)
> **文档编号**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)