使用 i18n.t() 全局方式(避免 hook 定位问题): - 288 目标文件中 135 个成功转换 - 2228 处中文替换为 i18n.t() 调用 - 1006 个新翻译 key 添加到 zh-CN.json + en-US.json - 词典总量: 3554 keys (22 namespaces) - tsc 零错误 + Vite 构建成功 - 6 个含代码示例/数据字符串的文件安全回退
172 lines
5.7 KiB
TypeScript
172 lines
5.7 KiB
TypeScript
import i18n from '@/i18n';
|
|
// 站点拨测辅助函数 // Logan.Li
|
|
|
|
export const PROBE_TYPE_OPTIONS = ['HTTP', 'SSL', 'TCP', 'DNS', 'PING'] as const;
|
|
export type ProbeType = (typeof PROBE_TYPE_OPTIONS)[number];
|
|
|
|
export interface SiteTask {
|
|
id: number;
|
|
name: string;
|
|
url: string;
|
|
type: string;
|
|
frequency_sec: number;
|
|
timeout_sec: number;
|
|
expected_status_code: number;
|
|
enabled: boolean;
|
|
last_status?: string;
|
|
last_response_time_ms?: number;
|
|
last_checked_at?: string;
|
|
success_rate?: number;
|
|
alert_status?: 'normal' | 'alerting';
|
|
created_at: string;
|
|
ssl_days_remaining?: number;
|
|
ssl_cert_expiry?: string;
|
|
}
|
|
|
|
export interface SiteResult {
|
|
id: number;
|
|
task_id: number;
|
|
status: string;
|
|
http_status_code?: number;
|
|
response_time?: number;
|
|
total_time: number;
|
|
remote_ip?: string;
|
|
error_message?: string;
|
|
checked_at: string;
|
|
ssl_days_remaining?: number;
|
|
ssl_cert_expiry?: string;
|
|
ssl_cert_issuer?: string;
|
|
}
|
|
|
|
export interface SiteStats {
|
|
total_tasks: number;
|
|
enabled_tasks: number;
|
|
up_count: number;
|
|
down_count: number;
|
|
availability: number;
|
|
probe_count: number;
|
|
}
|
|
|
|
export type SiteTimeRange = '1h' | '6h' | '24h' | '7d';
|
|
|
|
export const SITE_TIME_RANGE_HOURS: Record<SiteTimeRange, number> = {
|
|
'1h': 1,
|
|
'6h': 6,
|
|
'24h': 24,
|
|
'7d': 168,
|
|
};
|
|
|
|
export const SITE_TIME_RANGE_LABELS: Record<SiteTimeRange, string> = {
|
|
'1h': i18n.t('monitor.helpersts.sf972b7b1'),
|
|
'6h': i18n.t('monitor.siteProtocol.rangeDefault'),
|
|
'24h': i18n.t('monitor.helpersts.s6e99b786'),
|
|
'7d': i18n.t('monitor.helpersts.sd765efc4'),
|
|
};
|
|
|
|
/** 各协议推荐默认拨测间隔(秒)// Logan.Li */
|
|
export const DEFAULT_PROBE_FREQUENCY: Record<ProbeType, number> = {
|
|
HTTP: 60,
|
|
SSL: 3600,
|
|
TCP: 120,
|
|
DNS: 300,
|
|
PING: 120,
|
|
};
|
|
|
|
/** 各协议最小拨测间隔(秒)// Logan.Li */
|
|
export const MIN_PROBE_FREQUENCY: Record<ProbeType, number> = {
|
|
HTTP: 30,
|
|
SSL: 600,
|
|
TCP: 30,
|
|
DNS: 60,
|
|
PING: 30,
|
|
};
|
|
|
|
export function defaultProbeFrequency(type: ProbeType): number {
|
|
return DEFAULT_PROBE_FREQUENCY[type] ?? 60;
|
|
}
|
|
|
|
export const probeTypeMeta: Record<ProbeType, { label: string; placeholder: string; hint: string }> = {
|
|
HTTP: { label: i18n.t('monitor.helpersts.s277c74b4'), placeholder: 'https://example.com/health', hint: i18n.t('monitor.helpersts.s953f0b93') },
|
|
SSL: { label: i18n.t('monitor.helpersts.s8e3a1ea5'), placeholder: i18n.t('monitor.helpersts.s8a6cb9ae'), hint: i18n.t('monitor.helpersts.sefe596b0') },
|
|
TCP: { label: i18n.t('monitor.helpersts.seeda3abc'), placeholder: i18n.t('monitor.helpersts.sd315f501'), hint: i18n.t('monitor.helpersts.s5a87d291') },
|
|
DNS: { label: i18n.t('cloud.domainName'), placeholder: 'example.com', hint: i18n.t('monitor.helpersts.sd3fd8f1d') },
|
|
PING: { label: i18n.t('monitor.helpersts.saeb5271e'), placeholder: i18n.t('monitor.helpersts.sd6bbd624'), hint: i18n.t('monitor.helpersts.se850c8e9') },
|
|
};
|
|
|
|
export function probeFrequencyHint(type: ProbeType): string {
|
|
const sec = defaultProbeFrequency(type);
|
|
return `推荐 ${fmtFrequency(sec)},最小 ${fmtFrequency(MIN_PROBE_FREQUENCY[type])}`;
|
|
}
|
|
|
|
/** 拨测频率展示 // Logan.Li */
|
|
export function fmtFrequency(sec?: number): string {
|
|
if (!sec) return '--';
|
|
if (sec < 60) return `${sec}秒`;
|
|
if (sec < 3600) return `${Math.round(sec / 60)}分钟`;
|
|
return `${(sec / 3600).toFixed(1)}小时`;
|
|
}
|
|
|
|
/** 可用率 / 响应时间组合展示 // Logan.Li */
|
|
export function fmtAvailResponse(task: Pick<SiteTask, 'success_rate' | 'last_response_time_ms'>): string {
|
|
const avail = task.success_rate != null && task.success_rate >= 0
|
|
? `${task.success_rate.toFixed(1)}%`
|
|
: '--';
|
|
return `${avail} / ${fmtMs(task.last_response_time_ms)}`;
|
|
}
|
|
|
|
export function fmtMs(ms?: number): string {
|
|
if (ms == null) return '--';
|
|
if (ms < 1) return '0ms';
|
|
if (ms < 1000) return `${Math.round(ms)}ms`;
|
|
return `${(ms / 1000).toFixed(2)}s`;
|
|
}
|
|
|
|
/** 列表时间:MM-DD HH:mm // Logan.Li */
|
|
export function fmtTime(iso?: string): string {
|
|
if (!iso) return '--';
|
|
const d = new Date(iso);
|
|
const pad = (n: number) => String(n).padStart(2, '0');
|
|
return `${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`;
|
|
}
|
|
|
|
/** SSL 证书预警阈值(天)// Logan.Li */
|
|
export const SSL_EXPIRY_WARN_DAYS = 30;
|
|
|
|
/** 是否为 SSL 证书拨测任务 // Logan.Li */
|
|
export function isSslProbeTask(task: Pick<SiteTask, 'type'>): boolean {
|
|
const t = task.type?.toUpperCase();
|
|
return t === 'SSL' || t === 'HTTPS';
|
|
}
|
|
|
|
/** 证书是否进入预警期(默认 < 30 天)// Logan.Li */
|
|
export function isSslExpiringSoon(days?: number, threshold = SSL_EXPIRY_WARN_DAYS): boolean {
|
|
return days != null && days < threshold;
|
|
}
|
|
|
|
/** SSL 证书剩余天数展示 // Logan.Li */
|
|
export function fmtSslDays(days?: number): { text: string; tone: string } {
|
|
if (days == null) return { text: '--', tone: 'text-[var(--dg-text-muted)]' };
|
|
if (days < 0) return { text: i18n.t('system.expired2'), tone: 'dg-text-red' };
|
|
if (days <= 7) return { text: `${days}天`, tone: 'dg-text-red' };
|
|
if (days <= 30) return { text: `${days}天`, tone: 'dg-text-yellow' };
|
|
return { text: `${days}天`, tone: 'dg-text-green' };
|
|
}
|
|
|
|
/** 归一化拨测协议类型 // Logan.Li */
|
|
export function normalizeProbeType(raw?: string): ProbeType {
|
|
const upper = (raw || 'HTTP').toUpperCase();
|
|
if (upper === 'HTTPS') return 'HTTP';
|
|
if (PROBE_TYPE_OPTIONS.includes(upper as ProbeType)) return upper as ProbeType;
|
|
return 'HTTP';
|
|
}
|
|
|
|
export function isHttpProbeTask(task: Pick<SiteTask, 'type'>): boolean {
|
|
return normalizeProbeType(task.type) === 'HTTP';
|
|
}
|
|
|
|
export function fmtChartTime(iso?: string): string {
|
|
if (!iso) return '';
|
|
const d = new Date(iso);
|
|
const pad = (n: number) => String(n).padStart(2, '0');
|
|
return `${pad(d.getHours())}:${pad(d.getMinutes())}`;
|
|
} |