ed37d41d by lihua

敏感数据识别

1 parent 8bf5ea81
...@@ -112,8 +112,8 @@ export const saveSensitiveDataTask = (params) => request({ ...@@ -112,8 +112,8 @@ export const saveSensitiveDataTask = (params) => request({
112 /** 编辑修改敏感数据识别任务 */ 112 /** 编辑修改敏感数据识别任务 */
113 export const updateSensitiveDataTask = (params) => request({ 113 export const updateSensitiveDataTask = (params) => request({
114 url: `${import.meta.env.VITE_APP_ANONYMIZATION_BASEURL}/sensitive-data-task/update`, 114 url: `${import.meta.env.VITE_APP_ANONYMIZATION_BASEURL}/sensitive-data-task/update`,
115 method: 'post', 115 method: 'put',
116 params 116 data: params
117 }) 117 })
118 118
119 /** 删除敏感数据识别任务 */ 119 /** 删除敏感数据识别任务 */
...@@ -123,5 +123,72 @@ export const deleteSensitiveDataTask = (data) => request({ ...@@ -123,5 +123,72 @@ export const deleteSensitiveDataTask = (data) => request({
123 data 123 data
124 }) 124 })
125 125
126 /** 手动执行敏感任务 */
127 export const execSensitiveDataTask = (guid) => request({
128 url: `${import.meta.env.VITE_APP_ANONYMIZATION_BASEURL}/sensitive-data-task/exec-task?taskGuid=${guid}`,
129 method: 'get'
130 })
131
126 /** 数据来源类型 */ 132 /** 数据来源类型 */
127 //export const
...\ No newline at end of file ...\ No newline at end of file
133 export const dataSourceTypeList = [{
134 value: 1,
135 label: '数据源'
136 }, {
137 value: 2,
138 label: '文件导入'
139 }];
140
141 /** 获取数据库选择列表 */
142 export const getDatabase = (params) => request({
143 url: `${import.meta.env.VITE_APP_DATA_SOURCE_URL}/data-source/get-source-list`,
144 method: 'post',
145 data: params
146 })
147
148 /** 获取敏感数据任务执行的数据表列表 */
149 export const getExecSensitiveTable = (execGuid) => request({
150 url: `${import.meta.env.VITE_APP_ANONYMIZATION_BASEURL}/sensitive-data-task/get-exec-sensitive-table?execGuid=${execGuid}`,
151 method: 'get'
152 })
153
154 /** 根据数据源或表获取敏感数据任务执行的字段列表 */
155 export const getExecSensitiveFieldTable = (params) => request({
156 url: `${import.meta.env.VITE_APP_ANONYMIZATION_BASEURL}/sensitive-data-task/get-exec-sensitive-field`,
157 method: 'post',
158 data: params
159 })
160
161 /** 获取当前数据表下的执行字段 */
162 export const getExecSensitiveFieldLabel = (params) => request({
163 url: `${import.meta.env.VITE_APP_ANONYMIZATION_BASEURL}/sensitive-data-task/get-exec-sensitive-label`,
164 method: 'post',
165 data: params
166 })
167
168 /** 获取敏感数据识别任务执行后的统计结果 */
169 export const getStatisticsNum = (params) => request({
170 url: `${import.meta.env.VITE_APP_ANONYMIZATION_BASEURL}/sensitive-data-task/statistics-num`,
171 method: 'get',
172 params
173 })
174
175 /** 修改敏感数据识别字段标签 */
176 export const updateSensitiveDataTaskFieldLabel = (params) => request({
177 url: `${import.meta.env.VITE_APP_ANONYMIZATION_BASEURL}/sensitive-data-task/batch-update-label`,
178 method: 'put',
179 data: params
180 })
181
182 /** 批量修改确认状态 */
183 export const batchUpdateSensitiveDataTaskFieldStatus = (params) => request({
184 url: `${import.meta.env.VITE_APP_ANONYMIZATION_BASEURL}/sensitive-data-task/batch-change-status`,
185 method: 'post',
186 data: params
187 })
188
189 /** 获取敏感数据识别任务执行日志 */
190 export const getSensitiveDataTaskExecLog = (params) => request({
191 url: `${import.meta.env.VITE_APP_ANONYMIZATION_BASEURL}/sensitive-data-task/get-exec-sensitive-exec-log`,
192 method: 'post',
193 data: params
194 })
...\ No newline at end of file ...\ No newline at end of file
......
1 <?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1755825941248" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1233" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M102.784 179.648A32 32 0 0 1 128.064 128H768a32 32 0 0 1 25.28 51.648L576 458.944v468.992a32 32 0 0 1-49.728 26.624l-192-128a32 32 0 0 1-14.24-26.592V458.944L102.784 179.648z m274.528 248.672A32 32 0 0 1 384 448v334.848l128 85.344V448a32 32 0 0 1 6.72-19.68L702.624 192H193.472l183.84 236.32zM735.968 512h128a32 32 0 1 1 0 64h-128a32 32 0 1 1 0-64z m0 128h128a32 32 0 1 1 0 64h-128a32 32 0 1 1 0-64z m0 128h128a32 32 0 1 1 0 64h-128a32 32 0 1 1 0-64z" fill="#4fa1a4" p-id="1234"></path></svg>
...\ No newline at end of file ...\ No newline at end of file
1 <svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" class="icon" viewBox="0 0 1024 1024"><path d="M102.784 179.648A32 32 0 0 1 128.064 128H768a32 32 0 0 1 25.28 51.648L576 458.944v468.992a32 32 0 0 1-49.728 26.624l-192-128a32 32 0 0 1-14.24-26.592V458.944L102.784 179.648z m274.528 248.672A32 32 0 0 1 384 448v334.848l128 85.344V448a32 32 0 0 1 6.72-19.68L702.624 192H193.472l183.84 236.32zM735.968 512h128a32 32 0 1 1 0 64h-128a32 32 0 1 1 0-64z m0 128h128a32 32 0 1 1 0 64h-128a32 32 0 1 1 0-64z m0 128h128a32 32 0 1 1 0 64h-128a32 32 0 1 1 0-64z" fill="#999999" p-id="1519"></path></svg>
...\ No newline at end of file ...\ No newline at end of file
1 <svg t="1755766425695" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1233" width="200" height="200"><path d="M102.784 179.648A32 32 0 0 1 128.064 128H768a32 32 0 0 1 25.28 51.648L576 458.944v468.992a32 32 0 0 1-49.728 26.624l-192-128a32 32 0 0 1-14.24-26.592V458.944L102.784 179.648z m274.528 248.672A32 32 0 0 1 384 448v334.848l128 85.344V448a32 32 0 0 1 6.72-19.68L702.624 192H193.472l183.84 236.32zM735.968 512h128a32 32 0 1 1 0 64h-128a32 32 0 1 1 0-64z m0 128h128a32 32 0 1 1 0 64h-128a32 32 0 1 1 0-64z m0 128h128a32 32 0 1 1 0 64h-128a32 32 0 1 1 0-64z" fill="#999999" p-id="1234"></path></svg>
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -43,18 +43,23 @@ const btn = computed(() => { ...@@ -43,18 +43,23 @@ const btn = computed(() => {
43 return props.popoverInfo.btn ?? {}; 43 return props.popoverInfo.btn ?? {};
44 }); 44 });
45 45
46 const dataProps = computed(() => {
47 return <any>(props.popoverInfo.props || {});
48 });
49
46 const initAttr = () => { 50 const initAttr = () => {
47 const data = props.popoverInfo.data ?? [] 51 const data = props.popoverInfo.data ?? []
48 const check = props.popoverInfo.checked ?? [] 52 const check = props.popoverInfo.checked ?? []
49 checkedVal.value = check 53 checkedVal.value = check
50 isIndeterminate.value = data.length > 0 && data.length == check.length 54 checkAll.value = data.length > 0 && data.length == check.length;
55 isIndeterminate.value = check.length > 0 && data.length > check.length
51 authorities.value = data 56 authorities.value = data
52 } 57 }
53 58
54 const filterPopover = (val) => { 59 const filterPopover = (val) => {
55 let data = props.popoverInfo.data ?? [] 60 let data = props.popoverInfo.data ?? []
56 if (val) { 61 if (val) {
57 authorities.value = data.filter(item => item.dataPermissionName.indexOf(val) > -1) 62 authorities.value = data.filter(item => item[dataProps.value.label || 'dataPermissionName'].indexOf(val) > -1)
58 } else { 63 } else {
59 authorities.value = data 64 authorities.value = data
60 } 65 }
...@@ -70,7 +75,8 @@ const handleCheckedCitiesChange = (val) => { ...@@ -70,7 +75,8 @@ const handleCheckedCitiesChange = (val) => {
70 isIndeterminate.value = checkedCount > 0 && checkedCount < authorities.value.length; 75 isIndeterminate.value = checkedCount > 0 && checkedCount < authorities.value.length;
71 }; 76 };
72 const showPopver = () => { 77 const showPopver = () => {
73 inputValue.value = '' 78 inputValue.value = '';
79 initAttr();
74 emits('showPopver', props.popoverInfo.scope, btn.value) 80 emits('showPopver', props.popoverInfo.scope, btn.value)
75 } 81 }
76 const btnClick = () => { 82 const btnClick = () => {
...@@ -98,10 +104,10 @@ watch(() => props.popoverInfo, async (val) => { ...@@ -98,10 +104,10 @@ watch(() => props.popoverInfo, async (val) => {
98 </template> 104 </template>
99 <template v-else-if="type == 'checkbox-list-btns'"> 105 <template v-else-if="type == 'checkbox-list-btns'">
100 <div class="content_body"> 106 <div class="content_body">
101 <el-input v-model.trim="inputValue" placeholder="请输入权限名称" :prefix-icon="Search" clearable 107 <el-input v-model.trim="inputValue" v-show="popoverInfo.data?.length > 5" :placeholder="props.popoverInfo.placeholder ?? '请输入权限名称'" :prefix-icon="Search" clearable
102 @change="filterPopover" /> 108 @input="filterPopover" />
103 <el-checkbox-group v-model="checkedVal" @change="handleCheckedCitiesChange"> 109 <el-checkbox-group v-model="checkedVal" @change="handleCheckedCitiesChange">
104 <el-checkbox v-for="auth in authorities" :key="auth.guid" :label="auth.guid">{{ auth.dataPermissionName 110 <el-checkbox v-for="auth in authorities" :key="auth.guid" :value="auth.guid">{{ auth[dataProps.label || 'dataPermissionName']
105 }}</el-checkbox> 111 }}</el-checkbox>
106 </el-checkbox-group> 112 </el-checkbox-group>
107 </div> 113 </div>
...@@ -118,6 +124,9 @@ watch(() => props.popoverInfo, async (val) => { ...@@ -118,6 +124,9 @@ watch(() => props.popoverInfo, async (val) => {
118 </div> 124 </div>
119 <template #reference> 125 <template #reference>
120 <span v-if="btn.value == 'authority'" @click="showPopver" v-preReClick>{{ btn.label }}</span> 126 <span v-if="btn.value == 'authority'" @click="showPopver" v-preReClick>{{ btn.label }}</span>
127 <el-icon class="filter-icon" v-else-if="btn.value == 'filter'" @click="showPopver">
128 <svg-icon :name="checkedVal.length ? 'filter-mobile-select' : 'filter-mobile'" />
129 </el-icon>
121 <el-icon v-else-if="btn.value == 'QuestionFilled'"> 130 <el-icon v-else-if="btn.value == 'QuestionFilled'">
122 <QuestionFilled /> 131 <QuestionFilled />
123 </el-icon> 132 </el-icon>
...@@ -138,8 +147,8 @@ watch(() => props.popoverInfo, async (val) => { ...@@ -138,8 +147,8 @@ watch(() => props.popoverInfo, async (val) => {
138 } 147 }
139 148
140 .el-checkbox-group { 149 .el-checkbox-group {
141 margin: 8px -8px 0; 150 margin: 0px -8px 0;
142 max-height: 276px; 151 max-height: 256px;
143 overflow: hidden auto; 152 overflow: hidden auto;
144 153
145 .el-checkbox { 154 .el-checkbox {
......
...@@ -328,7 +328,7 @@ onMounted(() => { ...@@ -328,7 +328,7 @@ onMounted(() => {
328 <span v-if="item.unit">{{ item.unit }}</span> 328 <span v-if="item.unit">{{ item.unit }}</span>
329 </template> 329 </template>
330 <template #default="scope" v-else-if="item.type == 'switch'"> 330 <template #default="scope" v-else-if="item.type == 'switch'">
331 <el-switch v-model="scope.row[item.field]" inline-prompt :key="scope.row.guid" 331 <el-switch v-model="scope.row[item.field]" inline-prompt :key="scope.row[rowKey || 'guid']"
332 :disabled="!item.isDisabled ? false : item.isDisabled(scope)" :active-value="item.activeValue" 332 :disabled="!item.isDisabled ? false : item.isDisabled(scope)" :active-value="item.activeValue"
333 :inactive-value="item.inactiveValue" :width="item.switchWidth" :active-text="item.activeText" 333 :inactive-value="item.inactiveValue" :width="item.switchWidth" :active-text="item.activeText"
334 :inactive-text="item.inactiveText" :before-change="() => beforeChange(scope, item)" 334 :inactive-text="item.inactiveText" :before-change="() => beforeChange(scope, item)"
......
...@@ -85,6 +85,42 @@ const routes: RouteRecordRaw[] = [ ...@@ -85,6 +85,42 @@ const routes: RouteRecordRaw[] = [
85 cache: true 85 cache: true
86 }, 86 },
87 }, 87 },
88 {
89 path: 'sensitive-identify-config',
90 name: 'sensitiveIdentifyConfig',
91 component: () => import('@/views/data_anonymization/sensitiveIdentifyConfig.vue'),
92 meta: {
93 title: '敏感数据识别查看',
94 sidebar: false,
95 breadcrumb: false,
96 cache: true,
97 reuse: true,
98 editPage: false,
99 activeMenu: '/data-anonymization/sensitive-identify'
100 },
101 beforeEnter: (to, from) => {
102 if (to.query.taskName) {
103 to.meta.title = `敏感数据识别查看-${to.query.taskName}`;
104 }
105 }
106 },
107 {
108 path: 'sensitive-identify-task-exec-log',
109 name: 'sensitiveIdentifyTaskExecLog',
110 component: () => import('@/views/data_anonymization/sensitiveIdentifyTaskExecLog.vue'),
111 meta: {
112 title: '执行日志',
113 sidebar: false,
114 breadcrumb: false,
115 cache: true,
116 reuse: true
117 },
118 beforeEnter: (to, from) => {
119 if (to.query.guid) {
120 to.meta.title = `日志-${to.query.name}`;
121 }
122 }
123 }
88 ], 124 ],
89 }, 125 },
90 { 126 {
......
...@@ -495,6 +495,16 @@ export const tagType = (row, type) => { ...@@ -495,6 +495,16 @@ export const tagType = (row, type) => {
495 } else { 495 } else {
496 state = 'info'; 496 state = 'info';
497 } 497 }
498 } else if (type == 'sensitiveIdentifyTaskStatus') {
499 if (row[type] == 'Y') {
500 state = 'success'
501 } else if (row[type] == 'N') {
502 state = 'info';
503 } else if (row[type] == 'E') {
504 state = 'danger';
505 } else if (row[type] == 'R') {
506 state = 'warning';
507 }
498 } else if (type == 'state' || type == 'documentState') { 508 } else if (type == 'state' || type == 'documentState') {
499 switch (row[type]) { 509 switch (row[type]) {
500 case 'N': 510 case 'N':
...@@ -805,6 +815,16 @@ export const tagMethod = (row, type) => { ...@@ -805,6 +815,16 @@ export const tagMethod = (row, type) => {
805 }else if (row[type] == 'R') { //部分通过 815 }else if (row[type] == 'R') { //部分通过
806 tag = '执行中'; 816 tag = '执行中';
807 } 817 }
818 } else if (type == 'sensitiveIdentifyTaskStatus') {
819 if (row[type] == 'Y') {
820 tag = '成功'
821 } else if (row[type] == 'N') {
822 tag = '未执行';
823 } else if (row[type] == 'E') { //部分通过
824 tag = '失败';
825 }else if (row[type] == 'R') { //部分通过
826 tag = '执行中';
827 }
808 } else if (type == 'execState') { 828 } else if (type == 'execState') {
809 if (row[type] == 0 || row[type] == null) { 829 if (row[type] == 0 || row[type] == null) {
810 tag = '未执行' 830 tag = '未执行'
......
...@@ -82,7 +82,7 @@ const tableInfo = ref({ ...@@ -82,7 +82,7 @@ const tableInfo = ref({
82 proxy.$openMessageBox("此操作将永久删除, 是否继续?", () => { 82 proxy.$openMessageBox("此操作将永久删除, 是否继续?", () => {
83 let guids = [scope.row.guid]; 83 let guids = [scope.row.guid];
84 deleteGeneralizeFile(guids).then((res: any) => { 84 deleteGeneralizeFile(guids).then((res: any) => {
85 if (res.code == proxy.$passCode) { 85 if (res?.code == proxy.$passCode) {
86 getTableData(); 86 getTableData();
87 proxy.$ElMessage({ 87 proxy.$ElMessage({
88 type: "success", 88 type: "success",
...@@ -122,7 +122,7 @@ const getTableData = () => { ...@@ -122,7 +122,7 @@ const getTableData = () => {
122 generalizeFileName: page.value.generalizeFileName, 122 generalizeFileName: page.value.generalizeFileName,
123 fieldType: page.value.fieldType 123 fieldType: page.value.fieldType
124 }).then((res: any) => { 124 }).then((res: any) => {
125 if (res.code == proxy.$passCode) { 125 if (res?.code == proxy.$passCode) {
126 const data = res.data || {} 126 const data = res.data || {}
127 tableInfo.value.data = data.records || [] 127 tableInfo.value.data = data.records || []
128 tableInfo.value.page.limit = data.pageSize 128 tableInfo.value.page.limit = data.pageSize
......
...@@ -268,7 +268,7 @@ const saveUpdate = async () => { ...@@ -268,7 +268,7 @@ const saveUpdate = async () => {
268 if (!guid.value) { 268 if (!guid.value) {
269 saveLoading.value = true; 269 saveLoading.value = true;
270 saveGeneralizeFile(params).then((res: any) => { 270 saveGeneralizeFile(params).then((res: any) => {
271 if (res.code == proxy.$passCode) { 271 if (res?.code == proxy.$passCode) {
272 proxy.$ElMessage.success('泛化文件新建成功'); 272 proxy.$ElMessage.success('泛化文件新建成功');
273 userStore.setTabbar(userStore.tabbar.filter((tab: any) => tab.fullPath !== fullPath)); 273 userStore.setTabbar(userStore.tabbar.filter((tab: any) => tab.fullPath !== fullPath));
274 anonymizationStore.setIsRefresh(true); 274 anonymizationStore.setIsRefresh(true);
...@@ -285,7 +285,7 @@ const saveUpdate = async () => { ...@@ -285,7 +285,7 @@ const saveUpdate = async () => {
285 params.guid = guid.value; 285 params.guid = guid.value;
286 saveLoading.value = true; 286 saveLoading.value = true;
287 updateGeneralizeFile(params).then((res: any) => { 287 updateGeneralizeFile(params).then((res: any) => {
288 if (res.code == proxy.$passCode) { 288 if (res?.code == proxy.$passCode) {
289 proxy.$ElMessage.success('泛化文件编辑成功'); 289 proxy.$ElMessage.success('泛化文件编辑成功');
290 userStore.setTabbar(userStore.tabbar.filter((tab: any) => tab.fullPath !== fullPath)); 290 userStore.setTabbar(userStore.tabbar.filter((tab: any) => tab.fullPath !== fullPath));
291 anonymizationStore.setIsRefresh(true); 291 anonymizationStore.setIsRefresh(true);
...@@ -310,7 +310,7 @@ onBeforeMount(() => { ...@@ -310,7 +310,7 @@ onBeforeMount(() => {
310 if (guid.value) { 310 if (guid.value) {
311 fullscreenLoading.value = true; 311 fullscreenLoading.value = true;
312 getGeneralizeFileDetail(guid.value).then(async (res: any) => { 312 getGeneralizeFileDetail(guid.value).then(async (res: any) => {
313 if (res.code == proxy.$passCode) { 313 if (res?.code == proxy.$passCode) {
314 let detail = res.data || {}; 314 let detail = res.data || {};
315 baseInfoItems.value.forEach(item => { 315 baseInfoItems.value.forEach(item => {
316 item.default = detail[item.field]; 316 item.default = detail[item.field];
......
...@@ -73,7 +73,7 @@ const tableInfo = ref({ ...@@ -73,7 +73,7 @@ const tableInfo = ref({
73 label: "编辑", value: "edit", click: (scope) => { 73 label: "编辑", value: "edit", click: (scope) => {
74 currTableData.value = scope.row; 74 currTableData.value = scope.row;
75 getLabelDetail(scope.row.guid).then((res: any) => { 75 getLabelDetail(scope.row.guid).then((res: any) => {
76 if (res.code == proxy.$passCode) { 76 if (res?.code == proxy.$passCode) {
77 const detail = res.data || {}; 77 const detail = res.data || {};
78 currTableData.value = Object.assign({}, currTableData.value, detail); 78 currTableData.value = Object.assign({}, currTableData.value, detail);
79 newCreateLabelFormItems.value.forEach(item => { 79 newCreateLabelFormItems.value.forEach(item => {
...@@ -120,7 +120,7 @@ const tableInfo = ref({ ...@@ -120,7 +120,7 @@ const tableInfo = ref({
120 proxy.$openMessageBox("此操作将永久删除, 是否继续?", () => { 120 proxy.$openMessageBox("此操作将永久删除, 是否继续?", () => {
121 let guids = [scope.row.guid]; 121 let guids = [scope.row.guid];
122 deleteLabel(guids).then((res: any) => { 122 deleteLabel(guids).then((res: any) => {
123 if (res.code == proxy.$passCode) { 123 if (res?.code == proxy.$passCode) {
124 getTableData(); 124 getTableData();
125 proxy.$ElMessage({ 125 proxy.$ElMessage({
126 type: "success", 126 type: "success",
...@@ -159,7 +159,7 @@ const getTableData = () => { ...@@ -159,7 +159,7 @@ const getTableData = () => {
159 pageSize: page.value.limit, 159 pageSize: page.value.limit,
160 labelName: page.value.labelName 160 labelName: page.value.labelName
161 }).then((res: any) => { 161 }).then((res: any) => {
162 if (res.code == proxy.$passCode) { 162 if (res?.code == proxy.$passCode) {
163 const data = res.data || {} 163 const data = res.data || {}
164 tableInfo.value.data = data.records || [] 164 tableInfo.value.data = data.records || []
165 tableInfo.value.page.limit = data.pageSize 165 tableInfo.value.page.limit = data.pageSize
...@@ -193,7 +193,7 @@ const tableSwitchChange = (val, scope, field) => { ...@@ -193,7 +193,7 @@ const tableSwitchChange = (val, scope, field) => {
193 bizState: val 193 bizState: val
194 } 194 }
195 updateLabelState(params).then((res: any) => { 195 updateLabelState(params).then((res: any) => {
196 if (res.code == proxy.$passCode && res.data) { 196 if (res?.code == proxy.$passCode && res.data) {
197 getTableData(); 197 getTableData();
198 proxy.$ElMessage({ 198 proxy.$ElMessage({
199 type: "success", 199 type: "success",
...@@ -331,7 +331,7 @@ const newCreateLabelDialogInfo = ref({ ...@@ -331,7 +331,7 @@ const newCreateLabelDialogInfo = ref({
331 newCreateLabelDialogInfo.value.submitBtnLoading = true; 331 newCreateLabelDialogInfo.value.submitBtnLoading = true;
332 if (newCreateLabelDialogInfo.value.type == 'add') { 332 if (newCreateLabelDialogInfo.value.type == 'add') {
333 saveLabel(params).then((res: any) => { 333 saveLabel(params).then((res: any) => {
334 if (res.code == proxy.$passCode) { 334 if (res?.code == proxy.$passCode) {
335 proxy.$ElMessage.success('标签新建成功'); 335 proxy.$ElMessage.success('标签新建成功');
336 newCreateLabelDialogInfo.value.visible = false; 336 newCreateLabelDialogInfo.value.visible = false;
337 newCreateLabelDialogInfo.value.submitBtnLoading = false; 337 newCreateLabelDialogInfo.value.submitBtnLoading = false;
...@@ -350,7 +350,7 @@ const newCreateLabelDialogInfo = ref({ ...@@ -350,7 +350,7 @@ const newCreateLabelDialogInfo = ref({
350 params.labelRuleContent.guid = currTableData.value.labelRuleContent?.guid; 350 params.labelRuleContent.guid = currTableData.value.labelRuleContent?.guid;
351 params.labelRuleField.guid = currTableData.value.labelRuleField?.guid; 351 params.labelRuleField.guid = currTableData.value.labelRuleField?.guid;
352 updateLabel(params).then((res: any) => { 352 updateLabel(params).then((res: any) => {
353 if (res.code == proxy.$passCode) { 353 if (res?.code == proxy.$passCode) {
354 proxy.$ElMessage.success('标签编辑成功'); 354 proxy.$ElMessage.success('标签编辑成功');
355 newCreateLabelDialogInfo.value.visible = false; 355 newCreateLabelDialogInfo.value.visible = false;
356 newCreateLabelDialogInfo.value.submitBtnLoading = false; 356 newCreateLabelDialogInfo.value.submitBtnLoading = false;
...@@ -654,7 +654,7 @@ onBeforeMount(() => { ...@@ -654,7 +654,7 @@ onBeforeMount(() => {
654 getParamsList({ 654 getParamsList({
655 dictType: "标签类型", 655 dictType: "标签类型",
656 }).then((res: any) => { 656 }).then((res: any) => {
657 if (res.code == proxy.$passCode) { 657 if (res?.code == proxy.$passCode) {
658 labelTypeList.value = res.data || []; 658 labelTypeList.value = res.data || [];
659 let item = newCreateLabelFormItems.value.find(item => item.field == 'labelgroup'); 659 let item = newCreateLabelFormItems.value.find(item => item.field == 'labelgroup');
660 item && (item.children[0].options = labelTypeList.value); 660 item && (item.children[0].options = labelTypeList.value);
...@@ -665,7 +665,7 @@ onBeforeMount(() => { ...@@ -665,7 +665,7 @@ onBeforeMount(() => {
665 getParamsList({ 665 getParamsList({
666 dictType: "内置规则", 666 dictType: "内置规则",
667 }).then((res: any) => { 667 }).then((res: any) => {
668 if (res.code == proxy.$passCode) { 668 if (res?.code == proxy.$passCode) {
669 builtInRuleList.value = res.data || []; 669 builtInRuleList.value = res.data || [];
670 ruleContentFormItems.value[1].options = builtInRuleList.value; 670 ruleContentFormItems.value[1].options = builtInRuleList.value;
671 } else { 671 } else {
......
...@@ -8,10 +8,18 @@ import { commonPageConfig } from '@/components/PageNav/index'; ...@@ -8,10 +8,18 @@ import { commonPageConfig } from '@/components/PageNav/index';
8 import { TableColumnWidth } from "@/utils/enum"; 8 import { TableColumnWidth } from "@/utils/enum";
9 import { 9 import {
10 getSensitiveDataTaskList, 10 getSensitiveDataTaskList,
11 dataSourceTypeList,
12 deleteSensitiveDataTask,
13 saveSensitiveDataTask,
14 updateSensitiveDataTask,
15 getDatabase,
16 execSensitiveDataTask,
11 } from '@/api/modules/dataAnonymization'; 17 } from '@/api/modules/dataAnonymization';
18 import { useValidator } from '@/hooks/useValidator';
12 19
13 const router = useRouter() 20 const router = useRouter()
14 const { proxy } = getCurrentInstance() as any; 21 const { proxy } = getCurrentInstance() as any;
22 const { required } = useValidator();
15 23
16 const searchItemList = ref([{ 24 const searchItemList = ref([{
17 type: "input", 25 type: "input",
...@@ -23,9 +31,9 @@ const searchItemList = ref([{ ...@@ -23,9 +31,9 @@ const searchItemList = ref([{
23 }, { 31 }, {
24 type: "select", 32 type: "select",
25 label: "", 33 label: "",
26 field: "fieldType", 34 field: "dataSource",
27 default: null, 35 default: null,
28 options: [], 36 options: dataSourceTypeList,
29 placeholder: "数据来源", 37 placeholder: "数据来源",
30 clearable: true, 38 clearable: true,
31 filterable: true, 39 filterable: true,
...@@ -34,25 +42,342 @@ const searchItemList = ref([{ ...@@ -34,25 +42,342 @@ const searchItemList = ref([{
34 /** 分页及搜索传参信息配置。 */ 42 /** 分页及搜索传参信息配置。 */
35 const page = ref({ 43 const page = ref({
36 ...commonPageConfig, 44 ...commonPageConfig,
37 generalizeFileName: '', 45 taskName: '',
38 fieldType: '' 46 dataSource: null
39 }); 47 });
40 48
49 const currTableData = ref();
50
51 const tableInfo = ref({
52 id: 'data-file-table',
53 fields: [
54 { label: "序号", type: "index", width: TableColumnWidth.INDEX, align: "center" },
55 { label: "任务名称", field: "taskName", width: 160 },
56 {
57 label: "数据来源", field: "dataSource", width: 120, getName: (scope) => {
58 return scope.row.dataSource && dataSourceTypeList.find(f => f.value == scope.row.dataSource)?.label || '--';
59 }
60 },
61 { label: "任务状态", field: "sensitiveIdentifyTaskStatus", width: TableColumnWidth.STATE, align: 'center', type: "tag" },
62 { label: "执行人", field: "execUserName", width: TableColumnWidth.USERNAME },
63 { label: "执行时间", field: "execTime", width: TableColumnWidth.DATETIME },
64 { label: "修改人", field: "updateUserName", width: TableColumnWidth.USERNAME },
65 { label: "修改时间", field: "updateTime", width: TableColumnWidth.DATETIME },
66 ],
67 data: [],
68 page: {
69 type: "normal",
70 rows: 0,
71 ...page.value,
72 },
73 loading: false,
74 actionInfo: {
75 label: "操作",
76 type: "btn",
77 width: 304,
78 fixed: 'right',
79 btns: (scope) => {
80 return [{
81 label: '敏感数据查看', value: 'view', disabled: scope.row.status != 'Y', click: (scope) => {
82 router.push({
83 name: 'sensitiveIdentifyConfig',
84 query: {
85 guid: scope.row.guid,
86 execGuid: scope.row.execGuid,
87 taskName: scope.row.taskName
88 }
89 });
90 }
91 }, {
92 label: '手动执行', value: 'execute', disabled: scope.row.status == 'R', click: (scope) => {
93 execSensitiveDataTask(scope.row.guid).then((res: any) => {
94 if (res?.code == proxy.$passCode) {
95 getTableData();
96 proxy.$ElMessage.success('该任务手动执行提交成功');
97 } else {
98 proxy.$ElMessage.error(res.msg);
99 }
100 })
101 }
102 }, {
103 label: "编辑", value: "edit", disabled: scope.row.status == 'R', click: (scope) => {
104 let row = scope.row;
105 currTableData.value = row;
106 newCreateTaskDialogInfo.value.visible = true;
107 newCreateTaskDialogInfo.value.title = '编辑数据敏感识别任务';
108 newCreateTaskDialogInfo.value.type = 'edit';
109 newCreateTaskFormItems.value[0].default = row.taskName;
110 newCreateTaskFormItems.value[1].default = row.dataSource;
111 newCreateTaskFormItems.value[2].default = row.dataSourceGuid || '';
112 newCreateTaskFormItems.value[2].visible = row.dataSource == 1;
113 newCreateTaskFormItems.value[3].default = row.filePath || [];
114 newCreateTaskFormItems.value[3].visible = row.dataSource == 2;
115 }
116 }, {
117 label: "删除", value: "delete", disabled: scope.row.status == 'R', click: (scope) => {
118 proxy.$openMessageBox("此操作将永久删除, 是否继续?", () => {
119 let guids = [scope.row.guid];
120 deleteSensitiveDataTask(guids).then((res: any) => {
121 if (res?.code == proxy.$passCode) {
122 getTableData();
123 proxy.$ElMessage({
124 type: "success",
125 message: "删除成功",
126 });
127 } else {
128 proxy.$ElMessage({
129 type: "error",
130 message: res.msg,
131 });
132 }
133 });
134 })
135 }
136 }, {
137 label: '日志', value: 'log', click: (scope) => {
138 router.push({
139 name: 'sensitiveIdentifyTaskExecLog',
140 query: {
141 guid: scope.row.guid,
142 name: scope.row.taskName,
143 }
144 });
145 }
146 }]
147 }
148 }
149 })
150
151 const toSearch = (val: any, clear: boolean = false) => {
152 if (clear) {
153 searchItemList.value.map((item) => (item.default = ""));
154 page.value.taskName = '';
155 page.value.dataSource = null;
156 } else {
157 page.value.taskName = val.taskName;
158 page.value.dataSource = val.dataSource;
159 }
160 getTableData();
161 };
162
163 const getTableData = () => {
164 tableInfo.value.loading = true
165 getSensitiveDataTaskList({
166 pageIndex: page.value.curr,
167 pageSize: page.value.limit,
168 taskName: page.value.taskName,
169 dataSource: page.value.dataSource
170 }).then((res: any) => {
171 if (res?.code == proxy.$passCode) {
172 const data = res.data || {};
173 tableInfo.value.data = data.records?.map(d => {
174 d.sensitiveIdentifyTaskStatus = d.status;
175 return d;
176 }) || []
177 tableInfo.value.page.limit = data.pageSize
178 tableInfo.value.page.curr = data.pageIndex
179 tableInfo.value.page.rows = data.totalRows
180 } else {
181 proxy.$ElMessage({
182 type: 'error',
183 message: res.msg,
184 })
185 }
186 tableInfo.value.loading = false
187 })
188 };
189
190 const tablePageChange = (info) => {
191 page.value.curr = Number(info.curr);
192 page.value.limit = Number(info.limit);
193 getTableData();
194 };
195
196 const dataSourceList = ref([]);
197
198 const newCreateTaskFormItems = ref([{
199 label: '任务名称',
200 type: 'input',
201 placeholder: '请选择',
202 field: 'taskName',
203 default: '',
204 required: true,
205 filterable: true,
206 clearable: true,
207 visible: true,
208 },
209 {
210 label: '数据来源',
211 type: 'select',
212 placeholder: '请选择',
213 field: 'dataSource',
214 default: 1,
215 options: dataSourceTypeList,
216 props: {
217 label: "label",
218 value: "value",
219 },
220 required: true,
221 filterable: true,
222 clearable: true,
223 visible: true,
224 }, {
225 label: '数据源',
226 type: 'select',
227 placeholder: '请选择',
228 field: 'dataSourceGuid',
229 default: '',
230 options: dataSourceList.value,
231 props: {
232 label: 'databaseNameZh',
233 value: 'guid'
234 },
235 filterable: true,
236 visible: true,
237 required: true
238 }, {
239 label: '文件上传',
240 tip: '支持扩展名:xlsx、xls、csv,文件大小不超过10MB',
241 type: 'upload-file',
242 accept: '.xlsx, .xls, .csv',
243 limitSize: 10,
244 isExcel: true,
245 required: true,
246 default: <any>[],
247 block: true,
248 visible: false,
249 field: 'file',
250 }]);
251
252 const newCreateTaskFormRules = ref({
253 taskName: [required('请输入任务名称')],
254 dataSource: [required('请选择数据来源')],
255 dataSourceGuid: [required('请选择数据源')],
256 file: [{
257 validator: (rule: any, value: any, callback: any) => {
258 if (!value?.length) {
259 callback(new Error('请上传文件'))
260 } else {
261 callback();
262 }
263 }, trigger: 'change'
264 }]
265 });
266
267 const newCreateTaskDialogInfo = ref({
268 visible: false,
269 size: 550,
270 title: "添加数据敏感识别任务",
271 type: "",
272 formInfo: {
273 id: "label-form",
274 items: newCreateTaskFormItems.value,
275 rules: newCreateTaskFormRules.value,
276 },
277 submitBtnLoading: false,
278 btns: {
279 cancel: () => {
280 newCreateTaskDialogInfo.value.visible = false;
281 newCreateTaskDialogInfo.value.submitBtnLoading = false;
282 },
283 submit: (btn, info) => {
284 let params = Object.assign({}, info, {
285 filePath: info.file?.map(f => {
286 return {
287 name: f.name,
288 url: f.url
289 }
290 }) || []
291 });
292 delete params.file;
293 newCreateTaskDialogInfo.value.submitBtnLoading = true;
294 if (newCreateTaskDialogInfo.value.type == 'add') {
295 saveSensitiveDataTask(params).then((res: any) => {
296 if (res?.code == proxy.$passCode) {
297 proxy.$ElMessage.success('标签新建成功');
298 newCreateTaskDialogInfo.value.visible = false;
299 newCreateTaskDialogInfo.value.submitBtnLoading = false;
300 page.value.curr = 1;
301 getTableData();
302 } else {
303 newCreateTaskDialogInfo.value.submitBtnLoading = false;
304 proxy.$ElMessage.error(res.msg);
305 }
306 });
307 } else {
308 newCreateTaskDialogInfo.value.submitBtnLoading = true;
309 params.guid = currTableData.value.guid;
310 updateSensitiveDataTask(params).then((res: any) => {
311 if (res?.code == proxy.$passCode) {
312 proxy.$ElMessage.success('标签编辑成功');
313 newCreateTaskDialogInfo.value.visible = false;
314 newCreateTaskDialogInfo.value.submitBtnLoading = false;
315 getTableData();
316 } else {
317 newCreateTaskDialogInfo.value.submitBtnLoading = false;
318 proxy.$ElMessage.error(res.msg);
319 }
320 });
321 }
322 }
323 }
324 });
325
326 const handleTaskSelectChange = (val, row, item) => {
327 if (item.field == 'dataSource') {
328 newCreateTaskFormItems.value[0].default = row.taskName;
329 newCreateTaskFormItems.value[1].default = val;
330 newCreateTaskFormItems.value[2].default = row.dataSourceGuid || '';
331 newCreateTaskFormItems.value[2].visible = val == 1;
332 newCreateTaskFormItems.value[3].default = row.file || [];
333 newCreateTaskFormItems.value[3].visible = val == 2;
334 }
335 }
336
337 const handleCreate = () => {
338 newCreateTaskDialogInfo.value.visible = true;
339 newCreateTaskDialogInfo.value.title = '添加数据敏感识别任务';
340 newCreateTaskDialogInfo.value.type = 'add';
341 newCreateTaskFormItems.value[0].default = '';
342 newCreateTaskFormItems.value[1].default = 1;
343 newCreateTaskFormItems.value[2].default = '';
344 newCreateTaskFormItems.value[2].visible = true;
345 newCreateTaskFormItems.value[3].default = [];
346 newCreateTaskFormItems.value[3].visible = false;
347 }
348
349 onBeforeMount(() => {
350 toSearch({});
351 getDatabase({ connectStatus: 1 }).then((res: any) => {
352 if (res?.code == proxy.$passCode) {
353 dataSourceList.value = res.data || [];
354 newCreateTaskFormItems.value[2].options = dataSourceList.value;
355 } else {
356 proxy.$ElMessage({
357 type: "error",
358 message: res.msg,
359 });
360 }
361 })
362 })
363
41 </script> 364 </script>
42 365
43 <template> 366 <template>
44 <div class="container_wrap"> 367 <div class="container_wrap">
45 <div class="table_tool_wrap"> 368 <div class="table_tool_wrap">
46 <!-- 头部搜索 --> 369 <!-- 头部搜索 -->
47 <!-- <TableTools :searchItems="searchItemList" :searchId="'data-label-search'" @search="toSearch" :init="false" /> 370 <TableTools :searchItems="searchItemList" :searchId="'data-label-search'" @search="toSearch" :init="false" />
48 <div class="tools_btns"> 371 <div class="tools_btns">
49 <el-button type="primary" @click="handleCreate">新建</el-button> 372 <el-button type="primary" @click="handleCreate">新建</el-button>
50 </div> --> 373 </div>
51 </div> 374 </div>
52 <div class="table_panel_wrap"> 375 <div class="table_panel_wrap">
53 <!-- 右侧标签管理表格 --> 376 <!-- 右侧标签管理表格 -->
54 <!-- <Table :tableInfo="tableInfo" @tablePageChange="tablePageChange" /> --> 377 <Table :tableInfo="tableInfo" @tablePageChange="tablePageChange" />
55 </div> 378 </div>
379 <Dialog_form ref="dialogTaskFormRef" :dialogConfigInfo="newCreateTaskDialogInfo"
380 @formDialogSelectChange="handleTaskSelectChange"></Dialog_form>
56 </div> 381 </div>
57 </template> 382 </template>
58 383
......
1 <route lang="yaml">
2 name: sensitiveIdentifyConfig
3 </route>
4
5 <script lang="ts" setup name="sensitiveIdentifyConfig">
6 import {
7 getExecSensitiveTable,
8 getExecSensitiveFieldTable,
9 getExecSensitiveFieldLabel,
10 getDataLabelList,
11 getStatisticsNum,
12 getParamsList,
13 updateSensitiveDataTaskFieldLabel,
14 batchUpdateSensitiveDataTaskFieldStatus,
15 } from '@/api/modules/dataAnonymization';
16 import PageNav from "@/components/PageNav/index.vue";
17 import { commonPageConfig } from '@/components/PageNav/index';
18 import { ElMessageBox } from 'element-plus';
19 import { changeNum } from "@/utils/common";
20 import BtnPopover from "@/components/Popover/index.vue";
21
22 const route = useRoute();
23 const { proxy } = getCurrentInstance() as any;
24 const isLook = ref(!!route.query.isLook);
25
26 const treeInfo = ref({
27 id: "data-list-tree",
28 filter: true,
29 queryValue: "",
30 queryPlaceholder: "请输入关键字搜索",
31 props: {
32 label: "label",
33 value: "value",
34 isLeaf: "isLeaf",
35 children: 'tableList'
36 },
37 nodeKey: 'value',
38 expandedKey: <any>[],
39 currentNodeKey: '',
40 data: [],
41 expandOnNodeClick: false,
42 loading: false,
43 currentObj: <any>{}
44 });
45
46 const treeRef = ref();
47
48 const nodeClick = (data, node) => {
49 let exec = () => {
50 pageInfo.value.labelGuids = [];
51 pageInfo.value.labelTypeCodes = [];
52 pageInfo.value.confirmStatus = '';
53 treeInfo.value.currentNodeKey = data.value;
54 treeInfo.value.currentObj = data;
55 if (data.parent) {
56 pageInfo.value.databaseName = data.parent;
57 pageInfo.value.tableName = data.tableName;
58 } else {
59 pageInfo.value.databaseName = data.databaseName;
60 pageInfo.value.tableName = '';
61 }
62 getSensitiveTableFieldData();
63 getCntSumInfo();
64 getSensitiveFieldLabelData();
65 }
66 if (checkTableSave()) {
67 ElMessageBox.confirm(
68 '存在未保存的数据,切换后会丢失,是否确定切换',
69 '提示',
70 {
71 confirmButtonText: '确定',
72 cancelButtonText: '取消',
73 type: 'warning',
74 }
75 ).then(() => {
76 exec();
77 }).catch(() => {
78 treeRef.value.setCurrentKey(treeInfo.value.currentObj.value);
79 })
80 } else {
81 exec();
82 }
83 }
84
85 const batchConfirm = () => {
86 if (!selectTableFieldRows.value.length) {
87 proxy.$ElMessage.error('请先勾选待确认的字段');
88 return;
89 }
90 batchUpdateSensitiveDataTaskFieldStatus(selectTableFieldRows.value.map(s => s.guid)).then((res: any) => {
91 if (res?.code == proxy.$passCode) {
92 proxy.$ElMessage.success('批量确认字段成功');
93 getSensitiveTableFieldData();
94 } else {
95 proxy.$ElMessage.error(res.msg);
96 }
97 })
98 }
99
100 /** 数量统计信息 */
101 const cntSumInfo: any = ref({});
102
103 const getCntSumInfo = () => {
104 getStatisticsNum({
105 execGuid: route.query.execGuid,
106 databaseName: pageInfo.value.databaseName,
107 tableName: pageInfo.value.tableName
108 }).then((res: any) => {
109 if (res?.code == proxy.$passCode) {
110 cntSumInfo.value = res.data || {};
111 } else {
112 proxy.$ElMessage.error(res.msg);
113 }
114 })
115 }
116
117 const getExecSensitiveTableData = () => {
118 treeInfo.value.loading = true;
119 getExecSensitiveTable(route.query.execGuid).then((res: any) => {
120 treeInfo.value.loading = false;
121 if (res?.code == proxy.$passCode) {
122 treeInfo.value.data = res.data?.map(d => {
123 d.value = d.databaseName;
124 d.label = d.databaseChName;
125 d.tableList = d.tableList?.map(t => {
126 t.value = t.tableName;
127 t.label = t.tableChName;
128 t.parent = d.databaseName;
129 return t;
130 }) || []
131 return d;
132 }) || [];
133 let treeData: any = treeInfo.value.data || [];
134 if (treeData.length) {
135 treeInfo.value.expandedKey = [treeData[0].value];
136 treeInfo.value.currentNodeKey = treeData[0]?.value;
137 treeInfo.value.currentObj = treeData[0];
138 treeData[0].tableList?.[0] && nodeClick(treeData[0], {});
139 }
140 } else {
141 proxy.$ElMessage.error(res.msg);
142 }
143 })
144 }
145
146 /** 所有的标签列表供编辑下拉显示 */
147 const allDataLabelList: any = ref([]);
148
149 onBeforeMount(() => {
150 getExecSensitiveTableData();
151 getDataLabelList({
152 pageSize: -1,
153 bizState: 'Y'
154 }).then((res: any) => {
155 if (res?.code == proxy.$passCode) {
156 allDataLabelList.value = res.data?.records || [];
157 } else {
158 proxy.$ElMessage.error(res.msg);
159 }
160 })
161 getParamsList({
162 dictType: "标签类型",
163 }).then((res: any) => {
164 if (res?.code == proxy.$passCode) {
165 labelTypeList.value = res.data?.map(d => {
166 d.guid = d.value;
167 return d;
168 }) || [];
169 } else {
170 proxy.$ElMessage.error(res.msg);
171 }
172 });
173 })
174
175 /** ------------------------- 敏感数据识别字段列表操作 --------------------------------- */
176
177 const labelList = ref([]);
178
179 /** 标签类型的字典列表 */
180 const labelTypeList: any = ref([]);
181
182 /** 分页设置 */
183 const pageInfo = ref({
184 ...commonPageConfig,
185 taskExecGuid: route.query.execGuid,
186 databaseName: '',
187 tableName: '',
188 rows: 0,
189 labelGuids: [], //列头筛选
190 labelTypeCodes: [],
191 confirmStatus: ''
192 });
193
194 /** 敏感数据 */
195 const sensitiveTableData: any = ref([]);
196
197 const sensitiveTableDataLoading = ref(false);
198
199 const getSensitiveTableFieldData = () => {
200 sensitiveTableDataLoading.value = true;
201 let confirmStatus: any = [];
202 getExecSensitiveFieldTable({
203 pageIndex: pageInfo.value.curr,
204 pageSize: pageInfo.value.limit,
205 taskExecGuid: pageInfo.value.taskExecGuid,
206 databaseName: pageInfo.value.databaseName,
207 tableName: pageInfo.value.tableName,
208 labelGuids: pageInfo.value.labelGuids,
209 labelTypeCodes: pageInfo.value.labelTypeCodes,
210 confirmStatus: confirmStatus?.length > 1 ? null : confirmStatus[0]
211 }).then((res: any) => {
212 sensitiveTableDataLoading.value = false;
213 if (res?.code == proxy.$passCode) {
214 const data = res.data || {};
215 sensitiveTableData.value = data.records || [];
216 pageInfo.value.limit = data.pageSize
217 pageInfo.value.curr = data.pageIndex
218 pageInfo.value.rows = data.totalRows
219 } else {
220 proxy.$ElMessage({
221 type: 'error',
222 message: res.msg,
223 })
224 }
225 })
226 }
227
228 /** 获取当前选中的左侧库表下对应的数据标签数组,做列头筛选时使用。 */
229 const getSensitiveFieldLabelData = () => {
230 getExecSensitiveFieldLabel({
231 pageSize: -1,
232 taskExecGuid: pageInfo.value.taskExecGuid,
233 databaseName: pageInfo.value.databaseName,
234 tableName: pageInfo.value.tableName
235 }).then((res: any) => {
236 if (res?.code == proxy.$passCode) {
237 labelList.value = res.data?.map(d => {
238 d.guid = d.labelGuid;
239 return d;
240 }) || [];
241 } else {
242 proxy.$ElMessage({
243 type: 'error',
244 message: res.msg,
245 })
246 }
247 })
248 }
249
250 const popoverLabelListInfo = computed(() => {
251 return {
252 type: 'checkbox-list-btns',
253 data: labelList.value,
254 placeholder: '请输入关键字搜索',
255 scope: {
256 row: {}
257 },
258 placement: 'right-start',
259 props: {
260 value: 'guid',
261 label: 'labelName'
262 },
263 checked: pageInfo.value.labelGuids,
264 btn: {
265 value: 'filter'
266 }
267 }
268 });
269
270 const handleLabelPopoverClick = (scope) => {
271 if (checkTableSave()) {
272 ElMessageBox.confirm(
273 '存在未保存的数据,切换后会丢失,是否确定切换',
274 '提示',
275 {
276 confirmButtonText: '确定',
277 cancelButtonText: '取消',
278 type: 'warning',
279 }
280 ).then(() => {
281 pageInfo.value.labelGuids = scope.row.selectedData || [];
282 pageInfo.value.curr = 1;
283 getSensitiveTableFieldData();
284 })
285 } else {
286 pageInfo.value.labelGuids = scope.row.selectedData || [];
287 pageInfo.value.curr = 1;
288 getSensitiveTableFieldData();
289 }
290 }
291
292 const popoverLabelTypeListInfo = computed(() => {
293 return {
294 type: 'checkbox-list-btns',
295 data: labelTypeList.value,
296 placeholder: '请输入关键字搜索',
297 scope: {
298 row: {}
299 },
300 placement: 'right-start',
301 props: {
302 value: 'guid',
303 label: 'label'
304 },
305 checked: pageInfo.value.labelTypeCodes,
306 btn: {
307 value: 'filter'
308 }
309 }
310 });
311
312 const handleLabelTypePopoverClick = (scope) => {
313 if (checkTableSave()) {
314 ElMessageBox.confirm(
315 '存在未保存的数据,切换后会丢失,是否确定切换',
316 '提示',
317 {
318 confirmButtonText: '确定',
319 cancelButtonText: '取消',
320 type: 'warning',
321 }
322 ).then(() => {
323 pageInfo.value.labelTypeCodes = scope.row.selectedData || [];
324 pageInfo.value.curr = 1;
325 getSensitiveTableFieldData();
326 })
327 } else {
328 pageInfo.value.labelTypeCodes = scope.row.selectedData || [];
329 pageInfo.value.curr = 1;
330 getSensitiveTableFieldData();
331 }
332 }
333
334 const popoverStatusListInfo = computed(() => {
335 return {
336 type: 'checkbox-list-btns',
337 data: [{
338 guid: 'N',
339 label: '待确认'
340 }, {
341 guid: 'Y',
342 label: '已确认'
343 }],
344 placeholder: '请输入关键字搜索',
345 scope: {
346 row: {}
347 },
348 placement: 'right-start',
349 props: {
350 value: 'guid',
351 label: 'label'
352 },
353 checked: pageInfo.value.confirmStatus,
354 btn: {
355 value: 'filter'
356 }
357 }
358 });
359
360 const handleStatusPopoverClick = (scope) => {
361 if (checkTableSave()) {
362 ElMessageBox.confirm(
363 '存在未保存的数据,切换后会丢失,是否确定切换',
364 '提示',
365 {
366 confirmButtonText: '确定',
367 cancelButtonText: '取消',
368 type: 'warning',
369 }
370 ).then(() => {
371 pageInfo.value.confirmStatus = scope.row.selectedData || [];
372 pageInfo.value.curr = 1;
373 getSensitiveTableFieldData();
374 })
375 } else {
376 pageInfo.value.confirmStatus = scope.row.selectedData || [];
377 pageInfo.value.curr = 1;
378 getSensitiveTableFieldData();
379 }
380 }
381
382 /** 标签选择的值改变,标签类型跟着变化。 */
383 const handleSelectChange = (val) => {
384 //暂时不处理,因为未保存会出现清空的场景,需要先存下之前的值。
385 }
386
387 const sensitiveTableSelectable = (row, index) => {
388 return row.confirmStatus == 'N';
389 }
390
391 const selectTableFieldRows: any = ref([]);
392
393 /** 勾选字段标准选中变化。 */
394 const selectionDataChange = (val) => {
395 selectTableFieldRows.value = val;
396 };
397
398 const handleFieldClickEdit = (scope) => {
399 scope.row.isEdit = true;
400 }
401
402 const handleFieldClickSave = (scope) => {
403 let labelName = '';
404 let labelTypeCode = '';
405 if (scope.row.labelGuid) {
406 let label = allDataLabelList.value.find(label => label.guid == scope.row.labelGuid);
407 if (label) {
408 labelName = label.labelName;
409 labelTypeCode = label.labelTypeCode;
410 }
411 }
412 sensitiveTableDataLoading.value = true;
413 updateSensitiveDataTaskFieldLabel([{
414 guid: scope.row.guid,
415 labelGuid: scope.row.labelGuid,
416 labelName: labelName,
417 labelTypeCode: labelTypeCode
418 }]).then((res: any) => {
419 sensitiveTableDataLoading.value = false;
420 if (res?.code == proxy.$passCode) {
421 getSensitiveTableFieldData();
422 getSensitiveFieldLabelData();
423 getCntSumInfo();
424 proxy.$ElMessage.success('标签修改成功');
425 } else {
426 proxy.$ElMessage.error(res.msg);
427 }
428 });
429 }
430
431 const checkTableSave = () => {
432 return sensitiveTableData.value.some(s => s.isEdit == true);
433 }
434
435 const pageChange = (info) => {
436 const toChange = checkTableSave()
437 const changeCont = () => {
438 pageInfo.value.curr = Number(info.curr)
439 pageInfo.value.limit = Number(info.limit)
440 getSensitiveTableFieldData();
441 }
442 if (toChange) {
443 ElMessageBox.confirm(
444 '存在未保存的数据,切换后会丢失,是否确定切换',
445 '提示',
446 {
447 confirmButtonText: '确定',
448 cancelButtonText: '取消',
449 type: 'warning',
450 }
451 ).then(() => {
452 changeCont();
453 })
454 } else {
455 changeCont();
456 }
457 }
458
459 </script>
460
461 <template>
462 <div class="container_wrap full flex">
463 <div class="aside_wrap">
464 <div class="aside_title">数据表列表</div>
465 <Tree ref="treeRef" :treeInfo="treeInfo" @nodeClick="nodeClick" />
466 </div>
467 <div class="main_wrap">
468 <div class="table_tool_wrap">
469 <div class="tools_btns">
470 <el-button v-if="!isLook" type="primary" @click="batchConfirm">批量确认</el-button>
471 <div class="cnt-desc">{{ '表总数:' + changeNum(cntSumInfo.tableNum || 0, 0) + '张 敏感表总数:' +
472 changeNum(cntSumInfo.sensitiveTableNum || 0, 0) + '张 字段总数:'
473 + changeNum(cntSumInfo.fieldNum || 0, 0) + '个 敏感字段总数:' + changeNum(cntSumInfo.sensitiveFieldNum || 0, 0) +
474 '个,其中直接标识:' +
475 changeNum(cntSumInfo.directIdentifierNum || 0, 0) + '个 准标识:' + changeNum(cntSumInfo.standardIdentifierNum ||
476 0, 0) + '个 敏感:' +
477 changeNum(cntSumInfo.sensitiveNum || 0, 0) + '个 非敏感:' + changeNum(cntSumInfo.nonSensitiveNum || 0, 0) + '个'
478 }}</div>
479 </div>
480 </div>
481 <div class="table_panel_wrap">
482 <!-- 右侧表字段标签匹配管理表格 -->
483 <el-table ref="sensitiveTableRef" :data="sensitiveTableData" v-loading="sensitiveTableDataLoading"
484 :highlight-current-row="true" stripe border height="100%" row-key="guid"
485 @selection-change="selectionDataChange" tooltip-effect="light" :style="{
486 width: '100%',
487 'max-height': 'calc(100% - 16px)',
488 display: 'inline-block',
489 }">
490 <el-table-column type="selection" v-if="!isLook" :selectable="sensitiveTableSelectable" :width="32" align="center" />
491 <el-table-column label="序号" type="index" width="56px" align="center" show-overflow-tooltip>
492 </el-table-column>
493 <el-table-column label="字段中文名" prop="fieldChName" width="140" align="left" show-overflow-tooltip>
494 <template #default="scope">
495 <span>{{ scope.row.fieldChName || '--' }}</span>
496 </template>
497 </el-table-column>
498 <el-table-column label="字段英文名" prop="fieldName" width="140" align="left" show-overflow-tooltip>
499 <template #default="scope">
500 <span>{{ scope.row.fieldName || '--' }}</span>
501 </template>
502 </el-table-column>
503 <el-table-column label="标签" prop="labelGuid" class-name="filter-cell" width="140" align="left"
504 show-overflow-tooltip>
505 <template #header>
506 <span>标签</span>
507 <BtnPopover v-if="labelList.length" :popoverInfo="popoverLabelListInfo"
508 @popverBtnClick="handleLabelPopoverClick" />
509 </template>
510 <template #default="scope">
511 <el-select-v2 v-if="scope.row['isEdit']" v-model="scope.row['labelGuid']" filterable
512 :options="allDataLabelList" placeholder="请选择" clearable :props="{ value: 'guid', label: 'labelName' }"
513 @change="handleSelectChange" />
514 <span v-else>{{ scope.row["labelName"] || '--' }}</span>
515 </template>
516 </el-table-column>
517 <el-table-column label="标签类型" prop="labelTypeName" class-name="filter-cell" width="120" align="left"
518 show-overflow-tooltip>
519 <template #header>
520 <span>标签类型</span>
521 <BtnPopover v-if="labelTypeList.length" :popoverInfo="popoverLabelTypeListInfo"
522 @popverBtnClick="handleLabelTypePopoverClick" />
523 </template>
524 <template #default="scope">
525 <span>{{ scope.row.labelTypeName || '--' }}</span>
526 </template>
527 </el-table-column>
528 <el-table-column label="所属表名" prop="tableChName" width="140" align="left" show-overflow-tooltip>
529 </el-table-column>
530 <el-table-column label="确认状态" prop="confirmStatus" class-name="filter-cell" width="120" align="center"
531 show-overflow-tooltip>
532 <template #header>
533 <span>确认状态</span>
534 <BtnPopover :popoverInfo="popoverStatusListInfo" @popverBtnClick="handleStatusPopoverClick" />
535 </template>
536 <template #default="scope">
537 <el-tag v-if="scope.row.confirmStatus != null"
538 :type="scope.row.confirmStatus == 'Y' ? 'success' : 'warning'">{{
539 scope.row.confirmStatus == 'Y' ? '已确认' : '未确认'
540 }}</el-tag>
541 <span v-else>{{ '--' }}</span>
542 </template>
543 </el-table-column>
544 <el-table-column v-if="!isLook" label="操作" width="100px" align="left" fixed="right" show-overflow-tooltip>
545 <template #default="scope">
546 <span class="text_btn" v-if="!scope.row['isEdit']" @click="handleFieldClickEdit(scope)"
547 v-preReClick>编辑</span>
548 <span class="text_btn" v-else @click="handleFieldClickSave(scope)" v-preReClick>保存</span>
549 </template>
550 </el-table-column>
551 </el-table>
552 <PageNav :pageInfo="pageInfo" @pageChange="pageChange" />
553 </div>
554 </div>
555 </div>
556 </template>
557
558 <style lang="scss" scoped>
559 .container_wrap {
560 .aside_wrap {
561 width: 200px;
562 }
563
564 .table_tool_wrap {
565 display: flex;
566 }
567
568 .table_panel_wrap {
569 height: calc(100% - 70px);
570 }
571 }
572
573 .tree_panel {
574 height: 100%;
575 padding-top: 0;
576
577 :deep(.el-tree) {
578 margin: 0;
579 height: calc(100% - 68px);
580 overflow: hidden auto;
581 }
582 }
583
584 :deep(.el-table) {
585 & td.el-table__cell {
586 .cell {
587 padding: 0px 10px;
588 }
589
590 padding: 2px 0px;
591 height: 36px;
592 }
593 }
594
595 .tools_btns {
596 display: flex;
597 align-items: center;
598
599 .el-button {
600 margin-right: 8px;
601 }
602 }
603
604 :deep(.filter-cell) {
605 .cell {
606 position: relative;
607
608 .el-icon.filter-icon {
609 position: absolute;
610 right: 6px;
611 top: 2px;
612 width: 18px;
613 height: 18px;
614
615 svg {
616 width: 18px;
617 height: 18px;
618 }
619 }
620 }
621 }
622 </style>
...\ No newline at end of file ...\ No newline at end of file
1 <route lang="yaml">
2 name: sensitiveIdentifyTaskExecLog
3 </route>
4
5 <script lang="ts" setup name="sensitiveIdentifyTaskExecLog">
6 import { ref } from "vue";
7 import { useRouter, useRoute } from "vue-router";
8 import Table from "@/components/Table/index.vue";
9 import { ElMessage } from "element-plus";
10 import { commonPageConfig } from '@/components/PageNav/index';
11 import {
12 getSensitiveDataTaskExecLog,
13 } from '@/api/modules/dataAnonymization';
14
15
16 const { proxy } = getCurrentInstance() as any;
17
18 const router = useRouter();
19 const route = useRoute();
20 const guid = route.query.guid;
21 const wordName = route.query.name
22
23 const page = ref({
24 ...commonPageConfig
25 });
26
27 const tableInfo = ref({
28 id: "word-log-table",
29 loading: false,
30 fields: [
31 { label: "报告名称", field: "analysisReportName", width: 230 },
32 {
33 label: "方案类型", field: "analysisReportType", width: 100, getName: (scope) => {
34 let planType = scope.row.analysisReportType;
35 return planType == 1 ? '表' : (planType == 2 ? '数据库' : (planType == 4 ? '数据同步' : '分组'));
36 }
37 },
38 { label: "报告对象", field: "qualityModelName", width: 180, },
39 { label: "质量评分", field: "qualityScore", width: 100, align: "right" },
40 { label: "最后执行时间", field: "execTime", width: 180, },
41 { label: "执行状态", field: "execResult", type: "tag", width: 120, align: "center" },
42 ],
43 data: [],
44 page: {
45 type: "normal",
46 rows: 0,
47 ...page.value,
48 },
49 actionInfo: {
50 label: "操作",
51 type: "btn",
52 width: 100,
53 fixed: 'right',
54 btns: (scope) => {
55 return [{ label: "查看报告", value: "reportView", disabled: scope.row['execResult'] != 'Y' }];
56 }
57 }
58 });
59
60 const getTableData = () => {
61 tableInfo.value.loading = true;
62 getSensitiveDataTaskExecLog({ pageIndex: page.value.curr, pageSize: page.value.limit, taskGuid: guid }).then((res: any) => {
63 tableInfo.value.loading = false;
64 if (res?.code == proxy.$passCode) {
65 const data = res.data || {}
66 tableInfo.value.data = data.records || []
67 tableInfo.value.page.limit = data.pageSize
68 tableInfo.value.page.curr = data.pageIndex
69 tableInfo.value.page.rows = data.totalRows
70 } else {
71 ElMessage.error(res.msg);
72 }
73 })
74 };
75
76 const tableBtnClick = (scope, btn) => {
77 const type = btn.value;
78 const row = scope.row;
79 if (type == 'reportView') {
80 router.push({
81 name: 'analysisReport',
82 query: {
83 planGuid: row.planGuid,
84 reportExecGuid: row.guid,
85 name: wordName
86 }
87 });
88 }
89 };
90
91 onBeforeMount(() => {
92 getTableData();
93 });
94
95 </script>
96
97 <template>
98 <div class="container_wrap">
99 <div class="table_panel_wrap">
100 <Table :tableInfo="tableInfo" @tableBtnClick="tableBtnClick" />
101 </div>
102 </div>
103 </template>
104
105 <style lang="scss" scoped>
106 .container_wrap {
107 padding: 0;
108
109 .table_panel_wrap {
110 height: 100%;
111 padding: 16px 16px 0;
112 }
113 }
114 </style>
...\ No newline at end of file ...\ No newline at end of file
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!