534 lines
18 KiB
JavaScript
Raw Normal View History

2026-07-27 11:28:33 +08:00
/**
* 线上购药药品库 online-drug-info
* 与互联网医院药品库drug-info字段功能保持一致但使用独立的集合
*/
const dayjs = require("dayjs");
const { ObjectId } = require("mongodb");
const { getDrugList } = require("../drug-info/verify");
const validator = require("../../utils/validator");
exports.main = async (item, db) => {
switch (item.type) {
// 供患者/医生侧检索使用的简单查询(已在线使用,保留)
case "getOnlineDrugList":
return await getOnlineDrugList(item, db);
case "getOnlineSimilarDrugInfo":
return await getOnlineSimilarDrugInfo(item, db);
// 供后台管理使用的完整管理接口
case "getOnlineDrugInfo":
return await getOnlineDrugInfo(item, db);
case "addOnlineDrugInfo":
return await addOnlineDrugInfo(item, db);
case "editOnlineDrugInfo":
return await editOnlineDrugInfo(item, db);
case "setOnlineDrugOnSale":
return await setOnlineDrugOnSale(item, db);
case "importOnlineDrugInfo":
return await importOnlineDrugInfo(item, db);
case "checkOnlineDrugInfoStock":
return await checkOnlineDrugInfoStock(item, db);
case "getOnlineDrugRepeatTags":
return await getOnlineDrugRepeatTags(item, db);
default:
return { success: false, message: "未找到接口" };
}
};
// 患者/医生端使用:关键字+在售过滤
async function getOnlineDrugList(ctx, db) {
try {
const page =
Number.isInteger(ctx.page) && ctx.page > 0 ? ctx.page : 1;
const pageSize =
Number.isInteger(ctx.pageSize) && ctx.pageSize > 0
? ctx.pageSize
: 10;
const keyword =
typeof ctx.keyword === "string" ? ctx.keyword.trim() : "";
const query = {};
const onSale = typeof ctx.onSale === "boolean" ? ctx.onSale : true;
query.onSale = onSale;
let fuzzyQuery = null;
if (keyword) {
fuzzyQuery = {
$or: [
{ name: new RegExp(keyword.trim(), "i") },
{ generic_name: new RegExp(keyword.trim(), "i") },
{ barcode: keyword.trim() },
{ pinyin_code: new RegExp(keyword.trim(), "i") },
{ product_id_str: keyword.trim() },
],
};
}
if (Array.isArray(ctx.ids)) {
const ids = ctx.ids
.map((i) =>
typeof i === "string" && i.trim()
? new ObjectId(i.trim())
: null
)
.filter((i) => !!i);
if (ids.length) {
query._id = { $in: ids };
}
}
const applyQuery = fuzzyQuery ? { $and: [query, fuzzyQuery] } : query;
const [total, list] = await Promise.all([
db.collection("online-drug-info").countDocuments(applyQuery),
db
.collection("online-drug-info")
.find(applyQuery)
.skip((page - 1) * pageSize)
.limit(pageSize)
.toArray(),
]);
return {
success: true,
message: "查询成功",
data: list,
total,
pages: Math.ceil(total / pageSize),
};
} catch (e) {
return { success: false, message: e.message };
}
}
// 后台管理:分页查询(字段与 getHlwDrugInfo 一致)
async function getOnlineDrugInfo(ctx, db) {
try {
const page =
Number.isInteger(ctx.page) && ctx.page > 0 ? ctx.page : 1;
const pageSize =
Number.isInteger(ctx.pageSize) && ctx.pageSize > 0
? ctx.pageSize
: 10;
const query = {};
if (typeof ctx.name === "string" && ctx.name.trim()) {
query.name = new RegExp(ctx.name.trim(), "i");
}
if (typeof ctx.onSale === "boolean") {
query.onSale = ctx.onSale;
}
if (typeof ctx.productId === "string" && ctx.productId.trim()) {
query.product_id_str = ctx.productId.trim();
}
if (typeof ctx.barcode === "string" && ctx.barcode.trim()) {
query.barcode = ctx.barcode.trim();
}
if (
typeof ctx.insuranceCode === "string" &&
ctx.insuranceCode.trim()
) {
query.insurance_code = ctx.insuranceCode.trim();
}
if (typeof ctx.hisDrugCode === "string" && ctx.hisDrugCode.trim()) {
query.his_drug_code = ctx.hisDrugCode.trim();
}
if (typeof ctx.applyPeople === "string" && ctx.applyPeople.trim()) {
query.apply_people = ctx.applyPeople.trim();
}
const res = await db
.collection("online-drug-info")
.find(query)
.sort({ onSale: -1, createTime: -1 })
.skip((page - 1) * pageSize)
.limit(pageSize)
.toArray();
const total = await db
.collection("online-drug-info")
.countDocuments(query);
return {
success: true,
message: "查询成功",
data: res,
total,
pages: Math.ceil(total / pageSize),
};
} catch (e) {
return { success: false, message: e.message };
}
}
// 新增线上药品
async function addOnlineDrugInfo(ctx, db) {
const { params = {} } = ctx;
if (Object.prototype.toString.call(params) !== "[object Object]") {
return { success: false, message: "参数错误" };
}
try {
const peopleInfo = {
creator: typeof ctx.operator === "string" ? ctx.operator : "",
creatorId:
typeof ctx.operatorId === "string" ? ctx.operatorId : "",
createTime: Date.now(),
};
const { onSale, ...data } = params;
let newDrug = {};
if (Object.keys(data).length) {
if (!data.his_drug_code || !String(data.his_drug_code).trim()) {
return { success: false, message: "ERP编码不能为空" };
}
if (data.his_drug_code) {
const count = await db.collection("online-drug-info").countDocuments({ his_drug_code: data.his_drug_code });
if (count > 0) {
return { success: false, message: "ERP编码已存在" };
}
}
const [item] = getDrugList([data], true, peopleInfo);
const { msgs, ...drug } = item;
if (msgs.length) {
return { success: false, message: msgs.join(",") };
}
newDrug = { ...drug };
}
if (typeof onSale === "boolean") {
newDrug.onSale = onSale;
}
newDrug.createTime = Date.now();
const res = await db
.collection("online-drug-info")
.insertOne(newDrug);
return {
success: true,
message: "新增药品成功",
id: res.insertedId,
};
} catch (e) {
return {
success: false,
message: e.message || "新增药品失败",
};
}
}
// 编辑线上药品
async function editOnlineDrugInfo(ctx, db) {
const { id, params = {} } = ctx;
if (
Object.prototype.toString.call(params) !== "[object Object]" ||
typeof id !== "string"
) {
return { success: false, message: "参数错误" };
}
try {
const { onSale, ...data } = params;
let updateData = {};
if (Object.keys(data).length) {
if ("his_drug_code" in data && !String(data.his_drug_code).trim()) {
return { success: false, message: "ERP编码不能为空" };
}
if (data.his_drug_code) {
const count = await db.collection("online-drug-info").countDocuments({ his_drug_code: data.his_drug_code, _id: { $ne: new ObjectId(id) } });
if (count > 0) {
return { success: false, message: "ERP编码已存在" };
}
}
const peopleInfo = {
updater: typeof ctx.operator === "string" ? ctx.operator : "",
updaterId:
typeof ctx.operatorId === "string" ? ctx.operatorId : "",
updateTime: Date.now(),
};
const [item] = getDrugList([data], false, peopleInfo);
const { msgs, ...drug } = item;
if (msgs.length) {
return { success: false, message: msgs.join(",") };
}
updateData = { ...drug };
}
if (typeof onSale === "boolean") {
updateData.onSale = onSale;
}
if (Object.keys(updateData).length) {
updateData.updateTime = Date.now();
const res = await db
.collection("online-drug-info")
.updateOne(
{ _id: new ObjectId(id) },
{ $set: updateData }
);
if (res.matchedCount === 0) {
return { success: false, message: "未找到对应药品" };
}
}
return { success: true, message: "更新成功" };
} catch (e) {
console.log("editOnlineDrugInfo error", e);
return { success: false, message: e.message };
}
}
// 批量上/下架
async function setOnlineDrugOnSale(ctx, db) {
const { ids, onSale, updaterId, updater } = ctx;
const _ids = Array.isArray(ids)
? ids
.filter((i) => typeof i === "string" && i.trim())
.map((i) => new ObjectId(i.trim()))
: [ids];
if (
_ids.length === 0 ||
typeof onSale !== "boolean" ||
typeof updaterId !== "string" ||
typeof updater !== "string" ||
!updaterId.trim() ||
!updater.trim()
) {
return { success: false, message: "参数错误" };
}
try {
const res = await db
.collection("online-drug-info")
.updateMany(
{ _id: { $in: _ids } },
{
$set: {
onSale,
updateTime: Date.now(),
updaterId,
updater,
},
}
);
return { success: true, message: "更新成功", res };
} catch (e) {
console.log("setOnlineDrugOnSale error", e);
return { success: false, message: e.message };
}
}
// 批量导入用于程序接口调用CSV 上传走单独 upload-online-drug-csv
async function importOnlineDrugInfo(ctx, db) {
const drugs = Array.isArray(ctx.drugs)
? ctx.drugs.filter((i) => typeof i === "object" && i !== null)
: [];
const onSale =
typeof ctx.onSale === "boolean" ? ctx.onSale : true;
if (drugs.length === 0) {
return { success: false, message: "参数错误" };
}
try {
const peopleInfo = {
creator: typeof ctx.operator === "string" ? ctx.operator : "",
creatorId:
typeof ctx.operatorId === "string" ? ctx.operatorId : "",
createTime: Date.now(),
};
const datalist = getDrugList(drugs, true, peopleInfo);
datalist.forEach((i) => {
if (!i.his_drug_code || !String(i.his_drug_code).trim()) {
i.msgs.push("ERP编码不能为空");
}
});
const createTime = dayjs().valueOf();
const list = datalist
.filter((i) => i.msgs.length === 0)
.map((i) => {
const { msgs, ...drug } = i;
drug.createTime = createTime;
drug.onSale = onSale;
return drug;
});
if (!list.length) {
return { success: false, message: "导入失败" };
}
const res = await db
.collection("online-drug-info")
.insertMany(list);
if (res.insertedCount > 0) {
return {
success: true,
message: `成功导入${res.insertedCount}条数据`,
};
}
return { success: false, message: "导入失败" };
} catch (e) {
console.log("importOnlineDrugInfo error", e);
return { success: false, message: e.message };
}
}
async function getOnlineSimilarDrugInfo(ctx, db) {
try {
const accountId = typeof ctx.accountId === "string" && ctx.accountId.trim() !== "" ? ctx.accountId.trim() : "";
const patientId = typeof ctx.patientId === "string" && ctx.patientId.trim() !== "" ? ctx.patientId.trim() : "";
const patientName = typeof ctx.patientName === "string" && ctx.patientName.trim() !== "" ? ctx.patientName.trim() : "";
const phone = typeof ctx.phone === "string" && ctx.phone.trim() !== "" ? ctx.phone.trim() : "";
const drugs = Array.isArray(ctx.drugs) ? ctx.drugs.filter(i => i && typeof i.insurance_code == 'string' && i.insurance_code.trim() !== "") : [];
const insurance_codes = drugs.map(i => i.insurance_code);
const query = { insurance_code: { $in: insurance_codes }, onSale: true };
const medicines = await db.collection("online-drug-info").find(query).toArray();
const lackMedicines = drugs.filter(i => !medicines.some(med => med.insurance_code === i.insurance_code));
let similarDrugs = [];
if (lackMedicines.length > 0) {
const lackMedicineRegApi = require("../lack-medicine-reg");
// 补全厂商数据:从药品库(包括已下架)中查询完整信息
const lackInsuranceCodes = lackMedicines.map(i => i.insurance_code);
const allDrugsInDb = await db.collection("online-drug-info").find({
insurance_code: { $in: lackInsuranceCodes }
}).toArray();
const lackDrugsWithManufacturer = lackMedicines.map(drug => {
// 尝试从数据库中找到匹配的药品信息
const dbDrug = allDrugsInDb.find(d => d.insurance_code === drug.insurance_code);
return {
...drug,
drugName: drug.drugName || (dbDrug ? dbDrug.name : ''),
spec: drug.spec || (dbDrug ? dbDrug.specification : ''),
manufacturer: drug.manufacturer || (dbDrug ? dbDrug.manufacturer : ''),
insurance_code: drug.insurance_code
};
});
const res = await lackMedicineRegApi({
type: "batchAddLackMedicineReg",
drugs: lackDrugsWithManufacturer,
accountId,
patientId,
patientName,
phone,
inventory: 'online',
regType: 'outOfStock',
corpId: ctx.corpId,
}, db)
const similarQuery = lackMedicines.map(i => ({
$and: [
{ onSale: true, insurance_code: new RegExp(i.insurance_code.slice(0, -5), "i") },
{ insurance_code: { $ne: i.insuranceCode } }
]
}))
similarDrugs = await db.collection("online-drug-info").find({ $or: similarQuery }).toArray();
}
return { success: true, message: "查询成功", drugs: medicines, similarDrugs }
} catch (e) {
return { success: false, message: e.message }
}
}
async function checkOnlineDrugInfoStock(ctx, db) {
try {
const accountId = typeof ctx.accountId === 'string' ? ctx.accountId.trim() : '';
const patientId = typeof ctx.patientId === 'string' ? ctx.patientId.trim() : '';
const patientName = typeof ctx.patientName === 'string' ? ctx.patientName.trim() : '';
const phone = typeof ctx.phone === 'string' ? ctx.phone.trim() : '';
const drugs = Array.isArray(ctx.drugs) ? ctx.drugs.map(i => ({
insurance_code: i && typeof i.insurance_code === 'string' ? i.insurance_code.trim() : '',
num: i && Number(i.num) > 0 && Number.isInteger(Number(i.num)) ? Number(i.num) : 0,
})) : [];
const areaCode = typeof ctx.areaCode === 'string' ? ctx.areaCode.trim() : '';
if (accountId.length === 0) {
return { success: false, message: "账号id不能为空" }
}
if (accountId.length > 50) {
return { success: false, message: "账号id不能超过50个字" }
}
if (areaCode.length === 0) {
return { success: false, message: "地区编码不能为空" }
}
if (patientId.length > 50) {
return { success: false, message: "患者id不能超过50个字" }
}
if (patientName.length === 0) {
return { success: false, message: "患者姓名不能为空" }
}
if (patientName.length > 30) {
return { success: false, message: "患者姓名不能超过30个字" }
}
// 手机号验证:如果提供了手机号则必须格式正确
if (phone.length > 0 && !validator.isMobile(phone)) {
return { success: false, message: "患者手机号格式不正确" }
}
if (drugs.length === 0 || drugs.length > 5) {
return { success: false, message: "药品数量不能为空且不能超过5个" }
}
if (drugs.some(i => !(i.insurance_code && i.num))) {
return { success: false, message: "药品信息不完整" }
}
const list = await db.collection("online-drug-info").find({ insurance_code: { $in: drugs.map(i => i.insurance_code) } }, { projection: { name: 1, specification: 1, manufacturer: 1, insurance_code: 1 } }).toArray();
const arr = drugs.map(i => {
const drug = list.find(m => m.insurance_code === i.insurance_code);
return { drug, num: i.num, insurance_code: i.insurance_code }
})
const unvalid = arr.find(i => !i.drug);
if (unvalid) {
return { success: false, message: `药品${unvalid.insurance_code}不存在` }
}
const zytHis = require("../zyt-his")
const res = await zytHis({ type: 'getHisDrugInfo', areaCode, insuranceCodes: drugs.map(i => i.insurance_code) });
if (!res || !res.success) {
return { success: false, message: res && res.message ? res.message : '查询his库存信息失败' }
}
const hisDrugs = Array.isArray(res.data) ? res.data : [];
const lackMedicines = [];
const result = [];
arr.forEach(i => {
const hisDrug = hisDrugs.find(m => m.gjbm === i.insurance_code);
const stock = hisDrug && Number(hisDrug.stock_amount) > 0 ? Number(hisDrug.stock_amount) : 0;
const price = hisDrug && Number(hisDrug.pack_retprice) > 0 ? Number(hisDrug.pack_retprice) : undefined;
if (stock < i.num) {
lackMedicines.push({
drugName: i.drug.name,
spec: i.drug.specification,
manufacturer: i.drug.manufacturer,
insuranceCode: i.drug.insurance_code
})
}
result.push({ insuranceCode: i.insurance_code, stock, price })
})
if (lackMedicines.length > 0) {
const lackMedicineRegApi = require("../lack-medicine-reg");
lackMedicineRegApi({
type: "batchAddLackMedicineReg",
drugs: lackMedicines,
accountId,
patientId,
patientName,
phone,
inventory: 'online',
regType: 'lowStock',
corpId: ctx.corpId,
}, db)
}
return { success: true, message: '查询成功', data: result }
} catch (e) {
return { success: false, message: e.message }
}
}
async function getOnlineDrugRepeatTags(ctx, db) {
try {
const pipeline = [
{
$match: {
repeatTag: {
$type: "array",
$ne: []
}
}
},
{ $unwind: "$repeatTag" },
{ $match: { repeatTag: { $type: "number", $gt: 0 } } },
{ $group: { _id: "$repeatTag" } },
{ $sort: { _id: 1 } },
{
$group: {
_id: null,
uniqueTags: { $push: "$_id" }
}
},
{ $project: { _id: 0, uniqueTags: 1 } }
];
const result = await db.collection("online-drug-info").aggregate(pipeline).toArray();
const uniqueTags = result.length > 0 ? result[0].uniqueTags : [];
return { success: true, message: '查询成功', data: uniqueTags }
} catch (e) {
return { success: false, message: e.message }
}
}