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

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`(工具函数实现位置)