Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
N
nse-ui
概览
Overview
Details
Activity
Cycle Analytics
版本库
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
问题
0
Issues
0
列表
Board
标记
里程碑
合并请求
0
Merge Requests
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
Snippets
成员
Members
Collapse sidebar
Close sidebar
活动
图像
聊天
创建新问题
作业
提交
Issue Boards
Open sidebar
吴超
nse-ui
Commits
9e370fdb
Commit
9e370fdb
authored
Aug 25, 2025
by
周海峰
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
加密设置
parent
434380b0
隐藏空白字符变更
内嵌
并排
正在显示
4 个修改的文件
包含
559 行增加
和
214 行删除
+559
-214
src/api/classification/classification.js
+75
-0
src/views/classification/Classification/index.vue
+43
-110
src/views/classification/Classification/modules/EncryptionRuleDialog.vue
+116
-73
src/views/classification/Classification/modules/EncryptionTab.vue
+325
-31
没有找到文件。
src/api/classification/classification.js
View file @
9e370fdb
...
...
@@ -1172,3 +1172,77 @@ export function save(data) {
})
}
/**
* 单字段加密
* @param {*} data
*{
* columnName: "post_name"
* columnSize: "50"
* columnType: "VARCHAR"
* dataSystemId: "ff8081819882f3cd019883210d130015"
* flag: 0
* map: {
* dataSystemId: "ff8081819882f3cd019883210d130015"
* projectId: "fda50ea9-b7fa-4fe4-b368-eebeffded6b6"
* map: {
* ry.sys_post.post_name: {
* columnType: "VARCHAR",
* columnSize: "50",
* describe_info: "66",
* encryptionSecretKeyId: "ff80818198cf9ab10198db90819905ea",
* flag: "1"
* }
* }
* primaryKeys: ["post_id"]
* projectId: "fda50ea9-b7fa-4fe4-b368-eebeffded6b6"
* schema: "ry"
* secretKeyId: "ff80818198cf9ab10198db90819905ea"
* tableName: "sys_post"
*}
* @returns {"code":"POP_00014","msg":"成功。","totalCount":0,"flag":true,"data":null}
*/
export
function
checkSingleEncOrDecColumn
(
data
)
{
return
request
({
url
:
'/core/encryption/checkSingleEncOrDecColumn'
,
method
:
'POST'
,
data
:
data
})
}
/**
* 加载列信息
* @param {*} data
*{
* columnName: "post_name"
* columnSize: "50"
* columnType: "VARCHAR"
* dataSystemId: "ff8081819882f3cd019883210d130015"
* flag: 0
* map: {
* dataSystemId: "ff8081819882f3cd019883210d130015"
* projectId: "fda50ea9-b7fa-4fe4-b368-eebeffded6b6"
* map: {
* ry.sys_post.post_name: {
* columnType: "VARCHAR",
* columnSize: "50",
* describe_info: "66",
* encryptionSecretKeyId: "ff80818198cf9ab10198db90819905ea",
* flag: "1"
* }
* }
* primaryKeys: ["post_id"]
* projectId: "fda50ea9-b7fa-4fe4-b368-eebeffded6b6"
* schema: "ry"
* secretKeyId: "ff80818198cf9ab10198db90819905ea"
* tableName: "sys_post"
*}
*
* @returns {"code":"POP_00014","msg":"成功。","totalCount":0,"flag":true,"data":null}
*/
export
function
loadingColumn
(
data
)
{
return
request
({
url
:
'/core/encryption/loadingColumn'
,
method
:
'POST'
,
data
:
data
})
}
\ No newline at end of file
src/views/classification/Classification/index.vue
View file @
9e370fdb
<
script
setup
name=
"Classification"
>
import
{
ElMessageBox
,
ElMessage
}
from
'element-plus'
import
{
ref
,
toRefs
,
reactive
,
getCurrentInstance
,
proxyRefs
,
onMounted
,
watch
}
from
'vue'
import
{
ref
,
toRefs
,
reactive
,
getCurrentInstance
,
proxyRefs
,
onMounted
,
watch
,
provide
,
nextTick
}
from
'vue'
import
TreeFilter
from
'./modules/TreeFilter.vue'
import
BasicInfoTab
from
'./modules/BasicInfoTab.vue'
import
TableInfoTab
from
'./modules/TableInfoTab.vue'
import
StructureTab
from
'./modules/StructureTab.vue'
import
EncryptionTab
from
'./modules/EncryptionTab.vue'
import
{
changeRoute
}
from
'@/utils/switchRoute'
import
{
useRouter
}
from
'vue-router'
import
useAppStore
from
'@/store/modules/app'
import
usePermissionStore
from
'@/store/modules/permission'
import
{
query
,
getClassifyEnable
,
getGlobalOriginalConfig
,
changeGlobalOriginalConfig
,
queryDatasystemInfo
,
queryShemas
,
queryTables
,
querytableInfo
,
getfield
,
queryOriginalList
,
queryEncryptionList
save
}
from
'@/api/classification/classification.js'
import
{
id
}
from
'element-plus/es/locales.mjs'
const
route
=
useRoute
()
// 字段加密信息子组件列表
const
encryptionTabRef
=
ref
()
const
projectId
=
ref
(
''
)
// 树形数据
const
treeData
=
ref
([])
...
...
@@ -25,6 +23,7 @@ const basicInfoData = ref({})
const
activeTab
=
ref
(
'basic'
)
// 当前选中的节点数据
const
currentNodeData
=
ref
(
null
)
provide
(
'currentNodeData'
,
currentNodeData
)
const
currentNodeLevel
=
computed
(()
=>
{
if
(
!
currentNodeData
.
value
)
return
1
if
(
currentNodeData
.
value
.
type
===
'system'
)
return
1
...
...
@@ -36,8 +35,7 @@ const currentNodeLevel = computed(() => {
// 当前表结构数据 (匹配图片中的gen_table结构)
const
currentTableStructure
=
ref
([])
// 当前表字段加密配置
const
originalList
=
ref
([])
// 监听 currentNodeLevel 和 currentNodeData,一级节点时自动查详情
watch
([
currentNodeLevel
,
currentNodeData
,
activeTab
],
async
([
level
,
node
,
tab
])
=>
{
...
...
@@ -82,44 +80,10 @@ watch([currentNodeLevel, currentNodeData, activeTab], async ([level, node, tab])
//查询字段加密配置
if
(
level
===
4
&&
node
&&
tab
===
'encryption'
)
{
console
.
log
(
'查询字段加密配置'
,
node
)
// 查询字段原始值配置&字段加密配置
const
[
originalListRes
,
encryptionListRes
]
=
await
Promise
.
all
([
queryOriginalList
({
table_name
:
node
.
label
,
datasystem_id
:
node
.
parent
?.
parent
?.
tid
,
schema
:
node
.
parent
?.
parent
?.
label
,
projectId
:
projectId
.
value
}),
queryEncryptionList
({
table_name
:
node
.
label
,
datasystem_id
:
node
.
parent
?.
parent
?.
tid
,
schema
:
node
.
parent
?.
parent
?.
label
,
projectId
:
projectId
.
value
})
])
console
.
log
(
'encryptionListRes'
,
encryptionListRes
)
console
.
log
(
'originalListRes'
,
originalListRes
)
if
(
originalListRes
&&
originalListRes
.
data
)
{
// 处理字段加密配置
originalListRes
.
data
.
forEach
(
item
=>
{
const
encryptionItem
=
encryptionListRes
.
data
.
find
(
en
=>
en
.
fieldName
===
item
.
columnname
)
if
(
encryptionItem
)
{
item
.
maskingruleid
=
encryptionItem
.
encryptionIdTrue
item
.
maskingrulename
=
encryptionItem
.
encryptionTypeName
item
.
secretkeyId
=
encryptionItem
.
secretKey
item
.
secretkeyName
=
encryptionItem
.
encryptionTypeValue
item
.
flag
=
encryptionItem
.
flag
}
})
// 你可以将结果赋值到 basicInfoData 或其他变量
originalList
.
value
=
originalListRes
.
data
||
[]
}
nextTick
(()
=>
{
encryptionTabRef
.
value
.
getTableData
()
})
}
})
onMounted
(
async
()
=>
{
...
...
@@ -150,41 +114,41 @@ onMounted(async () => {
// 树节点点击处理
const
handleNodeClick
=
async
(
data
)
=>
{
currentNodeData
.
value
=
data
currentNodeData
.
value
=
data
// 2. 点击一层系统数据,查 schemas
if
(
data
.
type
===
'system'
)
{
activeTab
.
value
=
'basic'
const
res
=
await
queryShemas
({
dataSystemId
:
data
.
tid
,
dataType
:
data
.
dbtype
,
projectid
:
projectId
.
value
})
if
(
res
&&
res
.
data
)
{
data
.
children
=
res
.
data
.
map
(
schema
=>
({
id
:
uuid
(),
...
schema
,
type
:
'database'
,
label
:
schema
.
text
,
parent
:
data
,
children
:
[
{
id
:
uuid
(),
label
:
'表'
,
type
:
'category'
,
parent
:
{
...
schema
,
type
:
'database'
,
label
:
schema
.
text
,
parent
:
data
,
tid
:
data
.
tid
,
dbservername
:
schema
.
text
},
children
:
[]
}
]
}))
treeData
.
value
=
[...
treeData
.
value
]
// 触发视图更新
}
activeTab
.
value
=
'basic'
const
res
=
await
queryShemas
({
dataSystemId
:
data
.
tid
,
dataType
:
data
.
dbtype
,
projectid
:
projectId
.
value
})
if
(
res
&&
res
.
data
)
{
data
.
children
=
res
.
data
.
map
(
schema
=>
({
id
:
uuid
(),
...
schema
,
type
:
'database'
,
label
:
schema
.
text
,
parent
:
data
,
children
:
[
{
id
:
uuid
(),
label
:
'表'
,
type
:
'category'
,
parent
:
{
...
schema
,
type
:
'database'
,
label
:
schema
.
text
,
parent
:
data
,
tid
:
data
.
tid
,
dbservername
:
schema
.
text
},
children
:
[]
}
]
}))
treeData
.
value
=
[...
treeData
.
value
]
// 触发视图更新
}
}
// 3. 点击三层 category,查表
if
(
data
.
type
===
'category'
&&
data
.
parent
)
{
...
...
@@ -232,32 +196,6 @@ const handleDecryptChange = async (val) => {
}
}
// 批量加密
const
handleBatchEncrypt
=
()
=>
{
console
.
log
(
'批量加密'
,
currentNodeData
.
value
)
}
// 批量解密
const
handleBatchDecrypt
=
()
=>
{
console
.
log
(
'批量解密'
,
currentNodeData
.
value
)
}
// 删除多余列
const
handleDeleteColumns
=
()
=>
{
console
.
log
(
'删除多余列'
,
currentNodeData
.
value
)
}
const
handleSave
=
()
=>
{
console
.
log
(
'保存更改'
,
currentNodeData
.
value
)
}
// 编辑字段
const
handleEditField
=
(
field
)
=>
{
console
.
log
(
'编辑字段'
,
field
)
}
function
pageProjectManage
()
{
changeRoute
()
router
.
push
({
...
...
@@ -343,12 +281,7 @@ function uuid() {
<!-- 字段加密配置Tab (仅4级节点显示) -->
<el-tab-pane
label=
"字段加密配置"
name=
"encryption"
v-if=
"currentNodeLevel === 4"
>
<EncryptionTab
:table-data=
"originalList"
@
batch-encrypt=
"handleBatchEncrypt"
@
batch-decrypt=
"handleBatchDecrypt"
@
delete-columns=
"handleDeleteColumns"
@
save-changes=
"handleSave"
@
edit-field=
"handleEditField"
ref=
"encryptionTabRef"
v-if=
"activeTab === 'encryption'"
/>
</el-tab-pane>
...
...
src/views/classification/Classification/modules/EncryptionRuleDialog.vue
View file @
9e370fdb
...
...
@@ -10,30 +10,35 @@
<div
class=
"selection-section"
>
<!-- 左侧加密规则选择 -->
<div
class=
"rule-selection"
>
<div
class=
"section-title"
>
选择加密规则
</div>
<el-radio-group
v-model=
"selectedRule"
class=
"rule-radio-group"
>
<div
class=
"section-title gradient-title"
>
<i
class=
"el-icon-lock"
style=
"margin-right:6px;color:#409EFF;font-size:18px;"
></i>
选择加密规则
</div>
<el-radio-group
v-model=
"fieldData.maskingruleid"
class=
"rule-radio-group"
>
<el-radio
v-for=
"rule in encryptionRules"
:key=
"rule.id"
:
label
=
"rule.id"
:
value
=
"rule.id"
class=
"rule-radio"
>
{{
rule
.
name
}}
<span
style=
"color: aqua;"
>
(
{{
rule
.
list
.
length
||
0
}}
)
</span>
</el-radio>
</el-radio-group>
</div>
<!-- 分割线 -->
<div
class=
"divider"
></div>
<!-- 右侧加密密钥选择 -->
<div
class=
"key-selection"
>
<div
class=
"section-title"
>
选择加密密钥
</div>
<el-radio-group
v-model=
"selectedKey"
class=
"key-radio-group"
>
<div
class=
"section-title gradient-title"
>
<i
class=
"el-icon-key"
style=
"margin-right:6px;color:#67C23A;font-size:18px;"
></i>
选择加密密钥
</div>
<el-radio-group
v-model=
"fieldData.encryptionSecretKeyId"
@
change=
"handleKeyChange"
class=
"key-radio-group"
>
<el-radio
v-for=
"key in currentKeys"
:key=
"key.id"
:
label
=
"key.id"
:
value
=
"key.id"
class=
"key-radio"
>
{{
key
.
name
}}
...
...
@@ -48,18 +53,30 @@
<!-- 加密位置 -->
<div
class=
"config-item"
>
<span
class=
"required-label"
>
*加密位置:
</span>
<el-select
v-model=
"ruleConfig.positionType"
style=
"width: 120px"
>
<el-option
label=
"保留前"
value=
"prefix"
/>
<el-option
label=
"保留后"
value=
"suffix"
/>
<el-select
v-model=
"fieldData.keepfirst"
style=
"width: 120px"
>
<el-option
label=
"保留前"
value=
"0"
/>
<el-option
label=
"保留后"
value=
"1"
/>
<el-option
label=
"既保留前"
value=
"2"
/>
</el-select>
<el-input-number
v-model=
"
ruleConfig.position
"
v-model=
"
fieldData.encdigit
"
:min=
"0"
:max=
"100"
controls-position=
"right"
style=
"width: 100px; margin-left: 10px;"
/>
<span
class=
"unit"
>
位
</span>
<span
v-if=
"fieldData.keepfirst === '2'"
>
<span
class=
"unit"
>
又保留后
</span>
<el-input-number
v-model=
"fieldData.twoindex"
:min=
"0"
:max=
"100"
controls-position=
"right"
style=
"width: 100px; margin-left: 10px;"
/>
<span
class=
"unit"
>
位
</span>
</span>
</div>
</div>
<div
class=
"config-row"
>
...
...
@@ -67,7 +84,7 @@
<div
class=
"config-item"
>
<span
class=
"label"
>
源长度:
</span>
<el-input-number
v-model=
"
ruleConfig.sourceLength
"
v-model=
"
fieldData.columnSize
"
:min=
"0"
:max=
"1000"
controls-position=
"right"
...
...
@@ -90,7 +107,7 @@
</div>
</div>
<div
class=
"action-row"
>
<el-checkbox
v-model=
"
supportFuzzy
"
>
支持模糊
</el-checkbox>
<el-checkbox
v-model=
"
fieldData.isLike"
true-value=
"1"
false-value=
"0
"
>
支持模糊
</el-checkbox>
<div
class=
"action-buttons"
>
<el-button
@
click=
"resetRules"
>
重置规则
</el-button>
<el-button
type=
"primary"
@
click=
"confirmRules"
>
确定规则
</el-button>
...
...
@@ -102,8 +119,8 @@
</
template
>
<
script
setup
>
import
{
ref
,
computed
,
watch
}
from
'vue'
import
{
ref
,
computed
,
inject
,
onMounted
,
nextTick
}
from
'vue'
import
{
encryptionQuery
,
queryExtendColumnSize
}
from
'@/api/classification/classification.js'
const
props
=
defineProps
({
visible
:
{
type
:
Boolean
,
...
...
@@ -111,11 +128,29 @@ const props = defineProps({
},
fieldData
:
{
type
:
Object
,
default
:
()
=>
({})
default
:
()
=>
({
columnname
:
''
,
// 字段
columnSize
:
''
,
// 长度
realitycolumnsize
:
''
,
columnType
:
''
,
// 类型
note
:
''
,
maskingruleid
:
''
,
//加密规则
maskingrulename
:
''
,
encryptionSecretKeyId
:
''
,
// 密钥ID
secretkeyName
:
''
,
// 密钥名称
isLike
:
''
,
encdigit
:
''
,
keepfirst
:
''
,
twoindex
:
''
,
flag
:
"0"
})
}
})
const
emit
=
defineEmits
([
'update:visible'
,
'confirm'
])
// 获取父组件 provide 的 currentNodeData(响应式)
const
currentNodeData
=
inject
(
'currentNodeData'
)
// console.log(' currentNodeData.value', currentNodeData.value)
const
emit
=
defineEmits
([
'update:visible'
,
'confirm'
,
'reset'
])
// 控制弹窗显示
const
dialogVisible
=
computed
({
...
...
@@ -124,81 +159,70 @@ const dialogVisible = computed({
})
// 加密规则数据
const
encryptionRules
=
ref
([
{
id
:
'name'
,
name
:
'姓名加密规则'
},
{
id
:
'gender'
,
name
:
'性别加密规则'
}
])
// 加密密钥数据
const
encryptionKeys
=
ref
({
name
:
[
{
id
:
'name_key1'
,
name
:
'姓名加密密钥1'
},
{
id
:
'name_key2'
,
name
:
'姓名加密密钥2'
}
],
gender
:
[
{
id
:
'gender_key1'
,
name
:
'性别加密密钥1'
},
{
id
:
'gender_key2'
,
name
:
'性别加密密钥2'
}
]
})
// 当前选中的规则
const
selectedRule
=
ref
(
'name'
)
const
encryptionRules
=
ref
([])
// 当前选中的密钥
const
selectedKey
=
ref
(
''
)
// 当前显示的密钥列表
const
currentKeys
=
computed
(()
=>
{
return
encryptionKeys
.
value
[
selectedRule
.
value
]
||
[]
const
rule
=
encryptionRules
.
value
.
find
(
r
=>
r
.
id
===
props
.
fieldData
.
maskingruleid
)
props
.
fieldData
.
maskingrulename
=
rule
?
rule
.
name
:
''
return
rule
&&
rule
.
list
?
rule
.
list
.
map
(
key
=>
({
id
:
key
.
id
,
name
:
key
.
secret_key_name
}))
:
[]
})
// 加密配置
const
ruleConfig
=
ref
({
positionType
:
'prefix'
,
position
:
0
,
sourceLength
:
100
const
handleKeyChange
=
(
value
)
=>
{
const
selectedKey
=
currentKeys
.
value
.
find
(
key
=>
key
.
id
===
value
)
props
.
fieldData
.
secretkeyName
=
selectedKey
?
selectedKey
.
name
:
''
}
onMounted
(
async
()
=>
{
const
res
=
await
encryptionQuery
()
if
(
res
&&
res
.
data
)
{
// 处理加密规则
encryptionRules
.
value
=
res
.
data
.
map
(
item
=>
({
id
:
item
.
id
,
name
:
item
.
encryption_name
,
list
:
item
.
list
||
[]
}))
}
})
// 加密后长度
const
encryptedLength
=
ref
(
''
)
// 是否支持模糊
const
supportFuzzy
=
ref
(
false
)
// 监听规则变化,自动选择第一个密钥
watch
(
selectedRule
,
(
newVal
)
=>
{
if
(
currentKeys
.
value
.
length
>
0
)
{
selectedKey
.
value
=
currentKeys
.
value
[
0
].
id
}
},
{
immediate
:
true
})
// 计算加密后长度
const
calculateLength
=
()
=>
{
const
calculateLength
=
async
()
=>
{
if
(
!
props
.
fieldData
||
!
props
.
fieldData
.
encryptionSecretKeyId
)
{
encryptedLength
.
value
=
''
return
}
// 这里应该是实际的加密长度计算逻辑
encryptedLength
.
value
=
Math
.
floor
(
ruleConfig
.
value
.
sourceLength
*
0.8
)
const
res
=
await
queryExtendColumnSize
({
projectid
:
currentNodeData
.
value
.
parent
?.
parent
?.
parent
?.
project_id
,
datasystemid
:
currentNodeData
.
value
.
parent
?.
parent
?.
tid
,
tablecat
:
currentNodeData
.
value
.
parent
?.
parent
?.
label
,
tablename
:
currentNodeData
.
value
.
label
,
columnname
:
props
.
fieldData
.
columnname
,
columnsize
:
String
(
props
.
fieldData
.
columnSize
),
columntype
:
props
.
fieldData
.
columnType
,
dbtype
:
currentNodeData
.
value
.
parent
?.
parent
?.
parent
?.
dbtype
,
islike
:
props
.
fieldData
.
isLike
,
encryptionsecretkeyid
:
props
.
fieldData
.
encryptionSecretKeyId
})
encryptedLength
.
value
=
res
.
data
?.
extendcolumnsize
}
// 重置规则
const
resetRules
=
()
=>
{
selectedRule
.
value
=
'name'
ruleConfig
.
value
=
{
positionType
:
'prefix'
,
position
:
0
,
sourceLength
:
100
}
encryptedLength
.
value
=
''
supportFuzzy
.
value
=
false
emit
(
'reset'
)
dialogVisible
.
value
=
false
}
// 确认规则
const
confirmRules
=
()
=>
{
emit
(
'confirm'
,
{
rule
:
selectedRule
.
value
,
key
:
selectedKey
.
value
,
config
:
ruleConfig
.
value
,
supportFuzzy
:
supportFuzzy
.
value
,
encryptedLength
:
encryptedLength
.
value
})
emit
(
'confirm'
)
dialogVisible
.
value
=
false
}
...
...
@@ -206,6 +230,11 @@ const confirmRules = () => {
const
handleClose
=
(
done
)
=>
{
done
()
}
defineExpose
({
calculateLength
})
</
script
>
<
style
scoped
>
...
...
@@ -239,9 +268,23 @@ const handleClose = (done) => {
color
:
#333
;
}
.gradient-title
{
background
:
linear-gradient
(
90deg
,
#e3f0ff
0%
,
#f5fff7
100%
);
border-radius
:
6px
;
padding
:
6px
12px
;
display
:
flex
;
align-items
:
center
;
font-size
:
15px
;
font-weight
:
bold
;
color
:
#333
;
margin-bottom
:
15px
;
}
.rule-radio-group
,
.key-radio-group
{
display
:
flex
;
flex-direction
:
column
;
align-items
:
flex-start
;
margin-left
:
24px
;
}
.rule-radio
,
.key-radio
{
...
...
src/views/classification/Classification/modules/EncryptionTab.vue
View file @
9e370fdb
...
...
@@ -43,8 +43,8 @@
<el-table-column
prop=
"maskingrulename"
label=
"加密算法"
width=
"120"
align=
"center"
/>
<el-table-column
label=
"密钥"
width=
"120"
align=
"center"
>
<
template
#
default=
"{ row }"
>
<el-button
v-if=
"row.
secretkeyName"
link
type=
"primary"
>
{{
row
.
secretkeyName
}}
</el-button>
<el-button
v-
else
link
type=
"primary"
@
click=
"openEncryptionDialog(row)"
>
设置
</el-button>
<el-button
v-if=
"row.
typename!=='DATETIME' && row.primarykey !== '1' && row.secretkeyName"
link
type=
"primary"
@
click=
"openEncryptionDialog(row)"
>
{{
row
.
secretkeyName
}}
</el-button>
<el-button
v-
if=
"row.typename!=='DATETIME' && row.primarykey !== '1' && !row.secretkeyName"
link
type=
"primary"
@
click=
"openEncryptionDialog(row)"
>
设置
</el-button>
</
template
>
</el-table-column>
<el-table-column
label=
"状态"
width=
"100"
align=
"center"
>
...
...
@@ -55,8 +55,8 @@
<!-- 操作 -->
<el-table-column
label=
"操作"
width=
"100"
align=
"center"
>
<
template
#
default=
"{ row }"
>
<el-button
v-if=
"row.secretkeyName && ['1', '5', '44', '10', '11'].includes(row.flag)"
type=
"primary"
size=
"small"
@
click=
"handle
Edi
tField(row)"
>
解密
</el-button>
<el-button
v-if=
"row.secretkeyName && ['4', '6', '7', '9', '12'].includes(row.flag)"
type=
"primary"
size=
"small"
@
click=
"handleE
di
tField(row)"
>
加密
</el-button>
<el-button
v-if=
"row.secretkeyName && ['1', '5', '44', '10', '11'].includes(row.flag)"
type=
"primary"
size=
"small"
@
click=
"handle
UnEncryp
tField(row)"
>
解密
</el-button>
<el-button
v-if=
"row.secretkeyName && ['4', '6', '7', '9', '12'].includes(row.flag)"
type=
"primary"
size=
"small"
@
click=
"handleE
ncryp
tField(row)"
>
加密
</el-button>
</
template
>
</el-table-column>
<!-- 源长度 -->
...
...
@@ -70,10 +70,10 @@
<el-table-column
label=
"描述信息"
align=
"left"
fixed=
"right"
>
<
template
#
default=
"{ row }"
>
<el-input
v-if=
"row.typename!=='DATETIME' && row.primarykey !== '1'"
v-model=
"row.description"
size=
"small"
:disabled=
"!isEditing"
@
change=
"handleDescriptionChange(row)"
/>
</
template
>
</el-table-column>
...
...
@@ -98,25 +98,86 @@
<EncryptionRuleDialog
ref=
"encryptionRuleDialogRef"
v-model:visible=
"showEncryptionDialog"
:field-data=
"currentField"
@
confirm=
"handleRuleConfirm"
@
reset=
"handleRuleReset"
/>
</div>
</template>
<
script
setup
>
import
{
ref
,
computed
,
reactive
}
from
'vue'
import
{
ref
,
computed
,
reactive
,
inject
,
nextTick
}
from
'vue'
import
EncryptionRuleDialog
from
'./EncryptionRuleDialog.vue'
import
{
ElMessageBox
}
from
'element-plus'
import
{
queryOriginalList
,
queryEncryptionList
,
hasRedundanceColumns
,
queryIsLike
,
queryEncDigit
,
save
,
delTableColumn
,
checkSingleEncOrDecColumn
,
loadingColumn
}
from
'@/api/classification/classification.js'
const
props
=
defineProps
({
tableData
:
{
type
:
Array
,
required
:
true
,
default
:
()
=>
[]
}
//
tableData: {
//
type: Array,
//
required: true,
//
default: () => []
//
}
})
// 获取父组件 provide 的 currentNodeData(响应式)
const
currentNodeData
=
inject
(
'currentNodeData'
)
const
encryptionRuleDialogRef
=
ref
(
null
)
/**
* 表格数据
*/
const
tableData
=
ref
([])
/**
* 缓存一份tableData,用于比较是否有修改
*/
const
tableDataCache
=
ref
([])
/**
* 获取表格数据
*/
const
getTableData
=
async
()
=>
{
const
node
=
currentNodeData
.
value
// 查询字段原始值配置&字段加密配置
const
[
originalListRes
,
encryptionListRes
]
=
await
Promise
.
all
([
queryOriginalList
({
table_name
:
node
.
label
,
datasystem_id
:
node
.
parent
?.
parent
?.
tid
,
schema
:
node
.
parent
?.
parent
?.
label
,
projectId
:
node
.
parent
?.
parent
?.
parent
?.
project_id
}),
queryEncryptionList
({
table_name
:
node
.
label
,
datasystem_id
:
node
.
parent
?.
parent
?.
tid
,
schema
:
node
.
parent
?.
parent
?.
label
,
projectId
:
node
.
parent
?.
parent
?.
parent
?.
project_id
})
])
if
(
originalListRes
&&
originalListRes
.
data
)
{
// 处理字段加密配置
originalListRes
.
data
.
forEach
(
item
=>
{
const
encryptionItem
=
encryptionListRes
.
data
.
find
(
en
=>
en
.
fieldName
===
item
.
columnname
)
if
(
encryptionItem
)
{
item
.
maskingruleid
=
encryptionItem
.
encryptionIdTrue
item
.
maskingrulename
=
encryptionItem
.
encryptionTypeName
item
.
secretkeyId
=
encryptionItem
.
secretKey
.
id
// 编辑保存时,需要判断是否改变
item
.
secretkeyName
=
encryptionItem
.
encryptionTypeValue
item
.
flag
=
encryptionItem
.
flag
item
.
description
=
encryptionItem
.
describe_info
||
''
,
// 编辑保存时,需要判断是否改变
item
.
isLike
=
encryptionItem
.
isLike
,
// 编辑保存时,需要判断是否改变
item
.
encdigit
=
encryptionItem
.
encdigit
,
// 编辑保存时,需要判断是否改变
item
.
keepfirst
=
encryptionItem
.
keepfirst
,
// 编辑保存时,需要判断是否改变
item
.
twoindex
=
encryptionItem
.
twoindex
// 编辑保存时,需要判断是否改变
}
})
tableData
.
value
=
originalListRes
.
data
||
[]
}
// 缓存一份tableData,用于比较是否有修改
tableDataCache
.
value
=
JSON
.
parse
(
JSON
.
stringify
(
tableData
.
value
))
}
// 状态标识对象数组
const
encryptFlag
=
[
{
value
:
'-2'
,
label
:
'解密中'
},
...
...
@@ -155,22 +216,76 @@ const tableRowClassName = ({ row, rowIndex }) => {
return
row
.
status
===
'encrypted'
?
'encrypted-row'
:
''
}
// 处理搜索
const
handleSearch
=
()
=>
{
// 搜索逻辑已在计算属性中实现
}
// 切换编辑模式
const
toggleEditMode
=
()
=>
{
isEditing
.
value
=
!
isEditing
.
value
}
// 处理描述信息变更
const
handleDescriptionChange
=
(
row
)
=>
{
emit
(
'update-field'
,
row
)
/**
* 处理单个字段加密
* @param row
*/
const
handleEncryptField
=
async
(
row
)
=>
{
// 处理加密逻辑
const
schema
=
currentNodeData
.
value
.
parent
?.
parent
?.
label
const
tableName
=
currentNodeData
.
value
.
label
const
key
=
`
${
schema
}
.
${
tableName
}
.
${
row
.
columnname
}
`
const
params
=
{
columnName
:
row
.
columnname
,
columnSize
:
String
(
row
.
columnsize
),
columnType
:
row
.
typename
,
dataSystemId
:
currentNodeData
.
value
.
parent
?.
parent
?.
tid
,
flag
:
0
,
map
:
{
dataSystemId
:
currentNodeData
.
value
.
parent
?.
parent
?.
tid
,
projectId
:
currentNodeData
.
value
.
parent
?.
parent
?.
parent
?.
project_id
,
map
:
{
[
key
]:
{
columnType
:
row
.
typename
,
columnSize
:
String
(
row
.
columnsize
),
describe_info
:
row
.
description
||
''
,
encryptionSecretKeyId
:
row
.
secretkeyId
,
flag
:
row
.
flag
||
'1'
}
}
},
primaryKeys
:
tableData
.
value
.
filter
(
item
=>
item
.
primarykey
===
'1'
).
map
(
item
=>
item
.
columnname
),
projectId
:
currentNodeData
.
value
.
parent
?.
parent
?.
parent
?.
project_id
,
schema
:
schema
,
secretKeyId
:
row
.
secretkeyId
,
tableName
:
tableName
}
const
result
=
await
checkSingleEncOrDecColumn
(
params
)
if
(
result
&&
result
.
code
===
'POP_00014'
&&
result
.
flag
)
{
const
loadingResult
=
await
loadingColumn
(
params
)
if
(
loadingResult
&&
loadingResult
.
code
===
'POP_00014'
&&
loadingResult
.
flag
)
{
// 重新获取表格数据
await
getTableData
()
// 退出编辑模式
isEditing
.
value
=
false
}
else
{
ElMessageBox
.
alert
(
loadingResult
?
loadingResult
.
message
:
'加密失败,请重试'
,
'错误'
,
{
confirmButtonText
:
'确定'
,
type
:
'error'
})
}
}
else
{
ElMessageBox
.
alert
(
result
?
result
.
message
:
'加密失败,请重试'
,
'错误'
,
{
confirmButtonText
:
'确定'
,
type
:
'error'
})
}
}
/**
* 处理单个字段解密
* @param row
*/
const
handleUnEncryptField
=
(
row
)
=>
{
// 处理解密逻辑
}
// 批量加密
const
handleBatchEncrypt
=
()
=>
{
...
...
@@ -183,17 +298,102 @@ const handleBatchDecrypt = () => {
}
// 删除多余列
const
handleDeleteColumns
=
()
=>
{
emit
(
'delete-columns'
)
const
handleDeleteColumns
=
async
()
=>
{
const
res
=
await
delTableColumn
({
projectId
:
currentNodeData
.
value
.
parent
?.
parent
?.
parent
?.
project_id
,
dataSystemId
:
currentNodeData
.
value
.
parent
?.
parent
?.
tid
,
schema
:
currentNodeData
.
value
.
parent
?.
parent
?.
label
,
tableName
:
currentNodeData
.
value
.
label
})
if
(
res
&&
res
.
code
===
'POP_00014'
&&
res
.
flag
)
{
ElMessageBox
.
alert
(
'删除成功'
,
'成功'
,
{
confirmButtonText
:
'确定'
,
type
:
'success'
})
// 重新获取表格数据
await
getTableData
()
}
else
{
ElMessageBox
.
alert
(
res
?
res
.
message
:
'删除失败,请重试'
,
'错误'
,
{
confirmButtonText
:
'确定'
,
type
:
'error'
})
}
}
const
handleSave
=
()
=>
{
emit
(
'save-changes'
)
/**
* 保存修改
*/
const
handleSave
=
async
()
=>
{
// 判断数据是否有修改
const
changedData
=
{}
let
hasChanges
=
false
tableData
.
value
.
forEach
(
current
=>
{
const
original
=
tableDataCache
.
value
.
find
(
item
=>
item
.
columnname
===
current
.
columnname
)
if
(
original
)
{
// console.log('检测到字段变更:', current.columnname)
// console.log('检测到字段变更:', current)
// console.log('检测到字段变更:', original)
const
fieldsToCompare
=
[
'secretkeyId'
,
'description'
,
'isLike'
,
'encdigit'
,
'keepfirst'
,
'twoindex'
]
const
isChanged
=
fieldsToCompare
.
some
(
field
=>
current
[
field
]
!==
original
[
field
])
if
(
isChanged
)
{
// 构建key:schema#|#table#|#column格式
const
key
=
`
${
currentNodeData
.
value
.
parent
?.
parent
?.
label
}
#
|
#
$
{
currentNodeData
.
value
.
label
}
#
|
#
$
{
current
.
columnname
}
`
changedData[key] = {
columnType: current.typename,
describe_info: current.description || '',
encdigit: current.encdigit || '0',
encryptionSecretKeyId: current.secretkeyId || '',
flag: current.flag || '0',
note: current.remarks || '',
realitycolumnsize: String(current.columnsize || ''),
twoindex: current.twoindex || '0'
}
hasChanges = true
}
}
})
if (!hasChanges) {
ElMessageBox.alert('没有检测到更改', '提示', {
confirmButtonText: '确定',
type: 'info'
})
return
}
console.log('修改的字段changedData', changedData)
ElMessageBox.confirm('确认保存更改吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(async () => {
const res = await save({
projectId: currentNodeData.value.parent?.parent?.parent?.project_id,
datasystemid: currentNodeData.value.parent?.parent?.tid,
map: changedData
})
if (res && res.code === 'POP_00014' && res.flag) {
ElMessageBox.alert('保存成功', '成功', {
confirmButtonText: '确定',
type: 'success'
})
// 重新获取表格数据
await getTableData()
// 退出编辑模式
isEditing.value = false
} else {
ElMessageBox.alert(res ? res.message : '保存失败,请重试', '错误', {
confirmButtonText: '确定',
type: 'error'
})
}
})
}
// 过滤表格数据
const filteredTableData = computed(() => {
return
props
.
tableData
.
filter
(
item
=>
{
return
tableData.value
.filter(item => {
const matchesName = filterForm.columnname
? item.columnname.includes(filterForm.columnname)
: true
...
...
@@ -211,22 +411,116 @@ const filteredTableData = computed(() => {
const showEncryptionDialog = ref(false)
const currentField = ref({})
//
处理设置密钥
const
openEncryptionDialog
=
(
row
)
=>
{
//
点击密钥列的【密钥】或 设置
const openEncryptionDialog =
async
(row) => {
if(!isEditing.value) return
currentField
.
value
=
row
//验证table是否有重复的字段,如果重复提示
const hasRedundance = hasRedundanceColumns({
table: currentNodeData.value.label,
datasystemid: currentNodeData.value.parent?.parent?.tid,
schema: currentNodeData.value.parent?.parent?.label,
projectid: currentNodeData.value.parent?.parent?.parent?.project_id
})
if (hasRedundance && hasRedundance.code === 'POP_00014' && !hasRedundance.code.flag) {
ElMessageBox.alert('当前表存在重复字段,请先处理重复字段', '提示', {
confirmButtonText: '确定',
type: 'warning'
})
isEditing.value = false
return
}
// console.log('设置密钥openEncryptionDialog', row)
// console.log('当前字段:', row.columnname)
const [isLikeRes, encDigitRes] = await Promise.all([
queryIsLike({
tablename: currentNodeData.value.label,
datasystemid: currentNodeData.value.parent?.parent?.tid,
tablecat: currentNodeData.value.parent?.parent?.label,
projectid: currentNodeData.value.parent?.parent?.parent?.project_id,
columnname: row.columnname
}),
queryEncDigit({
tablename: currentNodeData.value.label,
datasystemid: currentNodeData.value.parent?.parent?.tid,
tablecat: currentNodeData.value.parent?.parent?.label,
projectid: currentNodeData.value.parent?.parent?.parent?.project_id,
columnname: row.columnname
})
])
currentField.value = {
// tablecat: row.tablecat, // 库名
// tablename: row.tablename, // 表名
columnname: row.columnname, // 字段
columnSize: Number(row.columnsize), // 长度
realitycolumnsize: Number(row.columnsize),
columnType: row.typename, // 类型
note: row.remarks,
maskingruleid: row.maskingruleid,//加密规则
maskingrulename: row.maskingrulename,//加密规则名称
encryptionSecretKeyId: row.secretkeyId, // 密钥ID
secretkeyName: row.secretkeyName, // 密钥名称
isLike: isLikeRes.data,
encdigit: Number(encDigitRes.data.encdigit),
keepfirst: encDigitRes.data.keepfirst,
twoindex: encDigitRes.data.twoindex,
flag: "0"
}
showEncryptionDialog.value = true
// 计算加密后长度
if(row.secretkeyId){
nextTick(() => {
encryptionRuleDialogRef.value.calculateLength()
})
}
}
const
handleRuleConfirm
=
(
ruleData
)
=>
{
console
.
log
(
'确认加密规则:'
,
ruleData
)
/**
* 确认加密规则-回调方法
*/
const handleRuleConfirm = () => {
// 更新表格数据或调用API
const field = tableData.value.find(f => f.columnname === currentField.value.columnname)
if (field) {
Object.assign(field, {
maskingruleid: currentField.value.maskingruleid,//加密规则
maskingrulename: currentField.value.maskingrulename,//加密规则名称
secretkeyId: currentField.value.encryptionSecretKeyId,
secretkeyName: currentField.value.secretkeyName, // 密钥名称
isLike: currentField.value.isLike,
encdigit: currentField.value.encdigit,
keepfirst: currentField.value.keepfirst,
twoindex: currentField.value.twoindex,
})
}
}
/**
* 重置加密规则
*/
const handleRuleReset = () => {
console.log('重置加密规则')
currentField.value.encryptionSecretKeyId = ''
const field = tableData.value.find(f => f.columnname === currentField.value.columnname)
if (field) {
field.maskingruleid = ''//加密规则
field.maskingrulename = ''//加密规则名称
field.secretkeyId = ''
field.secretkeyName = '' // 密钥名称
}
}
const handleTableMaskClick = () => {
ElMessageBox.alert('当前是只读状态,编辑可点击编辑按钮进行编辑!')
}
/**
* 暴露给父组件的数据
*/
defineExpose({
getTableData
})
</
script
>
<
style
scoped
>
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论