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 { 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) } }