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
2aa70cc4
authored
2025-09-05 17:04:56 +0800
by
lihua
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
匿名化处理接口联调2
1 parent
fd5bd230
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
410 additions
and
45 deletions
src/store/modules/dataAnonymization.ts
src/views/data_anonymization/anonResultView.vue
src/views/data_anonymization/anonTaskCreate.vue
src/views/data_anonymization/anonTaskStepTwo.vue
src/views/data_anonymization/resultProcess.vue
src/store/modules/dataAnonymization.ts
View file @
2aa70cc
const
useDataAnonymizationStore
=
defineStore
(
// 资产目录guid
"isRefresh"
,
'isRefresh'
,
()
=>
{
const
isRefresh
=
ref
<
boolean
>
(
false
);
function
setIsRefresh
(
v
:
boolean
)
{
isRefresh
.
value
=
v
;
}
const
isAnonPageRefresh
=
ref
<
boolean
>
(
false
);
function
setIsAnonPageRefresh
(
v
:
boolean
)
{
isAnonPageRefresh
.
value
=
v
;
}
return
{
isRefresh
,
isAnonPageRefresh
,
setIsRefresh
,
setIsAnonPageRefresh
,
};
}
);
...
...
src/views/data_anonymization/anonResultView.vue
View file @
2aa70cc
...
...
@@ -38,6 +38,7 @@ const tableFields: any = ref([]);
const
pageInfo
:
any
=
ref
({
...
commonPageConfig
,
rows
:
0
,
})
const
getData
=
()
=>
{
...
...
@@ -61,6 +62,7 @@ const getData = () => {
});
tableData
.
value
.
push
(
obj
);
});
pageInfo
.
value
.
rows
=
res
.
data
?.
totalRows
??
0
;
}
else
{
ElMessage
.
error
(
res
.
msg
);
}
...
...
@@ -128,6 +130,7 @@ watch(() => props.execGuid, (val) => {
if
(
res
.
code
==
proxy
.
$passCode
)
{
let
column
=
res
.
data
?.
column
||
{};
tableFields
.
value
=
column
;
pageInfo
.
value
.
curr
=
1
;
getData
();
}
else
{
ElMessage
.
error
(
res
.
msg
);
...
...
@@ -210,7 +213,7 @@ const exportData = () => {
<el-button
v-show=
"props.isPage"
style=
"margin-bottom: 8px;"
type=
"primary"
@
click=
"exportData"
v-preReClick
>
导出数据
</el-button>
<el-table
ref=
"tableRef"
v-show=
"tableFields.length"
:data=
"tableData"
:highlight-current-row=
"true"
stripe
border
tooltip-effect=
"light"
height=
"100%"
row-key=
"guid"
:style=
"
{ width: '100%', height: 'calc(100% - 64px)' }">
tooltip-effect=
"light"
height=
"100%"
row-key=
"guid"
:style=
"
{ width: '100%', height:
!props.isPage ? 'calc(100% - 34px)' :
'calc(100% - 64px)' }">
<template
v-for=
"(item, index) in (tableFields || [])"
>
<el-table-column
:label=
"item.chName"
:width=
"item.dataType === 'datetime'
? TableColumnWidth.DATETIME
...
...
src/views/data_anonymization/anonTaskCreate.vue
View file @
2aa70cc
...
...
@@ -32,9 +32,13 @@ import anonTaskStepTwo from './anonTaskStepTwo.vue';
import
*
as
XLSX
from
'xlsx'
;
import
{
ElMessage
}
from
'element-plus'
;
import
{
isEqual
,
cloneDeep
}
from
"lodash-es"
;
import
{
download
}
from
"@/utils/common"
;
import
{
changeNum
,
download
}
from
"@/utils/common"
;
import
anonResultView
from
'./anonResultView.vue'
;
import
useDataAnonymizationStore
from
"@/store/modules/dataAnonymization"
;
import
{
RefreshRight
,
CircleCloseFilled
,
Right
}
from
"@element-plus/icons-vue"
;
import
{
commonPageConfig
}
from
'@/components/PageNav'
;
const
anonymizationStore
=
useDataAnonymizationStore
();
const
{
proxy
}
=
getCurrentInstance
()
as
any
;
const
userStore
=
useUserStore
();
const
route
=
useRoute
();
...
...
@@ -43,7 +47,7 @@ const fullPath = route.fullPath;
const
taskGuid
=
ref
(
route
.
query
.
guid
);
/** 提交保存和编辑后的执行guid */
const
taskExecGuid
=
ref
(
''
);
/** 是否执行结束 */
/** 是否执行结束
,用于第四步获取执行结果
*/
const
isExecEnd
=
ref
(
false
);
const
{
required
}
=
useValidator
();
const
fullscreenLoading
=
ref
(
false
);
...
...
@@ -270,12 +274,12 @@ const handleDataSelectFormSelectChange = async (val, row, formInfo) => {
d
.
chName
=
d
.
columnZhName
;
return
d
;
})
||
[];
/** 判断有抽样数据,需要查询接口 */
getSampleDataByDsTable
();
}
else
{
ElMessage
.
error
(
res
.
msg
);
}
});
/** 判断有抽样数据,需要查询接口 */
getSampleDataByDsTable
();
}
}
...
...
@@ -402,8 +406,8 @@ const formatterPreviewDate = (row, info) => {
if
(
v
===
0
)
{
return
v
;
}
if
(
!
v
)
{
return
v
||
'--'
;
if
(
!
v
||
v
==
'null'
)
{
return
'--'
;
}
if
(
info
.
dataType
===
'datetime'
)
{
return
Moment
(
v
).
format
(
'YYYY-MM-DD HH:mm:ss'
);
...
...
@@ -470,13 +474,13 @@ const parseFileData = (fileRaw) => {
});
}
/** 获取文件解析后根据抽样比例得出的表格数据 */
/** 获取文件解析后根据抽样比例得出的表格数据
,默认查看前500条数据
*/
const
transferSampleData
=
()
=>
{
let
samplingRate
=
dataSimpleFormRef
.
value
?.
formInline
?.
samplingRate
;
if
(
parseFileDataSum
.
value
.
length
>
1
&&
samplingRate
)
{
let
totalCnt
=
parseFileDataSum
.
value
.
length
-
1
;
let
cnt
=
Math
.
ceil
(
samplingRate
*
0.01
*
totalCnt
)
+
1
;
sampleTableData
.
value
=
parseFileDataSum
.
value
.
slice
(
1
,
cnt
>
1000
?
10
01
:
cnt
).
map
((
info
,
row
)
=>
{
sampleTableData
.
value
=
parseFileDataSum
.
value
.
slice
(
1
,
cnt
>
500
?
5
01
:
cnt
).
map
((
info
,
row
)
=>
{
let
object
=
{};
parseFileDataSum
.
value
[
0
].
forEach
((
chName
,
col
)
=>
{
let
name
=
sampleTableFields
.
value
[
col
].
enName
;
...
...
@@ -510,8 +514,8 @@ const getSampleDataByDsTable = () => {
}
sampleTableDataLoading
.
value
=
true
;
getDsTableSampleData
({
limitNum
:
cnt
,
pageSize
:
cnt
,
limitNum
:
cnt
>
500
?
500
:
cnt
,
pageSize
:
cnt
>
500
?
500
:
cnt
,
pageIndex
:
1
,
dataSourceGuid
:
currDatasourceSelect
.
value
.
guid
,
database
:
currDatasourceSelect
.
value
.
databaseNameEn
,
...
...
@@ -530,7 +534,6 @@ const getSampleDataByDsTable = () => {
}
const
uploadFileChange
=
(
file
)
=>
{
sampleTableFields
.
value
=
[];
sampleTableData
.
value
=
[];
if
(
!
file
.
length
)
{
sampleTableFields
.
value
=
[];
...
...
@@ -545,13 +548,22 @@ const uploadFileChange = (file) => {
const
anonTaskStepTwoRef
=
ref
();
const
changeStep
=
async
(
val
)
=>
{
if
(
val
==
2
)
{
if
(
val
<=
step
.
value
)
{
step
.
value
=
val
-
1
;
stepsInfo
.
value
.
step
=
val
-
1
;
}
else
if
(
val
==
2
)
{
formRef
.
value
?.
ruleFormRef
?.
validate
((
valid
)
=>
{
if
(
valid
)
{
if
(
formRef
.
value
?.
formInline
?.
dataSource
==
2
&&
!
sampleTableFields
.
value
?.
length
)
{
proxy
.
$ElMessage
.
error
(
'上传文件的字段不能为空'
);
return
;
}
dataSimpleFormRef
.
value
?.
ruleFormRef
?.
validate
((
valid
)
=>
{
if
(
valid
)
{
// 第一步到第二步时,如果字段列表中与字段脱敏规则中的字段不匹配,应清空。
step
.
value
=
val
-
1
;
stepsInfo
.
value
.
step
=
val
-
1
;
anonTaskStepTwoRef
.
value
?.
updateNextStepRules
();
}
});
}
...
...
@@ -580,7 +592,7 @@ const changeStep = async (val) => {
}
else
{
saveParams
.
samplingRate
=
null
;
}
let
privacy
=
configInfo
.
anonPrivacyMode
;
let
privacy
=
configInfo
.
anonPrivacyMode
;
//值是克隆过的,可以删除
delete
privacy
.
isKaNumber
;
delete
privacy
.
isRiskThreshold
;
delete
privacy
.
isTcField
;
...
...
@@ -597,8 +609,14 @@ const changeStep = async (val) => {
saveParams
.
guid
=
taskGuid
.
value
;
}
if
(
isEqual
(
saveParams
,
oldAnonTaskValueInfo
.
value
))
{
isExecEnd
.
value
=
false
;
step
.
value
=
val
-
1
;
stepsInfo
.
value
.
step
=
val
-
1
;
if
(
!
analysisResultInfo
.
value
?.
status
)
{
processStepThreeResultView
();
}
else
{
isExecEnd
.
value
=
analysisResultInfo
.
value
?.
status
==
'E'
||
analysisResultInfo
.
value
?.
status
==
'Y'
;
}
return
;
}
if
(
!
taskGuid
.
value
)
{
//保存
...
...
@@ -611,7 +629,14 @@ const changeStep = async (val) => {
taskExecGuid
.
value
=
res
.
data
?.
lastExecGuid
;
step
.
value
=
val
-
1
;
stepsInfo
.
value
.
step
=
val
-
1
;
analysisResultInfo
.
value
=
{};
if
(
refreshTimer
.
value
)
{
clearInterval
(
refreshTimer
.
value
);
refreshTimer
.
value
=
null
;
}
processStepThreeResultView
();
oldAnonTaskValueInfo
.
value
=
saveParams
;
anonymizationStore
.
setIsAnonPageRefresh
(
true
);
}
else
{
ElMessage
.
error
(
res
.
msg
);
}
...
...
@@ -625,26 +650,21 @@ const changeStep = async (val) => {
taskExecGuid
.
value
=
res
.
data
;
step
.
value
=
val
-
1
;
stepsInfo
.
value
.
step
=
val
-
1
;
analysisResultInfo
.
value
=
{};
if
(
refreshTimer
.
value
)
{
clearInterval
(
refreshTimer
.
value
);
refreshTimer
.
value
=
null
;
}
processStepThreeResultView
();
oldAnonTaskValueInfo
.
value
=
saveParams
;
anonymizationStore
.
setIsAnonPageRefresh
(
true
);
}
else
{
ElMessage
.
error
(
res
.
msg
);
}
})
}
}
else
if
(
val
==
4
)
{
//下一步之后,调用分析结果。
getAnonAnalyzeResult
(
detailInfo
.
value
.
lastExecGuid
).
then
((
res
:
any
)
=>
{
debugger
});
getAnonAnalyzePageData
({
pageSize
:
-
1
}).
then
((
res
:
any
)
=>
{
debugger
});
step
.
value
=
val
-
1
;
stepsInfo
.
value
.
step
=
val
-
1
;
}
else
if
(
val
<=
step
.
value
)
{
//下一步之后,设置执行结束, 查看结果。
step
.
value
=
val
-
1
;
stepsInfo
.
value
.
step
=
val
-
1
;
}
...
...
@@ -682,6 +702,7 @@ onBeforeMount(() => {
getAnonTaskDetail
(
taskGuid
.
value
).
then
(
async
(
res
:
any
)
=>
{
if
(
res
?.
code
==
proxy
.
$passCode
)
{
detailInfo
.
value
=
res
.
data
||
{};
taskExecGuid
.
value
=
detailInfo
.
value
.
lastExecGuid
;
oldAnonTaskValueInfo
.
value
=
{
guid
:
detailInfo
.
value
.
guid
,
taskName
:
detailInfo
.
value
.
taskName
,
...
...
@@ -742,6 +763,15 @@ onBeforeMount(() => {
res
?.
msg
&&
ElMessage
.
error
(
res
?.
msg
);
}
})
// 会出现从文件切换到数据库时没有数据库列表的问题。
const
res
:
any
=
await
getDatabase
({
connectStatus
:
1
});
if
(
res
?.
code
==
proxy
.
$passCode
)
{
dataSourceList
.
value
=
res
.
data
||
[];
let
item
=
dataSelectInfoItems
.
value
.
find
(
item
=>
item
.
field
==
'dataSourceGuid'
);
item
&&
(
item
.
options
=
dataSourceList
.
value
);
}
else
{
proxy
.
$ElMessage
.
error
(
res
.
msg
);
}
}
else
{
const
res
:
any
=
await
getDatabase
({
connectStatus
:
1
});
if
(
res
?.
code
==
proxy
.
$passCode
)
{
...
...
@@ -783,12 +813,12 @@ onBeforeMount(() => {
d
.
chName
=
d
.
columnZhName
;
return
d
;
})
||
[];
/** 判断有抽样数据,需要查询接口 */
getSampleDataByDsTable
();
}
else
{
ElMessage
.
error
(
res
.
msg
);
}
});
/** 判断有抽样数据,需要查询接口 */
getSampleDataByDsTable
();
}
fullscreenLoading
.
value
=
false
;
}
else
{
...
...
@@ -840,6 +870,141 @@ const cancelTask = () => {
});
}
const
refreshTimer
=
ref
()
/** 执行结果信息 */
const
analysisResultInfo
:
any
=
ref
({});
const
getResultPromise
:
any
=
ref
(
null
);
/** 第三步处理,定时刷新查看结果 */
const
processStepThreeResultView
=
(
isRefresh
=
false
)
=>
{
let
process
=
(
isRefresh
)
=>
{
getResultPromise
.
value
=
getAnonAnalyzeResult
(
taskExecGuid
.
value
).
then
((
res
:
any
)
=>
{
getResultPromise
.
value
=
null
;
if
(
res
?.
code
==
proxy
.
$passCode
)
{
analysisResultInfo
.
value
=
res
.
data
||
{};
if
(
analysisResultInfo
.
value
.
status
==
'R'
)
{
//正在运行中
if
(
isRefresh
)
{
proxy
.
$ElMessage
.
success
(
'刷新成功,正在执行中...'
);
}
//添加定时器。
if
(
refreshTimer
.
value
)
{
return
;
}
refreshTimer
.
value
=
setInterval
(
async
()
=>
{
process
(
false
);
},
20000
);
}
else
if
(
analysisResultInfo
.
value
.
status
==
'Y'
)
{
//去获取结果。
isExecEnd
.
value
=
true
;
refreshTimer
.
value
&&
clearInterval
(
refreshTimer
.
value
);
refreshTimer
.
value
=
null
;
analysisResultTableFields
.
value
=
res
.
data
?.
column
||
[];
pageInfo
.
value
.
curr
=
1
;
getAnalysisResultPageData
();
}
else
if
(
analysisResultInfo
.
value
.
status
==
'E'
)
{
isExecEnd
.
value
=
true
refreshTimer
.
value
&&
clearInterval
(
refreshTimer
.
value
);
refreshTimer
.
value
=
null
;
}
}
else
{
proxy
.
$ElMessage
.
error
(
res
.
msg
);
}
});
}
process
(
isRefresh
);
}
/** 随时点击刷新查看结果。 */
const
refreshQueryData
=
()
=>
{
if
(
getResultPromise
.
value
)
{
return
;
}
if
(
refreshTimer
.
value
)
{
clearInterval
(
refreshTimer
.
value
);
refreshTimer
.
value
=
null
;
}
processStepThreeResultView
(
true
);
}
/** ------------------------- 匿名化分析结果页面数据展示 ---------------- */
const
pageInfo
:
any
=
ref
({
...
commonPageConfig
,
})
const
pageChange
=
(
info
)
=>
{
pageInfo
.
value
.
curr
=
Number
(
info
.
curr
);
pageInfo
.
value
.
limit
=
Number
(
info
.
limit
);
getAnalysisResultPageData
();
}
/** 每列字段对应的列宽计算结果。 */
const
originResultTableFieldColumn
=
ref
({});
/** 结果分析中的字段表格数据 */
const
resultData
:
any
=
ref
([]);
/** 结果分析中的字段信息 */
const
analysisResultTableFields
:
any
=
ref
([]);
const
analysisResultLoading
=
ref
(
false
);
watch
(
resultData
,
(
val
:
any
[],
oldVal
)
=>
{
if
(
!
analysisResultTableFields
.
value
?.
length
)
{
originResultTableFieldColumn
.
value
=
{};
return
;
}
originResultTableFieldColumn
.
value
=
{};
analysisResultTableFields
.
value
.
forEach
((
field
,
index
)
=>
{
originResultTableFieldColumn
.
value
[
field
.
enName
]
=
calcTableColumnWidth
(
val
?.
slice
(
0
,
20
)
||
[],
field
.
enName
,
field
.
chName
,
24
);
});
},
{
deep
:
true
,
}
);
const
getAnalysisResultPageData
=
()
=>
{
analysisResultLoading
.
value
=
true
;
getAnonAnalyzePageData
({
pageIndex
:
pageInfo
.
value
.
curr
,
pageSize
:
pageInfo
.
value
.
limit
,
taskExecGuid
:
taskExecGuid
.
value
,
}).
then
((
res
:
any
)
=>
{
analysisResultLoading
.
value
=
false
;
if
(
res
?.
code
==
proxy
.
$passCode
)
{
pageInfo
.
value
.
rows
=
resultData
.
value
=
[];
res
.
data
?.
records
?.
forEach
(
d
=>
{
let
obj
=
{};
analysisResultTableFields
.
value
.
forEach
(
t
=>
{
obj
[
t
.
enName
]
=
d
.
fieldValue
?.[
t
.
enName
];
});
obj
[
'equivalenceClassNum'
]
=
changeNum
(
d
.
equivalenceClassNum
||
0
,
0
);
obj
[
'reIdentifyRisk'
]
=
changeNum
(
d
.
reIdentifyRisk
||
0
,
2
);
obj
[
'isGtThreshold'
]
=
d
.
isGtThreshold
;
resultData
.
value
.
push
(
obj
);
});
pageInfo
.
value
.
rows
=
res
.
data
?.
totalRows
??
0
;
}
else
{
proxy
.
$ElMessage
.
error
(
res
.
msg
);
}
})
}
onUnmounted
(()
=>
{
refreshTimer
.
value
&&
clearInterval
(
refreshTimer
.
value
);
refreshTimer
.
value
=
null
;
})
</
script
>
<
template
>
...
...
@@ -883,17 +1048,88 @@ const cancelTask = () => {
</div>
</ContentWrap>
</div>
<anonTaskStepTwo
ref=
"anonTaskStepTwoRef"
v-show=
"step == 1"
:anonTaskRules=
"detailInfo.anonTaskRules"
:isFile=
"formRef?.formInline?.file?.length > 0"
:anonPrivacyMode=
"detailInfo.anonPrivacyMode"
:fieldTypeList=
"fieldTypeList"
:fieldNameList=
"sampleTableFields"
>
<anonTaskStepTwo
ref=
"anonTaskStepTwoRef"
v-show=
"step == 1"
:anonTaskRules=
"detailInfo.anonTaskRules"
:isFile=
"formRef?.formInline?.file?.length > 0"
:anonPrivacyMode=
"detailInfo.anonPrivacyMode"
:fieldTypeList=
"fieldTypeList"
:fieldNameList=
"sampleTableFields"
>
</anonTaskStepTwo>
<div
class=
"operator_panel_wrap"
v-show=
"step == 2"
>
<ContentWrap
id=
"analysis-result"
title=
"匿名结果分析"
description=
""
style=
"margin-top: 8px;"
>
<div
class=
"wait-result-div"
v-show=
"!isExecEnd"
>
<img
class=
"loading-img"
src=
"../../assets/images/loading.gif"
/>
<div
class=
"desc"
>
正在进行匿名化处理,请稍候...
</div>
<el-button
:icon=
"RefreshRight"
link
@
click=
"refreshQueryData"
v-preReClick
>
刷新查看结果
</el-button>
</div>
<div
class=
"wait-result-div"
v-show=
"isExecEnd && analysisResultInfo.status == 'E'"
>
<el-icon
class=
"failed"
>
<CircleCloseFilled
/>
</el-icon>
<div
class=
"error-desc"
>
{{ '执行失败,请返回上一步修改配置或联系管理员' }}
</div>
<div
v-show=
"analysisResultInfo.errorMsg"
class=
"error-desc"
>
{{ '【' + analysisResultInfo.errorMsg + '】' }}
</div>
</div>
<div
class=
"analysis-result-main"
v-show=
"isExecEnd && analysisResultInfo.status == 'Y'"
>
<el-table
ref=
"tableRef"
v-show=
"analysisResultTableFields.length"
:data=
"resultData"
v-loading=
"analysisResultLoading"
:highlight-current-row=
"true"
stripe
border
tooltip-effect=
"light"
height=
"100%"
row-key=
"guid"
:style=
"{ width: '100%', height: '280px' }"
>
<el-table-column
label=
"等价类"
type=
"index"
width=
"68px"
align=
"center"
show-overflow-tooltip
>
<
template
#
default=
"scope"
>
<span>
{{
pageInfo
.
curr
!==
undefined
?
(
pageInfo
.
curr
-
1
)
*
pageInfo
.
limit
+
scope
.
$index
+
1
:
scope
.
$index
+
1
}}
</span>
</
template
>
</el-table-column>
<
template
v-for=
"(item, index) in (analysisResultTableFields || [])"
>
<el-table-column
:label=
"item.chName"
:width=
"item.dataType === 'datetime'
? TableColumnWidth.DATETIME
: item.dataType === 'date'
? TableColumnWidth.DATE
: originResultTableFieldColumn[item.enName]
"
:align=
"getTextAlign(item)"
:header-align=
"getTextAlign(item)"
:formatter=
"(row) => formatterPreviewDate(row, item)"
:show-overflow-tooltip=
"true"
>
</el-table-column>
</
template
>
<el-table-column
label=
"等价类大小"
prop=
"equivalenceClassNum"
width=
"98"
align=
"right"
fixed=
"right"
show-overflow-tooltip
></el-table-column>
<el-table-column
label=
"重标识风险"
prop=
"reIdentifyRisk"
width=
"96"
align=
"right"
fixed=
"right"
show-overflow-tooltip
></el-table-column>
<el-table-column
label=
"判断重风险是否大于门限阈值"
prop=
"isGtThreshold"
width=
"130"
align=
"left"
fixed=
"right"
show-overflow-tooltip
></el-table-column>
</el-table>
<div
v-show=
"!analysisResultTableFields.length"
class=
"empty-content"
>
<img
src=
"../../assets/images/empty-data.png"
:style=
"{ width: '168px', height: '96px' }"
/>
<div
class=
"empty-text"
>
暂无数据
</div>
</div>
<PageNav
:class=
"[pageInfo.type]"
:pageInfo=
"pageInfo"
@
pageChange=
"pageChange"
/>
<div
v-show=
"Object.keys(analysisResultInfo).length > 0"
>
<div
class=
"value-desc"
><span
style=
"font-weight: 600;margin-right: 8px;"
>
重标识风险指标
</span>
{{ 'Rb=' +
changeNum(analysisResultInfo.reIdentifyRiskRb || 0, 2) + ' Rc='
+
changeNum(analysisResultInfo.reIdentifyRiskRc || 0, 2) }}
</div>
<div
class=
"value-desc"
><span
style=
"font-weight: 600;margin-right: 8px;"
>
环境重标识攻击概率
</span>
{{
'pr(context)=' +
changeNum(analysisResultInfo.envReAttackPr || 0, 2)
}}
</div>
<div
class=
"value-desc"
><span
style=
"font-weight: 600;margin-right: 8px;"
>
重标识总体风险
</span>
{{
'R=Rc*pr(context)=' +
changeNum(analysisResultInfo.reIdentifyOverallRisk || 0,
2) }}
</div>
<div
class=
"value-desc"
style=
"font-weight: 600;"
>
{{ '重标识总体风险值小于可接受风险阈值' +
(oldAnonTaskValueInfo.anonPrivacyMode?.riskThreshold ==
null ?
0.05 : (changeNum(oldAnonTaskValueInfo.anonPrivacyMode?.riskThreshold || 0, 2))) + ',评为' +
analysisResultInfo.rating + '级' }}
</div>
</div>
</div>
</ContentWrap>
</div>
<div
class=
"operator_panel_wrap"
v-show=
"step == 3"
>
<ContentWrap
id=
"analysis-result"
title=
"匿名化数据结果"
description=
""
style=
"margin-top: 8px;"
>
<anonResultView
:is-page=
"false"
:execGuid=
"isExecEnd ? taskExecGuid : ''"
></anonResultView>
<div
class=
"operator_panel_wrap step-result"
v-show=
"step == 3"
style=
"height: calc(100% - 88px);"
>
<ContentWrap
id=
"analysis-result"
title=
"匿名化数据结果"
description=
""
style=
"margin-top: 8px;height: 100%;"
>
<anonResultView
:is-page=
"false"
:execGuid=
"analysisResultInfo.status == 'Y' && step == 3 ? taskExecGuid : ''"
>
</anonResultView>
</ContentWrap>
</div>
</div>
...
...
@@ -904,14 +1140,16 @@ const cancelTask = () => {
</
template
>
<
template
v-else-if=
"step == 1"
>
<el-button
@
click=
"changeStep(1)"
>
上一步
</el-button>
<el-button
type=
"primary"
@
click=
"changeStep(3)"
>
保存并
下一步
</el-button>
<el-button
type=
"primary"
@
click=
"changeStep(3)"
>
下一步
</el-button>
</
template
>
<
template
v-else-if=
"step == 2"
>
<el-button
@
click=
"changeStep(2)"
>
上一步
</el-button>
<el-button
type=
"primary"
@
click=
"changeStep(4)"
>
下一步
</el-button>
<el-button
type=
"primary"
:disabled=
"analysisResultInfo.status == 'R' || (isExecEnd && analysisResultInfo.status == 'E')"
@
click=
"changeStep(4)"
>
下一步
</el-button>
</
template
>
<
template
v-else
>
<el-button
type=
"primary"
@
click=
"changeStep(2
)"
>
上一步
</el-button>
<el-button
@
click=
"changeStep(3
)"
>
上一步
</el-button>
<el-button
type=
"primary"
v-preReClick
@
click=
"exportResult"
>
导出
</el-button>
</
template
>
</div>
...
...
@@ -951,6 +1189,75 @@ const cancelTask = () => {
padding-bottom
:
12px
;
}
.wait-result-div
{
height
:
250px
;
display
:
flex
;
flex-direction
:
column
;
justify-content
:
center
;
align-items
:
center
;
.loading-img
{
width
:
40px
;
height
:
40px
;
margin-bottom
:
18px
;
}
.desc
{
color
:
#999
;
margin-bottom
:
18px
;
margin-left
:
26px
;
}
:deep
(
.el-icon.failed
)
{
color
:
#E63E33
;
width
:
32px
;
height
:
32px
;
margin-bottom
:
8px
;
svg
{
width
:
32px
;
height
:
32px
;
}
}
.error-desc
{
color
:
#E63E33
;
font-size
:
14px
;
line-height
:
21px
;
margin-bottom
:
8px
;
font-weight
:
600
;
}
}
.analysis-result-main
{
min-height
:
250px
;
.value-desc
{
font-size
:
14px
;
color
:
#212121
;
line-height
:
21px
;
}
}
.step-result
{
:deep(.v-content-wrap)
{
height
:
100%
;
.el-card__body
{
height
:
calc
(
100%
-
50px
)
!important
;
.card-body-content
{
height
:
100%
;
}
}
.table_tool_wrap
{
padding
:
0px
;
}
}
}
:deep
(
.custom-form
)
{
align-items
:
flex-start
;
...
...
src/views/data_anonymization/anonTaskStepTwo.vue
View file @
2aa70cc
...
...
@@ -12,6 +12,7 @@ import {
validateAnonRule
,
}
from
'@/api/modules/dataAnonymization'
;
import
{
useValidator
}
from
'@/hooks/useValidator'
;
import
{
cloneDeep
}
from
'lodash-es'
;
const
props
=
defineProps
({
fieldTypeList
:
{
...
...
@@ -460,7 +461,7 @@ const drawerBtnClick = async (btn, info) => {
proxy
.
$ElMessage
.
error
(
'K匿名泛化与脱敏规则不能同时为空'
);
return
;
}
if
((
info
.
fieldTypeCode
==
'int'
||
info
.
fieldTypeCode
==
'decimal'
||
info
.
fieldTypeCode
==
'tinyint'
))
{
if
(
!
(
info
.
fieldTypeCode
==
'int'
||
info
.
fieldTypeCode
==
'decimal'
||
info
.
fieldTypeCode
==
'tinyint'
))
{
if
(
info
.
desensitiveRuleCode
==
'ROUNDING'
)
{
proxy
.
$ElMessage
.
error
(
'数值类型字段的脱敏规则不能设置取整'
);
return
;
...
...
@@ -1037,7 +1038,7 @@ const getStepTwoConfigInfo = async () => {
await
privacyFormRef
.
value
?.
ruleFormRef
?.
validate
();
// 验证通过
return
{
anonPrivacyMode
:
privacyFormRef
.
value
?.
formInline
,
anonPrivacyMode
:
cloneDeep
(
privacyFormRef
.
value
?.
formInline
)
,
anonTaskRules
:
ruleModelTableInfo
.
value
.
data
};
}
catch
(
error
)
{
...
...
@@ -1046,8 +1047,43 @@ const getStepTwoConfigInfo = async () => {
}
}
/** 字段改变,可能是切换了表,需要清空规则配置。判断 第一步到第二步时,如果字段列表中与字段脱敏规则中的字段不匹配,应清空,并同时清空T接近字段。 */
const
updateNextStepRules
=
()
=>
{
let
deleteFieldNames
:
string
[]
=
[];
ruleModelTableInfo
.
value
.
data
=
ruleModelTableInfo
.
value
.
data
.
filter
(
rule
=>
{
if
(
!
props
.
fieldNameList
?.
some
(
v
=>
v
.
enName
==
rule
.
fieldName
))
{
deleteFieldNames
.
push
(
rule
.
fieldName
);
return
false
;
}
return
true
;
});
if
(
deleteFieldNames
?.
length
)
{
let
optionsList
=
ruleModelTableInfo
.
value
.
data
?.
map
(
v
=>
{
return
{
fieldName
:
v
.
fieldName
,
fieldChName
:
v
.
fieldChName
}
})
||
[];
privacyFormItems
.
value
[
2
].
children
[
0
].
options
=
optionsList
;
privacyFormItems
.
value
[
3
].
children
[
0
].
options
=
optionsList
;
let
formInline
=
privacyFormRef
.
value
?.
formInline
;
privacyFormItems
.
value
.
forEach
((
item
,
index
)
=>
{
item
.
default
=
formInline
[
item
.
field
];
if
(
item
.
default
==
'Y'
)
{
item
.
children
?.
forEach
(
child
=>
{
child
.
default
=
formInline
[
child
.
field
];
if
((
child
.
field
==
'tcFieldName'
||
child
.
field
==
'ldFieldName'
)
&&
deleteFieldNames
.
includes
(
child
.
default
))
{
child
.
default
=
''
}
});
}
})
}
}
defineExpose
({
getStepTwoConfigInfo
getStepTwoConfigInfo
,
updateNextStepRules
})
</
script
>
...
...
src/views/data_anonymization/resultProcess.vue
View file @
2aa70cc
...
...
@@ -12,7 +12,9 @@ import {
deleteAnonTask
,
}
from
'@/api/modules/dataAnonymization'
;
import
{
useValidator
}
from
'@/hooks/useValidator'
;
import
useDataAnonymizationStore
from
"@/store/modules/dataAnonymization"
;
const
anonymizationStore
=
useDataAnonymizationStore
();
const
router
=
useRouter
()
const
{
proxy
}
=
getCurrentInstance
()
as
any
;
const
{
required
}
=
useValidator
();
...
...
@@ -70,8 +72,8 @@ const tableInfo = ref({
width
:
180
,
fixed
:
'right'
,
btns
:
(
scope
)
=>
{
return
[
{
label
:
"编辑"
,
value
:
"edit"
,
disabled
:
scope
.
row
.
status
==
'R'
,
click
:
(
scope
)
=>
{
return
[{
label
:
"编辑"
,
value
:
"edit"
,
click
:
(
scope
)
=>
{
router
.
push
({
name
:
'anonTaskCreate'
,
query
:
{
...
...
@@ -92,11 +94,12 @@ const tableInfo = ref({
});
}
},
{
label
:
"删除"
,
value
:
"delete"
,
disabled
:
scope
.
row
.
status
==
'R'
,
click
:
(
scope
)
=>
{
label
:
"删除"
,
value
:
"delete"
,
click
:
(
scope
)
=>
{
proxy
.
$openMessageBox
(
"此操作将永久删除, 是否继续?"
,
()
=>
{
let
guids
=
[
scope
.
row
.
guid
];
deleteAnonTask
(
guids
).
then
((
res
:
any
)
=>
{
if
(
res
?.
code
==
proxy
.
$passCode
)
{
page
.
value
.
curr
=
1
;
getTableData
();
proxy
.
$ElMessage
({
type
:
"success"
,
...
...
@@ -169,8 +172,17 @@ const handleCreate = () => {
onBeforeMount
(()
=>
{
toSearch
({});
anonymizationStore
.
setIsAnonPageRefresh
(
false
);
})
onActivated
(()
=>
{
if
(
anonymizationStore
.
isAnonPageRefresh
)
{
//如果是首次加载,则不需要调用
page
.
value
.
curr
=
1
;
getTableData
();
anonymizationStore
.
setIsAnonPageRefresh
(
false
);
}
});
</
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