fix:接口调整
This commit is contained in:
parent
0165c2c064
commit
ec816dfdd6
@ -47,7 +47,7 @@ GET /im-chat/image/:msgId
|
|||||||
生产使用前建议补充问诊订单权限验证。
|
生产使用前建议补充问诊订单权限验证。
|
||||||
## 处方 PDF
|
## 处方 PDF
|
||||||
|
|
||||||
处方笺下载接口为 `GET /hlw/prescriptions/:id/pdf`;默认输出 A5,传 `paperSize=A4` 可输出 A4。
|
处方笺下载接口为 `GET /hlw/prescriptions/:id/pdf`;默认输出 A5,传 `paperSize=A4` 可输出 A4。获取 PDF Base64 内容可调用 `GET /hlw/prescriptions/:id/base64`,响应中的 `data` 字段为 Base64 字符串,也支持 `paperSize=A4`。
|
||||||
|
|
||||||
服务运行环境需要预装 Chromium/Chrome,并配置其可执行文件路径:
|
服务运行环境需要预装 Chromium/Chrome,并配置其可执行文件路径:
|
||||||
|
|
||||||
|
|||||||
@ -18,6 +18,7 @@ enum DiagnosticStatus {
|
|||||||
EXPIRED = 'EXPIRED', // 订单过期
|
EXPIRED = 'EXPIRED', // 订单过期
|
||||||
PASS_INVALID = 'PASS_INVALID', // 通过的处方作废
|
PASS_INVALID = 'PASS_INVALID', // 通过的处方作废
|
||||||
UNPASS_INVALID = 'UNPASS_INVALID', // 未通过的处方作废
|
UNPASS_INVALID = 'UNPASS_INVALID', // 未通过的处方作废
|
||||||
|
CANCELLED = 'CANCELLED', // 门店主动撤销
|
||||||
INVALID = 'INVALID', // 处方作废
|
INVALID = 'INVALID', // 处方作废
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,4 +123,5 @@ interface DiagnosticRecord {
|
|||||||
needReUpload?: boolean // 门店处方 是否需要重新上传(可能存在的场景 调用his接口上传成功了 但是his未上传医保, 需要药师手动去his的上传处理页面上传)
|
needReUpload?: boolean // 门店处方 是否需要重新上传(可能存在的场景 调用his接口上传成功了 但是his未上传医保, 需要药师手动去his的上传处理页面上传)
|
||||||
printCount?: number; // 门店自费处方打印次数
|
printCount?: number; // 门店自费处方打印次数
|
||||||
lastPrintTime?: number; // 门店自费处方最近一次打印时间
|
lastPrintTime?: number; // 门店自费处方最近一次打印时间
|
||||||
|
cancelTime?: number; // 门店主动撤销时间
|
||||||
}
|
}
|
||||||
|
|||||||
@ -90,8 +90,8 @@ function decryptDiagnosticRecordList(list) {
|
|||||||
return list.map((item) => decryptDiagnosticRecordFields(item));
|
return list.map((item) => decryptDiagnosticRecordFields(item));
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.formatUploadRxData = function (data) {
|
exports.formatUploadRxData = function (data, opt) {
|
||||||
return {
|
const result = {
|
||||||
// pdfUrl: getPrescriptionPdfUrl(data),
|
// pdfUrl: getPrescriptionPdfUrl(data),
|
||||||
pay_type: data.feeType === 'YB' ? '1' : '0',
|
pay_type: data.feeType === 'YB' ? '1' : '0',
|
||||||
patientid: data.patientId,
|
patientid: data.patientId,
|
||||||
@ -141,6 +141,10 @@ exports.formatUploadRxData = function (data) {
|
|||||||
icd_name: i.name,
|
icd_name: i.name,
|
||||||
})),
|
})),
|
||||||
};
|
};
|
||||||
|
if (opt && opt.pdf) {
|
||||||
|
result.pdf = opt.pdf
|
||||||
|
}
|
||||||
|
return result
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
let db = "";
|
let db = "";
|
||||||
const { ObjectId } = require("mongodb");
|
const { ObjectId } = require("mongodb");
|
||||||
|
const fs = require("fs/promises");
|
||||||
const { getDatabase } = require("../../mongodb");
|
const { getDatabase } = require("../../mongodb");
|
||||||
const dayjs = require("dayjs");
|
const dayjs = require("dayjs");
|
||||||
const { decryptOrderList } = require("../consult-order/format");
|
const { decryptOrderList } = require("../consult-order/format");
|
||||||
@ -20,6 +21,7 @@ const beijingCa = require("../beijing-ca");
|
|||||||
const BigNumber = require("bignumber.js");
|
const BigNumber = require("bignumber.js");
|
||||||
// const timeApi = require("../hlw-time-duration");
|
// const timeApi = require("../hlw-time-duration");
|
||||||
const types = require("./types");
|
const types = require("./types");
|
||||||
|
const { getOrCreatePrescriptionPdf } = require("../prescription-pdf");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 性能优化建议:
|
* 性能优化建议:
|
||||||
@ -75,6 +77,7 @@ const status = {
|
|||||||
passInvalid: "PASS_INVALID", //通过的处方作废 (目前就订单退费会导致处方作废)
|
passInvalid: "PASS_INVALID", //通过的处方作废 (目前就订单退费会导致处方作废)
|
||||||
unpassInvalid: "UNPASS_INVALID", //未通过的处方作废 (目前就订单退费会导致处方作废)
|
unpassInvalid: "UNPASS_INVALID", //未通过的处方作废 (目前就订单退费会导致处方作废)
|
||||||
invalid: "INVALID", //处方作废 (目前就订单退费会导致处方作废)
|
invalid: "INVALID", //处方作废 (目前就订单退费会导致处方作废)
|
||||||
|
cancelled: "CANCELLED", //门店主动撤销
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = async (item, mongodb, user) => {
|
module.exports = async (item, mongodb, user) => {
|
||||||
@ -90,6 +93,8 @@ module.exports = async (item, mongodb, user) => {
|
|||||||
return await getStoreDiagnosisRecord(item, db, user);
|
return await getStoreDiagnosisRecord(item, db, user);
|
||||||
case "markStoreRxPrinted":
|
case "markStoreRxPrinted":
|
||||||
return await markStoreRxPrinted(item, db, user);
|
return await markStoreRxPrinted(item, db, user);
|
||||||
|
case "cancelStoreDiagnosisRecord":
|
||||||
|
return await cancelStoreDiagnosisRecord(item, db, user);
|
||||||
case "getAuditDiagnosisList":
|
case "getAuditDiagnosisList":
|
||||||
return await getAuditDiagnosisList(item, db);
|
return await getAuditDiagnosisList(item, db);
|
||||||
case "getAuditedDiagnosisList":
|
case "getAuditedDiagnosisList":
|
||||||
@ -100,8 +105,6 @@ module.exports = async (item, mongodb, user) => {
|
|||||||
return await getPatientPassDiagnosisRecord(item, db);
|
return await getPatientPassDiagnosisRecord(item, db);
|
||||||
case "auditDiagnosis":
|
case "auditDiagnosis":
|
||||||
return await auditDiagnosis(item, db);
|
return await auditDiagnosis(item, db);
|
||||||
case "uploadDiagnosis":
|
|
||||||
return await uploadDiagnosis(item, db);
|
|
||||||
case "orderHasDiagnosis":
|
case "orderHasDiagnosis":
|
||||||
return await orderHasDiagnosis(item, db);
|
return await orderHasDiagnosis(item, db);
|
||||||
case "getLatestSubmitTime":
|
case "getLatestSubmitTime":
|
||||||
@ -140,11 +143,28 @@ module.exports = async (item, mongodb, user) => {
|
|||||||
return await getPatientWineBuyCount(item, db);
|
return await getPatientWineBuyCount(item, db);
|
||||||
case "getYbReviewResult":
|
case "getYbReviewResult":
|
||||||
return await getYbReviewResult(item, db);
|
return await getYbReviewResult(item, db);
|
||||||
|
case "getpdfbase64":
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: "查询成功",
|
||||||
|
data: await getpdfbase64(item, db),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let scheduleTaskIsRunning = false;
|
let scheduleTaskIsRunning = false;
|
||||||
|
|
||||||
|
async function getpdfbase64(ctx = {}, db) {
|
||||||
|
const prescriptionId = String(ctx.id || ctx._id || "").trim();
|
||||||
|
if (!ObjectId.isValid(prescriptionId)) {
|
||||||
|
throw new Error("处方 id 格式错误");
|
||||||
|
}
|
||||||
|
|
||||||
|
const paperSize = ctx.paperSize === "A4" ? "A4" : "A5";
|
||||||
|
const { pdfPath } = await getOrCreatePrescriptionPdf(db, prescriptionId, { paperSize });
|
||||||
|
return (await fs.readFile(pdfPath)).toString("base64");
|
||||||
|
}
|
||||||
|
|
||||||
async function scheduleAutoPassAfterPrescription({
|
async function scheduleAutoPassAfterPrescription({
|
||||||
rxId,
|
rxId,
|
||||||
orderId,
|
orderId,
|
||||||
@ -554,7 +574,7 @@ async function getStoreDiagnosisRecord(item, db, user) {
|
|||||||
}
|
}
|
||||||
const query = {
|
const query = {
|
||||||
drugStoreNo: { $in: [...new Set(storeIds)] },
|
drugStoreNo: { $in: [...new Set(storeIds)] },
|
||||||
status: status.pass,
|
status: { $in: [status.pass, status.cancelled] },
|
||||||
};
|
};
|
||||||
const page = item.page > 0 && Number.isInteger(item.page) ? item.page : 1;
|
const page = item.page > 0 && Number.isInteger(item.page) ? item.page : 1;
|
||||||
const pageSize =
|
const pageSize =
|
||||||
@ -619,6 +639,56 @@ async function getStoreDiagnosisRecord(item, db, user) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function cancelStoreDiagnosisRecord(item, db, user) {
|
||||||
|
const storeIds = await resolveStoreIds(item, db, user);
|
||||||
|
if (
|
||||||
|
typeof item.id !== "string" ||
|
||||||
|
!ObjectId.isValid(item.id.trim()) ||
|
||||||
|
storeIds.length === 0
|
||||||
|
) {
|
||||||
|
return { success: false, message: "参数错误" };
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const record = await db.collection("diagnostic-record").findOne({
|
||||||
|
_id: new ObjectId(item.id.trim()),
|
||||||
|
drugStoreNo: { $in: [...new Set(storeIds)] },
|
||||||
|
status: status.pass,
|
||||||
|
});
|
||||||
|
if (!record) {
|
||||||
|
return { success: false, message: "处方不存在或当前状态不可撤销" };
|
||||||
|
}
|
||||||
|
|
||||||
|
// 医保处方必须先由 HIS 撤销成功,才允许修改本地状态。
|
||||||
|
if (record.feeType === "YB") {
|
||||||
|
const hisResult = await hnHis({
|
||||||
|
type: "cancelInsuranceRx",
|
||||||
|
patientId: record.patientId,
|
||||||
|
orderno: record.medOrgOrderNo,
|
||||||
|
});
|
||||||
|
if (!hisResult || !hisResult.success) {
|
||||||
|
return { success: false, message: (hisResult && hisResult.message) || "医保处方撤销失败" };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const cancelTime = Date.now();
|
||||||
|
const result = await db.collection("diagnostic-record").updateOne(
|
||||||
|
{
|
||||||
|
_id: record._id,
|
||||||
|
drugStoreNo: { $in: [...new Set(storeIds)] },
|
||||||
|
status: status.pass,
|
||||||
|
},
|
||||||
|
{ $set: { status: status.cancelled, cancelTime } }
|
||||||
|
);
|
||||||
|
if (result.modifiedCount !== 1) {
|
||||||
|
return { success: false, message: "处方状态已变更,请刷新后重试" };
|
||||||
|
}
|
||||||
|
return { success: true, message: "处方撤销成功", data: { cancelTime } };
|
||||||
|
} catch (e) {
|
||||||
|
return { success: false, message: e.message || "处方撤销失败" };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function markStoreRxPrinted(item, db, user) {
|
async function markStoreRxPrinted(item, db, user) {
|
||||||
const storeIds = await resolveStoreIds(item, db, user);
|
const storeIds = await resolveStoreIds(item, db, user);
|
||||||
if (
|
if (
|
||||||
@ -1143,7 +1213,9 @@ async function auditDiagnosis(item, db) {
|
|||||||
|
|
||||||
async function uploadRx2His(rx, order) {
|
async function uploadRx2His(rx, order) {
|
||||||
try {
|
try {
|
||||||
const uploadData = formatUploadRxData(rx, order);
|
// 获取处方笺pdf
|
||||||
|
const base64 = await getpdfbase64({ id: rx._id.toString() }, db);
|
||||||
|
const uploadData = await formatUploadRxData(rx, { pdf: base64 });
|
||||||
const { success, message } = await hnHis({
|
const { success, message } = await hnHis({
|
||||||
type: 'hlwuploadprescription',
|
type: 'hlwuploadprescription',
|
||||||
data: uploadData
|
data: uploadData
|
||||||
@ -1281,52 +1353,6 @@ function getOriData(data) {
|
|||||||
return `医生${doctorName}向患者${patientName}开具的诊断是${diagnosis},开具的药物是${drugs}。`;
|
return `医生${doctorName}向患者${patientName}开具的诊断是${diagnosis},开具的药物是${drugs}。`;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function uploadDiagnosis(ids) {
|
|
||||||
if (!Array.isArray(ids) || ids.length == 0)
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
message: "参数错误",
|
|
||||||
};
|
|
||||||
try {
|
|
||||||
const res = await db
|
|
||||||
.collection("diagnostic-record")
|
|
||||||
.find({ _id: { $in: ids }, status: status.pass })
|
|
||||||
.limit(ids.length)
|
|
||||||
.toArray();
|
|
||||||
const list = res.map((item) => ({
|
|
||||||
payload: formatUploadRxData(item),
|
|
||||||
_id: item._id,
|
|
||||||
}));
|
|
||||||
const res1 = await Promise.all(
|
|
||||||
list.map((item) =>
|
|
||||||
zytHis({
|
|
||||||
type: "hlwuploadprescription",
|
|
||||||
payload: item.payload,
|
|
||||||
_id: item._id,
|
|
||||||
})
|
|
||||||
)
|
|
||||||
);
|
|
||||||
const successIds = res1.filter((i) => i.success).map((i) => i._id);
|
|
||||||
await db
|
|
||||||
.collection("diagnostic-record")
|
|
||||||
.updateMany(
|
|
||||||
{ _id: { $in: successIds } },
|
|
||||||
{ $set: { uploadStatus: "uploaded" } }
|
|
||||||
);
|
|
||||||
const successCount = successIds.length;
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
message: `成功上传${successCount}条数据`,
|
|
||||||
};
|
|
||||||
} catch (err) {
|
|
||||||
console.log(err, err.message);
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
message: err.message || "上传失败",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* orderStatus completed(已完成) processing(处理中) pending(待处理) cancelled(已取消) finished(已结束)
|
* orderStatus completed(已完成) processing(处理中) pending(待处理) cancelled(已取消) finished(已结束)
|
||||||
@ -1435,30 +1461,16 @@ async function orderHasDiagnosis(item) {
|
|||||||
|
|
||||||
async function reUploadDiagnosticRecord({ _id }) {
|
async function reUploadDiagnosticRecord({ _id }) {
|
||||||
try {
|
try {
|
||||||
|
return
|
||||||
const data = await db
|
const data = await db
|
||||||
.collection("diagnostic-record")
|
.collection("diagnostic-record")
|
||||||
.findOne({ _id: new ObjectId(_id) });
|
.findOne({ _id: new ObjectId(_id) });
|
||||||
|
console.log(data)
|
||||||
if (!data) return { success: false, message: "处方不存在" };
|
if (!data) return { success: false, message: "处方不存在" };
|
||||||
if (data.prescriptionType !== "storeMedicinePurchase") {
|
const base64 = await getpdfbase64({ id: data._id.toString() }, db);
|
||||||
return { success: false, message: "暂只支持门店处方重新上传" };
|
const payload = formatUploadRxData(data, { pdf: base64 });
|
||||||
}
|
console.log(payload)
|
||||||
if (data && data.uploadStatus === "uploaded")
|
return { success: false, message: '打住' }
|
||||||
return { success: false, message: "处方已上传" };
|
|
||||||
const { uploaded } = await zytHis({
|
|
||||||
type: "hlwPrescriptionOrderStatus",
|
|
||||||
orderno: data.orderId,
|
|
||||||
patientId: data.patientId,
|
|
||||||
});
|
|
||||||
if (uploaded) {
|
|
||||||
await db
|
|
||||||
.collection("diagnostic-record")
|
|
||||||
.updateOne(
|
|
||||||
{ _id: new ObjectId(_id) },
|
|
||||||
{ $set: { uploadStatus: "uploaded", hisUploadStatus: "uploaded" } }
|
|
||||||
);
|
|
||||||
return { success: true, message: "处方上传成功" };
|
|
||||||
}
|
|
||||||
const payload = formatUploadRxData(data);
|
|
||||||
const { success, message } = await zytHis({
|
const { success, message } = await zytHis({
|
||||||
type: "hlwuploadprescription",
|
type: "hlwuploadprescription",
|
||||||
payload,
|
payload,
|
||||||
|
|||||||
@ -19,56 +19,16 @@ module.exports = async (item) => {
|
|||||||
return await getHisCustomer(item);
|
return await getHisCustomer(item);
|
||||||
case "addHisCustomer":
|
case "addHisCustomer":
|
||||||
return await addHisCustomer(item);
|
return await addHisCustomer(item);
|
||||||
case "registration":
|
|
||||||
return await registration(item);
|
|
||||||
case "getPayStatus":
|
|
||||||
return await getPayStatus(item);
|
|
||||||
case "hlwRefund":
|
|
||||||
return await hlwRefund(item);
|
|
||||||
case "hlwuploadprescription":
|
case "hlwuploadprescription":
|
||||||
return await hlwuploadprescription(item);
|
return await hlwuploadprescription(item);
|
||||||
case "hlwPrescriptionOrderStatus":
|
|
||||||
return await hlwPrescriptionOrderStatus(item);
|
|
||||||
case "getHisPrescriptionUploadStatus":
|
|
||||||
return await getHisPrescriptionUploadStatus(item);
|
|
||||||
case "getHisStoreRegList":
|
|
||||||
return await getHisStoreRegList(item);
|
|
||||||
case "insurancePreSettle":
|
|
||||||
return await insurancePreSettle(item);
|
|
||||||
case "insuranceSettle":
|
|
||||||
return await insuranceSettle(item);
|
|
||||||
case "insuranceRefund":
|
|
||||||
return await insuranceRefund(item);
|
|
||||||
case "getRecent90daysDrugRecord":
|
|
||||||
return await getRecent90daysDrugRecord(item);
|
|
||||||
case "uploadMedicinePurchaseRx":
|
|
||||||
return await uploadMedicinePurchaseRx(item);
|
|
||||||
case "uploadWinePurchaseRx":
|
|
||||||
return await uploadWinePurchaseRx(item);
|
|
||||||
case "getHisDrugInfo":
|
|
||||||
return await getHisDrugInfo(item);
|
|
||||||
case "getHisMedicinePurchase":
|
|
||||||
return await getHisMedicinePurchase(item);
|
|
||||||
case "cancelMedicinePurchase":
|
|
||||||
return await cancelMedicinePurchase(item);
|
|
||||||
case "refundMedicinePurchase":
|
|
||||||
return await refundMedicinePurchase(item);
|
|
||||||
case "getHisInvoice":
|
|
||||||
return await getHisInvoice(item);
|
|
||||||
case "updateMedicinePurchaseDelivery":
|
|
||||||
return await updateMedicinePurchaseDelivery(item);
|
|
||||||
case 'syncHisChargeStatus':
|
|
||||||
return await syncHisChargeStatus(item);
|
|
||||||
case "hisTest":
|
case "hisTest":
|
||||||
return await hisTest(item);
|
return await hisTest(item);
|
||||||
case "getHisEmployeeInfo":
|
case "getHisEmployeeInfo":
|
||||||
return await getHisEmployeeInfo(item);
|
return await getHisEmployeeInfo(item);
|
||||||
case "syncHisRefundStatus":
|
|
||||||
return await syncHisRefundStatus(item);
|
|
||||||
case "getWineDrugStockInfo":
|
|
||||||
return await getWineDrugStockInfo(item);
|
|
||||||
case "ybReviewPrescription":
|
case "ybReviewPrescription":
|
||||||
return await ybReviewPrescription(item);
|
return await ybReviewPrescription(item);
|
||||||
|
case "cancelInsuranceRx":
|
||||||
|
return await cancelInsuranceRx(item);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -199,490 +159,6 @@ async function hlwuploadprescription(item) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 预约挂号
|
|
||||||
async function registration(item) {
|
|
||||||
const { patientId, doctorCode, appwin = 'line', unitCode, registerId, chargecode, reg_fee, shopid, shopname, op_id = '', channel } = item;
|
|
||||||
if (AppWin[appwin] == undefined) {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
message: "appwin参数错误"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (AppWin[appwin] == '线下挂号' && (typeof op_id !== 'string' || op_id.trim() === '')) {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
message: "op_id参数错误"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const url = `${baseUrl}/his/hlw/registration`;
|
|
||||||
// 根据dayjs 判断是上午 还是下午
|
|
||||||
const ampm = dayjs().hour() < 12 ? "a" : "p";
|
|
||||||
const requestday = dayjs().format("YYYY-MM-DD HH:mm:ss");
|
|
||||||
// registerId 为 H开头 15位随机数
|
|
||||||
const payload = {
|
|
||||||
patientId,
|
|
||||||
doctorCode,
|
|
||||||
unitCode,
|
|
||||||
requestday,
|
|
||||||
ampm,
|
|
||||||
registerId,
|
|
||||||
chargecode,
|
|
||||||
reg_fee,
|
|
||||||
shopid,
|
|
||||||
shopname,
|
|
||||||
chargetype: "普通",
|
|
||||||
appwin
|
|
||||||
};
|
|
||||||
if (AppWin[appwin] == '线下挂号') {
|
|
||||||
payload.op_id = op_id;
|
|
||||||
}
|
|
||||||
if (channel === 1) {
|
|
||||||
payload.channel = 1
|
|
||||||
}
|
|
||||||
const { data, status_code, message } = await request.main(
|
|
||||||
url,
|
|
||||||
payload,
|
|
||||||
"POST"
|
|
||||||
);
|
|
||||||
if (data && data.register && data.register.medorg_order_no) {
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
data,
|
|
||||||
message: message || "挂号成功",
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
message: message || "挂号失败",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
message: err.message || "挂号失败"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//订单支付状态查询
|
|
||||||
async function getPayStatus(item) {
|
|
||||||
const { patientId, registerId, medorgOrderNo } = item;
|
|
||||||
try {
|
|
||||||
const url = `${baseUrl}/his/hlw/settlement`;
|
|
||||||
const { status, status_code, message, ...rest } = await request.main(
|
|
||||||
url,
|
|
||||||
{
|
|
||||||
patientid: patientId,
|
|
||||||
registerid: registerId,
|
|
||||||
medorg_order_no: medorgOrderNo,
|
|
||||||
},
|
|
||||||
"POST"
|
|
||||||
);
|
|
||||||
const settlement =
|
|
||||||
rest.data && rest.data.settlement ? rest.data.settlement : null;
|
|
||||||
//settlement.status 0 已收费 1 已退费 5 未收费 x 已作废
|
|
||||||
if (status_code == 200) {
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
status: settlement ? settlement.status : '',
|
|
||||||
settlement,
|
|
||||||
message: "订单查询成功",
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
message: message || "获取失败",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
message: "获取失败",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//医保患者退费
|
|
||||||
async function hlwRefund(item) {
|
|
||||||
const { patientId, registerId, medorgOrderNo } = item;
|
|
||||||
try {
|
|
||||||
const url = `${baseUrl}/his/hlw/refund`;
|
|
||||||
const { data, status_code, message, ...rest } = await request.main(
|
|
||||||
url,
|
|
||||||
{
|
|
||||||
patientid: patientId,
|
|
||||||
registerid: registerId,
|
|
||||||
medorg_order_no: medorgOrderNo,
|
|
||||||
},
|
|
||||||
"POST"
|
|
||||||
);
|
|
||||||
if (status_code == 200 && !message) {
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
message: "退费成功",
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
message: message || "退费失败",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
message: "退费失败",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 外配处方状态查询
|
|
||||||
async function hlwPrescriptionOrderStatus(item) {
|
|
||||||
const { patientId, orderno } = item;
|
|
||||||
try {
|
|
||||||
const url = `${baseUrl}/his/hlw/orderstatus`;
|
|
||||||
const { status_code, message, data } = await request.main(
|
|
||||||
url,
|
|
||||||
{
|
|
||||||
patientid: patientId,
|
|
||||||
orderno,
|
|
||||||
},
|
|
||||||
"POST"
|
|
||||||
);
|
|
||||||
if (status_code == 200 && data && data.orderstatus) {
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
uploaded: data.orderstatus.status == '1',
|
|
||||||
status: data.orderstatus.status,
|
|
||||||
message: "查询成功",
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
message: message || "查询失败",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
message: "查询失败",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getHisPrescriptionUploadStatus(item) {
|
|
||||||
const { patientId, orderno, _id } = item;
|
|
||||||
try {
|
|
||||||
const url = `${baseUrl}/his/hlw/orderstatus`;
|
|
||||||
const { status_code, message, data } = await request.main(
|
|
||||||
url,
|
|
||||||
{
|
|
||||||
patientid: patientId,
|
|
||||||
orderno,
|
|
||||||
},
|
|
||||||
"POST"
|
|
||||||
);
|
|
||||||
if (status_code == 200 && data && data.orderstatus && data.orderstatus.status == 1) {
|
|
||||||
return { orderno, hisUploadStatus: 'uploaded', _id }
|
|
||||||
}
|
|
||||||
if (status_code == 200 && data && data.orderstatus && data.orderstatus.status == -1) {
|
|
||||||
return { orderno, hisUploadStatus: 'error', _id }
|
|
||||||
}
|
|
||||||
if (status_code == 200 && data && data.orderstatus && data.orderstatus.status == 0) {
|
|
||||||
return { orderno, hisUploadStatus: 'notUploaded', _id }
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
message: message || "查询失败",
|
|
||||||
|
|
||||||
};
|
|
||||||
} catch (err) {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
message: "查询失败",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getHisStoreRegList(item) {
|
|
||||||
const { storeId: shopid } = item;
|
|
||||||
if (typeof shopid !== 'string' || shopid.trim() === '') {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
message: "店铺id无效",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const url = `${baseUrl}/his/hlw/registerquery`;
|
|
||||||
const { status_code, message, data } = await request.main(
|
|
||||||
url,
|
|
||||||
{
|
|
||||||
shopid,
|
|
||||||
requestday: dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
|
||||||
status: "0",
|
|
||||||
starttime: dayjs().startOf('day').format('YYYY-MM-DD HH:mm:ss'),
|
|
||||||
endtime: dayjs().endOf('day').format('YYYY-MM-DD HH:mm:ss'),
|
|
||||||
hospid: "108",
|
|
||||||
},
|
|
||||||
"POST"
|
|
||||||
);
|
|
||||||
if (status_code == 200 && Array.isArray(data)) {
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
list: data,
|
|
||||||
message: "查询成功",
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
message: message || "查询失败",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
message: "查询失败",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function insurancePreSettle(ctx) {
|
|
||||||
const {
|
|
||||||
medorg_order_no: orderno,
|
|
||||||
patientId: patientid,
|
|
||||||
mdtrtCertNo: mdtrt_cert_no,
|
|
||||||
mdtrtCertType: mdtrt_cert_type,
|
|
||||||
cardSn: card_sn,
|
|
||||||
operator_code,
|
|
||||||
operator_name,
|
|
||||||
shopid,
|
|
||||||
hospid = "108"
|
|
||||||
} = ctx;
|
|
||||||
try {
|
|
||||||
const url = `${baseUrl}/his/hlw/presettle`;
|
|
||||||
const payload = { orderno, patientid, mdtrt_cert_no, mdtrt_cert_type, card_sn, operator_code, operator_name, hospid, shopid };
|
|
||||||
const { data, status_code, message } = await request.main(url, payload, "POST");
|
|
||||||
|
|
||||||
if (status_code == 200 && !message) {
|
|
||||||
return { success: true, data, message: '预结算成功' }
|
|
||||||
}
|
|
||||||
return { success: false, message: message || '预结算失败' }
|
|
||||||
} catch (e) {
|
|
||||||
return { success: false, message: e.message || '预结算失败' }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function insuranceSettle(ctx) {
|
|
||||||
const {
|
|
||||||
patientid,
|
|
||||||
orderno,
|
|
||||||
mdtrt_id,
|
|
||||||
mdtrt_cert_no,
|
|
||||||
outparm_1101,
|
|
||||||
outparm_2206A,
|
|
||||||
inparm_2207A,
|
|
||||||
outparm_2204,
|
|
||||||
totalamount,
|
|
||||||
selfpay,
|
|
||||||
operator_code,
|
|
||||||
operator_name
|
|
||||||
} = ctx;
|
|
||||||
const payload = {
|
|
||||||
patientid,
|
|
||||||
orderno,
|
|
||||||
settle_method: '7',
|
|
||||||
paymethod: '1', // 1: 现金 w: 支付宝 z: 微信
|
|
||||||
paysn: '',
|
|
||||||
payrequestsn: '',
|
|
||||||
mdtrt_id,
|
|
||||||
mdtrt_cert_no,
|
|
||||||
outparm_1101,
|
|
||||||
outparm_2206A,
|
|
||||||
inparm_2207A,
|
|
||||||
outparm_2204,
|
|
||||||
totalamount,
|
|
||||||
selfpay,
|
|
||||||
operator_code,
|
|
||||||
operator_name
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const url = `${baseUrl}/his/hlw/ybsettle`;
|
|
||||||
// const url = `${baseUrl}/his/hlw/presettle`;
|
|
||||||
const { data, status_code, message } = await request.main(url, payload, "POST");
|
|
||||||
if (status_code == 200 && !message) {
|
|
||||||
return { success: true, data, message: '结算成功' }
|
|
||||||
}
|
|
||||||
return { success: false, message: message || '结算失败' }
|
|
||||||
} catch (e) {
|
|
||||||
return { success: false, message: e.message || '结算失败' }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function insuranceRefund(ctx) {
|
|
||||||
const { type, ...payload } = ctx;
|
|
||||||
try {
|
|
||||||
const url = `${baseUrl}/his/hlw/ybrefund`;
|
|
||||||
// const url = `${baseUrl}/his/hlw/presettle`;
|
|
||||||
const { data, status_code, message } = await request.main(url, payload, "POST");
|
|
||||||
if (status_code == 200 && !message) {
|
|
||||||
return { success: true, data, message: '退费成功' }
|
|
||||||
}
|
|
||||||
return { success: false, message: message || '退费失败' }
|
|
||||||
} catch (e) {
|
|
||||||
return { success: false, message: e.message || '退费失败' }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getRecent90daysDrugRecord(ctx) {
|
|
||||||
const patientid = typeof ctx.patientId === 'string' ? ctx.patientId.trim() : '';
|
|
||||||
if (patientid === '') {
|
|
||||||
return { success: false, message: '患者ID不能为空' }
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const url = `${baseUrl}/his/hlw/patientzj3100`;
|
|
||||||
const payload = { patientid, hospid: "108", doctorCode: '10021' };
|
|
||||||
if (typeof ctx.doctorcode === 'string' && ctx.doctorcode.trim() !== '') {
|
|
||||||
payload.doctorcode = ctx.doctorcode.trim();
|
|
||||||
}
|
|
||||||
const { data, status_code, message } = await request.main(url, payload, "POST");
|
|
||||||
|
|
||||||
|
|
||||||
if (status_code == 200 && !message && data && data.outparm_zj3100) {
|
|
||||||
// 解析医保用药数据列表
|
|
||||||
const decodedBuffer = Buffer.from(data.outparm_zj3100, 'base64');
|
|
||||||
const gbkDecodedStr = decode(decodedBuffer, 'gbk');
|
|
||||||
const res = JSON.parse(gbkDecodedStr);
|
|
||||||
const drugList = res && res.data && Array.isArray(res.data.lists) ? res.data.lists.map(i => ({
|
|
||||||
hiListName: i.hiListName,
|
|
||||||
insuranceCode: i.hilistCode,
|
|
||||||
mdtrtId: i.mdtrtId,
|
|
||||||
quantity: i.cnt,
|
|
||||||
spec: i.spec && i.spec !== 'null' ? i.spec : '',
|
|
||||||
unit: i.unit && i.unit !== 'null' ? i.unit : ''
|
|
||||||
})) : [];
|
|
||||||
|
|
||||||
// 解析医保记录
|
|
||||||
const decodedBuffer1 = Buffer.from(data.outparm_zj3101, 'base64');
|
|
||||||
const gbkDecodedStr1 = decode(decodedBuffer1, 'gbk');
|
|
||||||
const res1 = JSON.parse(gbkDecodedStr1);
|
|
||||||
const recordList = res1 && res1.data && Array.isArray(res1.data.lists) ? res1.data.lists.map(i => ({
|
|
||||||
mdtrtId: i.mdtrtId,
|
|
||||||
date: i.admDate,
|
|
||||||
medinsName: i.medinsName,
|
|
||||||
})) : [];
|
|
||||||
|
|
||||||
return { success: true, drugList, message: '查询成功', recordList }
|
|
||||||
}
|
|
||||||
return { success: false, message: message || '查询失败' }
|
|
||||||
} catch (e) {
|
|
||||||
return { success: false, message: e.message || '查询失败' }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getHisDrugInfo(item) {
|
|
||||||
try {
|
|
||||||
const ignoreAreaCode = typeof item.ignoreAreaCode === 'boolean' ? item.ignoreAreaCode : false;
|
|
||||||
if (!ignoreAreaCode && (typeof item.areaCode !== 'string' || item.areaCode.trim() === '')) {
|
|
||||||
return { success: false, message: '区域代码不能为空' }
|
|
||||||
}
|
|
||||||
const showAll = typeof item.showAll === 'boolean' ? item.showAll : false;
|
|
||||||
const gjbm = Array.isArray(item.insuranceCodes) ? item.insuranceCodes.filter(i => typeof i === 'string' && i.trim() !== '') : [];
|
|
||||||
console.log('gjbm: ', gjbm)
|
|
||||||
if (gjbm.length === 0 && !showAll) {
|
|
||||||
return { success: false, message: '医保编码不能为空' }
|
|
||||||
}
|
|
||||||
const url = `${baseUrl}/his/hlw/drug`;
|
|
||||||
const payload = {
|
|
||||||
hospid: '108',
|
|
||||||
drug_type: 'xy',
|
|
||||||
area_code: typeof item.areaCode === 'string' ? item.areaCode.trim() : '',
|
|
||||||
gjbm: gjbm.join(',')
|
|
||||||
}
|
|
||||||
const { code, status_code, message, data } = await request.main(
|
|
||||||
url,
|
|
||||||
payload,
|
|
||||||
"POST"
|
|
||||||
);
|
|
||||||
if (status_code == 200 && code == '1' && !message) {
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
message: "[his]查询药品信息成功",
|
|
||||||
data: data && Array.isArray(data.drugs) ? data.drugs : []
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
message: `[his]查询药品信息传失败: ${message || '未知错误'}`,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
message: `[his]查询药品信息传错误: ${err.message || '未知'}`,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function uploadMedicinePurchaseRx(item) {
|
|
||||||
try {
|
|
||||||
const { data } = item;
|
|
||||||
const url = `${baseUrl}/his/hlw/mzordersave`;
|
|
||||||
const { code, status_code, message } = await request.main(
|
|
||||||
url,
|
|
||||||
data,
|
|
||||||
"POST"
|
|
||||||
);
|
|
||||||
if (status_code == 200 && code == '1' && !message) {
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
message: "[his]购药订单处上传成功",
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
message: `[his]购药订单处方上传失败: ${message || '未知错误'}`,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
message: `[his]购药订单处方上传错误: ${err.message || '未知'}`,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function uploadWinePurchaseRx(item) {
|
|
||||||
try {
|
|
||||||
const { data } = item;
|
|
||||||
const url = `${baseUrl}/his/hlw/tcsave`;
|
|
||||||
const { code, status_code, message } = await request.main(
|
|
||||||
url,
|
|
||||||
data,
|
|
||||||
"POST"
|
|
||||||
);
|
|
||||||
console.log('data', code, status_code, message);
|
|
||||||
if (status_code == 200 && code == '1' && !message) {
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
message: "[his]浸酒处上传成功",
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
message: `[his]浸酒处方上传失败: ${message || '未知错误'}`,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
message: `[his]浸酒处方上传错误: ${err.message || '未知'}`,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function ybReviewPrescription(item) {
|
async function ybReviewPrescription(item) {
|
||||||
try {
|
try {
|
||||||
const params = { type: "rationalDrugReview", data: item.data };
|
const params = { type: "rationalDrugReview", data: item.data };
|
||||||
@ -706,155 +182,6 @@ async function ybReviewPrescription(item) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async function getHisMedicinePurchase({ patientId, orderNo }) {
|
|
||||||
try {
|
|
||||||
const url = `${baseUrl}/his/hlw/orderquery`;
|
|
||||||
const { code, status_code, message, data } = await request.main(url, { patientid: patientId, orderno: orderNo }, "POST");
|
|
||||||
const order = data && Array.isArray(data.orders) ? data.orders[0] : null;
|
|
||||||
if (status_code == 200 && code == '1' && !message) {
|
|
||||||
if (order) {
|
|
||||||
return { success: true, data: order, message: '查询成功' }
|
|
||||||
}
|
|
||||||
return { success: false, message: `[his]处方订单查询失败: 未找到订单` }
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
message: `[his]处方订单查询失败: ${message || '未知错误'}`,
|
|
||||||
};
|
|
||||||
} catch (err) {
|
|
||||||
return { success: false, message: `[his]处方订单查询错误: ${err.message || '未知错误'}` };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function cancelMedicinePurchase({ patientId: patientid, orderNo: orderno }) {
|
|
||||||
try {
|
|
||||||
const url = `${baseUrl}/his/hlw/ordercancel`;
|
|
||||||
const { code, status_code, message } = await request.main(url, { patientid, orderno }, "POST");
|
|
||||||
if (status_code == 200 && code == '1' && !message) {
|
|
||||||
return { success: true, message: '[his]取消购药订单处方成功' }
|
|
||||||
}
|
|
||||||
return { success: false, message: `[his]取消购药订单处方失败: ${message || '未知错误'}` }
|
|
||||||
} catch (err) {
|
|
||||||
return { success: false, message: `[his]取消购药订单处方错误: ${err.message || '未知错误'}` };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function refundMedicinePurchase({ patientId: patientid, orderNo: orderno }) {
|
|
||||||
try {
|
|
||||||
const url = `${baseUrl}/his/hlw/orderrefund`;
|
|
||||||
const { code, status_code, message } = await request.main(url, { patientid, orderno }, "POST");
|
|
||||||
if (status_code == 200 && code == '1' && !message) {
|
|
||||||
return { success: true, message: '[his]退费购药订单处方成功' }
|
|
||||||
}
|
|
||||||
return { success: false, message: `[his]退费购药订单处方失败: ${message || '未知错误'}` }
|
|
||||||
} catch (err) {
|
|
||||||
return { success: false, message: `[his]退费购药订单处方错误: ${err.message || '未知错误'}` };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getHisInvoice(item) {
|
|
||||||
try {
|
|
||||||
const { patientId, orderNo } = item;
|
|
||||||
const url = `${baseUrl}/his/hlw/dzfp`;
|
|
||||||
let { code, status_code, message, data } = await request.main(url, { patientid: patientId, orderno: orderNo }, "POST");
|
|
||||||
if (status_code == 200 && code == '1' && !message) {
|
|
||||||
const dzfp = data && Array.isArray(data.dzfp) ? data.dzfp[0] : null;
|
|
||||||
return { success: true, data: dzfp && dzfp.dzfp_url ? dzfp.dzfp_url : '', message: '发票查询成功' }
|
|
||||||
}
|
|
||||||
return { success: false, message: `[his]发票查询失败: ${message || '未知错误'}` }
|
|
||||||
} catch (err) {
|
|
||||||
return { success: false, message: `[his]发票查询错误: ${err.message || '未知错误'}` };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function updateMedicinePurchaseDelivery(item) {
|
|
||||||
try {
|
|
||||||
const {
|
|
||||||
patientId: patientid,
|
|
||||||
orderNo: orderno,
|
|
||||||
backFlag: back_flag = 0,
|
|
||||||
shippingType: deliv_type,
|
|
||||||
shippingNo: deliv_no,
|
|
||||||
shippingFee: deliv_fee,
|
|
||||||
pickupCode: tracking_no,
|
|
||||||
payTime: pay_dt,
|
|
||||||
tradeNo: pay_orderno,
|
|
||||||
receiveName: shipp_name,
|
|
||||||
receivePhone: shipp_tel,
|
|
||||||
fullAddress: shipp_addr,
|
|
||||||
invoice
|
|
||||||
} = item;
|
|
||||||
const payload = {
|
|
||||||
patientid,
|
|
||||||
orderno,
|
|
||||||
back_flag, // 0 收取运费 | 1 退还运费
|
|
||||||
deliv_type,
|
|
||||||
deliv_no,
|
|
||||||
deliv_fee,
|
|
||||||
pay_dt,
|
|
||||||
pay_orderno,
|
|
||||||
shipp_name,
|
|
||||||
shipp_tel,
|
|
||||||
shipp_addr,
|
|
||||||
tracking_no,
|
|
||||||
invoice
|
|
||||||
}
|
|
||||||
const url = `${baseUrl}/his/hlw/delivery`;
|
|
||||||
let { code, status_code, message, data } = await request.main(url, payload, "POST");
|
|
||||||
if (status_code == 200 && code == '1' && !message) {
|
|
||||||
return { success: true, data, message: '[his]同步配药订单物流信息成功' }
|
|
||||||
}
|
|
||||||
return { success: false, message: `[his]同步配药订单物流信息失败: ${message || '未知错误'}` }
|
|
||||||
} catch (err) {
|
|
||||||
return { success: false, message: `[his]同步配药订单物流信息错误: ${err.message || '未知错误'}` };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function syncHisChargeStatus(ctx) {
|
|
||||||
try {
|
|
||||||
const payload = {
|
|
||||||
patientid: ctx.patientId,
|
|
||||||
orderno: ctx.orderNo,
|
|
||||||
settle_method: 1,
|
|
||||||
paymethod: 'h',
|
|
||||||
paysn: ctx.tradeNo,
|
|
||||||
payrequestsn: ctx.outTradeNo,
|
|
||||||
totalamount: ctx.totalAmount,
|
|
||||||
selfpay: ctx.totalAmount,
|
|
||||||
operator_code: 'hlw',
|
|
||||||
operator_name: '互联网医院'
|
|
||||||
}
|
|
||||||
const url = `${baseUrl}/his/hlw/ybsettle`;
|
|
||||||
let { code, status_code, message, data } = await request.main(url, payload, "POST");
|
|
||||||
if (status_code == 200 && code == '1' && !message) {
|
|
||||||
return { success: true, data, message: '[his]同步浸酒订单收费成功' }
|
|
||||||
}
|
|
||||||
return { success: false, message: `[his]同步浸酒订单收费失败: ${message || '未知错误'}` }
|
|
||||||
} catch (err) {
|
|
||||||
return { success: false, message: `[his]同步浸酒订单收费错误: ${err.message || '未知错误'}` };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function syncHisRefundStatus(ctx) {
|
|
||||||
try {
|
|
||||||
const payload = {
|
|
||||||
patientid: ctx.patientId,
|
|
||||||
orderno: ctx.orderNo,
|
|
||||||
ptlsh: ctx.refundSerialNo
|
|
||||||
}
|
|
||||||
const url = `${baseUrl}/his/hlw/orderrefund`;
|
|
||||||
let { code, status_code, message, data } = await request.main(url, payload, "POST");
|
|
||||||
if (status_code == 200 && code == '1' && !message) {
|
|
||||||
return { success: true, data, message: '[his]同步浸酒订单退费成功' }
|
|
||||||
}
|
|
||||||
return { success: false, message: `[his]同步浸酒订单退费失败: ${message || '未知错误'}` }
|
|
||||||
} catch (err) {
|
|
||||||
return { success: false, message: `[his]同步浸酒订单退费错误: ${err.message || '未知错误'}` };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
async function getHisEmployeeInfo(item) {
|
async function getHisEmployeeInfo(item) {
|
||||||
const { code } = item;
|
const { code } = item;
|
||||||
try {
|
try {
|
||||||
@ -877,46 +204,6 @@ async function getHisEmployeeInfo(item) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getWineDrugStockInfo(item) {
|
|
||||||
try {
|
|
||||||
if (typeof item.code !== 'string' || item.code.trim() === '') {
|
|
||||||
return { success: false, message: '中药饮片代码不能为空' }
|
|
||||||
}
|
|
||||||
if (!(Number.isInteger(item.num) && item.num > 0)) {
|
|
||||||
return { success: false, message: '中药饮片数量必须是整数且大于0' }
|
|
||||||
}
|
|
||||||
const url = `${baseUrl}/his/hlw/drug`;
|
|
||||||
const payload = {
|
|
||||||
hospid: '108',
|
|
||||||
drug_type: 'zcy',
|
|
||||||
tc_code: item.code.trim(),
|
|
||||||
tc_number: item.num
|
|
||||||
}
|
|
||||||
const { code, status_code, message, data } = await request.main(
|
|
||||||
url,
|
|
||||||
payload,
|
|
||||||
"POST"
|
|
||||||
);
|
|
||||||
if (status_code == 200 && code == '1') {
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
message: "[his]查询药品信息成功",
|
|
||||||
data: data
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
message: `中药饮品查询失败: ${message || '未知错误'}`,
|
|
||||||
};
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
message: `中药饮品查询失败错误: ${err.message || '未知'}`,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function hisTest() {
|
async function hisTest() {
|
||||||
// const data = {
|
// const data = {
|
||||||
// patientId: '10428622',
|
// patientId: '10428622',
|
||||||
@ -952,3 +239,31 @@ async function updateHisDrug({ data: drugArr }) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function cancelInsuranceRx(item) {
|
||||||
|
const patientId = typeof item.patientId === "string" ? item.patientId.trim() : "";
|
||||||
|
const orderno = typeof item.orderno === "string" ? item.orderno.trim() : "";
|
||||||
|
if (!patientId || !orderno) {
|
||||||
|
return { success: false, message: "医保处方缺少患者编号或处方编号" };
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const params = { type: "hlwPrescriptionOrderCancel", patientId, orderno };
|
||||||
|
const { code, status_code, message } = await request.main(url, params, "POST");
|
||||||
|
if (status_code == 200 && code == "1") {
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: `处方撤销成功`,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: message || "处方撤销失败",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: err.message || "处方撤销错误",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -131,7 +131,6 @@ module.exports = async (item, db, context) => {
|
|||||||
case "getAuditDiagnosisList":
|
case "getAuditDiagnosisList":
|
||||||
case "getAuditedDiagnosisList":
|
case "getAuditedDiagnosisList":
|
||||||
case "auditDiagnosis":
|
case "auditDiagnosis":
|
||||||
case "uploadDiagnosis":
|
|
||||||
case "reUploadDiagnosticRecord":
|
case "reUploadDiagnosticRecord":
|
||||||
case "getPatientDiagnosisRecord":
|
case "getPatientDiagnosisRecord":
|
||||||
case "getPatientPassDiagnosisRecord":
|
case "getPatientPassDiagnosisRecord":
|
||||||
@ -139,6 +138,7 @@ module.exports = async (item, db, context) => {
|
|||||||
case "orderHasDiagnosis":
|
case "orderHasDiagnosis":
|
||||||
case "getStoreDiagnosisRecord":
|
case "getStoreDiagnosisRecord":
|
||||||
case "markStoreRxPrinted":
|
case "markStoreRxPrinted":
|
||||||
|
case "cancelStoreDiagnosisRecord":
|
||||||
case "getAllDiagnosisRecord":
|
case "getAllDiagnosisRecord":
|
||||||
case "getDoctorRxStats":
|
case "getDoctorRxStats":
|
||||||
case "getPharmacistRxStats":
|
case "getPharmacistRxStats":
|
||||||
|
|||||||
@ -12,9 +12,11 @@ let browserPromise;
|
|||||||
let activeJobs = 0;
|
let activeJobs = 0;
|
||||||
const waiters = [];
|
const waiters = [];
|
||||||
const cachedPdfJobs = new Map();
|
const cachedPdfJobs = new Map();
|
||||||
const PDF_TEMPLATE_VERSION = "v5";
|
const PDF_TEMPLATE_VERSION = "v7";
|
||||||
const MAX_SIGNATURE_IMAGE_BYTES = 1024 * 1024;
|
const MAX_SIGNATURE_IMAGE_BYTES = 1024 * 1024;
|
||||||
const SIGNATURE_DOWNLOAD_TIMEOUT_MS = 5000;
|
const SIGNATURE_DOWNLOAD_TIMEOUT_MS = 5000;
|
||||||
|
const PRESCRIPTION_SEAL_IMAGE_URL = process.env.CONFIG_PRESCRIPTION_SEAL_IMAGE_URL
|
||||||
|
|| "https://hlwyy.hnkhhospital.com/upload-files/other/stamp.png";
|
||||||
|
|
||||||
const signatureMimeTypes = {
|
const signatureMimeTypes = {
|
||||||
".png": "image/png",
|
".png": "image/png",
|
||||||
@ -235,14 +237,28 @@ function signature(value, fallback) {
|
|||||||
: `<span>${escapeHtml(fallback)}</span>`;
|
: `<span>${escapeHtml(fallback)}</span>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function addDrugStoreName(db, record) {
|
||||||
|
if (typeof record.drugStoreName === "string" || typeof record.orderId !== "string" || !record.orderId.trim()) {
|
||||||
|
return record;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const order = await db.collection("consult-order").findOne(
|
||||||
|
{ orderId: record.orderId },
|
||||||
|
{ projection: { drugStoreName: 1 } }
|
||||||
|
);
|
||||||
|
return { ...record, drugStoreName: order?.drugStoreName || "" };
|
||||||
|
} catch (_error) {
|
||||||
|
// 门店名称仅用于处方提示语;查询异常不能阻止 PDF 的生成。
|
||||||
|
return record;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function buildPrescriptionHtml(record, paperSize = "A5", signatureImages = {}) {
|
function buildPrescriptionHtml(record, paperSize = "A5", signatureImages = {}) {
|
||||||
const size = paperSize === "A4" ? "A4" : "A5";
|
const size = paperSize === "A4" ? "A4" : "A5";
|
||||||
const diagnosis = Array.isArray(record.diagnosisList) ? record.diagnosisList : [];
|
const diagnosis = Array.isArray(record.diagnosisList) ? record.diagnosisList : [];
|
||||||
const drugs = Array.isArray(record.drugs) ? record.drugs : [];
|
const drugs = Array.isArray(record.drugs) ? record.drugs : [];
|
||||||
const prescriptionTime = dayjs(record.prescriptionEndTime || record.createTime);
|
const prescriptionTime = dayjs(record.prescriptionEndTime || record.createTime);
|
||||||
const diagnosisHtml = diagnosis.length
|
const diagnosisText = diagnosis.map((item) => item?.name).filter(Boolean).join("+");
|
||||||
? diagnosis.map((item, index) => `<div>${index + 1}. ${escapeHtml(item.name)}</div>`).join("")
|
|
||||||
: "<div>—</div>";
|
|
||||||
const drugHtml = drugs.length
|
const drugHtml = drugs.length
|
||||||
? drugs.map((drug, index) => `
|
? drugs.map((drug, index) => `
|
||||||
<section class="medicine-item">
|
<section class="medicine-item">
|
||||||
@ -255,34 +271,37 @@ function buildPrescriptionHtml(record, paperSize = "A5", signatureImages = {}) {
|
|||||||
return `<!doctype html>
|
return `<!doctype html>
|
||||||
<html lang="zh-CN"><head><meta charset="utf-8" />
|
<html lang="zh-CN"><head><meta charset="utf-8" />
|
||||||
<style>
|
<style>
|
||||||
@page { size: ${size} portrait; margin: 6mm; }
|
@page { size: ${size} portrait; margin: 8mm; }
|
||||||
* { box-sizing: border-box; }
|
* { box-sizing: border-box; }
|
||||||
html, body { margin: 0; padding: 0; color: #111; font-family: "Noto Sans CJK SC", "Noto Sans SC", SimSun, "Songti SC", serif; font-size: 12px; }
|
html, body { margin: 0; padding: 0; color: #111; font-family: "Noto Sans CJK SC", "Noto Sans SC", SimSun, "Songti SC", serif; font-size: 14px; }
|
||||||
body { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
|
body { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
|
||||||
.prescription { min-height: ${size === "A5" ? "198mm" : "285mm"}; display: flex; flex-direction: column; line-height: 1.5; }
|
.prescription { min-height: ${size === "A5" ? "194mm" : "281mm"}; display: flex; flex-direction: column; line-height: 1.28; overflow: hidden; }
|
||||||
.header { position: relative; border-bottom: 1px solid #111; padding: 1px 0 5px; }
|
.header { position: relative; border-bottom: 1px solid #111; padding: 3px 0 4px; }
|
||||||
.title { font-weight: 700; font-size: 16px; text-align: center; line-height: 1.75; }
|
.title { font-weight: 700; font-size: 17px; text-align: center; line-height: 1.4; }
|
||||||
.rx-type { position: absolute; top: 0; right: 0; width: 38px; border: 1px solid #555; text-align: center; color: #555; line-height: 1.55; }
|
.rx-type { position: absolute; top: 0; right: 0; width: 40px; border: 1px solid #333; text-align: center; color: #666; font-size: 12px; line-height: 1.3; }
|
||||||
.rx-number { margin-top: 4px; font-size: 12px; }
|
.rx-number { margin-top: 5px; }
|
||||||
.patient-info { padding-top: 5px; }
|
.patient-info { padding-top: 5px; }
|
||||||
.info-row { display: flex; padding: 2px 0; gap: 5px; }
|
.info-row { display: flex; padding: 2px; }
|
||||||
.info-cell { flex: 1; min-width: 0; overflow-wrap: anywhere; }
|
.info-cell { flex: 1; min-width: 0; overflow-wrap: anywhere; }
|
||||||
.info-half { width: 50%; overflow-wrap: anywhere; }
|
.info-half { width: 50%; overflow-wrap: anywhere; }
|
||||||
.diagnosis { margin-top: 5px; }
|
.diagnosis { margin-top: 5px; }
|
||||||
.diagnosis-head { display: flex; justify-content: space-between; gap: 8px; }
|
.diagnosis-head { display: flex; justify-content: space-between; gap: 8px; }
|
||||||
.diagnosis-list { padding-top: 2px; min-height: 18px; }
|
.diagnosis-text { flex: 1; min-width: 0; overflow-wrap: anywhere; }
|
||||||
.date { white-space: nowrap; color: #555; }
|
.date { flex: none; white-space: nowrap; }
|
||||||
.medicine { margin-top: 4px; }
|
.medicine { margin-top: 5px; }
|
||||||
.rp { font-size: 16px; font-weight: 700; margin-bottom: 3px; }
|
.rp-line { position: relative; display: flex; align-items: center; min-height: 30px; margin-bottom: 6px; }
|
||||||
.medicine-item { break-inside: avoid; margin: 0 0 11px; padding-left: 2px; }
|
.rp-line::after { content: ""; flex: 1; margin-left: 8px; border-top: 1px dashed #6b7280; }
|
||||||
.medicine-name { font-weight: 700; font-size: 13px; }
|
.rp { font-size: 20px; font-weight: 700; }
|
||||||
.medicine-detail { color: #444; margin-top: 2px; }
|
.seal-image { position: absolute; z-index: 1; top: -4px; right: 0; width: 120px; height: 120px; object-fit: contain; }
|
||||||
.footer { margin-top: auto; border-top: 1px dashed #999; padding-top: 6px; break-inside: avoid; }
|
.medicine-item { break-inside: avoid; margin: 0 0 6px; }
|
||||||
.signature-row, .action-row { display: flex; padding: 2px 0; }
|
.medicine-name { font-weight: 700; }
|
||||||
.signature-cell, .action-cell { width: 33.333%; min-height: 20px; }
|
.medicine-detail { color: #666; margin-top: 1px; }
|
||||||
.signature-image { display: inline-block; width: 82px; height: 28px; object-fit: contain; vertical-align: middle; }
|
.footer { margin-top: auto; border-top: 1px dashed #999; padding-top: 5px; break-inside: avoid; }
|
||||||
.notice { margin-top: 4px; color: #b33; font-size: 10px; line-height: 1.4; }
|
.signature-row, .action-row { display: flex; padding-top: 4px; }
|
||||||
.blank-line { display: inline-block; width: 35px; border-bottom: 1px solid currentColor; }
|
.signature-cell, .action-cell { width: 33.333%; min-height: 24px; }
|
||||||
|
.signature-image { display: inline-block; width: 76px; height: 30px; object-fit: contain; vertical-align: middle; }
|
||||||
|
.notice { margin-top: 0; font-size: 12px; line-height: 1.25; white-space: nowrap; }
|
||||||
|
.notice-first { margin-top: 7px; }
|
||||||
@media print { .medicine-item, .footer { page-break-inside: avoid; } }
|
@media print { .medicine-item, .footer { page-break-inside: avoid; } }
|
||||||
</style></head><body>
|
</style></head><body>
|
||||||
<main class="prescription">
|
<main class="prescription">
|
||||||
@ -292,14 +311,14 @@ function buildPrescriptionHtml(record, paperSize = "A5", signatureImages = {}) {
|
|||||||
<div class="rx-number">NO:${escapeHtml(record.medOrgOrderNo || record._id)}</div>
|
<div class="rx-number">NO:${escapeHtml(record.medOrgOrderNo || record._id)}</div>
|
||||||
</header>
|
</header>
|
||||||
<section class="patient-info">
|
<section class="patient-info">
|
||||||
<div class="info-row"><div class="info-cell">姓名:${escapeHtml(record.name)}</div><div class="info-cell">性别:${escapeHtml(getSex(record))}</div><div class="info-cell">费别:${record.feeType === "YB" ? "医保" : "自费"}</div><div class="info-cell">年龄:${escapeHtml(getAge(record))}</div></div>
|
<div class="info-row"><div class="info-cell">姓名:${escapeHtml(record.name)}</div><div class="info-cell">性别:${escapeHtml(getSex(record))}</div><div class="info-cell">年龄:${escapeHtml(getAge(record))}</div><div class="info-cell">费别:${record.feeType === "YB" ? "医保" : "自费"}</div></div>
|
||||||
<div class="info-row"><div class="info-half">门诊病历号:${escapeHtml(record.blhno)}</div><div class="info-half">科别:${escapeHtml(record.deptName)}</div></div>
|
<div class="info-row"><div class="info-half">门诊病历号:${escapeHtml(record.blhno)}</div><div class="info-half">科别:${escapeHtml(record.deptName)}</div></div>
|
||||||
<div class="info-row"><div class="info-cell">地址:${escapeHtml(record.address)}</div></div>
|
<div class="info-row"><div class="info-cell">地址:${escapeHtml(record.address)}</div></div>
|
||||||
<div class="info-row"><div class="info-cell">电话号:${escapeHtml(record.mobile)}</div></div>
|
<div class="info-row"><div class="info-cell">电话号:${escapeHtml(record.mobile)}</div></div>
|
||||||
</section>
|
</section>
|
||||||
<section class="diagnosis"><div class="diagnosis-head"><div>诊断:</div><div class="date">开方日期:${prescriptionTime.isValid() ? prescriptionTime.format("YYYY-MM-DD HH:mm") : ""}</div></div><div class="diagnosis-list">${diagnosisHtml}</div></section>
|
<section class="diagnosis"><div class="diagnosis-head"><div class="diagnosis-text">诊断:${escapeHtml(diagnosisText)}</div><div class="date">开方日期:${prescriptionTime.isValid() ? prescriptionTime.format("YYYY-MM-DD HH:mm") : ""}</div></div></section>
|
||||||
<section class="medicine"><div class="rp">Rp</div>${drugHtml}</section>
|
<section class="medicine"><div class="rp-line"><div class="rp">Rp</div>${signatureImages.seal ? `<img class="seal-image" src="${signatureImages.seal}" alt="处方印章" />` : ""}</div>${drugHtml}</section>
|
||||||
<footer class="footer"><div class="signature-row"><div class="signature-cell">医生:${signature(signatureImages.doctor || record.doctorSignImg, record.doctorName)}</div><div class="signature-cell">审方药师:${signature(signatureImages.pharmacist || record.pharmacistSignImg, record.pharmacist)}</div></div><div class="action-row"><div class="action-cell">调配:</div><div class="action-cell">核对:</div><div class="action-cell">发药:</div></div><div class="notice">注意:请勿丢失,处方当日有效,因特殊情况,该处方有效为<span class="blank-line"></span>天(签名:<span class="blank-line"></span>)</div></footer>
|
<footer class="footer"><div class="signature-row"><div class="signature-cell">医生:${signature(signatureImages.doctor || record.doctorSignImg, record.doctorName)}</div><div class="signature-cell">审方药师:${signature(signatureImages.pharmacist || record.pharmacistSignImg, record.pharmacist)}</div><div class="signature-cell"></div></div><div class="action-row"><div class="action-cell">审核:</div><div class="action-cell">调配:</div><div class="action-cell">核对/发药:</div></div><div class="notice notice-first">1.根据《处方管理办法》规定,本处方开具三天有效;</div><div class="notice">2.本处方仅供患者${escapeHtml(record.drugStoreName)}使用,本处方金额以实际药店成交金额为准;</div><div class="notice">3.请仔细阅读药品使用说明,服药谨遵医嘱,如有不适请立即停药并前往医院就诊。</div></footer>
|
||||||
</main>
|
</main>
|
||||||
</body></html>`;
|
</body></html>`;
|
||||||
}
|
}
|
||||||
@ -310,12 +329,13 @@ async function generatePrescriptionPdf(record, options = {}) {
|
|||||||
try {
|
try {
|
||||||
const browser = await getBrowser();
|
const browser = await getBrowser();
|
||||||
page = await browser.newPage();
|
page = await browser.newPage();
|
||||||
const [doctor, pharmacist] = await Promise.all([
|
const [doctor, pharmacist, seal] = await Promise.all([
|
||||||
loadSignatureDataImage(record.doctorSignImg),
|
loadSignatureDataImage(record.doctorSignImg),
|
||||||
loadSignatureDataImage(record.pharmacistSignImg),
|
loadSignatureDataImage(record.pharmacistSignImg),
|
||||||
|
loadSignatureDataImage(PRESCRIPTION_SEAL_IMAGE_URL),
|
||||||
]);
|
]);
|
||||||
await page.setContent(
|
await page.setContent(
|
||||||
buildPrescriptionHtml(record, options.paperSize, { doctor, pharmacist }),
|
buildPrescriptionHtml(record, options.paperSize, { doctor, pharmacist, seal }),
|
||||||
{ waitUntil: "load" }
|
{ waitUntil: "load" }
|
||||||
);
|
);
|
||||||
await page.evaluate(() => document.fonts && document.fonts.ready);
|
await page.evaluate(() => document.fonts && document.fonts.ready);
|
||||||
@ -343,7 +363,10 @@ async function createPrescriptionPdf(db, id, options) {
|
|||||||
error.statusCode = 404;
|
error.statusCode = 404;
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
return generatePrescriptionPdf(decryptDiagnosticRecordFields(record), options);
|
return generatePrescriptionPdf(
|
||||||
|
await addDrugStoreName(db, decryptDiagnosticRecordFields(record)),
|
||||||
|
options
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPdfPath(id, paperSize) {
|
function getPdfPath(id, paperSize) {
|
||||||
@ -394,7 +417,10 @@ async function getOrCreatePrescriptionPdf(db, id, options = {}) {
|
|||||||
error.statusCode = 404;
|
error.statusCode = 404;
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
const pdf = await generatePrescriptionPdf(decryptDiagnosticRecordFields(record), { paperSize });
|
const pdf = await generatePrescriptionPdf(
|
||||||
|
await addDrugStoreName(db, decryptDiagnosticRecordFields(record)),
|
||||||
|
{ paperSize }
|
||||||
|
);
|
||||||
const temporaryPath = `${pdfPath}.${crypto.randomUUID()}.tmp`;
|
const temporaryPath = `${pdfPath}.${crypto.randomUUID()}.tmp`;
|
||||||
try {
|
try {
|
||||||
await fsp.writeFile(temporaryPath, pdf, { flag: "wx" });
|
await fsp.writeFile(temporaryPath, pdf, { flag: "wx" });
|
||||||
|
|||||||
219
index.js
219
index.js
@ -52,6 +52,7 @@ const { jwtAuth, optionalJwtAuth } = require("./middleware/jwt-auth");
|
|||||||
const { smartAuth } = require("./middleware/smart-auth");
|
const { smartAuth } = require("./middleware/smart-auth");
|
||||||
const sms = require("./sms");
|
const sms = require("./sms");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
|
const fs = require("fs/promises");
|
||||||
const { ObjectId } = require("mongodb");
|
const { ObjectId } = require("mongodb");
|
||||||
const { useUploadFileParse } = require("./upload-file-parse");
|
const { useUploadFileParse } = require("./upload-file-parse");
|
||||||
const app = express();
|
const app = express();
|
||||||
@ -301,6 +302,17 @@ app.get(
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// 返回处方笺 PDF 的 Base64 内容,供客户端上传或嵌入预览。
|
||||||
|
app.get(
|
||||||
|
"/hlw/prescriptions/:id/base64",
|
||||||
|
asyncHandler(async (req, res) => {
|
||||||
|
const db = await getDatabase("Internet-hospital");
|
||||||
|
const paperSize = req.query.paperSize === "A4" ? "A4" : "A5";
|
||||||
|
const { pdfPath } = await getOrCreatePrescriptionPdf(db, req.params.id, { paperSize });
|
||||||
|
sendSuccess(res, (await fs.readFile(pdfPath)).toString("base64"), "查询成功");
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
// POST请求处理器
|
// POST请求处理器
|
||||||
app.post(
|
app.post(
|
||||||
"/getYoucanData/member",
|
"/getYoucanData/member",
|
||||||
@ -317,28 +329,6 @@ app.post(
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
app.post(
|
|
||||||
"/getYoucanData/todo",
|
|
||||||
jwtAuth,
|
|
||||||
asyncHandler(async (req, res) => {
|
|
||||||
const requestData = req.body;
|
|
||||||
const db = await getDatabase("admin");
|
|
||||||
let item = await todo.main(requestData, db);
|
|
||||||
safeSend(res, item);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
app.post(
|
|
||||||
"/getYoucanData/groupmsg",
|
|
||||||
jwtAuth,
|
|
||||||
asyncHandler(async (req, res) => {
|
|
||||||
const requestData = req.body;
|
|
||||||
const db = await getDatabase("admin");
|
|
||||||
let item = await groupmsg.main(requestData, db);
|
|
||||||
safeSend(res, item);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
app.post(
|
app.post(
|
||||||
"/getYoucanData/corp",
|
"/getYoucanData/corp",
|
||||||
smartAuth, // 使用智能鉴权,支持白名单 type 跳过鉴权
|
smartAuth, // 使用智能鉴权,支持白名单 type 跳过鉴权
|
||||||
@ -385,37 +375,6 @@ app.post(
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
app.post(
|
|
||||||
"/getYoucanData/sessionArchive",
|
|
||||||
jwtAuth,
|
|
||||||
asyncHandler(async (req, res) => {
|
|
||||||
const requestData = req.body;
|
|
||||||
const db = await getDatabase("corp");
|
|
||||||
const item = await sessionArchive.main(requestData, db);
|
|
||||||
safeSend(res, item);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
app.post(
|
|
||||||
"/getYoucanData/weCom",
|
|
||||||
jwtAuth,
|
|
||||||
asyncHandler(async (req, res) => {
|
|
||||||
const requestData = req.body;
|
|
||||||
const item = await weCom.main(requestData);
|
|
||||||
safeSend(res, item);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
app.post(
|
|
||||||
"/getYoucanData/customerHisSync",
|
|
||||||
jwtAuth,
|
|
||||||
asyncHandler(async (req, res) => {
|
|
||||||
const requestData = req.body;
|
|
||||||
const item = await customerHisSync.main(requestData);
|
|
||||||
safeSend(res, item);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
app.post(
|
app.post(
|
||||||
"/getYoucanData/sms",
|
"/getYoucanData/sms",
|
||||||
asyncHandler(async (req, res) => {
|
asyncHandler(async (req, res) => {
|
||||||
@ -457,42 +416,6 @@ app.post(
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
app.post(
|
|
||||||
"/union-pay-notify",
|
|
||||||
smartAuth, // 使用智能鉴权,支持白名单 type 跳过鉴权
|
|
||||||
asyncHandler(async (req, res) => {
|
|
||||||
await trade.handleUnionPayNotify(req, res);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
app.post(
|
|
||||||
"/fengniao-auth",
|
|
||||||
smartAuth, // 使用智能鉴权,支持白名单 type 跳过鉴权
|
|
||||||
asyncHandler(async (req, res) => {
|
|
||||||
await fengniao.handleFengNiaoAuth(req, res);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
app.post(
|
|
||||||
"/fengniao-notify",
|
|
||||||
smartAuth, // 使用智能鉴权,支持白名单 type 跳过鉴权
|
|
||||||
asyncHandler(async (req, res) => {
|
|
||||||
await fengniao.notify(req, res);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
app.post(
|
|
||||||
"/zyt-his-notify",
|
|
||||||
smartAuth, // 使用智能鉴权,支持白名单 type 跳过鉴权
|
|
||||||
asyncHandler(async (req, res) => {
|
|
||||||
const notifyHandler = require('./hlw/zyt-his/notify');
|
|
||||||
const requestData = req.body;
|
|
||||||
const result = await notifyHandler.handleNotify(requestData);
|
|
||||||
safeSend(res, result)
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
app.post(
|
app.post(
|
||||||
"/IMCallBack",
|
"/IMCallBack",
|
||||||
@ -529,124 +452,6 @@ app.get(
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
|
||||||
* mPaaS 音视频通话:云端自动录制回调
|
|
||||||
* - 控制台配置:通话应用 -> 功能配置 -> 配置云端自动录制及录制回调地址
|
|
||||||
* - 回调方式:POST(application/json)
|
|
||||||
* - 业务侧响应:{ bizRequestId, code: 0 }
|
|
||||||
*/
|
|
||||||
app.post(
|
|
||||||
"/mrtc/record/callback",
|
|
||||||
asyncHandler(async (req, res) => {
|
|
||||||
const payload = req.body && typeof req.body === "object" ? req.body : {};
|
|
||||||
const {
|
|
||||||
bizRequestId,
|
|
||||||
bizName,
|
|
||||||
appId,
|
|
||||||
workspaceId,
|
|
||||||
roomId,
|
|
||||||
recordId,
|
|
||||||
eventCode,
|
|
||||||
recordResult,
|
|
||||||
} = payload;
|
|
||||||
|
|
||||||
// 按文档要求回包,避免云端重试;落库失败也不影响回包
|
|
||||||
res.json({ bizRequestId: bizRequestId || "", code: 0 });
|
|
||||||
|
|
||||||
try {
|
|
||||||
const db = await getDatabase("Internet-hospital");
|
|
||||||
const now = Date.now();
|
|
||||||
|
|
||||||
let orderId = "";
|
|
||||||
let doctorCode = "";
|
|
||||||
if (typeof roomId === "string" && roomId) {
|
|
||||||
const order = await db.collection("consult-order").findOne(
|
|
||||||
{ mrtcRoomId: roomId },
|
|
||||||
{ projection: { orderId: 1, doctorCode: 1 } }
|
|
||||||
);
|
|
||||||
if (order && order.orderId) orderId = order.orderId;
|
|
||||||
if (order && order.doctorCode) doctorCode = order.doctorCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
const normalizedEventCode =
|
|
||||||
typeof eventCode === "number"
|
|
||||||
? eventCode
|
|
||||||
: typeof eventCode === "string" && eventCode !== ""
|
|
||||||
? Number(eventCode)
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
const rr = recordResult && typeof recordResult === "object" ? recordResult : null;
|
|
||||||
const status =
|
|
||||||
rr && rr.status !== undefined && rr.status !== null && rr.status !== "" ? Number(rr.status) : undefined;
|
|
||||||
|
|
||||||
const $set = {
|
|
||||||
updatedAt: now,
|
|
||||||
source: "AUTO_RECORD_CALLBACK",
|
|
||||||
};
|
|
||||||
if (orderId) $set.orderId = orderId;
|
|
||||||
if (doctorCode) $set.doctorCode = doctorCode;
|
|
||||||
if (typeof roomId === "string" && roomId) $set.roomId = roomId;
|
|
||||||
if (typeof recordId === "string" && recordId) $set.recordId = recordId;
|
|
||||||
if (typeof bizRequestId === "string" && bizRequestId) $set.bizRequestId = bizRequestId;
|
|
||||||
if (typeof bizName === "string" && bizName) $set.bizName = bizName;
|
|
||||||
if (typeof appId === "string" && appId) $set.appId = appId;
|
|
||||||
if (typeof workspaceId === "string" && workspaceId) $set.workspaceId = workspaceId;
|
|
||||||
if (normalizedEventCode !== undefined && Number.isFinite(normalizedEventCode)) $set.eventCode = normalizedEventCode;
|
|
||||||
|
|
||||||
// eventCode=99 时传 recordResult:status/fileType/filePath/recordStartTime/mediaType
|
|
||||||
if (normalizedEventCode === 99 && rr) {
|
|
||||||
if (status !== undefined && Number.isFinite(status)) $set.status = status;
|
|
||||||
if (rr.fileType !== undefined && rr.fileType !== null && rr.fileType !== "") $set.fileType = Number(rr.fileType);
|
|
||||||
if (typeof rr.filePath === "string") $set.filePath = rr.filePath;
|
|
||||||
if (rr.recordStartTime !== undefined && rr.recordStartTime !== null && rr.recordStartTime !== "")
|
|
||||||
$set.startAt = Number(rr.recordStartTime);
|
|
||||||
if (rr.mediaType !== undefined && rr.mediaType !== null && rr.mediaType !== "") $set.mediaType = Number(rr.mediaType);
|
|
||||||
}
|
|
||||||
|
|
||||||
// eventCode=11:录制结束(结束时间以回调到达时间为准)
|
|
||||||
if (normalizedEventCode === 11) {
|
|
||||||
$set.endAt = now;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 以 recordId 为主键幂等(回调不会携带 recordThirdId)
|
|
||||||
const filter = recordId ? { recordId } : { bizRequestId: bizRequestId || `AUTO_${now}` };
|
|
||||||
|
|
||||||
await db.collection("mrtc-video-record").updateOne(
|
|
||||||
filter,
|
|
||||||
{
|
|
||||||
// 注意:MongoDB 不允许在同一次 update 中同时用 $setOnInsert 与 $push 修改同一路径(会报 conflict)
|
|
||||||
// events 字段由 $push 在首次写入时自动创建为数组
|
|
||||||
$setOnInsert: { createdAt: now },
|
|
||||||
$set,
|
|
||||||
$push: {
|
|
||||||
events: {
|
|
||||||
event: "AUTO_RECORD_CALLBACK",
|
|
||||||
at: now,
|
|
||||||
eventCode: normalizedEventCode,
|
|
||||||
status,
|
|
||||||
payload,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ upsert: true }
|
|
||||||
);
|
|
||||||
|
|
||||||
logger.info("[MRTC][AUTO_RECORD] callback stored", {
|
|
||||||
bizRequestId,
|
|
||||||
roomId,
|
|
||||||
recordId,
|
|
||||||
eventCode: normalizedEventCode,
|
|
||||||
orderId,
|
|
||||||
status,
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
logger.error("[MRTC][AUTO_RECORD] callback store failed", {
|
|
||||||
message: e && e.message ? e.message : String(e),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
app.get(
|
app.get(
|
||||||
"/callback/data",
|
"/callback/data",
|
||||||
asyncHandler(async (req, res) => {
|
asyncHandler(async (req, res) => {
|
||||||
|
|||||||
@ -28,11 +28,15 @@ function get(url) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function post(url, data, config) {
|
function post(url, data, config) {
|
||||||
|
const hasPdf = data && data.data && typeof data.data.pdf == 'string' ? data.data.pdf.length > 50 : false;
|
||||||
const info = { url, method: "POST", data, start: dayjs().format('YYYY-MM-DD HH:mm:ss:SSS') };
|
const info = { url, method: "POST", data, start: dayjs().format('YYYY-MM-DD HH:mm:ss:SSS') };
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
const response = await axios.post(url, data, config);
|
const response = await axios.post(url, data, config);
|
||||||
resolve(response.data);
|
resolve(response.data);
|
||||||
|
if (hasPdf) {
|
||||||
|
info.data.data.pdf = 'pdfbase64'
|
||||||
|
}
|
||||||
writeLog(info, response);
|
writeLog(info, response);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
info.errMsg = error?.message || error;
|
info.errMsg = error?.message || error;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user