feat: add health data management workspace
This commit is contained in:
677
modules/core/server/default-workspace-data.ts
Normal file
677
modules/core/server/default-workspace-data.ts
Normal file
@@ -0,0 +1,677 @@
|
||||
import { eq } from "drizzle-orm";
|
||||
|
||||
import { getDatabase } from "@/modules/core/server/db";
|
||||
import {
|
||||
admissions,
|
||||
beds,
|
||||
buildings,
|
||||
campuses,
|
||||
chronicConditions,
|
||||
elders,
|
||||
floors,
|
||||
healthAnomalyReviews,
|
||||
healthProfiles,
|
||||
rooms,
|
||||
systemIncidents,
|
||||
vitalRecords,
|
||||
} from "@/modules/core/server/schema";
|
||||
|
||||
type SeedRoom = {
|
||||
buildingName: string;
|
||||
campusName: string;
|
||||
code: string;
|
||||
floorLevel: number;
|
||||
floorName: string;
|
||||
name: string;
|
||||
capacity: number;
|
||||
};
|
||||
|
||||
type SeedBed = {
|
||||
code: string;
|
||||
notes: string;
|
||||
roomCode: string;
|
||||
status: "available" | "occupied" | "maintenance" | "disabled";
|
||||
};
|
||||
|
||||
type SeedElder = {
|
||||
age: number;
|
||||
careLevel: "self-care" | "semi-assisted" | "assisted" | "intensive";
|
||||
gender: "male" | "female" | "other";
|
||||
medicalNotes: string;
|
||||
name: string;
|
||||
phone: string;
|
||||
primaryContact: string;
|
||||
status: "active" | "pending" | "discharged";
|
||||
};
|
||||
|
||||
type SeedAdmission = {
|
||||
bedCode: string;
|
||||
elderName: string;
|
||||
notes: string;
|
||||
status: "active" | "transferred" | "discharged";
|
||||
};
|
||||
|
||||
type SeedHealthProfile = {
|
||||
allergyNotes: string;
|
||||
careRestrictions: string;
|
||||
elderName: string;
|
||||
emergencyNotes: string;
|
||||
medicalHistory: string;
|
||||
medicationNotes: string;
|
||||
};
|
||||
|
||||
type SeedVitalRecord = {
|
||||
bloodGlucoseTenths?: number;
|
||||
diastolicBp?: number;
|
||||
elderName: string;
|
||||
heartRate?: number;
|
||||
notes: string;
|
||||
recordedHoursAgo: number;
|
||||
source: "manual" | "device" | "import";
|
||||
spo2?: number;
|
||||
systolicBp?: number;
|
||||
temperatureTenths?: number;
|
||||
weightTenths?: number;
|
||||
};
|
||||
|
||||
type SeedChronicCondition = {
|
||||
elderName: string;
|
||||
followUpNotes: string;
|
||||
name: string;
|
||||
status: "active" | "controlled" | "resolved";
|
||||
treatmentNotes: string;
|
||||
};
|
||||
|
||||
type SeedHealthReview = {
|
||||
description: string;
|
||||
elderName: string;
|
||||
resolutionNotes: string;
|
||||
severity: "info" | "warning" | "critical";
|
||||
status: "pending" | "reviewed" | "resolved";
|
||||
title: string;
|
||||
vitalIndex: number;
|
||||
};
|
||||
|
||||
const DEFAULT_ROOMS: SeedRoom[] = [
|
||||
{ campusName: "主院区", buildingName: "护理楼", floorName: "一层", floorLevel: 1, code: "A101", name: "阳光房", capacity: 2 },
|
||||
{ campusName: "主院区", buildingName: "护理楼", floorName: "一层", floorLevel: 1, code: "A102", name: "康养房", capacity: 2 },
|
||||
{ campusName: "主院区", buildingName: "护理楼", floorName: "二层", floorLevel: 2, code: "A201", name: "记忆照护房", capacity: 2 },
|
||||
{ campusName: "主院区", buildingName: "护理楼", floorName: "二层", floorLevel: 2, code: "A202", name: "重点照护房", capacity: 2 },
|
||||
{ campusName: "主院区", buildingName: "康复楼", floorName: "一层", floorLevel: 1, code: "R101", name: "康复观察房", capacity: 2 },
|
||||
{ campusName: "主院区", buildingName: "康复楼", floorName: "一层", floorLevel: 1, code: "R102", name: "短住评估房", capacity: 2 },
|
||||
{ campusName: "北苑院区", buildingName: "颐养楼", floorName: "一层", floorLevel: 1, code: "B101", name: "自理房", capacity: 2 },
|
||||
{ campusName: "北苑院区", buildingName: "颐养楼", floorName: "二层", floorLevel: 2, code: "B201", name: "亲情套房", capacity: 2 },
|
||||
];
|
||||
|
||||
const DEFAULT_BEDS: SeedBed[] = [
|
||||
{ code: "A101-1", roomCode: "A101", status: "occupied", notes: "靠窗,已完成入住评估" },
|
||||
{ code: "A101-2", roomCode: "A101", status: "available", notes: "可安排半护理老人入住" },
|
||||
{ code: "A102-1", roomCode: "A102", status: "occupied", notes: "夜间巡护重点关注" },
|
||||
{ code: "A102-2", roomCode: "A102", status: "maintenance", notes: "床头呼叫器检修中" },
|
||||
{ code: "A201-1", roomCode: "A201", status: "occupied", notes: "记忆照护专区" },
|
||||
{ code: "A201-2", roomCode: "A201", status: "available", notes: "靠近护理站" },
|
||||
{ code: "A202-1", roomCode: "A202", status: "occupied", notes: "压疮风险重点巡查" },
|
||||
{ code: "A202-2", roomCode: "A202", status: "disabled", notes: "待更换护栏" },
|
||||
{ code: "R101-1", roomCode: "R101", status: "occupied", notes: "康复训练后休息床位" },
|
||||
{ code: "R101-2", roomCode: "R101", status: "available", notes: "临时观察床位" },
|
||||
{ code: "R102-1", roomCode: "R102", status: "available", notes: "短住评估床位" },
|
||||
{ code: "R102-2", roomCode: "R102", status: "available", notes: "短住评估床位" },
|
||||
{ code: "B101-1", roomCode: "B101", status: "occupied", notes: "自理老人长期床位" },
|
||||
{ code: "B101-2", roomCode: "B101", status: "available", notes: "低照护需求床位" },
|
||||
{ code: "B201-1", roomCode: "B201", status: "occupied", notes: "亲属探访便利" },
|
||||
{ code: "B201-2", roomCode: "B201", status: "available", notes: "亲情套房备用床" },
|
||||
];
|
||||
|
||||
const DEFAULT_ELDERS: SeedElder[] = [
|
||||
{
|
||||
name: "王桂兰",
|
||||
gender: "female",
|
||||
age: 82,
|
||||
careLevel: "intensive",
|
||||
status: "active",
|
||||
primaryContact: "张敏",
|
||||
phone: "13800000001",
|
||||
medicalNotes: "高血压,需晨晚血压记录。",
|
||||
},
|
||||
{
|
||||
name: "李建国",
|
||||
gender: "male",
|
||||
age: 76,
|
||||
careLevel: "semi-assisted",
|
||||
status: "active",
|
||||
primaryContact: "李明",
|
||||
phone: "13800000002",
|
||||
medicalNotes: "餐后散步陪同,关注睡眠情况。",
|
||||
},
|
||||
{
|
||||
name: "周玉珍",
|
||||
gender: "female",
|
||||
age: 88,
|
||||
careLevel: "assisted",
|
||||
status: "active",
|
||||
primaryContact: "周强",
|
||||
phone: "13800000003",
|
||||
medicalNotes: "糖尿病饮食,餐前血糖提醒。",
|
||||
},
|
||||
{
|
||||
name: "赵国华",
|
||||
gender: "male",
|
||||
age: 91,
|
||||
careLevel: "intensive",
|
||||
status: "active",
|
||||
primaryContact: "赵琳",
|
||||
phone: "13800000004",
|
||||
medicalNotes: "夜间翻身,两小时巡房。",
|
||||
},
|
||||
{
|
||||
name: "孙秀梅",
|
||||
gender: "female",
|
||||
age: 73,
|
||||
careLevel: "semi-assisted",
|
||||
status: "active",
|
||||
primaryContact: "孙磊",
|
||||
phone: "13800000005",
|
||||
medicalNotes: "膝关节康复训练,每日下午一次。",
|
||||
},
|
||||
{
|
||||
name: "刘长青",
|
||||
gender: "male",
|
||||
age: 68,
|
||||
careLevel: "self-care",
|
||||
status: "active",
|
||||
primaryContact: "刘洋",
|
||||
phone: "13800000006",
|
||||
medicalNotes: "自理,需定期复查用药。",
|
||||
},
|
||||
{
|
||||
name: "陈秀英",
|
||||
gender: "female",
|
||||
age: 69,
|
||||
careLevel: "self-care",
|
||||
status: "pending",
|
||||
primaryContact: "陈佳",
|
||||
phone: "13800000007",
|
||||
medicalNotes: "待完成入住评估。",
|
||||
},
|
||||
{
|
||||
name: "何德明",
|
||||
gender: "male",
|
||||
age: 84,
|
||||
careLevel: "assisted",
|
||||
status: "pending",
|
||||
primaryContact: "何静",
|
||||
phone: "13800000008",
|
||||
medicalNotes: "家属已提交体检资料,等待床位确认。",
|
||||
},
|
||||
{
|
||||
name: "吴佩兰",
|
||||
gender: "female",
|
||||
age: 79,
|
||||
careLevel: "semi-assisted",
|
||||
status: "discharged",
|
||||
primaryContact: "吴昊",
|
||||
phone: "13800000009",
|
||||
medicalNotes: "已退住,保留历史档案。",
|
||||
},
|
||||
{
|
||||
name: "郑文远",
|
||||
gender: "male",
|
||||
age: 72,
|
||||
careLevel: "self-care",
|
||||
status: "discharged",
|
||||
primaryContact: "郑洁",
|
||||
phone: "13800000010",
|
||||
medicalNotes: "短住康复结束后退住。",
|
||||
},
|
||||
];
|
||||
|
||||
const DEFAULT_ADMISSIONS: SeedAdmission[] = [
|
||||
{ elderName: "王桂兰", bedCode: "A101-1", status: "active", notes: "默认工作区入住记录" },
|
||||
{ elderName: "李建国", bedCode: "A102-1", status: "active", notes: "默认工作区入住记录" },
|
||||
{ elderName: "周玉珍", bedCode: "A201-1", status: "active", notes: "记忆照护专区入住" },
|
||||
{ elderName: "赵国华", bedCode: "A202-1", status: "active", notes: "重点照护入住" },
|
||||
{ elderName: "孙秀梅", bedCode: "R101-1", status: "active", notes: "康复观察入住" },
|
||||
{ elderName: "刘长青", bedCode: "B101-1", status: "active", notes: "自理区入住" },
|
||||
{ elderName: "吴佩兰", bedCode: "B201-1", status: "discharged", notes: "历史退住记录" },
|
||||
];
|
||||
|
||||
const DEFAULT_HEALTH_PROFILES: SeedHealthProfile[] = [
|
||||
{
|
||||
elderName: "王桂兰",
|
||||
allergyNotes: "青霉素过敏",
|
||||
medicalHistory: "高血压十余年,偶发胸闷。",
|
||||
medicationNotes: "晨服降压药,晚间复核血压。",
|
||||
careRestrictions: "低盐饮食,避免剧烈活动。",
|
||||
emergencyNotes: "胸闷或血压持续升高时立即联系医生。",
|
||||
},
|
||||
{
|
||||
elderName: "周玉珍",
|
||||
allergyNotes: "无明确药物过敏史",
|
||||
medicalHistory: "2 型糖尿病,轻度认知障碍。",
|
||||
medicationNotes: "餐前血糖监测,按医嘱用药。",
|
||||
careRestrictions: "控糖饮食,夜间加强巡护。",
|
||||
emergencyNotes: "低血糖症状时立即补糖并记录。",
|
||||
},
|
||||
{
|
||||
elderName: "赵国华",
|
||||
allergyNotes: "海鲜过敏",
|
||||
medicalHistory: "脑梗后遗症,长期卧床风险。",
|
||||
medicationNotes: "抗凝药按时服用。",
|
||||
careRestrictions: "两小时翻身,防跌倒,防压疮。",
|
||||
emergencyNotes: "意识异常或血氧下降时立即启动应急流程。",
|
||||
},
|
||||
{
|
||||
elderName: "刘长青",
|
||||
allergyNotes: "",
|
||||
medicalHistory: "冠心病随访。",
|
||||
medicationNotes: "自主管理用药,护理员每日提醒。",
|
||||
careRestrictions: "避免爬楼和长时间站立。",
|
||||
emergencyNotes: "胸痛需立即报告。",
|
||||
},
|
||||
];
|
||||
|
||||
const DEFAULT_VITAL_RECORDS: SeedVitalRecord[] = [
|
||||
{
|
||||
elderName: "王桂兰",
|
||||
recordedHoursAgo: 2,
|
||||
source: "manual",
|
||||
systolicBp: 158,
|
||||
diastolicBp: 96,
|
||||
heartRate: 88,
|
||||
temperatureTenths: 367,
|
||||
spo2: 96,
|
||||
bloodGlucoseTenths: 62,
|
||||
weightTenths: 612,
|
||||
notes: "血压偏高,已安排复测。",
|
||||
},
|
||||
{
|
||||
elderName: "李建国",
|
||||
recordedHoursAgo: 5,
|
||||
source: "device",
|
||||
systolicBp: 128,
|
||||
diastolicBp: 78,
|
||||
heartRate: 76,
|
||||
temperatureTenths: 365,
|
||||
spo2: 98,
|
||||
notes: "体征平稳。",
|
||||
},
|
||||
{
|
||||
elderName: "周玉珍",
|
||||
recordedHoursAgo: 7,
|
||||
source: "manual",
|
||||
systolicBp: 134,
|
||||
diastolicBp: 82,
|
||||
heartRate: 80,
|
||||
temperatureTenths: 366,
|
||||
spo2: 97,
|
||||
bloodGlucoseTenths: 118,
|
||||
notes: "餐后血糖偏高,已记录饮食。",
|
||||
},
|
||||
{
|
||||
elderName: "赵国华",
|
||||
recordedHoursAgo: 12,
|
||||
source: "manual",
|
||||
systolicBp: 146,
|
||||
diastolicBp: 88,
|
||||
heartRate: 92,
|
||||
temperatureTenths: 381,
|
||||
spo2: 91,
|
||||
notes: "体温和血氧异常,需复核。",
|
||||
},
|
||||
];
|
||||
|
||||
const DEFAULT_CHRONIC_CONDITIONS: SeedChronicCondition[] = [
|
||||
{
|
||||
elderName: "王桂兰",
|
||||
name: "高血压",
|
||||
status: "active",
|
||||
treatmentNotes: "规律服药,晨晚血压监测。",
|
||||
followUpNotes: "每周汇总血压趋势。",
|
||||
},
|
||||
{
|
||||
elderName: "周玉珍",
|
||||
name: "糖尿病",
|
||||
status: "active",
|
||||
treatmentNotes: "控糖饮食,餐前餐后血糖记录。",
|
||||
followUpNotes: "异常血糖进入复核队列。",
|
||||
},
|
||||
{
|
||||
elderName: "刘长青",
|
||||
name: "冠心病",
|
||||
status: "controlled",
|
||||
treatmentNotes: "按医嘱服药,避免劳累。",
|
||||
followUpNotes: "月度复诊提醒。",
|
||||
},
|
||||
];
|
||||
|
||||
const DEFAULT_HEALTH_REVIEWS: SeedHealthReview[] = [
|
||||
{
|
||||
elderName: "王桂兰",
|
||||
vitalIndex: 0,
|
||||
severity: "warning",
|
||||
status: "pending",
|
||||
title: "血压异常",
|
||||
description: "收缩压和舒张压偏高,需要复测并确认用药。",
|
||||
resolutionNotes: "",
|
||||
},
|
||||
{
|
||||
elderName: "赵国华",
|
||||
vitalIndex: 3,
|
||||
severity: "critical",
|
||||
status: "pending",
|
||||
title: "血氧和体温异常",
|
||||
description: "血氧低于阈值且体温偏高,需要立即复核。",
|
||||
resolutionNotes: "",
|
||||
},
|
||||
{
|
||||
elderName: "周玉珍",
|
||||
vitalIndex: 2,
|
||||
severity: "info",
|
||||
status: "reviewed",
|
||||
title: "餐后血糖偏高",
|
||||
description: "餐后血糖高于日常水平。",
|
||||
resolutionNotes: "已调整晚餐主食并安排次日复测。",
|
||||
},
|
||||
];
|
||||
|
||||
function hasRows(rows: unknown[]): boolean {
|
||||
return rows.length > 0;
|
||||
}
|
||||
|
||||
export async function seedDefaultWorkspaceData(organizationId: string): Promise<void> {
|
||||
const database = getDatabase();
|
||||
const [existingRooms, existingBeds, existingElders, existingAdmissions] = await Promise.all([
|
||||
database.select({ id: rooms.id }).from(rooms).where(eq(rooms.organizationId, organizationId)).limit(1),
|
||||
database.select({ id: beds.id }).from(beds).where(eq(beds.organizationId, organizationId)).limit(1),
|
||||
database.select({ id: elders.id }).from(elders).where(eq(elders.organizationId, organizationId)).limit(1),
|
||||
database.select({ id: admissions.id }).from(admissions).where(eq(admissions.organizationId, organizationId)).limit(1),
|
||||
]);
|
||||
|
||||
if ([existingRooms, existingBeds, existingElders, existingAdmissions].some(hasRows)) {
|
||||
return;
|
||||
}
|
||||
|
||||
await database.transaction(async (transaction) => {
|
||||
const uniqueCampusNames = Array.from(new Set(DEFAULT_ROOMS.map((room) => room.campusName)));
|
||||
const campusRows = await transaction
|
||||
.insert(campuses)
|
||||
.values(
|
||||
uniqueCampusNames.map((name) => ({
|
||||
organizationId,
|
||||
name,
|
||||
address: `${name}养老服务院区`,
|
||||
})),
|
||||
)
|
||||
.returning();
|
||||
if (campusRows.length !== uniqueCampusNames.length) {
|
||||
throw new Error("默认院区初始化失败");
|
||||
}
|
||||
const campusIdByName = new Map(campusRows.map((campus) => [campus.name, campus.id]));
|
||||
|
||||
const uniqueBuildings = Array.from(
|
||||
new Map(DEFAULT_ROOMS.map((room) => [`${room.campusName}/${room.buildingName}`, room])).values(),
|
||||
);
|
||||
const buildingRows = await transaction
|
||||
.insert(buildings)
|
||||
.values(
|
||||
uniqueBuildings.map((building) => {
|
||||
const campusId = campusIdByName.get(building.campusName);
|
||||
if (!campusId) {
|
||||
throw new Error("默认楼栋初始化失败");
|
||||
}
|
||||
|
||||
return {
|
||||
organizationId,
|
||||
campusId,
|
||||
name: building.buildingName,
|
||||
};
|
||||
}),
|
||||
)
|
||||
.returning();
|
||||
if (buildingRows.length !== uniqueBuildings.length) {
|
||||
throw new Error("默认楼栋初始化失败");
|
||||
}
|
||||
const buildingIdByKey = new Map(
|
||||
buildingRows.map((building, index) => {
|
||||
const source = uniqueBuildings[index];
|
||||
if (!source) {
|
||||
throw new Error("默认楼栋初始化失败");
|
||||
}
|
||||
|
||||
return [`${source.campusName}/${source.buildingName}`, building.id];
|
||||
}),
|
||||
);
|
||||
|
||||
const uniqueFloors = Array.from(
|
||||
new Map(
|
||||
DEFAULT_ROOMS.map((room) => [
|
||||
`${room.campusName}/${room.buildingName}/${room.floorLevel}`,
|
||||
room,
|
||||
]),
|
||||
).values(),
|
||||
);
|
||||
const floorRows = await transaction
|
||||
.insert(floors)
|
||||
.values(
|
||||
uniqueFloors.map((floor) => {
|
||||
const buildingId = buildingIdByKey.get(`${floor.campusName}/${floor.buildingName}`);
|
||||
if (!buildingId) {
|
||||
throw new Error("默认楼层初始化失败");
|
||||
}
|
||||
|
||||
return {
|
||||
organizationId,
|
||||
buildingId,
|
||||
name: floor.floorName,
|
||||
level: floor.floorLevel,
|
||||
};
|
||||
}),
|
||||
)
|
||||
.returning();
|
||||
if (floorRows.length !== uniqueFloors.length) {
|
||||
throw new Error("默认楼层初始化失败");
|
||||
}
|
||||
const floorIdByKey = new Map(
|
||||
floorRows.map((floor, index) => {
|
||||
const source = uniqueFloors[index];
|
||||
if (!source) {
|
||||
throw new Error("默认楼层初始化失败");
|
||||
}
|
||||
|
||||
return [`${source.campusName}/${source.buildingName}/${source.floorLevel}`, floor.id];
|
||||
}),
|
||||
);
|
||||
|
||||
const roomRows = await transaction
|
||||
.insert(rooms)
|
||||
.values(
|
||||
DEFAULT_ROOMS.map((room) => {
|
||||
const floorId = floorIdByKey.get(`${room.campusName}/${room.buildingName}/${room.floorLevel}`);
|
||||
if (!floorId) {
|
||||
throw new Error("默认房间初始化失败");
|
||||
}
|
||||
|
||||
return {
|
||||
organizationId,
|
||||
floorId,
|
||||
name: room.name,
|
||||
code: room.code,
|
||||
capacity: room.capacity,
|
||||
};
|
||||
}),
|
||||
)
|
||||
.returning();
|
||||
if (roomRows.length !== DEFAULT_ROOMS.length) {
|
||||
throw new Error("默认房间初始化失败");
|
||||
}
|
||||
|
||||
const roomIdByCode = new Map(roomRows.map((room) => [room.code, room.id]));
|
||||
const bedRows = await transaction
|
||||
.insert(beds)
|
||||
.values(
|
||||
DEFAULT_BEDS.map((bed) => {
|
||||
const roomId = roomIdByCode.get(bed.roomCode);
|
||||
if (!roomId) {
|
||||
throw new Error("默认床位初始化失败");
|
||||
}
|
||||
|
||||
return {
|
||||
organizationId,
|
||||
roomId,
|
||||
code: bed.code,
|
||||
status: bed.status,
|
||||
notes: bed.notes,
|
||||
};
|
||||
}),
|
||||
)
|
||||
.returning();
|
||||
if (bedRows.length !== DEFAULT_BEDS.length) {
|
||||
throw new Error("默认床位初始化失败");
|
||||
}
|
||||
|
||||
const elderRows = await transaction
|
||||
.insert(elders)
|
||||
.values(DEFAULT_ELDERS.map((elder) => ({ ...elder, organizationId })))
|
||||
.returning();
|
||||
if (elderRows.length !== DEFAULT_ELDERS.length) {
|
||||
throw new Error("默认老人档案初始化失败");
|
||||
}
|
||||
|
||||
const elderIdByName = new Map(elderRows.map((elder) => [elder.name, elder.id]));
|
||||
const bedIdByCode = new Map(bedRows.map((bed) => [bed.code, bed.id]));
|
||||
await transaction.insert(admissions).values(
|
||||
DEFAULT_ADMISSIONS.map((admission) => {
|
||||
const elderId = elderIdByName.get(admission.elderName);
|
||||
const bedId = bedIdByCode.get(admission.bedCode);
|
||||
if (!elderId || !bedId) {
|
||||
throw new Error("默认入住初始化失败");
|
||||
}
|
||||
|
||||
return {
|
||||
organizationId,
|
||||
elderId,
|
||||
bedId,
|
||||
status: admission.status,
|
||||
dischargedAt: admission.status === "discharged" ? new Date() : undefined,
|
||||
notes: admission.notes,
|
||||
};
|
||||
}),
|
||||
);
|
||||
|
||||
await transaction.insert(healthProfiles).values(
|
||||
DEFAULT_HEALTH_PROFILES.map((profile) => {
|
||||
const elderId = elderIdByName.get(profile.elderName);
|
||||
if (!elderId) {
|
||||
throw new Error("默认健康档案初始化失败");
|
||||
}
|
||||
|
||||
return {
|
||||
organizationId,
|
||||
elderId,
|
||||
allergyNotes: profile.allergyNotes,
|
||||
medicalHistory: profile.medicalHistory,
|
||||
medicationNotes: profile.medicationNotes,
|
||||
careRestrictions: profile.careRestrictions,
|
||||
emergencyNotes: profile.emergencyNotes,
|
||||
};
|
||||
}),
|
||||
);
|
||||
|
||||
const now = new Date();
|
||||
const vitalRows = await transaction
|
||||
.insert(vitalRecords)
|
||||
.values(
|
||||
DEFAULT_VITAL_RECORDS.map((vital) => {
|
||||
const elderId = elderIdByName.get(vital.elderName);
|
||||
if (!elderId) {
|
||||
throw new Error("默认生命体征初始化失败");
|
||||
}
|
||||
|
||||
return {
|
||||
organizationId,
|
||||
elderId,
|
||||
recordedAt: new Date(now.getTime() - vital.recordedHoursAgo * 60 * 60 * 1000),
|
||||
source: vital.source,
|
||||
systolicBp: vital.systolicBp,
|
||||
diastolicBp: vital.diastolicBp,
|
||||
heartRate: vital.heartRate,
|
||||
temperatureTenths: vital.temperatureTenths,
|
||||
spo2: vital.spo2,
|
||||
bloodGlucoseTenths: vital.bloodGlucoseTenths,
|
||||
weightTenths: vital.weightTenths,
|
||||
notes: vital.notes,
|
||||
};
|
||||
}),
|
||||
)
|
||||
.returning();
|
||||
if (vitalRows.length !== DEFAULT_VITAL_RECORDS.length) {
|
||||
throw new Error("默认生命体征初始化失败");
|
||||
}
|
||||
|
||||
await transaction.insert(chronicConditions).values(
|
||||
DEFAULT_CHRONIC_CONDITIONS.map((condition) => {
|
||||
const elderId = elderIdByName.get(condition.elderName);
|
||||
if (!elderId) {
|
||||
throw new Error("默认慢病记录初始化失败");
|
||||
}
|
||||
|
||||
return {
|
||||
organizationId,
|
||||
elderId,
|
||||
name: condition.name,
|
||||
status: condition.status,
|
||||
treatmentNotes: condition.treatmentNotes,
|
||||
followUpNotes: condition.followUpNotes,
|
||||
};
|
||||
}),
|
||||
);
|
||||
|
||||
await transaction.insert(healthAnomalyReviews).values(
|
||||
DEFAULT_HEALTH_REVIEWS.map((review) => {
|
||||
const elderId = elderIdByName.get(review.elderName);
|
||||
const vital = vitalRows[review.vitalIndex];
|
||||
if (!elderId || !vital) {
|
||||
throw new Error("默认健康异常复核初始化失败");
|
||||
}
|
||||
|
||||
return {
|
||||
organizationId,
|
||||
elderId,
|
||||
vitalRecordId: vital.id,
|
||||
severity: review.severity,
|
||||
status: review.status,
|
||||
title: review.title,
|
||||
description: review.description,
|
||||
resolutionNotes: review.resolutionNotes,
|
||||
};
|
||||
}),
|
||||
);
|
||||
|
||||
await transaction.insert(systemIncidents).values([
|
||||
{
|
||||
organizationId,
|
||||
severity: "warning",
|
||||
status: "open",
|
||||
title: "床头呼叫器待检修",
|
||||
description: "A102-2 床位呼叫器处于检修状态,完成后可恢复使用。",
|
||||
source: "默认工作区初始化",
|
||||
},
|
||||
{
|
||||
organizationId,
|
||||
severity: "info",
|
||||
status: "acknowledged",
|
||||
title: "本周护理评估待完成",
|
||||
description: "陈秀英、何德明等待入住评估,可在老人档案和床位工作区继续处理。",
|
||||
source: "默认工作区初始化",
|
||||
},
|
||||
{
|
||||
organizationId,
|
||||
severity: "critical",
|
||||
status: "resolved",
|
||||
title: "夜间巡房异常已处理",
|
||||
description: "重点照护房夜间巡房提醒已恢复,保留事件用于状态页验证。",
|
||||
source: "默认工作区初始化",
|
||||
},
|
||||
]);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user