1416702f by lihua

迁移数据匿名化代码

1 parent bb72749e
...@@ -3,6 +3,51 @@ ...@@ -3,6 +3,51 @@
3 */ 3 */
4 import request from "@/utils/request"; 4 import request from "@/utils/request";
5 5
6 /** 获取标签列表。 */
7 export const getDataLabelList = (params) => request({
8 url: `${import.meta.env.VITE_APP_DIGITAL_CONTRACT_URL}/label/page-list`,
9 method: 'post',
10 data: params
11 })
12
13 /** 修改标签启用禁用状态 */
14 export const updateLabelState = (params) => request({
15 url: `${import.meta.env.VITE_APP_DIGITAL_CONTRACT_URL}/label/update-state`,
16 method: 'put',
17 params
18 })
19
20 export const saveLabel = (data) => request({
21 url: `${import.meta.env.VITE_APP_DIGITAL_CONTRACT_URL}/label/save`,
22 method: 'post',
23 data
24 })
25
26 export const deleteLabel = (data) => request({
27 url: `${import.meta.env.VITE_APP_DIGITAL_CONTRACT_URL}/label/delete`,
28 method: 'delete',
29 data
30 })
31
32 export const updateLabel = (data) => request({
33 url: `${import.meta.env.VITE_APP_DIGITAL_CONTRACT_URL}/label/update`,
34 method: 'put',
35 data
36 })
37
38 /** 获取标签详情 */
39 export const getLabelDetail = (guid) => request({
40 url: `${import.meta.env.VITE_APP_DIGITAL_CONTRACT_URL}/label/detail?guid=${guid}`,
41 method: 'get'
42 })
43
44 /** 获取数据字典配置 */
45 export const getParamsList = (params) => request({
46 url: `${import.meta.env.VITE_APP_CONFIG_URL}/dict/data/get-by-dictType`,
47 method: 'get',
48 params
49 })
50
6 /** 字段类型 */ 51 /** 字段类型 */
7 export const fieldTypeList = [{ 52 export const fieldTypeList = [{
8 value: '1', 53 value: '1',
...@@ -58,4 +103,241 @@ export const parseGeneralizeFileData = (data) => request({ ...@@ -58,4 +103,241 @@ export const parseGeneralizeFileData = (data) => request({
58 url: `${import.meta.env.VITE_APP_DIGITAL_CONTRACT_URL}/generalize-file/parse-file`, 103 url: `${import.meta.env.VITE_APP_DIGITAL_CONTRACT_URL}/generalize-file/parse-file`,
59 method: 'post', 104 method: 'post',
60 data 105 data
106 })
107
108
109 /** --------- 敏感数据识别接口 ------------------- */
110
111 /** 获取敏感数据识别任务列表 */
112 export const getSensitiveDataTaskList = (params) => request({
113 url: `${import.meta.env.VITE_APP_DIGITAL_CONTRACT_URL}/sensitive-data-task/page-list`,
114 method: 'post',
115 data: params
116 })
117
118 /** 新增敏感数据识别任务 */
119 export const saveSensitiveDataTask = (params) => request({
120 url: `${import.meta.env.VITE_APP_DIGITAL_CONTRACT_URL}/sensitive-data-task/save`,
121 method: 'post',
122 data: params
123 })
124
125 /** 编辑修改敏感数据识别任务 */
126 export const updateSensitiveDataTask = (params) => request({
127 url: `${import.meta.env.VITE_APP_DIGITAL_CONTRACT_URL}/sensitive-data-task/update`,
128 method: 'put',
129 data: params
130 })
131
132 /** 删除敏感数据识别任务 */
133 export const deleteSensitiveDataTask = (data) => request({
134 url: `${import.meta.env.VITE_APP_DIGITAL_CONTRACT_URL}/sensitive-data-task/delete`,
135 method: 'delete',
136 data
137 })
138
139 /** 手动执行敏感任务 */
140 export const execSensitiveDataTask = (guid) => request({
141 url: `${import.meta.env.VITE_APP_DIGITAL_CONTRACT_URL}/sensitive-data-task/exec-task?taskGuid=${guid}`,
142 method: 'get'
143 })
144
145 /** 数据来源类型 */
146 export const dataSourceTypeList = [{
147 value: 1,
148 label: '数据库'
149 }, {
150 value: 2,
151 label: '文件导入'
152 }];
153
154 /** 获取数据库选择列表 */
155 export const getDatabase = (params) => request({
156 url: `${import.meta.env.VITE_APP_DATA_SOURCE_URL}/data-source/get-source-list`,
157 method: 'post',
158 data: params
159 })
160
161 /** 获取敏感数据任务执行的数据表列表 */
162 export const getExecSensitiveTable = (execGuid) => request({
163 url: `${import.meta.env.VITE_APP_DIGITAL_CONTRACT_URL}/sensitive-data-task/get-exec-sensitive-table?execGuid=${execGuid}`,
164 method: 'get'
165 })
166
167 /** 根据数据源或表获取敏感数据任务执行的字段列表 */
168 export const getExecSensitiveFieldTable = (params) => request({
169 url: `${import.meta.env.VITE_APP_DIGITAL_CONTRACT_URL}/sensitive-data-task/get-exec-sensitive-field`,
170 method: 'post',
171 data: params
172 })
173
174 /** 获取当前数据表下的执行字段 */
175 export const getExecSensitiveFieldColumnListByCondition = (params) => request({
176 url: `${import.meta.env.VITE_APP_DIGITAL_CONTRACT_URL}/sensitive-data-task/column-list-by-condition`,
177 method: 'post',
178 data: params
179 })
180
181 /** 获取敏感数据识别任务执行后的统计结果 */
182 export const getStatisticsNum = (params) => request({
183 url: `${import.meta.env.VITE_APP_DIGITAL_CONTRACT_URL}/sensitive-data-task/statistics-num`,
184 method: 'get',
185 params
186 })
187
188 /** 修改敏感数据识别字段标签 */
189 export const updateSensitiveDataTaskFieldLabel = (params) => request({
190 url: `${import.meta.env.VITE_APP_DIGITAL_CONTRACT_URL}/sensitive-data-task/batch-update-label`,
191 method: 'put',
192 data: params
193 })
194
195 /** 批量修改确认状态 */
196 export const batchUpdateSensitiveDataTaskFieldStatus = (params) => request({
197 url: `${import.meta.env.VITE_APP_DIGITAL_CONTRACT_URL}/sensitive-data-task/batch-change-status`,
198 method: 'post',
199 data: params
200 })
201
202 /** 修改任务状态 */
203 export const confirmTaskStatus = (guid) => request({
204 url: `${import.meta.env.VITE_APP_DIGITAL_CONTRACT_URL}/sensitive-data-task/confirm-task?execGuid=${guid}`,
205 method: 'get'
206 })
207
208 /** 获取敏感数据识别任务执行日志 */
209 export const getSensitiveDataTaskExecLog = (params) => request({
210 url: `${import.meta.env.VITE_APP_DIGITAL_CONTRACT_URL}/sensitive-data-task/get-exec-sensitive-exec-log`,
211 method: 'post',
212 data: params
213 })
214
215 /** ---------- 匿名化处理 ------------------ */
216
217 /** 获取匿名化任务列表 */
218 export const getAnonTaskList = (params) => request({
219 url: `${import.meta.env.VITE_APP_DIGITAL_CONTRACT_URL}/anon-task/page-list`,
220 method: 'post',
221 data: params
222 })
223
224 /** 删除匿名化任务 */
225 export const deleteAnonTask = (data) => request({
226 url: `${import.meta.env.VITE_APP_DIGITAL_CONTRACT_URL}/anon-task/delete`,
227 method: 'delete',
228 data
229 })
230
231 /** 保存匿名化任务 */
232 export const saveAnonTask = (params) => request({
233 url: `${import.meta.env.VITE_APP_DIGITAL_CONTRACT_URL}/anon-task/save`,
234 method: 'post',
235 data: params
236 })
237
238 /** 更新匿名化任务 */
239 export const updateAnonTask = (params) => request({
240 url: `${import.meta.env.VITE_APP_DIGITAL_CONTRACT_URL}/anon-task/update`,
241 method: 'put',
242 data: params
243 })
244
245 /** 获取匿名化任务详情 */
246 export const getAnonTaskDetail = (guid) => request({
247 url: `${import.meta.env.VITE_APP_DIGITAL_CONTRACT_URL}/anon-task/detail?guid=${guid}`,
248 method: 'get'
249 })
250
251 /** 执行匿名化任务 */
252 export const execAnonTask = (taskGuid) => request({
253 url: `${import.meta.env.VITE_APP_DIGITAL_CONTRACT_URL}/anon-task/exec-task?taskGuid=${taskGuid}`,
254 method: 'post'
255 })
256
257 /** 匿名化任务检验接口 */
258 export const anonTaskCheck = (params) => request({
259 url: `${import.meta.env.VITE_APP_DIGITAL_CONTRACT_URL}/anon-task/check`,
260 method: 'post',
261 data: params
262 })
263
264 /** 获取匿名化任务分析结果数据 */
265 export const getAnonAnalyzeResult = (execGuid) => request({
266 url: `${import.meta.env.VITE_APP_DIGITAL_CONTRACT_URL}/anon-task/get-anon-analyze?taskExecGuid=${execGuid}`,
267 method: 'get'
268 })
269
270 /** 获取匿名化任务分析结果数据 */
271 export const getLastAnonAnalyzeResult = (execGuid) => request({
272 url: `${import.meta.env.VITE_APP_DIGITAL_CONTRACT_URL}/anon-task/get-anon-analyze?isResult=true&taskExecGuid=${execGuid}`,
273 method: 'get'
274 })
275
276 /** 获取匿名化任务分析结果统计分页数据 */
277 export const getAnonAnalyzePageData = (params) => request({
278 url: `${import.meta.env.VITE_APP_DIGITAL_CONTRACT_URL}/anon-task/page-anon-analyze-data`,
279 method: 'post',
280 data: params
281 })
282
283 /** 获取匿名化任务结果数据 */
284 export const getAnonPageData = (params) => request({
285 url: `${import.meta.env.VITE_APP_DIGITAL_CONTRACT_URL}/anon-task/page-anon-data`,
286 method: 'post',
287 data: params
288 })
289
290 /** 字段中文转英文 */
291 export const chTransformEn =(params)=> request({
292 url: `${import.meta.env.VITE_APP_COMMON_URL}/common/convert-field-ch-name`,
293 method: "post",
294 data: params,
295 });
296
297 /** 根据选择的连接池获取表列表 */
298 export const getDsTableByDs = (params) => request({
299 url: `${import.meta.env.VITE_APP_DATA_SOURCE_URL}/data-source/schema-table-page-list`,
300 method: 'post',
301 data: params
302 })
303
304 /** 根据数据表获取表字段结构 */
305 export const getDsTableFieldColumn = (params) => request({
306 url: `${import.meta.env.VITE_APP_DATA_SOURCE_URL}/data-source/table-column-list`,
307 method: 'post',
308 data: params
309 });
310
311 /** 根据数据表获取表数据 */
312 export const getDsTableSampleData = (params) => request({
313 url: `${import.meta.env.VITE_APP_DATA_SOURCE_URL}/data-source/table-data-preview-page`,
314 method: 'post',
315 data: params
316 });
317
318 /** 根据字段名称获取敏感数据识别标签 */
319 export const getLableByFieldName = (fieldName) => request({
320 url: `${import.meta.env.VITE_APP_DIGITAL_CONTRACT_URL}/sensitive-data-task/get-label-by-field-name?fieldName=${fieldName}`,
321 method: 'get'
322 });
323
324 /** 验证样本数据 */
325 export const validateAnonRule = (params) => request({
326 url: `${import.meta.env.VITE_APP_DIGITAL_CONTRACT_URL}/anon-task/check`,
327 method: 'post',
328 data: params
329 })
330
331 /** 导出匿名化结果数据 */
332 export const exportAnonExecData = (params) => request({
333 url: `${import.meta.env.VITE_APP_DIGITAL_CONTRACT_URL}/anon-task/export-anon-data?taskGuid=${params.taskGuid}&taskExecGuid=${params.execGuid}`,
334 method: 'get',
335 responseType: 'blob'
336 })
337
338 /** 下载匿名化评估报告 */
339 export const exportAnonReport = (params) => request({
340 url: `${import.meta.env.VITE_APP_DIGITAL_CONTRACT_URL}/anon-task/download-report?taskGuid=${params.taskGuid}&taskExecGuid=${params.execGuid}`,
341 method: 'post',
342 responseType: 'blob'
61 }) 343 })
...\ No newline at end of file ...\ No newline at end of file
......
1 import type { RouteRecordRaw } from 'vue-router'
2
3 function Layout() {
4 return import('@/layouts/index.vue')
5 }
6
7 const routes: RouteRecordRaw[] = [
8 {
9 path: '/data-anonymization/label-management',
10 component: Layout,
11 meta: {
12 title: '标签管理',
13 icon: 'sidebar-videos',
14 },
15 children: [
16 {
17 path: '',
18 name: 'labelManagement',
19 component: () => import('@/views/data_anonymization/labelManagement.vue'),
20 meta: {
21 title: '标签管理',
22 sidebar: false,
23 breadcrumb: false,
24 cache: true
25 },
26 }
27 ],
28 },
29 {
30 path: '/data-anonymization/generalize-file',
31 component: Layout,
32 meta: {
33 title: '泛化文件管理',
34 icon: 'sidebar-videos',
35 },
36 children: [
37 {
38 path: '',
39 name: 'generalizeFile',
40 component: () => import('@/views/data_anonymization/generalizeFile.vue'),
41 meta: {
42 title: '泛化文件管理',
43 sidebar: false,
44 breadcrumb: false,
45 cache: true
46 },
47 },
48 {
49 path: 'generalize-file-edit',
50 name: 'generalizeFileEdit',
51 component: () => import('@/views/data_anonymization/generalizeFileEdit.vue'),
52 meta: {
53 title: '新建泛化文件',
54 sidebar: false,
55 breadcrumb: false,
56 cache: true,
57 reuse: true,
58 editPage: true,
59 activeMenu: '/data-anonymization/generalize-file'
60 },
61 beforeEnter: (to, from) => {
62 if (to.query.fileName) {
63 to.meta.title = `编辑-${to.query.fileName}`;
64 }
65 }
66 },
67 ],
68 },
69 {
70 path: '/data-anonymization/sensitive-identify',
71 component: Layout,
72 meta: {
73 title: '敏感数据识别',
74 icon: 'sidebar-videos',
75 },
76 children: [
77 {
78 path: '',
79 name: 'sensitiveIdentify',
80 component: () => import('@/views/data_anonymization/sensitiveIdentify.vue'),
81 meta: {
82 title: '敏感数据识别',
83 sidebar: false,
84 breadcrumb: false,
85 cache: true
86 },
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.isLook == '1' ? '日志查看' : '查看'}-${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 }
124 ],
125 },
126 {
127 path: '/data-anonymization/result-process',
128 component: Layout,
129 meta: {
130 title: '匿名化处理',
131 icon: 'sidebar-videos',
132 },
133 children: [
134 {
135 path: '',
136 name: 'resultProcess',
137 component: () => import('@/views/data_anonymization/resultProcess.vue'),
138 meta: {
139 title: '匿名化处理',
140 sidebar: false,
141 breadcrumb: false,
142 cache: true
143 },
144 },
145 {
146 path: 'anon-task-create',
147 name: 'anonTaskCreate',
148 component: () => import('@/views/data_anonymization/anonTaskCreate.vue'),
149 meta: {
150 title: '匿名化处理任务',
151 sidebar: false,
152 breadcrumb: false,
153 cache: true,
154 reuse: true,
155 editPage: true,
156 activeMenu: '/data-anonymization/result-process'
157 },
158 beforeEnter: (to, from) => {
159 if (to.query.taskName) {
160 to.meta.title = `编辑-${to.query.taskName}`;
161 }
162 }
163 },
164 {
165 path: 'anonResultView',
166 name: 'anonResultView',
167 component: () => import('@/views/data_anonymization/anonResultView.vue'),
168 meta: {
169 title: '查看数据',
170 sidebar: false,
171 breadcrumb: false,
172 cache: true,
173 reuse: true
174 },
175 beforeEnter: (to, from) => {
176 if (to.query.guid) {
177 to.meta.title = `查看数据-${to.query.taskName}`;
178 }
179 }
180 },
181 {
182 path: 'anonResultReportView',
183 name: 'anonResultReportView',
184 component: () => import('@/views/data_anonymization/anonResultReportView.vue'),
185 meta: {
186 title: '查看报告',
187 sidebar: false,
188 breadcrumb: false,
189 cache: true,
190 reuse: true
191 },
192 beforeEnter: (to, from) => {
193 if (to.query.guid) {
194 to.meta.title = `查看报告-${to.query.taskName}`;
195 }
196 }
197 },
198 ],
199 },
200 ]
201
202 export default routes
...@@ -216,47 +216,7 @@ const routes: RouteRecordRaw[] = [ ...@@ -216,47 +216,7 @@ const routes: RouteRecordRaw[] = [
216 editPage: true 216 editPage: true
217 }, 217 },
218 }] 218 }]
219 }, 219 }
220 {
221 path: '/data-smart-contract-common/generalize-file',
222 component: Layout,
223 meta: {
224 title: '泛化文件管理',
225 icon: 'sidebar-videos',
226 },
227 children: [
228 {
229 path: '',
230 name: 'generalizeFile',
231 component: () => import('@/views/data_smart_contract/generalizeFile.vue'),
232 meta: {
233 title: '',
234 sidebar: false,
235 breadcrumb: false,
236 cache: true
237 },
238 },
239 {
240 path: 'generalize-file-edit',
241 name: 'generalizeFileEdit',
242 component: () => import('@/views/data_smart_contract/generalizeFileEdit.vue'),
243 meta: {
244 title: '新建泛化文件',
245 sidebar: false,
246 breadcrumb: false,
247 cache: true,
248 reuse: true,
249 editPage: true,
250 activeMenu: '/data-smart-contract-common/generalize-file'
251 },
252 beforeEnter: (to, from) => {
253 if (to.query.fileName) {
254 to.meta.title = `编辑-${to.query.fileName}`;
255 }
256 }
257 },
258 ],
259 },
260 ] 220 ]
261 221
262 export default routes 222 export default routes
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -7,6 +7,7 @@ import DataSmartContract from './modules/dataSmartContract'; ...@@ -7,6 +7,7 @@ import DataSmartContract from './modules/dataSmartContract';
7 import DataFacilitator from './modules/dataFacilitator'; 7 import DataFacilitator from './modules/dataFacilitator';
8 import HomeIndex from './modules/homeIndex'; 8 import HomeIndex from './modules/homeIndex';
9 import DataDelivery from './modules/dataDelivery'; 9 import DataDelivery from './modules/dataDelivery';
10 import DataAnonymization from './modules/dataAnonymization';
10 11
11 import useSettingsStore from '@/store/modules/settings' 12 import useSettingsStore from '@/store/modules/settings'
12 13
...@@ -99,6 +100,7 @@ const asyncRoutes: RouteRecordRaw[] = [ ...@@ -99,6 +100,7 @@ const asyncRoutes: RouteRecordRaw[] = [
99 ...DataFacilitator, 100 ...DataFacilitator,
100 ...HomeIndex, 101 ...HomeIndex,
101 ...DataDelivery, 102 ...DataDelivery,
103 ...DataAnonymization,
102 // ...DataAssetRegistry, 104 // ...DataAssetRegistry,
103 ] 105 ]
104 106
......
1 <route lang="yaml">
2 name: anonResultReportView
3 </route>
4
5 <script lang="ts" setup name="anonResultReportView">
6 import {
7 exportAnonReport,
8 getAnonAnalyzePageData,
9 getAnonAnalyzeResult,
10 getAnonTaskDetail,
11 } from '@/api/modules/dataAnonymization';
12 import { changeNum, download } from '@/utils/common';
13 import { ElMessage } from 'element-plus';
14 import anonResultAnalysis from './components/anonResultAnalysis.vue';
15 import { commonPageConfig } from '@/utils/enum';
16 import { calcColumnWidth } from '@/utils';
17
18 const route = useRoute();
19 const router = useRouter();
20 const fullPath = route.fullPath;
21 const taskGuid = ref(route.query.guid);
22 const { proxy } = getCurrentInstance() as any;
23 const resultDataLoading = ref(false);
24
25 const downPromise: any = ref()
26
27 /** 提交保存和编辑后的执行guid */
28 const taskExecGuid = ref(route.query.execGuid);
29
30 /** 记录原始的值信息,防止上一步之后未修改数据时不调用接口 */
31 const oldAnonTaskValueInfo: any = ref({});
32 /** 执行结果信息 */
33 const analysisResultInfo: any = ref({});
34
35 const containerRef = ref();
36
37 const containerWidth = ref(containerRef.value?.offsetWidth || 0)
38
39 /** ------------------------- 匿名化分析结果页面数据展示 ---------------- */
40 const pageInfo: any = ref({
41 ...commonPageConfig,
42 })
43
44 const pageChange = (info) => {
45 pageInfo.value.curr = Number(info.curr);
46 pageInfo.value.limit = Number(info.limit);
47 getAnalysisResultPageData();
48 }
49
50 /** 每列字段对应的列宽计算结果。 */
51 const originResultTableFieldColumn = ref({});
52
53 /** 结果分析中的字段表格数据 */
54 const resultData: any = ref([]);
55
56 /** 结果分析中的字段信息 */
57 const analysisResultTableFields: any = ref([]);
58
59 const analysisResultLoading = ref(false);
60
61 /** otherWidth表示使用标题宽度时添加标题排序图标等宽度 */
62 const calcTableColumnWidth = (data: any[], prop, title, otherWidth = 0) => {
63 let d: any[] = [];
64 data.forEach((dt) => d.push(dt[prop]));
65 //样式使用默认值。
66 return calcColumnWidth(
67 d,
68 title,
69 {
70 fontSize: 14,
71 fontFamily: "SimSun",
72 },
73 {
74 fontSize: 14,
75 fontFamily: "SimSun",
76 },
77 otherWidth
78 );
79 };
80
81 watch(
82 resultData,
83 (val: any[], oldVal) => {
84 if (!analysisResultTableFields.value?.length) {
85 originResultTableFieldColumn.value = {};
86 return;
87 }
88 originResultTableFieldColumn.value = {};
89 analysisResultTableFields.value.forEach((field, index) => {
90 originResultTableFieldColumn.value[field.enName] = calcTableColumnWidth(
91 val?.slice(0, 20) || [],
92 field.enName,
93 field.chName,
94 24
95 );
96 });
97 },
98 {
99 deep: true,
100 }
101 );
102
103 const getAnalysisResultPageData = () => {
104 analysisResultLoading.value = true;
105 getAnonAnalyzePageData({
106 pageIndex: pageInfo.value.curr,
107 pageSize: pageInfo.value.limit,
108 taskExecGuid: taskExecGuid.value,
109 }).then((res: any) => {
110 analysisResultLoading.value = false;
111 if (res?.code == proxy.$passCode) {
112 pageInfo.value.rows =
113 resultData.value = [];
114 res.data?.records?.forEach(d => {
115 let obj = {};
116 analysisResultTableFields.value.forEach(t => {
117 obj[t.enName] = d.fieldValue?.[t.enName];
118 });
119 obj['equivalenceClassNum'] = changeNum(d.equivalenceClassNum || 0, 0);
120 obj['reIdentifyRisk'] = changeNum(d.reIdentifyRisk || 0, 2);
121 obj['isGtThreshold'] = d.isGtThreshold;
122 resultData.value.push(obj);
123 });
124 pageInfo.value.rows = res.data?.totalRows ?? 0;
125 } else {
126 proxy.$ElMessage.error(res.msg);
127 }
128 })
129 }
130
131 /** 下载评估报告 */
132 const transfer = () => {
133 if (downPromise.value) {
134 return;
135 }
136 downPromise.value = exportAnonReport({
137 taskGuid: route.query.guid,
138 execGuid: taskExecGuid.value
139 }).then((res: any) => {
140 downPromise.value = null;
141 if (res && !res.msg) {
142 download(res, (route.query.taskName || oldAnonTaskValueInfo.value.taskName) + '_匿名化评估报告.docx', 'word')
143 } else {
144 res?.msg && ElMessage.error(res?.msg);
145 }
146 }).catch(() => {
147 downPromise.value = null;
148 })
149 }
150
151 onMounted(() => {
152 nextTick(() => {
153 containerWidth.value = containerRef.value?.offsetWidth || 0;
154 })
155 window.onresize = () => {
156 containerWidth.value = containerRef.value?.offsetWidth || 0;
157 }
158 })
159
160 onBeforeMount(() => {
161 resultDataLoading.value = true;
162 getAnonAnalyzeResult(taskExecGuid.value).then((res: any) => {
163 resultDataLoading.value = false;
164 if (res?.code == proxy.$passCode) {
165 analysisResultInfo.value = res.data || {};
166 analysisResultTableFields.value = res.data?.column || [];
167 pageInfo.value.curr = 1;
168 getAnalysisResultPageData();
169 } else {
170 res?.msg && proxy.$ElMessage.error(res.msg);
171 }
172 });
173 getAnonTaskDetail(taskGuid.value).then((res: any) => {
174 if (res?.code == proxy.$passCode) {
175 oldAnonTaskValueInfo.value = res.data || {};
176 } else {
177 res?.msg && proxy.$ElMessage.error(res.msg);
178 }
179 });
180 })
181
182 </script>
183
184 <template>
185 <div class="table_tool_wrap" v-loading="resultDataLoading" ref="containerRef">
186 <el-button style="margin-bottom: 8px;" type="primary" @click="transfer" v-preReClick>下载评估报告</el-button>
187 <anonResultAnalysis :show-title="true" :analysis-result-info="analysisResultInfo"
188 :analysis-result-loading="analysisResultLoading" :analysis-result-table-fields="analysisResultTableFields"
189 :old-anon-task-value-info="oldAnonTaskValueInfo" :container-width="containerWidth"
190 :origin-result-table-field-column="originResultTableFieldColumn" :page-info="pageInfo" :result-data="resultData"
191 @page-change="pageChange"></anonResultAnalysis>
192 </div>
193 </template>
194
195 <style lang="scss" scoped>
196 .table_tool_wrap {
197 width: 100%;
198 height: 100%;
199 padding: 8px 16px 16px;
200 overflow-y: auto;
201 }
202 </style>
1 <route lang="yaml">
2 name: anonResultView
3 </route>
4
5 <script lang="ts" setup name="anonResultView">
6 import { ref } from "vue";
7 import {
8 getAnonPageData,
9 getLastAnonAnalyzeResult,
10 exportAnonExecData,
11 } from "@/api/modules/dataAnonymization";
12 import { calcColumnWidth } from "@/utils/index";
13 import Moment from 'moment';
14 import { TableColumnWidth } from "@/utils/enum";
15 import { ElMessage } from "element-plus";
16 import { commonPageConfig } from '@/components/PageNav/index';
17 import { download } from "@/utils/common";
18
19 const { proxy } = getCurrentInstance() as any;
20
21 const route = useRoute();
22
23 const props = defineProps({
24 isPage: {
25 default: true,
26 type: Boolean
27 },
28 execGuid: {
29 default: '',
30 type: String
31 }
32 });
33
34 const tableData: any = ref([]);
35 const tableDataLoading = ref(false);
36
37 const tableFields: any = ref([]);
38
39 const pageInfo: any = ref({
40 ...commonPageConfig,
41 rows: 0,
42 })
43
44 const getData = () => {
45 tableData.value = [];
46 if (!tableFields.value?.length) {
47 return;
48 }
49 tableDataLoading.value = true;
50 getAnonPageData({
51 pageIndex: pageInfo.value.curr,
52 pageSize: pageInfo.value.limit,
53 taskExecGuid: props.isPage ? route.query.execGuid : props.execGuid,
54 }).then((res: any) => {
55 tableDataLoading.value = false;
56 if (res.code == proxy.$passCode) {
57 tableData.value = [];
58 res.data?.records?.forEach(d => {
59 let obj = {};
60 tableFields.value.forEach(t => {
61 obj[t.enName] = d.fieldValue?.[t.enName];
62 });
63 tableData.value.push(obj);
64 });
65 pageInfo.value.rows = res.data?.totalRows ?? 0;
66 } else {
67 ElMessage.error(res.msg);
68 }
69 });
70 }
71
72 const getTextAlign = (field) => {
73 if (field.dataType === 'decimal' || field.dataType === 'int' || field.dataType == 'bit' || field.dataType == 'tinyint') {
74 return 'right';
75 }
76 return 'left'
77 }
78
79 /** otherWidth表示使用标题宽度时添加标题排序图标等宽度 */
80 const calcTableColumnWidth = (data: any[], prop, title, otherWidth = 0) => {
81 let d: any[] = [];
82 data.forEach((dt) => d.push(dt[prop]));
83 return calcColumnWidth(
84 d,
85 title,
86 {
87 fontSize: 14,
88 fontFamily: "SimSun",
89 },
90 {
91 fontSize: 14,
92 fontFamily: "SimSun",
93 },
94 otherWidth
95 );
96 };
97
98 /** 每列字段对应的列宽计算结果。 */
99 const originTableFieldColumn = ref({});
100
101 watch(
102 tableData,
103 (val: any[], oldVal) => {
104 if (!tableFields.value?.length) {
105 originTableFieldColumn.value = {};
106 return;
107 }
108 originTableFieldColumn.value = {};
109 tableFields.value.forEach((field, index) => {
110 originTableFieldColumn.value[field.enName] = calcTableColumnWidth(
111 val?.slice(0, 20) || [],
112 field.enName,
113 field.chName,
114 24
115 );
116 });
117 },
118 {
119 deep: true,
120 }
121 );
122
123 watch(() => props.execGuid, (val) => {
124 if (!val) {
125 return;
126 }
127 tableDataLoading.value = true;
128 getLastAnonAnalyzeResult(val).then((res: any) => {
129 tableDataLoading.value = false;
130 if (res.code == proxy.$passCode) {
131 let column = res.data?.column || {};
132 tableFields.value = column;
133 pageInfo.value.curr = 1;
134 getData();
135 } else {
136 ElMessage.error(res.msg);
137 }
138 });
139 }, {
140 immediate: true
141 })
142
143 onBeforeMount(() => {
144 if (!props.isPage) {
145 return;
146 }
147 tableDataLoading.value = true;
148 getLastAnonAnalyzeResult(route.query.execGuid).then((res: any) => {
149 tableDataLoading.value = false;
150 if (res.code == proxy.$passCode) {
151 let column = res.data?.column || {};
152 tableFields.value = column;
153 getData();
154 } else {
155 ElMessage.error(res.msg);
156 }
157 });
158 });
159
160 const formatterPreviewDate = (row, info) => {
161 let enName = info.enName;
162 let v = row[enName];
163 if (v === 0) {
164 return v;
165 }
166 if (!v || v == 'null') {
167 return '--';
168 }
169 if (info.dataType === 'datetime') {
170 return Moment(v).format('YYYY-MM-DD HH:mm:ss');
171 }
172 if (info.dataType === 'date') {
173 if (isNaN(<any>(new Date(v)))) {
174 return Moment(parseInt(v)).format('YYYY-MM-DD');
175 } else {
176 return Moment(v).format('YYYY-MM-DD');
177 }
178 }
179 return v;
180 };
181
182 const pageChange = (info) => {
183 pageInfo.value.curr = Number(info.curr);
184 pageInfo.value.limit = Number(info.limit);
185 getData();
186 }
187
188 const promise: any = ref(null);
189
190 const exportData = () => {
191 if (promise.value) {
192 return;
193 }
194 promise.value = exportAnonExecData({
195 taskGuid: route.query.guid,
196 execGuid: route.query.execGuid
197 }).then((res: any) => {
198 promise.value = null;
199 if (res && !res.msg) {
200 download(res, route.query.taskName + '_匿名化数据.xlsx', 'excel')
201 } else {
202 res?.msg && ElMessage.error(res?.msg);
203 }
204 }).catch(() => {
205 promise.value = null;
206 })
207 }
208
209 </script>
210
211 <template>
212 <div class="table_tool_wrap" v-loading="tableDataLoading">
213 <el-button v-show="props.isPage" style="margin-bottom: 8px;" type="primary" @click="exportData"
214 v-preReClick>导出数据</el-button>
215 <el-table ref="tableRef" v-show="tableFields.length" :data="tableData" :highlight-current-row="true" stripe border
216 tooltip-effect="light" height="100%" row-key="guid" :style="{ width: '100%', height: !props.isPage ? 'calc(100% - 34px)' : 'calc(100% - 64px)' }">
217 <template v-for="(item, index) in (tableFields || [])">
218 <el-table-column :label="item.chName" :width="item.dataType === 'datetime'
219 ? TableColumnWidth.DATETIME
220 : item.dataType === 'date'
221 ? TableColumnWidth.DATE
222 : originTableFieldColumn[item.enName]
223 " :align="getTextAlign(item)" :header-align="getTextAlign(item)"
224 :formatter="(row) => formatterPreviewDate(row, item)" :show-overflow-tooltip="true">
225 </el-table-column>
226 </template>
227 </el-table>
228 <div v-show="!tableFields.length" class="empty-content">
229 <img src="../../assets/images/empty-data.png" :style="{ width: '168px', height: '96px' }" />
230 <div class="empty-text">暂无数据</div>
231 </div>
232 <PageNav :class="[pageInfo.type]" :pageInfo="pageInfo" @pageChange="pageChange" />
233 </div>
234 </template>
235
236 <style lang="scss" scoped>
237 .table_tool_wrap {
238 width: 100%;
239 height: 100%;
240 padding: 8px 16px 16px;
241
242 .tips_text {
243 font-size: 14px;
244 color: var(--el-text-color-tip);
245 display: block;
246 font-weight: normal;
247 margin-bottom: 8px;
248 line-height: 21px;
249 }
250
251 .el-table {
252 display: inline-block;
253 }
254
255 .empty-content {
256 display: flex;
257 align-items: center;
258 justify-content: center;
259 height: 100%;
260 width: 100%;
261 flex-direction: column;
262
263 .empty-text {
264 font-size: 14px;
265 color: #b2b2b2;
266 }
267 }
268 }
269 </style>
...\ No newline at end of file ...\ No newline at end of file
1 <route lang="yaml">
2 name: resultProcess
3 </route>
4
5 <script lang="ts" setup name="resultProcess">
6 import TableTools from "@/components/Tools/table_tools.vue";
7 import { commonPageConfig } from '@/components/PageNav/index';
8 import { TableColumnWidth } from "@/utils/enum";
9 import {
10 dataSourceTypeList,
11 getAnonTaskList,
12 deleteAnonTask,
13 } from '@/api/modules/dataAnonymization';
14 import { useValidator } from '@/hooks/useValidator';
15 import useDataAnonymizationStore from "@/store/modules/dataAnonymization";
16
17 const anonymizationStore = useDataAnonymizationStore();
18 const router = useRouter()
19 const { proxy } = getCurrentInstance() as any;
20 const { required } = useValidator();
21
22 const searchItemList = ref([{
23 type: "input",
24 label: "",
25 field: "taskName",
26 default: "",
27 placeholder: "数据集名称",
28 clearable: true,
29 }, {
30 type: "select",
31 label: "",
32 field: "dataSource",
33 default: null,
34 options: dataSourceTypeList,
35 placeholder: "数据来源",
36 clearable: true,
37 filterable: true,
38 }])
39
40 /** 分页及搜索传参信息配置。 */
41 const page = ref({
42 ...commonPageConfig,
43 taskName: '',
44 dataSource: null
45 });
46
47 const tableInfo = ref({
48 id: 'data-file-table',
49 fields: [
50 { label: "序号", type: "index", width: TableColumnWidth.INDEX, align: "center" },
51 { label: "数据集名称", field: "taskName", width: 160 },
52 {
53 label: "数据来源", field: "dataSource", width: 100, getName: (scope) => {
54 return scope.row.dataSource && dataSourceTypeList.find(f => f.value == scope.row.dataSource)?.label || '--';
55 }
56 },
57 { label: "任务状态", field: "sensitiveIdentifyTaskStatus", width: TableColumnWidth.STATE, align: 'center', type: "tag" },
58 { label: "导出时间", field: "exportTime", width: TableColumnWidth.DATETIME },
59 { label: "修改人", field: "updateUserName", width: TableColumnWidth.USERNAME },
60 { label: "修改时间", field: "updateTime", width: TableColumnWidth.DATETIME },
61 ],
62 data: [],
63 page: {
64 type: "normal",
65 rows: 0,
66 ...page.value,
67 },
68 loading: false,
69 actionInfo: {
70 label: "操作",
71 type: "btn",
72 width: 230,
73 fixed: 'right',
74 btns: (scope) => {
75 return [{
76 label: "编辑", value: "edit", click: (scope) => {
77 router.push({
78 name: 'anonTaskCreate',
79 query: {
80 guid: scope.row.guid,
81 taskName: scope.row.taskName
82 }
83 });
84 }
85 }, {
86 label: '查看报告', value: 'report', disabled: scope.row.status != 'Y', click: (scope) => {
87 router.push({
88 name: 'anonResultReportView',
89 query: {
90 guid: scope.row.guid,
91 execGuid: scope.row.lastExecGuid,
92 taskName: scope.row.taskName
93 }
94 });
95 }
96 }, {
97 label: '查看数据', value: 'view', disabled: scope.row.status != 'Y' || scope.row.handleType == '02', click: (scope) => {
98 router.push({
99 name: 'anonResultView',
100 query: {
101 guid: scope.row.guid,
102 execGuid: scope.row.lastExecGuid,
103 taskName: scope.row.taskName
104 }
105 });
106 }
107 }, {
108 label: "删除", value: "delete", click: (scope) => {
109 proxy.$openMessageBox("此操作将永久删除, 是否继续?", () => {
110 let guids = [scope.row.guid];
111 deleteAnonTask(guids).then((res: any) => {
112 if (res?.code == proxy.$passCode) {
113 page.value.curr = 1;
114 getTableData();
115 proxy.$ElMessage({
116 type: "success",
117 message: "删除成功",
118 });
119 } else {
120 proxy.$ElMessage({
121 type: "error",
122 message: res.msg,
123 });
124 }
125 });
126 })
127 }
128 }]
129 }
130 }
131 })
132
133 const toSearch = (val: any, clear: boolean = false) => {
134 if (clear) {
135 searchItemList.value.map((item) => (item.default = ""));
136 page.value.taskName = '';
137 page.value.dataSource = null;
138 } else {
139 page.value.taskName = val.taskName;
140 page.value.dataSource = val.dataSource;
141 }
142 getTableData();
143 };
144
145 const getTableData = () => {
146 tableInfo.value.loading = true
147 getAnonTaskList({
148 pageIndex: page.value.curr,
149 pageSize: page.value.limit,
150 taskName: page.value.taskName,
151 dataSource: page.value.dataSource
152 }).then((res: any) => {
153 if (res?.code == proxy.$passCode) {
154 const data = res.data || {};
155 tableInfo.value.data = data.records?.map(d => {
156 d.sensitiveIdentifyTaskStatus = d.status;
157 return d;
158 }) || []
159 tableInfo.value.page.limit = data.pageSize
160 tableInfo.value.page.curr = data.pageIndex
161 tableInfo.value.page.rows = data.totalRows
162 } else {
163 proxy.$ElMessage({
164 type: 'error',
165 message: res.msg,
166 })
167 }
168 tableInfo.value.loading = false
169 })
170 };
171
172 const tablePageChange = (info) => {
173 page.value.curr = Number(info.curr);
174 page.value.limit = Number(info.limit);
175 getTableData();
176 };
177
178 const handleCreate = () => {
179 router.push({
180 name: 'anonTaskCreate'
181 });
182 }
183
184 onBeforeMount(() => {
185 toSearch({});
186 anonymizationStore?.setIsAnonPageRefresh?.(false);
187 })
188
189 onActivated(() => {
190 if (anonymizationStore.isAnonPageRefresh) {//如果是首次加载,则不需要调用
191 page.value.curr = 1;
192 getTableData();
193 anonymizationStore.setIsAnonPageRefresh(false);
194 }
195 });
196
197 </script>
198
199 <template>
200 <div class="container_wrap">
201 <div class="table_tool_wrap">
202 <!-- 头部搜索 -->
203 <TableTools :searchItems="searchItemList" :searchId="'data-label-search'" @search="toSearch" :init="false" />
204 <div class="tools_btns">
205 <el-button type="primary" @click="handleCreate">新建</el-button>
206 </div>
207 </div>
208 <div class="table_panel_wrap">
209 <!-- 右侧标签管理表格 -->
210 <Table :tableInfo="tableInfo" @tablePageChange="tablePageChange" />
211 </div>
212 </div>
213 </template>
214
215 <style lang="scss" scoped>
216 .table_tool_wrap {
217 width: 100%;
218 height: 84px !important;
219 padding: 0 8px;
220
221 .tools_btns {
222 padding: 0px 0 0;
223 }
224 }
225
226 .table_panel_wrap {
227 width: 100%;
228 height: calc(100% - 84px);
229 padding: 0px 8px 0;
230 }
231 </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 import { TableColumnWidth } from "@/utils/enum";
15
16
17 const { proxy } = getCurrentInstance() as any;
18
19 const router = useRouter();
20 const route = useRoute();
21 const guid = route.query.guid;
22 const wordName = route.query.name
23
24 const page = ref({
25 ...commonPageConfig
26 });
27
28 const tableInfo = ref({
29 id: "word-log-table",
30 loading: false,
31 fields: [
32 { label: "序号", type: "index", width: TableColumnWidth.INDEX, align: "center" },
33 { label: "执行人", field: "createUserName", width: TableColumnWidth.USERNAME },
34 { label: "执行时间", field: "execTime", width: TableColumnWidth.DATETIME },
35 { label: "执行状态", field: "sensitiveIdentifyTaskStatus", width: TableColumnWidth.STATE, align: 'center', type: "tag" },
36 { label: "确认人", field: "confirmUserName", width: TableColumnWidth.USERNAME },
37 { label: "确认时间", field: "confirmTime", width: TableColumnWidth.DATETIME },
38 { label: "确认状态", field: "sensitiveIdentifyConfirmStatus", width: TableColumnWidth.STATE, align: 'center', type: "tag" },
39 ],
40 data: [],
41 page: {
42 type: "normal",
43 rows: 0,
44 ...page.value,
45 },
46 actionInfo: {
47 label: "操作",
48 type: "btn",
49 width: 100,
50 fixed: 'right',
51 btns: (scope) => {
52 return [{
53 label: "查看", value: "report", disabled: scope.row['status'] != 'Y', click: (scope) => {
54 router.push({
55 name: 'sensitiveIdentifyConfig',
56 query: {
57 guid: route.query.guid,
58 execGuid: scope.row.guid,
59 taskName: route.query.name,
60 isLook: '1',
61 }
62 });
63 }
64 }];
65 }
66 }
67 });
68
69 const getTableData = () => {
70 tableInfo.value.loading = true;
71 getSensitiveDataTaskExecLog({ pageIndex: page.value.curr, pageSize: page.value.limit, taskGuid: guid }).then((res: any) => {
72 tableInfo.value.loading = false;
73 if (res?.code == proxy.$passCode) {
74 const data = res.data || {}
75 tableInfo.value.data = data.records?.map(d => {
76 d.sensitiveIdentifyTaskStatus = d.status;
77 d.sensitiveIdentifyConfirmStatus = d.confirmStatus;
78 return d;
79 }) || []
80 tableInfo.value.page.limit = data.pageSize
81 tableInfo.value.page.curr = data.pageIndex
82 tableInfo.value.page.rows = data.totalRows
83 } else {
84 ElMessage.error(res.msg);
85 }
86 })
87 };
88
89 const tableBtnClick = (scope, btn) => {
90 const type = btn.value;
91 const row = scope.row;
92 if (type == 'reportView') {
93 router.push({
94 name: 'analysisReport',
95 query: {
96 planGuid: row.planGuid,
97 reportExecGuid: row.guid,
98 name: wordName
99 }
100 });
101 }
102 };
103
104 onActivated(() => {
105 getTableData();
106 });
107
108 </script>
109
110 <template>
111 <div class="container_wrap">
112 <div class="table_panel_wrap">
113 <Table :tableInfo="tableInfo" @tableBtnClick="tableBtnClick" />
114 </div>
115 </div>
116 </template>
117
118 <style lang="scss" scoped>
119 .container_wrap {
120 padding: 0;
121
122 .table_panel_wrap {
123 height: 100%;
124 padding: 16px 16px 0;
125 }
126 }
127 </style>
...\ No newline at end of file ...\ No newline at end of file
...@@ -1392,7 +1392,7 @@ onActivated(() => { ...@@ -1392,7 +1392,7 @@ onActivated(() => {
1392 <ContentWrap v-show="!currentStep && detailType == 'sign' || currentStep == 3" id="sign-info" title="合约签署" 1392 <ContentWrap v-show="!currentStep && detailType == 'sign' || currentStep == 3" id="sign-info" title="合约签署"
1393 expandSwicth style="margin-top: 15px" :isExpand="expandSign" @expand="(v) => (expandSign = v)" description=""> 1393 expandSwicth style="margin-top: 15px" :isExpand="expandSign" @expand="(v) => (expandSign = v)" description="">
1394 <template v-for="(item, index) in signDetailInfo"> 1394 <template v-for="(item, index) in signDetailInfo">
1395 <div :class="{ 'h-title': true, 'mt6': index > 0 }">{{ item.executionerTypeName }}</div> 1395 <div :class="{ 'h-title': true, 'mt6': <number>index > 0 }">{{ item.executionerTypeName }}</div>
1396 <div class="list_panel"> 1396 <div class="list_panel">
1397 <div class="list_item wrap"> 1397 <div class="list_item wrap">
1398 <span class="item_label">签署主体标识</span> 1398 <span class="item_label">签署主体标识</span>
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!