refactor: validator调整

This commit is contained in:
meilin.huang
2023-08-04 12:22:21 +08:00
parent c2ee4f9955
commit 3ae7e0de75
9 changed files with 156 additions and 54 deletions

View File

@@ -104,7 +104,6 @@ function buildMac() {
function buildDocker() { function buildDocker() {
echo_yellow "-------------------构建docker镜像开始-------------------" echo_yellow "-------------------构建docker镜像开始-------------------"
imageVersion=$1 imageVersion=$1
cd ${server_folder}
imageName="mayflygo/mayfly-go:${imageVersion}" imageName="mayflygo/mayfly-go:${imageVersion}"
docker build --platform linux/amd64 -t "${imageName}" . docker build --platform linux/amd64 -t "${imageName}" .
echo_green "docker镜像构建完成->[${imageName}]" echo_green "docker镜像构建完成->[${imageName}]"
@@ -114,7 +113,6 @@ function buildDocker() {
function buildxDocker() { function buildxDocker() {
echo_yellow "-------------------docker buildx构建镜像开始-------------------" echo_yellow "-------------------docker buildx构建镜像开始-------------------"
imageVersion=$1 imageVersion=$1
cd ${server_folder}
imageName="ccr.ccs.tencentyun.com/mayfly/mayfly-go:${imageVersion}" imageName="ccr.ccs.tencentyun.com/mayfly/mayfly-go:${imageVersion}"
docker buildx build --push --platform linux/amd64,linux/arm64 -t "${imageName}" . docker buildx build --push --platform linux/amd64,linux/arm64 -t "${imageName}" .
echo_green "docker多版本镜像构建完成->[${imageName}]" echo_green "docker多版本镜像构建完成->[${imageName}]"
@@ -147,6 +145,11 @@ function runBuild() {
# 进入目标路径,并赋值全路径 # 进入目标路径,并赋值全路径
cd ${toPath} cd ${toPath}
toPath=`pwd` toPath=`pwd`
# read -p "是否构建前端[0|其他->否 1->是 2->构建并拷贝至server/static/static]: " runBuildWeb
runBuildWeb="2"
# 编译web前端
buildWeb ${runBuildWeb}
fi fi
if [[ "${buildType}" == "5" ]] || [[ "${buildType}" == "6" ]] ; then if [[ "${buildType}" == "5" ]] || [[ "${buildType}" == "6" ]] ; then
@@ -157,12 +160,6 @@ function runBuild() {
fi fi
fi fi
# read -p "是否构建前端[0|其他->否 1->是 2->构建并拷贝至server/static/static]: " runBuildWeb
runBuildWeb="2"
# 编译web前端
buildWeb ${runBuildWeb}
case ${buildType} in case ${buildType} in
"1") "1")
buildLinuxAmd64 ${toPath} ${copyDocScript} buildLinuxAmd64 ${toPath} ${copyDocScript}
@@ -190,11 +187,13 @@ function runBuild() {
;; ;;
esac esac
if [[ "${buildType}" != "5" ]] && [[ "${buildType}" != "6" ]] ; then
echo_green "删除['${server_folder}/static/static']下静态资源文件." echo_green "删除['${server_folder}/static/static']下静态资源文件."
# 删除静态资源文件保留一个favicon.ico否则后端启动会报错 # 删除静态资源文件保留一个favicon.ico否则后端启动会报错
rm -rf ${server_folder}/static/static/assets rm -rf ${server_folder}/static/static/assets
rm -rf ${server_folder}/static/static/config.js rm -rf ${server_folder}/static/static/config.js
rm -rf ${server_folder}/static/static/index.html rm -rf ${server_folder}/static/static/index.html
fi
} }
runBuild runBuild

File diff suppressed because one or more lines are too long

View File

@@ -102,7 +102,7 @@
<el-table <el-table
v-bind="$attrs" v-bind="$attrs"
max-height="700" :max-height="tableMaxHeight"
@selection-change="handleSelectionChange" @selection-change="handleSelectionChange"
:data="props.data" :data="props.data"
highlight-current-row highlight-current-row
@@ -264,6 +264,7 @@ const state = reactive({
// 输入框宽度 // 输入框宽度
inputWidth: "200px" as any, inputWidth: "200px" as any,
formatVal: '', // 格式化后的值 formatVal: '', // 格式化后的值
tableMaxHeight: window.innerHeight - 240 + 'px',
}) })
const { const {
@@ -274,6 +275,7 @@ const {
loadingData, loadingData,
inputWidth, inputWidth,
formatVal, formatVal,
tableMaxHeight,
} = toRefs(state) } = toRefs(state)
watch(() => props.queryForm, (newValue: any) => { watch(() => props.queryForm, (newValue: any) => {
@@ -304,7 +306,7 @@ onMounted(() => {
state.pageNum = props.pageNum; state.pageNum = props.pageNum;
state.pageSize = pageSize; state.pageSize = pageSize;
state.queryForm = props.queryForm; state.queryForm = props.queryForm;
state.pageSizes = [pageSize, pageSize * 2, pageSize * 3, pageSize * 4]; state.pageSizes = [pageSize, pageSize * 2, pageSize * 3, pageSize * 4, pageSize * 5];
// 如果没传输入框宽度则根据组件size设置默认宽度 // 如果没传输入框宽度则根据组件size设置默认宽度
if (!props.inputWidth) { if (!props.inputWidth) {

View File

@@ -64,7 +64,7 @@ const columns = ref([
TableColumn.new('machineIp', '机器IP').setMinWidth(120), TableColumn.new('machineIp', '机器IP').setMinWidth(120),
TableColumn.new('machineName', '机器名称').setMinWidth(100), TableColumn.new('machineName', '机器名称').setMinWidth(100),
TableColumn.new('status', '状态').typeTag(CronJobExecStatusEnum).setMinWidth(70), TableColumn.new('status', '状态').typeTag(CronJobExecStatusEnum).setMinWidth(70),
TableColumn.new('res', '执行结果').setMinWidth(250), TableColumn.new('res', '执行结果').setMinWidth(250).canBeautify(),
TableColumn.new('execTime', '执行时间').isTime().setMinWidth(150), TableColumn.new('execTime', '执行时间').isTime().setMinWidth(150),
]); ]);

View File

@@ -20,13 +20,6 @@ import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
func WrapStaticHandler(h http.Handler) gin.HandlerFunc {
return func(c *gin.Context) {
c.Writer.Header().Set("Cache-Control", `public, max-age=31536000`)
h.ServeHTTP(c.Writer, c.Request)
}
}
func InitRouter() *gin.Engine { func InitRouter() *gin.Engine {
// server配置 // server配置
serverConfig := config.Conf.Server serverConfig := config.Conf.Server
@@ -40,28 +33,8 @@ func InitRouter() *gin.Engine {
g.JSON(http.StatusNotFound, gin.H{"code": 404, "msg": fmt.Sprintf("not found '%s:%s'", g.Request.Method, g.Request.URL.Path)}) g.JSON(http.StatusNotFound, gin.H{"code": 404, "msg": fmt.Sprintf("not found '%s:%s'", g.Request.Method, g.Request.URL.Path)})
}) })
// 使用embed打包静态资源至二进制文件中
fsys, _ := fs.Sub(static.Static, "static")
fileServer := http.FileServer(http.FS(fsys))
handler := WrapStaticHandler(fileServer)
router.GET("/", handler)
router.GET("/favicon.ico", handler)
router.GET("/config.js", handler)
// 所有/assets/**开头的都是静态资源文件
router.GET("/assets/*file", handler)
// 设置静态资源 // 设置静态资源
if staticConfs := serverConfig.Static; staticConfs != nil { setStatic(router)
for _, scs := range *staticConfs {
router.StaticFS(scs.RelativePath, http.Dir(scs.Root))
}
}
// 设置静态文件
if staticFileConfs := serverConfig.StaticFile; staticFileConfs != nil {
for _, sfs := range *staticFileConfs {
router.StaticFile(sfs.RelativePath, sfs.Filepath)
}
}
// 是否允许跨域 // 是否允许跨域
if serverConfig.Cors { if serverConfig.Cors {
@@ -71,8 +44,7 @@ func InitRouter() *gin.Engine {
// 设置路由组 // 设置路由组
api := router.Group("/api") api := router.Group("/api")
{ {
common_router.InitIndexRouter(api) common_router.Init(api)
common_router.InitCommonRouter(api)
auth_router.Init(api) auth_router.Init(api)
@@ -88,3 +60,35 @@ func InitRouter() *gin.Engine {
return router return router
} }
func setStatic(router *gin.Engine) {
// 使用embed打包静态资源至二进制文件中
fsys, _ := fs.Sub(static.Static, "static")
fileServer := http.FileServer(http.FS(fsys))
handler := WrapStaticHandler(fileServer)
router.GET("/", handler)
router.GET("/favicon.ico", handler)
router.GET("/config.js", handler)
// 所有/assets/**开头的都是静态资源文件
router.GET("/assets/*file", handler)
// 设置静态资源
if staticConfs := config.Conf.Server.Static; staticConfs != nil {
for _, scs := range *staticConfs {
router.StaticFS(scs.RelativePath, http.Dir(scs.Root))
}
}
// 设置静态文件
if staticFileConfs := config.Conf.Server.StaticFile; staticFileConfs != nil {
for _, sfs := range *staticFileConfs {
router.StaticFile(sfs.RelativePath, sfs.Filepath)
}
}
}
func WrapStaticHandler(h http.Handler) gin.HandlerFunc {
return func(c *gin.Context) {
c.Writer.Header().Set("Cache-Control", `public, max-age=31536000`)
h.ServeHTTP(c.Writer, c.Request)
}
}

View File

@@ -0,0 +1,8 @@
package router
import "github.com/gin-gonic/gin"
func Init(router *gin.RouterGroup) {
InitCommonRouter(router)
InitIndexRouter(router)
}

View File

@@ -104,6 +104,7 @@ func (m *MachineFile) GetDirEntry(rc *req.Ctx) {
g := rc.GinCtx g := rc.GinCtx
fid := GetMachineFileId(g) fid := GetMachineFileId(g)
readPath := g.Query("path") readPath := g.Query("path")
rc.ReqParam = fmt.Sprintf("path: %s", readPath)
if !strings.HasSuffix(readPath, "/") { if !strings.HasSuffix(readPath, "/") {
readPath = readPath + "/" readPath = readPath + "/"
@@ -120,7 +121,6 @@ func (m *MachineFile) GetDirEntry(rc *req.Ctx) {
} }
sort.Sort(vo.MachineFileInfos(fisVO)) sort.Sort(vo.MachineFileInfos(fisVO))
rc.ResData = fisVO rc.ResData = fisVO
rc.ReqParam = fmt.Sprintf("path: %s", readPath)
} }
func (m *MachineFile) GetDirSize(rc *req.Ctx) { func (m *MachineFile) GetDirSize(rc *req.Ctx) {

View File

@@ -2,7 +2,7 @@ package form
type AccountCreateForm struct { type AccountCreateForm struct {
Id uint64 `json:"id"` Id uint64 `json:"id"`
Name string `json:"name" binding:"required,max=16"` Name string `json:"name" binding:"required,max=16" msg:"required=姓名不能为空,max=姓名最大长度不能超过16位"`
Username string `json:"username" binding:"pattern=account_username"` Username string `json:"username" binding:"pattern=account_username"`
Password string `json:"password"` Password string `json:"password"`
} }

View File

@@ -1,6 +1,7 @@
package validatorx package validatorx
import ( import (
"mayfly-go/pkg/utils/stringx"
"mayfly-go/pkg/utils/structx" "mayfly-go/pkg/utils/structx"
"reflect" "reflect"
"strings" "strings"
@@ -12,6 +13,8 @@ import (
zh_trans "github.com/go-playground/validator/v10/translations/zh" zh_trans "github.com/go-playground/validator/v10/translations/zh"
) )
const CustomMsgTagName = "msg"
var ( var (
trans ut.Translator trans ut.Translator
) )
@@ -26,7 +29,7 @@ func Init() {
// 修改返回字段key的格式 // 修改返回字段key的格式
validate.RegisterTagNameFunc(func(fld reflect.StructField) string { validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
// 如果存在校验错误提示消息,则使用字段名,后续需要通过该字段名获取相应错误消息 // 如果存在校验错误提示消息,则使用字段名,后续需要通过该字段名获取相应错误消息
if _, ok := fld.Tag.Lookup("valid_msg"); ok { if _, ok := fld.Tag.Lookup(CustomMsgTagName); ok {
return fld.Name return fld.Name
} }
name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0] name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
@@ -63,16 +66,19 @@ func Translate(data any, err error) map[string][]string {
// 判断该字段是否设置了自定义的错误描述信息,存在则使用自定义错误信息进行提示 // 判断该字段是否设置了自定义的错误描述信息,存在则使用自定义错误信息进行提示
if field, ok := structx.IndirectType(reflect.TypeOf(data)).FieldByName(fieldName); ok { if field, ok := structx.IndirectType(reflect.TypeOf(data)).FieldByName(fieldName); ok {
if errMsg, ok := field.Tag.Lookup("valid_msg"); ok { if errMsg, ok := field.Tag.Lookup(CustomMsgTagName); ok {
result[fieldName] = append(result[fieldName], errMsg) customMsg := getCustomErrMsg(err.Tag(), errMsg)
break if customMsg != "" {
result[fieldName] = append(result[fieldName], customMsg)
continue
}
} }
} }
// 如果是自定义正则校验规则,则使用自定义的错误描述信息 // 如果是自定义正则校验规则,则使用自定义的错误描述信息
if err.Tag() == CustomPatternTagName { if err.Tag() == CustomPatternTagName {
result[fieldName] = append(result[fieldName], fieldName+patternErrMsg[err.Param()]) result[fieldName] = append(result[fieldName], fieldName+patternErrMsg[err.Param()])
break continue
} }
result[fieldName] = append(result[fieldName], err.Translate(trans)) result[fieldName] = append(result[fieldName], err.Translate(trans))
@@ -90,3 +96,21 @@ func Translate2Str(data any, err error) string {
} }
return strings.Join(errMsgs, ", ") return strings.Join(errMsgs, ", ")
} }
// 获取自定义的错误提示消息
//
// @param validTag 校验标签如required等
// @param customMsg 自定义错误消息
func getCustomErrMsg(validTag, customMsg string) string {
// 解析 msg:"required=用户名不能为空,min=用户名长度不能小于8位"
msgs := strings.Split(customMsg, ",")
for _, msg := range msgs {
tagAndMsg := strings.Split(stringx.Trim(msg), "=")
if len(tagAndMsg) > 1 && validTag == stringx.Trim(tagAndMsg[0]) {
// 获取valid tag对应的错误消息
return stringx.Trim(tagAndMsg[1])
}
}
return customMsg
}