818 lines
24 KiB
JavaScript
Raw Normal View History

2026-07-27 11:28:33 +08:00
const { ObjectId } = require("mongodb");
const dayjs = require("dayjs");
const peopleUtils = require("./hlw-people-utils");
const { recordDoctorRecommendation, getDoctorRecommendationCount } = require("./doctor-count-in-one-minute");
let db = "";
module.exports = async (item, mongodb) => {
db = mongodb;
switch (item.type) {
case "getHlwDoctorList":
return await getHlwDoctorList(item);
case "getHlwPersonList":
return await getHlwPersonList(item);
case "deleteHlwDoctor":
return await deleteHlwDoctor(item);
case "updateHlwDoctor":
return await updateHlwDoctor(item);
case "addHlwDoctor":
return await addHlwDoctor(item);
case "getRandomOnlineDoctor":
return await getRandomOnlineDoctor(item);
case "isDoctorOnline":
return await isDoctorOnline(item);
case "getAllDoctorNos":
return await getAllDoctorNos(item);
case "getRecommendDoctor":
return await getRecommendDoctor(item);
case "getOptimalRecommendDoctor":
return await getOptimalRecommendDoctor(item);
case "setPharmacistOnlineStatus":
return await setPharmacistOnlineStatus(item);
case "getPharmacistOnlineStatus":
return await getPharmacistOnlineStatus(item);
case "addHlwPerson":
return await addHlwPerson(item);
case "updateHlwPerson":
return await updateHlwPerson(item);
case "deleteHlwPerson":
return await deleteHlwPerson(item);
case "updateHlwPersonDeptInfo":
return await updateHlwPersonDeptInfo(item);
case "autoSetPeopleOffline":
return await autoSetPeopleOffline(item);
case "getDoctorByNo":
return await getDoctorByNo(item);
}
};
async function getPendingOrdersCount(doctorList) {
const doctorNos = doctorList.map((doctor) => doctor.doctorNo);
const before3Minutes = Date.now() - 3 * 60 * 1000;
const case1 = {
orderStatus: 'pending',
payStatus: 'pending',
createTime: { $gte: before3Minutes },
} // 3分钟内的待支付订单
const case2 = {
orderStatus: { $in: ['pending', 'processing'] },
payStatus: 'success',
createTime: { $gte: dayjs().startOf('day').valueOf() },
expireTime: { $gt: Date.now() }
} // 当天并且未过期的处理中订单
const countMap = new Map();
try {
const doctorOrderCount = await db.collection("consult-order").aggregate([
{ $match: { doctorCode: { $in: doctorNos }, $or: [case1, case2] } },
{ $group: { _id: "$doctorCode", count: { $sum: 1 } } }, // 按照医生编号分组,并计算订单数量
]).toArray()
doctorOrderCount.forEach((item) => {
countMap.set(item._id, item.count);
});
} catch (e) {
console.log("获取医生待支付订单数量失败", e);
}
return doctorList.map(i => ({
...i,
pendingOrdersCount: countMap.get(i.doctorNo) || 0
})).sort((a, b) => {
return a.pendingOrdersCount - b.pendingOrdersCount;
});
}
/**
* 获取推荐医生
* @param storeCode 店铺代码
* @param presType 处方类型 西药处方 west 中医处方 chinese
* @returns
*/
async function getRecommendDoctor({ storeCode, presType }) {
try {
// 获取所有在线且服务可用的医生
const doctorListResult = await getOptimalRecommendDoctor({ recordInOneMinute: true, doctorType: presType },);
if (!doctorListResult.success) {
return {
success: false,
message: "没有可用的在线医生",
};
}
const doctor = doctorListResult.data;
// 如果提供了店铺代码,获取收费信息
if (doctor && storeCode) {
const storeApi = require("../drug-store");
const { success, list } = await storeApi(
{ type: "getDrugStoreList", storeId: storeCode, pageSize: 1 },
db
);
const store = list && list[0] ? list[0] : null;
const chargeItem =
store && store.chargeItems ? store.chargeItems[0] : null;
if (success && chargeItem && chargeItem.code) {
doctor.feeCode = chargeItem.code;
doctor.chargeFee = chargeItem.fee;
} else {
return {
success: false,
message: `店铺(${storeCode})信息不存在或者店铺收费编码未配置`,
};
}
}
return {
success: true,
message: "获取推荐医生成功",
data: doctor,
};
} catch (error) {
return {
success: false,
message: error.message || "获取推荐医生失败",
};
}
}
/**
*
* @param {boolean} recordInOneMinute 是否记录一分钟内获取推荐医生的数量
* @returns
*/
async function getOptimalRecommendDoctor({ recordInOneMinute = false, doctorType }) {
try {
const type = ['west', 'chinese'].includes(doctorType) ? doctorType : 'west';
// 查询条件:在线且服务状态启用的医生
const query = {
onlineStatus: "online",
serviceStatus: "enabled",
job: "doctor",
testDoctor: { $ne: true }, // 过滤测试医生
};
if (type === 'chinese') {
query.openChinesePres = true;
} else if (type === 'west') {
query.openWestPres = true;
}
const projection = {
doctorNo: 1,
doctorName: 1,
title: 1,
deptName: 1,
serviceFee: 1,
deptCode: 1,
onlineStatus: 1,
serviceStatus: 1,
}
const doctorList = await db.collection("hlw-doctor").find(query, { projection }).toArray();
if (doctorList.length === 0) {
return {
success: false,
message: "没有在线医生可推荐",
};
}
const doctors = await getPendingOrdersCount(doctorList);
doctors.forEach((doc) => {
const count = getDoctorRecommendationCount(doc.doctorNo);// 获取一分钟内被推荐次数
doc.weight = doc.pendingOrdersCount + count; // 计算权重 权重 = 待支付订单数 + 门店端)一分钟(内被推荐次数
})
doctors.sort((a, b) => a.weight - b.weight);
// 获取最小权重
const minWight = doctors[0].weight;
// console.log(doctors.map(i => ({ doctorNo: i.doctorNo, doctorName: i.doctorName, weight: i.weight })))
// 筛选出所有具有最小权重的医生
const optimalDoctors = doctors.filter(
(doc) => doc.weight === minWight
);
if (optimalDoctors.length === 1) {
if (recordInOneMinute) {
recordDoctorRecommendation(optimalDoctors[0].doctorNo); // 记录医生被推荐
}
return {
success: true,
message: "获取最优推荐医生成功",
data: optimalDoctors[0],
};
}
const condition = {
doctorCode: { $in: optimalDoctors.map(i => i.doctorNo) },
orderStatus: { $in: ['pending', 'processing'] },
payStatus: 'success',
settlement: { $exists: true },
createTime: { $gte: dayjs().subtract(0.5, 'hour').valueOf() },
} //
const [first] = await db.collection("consult-order").aggregate([
{ $match: condition },
// 提前进行分组,减少后续处理的数据量
{
$group: {
_id: "$doctorCode",
earliestOrder: {
$min: {
createTime: "$createTime",
chargeDate: {
$dateFromString: {
dateString: "$settlement.chage_date",
format: "%Y/%m/%d %H:%M:%S"
}
}
}
}
}
},
// 按照结算时间排序
{ $sort: { "earliestOrder.chargeDate": 1 } },
// 只返回需要的字段
{
$project: {
doctorCode: "$_id",
createTime: "$earliestOrder.createTime",
_id: 0
}
},
{ $limit: 1 } // 如果只需要第一条记录,提前限制结果
]).toArray();
const randomIndex = Math.floor(Math.random() * optimalDoctors.length);
const doctor = first ? optimalDoctors.find(i => i.doctorNo === first.doctorCode) : optimalDoctors[randomIndex];
if (doctor && doctor.doctorNo && recordInOneMinute) {
recordDoctorRecommendation(doctor.doctorNo);
}
return {
success: true,
message: "获取最优推荐医生成功",
data: doctor,
};
} catch (err) {
return {
success: false,
message: err.message || "获取最优推荐医生失败",
};
}
}
// 获取最优推荐医生(问诊量最少)
async function getOptimalRecommendDoctor1() {
try {
// 查询条件:在线且服务状态启用的医生
const query = {
onlineStatus: "online",
serviceStatus: "enabled",
job: "doctor",
testDoctor: { $ne: true }, // 过滤测试医生
};
// 使用聚合查询获取医生并计算问诊量
const doctors = await db
.collection("hlw-doctor")
.aggregate([
{ $match: query },
{
$lookup: {
from: "consult-order",
localField: "doctorNo",
foreignField: "doctorCode",
as: "orders",
},
},
{
$addFields: {
pendingOrdersCount: {
$size: {
$filter: {
input: "$orders",
as: "order",
cond: {
$or: [
{
$and: [
{
$in: [
"$$order.orderStatus",
["pending", "processing"],
],
},
{ $eq: ["$$order.payStatus", "success"] },
{ $gt: ["$$order.expireTime", Date.now()] },
{ $gt: ["$$order.createTime", dayjs().startOf('day').valueOf()] },
],
},
],
},
},
},
},
},
},
{
$sort: {
pendingOrdersCount: 1, // 按问诊量升序排序
},
},
{
$project: {
doctorNo: 1,
doctorName: 1,
title: 1,
deptName: 1,
serviceFee: 1,
deptCode: 1,
onlineStatus: 1,
serviceStatus: 1,
pendingOrdersCount: 1,
},
},
])
.toArray();
// 如果没有找到符合条件的医生
if (!doctors || doctors.length === 0) {
return {
success: false,
message: "没有在线医生可推荐",
};
}
// 获取最少问诊量的值
const minPendingOrders = doctors[0].pendingOrdersCount;
// 筛选出所有具有最少问诊量的医生
const optimalDoctors = doctors.filter(
(doc) => doc.pendingOrdersCount === minPendingOrders
);
// 如果有多个问诊量相同的医生,随机选择一个
const randomIndex = Math.floor(Math.random() * optimalDoctors.length);
const doctor = optimalDoctors[randomIndex];
return {
success: true,
message: "获取最优推荐医生成功",
data: doctor,
};
} catch (err) {
return {
success: false,
message: err.message || "获取最优推荐医生失败",
};
}
}
// 获取医生列表 hlw-doctor 分页 数据库
async function getHlwDoctorList(item) {
const {
doctorName,
page,
pageSize,
doctorCode,
onlineStatus,
serviceStatus,
corpId,
} = item;
let query = { job: 'doctor' };
if (doctorCode) query.doctorNo = doctorCode;
if (onlineStatus) query.onlineStatus = onlineStatus;
if (serviceStatus) query.serviceStatus = serviceStatus;
if (corpId) query.corpId = corpId;
if (typeof doctorName === "string") {
query.doctorName = new RegExp(doctorName.trim(), "i");
}
if (pageSize === 1) {
// 查询单个医生(默认为查询推荐医生 过滤测试医生)
query.testDoctor = { $ne: true };
}
if (item.doctorType === 'west') {
query.openWestPres = true;
} else if (item.doctorType === 'chinese') {
query.openChinesePres = true;
}
try {
const projection = {
doctorNo: 1,
doctorName: 1,
title: 1,
deptName: 1,
serviceFee: 1,
deptCode: 1,
onlineStatus: 1,
serviceStatus: 1,
enableVideoConsult: 1,
}
const pageNum = Number.isInteger(page) && page > 0 ? page : 1;
const pageSizeNum =
Number.isInteger(pageSize) && pageSize > 0 ? pageSize : 15;
const doctorList = await db.collection("hlw-doctor")
.find(query, { projection })
.skip((pageNum - 1) * pageSizeNum)
.limit(pageSizeNum)
.toArray();
console.log("doctorList", doctorList);
const res = await getPendingOrdersCount(doctorList);
const total = await db.collection("hlw-doctor").countDocuments(query);
return {
success: true,
message: "查询成功",
data: res,
total,
pages: Math.ceil(total / pageSize),
};
} catch (err) {
return {
success: false,
message: err.message || "查询失败",
};
}
}
// 删除医生信息
async function deleteHlwDoctor(item) {
const { _id } = item;
try {
// 调用mongo 数据库删除
const res = await db.collection("hlw-doctor").deleteOne({
_id: new ObjectId(_id),
job: "doctor",
});
return {
success: true,
message: "删除成功",
};
} catch (err) {
return {
success: false,
message: "删除失败",
};
}
}
// 更新医生信息
async function updateHlwDoctor(item) {
const { _id, params, doctorNo } = item;
try {
let query = { job: { $in: ['doctor', 'TCMDoctor'] } };
if (_id) query._id = new ObjectId(_id);
if (doctorNo) query.doctorNo = doctorNo;
// 调用mongo 数据库更新
// 如果包含 onlineStatus 字段,按需维护 offlineTime 字段
const setObj = {
...params,
updateTime: Date.now(),
};
if (Object.prototype.hasOwnProperty.call(params || {}, 'onlineStatus')) {
if (params.onlineStatus === 'offline') {
// 记录下线时间
setObj.offlineTime = Date.now();
} else if (params.onlineStatus === 'online') {
// 清除 offlineTime
setObj.offlineTime = null;
}
}
const res = await db.collection("hlw-doctor").updateOne(query, {
$set: setObj,
});
return {
success: true,
message: "更新成功",
res,
};
} catch (err) {
return {
success: false,
message: "更新失败",
};
}
}
//新增医生信息
async function addHlwDoctor(item) {
const { doctorName, doctorTitle, doctorDepartment } = item;
try {
// 调用mongo 数据库新增
const res = await db.collection("hlw-doctor").insertOne({
doctorName,
doctorTitle,
doctorDepartment,
createTime: Date.now(),
job: "doctor",
});
return {
success: true,
message: "新增成功",
data: res,
};
} catch (err) {
return {
success: false,
message: "新增失败",
};
}
}
// 正在咨询数
async function getRandomOnlineDoctor(params) {
try {
const query = {
onlineStatus: "online",
serviceStatus: "enabled",
job: "doctor",
};
if (query.doctorNo) {
query.doctorNo = query.doctorNo;
}
const res = await db
.collection("hlw-doctor")
.aggregate([
{ $match: query }, // 假设这是你的查询条件
{ $project: { idNo: 0 } },
{ $sample: { size: 1 } }, // 随机返回一个文档
])
.toArray();
return { success: true, data: res, message: "查询成功" };
} catch (e) {
return {
success: false,
message: e.message || "查询失败",
};
}
}
async function isDoctorOnline() {
try {
const count = await db.collection("hlw-doctor").countDocuments({
onlineStatus: "online",
serviceStatus: "enabled",
openWestPres: true,
job: "doctor",
});
return { success: true, data: count > 0, message: "查询成功" };
} catch (e) {
return {
success: false,
message: e.message || "查询失败",
};
}
}
async function getAllDoctorNos(ctx) {
try {
const jobs = Array.isArray(ctx.jobs) ? ctx.jobs : ['doctor'];
const query = ctx.showAll === true ? {} : { job: { $in: jobs } };
const res = await db
.collection("hlw-doctor")
.find(query, { projection: { doctorNo: 1, doctorName: 1, job: 1 } })
.toArray();
return { success: true, data: res, message: "查询成功" };
} catch (e) {
return {
success: false,
message: e.message || "查询失败",
};
}
}
async function getPharmacistOnlineStatus(ctx) {
if (typeof ctx.doctorNo !== 'string' || ctx.doctorNo.trim() === '') {
return { success: false, message: "药师编号不能为空" }
}
try {
const res = await db.collection("hlw-doctor").findOne(
{ doctorNo: ctx.doctorNo, job: 'pharmacist' },
{ projection: { onlineStatus: 1 } }
);
if (!res) {
return { success: false, message: "药师不存在或不是药师" }
}
return { success: true, message: "查询成功", data: res.onlineStatus }
} catch (e) {
return {
success: false,
message: e.message || "查询药师在线状态失败",
};
}
}
async function setPharmacistOnlineStatus(ctx) {
if (typeof ctx.doctorNo !== 'string' || ctx.doctorNo.trim() === '') {
return { success: false, message: "药师编号不能为空" }
}
if (!['online', 'offline'].includes(ctx.onlineStatus)) {
return { success: false, message: "无效的在线状态" }
}
try {
const res = await db.collection("hlw-doctor").updateOne(
{ doctorNo: ctx.doctorNo, job: 'pharmacist' },
{ $set: { onlineStatus: ctx.onlineStatus } }
);
if (res.matchedCount === 0) {
return { success: false, message: "药师不存在或不是药师" }
}
if (res.modifiedCount === 1) {
return { success: true, message: "在线状态修改成功", data: ctx.onlineStatus }
}
return { success: false, message: "在线状态修改失败" }
} catch (e) {
return {
success: false,
message: e.message || "设置药师在线状态失败",
};
}
}
async function getHlwPersonList(ctx) {
const corpId = typeof ctx.corpId === 'string' ? ctx.corpId.trim() : '';
if (!corpId) {
return { success: false, message: "机构ID不能为空" }
}
const page = Number.isInteger(ctx.page) && ctx.page > 0 ? ctx.page : 1;
const pageSize = Number.isInteger(ctx.pageSize) && ctx.pageSize > 0 ? ctx.pageSize : 10;
try {
const query = { corpId };
if (typeof ctx.keyword === 'string' && ctx.keyword.trim() !== '') {
query['$or'] = [
{ doctorName: new RegExp(ctx.keyword.trim(), 'i') },
{ doctorNo: new RegExp(ctx.keyword.trim(), 'i') },
]
}
if (typeof ctx.deptCode === 'string' && ctx.deptCode.trim() !== '') {
query.deptCode = ctx.deptCode.trim();
}
if (Array.isArray(ctx.deptCodes)) {
query.deptCode = { $in: ctx.deptCodes };
}
if (typeof ctx.doctorNo === 'string' && ctx.doctorNo.trim() !== '') {
query.doctorNo = ctx.doctorNo.trim();
}
const res = await db.collection("hlw-doctor").find(query, { projection: { idNo: 0 } }).sort({ createTime: -1 }).skip((page - 1) * pageSize).limit(pageSize).toArray();
const total = await db.collection("hlw-doctor").countDocuments(query);
return { success: true, message: "查询成功", data: res, total };
} catch (e) {
return {
success: false,
message: e.message || "查询人员列表失败",
};
}
}
async function addHlwPerson(ctx) {
try {
const { success, message, data } = peopleUtils.getPeopleData(ctx);
if (!success) {
return { success, message };
}
const corpId = typeof ctx.corpId === 'string' ? ctx.corpId.trim() : '';
if (!corpId) {
return { success: false, message: "机构ID不能为空" }
}
const total = await db.collection("hlw-doctor").countDocuments({ corpId, doctorNo: data.doctorNo });
if (total > 0) {
return { success: false, message: "院内工号已存在" }
}
const res = await db.collection("hlw-doctor").insertOne({
...data,
corpId,
serviceStatus: "enabled", // 默认启用
onlineStatus: "offline", // 默认离线
createTime: Date.now()
});
return {
success: true,
message: "新增人员成功",
id: res.insertedId,
};
} catch (e) {
return {
success: false,
message: e.message || "新增人员失败",
};
}
}
async function updateHlwPerson(ctx) {
const { success, data, message } = peopleUtils.getPeopleData(ctx, false);
if (!success) {
return { success, message };
}
try {
const { doctorCode, ...rest } = data; // 员工编号 不支持修改
const res = await db.collection("hlw-doctor").updateOne(
{ _id: new ObjectId(ctx._id) },
{ $set: { ...rest, updateTime: Date.now() } }
);
if (res.matchedCount === 0) {
return { success: false, message: "人员不存在" }
}
return {
success: true,
message: "更新人员成功",
data: res,
};
} catch (e) {
return {
success: false,
message: e.message || "更新人员失败",
};
}
}
async function updateHlwPersonDeptInfo(ctx) {
try {
const query = {
corpId: typeof ctx.corpId === 'string' ? ctx.corpId.trim() : '',
deptCode: Array.isArray(ctx.deptCodes) ? { $in: ctx.deptCodes } : '',
}
const data = {
deptCode: typeof ctx.newDeptCode == 'string' ? ctx.newDeptCode.trim() : '',
deptName: typeof ctx.newDeptName == 'string' ? ctx.newDeptName.trim() : '',
}
const res = await db.collection("hlw-doctor").updateMany(
query,
{ $set: { ...data, updateTime: Date.now() } }
);
return {
success: true,
message: "更新人员成功",
data: res,
};
} catch (e) {
return {
success: false,
message: e.message || "更新人员失败",
};
}
}
async function deleteHlwPerson(ctx) {
try {
const res = await db.collection("hlw-doctor").deleteOne({
_id: new ObjectId(ctx._id)
});
if (res.deletedCount === 0) {
return { success: false, message: "人员不存在" }
}
return {
success: true,
message: "删除人员成功",
};
} catch (e) {
return {
success: false,
message: e.message || "删除人员失败",
};
}
}
async function autoSetPeopleOffline() {
if (![22, 23, 24].includes(dayjs().hour())) {
return { success: false, message: '每天自动下线时间在22:00-24:00之间' }
}
try {
await db.collection("hlw-doctor").updateMany(
{ onlineStatus: 'online' },
{ $set: { onlineStatus: 'offline' } }
);
return { success: true, message: "设置人员离线成功" }
} catch (e) {
return {
success: false,
message: e.message || "设置人员离线失败",
}
}
}
/**
* 一对一通过 doctorNo 查询人员信息
* 仅允许 job doctor pharmacist
*/
async function getDoctorByNo(ctx) {
const doctorNo = typeof ctx.doctorNo === 'string' ? ctx.doctorNo.trim() : '';
const corpId = typeof ctx.corpId === 'string' ? ctx.corpId.trim() : '';
if (!doctorNo) {
return { success: false, message: "doctorNo 不能为空" };
}
const query = {
doctorNo,
job: { $in: ['doctor', 'pharmacist'] },
};
if (corpId) {
query.corpId = corpId;
}
try {
const projection = {
idNo: 0, // 默认不返回证件号等敏感信息,如需可调整
};
const res = await db.collection("hlw-doctor").findOne(query, { projection });
if (!res) {
return {
success: false,
message: "人员不存在,或不是医生/药师",
};
}
return {
success: true,
message: "查询成功",
data: res,
};
} catch (err) {
return {
success: false,
message: err.message || "查询失败",
};
}
}