初始
This commit is contained in:
249
library/libUtils/slice_tree.go
Normal file
249
library/libUtils/slice_tree.go
Normal file
@ -0,0 +1,249 @@
|
||||
package libUtils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/v2/container/garray"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// ParentSonSort 有层级关系的数组,父级-》子级 排序
|
||||
func ParentSonSort(list g.List, params ...interface{}) g.List {
|
||||
args := make([]interface{}, 8)
|
||||
for k, v := range params {
|
||||
if k == 8 {
|
||||
break
|
||||
}
|
||||
args[k] = v
|
||||
}
|
||||
var (
|
||||
pid int //父级id
|
||||
level int //层级数
|
||||
fieldName string //父级id键名
|
||||
id string //id键名
|
||||
levelName string //层级名称
|
||||
title string //标题名称
|
||||
breaks int //中断层级
|
||||
prefixStr string //字符串前缀
|
||||
)
|
||||
pid = gconv.Int(GetSliceByKey(args, 0, 0))
|
||||
level = gconv.Int(GetSliceByKey(args, 1, 0))
|
||||
fieldName = gconv.String(GetSliceByKey(args, 2, "pid"))
|
||||
id = gconv.String(GetSliceByKey(args, 3, "id"))
|
||||
levelName = gconv.String(GetSliceByKey(args, 4, "flg"))
|
||||
title = gconv.String(GetSliceByKey(args, 5, "title"))
|
||||
breaks = gconv.Int(GetSliceByKey(args, 6, -1))
|
||||
prefixStr = gconv.String(GetSliceByKey(args, 7, "─"))
|
||||
//定义一个新slice用于返回
|
||||
var returnSlice g.List
|
||||
for _, v := range list {
|
||||
if pid == gconv.Int(v[fieldName]) {
|
||||
v[levelName] = level
|
||||
levelClone := level
|
||||
titlePrefix := ""
|
||||
for {
|
||||
if levelClone < 0 {
|
||||
break
|
||||
}
|
||||
titlePrefix += prefixStr
|
||||
levelClone--
|
||||
}
|
||||
titlePrefix = "├" + titlePrefix
|
||||
if level == 0 {
|
||||
v["title_prefix"] = ""
|
||||
} else {
|
||||
v["title_prefix"] = titlePrefix
|
||||
}
|
||||
v["title_show"] = fmt.Sprintf("%s%s", v["title_prefix"], v[title])
|
||||
returnSlice = append(returnSlice, v)
|
||||
if breaks != -1 && breaks == level {
|
||||
continue
|
||||
}
|
||||
args[0] = v[id]
|
||||
args[1] = level + 1
|
||||
newSlice2 := ParentSonSort(list, args...)
|
||||
if len(newSlice2) > 0 {
|
||||
returnSlice = append(returnSlice, newSlice2...)
|
||||
}
|
||||
}
|
||||
}
|
||||
return returnSlice
|
||||
}
|
||||
|
||||
// PushSonToParent 有层级关系的数组 ,将子级压入到父级(树形结构)
|
||||
func PushSonToParent(list g.List, params ...interface{}) g.List {
|
||||
args := make([]interface{}, 7)
|
||||
for k, v := range params {
|
||||
if k == 7 {
|
||||
break
|
||||
}
|
||||
args[k] = v
|
||||
}
|
||||
var (
|
||||
pid string //父级id
|
||||
fieldName string //父级id键名
|
||||
id string //id键名
|
||||
key string //子级数组键名
|
||||
filter string //过滤键名
|
||||
filterVal interface{} //过滤的值
|
||||
showNoChild bool //是否显示不存在的子级健
|
||||
)
|
||||
pid = gconv.String(GetSliceByKey(args, 0, 0))
|
||||
fieldName = gconv.String(GetSliceByKey(args, 1, "pid"))
|
||||
id = gconv.String(GetSliceByKey(args, 2, "id"))
|
||||
key = gconv.String(GetSliceByKey(args, 3, "children"))
|
||||
filter = gconv.String(GetSliceByKey(args, 4, ""))
|
||||
filterVal = GetSliceByKey(args, 5, nil)
|
||||
showNoChild = gconv.Bool(GetSliceByKey(args, 6, true))
|
||||
var returnList g.List
|
||||
for _, v := range list {
|
||||
if gconv.String(v[fieldName]) == pid {
|
||||
if filter != "" {
|
||||
if reflect.DeepEqual(v[filter], filterVal) {
|
||||
args[0] = v[id]
|
||||
child := PushSonToParent(list, args...)
|
||||
if child != nil || showNoChild {
|
||||
v[key] = child
|
||||
}
|
||||
returnList = append(returnList, v)
|
||||
}
|
||||
} else {
|
||||
args[0] = v[id]
|
||||
child := PushSonToParent(list, args...)
|
||||
if child != nil || showNoChild {
|
||||
v[key] = child
|
||||
}
|
||||
returnList = append(returnList, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
return returnList
|
||||
}
|
||||
|
||||
// GetSliceByKey 获取切片里的值 若为nil 可设置默认值val
|
||||
func GetSliceByKey(args []interface{}, key int, val interface{}) interface{} {
|
||||
var value interface{}
|
||||
if args[key] != nil {
|
||||
value = args[key]
|
||||
} else {
|
||||
value = val
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
// FindSonByParentId 有层级关系的切片,通过父级id查找所有子级id数组
|
||||
// parentId 父级id
|
||||
// parentIndex 父级索引名称
|
||||
// idIndex id索引名称
|
||||
func FindSonByParentId(list g.List, parentId interface{}, parentIndex, idIndex string) g.List {
|
||||
newList := make(g.List, 0, len(list))
|
||||
for _, v := range list {
|
||||
if reflect.DeepEqual(v[parentIndex], parentId) {
|
||||
newList = append(newList, v)
|
||||
fList := FindSonByParentId(list, v[idIndex], parentIndex, idIndex)
|
||||
newList = append(newList, fList...)
|
||||
}
|
||||
}
|
||||
return newList
|
||||
}
|
||||
|
||||
// GetTopPidList 获取最顶层 parent Id
|
||||
func GetTopPidList(list g.List, parentIndex, idIndex string) *garray.Array {
|
||||
arr := garray.NewArray()
|
||||
for _, v1 := range list {
|
||||
tag := true
|
||||
for _, v2 := range list {
|
||||
if v1[parentIndex] == v2[idIndex] {
|
||||
tag = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if tag {
|
||||
arr.PushRight(v1[parentIndex])
|
||||
}
|
||||
}
|
||||
return arr.Unique()
|
||||
}
|
||||
|
||||
// FindParentBySonPid 有层级关系的数组,通过子级fid查找所有父级数组
|
||||
func FindParentBySonPid(list g.List, id int, params ...interface{}) g.List {
|
||||
args := make([]interface{}, 4)
|
||||
for k, v := range params {
|
||||
if k == 4 {
|
||||
break
|
||||
}
|
||||
args[k] = v
|
||||
}
|
||||
var (
|
||||
filter = gconv.String(GetSliceByKey(args, 0, "filter")) //过滤键名
|
||||
fPid = gconv.String(GetSliceByKey(args, 1, "pid")) //父级id字段键名
|
||||
filterValue = GetSliceByKey(args, 2, nil) //过滤键值
|
||||
fid = gconv.String(GetSliceByKey(args, 3, "id")) //id字段键名
|
||||
)
|
||||
rList := make(g.List, 0, len(list))
|
||||
for _, v := range list {
|
||||
if gconv.Int(v[fid]) == id {
|
||||
if fv, ok := v[filter]; ok {
|
||||
if reflect.DeepEqual(fv, filterValue) {
|
||||
rList = append(rList, v)
|
||||
}
|
||||
} else {
|
||||
rList = append(rList, v)
|
||||
}
|
||||
r := FindParentBySonPid(list, gconv.Int(v[fPid]), filter, fPid, filterValue, fid)
|
||||
rList = append(rList, r...)
|
||||
}
|
||||
}
|
||||
return rList
|
||||
}
|
||||
|
||||
// FindTopParent
|
||||
/**
|
||||
* 根据id查询最顶层父级信息
|
||||
* @param list 有层级关系的数组
|
||||
* @param id 查找的id
|
||||
* @param string fpid 父级id键名
|
||||
* @param string fid 当前id键名
|
||||
* @return g.Map
|
||||
*/
|
||||
func FindTopParent(list g.List, id int64, params ...interface{}) g.Map {
|
||||
if len(list) == 0 {
|
||||
return g.Map{}
|
||||
}
|
||||
args := make([]interface{}, 2)
|
||||
for k, v := range params {
|
||||
if k == 2 {
|
||||
break
|
||||
}
|
||||
args[k] = v
|
||||
}
|
||||
var (
|
||||
fPid = gconv.String(GetSliceByKey(args, 0, "pid")) //父级id字段键名
|
||||
fid = gconv.String(GetSliceByKey(args, 1, "id")) //id字段键名
|
||||
)
|
||||
hasParent := true
|
||||
top := g.Map{}
|
||||
//找到要查找id值的数组
|
||||
for _, v := range list {
|
||||
if gconv.Int64(v[fid]) == gconv.Int64(id) {
|
||||
top = v
|
||||
break
|
||||
}
|
||||
}
|
||||
for {
|
||||
if !hasParent {
|
||||
break
|
||||
}
|
||||
//查询最顶层
|
||||
for _, v := range list {
|
||||
if gconv.Int64(top[fPid]) == gconv.Int64(v[fid]) {
|
||||
top = v
|
||||
hasParent = true
|
||||
break
|
||||
}
|
||||
hasParent = false
|
||||
}
|
||||
}
|
||||
return top
|
||||
}
|
232
library/libUtils/utils.go
Normal file
232
library/libUtils/utils.go
Normal file
@ -0,0 +1,232 @@
|
||||
/*
|
||||
* @desc:工具
|
||||
* @company:云南奇讯科技有限公司
|
||||
* @Author: yixiaohu
|
||||
* @Date: 2022/3/4 22:16
|
||||
*/
|
||||
|
||||
package libUtils
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/bwmarrin/snowflake"
|
||||
"github.com/gogf/gf/v2/crypto/gmd5"
|
||||
"github.com/gogf/gf/v2/encoding/gcharset"
|
||||
"github.com/gogf/gf/v2/encoding/gjson"
|
||||
"github.com/gogf/gf/v2/encoding/gurl"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
"github.com/samber/lo"
|
||||
"github.com/tiger1103/gfast/v3/internal/app/common/consts"
|
||||
"github.com/tiger1103/gfast/v3/internal/app/system/dao"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// EncryptPassword 密码加密
|
||||
func EncryptPassword(password, salt string) string {
|
||||
return gmd5.MustEncryptString(gmd5.MustEncryptString(password) + gmd5.MustEncryptString(salt))
|
||||
}
|
||||
|
||||
// GetDomain 获取当前请求接口域名
|
||||
func GetDomain(ctx context.Context) string {
|
||||
r := g.RequestFromCtx(ctx)
|
||||
pathInfo, err := gurl.ParseURL(r.GetUrl(), -1)
|
||||
if err != nil {
|
||||
g.Log().Error(ctx, err)
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf("%s://%s:%s/", pathInfo["scheme"], pathInfo["host"], pathInfo["port"])
|
||||
}
|
||||
|
||||
// GetClientIp 获取客户端IP
|
||||
func GetClientIp(ctx context.Context) string {
|
||||
return g.RequestFromCtx(ctx).GetClientIp()
|
||||
}
|
||||
|
||||
// GetUserAgent 获取user-agent
|
||||
func GetUserAgent(ctx context.Context) string {
|
||||
return ghttp.RequestFromCtx(ctx).Header.Get("User-Agent")
|
||||
}
|
||||
|
||||
// GetLocalIP 服务端ip
|
||||
func GetLocalIP() (ip string, err error) {
|
||||
var addrs []net.Addr
|
||||
addrs, err = net.InterfaceAddrs()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for _, addr := range addrs {
|
||||
ipAddr, ok := addr.(*net.IPNet)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if ipAddr.IP.IsLoopback() {
|
||||
continue
|
||||
}
|
||||
if !ipAddr.IP.IsGlobalUnicast() {
|
||||
continue
|
||||
}
|
||||
return ipAddr.IP.String(), nil
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetCityByIp 获取ip所属城市
|
||||
func GetCityByIp(ip string) string {
|
||||
if ip == "" {
|
||||
return ""
|
||||
}
|
||||
if ip == "::1" || ip == "127.0.0.1" {
|
||||
return "内网IP"
|
||||
}
|
||||
url := "http://whois.pconline.com.cn/ipJson.jsp?json=true&ip=" + ip
|
||||
bytes := g.Client().GetBytes(context.TODO(), url)
|
||||
src := string(bytes)
|
||||
srcCharset := "GBK"
|
||||
tmp, _ := gcharset.ToUTF8(srcCharset, src)
|
||||
json, err := gjson.DecodeToJson(tmp)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
if json.Get("code").Int() == 0 {
|
||||
city := fmt.Sprintf("%s %s", json.Get("pro").String(), json.Get("city").String())
|
||||
return city
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
// 写入文件
|
||||
func WriteToFile(fileName string, content string) error {
|
||||
f, err := os.OpenFile(fileName, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
n, _ := f.Seek(0, os.SEEK_END)
|
||||
_, err = f.WriteAt([]byte(content), n)
|
||||
defer f.Close()
|
||||
return err
|
||||
}
|
||||
|
||||
// 文件或文件夹是否存在
|
||||
func FileIsExisted(filename string) bool {
|
||||
existed := true
|
||||
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
||||
existed = false
|
||||
}
|
||||
return existed
|
||||
}
|
||||
|
||||
// 解析路径获取文件名称及后缀
|
||||
func ParseFilePath(pathStr string) (fileName string, fileType string) {
|
||||
fileNameWithSuffix := path.Base(pathStr)
|
||||
fileType = path.Ext(fileNameWithSuffix)
|
||||
fileName = strings.TrimSuffix(fileNameWithSuffix, fileType)
|
||||
return
|
||||
}
|
||||
|
||||
// IsNotExistMkDir 检查文件夹是否存在
|
||||
// 如果不存在则新建文件夹
|
||||
func IsNotExistMkDir(src string) error {
|
||||
if exist := !FileIsExisted(src); exist == false {
|
||||
if err := MkDir(src); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MkDir 新建文件夹
|
||||
func MkDir(src string) error {
|
||||
err := os.MkdirAll(src, os.ModePerm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 获取文件后缀
|
||||
func GetExt(fileName string) string {
|
||||
return path.Ext(fileName)
|
||||
}
|
||||
|
||||
// GetType 获取文件类型
|
||||
func GetType(p string) (result string, err error) {
|
||||
file, err := os.Open(p)
|
||||
if err != nil {
|
||||
g.Log().Error(context.TODO(), err)
|
||||
return
|
||||
}
|
||||
buff := make([]byte, 512)
|
||||
|
||||
_, err = file.Read(buff)
|
||||
|
||||
if err != nil {
|
||||
g.Log().Error(context.TODO(), err)
|
||||
return
|
||||
}
|
||||
filetype := http.DetectContentType(buff)
|
||||
return filetype, nil
|
||||
}
|
||||
|
||||
// GetFilesPath 获取附件相对路径
|
||||
func GetFilesPath(ctx context.Context, fileUrl string) (path string, err error) {
|
||||
upType := g.Cfg().MustGet(ctx, "upload.default").Int()
|
||||
if upType != 0 || (upType == 0 && !gstr.ContainsI(fileUrl, consts.UploadPath)) {
|
||||
path = fileUrl
|
||||
return
|
||||
}
|
||||
pathInfo, err := gurl.ParseURL(fileUrl, 32)
|
||||
if err != nil {
|
||||
g.Log().Error(ctx, err)
|
||||
err = gerror.New("解析附件路径失败")
|
||||
return
|
||||
}
|
||||
pos := gstr.PosI(pathInfo["path"], consts.UploadPath)
|
||||
if pos >= 0 {
|
||||
path = gstr.SubStr(pathInfo["path"], pos)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetFakeOpenID 生成 Fake OpenID
|
||||
func GetFakeOpenID() (string, error) {
|
||||
node, err := snowflake.NewNode(1)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// 生成一个 Fake OpenID
|
||||
openID := node.Generate().Base64()
|
||||
|
||||
// 保证生成的 OpenID 在 bus_construction_user 表中唯一
|
||||
_, err = lo.Attempt(3, func(_ int) error {
|
||||
exist, err := dao.BusConstructionUser.Ctx(context.Background()).Where(dao.BusConstructionUser.Columns().Openid, openID).Count()
|
||||
if err != nil {
|
||||
openID = node.Generate().Base64()
|
||||
return err
|
||||
}
|
||||
|
||||
if exist > 0 {
|
||||
openID = node.Generate().Base64()
|
||||
return errors.New("OpenID 已存在")
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return openID, nil
|
||||
}
|
Reference in New Issue
Block a user