feat(admin): 数据总览按客迹视觉V1重做(周期卡/趋势双线/渠道条形/最近访问)
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -80,6 +80,29 @@ export function channelBadge(row: ChannelBadgeRow): string {
|
||||
export const formatDateTime = (iso?: string | null): string =>
|
||||
iso ? iso.replace('T', ' ').slice(0, 16) : '—'
|
||||
|
||||
/** 上海自然日今天(YYYY-MM-DD;后端 ISO 串同为上海时间,日期部分可直接比对) */
|
||||
const shanghaiDate = (): string =>
|
||||
new Intl.DateTimeFormat('en-CA', { timeZone: 'Asia/Shanghai' }).format(new Date())
|
||||
|
||||
/** YYYY-MM-DD 平移 n 天(按 UTC 毫秒运算,不受本地时区夏令时干扰) */
|
||||
const shiftDate = (date: string, days: number): string => {
|
||||
const d = new Date(`${date}T00:00:00Z`)
|
||||
d.setUTCDate(d.getUTCDate() + days)
|
||||
return d.toISOString().slice(0, 10)
|
||||
}
|
||||
|
||||
/** ISO 时间 → 智能短时间:今天 HH:mm / 昨天 HH:mm / 更早 MM-DD HH:mm(空值 —)
|
||||
* 后端已是上海时间,日期部分与 shanghaiDate 同口径比对,不做时区换算 */
|
||||
export const formatSmartTime = (iso?: string | null): string => {
|
||||
if (!iso) return '—'
|
||||
const date = iso.slice(0, 10)
|
||||
const time = iso.slice(11, 16)
|
||||
const today = shanghaiDate()
|
||||
if (date === today) return `今天 ${time}`
|
||||
if (date === shiftDate(today, -1)) return `昨天 ${time}`
|
||||
return `${date.slice(5)} ${time}`
|
||||
}
|
||||
|
||||
/** 毫秒 → x天x小时x分x秒(智能省略:为 0 的单位不显示;全 0 / 不足 1 秒显示 0秒) */
|
||||
export const formatStay = (ms?: number | null): string => {
|
||||
const totalSec = Math.max(0, Math.floor((ms ?? 0) / 1000))
|
||||
|
||||
Reference in New Issue
Block a user