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
|
cLoadDir = loadDir
|
||||||
cLoadHandle = loadHandle
|
cLoadHandle = loadHandle
|
||||||
cRefreshHandle = refreshHandle
|
cRefreshHandle = refreshHandle
|
||||||
|
Load()
|
||||||
|
Refresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load 加载配置
|
// Load 加载配置
|
||||||
|
// - 加载后并不会刷新线上配置,需要执行 Refresh 函数对线上配置进行刷新
|
||||||
func Load() {
|
func Load() {
|
||||||
mutex.Lock()
|
mutex.Lock()
|
||||||
if cTicker != nil {
|
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"
|
"fmt"
|
||||||
"github.com/kercylan98/minotaur/planner/configexport/internal"
|
"github.com/kercylan98/minotaur/planner/configexport/internal"
|
||||||
"github.com/kercylan98/minotaur/utils/file"
|
"github.com/kercylan98/minotaur/utils/file"
|
||||||
|
"github.com/kercylan98/minotaur/utils/log"
|
||||||
"github.com/kercylan98/minotaur/utils/str"
|
"github.com/kercylan98/minotaur/utils/str"
|
||||||
"github.com/tealeg/xlsx"
|
"github.com/tealeg/xlsx"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// New 创建一个导表配置
|
||||||
func New(xlsxPath string) *ConfigExport {
|
func New(xlsxPath string) *ConfigExport {
|
||||||
ce := &ConfigExport{xlsxPath: xlsxPath}
|
ce := &ConfigExport{xlsxPath: xlsxPath, exist: make(map[string]bool)}
|
||||||
xlsxFile, err := xlsx.OpenFile(xlsxPath)
|
xlsxFile, err := xlsx.OpenFile(xlsxPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
for i := 0; i < len(xlsxFile.Sheets); i++ {
|
for i := 0; i < len(xlsxFile.Sheets); i++ {
|
||||||
if config, err := internal.NewConfig(xlsxFile.Sheets[i]); err != nil {
|
sheet := xlsxFile.Sheets[i]
|
||||||
panic(err)
|
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 {
|
} else {
|
||||||
|
if config == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
ce.configs = append(ce.configs, config)
|
ce.configs = append(ce.configs, config)
|
||||||
|
ce.exist[config.Name] = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ce
|
return ce
|
||||||
|
@ -31,6 +59,34 @@ func New(xlsxPath string) *ConfigExport {
|
||||||
type ConfigExport struct {
|
type ConfigExport struct {
|
||||||
xlsxPath string
|
xlsxPath string
|
||||||
configs []*internal.Config
|
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) {
|
func (slf *ConfigExport) ExportClient(prefix, outputDir string) {
|
||||||
|
@ -99,9 +155,13 @@ func (slf *ConfigExport) exportGoConfig(outputDir string) {
|
||||||
return nil
|
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)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cmd := exec.Command("gofmt", "-w", filePath)
|
||||||
|
_ = cmd.Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (slf *ConfigExport) exportGoDefine(outputDir string) {
|
func (slf *ConfigExport) exportGoDefine(outputDir string) {
|
||||||
|
@ -136,7 +196,11 @@ func (slf *ConfigExport) exportGoDefine(outputDir string) {
|
||||||
return nil
|
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)
|
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,
|
"Id": 1,
|
||||||
"Count": "a",
|
|
||||||
"Award": {
|
"Award": {
|
||||||
"0": "asd",
|
"0": "asd",
|
||||||
"1": "12"
|
"1": "12"
|
||||||
|
},
|
||||||
|
"Other": {
|
||||||
|
"0": {
|
||||||
|
"id": 1,
|
||||||
|
"name": "张飞"
|
||||||
|
},
|
||||||
|
"1": {
|
||||||
|
"id": 2,
|
||||||
|
"name": "刘备"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,22 +1,22 @@
|
||||||
{
|
{
|
||||||
"1": {
|
"1": {
|
||||||
"b": {
|
"b": {
|
||||||
"Id": 1,
|
|
||||||
"Count": "b",
|
|
||||||
"Award": {
|
"Award": {
|
||||||
"0": "asd",
|
"0": "asd",
|
||||||
"1": "12"
|
"1": "12"
|
||||||
},
|
},
|
||||||
"Other": {
|
"Other": {
|
||||||
"0": {
|
"0": {
|
||||||
"id": 1,
|
"name": "张飞",
|
||||||
"name": "张飞"
|
"id": 1
|
||||||
},
|
},
|
||||||
"1": {
|
"1": {
|
||||||
"id": 2,
|
"name": "刘备",
|
||||||
"name": "刘备"
|
"id": 2
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Id": 1,
|
||||||
|
"Count": "b"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"2": {
|
"2": {
|
||||||
|
@ -27,12 +27,12 @@
|
||||||
},
|
},
|
||||||
"Other": {
|
"Other": {
|
||||||
"0": {
|
"0": {
|
||||||
"id": 1,
|
"name": "张飞",
|
||||||
"name": "张飞"
|
"id": 1
|
||||||
},
|
},
|
||||||
"1": {
|
"1": {
|
||||||
"name": "刘备",
|
"id": 2,
|
||||||
"id": 2
|
"name": "刘备"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Id": 2,
|
"Id": 2,
|
||||||
|
@ -42,8 +42,8 @@
|
||||||
"Id": 2,
|
"Id": 2,
|
||||||
"Count": "d",
|
"Count": "d",
|
||||||
"Award": {
|
"Award": {
|
||||||
"0": "asd",
|
"1": "12",
|
||||||
"1": "12"
|
"0": "asd"
|
||||||
},
|
},
|
||||||
"Other": {
|
"Other": {
|
||||||
"0": {
|
"0": {
|
|
@ -1,13 +1,22 @@
|
||||||
// Code generated by minotaur-config-export. DO NOT EDIT.
|
// Code generated by minotaur-config-export. DO NOT EDIT.
|
||||||
package example
|
package example
|
||||||
// IndexConfig 有索引
|
|
||||||
type IndexConfig struct {
|
// IndexConfigDefine 有索引
|
||||||
|
type IndexConfigDefine struct {
|
||||||
Id int // 任务ID
|
Id int // 任务ID
|
||||||
Count string // 次数
|
Count string // 次数
|
||||||
Info *IndexConfigInfo // 信息
|
Info *IndexConfigInfo // 信息
|
||||||
Other map[int]*IndexConfigOther // 信息2
|
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 {
|
type IndexConfigInfo struct {
|
||||||
Id int
|
Id int
|
||||||
Name string
|
Name string
|
||||||
|
@ -29,14 +38,21 @@ type IndexConfigOther struct {
|
||||||
Name string
|
Name string
|
||||||
}
|
}
|
||||||
|
|
||||||
// EasyConfig 无索引
|
// EasyConfigDefine 无索引
|
||||||
type EasyConfig struct {
|
type EasyConfigDefine struct {
|
||||||
Id int // 任务ID
|
Id int // 任务ID
|
||||||
Count string // 次数
|
|
||||||
Info *EasyConfigInfo // 信息
|
Info *EasyConfigInfo // 信息
|
||||||
Other map[int]*EasyConfigOther // 信息2
|
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 {
|
type EasyConfigInfo struct {
|
||||||
Id int
|
Id int
|
||||||
Name string
|
Name string
|
||||||
|
@ -57,4 +73,3 @@ type EasyConfigOther struct {
|
||||||
Id int
|
Id int
|
||||||
Name string
|
Name string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
// Code generated by minotaur-config-export. DO NOT EDIT.
|
// Code generated by minotaur-config-export. DO NOT EDIT.
|
||||||
package example
|
package example
|
||||||
|
|
||||||
import (
|
import (
|
||||||
jsonIter "github.com/json-iterator/go"
|
jsonIter "github.com/json-iterator/go"
|
||||||
"github.com/kercylan98/minotaur/utils/log"
|
"github.com/kercylan98/minotaur/utils/log"
|
||||||
|
@ -9,29 +10,31 @@ import (
|
||||||
|
|
||||||
var json = jsonIter.ConfigCompatibleWithStandardLibrary
|
var json = jsonIter.ConfigCompatibleWithStandardLibrary
|
||||||
var (
|
var (
|
||||||
IIndexConfig map[int]map[string]*IndexConfig
|
// IndexConfig 有索引
|
||||||
iIndexConfig map[int]map[string]*IndexConfig
|
IndexConfig map[int]map[string]*IndexConfigDefine
|
||||||
IEasyConfig *EasyConfig
|
_IndexConfig map[int]map[string]*IndexConfigDefine
|
||||||
iEasyConfig *EasyConfig
|
// EasyConfig 无索引
|
||||||
|
EasyConfig *EasyConfigDefine
|
||||||
|
_EasyConfig *EasyConfigDefine
|
||||||
)
|
)
|
||||||
|
|
||||||
func LoadConfig(handle func(filename string, config any) error) {
|
func LoadConfig(handle func(filename string, config any) error) {
|
||||||
var err error
|
var err error
|
||||||
iIndexConfig = make(map[int]map[string]*IndexConfig)
|
_IndexConfig = make(map[int]map[string]*IndexConfigDefine)
|
||||||
if err = handle("server.IndexConfig.json", &iIndexConfig); err != nil {
|
if err = handle("IndexConfig.json", &_IndexConfig); err != nil {
|
||||||
log.Error("Config", zap.String("Name", "IndexConfig"), zap.Bool("Invalid", true), zap.Error(err))
|
log.Error("Config", zap.String("Name", "IndexConfig"), zap.Bool("Invalid", true), zap.Error(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
iEasyConfig = new(EasyConfig)
|
_EasyConfig = new(EasyConfigDefine)
|
||||||
if err = handle("server.EasyConfig.json", iEasyConfig); err != nil {
|
if err = handle("EasyConfig.json", _EasyConfig); err != nil {
|
||||||
log.Error("Config", zap.String("Name", "EasyConfig"), zap.Bool("Invalid", true), zap.Error(err))
|
log.Error("Config", zap.String("Name", "EasyConfig"), zap.Bool("Invalid", true), zap.Error(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Refresh() {
|
func Refresh() {
|
||||||
IIndexConfig = iIndexConfig
|
IndexConfig = _IndexConfig
|
||||||
IEasyConfig = iEasyConfig
|
EasyConfig = _EasyConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
func DefaultLoad(filepath string) {
|
func DefaultLoad(filepath string) {
|
||||||
|
@ -44,4 +47,3 @@ func DefaultLoad(filepath string) {
|
||||||
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"
|
"fmt"
|
||||||
jsonIter "github.com/json-iterator/go"
|
jsonIter "github.com/json-iterator/go"
|
||||||
"github.com/kercylan98/minotaur/utils/geometry/matrix"
|
"github.com/kercylan98/minotaur/utils/geometry/matrix"
|
||||||
|
"github.com/kercylan98/minotaur/utils/hash"
|
||||||
"github.com/kercylan98/minotaur/utils/str"
|
"github.com/kercylan98/minotaur/utils/str"
|
||||||
"github.com/kercylan98/minotaur/utils/xlsxtool"
|
"github.com/kercylan98/minotaur/utils/xlsxtool"
|
||||||
"github.com/tealeg/xlsx"
|
"github.com/tealeg/xlsx"
|
||||||
|
@ -15,10 +16,14 @@ import (
|
||||||
|
|
||||||
// NewConfig 定位为空将读取Sheet名称
|
// NewConfig 定位为空将读取Sheet名称
|
||||||
// - 表格中需要严格遵守 描述、名称、类型、导出参数、数据列的顺序
|
// - 表格中需要严格遵守 描述、名称、类型、导出参数、数据列的顺序
|
||||||
func NewConfig(sheet *xlsx.Sheet) (*Config, error) {
|
func NewConfig(sheet *xlsx.Sheet, exist map[string]bool) (*Config, error) {
|
||||||
config := &Config{
|
config := &Config{
|
||||||
ignore: "#",
|
ignore: "#",
|
||||||
excludeFields: map[int]bool{0: true},
|
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 {
|
if err := config.initField(sheet); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -27,6 +32,7 @@ func NewConfig(sheet *xlsx.Sheet) (*Config, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
|
Exist map[string]bool
|
||||||
Prefix string
|
Prefix string
|
||||||
DisplayName string
|
DisplayName string
|
||||||
Name string
|
Name string
|
||||||
|
@ -68,6 +74,12 @@ func (slf *Config) initField(sheet *xlsx.Sheet) error {
|
||||||
slf.Name = str.FirstUpper(strings.TrimSpace(value.String()))
|
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 {
|
if indexCount == nil {
|
||||||
slf.IndexCount, _ = strconv.Atoi(sheet.Name)
|
slf.IndexCount, _ = strconv.Atoi(sheet.Name)
|
||||||
|
@ -120,22 +132,22 @@ func (slf *Config) initField(sheet *xlsx.Sheet) error {
|
||||||
describe, fieldName, fieldType, exportParam string
|
describe, fieldName, fieldType, exportParam string
|
||||||
)
|
)
|
||||||
var skip bool
|
var skip bool
|
||||||
if value := slf.matrix.Get(dx, dy); value == nil {
|
if value, exist := slf.matrix.GetExist(dx, dy); !exist {
|
||||||
skip = true
|
skip = true
|
||||||
} else {
|
} else {
|
||||||
describe = value.String()
|
describe = value.String()
|
||||||
}
|
}
|
||||||
if value := slf.matrix.Get(nx, ny); value == nil {
|
if value, exist := slf.matrix.GetExist(nx, ny); !exist {
|
||||||
skip = true
|
skip = true
|
||||||
} else {
|
} else {
|
||||||
fieldName = str.FirstUpper(strings.TrimSpace(value.String()))
|
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
|
skip = true
|
||||||
} else {
|
} else {
|
||||||
fieldType = strings.TrimSpace(value.String())
|
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
|
skip = true
|
||||||
} else {
|
} else {
|
||||||
exportParam = strings.ToLower(strings.TrimSpace(value.String()))
|
exportParam = strings.ToLower(strings.TrimSpace(value.String()))
|
||||||
|
@ -233,6 +245,7 @@ func (slf *Config) initData() error {
|
||||||
var lineClient = map[any]any{}
|
var lineClient = map[any]any{}
|
||||||
var skip bool
|
var skip bool
|
||||||
var offset int
|
var offset int
|
||||||
|
var stop bool
|
||||||
for i := 0; i < len(slf.Fields); i++ {
|
for i := 0; i < len(slf.Fields); i++ {
|
||||||
if slf.excludeFields[i] {
|
if slf.excludeFields[i] {
|
||||||
if c := slf.matrix.Get(x+i, y); c != nil && strings.HasPrefix(c.String(), "#") {
|
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
|
var value any
|
||||||
if slf.horizontal {
|
if slf.horizontal {
|
||||||
c := slf.matrix.Get(x+i, y)
|
c := slf.matrix.Get(x+i, y)
|
||||||
if c == nil || (currentIndex < slf.IndexCount && len(c.String()) == 0) {
|
if c == nil || (currentIndex < slf.IndexCount && len(strings.TrimSpace(c.String())) == 0) {
|
||||||
skip = true
|
stop = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
value = getValueWithType(field.SourceType, c.String())
|
value = getValueWithType(field.SourceType, c.String())
|
||||||
|
@ -273,6 +286,9 @@ func (slf *Config) initData() error {
|
||||||
case "sc", "cs":
|
case "sc", "cs":
|
||||||
lineServer[field.Name] = value
|
lineServer[field.Name] = value
|
||||||
lineClient[field.Name] = value
|
lineClient[field.Name] = value
|
||||||
|
default:
|
||||||
|
skip = true
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if currentIndex < slf.IndexCount {
|
if currentIndex < slf.IndexCount {
|
||||||
|
@ -304,7 +320,9 @@ func (slf *Config) initData() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if slf.horizontal {
|
if stop {
|
||||||
|
break
|
||||||
|
} else if slf.horizontal {
|
||||||
y++
|
y++
|
||||||
if y >= slf.matrix.GetHeight() {
|
if y >= slf.matrix.GetHeight() {
|
||||||
break
|
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 {
|
func (slf *Config) GetVariableGen() string {
|
||||||
|
|
|
@ -3,6 +3,8 @@ package internal
|
||||||
import "errors"
|
import "errors"
|
||||||
|
|
||||||
var (
|
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")
|
ErrReadConfigFailedWithDisplayName = errors.New("read config display name failed, can not found position")
|
||||||
ErrReadConfigFailedWithName = errors.New("read config 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")
|
ErrReadConfigFailedWithIndexCount = errors.New("read config index count failed, can not found position")
|
||||||
|
|
|
@ -3,12 +3,19 @@ package internal
|
||||||
const (
|
const (
|
||||||
generateConfigTemplate = `
|
generateConfigTemplate = `
|
||||||
|
|
||||||
// {{.Name}} {{.DisplayName}}
|
// {{.Name}}Define {{.DisplayName}}
|
||||||
type {{.Name}} struct {
|
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}}
|
{{range $index, $value := .Fields}}{{if eq $value.Server true}}{{if eq $value.Ignore false}}{{$value.Name}} {{$value.Type}} // {{$value.Describe}}{{end}}{{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}}
|
{{range $index, $value := .Fields}}{{$value}}{{end}}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
@ -37,21 +44,22 @@ var json = jsonIter.ConfigCompatibleWithStandardLibrary
|
||||||
|
|
||||||
var (
|
var (
|
||||||
{{range $index, $config := .Configs}}
|
{{range $index, $config := .Configs}}
|
||||||
I{{$config.Name}} {{$config.GetVariable}}
|
// {{$config.Name}} {{$config.DisplayName}}
|
||||||
i{{$config.Name}} {{$config.GetVariable}}
|
{{$config.Name}} {{$config.GetVariable}}
|
||||||
|
_{{$config.Name}} {{$config.GetVariable}}
|
||||||
{{end}}
|
{{end}}
|
||||||
)
|
)
|
||||||
|
|
||||||
func LoadConfig(handle func(filename string, config any) error) {
|
func LoadConfig(handle func(filename string, config any) error) {
|
||||||
var err error
|
var err error
|
||||||
{{range $index, $config := .Configs}}
|
{{range $index, $config := .Configs}}
|
||||||
i{{$config.Name}} = {{$config.GetVariableGen}}
|
_{{$config.Name}} = {{$config.GetVariableGen}}
|
||||||
{{if eq $config.IndexCount 0}}
|
{{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))
|
log.Error("Config", zap.String("Name", "{{$config.Name}}"), zap.Bool("Invalid", true), zap.Error(err))
|
||||||
}
|
}
|
||||||
{{else}}
|
{{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))
|
log.Error("Config", zap.String("Name", "{{$config.Name}}"), zap.Bool("Invalid", true), zap.Error(err))
|
||||||
}
|
}
|
||||||
{{end}}
|
{{end}}
|
||||||
|
@ -60,7 +68,7 @@ func LoadConfig(handle func(filename string, config any) error) {
|
||||||
|
|
||||||
func Refresh() {
|
func Refresh() {
|
||||||
{{range $index, $config := .Configs}}
|
{{range $index, $config := .Configs}}
|
||||||
I{{$config.Name}} = i{{$config.Name}}
|
{{$config.Name}} = _{{$config.Name}}
|
||||||
{{end}}
|
{{end}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Binary file not shown.
|
@ -1,6 +1,7 @@
|
||||||
package matrix
|
package matrix
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/kercylan98/minotaur/utils/generic"
|
||||||
"github.com/kercylan98/minotaur/utils/geometry"
|
"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)]
|
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 获取特定坐标的内容
|
// GetWithPos 获取特定坐标的内容
|
||||||
func (slf *Matrix[T]) GetWithPos(pos int) (value T) {
|
func (slf *Matrix[T]) GetWithPos(pos int) (value T) {
|
||||||
return slf.m[pos]
|
return slf.m[pos]
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package hash
|
package hash
|
||||||
|
|
||||||
|
import "encoding/json"
|
||||||
|
|
||||||
// Exist 检查特定 key 是否存在
|
// Exist 检查特定 key 是否存在
|
||||||
func Exist[K comparable, V any](m map[K]V, key K) bool {
|
func Exist[K comparable, V any](m map[K]V, key K) bool {
|
||||||
_, exist := m[key]
|
_, exist := m[key]
|
||||||
|
@ -15,3 +17,11 @@ func AllExist[K comparable, V any](m map[K]V, keys ...K) bool {
|
||||||
}
|
}
|
||||||
return true
|
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