Commit a76586a0 by wuchao

Merge branch 'master' of https://code.palacesun.com/wuchao/nse-ui

parents 82a090d9 8841058d
......@@ -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
})
}
......@@ -67,4 +67,43 @@ export function queryShemas(data) {
})
}
export function getAllDataAreaAndRule(data) {
return request({
url: '/core/tdataarea/getAllDataAreaAndRule',
method: 'post',
data: data
})
}
export function addDataProject(data) {
return request({
url: '/core/tdataproject/addDataProject',
method: 'post',
data: data
})
}
export function deleteDataProject(data) {
return request({
url: '/core/tdataproject/deleteDataProject',
method: 'post',
data: data
})
}
export function getDataProjectDetail(data) {
return request({
url: '/core/tdataproject/getDataProjectDetail',
method: 'post',
data: data
})
}
export function updateDataProject(data) {
return request({
url: '/core/tdataproject/updateDataProject',
method: 'post',
data: data
})
}
......@@ -12,3 +12,55 @@ export function query(query) {
params: query
})
}
/**
* 脱敏算法 - 新增算法
* @param {*} data
* @returns
*/
export function save(data) {
return request({
url: '/core/desensitizationrule/save',
method: 'post',
data: data
})
}
/**
* 脱敏算法 - 获取函数列表
* @param {*} query
* @returns
*/
export function queryFunctionList(query) {
return request({
url: '/core/desensitizationAlgorithm/queryFunctionList',
method: 'get',
params: query
})
}
/**
* 脱敏算法 - 删除算法
* @param {*} data
* @returns
*/
export function del(data) {
return request({
url: '/core/desensitizationrule/delete',
method: 'post',
data: data
})
}
/**
* 脱敏算法 - 测试算法
* @param {*} data
* @returns
*/
export function test(data) {
return request({
url: '/core/desensitizationrule/test',
method: 'post',
data: data
})
}
\ No newline at end of file
import request from '@/utils/request'
/**
* 加密规则 - 查询加密规则列表
* @param {*} query
* @returns
*/
export function query(query) {
return request({
url: '/core/encryption/query',
method: 'get',
params: query
})
}
/**
* 加密规则 - 查询加密方式列表
* @param {*} query
* @returns
*/
export function initEncryptionTypeList(query) {
return request({
url: '/core/encryption/initEncryptionTypeList',
method: 'get',
params: query
})
}
/**
* 加密规则 - 获取字典分类
* @param {*} query
* @returns
*/
export function getDictinaryTypes(query) {
return request({
url: '/core/dictionary/getDictinaryTypes',
method: 'get',
params: query
})
}
/**
* 加密规则 - 新增加密分类
* @param {*} data
* @returns
*/
export function save(data) {
return request({
url: '/core/encryption/save',
method: 'post',
data: data
})
}
/**
* 加密规则 - 删除加密分类
* @param {*} data
* @returns
*/
export function deleteType(data) {
return request({
url: '/core/encryption/delete',
method: 'post',
data: data
})
}
/**
* 加密规则 - 密钥生成
* @param {*} query
* @returns
*/
export function getRandomValue(query) {
return request({
url: '/core/encryption/getRandomValue',
method: 'get',
params: query
})
}
/**
* 加密规则 - 测试
* @param {*} data
* @returns
*/
export function testEncryption(data) {
return request({
url: '/core/encryption/testEncryption',
method: 'post',
data: data
})
}
/**
* 加密规则 - 新增密钥
* @param {*} data
* @returns
*/
export function saveSecretKey(data) {
return request({
url: '/core/encryption/saveSecretKey',
method: 'post',
data: data
})
}
/**
* 加密规则 - 删除密钥
* @param {*} data
* @returns
*/
export function delSecretKey(data) {
return request({
url: '/core/encryption/delSecretKey',
method: 'post',
data: data
})
}
<script setup lang="ts" name="ExpressionEditor">
import { ref, onMounted, toRefs } from "vue";
import ModalPop from "./ModalPop.vue"
import { ref, onMounted, toRefs, watch, reactive } from "vue";
import ModalPop from "./ModalPop.vue";
import { queryFunctionList, test } from "@/api/ruleConfig/algorithm";
const props = defineProps<{
modelValue: boolean;
data?: Object;
rulename?: String;
}>();
const emit = defineEmits(["update:modelValue", "confirm", "cancel"]);
const editorName = ref("");
const editorValue = ref("");
const infoText = ref('')
const listData = ref([
{
name: 'convert_base1()'
},
{
name: 'convert_base2()'
}
])
const infoText = ref("");
const listData = ref([]);
const testVisible = ref(false);
const testResult = ref(""); // 执行结果
const testData = reactive({
expression: "",
param: "",
});
// 确认
const confirm = () => {
emit("confirm", editorValue.value);
};
// 测试
const test = () => {
console.log("test");
};
const cancel = () => {
editorValue.value = JSON.parse(JSON.stringify(props.rulename));
editorName.value = JSON.parse(JSON.stringify(props.rulename));
emit("cancel");
}
};
// 划过事件
const hoverFunc = (item) => {
infoText.value = item;
}
infoText.value = item.remark;
};
// 获取函数列表
const getQueryFuncList = () => {
queryFunctionList({}).then((res) => {
const { data } = res;
listData.value = data;
});
};
const change = (val) => {
if(!val) return;
console.log(props.data)
editorValue.value = props.data.name;
// 执行测试
const executeTest = () => {
testData.expression = editorValue.value;
test(testData).then((res) => {
const { flag, data } = res;
if (flag) {
testResult.value = data;
}
});
};
// 测试关闭
const testCancel = () => {
testVisible.value = false;
testData.param = ''
testResult.value = "";
}
watch(
() => props.modelValue,
(newVal) => {
if (props.modelValue) {
getQueryFuncList();
}
},
{ deep: true, immediate: true }
);
watch(
() => props.rulename,
(newVal) => {
editorValue.value = JSON.parse(JSON.stringify(props.rulename));
editorName.value = JSON.parse(JSON.stringify(props.rulename));
},
{ deep: true, immediate: true }
);
</script>
<template>
<ModalPop v-model="props.modelValue" title="编辑器" @cancel="cancel" @change="change">
<div>
<ModalPop v-model="props.modelValue" title="编辑器" @cancel="cancel">
<template #content>
<div class="title">算法名称 :</div>
<div class="title">算法名称 : {{ editorName }}</div>
<div class="content">
<div class="content_left">
<div class="content_left_tap">函数</div>
<div class="content_left_list">
<el-scrollbar height="362px">
<div class="function__item" @mouseover="hoverFunc(item)" v-for="(item,index) in listData" :key="index">{{ item.name }}</div>
<div class="function__item" @mouseover="hoverFunc(item)" v-for="(item,index) in listData" :key="index">
{{ item.name }}</div>
</el-scrollbar>
</div>
</div>
......@@ -65,39 +103,55 @@ const change = (val) => {
<div class="content_right_info_content">定义:{{ infoText }}</div>
</div>
<div class="content_right_editor">
<el-input
type="textarea"
placeholder="请输入内容"
v-model="editorValue"
/>
<el-input type="textarea" placeholder="请输入内容" v-model="editorValue" />
</div>
</div>
</div>
<div style="display: flex; justify-content: center; padding-top: 20px;">
<el-button type="primary" style="width: 150px;" @click="test">测试</el-button>
<el-button type="primary" style="width: 150px;" @click="testVisible = true">测试</el-button>
<el-button type="info" style="width: 150px;" @click="cancel">取消</el-button>
<el-button type="primary" style="width: 150px;" @click="confirm">确认</el-button>
</div>
</template>
</ModalPop>
<!-- 测试 -->
<ModalPop v-model="testVisible" width="800px" title="测试" @cancel="testCancel">
<template #content>
<el-form-item label="输入参数$value的值:" label-width="180px" prop="expression">
<div style="width: 100%;display: flex; justify-content: center;">
<el-input placeholder="输入参数$value的值" v-model="testData.param" />
<el-button type="primary" style="margin-left: 10px;" @click="executeTest">执行</el-button>
</div>
</el-form-item>
<el-form-item label="执行结果:" label-width="180px">
<div>{{ testResult }}</div>
</el-form-item>
<div style="display: flex; justify-content: center; padding-top: 20px;">
<el-button type="primary" style="width: 150px;" @click="testCancel">关闭</el-button>
</div>
</template>
</ModalPop>
</div>
</template>
<style lang="scss" scoped>
.title{
height: 32px; line-height: 32px;
.title {
height: 32px;
line-height: 32px;
}
.content{
.content {
display: flex;
height: 400px;
width: 100%;
&_left{
&_left {
height: 100%;
width: 322px;
border-width: 1px;
border-style: solid;
border-color: rgb(220, 229, 235);
border-image: initial;
&_tap{
&_tap {
height: 36px;
line-height: 36px;
font-size: 14px;
......@@ -106,46 +160,46 @@ const change = (val) => {
padding-left: 20px;
color: rgb(44, 158, 247);
}
&_list{
&_list {
height: 100%;
.function__item{
.function__item {
padding-left: 20px;
cursor: pointer;
color: #7A8596;
color: #7a8596;
}
.function__item:hover{
.function__item:hover {
background: rgb(243, 245, 250);
}
}
}
&_right{
&_right {
margin-left: 10px;
height: 100%;
flex: 1;
&_info{
&_info {
height: 146px;
border-style: solid;
border-color: rgb(220, 229, 235);
border-image: initial;
border-width: 1px 1px 0px;
padding: 0px 20px;
&_title{
&_title {
height: 42px;
line-height: 42px;
color: rgb(122, 132, 149);
font-size: 14px;
font-weight: 700;
}
&_content{
&_content {
margin-top: -4px;
color: rgb(122, 132, 149);
font-size: 12px;
word-break: break-all;
}
}
&_editor{
&_editor {
width: 100%;
:deep(.el-textarea__inner){
:deep(.el-textarea__inner) {
box-sizing: border-box !important;
height: 254px !important;
min-height: 254px !important;
......
import router from './router'
import { ElMessage } from 'element-plus'
import NProgress from 'nprogress'
import NProgress, { settings } from 'nprogress'
import 'nprogress/nprogress.css'
import { getToken } from '@/utils/auth'
import { isHttp, isPathMatch } from '@/utils/validate'
......@@ -17,55 +17,63 @@ const isWhiteList = (path) => {
return whiteList.some(pattern => isPathMatch(pattern, path))
}
router.beforeEach((to, from, next) => {
router.beforeEach(async (to, from, next) => {
NProgress.start()
// if (getToken()) {
// to.meta.title && useSettingsStore().setTitle(to.meta.title)
// /* has token*/
// if (to.path === '/login') {
// next({ path: '/' })
// NProgress.done()
// } else if (isWhiteList(to.path)) {
// next()
// } else {
// if (useUserStore().roles.length === 0) {
// isRelogin.show = true
// // 判断当前用户是否已拉取完user_info信息
// useUserStore().getInfo().then(() => {
// isRelogin.show = false
// usePermissionStore().generateRoutes().then(accessRoutes => {
// // 根据roles权限生成可访问的路由表
// accessRoutes.forEach(route => {
// if (!isHttp(route.path)) {
// router.addRoute(route) // 动态添加可访问路由表
// }
// })
// next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
// })
// }).catch(err => {
// useUserStore().logOut().then(() => {
// ElMessage.error(err)
// next({ path: '/' })
// })
// })
// } else {
// next()
// }
// }
// } else {
// // 没有token
// if (isWhiteList(to.path)) {
// // 在免登录白名单,直接进入
// next()
// } else {
// next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页
// NProgress.done()
// }
// }
// 获取permissionStore实例
const permissionStore = usePermissionStore()
if (sessionStorage.getItem('__token') || isWhiteList(to.path)) {
console.log('next1')
try {
// 检查是否已经有路由数据,避免重复设置
if (!permissionStore.sidebarRouters || permissionStore.sidebarRouters.length === 0) {
console.log('next2')
// 从sessionStorage获取数据
const allnavListStr = sessionStorage.getItem('allnavList')
const navStatusStr = sessionStorage.getItem('navStatus')
if (allnavListStr && navStatusStr) {
console.log('next3')
try {
const allnavList = JSON.parse(allnavListStr)
const navStatus = JSON.parse(navStatusStr)
console.log('allnavList' , allnavList)
console.log('navStatus' , navStatus)
// 根据navStatus.type过滤菜单
let filterMenus = []
if (navStatus && navStatus.type) {
let type = navStatus.type === 'manage' ? '1' : '2'
filterMenus = allnavList.filter(item => item.type === type)
console.log('filterMenus' , filterMenus)
} else {
// 默认处理,如果没有type则使用全部菜单
filterMenus = allnavList
}
// 存入permissionStore
if (filterMenus && filterMenus.length > 0) {
permissionStore.setSidebarRouters(filterMenus)
}
} catch (parseError) {
console.error('解析sessionStorage数据失败:', parseError)
// 解析失败时清除无效数据
sessionStorage.removeItem('allnavList')
sessionStorage.removeItem('navStatus')
}
}
}
console.log(permissionStore.sidebarRouters)
console.log('next6',router.getRoutes())
next()
} catch (error) {
console.error('路由守卫处理失败:', error)
next()
}
} else {
next(`/login?redirect=${to.fullPath}`)
NProgress.done()
......
import axios from 'axios'
import { ElNotification , ElMessageBox, ElMessage, ElLoading } from 'element-plus'
import { getToken } from '@/utils/auth'
import { getToken, removeToken } from '@/utils/auth'
import errorCode from '@/utils/errorCode'
import { tansParams, blobValidate } from '@/utils/ruoyi'
import cache from '@/plugins/cache'
......@@ -81,14 +81,13 @@ service.interceptors.response.use(res => {
if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
return res.data
}
if (code === 401) {
if (code === 'TOK_ERR_002') {
if (!isRelogin.show) {
isRelogin.show = true
ElMessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => {
isRelogin.show = false
useUserStore().logOut().then(() => {
location.href = '/index'
})
removeToken()
window.location.href = `${location.origin}${import.meta.env.BASE_URL}login`
}).catch(() => {
isRelogin.show = false
})
......
<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,23 @@ 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'
import { id } from 'element-plus/es/locales.mjs'
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 +34,205 @@ 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,
id: uuid(),
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 +248,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 +295,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 +321,15 @@ defineExpose({
<!-- 基本信息Tab -->
<el-tab-pane label="基本信息" name="basic">
<BasicInfoTab
:node-data="currentNodeData"
v-if="activeTab === 'basic' && currentNodeLevel === 1"
:node-data="basicInfoData"
v-if="activeTab === 'basic' && [1,2,3].includes(currentNodeLevel)"
/>
<!-- 表信息Tab -->
<TableInfoTab
:node-data="currentNodeData"
:node-data="basicInfoData"
v-if="activeTab === 'basic' && currentNodeLevel === 4"
/>
</el-tab-pane>
<!-- 数据结构Tab (仅4级节点显示) -->
......@@ -204,10 +343,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 +381,7 @@ defineExpose({
.left {
.tree-container {
width: 300px;
overflow-y: auto; // 内容超出滚动
}
}
.right {
......
<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>
......
......@@ -5,51 +5,68 @@
<el-form :inline="true" :model="filterForm" class="filter-form">
<el-form-item label="字段名过滤:">
<el-input
v-model="filterForm.fieldName"
v-model="filterForm.columnname"
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.fieldName
? item.fieldName.includes(filterForm.fieldName)
const matchesName = filterForm.columnname
? item.columnname.includes(filterForm.columnname)
: 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
......@@ -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>
......
<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>
......
......@@ -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;
}
......
......@@ -68,6 +68,7 @@ const getHomePageFunc = () => {
topList.value[5].num = data.encryptColumnCount
console.log(dataObj.value)
if(!data.space) return
homeChartData.xList = data.space.map(item => item.path)
homeChartData.yList1 = data.space.map(item => item.usedpace)
homeChartData.yList2 = data.space.map(item => item.freespace)
......
......@@ -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: ""
......
......@@ -80,7 +80,7 @@
:key="db.id"
class="db-item"
>
<el-checkbox :label="db.tid">
<el-checkbox :value="db.tid">
{{ db.sysname }}
</el-checkbox>
</div>
......@@ -120,11 +120,11 @@
<el-scrollbar height="400px">
<div class="datasource-list">
<div
v-for="db in selectedDbDetails"
v-for="(db,dbindex) in selectedDbDetails"
:key="db.tid"
class="datasource-item"
:class="{ active: selectedDataSource === db.tid }"
@click="selectDataSource(db.tid)"
@click="selectDataSource(db.tid,dbindex)"
>
{{ db.sysname }}
</div>
......@@ -143,20 +143,19 @@
>
全选
</el-checkbox>
<span class="schema-count">{{ selectedSchemas.length }}/{{ allSchemas.length }}</span>
<span class="schema-count">{{ selectedSchemas.length }}/{{ allSchemasCompute.length }}</span>
</div>
</div>
<el-scrollbar height="400px">
<el-checkbox-group v-model="selectedSchemas">
<el-checkbox-group v-model="selectedSchemas" @change="schemaChange">
<div
v-for="schema in allSchemas"
v-for="schema in allSchemasCompute"
:key="schema"
class="schema-item"
>
<el-checkbox :label="schema">
{{ schema }}
</el-checkbox>
<el-checkbox :value="schema.value" :label=" schema.text" />
</div>
</el-checkbox-group>
</el-scrollbar>
......@@ -175,24 +174,24 @@
<div class="section-title">可选择数据域</div>
</div>
<div class="domain-group" v-for="group in domainGroups" :key="group.name">
<div class="domain-group" v-for="group in domainGroups" :key="group.id">
<div class="group-header">
<el-checkbox
v-model="group.selectedAll"
@change="(val) => toggleGroupSelection(group, val)"
>
{{ group.name }}
{{ group.dataarea }}
</el-checkbox>
</div>
<el-scrollbar height="300px">
<el-scrollbar height="150px">
<el-checkbox-group v-model="selectedDomains">
<div
v-for="domain in group.domains"
v-for="domain in group.list"
:key="domain.id"
class="domain-item"
>
<el-checkbox :label="domain.id">
<el-checkbox :value="domain.id">
<div class="domain-content">
<div class="domain-name">{{ domain.name }}</div>
<div v-if="domain.desc" class="domain-desc">{{ domain.desc }}</div>
......@@ -202,6 +201,7 @@
</el-checkbox-group>
</el-scrollbar>
</div>
</div>
<!-- 右侧已选择数据域 -->
......@@ -262,8 +262,9 @@ import {
checkDatasystem,
queryByEditSort,
selectProDataSource,
queryShemas
queryShemas,
getAllDataAreaAndRule,
getDataProjectDetail
} from '@/api/project'
import useAppStore from '@/store/modules/app'
......@@ -353,7 +354,7 @@ const formData = ref({
projectType: 'normal',
databases: [],
schemas: [],
domains: []
domains: [],
})
// 步骤条相关
......@@ -401,37 +402,37 @@ const selectAllSchemas = ref(false)
// 第四步:数据域选择相关
const domainGroups = ref([
{
name: '混合数据域',
selectedAll: false,
domains: [
{ id: 'domain1', name: '566546', desc: '' },
{ id: 'domain2', name: '通用规则', desc: '' },
{ id: 'domain3', name: '解密数据', desc: '' },
{ id: 'domain4', name: '混合证件号', desc: '按混合证件号字段查询' }
]
},
{
name: '智能数据域',
selectedAll: false,
domains: [
{ id: 'domain5', name: '智能推荐', desc: '' },
{ id: 'domain6', name: '电子邮件', desc: '按邮箱字段查找' },
{ id: 'domain7', name: '社保卡号', desc: '' }
]
},
{
name: '测试数据域',
selectedAll: false,
domains: [
{ id: 'domain8', name: '发现规则1', desc: '' },
{ id: 'domain9', name: '营业执照', desc: '按营业执照字段查询' },
{ id: 'domain10', name: '邮政编码', desc: '邮政编码字段查找' }
]
}
// {
// name: '混合数据域',
// selectedAll: false,
// domains: [
// { id: 'domain1', name: '566546', desc: '' },
// { id: 'domain2', name: '通用规则', desc: '' },
// { id: 'domain3', name: '解密数据', desc: '' },
// { id: 'domain4', name: '混合证件号', desc: '按混合证件号字段查询' }
// ]
// },
// {
// name: '智能数据域',
// selectedAll: false,
// domains: [
// { id: 'domain5', name: '智能推荐', desc: '' },
// { id: 'domain6', name: '电子邮件', desc: '按邮箱字段查找' },
// { id: 'domain7', name: '社保卡号', desc: '' }
// ]
// },
// {
// name: '测试数据域',
// selectedAll: false,
// domains: [
// { id: 'domain8', name: '发现规则1', desc: '' },
// { id: 'domain9', name: '营业执照', desc: '按营业执照字段查询' },
// { id: 'domain10', name: '邮政编码', desc: '邮政编码字段查找' }
// ]
// }
])
const selectedDomains = ref(['domain2', 'domain3', 'domain4', 'domain6', 'domain7', 'domain9', 'domain10'])
const selectedDomains = ref([])
// 计算属性
const filteredDatabases = computed(() => {
......@@ -447,12 +448,13 @@ const selectedDbDetails = computed(() => {
})
const selectedDomainDetails = computed(() => {
const allDomains = domainGroups.value.flatMap(group => group.domains)
const allDomains = domainGroups.value.flatMap(group => group.list)
return allDomains.filter(domain => selectedDomains.value.includes(domain.id))
})
// 方法
const handleSelectAll = (val) => {
console.log('selectedDbs',selectedDbs)
if (val) {
selectedDbs.value = filteredDatabases.value.map(db => db.tid)
} else {
......@@ -464,21 +466,69 @@ const handleClearSelected = () => {
selectedDbs.value = []
selectAll.value = false
}
const allSchemasCompute = computed(() => {
return allSchemas.value[allSchemasIndex.value]
})
const allSchemasIndex = ref(0)
const selectDataSource = (dbId) => {
const selectDataSource = (dbId,index) => {
selectedDataSource.value = dbId
allSchemasIndex.value = index
console.log('allSchemasCompute.value',allSchemasCompute.value)
selectedSchemas.value = []
console.log('已经选择的表',schemalist.value)
allSchemasCompute.value.forEach(element => {
if(schemalist.value.find(item => item.schemaname === element.value && (item.osdsid ==selectedDbDetails.value[allSchemasIndex.value].tid))){
selectedSchemas.value.push(element.value)
}
});
}
const handleSelectAllSchemas = (val) => {
console.log('selectedSchemas.value',selectedSchemas.value)
// return
if (val) {
selectedSchemas.value = [...allSchemas.value]
let list = []
allSchemasCompute.value.forEach(element => {
list.push(element.value)
});
selectedSchemas.value = list
} else {
selectedSchemas.value = []
}
}
const schemalist = ref([])
const schemaChange = () =>{
console.log('allSchemasIndex.value',allSchemasIndex.value)
console.log('selectedSchemas.value ',selectedSchemas.value)
console.log('selectedDbDetails.value',selectedDbDetails.value)
// schemalist.value = []
selectedSchemas.value.forEach(element => {
console.log('element',element)
let data = {
schemaname: element,
dbtype:selectedDbDetails.value[allSchemasIndex.value].dbtype,
osdsid:selectedDbDetails.value[allSchemasIndex.value].tid,
}
schemalist.value.push(data)
});
}
const toggleGroupSelection = (group, selected) => {
const groupDomainIds = group.domains.map(d => d.id)
const groupDomainIds = group.list.map(d => d.id)
if (selected) {
const newSelected = [...new Set([...selectedDomains.value, ...groupDomainIds])]
......@@ -555,13 +605,31 @@ const handleNextStep = async () => {
// 其他步骤直接前进
activeStep.value++
getAllDataAreaAndRule().then(res=>{
console.log(res)
domainGroups.value = res.data
})
} else {
console.log('selectedDomainDetails',selectedDomainDetails.value)
// 最后一步提交数据
formData.value.databases = selectedDbDetails.value
formData.value.schemas = selectedSchemas.value
formData.value.domains = selectedDomainDetails.value
formData.value.schemas = schemalist.value
formData.value.domains = selectedDomainDetails.value.map(item=>(({
dataarea_id:item.dataarea_id,
rule_id:item.id
})))
emit('submit', formData.value)
setTimeout(() => {
reset()
dialogVisible.value = false
}, 300);
}
}
// 第一步验证接口函数
......@@ -613,15 +681,17 @@ watch(selectedDbs, (newVal) => {
selectAll.value = newVal.length > 0 && newVal.length === allDatabases.value.length
})
watch(selectedSchemas, (newVal) => {
selectAllSchemas.value = newVal.length === allSchemas.value.length
}, { deep: true })
watch(selectedDomains, (newVal) => {
if(domainGroups.value.length>0){
console.log('domainGroups',domainGroups.value)
domainGroups.value.forEach(group => {
const groupDomainIds = group.domains.map(d => d.id)
const groupDomainIds = group.list.map(d => d.id)
group.selectedAll = groupDomainIds.every(id => newVal.includes(id))
})
}
}, { deep: true })
// 初始化时自动选择第一个数据源
......@@ -630,6 +700,7 @@ watch(selectedDbDetails,async (newVal,oldVal) => {
if(newVal.length > 0){
if(JSON.stringify(newVal) !== JSON.stringify(oldVal)){
await fetchAllSchemas(newVal)
}
......@@ -675,7 +746,7 @@ const fetchAllSchemas = async (databases) => {
// 合并成功的数据
successResults.forEach(res => {
if (res.data && Array.isArray(res.data)) {
allSchemas.value = [...allSchemas.value, ...res.data]
allSchemas.value.push(res.data)
}
})
......@@ -687,7 +758,7 @@ const fetchAllSchemas = async (databases) => {
if (errorResults.length > 0) {
console.log(`${errorResults.length} 个数据库的Schema获取失败`)
}
console.log('allSchemas',allSchemas.value)
} catch (error) {
console.error('获取Schema数据过程中出错:', error)
ElMessage.error('获取Schema数据过程中出错')
......@@ -697,17 +768,107 @@ const fetchAllSchemas = async (databases) => {
}
const processAreaAndRuleList = (areaAndRuleList) => {
if (!areaAndRuleList || !Array.isArray(areaAndRuleList)) return
// 获取所有数据域分组信息
getAllDataAreaAndRule().then(res => {
console.log('所有数据域分组:', res.data)
// 处理已选择的数据域
const selectedDomainIds = []
// 将接口返回的数据映射到 domainGroups
domainGroups.value = res.data.map(group => {
// 处理组内的每个规则
const processedList = group.list.map(domain => {
// 检查这个规则是否在已选择的列表中
const isSelected = areaAndRuleList.some(item =>
item.dataarea_id === group.dataarea_id && item.rule_id === domain.id
)
if (isSelected) {
selectedDomainIds.push(domain.id)
}
return {
...domain,
dataarea_id: group.dataarea_id // 添加数据域ID引用
}
})
// 检查是否全选
const groupDomainIds = processedList.map(d => d.id)
const selectedInGroup = selectedDomainIds.filter(id => groupDomainIds.includes(id))
group.selectedAll = selectedInGroup.length === groupDomainIds.length && groupDomainIds.length > 0
return {
...group,
list: processedList
}
})
// 设置已选择的数据域
selectedDomains.value = selectedDomainIds
console.log('已选择的数据域ID:', selectedDomains.value)
})
}
// 处理Schema数据
const processSchemaList = (schemaList) => {
if (!schemaList || !Array.isArray(schemaList)) return
// 获取所有数据源的Schema信息
fetchAllSchemas(selectedDbDetails.value).then(() => {
// 设置已选择的Schema
selectedSchemas.value = schemaList.map(item => item.schemaname)
// 构建schemalist用于表单提交
schemalist.value = schemaList.map(item => ({
schemaname: item.schemaname,
dbtype: item.dbtype,
osdsid: item.osdsid
}))
console.log('已选择的Schema:', selectedSchemas.value)
console.log('用于提交的schemalist:', schemalist.value)
})
}
// 监听传入的项目数据变化
watch(() => props.projectData, (newVal) => {
if (props.mode === 'edit') {
formData.value = { ...newVal }
getDataProjectDetail({projectId:newVal.id}).then(res => {
if(res.flag){
let data = res.data
if(!data) return
formData.value.name = data.project.project
formData.value.remark = data.project.note
selectedDbs.value = data.dataSourceIdList.map(item => item.systemsource_id)
// selectedSchemas.value = data.schemalist.map(item =>item.schemaname)
// selectedDomains.value = data.areaAndRuleList.map(item =>item.id)
// console.log('selectedSchemas',selectedSchemas.value)
// 处理Schema数据
processSchemaList(data.schemalist)
// let list = data.areaAndRuleList
processAreaAndRuleList(data.areaAndRuleList)
}else{
ElMessage.error(res.msg)
}
}).catch(err =>{
ElMessage.error(res.msg)
})
// 初始化选中状态
selectedDbs.value = newVal.databases.map(db => db.id)
selectedSchemas.value = [...newVal.schemas]
selectedDomains.value = newVal.domains.map(domain => domain.id)
// selectedDbs.value = newVal.databases.map(db => db.id)
// selectedSchemas.value = [...newVal.schemas]
// selectedDomains.value = newVal.domains.map(domain => domain.id)
}
}, { immediate: true, deep: true })
</script>
......@@ -874,6 +1035,8 @@ watch(() => props.projectData, (newVal) => {
border: 1px solid #ebeef5;
border-radius: 4px;
background-color: #f8f8f8;
height: 500px;
overflow-y: auto;
}
.section-header {
......
<script setup name="ProjectManageList">
import { getCurrentInstance, reactive, ref, toRefs,onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import { ElMessage,ElMessageBox } from 'element-plus'
import QueryForm from './QueryForm.vue'
import ProjectEditDialog from './ProjectEditDialog.vue'
import DownloadPluginDialog from './DownloadPluginDialog.vue'
......@@ -10,7 +10,9 @@ import {changeRoute} from '@/utils/switchRoute'
import {
selectDataProject,
checkProjectNum,
getdatascopeprojectlist
addDataProject,
deleteDataProject,
updateDataProject
} from '@/api/project'
import useAppStore from '@/store/modules/app'
......@@ -201,7 +203,7 @@ const handleCommandProject = (command, project) => {
const handleEnterProject = (project) => {
console.log('进入项目:', project)
changeRoute()
sessionStorage.setItem('projectId',project.id)
router.push({ path:'/indexManage/ItemManage',query: { projectId: project.id } })
......@@ -215,8 +217,39 @@ const handleEditProject = (project) => {
// 删除项目
const handleDeleteProject = (project) => {
const handleDeleteProject = (val) => {
ElMessageBox.confirm(
`确定要删除项目「${val.project}」吗?此操作不可恢复。`,
'删除确认',
{
confirmButtonText: '确认删除',
cancelButtonText: '取消',
type: 'warning',
center: true,
callback: (action) => {
if (action === 'confirm') {
// 执行删除操作
let parms = {
loginUser:loginUser,
project:val
}
deleteDataProject(parms).then(res=>{
if(res.flag){
ElMessage.success(`项目「${val.project}」已删除`);
}else{
ElMessage.info(res.msg);
}
}).catch(err=>{
ElMessage.info(res.msg);
})
} else {
ElMessage.info('已取消删除');
}
}
}
);
}
// 导入项目
......@@ -245,22 +278,66 @@ const handleSubmit = (formData) => {
if (dialogMode.value === 'add') {
// 模拟新增
const newProject = {
id: tableList.value.length + 1,
proName: formData.proName,
datasource: '待配置',
domain: '待配置',
findRule: '待配置'
loginUser:loginUser,
project:{
edition_id: '',
note: formData.remark,
project: formData.name,
projectType: "normal",
},
schemalist:formData.schemas,
areaAndRuleList:formData.domains,
dataSourceIdList:formData.databases.map(item =>(({
id:item.tid,
sysname:item.sysname,
systemstyle:1,
dbtype:item.dbtype
})))
}
tableList.value.push(newProject)
total.value++
addDataProject(newProject).then(res=>{
console.log(res)
if(res.flag){
ElMessage.success('新增项目成功')
handleQuery()
}
})
// tableList.value.push(newProject)
// total.value++
// ElMessage.success('新增项目成功')
} else {
// 模拟编辑
const index = tableList.value.findIndex(p => p.id === currentProject.value.id)
if (index !== -1) {
tableList.value[index].proName = formData.proName
ElMessage.success('编辑项目成功')
const newProject = {
loginUser:loginUser,
project:{
edition_id: '',
note: formData.remark,
project: formData.name,
id:formData.id,
projectType: "normal",
},
schemalist:formData.schemas,
areaAndRuleList:formData.domains,
dataSourceIdList:formData.databases.map(item =>(({
id:item.tid,
sysname:item.sysname,
systemstyle:1,
dbtype:item.dbtype
})))
}
console.log('newProject',newProject)
updateDataProject(newProject).then(res=>{
console.log(res)
if(res.flag){
ElMessage.success('新增项目成功')
handleQuery()
}
})
}
}
......
<script setup name="Algorithm">
import { onMounted, ref, toRefs } from 'vue'
import { Split } from 'view-ui-plus';
import { ElMessage } from "element-plus";
import CollapseView from '@/components/CollapseView/index.vue'
import formModule from './modules/formModule.vue'
import ModalPop from "@/components/EditPop/ModalPop.vue"
import { query } from '@/api/ruleConfig/algorithm.js'
import { query, del } from '@/api/ruleConfig/algorithm.js'
const splitNum = ref(0.31) // 左右分割比例
const collapseList = ref([])
const rulenameList = ref([]) // 规则名称列表
const searchValue = ref('')
const data = reactive({
formEdit: {
name: "",
},
formAdd: {
name: "",
addForm: {},
editForm: {},
delData: {
id: ''
}
});
const { formEdit, formAdd } = toRefs(data);
const { addForm, editForm, delData } = toRefs(data);
const modalData = reactive({
show: false,
......@@ -33,26 +34,41 @@ const modalData = reactive({
const modalPopShow = ref(false)
// 获取数据
const getCollapse = () => {
query({dataarea: searchValue.value}).then(res => {
const getCollapse = (type) => {
query({ dataarea: searchValue.value }).then(res => {
rulenameList.value = []
const { data } = res
collapseList.value = data.map(item => {
const list = item.ruleList.map(itemTwo => {
rulenameList.value.push(itemTwo.rulename)
return {
...itemTwo,
name: itemTwo.rulename,
defaulttype: itemTwo.defaluttype,
isCheck: false,
isDelete: true,
}
})
return {
...item,
list: list,
isAdd: true,
isView: false,
isDelete: false,
}
})
if (type === 'edit') return
if (collapseList.value.length <= 0) return
if (collapseList.value[0].ruleList.length > 0) {
editForm.value = collapseList.value[0].ruleList[0]
} else {
const { id } = collapseList.value[0]
editForm.value = {
dataarea_id: id
}
}
})
// collapseList.value = data.map(item => {
// const list = item.list.map(itemTwo => {
// return {
// ...itemTwo,
// isCheck: false,
// isDelete: true,
// }
// })
// return {
// ...item,
// list: list,
// isAdd: true,
// isView: false,
// isDelete: false,
// }
// })
}
// 新增算法关闭
......@@ -62,32 +78,50 @@ const modalPopCancel = () => {
// 新增算法
const collapseAdd = (item) => {
console.log('添加事件', item)
formAdd.value = {}
// console.log('添加事件', item)
const { id } = item
addForm.value = {
dataarea_id: id
}
modalPopShow.value = true
}
// 删除事件
const collapseDelete = (item) => {
console.log('删除事件', item)
// console.log('删除事件', item)
const { rulename } = item
delData.value = item
modalData.show = true
modalData.icon = 'error'
modalData.text = '删除后无法恢复,是否确认删除[' + item.name + ']?'
modalData.text = '删除后无法恢复,是否确认删除[' + rulename + ']?'
}
// 删除回调
const modalConfirm = () => {
const { id } = delData.value
const data = {
ruleId: id
}
del(data).then(res => {
const { flag } = res
if (flag) {
ElMessage.success('删除成功')
getCollapse()
modalData.show = false
} else {
ElMessage.error('删除失败')
}
})
}
// 点击监听
const collapseChange = (item) => {
formEdit.value = item
editForm.value = item.item
}
// 算法确认
const formModuleConfirm = (item) => {
console.log('新增算法', item)
const formModuleConfirm = (val) => {
getCollapse(val)
modalPopShow.value = false
}
......@@ -106,7 +140,7 @@ onMounted(() => {
<div class="app-container__body">
<Split v-model="splitNum">
<template #left>
<div class="demo-split-pane" style="padding: 0 38px 10px 0;width: 100%;overflow: auto;height: 100%;">
<div class="demo-split-pane" style="padding: 0 38px 10px 0;width: 100%;overflow: auto;height: 100%;display: flex;flex-direction: column;">
<el-input class="mb20" v-model="searchValue" placeholder="脱敏规则搜索">
<template #suffix>
<el-icon style="vertical-align: middle;cursor: pointer;" @click="getCollapse">
......@@ -114,7 +148,10 @@ onMounted(() => {
</el-icon>
</template>
</el-input>
<CollapseView :list="collapseList" @add="collapseAdd" @childDelete="collapseDelete" @change="collapseChange" />
<el-scrollbar style="width: 100%;flex: 1;padding-right: 38px;">
<CollapseView :list="collapseList" @add="collapseAdd" @childDelete="collapseDelete"
@change="collapseChange" />
</el-scrollbar>
</div>
</template>
<template #right>
......@@ -127,7 +164,7 @@ onMounted(() => {
<span style="margin-left: 5px;">脱敏规则</span>
</div>
<div class="right-content">
<formModule v-model="formEdit" type="edit" />
<formModule :itemData="editForm" :nameList="rulenameList" type="edit" @confirm="formModuleConfirm" />
</div>
</div>
</div>
......@@ -139,9 +176,10 @@ onMounted(() => {
@confirm="modalConfirm"></Modal>
<!-- 新增算法 -->
<ModalPop v-model="modalPopShow" title="编辑器" @cancel="modalPopCancel">
<ModalPop v-model="modalPopShow" title="新增算法" @cancel="modalPopCancel">
<template #content>
<formModule v-model="formAdd" type="add" @cancel="modalPopCancel" @confirm="formModuleConfirm" />
<formModule :itemData="addForm" :nameList="rulenameList" type="add" @cancel="modalPopCancel"
@confirm="formModuleConfirm" />
</template>
</ModalPop>
</div>
......
<script setup lang="ts" name="Form">
import { onMounted, reactive, ref, toRefs, watch } from "vue";
import { Switch } from "view-ui-plus";
import ExpressionEditor from '@/components/EditPop/ExpressionEditor.vue'
import type { FormInstance } from "element-plus";
import { ElMessage } from "element-plus";
import ExpressionEditor from "@/components/EditPop/ExpressionEditor.vue";
import { save } from "@/api/ruleConfig/algorithm";
const props = defineProps<{
modelValue: boolean;
itemData: Object;
type: string;
nameList: any;
}>();
const emit = defineEmits(["update:modelValue", 'cancel','confirm']);
const emit = defineEmits(["cancel", "confirm"]);
const data = reactive({
rules: {},
form: <any>{
dataarea_id: "",
defaluttype: "0",
expression: "",
id: "",
rulename: "",
rulesource: "",
},
rules: {
expression: [
{
required: true,
message: "请输入表达式",
trigger: ["blur"],
},
],
},
});
const { rules } = toRefs(data);
const { form, rules } = toRefs(data);
const editorShow = ref(false);
const readOnly = ref(true);
const editor = ref({});
const rulenameList = ref([])
const formRef = ref<FormInstance>();
watch(
() => props.type,
(newVal) => {
readOnly.value = props.type === 'edit' ? true : false;
},
{ deep: true, immediate: true }
);
// 重置
const reset = () => {
form.value = {
dataarea_id: "",
defaulttype: "0",
enc_name: "",
encryption_id: "",
secretkey_id: "",
};
};
// 打开编辑器
const openEditor = () => {
editorShow.value = true
editor.value = props.modelValue
}
editorShow.value = true;
editor.value = form.value.expression;
};
// 取消
const cancel = () => {
if (props.type === 'edit') {
readOnly.value = true
}else if (props.type === 'add') {
emit('cancel')
if (props.type === "edit") {
readOnly.value = true;
const data = JSON.parse(JSON.stringify(props.itemData));
form.value = { ...form.value, ...data };
} else if (props.type === "add") {
emit("cancel");
}
}
};
const confirm = () => {
if (props.type === 'edit') {
readOnly.value = true
formRef.value?.validate((valid) => {
if (valid) {
saveFunc();
} else {
}
emit('confirm')
}
});
};
const saveFunc = () => {
if (props.type === "edit") {
form.value = { ...form.value, ...{ id: form.value.id } };
}
save(form.value).then((res) => {
const { flag } = res;
if (flag) {
ElMessage.success(
props.type === "add" || !form.value.id ? "新增成功" : "修改成功"
);
if (props.type === "edit") {
readOnly.value = true;
} else if (props.type === "add") {
reset();
}
emit("confirm", props.type);
}
});
};
// 算法名称验证
const validateRulename = (rule, value, callback) => {
if (form.value.id && form.value.rulename === value) {
callback();
return false;
}
const state = rulenameList.value.includes(value);
if (state) {
callback(new Error('算法名称已存在'));
} else {
callback();
}
};
// 编辑器确认
const formConfirm = (val) => {
editorShow.value = false
props.modelValue.name = val
}
editorShow.value = false;
form.value.expression = val;
};
watch(
() => props.type,
(newVal) => {
readOnly.value = props.type === "edit" ? true : false;
},
{ deep: true, immediate: true }
);
watch(
() => props.itemData,
(newVal) => {
if (props.itemData) {
const data = JSON.parse(JSON.stringify(props.itemData));
form.value = { ...form.value, ...data };
if (props.type === 'edit') {
rulenameList.value = rulenameList.value.filter(item => item !== data.rulename)
}
}
},
{ deep: true, immediate: true }
);
watch(
() => props.nameList,
(newVal) => {
rulenameList.value = props.nameList;
const data = JSON.parse(JSON.stringify(props.itemData));
if (props.type === 'edit' && data) {
rulenameList.value = rulenameList.value.filter(item => item !== data.rulename)
}
},
{ deep: true, immediate: true }
);
</script>
<template>
<div>
<el-form ref="formRef" :model="modelValue" label-width="100px" :disabled="readOnly">
<el-form-item label="算法名称" required>
<el-input v-model="modelValue.name"></el-input>
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px" :disabled="readOnly">
<el-form-item label="算法名称" prop="rulename" required
:rules="[{ required: true, message: '请输入算法名称', trigger:'blur' },{ required: true, validator: validateRulename, trigger:'blur' }]">
<el-input v-model="form.rulename"></el-input>
</el-form-item>
<el-form-item label="表达式" required>
<el-input type="textarea" rows="8" v-model="modelValue.name"></el-input>
<el-form-item label="表达式" prop="expression" required>
<el-input type="textarea" rows="8" v-model="form.expression"></el-input>
<el-button class="openEditor" type="primary" @click="openEditor">打开编辑器</el-button>
</el-form-item>
<el-form-item label="默认规则">
<Switch :disabled="readOnly">
<Switch true-value="1" false-value="0" v-model="form.defaluttype" :disabled="readOnly">
<template #open>
<span></span>
</template>
......@@ -86,7 +182,7 @@ const formConfirm = (val) => {
<el-button type="primary" style="width: 150px;" @click="confirm" v-if="!readOnly">确认</el-button>
</div>
<ExpressionEditor v-model="editorShow" :data="editor" @cancel=" editorShow = false" @confirm="formConfirm" />
<ExpressionEditor v-model="editorShow" :rulename="editor" @cancel=" editorShow = false" @confirm="formConfirm" />
</div>
</template>
......
......@@ -14,9 +14,8 @@ const collapseList = ref([])
const encryptionList = ref([]) // 加密规则列表
const data = reactive({
formData: {
name: "",
},
addForm: {},
editForm: {},
queryParams: {
dataarea: ''
},
......@@ -25,7 +24,7 @@ const data = reactive({
}
});
const { formData, queryParams, delData } = toRefs(data);
const { addForm, editForm, queryParams, delData } = toRefs(data);
const modalData = reactive({
show: false,
......@@ -37,7 +36,7 @@ const modalData = reactive({
const modalPopShow = ref(false)
// 获取数据
const getCollapse = () => {
const getCollapse = (type) => {
query(queryParams.value).then(res => {
const { data } = res
collapseList.value = data.map(item => {
......@@ -57,14 +56,15 @@ const getCollapse = () => {
isDelete: false,
}
})
if (type === 'edit') return
if (collapseList.value.length <= 0) return
if (collapseList.value[0].secretkeyList.length > 0) {
formData.value = {
editForm.value = {
dataarea_id: collapseList.value[0].id,
...collapseList.value[0].secretkeyList[0]
}
} else {
formData.value = {
editForm.value = {
dataarea_id: collapseList.value[0].id
}
}
......@@ -80,7 +80,7 @@ const modalPopCancel = () => {
const collapseAdd = (item) => {
// console.log('添加事件', item)
const { id } = item
formData.value = {
addForm.value = {
dataarea_id: id
}
modalPopShow.value = true
......@@ -88,7 +88,7 @@ const collapseAdd = (item) => {
// 删除事件
const collapseDelete = (item) => {
console.log('删除事件', item)
// console.log('删除事件', item)
const { name } = item
delData.value = item
modalData.show = true
......@@ -112,21 +112,20 @@ const modalConfirm = () => {
ElMessage.error('删除失败')
}
})
}
// 点击监听
const collapseChange = (item) => {
console.log('修改事件', item)
formData.value = {
// console.log('修改事件', item)
editForm.value = {
...item.item
}
}
// 算法确认
const formModuleConfirm = (item) => {
console.log('新增算法', item)
getCollapse()
const formModuleConfirm = (val) => {
// console.log('新增算法', val)
getCollapse(val)
modalPopShow.value = false
}
......@@ -183,7 +182,7 @@ onMounted(() => {
<span style="margin-left: 5px;">加密算法</span>
</div>
<div class="right-content">
<formModule :itemData="formData" :encryptionDict="encryptionList" type="edit" @cancel="modalPopCancel"
<formModule :itemData="editForm" :encryptionDict="encryptionList" type="edit" @cancel="modalPopCancel"
@confirm="formModuleConfirm" />
</div>
</div>
......@@ -196,9 +195,9 @@ onMounted(() => {
@confirm="modalConfirm"></Modal>
<!-- 新增加密算法 -->
<ModalPop v-model="modalPopShow" title="编辑器" @cancel="modalPopCancel">
<ModalPop v-model="modalPopShow" width="800px" title="新增加密算法" @cancel="modalPopCancel">
<template #content>
<formModule :itemData="formData" :encryptionDict="encryptionList" type="add" @cancel="modalPopCancel"
<formModule :itemData="addForm" :encryptionDict="encryptionList" type="add" @cancel="modalPopCancel"
@confirm="formModuleConfirm" />
</template>
</ModalPop>
......
<script setup lang="ts" name="Form">
import { onMounted, reactive, ref, toRefs, watch } from "vue";
import { onMounted, reactive, ref, toRefs, watch, computed } from "vue";
import { Switch } from "view-ui-plus";
import type { FormInstance } from "element-plus";
import { ElMessage } from "element-plus";
......@@ -47,10 +47,10 @@ const data = reactive({
});
const { form, rules } = toRefs(data);
const encryptionList = ref<any[]>([]); // 加密规则选项列表
const secretkeyList = ref<any[]>([]); // 密钥选项列表
const readOnly = ref(true);
const formRef = ref<FormInstance>();
const encryptionList = computed(() => props.encryptionDict); // 加密规则选项列表
// 重置
const reset = () => {
......@@ -85,7 +85,7 @@ const confirm = () => {
};
const saveFunc = () => {
console.log(form.value)
// console.log(form.value)
if (props.type === "edit") {
form.value = { ...form.value, ...{ id: form.value.id } }
}
......@@ -135,9 +135,6 @@ watch(
() => props.itemData,
(newVal) => {
if (props.itemData) {
if (!props.itemData.enc_name) {
reset()
}
const data = JSON.parse(JSON.stringify(props.itemData));
form.value = { ...form.value, ...data };
if (props.type === "edit" && form.value.secretkey_id) {
......@@ -148,13 +145,6 @@ watch(
{ deep: true, immediate: true }
);
watch(
() => props.encryptionDict,
(newVal) => {
encryptionList.value = props.encryptionDict;
},
{ deep: true, immediate: true }
);
</script>
<template>
......
<script setup lang="ts" name="AddValue">
import { onMounted, reactive, ref, toRefs, watch } from "vue";
import { onMounted, reactive, ref, toRefs, watch, computed } from "vue";
import type { FormInstance } from "element-plus";
import { ElMessage } from "element-plus";
......@@ -36,7 +36,7 @@ const data = reactive({
const { form, rules } = toRefs(data);
const formRef = ref<FormInstance>();
const classDictList = ref<any[]>([]);
const classDictList = computed(() => props.classDict);
// 重置
const reset = () => {
......@@ -81,20 +81,12 @@ watch(
() => props.itemData,
(newVal) => {
if (props.itemData) {
const data = JSON.parse(JSON.stringify(props.itemData))
form.value = {...form.value, ...data}
const data = JSON.parse(JSON.stringify(props.itemData));
form.value = { ...form.value, ...data };
}
},
{ deep: true, immediate: true }
);
watch(
() => props.classDict,
(newVal) => {
classDictList.value = props.classDict;
},
{ deep: true, immediate: true }
);
</script>
<template>
......
......@@ -30,29 +30,12 @@ const { form, rules } = toRefs(data);
const readOnly = ref(true);
const formRef = ref<FormInstance>();
watch(
() => props.type,
(newVal) => {
readOnly.value = props.type === 'edit' ? true : false;
},
{ deep: true, immediate: true }
);
watch(
() => props.itemData,
(newVal) => {
if (props.type === 'edit' && props.itemData) {
form.value = JSON.parse(JSON.stringify(props.itemData))
}
},
{ deep: true, immediate: true }
);
// 取消
const cancel = () => {
if (props.type === 'edit') {
form.value = props.itemData
readOnly.value = true
const data = JSON.parse(JSON.stringify(props.itemData));
form.value = { ...form.value, ...data };
} else if (props.type === 'add') {
emit('cancel')
form.value = {}
......@@ -107,6 +90,24 @@ const addDataAreaFun = () => {
})
}
watch(
() => props.type,
(newVal) => {
readOnly.value = props.type === 'edit' ? true : false;
},
{ deep: true, immediate: true }
);
watch(
() => props.itemData,
(newVal) => {
if (props.type === 'edit' && props.itemData) {
const data = JSON.parse(JSON.stringify(props.itemData));
form.value = { ...form.value, ...data };
}
},
{ deep: true, immediate: true }
);
</script>
......
<script setup name="Discover">
import { onMounted, ref, toRefs } from 'vue'
import { Split } from 'view-ui-plus';
import { ElMessage } from 'element-plus'
import CollapseView from '@/components/CollapseView/index.vue'
import AddEncryption from './modules/AddEncryption.vue' // 加密表单
import AddKey from './modules/AddKey.vue' // 密钥表单
import ModalPop from "@/components/EditPop/ModalPop.vue"
import { query, initEncryptionTypeList, getDictinaryTypes, deleteType, delSecretKey } from '@/api/ruleConfig/encryption'
const splitNum = ref(0.31) // 左右分割比例
const collapseList = ref([])
const collapseList = ref([]) // 左侧列表数据
const encryptionTypeList = ref([]) // 加密类型列表
const dictinaryTypes = ref([]) // 字典类型列表
const typeNameList = ref([]) // 分类名称列表
const keyNameList = ref([]) // 分类名称列表
const data = reactive({
editEncryptionForm: {
name: "",
},
addEncryptionForm: {
name: "",
encryptionForm: {},
keyForm: {},
queryParams: {
encryption_name: ''
},
editKeyForm: {
name: "",
},
addKeyForm: {
name: "",
delData: {
id: ''
}
});
const { editEncryptionForm, addEncryptionForm, editKeyForm, addKeyForm } = toRefs(data);
const { encryptionForm, keyForm, queryParams, delData } = toRefs(data);
const rightType = ref('encryption') // 右侧展示类型
const modalData = reactive({
show: false,
......@@ -42,48 +44,40 @@ const modalPopData = reactive({
})
// 获取数据
const getCollapse = () => {
const data = [
{
name: '测试加密',
list: [
{
name: '按混合证件号字段查询'
}
]
},
{
name: '通用规则',
list: [
{
name: 'aaaaa'
},
{
name: 'bbbbb'
}
]
},
{
name: '解密数据',
list: []
}
]
const getCollapse = (type) => {
query(queryParams.value).then(res => {
const { data } = res
collapseList.value = data.map(item => {
const list = item.list.map(itemTwo => {
return {
...itemTwo,
name: itemTwo.secret_key_name,
isCheck: false,
isDelete: true,
}
})
return {
...item,
dataarea: item.encryption_name,
list: list,
isAdd: true,
isView: true,
isDelete: true,
}
})
if (type === 'edit') return
if (collapseList.value.length <= 0) return
modalData.type = 'encryption'
encryptionForm.value = collapseList.value[0]
})
}
// 获取加密类型列表
const getInitEncryptionTypeList = () => {
initEncryptionTypeList({}).then(res => {
const { data } = res
encryptionTypeList.value = data
})
}
// 新增关闭
......@@ -93,78 +87,119 @@ const modalPopCancel = () => {
// 新增加密
const addDomainClick = (item) => {
console.log('新增加密')
typeNameList.value = []
collapseList.value.forEach(item => {
typeNameList.value.push(item.encryption_name)
})
modalPopData.title = '新增加密'
modalPopData.type = 'encryption'
addEncryptionForm.value = {}
encryptionForm.value = {}
modalPopData.show = true
}
// 新增密钥
const collapseAdd = (item) => {
console.log('新增密钥', item)
keyNameList.value = []
item.list.forEach(item => {
keyNameList.value.push(item.secret_key_name)
})
const { encryption_name, encryption_type, id } = item
modalPopData.title = '新增密钥'
modalPopData.type = 'key'
addKeyForm.value = {}
keyForm.value = {
encryption_name: encryption_name,
encryption_type: encryption_type,
encryption_id: id
}
modalPopData.show = true
}
// 删除密钥
const collapseDelete = (item) => {
console.log('删除密钥', item)
modalData.type = 'key'
modalData.cancel = true
modalData.icon = 'error'
modalData.text = '删除后无法恢复,是否确认删除[' + item.name + ']?'
modalData.show = true
}
// 删除加密
const collapseMainDeletion = (item) => {
console.log('删除加密事件', item)
const { encryption_name } = item
delData.value = item
modalData.type = 'encryption'
modalData.cancel = false
modalData.icon = 'error'
modalData.text = '删除后无法恢复,是否确认删除[' + item.name + ']?'
modalData.text = '删除后无法恢复,是否确认删除[' + encryption_name + ']?'
modalData.show = true
}
// 删除密钥
const collapseDelete = (item) => {
const { secret_key_name } = item
delData.value = item
modalData.type = 'key'
modalData.cancel = true
modalData.icon = 'error'
modalData.text = '删除后无法恢复,是否确认删除[' + secret_key_name + ']?'
modalData.show = true
}
// 提示回调
const modalConfirm = () => {
if (modalData.type === 'encryption') {
console.log('删除加密确认')
const { id } = delData.value
deleteType({ encryptionId: id }).then(res => {
const { flag } = res
if (flag) {
ElMessage.success('删除成功')
getCollapse()
} else {
ElMessage.error('删除失败')
}
})
} else if (modalData.type === 'key') {
console.log('删除密钥确认')
} else if (modalData.type === 'default') {
console.log('设置默认项')
const { id } = delData.value
delSecretKey({ keyId: id }).then(res => {
const { flag } = res
if (flag) {
ElMessage.success('删除成功')
getCollapse()
} else {
ElMessage.error('删除失败')
}
})
}
modalData.show = false
}
// 加密查看
const collapseView = (item) => {
editEncryptionForm.value = item
typeNameList.value = []
collapseList.value.forEach(item => {
typeNameList.value.push(item.encryption_name)
})
encryptionForm.value = item
rightType.value = 'encryption'
}
// 规则点击监听
const collapseChange = (item) => {
editKeyForm.value = item
// 密钥点击监听
const collapseChange = (itemData) => {
const { parentItem, item } = itemData
const { encryption_name, encryption_type } = parentItem
keyNameList.value = []
parentItem.list.forEach(itemLi => {
keyNameList.value.push(itemLi.secret_key_name)
})
console.log('密钥点击监听', item)
keyForm.value = { ...item, ...{ encryption_name: encryption_name, encryption_type: encryption_type } }
rightType.value = 'key'
}
// 新增确认
const AddDomainConfirm = (item) => {
const AddFormConfirm = (item) => {
if (modalPopData.type === 'encryption') {
console.log('新增加密确认', item)
getCollapse(item)
} else if (modalPopData.type === 'key') {
console.log('新增密钥确认', item)
getCollapse(item)
}
modalPopData.show = false
}
onMounted(() => {
getCollapse()
getInitEncryptionTypeList()
})
</script>
......@@ -184,17 +219,17 @@ onMounted(() => {
<el-button class="mr10" icon="Download" type="primary">备份</el-button>
</div>
<div class="mb20" style="display: flex;align-items: center;justify-content: space-between;">
<el-input class="mr20" placeholder="加密方式搜索">
<el-input class="mr20" v-model="queryParams.encryption_name" placeholder="加密方式搜索">
<template #suffix>
<el-icon style="vertical-align: middle;">
<el-icon style="vertical-align: middle;cursor: pointer;" @click="getCollapse">
<search />
</el-icon>
</template>
</el-input>
<el-button type="primary" icon="Plus" @click="addDomainClick">新增加密</el-button>
</div>
<CollapseView :list="collapseList" @add="collapseAdd" @mainDeletion="collapseMainDeletion" @childDelete="collapseDelete"
@change="collapseChange" @view="collapseView" />
<CollapseView :list="collapseList" @add="collapseAdd" @mainDeletion="collapseMainDeletion"
@childDelete="collapseDelete" @change="collapseChange" @view="collapseView" />
</div>
</template>
<template #right>
......@@ -207,8 +242,11 @@ onMounted(() => {
<span style="margin-left: 5px;">{{ rightType === 'encryption' ? '加密定义' : '密钥定义' }}</span>
</div>
<div class="right-content">
<AddEncryption v-model="editEncryptionForm" type="edit" v-if="rightType === 'encryption'" />
<AddKey v-model="editKeyForm" type="edit" v-if="rightType === 'key'" />
<AddEncryption :itemData="encryptionForm" :encryptionTypeDict="encryptionTypeList"
:typeNameDict="typeNameList" type="edit" v-if="rightType === 'encryption'" @cancel="modalPopCancel"
@confirm="AddFormConfirm" />
<AddKey :itemData="keyForm" :encryptionTypeDict="encryptionTypeList" :keyNameDict="keyNameList"
type="edit" v-if="rightType === 'key'" @cancel="modalPopCancel" @confirm="AddFormConfirm" />
</div>
</div>
</div>
......@@ -222,10 +260,10 @@ onMounted(() => {
<!-- 新增加密 / 密钥 -->
<ModalPop :width="'850'" v-model="modalPopData.show" :title="modalPopData.title" @cancel="modalPopCancel">
<template #content>
<AddEncryption v-model="addEncryptionForm" type="add" @cancel="modalPopCancel" @confirm="AddDomainConfirm"
v-if="modalPopData.type === 'encryption'" />
<AddKey v-model="addKeyForm" type="add" @cancel="modalPopCancel" @confirm="AddDomainConfirm"
v-if="modalPopData.type === 'key'" />
<AddEncryption :itemData="encryptionForm" :encryptionTypeDict="encryptionTypeList" :typeNameDict="typeNameList"
type="add" @cancel="modalPopCancel" @confirm="AddFormConfirm" v-if="modalPopData.type === 'encryption'" />
<AddKey :itemData="keyForm" :encryptionTypeDict="encryptionTypeList" :keyNameDict="keyNameList" type="add"
@cancel="modalPopCancel" @confirm="AddFormConfirm" v-if="modalPopData.type === 'key'" />
</template>
</ModalPop>
</div>
......
<script setup lang="ts" name="AddDomain">
import { onMounted, reactive, ref, toRefs, watch } from "vue";
import { onMounted, reactive, ref, toRefs, watch, computed } from "vue";
import type { FormInstance } from "element-plus";
import { ElMessage } from 'element-plus'
import { save } from '@/api/ruleConfig/encryption'
const props = defineProps<{
modelValue: boolean;
itemData: Object;
type: string;
encryptionTypeDict: Array<any>;
typeNameDict: any;
}>();
const emit = defineEmits(["update:modelValue", 'cancel','confirm']);
const emit = defineEmits(['cancel','confirm']);
const data = reactive({
rules: {},
form: <any>{
},
rules: {
encryption_type: [
{
required: true,
message: "请选择加密方式",
trigger: ["change"],
},
],
},
});
const { rules } = toRefs(data);
const { form, rules } = toRefs(data);
const readOnly = ref(true);
watch(
() => props.type,
(newVal) => {
readOnly.value = props.type === 'edit' ? true : false;
},
{ deep: true, immediate: true }
);
const typeNameList = ref([])
const encryptionTypeOptions = computed(() => props.encryptionTypeDict)
const formRef = ref<FormInstance>();
// 取消
const cancel = () => {
if (props.type === 'edit') {
readOnly.value = true
}else if (props.type === 'add') {
const data = JSON.parse(JSON.stringify(props.itemData));
form.value = { ...form.value, ...data };
} else if (props.type === 'add') {
emit('cancel')
form.value = {}
}
}
const confirm = () => {
formRef.value?.validate((valid) => {
if (valid) {
addDataFun()
} else {
}
});
}
// 添加加密分类
const addDataFun = () => {
if (props.type === 'edit') {
form.value = {...form.value,...{id: form.value.id}}
}
save(form.value).then(res => {
const { flag } = res
if (flag) {
ElMessage.success((props.type === "add" || !form.value.id) ? "新增成功" : "修改成功");
if (props.type === 'edit') {
readOnly.value = true
} else if (props.type === 'add') {
form.value = {}
}
emit('confirm')
emit('confirm', props.type)
}
})
}
// 分类称验证
const validateRulename = (rule, value, callback) => {
const state = typeNameList.value.includes(value);
if (state) {
callback(new Error('加密名称已存在'));
} else {
callback();
}
};
watch(
() => props.type,
(newVal) => {
readOnly.value = props.type === 'edit' ? true : false;
},
{ deep: true, immediate: true }
);
watch(
() => props.itemData,
(newVal) => {
if (props.type === 'edit' && props.itemData) {
const data = JSON.parse(JSON.stringify(props.itemData));
form.value = { ...form.value, ...data };
if (props.type === 'edit') {
typeNameList.value = typeNameList.value.filter(item => item !== data.encryption_name)
}
}
},
{ deep: true, immediate: true }
);
watch(
() => props.typeNameDict,
(newVal) => {
typeNameList.value = props.typeNameDict
const data = JSON.parse(JSON.stringify(props.itemData));
if (props.type === 'edit' && data) {
typeNameList.value = typeNameList.value.filter(item => item !== data.encryption_name)
}
},
{ deep: true, immediate: true }
);
</script>
<template>
<div>
<el-form ref="formRef" :model="modelValue" label-width="100px" :disabled="readOnly">
<el-form-item label="加密名称" required>
<el-input v-model="modelValue.name"></el-input>
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px" :disabled="readOnly">
<el-form-item label="加密名称" prop="encryption_name" required :rules="[{ required: true, message: '请输入加密名称', trigger:'blur' },{ required: true, validator: validateRulename, trigger:'blur' }]">
<el-input v-model="form.encryption_name"></el-input>
</el-form-item>
<el-form-item label="加密方式" required>
<el-form-item label="加密方式" prop="encryption_type" required>
<div style="width: 100%;background: #F3F5FA;">
<el-input v-model="modelValue.name" v-if="readOnly"></el-input>
<el-select v-model="modelValue.name" v-if="!readOnly">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value">
<el-select v-model="form.encryption_type">
<el-option v-for="item in encryptionTypeOptions" :key="item.value" :label="item.text" :value="item.value">
</el-option>
</el-select>
</div>
</el-form-item>
<el-form-item label="备注">
<el-input type="textarea" rows="4" v-model="modelValue.name"></el-input>
<el-input type="textarea" rows="4" v-model="form.note"></el-input>
</el-form-item>
</el-form>
<div class="btn">
......@@ -76,4 +152,9 @@ const confirm = () => {
display: flex;
justify-content: center;
}
:deep(.el-form-item__error) {
left: auto;
right: 30px;
top: 24%;
}
</style>
\ No newline at end of file
<script setup lang="ts" name="AddRules">
import { onMounted, reactive, ref, toRefs, watch } from "vue";
import { Switch } from "view-ui-plus";
import { onMounted, reactive, ref, toRefs, watch, computed } from "vue";
import type { FormInstance } from "element-plus";
import { ElMessage } from "element-plus";
import { getRandomValue, testEncryption, saveSecretKey } from '@/api/ruleConfig/encryption'
const props = defineProps<{
modelValue: boolean;
itemData: Object;
type: string;
encryptionTypeDict: Array<any>;
keyNameDict: any;
}>();
const emit = defineEmits(["update:modelValue", "cancel", "confirm"]);
const emit = defineEmits(['cancel','confirm']);
const data = reactive({
rules: {},
});
const { rules } = toRefs(data);
form: <any>{
const readOnly = ref(true);
const radio = ref(1);
const radioOptions = ref([
{
label: "正则表达式",
value: 1,
},
rules: {
sectet_key_value: [
{
label: "自定义方法",
value: 2,
required: true,
message: "密钥值不能为空",
trigger: ["change"],
},
{
label: "字典发现",
value: 3,
],
},
]);
});
const { form, rules } = toRefs(data);
const readOnly = ref(true);
const testParam = ref(""); // 测试参数
const encryptedValue = ref(""); // 加密后的值
const formRef = ref<FormInstance>();
const keyNameList = ref([])
watch(
() => props.type,
(newVal) => {
readOnly.value = props.type === "edit" ? true : false;
},
{ deep: true, immediate: true }
);
// 取消
const cancel = () => {
if (props.type === "edit") {
readOnly.value = true;
const data = JSON.parse(JSON.stringify(props.itemData));
form.value = { ...form.value, ...data };
} else if (props.type === "add") {
emit("cancel");
}
};
const confirm = () => {
if (props.type === "edit") {
readOnly.value = true;
formRef.value?.validate((valid) => {
if (valid) {
saveSecretKeyFun()
} else {
}
});
};
// 添加密钥
const saveSecretKeyFun = () => {
const { encryption_id, secret_key_name, sectet_key_value, id } = form.value;
let data = {
encryption_id: encryption_id,
secret_key_name: secret_key_name,
sectet_key_value: sectet_key_value,
}
if (props.type === 'edit') {
data = {...data,...{id: id}}
}
saveSecretKey(data).then(res => {
const { flag } = res
if (flag) {
ElMessage.success((props.type === "add" || !form.value.id) ? "新增成功" : "修改成功");
if (props.type === 'edit') {
readOnly.value = true
} else if (props.type === 'add') {
form.value = {}
}
testParam.value = ""
encryptedValue.value = ""
emit('confirm', props.type)
}
})
}
// 密钥生成
const getKeyGeneration = () => {
const { encryption_type } = form.value;
getRandomValue({ type: encryption_type}).then((res) => {
const { flag, data } = res;
if (flag){
form.value.sectet_key_value = data;
}
});
};
// 测试
const getKeyText = () => {
const { encryption_type } = form.value;
if (!encryption_type) {
return ElMessage.error("密钥值不能为空!");
}
const data = {
param: testParam.value,
type: encryption_type,
secret_key: form.value.sectet_key_value,
}
testEncryption(data).then((res) => {
const { flag, data } = res;
if (flag){
encryptedValue.value = data;
}
});
}
// 分类称验证
const validateRulename = (rule, value, callback) => {
const state = keyNameList.value.includes(value);
if (state) {
callback(new Error('加密名称已存在'));
} else {
callback();
}
emit("confirm");
};
watch(
() => props.type,
(newVal) => {
readOnly.value = props.type === "edit" ? true : false;
},
{ deep: true, immediate: true }
);
watch(
() => props.itemData,
(newVal) => {
if (props.itemData) {
const data = JSON.parse(JSON.stringify(props.itemData));
form.value = { ...form.value, ...data };
if (props.type === 'edit' && data) {
keyNameList.value = keyNameList.value.filter(item => item !== data.secret_key_name)
}
}
},
{ deep: true, immediate: true }
);
watch(
() => props.keyNameDict,
(newVal) => {
keyNameList.value = props.keyNameDict
const data = JSON.parse(JSON.stringify(props.itemData));
if (props.type === 'edit' && data) {
keyNameList.value = keyNameList.value.filter(item => item !== data.secret_key_name)
}
},
{ deep: true, immediate: true }
);
</script>
<template>
<div>
<el-form ref="formRef" :model="modelValue" label-width="100px" :disabled="readOnly">
<el-form-item label="密钥名称" required>
<el-input v-model="modelValue.name"></el-input>
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px" :disabled="readOnly">
<el-form-item label="密钥名称" prop="secret_key_name" required :rules="[{ required: true, message: '请输入加密名称', trigger:'blur' },{ required: true, validator: validateRulename, trigger:'blur' }]">
<el-input v-model="form.secret_key_name"></el-input>
</el-form-item>
<el-form-item label="加密算法">
<el-input v-model="modelValue.name" disabled></el-input>
<el-input v-model="form.encryption_name" disabled></el-input>
</el-form-item>
<el-form-item label="密钥值" required>
<el-form-item label="密钥值" prop="sectet_key_value" required>
<div style="width: 100%;display: flex;align-items: center;">
<el-input v-model="modelValue.name" style="flex: 1;"></el-input>
<el-button type="primary" style="margin-left: 8px;" v-if="!readOnly">密钥生成</el-button>
<el-input v-model="form.sectet_key_value" disabled style="flex: 1;"></el-input>
<el-button type="primary" style="margin-left: 8px;" @click="getKeyGeneration" v-if="!readOnly">密钥生成</el-button>
</div>
</el-form-item>
<el-form-item label="测试">
<div style="width: 100%;display: flex;align-items: center;">
<el-input v-model="modelValue.name" style="flex: 1;"></el-input>
<el-button type="primary" style="margin-left: 8px;" v-if="!readOnly">测试</el-button>
<el-input v-model="testParam" style="flex: 1;"></el-input>
<el-button type="primary" style="margin-left: 8px;" @click="getKeyText" v-if="!readOnly">测试</el-button>
</div>
</el-form-item>
<el-form-item label="加密后的值">
<el-input v-model="modelValue.name" disabled></el-input>
<el-input v-model="encryptedValue" disabled></el-input>
</el-form-item>
</el-form>
<div class="btn">
......@@ -91,7 +193,7 @@ const confirm = () => {
<style lang="scss" scoped>
.el-form-item {
margin-bottom: 8px;
margin-bottom: 15px;
}
.btn {
padding: 20px;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论