336 lines
9.8 KiB
JavaScript
336 lines
9.8 KiB
JavaScript
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;
|