Merge branch 'gva-plugins' into feat/notify-dingding

This commit is contained in:
奇淼(piexlmax
2021-08-27 23:20:59 +08:00
committed by GitHub
87 changed files with 4575 additions and 18747 deletions
-2
View File
@@ -6,10 +6,8 @@ type ApiGroup struct {
CustomerApi
ExcelApi
FileUploadAndDownloadApi
SimpleUploaderApi
}
var fileUploadAndDownloadService = service.ServiceGroupApp.ExampleServiceGroup.FileUploadAndDownloadService
var customerService = service.ServiceGroupApp.ExampleServiceGroup.CustomerService
var excelService = service.ServiceGroupApp.ExampleServiceGroup.ExcelService
var simpleUploaderService = service.ServiceGroupApp.ExampleServiceGroup.SimpleUploaderService
@@ -1,95 +0,0 @@
package example
import (
"github.com/flipped-aurora/gin-vue-admin/server/global"
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
"github.com/flipped-aurora/gin-vue-admin/server/model/example"
"github.com/flipped-aurora/gin-vue-admin/server/utils"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
)
type SimpleUploaderApi struct {
}
// @Tags SimpleUploader
// @Summary 断点续传插件版示例
// @Security ApiKeyAuth
// @accept multipart/form-data
// @Produce application/json
// @Param file formData file true "断点续传插件版示例"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"切片创建成功"}"
// @Router /SimpleUploaderApi/upload [post]
func (s *SimpleUploaderApi) SimpleUploaderUpload(c *gin.Context) {
var chunk example.ExaSimpleUploader
_, header, err := c.Request.FormFile("file")
chunk.Filename = c.PostForm("filename")
chunk.ChunkNumber = c.PostForm("chunkNumber")
chunk.CurrentChunkSize = c.PostForm("currentChunkSize")
chunk.Identifier = c.PostForm("identifier")
chunk.TotalSize = c.PostForm("totalSize")
chunk.TotalChunks = c.PostForm("totalChunks")
var chunkDir = "./chunk/" + chunk.Identifier + "/"
hasDir, _ := utils.PathExists(chunkDir)
if !hasDir {
if err := utils.CreateDir(chunkDir); err != nil {
global.GVA_LOG.Error("创建目录失败!", zap.Any("err", err))
}
}
chunkPath := chunkDir + chunk.Filename + chunk.ChunkNumber
err = c.SaveUploadedFile(header, chunkPath)
if err != nil {
global.GVA_LOG.Error("切片创建失败!", zap.Any("err", err))
response.FailWithMessage("切片创建失败", c)
return
}
chunk.CurrentChunkPath = chunkPath
err = simpleUploaderService.SaveChunk(chunk)
if err != nil {
global.GVA_LOG.Error("切片创建失败!", zap.Any("err", err))
response.FailWithMessage("切片创建失败", c)
return
} else {
response.OkWithMessage("切片创建成功", c)
}
}
// @Tags SimpleUploader
// @Summary 断点续传插件版示例
// @Security ApiKeyAuth
// @Produce application/json
// @Param md5 query string true "md5"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"查询成功"}"
// @Router /SimpleUploaderApi/checkFileMd5 [get]
func (s *SimpleUploaderApi) CheckFileMd5(c *gin.Context) {
md5 := c.Query("md5")
err, chunks, isDone := simpleUploaderService.CheckFileMd5(md5)
if err != nil {
global.GVA_LOG.Error("md5读取失败!", zap.Any("err", err))
response.FailWithMessage("md5读取失败", c)
} else {
response.OkWithDetailed(gin.H{
"chunks": chunks,
"isDone": isDone,
}, "查询成功", c)
}
}
// @Tags SimpleUploader
// @Summary 合并文件
// @Security ApiKeyAuth
// @Produce application/json
// @Param md5 query string true "md5"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"合并成功"}"
// @Router /SimpleUploaderApi/mergeFileMd5 [get]
func (s *SimpleUploaderApi) MergeFileMd5(c *gin.Context) {
md5 := c.Query("md5")
fileName := c.Query("fileName")
err := simpleUploaderService.MergeFileMd5(md5, fileName)
if err != nil {
global.GVA_LOG.Error("md5读取失败!", zap.Any("err", err))
response.FailWithMessage("md5读取失败", c)
} else {
response.OkWithMessage("合并成功", c)
}
}
+1 -2
View File
@@ -155,8 +155,7 @@ func (autoApi *AutoCodeApi) CreateTemp(c *gin.Context) {
err := autoCodeService.CreateTemp(a, apiIds...)
if err != nil {
if errors.Is(err, system.AutoMoveErr) {
c.Writer.Header().Add("success", "false")
c.Writer.Header().Add("msgtype", "success")
c.Writer.Header().Add("success", "true")
c.Writer.Header().Add("msg", url.QueryEscape(err.Error()))
} else {
c.Writer.Header().Add("success", "false")
-1
View File
@@ -48,7 +48,6 @@ func MysqlTables(db *gorm.DB) {
example.ExaFileUploadAndDownload{},
example.ExaFile{},
example.ExaFileChunk{},
example.ExaSimpleUploader{},
example.ExaCustomer{},
system.SysOperationRecord{},
system.SysAutoCodeHistory{},
+20
View File
@@ -1,6 +1,10 @@
package initialize
import (
"github.com/flipped-aurora/gin-vue-admin/server/global"
//email "github.com/flipped-aurora/gva-plug-email" // 在线仓库模式
"github.com/flipped-aurora/gin-vue-admin/server/plugin/email" // 本地插件仓库地址模式
"github.com/flipped-aurora/gin-vue-admin/server/plugin/example_plugin"
"github.com/flipped-aurora/gin-vue-admin/server/utils/plugin"
"github.com/gin-gonic/gin"
)
@@ -11,3 +15,19 @@ func PluginInit(group *gin.RouterGroup, Plugin ...plugin.Plugin) {
Plugin[i].Register(PluginGroup)
}
}
func InstallPlugin(PublicGroup *gin.RouterGroup, PrivateGroup *gin.RouterGroup) {
// 添加开放权限的插件 示例
PluginInit(PublicGroup, example_plugin.ExamplePlugin)
// 添加跟角色挂钩权限的插件 示例 本地示例模式于在线仓库模式注意上方的import 可以自行切换 效果相同
PluginInit(PrivateGroup, email.CreateEmailPlug(
global.GVA_CONFIG.Email.To,
global.GVA_CONFIG.Email.From,
global.GVA_CONFIG.Email.Host,
global.GVA_CONFIG.Email.Secret,
global.GVA_CONFIG.Email.Nickname,
global.GVA_CONFIG.Email.Port,
global.GVA_CONFIG.Email.IsSSL,
))
}
+6 -1
View File
@@ -1,10 +1,12 @@
package initialize
import (
//email "github.com/flipped-aurora/gva-plug-email" // 在线仓库模式
"github.com/flipped-aurora/gin-vue-admin/server/plugin/email" // 本地插件仓库地址模式
"github.com/flipped-aurora/gin-vue-admin/server/plugin/example_plugin"
"github.com/flipped-aurora/gin-vue-admin/server/plugin/notify"
"net/http"
_ "github.com/flipped-aurora/gin-vue-admin/server/docs"
@@ -55,7 +57,6 @@ func Routers() *gin.Engine {
systemRouter.InitSysDictionaryDetailRouter(PrivateGroup) // 字典详情管理
exampleRouter.InitFileUploadAndDownloadRouter(PrivateGroup) // 文件上传下载功能路由
exampleRouter.InitExcelRouter(PrivateGroup) // 表格导入导出
exampleRouter.InitSimpleUploaderRouter(PrivateGroup) // 断点续传(插件版)
exampleRouter.InitCustomerRouter(PrivateGroup) // 客户路由
// Code generated by github.com/flipped-aurora/gin-vue-admin/server Begin; DO NOT EDIT.
@@ -63,6 +64,7 @@ func Routers() *gin.Engine {
// Code generated by github.com/flipped-aurora/gin-vue-admin/server End; DO NOT EDIT.
}
// 添加开放权限的插件 示例
PluginInit(PublicGroup, example_plugin.ExamplePlugin)
@@ -80,6 +82,9 @@ func Routers() *gin.Engine {
global.GVA_CONFIG.Email.IsSSL,
))
InstallPlugin(PublicGroup, PrivateGroup) // 安装插件
global.GVA_LOG.Info("router register success")
return Router
}
@@ -1,13 +0,0 @@
package example
type ExaSimpleUploader struct {
ChunkNumber string `json:"chunkNumber" gorm:"comment:当前切片标记"`
CurrentChunkSize string `json:"currentChunkSize" gorm:"comment:当前切片容量"`
CurrentChunkPath string `json:"currentChunkPath" gorm:"comment:切片本地路径"`
TotalSize string `json:"totalSize" gorm:"comment:总容量"`
Identifier string `json:"identifier" gorm:"comment:文件标识(md5)"`
Filename string `json:"filename" gorm:"comment:文件名"`
TotalChunks string `json:"totalChunks" gorm:"comment:切片总数"`
IsDone bool `json:"isDone" gorm:"comment:是否上传完成"`
FilePath string `json:"filePath" gorm:"comment:文件本地路径"`
}
-8
View File
@@ -7,13 +7,6 @@ import (
)
type emailPlugin struct {
To string
From string
Host string
Secret string
Nickname string
Port int
IsSsl bool
}
func CreateEmailPlug(To, From, Host, Secret, Nickname string, Port int, IsSSL bool) *emailPlugin {
@@ -25,7 +18,6 @@ func CreateEmailPlug(To, From, Host, Secret, Nickname string, Port int, IsSSL bo
global.GlobalConfig.Port = Port
global.GlobalConfig.IsSSL = IsSSL
return &emailPlugin{}
}
func (*emailPlugin) Register(group *gin.RouterGroup) {
File diff suppressed because one or more lines are too long
-2
View File
@@ -5,5 +5,3 @@
项目github:"https://github.com/piexlmax/github.com/flipped-aurora/gin-vue-admin/server"
希望大家给个star多多鼓励
暂时不保存大家生成的结构体 只为方便一次性使用
+2 -2
View File
@@ -4,7 +4,7 @@
{{- range .Fields}}
<el-form-item label="{{.FieldDesc}}:">
{{- if eq .FieldType "bool" }}
<el-switch active-color="#13ce66" inactive-color="#ff4949" active-text="是" inactive-text="否" v-model="formData.{{.FieldJson}}" clearable ></el-switch>
<el-switch v-model="formData.{{.FieldJson}}" active-color="#13ce66" inactive-color="#ff4949" active-text="是" inactive-text="否" clearable ></el-switch>
{{- end }}
{{- if eq .FieldType "string" }}
<el-input v-model="formData.{{.FieldJson}}" clearable placeholder="请输入" />
@@ -19,7 +19,7 @@
{{- end }}
{{- end }}
{{- if eq .FieldType "time.Time" }}
<el-date-picker type="date" placeholder="选择日期" v-model="formData.{{ .FieldJson }}" clearable></el-date-picker>
<el-date-picker v-model="formData.{{ .FieldJson }}" type="date" placeholder="选择日期" clearable></el-date-picker>
{{- end }}
{{- if eq .FieldType "float64" }}
<el-input-number v-model="formData.{{ .FieldJson }}" :precision="2" clearable></el-input-number>
+17 -31
View File
@@ -24,13 +24,15 @@
<el-form-item>
<el-button size="mini" type="primary" icon="el-icon-search" @click="onSubmit">查询</el-button>
<el-button size="mini" type="primary" icon="el-icon-plus" @click="openDialog">新增</el-button>
<el-popover v-model="deleteVisible" placement="top" width="160">
<el-popover v-model:visible="deleteVisible" placement="top" width="160">
<p>确定要删除吗?</p>
<div style="text-align: right; margin: 0">
<el-button size="mini" type="text" @click="deleteVisible = false">取消</el-button>
<el-button size="mini" type="primary" @click="onDelete">确定</el-button>
</div>
<el-button slot="reference" icon="el-icon-delete" size="mini" type="danger" style="margin-left: 10px;">批量删除</el-button>
<template #reference>
<el-button icon="el-icon-delete" size="mini" type="danger" style="margin-left: 10px;">批量删除</el-button>
</template>
</el-popover>
</el-form-item>
</el-form>
@@ -46,24 +48,24 @@
>
<el-table-column type="selection" width="55" />
<el-table-column label="日期" width="180">
<template slot-scope="scope">{{ "{{ scope.row.CreatedAt|formatDate }}" }}</template>
<template #default="scope">{{ "{{ formatDate(scope.row.CreatedAt) }}" }}</template>
</el-table-column>
{{- range .Fields}}
{{- if .DictType}}
<el-table-column label="{{.FieldDesc}}" prop="{{.FieldJson}}" width="120">
<template slot-scope="scope">
<template #default="scope">
{{"{{"}} filterDict(scope.row.{{.FieldJson}},"{{.DictType}}") {{"}}"}}
</template>
</el-table-column>
{{- else if eq .FieldType "bool" }}
<el-table-column label="{{.FieldDesc}}" prop="{{.FieldJson}}" width="120">
<template slot-scope="scope">{{ "{{scope.row."}}{{.FieldJson}}{{"|formatBoolean}}" }}</template>
<template #default="scope">{{"{{"}} formatBoolean(scope.row.{{.FieldJson}}) {{"}}"}}</template>
</el-table-column> {{- else }}
<el-table-column label="{{.FieldDesc}}" prop="{{.FieldJson}}" width="120" />
{{- end }}
{{- end }}
<el-table-column label="按钮组">
<template slot-scope="scope">
<template #default="scope">
<el-button size="small" type="primary" icon="el-icon-edit" class="table-button" @click="update{{.StructName}}(scope.row)">变更</el-button>
<el-button type="danger" icon="el-icon-delete" size="mini" @click="deleteRow(scope.row)">删除</el-button>
</template>
@@ -79,12 +81,12 @@
@current-change="handleCurrentChange"
@size-change="handleSizeChange"
/>
<el-dialog :before-close="closeDialog" :visible.sync="dialogFormVisible" title="弹窗操作">
<el-dialog v-model="dialogFormVisible" :before-close="closeDialog" title="弹窗操作">
<el-form :model="formData" label-position="right" label-width="80px">
{{- range .Fields}}
<el-form-item label="{{.FieldDesc}}:">
{{- if eq .FieldType "bool" }}
<el-switch active-color="#13ce66" inactive-color="#ff4949" active-text="是" inactive-text="否" v-model="formData.{{.FieldJson}}" clearable ></el-switch>
<el-switch v-model="formData.{{.FieldJson}}" active-color="#13ce66" inactive-color="#ff4949" active-text="是" inactive-text="否" clearable ></el-switch>
{{- end }}
{{- if eq .FieldType "string" }}
<el-input v-model="formData.{{.FieldJson}}" clearable placeholder="请输入" />
@@ -99,7 +101,7 @@
{{- end }}
{{- end }}
{{- if eq .FieldType "time.Time" }}
<el-date-picker type="date" placeholder="选择日期" v-model="formData.{{ .FieldJson }}" clearable />
<el-date-picker v-model="formData.{{ .FieldJson }}" type="date" placeholder="选择日期" clearable />
{{- end }}
{{- if eq .FieldType "float64" }}
<el-input-number v-model="formData.{{ .FieldJson }}" :precision="2" clearable />
@@ -107,10 +109,12 @@
</el-form-item>
{{- end }}
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="closeDialog">取 消</el-button>
<el-button type="primary" @click="enterDialog">确 定</el-button>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="closeDialog">取 消</el-button>
<el-button type="primary" @click="enterDialog">确 定</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
@@ -124,27 +128,9 @@ import {
find{{.StructName}},
get{{.StructName}}List
} from '@/api/{{.PackageName}}' // 此处请自行替换地址
import { formatTimeToStr } from '@/utils/date'
import infoList from '@/mixins/infoList'
export default {
name: '{{.StructName}}',
filters: {
formatDate: function(time) {
if (time !== null && time !== '') {
var date = new Date(time)
return formatTimeToStr(date, 'yyyy-MM-dd hh:mm:ss')
} else {
return ''
}
},
formatBoolean: function(bool) {
if (bool != null) {
return bool ? '是' : '否'
} else {
return ''
}
}
},
mixins: [infoList],
data() {
return {
-1
View File
@@ -4,5 +4,4 @@ type RouterGroup struct {
CustomerRouter
ExcelRouter
FileUploadAndDownloadRouter
SimpleUploaderRouter
}
@@ -1,18 +0,0 @@
package example
import (
v1 "github.com/flipped-aurora/gin-vue-admin/server/api/v1"
"github.com/gin-gonic/gin"
)
type SimpleUploaderRouter struct{}
func (e *SimpleUploaderRouter) InitSimpleUploaderRouter(Router *gin.RouterGroup) {
simpleUploaderRouter := Router.Group("simpleUploader")
var simpleUploaderApi = v1.ApiGroupApp.ExampleApiGroup.SimpleUploaderApi
{
simpleUploaderRouter.POST("upload", simpleUploaderApi.SimpleUploaderUpload) // 上传功能
simpleUploaderRouter.GET("checkFileMd5", simpleUploaderApi.CheckFileMd5) // 文件完整度验证
simpleUploaderRouter.GET("mergeFileMd5", simpleUploaderApi.MergeFileMd5) // 合并文件
}
}
-1
View File
@@ -4,5 +4,4 @@ type ServiceGroup struct {
FileUploadAndDownloadService
CustomerService
ExcelService
SimpleUploaderService
}
@@ -1,98 +0,0 @@
package example
import (
"errors"
"fmt"
"io/ioutil"
"os"
"strconv"
"github.com/flipped-aurora/gin-vue-admin/server/global"
"github.com/flipped-aurora/gin-vue-admin/server/model/example"
"gorm.io/gorm"
)
type SimpleUploaderService struct {
}
//@author: [piexlmax](https://github.com/piexlmax)
//@function: SaveChunk
//@description: 保存文件切片路径
//@param: uploader model.ExaSimpleUploader
//@return: err error
func (exa *SimpleUploaderService) SaveChunk(uploader example.ExaSimpleUploader) (err error) {
return global.GVA_DB.Create(uploader).Error
}
//@author: [piexlmax](https://github.com/piexlmax)
//@function: CheckFileMd5
//@description: 检查文件是否已经上传过
//@param: md5 string
//@return: err error, uploads []model.ExaSimpleUploader, isDone bool
func (exa *SimpleUploaderService) CheckFileMd5(md5 string) (err error, uploads []example.ExaSimpleUploader, isDone bool) {
err = global.GVA_DB.Find(&uploads, "identifier = ? AND is_done = ?", md5, false).Error
isDone = errors.Is(global.GVA_DB.First(&example.ExaSimpleUploader{}, "identifier = ? AND is_done = ?", md5, true).Error, gorm.ErrRecordNotFound)
return err, uploads, !isDone
}
//@author: [piexlmax](https://github.com/piexlmax)
//@function: MergeFileMd5
//@description: 合并文件
//@param: md5 string, fileName string
//@return: err error
func (exa *SimpleUploaderService) MergeFileMd5(md5 string, fileName string) (err error) {
finishDir := "./finish/"
dir := "./chunk/" + md5
// 如果文件上传成功 不做后续操作 通知成功即可
if !errors.Is(global.GVA_DB.First(&example.ExaSimpleUploader{}, "identifier = ? AND is_done = ?", md5, true).Error, gorm.ErrRecordNotFound) {
return nil
}
// 打开切片文件夹
rd, err := ioutil.ReadDir(dir)
_ = os.MkdirAll(finishDir, os.ModePerm)
// 创建目标文件
fd, err := os.OpenFile(finishDir+fileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
if err != nil {
return
}
// 关闭文件
defer fd.Close()
// 将切片文件按照顺序写入
for k := range rd {
content, _ := ioutil.ReadFile(dir + "/" + fileName + strconv.Itoa(k+1))
_, err = fd.Write(content)
if err != nil {
_ = os.Remove(finishDir + fileName)
}
}
if err != nil {
return err
}
err = global.GVA_DB.Transaction(func(tx *gorm.DB) error {
// 删除切片信息
if err = tx.Delete(&example.ExaSimpleUploader{}, "identifier = ? AND is_done = ?", md5, false).Error; err != nil {
fmt.Println(err)
return err
}
data := example.ExaSimpleUploader{
Identifier: md5,
IsDone: true,
FilePath: finishDir + fileName,
Filename: fileName,
}
// 添加文件信息
if err = tx.Create(&data).Error; err != nil {
fmt.Println(err)
return err
}
return nil
})
err = os.RemoveAll(dir) // 清除切片
return err
}
+1 -1
View File
@@ -247,7 +247,7 @@ func (autoCodeService *AutoCodeService) CreateTemp(autoCode system.AutoCodeStruc
return err
}
if autoCode.AutoMoveFile {
return errors.New("创建代码成功并移动文件成功")
return system.AutoMoveErr
}
return nil
-1
View File
@@ -133,7 +133,6 @@ func (initDBService *InitDBService) InitDB(conf request.InitDB) error {
example.ExaFileUploadAndDownload{},
example.ExaFile{},
example.ExaFileChunk{},
example.ExaSimpleUploader{},
example.ExaCustomer{},
system.SysOperationRecord{},
system.SysAutoCodeHistory{},
-1
View File
@@ -36,7 +36,6 @@ var authorityMenus = []AuthorityMenus{
{"888", 18},
{"888", 19},
{"888", 20},
{"888", 21},
{"888", 22},
{"888", 23},
{"888", 24},
+1 -2
View File
@@ -35,8 +35,7 @@ var menus = []system.SysBaseMenu{
{GVA_MODEL: global.GVA_MODEL{ID: 18, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, Hidden: false, ParentId: "3", Path: "dictionary", Name: "dictionary", Component: "view/superAdmin/dictionary/sysDictionary.vue", Sort: 5, Meta: system.Meta{Title: "字典管理", Icon: "notebook-2"}},
{GVA_MODEL: global.GVA_MODEL{ID: 19, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, Hidden: true, ParentId: "3", Path: "dictionaryDetail/:id", Name: "dictionaryDetail", Component: "view/superAdmin/dictionary/sysDictionaryDetail.vue", Sort: 1, Meta: system.Meta{Title: "字典详情", Icon: "s-order"}},
{GVA_MODEL: global.GVA_MODEL{ID: 20, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, Hidden: false, ParentId: "3", Path: "operation", Name: "operation", Component: "view/superAdmin/operation/sysOperationRecord.vue", Sort: 6, Meta: system.Meta{Title: "操作历史", Icon: "time"}},
{GVA_MODEL: global.GVA_MODEL{ID: 21, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, Hidden: false, ParentId: "9", Path: "simpleUploader", Name: "simpleUploader", Component: "view/example/simpleUploader/simpleUploader", Sort: 6, Meta: system.Meta{Title: "断点续传(插件版)", Icon: "upload"}},
{GVA_MODEL: global.GVA_MODEL{ID: 22, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, ParentId: "0", Path: "https://www.github.com/flipped-aurora/gin-vue-admin/server.com", Name: "https://www.github.com/flipped-aurora/gin-vue-admin/server.com", Hidden: false, Component: "/", Sort: 0, Meta: system.Meta{Title: "官方网站", Icon: "s-home"}},
{GVA_MODEL: global.GVA_MODEL{ID: 22, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, ParentId: "0", Path: "https://www.gin-vue-admin.com", Name: "https://www.gin-vue-admin.com", Hidden: false, Component: "/", Sort: 0, Meta: system.Meta{Title: "官方网站", Icon: "s-home"}},
{GVA_MODEL: global.GVA_MODEL{ID: 23, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, ParentId: "0", Path: "state", Name: "state", Hidden: false, Component: "view/system/state.vue", Sort: 6, Meta: system.Meta{Title: "服务器状态", Icon: "cloudy"}},
{GVA_MODEL: global.GVA_MODEL{ID: 24, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, ParentId: "14", Path: "autoCodeAdmin", Name: "autoCodeAdmin", Hidden: false, Component: "view/systemTools/autoCodeAdmin/index.vue", Sort: 1, Meta: system.Meta{Title: "自动化代码管理", Icon: "s-finance"}},
{GVA_MODEL: global.GVA_MODEL{ID: 25, CreatedAt: time.Now(), UpdatedAt: time.Now()}, MenuLevel: 0, ParentId: "14", Path: "autoCodeEdit/:id", Name: "autoCodeEdit", Hidden: true, Component: "view/systemTools/autoCode/index.vue", Sort: 0, Meta: system.Meta{Title: "自动化代码(复用)", Icon: "s-finance"}},