Skip to content
Toggle navigation
Toggle navigation
This project
Loading...
Sign in
csbr-daop
/
fe-data-trusted-space
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Issue Boards
Files
Commits
Network
Compare
Branches
Tags
fc97e0eb
authored
2025-08-14 14:07:27 +0800
by
lxs
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
数据定价更新
1 parent
3a72832b
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
62 additions
and
187 deletions
src/views/data_pricing/calculateConfig.vue
src/views/data_pricing/calculateConfig.vue
View file @
fc97e0e
...
...
@@ -52,11 +52,13 @@ const dictionaryData: any = ref([]);
const
diseaseData
:
any
=
ref
([]);
const
qualityScoreData
:
any
=
ref
({});
const
disScore
:
any
=
ref
([]);
const
export
Data
:
any
=
ref
([]);
const
buildIn
Data
:
any
=
ref
([]);
const
dataUsage
=
ref
({
field
:
''
,
dictValue
:
''
});
// 基础设置
const
baseConfigFormRef
=
ref
();
const
baseConfigFormItems
:
any
=
ref
([
...
...
@@ -143,8 +145,13 @@ const tableLoading = ref(false);
const
dataTransactionPrice
:
any
=
ref
(
''
);
const
setFormItems
=
(
info
=
null
)
=>
{
let
datas
:
any
=
info
||
flowDetail
.
value
||
{};
const
dData
=
datas
.
dictionaryJson
?
JSON
.
parse
(
datas
.
dictionaryJson
)
:
{};
datas
=
{
...
datas
,
...
dData
};
const
dictData
=
datas
.
dictionaryJson
?
JSON
.
parse
(
datas
.
dictionaryJson
)
:
{};
const
builtIndicators
=
datas
.
builtIndicators
||
[];
let
buildData
=
{};
builtIndicators
.
map
(
item
=>
{
buildData
[
`build_
${
item
.
guid
}
`
]
=
item
.
targetValue
;
});
datas
=
{
...
datas
,
...
dictData
,
...
buildData
};
baseConfigFormItems
.
value
.
map
(
item
=>
{
item
.
default
=
datas
[
item
.
field
]
||
''
;
item
.
label
==
'数据用途'
&&
(
dataUsage
.
value
.
dictValue
=
datas
[
item
.
field
]
||
''
);
...
...
@@ -266,8 +273,10 @@ const getDetail = () => {
typeMap
.
value
.
modelGuid
.
unshift
(
mtem
);
baseConfigFormItems
.
value
[
0
].
options
.
unshift
(
mtem
);
};
setTimeout
(()
=>
{
getModelInfo
(
flowDetail
.
value
.
modelGuid
);
getDataTypeList
()
},
200
)
}
}).
catch
(()
=>
{
loading
.
value
=
false
;
...
...
@@ -304,7 +313,7 @@ const setDictFormItems = (dictList) => {
filterable
:
true
,
required
:
true
,
});
baseConfigFormRules
.
value
[
dictField
]
=
{
required
:
true
,
trigger
:
'change'
,
message
:
`请选择
${
dictName
}
`
}
;
baseConfigFormRules
.
value
[
dictField
]
=
[{
required
:
true
,
trigger
:
'change'
,
message
:
`请选择
${
dictName
}
`
}]
;
dictName
==
'数据用途'
&&
(
dataUsage
.
value
.
field
=
dictField
);
(()
=>
{
if
(
typeMap
.
value
[
dictField
]
==
undefined
)
{
...
...
@@ -338,7 +347,7 @@ const setDiseaseFormItems = () => {
clearable
:
true
,
required
:
true
,
});
baseConfigFormRules
.
value
.
diseaseGuid
=
{
required
:
true
,
trigger
:
'change'
,
message
:
"请选择所属疾病"
}
;
baseConfigFormRules
.
value
.
diseaseGuid
=
[{
required
:
true
,
trigger
:
'change'
,
message
:
"请选择所属疾病"
}]
;
if
(
typeMap
.
value
[
'diseaseGuid'
]
==
undefined
)
{
getDiseaseData
();
}
else
{
...
...
@@ -361,16 +370,44 @@ const setBuildInFormItems = (buildList) => {
buildList
.
map
(
b
=>
{
const
buildName
=
b
.
targetName
;
const
buildField
=
`build_
${
b
.
guid
}
`
;
buildInData
.
value
.
push
({
guid
:
b
.
guid
,
targetName
:
buildName
,
})
baseConfigFormItems
.
value
.
push
({
label
:
buildName
,
type
:
'input'
,
placeholder
:
''
,
field
:
buildField
,
default
:
b
.
defaultValue
||
''
,
default
:
changeNum
(
b
.
defaultValue
,
2
),
inputType
:
'moneyNumber'
,
maxlength
:
18
,
clearable
:
true
,
disabled
:
b
.
isInputParameter
=
=
'Y'
disabled
:
b
.
isInputParameter
!
=
'Y'
});
baseConfigFormRules
.
value
[
buildField
]
=
{
required
:
true
,
trigger
:
'blur'
,
message
:
`请填写
${
buildName
}
`
};
baseConfigFormRules
.
value
[
buildField
]
=
[
{
required
:
true
,
message
:
`请填写
${
buildName
}
`
,
trigger
:
'blur'
},
{
validator
:
(
rule
,
value
,
callback
)
=>
{
if
(
value
===
''
)
{
callback
(
new
Error
(
`请填写
${
buildName
}
`
));
return
;
}
const
num
=
parseFloat
(
value
);
if
(
isNaN
(
num
))
{
callback
(
new
Error
(
'请输入有效的数字'
));
return
;
}
// 已自动保留两位小数,不需再验证小数位数
if
(
num
<
0
||
num
>
b
.
defaultValue
)
{
callback
(
new
Error
(
`输入值必须在0到
${
b
.
defaultValue
}
之间`
));
}
else
{
callback
();
}
},
trigger
:
"blur"
,
},
]
})
};
...
...
@@ -413,7 +450,7 @@ const setFormItemData = async () => {
// 添加数据字典
dictionaryList
.
length
>
0
&&
await
setDictFormItems
(
dictionaryList
);
// 添加内置指标
//
buildInList.length > 0 && await setBuildInFormItems(buildInList);
buildInList
.
length
>
0
&&
await
setBuildInFormItems
(
buildInList
);
setTimeout
(()
=>
{
baseConfigFormRef
.
value
.
ruleFormRef
?.
clearValidate
();
...
...
@@ -476,6 +513,7 @@ const getModelConfig = (mGuid) => {
demandTableList
.
value
=
data
.
pricingDemandMenuRSVOS
||
[];
pricingTargetList
.
value
=
data
.
pricingTargetRSVOS
||
[];
demandTableFieldAllNum
.
value
=
data
.
fieldCount
||
0
;
buildInData
.
value
=
[];
}
})
}
...
...
@@ -773,34 +811,7 @@ const toPath = () => {
})
}
// 获取维度公式计算结果
const
getSignatory
=
(
row
)
=>
{
let
formulaVal
=
0
;
const
pricingTargetData
=
row
.
pricingTargetRSVOS
||
[];
if
(
!
row
.
computationalFormula
||
row
.
computationalFormula
==
'custom'
)
{
let
formula
=
row
.
customize
;
// 遍历数组,检查 customize 是否包含对应的 targetName,若包含则替换为 tNum
pricingTargetData
.
forEach
((
item
)
=>
{
if
(
formula
.
includes
(
item
.
targetName
))
{
formula
=
formula
.
replace
(
new
RegExp
(
item
.
targetName
,
'g'
),
item
.
tNum
);
}
});
// 使用 eval 计算公式结果(注意:eval 存在安全风险,仅适用于受控环境)
try
{
formulaVal
=
eval
(
formula
);
}
catch
(
error
)
{
console
.
error
(
'公式计算错误:'
,
error
);
}
}
else
{
const
formula
=
pricingTargetData
.
map
(
item
=>
item
.
tNum
);
if
(
row
.
computationalFormula
==
'3'
)
{
formulaVal
=
formula
.
reduce
((
accumulator
,
currentValue
)
=>
parseFloat
(
accumulator
)
*
parseFloat
(
currentValue
),
1
);
// 初始值为1
}
else
{
formulaVal
=
formula
.
reduce
((
accumulator
,
currentValue
)
=>
parseFloat
(
accumulator
)
+
parseFloat
(
currentValue
),
0
);
// 初始值为0
}
}
return
(
Math
.
round
(
formulaVal
*
100
)
/
100
).
toFixed
(
2
);
};
// 获取疾病得分
const
getTargetNum
=
(
params
)
=>
{
// loading.value = true;
getPriceResult
(
params
).
then
((
res
:
any
)
=>
{
...
...
@@ -816,151 +827,6 @@ const getTargetNum = (params) => {
});
}
// 生成报告内容
const
reporting
=
(
formInfo
)
=>
{
let
resultInfo
:
any
=
[];
const
signatoryData
=
JSON
.
parse
(
JSON
.
stringify
(
modelData
.
value
.
pricingDimensionalityRSVOS
||
'[]'
));
signatoryData
.
map
((
sign
,
s
)
=>
{
resultInfo
.
push
({
dimensionalityName
:
sign
.
dimensionalityName
,
computationalFormula
:
sign
.
computationalFormula
,
customize
:
sign
.
customize
,
pricingTargetRSVOS
:
[]
});
const
targets
=
sign
.
pricingTargetRSVOS
||
[];
const
signTargets
=
targets
.
map
(
t
=>
{
let
tNum
:
any
=
0
,
tCustomize
=
''
;
if
(
t
.
targetType
==
'3'
)
{
// 指标类型-数据字典
const
tName
=
dictionaryData
.
value
.
find
(
d
=>
d
.
guid
==
t
.
guid
)
?
`dict_
${
t
.
guid
}
`
:
''
;
if
(
tName
)
{
const
pVal
=
typeMap
.
value
[
tName
].
find
(
t
=>
t
.
value
==
formInfo
[
tName
]);
const
dictionary
=
t
.
dictionaryJson
.
find
(
d
=>
d
.
name
==
pVal
.
label
);
if
(
sign
.
computationalFormula
==
'1'
)
{
// 加权平均
tNum
=
parseFloat
(
t
.
weight
)
/
100
*
parseFloat
(
dictionary
?.
value
||
t
.
defaultValue
||
0
);
tCustomize
=
`权重
${
parseFloat
(
t
.
weight
)
/
100
}
* 因子/默认值
${
parseFloat
(
dictionary
?.
value
||
t
.
defaultValue
||
0
)}
`;
} else { // 其他
tNum = parseFloat(dictionary?.value || t.defaultValue || 0);
tCustomize = `
默认值
$
{
parseFloat
(
dictionary
?.
value
||
t
.
defaultValue
||
0
)}
`;
}
t.dictionaryName == '数据用途' && (dataUsage.value.dictValue = pVal.value || '');
}
} else if (t.targetType == '2') {// 指标类型-系统功能
if (t.functionName == '1') { // 功能名称-质量评价模型
const score = parseFloat(qualityScoreData.value.qualityScore || 0);
tNum = parseFloat(t.weight || 1) / 100 * score / 100;
tCustomize = `
权重
$
{
parseFloat
(
t
.
weight
||
1
)
/
100
}
*
模型评分
$
{
score
}
/100`
;
}
else
if
(
t
.
functionName
==
'2'
)
{
// 功能名称-疾病管理
if
(
sign
.
computationalFormula
==
'1'
)
{
// 加权平均
const
score
=
parseFloat
(
disScore
.
value
.
find
(
d
=>
d
.
guid
==
t
.
guid
)?.
factor
||
0
);
tNum
=
parseFloat
(
t
.
weight
)
/
100
*
score
;
tCustomize
=
`权重
${
parseFloat
(
t
.
weight
)
/
100
}
* 疾病得分
${
score
}
`
;
}
else
{
//其他
tNum
=
parseFloat
(
disScore
.
value
.
find
(
d
=>
d
.
guid
==
t
.
guid
)?.
factor
||
0
);
tCustomize
=
`疾病得分
${
tNum
}
`
;
}
}
else
if
(
t
.
functionName
==
'3'
)
{
// 功能名称-需求表管理
const
tData
=
tableData
.
value
.
find
(
f
=>
f
.
demandTableGuid
==
t
.
demandTableGuid
||
f
.
guid
==
t
.
demandTableGuid
);
if
(
tData
)
{
if
(
sign
.
computationalFormula
==
'1'
)
{
// 加权平均
tNum
=
parseFloat
(
t
.
weight
)
/
100
*
(
parseFloat
(
tData
.
dataFieldsNum
)
/
tData
.
dataFields
.
length
||
parseFloat
(
t
.
defaultValue
||
0
));
tCustomize
=
`权重
${
parseFloat
(
t
.
weight
)
/
100
}
* 匹配率/默认值
${
parseFloat
(
tData
.
dataFieldsNum
)
/
tData
.
dataFields
.
length
||
parseFloat
(
t
.
defaultValue
||
0
)}
`
;
}
else
{
//其他
tNum
=
parseFloat
(
tData
.
dataFieldsNum
)
/
tData
.
dataFields
.
length
||
parseFloat
(
t
.
defaultValue
||
0
);
tCustomize
=
`匹配率/默认值
${
parseFloat
(
tData
.
dataFieldsNum
)
/
tData
.
dataFields
.
length
||
parseFloat
(
t
.
defaultValue
||
0
)}
`
;
}
}
}
}
else
{
// 指标类型-系统内置
if
(
sign
.
computationalFormula
==
'1'
)
{
// 加权平均
tNum
=
parseFloat
(
t
.
weight
)
/
100
*
parseFloat
(
t
.
defaultValue
||
0
);
tCustomize
=
`权重
${
parseFloat
(
t
.
weight
)
/
100
}
* 默认值
${
parseFloat
(
t
.
defaultValue
||
0
)}
`
;
}
else
{
//其他
tNum
=
parseFloat
(
t
.
defaultValue
||
0
);
tCustomize
=
`默认值
${
parseFloat
(
t
.
defaultValue
||
0
)}
`
;
}
}
t
.
tNum
=
(
Math
.
round
(
parseFloat
(
tNum
)
*
100
)
/
100
).
toFixed
(
2
);
resultInfo
[
s
].
pricingTargetRSVOS
.
push
({
targetName
:
t
.
targetName
,
targetType
:
t
.
targetType
,
functionName
:
t
.
functionName
,
customize
:
tCustomize
,
tNum
:
t
.
tNum
,
})
return
t
;
})
sign
.
pricingTargetRSVOS
=
signTargets
;
sign
.
sNum
=
getSignatory
(
sign
);
resultInfo
[
s
].
sNum
=
sign
.
sNum
;
})
// exportData.value = resultInfo;
return
{
signatoryData
,
resultInfo
};
}
// 计算价格
const
calculatePrice
=
(
pData
)
=>
{
let
modelFormula
=
modelData
.
value
.
modelFormula
;
// 1. 移除所有干扰的引号(确保是数学表达式)
modelFormula
=
modelFormula
.
replace
(
/
[
"'
]
/g
,
""
).
trim
();
// 2. 定义允许的数学运算符和函数
const
allowedOperators
=
/
[
+
\-
*
/
%^() .
\d]
/
;
const
mathFunctions
=
[
'sin'
,
'cos'
,
'tan'
,
'log'
,
'sqrt'
,
'abs'
,
'pow'
];
// 3. 提取变量名
const
variableRegex
=
/
[\u
4e00-
\u
9fa5a-zA-Z_
][\u
4e00-
\u
9fa5a-zA-Z0-9_
]
*/g
;
const
variableNames
=
[...
new
Set
(
modelFormula
.
match
(
variableRegex
)
||
[])];
// 4. 构建变量映射
const
variables
=
{};
variableNames
.
forEach
(
name
=>
{
const
dim
=
pData
.
find
(
d
=>
d
.
dimensionalityName
===
name
);
variables
[
name
]
=
dim
?
parseFloat
(
dim
.
sNum
)
||
0
:
0
;
});
// 5. 替换变量为数值(考虑边界情况)
let
expression
=
modelFormula
;
Object
.
keys
(
variables
).
forEach
(
name
=>
{
expression
=
expression
.
replace
(
new
RegExp
(
name
,
'g'
),
variables
[
name
]);
});
// 6. 表达式规范化(不丢失括号)
expression
=
expression
.
replace
(
/
\s
+/g
,
''
)
// 去空格
.
replace
(
/
\^
/g
,
'**'
)
// 幂运算转换
.
replace
(
/"|'/g
,
''
)
// 去引号(不破坏括号)
.
replace
(
/
(\d)\(
/g
,
'$1*('
)
// 处理隐式乘法
.
replace
(
/
\)\(
/g
,
')*('
);
// 括号间乘法
// 7. 验证括号配对
const
balance
=
expression
.
split
(
''
).
reduce
((
acc
,
char
)
=>
{
if
(
char
===
'('
)
acc
++
;
if
(
char
===
')'
)
acc
--
;
return
acc
;
},
0
);
if
(
balance
!==
0
)
{
console
.
error
(
'括号不匹配'
);
return
NaN
;
}
// 8. 安全计算
try
{
const
result
=
new
Function
(
'return '
+
expression
)();
const
roundedResult
=
Math
.
round
(
parseFloat
(
result
)
*
100
)
/
100
;
dataTransactionPrice
.
value
=
roundedResult
.
toFixed
(
2
);
return
roundedResult
;
}
catch
(
error
)
{
console
.
error
(
'计算错误:'
,
{
error
,
original
:
modelFormula
,
processed
:
expression
});
return
NaN
;
}
};
// 获取定价计算配置参数
const
getCalculateParams
=
(
baseConfigFormObj
,
baseConfigFormInfo
)
=>
{
const
modelName
=
typeMap
.
value
.
modelGuid
.
find
(
d
=>
d
.
guid
==
baseConfigFormInfo
.
modelGuid
)?.
modelName
||
''
;
...
...
@@ -983,13 +849,20 @@ const getCalculateParams = (baseConfigFormObj, baseConfigFormInfo) => {
const
parentsData
=
baseConfigFormObj
.
getCascaderCheckedData
();
params
.
diseaseName
=
parentsData
[
0
]?.
label
||
''
;
}
let
dictionaryJson
=
{};
let
dictionaryJson
=
{}
,
builtInTarget
:
any
=
[]
;
for
(
var
b
in
baseConfigFormInfo
)
{
if
(
b
.
indexOf
(
'dict_'
)
>
-
1
)
{
dictionaryJson
[
b
]
=
baseConfigFormInfo
[
b
];
}
}
buildInData
.
value
.
map
(
item
=>
{
builtInTarget
.
push
({
...
item
,
targetValue
:
baseConfigFormInfo
[
`build_
${
item
.
guid
}
`
],
})
})
params
.
dictionaryJson
=
Object
.
keys
(
dictionaryJson
).
length
?
JSON
.
stringify
(
dictionaryJson
)
:
''
;
params
.
builtIndicators
=
builtInTarget
;
let
demandMatchingData
:
any
=
[];
tableData
.
value
.
map
(
item
=>
{
demandMatchingData
.
push
({
...
...
@@ -1019,15 +892,16 @@ const getCalculateParams = (baseConfigFormObj, baseConfigFormInfo) => {
const
getCalculatPrice
=
async
(
params
)
=>
{
try
{
const
res
:
any
=
await
calculatPrice
(
params
);
loading
.
value
=
false
;
if
(
res
.
code
===
proxy
.
$passCode
)
{
const
data
=
res
.
data
||
{};
return
data
;
// 返回计算结果以便后续使用
}
else
{
proxy
.
$ElMessage
.
error
(
res
.
msg
);
loading
.
value
=
false
;
throw
new
Error
(
res
.
msg
);
// 抛出错误以便 catch 捕获
}
}
catch
(
error
)
{
console
.
error
(
'计算价格失败:'
,
error
);
loading
.
value
=
false
;
throw
error
;
// 重新抛出错误
}
...
...
@@ -1047,9 +921,8 @@ const checkForm = (type) => {
// 显示结果
dataTransactionPrice
.
value
=
priceData
.
transactionPrice
.
toFixed
(
2
);
if
(
type
==
'calculate'
)
{
loading
.
value
=
false
;
}
else
if
(
type
==
'export'
)
{
if
(
type
==
'export'
)
{
loading
.
value
=
true
;
const
exportOut
=
{
one
:
priceData
.
one
,
two
:
priceData
.
two
,
...
...
@@ -1078,6 +951,7 @@ const checkForm = (type) => {
...
paramsInfo
,
dataTransactionPrice
:
dataTransactionPrice
.
value
,
}
loading
.
value
=
true
;
savePrice
(
params
).
then
((
res
:
any
)
=>
{
loading
.
value
=
false
;
if
(
res
.
code
==
proxy
.
$passCode
)
{
...
...
@@ -1177,6 +1051,7 @@ onBeforeMount(() => {
}
})
onMounted
(()
=>
{
getModel
()
})
</
script
>
<
template
>
...
...
Write
Preview
Styling with
Markdown
is supported
Attach a file
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to post a comment