export const DEVICE_ASSET_STATUS_VALUES = ["active", "maintenance", "disabled", "retired"] as const; export type DeviceAssetStatus = (typeof DEVICE_ASSET_STATUS_VALUES)[number]; export const MAINTENANCE_TICKET_STATUS_VALUES = ["open", "assigned", "resolved", "closed", "cancelled"] as const; export type MaintenanceTicketStatus = (typeof MAINTENANCE_TICKET_STATUS_VALUES)[number]; export const MAINTENANCE_TICKET_PRIORITY_VALUES = ["low", "normal", "high", "urgent"] as const; export type MaintenanceTicketPriority = (typeof MAINTENANCE_TICKET_PRIORITY_VALUES)[number]; export const DEVICE_ASSET_STATUS_LABELS: Record = { active: "运行中", maintenance: "维护中", disabled: "停用", retired: "已退役", }; export const MAINTENANCE_TICKET_STATUS_LABELS: Record = { open: "待处理", assigned: "已派单", resolved: "已解决", closed: "已关闭", cancelled: "已取消", }; export const MAINTENANCE_TICKET_PRIORITY_LABELS: Record = { low: "低", normal: "普通", high: "高", urgent: "紧急", }; export type DeviceAsset = { id: string; organizationId: string; name: string; code: string; category: string; location: string; status: DeviceAssetStatus; lastInspectedAt?: string; notes: string; createdAt: string; updatedAt: string; }; export type MaintenanceTicket = { id: string; organizationId: string; deviceId?: string; deviceName: string; title: string; description: string; priority: MaintenanceTicketPriority; status: MaintenanceTicketStatus; assigneeLabel: string; resolutionNotes: string; resolvedAt?: string; createdAt: string; updatedAt: string; }; export type DeviceOperationsData = { metrics: { activeDevices: number; maintenanceDevices: number; openTickets: number; urgentTickets: number; }; devices: DeviceAsset[]; tickets: MaintenanceTicket[]; }; export type DeviceAssetInput = { name: string; code: string; category: string; location: string; status: DeviceAssetStatus; lastInspectedAt?: string; notes: string; }; export type MaintenanceTicketInput = { deviceId?: string; title: string; description: string; priority: MaintenanceTicketPriority; status: MaintenanceTicketStatus; assigneeLabel: string; resolutionNotes: string; }; type ValidationSuccess = { success: true; data: T; }; type ValidationFailure = { success: false; reason: string; }; export type ValidationResult = ValidationSuccess | ValidationFailure; function isRecord(value: unknown): value is Record { return typeof value === "object" && value !== null && !Array.isArray(value); } function readString(source: Record, key: string): string { const value = source[key]; return typeof value === "string" ? value.trim() : ""; } function readOptionalString(source: Record, key: string): string | undefined { const value = readString(source, key); return value || undefined; } function readEnum(value: unknown, values: readonly T[]): T | null { return typeof value === "string" ? values.find((item) => item === value) ?? null : null; } function validateIsoDate(value: string | undefined, label: string): ValidationResult { if (!value) { return { success: true, data: undefined }; } return Number.isNaN(new Date(value).getTime()) ? { success: false, reason: `${label}无效` } : { success: true, data: value }; } export function validateDeviceAssetInput(value: unknown): ValidationResult { if (!isRecord(value)) { return { success: false, reason: "请求数据格式无效" }; } const name = readString(value, "name"); const code = readString(value, "code"); if (!name || !code) { return { success: false, reason: "设备名称和编号不能为空" }; } const status = readEnum(value.status, DEVICE_ASSET_STATUS_VALUES); if (!status) { return { success: false, reason: "设备状态无效" }; } const lastInspectedAt = validateIsoDate(readOptionalString(value, "lastInspectedAt"), "最近巡检时间"); if (!lastInspectedAt.success) { return lastInspectedAt; } return { success: true, data: { name, code, category: readString(value, "category"), location: readString(value, "location"), status, lastInspectedAt: lastInspectedAt.data, notes: readString(value, "notes"), }, }; } export function validateMaintenanceTicketInput(value: unknown): ValidationResult { if (!isRecord(value)) { return { success: false, reason: "请求数据格式无效" }; } const title = readString(value, "title"); if (!title) { return { success: false, reason: "工单标题不能为空" }; } const priority = readEnum(value.priority, MAINTENANCE_TICKET_PRIORITY_VALUES); if (!priority) { return { success: false, reason: "工单优先级无效" }; } const status = readEnum(value.status, MAINTENANCE_TICKET_STATUS_VALUES); if (!status) { return { success: false, reason: "工单状态无效" }; } return { success: true, data: { deviceId: readOptionalString(value, "deviceId"), title, description: readString(value, "description"), priority, status, assigneeLabel: readString(value, "assigneeLabel"), resolutionNotes: readString(value, "resolutionNotes"), }, }; }