424 lines
9.3 KiB
Go
424 lines
9.3 KiB
Go
package internal
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
jsonIter "github.com/json-iterator/go"
|
|
"github.com/kercylan98/minotaur/utils/geometry/matrix"
|
|
"github.com/kercylan98/minotaur/utils/hash"
|
|
"github.com/kercylan98/minotaur/utils/str"
|
|
"github.com/kercylan98/minotaur/utils/xlsxtool"
|
|
"github.com/tealeg/xlsx"
|
|
"strconv"
|
|
"strings"
|
|
"text/template"
|
|
)
|
|
|
|
// NewConfig 定位为空将读取Sheet名称
|
|
// - 表格中需要严格遵守 描述、名称、类型、导出参数、数据列的顺序
|
|
func NewConfig(sheet *xlsx.Sheet, exist map[string]bool) (*Config, error) {
|
|
config := &Config{
|
|
ignore: "#",
|
|
excludeFields: map[int]bool{0: true},
|
|
Exist: exist,
|
|
}
|
|
if strings.HasPrefix(sheet.Name, config.ignore) {
|
|
return nil, ErrReadConfigFailedIgnore
|
|
}
|
|
if err := config.initField(sheet); err != nil {
|
|
return nil, err
|
|
}
|
|
return config, nil
|
|
}
|
|
|
|
type Config struct {
|
|
Exist map[string]bool
|
|
Prefix string
|
|
DisplayName string
|
|
Name string
|
|
Describe string
|
|
ExportParam string
|
|
IndexCount int
|
|
Fields []*Field
|
|
|
|
matrix *matrix.Matrix[*xlsx.Cell]
|
|
excludeFields map[int]bool // 排除的字段
|
|
ignore string
|
|
horizontal bool
|
|
dataStart int
|
|
|
|
dataServer map[any]any
|
|
dataClient map[any]any
|
|
}
|
|
|
|
func (slf *Config) initField(sheet *xlsx.Sheet) error {
|
|
slf.matrix = xlsxtool.GetSheetMatrix(sheet)
|
|
var displayName *Position
|
|
name, indexCount := NewPosition(1, 0), NewPosition(1, 1)
|
|
if displayName == nil {
|
|
slf.DisplayName = sheet.Name
|
|
} else {
|
|
if value := slf.matrix.Get(displayName.X, displayName.Y); value == nil {
|
|
return ErrReadConfigFailedWithDisplayName
|
|
} else {
|
|
slf.DisplayName = strings.TrimSpace(value.String())
|
|
}
|
|
}
|
|
|
|
if name == nil {
|
|
slf.Name = sheet.Name
|
|
} else {
|
|
if value := slf.matrix.Get(name.X, name.Y); value == nil {
|
|
return ErrReadConfigFailedWithName
|
|
} else {
|
|
slf.Name = str.FirstUpper(strings.TrimSpace(value.String()))
|
|
}
|
|
}
|
|
if strings.HasPrefix(sheet.Name, slf.ignore) {
|
|
return ErrReadConfigFailedIgnore
|
|
}
|
|
if hash.Exist(slf.Exist, slf.Name) {
|
|
return ErrReadConfigFailedSame
|
|
}
|
|
|
|
if indexCount == nil {
|
|
slf.IndexCount, _ = strconv.Atoi(sheet.Name)
|
|
} else {
|
|
if value := slf.matrix.Get(indexCount.X, indexCount.Y); value == nil {
|
|
return ErrReadConfigFailedWithIndexCount
|
|
} else {
|
|
indexCount, err := value.Int()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if indexCount < 0 {
|
|
return ErrReadConfigFailedWithIndexCountLessThanZero
|
|
}
|
|
slf.IndexCount = indexCount
|
|
}
|
|
}
|
|
|
|
var (
|
|
describeStart int
|
|
horizontal bool
|
|
fields = make(map[string]bool)
|
|
dx, dy, nx, ny, tx, ty, ex, ey int
|
|
)
|
|
horizontal = slf.IndexCount > 0
|
|
slf.horizontal = horizontal
|
|
|
|
if horizontal {
|
|
describeStart = 3
|
|
dy = describeStart
|
|
ny = dy + 1
|
|
ty = ny + 1
|
|
ey = ty + 1
|
|
slf.dataStart = ey + 1
|
|
} else {
|
|
delete(slf.excludeFields, 0)
|
|
describeStart = 4
|
|
dy = describeStart
|
|
ny = dy
|
|
ty = dy
|
|
ey = dy
|
|
nx = dx + 1
|
|
tx = nx + 1
|
|
ex = tx + 1
|
|
slf.dataStart = ey + 1
|
|
}
|
|
var index = slf.IndexCount
|
|
for {
|
|
var (
|
|
describe, fieldName, fieldType, exportParam string
|
|
)
|
|
var skip bool
|
|
if value, exist := slf.matrix.GetExist(dx, dy); !exist {
|
|
skip = true
|
|
} else {
|
|
describe = value.String()
|
|
}
|
|
if value, exist := slf.matrix.GetExist(nx, ny); !exist {
|
|
skip = true
|
|
} else {
|
|
fieldName = str.FirstUpper(strings.TrimSpace(value.String()))
|
|
}
|
|
if value, exist := slf.matrix.GetExist(tx, ty); !exist {
|
|
skip = true
|
|
} else {
|
|
fieldType = strings.TrimSpace(value.String())
|
|
}
|
|
if value, exist := slf.matrix.GetExist(ex, ey); !exist {
|
|
skip = true
|
|
} else {
|
|
exportParam = strings.ToLower(strings.TrimSpace(value.String()))
|
|
}
|
|
if len(strings.TrimSpace(fieldName))+len(strings.TrimSpace(fieldType))+len(strings.TrimSpace(exportParam)) < 3 {
|
|
skip = true
|
|
}
|
|
|
|
var field = NewField(slf.Name, fieldName, fieldType)
|
|
field.Describe = strings.ReplaceAll(describe, "\n", ", ")
|
|
if strings.HasSuffix(field.Describe, ", ") {
|
|
field.Describe = field.Describe[:len(field.Describe)-2]
|
|
}
|
|
field.ExportParam = exportParam
|
|
switch field.ExportParam {
|
|
case "s", "sc", "cs":
|
|
field.Server = true
|
|
}
|
|
|
|
if horizontal {
|
|
dx++
|
|
nx++
|
|
tx++
|
|
ex++
|
|
} else {
|
|
dy++
|
|
ny++
|
|
ty++
|
|
ey++
|
|
}
|
|
|
|
if !skip {
|
|
|
|
field.Ignore = slf.excludeFields[len(slf.Fields)]
|
|
if !field.Ignore {
|
|
if strings.HasPrefix(field.Describe, slf.ignore) {
|
|
field.Ignore = true
|
|
} else if strings.HasPrefix(field.Name, slf.ignore) {
|
|
field.Ignore = true
|
|
} else if strings.HasPrefix(field.Type, slf.ignore) {
|
|
field.Ignore = true
|
|
} else if strings.HasPrefix(field.ExportParam, slf.ignore) {
|
|
field.Ignore = true
|
|
}
|
|
}
|
|
if !field.Ignore {
|
|
switch exportParam {
|
|
case "s", "c", "sc", "cs":
|
|
default:
|
|
continue
|
|
}
|
|
}
|
|
|
|
if fields[field.Name] && !field.Ignore {
|
|
return ErrReadConfigFailedWithNameDuplicate
|
|
}
|
|
if index > 0 && !field.Ignore {
|
|
if _, exist := basicTypeName[field.Type]; !exist {
|
|
return ErrReadConfigFailedWithIndexTypeException
|
|
}
|
|
index--
|
|
}
|
|
|
|
fields[field.Name] = true
|
|
slf.Fields = append(slf.Fields, field)
|
|
}
|
|
|
|
if horizontal {
|
|
if dx >= slf.matrix.GetWidth() {
|
|
break
|
|
}
|
|
} else {
|
|
if dy >= slf.matrix.GetHeight() {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
return slf.initData()
|
|
}
|
|
|
|
func (slf *Config) initData() error {
|
|
var x, y int
|
|
if slf.horizontal {
|
|
y = slf.dataStart
|
|
} else {
|
|
x = 4
|
|
y = 4
|
|
}
|
|
var dataSourceServer = make(map[any]any)
|
|
var dataSourceClient = make(map[any]any)
|
|
for {
|
|
var dataServer = dataSourceServer
|
|
var dataClient = dataSourceClient
|
|
var currentIndex = 0
|
|
|
|
var lineServer = map[any]any{}
|
|
var lineClient = map[any]any{}
|
|
var skip bool
|
|
var offset int
|
|
var stop bool
|
|
for i := 0; i < len(slf.Fields); i++ {
|
|
if slf.excludeFields[i] {
|
|
if c := slf.matrix.Get(x+i, y); c != nil && strings.HasPrefix(c.String(), "#") {
|
|
skip = true
|
|
break
|
|
}
|
|
continue
|
|
}
|
|
|
|
field := slf.Fields[i]
|
|
if field.Ignore {
|
|
continue
|
|
}
|
|
var value any
|
|
var zero bool
|
|
if slf.horizontal {
|
|
c := slf.matrix.Get(x+i, y)
|
|
if c == nil {
|
|
if currentIndex < slf.IndexCount {
|
|
stop = true
|
|
break
|
|
}
|
|
value = getValueZero(field.SourceType)
|
|
zero = true
|
|
} else if currentIndex < slf.IndexCount && len(strings.TrimSpace(c.String())) == 0 {
|
|
stop = true
|
|
break
|
|
}
|
|
if !zero {
|
|
value = getValueWithType(field.SourceType, c.String())
|
|
}
|
|
} else {
|
|
c := slf.matrix.Get(x, y+i+offset)
|
|
for c == nil {
|
|
offset++
|
|
c = slf.matrix.Get(x, y+i+offset)
|
|
if y+i+offset >= slf.matrix.GetHeight() {
|
|
break
|
|
}
|
|
}
|
|
value = getValueWithType(field.SourceType, c.String())
|
|
}
|
|
switch field.ExportParam {
|
|
case "s":
|
|
lineServer[field.Name] = value
|
|
case "c":
|
|
lineClient[field.Name] = value
|
|
case "sc", "cs":
|
|
lineServer[field.Name] = value
|
|
lineClient[field.Name] = value
|
|
default:
|
|
skip = true
|
|
break
|
|
}
|
|
|
|
if currentIndex < slf.IndexCount {
|
|
currentIndex++
|
|
m, exist := dataServer[value]
|
|
if !exist {
|
|
if currentIndex == slf.IndexCount {
|
|
dataServer[value] = lineServer
|
|
} else {
|
|
m = map[any]any{}
|
|
dataServer[value] = m
|
|
}
|
|
}
|
|
if currentIndex < slf.IndexCount {
|
|
dataServer = m.(map[any]any)
|
|
}
|
|
|
|
m, exist = dataClient[value]
|
|
if !exist {
|
|
if currentIndex == slf.IndexCount {
|
|
dataClient[value] = lineClient
|
|
} else {
|
|
m = map[any]any{}
|
|
dataClient[value] = m
|
|
}
|
|
}
|
|
if currentIndex < slf.IndexCount {
|
|
dataClient = m.(map[any]any)
|
|
}
|
|
}
|
|
}
|
|
if stop {
|
|
break
|
|
} else if slf.horizontal {
|
|
y++
|
|
if y >= slf.matrix.GetHeight() {
|
|
break
|
|
}
|
|
} else {
|
|
if !skip {
|
|
slf.dataServer = lineServer
|
|
slf.dataClient = lineClient
|
|
}
|
|
break
|
|
}
|
|
}
|
|
if slf.horizontal {
|
|
slf.dataServer = dataSourceServer
|
|
slf.dataClient = dataSourceClient
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (slf *Config) String() string {
|
|
tmpl, err := template.New("struct").Parse(generateConfigTemplate)
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
|
|
var buf bytes.Buffer
|
|
if err = tmpl.Execute(&buf, slf); err != nil {
|
|
return ""
|
|
}
|
|
var result string
|
|
_ = str.RangeLine(buf.String(), func(index int, line string) error {
|
|
if len(strings.TrimSpace(line)) == 0 {
|
|
return nil
|
|
}
|
|
result += fmt.Sprintf("%s\n", strings.ReplaceAll(line, "\t\t", "\t"))
|
|
if len(strings.TrimSpace(line)) == 1 {
|
|
result += "\n"
|
|
}
|
|
return nil
|
|
})
|
|
return result
|
|
}
|
|
|
|
func (slf *Config) JsonServer() []byte {
|
|
buffer := &bytes.Buffer{}
|
|
encoder := jsonIter.NewEncoder(buffer)
|
|
encoder.SetEscapeHTML(false)
|
|
encoder.SetIndent("", " ")
|
|
_ = encoder.Encode(slf.dataServer)
|
|
return buffer.Bytes()
|
|
}
|
|
|
|
func (slf *Config) JsonClient() []byte {
|
|
buffer := &bytes.Buffer{}
|
|
encoder := jsonIter.NewEncoder(buffer)
|
|
encoder.SetEscapeHTML(false)
|
|
encoder.SetIndent("", " ")
|
|
_ = encoder.Encode(slf.dataClient)
|
|
return buffer.Bytes()
|
|
}
|
|
|
|
func (slf *Config) GetVariable() string {
|
|
var result string
|
|
var count int
|
|
if slf.IndexCount > 0 {
|
|
for _, field := range slf.Fields {
|
|
if field.Ignore {
|
|
continue
|
|
}
|
|
result += fmt.Sprintf("map[%s]", field.Type)
|
|
count++
|
|
if count >= slf.IndexCount {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
return fmt.Sprintf("%s*%sDefine", result, slf.Name)
|
|
}
|
|
|
|
func (slf *Config) GetVariableGen() string {
|
|
if slf.IndexCount == 0 {
|
|
return fmt.Sprintf("new(%s)", strings.TrimPrefix(slf.GetVariable(), "*"))
|
|
}
|
|
return fmt.Sprintf("make(%s)", slf.GetVariable())
|
|
}
|