export const GENDER_VALUES = ["male", "female", "other"] as const; export type Gender = (typeof GENDER_VALUES)[number]; export const CARE_LEVEL_VALUES = ["self-care", "semi-assisted", "assisted", "intensive"] as const; export type CareLevel = (typeof CARE_LEVEL_VALUES)[number]; export const ELDER_STATUS_VALUES = ["active", "pending", "discharged"] as const; export type ElderStatus = (typeof ELDER_STATUS_VALUES)[number]; export const GENDER_LABELS: Record = { male: "男", female: "女", other: "其他", }; export const CARE_LEVEL_LABELS: Record = { "self-care": "自理", "semi-assisted": "半失能", assisted: "失能", intensive: "重点照护", }; export const ELDER_STATUS_LABELS: Record = { active: "在院", pending: "待入住", discharged: "已退住", }; export type Elder = { id: string; organizationId?: string; name: string; gender: Gender; age: number; careLevel: CareLevel; room: string; bed: string; bedId?: string; status: ElderStatus; primaryContact: string; phone: string; medicalNotes: string; createdAt: string; updatedAt: string; }; export type ElderInput = Omit; 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 readRequiredString( source: Record, key: keyof ElderInput, label: string, ): ValidationResult { const value = source[key]; if (typeof value !== "string" || value.trim().length === 0) { return { success: false, reason: `${label}不能为空` }; } return { success: true, data: value.trim() }; } function readOptionalString(source: Record, key: string): string | undefined { const value = source[key]; if (typeof value !== "string") { return undefined; } const trimmed = value.trim(); return trimmed.length > 0 ? trimmed : undefined; } function readEnum( source: Record, key: keyof ElderInput, values: readonly T[], label: string, ): ValidationResult { const value = source[key]; if (typeof value !== "string") { return { success: false, reason: `${label}无效` }; } const matched = values.find((item) => item === value); if (!matched) { return { success: false, reason: `${label}无效` }; } return { success: true, data: matched }; } function readAge(source: Record): ValidationResult { const value = source.age; const numeric = typeof value === "number" ? value : Number(value); if (!Number.isInteger(numeric) || numeric < 0 || numeric > 130) { return { success: false, reason: "年龄需为0到130之间的整数" }; } return { success: true, data: numeric }; } export function validateElderInput(value: unknown): ValidationResult { if (!isRecord(value)) { return { success: false, reason: "请求数据格式无效" }; } const name = readRequiredString(value, "name", "姓名"); if (!name.success) { return name; } const gender = readEnum(value, "gender", GENDER_VALUES, "性别"); if (!gender.success) { return gender; } const age = readAge(value); if (!age.success) { return age; } const careLevel = readEnum(value, "careLevel", CARE_LEVEL_VALUES, "护理等级"); if (!careLevel.success) { return careLevel; } const room = readOptionalString(value, "room") ?? ""; const bed = readOptionalString(value, "bed") ?? ""; const bedId = readOptionalString(value, "bedId"); const status = readEnum(value, "status", ELDER_STATUS_VALUES, "状态"); if (!status.success) { return status; } const primaryContact = readRequiredString(value, "primaryContact", "联系人"); if (!primaryContact.success) { return primaryContact; } const phone = readRequiredString(value, "phone", "联系电话"); if (!phone.success) { return phone; } const medicalNotesValue = value.medicalNotes; const medicalNotes = typeof medicalNotesValue === "string" ? medicalNotesValue.trim() : ""; return { success: true, data: { name: name.data, gender: gender.data, age: age.data, careLevel: careLevel.data, room, bed, bedId, status: status.data, primaryContact: primaryContact.data, phone: phone.data, medicalNotes, }, }; }