作者 yangfu

Merge branch 'test'

正在显示 61 个修改的文件 包含 1397 行增加128 行删除
  1 +ALTER TABLE files ADD file_from TEXT;
  2 +ALTER TABLE files ADD app_key TEXT;
  3 +Update files set file_from = 'ByteBankWebClient';
  4 +
  5 +CREATE INDEX IF NOT EXISTS idx_files_app_key ON metadata.files USING btree(app_key);
@@ -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 +}
  1 +package command
  2 +
  3 +type DeleteAppTableFileCommand struct {
  4 + Name string `json:"name"`
  5 + AppKey string `json:"appKey"`
  6 +}
@@ -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 +}
  1 +package query
  2 +
  3 +type ListAppTableFileCommand struct {
  4 + Name string `json:"name"`
  5 + AppKey string `json:"appKey"`
  6 +}
@@ -21,6 +21,7 @@ type SearchFileQuery struct { @@ -21,6 +21,7 @@ type SearchFileQuery struct {
21 PageSize int `cname:"页数" json:"pageSize,omitempty"` 21 PageSize int `cname:"页数" json:"pageSize,omitempty"`
22 LastId int `cname:"最后一条记录ID" json:"lastId"` 22 LastId int `cname:"最后一条记录ID" json:"lastId"`
23 FileType domain.FileType `cname:"文件类型" json:"fileType" valid:"Required"` 23 FileType domain.FileType `cname:"文件类型" json:"fileType" valid:"Required"`
  24 + InAppKeys []string `json:"inAppKeys"`
24 Context *domain.Context 25 Context *domain.Context
25 } 26 }
26 27
  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)  
60 - } 54 +
  55 + var (
  56 + querySetMapById = make(map[int]*domain.QuerySet)
61 // BindTableId , parentId 57 // BindTableId , parentId
62 - querySetMapByTableId := make(map[int]*domain.QuerySet) 58 + querySetMapByTableId = make(map[int]*domain.QuerySet)
  59 + )
  60 + if searchQuery.ReturnGroupItem {
  61 + for _, qs := range querySets {
  62 + querySetMapById[qs.QuerySetId] = qs
  63 + }
  64 + }
  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 - 76 + } else {
82 switch table.TableType { 77 switch table.TableType {
83 case domain.CalculateSet.ToString(): 78 case domain.CalculateSet.ToString():
84 response.Fields = dataTable.Fields 79 response.Fields = dataTable.Fields
85 - response.Data = domain.GripData(domain.ToFieldData(dataTable.Fields, dataTable.Data, false), int64(len(dataTable.Data))) 80 + response.Data = domain.GripData(domain.ToFieldData(dataTable.Fields, pageData(cmd.Where.PageNumber, cmd.Where.PageSize, dataTable.Data), false), int64(len(dataTable.Data)))
86 default: 81 default:
87 response.Load(table, dataTable, domain.ObjectMetaTable) 82 response.Load(table, dataTable, domain.ObjectMetaTable)
88 } 83 }
  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 +}
  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) 110 + var err error
  111 + if len(options.FileMap) == 0 {
  112 + r, err = r.JSONBody(requestParam.Param)
108 if err != nil { 113 if err != nil {
109 return err 114 return err
110 } 115 }
111 - byteResult, err := req.Bytes() 116 + }
  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)
@@ -10,12 +10,14 @@ type RequestCheckoutTablesQuery struct { @@ -10,12 +10,14 @@ type RequestCheckoutTablesQuery struct {
10 OriginalTableId string `json:"originalTableId"` 10 OriginalTableId string `json:"originalTableId"`
11 IsFromOriginalTable bool `json:"isFromOriginalTable"` 11 IsFromOriginalTable bool `json:"isFromOriginalTable"`
12 TableFileUrl string `json:"tableFileUrl"` 12 TableFileUrl string `json:"tableFileUrl"`
  13 + TableFileUrlInternal string `json:"tableFileUrlInternal"`
13 ColumnSchemas []domain.ColumnSchema `json:"columnSchemas"` 14 ColumnSchemas []domain.ColumnSchema `json:"columnSchemas"`
14 PageNumber int `json:"pageNumber"` 15 PageNumber int `json:"pageNumber"`
15 PageSize int `json:"pageSize"` 16 PageSize int `json:"pageSize"`
16 QueryParameters []domain.QueryParameter `json:"queryParameters"` 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,10 +39,14 @@ func NewRequestCheckoutTablesQuery(param domain.ReqLoadDataTable) RequestCheckou @@ -37,10 +39,14 @@ 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, 46 OriginalTableId: param.OriginalTableId,
42 IsFromOriginalTable: isSourceFile, 47 IsFromOriginalTable: isSourceFile,
43 - TableFileUrl: tableFileUrl, 48 + TableFileUrl: domain.ConvertFileUrlToInternal(tableFileUrl),
  49 + TableFileUrlInternal: tableFileUrl,
44 ColumnSchemas: param.ColumnSchemas, 50 ColumnSchemas: param.ColumnSchemas,
45 PageNumber: param.PageNumber, 51 PageNumber: param.PageNumber,
46 PageSize: param.PageSize, 52 PageSize: param.PageSize,
@@ -48,6 +54,7 @@ func NewRequestCheckoutTablesQuery(param domain.ReqLoadDataTable) RequestCheckou @@ -48,6 +54,7 @@ func NewRequestCheckoutTablesQuery(param domain.ReqLoadDataTable) RequestCheckou
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 {
@@ -128,6 +137,7 @@ type ( @@ -128,6 +137,7 @@ type (
128 RequestCheckoutTablesGenerateMasterTable struct { 137 RequestCheckoutTablesGenerateMasterTable struct {
129 OriginalTableId string `json:"originalTableId"` 138 OriginalTableId string `json:"originalTableId"`
130 CheckoutTableFileUrl string `json:"checkoutTableFileUrl"` 139 CheckoutTableFileUrl string `json:"checkoutTableFileUrl"`
  140 + CheckoutTableFileUrlInternal string `json:"checkoutTableFileUrlInternal"`
131 ColumnSchemas []domain.ColumnSchema `json:"columnSchemas"` 141 ColumnSchemas []domain.ColumnSchema `json:"columnSchemas"`
132 MasterTableName string `json:"masterTableName"` 142 MasterTableName string `json:"masterTableName"`
133 FieldSchemas []FieldSchema `json:"fieldSchemas"` 143 FieldSchemas []FieldSchema `json:"fieldSchemas"`
@@ -148,7 +158,8 @@ type ( @@ -148,7 +158,8 @@ type (
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), 160 OriginalTableId: fmt.Sprintf("%v", param.FileId),
151 - CheckoutTableFileUrl: param.FileUrl, 161 + CheckoutTableFileUrl: domain.ConvertFileUrlToInternal(param.FileUrl),
  162 + CheckoutTableFileUrlInternal: param.FileUrl,
152 ColumnSchemas: DomainFieldsToColumnSchemas(param.Table.DataFields), 163 ColumnSchemas: DomainFieldsToColumnSchemas(param.Table.DataFields),
153 MasterTableName: param.Table.SQLName, 164 MasterTableName: param.Table.SQLName,
154 FieldSchemas: ToFieldSchemas(param.Table.DataFields), 165 FieldSchemas: ToFieldSchemas(param.Table.DataFields),
@@ -162,6 +173,7 @@ type ( @@ -162,6 +173,7 @@ type (
162 //MasterTableId string `json:"masterTableId"` 173 //MasterTableId string `json:"masterTableId"`
163 OriginalTableId string `json:"originalTableId"` 174 OriginalTableId string `json:"originalTableId"`
164 CheckoutTableFileUrl string `json:"checkoutTableFileUrl"` 175 CheckoutTableFileUrl string `json:"checkoutTableFileUrl"`
  176 + CheckoutTableFileUrlInternal string `json:"checkoutTableFileUrlInternal"`
165 DatabaseTableName string `json:"databaseTableName"` 177 DatabaseTableName string `json:"databaseTableName"`
166 ColumnSchemas []domain.ColumnSchema `json:"columnSchemas"` 178 ColumnSchemas []domain.ColumnSchema `json:"columnSchemas"`
167 FieldSchemas []FieldSchema `json:"fieldSchemas"` 179 FieldSchemas []FieldSchema `json:"fieldSchemas"`
@@ -186,7 +198,8 @@ func NewTableAppendRequest(param domain.ReqAppendData) TableAppendRequest { @@ -186,7 +198,8 @@ 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), 200 OriginalTableId: intToString(param.FileId),
189 - CheckoutTableFileUrl: param.FileUrl, 201 + CheckoutTableFileUrl: domain.ConvertFileUrlToInternal(param.FileUrl),
  202 + CheckoutTableFileUrlInternal: param.FileUrl,
190 DatabaseTableName: param.Table.SQLName, 203 DatabaseTableName: param.Table.SQLName,
191 ColumnSchemas: DomainFieldsToColumnSchemas(param.ExcelTable.DataFields), //这里主要需要传递原文件所有字段 param.From 204 ColumnSchemas: DomainFieldsToColumnSchemas(param.ExcelTable.DataFields), //这里主要需要传递原文件所有字段 param.From
192 FieldSchemas: ToFieldSchemas(param.Table.DataFields), 205 FieldSchemas: ToFieldSchemas(param.Table.DataFields),
@@ -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
  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{}
  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 +}
  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 +}
  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 }