refactor: 导表工具重构,增加部分特性,修复部分问题
1、增加测试用例; 2、支持多文件合并导表; 3、支持 "#" 开头忽略; 4、修复越界问题; 5、优化模板样式,增加模板规则说明;
This commit is contained in:
parent
73cefc9b48
commit
afdda793bc
|
@ -36,9 +36,12 @@ func Init(loadDir string, loadHandle LoadHandle, refreshHandle RefreshHandle) {
|
|||
cLoadDir = loadDir
|
||||
cLoadHandle = loadHandle
|
||||
cRefreshHandle = refreshHandle
|
||||
Load()
|
||||
Refresh()
|
||||
}
|
||||
|
||||
// Load 加载配置
|
||||
// - 加载后并不会刷新线上配置,需要执行 Refresh 函数对线上配置进行刷新
|
||||
func Load() {
|
||||
mutex.Lock()
|
||||
if cTicker != nil {
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
// Code generated by minotaur-config-export. DO NOT EDIT.
|
||||
package configs
|
||||
// SystemConfig 系统
|
||||
type SystemConfig struct {
|
||||
Addr string // 监听地址
|
||||
Finish string // 启动完成
|
||||
}
|
||||
|
||||
// WelcomeConfig 欢迎词
|
||||
type WelcomeConfig struct {
|
||||
Id int // ID
|
||||
Text string // 内容
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
// Code generated by minotaur-config-export. DO NOT EDIT.
|
||||
package configs
|
||||
import (
|
||||
jsonIter "github.com/json-iterator/go"
|
||||
"github.com/kercylan98/minotaur/utils/log"
|
||||
"go.uber.org/zap"
|
||||
"os"
|
||||
)
|
||||
|
||||
var json = jsonIter.ConfigCompatibleWithStandardLibrary
|
||||
var (
|
||||
ISystemConfig *SystemConfig
|
||||
iSystemConfig *SystemConfig
|
||||
IWelcomeConfig map[int]*WelcomeConfig
|
||||
iWelcomeConfig map[int]*WelcomeConfig
|
||||
)
|
||||
|
||||
func LoadConfig(handle func(filename string, config any) error) {
|
||||
var err error
|
||||
iSystemConfig = new(SystemConfig)
|
||||
if err = handle("SystemConfig.json", iSystemConfig); err != nil {
|
||||
log.Error("Config", zap.String("Name", "SystemConfig"), zap.Bool("Invalid", true), zap.Error(err))
|
||||
}
|
||||
|
||||
iWelcomeConfig = make(map[int]*WelcomeConfig)
|
||||
if err = handle("WelcomeConfig.json", &iWelcomeConfig); err != nil {
|
||||
log.Error("Config", zap.String("Name", "WelcomeConfig"), zap.Bool("Invalid", true), zap.Error(err))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func Refresh() {
|
||||
ISystemConfig = iSystemConfig
|
||||
IWelcomeConfig = iWelcomeConfig
|
||||
}
|
||||
|
||||
func DefaultLoad(filepath string) {
|
||||
LoadConfig(func(filename string, config any) error {
|
||||
bytes, err := os.ReadFile(filepath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return json.Unmarshal(bytes, &config)
|
||||
})
|
||||
}
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"Finish": "StartFinish",
|
||||
"Addr": ":9999"
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"1": {
|
||||
"Id": 1,
|
||||
"Text": "Hello"
|
||||
},
|
||||
"2": {
|
||||
"Id": 2,
|
||||
"Text": "World"
|
||||
}
|
||||
}
|
Binary file not shown.
|
@ -1,30 +0,0 @@
|
|||
// 该案例演示了配置导表工具的使用,其中包括了作为模板的配置文件及导出的配置文件
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/kercylan98/minotaur/config"
|
||||
"github.com/kercylan98/minotaur/examples/simple-server-config/config/configs"
|
||||
"github.com/kercylan98/minotaur/planner/configexport"
|
||||
"github.com/kercylan98/minotaur/utils/log"
|
||||
"go.uber.org/zap"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
const (
|
||||
workdir = "./examples/simple-server-config"
|
||||
)
|
||||
|
||||
func main() {
|
||||
export()
|
||||
config.Init(filepath.Join(workdir, "config", "json"), configs.LoadConfig, configs.Refresh)
|
||||
config.Load()
|
||||
config.Refresh()
|
||||
log.Info("Config", zap.Any("SystemConfig", configs.ISystemConfig))
|
||||
log.Info("Config", zap.Any("WelcomeConfig", configs.IWelcomeConfig))
|
||||
}
|
||||
|
||||
func export() {
|
||||
c := configexport.New(filepath.Join(workdir, "config", "系统配置.xlsx"))
|
||||
c.ExportGo("", filepath.Join(workdir, "config", "configs"))
|
||||
c.ExportServer("", filepath.Join(workdir, "config", "json"))
|
||||
}
|
|
@ -5,24 +5,52 @@ import (
|
|||
"fmt"
|
||||
"github.com/kercylan98/minotaur/planner/configexport/internal"
|
||||
"github.com/kercylan98/minotaur/utils/file"
|
||||
"github.com/kercylan98/minotaur/utils/log"
|
||||
"github.com/kercylan98/minotaur/utils/str"
|
||||
"github.com/tealeg/xlsx"
|
||||
"go.uber.org/zap"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
// New 创建一个导表配置
|
||||
func New(xlsxPath string) *ConfigExport {
|
||||
ce := &ConfigExport{xlsxPath: xlsxPath}
|
||||
ce := &ConfigExport{xlsxPath: xlsxPath, exist: make(map[string]bool)}
|
||||
xlsxFile, err := xlsx.OpenFile(xlsxPath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for i := 0; i < len(xlsxFile.Sheets); i++ {
|
||||
if config, err := internal.NewConfig(xlsxFile.Sheets[i]); err != nil {
|
||||
panic(err)
|
||||
sheet := xlsxFile.Sheets[i]
|
||||
if config, err := internal.NewConfig(sheet, ce.exist); err != nil {
|
||||
switch err {
|
||||
case internal.ErrReadConfigFailedSame:
|
||||
log.Warn("ConfigExport",
|
||||
zap.String("File", xlsxPath),
|
||||
zap.String("Sheet", sheet.Name),
|
||||
zap.String("Info", "A configuration with the same name exists, skipped"),
|
||||
)
|
||||
case internal.ErrReadConfigFailedIgnore:
|
||||
log.Info("ConfigExport",
|
||||
zap.String("File", xlsxPath),
|
||||
zap.String("Sheet", sheet.Name),
|
||||
zap.String("Info", "Excluded non-configuration table files"),
|
||||
)
|
||||
default:
|
||||
log.ErrorHideStack("ConfigExport",
|
||||
zap.String("File", xlsxPath),
|
||||
zap.String("Sheet", sheet.Name),
|
||||
zap.String("Info", "Excluded non-configuration table files"),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
if config == nil {
|
||||
continue
|
||||
}
|
||||
ce.configs = append(ce.configs, config)
|
||||
ce.exist[config.Name] = true
|
||||
}
|
||||
}
|
||||
return ce
|
||||
|
@ -31,6 +59,34 @@ func New(xlsxPath string) *ConfigExport {
|
|||
type ConfigExport struct {
|
||||
xlsxPath string
|
||||
configs []*internal.Config
|
||||
exist map[string]bool
|
||||
}
|
||||
|
||||
// Merge 合并多个导表配置
|
||||
func Merge(exports ...*ConfigExport) *ConfigExport {
|
||||
if len(exports) == 0 {
|
||||
return nil
|
||||
}
|
||||
if len(exports) == 1 {
|
||||
return exports[0]
|
||||
}
|
||||
var export = exports[0]
|
||||
for i := 1; i < len(exports); i++ {
|
||||
ce := exports[i]
|
||||
for _, config := range ce.configs {
|
||||
if _, ok := export.exist[config.Name]; ok {
|
||||
log.Warn("ConfigExport",
|
||||
zap.String("File", ce.xlsxPath),
|
||||
zap.String("Sheet", config.Name),
|
||||
zap.String("Info", "A configuration with the same name exists, skipped"),
|
||||
)
|
||||
continue
|
||||
}
|
||||
export.configs = append(export.configs, config)
|
||||
export.exist[config.Name] = true
|
||||
}
|
||||
}
|
||||
return export
|
||||
}
|
||||
|
||||
func (slf *ConfigExport) ExportClient(prefix, outputDir string) {
|
||||
|
@ -99,9 +155,13 @@ func (slf *ConfigExport) exportGoConfig(outputDir string) {
|
|||
return nil
|
||||
})
|
||||
|
||||
if err := file.WriterFile(filepath.Join(outputDir, "config.go"), []byte(result)); err != nil {
|
||||
filePath := filepath.Join(outputDir, "config.go")
|
||||
if err := file.WriterFile(filePath, []byte(result)); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
cmd := exec.Command("gofmt", "-w", filePath)
|
||||
_ = cmd.Run()
|
||||
}
|
||||
|
||||
func (slf *ConfigExport) exportGoDefine(outputDir string) {
|
||||
|
@ -136,7 +196,11 @@ func (slf *ConfigExport) exportGoDefine(outputDir string) {
|
|||
return nil
|
||||
})
|
||||
|
||||
if err := file.WriterFile(filepath.Join(outputDir, "config.define.go"), []byte(result)); err != nil {
|
||||
filePath := filepath.Join(outputDir, "config.define.go")
|
||||
if err := file.WriterFile(filePath, []byte(result)); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
cmd := exec.Command("gofmt", "-w", filePath)
|
||||
_ = cmd.Run()
|
||||
}
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
package configexport_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/kercylan98/minotaur/config"
|
||||
"github.com/kercylan98/minotaur/planner/configexport"
|
||||
"github.com/kercylan98/minotaur/planner/configexport/example"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func ExampleNew() {
|
||||
var workdir = "./"
|
||||
files, err := os.ReadDir(workdir)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
var ces []*configexport.ConfigExport
|
||||
for _, file := range files {
|
||||
if file.IsDir() || !strings.HasSuffix(file.Name(), ".xlsx") || strings.HasPrefix(file.Name(), "~") {
|
||||
continue
|
||||
}
|
||||
|
||||
ces = append(ces, configexport.New(filepath.Join(workdir, file.Name())))
|
||||
}
|
||||
|
||||
c := configexport.Merge(ces...)
|
||||
outDir := filepath.Join(workdir, "example")
|
||||
c.ExportGo("", outDir)
|
||||
c.ExportServer("", outDir)
|
||||
c.ExportClient("", outDir)
|
||||
|
||||
// 下方为配置加载代码
|
||||
// 使用生成的 LoadConfig 函数加载配置
|
||||
config.Init(outDir, example.LoadConfig, example.Refresh)
|
||||
|
||||
fmt.Println("success")
|
||||
|
||||
// Output:
|
||||
// success
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
package configexport
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestNew(t *testing.T) {
|
||||
c := New(`./template.xlsx`)
|
||||
|
||||
c.ExportGo("server", "./example")
|
||||
c.ExportClient("client", "./example")
|
||||
c.ExportServer("server", "./example")
|
||||
}
|
|
@ -1,18 +1,17 @@
|
|||
{
|
||||
"Other": {
|
||||
"1": {
|
||||
"id": 2,
|
||||
"name": "刘备"
|
||||
},
|
||||
"0": {
|
||||
"id": 1,
|
||||
"name": "张飞"
|
||||
}
|
||||
},
|
||||
"Id": 1,
|
||||
"Count": "a",
|
||||
"Award": {
|
||||
"0": "asd",
|
||||
"1": "12"
|
||||
},
|
||||
"Other": {
|
||||
"0": {
|
||||
"id": 1,
|
||||
"name": "张飞"
|
||||
},
|
||||
"1": {
|
||||
"id": 2,
|
||||
"name": "刘备"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,22 +1,22 @@
|
|||
{
|
||||
"1": {
|
||||
"b": {
|
||||
"Id": 1,
|
||||
"Count": "b",
|
||||
"Award": {
|
||||
"0": "asd",
|
||||
"1": "12"
|
||||
},
|
||||
"Other": {
|
||||
"0": {
|
||||
"id": 1,
|
||||
"name": "张飞"
|
||||
"name": "张飞",
|
||||
"id": 1
|
||||
},
|
||||
"1": {
|
||||
"id": 2,
|
||||
"name": "刘备"
|
||||
"name": "刘备",
|
||||
"id": 2
|
||||
}
|
||||
}
|
||||
},
|
||||
"Id": 1,
|
||||
"Count": "b"
|
||||
}
|
||||
},
|
||||
"2": {
|
||||
|
@ -27,12 +27,12 @@
|
|||
},
|
||||
"Other": {
|
||||
"0": {
|
||||
"id": 1,
|
||||
"name": "张飞"
|
||||
"name": "张飞",
|
||||
"id": 1
|
||||
},
|
||||
"1": {
|
||||
"name": "刘备",
|
||||
"id": 2
|
||||
"id": 2,
|
||||
"name": "刘备"
|
||||
}
|
||||
},
|
||||
"Id": 2,
|
||||
|
@ -42,8 +42,8 @@
|
|||
"Id": 2,
|
||||
"Count": "d",
|
||||
"Award": {
|
||||
"0": "asd",
|
||||
"1": "12"
|
||||
"1": "12",
|
||||
"0": "asd"
|
||||
},
|
||||
"Other": {
|
||||
"0": {
|
|
@ -1,60 +1,75 @@
|
|||
// Code generated by minotaur-config-export. DO NOT EDIT.
|
||||
package example
|
||||
// IndexConfig 有索引
|
||||
type IndexConfig struct {
|
||||
Id int // 任务ID
|
||||
Count string // 次数
|
||||
Info *IndexConfigInfo // 信息
|
||||
|
||||
// IndexConfigDefine 有索引
|
||||
type IndexConfigDefine struct {
|
||||
Id int // 任务ID
|
||||
Count string // 次数
|
||||
Info *IndexConfigInfo // 信息
|
||||
Other map[int]*IndexConfigOther // 信息2
|
||||
}
|
||||
}
|
||||
|
||||
func (slf *IndexConfigDefine) String() string {
|
||||
if data, err := json.Marshal(slf); err == nil {
|
||||
return string(data)
|
||||
}
|
||||
|
||||
return "{}"
|
||||
}
|
||||
|
||||
type IndexConfigInfo struct {
|
||||
Id int
|
||||
Id int
|
||||
Name string
|
||||
Info *IndexConfigInfoInfo
|
||||
}
|
||||
}
|
||||
|
||||
type IndexConfigInfoInfo struct {
|
||||
Lv int
|
||||
Lv int
|
||||
Exp *IndexConfigInfoInfoExp
|
||||
}
|
||||
}
|
||||
|
||||
type IndexConfigInfoInfoExp struct {
|
||||
Mux int
|
||||
Mux int
|
||||
Count int
|
||||
}
|
||||
}
|
||||
|
||||
type IndexConfigOther struct {
|
||||
Id int
|
||||
Id int
|
||||
Name string
|
||||
}
|
||||
}
|
||||
|
||||
// EasyConfig 无索引
|
||||
type EasyConfig struct {
|
||||
Id int // 任务ID
|
||||
Count string // 次数
|
||||
Info *EasyConfigInfo // 信息
|
||||
// EasyConfigDefine 无索引
|
||||
type EasyConfigDefine struct {
|
||||
Id int // 任务ID
|
||||
Info *EasyConfigInfo // 信息
|
||||
Other map[int]*EasyConfigOther // 信息2
|
||||
}
|
||||
}
|
||||
|
||||
func (slf *EasyConfigDefine) String() string {
|
||||
if data, err := json.Marshal(slf); err == nil {
|
||||
return string(data)
|
||||
}
|
||||
|
||||
return "{}"
|
||||
}
|
||||
|
||||
type EasyConfigInfo struct {
|
||||
Id int
|
||||
Id int
|
||||
Name string
|
||||
Info *EasyConfigInfoInfo
|
||||
}
|
||||
}
|
||||
|
||||
type EasyConfigInfoInfo struct {
|
||||
Lv int
|
||||
Lv int
|
||||
Exp *EasyConfigInfoInfoExp
|
||||
}
|
||||
}
|
||||
|
||||
type EasyConfigInfoInfoExp struct {
|
||||
Mux int
|
||||
Mux int
|
||||
Count int
|
||||
}
|
||||
}
|
||||
|
||||
type EasyConfigOther struct {
|
||||
Id int
|
||||
Id int
|
||||
Name string
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// Code generated by minotaur-config-export. DO NOT EDIT.
|
||||
package example
|
||||
|
||||
import (
|
||||
jsonIter "github.com/json-iterator/go"
|
||||
"github.com/kercylan98/minotaur/utils/log"
|
||||
|
@ -9,39 +10,40 @@ import (
|
|||
|
||||
var json = jsonIter.ConfigCompatibleWithStandardLibrary
|
||||
var (
|
||||
IIndexConfig map[int]map[string]*IndexConfig
|
||||
iIndexConfig map[int]map[string]*IndexConfig
|
||||
IEasyConfig *EasyConfig
|
||||
iEasyConfig *EasyConfig
|
||||
// IndexConfig 有索引
|
||||
IndexConfig map[int]map[string]*IndexConfigDefine
|
||||
_IndexConfig map[int]map[string]*IndexConfigDefine
|
||||
// EasyConfig 无索引
|
||||
EasyConfig *EasyConfigDefine
|
||||
_EasyConfig *EasyConfigDefine
|
||||
)
|
||||
|
||||
func LoadConfig(handle func(filename string, config any) error) {
|
||||
var err error
|
||||
iIndexConfig = make(map[int]map[string]*IndexConfig)
|
||||
if err = handle("server.IndexConfig.json", &iIndexConfig); err != nil {
|
||||
_IndexConfig = make(map[int]map[string]*IndexConfigDefine)
|
||||
if err = handle("IndexConfig.json", &_IndexConfig); err != nil {
|
||||
log.Error("Config", zap.String("Name", "IndexConfig"), zap.Bool("Invalid", true), zap.Error(err))
|
||||
}
|
||||
|
||||
iEasyConfig = new(EasyConfig)
|
||||
if err = handle("server.EasyConfig.json", iEasyConfig); err != nil {
|
||||
_EasyConfig = new(EasyConfigDefine)
|
||||
if err = handle("EasyConfig.json", _EasyConfig); err != nil {
|
||||
log.Error("Config", zap.String("Name", "EasyConfig"), zap.Bool("Invalid", true), zap.Error(err))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func Refresh() {
|
||||
IIndexConfig = iIndexConfig
|
||||
IEasyConfig = iEasyConfig
|
||||
IndexConfig = _IndexConfig
|
||||
EasyConfig = _EasyConfig
|
||||
}
|
||||
|
||||
func DefaultLoad(filepath string) {
|
||||
LoadConfig(func(filename string, config any) error {
|
||||
bytes, err := os.ReadFile(filepath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
bytes, err := os.ReadFile(filepath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return json.Unmarshal(bytes, &config)
|
||||
return json.Unmarshal(bytes, &config)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
{
|
||||
"Other": {
|
||||
"0": {
|
||||
"id": 1,
|
||||
"name": "张飞"
|
||||
},
|
||||
"1": {
|
||||
"id": 2,
|
||||
"name": "刘备"
|
||||
}
|
||||
},
|
||||
"Id": 1,
|
||||
"Count": "a",
|
||||
"Info": {
|
||||
"id": 1,
|
||||
"name": "小明",
|
||||
"info": {
|
||||
"lv": 1,
|
||||
"exp": {
|
||||
"mux": 10,
|
||||
"count": 100
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
{
|
||||
"2": {
|
||||
"c": {
|
||||
"Info": {
|
||||
"id": 1,
|
||||
"name": "小明",
|
||||
"info": {
|
||||
"lv": 1,
|
||||
"exp": {
|
||||
"mux": 10,
|
||||
"count": 100
|
||||
}
|
||||
}
|
||||
},
|
||||
"Other": {
|
||||
"0": {
|
||||
"id": 1,
|
||||
"name": "张飞"
|
||||
},
|
||||
"1": {
|
||||
"id": 2,
|
||||
"name": "刘备"
|
||||
}
|
||||
},
|
||||
"Id": 2,
|
||||
"Count": "c"
|
||||
},
|
||||
"d": {
|
||||
"Id": 2,
|
||||
"Count": "d",
|
||||
"Info": {
|
||||
"id": 1,
|
||||
"name": "小明",
|
||||
"info": {
|
||||
"lv": 1,
|
||||
"exp": {
|
||||
"mux": 10,
|
||||
"count": 100
|
||||
}
|
||||
}
|
||||
},
|
||||
"Other": {
|
||||
"0": {
|
||||
"id": 1,
|
||||
"name": "张飞"
|
||||
},
|
||||
"1": {
|
||||
"id": 2,
|
||||
"name": "刘备"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"1": {
|
||||
"b": {
|
||||
"Id": 1,
|
||||
"Count": "b",
|
||||
"Info": {
|
||||
"id": 1,
|
||||
"name": "小明",
|
||||
"info": {
|
||||
"lv": 1,
|
||||
"exp": {
|
||||
"mux": 10,
|
||||
"count": 100
|
||||
}
|
||||
}
|
||||
},
|
||||
"Other": {
|
||||
"0": {
|
||||
"id": 1,
|
||||
"name": "张飞"
|
||||
},
|
||||
"1": {
|
||||
"id": 2,
|
||||
"name": "刘备"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@ import (
|
|||
"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"
|
||||
|
@ -15,10 +16,14 @@ import (
|
|||
|
||||
// NewConfig 定位为空将读取Sheet名称
|
||||
// - 表格中需要严格遵守 描述、名称、类型、导出参数、数据列的顺序
|
||||
func NewConfig(sheet *xlsx.Sheet) (*Config, error) {
|
||||
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
|
||||
|
@ -27,6 +32,7 @@ func NewConfig(sheet *xlsx.Sheet) (*Config, error) {
|
|||
}
|
||||
|
||||
type Config struct {
|
||||
Exist map[string]bool
|
||||
Prefix string
|
||||
DisplayName string
|
||||
Name string
|
||||
|
@ -68,6 +74,12 @@ func (slf *Config) initField(sheet *xlsx.Sheet) error {
|
|||
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)
|
||||
|
@ -120,22 +132,22 @@ func (slf *Config) initField(sheet *xlsx.Sheet) error {
|
|||
describe, fieldName, fieldType, exportParam string
|
||||
)
|
||||
var skip bool
|
||||
if value := slf.matrix.Get(dx, dy); value == nil {
|
||||
if value, exist := slf.matrix.GetExist(dx, dy); !exist {
|
||||
skip = true
|
||||
} else {
|
||||
describe = value.String()
|
||||
}
|
||||
if value := slf.matrix.Get(nx, ny); value == nil {
|
||||
if value, exist := slf.matrix.GetExist(nx, ny); !exist {
|
||||
skip = true
|
||||
} else {
|
||||
fieldName = str.FirstUpper(strings.TrimSpace(value.String()))
|
||||
}
|
||||
if value := slf.matrix.Get(tx, ty); value == nil {
|
||||
if value, exist := slf.matrix.GetExist(tx, ty); !exist {
|
||||
skip = true
|
||||
} else {
|
||||
fieldType = strings.TrimSpace(value.String())
|
||||
}
|
||||
if value := slf.matrix.Get(ex, ey); value == nil {
|
||||
if value, exist := slf.matrix.GetExist(ex, ey); !exist {
|
||||
skip = true
|
||||
} else {
|
||||
exportParam = strings.ToLower(strings.TrimSpace(value.String()))
|
||||
|
@ -233,6 +245,7 @@ func (slf *Config) initData() error {
|
|||
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(), "#") {
|
||||
|
@ -249,8 +262,8 @@ func (slf *Config) initData() error {
|
|||
var value any
|
||||
if slf.horizontal {
|
||||
c := slf.matrix.Get(x+i, y)
|
||||
if c == nil || (currentIndex < slf.IndexCount && len(c.String()) == 0) {
|
||||
skip = true
|
||||
if c == nil || (currentIndex < slf.IndexCount && len(strings.TrimSpace(c.String())) == 0) {
|
||||
stop = true
|
||||
break
|
||||
}
|
||||
value = getValueWithType(field.SourceType, c.String())
|
||||
|
@ -273,6 +286,9 @@ func (slf *Config) initData() error {
|
|||
case "sc", "cs":
|
||||
lineServer[field.Name] = value
|
||||
lineClient[field.Name] = value
|
||||
default:
|
||||
skip = true
|
||||
break
|
||||
}
|
||||
|
||||
if currentIndex < slf.IndexCount {
|
||||
|
@ -304,7 +320,9 @@ func (slf *Config) initData() error {
|
|||
}
|
||||
}
|
||||
}
|
||||
if slf.horizontal {
|
||||
if stop {
|
||||
break
|
||||
} else if slf.horizontal {
|
||||
y++
|
||||
if y >= slf.matrix.GetHeight() {
|
||||
break
|
||||
|
@ -373,7 +391,7 @@ func (slf *Config) GetVariable() string {
|
|||
}
|
||||
}
|
||||
}
|
||||
return fmt.Sprintf("%s*%s", result, slf.Name)
|
||||
return fmt.Sprintf("%s*%sDefine", result, slf.Name)
|
||||
}
|
||||
|
||||
func (slf *Config) GetVariableGen() string {
|
||||
|
|
|
@ -3,6 +3,8 @@ package internal
|
|||
import "errors"
|
||||
|
||||
var (
|
||||
ErrReadConfigFailedIgnore = errors.New("read config skip ignore")
|
||||
ErrReadConfigFailedSame = errors.New("read config skip, same name")
|
||||
ErrReadConfigFailedWithDisplayName = errors.New("read config display name failed, can not found position")
|
||||
ErrReadConfigFailedWithName = errors.New("read config name failed, can not found position")
|
||||
ErrReadConfigFailedWithIndexCount = errors.New("read config index count failed, can not found position")
|
||||
|
|
|
@ -3,12 +3,19 @@ package internal
|
|||
const (
|
||||
generateConfigTemplate = `
|
||||
|
||||
// {{.Name}} {{.DisplayName}}
|
||||
type {{.Name}} struct {
|
||||
// {{.Name}}Define {{.DisplayName}}
|
||||
type {{.Name}}Define struct {
|
||||
{{range $index, $value := .Fields}}{{if eq $value.Server true}}{{if eq $value.Ignore false}}{{$value.Name}} {{$value.Type}} // {{$value.Describe}}{{end}}{{end}}
|
||||
{{end}}
|
||||
}
|
||||
|
||||
func (slf *{{.Name}}Define) String() string {
|
||||
if data, err := json.Marshal(slf); err == nil {
|
||||
return string(data)
|
||||
}
|
||||
return "{}"
|
||||
}
|
||||
|
||||
{{range $index, $value := .Fields}}{{$value}}{{end}}
|
||||
`
|
||||
|
||||
|
@ -37,21 +44,22 @@ var json = jsonIter.ConfigCompatibleWithStandardLibrary
|
|||
|
||||
var (
|
||||
{{range $index, $config := .Configs}}
|
||||
I{{$config.Name}} {{$config.GetVariable}}
|
||||
i{{$config.Name}} {{$config.GetVariable}}
|
||||
// {{$config.Name}} {{$config.DisplayName}}
|
||||
{{$config.Name}} {{$config.GetVariable}}
|
||||
_{{$config.Name}} {{$config.GetVariable}}
|
||||
{{end}}
|
||||
)
|
||||
|
||||
func LoadConfig(handle func(filename string, config any) error) {
|
||||
var err error
|
||||
{{range $index, $config := .Configs}}
|
||||
i{{$config.Name}} = {{$config.GetVariableGen}}
|
||||
_{{$config.Name}} = {{$config.GetVariableGen}}
|
||||
{{if eq $config.IndexCount 0}}
|
||||
if err = handle("{{$config.Prefix}}{{$config.Name}}.json", i{{$config.Name}}); err != nil {
|
||||
if err = handle("{{$config.Prefix}}{{$config.Name}}.json", _{{$config.Name}}); err != nil {
|
||||
log.Error("Config", zap.String("Name", "{{$config.Name}}"), zap.Bool("Invalid", true), zap.Error(err))
|
||||
}
|
||||
{{else}}
|
||||
if err = handle("{{$config.Prefix}}{{$config.Name}}.json", &i{{$config.Name}}); err != nil {
|
||||
if err = handle("{{$config.Prefix}}{{$config.Name}}.json", &_{{$config.Name}}); err != nil {
|
||||
log.Error("Config", zap.String("Name", "{{$config.Name}}"), zap.Bool("Invalid", true), zap.Error(err))
|
||||
}
|
||||
{{end}}
|
||||
|
@ -60,7 +68,7 @@ func LoadConfig(handle func(filename string, config any) error) {
|
|||
|
||||
func Refresh() {
|
||||
{{range $index, $config := .Configs}}
|
||||
I{{$config.Name}} = i{{$config.Name}}
|
||||
{{$config.Name}} = _{{$config.Name}}
|
||||
{{end}}
|
||||
}
|
||||
|
||||
|
|
Binary file not shown.
|
@ -1,6 +1,7 @@
|
|||
package matrix
|
||||
|
||||
import (
|
||||
"github.com/kercylan98/minotaur/utils/generic"
|
||||
"github.com/kercylan98/minotaur/utils/geometry"
|
||||
)
|
||||
|
||||
|
@ -60,6 +61,19 @@ func (slf *Matrix[T]) Get(x, y int) (value T) {
|
|||
return slf.m[geometry.CoordinateToPos(slf.w, x, y)]
|
||||
}
|
||||
|
||||
// GetExist 获取特定坐标的内容,如果不存在则返回 false
|
||||
func (slf *Matrix[T]) GetExist(x, y int) (value T, exist bool) {
|
||||
pos := geometry.CoordinateToPos(slf.w, x, y)
|
||||
if pos >= len(slf.m) {
|
||||
return
|
||||
}
|
||||
t := slf.m[pos]
|
||||
if generic.IsNil(t) {
|
||||
return
|
||||
}
|
||||
return slf.m[pos], true
|
||||
}
|
||||
|
||||
// GetWithPos 获取特定坐标的内容
|
||||
func (slf *Matrix[T]) GetWithPos(pos int) (value T) {
|
||||
return slf.m[pos]
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package hash
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
// Exist 检查特定 key 是否存在
|
||||
func Exist[K comparable, V any](m map[K]V, key K) bool {
|
||||
_, exist := m[key]
|
||||
|
@ -15,3 +17,11 @@ func AllExist[K comparable, V any](m map[K]V, keys ...K) bool {
|
|||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// ToJson 将 map 转换为 json 字符串
|
||||
func ToJson[K comparable, V any](m map[K]V) string {
|
||||
if data, err := json.Marshal(m); err == nil {
|
||||
return string(data)
|
||||
}
|
||||
return "{}"
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue