import test from 'node:test' import assert from 'node:assert/strict' import { readFile } from 'node:fs/promises' import ts from 'typescript' function toModuleUrl(source) { const { outputText } = ts.transpileModule(source, { compilerOptions: { module: ts.ModuleKind.ESNext, target: ts.ScriptTarget.ESNext } }) return `data:text/javascript;base64,${Buffer.from(outputText).toString('base64')}` } const formatModuleUrl = toModuleUrl(await readFile('src/utils/business/format.ts', 'utf8')) const { formatDateTime } = await import(formatModuleUrl) const realNameTimeSource = await readFile('src/utils/business/realNameTime.ts', 'utf8') const { formatRealNameTime } = await import( toModuleUrl(realNameTimeSource.replace("from './format'", `from '${formatModuleUrl}'`)) ) test('实名时间在现有时区换算基础上额外增加 8 小时', () => { const cases = [ ['2026-10-09T01:02:03Z', '2026-10-09 17:02:03'], ['2026-10-09T01:02:03+00:00', '2026-10-09 17:02:03'], ['2026-10-09T01:02:03+08:00', '2026-10-09 09:02:03'], ['2026-10-09T01:02:03-05:00', '2026-10-09 22:02:03'], ['2026-10-09 01:02:03', '2026-10-09 09:02:03'], ['2026-10-09T01:02:03', '2026-10-09 09:02:03'], ['2026-10-09', '2026-10-09 08:00:00'] ] for (const [input, expected] of cases) { assert.equal(formatRealNameTime(input), expected, input) } }) test('实名时间支持秒、毫秒时间戳及 Date 对象', () => { const timestamp = Date.parse('2026-10-09T01:02:03Z') for (const input of [ timestamp, timestamp / 1000, String(timestamp), String(timestamp / 1000), new Date(timestamp) ]) { assert.equal(formatRealNameTime(input), '2026-10-09 17:02:03') } }) test('实名时间加 8 小时正确处理跨日、跨年和闰日', () => { assert.equal(formatRealNameTime('2026-10-09 20:30:00'), '2026-10-10 04:30:00') assert.equal(formatRealNameTime('2026-12-31 20:30:00'), '2027-01-01 04:30:00') assert.equal(formatRealNameTime('2024-02-28 20:30:00'), '2024-02-29 04:30:00') assert.equal(formatRealNameTime('2024-02-29 20:30:00'), '2024-03-01 04:30:00') }) test('实名时间为空或无效时保留占位符', () => { for (const input of [undefined, null, '', ' ', 'invalid', NaN, new Date(NaN)]) { assert.equal(formatRealNameTime(input), '-') } }) test('通用时间格式化逻辑保持不变', () => { assert.equal(formatDateTime('2026-10-09T01:02:03Z'), '2026-10-09 09:02:03') assert.equal(formatDateTime('2026-10-09 01:02:03'), '2026-10-09 01:02:03') }) test('实名时间展示不依赖运行环境时区', () => { const originalTimezone = process.env.TZ try { for (const timezone of ['UTC', 'Asia/Shanghai', 'America/New_York']) { process.env.TZ = timezone assert.equal(formatRealNameTime('2026-10-09 01:02:03'), '2026-10-09 09:02:03') assert.equal(formatRealNameTime('2026-10-09T01:02:03Z'), '2026-10-09 17:02:03') } } finally { if (originalTimezone === undefined) delete process.env.TZ else process.env.TZ = originalTimezone } }) test('资产信息仅在卡信息、设备信息及绑定卡列表的实名时间使用额外偏移', async () => { const component = await readFile( 'src/views/asset-management/asset-information/components/BasicInfoCard.vue', 'utf8' ) assert.ok(component.includes('formatRealNameTime(cardInfo?.real_name_at)')) assert.ok(component.includes('formatRealNameTime(selectedDeviceStatusCard?.real_name_at)')) assert.ok(component.includes('formatRealNameTime(bindingCard.real_name_at)')) assert.equal(component.match(/formatRealNameTime\(/g)?.length, 3) assert.ok(component.includes('formatAssetInfoTime(cardInfo?.last_real_name_check_at)')) assert.ok(component.includes('formatAssetInfoTime(cardInfo?.last_card_status_check_at)')) assert.ok(component.includes('formatAssetInfoTime(cardInfo?.last_data_check_at)')) assert.ok( component.includes( 'const formatAssetInfoTime = (value?: string | null) => formatDateTime(value)' ) ) })