diff --git a/build_release.sh b/build_release.sh
index 462eea0b..b1e32b94 100755
--- a/build_release.sh
+++ b/build_release.sh
@@ -104,7 +104,6 @@ function buildMac() {
function buildDocker() {
echo_yellow "-------------------构建docker镜像开始-------------------"
imageVersion=$1
- cd ${server_folder}
imageName="mayflygo/mayfly-go:${imageVersion}"
docker build --platform linux/amd64 -t "${imageName}" .
echo_green "docker镜像构建完成->[${imageName}]"
@@ -114,7 +113,6 @@ function buildDocker() {
function buildxDocker() {
echo_yellow "-------------------docker buildx构建镜像开始-------------------"
imageVersion=$1
- cd ${server_folder}
imageName="ccr.ccs.tencentyun.com/mayfly/mayfly-go:${imageVersion}"
docker buildx build --push --platform linux/amd64,linux/arm64 -t "${imageName}" .
echo_green "docker多版本镜像构建完成->[${imageName}]"
@@ -147,6 +145,11 @@ function runBuild() {
# 进入目标路径,并赋值全路径
cd ${toPath}
toPath=`pwd`
+
+ # read -p "是否构建前端[0|其他->否 1->是 2->构建并拷贝至server/static/static]: " runBuildWeb
+ runBuildWeb="2"
+ # 编译web前端
+ buildWeb ${runBuildWeb}
fi
if [[ "${buildType}" == "5" ]] || [[ "${buildType}" == "6" ]] ; then
@@ -157,12 +160,6 @@ function runBuild() {
fi
fi
-
- # read -p "是否构建前端[0|其他->否 1->是 2->构建并拷贝至server/static/static]: " runBuildWeb
- runBuildWeb="2"
- # 编译web前端
- buildWeb ${runBuildWeb}
-
case ${buildType} in
"1")
buildLinuxAmd64 ${toPath} ${copyDocScript}
@@ -190,11 +187,13 @@ function runBuild() {
;;
esac
- echo_green "删除['${server_folder}/static/static']下静态资源文件."
- # 删除静态资源文件,保留一个favicon.ico,否则后端启动会报错
- rm -rf ${server_folder}/static/static/assets
- rm -rf ${server_folder}/static/static/config.js
- rm -rf ${server_folder}/static/static/index.html
+ if [[ "${buildType}" != "5" ]] && [[ "${buildType}" != "6" ]] ; then
+ echo_green "删除['${server_folder}/static/static']下静态资源文件."
+ # 删除静态资源文件,保留一个favicon.ico,否则后端启动会报错
+ rm -rf ${server_folder}/static/static/assets
+ rm -rf ${server_folder}/static/static/config.js
+ rm -rf ${server_folder}/static/static/index.html
+ fi
}
runBuild
diff --git a/mayfly_go_web/src/assets/iconfont/iconfont.js b/mayfly_go_web/src/assets/iconfont/iconfont.js
index 80adf06a..b9b4f4d5 100644
--- a/mayfly_go_web/src/assets/iconfont/iconfont.js
+++ b/mayfly_go_web/src/assets/iconfont/iconfont.js
@@ -1 +1,66 @@
-window._iconfont_svg_string_3953964='',function(c){var t=(t=document.getElementsByTagName("script"))[t.length-1],a=t.getAttribute("data-injectcss"),t=t.getAttribute("data-disable-injectsvg");if(!t){var l,e,i,o,n,h=function(t,a){a.parentNode.insertBefore(t,a)};if(a&&!c.__iconfont__svg__cssinject__){c.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(t){console&&console.log(t)}}l=function(){var t,a=document.createElement("div");a.innerHTML=c._iconfont_svg_string_3953964,(a=a.getElementsByTagName("svg")[0])&&(a.setAttribute("aria-hidden","true"),a.style.position="absolute",a.style.width=0,a.style.height=0,a.style.overflow="hidden",a=a,(t=document.body).firstChild?h(a,t.firstChild):t.appendChild(a))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(l,0):(e=function(){document.removeEventListener("DOMContentLoaded",e,!1),l()},document.addEventListener("DOMContentLoaded",e,!1)):document.attachEvent&&(i=l,o=c.document,n=!1,s(),o.onreadystatechange=function(){"complete"==o.readyState&&(o.onreadystatechange=null,d())})}function d(){n||(n=!0,i())}function s(){try{o.documentElement.doScroll("left")}catch(t){return void setTimeout(s,50)}d()}}(window);
\ No newline at end of file
+(window._iconfont_svg_string_3953964 =
+ ''),
+ (function (c) {
+ var t = (t = document.getElementsByTagName('script'))[t.length - 1],
+ a = t.getAttribute('data-injectcss'),
+ t = t.getAttribute('data-disable-injectsvg');
+ if (!t) {
+ var l,
+ e,
+ i,
+ o,
+ n,
+ h = function (t, a) {
+ a.parentNode.insertBefore(t, a);
+ };
+ if (a && !c.__iconfont__svg__cssinject__) {
+ c.__iconfont__svg__cssinject__ = !0;
+ try {
+ document.write(
+ ''
+ );
+ } catch (t) {
+ console && console.log(t);
+ }
+ }
+ (l = function () {
+ var t,
+ a = document.createElement('div');
+ (a.innerHTML = c._iconfont_svg_string_3953964),
+ (a = a.getElementsByTagName('svg')[0]) &&
+ (a.setAttribute('aria-hidden', 'true'),
+ (a.style.position = 'absolute'),
+ (a.style.width = 0),
+ (a.style.height = 0),
+ (a.style.overflow = 'hidden'),
+ (a = a),
+ (t = document.body).firstChild ? h(a, t.firstChild) : t.appendChild(a));
+ }),
+ document.addEventListener
+ ? ~['complete', 'loaded', 'interactive'].indexOf(document.readyState)
+ ? setTimeout(l, 0)
+ : ((e = function () {
+ document.removeEventListener('DOMContentLoaded', e, !1), l();
+ }),
+ document.addEventListener('DOMContentLoaded', e, !1))
+ : document.attachEvent &&
+ ((i = l),
+ (o = c.document),
+ (n = !1),
+ s(),
+ (o.onreadystatechange = function () {
+ 'complete' == o.readyState && ((o.onreadystatechange = null), d());
+ }));
+ }
+ function d() {
+ n || ((n = !0), i());
+ }
+ function s() {
+ try {
+ o.documentElement.doScroll('left');
+ } catch (t) {
+ return void setTimeout(s, 50);
+ }
+ d();
+ }
+ })(window);
diff --git a/mayfly_go_web/src/components/pagetable/PageTable.vue b/mayfly_go_web/src/components/pagetable/PageTable.vue
index 18f92500..b84a2995 100644
--- a/mayfly_go_web/src/components/pagetable/PageTable.vue
+++ b/mayfly_go_web/src/components/pagetable/PageTable.vue
@@ -102,7 +102,7 @@
props.queryForm, (newValue: any) => {
@@ -304,7 +306,7 @@ onMounted(() => {
state.pageNum = props.pageNum;
state.pageSize = pageSize;
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设置默认宽度
if (!props.inputWidth) {
diff --git a/mayfly_go_web/src/views/ops/machine/cronjob/CronJobExecList.vue b/mayfly_go_web/src/views/ops/machine/cronjob/CronJobExecList.vue
index 2aab95f9..4054bc6d 100644
--- a/mayfly_go_web/src/views/ops/machine/cronjob/CronJobExecList.vue
+++ b/mayfly_go_web/src/views/ops/machine/cronjob/CronJobExecList.vue
@@ -64,7 +64,7 @@ const columns = ref([
TableColumn.new('machineIp', '机器IP').setMinWidth(120),
TableColumn.new('machineName', '机器名称').setMinWidth(100),
TableColumn.new('status', '状态').typeTag(CronJobExecStatusEnum).setMinWidth(70),
- TableColumn.new('res', '执行结果').setMinWidth(250),
+ TableColumn.new('res', '执行结果').setMinWidth(250).canBeautify(),
TableColumn.new('execTime', '执行时间').isTime().setMinWidth(150),
]);
diff --git a/server/initialize/router.go b/server/initialize/router.go
index 2105dc4e..c36c1f09 100644
--- a/server/initialize/router.go
+++ b/server/initialize/router.go
@@ -20,13 +20,6 @@ import (
"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 {
// 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)})
})
- // 使用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 {
- 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)
- }
- }
+ setStatic(router)
// 是否允许跨域
if serverConfig.Cors {
@@ -71,8 +44,7 @@ func InitRouter() *gin.Engine {
// 设置路由组
api := router.Group("/api")
{
- common_router.InitIndexRouter(api)
- common_router.InitCommonRouter(api)
+ common_router.Init(api)
auth_router.Init(api)
@@ -88,3 +60,35 @@ func InitRouter() *gin.Engine {
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)
+ }
+}
diff --git a/server/internal/common/router/router.go b/server/internal/common/router/router.go
new file mode 100644
index 00000000..8c0f1c2b
--- /dev/null
+++ b/server/internal/common/router/router.go
@@ -0,0 +1,8 @@
+package router
+
+import "github.com/gin-gonic/gin"
+
+func Init(router *gin.RouterGroup) {
+ InitCommonRouter(router)
+ InitIndexRouter(router)
+}
diff --git a/server/internal/machine/api/machine_file.go b/server/internal/machine/api/machine_file.go
index c0d95922..de1270ce 100644
--- a/server/internal/machine/api/machine_file.go
+++ b/server/internal/machine/api/machine_file.go
@@ -104,6 +104,7 @@ func (m *MachineFile) GetDirEntry(rc *req.Ctx) {
g := rc.GinCtx
fid := GetMachineFileId(g)
readPath := g.Query("path")
+ rc.ReqParam = fmt.Sprintf("path: %s", readPath)
if !strings.HasSuffix(readPath, "/") {
readPath = readPath + "/"
@@ -120,7 +121,6 @@ func (m *MachineFile) GetDirEntry(rc *req.Ctx) {
}
sort.Sort(vo.MachineFileInfos(fisVO))
rc.ResData = fisVO
- rc.ReqParam = fmt.Sprintf("path: %s", readPath)
}
func (m *MachineFile) GetDirSize(rc *req.Ctx) {
diff --git a/server/internal/sys/api/form/account.go b/server/internal/sys/api/form/account.go
index dc8ddf70..822b5e6f 100644
--- a/server/internal/sys/api/form/account.go
+++ b/server/internal/sys/api/form/account.go
@@ -2,7 +2,7 @@ package form
type AccountCreateForm struct {
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"`
Password string `json:"password"`
}
diff --git a/server/pkg/validatorx/validatorx.go b/server/pkg/validatorx/validatorx.go
index 0d16b47b..5788de7e 100644
--- a/server/pkg/validatorx/validatorx.go
+++ b/server/pkg/validatorx/validatorx.go
@@ -1,6 +1,7 @@
package validatorx
import (
+ "mayfly-go/pkg/utils/stringx"
"mayfly-go/pkg/utils/structx"
"reflect"
"strings"
@@ -12,6 +13,8 @@ import (
zh_trans "github.com/go-playground/validator/v10/translations/zh"
)
+const CustomMsgTagName = "msg"
+
var (
trans ut.Translator
)
@@ -26,7 +29,7 @@ func Init() {
// 修改返回字段key的格式
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
}
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 errMsg, ok := field.Tag.Lookup("valid_msg"); ok {
- result[fieldName] = append(result[fieldName], errMsg)
- break
+ if errMsg, ok := field.Tag.Lookup(CustomMsgTagName); ok {
+ customMsg := getCustomErrMsg(err.Tag(), errMsg)
+ if customMsg != "" {
+ result[fieldName] = append(result[fieldName], customMsg)
+ continue
+ }
}
}
// 如果是自定义正则校验规则,则使用自定义的错误描述信息
if err.Tag() == CustomPatternTagName {
result[fieldName] = append(result[fieldName], fieldName+patternErrMsg[err.Param()])
- break
+ continue
}
result[fieldName] = append(result[fieldName], err.Translate(trans))
@@ -90,3 +96,21 @@ func Translate2Str(data any, err error) string {
}
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
+}