im 管理后台

This commit is contained in:
richjohnrambo
2026-08-11 23:13:51 +08:00
parent 0397fe5f22
commit 331a55751d
1407 changed files with 162069 additions and 2 deletions
+166
View File
@@ -0,0 +1,166 @@
// Package convert
// @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 convert
import (
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/text/gstr"
"hotgo/utility/validate"
"reflect"
"unicode"
"unsafe"
)
var (
descTags = []string{"description", "dc", "json"} // 实体描述标签
fieldTags = []string{"json"} // 实体字段名称映射
)
// GetModelTable 获取模型中的表定义
func GetModelTable(m *gdb.Model) (tablesInit, tables string) {
if m == nil {
return "", ""
}
v := reflect.ValueOf(m).Elem()
t := reflect.TypeOf(m).Elem()
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
val := v.Field(i)
if field.Name == "tablesInit" {
tablesInit = reflect.NewAt(val.Type(), unsafe.Pointer(val.UnsafeAddr())).Elem().String()
tablesInit = gstr.Replace(tablesInit, "`", "")
continue
}
if field.Name == "tables" {
tables = reflect.NewAt(val.Type(), unsafe.Pointer(val.UnsafeAddr())).Elem().String()
continue
}
}
return
}
// EscapeFieldsToSlice 将转义过的字段转换为字段集切片
func EscapeFieldsToSlice(s string) []string {
return gstr.Explode(",", gstr.Replace(gstr.Replace(s, "`,`", ","), "`", ""))
}
// GetMapKeys 获取map的所有key
func GetMapKeys[K comparable](m map[K]any) []K {
j := 0
keys := make([]K, len(m))
for k := range m {
keys[j] = k
j++
}
return keys
}
// CamelCaseToUnderline 驼峰单词转下划线单词
func CamelCaseToUnderline(s string) string {
var output []rune
for i, r := range s {
if i == 0 {
output = append(output, unicode.ToLower(r))
} else {
if unicode.IsUpper(r) {
output = append(output, '_')
}
output = append(output, unicode.ToLower(r))
}
}
return string(output)
}
// GetEntityFieldTags 获取实体中的字段名称
func GetEntityFieldTags(entity interface{}) (tags []string, err error) {
var formRef = reflect.TypeOf(entity)
for i := 0; i < formRef.NumField(); i++ {
field := formRef.Field(i)
if field.Type.Kind() == reflect.Struct {
addTags, err := reflectTag(field.Type, fieldTags, []string{})
if err != nil {
return nil, err
}
tags = append(tags, addTags...)
continue
}
tags = append(tags, reflectTagName(field, fieldTags, true))
}
return
}
// GetEntityDescTags 获取实体中的描述标签
func GetEntityDescTags(entity interface{}) (tags []string, err error) {
var formRef = reflect.TypeOf(entity)
for i := 0; i < formRef.NumField(); i++ {
field := formRef.Field(i)
if field.Type.Kind() == reflect.Struct {
addTags, err := reflectTag(field.Type, descTags, []string{})
if err != nil {
return nil, err
}
tags = append(tags, addTags...)
continue
}
tags = append(tags, reflectTagName(field, descTags, true))
}
return
}
// reflectTag 层级递增解析tag
func reflectTag(reflectType reflect.Type, filterTags []string, tags []string) ([]string, error) {
if reflectType.Kind() == reflect.Ptr {
return nil, gerror.Newf("reflect type do not support reflect.Ptr yet, reflectType:%+v", reflectType)
}
if reflectType.Kind() != reflect.Struct {
return nil, nil
}
for i := 0; i < reflectType.NumField(); i++ {
tag := reflectTagName(reflectType.Field(i), filterTags, false)
if tag == "" {
addTags, err := reflectTag(reflectType.Field(i).Type, filterTags, tags)
if err != nil {
return nil, err
}
tags = append(tags, addTags...)
continue
}
tags = append(tags, tag)
}
return tags, nil
}
// reflectTagName 解析实体中的描述标签,优先级:description > dc > json > Name
func reflectTagName(field reflect.StructField, filterTags []string, isDef bool) string {
if validate.InSlice(filterTags, "description") {
if description, ok := field.Tag.Lookup("description"); ok && description != "" {
return description
}
}
if validate.InSlice(filterTags, "dc") {
if dc, ok := field.Tag.Lookup("dc"); ok && dc != "" {
return dc
}
}
if validate.InSlice(filterTags, "json") {
if jsonName, ok := field.Tag.Lookup("json"); ok && jsonName != "" {
return jsonName
}
}
if !isDef {
return ""
}
return field.Name
}
+115
View File
@@ -0,0 +1,115 @@
// Package convert
// @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 convert
import (
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gconv"
"hotgo/utility/validate"
)
// IpFilterStrategy ip过滤策略
func IpFilterStrategy(originIp string) (list map[string]struct{}) {
list = make(map[string]struct{})
// 所有IP
if originIp == "*" {
list["*"] = struct{}{}
return
}
// 多个IP
if gstr.Contains(originIp, ",") {
ips := gstr.Explode(",", originIp)
if len(ips) > 0 {
for _, ip := range ips {
if !validate.IsIp(ip) {
continue
}
list[ip] = struct{}{}
}
}
return
}
// IP段
if gstr.Contains(originIp, "/24") {
segment := gstr.Replace(originIp, "/24", "")
if !validate.IsIp(segment) {
return
}
var (
start = gstr.Explode(".", segment)
prefix = gstr.Implode(".", start[:len(start)-1]) + "."
index = gconv.Int(start[len(start)-1])
)
if index < 1 {
index = 1
}
for i := index; i <= 254; i++ {
list[prefix+gconv.String(i)] = struct{}{}
}
return
}
// IP范围
if gstr.Contains(originIp, "-") {
originIps := gstr.Explode("-", originIp)
if len(originIps) != 2 {
return
}
if !validate.IsIp(originIps[0]) || !validate.IsIp(originIps[1]) {
return
}
var (
start = gstr.Explode(".", originIps[0])
prefix = gstr.Implode(".", start[:len(start)-1]) + "."
startIndex = gconv.Int(gstr.SubStrFromREx(originIps[0], "."))
endIndex = gconv.Int(gstr.SubStrFromREx(originIps[1], "."))
)
if startIndex >= endIndex {
list[originIps[0]] = struct{}{}
return
}
if startIndex < 1 {
startIndex = 1
}
if endIndex > 254 {
endIndex = 254
}
for i := startIndex; i <= endIndex; i++ {
list[prefix+gconv.String(i)] = struct{}{}
}
return
}
// 指定IP
if validate.IsIp(originIp) {
list[originIp] = struct{}{}
return
}
return list
}
// MatchIpStrategy 匹配IP策略,输入ip如果在策略当中返回true
func MatchIpStrategy(rules, ip string) bool {
allowedIps := IpFilterStrategy(rules)
if _, ok := allowedIps["*"]; ok {
return true
}
_, ok := allowedIps[ip]
return ok
}
+59
View File
@@ -0,0 +1,59 @@
// Package convert
// @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 convert
// UniqueSlice 切片去重
func UniqueSlice[K comparable](languages []K) []K {
result := make([]K, 0, len(languages))
temp := map[K]struct{}{}
for _, item := range languages {
if _, ok := temp[item]; !ok {
temp[item] = struct{}{}
result = append(result, item)
}
}
return result
}
func Remove(sl []interface{}, f func(v1 interface{}) bool) []interface{} {
for k, v := range sl {
if f(v) {
sl[k] = sl[len(sl)-1]
sl = sl[:len(sl)-1]
return sl
}
}
return sl
}
func RemoveSlice[K comparable](src []K, sub K) []K {
for k, v := range src {
if v == sub {
copy(src[k:], src[k+1:])
return src[:len(src)-1]
}
}
return src
}
// DifferenceSlice 比较两个切片,返回他们的差集
// slice1 := []int{1, 2, 3, 4, 5}
// slice2 := []int{4, 5, 6, 7, 8}
// fmt.Println(Difference(slice1, slice2)) // Output: [1 2 3]
func DifferenceSlice[T comparable](s1, s2 []T) []T {
m := make(map[T]bool)
for _, item := range s1 {
m[item] = true
}
var diff []T
for _, item := range s2 {
if _, ok := m[item]; !ok {
diff = append(diff, item)
}
}
return diff
}