e6956aa001
- React frontend with route-level code splitting - Backend rebranded from Baihu to TaskPool - DB brand migration script and local compatibility
47 lines
1.6 KiB
TypeScript
47 lines
1.6 KiB
TypeScript
export function formatDuration(ms?: number | null): string {
|
|
if (ms == null || Number.isNaN(ms)) return '-'
|
|
if (ms < 1000) return `${Math.round(ms)}毫秒`
|
|
if (ms < 60000) return `${(ms / 1000).toFixed(1)}秒`
|
|
if (ms < 3600000) return `${(ms / 60000).toFixed(1)}分钟`
|
|
return `${(ms / 3600000).toFixed(1)}小时`
|
|
}
|
|
|
|
export function formatDateTime(value?: string | null): string {
|
|
if (!value || value === '-') return '-'
|
|
const d = new Date(value)
|
|
if (Number.isNaN(d.getTime())) return value
|
|
return d.toLocaleString()
|
|
}
|
|
|
|
/** 简单 cron 说明(6 段秒级或 5 段) */
|
|
export function getCronDescription(expr?: string | null): string {
|
|
if (!expr?.trim()) return '未设置'
|
|
const parts = expr.trim().split(/\s+/)
|
|
if (parts.length < 5) return expr
|
|
// 常见快捷
|
|
if (expr === '0 * * * * *' || expr === '* * * * *') return '每分钟'
|
|
if (expr === '0 0 * * * *' || expr === '0 * * * *') return '每小时'
|
|
if (expr === '0 0 0 * * *' || expr === '0 0 * * *') return '每天 0 点'
|
|
if (expr.startsWith('*/')) return `周期: ${expr}`
|
|
return expr
|
|
}
|
|
|
|
export function copyToClipboard(text: string): Promise<boolean> {
|
|
if (navigator.clipboard?.writeText) {
|
|
return navigator.clipboard.writeText(text).then(() => true).catch(() => false)
|
|
}
|
|
try {
|
|
const ta = document.createElement('textarea')
|
|
ta.value = text
|
|
ta.style.position = 'fixed'
|
|
ta.style.left = '-9999px'
|
|
document.body.appendChild(ta)
|
|
ta.select()
|
|
const ok = document.execCommand('copy')
|
|
document.body.removeChild(ta)
|
|
return Promise.resolve(ok)
|
|
} catch {
|
|
return Promise.resolve(false)
|
|
}
|
|
}
|