Commit 9e370fdb by 周海峰

加密设置

parent 434380b0
......@@ -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">
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>
......
......@@ -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 {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论