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 || "查询失败", }; } }