作者 yangfu

Merge branch 'test' into dev

正在显示 88 个修改的文件 包含 3824 行增加248 行删除

要显示太多修改。

为保证性能只显示 88 of 88+ 个文件。

@@ -23,6 +23,7 @@ _testmain.go @@ -23,6 +23,7 @@ _testmain.go
23 *.test 23 *.test
24 .log 24 .log
25 .idea 25 .idea
  26 +.vscode
26 27
27 app.log 28 app.log
28 go.sum 29 go.sum
1 FROM golang:latest 1 FROM golang:latest
  2 +#FROM 192.168.0.243:5000/mmm/character-library-metadata-bastion:base
2 ENV APP_DIR $GOPATH/src/character-library-metadata-bastion 3 ENV APP_DIR $GOPATH/src/character-library-metadata-bastion
3 RUN mkdir -p $APP_DIR 4 RUN mkdir -p $APP_DIR
4 WORKDIR $APP_DIR/ 5 WORKDIR $APP_DIR/
@@ -8,7 +9,7 @@ COPY ./go.mod go.mod @@ -8,7 +9,7 @@ COPY ./go.mod go.mod
8 COPY ./main.go main.go 9 COPY ./main.go main.go
9 RUN ["ln","-sf","/usr/share/zoneinfo/Asia/Shanghai","/etc/localtime"] 10 RUN ["ln","-sf","/usr/share/zoneinfo/Asia/Shanghai","/etc/localtime"]
10 ENV GO111MODULE on 11 ENV GO111MODULE on
11 -ENV GOPROXY https://goproxy.io 12 +ENV GOPROXY https://goproxy.cn
12 RUN ["go","mod","tidy"] 13 RUN ["go","mod","tidy"]
13 RUN ["ls"] 14 RUN ["ls"]
14 RUN ["go","build"] 15 RUN ["go","build"]
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 ## 源文件管理 3 ## 源文件管理
4 4
5 - 文件列表 - list 5 - 文件列表 - list
6 -- 上传 - 上传oss / 创建file 6 +- 上传 - 上传 oss / 创建 file
7 - 加载 - loadDataTable 7 - 加载 - loadDataTable
8 - 编辑 - editDataTable 8 - 编辑 - editDataTable
9 - 持久化 - flushDataTable 9 - 持久化 - flushDataTable
@@ -11,7 +11,6 @@ @@ -11,7 +11,6 @@
11 - 删除 - delete 11 - 删除 - delete
12 - 操作日志 - log 12 - 操作日志 - log
13 13
14 -  
15 - editDataTable params 列表 14 - editDataTable params 列表
16 15
17 ### 加载表格数据 loadDataTable - 查询 16 ### 加载表格数据 loadDataTable - 查询
@@ -20,15 +19,15 @@ @@ -20,15 +19,15 @@
20 { 19 {
21 "fileId": 1, 20 "fileId": 1,
22 "where": [ 21 "where": [
23 - {  
24 - "field": {  
25 - "index": 1,  
26 - "name": "产品名称"  
27 - },  
28 - "in": ["a","b"],  
29 - "ex": ["c","d"],  
30 - "sort": ["a","asc"]  
31 - } 22 + {
  23 + "field": {
  24 + "index": 1,
  25 + "name": "产品名称"
  26 + },
  27 + "in": ["a", "b"],
  28 + "ex": ["c", "d"],
  29 + "sort": ["a", "asc"]
  30 + }
32 ] 31 ]
33 } 32 }
34 ``` 33 ```
@@ -37,137 +36,523 @@ @@ -37,137 +36,523 @@
37 36
38 ```json 37 ```json
39 { 38 {
40 - "field": {  
41 - "index": 1,  
42 - "name": "产品名称"  
43 - },  
44 - "operation": {  
45 - "desc": ["拆分","按字符数"],  
46 - "code": "split_by_char_number"  
47 - },  
48 - "params": [] 39 + "field": {
  40 + "index": 1,
  41 + "name": "产品名称"
  42 + },
  43 + "operation": {
  44 + "desc": ["拆分", "按字符数"],
  45 + "code": "split_by_char_number"
  46 + },
  47 + "params": []
49 } 48 }
50 ``` 49 ```
  50 +
51 精简 51 精简
  52 +
52 ```json 53 ```json
53 { 54 {
54 - "field": "产品名称",  
55 - "desc": ["拆分","按字符数"],  
56 - "operationCode": "split_by_char_number",  
57 - "params": [] 55 + "field": "产品名称",
  56 + "desc": ["拆分", "按字符数"],
  57 + "operationCode": "split_by_char_number",
  58 + "params": []
58 } 59 }
59 ``` 60 ```
60 61
61 `params 列表` 62 `params 列表`
62 63
63 -  
64 ### 数据展示 64 ### 数据展示
65 65
66 ```json 66 ```json
67 { 67 {
68 - "code": 0,  
69 - "data": {  
70 - "dataFields": [  
71 - {  
72 - "index": 1,  
73 - "name": "产品名称",  
74 - "type": "string"  
75 - },  
76 - {  
77 - "index": 2,  
78 - "name": "产品数量",  
79 - "type": "int"  
80 - }  
81 - ],  
82 - "dataRows": [  
83 - [  
84 - "素面",  
85 - 200  
86 - ],  
87 - [  
88 - "冻豆腐",  
89 - 400  
90 - ],  
91 - [  
92 - "冻豆腐1",  
93 - 300  
94 - ],  
95 - [  
96 - "冻豆2",  
97 - "A"  
98 - ]  
99 - ],  
100 - "total": 100,  
101 - "pageNumber": 1,  
102 - "inValidCells": [  
103 - {  
104 - "x": 1,  
105 - "y": 3,  
106 - "error": "不是一个有效的数值"  
107 - }  
108 - ]  
109 - },  
110 - "msg": "ok" 68 + "code": 0,
  69 + "data": {
  70 + "dataFields": [
  71 + {
  72 + "index": 1,
  73 + "name": "产品名称",
  74 + "type": "string"
  75 + },
  76 + {
  77 + "index": 2,
  78 + "name": "产品数量",
  79 + "type": "int"
  80 + }
  81 + ],
  82 + "dataRows": [
  83 + ["素面", 200],
  84 + ["冻豆腐", 400],
  85 + ["冻豆腐1", 300],
  86 + ["冻豆2", "A"]
  87 + ],
  88 + "total": 100,
  89 + "pageNumber": 1,
  90 + "inValidCells": [
  91 + {
  92 + "x": 1,
  93 + "y": 3,
  94 + "error": "不是一个有效的数值"
  95 + }
  96 + ]
  97 + },
  98 + "msg": "ok"
111 } 99 }
112 ``` 100 ```
113 101
114 -  
115 ## 表关联关系 102 ## 表关联关系
116 103
117 -- [x] 可追加数据的表列表 /tables/search-appended-list  
118 -- [x] 校验文件列表 /files/search-verified-file  
119 -- [x] 匹配方案列表 /mapping-rule-config/search  
120 -- [x] 匹配方案主表 /mapping-rule-config/prepare //主表 校验表 主表字段 校验文件表字段  
121 -- [x] 匹配方案添加 /mapping-rule-config/  
122 -- [x] 匹配方案删除 /mapping-rule-config/:id  
123 -- [x] 追加数据到表格 /append-data-to-table // 验证是否追加过  
124 -- [ ] 取消校验中的文件 /cancel-verifying-file //  
125 -  
126 -- [x] 表结构更新 /tables/update-table-struct  
127 -- [x] 表结构添加 /tables/add-table-struct  
128 -- [x] 分表列表 /tables/search  
129 -- [x] 表复制 /tables/copy-data-table  
130 -- [x] 表删除 /tables/:id // 若是删除主表,需级联删除关联的分表,删除内容包括表数据及表结构;? 分表的副表是否要删除  
131 -- [x] 表详情 /tables/:id // 表结构  
132 -- [x] 表更新 /tables/:id // 表结构、分表才可以编辑  
133 -  
134 -- [x] 日志搜索 /log/search  
135 -- [x] 校验步骤日志 /log/verified-step-Log 104 +- [x] 可追加数据的表列表 /tables/search-appended-list
  105 +- [x] 校验文件列表 /files/search-verified-file
  106 +- [x] 匹配方案列表 /mapping-rule-config/search
  107 +- [x] 匹配方案主表 /mapping-rule-config/prepare //主表 校验表 主表字段 校验文件表字段
  108 +- [x] 匹配方案添加 /mapping-rule-config/
  109 +- [x] 匹配方案删除 /mapping-rule-config/:id
  110 +- [x] 追加数据到表格 /append-data-to-table // 验证是否追加过
  111 +- [ ] 取消校验中的文件 /cancel-verifying-file //
  112 +
  113 +- [x] 表结构更新 /tables/update-table-struct
  114 +- [x] 表结构添加 /tables/add-table-struct
  115 +- [x] 分表列表 /tables/search
  116 +- [x] 表复制 /tables/copy-data-table
  117 +- [x] 表删除 /tables/:id // 若是删除主表,需级联删除关联的分表,删除内容包括表数据及表结构;? 分表的副表是否要删除
  118 +- [x] 表详情 /tables/:id // 表结构
  119 +- [x] 表更新 /tables/:id // 表结构、分表才可以编辑
  120 +
  121 +- [x] 日志搜索 /log/search
  122 +- [x] 校验步骤日志 /log/verified-step-Log
136 123
137 ## 数据预览 124 ## 数据预览
138 -- [x] 表数据预览(格式) /table/preview  
139 -- [x] 表数据自定义查询 /table/preview where conditions 升序、降序 包含、不包含  
140 -- [x] 表数据字段可选值搜索 /table/field-optional 文本匹配 125 +
  126 +- [x] 表数据预览(格式) /table/preview
  127 +- [x] 表数据自定义查询 /table/preview where conditions 升序、降序 包含、不包含
  128 +- [x] 表数据字段可选值搜索 /table/field-optional 文本匹配
141 - [x] 表数据更新、添加、删除 /table/row-data-mutation 129 - [x] 表数据更新、添加、删除 /table/row-data-mutation
142 -- [x] 表数据导出 /table/export-table 130 +- [x] 表数据导出 /table/export-table
143 131
144 ## 数据验证 132 ## 数据验证
145 133
146 -- [x] 文件验证 /data/edit-data-table 134 +- [x] 文件验证 /data/edit-data-table
147 135
148 ## 底层字库接口 136 ## 底层字库接口
149 137
150 -```json  
151 -{  
152 - "file": {},  
153 - "fields": [],  
154 - "action":"filed_rename",  
155 - "params": ["产品名2"]  
156 -}  
157 -```  
158 -- [ ] 数据预览 1  
159 -- [ ] 表格编辑 1  
160 -- [ ] 保存校验文件 (文件地址) 1  
161 -- [ ] 生成主表 1  
162 -- [ ] 表复制 (副表)  
163 -- [ ] 追加数据 (主表、副表) 138 +- [x] 数据预览 1
  139 +- [x] 表格编辑 1
  140 +- [x] 保存校验文件 (文件地址) 1
  141 +- [x] 生成主表 1
  142 +- [x] 表复制 (副表)1
  143 +- [x] 追加数据 (主表、副表)
164 - [ ] 表删除 (主表、副表)~~、分表~~ 144 - [ ] 表删除 (主表、副表)~~、分表~~
165 -- [x] ~~表拆分~~  
166 -- [x] ~~更新表结构(分表)~~  
167 -- [ ] 编辑、添加、删除表数据(副表) 1 145 +- [x] 表拆分 1
  146 +- [x] 更新表结构(分表)1
  147 +- [x] 编辑、添加、删除表数据(副表) 1
168 - [ ] 取消校验 148 - [ ] 取消校验
169 149
170 ## 定时作业 150 ## 定时作业
171 151
172 - [x] 隔天清理校验中的文件 152 - [x] 隔天清理校验中的文件
173 -- [x] 隔天清理public临时文件  
  153 +- [x] 隔天清理 public 临时文件
  154 +
  155 +## 表数据导出
  156 +
  157 +- [ ] 加锁,只允许当前用户同时只能发起一次导出命令 ,3min 过期
  158 +- [ ] 单次拉取数量 MR
  159 + - [ ] 100W ..
  160 + - [ ] 50W 120s 读取数据库:30s 保存文件:10s 下载:30M/500K=60S;RAR 压缩 24M/500k=50S
  161 + - [ ] 20W ..
  162 + - [ ] 10W ..
  163 +- [ ] 保存单个文件、压缩 | 保存多个文件、压缩
  164 +
  165 +## 表达式解析
  166 +
  167 +### 表达式类型说明
  168 +- ValueExprAST: 值表达式(数值,字符串) e.g. 1 、 2011-1-1 、字符串
  169 +```json
  170 +{
  171 + "exprType":"ValueExprAST",
  172 + "val":"",
  173 + "str":"业绩2"
  174 +}
  175 +```
  176 +- FieldExprAST: 字段表达式(处理的字段) e.g. 生产明细.业绩
  177 +```json
  178 +{
  179 + "exprType":"FieldExprAST",
  180 + "str":"业绩1",
  181 + "field":{
  182 + "tableId":1,
  183 + "tableName":"测试ABC",
  184 + "tableSqlName":"table_abc_test",
  185 + "fieldName":"业绩",
  186 + "fieldSqlName":"ye_ji_1",
  187 + "fieldSqlType":"Float"
  188 + }
  189 +}
  190 +```
  191 +- BinaryExprAST: 二元表达式 e.g. 1 + 2 、 100 * 生产明细.业绩
  192 +```json
  193 +{
  194 + "exprType":"BinaryExprAST",
  195 + "op":"/",
  196 + "lhs":{},
  197 + "rhs":{}
  198 +}
  199 +```
  200 +
  201 +- FunCallerExprAST:函数表达式 e.g. sum(arg1,arg2,arg3)
  202 +```json
  203 +{
  204 + "arrayFlag": false,
  205 + "exprType": "FunCallerExprAST",
  206 + "name": "sum",
  207 + "args": []
  208 +}
  209 +```
  210 +
  211 +### 用例
  212 +- 输入表达式 `SUM(1/COUNTIFS(【业绩】,【业绩】))`
  213 +```json
  214 +{
  215 + "arrayFlag":false,
  216 + "exprType":"FunCallerExprAST",
  217 + "name":"sum",
  218 + "args":[
  219 + {
  220 + "exprType":"BinaryExprAST",
  221 + "op":"/",
  222 + "lhs":{
  223 + "exprType":"ValueExprAST",
  224 + "val":"",
  225 + "str":"1"
  226 + },
  227 + "rhs":{
  228 + "arrayFlag":false,
  229 + "exprType":"FunCallerExprAST",
  230 + "name":"countifs",
  231 + "args":[
  232 + {
  233 + "exprType":"FieldExprAST",
  234 + "str":"业绩1",
  235 + "field":{
  236 + "tableId":1,
  237 + "tableName":"测试ABC",
  238 + "tableSqlName":"table_abc_test",
  239 + "fieldName":"业绩",
  240 + "fieldSqlName":"ye_ji_1",
  241 + "fieldSqlType":"Float"
  242 + }
  243 + },
  244 + {
  245 + "exprType":"ValueExprAST",
  246 + "val":"",
  247 + "str":"业绩2"
  248 + }
  249 + ]
  250 + }
  251 + }
  252 + ]
  253 +}
  254 +```
  255 +
  256 +## 讨论事项
  257 +
  258 +- [ ] 校验动作,参数模型讨论
  259 +- [ ] 校验日志错误(标红)
  260 +- [ ] 校验完毕应答实体,类型修改即使错误,也要返回修改完毕的表
  261 +
  262 +## 参数说明
  263 +
  264 +### 通用格式
  265 +
  266 +```json
  267 +{
  268 + "objectId": 1,
  269 + "processFields": [],
  270 + "action": "xx",
  271 + "params": {}
  272 +}
  273 +```
  274 +
  275 +processFields:操作字段
  276 +
  277 +### 常规
  278 +
  279 +1. 删除列
  280 +
  281 +```json
  282 +{
  283 + "action": "remove-column",
  284 + "params": {}
  285 +}
  286 +```
  287 +
  288 +2. 复制列
  289 +
  290 +```json
  291 +{
  292 + "action": "copy-column",
  293 + "params": {}
  294 +}
  295 +```
  296 +
  297 +3. 重命名
  298 +
  299 +```json
  300 +{
  301 + "action": "rename-column",
  302 + "params": {
  303 + "newColumnName": "新的列名称"
  304 + }
  305 +}
  306 +```
  307 +
  308 +4. 替换值
  309 +
  310 +```json
  311 +{
  312 + "action": "replace-column",
  313 + "params": {
  314 + "replaceMethod": "replace",
  315 + "searchValue": "搜索值",
  316 + "replaceValue": "替换值"
  317 + }
  318 +}
  319 +```
  320 +
  321 +参数说明
  322 +
  323 +```
  324 +replaceMethod: 替换方法(1.replace:替换值 2.add-prefix:添加前缀 3.add-postfix:添加后缀 4.remove-prefix:去除前缀 5.remove-postfix:去除后缀 6.remove-chars:去除固定字符 7.clean:清除)
  325 +searchValue: 搜索值-replace,remove-prefix,remove-postfix,remove-chars参数
  326 +replaceValue: 替换值-replace,add-prefix,add-postfix参数
  327 +```
  328 +
  329 +### 格式 formatMethod
  330 +
  331 +1. 大写
  332 +
  333 +```json
  334 +{
  335 + "action": "format-column",
  336 + "params": {
  337 + "formatMethod": "upper"
  338 + }
  339 +}
  340 +```
  341 +
  342 +参数说明
  343 +
  344 +```
  345 +formatMethod: 格式化方法(1.upper:大写2.lower:小写3.capitalize:首字母大写4.strip:修整)
  346 +```
  347 +
  348 +2. 小写
  349 +
  350 +```json
  351 +{
  352 + "action": "format-column",
  353 + "params": {
  354 + "formatMethod": "lower"
  355 + }
  356 +}
  357 +```
  358 +
  359 +3. 首字母大写
  360 +
  361 +```json
  362 +{
  363 + "action": "format-column",
  364 + "params": {
  365 + "formatMethod": "capitalize"
  366 + }
  367 +}
  368 +```
  369 +
  370 +4. 清除
  371 +
  372 +```json
  373 +{
  374 + "action": "replace-column",
  375 + "params": {
  376 + "replaceMethod": "clean"
  377 + }
  378 +}
  379 +```
  380 +
  381 +5. 修整
  382 +
  383 +```json
  384 +{
  385 + "action": "format-column",
  386 + "params": {
  387 + "formatMethod": "strip"
  388 + }
  389 +}
  390 +```
  391 +
  392 +6. 添加前缀
  393 +
  394 +```json
  395 +{
  396 + "action": "replace-column",
  397 + "params": {
  398 + "replaceMethod": "add-prefix",
  399 + "replaceValue": "前缀值"
  400 + }
  401 +}
  402 +```
  403 +
  404 +7. 添加后缀
  405 +
  406 +```json
  407 +{
  408 + "action": "replace-column",
  409 + "params": {
  410 + "replaceMethod": "add-postfix",
  411 + "replaceValue": "后缀值"
  412 + }
  413 +}
  414 +```
  415 +
  416 +8. 去除前缀
  417 +
  418 +```json
  419 +{
  420 + "action": "replace-column",
  421 + "params": {
  422 + "replaceMethod": "remove-prefix",
  423 + "searchValue": "前缀值"
  424 + }
  425 +}
  426 +```
  427 +
  428 +9. 去除后最
  429 +
  430 +```json
  431 +{
  432 + "action": "replace-column",
  433 + "params": {
  434 + "replaceMethod": "remove-postfix",
  435 + "searchValue": "后缀值"
  436 + }
  437 +}
  438 +```
  439 +
  440 +10. 去除固定字符
  441 +
  442 +```json
  443 +{
  444 + "action": "replace-column",
  445 + "params": {
  446 + "replaceMethod": "remove-chars",
  447 + "searchValue": "字符"
  448 + }
  449 +}
  450 +```
  451 +
  452 +### 拆分 split-column
  453 +
  454 +1. 按分隔符
  455 +
  456 +```json
  457 +{
  458 + "action": "split-column",
  459 + "params": {
  460 + "splitMethod": "separator",
  461 + "separator": "|",
  462 + "splitDirection": "left",
  463 + "splitCount": "1"
  464 + }
  465 +}
  466 +```
  467 +
  468 +参数说明
  469 +
  470 +```
  471 +separator: 分割符号 ‘|’
  472 +splitDirection: 拆分方向(1.left:从左边 2.right:从右边)
  473 +splitCount: 拆分次数
  474 +```
  475 +
  476 +2. 按字符数
  477 +
  478 +```json
  479 +{
  480 + "action": "split-column",
  481 + "params": {
  482 + "splitMethod": "char-length",
  483 + "splitDirection": "left",
  484 + "charLength": "10",
  485 + "splitCount": "1"
  486 + }
  487 +}
  488 +```
  489 +
  490 +参数说明
  491 +
  492 +```
  493 +charLength: 字符长度-char-length专属参数
  494 +splitDirection: 拆分方向(1.left:从左边 2.right:从右边)
  495 +splitCount: 拆分次数 (拆分策略是重复时:值0或者非1整数)
  496 +```
  497 +
  498 +### 提取 extract-column
  499 +
  500 +1. 按日期
  501 +
  502 +```json
  503 +{
  504 + "action": "extract-column",
  505 + "params": {
  506 + "extractMethod": "by-date"
  507 + }
  508 +}
  509 +```
  510 +
  511 +参数说明
  512 +
  513 +```
  514 +extractMethod: 提取方法(1.by-date:按日期 2.by-number:按数值)
  515 +```
  516 +
  517 +2. 按数值 action
  518 +
  519 +```json
  520 +{
  521 + "action": "extract-column",
  522 + "params": {
  523 + "extractMethod": "by-number"
  524 + }
  525 +}
  526 +```
  527 +
  528 +### 修改字段类型
  529 +
  530 +```json
  531 +{
  532 + "action": "convert-column-type",
  533 + "params": {
  534 + "convertType": "STRING"
  535 + }
  536 +}
  537 +```
  538 +
  539 +参数说明
  540 +
  541 +```
  542 +convertType:转换类型 STRING 数值: INT 小数: FLOAT 日期: DATE 时间: DATETIME
  543 +```
  544 +
  545 +## 优化点
  546 +- [] 0.测试服务、数据库的上限(QPS,TPS)查询瓶颈的接口
  547 +
  548 +- [] 1.模型详情缓存(tables、query_set)
  549 +
  550 +- [] 2.列表搜索缓存 (tables、query_set),减轻数据库压力
  551 +
  552 +```
  553 +更新、删除、重命名
  554 +get list:queryset:cxxx:*
  555 +删除所有匹配的缓存
  556 +
  557 +消息队列更新事件、确保缓存一定移除成功、缓存时间控制
  558 +```
1 -POSTGRESQL_DB_NAME = allied_creation_dev 1 +POSTGRESQL_DB_NAME = allied_creation_test
2 POSTGRESQL_HOST = 114.55.200.59 2 POSTGRESQL_HOST = 114.55.200.59
3 POSTGRESQL_PORT = 31543 3 POSTGRESQL_PORT = 31543
4 POSTGRESQL_USER = postgres 4 POSTGRESQL_USER = postgres
@@ -9,3 +9,19 @@ HTTP_PORT = 8081 @@ -9,3 +9,19 @@ HTTP_PORT = 8081
9 ENABLE_KAFKA_LOG11 = true 9 ENABLE_KAFKA_LOG11 = true
10 HTTPS_PORT = 8143 10 HTTPS_PORT = 8143
11 ALLIED_CREATION_USER_HOST = http://allied-creation-user-dev.fjmaimaimai.com 11 ALLIED_CREATION_USER_HOST = http://allied-creation-user-dev.fjmaimaimai.com
  12 +# AUTH_SERVER_HOST = http://127.0.0.1:8081
  13 +BYTE_CORE_HOST = http://47.97.5.102:8303
  14 +METADATA_BASTION_HOST = http://106.75.231.90:9999
  15 +
  16 +KAFKA_HOST =47.97.5.102:9092
  17 +#192.168.100.35:9092
  18 +
  19 +STARROCKS_DB_NAME = character_library
  20 +STARROCKS_USER = root
  21 +STARROCKS_PASSWORD = eagle1010
  22 +STARROCKS_HOST = 220.250.41.79
  23 +STARROCKS_PORT = 9030
  24 +
  25 +BLACK_LIST_USER = 0
  26 +BLACK_LIST_COMPANY = 1612991734952759296
  27 +WHITE_LIST_USERS = 22,23
  1 +/*
  2 + 1. 查询依赖的查询集
  3 +*/
  4 +select * from metadata.query_sets where query_set_info->>'BindTableId' in (
  5 + select distinct table_id::text from ( /*element_id,table_info,table_type*/
  6 + select json_array_elements(to_json(table_info->'dependencyTables'))::text::int element_id,table_info,table_id,table_type
  7 + from metadata.tables where table_info->'dependencyTables'::text <>'null' and table_type in ('SubProcess','CalculateTable')
  8 + ) a where a.element_id in (select table_id from metadata.tables where table_type in ('MainTable','SubTable','SideTable'))
  9 + order by table_id asc
  10 +) and context->>'operatorId' = '22'
@@ -18,4 +18,7 @@ CREATE INDEX IF NOT EXISTS idx_logs_company_id_operator_name ON metadata.logs US @@ -18,4 +18,7 @@ CREATE INDEX IF NOT EXISTS idx_logs_company_id_operator_name ON metadata.logs US
18 CREATE INDEX IF NOT EXISTS idx_logs_company_id_created_at ON metadata.logs USING btree((context->>'companyId'),created_at); 18 CREATE INDEX IF NOT EXISTS idx_logs_company_id_created_at ON metadata.logs USING btree((context->>'companyId'),created_at);
19 19
20 /*mapping_rules*/ 20 /*mapping_rules*/
21 -CREATE INDEX IF NOT EXISTS idx_mapping_rules_company_id_table_id_file_id ON metadata.mapping_rules USING btree((context->>'companyId'),table_id,file_id);  
  21 +CREATE INDEX IF NOT EXISTS idx_mapping_rules_company_id_table_id_file_id ON metadata.mapping_rules USING btree((context->>'companyId'),table_id,file_id);
  22 +
  23 +/*query_sets*/
  24 +CREATE INDEX IF NOT EXISTS idx_query_sets_company_id_type_deleted_at ON metadata.query_sets USING btree((context->>'companyId'),type,deleted_at);
  1 +ALTER TABLE files ADD file_from TEXT;
  2 +ALTER TABLE files ADD app_key TEXT;
  3 +Update files set file_from = 'ByteBankWebClient';
  4 +
  5 +CREATE INDEX IF NOT EXISTS idx_files_app_key ON metadata.files USING btree(app_key);
  6 +
  7 +
  8 +alter table metadata.tables add column apply_at timestamptz;
  9 +update metadata.tables set apply_at = null where table_type in ('MainTable','SubTable','SideTable') and apply_at is null;
@@ -102,9 +102,9 @@ spec: @@ -102,9 +102,9 @@ spec:
102 - name: METADATA_BASTION_HOST 102 - name: METADATA_BASTION_HOST
103 value: "http://character-library-metadata-bastion-dev.fjmaimaimai.com" 103 value: "http://character-library-metadata-bastion-dev.fjmaimaimai.com"
104 - name: BYTE_CORE_HOST 104 - name: BYTE_CORE_HOST
105 - value: "http://192.168.100.34:8303" 105 + value: "http://47.97.5.102:8303"
106 - name: STARROCKS_HOST 106 - name: STARROCKS_HOST
107 - value: "118.178.239.45" 107 + value: "220.250.41.79"
108 - name: STARROCKS_PORT 108 - name: STARROCKS_PORT
109 value: "9030" 109 value: "9030"
110 - name: STARROCKS_DB_NAME 110 - name: STARROCKS_DB_NAME
  1 +apiVersion: v1
  2 +kind: Service
  3 +metadata:
  4 + name: character-library-metadata-bastion
  5 + namespace: mmm-suplus-test
  6 + labels:
  7 + k8s-app: character-library-metadata-bastion
  8 +spec:
  9 + ports:
  10 + - name: "http"
  11 + port: 80
  12 + targetPort: 8082
  13 + selector:
  14 + k8s-app: character-library-metadata-bastion
  15 +---
  16 +apiVersion: extensions/v1beta1
  17 +kind: Deployment
  18 +metadata:
  19 + name: character-library-metadata-bastion
  20 + namespace: mmm-suplus-test
  21 + labels:
  22 + k8s-app: character-library-metadata-bastion
  23 +spec:
  24 + replicas: 1
  25 + template:
  26 + metadata:
  27 + labels:
  28 + k8s-app: character-library-metadata-bastion
  29 + spec:
  30 + affinity:
  31 + nodeAffinity:
  32 + preferredDuringSchedulingIgnoredDuringExecution:
  33 + - preference: {}
  34 + weight: 100
  35 + requiredDuringSchedulingIgnoredDuringExecution:
  36 + nodeSelectorTerms:
  37 + - matchExpressions:
  38 + - key: kubernetes.io/hostname
  39 + operator: In
  40 + values:
  41 + - cn-hangzhou.i-bp1djh1xn7taumbue1ze
  42 +
  43 + containers:
  44 + - name: character-library-metadata-bastion
  45 + image: 192.168.0.243:5000/mmm/character-library-metadata-bastion:dev
  46 + imagePullPolicy: Always
  47 + ports:
  48 + - containerPort: 8082
  49 + volumeMounts:
  50 + - mountPath: /opt/logs
  51 + name: accesslogs
  52 + env:
  53 + - name: POSTGRESQL_DB_NAME
  54 + valueFrom:
  55 + configMapKeyRef:
  56 + name: suplus-config
  57 + key: postgresqlalliedcreation.dbname
  58 + - name: POSTGRESQL_USER
  59 + valueFrom:
  60 + configMapKeyRef:
  61 + name: suplus-config
  62 + key: postgresql.user
  63 + - name: POSTGRESQL_PASSWORD
  64 + valueFrom:
  65 + configMapKeyRef:
  66 + name: suplus-config
  67 + key: postgresql.password
  68 + - name: POSTGRESQL_HOST
  69 + valueFrom:
  70 + configMapKeyRef:
  71 + name: suplus-config
  72 + key: postgresql.host
  73 + - name: POSTGRESQL_PORT
  74 + valueFrom:
  75 + configMapKeyRef:
  76 + name: suplus-config
  77 + key: postgresql.port
  78 + - name: REDIS_HOST
  79 + valueFrom:
  80 + configMapKeyRef:
  81 + name: suplus-config
  82 + key: redis.ip
  83 + - name: REDIS_PORT
  84 + valueFrom:
  85 + configMapKeyRef:
  86 + name: suplus-config
  87 + key: redis.port
  88 + - name: REDIS_AUTH
  89 + value: ""
  90 + - name: LOG_LEVEL
  91 + value: "debug"
  92 + - name: ERROR_BASE_CODE
  93 + value: "1"
  94 + - name: ERROR_BASE_CODE_MULTIPLE
  95 + value: "2000"
  96 + - name: KAFKA_HOST
  97 + value: "47.97.5.102:9092"
  98 + - name: HTTP_PORT
  99 + value: "8082"
  100 + - name: SERVICE_ENV
  101 + value: "test"
  102 + - name: METADATA_BASTION_HOST
  103 + value: "https://character-library-metadata-bastion-test.fjmaimaimai.com"
  104 + - name: BYTE_CORE_HOST
  105 + value: "http://47.97.5.102:8303"
  106 + - name: STARROCKS_HOST
  107 + value: "220.250.41.79"
  108 + - name: STARROCKS_PORT
  109 + value: "9030"
  110 + - name: STARROCKS_DB_NAME
  111 + value: "character_library"
  112 + - name: STARROCKS_USER
  113 + value: "root"
  114 + - name: STARROCKS_PASSWORD
  115 + value: "eagle1010"
  116 + - name: BLACK_LIST_USER
  117 + value: "1"
  118 + - name: BLACK_LIST_COMPANY
  119 + value: "1646025721363042304"
  120 + - name: WHITE_LIST_USERS
  121 + value: "0"
  122 + volumes:
  123 + - name: accesslogs
  124 + emptyDir: {}
  1 +#!/bin/bash
  2 +export PATH=/root/local/bin:$PATH
  3 +kubectl -n mmm-suplus-test get pods | grep -q character-library-metadata-bastion
  4 +if [ "$?" == "1" ];then
  5 + kubectl create -f /tmp/test/character-library-metadata-bastion/character-library-metadata-bastion.yaml --record
  6 + kubectl -n mmm-suplus-test get svc | grep -q character-library-metadata-bastion
  7 + if [ "$?" == "0" ];then
  8 + echo "character-library-metadata-bastion service install success!"
  9 + else
  10 + echo "character-library-metadata-bastion service install fail!"
  11 + fi
  12 + kubectl -n mmm-suplus-test get pods | grep -q character-library-metadata-bastion
  13 + if [ "$?" == "0" ];then
  14 + echo "character-library-metadata-bastion deployment install success!"
  15 + else
  16 + echo "character-library-metadata-bastion deployment install fail!"
  17 + fi
  18 +else
  19 + kubectl delete -f /tmp/test/character-library-metadata-bastion/character-library-metadata-bastion.yaml
  20 + kubectl -n mmm-suplus-test get svc | grep -q character-library-metadata-bastion
  21 + while [ "$?" == "0" ]
  22 + do
  23 + kubectl -n mmm-suplus-test get svc | grep -q character-library-metadata-bastion
  24 + done
  25 + kubectl -n mmm-suplus-test get pods | grep -q character-library-metadata-bastion
  26 + while [ "$?" == "0" ]
  27 + do
  28 + kubectl -n mmm-suplus-test get pods | grep -q character-library-metadata-bastion
  29 + done
  30 + kubectl create -f /tmp/test/character-library-metadata-bastion/character-library-metadata-bastion.yaml --record
  31 + kubectl -n mmm-suplus-test get svc | grep -q character-library-metadata-bastion
  32 + if [ "$?" == "0" ];then
  33 + echo "character-library-metadata-bastion service update success!"
  34 + else
  35 + echo "character-library-metadata-bastion service update fail!"
  36 + fi
  37 + kubectl -n mmm-suplus-test get pods | grep -q character-library-metadata-bastion
  38 + if [ "$?" == "0" ];then
  39 + echo "character-library-metadata-bastion deployment update success!"
  40 + else
  41 + echo "character-library-metadata-bastion deployment update fail!"
  42 + fi
  43 +fi
  1 +version: v1
  2 +kind: HttpApi
  3 +metadata:
  4 + service: querySet
  5 + path: /query-sets
  6 + endpoints:
  7 + - method: createQuerySet
  8 + route:
  9 + post: /
  10 + - method: updateQuerySet
  11 + route:
  12 + put: /{Id}
  13 + - method: getQuerySet
  14 + route:
  15 + get: /{Id}
  16 + - method: removeQuerySet
  17 + route:
  18 + delete: /{Id}
  19 + - method: listQuerySet
  20 + route:
  21 + get: /
  22 + params:
  23 + - name: offset
  24 + - name: limit
  25 + - method: changeStatus
  26 + route:
  27 + post: /change-status
  28 + - method: copy
  29 + route:
  30 + post: /copy
  31 + - method: dependencyGraph
  32 + route:
  33 + post: /dependency-ggraph
  34 + - method: move
  35 + route:
  36 + post: /move
  37 + - method: rename
  38 + route:
  39 + post: /rename
  40 + - method: searchQuerySet
  41 + route:
  42 + post: /search
  1 +version: v1
  2 +kind: Attribute
  3 +metadata:
  4 + name: context
  5 + description: 扩展
  6 + type:
  7 + array: string
  1 +version: v1
  2 +kind: Attribute
  3 +metadata:
  4 + name: flag
  5 + description: 标识 1.group 2.query-set
  6 + type:
  7 + primitive: string
  1 +version: v1
  2 +kind: Attribute
  3 +metadata:
  4 + name: name
  5 + description: 名称
  6 + type:
  7 + primitive: string
  1 +version: v1
  2 +kind: Attribute
  3 +metadata:
  4 + name: pinName
  5 + description: 拼音(排序使用)
  6 + type:
  7 + primitive: string
  1 +version: v1
  2 +kind: Attribute
  3 +metadata:
  4 + name: queryComponents
  5 + description: 查询组件
  6 + type:
  7 + array: string
  1 +version: v1
  2 +kind: Attribute
  3 +metadata:
  4 + name: querySetId
  5 + description: 查询集合ID
  6 + type:
  7 + primitive: int
  1 +version: v1
  2 +kind: Attribute
  3 +metadata:
  4 + name: querySetInfo
  5 + description: 查询集合信息
  6 + type:
  7 + primitive: string
  1 +version: v1
  2 +kind: Attribute
  3 +metadata:
  4 + name: status
  5 + description: 状态 1:启用 2:关闭 (子过程默认启用)
  6 + type:
  7 + primitive: int
  1 +version: v1
  2 +kind: Attribute
  3 +metadata:
  4 + name: type
  5 + description: schema:方案 sub-process:子过程
  6 + type:
  7 + primitive: string
  1 +version: v1
  2 +kind: Schema
  3 +metadata:
  4 + name: querySet
  5 + description: 查询集合
  6 + attributes:
  7 + - ref: querySetId
  8 + required: true
  9 + - ref: type
  10 + required: true
  11 + - ref: flag
  12 + required: true
  13 + - ref: name
  14 + required: true
  15 + - ref: pinName
  16 + required: true
  17 + - ref: parentId
  18 + required: true
  19 + - ref: status
  20 + required: true
  21 + - ref: querySetInfo
  22 + required: true
  23 + - ref: queryComponents
  24 + required: true
  25 + - ref: sort
  26 + required: true
  27 + - ref: createdAt
  28 + required: true
  29 + - ref: updatedAt
  30 + required: true
  31 + - ref: deletedAt
  32 + required: true
  33 + - ref: context
  34 + required: true
  1 +version: v1
  2 +kind: Method
  3 +metadata:
  4 + name: changeStatus
  5 + type: command
  6 + description: 修改状态
  7 + payload:
  8 + - ref: querySetId
  9 + required: true
  10 + - ref: status
  11 + required: true
  12 + result:
  13 + - name: querySet
  14 + type:
  15 + schema: querySet
  16 + required: true
  1 +version: v1
  2 +kind: Method
  3 +metadata:
  4 + name: copy
  5 + type: command
  6 + description: 移动
  7 + payload:
  8 + - ref: flag
  9 + required: true
  10 + - ref: parentId
  11 + required: true
  12 + - ref: name
  13 + required: true
  14 + - ref: querySetId
  15 + required: true
  16 + result:
  17 + - name: querySet
  18 + type:
  19 + schema: querySet
  20 + required: true
  1 +version: v1
  2 +kind: Method
  3 +metadata:
  4 + name: createQuerySet
  5 + type: command
  6 + description: 创建查询集合服务
  7 + payload:
  8 + - ref: type
  9 + required: true
  10 + - ref: flag
  11 + required: true
  12 + - ref: name
  13 + required: true
  14 + - ref: parentId
  15 + required: false
  16 + result:
  17 + - name: querySet
  18 + type:
  19 + schema: querySet
  20 + required: true
  1 +version: v1
  2 +kind: Method
  3 +metadata:
  4 + name: dependencyGraph
  5 + type: query
  6 + description: 依赖关系图
  7 + payload:
  8 + - ref: querySetId
  9 + required: true
  10 + result:
  11 + - name: querySet
  12 + type:
  13 + schema: querySet
  14 + required: true
  1 +version: v1
  2 +kind: Method
  3 +metadata:
  4 + name: getQuerySet
  5 + type: query
  6 + description: 返回查询集合服务
  7 + payload:
  8 + - ref: querySetId
  9 + required: true
  10 + result:
  11 + - name: querySet
  12 + type:
  13 + schema: querySet
  14 + required: true
  1 +version: v1
  2 +kind: Method
  3 +metadata:
  4 + name: listQuerySet
  5 + type: query
  6 + description: 返回查询集合服务列表
  7 + payload:
  8 + - ref: offset
  9 + required: true
  10 + - ref: limit
  11 + required: true
  12 + result:
  13 + - ref: count
  14 + required: true
  15 + - name: querySets
  16 + type:
  17 + array: querySet
  18 + required: true
  1 +version: v1
  2 +kind: Method
  3 +metadata:
  4 + name: move
  5 + type: command
  6 + description: 移动
  7 + payload:
  8 + - ref: querySetId
  9 + required: true
  10 + - ref: parentId
  11 + required: true
  12 + result:
  13 + - name: querySet
  14 + type:
  15 + schema: querySet
  16 + required: true
  1 +version: v1
  2 +kind: Method
  3 +metadata:
  4 + name: removeQuerySet
  5 + type: command
  6 + description: 移除查询集合服务
  7 + payload:
  8 + - ref: querySetId
  9 + required: true
  10 + result:
  11 + - name: querySet
  12 + type:
  13 + schema: querySet
  14 + required: true
  1 +version: v1
  2 +kind: Method
  3 +metadata:
  4 + name: rename
  5 + type: command
  6 + description: 重命名
  7 + payload:
  8 + - ref: querySetId
  9 + required: true
  10 + - ref: name
  11 + required: true
  12 + result:
  13 + - name: querySet
  14 + type:
  15 + schema: querySet
  16 + required: true
  1 +version: v1
  2 +kind: Method
  3 +metadata:
  4 + name: searchQuerySet
  5 + type: query
  6 + description: 返回查询集合服务列表
  7 + payload:
  8 + - ref: offset
  9 + required: true
  10 + - ref: limit
  11 + required: true
  12 + result:
  13 + - ref: count
  14 + required: true
  15 + - name: querySets
  16 + type:
  17 + array: querySet
  18 + required: true
  1 +version: v1
  2 +kind: Method
  3 +metadata:
  4 + name: updateQuerySet
  5 + type: command
  6 + description: 更新查询集合服务
  7 + payload:
  8 + - ref: querySetId
  9 + required: true
  10 + result:
  11 + - name: querySet
  12 + type:
  13 + schema: querySet
  14 + required: true
  1 +version: v1
  2 +kind: Service
  3 +metadata:
  4 + name: querySet
  5 + description: 查询集合服务
@@ -3,51 +3,57 @@ module gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion @@ -3,51 +3,57 @@ module gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion
3 go 1.16 3 go 1.16
4 4
5 require ( 5 require (
6 - github.com/Shopify/sarama v1.30.0 // indirect  
7 - github.com/ajg/form v1.5.1 // indirect 6 + github.com/aliyun/aliyun-oss-go-sdk v2.2.7+incompatible
8 github.com/beego/beego/v2 v2.0.1 7 github.com/beego/beego/v2 v2.0.1
9 github.com/bwmarrin/snowflake v0.3.0 8 github.com/bwmarrin/snowflake v0.3.0
  9 + github.com/dgrijalva/jwt-go v3.2.0+incompatible
10 github.com/extrame/xls v0.0.1 10 github.com/extrame/xls v0.0.1
11 - github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072 // indirect  
12 - github.com/fatih/structs v1.1.0 // indirect  
13 github.com/gavv/httpexpect v2.0.0+incompatible 11 github.com/gavv/httpexpect v2.0.0+incompatible
  12 + github.com/go-gota/gota v0.12.0
14 github.com/go-pg/pg/v10 v10.10.6 13 github.com/go-pg/pg/v10 v10.10.6
15 github.com/go-redis/redis v6.15.9+incompatible 14 github.com/go-redis/redis v6.15.9+incompatible
16 - github.com/google/go-cmp v0.5.7 // indirect  
17 - github.com/google/go-querystring v1.1.0 // indirect 15 + github.com/google/gofuzz v1.2.0
18 github.com/google/uuid v1.3.0 16 github.com/google/uuid v1.3.0
19 - github.com/imkira/go-interpol v1.1.0 // indirect 17 + github.com/gookit/event v1.0.6
20 github.com/linmadan/egglib-go v0.0.0-20210313060205-8b5e456b11f7 18 github.com/linmadan/egglib-go v0.0.0-20210313060205-8b5e456b11f7
21 - github.com/mattn/go-colorable v0.1.9 // indirect  
22 - github.com/mattn/go-isatty v0.0.14 // indirect  
23 - github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect  
24 - github.com/moul/http2curl v1.0.0 // indirect  
25 github.com/onsi/ginkgo v1.16.5 19 github.com/onsi/ginkgo v1.16.5
26 github.com/onsi/gomega v1.18.1 20 github.com/onsi/gomega v1.18.1
27 - github.com/prometheus/client_golang v1.12.2 // indirect  
28 - github.com/sergi/go-diff v1.2.0 // indirect 21 + github.com/patrickmn/go-cache v2.1.0+incompatible
29 github.com/shopspring/decimal v1.3.1 22 github.com/shopspring/decimal v1.3.1
30 - github.com/smartystreets/goconvey v1.7.2 // indirect  
31 github.com/stretchr/testify v1.7.1 23 github.com/stretchr/testify v1.7.1
  24 + github.com/xuri/excelize/v2 v2.6.0
  25 + github.com/zeromicro/go-zero v1.3.4
  26 + golang.org/x/text v0.3.7
  27 + gorm.io/driver/mysql v1.3.6
  28 + gorm.io/driver/postgres v1.3.9
  29 + gorm.io/gorm v1.23.8
  30 +)
  31 +
  32 +require (
  33 + github.com/ajg/form v1.5.1 // indirect
  34 + github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072 // indirect
  35 + github.com/fatih/structs v1.1.0 // indirect
  36 + github.com/go-sql-driver/mysql v1.7.0 // indirect
  37 + github.com/google/go-querystring v1.1.0 // indirect
  38 + github.com/imkira/go-interpol v1.1.0 // indirect
  39 + github.com/moul/http2curl v1.0.0 // indirect
  40 + github.com/sergi/go-diff v1.2.0 // indirect
  41 + github.com/sirupsen/logrus v1.9.0 // indirect
  42 + github.com/smartystreets/goconvey v1.7.2 // indirect
32 github.com/valyala/fasthttp v1.38.0 // indirect 43 github.com/valyala/fasthttp v1.38.0 // indirect
33 github.com/xeipuuv/gojsonschema v1.2.0 // indirect 44 github.com/xeipuuv/gojsonschema v1.2.0 // indirect
34 - github.com/xuri/excelize/v2 v2.6.0 45 + github.com/xuri/efp v0.0.0-20220603152613-6918739fd470 // indirect
35 github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 // indirect 46 github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 // indirect
36 github.com/yudai/gojsondiff v1.0.0 // indirect 47 github.com/yudai/gojsondiff v1.0.0 // indirect
37 github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect 48 github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect
38 github.com/yudai/pp v2.0.1+incompatible // indirect 49 github.com/yudai/pp v2.0.1+incompatible // indirect
39 - go.uber.org/automaxprocs v1.5.1 // indirect  
40 - golang.org/x/net v0.0.0-20220421235706-1d1ef9303861 // indirect  
41 - golang.org/x/sys v0.0.0-20220429233432-b5fbb4746d32 // indirect  
42 - golang.org/x/text v0.3.7  
43 - golang.org/x/tools v0.1.5 // indirect  
44 - google.golang.org/protobuf v1.28.0 // indirect  
45 - gorm.io/driver/mysql v1.3.6  
46 - gorm.io/driver/postgres v1.3.9  
47 - gorm.io/gorm v1.23.8 50 + github.com/zeromicro/go-queue v1.1.6
  51 + golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d // indirect
48 ) 52 )
49 53
50 replace ( 54 replace (
51 github.com/extrame/xls v0.0.1 => github.com/tiptok/xls v1.0.1 55 github.com/extrame/xls v0.0.1 => github.com/tiptok/xls v1.0.1
52 - github.com/linmadan/egglib-go v0.0.0-20210313060205-8b5e456b11f7 => github.com/tiptok/egglib-go v0.0.0-20220421085958-9682d0ac42c1 56 + github.com/go-sql-driver/mysql v1.7.0 => github.com/StarRocks/go-mysql-driver v1.7.0
  57 + //github.com/linmadan/egglib-go v0.0.0-20210313060205-8b5e456b11f7 => github.com/tiptok/egglib-go v0.0.0-20220421085958-9682d0ac42c1
  58 + github.com/linmadan/egglib-go v0.0.0-20210313060205-8b5e456b11f7 => github.com/tiptok/egglib-go v1.0.2
53 ) 59 )
@@ -5,19 +5,18 @@ import ( @@ -5,19 +5,18 @@ import (
5 "github.com/beego/beego/v2/server/web" 5 "github.com/beego/beego/v2/server/web"
6 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/crontab" 6 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/crontab"
7 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/constant" 7 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/constant"
  8 + _ "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/constant"
8 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/pg" 9 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/pg"
9 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/redis" 10 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/redis"
  11 + _ "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/redis"
10 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/starrocks" 12 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/starrocks"
11 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/log" 13 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/log"
12 - "time"  
13 -  
14 - _ "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/constant"  
15 - _ "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/redis"  
16 _ "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/log" 14 _ "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/log"
17 _ "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/port/beego" 15 _ "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/port/beego"
  16 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/port/event"
18 ) 17 )
19 18
20 -const Version = "v1.0.1" 19 +const Version = "v1.4.0"
21 20
22 func main() { 21 func main() {
23 defer func() { 22 defer func() {
@@ -28,6 +27,7 @@ func main() { @@ -28,6 +27,7 @@ func main() {
28 27
29 log.InitLogHook(constant.ENABLE_KAFKA_LOG, true) 28 log.InitLogHook(constant.ENABLE_KAFKA_LOG, true)
30 redis.InitRedis() 29 redis.InitRedis()
  30 + redis.InitZeroCoreRedis()
31 pg.Init() 31 pg.Init()
32 if err := starrocks.Init(); err != nil { 32 if err := starrocks.Init(); err != nil {
33 log.Logger.Error(err.Error()) 33 log.Logger.Error(err.Error())
@@ -35,8 +35,7 @@ func main() { @@ -35,8 +35,7 @@ func main() {
35 cron := crontab.NewCrontabService(nil) 35 cron := crontab.NewCrontabService(nil)
36 cron.StartCrontabTask() 36 cron.StartCrontabTask()
37 defer cron.StopCrontabTask() 37 defer cron.StopCrontabTask()
38 -  
39 - time.Sleep(time.Second) 38 + event.Start()
40 log.Logger.Info("Service:" + constant.SERVICE_NAME) 39 log.Logger.Info("Service:" + constant.SERVICE_NAME)
41 log.Logger.Info("Version:" + Version) 40 log.Logger.Info("Version:" + Version)
42 log.Logger.Info("server start!") 41 log.Logger.Info("server start!")
@@ -4,9 +4,12 @@ import ( @@ -4,9 +4,12 @@ import (
4 "context" 4 "context"
5 "fmt" 5 "fmt"
6 "github.com/beego/beego/v2/task" 6 "github.com/beego/beego/v2/task"
  7 + pgTransaction "github.com/linmadan/egglib-go/transaction/pg"
7 "github.com/linmadan/egglib-go/utils/xtime" 8 "github.com/linmadan/egglib-go/utils/xtime"
8 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/factory" 9 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/factory"
9 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain" 10 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
  11 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/dao"
  12 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/starrocks"
10 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/log" 13 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/log"
11 "io/fs" 14 "io/fs"
12 "os" 15 "os"
@@ -28,6 +31,9 @@ func (crontabService *CrontabService) initTask() { @@ -28,6 +31,9 @@ func (crontabService *CrontabService) initTask() {
28 31
29 autoRemovePublicDownloadFile := task.NewTask("定时清理缓存文件", "0 20 */1 * * *", AutoRemovePublicDownloadFile) 32 autoRemovePublicDownloadFile := task.NewTask("定时清理缓存文件", "0 20 */1 * * *", AutoRemovePublicDownloadFile)
30 task.AddTask("autoRemovePublicDownloadFile", autoRemovePublicDownloadFile) 33 task.AddTask("autoRemovePublicDownloadFile", autoRemovePublicDownloadFile)
  34 +
  35 + autoRemoveTemporaryTable := task.NewTask("定时清理临时表", "0 57 */1 * * *", AutoRemoveTemporaryTable)
  36 + task.AddTask("autoRemoveTemporaryTable", autoRemoveTemporaryTable)
31 } 37 }
32 38
33 func (crontabService *CrontabService) StartCrontabTask() { 39 func (crontabService *CrontabService) StartCrontabTask() {
@@ -115,3 +121,49 @@ func AutoRemovePublicDownloadFile(ctx context.Context) error { @@ -115,3 +121,49 @@ func AutoRemovePublicDownloadFile(ctx context.Context) error {
115 } 121 }
116 return nil 122 return nil
117 } 123 }
  124 +
  125 +func AutoRemoveTemporaryTable(ctx context.Context) error {
  126 + defer func() {
  127 + if r := recover(); r != nil {
  128 + log.Logger.Error(fmt.Sprintf("%v", r), map[string]interface{}{"task": "定时清理过期临时文件记录"})
  129 + }
  130 + }()
  131 + transactionContext, err := factory.CreateTransactionContext(nil)
  132 + if err != nil {
  133 + return err
  134 + }
  135 + if err := transactionContext.StartTransaction(); err != nil {
  136 + return err
  137 + }
  138 + defer func() {
  139 + if err != nil {
  140 + log.Logger.Error("【定时清理临时表】 失败:" + err.Error())
  141 + }
  142 + transactionContext.RollbackTransaction()
  143 + }()
  144 +
  145 + log.Logger.Debug("【定时清理临时表】 启动")
  146 + end := xtime.New(time.Now()).BeginningOfDay().Add(-time.Hour * 12)
  147 + begin := end.AddDate(0, 0, -7)
  148 +
  149 + tableRepository, _, _ := factory.FastPgTable(transactionContext, 0)
  150 + _, tables, err := tableRepository.Find(map[string]interface{}{"beginTime": begin, "endTime": end, "tableTypes": []string{domain.TemporaryTable.ToString()}})
  151 + if err != nil {
  152 + return nil
  153 + }
  154 + for i, t := range tables {
  155 + if err = dao.TableDelete(transactionContext.(*pgTransaction.TransactionContext), t.TableId, domain.TemporaryTable); err != nil {
  156 + log.Logger.Error(err.Error())
  157 + return nil
  158 + }
  159 + log.Logger.Info(fmt.Sprintf("序号:%d 清理临时表 %v", i, t.SQLName))
  160 + if err = starrocks.DropView(starrocks.DB, t.SQLName); err != nil {
  161 + log.Logger.Error(err.Error())
  162 + return nil
  163 + }
  164 + }
  165 + if err = transactionContext.CommitTransaction(); err != nil {
  166 + return err
  167 + }
  168 + return nil
  169 +}
  1 +package command
  2 +
  3 +import "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
  4 +
  5 +type TableEventCommand struct {
  6 + EventTable *domain.EventTable
  7 +}
  1 +package service
  2 +
  3 +import (
  4 + "fmt"
  5 + "github.com/linmadan/egglib-go/core/application"
  6 + pgTransaction "github.com/linmadan/egglib-go/transaction/pg"
  7 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/event/command"
  8 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/factory"
  9 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/constant"
  10 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
  11 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/api/digitalLib"
  12 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/broker"
  13 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/domainService"
  14 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/log"
  15 + "math"
  16 + "time"
  17 +)
  18 +
  19 +func (tableEventService *TableEventService) DigitalPlatformEventSubscribe(ctx *domain.Context, cmd *command.TableEventCommand) (interface{}, error) {
  20 + transactionContext, err := factory.CreateTransactionContext(nil)
  21 + if err != nil {
  22 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  23 + }
  24 + if err := transactionContext.StartTransaction(); err != nil {
  25 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  26 + }
  27 + defer func() {
  28 + transactionContext.RollbackTransaction()
  29 + }()
  30 +
  31 + var (
  32 + dataChanged = true
  33 + structChanged = true
  34 + ok bool
  35 + tableId int
  36 + )
  37 + event := cmd.EventTable
  38 + if tableId = resolveTableId(event); tableId == 0 {
  39 + return nil, nil
  40 + }
  41 + if event.Type == domain.TableApplyOnEvent {
  42 + dataChanged = false
  43 + }
  44 + var notifyData = &NotifyData{
  45 + DataChanged: dataChanged,
  46 + StructChanged: structChanged,
  47 + TableId: tableId,
  48 + Event: event.Type.ToString(),
  49 + Metadata: event.Metadata,
  50 + }
  51 + // 表类型
  52 + tableRepository, table, _ := factory.FastPgTable(transactionContext, tableId)
  53 + if table == nil && event.Table != nil {
  54 + table = event.Table
  55 + notifyData.CompanyId = table.Context.CompanyId
  56 + }
  57 + notifyData.SetType(event, table)
  58 +
  59 + // 依赖的表 \ 依赖的查询集合
  60 + _, tables, err := tableRepository.Find(map[string]interface{}{"context": event.Context, "tableTypesNotIn": []string{domain.TemporaryTable.ToString(), domain.ExcelTable.ToString()}})
  61 + if err != nil {
  62 + return nil, err
  63 + }
  64 + tableDependencyService, _ := domainService.NewTableDependencyService(transactionContext.(*pgTransaction.TransactionContext))
  65 + tableDependTree := tableDependencyService.TableDependTree(tables, tableId)
  66 + tree := tableDependTree.Tree
  67 + querySetRepository, _, _ := factory.FastPgQuerySet(transactionContext, 0)
  68 + var mapTableQuerySet = make(map[int]*domain.QuerySet)
  69 + if len(tree) > 0 {
  70 + _, querySets, _ := querySetRepository.Find(map[string]interface{}{
  71 + "types": []string{domain.SchemaTable.ToString(), domain.CalculateItem.ToString(), domain.CalculateSet.ToString()},
  72 + "bindTableIds": tree,
  73 + "status": domain.StatusOn,
  74 + })
  75 + for _, q := range querySets {
  76 + mapTableQuerySet[q.QuerySetInfo.BindTableId] = q
  77 + }
  78 + }
  79 +
  80 + // 过滤出需要推送的表
  81 + for i := range tree {
  82 + table, ok = tableDependencyService.TableMap[tree[i]]
  83 + if !ok {
  84 + continue
  85 + }
  86 + if notifyData.CompanyId == 0 {
  87 + notifyData.CompanyId = table.Context.CompanyId
  88 + }
  89 + switch table.TableType {
  90 + case domain.MainTable.ToString(), domain.SubTable.ToString(), domain.SideTable.ToString():
  91 + if table.TableInfo != nil {
  92 + applyOn := domain.ModuleDigitalCenter | domain.ModuleChartTemplate
  93 + if table.TableInfo.ApplyOnModule&applyOn == 0 {
  94 + continue
  95 + }
  96 + }
  97 + break
  98 + case domain.SubProcessTable.ToString(), domain.CalculateTable.ToString():
  99 + continue
  100 + case domain.SchemaTable.ToString(), domain.CalculateSet.ToString(), domain.CalculateItem.ToString():
  101 + var querySet *domain.QuerySet
  102 + if querySet, ok = mapTableQuerySet[tree[i]]; !ok {
  103 + continue
  104 + }
  105 + // 不是当前的查询集。且状态为关闭的都补推送
  106 + if querySet.Status != domain.StatusOn && querySet.QuerySetInfo.BindTableId != 0 && querySet.QuerySetInfo.BindTableId != tableId {
  107 + continue
  108 + }
  109 + }
  110 + notifyData.TableAffectedList = append(notifyData.TableAffectedList, tree[i])
  111 + }
  112 + // 包含自己
  113 + if !exist(notifyData.TableAffectedList, tableId) {
  114 + notifyData.TableAffectedList = append(notifyData.TableAffectedList, tableId)
  115 + }
  116 + // 通过消息队列发送
  117 + if err = tableEventService.send(notifyData, tableEventService.sendBroker); err != nil {
  118 + return nil, err
  119 + }
  120 + if err = transactionContext.CommitTransaction(); err != nil {
  121 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  122 + }
  123 + return nil, nil
  124 +}
  125 +
  126 +func (tableEventService *TableEventService) send(notifyData *NotifyData, sendFunc func(*NotifyData) error) error {
  127 + var err error
  128 + if err = sendFunc(notifyData); err != nil {
  129 + log.Logger.Error(fmt.Sprintf("通知数控失败:%s", err.Error()))
  130 + if t, ok := notifyData.Retry(); ok {
  131 + tableEventService.TimingWheel.SetTimer(notifyData.Key(), &notifyData, t)
  132 + log.Logger.Debug(fmt.Sprintf("通知数控重试 key:%s wait:%vs", notifyData.Key(), t.Seconds()))
  133 + }
  134 + }
  135 + return err
  136 +}
  137 +
  138 +func (tableEventService *TableEventService) sendHttp(notifyData *NotifyData) error {
  139 + var err error
  140 + lib := digitalLib.NewDigitalLib(constant.DIGITAL_SERVER_HOST)
  141 + if _, err = lib.SyncNotice(digitalLib.RequestSyncNotice{Body: notifyData}); err != nil {
  142 + return err
  143 + }
  144 + return nil
  145 +}
  146 +
  147 +func (tableEventService *TableEventService) sendBroker(notifyData *NotifyData) error {
  148 + var err error
  149 + if err = broker.Push(constant.KAFKA_HOST, constant.TOPIC_TABLE_DATA_SYNC, notifyData); err != nil {
  150 + return err
  151 + }
  152 + return nil
  153 +}
  154 +
  155 +func resolveTableId(event *domain.EventTable) (tableId int) {
  156 + switch event.Type {
  157 + case domain.TableDataImportEvent, domain.TableDataEditEvent, domain.TableDeleteEvent, domain.TableStructEditEvent:
  158 + tableId = event.Table.TableId
  159 + case domain.QuerySetUpdateEvent, domain.QuerySetUpdateRenameEvent:
  160 + if event.QuerySet.Status != domain.StatusOn {
  161 + return
  162 + }
  163 + if !domain.AssertTableType(event.QuerySet.Type, domain.SchemaTable, domain.CalculateItem, domain.CalculateSet) {
  164 + return
  165 + }
  166 + tableId = event.QuerySet.QuerySetInfo.BindTableId
  167 + case domain.QuerySetUpdateStatusEvent:
  168 + if !domain.AssertTableType(event.QuerySet.Type, domain.SchemaTable, domain.CalculateItem, domain.CalculateSet) {
  169 + return
  170 + }
  171 + tableId = event.QuerySet.QuerySetInfo.BindTableId
  172 + case domain.TableApplyOnEvent:
  173 + tableId = event.Table.TableId
  174 + case domain.QuerySetDeleteEvent:
  175 + tableId = event.Table.TableId
  176 + }
  177 + return tableId
  178 +}
  179 +
  180 +func exist(idList []int, target int) bool {
  181 + found := false
  182 + for _, id := range idList {
  183 + if id == target {
  184 + found = true
  185 + }
  186 + }
  187 + return found
  188 +}
  189 +
  190 +type NotifyData struct {
  191 + DataChanged bool `json:"dataChanged"` // 数据有变化
  192 + StructChanged bool `json:"structChanged"` // 结构有变化
  193 + TableId int `json:"tableId"` // 表ID
  194 + TableType string `json:"tableType"` // 表类型:导入模块(主表,副表,分表) 拆解模块(方案、子过程、计算表) 计算模块(计算项,计算集)
  195 + ObjectType string `json:"objectType"` // 导入模块、拆解模块、计算模块
  196 + CompanyId int `json:"companyId"` // 公司
  197 + Event string `json:"event"` // 事件名称
  198 + TableAffectedList []int `json:"tableAffectedList"` // 级联影响到的表
  199 + Metadata map[string]interface{} `json:"metadata"` // 元数据
  200 + sendRetry int
  201 +}
  202 +
  203 +func (n *NotifyData) SetType(event *domain.EventTable, table *domain.Table) {
  204 + var tableType string
  205 + // 表类型
  206 + if tableType == "" && table != nil {
  207 + tableType = table.TableType
  208 + }
  209 + if tableType == "" && event.QuerySet != nil {
  210 + tableType = event.QuerySet.Type
  211 + }
  212 + n.TableType = domain.EnumsDescription(domain.ObjectTypeMap, tableType)
  213 + if table != nil {
  214 + switch domain.TableType(tableType) {
  215 + case domain.MainTable, domain.SubTable, domain.SideTable:
  216 + n.ObjectType = "导入模块"
  217 + case domain.SchemaTable, domain.SubProcessTable, domain.CalculateTable:
  218 + n.ObjectType = "拆解模块"
  219 + case domain.CalculateItem, domain.CalculateSet:
  220 + n.ObjectType = "计算模块"
  221 + }
  222 + }
  223 +}
  224 +
  225 +func (n *NotifyData) Key() string {
  226 + return fmt.Sprintf("delay:notify:table:%d", n.TableId)
  227 +}
  228 +
  229 +func (n *NotifyData) Retry() (time.Duration, bool) {
  230 + n.sendRetry++
  231 + if n.sendRetry > 3 {
  232 + return n.Delay(), false
  233 + }
  234 + if n.sendRetry == 1 {
  235 + return n.Delay(), true
  236 + }
  237 + return n.Delay() * time.Duration(int(math.Pow(float64(2), float64(n.sendRetry)))), true
  238 +}
  239 +
  240 +func (n *NotifyData) Delay() time.Duration {
  241 + return time.Second * 10
  242 +}
  243 +
  244 +func (n *NotifyData) RetryTime() int {
  245 + return n.sendRetry
  246 +}
  1 +package service
  2 +
  3 +import (
  4 + "fmt"
  5 + "github.com/linmadan/egglib-go/core/application"
  6 + pgTransaction "github.com/linmadan/egglib-go/transaction/pg"
  7 + "github.com/zeromicro/go-zero/core/collection"
  8 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/event/command"
  9 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/factory"
  10 + tablecommand "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/table/command"
  11 + tableservice "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/table/service"
  12 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
  13 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/api/digitalLib"
  14 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/cache"
  15 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/domainService"
  16 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/log"
  17 + "time"
  18 +)
  19 +
  20 +type TableEventService struct {
  21 + TimingWheel *collection.TimingWheel
  22 +}
  23 +
  24 +func (tableEventService *TableEventService) Handler(ctx *domain.Context, cmd *command.TableEventCommand) (interface{}, error) {
  25 + transactionContext, err := factory.CreateTransactionContext(nil)
  26 + if err != nil {
  27 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  28 + }
  29 + if err := transactionContext.StartTransaction(); err != nil {
  30 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  31 + }
  32 + defer func() {
  33 + transactionContext.RollbackTransaction()
  34 + }()
  35 +
  36 + data := cmd.EventTable
  37 + tableId := 0
  38 + switch data.Type {
  39 + case domain.TableDataImportEvent, domain.TableDataEditEvent, domain.TableDeleteEvent, domain.TableStructEditEvent:
  40 + tableId = data.Table.TableId
  41 + case domain.QuerySetUpdateEvent:
  42 + tableId = data.QuerySet.QuerySetInfo.BindTableId
  43 + default:
  44 + return nil, err
  45 + }
  46 + if tableId == 0 {
  47 + return nil, nil
  48 + }
  49 + // tableId 相关联的
  50 + tableRepository, _, _ := factory.FastPgTable(transactionContext, 0)
  51 + _, tables, err := tableRepository.Find(map[string]interface{}{"context": data.Context, "tableTypesNotIn": []string{domain.TemporaryTable.ToString(), domain.ExcelTable.ToString()}})
  52 + if err != nil {
  53 + return nil, err
  54 + }
  55 +
  56 + tableDependencyService, _ := domainService.NewTableDependencyService(transactionContext.(*pgTransaction.TransactionContext))
  57 + tableDependTree := tableDependencyService.TableDependTree(tables, tableId)
  58 + tree := tableDependTree.Tree
  59 +
  60 + tableService := tableservice.NewTableService(nil)
  61 + for i := range tree {
  62 + cache.DefaultDataTableCacheService.DeleteDataTable(tree[i])
  63 + // fresh cache
  64 + tableService.TablePreview(data.Context, &tablecommand.TablePreviewCommand{
  65 + TableId: tree[i],
  66 + ObjectType: domain.ObjectMetaTable,
  67 + PageSize: 10000,
  68 + PageNumber: 0,
  69 + UseCache: true,
  70 + })
  71 + }
  72 +
  73 + if err := transactionContext.CommitTransaction(); err != nil {
  74 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  75 + }
  76 + return nil, nil
  77 +}
  78 +
  79 +func NewTableEventService(options map[string]interface{}) *TableEventService {
  80 + svr := &TableEventService{}
  81 + delayNotifyTimingWheel, _ := collection.NewTimingWheel(time.Second, 10, svr.TimingWheelFunc)
  82 + svr.TimingWheel = delayNotifyTimingWheel
  83 + return svr
  84 +}
  85 +
  86 +func (tableEventService *TableEventService) TimingWheelFunc(key, value interface{}) {
  87 + v, ok := value.(*NotifyData)
  88 + if !ok {
  89 + return
  90 + }
  91 + lib := digitalLib.NewDigitalLib("")
  92 + if _, err := lib.SyncNotice(digitalLib.RequestSyncNotice{Body: v}); err != nil {
  93 + log.Logger.Error(fmt.Sprintf("通知数控失败:%s", err.Error()))
  94 + if t, ok := v.Retry(); ok {
  95 + if err = tableEventService.TimingWheel.SetTimer(v.Key(), v, t); err == nil {
  96 + log.Logger.Debug(fmt.Sprintf("通知数控重试(%d) key:%s wait:%vs", v.RetryTime(), v.Key(), t.Seconds()))
  97 + return
  98 + }
  99 + }
  100 + }
  101 + tableEventService.TimingWheel.RemoveTimer(v.Key())
  102 +}
  1 +package service
  2 +
  3 +import (
  4 + "errors"
  5 + "fmt"
  6 + "github.com/linmadan/egglib-go/core/application"
  7 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/event/command"
  8 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/factory"
  9 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
  10 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/log"
  11 + "reflect"
  12 + "sort"
  13 +)
  14 +
  15 +func (tableEventService *TableEventService) HandlerTableAffectedMarkToConflictStatus(ctx *domain.Context, cmd *command.TableEventCommand) (interface{}, error) {
  16 + transactionContext, err := factory.CreateTransactionContext(nil)
  17 + if err != nil {
  18 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  19 + }
  20 + if err := transactionContext.StartTransaction(); err != nil {
  21 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  22 + }
  23 + defer func() {
  24 + transactionContext.RollbackTransaction()
  25 + }()
  26 +
  27 + data := cmd.EventTable
  28 + tableId := 0
  29 + switch data.Type {
  30 + case domain.TableStructEditEvent, domain.TableDeleteEvent:
  31 + tableId = data.Table.TableId
  32 + case domain.QuerySetUpdateEvent:
  33 + // 结构变更才报冲突
  34 + if !checkStructChange(cmd) {
  35 + return nil, err
  36 + }
  37 + tableId = data.QuerySet.QuerySetInfo.BindTableId
  38 + case domain.QuerySetUpdateRenameEvent:
  39 + tableId = data.QuerySet.QuerySetInfo.BindTableId
  40 + default:
  41 + return nil, err
  42 + }
  43 + if tableId == 0 {
  44 + return nil, nil
  45 + }
  46 + // tableId 相关联的
  47 + tableRepository, _, _ := factory.FastPgTable(transactionContext, 0)
  48 +
  49 + _, tables, err := tableRepository.Find(map[string]interface{}{"context": ctx, "dependencyTable": tableId, "tableTypesNotIn": []string{domain.TemporaryTable.ToString()}})
  50 + if errors.Is(err, domain.ErrorNotFound) {
  51 + return nil, nil
  52 + }
  53 + tableIds := make([]int, 0)
  54 + for _, table := range tables {
  55 + tableIds = append(tableIds, table.TableId)
  56 + }
  57 + if len(tableIds) == 0 {
  58 + return nil, nil
  59 + }
  60 + querySetRepository, _, _ := factory.FastPgQuerySet(transactionContext, 0)
  61 + _, querySets, _ := querySetRepository.Find(map[string]interface{}{"context": ctx, "bindTableIds": tableIds})
  62 + for _, querySet := range querySets {
  63 + log.Logger.Debug(fmt.Sprintf("【集合状态更新】 id:%v name:%v ReadyStatus:1", querySet.QuerySetId, querySet.Name))
  64 + querySet.QuerySetInfo.WithConflictStatus()
  65 + _, err = querySetRepository.Save(querySet)
  66 + if err != nil {
  67 + return nil, err
  68 + }
  69 + }
  70 +
  71 + //tableDependencyService, _ := domainService.NewTableDependencyService(transactionContext.(*pgTransaction.TransactionContext))
  72 + //tableDependTree := tableDependencyService.TableDependTree(tables, tableId)
  73 + //tree := tableDependTree.Tree
  74 + //
  75 + //querySetRepository, _, _ := factory.FastPgQuerySet(transactionContext, 0)
  76 + //if len(tree) > 0 {
  77 + // _, querySets, _ := querySetRepository.Find(map[string]interface{}{
  78 + // "types": []string{domain.SchemaTable.ToString(), domain.SubProcessTable.ToString(), domain.CalculateTable.ToString()},
  79 + // "bindTableIds": tree,
  80 + // })
  81 + // for _, querySet := range querySets {
  82 + // log.Logger.Debug(fmt.Sprintf("【集合状态更新】 id:%v name:%v 标记冲突", querySet.QuerySetId, querySet.Name))
  83 + // querySet.QuerySetInfo.WithConflictStatus()
  84 + // _, err = querySetRepository.Save(querySet)
  85 + // if err != nil {
  86 + // return nil, err
  87 + // }
  88 + // }
  89 + //}
  90 +
  91 + if err := transactionContext.CommitTransaction(); err != nil {
  92 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  93 + }
  94 + return nil, nil
  95 +}
  96 +
  97 +func checkStructChange(cmd *command.TableEventCommand) bool {
  98 + var (
  99 + newSet = cmd.EventTable.QuerySet
  100 + oldSet = cmd.EventTable.OldQuerySet
  101 + newTable = cmd.EventTable.Table
  102 + oldTable = cmd.EventTable.OldTable
  103 + )
  104 + if newSet == nil || oldSet == nil {
  105 + return false
  106 + }
  107 + var (
  108 + t string = newSet.Type
  109 + )
  110 +
  111 + switch t {
  112 + case domain.SchemaTable.ToString(), domain.SubProcessTable.ToString():
  113 + // 第一步表有变更
  114 + newSetDepTables := newSet.GetDependencyTables(newSet.QueryComponents)
  115 + oldSetDepTables := newSet.GetDependencyTables(oldSet.QueryComponents)
  116 + sort.SliceStable(newSetDepTables, func(i, j int) bool {
  117 + return newSetDepTables[i] < newSetDepTables[j]
  118 + })
  119 + sort.SliceStable(oldSetDepTables, func(i, j int) bool {
  120 + return oldSetDepTables[i] < oldSetDepTables[j]
  121 + })
  122 + if !reflect.DeepEqual(newSetDepTables, oldSetDepTables) {
  123 + log.Logger.Debug(fmt.Sprintf("方案/过程:%v 依赖变更 %v -> %v", t, oldSetDepTables, newSetDepTables))
  124 + return true
  125 + }
  126 + case domain.CalculateTable.ToString():
  127 +
  128 + case domain.CalculateItem.ToString(), domain.CalculateSet.ToString():
  129 + return false
  130 + }
  131 + if newTable == nil || oldTable == nil {
  132 + return false
  133 + }
  134 + // 第二步判断字段是否有变更
  135 + newTableFields := tableFields(newTable)
  136 + oldTableFields := tableFields(oldTable)
  137 + sort.Strings(newTableFields)
  138 + sort.Strings(oldTableFields)
  139 + if !reflect.DeepEqual(newTableFields, oldTableFields) {
  140 + log.Logger.Debug(fmt.Sprintf("计算表:%v 结构变更 %v -> %v", t, oldTableFields, newTableFields))
  141 + return true
  142 + }
  143 + return false
  144 +}
  145 +
  146 +func tableFields(t *domain.Table) []string {
  147 + var result = make([]string, 0)
  148 + for _, f := range t.Fields(false) {
  149 + result = append(result, f.Name)
  150 + }
  151 + return result
  152 +}
@@ -4,7 +4,6 @@ import ( @@ -4,7 +4,6 @@ import (
4 "github.com/linmadan/egglib-go/core/application" 4 "github.com/linmadan/egglib-go/core/application"
5 "github.com/linmadan/egglib-go/transaction/pg" 5 "github.com/linmadan/egglib-go/transaction/pg"
6 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain" 6 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
7 - "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain/bytecore"  
8 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/domainService" 7 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/domainService"
9 ) 8 )
10 9
@@ -58,6 +57,6 @@ func CreateTableEditDataService(transactionContext application.TransactionContex @@ -58,6 +57,6 @@ func CreateTableEditDataService(transactionContext application.TransactionContex
58 } 57 }
59 58
60 // 字库核心 59 // 字库核心
61 -func CreateByteCoreService(transactionContext application.TransactionContext) (bytecore.ByteLibService, error) { 60 +func CreateByteCoreService(transactionContext application.TransactionContext) (domain.ByteLibService, error) {
62 return domainService.ByteCore, nil 61 return domainService.ByteCore, nil
63 } 62 }
@@ -2,7 +2,9 @@ package factory @@ -2,7 +2,9 @@ package factory
2 2
3 import ( 3 import (
4 "github.com/linmadan/egglib-go/core/application" 4 "github.com/linmadan/egglib-go/core/application"
  5 + pgTransaction "github.com/linmadan/egglib-go/transaction/pg"
5 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain" 6 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
  7 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/domainService"
6 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/starrocks" 8 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/starrocks"
7 ) 9 )
8 10
@@ -10,6 +12,18 @@ func FastError(err error) error { @@ -10,6 +12,18 @@ func FastError(err error) error {
10 return application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error()) 12 return application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
11 } 13 }
12 14
  15 +func FastErrorResponse(err error, args ...interface{}) interface{} {
  16 + var response = make(map[string]interface{})
  17 + response["internalErr"] = err.Error()
  18 + for i := 0; i < len(args); i += 2 {
  19 + if i+1 >= len(args) {
  20 + break
  21 + }
  22 + response[args[i].(string)] = args[i+1]
  23 + }
  24 + return response
  25 +}
  26 +
13 func FastDataTable(options starrocks.QueryOptions) (*domain.DataTable, error) { 27 func FastDataTable(options starrocks.QueryOptions) (*domain.DataTable, error) {
14 var err error 28 var err error
15 // 待优化分批下载,压缩 29 // 待优化分批下载,压缩
@@ -25,3 +39,7 @@ func FastDataTable(options starrocks.QueryOptions) (*domain.DataTable, error) { @@ -25,3 +39,7 @@ func FastDataTable(options starrocks.QueryOptions) (*domain.DataTable, error) {
25 } 39 }
26 return dataTable, nil 40 return dataTable, nil
27 } 41 }
  42 +
  43 +func FastQuerySetServices(transactionContext application.TransactionContext) (*domainService.QuerySetService, error) {
  44 + return domainService.NewQuerySetService(transactionContext.(*pgTransaction.TransactionContext))
  45 +}
@@ -23,9 +23,9 @@ func FastPgFile(transactionContext application.TransactionContext, id int) (doma @@ -23,9 +23,9 @@ func FastPgFile(transactionContext application.TransactionContext, id int) (doma
23 if id > 0 { 23 if id > 0 {
24 if mod, err = rep.FindOne(map[string]interface{}{"fileId": id}); err != nil { 24 if mod, err = rep.FindOne(map[string]interface{}{"fileId": id}); err != nil {
25 if err == domain.ErrorNotFound { 25 if err == domain.ErrorNotFound {
26 - return nil, nil, application.ThrowError(application.RES_NO_FIND_ERROR, "该文件不存在") 26 + return rep, nil, application.ThrowError(application.RES_NO_FIND_ERROR, "该文件不存在")
27 } 27 }
28 - return nil, nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) 28 + return rep, nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
29 } 29 }
30 } 30 }
31 //if err = fastPgDataAuth(transactionContext, mod, options...); err != nil { 31 //if err = fastPgDataAuth(transactionContext, mod, options...); err != nil {
@@ -52,9 +52,9 @@ func FastPgTable(transactionContext application.TransactionContext, id int) (dom @@ -52,9 +52,9 @@ func FastPgTable(transactionContext application.TransactionContext, id int) (dom
52 if id > 0 { 52 if id > 0 {
53 if mod, err = rep.FindOne(map[string]interface{}{"tableId": id}); err != nil { 53 if mod, err = rep.FindOne(map[string]interface{}{"tableId": id}); err != nil {
54 if err == domain.ErrorNotFound { 54 if err == domain.ErrorNotFound {
55 - return nil, nil, application.ThrowError(application.RES_NO_FIND_ERROR, "该表格不存在") 55 + return rep, nil, application.ThrowError(application.RES_NO_FIND_ERROR, "该表格不存在")
56 } 56 }
57 - return nil, nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) 57 + return rep, nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
58 } 58 }
59 } 59 }
60 return rep, mod, err 60 return rep, mod, err
@@ -78,9 +78,9 @@ func FastPgLog(transactionContext application.TransactionContext, id int) (domai @@ -78,9 +78,9 @@ func FastPgLog(transactionContext application.TransactionContext, id int) (domai
78 if id > 0 { 78 if id > 0 {
79 if mod, err = rep.FindOne(map[string]interface{}{"logId": id}); err != nil { 79 if mod, err = rep.FindOne(map[string]interface{}{"logId": id}); err != nil {
80 if err == domain.ErrorNotFound { 80 if err == domain.ErrorNotFound {
81 - return nil, nil, application.ThrowError(application.RES_NO_FIND_ERROR, "该日志不存在") 81 + return rep, nil, application.ThrowError(application.RES_NO_FIND_ERROR, "该日志不存在")
82 } 82 }
83 - return nil, nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) 83 + return rep, nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
84 } 84 }
85 } 85 }
86 return rep, mod, err 86 return rep, mod, err
@@ -104,9 +104,35 @@ func FastPgMappingRule(transactionContext application.TransactionContext, id int @@ -104,9 +104,35 @@ func FastPgMappingRule(transactionContext application.TransactionContext, id int
104 if id > 0 { 104 if id > 0 {
105 if mod, err = rep.FindOne(map[string]interface{}{"mappingRuleId": id}); err != nil { 105 if mod, err = rep.FindOne(map[string]interface{}{"mappingRuleId": id}); err != nil {
106 if err == domain.ErrorNotFound { 106 if err == domain.ErrorNotFound {
107 - return nil, nil, application.ThrowError(application.RES_NO_FIND_ERROR, "该匹配规则不存在") 107 + return rep, nil, application.ThrowError(application.RES_NO_FIND_ERROR, "该匹配规则不存在")
108 } 108 }
109 - return nil, nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) 109 + return rep, nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  110 + }
  111 + }
  112 + return rep, mod, err
  113 +}
  114 +
  115 +// FastPgQuerySet 快速返回查询集合
  116 +//
  117 +// transactionContext 事务
  118 +// id 对象唯一标识
  119 +func FastPgQuerySet(transactionContext application.TransactionContext, id int) (domain.QuerySetRepository, *domain.QuerySet, error) {
  120 + var rep domain.QuerySetRepository
  121 + var mod *domain.QuerySet
  122 + var err error
  123 + if value, err := CreateQuerySetRepository(map[string]interface{}{
  124 + "transactionContext": transactionContext,
  125 + }); err != nil {
  126 + return nil, nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  127 + } else {
  128 + rep = value
  129 + }
  130 + if id > 0 {
  131 + if mod, err = rep.FindOne(map[string]interface{}{"querySetId": id}); err != nil {
  132 + if err == domain.ErrorNotFound {
  133 + return rep, nil, application.ThrowError(application.RES_NO_FIND_ERROR, "该查询集合不存在")
  134 + }
  135 + return rep, nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
110 } 136 }
111 } 137 }
112 return rep, mod, err 138 return rep, mod, err
@@ -37,3 +37,11 @@ func CreateMappingRuleRepository(options map[string]interface{}) (domain.Mapping @@ -37,3 +37,11 @@ func CreateMappingRuleRepository(options map[string]interface{}) (domain.Mapping
37 } 37 }
38 return repository.NewMappingRuleRepository(transactionContext) 38 return repository.NewMappingRuleRepository(transactionContext)
39 } 39 }
  40 +
  41 +func CreateQuerySetRepository(options map[string]interface{}) (domain.QuerySetRepository, error) {
  42 + var transactionContext *pg.TransactionContext
  43 + if value, ok := options["transactionContext"]; ok {
  44 + transactionContext = value.(*pg.TransactionContext)
  45 + }
  46 + return repository.NewQuerySetRepository(transactionContext)
  47 +}
  1 +package command
  2 +
  3 +import "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
  4 +
  5 +type AppTableFileAppendDataCommand struct {
  6 + Name string `json:"name"`
  7 + // name 字段中文名
  8 + Fields []*domain.Field `json:"fields"`
  9 + // 数据列表 key:name(字段中文名) value:值(字符串类型)
  10 + Data []map[string]string `json:"data"`
  11 +
  12 + AppKey string `json:"appKey"`
  13 +
  14 + // 追加表数据标识 true:往应用表里面追加数据 false:跳过
  15 + AppendTableDataFlag bool `json:"appendTableDataFlag"`
  16 +}
  1 +package command
  2 +
  3 +import "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
  4 +
  5 +type CreateAppTableFileCommand struct {
  6 + Name string `json:"name"`
  7 + // name 字段中文名
  8 + Fields []*domain.Field `json:"fields"`
  9 + // 数据列表 key:name(字段中文名) value:值(字符串类型)
  10 + Data []map[string]string `json:"data"`
  11 + // 生成表标识 true:实例化一个表 false:跳过
  12 + GenerateTableFlag bool `json:"generateTableFlag"`
  13 +}
  1 +package command
  2 +
  3 +type DeleteAppTableFileCommand struct {
  4 + Name string `json:"name"`
  5 + AppKey string `json:"appKey"`
  6 +}
  1 +package command
  2 +
  3 +import "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
  4 +
  5 +type UpdateAppTableFileCommand struct {
  6 + Name string `json:"name"`
  7 + AppKey string `json:"appKey"`
  8 + AddFields []*domain.Field `json:"addFields"`
  9 +}
@@ -19,7 +19,14 @@ type AppendDataToTableCommand struct { @@ -19,7 +19,14 @@ type AppendDataToTableCommand struct {
19 } 19 }
20 20
21 func (cmd *AppendDataToTableCommand) Valid(validation *validation.Validation) { 21 func (cmd *AppendDataToTableCommand) Valid(validation *validation.Validation) {
22 - 22 + newMappingFields := make([]*domain.MappingField, 0)
  23 + for i := range cmd.MappingFields {
  24 + if len(cmd.MappingFields[i].VerifiedFileFieldName) == 0 {
  25 + continue
  26 + }
  27 + newMappingFields = append(newMappingFields, cmd.MappingFields[i])
  28 + }
  29 + cmd.MappingFields = newMappingFields
23 } 30 }
24 31
25 func (cmd *AppendDataToTableCommand) ValidateCommand() error { 32 func (cmd *AppendDataToTableCommand) ValidateCommand() error {
  1 +package command
  2 +
  3 +import (
  4 + "fmt"
  5 + "reflect"
  6 + "strings"
  7 +
  8 + "github.com/beego/beego/v2/core/validation"
  9 +)
  10 +
  11 +type CheckFileVerifyStatusCommand struct {
  12 + // 文件ID
  13 + FileId int `cname:"文件ID" json:"objectId" valid:"Required"`
  14 +}
  15 +
  16 +func (cmd *CheckFileVerifyStatusCommand) Valid(validation *validation.Validation) {
  17 +
  18 +}
  19 +
  20 +func (cmd *CheckFileVerifyStatusCommand) ValidateCommand() error {
  21 + valid := validation.Validation{}
  22 + b, err := valid.Valid(cmd)
  23 + if err != nil {
  24 + return err
  25 + }
  26 + if !b {
  27 + elem := reflect.TypeOf(cmd).Elem()
  28 + for _, validErr := range valid.Errors {
  29 + field, isExist := elem.FieldByName(validErr.Field)
  30 + if isExist {
  31 + return fmt.Errorf(strings.Replace(validErr.Message, validErr.Field, field.Tag.Get("cname"), -1))
  32 + } else {
  33 + return fmt.Errorf(validErr.Message)
  34 + }
  35 + }
  36 + }
  37 + return nil
  38 +}
@@ -17,14 +17,37 @@ type CreateFileCommand struct { @@ -17,14 +17,37 @@ type CreateFileCommand struct {
17 Url string `cname:"文件地址" json:"url" valid:"Required"` 17 Url string `cname:"文件地址" json:"url" valid:"Required"`
18 // 文件大小 单位KB 18 // 文件大小 单位KB
19 FileSize int `cname:"文件大小" json:"fileSize" valid:"Required"` 19 FileSize int `cname:"文件大小" json:"fileSize" valid:"Required"`
  20 + // 文件来源
  21 + FileFrom string `json:"-"`
  22 + // AppKey
  23 + AppKey string `json:"-"`
  24 +
  25 + // 生成表标识 true:实例化一个表 false:跳过
  26 + GenerateTableFlag bool `json:"-"`
  27 + // name 字段中文名
  28 + Fields []*domain.Field `json:"-"`
20 } 29 }
21 30
  31 +var MaxFileSize = 50 * 1024 * 1024
  32 +
22 func (createFileCommand *CreateFileCommand) Valid(validation *validation.Validation) { 33 func (createFileCommand *CreateFileCommand) Valid(validation *validation.Validation) {
23 ext := filepath.Ext(createFileCommand.Name) 34 ext := filepath.Ext(createFileCommand.Name)
24 if !(ext == domain.XLS || ext == domain.XLSX) { 35 if !(ext == domain.XLS || ext == domain.XLSX) {
25 - validation.Error(fmt.Sprintf("仅支持文件格式 xls 、 xlsx")) 36 + validation.Error("仅支持文件格式 xls 、 xlsx")
  37 + return
  38 + }
  39 + if createFileCommand.FileSize > 0 && createFileCommand.FileSize > MaxFileSize {
  40 + validation.Error("文件大小超过50M")
26 return 41 return
27 } 42 }
  43 + if createFileCommand.GenerateTableFlag {
  44 + for _, f := range createFileCommand.Fields {
  45 + if err := f.Valid(); err != nil {
  46 + validation.Error(err.Error())
  47 + return
  48 + }
  49 + }
  50 + }
28 } 51 }
29 52
30 func (createFileCommand *CreateFileCommand) ValidateCommand() error { 53 func (createFileCommand *CreateFileCommand) ValidateCommand() error {
@@ -15,10 +15,11 @@ type EditDataTableCommand struct { @@ -15,10 +15,11 @@ type EditDataTableCommand struct {
15 // 15 //
16 //Fields []*domain.Field 16 //Fields []*domain.Field
17 domain.EditTableRequest 17 domain.EditTableRequest
  18 + HeaderRow int `json:"headerRow"` // 行号 默认:0
18 } 19 }
19 20
20 func (editDataTableCommand *EditDataTableCommand) Valid(validation *validation.Validation) { 21 func (editDataTableCommand *EditDataTableCommand) Valid(validation *validation.Validation) {
21 - if len(editDataTableCommand.ProcessFields) == 0 { 22 + if len(editDataTableCommand.ProcessFieldNames) == 0 {
22 validation.Error("未选择操作列") 23 validation.Error("未选择操作列")
23 return 24 return
24 } 25 }
@@ -30,6 +31,7 @@ func (editDataTableCommand *EditDataTableCommand) Valid(validation *validation.V @@ -30,6 +31,7 @@ func (editDataTableCommand *EditDataTableCommand) Valid(validation *validation.V
30 validation.Error("文件ID不能为空") 31 validation.Error("文件ID不能为空")
31 return 32 return
32 } 33 }
  34 + editDataTableCommand.Where.HeaderRow = domain.SetHeaderRow(editDataTableCommand.HeaderRow)
33 } 35 }
34 36
35 func (editDataTableCommand *EditDataTableCommand) ValidateCommand() error { 37 func (editDataTableCommand *EditDataTableCommand) ValidateCommand() error {
  1 +package command
  2 +
  3 +import (
  4 + "fmt"
  5 + "reflect"
  6 + "strings"
  7 +
  8 + "github.com/beego/beego/v2/core/validation"
  9 +)
  10 +
  11 +type ExportFileCommand struct {
  12 + // 文件ID
  13 + FileId int `cname:"文件ID" json:"fileId" valid:"Required"`
  14 +}
  15 +
  16 +func (cmd *ExportFileCommand) Valid(validation *validation.Validation) {
  17 +
  18 +}
  19 +
  20 +func (cmd *ExportFileCommand) ValidateCommand() error {
  21 + valid := validation.Validation{}
  22 + b, err := valid.Valid(cmd)
  23 + if err != nil {
  24 + return err
  25 + }
  26 + if !b {
  27 + elem := reflect.TypeOf(cmd).Elem()
  28 + for _, validErr := range valid.Errors {
  29 + field, isExist := elem.FieldByName(validErr.Field)
  30 + if isExist {
  31 + return fmt.Errorf(strings.Replace(validErr.Message, validErr.Field, field.Tag.Get("cname"), -1))
  32 + } else {
  33 + return fmt.Errorf(validErr.Message)
  34 + }
  35 + }
  36 + }
  37 + return nil
  38 +}
@@ -2,7 +2,6 @@ package command @@ -2,7 +2,6 @@ package command
2 2
3 import ( 3 import (
4 "fmt" 4 "fmt"
5 - "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"  
6 "reflect" 5 "reflect"
7 "strings" 6 "strings"
8 7
@@ -11,11 +10,11 @@ import ( @@ -11,11 +10,11 @@ import (
11 10
12 type FlushDataTableCommand struct { 11 type FlushDataTableCommand struct {
13 // 文件ID 12 // 文件ID
14 - FileId int `cname:"文件ID" json:"objectId" valid:"Required"` 13 + ObjectId int `cname:"文件ID" json:"objectId" valid:"Required"`
15 // 记录数 14 // 记录数
16 - RowCount int `cname:"记录数" json:"rowCount" valid:"Required"` 15 + //RowCount int `cname:"记录数" json:"rowCount" valid:"Required"`
17 // 数据列 16 // 数据列
18 - DataFields []*domain.Field `cname:"数据列" json:"fields" valid:"Required"` 17 + //DataFields []*domain.Field `cname:"数据列" json:"fields" valid:"Required"`
19 } 18 }
20 19
21 func (flushDataTableCommand *FlushDataTableCommand) Valid(validation *validation.Validation) { 20 func (flushDataTableCommand *FlushDataTableCommand) Valid(validation *validation.Validation) {
@@ -23,6 +23,7 @@ func (loadDataTableCommand *LoadDataTableCommand) Valid(validation *validation.V @@ -23,6 +23,7 @@ func (loadDataTableCommand *LoadDataTableCommand) Valid(validation *validation.V
23 if loadDataTableCommand.PageSize == 0 { 23 if loadDataTableCommand.PageSize == 0 {
24 loadDataTableCommand.PageSize = 20 24 loadDataTableCommand.PageSize = 20
25 } 25 }
  26 + loadDataTableCommand.HeaderRow = domain.SetHeaderRow(loadDataTableCommand.HeaderRow)
26 } 27 }
27 28
28 func (loadDataTableCommand *LoadDataTableCommand) ValidateCommand() error { 29 func (loadDataTableCommand *LoadDataTableCommand) ValidateCommand() error {
  1 +package command
  2 +
  3 +import (
  4 + "fmt"
  5 + "reflect"
  6 + "strings"
  7 +
  8 + "github.com/beego/beego/v2/core/validation"
  9 +)
  10 +
  11 +type PrepareTemporaryFileCommand struct {
  12 + // 文件ID
  13 + FileId int `cname:"文件ID" json:"fileId" valid:"Required"`
  14 +}
  15 +
  16 +func (cmd *PrepareTemporaryFileCommand) Valid(validation *validation.Validation) {
  17 +
  18 +}
  19 +
  20 +func (cmd *PrepareTemporaryFileCommand) ValidateCommand() error {
  21 + valid := validation.Validation{}
  22 + b, err := valid.Valid(cmd)
  23 + if err != nil {
  24 + return err
  25 + }
  26 + if !b {
  27 + elem := reflect.TypeOf(cmd).Elem()
  28 + for _, validErr := range valid.Errors {
  29 + field, isExist := elem.FieldByName(validErr.Field)
  30 + if isExist {
  31 + return fmt.Errorf(strings.Replace(validErr.Message, validErr.Field, field.Tag.Get("cname"), -1))
  32 + } else {
  33 + return fmt.Errorf(validErr.Message)
  34 + }
  35 + }
  36 + }
  37 + return nil
  38 +}
  1 +package command
  2 +
  3 +import (
  4 + "fmt"
  5 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
  6 + "reflect"
  7 + "strings"
  8 +
  9 + "github.com/beego/beego/v2/core/validation"
  10 +)
  11 +
  12 +type ResetTableHeaderCommand struct {
  13 + // 文件ID
  14 + FileId int `cname:"文件ID" json:"objectId" valid:"Required"`
  15 + domain.Where
  16 +}
  17 +
  18 +func (loadDataTableCommand *ResetTableHeaderCommand) Valid(validation *validation.Validation) {
  19 + loadDataTableCommand.HeaderRow = domain.SetHeaderRow(loadDataTableCommand.HeaderRow)
  20 +}
  21 +
  22 +func (loadDataTableCommand *ResetTableHeaderCommand) ValidateCommand() error {
  23 + valid := validation.Validation{}
  24 + b, err := valid.Valid(loadDataTableCommand)
  25 + if err != nil {
  26 + return err
  27 + }
  28 + if !b {
  29 + elem := reflect.TypeOf(loadDataTableCommand).Elem()
  30 + for _, validErr := range valid.Errors {
  31 + field, isExist := elem.FieldByName(validErr.Field)
  32 + if isExist {
  33 + return fmt.Errorf(strings.Replace(validErr.Message, validErr.Field, field.Tag.Get("cname"), -1))
  34 + } else {
  35 + return fmt.Errorf(validErr.Message)
  36 + }
  37 + }
  38 + }
  39 + return nil
  40 +}
  1 +package dto
  2 +
  3 +import "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
  4 +
  5 +type EditDataTableDto struct {
  6 + Code int `json:"errNo,omitempty"`
  7 + Error string `json:"errMsg,omitempty"`
  8 + InValidCells []domain.InValidCell `json:"inValidCells,omitempty"`
  9 +}
  10 +
  11 +func (d *EditDataTableDto) Load(m *domain.DataEditDataTable) *EditDataTableDto {
  12 + d.Error = ""
  13 + if len(m.InValidCells) > 0 {
  14 + d.Error = "类型转换错误"
  15 + d.Code = 1001 // 1001:类型转换错误
  16 + }
  17 + //d.InValidCells = m.InValidCells
  18 + return d
  19 +}
@@ -14,14 +14,77 @@ type FileDto struct { @@ -14,14 +14,77 @@ type FileDto struct {
14 Url string `json:"url"` 14 Url string `json:"url"`
15 // 文件类型 15 // 文件类型
16 FileType string `json:"fileType"` 16 FileType string `json:"fileType"`
  17 + // 后缀扩展
  18 + Ext string `json:"ext"`
17 // 创建时间 19 // 创建时间
18 Time string `json:"time"` 20 Time string `json:"time"`
  21 + // 行号
  22 + HeaderRow int `json:"headerRow"`
  23 + // 所属应用
  24 + AppKey string `json:"appKey"`
  25 + // 表ID
  26 + TableId int `json:"tableId"`
  27 + // 允许表生成标识 1:允许生成分表 0:不允许
  28 + AllowTableGenerateFlag int `json:"-"`
  29 + // 允许表处理标识 1:允许 0:不允许
  30 + AllowTableProcessFlag int `json:"-"`
  31 + // 允许表导出标识 1:允许 0:不允许
  32 + AllowTableExportFlag int `json:"-"`
  33 + // 标志位 1:可校验 2:可分表生成 4:导出
  34 + Flag int `json:"-"`
  35 + // 标志位 1:可校验 2:可分表生成 4:导出
  36 + Flags []int `json:"flags"`
19 } 37 }
20 38
21 -func (d *FileDto) Load(f *domain.File) { 39 +func (d *FileDto) Load(f *domain.File) *FileDto {
  40 + if f == nil {
  41 + return nil
  42 + }
22 d.FileId = f.FileId 43 d.FileId = f.FileId
23 d.Name = f.FileInfo.Name 44 d.Name = f.FileInfo.Name
24 d.Url = f.FileInfo.Url 45 d.Url = f.FileInfo.Url
25 d.FileType = f.FileType 46 d.FileType = f.FileType
26 - d.Time = xtime.New(f.CreatedAt).Local().Format("2006-01-02 15:04:05") 47 + d.Ext = f.FileInfo.Ext
  48 + d.Time = xtime.New(f.UpdatedAt).Local().Format("2006-01-02 15:04:05")
  49 + d.HeaderRow = domain.GetHeaderRow(f.FileInfo.HeaderRow)
  50 + d.AppKey = f.AppKey
  51 + //d.AllowTableProcessFlag = 1
  52 + //d.AllowTableExportFlag = 1
  53 + d.AddFlag(5) // 默认可以 校验、导出
  54 + if len(f.AppKey) > 0 && f.FileInfo.TableId > 0 {
  55 + d.TableId = f.FileInfo.TableId
  56 + //d.AllowTableGenerateFlag = 1
  57 + d.AddFlag(2) // 可分表生成
  58 + d.RemoveFlag(1) // 不可校验
  59 + //d.RemoveFlag(4) // 不可校验
  60 + //d.AllowTableProcessFlag = 0
  61 + //d.AllowTableExportFlag = 0
  62 + }
  63 + for i := 1; i <= 4; i = i << 1 {
  64 + if i&d.Flag == i {
  65 + d.Flags = append(d.Flags, i)
  66 + }
  67 + }
  68 + return d
  69 +}
  70 +
  71 +func (d *FileDto) AddFlag(flag int) {
  72 + if d.Flag&flag == flag {
  73 + return
  74 + }
  75 + d.Flag |= flag
  76 +}
  77 +
  78 +func (d *FileDto) RemoveFlag(flag int) {
  79 + if d.Flag&flag != flag {
  80 + return
  81 + }
  82 + d.Flag ^= flag
  83 +}
  84 +
  85 +type AppDto struct {
  86 + AppId int64 `json:"appId"`
  87 + AppKey string `json:"appKey"`
  88 + AppName string `json:"appName"`
  89 + Files []*FileDto `json:"files"`
27 } 90 }
@@ -10,11 +10,15 @@ import ( @@ -10,11 +10,15 @@ import (
10 10
11 type GetFileQuery struct { 11 type GetFileQuery struct {
12 // 文件ID 12 // 文件ID
13 - FileId int `cname:"文件ID" json:"fileId" valid:"Required"` 13 + FileId int `cname:"文件ID" json:"fileId"`
  14 +
  15 + FileName string `json:"name"`
  16 +
  17 + FileType string `json:"type"`
14 } 18 }
15 19
16 func (getFileQuery *GetFileQuery) Valid(validation *validation.Validation) { 20 func (getFileQuery *GetFileQuery) Valid(validation *validation.Validation) {
17 - validation.SetError("CustomValid", "未实现的自定义认证") 21 +
18 } 22 }
19 23
20 func (getFileQuery *GetFileQuery) ValidateQuery() error { 24 func (getFileQuery *GetFileQuery) ValidateQuery() error {
  1 +package query
  2 +
  3 +type ListAppTableFileCommand struct {
  4 + Name string `json:"name"`
  5 + AppKey string `json:"appKey"`
  6 +}
@@ -17,11 +17,12 @@ type SearchFileQuery struct { @@ -17,11 +17,12 @@ type SearchFileQuery struct {
17 // 页码 17 // 页码
18 // PageNumber int `cname:"页码" json:"pageNumber,omitempty"` 18 // PageNumber int `cname:"页码" json:"pageNumber,omitempty"`
19 // 页数 19 // 页数
20 - FileName string `cname:"文件名称" json:"fileName,omitempty"`  
21 - PageSize int `cname:"页数" json:"pageSize,omitempty"`  
22 - LastId int `cname:"最后一条记录ID" json:"lastId"`  
23 - FileType domain.FileType `cname:"文件类型" json:"fileType" valid:"Required"`  
24 - Context *domain.Context 20 + FileName string `cname:"文件名称" json:"fileName,omitempty"`
  21 + PageSize int `cname:"页数" json:"pageSize,omitempty"`
  22 + LastId int `cname:"最后一条记录ID" json:"lastId"`
  23 + FileType domain.FileType `cname:"文件类型" json:"fileType" valid:"Required"`
  24 + InAppKeys []string `json:"inAppKeys"`
  25 + Context *domain.Context
25 } 26 }
26 27
27 func (cmd *SearchFileQuery) Valid(validation *validation.Validation) { 28 func (cmd *SearchFileQuery) Valid(validation *validation.Validation) {
  1 +package service
  2 +
  3 +import (
  4 + "bytes"
  5 + "errors"
  6 + "fmt"
  7 + "github.com/beego/beego/v2/client/httplib"
  8 + "github.com/linmadan/egglib-go/core/application"
  9 + pgTransaction "github.com/linmadan/egglib-go/transaction/pg"
  10 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/factory"
  11 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/file/command"
  12 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/file/query"
  13 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/constant"
  14 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
  15 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/api/apilib"
  16 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/domainService"
  17 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/excel"
  18 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/starrocks"
  19 + "os"
  20 + "strings"
  21 + "time"
  22 +)
  23 +
  24 +func (fileService *FileService) CreateAppTableFile(ctx *domain.Context, cmd *command.CreateAppTableFileCommand) (*command.CreateFileCommand, error) {
  25 + response := &command.CreateFileCommand{}
  26 + var (
  27 + titles = make([]string, 0)
  28 + dataList = make([][]string, 0)
  29 + )
  30 + for _, filed := range cmd.Fields {
  31 + titles = append(titles, filed.Name)
  32 + }
  33 + for i := range cmd.Data {
  34 + row := make([]string, 0)
  35 + for _, filed := range titles {
  36 + if v, ok := cmd.Data[i][filed]; ok {
  37 + row = append(row, v)
  38 + } else {
  39 + row = append(row, "")
  40 + }
  41 + }
  42 + dataList = append(dataList, row)
  43 + }
  44 + fileUpload, err := saveFile(cmd.Name, titles, dataList, nil)
  45 + if err != nil {
  46 + return nil, factory.FastError(err)
  47 + }
  48 + response.Name = cmd.Name
  49 + if !strings.HasSuffix(response.Name, domain.XLSX) {
  50 + response.Name = response.Name + domain.XLSX
  51 + }
  52 + response.Url = fileUpload.Url
  53 + response.FileSize = int(fileUpload.FileSize)
  54 + response.FileFrom = domain.FileFromDigitalAppClient
  55 + return response, nil
  56 +}
  57 +
  58 +func saveFile(name string, title []string, dataList [][]string, toInterfaces func([]string) []interface{}) (FileUpload, error) {
  59 + var (
  60 + response = FileUpload{}
  61 + err error
  62 + )
  63 + var writerTo = excel.NewXLXSWriterTo(title, dataList)
  64 + if toInterfaces != nil {
  65 + writerTo.ToInterfaces = toInterfaces
  66 + }
  67 + filename := fmt.Sprintf("%v_%v.xlsx", name, time.Now().Format("060102150405"))
  68 + path := fmt.Sprintf("public/%v", filename)
  69 + if err = writerTo.Save(path); err != nil {
  70 + return response, factory.FastError(err)
  71 + }
  72 + api := apilib.NewApiAuthLib(constant.OPEN_API_HOST)
  73 + uploadResponse, err := api.Upload(apilib.RequestUpload{
  74 + UploadFileMap: map[string]string{"file": path},
  75 + })
  76 + if err != nil {
  77 + return response, err
  78 + }
  79 + if stat, err := os.Stat(path); err == nil {
  80 + response.FileSize = stat.Size()
  81 + }
  82 + response.Url = domain.ConvertInternalFileUrlToPublic(uploadResponse.Path)
  83 + response.FileName = name
  84 + response.Ext = domain.XLSX
  85 +
  86 + return response, nil
  87 +}
  88 +
  89 +func saveCsvFile(name string, title []string, dataList [][]string, toInterfaces func([]string) []interface{}) (FileUpload, error) {
  90 + var (
  91 + response = FileUpload{}
  92 + err error
  93 + )
  94 + var writerTo = excel.NewCSVWriterTo(title, dataList)
  95 + filename := fmt.Sprintf("%v_%v.csv", name, time.Now().Format("060102150405"))
  96 + path := fmt.Sprintf("public/%v", filename)
  97 + if err = writerTo.Save(path); err != nil {
  98 + return response, factory.FastError(err)
  99 + }
  100 + api := apilib.NewApiAuthLib(constant.OPEN_API_HOST)
  101 + uploadResponse, err := api.Upload(apilib.RequestUpload{
  102 + UploadFileMap: map[string]string{"file": path},
  103 + })
  104 + if err != nil {
  105 + return response, err
  106 + }
  107 + if stat, err := os.Stat(path); err == nil {
  108 + response.FileSize = stat.Size()
  109 + }
  110 + response.Url = domain.ConvertInternalFileUrlToPublic(uploadResponse.Path)
  111 + response.FileName = name
  112 + response.Ext = domain.CSV
  113 +
  114 + return response, nil
  115 +}
  116 +
  117 +type FileUpload struct {
  118 + Url string `json:"url"`
  119 + Ext string `json:"ext"`
  120 + FileName string `json:"fileName"`
  121 + FileSize int64 `json:"fileSize"`
  122 +}
  123 +
  124 +func (fileService *FileService) DeleteAppTableFile(ctx *domain.Context, cmd *command.DeleteAppTableFileCommand) (interface{}, error) {
  125 + transactionContext, err := factory.CreateTransactionContext(nil)
  126 + if err != nil {
  127 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  128 + }
  129 + if err := transactionContext.StartTransaction(); err != nil {
  130 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  131 + }
  132 + defer func() {
  133 + transactionContext.RollbackTransaction()
  134 + }()
  135 +
  136 + fileRepository, file, _ := factory.FastPgFile(transactionContext, 0)
  137 + file, err = fileRepository.FindOne(map[string]interface{}{"appKey": cmd.AppKey, "fileName": cmd.Name, "fileType": domain.SourceFile})
  138 + if err == domain.ErrorNotFound {
  139 + return nil, factory.FastError(errors.New("文件不存在"))
  140 + }
  141 + if err != nil {
  142 + return nil, factory.FastError(err)
  143 + }
  144 + if _, err := fileRepository.Remove(file); err != nil {
  145 + return nil, factory.FastError(err)
  146 + }
  147 + if err := transactionContext.CommitTransaction(); err != nil {
  148 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  149 + }
  150 + return struct{}{}, nil
  151 +}
  152 +
  153 +func (fileService *FileService) AppTableFileAppendData(ctx *domain.Context, cmd *command.AppTableFileAppendDataCommand) (interface{}, error) {
  154 + transactionContext, err := factory.CreateTransactionContext(nil)
  155 + if err != nil {
  156 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  157 + }
  158 + if err := transactionContext.StartTransaction(); err != nil {
  159 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  160 + }
  161 + defer func() {
  162 + transactionContext.RollbackTransaction()
  163 + }()
  164 +
  165 + fileRepository, file, _ := factory.FastPgFile(transactionContext, 0)
  166 + file, err = fileRepository.FindOne(map[string]interface{}{"appKey": cmd.AppKey, "fileName": cmd.Name, "fileType": domain.SourceFile})
  167 + if err == domain.ErrorNotFound {
  168 + return nil, factory.FastError(errors.New("文件不存在"))
  169 + }
  170 + if err != nil {
  171 + return nil, factory.FastError(err)
  172 + }
  173 +
  174 + // 下载文件
  175 + f, err := httplib.Get(domain.ConvertFileUrlToInternal(file.FileInfo.Url)).Bytes()
  176 + if err != nil {
  177 + return nil, factory.FastError(err)
  178 + }
  179 + reader := bytes.NewReader(f)
  180 + var (
  181 + importer *excel.Importer = excel.NewExcelImportByFile(file.FileInfo.Ext)
  182 + appendTableDataList = make([][]string, 0)
  183 + )
  184 + data, err := importer.OpenExcelFromIoReader(reader)
  185 + if err != nil {
  186 + return nil, factory.FastError(err)
  187 + }
  188 + titles := importer.Reader().Header().Columns
  189 + for _, f := range cmd.Fields {
  190 + found := false
  191 + for _, column := range titles {
  192 + if column == f.Name {
  193 + found = true
  194 + break
  195 + }
  196 + }
  197 + if !found {
  198 + titles = append(titles, f.Name)
  199 + }
  200 + }
  201 + // 填充旧数据
  202 + // 追加文件
  203 + for i := range data {
  204 + if len(data[i]) < len(titles) {
  205 + for j := 0; j < (len(titles) - len(data[i])); j++ {
  206 + data[i] = append(data[i], "")
  207 + }
  208 + }
  209 + }
  210 + for i := range cmd.Data {
  211 + row := make([]string, 0)
  212 + for _, filed := range titles {
  213 + if v, ok := cmd.Data[i][filed]; ok {
  214 + row = append(row, v)
  215 + } else {
  216 + row = append(row, "")
  217 + }
  218 + }
  219 + data = append(data, row)
  220 + if cmd.AppendTableDataFlag {
  221 + appendTableDataList = append(appendTableDataList, row)
  222 + }
  223 + }
  224 +
  225 + //if !cmd.AppendTableDataFlag {
  226 + // 上传文件
  227 + fileUpload, err := saveFile(cmd.Name, titles, data, nil)
  228 + if err != nil {
  229 + return nil, factory.FastError(err)
  230 + }
  231 + // 更新文件
  232 + file.FileInfo.Url = fileUpload.Url
  233 + file.FileInfo.FileSize = int(fileUpload.FileSize)
  234 + file.FileInfo.RowCount = len(data)
  235 + _, err = fileRepository.Save(file)
  236 + if err != nil {
  237 + return nil, factory.FastError(err)
  238 + }
  239 + //}
  240 + //else if cmd.AppendTableDataFlag && file.FileInfo.TableId != 0 { // 追加数据到应用表
  241 + //var table *domain.Table
  242 + //if _, table, err = factory.FastPgTable(transactionContext, file.FileInfo.TableId); err != nil {
  243 + // return nil, factory.FastError(err)
  244 + //}
  245 + //// 上传文件
  246 + //fileUpload, err := saveCsvFile(cmd.Name, titles, appendTableDataList, nil)
  247 + //if err != nil {
  248 + // return nil, factory.FastError(err)
  249 + //}
  250 + //appendDataToTableService, _ := domainService.NewAppendDataToTableService(transactionContext.(*pgTransaction.TransactionContext))
  251 + //var mappingFields = make([]*domain.MappingField, 0)
  252 + //for _, f := range cmd.Fields {
  253 + // mappingFields = append(mappingFields, &domain.MappingField{
  254 + // MainTableField: &domain.Field{Name: f.Name},
  255 + // VerifiedFileFieldName: f.Name,
  256 + // })
  257 + //}
  258 + //if _, err = appendDataToTableService.AppendDataDirectly(ctx, fileUpload.Url, table, mappingFields); err != nil {
  259 + // return nil, factory.FastError(err)
  260 + //}
  261 + //}
  262 +
  263 + if err := transactionContext.CommitTransaction(); err != nil {
  264 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  265 + }
  266 + return struct{}{}, nil
  267 +}
  268 +
  269 +func (fileService *FileService) AppTableAppendData(ctx *domain.Context, cmd *command.AppTableFileAppendDataCommand) (interface{}, error) {
  270 + transactionContext, err := factory.CreateTransactionContext(nil)
  271 + if err != nil {
  272 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  273 + }
  274 + if err := transactionContext.StartTransaction(); err != nil {
  275 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  276 + }
  277 + defer func() {
  278 + transactionContext.RollbackTransaction()
  279 + }()
  280 +
  281 + fileRepository, file, _ := factory.FastPgFile(transactionContext, 0)
  282 + file, err = fileRepository.FindOne(map[string]interface{}{"appKey": cmd.AppKey, "fileName": cmd.Name, "fileType": domain.SourceFile})
  283 + if err == domain.ErrorNotFound {
  284 + return nil, factory.FastError(errors.New("文件不存在"))
  285 + }
  286 + if err != nil {
  287 + return nil, factory.FastError(err)
  288 + }
  289 + if file.FileInfo.TableId == 0 {
  290 + return nil, factory.FastError(errors.New("表不存在"))
  291 + }
  292 + var (
  293 + appendTableDataList = make([][]string, 0)
  294 + titles = make([]string, 0)
  295 + table *domain.Table
  296 + )
  297 + _, table, err = factory.FastPgTable(transactionContext, file.FileInfo.TableId)
  298 + if err != nil {
  299 + return nil, factory.FastError(err)
  300 + }
  301 + for _, f := range table.Fields(false) {
  302 + titles = append(titles, f.Name)
  303 + }
  304 + for _, f := range cmd.Fields {
  305 + found := false
  306 + for _, column := range titles {
  307 + if column == f.Name {
  308 + found = true
  309 + break
  310 + }
  311 + }
  312 + if !found {
  313 + titles = append(titles, f.Name)
  314 + }
  315 + }
  316 + for i := range cmd.Data {
  317 + row := make([]string, 0)
  318 + for _, filed := range titles {
  319 + if v, ok := cmd.Data[i][filed]; ok {
  320 + row = append(row, v)
  321 + } else {
  322 + row = append(row, "")
  323 + }
  324 + }
  325 + appendTableDataList = append(appendTableDataList, row)
  326 + }
  327 +
  328 + // 上传文件
  329 + fileUpload, err := saveCsvFile(cmd.Name, titles, appendTableDataList, nil)
  330 + if err != nil {
  331 + return nil, factory.FastError(err)
  332 + }
  333 + appendDataToTableService, _ := domainService.NewAppendDataToTableService(transactionContext.(*pgTransaction.TransactionContext))
  334 + var mappingFields = make([]*domain.MappingField, 0)
  335 + for _, f := range cmd.Fields {
  336 + mappingFields = append(mappingFields, &domain.MappingField{
  337 + MainTableField: &domain.Field{Name: f.Name},
  338 + VerifiedFileFieldName: f.Name,
  339 + })
  340 + }
  341 + if _, err = appendDataToTableService.AppendDataDirectly(ctx, fileUpload.Url, table, mappingFields); err != nil {
  342 + return nil, factory.FastError(err)
  343 + }
  344 +
  345 + if err := transactionContext.CommitTransaction(); err != nil {
  346 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  347 + }
  348 + return struct{}{}, nil
  349 +}
  350 +
  351 +func (fileService *FileService) AppTableAppendDataDirect(ctx *domain.Context, cmd *command.AppTableFileAppendDataCommand) (interface{}, error) {
  352 + transactionContext, err := factory.CreateTransactionContext(nil)
  353 + if err != nil {
  354 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  355 + }
  356 + if err := transactionContext.StartTransaction(); err != nil {
  357 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  358 + }
  359 + defer func() {
  360 + transactionContext.RollbackTransaction()
  361 + }()
  362 +
  363 + fileRepository, file, _ := factory.FastPgFile(transactionContext, 0)
  364 + file, err = fileRepository.FindOne(map[string]interface{}{"appKey": cmd.AppKey, "fileName": cmd.Name, "fileType": domain.SourceFile})
  365 + if err == domain.ErrorNotFound {
  366 + return nil, factory.FastError(errors.New("文件不存在"))
  367 + }
  368 + if err != nil {
  369 + return nil, factory.FastError(err)
  370 + }
  371 + if file.FileInfo.TableId == 0 {
  372 + return nil, factory.FastError(errors.New("表不存在"))
  373 + }
  374 + var (
  375 + titles = make([]string, 0)
  376 + table *domain.Table
  377 + )
  378 + _, table, err = factory.FastPgTable(transactionContext, file.FileInfo.TableId)
  379 + if err != nil {
  380 + return nil, factory.FastError(err)
  381 + }
  382 + for _, f := range table.Fields(false) {
  383 + titles = append(titles, f.Name)
  384 + }
  385 + mapNameField := domain.Fields(table.Fields(false)).ToMap()
  386 + for _, f := range cmd.Fields {
  387 + found := false
  388 + for _, column := range titles {
  389 + if column == f.Name {
  390 + found = true
  391 + break
  392 + }
  393 + }
  394 + if !found {
  395 + titles = append(titles, f.Name)
  396 + }
  397 + }
  398 + var mapData = make([]map[string]string, 0)
  399 + for i := range cmd.Data {
  400 + mapItem := make(map[string]string)
  401 + for k, v := range cmd.Data[i] {
  402 + if f, ok := mapNameField[k]; ok {
  403 + mapItem[f.SQLName] = v
  404 + }
  405 + }
  406 + mapData = append(mapData, mapItem)
  407 + }
  408 + editDataService, _ := factory.CreateTableEditDataService(transactionContext)
  409 + _, err = editDataService.BatchAdd(ctx, domain.EditDataRequest{
  410 + TableId: table.TableId,
  411 + Table: table,
  412 + Where: domain.Where{},
  413 + UpdateList: nil,
  414 + AddList: domainService.MapArrayToFieldValues(mapData, table, nil, false),
  415 + RemoveList: nil,
  416 + IgnoreTableType: true,
  417 + })
  418 + if err != nil {
  419 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  420 + }
  421 +
  422 + if err := transactionContext.CommitTransaction(); err != nil {
  423 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  424 + }
  425 + return struct{}{}, nil
  426 +}
  427 +
  428 +func (fileService *FileService) AppTableFileList(ctx *domain.Context, cmd *query.ListAppTableFileCommand) (interface{}, error) {
  429 + return fileService.GetAppFile(ctx, cmd.AppKey, cmd.Name)
  430 +}
  431 +
  432 +func (fileService *FileService) UpdateAppTableFile(ctx *domain.Context, cmd *command.UpdateAppTableFileCommand) (interface{}, error) {
  433 + transactionContext, err := factory.CreateTransactionContext(nil)
  434 + if err != nil {
  435 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  436 + }
  437 + if err := transactionContext.StartTransaction(); err != nil {
  438 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  439 + }
  440 + defer func() {
  441 + transactionContext.RollbackTransaction()
  442 + }()
  443 +
  444 + fileRepository, file, _ := factory.FastPgFile(transactionContext, 0)
  445 + file, err = fileRepository.FindOne(map[string]interface{}{"appKey": cmd.AppKey, "fileName": cmd.Name, "fileType": domain.SourceFile})
  446 + if err == domain.ErrorNotFound {
  447 + return nil, factory.FastError(errors.New("文件不存在"))
  448 + }
  449 + if err != nil {
  450 + return nil, factory.FastError(err)
  451 + }
  452 + if len(cmd.AddFields) == 0 {
  453 + return nil, nil
  454 + }
  455 + tableRepository, table, _ := factory.FastPgTable(transactionContext, file.FileInfo.TableId)
  456 + if err == domain.ErrorNotFound {
  457 + return nil, factory.FastError(errors.New("文件表不存在"))
  458 + }
  459 + builder := domainService.NewDataFieldsBuilder()
  460 + for i, _ := range cmd.AddFields {
  461 + if _, ok := table.MatchField(cmd.AddFields[i]); ok {
  462 + return nil, factory.FastError(errors.New("字段已存在"))
  463 + }
  464 + }
  465 + for _, f := range cmd.AddFields {
  466 + dataField := builder.NewDataField(f.Name, f.SQLType, domain.MainTableField)
  467 + table.DataFields = append(table.DataFields, dataField)
  468 + if err = starrocks.AddTableColumn(starrocks.DB, table.SQLName, dataField); err != nil {
  469 + return nil, factory.FastError(err)
  470 + }
  471 + }
  472 +
  473 + if table, err = tableRepository.Save(table); err != nil {
  474 + return nil, factory.FastError(err)
  475 + }
  476 +
  477 + if err := transactionContext.CommitTransaction(); err != nil {
  478 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  479 + }
  480 + return struct{}{}, nil
  481 +}
1 package service 1 package service
2 2
3 import ( 3 import (
  4 + "bytes"
  5 + "fmt"
  6 + "github.com/beego/beego/v2/client/httplib"
4 "github.com/linmadan/egglib-go/core/application" 7 "github.com/linmadan/egglib-go/core/application"
  8 + "github.com/linmadan/egglib-go/transaction/pg"
5 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/factory" 9 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/factory"
6 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/file/command" 10 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/file/command"
  11 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/file/dto"
7 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain" 12 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
  13 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/domainService"
  14 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/excel"
  15 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/redis"
8 ) 16 )
9 17
10 // FilePreview 加载表格数据 18 // FilePreview 加载表格数据
@@ -33,10 +41,88 @@ func (fileService *FileService) FilePreview(ctx *domain.Context, loadDataTableCo @@ -33,10 +41,88 @@ func (fileService *FileService) FilePreview(ctx *domain.Context, loadDataTableCo
33 return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) 41 return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
34 } 42 }
35 43
36 - //return dto.NewDataTableDtoDemo(loadDataTableService.GetFileId()), nil  
37 return data, nil 44 return data, nil
38 } 45 }
39 46
  47 +func (fileService *FileService) ResetHeaderRow(ctx *domain.Context, loadDataTableCommand *command.ResetTableHeaderCommand) (interface{}, error) {
  48 + if err := loadDataTableCommand.ValidateCommand(); err != nil {
  49 + return nil, application.ThrowError(application.ARG_ERROR, err.Error())
  50 + }
  51 + transactionContext, err := factory.CreateTransactionContext(nil)
  52 + if err != nil {
  53 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  54 + }
  55 + if err := transactionContext.StartTransaction(); err != nil {
  56 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  57 + }
  58 + defer func() {
  59 + transactionContext.RollbackTransaction()
  60 + }()
  61 + cache := redis.NewFileCacheService()
  62 + temporaryFile, err := cache.Get(redis.KeyTemporaryFileInfo(loadDataTableCommand.FileId))
  63 + if err != nil {
  64 + return nil, factory.FastError(err)
  65 + }
  66 + loadDataTableService, _ := factory.CreateLoadDataTableService(transactionContext)
  67 + data, err := loadDataTableService.RePreview(ctx, loadDataTableCommand.FileId, temporaryFile.Fields, loadDataTableCommand.Where)
  68 + // 处理错误
  69 + level := domain.LevelInfo
  70 + errMsg := ""
  71 + if err != nil {
  72 + level = domain.LevelError
  73 + errMsg = err.Error()
  74 + }
  75 + if logErr := domainService.FastLog(transactionContext.(*pg.TransactionContext),
  76 + domain.VerifiedStepLog, temporaryFile.FileId, &domainService.ExcelTableResetHeaderLog{
  77 + LogEntry: domain.NewLogEntry(temporaryFile.FileName, domain.VerifiedFile.ToString(), domain.FileVerify,
  78 + ctx.WithValue(domain.ContextWithLogLevel, level).
  79 + WithValue(domain.ContextWithLogMsg, errMsg)),
  80 + HeaderRow: domain.GetHeaderRow(loadDataTableCommand.HeaderRow),
  81 + }); logErr != nil {
  82 + return nil, logErr
  83 + }
  84 + if err != nil {
  85 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  86 + }
  87 +
  88 + if err := transactionContext.CommitTransaction(); err != nil {
  89 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  90 + }
  91 +
  92 + return data, nil
  93 +}
  94 +
  95 +// PrepareTemporaryFile 准备临时文件
  96 +func (fileService *FileService) PrepareTemporaryFile(ctx *domain.Context, cmd *command.PrepareTemporaryFileCommand) (interface{}, error) {
  97 + if err := cmd.ValidateCommand(); err != nil {
  98 + return nil, application.ThrowError(application.ARG_ERROR, err.Error())
  99 + }
  100 + transactionContext, err := factory.CreateTransactionContext(nil)
  101 + if err != nil {
  102 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  103 + }
  104 + if err := transactionContext.StartTransaction(); err != nil {
  105 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  106 + }
  107 + defer func() {
  108 + transactionContext.RollbackTransaction()
  109 + }()
  110 +
  111 + loadDataTableService, _ := factory.CreateLoadDataTableService(transactionContext)
  112 + data, err := loadDataTableService.CreateTemporaryFile(ctx, cmd.FileId)
  113 + if err != nil {
  114 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  115 + }
  116 +
  117 + if err := transactionContext.CommitTransaction(); err != nil {
  118 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  119 + }
  120 +
  121 + fileDto := &dto.FileDto{}
  122 + fileDto.Load(data)
  123 + return fileDto, nil
  124 +}
  125 +
40 // EditDataTable 编辑表格数据 126 // EditDataTable 编辑表格数据
41 func (fileService *FileService) EditDataTable(ctx *domain.Context, editDataTableCommand *command.EditDataTableCommand) (interface{}, error) { 127 func (fileService *FileService) EditDataTable(ctx *domain.Context, editDataTableCommand *command.EditDataTableCommand) (interface{}, error) {
42 if err := editDataTableCommand.ValidateCommand(); err != nil { 128 if err := editDataTableCommand.ValidateCommand(); err != nil {
@@ -53,15 +139,47 @@ func (fileService *FileService) EditDataTable(ctx *domain.Context, editDataTable @@ -53,15 +139,47 @@ func (fileService *FileService) EditDataTable(ctx *domain.Context, editDataTable
53 transactionContext.RollbackTransaction() 139 transactionContext.RollbackTransaction()
54 }() 140 }()
55 141
  142 + cache := redis.NewFileCacheService()
  143 + temporaryFile, err := cache.Get(redis.KeyTemporaryFileInfo(editDataTableCommand.FileId))
  144 + if err != nil {
  145 + return nil, factory.FastError(err)
  146 + }
  147 + editDataTableCommand.Fields = temporaryFile.Fields
  148 + editDataTableCommand.ProcessFields = temporaryFile.MatchFields(editDataTableCommand.ProcessFieldNames)
  149 + if len(editDataTableCommand.ProcessFields) == 0 {
  150 + return nil, factory.FastError(fmt.Errorf("请至少选择一个数据列"))
  151 + }
  152 + if editDataTableCommand.Action == "remove-column" && len(temporaryFile.Fields) == len(editDataTableCommand.ProcessFields) {
  153 + return nil, factory.FastError(fmt.Errorf("请至少保留一个数据列"))
  154 + }
  155 + if editDataTableCommand.Action == "rename-column" {
  156 + targetColumn := editDataTableCommand.ProcessFieldNames[0]
  157 + newColumnName := editDataTableCommand.Params["newColumnName"].(string)
  158 + if len(temporaryFile.MatchFields([]string{newColumnName})) > 0 && newColumnName != targetColumn {
  159 + return nil, factory.FastError(fmt.Errorf("已存在相同名称,修改无效"))
  160 + }
  161 + }
  162 + // allowAction := func(fields []*domain.Field, action string) error {
  163 + // for _, f := range fields {
  164 + // if f.SQLType != string(domain.String) &&
  165 + // !(action == domain.RemoveColumn || action == domain.CopyColumn || action == domain.RenameColumn || action == domain.ConvertColumnType) {
  166 + // return fmt.Errorf("列【%v】必须先转字符串类型",f.Name)
  167 + // }
  168 + // }
  169 + // return nil
  170 + // }
  171 + // if err = allowAction(editDataTableCommand.ProcessFields, editDataTableCommand.Action); err != nil {
  172 + // return nil, factory.FastError(err)
  173 + // }
56 editDataTableService, _ := factory.CreateEditDataTableService(transactionContext) 174 editDataTableService, _ := factory.CreateEditDataTableService(transactionContext)
57 - _, err = editDataTableService.Edit(ctx, editDataTableCommand.EditTableRequest) 175 + response, err := editDataTableService.Edit(ctx, editDataTableCommand.EditTableRequest)
58 if err != nil { 176 if err != nil {
59 return nil, factory.FastError(err) 177 return nil, factory.FastError(err)
60 } 178 }
61 if err := transactionContext.CommitTransaction(); err != nil { 179 if err := transactionContext.CommitTransaction(); err != nil {
62 return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) 180 return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
63 } 181 }
64 - return struct{}{}, nil 182 + return (&dto.EditDataTableDto{}).Load(response), nil
65 } 183 }
66 184
67 // FlushDataTable 持久化表格数据 185 // FlushDataTable 持久化表格数据
@@ -80,16 +198,19 @@ func (fileService *FileService) FlushDataTable(ctx *domain.Context, flushDataTab @@ -80,16 +198,19 @@ func (fileService *FileService) FlushDataTable(ctx *domain.Context, flushDataTab
80 transactionContext.RollbackTransaction() 198 transactionContext.RollbackTransaction()
81 }() 199 }()
82 flushDataTableService, _ := factory.CreateFlushDataTableService(transactionContext) 200 flushDataTableService, _ := factory.CreateFlushDataTableService(transactionContext)
83 - fields := make([]*domain.Field, 0)  
84 - for _, f := range flushDataTableCommand.DataFields {  
85 - fields = append(fields, &domain.Field{  
86 - Name: f.Name,  
87 - SQLType: f.SQLType,  
88 - })  
89 - }  
90 - if _, err := flushDataTableService.Flush(ctx, flushDataTableCommand.FileId, &domain.Table{  
91 - DataFields: fields,  
92 - RowCount: flushDataTableCommand.RowCount, 201 + cache := redis.NewFileCacheService()
  202 + temporaryFile, err := cache.Get(redis.KeyTemporaryFileInfo(flushDataTableCommand.ObjectId))
  203 + if err != nil {
  204 + return nil, factory.FastError(err)
  205 + }
  206 + if err = temporaryFile.Valid(); err != nil {
  207 + return nil, factory.FastError(err)
  208 + }
  209 +
  210 + if _, err := flushDataTableService.Flush(ctx, flushDataTableCommand.ObjectId, &domain.Table{
  211 + DataFields: temporaryFile.Fields,
  212 + RowCount: temporaryFile.Total,
  213 + HeaderRow: temporaryFile.HeaderRow,
93 }); err != nil { 214 }); err != nil {
94 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error()) 215 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
95 } 216 }
@@ -131,6 +252,9 @@ func (fileService *FileService) AppendDataToTable(ctx *domain.Context, cmd *comm @@ -131,6 +252,9 @@ func (fileService *FileService) AppendDataToTable(ctx *domain.Context, cmd *comm
131 if err := cmd.ValidateCommand(); err != nil { 252 if err := cmd.ValidateCommand(); err != nil {
132 return nil, application.ThrowError(application.ARG_ERROR, err.Error()) 253 return nil, application.ThrowError(application.ARG_ERROR, err.Error())
133 } 254 }
  255 + if len(cmd.MappingFields) == 0 {
  256 + return nil, factory.FastError(fmt.Errorf("请选择对应字段"))
  257 + }
134 transactionContext, err := factory.CreateTransactionContext(nil) 258 transactionContext, err := factory.CreateTransactionContext(nil)
135 if err != nil { 259 if err != nil {
136 return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) 260 return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
@@ -152,3 +276,85 @@ func (fileService *FileService) AppendDataToTable(ctx *domain.Context, cmd *comm @@ -152,3 +276,85 @@ func (fileService *FileService) AppendDataToTable(ctx *domain.Context, cmd *comm
152 } 276 }
153 return result, nil 277 return result, nil
154 } 278 }
  279 +
  280 +// AppendDataToTablePreflightCheck 追加数据预查
  281 +func (fileService *FileService) AppendDataToTablePreflightCheck(ctx *domain.Context, cmd *command.AppendDataToTableCommand) (interface{}, error) {
  282 + if err := cmd.ValidateCommand(); err != nil {
  283 + return nil, application.ThrowError(application.ARG_ERROR, err.Error())
  284 + }
  285 + transactionContext, err := factory.CreateTransactionContext(nil)
  286 + if err != nil {
  287 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  288 + }
  289 + if err := transactionContext.StartTransaction(); err != nil {
  290 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  291 + }
  292 + defer func() {
  293 + transactionContext.RollbackTransaction()
  294 + }()
  295 +
  296 + generateMainTableService, _ := factory.CreateAppendDataToTableService(transactionContext)
  297 + result, err := generateMainTableService.PreflightCheck(ctx, cmd.FileId, cmd.TableId, cmd.MappingFields)
  298 + if err != nil {
  299 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  300 + }
  301 + if err := transactionContext.CommitTransaction(); err != nil {
  302 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  303 + }
  304 + return result, nil
  305 +}
  306 +
  307 +// ExportFile 文件下载
  308 +func (fileService *FileService) ExportFile(ctx *domain.Context, cmd *command.ExportFileCommand) (interface{}, error) {
  309 + if err := cmd.ValidateCommand(); err != nil {
  310 + return nil, application.ThrowError(application.ARG_ERROR, err.Error())
  311 + }
  312 + transactionContext, err := factory.CreateTransactionContext(nil)
  313 + if err != nil {
  314 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  315 + }
  316 + if err := transactionContext.StartTransaction(); err != nil {
  317 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  318 + }
  319 + defer func() {
  320 + transactionContext.RollbackTransaction()
  321 + }()
  322 +
  323 + _, file, err := factory.FastPgFile(transactionContext, cmd.FileId)
  324 + if err != nil {
  325 + return nil, factory.FastError(err)
  326 + }
  327 +
  328 + var response = FileUpload{}
  329 + if file.FileType == domain.SourceFile.ToString() {
  330 + response.Url = file.FileInfo.Url
  331 + response.Ext = domain.XLSX
  332 + response.FileName = file.FileInfo.Name
  333 + return response, nil
  334 + }
  335 + _, table, err := factory.FastPgTable(transactionContext, file.FileInfo.TableId)
  336 + if err != nil {
  337 + return nil, factory.FastError(err)
  338 + }
  339 +
  340 + f, err := httplib.Get(domain.ConvertFileUrlToInternal(file.FileInfo.Url)).Bytes()
  341 + if err != nil {
  342 + return nil, factory.FastError(err)
  343 + }
  344 + reader := bytes.NewReader(f)
  345 + var importer *excel.Importer = excel.NewExcelImportByFile(file.FileInfo.Ext)
  346 + data, err := importer.OpenExcelFromIoReader(reader)
  347 + if err != nil {
  348 + return nil, factory.FastError(err)
  349 + }
  350 +
  351 + response, err = saveFile(file.FileInfo.Name, importer.Reader().Header().Columns, data, domain.MakeToInterfaces(table.DataFields))
  352 + if err != nil {
  353 + return nil, factory.FastError(err)
  354 + }
  355 +
  356 + if err := transactionContext.CommitTransaction(); err != nil {
  357 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  358 + }
  359 + return response, nil
  360 +}
@@ -2,6 +2,14 @@ package service @@ -2,6 +2,14 @@ package service
2 2
3 import ( 3 import (
4 "fmt" 4 "fmt"
  5 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/constant"
  6 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/api/authlib"
  7 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/api/bytelib"
  8 + "path/filepath"
  9 + "sort"
  10 + "strings"
  11 + "time"
  12 +
5 "github.com/linmadan/egglib-go/core/application" 13 "github.com/linmadan/egglib-go/core/application"
6 "github.com/linmadan/egglib-go/utils/tool_funs" 14 "github.com/linmadan/egglib-go/utils/tool_funs"
7 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/factory" 15 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/factory"
@@ -9,19 +17,16 @@ import ( @@ -9,19 +17,16 @@ import (
9 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/file/dto" 17 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/file/dto"
10 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/file/query" 18 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/file/query"
11 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain" 19 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
12 - "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain/bytecore"  
13 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/domainService" 20 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/domainService"
14 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/utils" 21 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/utils"
15 - "path/filepath"  
16 - "time"  
17 ) 22 )
18 23
19 -// 文件服务 24 +// FileService 文件服务
20 type FileService struct { 25 type FileService struct {
21 } 26 }
22 27
23 -// 创建文件服务  
24 -func (fileService *FileService) CreateFile(ctx *domain.Context, createFileCommand *command.CreateFileCommand) (interface{}, error) { 28 +// CreateFile 创建文件服务
  29 +func (fileService *FileService) CreateFile(ctx *domain.Context, createFileCommand *command.CreateFileCommand) (*domain.File, error) {
25 if err := createFileCommand.ValidateCommand(); err != nil { 30 if err := createFileCommand.ValidateCommand(); err != nil {
26 return nil, application.ThrowError(application.ARG_ERROR, err.Error()) 31 return nil, application.ThrowError(application.ARG_ERROR, err.Error())
27 } 32 }
@@ -35,25 +40,81 @@ func (fileService *FileService) CreateFile(ctx *domain.Context, createFileComman @@ -35,25 +40,81 @@ func (fileService *FileService) CreateFile(ctx *domain.Context, createFileComman
35 defer func() { 40 defer func() {
36 transactionContext.RollbackTransaction() 41 transactionContext.RollbackTransaction()
37 }() 42 }()
  43 + fileInfo := &domain.FileInfo{
  44 + Name: domain.FileName(createFileCommand.Name),
  45 + Url: createFileCommand.Url,
  46 + FileSize: createFileCommand.FileSize,
  47 + Ext: filepath.Ext(createFileCommand.Name),
  48 + }
38 newFile := &domain.File{ 49 newFile := &domain.File{
39 - FileType: domain.SourceFile.ToString(),  
40 - FileInfo: &domain.FileInfo{  
41 - Name: domain.FileName(createFileCommand.Name),  
42 - Url: createFileCommand.Url,  
43 - FileSize: createFileCommand.FileSize,  
44 - Ext: filepath.Ext(createFileCommand.Name),  
45 - }, 50 + FileType: domain.SourceFile.ToString(),
  51 + FileInfo: fileInfo,
46 SourceFileId: 0, 52 SourceFileId: 0,
47 //Operator: "", 53 //Operator: "",
48 CreatedAt: time.Now(), 54 CreatedAt: time.Now(),
49 UpdatedAt: time.Now(), 55 UpdatedAt: time.Now(),
50 Context: ctx, 56 Context: ctx,
  57 + FileFrom: createFileCommand.FileFrom,
  58 + AppKey: createFileCommand.AppKey,
51 } 59 }
52 fileRepository, _, _ := factory.FastPgFile(transactionContext, 0) 60 fileRepository, _, _ := factory.FastPgFile(transactionContext, 0)
  61 +
  62 + // 文件名相同,进行替换
  63 + if oldFile, findOldFileErr := fileRepository.FindOne(map[string]interface{}{
  64 + "context": ctx,
  65 + "fileName": fileInfo.Name,
  66 + "fileType": domain.SourceFile.ToString(),
  67 + }); oldFile != nil && findOldFileErr == nil {
  68 + oldFile.FileInfo = fileInfo
  69 + oldFile.UpdatedAt = time.Now()
  70 + newFile = oldFile
  71 +
  72 + if err = factory.FastLog(transactionContext, domain.CommonLog, oldFile.FileId, &domainService.FileReplaceLog{
  73 + LogEntry: domain.NewLogEntry(oldFile.FileInfo.Name, domain.SourceFile.ToString(), domain.FileUpload, ctx),
  74 + }); err != nil {
  75 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  76 + }
  77 + }
  78 +
53 file, err := fileRepository.Save(newFile) 79 file, err := fileRepository.Save(newFile)
54 if err != nil { 80 if err != nil {
55 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error()) 81 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
56 } 82 }
  83 + // 同时生成主表
  84 + // 前置需要进行预览、保持文件,才能生成主表
  85 + if createFileCommand.GenerateTableFlag {
  86 + table := domainService.NewTable(domain.MainTable, fileInfo.Name, createFileCommand.Fields, 0).
  87 + WithPrefix(domain.MainTable.ToString()).WithContext(&domain.Context{})
  88 + tableRepository, _, _ := factory.FastPgTable(transactionContext, 0)
  89 + if table, err = tableRepository.Save(table); err != nil {
  90 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  91 + }
  92 + domainService.ByteCore.LoadDataTable(domain.ReqLoadDataTable{
  93 + FileId: file.FileId,
  94 + FileName: file.FileInfo.Name,
  95 + Url: file.FileInfo.Url,
  96 + Ext: file.FileInfo.Ext,
  97 + //Where: where,
  98 + OriginalTableId: fmt.Sprintf("%v", file.FileId),
  99 + IsFromOriginalTable: true,
  100 + TableFileUrl: file.FileInfo.Url,
  101 + ColumnSchemas: bytelib.DomainFieldsToColumnSchemas(table.Fields(false)),
  102 + SortParameters: make(map[string]interface{}),
  103 + })
  104 + response, err := domainService.ByteCore.SaveTable(domain.ReqSaveTable{FileId: file.FileId, Table: table})
  105 + if err != nil {
  106 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  107 + }
  108 + if _, err = domainService.ByteCore.GenerateTable(ctx, domain.ReqGenerateTable{
  109 + file.FileId, response.Url, table,
  110 + }); err != nil {
  111 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  112 + }
  113 + file.FileInfo.TableId = table.TableId
  114 + if file, err = fileRepository.Save(file); err != nil {
  115 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  116 + }
  117 + }
57 if err = factory.FastLog(transactionContext, domain.CommonLog, file.FileId, &domainService.FileUploadSuccessLog{ 118 if err = factory.FastLog(transactionContext, domain.CommonLog, file.FileId, &domainService.FileUploadSuccessLog{
58 LogEntry: domain.NewLogEntry(file.FileInfo.Name, domain.SourceFile.ToString(), domain.FileUpload, ctx), 119 LogEntry: domain.NewLogEntry(file.FileInfo.Name, domain.SourceFile.ToString(), domain.FileUpload, ctx),
59 }); err != nil { 120 }); err != nil {
@@ -62,11 +123,11 @@ func (fileService *FileService) CreateFile(ctx *domain.Context, createFileComman @@ -62,11 +123,11 @@ func (fileService *FileService) CreateFile(ctx *domain.Context, createFileComman
62 if err := transactionContext.CommitTransaction(); err != nil { 123 if err := transactionContext.CommitTransaction(); err != nil {
63 return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) 124 return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
64 } 125 }
65 - return struct{}{}, nil 126 + return file, nil
66 } 127 }
67 128
68 -// 返回文件服务  
69 -func (fileService *FileService) GetFile(getFileQuery *query.GetFileQuery) (interface{}, error) { 129 +// GetFile 返回文件服务
  130 +func (fileService *FileService) GetFile(ctx *domain.Context, getFileQuery *query.GetFileQuery) (interface{}, error) {
70 if err := getFileQuery.ValidateQuery(); err != nil { 131 if err := getFileQuery.ValidateQuery(); err != nil {
71 return nil, application.ThrowError(application.ARG_ERROR, err.Error()) 132 return nil, application.ThrowError(application.ARG_ERROR, err.Error())
72 } 133 }
@@ -88,21 +149,35 @@ func (fileService *FileService) GetFile(getFileQuery *query.GetFileQuery) (inter @@ -88,21 +149,35 @@ func (fileService *FileService) GetFile(getFileQuery *query.GetFileQuery) (inter
88 } else { 149 } else {
89 fileRepository = value 150 fileRepository = value
90 } 151 }
91 - file, err := fileRepository.FindOne(map[string]interface{}{"fileId": getFileQuery.FileId})  
92 - if err != nil {  
93 - return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error()) 152 + response := map[string]interface{}{
  153 + "file": nil,
94 } 154 }
95 - if file == nil {  
96 - return nil, application.ThrowError(application.RES_NO_FIND_ERROR, fmt.Sprintf("%s", string(getFileQuery.FileId)))  
97 - } else {  
98 - if err := transactionContext.CommitTransaction(); err != nil {  
99 - return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())  
100 - }  
101 - return file, nil 155 + options := map[string]interface{}{"context": ctx}
  156 + if getFileQuery.FileId > 0 {
  157 + options["fileId"] = getFileQuery.FileId
  158 + }
  159 + if len(getFileQuery.FileName) > 0 {
  160 + options["fileName"] = domain.FileName(getFileQuery.FileName)
  161 + }
  162 + if len(getFileQuery.FileType) > 0 {
  163 + options["fileType"] = getFileQuery.FileType
102 } 164 }
  165 + // 未传递参数
  166 + if len(options) == 1 {
  167 + return response, nil
  168 + }
  169 + file, _ := fileRepository.FindOne(options)
  170 + //if err != nil {
  171 + // return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  172 + //}
  173 + if err := transactionContext.CommitTransaction(); err != nil {
  174 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  175 + }
  176 + response["file"] = (&dto.FileDto{}).Load(file)
  177 + return response, nil
103 } 178 }
104 179
105 -// 返回文件服务列表 180 +// ListFile 返回文件服务列表
106 func (fileService *FileService) ListFile(listFileQuery *query.ListFileQuery) (interface{}, error) { 181 func (fileService *FileService) ListFile(listFileQuery *query.ListFileQuery) (interface{}, error) {
107 if err := listFileQuery.ValidateQuery(); err != nil { 182 if err := listFileQuery.ValidateQuery(); err != nil {
108 return nil, application.ThrowError(application.ARG_ERROR, err.Error()) 183 return nil, application.ThrowError(application.ARG_ERROR, err.Error())
@@ -180,8 +255,131 @@ func (fileService *FileService) SearchFile(listFileQuery *query.SearchFileQuery) @@ -180,8 +255,131 @@ func (fileService *FileService) SearchFile(listFileQuery *query.SearchFileQuery)
180 }, nil 255 }, nil
181 } 256 }
182 257
183 -// 移除文件服务  
184 -func (fileService *FileService) RemoveFile(removeFileCommand *command.RemoveFileCommand) (interface{}, error) { 258 +// SearchAppFile 返回文件服务列表
  259 +func (fileService *FileService) SearchAppFile(ctx *domain.Context, listFileQuery *query.SearchFileQuery) (interface{}, error) {
  260 + if err := listFileQuery.ValidateQuery(); err != nil {
  261 + return nil, application.ThrowError(application.ARG_ERROR, err.Error())
  262 + }
  263 + transactionContext, err := factory.CreateTransactionContext(nil)
  264 + if err != nil {
  265 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  266 + }
  267 + if err := transactionContext.StartTransaction(); err != nil {
  268 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  269 + }
  270 + defer func() {
  271 + transactionContext.RollbackTransaction()
  272 + }()
  273 + var fileRepository, _, _ = factory.FastPgFile(transactionContext, 0)
  274 +
  275 + apiAuthLib := authlib.NewApiAuthLib(constant.AUTH_SERVER_HOST).WithToken(ctx.AccessToken)
  276 + response, err := apiAuthLib.MeAppInfo(authlib.RequestUserMeQuery{UserId: ctx.TenantId})
  277 + if err != nil {
  278 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  279 + }
  280 + inAppKeys := make([]string, 0)
  281 + for _, app := range response.Apps {
  282 + inAppKeys = append(inAppKeys, app.AppKey)
  283 + }
  284 + var (
  285 + fileDtos = make([]*dto.FileDto, 0)
  286 + total int64
  287 + )
  288 + if len(inAppKeys) > 0 {
  289 + queryOptions := utils.ObjectToMap(listFileQuery)
  290 + queryOptions["inAppKeys"] = inAppKeys
  291 + queryOptions["limit"] = 1000
  292 + queryOptions["fileName"] = listFileQuery.FileName
  293 + count, files, err := fileRepository.Find(queryOptions)
  294 + if err != nil {
  295 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  296 + }
  297 + for _, file := range files {
  298 + var item = &dto.FileDto{}
  299 + item.Load(file)
  300 + fileDtos = append(fileDtos, item)
  301 + }
  302 + total = count
  303 + }
  304 + var apps = make([]*dto.AppDto, 0)
  305 + for _, app := range response.Apps {
  306 + if len(listFileQuery.FileName) > 0 && !strings.Contains(app.AppName, listFileQuery.FileName) {
  307 + continue
  308 + }
  309 + files := make([]*dto.FileDto, 0)
  310 + for _, file := range fileDtos {
  311 + if file.AppKey == app.AppKey {
  312 + files = append(files, file)
  313 + }
  314 + }
  315 + sort.SliceStable(files, func(i, j int) bool {
  316 + return files[i].Name < files[j].Name
  317 + })
  318 + apps = append(apps, &dto.AppDto{
  319 + AppId: app.AppId,
  320 + AppKey: app.AppKey,
  321 + AppName: app.AppName,
  322 + Files: files,
  323 + })
  324 + }
  325 +
  326 + if err := transactionContext.CommitTransaction(); err != nil {
  327 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  328 + }
  329 + return map[string]interface{}{
  330 + "apps": apps,
  331 + "count": total,
  332 + }, nil
  333 +}
  334 +
  335 +// GetAppFile 返回应用对应的文件服务列表
  336 +func (fileService *FileService) GetAppFile(ctx *domain.Context, appKey string, fileName string) (interface{}, error) {
  337 + transactionContext, err := factory.CreateTransactionContext(nil)
  338 + if err != nil {
  339 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  340 + }
  341 + if err := transactionContext.StartTransaction(); err != nil {
  342 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  343 + }
  344 + defer func() {
  345 + transactionContext.RollbackTransaction()
  346 + }()
  347 + var fileRepository, _, _ = factory.FastPgFile(transactionContext, 0)
  348 +
  349 + var (
  350 + fileDtos = make([]*dto.FileDto, 0)
  351 + total int64
  352 + )
  353 +
  354 + queryOptions := make(map[string]interface{})
  355 + queryOptions["fileType"] = domain.SourceFile
  356 + queryOptions["inAppKeys"] = []string{appKey}
  357 + queryOptions["limit"] = 100
  358 + count, files, err := fileRepository.Find(queryOptions)
  359 + if err != nil {
  360 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  361 + }
  362 + for _, file := range files {
  363 + var item = &dto.FileDto{}
  364 + if fileName != "" && file.FileInfo.Name != fileName {
  365 + continue
  366 + }
  367 + item.Load(file)
  368 + fileDtos = append(fileDtos, item)
  369 + }
  370 + total = count
  371 +
  372 + if err := transactionContext.CommitTransaction(); err != nil {
  373 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  374 + }
  375 + return map[string]interface{}{
  376 + "count": total,
  377 + "files": fileDtos,
  378 + }, nil
  379 +}
  380 +
  381 +// RemoveFile 移除文件服务
  382 +func (fileService *FileService) RemoveFile(ctx *domain.Context, removeFileCommand *command.RemoveFileCommand) (interface{}, error) {
185 if err := removeFileCommand.ValidateCommand(); err != nil { 383 if err := removeFileCommand.ValidateCommand(); err != nil {
186 return nil, application.ThrowError(application.ARG_ERROR, err.Error()) 384 return nil, application.ThrowError(application.ARG_ERROR, err.Error())
187 } 385 }
@@ -208,10 +406,10 @@ func (fileService *FileService) RemoveFile(removeFileCommand *command.RemoveFile @@ -208,10 +406,10 @@ func (fileService *FileService) RemoveFile(removeFileCommand *command.RemoveFile
208 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error()) 406 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
209 } 407 }
210 if file == nil { 408 if file == nil {
211 - return nil, application.ThrowError(application.RES_NO_FIND_ERROR, fmt.Sprintf("%s", string(removeFileCommand.FileId))) 409 + return nil, application.ThrowError(application.RES_NO_FIND_ERROR, fmt.Sprintf("%d", removeFileCommand.FileId))
212 } 410 }
213 deleteFileService, _ := factory.CreateDeleteFileService(transactionContext) 411 deleteFileService, _ := factory.CreateDeleteFileService(transactionContext)
214 - err = deleteFileService.DeleteFiles(nil, file) 412 + err = deleteFileService.DeleteFiles(ctx, file)
215 if err != nil { 413 if err != nil {
216 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error()) 414 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
217 } 415 }
@@ -221,7 +419,7 @@ func (fileService *FileService) RemoveFile(removeFileCommand *command.RemoveFile @@ -221,7 +419,7 @@ func (fileService *FileService) RemoveFile(removeFileCommand *command.RemoveFile
221 return struct{}{}, nil 419 return struct{}{}, nil
222 } 420 }
223 421
224 -// 更新文件服务 422 +// UpdateFile 更新文件服务
225 func (fileService *FileService) UpdateFile(updateFileCommand *command.UpdateFileCommand) (interface{}, error) { 423 func (fileService *FileService) UpdateFile(updateFileCommand *command.UpdateFileCommand) (interface{}, error) {
226 if err := updateFileCommand.ValidateCommand(); err != nil { 424 if err := updateFileCommand.ValidateCommand(); err != nil {
227 return nil, application.ThrowError(application.ARG_ERROR, err.Error()) 425 return nil, application.ThrowError(application.ARG_ERROR, err.Error())
@@ -249,7 +447,7 @@ func (fileService *FileService) UpdateFile(updateFileCommand *command.UpdateFile @@ -249,7 +447,7 @@ func (fileService *FileService) UpdateFile(updateFileCommand *command.UpdateFile
249 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error()) 447 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
250 } 448 }
251 if file == nil { 449 if file == nil {
252 - return nil, application.ThrowError(application.RES_NO_FIND_ERROR, fmt.Sprintf("%s", string(updateFileCommand.FileId))) 450 + return nil, application.ThrowError(application.RES_NO_FIND_ERROR, fmt.Sprintf("%d", updateFileCommand.FileId))
253 } 451 }
254 if err := file.Update(tool_funs.SimpleStructToMap(updateFileCommand)); err != nil { 452 if err := file.Update(tool_funs.SimpleStructToMap(updateFileCommand)); err != nil {
255 return nil, application.ThrowError(application.BUSINESS_ERROR, err.Error()) 453 return nil, application.ThrowError(application.BUSINESS_ERROR, err.Error())
@@ -264,7 +462,7 @@ func (fileService *FileService) UpdateFile(updateFileCommand *command.UpdateFile @@ -264,7 +462,7 @@ func (fileService *FileService) UpdateFile(updateFileCommand *command.UpdateFile
264 } 462 }
265 } 463 }
266 464
267 -// 取消校验中的文件 465 +// CancelVerifyingFile 取消校验中的文件
268 func (fileService *FileService) CancelVerifyingFile(ctx *domain.Context, cmd *command.CancelVerifyingFileCommand) (interface{}, error) { 466 func (fileService *FileService) CancelVerifyingFile(ctx *domain.Context, cmd *command.CancelVerifyingFileCommand) (interface{}, error) {
269 if err := cmd.ValidateCommand(); err != nil { 467 if err := cmd.ValidateCommand(); err != nil {
270 return nil, application.ThrowError(application.ARG_ERROR, err.Error()) 468 return nil, application.ThrowError(application.ARG_ERROR, err.Error())
@@ -295,7 +493,7 @@ func (fileService *FileService) CancelVerifyingFile(ctx *domain.Context, cmd *co @@ -295,7 +493,7 @@ func (fileService *FileService) CancelVerifyingFile(ctx *domain.Context, cmd *co
295 } 493 }
296 494
297 byteCore, _ := factory.CreateByteCoreService(transactionContext) 495 byteCore, _ := factory.CreateByteCoreService(transactionContext)
298 - _, err = byteCore.CancelFile(bytecore.ReqCancelFile{}) 496 + _, err = byteCore.CancelFile(domain.ReqCancelFile{})
299 if err != nil { 497 if err != nil {
300 return nil, factory.FastError(err) 498 return nil, factory.FastError(err)
301 } 499 }
@@ -306,6 +504,40 @@ func (fileService *FileService) CancelVerifyingFile(ctx *domain.Context, cmd *co @@ -306,6 +504,40 @@ func (fileService *FileService) CancelVerifyingFile(ctx *domain.Context, cmd *co
306 return struct{}{}, nil 504 return struct{}{}, nil
307 } 505 }
308 506
  507 +// CheckFileVerifyStatus 检查文件校验状态
  508 +func (fileService *FileService) CheckFileVerifyStatus(ctx *domain.Context, cmd *command.CheckFileVerifyStatusCommand) (interface{}, error) {
  509 + if err := cmd.ValidateCommand(); err != nil {
  510 + return nil, application.ThrowError(application.ARG_ERROR, err.Error())
  511 + }
  512 + transactionContext, err := factory.CreateTransactionContext(nil)
  513 + if err != nil {
  514 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  515 + }
  516 + if err := transactionContext.StartTransaction(); err != nil {
  517 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  518 + }
  519 + defer func() {
  520 + transactionContext.RollbackTransaction()
  521 + }()
  522 +
  523 + fileRepository, file, err := factory.FastPgFile(transactionContext, cmd.FileId)
  524 + if err != nil {
  525 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  526 + }
  527 + var res = struct {
  528 + ExistVerifyFile bool `json:"existVerifyFile"`
  529 + }{}
  530 + _, verifyFiles, findErr := fileRepository.Find(map[string]interface{}{"context": ctx, "fileType": domain.VerifiedFile.ToString(), "sourceFileId": file.SourceFileId})
  531 + if findErr == nil && len(verifyFiles) > 0 {
  532 + res.ExistVerifyFile = true
  533 + }
  534 +
  535 + if err := transactionContext.CommitTransaction(); err != nil {
  536 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  537 + }
  538 + return res, nil
  539 +}
  540 +
309 func NewFileService(options map[string]interface{}) *FileService { 541 func NewFileService(options map[string]interface{}) *FileService {
310 newFileService := &FileService{} 542 newFileService := &FileService{}
311 return newFileService 543 return newFileService
@@ -2,11 +2,12 @@ package command @@ -2,11 +2,12 @@ package command
2 2
3 import ( 3 import (
4 "fmt" 4 "fmt"
5 - "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"  
6 "reflect" 5 "reflect"
7 "strings" 6 "strings"
8 "time" 7 "time"
9 8
  9 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
  10 +
10 "github.com/beego/beego/v2/core/validation" 11 "github.com/beego/beego/v2/core/validation"
11 ) 12 )
12 13
@@ -23,6 +24,8 @@ type SearchLogCommand struct { @@ -23,6 +24,8 @@ type SearchLogCommand struct {
23 PageNumber int `cname:"页码" json:"pageNumber,omitempty"` 24 PageNumber int `cname:"页码" json:"pageNumber,omitempty"`
24 // 页数 25 // 页数
25 PageSize int `cname:"页数" json:"pageSize,omitempty"` 26 PageSize int `cname:"页数" json:"pageSize,omitempty"`
  27 + // 对象名称
  28 + ObjectName string `cname:"页数" json:"objectName,omitempty"`
26 29
27 Year int `cname:"年" json:"year,omitempty"` 30 Year int `cname:"年" json:"year,omitempty"`
28 Month int `cname:"月" json:"month,omitempty"` 31 Month int `cname:"月" json:"month,omitempty"`
@@ -31,8 +34,9 @@ type SearchLogCommand struct { @@ -31,8 +34,9 @@ type SearchLogCommand struct {
31 BeginTime time.Time `cname:"开始时间" json:"beginTime"` 34 BeginTime time.Time `cname:"开始时间" json:"beginTime"`
32 // 结束时间 35 // 结束时间
33 EndTime time.Time `cname:"结束时间" json:"endTime"` 36 EndTime time.Time `cname:"结束时间" json:"endTime"`
34 -  
35 - Context *domain.Context 37 + // 按log_id 排序
  38 + SortByLogId string `json:"sortByLogId"`
  39 + Context *domain.Context
36 } 40 }
37 41
38 func (cmd *SearchLogCommand) Valid(validation *validation.Validation) { 42 func (cmd *SearchLogCommand) Valid(validation *validation.Validation) {
@@ -46,7 +50,10 @@ func (cmd *SearchLogCommand) Valid(validation *validation.Validation) { @@ -46,7 +50,10 @@ func (cmd *SearchLogCommand) Valid(validation *validation.Validation) {
46 } 50 }
47 if cmd.Year > 0 && cmd.Month > 0 && cmd.Day > 0 { 51 if cmd.Year > 0 && cmd.Month > 0 && cmd.Day > 0 {
48 cmd.BeginTime = time.Date(cmd.Year, time.Month(cmd.Month), cmd.Day, 0, 0, 0, 0, time.Local) 52 cmd.BeginTime = time.Date(cmd.Year, time.Month(cmd.Month), cmd.Day, 0, 0, 0, 0, time.Local)
49 - cmd.EndTime = cmd.BeginTime.AddDate(0, 0, cmd.Day) 53 + cmd.EndTime = cmd.BeginTime.AddDate(0, 0, 1)
  54 + }
  55 + if cmd.PageNumber == 0 {
  56 + cmd.PageNumber = 1
50 } 57 }
51 } 58 }
52 59
@@ -21,6 +21,10 @@ type VerifiedStepLogDto struct { @@ -21,6 +21,10 @@ type VerifiedStepLogDto struct {
21 //OperatorName string `json:"operatorName"` 21 //OperatorName string `json:"operatorName"`
22 // 创建时间 22 // 创建时间
23 CreatedAt string `json:"createdAt"` 23 CreatedAt string `json:"createdAt"`
  24 + // 错误级别
  25 + Level string `json:"level"`
  26 + // 错误信息
  27 + Error string `json:"error"`
24 } 28 }
25 29
26 func (d *VerifiedStepLogDto) Load(m *domain.Log) { 30 func (d *VerifiedStepLogDto) Load(m *domain.Log) {
@@ -32,4 +36,9 @@ func (d *VerifiedStepLogDto) Load(m *domain.Log) { @@ -32,4 +36,9 @@ func (d *VerifiedStepLogDto) Load(m *domain.Log) {
32 d.Content = m.Content 36 d.Content = m.Content
33 //d.OperatorName = m.OperatorName 37 //d.OperatorName = m.OperatorName
34 d.CreatedAt = m.CreatedAt.Local().Format("2006-01-02 15:04:05") 38 d.CreatedAt = m.CreatedAt.Local().Format("2006-01-02 15:04:05")
  39 + d.Level = m.Entry.Level
  40 + d.Error = m.Entry.Error
  41 + if len(d.Level) == 0 {
  42 + d.Level = domain.LevelInfo.ToString()
  43 + }
35 } 44 }
@@ -12,11 +12,9 @@ import ( @@ -12,11 +12,9 @@ import (
12 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/utils" 12 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/utils"
13 ) 13 )
14 14
15 -// 日志服务  
16 type LogService struct { 15 type LogService struct {
17 } 16 }
18 17
19 -// 创建日志服务  
20 func (logService *LogService) CreateLog(createLogCommand *command.CreateLogCommand) (interface{}, error) { 18 func (logService *LogService) CreateLog(createLogCommand *command.CreateLogCommand) (interface{}, error) {
21 if err := createLogCommand.ValidateCommand(); err != nil { 19 if err := createLogCommand.ValidateCommand(); err != nil {
22 return nil, application.ThrowError(application.ARG_ERROR, err.Error()) 20 return nil, application.ThrowError(application.ARG_ERROR, err.Error())
@@ -56,7 +54,6 @@ func (logService *LogService) CreateLog(createLogCommand *command.CreateLogComma @@ -56,7 +54,6 @@ func (logService *LogService) CreateLog(createLogCommand *command.CreateLogComma
56 } 54 }
57 } 55 }
58 56
59 -// 返回日志服务  
60 func (logService *LogService) GetLog(getLogQuery *query.GetLogQuery) (interface{}, error) { 57 func (logService *LogService) GetLog(getLogQuery *query.GetLogQuery) (interface{}, error) {
61 if err := getLogQuery.ValidateQuery(); err != nil { 58 if err := getLogQuery.ValidateQuery(); err != nil {
62 return nil, application.ThrowError(application.ARG_ERROR, err.Error()) 59 return nil, application.ThrowError(application.ARG_ERROR, err.Error())
@@ -93,7 +90,6 @@ func (logService *LogService) GetLog(getLogQuery *query.GetLogQuery) (interface{ @@ -93,7 +90,6 @@ func (logService *LogService) GetLog(getLogQuery *query.GetLogQuery) (interface{
93 } 90 }
94 } 91 }
95 92
96 -// 返回日志服务列表  
97 func (logService *LogService) ListLog(listLogQuery *query.ListLogQuery) (interface{}, error) { 93 func (logService *LogService) ListLog(listLogQuery *query.ListLogQuery) (interface{}, error) {
98 if err := listLogQuery.ValidateQuery(); err != nil { 94 if err := listLogQuery.ValidateQuery(); err != nil {
99 return nil, application.ThrowError(application.ARG_ERROR, err.Error()) 95 return nil, application.ThrowError(application.ARG_ERROR, err.Error())
@@ -129,7 +125,6 @@ func (logService *LogService) ListLog(listLogQuery *query.ListLogQuery) (interfa @@ -129,7 +125,6 @@ func (logService *LogService) ListLog(listLogQuery *query.ListLogQuery) (interfa
129 } 125 }
130 } 126 }
131 127
132 -// 移除日志服务  
133 func (logService *LogService) RemoveLog(removeLogCommand *command.RemoveLogCommand) (interface{}, error) { 128 func (logService *LogService) RemoveLog(removeLogCommand *command.RemoveLogCommand) (interface{}, error) {
134 if err := removeLogCommand.ValidateCommand(); err != nil { 129 if err := removeLogCommand.ValidateCommand(); err != nil {
135 return nil, application.ThrowError(application.ARG_ERROR, err.Error()) 130 return nil, application.ThrowError(application.ARG_ERROR, err.Error())
@@ -169,7 +164,6 @@ func (logService *LogService) RemoveLog(removeLogCommand *command.RemoveLogComma @@ -169,7 +164,6 @@ func (logService *LogService) RemoveLog(removeLogCommand *command.RemoveLogComma
169 } 164 }
170 } 165 }
171 166
172 -// 搜索日志  
173 func (logService *LogService) SearchLog(searchLogCommand *command.SearchLogCommand) (int64, interface{}, error) { 167 func (logService *LogService) SearchLog(searchLogCommand *command.SearchLogCommand) (int64, interface{}, error) {
174 if err := searchLogCommand.ValidateCommand(); err != nil { 168 if err := searchLogCommand.ValidateCommand(); err != nil {
175 return 0, nil, application.ThrowError(application.ARG_ERROR, err.Error()) 169 return 0, nil, application.ThrowError(application.ARG_ERROR, err.Error())
@@ -204,7 +198,6 @@ func (logService *LogService) SearchLog(searchLogCommand *command.SearchLogComma @@ -204,7 +198,6 @@ func (logService *LogService) SearchLog(searchLogCommand *command.SearchLogComma
204 return count, result, nil 198 return count, result, nil
205 } 199 }
206 200
207 -// 搜索日志  
208 func (logService *LogService) VerifiedStepLog(searchLogCommand *command.SearchLogCommand) (int64, interface{}, error) { 201 func (logService *LogService) VerifiedStepLog(searchLogCommand *command.SearchLogCommand) (int64, interface{}, error) {
209 if err := searchLogCommand.ValidateCommand(); err != nil { 202 if err := searchLogCommand.ValidateCommand(); err != nil {
210 return 0, nil, application.ThrowError(application.ARG_ERROR, err.Error()) 203 return 0, nil, application.ThrowError(application.ARG_ERROR, err.Error())
@@ -252,7 +245,6 @@ func (logService *LogService) VerifiedStepLog(searchLogCommand *command.SearchLo @@ -252,7 +245,6 @@ func (logService *LogService) VerifiedStepLog(searchLogCommand *command.SearchLo
252 }, nil 245 }, nil
253 } 246 }
254 247
255 -// 更新日志服务  
256 func (logService *LogService) UpdateLog(updateLogCommand *command.UpdateLogCommand) (interface{}, error) { 248 func (logService *LogService) UpdateLog(updateLogCommand *command.UpdateLogCommand) (interface{}, error) {
257 if err := updateLogCommand.ValidateCommand(); err != nil { 249 if err := updateLogCommand.ValidateCommand(); err != nil {
258 return nil, application.ThrowError(application.ARG_ERROR, err.Error()) 250 return nil, application.ThrowError(application.ARG_ERROR, err.Error())
@@ -13,7 +13,7 @@ type UpdateMappingRuleCommand struct { @@ -13,7 +13,7 @@ type UpdateMappingRuleCommand struct {
13 // 匹配规则ID 13 // 匹配规则ID
14 MappingRuleId int `cname:"匹配规则ID" json:"mappingRuleId" valid:"Required"` 14 MappingRuleId int `cname:"匹配规则ID" json:"mappingRuleId" valid:"Required"`
15 // 名称 15 // 名称
16 - Name string `cname:"名称" json:"name" valid:"Required"` 16 + Name string `cname:"名称" json:"name"`
17 // 校验文件列 17 // 校验文件列
18 MappingFields []*domain.MappingField `cname:"匹配规则列表" json:"mappingFields" valid:"Required"` 18 MappingFields []*domain.MappingField `cname:"匹配规则列表" json:"mappingFields" valid:"Required"`
19 } 19 }
@@ -13,11 +13,11 @@ import ( @@ -13,11 +13,11 @@ import (
13 "time" 13 "time"
14 ) 14 )
15 15
16 -// 匹配规则服务 16 +// MappingRuleService 匹配规则服务
17 type MappingRuleService struct { 17 type MappingRuleService struct {
18 } 18 }
19 19
20 -// 创建匹配规则服务 20 +// CreateMappingRule 创建匹配规则服务
21 func (mappingRuleService *MappingRuleService) CreateMappingRule(ctx *domain.Context, cmd *command.CreateMappingRuleCommand) (interface{}, error) { 21 func (mappingRuleService *MappingRuleService) CreateMappingRule(ctx *domain.Context, cmd *command.CreateMappingRuleCommand) (interface{}, error) {
22 if err := cmd.ValidateCommand(); err != nil { 22 if err := cmd.ValidateCommand(); err != nil {
23 return nil, application.ThrowError(application.ARG_ERROR, err.Error()) 23 return nil, application.ThrowError(application.ARG_ERROR, err.Error())
@@ -47,7 +47,7 @@ func (mappingRuleService *MappingRuleService) CreateMappingRule(ctx *domain.Cont @@ -47,7 +47,7 @@ func (mappingRuleService *MappingRuleService) CreateMappingRule(ctx *domain.Cont
47 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error()) 47 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
48 } 48 }
49 49
50 - if duplicateRule, e := mappingRuleRepository.FindOne(map[string]interface{}{"context": ctx, "name": cmd.Name}); e == nil && duplicateRule != nil { 50 + if duplicateRule, e := mappingRuleRepository.FindOne(map[string]interface{}{"context": ctx, "name": cmd.Name, "tableId": cmd.TableId}); e == nil && duplicateRule != nil {
51 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, "方案名称重复") 51 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, "方案名称重复")
52 } 52 }
53 53
@@ -81,7 +81,7 @@ func (mappingRuleService *MappingRuleService) CreateMappingRule(ctx *domain.Cont @@ -81,7 +81,7 @@ func (mappingRuleService *MappingRuleService) CreateMappingRule(ctx *domain.Cont
81 return result, nil 81 return result, nil
82 } 82 }
83 83
84 -// 返回匹配规则服务 84 +// GetMappingRule 返回匹配规则服务
85 func (mappingRuleService *MappingRuleService) GetMappingRule(getMappingRuleQuery *query.GetMappingRuleQuery) (interface{}, error) { 85 func (mappingRuleService *MappingRuleService) GetMappingRule(getMappingRuleQuery *query.GetMappingRuleQuery) (interface{}, error) {
86 if err := getMappingRuleQuery.ValidateQuery(); err != nil { 86 if err := getMappingRuleQuery.ValidateQuery(); err != nil {
87 return nil, application.ThrowError(application.ARG_ERROR, err.Error()) 87 return nil, application.ThrowError(application.ARG_ERROR, err.Error())
@@ -109,7 +109,7 @@ func (mappingRuleService *MappingRuleService) GetMappingRule(getMappingRuleQuery @@ -109,7 +109,7 @@ func (mappingRuleService *MappingRuleService) GetMappingRule(getMappingRuleQuery
109 return result, nil 109 return result, nil
110 } 110 }
111 111
112 -// 返回匹配规则服务列表 112 +// ListMappingRule 返回匹配规则服务列表
113 func (mappingRuleService *MappingRuleService) ListMappingRule(listMappingRuleQuery *query.ListMappingRuleQuery) (interface{}, error) { 113 func (mappingRuleService *MappingRuleService) ListMappingRule(listMappingRuleQuery *query.ListMappingRuleQuery) (interface{}, error) {
114 if err := listMappingRuleQuery.ValidateQuery(); err != nil { 114 if err := listMappingRuleQuery.ValidateQuery(); err != nil {
115 return nil, application.ThrowError(application.ARG_ERROR, err.Error()) 115 return nil, application.ThrowError(application.ARG_ERROR, err.Error())
@@ -145,7 +145,7 @@ func (mappingRuleService *MappingRuleService) ListMappingRule(listMappingRuleQue @@ -145,7 +145,7 @@ func (mappingRuleService *MappingRuleService) ListMappingRule(listMappingRuleQue
145 } 145 }
146 } 146 }
147 147
148 -// 匹配规则预准备(新建规则) 148 +// Prepare 匹配规则预准备(新建规则)
149 func (mappingRuleService *MappingRuleService) Prepare(prepareCommand *command.PrepareCommand) (interface{}, error) { 149 func (mappingRuleService *MappingRuleService) Prepare(prepareCommand *command.PrepareCommand) (interface{}, error) {
150 if err := prepareCommand.ValidateCommand(); err != nil { 150 if err := prepareCommand.ValidateCommand(); err != nil {
151 return nil, application.ThrowError(application.ARG_ERROR, err.Error()) 151 return nil, application.ThrowError(application.ARG_ERROR, err.Error())
@@ -182,7 +182,7 @@ func (mappingRuleService *MappingRuleService) Prepare(prepareCommand *command.Pr @@ -182,7 +182,7 @@ func (mappingRuleService *MappingRuleService) Prepare(prepareCommand *command.Pr
182 return ruleDto, nil 182 return ruleDto, nil
183 } 183 }
184 184
185 -// 移除匹配规则服务 185 +// RemoveMappingRule 移除匹配规则服务
186 func (mappingRuleService *MappingRuleService) RemoveMappingRule(removeMappingRuleCommand *command.RemoveMappingRuleCommand) (interface{}, error) { 186 func (mappingRuleService *MappingRuleService) RemoveMappingRule(removeMappingRuleCommand *command.RemoveMappingRuleCommand) (interface{}, error) {
187 if err := removeMappingRuleCommand.ValidateCommand(); err != nil { 187 if err := removeMappingRuleCommand.ValidateCommand(); err != nil {
188 return nil, application.ThrowError(application.ARG_ERROR, err.Error()) 188 return nil, application.ThrowError(application.ARG_ERROR, err.Error())
@@ -222,7 +222,7 @@ func (mappingRuleService *MappingRuleService) RemoveMappingRule(removeMappingRul @@ -222,7 +222,7 @@ func (mappingRuleService *MappingRuleService) RemoveMappingRule(removeMappingRul
222 }{}, nil 222 }{}, nil
223 } 223 }
224 224
225 -// 搜索规则 225 +// Search 搜索规则
226 func (mappingRuleService *MappingRuleService) Search(searchCommand *command.SearchCommand) (interface{}, error) { 226 func (mappingRuleService *MappingRuleService) Search(searchCommand *command.SearchCommand) (interface{}, error) {
227 if err := searchCommand.ValidateCommand(); err != nil { 227 if err := searchCommand.ValidateCommand(); err != nil {
228 return nil, application.ThrowError(application.ARG_ERROR, err.Error()) 228 return nil, application.ThrowError(application.ARG_ERROR, err.Error())
@@ -259,7 +259,7 @@ func (mappingRuleService *MappingRuleService) Search(searchCommand *command.Sear @@ -259,7 +259,7 @@ func (mappingRuleService *MappingRuleService) Search(searchCommand *command.Sear
259 }, nil 259 }, nil
260 } 260 }
261 261
262 -// 更新匹配规则服务 262 +// UpdateMappingRule 更新匹配规则服务
263 func (mappingRuleService *MappingRuleService) UpdateMappingRule(ctx *domain.Context, cmd *command.UpdateMappingRuleCommand) (interface{}, error) { 263 func (mappingRuleService *MappingRuleService) UpdateMappingRule(ctx *domain.Context, cmd *command.UpdateMappingRuleCommand) (interface{}, error) {
264 if err := cmd.ValidateCommand(); err != nil { 264 if err := cmd.ValidateCommand(); err != nil {
265 return nil, application.ThrowError(application.ARG_ERROR, err.Error()) 265 return nil, application.ThrowError(application.ARG_ERROR, err.Error())
@@ -288,11 +288,14 @@ func (mappingRuleService *MappingRuleService) UpdateMappingRule(ctx *domain.Cont @@ -288,11 +288,14 @@ func (mappingRuleService *MappingRuleService) UpdateMappingRule(ctx *domain.Cont
288 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error()) 288 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
289 } 289 }
290 290
291 - if duplicateRule, e := mappingRuleRepository.FindOne(map[string]interface{}{"context": ctx, "name": cmd.Name}); e == nil && duplicateRule != nil && duplicateRule.MappingRuleId != cmd.MappingRuleId {  
292 - return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, "方案名称重复") 291 + if len(cmd.Name) != 0 {
  292 + if duplicateRule, e := mappingRuleRepository.FindOne(map[string]interface{}{"context": ctx, "name": cmd.Name}); e == nil && duplicateRule != nil && duplicateRule.MappingRuleId != cmd.MappingRuleId {
  293 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, "方案名称重复")
  294 + }
  295 + }
  296 + if len(cmd.Name) > 0 {
  297 + mappingRule.Name = cmd.Name
293 } 298 }
294 -  
295 - mappingRule.Name = cmd.Name  
296 mappingRule.MappingFields = cmd.MappingFields 299 mappingRule.MappingFields = cmd.MappingFields
297 mappingRule.VerifiedFileFields = fileTable.Fields(false) 300 mappingRule.VerifiedFileFields = fileTable.Fields(false)
298 mappingRule.UpdatedAt = time.Now() 301 mappingRule.UpdatedAt = time.Now()
  1 +package command
  2 +
  3 +import (
  4 + "fmt"
  5 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
  6 + "reflect"
  7 + "strings"
  8 +
  9 + "github.com/beego/beego/v2/core/validation"
  10 +)
  11 +
  12 +type ChangeStatusCommand struct {
  13 + // 查询集合ID
  14 + QuerySetId int `cname:"查询集合ID" json:"querySetId" valid:"Required"`
  15 + // 状态 1:启用 2:关闭 (子过程默认启用)
  16 + Status int `cname:"状态 1:启用 2:关闭 (子过程默认启用)" json:"status" valid:"Required"`
  17 +}
  18 +
  19 +func (changeStatusCommand *ChangeStatusCommand) Valid(validation *validation.Validation) {
  20 + if !(changeStatusCommand.Status == domain.StatusOn || changeStatusCommand.Status == domain.StatusOff) {
  21 + validation.Error("状态值有误")
  22 + }
  23 +}
  24 +
  25 +func (changeStatusCommand *ChangeStatusCommand) ValidateCommand() error {
  26 + valid := validation.Validation{}
  27 + b, err := valid.Valid(changeStatusCommand)
  28 + if err != nil {
  29 + return err
  30 + }
  31 + if !b {
  32 + elem := reflect.TypeOf(changeStatusCommand).Elem()
  33 + for _, validErr := range valid.Errors {
  34 + field, isExist := elem.FieldByName(validErr.Field)
  35 + if isExist {
  36 + return fmt.Errorf(strings.Replace(validErr.Message, validErr.Field, field.Tag.Get("cname"), -1))
  37 + } else {
  38 + return fmt.Errorf(validErr.Message)
  39 + }
  40 + }
  41 + }
  42 + return nil
  43 +}
  1 +package command
  2 +
  3 +import (
  4 + "fmt"
  5 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
  6 + "reflect"
  7 + "strings"
  8 +
  9 + "github.com/beego/beego/v2/core/validation"
  10 +)
  11 +
  12 +type CopyCommand struct {
  13 + // Schema:方案 SubProcess:子过程
  14 + Type string `cname:"类型" json:"type" valid:"Required"`
  15 + // 父级ID
  16 + ParentId int `cname:"父级ID" json:"parentId" valid:"Required"`
  17 + // 名称
  18 + Name string `cname:"名称" json:"name" valid:"Required"`
  19 + // 查询集合ID
  20 + QuerySetId int `cname:"查询集合ID" json:"querySetId" valid:"Required"`
  21 +}
  22 +
  23 +func (cmd *CopyCommand) Valid(validation *validation.Validation) {
  24 + if err := domain.ValidQuerySetType(cmd.Type); err != nil {
  25 + validation.Error(err.Error())
  26 + return
  27 + }
  28 +}
  29 +
  30 +func (cmd *CopyCommand) ValidateCommand() error {
  31 + valid := validation.Validation{}
  32 + b, err := valid.Valid(cmd)
  33 + if err != nil {
  34 + return err
  35 + }
  36 + if !b {
  37 + elem := reflect.TypeOf(cmd).Elem()
  38 + for _, validErr := range valid.Errors {
  39 + field, isExist := elem.FieldByName(validErr.Field)
  40 + if isExist {
  41 + return fmt.Errorf(strings.Replace(validErr.Message, validErr.Field, field.Tag.Get("cname"), -1))
  42 + } else {
  43 + return fmt.Errorf(validErr.Message)
  44 + }
  45 + }
  46 + }
  47 + return nil
  48 +}
  1 +package command
  2 +
  3 +import (
  4 + "fmt"
  5 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
  6 + "reflect"
  7 + "strings"
  8 +
  9 + "github.com/beego/beego/v2/core/validation"
  10 +)
  11 +
  12 +type CreateQuerySetCommand struct {
  13 + // Schema:方案 SubProcess:子过程
  14 + Type string `cname:"类型" json:"type" valid:"Required"`
  15 + // 标识
  16 + Flag string `cname:"标识" json:"flag" valid:"Required"`
  17 + // 名称
  18 + Name string `cname:"名称" json:"name"`
  19 + // 父级ID
  20 + ParentId int `cname:"父级ID" json:"parentId,omitempty"`
  21 +}
  22 +
  23 +func (cmd *CreateQuerySetCommand) Valid(validation *validation.Validation) {
  24 + if err := domain.ValidQuerySetType(cmd.Type); err != nil {
  25 + validation.Error(err.Error())
  26 + return
  27 + }
  28 + if err := domain.ValidQuerySetFlag(cmd.Flag); err != nil {
  29 + validation.Error(err.Error())
  30 + return
  31 + }
  32 +}
  33 +
  34 +func (cmd *CreateQuerySetCommand) ValidateCommand() error {
  35 + valid := validation.Validation{}
  36 + b, err := valid.Valid(cmd)
  37 + if err != nil {
  38 + return err
  39 + }
  40 + if !b {
  41 + elem := reflect.TypeOf(cmd).Elem()
  42 + for _, validErr := range valid.Errors {
  43 + field, isExist := elem.FieldByName(validErr.Field)
  44 + if isExist {
  45 + return fmt.Errorf(strings.Replace(validErr.Message, validErr.Field, field.Tag.Get("cname"), -1))
  46 + } else {
  47 + return fmt.Errorf(validErr.Message)
  48 + }
  49 + }
  50 + }
  51 + return nil
  52 +}
  1 +package command
  2 +
  3 +import (
  4 + "fmt"
  5 + "reflect"
  6 + "strings"
  7 +
  8 + "github.com/beego/beego/v2/core/validation"
  9 +)
  10 +
  11 +type MoveCommand struct {
  12 + // 查询集合ID
  13 + QuerySetId int `cname:"查询集合ID" json:"querySetId" valid:"Required"`
  14 + // 父级ID
  15 + ParentId int `cname:"父级ID" json:"parentId" valid:"Required"`
  16 + // 排序
  17 + Index int `cname:"序号" json:"index" valid:"Required"`
  18 +}
  19 +
  20 +func (moveCommand *MoveCommand) Valid(validation *validation.Validation) {
  21 + //validation.SetError("CustomValid", "未实现的自定义认证")
  22 +}
  23 +
  24 +func (moveCommand *MoveCommand) ValidateCommand() error {
  25 + valid := validation.Validation{}
  26 + b, err := valid.Valid(moveCommand)
  27 + if err != nil {
  28 + return err
  29 + }
  30 + if !b {
  31 + elem := reflect.TypeOf(moveCommand).Elem()
  32 + for _, validErr := range valid.Errors {
  33 + field, isExist := elem.FieldByName(validErr.Field)
  34 + if isExist {
  35 + return fmt.Errorf(strings.Replace(validErr.Message, validErr.Field, field.Tag.Get("cname"), -1))
  36 + } else {
  37 + return fmt.Errorf(validErr.Message)
  38 + }
  39 + }
  40 + }
  41 + return nil
  42 +}
  1 +package command
  2 +
  3 +import (
  4 + "fmt"
  5 + "reflect"
  6 + "strings"
  7 +
  8 + "github.com/beego/beego/v2/core/validation"
  9 +)
  10 +
  11 +type RefreshQuerySetCommand struct {
  12 + // 查询集合ID
  13 + QuerySetId int `cname:"查询集合ID" json:"querySetId" valid:"Required"`
  14 +}
  15 +
  16 +func (updateQuerySetCommand *RefreshQuerySetCommand) Valid(validation *validation.Validation) {
  17 + //validation.SetError("CustomValid", "未实现的自定义认证")
  18 +}
  19 +
  20 +func (updateQuerySetCommand *RefreshQuerySetCommand) ValidateCommand() error {
  21 + valid := validation.Validation{}
  22 + b, err := valid.Valid(updateQuerySetCommand)
  23 + if err != nil {
  24 + return err
  25 + }
  26 + if !b {
  27 + elem := reflect.TypeOf(updateQuerySetCommand).Elem()
  28 + for _, validErr := range valid.Errors {
  29 + field, isExist := elem.FieldByName(validErr.Field)
  30 + if isExist {
  31 + return fmt.Errorf(strings.Replace(validErr.Message, validErr.Field, field.Tag.Get("cname"), -1))
  32 + } else {
  33 + return fmt.Errorf(validErr.Message)
  34 + }
  35 + }
  36 + }
  37 + return nil
  38 +}
  1 +package command
  2 +
  3 +import (
  4 + "fmt"
  5 + "reflect"
  6 + "strings"
  7 +
  8 + "github.com/beego/beego/v2/core/validation"
  9 +)
  10 +
  11 +type RemoveQuerySetCommand struct {
  12 + // 查询集合ID
  13 + QuerySetId int `cname:"查询集合ID" json:"querySetId" valid:"Required"`
  14 +}
  15 +
  16 +func (removeQuerySetCommand *RemoveQuerySetCommand) Valid(validation *validation.Validation) {
  17 + //validation.SetError("CustomValid", "未实现的自定义认证")
  18 +}
  19 +
  20 +func (removeQuerySetCommand *RemoveQuerySetCommand) ValidateCommand() error {
  21 + valid := validation.Validation{}
  22 + b, err := valid.Valid(removeQuerySetCommand)
  23 + if err != nil {
  24 + return err
  25 + }
  26 + if !b {
  27 + elem := reflect.TypeOf(removeQuerySetCommand).Elem()
  28 + for _, validErr := range valid.Errors {
  29 + field, isExist := elem.FieldByName(validErr.Field)
  30 + if isExist {
  31 + return fmt.Errorf(strings.Replace(validErr.Message, validErr.Field, field.Tag.Get("cname"), -1))
  32 + } else {
  33 + return fmt.Errorf(validErr.Message)
  34 + }
  35 + }
  36 + }
  37 + return nil
  38 +}
  1 +package command
  2 +
  3 +import (
  4 + "fmt"
  5 + "reflect"
  6 + "strings"
  7 +
  8 + "github.com/beego/beego/v2/core/validation"
  9 +)
  10 +
  11 +type RenameCommand struct {
  12 + // 查询集合ID
  13 + QuerySetId int `cname:"查询集合ID" json:"querySetId" valid:"Required"`
  14 + // 名称
  15 + Name string `cname:"名称" json:"name" valid:"Required"`
  16 +}
  17 +
  18 +func (renameCommand *RenameCommand) Valid(validation *validation.Validation) {
  19 + //validation.SetError("CustomValid", "未实现的自定义认证")
  20 +}
  21 +
  22 +func (renameCommand *RenameCommand) ValidateCommand() error {
  23 + valid := validation.Validation{}
  24 + b, err := valid.Valid(renameCommand)
  25 + if err != nil {
  26 + return err
  27 + }
  28 + if !b {
  29 + elem := reflect.TypeOf(renameCommand).Elem()
  30 + for _, validErr := range valid.Errors {
  31 + field, isExist := elem.FieldByName(validErr.Field)
  32 + if isExist {
  33 + return fmt.Errorf(strings.Replace(validErr.Message, validErr.Field, field.Tag.Get("cname"), -1))
  34 + } else {
  35 + return fmt.Errorf(validErr.Message)
  36 + }
  37 + }
  38 + }
  39 + return nil
  40 +}
  1 +package command
  2 +
  3 +import (
  4 + "fmt"
  5 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
  6 + "reflect"
  7 + "strings"
  8 +
  9 + "github.com/beego/beego/v2/core/validation"
  10 +)
  11 +
  12 +type UpdateQuerySetCommand struct {
  13 + // 查询集合ID
  14 + QuerySetId int `cname:"查询集合ID" json:"querySetId" valid:"Required"`
  15 + QueryComponents []*domain.QueryComponent `cname:"查询组件" json:"queryComponents" valid:"Required"`
  16 +}
  17 +
  18 +func (updateQuerySetCommand *UpdateQuerySetCommand) Valid(validation *validation.Validation) {
  19 + //validation.SetError("CustomValid", "未实现的自定义认证")
  20 +}
  21 +
  22 +func (updateQuerySetCommand *UpdateQuerySetCommand) ValidateCommand() error {
  23 + valid := validation.Validation{}
  24 + b, err := valid.Valid(updateQuerySetCommand)
  25 + if err != nil {
  26 + return err
  27 + }
  28 + if !b {
  29 + elem := reflect.TypeOf(updateQuerySetCommand).Elem()
  30 + for _, validErr := range valid.Errors {
  31 + field, isExist := elem.FieldByName(validErr.Field)
  32 + if isExist {
  33 + return fmt.Errorf(strings.Replace(validErr.Message, validErr.Field, field.Tag.Get("cname"), -1))
  34 + } else {
  35 + return fmt.Errorf(validErr.Message)
  36 + }
  37 + }
  38 + }
  39 + return nil
  40 +}
  1 +package dto
  2 +
  3 +import "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
  4 +
  5 +type QuerySetDetailDto struct {
  6 + // 查询集合ID
  7 + QuerySetId int `json:"querySetId"`
  8 + // Schema:方案 SubProcess:子过程
  9 + Type string `json:"type"`
  10 + // 标识 分组:Group 子过程/方案:Set
  11 + Flag string `json:"flag"`
  12 + // 名称
  13 + Name string `json:"name"`
  14 + // 查询组件
  15 + QueryComponents []*domain.QueryComponent `json:"queryComponents"`
  16 + // 查询集绑定的表
  17 + TableId int `json:"tableId"`
  18 + // 在冲突状态 true:冲突异常 false:正常
  19 + InConflict bool `json:"inConflict"`
  20 +}
  21 +
  22 +func (d *QuerySetDetailDto) Load(m *domain.QuerySet, mapTables map[int]*domain.Table) *QuerySetDetailDto {
  23 + d.QuerySetId = m.QuerySetId
  24 + d.Type = m.Type
  25 + d.Flag = m.Flag
  26 + d.Name = m.Name
  27 + d.QueryComponents = m.QueryComponents
  28 + if m.QuerySetInfo != nil {
  29 + d.TableId = m.QuerySetInfo.BindTableId
  30 + }
  31 + hasUpdateTable := false
  32 + for i, q := range d.QueryComponents {
  33 + if q.MasterTable != nil && q.MasterTable.TableId != 0 {
  34 + if t, ok := mapTables[q.MasterTable.TableId]; ok {
  35 + d.QueryComponents[i].MasterTable = domain.NewQueryComponentTable(t)
  36 + d.QueryComponents[i].UpdateTables(t)
  37 + hasUpdateTable = true
  38 + }
  39 + }
  40 + if d.QueryComponents[i].Aggregation != nil {
  41 + d.QueryComponents[i].Aggregation.Aggregation.AllFields = d.QueryComponents[i].Aggregation.AggregationFields()
  42 + }
  43 + if !hasUpdateTable && len(mapTables) == 1 {
  44 + for _, t := range mapTables {
  45 + d.QueryComponents[i].UpdateTables(t)
  46 + hasUpdateTable = true
  47 + break
  48 + }
  49 + }
  50 + }
  51 + d.InConflict = false
  52 + if m.QuerySetInfo != nil {
  53 + if m.QuerySetInfo.ReadyStatus == 1 {
  54 + d.InConflict = true
  55 + }
  56 + }
  57 + return d
  58 +}
  1 +package dto
  2 +
  3 +import "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
  4 +
  5 +type QuerySetDto struct {
  6 + // 查询集合ID
  7 + QuerySetId int `json:"querySetId"`
  8 + // Schema:方案 SubProcess:子过程
  9 + Type string `json:"type"`
  10 + // 标识 分组:Group 子过程/方案:Set
  11 + Flag string `json:"flag"`
  12 + // 名称
  13 + Name string `json:"name"`
  14 + // 父级ID
  15 + ParentId int `json:"parentId"`
  16 + // 状态 1:启用 2:关闭 (子过程默认启用)
  17 + Status int `json:"status"`
  18 + // 排序
  19 + Sort int `json:"sort"`
  20 + // 时间
  21 + Time string `json:"time"`
  22 + // 绑定的表ID
  23 + BindTableId int `json:"tableId"`
  24 + // 在冲突状态 true:冲突异常 false:正常
  25 + InConflict bool `json:"inConflict"`
  26 +}
  27 +
  28 +func (d *QuerySetDto) Load(m *domain.QuerySet) *QuerySetDto {
  29 + d.QuerySetId = m.QuerySetId
  30 + d.Type = m.Type
  31 + d.Flag = m.Flag
  32 + d.Name = m.Name
  33 + d.ParentId = m.ParentId
  34 + d.Status = m.Status
  35 + d.Sort = m.Sort
  36 + d.Time = m.CreatedAt.Local().Format("2006-01-02 15:04:05")
  37 + d.BindTableId = m.QuerySetInfo.BindTableId
  38 + d.InConflict = m.QuerySetInfo.ReadyStatus == 1
  39 + return d
  40 +}
  41 +
  42 +func NewQuerySetDtoList(querySets []*domain.QuerySet) []*QuerySetDto {
  43 + var result = make([]*QuerySetDto, 0)
  44 + for _, set := range querySets {
  45 + var item = &QuerySetDto{}
  46 + item.Load(set)
  47 + result = append(result, item)
  48 + }
  49 + return result
  50 +}
  1 +package query
  2 +
  3 +import (
  4 + "fmt"
  5 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
  6 + "reflect"
  7 + "strings"
  8 +
  9 + "github.com/beego/beego/v2/core/validation"
  10 +)
  11 +
  12 +type CalculateItemPreviewQuery struct {
  13 + // 查询集合ID
  14 + QuerySetId int `cname:"查询集合ID" json:"querySetId" valid:"Required"`
  15 + // 公式
  16 + Formula *domain.FieldExpr `json:"formula" valid:"Required"`
  17 +}
  18 +
  19 +func (dependencyGraphQuery *CalculateItemPreviewQuery) Valid(validation *validation.Validation) {
  20 + //validation.SetError("CustomValid", "未实现的自定义认证")
  21 +}
  22 +
  23 +func (dependencyGraphQuery *CalculateItemPreviewQuery) ValidateQuery() error {
  24 + valid := validation.Validation{}
  25 + b, err := valid.Valid(dependencyGraphQuery)
  26 + if err != nil {
  27 + return err
  28 + }
  29 + if !b {
  30 + elem := reflect.TypeOf(dependencyGraphQuery).Elem()
  31 + for _, validErr := range valid.Errors {
  32 + field, isExist := elem.FieldByName(validErr.Field)
  33 + if isExist {
  34 + return fmt.Errorf(strings.Replace(validErr.Message, validErr.Field, field.Tag.Get("cname"), -1))
  35 + } else {
  36 + return fmt.Errorf(validErr.Message)
  37 + }
  38 + }
  39 + }
  40 + return nil
  41 +}
  1 +package query
  2 +
  3 +import (
  4 + "fmt"
  5 + "reflect"
  6 + "strings"
  7 +
  8 + "github.com/beego/beego/v2/core/validation"
  9 +)
  10 +
  11 +type DependencyGraphQuery struct {
  12 + // 查询集合ID
  13 + QuerySetId int `cname:"查询集合ID" json:"querySetId" valid:"Required"`
  14 +}
  15 +
  16 +func (dependencyGraphQuery *DependencyGraphQuery) Valid(validation *validation.Validation) {
  17 + //validation.SetError("CustomValid", "未实现的自定义认证")
  18 +}
  19 +
  20 +func (dependencyGraphQuery *DependencyGraphQuery) ValidateQuery() error {
  21 + valid := validation.Validation{}
  22 + b, err := valid.Valid(dependencyGraphQuery)
  23 + if err != nil {
  24 + return err
  25 + }
  26 + if !b {
  27 + elem := reflect.TypeOf(dependencyGraphQuery).Elem()
  28 + for _, validErr := range valid.Errors {
  29 + field, isExist := elem.FieldByName(validErr.Field)
  30 + if isExist {
  31 + return fmt.Errorf(strings.Replace(validErr.Message, validErr.Field, field.Tag.Get("cname"), -1))
  32 + } else {
  33 + return fmt.Errorf(validErr.Message)
  34 + }
  35 + }
  36 + }
  37 + return nil
  38 +}
  1 +package query
  2 +
  3 +import (
  4 + "fmt"
  5 + "reflect"
  6 + "strings"
  7 +
  8 + "github.com/beego/beego/v2/core/validation"
  9 +)
  10 +
  11 +type GetQuerySetQuery struct {
  12 + // 查询集合ID
  13 + QuerySetId int `cname:"查询集合ID" json:"querySetId" valid:"Required"`
  14 +}
  15 +
  16 +func (getQuerySetQuery *GetQuerySetQuery) Valid(validation *validation.Validation) {
  17 + //validation.SetError("CustomValid", "未实现的自定义认证")
  18 +}
  19 +
  20 +func (getQuerySetQuery *GetQuerySetQuery) ValidateQuery() error {
  21 + valid := validation.Validation{}
  22 + b, err := valid.Valid(getQuerySetQuery)
  23 + if err != nil {
  24 + return err
  25 + }
  26 + if !b {
  27 + elem := reflect.TypeOf(getQuerySetQuery).Elem()
  28 + for _, validErr := range valid.Errors {
  29 + field, isExist := elem.FieldByName(validErr.Field)
  30 + if isExist {
  31 + return fmt.Errorf(strings.Replace(validErr.Message, validErr.Field, field.Tag.Get("cname"), -1))
  32 + } else {
  33 + return fmt.Errorf(validErr.Message)
  34 + }
  35 + }
  36 + }
  37 + return nil
  38 +}
  1 +package query
  2 +
  3 +import (
  4 + "fmt"
  5 + "reflect"
  6 + "strings"
  7 +
  8 + "github.com/beego/beego/v2/core/validation"
  9 +)
  10 +
  11 +type ListQuerySetQuery struct {
  12 + // 查询偏离量
  13 + Offset int `cname:"查询偏离量" json:"offset" valid:"Required"`
  14 + // 查询限制
  15 + Limit int `cname:"查询限制" json:"limit" valid:"Required"`
  16 +}
  17 +
  18 +func (listQuerySetQuery *ListQuerySetQuery) Valid(validation *validation.Validation) {
  19 + //validation.SetError("CustomValid", "未实现的自定义认证")
  20 +}
  21 +
  22 +func (listQuerySetQuery *ListQuerySetQuery) ValidateQuery() error {
  23 + valid := validation.Validation{}
  24 + b, err := valid.Valid(listQuerySetQuery)
  25 + if err != nil {
  26 + return err
  27 + }
  28 + if !b {
  29 + elem := reflect.TypeOf(listQuerySetQuery).Elem()
  30 + for _, validErr := range valid.Errors {
  31 + field, isExist := elem.FieldByName(validErr.Field)
  32 + if isExist {
  33 + return fmt.Errorf(strings.Replace(validErr.Message, validErr.Field, field.Tag.Get("cname"), -1))
  34 + } else {
  35 + return fmt.Errorf(validErr.Message)
  36 + }
  37 + }
  38 + }
  39 + return nil
  40 +}
  1 +package query
  2 +
  3 +import (
  4 + "fmt"
  5 + "github.com/beego/beego/v2/core/validation"
  6 + "reflect"
  7 + "strings"
  8 +)
  9 +
  10 +type StatisticsQuery struct {
  11 +}
  12 +
  13 +func (q *StatisticsQuery) Valid(validation *validation.Validation) {
  14 + //validation.SetError("CustomValid", "未实现的自定义认证")
  15 +}
  16 +
  17 +func (q *StatisticsQuery) ValidateQuery() error {
  18 + valid := validation.Validation{}
  19 + b, err := valid.Valid(q)
  20 + if err != nil {
  21 + return err
  22 + }
  23 + if !b {
  24 + elem := reflect.TypeOf(q).Elem()
  25 + for _, validErr := range valid.Errors {
  26 + field, isExist := elem.FieldByName(validErr.Field)
  27 + if isExist {
  28 + return fmt.Errorf(strings.Replace(validErr.Message, validErr.Field, field.Tag.Get("cname"), -1))
  29 + } else {
  30 + return fmt.Errorf(validErr.Message)
  31 + }
  32 + }
  33 + }
  34 + return nil
  35 +}
  1 +package query
  2 +
  3 +import (
  4 + "fmt"
  5 + "github.com/beego/beego/v2/adapter/utils"
  6 + "reflect"
  7 + "strings"
  8 +
  9 + "github.com/beego/beego/v2/core/validation"
  10 +)
  11 +
  12 +type SearchQuerySetQuery struct {
  13 + Type string `cname:"类型" json:"type"`
  14 + Types []string `cname:"类型" json:"types"`
  15 + Flag string `cname:"标识" json:"flag"`
  16 + Status int `cname:"状态 1:启用 2:关闭" json:"status"`
  17 + MatchName string `cname:"匹配名称" json:"matchName"`
  18 + SortByName string `json:"sortByName"`
  19 + SortByTime string `json:"sortByTime"`
  20 +}
  21 +
  22 +func (searchQuerySetQuery *SearchQuerySetQuery) Valid(validation *validation.Validation) {
  23 + optionsValues := []string{"asc", "desc"}
  24 + if searchQuerySetQuery.SortByName != "" && !utils.InSlice(strings.ToLower(searchQuerySetQuery.SortByName), optionsValues) {
  25 + validation.Error("排序值有误 ASC|DESC")
  26 + }
  27 + if searchQuerySetQuery.SortByTime != "" && !utils.InSlice(strings.ToLower(searchQuerySetQuery.SortByTime), optionsValues) {
  28 + validation.Error("排序值有误 ASC|DESC")
  29 + }
  30 +}
  31 +
  32 +func (searchQuerySetQuery *SearchQuerySetQuery) ValidateQuery() error {
  33 + valid := validation.Validation{}
  34 + b, err := valid.Valid(searchQuerySetQuery)
  35 + if err != nil {
  36 + return err
  37 + }
  38 + if !b {
  39 + elem := reflect.TypeOf(searchQuerySetQuery).Elem()
  40 + for _, validErr := range valid.Errors {
  41 + field, isExist := elem.FieldByName(validErr.Field)
  42 + if isExist {
  43 + return fmt.Errorf(strings.Replace(validErr.Message, validErr.Field, field.Tag.Get("cname"), -1))
  44 + } else {
  45 + return fmt.Errorf(validErr.Message)
  46 + }
  47 + }
  48 + }
  49 + return nil
  50 +}
  1 +package service
  2 +
  3 +import (
  4 + "fmt"
  5 + "github.com/linmadan/egglib-go/core/application"
  6 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/factory"
  7 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/querySet/command"
  8 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/table/dto"
  9 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
  10 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/excel"
  11 + "time"
  12 +)
  13 +
  14 +// CalculateSetPreview 计算集预览
  15 +func (querySetService *QuerySetService) CalculateSetPreview(ctx *domain.Context, updateQuerySetCommand *command.UpdateQuerySetCommand) (interface{}, error) {
  16 + if err := updateQuerySetCommand.ValidateCommand(); err != nil {
  17 + return nil, application.ThrowError(application.ARG_ERROR, err.Error())
  18 + }
  19 + transactionContext, err := factory.CreateTransactionContext(nil)
  20 + if err != nil {
  21 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  22 + }
  23 + if err := transactionContext.StartTransaction(); err != nil {
  24 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  25 + }
  26 + defer func() {
  27 + transactionContext.RollbackTransaction()
  28 + }()
  29 +
  30 + var querySet *domain.QuerySet
  31 + _, querySet, err = factory.FastPgQuerySet(transactionContext, updateQuerySetCommand.QuerySetId)
  32 + if err != nil {
  33 + return nil, factory.FastError(err)
  34 + }
  35 +
  36 + svr, _ := factory.FastQuerySetServices(transactionContext)
  37 + var dataTable *domain.DataTable
  38 + dataTable, err = svr.LoadCalculateSetData(ctx, querySet, updateQuerySetCommand.QueryComponents)
  39 + if err != nil {
  40 + return nil, factory.FastError(err)
  41 + }
  42 + response := (&dto.TablePreviewDto{})
  43 + response.ObjectType = querySet.Type
  44 + response.Name = querySet.Name
  45 + response.Fields = dataTable.Fields
  46 + response.Data = domain.GripData(domain.ToFieldData(dataTable.Fields, dataTable.Data, false, true), int64(len(dataTable.Data)))
  47 +
  48 + if err := transactionContext.CommitTransaction(); err != nil {
  49 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  50 + }
  51 + return response, nil
  52 +}
  53 +
  54 +// CalculateSetExport 计算集导出
  55 +func (querySetService *QuerySetService) CalculateSetExport(ctx *domain.Context, updateQuerySetCommand *command.UpdateQuerySetCommand) (interface{}, error) {
  56 + if err := updateQuerySetCommand.ValidateCommand(); err != nil {
  57 + return nil, application.ThrowError(application.ARG_ERROR, err.Error())
  58 + }
  59 + transactionContext, err := factory.CreateTransactionContext(nil)
  60 + if err != nil {
  61 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  62 + }
  63 + if err := transactionContext.StartTransaction(); err != nil {
  64 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  65 + }
  66 + defer func() {
  67 + transactionContext.RollbackTransaction()
  68 + }()
  69 +
  70 + var querySet *domain.QuerySet
  71 + _, querySet, err = factory.FastPgQuerySet(transactionContext, updateQuerySetCommand.QuerySetId)
  72 + if err != nil {
  73 + return nil, factory.FastError(err)
  74 + }
  75 +
  76 + svr, _ := factory.FastQuerySetServices(transactionContext)
  77 + var dataTable *domain.DataTable
  78 + dataTable, err = svr.LoadCalculateSetData(ctx, querySet, updateQuerySetCommand.QueryComponents)
  79 + if err != nil {
  80 + return nil, factory.FastError(err)
  81 + }
  82 +
  83 + var fields []string
  84 + filename := fmt.Sprintf("%v_%v.xlsx", querySet.Name, time.Now().Format("060102150405"))
  85 + path := fmt.Sprintf("public/%v", filename)
  86 + for _, f := range dataTable.Fields {
  87 + fields = append(fields, f.Name)
  88 + }
  89 + excelWriter := excel.NewXLXSWriterTo(fields, dataTable.Data)
  90 + excelWriter.IgnoreTitle = false
  91 + if err = excelWriter.Save(path); err != nil {
  92 + return nil, factory.FastError(err)
  93 + }
  94 +
  95 + if err := transactionContext.CommitTransaction(); err != nil {
  96 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  97 + }
  98 + return map[string]interface{}{
  99 + "url": domain.DownloadUrl(filename),
  100 + }, err
  101 +}