Commit 2b60e6ce by 周海峰

项目加密设置页面

parent 755912ad
...@@ -889,6 +889,93 @@ export function queryExtendColumnSize(data) { ...@@ -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) { ...@@ -1037,9 +1124,51 @@ export function encryptionQuery(data) {
return request({ return request({
url: '/core/encryption/query', url: '/core/encryption/query',
method: 'get', 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
})
}
<template> <template>
<div class="basic-info-tab"> <div class="basic-info-tab">
<el-descriptions <el-descriptions
title="系统基本信息" title=""
border border
:column="1" :column="1"
size="medium"
> >
<el-descriptions-item label="项目">若依配测系统</el-descriptions-item> <el-descriptions-item label="项目">{{ nodeInfo.projectName || ''}}</el-descriptions-item>
<el-descriptions-item label="数据源">若依配测系统</el-descriptions-item> <el-descriptions-item label="数据源">{{ nodeInfo.datasystemName || ''}}</el-descriptions-item>
<el-descriptions-item label="数据源类型">MYSQL</el-descriptions-item> <el-descriptions-item label="数据源类型">{{ nodeInfo.dbType || ''}}</el-descriptions-item>
<el-descriptions-item label="IP">172.19.1.166</el-descriptions-item> <el-descriptions-item label="IP">{{ nodeInfo.ip || ''}}</el-descriptions-item>
<el-descriptions-item label="管理的SCHEMA">ry</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> </el-descriptions>
</div> </div>
</template> </template>
<script setup> <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> </script>
<style scoped> <style scoped>
......
...@@ -5,51 +5,68 @@ ...@@ -5,51 +5,68 @@
<el-form :inline="true" :model="filterForm" class="filter-form"> <el-form :inline="true" :model="filterForm" class="filter-form">
<el-form-item label="字段名过滤:"> <el-form-item label="字段名过滤:">
<el-input <el-input
v-model="filterForm.fieldName" v-model="filterForm.columnname"
placeholder="字段名模糊搜索" placeholder="字段名模糊搜索"
clearable clearable
style="width: 200px;" style="width: 200px;"
/> />
</el-form-item> </el-form-item>
<el-form-item label="状态:"> <el-form-item label="状态:">
<el-select style="width: 200px;" v-model="filterForm.status" placeholder="全部" clearable> <el-select style="width: 200px;" v-model="filterForm.flag" placeholder="全部" clearable>
<el-option label="已加密" value="encrypted" /> <el-option label="全部" value="" />
<el-option label="未加密" value="unencrypted" /> <el-option v-for="item in encryptFlag" :key="item.value" :label="item.label" :value="item.value" />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item> <!-- <el-form-item>
<el-button type="primary" @click="handleSearch">搜索</el-button> <el-button type="primary" @click="handleSearch">搜索</el-button>
</el-form-item> </el-form-item> -->
</el-form> </el-form>
</div> </div>
<!-- 表格区域 --> <!-- 表格区域 -->
<div class="table-wrapper" style="position:relative;">
<el-table <el-table
:data="filteredTableData" :data="filteredTableData"
border border
style="width: 100%; margin-top: 15px;" style="width: 100%; margin-top: 15px;"
max-height="500px"
:row-class-name="tableRowClassName" :row-class-name="tableRowClassName"
> >
<!-- 左浮动列 --> <!-- 左浮动列 -->
<el-table-column prop="pk" label="主键" width="60" align="left" fixed /> <el-table-column label="主键" width="60" align="left" fixed >
<el-table-column prop="fieldName" label="字段名" width="150" align="left" fixed/> <template #default="scope">
<el-table-column prop="fieldType" label="字段类型" width="120" align="center" /> <el-tag v-if="scope.row.primarykey === '1'" type="success"></el-tag>
<el-table-column prop="length" label="长度" width="80" align="center" /> </template>
<el-table-column prop="algorithm" label="加密算法" width="120" align="center" /> </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"> <el-table-column label="密钥" width="120" align="center">
<template #default="{ row }"> <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> </template>
</el-table-column> </el-table-column>
<el-table-column prop="status" label="状态" width="100" align="center"> <el-table-column label="状态" width="100" align="center">
<template #default="{ row }"> <template #default="{ row }">
<el-tag v-if="row.status === 'encrypted'" type="success" size="small">已加密</el-tag> <span>{{ getFlagName(row.flag) }}</span>
<el-tag v-else type="info" size="small">未加密</el-tag> </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> </template>
</el-table-column> </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"> <el-table-column label="描述信息" align="left" fixed="right">
<template #default="{ row }"> <template #default="{ row }">
<el-input <el-input
...@@ -61,23 +78,22 @@ ...@@ -61,23 +78,22 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="plaintextProcess" label="明文处理" align="left" fixed="right"/> <el-table-column prop="plaintextProcess" label="明文处理" align="left" fixed="right"/>
</el-table> </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"> <div class="action-buttons">
<el-button type="primary" @click="handleBatchEncrypt">批量加密</el-button> <el-button v-if="!isEditing" type="primary" @click="handleBatchEncrypt">批量加密</el-button>
<el-button type="primary" @click="handleBatchDecrypt">批量解密</el-button> <el-button v-if="!isEditing" type="primary" @click="handleBatchDecrypt">批量解密</el-button>
<el-button type="primary" @click="handleDeleteColumns">删除多余列</el-button> <el-button v-if="!isEditing" type="primary" @click="handleDeleteColumns">删除多余列</el-button>
<el-button <el-button v-if="!isEditing" type="primary" @click="toggleEditMode">编辑</el-button>
type="primary" <el-button v-if="isEditing" type="info" @click="toggleEditMode">取消</el-button>
<el-button v-if="isEditing" type="primary" @click="handleSave">保存</el-button>
@click="toggleEditMode"
>
{{ isEditing ? '保存' : '编辑' }}
</el-button>
</div> </div>
...@@ -92,33 +108,43 @@ ...@@ -92,33 +108,43 @@
<script setup> <script setup>
import { ref, computed, reactive } from 'vue' import { ref, computed, reactive } from 'vue'
import EncryptionRuleDialog from './EncryptionRuleDialog.vue' import EncryptionRuleDialog from './EncryptionRuleDialog.vue'
import { ElMessageBox } from 'element-plus'
const props = defineProps({ const props = defineProps({
tableData: { tableData: {
type: Array, type: Array,
required: true, required: true,
default: () => [ default: () => []
{
pk: 'PK',
fieldName: 'table_id',
fieldType: 'BIGINT',
length: '19',
algorithm: '',
status: 'unencrypted',
comment: '编号',
description: '主键ID',
plaintextProcess: ''
},
// 其他数据行...
]
} }
}) })
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({ const filterForm = reactive({
fieldName: '', fieldName: '',
status: '' flag: ''
}) })
// 编辑模式 // 编辑模式
...@@ -129,6 +155,7 @@ const tableRowClassName = ({ row, rowIndex }) => { ...@@ -129,6 +155,7 @@ const tableRowClassName = ({ row, rowIndex }) => {
return row.status === 'encrypted' ? 'encrypted-row' : '' return row.status === 'encrypted' ? 'encrypted-row' : ''
} }
// 处理搜索 // 处理搜索
const handleSearch = () => { const handleSearch = () => {
// 搜索逻辑已在计算属性中实现 // 搜索逻辑已在计算属性中实现
...@@ -139,7 +166,6 @@ const toggleEditMode = () => { ...@@ -139,7 +166,6 @@ const toggleEditMode = () => {
isEditing.value = !isEditing.value isEditing.value = !isEditing.value
} }
// 处理描述信息变更 // 处理描述信息变更
const handleDescriptionChange = (row) => { const handleDescriptionChange = (row) => {
emit('update-field', row) emit('update-field', row)
...@@ -161,15 +187,19 @@ const handleDeleteColumns = () => { ...@@ -161,15 +187,19 @@ const handleDeleteColumns = () => {
emit('delete-columns') emit('delete-columns')
} }
const handleSave = () => {
emit('save-changes')
}
// 过滤表格数据 // 过滤表格数据
const filteredTableData = computed(() => { const filteredTableData = computed(() => {
return props.tableData.filter(item => { return props.tableData.filter(item => {
const matchesName = filterForm.fieldName const matchesName = filterForm.columnname
? item.fieldName.includes(filterForm.fieldName) ? item.columnname.includes(filterForm.columnname)
: true : true
const matchesStatus = filterForm.status const matchesStatus = filterForm.flag
? item.status === filterForm.status ? item.flag === filterForm.flag
: true : true
return matchesName && matchesStatus return matchesName && matchesStatus
...@@ -193,6 +223,10 @@ const handleRuleConfirm = (ruleData) => { ...@@ -193,6 +223,10 @@ const handleRuleConfirm = (ruleData) => {
console.log('确认加密规则:', ruleData) console.log('确认加密规则:', ruleData)
// 更新表格数据或调用API // 更新表格数据或调用API
} }
const handleTableMaskClick = () => {
ElMessageBox.alert('当前是只读状态,编辑可点击编辑按钮进行编辑!')
}
</script> </script>
<style scoped> <style scoped>
...@@ -235,4 +269,9 @@ const handleRuleConfirm = (ruleData) => { ...@@ -235,4 +269,9 @@ const handleRuleConfirm = (ruleData) => {
color: #333; color: #333;
font-weight: normal; font-weight: normal;
} }
.table-mask-click {
/* 只拦截点击事件,不影响滚动和悬浮 */
pointer-events: auto;
}
</style> </style>
\ No newline at end of file
...@@ -2,18 +2,23 @@ ...@@ -2,18 +2,23 @@
<div class="structure-tab"> <div class="structure-tab">
<el-table <el-table
:data="tableData" :data="tableData"
max-height="500px"
border border
style="width: 100%" style="width: 100%"
:header-cell-style="{ background: '#f5f7fa', color: '#333' }" :header-cell-style="{ background: '#f5f7fa', color: '#333' }"
:row-style="{ height: '40px' }" :row-style="{ height: '40px' }"
:cell-style="{ padding: '8px 0', textAlign: 'center' }" :cell-style="{ padding: '8px 0', textAlign: 'center' }"
> >
<el-table-column prop="pk" label="主键" width="120" fixed/> <el-table-column label="主键" width="80" fixed>
<el-table-column prop="fieldName" label="字段名" width="180" /> <template #default="scope">
<el-table-column prop="comment" label="注释" min-width="200" /> <el-tag v-if="scope.row.primarykey === '1'" type="success"></el-tag>
<el-table-column prop="fieldType" label="类型" width="120" /> </template>
<el-table-column prop="length" label="长度" width="120" /> </el-table-column>
<el-table-column prop="precision" label="精度" width="120" /> <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> </el-table>
</div> </div>
</template> </template>
...@@ -23,18 +28,7 @@ const props = defineProps({ ...@@ -23,18 +28,7 @@ const props = defineProps({
tableData: { tableData: {
type: Array, type: Array,
required: true, required: true,
default: () => [ 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: '' }
]
} }
}) })
</script> </script>
......
<template> <template>
<div class="table-info-tab"> <div class="table-info-tab">
<!-- 表基本信息 -->
<el-descriptions <el-descriptions
title="表基本信息" title=""
border border
:column="1" :column="1"
size="medium"
> >
<el-descriptions-item label="字段数">224</el-descriptions-item> <el-descriptions-item label="字段数">{{ nodeData.totalColumnCount }}</el-descriptions-item>
<el-descriptions-item label="加密表数量">0</el-descriptions-item> <el-descriptions-item label="未加密字段数量">{{ nodeData.unencryptColumnCount }}</el-descriptions-item>
<el-descriptions-item label="加密字段数量">0</el-descriptions-item> <el-descriptions-item label="加密字段数量">{{ nodeData.encryptColumnCount }}</el-descriptions-item>
<el-descriptions-item label="未加密表数量">20</el-descriptions-item> <el-descriptions-item label="操作人">{{ nodeData.operator }}</el-descriptions-item>
<el-descriptions-item label="未加密字段数量">224</el-descriptions-item> <el-descriptions-item label="操作时间">{{ nodeData.operationTime }}</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> </el-descriptions>
</div> </div>
</template> </template>
<script setup> <script setup>
// 可以留空,因为数据是静态的 // 可以留空,因为数据是静态的
const props = defineProps({
nodeData: {
type: Object,
default: () => ({})
}
})
</script> </script>
<style scoped> <style scoped>
......
...@@ -27,6 +27,18 @@ ...@@ -27,6 +27,18 @@
<span class="custom-tree-node"> <span class="custom-tree-node">
<i :class="getNodeIcon(data.type)" class="node-icon"></i> <i :class="getNodeIcon(data.type)" class="node-icon"></i>
<span>{{ node.label }}</span> <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> </span>
</template> </template>
</el-tree> </el-tree>
...@@ -125,9 +137,11 @@ const handleNodeClick = (data) => { ...@@ -125,9 +137,11 @@ const handleNodeClick = (data) => {
<style scoped> <style scoped>
.tree-filter-container { .tree-filter-container {
max-height: 700px;
overflow-y: auto;
width: 100%; width: 100%;
height: 100%; height: 100%;
background-color: #f5f5f5; /* background-color: #f5f5f5; */
padding: 10px; padding: 10px;
border-right: 1px solid #e6e6e6; border-right: 1px solid #e6e6e6;
} }
...@@ -152,6 +166,19 @@ const handleNodeClick = (data) => { ...@@ -152,6 +166,19 @@ const handleNodeClick = (data) => {
color: #606266; 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) { :deep(.el-tree-node__content) {
height: 36px; height: 36px;
} }
......
...@@ -59,7 +59,7 @@ ...@@ -59,7 +59,7 @@
</el-form> </el-form>
<!-- 底部 --> <!-- 底部 -->
<div class="el-login-footer"> <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>
</div> </div>
</template> </template>
...@@ -86,8 +86,8 @@ const appStore = useAppStore() ...@@ -86,8 +86,8 @@ const appStore = useAppStore()
const { proxy } = getCurrentInstance() const { proxy } = getCurrentInstance()
const loginForm = ref({ const loginForm = ref({
username: "admin", username: "",
password: "admin123", password: "",
rememberMe: false, rememberMe: false,
code: "", code: "",
uuid: "" uuid: ""
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论