first commit

This commit is contained in:
Awuqing
2026-03-17 13:29:09 +08:00
commit eadd3f8961
219 changed files with 22394 additions and 0 deletions

11
web/src/utils/error.ts Normal file
View File

@@ -0,0 +1,11 @@
import axios from 'axios'
export function resolveErrorMessage(error: unknown, fallback = '请求失败,请稍后重试') {
if (axios.isAxiosError(error)) {
return error.response?.data?.message ?? fallback
}
if (error instanceof Error && error.message) {
return error.message
}
return fallback
}

View File

@@ -0,0 +1,16 @@
import { describe, expect, it } from 'vitest'
import { formatBytes, formatDuration, formatPercent } from './format'
describe('format utils', () => {
it('formats bytes into readable units', () => {
expect(formatBytes(0)).toBe('0 B')
expect(formatBytes(1024)).toBe('1 KB')
expect(formatBytes(1536)).toBe('1.5 KB')
})
it('formats percent and duration', () => {
expect(formatPercent(0.56)).toBe('56%')
expect(formatDuration(45)).toBe('45 秒')
expect(formatDuration(3661)).toBe('1 小时 1 分 1 秒')
})
})

56
web/src/utils/format.ts Normal file
View File

@@ -0,0 +1,56 @@
export function formatDateTime(value?: string | Date | null) {
if (!value) {
return '-'
}
const date = value instanceof Date ? value : new Date(value)
if (Number.isNaN(date.getTime())) {
return '-'
}
return new Intl.DateTimeFormat('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
}).format(date)
}
export function formatBytes(value?: number | null) {
if (!value || value <= 0) {
return '0 B'
}
const units = ['B', 'KB', 'MB', 'GB', 'TB']
let current = value
let index = 0
while (current >= 1024 && index < units.length - 1) {
current /= 1024
index += 1
}
const digits = current >= 10 || index === 0 ? 0 : 1
const formatted = current.toFixed(digits).replace(/\.0$/, '')
return `${formatted} ${units[index]}`
}
export function formatPercent(value?: number | null) {
if (typeof value !== 'number' || Number.isNaN(value)) {
return '0%'
}
return `${(value * 100).toFixed(value >= 0.1 ? 0 : 1)}%`
}
export function formatDuration(seconds?: number | null) {
if (!seconds || seconds <= 0) {
return '0 秒'
}
if (seconds < 60) {
return `${seconds}`
}
const hours = Math.floor(seconds / 3600)
const minutes = Math.floor((seconds % 3600) / 60)
const remainSeconds = seconds % 60
if (hours > 0) {
return `${hours} 小时 ${minutes}${remainSeconds}`
}
return `${minutes}${remainSeconds}`
}