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;