匿名化处理的接口联调
Showing
10 changed files
with
452 additions
and
33 deletions
| ... | @@ -67,6 +67,12 @@ export const getGeneralizeFileList = (params) => request({ | ... | @@ -67,6 +67,12 @@ export const getGeneralizeFileList = (params) => request({ |
| 67 | data: params | 67 | data: params |
| 68 | }) | 68 | }) |
| 69 | 69 | ||
| 70 | /** 获取泛化文件列表,包括名称和guid */ | ||
| 71 | export const getGeneralizeFileNameList = () => request({ | ||
| 72 | url: `${import.meta.env.VITE_APP_ANONYMIZATION_BASEURL}/generalize-file/name-list`, | ||
| 73 | method: 'post' | ||
| 74 | }) | ||
| 75 | |||
| 70 | export const saveGeneralizeFile = (data) => request({ | 76 | export const saveGeneralizeFile = (data) => request({ |
| 71 | url: `${import.meta.env.VITE_APP_ANONYMIZATION_BASEURL}/generalize-file/save`, | 77 | url: `${import.meta.env.VITE_APP_ANONYMIZATION_BASEURL}/generalize-file/save`, |
| 72 | method: 'post', | 78 | method: 'post', |
| ... | @@ -213,4 +219,105 @@ export const deleteAnonTask = (data) => request({ | ... | @@ -213,4 +219,105 @@ export const deleteAnonTask = (data) => request({ |
| 213 | url: `${import.meta.env.VITE_APP_ANONYMIZATION_BASEURL}/anon-task/delete`, | 219 | url: `${import.meta.env.VITE_APP_ANONYMIZATION_BASEURL}/anon-task/delete`, |
| 214 | method: 'delete', | 220 | method: 'delete', |
| 215 | data | 221 | data |
| 222 | }) | ||
| 223 | |||
| 224 | /** 保存匿名化任务 */ | ||
| 225 | export const saveAnonTask = (params) => request({ | ||
| 226 | url: `${import.meta.env.VITE_APP_ANONYMIZATION_BASEURL}/anon-task/save`, | ||
| 227 | method: 'post', | ||
| 228 | data: params | ||
| 229 | }) | ||
| 230 | |||
| 231 | /** 更新匿名化任务 */ | ||
| 232 | export const updateAnonTask = (params) => request({ | ||
| 233 | url: `${import.meta.env.VITE_APP_ANONYMIZATION_BASEURL}/anon-task/update`, | ||
| 234 | method: 'put', | ||
| 235 | data: params | ||
| 236 | }) | ||
| 237 | |||
| 238 | /** 获取匿名化任务详情 */ | ||
| 239 | export const getAnonTaskDetail = (guid) => request({ | ||
| 240 | url: `${import.meta.env.VITE_APP_ANONYMIZATION_BASEURL}/anon-task/detail?guid=${guid}`, | ||
| 241 | method: 'get' | ||
| 242 | }) | ||
| 243 | |||
| 244 | /** 执行匿名化任务 */ | ||
| 245 | export const execAnonTask = (taskGuid) => request({ | ||
| 246 | url: `${import.meta.env.VITE_APP_ANONYMIZATION_BASEURL}/anon-task/exec-task?taskGuid=${taskGuid}`, | ||
| 247 | method: 'post' | ||
| 248 | }) | ||
| 249 | |||
| 250 | /** 匿名化任务检验接口 */ | ||
| 251 | export const anonTaskCheck = (params) => request({ | ||
| 252 | url: `${import.meta.env.VITE_APP_ANONYMIZATION_BASEURL}/anon-task/check`, | ||
| 253 | method: 'post', | ||
| 254 | data: params | ||
| 255 | }) | ||
| 256 | |||
| 257 | /** 获取匿名化任务分析结果数据 */ | ||
| 258 | export const getAnonAnalyzeResult = (execGuid) => request({ | ||
| 259 | url: `${import.meta.env.VITE_APP_ANONYMIZATION_BASEURL}/anon-task/get-anon-analyze?taskExecGuid=${execGuid}`, | ||
| 260 | method: 'get' | ||
| 261 | }) | ||
| 262 | |||
| 263 | /** 获取匿名化任务分析结果统计分页数据 */ | ||
| 264 | export const getAnonAnalyzePageData = (params) => request({ | ||
| 265 | url: `${import.meta.env.VITE_APP_ANONYMIZATION_BASEURL}/anon-task/page-anon-analyze-data`, | ||
| 266 | method: 'post', | ||
| 267 | data: params | ||
| 268 | }) | ||
| 269 | |||
| 270 | /** 获取匿名化任务结果数据 */ | ||
| 271 | export const getAnonPageData = (params) => request({ | ||
| 272 | url: `${import.meta.env.VITE_APP_ANONYMIZATION_BASEURL}/anon-task/page-anon-data`, | ||
| 273 | method: 'post', | ||
| 274 | data: params | ||
| 275 | }) | ||
| 276 | |||
| 277 | /** 字段中文转英文 */ | ||
| 278 | export const chTransformEn =(params)=> request({ | ||
| 279 | url: `${import.meta.env.VITE_APP_COMMON_URL}/common/convert-field-ch-name`, | ||
| 280 | method: "post", | ||
| 281 | data: params, | ||
| 282 | }); | ||
| 283 | |||
| 284 | /** 根据选择的连接池获取表列表 */ | ||
| 285 | export const getDsTableByDs = (params) => request({ | ||
| 286 | url: `${import.meta.env.VITE_APP_DATA_SOURCE_URL}/data-source/schema-table-page-list`, | ||
| 287 | method: 'post', | ||
| 288 | data: params | ||
| 289 | }) | ||
| 290 | |||
| 291 | /** 根据数据表获取表字段结构 */ | ||
| 292 | export const getDsTableFieldColumn = (params) => request({ | ||
| 293 | url: `${import.meta.env.VITE_APP_DATA_SOURCE_URL}/data-source/table-column-list`, | ||
| 294 | method: 'post', | ||
| 295 | data: params | ||
| 296 | }); | ||
| 297 | |||
| 298 | /** 根据数据表获取表数据 */ | ||
| 299 | export const getDsTableSampleData = (params) => request({ | ||
| 300 | url: `${import.meta.env.VITE_APP_DATA_SOURCE_URL}/data-source/table-data-preview-page`, | ||
| 301 | method: 'post', | ||
| 302 | data: params | ||
| 303 | }); | ||
| 304 | |||
| 305 | /** 根据字段名称获取敏感数据识别标签 */ | ||
| 306 | export const getLableByFieldName = (fieldName) => request({ | ||
| 307 | url: `${import.meta.env.VITE_APP_ANONYMIZATION_BASEURL}/sensitive-data-task/get-label-by-field-name?fieldName=${fieldName}`, | ||
| 308 | method: 'get' | ||
| 309 | }); | ||
| 310 | |||
| 311 | /** 验证样本数据 */ | ||
| 312 | export const validateAnonRule = (params) => request({ | ||
| 313 | url: `${import.meta.env.VITE_APP_ANONYMIZATION_BASEURL}/anon-task/check`, | ||
| 314 | method: 'post', | ||
| 315 | data: params | ||
| 316 | }) | ||
| 317 | |||
| 318 | /** 导出匿名化结果数据 */ | ||
| 319 | export const exportAnonExecData = (params) => request({ | ||
| 320 | url: `${import.meta.env.VITE_APP_ANONYMIZATION_BASEURL}/anon-task/export-anon-data?taskGuid=${params.taskGuid}&taskExecGuid=${params.execGuid}`, | ||
| 321 | method: 'get', | ||
| 322 | responseType: 'blob' | ||
| 216 | }) | 323 | }) |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| ... | @@ -13,6 +13,7 @@ const emits = defineEmits([ | ... | @@ -13,6 +13,7 @@ const emits = defineEmits([ |
| 13 | "drawerBtnClick", | 13 | "drawerBtnClick", |
| 14 | "radioGroupChange", | 14 | "radioGroupChange", |
| 15 | "drawerSelectChange", | 15 | "drawerSelectChange", |
| 16 | 'drawerInputChange', | ||
| 16 | "drawerTableSelectChange", | 17 | "drawerTableSelectChange", |
| 17 | "drawerTableBtnClick", | 18 | "drawerTableBtnClick", |
| 18 | "drawerTableToolBtnClick", | 19 | "drawerTableToolBtnClick", |
| ... | @@ -98,15 +99,15 @@ const onClickOutside = (e: any) => { | ... | @@ -98,15 +99,15 @@ const onClickOutside = (e: any) => { |
| 98 | emits("onClickOutside"); | 99 | emits("onClickOutside"); |
| 99 | }; | 100 | }; |
| 100 | 101 | ||
| 101 | const getDrawerConRef = (refName) => { | 102 | const getDrawerConRef = (refName, index = 0) => { |
| 102 | console.log(refName, '----------') | 103 | //console.log(refName, '----------') |
| 103 | if (refName == 'drawerTableRef') { | 104 | if (refName == 'drawerTableRef') { |
| 104 | const dtf = drawerTableRef.value[0] || drawerTableRef.value | 105 | const dtf = drawerTableRef.value[0] || drawerTableRef.value |
| 105 | return dtf?.tableRef | 106 | return dtf?.tableRef |
| 106 | } | 107 | } |
| 107 | // const drawerForm = drawerFormRef.value[0] || drawerFormRef.value; | 108 | // const drawerForm = drawerFormRef.value[0] || drawerFormRef.value; |
| 108 | if (refName == 'drawerFormRef') { | 109 | if (refName == 'drawerFormRef') { |
| 109 | const drawerForm = drawerFormRef.value?.[0] || drawerFormRef.value; | 110 | const drawerForm = drawerFormRef.value?.[index] || drawerFormRef.value; |
| 110 | return drawerForm | 111 | return drawerForm |
| 111 | } | 112 | } |
| 112 | } | 113 | } |
| ... | @@ -187,6 +188,10 @@ const radioGroupChange = (val, info) => { | ... | @@ -187,6 +188,10 @@ const radioGroupChange = (val, info) => { |
| 187 | emits("radioGroupChange", val, info); | 188 | emits("radioGroupChange", val, info); |
| 188 | }; | 189 | }; |
| 189 | 190 | ||
| 191 | const formInputChange = (val, row, info) => { | ||
| 192 | emits("drawerInputChange", val, row, info); | ||
| 193 | } | ||
| 194 | |||
| 190 | const formSelectChange = (val, row, info) => { | 195 | const formSelectChange = (val, row, info) => { |
| 191 | emits("drawerSelectChange", val, row, info); | 196 | emits("drawerSelectChange", val, row, info); |
| 192 | }; | 197 | }; |
| ... | @@ -319,10 +324,10 @@ const drawerClose = () => { | ... | @@ -319,10 +324,10 @@ const drawerClose = () => { |
| 319 | <template v-else> | 324 | <template v-else> |
| 320 | <Form ref="drawerFormRef" :itemList="con.formInfo.items" :formId="con.formInfo.id" :rules="con.formInfo.rules" | 325 | <Form ref="drawerFormRef" :itemList="con.formInfo.items" :formId="con.formInfo.id" :rules="con.formInfo.rules" |
| 321 | :col="con.formInfo.col" :readonly="con.formInfo.readonly" @radioGroupChange="radioGroupChange" | 326 | :col="con.formInfo.col" :readonly="con.formInfo.readonly" @radioGroupChange="radioGroupChange" |
| 322 | @selectChange="formSelectChange" @btnClick="formBtnClick"> | 327 | @selectChange="formSelectChange" @input-change="formInputChange" @btnClick="formBtnClick"> |
| 323 | </Form> | 328 | </Form> |
| 324 | <!-- 插槽内容 --> | 329 | <!-- 插槽内容 --> |
| 325 | <slot></slot> | 330 | <slot v-if="con.showSlot !== false"></slot> |
| 326 | </template> | 331 | </template> |
| 327 | </div> | 332 | </div> |
| 328 | </template> | 333 | </template> | ... | ... |
| ... | @@ -189,27 +189,30 @@ const inputFocus = (event, item) => { | ... | @@ -189,27 +189,30 @@ const inputFocus = (event, item) => { |
| 189 | } | 189 | } |
| 190 | 190 | ||
| 191 | const inputChange = (val, row) => { | 191 | const inputChange = (val, row) => { |
| 192 | let decimalCnt = row.decimalCnt || 2; | ||
| 192 | if (row.inputType == "moneyNumber" || row.inputType == 'scoreNumber') { | 193 | if (row.inputType == "moneyNumber" || row.inputType == 'scoreNumber') { |
| 193 | let strArr = val.split("."); | 194 | let strArr = val.split("."); |
| 194 | if (strArr.length > 1) { | 195 | if (strArr.length > 1) { |
| 195 | let right = strArr[1]; | 196 | let right = strArr[1]; |
| 196 | if (right === "" || right.length < 2) { | 197 | if (right === "" || right.length < decimalCnt) { |
| 197 | formInline.value[row.field] = val = parseFloat(val || 0).toFixed(2); | 198 | formInline.value[row.field] = val = parseFloat(val || 0).toFixed(decimalCnt); |
| 198 | } | 199 | } |
| 199 | } else { | 200 | } else { |
| 200 | formInline.value[row.field] = val = parseFloat(val || 0).toFixed(2); | 201 | formInline.value[row.field] = val = parseFloat(val || 0).toFixed(decimalCnt); |
| 201 | } | 202 | } |
| 202 | } | 203 | } |
| 203 | if (row.inputType == 'scoreNumber' && parseFloat(val) > 100) { | 204 | let max = row.max || 100; |
| 205 | if (row.inputType == 'scoreNumber' && parseFloat(val) > max) { | ||
| 204 | // 先去除非数字和小数点字符 | 206 | // 先去除非数字和小数点字符 |
| 205 | val = val.replace(/[^\d.]/g, ""); | 207 | val = val.replace(/[^\d.]/g, ""); |
| 206 | // 限制最多保留两位小数 | 208 | // 限制最多保留两位小数 |
| 207 | val = val.replace(/\.{2,}/g, "."); | 209 | val = val.replace(/\.{2,}/g, "."); |
| 208 | val = val.replace(/^(\d+)\.(\d{2}).*$/, "$1.$2"); | 210 | let exp2 = new RegExp(`^(\d+)\.(\d{${decimalCnt}}).*$`, 'g'); |
| 211 | val = val.replace(exp2, "$1.$2"); | ||
| 209 | let num = parseFloat(val); | 212 | let num = parseFloat(val); |
| 210 | if (num > 100) { | 213 | if (num > max) { |
| 211 | num = 100; // 超过100时将其设置为100 | 214 | num = max; // 超过100时将其设置为100 |
| 212 | val = num.toFixed(2); // 保证显示为两位小数 | 215 | val = num.toFixed(decimalCnt); // 保证显示为两位小数 |
| 213 | } | 216 | } |
| 214 | formInline.value[row.field] = val; | 217 | formInline.value[row.field] = val; |
| 215 | } | 218 | } |
| ... | @@ -250,11 +253,15 @@ const inputEventChange = (val, item) => { | ... | @@ -250,11 +253,15 @@ const inputEventChange = (val, item) => { |
| 250 | } | 253 | } |
| 251 | return; | 254 | return; |
| 252 | } else if (item.inputType == 'scoreNumber') {//小于100的,保留两位小数 | 255 | } else if (item.inputType == 'scoreNumber') {//小于100的,保留两位小数 |
| 256 | let decimalCnt = item.decimalCnt || 2; | ||
| 253 | formInline.value[item.field] = formInline.value[item.field].toString().replace(/[^\d.]/g, "") | 257 | formInline.value[item.field] = formInline.value[item.field].toString().replace(/[^\d.]/g, "") |
| 258 | /** 连续两个小数点替换为一个小数点 */ | ||
| 254 | formInline.value[item.field] = formInline.value[item.field].toString().replace(/\.{2,}/g, ".") | 259 | formInline.value[item.field] = formInline.value[item.field].toString().replace(/\.{2,}/g, ".") |
| 255 | formInline.value[item.field] = formInline.value[item.field].toString().replace(/^\D*(\d{0,3}(?:\.\d{0,2})?).*$/g, "$1") | 260 | /** 最多取三位整数,2位小数 */ |
| 261 | let exp2 = new RegExp(`^\\D*(\\d{0,3}(?:\\.\\d{0,${decimalCnt}})?).*$`, 'g'); | ||
| 262 | formInline.value[item.field] = formInline.value[item.field].toString().replace(exp2, "$1") | ||
| 256 | if (item.max != null && formInline.value[item.field] > item.max) { | 263 | if (item.max != null && formInline.value[item.field] > item.max) { |
| 257 | formInline.value[item.field] = item.max.toFixed(2); | 264 | formInline.value[item.field] = item.max.toFixed(decimalCnt); |
| 258 | } | 265 | } |
| 259 | return; | 266 | return; |
| 260 | } else if (item.inputType == 'moneyNumber') {// 单位是元,保留两位小数。 | 267 | } else if (item.inputType == 'moneyNumber') {// 单位是元,保留两位小数。 |
| ... | @@ -754,22 +761,31 @@ const panelChange = (scope, row) => { | ... | @@ -754,22 +761,31 @@ const panelChange = (scope, row) => { |
| 754 | <div class="input_panel" v-for="child in item.children"> | 761 | <div class="input_panel" v-for="child in item.children"> |
| 755 | <span v-if="child.prepend">{{ child.prepend }}</span> | 762 | <span v-if="child.prepend">{{ child.prepend }}</span> |
| 756 | <el-input v-if="child.visible ?? true" v-model.trim="formInline[child.field]" | 763 | <el-input v-if="child.visible ?? true" v-model.trim="formInline[child.field]" |
| 757 | :disabled="child.disabled || readonly" :placeholder="child.placeholder" | 764 | :disabled="child.disabled || readonly" :placeholder="child.placeholder" |
| 758 | :maxlength="child.maxlength ?? ''" /> | 765 | :maxlength="child.maxlength ?? ''" @change="(val) => inputChange(val, child)" |
| 766 | @input="(val) => inputEventChange(val, child)" /> | ||
| 759 | <span v-if="child.append">{{ child.append }}</span> | 767 | <span v-if="child.append">{{ child.append }}</span> |
| 760 | </div> | 768 | </div> |
| 761 | </div> | 769 | </div> |
| 762 | <div class="checkbox_input" :class="[item.col, { is_block: item.block }]" | 770 | <div class="checkbox_input" :class="[item.col, { is_block: item.block }]" |
| 763 | v-else-if="item.type == 'checkbox-input-item'"> | 771 | v-else-if="item.type == 'checkbox-input-item'"> |
| 764 | <el-checkbox v-model="formInline[item.field]" :disabled="item.disabled || readonly" | 772 | <el-checkbox v-model="formInline[item.field]" :disabled="item.disabled || readonly" |
| 765 | @change="(val) => checkboxChange(val, item)" :true-label="item.trueValue ?? true" | 773 | @change="(val) => checkboxChange(val, item)" :true-value="item.trueValue ?? true" |
| 766 | :false-label="item.falseValue ?? false">{{ item.placeholder }}</el-checkbox> | 774 | :false-value="item.falseValue ?? false">{{ item.placeholder }}</el-checkbox> |
| 767 | <div class="input_panel" v-for="child in item.children"> | 775 | <div class="input_panel" v-for="child in item.children"> |
| 768 | <el-form-item v-if="child.visible ?? true" :prop="child.field" | 776 | <el-form-item v-if="child.visible ?? true" :prop="child.field" |
| 769 | :validate-status="child.validateStatus ?? ''" :error="child.error" | 777 | :validate-status="child.validateStatus ?? ''" :error="child.error" |
| 770 | :class="[child.col, { is_block: child.block }]" :style="child.style ?? {}"> | 778 | :class="[child.col, { is_block: child.block }]" :style="child.style ?? {}"> |
| 771 | <el-input v-model.trim="formInline[child.field]" :disabled="child.disabled || readonly" | 779 | <el-input v-if="child.type == 'input'" v-model.trim="formInline[child.field]" :disabled="child.disabled || readonly" |
| 772 | :placeholder="child.placeholder" :maxlength="child.maxlength ?? ''" /> | 780 | :placeholder="child.placeholder" :maxlength="child.maxlength ?? ''" @change="(val) => inputChange(val, child)" |
| 781 | @input="(val) => inputEventChange(val, child)" /> | ||
| 782 | <el-select v-else-if="child.type == 'select'" v-model="formInline[child.field]" | ||
| 783 | :placeholder="child.placeholder" :disabled="child.disabled || readonly" :filterable="child.filterable" :clearable="child.clearable" | ||
| 784 | :teleported="child.teleported || true"> | ||
| 785 | <el-option v-for="opts in child.options" | ||
| 786 | :label="child.props?.label ? opts[child.props.label] : opts.label" | ||
| 787 | :value="child.props?.value ? opts[child.props.value] : opts.value" :disabled="opts.disabled" /> | ||
| 788 | </el-select> | ||
| 773 | </el-form-item> | 789 | </el-form-item> |
| 774 | </div> | 790 | </div> |
| 775 | </div> | 791 | </div> | ... | ... |
| ... | @@ -147,7 +147,7 @@ const routes: RouteRecordRaw[] = [ | ... | @@ -147,7 +147,7 @@ const routes: RouteRecordRaw[] = [ |
| 147 | name: 'anonTaskCreate', | 147 | name: 'anonTaskCreate', |
| 148 | component: () => import('@/views/data_anonymization/anonTaskCreate.vue'), | 148 | component: () => import('@/views/data_anonymization/anonTaskCreate.vue'), |
| 149 | meta: { | 149 | meta: { |
| 150 | title: '新建匿名化处理任务', | 150 | title: '匿名化处理任务', |
| 151 | sidebar: false, | 151 | sidebar: false, |
| 152 | breadcrumb: false, | 152 | breadcrumb: false, |
| 153 | cache: true, | 153 | cache: true, |
| ... | @@ -161,6 +161,23 @@ const routes: RouteRecordRaw[] = [ | ... | @@ -161,6 +161,23 @@ const routes: RouteRecordRaw[] = [ |
| 161 | } | 161 | } |
| 162 | } | 162 | } |
| 163 | }, | 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 | }, | ||
| 164 | ], | 181 | ], |
| 165 | }, | 182 | }, |
| 166 | ] | 183 | ] | ... | ... |
| 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 | getAnonAnalyzeResult, | ||
| 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 | }) | ||
| 42 | |||
| 43 | const getData = () => { | ||
| 44 | tableData.value = []; | ||
| 45 | if (!tableFields.value?.length) { | ||
| 46 | return; | ||
| 47 | } | ||
| 48 | tableDataLoading.value = true; | ||
| 49 | getAnonPageData({ | ||
| 50 | pageIndex: pageInfo.value.curr, | ||
| 51 | pageSize: pageInfo.value.limit, | ||
| 52 | taskExecGuid: props.isPage ? route.query.execGuid : props.execGuid, | ||
| 53 | }).then((res: any) => { | ||
| 54 | tableDataLoading.value = false; | ||
| 55 | if (res.code == proxy.$passCode) { | ||
| 56 | tableData.value = []; | ||
| 57 | res.data?.records?.forEach(d => { | ||
| 58 | let obj = {}; | ||
| 59 | tableFields.value.forEach(t => { | ||
| 60 | obj[t.enName] = d.fieldValue?.[t.enName]; | ||
| 61 | }); | ||
| 62 | tableData.value.push(obj); | ||
| 63 | }); | ||
| 64 | } else { | ||
| 65 | ElMessage.error(res.msg); | ||
| 66 | } | ||
| 67 | }); | ||
| 68 | } | ||
| 69 | |||
| 70 | const getTextAlign = (field) => { | ||
| 71 | if (field.dataType === 'decimal' || field.dataType === 'int' || field.dataType == 'bit' || field.dataType == 'tinyint') { | ||
| 72 | return 'right'; | ||
| 73 | } | ||
| 74 | return 'left' | ||
| 75 | } | ||
| 76 | |||
| 77 | /** otherWidth表示使用标题宽度时添加标题排序图标等宽度 */ | ||
| 78 | const calcTableColumnWidth = (data: any[], prop, title, otherWidth = 0) => { | ||
| 79 | let d: any[] = []; | ||
| 80 | data.forEach((dt) => d.push(dt[prop])); | ||
| 81 | return calcColumnWidth( | ||
| 82 | d, | ||
| 83 | title, | ||
| 84 | { | ||
| 85 | fontSize: 14, | ||
| 86 | fontFamily: "SimSun", | ||
| 87 | }, | ||
| 88 | { | ||
| 89 | fontSize: 14, | ||
| 90 | fontFamily: "SimSun", | ||
| 91 | }, | ||
| 92 | otherWidth | ||
| 93 | ); | ||
| 94 | }; | ||
| 95 | |||
| 96 | /** 每列字段对应的列宽计算结果。 */ | ||
| 97 | const originTableFieldColumn = ref({}); | ||
| 98 | |||
| 99 | watch( | ||
| 100 | tableData, | ||
| 101 | (val: any[], oldVal) => { | ||
| 102 | if (!tableFields.value?.length) { | ||
| 103 | originTableFieldColumn.value = {}; | ||
| 104 | return; | ||
| 105 | } | ||
| 106 | originTableFieldColumn.value = {}; | ||
| 107 | tableFields.value.forEach((field, index) => { | ||
| 108 | originTableFieldColumn.value[field.enName] = calcTableColumnWidth( | ||
| 109 | val?.slice(0, 20) || [], | ||
| 110 | field.enName, | ||
| 111 | field.chName, | ||
| 112 | 24 | ||
| 113 | ); | ||
| 114 | }); | ||
| 115 | }, | ||
| 116 | { | ||
| 117 | deep: true, | ||
| 118 | } | ||
| 119 | ); | ||
| 120 | |||
| 121 | watch(() => props.execGuid, (val) => { | ||
| 122 | if (!val) { | ||
| 123 | return; | ||
| 124 | } | ||
| 125 | tableDataLoading.value = true; | ||
| 126 | getAnonAnalyzeResult(val).then((res: any) => { | ||
| 127 | tableDataLoading.value = false; | ||
| 128 | if (res.code == proxy.$passCode) { | ||
| 129 | let column = res.data?.column || {}; | ||
| 130 | tableFields.value = column; | ||
| 131 | getData(); | ||
| 132 | } else { | ||
| 133 | ElMessage.error(res.msg); | ||
| 134 | } | ||
| 135 | }); | ||
| 136 | }, { | ||
| 137 | immediate: true | ||
| 138 | }) | ||
| 139 | |||
| 140 | onBeforeMount(() => { | ||
| 141 | if (!props.isPage) { | ||
| 142 | return; | ||
| 143 | } | ||
| 144 | tableDataLoading.value = true; | ||
| 145 | getAnonAnalyzeResult(route.query.execGuid).then((res: any) => { | ||
| 146 | tableDataLoading.value = false; | ||
| 147 | if (res.code == proxy.$passCode) { | ||
| 148 | let column = res.data?.column || {}; | ||
| 149 | tableFields.value = column; | ||
| 150 | getData(); | ||
| 151 | } else { | ||
| 152 | ElMessage.error(res.msg); | ||
| 153 | } | ||
| 154 | }); | ||
| 155 | }); | ||
| 156 | |||
| 157 | const formatterPreviewDate = (row, info) => { | ||
| 158 | let enName = info.enName; | ||
| 159 | let v = row[enName]; | ||
| 160 | if (v === 0) { | ||
| 161 | return v; | ||
| 162 | } | ||
| 163 | if (!v || v == 'null') { | ||
| 164 | return '--'; | ||
| 165 | } | ||
| 166 | if (info.dataType === 'datetime') { | ||
| 167 | return Moment(v).format('YYYY-MM-DD HH:mm:ss'); | ||
| 168 | } | ||
| 169 | if (info.dataType === 'date') { | ||
| 170 | if (isNaN(<any>(new Date(v)))) { | ||
| 171 | return Moment(parseInt(v)).format('YYYY-MM-DD'); | ||
| 172 | } else { | ||
| 173 | return Moment(v).format('YYYY-MM-DD'); | ||
| 174 | } | ||
| 175 | } | ||
| 176 | return v; | ||
| 177 | }; | ||
| 178 | |||
| 179 | const pageChange = (info) => { | ||
| 180 | pageInfo.value.curr = Number(info.curr); | ||
| 181 | pageInfo.value.limit = Number(info.limit); | ||
| 182 | getData(); | ||
| 183 | } | ||
| 184 | |||
| 185 | const promise: any = ref(null); | ||
| 186 | |||
| 187 | const exportData = () => { | ||
| 188 | if (promise) { | ||
| 189 | return; | ||
| 190 | } | ||
| 191 | promise.value = exportAnonExecData({ | ||
| 192 | taskGuid: route.query.guid, | ||
| 193 | execGuid: route.query.execGuid | ||
| 194 | }).then((res: any) => { | ||
| 195 | promise.value = null; | ||
| 196 | if (res && !res.msg) { | ||
| 197 | download(res, route.query.taskName + '_匿名化数据.xlsx', 'excel') | ||
| 198 | } else { | ||
| 199 | res?.msg && ElMessage.error(res?.msg); | ||
| 200 | } | ||
| 201 | }).catch(() => { | ||
| 202 | promise.value = null; | ||
| 203 | }) | ||
| 204 | } | ||
| 205 | |||
| 206 | </script> | ||
| 207 | |||
| 208 | <template> | ||
| 209 | <div class="table_tool_wrap" v-loading="tableDataLoading"> | ||
| 210 | <el-button v-show="props.isPage" style="margin-bottom: 8px;" type="primary" @click="exportData" | ||
| 211 | v-preReClick>导出数据</el-button> | ||
| 212 | <el-table ref="tableRef" v-show="tableFields.length" :data="tableData" :highlight-current-row="true" stripe border | ||
| 213 | tooltip-effect="light" height="100%" row-key="guid" :style="{ width: '100%', height: 'calc(100% - 64px)' }"> | ||
| 214 | <template v-for="(item, index) in (tableFields || [])"> | ||
| 215 | <el-table-column :label="item.chName" :width="item.dataType === 'datetime' | ||
| 216 | ? TableColumnWidth.DATETIME | ||
| 217 | : item.dataType === 'date' | ||
| 218 | ? TableColumnWidth.DATE | ||
| 219 | : originTableFieldColumn[item.enName] | ||
| 220 | " :align="getTextAlign(item)" :header-align="getTextAlign(item)" | ||
| 221 | :formatter="(row) => formatterPreviewDate(row, item)" :show-overflow-tooltip="true"> | ||
| 222 | </el-table-column> | ||
| 223 | </template> | ||
| 224 | </el-table> | ||
| 225 | <div v-show="!tableFields.length" class="empty-content"> | ||
| 226 | <img src="../../assets/images/empty-data.png" :style="{ width: '168px', height: '96px' }" /> | ||
| 227 | <div class="empty-text">暂无数据</div> | ||
| 228 | </div> | ||
| 229 | <PageNav :class="[pageInfo.type]" :pageInfo="pageInfo" @pageChange="pageChange" /> | ||
| 230 | </div> | ||
| 231 | </template> | ||
| 232 | |||
| 233 | <style lang="scss" scoped> | ||
| 234 | .table_tool_wrap { | ||
| 235 | width: 100%; | ||
| 236 | height: 100%; | ||
| 237 | padding: 8px 16px 16px; | ||
| 238 | |||
| 239 | .tips_text { | ||
| 240 | font-size: 14px; | ||
| 241 | color: var(--el-text-color-tip); | ||
| 242 | display: block; | ||
| 243 | font-weight: normal; | ||
| 244 | margin-bottom: 8px; | ||
| 245 | line-height: 21px; | ||
| 246 | } | ||
| 247 | |||
| 248 | .el-table { | ||
| 249 | display: inline-block; | ||
| 250 | } | ||
| 251 | |||
| 252 | .empty-content { | ||
| 253 | display: flex; | ||
| 254 | align-items: center; | ||
| 255 | justify-content: center; | ||
| 256 | height: 100%; | ||
| 257 | width: 100%; | ||
| 258 | flex-direction: column; | ||
| 259 | |||
| 260 | .empty-text { | ||
| 261 | font-size: 14px; | ||
| 262 | color: #b2b2b2; | ||
| 263 | } | ||
| 264 | } | ||
| 265 | } | ||
| 266 | </style> | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
| ... | @@ -72,18 +72,24 @@ const tableInfo = ref({ | ... | @@ -72,18 +72,24 @@ const tableInfo = ref({ |
| 72 | btns: (scope) => { | 72 | btns: (scope) => { |
| 73 | return [ { | 73 | return [ { |
| 74 | label: "编辑", value: "edit", disabled: scope.row.status == 'R', click: (scope) => { | 74 | label: "编辑", value: "edit", disabled: scope.row.status == 'R', click: (scope) => { |
| 75 | 75 | router.push({ | |
| 76 | name: 'anonTaskCreate', | ||
| 77 | query: { | ||
| 78 | guid: scope.row.guid, | ||
| 79 | taskName: scope.row.taskName | ||
| 80 | } | ||
| 81 | }); | ||
| 76 | } | 82 | } |
| 77 | }, { | 83 | }, { |
| 78 | label: '查看数据', value: 'view', disabled: scope.row.status != 'Y', click: (scope) => { | 84 | label: '查看数据', value: 'view', disabled: scope.row.status != 'Y', click: (scope) => { |
| 79 | // router.push({ | 85 | router.push({ |
| 80 | // name: 'sensitiveIdentifyConfig', | 86 | name: 'anonResultView', |
| 81 | // query: { | 87 | query: { |
| 82 | // guid: scope.row.guid, | 88 | guid: scope.row.guid, |
| 83 | // execGuid: scope.row.execGuid, | 89 | execGuid: scope.row.lastExecGuid, |
| 84 | // taskName: scope.row.taskName | 90 | taskName: scope.row.taskName |
| 85 | // } | 91 | } |
| 86 | // }); | 92 | }); |
| 87 | } | 93 | } |
| 88 | }, { | 94 | }, { |
| 89 | label: "删除", value: "delete", disabled: scope.row.status == 'R', click: (scope) => { | 95 | label: "删除", value: "delete", disabled: scope.row.status == 'R', click: (scope) => { | ... | ... |
| ... | @@ -983,14 +983,14 @@ const btnFormClick = (btn, type) => { | ... | @@ -983,14 +983,14 @@ const btnFormClick = (btn, type) => { |
| 983 | modelsDialogVisible.value = true; | 983 | modelsDialogVisible.value = true; |
| 984 | if (!databaseList.value?.length) { | 984 | if (!databaseList.value?.length) { |
| 985 | getDataSourceListData().then(() => { | 985 | getDataSourceListData().then(() => { |
| 986 | if (databaseInfo.value == databaseList.value[0]?.guid ?? "") { | 986 | if (databaseInfo.value == (databaseList.value[0]?.guid ?? "")) { |
| 987 | dsFromTreeData.value = JSON.parse(JSON.stringify(currentDsFromTreeData.value)); | 987 | dsFromTreeData.value = JSON.parse(JSON.stringify(currentDsFromTreeData.value)); |
| 988 | } else { | 988 | } else { |
| 989 | databaseInfo.value = databaseList.value[0]?.guid ?? ""; | 989 | databaseInfo.value = databaseList.value[0]?.guid ?? ""; |
| 990 | } | 990 | } |
| 991 | }) | 991 | }) |
| 992 | } else { | 992 | } else { |
| 993 | if (databaseInfo.value == databaseList.value[0]?.guid ?? "") { | 993 | if (databaseInfo.value == (databaseList.value[0]?.guid ?? "")) { |
| 994 | dsFromTreeData.value = JSON.parse(JSON.stringify(currentDsFromTreeData.value)); | 994 | dsFromTreeData.value = JSON.parse(JSON.stringify(currentDsFromTreeData.value)); |
| 995 | } else { | 995 | } else { |
| 996 | databaseInfo.value = databaseList.value[0]?.guid ?? ""; | 996 | databaseInfo.value = databaseList.value[0]?.guid ?? ""; | ... | ... |
-
Please register or sign in to post a comment