2026-07-27 11:28:33 +08:00

534 lines
18 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.

/**
* 线上购药药品库 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 }
}
}