feat: add Go backend

This commit is contained in:
richjohnrambo
2026-10-10 20:56:17 +08:00
parent 50fcfd2d3d
commit f6024f0964
1040 changed files with 107169 additions and 0 deletions
+81
View File
@@ -0,0 +1,81 @@
// Package dict
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2023 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
package dict
import (
"context"
"errors"
"fmt"
"github.com/gogf/gf/v2/frame/g"
"hash/fnv"
"hotgo/internal/model"
"strconv"
)
const (
BuiltinId int64 = -1 // 内置字典ID
EnumsId int64 = -2 // 枚举字典ID
FuncId int64 = -3 // 方法字典ID
)
var NotExistKeyError = errors.New("not exist key")
// GetOptions 获取内置选项
func GetOptions(ctx context.Context, key string) (opts []*model.Option, err error) {
opts = GetEnumsOptions(key)
if opts != nil {
return
}
return GetFuncOptions(ctx, key)
}
// GetOptionsById 通过类型ID获取内置选项
func GetOptionsById(ctx context.Context, id int64) (opts []*model.Option, err error) {
for _, v := range GetAllEnums() {
if v.Id == id {
return v.Opts, nil
}
}
for _, v := range GetAllFunc() {
g.Log().Warningf(ctx, "GetAllFunc GetOptionsById v:%v, %v", v.Id, v.Key)
if v.Id == id {
return LoadFuncOptions(ctx, v)
}
}
err = NotExistKeyError
return
}
// GetTypeById 通过类型ID获取内置选项类型
func GetTypeById(ctx context.Context, id int64) (typ string, err error) {
for _, v := range GetAllEnums() {
if v.Id == id {
return v.Key, nil
}
}
for _, v := range GetAllFunc() {
if v.Id == id {
return v.Key, nil
}
}
err = NotExistKeyError
return
}
// GenIdHash 生成字典id
func GenIdHash(str string, t int64) int64 {
prefix := 10000 * t
h := fnv.New32a()
h.Write([]byte("dict" + str))
idStr := fmt.Sprintf("%d%d", prefix, int64(h.Sum32()))
id, _ := strconv.ParseInt(idStr, 10, 64)
return id
}
+181
View File
@@ -0,0 +1,181 @@
// Package dict
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2023 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
package dict
import (
"hash/fnv"
"hotgo/internal/model"
"github.com/gogf/gf/v2/util/gconv"
)
// GenDefaultOption 生成默认表格回显样式
func GenDefaultOption(key interface{}, label string, extra ...any) *model.Option {
e := interface{}(nil)
if len(extra) > 0 {
e = extra[0]
}
return &model.Option{
Key: key,
Label: label,
Value: key,
ListClass: "default",
Extra: e,
}
}
func GenSuccessOption(key interface{}, label string, extra ...any) *model.Option {
e := interface{}(nil)
if len(extra) > 0 {
e = extra[0]
}
return &model.Option{
Key: key,
Label: label,
Value: key,
ListClass: "success",
Extra: e,
}
}
func GenWarningOption(key interface{}, label string, extra ...any) *model.Option {
e := interface{}(nil)
if len(extra) > 0 {
e = extra[0]
}
return &model.Option{
Key: key,
Label: label,
Value: key,
ListClass: "warning",
Extra: e,
}
}
func GenErrorOption(key interface{}, label string, extra ...any) *model.Option {
e := interface{}(nil)
if len(extra) > 0 {
e = extra[0]
}
return &model.Option{
Key: key,
Label: label,
Value: key,
ListClass: "error",
Extra: e,
}
}
func GenInfoOption(key interface{}, label string, extra ...any) *model.Option {
e := interface{}(nil)
if len(extra) > 0 {
e = extra[0]
}
return &model.Option{
Key: key,
Label: label,
Value: key,
ListClass: "info",
Extra: e,
}
}
func GenPrimaryOption(key interface{}, label string, extra ...any) *model.Option {
e := interface{}(nil)
if len(extra) > 0 {
e = extra[0]
}
return &model.Option{
Key: key,
Label: label,
Value: key,
ListClass: "primary",
Extra: e,
}
}
// GenCustomOption 生成自定义表格回显样式
func GenCustomOption(key interface{}, label string, custom string, extra ...any) *model.Option {
e := interface{}(nil)
if len(extra) > 0 {
e = extra[0]
}
return &model.Option{
Key: key,
Label: label,
Value: key,
ListClass: custom,
Extra: e,
}
}
// GenHashOption 根据不同label以hash算法生成表格回显样式
func GenHashOption(key interface{}, label string, extra ...any) *model.Option {
e := interface{}(nil)
if len(extra) > 0 {
e = extra[0]
}
strings := []string{"default", "primary", "info", "success", "warning", "error"}
hash := fnv.New32()
tag := "default"
if _, err := hash.Write(gconv.Bytes(label)); err == nil {
index := uint32(hash.Sum32()) % uint32(len(strings))
if index < uint32(len(strings)) {
tag = strings[index]
}
}
return &model.Option{
Key: key,
Label: label,
Value: key,
ListClass: tag,
Extra: e,
}
}
// GetOption 通过key找到label
func GetOption(ses []*model.Option, key interface{}) *model.Option {
for _, v := range ses {
if gconv.String(v.Key) == gconv.String(key) {
return v
}
}
return nil
}
// GetOptionLabel 通过key找到label
func GetOptionLabel(ses []*model.Option, key interface{}) string {
for _, v := range ses {
if gconv.String(v.Key) == gconv.String(key) {
return v.Label
}
}
return ``
}
// HasOptionKey 是否存在指定key
func HasOptionKey(ses []*model.Option, key interface{}) bool {
for _, v := range ses {
if gconv.String(v.Key) == gconv.String(key) {
return true
}
}
return false
}
// UniqueOption 去重选项
func UniqueOption(src []*model.Option) (dst []*model.Option) {
temp := map[string]struct{}{}
for _, item := range src {
key := gconv.String(item.Key)
if _, ok := temp[key]; !ok {
temp[key] = struct{}{}
dst = append(dst, item)
}
}
return dst
}
@@ -0,0 +1,70 @@
// Package dict
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2023 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
package dict
import (
"fmt"
"hotgo/internal/model"
"sync"
)
type EnumsOption struct {
Id int64 // 字典ID,由系统自动生成
Key string // 字典选项key
Label string // 字典选项标签名称
Opts []*model.Option // 数据选项
}
var (
enumsOptions = make(map[string]*EnumsOption)
eLock sync.Mutex
)
// GetAllEnums 获取所有枚举字典
func GetAllEnums() map[string]*EnumsOption {
return enumsOptions
}
// RegisterEnums 注册枚举字典选项
func RegisterEnums(key, label string, opts []*model.Option) {
eLock.Lock()
defer eLock.Unlock()
if len(key) == 0 {
panic("字典key不能为空")
}
if _, ok := enumsOptions[key]; ok {
panic(fmt.Sprintf("重复注册枚举字典选项:%v", key))
}
for _, v := range opts {
v.Type = key
}
enumsOptions[key] = &EnumsOption{
Id: GenIdHash(key, EnumsId),
Key: key,
Label: label,
Opts: opts,
}
}
// SaveEnums 更新枚举字典选项
func SaveEnums(key, label string, opts []*model.Option) {
eLock.Lock()
defer eLock.Unlock()
delete(enumsOptions, key)
RegisterEnums(key, label, opts)
}
// GetEnumsOptions 获取指定枚举字典的数据选项
func GetEnumsOptions(key string) []*model.Option {
enums, ok := enumsOptions[key]
if !ok {
return nil
}
return enums.Opts
}
@@ -0,0 +1,129 @@
// Package dict
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2023 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
package dict
import (
"context"
"fmt"
"hotgo/internal/model"
"sync"
)
// FuncDict 方法字典,实现本接口即可使用内置方法字典
type FuncDict func(ctx context.Context) (res []*model.Option, err error)
type FuncOption struct {
Id int64 // 字典ID,由系统自动生成
Key string // 字典选项key
Label string // 字典选项标签名称
Fun FuncDict // 字典方法
Cache bool // 是否缓存数据选项
Opts []*model.Option // 缓存的数据选项
sync.Mutex
}
var (
funcOptions = make(map[string]*FuncOption)
fLock sync.Mutex
)
// GetAllFunc 获取所有方法字典
func GetAllFunc() map[string]*FuncOption {
return funcOptions
}
// RegisterFunc 注册方法字典选项
func RegisterFunc(key, label string, fun FuncDict, cache ...bool) {
fLock.Lock()
defer fLock.Unlock()
if len(key) == 0 {
panic("字典key不能为空")
}
if _, ok := funcOptions[key]; ok {
panic(fmt.Sprintf("重复注册方法选项:%v", key))
}
isCache := false
if len(cache) > 0 {
isCache = cache[0]
}
funcOptions[key] = &FuncOption{
Id: GenIdHash(key, FuncId),
Key: key,
Label: label,
Fun: fun,
Cache: isCache,
Opts: nil,
}
}
// SaveFunc 更新方法字典选项
func SaveFunc(key, label string, fun FuncDict, cache ...bool) {
fLock.Lock()
defer fLock.Unlock()
delete(funcOptions, key)
RegisterFunc(key, label, fun, cache...)
}
// ClearFuncCache 清理指定方法缓存选项
func ClearFuncCache(key string) (err error) {
fun, ok := funcOptions[key]
if !ok {
err = NotExistKeyError
return
}
fun.Lock()
defer fun.Unlock()
if fun.Opts != nil {
fun.Opts = nil
}
return
}
// GetFuncOptions 获取指定方法字典的数据选项
func GetFuncOptions(ctx context.Context, key string) (res []*model.Option, err error) {
fun, ok := funcOptions[key]
if !ok {
err = NotExistKeyError
return
}
return LoadFuncOptions(ctx, fun)
}
// LoadFuncOptions 加载指定方法字典的数据选项
func LoadFuncOptions(ctx context.Context, fun *FuncOption) (res []*model.Option, err error) {
if fun.Cache && fun.Opts != nil {
res = fun.Opts
return
}
fun.Lock()
defer fun.Unlock()
if fun.Cache && fun.Opts != nil {
res = fun.Opts
return
}
res, err = fun.Fun(ctx)
if err != nil {
return nil, err
}
for k := range res {
res[k].Type = fun.Key
}
if fun.Cache {
fun.Opts = res
}
return
}