Commit 9e370fdb by 周海峰

加密设置

parent 434380b0
...@@ -1172,3 +1172,77 @@ export function save(data) { ...@@ -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
<script setup name="Classification"> <script setup name="Classification">
import { ElMessageBox, ElMessage } from 'element-plus' 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 TreeFilter from './modules/TreeFilter.vue'
import BasicInfoTab from './modules/BasicInfoTab.vue' import BasicInfoTab from './modules/BasicInfoTab.vue'
import TableInfoTab from './modules/TableInfoTab.vue' import TableInfoTab from './modules/TableInfoTab.vue'
import StructureTab from './modules/StructureTab.vue' import StructureTab from './modules/StructureTab.vue'
import EncryptionTab from './modules/EncryptionTab.vue' import EncryptionTab from './modules/EncryptionTab.vue'
import { changeRoute } from '@/utils/switchRoute' 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, import { query, getClassifyEnable, getGlobalOriginalConfig, changeGlobalOriginalConfig, queryDatasystemInfo,
queryShemas, queryTables, querytableInfo, getfield, queryShemas, queryTables, querytableInfo, getfield,
queryOriginalList, queryEncryptionList save
} from '@/api/classification/classification.js' } from '@/api/classification/classification.js'
import { id } from 'element-plus/es/locales.mjs'
const route = useRoute() const route = useRoute()
// 字段加密信息子组件列表
const encryptionTabRef = ref()
const projectId = ref('') const projectId = ref('')
// 树形数据 // 树形数据
const treeData = ref([]) const treeData = ref([])
...@@ -25,6 +23,7 @@ const basicInfoData = ref({}) ...@@ -25,6 +23,7 @@ const basicInfoData = ref({})
const activeTab = ref('basic') const activeTab = ref('basic')
// 当前选中的节点数据 // 当前选中的节点数据
const currentNodeData = ref(null) const currentNodeData = ref(null)
provide('currentNodeData', currentNodeData)
const currentNodeLevel = computed(() => { const currentNodeLevel = computed(() => {
if (!currentNodeData.value) return 1 if (!currentNodeData.value) return 1
if (currentNodeData.value.type === 'system') return 1 if (currentNodeData.value.type === 'system') return 1
...@@ -36,8 +35,7 @@ const currentNodeLevel = computed(() => { ...@@ -36,8 +35,7 @@ const currentNodeLevel = computed(() => {
// 当前表结构数据 (匹配图片中的gen_table结构) // 当前表结构数据 (匹配图片中的gen_table结构)
const currentTableStructure = ref([]) const currentTableStructure = ref([])
// 当前表字段加密配置
const originalList = ref([])
// 监听 currentNodeLevel 和 currentNodeData,一级节点时自动查详情 // 监听 currentNodeLevel 和 currentNodeData,一级节点时自动查详情
watch([currentNodeLevel, currentNodeData, activeTab], async ([level, node, tab]) => { watch([currentNodeLevel, currentNodeData, activeTab], async ([level, node, tab]) => {
...@@ -82,44 +80,10 @@ 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') { if (level === 4 && node && tab === 'encryption') {
console.log('查询字段加密配置', node) nextTick(() => {
encryptionTabRef.value.getTableData()
// 查询字段原始值配置&字段加密配置 })
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 () => { onMounted(async () => {
...@@ -150,41 +114,41 @@ onMounted(async () => { ...@@ -150,41 +114,41 @@ onMounted(async () => {
// 树节点点击处理 // 树节点点击处理
const handleNodeClick = async (data) => { const handleNodeClick = async (data) => {
currentNodeData.value = data currentNodeData.value = data
// 2. 点击一层系统数据,查 schemas // 2. 点击一层系统数据,查 schemas
if (data.type === 'system') { if (data.type === 'system') {
activeTab.value = 'basic' activeTab.value = 'basic'
const res = await queryShemas({ const res = await queryShemas({
dataSystemId: data.tid, dataSystemId: data.tid,
dataType: data.dbtype, dataType: data.dbtype,
projectid: projectId.value projectid: projectId.value
}) })
if (res && res.data) { if (res && res.data) {
data.children = res.data.map(schema => ({ data.children = res.data.map(schema => ({
id: uuid(), id: uuid(),
...schema, ...schema,
type: 'database', type: 'database',
label: schema.text, label: schema.text,
parent: data, parent: data,
children: [ children: [
{ {
id: uuid(), id: uuid(),
label: '表', label: '表',
type: 'category', type: 'category',
parent: { parent: {
...schema, ...schema,
type: 'database', type: 'database',
label: schema.text, label: schema.text,
parent: data, parent: data,
tid: data.tid, tid: data.tid,
dbservername: schema.text dbservername: schema.text
}, },
children: [] children: []
} }
] ]
})) }))
treeData.value = [...treeData.value] // 触发视图更新 treeData.value = [...treeData.value] // 触发视图更新
} }
} }
// 3. 点击三层 category,查表 // 3. 点击三层 category,查表
if (data.type === 'category' && data.parent) { if (data.type === 'category' && data.parent) {
...@@ -232,32 +196,6 @@ const handleDecryptChange = async (val) => { ...@@ -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() { function pageProjectManage() {
changeRoute() changeRoute()
router.push({ router.push({
...@@ -343,12 +281,7 @@ function uuid() { ...@@ -343,12 +281,7 @@ function uuid() {
<!-- 字段加密配置Tab (仅4级节点显示) --> <!-- 字段加密配置Tab (仅4级节点显示) -->
<el-tab-pane label="字段加密配置" name="encryption" v-if="currentNodeLevel === 4"> <el-tab-pane label="字段加密配置" name="encryption" v-if="currentNodeLevel === 4">
<EncryptionTab <EncryptionTab
:table-data="originalList" ref="encryptionTabRef"
@batch-encrypt="handleBatchEncrypt"
@batch-decrypt="handleBatchDecrypt"
@delete-columns="handleDeleteColumns"
@save-changes="handleSave"
@edit-field="handleEditField"
v-if="activeTab === 'encryption'" v-if="activeTab === 'encryption'"
/> />
</el-tab-pane> </el-tab-pane>
......
...@@ -10,30 +10,35 @@ ...@@ -10,30 +10,35 @@
<div class="selection-section"> <div class="selection-section">
<!-- 左侧加密规则选择 --> <!-- 左侧加密规则选择 -->
<div class="rule-selection"> <div class="rule-selection">
<div class="section-title">选择加密规则</div> <div class="section-title gradient-title">
<el-radio-group v-model="selectedRule" class="rule-radio-group"> <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 <el-radio
v-for="rule in encryptionRules" v-for="rule in encryptionRules"
:key="rule.id" :key="rule.id"
:label="rule.id" :value="rule.id"
class="rule-radio" class="rule-radio"
> >
{{ rule.name }} {{ rule.name }}
<span style="color: aqua;">{{ rule.list.length || 0 }}</span>
</el-radio> </el-radio>
</el-radio-group> </el-radio-group>
</div> </div>
<!-- 分割线 --> <!-- 分割线 -->
<div class="divider"></div> <div class="divider"></div>
<!-- 右侧加密密钥选择 --> <!-- 右侧加密密钥选择 -->
<div class="key-selection"> <div class="key-selection">
<div class="section-title">选择加密密钥</div> <div class="section-title gradient-title">
<el-radio-group v-model="selectedKey" class="key-radio-group"> <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 <el-radio
v-for="key in currentKeys" v-for="key in currentKeys"
:key="key.id" :key="key.id"
:label="key.id" :value="key.id"
class="key-radio" class="key-radio"
> >
{{ key.name }} {{ key.name }}
...@@ -48,18 +53,30 @@ ...@@ -48,18 +53,30 @@
<!-- 加密位置 --> <!-- 加密位置 -->
<div class="config-item"> <div class="config-item">
<span class="required-label">*加密位置:</span> <span class="required-label">*加密位置:</span>
<el-select v-model="ruleConfig.positionType" style="width: 120px"> <el-select v-model="fieldData.keepfirst" style="width: 120px">
<el-option label="保留前" value="prefix" /> <el-option label="保留前" value="0" />
<el-option label="保留后" value="suffix" /> <el-option label="保留后" value="1" />
<el-option label="既保留前" value="2" />
</el-select> </el-select>
<el-input-number <el-input-number
v-model="ruleConfig.position" v-model="fieldData.encdigit"
:min="0" :min="0"
:max="100" :max="100"
controls-position="right" controls-position="right"
style="width: 100px; margin-left: 10px;" style="width: 100px; margin-left: 10px;"
/> />
<span class="unit"></span> <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> </div>
<div class="config-row"> <div class="config-row">
...@@ -67,7 +84,7 @@ ...@@ -67,7 +84,7 @@
<div class="config-item"> <div class="config-item">
<span class="label">源长度:</span> <span class="label">源长度:</span>
<el-input-number <el-input-number
v-model="ruleConfig.sourceLength" v-model="fieldData.columnSize"
:min="0" :min="0"
:max="1000" :max="1000"
controls-position="right" controls-position="right"
...@@ -90,7 +107,7 @@ ...@@ -90,7 +107,7 @@
</div> </div>
</div> </div>
<div class="action-row"> <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"> <div class="action-buttons">
<el-button @click="resetRules">重置规则</el-button> <el-button @click="resetRules">重置规则</el-button>
<el-button type="primary" @click="confirmRules">确定规则</el-button> <el-button type="primary" @click="confirmRules">确定规则</el-button>
...@@ -102,8 +119,8 @@ ...@@ -102,8 +119,8 @@
</template> </template>
<script setup> <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({ const props = defineProps({
visible: { visible: {
type: Boolean, type: Boolean,
...@@ -111,11 +128,29 @@ const props = defineProps({ ...@@ -111,11 +128,29 @@ const props = defineProps({
}, },
fieldData: { fieldData: {
type: Object, 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({ const dialogVisible = computed({
...@@ -124,81 +159,70 @@ const dialogVisible = computed({ ...@@ -124,81 +159,70 @@ const dialogVisible = computed({
}) })
// 加密规则数据 // 加密规则数据
const encryptionRules = ref([ 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 selectedKey = ref('')
// 当前显示的密钥列表 // 当前显示的密钥列表
const currentKeys = computed(() => { 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 handleKeyChange = (value) => {
const ruleConfig = ref({ const selectedKey = currentKeys.value.find(key => key.id === value)
positionType: 'prefix', props.fieldData.secretkeyName = selectedKey ? selectedKey.name : ''
position: 0, }
sourceLength: 100
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 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 = () => { const resetRules = () => {
selectedRule.value = 'name' emit('reset')
ruleConfig.value = { dialogVisible.value = false
positionType: 'prefix',
position: 0,
sourceLength: 100
}
encryptedLength.value = ''
supportFuzzy.value = false
} }
// 确认规则 // 确认规则
const confirmRules = () => { const confirmRules = () => {
emit('confirm', { emit('confirm')
rule: selectedRule.value,
key: selectedKey.value,
config: ruleConfig.value,
supportFuzzy: supportFuzzy.value,
encryptedLength: encryptedLength.value
})
dialogVisible.value = false dialogVisible.value = false
} }
...@@ -206,6 +230,11 @@ const confirmRules = () => { ...@@ -206,6 +230,11 @@ const confirmRules = () => {
const handleClose = (done) => { const handleClose = (done) => {
done() done()
} }
defineExpose({
calculateLength
})
</script> </script>
<style scoped> <style scoped>
...@@ -239,9 +268,23 @@ const handleClose = (done) => { ...@@ -239,9 +268,23 @@ const handleClose = (done) => {
color: #333; 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 { .rule-radio-group, .key-radio-group {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: flex-start;
margin-left: 24px;
} }
.rule-radio, .key-radio { .rule-radio, .key-radio {
......
...@@ -43,8 +43,8 @@ ...@@ -43,8 +43,8 @@
<el-table-column prop="maskingrulename" label="加密算法" width="120" align="center" /> <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 v-if="row.secretkeyName" link type="primary" >{{ row.secretkeyName }}</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-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)">设置</el-button>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="状态" width="100" align="center"> <el-table-column label="状态" width="100" align="center">
...@@ -55,8 +55,8 @@ ...@@ -55,8 +55,8 @@
<!-- 操作 --> <!-- 操作 -->
<el-table-column label="操作" width="100" align="center"> <el-table-column label="操作" width="100" align="center">
<template #default="{ row }"> <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 && ['1', '5', '44', '10', '11'].includes(row.flag)" type="primary" size="small" @click="handleUnEncryptField(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> <el-button v-if="row.secretkeyName && ['4', '6', '7', '9', '12'].includes(row.flag)" type="primary" size="small" @click="handleEncryptField(row)">加密</el-button>
</template> </template>
</el-table-column> </el-table-column>
<!-- 源长度 --> <!-- 源长度 -->
...@@ -70,10 +70,10 @@ ...@@ -70,10 +70,10 @@
<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
v-if="row.typename!=='DATETIME' && row.primarykey !== '1'"
v-model="row.description" v-model="row.description"
size="small" size="small"
:disabled="!isEditing" :disabled="!isEditing"
@change="handleDescriptionChange(row)"
/> />
</template> </template>
</el-table-column> </el-table-column>
...@@ -98,25 +98,86 @@ ...@@ -98,25 +98,86 @@
<EncryptionRuleDialog <EncryptionRuleDialog
ref="encryptionRuleDialogRef"
v-model:visible="showEncryptionDialog" v-model:visible="showEncryptionDialog"
:field-data="currentField" :field-data="currentField"
@confirm="handleRuleConfirm" @confirm="handleRuleConfirm"
@reset="handleRuleReset"
/> />
</div> </div>
</template> </template>
<script setup> <script setup>
import { ref, computed, reactive } from 'vue' import { ref, computed, reactive, inject, nextTick} from 'vue'
import EncryptionRuleDialog from './EncryptionRuleDialog.vue' import EncryptionRuleDialog from './EncryptionRuleDialog.vue'
import { ElMessageBox } from 'element-plus' import { ElMessageBox } from 'element-plus'
import { queryOriginalList, queryEncryptionList, hasRedundanceColumns, queryIsLike, queryEncDigit, save, delTableColumn, checkSingleEncOrDecColumn, loadingColumn } from '@/api/classification/classification.js'
const props = defineProps({ const props = defineProps({
tableData: { // tableData: {
type: Array, // type: Array,
required: true, // required: true,
default: () => [] // 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 = [ const encryptFlag = [
{ value: '-2', label: '解密中' }, { value: '-2', label: '解密中' },
...@@ -155,22 +216,76 @@ const tableRowClassName = ({ row, rowIndex }) => { ...@@ -155,22 +216,76 @@ const tableRowClassName = ({ row, rowIndex }) => {
return row.status === 'encrypted' ? 'encrypted-row' : '' return row.status === 'encrypted' ? 'encrypted-row' : ''
} }
// 处理搜索
const handleSearch = () => {
// 搜索逻辑已在计算属性中实现
}
// 切换编辑模式 // 切换编辑模式
const toggleEditMode = () => { const toggleEditMode = () => {
isEditing.value = !isEditing.value 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 = () => { const handleBatchEncrypt = () => {
...@@ -183,17 +298,102 @@ const handleBatchDecrypt = () => { ...@@ -183,17 +298,102 @@ const handleBatchDecrypt = () => {
} }
// 删除多余列 // 删除多余列
const handleDeleteColumns = () => { const handleDeleteColumns = async () => {
emit('delete-columns') 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(() => { const filteredTableData = computed(() => {
return props.tableData.filter(item => { return tableData.value.filter(item => {
const matchesName = filterForm.columnname const matchesName = filterForm.columnname
? item.columnname.includes(filterForm.columnname) ? item.columnname.includes(filterForm.columnname)
: true : true
...@@ -211,22 +411,116 @@ const filteredTableData = computed(() => { ...@@ -211,22 +411,116 @@ const filteredTableData = computed(() => {
const showEncryptionDialog = ref(false) const showEncryptionDialog = ref(false)
const currentField = ref({}) const currentField = ref({})
// 处理设置密钥 // 点击密钥列的【密钥】或 设置
const openEncryptionDialog = (row) => { const openEncryptionDialog = async (row) => {
if(!isEditing.value) return 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 showEncryptionDialog.value = true
// 计算加密后长度
if(row.secretkeyId){
nextTick(() => {
encryptionRuleDialogRef.value.calculateLength()
})
}
} }
/**
const handleRuleConfirm = (ruleData) => { * 确认加密规则-回调方法
console.log('确认加密规则:', ruleData) */
const handleRuleConfirm = () => {
// 更新表格数据或调用API // 更新表格数据或调用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 = () => { const handleTableMaskClick = () => {
ElMessageBox.alert('当前是只读状态,编辑可点击编辑按钮进行编辑!') ElMessageBox.alert('当前是只读状态,编辑可点击编辑按钮进行编辑!')
} }
/**
* 暴露给父组件的数据
*/
defineExpose({
getTableData
})
</script> </script>
<style scoped> <style scoped>
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论