支持根据标准新建数据集
Showing
7 changed files
with
2681 additions
and
12 deletions
| ... | @@ -404,7 +404,137 @@ export const getSankeyData = (guid) => request({ | ... | @@ -404,7 +404,137 @@ export const getSankeyData = (guid) => request({ |
| 404 | 404 | ||
| 405 | /** 数仓目录树列表查询 */ | 405 | /** 数仓目录树列表查询 */ |
| 406 | export const getDataWareCatalogList = (params) => request({ | 406 | export const getDataWareCatalogList = (params) => request({ |
| 407 | url: `${import.meta.env.VITE_APP_DATA_DELIVERY}delivery/ms-daop-data-plan-service/data-catalog-directory/tree-list`, | 407 | // url: `${import.meta.env.VITE_APP_DATA_DELIVERY}delivery/ms-daop-data-plan-service/data-catalog-directory/tree-list`, |
| 408 | url: `http://localhost:9000/delivery/ms-daop-data-plan-service/data-catalog-directory/tree-list`, | ||
| 408 | method: 'post', | 409 | method: 'post', |
| 409 | data: params | 410 | data: params |
| 410 | }) | 411 | }) |
| 412 | |||
| 413 | export const getAllFlowData = (dictType) => request({ | ||
| 414 | url: `${import.meta.env.VITE_APP_CONFIG_URL}/dict/data/get-by-dictType?dictType=${dictType}`, | ||
| 415 | method: 'get', | ||
| 416 | }) | ||
| 417 | |||
| 418 | /** 元数据标准guid查询新建数据集字段 */ | ||
| 419 | export const getMetaStandardDsField = (guid) => request({ | ||
| 420 | url: `${import.meta.env.VITE_APP_STANDARD_URL}/meta-standard/get-standard?metaStandardGuid=${guid}`, | ||
| 421 | method: 'get' | ||
| 422 | }) | ||
| 423 | |||
| 424 | /** 表分类类型 */ | ||
| 425 | export const tableCategoryList = [ | ||
| 426 | { | ||
| 427 | value: 1, | ||
| 428 | label: "明细表", | ||
| 429 | }, | ||
| 430 | { | ||
| 431 | value: 2, | ||
| 432 | label: "汇总表", | ||
| 433 | }, | ||
| 434 | { | ||
| 435 | value: 3, | ||
| 436 | label: "应用表", | ||
| 437 | }, | ||
| 438 | { | ||
| 439 | value: 6, | ||
| 440 | label: "业务表", | ||
| 441 | }, | ||
| 442 | // { | ||
| 443 | // value: 4, | ||
| 444 | // label: "维度表", | ||
| 445 | // }, | ||
| 446 | // { | ||
| 447 | // value: 5, | ||
| 448 | // label: "缓慢变化维", | ||
| 449 | // } | ||
| 450 | ]; | ||
| 451 | |||
| 452 | /** 同步策略 */ | ||
| 453 | export const syncPolicys = [ | ||
| 454 | { | ||
| 455 | value: 1, | ||
| 456 | label: "实时", | ||
| 457 | }, | ||
| 458 | { | ||
| 459 | value: 2, | ||
| 460 | label: "增量", | ||
| 461 | }, | ||
| 462 | { | ||
| 463 | value: 3, | ||
| 464 | label: "全量", | ||
| 465 | }, | ||
| 466 | { | ||
| 467 | value: 4, | ||
| 468 | label: "增量加更新", | ||
| 469 | }, | ||
| 470 | ]; | ||
| 471 | |||
| 472 | /** 维表类型 */ | ||
| 473 | export const dimTypeList = [{ | ||
| 474 | label: "列表", | ||
| 475 | value: 1, | ||
| 476 | }, | ||
| 477 | { | ||
| 478 | label: "层级", | ||
| 479 | value: 2, | ||
| 480 | }, | ||
| 481 | { | ||
| 482 | label: "螺旋", | ||
| 483 | value: 3, | ||
| 484 | }, | ||
| 485 | { | ||
| 486 | label: "通用", | ||
| 487 | value: 4, | ||
| 488 | }]; | ||
| 489 | |||
| 490 | /** 表模型分类 */ | ||
| 491 | export const tableModels = [ | ||
| 492 | { | ||
| 493 | label: "主键模型", | ||
| 494 | value: 1, | ||
| 495 | }, | ||
| 496 | { | ||
| 497 | label: "聚合模型", | ||
| 498 | value: 2, | ||
| 499 | }, | ||
| 500 | { | ||
| 501 | label: "明细模型", | ||
| 502 | value: 3, | ||
| 503 | } | ||
| 504 | ]; | ||
| 505 | |||
| 506 | /** 聚合方式 */ | ||
| 507 | export const aggMethodList = [{ | ||
| 508 | value: 'SUM', | ||
| 509 | }, { | ||
| 510 | value: 'MAX' | ||
| 511 | }, { | ||
| 512 | value: 'MIN' | ||
| 513 | }, { | ||
| 514 | value: 'REPLACE' | ||
| 515 | }, { | ||
| 516 | value: 'REPLACE_IF_NOT_NULL' | ||
| 517 | }, { | ||
| 518 | value: 'HLL_UNION' | ||
| 519 | }, { | ||
| 520 | value: 'BITMAP_UNION' | ||
| 521 | }]; | ||
| 522 | |||
| 523 | /** 保存主题表设置,直接入库 */ | ||
| 524 | export const saveSubjectTable = (params) => request({ | ||
| 525 | url: `http://localhost:9000/delivery/ms-daop-data-plan-service/data-catalog-subject/add`, | ||
| 526 | method: 'post', | ||
| 527 | data: params | ||
| 528 | }) | ||
| 529 | |||
| 530 | /** 获取字典列表 */ | ||
| 531 | export const getDictionary = (params) => request({ | ||
| 532 | url: `${import.meta.env.VITE_APP_PLAN_BASEURL}/data-dictionary-general/list-all?state=1`, | ||
| 533 | method: 'post' | ||
| 534 | }) | ||
| 535 | |||
| 536 | /** 获取维度列表 */ | ||
| 537 | export const getDimList = () => request({ | ||
| 538 | url: `http://localhost:9000/delivery/ms-daop-data-plan-service/data-catalog-subject/get-dim-list`, | ||
| 539 | method: 'get' | ||
| 540 | }) | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| ... | @@ -221,6 +221,44 @@ const routes: RouteRecordRaw[] = [ | ... | @@ -221,6 +221,44 @@ const routes: RouteRecordRaw[] = [ |
| 221 | } | 221 | } |
| 222 | }, | 222 | }, |
| 223 | { | 223 | { |
| 224 | path: 'table-create-manual', | ||
| 225 | name: 'tableCreateManual', | ||
| 226 | component: () => import('@/views/data_meta/tableCreateManual.vue'), | ||
| 227 | meta: { | ||
| 228 | title: '新建表', | ||
| 229 | sidebar: false, | ||
| 230 | breadcrumb: false, | ||
| 231 | cache: true, | ||
| 232 | reuse: true, | ||
| 233 | activeMenu: '/data-meta/metadata-standard/standard-query' | ||
| 234 | }, | ||
| 235 | beforeEnter: (to, from) => { | ||
| 236 | if (to.query.domainName) { | ||
| 237 | to.meta.title = `新建表(${to.query.domainName})-${to.query.standardName}`; | ||
| 238 | to.meta.editPage = true; | ||
| 239 | } | ||
| 240 | } | ||
| 241 | }, | ||
| 242 | { | ||
| 243 | path: 'dim-table-create-manual', | ||
| 244 | name: 'dimTableCreateManual', | ||
| 245 | component: () => import('@/views/data_meta/dimTableCreateManual.vue'), | ||
| 246 | meta: { | ||
| 247 | title: '新建表', | ||
| 248 | sidebar: false, | ||
| 249 | breadcrumb: false, | ||
| 250 | cache: true, | ||
| 251 | reuse: true, | ||
| 252 | activeMenu: '/data-meta/metadata-standard/standard-query' | ||
| 253 | }, | ||
| 254 | beforeEnter: (to, from) => { | ||
| 255 | if (to.query.domainName) { | ||
| 256 | to.meta.title = `新建表(${to.query.domainName})-${to.query.standardName}`; | ||
| 257 | to.meta.editPage = true; | ||
| 258 | } | ||
| 259 | } | ||
| 260 | }, | ||
| 261 | { | ||
| 224 | path: 'standard-codetable', | 262 | path: 'standard-codetable', |
| 225 | name: 'metadataStandardCodetable', | 263 | name: 'metadataStandardCodetable', |
| 226 | component: () => import('@/views/data_meta/standard-codetable.vue'), | 264 | component: () => import('@/views/data_meta/standard-codetable.vue'), | ... | ... |
| 1 | <script lang="ts" setup name="existingTableSelect"> | ||
| 2 | import { ref } from "vue"; | ||
| 3 | import Dialog from "@/components/Dialog/index.vue"; | ||
| 4 | |||
| 5 | const emits = defineEmits([ | ||
| 6 | "expandValueChange" | ||
| 7 | ]); | ||
| 8 | |||
| 9 | const props = defineProps({ | ||
| 10 | tableCreateInfo: { | ||
| 11 | type: Object, | ||
| 12 | default: {}, | ||
| 13 | }, | ||
| 14 | partitionAttribute: { | ||
| 15 | type: Object, | ||
| 16 | default: {}, | ||
| 17 | }, | ||
| 18 | isLook: { | ||
| 19 | type: Boolean, | ||
| 20 | default: false | ||
| 21 | } | ||
| 22 | }); | ||
| 23 | |||
| 24 | const expandProperties: any = computed(() => { | ||
| 25 | let partitionAttribute = props.tableCreateInfo.partitionAttribute; | ||
| 26 | return { | ||
| 27 | partitionMode: partitionAttribute?.partitionMode || 'dynamic', | ||
| 28 | staticPartitionType: partitionAttribute?.staticPartitionType || 'Range', | ||
| 29 | partitionCol: partitionAttribute?.partitionCol || "", | ||
| 30 | partitionTimeUnit: partitionAttribute?.partitionTimeUnit || "DAY", | ||
| 31 | dynamicPartitionEnd: partitionAttribute?.dynamicPartitionEnd == null ? 3 : partitionAttribute?.dynamicPartitionEnd, | ||
| 32 | staticPartitionRange: partitionAttribute?.staticPartitionRangeBegin ? [partitionAttribute?.staticPartitionRangeBegin, | ||
| 33 | partitionAttribute?.staticPartitionRangeEnd] : null, | ||
| 34 | dynamicPartitionHistory: partitionAttribute?.dynamicPartitionHistory === "Y", | ||
| 35 | dynamicPartitionHistoryNum: partitionAttribute?.dynamicPartitionHistoryNum, | ||
| 36 | staticPartitionEnum: partitionAttribute?.staticPartitionEnum, | ||
| 37 | } | ||
| 38 | }) | ||
| 39 | |||
| 40 | const formItems: any = ref([ | ||
| 41 | { | ||
| 42 | label: "分区模式", | ||
| 43 | type: "radio-panel", | ||
| 44 | placeholder: "", | ||
| 45 | field: "partitionMode", | ||
| 46 | default: "dynamic", | ||
| 47 | options: [ | ||
| 48 | { label: "动态分区", value: "dynamic" }, | ||
| 49 | { label: "静态分区", value: "static" }, | ||
| 50 | ], | ||
| 51 | children: [], | ||
| 52 | required: true, | ||
| 53 | block: true, | ||
| 54 | col: "no-wrap col2", | ||
| 55 | }, | ||
| 56 | { | ||
| 57 | label: "分区类型", | ||
| 58 | type: "select", | ||
| 59 | placeholder: "请选择", | ||
| 60 | options: [ | ||
| 61 | { | ||
| 62 | label: "Range", | ||
| 63 | value: "Range", | ||
| 64 | }, | ||
| 65 | { | ||
| 66 | label: "List", | ||
| 67 | value: "List", | ||
| 68 | }, | ||
| 69 | ], | ||
| 70 | field: "staticPartitionType", | ||
| 71 | default: 'Range', | ||
| 72 | required: true, | ||
| 73 | visible: false, | ||
| 74 | }, | ||
| 75 | { | ||
| 76 | label: "分区字段", | ||
| 77 | type: "select", | ||
| 78 | placeholder: "请选择", | ||
| 79 | options: [], | ||
| 80 | field: "partitionCol", | ||
| 81 | default: "", | ||
| 82 | props: { | ||
| 83 | label: 'chName', | ||
| 84 | value: 'enName' | ||
| 85 | }, | ||
| 86 | tooltip: true, | ||
| 87 | tooltipContent: '分区字段为日期、日期时间类型且为主键的字段。', | ||
| 88 | clearable: true, | ||
| 89 | required: true, | ||
| 90 | visible: true, | ||
| 91 | }, | ||
| 92 | { | ||
| 93 | label: "分区单位", | ||
| 94 | type: "select", | ||
| 95 | placeholder: "请选择", | ||
| 96 | options: [ | ||
| 97 | { | ||
| 98 | value: "DAY", | ||
| 99 | label: "按天", | ||
| 100 | }, | ||
| 101 | { | ||
| 102 | value: "WEEK", | ||
| 103 | label: "按星期", | ||
| 104 | }, | ||
| 105 | { | ||
| 106 | value: "MONTH", | ||
| 107 | label: "按月", | ||
| 108 | }, | ||
| 109 | { | ||
| 110 | value: "YEAR", | ||
| 111 | label: "按年", | ||
| 112 | }, | ||
| 113 | ], | ||
| 114 | default: "DAY", | ||
| 115 | field: "partitionTimeUnit", | ||
| 116 | required: true, | ||
| 117 | visible: false, | ||
| 118 | }, | ||
| 119 | { | ||
| 120 | type: "select-group", | ||
| 121 | field: "dynamicPartitionTimeUnit", | ||
| 122 | children: [ | ||
| 123 | { | ||
| 124 | label: "分区单位", | ||
| 125 | type: "select", | ||
| 126 | placeholder: "请选择", | ||
| 127 | options: [ | ||
| 128 | { | ||
| 129 | value: "HOUR", | ||
| 130 | label: "按小时", | ||
| 131 | }, | ||
| 132 | { | ||
| 133 | value: "DAY", | ||
| 134 | label: "按天", | ||
| 135 | }, | ||
| 136 | { | ||
| 137 | value: "WEEK", | ||
| 138 | label: "按星期", | ||
| 139 | }, | ||
| 140 | { | ||
| 141 | value: "MONTH", | ||
| 142 | label: "按月", | ||
| 143 | }, | ||
| 144 | { | ||
| 145 | value: "YEAR", | ||
| 146 | label: "按年", | ||
| 147 | }, | ||
| 148 | ], | ||
| 149 | default: "DAY", | ||
| 150 | field: "partitionTimeUnit", | ||
| 151 | required: true, | ||
| 152 | visible: true, | ||
| 153 | }, | ||
| 154 | { | ||
| 155 | label: " ", | ||
| 156 | type: "input", | ||
| 157 | placeholder: "结束偏移量", | ||
| 158 | default: 3, | ||
| 159 | field: "dynamicPartitionEnd", | ||
| 160 | required: true, | ||
| 161 | visible: true, | ||
| 162 | }, | ||
| 163 | ], | ||
| 164 | col: "col2", | ||
| 165 | visible: true | ||
| 166 | }, | ||
| 167 | { | ||
| 168 | label: "分区范围", | ||
| 169 | type: "date-picker", | ||
| 170 | field: "staticPartitionRange", | ||
| 171 | default: null, | ||
| 172 | placeholder: "开始时间~截止时间", | ||
| 173 | clearable: true, | ||
| 174 | required: true, | ||
| 175 | visible: false, | ||
| 176 | }, | ||
| 177 | { | ||
| 178 | type: "checkbox-input", | ||
| 179 | placeholder: "创建历史分区", | ||
| 180 | field: "dynamicPartitionHistory", | ||
| 181 | default: false, | ||
| 182 | children: [ | ||
| 183 | { | ||
| 184 | label: "", | ||
| 185 | type: "input", | ||
| 186 | placeholder: "历史分区数量", | ||
| 187 | field: "dynamicPartitionHistoryNum", | ||
| 188 | default: 1, | ||
| 189 | required: false, | ||
| 190 | visible: false, | ||
| 191 | }, | ||
| 192 | ], | ||
| 193 | class: "dialog-checkbox-input", | ||
| 194 | visible: true, | ||
| 195 | required: false, | ||
| 196 | }, | ||
| 197 | { | ||
| 198 | label: "分区枚举值", | ||
| 199 | type: "textarea", | ||
| 200 | placeholder: "请使用“,”号分隔", | ||
| 201 | field: "staticPartitionEnum", | ||
| 202 | default: "", | ||
| 203 | clearable: true, | ||
| 204 | required: true, | ||
| 205 | block: true, | ||
| 206 | visible: false, | ||
| 207 | }, | ||
| 208 | ]); | ||
| 209 | const formRules = ref({ | ||
| 210 | staticPartitionType: [ | ||
| 211 | { | ||
| 212 | validator: (rule: any, value: any, callback: any) => { | ||
| 213 | if (!value) { | ||
| 214 | callback(new Error("分区类型不为空")); | ||
| 215 | } else { | ||
| 216 | callback(); | ||
| 217 | } | ||
| 218 | }, | ||
| 219 | trigger: "blur", | ||
| 220 | }, | ||
| 221 | ], | ||
| 222 | partitionCol: [{ | ||
| 223 | validator: (rule: any, value: any, callback: any) => { | ||
| 224 | if (!value) { | ||
| 225 | callback(new Error("分区字段不为空")); | ||
| 226 | } else { | ||
| 227 | callback(); | ||
| 228 | } | ||
| 229 | }, | ||
| 230 | trigger: "blur", | ||
| 231 | }], | ||
| 232 | staticPartitionRange: [{ | ||
| 233 | validator: (rule: any, value: any, callback: any) => { | ||
| 234 | if (!value?.length) { | ||
| 235 | callback(new Error("分区范围不为空")); | ||
| 236 | } else { | ||
| 237 | callback(); | ||
| 238 | } | ||
| 239 | }, | ||
| 240 | trigger: "blur", | ||
| 241 | }], | ||
| 242 | staticPartitionEnum: [{ | ||
| 243 | trigger: "blur", | ||
| 244 | required: true, | ||
| 245 | message: '分区枚举值不能为空' | ||
| 246 | }], | ||
| 247 | dynamicPartitionHistoryNum: { | ||
| 248 | validator: (rule: any, value: any, callback: any) => { | ||
| 249 | const r = /(^[0-9]([0-9]*)$|^[0-9]$)/; // 正整数(可以以0打头) | ||
| 250 | if (value && !r.test(value)) { | ||
| 251 | callback(new Error('请填写大于或等于零整数')); | ||
| 252 | return; | ||
| 253 | } | ||
| 254 | if ((value + '').length > 6) { | ||
| 255 | callback(new Error('请填写小于7位的整数')); | ||
| 256 | return; | ||
| 257 | } | ||
| 258 | callback(); | ||
| 259 | }, | ||
| 260 | trigger: "blur", | ||
| 261 | }, | ||
| 262 | dynamicPartitionEnd: { | ||
| 263 | validator: (rule: any, value: any, callback: any) => { | ||
| 264 | const r = /(^[0-9]([0-9]*)$|^[0-9]$)/; // 正整数(可以以0打头) | ||
| 265 | if (value && !r.test(value)) { | ||
| 266 | callback(new Error('请填写大于或等于零整数')); | ||
| 267 | return; | ||
| 268 | } | ||
| 269 | if ((value + '').length > 6) { | ||
| 270 | callback(new Error('请填写小于7位的整数')); | ||
| 271 | return; | ||
| 272 | } | ||
| 273 | callback(); | ||
| 274 | }, | ||
| 275 | trigger: "blur", | ||
| 276 | }, | ||
| 277 | }); | ||
| 278 | |||
| 279 | const expandPropertyDialogInfo = ref({ | ||
| 280 | readonly: false, | ||
| 281 | visible: false, | ||
| 282 | size: 700, | ||
| 283 | height: "270px", | ||
| 284 | header: { | ||
| 285 | title: "扩展属性", | ||
| 286 | }, | ||
| 287 | direction: "column", | ||
| 288 | type: "", | ||
| 289 | contents: [ | ||
| 290 | { | ||
| 291 | type: "form", | ||
| 292 | title: "", | ||
| 293 | formInfo: { | ||
| 294 | readonly: false, | ||
| 295 | id: "edit-expand-property", | ||
| 296 | items: formItems.value, | ||
| 297 | rules: formRules.value, | ||
| 298 | }, | ||
| 299 | }, | ||
| 300 | ], | ||
| 301 | footer: { | ||
| 302 | visible: true, | ||
| 303 | btns: [ | ||
| 304 | { type: "default", label: "取消", value: "cancel" }, | ||
| 305 | { type: "primary", label: "确定", value: "submit" }, | ||
| 306 | ], | ||
| 307 | }, | ||
| 308 | }); | ||
| 309 | |||
| 310 | /** 记录对话框编辑过程中的扩展属性。提交之后才会记录在expandProperties */ | ||
| 311 | const editExpandProperties: any = ref({}); | ||
| 312 | |||
| 313 | /** 扩展属性弹出对话框 */ | ||
| 314 | const handleClickExpand = () => { | ||
| 315 | expandPropertyDialogInfo.value.visible = true; | ||
| 316 | if (props.isLook || props.tableCreateInfo.isCreate) { | ||
| 317 | expandPropertyDialogInfo.value.contents[0].formInfo.readonly = true; | ||
| 318 | expandPropertyDialogInfo.value.footer.visible = false; | ||
| 319 | } else { | ||
| 320 | expandPropertyDialogInfo.value.contents[0].formInfo.readonly = false; | ||
| 321 | expandPropertyDialogInfo.value.footer.visible = true; | ||
| 322 | } | ||
| 323 | if (expandProperties.value.partitionMode === 'dynamic') { | ||
| 324 | formItems.value[1].visible = false; | ||
| 325 | formItems.value[2].visible = true; | ||
| 326 | formItems.value[3].visible = false; | ||
| 327 | formItems.value[4].visible = true; | ||
| 328 | formItems.value[5].visible = false; | ||
| 329 | formItems.value[6].visible = true; | ||
| 330 | formItems.value[7].visible = false; | ||
| 331 | formItems.value[6].children[0].visible = expandProperties.value.dynamicPartitionHistory; | ||
| 332 | formItems.value[2].options = props.tableCreateInfo.tableFields?.filter(field => field.isPrimary === 'Y' && (field.dataType === 'date' || field.dataType === 'datetime')) || []; | ||
| 333 | formItems.value[2].tooltipContent = '分区字段为日期、日期时间类型且为主键的字段。'; | ||
| 334 | } else { | ||
| 335 | formItems.value[1].visible = true; | ||
| 336 | formItems.value[2].visible = true; | ||
| 337 | formItems.value[3].visible = true; | ||
| 338 | formItems.value[4].visible = false; | ||
| 339 | formItems.value[5].visible = true; | ||
| 340 | formItems.value[6].visible = false; | ||
| 341 | formItems.value[7].visible = false; | ||
| 342 | let val = expandProperties.value.staticPartitionType; | ||
| 343 | formItems.value[3].visible = val !== 'List'; | ||
| 344 | formItems.value[5].visible = val !== 'List'; | ||
| 345 | formItems.value[7].visible = val === 'List'; | ||
| 346 | if (val !== 'List') { | ||
| 347 | formItems.value[2].options = props.tableCreateInfo.tableFields?.filter(field => field.isPrimary === 'Y' && (field.dataType === 'date' || field.dataType === 'datetime')) || []; | ||
| 348 | formItems.value[2].tooltipContent = '分区字段为日期、日期时间类型且为主键的字段。'; | ||
| 349 | } else { | ||
| 350 | formItems.value[2].options = props.tableCreateInfo.tableFields?.filter(field => field.isPrimary === 'Y') || []; | ||
| 351 | formItems.value[2].tooltipContent = '分区字段为主键字段。'; | ||
| 352 | } | ||
| 353 | } | ||
| 354 | expandPropertyDialogInfo.value.contents[0].formInfo.items = formItems.value; | ||
| 355 | editExpandProperties.value = Object.assign({}, expandProperties.value); | ||
| 356 | setFormItems(editExpandProperties.value); | ||
| 357 | }; | ||
| 358 | |||
| 359 | /** 重置formItems的值 */ | ||
| 360 | const setFormItems = (row: any = null) => { | ||
| 361 | formItems.value.forEach(item => { | ||
| 362 | if (item.field === 'dynamicPartitionTimeUnit') { | ||
| 363 | item.children.forEach(child => { | ||
| 364 | child.default = row[child.field]; | ||
| 365 | }); | ||
| 366 | } else if (item.field === 'dynamicPartitionHistory') { | ||
| 367 | item.default = row[item.field]; | ||
| 368 | item.children.forEach(child => { | ||
| 369 | child.default = row[child.field]; | ||
| 370 | }); | ||
| 371 | } else { | ||
| 372 | item.default = row[item.field]; | ||
| 373 | } | ||
| 374 | }) | ||
| 375 | } | ||
| 376 | |||
| 377 | const radioGroupChange = (val, info) => { | ||
| 378 | formItems.value[0].default = val; | ||
| 379 | if (val == "dynamic") { | ||
| 380 | formItems.value[1].visible = false; | ||
| 381 | formItems.value[2].visible = true; | ||
| 382 | formItems.value[3].visible = false; | ||
| 383 | formItems.value[4].visible = true; | ||
| 384 | formItems.value[5].visible = false; | ||
| 385 | formItems.value[6].visible = true; | ||
| 386 | formItems.value[7].visible = false; | ||
| 387 | } else if (val == "static") { | ||
| 388 | formItems.value[1].visible = true; | ||
| 389 | formItems.value[2].visible = true; | ||
| 390 | formItems.value[3].visible = true; | ||
| 391 | formItems.value[4].visible = false; | ||
| 392 | formItems.value[5].visible = true; | ||
| 393 | formItems.value[6].visible = false; | ||
| 394 | formItems.value[7].visible = false; | ||
| 395 | } | ||
| 396 | expandPropertyDialogInfo.value.contents[0].formInfo.items = formItems.value; | ||
| 397 | editExpandProperties.value = Object.assign({}, editExpandProperties.value, info) | ||
| 398 | setFormItems(editExpandProperties.value); | ||
| 399 | }; | ||
| 400 | |||
| 401 | const dialogCheckboxChange = (val, info) => { | ||
| 402 | let opts: any = formItems.value[6].children; | ||
| 403 | opts[0].visible = val; | ||
| 404 | editExpandProperties.value = Object.assign({}, editExpandProperties.value, info) | ||
| 405 | setFormItems(editExpandProperties.value); | ||
| 406 | }; | ||
| 407 | |||
| 408 | const dialogSelectChange = (val, row, info) => { | ||
| 409 | if (row.field == 'staticPartitionType') { | ||
| 410 | formItems.value[3].visible = val !== 'List'; | ||
| 411 | formItems.value[5].visible = val !== 'List'; | ||
| 412 | formItems.value[7].visible = val === 'List'; | ||
| 413 | if (val !== 'List') { | ||
| 414 | formItems.value[2].options = props.tableCreateInfo.tableFields?.filter(field => field.isPrimary === 'Y' && (field.dataType === 'date' || field.dataType === 'datetime')) || []; | ||
| 415 | formItems.value[2].tooltipContent = '分区字段为日期、日期时间类型且为主键的字段。'; | ||
| 416 | } else { | ||
| 417 | formItems.value[2].options = props.tableCreateInfo.tableFields?.filter(field => field.isPrimary === 'Y') || []; | ||
| 418 | formItems.value[2].tooltipContent = '分区字段为主键字段。'; | ||
| 419 | } | ||
| 420 | } | ||
| 421 | editExpandProperties.value = Object.assign({}, editExpandProperties.value, info) | ||
| 422 | setFormItems(editExpandProperties.value); | ||
| 423 | } | ||
| 424 | |||
| 425 | const expandPropertyDialogBtnClick = (btn, info) => { | ||
| 426 | if (btn.value == 'submit') { | ||
| 427 | emits('expandValueChange', info); | ||
| 428 | expandPropertyDialogInfo.value.visible = false; | ||
| 429 | } else if (btn.value == 'cancel') { | ||
| 430 | expandPropertyDialogInfo.value.visible = false; | ||
| 431 | } | ||
| 432 | }; | ||
| 433 | |||
| 434 | defineExpose({ | ||
| 435 | handleClickExpand | ||
| 436 | }); | ||
| 437 | |||
| 438 | </script> | ||
| 439 | |||
| 440 | <template> | ||
| 441 | <Dialog ref="expandPropertyDialogRef" :dialogInfo="expandPropertyDialogInfo" @radioGroupChange="radioGroupChange" | ||
| 442 | @checkboxChange="dialogCheckboxChange" @selectChange="dialogSelectChange" @btnClick="expandPropertyDialogBtnClick" /> | ||
| 443 | </template> | ||
| 444 | |||
| 445 | <style scoped lang="scss"></style> | ||
| 446 |
| 1 | <template> | ||
| 2 | <el-select v-if="!readonly && isEdit && isSelectType(dbType, scope)" v-model="scope.row['defaultValue']" placeholder="请选择" collapse-tags-tooltip | ||
| 3 | filterable allow-create default-first-option :reserve-keyword="false"> | ||
| 4 | <el-option v-for="opt in optionsConfig[dataType]" :key="opt['value']" :label="opt['label']" :value="opt['value']" /> | ||
| 5 | </el-select> | ||
| 6 | <el-date-picker v-else-if="!readonly && isEdit && dataType === 'date'" v-model="scope.row['defaultValue']" type="date" | ||
| 7 | format="YYYY-MM-DD" value-format="YYYY-MM-DD" placeholder="请选择" /> | ||
| 8 | <el-date-picker v-else-if="!readonly && isEdit && dbType === 'mysql' && dataType === 'datetime'" | ||
| 9 | v-model="scope.row['defaultValue']" placeholder="请选择" type="datetime" format="YYYY-MM-DD HH:mm:ss" | ||
| 10 | value-format="YYYY-MM-DD HH:mm:ss" /> | ||
| 11 | <el-input v-else-if="!readonly && isEdit" v-model.trim="scope.row['defaultValue']" placeholder="请填写" | ||
| 12 | @input="(val) => inputChange(val, scope.row.dataType, scope)" /> | ||
| 13 | <span v-else>{{ scope.row["defaultValue"] == null ? '-' : (isSelectType(dbType, scope) ? | ||
| 14 | (optionsConfig[dataType].find(s => s.value == scope.row["defaultValue"])?.label ?? | ||
| 15 | scope.row["defaultValue"]) : scope.row["defaultValue"]) }}</span> | ||
| 16 | </template> | ||
| 17 | |||
| 18 | <script lang="ts" setup name="tableDefaultValue"> | ||
| 19 | import { ref } from "vue"; | ||
| 20 | import { useDefault } from "@/hooks/useDefault"; | ||
| 21 | const { optionsConfig, inputChange, isSelectType } = useDefault() | ||
| 22 | |||
| 23 | const props = defineProps({ | ||
| 24 | dbType: { | ||
| 25 | type: String, | ||
| 26 | default: '' | ||
| 27 | }, | ||
| 28 | scope: { | ||
| 29 | type: Object, | ||
| 30 | default: {} | ||
| 31 | }, | ||
| 32 | readonly: { | ||
| 33 | type: Boolean, | ||
| 34 | default: false | ||
| 35 | } | ||
| 36 | }) | ||
| 37 | |||
| 38 | const isEdit = computed(() => { | ||
| 39 | return props.scope.row['isEdit']; | ||
| 40 | }); | ||
| 41 | |||
| 42 | const dataType = computed(() => { | ||
| 43 | return props.scope.row['dataType']; | ||
| 44 | }); | ||
| 45 | |||
| 46 | </script> | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
src/views/data_meta/dimTableCreateManual.vue
0 → 100644
| 1 | <route lang="yaml"> | ||
| 2 | name: dimTableCreateManual | ||
| 3 | </route> | ||
| 4 | |||
| 5 | <script lang="ts" setup name="dimTableCreateManual"> | ||
| 6 | import { ref } from "vue"; | ||
| 7 | import { useRouter, useRoute } from "vue-router"; | ||
| 8 | import { ElMessage, ElMessageBox, ElTable } from "element-plus"; | ||
| 9 | import { QuestionFilled } from "@element-plus/icons-vue"; | ||
| 10 | import { | ||
| 11 | getDatabase, | ||
| 12 | saveSubjectTable, | ||
| 13 | dimTypeList, | ||
| 14 | syncPolicys, | ||
| 15 | tableModels, | ||
| 16 | aggMethodList, | ||
| 17 | getMetaStandardDsField, | ||
| 18 | getAllFlowData | ||
| 19 | } from "@/api/modules/dataMetaService"; | ||
| 20 | import useUserStore from "@/store/modules/user"; | ||
| 21 | import expandPropertyDialog from "./components/expandPropertyDialog.vue"; | ||
| 22 | import tableDefaultValue from "./components/tableDefaultValue.vue"; | ||
| 23 | import { useDefault } from "@/hooks/useDefault" | ||
| 24 | import { getCamundaDeploymentId } from "@/api/modules/workFlowService" | ||
| 25 | |||
| 26 | const userStore = useUserStore(); | ||
| 27 | const { checkDefault } = useDefault() | ||
| 28 | |||
| 29 | const router = useRouter(); | ||
| 30 | const route = useRoute(); | ||
| 31 | const fullPath = route.fullPath; | ||
| 32 | const isLook = <any>route.query.isLook == 1; | ||
| 33 | const subjectDomainGuid: any = ref(route.query.domainGuid); | ||
| 34 | |||
| 35 | const tableCreateInfoLoading = ref(false); | ||
| 36 | |||
| 37 | const { proxy } = getCurrentInstance() as any; | ||
| 38 | const fieldStandardTableRef = ref<InstanceType<typeof ElTable>>(); | ||
| 39 | |||
| 40 | /** 表模型,只有doris数据库才有 */ | ||
| 41 | const dbType = ref(""); | ||
| 42 | |||
| 43 | const databaseList: any = ref([]); | ||
| 44 | |||
| 45 | const tableFieldsLoading = ref(false); | ||
| 46 | |||
| 47 | //记录当前正在编辑的表创建信息。 | ||
| 48 | const tableCreateInfo: Ref<any> = ref({ | ||
| 49 | guid: "", | ||
| 50 | isCreate: false, | ||
| 51 | inputNameValue: '', | ||
| 52 | tableCreateType: 1, | ||
| 53 | tableData: [ | ||
| 54 | { | ||
| 55 | //数据库表信息。 | ||
| 56 | dataSourceGuid: '', | ||
| 57 | dataServerName: "", | ||
| 58 | dataServerChName: "", | ||
| 59 | enName: "", | ||
| 60 | chName: "", | ||
| 61 | subjectDomain: route.query.domainName, | ||
| 62 | subjectDomainGuid: subjectDomainGuid.value, | ||
| 63 | dimType: 1, | ||
| 64 | codeColumn: '', | ||
| 65 | codeName: '', | ||
| 66 | syncPolicy: 3, | ||
| 67 | tableCategory: 4, | ||
| 68 | characterSet: 'utf8mb3', | ||
| 69 | tableModel: 1, //若是聚合模型,下方出现一列聚合方式选择。处了主键列,其余列都需要选择。每个表里都要有主键。 | ||
| 70 | description: "", | ||
| 71 | }, | ||
| 72 | ], | ||
| 73 | partitionAttribute: {}, | ||
| 74 | tableFields: [], // 字段标准数组。 | ||
| 75 | }); | ||
| 76 | |||
| 77 | const selectTableFieldRows = ref([]); | ||
| 78 | |||
| 79 | //字段类型 | ||
| 80 | const fieldTypes: any = ref([]); | ||
| 81 | |||
| 82 | //字符集 | ||
| 83 | const characterList: any = ref([]); | ||
| 84 | |||
| 85 | //是否列表 | ||
| 86 | const isNotList = ref([ | ||
| 87 | { | ||
| 88 | label: "Y", | ||
| 89 | value: "Y", | ||
| 90 | }, | ||
| 91 | { | ||
| 92 | label: "N", | ||
| 93 | value: "N", | ||
| 94 | }, | ||
| 95 | ]); | ||
| 96 | |||
| 97 | const fullscreenLoading = ref(false); | ||
| 98 | |||
| 99 | /** 表里有数据时删除字段时提示。 */ | ||
| 100 | const hasSubjectData = ref(false); | ||
| 101 | |||
| 102 | const expandProperties = ref({}); | ||
| 103 | |||
| 104 | const deploymentId = ref(''); | ||
| 105 | const flowExpand = ref(true); | ||
| 106 | |||
| 107 | onBeforeMount(() => { | ||
| 108 | getDatabaseList(); | ||
| 109 | getFieldTypeList(); | ||
| 110 | getCharacterListData(); | ||
| 111 | if (route.query.metaStandard) { | ||
| 112 | tableCreateInfo.value.tableData[0].chName = route.query.standardName; | ||
| 113 | tableCreateInfoLoading.value = true; | ||
| 114 | getMetaStandardDsField(route.query.metaStandard).then((res: any) => { | ||
| 115 | tableCreateInfoLoading.value = false; | ||
| 116 | if (res.code == proxy.$passCode) { | ||
| 117 | tableCreateInfo.value.tableFields = res.data?.map((d, i) => { | ||
| 118 | d.orderNum = i; | ||
| 119 | d.isEdit = true; | ||
| 120 | return d; | ||
| 121 | }) || []; | ||
| 122 | } else { | ||
| 123 | proxy.$ElMessage.error(res.msg); | ||
| 124 | } | ||
| 125 | }) | ||
| 126 | } | ||
| 127 | getCamundaDeploymentId('10025').then((res: any) => { | ||
| 128 | if (res.code == proxy.$passCode) { | ||
| 129 | deploymentId.value = res.data; | ||
| 130 | } else { | ||
| 131 | proxy.$ElMessage.error(res.msg); | ||
| 132 | } | ||
| 133 | }) | ||
| 134 | }) | ||
| 135 | |||
| 136 | onMounted(() => { | ||
| 137 | }) | ||
| 138 | |||
| 139 | onActivated(() => { | ||
| 140 | }); | ||
| 141 | |||
| 142 | const getDatabaseList = () => { | ||
| 143 | getDatabase({ connectStatus: 1 }).then((res: any) => { | ||
| 144 | databaseList.value = []; | ||
| 145 | if (res.code == proxy.$passCode) { | ||
| 146 | databaseList.value = res.data || []; | ||
| 147 | } else { | ||
| 148 | ElMessage.error(res.msg); | ||
| 149 | } | ||
| 150 | }) | ||
| 151 | }; | ||
| 152 | |||
| 153 | const getFieldTypeList = () => { | ||
| 154 | getAllFlowData('字段类型').then((res: any) => { | ||
| 155 | fieldTypes.value = []; | ||
| 156 | if (res.code == proxy.$passCode) { | ||
| 157 | fieldTypes.value = res.data || []; | ||
| 158 | } else { | ||
| 159 | ElMessage.error(res.msg); | ||
| 160 | } | ||
| 161 | }) | ||
| 162 | } | ||
| 163 | |||
| 164 | const getCharacterListData = () => { | ||
| 165 | getAllFlowData('Mysql字符集').then((res: any) => { | ||
| 166 | characterList.value = []; | ||
| 167 | if (res.code == proxy.$passCode) { | ||
| 168 | characterList.value = res.data || []; | ||
| 169 | } else { | ||
| 170 | ElMessage.error(res.msg); | ||
| 171 | } | ||
| 172 | }) | ||
| 173 | } | ||
| 174 | |||
| 175 | /** 限制长度输入框只能输入整型数字,表,字段英文名称,限制输入字符,数字和下划线。 */ | ||
| 176 | const inputLengthKeyUp = (regexp, scope, field, max: any = null, min: any = null) => { | ||
| 177 | scope.row[field] = scope.row[field].replace(regexp, ''); | ||
| 178 | if (field == 'fieldLength' && scope.row.dataType == 'decimal') { | ||
| 179 | max = 65; | ||
| 180 | } | ||
| 181 | /** 最大值设置2000 */ | ||
| 182 | if (max && scope.row[field] > max) { | ||
| 183 | scope.row[field] = max; | ||
| 184 | } | ||
| 185 | if (min !== null && scope.row[field] != '' && scope.row[field] <= min) { | ||
| 186 | scope.row[field] = min; | ||
| 187 | } | ||
| 188 | } | ||
| 189 | |||
| 190 | /** 保存表 */ | ||
| 191 | const saveTable = () => { | ||
| 192 | let tableData = tableCreateInfo.value.tableData[0]; | ||
| 193 | if (!tableData.chName) { | ||
| 194 | ElMessage({ | ||
| 195 | type: "error", | ||
| 196 | message: "主题表名称不能为空", | ||
| 197 | }); | ||
| 198 | return; | ||
| 199 | } | ||
| 200 | if (!tableData.dataServerName) { | ||
| 201 | ElMessage({ | ||
| 202 | type: "error", | ||
| 203 | message: "数据源不能为空", | ||
| 204 | }); | ||
| 205 | return; | ||
| 206 | } | ||
| 207 | if (tableData.dataServerName.indexOf('-') > -1) { | ||
| 208 | ElMessage.error('数据库表名称不能包含中划线,可以改为下划线'); | ||
| 209 | return; | ||
| 210 | } | ||
| 211 | if (!tableCreateInfo.value.inputNameValue) { | ||
| 212 | ElMessage({ | ||
| 213 | type: "error", | ||
| 214 | message: "主题表名称不能为空", | ||
| 215 | }); | ||
| 216 | return; | ||
| 217 | } | ||
| 218 | if (!tableData.codeColumn) { | ||
| 219 | ElMessage({ | ||
| 220 | type: "error", | ||
| 221 | message: "编码字段不能为空", | ||
| 222 | }); | ||
| 223 | return; | ||
| 224 | } | ||
| 225 | if (!tableData.codeName) { | ||
| 226 | ElMessage({ | ||
| 227 | type: "error", | ||
| 228 | message: "编码名称不能为空", | ||
| 229 | }); | ||
| 230 | return; | ||
| 231 | } | ||
| 232 | let tableFields = tableCreateInfo.value.tableFields; | ||
| 233 | if (!tableFields.length) { | ||
| 234 | ElMessage({ | ||
| 235 | type: "error", | ||
| 236 | message: "表字段不能为0行", | ||
| 237 | }); | ||
| 238 | return; | ||
| 239 | } | ||
| 240 | // 若开启了字段标准,则不能为空。 | ||
| 241 | // 必须含有主键。若是聚合模型,则除了主键必须有聚合方式。 | ||
| 242 | let isSumModel = tableData.tableModel === 2; | ||
| 243 | let hasPrimary = false; | ||
| 244 | let enNames: any = []; | ||
| 245 | let chNames: any = []; | ||
| 246 | const regex = /^[a-zA-Z]/; | ||
| 247 | for (const field of tableFields) { | ||
| 248 | if (!field.enName) { | ||
| 249 | ElMessage.error(`第 ${field.orderNum} 个字段的英文名称不能为空`); | ||
| 250 | return; | ||
| 251 | } | ||
| 252 | if (!regex.test(field.enName)) { | ||
| 253 | ElMessage.error(`第 ${field.orderNum} 个字段的英文名称必须以英文字符开头`); | ||
| 254 | return; | ||
| 255 | } | ||
| 256 | if (!field.dataType) { | ||
| 257 | ElMessage.error(`第 ${field.orderNum} 个字段的字段类型不能为空`); | ||
| 258 | return; | ||
| 259 | } | ||
| 260 | if (enNames.indexOf(field.enName) > -1) { | ||
| 261 | ElMessage.error(`字段的英文名称 ${field.enName} 不能重复`); | ||
| 262 | return; | ||
| 263 | } | ||
| 264 | if (chNames.indexOf(field.chName) > -1) { | ||
| 265 | ElMessage.error(`字段的中文名称 ${field.chName} 不能重复`); | ||
| 266 | return; | ||
| 267 | } | ||
| 268 | if (field.dataType === "decimal" && (!field.fieldPrecision && field.fieldPrecision != 0)) { | ||
| 269 | ElMessage.error(`第 ${field.orderNum} 个字段的字段类型为浮点型时,精度不能为空`); | ||
| 270 | return; | ||
| 271 | } | ||
| 272 | if (field.dataType === "varchar" && (!field.fieldLength && field.fieldLength != 0)) { | ||
| 273 | ElMessage.error(`第 ${field.orderNum} 个字段的字段类型为字符型时,长度不能为空`); | ||
| 274 | return; | ||
| 275 | } | ||
| 276 | if (field.dataType === "char" && (!field.fieldLength && field.fieldLength != 0)) { | ||
| 277 | ElMessage.error(`第 ${field.orderNum} 个字段的字段类型为单字符型时,长度不能为空`); | ||
| 278 | return; | ||
| 279 | } | ||
| 280 | if (field.dataType === "decimal" && (!field.fieldLength && field.fieldLength != 0)) { | ||
| 281 | ElMessage.error(`第 ${field.orderNum} 个字段的字段类型为浮点符型时,长度不能为空`); | ||
| 282 | return; | ||
| 283 | } | ||
| 284 | if (field.isPrimary === 'Y') { | ||
| 285 | hasPrimary = true; | ||
| 286 | if (field.notNull != 'Y') { | ||
| 287 | ElMessage.error(`第 ${field.orderNum} 个字段为主键,应设置为必填`); | ||
| 288 | return; | ||
| 289 | } | ||
| 290 | if (field.dataType == 'text') { | ||
| 291 | ElMessage.error(`第 ${field.orderNum} 个字段为主键,字段类型不能设置为‘大字段型’`); | ||
| 292 | return; | ||
| 293 | } | ||
| 294 | if (field.dataType == 'json') { | ||
| 295 | ElMessage.error(`第 ${field.orderNum} 个字段为主键,字段类型不能设置为‘JSON类型’`); | ||
| 296 | return; | ||
| 297 | } | ||
| 298 | if (field.dataType == 'bit') { | ||
| 299 | ElMessage.error(`第 ${field.orderNum} 个字段为主键,字段类型不能设置为‘布尔类型’`); | ||
| 300 | return; | ||
| 301 | } | ||
| 302 | } else { | ||
| 303 | if (!field.aggWay && isSumModel) { | ||
| 304 | ElMessage.error(`聚合模型的非主键字段必须设置聚合方式`); | ||
| 305 | return; | ||
| 306 | } | ||
| 307 | } | ||
| 308 | if (field.isEdit) { | ||
| 309 | if (checkDefault[field.dataType]) { | ||
| 310 | if (!field.fieldLength) { } | ||
| 311 | if (!checkDefault[field.dataType]({ row: field })) { | ||
| 312 | return; | ||
| 313 | } | ||
| 314 | } | ||
| 315 | } | ||
| 316 | enNames.push(field.enName); | ||
| 317 | chNames.push(field.chName); | ||
| 318 | field.fieldStandardGuid = route.query.metaStandard; | ||
| 319 | } | ||
| 320 | if (!hasPrimary) { | ||
| 321 | ElMessage.error(`字段至少有一个主键字段!`); | ||
| 322 | return; | ||
| 323 | } | ||
| 324 | let addInfo = Object.assign({}, tableCreateInfo.value.tableData[0], { | ||
| 325 | enName: tableCreateInfo.value.inputNameValue, | ||
| 326 | tableCreateType: tableCreateInfo.value.tableCreateType, | ||
| 327 | saveFlag: 1, | ||
| 328 | dbType: dbType.value, | ||
| 329 | dataState: 1, | ||
| 330 | partitionAttribute: !Object.keys(tableCreateInfo.value.partitionAttribute).length ? null : Object.assign({}, tableCreateInfo.value.partitionAttribute, { | ||
| 331 | dynamicPartitionHistory: tableCreateInfo.value.partitionAttribute ? "Y" : 'N' | ||
| 332 | }), | ||
| 333 | subjectFieldAddDTOS: tableCreateInfo.value.tableFields.map((field, i) => { | ||
| 334 | return Object.assign({}, field, { orderNum: i + 1 }); | ||
| 335 | }), | ||
| 336 | }) | ||
| 337 | if (!tableCreateInfo.value.guid) { //添加 | ||
| 338 | fullscreenLoading.value = true; | ||
| 339 | saveSubjectTable(addInfo).then((res: any) => { | ||
| 340 | fullscreenLoading.value = false; | ||
| 341 | if (res.code == proxy.$passCode) { | ||
| 342 | ElMessage.success('新建表提交成功!'); | ||
| 343 | router.push({ | ||
| 344 | name: 'metadataStandardQuery' | ||
| 345 | }); | ||
| 346 | userStore.setTabbar(userStore.tabbar.filter((tab: any) => tab.fullPath !== fullPath)); | ||
| 347 | } else { | ||
| 348 | ElMessage.error(res.msg); | ||
| 349 | } | ||
| 350 | }).catch((err) => { | ||
| 351 | ElMessage.error(err); | ||
| 352 | fullscreenLoading.value = false; | ||
| 353 | }); | ||
| 354 | } | ||
| 355 | }; | ||
| 356 | |||
| 357 | //数据库选择改变,对应的表名称是否需要变化。需要根据此属性带出表名前缀,以及是否是doris数据库。 | ||
| 358 | const selectDatabaseChange = (val) => { | ||
| 359 | let oldDbType = dbType.value; | ||
| 360 | let d = databaseList.value.find(d => d.guid === val); | ||
| 361 | if (d) { | ||
| 362 | dbType.value = d.databaseType; | ||
| 363 | tableCreateInfo.value.tableData[0].dataSourceGuid = d.guid; | ||
| 364 | tableCreateInfo.value.tableData[0].dataServerName = d.databaseNameEn; | ||
| 365 | } else { | ||
| 366 | dbType.value = ""; | ||
| 367 | tableCreateInfo.value.tableData[0].dataSourceGuid = ''; | ||
| 368 | tableCreateInfo.value.tableData[0].dataServerName = ''; | ||
| 369 | } | ||
| 370 | if (oldDbType != dbType.value) { | ||
| 371 | tableCreateInfo.value.tableFields.forEach((tableField: any) => { | ||
| 372 | if (tableField['dataType'] === "datetime") { | ||
| 373 | tableField.defaultValue = "" | ||
| 374 | } | ||
| 375 | }) | ||
| 376 | } | ||
| 377 | }; | ||
| 378 | |||
| 379 | /** 添加字段标准 */ | ||
| 380 | const addField = () => { | ||
| 381 | let len = tableCreateInfo.value.tableFields.length; | ||
| 382 | tableCreateInfo.value.tableFields.push({ | ||
| 383 | orderNum: len + 1, | ||
| 384 | isDim: "N", | ||
| 385 | isPrimary: "N", | ||
| 386 | notNull: "N", | ||
| 387 | isEdit: true | ||
| 388 | }); | ||
| 389 | //设置选中表格当前新增行。 | ||
| 390 | fieldStandardTableRef.value?.setCurrentRow( | ||
| 391 | tableCreateInfo.value.tableFields[tableCreateInfo.value.tableFields.length - 1] | ||
| 392 | ); | ||
| 393 | nextTick(() => { | ||
| 394 | let bodyWrapper = fieldStandardTableRef.value?.$el.querySelector('.el-table__body'); | ||
| 395 | let domScroll = bodyWrapper.parentElement.parentElement; | ||
| 396 | let rect = domScroll.getBoundingClientRect(); | ||
| 397 | let maxNum = len + 1; | ||
| 398 | if (maxNum * 36 > rect.height + domScroll.scrollTop) { | ||
| 399 | fieldStandardTableRef.value?.setScrollTop(maxNum * 36 - rect.height + 2) | ||
| 400 | } | ||
| 401 | }) | ||
| 402 | }; | ||
| 403 | |||
| 404 | /** 勾选字段标准选中变化。 */ | ||
| 405 | const selectionFieldsChange = (val) => { | ||
| 406 | selectTableFieldRows.value = val; | ||
| 407 | }; | ||
| 408 | |||
| 409 | /** | ||
| 410 | * 上移规则: | ||
| 411 | * 勾选多个时先从最上面开始逐个上移一行,若已经移到最上面一行,则不处理。 | ||
| 412 | */ | ||
| 413 | const moveUp = () => { | ||
| 414 | let selectRows = fieldStandardTableRef.value?.getSelectionRows(); | ||
| 415 | if (!selectRows.length) { | ||
| 416 | ElMessage.error('请先选择需要勾选的数据进行上移'); | ||
| 417 | return; | ||
| 418 | } | ||
| 419 | let data = tableCreateInfo.value.tableFields; | ||
| 420 | let selectRowIndexs: number[] = []; | ||
| 421 | let minNum: number = 0; | ||
| 422 | selectRows.forEach((row, i) => { | ||
| 423 | let orderNum = data.findIndex(d => d === row) + 1; | ||
| 424 | if (orderNum == 1) { | ||
| 425 | selectRowIndexs.push(orderNum); | ||
| 426 | minNum = orderNum; | ||
| 427 | return; | ||
| 428 | } | ||
| 429 | if (selectRowIndexs.includes(orderNum - 1)) { | ||
| 430 | //下一行也是选中的,则不做转换。 | ||
| 431 | return; | ||
| 432 | } | ||
| 433 | let topNum = orderNum - 1; | ||
| 434 | if (i === 0) { | ||
| 435 | minNum = topNum; | ||
| 436 | } | ||
| 437 | row.orderNum = topNum; | ||
| 438 | let changeRow = data[topNum - 1]; | ||
| 439 | changeRow.orderNum = orderNum; | ||
| 440 | selectRowIndexs.push(topNum); | ||
| 441 | data[topNum] = changeRow; | ||
| 442 | data[topNum - 1] = row; | ||
| 443 | }); | ||
| 444 | nextTick().then(() => { | ||
| 445 | let bodyWrapper = fieldStandardTableRef.value?.$el.querySelector('.el-table__body'); | ||
| 446 | let domScroll = bodyWrapper.parentElement.parentElement; | ||
| 447 | if ((minNum * 36 - 36 - 2) < domScroll.scrollTop) { | ||
| 448 | fieldStandardTableRef.value?.setScrollTop((domScroll.scrollTop - 36 - 2) < 0 ? 0 : (domScroll.scrollTop - 36 - 2)) | ||
| 449 | } | ||
| 450 | }); | ||
| 451 | } | ||
| 452 | |||
| 453 | /** | ||
| 454 | * 下移规则: | ||
| 455 | * 勾选多个时先从最下面开始逐个下移一行,若已经移到最下面一行,则不处理。 | ||
| 456 | */ | ||
| 457 | const moveDown = () => { | ||
| 458 | let selectRows = fieldStandardTableRef.value?.getSelectionRows(); | ||
| 459 | if (!selectRows.length) { | ||
| 460 | ElMessage.error('请先选择需要勾选的数据进行下移'); | ||
| 461 | return; | ||
| 462 | } | ||
| 463 | let data = tableCreateInfo.value.tableFields; | ||
| 464 | let selectRowIndexs: number[] = []; | ||
| 465 | let maxNum: number = 0; | ||
| 466 | selectRows.slice(0).reverse().forEach((row, i) => { | ||
| 467 | let orderNum = data.findIndex(d => d === row) + 1; | ||
| 468 | if (orderNum === data.length) { | ||
| 469 | maxNum = orderNum; | ||
| 470 | selectRowIndexs.push(orderNum); | ||
| 471 | return; | ||
| 472 | } | ||
| 473 | if (selectRowIndexs.includes(orderNum + 1)) { | ||
| 474 | //下一行也是选中的,则不做转换。 | ||
| 475 | return; | ||
| 476 | } | ||
| 477 | let bottomNum = orderNum + 1; | ||
| 478 | row.orderNum = bottomNum; | ||
| 479 | if (i === 0) { | ||
| 480 | maxNum = bottomNum; | ||
| 481 | } | ||
| 482 | let changeRow = data[bottomNum - 1]; | ||
| 483 | changeRow.orderNum = orderNum; | ||
| 484 | selectRowIndexs.push(bottomNum); | ||
| 485 | data[orderNum - 1] = changeRow; | ||
| 486 | data[bottomNum - 1] = row; | ||
| 487 | }); | ||
| 488 | nextTick(() => { | ||
| 489 | let bodyWrapper = fieldStandardTableRef.value?.$el.querySelector('.el-table__body'); | ||
| 490 | let domScroll = bodyWrapper.parentElement.parentElement; | ||
| 491 | let rect = domScroll.getBoundingClientRect(); | ||
| 492 | if (maxNum * 36 > rect.height + domScroll.scrollTop) { | ||
| 493 | fieldStandardTableRef.value?.setScrollTop(maxNum * 36 - rect.height + 2) | ||
| 494 | } | ||
| 495 | }) | ||
| 496 | } | ||
| 497 | |||
| 498 | |||
| 499 | /** 批量删除字段标准 */ | ||
| 500 | const delFeilds = () => { | ||
| 501 | if (selectTableFieldRows.value.length == 0) { | ||
| 502 | ElMessage({ | ||
| 503 | type: "info", | ||
| 504 | message: "请选择需要删除的字段", | ||
| 505 | }); | ||
| 506 | return; | ||
| 507 | } | ||
| 508 | if (tableCreateInfo.value.isCreate) { | ||
| 509 | if (selectTableFieldRows.value.find((row: any) => row.isPrimary === 'Y')) { | ||
| 510 | ElMessage.error('已建表不能删除主键字段'); | ||
| 511 | return; | ||
| 512 | } | ||
| 513 | } | ||
| 514 | let hasCreateField = selectTableFieldRows.value.some((row: any) => row.isCreate === 'Y'); | ||
| 515 | ElMessageBox.confirm(hasCreateField && hasSubjectData.value ? '已选择的字段中含有已创建的表字段且有数据,此操作将永久删除,是否继续?' : "此操作将永久删除,是否继续?", "提示", { | ||
| 516 | confirmButtonText: "确定", | ||
| 517 | cancelButtonText: "取消", | ||
| 518 | type: "warning", | ||
| 519 | }) | ||
| 520 | .then(() => { | ||
| 521 | //此删除是直接从库里删除,还是点击保存后再删除呢??如果是入库删除,后,调用接口获取数据。 | ||
| 522 | let tableFields = tableCreateInfo.value.tableFields; | ||
| 523 | let tableData = tableCreateInfo.value.tableData[0]; | ||
| 524 | selectTableFieldRows.value.forEach((r: any) => { | ||
| 525 | let index = tableFields.findIndex((t: any) => t.orderNum === r.orderNum); | ||
| 526 | if (index !== -1) { | ||
| 527 | let row = tableFields[index]; | ||
| 528 | tableFields.splice(index, 1); | ||
| 529 | if (tableData.codeName == row.enName) { | ||
| 530 | tableData.codeName = ""; | ||
| 531 | } | ||
| 532 | if (tableData.codeColumn == row.enName) { | ||
| 533 | tableData.codeColumn = ""; | ||
| 534 | } | ||
| 535 | } | ||
| 536 | }); | ||
| 537 | fieldStandardTableRef.value?.clearSelection(); | ||
| 538 | tableCreateInfo.value.tableFields.forEach((field, i) => { | ||
| 539 | field.orderNum = i + 1; | ||
| 540 | }); | ||
| 541 | ElMessage({ | ||
| 542 | type: "success", | ||
| 543 | message: "删除成功", | ||
| 544 | }); | ||
| 545 | }) | ||
| 546 | .catch(() => { | ||
| 547 | ElMessage({ | ||
| 548 | type: "info", | ||
| 549 | message: "已取消删除", | ||
| 550 | }); | ||
| 551 | }); | ||
| 552 | }; | ||
| 553 | |||
| 554 | //点击编辑按钮 | ||
| 555 | const handleFieldClickEdit = (scope) => { | ||
| 556 | scope.row['isEdit'] = true; | ||
| 557 | }; | ||
| 558 | |||
| 559 | //点击保存按钮 | ||
| 560 | const handleFieldClickSave = (scope) => { | ||
| 561 | if (!scope.row.fieldStandardCode) { | ||
| 562 | ElMessage({ | ||
| 563 | type: "error", | ||
| 564 | message: "该主题域开启了字段标准,当前行字段标准不能为空!", | ||
| 565 | }); | ||
| 566 | return; | ||
| 567 | } | ||
| 568 | if (!scope.row.enName) { | ||
| 569 | ElMessage({ | ||
| 570 | type: "error", | ||
| 571 | message: "字段英文名不能为空!", | ||
| 572 | }); | ||
| 573 | return; | ||
| 574 | } | ||
| 575 | scope.row['isEdit'] = false; | ||
| 576 | }; | ||
| 577 | |||
| 578 | const handleFieldDelete = (scope) => { | ||
| 579 | ElMessageBox.confirm(scope.row['isCreate'] === 'Y' && hasSubjectData.value ? '该字段已被创建且表中有数据,此操作将永久删除,是否继续?' : "此操作将永久删除,是否继续?", "提示", { | ||
| 580 | confirmButtonText: "确定", | ||
| 581 | cancelButtonText: "取消", | ||
| 582 | type: "warning", | ||
| 583 | }) | ||
| 584 | .then(() => { | ||
| 585 | let tableFields = tableCreateInfo.value.tableFields; | ||
| 586 | tableFields.splice(scope.$index, 1); | ||
| 587 | tableCreateInfo.value.tableFields.forEach((field, i) => { | ||
| 588 | field.orderNum = i + 1; | ||
| 589 | }); | ||
| 590 | tableCreateInfo.value.tableFields.forEach((field, i) => { | ||
| 591 | field.orderNum = i + 1; | ||
| 592 | }); | ||
| 593 | let row = scope.row; | ||
| 594 | let tableData = tableCreateInfo.value.tableData[0]; | ||
| 595 | if (tableData.codeName == row.enName) { | ||
| 596 | tableData.codeName = ""; | ||
| 597 | } | ||
| 598 | if (tableData.codeColumn == row.enName) { | ||
| 599 | tableData.codeColumn = ""; | ||
| 600 | } | ||
| 601 | ElMessage({ | ||
| 602 | type: "success", | ||
| 603 | message: "删除成功", | ||
| 604 | }); | ||
| 605 | }) | ||
| 606 | .catch(() => { | ||
| 607 | ElMessage({ | ||
| 608 | type: "info", | ||
| 609 | message: "已取消删除", | ||
| 610 | }); | ||
| 611 | }); | ||
| 612 | } | ||
| 613 | |||
| 614 | const dataTypeChange = (val, scope) => { | ||
| 615 | scope.row['defaultValue'] = '' | ||
| 616 | scope.row['fieldLength'] = undefined | ||
| 617 | scope.row['fieldPrecision'] = undefined | ||
| 618 | } | ||
| 619 | |||
| 620 | /** 扩展属性弹出对话框 */ | ||
| 621 | const expandPropertyDialogRef = ref(); | ||
| 622 | |||
| 623 | /** 扩展属性弹出对话框 */ | ||
| 624 | const handleClickExpand = () => { | ||
| 625 | expandPropertyDialogRef.value?.handleClickExpand(); | ||
| 626 | } | ||
| 627 | |||
| 628 | const expandDialogValueChange = (val) => { | ||
| 629 | tableCreateInfo.value.partitionAttribute = val; | ||
| 630 | expandProperties.value = val; | ||
| 631 | } | ||
| 632 | |||
| 633 | const tableSelectFields = computed(() => { | ||
| 634 | return tableCreateInfo.value.tableFields.filter(t => !!t.enName); | ||
| 635 | }) | ||
| 636 | |||
| 637 | </script> | ||
| 638 | |||
| 639 | <template> | ||
| 640 | <div class="table_tool_wrap" v-loading.fullscreen.lock="fullscreenLoading"> | ||
| 641 | <div class="tools_btns"> | ||
| 642 | <!-- <el-button type="primary" :disabled="isLook" @click="saveDraftTable" v-preReClick>保存为草稿</el-button> --> | ||
| 643 | <el-button type="primary" :disabled="isLook" @click="saveTable" v-preReClick>提交</el-button> | ||
| 644 | </div> | ||
| 645 | <el-table ref="tableRef" :data="tableCreateInfo.tableData" v-loading="tableCreateInfoLoading" | ||
| 646 | :highlight-current-row="true" stripe border height="100%" tooltip-effect="light" row-key="guid" :style="{ | ||
| 647 | width: '100%', | ||
| 648 | height: 'auto', | ||
| 649 | display: 'inline-block', | ||
| 650 | }"> | ||
| 651 | <el-table-column prop="dataSourceGuid" label="数据源" width="200px" align="left" show-overflow-tooltip> | ||
| 652 | <template #header> | ||
| 653 | <span>数据源</span> | ||
| 654 | <span v-if="!isLook" style="color:red;margin-left: 2px;">*</span> | ||
| 655 | </template> | ||
| 656 | <template #default="scope"> | ||
| 657 | <el-select v-if="!isLook" v-model="scope.row['dataSourceGuid']" placeholder="请选择" | ||
| 658 | :disabled="tableCreateInfo.isCreate" @change="(val) => selectDatabaseChange(val)" clearable filterable> | ||
| 659 | <el-option v-for="opt in databaseList" :key="opt['guid']" :label="opt['databaseNameZh']" | ||
| 660 | :value="opt['guid']" /> | ||
| 661 | </el-select> | ||
| 662 | <span v-else>{{ scope.row["dataServerChName"] }}</span> | ||
| 663 | </template> | ||
| 664 | </el-table-column> | ||
| 665 | <el-table-column prop="enName" label="数据库表" width="200px" align="left" show-overflow-tooltip> | ||
| 666 | <template #header> | ||
| 667 | <span>数据库表</span> | ||
| 668 | <span v-if="!isLook" style="color:red;margin-left: 2px;">*</span> | ||
| 669 | </template> | ||
| 670 | <template #default="scope"> | ||
| 671 | <template v-if="!isLook"> | ||
| 672 | <div class="prefix-or-suffix-cell"> | ||
| 673 | <el-input :disabled="tableCreateInfo.isCreate" v-model.trim="tableCreateInfo.inputNameValue" | ||
| 674 | :maxlength="50" placeholder="必填" /> | ||
| 675 | </div> | ||
| 676 | </template> | ||
| 677 | <span v-else>{{ scope.row["enName"] }}</span> | ||
| 678 | </template> | ||
| 679 | </el-table-column> | ||
| 680 | <el-table-column prop="chName" label="主题表名称" width="200px" align="left" show-overflow-tooltip> | ||
| 681 | <template #header> | ||
| 682 | <span>主题表名称</span> | ||
| 683 | <span v-if="!isLook" style="color:red;margin-left: 2px;">*</span> | ||
| 684 | </template> | ||
| 685 | <template #default="scope"> | ||
| 686 | <el-input v-if="!isLook" v-model.trim="scope.row['chName']" placeholder="必填" :maxlength="50" /> | ||
| 687 | <span v-else>{{ scope.row["chName"] }}</span> | ||
| 688 | </template> | ||
| 689 | </el-table-column> | ||
| 690 | <el-table-column prop="subjectDomain" label="主题域" width="180px" align="left" show-overflow-tooltip> | ||
| 691 | <template #default="scope"> | ||
| 692 | <el-input v-if="!isLook" disabled v-model.trim="scope.row['subjectDomain']" /> | ||
| 693 | <span v-else>{{ scope.row["subjectDomain"] }}</span> | ||
| 694 | </template> | ||
| 695 | </el-table-column> | ||
| 696 | <el-table-column prop="tableModel" label="表模型" :width="isLook ? '100px' : '150px'" align="left" | ||
| 697 | show-overflow-tooltip> | ||
| 698 | <template #default="scope"> | ||
| 699 | <el-select v-if="dbType == 'doris' && !isLook" v-model="scope.row['tableModel']" placeholder="请选择" | ||
| 700 | :disabled="tableCreateInfo.isCreate"> | ||
| 701 | <el-option v-for="opt in tableModels" :key="opt['value']" :label="opt['label']" :value="opt['value']" /> | ||
| 702 | </el-select> | ||
| 703 | <span v-else-if="dbType == 'doris'">{{tableModels.find(t => t.value === scope.row["tableModel"])?.label || | ||
| 704 | '-' | ||
| 705 | }}</span> | ||
| 706 | <span v-else>--</span> | ||
| 707 | </template> | ||
| 708 | </el-table-column> | ||
| 709 | <el-table-column prop="dimType" label="维表类型" :width="isLook ? '100px' : '150px'" align="left" | ||
| 710 | show-overflow-tooltip> | ||
| 711 | <template #default="scope"> | ||
| 712 | <el-select v-if="!isLook" v-model="scope.row['dimType']" placeholder="请选择"> | ||
| 713 | <el-option v-for="opt in dimTypeList" :key="opt['value']" :label="opt['label']" :value="opt['value']" /> | ||
| 714 | </el-select> | ||
| 715 | <span v-else>{{dimTypeList.find(t => t.value === scope.row["dimType"])?.label || '-'}}</span> | ||
| 716 | </template> | ||
| 717 | </el-table-column> | ||
| 718 | <el-table-column prop="codeColumn" label="编码字段" :width="isLook ? '100px' : '150px'" align="left" | ||
| 719 | show-overflow-tooltip> | ||
| 720 | <template #header> | ||
| 721 | <div class="header_title"> | ||
| 722 | <span>编码字段</span> | ||
| 723 | <span v-if="!isLook" style="color:red;margin-left: 2px;margin-right: 8px;">*</span> | ||
| 724 | <el-tooltip placement="top" effect="light" popper-class="table_tooltip"> | ||
| 725 | <template #content> | ||
| 726 | <div style="max-width: 236px;"> | ||
| 727 | 下拉列表来自于该表的字段。 | ||
| 728 | </div> | ||
| 729 | </template> | ||
| 730 | <el-icon> | ||
| 731 | <QuestionFilled /> | ||
| 732 | </el-icon> | ||
| 733 | </el-tooltip> | ||
| 734 | </div> | ||
| 735 | </template> | ||
| 736 | <template #default="scope"> | ||
| 737 | <el-select v-if="!isLook" v-model="scope.row['codeColumn']" placeholder="请选择"> | ||
| 738 | <el-option v-for="opt in tableSelectFields" :key="opt['enName']" :label="opt['chName']" | ||
| 739 | :value="opt['enName']" /> | ||
| 740 | </el-select> | ||
| 741 | <span v-else>{{ scope.row["codeColumn"] || '-' }}</span> | ||
| 742 | </template> | ||
| 743 | </el-table-column> | ||
| 744 | <el-table-column prop="codeName" label="编码名称" :width="isLook ? '100px' : '150px'" align="left" | ||
| 745 | show-overflow-tooltip> | ||
| 746 | <template #header> | ||
| 747 | <div class="header_title"> | ||
| 748 | <span>编码名称</span> | ||
| 749 | <span v-if="!isLook" style="color:red;margin-left: 2px;margin-right: 8px;">*</span> | ||
| 750 | <el-tooltip placement="top" effect="light" popper-class="table_tooltip"> | ||
| 751 | <template #content> | ||
| 752 | <div style="max-width: 236px;"> | ||
| 753 | 下拉列表来自于该表的字段。 | ||
| 754 | </div> | ||
| 755 | </template> | ||
| 756 | <el-icon> | ||
| 757 | <QuestionFilled /> | ||
| 758 | </el-icon> | ||
| 759 | </el-tooltip> | ||
| 760 | </div> | ||
| 761 | </template> | ||
| 762 | <template #default="scope"> | ||
| 763 | <el-select v-if="!isLook" v-model="scope.row['codeName']" placeholder="请选择"> | ||
| 764 | <el-option v-for="opt in tableSelectFields" :key="opt['enName']" :label="opt['chName']" | ||
| 765 | :value="opt['enName']" /> | ||
| 766 | </el-select> | ||
| 767 | <span v-else>{{ scope.row["codeName"] || '-' }}</span> | ||
| 768 | </template> | ||
| 769 | </el-table-column> | ||
| 770 | <el-table-column prop="syncPolicy" label="同步策略" :width="isLook ? '100px' : '150px'" align="left" | ||
| 771 | show-overflow-tooltip> | ||
| 772 | <template #default="scope"> | ||
| 773 | <el-select v-if="!isLook" v-model="scope.row['syncPolicy']" placeholder="请选择"> | ||
| 774 | <el-option v-for="opt in syncPolicys" :key="opt['value']" :label="opt['label']" :value="opt['value']" /> | ||
| 775 | </el-select> | ||
| 776 | <span v-else>{{syncPolicys.find(s => s.value === scope.row["syncPolicy"])?.label || '-'}}</span> | ||
| 777 | </template> | ||
| 778 | </el-table-column> | ||
| 779 | <el-table-column prop="characterSet" label="字符集" :width="isLook ? '100px' : '150px'" align="left" | ||
| 780 | show-overflow-tooltip> | ||
| 781 | <template #default="scope"> | ||
| 782 | <el-select v-if="!isLook" v-model="scope.row['characterSet']" placeholder="请选择"> | ||
| 783 | <el-option v-for="opt in characterList" :key="opt['value']" :label="opt['label']" :value="opt['value']" /> | ||
| 784 | </el-select> | ||
| 785 | <span v-else>{{characterList.find(c => c.value === scope.row["characterSet"])?.label || '-' | ||
| 786 | }}</span> | ||
| 787 | </template> | ||
| 788 | </el-table-column> | ||
| 789 | <el-table-column prop="description" label="描述" width="220px" align="left" show-overflow-tooltip> | ||
| 790 | <template #default="scope"> | ||
| 791 | <el-input v-if="!isLook" v-model.trim="scope.row['description']" /> | ||
| 792 | <span v-else>{{ scope.row["description"] || '-' }}</span> | ||
| 793 | </template> | ||
| 794 | </el-table-column> | ||
| 795 | <el-table-column label="操作" width="100px" align="left" fixed="right" show-overflow-tooltip> | ||
| 796 | <template #default="scope"> | ||
| 797 | <span class="text_btn" @click="handleClickExpand()" v-preReClick>扩展属性</span> | ||
| 798 | </template> | ||
| 799 | </el-table-column> | ||
| 800 | </el-table> | ||
| 801 | <div class="tools_btns"> | ||
| 802 | <el-button type="primary" :disabled="isLook" @click="addField">新增</el-button> | ||
| 803 | <el-button @click="moveUp" :disabled="isLook">上移</el-button> | ||
| 804 | <el-button @click="moveDown" :disabled="isLook">下移</el-button> | ||
| 805 | <el-button @click="delFeilds" :disabled="isLook">批量删除</el-button> | ||
| 806 | </div> | ||
| 807 | <div class="table_panel"> | ||
| 808 | <el-table ref="fieldStandardTableRef" :data="tableCreateInfo.tableFields" v-loading="tableFieldsLoading" | ||
| 809 | :highlight-current-row="true" stripe border height="100%" row-key="guid" | ||
| 810 | @selection-change="selectionFieldsChange" tooltip-effect="light" :style="{ | ||
| 811 | width: '100%', | ||
| 812 | 'max-height': 'calc(100% - 16px)', | ||
| 813 | display: 'inline-block', | ||
| 814 | }"> | ||
| 815 | <el-table-column type="selection" v-if="!isLook" :width="32" align="center" /> | ||
| 816 | <el-table-column label="排序" type="index" width="56px" align="center" show-overflow-tooltip> | ||
| 817 | </el-table-column> | ||
| 818 | <el-table-column prop="chName" label="字段中文名称" width="150px" align="left" show-overflow-tooltip> | ||
| 819 | <template #default="scope"> | ||
| 820 | <el-input v-if="scope.row['isEdit']" placeholder="请输入" v-model.trim="scope.row['chName']" /> | ||
| 821 | <span v-else>{{ scope.row["chName"] || '-' }}</span> | ||
| 822 | </template> | ||
| 823 | </el-table-column> | ||
| 824 | <el-table-column prop="enName" label="字段英文名" width="150px" align="left" show-overflow-tooltip> | ||
| 825 | <template #default="scope"> | ||
| 826 | <el-input v-if="scope.row['isEdit'] && !(scope.row['guid'] && tableCreateInfo.isCreate)" | ||
| 827 | v-model.trim="scope.row['enName']" placeholder="必填" | ||
| 828 | @input="inputLengthKeyUp(/[^a-zA-Z0-9_]/g, scope, 'enName')" /> | ||
| 829 | <span v-else>{{ scope.row["enName"] || '-' }}</span> | ||
| 830 | </template> | ||
| 831 | </el-table-column> | ||
| 832 | <el-table-column prop="dataType" label="字段类型" width="120px" align="left" show-overflow-tooltip> | ||
| 833 | <template #default="scope"> | ||
| 834 | <el-select v-if="scope.row['isEdit'] && !(tableCreateInfo.isCreate && scope.row['isCreate'] === 'Y')" | ||
| 835 | v-model="scope.row['dataType']" placeholder="请选择" @change="(val) => dataTypeChange(val, scope)"> | ||
| 836 | <el-option v-for="opt in fieldTypes" :key="opt['value']" :label="opt['label']" :value="opt['value']" /> | ||
| 837 | </el-select> | ||
| 838 | <span v-else>{{fieldTypes.find(f => f.value === scope.row["dataType"])?.label || '-'}}</span> | ||
| 839 | </template> | ||
| 840 | </el-table-column> | ||
| 841 | <el-table-column prop="fieldLength" label="长度" width="115px" align="left" show-overflow-tooltip> | ||
| 842 | <template #default="scope"> | ||
| 843 | <el-input | ||
| 844 | v-if="scope.row['isEdit'] && !(tableCreateInfo.isCreate && scope.row['isCreate'] === 'Y') && (scope.row['dataType'] == 'varchar' || scope.row['dataType'] == 'decimal' || scope.row['dataType'] == 'char')" | ||
| 845 | v-model.trim="scope.row['fieldLength']" placeholder="必填" | ||
| 846 | @input="inputLengthKeyUp(/\D/g, scope, 'fieldLength', 2000, 1)" /> | ||
| 847 | <span v-else>{{ scope.row["fieldLength"] == null ? '-' : scope.row["fieldLength"] }}</span> | ||
| 848 | </template> | ||
| 849 | </el-table-column> | ||
| 850 | <el-table-column prop="fieldPrecision" label="精度" width="115px" align="left" show-overflow-tooltip> | ||
| 851 | <template #default="scope"> | ||
| 852 | <el-input | ||
| 853 | v-if="scope.row['isEdit'] && !(tableCreateInfo.isCreate && scope.row['isCreate'] === 'Y') && scope.row['dataType'] == 'decimal'" | ||
| 854 | v-model.trim="scope.row['fieldPrecision']" placeholder="必填" | ||
| 855 | @input="inputLengthKeyUp(/\D/g, scope, 'fieldPrecision', 30, 1)" /> | ||
| 856 | <span v-else>{{ scope.row["fieldPrecision"] == null ? '-' : scope.row["fieldPrecision"] }}</span> | ||
| 857 | </template> | ||
| 858 | </el-table-column> | ||
| 859 | <el-table-column prop="isPrimary" label="是否主键" width="90px" align="left" show-overflow-tooltip> | ||
| 860 | <template #default="scope"> | ||
| 861 | <el-select v-if="scope.row['isEdit'] && !tableCreateInfo.isCreate" v-model="scope.row['isPrimary']" | ||
| 862 | placeholder="请选择"> | ||
| 863 | <el-option v-for="opt in isNotList" :key="opt['value']" :label="opt['label']" :value="opt['value']" /> | ||
| 864 | </el-select> | ||
| 865 | <span v-else>{{ scope.row["isPrimary"] || '-' }}</span> | ||
| 866 | </template> | ||
| 867 | </el-table-column> | ||
| 868 | <el-table-column v-if="tableCreateInfo.tableData[0].tableModel == 2" prop="aggWay" label="聚合方式" width="120px" | ||
| 869 | align="left" show-overflow-tooltip> | ||
| 870 | <template #default="scope"> | ||
| 871 | <el-select v-if="scope.row['isEdit']" v-model="scope.row['aggWay']" placeholder="请选择"> | ||
| 872 | <el-option v-for="opt in aggMethodList" :key="opt['value']" :label="opt['label']" :value="opt['value']" /> | ||
| 873 | </el-select> | ||
| 874 | <span v-else>{{ scope.row["aggWay"] || '-' }}</span> | ||
| 875 | </template> | ||
| 876 | </el-table-column> | ||
| 877 | <el-table-column prop="notNull" label="是否必填" width="90px" align="left" show-overflow-tooltip> | ||
| 878 | <template #default="scope"> | ||
| 879 | <el-select v-if="scope.row['isEdit'] && !(scope.row.isCreate == 'Y' && scope.row['notNull'] == 'N')" | ||
| 880 | v-model="scope.row['notNull']" placeholder="请选择"> | ||
| 881 | <el-option v-for="opt in isNotList" :key="opt['value']" :label="opt['label']" :value="opt['value']" /> | ||
| 882 | </el-select> | ||
| 883 | <span v-else>{{ scope.row["notNull"] || '-' }}</span> | ||
| 884 | </template> | ||
| 885 | </el-table-column> | ||
| 886 | <el-table-column prop="defaultValue" label="默认值" width="205px" align="left" show-overflow-tooltip> | ||
| 887 | <template #default="scope"> | ||
| 888 | <tableDefaultValue :scope="scope" :dbType="dbType" | ||
| 889 | :readonly="dbType == 'doris' && scope.row.isCreate == 'Y'"></tableDefaultValue> | ||
| 890 | </template> | ||
| 891 | </el-table-column> | ||
| 892 | <el-table-column v-if="!isLook" label="操作" width="100px" align="left" fixed="right" show-overflow-tooltip> | ||
| 893 | <template #default="scope"> | ||
| 894 | <template v-if="!(tableCreateInfo.isCreate && scope.row['isPrimary'] === 'Y')"> | ||
| 895 | <span class="text_btn" v-if="!scope.row['isEdit']" @click="handleFieldClickEdit(scope)" | ||
| 896 | v-preReClick>编辑</span> | ||
| 897 | <span class="text_btn" v-else @click="handleFieldClickSave(scope)" v-preReClick>保存</span> | ||
| 898 | <el-divider direction="vertical" /> | ||
| 899 | <span class="text_btn" @click="handleFieldDelete(scope)">删除</span> | ||
| 900 | </template> | ||
| 901 | <span v-else>--</span> | ||
| 902 | </template> | ||
| 903 | </el-table-column> | ||
| 904 | </el-table> | ||
| 905 | </div> | ||
| 906 | <ContentWrap title="流程审批" description="" :isExpand="flowExpand" :expand-swicth="true" class="mb16" | ||
| 907 | @expand="(v) => flowExpand = v"> | ||
| 908 | <ApprovalProcess v-if="deploymentId" :deploymentId="deploymentId" :definitionId="''"> | ||
| 909 | </ApprovalProcess> | ||
| 910 | </ContentWrap> | ||
| 911 | <expandPropertyDialog ref="expandPropertyDialogRef" :is-look="isLook" :partitionAttribute="expandProperties" | ||
| 912 | :table-create-info="tableCreateInfo" @expandValueChange="expandDialogValueChange" /> | ||
| 913 | </div> | ||
| 914 | </template> | ||
| 915 | |||
| 916 | <style lang="scss" scoped> | ||
| 917 | .table_tool_wrap { | ||
| 918 | width: 100%; | ||
| 919 | height: 100%; | ||
| 920 | padding: 0 16px; | ||
| 921 | overflow: hidden auto; | ||
| 922 | |||
| 923 | .tools_btns { | ||
| 924 | padding: 8px 0; | ||
| 925 | } | ||
| 926 | |||
| 927 | :deep(.el-table) { | ||
| 928 | .cell { | ||
| 929 | |||
| 930 | .prefix-or-suffix-cell { | ||
| 931 | display: inline-flex; | ||
| 932 | align-items: center; | ||
| 933 | } | ||
| 934 | } | ||
| 935 | } | ||
| 936 | |||
| 937 | .table_panel { | ||
| 938 | height: 268px; | ||
| 939 | |||
| 940 | :deep(.el-table) { | ||
| 941 | & td.el-table__cell { | ||
| 942 | padding: 2px 0; | ||
| 943 | height: 36px; | ||
| 944 | } | ||
| 945 | } | ||
| 946 | } | ||
| 947 | } | ||
| 948 | |||
| 949 | :deep(.el-dialog) { | ||
| 950 | .dialog-form-inline { | ||
| 951 | .checkbox_input { | ||
| 952 | display: flex; | ||
| 953 | flex-direction: column; | ||
| 954 | |||
| 955 | .input_panel { | ||
| 956 | margin: 0; | ||
| 957 | } | ||
| 958 | } | ||
| 959 | |||
| 960 | .select_group { | ||
| 961 | .el-form-item__content>.el-input { | ||
| 962 | margin-top: 21px; | ||
| 963 | } | ||
| 964 | } | ||
| 965 | |||
| 966 | .radio_panel { | ||
| 967 | .panel_content { | ||
| 968 | display: none; | ||
| 969 | } | ||
| 970 | } | ||
| 971 | } | ||
| 972 | } | ||
| 973 | |||
| 974 | :deep(.batchDialog) { | ||
| 975 | .el-tree-node__content { | ||
| 976 | padding-left: 8px !important; | ||
| 977 | |||
| 978 | .el-icon { | ||
| 979 | display: none; | ||
| 980 | } | ||
| 981 | } | ||
| 982 | } | ||
| 983 | |||
| 984 | .header_title { | ||
| 985 | margin-left: 8px; | ||
| 986 | display: flex; | ||
| 987 | align-items: center; | ||
| 988 | |||
| 989 | .el-icon { | ||
| 990 | color: #b2b2b2; | ||
| 991 | width: 16px; | ||
| 992 | height: 16px; | ||
| 993 | } | ||
| 994 | } | ||
| 995 | </style> | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| ... | @@ -228,14 +228,7 @@ onBeforeUnmount(() => { | ... | @@ -228,14 +228,7 @@ onBeforeUnmount(() => { |
| 228 | }) | 228 | }) |
| 229 | 229 | ||
| 230 | /** 数仓目录树形列表 */ | 230 | /** 数仓目录树形列表 */ |
| 231 | const dataCatalogList = ref([{ | 231 | const dataCatalogList = ref([]); |
| 232 | name: '测试', | ||
| 233 | guid: '1', | ||
| 234 | children: [{ | ||
| 235 | name: 'cesi', | ||
| 236 | guid: '1-1' | ||
| 237 | }] | ||
| 238 | }]); | ||
| 239 | 232 | ||
| 240 | const formItems = ref([{ | 233 | const formItems = ref([{ |
| 241 | label: "数仓目录", | 234 | label: "数仓目录", |
| ... | @@ -299,12 +292,37 @@ const dialogBtnClick = (btn, info) => { | ... | @@ -299,12 +292,37 @@ const dialogBtnClick = (btn, info) => { |
| 299 | if (btn.value == 'submit') { | 292 | if (btn.value == 'submit') { |
| 300 | dialogInfo.value.visible = false; | 293 | dialogInfo.value.visible = false; |
| 301 | if (selectDataCatalogNodeObj.value.parent.data.layereAttribute == 2) { //维度 | 294 | if (selectDataCatalogNodeObj.value.parent.data.layereAttribute == 2) { //维度 |
| 302 | window.open(`${import.meta.env.VITE_APP_DATA_DELIVERY}data-catalog/data-warehouse/dim-table-create-manual?domainGuid=${info.domainGuid}&domainName=${selectDataCatalogNodeObj.value.data.name}&metaStandard=${contextNodeData.value.guid}`); | 295 | router.push({ |
| 296 | name: 'dimTableCreateManual', | ||
| 297 | query: { | ||
| 298 | domainGuid: info.domainGuid, | ||
| 299 | domainName: selectDataCatalogNodeObj.value.data.name, | ||
| 300 | metaStandard: contextNodeData.value.guid, | ||
| 301 | standardName: contextNodeData.value.label | ||
| 302 | } | ||
| 303 | }); | ||
| 303 | } else { | 304 | } else { |
| 304 | if (selectDataCatalogNodeObj.value.parent.data.layereAttribute == 4) { | 305 | if (selectDataCatalogNodeObj.value.parent.data.layereAttribute == 4) { |
| 305 | window.open(`${import.meta.env.VITE_APP_DATA_DELIVERY}data-catalog/data-warehouse/table-create-manual?domainGuid=${info.domainGuid}&domainName=${selectDataCatalogNodeObj.value.data.name}&layereAttribute=${selectDataCatalogNodeObj.value.parent.data.layereAttribute}&metaStandard=${contextNodeData.value.guid}`); | 306 | router.push({ |
| 307 | name: 'tableCreateManual', | ||
| 308 | query: { | ||
| 309 | domainGuid: info.domainGuid, | ||
| 310 | domainName: selectDataCatalogNodeObj.value.data.name, | ||
| 311 | metaStandard: contextNodeData.value.guid, | ||
| 312 | layereAttribute: selectDataCatalogNodeObj.value.parent.data.layereAttribute, | ||
| 313 | standardName: contextNodeData.value.label | ||
| 314 | } | ||
| 315 | }); | ||
| 306 | } else { | 316 | } else { |
| 307 | window.open(`${import.meta.env.VITE_APP_DATA_DELIVERY}data-catalog/data-warehouse/table-create-manual?domainGuid=${info.domainGuid}&domainName=${selectDataCatalogNodeObj.value.data.name}&metaStandard=${contextNodeData.value.guid}`); | 317 | router.push({ |
| 318 | name: 'tableCreateManual', | ||
| 319 | query: { | ||
| 320 | domainGuid: info.domainGuid, | ||
| 321 | domainName: selectDataCatalogNodeObj.value.data.name, | ||
| 322 | metaStandard: contextNodeData.value.guid, | ||
| 323 | standardName: contextNodeData.value.label | ||
| 324 | } | ||
| 325 | }); | ||
| 308 | } | 326 | } |
| 309 | } | 327 | } |
| 310 | } else if (btn.value == 'cancel') { | 328 | } else if (btn.value == 'cancel') { | ... | ... |
src/views/data_meta/tableCreateManual.vue
0 → 100644
| 1 | <route lang="yaml"> | ||
| 2 | name: tableCreateManual | ||
| 3 | </route> | ||
| 4 | |||
| 5 | <script lang="ts" setup name="tableCreateManual"> | ||
| 6 | import { ref } from "vue"; | ||
| 7 | import { useRouter, useRoute } from "vue-router"; | ||
| 8 | import { ElMessage, ElMessageBox, ElTable } from "element-plus"; | ||
| 9 | import { QuestionFilled } from "@element-plus/icons-vue"; | ||
| 10 | import { | ||
| 11 | getDatabase, | ||
| 12 | saveSubjectTable, | ||
| 13 | syncPolicys, | ||
| 14 | tableModels, | ||
| 15 | tableCategoryList, | ||
| 16 | getDimList, | ||
| 17 | getDictionary, | ||
| 18 | aggMethodList, | ||
| 19 | getMetaStandardDsField, | ||
| 20 | getAllFlowData | ||
| 21 | } from "@/api/modules/dataMetaService"; | ||
| 22 | import useUserStore from "@/store/modules/user"; | ||
| 23 | import expandPropertyDialog from "./components/expandPropertyDialog.vue"; | ||
| 24 | import tableDefaultValue from "./components/tableDefaultValue.vue"; | ||
| 25 | import { useDefault } from "@/hooks/useDefault" | ||
| 26 | import { getCamundaDeploymentId } from "@/api/modules/workFlowService" | ||
| 27 | |||
| 28 | const userStore = useUserStore(); | ||
| 29 | const { checkDefault } = useDefault() | ||
| 30 | const router = useRouter(); | ||
| 31 | const route = useRoute(); | ||
| 32 | const flowExpand = ref(true); | ||
| 33 | const deploymentId = ref(''); | ||
| 34 | const fullPath = route.fullPath; | ||
| 35 | const isLook = <any>route.query.isLook == 1; | ||
| 36 | const subjectDomainGuid: any = ref(route.query.domainGuid); | ||
| 37 | const { proxy } = getCurrentInstance() as any; | ||
| 38 | const fieldStandardTableRef = ref<InstanceType<typeof ElTable>>(); | ||
| 39 | |||
| 40 | /** 表模型,只有doris数据库才有 */ | ||
| 41 | const dbType = ref(""); | ||
| 42 | |||
| 43 | const databaseList: any = ref([]); | ||
| 44 | |||
| 45 | const tableFieldsLoading = ref(false); | ||
| 46 | |||
| 47 | const tableCreateInfoLoading = ref(false); | ||
| 48 | |||
| 49 | //记录当前正在编辑的表创建信息。 | ||
| 50 | const tableCreateInfo: Ref<any> = ref({ | ||
| 51 | guid: "", | ||
| 52 | isCreate: false, | ||
| 53 | inputNameValue: '', | ||
| 54 | tableCreateType: 1, | ||
| 55 | tableData: [ | ||
| 56 | { | ||
| 57 | //数据库表信息。 | ||
| 58 | dataSourceGuid: '', | ||
| 59 | dataServerName: "", | ||
| 60 | dataServerChName: "", | ||
| 61 | enName: "", | ||
| 62 | chName: "", | ||
| 63 | subjectDomain: route.query.domainName, | ||
| 64 | subjectDomainGuid: subjectDomainGuid.value, | ||
| 65 | tableCategory: route.query.layereAttribute == '3' ? 6 : 1, | ||
| 66 | syncPolicy: 3, | ||
| 67 | characterSet: 'utf8mb3', | ||
| 68 | tableModel: 1, //若是聚合模型,下方出现一列聚合方式选择。处了主键列,其余列都需要选择。每个表里都要有主键。 | ||
| 69 | description: "", | ||
| 70 | }, | ||
| 71 | ], | ||
| 72 | partitionAttribute: {}, | ||
| 73 | tableFields: [], // 字段标准数组。 | ||
| 74 | }); | ||
| 75 | |||
| 76 | const selectTableFieldRows = ref([]); | ||
| 77 | |||
| 78 | //字段类型 | ||
| 79 | const fieldTypes: any = ref([]); | ||
| 80 | |||
| 81 | //字符集 | ||
| 82 | const characterList: any = ref([]); | ||
| 83 | |||
| 84 | //是否列表 | ||
| 85 | const isNotList = ref([ | ||
| 86 | { | ||
| 87 | label: "Y", | ||
| 88 | value: "Y", | ||
| 89 | }, | ||
| 90 | { | ||
| 91 | label: "N", | ||
| 92 | value: "N", | ||
| 93 | }, | ||
| 94 | ]); | ||
| 95 | |||
| 96 | //字典列表 | ||
| 97 | const dictionaryList: any = ref([]); | ||
| 98 | |||
| 99 | // 可选择的关联维度的列表。 | ||
| 100 | const dimListData: any = ref([]); | ||
| 101 | |||
| 102 | const fullscreenLoading = ref(false); | ||
| 103 | |||
| 104 | /** 表里有数据时不能修改字段类型,长度,精度 */ | ||
| 105 | const hasSubjectData = ref(false); | ||
| 106 | |||
| 107 | const expandProperties = ref({}); | ||
| 108 | |||
| 109 | onBeforeMount(() => { | ||
| 110 | getDatabaseList(); | ||
| 111 | getFieldTypeList(); | ||
| 112 | getCharacterListData(); | ||
| 113 | if (route.query.metaStandard) { | ||
| 114 | tableCreateInfo.value.tableData[0].chName = route.query.standardName; | ||
| 115 | tableCreateInfoLoading.value = true; | ||
| 116 | getMetaStandardDsField(route.query.metaStandard).then((res: any) => { | ||
| 117 | tableCreateInfoLoading.value = false; | ||
| 118 | if (res.code == proxy.$passCode) { | ||
| 119 | tableCreateInfo.value.tableFields = res.data?.map((d, i) => { | ||
| 120 | d.orderNum = i; | ||
| 121 | d.isEdit = true; | ||
| 122 | return d; | ||
| 123 | }) || []; | ||
| 124 | } else { | ||
| 125 | proxy.$ElMessage.error(res.msg); | ||
| 126 | } | ||
| 127 | }) | ||
| 128 | } | ||
| 129 | getCamundaDeploymentId('10025').then((res: any) => { | ||
| 130 | if (res.code == proxy.$passCode) { | ||
| 131 | deploymentId.value = res.data; | ||
| 132 | } else { | ||
| 133 | proxy.$ElMessage.error(res.msg); | ||
| 134 | } | ||
| 135 | }) | ||
| 136 | }) | ||
| 137 | |||
| 138 | onActivated(() => { | ||
| 139 | console.log("activated"); | ||
| 140 | getDictionaryList(); | ||
| 141 | getDimListData(); | ||
| 142 | }); | ||
| 143 | |||
| 144 | |||
| 145 | const getDatabaseList = () => { | ||
| 146 | getDatabase({ connectStatus: 1 }).then((res: any) => { | ||
| 147 | databaseList.value = []; | ||
| 148 | if (res.code == proxy.$passCode) { | ||
| 149 | databaseList.value = res.data || []; | ||
| 150 | } else { | ||
| 151 | ElMessage.error(res.msg); | ||
| 152 | } | ||
| 153 | }) | ||
| 154 | }; | ||
| 155 | |||
| 156 | const getDictionaryList = () => { | ||
| 157 | getDictionary({}).then((res: any) => { | ||
| 158 | dictionaryList.value = []; | ||
| 159 | if (res.code == proxy.$passCode) { | ||
| 160 | dictionaryList.value = res.data || []; | ||
| 161 | dimOrDictList.value[0].children = dictionaryList.value; | ||
| 162 | dimOrDictList.value[0].disabled = !dictionaryList.value.length; | ||
| 163 | } else { | ||
| 164 | ElMessage.error(res.msg); | ||
| 165 | } | ||
| 166 | }) | ||
| 167 | }; | ||
| 168 | |||
| 169 | const getDimListData = () => { | ||
| 170 | getDimList().then((res: any) => { | ||
| 171 | dimListData.value = []; | ||
| 172 | if (res.code == proxy.$passCode) { | ||
| 173 | dimListData.value = res.data?.map(r => { | ||
| 174 | return { | ||
| 175 | guid: r.guid, | ||
| 176 | chName: r.chName, | ||
| 177 | subjectDomainName: r.subjectDomainName, | ||
| 178 | parentGuid: '2' | ||
| 179 | } | ||
| 180 | }) || []; | ||
| 181 | dimOrDictList.value[1].children = dimListData.value; | ||
| 182 | dimOrDictList.value[1].disabled = !dimListData.value.length; | ||
| 183 | } else { | ||
| 184 | ElMessage.error(res.msg); | ||
| 185 | } | ||
| 186 | }) | ||
| 187 | }; | ||
| 188 | |||
| 189 | const getFieldTypeList = () => { | ||
| 190 | getAllFlowData('字段类型').then((res: any) => { | ||
| 191 | fieldTypes.value = []; | ||
| 192 | if (res.code == proxy.$passCode) { | ||
| 193 | fieldTypes.value = res.data || []; | ||
| 194 | } else { | ||
| 195 | ElMessage.error(res.msg); | ||
| 196 | } | ||
| 197 | }) | ||
| 198 | } | ||
| 199 | |||
| 200 | const getCharacterListData = () => { | ||
| 201 | getAllFlowData('Mysql字符集').then((res: any) => { | ||
| 202 | characterList.value = []; | ||
| 203 | if (res.code == proxy.$passCode) { | ||
| 204 | characterList.value = res.data || []; | ||
| 205 | } else { | ||
| 206 | ElMessage.error(res.msg); | ||
| 207 | } | ||
| 208 | }) | ||
| 209 | } | ||
| 210 | |||
| 211 | /** 限制长度输入框只能输入整型数字,表,字段英文名称,限制输入字符,数字和下划线。 */ | ||
| 212 | const inputLengthKeyUp = (regexp, scope, field, max: any = null, min: any = null) => { | ||
| 213 | scope.row[field] = scope.row[field].replace(regexp, ''); | ||
| 214 | if (field == 'fieldLength' && scope.row.dataType == 'decimal') { | ||
| 215 | max = 65; | ||
| 216 | } | ||
| 217 | /** 最大值设置2000 */ | ||
| 218 | if (max && scope.row[field] > max) { | ||
| 219 | scope.row[field] = max; | ||
| 220 | } | ||
| 221 | if (min !== null && scope.row[field] != '' && scope.row[field] <= min) { | ||
| 222 | scope.row[field] = min; | ||
| 223 | } | ||
| 224 | } | ||
| 225 | |||
| 226 | /** 保存表 */ | ||
| 227 | const saveTable = () => { | ||
| 228 | let tableData = tableCreateInfo.value.tableData[0]; | ||
| 229 | if (!tableData.chName) { | ||
| 230 | ElMessage({ | ||
| 231 | type: "error", | ||
| 232 | message: "主题表名称不能为空", | ||
| 233 | }); | ||
| 234 | return; | ||
| 235 | } | ||
| 236 | if (!tableData.dataServerName) { | ||
| 237 | ElMessage({ | ||
| 238 | type: "error", | ||
| 239 | message: "数据源不能为空", | ||
| 240 | }); | ||
| 241 | return; | ||
| 242 | } | ||
| 243 | if (tableData.dataServerName.indexOf('-') > -1) { | ||
| 244 | ElMessage.error('数据库表名称不能包含中划线,可以改为下划线'); | ||
| 245 | return; | ||
| 246 | } | ||
| 247 | if (!tableCreateInfo.value.inputNameValue) { | ||
| 248 | ElMessage({ | ||
| 249 | type: "error", | ||
| 250 | message: "主题表名称不能为空", | ||
| 251 | }); | ||
| 252 | return; | ||
| 253 | } | ||
| 254 | let tableFields = tableCreateInfo.value.tableFields; | ||
| 255 | if (!tableFields.length) { | ||
| 256 | ElMessage({ | ||
| 257 | type: "error", | ||
| 258 | message: "表字段不能为0行", | ||
| 259 | }); | ||
| 260 | return; | ||
| 261 | } | ||
| 262 | // 若开启了字段标准,则不能为空。 | ||
| 263 | // 必须含有主键。若是聚合模型,则除了主键必须有聚合方式。 | ||
| 264 | let isSumModel = tableData.tableModel === 2; | ||
| 265 | let hasPrimary = false; | ||
| 266 | let enNames: any = []; | ||
| 267 | let chNames: any = []; | ||
| 268 | const regex = /^[a-zA-Z]/; | ||
| 269 | for (const field of tableFields) { | ||
| 270 | if (!field.enName) { | ||
| 271 | ElMessage.error(`第 ${field.orderNum} 个字段的英文名称不能为空`); | ||
| 272 | return; | ||
| 273 | } | ||
| 274 | if (!regex.test(field.enName)) { | ||
| 275 | ElMessage.error(`第 ${field.orderNum} 个字段的英文名称必须以英文字符开头`); | ||
| 276 | return; | ||
| 277 | } | ||
| 278 | if (!field.dataType) { | ||
| 279 | ElMessage.error(`第 ${field.orderNum} 个字段的字段类型不能为空`); | ||
| 280 | return; | ||
| 281 | } | ||
| 282 | if (enNames.indexOf(field.enName) > -1) { | ||
| 283 | ElMessage.error(`字段的英文名称 ${field.enName} 不能重复`); | ||
| 284 | return; | ||
| 285 | } | ||
| 286 | if (chNames.indexOf(field.chName) > -1) { | ||
| 287 | ElMessage.error(`字段的中文名称 ${field.chName} 不能重复`); | ||
| 288 | return; | ||
| 289 | } | ||
| 290 | if (field.dataType === "decimal" && (!field.fieldPrecision && field.fieldPrecision != 0)) { | ||
| 291 | ElMessage.error(`第 ${field.orderNum} 个字段的字段类型为浮点型时,精度不能为空`); | ||
| 292 | return; | ||
| 293 | } | ||
| 294 | if (field.dataType === "varchar" && (!field.fieldLength && field.fieldLength != 0)) { | ||
| 295 | ElMessage.error(`第 ${field.orderNum} 个字段的字段类型为字符型时,长度不能为空`); | ||
| 296 | return; | ||
| 297 | } | ||
| 298 | if (field.dataType === "char" && (!field.fieldLength && field.fieldLength != 0)) { | ||
| 299 | ElMessage.error(`第 ${field.orderNum} 个字段的字段类型为单字符型时,长度不能为空`); | ||
| 300 | return; | ||
| 301 | } | ||
| 302 | if (field.dataType === "decimal" && (!field.fieldLength && field.fieldLength != 0)) { | ||
| 303 | ElMessage.error(`第 ${field.orderNum} 个字段的字段类型为浮点符型时,长度不能为空`); | ||
| 304 | return; | ||
| 305 | } | ||
| 306 | if (field.isPrimary === 'Y') { | ||
| 307 | hasPrimary = true; | ||
| 308 | if (field.notNull != 'Y') { | ||
| 309 | ElMessage.error(`第 ${field.orderNum} 个字段为主键,应设置为必填`); | ||
| 310 | return; | ||
| 311 | } | ||
| 312 | if (field.dataType == 'text') { | ||
| 313 | ElMessage.error(`第 ${field.orderNum} 个字段为主键,字段类型不能设置为‘大字段型’`); | ||
| 314 | return; | ||
| 315 | } | ||
| 316 | if (field.dataType == 'json') { | ||
| 317 | ElMessage.error(`第 ${field.orderNum} 个字段为主键,字段类型不能设置为‘JSON类型’`); | ||
| 318 | return; | ||
| 319 | } | ||
| 320 | if (field.dataType == 'bit') { | ||
| 321 | ElMessage.error(`第 ${field.orderNum} 个字段为主键,字段类型不能设置为‘布尔类型’`); | ||
| 322 | return; | ||
| 323 | } | ||
| 324 | } else { | ||
| 325 | if (!field.aggWay && isSumModel) { | ||
| 326 | ElMessage.error(`聚合模型的非主键字段必须设置聚合方式`); | ||
| 327 | return; | ||
| 328 | } | ||
| 329 | } | ||
| 330 | if (field.isEdit) { | ||
| 331 | if (checkDefault[field.dataType]) { | ||
| 332 | if (!field.fieldLength) { } | ||
| 333 | if (!checkDefault[field.dataType]({ row: field })) { | ||
| 334 | return; | ||
| 335 | } | ||
| 336 | } | ||
| 337 | } | ||
| 338 | field.fieldStandardGuid = route.query.metaStandard; | ||
| 339 | enNames.push(field.enName); | ||
| 340 | chNames.push(field.chName); | ||
| 341 | } | ||
| 342 | if (!hasPrimary) { | ||
| 343 | ElMessage.error(`字段至少有一个主键字段!`); | ||
| 344 | return; | ||
| 345 | } | ||
| 346 | let addInfo = Object.assign({}, tableCreateInfo.value.tableData[0], { | ||
| 347 | enName: tableCreateInfo.value.inputNameValue, | ||
| 348 | tableCreateType: tableCreateInfo.value.tableCreateType, | ||
| 349 | saveFlag: 1, | ||
| 350 | layereAttribute: route.query.layereAttribute, | ||
| 351 | dbType: dbType.value, | ||
| 352 | dataState: 1, | ||
| 353 | immediateApprove: true, | ||
| 354 | partitionAttribute: !Object.keys(tableCreateInfo.value.partitionAttribute).length ? null : Object.assign({}, tableCreateInfo.value.partitionAttribute, { | ||
| 355 | dynamicPartitionHistory: tableCreateInfo.value.partitionAttribute ? "Y" : 'N' | ||
| 356 | }), | ||
| 357 | subjectFieldAddDTOS: tableCreateInfo.value.tableFields.map((field, i) => { | ||
| 358 | return Object.assign({}, field, { orderNum: i + 1 }); | ||
| 359 | }) | ||
| 360 | }) | ||
| 361 | if (!tableCreateInfo.value.guid) { //添加 | ||
| 362 | fullscreenLoading.value = true; | ||
| 363 | saveSubjectTable(addInfo).then((res: any) => { | ||
| 364 | fullscreenLoading.value = false; | ||
| 365 | if (res.code == proxy.$passCode) { | ||
| 366 | ElMessage.success('新建表提交成功!'); | ||
| 367 | router.push({ | ||
| 368 | name: 'metadataStandardQuery' | ||
| 369 | }); | ||
| 370 | userStore.setTabbar(userStore.tabbar.filter((tab: any) => tab.fullPath !== fullPath)); | ||
| 371 | } else { | ||
| 372 | ElMessage.error(res.msg); | ||
| 373 | } | ||
| 374 | }); | ||
| 375 | } | ||
| 376 | }; | ||
| 377 | |||
| 378 | //数据库选择改变,对应的表名称是否需要变化。需要根据此属性带出表名前缀,以及是否是doris数据库。 | ||
| 379 | const selectDatabaseChange = (val) => { | ||
| 380 | let d = databaseList.value.find(d => d.guid === val); | ||
| 381 | if (d) { | ||
| 382 | dbType.value = d.databaseType; | ||
| 383 | tableCreateInfo.value.tableData[0].dataSourceGuid = d.guid; | ||
| 384 | tableCreateInfo.value.tableData[0].dataServerName = d.databaseNameEn; | ||
| 385 | } else { | ||
| 386 | dbType.value = ""; | ||
| 387 | tableCreateInfo.value.tableData[0].dataSourceGuid = ''; | ||
| 388 | tableCreateInfo.value.tableData[0].dataServerName = ''; | ||
| 389 | } | ||
| 390 | tableCreateInfo.value.tableFields.forEach((tableField: any) => { | ||
| 391 | if (tableField['dataType'] === "datetime") { | ||
| 392 | tableField.defaultValue = "" | ||
| 393 | } | ||
| 394 | }) | ||
| 395 | }; | ||
| 396 | |||
| 397 | /** 添加字段标准 */ | ||
| 398 | const addField = () => { | ||
| 399 | let len = tableCreateInfo.value.tableFields.length; | ||
| 400 | tableCreateInfo.value.tableFields.push({ | ||
| 401 | orderNum: len + 1, | ||
| 402 | isDim: "N", | ||
| 403 | isPrimary: "N", | ||
| 404 | notNull: "N", | ||
| 405 | isEdit: true | ||
| 406 | }); | ||
| 407 | //设置选中表格当前新增行。 | ||
| 408 | fieldStandardTableRef.value?.setCurrentRow( | ||
| 409 | tableCreateInfo.value.tableFields[tableCreateInfo.value.tableFields.length - 1] | ||
| 410 | ); | ||
| 411 | nextTick(() => { | ||
| 412 | let bodyWrapper = fieldStandardTableRef.value?.$el.querySelector('.el-table__body'); | ||
| 413 | let domScroll = bodyWrapper.parentElement.parentElement; | ||
| 414 | let rect = domScroll.getBoundingClientRect(); | ||
| 415 | let maxNum = len + 1; | ||
| 416 | if (maxNum * 36 > rect.height + domScroll.scrollTop) { | ||
| 417 | fieldStandardTableRef.value?.setScrollTop(maxNum * 36 - rect.height + 2) | ||
| 418 | } | ||
| 419 | }) | ||
| 420 | }; | ||
| 421 | |||
| 422 | /** 勾选字段标准选中变化。 */ | ||
| 423 | const selectionFieldsChange = (val) => { | ||
| 424 | selectTableFieldRows.value = val; | ||
| 425 | }; | ||
| 426 | |||
| 427 | /** | ||
| 428 | * 上移规则: | ||
| 429 | * 勾选多个时先从最上面开始逐个上移一行,若已经移到最上面一行,则不处理。 | ||
| 430 | */ | ||
| 431 | const moveUp = () => { | ||
| 432 | let selectRows = fieldStandardTableRef.value?.getSelectionRows(); | ||
| 433 | if (!selectRows.length) { | ||
| 434 | ElMessage.error('请先选择需要勾选的数据进行上移'); | ||
| 435 | return; | ||
| 436 | } | ||
| 437 | let data = tableCreateInfo.value.tableFields; | ||
| 438 | let selectRowIndexs: number[] = []; | ||
| 439 | let minNum: number = 0; | ||
| 440 | selectRows.forEach((row, i) => { | ||
| 441 | let orderNum = data.findIndex(d => d === row) + 1; | ||
| 442 | if (orderNum == 1) { | ||
| 443 | selectRowIndexs.push(orderNum); | ||
| 444 | minNum = orderNum; | ||
| 445 | return; | ||
| 446 | } | ||
| 447 | let topNum = orderNum - 1; | ||
| 448 | if (selectRowIndexs.includes(topNum)) { | ||
| 449 | //下一行也是选中的,则不做转换。 | ||
| 450 | return; | ||
| 451 | } | ||
| 452 | if (i === 0) { | ||
| 453 | minNum = topNum; | ||
| 454 | } | ||
| 455 | row.orderNum = topNum; | ||
| 456 | let changeRow = data[topNum - 1]; | ||
| 457 | changeRow.orderNum = orderNum; | ||
| 458 | selectRowIndexs.push(topNum); | ||
| 459 | data[topNum] = changeRow; | ||
| 460 | data[topNum - 1] = row; | ||
| 461 | }); | ||
| 462 | nextTick().then(() => { | ||
| 463 | let bodyWrapper = fieldStandardTableRef.value?.$el.querySelector('.el-table__body'); | ||
| 464 | let domScroll = bodyWrapper.parentElement.parentElement; | ||
| 465 | if ((minNum * 36 - 38) < domScroll.scrollTop) { | ||
| 466 | let top = domScroll.scrollTop - 38; | ||
| 467 | fieldStandardTableRef.value?.setScrollTop(top < 0 ? 0 : top) | ||
| 468 | } | ||
| 469 | }); | ||
| 470 | } | ||
| 471 | |||
| 472 | /** | ||
| 473 | * 下移规则: | ||
| 474 | * 勾选多个时先从最下面开始逐个下移一行,若已经移到最下面一行,则不处理。 | ||
| 475 | */ | ||
| 476 | const moveDown = () => { | ||
| 477 | let selectRows = fieldStandardTableRef.value?.getSelectionRows(); | ||
| 478 | if (!selectRows.length) { | ||
| 479 | ElMessage.error('请先选择需要勾选的数据进行下移'); | ||
| 480 | return; | ||
| 481 | } | ||
| 482 | let data = tableCreateInfo.value.tableFields; | ||
| 483 | let selectRowIndexs: number[] = []; | ||
| 484 | let maxNum: number = 0; | ||
| 485 | selectRows.slice(0).reverse().forEach((row, i) => { | ||
| 486 | let orderNum = data.findIndex(d => d === row) + 1; | ||
| 487 | if (orderNum === data.length) { | ||
| 488 | maxNum = orderNum; | ||
| 489 | selectRowIndexs.push(orderNum); | ||
| 490 | return; | ||
| 491 | } | ||
| 492 | if (selectRowIndexs.includes(orderNum + 1)) { | ||
| 493 | //下一行也是选中的,则不做转换。 | ||
| 494 | return; | ||
| 495 | } | ||
| 496 | let bottomNum = orderNum + 1; | ||
| 497 | row.orderNum = bottomNum; | ||
| 498 | if (i === 0) { | ||
| 499 | maxNum = bottomNum; | ||
| 500 | } | ||
| 501 | let changeRow = data[bottomNum - 1]; | ||
| 502 | changeRow.orderNum = orderNum; | ||
| 503 | selectRowIndexs.push(bottomNum); | ||
| 504 | data[orderNum - 1] = changeRow; | ||
| 505 | data[bottomNum - 1] = row; | ||
| 506 | }); | ||
| 507 | nextTick(() => { | ||
| 508 | let bodyWrapper = fieldStandardTableRef.value?.$el.querySelector('.el-table__body'); | ||
| 509 | let domScroll = bodyWrapper.parentElement.parentElement; | ||
| 510 | let rect = domScroll.getBoundingClientRect(); | ||
| 511 | if (maxNum * 36 > rect.height + domScroll.scrollTop) { | ||
| 512 | fieldStandardTableRef.value?.setScrollTop(maxNum * 36 - rect.height + 2) | ||
| 513 | } | ||
| 514 | }) | ||
| 515 | } | ||
| 516 | |||
| 517 | /** 批量删除字段标准 */ | ||
| 518 | const delFeilds = () => { | ||
| 519 | if (selectTableFieldRows.value.length == 0) { | ||
| 520 | ElMessage({ | ||
| 521 | type: "info", | ||
| 522 | message: "请选择需要删除的字段", | ||
| 523 | }); | ||
| 524 | return; | ||
| 525 | } | ||
| 526 | if (tableCreateInfo.value.isCreate) { | ||
| 527 | if (selectTableFieldRows.value.find((row: any) => row.isPrimary === 'Y')) { | ||
| 528 | ElMessage.error('已建表不能删除主键字段'); | ||
| 529 | return; | ||
| 530 | } | ||
| 531 | } | ||
| 532 | let hasCreateField = selectTableFieldRows.value.some((row: any) => row.isCreate === 'Y'); | ||
| 533 | ElMessageBox.confirm(hasCreateField && hasSubjectData.value ? '已选择的字段中含有已创建的表字段且有数据,此操作将永久删除,是否继续?' : "此操作将永久删除,是否继续?", "提示", { | ||
| 534 | confirmButtonText: "确定", | ||
| 535 | cancelButtonText: "取消", | ||
| 536 | type: "warning", | ||
| 537 | }) | ||
| 538 | .then(() => { | ||
| 539 | //此删除是直接从库里删除,还是点击保存后再删除呢??如果是入库删除,后,调用接口获取数据。 | ||
| 540 | let tableFields = tableCreateInfo.value.tableFields; | ||
| 541 | selectTableFieldRows.value.forEach((r: any) => { | ||
| 542 | let index = tableFields.findIndex((t: any) => t.orderNum === r.orderNum); | ||
| 543 | if (index !== -1) { | ||
| 544 | tableFields.splice(index, 1); | ||
| 545 | } | ||
| 546 | }); | ||
| 547 | fieldStandardTableRef.value?.clearSelection(); | ||
| 548 | tableCreateInfo.value.tableFields.forEach((field, i) => { | ||
| 549 | field.orderNum = i + 1; | ||
| 550 | }); | ||
| 551 | ElMessage({ | ||
| 552 | type: "success", | ||
| 553 | message: "删除成功", | ||
| 554 | }); | ||
| 555 | }) | ||
| 556 | .catch(() => { | ||
| 557 | ElMessage({ | ||
| 558 | type: "info", | ||
| 559 | message: "已取消删除", | ||
| 560 | }); | ||
| 561 | }); | ||
| 562 | }; | ||
| 563 | |||
| 564 | //点击编辑按钮 | ||
| 565 | const handleFieldClickEdit = (scope) => { | ||
| 566 | scope.row['isEdit'] = true; | ||
| 567 | }; | ||
| 568 | |||
| 569 | //点击保存按钮 | ||
| 570 | const handleFieldClickSave = (scope) => { | ||
| 571 | if (!scope.row.enName) { | ||
| 572 | ElMessage({ | ||
| 573 | type: "error", | ||
| 574 | message: "字段英文名不能为空!", | ||
| 575 | }); | ||
| 576 | return; | ||
| 577 | } | ||
| 578 | if (checkDefault[scope.row.dataType]) { | ||
| 579 | if (!scope.row.fieldLength) { } | ||
| 580 | if (!checkDefault[scope.row.dataType](scope)) { | ||
| 581 | return | ||
| 582 | } | ||
| 583 | } | ||
| 584 | scope.row['isEdit'] = false; | ||
| 585 | }; | ||
| 586 | |||
| 587 | const handleFieldDelete = (scope) => { | ||
| 588 | ElMessageBox.confirm(scope.row['isCreate'] === 'Y' && hasSubjectData.value ? '该字段已被创建且表中有数据,此操作将永久删除,是否继续?' : "此操作将永久删除,是否继续?", "提示", { | ||
| 589 | confirmButtonText: "确定", | ||
| 590 | cancelButtonText: "取消", | ||
| 591 | type: "warning", | ||
| 592 | }) | ||
| 593 | .then(() => { | ||
| 594 | //此删除是直接从库里删除,还是点击保存后再删除呢??如果是入库删除,后,调用接口获取数据。 | ||
| 595 | let tableFields = tableCreateInfo.value.tableFields; | ||
| 596 | tableFields.splice(scope.$index, 1); | ||
| 597 | tableCreateInfo.value.tableFields.forEach((field, i) => { | ||
| 598 | field.orderNum = i + 1; | ||
| 599 | }); | ||
| 600 | tableCreateInfo.value.tableFields.forEach((field, i) => { | ||
| 601 | field.orderNum = i + 1; | ||
| 602 | }); | ||
| 603 | ElMessage({ | ||
| 604 | type: "success", | ||
| 605 | message: "删除成功", | ||
| 606 | }); | ||
| 607 | }) | ||
| 608 | .catch(() => { | ||
| 609 | ElMessage({ | ||
| 610 | type: "info", | ||
| 611 | message: "已取消删除", | ||
| 612 | }); | ||
| 613 | }); | ||
| 614 | } | ||
| 615 | |||
| 616 | const dataTypeChange = (val, scope) => { | ||
| 617 | scope.row['defaultValue'] = '' | ||
| 618 | scope.row['fieldLength'] = undefined | ||
| 619 | scope.row['fieldPrecision'] = undefined | ||
| 620 | |||
| 621 | } | ||
| 622 | |||
| 623 | /*** 以下是处理数据字典或维表的树形选择框。 */ | ||
| 624 | |||
| 625 | const dimOrDictList: any = ref([{ | ||
| 626 | guid: '1', | ||
| 627 | chName: '数据字典', | ||
| 628 | children: dictionaryList.value, | ||
| 629 | isLeaf: false, | ||
| 630 | disabled: !dictionaryList.value.length, | ||
| 631 | }, { | ||
| 632 | guid: '2', | ||
| 633 | chName: '维度', | ||
| 634 | isLeaf: false, | ||
| 635 | disabled: !dimListData.value.length, | ||
| 636 | children: dimListData.value | ||
| 637 | }]); | ||
| 638 | |||
| 639 | const dimOrDictInputFilterMethod = (v, data) => { | ||
| 640 | return data.label?.includes(v) || data.chName?.includes(v); | ||
| 641 | }; | ||
| 642 | |||
| 643 | const dimOrDictSelectRef = ref(); | ||
| 644 | |||
| 645 | const dimOrDictSelectNode = ref(); | ||
| 646 | |||
| 647 | const handleDictSelectNodeChange = (node) => { | ||
| 648 | dimOrDictSelectNode.value = node; | ||
| 649 | } | ||
| 650 | |||
| 651 | const handleDictionaryChange = (val, scope) => { | ||
| 652 | if (!val) { | ||
| 653 | scope.row.dictionaryGuid = ''; | ||
| 654 | scope.row.dimGuid = ''; | ||
| 655 | scope.row.dictionaryChName = ''; | ||
| 656 | scope.row.dimChName = ''; | ||
| 657 | return; | ||
| 658 | } | ||
| 659 | let info = dimOrDictSelectNode.value; | ||
| 660 | if (!info) { | ||
| 661 | return; | ||
| 662 | } | ||
| 663 | if (info.parentGuid == '2') { | ||
| 664 | scope.row.dimGuid = val; | ||
| 665 | scope.row.dimChName = dimListData.value.find(d => d.guid === val)?.chName; | ||
| 666 | scope.row.dictionaryGuid = ''; | ||
| 667 | scope.row.dictionaryChName = ''; | ||
| 668 | } else { | ||
| 669 | scope.row.dictionaryGuid = val; | ||
| 670 | scope.row.dictionaryChName = dictionaryList.value.find(d => d.guid === val)?.chName; | ||
| 671 | scope.row.dimGuid = ''; | ||
| 672 | scope.row.dimChName = ''; | ||
| 673 | } | ||
| 674 | } | ||
| 675 | |||
| 676 | /** 扩展属性弹出对话框 */ | ||
| 677 | const expandPropertyDialogRef = ref(); | ||
| 678 | |||
| 679 | /** 扩展属性弹出对话框 */ | ||
| 680 | const handleClickExpand = () => { | ||
| 681 | expandPropertyDialogRef.value?.handleClickExpand(); | ||
| 682 | } | ||
| 683 | |||
| 684 | const expandDialogValueChange = (val) => { | ||
| 685 | tableCreateInfo.value.partitionAttribute = val; | ||
| 686 | expandProperties.value = val; | ||
| 687 | } | ||
| 688 | |||
| 689 | </script> | ||
| 690 | |||
| 691 | <template> | ||
| 692 | <div class="table_tool_wrap" v-loading.fullscreen.lock="fullscreenLoading"> | ||
| 693 | <div class="tools_btns"> | ||
| 694 | <!-- <el-button type="primary" :disabled="isLook" @click="saveDraftTable" v-preReClick>保存为草稿</el-button> --> | ||
| 695 | <el-button type="primary" :disabled="isLook" @click="saveTable" v-preReClick>提交</el-button> | ||
| 696 | </div> | ||
| 697 | <el-table ref="tableRef" :data="tableCreateInfo.tableData" v-loading="tableCreateInfoLoading" | ||
| 698 | :highlight-current-row="true" stripe border height="100%" tooltip-effect="light" row-key="guid" :style="{ | ||
| 699 | width: '100%', | ||
| 700 | height: 'auto', | ||
| 701 | display: 'inline-block', | ||
| 702 | }"> | ||
| 703 | <el-table-column prop="dataSourceGuid" label="数据源" width="200px" align="left" show-overflow-tooltip> | ||
| 704 | <template #header> | ||
| 705 | <span>数据源</span> | ||
| 706 | <span v-if="!isLook" style="color:red;margin-left: 2px;">*</span> | ||
| 707 | </template> | ||
| 708 | <template #default="scope"> | ||
| 709 | <el-select v-if="!isLook" v-model="scope.row['dataSourceGuid']" placeholder="请选择" | ||
| 710 | :disabled="tableCreateInfo.isCreate" @change="(val) => selectDatabaseChange(val)" clearable filterable> | ||
| 711 | <el-option v-for="opt in databaseList" :key="opt['guid']" :label="opt['databaseNameZh']" | ||
| 712 | :value="opt['guid']" /> | ||
| 713 | </el-select> | ||
| 714 | <span v-else>{{ scope.row["dataServerChName"] }}</span> | ||
| 715 | </template> | ||
| 716 | </el-table-column> | ||
| 717 | <el-table-column prop="enName" label="数据库表" width="200px" align="left" show-overflow-tooltip> | ||
| 718 | <template #header> | ||
| 719 | <span>数据库表</span> | ||
| 720 | <span v-if="!isLook" style="color:red;margin-left: 2px;">*</span> | ||
| 721 | </template> | ||
| 722 | <template #default="scope"> | ||
| 723 | <template v-if="!isLook"> | ||
| 724 | <div class="prefix-or-suffix-cell"> | ||
| 725 | <el-input :disabled="tableCreateInfo.isCreate" v-model.trim="tableCreateInfo.inputNameValue" | ||
| 726 | :maxlength="50" placeholder="必填" /> | ||
| 727 | </div> | ||
| 728 | </template> | ||
| 729 | <span v-else>{{ scope.row["enName"] }}</span> | ||
| 730 | </template> | ||
| 731 | </el-table-column> | ||
| 732 | <el-table-column prop="chName" label="主题表名称" width="200px" align="left" show-overflow-tooltip> | ||
| 733 | <template #header> | ||
| 734 | <span>主题表名称</span> | ||
| 735 | <span v-if="!isLook" style="color:red;margin-left: 2px;">*</span> | ||
| 736 | </template> | ||
| 737 | <template #default="scope"> | ||
| 738 | <el-input v-if="!isLook" v-model.trim="scope.row['chName']" placeholder="必填" :maxlength="50" /> | ||
| 739 | <span v-else>{{ scope.row["chName"] }}</span> | ||
| 740 | </template> | ||
| 741 | </el-table-column> | ||
| 742 | <el-table-column prop="subjectDomain" label="主题域" width="180px" align="left" show-overflow-tooltip> | ||
| 743 | <template #default="scope"> | ||
| 744 | <el-input v-if="!isLook" disabled v-model="scope.row['subjectDomain']" /> | ||
| 745 | <span v-else>{{ scope.row["subjectDomain"] }}</span> | ||
| 746 | </template> | ||
| 747 | </el-table-column> | ||
| 748 | <el-table-column prop="tableModel" label="表模型" :width="isLook ? '100px' : '150px'" align="left" | ||
| 749 | show-overflow-tooltip> | ||
| 750 | <template #default="scope"> | ||
| 751 | <el-select v-if="dbType == 'doris' && !isLook" v-model="scope.row['tableModel']" placeholder="请选择" | ||
| 752 | :disabled="tableCreateInfo.isCreate"> | ||
| 753 | <el-option v-for="opt in tableModels" :key="opt['value']" :label="opt['label']" :value="opt['value']" /> | ||
| 754 | </el-select> | ||
| 755 | <span v-else-if="dbType == 'doris'">{{tableModels.find(t => t.value === scope.row["tableModel"])?.label || | ||
| 756 | '-' | ||
| 757 | }}</span> | ||
| 758 | <span v-else>--</span> | ||
| 759 | </template> | ||
| 760 | </el-table-column> | ||
| 761 | <el-table-column prop="tableCategory" label="表分类" :width="isLook ? '100px' : '150px'" align="left" | ||
| 762 | show-overflow-tooltip> | ||
| 763 | <template #default="scope"> | ||
| 764 | <el-select v-if="!isLook" v-model="scope.row['tableCategory']" placeholder="请选择"> | ||
| 765 | <el-option v-for="opt in tableCategoryList" :key="opt['value']" :label="opt['label']" | ||
| 766 | :value="opt['value']" /> | ||
| 767 | </el-select> | ||
| 768 | <span v-else>{{tableCategoryList.find(t => t.value === scope.row["tableCategory"])?.label || '-'}}</span> | ||
| 769 | </template> | ||
| 770 | </el-table-column> | ||
| 771 | <el-table-column prop="syncPolicy" label="同步策略" :width="isLook ? '100px' : '150px'" align="left" | ||
| 772 | show-overflow-tooltip> | ||
| 773 | <template #default="scope"> | ||
| 774 | <el-select v-if="!isLook" v-model="scope.row['syncPolicy']" placeholder="请选择"> | ||
| 775 | <el-option v-for="opt in syncPolicys" :key="opt['value']" :label="opt['label']" :value="opt['value']" /> | ||
| 776 | </el-select> | ||
| 777 | <span v-else>{{syncPolicys.find(s => s.value === scope.row["syncPolicy"])?.label || '-'}}</span> | ||
| 778 | </template> | ||
| 779 | </el-table-column> | ||
| 780 | <el-table-column prop="characterSet" label="字符集" :width="isLook ? '100px' : '150px'" align="left" | ||
| 781 | show-overflow-tooltip> | ||
| 782 | <template #default="scope"> | ||
| 783 | <el-select v-if="!isLook" v-model="scope.row['characterSet']" placeholder="请选择" | ||
| 784 | :disabled="tableCreateInfo.isCreate"> | ||
| 785 | <el-option v-for="opt in characterList" :key="opt['value']" :label="opt['label']" :value="opt['value']" /> | ||
| 786 | </el-select> | ||
| 787 | <span v-else>{{characterList.find(c => c.value === scope.row["characterSet"])?.label || '-'}}</span> | ||
| 788 | </template> | ||
| 789 | </el-table-column> | ||
| 790 | <el-table-column prop="description" label="描述" width="220px" align="left" show-overflow-tooltip> | ||
| 791 | <template #default="scope"> | ||
| 792 | <el-input v-if="!isLook" v-model.trim="scope.row['description']" /> | ||
| 793 | <span v-else>{{ scope.row["description"] || '-' }}</span> | ||
| 794 | </template> | ||
| 795 | </el-table-column> | ||
| 796 | <el-table-column label="操作" width="100px" align="left" fixed="right" show-overflow-tooltip> | ||
| 797 | <template #default="scope"> | ||
| 798 | <span class="text_btn" @click="handleClickExpand()" v-preReClick>扩展属性</span> | ||
| 799 | </template> | ||
| 800 | </el-table-column> | ||
| 801 | </el-table> | ||
| 802 | <div class="tools_btns"> | ||
| 803 | <el-button type="primary" :disabled="isLook" @click="addField">新增</el-button> | ||
| 804 | <el-button @click="moveUp" :disabled="isLook">上移</el-button> | ||
| 805 | <el-button @click="moveDown" :disabled="isLook">下移</el-button> | ||
| 806 | <el-button @click="delFeilds" :disabled="isLook">批量删除</el-button> | ||
| 807 | </div> | ||
| 808 | <div class="table_panel"> | ||
| 809 | <el-table ref="fieldStandardTableRef" :data="tableCreateInfo.tableFields" v-loading="tableFieldsLoading" | ||
| 810 | :highlight-current-row="true" stripe border height="100%" row-key="guid" | ||
| 811 | @selection-change="selectionFieldsChange" tooltip-effect="light" :style="{ | ||
| 812 | width: '100%', | ||
| 813 | 'max-height': 'calc(100% - 16px)', | ||
| 814 | display: 'inline-block', | ||
| 815 | }"> | ||
| 816 | <el-table-column type="selection" v-if="!isLook" :width="32" align="center" /> | ||
| 817 | <el-table-column label="排序" type="index" width="56px" align="center" show-overflow-tooltip> | ||
| 818 | </el-table-column> | ||
| 819 | <el-table-column prop="chName" label="字段中文名称" width="150px" align="left" show-overflow-tooltip> | ||
| 820 | <template #default="scope"> | ||
| 821 | <el-input v-if="scope.row['isEdit']" :placeholder="'请输入'" v-model.trim="scope.row['chName']" /> | ||
| 822 | <span v-else>{{ scope.row["chName"] || '-' }}</span> | ||
| 823 | </template> | ||
| 824 | </el-table-column> | ||
| 825 | <el-table-column prop="enName" label="字段英文名" width="150px" align="left" show-overflow-tooltip> | ||
| 826 | <template #default="scope"> | ||
| 827 | <el-input v-if="scope.row['isEdit'] && !(scope.row['guid'] && tableCreateInfo.isCreate)" | ||
| 828 | v-model.trim="scope.row['enName']" placeholder="必填" | ||
| 829 | @input="inputLengthKeyUp(/[^a-zA-Z0-9_]/g, scope, 'enName')" /> | ||
| 830 | <span v-else>{{ scope.row["enName"] || '-' }}</span> | ||
| 831 | </template> | ||
| 832 | </el-table-column> | ||
| 833 | <el-table-column prop="dataType" label="字段类型" width="120px" align="left" show-overflow-tooltip> | ||
| 834 | <template #default="scope"> | ||
| 835 | <el-select v-if="scope.row['isEdit'] && !(tableCreateInfo.isCreate && scope.row['isCreate'] === 'Y')" | ||
| 836 | v-model="scope.row['dataType']" placeholder="请选择" @change="(val) => dataTypeChange(val, scope)"> | ||
| 837 | <el-option v-for="opt in fieldTypes" :key="opt['value']" :label="opt['label']" :value="opt['value']" /> | ||
| 838 | </el-select> | ||
| 839 | <span v-else>{{fieldTypes.find(f => f.value === scope.row["dataType"])?.label || '-'}}</span> | ||
| 840 | </template> | ||
| 841 | </el-table-column> | ||
| 842 | <el-table-column prop="fieldLength" label="长度" width="115px" align="left" show-overflow-tooltip> | ||
| 843 | <template #default="scope"> | ||
| 844 | <el-input | ||
| 845 | v-if="scope.row['isEdit'] && !(tableCreateInfo.isCreate && scope.row['isCreate'] === 'Y') && (scope.row['dataType'] == 'varchar' || scope.row['dataType'] == 'decimal' || scope.row['dataType'] == 'char')" | ||
| 846 | v-model.trim="scope.row['fieldLength']" placeholder="必填" | ||
| 847 | @input="inputLengthKeyUp(/\D/g, scope, 'fieldLength', 2000, 1)" /> | ||
| 848 | <span v-else>{{ scope.row["fieldLength"] == null ? '-' : scope.row["fieldLength"] }}</span> | ||
| 849 | </template> | ||
| 850 | </el-table-column> | ||
| 851 | <el-table-column prop="fieldPrecision" label="精度" width="115px" align="left" show-overflow-tooltip> | ||
| 852 | <template #default="scope"> | ||
| 853 | <el-input | ||
| 854 | v-if="scope.row['isEdit'] && !(tableCreateInfo.isCreate && scope.row['isCreate'] === 'Y') && scope.row['dataType'] == 'decimal'" | ||
| 855 | v-model.trim="scope.row['fieldPrecision']" placeholder="必填" | ||
| 856 | @input="inputLengthKeyUp(/\D/g, scope, 'fieldPrecision', 30, 1)" /> | ||
| 857 | <span v-else>{{ scope.row["fieldPrecision"] == null ? '-' : scope.row["fieldPrecision"] }}</span> | ||
| 858 | </template> | ||
| 859 | </el-table-column> | ||
| 860 | <el-table-column prop="dimOrdictionaryGuid" label="关联维度/字典" width="130px" align="left" show-overflow-tooltip> | ||
| 861 | <template #default="scope"> | ||
| 862 | <el-tree-select ref="dimOrDictSelectRef" v-if="scope.row['isEdit']" filterable clearable | ||
| 863 | :data="dimOrDictList" v-model="scope.row['dimOrdictionaryGuid']" node-key="guid" | ||
| 864 | :default-expanded-keys="scope.row['dictionaryGuid'] ? ['1'] : (scope.row['dimGuid'] ? ['2'] : [])" | ||
| 865 | placeholder="请选择" :filter-node-method="dimOrDictInputFilterMethod" :props="{ | ||
| 866 | label: 'chName', | ||
| 867 | value: 'guid', | ||
| 868 | children: 'children', | ||
| 869 | isLeaf: 'isLeaf' | ||
| 870 | }" @change="(v) => handleDictionaryChange(v, scope)" @current-change="handleDictSelectNodeChange"> | ||
| 871 | <template #default="{ node, data }"> | ||
| 872 | <template v-if="node.level > 1 && data.parentGuid == '2'"> | ||
| 873 | <span>{{ data["chName"] + `(${data["subjectDomainName"]})` }}</span> | ||
| 874 | </template> | ||
| 875 | <span v-else>{{ data['chName'] }}</span> | ||
| 876 | </template> | ||
| 877 | </el-tree-select> | ||
| 878 | <span v-else>{{ (scope.row['dictionaryGuid'] ? scope.row["dictionaryChName"] : (scope.row['dimGuid'] ? | ||
| 879 | scope.row['dimChName'] : '-')) || '-' }}</span> | ||
| 880 | </template> | ||
| 881 | </el-table-column> | ||
| 882 | <el-table-column prop="isPrimary" label="是否主键" width="90px" align="left" show-overflow-tooltip> | ||
| 883 | <template #default="scope"> | ||
| 884 | <el-select v-if="scope.row['isEdit'] && !tableCreateInfo.isCreate" v-model="scope.row['isPrimary']" | ||
| 885 | placeholder="请选择"> | ||
| 886 | <el-option v-for="opt in isNotList" :key="opt['value']" :label="opt['label']" :value="opt['value']" /> | ||
| 887 | </el-select> | ||
| 888 | <span v-else>{{ scope.row["isPrimary"] || '-' }}</span> | ||
| 889 | </template> | ||
| 890 | </el-table-column> | ||
| 891 | <el-table-column v-if="tableCreateInfo.tableData[0].tableModel == 2" prop="aggWay" label="聚合方式" width="120px" | ||
| 892 | align="left" show-overflow-tooltip> | ||
| 893 | <template #default="scope"> | ||
| 894 | <el-select v-if="scope.row['isEdit']" v-model="scope.row['aggWay']" placeholder="请选择"> | ||
| 895 | <el-option v-for="opt in aggMethodList" :key="opt['value']" :label="opt['label']" :value="opt['value']" /> | ||
| 896 | </el-select> | ||
| 897 | <span v-else>{{ scope.row["aggWay"] || '-' }}</span> | ||
| 898 | </template> | ||
| 899 | </el-table-column> | ||
| 900 | <el-table-column prop="notNull" label="是否必填" width="90px" align="left" show-overflow-tooltip> | ||
| 901 | <template #default="scope"> | ||
| 902 | <el-select v-if="scope.row['isEdit'] && !(scope.row.isCreate == 'Y' && scope.row['notNull'] == 'N')" | ||
| 903 | v-model="scope.row['notNull']" placeholder="请选择"> | ||
| 904 | <el-option v-for="opt in isNotList" :key="opt['value']" :label="opt['label']" :value="opt['value']" /> | ||
| 905 | </el-select> | ||
| 906 | <span v-else>{{ scope.row["notNull"] || '-' }}</span> | ||
| 907 | </template> | ||
| 908 | </el-table-column> | ||
| 909 | <el-table-column prop="defaultValue" label="默认值" width="205px" align="left" show-overflow-tooltip> | ||
| 910 | <template #default="scope"> | ||
| 911 | <tableDefaultValue :scope="scope" :dbType="dbType" | ||
| 912 | :readonly="dbType == 'doris' && scope.row.isCreate == 'Y'"></tableDefaultValue> | ||
| 913 | </template> | ||
| 914 | </el-table-column> | ||
| 915 | <el-table-column v-if="!isLook" label="操作" width="100px" align="left" fixed="right" show-overflow-tooltip> | ||
| 916 | <template #default="scope"> | ||
| 917 | <template v-if="!(tableCreateInfo.isCreate && scope.row['isPrimary'] === 'Y')"> | ||
| 918 | <span class="text_btn" v-if="!scope.row['isEdit']" @click="handleFieldClickEdit(scope)" | ||
| 919 | v-preReClick>编辑</span> | ||
| 920 | <span class="text_btn" v-else @click="handleFieldClickSave(scope)" v-preReClick>保存</span> | ||
| 921 | <el-divider direction="vertical" /> | ||
| 922 | <span class="text_btn" @click="handleFieldDelete(scope)">删除</span> | ||
| 923 | </template> | ||
| 924 | <span v-else>--</span> | ||
| 925 | </template> | ||
| 926 | </el-table-column> | ||
| 927 | </el-table> | ||
| 928 | </div> | ||
| 929 | <ContentWrap title="流程审批" description="" :isExpand="flowExpand" :expand-swicth="true" class="mb16" | ||
| 930 | @expand="(v) => flowExpand = v"> | ||
| 931 | <ApprovalProcess v-if="deploymentId" :deploymentId="deploymentId" :definitionId="''"> | ||
| 932 | </ApprovalProcess> | ||
| 933 | </ContentWrap> | ||
| 934 | <expandPropertyDialog ref="expandPropertyDialogRef" :is-look="isLook" :partitionAttribute="expandProperties" | ||
| 935 | :table-create-info="tableCreateInfo" @expandValueChange="expandDialogValueChange" /> | ||
| 936 | </div> | ||
| 937 | </template> | ||
| 938 | |||
| 939 | <style lang="scss" scoped> | ||
| 940 | .table_tool_wrap { | ||
| 941 | width: 100%; | ||
| 942 | height: 100%; | ||
| 943 | padding: 0 16px; | ||
| 944 | overflow: hidden auto; | ||
| 945 | |||
| 946 | .tools_btns { | ||
| 947 | padding: 8px 0; | ||
| 948 | } | ||
| 949 | |||
| 950 | :deep(.el-table) { | ||
| 951 | .cell { | ||
| 952 | |||
| 953 | .prefix-or-suffix-cell { | ||
| 954 | display: inline-flex; | ||
| 955 | align-items: center; | ||
| 956 | } | ||
| 957 | } | ||
| 958 | } | ||
| 959 | |||
| 960 | .table_panel { | ||
| 961 | height: 268px; | ||
| 962 | |||
| 963 | :deep(.el-table) { | ||
| 964 | & td.el-table__cell { | ||
| 965 | padding: 2px 0; | ||
| 966 | height: 36px; | ||
| 967 | } | ||
| 968 | } | ||
| 969 | } | ||
| 970 | } | ||
| 971 | |||
| 972 | :deep(.el-dialog) { | ||
| 973 | .dialog-form-inline { | ||
| 974 | .checkbox_input { | ||
| 975 | display: flex; | ||
| 976 | flex-direction: column; | ||
| 977 | |||
| 978 | .input_panel { | ||
| 979 | margin: 0; | ||
| 980 | } | ||
| 981 | } | ||
| 982 | |||
| 983 | .select_group { | ||
| 984 | .el-form-item__content>.el-input { | ||
| 985 | margin-top: 21px; | ||
| 986 | } | ||
| 987 | } | ||
| 988 | |||
| 989 | .radio_panel { | ||
| 990 | .panel_content { | ||
| 991 | display: none; | ||
| 992 | } | ||
| 993 | } | ||
| 994 | } | ||
| 995 | } | ||
| 996 | </style> |
-
Please register or sign in to post a comment