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
2b60e6ce
Commit
2b60e6ce
authored
Aug 24, 2025
by
周海峰
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
项目加密设置页面
parent
755912ad
显示空白字符变更
内嵌
并排
正在显示
8 个修改的文件
包含
543 行增加
和
196 行删除
+543
-196
src/api/classification/classification.js
+130
-1
src/views/classification/Classification/index.vue
+242
-103
src/views/classification/Classification/modules/BasicInfoTab.vue
+22
-8
src/views/classification/Classification/modules/EncryptionTab.vue
+93
-53
src/views/classification/Classification/modules/StructureTab.vue
+12
-18
src/views/classification/Classification/modules/TableInfoTab.vue
+13
-9
src/views/classification/Classification/modules/TreeFilter.vue
+28
-1
src/views/login.vue
+3
-3
没有找到文件。
src/api/classification/classification.js
View file @
2b60e6ce
...
...
@@ -889,6 +889,93 @@ export function queryExtendColumnSize(data) {
})
}
/**
* 查询加密类型
* @param {*} data
* @returns {"code":"200","msg":"","totalCount":0,"flag":true,"data":["jdbc","webhdfs"]}
*/
export
function
enctypes
(
data
)
{
return
request
({
url
:
'/core/tablerule/enctypes'
,
method
:
'post'
,
data
:
data
})
}
/**
* 查询后缀
* @param {*} data
* @returns
* {
* "code": "POP_00014",
* "msg": "成功。",
* "totalCount": 0,
* "flag": true,
* "data": {
* "cipherSuffix": "_cipher",
* "initialSuffix": "_initial",
* "copySuffix": "_copy"
* }
* }
*/
export
function
queryPostfix
(
data
)
{
return
request
({
url
:
'/core/encryption/queryPostfix'
,
method
:
'post'
,
data
:
data
})
}
/**
* 查询版本
* @param {*} data id
* @returns
* {
* "code": "POP_00014",
* "msg": "成功。",
* "totalCount": 0,
* "flag": true,
* "data": [
* {
* "value": "TaskVersion",
* "text": "任务版本",
* "flag": null,
* "filePath": null,
* "id": null,
* "dbType": null,
* "schmeid": null,
* "dataSystemId": null,
* "tid": null
* },
* {
* "value": "null",
* "text": "无版本",
* "flag": null,
* "filePath": null,
* "id": null,
* "dbType": null,
* "schmeid": null,
* "dataSystemId": null,
* "tid": null
* }
* ]
* }
*/
export
function
queryversion
(
data
)
{
return
request
({
url
:
'/core/fieldscopedata/queryversion'
,
method
:
'post'
,
data
:
data
})
}
//=========== 点击字段的设置===========开始
/**
...
...
@@ -1037,9 +1124,51 @@ export function encryptionQuery(data) {
return
request
({
url
:
'/core/encryption/query'
,
method
:
'get'
,
data
:
data
query
:
data
})
}
//=========== 点击字段的设置===========结束
/**
* 删除多余列(表字段)
* @param {*} data
* @returns
*/
export
function
delTableColumn
(
data
)
{
return
request
({
url
:
'/switchfield/delTableColumn'
,
method
:
'POST'
,
data
:
data
})
}
/**
* 保存加密配置
* @param {*} data
* {
* datasystemid: '',
* projectId: '',
* map: {
* ry#|#sys_user#|#dept_id: {
* columnType: "BIGINT",
* describe_info: "11",
* encdigit: "0",
* encryptionSecretKeyId: "",
* flag: "0",
* note: "部门ID",
* realitycolumnsize: "19",
* twoindex: "0"
* }
* }
* @returns
*/
export
function
save
(
data
)
{
return
request
({
url
:
'/core/encryptionconfig/save'
,
method
:
'POST'
,
data
:
data
})
}
src/views/classification/Classification/index.vue
View file @
2b60e6ce
<
script
setup
name=
"Classification"
>
import
{
ref
,
toRefs
,
reactive
,
getCurrentInstance
,
proxyRefs
,
onMounted
}
from
'vue'
import
{
ElMessageBox
,
ElMessage
}
from
'element-plus'
import
{
ref
,
toRefs
,
reactive
,
getCurrentInstance
,
proxyRefs
,
onMounted
,
watch
}
from
'vue'
import
TreeFilter
from
'./modules/TreeFilter.vue'
import
BasicInfoTab
from
'./modules/BasicInfoTab.vue'
import
TableInfoTab
from
'./modules/TableInfoTab.vue'
...
...
@@ -9,68 +10,22 @@ import { changeRoute } from '@/utils/switchRoute'
import
{
useRouter
}
from
'vue-router'
import
useAppStore
from
'@/store/modules/app'
import
usePermissionStore
from
'@/store/modules/permission'
const
appStore
=
useAppStore
()
const
permissionStore
=
usePermissionStore
()
const
router
=
useRouter
()
const
{
proxy
}
=
getCurrentInstance
()
import
{
query
,
getClassifyEnable
,
getGlobalOriginalConfig
,
changeGlobalOriginalConfig
,
queryDatasystemInfo
,
queryShemas
,
queryTables
,
querytableInfo
,
getfield
,
queryOriginalList
,
queryEncryptionList
}
from
'@/api/classification/classification.js'
const
route
=
useRoute
()
const
projectId
=
ref
(
''
)
onMounted
(()
=>
{
projectId
.
value
=
proxy
.
$route
.
query
.
projectId
console
.
log
(
'projectId'
,
projectId
.
value
)
})
// const props = defineProps({
// projectId: String, // 主键
// })
// 树形数据
const
treeData
=
ref
([
{
id
:
'system'
,
label
:
'若依配测系统'
,
type
:
'system'
,
children
:
[
{
id
:
'database'
,
label
:
'ry'
,
type
:
'database'
,
children
:
[
{
id
:
'tables'
,
label
:
'表'
,
type
:
'category'
,
children
:
[
{
id
:
'gen_table'
,
label
:
'gen_table'
,
type
:
'table'
},
{
id
:
'gen_table_column'
,
label
:
'gen_table_column'
,
type
:
'table'
},
{
id
:
'sys_config'
,
label
:
'sys_config'
,
type
:
'table'
},
{
id
:
'sys_dept'
,
label
:
'sys_dept'
,
type
:
'table'
},
{
id
:
'sys_dict_data'
,
label
:
'sys_dict_data'
,
type
:
'table'
},
{
id
:
'sys_dict_type'
,
label
:
'sys_dict_type'
,
type
:
'table'
},
{
id
:
'sys_job'
,
label
:
'sys_job'
,
type
:
'table'
},
{
id
:
'sys_job_log'
,
label
:
'sys_job_log'
,
type
:
'table'
},
{
id
:
'sys_logininfor'
,
label
:
'sys_logininfor'
,
type
:
'table'
},
{
id
:
'sys_menu'
,
label
:
'sys_menu'
,
type
:
'table'
},
{
id
:
'sys_notice'
,
label
:
'sys_notice'
,
type
:
'table'
},
{
id
:
'sys_oper_log'
,
label
:
'sys_oper_log'
,
type
:
'table'
},
{
id
:
'sys_post'
,
label
:
'sys_post'
,
type
:
'table'
},
{
id
:
'sys_role'
,
label
:
'sys_role'
,
type
:
'table'
},
{
id
:
'sys_role_dept'
,
label
:
'sys_role_dept'
,
type
:
'table'
},
{
id
:
'sys_role_menu'
,
label
:
'sys_role_menu'
,
type
:
'table'
},
{
id
:
'sys_user'
,
label
:
'sys_user'
,
type
:
'table'
},
{
id
:
'sys_user_online'
,
label
:
'sys_user_online'
,
type
:
'table'
},
{
id
:
'sys_user_post'
,
label
:
'sys_user_post'
,
type
:
'table'
},
{
id
:
'sys_user_role'
,
label
:
'sys_user_role'
,
type
:
'table'
}
]
}
]
}
]
}
])
const
treeData
=
ref
([])
// 基本信息数据(当前选中的数据源)
const
basicInfoData
=
ref
({})
// 当前激活的Tab
const
activeTab
=
ref
(
'basic'
)
// 当前选中的节点数据
const
currentNodeData
=
ref
(
null
)
const
currentNodeLevel
=
computed
(()
=>
{
if
(
!
currentNodeData
.
value
)
return
0
if
(
!
currentNodeData
.
value
)
return
1
if
(
currentNodeData
.
value
.
type
===
'system'
)
return
1
if
(
currentNodeData
.
value
.
type
===
'database'
)
return
2
if
(
currentNodeData
.
value
.
type
===
'category'
)
return
3
...
...
@@ -78,32 +33,204 @@ const currentNodeLevel = computed(() => {
return
0
})
// 是否启用解密插件
const
enableDecryptionPlugin
=
ref
(
false
)
// 当前表结构数据 (匹配图片中的gen_table结构)
const
currentTableStructure
=
ref
([])
// 当前表字段加密配置
const
originalList
=
ref
([])
// 当前激活的Tab
const
activeTab
=
ref
(
'basic'
)
// 监听 currentNodeLevel 和 currentNodeData,一级节点时自动查详情
watch
([
currentNodeLevel
,
currentNodeData
,
activeTab
],
async
([
level
,
node
,
tab
])
=>
{
if
(
level
===
1
&&
node
&&
tab
===
'basic'
)
{
const
res
=
await
queryDatasystemInfo
({
dataSystemId
:
node
.
tid
,
projectId
:
projectId
.
value
})
if
(
res
&&
res
.
data
)
{
// 你可以将结果赋值到 basicInfoData 或其他变量
basicInfoData
.
value
=
{
...
basicInfoData
.
value
,
...
res
.
data
}
}
}
// 当前表结构数据 (匹配图片中的gen_table结构)
const
currentTableStructure
=
ref
([
{
pk
:
''
,
fieldName
:
'business_name'
,
comment
:
'生成业务名'
,
fieldType
:
'VARCHAR'
,
length
:
'30'
,
precision
:
''
,
algorithm
:
''
},
{
pk
:
''
,
fieldName
:
'business_name_...'
,
comment
:
''
,
fieldType
:
'TEXT'
,
length
:
'65535'
,
precision
:
''
,
algorithm
:
''
},
{
pk
:
''
,
fieldName
:
'class_name'
,
comment
:
'实体类名称'
,
fieldType
:
'VARCHAR'
,
length
:
'100'
,
precision
:
''
,
algorithm
:
''
},
{
pk
:
''
,
fieldName
:
'create_by'
,
comment
:
'创建者'
,
fieldType
:
'VARCHAR'
,
length
:
'64'
,
precision
:
''
,
algorithm
:
''
},
{
pk
:
''
,
fieldName
:
'create_time'
,
comment
:
'创建时间'
,
fieldType
:
'DATETIME'
,
length
:
'19'
,
precision
:
''
,
algorithm
:
''
},
{
pk
:
''
,
fieldName
:
'function_author'
,
comment
:
'生成功能作者'
,
fieldType
:
'VARCHAR'
,
length
:
'50'
,
precision
:
''
,
algorithm
:
''
},
{
pk
:
''
,
fieldName
:
'function_name'
,
comment
:
'生成功能名'
,
fieldType
:
'VARCHAR'
,
length
:
'50'
,
precision
:
''
,
algorithm
:
''
},
{
pk
:
''
,
fieldName
:
'gen_path'
,
comment
:
'生成路径(不填...'
,
fieldType
:
'VARCHAR'
,
length
:
'200'
,
precision
:
''
,
algorithm
:
''
},
{
pk
:
''
,
fieldName
:
'gen_type'
,
comment
:
'生成代码方式(0...'
,
fieldType
:
'CHAR'
,
length
:
'1'
,
precision
:
''
,
algorithm
:
''
},
{
pk
:
''
,
fieldName
:
'module_name'
,
comment
:
'生成模块名'
,
fieldType
:
'VARCHAR'
,
length
:
'30'
,
precision
:
''
,
algorithm
:
''
}
])
// 查询表基本信息
if
(
level
===
4
&&
node
&&
tab
===
'basic'
)
{
console
.
log
(
'查询表基本信息'
,
node
)
const
res
=
await
querytableInfo
({
tableName
:
node
.
label
,
dataSystemId
:
node
.
parent
?.
parent
?.
tid
,
schema
:
node
.
parent
?.
parent
?.
label
,
flag
:
'1'
,
projectId
:
projectId
.
value
})
if
(
res
&&
res
.
data
)
{
// 你可以将结果赋值到 basicInfoData 或其他变量
basicInfoData
.
value
=
{...
res
.
data
}
}
}
// 查询表字段信息
if
(
level
===
4
&&
node
&&
tab
===
'structure'
)
{
console
.
log
(
'查询表字段信息'
,
node
)
const
res
=
await
getfield
({
tablename
:
node
.
label
,
datasystemid
:
node
.
parent
?.
parent
?.
tid
,
schema
:
node
.
parent
?.
parent
?.
label
,
taskid
:
''
})
if
(
res
&&
res
.
data
)
{
// 你可以将结果赋值到 basicInfoData 或其他变量
currentTableStructure
.
value
=
res
.
data
||
[]
}
}
//查询字段加密配置
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
||
[]
}
}
})
onMounted
(
async
()
=>
{
projectId
.
value
=
route
.
query
.
projectId
||
'df345570-d044-47b3-a2c6-0ff265f89b80'
if
(
projectId
.
value
)
{
// 1. 查询数据源列表
const
res
=
await
query
({
project_id
:
projectId
.
value
})
if
(
res
&&
res
.
data
)
{
treeData
.
value
=
res
.
data
.
map
(
item
=>
({
...
item
,
label
:
item
.
sysname
,
type
:
'system'
,
children
:
[
]
}))
// 赋值触发监听,默认查询第一个数据源的基本信息
currentNodeData
.
value
=
treeData
.
value
[
0
]
}
// 查询解密插件配置
const
configRes
=
await
getGlobalOriginalConfig
({
projectId
:
projectId
.
value
})
console
.
log
(
'解密插件配置'
,
configRes
)
if
(
configRes
)
{
enableDecryptionPlugin
.
value
=
configRes
.
data
===
1
}
}
})
// 树节点点击处理
const
handleNodeClick
=
(
data
)
=>
{
const
handleNodeClick
=
async
(
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
]
// 触发视图更新
}
}
// 3. 点击三层 category,查表
if
(
data
.
type
===
'category'
&&
data
.
parent
)
{
const
parentDb
=
data
.
parent
const
res
=
await
queryTables
({
dataSystemId
:
parentDb
.
tid
,
schema
:
parentDb
.
dbservername
})
if
(
res
&&
res
.
data
)
{
data
.
children
=
res
.
data
.
map
(
table
=>
({
...
table
,
label
:
table
.
showName
,
type
:
'table'
,
parent
:
data
}))
treeData
.
value
=
[...
treeData
.
value
]
}
}
}
// 是否启用解密插件
const
enableDecryptionPlugin
=
ref
(
true
)
// 解密插件变更处理
const
handleDecryptChange
=
async
(
val
)
=>
{
try
{
const
res
=
await
changeGlobalOriginalConfig
({
projectId
:
projectId
.
value
,
status
:
val
?
'1'
:
'0'
})
if
(
!
res
||
res
.
code
!==
'POP_00014'
||
!
res
.
flag
)
{
// 如果修改失败,回退到之前的值
enableDecryptionPlugin
.
value
=
!
val
ElMessageBox
.
alert
(
'修改解密插件配置失败,请重试'
,
'错误'
,
{
confirmButtonText
:
'确定'
,
type
:
'error'
})
}
}
catch
(
e
)
{
// 如果修改失败,回退到之前的值
enableDecryptionPlugin
.
value
=
!
val
// 可根据需要添加错误提示
ElMessageBox
.
alert
(
'修改解密插件配置失败,请重试'
,
'错误'
,
{
confirmButtonText
:
'确定'
,
type
:
'error'
})
}
}
// 批量加密
const
handleBatchEncrypt
=
()
=>
{
console
.
log
(
'批量加密'
,
currentNodeData
.
value
)
...
...
@@ -119,24 +246,45 @@ const handleDeleteColumns = () => {
console
.
log
(
'删除多余列'
,
currentNodeData
.
value
)
}
const
handleSave
=
()
=>
{
console
.
log
(
'保存更改'
,
currentNodeData
.
value
)
}
// 编辑字段
const
handleEditField
=
(
field
)
=>
{
console
.
log
(
'编辑字段'
,
field
)
}
const
openDecrypt
=
ref
(
false
)
function
pageProjectManage
()
{
function
pageProjectManage
()
{
changeRoute
()
router
.
push
({
path
:
'/project/Project'
})
}
defineExpose
({
// handleRedInk,
// handleVoid
})
const
getBreadcrumb
=
()
=>
{
const
result
=
[]
let
node
=
currentNodeData
.
value
while
(
node
)
{
result
.
unshift
({
label
:
node
.
label
})
node
=
node
.
parent
}
// 如果没有选中节点,默认显示系统
if
(
result
.
length
===
0
)
{
result
.
push
({
label
:
treeData
.
value
.
length
>
0
?
treeData
.
value
[
0
].
label
:
'数据源'
})
}
return
result
}
// 生成唯一标识符
function
uuid
()
{
return
'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
.
replace
(
/
[
xy
]
/g
,
function
(
c
)
{
var
r
=
Math
.
random
()
*
16
|
0
,
v
=
c
===
'x'
?
r
:
(
r
&
0x3
|
0x8
);
return
v
.
toString
(
16
);
});
}
</
script
>
<
template
>
...
...
@@ -145,34 +293,23 @@ defineExpose({
<template
#
title
>
返回项目管理
</
template
>
</PageTitle>
<div
class=
"app-container__body"
>
<div
class=
"flex-container content-container"
>
<div
class=
"left"
>
<el-card
class=
"image-card tree-container"
>
<TreeFilter
:tree-data=
"treeData"
@
node-click=
"handleNodeClick"
/>
</el-card>
</div>
<div
class=
"right flex1"
>
<el-card
class=
"image-card"
>
<div
class=
"header-section"
>
<div
class=
"breadcrumb flex-container justify-between align-center"
>
<el-breadcrumb
separator=
"/"
>
<el-breadcrumb-item>
若依配测系统
</el-breadcrumb-item>
<el-breadcrumb-item
v-if=
"currentNodeLevel >= 2"
>
ry
</el-breadcrumb-item>
<el-breadcrumb-item
v-if=
"currentNodeLevel >= 3"
>
表
</el-breadcrumb-item>
<el-breadcrumb-item
v-if=
"currentNodeLevel >= 4"
>
{{ currentNodeData?.label }}
</el-breadcrumb-item>
<el-breadcrumb-item
v-for=
"(item, $index) in getBreadcrumb()"
:key=
"$index"
>
{{ item.label }}
</el-breadcrumb-item>
</el-breadcrumb>
<el-checkbox
v-model=
"openDecrypt"
>
是否启用解密插件
</el-checkbox>
</div>
<div
class=
"radio-group"
v-if=
"currentNodeLevel === 4"
>
<el-radio-group
v-model=
"enableDecryptionPlugin"
>
<el-radio
:label=
"true"
>
启用解密插件
</el-radio>
<el-radio
:label=
"false"
>
不启用解密插件
</el-radio>
</el-radio-group>
<el-checkbox
v-model=
"enableDecryptionPlugin"
@
change=
"handleDecryptChange"
>
是否启用解密插件
</el-checkbox>
</div>
</div>
...
...
@@ -182,15 +319,15 @@ defineExpose({
<!-- 基本信息Tab -->
<el-tab-pane
label=
"基本信息"
name=
"basic"
>
<BasicInfoTab
:node-data=
"
currentNode
Data"
v-if=
"activeTab === 'basic' &&
currentNodeLevel === 1
"
:node-data=
"
basicInfo
Data"
v-if=
"activeTab === 'basic' &&
[1,2,3].includes(currentNodeLevel)
"
/>
<!-- 表信息Tab -->
<TableInfoTab
:node-data=
"
currentNode
Data"
:node-data=
"
basicInfo
Data"
v-if=
"activeTab === 'basic' && currentNodeLevel === 4"
/>
</el-tab-pane>
<!-- 数据结构Tab (仅4级节点显示) -->
...
...
@@ -204,10 +341,11 @@ defineExpose({
<!-- 字段加密配置Tab (仅4级节点显示) -->
<el-tab-pane
label=
"字段加密配置"
name=
"encryption"
v-if=
"currentNodeLevel === 4"
>
<EncryptionTab
:table-data=
"
currentTableStructure
"
:table-data=
"
originalList
"
@
batch-encrypt=
"handleBatchEncrypt"
@
batch-decrypt=
"handleBatchDecrypt"
@
delete-columns=
"handleDeleteColumns"
@
save-changes=
"handleSave"
@
edit-field=
"handleEditField"
v-if=
"activeTab === 'encryption'"
/>
...
...
@@ -241,6 +379,7 @@ defineExpose({
.left
{
.tree-container
{
width
:
300px
;
overflow-y
:
auto
;
//
内容超出滚动
}
}
.right
{
...
...
src/views/classification/Classification/modules/BasicInfoTab.vue
View file @
2b60e6ce
<
template
>
<div
class=
"basic-info-tab"
>
<el-descriptions
title=
"
系统基本信息
"
title=
""
border
:column=
"1"
size=
"medium"
>
<el-descriptions-item
label=
"项目"
>
若依配测系统
</el-descriptions-item>
<el-descriptions-item
label=
"数据源"
>
若依配测系统
</el-descriptions-item>
<el-descriptions-item
label=
"数据源类型"
>
MYSQL
</el-descriptions-item>
<el-descriptions-item
label=
"IP"
>
172.19.1.166
</el-descriptions-item>
<el-descriptions-item
label=
"管理的SCHEMA"
>
ry
</el-descriptions-item>
<el-descriptions-item
label=
"项目"
>
{{
nodeInfo
.
projectName
||
''
}}
</el-descriptions-item>
<el-descriptions-item
label=
"数据源"
>
{{
nodeInfo
.
datasystemName
||
''
}}
</el-descriptions-item>
<el-descriptions-item
label=
"数据源类型"
>
{{
nodeInfo
.
dbType
||
''
}}
</el-descriptions-item>
<el-descriptions-item
label=
"IP"
>
{{
nodeInfo
.
ip
||
''
}}
</el-descriptions-item>
<el-descriptions-item
label=
"管理的SCHEMA"
>
{{
nodeInfo
.
schema
||
''
}}
</el-descriptions-item>
<el-descriptions-item
label=
"字段数"
>
{{
nodeInfo
.
totalFiledNum
||
''
}}
</el-descriptions-item>
<el-descriptions-item
label=
"加密表数量"
>
{{
nodeInfo
.
encryptTableCount
||
''
}}
</el-descriptions-item>
<el-descriptions-item
label=
"加密字段数量"
>
{{
nodeInfo
.
encryptFiledCount
||
''
}}
</el-descriptions-item>
<el-descriptions-item
label=
"未加密字段数量"
>
{{
nodeInfo
.
unencryptTableCount
||
''
}}
</el-descriptions-item>
<el-descriptions-item
label=
"未加密字段数量"
>
{{
nodeInfo
.
unencryptFiledCount
||
''
}}
</el-descriptions-item>
</el-descriptions>
</div>
</
template
>
<
script
setup
>
// 可以留空,因为数据是静态的
import
{
computed
}
from
'vue'
const
props
=
defineProps
({
nodeData
:
{
type
:
Object
,
default
:
()
=>
({})
}
})
// 可根据不同级别节点展示不同内容
const
nodeType
=
computed
(()
=>
props
.
nodeData
?.
type
)
const
nodeInfo
=
computed
(()
=>
props
.
nodeData
||
{})
</
script
>
<
style
scoped
>
...
...
src/views/classification/Classification/modules/EncryptionTab.vue
View file @
2b60e6ce
...
...
@@ -5,51 +5,68 @@
<el-form
:inline=
"true"
:model=
"filterForm"
class=
"filter-form"
>
<el-form-item
label=
"字段名过滤:"
>
<el-input
v-model=
"filterForm.
fieldN
ame"
v-model=
"filterForm.
columnn
ame"
placeholder=
"字段名模糊搜索"
clearable
style=
"width: 200px;"
/>
</el-form-item>
<el-form-item
label=
"状态:"
>
<el-select
style=
"width: 200px;"
v-model=
"filterForm.
status
"
placeholder=
"全部"
clearable
>
<el-option
label=
"
已加密"
value=
"encrypted
"
/>
<el-option
label=
"未加密"
value=
"unencrypted
"
/>
<el-select
style=
"width: 200px;"
v-model=
"filterForm.
flag
"
placeholder=
"全部"
clearable
>
<el-option
label=
"
全部"
value=
"
"
/>
<el-option
v-for=
"item in encryptFlag"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value
"
/>
</el-select>
</el-form-item>
<el-form-item>
<
!--
<
el-form-item>
<el-button
type=
"primary"
@
click=
"handleSearch"
>
搜索
</el-button>
</el-form-item>
</el-form-item>
-->
</el-form>
</div>
<!-- 表格区域 -->
<div
class=
"table-wrapper"
style=
"position:relative;"
>
<el-table
:data=
"filteredTableData"
border
style=
"width: 100%; margin-top: 15px;"
max-height=
"500px"
:row-class-name=
"tableRowClassName"
>
<!-- 左浮动列 -->
<el-table-column
prop=
"pk"
label=
"主键"
width=
"60"
align=
"left"
fixed
/>
<el-table-column
prop=
"fieldName"
label=
"字段名"
width=
"150"
align=
"left"
fixed
/>
<el-table-column
prop=
"fieldType"
label=
"字段类型"
width=
"120"
align=
"center"
/>
<el-table-column
prop=
"length"
label=
"长度"
width=
"80"
align=
"center"
/>
<el-table-column
prop=
"algorithm"
label=
"加密算法"
width=
"120"
align=
"center"
/>
<el-table-column
label=
"主键"
width=
"60"
align=
"left"
fixed
>
<template
#
default=
"scope"
>
<el-tag
v-if=
"scope.row.primarykey === '1'"
type=
"success"
>
是
</el-tag>
</
template
>
</el-table-column>
<el-table-column
prop=
"columnname"
label=
"字段名"
width=
"180"
/>
<el-table-column
prop=
"typename"
label=
"类型"
width=
"120"
/>
<el-table-column
prop=
"columnsize"
label=
"长度"
width=
"80"
/>
<el-table-column
prop=
"maskingrulename"
label=
"加密算法"
width=
"120"
align=
"center"
/>
<el-table-column
label=
"密钥"
width=
"120"
align=
"center"
>
<
template
#
default=
"{ row }"
>
<el-button
type=
"text"
@
click=
"openEncryptionDialog(row)"
>
设置
</el-button>
<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>
</
template
>
</el-table-column>
<el-table-column
prop=
"status"
label=
"状态"
width=
"100"
align=
"center"
>
<el-table-column
label=
"状态"
width=
"100"
align=
"center"
>
<
template
#
default=
"{ row }"
>
<el-tag
v-if=
"row.status === 'encrypted'"
type=
"success"
size=
"small"
>
已加密
</el-tag>
<el-tag
v-else
type=
"info"
size=
"small"
>
未加密
</el-tag>
<span>
{{
getFlagName
(
row
.
flag
)
}}
</span>
</
template
>
</el-table-column>
<!-- 操作 -->
<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=
"handleEditField(row)"
>
解密
</el-button>
<el-button
v-if=
"row.secretkeyName && ['4', '6', '7', '9', '12'].includes(row.flag)"
type=
"primary"
size=
"small"
@
click=
"handleEditField(row)"
>
加密
</el-button>
</
template
>
</el-table-column>
<!-- 源长度 -->
<el-table-column
label=
"源长度"
width=
"100"
align=
"center"
>
<
template
#
default=
"{ row }"
>
<el-button
link
type=
"success"
v-if=
"row.secretkeyName"
>
{{
row
.
columnsize
}}
</el-button>
</
template
>
</el-table-column>
<!-- 右浮动列 -->
<el-table-column
prop=
"comment
"
label=
"注释"
align=
"left"
min-width=
"200"
/>
<el-table-column
prop=
"remarks
"
label=
"注释"
align=
"left"
min-width=
"200"
/>
<el-table-column
label=
"描述信息"
align=
"left"
fixed=
"right"
>
<
template
#
default=
"{ row }"
>
<el-input
...
...
@@ -61,23 +78,22 @@
</
template
>
</el-table-column>
<el-table-column
prop=
"plaintextProcess"
label=
"明文处理"
align=
"left"
fixed=
"right"
/>
</el-table>
<div
v-if=
"!isEditing"
class=
"table-mask-click"
@
click=
"handleTableMaskClick"
style=
"position:absolute;top:0;left:0;width:100%;height:100%;background:rgba(255,255,255,0.01);z-index:11;cursor:not-allowed;"
></div>
</div>
<!-- 操作按钮区域 -->
<div
class=
"action-buttons"
>
<el-button
type=
"primary"
@
click=
"handleBatchEncrypt"
>
批量加密
</el-button>
<el-button
type=
"primary"
@
click=
"handleBatchDecrypt"
>
批量解密
</el-button>
<el-button
type=
"primary"
@
click=
"handleDeleteColumns"
>
删除多余列
</el-button>
<el-button
type=
"primary"
@
click=
"toggleEditMode"
>
{{ isEditing ? '保存' : '编辑' }}
</el-button>
<el-button
v-if=
"!isEditing"
type=
"primary"
@
click=
"handleBatchEncrypt"
>
批量加密
</el-button>
<el-button
v-if=
"!isEditing"
type=
"primary"
@
click=
"handleBatchDecrypt"
>
批量解密
</el-button>
<el-button
v-if=
"!isEditing"
type=
"primary"
@
click=
"handleDeleteColumns"
>
删除多余列
</el-button>
<el-button
v-if=
"!isEditing"
type=
"primary"
@
click=
"toggleEditMode"
>
编辑
</el-button>
<el-button
v-if=
"isEditing"
type=
"info"
@
click=
"toggleEditMode"
>
取消
</el-button>
<el-button
v-if=
"isEditing"
type=
"primary"
@
click=
"handleSave"
>
保存
</el-button>
</div>
...
...
@@ -92,33 +108,43 @@
<
script
setup
>
import
{
ref
,
computed
,
reactive
}
from
'vue'
import
EncryptionRuleDialog
from
'./EncryptionRuleDialog.vue'
import
{
ElMessageBox
}
from
'element-plus'
const
props
=
defineProps
({
tableData
:
{
type
:
Array
,
required
:
true
,
default
:
()
=>
[
{
pk
:
'PK'
,
fieldName
:
'table_id'
,
fieldType
:
'BIGINT'
,
length
:
'19'
,
algorithm
:
''
,
status
:
'unencrypted'
,
comment
:
'编号'
,
description
:
'主键ID'
,
plaintextProcess
:
''
},
// 其他数据行...
]
default
:
()
=>
[]
}
})
const
emit
=
defineEmits
([
'batch-encrypt'
,
'batch-decrypt'
,
'delete-columns'
,
'edit-field'
,
'update-field'
])
// 状态标识对象数组
const
encryptFlag
=
[
{
value
:
'-2'
,
label
:
'解密中'
},
{
value
:
'-1'
,
label
:
'加密中'
},
{
value
:
'1'
,
label
:
'加密完成'
},
{
value
:
'5'
,
label
:
'加密完成'
},
{
value
:
'4'
,
label
:
'加密失败'
},
{
value
:
'44'
,
label
:
'解密失败'
},
{
value
:
'6'
,
label
:
'解密完成'
},
{
value
:
'7'
,
label
:
'解密完成'
},
{
value
:
'9'
,
label
:
'加密替换失败'
},
{
value
:
'10'
,
label
:
'解密替换失败'
},
{
value
:
'11'
,
label
:
'解密校验失败'
},
{
value
:
'12'
,
label
:
'加密校验失败'
}
]
/**
* 加密状态标识
*/
const
getFlagName
=
(
flag
)
=>
{
const
found
=
encryptFlag
.
find
(
item
=>
item
.
value
===
String
(
flag
))
return
found
?
found
.
label
:
''
}
// 搜索表单
const
filterForm
=
reactive
({
fieldName
:
''
,
status
:
''
flag
:
''
})
// 编辑模式
...
...
@@ -129,6 +155,7 @@ const tableRowClassName = ({ row, rowIndex }) => {
return
row
.
status
===
'encrypted'
?
'encrypted-row'
:
''
}
// 处理搜索
const
handleSearch
=
()
=>
{
// 搜索逻辑已在计算属性中实现
...
...
@@ -139,7 +166,6 @@ const toggleEditMode = () => {
isEditing
.
value
=
!
isEditing
.
value
}
// 处理描述信息变更
const
handleDescriptionChange
=
(
row
)
=>
{
emit
(
'update-field'
,
row
)
...
...
@@ -161,15 +187,19 @@ const handleDeleteColumns = () => {
emit
(
'delete-columns'
)
}
const
handleSave
=
()
=>
{
emit
(
'save-changes'
)
}
// 过滤表格数据
const
filteredTableData
=
computed
(()
=>
{
return
props
.
tableData
.
filter
(
item
=>
{
const
matchesName
=
filterForm
.
fieldN
ame
?
item
.
fieldName
.
includes
(
filterForm
.
fieldN
ame
)
const
matchesName
=
filterForm
.
columnn
ame
?
item
.
columnname
.
includes
(
filterForm
.
columnn
ame
)
:
true
const
matchesStatus
=
filterForm
.
status
?
item
.
status
===
filterForm
.
status
const
matchesStatus
=
filterForm
.
flag
?
item
.
flag
===
filterForm
.
flag
:
true
return
matchesName
&&
matchesStatus
...
...
@@ -193,6 +223,10 @@ const handleRuleConfirm = (ruleData) => {
console
.
log
(
'确认加密规则:'
,
ruleData
)
// 更新表格数据或调用API
}
const
handleTableMaskClick
=
()
=>
{
ElMessageBox
.
alert
(
'当前是只读状态,编辑可点击编辑按钮进行编辑!'
)
}
</
script
>
<
style
scoped
>
...
...
@@ -235,4 +269,9 @@ const handleRuleConfirm = (ruleData) => {
color
:
#333
;
font-weight
:
normal
;
}
.table-mask-click
{
/* 只拦截点击事件,不影响滚动和悬浮 */
pointer-events
:
auto
;
}
</
style
>
\ No newline at end of file
src/views/classification/Classification/modules/StructureTab.vue
View file @
2b60e6ce
...
...
@@ -2,18 +2,23 @@
<div
class=
"structure-tab"
>
<el-table
:data=
"tableData"
max-height=
"500px"
border
style=
"width: 100%"
:header-cell-style=
"
{ background: '#f5f7fa', color: '#333' }"
:row-style="{ height: '40px' }"
:cell-style="{ padding: '8px 0', textAlign: 'center' }"
>
<el-table-column
prop=
"pk"
label=
"主键"
width=
"120"
fixed
/>
<el-table-column
prop=
"fieldName"
label=
"字段名"
width=
"180"
/>
<el-table-column
prop=
"comment"
label=
"注释"
min-width=
"200"
/>
<el-table-column
prop=
"fieldType"
label=
"类型"
width=
"120"
/>
<el-table-column
prop=
"length"
label=
"长度"
width=
"120"
/>
<el-table-column
prop=
"precision"
label=
"精度"
width=
"120"
/>
<el-table-column
label=
"主键"
width=
"80"
fixed
>
<template
#
default=
"scope"
>
<el-tag
v-if=
"scope.row.primarykey === '1'"
type=
"success"
>
是
</el-tag>
</
template
>
</el-table-column>
<el-table-column
prop=
"columnname"
label=
"字段名"
width=
"180"
/>
<el-table-column
prop=
"remarks"
label=
"注释"
min-width=
"200"
/>
<el-table-column
prop=
"typename"
label=
"类型"
width=
"120"
/>
<el-table-column
prop=
"columnsize"
label=
"长度"
width=
"120"
/>
<el-table-column
prop=
"decimaldigits"
label=
"精度"
width=
"120"
/>
</el-table>
</div>
</template>
...
...
@@ -23,18 +28,7 @@ const props = defineProps({
tableData
:
{
type
:
Array
,
required
:
true
,
default
:
()
=>
[
{
pk
:
''
,
fieldName
:
'business_name'
,
comment
:
'生成业务名'
,
fieldType
:
'VARCHAR'
,
length
:
'30'
,
precision
:
''
},
{
pk
:
''
,
fieldName
:
'business_name_...'
,
comment
:
''
,
fieldType
:
'TEXT'
,
length
:
'65535'
,
precision
:
''
},
{
pk
:
''
,
fieldName
:
'class_name'
,
comment
:
'实体类名称'
,
fieldType
:
'VARCHAR'
,
length
:
'100'
,
precision
:
''
},
{
pk
:
''
,
fieldName
:
'create_by'
,
comment
:
'创建者'
,
fieldType
:
'VARCHAR'
,
length
:
'64'
,
precision
:
''
},
{
pk
:
''
,
fieldName
:
'create_time'
,
comment
:
'创建时间'
,
fieldType
:
'DATETIME'
,
length
:
'19'
,
precision
:
''
},
{
pk
:
''
,
fieldName
:
'function_author'
,
comment
:
'生成功能作者'
,
fieldType
:
'VARCHAR'
,
length
:
'50'
,
precision
:
''
},
{
pk
:
''
,
fieldName
:
'function_name'
,
comment
:
'生成功能名'
,
fieldType
:
'VARCHAR'
,
length
:
'50'
,
precision
:
''
},
{
pk
:
''
,
fieldName
:
'gen_path'
,
comment
:
'生成路径(不填...'
,
fieldType
:
'VARCHAR'
,
length
:
'200'
,
precision
:
''
},
{
pk
:
''
,
fieldName
:
'gen_type'
,
comment
:
'生成代码方式(0...'
,
fieldType
:
'CHAR'
,
length
:
'1'
,
precision
:
''
},
{
pk
:
''
,
fieldName
:
'module_name'
,
comment
:
'生成模块名'
,
fieldType
:
'VARCHAR'
,
length
:
'30'
,
precision
:
''
}
]
default
:
()
=>
[]
}
})
</
script
>
...
...
src/views/classification/Classification/modules/TableInfoTab.vue
View file @
2b60e6ce
<
template
>
<div
class=
"table-info-tab"
>
<!-- 表基本信息 -->
<el-descriptions
title=
"
表基本信息
"
title=
""
border
:column=
"1"
size=
"medium"
>
<el-descriptions-item
label=
"字段数"
>
224
</el-descriptions-item>
<el-descriptions-item
label=
"加密表数量"
>
0
</el-descriptions-item>
<el-descriptions-item
label=
"加密字段数量"
>
0
</el-descriptions-item>
<el-descriptions-item
label=
"未加密表数量"
>
20
</el-descriptions-item>
<el-descriptions-item
label=
"未加密字段数量"
>
224
</el-descriptions-item>
<el-descriptions-item
label=
"操作人"
>
admin
</el-descriptions-item>
<el-descriptions-item
label=
"操作时间"
>
2023-05-15 14:30:22
</el-descriptions-item>
<el-descriptions-item
label=
"字段数"
>
{{
nodeData
.
totalColumnCount
}}
</el-descriptions-item>
<el-descriptions-item
label=
"未加密字段数量"
>
{{
nodeData
.
unencryptColumnCount
}}
</el-descriptions-item>
<el-descriptions-item
label=
"加密字段数量"
>
{{
nodeData
.
encryptColumnCount
}}
</el-descriptions-item>
<el-descriptions-item
label=
"操作人"
>
{{
nodeData
.
operator
}}
</el-descriptions-item>
<el-descriptions-item
label=
"操作时间"
>
{{
nodeData
.
operationTime
}}
</el-descriptions-item>
</el-descriptions>
</div>
</
template
>
<
script
setup
>
// 可以留空,因为数据是静态的
const
props
=
defineProps
({
nodeData
:
{
type
:
Object
,
default
:
()
=>
({})
}
})
</
script
>
<
style
scoped
>
...
...
src/views/classification/Classification/modules/TreeFilter.vue
View file @
2b60e6ce
...
...
@@ -27,6 +27,18 @@
<span
class=
"custom-tree-node"
>
<i
:class=
"getNodeIcon(data.type)"
class=
"node-icon"
></i>
<span>
{{
node
.
label
}}
</span>
<template
v-if=
"data.type === 'category'"
>
<i
class=
"el-icon-collection icon-category"
style=
"margin-left:6px;color:#F7BA2A;font-size:16px;"
></i>
</
template
>
<
template
v-if=
"data.type === 'system'"
>
<i
class=
"el-icon-s-platform icon-system"
style=
"margin-left:6px;color:#409EFF;font-size:16px;"
></i>
</
template
>
<
template
v-if=
"data.type === 'database'"
>
<i
class=
"el-icon-s-data icon-database"
style=
"margin-left:6px;color:#67C23A;font-size:16px;"
></i>
</
template
>
<
template
v-if=
"data.type === 'table'"
>
<i
class=
"el-icon-s-grid icon-table"
style=
"margin-left:6px;color:#E6A23C;font-size:16px;"
></i>
</
template
>
</span>
</template>
</el-tree>
...
...
@@ -125,9 +137,11 @@ const handleNodeClick = (data) => {
<
style
scoped
>
.tree-filter-container
{
max-height
:
700px
;
overflow-y
:
auto
;
width
:
100%
;
height
:
100%
;
background-color
:
#f5f5f5
;
/* background-color: #f5f5f5; */
padding
:
10px
;
border-right
:
1px
solid
#e6e6e6
;
}
...
...
@@ -152,6 +166,19 @@ const handleNodeClick = (data) => {
color
:
#606266
;
}
.icon-category
{
vertical-align
:
middle
;
}
.icon-system
{
vertical-align
:
middle
;
}
.icon-database
{
vertical-align
:
middle
;
}
.icon-table
{
vertical-align
:
middle
;
}
:deep
(
.el-tree-node__content
)
{
height
:
36px
;
}
...
...
src/views/login.vue
View file @
2b60e6ce
...
...
@@ -59,7 +59,7 @@
</el-form>
<!-- 底部 -->
<div
class=
"el-login-footer"
>
<span>
Copyright © 2018-2025
ruoyi.vip
All Rights Reserved.
</span>
<span>
Copyright © 2018-2025 All Rights Reserved.
</span>
</div>
</div>
</template>
...
...
@@ -86,8 +86,8 @@ const appStore = useAppStore()
const
{
proxy
}
=
getCurrentInstance
()
const
loginForm
=
ref
({
username
:
"
admin
"
,
password
:
"
admin123
"
,
username
:
""
,
password
:
""
,
rememberMe
:
false
,
code
:
""
,
uuid
:
""
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论