Initial commit: TaskPool React panel

- React frontend with route-level code splitting
- Backend rebranded from Baihu to TaskPool
- DB brand migration script and local compatibility
This commit is contained in:
2026-07-26 08:43:52 +08:00
commit e6956aa001
397 changed files with 73621 additions and 0 deletions
+46
View File
@@ -0,0 +1,46 @@
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)
}
}