Browse Source

应用管理,项目管理中系统管理员权限更新

huangyan 9 months ago
parent
commit
c36f258f05

+ 24 - 0
Makefile

@@ -0,0 +1,24 @@
+BINARY_NAME := project_management
+GOOS := linux
+GOARCH := amd64
+
+all: build
+# 运行
+run:
+	@echo "Running $(BINARY_NAME)..."
+	go run main.go
+# 编译为linux下的二进制文件
+build:
+	@echo "Cross-compiling for $(GOOS)/$(GOARCH)..."
+	go build -o $(BINARY_NAME)-$(GOOS)-$(GOARCH) -ldflags="-s -w" -tags netgo -a -installsuffix cgo -x -v -gcflags=all=-trimpath=$(GOPATH) -asmflags=all=-trimpath=$(GOPATH)
+# 安装必要的依赖
+deps:
+	@echo "Installing dependencies..."
+	go mod tidy
+	go mod download
+# 删除编译生成的文件
+clean:
+	@echo "Cleaning..."
+	del /Q $(BINARY_NAME)-*
+
+.PHONY: all build clean

+ 27 - 0
app/controller/admin/adminApply.go

@@ -0,0 +1,27 @@
+package admin
+
+import (
+	"github.com/gin-gonic/gin"
+	"project_management/app/e"
+	"project_management/app/model"
+	"project_management/unity"
+)
+
+// AdminApplyList 管理员获取所有应用列表
+func AdminApplyList(c *gin.Context) {
+	var params unity.QueryPageParams
+	if err := c.ShouldBindJSON(&params); err != nil {
+		e.ResponseWithMsg(c, e.JSONParsingFailed, e.JSONParsingFailed.GetMsg())
+		return
+	}
+	queryCond := "app_name like ?"
+	params.Query = "%" + params.Query + "%"
+	result, total, err := unity.PaginateWithCondition(params, model.Apply{}, queryCond)
+	if err != nil {
+		e.ResponseWithMsg(c, e.PaginationFailed, e.PaginationFailed.GetMsg())
+		return
+	} else {
+		e.ResPonsePage(c, result, total, params)
+		return
+	}
+}

+ 76 - 4
app/controller/appUser.go

@@ -2,10 +2,11 @@ package controller
 
 import (
 	"github.com/gin-gonic/gin"
-	"github.com/go-playground/validator/v10"
 	"project_management/app/e"
 	"project_management/app/model"
 	"project_management/app/services"
+	"project_management/unity"
+	"strconv"
 )
 
 var AppUser services.AppUser = &model.AppUser{}
@@ -36,11 +37,15 @@ func AddAppUser(c *gin.Context) {
 		e.ResponseWithMsg(c, e.JSONParsingFailed, e.JSONParsingFailed.GetMsg())
 		return
 	}
-	validate := validator.New()
-	if err := validate.Struct(appuser); err != nil {
+	//validate := validator.New()
+	err := unity.Validate.Struct(appuser)
+	if err != nil {
 		e.ResponseWithMsg(c, e.JSONParsingFailed, err.Error())
-		return
 	}
+	//if err := validate.Struct(appuser); err != nil {
+	//	e.ResponseWithMsg(c, e.JSONParsingFailed, err.Error())
+	//	return
+	//}
 	user := AppUser.AddAppUser(appuser)
 	if user == e.SUCCESS {
 		e.ResponseWithMsg(c, e.SUCCESS, e.SUCCESS.GetMsg())
@@ -49,6 +54,73 @@ func AddAppUser(c *gin.Context) {
 	e.ResponseWithMsg(c, user, user.GetMsg())
 }
 
+// GetAppUserList 获取用户列表
 func GetAppUserList(c *gin.Context) {
+	var params unity.QueryPageParams
+	if err := c.ShouldBindJSON(&params); err != nil {
+		e.ResponseWithMsg(c, e.JSONParsingFailed, e.JSONParsingFailed.GetMsg())
+		return
+	}
+	app_id := c.Query("app_id")
+	err := unity.Validate.Var(app_id, "required")
+	if err != nil {
+		e.ResponseWithMsg(c, e.JSONParsingFailed, "缺少appid")
+		return
+	}
+	tableName := "appuser_" + app_id
+	queryCond := "username like ?"
+	params.Query = "%" + params.Query + "%"
+	result, total, err := AppUser.GetAppUserList(params, tableName, queryCond)
+	if err != nil {
+		e.ResponseWithMsg(c, e.PaginationFailed, e.PaginationFailed.GetMsg())
+		return
+	}
+	e.ResPonsePage(c, result, total, params)
+}
+
+// UpdateAppUser 更新用户信息
+func UpdateAppUser(c *gin.Context) {
+	var appuser model.AppUser
+	if err := c.ShouldBindJSON(&appuser); err != nil {
+		e.ResponseWithMsg(c, e.JSONParsingFailed, e.JSONParsingFailed.GetMsg())
+		return
+	}
+	app_id := c.Query("app_id")
+	if err := unity.Validate.Var(app_id, "required"); err != nil {
+		e.ResponseWithMsg(c, e.JSONParsingFailed, "缺少appid")
+		return
+	}
+	tablename := "appuser_" + app_id
+	user := AppUser.UpdateAppUser(appuser, tablename)
+	if user == e.SUCCESS {
+		e.ResponseSuccess(c, "")
+		return
+	}
+	e.ResponseWithMsg(c, user, user.GetMsg())
+}
 
+// DeleteAppUserByID 删除用户
+func DeleteAppUserByID(c *gin.Context) {
+	id := c.PostForm("id")
+	app_id := c.PostForm("app_id")
+	if err := unity.Validate.Var(id, "required"); err != nil {
+		e.ResponseWithMsg(c, e.JSONParsingFailed, "缺少id")
+		return
+	}
+	if err := unity.Validate.Var(app_id, "required"); err != nil {
+		e.ResponseWithMsg(c, e.JSONParsingFailed, "缺少appid")
+		return
+	}
+	tablename := "appuser_" + app_id
+	atoi, err := strconv.Atoi(id)
+	if err != nil {
+		e.ResponseWithMsg(c, e.JSONParsingFailed, "id格式错误")
+		return
+	}
+	byID := AppUser.DeleteAppUserByID(atoi, tablename)
+	if byID == e.SUCCESS {
+		e.ResponseSuccess(c, "")
+		return
+	}
+	e.ResponseWithMsg(c, byID, byID.GetMsg())
 }

+ 21 - 21
app/controller/apply.go

@@ -21,7 +21,7 @@ func GetApplyList(c *gin.Context) {
 	}
 	queryCond := "app_name like ?"
 	params.Query = "%" + params.Query + "%"
-	uId, _ := unity.GetUId(c)
+	uId, _, _ := unity.GetUId(c)
 	apply.UserId = uId
 	result, total, err := Apply.GetApplyList(params, apply, queryCond)
 	if err != nil {
@@ -37,34 +37,25 @@ func GetApplyList(c *gin.Context) {
 func GetApplyState(c *gin.Context) {
 	var params unity.QueryPageParams
 	var apply model.Apply
+	_, _, role := unity.GetUId(c)
 	if err := c.ShouldBindJSON(&params); err != nil {
 		e.ResponseWithMsg(c, e.JSONParsingFailed, e.JSONParsingFailed.GetMsg())
 		return
 	}
 	queryCond := "app_name like ?"
 	params.Query = "%" + params.Query + "%"
-	uId, _ := unity.GetUId(c)
+	uId, _, _ := unity.GetUId(c)
 	apply.UserId = uId
-	result, total, err := Apply.GetApplyList(params, apply, queryCond)
-	if err != nil {
-		e.ResponseWithMsg(c, e.PaginationFailed, e.PaginationFailed.GetMsg())
-		return
-	} else {
+	if role == "admin" {
+		result, total, err := Apply.GetApplyAminList(params, apply, queryCond)
+		if err != nil {
+			e.ResponseWithMsg(c, e.PaginationFailed, e.PaginationFailed.GetMsg())
+			return
+		}
 		e.ResPonsePage(c, result, total, params)
 		return
 	}
-}
-
-// AdminApplyList 管理员获取所有应用列表
-func AdminApplyList(c *gin.Context) {
-	var params unity.QueryPageParams
-	if err := c.ShouldBindJSON(&params); err != nil {
-		e.ResponseWithMsg(c, e.JSONParsingFailed, e.JSONParsingFailed.GetMsg())
-		return
-	}
-	queryCond := "app_name like ?"
-	params.Query = "%" + params.Query + "%"
-	result, total, err := unity.PaginateWithCondition(params, model.Apply{}, queryCond)
+	result, total, err := Apply.GetApplyList(params, apply, queryCond)
 	if err != nil {
 		e.ResponseWithMsg(c, e.PaginationFailed, e.PaginationFailed.GetMsg())
 		return
@@ -92,7 +83,7 @@ func AddApply(c *gin.Context) {
 		id = unity.RandomAppID()
 	}
 	//获取当前用户ID
-	uId, username := unity.GetUId(c)
+	uId, username, _ := unity.GetUId(c)
 	apply.UserId = uId
 	apply.AppID = id
 	apply.UserName = username
@@ -112,7 +103,16 @@ func UserUpdateApply(c *gin.Context) {
 		e.ResponseWithMsg(c, e.JSONParsingFailed, e.JSONParsingFailed.GetMsg())
 		return
 	}
-	id, _ := unity.GetUId(c)
+	id, _, role := unity.GetUId(c)
+	if role == "admin" {
+		byId, err := unity.UpdateById(apply.ID, apply)
+		if err != nil {
+			e.ResponseWithMsg(c, e.UPDATEFAIL, e.UPDATEFAIL.GetMsg())
+			return
+		}
+		e.ResponseSuccess(c, byId)
+		return
+	}
 	apply.UserId = id
 	updateApply := Apply.UserUpdateApply(apply)
 	if updateApply != e.SUCCESS {

+ 13 - 0
app/controller/qiniu.go

@@ -0,0 +1,13 @@
+package controller
+
+import (
+	"github.com/gin-gonic/gin"
+	"project_management/app/e"
+	"project_management/utils"
+)
+
+func GetQiniuToken(c *gin.Context) {
+	T_suffix := c.Query("T_suffix")
+	token := utils.GetToken(T_suffix)
+	e.ResponseSuccess(c, token)
+}

+ 58 - 8
app/model/appUser.go

@@ -6,21 +6,23 @@ import (
 	"project_management/global"
 	"project_management/unity"
 	"project_management/utils"
+	"strings"
 	"time"
 )
 
 type AppUser struct {
 	//gorm.Model
 	utils.BaseModel
-	Username      string `gorm:"type:varchar(50);index:username_name,unique" json:"username" validate:"required" min:"3" max:"50"` // 用户名
-	Phone         string `gorm:"type:varchar(50);" json:"phone" min:"11" max:"11"`                                                 // 手机号
-	Nickname      string `gorm:"type:varchar(50);" json:"nickname"`                                                                // 昵称
-	Password      string `gorm:"type:varchar(50);" json:"password" validate:"required"`                                            // 密码
-	LastLoginTime string `gorm:"type:datetime;" json:"last_login_time"`                                                            // 最后登录时间
-	State         int    `gorm:"type:int;" json:"state"`                                                                           // 状态 0:正常 1:禁用
-	AppID         string `gorm:"type:varchar(50);" json:"app_id" validate:"required"`                                              // 应用id
-	RegistMethod  int    `gorm:"type:int;" json:"regist_method"`                                                                   // 注册方式 1 短信登录 2 微信登录 3 系统添加
+	Username      string `gorm:"type:varchar(50);index:username_name,unique" json:"username" min:"3" max:"50"` // 用户名
+	Phone         string `gorm:"type:varchar(50);" json:"phone" min:"11" max:"11"`                             // 手机号
+	Nickname      string `gorm:"type:varchar(50);" json:"nickname"`                                            // 昵称
+	Password      string `gorm:"type:varchar(50);" json:"password"`                                            // 密码
+	LastLoginTime string `gorm:"type:datetime;" json:"last_login_time"`                                        // 最后登录时间
+	State         int    `gorm:"type:int;" json:"state"`                                                       // 状态 0:正常 1:禁用
+	AppID         string `gorm:"type:varchar(50);" json:"app_id" `                                             // 应用id
+	RegistMethod  int    `gorm:"type:int;" json:"regist_method"`                                               // 注册方式 1 短信登录 2 微信登录 3 系统添加
 }
+
 type AppUserRegist struct {
 	Username     string `gorm:"type:varchar(50);index:username_name,unique" json:"username" validate:"required" min:"3" max:"50"` // 用户名
 	Phone        string `gorm:"type:varchar(50);" json:"phone" validate:"required" min:"11" max:"11"`                             // 手机号
@@ -31,6 +33,41 @@ type AppUserRegist struct {
 	RegistMethod int    `gorm:"type:int;" json:"regist_method"`                                                                   // 注册方式 1 短信登录 2 微信登录 3 系统添加
 }
 
+func (a AppUser) DeleteAppUserByID(id int, tableName string) e.Rescode {
+	//TODO implement me
+	tx := global.DBLink.Table(tableName).Where("id=?", id).Delete(&a)
+	if tx.Error != nil {
+		return e.DELETEFAIL
+	}
+	return e.SUCCESS
+}
+func (a AppUser) UpdateAppUser(appUser AppUser, tabaleName string) e.Rescode {
+	//TODO implement me
+	tx := global.DBLink.Table(tabaleName).Updates(appUser)
+	if tx.Error != nil {
+		return e.UPDATEFAIL
+	}
+	return e.SUCCESS
+}
+
+func (a AppUser) GetAppUserList(params unity.QueryPageParams, tableName string, queryCond string) (result []AppUser, total int64, err error) {
+	query := global.DBLink.Table(tableName)
+	if params.Query != "%%" {
+		query = query.Where(queryCond, params.Query)
+	}
+	if params.State != "" {
+		query = query.Where("state=?", params.State)
+	}
+	if err = query.Count(&total).Error; err != nil {
+		return nil, 0, err
+	}
+	offset := (params.Page - 1) * params.Size
+	if err = query.Offset(offset).Limit(params.Size).Order(params.Desc).Find(&result).Error; err != nil {
+		return nil, 0, err
+	}
+	return result, total, nil
+}
+
 // RegistAppUser 注册用户
 func (a AppUser) RegistAppUser(appUser AppUserRegist) e.Rescode {
 	//TODO implement me
@@ -84,7 +121,20 @@ func (a AppUser) AddAppUser(appUser AppUser) e.Rescode {
 	a.LastLoginTime = time.Now().Format("2006-01-02 15:04:05")
 	a.RegistMethod = 3
 	if err := global.DBLink.Table(tableName).Create(&a).Error; err != nil {
+		if strings.Contains(err.Error(), "Duplicate entry") {
+			return e.TheUserAlreadyExists
+		}
 		return e.AddAppUserFail
 	}
 	return e.SUCCESS
 }
+
+// GetAllUserCount 获取用户总数
+func GetAllUserCount(tableName string) (e.Rescode, int64) {
+	var count int64
+	tx := global.DBLink.Table(tableName).Count(&count)
+	if tx.Error != nil {
+		return e.ERROR, 0
+	}
+	return e.SUCCESS, count
+}

+ 38 - 3
app/model/apply.go

@@ -20,13 +20,50 @@ type Apply struct {
 	CertificationTime      utils.Time `gorm:"type:datetime;" json:"certification_time"`                                                    // 认证到期时间
 	State                  int        `gorm:"type:int;" json:"state"`                                                                      // 状态 1 正常 2 停用 3 过期 4 禁用
 	Icon                   string     `gorm:"type:varchar(50);" json:"icon"`                                                               // 应用图标
-	StartupDiagram         string     `gorm:"type:varchar(50);" json:"startup_diagram"`                                                    // 启动图
+	StartupDiagramPc       string     `gorm:"type:varchar(50);" json:"startup_diagram_pc"`                                                 // 启动图pc
+	StartupDiagramMobile   string     `gorm:"type:varchar(50);" json:"startup_diagram_mobile"`                                             // 启动图移动
 	LoginMode              int        `gorm:"type:int;" json:"login_mode"`                                                                 // 登录模式 1 公开注册 2禁止注册
 	LoginMethod            int        `gorm:"type:int;" json:"login_method"`                                                               // 登录方式 1 短信登录 2 微信登录
 	BackgroundImage        string     `gorm:"type:varchar(50);" json:"background_image"`                                                   // 背景图
 	BackgroundImageObscure int        `gorm:"type:int;" json:"background_image_obscure"`                                                   // 背景图模糊度
 }
 
+type AppDto struct {
+	Apply
+	AppUserCount int64 `json:"app_user_count"`
+}
+
+func (a Apply) GetApplyAminList(params unity.QueryPageParams, apply Apply, queryCond string) (result []AppDto, total int64, err error) {
+	//TODO implement me
+	query := global.DBLink.Table(apply.TableName())
+	if params.Query != "%%" {
+		query = query.Where(queryCond, params.Query)
+	}
+	if params.State != "" {
+		query = query.Where("state=?", params.State)
+	}
+	if err = query.Count(&total).Error; err != nil {
+		return nil, 0, err
+	}
+	offset := (params.Page - 1) * params.Size
+	if err = query.Offset(offset).Limit(params.Size).Order(params.Desc).Find(&result).Error; err != nil {
+		return nil, 0, err
+	}
+	for i, _ := range result {
+		tableName := "appuser_" + result[i].AppID
+		recode, count := GetAllUserCount(tableName)
+		if recode == e.SUCCESS {
+			result[i].AppUserCount = count
+		} else {
+			result[i].AppUserCount = 0
+		}
+	}
+	return result, total, nil
+}
+
+func (a Apply) TableName() string {
+	return "applies"
+}
 func (a Apply) QueryApplyByAppName(appName string) ([]Apply, error) {
 	//TODO implement me
 	var app []Apply
@@ -43,9 +80,7 @@ func (a Apply) QueryApplyByAppName(appName string) ([]Apply, error) {
 func (a Apply) GetApplyById(appid string) (Apply, error) {
 	//TODO implement me
 	tx := global.DBLink.
-		Select("app_name", "icon", "app_description", "app_id", "user_name").
 		Where("app_id=?", appid).
-		Where("state=?", 1).
 		First(&a)
 	if tx.Error != nil {
 		return Apply{}, tx.Error

+ 5 - 2
app/router.go

@@ -10,13 +10,16 @@ import (
 func InitRouter() error {
 	engine := gin.New()
 	engine.Use(middlewares.Cors())
+	routers.QiniuRouter(engine)
 	routers.UserRouter(engine)
-	//外部用户登录
+	//第三方用户登录
 	engine.Use(middlewares.LogonMiddeware())
 	routers.AppUserRouter(engine)
 	routers.ApplyNotLogin(engine)
-	//管理员登录
+	//用户登录
 	engine.Use(middlewares.LoginMiddleware())
 	routers.ApplyRouter(engine)
+	//系统管理员
+
 	return engine.Run(global.ServerSetting.Port)
 }

+ 3 - 1
app/routers/appUser.go

@@ -9,5 +9,7 @@ func AppUserRouter(r *gin.Engine) {
 	group := r.Group("/api")
 	group.POST("/regist", controller.RegistApply)
 	group.POST("/appuser", controller.AddAppUser)
-
+	group.POST("/appuserlist", controller.GetAppUserList)
+	group.PUT("/appuser", controller.UpdateAppUser)
+	group.DELETE("/appuser", controller.DeleteAppUserByID)
 }

+ 1 - 0
app/routers/apply.go

@@ -11,4 +11,5 @@ func ApplyRouter(r *gin.Engine) {
 	group.POST("/applyall", controller.GetApplyList)
 	group.POST("/applystate", controller.GetApplyState)
 	group.PUT("/apply", controller.UserUpdateApply)
+	group.GET("/apply", controller.GetApplyByAPPID)
 }

+ 1 - 1
app/routers/applynotlogin.go

@@ -8,5 +8,5 @@ import (
 func ApplyNotLogin(r *gin.Engine) {
 	group := r.Group("/api")
 	group.GET("/applyname", controller.GetApplyByName)
-	group.GET("/apply", controller.GetApplyByAPPID)
+
 }

+ 11 - 0
app/routers/qiniu.go

@@ -0,0 +1,11 @@
+package routers
+
+import (
+	"github.com/gin-gonic/gin"
+	"project_management/app/controller"
+)
+
+func QiniuRouter(r *gin.Engine) {
+	group := r.Group("/api")
+	group.GET("/qiniu/token", controller.GetQiniuToken)
+}

+ 4 - 0
app/services/appUser.go

@@ -3,9 +3,13 @@ package services
 import (
 	"project_management/app/e"
 	"project_management/app/model"
+	"project_management/unity"
 )
 
 type AppUser interface {
 	AddAppUser(appUser model.AppUser) e.Rescode
 	RegistAppUser(appUser model.AppUserRegist) e.Rescode
+	GetAppUserList(params unity.QueryPageParams, tableName string, queryCond string) (result []model.AppUser, total int64, err error)
+	UpdateAppUser(appUser model.AppUser, tabaleName string) e.Rescode
+	DeleteAppUserByID(id int, tableName string) e.Rescode
 }

+ 1 - 0
app/services/apply.go

@@ -12,4 +12,5 @@ type Apply interface {
 	UserUpdateApply(apply model.Apply) e.Rescode
 	GetApplyById(appid string) (model.Apply, error)
 	QueryApplyByAppName(appName string) ([]model.Apply, error)
+	GetApplyAminList(params unity.QueryPageParams, apply model.Apply, queryCond string) (result []model.AppDto, total int64, err error)
 }

+ 7 - 2
configs/config.yaml

@@ -35,11 +35,16 @@ subMail:
   appid: "97173"
   signature: "f639a60e41ee0554921d89884f5ff87e"
 redis:
-  addr: "192.168.1.16:6379"
+  addr: "192.168.11.33:6379"
   password: ""
   db: 0
 nats:
   NatsServer_Url: "nats://127.0.0.0:4222"
 swag:
   # 将环境变量 NAME_OF_ENV_VARIABLE设置为任意值,则 /swagger/*any 返回404响应
-  enable: "NAME_OF_ENV_VARIABLE"
+  enable: "NAME_OF_ENV_VARIABLE"
+qiniu:
+  endpoint: "https://bzdcdn.baozhida.cn/"
+  accessKeyID: "-8ezB_d-8-eUFTMvhOGbGzgeQRPeKQnaQ3DBcUxo"
+  accessKeySecret: "KFhkYxTAJ2ZPN3ZS3euTsfWk8-C92rKgkhAMkDRN"
+  bucketName: "bzdcdn"

+ 10 - 0
global/setting.go

@@ -49,6 +49,14 @@ type Swagger struct {
 	Enable string `json:"enable"`
 }
 
+// Qiniu qiniu
+type Qiniu struct {
+	AccessKeyID     string `json:"accessKeyID"`
+	Endpoint        string `json:"endpoint"`
+	AccessKeySecret string `json:"accessKeySecret"`
+	BucketName      string `json:"bucketName"`
+}
+
 var (
 	DatabaseSetting *DatabaseSettingS
 	NatsSetting     *Nats
@@ -57,6 +65,7 @@ var (
 	SubMailSetting  *SubMail
 	RedisSetting    *Redis
 	SwaggerSetting  *Swagger
+	QiniuSetting    *Qiniu
 )
 
 // SetupSetting 读取配置到全局变量
@@ -69,6 +78,7 @@ func SetupSetting() error {
 	err = s.ReadSection("SubMail", &SubMailSetting)
 	err = s.ReadSection("Redis", &RedisSetting)
 	err = s.ReadSection("Swagger", &SwaggerSetting)
+	err = s.ReadSection("Qiniu", &QiniuSetting)
 	if err != nil {
 		return err
 	}

+ 8 - 2
go.mod

@@ -9,7 +9,10 @@ require (
 	github.com/go-playground/universal-translator v0.18.1
 	github.com/go-playground/validator/v10 v10.22.0
 	github.com/go-redis/redis/v8 v8.11.5
+	github.com/go-resty/resty/v2 v2.13.1
+	github.com/golang-jwt/jwt/v4 v4.5.0
 	github.com/nats-io/nats.go v1.36.0
+	github.com/qiniu/go-sdk/v7 v7.21.1
 	github.com/spf13/viper v1.19.0
 	go.uber.org/zap v1.27.0
 	gopkg.in/natefinch/lumberjack.v2 v2.2.1
@@ -18,6 +21,8 @@ require (
 )
 
 require (
+	github.com/BurntSushi/toml v1.3.2 // indirect
+	github.com/alex-ant/gomath v0.0.0-20160516115720-89013a210a82 // indirect
 	github.com/bytedance/sonic/loader v0.1.1 // indirect
 	github.com/cespare/xxhash/v2 v2.1.2 // indirect
 	github.com/cloudwego/base64x v0.1.4 // indirect
@@ -26,10 +31,9 @@ require (
 	github.com/fsnotify/fsnotify v1.7.0 // indirect
 	github.com/gabriel-vasile/mimetype v1.4.3 // indirect
 	github.com/gin-contrib/sse v0.1.0 // indirect
-	github.com/go-resty/resty/v2 v2.13.1 // indirect
 	github.com/go-sql-driver/mysql v1.7.0 // indirect
 	github.com/goccy/go-json v0.10.2 // indirect
-	github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
+	github.com/gofrs/flock v0.8.1 // indirect
 	github.com/google/uuid v1.6.0 // indirect
 	github.com/hashicorp/hcl v1.0.0 // indirect
 	github.com/jinzhu/inflection v1.0.0 // indirect
@@ -39,6 +43,7 @@ require (
 	github.com/klauspost/cpuid/v2 v2.2.7 // indirect
 	github.com/leodido/go-urn v1.4.0 // indirect
 	github.com/magiconair/properties v1.8.7 // indirect
+	github.com/matishsiao/goInfo v0.0.0-20210923090445-da2e3fa8d45f // indirect
 	github.com/mattn/go-isatty v0.0.20 // indirect
 	github.com/mitchellh/mapstructure v1.5.0 // indirect
 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
@@ -60,6 +65,7 @@ require (
 	golang.org/x/crypto v0.23.0 // indirect
 	golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
 	golang.org/x/net v0.25.0 // indirect
+	golang.org/x/sync v0.6.0 // indirect
 	golang.org/x/sys v0.20.0 // indirect
 	golang.org/x/text v0.15.0 // indirect
 	google.golang.org/protobuf v1.34.1 // indirect

+ 49 - 2
go.sum

@@ -1,3 +1,7 @@
+github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
+github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
+github.com/alex-ant/gomath v0.0.0-20160516115720-89013a210a82 h1:7dONQ3WNZ1zy960TmkxJPuwoolZwL7xKtpcM04MBnt4=
+github.com/alex-ant/gomath v0.0.0-20160516115720-89013a210a82/go.mod h1:nLnM0KdK1CmygvjpDUO6m1TjSsiQtL61juhNsvV/JVI=
 github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
 github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
 github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
@@ -8,6 +12,8 @@ github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/
 github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
 github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
 github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
+github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/dave/jennifer v1.6.1/go.mod h1:nXbxhEmQfOZhWml3D1cDK5M1FLnMSozpbFN/m3RmGZc=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
@@ -24,12 +30,18 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE
 github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
 github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
 github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
+github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
 github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
 github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
+github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
+github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
 github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
 github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
+github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
+github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
 github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
 github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
+github.com/go-playground/validator/v10 v10.8.0/go.mod h1:9JhgTzTaE31GZDpH/HSvHiRJrJ3iKAgqqH0Bl/Ocjdk=
 github.com/go-playground/validator/v10 v10.22.0 h1:k6HsTZ0sTnROkhS//R0O+55JgM8C4Bx7ia+JlgcnOao=
 github.com/go-playground/validator/v10 v10.22.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
 github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
@@ -40,6 +52,8 @@ github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ
 github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
 github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
 github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
+github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
+github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
 github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
 github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
 github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
@@ -49,6 +63,7 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
 github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
 github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
+github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
 github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
 github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
 github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
@@ -61,14 +76,22 @@ github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02
 github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
 github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
 github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
 github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
 github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
 github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
 github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
 github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
 github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
+github.com/matishsiao/goInfo v0.0.0-20210923090445-da2e3fa8d45f h1:B0OD7nYl2FPQEVrw8g2uyc1lGEzNbvrKh7fspGZcbvY=
+github.com/matishsiao/goInfo v0.0.0-20210923090445-da2e3fa8d45f/go.mod h1:aEt7p9Rvh67BYApmZwNDPpgircTO2kgdmDUoF/1QmwA=
 github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
 github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
 github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
@@ -92,9 +115,16 @@ github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
 github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
 github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
 github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
+github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/qiniu/dyn v1.3.0/go.mod h1:E8oERcm8TtwJiZvkQPbcAh0RL8jO1G0VXJMW3FAWdkk=
+github.com/qiniu/go-sdk/v7 v7.21.1 h1:D/IjVOlg5pTw0jeDjqTo6H5QM73Obb1AYfPOHmIFN+Q=
+github.com/qiniu/go-sdk/v7 v7.21.1/go.mod h1:8EM2awITynlem2VML2dXGHkMYP2UyECsGLOdp6yMpco=
+github.com/qiniu/x v1.10.5/go.mod h1:03Ni9tj+N2h2aKnAz+6N0Xfl8FwMEDRC2PAlxekASDs=
+github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
+github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
 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/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
@@ -116,6 +146,7 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS
 github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
 github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
@@ -140,7 +171,9 @@ golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUu
 golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
 golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
 golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
 golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
 golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
@@ -151,6 +184,7 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
+golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
 golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
 golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
 golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
@@ -159,31 +193,41 @@ golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
+golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
 golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
 golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
 golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
 golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
 golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
 golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
 golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
 golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
 golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
 golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@@ -193,8 +237,10 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
 google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
 google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
-gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/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-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
 gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
 gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
 gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
@@ -204,6 +250,7 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD
 gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
 gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo=

+ 4 - 4
main.go

@@ -7,7 +7,6 @@ import (
 	"project_management/global"
 	"project_management/nats"
 	"project_management/simple_zap"
-	"project_management/unity"
 )
 
 func init() {
@@ -22,9 +21,10 @@ func init() {
 	// 数据库迁移
 	database.Migrate(global.DBLink)
 	//本地化
-	if err = unity.Translator("zh"); err != nil {
-		simple_zap.WithCtx(context.Background()).Sugar().Warn(err, "注册本地化失败")
-	}
+	//err = unity.InitializeValidator("zh")
+	//if err != nil {
+	//	simple_zap.WithCtx(context.Background()).Sugar().Warn(err, "本地化失败")
+	//}
 	//nats
 	nats.SetupNats()
 	//redis

+ 6 - 6
unity/getuid.go

@@ -4,14 +4,14 @@ import (
 	"github.com/gin-gonic/gin"
 )
 
-func GetUId(c *gin.Context) (int, string) {
-	//mustGet := c.MustGet("user")
+func GetUId(c *gin.Context) (id int, name, role string) {
 	value, exists := c.Get("user")
 	if exists {
 		users := value.(map[string]interface{})
-		id := int(users["ID"].(float64))
-		name := users["username"].(string)
-		return id, name
+		id = int(users["ID"].(float64))
+		name = users["username"].(string)
+		role = users["role"].(string)
+		return id, name, role
 	}
-	return 0, ""
+	return 0, "", ""
 }

+ 18 - 1
unity/unity.go

@@ -81,7 +81,7 @@ func GetById[T any](id int, model T) (T, error) {
 }
 
 // UpdateById 根据id进行修改
-func UpdateById[T any](id int, model T) (T, error) {
+func UpdateById[T any](id uint, model T) (T, error) {
 	tx := global.DBLink.Where("id = ?", id).Updates(&model)
 	if tx.RowsAffected > 0 {
 		return model, nil
@@ -119,3 +119,20 @@ func QueryAll(table string) ([]any, error) {
 	}
 	return result, nil
 }
+func GetListALL[T any](params QueryPageParams, tableName string, queryCond string, model T) (result []T, total int64, err error) {
+	query := global.DBLink.Table(tableName)
+	if params.Query != "%%" {
+		query = query.Where(queryCond, params.Query)
+	}
+	if params.State != "" {
+		query = query.Where("state=?", params.State)
+	}
+	if err = query.Count(&total).Error; err != nil {
+		return nil, 0, err
+	}
+	offset := (params.Page - 1) * params.Size
+	if err = query.Offset(offset).Limit(params.Size).Order(params.Desc).Find(&result).Error; err != nil {
+		return nil, 0, err
+	}
+	return result, total, nil
+}

+ 42 - 37
unity/zh_cn.go

@@ -11,47 +11,52 @@ import (
 	zhTranslations "github.com/go-playground/validator/v10/translations/zh"
 )
 
-var Trans ut.Translator // 声明一个全局的Translator变量
+var Validate *validator.Validate // 声明一个全局的validator.Validate实例
+var Trans ut.Translator          // 声明一个全局的Translator变量
 
-// Translator 是一个用于设置验证器本地化翻译的函数
-func Translator(local string) error {
-	// 验证并获取Validator引擎实例
-	if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
-		// 初始化英语和中文翻译器
-		zhT := zh.New()
-		enT := en.New()
-
-		// 创建一个通用翻译器实例,传入多个翻译器(这里是英语和中文)
-		uni := ut.New(enT, zhT, enT)
-
-		// 尝试从通用翻译器中获取指定语言的翻译器
-		var found bool
-		Trans, found = uni.GetTranslator(local)
-		if !found {
-			return fmt.Errorf("failed to find translator for %s", local)
-		}
+// InitializeValidator 初始化全局验证器并注册翻译器
+func InitializeValidator(local string) error {
+	Validate = validator.New()
+
+	// 初始化英语和中文翻译器
+	zhT := zh.New()
+	enT := en.New()
+
+	// 创建一个通用翻译器实例,传入多个翻译器
+	uni := ut.New(enT, zhT, enT)
+
+	// 尝试从通用翻译器中获取指定语言的翻译器
+	var found bool
+	Trans, found = uni.GetTranslator(local)
+	if !found {
+		return fmt.Errorf("failed to find translator for %s", local)
+	}
 
-		// 根据本地化语言注册相应的翻译器到验证器中
-		switch local {
-		case "en":
-			err := enTranslations.RegisterDefaultTranslations(v, Trans)
-			if err != nil {
-				return err
-			}
-		case "zh":
-			err := zhTranslations.RegisterDefaultTranslations(v, Trans)
-			if err != nil {
-				return err
-			}
-		default:
-			// 如果指定了不受支持的语言,默认使用英文
-			err := enTranslations.RegisterDefaultTranslations(v, Trans)
-			if err != nil {
-				return err
-			}
+	// 注册翻译到验证器
+	switch local {
+	case "en":
+		err := enTranslations.RegisterDefaultTranslations(Validate, Trans)
+		if err != nil {
+			return err
 		}
+	case "zh":
+		err := zhTranslations.RegisterDefaultTranslations(Validate, Trans)
+		if err != nil {
+			return err
+		}
+	default:
+		err := enTranslations.RegisterDefaultTranslations(Validate, Trans)
+		if err != nil {
+			return err
+		}
+	}
+
+	// 如果您使用 Gin,并想替换 Gin 的默认验证器引擎,请执行以下操作
+	if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
+		*v = *Validate
 	} else {
-		return fmt.Errorf("validator engine not found")
+		return fmt.Errorf("failed to replace Gin's default validator engine")
 	}
+
 	return nil
 }

+ 69 - 0
utils/qiniu.go

@@ -0,0 +1,69 @@
+package utils
+
+import (
+	"fmt"
+	"github.com/google/uuid"
+	"github.com/qiniu/go-sdk/v7/auth/qbox"
+	"github.com/qiniu/go-sdk/v7/storage"
+	"log"
+	"project_management/global"
+	"strconv"
+	"time"
+)
+
+// GetToken 获取上传凭证
+func GetToken(T_suffix string) string {
+	mac := qbox.NewMac(global.QiniuSetting.AccessKeyID, global.QiniuSetting.AccessKeySecret)
+	Tokey := strconv.FormatInt(time.Now().Unix(), 10) + uuid.NewString()
+	if len(T_suffix) == 0 {
+		T_suffix = "png"
+	}
+	// 构建表单上传的对象
+	putPolicy := storage.PutPolicy{
+		Scope:        global.QiniuSetting.BucketName,
+		Expires:      7200,
+		InsertOnly:   1,
+		ForceSaveKey: true,
+		ReturnBody:   `{"key":"` + global.QiniuSetting.Endpoint + `/$(key)","hash":"$(etag)","fsize":$(fsize),"bucket":"$(bucket)"}`, SaveKey: "UpImage/" + Tokey + "." + T_suffix,
+		MimeLimit:  "image/*;application/pdf;application/octet-stream;application/zip;application/x-tar",
+		FsizeLimit: 1024 * 1024 * 100,
+	}
+	upToken := putPolicy.UploadToken(mac)
+	return upToken
+}
+
+// DeleteFiles 删除文件
+func DeleteFiles(accessKey, secretKey, bucket string, files []string) {
+	cfg := storage.Config{
+		Zone: &storage.ZoneHuanan,
+	}
+	bucketManager := storage.NewBucketManager(qbox.NewMac(accessKey, secretKey), &cfg)
+	ops := make([]string, len(files))
+	for i, file := range files {
+		ops[i] = storage.URIDelete(bucket, file)
+	}
+	_, err := bucketManager.Batch(ops)
+	if err != nil {
+		log.Fatal("Batch delete failed:", err)
+	}
+	fmt.Println("Files deleted successfully.")
+}
+
+// GetFileInfo 获取文件信息
+func GetFileInfo(accessKey, secretKey, bucket string, files []string) map[string]storage.FileInfo {
+	mac := qbox.NewMac(accessKey, secretKey)
+	cfg := storage.Config{
+		Zone: &storage.ZoneHuadong,
+	}
+	bucketManager := storage.NewBucketManager(mac, &cfg)
+	fileInfoMap := make(map[string]storage.FileInfo)
+	for _, file := range files {
+		fileInfo, err := bucketManager.Stat(bucket, file)
+		if err != nil {
+			log.Println("Get file info failed:", err)
+		} else {
+			fileInfoMap[file] = fileInfo
+		}
+	}
+	return fileInfoMap
+}