f8d07716 by xukangle

update: 联调分类分级目录接口

1 parent e74fabf2
1 # 页面标题 1 # 页面标题
2 VITE_APP_TITLE = 数据资产管理系统 2 VITE_APP_TITLE = 数据资产管理系统
3 # 接口域名 3 # 接口域名
4 VITE_API_BASEURL = https://www.zgsjzc.com/api 4 VITE_API_BASEURL = http://192.168.6.20:28052/
5 # VITE_API_BASEURL = http://49.4.26.201:31709/ 5 # VITE_API_BASEURL = http://49.4.26.201:31709/
6 # # 平台用户 接口请地址
7 # VITE_APP_USER_API_BASEURL = gateway-server
8 # # 系统管理 接口地址
9 # VITE_APP_API_BASEURL = ms-daop-zcgl-system-manager-service
10 # # 文件上传请求地址
11 # VITE_APP_ADD_FILE = ms-daop-import-data-service
12 # # 调试工具,可设置 eruda 或 vconsole,如果不需要开启则留空
13 # VITE_APP_DEBUG_TOOL =
14 # # 是否开启代理
15 # VITE_OPEN_PROXY = true
16 # # vite serve base
17 # VITE_SERVE_BASE = /
18 # # 流程设计访问地址
19 # VITE_BPMN_URL = https://workflow.zgsjzc.com
20 # # 数据标准、元数据、数据目录 接口地址
21 # VITE_APP_PLAN_BASEURL = ms-daop-jgjf-data-plan-service
22 # #数据质量接口地址
23 # VITE_APP_QUALITY_BASEURL = ms-daop-data-quality-service
24
25 # #门户接口
26 # VITE_API_PORTALURL = https://www.zgsjzc.com/portal
27
28 # #数据资产接口地址
29 # VITE_API_ASSET_BASEURL = ms-swzl-data-dam-service
30 # #数据同步接口地址
31 # VITE_API_DATA_SYNC = ms-swzl-data-sync-service
32 # #消息接口
33 # VITE_API_MESSAGE = ms-swzl-message-notification-service
6 # 平台用户 接口请地址 34 # 平台用户 接口请地址
7 VITE_APP_USER_API_BASEURL = gateway-server 35 VITE_APP_USER_API_BASEURL = gateway-server
36
37 #AUTH服务
38 VITE_APP_AUTH_URL = 'ms-daop-auth-service'
39
8 # 系统管理 接口地址 40 # 系统管理 接口地址
9 VITE_APP_API_BASEURL = ms-daop-zcgl-system-manager-service 41 VITE_APP_API_BASEURL = ms-daop-zcgl-system-manager-service
42
10 # 文件上传请求地址 43 # 文件上传请求地址
11 VITE_APP_ADD_FILE = ms-daop-import-data-service 44 VITE_APP_ADD_FILE = ms-daop-import-data-service
12 # 调试工具,可设置 eruda 或 vconsole,如果不需要开启则留空 45 # 调试工具,可设置 eruda 或 vconsole,如果不需要开启则留空
...@@ -16,14 +49,22 @@ VITE_OPEN_PROXY = true ...@@ -16,14 +49,22 @@ VITE_OPEN_PROXY = true
16 # vite serve base 49 # vite serve base
17 VITE_SERVE_BASE = / 50 VITE_SERVE_BASE = /
18 # 流程设计访问地址 51 # 流程设计访问地址
19 VITE_BPMN_URL = https://workflow.zgsjzc.com 52 VITE_BPMN_URL = https://workflow-swzl-test.csbr.cn
20 # 数据标准、元数据、数据目录 接口地址 53 # 数据标准、元数据、数据目录 接口地址
21 VITE_APP_PLAN_BASEURL = ms-daop-jgjf-data-plan-service 54 VITE_APP_PLAN_BASEURL = ms-daop-jgjf-data-plan-service
22 #数据质量接口地址 55 #数据质量接口地址
23 VITE_APP_QUALITY_BASEURL = ms-daop-data-quality-service 56 VITE_APP_QUALITY_BASEURL = ms-daop-data-quality-service
24 57
58 #数据盘点接口地址ms-daop-zcgl-data-inventory
59 # VITE_APP_CHECK_BASEURL = /mock
60 VITE_APP_CHECK_BASEURL = ms-daop-zcgl-data-inventory
61
62 # 数据字典接口地址
63 VITE_APP_CONFIG_URL = 'ms-daop-configure-service'
64
65
25 #门户接口 66 #门户接口
26 VITE_API_PORTALURL = https://www.zgsjzc.com/portal 67 VITE_API_PORTALURL = https://swzl-test.zgsjzc.com/portal
27 68
28 #数据资产接口地址 69 #数据资产接口地址
29 VITE_API_ASSET_BASEURL = ms-swzl-data-dam-service 70 VITE_API_ASSET_BASEURL = ms-swzl-data-dam-service
......
1 FROM 192.168.5.4:82/csbr/nginx:stable-alpine 1
2
3 FROM 192.168.6.22:8081/csbr/nginx:stable-alpine
2 VOLUME /tmp 4 VOLUME /tmp
3 #将当前文件夹的dist文件复制到容器的/usr/share/nginx/html目录 5 #将当前文件夹的dist文件复制到容器的/usr/share/nginx/html目录
4 COPY ./dist/* /usr/share/nginx/html/ 6 COPY ./dist/* /usr/share/nginx/html/
5 COPY ./dist/assets /usr/share/nginx/html/assets 7 COPY ./dist/assets /usr/share/nginx/html/assets
6 #COPY ./dist/importTemplate /usr/share/nginx/html/importTemplate
7 COPY default.conf /etc/nginx/conf.d/ 8 COPY default.conf /etc/nginx/conf.d/
8 #声明运行时容器暴露的端口(容器提供的服务端口) 9 #声明运行时容器暴露的端口(容器提供的服务端口)
9 EXPOSE 8911 10 RUN chown -R nginx:nginx /usr/share/nginx/html
11 EXPOSE 29900
10 #CMD:指定容器启动时要运行的命令 12 #CMD:指定容器启动时要运行的命令
11 CMD ["nginx", "-g", "daemon off;"]
...\ No newline at end of file ...\ No newline at end of file
13 CMD ["nginx", "-g", "daemon off;"]
......
...@@ -3,21 +3,22 @@ pipeline { ...@@ -3,21 +3,22 @@ pipeline {
3 //环境定义 3 //环境定义
4 environment{ 4 environment{
5 //服务名称 5 //服务名称
6 SVN_FOLD = "fe-swzl-asset-temp" 6 SVN_FOLD = "fe-data-asset-management"
7 //部署远程服务器 7 //部署远程服务器
8 //192.168.4.4服务器 8 //192.168.4.4服务器
9 //SSH_PATH = "csbr4.4" 9 //SSH_PATH = "csbr4.4"
10 //192.168.5.4 10 //192.168.5.4
11 SSH_PATH = "csbr5.2" 11 SSH_PATH = "csbr20"
12 SVN_TYPE = "dev"
12 //139.9.190.186 13 //139.9.190.186
13 //SSH_PATH = "csbr190.186" 14 //SSH_PATH = "csbr190.186"
14 //SVN_TYPE = "master" 15 //SVN_TYPE = "master"
15 //镜像版本号 16 //镜像版本号
16 image_tag = "1.0.0" 17 image_tag = "1.0.0"
17 //docker私服ip 18 //docker私服ip
18 ip = "192.168.5.4:82" 19 ip = "192.168.6.22:8081"
19 //前端端口号 20 //前端端口号
20 port = "8911" 21 port = "29900"
21 //映射端口号 22 //映射端口号
22 vport = "80" 23 vport = "80"
23 24
...@@ -63,9 +64,9 @@ pipeline { ...@@ -63,9 +64,9 @@ pipeline {
63 steps { 64 steps {
64 //分分支构建 65 //分分支构建
65 script{ 66 script{
66 if(env.BRANCH_NAME=='master-asset'){ 67 if(env.BRANCH_NAME=='develop'){
67 //master-asset分支环境 68 //master-asset分支环境
68 echo 'start to deploy ${SVN_FOLD} on master-asset ...' 69 echo 'start to deploy ${SVN_FOLD} on develop ...'
69 sh ''' 70 sh '''
70 #docker rmi -f $(docker images | grep "none" | awk '{print $3}') 71 #docker rmi -f $(docker images | grep "none" | awk '{print $3}')
71 CID=$(docker ps -a | grep "${SVN_FOLD}" | awk '{print $1}') 72 CID=$(docker ps -a | grep "${SVN_FOLD}" | awk '{print $1}')
...@@ -107,14 +108,14 @@ pipeline { ...@@ -107,14 +108,14 @@ pipeline {
107 echo 'Deploying' 108 echo 'Deploying'
108 //分分支部署 109 //分分支部署
109 script{ 110 script{
110 if(env.BRANCH_NAME=='master-asset'){ 111 if(env.BRANCH_NAME=='develop'){
111 //master-asset分支环境 112 //master-asset分支环境
112 echo 'start to deploy ${SVN_FOLD} on master-asset ...' 113 echo 'start to deploy ${SVN_FOLD} on develop ...'
113 //调用Publish Over SSH插件,上传docker-compose.yaml文件并且执行deploy脚本 114 //调用Publish Over SSH插件,上传docker-compose.yaml文件并且执行deploy脚本
114 sshPublisher(publishers: [sshPublisherDesc(configName: "csbr5.3", transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: """ 115 sshPublisher(publishers: [sshPublisherDesc(configName: "csbr5.3", transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: """
115 #使用k8s构建 116 #使用k8s构建
116 kubectl delete -f /mnt/k8s/production/fe-swzl-asset.yaml 117 kubectl delete -f /mnt/k8s/develop/daop-jgjf/fe-data-asset-management.yaml
117 kubectl apply -f /mnt/k8s/production/fe-swzl-asset.yaml 118 kubectl apply -f /mnt/k8s/develop/daop-jgjf/fe-data-asset-management.yaml
118 """, execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '/mnt/csbr/data', remoteDirectorySDF: false, removePrefix: '', sourceFiles: 'output/*.*')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)]) 119 """, execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '/mnt/csbr/data', remoteDirectorySDF: false, removePrefix: '', sourceFiles: 'output/*.*')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
119 120
120 echo 'Depoly ${SVN_FOLD} success ...' 121 echo 'Depoly ${SVN_FOLD} success ...'
......
...@@ -2,48 +2,53 @@ server { ...@@ -2,48 +2,53 @@ server {
2 listen 80; 2 listen 80;
3 listen [::]:80; 3 listen [::]:80;
4 server_name localhost; 4 server_name localhost;
5 # server_name http://192.168.6.20:8052;
5 6
6 #charset koi8-r; 7
7 #access_log /var/log/nginx/host.access.log main; 8 # 设置允许跨域的域名,可以使用通配符 '*' 允许所有域访问
9 add_header 'Access-Control-Allow-Origin' * always;
10 # 设置允许的 HTTP 方法
11 add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, DELETE, PUT';
12 # 设置允许的请求头
13 add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, Accept, Origin, X-Requested-With';
14 # 如果需要支持 cookie,可以设置以下 header
15 add_header 'Access-Control-Allow-Credentials' 'true';
16 # 缓存设置
17 add_header Cache-Control no-cache;
18 add_header Cache-Control private;
19 # # 预检请求处理
20 # if ($request_method = OPTIONS) {
21 # return 204;
22 # }
8 23
9 location / { 24 location / {
10 root /usr/share/nginx/html; 25 root /usr/share/nginx/html;
11 index index.html index.htm; 26 index index.html index.htm;
12 try_files $uri $uri/ /index.html; 27 try_files $uri $uri/ /index.html;
28 expires -1s;
29 }
30
31 location /api {
32 # 设置允许跨域的域名,可以使用通配符 '*' 允许所有域访问
33 add_header 'Access-Control-Allow-Origin' * always;
34 # 设置允许的 HTTP 方法
35 add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, DELETE, PUT';
36 # 设置允许的请求头
37 add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, Accept, Origin, X-Requested-With';
38 # 如果需要支持 cookie,可以设置以下 header
39 add_header 'Access-Control-Allow-Credentials' 'true';
40 # 缓存设置
13 add_header Cache-Control no-cache; 41 add_header Cache-Control no-cache;
14 add_header Cache-Control private; 42 add_header Cache-Control private;
15 expires -1s; 43
44 # 使用 rewrite 将 /api 替换为 /new-api
45 rewrite ^/api/(.*)$ /$1 break;
46 proxy_pass http://192.168.6.20:28052;
16 } 47 }
17 48
18 #error_page 404 /404.html;
19 49
20 # redirect server error pages to the static page /50x.html
21 #
22 error_page 500 502 503 504 /50x.html; 50 error_page 500 502 503 504 /50x.html;
23 location = /50x.html { 51 location = /50x.html {
24 root /usr/share/nginx/html; 52 root /usr/share/nginx/html;
25 } 53 }
26
27 # proxy the PHP scripts to Apache listening on 127.0.0.1:80
28 #
29 #location ~ \.php$ {
30 # proxy_pass http://127.0.0.1;
31 #}
32
33 # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
34 #
35 #location ~ \.php$ {
36 # root html;
37 # fastcgi_pass 127.0.0.1:9000;
38 # fastcgi_index index.php;
39 # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
40 # include fastcgi_params;
41 #}
42
43 # deny access to .htaccess files, if Apache's document root
44 # concurs with nginx's one
45 #
46 #location ~ /\.ht {
47 # deny all;
48 #}
49 } 54 }
......
...@@ -4,6 +4,7 @@ import request from "@/utils/request"; ...@@ -4,6 +4,7 @@ import request from "@/utils/request";
4 /** 4 /**
5 * 数据字典 5 * 数据字典
6 **/ 6 **/
7
7 // 编码规则流水号 8 // 编码规则流水号
8 export const getCoderuleList = (params) => request({ 9 export const getCoderuleList = (params) => request({
9 url: `${import.meta.env.VITE_APP_PLAN_BASEURL}/code-rule/list`, 10 url: `${import.meta.env.VITE_APP_PLAN_BASEURL}/code-rule/list`,
...@@ -48,11 +49,11 @@ export const checkDeleteDictionaryScheme = (params) => request({ ...@@ -48,11 +49,11 @@ export const checkDeleteDictionaryScheme = (params) => request({
48 data: params 49 data: params
49 }) 50 })
50 // 分页查询 51 // 分页查询
51 export const getDictionary = (params) => request({ 52 // export const getDictionary = (params) => request({
52 url: `${import.meta.env.VITE_APP_PLAN_BASEURL}/data-dictionary-general/page-list`, 53 // url: `${import.meta.env.VITE_APP_PLAN_BASEURL}/data-dictionary-general/page-list`,
53 method: 'post', 54 // method: 'post',
54 data: params 55 // data: params
55 }) 56 // })
56 // 查询数据字典启用状态的数据 57 // 查询数据字典启用状态的数据
57 export const getDictionaryAll = (params) => request({ 58 export const getDictionaryAll = (params) => request({
58 url: `${import.meta.env.VITE_APP_PLAN_BASEURL}/data-dictionary-general/list-all`, 59 url: `${import.meta.env.VITE_APP_PLAN_BASEURL}/data-dictionary-general/list-all`,
...@@ -161,10 +162,14 @@ export const checkDictionaryData = (params) => request({ ...@@ -161,10 +162,14 @@ export const checkDictionaryData = (params) => request({
161 * DATA-CLASSIFY 数据类别 162 * DATA-CLASSIFY 数据类别
162 * DATA-GRADE 数据级别 163 * DATA-GRADE 数据级别
163 */ 164 */
164 export const getLargeCategoryList = (data) => request({ 165 // export const getLargeCategoryList = (data) => request({
165 url:`${import.meta.env.VITE_APP_API_BASEURL}/data-dict/get-data-list`, 166 // url:`${import.meta.env.VITE_APP_API_BASEURL}/data-dict/get-data-list`,
166 method: 'post', 167 // method: 'post',
167 data 168 // data
169 // })
170 export const getLargeCategoryList = (params) => request({
171 url: `${import.meta.env.VITE_APP_CONFIG_URL}/dict/data/get-by-dictType?dictType=${params.dictType}`,
172 method: 'get',
168 }) 173 })
169 174
170 175
...@@ -355,6 +360,18 @@ export const getCgTemplateClassifyTreeList = (data) => request({ ...@@ -355,6 +360,18 @@ export const getCgTemplateClassifyTreeList = (data) => request({
355 360
356 361
357 /**-------------------------分类分级目录--------------------------------- */ 362 /**-------------------------分类分级目录--------------------------------- */
363 /**
364 * 查询执行guid和目录名称
365 * @param {no params}
366 * @path /cg-dir/get-exec-guid-and-name
367 */
368 export const getExecGuidAndName = () => request({
369 url: `${import.meta.env.VITE_APP_CHECK_BASEURL}/cg-dir/get-exec-guid-and-name`,
370 method: 'post',
371 })
372
373
374
358 375
359 /** 376 /**
360 * 分类分级目录树形列表 377 * 分类分级目录树形列表
...@@ -383,10 +400,10 @@ export const getCgDirFieldPageList = (data) => request({ ...@@ -383,10 +400,10 @@ export const getCgDirFieldPageList = (data) => request({
383 /** 获取字典列表 400 /** 获取字典列表
384 * VITE_APP_PLAN_BASEURL 为环境变量 现在只是mock数据 401 * VITE_APP_PLAN_BASEURL 为环境变量 现在只是mock数据
385 */ 402 */
386 // export const getDictionary = (params) => request({ 403 export const getDictionary = (params) => request({
387 // url: `${import.meta.env.VITE_APP_CHECK_BASEURL}/data-dictionary-general/list-all?state=1`, 404 url: `${import.meta.env.VITE_APP_CHECK_BASEURL}/data-dictionary-general/list-all?state=1`,
388 // method: 'post' 405 method: 'post'
389 // }) 406 })
390 407
391 408
392 409
...@@ -422,7 +439,109 @@ export const getDbDirTablePageList = (data) => request({ ...@@ -422,7 +439,109 @@ export const getDbDirTablePageList = (data) => request({
422 data 439 data
423 }) 440 })
424 441
442 /**
443 * 数据库目录-已有数据库列表
444 * @param {no params}
445 * @path /db-dir/data-source/list
446 */
447 export const getDbDirDataSourceList = (params) => request({
448 url: `${import.meta.env.VITE_APP_CHECK_BASEURL}/db-dir/data-source/list?execGuid=${params.execGuid}`,
449 method: 'post',
450 })
451
452 /**
453 * 获取列表
454 * @param {Object}
455 * @path /db-dir/field/page-list
456 * @returns
457 */
458 export const getDbDirFieldPageList = (data) => request({
459 url: `${import.meta.env.VITE_APP_CHECK_BASEURL}/db-dir/field/page-list`,
460 method: 'post',
461 data
462 })
463
464
465
466 /** 获取已有字段信息 */
467 export const getDsTableStructure= (data) => request({
468 url: `${import.meta.env.VITE_APP_CHECK_BASEURL}/db-dir/field/list-by-table-guid`,
469 method: 'post',
470 data
471 });
472
473 /** 根据选择的连接池获取表列表 */
474 export const getDsTableByDs = (params) => request({
475 url: `${import.meta.env.VITE_APP_CHECK_BASEURL}/db-dir/table/list-by-datasource-guid`,
476 method: 'post',
477 data: params
478 })
479
480 /** 根据数据表获取表结构 */
481 export const getDsData= (params) => request({
482 url: `${import.meta.env.VITE_APP_PLAN_BASEURL}/data-catalog-subject/table-column-list`,
483 method: 'post',
484 data: params
485 });
486
487
488 /**
489 * 数据库新建目录表
490 * @param {Object}
491 * @path /db-dir/table/save
492 */
493 export const saveDbDirTable = (data) => request({
494 url: `${import.meta.env.VITE_APP_CHECK_BASEURL}/db-dir/table/save`,
495 method: 'post',
496 data
497 })
498
499 /**
500 * 数据库目录修改表
501 * @param {Object}
502 * @path /db-dir/table/update
503 */
504 export const updateDbDirTable = (data) => request({
505 url: `${import.meta.env.VITE_APP_CHECK_BASEURL}/db-dir/table/update`,
506 method: 'post',
507 data
508 })
509
510 /**
511 * 生成建表sql语句
512 * @param {Object}
513 * @path /db-dir/table/create-table-sql
514 */
515 export const createTableSql = (data) => request({
516 url: `${import.meta.env.VITE_APP_CHECK_BASEURL}/db-dir/table/create-table-sql`,
517 method: 'post',
518 data
519 })
520
425 521
426 522
427 523
524 /*********************业务规则配置 ************数据库目录************************* */
525
526 /**
527 * 业务规则配置-详情
528 * @param {Object}
529 * @path /biz-rule-config/detail
530 * @returns
531 */
532 export const getBizRuleConfigDetail = (params) => request({
533 url: `${import.meta.env.VITE_APP_CHECK_BASEURL}/biz-rule-config/detail?tableGuid=${params.tableGuid}&execGuid=${params.execGuid}`,
534 method: 'get',
535 })
428 536
537 /**
538 * 业务规则配置-修改
539 * @param {Object}
540 * @path /biz-rule-config/update
541 * @returns
542 */
543 export const updateBizRuleConfig = (data) => request({
544 url: `${import.meta.env.VITE_APP_CHECK_BASEURL}/biz-rule-config/update`,
545 method: 'post',
546 data
547 })
......
...@@ -284,14 +284,340 @@ export const getDbDirTablePageList = { ...@@ -284,14 +284,340 @@ export const getDbDirTablePageList = {
284 databaseChName: '@cword(3, 5)', 284 databaseChName: '@cword(3, 5)',
285 foundMode: '@integer(1, 3)', 285 foundMode: '@integer(1, 3)',
286 state: '@integer(0,2)', 286 state: '@integer(0,2)',
287 isDataAsset: 'Y' 287 isDataAsset: 'Y',
288 description: '@cword(10, 15)',
288 }] 289 }]
289 } 290 }
290 } 291 }
291 } 292 }
292 } 293 }
293 294
295 /**
296 * export const getDbDirDataSourceList = () => request({
297 url: `${import.meta.env.VITE_APP_CHECK_BASEURL}/db-dir/data-source/list`,
298 method: 'post',
299 })
300 "data": [
301 {
302 "tableGuid": "string",
303 "tableName": "string",
304 "tableChName": "string",
305 "databaseGuid": "string",
306 "database": "string",
307 "databaseChName": "string"
308 }
309 ],
310 */
311
312 export const getDbDirDataSourceList = {
313 url: '/mock/db-dir/data-source/list',
314 method: 'post',
315 response: ({body}:{body:any}) => {
316 return {
317 code: '00000',
318 message: '成功',
319 'data|10-30': [{
320 tableGuid: '@guid',
321 tableName: '@cword(3, 5)',
322 tableChName: '@cword(3, 5)',
323 databaseGuid: '@guid',
324 database: '@cword(3, 5)',
325 databaseChName: '@cword(3, 5)'
326 }]
327 }
328 }
329 }
330
331 /**
332 * export const getDsData = (params) => request({
333 url: `${import.meta.env.VITE_APP_CHECK_BASEURL}/db-dir/table/list-by-datasource-guid`,
334 method: 'post',
335 data: params
336 });
337 "data": {
338 "totalRows": 0,
339 "totalPages": 0,
340 "pageSize": 0,
341 "pageIndex": 0,
342 "records": [
343 {
344 "tableGuid": "string",
345 "tableName": "string",
346 "tableChName": "string",
347 "databaseGuid": "string",
348 "database": "string",
349 "databaseChName": "string"
350 }
351 ],
352 */
353
354 export const getDsTableByDs = {
355 url: '/mock/db-dir/table/list-by-datasource-guid',
356 method: 'post',
357 response: ({body}:{body:any}) => {
358 return {
359 code: '00000',
360 message: '成功',
361 'data': {
362 totalRows: '@integer(50, 100)',
363 totalPages: '@integer(1, 10)',
364 pageSize: 10,
365 pageIndex: 1,
366 'records|50-100': [{
367 tableGuid: '@guid',
368 tableName: '@cword(3, 5)',
369 tableChName: '@cword(3, 5)',
370 databaseGuid: '@guid',
371 database: '@cword(3, 5)',
372 databaseChName: '@cword(3, 5)'
373 }]
374 }
375 }
376 }
377 }
378 export const getDsTableStructure = {
379 url: '/mock/db-dir/field/list-by-table-guid',
380 method: 'post',
381 response: ({body}:{body:any}) => {
382 return {
383 code: '00000',
384 message: '成功',
385 'data|2-5': [{
386 guid: '@guid',
387 tableGuid: '@guid',
388 tableName: '@cword(3, 5)',
389 tableChName: '@cword(3, 5)',
390 databaseGuid: '@guid',
391 database: '@cword(3, 5)',
392 databaseChName: '@cword(3, 5)',
393 fieldGuid: '@guid',
394 fieldName: '@cword(3, 5)',
395 fieldChName: '@cword(3, 5)',
396 fieldType: '@cword(3, 5)',
397 fieldLength: '@integer(1, 100)',
398 fieldPrecision: '@integer(1, 100)',
399 dimGuid: '@guid',
400 dictionaryGuid: '@guid',
401 sortValue: '@integer(1, 100)',
402 isPrimary: 'Y',
403 isFk: 'Y',
404 isNotNull: 'Y'
405 }]
406 }
407 }
408 }
409
410 /**
411 * export const getDbDirFieldPageList = (data) => request({
412 url: `${import.meta.env.VITE_APP_CHECK_BASEURL}/db-dir/field/page-list`,
413 method: 'post',
414 data
415 })
416 {
417 "code": "string",
418 "msg": "string",
419 "data": {
420 "totalRows": 0,
421 "totalPages": 0,
422 "pageSize": 0,
423 "pageIndex": 0,
424 "records": [
425 {
426 "guid": "string",
427 "tenantGuid": "string",
428 "cgDirName": "string",
429 "dirGuid": "string",
430 "classifyName": "string",
431 "gradeDetailName": "string",
432 "label": "string",
433 "fieldName": "string",
434 "fieldChName": "string",
435 "tableName": "string",
436 "tableChName": "string",
437 "database": "string",
438 "databaseChName": "string"
439 }
440 ],
441 */
294 442
443 export const getDbDirFieldPageList = {
444 url: '/mock/db-dir/field/page-list',
445 method: 'post',
446 response: ({body}:{body:any}) => {
447 return {
448 code: '00000',
449 message: '成功',
450 'data': {
451 totalRows: '@integer(50, 100)',
452 totalPages: '@integer(1, 10)',
453 pageSize: 10,
454 pageIndex: 1,
455 'records|20-30': [{
456 guid: '@guid',
457 tenantGuid: '@guid',
458 cgDirName: '@cword(3, 5)',
459 dirGuid: '@guid',
460 classifyName: '@cword(3, 5)',
461 gradeDetailName: '@cword(3, 5)',
462 label: '@cword(3, 5)',
463 fieldName: '@cword(3, 5)',
464 fieldChName: '@cword(3, 5)',
465 tableName: '@cword(3, 5)',
466 tableChName: '@cword(3, 5)',
467 database: '@cword(3, 5)',
468 databaseChName: '@cword(3, 5)'
469 }]
470 }
471 }
472 }
473 }
474 /**
475 * export const getBizRuleConfigDetail = (params) => request({
476 url: `${import.meta.env.VITE_APP_CHECK_BASEURL}/biz-rule-config/detail?tableGuid=${params.tableGuid}&execGuid=${params.execGuid}`,
477 method: 'get',
478 })
479 "data": [
480 {
481 "guid": "string",
482 "tenantGuid": "string",
483 "classifyName": "string",
484 "gradeDetailName": "string",
485 "fieldName": "string",
486 "fieldChName": "string",
487 "fieldGuid": "string",
488 "fieldType": "string",
489 "fieldLengthCondition": "string",
490 "fieldPrecision": 0,
491 "dictionaryGuid": "string",
492 "isUnique": "string",
493 "isNotNull": "string",
494 "fieldValueRange": "string"
495 }
496 ],
497 */
498 export const getBizRuleConfigDetail = {
499 url: '/mock/biz-rule-config/detail',
500 method: 'get',
501 response: ({body}:{body:any}) => {
502 return {
503 code: '00000',
504 message: '成功',
505 'data|1-3': [{
506 guid: '@guid',
507 tenantGuid: '@guid',
508 classifyName: '@cword(3, 5)',
509 gradeDetailName: '@cword(3, 5)',
510 fieldName: '@cword(3, 5)',
511 fieldChName: '@cword(3, 5)',
512 fieldGuid: '@guid',
513 fieldType: '@cword(3, 5)',
514 fieldLengthCondition: '>#10',
515 fieldPrecision: '@integer(1, 100)',
516 dictionaryGuid: '@guid',
517 isUnique: 'Y',
518 isNotNull: 'Y',
519 fieldValueRange: '0-100'
520 }]
521 }
522 }
523 }
524 /**
525 * export const updateBizRuleConfig = (data) => request({
526 url: `${import.meta.env.VITE_APP_CHECK_BASEURL}/biz-rule-config/update`,
527 method: 'post',
528 data
529 }){
530 "code": "string",
531 "msg": "string",
532 "data": true,
533 "at": "string",
534 "serviceCode": "string"
535 }
536 */
537 export const updateBizRuleConfig = {
538 url: '/mock/biz-rule-config/update',
539 method: 'post',
540 response: ({body}:{body:any}) => {
541 return {
542 code: '00000',
543 message: '成功',
544 data: true,
545 at: 'string',
546 serviceCode: 'string'
547 }
548 }
549 }
550 /**
551 * /**
552 * 数据库新建目录表
553 * @param {Object}
554 * @path /db-dir/table/save
555 * export const saveDbDirTable = (data) => request({
556 url: `${import.meta.env.VITE_APP_CHECK_BASEURL}/db-dir/table/save`,
557 method: 'post',
558 data
559 })
560 */
561 export const saveDbDirTable = {
562 url: '/mock/db-dir/table/save',
563 method: 'post',
564 response: ({body}:{body:any}) => {
565 return {
566 code: '00000',
567 message: '成功'
568 }
569 }
570 }
571
572 /**
573 * /**
574 * 数据库目录修改表
575 * @param {Object}
576 * @path /db-dir/table/update
577 * export const updateDbDirTable = (data) => request({
578 url: `${import.meta.env.VITE_APP_CHECK_BASEURL}/db-dir/table/update`,
579 method: 'post',
580 data
581 })
582
583 */
584 export const updateDbDirTable = {
585 url: '/mock/db-dir/table/update',
586 method: 'post',
587 response: ({body}:{body:any}) => {
588 return {
589 code: '00000',
590 message: '成功'
591 }
592 }
593 }
295 594
595 /***
596 * /**
597 * 生成建表sql语句
598 * @param {Object}
599 * @path /db-dir/table/create-table-sql
600 * export const createTableSql = (data) => request({
601 url: `${import.meta.env.VITE_APP_CHECK_BASEURL}/db-dir/table/create-table-sql`,
602 method: 'post',
603 data
604 })
605 */
606
607 export const createTableSql = {
608 url: '/mock/db-dir/table/create-table-sql',
609 method: 'post',
610 response: ({body}:{body:any}) => {
611 return {
612 code: '00000',
613 message: '成功',
614 data: 'create table test_table (id int, name varchar(255))'
615 }
616 }
617 }
296 618
297 export default [getCgDirTreeList,getCgDirFieldPageList, getDictionary,saveBizRuleConfig, getDbDirTreeList, getDbDirTablePageList] as MockMethod[] 619 export default [getCgDirTreeList,getCgDirFieldPageList,
620 getDictionary,saveBizRuleConfig, getDbDirTreeList,
621 getDbDirTablePageList,getDbDirDataSourceList,getDsTableByDs,
622 getDsTableStructure,getDbDirFieldPageList,getBizRuleConfigDetail,
623 updateBizRuleConfig,saveDbDirTable,createTableSql,updateDbDirTable] as MockMethod[]
......
...@@ -219,7 +219,7 @@ const routes: RouteRecordRaw[] = [ ...@@ -219,7 +219,7 @@ const routes: RouteRecordRaw[] = [
219 { 219 {
220 path: 'configure-rules', 220 path: 'configure-rules',
221 name: 'configureRules', 221 name: 'configureRules',
222 component: () => import('@/views/data_inventory/configureRules.vue'), 222 component: () => import('@/views/data_inventory/configureRules1.vue'),
223 meta: { 223 meta: {
224 title: '配置业务规则', 224 title: '配置业务规则',
225 sidebar: false, 225 sidebar: false,
...@@ -230,10 +230,43 @@ const routes: RouteRecordRaw[] = [ ...@@ -230,10 +230,43 @@ const routes: RouteRecordRaw[] = [
230 activeMenu: '/data-inventory/classify-grade-catalogue', 230 activeMenu: '/data-inventory/classify-grade-catalogue',
231 }, 231 },
232 }, 232 },
233 {
234 path: 'table-create-existing',
235 name: 'tableCreateExisting',
236 component: () => import('@/views/data_inventory/tableCreateExisting.vue'),
237 meta: {
238 title: '已有表新建',
239 sidebar: false,
240 breadcrumb: false,
241 cache: true,
242 reuse: true
243 },
244 beforeEnter: (to, from) => {
245 if (to.query.domainName) {
246 to.meta.title = `已有表新建(${to.query.domainName})`;
247 to.meta.editPage = true;
248 }
249 }
250 },
251 {
252 path: 'table-create-file',
253 name: 'tableCreateFile',
254 component: () => import('@/views/data_inventory/tableCreateFile.vue'),
255 meta: {
256 title: '根据文件新建',
257 sidebar: false,
258 breadcrumb: false,
259 cache: true,
260 reuse: true
261 },
262 beforeEnter: (to, from) => {
263
264 }
265 },
233 ], 266 ],
234 }, 267 },
235 { 268 {
236 path: '/data-standards/data-dictionary', 269 path: '/data-inventory/data-dictionary',
237 component: Layout, 270 component: Layout,
238 meta: { 271 meta: {
239 title: '数据字典', 272 title: '数据字典',
...@@ -243,7 +276,7 @@ const routes: RouteRecordRaw[] = [ ...@@ -243,7 +276,7 @@ const routes: RouteRecordRaw[] = [
243 { 276 {
244 path: '', 277 path: '',
245 name: 'dictionary', 278 name: 'dictionary',
246 component: () => import('@/views/data_standards/dictionary.vue'), 279 component: () => import('@/views/data_inventory/dictionary.vue'),
247 meta: { 280 meta: {
248 title: '数据字典', 281 title: '数据字典',
249 sidebar: false, 282 sidebar: false,
......
...@@ -101,6 +101,13 @@ const systemRoutes: RouteRecordRaw[] = [ ...@@ -101,6 +101,13 @@ const systemRoutes: RouteRecordRaw[] = [
101 // 动态路由(异步路由、导航栏路由) 101 // 动态路由(异步路由、导航栏路由)
102 const asyncRoutes: Route.recordMainRaw[] = [ 102 const asyncRoutes: Route.recordMainRaw[] = [
103 { 103 {
104 meta:{
105 title: '首页',
106 },
107 children: [
108 ],
109 },
110 {
104 meta: { 111 meta: {
105 title: '数据资产管理', 112 title: '数据资产管理',
106 }, 113 },
......
...@@ -72,9 +72,12 @@ const tableInfo = ref({ ...@@ -72,9 +72,12 @@ const tableInfo = ref({
72 return status == 'Y' ? '有效' : '停用'; 72 return status == 'Y' ? '有效' : '停用';
73 } 73 }
74 }, 74 },
75 { label: "定义说明", width: 360, field: "description", }, 75 { label: "定义说明", width: 140, field: "description", },
76 { 76 {
77 label: "最低安全级别参考", field: "name", width: 140, 77 label: "最低安全级别参考", field: "name", width: 140, getName: (scope) => {
78 let dataGrade = scope.row.dataGrade;
79 return dataGrade + '级';
80 }
78 }, 81 },
79 { label: "修改人", field: "updateUserName", width: 140 }, 82 { label: "修改人", field: "updateUserName", width: 140 },
80 { label: "更新时间", field: "updateTime", width: 180 }, 83 { label: "更新时间", field: "updateTime", width: 180 },
...@@ -386,6 +389,7 @@ const getGradeListData = async () => { ...@@ -386,6 +389,7 @@ const getGradeListData = async () => {
386 389
387 const newCreateClass = () => { 390 const newCreateClass = () => {
388 drawerInfo.value.visible = true; 391 drawerInfo.value.visible = true;
392 classEditFormItems.value[2].options = treeListData.value;
389 drawerInfo.value.header.title = '添加分类'; 393 drawerInfo.value.header.title = '添加分类';
390 classEditFormItems.value.forEach(item => { 394 classEditFormItems.value.forEach(item => {
391 if (item.field == 'status') { 395 if (item.field == 'status') {
...@@ -702,7 +706,7 @@ onMounted(() => { ...@@ -702,7 +706,7 @@ onMounted(() => {
702 style="margin-top:16px; height: calc(100% - 161px)"> 706 style="margin-top:16px; height: calc(100% - 161px)">
703 <div class="tools_btns"> 707 <div class="tools_btns">
704 <el-button v-show="dataShowMethod == 'table'" type="primary" @click="newCreateClass">添加分类</el-button> 708 <el-button v-show="dataShowMethod == 'table'" type="primary" @click="newCreateClass">添加分类</el-button>
705 <el-button v-show="dataShowMethod == 'table'" @click="importClass">导入分类</el-button> 709 <!-- <el-button v-show="dataShowMethod == 'table'" @click="importClass">导入分类</el-button> -->
706 <el-button class="show-change-btn" @click="changeShowMethod">{{ '图形展示' }}</el-button> 710 <el-button class="show-change-btn" @click="changeShowMethod">{{ '图形展示' }}</el-button>
707 </div> 711 </div>
708 <Table v-show="dataShowMethod == 'table'" :tableInfo="tableInfo" /> 712 <Table v-show="dataShowMethod == 'table'" :tableInfo="tableInfo" />
......
...@@ -31,14 +31,14 @@ const getGradeListData = async () => { ...@@ -31,14 +31,14 @@ const getGradeListData = async () => {
31 // 获取数据类别 31 // 获取数据类别
32 const getDataGrade = async () => { 32 const getDataGrade = async () => {
33 const params = { 33 const params = {
34 paramCode: "DATA-CLASSIFY" 34 dictType: "数据类别"
35 } 35 }
36 const res: any = await getLargeCategoryList(params); 36 const res: any = await getLargeCategoryList(params);
37 if (res.code == proxy.$passCode) { 37 if (res.code == proxy.$passCode) {
38 // 提出value和label 作为select的options 38 // 提出value和label 作为select的options
39 const options = res.data.map((item: any) => ({ 39 const options = res.data.map((item: any) => ({
40 label: item.paramName, 40 label: item.label,
41 value: item.paramValue 41 value: item.value
42 })); 42 }));
43 newCreateGradeFormItems.value[1].options = options; 43 newCreateGradeFormItems.value[1].options = options;
44 classDataRef.value = options; 44 classDataRef.value = options;
...@@ -50,14 +50,14 @@ const getDataGrade = async () => { ...@@ -50,14 +50,14 @@ const getDataGrade = async () => {
50 // 获取数据级别 50 // 获取数据级别
51 const getDataClassify = async () => { 51 const getDataClassify = async () => {
52 const params = { 52 const params = {
53 paramCode: "DATA-GRADE" 53 dictType: "数据级别"
54 } 54 }
55 const res: any = await getLargeCategoryList(params); 55 const res: any = await getLargeCategoryList(params);
56 if (res.code == proxy.$passCode) { 56 if (res.code == proxy.$passCode) {
57 // 提出value和label 作为select的options 57 // 提出value和label 作为select的options
58 const options = res.data.map((item: any) => ({ 58 const options = res.data.map((item: any) => ({
59 label: item.paramName, 59 label: item.label,
60 value: item.paramValue 60 value: item.value
61 })); 61 }));
62 newCreateGradeFormItems.value[0].options = options; 62 newCreateGradeFormItems.value[0].options = options;
63 // 这里需要过滤已经在表格中数据级别 63 // 这里需要过滤已经在表格中数据级别
......
...@@ -5,11 +5,13 @@ ...@@ -5,11 +5,13 @@
5 <script lang="ts" setup name="classifyGradeCatalogue"> 5 <script lang="ts" setup name="classifyGradeCatalogue">
6 import { Warning } from "@element-plus/icons-vue"; 6 import { Warning } from "@element-plus/icons-vue";
7 import TableTools from '@/components/Tools/table_tools.vue'; 7 import TableTools from '@/components/Tools/table_tools.vue';
8 import { getCgDirTreeList, getCgDirFieldPageList, getDictionary, saveBizRuleConfig, getDbDirTreeList, getDbDirTablePageList } from '@/api/modules/dataInventory'; 8 import {
9 getCgDirTreeList, getCgDirFieldPageList, getDictionary, saveBizRuleConfig,
10 getDbDirTreeList, getDbDirTablePageList, getDbDirFieldPageList, getExecGuidAndName
11 } from '@/api/modules/dataInventory';
9 import { TableColumnWidth } from "@/utils/enum"; 12 import { TableColumnWidth } from "@/utils/enum";
10 import router from "@/router"; 13 import router from "@/router";
11 14
12
13 const currentPath = ref<string[]>([]); 15 const currentPath = ref<string[]>([]);
14 const { proxy } = getCurrentInstance() as any; 16 const { proxy } = getCurrentInstance() as any;
15 17
...@@ -76,10 +78,23 @@ const getDictionaryList = () => { ...@@ -76,10 +78,23 @@ const getDictionaryList = () => {
76 }) 78 })
77 }; 79 };
78 80
81 // 获取执行guid
82 const execGuidInfo = ref<any>({});
83 const getExecGuid = async () => {
84 const res: any = await getExecGuidAndName();
85 if (res.code == proxy.$passCode) {
86 execGuidInfo.value = res.data;
87 } else {
88 proxy.$ElMessage.error(res.msg);
89 }
90 }
91
92
79 onMounted(() => { 93 onMounted(() => {
80 getCgDirTreeData(); 94 getCgDirTreeData();
81 getCgDirFieldPage(); 95 getCgDirFieldPage();
82 getDictionaryList(); 96 getDictionaryList();
97 getExecGuid();
83 }) 98 })
84 99
85 // 左侧tree-list 100 // 左侧tree-list
...@@ -124,20 +139,20 @@ const searchItemList = ref([ ...@@ -124,20 +139,20 @@ const searchItemList = ref([
124 }, 139 },
125 clearable: true, 140 clearable: true,
126 }, 141 },
127 { 142 // {
128 label: '字段名', 143 // label: '字段名',
129 type: 'select', 144 // type: 'select',
130 maxlength: 19, 145 // maxlength: 19,
131 placeholder: '选择字段名', 146 // placeholder: '选择字段名',
132 field: 'fieldName', 147 // field: 'fieldName',
133 default: '', 148 // default: '',
134 options: [], 149 // options: [],
135 props: { 150 // props: {
136 label: 'name', 151 // label: 'name',
137 value: 'guid', 152 // value: 'guid',
138 }, 153 // },
139 clearable: true, 154 // clearable: true,
140 }, 155 // },
141 { 156 {
142 label: '分类', 157 label: '分类',
143 type: 'select', 158 type: 'select',
...@@ -164,34 +179,7 @@ const searchItemList = ref([ ...@@ -164,34 +179,7 @@ const searchItemList = ref([
164 value: 'guid', 179 value: 'guid',
165 }, 180 },
166 clearable: true, 181 clearable: true,
167 }, {
168 label: '数据库名',
169 type: 'select',
170 maxlength: 19,
171 placeholder: '选择数据库名',
172 field: 'databaseName',
173 default: '',
174 options: [],
175 props: {
176 label: 'name',
177 value: 'guid',
178 },
179 clearable: true,
180 }, 182 },
181 {
182 label: '表名',
183 type: 'select',
184 maxlength: 19,
185 placeholder: '选择表名',
186 field: 'tableName',
187 default: '',
188 options: [],
189 props: {
190 label: 'name',
191 value: 'guid',
192 },
193 clearable: true,
194 }
195 ]) 183 ])
196 const searchParams = ref({}) 184 const searchParams = ref({})
197 const toSearch = (val: any, clear: boolean = false) => { 185 const toSearch = (val: any, clear: boolean = false) => {
...@@ -339,7 +327,7 @@ const batchControlRules = () => { ...@@ -339,7 +327,7 @@ const batchControlRules = () => {
339 327
340 // 数据库目录 328 // 数据库目录
341 // 左侧tree-list 329 // 左侧tree-list
342 const dataBaseTreeInfo = ref({ 330 const dataBaseTreeInfo = ref<any>({
343 id: "data-pickup-tree", 331 id: "data-pickup-tree",
344 filter: true, 332 filter: true,
345 editTreeItem: false, 333 editTreeItem: false,
...@@ -376,9 +364,9 @@ const dataBaseTableInfo = ref({ ...@@ -376,9 +364,9 @@ const dataBaseTableInfo = ref({
376 fixedSelection: true, 364 fixedSelection: true,
377 fields: [ 365 fields: [
378 { label: "序号", type: "index", width: 56, align: "center" }, 366 { label: "序号", type: "index", width: 56, align: "center" },
379 { label: "数据源", field: "databaseChName", width: 140 }, 367 { label: "数据源", field: "cgDirName", width: 140 },
380 { label: "表名称", field: "tableChName", width: 180 }, 368 { label: "表名称", field: "tableName", width: 180 },
381 { label: "数据库表", field: "enName", width: 120 }, 369 { label: "数据库表", field: "tableChName", width: 120 },
382 { 370 {
383 label: "新建方式", field: "foundMode", width: 140, getName: (scope) => { 371 label: "新建方式", field: "foundMode", width: 140, getName: (scope) => {
384 let dataGrade = scope.row.foundMode; 372 let dataGrade = scope.row.foundMode;
...@@ -394,7 +382,7 @@ const dataBaseTableInfo = ref({ ...@@ -394,7 +382,7 @@ const dataBaseTableInfo = ref({
394 }, 382 },
395 { label: "任务修改人", field: "damName", width: 120 }, 383 { label: "任务修改人", field: "damName", width: 120 },
396 { label: "修改时间", field: "updateTime", width: TableColumnWidth.DATETIME }, 384 { label: "修改时间", field: "updateTime", width: TableColumnWidth.DATETIME },
397 { label: "描述", field: "databaseName", width: 120, align: 'center' }, 385 { label: "描述", field: "description", width: 120, align: 'center' },
398 { label: "规划数据资产", field: "isDataAsset", type: 'switch', activeText: '是', inactiveText: '否', activeValue: 'Y', inactiveValue: 'N', switchWidth: 56, width: 120, align: 'center' }, 386 { label: "规划数据资产", field: "isDataAsset", type: 'switch', activeText: '是', inactiveText: '否', activeValue: 'Y', inactiveValue: 'N', switchWidth: 56, width: 120, align: 'center' },
399 387
400 ], 388 ],
...@@ -415,16 +403,15 @@ const dataBaseTableInfo = ref({ ...@@ -415,16 +403,15 @@ const dataBaseTableInfo = ref({
415 console.log('编辑', scope); 403 console.log('编辑', scope);
416 // 路由跳转configure-rules 404 // 路由跳转configure-rules
417 router.push({ 405 router.push({
418 name: 'configure-rules', 406 name: 'configureRules',
419 query: { 407 query: {
420 guid: scope.row.guid, 408 cgDirName: scope.row.cgDirName,
409 tableName: scope.row.tableName,
421 tableChName: scope.row.tableChName, 410 tableChName: scope.row.tableChName,
422 databaseChName: scope.row.databaseChName, 411 guid: scope.row.guid,
423 databaseGuid: scope.row.databaseGuid, 412 description: scope.row.description,
424 tableGuid: scope.row.guid,
425 } 413 }
426 }); 414 });
427
428 } 415 }
429 }, 416 },
430 417
...@@ -646,6 +633,7 @@ const handleClick = (tab: any) => { ...@@ -646,6 +633,7 @@ const handleClick = (tab: any) => {
646 if (tab.props.name === 'second') { 633 if (tab.props.name === 'second') {
647 getDataBaseTreeData(); 634 getDataBaseTreeData();
648 getDataBaseTableData(); 635 getDataBaseTableData();
636 getDataBaseFieldData();
649 } 637 }
650 } 638 }
651 639
...@@ -656,9 +644,12 @@ const getDataBaseTreeData = async () => { ...@@ -656,9 +644,12 @@ const getDataBaseTreeData = async () => {
656 try { 644 try {
657 const res: any = await getDbDirTreeList({}); 645 const res: any = await getDbDirTreeList({});
658 if (res.code == proxy.$passCode) { 646 if (res.code == proxy.$passCode) {
659 res.data.forEach(addGuids); 647 const dataArray = [res.data];
660 dataBaseTreeData.value = res.data; 648 // 遍历并添加 GUIDs
661 dataBaseTreeInfo.value.data = res.data; 649 dataArray.forEach(addGuids);
650 // 更新到绑定的响应式数据
651 dataBaseTreeData.value = dataArray;
652 dataBaseTreeInfo.value.data = dataArray;
662 } else { 653 } else {
663 proxy.$ElMessage.error(res.msg); 654 proxy.$ElMessage.error(res.msg);
664 } 655 }
...@@ -668,8 +659,7 @@ const getDataBaseTreeData = async () => { ...@@ -668,8 +659,7 @@ const getDataBaseTreeData = async () => {
668 dataBaseTreeInfo.value.loading = false; 659 dataBaseTreeInfo.value.loading = false;
669 } 660 }
670 }; 661 };
671 662 // 处理数据,给每个节点添加 GUID
672 // 递归添加 GUID 的函数
673 const addGuids = (node) => { 663 const addGuids = (node) => {
674 if (node.databaseGuid) { 664 if (node.databaseGuid) {
675 node.guid = node.databaseGuid; 665 node.guid = node.databaseGuid;
...@@ -687,6 +677,7 @@ const addGuids = (node) => { ...@@ -687,6 +677,7 @@ const addGuids = (node) => {
687 } 677 }
688 }; 678 };
689 679
680
690 // 获取数据列表 681 // 获取数据列表
691 const dataBaseTableDataList = ref<any>(); 682 const dataBaseTableDataList = ref<any>();
692 const getDataBaseTableData = async (params = {}) => { 683 const getDataBaseTableData = async (params = {}) => {
...@@ -696,6 +687,7 @@ const getDataBaseTableData = async (params = {}) => { ...@@ -696,6 +687,7 @@ const getDataBaseTableData = async (params = {}) => {
696 pageSize: 10, 687 pageSize: 10,
697 databaseGuid: "", 688 databaseGuid: "",
698 isDataAsset: checked.value ? 'Y' : 'N', 689 isDataAsset: checked.value ? 'Y' : 'N',
690 execGuid: execGuidInfo.value.execGuid,
699 }; 691 };
700 const finalParams = { ...dataBaseParams, ...params }; 692 const finalParams = { ...dataBaseParams, ...params };
701 693
...@@ -723,9 +715,96 @@ const dataBaseTablePageChange = (info) => { ...@@ -723,9 +715,96 @@ const dataBaseTablePageChange = (info) => {
723 } 715 }
724 716
725 717
718 // 获取字段信息getDbDirFieldPageList
719 const tableFieldsLoading = ref(false);
720 const tableFieldsData = ref([]);
721 const getDataBaseFieldData = async (params = {}) => {
722 tableFieldsLoading.value = true;
723 const dataBaseParams = {
724 pageIndex: 1,
725 pageSize: 10,
726 tableGuid: "",
727 execGuid: execGuidInfo.value.execGuid,
728 databaseGuid: "",
729 isDataAsset: checked.value ? 'Y' : 'N',
730 };
731 const finalParams = { ...dataBaseParams, ...params };
732
733 const res: any = await getDbDirFieldPageList(finalParams);
734 if (res.code == proxy.$passCode) {
735 tableFieldsData.value = res.data.records;
736 tableFieldsDataInfo.value.data = res.data.records;
737 } else {
738 proxy.$ElMessage.error(res.msg);
739 }
740 tableFieldsLoading.value = false;
741 };
742
743 const tableFieldsDataInfo = ref({
744 id: "data-field-table",
745 multiple: false,
746 fixedSelection: true,
747 fields: [
748 { label: "序号", type: "index", width: 56, align: "center" },
749 { label: "字段名", field: "fieldName", width: 140 },
750 { label: "字段中文名", field: "fieldChName", width: 180 },
751 { label: "表名", field: "tableName", width: 120 },
752 { label: "表中文名", field: "tableChName", width: 140, },
753 { label: "数据库名称", field: "database", width: 120 },
754 { label: "数据库中文名", field: "databaseChName", width: TableColumnWidth.DATETIME },
755 { label: "分类", field: "description", width: 120, align: 'center' },
756 { label: "分级", field: "isDataAsset", width: 120, align: 'center' },
757 { label: "标签", field: "label", width: 120, align: 'center' },
758 ],
759 data: [],
760 showPage: false,
761 page: {
762 // type: "normal",
763 // rows: 0,
764 // ...dataBasePage.value,
765
766 },
767 actionInfo: {
768 show: false,
769 },
770 loading: false
771 });
772
773
726 const showTableOrDatabase = ref(true); 774 const showTableOrDatabase = ref(true);
775 // 定义tableGuid
776 const tableGuid = ref('');
777 const dataBaseGuid = ref('');
778
727 const dataBasenodeClick = (data: any) => { 779 const dataBasenodeClick = (data: any) => {
728 console.log('dataBasenodeClick', data); 780 console.log('dataBasenodeClick', data);
781 if (data.cgDirName) {
782 tableGuid.value = '';
783 dataBaseGuid.value = '';
784 getDataBaseFieldData();
785 getDataBaseTableData();
786 }
787 if (data.databaseGuid) {
788 dataBaseGuid.value = data.databaseGuid;
789 tableGuid.value = '';
790 getDataBaseFieldData({
791 databaseGuid: data.databaseGuid
792 });
793 getDataBaseTableData({
794 databaseGuid: data.databaseGuid
795 });
796 }
797 if (data.tableGuid) {
798 tableGuid.value = data.tableGuid;
799 dataBaseGuid.value = '';
800 getDataBaseFieldData({
801 tableGuid: data.tableGuid
802 });
803 getDataBaseTableData({
804 tableGuid: data.tableGuid
805 });
806 }
807
729 if (data.databaseGuid || data.cgDirName) { 808 if (data.databaseGuid || data.cgDirName) {
730 showTableOrDatabase.value = true; 809 showTableOrDatabase.value = true;
731 return; 810 return;
...@@ -736,9 +815,28 @@ const dataBasenodeClick = (data: any) => { ...@@ -736,9 +815,28 @@ const dataBasenodeClick = (data: any) => {
736 } 815 }
737 } 816 }
738 817
818 const nodeSelectChange = (data: any) => {
819 console.log('nodeSelectChange', data);
820 }
739 821
740 const handleSubjectTableCommand = (command: string) => { 822 const handleSubjectTableCommand = (command: string) => {
741 console.log('handleSubjectTableCommand', command); 823 console.log('handleSubjectTableCommand', command);
824 if (command === 'manualCreate') {
825 router.push({
826 name: 'tableCreateFile',
827 query: {
828 type: 'tableCreateFile'
829 }
830 });
831 } else if (command === 'existingCreate') {
832 // 已有表新建
833 router.push({
834 name: 'tableCreateExisting',
835 query: {
836 execGuid: execGuidInfo.value.execGuid
837 }
838 });
839 }
742 } 840 }
743 841
744 // 文字提示区域 842 // 文字提示区域
...@@ -760,11 +858,103 @@ const setActiveTab = (tab) => { ...@@ -760,11 +858,103 @@ const setActiveTab = (tab) => {
760 activeTab.value = tab; 858 activeTab.value = tab;
761 }; 859 };
762 860
861 // 模拟后端接口
862 const fetchOptionsA = () => {
863 return new Promise((resolve) => {
864 setTimeout(() => {
865 resolve([
866 { label: "选项 A1", value: "a1" },
867 { label: "选项 A2", value: "a2" },
868 ]);
869 }, 500);
870 });
871 };
872
873 const fetchOptionsB = (aValue) => {
874 return new Promise((resolve) => {
875 setTimeout(() => {
876 const data = {
877 a1: [
878 { label: "B1-1", value: "b1" },
879 { label: "B1-2", value: "b2" },
880 ],
881 a2: [
882 { label: "B2-1", value: "b3" },
883 { label: "B2-2", value: "b4" },
884 ],
885 };
886 resolve(data[aValue] || []);
887 }, 500);
888 });
889 };
890
891 const fetchOptionsC = (bValue) => {
892 return new Promise((resolve) => {
893 setTimeout(() => {
894 const data = {
895 b1: [
896 { label: "C1-1", value: "c1" },
897 { label: "C1-2", value: "c2" },
898 ],
899 b3: [
900 { label: "C2-1", value: "c3" },
901 { label: "C2-2", value: "c4" },
902 ],
903 };
904 resolve(data[bValue] || []);
905 }, 500);
906 });
907 };
908
909 const selectedA = ref<any>(null);
910 const selectedB = ref<any>(null);
911 const selectedC = ref<any>(null);
912
913 const optionsA = ref<any>([]);
914 const optionsB = ref<any>([]);
915 const optionsC = ref<any>([]);
916
917 // 初始化加载第一个下拉框的选项
918 const loadOptionsA = async () => {
919 optionsA.value = await fetchOptionsA();
920 };
921
922 // 第一个下拉框值改变时
923 const onAChange = async () => {
924 selectedB.value = null;
925 selectedC.value = null;
926 optionsB.value = [];
927 optionsC.value = [];
928 optionsB.value = await fetchOptionsB(selectedA.value); // 根据 A 动态加载 B 的选项
929 };
930
931 // 第二个下拉框值改变时
932 const onBChange = async () => {
933 selectedC.value = null;
934 optionsC.value = [];
935 optionsC.value = await fetchOptionsC(selectedB.value); // 根据 B 动态加载 C 的选项
936 };
937
938 // 页面加载时初始化 A 的数据
939 loadOptionsA();
940
763 </script> 941 </script>
764 942
765 <template> 943 <template>
766 <div class="classification-template-content"> 944 <div class="classification-template-content">
767 <div class="v-table-tools"> 945 <div class="v-table-tools">
946 <el-select v-model="selectedA" placeholder="选择数据库名" @change="onAChange" style="width: 140px; margin-right: 8px"
947 clearable>
948 <el-option v-for="item in optionsA" :key="item.value" :label="item.label" :value="item.value" />
949 </el-select>
950 <el-select v-model="selectedB" placeholder="选择表名" :disabled="!selectedA" @change="onBChange"
951 style="width: 140px; margin-right: 8px" clearable>
952 <el-option v-for="item in optionsB" :key="item.value" :label="item.label" :value="item.value" />
953 </el-select>
954 <el-select v-model="selectedC" placeholder="选择字段名" :disabled="!selectedB" style="width: 140px;margin-right: 8px"
955 clearable>
956 <el-option v-for="item in optionsC" :key="item.value" :label="item.label" :value="item.value" />
957 </el-select>
768 <TableTools :searchItems="searchItemList" :init="false" :searchId="'files-standard-search'" @search="toSearch" /> 958 <TableTools :searchItems="searchItemList" :init="false" :searchId="'files-standard-search'" @search="toSearch" />
769 </div> 959 </div>
770 <div class="container_wrap full flex"> 960 <div class="container_wrap full flex">
...@@ -774,7 +964,7 @@ const setActiveTab = (tab) => { ...@@ -774,7 +964,7 @@ const setActiveTab = (tab) => {
774 <Tree :treeInfo="treeInfo" @nodeClick="nodeClick" @itemMenuClick="handleTreeItemMenuClick" /> 964 <Tree :treeInfo="treeInfo" @nodeClick="nodeClick" @itemMenuClick="handleTreeItemMenuClick" />
775 </el-tab-pane> 965 </el-tab-pane>
776 <el-tab-pane label="数据库目录" name="second"> 966 <el-tab-pane label="数据库目录" name="second">
777 <Tree :treeInfo="dataBaseTreeInfo" @nodeClick="dataBasenodeClick" /> 967 <Tree :treeInfo="dataBaseTreeInfo" @nodeClick="dataBasenodeClick" @nodeSelectChange='nodeSelectChange' />
778 </el-tab-pane> 968 </el-tab-pane>
779 </el-tabs> 969 </el-tabs>
780 </div> 970 </div>
...@@ -838,7 +1028,9 @@ const setActiveTab = (tab) => { ...@@ -838,7 +1028,9 @@ const setActiveTab = (tab) => {
838 字段信息 1028 字段信息
839 </div> 1029 </div>
840 </div> 1030 </div>
841 <div class="btns-area"> 1031
1032
1033 <div class="btns-area" v-if="!tableGuid && activeTab === 'table'">
842 <div class="left-btns"> 1034 <div class="left-btns">
843 <div class="dropdown_btn"> 1035 <div class="dropdown_btn">
844 <el-dropdown popper-class="table-create-menu" @command="handleSubjectTableCommand" 1036 <el-dropdown popper-class="table-create-menu" @command="handleSubjectTableCommand"
...@@ -878,9 +1070,12 @@ const setActiveTab = (tab) => { ...@@ -878,9 +1070,12 @@ const setActiveTab = (tab) => {
878 <el-checkbox v-model="checked" label="仅看规划数据资产表" size="large" @change="changeCheck" /> 1070 <el-checkbox v-model="checked" label="仅看规划数据资产表" size="large" @change="changeCheck" />
879 </div> 1071 </div>
880 </div> 1072 </div>
881 <div class="table_panel_wrap_database"> 1073 <div class="table_panel_wrap_database" v-if="!tableGuid && activeTab === 'table'">
882 <Table :tableInfo="dataBaseTableInfo" @tablePageChange="dataBaseTablePageChange" /> 1074 <Table :tableInfo="dataBaseTableInfo" @tablePageChange="dataBaseTablePageChange" />
883 </div> 1075 </div>
1076 <div class="table_field" v-if="tableGuid || activeTab === 'word'">
1077 <Table :tableInfo="tableFieldsDataInfo" :loading="tableFieldsLoading" />
1078 </div>
884 </div> 1079 </div>
885 <Drawer :drawerInfo="drawerInfo" @drawerBtnClick="drawerBtnClick" class="v-drawer" /> 1080 <Drawer :drawerInfo="drawerInfo" @drawerBtnClick="drawerBtnClick" class="v-drawer" />
886 1081
...@@ -898,6 +1093,8 @@ const setActiveTab = (tab) => { ...@@ -898,6 +1093,8 @@ const setActiveTab = (tab) => {
898 flex-direction: column; 1093 flex-direction: column;
899 1094
900 .v-table-tools { 1095 .v-table-tools {
1096 display: flex;
1097 align-items: center;
901 padding: 8px 12px; 1098 padding: 8px 12px;
902 } 1099 }
903 1100
...@@ -911,6 +1108,11 @@ const setActiveTab = (tab) => { ...@@ -911,6 +1108,11 @@ const setActiveTab = (tab) => {
911 border-right: 1px solid #d9d9d9; 1108 border-right: 1px solid #d9d9d9;
912 box-shadow: none; 1109 box-shadow: none;
913 1110
1111 :deep(.el-tabs__item) {
1112 padding: 0 8px;
1113 }
1114
1115
914 .v-tabs { 1116 .v-tabs {
915 height: 100%; 1117 height: 100%;
916 1118
...@@ -922,11 +1124,11 @@ const setActiveTab = (tab) => { ...@@ -922,11 +1124,11 @@ const setActiveTab = (tab) => {
922 } 1124 }
923 } 1125 }
924 1126
925 :deep(.v-tabs) { 1127 // :deep(.v-tabs) {
926 .el-tabs__item { 1128 // .el-tabs__item {
927 padding: 0 10px; 1129 // padding: 0 12px;
928 } 1130 // }
929 } 1131 // }
930 1132
931 .tree_panel { 1133 .tree_panel {
932 height: 100%; 1134 height: 100%;
...@@ -1019,6 +1221,13 @@ const setActiveTab = (tab) => { ...@@ -1019,6 +1221,13 @@ const setActiveTab = (tab) => {
1019 overflow: visible; 1221 overflow: visible;
1020 } 1222 }
1021 1223
1224 .table_field {
1225 width: 100%;
1226 height: calc(100% - 180px);
1227 min-height: 210px;
1228 overflow: visible;
1229 }
1230
1022 /* 外层容器 */ 1231 /* 外层容器 */
1023 .tab-btn { 1232 .tab-btn {
1024 display: flex; 1233 display: flex;
......
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
1 <script lang="ts" setup name="uploadExcelFile">
2 import { ref } from "vue";
3 import { ElMessage, ElMessageBox, ElTable } from "element-plus";
4 import { TableColumnWidth } from '@/utils/enum';
5 import Moment from 'moment';
6 import { calcColumnWidth } from "@/utils/index";
7 import * as XLSX from 'xlsx';
8 import {
9 getImageContent
10 } from '@/api/modules/queryService';
11 const props = defineProps({
12 noUpload: {
13 type: Boolean,
14 default: false
15 }
16 })
17 const emits = defineEmits([
18 "fileDataChange"
19 ]);
20 const noUpload = computed(() => props.noUpload)
21 const sheetList: any = ref([]);
22 const fileFormRef = ref();
23 /** 文件上传表单配置。 */
24 const fileFormItems: any = ref([
25 {
26 label: '选择文件上传',
27 tip: '支持扩展名:xlsx、xls,文件大小不超过20MB',
28 type: 'upload-file',
29 accept: '.xlsx, .xls',
30 limit: 1,
31 limitSize: 20,
32 isExcel: true,
33 required: true,
34 default: [],
35 field: 'file',
36 },
37 {
38 label: '选择sheet页',
39 type: 'select',
40 placeholder: '请选择',
41 field: 'sheet',
42 default: '',
43 options: sheetList,
44 required: true,
45 visible: true
46 },
47 ]);
48 const fileFormRules = ref({
49 file: [{
50 validator: (rule: any, value: any, callback: any) => {
51 if (!value?.length) {
52 callback(new Error('请上传文件'))
53 } else {
54 callback();
55 }
56 }, trigger: 'change'
57 }],
58 sheet: [
59 { required: true, trigger: 'change', message: "请选择sheet页" }
60 ],
61 });
62 const uploadFileChange = (file) => {
63 fileTableFields.value = [];
64 fileTableData.value = [];
65 sheetList.value = [];
66 if (!file.length) {
67 fileTableFields.value = [];
68 fileTableData.value = [];
69 sheetList.value = [];
70 fileFormItems.value[1].options = sheetList.value;
71 fileFormItems.value[1].default = '';
72 fileFormItems.value[0].default = file;
73 fileWb.value = {};
74 emits("fileDataChange", fileTableFields.value, file, '', fileTableData.value);
75 return;
76 }
77 let fileRaw = file[0].file;
78 fileFieldLoading.value = true;
79 fileRaw.arrayBuffer().then((f) => {
80 const wb = XLSX.read(f, {
81 raw: false, cellDates: true
82 });
83 fileWb.value = wb;
84 console.log(wb);
85 sheetList.value = wb.SheetNames?.map(s => {
86 return {
87 value: s,
88 label: s
89 }
90 }) || [];
91 fileFormItems.value[1].options = sheetList.value;
92 fileFormItems.value[1].default = wb.SheetNames[0];
93 fileFormItems.value[0].default = file;
94 const sheet = wb.Sheets[wb.SheetNames[0]];
95 const json: any[] = XLSX.utils.sheet_to_json(sheet, { header: 1 });
96 if (json.length == 0) {
97 fileTableFields.value = [];
98 fileTableData.value = [];
99 } else {
100 fileTableFields.value = json[0]?.map((j, index) => {
101 return {
102 index: index,
103 enName: j + '',
104 chName: j + '',
105 dataType: 'varchar'
106 }
107 }) || [];
108 if (json.length > 1) {
109 fileTableData.value = json.slice(1, 51).map((info, row) => {
110 let object = {};
111 json[0].forEach((name, col) => {
112 if (info[col] === "" || info[col] == null) {
113 object[name] = info[col];
114 } else {
115 var cellRef = XLSX.utils.encode_cell({ r: row + 1, c: col });
116 var cell = sheet[cellRef];
117 object[name] = cell.w || info[col];
118 let isNum = cell.t == 'n';
119 if (isNum && fileTableFields.value[col].dataType != 'int') {
120 fileTableFields.value[col].dataType = 'int';
121 }
122 }
123 });
124 return object;
125 });
126 } else {
127 fileTableData.value = [];
128 }
129 }
130 fileFieldLoading.value = false;
131 emits("fileDataChange", fileTableFields.value, file, wb.SheetNames[0], fileTableData.value);
132 });
133 }
134 /** 切换sheet页 */
135 const handleSelectChange = (val, row, info) => {
136 if (!val) {
137 return;
138 }
139 let wb = fileWb.value;
140 const sheet = wb.Sheets[val];
141 const json: any[] = XLSX.utils.sheet_to_json(sheet, { header: 1 });
142 if (json.length == 0) {
143 fileTableFields.value = [];
144 fileTableData.value = [];
145 } else {
146 fileTableFields.value = json[0]?.map((j, index) => {
147 return {
148 index: index,
149 enName: j + '',
150 chName: j + '',
151 dataType: 'varchar'
152 }
153 }) || [];
154 if (json.length > 1) {
155 fileTableData.value = json.slice(1, 51).map((info, row) => {
156 let object = {};
157 json[0].forEach((name, col) => {
158 if (info[col] === "" || info[col] == null) {
159 object[name] = info[col];
160 } else {
161 var cellRef = XLSX.utils.encode_cell({ r: row + 1, c: col });
162 var cell = sheet[cellRef];
163 object[name] = cell.w || info[col];
164 let isNum = cell.t == 'n';
165 if (isNum && fileTableFields.value[col].dataType != 'int') {
166 fileTableFields.value[col].dataType = 'int';
167 }
168 }
169 });
170 return object;
171 });
172 } else {
173 fileTableData.value = [];
174 }
175 }
176 emits("fileDataChange", fileTableFields.value, info.file, val, fileTableData.value);
177 }
178 /** 上传文件之后解析出字段和数据 */
179 const fileFieldLoading = ref(false);
180
181 const fileTableFields: any = ref([]);
182
183 const fileTableData: any = ref([]);
184
185 /** 解析后的excel文件流信息,切换sheet页选择时使用。 */
186 const fileWb: any = ref({});
187 const getTextAlign = (field) => {
188 if (field.dataType === 'decimal' || field.dataType === 'int') {
189 return 'right';
190 }
191 return 'left'
192 }
193 /** otherWidth表示使用标题宽度时添加标题排序图标等宽度 */
194 const calcTableColumnWidth = (data: any[], prop, title, otherWidth = 0) => {
195 let d: any[] = [];
196 data.forEach((dt) => d.push(dt[prop]));
197 return calcColumnWidth(
198 d,
199 title,
200 {
201 fontSize: 14,
202 fontFamily: "SimSun",
203 },
204 {
205 fontSize: 14,
206 fontFamily: "SimSun",
207 },
208 otherWidth
209 );
210 };
211 /** 每列字段对应的列宽计算结果。 */
212 const originTableFieldColumn = ref({});
213 watch(
214 fileTableData,
215 (val: any[], oldVal) => {
216 if (!fileTableFields.value?.length) {
217 originTableFieldColumn.value = {};
218 return;
219 }
220 originTableFieldColumn.value = {};
221 fileTableFields.value.forEach((field, index) => {
222 originTableFieldColumn.value[field.enName] = calcTableColumnWidth(
223 val?.slice(0, 20) || [],
224 field.enName,
225 field.chName,
226 24
227 );
228 });
229 },
230 {
231 deep: true,
232 }
233 );
234 const formatterPreviewDate = (row, info) => {
235 let enName = info.enName;
236 let v = row[enName];
237 if (v === 0) {
238 return v;
239 }
240 if (!v) {
241 return v || '--';
242 }
243 if (info.dataType === 'datetime') {
244 return Moment(v).format('YYYY-MM-DD HH:mm:ss');
245 }
246 if (info.dataType === 'date') {
247 if (isNaN(<any>(new Date(v)))) {
248 return Moment(parseInt(v)).format('YYYY-MM-DD');
249 } else {
250 return Moment(v).format('YYYY-MM-DD');
251 }
252 }
253 return v;
254 };
255 const setFormValue = (v) => {
256 fileFormItems.value[1].default = v.sheetName || "";
257 let url = v.file?.[0]?.url;
258 if (fileFormItems.value[0].default?.[0]?.url !== url) {
259 fileFormItems.value[0].default = v.file || [];
260 //获取文件流去解析出数据和字段。
261 fileFieldLoading.value = true;
262 fileTableFields.value = [];
263 fileTableData.value = [];
264 getImageContent(url).then((res: any) => {
265 if (res && !res.msg) {
266 let urlNames = url.split('/');
267 let name = urlNames.at(-1);
268 let reader = new FileReader();
269 reader.onload = function (e) {
270 if (!e?.target) {
271 fileFieldLoading.value = false;
272 return;
273 }
274 let data = new Uint8Array(<any>e.target.result);
275 const wb = XLSX.read(data, { type: 'array', raw: false, cellDates: true });
276 fileWb.value = wb;
277 console.log(wb);
278 sheetList.value = wb.SheetNames?.map(s => {
279 return {
280 value: s,
281 label: s
282 }
283 }) || [];
284 fileFormItems.value[1].options = sheetList.value;
285 fileFormItems.value[1].default = v.sheetName || "";
286 const sheet = wb.Sheets[v.sheetName];
287 const json: any[] = XLSX.utils.sheet_to_json(sheet, { header: 1 });
288 if (json.length == 0) {
289 fileTableFields.value = [];
290 fileTableData.value = [];
291 } else {
292 fileTableFields.value = json[0]?.map((j, index) => {
293 return {
294 index: index,
295 enName: j + '',
296 chName: j + '',
297 dataType: 'varchar'
298 }
299 }) || [];
300 if (json.length > 1) {
301 fileTableData.value = json.slice(1, 51).map((info, row) => {
302 let object = {};
303 json[0].forEach((name, col) => {
304 if (info[col] === "" || info[col] == null) {
305 object[name] = info[col];
306 } else {
307 var cellRef = XLSX.utils.encode_cell({ r: row + 1, c: col });
308 var cell = sheet[cellRef];
309 object[name] = cell.w || info[col];
310 let isNum = cell.t == 'n';
311 if (isNum && fileTableFields.value[col].dataType != 'int') {
312 fileTableFields.value[col].dataType = 'int';
313 }
314 }
315 });
316 return object;
317 });
318 } else {
319 fileTableData.value = [];
320 }
321 }
322 fileFieldLoading.value = false;
323 };
324 reader.readAsArrayBuffer(res);
325 } else {
326 res?.msg && ElMessage.error(res?.msg);
327 }
328 })
329 }
330 }
331 defineExpose({
332 fileFormRef,
333 setFormValue
334 });
335 </script>
336 <template>
337 <div class="upload-main">
338 <div class="header-bg-title">选择文件上传</div>
339 <div class="form-main">
340 <Form ref="fileFormRef" :itemList="fileFormItems" :noUpload="noUpload" formId="file-form" :rules="fileFormRules"
341 @uploadFileChange="uploadFileChange" @select-change="handleSelectChange" />
342 </div>
343 <div class="header-bg-title">预览文件
344 <div class="preview-data-totals">
345 <span>该页面仅显示</span>
346 <span class="fontC-4fa1a4"> 50 </span>
347 <span>条数据</span>
348 </div>
349 </div>
350 <div class="table-main">
351 <el-table ref="tableRef" v-loading="fileFieldLoading" v-show="fileTableFields.length" :data="fileTableData"
352 :highlight-current-row="true" stripe border tooltip-effect="light" height="100%" row-key="guid"
353 :style="{ width: '100%', height: '100%' }">
354 <template v-for="(item, index) in (fileTableFields || [])">
355 <el-table-column :label="item.chName" :width="item.dataType === 'datetime'
356 ? TableColumnWidth.DATETIME
357 : item.dataType === 'date'
358 ? TableColumnWidth.DATE
359 : originTableFieldColumn[item.enName]
360 " :align="getTextAlign(item)" :header-align="getTextAlign(item)"
361 :formatter="(row) => formatterPreviewDate(row, item)" :show-overflow-tooltip="true">
362 </el-table-column>
363 </template>
364 </el-table>
365 <div v-show="!fileTableFields.length" class="empty-content">
366 <img src="../../../assets/images/empty-data.png" :style="{ width: '168px', height: '96px' }" />
367 <div class="empty-text">暂无数据</div>
368 </div>
369 </div>
370 </div>
371 </template>
372 <style lang="scss" scoped>
373 .upload-main {
374 height: calc(100% - 96px);
375 }
376
377 .header-bg-title {
378 margin: 16px 16px 0px;
379 background: #F5F5F5;
380 padding-left: 16px;
381 height: 48px;
382 font-size: 14px;
383 color: #212121;
384 letter-spacing: 0;
385 line-height: 21px;
386 font-weight: 600;
387 display: flex;
388 align-items: center;
389 position: relative;
390
391 .preview-data-totals {
392 position: absolute;
393 right: 16px;
394 line-height: 32px;
395 font-size: 14px;
396 color: #666666;
397 font-weight: 400;
398 }
399
400 .fontC-4fa1a4 {
401 color: var(--el-color-primary);
402 }
403 }
404
405 .form-main {
406 border: 1px solid #d9d9d9;
407 margin: 0px 16px;
408 padding: 16px 16px 0px 16px;
409 height: 125px;
410
411 .dialog-form-inline {
412 align-items: flex-start;
413 }
414
415 :deep(.el-form) {
416 .item-label {
417 width: 100%;
418 }
419
420 .el-select {
421 max-width: 300px;
422 }
423 }
424 }
425
426 .table-main {
427 height: calc(100% - 253px);
428 border: 1px solid #d9d9d9;
429 margin: 0px 16px 16px 16px;
430 padding: 16px;
431 }
432
433 .empty-content {
434 display: flex;
435 align-items: center;
436 justify-content: center;
437 height: 100%;
438 width: 100%;
439 flex-direction: column;
440
441 .empty-text {
442 font-size: 14px;
443 color: #b2b2b2;
444 }
445 }
446
447 :deep(.upload-file .el-upload-list) {
448 .el-upload-list__item {
449 &:first-child {
450 display: flex;
451 }
452
453 display: none
454 }
455 }
456 </style>
...\ No newline at end of file ...\ No newline at end of file
...@@ -3,85 +3,423 @@ ...@@ -3,85 +3,423 @@
3 </route> 3 </route>
4 4
5 <script lang="ts" setup name="configureRules"> 5 <script lang="ts" setup name="configureRules">
6 import { TableColumnWidth } from '@/utils/enum'; 6 import { ref } from "vue";
7 7 import router from "@/router";
8 const dataBasePage = ref({ 8 import { getBizRuleConfigDetail, updateBizRuleConfig } from '@/api/modules/dataInventory'
9 limit: 10, 9
10 curr: 1, 10 const { proxy } = getCurrentInstance() as any;
11 sizes: [ 11 const bizRuleConfigData = ref<any>()
12 { label: "10", value: 10 }, 12 const getBizRuleConfigDetailData = async () => {
13 { label: "20", value: 20 }, 13 const params = {
14 { label: "100", value: 100 }, 14 tableGuid: router.currentRoute.value.query.guid,
15 { label: "150", value: 150 }, 15 execGuid: router.currentRoute.value.query.execGuid
16 { label: "200", value: 200 }, 16 }
17 ], 17 const res: any = await getBizRuleConfigDetail(params)
18 }); 18 if (res.code === proxy.$passCode) {
19 19 bizRuleConfigData.value = res.data
20 const dataBaseTableInfo = ref({ 20 // 每条数据添加一个isEdit: false 属性,用于判断是否进入编辑模式
21 id: "data-base-table", 21 bizRuleConfigData.value.forEach((item: any) => {
22 multiple: false, 22 item.isEdit = false
23 fixedSelection: true, 23 })
24 fields: [ 24 tableData.value = bizRuleConfigData.value
25 { label: "序号", type: "index", width: 56, align: "center" }, 25 } else {
26 { label: "数据源", field: "databaseChName", width: 140 }, 26 proxy.$message.error(res.msg)
27 { label: "表名称", field: "tableChName", width: 180 }, 27 }
28 { label: "数据库表", field: "enName", width: 120 }, 28 }
29 { 29
30 label: "新建方式", field: "foundMode", width: 140, getName: (scope) => { 30 onMounted(() => {
31 let dataGrade = scope.row.foundMode; 31 getBizRuleConfigDetailData()
32 return dataGrade == 1 ? '根据文件新建' : '已有表新建'; 32 })
33
34
35 const tableData1 = ref([
36 {
37 cgDirName: router.currentRoute.value.query.cgDirName,
38 tableName: router.currentRoute.value.query.tableName,
39 tableChName: router.currentRoute.value.query.tableChName,
40 description: router.currentRoute.value.query.description,
41 },
42 ])
43 // 表格数据
44 const tableData = ref()
45
46 // 配置哪些字段可编辑
47 const editableFields = {
48 fieldName: true, // 字段中文名可编辑
49 length: true, // 长度可编辑
50 isUnique: true, // 数据是否唯一可编辑
51 fieldPrecision: true, // 精度可编辑
52 dictionaryGuid: true, // 关联字典可编辑
53 }
54
55 const tableFieldsLoading = ref(false)
56 const selectedRows = ref([]);
57 // 监听选中行
58 const selectionFieldsChange = (selection) => {
59 console.log('selection', selection)
60 selectedRows.value = selection;
61 };
62
63 // 上移功能
64 const moveUp = () => {
65 // 1. 找到选中行在 tableData 中的索引
66 const selectedIds = selectedRows.value.map((row: any) => row.id);
67
68 // 2. 遍历选中行,按顺序上移
69 for (let i = 0; i < tableData.value.length; i++) {
70 const currentRow = tableData.value[i];
71
72 // 如果当前行被选中,且不是第一行,则交换位置
73 if (selectedIds.includes(currentRow.id) && i > 0) {
74 const previousRow = tableData.value[i - 1];
75
76 // 如果上一行没有被选中,交换位置
77 if (!selectedIds.includes(previousRow.id)) {
78 [tableData.value[i], tableData.value[i - 1]] = [tableData.value[i - 1], tableData.value[i]];
33 } 79 }
34 }, 80 }
35 { 81 }
36 label: "状态", field: "state", type: 'tag', width: 180, getName: (scope) => { 82 };
37 let status = scope.row.state; 83
38 // 0 草稿中 1 已建表 2 已有默认表 84 // 下移功能
39 return status == 0 ? '草稿中' : status == 1 ? '已建表' : '已有默认表'; 85 const moveDown = () => {
86 // 1. 找到选中行在 tableData 中的索引
87 const selectedIds = selectedRows.value.map((row: any) => row.id);
88
89 // 2. 遍历选中行,倒序下移
90 for (let i = tableData.value.length - 1; i >= 0; i--) {
91 const currentRow = tableData.value[i];
92
93 // 如果当前行被选中,且不是最后一行,则交换位置
94 if (selectedIds.includes(currentRow.id) && i < tableData.value.length - 1) {
95 const nextRow = tableData.value[i + 1];
96
97 // 如果下一行没有被选中,交换位置
98 if (!selectedIds.includes(nextRow.id)) {
99 [tableData.value[i], tableData.value[i + 1]] = [tableData.value[i + 1], tableData.value[i]];
40 } 100 }
41 }, 101 }
42 { label: "任务修改人", field: "damName", width: 120 }, 102 }
43 { label: "修改时间", field: "updateTime", width: TableColumnWidth.DATETIME }, 103 };
44 { label: "描述", field: "databaseName", width: 120, align: 'center' }, 104
45 { 105 // 编辑行
46 label: "规划数据资产", field: "isDataAsset", type: 'switch', activeText: '是', inactiveText: '否', activeValue: 'Y', 106 const editRow = (row) => {
47 inactiveValue: 'N', switchWidth: 56, width: 120, align: 'center' 107 if (!row.isEdit) {
48 }, 108 const [symbol, value] = row.fieldLengthCondition.split('#');
49 109 row.lengthSymbol = symbol; // 初始化符号部分
50 ], 110 row.lengthValue = value; // 初始化数值部分
51 data: [], 111 row.isEdit = true; // 进入编辑模式
52 page: { 112 }
53 type: "normal", 113 };
54 rows: 0, 114
55 ...dataBasePage.value, 115 // 保存数据
116 const saveRow = (row) => {
117 row.fieldLengthCondition = `${row.lengthSymbol}#${row.lengthValue}`;
118 row.isEdit = false
119 }
120
121 // 删除行
122 const deleteRow = (index) => {
123 tableData.value.splice(index, 1)
124 }
125 // 批量删除功能
126 const batchDelete = () => {
127 selectedRows.value.forEach((row: any) => {
128 const index = tableData.value.findIndex((item) => item.id === row.id);
129 if (index !== -1) tableData.value.splice(index, 1);
130 });
131 selectedRows.value = [];
132 };
133 const data = [
134 {
135 value: '1',
136 label: 'Level one 1',
137 children: [
138 {
139 value: '1-1',
140 label: 'Level two 1-1',
141 children: [
142 {
143 value: '1-1-1',
144 label: 'Level three 1-1-1',
145 },
146 ],
147 },
148 ],
149 },
150 {
151 value: '2',
152 label: 'Level one 2',
153 children: [
154 {
155 value: '2-1',
156 label: 'Level two 2-1',
157 children: [
158 {
159 value: '2-1-1',
160 label: 'Level three 2-1-1',
161 },
162 ],
163 },
164 {
165 value: '2-2',
166 label: 'Level two 2-2',
167 children: [
168 {
169 value: '2-2-1',
170 label: 'Level three 2-2-1',
171 },
172 ],
173 },
174 ],
56 }, 175 },
57 actionInfo: { 176 {
58 label: "操作", 177 value: '3',
59 type: "btn", 178 label: 'Level one 3',
60 width: 300, 179 children: [
61 fixed: 'right', 180 {
62 btns: [ 181 value: '3-1',
182 label: 'Level two 3-1',
183 children: [
184 {
185 value: '3-1-1',
186 label: 'Level three 3-1-1',
187 },
188 ],
189 },
63 { 190 {
64 label: "配置业务规则", value: "edit", click: (scope) => { 191 value: '3-2',
65 console.log('编辑', scope); 192 label: 'Level two 3-2',
66 // 路由跳转configure-rules 193 children: [
194 {
195 value: '3-2-1',
196 label: 'Level three 3-2-1',
197 },
198 ],
199 },
200 ],
201 },
202 ]
67 203
204 const saveData = async () => {
68 205
69 } 206 /**入参
70 }, 207 * "guid": "string",
208 "fieldGuid": "string",
209 "fieldLengthCondition": "string",
210 "fieldPrecision": 0,
211 "dictionaryGuid": "string",
212 "isUnique": "string",
213 "isNotNull": "string",
214 "fieldValueRange": "string"
215 */
216 const params = tableData.value.map((item: any) => {
217 return {
218 guid: item.guid,
219 fieldGuid: item.fieldGuid,
220 fieldLengthCondition: item.fieldLengthCondition,
221 fieldPrecision: item.fieldPrecision,
222 dictionaryGuid: item.dictionaryGuid,
223 isUnique: item.isUnique,
224 isNotNull: item.isNotNull,
225 fieldValueRange: item.fieldValueRange
226 }
227 })
228 const res: any = await updateBizRuleConfig(params)
229 if (res.code === proxy.$passCode) {
230 proxy.$message.success('修改配置规则成功!')
231 router.back()
232 } else {
233 proxy.$message.error(res.msg)
234 }
235 }
71 236
72 { 237 const cancel = () => {
73 label: "编辑表结构", value: "copy", click: (scope) => { 238 router.back()
74 console.log('复制', scope); 239 }
75 }
76 }
77 ]
78 240
79 },
80 loading: false
81 });
82 </script> 241 </script>
83 <template> 242 <template>
84 <div class="table_panel_wrap"> 243 <div class="configure-rules">
85 <Table :tableInfo="dataBaseTableInfo" /> 244 <div class="table_panel_wrap">
245 <el-table :data="tableData1" :highlight-current-row="true" stripe border height="100%" row-key="guid"
246 tooltip-effect="light" :style="{
247 width: '100%',
248 'max-height': 'calc(100% - 16px)',
249 display: 'inline-block',
250 }">
251 <el-table-column prop="cgDirName" label="数据源" width="180" />
252 <el-table-column prop="tableName" label="表名称" width="180" />
253 <el-table-column prop="tableChName" label="数据库表" width="280" />
254 <el-table-column prop="description" label="描述" width="180" show-overflow-tooltip />
255 </el-table>
256 </div>
257 <div class="btn-area">
258 <el-button @click="moveUp">上移</el-button>
259 <el-button @click="moveDown">下移</el-button>
260 <el-button @click="batchDelete">批量删除</el-button>
261 </div>
262 <div class="bottom_table">
263 <el-table :data="tableData" v-loading="tableFieldsLoading" :highlight-current-row="true" stripe border
264 height="100%" row-key="guid" @selection-change="selectionFieldsChange" tooltip-effect="light" :style="{
265 width: '100%',
266 'max-height': 'calc(100% - 16px)',
267 display: 'inline-block',
268 }">
269 <el-table-column type="selection" :width="32" align="center" />
270 <!-- 排序列(不可编辑) -->
271 <el-table-column prop="index" label="排序" width="80" align="center" />
272 <!-- 字段中文名(不可编辑)fieldChName -->
273 <el-table-column prop="fieldName" label="字段中文名" width="120">
274 <template #default="scope">
275 {{ scope.row.fieldName ? scope.row.fieldName : '--' }}
276 </template>
277 </el-table-column>
278 <!-- 字段英文名(不可编辑) -->
279 <el-table-column prop="fieldEnglish" label="字段英文名" width="120">
280 <template #default="scope">
281 {{ scope.row.fieldEnglish ? scope.row.fieldEnglish : '--' }}
282 </template>
283 </el-table-column>
284 <!-- 分类(不可编辑)classifyName -->
285 <el-table-column prop="fieldEnglish" label="分类" width="120">
286 <template #default="scope">
287 {{ scope.row.fieldEnglish ? scope.row.fieldEnglish : '--' }}
288 </template>
289 </el-table-column>
290 <!-- 分级(不可编辑) -->
291 <el-table-column prop="gradeDetailName" label="分级" width="120" align="center">
292 <template #default="scope">
293 {{ scope.row.gradeDetailName ? scope.row.gradeDetailName : '--' }}
294 </template>
295 </el-table-column>
296 <!-- 字段类型fieldType (不可编辑) -->
297 <el-table-column prop="fieldType" label="字段类型" width="150" align="center">
298 <template #default="scope">
299 {{ scope.row.fieldType ? scope.row.fieldType : '--' }}
300 </template>
301 </el-table-column>
302
303 <!-- 长度列 fieldLengthCondition: '>#10',-->
304 <el-table-column prop="fieldLengthCondition" label="长度" width="240" align="center">
305 <template #default="scope">
306 <span v-if="!scope.row.isEdit">{{ scope.row.fieldLengthCondition || '--' }}</span>
307 <div v-else>
308 <el-select v-model="scope.row.lengthSymbol" placeholder="请选择" style="width: 50%;margin-right: 8px;">
309 <el-option label="大于" value=">"></el-option>
310 <el-option label="等于" value="="></el-option>
311 <el-option label="小于" value="<"></el-option>
312 </el-select>
313 <el-input v-model="scope.row.lengthValue" placeholder="请输入" style="width: 45%;" />
314 </div>
315 </template>
316 </el-table-column>
317
318 <!-- 精度列 -->
319 <!-- <el-table-column prop="fieldPrecision" label="精度" width="240" align="center">
320 <template #default="scope">
321 <span v-if="!scope.row.isEdit">{{ scope.row.fieldPrecision || '--' }}</span>
322 <div v-else>
323 <el-select v-model="scope.row.fieldPrecision" placeholder="请选择" style="width: 50%;margin-right: 8px;">
324 <el-option label="<=500" value="<=500"></el-option>
325 <el-option label=">500" value=">500"></el-option>
326 </el-select>
327 <el-input v-model="scope.row.precisionValue" placeholder="请输入" style="width: 45%;" />
328 </div>
329 </template>
330 </el-table-column> -->
331 <!-- 精度(可编辑)fieldPrecision -->
332 <el-table-column prop="fieldPrecision" label="精度" width="120" align="center">
333 <template #default="scope">
334 <span v-if="!scope.row.isEdit || !editableFields.fieldPrecision">{{
335 scope.row.fieldPrecision ? scope.row.fieldPrecision : '--' }}</span>
336 <el-input v-else v-model="scope.row.fieldPrecision" placeholder="请输入精度" />
337 </template>
338 </el-table-column>
339
340 <!-- 关联字典(可编辑)el-tree-select 形式下拉形式 -->
341 <el-table-column prop="dictionaryGuid" label="关联字典" width="150" align="center">
342 <template #default="scope">
343 <span v-if="!scope.row.isEdit || !editableFields.dictionaryGuid">{{ scope.row.isDict ? scope.row.isDict :
344 '--' }}</span>
345 <el-tree-select v-else v-model="scope.row.isDict" :data="data" placeholder="请选择" />
346 </template>
347 </el-table-column>
348
349 <!-- 数据是否唯一(可编辑) -->
350 <el-table-column prop="isUnique" label="数据是否唯一" width="150" align="center">
351 <template #default="scope">
352 <span v-if="!scope.row.isEdit || !editableFields.isUnique">{{ scope.row.isUnique ? scope.row.isUnique : '--'
353 }}</span>
354 <el-select v-else v-model="scope.row.isUnique" placeholder="请选择">
355 <el-option label="是" value="Y" />
356 <el-option label="否" value="N" />
357 </el-select>
358 </template>
359 </el-table-column>
360 <!-- 是否必填(可编辑) -->
361 <el-table-column prop="isRequired" label="是否必填" width="120" align="center">
362 <template #default="scope">
363 <span v-if="!scope.row.isEdit">{{ scope.row.isRequired ? scope.row.isRequired : '--' }}</span>
364 <el-select v-else v-model="scope.row.isRequired" placeholder="请选择">
365 <el-option label="是" value="Y" />
366 <el-option label="否" value="N" />
367 </el-select>
368 </template>
369 </el-table-column>
370 <!-- 字段取值范围 fieldValueRange(可编辑)-->
371 <el-table-column prop="fieldValueRange" label="字段取值范围" width="150" align="center">
372 <template #default="scope">
373 <span v-if="!scope.row.isEdit">{{ scope.row.fieldValueRange ? scope.row.fieldValueRange : '--' }}</span>
374 <el-input v-else v-model="scope.row.fieldValueRange" placeholder="请输入字段取值范围" />
375 </template>
376 </el-table-column>
377
378 <!-- 操作列 -->
379 <el-table-column label="操作" width="100" align="center" fixed="right">
380 <template #default="scope">
381 <span class="text_btn" v-if="!scope.row.isEdit" @click="editRow(scope.row)">编辑</span>
382 <span class="text_btn" v-else @click="saveRow(scope.row)">保存</span>
383 <el-divider direction="vertical" />
384 <span class="text_btn" @click="deleteRow(scope.$index)">删除</span>
385 </template>
386 </el-table-column>
387 </el-table>
388 </div>
389 <div class="botton_btn">
390 <el-button type="primary" @click="saveData">保存</el-button>
391 <el-button @click="cancel">取消</el-button>
392 </div>
86 </div> 393 </div>
394
395
87 </template> 396 </template>
397
398 <style lang="scss" scoped>
399 .configure-rules {
400 padding: 16px;
401 height: 100%;
402
403 .table_panel_wrap {
404 width: 100%;
405 height: auto;
406 overflow: visible;
407 }
408
409
410 .btn-area {
411 margin-top: 12px;
412 }
413
414 :deep(.bottom_table) {
415 margin-top: 12px;
416 height: calc(100% - 150px);
417 overflow-y: auto;
418
419 .el-table td.el-table__cell {
420 padding: 2px 0;
421 height: 36px;
422 }
423 }
424 }
425 </style>
......
...@@ -123,7 +123,7 @@ const treeInfo = ref<any>({ ...@@ -123,7 +123,7 @@ const treeInfo = ref<any>({
123 filter: true, 123 filter: true,
124 queryValue: "", 124 queryValue: "",
125 className: 'tree-list', 125 className: 'tree-list',
126 queryPlaceholder: "输入标准集名称搜索", 126 queryPlaceholder: "输入目录名称搜索",
127 props: { 127 props: {
128 label: "classifyName", 128 label: "classifyName",
129 value: "guid", 129 value: "guid",
......
1 <route lang="yaml">
2 name: dictFileds
3 </route>
4
5 <script lang="ts" setup name="dictFileds">
6 import { ref } from 'vue'
7 import router from '@/router'
8 import { ElMessage, ElMessageBox } from "element-plus";
9 import Table from '@/components/Table/index.vue'
10 // import Dialog from '@/components/Dialog/index.vue'
11 import useCatchStore from "@/store/modules/catch";
12 import { chunk } from '@/utils/common'
13
14 import {
15 saveDictionaryData,
16 getDictionaryFileds,
17 deleteDictionaryData,
18 checkDictionaryData,
19 showDictionary,
20 getDictionaryRuleData
21 } from '@/api/modules/dataInventory';
22
23 const emits = defineEmits(["exportData"])
24 const { proxy } = getCurrentInstance() as any;
25
26 const cacheStore = useCatchStore()
27 const dictionaryGuid = ref("")
28 const tableSearchInput = ref('')
29 const tableFields: any = ref([])
30 const orginData: any = ref([])
31 const currTableData: any = ref<Object>({});
32 const selectRowData = ref([])
33 const page = ref({
34 limit: 50,
35 curr: 1,
36 // sizes: [
37 // { label: "100", value: 100 },
38 // { label: "200", value: 200 },
39 // { label: "300", value: 300 },
40 // { label: "400", value: 400 },
41 // { label: "500", value: 500 },
42 // ],
43 });
44 const tableChunkData: any = ref([])
45 const tableData: any = ref([])
46 const tableInfo: any = ref({
47 id: 'data-fileds-table',
48 multiple: true,
49 fields: [],
50 data: [],
51 page: {
52 type: "count",
53 rows: 0,
54 ...page.value,
55 },
56 // showPage: false,
57 actionInfo: {
58 label: "操作",
59 type: "btn",
60 width: 92,
61 btns: (scope) => {
62 return [
63 { label: "编辑", value: "edit", visible: scope.row['STATE'] !== 'Running' },
64 { label: "删除", value: "remove", visible: scope.row['STATE'] !== 'Running' },
65 { label: "保存", value: "save", visible: scope.row['STATE'] === 'Running' },
66 { label: "取消", value: "cancel", visible: scope.row['STATE'] === 'Running' },
67 ]
68 },
69 },
70 editInfo: {},
71 loading: false
72 })
73
74 const uploadFiles = ref([])
75 const uploadInfo = ref({
76 type: 'upload',
77 title: '',
78 col: '',
79 uploadInfo: {
80 id: 'upload-file-form',
81 type: 'panel',
82 action: '',
83 auto: false,
84 cover: true,
85 fileList: [],
86 accept: '.xlsx, .xls',
87 triggerBtn: {
88 label: '导入',
89 value: 'import_file',
90 icon: 'Upload',
91 },
92 tips: '当前支持xls、xlsx文件,默认使用第一个sheet'
93 },
94 })
95
96 const dialogInfo = ref({
97 visible: false,
98 size: 640,
99 direction: "column",
100 header: {
101 title: "新建",
102 },
103 type: '',
104 contents: [
105 uploadInfo.value
106 ],
107 footer: {
108 visible: true,
109 btns: [
110 { type: "default", label: "取消", value: "cancel" },
111 { type: "primary", label: "开始导入", value: "submit" },
112 ],
113 },
114 })
115
116
117 const getFirstPageData = () => {
118 toSearch({})
119 }
120
121 const toSearch = (val: any, clear: boolean = false) => {
122 let params = dictionaryGuid.value
123 getTableData(params);
124 };
125
126 const getTableData = (params) => {
127 tableInfo.value.loading = true
128 getDictionaryFileds(params).then((res: any) => {
129 if (res.code == proxy.$passCode) {
130 const data = res.data ?? {}
131 setUploadDataInfo(data, true)
132 } else {
133 ElMessage({
134 type: 'error',
135 message: res.msg,
136 })
137 }
138 tableInfo.value.loading = false
139 }).catch(xhr => {
140 tableInfo.value.loading = false
141 })
142 };
143
144 const tableSelectionChange = (val, tId) => {
145 selectRowData.value = val;
146 };
147
148 const tablePageChange = (info) => {
149 page.value.curr = Number(info.curr);
150 if (page.value.limit != Number(info.limit)) {
151 page.value.limit = Number(info.limit);
152 chunkData()
153 } else {
154 tableData.value = tableChunkData.value[page.value.curr - 1]
155 tableInfo.value.data = tableData.value
156 tableInfo.value.page.limit = page.value.limit
157 tableInfo.value.page.curr = page.value.curr
158 }
159 };
160
161 const toolBtnClick = (btn) => {
162 const type = btn.value
163 if (type == 'export') {
164 exportData()
165 } else if (type == 'import') {
166 const info = {
167 type: 'dictionary',
168 dictionaryGuid: dictionaryGuid.value
169 }
170 cacheStore.setCatch('uploadSetting', info)
171 nextTick(() => {
172 router.push({
173 path: '/data-standards/import-file',
174 });
175 })
176 } else if (type == 'submit') {
177 saveData()
178 } else if (type == 'add_row') {
179 const params = {
180 guid: dictionaryGuid.value
181 }
182 getDictionaryRuleData(params).then((res: any) => {
183 if (res.code == proxy.$passCode) {
184 const data = res.data ?? {}
185 let rowInfo: any = {}
186 tableFields.value.map(item => {
187 rowInfo[item.field] = data[item.field] ?? ''
188 })
189 rowInfo.guid = undefined;
190 rowInfo.STATE = 'Running'
191 rowInfo.STATUS = 'edit'
192 rowInfo.ROWID = `upload_${tableData.value.length}`
193 tableData.value.unshift(rowInfo)
194 orginData.value.unshift(rowInfo)
195 tableInfo.value.page.rows = tableData.value.length
196 // orginData.value.unshift(rowInfo)
197 // page.value.curr = 1
198 // chunkData()
199 } else {
200 ElMessage({
201 type: 'error',
202 message: res.msg
203 })
204 }
205 })
206 }
207 }
208
209 const tableBtnClick = (scope, btn) => {
210 const type = btn.value;
211 let row = scope.row;
212 currTableData.value = row;
213 if (type == "edit") {
214 row.STATE = 'Running'
215 row.STATUS = 'edit'
216 tableData.value[scope.$index] = row
217 } else if (type == 'save') {
218 saveData(scope)
219 } else if (type == 'cancel') {
220 if (row.guid != undefined) {
221 // row = orginData.value[(page.value.curr - 1) * page.value.limit + scope.$index]
222 row = JSON.parse(JSON.stringify(orginData.value[scope.$index]))
223 row.STATE = ''
224 row.STATUS = ''
225 tableData.value[scope.$index] = row
226 } else {
227 tableData.value.splice(scope.$index, 1)
228 orginData.value.splice(scope.$index, 1)
229 // orginData.value.splice((page.value.curr - 1) * page.value.limit + scope.$index, 1)
230 // if (scope.$index == 0) {
231 // page.value.curr = (page.value.curr - 1 > 1) ? page.value.curr - 1 : 1
232 // }
233 // chunkData()
234 }
235 tableInfo.value.page.rows = tableData.value.length
236 } else if (type == 'remove') {
237 open("是否确定删除所选数据?", "warning");
238 }
239 };
240
241 const onUpload = (file, fileList) => {
242 uploadFiles.value = fileList
243 }
244
245 const uploadBtnClick = (btn) => {
246 exportData('model')
247 }
248
249 const exportData = (type: any = null) => {
250 emits('exportData', type)
251 }
252
253 const importData = (file: any = null) => {
254 let params = new FormData()
255 if (file) {
256 params.append("file", file.raw);
257 } else {
258 if (uploadFiles.value.length) {
259 uploadFiles.value.forEach((item: any, index: number) => {
260 params.append("file", item.raw);
261 });
262 }
263 }
264
265 params.append("dictionaryGuid", dictionaryGuid.value);
266 showDictionary(params).then((res: any) => {
267 if (res.code == proxy.$passCode) {
268 dialogInfo.value.visible = false
269 let data = res.data ?? []
270 // data.map((item: any, i) => {
271 // item.index = tableData.value.length + i
272 // })
273 const tData = { jsonArray: data }
274 setUploadDataInfo(tData)
275 // saveData(null, tData)
276 } else {
277 ElMessage({
278 type: "error",
279 message: res.msg,
280 });
281 // dialogInfo.value.footer.btns.map((item: any) => delete item.disabled)
282 }
283 }).catch(() => {
284 // dialogInfo.value.footer.btns.map((item: any) => delete item.disabled)
285 });
286 }
287
288 const checkSave = () => {
289 const toSaveData = tableData.value.filter(item => item.STATE === 'Running')
290 return toSaveData.length == 0 ? true : false
291 }
292
293 const checkParamsData = (scope: any = null) => {
294 let addJsonArray: any = [], upJsonArray: any = [], jsonArray: any = [], pass = true
295 let passArr = scope ? [scope.row] : tableData.value
296 passArr.map((item, index) => {
297 const obj = JSON.parse(JSON.stringify(item))
298 delete obj.STATUS
299 delete obj.NOTES
300 delete obj.STATE
301 delete obj.ROWID
302 // if (item.STATE === 'Running') {
303 for (var i in obj) {
304 if (obj[i] == '') {
305 pass = false
306 }
307 }
308 // }
309 if (obj.guid !== undefined) {
310 upJsonArray.push(obj)
311 } else {
312 addJsonArray.push(obj)
313 }
314 if (scope) {
315 obj.index = scope.$index
316 jsonArray.push(obj)
317 } else {
318 obj.index = index
319 jsonArray.push(obj)
320 }
321 })
322 return { pass, addJsonArray, upJsonArray, jsonArray }
323 }
324
325 const saveData = async (scope: any = null, checkParamData: any = null) => {
326 let passInfo: any = {}
327 if (checkParamData) {
328 passInfo = checkParamData
329 } else {
330 passInfo = await checkParamsData(scope)
331 if (!passInfo.pass) {
332 // ElMessage({
333 // type: 'error',
334 // message: '请填写所有数据项'
335 // })
336 // return
337 }
338 }
339
340 const checkParams = {
341 dictionaryGuid: dictionaryGuid.value,
342 addJsonArray: passInfo.jsonArray
343 }
344 checkDictionaryData(checkParams).then((res: any) => {
345 if (res.code == proxy.$passCode) {
346 const data = res.data
347 if (Object.keys(data).length) {
348 addColumn(data)
349 } else {
350 addColumn()
351 const params = {
352 dictionaryGuid: dictionaryGuid.value,
353 addJsonArray: passInfo.addJsonArray,
354 upJsonArray: passInfo.upJsonArray
355 }
356 saveDictionaryData(params).then((res: any) => {
357 if (res.code == proxy.$passCode) {
358 getFirstPageData();
359 ElMessage({
360 type: 'success',
361 message: '保存成功'
362 })
363 } else {
364 ElMessage({
365 type: 'error',
366 message: res.msg,
367 })
368 }
369 })
370 }
371 } else {
372 ElMessage({
373 type: 'error',
374 message: res.msg,
375 })
376 }
377 })
378 }
379
380 const addColumn = (info: any = null) => {
381 const fields = tableFields.value
382 const existIndex = fields.findIndex(item => item.field == 'NOTES')
383 if (info) {
384 if (existIndex == -1) {
385 fields.push({
386 label: '备注',
387 field: 'NOTES',
388 width: 200
389 })
390 }
391 for (var d in info) {
392 tableData.value[d].NOTES = info[d].join(',')
393 }
394 } else {
395 if (existIndex > -1) {
396 fields.splice(existIndex, 1)
397 }
398 }
399 }
400
401 // 生成表头
402 const setUploadDataFields = (data) => {
403 let fields: any = [], editInfo: any = {}
404 data.map(item => {
405 let fieldItem: any = {
406 label: item.description, field: item.fieldName, width: 140
407 }
408 fieldItem.type = 'edit'
409 fieldItem.columClass = 'edit-colum'
410 editInfo[item.fieldName] = {
411 label: '',
412 type: 'input',
413 placeholder: '',
414 maxlength: 50,
415 field: item.fieldName,
416 default: '',
417 disabled: item.codeRuleGuid ? true : false,
418 clearable: true,
419 }
420 fields.push(fieldItem)
421 })
422 tableFields.value = fields
423 tableInfo.value.fields = tableFields.value
424 tableInfo.value.editInfo = editInfo
425 }
426
427 // 生成表数据
428 const setUploadDataInfo = async (info, setField = false) => {
429 if (setField) {
430 const fields = info.schemaDataVOS ?? []
431 await setUploadDataFields(fields)
432 }
433 let data = info.jsonArray ?? []
434 // 设置表数据
435 data.map((item, i) => {
436 item.ROWID = `upload_${tableData.value.length + i}`
437 })
438 if (setField) {
439 tableData.value = data
440 } else {
441 tableData.value = [...tableData.value, ...data]
442 }
443 orginData.value = JSON.parse(JSON.stringify(tableData.value))
444 tableInfo.value.data = tableData.value
445 tableInfo.value.page.rows = tableData.value.length
446 // if (setField) {
447 // orginData.value = data
448 // } else {
449 // orginData.value = [...orginData.value, ...data]
450 // }
451 // chunkData()
452 }
453
454 const chunkData = () => {
455 const data = orginData.value
456 tableChunkData.value = chunk(data, page.value.limit)
457 tableData.value = tableChunkData.value[page.value.curr - 1]
458 tableInfo.value.data = tableData.value
459 tableInfo.value.page.limit = page.value.limit
460 tableInfo.value.page.curr = page.value.curr
461 tableInfo.value.page.rows = orginData.value.length
462 }
463
464 const batching = (type) => {
465 if (type == 'delete') {
466 if (selectRowData.value.length == 0) {
467 ElMessage({
468 type: 'error',
469 message: '请选择需要删除的数据',
470 })
471 return
472 }
473 open("是否确定删除所选数据?", "warning", true);
474 }
475 };
476
477 const open = (msg, type, isBatch = false) => {
478 ElMessageBox.confirm(msg, "提示", {
479 confirmButtonText: "确定",
480 cancelButtonText: "取消",
481 type: type,
482 }).then(() => {
483 let guids: any = []
484 if (isBatch) {
485 const list = selectRowData.value.filter((item: any) => item.guid !== undefined)
486 if (list.length) {
487 guids = list.map((l: any) => l.guid)
488 }
489 const newRows = selectRowData.value.filter((item: any) => item.guid == undefined)
490 newRows.map((n: any, r) => {
491 const existIndex = tableData.value.findIndex(t => t.ROWID == n.ROWID)
492 if (existIndex > -1) {
493 tableData.value.splice(existIndex, 1)
494 orginData.value.splice(existIndex, 1)
495 }
496 // const existIndex = orginData.value.findIndex(t => t.id == n.id)
497 // existIndex > -1 && orginData.value.splice(existIndex, 1)
498 // if (r == newRows.length - 1) {
499 // page.value.curr = 1
500 // chunkData()
501 // }
502 })
503 tableInfo.value.page.rows = tableData.value.length
504 } else {
505 guids = [currTableData.value.guid]
506 }
507 if (guids.length) {
508 const params = {
509 guid: dictionaryGuid.value,
510 delGuids: guids
511 }
512 deleteDictionaryData(params).then((res: any) => {
513 if (res.code == proxy.$passCode) {
514 getFirstPageData();
515 ElMessage({
516 type: "success",
517 message: "删除成功",
518 });
519 } else {
520 ElMessage({
521 type: "error",
522 message: res.msg,
523 });
524 }
525 });
526 }
527 });
528 };
529
530 const dialogBtnClick = (btn, info) => {
531 if (btn.value == 'submit') {
532 // dialogInfo.value.footer.btns.map((item: any) => item.disabled = true)
533 importData()
534 } else if (btn.value == 'cancel') {
535 // dialogInfo.value.footer.btns.map((item: any) => delete item.disabled)
536 nextTick(() => {
537 dialogInfo.value.visible = false;
538 })
539 }
540 };
541
542 defineExpose({
543 dictionaryGuid,
544 getFirstPageData,
545 checkSave
546 });
547
548 </script>
549
550 <template>
551 <div class="container_wrap full flex">
552 <div class="main_wrap">
553 <div class="table_tool_wrap">
554 <div class="tools_btns">
555 <el-button type="primary" @click="toolBtnClick({ value: 'add_row' })" v-preReClick>新增行</el-button>
556 <el-button type="primary" plain @click="toolBtnClick({ value: 'submit' })" v-preReClick>保存数据</el-button>
557 <el-button @click="batching('delete')" v-preReClick>批量删除</el-button>
558 <el-button @click="toolBtnClick({ value: 'import' })" v-preReClick>导入数据</el-button>
559 <el-button @click="toolBtnClick({ value: 'export' })" v-preReClick>导出数据</el-button>
560 </div>
561 <!-- <el-input class="table_search_input" v-model.trim="tableSearchInput" placeholder="输入名称搜索" :suffix-icon="Search" clearable
562 @change="val => toSearch({})" /> -->
563 </div>
564 <div class="table_panel_wrap full">
565 <Table :tableInfo="tableInfo" @tableBtnClick="tableBtnClick" @tableSelectionChange="tableSelectionChange"
566 @tablePageChange="tablePageChange" />
567 </div>
568 </div>
569
570 <!-- <Dialog :dialogInfo="dialogInfo" @btnClick="dialogBtnClick" @onUpload="onUpload" @uploadBtnClick="uploadBtnClick" /> -->
571 </div>
572 </template>
573
574 <style lang="scss" scoped>
575 .container_wrap {
576 width: calc(100% - 200px);
577
578 .main_wrap {
579 width: 100%;
580
581 .table_panel_wrap {
582 height: calc(100% - 44px);
583 }
584 }
585 }
586 </style>
1 <script lang="ts" setup name="existingTableSelect">
2 import { ref } from "vue";
3 import { Search, Close } from "@element-plus/icons-vue";
4 import { ElMessage, ElTable } from "element-plus";
5 import PageNav from "@/components/PageNav/index.vue";
6 import Moment from 'moment';
7 import {
8 getDsTableByDs,
9 getDsData,
10 getDsTableStructure,
11 } from "@/api/modules/dataInventory";
12
13
14
15 /** 需要从父组件接收已选中的数据表 和 数据库列表(由父组件获取,只需获取一次,因为父组件也需要使用)。 */
16 const props = defineProps({
17 databaseList: {
18 type: Array<any>,
19 default: [],
20 },
21 dataSourceGuid: {
22 type: String,
23 default: ''
24 },
25 dsList: {
26 type: Array<any>,
27 default: [],
28 },
29 isLook: {
30 type: Boolean,
31 default: false,
32 },
33 tableCreateType: {
34 type: Number,
35 default: 2,
36 },
37 subjectDomainGuid: {
38 type: String,
39 default: ''
40 },
41 execGuid: {
42 type: String,
43 default: ''
44 }
45 });
46
47 watch(() => { }, () => {
48 // datasourceSelectedRows.value = props.dsList?.slice(0) || [];
49 let selectTableName = currDatasourceSelect.value?.tableName;
50 if (selectTableName) {
51 let ds = datasourceSelectedRows.value?.find(d => d.tableName === selectTableName);
52 if (!ds) {
53 currDatasourceSelect.value = {};
54 }
55 }
56 })
57
58 const datasourceSelectedRows: any = ref([]);
59
60 const emits = defineEmits(["datasourceSelectedChange"]);
61
62 const { proxy } = getCurrentInstance() as any;
63
64 /** 当前选中的数据源连接池guid,和相关信息。 */
65 const databaseInfo: any = computed(() => {
66 if (!databaseGuid.value) {
67 return {};
68 }
69 return props.databaseList.find(d => d.guid == databaseGuid.value);
70 });
71
72 const databaseGuid: any = ref('');
73
74 watch(() => props.databaseList, (val) => {
75 if (!val?.length) {
76 return;
77 }
78 if (props.dataSourceGuid != "") {
79 databaseGuid.value = props.dataSourceGuid;
80 } else if (!databaseInfo.value.guid) {
81 databaseGuid.value = val[0]?.guid;
82 }
83 })
84
85 const searchKey = ref("");
86
87 const dsTableList: Ref<any> = ref();
88 const dsTableListLoading = ref(false);
89
90 const datasourceTableRef = ref<InstanceType<typeof ElTable>>();
91
92 const dsPageInfo = ref({
93 limit: 50,
94 curr: 1,
95 rows: 0,
96 type: "concise",
97 });
98
99 const currDatasourceSelect: Ref<any> = ref({});
100 const currDsPreviewActiveName = ref("resultData");
101 const currDsPreviewData = ref([]);
102 const currDsFields: Ref<any> = ref([]);
103 /** 每列字段对应的列宽计算结果。 */
104 const originTableFieldColumn = ref({});
105 const currDsPreviewDataLoading = ref(false);
106 const currDsTableStructure = ref([]);
107 const currDsTableStructureLoading = ref(false);
108
109 // const calcTableColumnWidth = (data: any[], prop, title) => {
110 // let d: any[] = [];
111 // data.forEach((dt) => d.push(dt[prop]));
112 // return calcColumnWidth(
113 // d,
114 // title,
115 // {
116 // fontSize: 14,
117 // fontFamily: "SimSun",
118 // },
119 // {
120 // fontSize: 14,
121 // fontFamily: "SimSun",
122 // }
123 // );
124 // };
125
126 const formatterPreviewDate = (row, info) => {
127 let enName = info.enName;
128 let v = row[enName];
129 if (v === 0) {
130 return v;
131 }
132 if (!v) {
133 return v || '--';
134 }
135 if (info.dataType === 'datetime') {
136 return Moment(v).format('YYYY-MM-DD HH:mm:ss');
137 }
138 if (info.dataType === 'date') {
139 if (isNaN(<any>(new Date(v)))) {
140 return Moment(parseInt(v)).format('YYYY-MM-DD');
141 } else {
142 return Moment(v).format('YYYY-MM-DD');
143 }
144 }
145 return v;
146 };
147
148 const getTableListPromise = ref();
149
150 const getDsTableList = (params) => {
151 dsTableList.value = [];
152 dsTableListLoading.value = true;
153 let promise: any = null;
154 promise = getTableListPromise.value = getDsTableByDs(params).then((res: any) => {
155 if (promise !== getTableListPromise.value) {
156 return;
157 }
158 dsTableListLoading.value = false;
159 if (res.code == proxy.$passCode) {
160 dsPageInfo.value.rows = res.data?.totalRows || 0;
161 dsTableList.value = res.data?.records || [];
162 //需要根据新的datasourceList 和选中行,设置表格的选中。
163 nextTick(() => {
164 datasourceSelectedRows.value.forEach((d) => {
165 let row = dsTableList.value.find((v: any) => v.tableName == d.tableName);
166 if (row) {
167 datasourceTableRef.value?.toggleRowSelection(row, true);
168 }
169 });
170 });
171 } else {
172 ElMessage.error(res.msg);
173 }
174 })
175 };
176
177 const getPreviewData = () => {
178 currDsPreviewData.value = [];
179 currDsPreviewDataLoading.value = true;
180 getDsData({
181 pageSize: 50,
182 pageIndex: 1,
183 dataSourceGuid: databaseInfo.value.guid,
184 database: currDatasourceSelect.value.database,
185 tableName: currDatasourceSelect.value.tableName,
186 }).then((res: any) => {
187 currDsPreviewDataLoading.value = false;
188 if (res.code == proxy.$passCode) {
189 currDsPreviewData.value = res.data.datas || [];
190 currDsFields.value = res.data.fields || [];
191 } else {
192 ElMessage.error(res.msg);
193 }
194 });
195 };
196
197 const getTableStructure = () => {
198 let tableName = currDatasourceSelect.value.tableName;
199 currDsTableStructureLoading.value = true;
200 currDsTableStructure.value = [];
201 getDsTableStructure({
202 tableName: tableName,
203 dataSourceGuid: databaseInfo.value.guid,
204 database: databaseInfo.value.databaseNameEn,
205 databaseType: databaseInfo.value.databaseType
206 }).then((res: any) => {
207 currDsTableStructureLoading.value = false;
208 if (res.code == proxy.$passCode) {
209 currDsTableStructure.value = res.data || [];
210 } else {
211 ElMessage.error(res.msg);
212 }
213 });
214 };
215
216 watch(() => databaseInfo.value, (val) => {
217 if (!val) {
218 return;
219 }
220 dsPageInfo.value.curr = 1;
221 searchKey.value = "";
222 getDsTableList({
223 pageSize: dsPageInfo.value.limit,
224 pageIndex: dsPageInfo.value.curr,
225 dataSourceGuid: val.guid,
226 execGuid: props.execGuid
227 });
228 })
229
230 const handleSearchInputChange = () => {
231 dsPageInfo.value.curr = 1;
232 getDsTableList({
233 pageSize: dsPageInfo.value.limit,
234 pageIndex: dsPageInfo.value.curr,
235 dataSourceGuid: databaseInfo.value.guid,
236 execGuid: props.execGuid
237 });
238 };
239
240 const dsPageChange = (page) => {
241 console.log(page);
242 dsPageInfo.value.curr = page.curr;
243 dsPageInfo.value.limit = page.limit;
244 getDsTableList({
245 pageSize: dsPageInfo.value.limit,
246 pageIndex: dsPageInfo.value.curr,
247 dataSourceGuid: databaseInfo.value.guid,
248 execGuid: props.execGuid
249 });
250 };
251
252 const datasource_row_class_name = ({ row, rowIndex }) => {
253 return datasourceSelectedRows.value.find((v: any) => v.tableName == row.tableName)
254 ? "selected"
255 : "";
256 };
257
258 const datasource_selection_all_change = (selection) => {
259 let isChecked = selection.length > 0;
260 dsTableList.value.forEach((d) => {
261 let index = datasourceSelectedRows.value.findIndex(
262 (v: any) => v.tableName == d.tableName
263 );
264 if (index === -1 && isChecked) {
265 datasourceSelectedRows.value.push(Object.assign({}, d, databaseInfo.value));
266 } else if (index !== -1 && !isChecked) {
267 datasourceSelectedRows.value.splice(index, 1);
268 if (currDatasourceSelect.value?.tableName === d.tableName) {
269 currDatasourceSelect.value = {};
270 }
271 }
272 });
273 };
274 const datasource_selection_change = (selection, row) => {
275 console.log(selection, row);
276 let index = selection.findIndex((s) => s.tableName == row.tableName);
277 if (index === -1) {
278 datasourceSelectedRows.value.splice(
279 datasourceSelectedRows.value.findIndex((v: any) => v.tableName == row.tableName),
280 1
281 );
282 if (currDatasourceSelect.value?.tableName === row.tableName) {
283 currDatasourceSelect.value = {};
284 }
285 } else {
286 datasourceSelectedRows.value.push(Object.assign({}, row));
287 }
288 };
289 /** 点击行选中或再次点击取消。不知是否有此种需求,一般都是点击勾选框选中。@row-click="datasource_row_click" */
290 // const datasource_row_click = (row, column, event) => {
291 // let index = datasourceSelectedRows.value.findIndex(
292 // (v: any) => v.tableName == row.tableName
293 // );
294 // datasourceTableRef.value?.toggleRowSelection(row, index === -1);
295 // if (index === -1) {
296 // datasourceSelectedRows.value.push(Object.assign({}, row, databaseInfo.value));
297 // } else {
298 // datasourceSelectedRows.value.splice(index, 1);
299 // }
300 // };
301
302 const handleDsSelect = (item) => {
303 currDatasourceSelect.value = item;
304 };
305
306 const delSelectDs = (item, i) => {
307 datasourceSelectedRows.value.splice(i, 1);
308 if (currDatasourceSelect.value?.tableName === item.tableName) {
309 currDatasourceSelect.value = {};
310 }
311 let table = dsTableList.value.find(t => t.tableName === item.tableName);
312 table && datasourceTableRef.value?.toggleRowSelection(table, false);
313 };
314
315 watch(
316 datasourceSelectedRows,
317 (val, oldVal) => {
318 if (val?.length && !currDatasourceSelect.value?.tableName) {
319 currDatasourceSelect.value = val[0];
320 }
321 emits("datasourceSelectedChange", val);
322 },
323 {
324 deep: true,
325 }
326 );
327
328 watch(currDatasourceSelect, (val) => {
329 if (val?.tableName) {
330 getPreviewData();
331 getTableStructure();
332 }
333 });
334
335 const getTextAlign = (field) => {
336 if (field.dataType === 'decimal' || field.dataType === 'int' || field.dataType == 'bit' || field.dataType == 'tinyint') {
337 return 'right';
338 }
339 return 'left'
340 }
341 </script>
342
343 <template>
344 <div class="first-step-content">
345 <div class="content-left">
346 <div class="title-left">待选库表</div>
347 <div class="content-selecte-left">
348 <span class="select-ds-title">数据存储连接池</span>
349 <el-select v-model="databaseGuid" placeholder="请选择" filterable value-key="guid">
350 <el-option v-for="opt in databaseList" :key="opt['guid']" :label="opt['databaseChName']"
351 :value="opt['guid']" />
352 </el-select>
353 <el-input class="table_search_input" v-model.trim="searchKey" placeholder="关键字搜索" :prefix-icon="Search"
354 @change="handleSearchInputChange" clearable />
355 <el-table class="datasource-small-table" ref="datasourceTableRef" :data="dsTableList"
356 v-loading="dsTableListLoading" :border="false" row-key="tableName" :row-class-name="datasource_row_class_name"
357 @select="datasource_selection_change" @select-all="datasource_selection_all_change" tooltip-effect="light">
358 <el-table-column type="selection" :width="22" align="center" />
359 <el-table-column prop="tableName" label="名称" width="100px" align="left" show-overflow-tooltip>
360 </el-table-column>
361 <el-table-column prop="tableComment" label="表注释" width="60px" align="left" show-overflow-tooltip>
362 <template #default="scope">
363 <span>{{ scope.row['tableComment'] ?? '--' }}</span>
364 </template>
365 </el-table-column>
366 </el-table>
367 <PageNav :class="[dsPageInfo.type]" :pageInfo="dsPageInfo" @pageChange="dsPageChange" />
368 </div>
369 </div>
370 <div class="content-right">
371 <div class="title-right">已选库表</div>
372 <div class="ds-select-container">
373 <template v-if="datasourceSelectedRows.length">
374 <div v-for="(item, i) in datasourceSelectedRows" :key="item.tableName" :class="currDatasourceSelect?.tableName === item.tableName
375 ? 'ds-select-item selected'
376 : 'ds-select-item'
377 " @click="handleDsSelect(item)" v-preReClick>
378 <span class="item-title">{{ item.tableName }}</span>
379 <el-icon v-if="!isLook" @click.stop="delSelectDs(item, i)" v-preReClick>
380 <Close />
381 </el-icon>
382 </div>
383 </template>
384 <div v-if="!datasourceSelectedRows.length" class="ds-select-placeholder">
385 请从左侧待选库表选择
386 </div>
387 </div>
388 <div class="ds-data-preview">
389 <div class="preview-data-totals t-left" v-show="currDsPreviewActiveName == 'resultData'">
390 <span>该页面仅显示</span>
391 <span style="color: var(--el-color-primary)"> 50 </span>
392 <span>条数据</span>
393 </div>
394 <el-tabs class="preview-tabs" v-model="currDsPreviewActiveName">
395 <el-tab-pane label="查询结果" name="resultData" class="t-left">
396 <div v-if="!currDatasourceSelect?.tableName" class="no-select-table">
397 <img src="../../assets/images/no-data.png" :style="{ width: '96px', height: '96px' }" />
398 <span>请从已选库表中选择</span>
399 </div>
400 <el-table key="previewTableData" v-loading="currDsPreviewDataLoading" :data="currDsPreviewData" border
401 tooltip-effect="light" style="
402 width: 100%;
403 min-width: 200px;
404 max-width: calc(100% - 17px);
405 height: calc(100% - 8px);
406 display: inline-block;
407 margin: 0 8px;
408 " stripe ref="previewTable">
409 <el-table-column v-for="(field, index) in currDsFields" :key="field.enName" :prop="field.enName"
410 :label="field.chName" :width="field.dataType === 'datetime'
411 ? 180
412 : field.dataType === 'date'
413 ? 140
414 : originTableFieldColumn[field.enName]
415 " :align="getTextAlign(field)" :header-align="getTextAlign(field)" :show-overflow-tooltip="true"
416 :formatter="(row) => formatterPreviewDate(row, field)">
417 </el-table-column>
418 </el-table>
419 </el-tab-pane>
420 <el-tab-pane label="库表结构" name="tableStructure" class="t-left">
421 <div v-if="!currDatasourceSelect?.tableName" class="no-select-table">
422 <img src="../../assets/images/no-data.png" :style="{ width: '96px', height: '96px' }" />
423 <span>请从已选库表中选择</span>
424 </div>
425 <el-table key="previewTableStructure" v-loading="currDsTableStructureLoading" tooltip-effect="light"
426 :data="currDsTableStructure" border style="
427 width: 100%;
428 max-width: calc(100% - 17px);
429 height: calc(100% - 8px);
430 display: inline-block;
431 margin: 0 8px;
432 " stripe ref="previewTableStructure">
433 <el-table-column type="index" label="序号" :width="56" align="center" />
434 <el-table-column prop="fieldName" label="字段英文名" width="150px" align="left" header-align="left"
435 show-overflow-tooltip>
436 </el-table-column>
437 <el-table-column prop="fieldChName" label="字段名" width="150px" align="left" header-align="left"
438 show-overflow-tooltip>
439 <template #default="scope">
440 <span>{{ scope.row['fieldChName'] ?? '--' }}</span>
441 </template>
442 </el-table-column>
443 <el-table-column prop="fieldType" label="字段类型" width="100px" align="left" header-align="left"
444 show-overflow-tooltip>
445 <template #default="scope">
446 <span>{{ scope.row['fieldType'] ?? '--' }}</span>
447 </template>
448 </el-table-column>
449 <el-table-column prop="fieldLength" label="长度" width="100px" align="left" header-align="left"
450 show-overflow-tooltip>
451 <template #default="scope">
452 <!--- 直接用??会导致空字符串时无法显示'--',此处需要区分0和“” -->
453 <span>{{ (scope.row['fieldLength'] !== 0 && !scope.row['fieldLength']) ? "--" :
454 scope.row['fieldLength'] }}</span>
455 </template>
456 </el-table-column>
457 <el-table-column prop="fieldPrecision" label="精度" width="100px" align="left" header-align="left"
458 show-overflow-tooltip>
459 <template #default="scope">
460 <!--- 直接用??会导致空字符串时无法显示'--',此处需要区分0和“” -->
461 <span>{{ (scope.row['fieldPrecision'] !== 0 && !scope.row['fieldPrecision']) ? "--" :
462 scope.row['fieldPrecision'] }}</span>
463 </template>
464 </el-table-column>
465 <el-table-column prop="isPrimary" label="是否主键" width="100px" align="left" header-align="left"
466 show-overflow-tooltip>
467 <template #default="scope">
468 <span>{{ scope.row['isPrimary'] ?? '--' }}</span>
469 </template>
470 </el-table-column>
471 <el-table-column prop="isNotNull" label="是否必填" width="100px" align="left" header-align="left"
472 show-overflow-tooltip>
473 <template #default="scope">{{ scope.row['isNotNull'] === 'Y' ? 'N' : 'Y' }}</template>
474 </el-table-column>
475 <el-table-column prop="isFk" label="是否外键" width="100px" align="left" header-align="left"
476 show-overflow-tooltip>
477 <template #default="scope">
478 <span>{{ scope.row['isFk'] ?? '--' }}</span>
479 </template>
480 </el-table-column>
481 </el-table>
482 </el-tab-pane>
483 </el-tabs>
484 </div>
485 </div>
486 </div>
487 </template>
488
489 <style lang="scss" scoped>
490 .first-step-content {
491 display: flex;
492 flex-direction: row;
493 height: calc(100% - 80px);
494
495 .content-left {
496 width: 200px;
497 border-right: 1px solid #d9d9d9;
498
499 .title-left {
500 height: 44px;
501 line-height: 44px;
502 border-bottom: 1px solid #d9d9d9;
503 padding-left: 8px;
504 font-size: 14px;
505 color: #212121;
506 }
507
508 .content-selecte-left {
509 height: calc(100% - 44px);
510 padding: 6px 8px 0px 8px;
511
512 .select-ds-title {
513 display: block;
514 font-size: 14px;
515 color: #999999;
516 line-height: 21px;
517 margin-bottom: 2px;
518 }
519
520 .table_search_input {
521 margin-top: 16px;
522 }
523
524 .page_nav_wrap.concise {
525 justify-content: center;
526 }
527 }
528 }
529
530 .content-right {
531 width: calc(100% - 200px);
532
533 .title-right {
534 height: 44px;
535 line-height: 44px;
536 border-bottom: 1px solid #d9d9d9;
537 padding-left: 8px;
538 font-size: 14px;
539 color: #212121;
540 }
541
542 .ds-select-container {
543 background: #f2f2f2;
544 height: 100px;
545 display: flex;
546 padding: 0px 0 12px 12px;
547 flex-direction: row;
548 flex-wrap: wrap;
549 overflow-y: auto;
550
551 .ds-select-placeholder {
552 width: 100%;
553 height: 100%;
554 display: flex;
555 align-items: center;
556 justify-content: center;
557 color: #999999;
558 }
559
560 .ds-select-item {
561 height: 32px;
562 border: 2px solid #d9d9d9;
563 display: flex;
564 align-items: center;
565 padding: 0 8px;
566 background: #fff;
567 cursor: pointer;
568 margin-right: 12px;
569 margin-top: 12px;
570
571 .item-title {
572 font-size: 14px;
573 color: #212121;
574 margin-right: 16px;
575 }
576 }
577
578 .ds-select-item:hover {
579 border: 2px solid var(--el-color-primary);
580 }
581
582 .ds-select-item.selected {
583 border: 2px solid var(--el-color-primary);
584 background-color: var(--el-menu-hover-bg-color);
585 }
586 }
587
588 .ds-data-preview {
589 height: calc(100% - 144px);
590 position: relative;
591
592 .preview-data-totals {
593 position: absolute;
594 right: 0;
595 top: 10px;
596 right: 16px;
597 }
598 }
599 }
600 }
601
602 :deep(.datasource-small-table) {
603 height: calc(100% - 143px);
604 margin-top: 4px;
605 border: 1px solid #d9d9d9;
606
607 td.el-table__cell::after,
608 .el-table__inner-wrapper::before {
609 height: 0px;
610 }
611
612 .cell {
613 padding: 0 2px;
614 }
615
616 th.el-table__cell {
617 line-height: 18px;
618 font-size: 12px;
619 color: #999999;
620 background-color: #fff;
621 }
622
623 td.el-table__cell .cell {
624 line-height: 18px;
625 font-size: 12px;
626 color: #212121;
627 }
628
629 tr.selected {
630 background-color: var(--el-menu-hover-bg-color);
631
632 td {
633 background-color: var(--el-menu-hover-bg-color);
634 }
635 }
636
637 .el-table__body tr.selected:hover>td.el-table__cell {
638 background-color: var(--el-menu-hover-bg-color);
639 }
640 }
641
642 :deep(.preview-tabs) {
643 height: 100%;
644
645 .el-tabs__header {
646 margin: 0 0 8px;
647 }
648
649 .el-tabs__nav-wrap::after {
650 height: 1px;
651 }
652
653 .el-tabs__item {
654 width: 88px;
655 padding: 0;
656 }
657
658 .el-tabs__nav {
659 padding-left: 8px;
660 }
661
662 .el-tabs__content {
663 height: calc(100% - 48px);
664
665 .el-tab-pane {
666 height: 100%;
667
668 :deep(.el-table) {
669 .cell {
670 white-space: nowrap;
671 }
672 }
673
674 .no-select-table {
675 width: 100%;
676 height: 100%;
677 display: flex;
678 align-items: center;
679 justify-content: center;
680 flex-direction: column;
681 color: #999999;
682 background-color: #fafafa;
683 }
684 }
685 }
686 }
687
688 :deep(.el-table) {
689 .el-scrollbar__view {
690 height: 100%;
691 }
692 }
693 </style>
1 <route lang="yaml">
2 name: tableCreateExisting
3 </route>
4
5 <script lang="ts" setup name="tableCreateExisting">
6 import { ref } from "vue";
7 import { ElMessage } from "element-plus";
8 import StepBar from "@/components/StepBar/index.vue";
9 import {
10 getDbDirDataSourceList,
11 getDsData,
12 getDsTableStructure,
13 saveDbDirTable,
14 updateDbDirTable,
15 createTableSql,
16 } from "@/api/modules/dataInventory";
17 import existingTableSelect from "./existingTableSelect.vue";
18
19 /** 草稿中未建表时就可以编辑表相关信息。如果建表之后就只能编辑字段。 不能修改字段英文名称,数据库修改英文名就相当于删除再添加。都可以直接跳转到*/
20
21 const { proxy } = getCurrentInstance() as any;
22 const router = useRouter();
23 const route = useRoute();
24 const isDimTable = route.query.isDim;
25 const execGuid: any = ref(route.query.execGuid);
26
27 // 获取数据库列表
28 const databaseList: any = ref([]);
29 const getDbDirDataSourceListData = async () => {
30 const params = {
31 execGuid: execGuid.value,
32 };
33 const res: any = await getDbDirDataSourceList(params);
34 if (res.code === proxy.$passCode) {
35 databaseList.value = processData(res.data);
36 } else {
37 proxy.$ElMessage.error(res.msg);
38 }
39 };
40 // 数据处理函数
41 const processData = (data) => {
42 return data.map(item => ({
43 ...item,
44 guid: item.databaseGuid, // 添加新键 "guid"
45 databaseGuid: undefined, // 删除旧键 "databaseGuid"
46 })).map(({ databaseGuid, ...rest }) => rest); // 过滤掉 undefined 键
47 };
48 onMounted(async () => {
49 await getDbDirDataSourceListData();
50 });
51
52 const stepsInfo = ref({
53 step: 0,
54 list: [
55 { title: "选择数据库表", value: 1 },
56 { title: "设置属性字段", value: 2 },
57 ],
58 });
59
60
61
62 const datasourceSelectedRows: Ref<any> = ref([]);
63
64 //记录下一步时选中的库表信息。
65 const selectedDatabaseTable: Ref<any> = ref([]);
66
67 const handlDsSelectedChange = (v) => {
68 datasourceSelectedRows.value = v || [];
69 const params: any = [];
70 v.forEach((item) => {
71 params.push({
72 tableName: item.tableName,
73 database: item.database,
74 });
75 });
76 selectedDatabaseTable.value = params;
77 console.log('params', params)
78 // if (isPrevious.value) {
79 // tableCreateInfo.value.tableFields = [];
80 // tableCreateInfo.value.inputNameValue = '';
81 // tableCreateInfo.value.tableData[0].chName = '';
82 // }
83 };
84
85
86 const fullscreenLoading = ref(false);
87 /** 下一步 */
88 const nextStep = () => {
89 if (!datasourceSelectedRows.value.length) {
90 ElMessage({
91 type: "error",
92 message: "已选库表不能为空!",
93 });
94 return;
95 }
96 getNextTableInfo();
97 stepsInfo.value.step = 1;
98 };
99
100 //下一步获取表字段信息getNextTableInfo。getDsData 入参selectedDatabaseTable.value
101 const getNextTableInfo = async () => {
102 const res: any = await getDsTableStructure(selectedDatabaseTable.value);
103 if (res.code === proxy.$passCode) {
104 tableDataDetailInfo.value = res.data;
105 } else {
106 proxy.$ElMessage.error(res.msg);
107 }
108 };
109 const isPrevious = ref(false);
110
111 /** 上一步 */
112 const previousStep = () => {
113 stepsInfo.value.step = 0;
114 isPrevious.value = true;
115 };
116 //记录当前正在编辑的表创建信息。
117 const tableCreateInfo: Ref<any> = ref({
118 guid: "",
119 isCreate: false,
120 inputNameValue: '',
121 tableData: [],
122 partitionAttribute: {},
123 tableFields: [], // 字段标准数组。
124 });
125
126
127 const tableDataInfo = ref([
128 {
129 tableName: '',
130 tableChName: '',
131 description: '',
132 },
133 ])
134 // 表格数据
135 const tableDataDetailInfo = ref([
136 { id: 1, fieldName: '系统唯一标识', fieldEnglish: 'ID', length: '<200', isUnique: '是', isEdit: false },
137 { id: 2, fieldName: '姓名', fieldEnglish: 'NAME', length: '<=200', isUnique: '否', isEdit: false },
138 { id: 3, fieldName: '年纪', fieldEnglish: 'AGE', length: '=200', isUnique: '否', isEdit: false },
139 { id: 4, fieldName: '系统唯一标识', fieldEnglish: 'ID', length: '<200', isUnique: '是', isEdit: false },
140 { id: 5, fieldName: '姓名', fieldEnglish: 'NAME', length: '<=200', isUnique: '否', isEdit: false },
141 { id: 6, fieldName: '年纪', fieldEnglish: 'AGE', length: '=200', isUnique: '否', isEdit: false },
142 ])
143
144 // 配置哪些字段可编辑
145 const editableFields = {
146 fieldName: true, // 字段中文名可编辑
147 length: true, // 长度可编辑
148 isUnique: true, // 数据是否唯一可编辑
149 fieldPrecision: true, // 精度可编辑
150 dictionaryGuid: true, // 关联字典可编辑
151 }
152
153 const tableFieldsLoading = ref(false)
154 const selectedRows = ref([]);
155 // 监听选中行
156 const selectionFieldsChange = (selection) => {
157 console.log('selection', selection)
158 selectedRows.value = selection;
159 };
160
161 // 上移功能
162 const moveUp = () => {
163 // 1. 找到选中行在 tableData 中的索引
164 const selectedIds = selectedRows.value.map((row: any) => row.id);
165
166 // 2. 遍历选中行,按顺序上移
167 for (let i = 0; i < tableDataDetailInfo.value.length; i++) {
168 const currentRow = tableDataDetailInfo.value[i];
169
170 // 如果当前行被选中,且不是第一行,则交换位置
171 if (selectedIds.includes(currentRow.id) && i > 0) {
172 const previousRow = tableDataDetailInfo.value[i - 1];
173
174 // 如果上一行没有被选中,交换位置
175 if (!selectedIds.includes(previousRow.id)) {
176 [tableDataDetailInfo.value[i], tableDataDetailInfo.value[i - 1]] = [tableDataDetailInfo.value[i - 1], tableDataDetailInfo.value[i]];
177 }
178 }
179 }
180 };
181
182 // 下移功能
183 const moveDown = () => {
184 // 1. 找到选中行在 tableData 中的索引
185 const selectedIds = selectedRows.value.map((row: any) => row.id);
186
187 // 2. 遍历选中行,倒序下移
188 for (let i = tableDataDetailInfo.value.length - 1; i >= 0; i--) {
189 const currentRow = tableDataDetailInfo.value[i];
190
191 // 如果当前行被选中,且不是最后一行,则交换位置
192 if (selectedIds.includes(currentRow.id) && i < tableDataDetailInfo.value.length - 1) {
193 const nextRow = tableDataDetailInfo.value[i + 1];
194
195 // 如果下一行没有被选中,交换位置
196 if (!selectedIds.includes(nextRow.id)) {
197 [tableDataDetailInfo.value[i], tableDataDetailInfo.value[i + 1]] = [tableDataDetailInfo.value[i + 1], tableDataDetailInfo.value[i]];
198 }
199 }
200 }
201 };
202
203 // 进入编辑模式
204 const editRow = (row) => {
205 row.isEdit = true
206 }
207
208 // 保存数据
209 const saveRow = (row) => {
210 row.isEdit = false
211 }
212
213 // 删除行
214 const deleteRow = (index) => {
215 // confirm 弹窗
216 proxy.$confirm('是否删除该行数据?', '提示', {
217 confirmButtonText: '确定',
218 cancelButtonText: '取消',
219 type: 'warning',
220 }).then(() => {
221 tableDataDetailInfo.value.splice(index, 1)
222 }).catch(() => {
223 proxy.$message({
224 type: 'info',
225 message: '已取消删除'
226 });
227 });
228 }
229 // 批量删除功能
230 const batchDelete = () => {
231 selectedRows.value.forEach((row: any) => {
232 const index = tableDataDetailInfo.value.findIndex((item) => item.id === row.id);
233 if (index !== -1) tableDataDetailInfo.value.splice(index, 1);
234 });
235 selectedRows.value = [];
236 };
237
238 // 新增一行
239 const addRow = () => {
240 tableDataDetailInfo.value.push({
241 id: tableDataDetailInfo.value.length + 1,
242 fieldName: '',
243 fieldEnglish: '', // 英文名不可编辑
244 length: '',
245 isUnique: '',
246 isEdit: true, // 新增时默认进入编辑模式
247 })
248 }
249
250 const data = [
251 {
252 value: '1',
253 label: 'Level one 1',
254 children: [
255 {
256 value: '1-1',
257 label: 'Level two 1-1',
258 children: [
259 {
260 value: '1-1-1',
261 label: 'Level three 1-1-1',
262 },
263 ],
264 },
265 ],
266 },
267 {
268 value: '2',
269 label: 'Level one 2',
270 children: [
271 {
272 value: '2-1',
273 label: 'Level two 2-1',
274 children: [
275 {
276 value: '2-1-1',
277 label: 'Level three 2-1-1',
278 },
279 ],
280 },
281 {
282 value: '2-2',
283 label: 'Level two 2-2',
284 children: [
285 {
286 value: '2-2-1',
287 label: 'Level three 2-2-1',
288 },
289 ],
290 },
291 ],
292 },
293 {
294 value: '3',
295 label: 'Level one 3',
296 children: [
297 {
298 value: '3-1',
299 label: 'Level two 3-1',
300 children: [
301 {
302 value: '3-1-1',
303 label: 'Level three 3-1-1',
304 },
305 ],
306 },
307 {
308 value: '3-2',
309 label: 'Level two 3-2',
310 children: [
311 {
312 value: '3-2-1',
313 label: 'Level three 3-2-1',
314 },
315 ],
316 },
317 ],
318 },
319 ]
320
321 const submitAsDraft = () => {
322 // 保存为草稿,无论有没有guid 都传入guid
323
324 saveOrUpdate({ isDraft: 'Y' }, 0)
325
326 }
327
328 /**
329 * 需求写一个校验函数,校验表格数据是否填写完整
330 * 1、表名称、数据库表、为空
331 * 2、tableDataDetailInfo.value 每一项中的字段名称、字段英文名、字段类型、长度、精度、是否唯一、是否必填、字段取值范围、关联字典、不能为空
332 */
333
334 const checkTableData = (tableDataInfo, tableDataDetailInfo) => {
335
336 const tableDataInfoKeys = ['tableName', 'tableChName']
337 const tableDataDetailInfoKeys = ['fieldName', 'fieldEnglish', 'fieldType', 'length', 'fieldPrecision', 'isUnique', 'isRequired', 'fieldValueRange', 'dictionaryGuid']
338 let flag = true
339 tableDataInfo.forEach(item => {
340 tableDataInfoKeys.forEach(key => {
341 if (!item[key]) {
342 flag = false
343 proxy.$ElMessage.error('表名称、数据库表不能为空')
344 }
345 })
346 })
347 tableDataDetailInfo.forEach(item => {
348 tableDataDetailInfoKeys.forEach(key => {
349 if (!item[key]) {
350 flag = false
351 proxy.$ElMessage.error('字段名称、字段英文名、字段类型、长度、精度、是否唯一、是否必填、字段取值范围、关联字典不能为空')
352 }
353 })
354 })
355 return flag
356 }
357
358 const guid = ref('')
359 const submit = async () => {
360 console.log('提交', tableDataDetailInfo.value, tableDataInfo.value)
361 // 校验表格数据是否填写完整
362 if (!checkTableData(tableDataDetailInfo.value, tableDataInfo.value)) {
363 return
364 }
365 /**
366 "guid": "string",
367 "cgDirName": "string",
368 "dirGuid": "string",
369 "tableGuid": "string",
370 "tableName": "string",
371 "tableChName": "string",
372 "databaseGuid": "string",
373 "database": "string",
374 "dbType": "string",
375 "databaseChName": "string",
376 "foundMode": 0,
377 "state": 0,
378 "isDraft": "string",
379 "fieldRQVOList": [
380 {
381 "guid": "string",
382 "cgDirName": "string",
383 "dirGuid": "string",
384 "classifyName": "string",
385 "gradeDetailName": "string",
386 "tableGuid": "string",
387 "tableName": "string",
388 "tableChName": "string",
389 "databaseGuid": "string",
390 "database": "string",
391 "databaseChName": "string",
392 "fieldGuid": "string",
393 "fieldName": "string",
394 "fieldChName": "string",
395 "fieldType": "string",
396 "fieldLength": 0,
397 "fieldPrecision": 0,
398 "dimGuid": "string",
399 "dictionaryGuid": "string",
400 "sortValue": 0,
401 "isPrimary": "string",
402 "isFk": "string",
403 "isNotNull": "string",
404 "defaultValue": "string"
405 }
406 ], 这是入参
407 */
408 // 如果提交时没有 guid 则为新增type 0,否则为修改 type 1, 也要传参
409 if (!guid.value) {
410 saveOrUpdate({}, 0)
411 } else {
412 saveOrUpdate({}, 1)
413 }
414
415 }
416
417 // 单独将保存和修改函数提取出来 type 0 保存 1 修改 2 生成建表语句
418 const saveOrUpdate = async (params: any = {}, type) => {
419 const InParams = {
420 guid: '',
421 cgDirName: '',
422 dirGuid: '',
423 tableGuid: '',
424 tableName: '',
425 tableChName: '',
426 databaseGuid: '',
427 database: '',
428 dbType: '',
429 databaseChName: '',
430 foundMode: 0,
431 state: 0,
432 isDraft: '',
433 fieldRQVOList: tableDataDetailInfo.value
434 }
435 const finalParams = { ...InParams, ...params }
436 // 使用switch case 语句
437 switch (type) {
438 case 0:
439 // 保存/保存为草稿
440 const res: any = await saveDbDirTable(finalParams);
441 if (res.code === proxy.$passCode) {
442 if (params.isDraft === 'Y') {
443 proxy.$ElMessage.success('保存为草稿成功!');
444 }
445 proxy.$ElMessage.success('保存成功!');
446 router.push({ name: 'classifyGradeCatalogue' });
447 } else {
448 proxy.$ElMessage.error(res.msg);
449 }
450 break;
451 case 1:
452 // 修改
453 const res1: any = await updateDbDirTable(finalParams);
454 if (res1.code === proxy.$passCode) {
455 proxy.$ElMessage.success('修改成功!');
456 router.push({ name: 'classifyGradeCatalogue' });
457 } else {
458 proxy.$ElMessage.error(res1.msg);
459 }
460 break;
461 case 2:
462 // 生成建表语句
463 const res2: any = await createTableSql(finalParams);
464 if (res2.code === proxy.$passCode) {
465 proxy.$ElMessage.success('建表生成成功!');
466 } else {
467 proxy.$ElMessage.error(res2.msg);
468 }
469 break;
470 default:
471 break;
472 }
473 }
474
475 // 生成建表弹窗区域
476
477 const options = [
478 { value: 'mysql', label: 'mysql' },
479 { value: 'doris', label: 'doris' },
480
481 ];
482
483 const newCreateSqlFormItems = ref([{
484 label: '选择数据库',
485 type: 'select',
486 maxlength: 50,
487 placeholder: '请输入',
488 field: 'name',
489 default: 'mysql',
490 options: options,
491 block: true,
492 clearable: true,
493 required: true
494 }]);
495
496 const newCreateSqlFormRules = ref({
497 name: [
498 { required: true, message: '请选择数据库名称', trigger: 'blur' },
499 ]
500 });
501
502 const newCreateSqlDialogInfo = ref({
503 visible: false,
504 size: 460,
505 title: "生成建表语句",
506 type: "",
507 formInfo: {
508 id: "grade-form",
509 items: newCreateSqlFormItems.value,
510 rules: newCreateSqlFormRules.value,
511 },
512 submitBtnLoading: false,
513 btns: {
514 cancel: () => {
515 newCreateSqlDialogInfo.value.visible = false;
516 },
517
518 submit: async (btn, info) => {
519 newCreateSqlDialogInfo.value.submitBtnLoading = true;
520 const params = {
521 ...info,
522 };
523 await saveOrUpdate(params, 2);
524 newCreateSqlDialogInfo.value.submitBtnLoading = false;
525 newCreateSqlDialogInfo.value.visible = false;
526 }
527 }
528 })
529
530 // 生成建表语句
531 const createNewSql = () => {
532 newCreateSqlDialogInfo.value.visible = true;
533 }
534
535
536 </script>
537
538 <template>
539 <div class="container_wrap full" v-loading.fullscreen.lock="fullscreenLoading">
540 <div class="content_main">
541 <div class="top_tool_wrap">
542 <StepBar :steps-info="stepsInfo" />
543 </div>
544 <existingTableSelect v-show="stepsInfo.step === 0" :databaseList="databaseList" :table-create-type="2"
545 :execGuid="execGuid" @datasource-selected-change="handlDsSelectedChange"></existingTableSelect>
546 <div class="second-step-content" v-show="stepsInfo.step === 1">
547 <div class="table_panel_wrap">
548 <el-table :data="tableDataInfo" :highlight-current-row="true" stripe border height="100%" row-key="guid"
549 tooltip-effect="light" :style="{
550 width: '100%',
551 'max-height': 'calc(100% - 16px)',
552 display: 'inline-block',
553 }">
554 <!-- 表名称列 -->
555 <el-table-column prop="tableName" label="表名称" width="180">
556 <template #header>
557 <span>表名称</span>
558 <span style="color:red;margin-left: 2px;">*</span>
559 </template>
560 <template #default="scope">
561 <el-input v-model="scope.row.tableName" placeholder="请输入表名称" />
562 </template>
563 </el-table-column>
564
565 <!-- 数据库表列 -->
566 <el-table-column prop="tableChName" label="数据库表" width="280">
567 <template #header>
568 <span>数据库表</span>
569 <span style="color:red;margin-left: 2px;">*</span>
570 </template>
571 <template #default="scope">
572 <el-input v-model="scope.row.tableChName" placeholder="请输入数据库表" />
573 </template>
574 </el-table-column>
575
576 <!-- 描述列 -->
577 <el-table-column prop="description" label="描述" width="180">
578 <template #default="scope">
579 <el-input v-model="scope.row.description" placeholder="请输入描述" />
580 </template>
581 </el-table-column>
582 </el-table>
583 </div>
584 <div class="btn-area">
585 <el-button type="primary" @click="addRow">新增</el-button>
586 <el-button @click="moveUp">上移</el-button>
587 <el-button @click="moveDown">下移</el-button>
588 <el-button @click="batchDelete">批量删除</el-button>
589 <el-button @click="createNewSql">生成建表语句</el-button>
590 </div>
591 <div class="bottom_table">
592 <el-table :data="tableDataDetailInfo" v-loading="tableFieldsLoading" :highlight-current-row="true" stripe
593 border height="100%" row-key="guid" @selection-change="selectionFieldsChange" tooltip-effect="light" :style="{
594 width: '100%',
595 'max-height': 'calc(100% - 16px)',
596 display: 'inline-block',
597 }">
598 <el-table-column type="selection" :width="32" align="center" />
599 <!-- 排序列(不可编辑) -->
600 <el-table-column prop="id" label="排序" width="80" align="center" />
601 <!-- 字段中文名(不可编辑)fieldChName -->
602 <el-table-column prop="fieldName" label="字段中文名" width="150">
603 <template #default="scope">
604 {{ scope.row.fieldName ? scope.row.fieldName : '--' }}
605 </template>
606 </el-table-column>
607 <!-- 字段英文名(不可编辑) -->
608 <el-table-column prop="fieldEnglish" label="字段英文名" width="150">
609 <template #default="scope">
610 {{ scope.row.fieldEnglish ? scope.row.fieldEnglish : '--' }}
611 </template>
612 </el-table-column>
613 <!-- 分类(不可编辑)classifyName -->
614 <el-table-column prop="classifyName" label="分类" width="150">
615 <template #default="scope">
616 {{ scope.row.classifyName ? scope.row.classifyName : '--' }}
617 </template>
618 </el-table-column>
619 <!-- 分级(不可编辑) -->
620 <el-table-column prop="gradeDetailName" label="分级" width="120" align="center">
621 <template #default="scope">
622 {{ scope.row.gradeDetailName ? scope.row.gradeDetailName : '--' }}
623 </template>
624 </el-table-column>
625 <!-- 字段类型fieldType (不可编辑) -->
626 <el-table-column prop="fieldType" label="字段类型" width="150" align="center">
627 <template #default="scope">
628 {{ scope.row.fieldType ? scope.row.fieldType : '--' }}
629 </template>
630 </el-table-column>
631
632 <!-- 长度(可编辑) -->
633 <el-table-column prop="length" label="长度" width="120" align="center">
634 <template #default="scope">
635 <span v-if="!scope.row.isEdit || !editableFields.length">{{ scope.row.length ? scope.row.length
636 : '--' }}</span>
637 <el-input v-else v-model="scope.row.length" placeholder="请输入长度" />
638 </template>
639 </el-table-column>
640 <!-- 精度(可编辑)fieldPrecision -->
641 <el-table-column prop="fieldPrecision" label="精度" width="120" align="center">
642 <template #default="scope">
643 <span v-if="!scope.row.isEdit || !editableFields.fieldPrecision">{{ scope.row.fieldPrecision ?
644 scope.row.fieldPrecision : '--' }}</span>
645 <el-input v-else v-model="scope.row.fieldPrecision" placeholder="请输入精度" />
646 </template>
647 </el-table-column>
648
649 <!-- 关联字典(可编辑)el-tree-select 形式下拉形式 -->
650 <el-table-column prop="dictionaryGuid" label="关联字典" width="150" align="center">
651 <template #default="scope">
652 <span v-if="!scope.row.isEdit || !editableFields.dictionaryGuid">{{ scope.row.isDict ? scope.row.isDict
653 : '--' }}</span>
654 <el-tree-select v-else v-model="scope.row.isDict" :data="data" placeholder="请选择" />
655 </template>
656 </el-table-column>
657
658 <!-- 数据是否唯一(可编辑) -->
659 <el-table-column prop="isUnique" label="数据是否唯一" width="150" align="center">
660 <template #default="scope">
661 <span v-if="!scope.row.isEdit || !editableFields.isUnique">{{ scope.row.isUnique ? scope.row.isUnique :
662 '--' }}</span>
663 <el-select v-else v-model="scope.row.isUnique" placeholder="请选择">
664 <el-option label="是" value="是" />
665 <el-option label="否" value="否" />
666 </el-select>
667 </template>
668 </el-table-column>
669 <!-- 是否必填(可编辑) -->
670 <el-table-column prop="isRequired" label="是否必填" width="120" align="center">
671 <template #default="scope">
672 <span v-if="!scope.row.isEdit">{{ scope.row.isRequired ? scope.row.isRequired : '--' }}</span>
673 <el-select v-else v-model="scope.row.isRequired" placeholder="请选择">
674 <el-option label="是" value="是" />
675 <el-option label="否" value="否" />
676 </el-select>
677 </template>
678 </el-table-column>
679 <!-- 字段取值范围 fieldValueRange(可编辑)-->
680 <el-table-column prop="fieldValueRange" label="字段取值范围" width="150" align="center">
681 <template #default="scope">
682 <span v-if="!scope.row.isEdit">{{ scope.row.fieldValueRange ? scope.row.fieldValueRange : '--' }}</span>
683 <el-input v-else v-model="scope.row.fieldValueRange" placeholder="请输入字段取值范围" />
684 </template>
685 </el-table-column>
686
687 <!-- 操作列 -->
688 <el-table-column label="操作" width="100" align="center" fixed="right">
689 <template #default="scope">
690
691 <!-- <el-button v-if="!scope.row.isEdit" type="primary" size="small" @click="editRow(scope.row)">
692 编辑
693 </el-button> -->
694 <!-- <el-button v-else type="success" size="small" @click="saveRow(scope.row)">
695 保存
696 </el-button>
697
698 <el-button type="danger" size="small" @click="deleteRow(scope.$index)">
699 删除
700 </el-button> -->
701 <span class="text_btn" v-if="!scope.row.isEdit" @click="editRow(scope.row)">编辑</span>
702 <span class="text_btn" v-else @click="saveRow(scope.row)">保存</span>
703 <el-divider direction="vertical" />
704 <span class="text_btn" @click="deleteRow(scope.$index)">删除</span>
705 </template>
706 </el-table-column>
707 </el-table>
708 </div>
709 </div>
710 </div>
711 <div class="bottom_tool_wrap">
712 <template v-if="stepsInfo.step == 0">
713 <el-button type="primary" @click="nextStep">下一步</el-button>
714 </template>
715 <template v-else>
716 <el-button @click="previousStep">上一步</el-button>
717 <el-button type="primary" @click="submitAsDraft">保存为草稿</el-button>
718 <el-button type="primary" @click="submit">提交</el-button>
719 </template>
720 </div>
721 <Dialog_form :dialogConfigInfo="newCreateSqlDialogInfo" />
722 </div>
723 </template>
724
725 <style lang="scss" scoped>
726 .top_tool_wrap {
727 width: 100%;
728 height: 80px;
729 display: flex;
730 justify-content: center;
731 align-items: center;
732 border-bottom: 1px solid #d9d9d9;
733
734 :deep(.el-steps) {
735 width: 30%;
736 }
737 }
738
739 .content_main {
740 height: calc(100% - 40px);
741
742 .second-step-content {
743 height: calc(100% - 80px);
744 width: 100%;
745 padding: 16px;
746
747 .table_panel_wrap {
748 width: 100%;
749 height: auto;
750 overflow: visible;
751 }
752
753
754 .btn-area {
755 margin-top: 12px;
756 }
757
758 :deep(.bottom_table) {
759 margin-top: 12px;
760 height: calc(100% - 150px);
761 overflow-y: auto;
762
763 .el-table td.el-table__cell {
764 padding: 2px 0;
765 height: 36px;
766 }
767 }
768 }
769 }
770
771 :deep(.el-dialog) {
772 .dialog-form-inline {
773 .checkbox_input {
774 display: flex;
775 flex-direction: column;
776
777 .input_panel {
778 margin: 0;
779 }
780 }
781
782 .select_group {
783 .el-form-item__content>.el-input {
784 margin-top: 21px;
785 }
786 }
787
788 .radio_panel {
789 .panel_content {
790 display: none;
791 }
792 }
793 }
794 }
795
796 :deep(.batchDialog) {
797 .el-tree-node__content {
798 padding-left: 8px !important;
799
800 .el-icon {
801 display: none;
802 }
803 }
804 }
805
806 .bottom_tool_wrap {
807 height: 40px;
808 padding: 0 16px;
809 border-top: 1px solid #d9d9d9;
810 display: flex;
811 justify-content: flex-end;
812 align-items: center;
813 }
814 </style>
1 <route lang="yaml">
2 name: tableCreateFile
3 </route>
4
5 <script lang="ts" setup name="tableCreateFile">
6
7 import { ref } from "vue";
8 import { ElMessage, ElMessageBox, ElTable } from "element-plus";
9 import useUserStore from "@/store/modules/user";
10 import useDataCatalogStore from "@/store/modules/dataCatalog";
11 import expandPropertyDialog from "./expandPropertyDialog.vue";
12 import tableDefaultValue from "./components/tableDefaultValue.vue";
13 // import {
14 // getDatabase,
15 // getFileStandards,
16 // getDictionary,
17 // getSubjectFieldByFile,
18 // tableCategoryList,
19 // syncPolicys,
20 // getDataTypeList,
21 // tableModels,
22 // aggMethodList,
23 // getCharacterList,
24 // saveSubjectTable,
25 // updateSubjectTable,
26 // getTableStandardDetail,
27 // getSubjectDomainDetail,
28 // saveSubjectTableDraft,
29 // updateSubjectTableDraft,
30 // getFieldStandardTree,
31 // dimTypeList,
32 // getDimList,
33 // getSubjectTableDetail,
34 // checkSubjectTableData
35 // } from "@/api/modules/dataCatalogService";
36 import { useDefault } from "@/hooks/useDefault";
37 import uploadExcelFile from "./components/uploadExcelFile.vue";
38
39 const userStore = useUserStore();
40 const dataCatalogStore = useDataCatalogStore();
41 const { checkDefault } = useDefault();
42 const userData = JSON.parse(userStore.userData);
43 const { proxy } = getCurrentInstance() as any;
44 const router = useRouter();
45 const route = useRoute();
46 const isDimTable = route.query.isDim;
47 const subjectDomainGuid: any = ref(route.query.domainGuid);
48 const fullPath = route.fullPath;
49 const standardSetGuids = ref([]);
50 //记录已入库的表创建信息。
51 const originTableCreateInfo = ref({});
52
53 //记录当前正在编辑的表创建信息。
54 const tableCreateInfo: Ref<any> = ref({
55 guid: "",
56 isCreate: false,
57 inputNameValue: '',
58 isSync: 'Y', //是否默认同步数据。
59 sheetName: '', //所选择的sheet页。
60 tableData: [
61 {
62 //数据库表信息。
63 dataSourceGuid: '',
64 dataServerName: "",
65 dataServerChName: "",
66 enName: "",
67 chName: "",
68 subjectDomain: route.query.domainName,
69 subjectDomainGuid: subjectDomainGuid.value,
70 tableCategory: route.query.layereAttribute == '3' ? 6 : 1,
71 dimType: isDimTable ? 1 : null,
72 codeColumn: '',
73 codeName: '',
74 syncPolicy: 3,
75 characterSet: 'utf8mb3',
76 tableModel: 1, //若是聚合模型,下方出现一列聚合方式选择。处了主键列,其余列都需要选择。每个表里都要有主键。
77 description: "",
78 },
79 ],
80 partitionAttribute: {},
81 tableFields: [], // 字段标准数组。
82 });
83
84 const stepsInfo = ref({
85 step: 0,
86 list: [
87 { title: "上传文件", value: 1 },
88 { title: "设置属性字段", value: 2 },
89 ],
90 });
91
92 /** 上传的文件字段信息。 */
93 const fileTableFields: any = ref([]);
94 /** 上传的文件数据信息 */
95 const fileTableData: any = ref([]);
96 /** 上传的文件信息。 */
97 const uploadDataFileInfo: any = ref([]);
98
99 const handleFileDataChange = (fileFields, files, sheetName, data) => {
100 if (fileTableFields.value != fileFields) {//文件字段改变,下一步时需要清空。
101 fileTableFields.value = fileFields.slice(0);
102 tableCreateInfo.value.tableFields = [];
103 }
104 fileTableData.value = data;
105 uploadDataFileInfo.value = files;
106 tableCreateInfo.value.sheetName = sheetName;
107 console.log(files);
108 }
109
110 const uploadFileRef = ref();
111
112 // const getSubjectField = () => {
113 // tableFieldsLoading.value = true;
114 // getSubjectFieldByFile(fileTableFields.value.map(f => f.chName), tableCreateInfo.value.tableData[0].subjectDomainGuid).then((res: any) => {
115 // tableFieldsLoading.value = false;
116 // if (res.code == proxy.$passCode) {
117 // tableCreateInfo.value.tableFields = res.data?.map((field, i) => {
118 // field.dimOrdictionaryGuid = field.dictionaryGuid;
119 // field.fileFieldName = fileTableFields.value[i].chName;
120 // field.isEdit = true;
121 // !field.notNull && (field.notNull = 'N');
122 // return field;
123 // }) || [];
124 // } else {
125 // ElMessage.error(res.msg);
126 // }
127 // });
128 // }
129
130 const nextStep = () => {
131 uploadFileRef.value.fileFormRef.ruleFormRef.validate((valid) => {
132 if (valid) {
133 if (!fileTableFields.value.length) {
134 ElMessage({
135 type: "error",
136 message: "上传文件字段不能为空!",
137 });
138 return;
139 }
140 if (!fileTableData.value.length) {
141 tableCreateInfo.value.isSync = 'N';
142 } else {
143 tableCreateInfo.value.isSync = 'Y';
144 }
145 stepsInfo.value.step = 1;
146 // getDictionaryList();
147 // getDimListData();
148 // if (!fieldTypes.value.length) {
149 // getFieldTypeList();
150 // getCharacterListData();
151 // }
152 // if (!databaseList.value.length) {
153 // getDatabaseList();
154 // }
155 // getDomainDetail(subjectDomainGuid.value);
156 // if (!tableCreateInfo.value.tableFields.length) {
157 // getSubjectField();
158 // }
159 }
160 });
161 };
162
163 const isPrevious = ref(false);
164
165 /** 上一步 */
166 const previousStep = () => {
167 stepsInfo.value.step = 0;
168 isPrevious.value = true;
169 };
170
171 /** 记录是否开启字段标准,根据主题域相关信息获取 */
172 const isOpenStandard = ref(true);
173
174 const selectTableFieldRows = ref([]);
175
176 const tableStandardGuid = ref('');
177 const tableStandardDetail: any = ref({});
178 const fieldStandardSetGuids = ref([]);
179
180 // 实际显示的字段标准列表
181 const standardListOptions: any = ref([]);
182
183 const databaseList: any = ref([]);
184
185 //字段类型
186 const fieldTypes: any = ref([]);
187
188 //字符集
189 const characterList: any = ref([]);
190
191 //是否列表
192 const isNotList = ref([
193 {
194 label: "Y",
195 value: "Y",
196 },
197 {
198 label: "N",
199 value: "N",
200 },
201 ]);
202
203 const batchAddFieldStandardPage = ref({
204 pageSize: 50,
205 pageIndex: 1,
206 standardSetGuids: [],
207 approveState: 'Y',
208 name: '',
209 standardSetLevelCode: ""
210 });
211
212 const init = ref(true);
213
214 const fullscreenLoading = ref(false);
215
216 /** 表里有数据时不能修改字段类型,长度,精度 */
217 const hasSubjectData = ref(false);
218
219
220
221 /** 保存表 */
222 const saveTable = () => {
223 }
224 </script>
225
226 <template>
227 <div class="container_wrap full" v-loading.fullscreen.lock="fullscreenLoading">
228 <div class="content_main">
229 <div class="top_tool_wrap">
230 <StepBar :steps-info="stepsInfo" />
231 </div>
232 <uploadExcelFile ref="uploadFileRef" v-show="stepsInfo.step === 0" @fileDataChange="handleFileDataChange">
233 </uploadExcelFile>
234 <div class="second-step-content" v-show="stepsInfo.step === 1">
235 aaa
236 </div>
237 </div>
238 <div class="bottom_tool_wrap">
239 <template v-if="stepsInfo.step == 0">
240 <el-button type="primary" @click="nextStep">下一步</el-button>
241 </template>
242 <template v-else>
243 <el-checkbox v-model="tableCreateInfo.isSync" true-label="Y" :disabled="!fileTableData?.length"
244 false-label="N">同步数据(说明:勾选代表建表同时写入表格数据。)</el-checkbox>
245 <el-button @click="previousStep">上一步</el-button>
246 <el-button type="primary">保存为草稿</el-button>
247 <el-button type="primary" @click="saveTable">提交</el-button>
248 </template>
249 </div>
250
251 </div>
252 </template>
253
254 <style lang="scss" scoped>
255 .top_tool_wrap {
256 width: 100%;
257 height: 80px;
258 display: flex;
259 justify-content: center;
260 align-items: center;
261 border-bottom: 1px solid #d9d9d9;
262
263 :deep(.el-steps) {
264 width: 30%;
265 }
266 }
267
268 .content_main {
269 height: calc(100% - 40px);
270
271 .header-bg-title {
272 margin: 16px 16px 0px;
273 background: #F5F5F5;
274 padding-left: 16px;
275 height: 48px;
276 font-size: 14px;
277 color: #212121;
278 letter-spacing: 0;
279 line-height: 21px;
280 font-weight: 600;
281 display: flex;
282 align-items: center;
283 position: relative;
284
285 .preview-data-totals {
286 position: absolute;
287 right: 16px;
288 line-height: 32px;
289 font-size: 14px;
290 color: #666666;
291 font-weight: 400;
292 }
293
294 .fontC-4fa1a4 {
295 color: var(--el-color-primary);
296 }
297 }
298
299 .form-main {
300 border: 1px solid #d9d9d9;
301 margin: 0px 16px;
302 padding: 16px 16px 0px 16px;
303 height: 125px;
304
305 .dialog-form-inline {
306 align-items: flex-start;
307 }
308
309 :deep(.el-form) {
310 .item-label {
311 width: 100%;
312 }
313
314 .el-select {
315 max-width: 300px;
316 }
317 }
318 }
319
320 .table-main {
321 height: calc(100% - 350px);
322 border: 1px solid #d9d9d9;
323 margin: 0px 16px 16px 16px;
324 padding: 16px;
325 }
326
327 .empty-content {
328 display: flex;
329 align-items: center;
330 justify-content: center;
331 height: 100%;
332 width: 100%;
333 flex-direction: column;
334
335 .empty-text {
336 font-size: 14px;
337 color: #b2b2b2;
338 }
339 }
340
341 .second-step-content {
342 height: calc(100% - 80px);
343 width: 100%;
344 padding: 16px;
345
346 .tools_btns {
347 padding: 8px 0;
348 }
349
350 :deep(.el-table) {
351 .cell {
352
353 .prefix-or-suffix-cell {
354 display: inline-flex;
355 align-items: center;
356 }
357 }
358 }
359
360 .table_panel {
361 height: calc(100% - 114px);
362 }
363
364 :deep(.el-table) {
365 & td.el-table__cell {
366 padding: 3px 0;
367 height: 36px;
368 }
369 }
370 }
371 }
372
373 :deep(.el-dialog) {
374 .dialog-form-inline {
375 .checkbox_input {
376 display: flex;
377 flex-direction: column;
378
379 .input_panel {
380 margin: 0;
381 }
382 }
383
384 .select_group {
385 .el-form-item__content>.el-input {
386 margin-top: 21px;
387 }
388 }
389
390 .radio_panel {
391 .panel_content {
392 display: none;
393 }
394 }
395 }
396 }
397
398 :deep(.batchDialog) {
399 .el-tree-node__content {
400 padding-left: 8px !important;
401
402 .el-icon {
403 display: none;
404 }
405 }
406 }
407
408 .bottom_tool_wrap {
409 height: 40px;
410 padding: 0 16px;
411 border-top: 1px solid #d9d9d9;
412 display: flex;
413 justify-content: flex-end;
414 align-items: center;
415
416 .el-checkbox {
417 margin-right: 20px;
418 }
419
420 :deep(.el-checkbox__input.is-checked + .el-checkbox__label) {
421 color: var(--el-color-regular);
422 }
423 }
424 </style>
...@@ -137,6 +137,9 @@ const handleClassDataEdit = (params) => { ...@@ -137,6 +137,9 @@ const handleClassDataEdit = (params) => {
137 if (item.field === 'classStandardName') { 137 if (item.field === 'classStandardName') {
138 item.default = params.name 138 item.default = params.name
139 } 139 }
140 if (item.field === 'description') {
141 item.default = params.description
142 }
140 }) 143 })
141 } 144 }
142 145
...@@ -209,6 +212,15 @@ const classStandardFormItems = ref([{ ...@@ -209,6 +212,15 @@ const classStandardFormItems = ref([{
209 default: '', 212 default: '',
210 required: true, 213 required: true,
211 block: true, 214 block: true,
215 }, {
216 label: '分类描述',
217 type: 'textarea',
218 placeholder: '请输入',
219 field: 'description',
220 default: '',
221 clearable: true,
222 required: false,
223 block: true
212 }]); 224 }]);
213 225
214 const classStandardFormRules = ref({ 226 const classStandardFormRules = ref({
...@@ -235,6 +247,7 @@ const newCreateClassStandardDialogInfo = ref({ ...@@ -235,6 +247,7 @@ const newCreateClassStandardDialogInfo = ref({
235 if (newCreateClassStandardDialogInfo.value.title === '新增分类') { 247 if (newCreateClassStandardDialogInfo.value.title === '新增分类') {
236 newCreateClassStandardDialogInfo.value.submitBtnLoading = true; 248 newCreateClassStandardDialogInfo.value.submitBtnLoading = true;
237 const params = { 249 const params = {
250 description: info.description,
238 name: info.classStandardName, 251 name: info.classStandardName,
239 refGradeGuid: info.refGradeGuid, 252 refGradeGuid: info.refGradeGuid,
240 type: 'C' 253 type: 'C'
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!