141 lines
5.3 KiB
JavaScript
141 lines
5.3 KiB
JavaScript
import { tool } from "@langchain/core/tools";
|
||
import z from "zod";
|
||
import mongoose from "mongoose";
|
||
import { DBModel } from "../../../../models/index.js";
|
||
import { genPinyin, genPinyinFL } from "../../../../models/schema/health_profile.js";
|
||
|
||
const PROFILE_KEYS = ["name", "mobile", "sex", "birth", "idnumber"];
|
||
const LOCATION_KEYS = ["country", "province", "city", "district", "address"];
|
||
const HEALTH_KEYS = ["height", "weight", "bloodType", "remark"];
|
||
|
||
const profileSchema = z
|
||
.object({
|
||
name: z.string().optional().describe("患者姓名"),
|
||
mobile: z.string().optional().describe("患者电话"),
|
||
sex: z.enum(["male", "female"]).optional().describe("性别"),
|
||
birth: z.string().optional().describe("出生年月(YYYY-MM-DD)"),
|
||
idnumber: z.string().optional().describe("证件号(身份证/护照等)"),
|
||
})
|
||
.optional()
|
||
.describe("患者基本信息");
|
||
|
||
const locationSchema = z
|
||
.object({
|
||
country: z.string().optional().describe("国家(国外用户填国家,国内默认中国)"),
|
||
province: z.string().optional().describe("省"),
|
||
city: z.string().optional().describe("市"),
|
||
district: z.string().optional().describe("区/县"),
|
||
address: z.string().optional().describe("详细地址"),
|
||
})
|
||
.optional()
|
||
.describe("所在地信息");
|
||
|
||
const healthSchema = z
|
||
.object({
|
||
height: z.number().optional().describe("身高(cm)"),
|
||
weight: z.number().optional().describe("体重(kg)"),
|
||
bloodType: z.string().optional().describe("血型"),
|
||
remark: z.string().optional().describe("备注"),
|
||
})
|
||
.optional()
|
||
.describe("健康信息");
|
||
|
||
const healthProfileSetTool = tool(
|
||
async ({ action, profileId, userId, profile, location, health }) => {
|
||
try {
|
||
if (action === "create") {
|
||
if (!profile || (!profile.name && !profile.mobile)) {
|
||
return { success: false, error: "创建健康档案至少需要提供患者姓名或电话" };
|
||
}
|
||
|
||
const docData = {
|
||
profile: { ...profile },
|
||
location: { ...location },
|
||
health: { ...health },
|
||
meta: { createtime: new Date(), updatetime: new Date() },
|
||
};
|
||
if (userId) {
|
||
if (!mongoose.Types.ObjectId.isValid(userId)) {
|
||
return { success: false, error: `Invalid user ID: ${userId}` };
|
||
}
|
||
docData.userId = new mongoose.Types.ObjectId(userId);
|
||
}
|
||
|
||
const doc = await DBModel.HealthProfile.create(docData);
|
||
return { success: true, data: doc };
|
||
}
|
||
|
||
if (action === "update") {
|
||
if (!profileId) {
|
||
return { success: false, error: "更新健康档案必须提供 profileId(可先用 health_profile_query 查询定位)" };
|
||
}
|
||
if (!mongoose.Types.ObjectId.isValid(profileId)) {
|
||
return { success: false, error: `Invalid profile ID: ${profileId}` };
|
||
}
|
||
|
||
const update = {};
|
||
if (userId) {
|
||
if (!mongoose.Types.ObjectId.isValid(userId)) {
|
||
return { success: false, error: `Invalid user ID: ${userId}` };
|
||
}
|
||
update.userId = new mongoose.Types.ObjectId(userId);
|
||
}
|
||
if (profile) {
|
||
for (const key of PROFILE_KEYS) {
|
||
if (profile[key] !== undefined) update[`profile.${key}`] = profile[key];
|
||
}
|
||
// 更新姓名时同步拼音字段(findByIdAndUpdate 不触发 pre("save"))
|
||
if (profile.name !== undefined) {
|
||
update["profile.pinyin"] = genPinyin(profile.name);
|
||
update["profile.pinyinFL"] = genPinyinFL(profile.name);
|
||
}
|
||
}
|
||
if (location) {
|
||
for (const key of LOCATION_KEYS) {
|
||
if (location[key] !== undefined) update[`location.${key}`] = location[key];
|
||
}
|
||
}
|
||
if (health) {
|
||
for (const key of HEALTH_KEYS) {
|
||
if (health[key] !== undefined) update[`health.${key}`] = health[key];
|
||
}
|
||
}
|
||
|
||
if (Object.keys(update).length === 0) {
|
||
return { success: false, error: "未提供任何要更新的字段" };
|
||
}
|
||
update["meta.updatetime"] = new Date();
|
||
|
||
const updated = await DBModel.HealthProfile.findByIdAndUpdate(
|
||
profileId,
|
||
{ $set: update },
|
||
{ new: true }
|
||
);
|
||
if (!updated) {
|
||
return { success: false, error: `未找到 ID 为 ${profileId} 的健康档案` };
|
||
}
|
||
return { success: true, data: updated };
|
||
}
|
||
|
||
return { success: false, error: "未知的 action,可选值:create / update" };
|
||
} catch (error) {
|
||
return { success: false, error: error.message };
|
||
}
|
||
},
|
||
{
|
||
name: "health_profile_set",
|
||
description:
|
||
"创建或更新患者健康档案。create 新建档案(至少提供患者姓名或电话);update 按档案 ID 局部更新,仅修改提供的字段。更新前建议先用 health_profile_query 查询现有内容。",
|
||
schema: z.object({
|
||
action: z.enum(["create", "update"]).describe("操作类型:create 新建 / update 更新"),
|
||
profileId: z.string().optional().describe("健康档案 ID(_id),update 时必填"),
|
||
userId: z.string().optional().describe("所属用户ID(可选,用于关联小程序用户)"),
|
||
profile: profileSchema,
|
||
location: locationSchema,
|
||
health: healthSchema,
|
||
}),
|
||
}
|
||
);
|
||
|
||
export { healthProfileSetTool };
|