正在显示
61 个修改的文件
包含
1443 行增加
和
174 行删除
deploy/db/db_script_v14.0.sql
0 → 100644
@@ -4,6 +4,7 @@ go 1.16 | @@ -4,6 +4,7 @@ go 1.16 | ||
4 | 4 | ||
5 | require ( | 5 | require ( |
6 | github.com/ajg/form v1.5.1 // indirect | 6 | github.com/ajg/form v1.5.1 // indirect |
7 | + github.com/aliyun/aliyun-oss-go-sdk v2.2.7+incompatible // indirect | ||
7 | github.com/beego/beego/v2 v2.0.1 | 8 | github.com/beego/beego/v2 v2.0.1 |
8 | github.com/bwmarrin/snowflake v0.3.0 | 9 | github.com/bwmarrin/snowflake v0.3.0 |
9 | github.com/dgrijalva/jwt-go v3.2.0+incompatible | 10 | github.com/dgrijalva/jwt-go v3.2.0+incompatible |
1 | +package service | ||
2 | + | ||
3 | +import ( | ||
4 | + "github.com/linmadan/egglib-go/core/application" | ||
5 | + pgTransaction "github.com/linmadan/egglib-go/transaction/pg" | ||
6 | + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/event/command" | ||
7 | + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/factory" | ||
8 | + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain" | ||
9 | + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/cache" | ||
10 | + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/domainService" | ||
11 | +) | ||
12 | + | ||
13 | +func (tableEventService *TableEventService) DigitalPlatformEventSubscribe(ctx *domain.Context, cmd *command.TableEventCommand) (interface{}, error) { | ||
14 | + transactionContext, err := factory.CreateTransactionContext(nil) | ||
15 | + if err != nil { | ||
16 | + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) | ||
17 | + } | ||
18 | + //if err := transactionContext.StartTransaction(); err != nil { | ||
19 | + // return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) | ||
20 | + //} | ||
21 | + //defer func() { | ||
22 | + // transactionContext.RollbackTransaction() | ||
23 | + //}() | ||
24 | + | ||
25 | + var ( | ||
26 | + dataChanged = true | ||
27 | + structChanged = true | ||
28 | + ) | ||
29 | + | ||
30 | + data := cmd.EventTable | ||
31 | + tableId := 0 | ||
32 | + switch data.Type { | ||
33 | + case domain.TableDataImportEvent, domain.TableDataEditEvent, domain.TableDeleteEvent: | ||
34 | + // dataChanged = true | ||
35 | + tableId = data.Table.TableId | ||
36 | + case domain.QuerySetUpdateEvent: | ||
37 | + tableId = data.QuerySet.QuerySetInfo.BindTableId | ||
38 | + // structChanged = true | ||
39 | + } | ||
40 | + if tableId == 0 { | ||
41 | + return nil, nil | ||
42 | + } | ||
43 | + var notifyData = struct { | ||
44 | + DataChanged bool `json:"dataChanged"` | ||
45 | + StructChanged bool `json:"structChanged"` | ||
46 | + TableId int `json:"tableId"` | ||
47 | + Event string `json:"event"` | ||
48 | + TableAffectedList []int `json:"tableAffectedList"` | ||
49 | + }{ | ||
50 | + DataChanged: dataChanged, | ||
51 | + StructChanged: structChanged, | ||
52 | + TableId: tableId, | ||
53 | + Event: data.Type.ToString(), | ||
54 | + } | ||
55 | + // tableId 相关联的 | ||
56 | + tableRepository, _, _ := factory.FastPgTable(transactionContext, 0) | ||
57 | + _, tables, err := tableRepository.Find(map[string]interface{}{"context": data.Context, "tableTypesNotIn": []string{domain.TemporaryTable.ToString(), domain.ExcelTable.ToString()}}) | ||
58 | + if err != nil { | ||
59 | + return nil, err | ||
60 | + } | ||
61 | + | ||
62 | + tableDependencyService, _ := domainService.NewTableDependencyService(transactionContext.(*pgTransaction.TransactionContext)) | ||
63 | + tableDependTree := tableDependencyService.TableDependTree(tables, tableId) | ||
64 | + tree := tableDependTree.Tree | ||
65 | + | ||
66 | + //tableService := tableservice.NewTableService(nil) | ||
67 | + for i := range tree { | ||
68 | + cache.DefaultDataTableCacheService.DeleteDataTable(tree[i]) | ||
69 | + // fresh cache | ||
70 | + //tableService.TablePreview(data.Context, &tablecommand.TablePreviewCommand{ | ||
71 | + // TableId: tree[i], | ||
72 | + // ObjectType: domain.ObjectMetaTable, | ||
73 | + // PageSize: 10000, | ||
74 | + // PageNumber: 0, | ||
75 | + // UseCache: true, | ||
76 | + //}) | ||
77 | + notifyData.TableAffectedList = append(notifyData.TableAffectedList, tree[i]) | ||
78 | + } | ||
79 | + | ||
80 | + //if err := transactionContext.CommitTransaction(); err != nil { | ||
81 | + // return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) | ||
82 | + //} | ||
83 | + return nil, nil | ||
84 | +} |
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 | +} |
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 | +} |
@@ -17,6 +17,10 @@ type CreateFileCommand struct { | @@ -17,6 +17,10 @@ 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:"-"` | ||
20 | } | 24 | } |
21 | 25 | ||
22 | var MaxFileSize = 50 * 1024 * 1024 | 26 | var MaxFileSize = 50 * 1024 * 1024 |
@@ -15,6 +15,7 @@ type EditDataTableCommand struct { | @@ -15,6 +15,7 @@ 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) { |
@@ -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 { |
@@ -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 | + "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 | +} |
@@ -18,6 +18,10 @@ type FileDto struct { | @@ -18,6 +18,10 @@ type FileDto struct { | ||
18 | Ext string `json:"ext"` | 18 | Ext string `json:"ext"` |
19 | // 创建时间 | 19 | // 创建时间 |
20 | Time string `json:"time"` | 20 | Time string `json:"time"` |
21 | + // 行号 | ||
22 | + HeaderRow int `json:"headerRow"` | ||
23 | + // 所属应用 | ||
24 | + AppKey string `json:"appKey"` | ||
21 | } | 25 | } |
22 | 26 | ||
23 | func (d *FileDto) Load(f *domain.File) *FileDto { | 27 | func (d *FileDto) Load(f *domain.File) *FileDto { |
@@ -30,5 +34,14 @@ func (d *FileDto) Load(f *domain.File) *FileDto { | @@ -30,5 +34,14 @@ func (d *FileDto) Load(f *domain.File) *FileDto { | ||
30 | d.FileType = f.FileType | 34 | d.FileType = f.FileType |
31 | d.Ext = f.FileInfo.Ext | 35 | d.Ext = f.FileInfo.Ext |
32 | d.Time = xtime.New(f.UpdatedAt).Local().Format("2006-01-02 15:04:05") | 36 | d.Time = xtime.New(f.UpdatedAt).Local().Format("2006-01-02 15:04:05") |
37 | + d.HeaderRow = domain.GetHeaderRow(f.FileInfo.HeaderRow) | ||
38 | + d.AppKey = f.AppKey | ||
33 | return d | 39 | return d |
34 | } | 40 | } |
41 | + | ||
42 | +type AppDto struct { | ||
43 | + AppId int64 `json:"appId"` | ||
44 | + AppKey string `json:"appKey"` | ||
45 | + AppName string `json:"appName"` | ||
46 | + Files []*FileDto `json:"files"` | ||
47 | +} |
@@ -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 | + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/factory" | ||
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/query" | ||
12 | + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/constant" | ||
13 | + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain" | ||
14 | + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/api/apilib" | ||
15 | + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/excel" | ||
16 | + "os" | ||
17 | + "strings" | ||
18 | + "time" | ||
19 | +) | ||
20 | + | ||
21 | +func (fileService *FileService) CreateAppTableFile(ctx *domain.Context, cmd *command.CreateAppTableFileCommand) (*command.CreateFileCommand, error) { | ||
22 | + response := &command.CreateFileCommand{} | ||
23 | + var ( | ||
24 | + titles = make([]string, 0) | ||
25 | + dataList = make([][]string, 0) | ||
26 | + ) | ||
27 | + for _, filed := range cmd.Fields { | ||
28 | + titles = append(titles, filed.Name) | ||
29 | + } | ||
30 | + for i := range cmd.Data { | ||
31 | + row := make([]string, 0) | ||
32 | + for _, filed := range titles { | ||
33 | + if v, ok := cmd.Data[i][filed]; ok { | ||
34 | + row = append(row, v) | ||
35 | + } else { | ||
36 | + row = append(row, "") | ||
37 | + } | ||
38 | + } | ||
39 | + dataList = append(dataList, row) | ||
40 | + } | ||
41 | + fileUpload, err := saveFile(cmd.Name, titles, dataList, nil) | ||
42 | + if err != nil { | ||
43 | + return nil, factory.FastError(err) | ||
44 | + } | ||
45 | + response.Name = cmd.Name | ||
46 | + if !strings.HasSuffix(response.Name, domain.XLSX) { | ||
47 | + response.Name = response.Name + domain.XLSX | ||
48 | + } | ||
49 | + response.Url = fileUpload.Url | ||
50 | + response.FileSize = int(fileUpload.FileSize) | ||
51 | + response.FileFrom = domain.FileFromDigitalAppClient | ||
52 | + return response, nil | ||
53 | +} | ||
54 | + | ||
55 | +func saveFile(name string, title []string, dataList [][]string, toInterfaces func([]string) []interface{}) (FileUpload, error) { | ||
56 | + var ( | ||
57 | + response = FileUpload{} | ||
58 | + err error | ||
59 | + ) | ||
60 | + var writerTo = excel.NewXLXSWriterTo(title, dataList) | ||
61 | + if toInterfaces != nil { | ||
62 | + writerTo.ToInterfaces = toInterfaces | ||
63 | + } | ||
64 | + filename := fmt.Sprintf("%v_%v.xlsx", name, time.Now().Format("060102150405")) | ||
65 | + path := fmt.Sprintf("public/%v", filename) | ||
66 | + if err = writerTo.Save(path); err != nil { | ||
67 | + return response, factory.FastError(err) | ||
68 | + } | ||
69 | + api := apilib.NewApiAuthLib(constant.OPEN_API_HOST) | ||
70 | + uploadResponse, err := api.Upload(apilib.RequestUpload{ | ||
71 | + UploadFileMap: map[string]string{"file": path}, | ||
72 | + }) | ||
73 | + if err != nil { | ||
74 | + return response, err | ||
75 | + } | ||
76 | + if stat, err := os.Stat(path); err == nil { | ||
77 | + response.FileSize = stat.Size() | ||
78 | + } | ||
79 | + response.Url = uploadResponse.Path | ||
80 | + response.FileName = name | ||
81 | + response.Ext = domain.XLSX | ||
82 | + | ||
83 | + return response, nil | ||
84 | +} | ||
85 | + | ||
86 | +type FileUpload struct { | ||
87 | + Url string `json:"url"` | ||
88 | + Ext string `json:"ext"` | ||
89 | + FileName string `json:"fileName"` | ||
90 | + FileSize int64 `json:"fileSize"` | ||
91 | +} | ||
92 | + | ||
93 | +func (fileService *FileService) DeleteAppTableFile(ctx *domain.Context, cmd *command.DeleteAppTableFileCommand) (interface{}, error) { | ||
94 | + //if err := cmd.ValidateCommand(); err != nil { | ||
95 | + // return nil, application.ThrowError(application.ARG_ERROR, err.Error()) | ||
96 | + //} | ||
97 | + transactionContext, err := factory.CreateTransactionContext(nil) | ||
98 | + if err != nil { | ||
99 | + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) | ||
100 | + } | ||
101 | + if err := transactionContext.StartTransaction(); err != nil { | ||
102 | + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) | ||
103 | + } | ||
104 | + defer func() { | ||
105 | + transactionContext.RollbackTransaction() | ||
106 | + }() | ||
107 | + | ||
108 | + fileRepository, file, _ := factory.FastPgFile(transactionContext, 0) | ||
109 | + file, err = fileRepository.FindOne(map[string]interface{}{"appKey": cmd.AppKey, "fileName": cmd.Name, "fileType": domain.SourceFile}) | ||
110 | + if err == domain.ErrorNotFound { | ||
111 | + return nil, factory.FastError(errors.New("文件不存在")) | ||
112 | + } | ||
113 | + if err != nil { | ||
114 | + return nil, factory.FastError(err) | ||
115 | + } | ||
116 | + if _, err := fileRepository.Remove(file); err != nil { | ||
117 | + return nil, factory.FastError(err) | ||
118 | + } | ||
119 | + if err := transactionContext.CommitTransaction(); err != nil { | ||
120 | + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) | ||
121 | + } | ||
122 | + return struct{}{}, nil | ||
123 | +} | ||
124 | + | ||
125 | +func (fileService *FileService) AppTableFileAppendData(ctx *domain.Context, cmd *command.AppTableFileAppendDataCommand) (interface{}, error) { | ||
126 | + //if err := cmd.ValidateCommand(); err != nil { | ||
127 | + // return nil, application.ThrowError(application.ARG_ERROR, err.Error()) | ||
128 | + //} | ||
129 | + transactionContext, err := factory.CreateTransactionContext(nil) | ||
130 | + if err != nil { | ||
131 | + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) | ||
132 | + } | ||
133 | + if err := transactionContext.StartTransaction(); err != nil { | ||
134 | + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) | ||
135 | + } | ||
136 | + defer func() { | ||
137 | + transactionContext.RollbackTransaction() | ||
138 | + }() | ||
139 | + | ||
140 | + fileRepository, file, _ := factory.FastPgFile(transactionContext, 0) | ||
141 | + file, err = fileRepository.FindOne(map[string]interface{}{"appKey": cmd.AppKey, "fileName": cmd.Name, "fileType": domain.SourceFile}) | ||
142 | + if err == domain.ErrorNotFound { | ||
143 | + return nil, factory.FastError(errors.New("文件不存在")) | ||
144 | + } | ||
145 | + if err != nil { | ||
146 | + return nil, factory.FastError(err) | ||
147 | + } | ||
148 | + | ||
149 | + // 下载文件 | ||
150 | + f, err := httplib.Get(domain.ConvertFileUrlToInternal(file.FileInfo.Url)).Bytes() | ||
151 | + if err != nil { | ||
152 | + return nil, factory.FastError(err) | ||
153 | + } | ||
154 | + reader := bytes.NewReader(f) | ||
155 | + var importer *excel.Importer = excel.NewExcelImportByFile(file.FileInfo.Ext) | ||
156 | + data, err := importer.OpenExcelFromIoReader(reader) | ||
157 | + if err != nil { | ||
158 | + return nil, factory.FastError(err) | ||
159 | + } | ||
160 | + titles := importer.Reader().Header().Columns | ||
161 | + for _, f := range cmd.Fields { | ||
162 | + found := false | ||
163 | + for _, column := range titles { | ||
164 | + if column == f.Name { | ||
165 | + found = true | ||
166 | + break | ||
167 | + } | ||
168 | + } | ||
169 | + if !found { | ||
170 | + titles = append(titles, f.Name) | ||
171 | + } | ||
172 | + } | ||
173 | + // 填充旧数据 | ||
174 | + // 追加文件 | ||
175 | + for i := range data { | ||
176 | + if len(data[i]) < len(titles) { | ||
177 | + for j := 0; j < (len(titles) - len(data[i])); j++ { | ||
178 | + data[i] = append(data[i], "") | ||
179 | + } | ||
180 | + } | ||
181 | + } | ||
182 | + for i := range cmd.Data { | ||
183 | + row := make([]string, 0) | ||
184 | + for _, filed := range titles { | ||
185 | + if v, ok := cmd.Data[i][filed]; ok { | ||
186 | + row = append(row, v) | ||
187 | + } else { | ||
188 | + row = append(row, "") | ||
189 | + } | ||
190 | + } | ||
191 | + data = append(data, row) | ||
192 | + } | ||
193 | + | ||
194 | + // 上传文件 | ||
195 | + fileUpload, err := saveFile(cmd.Name, titles, data, nil) | ||
196 | + if err != nil { | ||
197 | + return nil, factory.FastError(err) | ||
198 | + } | ||
199 | + | ||
200 | + // 更新文件 | ||
201 | + file.FileInfo.Url = fileUpload.Url | ||
202 | + file.FileInfo.FileSize = int(fileUpload.FileSize) | ||
203 | + file.FileInfo.RowCount = len(data) | ||
204 | + _, err = fileRepository.Save(file) | ||
205 | + if err != nil { | ||
206 | + return nil, factory.FastError(err) | ||
207 | + } | ||
208 | + | ||
209 | + if err := transactionContext.CommitTransaction(); err != nil { | ||
210 | + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) | ||
211 | + } | ||
212 | + return struct{}{}, nil | ||
213 | +} | ||
214 | + | ||
215 | +func (fileService *FileService) AppTableFileList(ctx *domain.Context, cmd *query.ListAppTableFileCommand) (interface{}, error) { | ||
216 | + return fileService.GetAppFile(ctx, cmd.AppKey, cmd.Name) | ||
217 | +} |
@@ -4,14 +4,14 @@ import ( | @@ -4,14 +4,14 @@ import ( | ||
4 | "bytes" | 4 | "bytes" |
5 | "fmt" | 5 | "fmt" |
6 | "github.com/beego/beego/v2/client/httplib" | 6 | "github.com/beego/beego/v2/client/httplib" |
7 | - "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/excel" | ||
8 | - "time" | ||
9 | - | ||
10 | "github.com/linmadan/egglib-go/core/application" | 7 | "github.com/linmadan/egglib-go/core/application" |
8 | + "github.com/linmadan/egglib-go/transaction/pg" | ||
11 | "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" |
12 | "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" |
13 | "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/file/dto" | 11 | "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/file/dto" |
14 | "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" | 15 | "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/redis" |
16 | ) | 16 | ) |
17 | 17 | ||
@@ -44,6 +44,54 @@ func (fileService *FileService) FilePreview(ctx *domain.Context, loadDataTableCo | @@ -44,6 +44,54 @@ func (fileService *FileService) FilePreview(ctx *domain.Context, loadDataTableCo | ||
44 | return data, nil | 44 | return data, nil |
45 | } | 45 | } |
46 | 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 | + | ||
47 | // PrepareTemporaryFile 准备临时文件 | 95 | // PrepareTemporaryFile 准备临时文件 |
48 | func (fileService *FileService) PrepareTemporaryFile(ctx *domain.Context, cmd *command.PrepareTemporaryFileCommand) (interface{}, error) { | 96 | func (fileService *FileService) PrepareTemporaryFile(ctx *domain.Context, cmd *command.PrepareTemporaryFileCommand) (interface{}, error) { |
49 | if err := cmd.ValidateCommand(); err != nil { | 97 | if err := cmd.ValidateCommand(); err != nil { |
@@ -104,6 +152,13 @@ func (fileService *FileService) EditDataTable(ctx *domain.Context, editDataTable | @@ -104,6 +152,13 @@ func (fileService *FileService) EditDataTable(ctx *domain.Context, editDataTable | ||
104 | if editDataTableCommand.Action == "remove-column" && len(temporaryFile.Fields) == len(editDataTableCommand.ProcessFields) { | 152 | if editDataTableCommand.Action == "remove-column" && len(temporaryFile.Fields) == len(editDataTableCommand.ProcessFields) { |
105 | return nil, factory.FastError(fmt.Errorf("请至少保留一个数据列")) | 153 | return nil, factory.FastError(fmt.Errorf("请至少保留一个数据列")) |
106 | } | 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 | + } | ||
107 | // allowAction := func(fields []*domain.Field, action string) error { | 162 | // allowAction := func(fields []*domain.Field, action string) error { |
108 | // for _, f := range fields { | 163 | // for _, f := range fields { |
109 | // if f.SQLType != string(domain.String) && | 164 | // if f.SQLType != string(domain.String) && |
@@ -148,10 +203,14 @@ func (fileService *FileService) FlushDataTable(ctx *domain.Context, flushDataTab | @@ -148,10 +203,14 @@ func (fileService *FileService) FlushDataTable(ctx *domain.Context, flushDataTab | ||
148 | if err != nil { | 203 | if err != nil { |
149 | return nil, factory.FastError(err) | 204 | return nil, factory.FastError(err) |
150 | } | 205 | } |
206 | + if err = temporaryFile.Valid(); err != nil { | ||
207 | + return nil, factory.FastError(err) | ||
208 | + } | ||
151 | 209 | ||
152 | if _, err := flushDataTableService.Flush(ctx, flushDataTableCommand.ObjectId, &domain.Table{ | 210 | if _, err := flushDataTableService.Flush(ctx, flushDataTableCommand.ObjectId, &domain.Table{ |
153 | DataFields: temporaryFile.Fields, | 211 | DataFields: temporaryFile.Fields, |
154 | RowCount: temporaryFile.Total, | 212 | RowCount: temporaryFile.Total, |
213 | + HeaderRow: temporaryFile.HeaderRow, | ||
155 | }); err != nil { | 214 | }); err != nil { |
156 | return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error()) | 215 | return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error()) |
157 | } | 216 | } |
@@ -266,11 +325,7 @@ func (fileService *FileService) ExportFile(ctx *domain.Context, cmd *command.Exp | @@ -266,11 +325,7 @@ func (fileService *FileService) ExportFile(ctx *domain.Context, cmd *command.Exp | ||
266 | return nil, factory.FastError(err) | 325 | return nil, factory.FastError(err) |
267 | } | 326 | } |
268 | 327 | ||
269 | - var response = struct { | ||
270 | - Url string `json:"url"` | ||
271 | - Ext string `json:"ext"` | ||
272 | - FileName string `json:"fileName"` | ||
273 | - }{} | 328 | + var response = FileUpload{} |
274 | if file.FileType == domain.SourceFile.ToString() { | 329 | if file.FileType == domain.SourceFile.ToString() { |
275 | response.Url = file.FileInfo.Url | 330 | response.Url = file.FileInfo.Url |
276 | response.Ext = domain.XLSX | 331 | response.Ext = domain.XLSX |
@@ -282,7 +337,7 @@ func (fileService *FileService) ExportFile(ctx *domain.Context, cmd *command.Exp | @@ -282,7 +337,7 @@ func (fileService *FileService) ExportFile(ctx *domain.Context, cmd *command.Exp | ||
282 | return nil, factory.FastError(err) | 337 | return nil, factory.FastError(err) |
283 | } | 338 | } |
284 | 339 | ||
285 | - f, err := httplib.Get(file.FileInfo.Url).Bytes() | 340 | + f, err := httplib.Get(domain.ConvertFileUrlToInternal(file.FileInfo.Url)).Bytes() |
286 | if err != nil { | 341 | if err != nil { |
287 | return nil, factory.FastError(err) | 342 | return nil, factory.FastError(err) |
288 | } | 343 | } |
@@ -292,17 +347,46 @@ func (fileService *FileService) ExportFile(ctx *domain.Context, cmd *command.Exp | @@ -292,17 +347,46 @@ func (fileService *FileService) ExportFile(ctx *domain.Context, cmd *command.Exp | ||
292 | if err != nil { | 347 | if err != nil { |
293 | return nil, factory.FastError(err) | 348 | return nil, factory.FastError(err) |
294 | } | 349 | } |
295 | - filename := fmt.Sprintf("%v_%v.xlsx", file.FileInfo.Name, time.Now().Format("060102150405")) | ||
296 | - path := fmt.Sprintf("public/%v", filename) | ||
297 | - writerTo := excel.NewXLXSWriterTo(importer.Reader().Header().Columns, data) | ||
298 | - writerTo.ToInterfaces = domain.MakeToInterfaces(table.DataFields) | ||
299 | - if err := writerTo.Save(path); err != nil { | 350 | + |
351 | + response, err = saveFile(file.FileInfo.Name, importer.Reader().Header().Columns, data, domain.MakeToInterfaces(table.DataFields)) | ||
352 | + if err != nil { | ||
300 | return nil, factory.FastError(err) | 353 | return nil, factory.FastError(err) |
301 | } | 354 | } |
302 | - | ||
303 | - response.Url = domain.DownloadUrl(filename) | ||
304 | - response.FileName = file.FileInfo.Name | ||
305 | - response.Ext = domain.XLSX | 355 | + //filename := fmt.Sprintf("%v_%v.xlsx", file.FileInfo.Name, time.Now().Format("060102150405")) |
356 | + //path := fmt.Sprintf("public/%v", filename) | ||
357 | + //writerTo := excel.NewXLXSWriterTo(importer.Reader().Header().Columns, data) | ||
358 | + //writerTo.ToInterfaces = domain.MakeToInterfaces(table.DataFields) | ||
359 | + //if err := writerTo.Save(path); err != nil { | ||
360 | + // return nil, factory.FastError(err) | ||
361 | + //} | ||
362 | + // | ||
363 | + //var ( | ||
364 | + // config = utils.RouterConfig{ | ||
365 | + // OssEndPoint: "oss-cn-hangzhou.aliyuncs-internal.com", | ||
366 | + // AccessKeyID: "LTAI4Fz1LUBW2fXp6QWaJHRS", | ||
367 | + // AccessKeySecret: "aLZXwK8pgrs10Ws03qcN7NsrSXFVsg", | ||
368 | + // BuckName: "byte-bank", | ||
369 | + // } | ||
370 | + // key = fmt.Sprintf("byte-bank/%v/%v", time.Now().Format("2006-01-02"), filename) | ||
371 | + //) | ||
372 | + //bucket, bucketErr := utils.NewBucket(config) | ||
373 | + //if bucketErr == nil && bucket != nil { | ||
374 | + // log.Logger.Info(fmt.Sprintf("end-point:%v key:%v", config.OssEndPoint, key)) | ||
375 | + // f, _ := os.Open(path) | ||
376 | + // if err = utils.CreateObjects(bucket, utils.Object{ | ||
377 | + // Key: key, | ||
378 | + // Value: f, | ||
379 | + // }); err != nil { | ||
380 | + // log.Logger.Error(err.Error()) | ||
381 | + // } else { | ||
382 | + // response.Url = domain.ConvertInternalFileUrlToPublic(fmt.Sprintf("https://%v.%v/%v", config.BuckName, config.OssEndPoint, key)) | ||
383 | + // } | ||
384 | + //} | ||
385 | + //if len(response.Url) == 0 { | ||
386 | + // response.Url = domain.DownloadUrl(filename) | ||
387 | + //} | ||
388 | + //response.FileName = file.FileInfo.Name | ||
389 | + //response.Ext = domain.XLSX | ||
306 | 390 | ||
307 | if err := transactionContext.CommitTransaction(); err != nil { | 391 | if err := transactionContext.CommitTransaction(); err != nil { |
308 | return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) | 392 | return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) |
@@ -2,7 +2,10 @@ package service | @@ -2,7 +2,10 @@ 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" | ||
5 | "path/filepath" | 7 | "path/filepath" |
8 | + "strings" | ||
6 | "time" | 9 | "time" |
7 | 10 | ||
8 | "github.com/linmadan/egglib-go/core/application" | 11 | "github.com/linmadan/egglib-go/core/application" |
@@ -49,6 +52,8 @@ func (fileService *FileService) CreateFile(ctx *domain.Context, createFileComman | @@ -49,6 +52,8 @@ func (fileService *FileService) CreateFile(ctx *domain.Context, createFileComman | ||
49 | CreatedAt: time.Now(), | 52 | CreatedAt: time.Now(), |
50 | UpdatedAt: time.Now(), | 53 | UpdatedAt: time.Now(), |
51 | Context: ctx, | 54 | Context: ctx, |
55 | + FileFrom: createFileCommand.FileFrom, | ||
56 | + AppKey: createFileCommand.AppKey, | ||
52 | } | 57 | } |
53 | fileRepository, _, _ := factory.FastPgFile(transactionContext, 0) | 58 | fileRepository, _, _ := factory.FastPgFile(transactionContext, 0) |
54 | 59 | ||
@@ -213,6 +218,126 @@ func (fileService *FileService) SearchFile(listFileQuery *query.SearchFileQuery) | @@ -213,6 +218,126 @@ func (fileService *FileService) SearchFile(listFileQuery *query.SearchFileQuery) | ||
213 | }, nil | 218 | }, nil |
214 | } | 219 | } |
215 | 220 | ||
221 | +// 返回文件服务列表 | ||
222 | +func (fileService *FileService) SearchAppFile(ctx *domain.Context, listFileQuery *query.SearchFileQuery) (interface{}, error) { | ||
223 | + if err := listFileQuery.ValidateQuery(); err != nil { | ||
224 | + return nil, application.ThrowError(application.ARG_ERROR, err.Error()) | ||
225 | + } | ||
226 | + transactionContext, err := factory.CreateTransactionContext(nil) | ||
227 | + if err != nil { | ||
228 | + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) | ||
229 | + } | ||
230 | + if err := transactionContext.StartTransaction(); err != nil { | ||
231 | + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) | ||
232 | + } | ||
233 | + defer func() { | ||
234 | + transactionContext.RollbackTransaction() | ||
235 | + }() | ||
236 | + var fileRepository, _, _ = factory.FastPgFile(transactionContext, 0) | ||
237 | + | ||
238 | + apiAuthLib := authlib.NewApiAuthLib(constant.AUTH_SERVER_HOST).WithToken(ctx.AccessToken) | ||
239 | + response, err := apiAuthLib.MeAppInfo(authlib.RequestUserMeQuery{UserId: ctx.TenantId}) | ||
240 | + if err != nil { | ||
241 | + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error()) | ||
242 | + } | ||
243 | + inAppKeys := make([]string, 0) | ||
244 | + for _, app := range response.Apps { | ||
245 | + inAppKeys = append(inAppKeys, app.AppKey) | ||
246 | + } | ||
247 | + var ( | ||
248 | + fileDtos = make([]*dto.FileDto, 0) | ||
249 | + total int64 | ||
250 | + ) | ||
251 | + if len(inAppKeys) > 0 { | ||
252 | + queryOptions := utils.ObjectToMap(listFileQuery) | ||
253 | + queryOptions["inAppKeys"] = inAppKeys | ||
254 | + queryOptions["limit"] = 1000 | ||
255 | + queryOptions["fileName"] = listFileQuery.FileName | ||
256 | + count, files, err := fileRepository.Find(queryOptions) | ||
257 | + if err != nil { | ||
258 | + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error()) | ||
259 | + } | ||
260 | + for _, file := range files { | ||
261 | + var item = &dto.FileDto{} | ||
262 | + item.Load(file) | ||
263 | + fileDtos = append(fileDtos, item) | ||
264 | + } | ||
265 | + total = count | ||
266 | + } | ||
267 | + var apps = make([]*dto.AppDto, 0) | ||
268 | + for _, app := range response.Apps { | ||
269 | + if len(listFileQuery.FileName) > 0 && !strings.Contains(app.AppName, listFileQuery.FileName) { | ||
270 | + continue | ||
271 | + } | ||
272 | + files := make([]*dto.FileDto, 0) | ||
273 | + for _, file := range fileDtos { | ||
274 | + if file.AppKey == app.AppKey { | ||
275 | + files = append(files, file) | ||
276 | + } | ||
277 | + } | ||
278 | + apps = append(apps, &dto.AppDto{ | ||
279 | + AppId: app.AppId, | ||
280 | + AppKey: app.AppKey, | ||
281 | + AppName: app.AppName, | ||
282 | + Files: files, | ||
283 | + }) | ||
284 | + } | ||
285 | + | ||
286 | + if err := transactionContext.CommitTransaction(); err != nil { | ||
287 | + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) | ||
288 | + } | ||
289 | + return map[string]interface{}{ | ||
290 | + "apps": apps, | ||
291 | + "count": total, | ||
292 | + }, nil | ||
293 | +} | ||
294 | + | ||
295 | +// GetAppFile 返回应用对应的文件服务列表 | ||
296 | +func (fileService *FileService) GetAppFile(ctx *domain.Context, appKey string, fileName string) (interface{}, error) { | ||
297 | + transactionContext, err := factory.CreateTransactionContext(nil) | ||
298 | + if err != nil { | ||
299 | + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) | ||
300 | + } | ||
301 | + if err := transactionContext.StartTransaction(); err != nil { | ||
302 | + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) | ||
303 | + } | ||
304 | + defer func() { | ||
305 | + transactionContext.RollbackTransaction() | ||
306 | + }() | ||
307 | + var fileRepository, _, _ = factory.FastPgFile(transactionContext, 0) | ||
308 | + | ||
309 | + var ( | ||
310 | + fileDtos = make([]*dto.FileDto, 0) | ||
311 | + total int64 | ||
312 | + ) | ||
313 | + | ||
314 | + queryOptions := make(map[string]interface{}) | ||
315 | + queryOptions["fileType"] = domain.SourceFile | ||
316 | + queryOptions["inAppKeys"] = []string{appKey} | ||
317 | + queryOptions["limit"] = 100 | ||
318 | + count, files, err := fileRepository.Find(queryOptions) | ||
319 | + if err != nil { | ||
320 | + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error()) | ||
321 | + } | ||
322 | + for _, file := range files { | ||
323 | + var item = &dto.FileDto{} | ||
324 | + if fileName != "" && file.FileInfo.Name != fileName { | ||
325 | + continue | ||
326 | + } | ||
327 | + item.Load(file) | ||
328 | + fileDtos = append(fileDtos, item) | ||
329 | + } | ||
330 | + total = count | ||
331 | + | ||
332 | + if err := transactionContext.CommitTransaction(); err != nil { | ||
333 | + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) | ||
334 | + } | ||
335 | + return map[string]interface{}{ | ||
336 | + "count": total, | ||
337 | + "files": fileDtos, | ||
338 | + }, nil | ||
339 | +} | ||
340 | + | ||
216 | // 移除文件服务 | 341 | // 移除文件服务 |
217 | func (fileService *FileService) RemoveFile(ctx *domain.Context, removeFileCommand *command.RemoveFileCommand) (interface{}, error) { | 342 | func (fileService *FileService) RemoveFile(ctx *domain.Context, removeFileCommand *command.RemoveFileCommand) (interface{}, error) { |
218 | if err := removeFileCommand.ValidateCommand(); err != nil { | 343 | if err := removeFileCommand.ValidateCommand(); err != nil { |
@@ -17,10 +17,11 @@ type TablePreviewCommand struct { | @@ -17,10 +17,11 @@ type TablePreviewCommand struct { | ||
17 | PageSize int `json:"pageSize"` | 17 | PageSize int `json:"pageSize"` |
18 | Where domain.Where `json:"where"` | 18 | Where domain.Where `json:"where"` |
19 | UseCache bool `json:"useCache"` | 19 | UseCache bool `json:"useCache"` |
20 | + HiddenData bool `json:"hiddenData"` // 隐藏数据,只返回结构 | ||
20 | } | 21 | } |
21 | 22 | ||
22 | func (cmd *TablePreviewCommand) Valid(validation *validation.Validation) { | 23 | func (cmd *TablePreviewCommand) Valid(validation *validation.Validation) { |
23 | - if cmd.UseCache && cmd.PageSize == 0 { | 24 | + if cmd.UseCache && cmd.PageSize == 0 && cmd.Where.PageSize == 0 { |
24 | cmd.PageNumber = 1 | 25 | cmd.PageNumber = 1 |
25 | cmd.PageSize = 30000 //默认缓存前30000条 | 26 | cmd.PageSize = 30000 //默认缓存前30000条 |
26 | } | 27 | } |
@@ -16,6 +16,7 @@ type TablePreviewDto struct { | @@ -16,6 +16,7 @@ type TablePreviewDto struct { | ||
16 | Fields []*domain.Field `json:"fields"` | 16 | Fields []*domain.Field `json:"fields"` |
17 | Data interface{} `json:"grid"` | 17 | Data interface{} `json:"grid"` |
18 | //Total int64 `json:"total"` | 18 | //Total int64 `json:"total"` |
19 | + HiddenData bool `json:"-"` | ||
19 | } | 20 | } |
20 | 21 | ||
21 | func (d *TablePreviewDto) Load(m *domain.Table, dataTable *domain.DataTable, objectType string) *TablePreviewDto { | 22 | func (d *TablePreviewDto) Load(m *domain.Table, dataTable *domain.DataTable, objectType string) *TablePreviewDto { |
@@ -26,6 +27,12 @@ func (d *TablePreviewDto) Load(m *domain.Table, dataTable *domain.DataTable, obj | @@ -26,6 +27,12 @@ func (d *TablePreviewDto) Load(m *domain.Table, dataTable *domain.DataTable, obj | ||
26 | d.Fields = dataTable.MatchFields(m.Fields(true)) | 27 | d.Fields = dataTable.MatchFields(m.Fields(true)) |
27 | d.Data = domain.GripData(domain.ToFieldData(m.Fields(true), dataTable.Data, false), dataTable.Total) | 28 | d.Data = domain.GripData(domain.ToFieldData(m.Fields(true), dataTable.Data, false), dataTable.Total) |
28 | //d.Total = dataTable.Total | 29 | //d.Total = dataTable.Total |
30 | + if d.HiddenData { | ||
31 | + d.Data = map[string]interface{}{ | ||
32 | + "list": make([]map[string]string, 0), | ||
33 | + "total": 0, | ||
34 | + } | ||
35 | + } | ||
29 | return d | 36 | return d |
30 | } | 37 | } |
31 | 38 |
@@ -41,6 +41,12 @@ func (searchQuery *SearchTableQuery) Valid(validation *validation.Validation) { | @@ -41,6 +41,12 @@ func (searchQuery *SearchTableQuery) Valid(validation *validation.Validation) { | ||
41 | if searchQuery.ParentTableId > 0 && searchQuery.ParentId == 0 { | 41 | if searchQuery.ParentTableId > 0 && searchQuery.ParentId == 0 { |
42 | searchQuery.ParentId = searchQuery.ParentTableId | 42 | searchQuery.ParentId = searchQuery.ParentTableId |
43 | } | 43 | } |
44 | + if searchQuery.Module == 4 { | ||
45 | + searchQuery.FilterRules = append(searchQuery.FilterRules, &FilterRule{ | ||
46 | + TableType: domain.SchemaTable.ToString(), | ||
47 | + Status: domain.StatusOn, | ||
48 | + }) | ||
49 | + } | ||
44 | } | 50 | } |
45 | 51 | ||
46 | func (searchQuery *SearchTableQuery) ValidateQuery() error { | 52 | func (searchQuery *SearchTableQuery) ValidateQuery() error { |
@@ -117,7 +117,9 @@ func (tableService *TableService) RowsDelete(ctx *domain.Context, cmd *command.R | @@ -117,7 +117,9 @@ func (tableService *TableService) RowsDelete(ctx *domain.Context, cmd *command.R | ||
117 | if err != nil { | 117 | if err != nil { |
118 | return nil, factory.FastError(err) | 118 | return nil, factory.FastError(err) |
119 | } | 119 | } |
120 | - | 120 | + defer func() { |
121 | + domainService.AsyncEvent(domain.NewEventTable(ctx, domain.TableDataEditEvent).WithTable(table)) | ||
122 | + }() | ||
121 | var options = starrocks.QueryOptions{ | 123 | var options = starrocks.QueryOptions{ |
122 | TableName: table.SQLName, | 124 | TableName: table.SQLName, |
123 | Select: []*domain.Field{domain.PK()}, //table.Fields(true), | 125 | Select: []*domain.Field{domain.PK()}, //table.Fields(true), |
@@ -19,12 +19,6 @@ func (tableService *TableService) TableObjectSearch(searchQuery *query.SearchTab | @@ -19,12 +19,6 @@ func (tableService *TableService) TableObjectSearch(searchQuery *query.SearchTab | ||
19 | if err != nil { | 19 | if err != nil { |
20 | return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) | 20 | return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) |
21 | } | 21 | } |
22 | - //if err := transactionContext.StartTransaction(); err != nil { | ||
23 | - // return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) | ||
24 | - //} | ||
25 | - //defer func() { | ||
26 | - // transactionContext.RollbackTransaction() | ||
27 | - //}() | ||
28 | 22 | ||
29 | tableRepository, _, _ := factory.FastPgTable(transactionContext, 0) | 23 | tableRepository, _, _ := factory.FastPgTable(transactionContext, 0) |
30 | _, tables, err := tableRepository.Find(utils.ObjectToMap(searchQuery)) | 24 | _, tables, err := tableRepository.Find(utils.ObjectToMap(searchQuery)) |
@@ -40,7 +34,9 @@ func (tableService *TableService) TableObjectSearch(searchQuery *query.SearchTab | @@ -40,7 +34,9 @@ func (tableService *TableService) TableObjectSearch(searchQuery *query.SearchTab | ||
40 | item.SetDetailStructInfo(table) | 34 | item.SetDetailStructInfo(table) |
41 | } | 35 | } |
42 | item.Flag = domain.FlagSet | 36 | item.Flag = domain.FlagSet |
43 | - if item.TableType == domain.MainTable.ToString() || item.TableType == domain.SubTable.ToString() || item.TableType == domain.SideTable.ToString() { | 37 | + if item.TableType == domain.MainTable.ToString() || |
38 | + item.TableType == domain.SubTable.ToString() || | ||
39 | + item.TableType == domain.SideTable.ToString() { | ||
44 | item.ParentId = 0 | 40 | item.ParentId = 0 |
45 | item.Status = domain.StatusOn | 41 | item.Status = domain.StatusOn |
46 | } | 42 | } |
@@ -55,23 +51,33 @@ func (tableService *TableService) TableObjectSearch(searchQuery *query.SearchTab | @@ -55,23 +51,33 @@ func (tableService *TableService) TableObjectSearch(searchQuery *query.SearchTab | ||
55 | 51 | ||
56 | querySetRepository, _, _ := factory.FastPgQuerySet(transactionContext, 0) | 52 | querySetRepository, _, _ := factory.FastPgQuerySet(transactionContext, 0) |
57 | _, querySets, _ := querySetRepository.Find(map[string]interface{}{"context": searchQuery.Context}) | 53 | _, querySets, _ := querySetRepository.Find(map[string]interface{}{"context": searchQuery.Context}) |
58 | - if !searchQuery.ReturnGroupItem { | ||
59 | - querySets = make([]*domain.QuerySet, 0) | 54 | + |
55 | + var ( | ||
56 | + querySetMapById = make(map[int]*domain.QuerySet) | ||
57 | + // BindTableId , parentId | ||
58 | + querySetMapByTableId = make(map[int]*domain.QuerySet) | ||
59 | + ) | ||
60 | + if searchQuery.ReturnGroupItem { | ||
61 | + for _, qs := range querySets { | ||
62 | + querySetMapById[qs.QuerySetId] = qs | ||
63 | + } | ||
60 | } | 64 | } |
61 | - // BindTableId , parentId | ||
62 | - querySetMapByTableId := make(map[int]*domain.QuerySet) | 65 | + |
63 | for _, qs := range querySets { | 66 | for _, qs := range querySets { |
64 | if qs.QuerySetInfo.BindTableId == 0 { | 67 | if qs.QuerySetInfo.BindTableId == 0 { |
65 | continue | 68 | continue |
66 | } | 69 | } |
67 | querySetMapByTableId[qs.QuerySetInfo.BindTableId] = qs | 70 | querySetMapByTableId[qs.QuerySetInfo.BindTableId] = qs |
68 | } | 71 | } |
69 | - querySetMapById := make(map[int]*domain.QuerySet) | ||
70 | - for _, qs := range querySets { | ||
71 | - querySetMapById[qs.QuerySetId] = qs | ||
72 | - } | ||
73 | 72 | ||
74 | var response = make([]*dto.TableObjectDto, 0) | 73 | var response = make([]*dto.TableObjectDto, 0) |
74 | + for index, t := range result { | ||
75 | + v, ok := querySetMapByTableId[t.TableId] | ||
76 | + if !ok { | ||
77 | + continue | ||
78 | + } | ||
79 | + result[index].Update(v) | ||
80 | + } | ||
75 | // 分组 | 81 | // 分组 |
76 | querySetMapGroup := make(map[int]bool) | 82 | querySetMapGroup := make(map[int]bool) |
77 | querySetGroups := make([]*domain.QuerySet, 0) | 83 | querySetGroups := make([]*domain.QuerySet, 0) |
@@ -79,7 +85,7 @@ func (tableService *TableService) TableObjectSearch(searchQuery *query.SearchTab | @@ -79,7 +85,7 @@ func (tableService *TableService) TableObjectSearch(searchQuery *query.SearchTab | ||
79 | if filterTableByFilterRule(t, searchQuery) { | 85 | if filterTableByFilterRule(t, searchQuery) { |
80 | continue | 86 | continue |
81 | } | 87 | } |
82 | - if !domain.TableType(t.TableType).TableHasGroup() { | 88 | + if !domain.TableType(t.TableType).TableIsSplitByGroup() { |
83 | response = append(response, t) | 89 | response = append(response, t) |
84 | continue | 90 | continue |
85 | } | 91 | } |
@@ -112,9 +118,6 @@ func (tableService *TableService) TableObjectSearch(searchQuery *query.SearchTab | @@ -112,9 +118,6 @@ func (tableService *TableService) TableObjectSearch(searchQuery *query.SearchTab | ||
112 | groupItem.LoadGroup(querySetGroup) | 118 | groupItem.LoadGroup(querySetGroup) |
113 | response = append(response, groupItem) | 119 | response = append(response, groupItem) |
114 | } | 120 | } |
115 | - //if err := transactionContext.CommitTransaction(); err != nil { | ||
116 | - // return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) | ||
117 | - //} | ||
118 | 121 | ||
119 | sort.Slice(response, func(i, j int) bool { | 122 | sort.Slice(response, func(i, j int) bool { |
120 | item1 := response[i] | 123 | item1 := response[i] |
1 | package service | 1 | package service |
2 | 2 | ||
3 | import ( | 3 | import ( |
4 | + "fmt" | ||
4 | "github.com/linmadan/egglib-go/core/application" | 5 | "github.com/linmadan/egglib-go/core/application" |
5 | "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/factory" | 6 | "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/factory" |
6 | "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/table/command" | 7 | "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/table/command" |
@@ -8,6 +9,7 @@ import ( | @@ -8,6 +9,7 @@ import ( | ||
8 | "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain" | 9 | "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain" |
9 | "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/cache" | 10 | "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/cache" |
10 | "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/starrocks" | 11 | "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/starrocks" |
12 | + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/log" | ||
11 | ) | 13 | ) |
12 | 14 | ||
13 | func (tableService *TableService) TablePreview(ctx *domain.Context, cmd *command.TablePreviewCommand) (interface{}, error) { | 15 | func (tableService *TableService) TablePreview(ctx *domain.Context, cmd *command.TablePreviewCommand) (interface{}, error) { |
@@ -21,12 +23,6 @@ func (tableService *TableService) TablePreview(ctx *domain.Context, cmd *command | @@ -21,12 +23,6 @@ func (tableService *TableService) TablePreview(ctx *domain.Context, cmd *command | ||
21 | if err != nil { | 23 | if err != nil { |
22 | return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) | 24 | return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) |
23 | } | 25 | } |
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 | var dataTable *domain.DataTable | 26 | var dataTable *domain.DataTable |
31 | var table *domain.Table | 27 | var table *domain.Table |
32 | var cacheMiss bool | 28 | var cacheMiss bool |
@@ -42,7 +38,7 @@ func (tableService *TableService) TablePreview(ctx *domain.Context, cmd *command | @@ -42,7 +38,7 @@ func (tableService *TableService) TablePreview(ctx *domain.Context, cmd *command | ||
42 | cacheMiss = true | 38 | cacheMiss = true |
43 | } | 39 | } |
44 | } | 40 | } |
45 | - response := &dto.TablePreviewDto{} | 41 | + response := &dto.TablePreviewDto{HiddenData: cmd.HiddenData} |
46 | if dataTable == nil { | 42 | if dataTable == nil { |
47 | switch table.TableType { | 43 | switch table.TableType { |
48 | case domain.CalculateSet.ToString(): | 44 | case domain.CalculateSet.ToString(): |
@@ -57,7 +53,7 @@ func (tableService *TableService) TablePreview(ctx *domain.Context, cmd *command | @@ -57,7 +53,7 @@ func (tableService *TableService) TablePreview(ctx *domain.Context, cmd *command | ||
57 | return nil, factory.FastError(err) | 53 | return nil, factory.FastError(err) |
58 | } | 54 | } |
59 | response.Fields = dataTable.Fields | 55 | response.Fields = dataTable.Fields |
60 | - response.Data = domain.GripData(domain.ToFieldData(dataTable.Fields, dataTable.Data, false), int64(len(dataTable.Data))) | 56 | + response.Data = domain.GripData(domain.ToFieldData(dataTable.Fields, pageData(cmd.Where.PageNumber, cmd.Where.PageSize, dataTable.Data), false), int64(len(dataTable.Data))) |
61 | default: | 57 | default: |
62 | var options = starrocks.QueryOptions{ | 58 | var options = starrocks.QueryOptions{ |
63 | Table: table, | 59 | Table: table, |
@@ -77,22 +73,34 @@ func (tableService *TableService) TablePreview(ctx *domain.Context, cmd *command | @@ -77,22 +73,34 @@ func (tableService *TableService) TablePreview(ctx *domain.Context, cmd *command | ||
77 | // } | 73 | // } |
78 | response.Load(table, dataTable, domain.ObjectMetaTable) | 74 | response.Load(table, dataTable, domain.ObjectMetaTable) |
79 | } | 75 | } |
80 | - } | ||
81 | - | ||
82 | - switch table.TableType { | ||
83 | - case domain.CalculateSet.ToString(): | ||
84 | - response.Fields = dataTable.Fields | ||
85 | - response.Data = domain.GripData(domain.ToFieldData(dataTable.Fields, dataTable.Data, false), int64(len(dataTable.Data))) | ||
86 | - default: | ||
87 | - response.Load(table, dataTable, domain.ObjectMetaTable) | 76 | + } else { |
77 | + switch table.TableType { | ||
78 | + case domain.CalculateSet.ToString(): | ||
79 | + response.Fields = dataTable.Fields | ||
80 | + response.Data = domain.GripData(domain.ToFieldData(dataTable.Fields, pageData(cmd.Where.PageNumber, cmd.Where.PageSize, dataTable.Data), false), int64(len(dataTable.Data))) | ||
81 | + default: | ||
82 | + response.Load(table, dataTable, domain.ObjectMetaTable) | ||
83 | + } | ||
88 | } | 84 | } |
89 | 85 | ||
90 | if cacheMiss && dataTable != nil { | 86 | if cacheMiss && dataTable != nil { |
91 | // 存储缓存 | 87 | // 存储缓存 |
92 | cache.SetDataTable(table.TableId, dataTable) | 88 | cache.SetDataTable(table.TableId, dataTable) |
93 | } | 89 | } |
94 | - //if err := transactionContext.CommitTransaction(); err != nil { | ||
95 | - // return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) | ||
96 | - //} | ||
97 | return response, nil | 90 | return response, nil |
98 | } | 91 | } |
92 | + | ||
93 | +func pageData(pageNumber, pageSize int, data [][]string) [][]string { | ||
94 | + if pageNumber == 0 || pageSize == 0 { | ||
95 | + return data | ||
96 | + } | ||
97 | + offset := (pageNumber - 1) * pageSize | ||
98 | + if len(data) < offset { | ||
99 | + return [][]string{} | ||
100 | + } | ||
101 | + if len(data) < offset+pageSize { | ||
102 | + pageSize = len(data) - offset | ||
103 | + } | ||
104 | + log.Logger.Info(fmt.Sprintf("%v %v %v", len(data), offset, pageSize)) | ||
105 | + return data[offset : offset+pageSize] | ||
106 | +} |
@@ -28,6 +28,8 @@ var BYTE_CORE_HOST = "http://192.168.100.34:8303" | @@ -28,6 +28,8 @@ var BYTE_CORE_HOST = "http://192.168.100.34:8303" | ||
28 | 28 | ||
29 | var AUTH_SERVER_HOST = "http://digital-platform-dev.fjmaimaimai.com" | 29 | var AUTH_SERVER_HOST = "http://digital-platform-dev.fjmaimaimai.com" |
30 | 30 | ||
31 | +var OPEN_API_HOST = "http://mmm-open-api-test.fjmaimaimai.com" | ||
32 | + | ||
31 | var BLACK_LIST_USER int64 | 33 | var BLACK_LIST_USER int64 |
32 | var BLACK_LIST_COMPANY int64 | 34 | var BLACK_LIST_COMPANY int64 |
33 | var WHITE_LIST_USERS []int | 35 | var WHITE_LIST_USERS []int |
@@ -52,6 +54,7 @@ func init() { | @@ -52,6 +54,7 @@ func init() { | ||
52 | SERVICE_ENV = Configurator.DefaultString("SERVICE_ENV", SERVICE_ENV) | 54 | SERVICE_ENV = Configurator.DefaultString("SERVICE_ENV", SERVICE_ENV) |
53 | HTTP_PORT = Configurator.DefaultInt("HTTP_PORT", HTTP_PORT) | 55 | HTTP_PORT = Configurator.DefaultInt("HTTP_PORT", HTTP_PORT) |
54 | AUTH_SERVER_HOST = Configurator.DefaultString("AUTH_SERVER_HOST", AUTH_SERVER_HOST) | 56 | AUTH_SERVER_HOST = Configurator.DefaultString("AUTH_SERVER_HOST", AUTH_SERVER_HOST) |
57 | + OPEN_API_HOST = Configurator.DefaultString("OPEN_API_HOST", OPEN_API_HOST) | ||
55 | SERVICE_NAME = fmt.Sprintf("%v-%v", SERVICE_NAME, SERVICE_ENV) | 58 | SERVICE_NAME = fmt.Sprintf("%v-%v", SERVICE_NAME, SERVICE_ENV) |
56 | PPROF_ON = Configurator.DefaultBool("PPROF_ON", PPROF_ON) | 59 | PPROF_ON = Configurator.DefaultBool("PPROF_ON", PPROF_ON) |
57 | CACHE_PREFIX = SERVICE_NAME + ":" + SERVICE_ENV | 60 | CACHE_PREFIX = SERVICE_NAME + ":" + SERVICE_ENV |
@@ -111,6 +111,7 @@ type ( | @@ -111,6 +111,7 @@ type ( | ||
111 | ProcessFields []*Field `json:"processFields"` | 111 | ProcessFields []*Field `json:"processFields"` |
112 | Action string `json:"action"` | 112 | Action string `json:"action"` |
113 | Params map[string]interface{} `json:"params"` | 113 | Params map[string]interface{} `json:"params"` |
114 | + HeaderRow int `json:"headerRow"` | ||
114 | } | 115 | } |
115 | 116 | ||
116 | DataEditDataTable struct { | 117 | DataEditDataTable struct { |
@@ -11,6 +11,10 @@ type Context struct { | @@ -11,6 +11,10 @@ type Context struct { | ||
11 | OperatorName string `json:"operatorName"` | 11 | OperatorName string `json:"operatorName"` |
12 | // 租户 (个人、企业) | 12 | // 租户 (个人、企业) |
13 | TenantId int `json:"tenantId"` | 13 | TenantId int `json:"tenantId"` |
14 | + // 应用键值 | ||
15 | + AppKey string `json:"appKey"` | ||
16 | + // Token | ||
17 | + AccessToken string `json:"-"` | ||
14 | // 附加数据 | 18 | // 附加数据 |
15 | data map[string]interface{} | 19 | data map[string]interface{} |
16 | } | 20 | } |
@@ -11,6 +11,7 @@ type DataTable struct { | @@ -11,6 +11,7 @@ type DataTable struct { | ||
11 | type Where struct { | 11 | type Where struct { |
12 | PageNumber int `json:"pageNumber"` | 12 | PageNumber int `json:"pageNumber"` |
13 | PageSize int `json:"pageSize"` | 13 | PageSize int `json:"pageSize"` |
14 | + HeaderRow int `json:"headerRow"` // 行号 默认:0 | ||
14 | Conditions []Condition `json:"conditions"` | 15 | Conditions []Condition `json:"conditions"` |
15 | } | 16 | } |
16 | 17 |
@@ -19,6 +19,7 @@ type TableService interface { | @@ -19,6 +19,7 @@ type TableService interface { | ||
19 | 19 | ||
20 | type PreviewDataTableService interface { | 20 | type PreviewDataTableService interface { |
21 | Preview(ctx *Context, fileId int, fields []*Field, where Where) (interface{}, error) | 21 | Preview(ctx *Context, fileId int, fields []*Field, where Where) (interface{}, error) |
22 | + RePreview(ctx *Context, fileId int, fields []*Field, where Where) (interface{}, error) | ||
22 | CreateTemporaryFile(ctx *Context, fileId int) (*File, error) | 23 | CreateTemporaryFile(ctx *Context, fileId int) (*File, error) |
23 | GetFileId() int | 24 | GetFileId() int |
24 | } | 25 | } |
@@ -10,6 +10,10 @@ const ( | @@ -10,6 +10,10 @@ const ( | ||
10 | ExprModeExcelFunction | 10 | ExprModeExcelFunction |
11 | ) | 11 | ) |
12 | 12 | ||
13 | +const ( | ||
14 | + MaxQueryRow = 1000 | ||
15 | +) | ||
16 | + | ||
13 | var ( | 17 | var ( |
14 | ErrorNotFound = fmt.Errorf("没有此资源") | 18 | ErrorNotFound = fmt.Errorf("没有此资源") |
15 | ) | 19 | ) |
@@ -170,7 +174,7 @@ func (t TableType) TableStatusEditable() bool { | @@ -170,7 +174,7 @@ func (t TableType) TableStatusEditable() bool { | ||
170 | return t == SchemaTable || t == CalculateItem || t == CalculateSet | 174 | return t == SchemaTable || t == CalculateItem || t == CalculateSet |
171 | } | 175 | } |
172 | 176 | ||
173 | -func (t TableType) TableHasGroup() bool { | 177 | +func (t TableType) TableIsSplitByGroup() bool { |
174 | return t == SchemaTable || t == SubProcessTable || t == CalculateItem || t == CalculateTable || t == CalculateSet | 178 | return t == SchemaTable || t == SubProcessTable || t == CalculateItem || t == CalculateTable || t == CalculateSet |
175 | } | 179 | } |
176 | 180 | ||
@@ -419,6 +423,17 @@ func (t LogLevel) ToString() string { | @@ -419,6 +423,17 @@ func (t LogLevel) ToString() string { | ||
419 | return string(t) | 423 | return string(t) |
420 | } | 424 | } |
421 | 425 | ||
426 | +type FileFromType string | ||
427 | + | ||
428 | +const ( | ||
429 | + FileFromByteBankWebClient = "ByteBankWebClient" | ||
430 | + FileFromDigitalAppClient = "DigitalAppClient" | ||
431 | +) | ||
432 | + | ||
433 | +func (t FileFromType) ToString() string { | ||
434 | + return string(t) | ||
435 | +} | ||
436 | + | ||
422 | const ( | 437 | const ( |
423 | DefaultPkField = "id" | 438 | DefaultPkField = "id" |
424 | ) | 439 | ) |
@@ -6,6 +6,7 @@ const ( | @@ -6,6 +6,7 @@ const ( | ||
6 | InvalidSign = 903 | 6 | InvalidSign = 903 |
7 | InvalidClientId = 904 | 7 | InvalidClientId = 904 |
8 | InvalidUUid = 905 | 8 | InvalidUUid = 905 |
9 | + InvalidApp = 906 | ||
9 | ) | 10 | ) |
10 | 11 | ||
11 | var CodeMsg = map[int]string{ | 12 | var CodeMsg = map[int]string{ |
@@ -14,4 +15,5 @@ var CodeMsg = map[int]string{ | @@ -14,4 +15,5 @@ var CodeMsg = map[int]string{ | ||
14 | InvalidSign: "sign 签名无效,需重新登录手机 APP", | 15 | InvalidSign: "sign 签名无效,需重新登录手机 APP", |
15 | InvalidClientId: "client id 或 client secret 无效,需强制更新手机 APP", | 16 | InvalidClientId: "client id 或 client secret 无效,需强制更新手机 APP", |
16 | InvalidUUid: "uuid 无效", | 17 | InvalidUUid: "uuid 无效", |
18 | + InvalidApp: "AppKey或者Token无效", | ||
17 | } | 19 | } |
@@ -26,6 +26,10 @@ type File struct { | @@ -26,6 +26,10 @@ type File struct { | ||
26 | Version int `json:"version"` | 26 | Version int `json:"version"` |
27 | // 扩展 | 27 | // 扩展 |
28 | Context *Context `json:"context"` | 28 | Context *Context `json:"context"` |
29 | + // 文件来源 | ||
30 | + FileFrom string `json:"fileFrom"` | ||
31 | + // 来源是 DigitalAppClient 时有值 | ||
32 | + AppKey string `json:"appKey"` | ||
29 | } | 33 | } |
30 | 34 | ||
31 | type FileRepository interface { | 35 | type FileRepository interface { |
@@ -42,15 +46,16 @@ func (file *File) Identify() interface{} { | @@ -42,15 +46,16 @@ func (file *File) Identify() interface{} { | ||
42 | return file.FileId | 46 | return file.FileId |
43 | } | 47 | } |
44 | 48 | ||
45 | -func (file *File) UpdateFileUrl(url string) { | 49 | +func (file *File) UpdateFileUrl(url string) *File { |
46 | if len(url) == 0 { | 50 | if len(url) == 0 { |
47 | - return | 51 | + return file |
48 | } | 52 | } |
49 | if url == file.FileInfo.Url { | 53 | if url == file.FileInfo.Url { |
50 | - return | 54 | + return file |
51 | } | 55 | } |
52 | file.FileInfo.Ext = filepath.Ext(url) | 56 | file.FileInfo.Ext = filepath.Ext(url) |
53 | file.FileInfo.Url = url | 57 | file.FileInfo.Url = url |
58 | + return file | ||
54 | } | 59 | } |
55 | 60 | ||
56 | func (file *File) Update(data map[string]interface{}) error { | 61 | func (file *File) Update(data map[string]interface{}) error { |
@@ -81,7 +86,37 @@ func (file *File) CopyTo(fileType FileType, ctx *Context) *File { | @@ -81,7 +86,37 @@ func (file *File) CopyTo(fileType FileType, ctx *Context) *File { | ||
81 | CreatedAt: time.Now(), | 86 | CreatedAt: time.Now(), |
82 | UpdatedAt: time.Now(), | 87 | UpdatedAt: time.Now(), |
83 | SourceFileId: file.FileId, | 88 | SourceFileId: file.FileId, |
89 | + FileFrom: file.FileFrom, | ||
84 | Context: ctx, | 90 | Context: ctx, |
85 | } | 91 | } |
86 | return t | 92 | return t |
87 | } | 93 | } |
94 | + | ||
95 | +func (file *File) SetHeaderRow(headerRow int) *File { | ||
96 | + //file.FileInfo.HeaderRow = headerRow | ||
97 | + return file | ||
98 | +} | ||
99 | + | ||
100 | +func (file *File) SetContext(context *Context) *File { | ||
101 | + //file.FileInfo.HeaderRow = headerRow | ||
102 | + file.Context = context | ||
103 | + return file | ||
104 | +} | ||
105 | + | ||
106 | +func (file *File) GetHeaderRow() int { | ||
107 | + return file.FileInfo.HeaderRow | ||
108 | +} | ||
109 | + | ||
110 | +func SetHeaderRow(headerRow int) int { | ||
111 | + if headerRow-1 < 0 { | ||
112 | + return 0 | ||
113 | + } | ||
114 | + return headerRow - 1 | ||
115 | +} | ||
116 | + | ||
117 | +func GetHeaderRow(headerRow int) int { | ||
118 | + if headerRow == 0 { | ||
119 | + return 1 | ||
120 | + } | ||
121 | + return headerRow + 1 | ||
122 | +} |
1 | package domain | 1 | package domain |
2 | 2 | ||
3 | +import ( | ||
4 | + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/constant" | ||
5 | + "strings" | ||
6 | +) | ||
7 | + | ||
3 | // FileInfo 文件信息 | 8 | // FileInfo 文件信息 |
4 | type FileInfo struct { | 9 | type FileInfo struct { |
5 | // 名称 | 10 | // 名称 |
@@ -14,4 +19,34 @@ type FileInfo struct { | @@ -14,4 +19,34 @@ type FileInfo struct { | ||
14 | RowCount int `json:"rowCount"` | 19 | RowCount int `json:"rowCount"` |
15 | // 表结构ID | 20 | // 表结构ID |
16 | TableId int `json:"tableId"` | 21 | TableId int `json:"tableId"` |
22 | + // 行号 | ||
23 | + HeaderRow int `json:"headerRow"` | ||
24 | +} | ||
25 | + | ||
26 | +// ConvertFileUrlToInternal 传递内网地址 | ||
27 | +// byte-bank.oss-cn-hangzhou 当oss与字库同属于这个节点下面,使用内网进行传输 | ||
28 | +func ConvertFileUrlToInternal(fileUrl string) string { | ||
29 | + if constant.SERVICE_ENV != "prod" { | ||
30 | + return fileUrl | ||
31 | + } | ||
32 | + var bucketRegion = "https://byte-bank.oss-cn-hangzhou" | ||
33 | + var bucketInternalRegion = "https://byte-bank.oss-cn-hangzhou-internal" | ||
34 | + if strings.HasPrefix(fileUrl, bucketRegion) { | ||
35 | + return strings.Replace(fileUrl, bucketRegion, bucketInternalRegion, 1) | ||
36 | + } | ||
37 | + return fileUrl | ||
38 | +} | ||
39 | + | ||
40 | +// ConvertInternalFileUrlToPublic 转内网地址为外网地址 | ||
41 | +func ConvertInternalFileUrlToPublic(fileUrl string) string { | ||
42 | + //var bucketRegion = "https://byte-bank.oss-cn-hangzhou" | ||
43 | + //var bucketInternalRegion = "https://byte-bank.oss-cn-hangzhou-internal" | ||
44 | + //if strings.HasPrefix(fileUrl, bucketInternalRegion) { | ||
45 | + // return strings.Replace(fileUrl, bucketInternalRegion, bucketRegion, 1) | ||
46 | + //} | ||
47 | + var internal = "-internal" | ||
48 | + if strings.Contains(fileUrl, internal) { | ||
49 | + return strings.Replace(fileUrl, internal, "", 1) | ||
50 | + } | ||
51 | + return fileUrl | ||
17 | } | 52 | } |
@@ -45,6 +45,9 @@ type Table struct { | @@ -45,6 +45,9 @@ type Table struct { | ||
45 | Context *Context `json:"context"` | 45 | Context *Context `json:"context"` |
46 | // 表信息 | 46 | // 表信息 |
47 | TableInfo *TableInfo `json:"tableInfo"` | 47 | TableInfo *TableInfo `json:"tableInfo"` |
48 | + | ||
49 | + // 表头行号 从0开始 | ||
50 | + HeaderRow int `json:"-"` | ||
48 | } | 51 | } |
49 | 52 | ||
50 | type TableRepository interface { | 53 | type TableRepository interface { |
1 | +package apilib | ||
2 | + | ||
3 | +import ( | ||
4 | + "fmt" | ||
5 | + "github.com/beego/beego/v2/core/logs" | ||
6 | + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/api" | ||
7 | + "net/http" | ||
8 | + "time" | ||
9 | +) | ||
10 | + | ||
11 | +type OpenApiLib struct { | ||
12 | + Token string | ||
13 | + api.BaseServiceGateway | ||
14 | +} | ||
15 | + | ||
16 | +func (gateway *OpenApiLib) WithToken(token string) *OpenApiLib { | ||
17 | + gateway.Token = token | ||
18 | + return gateway | ||
19 | +} | ||
20 | + | ||
21 | +func (gateway *OpenApiLib) DefaultHeader() http.Header { | ||
22 | + var header = make(map[string][]string) | ||
23 | + header["x-mmm-accesstoken"] = []string{gateway.Token} | ||
24 | + header["x-mmm-appproject"] = []string{"byte-bank"} | ||
25 | + return header | ||
26 | +} | ||
27 | + | ||
28 | +func NewApiAuthLib(host string) *OpenApiLib { | ||
29 | + gt := api.NewBaseServiceGateway(host) | ||
30 | + gt.ConnectTimeout = 360 * time.Second | ||
31 | + gt.ReadWriteTimeout = 360 * time.Second | ||
32 | + gt.Interceptor = func(msg string) { | ||
33 | + logs.Debug(msg) | ||
34 | + } | ||
35 | + gt.ServiceName = "【开发接口】" | ||
36 | + return &OpenApiLib{ | ||
37 | + BaseServiceGateway: gt, | ||
38 | + } | ||
39 | +} | ||
40 | + | ||
41 | +func (gateway *OpenApiLib) Upload(param RequestUpload) (*DataUploadItem, error) { | ||
42 | + url := gateway.Host() + "/v1/vod/putObject" | ||
43 | + method := "post" | ||
44 | + var data DataUpload | ||
45 | + err := gateway.FastDoRequest(url, method, struct{}{}, &data, api.WithHeader(gateway.DefaultHeader()), api.WithFileMap(param.UploadFileMap)) | ||
46 | + if err != nil { | ||
47 | + return nil, err | ||
48 | + } | ||
49 | + if len(data) > 0 { | ||
50 | + return data[0], nil | ||
51 | + } | ||
52 | + return nil, fmt.Errorf("上传失败") | ||
53 | +} |
pkg/infrastructure/api/apilib/types.go
0 → 100644
1 | +package apilib | ||
2 | + | ||
3 | +type DataUpload []*DataUploadItem | ||
4 | + | ||
5 | +type DataUploadItem struct { | ||
6 | + Host string `json:"host"` | ||
7 | + Key string `json:"key"` | ||
8 | + Path string `json:"path"` | ||
9 | + FileName string `json:"fileName"` | ||
10 | +} | ||
11 | + | ||
12 | +type RequestUpload struct { | ||
13 | + UploadFileMap map[string]string | ||
14 | +} |
@@ -48,6 +48,17 @@ func (gateway *ApiAuthLib) MeInfo(param RequestUserMeQuery) (*DataUserMe, error) | @@ -48,6 +48,17 @@ func (gateway *ApiAuthLib) MeInfo(param RequestUserMeQuery) (*DataUserMe, error) | ||
48 | return &data, nil | 48 | return &data, nil |
49 | } | 49 | } |
50 | 50 | ||
51 | +func (gateway *ApiAuthLib) MeAppInfo(param RequestUserMeQuery) (*DataUserAppInfo, error) { | ||
52 | + url := gateway.Host() + "/v1/user/me-app-info" | ||
53 | + method := "get" | ||
54 | + var data DataUserAppInfo | ||
55 | + err := gateway.FastDoRequest(url, method, param, &data, api.WithHeader(gateway.DefaultHeader())) | ||
56 | + if err != nil { | ||
57 | + return nil, err | ||
58 | + } | ||
59 | + return &data, nil | ||
60 | +} | ||
61 | + | ||
51 | func (gateway *ApiAuthLib) LoginCheck(param RequestLoginCheck) (*DataLoginCheck, error) { | 62 | func (gateway *ApiAuthLib) LoginCheck(param RequestLoginCheck) (*DataLoginCheck, error) { |
52 | url := gateway.Host() + "/v1/login/check?token=" + param.Token | 63 | url := gateway.Host() + "/v1/login/check?token=" + param.Token |
53 | method := "get" | 64 | method := "get" |
@@ -64,3 +75,14 @@ func (gateway *ApiAuthLib) LoginCheck(param RequestLoginCheck) (*DataLoginCheck, | @@ -64,3 +75,14 @@ func (gateway *ApiAuthLib) LoginCheck(param RequestLoginCheck) (*DataLoginCheck, | ||
64 | } | 75 | } |
65 | return &data, nil | 76 | return &data, nil |
66 | } | 77 | } |
78 | + | ||
79 | +func (gateway *ApiAuthLib) AppLogin(param RequestAppLogin) (*DataAppLogin, error) { | ||
80 | + url := gateway.Host() + "/v1/login/app-login" | ||
81 | + method := "post" | ||
82 | + var data DataAppLogin | ||
83 | + err := gateway.FastDoRequest(url, method, param, &data, api.WithHeader(gateway.DefaultHeader())) | ||
84 | + if err != nil { | ||
85 | + return nil, err | ||
86 | + } | ||
87 | + return &data, nil | ||
88 | +} |
@@ -50,3 +50,24 @@ type DataLoginCheck struct { | @@ -50,3 +50,24 @@ type DataLoginCheck struct { | ||
50 | Code int `json:"code"` | 50 | Code int `json:"code"` |
51 | Msg string `json:"msg"` | 51 | Msg string `json:"msg"` |
52 | } | 52 | } |
53 | + | ||
54 | +type ( | ||
55 | + RequestAppLogin struct { | ||
56 | + AppKey string `json:"appKey" valid:"Required"` // 应用键值 | ||
57 | + Token string `json:"token" valid:"Required"` // 凭证 | ||
58 | + } | ||
59 | + DataAppLogin struct { | ||
60 | + AppEnabled bool `json:"appEnabled"` | ||
61 | + } | ||
62 | +) | ||
63 | + | ||
64 | +type ( | ||
65 | + DataUserAppInfo struct { | ||
66 | + Apps []AppItem `json:"apps"` | ||
67 | + } | ||
68 | + AppItem struct { | ||
69 | + AppId int64 | ||
70 | + AppKey string | ||
71 | + AppName string | ||
72 | + } | ||
73 | +) |
@@ -58,6 +58,9 @@ func (gateway BaseServiceGateway) CreateRequest(url string, method string, optio | @@ -58,6 +58,9 @@ func (gateway BaseServiceGateway) CreateRequest(url string, method string, optio | ||
58 | request.Header(k, strings.Join(v, ";")) | 58 | request.Header(k, strings.Join(v, ";")) |
59 | } | 59 | } |
60 | } | 60 | } |
61 | + for k, v := range options.FileMap { | ||
62 | + request.PostFile(k, v) | ||
63 | + } | ||
61 | return request.SetTimeout(gateway.ConnectTimeout, gateway.ReadWriteTimeout) | 64 | return request.SetTimeout(gateway.ConnectTimeout, gateway.ReadWriteTimeout) |
62 | } | 65 | } |
63 | 66 | ||
@@ -104,11 +107,14 @@ func (gateway BaseServiceGateway) FastDoRequest(url, method string, param interf | @@ -104,11 +107,14 @@ func (gateway BaseServiceGateway) FastDoRequest(url, method string, param interf | ||
104 | 107 | ||
105 | func (gateway BaseServiceGateway) DoRequest(requestParam Request, val interface{}, options *RequestOptions) error { | 108 | func (gateway BaseServiceGateway) DoRequest(requestParam Request, val interface{}, options *RequestOptions) error { |
106 | r := gateway.CreateRequest(requestParam.Url, requestParam.Method, options) | 109 | r := gateway.CreateRequest(requestParam.Url, requestParam.Method, options) |
107 | - req, err := r.JSONBody(requestParam.Param) | ||
108 | - if err != nil { | ||
109 | - return err | 110 | + var err error |
111 | + if len(options.FileMap) == 0 { | ||
112 | + r, err = r.JSONBody(requestParam.Param) | ||
113 | + if err != nil { | ||
114 | + return err | ||
115 | + } | ||
110 | } | 116 | } |
111 | - byteResult, err := req.Bytes() | 117 | + byteResult, err := r.Bytes() |
112 | if err != nil { | 118 | if err != nil { |
113 | gateway.InterceptSimple(requestParam.Url, string(byteResult), err) | 119 | gateway.InterceptSimple(requestParam.Url, string(byteResult), err) |
114 | return err | 120 | return err |
@@ -149,6 +155,8 @@ func NewBaseServiceGateway(host string) BaseServiceGateway { | @@ -149,6 +155,8 @@ func NewBaseServiceGateway(host string) BaseServiceGateway { | ||
149 | 155 | ||
150 | type RequestOptions struct { | 156 | type RequestOptions struct { |
151 | Header http.Header | 157 | Header http.Header |
158 | + // key:form key value:path | ||
159 | + FileMap map[string]string | ||
152 | } | 160 | } |
153 | 161 | ||
154 | type Option func(o *RequestOptions) | 162 | type Option func(o *RequestOptions) |
@@ -158,3 +166,9 @@ func WithHeader(header http.Header) Option { | @@ -158,3 +166,9 @@ func WithHeader(header http.Header) Option { | ||
158 | o.Header = header | 166 | o.Header = header |
159 | } | 167 | } |
160 | } | 168 | } |
169 | + | ||
170 | +func WithFileMap(v map[string]string) Option { | ||
171 | + return func(o *RequestOptions) { | ||
172 | + o.FileMap = v | ||
173 | + } | ||
174 | +} |
1 | package bytelib | 1 | package bytelib |
2 | 2 | ||
3 | -import "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain" | 3 | +import ( |
4 | + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain" | ||
5 | +) | ||
4 | 6 | ||
5 | func DomainFieldsToColumnSchemas(fields []*domain.Field) []domain.ColumnSchema { | 7 | func DomainFieldsToColumnSchemas(fields []*domain.Field) []domain.ColumnSchema { |
6 | result := make([]domain.ColumnSchema, 0) | 8 | result := make([]domain.ColumnSchema, 0) |
@@ -7,15 +7,17 @@ import ( | @@ -7,15 +7,17 @@ import ( | ||
7 | ) | 7 | ) |
8 | 8 | ||
9 | type RequestCheckoutTablesQuery struct { | 9 | type RequestCheckoutTablesQuery struct { |
10 | - OriginalTableId string `json:"originalTableId"` | ||
11 | - IsFromOriginalTable bool `json:"isFromOriginalTable"` | ||
12 | - TableFileUrl string `json:"tableFileUrl"` | ||
13 | - ColumnSchemas []domain.ColumnSchema `json:"columnSchemas"` | ||
14 | - PageNumber int `json:"pageNumber"` | ||
15 | - PageSize int `json:"pageSize"` | ||
16 | - QueryParameters []domain.QueryParameter `json:"queryParameters"` | 10 | + OriginalTableId string `json:"originalTableId"` |
11 | + IsFromOriginalTable bool `json:"isFromOriginalTable"` | ||
12 | + TableFileUrl string `json:"tableFileUrl"` | ||
13 | + TableFileUrlInternal string `json:"tableFileUrlInternal"` | ||
14 | + ColumnSchemas []domain.ColumnSchema `json:"columnSchemas"` | ||
15 | + PageNumber int `json:"pageNumber"` | ||
16 | + PageSize int `json:"pageSize"` | ||
17 | + QueryParameters []domain.QueryParameter `json:"queryParameters"` | ||
17 | //QueryParameters map[string]interface{} `json:"queryParameters"` | 18 | //QueryParameters map[string]interface{} `json:"queryParameters"` |
18 | SortParameters map[string]interface{} `json:"sortParameters"` | 19 | SortParameters map[string]interface{} `json:"sortParameters"` |
20 | + HeaderRow int `json:"headerRow"` | ||
19 | } | 21 | } |
20 | 22 | ||
21 | type DataCheckoutTables struct { | 23 | type DataCheckoutTables struct { |
@@ -37,17 +39,22 @@ func NewRequestCheckoutTablesQuery(param domain.ReqLoadDataTable) RequestCheckou | @@ -37,17 +39,22 @@ func NewRequestCheckoutTablesQuery(param domain.ReqLoadDataTable) RequestCheckou | ||
37 | if param.IsFromOriginalTable { | 39 | if param.IsFromOriginalTable { |
38 | tableFileUrl = param.TableFileUrl | 40 | tableFileUrl = param.TableFileUrl |
39 | } | 41 | } |
42 | + if param.HeaderRow > 0 { | ||
43 | + isSourceFile = true | ||
44 | + } | ||
40 | return RequestCheckoutTablesQuery{ | 45 | return RequestCheckoutTablesQuery{ |
41 | - OriginalTableId: param.OriginalTableId, | ||
42 | - IsFromOriginalTable: isSourceFile, | ||
43 | - TableFileUrl: tableFileUrl, | ||
44 | - ColumnSchemas: param.ColumnSchemas, | ||
45 | - PageNumber: param.PageNumber, | ||
46 | - PageSize: param.PageSize, | 46 | + OriginalTableId: param.OriginalTableId, |
47 | + IsFromOriginalTable: isSourceFile, | ||
48 | + TableFileUrl: domain.ConvertFileUrlToInternal(tableFileUrl), | ||
49 | + TableFileUrlInternal: tableFileUrl, | ||
50 | + ColumnSchemas: param.ColumnSchemas, | ||
51 | + PageNumber: param.PageNumber, | ||
52 | + PageSize: param.PageSize, | ||
47 | //QueryParameters: param.QueryParameters, | 53 | //QueryParameters: param.QueryParameters, |
48 | QueryParameters: make([]domain.QueryParameter, 0), | 54 | QueryParameters: make([]domain.QueryParameter, 0), |
49 | //QueryParameters: make(map[string]interface{}), | 55 | //QueryParameters: make(map[string]interface{}), |
50 | SortParameters: param.SortParameters, | 56 | SortParameters: param.SortParameters, |
57 | + HeaderRow: param.HeaderRow, | ||
51 | } | 58 | } |
52 | } | 59 | } |
53 | 60 | ||
@@ -61,6 +68,7 @@ type RequestCheckoutTablesPreProccess struct { | @@ -61,6 +68,7 @@ type RequestCheckoutTablesPreProccess struct { | ||
61 | PageSize int `json:"pageSize"` | 68 | PageSize int `json:"pageSize"` |
62 | QueryParameters interface{} `json:"queryParameters"` | 69 | QueryParameters interface{} `json:"queryParameters"` |
63 | SortParameters map[string]interface{} `json:"sortParameters"` | 70 | SortParameters map[string]interface{} `json:"sortParameters"` |
71 | + HeaderRow int `json:"headerRow"` | ||
64 | } | 72 | } |
65 | 73 | ||
66 | func NewRequestCheckoutTablesPreProccess(param domain.ReqEditDataTable) RequestCheckoutTablesPreProccess { | 74 | func NewRequestCheckoutTablesPreProccess(param domain.ReqEditDataTable) RequestCheckoutTablesPreProccess { |
@@ -73,6 +81,7 @@ func NewRequestCheckoutTablesPreProccess(param domain.ReqEditDataTable) RequestC | @@ -73,6 +81,7 @@ func NewRequestCheckoutTablesPreProccess(param domain.ReqEditDataTable) RequestC | ||
73 | PageSize: 20, //param.PageSize, | 81 | PageSize: 20, //param.PageSize, |
74 | QueryParameters: []interface{}{}, | 82 | QueryParameters: []interface{}{}, |
75 | SortParameters: make(map[string]interface{}), | 83 | SortParameters: make(map[string]interface{}), |
84 | + HeaderRow: param.HeaderRow, | ||
76 | } | 85 | } |
77 | 86 | ||
78 | if len(param.Params) == 0 { | 87 | if len(param.Params) == 0 { |
@@ -126,12 +135,13 @@ func ToDataLoadDataTable(data DataCheckoutTables) *domain.DataLoadDataTable { | @@ -126,12 +135,13 @@ func ToDataLoadDataTable(data DataCheckoutTables) *domain.DataLoadDataTable { | ||
126 | 135 | ||
127 | type ( | 136 | type ( |
128 | RequestCheckoutTablesGenerateMasterTable struct { | 137 | RequestCheckoutTablesGenerateMasterTable struct { |
129 | - OriginalTableId string `json:"originalTableId"` | ||
130 | - CheckoutTableFileUrl string `json:"checkoutTableFileUrl"` | ||
131 | - ColumnSchemas []domain.ColumnSchema `json:"columnSchemas"` | ||
132 | - MasterTableName string `json:"masterTableName"` | ||
133 | - FieldSchemas []FieldSchema `json:"fieldSchemas"` | ||
134 | - KeyFieldEnNames []string `json:"keyFieldEnNames"` | 138 | + OriginalTableId string `json:"originalTableId"` |
139 | + CheckoutTableFileUrl string `json:"checkoutTableFileUrl"` | ||
140 | + CheckoutTableFileUrlInternal string `json:"checkoutTableFileUrlInternal"` | ||
141 | + ColumnSchemas []domain.ColumnSchema `json:"columnSchemas"` | ||
142 | + MasterTableName string `json:"masterTableName"` | ||
143 | + FieldSchemas []FieldSchema `json:"fieldSchemas"` | ||
144 | + KeyFieldEnNames []string `json:"keyFieldEnNames"` | ||
135 | } | 145 | } |
136 | DataCheckoutTablesGenerateMasterTable struct { | 146 | DataCheckoutTablesGenerateMasterTable struct { |
137 | MasterTableName string `json:"masterTableName"` | 147 | MasterTableName string `json:"masterTableName"` |
@@ -147,12 +157,13 @@ type ( | @@ -147,12 +157,13 @@ type ( | ||
147 | 157 | ||
148 | func NewRequestCheckoutTablesGenerateMasterTable(param domain.ReqGenerateTable) RequestCheckoutTablesGenerateMasterTable { | 158 | func NewRequestCheckoutTablesGenerateMasterTable(param domain.ReqGenerateTable) RequestCheckoutTablesGenerateMasterTable { |
149 | request := RequestCheckoutTablesGenerateMasterTable{ | 159 | request := RequestCheckoutTablesGenerateMasterTable{ |
150 | - OriginalTableId: fmt.Sprintf("%v", param.FileId), | ||
151 | - CheckoutTableFileUrl: param.FileUrl, | ||
152 | - ColumnSchemas: DomainFieldsToColumnSchemas(param.Table.DataFields), | ||
153 | - MasterTableName: param.Table.SQLName, | ||
154 | - FieldSchemas: ToFieldSchemas(param.Table.DataFields), | ||
155 | - KeyFieldEnNames: []string{param.Table.PK.SQLName}, | 160 | + OriginalTableId: fmt.Sprintf("%v", param.FileId), |
161 | + CheckoutTableFileUrl: domain.ConvertFileUrlToInternal(param.FileUrl), | ||
162 | + CheckoutTableFileUrlInternal: param.FileUrl, | ||
163 | + ColumnSchemas: DomainFieldsToColumnSchemas(param.Table.DataFields), | ||
164 | + MasterTableName: param.Table.SQLName, | ||
165 | + FieldSchemas: ToFieldSchemas(param.Table.DataFields), | ||
166 | + KeyFieldEnNames: []string{param.Table.PK.SQLName}, | ||
156 | } | 167 | } |
157 | return request | 168 | return request |
158 | } | 169 | } |
@@ -160,12 +171,13 @@ func NewRequestCheckoutTablesGenerateMasterTable(param domain.ReqGenerateTable) | @@ -160,12 +171,13 @@ func NewRequestCheckoutTablesGenerateMasterTable(param domain.ReqGenerateTable) | ||
160 | type ( | 171 | type ( |
161 | TableAppendRequest struct { | 172 | TableAppendRequest struct { |
162 | //MasterTableId string `json:"masterTableId"` | 173 | //MasterTableId string `json:"masterTableId"` |
163 | - OriginalTableId string `json:"originalTableId"` | ||
164 | - CheckoutTableFileUrl string `json:"checkoutTableFileUrl"` | ||
165 | - DatabaseTableName string `json:"databaseTableName"` | ||
166 | - ColumnSchemas []domain.ColumnSchema `json:"columnSchemas"` | ||
167 | - FieldSchemas []FieldSchema `json:"fieldSchemas"` | ||
168 | - SchemaMap map[string]domain.ColumnSchema `json:"schemaMap"` | 174 | + OriginalTableId string `json:"originalTableId"` |
175 | + CheckoutTableFileUrl string `json:"checkoutTableFileUrl"` | ||
176 | + CheckoutTableFileUrlInternal string `json:"checkoutTableFileUrlInternal"` | ||
177 | + DatabaseTableName string `json:"databaseTableName"` | ||
178 | + ColumnSchemas []domain.ColumnSchema `json:"columnSchemas"` | ||
179 | + FieldSchemas []FieldSchema `json:"fieldSchemas"` | ||
180 | + SchemaMap map[string]domain.ColumnSchema `json:"schemaMap"` | ||
169 | } | 181 | } |
170 | 182 | ||
171 | MasterTablesAppendRequest struct { | 183 | MasterTablesAppendRequest struct { |
@@ -185,12 +197,13 @@ type ( | @@ -185,12 +197,13 @@ type ( | ||
185 | func NewTableAppendRequest(param domain.ReqAppendData) TableAppendRequest { | 197 | func NewTableAppendRequest(param domain.ReqAppendData) TableAppendRequest { |
186 | columnSchemas := DomainFieldsToColumnSchemas(param.From) | 198 | columnSchemas := DomainFieldsToColumnSchemas(param.From) |
187 | req := TableAppendRequest{ | 199 | req := TableAppendRequest{ |
188 | - OriginalTableId: intToString(param.FileId), | ||
189 | - CheckoutTableFileUrl: param.FileUrl, | ||
190 | - DatabaseTableName: param.Table.SQLName, | ||
191 | - ColumnSchemas: DomainFieldsToColumnSchemas(param.ExcelTable.DataFields), //这里主要需要传递原文件所有字段 param.From | ||
192 | - FieldSchemas: ToFieldSchemas(param.Table.DataFields), | ||
193 | - SchemaMap: make(map[string]domain.ColumnSchema), | 200 | + OriginalTableId: intToString(param.FileId), |
201 | + CheckoutTableFileUrl: domain.ConvertFileUrlToInternal(param.FileUrl), | ||
202 | + CheckoutTableFileUrlInternal: param.FileUrl, | ||
203 | + DatabaseTableName: param.Table.SQLName, | ||
204 | + ColumnSchemas: DomainFieldsToColumnSchemas(param.ExcelTable.DataFields), //这里主要需要传递原文件所有字段 param.From | ||
205 | + FieldSchemas: ToFieldSchemas(param.Table.DataFields), | ||
206 | + SchemaMap: make(map[string]domain.ColumnSchema), | ||
194 | } | 207 | } |
195 | for i := 0; i < len(param.To); i++ { | 208 | for i := 0; i < len(param.To); i++ { |
196 | if len(columnSchemas) > i { | 209 | if len(columnSchemas) > i { |
@@ -31,6 +31,7 @@ func (ptr *EditDataTableService) Edit(ctx *domain.Context, req domain.EditTableR | @@ -31,6 +31,7 @@ func (ptr *EditDataTableService) Edit(ctx *domain.Context, req domain.EditTableR | ||
31 | ProcessFields: domain.ToFields(req.ProcessFields), | 31 | ProcessFields: domain.ToFields(req.ProcessFields), |
32 | Action: req.Action, | 32 | Action: req.Action, |
33 | Params: req.Params, | 33 | Params: req.Params, |
34 | + HeaderRow: req.Where.HeaderRow, | ||
34 | }) | 35 | }) |
35 | if err != nil { | 36 | if err != nil { |
36 | return nil, err | 37 | return nil, err |
@@ -29,6 +29,7 @@ func (ptr *FlushDataTableService) Flush(ctx *domain.Context, fileId int, table * | @@ -29,6 +29,7 @@ func (ptr *FlushDataTableService) Flush(ctx *domain.Context, fileId int, table * | ||
29 | if err != nil { | 29 | if err != nil { |
30 | return nil, fmt.Errorf("源文件不存在") | 30 | return nil, fmt.Errorf("源文件不存在") |
31 | } | 31 | } |
32 | + sourceFile.SetHeaderRow(table.HeaderRow) | ||
32 | // New Table | 33 | // New Table |
33 | table = NewTable(domain.ExcelTable, file.FileInfo.Name, table.DataFields, table.RowCount).WithContext(ctx) | 34 | table = NewTable(domain.ExcelTable, file.FileInfo.Name, table.DataFields, table.RowCount).WithContext(ctx) |
34 | // 通知底层保存、进行回调 | 35 | // 通知底层保存、进行回调 |
@@ -40,7 +41,7 @@ func (ptr *FlushDataTableService) Flush(ctx *domain.Context, fileId int, table * | @@ -40,7 +41,7 @@ func (ptr *FlushDataTableService) Flush(ctx *domain.Context, fileId int, table * | ||
40 | // 临时文件 -》校验文件 | 41 | // 临时文件 -》校验文件 |
41 | var newUrl string | 42 | var newUrl string |
42 | if response != nil { | 43 | if response != nil { |
43 | - newUrl = response.Url | 44 | + newUrl = domain.ConvertInternalFileUrlToPublic(response.Url) |
44 | } | 45 | } |
45 | log.Logger.Info("更新文件地址", map[string]interface{}{"from_url": file.FileInfo.Url, "to_url": newUrl, "sourceFileId": file.SourceFileId}) | 46 | log.Logger.Info("更新文件地址", map[string]interface{}{"from_url": file.FileInfo.Url, "to_url": newUrl, "sourceFileId": file.SourceFileId}) |
46 | switch sourceFile.FileType { | 47 | switch sourceFile.FileType { |
@@ -72,9 +73,15 @@ func (ptr *FlushDataTableService) flushSourceFile(ctx *domain.Context, table *do | @@ -72,9 +73,15 @@ func (ptr *FlushDataTableService) flushSourceFile(ctx *domain.Context, table *do | ||
72 | if err != nil { | 73 | if err != nil { |
73 | return err | 74 | return err |
74 | } | 75 | } |
76 | + if _, err = fileRepository.Save(sourceFile); err != nil { | ||
77 | + return err | ||
78 | + } | ||
75 | file.FileInfo.TableId = table.TableId | 79 | file.FileInfo.TableId = table.TableId |
76 | file.FileType = domain.VerifiedFile.ToString() | 80 | file.FileType = domain.VerifiedFile.ToString() |
77 | - file.UpdateFileUrl(url) | 81 | + file.UpdateFileUrl(url).SetHeaderRow(sourceFile.FileInfo.HeaderRow) |
82 | + if file.FileFrom == domain.FileFromDigitalAppClient { | ||
83 | + file.SetContext(ctx) | ||
84 | + } | ||
78 | if file, err = fileRepository.Save(file); err != nil { | 85 | if file, err = fileRepository.Save(file); err != nil { |
79 | return err | 86 | return err |
80 | } | 87 | } |
@@ -14,6 +14,50 @@ type PreviewDataTableService struct { | @@ -14,6 +14,50 @@ type PreviewDataTableService struct { | ||
14 | transactionContext *pgTransaction.TransactionContext | 14 | transactionContext *pgTransaction.TransactionContext |
15 | } | 15 | } |
16 | 16 | ||
17 | +// RePreview 重新预览 | ||
18 | +func (ptr *PreviewDataTableService) RePreview(ctx *domain.Context, fileId int, fields []*domain.Field, where domain.Where) (interface{}, error) { | ||
19 | + fileRepository, _ := repository.NewFileRepository(ptr.transactionContext) | ||
20 | + file, err := fileRepository.FindOne(map[string]interface{}{"fileId": fileId}) | ||
21 | + if err != nil { | ||
22 | + return nil, fmt.Errorf("校验文件不存在") | ||
23 | + } | ||
24 | + isSourceFile := true | ||
25 | + fileUrl := file.FileInfo.Url | ||
26 | + fileCache := redis.NewFileCacheService() | ||
27 | + tempFile, _ := fileCache.Get(redis.KeyTemporaryFileInfo(fileId)) | ||
28 | + if tempFile == nil { | ||
29 | + return nil, fmt.Errorf("临时文件不存在") | ||
30 | + } | ||
31 | + // Load Data From Excel(python api) | ||
32 | + byteCore, _ := CreateByteCoreService() | ||
33 | + response, err := byteCore.LoadDataTable(domain.ReqLoadDataTable{ | ||
34 | + FileId: file.FileId, | ||
35 | + FileName: file.FileInfo.Name, | ||
36 | + Url: file.FileInfo.Url, | ||
37 | + Ext: file.FileInfo.Ext, | ||
38 | + Where: where, | ||
39 | + OriginalTableId: fmt.Sprintf("%v", file.FileId), | ||
40 | + IsFromOriginalTable: isSourceFile, | ||
41 | + TableFileUrl: fileUrl, | ||
42 | + ColumnSchemas: bytelib.DomainFieldsToColumnSchemas(fields), | ||
43 | + SortParameters: make(map[string]interface{}), | ||
44 | + }) | ||
45 | + if err != nil { | ||
46 | + return nil, err | ||
47 | + } | ||
48 | + // 强制刷新列 | ||
49 | + fields = response.Fields | ||
50 | + | ||
51 | + cache := redis.NewFileCacheService() | ||
52 | + tempFile, err = cache.Update(redis.KeyTemporaryFileInfo(file.FileId), file, fields, response.Total, redis.WithHeaderRow(where.HeaderRow)) | ||
53 | + if err != nil { | ||
54 | + return nil, err | ||
55 | + } | ||
56 | + var responseDto = &FilePreviewDto{} | ||
57 | + //responseDto.Load(file.FileId, response, tempFile) | ||
58 | + return responseDto, nil | ||
59 | +} | ||
60 | + | ||
17 | // Preview 预览 【data-table】 | 61 | // Preview 预览 【data-table】 |
18 | func (ptr *PreviewDataTableService) Preview(ctx *domain.Context, fileId int, fields []*domain.Field, where domain.Where) (interface{}, error) { | 62 | func (ptr *PreviewDataTableService) Preview(ctx *domain.Context, fileId int, fields []*domain.Field, where domain.Where) (interface{}, error) { |
19 | fileRepository, _ := repository.NewFileRepository(ptr.transactionContext) | 63 | fileRepository, _ := repository.NewFileRepository(ptr.transactionContext) |
@@ -98,6 +142,7 @@ type FilePreviewDto struct { | @@ -98,6 +142,7 @@ type FilePreviewDto struct { | ||
98 | Data interface{} `json:"grid"` | 142 | Data interface{} `json:"grid"` |
99 | PageNumber int `json:"pageNumber"` | 143 | PageNumber int `json:"pageNumber"` |
100 | InValidCells []domain.InValidCell `json:"inValidCells"` | 144 | InValidCells []domain.InValidCell `json:"inValidCells"` |
145 | + HeaderRow int `json:"headerRow"` | ||
101 | } | 146 | } |
102 | 147 | ||
103 | func (d *FilePreviewDto) Load(fileId int, m *domain.DataLoadDataTable, file *redis.TemporaryFileInfo) { | 148 | func (d *FilePreviewDto) Load(fileId int, m *domain.DataLoadDataTable, file *redis.TemporaryFileInfo) { |
@@ -137,6 +182,7 @@ func (d *FilePreviewDto) Load(fileId int, m *domain.DataLoadDataTable, file *red | @@ -137,6 +182,7 @@ func (d *FilePreviewDto) Load(fileId int, m *domain.DataLoadDataTable, file *red | ||
137 | } | 182 | } |
138 | 183 | ||
139 | d.InValidCells = domain.NewInValidCells(fields, mapData) | 184 | d.InValidCells = domain.NewInValidCells(fields, mapData) |
185 | + d.HeaderRow = domain.GetHeaderRow(file.HeaderRow) | ||
140 | } | 186 | } |
141 | 187 | ||
142 | func (ptr *PreviewDataTableService) GetFileId() int { | 188 | func (ptr *PreviewDataTableService) GetFileId() int { |
@@ -348,6 +348,19 @@ func (l *ExcelTableEditLog) Content() string { | @@ -348,6 +348,19 @@ func (l *ExcelTableEditLog) Content() string { | ||
348 | return msg | 348 | return msg |
349 | } | 349 | } |
350 | 350 | ||
351 | +type ExcelTableResetHeaderLog struct { | ||
352 | + domain.LogEntry | ||
353 | + // 操作名称 | ||
354 | + // OperateName string | ||
355 | + // 操作列 | ||
356 | + HeaderRow int | ||
357 | +} | ||
358 | + | ||
359 | +func (l *ExcelTableResetHeaderLog) Content() string { | ||
360 | + msg := fmt.Sprintf("修改标题行位置:%v行", l.HeaderRow) | ||
361 | + return msg | ||
362 | +} | ||
363 | + | ||
351 | /* *********************************************拆解模块************************************************** */ | 364 | /* *********************************************拆解模块************************************************** */ |
352 | 365 | ||
353 | type CreateQuerySetLog struct { | 366 | type CreateQuerySetLog struct { |
@@ -368,11 +368,18 @@ func (d *DataLayoutDataTable) addByLocation(cell *domain.LayoutCell, blockData [ | @@ -368,11 +368,18 @@ func (d *DataLayoutDataTable) addByLocation(cell *domain.LayoutCell, blockData [ | ||
368 | } | 368 | } |
369 | d.PointEnd.Update(cell.X+len(blockData)-1, cell.Y, max) | 369 | d.PointEnd.Update(cell.X+len(blockData)-1, cell.Y, max) |
370 | case domain.DirectionNone: | 370 | case domain.DirectionNone: |
371 | - d.DataTable.Data[cell.X][cell.Y] = blockData[0] | 371 | + d.DataTable.Data[cell.X][cell.Y] = safeBlockData(blockData, 0) |
372 | d.PointEnd.Update(cell.X, cell.Y, max) | 372 | d.PointEnd.Update(cell.X, cell.Y, max) |
373 | } | 373 | } |
374 | } | 374 | } |
375 | 375 | ||
376 | +func safeBlockData(data []string, index int) string { | ||
377 | + if len(data) < index+1 { | ||
378 | + return "" | ||
379 | + } | ||
380 | + return data[index] | ||
381 | +} | ||
382 | + | ||
376 | func (d *DataLayoutDataTable) changeUnProcessedLocation(lastCell *domain.LayoutCell, length int) { | 383 | func (d *DataLayoutDataTable) changeUnProcessedLocation(lastCell *domain.LayoutCell, length int) { |
377 | for _, cell := range d.unprocessed { | 384 | for _, cell := range d.unprocessed { |
378 | switch lastCell.Direction { | 385 | switch lastCell.Direction { |
@@ -389,7 +396,7 @@ func (d *DataLayoutDataTable) changeUnProcessedLocation(lastCell *domain.LayoutC | @@ -389,7 +396,7 @@ func (d *DataLayoutDataTable) changeUnProcessedLocation(lastCell *domain.LayoutC | ||
389 | } | 396 | } |
390 | 397 | ||
391 | func (d *DataLayoutDataTable) BlockData(cells *domain.LayoutCell) ([]string, int) { | 398 | func (d *DataLayoutDataTable) BlockData(cells *domain.LayoutCell) ([]string, int) { |
392 | - var block []string | 399 | + var block = make([]string, 0) |
393 | if cells.Type == domain.CellTypeText { | 400 | if cells.Type == domain.CellTypeText { |
394 | data := []string{cells.Data.Text} | 401 | data := []string{cells.Data.Text} |
395 | return data, 1 | 402 | return data, 1 |
@@ -27,4 +27,8 @@ type File struct { | @@ -27,4 +27,8 @@ type File struct { | ||
27 | Version int `comment:"版本"` | 27 | Version int `comment:"版本"` |
28 | // 扩展 | 28 | // 扩展 |
29 | Context *domain.Context `json:"context"` | 29 | Context *domain.Context `json:"context"` |
30 | + // 文件来源 | ||
31 | + FileFrom string | ||
32 | + // 来源是 DigitalAppClient 时有值 | ||
33 | + AppKey string | ||
30 | } | 34 | } |
@@ -17,5 +17,7 @@ func TransformToFileDomainModelFromPgModels(fileModel *models.File) (*domain.Fil | @@ -17,5 +17,7 @@ func TransformToFileDomainModelFromPgModels(fileModel *models.File) (*domain.Fil | ||
17 | DeletedAt: fileModel.DeletedAt, | 17 | DeletedAt: fileModel.DeletedAt, |
18 | Version: fileModel.Version, | 18 | Version: fileModel.Version, |
19 | Context: fileModel.Context, | 19 | Context: fileModel.Context, |
20 | + AppKey: fileModel.AppKey, | ||
21 | + FileFrom: fileModel.FileFrom, | ||
20 | }, nil | 22 | }, nil |
21 | } | 23 | } |
@@ -5,6 +5,7 @@ import ( | @@ -5,6 +5,7 @@ import ( | ||
5 | "github.com/linmadan/egglib-go/utils/json" | 5 | "github.com/linmadan/egglib-go/utils/json" |
6 | "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/constant" | 6 | "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/constant" |
7 | "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain" | 7 | "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain" |
8 | + "strings" | ||
8 | ) | 9 | ) |
9 | 10 | ||
10 | const ( | 11 | const ( |
@@ -19,7 +20,9 @@ type TemporaryFileInfo struct { | @@ -19,7 +20,9 @@ type TemporaryFileInfo struct { | ||
19 | OriginalFileId int `json:"originalFileId"` | 20 | OriginalFileId int `json:"originalFileId"` |
20 | FileId int `json:"fileId"` | 21 | FileId int `json:"fileId"` |
21 | FileType string `json:"fileType"` | 22 | FileType string `json:"fileType"` |
23 | + FileName string `json:"fileName"` | ||
22 | Total int `json:"total"` | 24 | Total int `json:"total"` |
25 | + HeaderRow int `json:"headerRow"` | ||
23 | Fields []*domain.Field `json:"fields"` | 26 | Fields []*domain.Field `json:"fields"` |
24 | // 编辑表错误,有错误不允许保存成校验文件 | 27 | // 编辑表错误,有错误不允许保存成校验文件 |
25 | // 行记录错误 | 28 | // 行记录错误 |
@@ -28,6 +31,15 @@ type TemporaryFileInfo struct { | @@ -28,6 +31,15 @@ type TemporaryFileInfo struct { | ||
28 | ConvertTypeErrors []ConvertTypeError `json:"convertTypeErrors"` | 31 | ConvertTypeErrors []ConvertTypeError `json:"convertTypeErrors"` |
29 | } | 32 | } |
30 | 33 | ||
34 | +func (f *TemporaryFileInfo) Valid() error { | ||
35 | + for _, f := range f.Fields { | ||
36 | + if strings.HasPrefix(f.Name, "Unnamed:") { | ||
37 | + return fmt.Errorf("存在空字段 `%s` 请重命名", f.Name) | ||
38 | + } | ||
39 | + } | ||
40 | + return nil | ||
41 | +} | ||
42 | + | ||
31 | func (f *TemporaryFileInfo) MatchFields(columns []string) []*domain.Field { | 43 | func (f *TemporaryFileInfo) MatchFields(columns []string) []*domain.Field { |
32 | mapFields := (domain.Fields)(f.Fields).ToMap() | 44 | mapFields := (domain.Fields)(f.Fields).ToMap() |
33 | var result = make([]*domain.Field, 0) | 45 | var result = make([]*domain.Field, 0) |
@@ -42,6 +54,7 @@ func (f *TemporaryFileInfo) MatchFields(columns []string) []*domain.Field { | @@ -42,6 +54,7 @@ func (f *TemporaryFileInfo) MatchFields(columns []string) []*domain.Field { | ||
42 | func (f *TemporaryFileInfo) SetFile(file *domain.File) *TemporaryFileInfo { | 54 | func (f *TemporaryFileInfo) SetFile(file *domain.File) *TemporaryFileInfo { |
43 | f.FileId = file.FileId | 55 | f.FileId = file.FileId |
44 | f.FileType = file.FileType | 56 | f.FileType = file.FileType |
57 | + f.FileName = file.FileInfo.Name | ||
45 | return f | 58 | return f |
46 | } | 59 | } |
47 | 60 | ||
@@ -66,6 +79,11 @@ func (f *TemporaryFileInfo) SetTotal(total int) *TemporaryFileInfo { | @@ -66,6 +79,11 @@ func (f *TemporaryFileInfo) SetTotal(total int) *TemporaryFileInfo { | ||
66 | return f | 79 | return f |
67 | } | 80 | } |
68 | 81 | ||
82 | +func (f *TemporaryFileInfo) SetHeaderRow(headerRow int) *TemporaryFileInfo { | ||
83 | + f.HeaderRow = headerRow | ||
84 | + return f | ||
85 | +} | ||
86 | + | ||
69 | func (f *TemporaryFileInfo) AddConvertTypeError(e ConvertTypeError) *TemporaryFileInfo { | 87 | func (f *TemporaryFileInfo) AddConvertTypeError(e ConvertTypeError) *TemporaryFileInfo { |
70 | f.RemoveConvertTypeError(e) | 88 | f.RemoveConvertTypeError(e) |
71 | f.addConvertTypeError(e) | 89 | f.addConvertTypeError(e) |
@@ -99,46 +117,52 @@ type ConvertTypeError struct { | @@ -99,46 +117,52 @@ type ConvertTypeError struct { | ||
99 | type FileCacheService struct { | 117 | type FileCacheService struct { |
100 | } | 118 | } |
101 | 119 | ||
102 | -func (s *FileCacheService) Update(key string, file *domain.File, fields []*domain.Field, total int, errors ...FileCacheOptionsFunc) (*TemporaryFileInfo, error) { | 120 | +func (s *FileCacheService) Update(key string, file *domain.File, fields []*domain.Field, total int, option ...FileCacheOptionsFunc) (*TemporaryFileInfo, error) { |
121 | + options := NewFileCacheOptions(option...) | ||
103 | ok, err := ZeroCoreRedis.Exists(key) | 122 | ok, err := ZeroCoreRedis.Exists(key) |
104 | - var response = &TemporaryFileInfo{} | 123 | + var tmpFile = &TemporaryFileInfo{} |
105 | if err != nil { | 124 | if err != nil { |
106 | - return response, err | 125 | + return tmpFile, err |
107 | } | 126 | } |
108 | if !ok { | 127 | if !ok { |
109 | - response.SetFile(file).SetFields(fields).SetTotal(total) | ||
110 | - return response, ZeroCoreRedis.Setex(key, json.MarshalToString(response), TemporaryFileExpire) | 128 | + tmpFile.SetFile(file).SetFields(fields).SetTotal(total) |
129 | + if options.HasSetHeaderRow { | ||
130 | + tmpFile.SetHeaderRow(options.HeaderRow) | ||
131 | + } | ||
132 | + return tmpFile, ZeroCoreRedis.Setex(key, json.MarshalToString(tmpFile), TemporaryFileExpire) | ||
111 | } | 133 | } |
112 | data, err := ZeroCoreRedis.Get(key) | 134 | data, err := ZeroCoreRedis.Get(key) |
113 | if err != nil { | 135 | if err != nil { |
114 | return nil, err | 136 | return nil, err |
115 | } | 137 | } |
116 | - err = json.UnmarshalFromString(data, response) | 138 | + err = json.UnmarshalFromString(data, tmpFile) |
117 | if err != nil { | 139 | if err != nil { |
118 | return nil, err | 140 | return nil, err |
119 | } | 141 | } |
120 | - response.SetFields(fields) | 142 | + tmpFile.SetFields(fields) |
143 | + if options.HasSetHeaderRow { | ||
144 | + tmpFile.SetHeaderRow(options.HeaderRow) | ||
145 | + } | ||
121 | 146 | ||
122 | - options := NewFileCacheOptions(errors...) | ||
123 | for i := range options.AddConvertTypeErrors { | 147 | for i := range options.AddConvertTypeErrors { |
124 | - response.AddConvertTypeError(options.AddConvertTypeErrors[i]) | 148 | + tmpFile.AddConvertTypeError(options.AddConvertTypeErrors[i]) |
125 | } | 149 | } |
126 | for i := range options.RemoveConvertTypeErrors { | 150 | for i := range options.RemoveConvertTypeErrors { |
127 | convertType := options.RemoveConvertTypeErrors[i] | 151 | convertType := options.RemoveConvertTypeErrors[i] |
128 | - response.RemoveConvertTypeError(options.RemoveConvertTypeErrors[i]) | ||
129 | - for j := range response.Fields { | ||
130 | - if response.Fields[j].Name == convertType.FieldName { | ||
131 | - response.Fields[j].SQLType = convertType.ToType | 152 | + tmpFile.RemoveConvertTypeError(options.RemoveConvertTypeErrors[i]) |
153 | + for j := range tmpFile.Fields { | ||
154 | + if tmpFile.Fields[j].Name == convertType.FieldName { | ||
155 | + tmpFile.Fields[j].SQLType = convertType.ToType | ||
132 | break | 156 | break |
133 | } | 157 | } |
134 | } | 158 | } |
135 | } | 159 | } |
136 | 160 | ||
137 | - err = ZeroCoreRedis.Setex(key, json.MarshalToString(response), TemporaryFileExpire) | 161 | + err = ZeroCoreRedis.Setex(key, json.MarshalToString(tmpFile), TemporaryFileExpire) |
138 | if err != nil { | 162 | if err != nil { |
139 | return nil, err | 163 | return nil, err |
140 | } | 164 | } |
141 | - return response, err | 165 | + return tmpFile, err |
142 | } | 166 | } |
143 | 167 | ||
144 | func (s *FileCacheService) UpdateField(key string, file *domain.File, errors ...FileCacheOptionsFunc) (*TemporaryFileInfo, error) { | 168 | func (s *FileCacheService) UpdateField(key string, file *domain.File, errors ...FileCacheOptionsFunc) (*TemporaryFileInfo, error) { |
@@ -209,6 +233,8 @@ type FileCacheOptions struct { | @@ -209,6 +233,8 @@ type FileCacheOptions struct { | ||
209 | //OriginalFileId int | 233 | //OriginalFileId int |
210 | RemoveConvertTypeErrors []ConvertTypeError | 234 | RemoveConvertTypeErrors []ConvertTypeError |
211 | AddConvertTypeErrors []ConvertTypeError | 235 | AddConvertTypeErrors []ConvertTypeError |
236 | + HeaderRow int | ||
237 | + HasSetHeaderRow bool | ||
212 | } | 238 | } |
213 | 239 | ||
214 | type FileCacheOptionsFunc func(o *FileCacheOptions) | 240 | type FileCacheOptionsFunc func(o *FileCacheOptions) |
@@ -225,6 +251,13 @@ func WithAddConvertTypeErrors(errors []ConvertTypeError) FileCacheOptionsFunc { | @@ -225,6 +251,13 @@ func WithAddConvertTypeErrors(errors []ConvertTypeError) FileCacheOptionsFunc { | ||
225 | } | 251 | } |
226 | } | 252 | } |
227 | 253 | ||
254 | +func WithHeaderRow(headerRow int) FileCacheOptionsFunc { | ||
255 | + return func(o *FileCacheOptions) { | ||
256 | + o.HeaderRow = headerRow | ||
257 | + o.HasSetHeaderRow = true | ||
258 | + } | ||
259 | +} | ||
260 | + | ||
228 | //func WithOriginalFileId(originalFileId int) FileCacheOptionsFunc { | 261 | //func WithOriginalFileId(originalFileId int) FileCacheOptionsFunc { |
229 | // return func(o *FileCacheOptions) { | 262 | // return func(o *FileCacheOptions) { |
230 | // o.OriginalFileId = originalFileId | 263 | // o.OriginalFileId = originalFileId |
@@ -28,6 +28,8 @@ func (repository *FileRepository) Save(file *domain.File) (*domain.File, error) | @@ -28,6 +28,8 @@ func (repository *FileRepository) Save(file *domain.File) (*domain.File, error) | ||
28 | "deleted_at", | 28 | "deleted_at", |
29 | "version", | 29 | "version", |
30 | "context", | 30 | "context", |
31 | + "file_from", | ||
32 | + "app_key", | ||
31 | } | 33 | } |
32 | insertFieldsSnippet := sqlbuilder.SqlFieldsSnippet(sqlbuilder.RemoveSqlFields(sqlBuildFields, "file_id", "deleted_at")) | 34 | insertFieldsSnippet := sqlbuilder.SqlFieldsSnippet(sqlbuilder.RemoveSqlFields(sqlBuildFields, "file_id", "deleted_at")) |
33 | insertPlaceHoldersSnippet := sqlbuilder.SqlPlaceHoldersSnippet(sqlbuilder.RemoveSqlFields(sqlBuildFields, "file_id", "deleted_at")) | 35 | insertPlaceHoldersSnippet := sqlbuilder.SqlPlaceHoldersSnippet(sqlbuilder.RemoveSqlFields(sqlBuildFields, "file_id", "deleted_at")) |
@@ -48,6 +50,8 @@ func (repository *FileRepository) Save(file *domain.File) (*domain.File, error) | @@ -48,6 +50,8 @@ func (repository *FileRepository) Save(file *domain.File) (*domain.File, error) | ||
48 | &file.DeletedAt, | 50 | &file.DeletedAt, |
49 | &file.Version, | 51 | &file.Version, |
50 | &file.Context, | 52 | &file.Context, |
53 | + &file.FileFrom, | ||
54 | + &file.AppKey, | ||
51 | ), | 55 | ), |
52 | fmt.Sprintf("INSERT INTO metadata.files (%s) VALUES (%s) RETURNING %s", insertFieldsSnippet, insertPlaceHoldersSnippet, returningFieldsSnippet), | 56 | fmt.Sprintf("INSERT INTO metadata.files (%s) VALUES (%s) RETURNING %s", insertFieldsSnippet, insertPlaceHoldersSnippet, returningFieldsSnippet), |
53 | file.FileType, | 57 | file.FileType, |
@@ -58,6 +62,8 @@ func (repository *FileRepository) Save(file *domain.File) (*domain.File, error) | @@ -58,6 +62,8 @@ func (repository *FileRepository) Save(file *domain.File) (*domain.File, error) | ||
58 | file.UpdatedAt, | 62 | file.UpdatedAt, |
59 | file.Version, | 63 | file.Version, |
60 | file.Context, | 64 | file.Context, |
65 | + file.FileFrom, | ||
66 | + file.AppKey, | ||
61 | ); err != nil { | 67 | ); err != nil { |
62 | return file, err | 68 | return file, err |
63 | } | 69 | } |
@@ -76,6 +82,8 @@ func (repository *FileRepository) Save(file *domain.File) (*domain.File, error) | @@ -76,6 +82,8 @@ func (repository *FileRepository) Save(file *domain.File) (*domain.File, error) | ||
76 | &file.DeletedAt, | 82 | &file.DeletedAt, |
77 | &file.Version, | 83 | &file.Version, |
78 | &file.Context, | 84 | &file.Context, |
85 | + &file.FileFrom, | ||
86 | + &file.AppKey, | ||
79 | ), | 87 | ), |
80 | fmt.Sprintf("UPDATE metadata.files SET %s WHERE file_id=? and version=? RETURNING %s", updateFieldsSnippet, returningFieldsSnippet), | 88 | fmt.Sprintf("UPDATE metadata.files SET %s WHERE file_id=? and version=? RETURNING %s", updateFieldsSnippet, returningFieldsSnippet), |
81 | file.FileType, | 89 | file.FileType, |
@@ -86,6 +94,8 @@ func (repository *FileRepository) Save(file *domain.File) (*domain.File, error) | @@ -86,6 +94,8 @@ func (repository *FileRepository) Save(file *domain.File) (*domain.File, error) | ||
86 | file.UpdatedAt, | 94 | file.UpdatedAt, |
87 | file.Version, | 95 | file.Version, |
88 | file.Context, | 96 | file.Context, |
97 | + file.FileFrom, | ||
98 | + file.AppKey, | ||
89 | file.Identify(), | 99 | file.Identify(), |
90 | oldVersion, | 100 | oldVersion, |
91 | ); err != nil { | 101 | ); err != nil { |
@@ -111,6 +121,7 @@ func (repository *FileRepository) FindOne(queryOptions map[string]interface{}) ( | @@ -111,6 +121,7 @@ func (repository *FileRepository) FindOne(queryOptions map[string]interface{}) ( | ||
111 | WhereContext(query, queryOptions) | 121 | WhereContext(query, queryOptions) |
112 | query.SetWhereByQueryOption("file_info->>'name' = ?", "fileName") | 122 | query.SetWhereByQueryOption("file_info->>'name' = ?", "fileName") |
113 | query.SetWhereByQueryOption("file_type = ?", "fileType") | 123 | query.SetWhereByQueryOption("file_type = ?", "fileType") |
124 | + query.SetWhereByQueryOption("app_key = ?", "appKey") | ||
114 | if err := query.First(); err != nil { | 125 | if err := query.First(); err != nil { |
115 | if err.Error() == "pg: no rows in result set" { | 126 | if err.Error() == "pg: no rows in result set" { |
116 | return nil, domain.ErrorNotFound | 127 | return nil, domain.ErrorNotFound |
@@ -138,6 +149,9 @@ func (repository *FileRepository) Find(queryOptions map[string]interface{}) (int | @@ -138,6 +149,9 @@ func (repository *FileRepository) Find(queryOptions map[string]interface{}) (int | ||
138 | if v, ok := queryOptions["notInFileIds"]; ok && len(v.([]int)) > 0 { | 149 | if v, ok := queryOptions["notInFileIds"]; ok && len(v.([]int)) > 0 { |
139 | query.Where(`file_id not in (?)`, pg.In(v.([]int))) | 150 | query.Where(`file_id not in (?)`, pg.In(v.([]int))) |
140 | } | 151 | } |
152 | + if v, ok := queryOptions["inAppKeys"]; ok && len(v.([]string)) > 0 { | ||
153 | + query.Where(`app_key in (?)`, pg.In(v.([]string))) | ||
154 | + } | ||
141 | if v, ok := queryOptions["updatedAtBegin"]; ok && !v.(time.Time).IsZero() { | 155 | if v, ok := queryOptions["updatedAtBegin"]; ok && !v.(time.Time).IsZero() { |
142 | query.Where(`updated_at>?`, v.(time.Time)) | 156 | query.Where(`updated_at>?`, v.(time.Time)) |
143 | } | 157 | } |
@@ -368,6 +368,12 @@ func WrapDeleteFuncWithDB(db *gorm.DB) func(QueryOptions) (int64, error) { | @@ -368,6 +368,12 @@ func WrapDeleteFuncWithDB(db *gorm.DB) func(QueryOptions) (int64, error) { | ||
368 | continue | 368 | continue |
369 | } | 369 | } |
370 | idList = append(idList, row[0]) | 370 | idList = append(idList, row[0]) |
371 | + if len(idList) > 5000 { | ||
372 | + c := Condition{} | ||
373 | + sql := fmt.Sprintf("delete from %v where id in %v", params.TableName, c.InArgs(idList)) | ||
374 | + query = db.Exec(sql) | ||
375 | + idList = make([]string, 0) | ||
376 | + } | ||
371 | } | 377 | } |
372 | if len(idList) == 0 { | 378 | if len(idList) == 0 { |
373 | return 0, nil | 379 | return 0, nil |
pkg/infrastructure/utils/oss.go
0 → 100644
1 | +package utils | ||
2 | + | ||
3 | +import ( | ||
4 | + "fmt" | ||
5 | + "github.com/aliyun/aliyun-oss-go-sdk/oss" | ||
6 | + "github.com/google/uuid" | ||
7 | + "io" | ||
8 | + "path" | ||
9 | + "time" | ||
10 | +) | ||
11 | + | ||
12 | +type RouterConfig struct { | ||
13 | + OssEndPoint string | ||
14 | + AccessKeyID string | ||
15 | + AccessKeySecret string | ||
16 | + BuckName string | ||
17 | + AppProject string | ||
18 | + | ||
19 | + RegionID string | ||
20 | + RoleArn string | ||
21 | +} | ||
22 | + | ||
23 | +type ( | ||
24 | + CreateStsAuthRequest struct { | ||
25 | + Files []string `json:"files"` | ||
26 | + } | ||
27 | + CreateStsAuthResponse struct { | ||
28 | + Certificate interface{} `json:"certificate"` | ||
29 | + Files []BuckObject `json:"files"` | ||
30 | + } | ||
31 | + | ||
32 | + Object struct { | ||
33 | + Key string | ||
34 | + Value io.Reader | ||
35 | + } | ||
36 | + BuckObject struct { | ||
37 | + DefaultHost string `json:"host"` | ||
38 | + Key string `json:"key"` | ||
39 | + Path string `json:"path"` | ||
40 | + FileName string `json:"fileName"` | ||
41 | + } | ||
42 | +) | ||
43 | + | ||
44 | +func NewBucket(config RouterConfig) (*oss.Bucket, error) { | ||
45 | + client, err := oss.New(config.OssEndPoint, config.AccessKeyID, config.AccessKeySecret) | ||
46 | + if err != nil { | ||
47 | + return nil, err | ||
48 | + } | ||
49 | + bucket, err := client.Bucket(config.BuckName) | ||
50 | + if err != nil { | ||
51 | + return nil, err | ||
52 | + } | ||
53 | + | ||
54 | + return bucket, nil | ||
55 | +} | ||
56 | + | ||
57 | +func CreateObjects(bucket *oss.Bucket, objects ...Object) error { | ||
58 | + for _, object := range objects { | ||
59 | + err := bucket.PutObject(object.Key, object.Value) | ||
60 | + if err != nil { | ||
61 | + return err | ||
62 | + } | ||
63 | + } | ||
64 | + return nil | ||
65 | +} | ||
66 | + | ||
67 | +func DeleteObjects(bucket *oss.Bucket, objects ...string) error { | ||
68 | + for _, object := range objects { | ||
69 | + err := bucket.DeleteObject(object) | ||
70 | + if err != nil { | ||
71 | + return err | ||
72 | + } | ||
73 | + } | ||
74 | + return nil | ||
75 | +} | ||
76 | + | ||
77 | +func GetFileName(projectName, filename string) string { | ||
78 | + date := time.Now().Format("20060102") | ||
79 | + ext := path.Ext(filename) | ||
80 | + if len(projectName) == 0 { | ||
81 | + projectName = "default" | ||
82 | + } | ||
83 | + uid, _ := uuid.NewUUID() | ||
84 | + filename = fmt.Sprintf("%v%v", uid.String(), ext) | ||
85 | + sourcePath := fmt.Sprintf("%v/%v/%v", projectName, date, filename) | ||
86 | + return sourcePath | ||
87 | +} |
@@ -7,10 +7,8 @@ import ( | @@ -7,10 +7,8 @@ import ( | ||
7 | "github.com/beego/beego/v2/server/web/context" | 7 | "github.com/beego/beego/v2/server/web/context" |
8 | "github.com/linmadan/egglib-go/web/beego/filters" | 8 | "github.com/linmadan/egglib-go/web/beego/filters" |
9 | "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/constant" | 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/authlib" | ||
12 | "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/port/beego/controllers" | 10 | "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/port/beego/controllers" |
13 | - "net/http" | 11 | + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/port/beego/middleware" |
14 | "os" | 12 | "os" |
15 | "strconv" | 13 | "strconv" |
16 | "strings" | 14 | "strings" |
@@ -56,7 +54,7 @@ func init() { | @@ -56,7 +54,7 @@ func init() { | ||
56 | } | 54 | } |
57 | 55 | ||
58 | web.InsertFilter("/*", web.BeforeRouter, filters.AllowCors()) | 56 | web.InsertFilter("/*", web.BeforeRouter, filters.AllowCors()) |
59 | - web.InsertFilter("/*", web.BeforeRouter, JwtFilter()) | 57 | + web.InsertFilter("/data/*", web.BeforeRouter, middleware.JwtFilter()) |
60 | web.InsertFilter("/*", web.BeforeRouter, RequestCostBefore()) | 58 | web.InsertFilter("/*", web.BeforeRouter, RequestCostBefore()) |
61 | web.InsertFilter("/*", web.BeforeExec, controllers.BlacklistFilter(controllers.BlacklistRouters)) | 59 | web.InsertFilter("/*", web.BeforeExec, controllers.BlacklistFilter(controllers.BlacklistRouters)) |
62 | web.InsertFilter("/*", web.BeforeExec, CreateRequestLogFilter(true)) // filters.CreateRequstLogFilter(Logger) | 60 | web.InsertFilter("/*", web.BeforeExec, CreateRequestLogFilter(true)) // filters.CreateRequstLogFilter(Logger) |
@@ -76,48 +74,6 @@ func CreateRequestLogFilter(console bool) func(ctx *context.Context) { | @@ -76,48 +74,6 @@ func CreateRequestLogFilter(console bool) func(ctx *context.Context) { | ||
76 | } | 74 | } |
77 | } | 75 | } |
78 | 76 | ||
79 | -func JwtFilter() func(ctx *context.Context) { | ||
80 | - authLib := authlib.NewApiAuthLib(constant.AUTH_SERVER_HOST) | ||
81 | - authLib.BaseServiceGateway.ConnectTimeout = 200 * time.Millisecond | ||
82 | - authLib.BaseServiceGateway.ReadWriteTimeout = 200 * time.Millisecond | ||
83 | - return func(ctx *context.Context) { | ||
84 | - //token := ctx.Request.Header.Get("Authorization") | ||
85 | - token := ctx.Request.Header.Get("x-mmm-accesstoken") | ||
86 | - if len(token) > 0 { | ||
87 | - token = strings.TrimPrefix(token, "Bearer ") | ||
88 | - userToken := &domain.UserToken{} | ||
89 | - err := userToken.ParseToken(token) | ||
90 | - if err != nil { | ||
91 | - ctx.Output.SetStatus(http.StatusOK) | ||
92 | - ctx.Output.JSON(WithCodeMsgResponse(domain.InvalidRefreshToken), false, false) | ||
93 | - return | ||
94 | - } | ||
95 | - if userToken.UserId > 0 && userToken.CompanyId > 0 { | ||
96 | - loginCheckResponse, _ := authLib.LoginCheck(authlib.RequestLoginCheck{Token: token}) | ||
97 | - if loginCheckResponse != nil && loginCheckResponse.Code == 901 { | ||
98 | - ctx.Output.SetStatus(http.StatusOK) | ||
99 | - ctx.Output.JSON(WithCodeMsgResponse(domain.InvalidRefreshToken), false, false) | ||
100 | - return | ||
101 | - } | ||
102 | - } | ||
103 | - ctx.Input.SetData("UserToken", userToken) | ||
104 | - ctx.Input.SetData("Accesstoken", token) | ||
105 | - } | ||
106 | - } | ||
107 | -} | ||
108 | - | ||
109 | -func WithCodeMsgResponse(code int) map[string]interface{} { | ||
110 | - msg := "token 过期或无效,需刷新令牌" | ||
111 | - if codeMsg, ok := domain.CodeMsg[code]; ok { | ||
112 | - msg = codeMsg | ||
113 | - } | ||
114 | - return map[string]interface{}{ | ||
115 | - "msg": msg, | ||
116 | - "code": code, | ||
117 | - "data": struct{}{}, | ||
118 | - } | ||
119 | -} | ||
120 | - | ||
121 | func RequestCostBefore() func(ctx *context.Context) { | 77 | func RequestCostBefore() func(ctx *context.Context) { |
122 | return func(ctx *context.Context) { | 78 | return func(ctx *context.Context) { |
123 | ctx.Input.SetData("cost-begin", time.Now().UnixMilli()) | 79 | ctx.Input.SetData("cost-begin", time.Now().UnixMilli()) |
@@ -43,6 +43,22 @@ func Must(err error) { | @@ -43,6 +43,22 @@ func Must(err error) { | ||
43 | } | 43 | } |
44 | } | 44 | } |
45 | 45 | ||
46 | +func ParseAppKey(c beego.BaseController) string { | ||
47 | + appKey := c.Ctx.Input.GetData("AppKey") | ||
48 | + if appKey == nil { | ||
49 | + return "" | ||
50 | + } | ||
51 | + return appKey.(string) | ||
52 | +} | ||
53 | + | ||
54 | +func ParseAccessToken(c beego.BaseController) string { | ||
55 | + token := c.Ctx.Input.GetData("Accesstoken") | ||
56 | + if token == nil { | ||
57 | + return "" | ||
58 | + } | ||
59 | + return token.(string) | ||
60 | +} | ||
61 | + | ||
46 | func ParseContext(c beego.BaseController) *domain.Context { | 62 | func ParseContext(c beego.BaseController) *domain.Context { |
47 | var companyId int = 1598224576532189184 | 63 | var companyId int = 1598224576532189184 |
48 | var userId int = 1 | 64 | var userId int = 1 |
@@ -84,6 +100,7 @@ END: | @@ -84,6 +100,7 @@ END: | ||
84 | CompanyId: companyId, | 100 | CompanyId: companyId, |
85 | OperatorId: userId, | 101 | OperatorId: userId, |
86 | OperatorName: userName, | 102 | OperatorName: userName, |
103 | + AccessToken: ParseAccessToken(c), | ||
87 | TenantId: 1, | 104 | TenantId: 1, |
88 | } | 105 | } |
89 | return ctx | 106 | return ctx |
@@ -16,11 +16,55 @@ func (controller *FileController) CreateFile() { | @@ -16,11 +16,55 @@ func (controller *FileController) CreateFile() { | ||
16 | fileService := service.NewFileService(nil) | 16 | fileService := service.NewFileService(nil) |
17 | createFileCommand := &command.CreateFileCommand{} | 17 | createFileCommand := &command.CreateFileCommand{} |
18 | controller.Unmarshal(createFileCommand) | 18 | controller.Unmarshal(createFileCommand) |
19 | + createFileCommand.FileFrom = domain.FileFromByteBankWebClient | ||
19 | ctx := ParseContext(controller.BaseController) | 20 | ctx := ParseContext(controller.BaseController) |
20 | data, err := fileService.CreateFile(ctx, createFileCommand) | 21 | data, err := fileService.CreateFile(ctx, createFileCommand) |
21 | controller.Response(data, err) | 22 | controller.Response(data, err) |
22 | } | 23 | } |
23 | 24 | ||
25 | +func (controller *FileController) CreateAppTableFile() { | ||
26 | + fileService := service.NewFileService(nil) | ||
27 | + createDigitalAppFileCommand := &command.CreateAppTableFileCommand{} | ||
28 | + controller.Unmarshal(createDigitalAppFileCommand) | ||
29 | + | ||
30 | + ctx := ParseContext(controller.BaseController) | ||
31 | + createFileCommand, err := fileService.CreateAppTableFile(ctx, createDigitalAppFileCommand) | ||
32 | + if err != nil { | ||
33 | + controller.Response(nil, err) | ||
34 | + return | ||
35 | + } | ||
36 | + createFileCommand.AppKey = ParseAppKey(controller.BaseController) | ||
37 | + data, err := fileService.CreateFile(&domain.Context{}, createFileCommand) | ||
38 | + controller.Response(data, err) | ||
39 | +} | ||
40 | + | ||
41 | +func (controller *FileController) DeleteAppTableFile() { | ||
42 | + fileService := service.NewFileService(nil) | ||
43 | + cmd := &command.DeleteAppTableFileCommand{} | ||
44 | + controller.Unmarshal(cmd) | ||
45 | + cmd.AppKey = ParseAppKey(controller.BaseController) | ||
46 | + data, err := fileService.DeleteAppTableFile(&domain.Context{}, cmd) | ||
47 | + controller.Response(data, err) | ||
48 | +} | ||
49 | + | ||
50 | +func (controller *FileController) AppendDataAppTableFile() { | ||
51 | + fileService := service.NewFileService(nil) | ||
52 | + cmd := &command.AppTableFileAppendDataCommand{} | ||
53 | + controller.Unmarshal(cmd) | ||
54 | + cmd.AppKey = ParseAppKey(controller.BaseController) | ||
55 | + data, err := fileService.AppTableFileAppendData(&domain.Context{}, cmd) | ||
56 | + controller.Response(data, err) | ||
57 | +} | ||
58 | + | ||
59 | +func (controller *FileController) ListAppTableFile() { | ||
60 | + fileService := service.NewFileService(nil) | ||
61 | + cmd := &query.ListAppTableFileCommand{} | ||
62 | + controller.Unmarshal(cmd) | ||
63 | + cmd.AppKey = ParseAppKey(controller.BaseController) | ||
64 | + data, err := fileService.AppTableFileList(&domain.Context{}, cmd) | ||
65 | + controller.Response(data, err) | ||
66 | +} | ||
67 | + | ||
24 | func (controller *FileController) UpdateFile() { | 68 | func (controller *FileController) UpdateFile() { |
25 | fileService := service.NewFileService(nil) | 69 | fileService := service.NewFileService(nil) |
26 | updateFileCommand := &command.UpdateFileCommand{} | 70 | updateFileCommand := &command.UpdateFileCommand{} |
@@ -76,16 +120,41 @@ func (controller *FileController) SearchSourceFile() { | @@ -76,16 +120,41 @@ func (controller *FileController) SearchSourceFile() { | ||
76 | fileService := service.NewFileService(nil) | 120 | fileService := service.NewFileService(nil) |
77 | cmd := &query.SearchFileQuery{} | 121 | cmd := &query.SearchFileQuery{} |
78 | Must(controller.Unmarshal(cmd)) | 122 | Must(controller.Unmarshal(cmd)) |
123 | + if cmd.PageSize == 0 { | ||
124 | + cmd.PageSize = domain.MaxQueryRow | ||
125 | + } | ||
79 | cmd.FileType = domain.SourceFile | 126 | cmd.FileType = domain.SourceFile |
80 | cmd.Context = ParseContext(controller.BaseController) | 127 | cmd.Context = ParseContext(controller.BaseController) |
81 | data, err := fileService.SearchFile(cmd) | 128 | data, err := fileService.SearchFile(cmd) |
82 | controller.Response(data, err) | 129 | controller.Response(data, err) |
83 | } | 130 | } |
84 | 131 | ||
132 | +func (controller *FileController) SearchAppSourceFile() { | ||
133 | + fileService := service.NewFileService(nil) | ||
134 | + cmd := &query.SearchFileQuery{} | ||
135 | + Must(controller.Unmarshal(cmd)) | ||
136 | + if cmd.PageSize == 0 { | ||
137 | + cmd.PageSize = domain.MaxQueryRow | ||
138 | + } | ||
139 | + cmd.FileType = domain.SourceFile | ||
140 | + data, err := fileService.SearchAppFile(ParseContext(controller.BaseController), cmd) | ||
141 | + controller.Response(data, err) | ||
142 | +} | ||
143 | + | ||
144 | +func (controller *FileController) GetAppFile() { | ||
145 | + fileService := service.NewFileService(nil) | ||
146 | + appKey := controller.GetString("app_key", "") | ||
147 | + data, err := fileService.GetAppFile(ParseContext(controller.BaseController), appKey, "") | ||
148 | + controller.Response(data, err) | ||
149 | +} | ||
150 | + | ||
85 | func (controller *FileController) SearchVerifiedFile() { | 151 | func (controller *FileController) SearchVerifiedFile() { |
86 | fileService := service.NewFileService(nil) | 152 | fileService := service.NewFileService(nil) |
87 | cmd := &query.SearchFileQuery{} | 153 | cmd := &query.SearchFileQuery{} |
88 | Must(controller.Unmarshal(cmd)) | 154 | Must(controller.Unmarshal(cmd)) |
155 | + if cmd.PageSize == 0 { | ||
156 | + cmd.PageSize = domain.MaxQueryRow | ||
157 | + } | ||
89 | cmd.FileType = domain.VerifiedFile | 158 | cmd.FileType = domain.VerifiedFile |
90 | cmd.Context = ParseContext(controller.BaseController) | 159 | cmd.Context = ParseContext(controller.BaseController) |
91 | data, err := fileService.SearchFile(cmd) | 160 | data, err := fileService.SearchFile(cmd) |
@@ -248,6 +248,7 @@ func (controller *TableController) Preview() { | @@ -248,6 +248,7 @@ func (controller *TableController) Preview() { | ||
248 | fileService := fileservice.NewFileService(nil) | 248 | fileService := fileservice.NewFileService(nil) |
249 | cmd := &struct { | 249 | cmd := &struct { |
250 | ObjectType string `json:"objectType"` | 250 | ObjectType string `json:"objectType"` |
251 | + Action string `json:"action"` | ||
251 | }{} | 252 | }{} |
252 | Must(controller.Unmarshal(cmd)) | 253 | Must(controller.Unmarshal(cmd)) |
253 | var data interface{} | 254 | var data interface{} |
@@ -271,6 +272,14 @@ func (controller *TableController) Preview() { | @@ -271,6 +272,14 @@ func (controller *TableController) Preview() { | ||
271 | controller.Response(data, err) | 272 | controller.Response(data, err) |
272 | } | 273 | } |
273 | 274 | ||
275 | +func (controller *TableController) TableResetHeaderRow() { | ||
276 | + fileService := fileservice.NewFileService(nil) | ||
277 | + cmd := &filecommand.ResetTableHeaderCommand{} | ||
278 | + Must(controller.Unmarshal(cmd)) | ||
279 | + data, err := fileService.ResetHeaderRow(ParseContext(controller.BaseController), cmd) | ||
280 | + controller.Response(data, err) | ||
281 | +} | ||
282 | + | ||
274 | func (controller *TableController) RowEdit() { | 283 | func (controller *TableController) RowEdit() { |
275 | tableService := service.NewTableService(nil) | 284 | tableService := service.NewTableService(nil) |
276 | cmd := &command.RowEditCommandV2{} | 285 | cmd := &command.RowEditCommandV2{} |
pkg/port/beego/middleware/app_access.go
0 → 100644
1 | +package middleware | ||
2 | + | ||
3 | +import ( | ||
4 | + "github.com/beego/beego/v2/server/web/context" | ||
5 | + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/constant" | ||
6 | + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain" | ||
7 | + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/api/authlib" | ||
8 | + "net/http" | ||
9 | + "time" | ||
10 | +) | ||
11 | + | ||
12 | +func AppAccessFilter() func(ctx *context.Context) { | ||
13 | + authLib := authlib.NewApiAuthLib(constant.AUTH_SERVER_HOST) | ||
14 | + authLib.BaseServiceGateway.ConnectTimeout = 200 * time.Millisecond | ||
15 | + authLib.BaseServiceGateway.ReadWriteTimeout = 200 * time.Millisecond | ||
16 | + return func(ctx *context.Context) { | ||
17 | + token := ctx.Request.Header.Get("x-mmm-accesstoken") | ||
18 | + appKey := ctx.Request.Header.Get("x-mmm-appkey") | ||
19 | + if len(appKey) == 0 || len(token) == 0 { | ||
20 | + ctx.Output.SetStatus(http.StatusOK) | ||
21 | + ctx.Output.JSON(WithCodeMsgResponse(domain.InvalidApp), false, false) | ||
22 | + return | ||
23 | + } | ||
24 | + response, err := authLib.AppLogin(authlib.RequestAppLogin{ | ||
25 | + AppKey: appKey, | ||
26 | + Token: token, | ||
27 | + }) | ||
28 | + if err != nil { | ||
29 | + ctx.Output.SetStatus(http.StatusOK) | ||
30 | + ctx.Output.JSON(WithCodeMsgResponse(domain.InvalidApp), false, false) | ||
31 | + return | ||
32 | + } | ||
33 | + if !response.AppEnabled { | ||
34 | + ctx.Output.SetStatus(http.StatusOK) | ||
35 | + ctx.Output.JSON(WithCodeMsgResponse(domain.InvalidApp), false, false) | ||
36 | + return | ||
37 | + } | ||
38 | + ctx.Input.SetData("AppKey", appKey) | ||
39 | + } | ||
40 | +} |
pkg/port/beego/middleware/jwt.go
0 → 100644
1 | +package middleware | ||
2 | + | ||
3 | +import ( | ||
4 | + "github.com/beego/beego/v2/server/web/context" | ||
5 | + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/constant" | ||
6 | + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain" | ||
7 | + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/api/authlib" | ||
8 | + "net/http" | ||
9 | + "strings" | ||
10 | + "time" | ||
11 | +) | ||
12 | + | ||
13 | +func JwtFilter() func(ctx *context.Context) { | ||
14 | + authLib := authlib.NewApiAuthLib(constant.AUTH_SERVER_HOST) | ||
15 | + authLib.BaseServiceGateway.ConnectTimeout = 200 * time.Millisecond | ||
16 | + authLib.BaseServiceGateway.ReadWriteTimeout = 200 * time.Millisecond | ||
17 | + return func(ctx *context.Context) { | ||
18 | + //token := ctx.Request.Header.Get("Authorization") | ||
19 | + token := ctx.Request.Header.Get("x-mmm-accesstoken") | ||
20 | + if len(token) > 0 { | ||
21 | + token = strings.TrimPrefix(token, "Bearer ") | ||
22 | + userToken := &domain.UserToken{} | ||
23 | + err := userToken.ParseToken(token) | ||
24 | + if err != nil { | ||
25 | + ctx.Output.SetStatus(http.StatusOK) | ||
26 | + ctx.Output.JSON(WithCodeMsgResponse(domain.InvalidRefreshToken), false, false) | ||
27 | + return | ||
28 | + } | ||
29 | + if userToken.UserId > 0 && userToken.CompanyId > 0 { | ||
30 | + loginCheckResponse, _ := authLib.LoginCheck(authlib.RequestLoginCheck{Token: token}) | ||
31 | + if loginCheckResponse != nil && loginCheckResponse.Code == 901 { | ||
32 | + ctx.Output.SetStatus(http.StatusOK) | ||
33 | + ctx.Output.JSON(WithCodeMsgResponse(domain.InvalidRefreshToken), false, false) | ||
34 | + return | ||
35 | + } | ||
36 | + } | ||
37 | + ctx.Input.SetData("UserToken", userToken) | ||
38 | + ctx.Input.SetData("Accesstoken", token) | ||
39 | + } | ||
40 | + } | ||
41 | +} | ||
42 | + | ||
43 | +func WithCodeMsgResponse(code int) map[string]interface{} { | ||
44 | + msg := "token 过期或无效,需刷新令牌" | ||
45 | + if codeMsg, ok := domain.CodeMsg[code]; ok { | ||
46 | + msg = codeMsg | ||
47 | + } | ||
48 | + return map[string]interface{}{ | ||
49 | + "msg": msg, | ||
50 | + "code": code, | ||
51 | + "data": struct{}{}, | ||
52 | + } | ||
53 | +} |
pkg/port/beego/routers/api_router.go
0 → 100644
1 | +package routers | ||
2 | + | ||
3 | +import ( | ||
4 | + "github.com/beego/beego/v2/server/web" | ||
5 | + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/port/beego/controllers" | ||
6 | + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/port/beego/middleware" | ||
7 | +) | ||
8 | + | ||
9 | +func init() { | ||
10 | + web.InsertFilter("/api/app-table-file/*", web.BeforeRouter, middleware.AppAccessFilter()) | ||
11 | + web.Router("/api/app-table-file/create", &controllers.FileController{}, "Post:CreateAppTableFile") | ||
12 | + web.Router("/api/app-table-file/delete", &controllers.FileController{}, "Post:DeleteAppTableFile") | ||
13 | + web.Router("/api/app-table-file/append-data", &controllers.FileController{}, "Post:AppendDataAppTableFile") | ||
14 | + web.Router("/api/app-table-file/list", &controllers.FileController{}, "Post:ListAppTableFile") | ||
15 | +} |
@@ -3,8 +3,10 @@ package routers | @@ -3,8 +3,10 @@ package routers | ||
3 | import ( | 3 | import ( |
4 | "github.com/beego/beego/v2/server/web" | 4 | "github.com/beego/beego/v2/server/web" |
5 | "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/port/beego/controllers" | 5 | "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/port/beego/controllers" |
6 | + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/port/beego/middleware" | ||
6 | ) | 7 | ) |
7 | 8 | ||
8 | func init() { | 9 | func init() { |
10 | + web.InsertFilter("/static/*", web.BeforeRouter, middleware.JwtFilter()) | ||
9 | web.Router("/static/:filename", &controllers.DownloadFileController{}, "*:DownloadHandle") | 11 | web.Router("/static/:filename", &controllers.DownloadFileController{}, "*:DownloadHandle") |
10 | } | 12 | } |
@@ -15,11 +15,14 @@ func init() { | @@ -15,11 +15,14 @@ func init() { | ||
15 | web.Router("/data/files/check-status", &controllers.FileController{}, "Post:CheckFileVerifyStatus") | 15 | web.Router("/data/files/check-status", &controllers.FileController{}, "Post:CheckFileVerifyStatus") |
16 | web.Router("/data/files/search", &controllers.FileController{}, "Post:SearchFile") | 16 | web.Router("/data/files/search", &controllers.FileController{}, "Post:SearchFile") |
17 | web.Router("/data/files/search-source-file", &controllers.FileController{}, "Post:SearchSourceFile") | 17 | web.Router("/data/files/search-source-file", &controllers.FileController{}, "Post:SearchSourceFile") |
18 | + web.Router("/data/files/search-app-source-file", &controllers.FileController{}, "Post:SearchAppSourceFile") | ||
18 | web.Router("/data/files/search-verified-file", &controllers.FileController{}, "Post:SearchVerifiedFile") | 19 | web.Router("/data/files/search-verified-file", &controllers.FileController{}, "Post:SearchVerifiedFile") |
19 | web.Router("/data/files/cancel-verifying-file", &controllers.FileController{}, "Post:CancelVerifyingFile") | 20 | web.Router("/data/files/cancel-verifying-file", &controllers.FileController{}, "Post:CancelVerifyingFile") |
20 | web.Router("/data/files/prepare-temporary-file", &controllers.FileController{}, "Post:PrepareTemporaryFile") | 21 | web.Router("/data/files/prepare-temporary-file", &controllers.FileController{}, "Post:PrepareTemporaryFile") |
21 | web.Router("/data/files/export-file", &controllers.FileController{}, "Post:ExportFile") | 22 | web.Router("/data/files/export-file", &controllers.FileController{}, "Post:ExportFile") |
22 | 23 | ||
24 | + web.Router("/data/files/app-file", &controllers.FileController{}, "Get:GetAppFile") | ||
25 | + | ||
23 | web.Router("/data/file-preview", &controllers.FileController{}, "Post:FilePreview") | 26 | web.Router("/data/file-preview", &controllers.FileController{}, "Post:FilePreview") |
24 | web.Router("/data/edit-data-table", &controllers.FileController{}, "Post:EditDataTable") | 27 | web.Router("/data/edit-data-table", &controllers.FileController{}, "Post:EditDataTable") |
25 | web.Router("/data/flush-data-table", &controllers.FileController{}, "Post:FlushDataTable") | 28 | web.Router("/data/flush-data-table", &controllers.FileController{}, "Post:FlushDataTable") |
@@ -42,5 +42,7 @@ func init() { | @@ -42,5 +42,7 @@ func init() { | ||
42 | web.Router("/business/db-table-preview", tableController, "Post:DBTablePreview") | 42 | web.Router("/business/db-table-preview", tableController, "Post:DBTablePreview") |
43 | web.Router("/data/table-preview", tableController, "Post:Preview") | 43 | web.Router("/data/table-preview", tableController, "Post:Preview") |
44 | 44 | ||
45 | + web.Router("/data/reset-header-row", tableController, "Post:TableResetHeaderRow") | ||
46 | + | ||
45 | web.Router("/data/tables/exec/:name", tableController, "Get:ExecScript") | 47 | web.Router("/data/tables/exec/:name", tableController, "Get:ExecScript") |
46 | } | 48 | } |
@@ -19,5 +19,9 @@ func tableDataChangeHandler(e event.Event) error { | @@ -19,5 +19,9 @@ func tableDataChangeHandler(e event.Event) error { | ||
19 | _, err := svr.Handler(nil, &command.TableEventCommand{ | 19 | _, err := svr.Handler(nil, &command.TableEventCommand{ |
20 | EventTable: et, | 20 | EventTable: et, |
21 | }) | 21 | }) |
22 | + | ||
23 | + _, err = svr.DigitalPlatformEventSubscribe(nil, &command.TableEventCommand{ | ||
24 | + EventTable: et, | ||
25 | + }) | ||
22 | return err | 26 | return err |
23 | } | 27 | } |
-
请 注册 或 登录 后发表评论