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

336 lines
9.8 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.

const dayjs = require("dayjs");
const Sm4Util = require("../../utils/sm4-util");
/**
* 需要加密的字段列表
*/
const ENCRYPTED_FIELDS = ["name", "mobile", "idCard"];
/**
* 加密诊断记录敏感字段
* @param {Object} data - 诊断记录数据
* @returns {Object} 加密后的数据
*/
function encryptDiagnosticRecordFields(data) {
if (!data || typeof data !== "object") {
return data;
}
const encryptedData = { ...data };
ENCRYPTED_FIELDS.forEach((field) => {
if (
encryptedData[field] &&
typeof encryptedData[field] === "string" &&
encryptedData[field].trim() !== ""
) {
try {
encryptedData[field] = Sm4Util.encryptDataForSm3(encryptedData[field]);
} catch (error) {
console.error(`加密字段 ${field} 失败:`, error.message);
}
}
});
return encryptedData;
}
/**
* 解密诊断记录敏感字段
* @param {Object} data - 诊断记录数据
* @returns {Object} 解密后的数据
*/
function decryptDiagnosticRecordFields(data) {
if (!data || typeof data !== "object") {
return data;
}
const decryptedData = { ...data };
ENCRYPTED_FIELDS.forEach((field) => {
if (
decryptedData[field] &&
typeof decryptedData[field] === "string" &&
decryptedData[field].trim() !== ""
) {
try {
decryptedData[field] = Sm4Util.decryptDataForSm3(decryptedData[field]) || decryptedData[field];
} catch (error) {
console.error(`解密字段 ${field} 失败:`, error.message);
// 解密失败时保留原值
}
}
});
return decryptedData;
}
/**
* 批量解密诊断记录列表的敏感字段
* @param {Array} list - 诊断记录列表
* @returns {Array} 解密后的诊断记录列表
*/
function decryptDiagnosticRecordList(list) {
if (!Array.isArray(list)) {
return list;
}
return list.map((item) => decryptDiagnosticRecordFields(item));
}
exports.formatUploadRxData = function (data) {
return {
patientid: data.patientId,
orderno: data.medOrgOrderNo,
doctorcode: data.doctorCode,
unitcode: data.unitCode,
hospid: "108",
phar_code: data.pharmacistNo,
phar_name: data.pharmacist,
phar_chk_time: dayjs(data.auditTime).format("YYYY-MM-DD HH:mm:ss"),
ysjd_time: dayjs(data.prescriptionStartTime).format("YYYY-MM-DD HH:mm:ss"),
prsc_time: dayjs(data.prescriptionEndTime).format("YYYY-MM-DD HH:mm:ss"),
details: data.drugs.map((i) => {
const item = {
drug_id: i.insurance_code,
drug_name: i.drugName,
drug_dosform: "",
drug_spec: i.specification || "",
drug_pric: "0",
drug_cnt: i.quantity,
drug_sumamt: "0",
medc_way_codg: i.usageCode,
medc_way_dscr: i.usageName,
medc_days: i.days,
remark: "",
limit_flag: "0",
used_frqu_codg: i.frequencyCode,
used_frqu_name: i.frequencyName,
sin_doscnt: i.dosage,
sin_dosunt: i.dosage_unit,
unit: i.unit,
appr_flag: i.forceSelfPay === 'Y' ? '2' : '1'
}
if (item.appr_flag === '2') {
//[his要求]当appr_flag=2时必填如果这个药品维护了限制使用范围的传1否则就传2
item.self_pay_rea = i.limitUsageScope === 'Y' ? '1' : '2'
}
return item
}),
icds: data.diagnosisList.map((i) => ({
icd_code: i.code,
icd_name: i.name,
})),
};
};
exports.formatOnlineMedicinePurchaseData = function (data) {
const details = data.drugs.map(i => {
const item = {
drug_type: "xy",
drug_groupno: i.hisChargeInfo.drugGroupNo,
drug_group: "",
drug_id: i.hisChargeInfo.drugId,
drug_serial: i.hisChargeInfo.drugSerial,
drug_name: i.drugName,
drug_spec: i.specification || "",
drug_pric: i.hisChargeInfo.drugPrice,
drug_cnt: i.quantity,
drug_sumamt: i.hisChargeInfo.drugSumamt, //总金额 总金额=数量*单价
supple_code: i.usageCode,
supple_name: i.usageName,
medc_days: i.days,
drug_times: 1,
drug_comm: "",
drug_ma: "",
remark: "",
limit_flag: "0",
usage: i.frequencyCode,
usage_name: i.frequencyName,
sin_doscnt: i.dosage,
sin_dosunt: i.dosage_unit_code,
unit: i.unit,
appr_flag: i.forceSelfPay === 'Y' ? '2':'1'
}
if (item.appr_flag === '2') {
//[his要求]当appr_flag=2时必填如果这个药品维护了限制使用范围的传1否则就传2
item.self_pay_rea = i.limitUsageScope === 'Y' ? '1' : '2'
}
return item
})
return {
patientid: data.patientId,
registerid: "",
orderno: data.medOrgOrderNo,
doctorcode: data.doctorCode,
unitcode: data.unitCode,
visit_time: dayjs(data.prescriptionStartTime).format("YYYY-MM-DD HH:mm:ss"),
area_code: data.areaCode,
hospid: "108",
details,
icds: data.diagnosisList.map((i, idx) => ({
icd_code: i.code,
icd_name: i.name,
sort: idx + 1
}))
}
}
exports.formatWinePurchaseData = function (data, order) {
const [wine] = data.wines;
return {
patientid: data.patientId,
registerid: order.medorg_order_no,
orderno: data.medOrgOrderNo,
doctorcode: data.doctorCode,
unitcode: data.unitCode,
visit_time: dayjs(data.prescriptionStartTime).format("YYYY-MM-DD HH:mm:ss"),
operator_id: data.drugStoreNo,
tc_code: wine.hisId,
drug_times: wine.quantity,
delivery: data.pickUpType === 'delivery' ? 1 :0,//是否配送 1配送 0自提 order.pickUpType === 'delivery' ? 1 :0
hospid: "108",
icds: data.diagnosisList.map((i) => ({
icd_code: i.code,
icd_name: i.name,
})),
};
}
/**
* 构建支持明文+密文混合搜索的查询条件
* 用于数据迁移期间,数据库中同时存在明文和密文数据的情况
*
* @param {string} fieldName - 字段名(如 'name', 'mobile', 'idCard'
* @param {string} searchValue - 搜索值(明文)
* @param {boolean} exactMatch - 是否精确匹配默认为false模糊匹配
* @returns {Object} MongoDB查询条件对象
*/
function buildHybridSearchQuery(fieldName, searchValue, exactMatch = false) {
if (
!searchValue ||
typeof searchValue !== "string" ||
searchValue.trim() === ""
) {
return null;
}
const trimmedValue = searchValue.trim();
try {
// 尝试加密搜索值
const encryptedValue = Sm4Util.encryptDataForSm3(trimmedValue);
if (exactMatch) {
// 精确匹配:同时匹配明文和密文
return {
$or: [
{ [fieldName]: trimmedValue }, // 明文精确匹配
{ [fieldName]: encryptedValue }, // 密文精确匹配
],
};
} else {
// 模糊匹配:明文用正则,密文用精确匹配(因为密文无法模糊匹配)
return {
$or: [
{ [fieldName]: new RegExp(trimmedValue, "i") }, // 明文模糊匹配(不区分大小写)
{ [fieldName]: encryptedValue }, // 密文精确匹配
],
};
}
} catch (error) {
// 如果加密失败(如环境变量未配置),只搜索明文
console.warn(`加密搜索值失败,只搜索明文数据: ${error.message}`);
if (exactMatch) {
return { [fieldName]: trimmedValue };
} else {
return { [fieldName]: new RegExp(trimmedValue, "i") };
}
}
}
/**
* 批量构建混合搜索条件
* @param {Object} searchParams - 搜索参数对象,如 { name: '张三', mobile: '138' }
* @param {boolean} exactMatch - 是否精确匹配
* @returns {Array} MongoDB $and 条件数组
*/
function buildMultiFieldHybridSearch(searchParams, exactMatch = false) {
const conditions = [];
Object.keys(searchParams).forEach((fieldName) => {
const searchValue = searchParams[fieldName];
const condition = buildHybridSearchQuery(
fieldName,
searchValue,
exactMatch
);
if (condition) {
conditions.push(condition);
}
});
return conditions;
}
exports.formatReviewData = function (data) {
const details = data.drugs.map(i => {
const item = {
drug_type: "xy",
drug_groupno: i.hisChargeInfo.drugGroupNo,
drug_group: "",
drug_id: i.hisChargeInfo.drugId,
drug_serial: i.hisChargeInfo.drugSerial,
drug_name: i.drugName,
drug_spec: i.specification || "",
drug_pric: i.hisChargeInfo.drugPrice,
drug_cnt: i.quantity,
drug_sumamt: i.hisChargeInfo.drugSumamt, //总金额 总金额=数量*单价
supple_code: i.usageCode,
supple_name: i.usageName,
medc_days: i.days,
drug_times: 1,
drug_comm: "",
drug_ma: "",
remark: "",
limit_flag: "0",
usage: i.frequencyCode,
usage_name: i.frequencyName,
sin_doscnt: i.dosage,
sin_dosunt: i.dosage_unit_code,
unit: i.unit,
appr_flag: i.forceSelfPay === 'Y' ? '2':'1'
}
if (item.appr_flag === '2') {
//[his要求]当appr_flag=2时必填如果这个药品维护了限制使用范围的传1否则就传2
item.self_pay_rea = i.limitUsageScope === 'Y' ? '1' : '2'
}
return item
})
return {
patientid: data.patientId,
registerid: "",
orderno: data.medOrgOrderNo,
doctorcode: data.doctorCode,
unitcode: data.unitCode,
visit_time: dayjs(data.prescriptionStartTime).format("YYYY-MM-DD HH:mm:ss"),
area_code: data.areaCode,
hospid: "108",
details,
icds: data.diagnosisList.map((i, idx) => ({
icd_code: i.code,
icd_name: i.name,
sort: idx + 1
}))
}
}
exports.encryptDiagnosticRecordFields = encryptDiagnosticRecordFields;
exports.decryptDiagnosticRecordFields = decryptDiagnosticRecordFields;
exports.decryptDiagnosticRecordList = decryptDiagnosticRecordList;
exports.buildHybridSearchQuery = buildHybridSearchQuery;
exports.buildMultiFieldHybridSearch = buildMultiFieldHybridSearch;
exports.ENCRYPTED_FIELDS = ENCRYPTED_FIELDS;