This commit is contained in:
lik
2026-09-09 17:36:45 +08:00
parent d6efb180dd
commit 223e0ed2ee
25 changed files with 933 additions and 59 deletions
@@ -0,0 +1,85 @@
import { tool } from "@langchain/core/tools";
import z from "zod";
import mongoose from "mongoose";
import { DBModel } from "../../../../models/index.js";
const healthProfileQueryTool = tool(
async ({ profileId, userId, name, mobile, page = 1, pageSize = 20 }) => {
try {
// 按档案 _id 精确查询单条
if (profileId) {
if (!mongoose.Types.ObjectId.isValid(profileId)) {
return { success: false, error: `Invalid profile ID: ${profileId}` };
}
const doc = await DBModel.HealthProfile.findById(profileId).lean();
if (!doc) {
return { success: false, error: `未找到 ID 为 ${profileId} 的健康档案` };
}
return { success: true, data: [doc], total: 1 };
}
const filter = {};
if (userId) {
if (!mongoose.Types.ObjectId.isValid(userId)) {
return { success: false, error: `Invalid user ID: ${userId}` };
}
filter.userId = new mongoose.Types.ObjectId(userId);
}
if (name) {
// 转义正则特殊字符,避免查询报错或 ReDoS;姓名支持中文、全拼、拼音首字母匹配
const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
const re = { $regex: escaped, $options: "i" };
filter.$or = [{ "profile.name": re }, { "profile.pinyin": re }, { "profile.pinyinFL": re }];
}
if (mobile) {
filter["profile.mobile"] = mobile;
}
const skip = (page - 1) * pageSize;
const [list, total] = await Promise.all([
DBModel.HealthProfile.find(filter)
.sort({ "meta.createtime": -1 })
.skip(skip)
.limit(pageSize)
.lean(),
DBModel.HealthProfile.countDocuments(filter),
]);
return {
success: true,
data: list,
total,
page,
pageSize,
};
} catch (error) {
return { success: false, error: error.message };
}
},
{
name: "health_profile_query",
description:
"查询患者健康档案。支持按档案 ID 精确查询,或按用户 ID、患者姓名(模糊)、患者电话筛选,返回分页结果。",
schema: z.object({
profileId: z
.string()
.optional()
.describe("健康档案 ID(_id),提供时精确查询单条,忽略其他筛选条件"),
userId: z.string().optional().describe("所属用户ID(精确匹配)"),
name: z.string().optional().describe("患者姓名(支持中文模糊、全拼、拼音首字母匹配,如 张三/zhangsan/zs"),
mobile: z.string().optional().describe("患者电话(精确匹配)"),
page: z.number().int().min(1).optional().describe("页码,从 1 开始"),
pageSize: z
.number()
.int()
.min(1)
.max(50)
.optional()
.describe("每页数量(1-50),默认 20"),
}),
}
);
export { healthProfileQueryTool };