作者 yangfu

feat: router define

... ... @@ -9,3 +9,104 @@
- 持久化 - flushDataTable
- 导出 - url
- 删除 - delete
- 操作日志 - log
- editDataTable params 列表
### 加载表格数据 loadDataTable - 查询
```json
{
"fileId": 1,
"where": [
{
"field": {
"index": 1,
"name": "产品名称"
},
"in": ["a","b"],
"ex": ["c","d"],
"sort": ["a","asc"]
}
]
}
```
### 编辑表格 editDataTable
```json
{
"field": {
"index": 1,
"name": "产品名称"
},
"operation": {
"desc": ["拆分","按字符数"],
"code": "split_by_char_number"
},
"params": []
}
```
精简
```json
{
"field": "产品名称",
"desc": ["拆分","按字符数"],
"operationCode": "split_by_char_number",
"params": []
}
```
`params 列表`
### 数据展示
```json
{
"code": 0,
"data": {
"dataFields": [
{
"index": 1,
"name": "产品名称",
"Type": "string"
},
{
"index": 2,
"name": "产品数量",
"Type": "number"
}
],
"dataRows": [
[
"素面",
200
],
[
"冻豆腐",
400
],
[
"冻豆腐1",
300
],
[
"冻豆2",
"A"
]
],
"total": 100,
"pageNumber": 1,
"inValidCells": [
{
"x": 1,
"y": 3,
"error": "不是一个有效的数值"
}
]
},
"msg": "ok"
}
```
\ No newline at end of file
... ...
... ... @@ -13,12 +13,12 @@ type CreateFileCommand struct {
Name string `cname:"名称" json:"name" valid:"Required"`
// 文件地址
Url string `cname:"文件地址" json:"url" valid:"Required"`
// 文件大小
// 文件大小 单位KB
FileSize int `cname:"文件大小" json:"fileSize" valid:"Required"`
}
func (createFileCommand *CreateFileCommand) Valid(validation *validation.Validation) {
validation.SetError("CustomValid", "未实现的自定义认证")
}
func (createFileCommand *CreateFileCommand) ValidateCommand() error {
... ...
... ... @@ -14,7 +14,7 @@ type EditDataTableCommand struct {
}
func (editDataTableCommand *EditDataTableCommand) Valid(validation *validation.Validation) {
validation.SetError("CustomValid", "未实现的自定义认证")
}
func (editDataTableCommand *EditDataTableCommand) ValidateCommand() error {
... ...
... ... @@ -14,7 +14,7 @@ type LoadDataTableCommand struct {
}
func (loadDataTableCommand *LoadDataTableCommand) Valid(validation *validation.Validation) {
validation.SetError("CustomValid", "未实现的自定义认证")
}
func (loadDataTableCommand *LoadDataTableCommand) ValidateCommand() error {
... ...
... ... @@ -14,7 +14,7 @@ type RemoveFileCommand struct {
}
func (removeFileCommand *RemoveFileCommand) Valid(validation *validation.Validation) {
validation.SetError("CustomValid", "未实现的自定义认证")
}
func (removeFileCommand *RemoveFileCommand) ValidateCommand() error {
... ...
package dto
type DataTableDto struct {
DataFields []*Field `json:"dataFields"`
DataRows [][]interface{} `json:"dataRows"`
Total int `json:"total"`
PageNumber int `json:"pageNumber"`
InValidCells []InValidCell `json:"inValidCells"`
}
type Field struct {
// 索引序号
Index int `json:"index"`
// 名称
Name string `json:"name"`
// 对应数据库类型
Type string `json:"Type"`
}
type InValidCell struct {
X int `json:"x"`
Y int `json:"y"`
Error string `json:"error"`
}
func NewDataTableDtoDemo() DataTableDto {
return DataTableDto{
DataFields: []*Field{
{
Index: 1,
Name: "产品名称",
Type: "string",
},
{
Index: 2,
Name: "产品数量",
Type: "number",
},
},
DataRows: [][]interface{}{
{"素面", 200},
{"冻豆腐", 400},
{"冻豆腐1", 300},
{"冻豆2", "A"},
},
InValidCells: []InValidCell{
{
X: 1,
Y: 3,
Error: "不是一个有效的数值",
},
},
PageNumber: 1,
Total: 100,
}
}
... ...
package query
import (
"fmt"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
"reflect"
"strings"
"github.com/beego/beego/v2/core/validation"
)
type SearchFileQuery struct {
// 查询偏离量
// Offset int `cname:"查询偏离量" json:"offset"`
// 查询限制
Limit int `cname:"查询限制" json:"limit"`
// 页码
// PageNumber int `cname:"页码" json:"pageNumber,omitempty"`
// 页数
FileName int `cname:"文件名称" json:"fileName,omitempty"`
PageSize int `cname:"页数" json:"pageSize,omitempty"`
LastId int `cname:"最后一条记录ID" json:"lastId"`
FileType domain.FileType `cname:"文件类型" json:"fileType" valid:"Required"`
}
func (cmd *SearchFileQuery) Valid(validation *validation.Validation) {
cmd.Limit = cmd.PageSize
}
func (cmd *SearchFileQuery) ValidateQuery() error {
valid := validation.Validation{}
b, err := valid.Valid(cmd)
if err != nil {
return err
}
if !b {
elem := reflect.TypeOf(cmd).Elem()
for _, validErr := range valid.Errors {
field, isExist := elem.FieldByName(validErr.Field)
if isExist {
return fmt.Errorf(strings.Replace(validErr.Message, validErr.Field, field.Tag.Get("cname"), -1))
} else {
return fmt.Errorf(validErr.Message)
}
}
}
return nil
}
... ...
... ... @@ -6,6 +6,7 @@ import (
"github.com/linmadan/egglib-go/utils/tool_funs"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/factory"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/file/command"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/file/dto"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/file/query"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
)
... ... @@ -29,27 +30,27 @@ func (fileService *FileService) CreateFile(createFileCommand *command.CreateFile
defer func() {
transactionContext.RollbackTransaction()
}()
newFile := &domain.File{
//newFile := &domain.File{
//Name: createFileCommand.Name,
//Url: createFileCommand.Url,
//FileSize: createFileCommand.FileSize,
}
var fileRepository domain.FileRepository
if value, err := factory.CreateFileRepository(map[string]interface{}{
"transactionContext": transactionContext,
}); err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
} else {
fileRepository = value
}
if file, err := fileRepository.Save(newFile); err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
} else {
//}
//var fileRepository domain.FileRepository
//if value, err := factory.CreateFileRepository(map[string]interface{}{
// "transactionContext": transactionContext,
//}); err != nil {
// return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
//} else {
// fileRepository = value
//}
//file, err := fileRepository.Save(newFile)
//if err != nil {
// return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
//}
if err := transactionContext.CommitTransaction(); err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
return file, nil
}
return struct{}{}, nil
}
// 编辑表格数据
... ... @@ -70,7 +71,7 @@ func (fileService *FileService) EditDataTable(editDataTableCommand *command.Edit
if err := transactionContext.CommitTransaction(); err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
return nil, nil
return struct{}{}, nil
}
// 持久化表格数据
... ... @@ -188,6 +189,42 @@ func (fileService *FileService) ListFile(listFileQuery *query.ListFileQuery) (in
}
}
// 返回文件服务列表
func (fileService *FileService) SearchFile(listFileQuery *query.SearchFileQuery) (interface{}, error) {
if err := listFileQuery.ValidateQuery(); err != nil {
return nil, application.ThrowError(application.ARG_ERROR, err.Error())
}
transactionContext, err := factory.CreateTransactionContext(nil)
if err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
if err := transactionContext.StartTransaction(); err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
defer func() {
transactionContext.RollbackTransaction()
}()
var fileRepository domain.FileRepository
if value, err := factory.CreateFileRepository(map[string]interface{}{
"transactionContext": transactionContext,
}); err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
} else {
fileRepository = value
}
count, files, err := fileRepository.Find(tool_funs.SimpleStructToMap(listFileQuery))
if err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
}
if err := transactionContext.CommitTransaction(); err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
return map[string]interface{}{
"count": count,
"files": files,
}, nil
}
// 加载表格数据
func (fileService *FileService) LoadDataTable(loadDataTableCommand *command.LoadDataTableCommand) (interface{}, error) {
if err := loadDataTableCommand.ValidateCommand(); err != nil {
... ... @@ -206,7 +243,8 @@ func (fileService *FileService) LoadDataTable(loadDataTableCommand *command.Load
if err := transactionContext.CommitTransaction(); err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
return nil, nil
return dto.NewDataTableDtoDemo(), nil
}
// 移除文件服务
... ...
package domain
type FileType string
var (
SourceFile FileType = "SourceFile"
VerifiedFile FileType = "VerifiedFile"
TemporaryFile FileType = "TemporaryFile"
)
var (
GenerateMainTable OperationType = "GenerateMainTable" // 主表生成
SpiltMainTable OperationType = "SpiltMainTable" //主表拆分
ImportData OperationType = "ImportData" //数据导入
GenerateSubTable OperationType = "GenerateSubTable" //分表生成
CopyTable OperationType = "CopyTable" //表复制
RowEdit OperationType = "RowEdit" // 编辑记录
FileUpload OperationType = "FileUpload" // 文件上传
FileVerify OperationType = "FileVerify" // 文件校验
)
var (
VerifiedStepLog LogType = 1
CommonLog LogType = 2
)
var (
MainTable TableType = "MainTable"
SideTable TableType = "SideTable"
SubTable TableType = "SubTable"
ExcelTable TableType = "ExcelTable"
VerifiedExcelTable TableType = "VerifiedExcelTable"
)
func (t FileType) ToString() string {
return string(t)
}
type LogType int
type TableType string
func (t TableType) ToString() string {
return string(t)
}
type ObjectType TableType
type OperationType string
func (t OperationType) ToString() string {
return string(t)
}
... ...
... ... @@ -17,11 +17,11 @@ type Table struct {
// 数据字段序号
DataFieldIndex int `json:"dataFieldIndex"`
// 主键字段
PK string `json:"pK"`
PK *Field `json:"pK"`
// 数据列
DataFields string `json:"dataFields"`
DataFields []*Field `json:"dataFields"`
// 手动添加的列
ManualFields string `json:"manualFields"`
ManualFields []*Field `json:"manualFields"`
// 创建时间
CreatedAt time.Time `json:"createdAt"`
// 更新时间
... ...
... ... @@ -5,6 +5,7 @@ import (
"github.com/go-pg/pg/v10"
"github.com/go-pg/pg/v10/orm"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/constant"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/pg/models"
//_ "gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/infrastructure/pg/models"
"github.com/linmadan/egglib-go/persistent/pg/comment"
... ... @@ -24,7 +25,11 @@ func init() {
DB.AddQueryHook(hooks.SqlGeneratePrintHook{})
}
if !constant.DISABLE_CREATE_TABLE {
for _, model := range []interface{}{} {
for _, model := range []interface{}{
(*models.File)(nil),
(*models.Table)(nil),
(*models.Log)(nil),
} {
err := DB.Model(model).CreateTable(&orm.CreateTableOptions{
Temp: false,
IfNotExists: true,
... ...
... ... @@ -22,7 +22,7 @@ type File struct {
// 更新时间
UpdatedAt time.Time `comment:"更新时间"`
// 删除时间
DeletedAt time.Time `comment:"删除时间"`
DeletedAt time.Time `pg:",soft_delete" comment:"删除时间"`
// 版本
Version int `comment:"版本"`
}
... ...
package models
import "time"
import (
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
"time"
)
type Table struct {
tableName string `comment:"表" pg:"metadata.tables,alias:table"`
... ... @@ -17,17 +20,17 @@ type Table struct {
// 数据字段序号
DataFieldIndex int `comment:"数据字段序号"`
// 主键字段
PK string `comment:"主键字段"`
PK *domain.Field `comment:"主键字段"`
// 数据列
DataFields string `comment:"数据列"`
DataFields []*domain.Field `comment:"数据列"`
// 手动添加的列
ManualFields string `comment:"手动添加的列"`
ManualFields []*domain.Field `comment:"手动添加的列"`
// 创建时间
CreatedAt time.Time `comment:"创建时间"`
// 更新时间
UpdatedAt time.Time `comment:"更新时间"`
// 删除时间
DeletedAt time.Time `comment:"删除时间"`
DeletedAt time.Time `pg:",soft_delete" comment:"删除时间"`
// 版本
Version int `comment:"版本"`
}
... ...
... ... @@ -68,6 +68,8 @@ func (repository *FileRepository) Save(file *domain.File) (*domain.File, error)
return file, err
}
} else {
oldVersion := file.Version
file.Version += 1
if _, err := tx.QueryOne(
pg.Scan(
&file.FileId,
... ... @@ -80,7 +82,7 @@ func (repository *FileRepository) Save(file *domain.File) (*domain.File, error)
&file.DeletedAt,
&file.Version,
),
fmt.Sprintf("UPDATE metadata.files SET %s WHERE file_id=? RETURNING %s", updateFieldsSnippet, returningFieldsSnippet),
fmt.Sprintf("UPDATE metadata.files SET %s WHERE file_id=? and version=? RETURNING %s", updateFieldsSnippet, returningFieldsSnippet),
file.FileId,
file.FileType,
file.FileInfo,
... ... @@ -91,6 +93,7 @@ func (repository *FileRepository) Save(file *domain.File) (*domain.File, error)
file.DeletedAt,
file.Version,
file.Identify(),
oldVersion,
); err != nil {
return file, err
}
... ...
... ... @@ -81,6 +81,8 @@ func (repository *TableRepository) Save(table *domain.Table) (*domain.Table, err
return table, err
}
} else {
oldVersion := table.Version
table.Version += 1
if _, err := tx.QueryOne(
pg.Scan(
&table.TableId,
... ... @@ -97,7 +99,7 @@ func (repository *TableRepository) Save(table *domain.Table) (*domain.Table, err
&table.DeletedAt,
&table.Version,
),
fmt.Sprintf("UPDATE metadata.tables SET %s WHERE table_id=? RETURNING %s", updateFieldsSnippet, returningFieldsSnippet),
fmt.Sprintf("UPDATE metadata.tables SET %s WHERE table_id=? and version=? RETURNING %s", updateFieldsSnippet, returningFieldsSnippet),
table.TableId,
table.TableType,
table.Name,
... ... @@ -111,6 +113,7 @@ func (repository *TableRepository) Save(table *domain.Table) (*domain.Table, err
table.UpdatedAt,
table.DeletedAt,
table.Version,
oldVersion,
table.Identify(),
); err != nil {
return table, err
... ...
package controllers
import (
"github.com/beego/beego/v2/server/web/context"
"github.com/linmadan/egglib-go/web/beego"
"github.com/linmadan/egglib-go/web/beego/utils"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/log"
)
func ResponseGrid(c beego.BaseController, total int64, data interface{}, err error) {
var response utils.JsonResponse
if err != nil {
response = utils.ResponseError(c.Ctx, err)
} else {
response = ResponseGridData(c.Ctx, total, data)
}
c.Data["json"] = response
c.ServeJSON()
}
func ResponseGridData(ctx *context.Context, total int64, data interface{}) utils.JsonResponse {
jsonResponse := utils.JsonResponse{}
jsonResponse["code"] = 0
jsonResponse["msg"] = "ok"
jsonResponse["data"] = map[string]interface{}{"grid": map[string]interface{}{
"total": total,
"list": data,
}}
ctx.Input.SetData("outputData", jsonResponse)
return jsonResponse
}
func Must(err error) {
if err != nil {
log.Logger.Error(err.Error())
}
}
// ParseOperateInfo 从头部解析操作对象信息
//func ParseOperateInfo(c beego.BaseController) *domain.OperateInfo {
// opt := &domain.OperateInfo{}
// opt.UserId = header(c, constant.HeaderUserId)
// opt.CompanyId = header(c, constant.HeaderCompanyId)
// opt.OrgId = header(c, constant.HeaderOrgId)
// orgIdList := c.Ctx.Input.Header(constant.HeaderOrgIds)
// splitOrgIdList := strings.Split(orgIdList, constant.CUSTOMER_ACCOUNT_DELIMITER)
// for i := range splitOrgIdList {
// orgId, _ := strconv.Atoi(splitOrgIdList[i])
// if orgId == 0 {
// continue
// }
// opt.OrgIds = append(opt.OrgIds, orgId)
// }
// return opt
//}
//
//func header(c beego.BaseController, key string) int {
// if len(c.Ctx.Input.Header(key)) == 0 {
// return 0
// }
// res, err := strconv.Atoi(c.Ctx.Input.Header(key))
// if err != nil {
// log.Logger.Error(err.Error())
// return 0
// }
// return res
//}
... ...
... ... @@ -5,6 +5,7 @@ import (
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/file/command"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/file/query"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/application/file/service"
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
)
type FileController struct {
... ... @@ -59,6 +60,32 @@ func (controller *FileController) ListFile() {
controller.Response(data, err)
}
func (controller *FileController) SearchFile() {
fileService := service.NewFileService(nil)
searchFileQuery := &query.SearchFileQuery{}
Must(controller.Unmarshal(searchFileQuery))
data, err := fileService.SearchFile(searchFileQuery)
controller.Response(data, err)
}
func (controller *FileController) SearchSourceFile() {
fileService := service.NewFileService(nil)
searchFileQuery := &query.SearchFileQuery{}
Must(controller.Unmarshal(searchFileQuery))
searchFileQuery.FileType = domain.SourceFile
data, err := fileService.SearchFile(searchFileQuery)
controller.Response(data, err)
}
func (controller *FileController) SearchVerifiedFile() {
fileService := service.NewFileService(nil)
searchFileQuery := &query.SearchFileQuery{}
Must(controller.Unmarshal(searchFileQuery))
searchFileQuery.FileType = domain.VerifiedFile
data, err := fileService.SearchFile(searchFileQuery)
controller.Response(data, err)
}
func (controller *FileController) LoadDataTable() {
fileService := service.NewFileService(nil)
loadDataTableCommand := &command.LoadDataTableCommand{}
... ...
... ... @@ -11,6 +11,11 @@ func init() {
web.Router("/bastion/files/:fileId", &controllers.FileController{}, "Get:GetFile")
web.Router("/bastion/files/:fileId", &controllers.FileController{}, "Delete:RemoveFile")
web.Router("/bastion/files/", &controllers.FileController{}, "Get:ListFile")
web.Router("/bastion/files/search", &controllers.FileController{}, "Post:SearchFile")
web.Router("/bastion/files/search", &controllers.FileController{}, "Post:SearchFile")
web.Router("/bastion/files/search-source-file", &controllers.FileController{}, "Post:SearchSourceFile")
web.Router("/bastion/files/search-verified-file", &controllers.FileController{}, "Post:SearchVerifiedFile")
web.Router("/bastion/load-data-table", &controllers.FileController{}, "Post:LoadDataTable")
web.Router("/bastion/edit-data-table", &controllers.FileController{}, "Post:EditDataTable")
web.Router("/bastion/flush-data-table", &controllers.FileController{}, "Post:FlushDataTable")
... ...