Files
pikasTech-HWLAB/web/hwlab-cloud-web/src/utils/index.ts
T

67 lines
2.6 KiB
TypeScript

export function asRecord(value: unknown): Record<string, unknown> | null {
return value && typeof value === "object" ? value as Record<string, unknown> : null;
}
export function nonEmptyString(value: unknown): string | null {
if (typeof value !== "string") return null;
const text = value.trim();
return text ? text : null;
}
export function firstNonEmptyString(...values: unknown[]): string | null {
for (const value of values) {
const text = nonEmptyString(value);
if (text) return text;
}
return null;
}
export function normalizeWorkbenchConversationId(value: unknown): string | null {
const text = nonEmptyString(value);
if (!text) return null;
return /^cnv_[A-Za-z0-9_.:-]+$/u.test(text) ? text : null;
}
export function normalizeWorkbenchSessionId(value: unknown): string | null {
const text = nonEmptyString(value);
if (!text) return null;
return /^ses_[A-Za-z0-9_.:-]+$/u.test(text) ? text : null;
}
export function normalizeWorkbenchSessionRouteId(value: unknown): string | null {
const text = nonEmptyString(value);
if (!text) return null;
return normalizeWorkbenchSessionId(text) ?? normalizeWorkbenchConversationId(text);
}
export function workbenchSessionPath(sessionId: string): string {
return `/workbench/sessions/${encodeURIComponent(sessionId)}`;
}
export function nextProtocolId(prefix: string): string {
const cryptoApi = typeof crypto !== "undefined" ? crypto : null;
const suffix = cryptoApi?.randomUUID ? cryptoApi.randomUUID().replace(/-/gu, "").slice(0, 16) : `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 8)}`;
return `${prefix}_${suffix}`;
}
export function statusTone(status: string | undefined | null): string {
const text = String(status ?? "").toLowerCase();
if (["completed", "ok", "healthy", "ready", "active"].includes(text)) return "ok";
if (["running", "accepted", "pending", "processing"].includes(text)) return "pending";
if (["warn", "warning", "degraded", "build_time_unavailable"].includes(text)) return "warn";
if (["blocked", "stale"].includes(text)) return "blocked";
if (["failed", "error", "timeout", "canceled", "cancelled"].includes(text)) return "error";
return "pending";
}
export function formatRelativeTime(value: string | null | undefined): string {
if (!value) return "未记录";
const date = new Date(value);
if (!Number.isFinite(date.getTime())) return value;
const delta = Date.now() - date.getTime();
if (delta < 60_000) return "刚刚";
if (delta < 3_600_000) return `${Math.round(delta / 60_000)} 分钟前`;
if (delta < 86_400_000) return `${Math.round(delta / 3_600_000)} 小时前`;
return date.toLocaleString();
}