作者 yangfu

Merge branch 'test'

@@ -10,4 +10,7 @@ type AppTableFileAppendDataCommand struct { @@ -10,4 +10,7 @@ type AppTableFileAppendDataCommand struct {
10 Data []map[string]string `json:"data"` 10 Data []map[string]string `json:"data"`
11 11
12 AppKey string `json:"appKey"` 12 AppKey string `json:"appKey"`
  13 +
  14 + // 追加表数据标识 true:往应用表里面追加数据 false:跳过
  15 + AppendTableDataFlag bool `json:"appendTableDataFlag"`
13 } 16 }
@@ -8,4 +8,6 @@ type CreateAppTableFileCommand struct { @@ -8,4 +8,6 @@ type CreateAppTableFileCommand struct {
8 Fields []*domain.Field `json:"fields"` 8 Fields []*domain.Field `json:"fields"`
9 // 数据列表 key:name(字段中文名) value:值(字符串类型) 9 // 数据列表 key:name(字段中文名) value:值(字符串类型)
10 Data []map[string]string `json:"data"` 10 Data []map[string]string `json:"data"`
  11 + // 生成表标识 true:实例化一个表 false:跳过
  12 + GenerateTableFlag bool `json:"generateTableFlag"`
11 } 13 }
  1 +package command
  2 +
  3 +import "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
  4 +
  5 +type UpdateAppTableFileCommand struct {
  6 + Name string `json:"name"`
  7 + AppKey string `json:"appKey"`
  8 + AddFields []*domain.Field `json:"addFields"`
  9 +}
@@ -21,6 +21,11 @@ type CreateFileCommand struct { @@ -21,6 +21,11 @@ type CreateFileCommand struct {
21 FileFrom string `json:"-"` 21 FileFrom string `json:"-"`
22 // AppKey 22 // AppKey
23 AppKey string `json:"-"` 23 AppKey string `json:"-"`
  24 +
  25 + // 生成表标识 true:实例化一个表 false:跳过
  26 + GenerateTableFlag bool `json:"-"`
  27 + // name 字段中文名
  28 + Fields []*domain.Field `json:"-"`
24 } 29 }
25 30
26 var MaxFileSize = 50 * 1024 * 1024 31 var MaxFileSize = 50 * 1024 * 1024
@@ -35,6 +40,14 @@ func (createFileCommand *CreateFileCommand) Valid(validation *validation.Validat @@ -35,6 +40,14 @@ func (createFileCommand *CreateFileCommand) Valid(validation *validation.Validat
35 validation.Error("文件大小超过50M") 40 validation.Error("文件大小超过50M")
36 return 41 return
37 } 42 }
  43 + if createFileCommand.GenerateTableFlag {
  44 + for _, f := range createFileCommand.Fields {
  45 + if err := f.Valid(); err != nil {
  46 + validation.Error(err.Error())
  47 + return
  48 + }
  49 + }
  50 + }
38 } 51 }
39 52
40 func (createFileCommand *CreateFileCommand) ValidateCommand() error { 53 func (createFileCommand *CreateFileCommand) ValidateCommand() error {
@@ -22,6 +22,10 @@ type FileDto struct { @@ -22,6 +22,10 @@ type FileDto struct {
22 HeaderRow int `json:"headerRow"` 22 HeaderRow int `json:"headerRow"`
23 // 所属应用 23 // 所属应用
24 AppKey string `json:"appKey"` 24 AppKey string `json:"appKey"`
  25 + // 表ID
  26 + TableId int `json:"tableId"`
  27 + // 允许表生成标识 1:允许生成分表 0:不允许
  28 + AllowTableGenerateFlag int `json:"allowTableGenerateFlag"`
25 } 29 }
26 30
27 func (d *FileDto) Load(f *domain.File) *FileDto { 31 func (d *FileDto) Load(f *domain.File) *FileDto {
@@ -36,6 +40,10 @@ func (d *FileDto) Load(f *domain.File) *FileDto { @@ -36,6 +40,10 @@ func (d *FileDto) Load(f *domain.File) *FileDto {
36 d.Time = xtime.New(f.UpdatedAt).Local().Format("2006-01-02 15:04:05") 40 d.Time = xtime.New(f.UpdatedAt).Local().Format("2006-01-02 15:04:05")
37 d.HeaderRow = domain.GetHeaderRow(f.FileInfo.HeaderRow) 41 d.HeaderRow = domain.GetHeaderRow(f.FileInfo.HeaderRow)
38 d.AppKey = f.AppKey 42 d.AppKey = f.AppKey
  43 + if len(f.AppKey) > 0 && f.FileInfo.TableId > 0 {
  44 + d.TableId = f.FileInfo.TableId
  45 + d.AllowTableGenerateFlag = 1
  46 + }
39 return d 47 return d
40 } 48 }
41 49
@@ -6,13 +6,16 @@ import ( @@ -6,13 +6,16 @@ import (
6 "fmt" 6 "fmt"
7 "github.com/beego/beego/v2/client/httplib" 7 "github.com/beego/beego/v2/client/httplib"
8 "github.com/linmadan/egglib-go/core/application" 8 "github.com/linmadan/egglib-go/core/application"
  9 + pgTransaction "github.com/linmadan/egglib-go/transaction/pg"
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/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/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/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/constant"
13 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain" 14 "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/api/apilib"
  16 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/domainService"
15 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/excel" 17 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/excel"
  18 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/starrocks"
16 "os" 19 "os"
17 "strings" 20 "strings"
18 "time" 21 "time"
@@ -83,6 +86,34 @@ func saveFile(name string, title []string, dataList [][]string, toInterfaces fun @@ -83,6 +86,34 @@ func saveFile(name string, title []string, dataList [][]string, toInterfaces fun
83 return response, nil 86 return response, nil
84 } 87 }
85 88
  89 +func saveCsvFile(name string, title []string, dataList [][]string, toInterfaces func([]string) []interface{}) (FileUpload, error) {
  90 + var (
  91 + response = FileUpload{}
  92 + err error
  93 + )
  94 + var writerTo = excel.NewCSVWriterTo(title, dataList)
  95 + filename := fmt.Sprintf("%v_%v.csv", name, time.Now().Format("060102150405"))
  96 + path := fmt.Sprintf("public/%v", filename)
  97 + if err = writerTo.Save(path); err != nil {
  98 + return response, factory.FastError(err)
  99 + }
  100 + api := apilib.NewApiAuthLib(constant.OPEN_API_HOST)
  101 + uploadResponse, err := api.Upload(apilib.RequestUpload{
  102 + UploadFileMap: map[string]string{"file": path},
  103 + })
  104 + if err != nil {
  105 + return response, err
  106 + }
  107 + if stat, err := os.Stat(path); err == nil {
  108 + response.FileSize = stat.Size()
  109 + }
  110 + response.Url = domain.ConvertInternalFileUrlToPublic(uploadResponse.Path)
  111 + response.FileName = name
  112 + response.Ext = domain.CSV
  113 +
  114 + return response, nil
  115 +}
  116 +
86 type FileUpload struct { 117 type FileUpload struct {
87 Url string `json:"url"` 118 Url string `json:"url"`
88 Ext string `json:"ext"` 119 Ext string `json:"ext"`
@@ -146,7 +177,10 @@ func (fileService *FileService) AppTableFileAppendData(ctx *domain.Context, cmd @@ -146,7 +177,10 @@ func (fileService *FileService) AppTableFileAppendData(ctx *domain.Context, cmd
146 return nil, factory.FastError(err) 177 return nil, factory.FastError(err)
147 } 178 }
148 reader := bytes.NewReader(f) 179 reader := bytes.NewReader(f)
149 - var importer *excel.Importer = excel.NewExcelImportByFile(file.FileInfo.Ext) 180 + var (
  181 + importer *excel.Importer = excel.NewExcelImportByFile(file.FileInfo.Ext)
  182 + appendTableDataList = make([][]string, 0)
  183 + )
150 data, err := importer.OpenExcelFromIoReader(reader) 184 data, err := importer.OpenExcelFromIoReader(reader)
151 if err != nil { 185 if err != nil {
152 return nil, factory.FastError(err) 186 return nil, factory.FastError(err)
@@ -183,14 +217,17 @@ func (fileService *FileService) AppTableFileAppendData(ctx *domain.Context, cmd @@ -183,14 +217,17 @@ func (fileService *FileService) AppTableFileAppendData(ctx *domain.Context, cmd
183 } 217 }
184 } 218 }
185 data = append(data, row) 219 data = append(data, row)
  220 + if cmd.AppendTableDataFlag {
  221 + appendTableDataList = append(appendTableDataList, row)
  222 + }
186 } 223 }
187 224
  225 + //if !cmd.AppendTableDataFlag {
188 // 上传文件 226 // 上传文件
189 fileUpload, err := saveFile(cmd.Name, titles, data, nil) 227 fileUpload, err := saveFile(cmd.Name, titles, data, nil)
190 if err != nil { 228 if err != nil {
191 return nil, factory.FastError(err) 229 return nil, factory.FastError(err)
192 } 230 }
193 -  
194 // 更新文件 231 // 更新文件
195 file.FileInfo.Url = fileUpload.Url 232 file.FileInfo.Url = fileUpload.Url
196 file.FileInfo.FileSize = int(fileUpload.FileSize) 233 file.FileInfo.FileSize = int(fileUpload.FileSize)
@@ -199,6 +236,188 @@ func (fileService *FileService) AppTableFileAppendData(ctx *domain.Context, cmd @@ -199,6 +236,188 @@ func (fileService *FileService) AppTableFileAppendData(ctx *domain.Context, cmd
199 if err != nil { 236 if err != nil {
200 return nil, factory.FastError(err) 237 return nil, factory.FastError(err)
201 } 238 }
  239 + //}
  240 + //else if cmd.AppendTableDataFlag && file.FileInfo.TableId != 0 { // 追加数据到应用表
  241 + //var table *domain.Table
  242 + //if _, table, err = factory.FastPgTable(transactionContext, file.FileInfo.TableId); err != nil {
  243 + // return nil, factory.FastError(err)
  244 + //}
  245 + //// 上传文件
  246 + //fileUpload, err := saveCsvFile(cmd.Name, titles, appendTableDataList, nil)
  247 + //if err != nil {
  248 + // return nil, factory.FastError(err)
  249 + //}
  250 + //appendDataToTableService, _ := domainService.NewAppendDataToTableService(transactionContext.(*pgTransaction.TransactionContext))
  251 + //var mappingFields = make([]*domain.MappingField, 0)
  252 + //for _, f := range cmd.Fields {
  253 + // mappingFields = append(mappingFields, &domain.MappingField{
  254 + // MainTableField: &domain.Field{Name: f.Name},
  255 + // VerifiedFileFieldName: f.Name,
  256 + // })
  257 + //}
  258 + //if _, err = appendDataToTableService.AppendDataDirectly(ctx, fileUpload.Url, table, mappingFields); err != nil {
  259 + // return nil, factory.FastError(err)
  260 + //}
  261 + //}
  262 +
  263 + if err := transactionContext.CommitTransaction(); err != nil {
  264 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  265 + }
  266 + return struct{}{}, nil
  267 +}
  268 +
  269 +func (fileService *FileService) AppTableAppendData(ctx *domain.Context, cmd *command.AppTableFileAppendDataCommand) (interface{}, error) {
  270 + transactionContext, err := factory.CreateTransactionContext(nil)
  271 + if err != nil {
  272 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  273 + }
  274 + if err := transactionContext.StartTransaction(); err != nil {
  275 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  276 + }
  277 + defer func() {
  278 + transactionContext.RollbackTransaction()
  279 + }()
  280 +
  281 + fileRepository, file, _ := factory.FastPgFile(transactionContext, 0)
  282 + file, err = fileRepository.FindOne(map[string]interface{}{"appKey": cmd.AppKey, "fileName": cmd.Name, "fileType": domain.SourceFile})
  283 + if err == domain.ErrorNotFound {
  284 + return nil, factory.FastError(errors.New("文件不存在"))
  285 + }
  286 + if err != nil {
  287 + return nil, factory.FastError(err)
  288 + }
  289 + if file.FileInfo.TableId == 0 {
  290 + return nil, factory.FastError(errors.New("表不存在"))
  291 + }
  292 + var (
  293 + appendTableDataList = make([][]string, 0)
  294 + titles = make([]string, 0)
  295 + table *domain.Table
  296 + )
  297 + _, table, err = factory.FastPgTable(transactionContext, file.FileInfo.TableId)
  298 + if err != nil {
  299 + return nil, factory.FastError(err)
  300 + }
  301 + for _, f := range table.Fields(false) {
  302 + titles = append(titles, f.Name)
  303 + }
  304 + for _, f := range cmd.Fields {
  305 + found := false
  306 + for _, column := range titles {
  307 + if column == f.Name {
  308 + found = true
  309 + break
  310 + }
  311 + }
  312 + if !found {
  313 + titles = append(titles, f.Name)
  314 + }
  315 + }
  316 + for i := range cmd.Data {
  317 + row := make([]string, 0)
  318 + for _, filed := range titles {
  319 + if v, ok := cmd.Data[i][filed]; ok {
  320 + row = append(row, v)
  321 + } else {
  322 + row = append(row, "")
  323 + }
  324 + }
  325 + appendTableDataList = append(appendTableDataList, row)
  326 + }
  327 +
  328 + // 上传文件
  329 + fileUpload, err := saveCsvFile(cmd.Name, titles, appendTableDataList, nil)
  330 + if err != nil {
  331 + return nil, factory.FastError(err)
  332 + }
  333 + appendDataToTableService, _ := domainService.NewAppendDataToTableService(transactionContext.(*pgTransaction.TransactionContext))
  334 + var mappingFields = make([]*domain.MappingField, 0)
  335 + for _, f := range cmd.Fields {
  336 + mappingFields = append(mappingFields, &domain.MappingField{
  337 + MainTableField: &domain.Field{Name: f.Name},
  338 + VerifiedFileFieldName: f.Name,
  339 + })
  340 + }
  341 + if _, err = appendDataToTableService.AppendDataDirectly(ctx, fileUpload.Url, table, mappingFields); err != nil {
  342 + return nil, factory.FastError(err)
  343 + }
  344 +
  345 + if err := transactionContext.CommitTransaction(); err != nil {
  346 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  347 + }
  348 + return struct{}{}, nil
  349 +}
  350 +
  351 +func (fileService *FileService) AppTableAppendDataDirect(ctx *domain.Context, cmd *command.AppTableFileAppendDataCommand) (interface{}, error) {
  352 + transactionContext, err := factory.CreateTransactionContext(nil)
  353 + if err != nil {
  354 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  355 + }
  356 + if err := transactionContext.StartTransaction(); err != nil {
  357 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  358 + }
  359 + defer func() {
  360 + transactionContext.RollbackTransaction()
  361 + }()
  362 +
  363 + fileRepository, file, _ := factory.FastPgFile(transactionContext, 0)
  364 + file, err = fileRepository.FindOne(map[string]interface{}{"appKey": cmd.AppKey, "fileName": cmd.Name, "fileType": domain.SourceFile})
  365 + if err == domain.ErrorNotFound {
  366 + return nil, factory.FastError(errors.New("文件不存在"))
  367 + }
  368 + if err != nil {
  369 + return nil, factory.FastError(err)
  370 + }
  371 + if file.FileInfo.TableId == 0 {
  372 + return nil, factory.FastError(errors.New("表不存在"))
  373 + }
  374 + var (
  375 + titles = make([]string, 0)
  376 + table *domain.Table
  377 + )
  378 + _, table, err = factory.FastPgTable(transactionContext, file.FileInfo.TableId)
  379 + if err != nil {
  380 + return nil, factory.FastError(err)
  381 + }
  382 + for _, f := range table.Fields(false) {
  383 + titles = append(titles, f.Name)
  384 + }
  385 + mapNameField := domain.Fields(table.Fields(false)).ToMap()
  386 + for _, f := range cmd.Fields {
  387 + found := false
  388 + for _, column := range titles {
  389 + if column == f.Name {
  390 + found = true
  391 + break
  392 + }
  393 + }
  394 + if !found {
  395 + titles = append(titles, f.Name)
  396 + }
  397 + }
  398 + var mapData = make([]map[string]string, 0)
  399 + for i := range cmd.Data {
  400 + mapItem := make(map[string]string)
  401 + for k, v := range cmd.Data[i] {
  402 + if f, ok := mapNameField[k]; ok {
  403 + mapItem[f.SQLName] = v
  404 + }
  405 + }
  406 + mapData = append(mapData, mapItem)
  407 + }
  408 + editDataService, _ := factory.CreateTableEditDataService(transactionContext)
  409 + _, err = editDataService.BatchAdd(ctx, domain.EditDataRequest{
  410 + TableId: table.TableId,
  411 + Table: table,
  412 + Where: domain.Where{},
  413 + UpdateList: nil,
  414 + AddList: domainService.MapArrayToFieldValues(mapData, table, nil, false),
  415 + RemoveList: nil,
  416 + IgnoreTableType: true,
  417 + })
  418 + if err != nil {
  419 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  420 + }
202 421
203 if err := transactionContext.CommitTransaction(); err != nil { 422 if err := transactionContext.CommitTransaction(); err != nil {
204 return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) 423 return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
@@ -209,3 +428,54 @@ func (fileService *FileService) AppTableFileAppendData(ctx *domain.Context, cmd @@ -209,3 +428,54 @@ func (fileService *FileService) AppTableFileAppendData(ctx *domain.Context, cmd
209 func (fileService *FileService) AppTableFileList(ctx *domain.Context, cmd *query.ListAppTableFileCommand) (interface{}, error) { 428 func (fileService *FileService) AppTableFileList(ctx *domain.Context, cmd *query.ListAppTableFileCommand) (interface{}, error) {
210 return fileService.GetAppFile(ctx, cmd.AppKey, cmd.Name) 429 return fileService.GetAppFile(ctx, cmd.AppKey, cmd.Name)
211 } 430 }
  431 +
  432 +func (fileService *FileService) UpdateAppTableFile(ctx *domain.Context, cmd *command.UpdateAppTableFileCommand) (interface{}, error) {
  433 + transactionContext, err := factory.CreateTransactionContext(nil)
  434 + if err != nil {
  435 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  436 + }
  437 + if err := transactionContext.StartTransaction(); err != nil {
  438 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  439 + }
  440 + defer func() {
  441 + transactionContext.RollbackTransaction()
  442 + }()
  443 +
  444 + fileRepository, file, _ := factory.FastPgFile(transactionContext, 0)
  445 + file, err = fileRepository.FindOne(map[string]interface{}{"appKey": cmd.AppKey, "fileName": cmd.Name, "fileType": domain.SourceFile})
  446 + if err == domain.ErrorNotFound {
  447 + return nil, factory.FastError(errors.New("文件不存在"))
  448 + }
  449 + if err != nil {
  450 + return nil, factory.FastError(err)
  451 + }
  452 + if len(cmd.AddFields) == 0 {
  453 + return nil, nil
  454 + }
  455 + tableRepository, table, _ := factory.FastPgTable(transactionContext, file.FileInfo.TableId)
  456 + if err == domain.ErrorNotFound {
  457 + return nil, factory.FastError(errors.New("文件表不存在"))
  458 + }
  459 + builder := domainService.NewDataFieldsBuilder()
  460 + for i, _ := range cmd.AddFields {
  461 + if _, ok := table.MatchField(cmd.AddFields[i]); ok {
  462 + return nil, factory.FastError(errors.New("字段已存在"))
  463 + }
  464 + }
  465 + for _, f := range cmd.AddFields {
  466 + dataField := builder.NewDataField(f.Name, f.SQLType, domain.MainTableField)
  467 + table.DataFields = append(table.DataFields, dataField)
  468 + if err = starrocks.AddTableColumn(starrocks.DB, table.SQLName, dataField); err != nil {
  469 + return nil, factory.FastError(err)
  470 + }
  471 + }
  472 +
  473 + if table, err = tableRepository.Save(table); err != nil {
  474 + return nil, factory.FastError(err)
  475 + }
  476 +
  477 + if err := transactionContext.CommitTransaction(); err != nil {
  478 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  479 + }
  480 + return struct{}{}, nil
  481 +}
@@ -4,6 +4,7 @@ import ( @@ -4,6 +4,7 @@ import (
4 "fmt" 4 "fmt"
5 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/constant" 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" 6 "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/api/authlib"
  7 + "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/api/bytelib"
7 "path/filepath" 8 "path/filepath"
8 "strings" 9 "strings"
9 "time" 10 "time"
@@ -24,7 +25,7 @@ type FileService struct { @@ -24,7 +25,7 @@ type FileService struct {
24 } 25 }
25 26
26 // CreateFile 创建文件服务 27 // CreateFile 创建文件服务
27 -func (fileService *FileService) CreateFile(ctx *domain.Context, createFileCommand *command.CreateFileCommand) (interface{}, error) { 28 +func (fileService *FileService) CreateFile(ctx *domain.Context, createFileCommand *command.CreateFileCommand) (*domain.File, error) {
28 if err := createFileCommand.ValidateCommand(); err != nil { 29 if err := createFileCommand.ValidateCommand(); err != nil {
29 return nil, application.ThrowError(application.ARG_ERROR, err.Error()) 30 return nil, application.ThrowError(application.ARG_ERROR, err.Error())
30 } 31 }
@@ -57,7 +58,7 @@ func (fileService *FileService) CreateFile(ctx *domain.Context, createFileComman @@ -57,7 +58,7 @@ func (fileService *FileService) CreateFile(ctx *domain.Context, createFileComman
57 } 58 }
58 fileRepository, _, _ := factory.FastPgFile(transactionContext, 0) 59 fileRepository, _, _ := factory.FastPgFile(transactionContext, 0)
59 60
60 - // 文件名相同进行替换 61 + // 文件名相同,进行替换
61 if oldFile, findOldFileErr := fileRepository.FindOne(map[string]interface{}{ 62 if oldFile, findOldFileErr := fileRepository.FindOne(map[string]interface{}{
62 "context": ctx, 63 "context": ctx,
63 "fileName": fileInfo.Name, 64 "fileName": fileInfo.Name,
@@ -78,6 +79,41 @@ func (fileService *FileService) CreateFile(ctx *domain.Context, createFileComman @@ -78,6 +79,41 @@ func (fileService *FileService) CreateFile(ctx *domain.Context, createFileComman
78 if err != nil { 79 if err != nil {
79 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error()) 80 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
80 } 81 }
  82 + // 同时生成主表
  83 + // 前置需要进行预览、保持文件,才能生成主表
  84 + if createFileCommand.GenerateTableFlag {
  85 + table := domainService.NewTable(domain.MainTable, fileInfo.Name, createFileCommand.Fields, 0).
  86 + WithPrefix(domain.MainTable.ToString()).WithContext(&domain.Context{})
  87 + tableRepository, _, _ := factory.FastPgTable(transactionContext, 0)
  88 + if table, err = tableRepository.Save(table); err != nil {
  89 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  90 + }
  91 + domainService.ByteCore.LoadDataTable(domain.ReqLoadDataTable{
  92 + FileId: file.FileId,
  93 + FileName: file.FileInfo.Name,
  94 + Url: file.FileInfo.Url,
  95 + Ext: file.FileInfo.Ext,
  96 + //Where: where,
  97 + OriginalTableId: fmt.Sprintf("%v", file.FileId),
  98 + IsFromOriginalTable: true,
  99 + TableFileUrl: file.FileInfo.Url,
  100 + ColumnSchemas: bytelib.DomainFieldsToColumnSchemas(table.Fields(false)),
  101 + SortParameters: make(map[string]interface{}),
  102 + })
  103 + response, err := domainService.ByteCore.SaveTable(domain.ReqSaveTable{FileId: file.FileId, Table: table})
  104 + if err != nil {
  105 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  106 + }
  107 + if _, err = domainService.ByteCore.GenerateTable(ctx, domain.ReqGenerateTable{
  108 + file.FileId, response.Url, table,
  109 + }); err != nil {
  110 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  111 + }
  112 + file.FileInfo.TableId = table.TableId
  113 + if file, err = fileRepository.Save(file); err != nil {
  114 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  115 + }
  116 + }
81 if err = factory.FastLog(transactionContext, domain.CommonLog, file.FileId, &domainService.FileUploadSuccessLog{ 117 if err = factory.FastLog(transactionContext, domain.CommonLog, file.FileId, &domainService.FileUploadSuccessLog{
82 LogEntry: domain.NewLogEntry(file.FileInfo.Name, domain.SourceFile.ToString(), domain.FileUpload, ctx), 118 LogEntry: domain.NewLogEntry(file.FileInfo.Name, domain.SourceFile.ToString(), domain.FileUpload, ctx),
83 }); err != nil { 119 }); err != nil {
@@ -86,7 +122,7 @@ func (fileService *FileService) CreateFile(ctx *domain.Context, createFileComman @@ -86,7 +122,7 @@ func (fileService *FileService) CreateFile(ctx *domain.Context, createFileComman
86 if err := transactionContext.CommitTransaction(); err != nil { 122 if err := transactionContext.CommitTransaction(); err != nil {
87 return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) 123 return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
88 } 124 }
89 - return struct{}{}, nil 125 + return file, nil
90 } 126 }
91 127
92 // GetFile 返回文件服务 128 // GetFile 返回文件服务
@@ -68,6 +68,14 @@ func (tableService *TableService) FieldOptionalValues(ctx *domain.Context, cmd * @@ -68,6 +68,14 @@ func (tableService *TableService) FieldOptionalValues(ctx *domain.Context, cmd *
68 if !ok { 68 if !ok {
69 return nil, factory.FastError(fmt.Errorf("列:%v 不存在", cmd.Field.Name)) 69 return nil, factory.FastError(fmt.Errorf("列:%v 不存在", cmd.Field.Name))
70 } 70 }
  71 + // 字段只传name时,补齐sqlName
  72 + for i, c := range cmd.Where.Conditions {
  73 + if c.Field != nil && c.Field.SQLName == "" {
  74 + if v, ok := table.MatchField(c.Field); ok {
  75 + cmd.Where.Conditions[i].Field.SQLName = v.SQLName
  76 + }
  77 + }
  78 + }
71 if table.TableType == domain.SubTable.ToString() && field.Flag == domain.ManualField { 79 if table.TableType == domain.SubTable.ToString() && field.Flag == domain.ManualField {
72 return empty, nil 80 return empty, nil
73 } 81 }
@@ -30,6 +30,16 @@ func (tableService *TableService) TablePreview(ctx *domain.Context, cmd *command @@ -30,6 +30,16 @@ func (tableService *TableService) TablePreview(ctx *domain.Context, cmd *command
30 if err != nil { 30 if err != nil {
31 return nil, factory.FastError(err) 31 return nil, factory.FastError(err)
32 } 32 }
  33 +
  34 + // 字段只传name时,补齐sqlName
  35 + for i, c := range cmd.Where.Conditions {
  36 + if c.Field != nil && c.Field.SQLName == "" {
  37 + if v, ok := table.MatchField(c.Field); ok {
  38 + cmd.Where.Conditions[i].Field.SQLName = v.SQLName
  39 + }
  40 + }
  41 + }
  42 +
33 // 方案 计算项 计算集 做缓存 43 // 方案 计算项 计算集 做缓存
34 if cmd.UseCache && table.AssertTableType(domain.SchemaTable, domain.CalculateItem, domain.CalculateSet) { 44 if cmd.UseCache && table.AssertTableType(domain.SchemaTable, domain.CalculateItem, domain.CalculateSet) {
35 if d, ok := cache.GetDataTable(table.TableId); ok { 45 if d, ok := cache.GetDataTable(table.TableId); ok {
@@ -102,12 +102,14 @@ type EditTableRequest struct { @@ -102,12 +102,14 @@ type EditTableRequest struct {
102 102
103 type TableEditDataService interface { 103 type TableEditDataService interface {
104 RowEdit(ctx *Context, request EditDataRequest) (interface{}, error) 104 RowEdit(ctx *Context, request EditDataRequest) (interface{}, error)
  105 + BatchAdd(ctx *Context, request EditDataRequest) (interface{}, error)
105 } 106 }
106 type EditDataRequest struct { 107 type EditDataRequest struct {
107 - TableId int `json:"tableId"`  
108 - Table *Table  
109 - UpdateList []*FieldValues `json:"updateList"`  
110 - RemoveList []*FieldValues `json:"removeList"`  
111 - AddList []*FieldValues `json:"addList"`  
112 - Where Where `json:"where"` 108 + TableId int `json:"tableId"`
  109 + Table *Table
  110 + UpdateList []*FieldValues `json:"updateList"`
  111 + RemoveList []*FieldValues `json:"removeList"`
  112 + AddList []*FieldValues `json:"addList"`
  113 + Where Where `json:"where"`
  114 + IgnoreTableType bool
113 } 115 }
@@ -129,6 +129,7 @@ var ObjectTypeMap = map[string]string{ @@ -129,6 +129,7 @@ var ObjectTypeMap = map[string]string{
129 var ( 129 var (
130 XLS = ".xls" 130 XLS = ".xls"
131 XLSX = ".xlsx" 131 XLSX = ".xlsx"
  132 + CSV = ".csv"
132 ) 133 )
133 134
134 var ( 135 var (
@@ -98,6 +98,50 @@ func (ptr *AppendDataToTableService) AppendData(ctx *domain.Context, fileId int, @@ -98,6 +98,50 @@ func (ptr *AppendDataToTableService) AppendData(ctx *domain.Context, fileId int,
98 }, nil 98 }, nil
99 } 99 }
100 100
  101 +// AppendDataDirectly 直接追加数据
  102 +func (ptr *AppendDataToTableService) AppendDataDirectly(ctx *domain.Context, fileUrl string, table *domain.Table, mappingFields []*domain.MappingField) (interface{}, error) {
  103 + defer func() {
  104 + //AsyncEvent(domain.NewEventTable(ctx, domain.TableDataImportEvent).WithTable(table))
  105 + }()
  106 + if !(table.TableType == domain.MainTable.ToString() || table.TableType == domain.SideTable.ToString()) {
  107 + return nil, fmt.Errorf("只能追加数据到主表或者副表")
  108 + }
  109 + var err error
  110 + // 通知底层进行追加数据
  111 + requestData := domain.ReqAppendData{Table: table, FileId: int(time.Now().Unix()), FileUrl: fileUrl, ExcelTable: table}
  112 + if len(mappingFields) > 0 {
  113 + for _, m := range mappingFields {
  114 + var toField, fromField *domain.Field
  115 + var ok bool
  116 + toField, ok = table.MatchField(m.MainTableField)
  117 + if !ok {
  118 + continue
  119 + }
  120 + if len(m.VerifiedFileFieldName) == 0 {
  121 + fromField = &domain.Field{}
  122 + } else {
  123 + fromField, ok = table.MatchField(&domain.Field{Name: m.VerifiedFileFieldName})
  124 + if !ok {
  125 + continue
  126 + }
  127 + }
  128 + if fromField.SQLType != "" && !toField.SqlTypeEqual(fromField) {
  129 + //return nil, fmt.Errorf("字段【%s】的类型与导入数据表的类型不匹配", toField.Name)
  130 + return map[string]interface{}{
  131 + "result": fmt.Sprintf("字段【%s】的类型与导入数据表的类型不匹配", toField.Name),
  132 + }, nil
  133 + }
  134 + fromField.SQLType = toField.SQLType // 兼容 INT BIGINT
  135 + requestData.To = append(requestData.To, toField)
  136 + requestData.From = append(requestData.From, fromField)
  137 + }
  138 + }
  139 + if _, err = ByteCore.AppendData(requestData); err != nil {
  140 + return nil, err
  141 + }
  142 + return nil, nil
  143 +}
  144 +
101 // PreflightCheck 预检 145 // PreflightCheck 预检
102 func (ptr *AppendDataToTableService) PreflightCheck(ctx *domain.Context, fileId int, tableId int, mappingFields []*domain.MappingField) (interface{}, error) { 146 func (ptr *AppendDataToTableService) PreflightCheck(ctx *domain.Context, fileId int, tableId int, mappingFields []*domain.MappingField) (interface{}, error) {
103 tableRepository, _ := repository.NewTableRepository(ptr.transactionContext) 147 tableRepository, _ := repository.NewTableRepository(ptr.transactionContext)
@@ -35,7 +35,7 @@ func (ptr *TableEditDataService) RowEdit(ctx *domain.Context, request domain.Edi @@ -35,7 +35,7 @@ func (ptr *TableEditDataService) RowEdit(ctx *domain.Context, request domain.Edi
35 } 35 }
36 } 36 }
37 37
38 - if table.TableType != domain.SideTable.ToString() { 38 + if table.TableType != domain.SideTable.ToString() && !request.IgnoreTableType {
39 return nil, fmt.Errorf("副表才允许编辑数据") 39 return nil, fmt.Errorf("副表才允许编辑数据")
40 } 40 }
41 defer func() { 41 defer func() {
@@ -68,6 +68,31 @@ func (ptr *TableEditDataService) RowEdit(ctx *domain.Context, request domain.Edi @@ -68,6 +68,31 @@ func (ptr *TableEditDataService) RowEdit(ctx *domain.Context, request domain.Edi
68 return nil, nil 68 return nil, nil
69 } 69 }
70 70
  71 +// BatchAdd 行数据批量添加
  72 +func (ptr *TableEditDataService) BatchAdd(ctx *domain.Context, request domain.EditDataRequest) (interface{}, error) {
  73 + tableRepository, _ := repository.NewTableRepository(ptr.transactionContext)
  74 + var table *domain.Table = request.Table
  75 + var err error
  76 + if table == nil {
  77 + table, err = tableRepository.FindOne(map[string]interface{}{"tableId": request.TableId})
  78 + if err != nil {
  79 + return nil, err
  80 + }
  81 + }
  82 +
  83 + defer func() {
  84 + AsyncEvent(domain.NewEventTable(ctx, domain.TableDataEditEvent).WithTable(table))
  85 + }()
  86 +
  87 + for _, l := range request.AddList {
  88 + // 添加记录
  89 + if err = starrocks.Insert(starrocks.DB, table.SQLName, l.FieldValues); err != nil {
  90 + log.Logger.Error(fmt.Sprintf("添加记录错误:%v", err.Error()))
  91 + }
  92 + }
  93 + return nil, nil
  94 +}
  95 +
71 func (ptr *TableEditDataService) add(ctx *domain.Context, table *domain.Table, list *domain.FieldValues, where domain.Where) error { 96 func (ptr *TableEditDataService) add(ctx *domain.Context, table *domain.Table, list *domain.FieldValues, where domain.Where) error {
72 var err error 97 var err error
73 98
@@ -113,3 +138,41 @@ func (ptr *TableEditDataService) update(ctx *domain.Context, table *domain.Table @@ -113,3 +138,41 @@ func (ptr *TableEditDataService) update(ctx *domain.Context, table *domain.Table
113 } 138 }
114 return nil 139 return nil
115 } 140 }
  141 +
  142 +func MapArrayToFieldValues(list []map[string]string, table *domain.Table, dataTable *domain.DataTable, mustMatch bool) []*domain.FieldValues {
  143 + var result = make([]*domain.FieldValues, 0)
  144 + //history := dto.ToFieldDataByPK(table, dataTable)
  145 + mapField := domain.Fields(table.Fields(true)).ToMapBySqlName()
  146 + for _, m := range list {
  147 + var fieldValues = &domain.FieldValues{
  148 + FieldValues: make([]*domain.FieldValue, 0),
  149 + }
  150 + //matchItem, ok := history[m[domain.DefaultPkField]]
  151 + //if mustMatch {
  152 + // if !ok {
  153 + // continue
  154 + // }
  155 + //}
  156 + if _, ok := m[domain.DefaultPkField]; !ok {
  157 + m[domain.DefaultPkField] = ""
  158 + }
  159 + for key, value := range m {
  160 + field, ok := mapField[key]
  161 + if !ok || field.Flag == domain.ManualField {
  162 + continue
  163 + }
  164 + fieldValue := &domain.FieldValue{
  165 + Field: field,
  166 + Value: value,
  167 + }
  168 + //if mustMatch {
  169 + // if oldValue, ok := matchItem[key]; ok {
  170 + // fieldValue.OldValue = oldValue
  171 + // }
  172 + //}
  173 + fieldValues.FieldValues = append(fieldValues.FieldValues, fieldValue)
  174 + }
  175 + result = append(result, fieldValues)
  176 + }
  177 + return result
  178 +}
@@ -172,3 +172,15 @@ insert into {{.ViewName}} Values {{.Values}} @@ -172,3 +172,15 @@ insert into {{.ViewName}} Values {{.Values}}
172 }) 172 })
173 return html.UnescapeString(buf.String()) 173 return html.UnescapeString(buf.String())
174 } 174 }
  175 +
  176 +func AddTableColumn(db *gorm.DB, tableName string, filed *domain.Field) error {
  177 + tx := db.Exec(fmt.Sprintf("ALTER TABLE %s ADD COLUMN %s %s", tableName, filed.SQLName, convertFiledSQLType(filed.SQLType)))
  178 + return tx.Error
  179 +}
  180 +
  181 +func convertFiledSQLType(sqlType string) string {
  182 + if sqlType == domain.Float.ToString() || sqlType == domain.DECIMAL279.ToString() {
  183 + return domain.DECIMAL279.ToString()
  184 + }
  185 + return sqlType
  186 +}
@@ -58,7 +58,7 @@ func init() { @@ -58,7 +58,7 @@ func init() {
58 web.InsertFilter("/*", web.BeforeRouter, RequestCostBefore()) 58 web.InsertFilter("/*", web.BeforeRouter, RequestCostBefore())
59 web.InsertFilter("/*", web.BeforeExec, controllers.BlacklistFilter(controllers.BlacklistRouters)) 59 web.InsertFilter("/*", web.BeforeExec, controllers.BlacklistFilter(controllers.BlacklistRouters))
60 web.InsertFilter("/*", web.BeforeExec, CreateRequestLogFilter(true)) // filters.CreateRequstLogFilter(Logger) 60 web.InsertFilter("/*", web.BeforeExec, CreateRequestLogFilter(true)) // filters.CreateRequstLogFilter(Logger)
61 - if constant.SERVICE_ENV == "dev" { //|| web.BConfig.RunMode =="test" 61 + if constant.SERVICE_ENV == "test" { //|| web.BConfig.RunMode =="test"
62 web.InsertFilter("/*", web.AfterExec, filters.CreateResponseLogFilter(Logger), web.WithReturnOnOutput(false)) 62 web.InsertFilter("/*", web.AfterExec, filters.CreateResponseLogFilter(Logger), web.WithReturnOnOutput(false))
63 } 63 }
64 web.InsertFilter("/*", web.AfterExec, RequestCostAfter(150), web.WithReturnOnOutput(false)) 64 web.InsertFilter("/*", web.AfterExec, RequestCostAfter(150), web.WithReturnOnOutput(false))
@@ -34,8 +34,14 @@ func (controller *FileController) CreateAppTableFile() { @@ -34,8 +34,14 @@ func (controller *FileController) CreateAppTableFile() {
34 return 34 return
35 } 35 }
36 createFileCommand.AppKey = ParseAppKey(controller.BaseController) 36 createFileCommand.AppKey = ParseAppKey(controller.BaseController)
37 - data, err := fileService.CreateFile(&domain.Context{}, createFileCommand)  
38 - controller.Response(data, err) 37 + // GenerateTableFlag 如果是true,生成主表
  38 + if createDigitalAppFileCommand.GenerateTableFlag {
  39 + createFileCommand.GenerateTableFlag = true
  40 + createFileCommand.Fields = createDigitalAppFileCommand.Fields
  41 + }
  42 + _, err = fileService.CreateFile(&domain.Context{}, createFileCommand)
  43 +
  44 + controller.Response(struct{}{}, err)
39 } 45 }
40 46
41 func (controller *FileController) DeleteAppTableFile() { 47 func (controller *FileController) DeleteAppTableFile() {
@@ -52,7 +58,17 @@ func (controller *FileController) AppendDataAppTableFile() { @@ -52,7 +58,17 @@ func (controller *FileController) AppendDataAppTableFile() {
52 cmd := &command.AppTableFileAppendDataCommand{} 58 cmd := &command.AppTableFileAppendDataCommand{}
53 controller.Unmarshal(cmd) 59 controller.Unmarshal(cmd)
54 cmd.AppKey = ParseAppKey(controller.BaseController) 60 cmd.AppKey = ParseAppKey(controller.BaseController)
55 - data, err := fileService.AppTableFileAppendData(&domain.Context{}, cmd) 61 + var (
  62 + data interface{}
  63 + err error
  64 + )
  65 + // AppendDataToTableFlag 如果是true,生成主表 追加数据道表
  66 + if cmd.AppendTableDataFlag {
  67 + data, err = fileService.AppTableAppendDataDirect(&domain.Context{}, cmd)
  68 + } else {
  69 + data, err = fileService.AppTableFileAppendData(&domain.Context{}, cmd)
  70 + }
  71 +
56 controller.Response(data, err) 72 controller.Response(data, err)
57 } 73 }
58 74
@@ -65,6 +81,15 @@ func (controller *FileController) ListAppTableFile() { @@ -65,6 +81,15 @@ func (controller *FileController) ListAppTableFile() {
65 controller.Response(data, err) 81 controller.Response(data, err)
66 } 82 }
67 83
  84 +func (controller *FileController) UpdateAppTableFile() {
  85 + fileService := service.NewFileService(nil)
  86 + cmd := &command.UpdateAppTableFileCommand{}
  87 + controller.Unmarshal(cmd)
  88 + cmd.AppKey = ParseAppKey(controller.BaseController)
  89 + data, err := fileService.UpdateAppTableFile(&domain.Context{}, cmd)
  90 + controller.Response(data, err)
  91 +}
  92 +
68 func (controller *FileController) UpdateFile() { 93 func (controller *FileController) UpdateFile() {
69 fileService := service.NewFileService(nil) 94 fileService := service.NewFileService(nil)
70 updateFileCommand := &command.UpdateFileCommand{} 95 updateFileCommand := &command.UpdateFileCommand{}
@@ -12,4 +12,5 @@ func init() { @@ -12,4 +12,5 @@ func init() {
12 web.Router("/api/app-table-file/delete", &controllers.FileController{}, "Post:DeleteAppTableFile") 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") 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") 14 web.Router("/api/app-table-file/list", &controllers.FileController{}, "Post:ListAppTableFile")
  15 + web.Router("/api/app-table-file/update", &controllers.FileController{}, "Post:UpdateAppTableFile")
15 } 16 }