Files
2026-09-09 17:36:45 +08:00

141 lines
5.3 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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 };