数据定价更新
Showing
2 changed files
with
304 additions
and
101 deletions
| ... | @@ -52,13 +52,11 @@ const dictionaryData: any = ref([]); | ... | @@ -52,13 +52,11 @@ const dictionaryData: any = ref([]); |
| 52 | const diseaseData: any = ref([]); | 52 | const diseaseData: any = ref([]); |
| 53 | const qualityScoreData: any = ref({}); | 53 | const qualityScoreData: any = ref({}); |
| 54 | const disScore: any = ref([]); | 54 | const disScore: any = ref([]); |
| 55 | const buildInData: any = ref([]); | 55 | const exportData: any = ref([]); |
| 56 | const dataUsage = ref({ | 56 | const dataUsage = ref({ |
| 57 | field: '', | 57 | field: '', |
| 58 | dictValue: '' | 58 | dictValue: '' |
| 59 | }); | 59 | }); |
| 60 | const currModelGuid = ref(''); | ||
| 61 | |||
| 62 | // 基础设置 | 60 | // 基础设置 |
| 63 | const baseConfigFormRef = ref(); | 61 | const baseConfigFormRef = ref(); |
| 64 | const baseConfigFormItems: any = ref([ | 62 | const baseConfigFormItems: any = ref([ |
| ... | @@ -267,7 +265,6 @@ const getDetail = () => { | ... | @@ -267,7 +265,6 @@ const getDetail = () => { |
| 267 | flowDetail.value = data; | 265 | flowDetail.value = data; |
| 268 | dataTransactionPrice.value = flowDetail.value.dataTransactionPrice; | 266 | dataTransactionPrice.value = flowDetail.value.dataTransactionPrice; |
| 269 | dataUsage.value.dictValue = data.dataUsage || ''; | 267 | dataUsage.value.dictValue = data.dataUsage || ''; |
| 270 | currModelGuid.value = flowDetail.value.modelGuid; | ||
| 271 | const mItem = typeMap.value.modelGuid.find(m => m.guid == flowDetail.value.modelGuid); | 268 | const mItem = typeMap.value.modelGuid.find(m => m.guid == flowDetail.value.modelGuid); |
| 272 | if (!mItem) { | 269 | if (!mItem) { |
| 273 | const mtem = { guid: flowDetail.value.modelGuid, modelName: flowDetail.value.modelName }; | 270 | const mtem = { guid: flowDetail.value.modelGuid, modelName: flowDetail.value.modelName }; |
| ... | @@ -299,7 +296,7 @@ const getDataTypeList = () => { | ... | @@ -299,7 +296,7 @@ const getDataTypeList = () => { |
| 299 | // 设置数据字典选项 | 296 | // 设置数据字典选项 |
| 300 | const setDictFormItems = (dictList) => { | 297 | const setDictFormItems = (dictList) => { |
| 301 | dictList.map(d => { | 298 | dictList.map(d => { |
| 302 | const dictName = d.targetName; | 299 | const dictName = d.dictionaryName; |
| 303 | const dictField = `dict_${d.guid}`; | 300 | const dictField = `dict_${d.guid}`; |
| 304 | baseConfigFormItems.value.push({ | 301 | baseConfigFormItems.value.push({ |
| 305 | label: dictName, | 302 | label: dictName, |
| ... | @@ -312,11 +309,11 @@ const setDictFormItems = (dictList) => { | ... | @@ -312,11 +309,11 @@ const setDictFormItems = (dictList) => { |
| 312 | filterable: true, | 309 | filterable: true, |
| 313 | required: true, | 310 | required: true, |
| 314 | }); | 311 | }); |
| 315 | baseConfigFormRules.value[dictField] = [{ required: true, trigger: 'change', message: `请选择${dictName}` }]; | 312 | baseConfigFormRules.value[dictField] = { required: true, trigger: 'change', message: `请选择${dictName}` }; |
| 316 | d.dictionaryName == '数据用途' && (dataUsage.value.field = dictField); | 313 | dictName == '数据用途' && (dataUsage.value.field = dictField); |
| 317 | (() => { | 314 | (() => { |
| 318 | if (typeMap.value[dictField] == undefined) { | 315 | if (typeMap.value[dictField] == undefined) { |
| 319 | getDataType(d.dictionaryName, dictField) | 316 | getDataType(dictName, dictField) |
| 320 | } else { | 317 | } else { |
| 321 | let item = baseConfigFormItems.value.find(item => item.field == dictField); | 318 | let item = baseConfigFormItems.value.find(item => item.field == dictField); |
| 322 | item && (item.options = typeMap.value[dictField]); | 319 | item && (item.options = typeMap.value[dictField]); |
| ... | @@ -346,7 +343,7 @@ const setDiseaseFormItems = () => { | ... | @@ -346,7 +343,7 @@ const setDiseaseFormItems = () => { |
| 346 | clearable: true, | 343 | clearable: true, |
| 347 | required: true, | 344 | required: true, |
| 348 | }); | 345 | }); |
| 349 | baseConfigFormRules.value.diseaseGuid = [{ required: true, trigger: 'change', message: "请选择所属疾病" }]; | 346 | baseConfigFormRules.value.diseaseGuid = { required: true, trigger: 'change', message: "请选择所属疾病" }; |
| 350 | if (typeMap.value['diseaseGuid'] == undefined) { | 347 | if (typeMap.value['diseaseGuid'] == undefined) { |
| 351 | getDiseaseData(); | 348 | getDiseaseData(); |
| 352 | } else { | 349 | } else { |
| ... | @@ -369,47 +366,16 @@ const setBuildInFormItems = (buildList) => { | ... | @@ -369,47 +366,16 @@ const setBuildInFormItems = (buildList) => { |
| 369 | buildList.map(b => { | 366 | buildList.map(b => { |
| 370 | const buildName = b.targetName; | 367 | const buildName = b.targetName; |
| 371 | const buildField = `build_${b.guid}`; | 368 | const buildField = `build_${b.guid}`; |
| 372 | buildInData.value.push({ | ||
| 373 | guid: b.guid, | ||
| 374 | targetName: buildName, | ||
| 375 | targetValue: b.defaultValue || '', | ||
| 376 | isInputParameter: b.isInputParameter, | ||
| 377 | }) | ||
| 378 | baseConfigFormItems.value.push({ | 369 | baseConfigFormItems.value.push({ |
| 379 | label: buildName, | 370 | label: buildName, |
| 380 | type: 'input', | 371 | type: 'input', |
| 381 | placeholder: '', | 372 | placeholder: '', |
| 382 | field: buildField, | 373 | field: buildField, |
| 383 | default: b.isInputParameter != 'Y' ? changeNum(b.defaultValue, 2) : b.defaultValue != '' && b.defaultValue != null ? parseFloat(b.defaultValue).toFixed(2) : '', | 374 | default: b.defaultValue || '', |
| 384 | inputType: 'moneyNumber', | ||
| 385 | maxlength: 18, | ||
| 386 | clearable: true, | 375 | clearable: true, |
| 387 | disabled: b.isInputParameter != 'Y', | 376 | disabled: b.isInputParameter == 'Y' |
| 388 | required: true | ||
| 389 | }); | 377 | }); |
| 390 | baseConfigFormRules.value[buildField] = [ | 378 | baseConfigFormRules.value[buildField] = { required: true, trigger: 'blur', message: `请填写${buildName}` }; |
| 391 | { required: true, message: `请填写${buildName}`, trigger: 'blur' }, | ||
| 392 | { | ||
| 393 | validator: (rule, value, callback) => { | ||
| 394 | if (value === '') { | ||
| 395 | callback(new Error(`请填写${buildName}`)); | ||
| 396 | return; | ||
| 397 | } | ||
| 398 | const num = parseFloat(value); | ||
| 399 | if (isNaN(num)) { | ||
| 400 | callback(new Error('请输入有效的数字')); | ||
| 401 | return; | ||
| 402 | } | ||
| 403 | |||
| 404 | // 已自动保留两位小数,不需再验证小数位数 | ||
| 405 | if (num < 0 || num > b.defaultValue) { | ||
| 406 | callback(new Error(`输入值必须在0到${b.defaultValue}之间`)); | ||
| 407 | } else { | ||
| 408 | callback(); | ||
| 409 | } | ||
| 410 | }, trigger: "blur", | ||
| 411 | }, | ||
| 412 | ] | ||
| 413 | }) | 379 | }) |
| 414 | }; | 380 | }; |
| 415 | 381 | ||
| ... | @@ -452,7 +418,7 @@ const setFormItemData = async () => { | ... | @@ -452,7 +418,7 @@ const setFormItemData = async () => { |
| 452 | // 添加数据字典 | 418 | // 添加数据字典 |
| 453 | dictionaryList.length > 0 && await setDictFormItems(dictionaryList); | 419 | dictionaryList.length > 0 && await setDictFormItems(dictionaryList); |
| 454 | // 添加内置指标 | 420 | // 添加内置指标 |
| 455 | buildInList.length > 0 && await setBuildInFormItems(buildInList); | 421 | // buildInList.length > 0 && await setBuildInFormItems(buildInList); |
| 456 | 422 | ||
| 457 | setTimeout(() => { | 423 | setTimeout(() => { |
| 458 | baseConfigFormRef.value.ruleFormRef?.clearValidate(); | 424 | baseConfigFormRef.value.ruleFormRef?.clearValidate(); |
| ... | @@ -643,7 +609,6 @@ const getResourceInfo = (sGuid) => { | ... | @@ -643,7 +609,6 @@ const getResourceInfo = (sGuid) => { |
| 643 | } | 609 | } |
| 644 | } | 610 | } |
| 645 | 611 | ||
| 646 | // 需求表字段匹配 | ||
| 647 | const matchTableFields = (rData, tData) => { | 612 | const matchTableFields = (rData, tData) => { |
| 648 | rData.dataFields.map(t => { | 613 | rData.dataFields.map(t => { |
| 649 | const match = tData.find(d => d.chName == t.fieldName); | 614 | const match = tData.find(d => d.chName == t.fieldName); |
| ... | @@ -658,7 +623,9 @@ const matchTableFields = (rData, tData) => { | ... | @@ -658,7 +623,9 @@ const matchTableFields = (rData, tData) => { |
| 658 | }, 0); | 623 | }, 0); |
| 659 | } | 624 | } |
| 660 | 625 | ||
| 661 | const setRowData = (rowData, dGuid, detailDataTable) => { | 626 | |
| 627 | const setTableRowData = (dGuid, rIndex) => { | ||
| 628 | let rowData = tableData.value[rIndex]; | ||
| 662 | if (guid && dGuid == rowData.dataTableGuid) { | 629 | if (guid && dGuid == rowData.dataTableGuid) { |
| 663 | const pricingDemandField = detailDataTable?.pricingDemandFieldRQVOS || []; | 630 | const pricingDemandField = detailDataTable?.pricingDemandFieldRQVOS || []; |
| 664 | rowData.dataFields.map(f => { | 631 | rowData.dataFields.map(f => { |
| ... | @@ -687,7 +654,86 @@ const setTableRowData = (dGuid, rIndex, setRow = true) => { | ... | @@ -687,7 +654,86 @@ const setTableRowData = (dGuid, rIndex, setRow = true) => { |
| 687 | tableLoading.value = false; | 654 | tableLoading.value = false; |
| 688 | if (res.code == proxy.$passCode) { | 655 | if (res.code == proxy.$passCode) { |
| 689 | const data = res.data || {}; | 656 | const data = res.data || {}; |
| 690 | const damTableField = data.damCatalogTableField || []; | 657 | // const damTableField = data.damCatalogTableField || []; |
| 658 | const damTableField = [ | ||
| 659 | { | ||
| 660 | "guid": "dec5a8a8b4bc4ba0b879105f89c1b245", | ||
| 661 | "tenantGuid": "f150638598f74d1bb2d9c542aaf2296c", | ||
| 662 | "relationMenuGuid": "4c2042543d3c413c851f483c3d5e854a", | ||
| 663 | "enName": "patient_id", | ||
| 664 | "chName": "编号", | ||
| 665 | "isRequired": "Y", | ||
| 666 | "orderNum": 1, | ||
| 667 | "bizState": "Y", | ||
| 668 | "createTime": "2025-07-01 13:09:46" | ||
| 669 | }, | ||
| 670 | { | ||
| 671 | "guid": "28c1d258fca448e6b22f59c0c6e566e6", | ||
| 672 | "tenantGuid": "f150638598f74d1bb2d9c542aaf2296c", | ||
| 673 | "relationMenuGuid": "4c2042543d3c413c851f483c3d5e854a", | ||
| 674 | "enName": "patient_xm", | ||
| 675 | "chName": "姓名缩写", | ||
| 676 | "isRequired": "Y", | ||
| 677 | "orderNum": 4, | ||
| 678 | "bizState": "Y", | ||
| 679 | "createTime": "2025-07-01 13:09:46" | ||
| 680 | }, | ||
| 681 | { | ||
| 682 | "guid": "08b27a077049434bbdee0c6ab51c8b1a", | ||
| 683 | "tenantGuid": "f150638598f74d1bb2d9c542aaf2296c", | ||
| 684 | "relationMenuGuid": "4c2042543d3c413c851f483c3d5e854a", | ||
| 685 | "enName": "patient_sj", | ||
| 686 | "chName": "时间", | ||
| 687 | "isRequired": "Y", | ||
| 688 | "orderNum": 5, | ||
| 689 | "bizState": "Y", | ||
| 690 | "createTime": "2025-07-01 13:09:46" | ||
| 691 | }, | ||
| 692 | { | ||
| 693 | "guid": "a0d536a24fb64102acdd3f142f5eda77", | ||
| 694 | "tenantGuid": "f150638598f74d1bb2d9c542aaf2296c", | ||
| 695 | "relationMenuGuid": "4c2042543d3c413c851f483c3d5e854a", | ||
| 696 | "enName": "patient_sf", | ||
| 697 | "chName": "随访次数", | ||
| 698 | "isRequired": "Y", | ||
| 699 | "orderNum": 6, | ||
| 700 | "bizState": "Y", | ||
| 701 | "createTime": "2025-07-01 13:09:46" | ||
| 702 | }, | ||
| 703 | { | ||
| 704 | "guid": "5402d6915458404aa59115fbff40c965", | ||
| 705 | "tenantGuid": "f150638598f74d1bb2d9c542aaf2296c", | ||
| 706 | "relationMenuGuid": "4c2042543d3c413c851f483c3d5e854a", | ||
| 707 | "enName": "patient_sg", | ||
| 708 | "chName": "身高", | ||
| 709 | "isRequired": "Y", | ||
| 710 | "orderNum": 7, | ||
| 711 | "bizState": "Y", | ||
| 712 | "createTime": "2025-07-01 13:09:46" | ||
| 713 | }, | ||
| 714 | { | ||
| 715 | "guid": "752ee34845044ad2bbe30f5b738a1ef0", | ||
| 716 | "tenantGuid": "f150638598f74d1bb2d9c542aaf2296c", | ||
| 717 | "relationMenuGuid": "4c2042543d3c413c851f483c3d5e854a", | ||
| 718 | "enName": "patient_igf", | ||
| 719 | "chName": "IGF-1", | ||
| 720 | "isRequired": "Y", | ||
| 721 | "orderNum": 8, | ||
| 722 | "bizState": "Y", | ||
| 723 | "createTime": "2025-07-01 13:09:46" | ||
| 724 | }, | ||
| 725 | { | ||
| 726 | "guid": "8dce74c208184f958f0ac8587fe66839", | ||
| 727 | "tenantGuid": "f150638598f74d1bb2d9c542aaf2296c", | ||
| 728 | "relationMenuGuid": "4c2042543d3c413c851f483c3d5e854a", | ||
| 729 | "enName": "patient_tz", | ||
| 730 | "chName": "体重", | ||
| 731 | "isRequired": "Y", | ||
| 732 | "orderNum": 8, | ||
| 733 | "bizState": "Y", | ||
| 734 | "createTime": "2025-07-01 13:09:46" | ||
| 735 | } | ||
| 736 | ]; | ||
| 691 | const damFieldOptions = damTableField.map(d => { | 737 | const damFieldOptions = damTableField.map(d => { |
| 692 | return { | 738 | return { |
| 693 | ...d, | 739 | ...d, |
| ... | @@ -699,9 +745,8 @@ const setTableRowData = (dGuid, rIndex, setRow = true) => { | ... | @@ -699,9 +745,8 @@ const setTableRowData = (dGuid, rIndex, setRow = true) => { |
| 699 | t.damFieldTable = JSON.parse(JSON.stringify(damFieldOptions)); | 745 | t.damFieldTable = JSON.parse(JSON.stringify(damFieldOptions)); |
| 700 | }) | 746 | }) |
| 701 | // 匹配 | 747 | // 匹配 |
| 702 | if (!guid || (guid && (dGuid != currDataTableGuid || currModelGuid.value != flowDetail.value.modelGuid))) { | 748 | !guid && matchTableFields(rowData, damTableField); |
| 703 | matchTableFields(rowData, damTableField); | 749 | // console.log('rowData', rowData) |
| 704 | } | ||
| 705 | } else { | 750 | } else { |
| 706 | proxy.$ElMessage.error(res.msg); | 751 | proxy.$ElMessage.error(res.msg); |
| 707 | } | 752 | } |
| ... | @@ -818,7 +863,34 @@ const toPath = () => { | ... | @@ -818,7 +863,34 @@ const toPath = () => { |
| 818 | }) | 863 | }) |
| 819 | } | 864 | } |
| 820 | 865 | ||
| 821 | // 获取疾病得分 | 866 | // 获取维度公式计算结果 |
| 867 | const getSignatory = (row) => { | ||
| 868 | let formulaVal = 0; | ||
| 869 | const pricingTargetData = row.pricingTargetRSVOS || []; | ||
| 870 | if (!row.computationalFormula || row.computationalFormula == 'custom') { | ||
| 871 | let formula = row.customize; | ||
| 872 | // 遍历数组,检查 customize 是否包含对应的 targetName,若包含则替换为 tNum | ||
| 873 | pricingTargetData.forEach((item) => { | ||
| 874 | if (formula.includes(item.targetName)) { | ||
| 875 | formula = formula.replace(new RegExp(item.targetName, 'g'), item.tNum); | ||
| 876 | } | ||
| 877 | }); | ||
| 878 | // 使用 eval 计算公式结果(注意:eval 存在安全风险,仅适用于受控环境) | ||
| 879 | try { | ||
| 880 | formulaVal = eval(formula); | ||
| 881 | } catch (error) { | ||
| 882 | console.error('公式计算错误:', error); | ||
| 883 | } | ||
| 884 | } else { | ||
| 885 | const formula = pricingTargetData.map(item => item.tNum); | ||
| 886 | if (row.computationalFormula == '3') { | ||
| 887 | formulaVal = formula.reduce((accumulator, currentValue) => parseFloat(accumulator) * parseFloat(currentValue), 1); // 初始值为1 | ||
| 888 | } else { | ||
| 889 | formulaVal = formula.reduce((accumulator, currentValue) => parseFloat(accumulator) + parseFloat(currentValue), 0); // 初始值为0 | ||
| 890 | } | ||
| 891 | } | ||
| 892 | return (Math.round(formulaVal * 100) / 100).toFixed(2); | ||
| 893 | }; | ||
| 822 | const getTargetNum = (params) => { | 894 | const getTargetNum = (params) => { |
| 823 | // loading.value = true; | 895 | // loading.value = true; |
| 824 | getPriceResult(params).then((res: any) => { | 896 | getPriceResult(params).then((res: any) => { |
| ... | @@ -834,6 +906,151 @@ const getTargetNum = (params) => { | ... | @@ -834,6 +906,151 @@ const getTargetNum = (params) => { |
| 834 | }); | 906 | }); |
| 835 | } | 907 | } |
| 836 | 908 | ||
| 909 | // 生成报告内容 | ||
| 910 | const reporting = (formInfo) => { | ||
| 911 | let resultInfo: any = []; | ||
| 912 | const signatoryData = JSON.parse(JSON.stringify(modelData.value.pricingDimensionalityRSVOS || '[]')); | ||
| 913 | signatoryData.map((sign, s) => { | ||
| 914 | resultInfo.push({ | ||
| 915 | dimensionalityName: sign.dimensionalityName, | ||
| 916 | computationalFormula: sign.computationalFormula, | ||
| 917 | customize: sign.customize, | ||
| 918 | pricingTargetRSVOS: [] | ||
| 919 | }); | ||
| 920 | const targets = sign.pricingTargetRSVOS || []; | ||
| 921 | const signTargets = targets.map(t => { | ||
| 922 | let tNum: any = 0, tCustomize = ''; | ||
| 923 | if (t.targetType == '3') { // 指标类型-数据字典 | ||
| 924 | const tName = dictionaryData.value.find(d => d.guid == t.guid) ? `dict_${t.guid}` : ''; | ||
| 925 | if (tName) { | ||
| 926 | const pVal = typeMap.value[tName].find(t => t.value == formInfo[tName]); | ||
| 927 | const dictionary = t.dictionaryJson.find(d => d.name == pVal.label); | ||
| 928 | if (sign.computationalFormula == '1') {// 加权平均 | ||
| 929 | tNum = parseFloat(t.weight) / 100 * parseFloat(dictionary?.value || t.defaultValue || 0); | ||
| 930 | tCustomize = `权重${parseFloat(t.weight) / 100} * 因子/默认值${parseFloat(dictionary?.value || t.defaultValue || 0)}`; | ||
| 931 | } else { // 其他 | ||
| 932 | tNum = parseFloat(dictionary?.value || t.defaultValue || 0); | ||
| 933 | tCustomize = `默认值${parseFloat(dictionary?.value || t.defaultValue || 0)}`; | ||
| 934 | } | ||
| 935 | t.dictionaryName == '数据用途' && (dataUsage.value.dictValue = pVal.value || ''); | ||
| 936 | } | ||
| 937 | } else if (t.targetType == '2') {// 指标类型-系统功能 | ||
| 938 | if (t.functionName == '1') { // 功能名称-质量评价模型 | ||
| 939 | const score = parseFloat(qualityScoreData.value.qualityScore || 0); | ||
| 940 | tNum = parseFloat(t.weight || 1) / 100 * score / 100; | ||
| 941 | tCustomize = `权重${parseFloat(t.weight || 1) / 100} * 模型评分${score}/100`; | ||
| 942 | } else if (t.functionName == '2') { // 功能名称-疾病管理 | ||
| 943 | if (sign.computationalFormula == '1') {// 加权平均 | ||
| 944 | const score = parseFloat(disScore.value.find(d => d.guid == t.guid)?.factor || 0); | ||
| 945 | tNum = parseFloat(t.weight) / 100 * score; | ||
| 946 | tCustomize = `权重${parseFloat(t.weight) / 100} * 疾病得分${score}`; | ||
| 947 | } else { //其他 | ||
| 948 | tNum = parseFloat(disScore.value.find(d => d.guid == t.guid)?.factor || 0); | ||
| 949 | tCustomize = `疾病得分${tNum}`; | ||
| 950 | } | ||
| 951 | } else if (t.functionName == '3') {// 功能名称-需求表管理 | ||
| 952 | const tData = tableData.value.find(f => f.demandTableGuid == t.demandTableGuid || f.guid == t.demandTableGuid); | ||
| 953 | if (tData) { | ||
| 954 | if (sign.computationalFormula == '1') {// 加权平均 | ||
| 955 | tNum = parseFloat(t.weight) / 100 * (parseFloat(tData.dataFieldsNum) / tData.dataFields.length || parseFloat(t.defaultValue || 0)); | ||
| 956 | tCustomize = `权重${parseFloat(t.weight) / 100} * 匹配率/默认值${parseFloat(tData.dataFieldsNum) / tData.dataFields.length || parseFloat(t.defaultValue || 0)}`; | ||
| 957 | } else { //其他 | ||
| 958 | tNum = parseFloat(tData.dataFieldsNum) / tData.dataFields.length || parseFloat(t.defaultValue || 0); | ||
| 959 | tCustomize = `匹配率/默认值${parseFloat(tData.dataFieldsNum) / tData.dataFields.length || parseFloat(t.defaultValue || 0)}`; | ||
| 960 | } | ||
| 961 | } | ||
| 962 | } | ||
| 963 | } else { // 指标类型-系统内置 | ||
| 964 | if (sign.computationalFormula == '1') {// 加权平均 | ||
| 965 | tNum = parseFloat(t.weight) / 100 * parseFloat(t.defaultValue || 0); | ||
| 966 | tCustomize = `权重${parseFloat(t.weight) / 100} * 默认值${parseFloat(t.defaultValue || 0)}`; | ||
| 967 | } else { //其他 | ||
| 968 | tNum = parseFloat(t.defaultValue || 0); | ||
| 969 | tCustomize = `默认值${parseFloat(t.defaultValue || 0)}`; | ||
| 970 | } | ||
| 971 | } | ||
| 972 | t.tNum = (Math.round(parseFloat(tNum) * 100) / 100).toFixed(2); | ||
| 973 | resultInfo[s].pricingTargetRSVOS.push({ | ||
| 974 | targetName: t.targetName, | ||
| 975 | targetType: t.targetType, | ||
| 976 | functionName: t.functionName, | ||
| 977 | customize: tCustomize, | ||
| 978 | tNum: t.tNum, | ||
| 979 | }) | ||
| 980 | return t; | ||
| 981 | }) | ||
| 982 | sign.pricingTargetRSVOS = signTargets; | ||
| 983 | sign.sNum = getSignatory(sign); | ||
| 984 | resultInfo[s].sNum = sign.sNum; | ||
| 985 | }) | ||
| 986 | // exportData.value = resultInfo; | ||
| 987 | return { signatoryData, resultInfo }; | ||
| 988 | } | ||
| 989 | |||
| 990 | // 计算价格 | ||
| 991 | const calculatePrice = (pData) => { | ||
| 992 | let modelFormula = modelData.value.modelFormula; | ||
| 993 | // 1. 移除所有干扰的引号(确保是数学表达式) | ||
| 994 | modelFormula = modelFormula.replace(/["']/g, "").trim(); | ||
| 995 | |||
| 996 | // 2. 定义允许的数学运算符和函数 | ||
| 997 | const allowedOperators = /[+\-*/%^() .\d]/; | ||
| 998 | const mathFunctions = ['sin', 'cos', 'tan', 'log', 'sqrt', 'abs', 'pow']; | ||
| 999 | |||
| 1000 | // 3. 提取变量名 | ||
| 1001 | const variableRegex = /[\u4e00-\u9fa5a-zA-Z_][\u4e00-\u9fa5a-zA-Z0-9_]*/g; | ||
| 1002 | const variableNames = [...new Set(modelFormula.match(variableRegex) || [])]; | ||
| 1003 | |||
| 1004 | // 4. 构建变量映射 | ||
| 1005 | const variables = {}; | ||
| 1006 | variableNames.forEach(name => { | ||
| 1007 | const dim = pData.find(d => d.dimensionalityName === name); | ||
| 1008 | variables[name] = dim ? parseFloat(dim.sNum) || 0 : 0; | ||
| 1009 | }); | ||
| 1010 | |||
| 1011 | // 5. 替换变量为数值(考虑边界情况) | ||
| 1012 | let expression = modelFormula; | ||
| 1013 | Object.keys(variables).forEach(name => { | ||
| 1014 | expression = expression.replace(new RegExp(name, 'g'), variables[name]); | ||
| 1015 | }); | ||
| 1016 | |||
| 1017 | // 6. 表达式规范化(不丢失括号) | ||
| 1018 | expression = expression | ||
| 1019 | .replace(/\s+/g, '') // 去空格 | ||
| 1020 | .replace(/\^/g, '**') // 幂运算转换 | ||
| 1021 | .replace(/"|'/g, '') // 去引号(不破坏括号) | ||
| 1022 | .replace(/(\d)\(/g, '$1*(') // 处理隐式乘法 | ||
| 1023 | .replace(/\)\(/g, ')*('); // 括号间乘法 | ||
| 1024 | |||
| 1025 | // 7. 验证括号配对 | ||
| 1026 | const balance = expression.split('').reduce((acc, char) => { | ||
| 1027 | if (char === '(') acc++; | ||
| 1028 | if (char === ')') acc--; | ||
| 1029 | return acc; | ||
| 1030 | }, 0); | ||
| 1031 | |||
| 1032 | if (balance !== 0) { | ||
| 1033 | console.error('括号不匹配'); | ||
| 1034 | return NaN; | ||
| 1035 | } | ||
| 1036 | |||
| 1037 | // 8. 安全计算 | ||
| 1038 | try { | ||
| 1039 | const result = new Function('return ' + expression)(); | ||
| 1040 | const roundedResult = Math.round(parseFloat(result) * 100) / 100; | ||
| 1041 | |||
| 1042 | dataTransactionPrice.value = roundedResult.toFixed(2); | ||
| 1043 | return roundedResult; | ||
| 1044 | } catch (error) { | ||
| 1045 | console.error('计算错误:', { | ||
| 1046 | error, | ||
| 1047 | original: modelFormula, | ||
| 1048 | processed: expression | ||
| 1049 | }); | ||
| 1050 | return NaN; | ||
| 1051 | } | ||
| 1052 | }; | ||
| 1053 | |||
| 837 | // 获取定价计算配置参数 | 1054 | // 获取定价计算配置参数 |
| 838 | const getCalculateParams = (baseConfigFormObj, baseConfigFormInfo) => { | 1055 | const getCalculateParams = (baseConfigFormObj, baseConfigFormInfo) => { |
| 839 | const modelName = typeMap.value.modelGuid.find(d => d.guid == baseConfigFormInfo.modelGuid)?.modelName || ''; | 1056 | const modelName = typeMap.value.modelGuid.find(d => d.guid == baseConfigFormInfo.modelGuid)?.modelName || ''; | ... | ... |
| ... | @@ -222,7 +222,7 @@ const signatoryFormItems: any = ref([ | ... | @@ -222,7 +222,7 @@ const signatoryFormItems: any = ref([ |
| 222 | placeholder: '请输入', | 222 | placeholder: '请输入', |
| 223 | field: 'weight', | 223 | field: 'weight', |
| 224 | default: '', | 224 | default: '', |
| 225 | inputType: 'factorNumber', | 225 | inputType: 'scoreNumber', |
| 226 | maxlength: 10, | 226 | maxlength: 10, |
| 227 | clearable: true, | 227 | clearable: true, |
| 228 | }, | 228 | }, |
| ... | @@ -314,7 +314,7 @@ const targetFormItems: any = ref([ | ... | @@ -314,7 +314,7 @@ const targetFormItems: any = ref([ |
| 314 | placeholder: '请输入', | 314 | placeholder: '请输入', |
| 315 | field: 'weight', | 315 | field: 'weight', |
| 316 | default: '', | 316 | default: '', |
| 317 | inputType: 'factorNumber', | 317 | inputType: 'scoreNumber', |
| 318 | maxlength: 10, | 318 | maxlength: 10, |
| 319 | clearable: true, | 319 | clearable: true, |
| 320 | required: true, | 320 | required: true, |
| ... | @@ -354,7 +354,7 @@ const targetFormItems: any = ref([ | ... | @@ -354,7 +354,7 @@ const targetFormItems: any = ref([ |
| 354 | placeholder: '请输入', | 354 | placeholder: '请输入', |
| 355 | field: 'defaultValue', | 355 | field: 'defaultValue', |
| 356 | default: '', | 356 | default: '', |
| 357 | inputType: 'factorNumber', | 357 | inputType: 'moneyNumber', |
| 358 | maxlength: 18, | 358 | maxlength: 18, |
| 359 | clearable: true, | 359 | clearable: true, |
| 360 | required: false | 360 | required: false |
| ... | @@ -548,35 +548,44 @@ const drawerInfo: any = ref({ | ... | @@ -548,35 +548,44 @@ const drawerInfo: any = ref({ |
| 548 | }); | 548 | }); |
| 549 | 549 | ||
| 550 | const setTableField = (data) => { | 550 | const setTableField = (data) => { |
| 551 | tableData.value = []; | 551 | // tableData.value = []; |
| 552 | const dictionaryName = typeMap.value['dictionaryType'].find(item => item.value == dictionaryType.value)?.label || ''; | 552 | // const dictionaryName = typeMap.value['dictionaryType'].find(item => item.value == dictionaryType.value)?.label || ''; |
| 553 | const dictionaryJson = dictionaryName && dictionaryName == currTableData.value.dictionaryName ? (currTableData.value.dictionaryJson || []) : []; | 553 | // const dictionaryJson = dictionaryName && dictionaryName == currTableData.value.dictionaryName ? (currTableData.value.dictionaryJson || []) : []; |
| 554 | // if (dictionaryType.value == '1') { | ||
| 555 | // const tData = JSON.parse(JSON.stringify(mergeTableData)); | ||
| 556 | // if (dictionaryJson.length) { | 554 | // if (dictionaryJson.length) { |
| 557 | // tData.map((item, i) => { | 555 | // dictionaryJson.map(item => { |
| 558 | // item.factor = dictionaryJson[i]?.value || ''; | 556 | // tableData.value.push({ |
| 557 | // label: item.name, | ||
| 558 | // factor: item.value || '', | ||
| 559 | // }) | ||
| 559 | // }) | 560 | // }) |
| 560 | // } | ||
| 561 | // tableData.value = tData; | ||
| 562 | // getMergeRow(); | ||
| 563 | // } else { | 561 | // } else { |
| 562 | // data.map((item: any) => { | ||
| 563 | // tableData.value.push({ | ||
| 564 | // label: item.label, | ||
| 565 | // factor: '', | ||
| 566 | // }) | ||
| 567 | // }) | ||
| 568 | // } | ||
| 569 | |||
| 570 | tableData.value = []; | ||
| 571 | const dictionaryName = typeMap.value['dictionaryType'].find(item => item.value == dictionaryType.value)?.label || ''; | ||
| 572 | const dictionaryJson = dictionaryName && dictionaryName == currTableData.value.dictionaryName ? (currTableData.value.dictionaryJson || []) : []; | ||
| 573 | |||
| 574 | // 创建已有数据的映射表,以 label 为键 | ||
| 575 | const existingDataMap = {}; | ||
| 564 | if (dictionaryJson.length) { | 576 | if (dictionaryJson.length) { |
| 565 | dictionaryJson.map(item => { | 577 | dictionaryJson.forEach(item => { |
| 566 | tableData.value.push({ | 578 | existingDataMap[item.name] = item.value || ''; |
| 567 | label: item.name, | 579 | }); |
| 568 | factor: item.value || '', | 580 | } |
| 569 | }) | 581 | |
| 570 | }) | 582 | // 遍历最新数据,如果有匹配的已有数据则使用其值 |
| 571 | } else { | 583 | data.forEach((item: any) => { |
| 572 | data.map((item: any) => { | ||
| 573 | tableData.value.push({ | 584 | tableData.value.push({ |
| 574 | label: item.label, | 585 | label: item.label, |
| 575 | factor: '', | 586 | factor: existingDataMap[item.label] || '', // 使用已有值或空字符串 |
| 576 | }) | 587 | }); |
| 577 | }) | 588 | }); |
| 578 | } | ||
| 579 | // } | ||
| 580 | } | 589 | } |
| 581 | 590 | ||
| 582 | const getDictionaryRuleData = () => { | 591 | const getDictionaryRuleData = () => { |
| ... | @@ -833,6 +842,7 @@ const selectChange = async (val, row, info) => { | ... | @@ -833,6 +842,7 @@ const selectChange = async (val, row, info) => { |
| 833 | await setFormItems(tInfo, 'target'); | 842 | await setFormItems(tInfo, 'target'); |
| 834 | if (row.field == 'targetType') { | 843 | if (row.field == 'targetType') { |
| 835 | targetFormItems.value[3].default = val == '1' ? 'N' : 'Y'; | 844 | targetFormItems.value[3].default = val == '1' ? 'N' : 'Y'; |
| 845 | targetFormItems.value[4].default = val == '1' ? 'N' : 'Y'; | ||
| 836 | } | 846 | } |
| 837 | } | 847 | } |
| 838 | } | 848 | } |
| ... | @@ -1266,30 +1276,6 @@ onMounted(() => { | ... | @@ -1266,30 +1276,6 @@ onMounted(() => { |
| 1266 | <template v-if="showFactorTable"> | 1276 | <template v-if="showFactorTable"> |
| 1267 | <span class="required_mark" style="line-height: 21px;">字典值对应因子</span> | 1277 | <span class="required_mark" style="line-height: 21px;">字典值对应因子</span> |
| 1268 | <div class="table_panel"> | 1278 | <div class="table_panel"> |
| 1269 | <!-- <el-table border :data="tableData" :span-method="tableSpanMethod" tooltip-effect="light" style="height: 100%;" | ||
| 1270 | v-if="dictionaryType == '1'"> | ||
| 1271 | <el-table-column label="医院等级"> | ||
| 1272 | <el-table-column prop="level" label="级别" width="100" /> | ||
| 1273 | <el-table-column prop="grade" label="等次" width="100" /> | ||
| 1274 | </el-table-column> | ||
| 1275 | <el-table-column prop="factor" label="因子" class-name="edit-col"> | ||
| 1276 | <template #default="scope"> | ||
| 1277 | <el-input v-model="scope.row.factor" placeholder="请输入" | ||
| 1278 | @change="(val) => inputChange(val, scope, 'factor')" | ||
| 1279 | @input="(val) => inputEventChange(val, scope, 'factor')" /> | ||
| 1280 | </template> | ||
| 1281 | </el-table-column> | ||
| 1282 | </el-table> | ||
| 1283 | <el-table border :data="tableData" tooltip-effect="light" style="height: 100%;" v-else> | ||
| 1284 | <el-table-column label="字典名称" prop="label" width="140" /> | ||
| 1285 | <el-table-column prop="factor" label="因子" class-name="edit-col"> | ||
| 1286 | <template #default="scope"> | ||
| 1287 | <el-input v-model="scope.row.factor" placeholder="请输入" | ||
| 1288 | @change="(val) => inputChange(val, scope, 'factor')" | ||
| 1289 | @input="(val) => inputEventChange(val, scope, 'factor')" /> | ||
| 1290 | </template> | ||
| 1291 | </el-table-column> | ||
| 1292 | </el-table> --> | ||
| 1293 | <el-table border :data="tableData" tooltip-effect="light" style="height: 100%;"> | 1279 | <el-table border :data="tableData" tooltip-effect="light" style="height: 100%;"> |
| 1294 | <el-table-column label="字典名称" prop="label" width="140" /> | 1280 | <el-table-column label="字典名称" prop="label" width="140" /> |
| 1295 | <el-table-column prop="factor" label="因子" class-name="edit-col"> | 1281 | <el-table-column prop="factor" label="因子" class-name="edit-col"> | ... | ... |
-
Please register or sign in to post a comment