新增: 初始化 DevFlow 项目仓库
Tauri 2 + Vue 3 + Vite 6 桌面应用,Rust workspace 含 13 个 crate (df-ai / df-storage / df-workflow / df-core / df-execute 等)。 核心能力:AI 聊天 agentic 循环(工具调用+人工审批)、工作流引擎、 任务/想法/项目/阶段管理、可追溯性,及配套前端组件。
This commit is contained in:
52
src/utils/time.ts
Normal file
52
src/utils/time.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* 统一时间戳解析与格式化 — 根治前端时间显示 NaN 问题
|
||||
*
|
||||
* 后端 (df-storage) 统一以「毫秒数字字符串」存储 created_at / updated_at
|
||||
* (见 src-tauri now_millis:`SystemTime::now().as_millis().to_string()`)。
|
||||
*
|
||||
* 陷阱:`new Date("1718000000000")` 返回 Invalid Date —— JS 规范只对 number 类型
|
||||
* 按时间戳解析,纯数字字符串走日期字符串解析路径会失败 → getTime() = NaN
|
||||
* → `"{n} 天前".format(NaN)` = "NaN 天前"。
|
||||
*
|
||||
* 正确做法:先转 number 再 new Date。本模块统一处理毫秒字符串 / 秒级 / ISO / number / 空。
|
||||
*/
|
||||
|
||||
/** 解析任意时间值为毫秒时间戳;无效或空返回 null */
|
||||
export function parseTs(v: string | number | null | undefined): number | null {
|
||||
if (v == null) return null
|
||||
if (typeof v === 'number') {
|
||||
if (!Number.isFinite(v)) return null
|
||||
return v > 1e12 ? v : v * 1000 // 秒级 → 毫秒
|
||||
}
|
||||
const s = String(v).trim()
|
||||
if (!s) return null
|
||||
// 纯数字字符串:> 1e12 视为毫秒,否则秒
|
||||
if (/^\d+$/.test(s)) {
|
||||
const n = Number(s)
|
||||
return n > 1e12 ? n : n * 1000
|
||||
}
|
||||
// ISO / 其他日期字符串
|
||||
const ms = new Date(s).getTime()
|
||||
return isNaN(ms) ? null : ms
|
||||
}
|
||||
|
||||
/** 绝对日期 'YYYY/MM/DD HH:mm';无效返回 '—' */
|
||||
export function formatDate(v: string | number | null | undefined): string {
|
||||
const ms = parseTs(v)
|
||||
if (ms == null) return '—'
|
||||
const d = new Date(ms)
|
||||
return d.toLocaleDateString('zh-CN') + ' ' + d.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' })
|
||||
}
|
||||
|
||||
/** 中文相对时间 '刚刚 / X 分钟前 / X 小时前 / X 天前';无效返回 '—' */
|
||||
export function formatRelativeZh(v: string | number | null | undefined): string {
|
||||
const ms = parseTs(v)
|
||||
if (ms == null) return '—'
|
||||
const diffMin = Math.floor((Date.now() - ms) / 60000)
|
||||
if (diffMin < 1) return '刚刚'
|
||||
if (diffMin < 60) return `${diffMin} 分钟前`
|
||||
const diffH = Math.floor(diffMin / 60)
|
||||
if (diffH < 24) return `${diffH} 小时前`
|
||||
const diffD = Math.floor(diffH / 24)
|
||||
return `${diffD} 天前`
|
||||
}
|
||||
Reference in New Issue
Block a user