From 423318168f84f9afe3735497622b7c817a752089 Mon Sep 17 00:00:00 2001 From: kercylan98 Date: Wed, 17 May 2023 18:51:00 +0800 Subject: [PATCH] =?UTF-8?q?=E9=85=8D=E7=BD=AE=E5=AF=BC=E5=87=BA=E5=B7=A5?= =?UTF-8?q?=E5=85=B7=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go.mod | 7 + go.sum | 17 ++ planner/configexport/configexport.go | 98 +++++++ planner/configexport/internal/config.go | 257 ++++++++++++++++++ planner/configexport/internal/constants.go | 42 +++ planner/configexport/internal/export.go | 46 ++++ planner/configexport/internal/export_go.go | 1 + .../configexport/internal/internal/defines.go | 22 ++ planner/configexport/internal/template.xlsx | Bin 0 -> 9542 bytes planner/configexport/internal/types.go | 222 +++++++++++++++ utils/str/str.go | 18 ++ 11 files changed, 730 insertions(+) create mode 100644 planner/configexport/configexport.go create mode 100644 planner/configexport/internal/config.go create mode 100644 planner/configexport/internal/constants.go create mode 100644 planner/configexport/internal/export.go create mode 100644 planner/configexport/internal/export_go.go create mode 100644 planner/configexport/internal/internal/defines.go create mode 100644 planner/configexport/internal/template.xlsx create mode 100644 planner/configexport/internal/types.go diff --git a/go.mod b/go.mod index db9aa93..6ef6e62 100644 --- a/go.mod +++ b/go.mod @@ -26,6 +26,7 @@ require ( github.com/goccy/go-json v0.10.0 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/gopherjs/gopherjs v1.17.2 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jonboulle/clockwork v0.3.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/jtolds/gls v4.20.0+incompatible // indirect @@ -50,8 +51,14 @@ require ( github.com/richardlehane/mscfb v1.0.4 // indirect github.com/richardlehane/msoleps v1.0.3 // indirect github.com/smartystreets/assertions v1.13.1 // indirect + github.com/spf13/cobra v1.7.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/tealeg/xlsx v1.0.5 // indirect github.com/templexxx/cpu v0.0.9 // indirect github.com/templexxx/xorsimd v0.4.1 // indirect + github.com/tidwall/gjson v1.14.4 // indirect + github.com/tidwall/match v1.1.1 // indirect + github.com/tidwall/pretty v1.2.0 // indirect github.com/tjfoc/gmsm v1.4.1 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.9 // indirect diff --git a/go.sum b/go.sum index 5b81de5..0c58604 100644 --- a/go.sum +++ b/go.sum @@ -13,6 +13,7 @@ github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhD github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -62,6 +63,8 @@ github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25d github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jonboulle/clockwork v0.3.0 h1:9BSCMi8C+0qdApAp4auwX0RkLGUjs956h0EkuQymUhg= github.com/jonboulle/clockwork v0.3.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= @@ -134,12 +137,17 @@ github.com/richardlehane/msoleps v1.0.3 h1:aznSZzrwYRl3rLKRT3gUk9am7T/mLNSnJINvN github.com/richardlehane/msoleps v1.0.3/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/smartystreets/assertions v1.13.1 h1:Ef7KhSmjZcK6AVf9YbJdvPYG9avaF0ZxudX+ThRdWfU= github.com/smartystreets/assertions v1.13.1/go.mod h1:cXr/IwVfSo/RbCSPhoAPv73p3hlSdrBH/b3SdnW/LMY= github.com/smartystreets/goconvey v1.8.0 h1:Oi49ha/2MURE0WexF052Z0m+BNSGirfjg5RL+JXWq3w= github.com/smartystreets/goconvey v1.8.0/go.mod h1:EdX8jtrTIj26jmjCOVNMVSIYAtgexqXKHOXW2Dx9JLg= github.com/sony/sonyflake v1.1.0 h1:wnrEcL3aOkWmPlhScLEGAXKkLAIslnBteNUq4Bw6MM4= github.com/sony/sonyflake v1.1.0/go.mod h1:LORtCywH/cq10ZbyfhKrHYgAUGH7mOBa76enV9txy/Y= +github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= +github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= @@ -151,12 +159,20 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/tealeg/xlsx v1.0.5 h1:+f8oFmvY8Gw1iUXzPk+kz+4GpbDZPK1FhPiQRd+ypgE= +github.com/tealeg/xlsx v1.0.5/go.mod h1:btRS8dz54TDnvKNosuAqxrM1QgN1udgk9O34bDCnORM= github.com/templexxx/cpu v0.0.1/go.mod h1:w7Tb+7qgcAlIyX4NhLuDKt78AHA5SzPmq0Wj6HiEnnk= github.com/templexxx/cpu v0.0.7/go.mod h1:w7Tb+7qgcAlIyX4NhLuDKt78AHA5SzPmq0Wj6HiEnnk= github.com/templexxx/cpu v0.0.9 h1:cGGLK8twbc1J1S/fHnZW7BylXYaFP+0fR2s+nzsFDiU= github.com/templexxx/cpu v0.0.9/go.mod h1:w7Tb+7qgcAlIyX4NhLuDKt78AHA5SzPmq0Wj6HiEnnk= github.com/templexxx/xorsimd v0.4.1 h1:iUZcywbOYDRAZUasAs2eSCUW8eobuZDy0I9FJiORkVg= github.com/templexxx/xorsimd v0.4.1/go.mod h1:W+ffZz8jJMH2SXwuKu9WhygqBMbFnp14G2fqEr8qaNo= +github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM= +github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= +github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w= github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho= github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE= @@ -322,6 +338,7 @@ google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175 google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= diff --git a/planner/configexport/configexport.go b/planner/configexport/configexport.go new file mode 100644 index 0000000..c192f10 --- /dev/null +++ b/planner/configexport/configexport.go @@ -0,0 +1,98 @@ +package main + +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" + "os/exec" + "path/filepath" + "runtime/debug" + "sync" +) + +func New(xlsxPath string) *ConfigExport { + ce := &ConfigExport{xlsxPath: xlsxPath} + xlsxFile, err := xlsx.OpenFile(xlsxPath) + if err != nil { + panic(err) + } + for i := 0; i < len(xlsxFile.Sheets); i++ { + ce.configs = append(ce.configs, internal.NewConfig(xlsxFile.Sheets[i])) + } + return ce +} + +type ConfigExport struct { + xlsxPath string + configs []*internal.Config +} + +func (slf *ConfigExport) ExportJSON(outputDir string) { + var errors []func() + var wait sync.WaitGroup + for _, config := range slf.configs { + config := config + go func() { + wait.Add(1) + defer func() { + if err := recover(); err != nil { + errors = append(errors, func() { + log.Error("导出失败", zap.String("名称", slf.xlsxPath), zap.String("Sheet", config.GetName()), zap.Any("err", err)) + fmt.Println(debug.Stack()) + }) + } + }() + if err := file.WriterFile(filepath.Join(outputDir, fmt.Sprintf("%s.json", config.GetName())), config.GetJSON()); err != nil { + panic(err) + } + wait.Done() + }() + } + + wait.Wait() + + for _, f := range errors { + f() + } +} + +func (slf *ConfigExport) ExportGo(packageName string, outputDir string) { + var vars string + var varsMake string + var types string + var varsReplace string + for _, config := range slf.configs { + v := config.GetVariable() + vars += fmt.Sprintf("var %s %s\nvar _%sReady %s\n", str.FirstUpper(config.GetName()), v, str.FirstUpper(config.GetName()), v) + varsMake += fmt.Sprintf("_%sReady = make(%s)"+` + if err := handle("%s.json", &_%sReady); err != nil { + panic(err) + } +`, str.FirstUpper(config.GetName()), v, str.FirstUpper(config.GetName()), str.FirstUpper(config.GetName())) + types += fmt.Sprintf("%s\n", config.GetStruct()) + varsReplace += fmt.Sprintf("%s = _%sReady", str.FirstUpper(config.GetName()), str.FirstUpper(config.GetName())) + } + + _ = os.MkdirAll(outputDir, 0666) + if err := file.WriterFile(filepath.Join(outputDir, "config.struct.go"), []byte(fmt.Sprintf(internal.TemplateStructGo, packageName, types))); err != nil { + panic(err) + } + if err := file.WriterFile(filepath.Join(outputDir, "config.go"), []byte(fmt.Sprintf(internal.TemplateGo, packageName, vars, varsMake, varsReplace))); err != nil { + panic(err) + } + cmd := exec.Command("gofmt", "-w", filepath.Join(outputDir, "config.struct.go")) + if err := cmd.Run(); err != nil { + fmt.Println(err) + } + + cmd = exec.Command("gofmt", "-w", filepath.Join(outputDir, "config.go")) + if err := cmd.Run(); err != nil { + fmt.Println(err) + } + +} diff --git a/planner/configexport/internal/config.go b/planner/configexport/internal/config.go new file mode 100644 index 0000000..0096fdd --- /dev/null +++ b/planner/configexport/internal/config.go @@ -0,0 +1,257 @@ +package internal + +import ( + "errors" + "fmt" + jsonIter "github.com/json-iterator/go" + "github.com/kercylan98/minotaur/utils/str" + "github.com/tealeg/xlsx" + "strings" +) + +func NewConfig(sheet *xlsx.Sheet) *Config { + config := &Config{ + Sheet: sheet, + } + + var ( + skipField = make(map[int]bool) + describeLine = config.Sheet.Rows[3] + nameLine = config.Sheet.Rows[4] + typeLine = config.Sheet.Rows[5] + exportParamLine = config.Sheet.Rows[6] + ) + // 分析数据 + { + for i := 1; i < len(describeLine.Cells); i++ { + describe := strings.TrimSpace(nameLine.Cells[i].String()) + if strings.HasPrefix(describe, "#") { + skipField[i] = true + continue + } + typ := strings.TrimSpace(typeLine.Cells[i].String()) + if strings.HasPrefix(typ, "#") || len(typ) == 0 { + skipField[i] = true + continue + } + exportParam := strings.TrimSpace(exportParamLine.Cells[i].String()) + if strings.HasPrefix(exportParam, "#") || len(exportParam) == 0 { + skipField[i] = true + continue + } + } + if len(nameLine.Cells)-1-len(skipField) < config.GetIndexCount() { + panic(errors.New("index count must greater or equal to field count")) + } + } + + config.skipField = skipField + config.describeLine = describeLine + config.nameLine = nameLine + config.typeLine = typeLine + config.exportParamLine = exportParamLine + + // 整理数据 + var ( + dataLine = make([]map[any]any, len(config.Sheet.Rows)) + ) + for i := 1; i < len(config.describeLine.Cells); i++ { + if skipField[i] { + continue + } + + var ( + //describe = strings.TrimSpace(describeLine.Cells[i].String()) + name = strings.TrimSpace(nameLine.Cells[i].String()) + //typ = strings.TrimSpace(typeLine.Cells[i].String()) + //exportParam = strings.TrimSpace(exportParamLine.Cells[i].String()) + ) + + for row := 7; row < len(config.Sheet.Rows); row++ { + //value := slf.Sheet.Rows[row].Cells[i].String() + var value = getValueWithType(typeLine.Cells[i].String(), config.Sheet.Rows[row].Cells[i].String()) + + line := dataLine[row] + if line == nil { + line = map[any]any{} + dataLine[row] = line + } + line[name] = value + } + } + + // 索引 + var dataSource = make(map[any]any) + var data = dataSource + var index = config.GetIndexCount() + var currentIndex = 0 + for row := 7; row < len(config.Sheet.Rows); row++ { + for i, cell := range config.Sheet.Rows[row].Cells { + if i == 0 || skipField[i] { + continue + } + var value = getValueWithType(typeLine.Cells[i].String(), cell.String()) + + if currentIndex < index { + currentIndex++ + m, exist := data[value] + if !exist { + if currentIndex == index { + data[value] = dataLine[row] + } else { + m = map[any]any{} + data[value] = m + } + } + if currentIndex < index { + data = m.(map[any]any) + } + } + } + data = dataSource + currentIndex = 0 + } + config.data = dataSource + config.dataLine = dataLine[len(dataLine)-1] + return config +} + +type Config struct { + *xlsx.Sheet + skipField map[int]bool + describeLine *xlsx.Row + nameLine *xlsx.Row + typeLine *xlsx.Row + exportParamLine *xlsx.Row + data map[any]any + dataLine map[any]any +} + +// GetDisplayName 获取显示名称 +func (slf *Config) GetDisplayName() string { + return slf.Name +} + +// GetName 获取配置名称 +func (slf *Config) GetName() string { + return slf.Sheet.Rows[0].Cells[1].String() +} + +// GetIndexCount 获取索引数量 +func (slf *Config) GetIndexCount() int { + index, err := slf.Sheet.Rows[1].Cells[1].Int() + if err != nil { + panic(err) + } + return index +} + +// GetData 获取数据 +func (slf *Config) GetData() map[any]any { + return slf.data +} + +// GetJSON 获取JSON类型数据 +func (slf *Config) GetJSON() []byte { + bytes, err := jsonIter.MarshalIndent(slf.GetData(), "", " ") + if err != nil { + panic(err) + } + return bytes +} + +func (slf *Config) GetVariable() string { + var index = slf.GetIndexCount() + var mapStr = "map[%s]%s" + for i := 1; i < len(slf.typeLine.Cells); i++ { + if slf.skipField[i] { + continue + } + typ := slf.typeLine.Cells[i].String() + if index > 0 { + index-- + if index == 0 { + mapStr = fmt.Sprintf(mapStr, typ, "%s") + } else { + mapStr = fmt.Sprintf(mapStr, typ, "map[%s]%s") + } + } else { + mapStr = fmt.Sprintf(mapStr, "*_"+str.FirstUpper(slf.GetName())) + break + } + } + return fmt.Sprintf("%s", mapStr) +} + +func (slf *Config) GetStruct() string { + var result string + for i := 1; i < len(slf.typeLine.Cells); i++ { + if slf.skipField[i] { + continue + } + typ := slf.typeLine.Cells[i].String() + name := slf.nameLine.Cells[i].String() + + name = str.FirstUpper(name) + result += fmt.Sprintf("%s %s\n", name, slf.GetType(typ)) + } + return fmt.Sprintf("type _%s struct{\n%s}", str.FirstUpper(slf.GetName()), result) +} + +func (slf *Config) GetType(fieldType string) string { + if name, exist := basicTypeName[fieldType]; exist { + return name + } else if strings.HasPrefix(fieldType, "[]") { + s := strings.TrimPrefix(fieldType, "[]") + if name, exist := basicTypeName[s]; exist { + return fmt.Sprintf("map[int]%s", name) + } else { + return slf.GetType(s) + } + } + + var s = strings.TrimSuffix(strings.TrimPrefix(fieldType, "{"), "}") + var fields []string + var field string + var leftBrackets []int + for i, c := range s { + switch c { + case ',': + if len(leftBrackets) == 0 { + fields = append(fields, field) + field = "" + } else { + field += string(c) + } + case '{': + leftBrackets = append(leftBrackets, i) + field += string(c) + case '}': + leftBrackets = leftBrackets[:len(leftBrackets)-1] + field += string(c) + if len(leftBrackets) == 0 { + fields = append(fields, field) + field = "" + } + default: + field += string(c) + } + } + if len(field) > 0 { + fields = append(fields, field) + } + + var result = "*struct {\n%s}" + var fieldStr string + for _, fieldInfo := range fields { + fieldName, fieldType := str.KV(strings.TrimSpace(fieldInfo), ":") + n, exist := basicTypeName[fieldType] + if exist { + fieldStr += fmt.Sprintf("%s %s\n", str.FirstUpper(fieldName), n) + } else { + fieldStr += fmt.Sprintf("%s %s\n", str.FirstUpper(fieldName), slf.GetType(fieldType)) + } + } + + return fmt.Sprintf(result, fieldStr) +} diff --git a/planner/configexport/internal/constants.go b/planner/configexport/internal/constants.go new file mode 100644 index 0000000..652e621 --- /dev/null +++ b/planner/configexport/internal/constants.go @@ -0,0 +1,42 @@ +package internal + +var TemplateGo = `// Code generated DO NOT EDIT. + +package %s + +import ( + jsonIter "github.com/json-iterator/go" + "os" +) + +var json = jsonIter.ConfigCompatibleWithStandardLibrary + +%s + +func LoadConfig(handle func(filename string, config any) error) { + %s +} + +func Replace() { + %s +} + + +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) + }) +} + +` + +var TemplateStructGo = `// Code generated DO NOT EDIT. + +package %s + +%s +` diff --git a/planner/configexport/internal/export.go b/planner/configexport/internal/export.go new file mode 100644 index 0000000..008ab8d --- /dev/null +++ b/planner/configexport/internal/export.go @@ -0,0 +1,46 @@ +package internal + +import ( + "fmt" + "github.com/kercylan98/minotaur/utils/file" + "github.com/kercylan98/minotaur/utils/log" + "github.com/tealeg/xlsx" + "go.uber.org/zap" + "path/filepath" + "runtime/debug" + "sync" +) + +func ExportJSON(xlsxPath string, output string) { + xlsxFile, err := xlsx.OpenFile(xlsxPath) + if err != nil { + panic(err) + } + var errors []func() + var wait sync.WaitGroup + for _, sheet := range xlsxFile.Sheets { + sheet := sheet + go func() { + defer func() { + if err := recover(); err != nil { + errors = append(errors, func() { + log.Error("导出失败", zap.String("名称", xlsxPath), zap.String("Sheet", sheet.Name), zap.Any("err", err)) + fmt.Println(debug.Stack()) + }) + } + }() + wait.Add(1) + config := NewConfig(sheet) + if err := file.WriterFile(filepath.Join(output, fmt.Sprintf("%s.json", config.GetName())), config.GetJSON()); err != nil { + panic(err) + } + wait.Done() + }() + } + + wait.Wait() + + for _, f := range errors { + f() + } +} diff --git a/planner/configexport/internal/export_go.go b/planner/configexport/internal/export_go.go new file mode 100644 index 0000000..5bf0569 --- /dev/null +++ b/planner/configexport/internal/export_go.go @@ -0,0 +1 @@ +package internal diff --git a/planner/configexport/internal/internal/defines.go b/planner/configexport/internal/internal/defines.go new file mode 100644 index 0000000..5db08d7 --- /dev/null +++ b/planner/configexport/internal/internal/defines.go @@ -0,0 +1,22 @@ +package internal + +type XXConfig struct { + Id int + Count string + Award map[int]string + Info *struct { + Id int + Name string + Info *struct { + Lv int + Exp *struct { + Mux int + Count int + } + } + } + Other *struct { + Id int + Name string + } +} diff --git a/planner/configexport/internal/template.xlsx b/planner/configexport/internal/template.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..b21a7a5bb0996b984d537158e440afa0df1b472e GIT binary patch literal 9542 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 0 { + fields = append(fields, field) + } + + for _, fieldInfo := range fields { + fieldName, fieldType := str.KV(strings.TrimSpace(fieldInfo), ":") + handle, exist := basicType[fieldType] + if exist { + data[fieldName] = handle(gjson.Get(fieldValue, fieldName).String()) + } else { + data[fieldName] = withStructType(fieldType, gjson.Get(fieldValue, fieldName).String()) + } + } + + return data +} + +func withSliceType(fieldType string, fieldValue string) any { + if !strings.HasPrefix(fieldType, "[]") { + return nil + } + t := strings.TrimPrefix(fieldType, "[]") + var data = map[any]any{} + gjson.ForEachLine(fieldValue, func(line gjson.Result) bool { + line.ForEach(func(key, value gjson.Result) bool { + handle, exist := basicType[t] + if exist { + data[len(data)] = handle(value.String()) + } else { + data[len(data)] = withStructType(t, value.String()) + } + return true + }) + return true + }) + return data +} + +func withStringType(fieldValue string) any { + return fieldValue +} + +func withIntType(fieldValue string) any { + value, _ := strconv.Atoi(fieldValue) + return value +} + +func withInt8Type(fieldValue string) any { + value, _ := strconv.Atoi(fieldValue) + return int8(value) +} + +func withInt16Type(fieldValue string) any { + value, _ := strconv.Atoi(fieldValue) + return int16(value) +} + +func withInt32Type(fieldValue string) any { + value, _ := strconv.Atoi(fieldValue) + return int32(value) +} + +func withInt64Type(fieldValue string) any { + value, _ := strconv.ParseInt(fieldValue, 10, 64) + return value +} + +func withUintType(fieldValue string) any { + value, _ := strconv.Atoi(fieldValue) + return uint(value) +} + +func withUint8Type(fieldValue string) any { + value, _ := strconv.Atoi(fieldValue) + return uint8(value) +} + +func withUint16Type(fieldValue string) any { + value, _ := strconv.Atoi(fieldValue) + return uint16(value) +} + +func withUint32Type(fieldValue string) any { + value, _ := strconv.Atoi(fieldValue) + return uint32(value) +} + +func withUint64Type(fieldValue string) any { + value, _ := strconv.ParseInt(fieldValue, 10, 64) + return uint64(value) +} + +func withFloat32Type(fieldValue string) any { + value, _ := strconv.ParseFloat(fieldValue, 32) + return value +} + +func withFloat64Type(fieldValue string) any { + value, _ := strconv.ParseFloat(fieldValue, 64) + return value +} + +func withByteType(fieldValue string) any { + value, _ := strconv.Atoi(fieldValue) + return byte(value) +} + +func withRuneType(fieldValue string) any { + value, _ := strconv.Atoi(fieldValue) + return rune(value) +} + +func withBoolType(fieldValue string) any { + switch fieldValue { + case "0", "false", "!": + return false + case "1", "true", "&": + return true + default: + return false + } +} diff --git a/utils/str/str.go b/utils/str/str.go index df8f7e7..ddf83ee 100644 --- a/utils/str/str.go +++ b/utils/str/str.go @@ -1,2 +1,20 @@ package str +// FirstUpper 首字母大写 +func FirstUpper(str string) string { + var upperStr string + vv := []rune(str) // 后文有介绍 + for i := 0; i < len(vv); i++ { + if i == 0 { + if vv[i] >= 97 && vv[i] <= 122 { // 后文有介绍 + vv[i] -= 32 // string的码表相差32位 + upperStr += string(vv[i]) + } else { + return str + } + } else { + upperStr += string(vv[i]) + } + } + return upperStr +}