├── .gitignore ├── LICENSE ├── Queue.md ├── README.md ├── app ├── AdminUser │ ├── Bapi │ │ └── AdminUser.go │ ├── Model │ │ └── AdminUser.go │ └── Router │ │ └── AdminUser.go ├── Common │ ├── Bapi │ │ └── Common.go │ └── Model │ │ └── Model.go ├── Menu │ ├── Bapi │ │ └── Menu.go │ ├── Model │ │ └── Menu.go │ └── Router │ │ └── Menu.go ├── Notice │ ├── Api │ │ └── Notice.go │ ├── Bapi │ │ └── Notice.go │ ├── Model │ │ └── Notice.go │ └── Router │ │ └── Notice.go ├── Role │ ├── Bapi │ │ └── Role.go │ ├── Model │ │ ├── Role.go │ │ └── RoleMenu.go │ └── Router │ │ └── Role.go ├── System │ └── Bapi │ │ └── System.go ├── Test │ └── Test.go ├── Upload │ ├── Api │ │ ├── ImgUpload.go │ │ └── VideoUpload.go │ └── Router │ │ └── Upload.go ├── User │ ├── Api │ │ └── User.go │ ├── Model │ │ └── User.go │ └── Router │ │ └── User.go └── Ws │ ├── Ws.go │ └── testWs.html ├── asynq.yml ├── bootstrap └── bootstrap.go ├── config.yaml ├── core ├── Tpl │ ├── Api │ │ └── Tpl.go │ ├── Bapi │ │ └── Tpl.go │ ├── Model │ │ └── Tpl.go │ └── Router │ │ └── Tpl.go ├── config │ └── config.go ├── db │ └── db.go ├── global │ └── app.go ├── helper │ └── helper.go ├── log │ └── log.go ├── middle │ ├── RateLimiter.go │ ├── RequestLogger.go │ ├── auth │ │ ├── Claims.go │ │ ├── Func.go │ │ └── JwtAuth.go │ └── casbin │ │ ├── Check.go │ │ └── Enforcer.go ├── queue │ └── queue.go ├── redis │ └── redis.go ├── response │ └── response.go ├── router │ └── router.go ├── snow │ └── snow.go ├── trans │ └── trans.go └── validate │ └── validate.go ├── go.mod ├── go.sum ├── go_study.sql ├── job ├── TestJob.go └── job.go ├── lang ├── en │ └── en.json └── zh-cn │ └── zh-cn.json ├── main.go ├── rbac.conf ├── route └── route.go ├── storage ├── .gitignore └── logs │ └── .gitignore └── vTools ├── tools └── makeCurd.go └── vTools.go /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | /.vscode 3 | /storage/logs/* 4 | /*.exe 5 | /*.exe~ 6 | /*.log 7 | /configs/* 8 | vgo -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 闫春浩 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Queue.md: -------------------------------------------------------------------------------- 1 | ## 使用 asynq 命令行工具 2 | ```text 3 | https://github.com/hibiken/asynq/blob/master/tools/asynq/README.md 4 | ``` 5 | ```text 6 | go install github.com/hibiken/asynq/tools/asynq@latest 7 | ``` 8 | ```text 9 | asynq dash --config .\asynq.yml 10 | ``` 11 | 12 | #### 使用 asynq 可视化工具 【框架未内置,使用只需在app内定义方法路由即可】 13 | ```text 14 | https://github.com/hibiken/asynqmon?tab=readme-ov-file#import-as-a-library 15 | ``` 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Vgo 2 | 3 | ### 📖对go较熟悉的小朋友,可以直接拉取prod分支进行学习。 4 | ### 介绍 📖 5 | 6 | Vgo 是一款基于 Gin 开发的开源服务端框架。 7 | - 使用了Redis、Mysql、JWT、队列、等技术栈。 8 | - 比较适合Golang初学者作为学习项目学习。 9 | - 当前框架内实现了基本的Rbac权限管理(使用casbin)、队列、websocket、文件日志等功能。 10 | - 后续将陆续增加更多功能,欢迎大家共同参与进来。 11 | - 本项目主要是为了学习 Golang 而开发的,所以代码中难免有不足之处,还请大家多多包涵。 12 | 13 | ### 代码仓库 ⭐(记得 Star⭐) 14 | 15 | - Vgo-Github:https://github.com/xuewuzhiijngych/vgo.git 16 | - Vgo-Gitee:https://gitee.com/yan_chunhao_admin/vgo.git 17 | - 18 | - VgoAdmin-Github:https://github.com/xuewuzhiijngych/vgo-admin.git 19 | - VgoAdmin-Gitee:https://gitee.com/yan_chunhao_admin/vgo-admin.git 20 | 21 | ### 安装使用步骤 📔 22 | 23 | - **下载:** 24 | 25 | ```shell 26 | git clone https://github.com/xuewuzhiijngych/vgo.git 27 | ``` 28 | 29 | - **安装:** 30 | 31 | - 使用Mysql8,导入根目录的go_study.sql文件。 32 | - 准备redis 33 | - 修改根目录下的config.yaml文件,配置Mysql、Redis、JWT等信息。 34 | - 根目录的asynq.yml文件是配置asynq命令工具的,不使用,忽略即可。 35 | - 执行以下命令安装依赖包: 36 | 37 | ```shell 38 | go mod tidy 39 | ``` 40 | 41 | - **运行:** 42 | 43 | ```shell 44 | go run main.go 45 | ``` 46 | 47 | ### 项目目录 📚 48 | 49 | ```shell 50 | Vgo 51 | ├─ app # Vite 配置项 52 | ├─ AdminUser # 模块 53 | │ ├─ Bapi # Bapi 后台接口 54 | │ ├─ Api # Api 前台接口 55 | │ ├─ Model # Model 模型 56 | │ ├─ Router # Router 路由 57 | ├─ bootstrap # 框架启动文件 58 | ├─ core # 框架核心文件 59 | │ ├─ ... # 后续出详细介绍(亦可以自己通过源码了解) 60 | ├─ job # 队列 61 | ├─ lang # 翻译字典 62 | ├─ route # 路由 63 | ├─ storage # 日志或静态资源 64 | │ ├─ logs # 日志 65 | ├─ vTools # 命令行工具 66 | ├─ asynq.yml # asynq配置文件 67 | ├─ config.yaml # 框架配置文件 68 | ``` 69 | 70 | ### 前台使用 🌎 71 | - 基于本框架的接口,实现了一个拥有简单Rbac的后台管理系统,具体使用方法请参考VgoAdmin项目。 72 | - 前端项目地址:https://github.com/xuewuzhiijngych/vgo-admin.git 73 | 74 | ## 功能 75 | ### 代码生成 🏢 76 | - 开发时Go版本:go version go1.22.5 windows/amd64 77 | - 版本兼容未测试,预想问题不大。 78 | - 生成基本增删改查的golang代码,可使用命令: 79 | - Curd: 80 | ```shell 81 | go run vTools/vTools.go --method=Curd --module=Product --note=产品 82 | ``` 83 | - 执行代码后,会在app目录下生成一个Product模块,里面包含了增删改查的相关代码。 84 | - 随后需要自己在根目录route/router.go文件中注册路由。【后期实现自动注册】 85 | 86 | ### 权限管理 🔐 87 | - 基于casbin实现的权限管理,可实现用户角色、角色权限、用户权限等多种权限控制。 88 | - 具体使用方法请参考VgoAdmin项目。 89 | 90 | ### Map结合模型验证 🏭 91 | - 见app/User/Api/User.go 的 Register方法 92 | 93 | ### 自定义翻译器 📝 94 | - 翻译文字定义在根目录lang下 95 | - 使用: 96 | ```shell 97 | trans.Trans("手机号不能为空", "哈哈哈",666), 98 | ``` 99 | - 具体见:app/User/Api/User.go 的 Register方法 100 | 101 | ### 后续计划 🔮 102 | - 后续将陆续增加更多功能,欢迎大家共同参与进来。 103 | - 如有任何问题,请联系作者:<601266867@qq.com> -------------------------------------------------------------------------------- /app/AdminUser/Bapi/AdminUser.go: -------------------------------------------------------------------------------- 1 | package AdminUser 2 | 3 | import ( 4 | "errors" 5 | "github.com/gin-gonic/gin" 6 | "github.com/go-sql-driver/mysql" 7 | "golang.org/x/crypto/bcrypt" 8 | "gorm.io/gorm" 9 | "strconv" 10 | AdminUserModel "vgo/app/AdminUser/Model" 11 | "vgo/core/db" 12 | "vgo/core/helper" 13 | "vgo/core/middle/auth" 14 | "vgo/core/middle/casbin" 15 | "vgo/core/response" 16 | ) 17 | 18 | // Index 列表 19 | func Index(ctx *gin.Context) { 20 | var res []AdminUserModel.AdminUser 21 | var total int64 22 | pageNo, err := strconv.Atoi(ctx.DefaultQuery("pageNum", "1")) 23 | if err != nil { 24 | response.Fail(ctx, "页码参数无效", nil) 25 | return 26 | } 27 | Size, err := strconv.Atoi(ctx.DefaultQuery("pageSize", "10")) 28 | if err != nil { 29 | response.Fail(ctx, "每页大小参数无效", nil) 30 | return 31 | } 32 | if err := db.Con().Model(&AdminUserModel.AdminUser{}).Count(&total).Error; err != nil { 33 | response.Fail(ctx, "数据库查询失败", err.Error()) 34 | return 35 | } 36 | if err := db.Con().Order("id desc").Offset((pageNo-1)*Size).Limit(Size).Where("super = ?", 2).Find(&res).Error; err != nil { 37 | response.Fail(ctx, "数据库查询失败", err.Error()) 38 | return 39 | } 40 | totalPage := int(total) / Size 41 | if int(total)%Size != 0 { 42 | totalPage++ 43 | } 44 | response.Success(ctx, "成功", gin.H{ 45 | "pageNum": pageNo, 46 | "total": total, 47 | "pageSize": Size, 48 | "list": res, 49 | }, nil) 50 | } 51 | 52 | // SetRole 设置角色 53 | func SetRole(ctx *gin.Context) { 54 | var codes struct { 55 | ID uint64 `json:"id"` 56 | Roles []string `json:"roles"` 57 | } 58 | if err := helper.VgoShouldBindJSON(ctx, &codes); err != nil { 59 | response.Fail(ctx, "参数错误", err.Error(), nil) 60 | return 61 | } 62 | userID := codes.ID 63 | enforcer := casbin.SetupCasbin() 64 | _, err := enforcer.DeleteRolesForUser(strconv.FormatUint(userID, 10)) 65 | if err != nil { 66 | response.Fail(ctx, err.Error(), nil) 67 | return 68 | } 69 | for _, role := range codes.Roles { 70 | _, err2 := enforcer.AddRoleForUser(strconv.FormatUint(userID, 10), role) 71 | if err2 != nil { 72 | response.Fail(ctx, err2.Error(), nil) 73 | return 74 | } 75 | } 76 | response.Success(ctx, "设置成功", nil, nil) 77 | } 78 | 79 | // GetRole 获取角色 80 | func GetRole(ctx *gin.Context) { 81 | var codes struct { 82 | ID uint64 `json:"id"` 83 | } 84 | if err := helper.VgoShouldBindJSON(ctx, &codes); err != nil { 85 | response.Fail(ctx, "参数错误", err.Error(), nil) 86 | return 87 | } 88 | userID := codes.ID 89 | enforcer := casbin.SetupCasbin() 90 | roles, err := enforcer.GetRolesForUser(strconv.FormatUint(userID, 10)) 91 | if err != nil { 92 | response.Fail(ctx, "获取错误", err.Error(), nil) 93 | return 94 | } 95 | response.Success(ctx, "获取成功", roles, nil) 96 | } 97 | 98 | // Create 创建用户 99 | func Create(ctx *gin.Context) { 100 | var user AdminUserModel.AdminUser 101 | if err := helper.VgoShouldBindJSON(ctx, &user); err != nil { 102 | response.Fail(ctx, "参数错误", err.Error(), nil) 103 | return 104 | } 105 | // 查询已存在的用户 106 | var existingUser AdminUserModel.AdminUser 107 | if err := db.Con().Where("username = ?", user.UserName).First(&existingUser).Error; err != nil { 108 | if !errors.Is(err, gorm.ErrRecordNotFound) { 109 | response.Fail(ctx, "查询用户失败", err.Error(), nil) 110 | return 111 | } 112 | } else { 113 | response.Fail(ctx, "用户名已存在", nil, nil) 114 | return 115 | } 116 | // 对密码进行哈希处理 117 | hashedPassword, err := bcrypt.GenerateFromPassword([]byte(user.Password), bcrypt.DefaultCost) 118 | if err != nil { 119 | response.Fail(ctx, "密码哈希失败", err.Error(), nil) 120 | return 121 | } 122 | user.Password = string(hashedPassword) 123 | // 插入用户数据 124 | if err := db.Con().Create(&user).Error; err != nil { 125 | // 检查是否是唯一键冲突错误 126 | var mysqlErr *mysql.MySQLError 127 | if errors.As(err, &mysqlErr) && mysqlErr.Number == 1062 { 128 | response.Fail(ctx, "用户名已存在", err.Error(), nil) 129 | } 130 | return 131 | } 132 | response.Success(ctx, "成功", user, nil) 133 | } 134 | 135 | // Login 登录 136 | func Login(ctx *gin.Context) { 137 | var user AdminUserModel.AdminUser 138 | if err := helper.VgoShouldBindJSON(ctx, &user); err != nil { 139 | response.Fail(ctx, "参数错误", err.Error(), nil) 140 | return 141 | } 142 | // 查询用户数据 143 | var dbUser AdminUserModel.AdminUser 144 | if err := db.Con().Where("username = ?", user.UserName).First(&dbUser).Error; err != nil { 145 | response.Fail(ctx, "用户名或密码错误001", err.Error(), nil) 146 | return 147 | } 148 | // 验证密码 149 | if err := bcrypt.CompareHashAndPassword([]byte(dbUser.Password), []byte(user.Password)); err != nil { 150 | response.Fail(ctx, "用户名或密码错误002", err.Error(), nil) 151 | return 152 | } 153 | // 获取角色 154 | enforcer := casbin.SetupCasbin() 155 | roles, err := enforcer.GetRolesForUser(strconv.FormatUint(dbUser.ID, 10)) 156 | if err != nil { 157 | response.Fail(ctx, "获取错误", err.Error(), nil) 158 | return 159 | } 160 | // 生成token 161 | res, err := auth.GenAdminToken(ctx, dbUser.ID, roles, dbUser.Super) 162 | if err != nil { 163 | response.Fail(ctx, err.Error(), nil) 164 | return 165 | } 166 | response.Success(ctx, "登录成功", res) 167 | } 168 | 169 | // LogOut 退出登录 170 | func LogOut(ctx *gin.Context) { 171 | userID := ctx.GetUint64("userID") 172 | err := auth.DelAdminToken(ctx, userID) 173 | if err != nil { 174 | return 175 | } 176 | response.Success(ctx, "退出成功", nil) 177 | } 178 | 179 | // Update 更新 180 | func Update(ctx *gin.Context) { 181 | var notice AdminUserModel.AdminUser 182 | if err := helper.VgoShouldBindJSON(ctx, ¬ice); err != nil { 183 | response.Fail(ctx, "参数错误", err.Error(), nil) 184 | return 185 | } 186 | if err := db.Con().Model(&AdminUserModel.AdminUser{}).Where("id = ?", notice.ID).Updates(notice).Error; err != nil { 187 | response.Fail(ctx, "更新失败", err.Error()) 188 | return 189 | } 190 | response.Success(ctx, "成功", nil, nil) 191 | } 192 | 193 | // Delete 删除 194 | func Delete(ctx *gin.Context) { 195 | var ids struct { 196 | ID []uint64 `json:"id"` 197 | } 198 | if err := helper.VgoShouldBindJSON(ctx, &ids); err != nil { 199 | response.Fail(ctx, "参数错误", err.Error(), nil) 200 | return 201 | } 202 | // 删除token 203 | for _, values := range ids.ID { 204 | err := auth.DelAdminToken(ctx, values) 205 | if err != nil { 206 | continue 207 | } 208 | } 209 | if err := db.Con().Delete(&AdminUserModel.AdminUser{}, "id in (?)", ids.ID).Error; err != nil { 210 | response.Fail(ctx, "删除失败", err.Error()) 211 | return 212 | } 213 | response.Success(ctx, "成功", nil, nil) 214 | } 215 | 216 | // UserInfo 用户信息 217 | func UserInfo(ctx *gin.Context) { 218 | userID := ctx.GetUint64("userID") 219 | role := ctx.GetString("Role") 220 | response.Success(ctx, "成功", map[string]interface{}{ 221 | "userID": userID, 222 | "role": role, 223 | "message": "pong", 224 | }, nil) 225 | } 226 | -------------------------------------------------------------------------------- /app/AdminUser/Model/AdminUser.go: -------------------------------------------------------------------------------- 1 | package AdminUser 2 | 3 | import ( 4 | Common "vgo/app/Common/Model" 5 | ) 6 | 7 | // AdminUser 管理员用户 8 | type AdminUser struct { 9 | Common.Model 10 | UserName string `gorm:"column:username;unique;index;default:'';type:varchar(20);not null;comment:用户名" form:"username" json:"username"` 11 | Password string `gorm:"column:password;default:'';not null;comment:密码" form:"password" json:"password"` 12 | UserType string `gorm:"column:user_type;default:'100';not null;comment:用户类型:(100系统用户)" form:"user_type" json:"user_type"` 13 | Nickname string `gorm:"column:nickname;default:'';type:varchar(30);not null;comment:用户昵称" form:"nickname" json:"nickname"` 14 | Phone string `gorm:"column:phone;default:'';type:varchar(11);not null;comment:手机" form:"phone" json:"phone"` 15 | Email string `gorm:"column:email;default:'';type:varchar(50);not null;comment:用户邮箱" form:"email" json:"email"` 16 | Avatar string `gorm:"column:avatar;default:'';type:varchar(255);not null;comment:用户头像" form:"avatar" json:"avatar"` 17 | Signed string `gorm:"column:signed;default:'';type:varchar(255);not null;comment:个人签名" form:"signed" json:"signed"` 18 | Dashboard string `gorm:"column:dashboard;default:'';type:varchar(100);not null;comment:后台首页类型" form:"dashboard" json:"dashboard"` 19 | Status int `gorm:"column:status;default:1;not null;comment:状态 (1正常 2停用)" form:"status" json:"status"` 20 | Super int `gorm:"column:super;default:2;not null;comment:是否超级管理员 (1是 2否)" form:"super" json:"super"` 21 | LoginIP string `gorm:"column:login_ip;default:'';type:varchar(45);not null;comment:最后登陆IP" form:"login_ip" json:"login_ip"` 22 | BackendSetting string `gorm:"column:backend_setting;default:'';type:varchar(500);not null;comment:后台设置数据" form:"backend_setting" json:"backend_setting"` 23 | Remark string `gorm:"column:remark;default:'';type:varchar(255);not null;comment:备注" form:"remark" json:"remark"` 24 | } 25 | -------------------------------------------------------------------------------- /app/AdminUser/Router/AdminUser.go: -------------------------------------------------------------------------------- 1 | package AdminUser 2 | 3 | import ( 4 | AdminUser "vgo/app/AdminUser/Bapi" 5 | "vgo/core/router" 6 | ) 7 | 8 | func CollectRoutes() []router.BaseRoute { 9 | return []router.BaseRoute{ 10 | {"GET", "/admin_user", AdminUser.Index}, 11 | {"POST", "/admin_user/create", AdminUser.Create}, 12 | {"POST", "/admin_user/set/role", AdminUser.SetRole}, 13 | {"POST", "/admin_user/get/role", AdminUser.GetRole}, 14 | {"POST", "/admin_user/delete", AdminUser.Delete}, 15 | {"POST", "/admin_user/logout", AdminUser.LogOut}, 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/Common/Bapi/Common.go: -------------------------------------------------------------------------------- 1 | package Common 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "vgo/core/response" 6 | ) 7 | 8 | // GetGender 获取性别选项 9 | func GetGender(ctx *gin.Context) { 10 | seed := []map[string]interface{}{ 11 | { 12 | "label": "男", 13 | "value": 1, 14 | }, 15 | { 16 | "label": "女", 17 | "value": 1, 18 | }, 19 | } 20 | data := make([]map[string]interface{}, len(seed)) 21 | for k, item := range seed { 22 | data[k] = map[string]interface{}{ 23 | "genderLabel": item["label"], 24 | "genderValue": item["value"], 25 | } 26 | } 27 | response.Success(ctx, "成功", data, nil) 28 | } 29 | -------------------------------------------------------------------------------- /app/Common/Model/Model.go: -------------------------------------------------------------------------------- 1 | package Common 2 | 3 | import ( 4 | "gorm.io/gorm" 5 | "time" 6 | ) 7 | 8 | // Model 基模型 9 | type Model struct { 10 | ID uint64 `gorm:"primarykey" json:"id"` 11 | CreatedAt time.Time `json:"created_at"` 12 | UpdatedAt time.Time `json:"updated_at"` 13 | DeletedAt gorm.DeletedAt `gorm:"index" json:"deleted_at"` 14 | } 15 | -------------------------------------------------------------------------------- /app/Menu/Bapi/Menu.go: -------------------------------------------------------------------------------- 1 | package Menu 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "strconv" 6 | MenuModel "vgo/app/Menu/Model" 7 | Role "vgo/app/Role/Model" 8 | "vgo/core/db" 9 | "vgo/core/helper" 10 | "vgo/core/middle/casbin" 11 | "vgo/core/response" 12 | ) 13 | 14 | // Index 无限极分类菜单结构 15 | func Index(ctx *gin.Context) { 16 | var menus []MenuModel.Menu 17 | var err error 18 | if ctx.GetInt("super") == 1 { // 超级管理员 19 | err = db.Con().Order("sort desc").Find(&menus).Error 20 | } else { 21 | menuIDs := Role.GetMenuIdsByRoleId(ctx.GetUint64("userID")) 22 | err = db.Con().Order("sort desc").Find(&menus, "id in (?)", menuIDs).Error 23 | } 24 | if err != nil { 25 | response.Fail(ctx, "数据库查询失败", err) 26 | return 27 | } 28 | menuTree := MenuModel.BuildMenuTree(menus, 0) 29 | response.Success(ctx, "成功", menuTree, nil) 30 | } 31 | 32 | // Buttons 操作按钮 33 | func Buttons(ctx *gin.Context) { 34 | var data = make(map[string][]string) 35 | var menus []MenuModel.Menu 36 | var err error 37 | 38 | if ctx.GetInt("super") == 1 { // 超级管理员 39 | if err = db.Con().Where("type = ?", 1).Find(&menus).Error; err != nil { 40 | response.Fail(ctx, "数据库查询失败", err) 41 | return 42 | } 43 | for _, menu := range menus { 44 | var buttonMenus []MenuModel.Menu 45 | if err = db.Con().Where("parent_id = ? and type = ?", menu.ID, 2).Find(&buttonMenus).Error; err != nil { 46 | response.Fail(ctx, "数据库查询失败", err) 47 | return 48 | } 49 | if len(buttonMenus) > 0 { 50 | bbt := make([]string, len(buttonMenus)) 51 | for i, buttonMenu := range buttonMenus { 52 | bbt[i] = buttonMenu.Name 53 | } 54 | data[menu.Name] = bbt 55 | } 56 | } 57 | response.Success(ctx, "成功", data, nil) 58 | return 59 | } 60 | menuIDs := Role.GetMenuIdsByRoleId(ctx.GetUint64("userID")) 61 | if err = db.Con().Where("type = ? and id in (?)", 1, menuIDs).Find(&menus).Error; err != nil { 62 | response.Fail(ctx, "数据库查询失败", err) 63 | return 64 | } 65 | // 获取角色 66 | enforcer := casbin.SetupCasbin() 67 | roles, err := enforcer.GetRolesForUser(strconv.FormatUint(ctx.GetUint64("userID"), 10)) 68 | if err != nil { 69 | response.Fail(ctx, "角色获取失败", err) 70 | return 71 | } 72 | for _, menu := range menus { 73 | var buttonMenus []MenuModel.Menu 74 | if err = db.Con().Where("parent_id = ? and type = ?", menu.ID, 2).Find(&buttonMenus).Error; err != nil { 75 | response.Fail(ctx, "数据库查询失败", err) 76 | return 77 | } 78 | if len(buttonMenus) == 0 { 79 | continue 80 | } 81 | bbt := make([]string, 0, len(buttonMenus)) 82 | for _, buttonMenu := range buttonMenus { 83 | if buttonMenu.Name == "" { 84 | continue 85 | } 86 | // 判断按钮是否有权限 87 | hasPermission := false 88 | for _, role := range roles { 89 | if policy, err := enforcer.HasPolicy(role, buttonMenu.Api); err == nil && policy { 90 | hasPermission = true 91 | break 92 | } 93 | } 94 | if hasPermission { 95 | bbt = append(bbt, buttonMenu.Name) 96 | } 97 | } 98 | if len(bbt) > 0 { 99 | data[menu.Name] = bbt 100 | } 101 | } 102 | response.Success(ctx, "成功", data, nil) 103 | } 104 | 105 | // MenuSelect 下拉树结构 106 | type MenuSelect struct { 107 | Value uint64 `json:"value"` 108 | Label string `json:"label"` 109 | Children []MenuSelect `json:"children"` 110 | } 111 | 112 | // convertToMenuSelect 将Menu结构体转换为MenuSelect结构体 113 | func convertToMenuSelect(menu MenuModel.Menu) MenuSelect { 114 | menuSelect := MenuSelect{ 115 | Value: menu.ID, // 假设Menu结构体中有ID字段 116 | Label: menu.Title, // 假设Menu结构体中有Name字段 117 | Children: []MenuSelect{}, 118 | } 119 | for _, child := range menu.Children { 120 | menuSelect.Children = append(menuSelect.Children, convertToMenuSelect(child)) 121 | } 122 | return menuSelect 123 | } 124 | 125 | // GetSelectTree 获取下拉树结构 126 | func GetSelectTree(ctx *gin.Context) { 127 | var menus []MenuModel.Menu 128 | if err := db.Con().Order("sort desc").Find(&menus).Error; err != nil { 129 | response.Fail(ctx, "数据库查询失败", err) 130 | return 131 | } 132 | menuTree := MenuModel.BuildMenuTree(menus, 0) 133 | menuSelects := make([]MenuSelect, len(menuTree)) 134 | for i, menu := range menuTree { 135 | menuSelects[i] = convertToMenuSelect(menu) 136 | } 137 | response.Success(ctx, "查询成功", menuSelects, nil) 138 | } 139 | 140 | // Create 创建 141 | func Create(ctx *gin.Context) { 142 | var product MenuModel.Menu 143 | if err := helper.VgoShouldBindJSON(ctx, &product); err != nil { 144 | response.Fail(ctx, "参数错误", err.Error(), nil) 145 | return 146 | } 147 | db.Con().Create(&product) 148 | response.Success(ctx, "成功", product, nil) 149 | } 150 | 151 | // Update 更新 152 | func Update(ctx *gin.Context) { 153 | var notice MenuModel.Menu 154 | if err := helper.VgoShouldBindJSON(ctx, ¬ice); err != nil { 155 | response.Fail(ctx, "参数错误", err.Error(), nil) 156 | return 157 | } 158 | if err := db.Con().Model(&MenuModel.Menu{}).Where("id = ?", notice.ID).Updates(notice).Error; err != nil { 159 | response.Fail(ctx, "更新失败", err.Error()) 160 | return 161 | } 162 | response.Success(ctx, "成功", nil, nil) 163 | } 164 | 165 | // Delete 删除 166 | func Delete(ctx *gin.Context) { 167 | var ids struct { 168 | ID []int64 `json:"id"` 169 | } 170 | if err := helper.VgoShouldBindJSON(ctx, &ids); err != nil { 171 | response.Fail(ctx, "参数错误", err.Error(), nil) 172 | return 173 | } 174 | if err := db.Con().Delete(&MenuModel.Menu{}, "parent_id in (?)", ids.ID).Error; err != nil { 175 | response.Fail(ctx, "删除失败", err.Error()) 176 | return 177 | } 178 | if err := db.Con().Delete(&MenuModel.Menu{}, "id in (?)", ids.ID).Error; err != nil { 179 | response.Fail(ctx, "删除失败", err.Error()) 180 | return 181 | } 182 | response.Success(ctx, "成功", nil, nil) 183 | } 184 | -------------------------------------------------------------------------------- /app/Menu/Model/Menu.go: -------------------------------------------------------------------------------- 1 | package Menu 2 | 3 | import ( 4 | "gorm.io/gorm" 5 | Common "vgo/app/Common/Model" 6 | ) 7 | 8 | // Menu 菜单 9 | type Menu struct { 10 | Common.Model 11 | ParentId uint64 `gorm:"column:parent_id;type:bigint;not null;default:0;comment:父ID" json:"parent_id"` 12 | Path string `gorm:"column:path;type:varchar(50);not null;default:'';comment:路由访问路径" json:"path"` 13 | Name string `gorm:"column:name;type:varchar(50);not null;default:'';comment:路由name" json:"name"` 14 | Redirect string `gorm:"column:redirect;type:varchar(255);not null;default:'';comment:路由重定向地址" json:"redirect"` 15 | Api string `gorm:"column:api;type:varchar(255);not null;default:'';comment:请求接口地址" json:"api"` 16 | Component string `gorm:"column:component;type:varchar(255);not null;default:'';comment:视图文件路径" json:"component"` 17 | Icon string `gorm:"column:icon;type:varchar(50);not null;default:'';comment:菜单和面包屑对应的图标" json:"icon"` 18 | Title string `gorm:"column:title;type:varchar(50);not null;default:'';comment:路由标题(菜单名称)" json:"title"` 19 | ActiveMenu string `gorm:"column:activeMenu;type:varchar(500);not null;default:'';comment:是否在菜单中隐藏,需要高亮的path" json:"activeMenu"` 20 | IsLink string `gorm:"column:isLink;type:varchar(500);not null;default:'';comment:路由外链时填写的访问地址" json:"isLink"` 21 | IsHide int `gorm:"column:isHide;type:smallint;not null;default:2;comment:是否在菜单中隐藏 (1是 2否)" json:"isHide"` 22 | IsFull int `gorm:"column:isFull;type:smallint;not null;default:2;comment:菜单是否全屏 (1是 2否)" json:"isFull"` 23 | IsAffix int `gorm:"column:isAffix;type:smallint;not null;default:1;comment:菜单是否固定在标签页中 (1是 2否)" json:"isAffix"` 24 | IsKeepAlive int `gorm:"column:isKeepAlive;type:smallint;not null;default:2;comment:当前路由是否缓存 (1是 2否)" json:"isKeepAlive"` 25 | Status int `gorm:"column:status;type:smallint;not null;default:1;comment:状态 (1正常 2停用)" json:"status"` 26 | Type int `gorm:"column:type;type:smallint;not null;default:1;comment:类型 (1菜单2按钮3外链4Iframe)" json:"type"` 27 | Sort int `gorm:"column:sort;type:int;not null;default:0;comment:排序" json:"sort"` 28 | Meta map[string]interface{} `gorm:"-" json:"meta"` // 忽略数据库字段,使用Getter方法 29 | Children []Menu `gorm:"foreignKey:ParentId" json:"children"` 30 | } 31 | 32 | // AfterFind 回调函数,在查询后执行 33 | func (m *Menu) AfterFind(tx *gorm.DB) (err error) { 34 | m.Meta = m.getMetaAttribute() 35 | return 36 | } 37 | 38 | // GetMetaAttribute 获取菜单元数据属性 39 | func (m *Menu) getMetaAttribute() map[string]interface{} { 40 | meta := map[string]interface{}{ 41 | "icon": m.Icon, 42 | "title": m.Title, 43 | "activeMenu": m.ActiveMenu, 44 | "isLink": m.IsLink, 45 | "isHide": m.IsHide == 1, 46 | "isFull": m.IsFull == 1, 47 | "isAffix": m.IsAffix == 1, 48 | "isKeepAlive": m.IsKeepAlive == 1, 49 | } 50 | return meta 51 | } 52 | 53 | // BuildMenuTree 构建菜单树 54 | func BuildMenuTree(menus []Menu, parentID uint64) []Menu { 55 | var tree []Menu 56 | for _, menu := range menus { 57 | if menu.ParentId == parentID { 58 | children := BuildMenuTree(menus, menu.ID) 59 | if len(children) > 0 { 60 | menu.Children = children 61 | } 62 | tree = append(tree, menu) 63 | } 64 | } 65 | return tree 66 | } 67 | -------------------------------------------------------------------------------- /app/Menu/Router/Menu.go: -------------------------------------------------------------------------------- 1 | package Menu 2 | 3 | import ( 4 | Menu "vgo/app/Menu/Bapi" 5 | "vgo/core/router" 6 | ) 7 | 8 | func CollectRoutes() []router.BaseRoute { 9 | return []router.BaseRoute{ 10 | {"GET", "/menu/list", Menu.Index}, 11 | {"GET", "/menu/selectTreeDataSource", Menu.GetSelectTree}, 12 | {"POST", "/menu/create", Menu.Create}, 13 | {"POST", "/menu/update", Menu.Update}, 14 | {"POST", "/menu/delete", Menu.Delete}, 15 | {"GET", "/button/list", Menu.Buttons}, 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/Notice/Api/Notice.go: -------------------------------------------------------------------------------- 1 | package Notice 2 | -------------------------------------------------------------------------------- /app/Notice/Bapi/Notice.go: -------------------------------------------------------------------------------- 1 | package Notice 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "strconv" 6 | NoticeModel "vgo/app/Notice/Model" 7 | "vgo/core/db" 8 | "vgo/core/helper" 9 | "vgo/core/response" 10 | ) 11 | 12 | // Index 列表 13 | func Index(ctx *gin.Context) { 14 | var res []NoticeModel.Notice 15 | var total int64 16 | pageNo, err := strconv.Atoi(ctx.DefaultQuery("pageNum", "1")) 17 | if err != nil { 18 | response.Fail(ctx, "页码参数无效", nil) 19 | return 20 | } 21 | Size, err := strconv.Atoi(ctx.DefaultQuery("pageSize", "10")) 22 | if err != nil { 23 | response.Fail(ctx, "每页大小参数无效", nil) 24 | return 25 | } 26 | if err := db.Con().Model(&NoticeModel.Notice{}).Count(&total).Error; err != nil { 27 | response.Fail(ctx, "数据库查询失败", err.Error()) 28 | return 29 | } 30 | if err := db.Con().Order("id desc").Offset((pageNo - 1) * Size).Limit(Size).Find(&res).Error; err != nil { 31 | response.Fail(ctx, "数据库查询失败", err.Error()) 32 | return 33 | } 34 | totalPage := int(total) / Size 35 | if int(total)%Size != 0 { 36 | totalPage++ 37 | } 38 | response.Success(ctx, "成功", gin.H{ 39 | "pageNum": pageNo, 40 | "total": total, 41 | "pageSize": Size, 42 | "list": res, 43 | }, nil) 44 | } 45 | 46 | // Create 创建 47 | func Create(ctx *gin.Context) { 48 | var product NoticeModel.Notice 49 | if err := helper.VgoShouldBindJSON(ctx, &product); err != nil { 50 | response.Fail(ctx, "参数错误", err.Error(), nil) 51 | return 52 | } 53 | db.Con().Create(&product) 54 | response.Success(ctx, "成功", product, nil) 55 | } 56 | 57 | // Update 更新 58 | func Update(ctx *gin.Context) { 59 | var notice NoticeModel.Notice 60 | if err := helper.VgoShouldBindJSON(ctx, ¬ice); err != nil { 61 | response.Fail(ctx, "参数错误", err.Error(), nil) 62 | return 63 | } 64 | if err := db.Con().Model(&NoticeModel.Notice{}).Where("id = ?", notice.ID).Updates(notice).Error; err != nil { 65 | response.Fail(ctx, "更新失败", err.Error()) 66 | return 67 | } 68 | response.Success(ctx, "成功", nil, nil) 69 | } 70 | 71 | // Delete 删除 72 | func Delete(ctx *gin.Context) { 73 | var ids struct { 74 | ID []int64 `json:"id"` 75 | } 76 | if err := helper.VgoShouldBindJSON(ctx, &ids); err != nil { 77 | response.Fail(ctx, "参数错误", err.Error(), nil) 78 | return 79 | } 80 | if err := db.Con().Delete(&NoticeModel.Notice{}, "id in (?)", ids.ID).Error; err != nil { 81 | response.Fail(ctx, "删除失败", err.Error()) 82 | return 83 | } 84 | response.Success(ctx, "成功", nil, nil) 85 | } 86 | 87 | // Change 改变状态 88 | func Change(ctx *gin.Context) { 89 | var notice NoticeModel.Notice 90 | if err := helper.VgoShouldBindJSON(ctx, ¬ice); err != nil { 91 | response.Fail(ctx, "参数错误", err.Error(), nil) 92 | return 93 | } 94 | if err := db.Con().Model(&NoticeModel.Notice{}).Where("id = ?", notice.ID).Updates(notice).Error; err != nil { 95 | response.Fail(ctx, "更新失败", err.Error()) 96 | return 97 | } 98 | response.Success(ctx, "成功", nil, nil) 99 | 100 | } 101 | -------------------------------------------------------------------------------- /app/Notice/Model/Notice.go: -------------------------------------------------------------------------------- 1 | package Notice 2 | 3 | import Common "vgo/app/Common/Model" 4 | 5 | // Notice 公告 6 | type Notice struct { 7 | Common.Model 8 | Title string `gorm:"type:varchar(255);not null;column:title;default:'';comment:标题;" json:"title"` 9 | Type int `gorm:"type:smallint;not null;column:type;default:0;comment:公告类型(1通知 2公告);" json:"type"` 10 | Status int `gorm:"column:status;type:smallint;not null;default:1;comment:状态 (1启用 2禁用)" json:"status"` 11 | Content string `gorm:"type:text;column:content;comment:公告内容;" json:"content"` 12 | Remark string `gorm:"type:varchar(255);column:remark;default:'';comment:备注;" json:"remark"` 13 | } 14 | -------------------------------------------------------------------------------- /app/Notice/Router/Notice.go: -------------------------------------------------------------------------------- 1 | package Notice 2 | 3 | import ( 4 | Notice "vgo/app/Notice/Bapi" 5 | "vgo/core/router" 6 | ) 7 | 8 | func CollectRoutes() []router.BaseRoute { 9 | return []router.BaseRoute{ 10 | {"GET", "/notice", Notice.Index}, 11 | {"POST", "/notice/create", Notice.Create}, 12 | {"POST", "/notice/update", Notice.Update}, 13 | {"POST", "/notice/change", Notice.Change}, 14 | {"POST", "/notice/delete", Notice.Delete}, 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/Role/Bapi/Role.go: -------------------------------------------------------------------------------- 1 | package Role 2 | 3 | import ( 4 | "errors" 5 | "github.com/gin-gonic/gin" 6 | "github.com/go-sql-driver/mysql" 7 | "strconv" 8 | Menu "vgo/app/Menu/Model" 9 | RoleModel "vgo/app/Role/Model" 10 | "vgo/core/db" 11 | "vgo/core/helper" 12 | "vgo/core/middle/casbin" 13 | "vgo/core/response" 14 | ) 15 | 16 | // Index 列表 17 | func Index(ctx *gin.Context) { 18 | var res []RoleModel.Role 19 | var total int64 20 | pageNo, err := strconv.Atoi(ctx.DefaultQuery("pageNum", "1")) 21 | if err != nil { 22 | response.Fail(ctx, "页码参数无效", nil) 23 | return 24 | } 25 | Size, err := strconv.Atoi(ctx.DefaultQuery("pageSize", "10")) 26 | if err != nil { 27 | response.Fail(ctx, "每页大小参数无效", nil) 28 | return 29 | } 30 | if err := db.Con().Model(&RoleModel.Role{}).Count(&total).Error; err != nil { 31 | response.Fail(ctx, "数据库查询失败", err.Error()) 32 | return 33 | } 34 | if err := db.Con().Order("id desc").Offset((pageNo - 1) * Size).Limit(Size).Find(&res).Error; err != nil { 35 | response.Fail(ctx, "数据库查询失败", err.Error()) 36 | return 37 | } 38 | totalPage := int(total) / Size 39 | if int(total)%Size != 0 { 40 | totalPage++ 41 | } 42 | response.Success(ctx, "成功", gin.H{ 43 | "pageNum": pageNo, 44 | "total": total, 45 | "pageSize": Size, 46 | "list": res, 47 | }, nil) 48 | } 49 | 50 | // GetAll 获取全部 51 | func GetAll(ctx *gin.Context) { 52 | var res []RoleModel.Role 53 | if err := db.Con().Order("id desc").Find(&res).Error; err != nil { 54 | response.Fail(ctx, "数据库查询失败", err.Error()) 55 | return 56 | } 57 | response.Success(ctx, "成功", res, nil) 58 | } 59 | 60 | // Create 创建 61 | func Create(ctx *gin.Context) { 62 | var role RoleModel.Role 63 | if err := helper.VgoShouldBindJSON(ctx, &role); err != nil { 64 | response.Fail(ctx, "参数错误", err.Error(), nil) 65 | return 66 | } 67 | // 插入数据 68 | if err := db.Con().Create(&role).Error; err != nil { 69 | // 检查是否是唯一键冲突错误 70 | var mysqlErr *mysql.MySQLError 71 | if errors.As(err, &mysqlErr) && mysqlErr.Number == 1062 { 72 | response.Fail(ctx, "角色标识已存在", err.Error(), nil) 73 | } 74 | return 75 | } 76 | response.Success(ctx, "成功", role, nil) 77 | } 78 | 79 | // SetMenu 设置菜单 80 | func SetMenu(ctx *gin.Context) { 81 | var codes struct { 82 | ID uint64 `json:"id"` 83 | Menus []uint64 `json:"menus"` 84 | } 85 | if err := helper.VgoShouldBindJSON(ctx, &codes); err != nil { 86 | response.Fail(ctx, "参数错误", err.Error(), nil) 87 | return 88 | } 89 | roleID := codes.ID 90 | // 清理原有菜单 91 | if err := db.Con().Delete(&RoleModel.RoleMenu{}, "role_id = ?", roleID).Error; err != nil { 92 | response.Fail(ctx, "菜单清理失败", err.Error()) 93 | return 94 | } 95 | // 角色信息 96 | var role RoleModel.Role 97 | db.Con().First(&role, roleID) 98 | // 清理原有策略 99 | enforcer := casbin.SetupCasbin() 100 | _, err := enforcer.RemoveFilteredPolicy(0, role.Code) 101 | if err != nil { 102 | response.Fail(ctx, "策略清理失败", err.Error()) 103 | return 104 | } 105 | // 写入菜单 106 | var dbMenus []Menu.Menu 107 | db.Con().Where("id IN ?", codes.Menus).Find(&dbMenus) 108 | menuMap := make(map[int]Menu.Menu) 109 | for _, dbMenu := range dbMenus { 110 | menuMap[int(dbMenu.ID)] = dbMenu 111 | } 112 | // 写入角色菜单关联和策略 113 | for _, menu := range codes.Menus { 114 | var item RoleModel.RoleMenu 115 | item.RoleId = roleID 116 | item.MenuId = menu 117 | dbMenu, exists := menuMap[int(menu)] 118 | if exists { 119 | // 写入策略 120 | if dbMenu.Api != "" { 121 | _, err2 := enforcer.AddPolicy(role.Code, dbMenu.Api) 122 | if err2 != nil { 123 | response.Fail(ctx, "策略写入失败", err2.Error()) 124 | return 125 | } 126 | } 127 | } 128 | if err := db.Con().Create(&item).Error; err != nil { 129 | response.Fail(ctx, err.Error(), err.Error()) 130 | return 131 | } 132 | } 133 | response.Success(ctx, "设置成功", nil, nil) 134 | } 135 | 136 | // GetMenu 获取菜单 137 | func GetMenu(ctx *gin.Context) { 138 | var codes struct { 139 | ID uint64 `json:"id"` 140 | } 141 | if err := helper.VgoShouldBindJSON(ctx, &codes); err != nil { 142 | response.Fail(ctx, "参数错误", err.Error(), nil) 143 | return 144 | } 145 | var res []RoleModel.RoleMenu 146 | if err := db.Con().Where("role_id = ?", codes.ID).Find(&res).Error; err != nil { 147 | response.Fail(ctx, "数据库查询失败", err.Error()) 148 | return 149 | } 150 | response.Success(ctx, "成功", res, nil) 151 | } 152 | 153 | // Update 更新 154 | func Update(ctx *gin.Context) { 155 | var notice RoleModel.Role 156 | if err := helper.VgoShouldBindJSON(ctx, ¬ice); err != nil { 157 | response.Fail(ctx, "参数错误", err.Error(), nil) 158 | return 159 | } 160 | if err := db.Con().Model(&RoleModel.Role{}).Where("id = ?", notice.ID).Updates(notice).Error; err != nil { 161 | response.Fail(ctx, "更新失败", err.Error()) 162 | return 163 | } 164 | response.Success(ctx, "成功", nil, nil) 165 | } 166 | 167 | // Delete 删除 168 | func Delete(ctx *gin.Context) { 169 | var ids struct { 170 | ID []int64 `json:"id"` 171 | } 172 | if err := helper.VgoShouldBindJSON(ctx, &ids); err != nil { 173 | response.Fail(ctx, "参数错误", err.Error(), nil) 174 | return 175 | } 176 | if err := db.Con().Delete(&RoleModel.Role{}, "id in (?)", ids.ID).Error; err != nil { 177 | response.Fail(ctx, "删除失败", err.Error()) 178 | return 179 | } 180 | response.Success(ctx, "成功", nil, nil) 181 | } 182 | 183 | // Change 改变状态 184 | func Change(ctx *gin.Context) { 185 | var notice RoleModel.Role 186 | if err := helper.VgoShouldBindJSON(ctx, ¬ice); err != nil { 187 | response.Fail(ctx, "参数错误", err.Error(), nil) 188 | return 189 | } 190 | if err := db.Con().Model(&RoleModel.Role{}).Where("id = ?", notice.ID).Updates(notice).Error; err != nil { 191 | response.Fail(ctx, "更新失败", err.Error()) 192 | return 193 | } 194 | response.Success(ctx, "成功", nil, nil) 195 | 196 | } 197 | -------------------------------------------------------------------------------- /app/Role/Model/Role.go: -------------------------------------------------------------------------------- 1 | package Role 2 | 3 | import ( 4 | Common "vgo/app/Common/Model" 5 | ) 6 | 7 | // Role 角色 8 | type Role struct { 9 | Common.Model 10 | Name string `gorm:"column:name;type:varchar(50);not null;default:'';comment:角色名称" json:"name"` 11 | Code string `gorm:"column:code;type:varchar(50);unique;not null;default:'';comment:角色代码" json:"code"` 12 | } 13 | -------------------------------------------------------------------------------- /app/Role/Model/RoleMenu.go: -------------------------------------------------------------------------------- 1 | package Role 2 | 3 | import ( 4 | "strconv" 5 | Common "vgo/app/Common/Model" 6 | "vgo/core/db" 7 | "vgo/core/middle/casbin" 8 | ) 9 | 10 | // RoleMenu 角色菜单 11 | type RoleMenu struct { 12 | Common.Model 13 | RoleId uint64 `gorm:"column:role_id;not null;default:0;comment:角色ID" json:"role_id"` 14 | MenuId uint64 `gorm:"column:menu_id;not null;default:0;comment:菜单ID" json:"menu_id"` 15 | } 16 | 17 | // GetMenuIdsByRoleId 获取角色菜单ID列表 18 | func GetMenuIdsByRoleId(userID uint64) []uint64 { 19 | // 获取角色 20 | enforcer := casbin.SetupCasbin() 21 | roles, err := enforcer.GetRolesForUser(strconv.FormatUint(userID, 10)) 22 | if err != nil { 23 | return nil 24 | } 25 | var dbRoles []Role 26 | db.Con().Find(&dbRoles, "code in (?)", roles) 27 | roleIDs := make([]uint64, 0) 28 | for _, rid := range dbRoles { 29 | roleIDs = append(roleIDs, rid.ID) 30 | } 31 | // 获取角色菜单关联 32 | var roleMenu []RoleMenu 33 | db.Con().Find(&roleMenu, "role_id in (?)", roleIDs) 34 | menuIDs := make([]uint64, 0) 35 | for _, roleMenu := range roleMenu { 36 | menuIDs = append(menuIDs, roleMenu.MenuId) 37 | } 38 | return menuIDs 39 | } 40 | -------------------------------------------------------------------------------- /app/Role/Router/Role.go: -------------------------------------------------------------------------------- 1 | package Role 2 | 3 | import ( 4 | Role "vgo/app/Role/Bapi" 5 | "vgo/core/router" 6 | ) 7 | 8 | func CollectRoutes() []router.BaseRoute { 9 | return []router.BaseRoute{ 10 | {"GET", "/role", Role.Index}, 11 | {"POST", "/role/create", Role.Create}, 12 | {"POST", "/role/update", Role.Update}, 13 | {"POST", "/role/delete", Role.Delete}, 14 | {"GET", "/role/allDataSource", Role.GetAll}, 15 | {"POST", "/role/set/menu", Role.SetMenu}, 16 | {"POST", "/role/get/menu", Role.GetMenu}, 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/System/Bapi/System.go: -------------------------------------------------------------------------------- 1 | package System 2 | 3 | import ( 4 | "encoding/json" 5 | "github.com/gin-gonic/gin" 6 | "io" 7 | "net/http" 8 | "vgo/core/response" 9 | ) 10 | 11 | // GetBingBackgroundImage 获取必应每日背景图 12 | func GetBingBackgroundImage(ctx *gin.Context) { 13 | isAbroad := false 14 | var url string 15 | if isAbroad { 16 | url = "https://bing.com/th?id=OHR.TateishiPark_ZH-CN9903501398_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp" 17 | } else { 18 | url = "https://cn.bing.com/th?id=OHR.TateishiPark_ZH-CN9903501398_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp" 19 | } 20 | response.Success(ctx, "成功", map[string]string{"url": url}, nil) 21 | } 22 | 23 | // getBingImageURL 联网获取必应每日背景图URL 24 | func getBingImageURL(isAbroad bool, defaultURL string) (string, error) { 25 | var domain string 26 | if isAbroad { 27 | domain = "https://cn.bing.com" 28 | } else { 29 | domain = "https://bing.com" 30 | } 31 | resp, err := http.Get(domain + "/HPImageArchive.aspx?format=js&idx=0&n=1") 32 | if err != nil { 33 | return defaultURL, err 34 | } 35 | defer resp.Body.Close() 36 | body, err := io.ReadAll(resp.Body) 37 | if err != nil { 38 | return defaultURL, err 39 | } 40 | var content struct { 41 | Images []struct { 42 | URL string `json:"url"` 43 | } `json:"images"` 44 | } 45 | if err := json.Unmarshal(body, &content); err != nil { 46 | return defaultURL, err 47 | } 48 | if len(content.Images) > 0 && content.Images[0].URL != "" { 49 | return domain + content.Images[0].URL, nil 50 | } 51 | return defaultURL, nil 52 | } 53 | -------------------------------------------------------------------------------- /app/Test/Test.go: -------------------------------------------------------------------------------- 1 | package Test 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "vgo/core/response" 6 | "vgo/core/snow" 7 | ) 8 | 9 | func Index(ctx *gin.Context) { 10 | //err := db.Con().AutoMigrate(&User.User{}) 11 | //if err != nil { 12 | // return 13 | //} 14 | //response.Success(ctx, "666", nil) 15 | //return 16 | response.Success(ctx, "666", nil) 17 | } 18 | 19 | func Index2(ctx *gin.Context) { 20 | id := snow.Node().Generate() 21 | response.Success(ctx, "Generated ID", id) 22 | } 23 | -------------------------------------------------------------------------------- /app/Upload/Api/ImgUpload.go: -------------------------------------------------------------------------------- 1 | package Upload 2 | 3 | import ( 4 | "fmt" 5 | "github.com/gabriel-vasile/mimetype" 6 | "github.com/gin-gonic/gin" 7 | "io" 8 | "os" 9 | "path/filepath" 10 | "strconv" 11 | "time" 12 | "vgo/core/global" 13 | "vgo/core/response" 14 | "vgo/core/snow" 15 | ) 16 | 17 | // ImgUpload 图片上传 18 | func ImgUpload(ctx *gin.Context) { 19 | // 获取上传的文件 20 | file, err := ctx.FormFile("file") 21 | if err != nil { 22 | response.Fail(ctx, "获取文件失败", err.Error(), nil) 23 | return 24 | } 25 | 26 | // 检查文件大小 27 | const maxFileSize = 10 * 1024 * 1024 // 10MB 28 | if file.Size > maxFileSize { 29 | response.Fail(ctx, fmt.Sprintf("文件大小不能超过 %d MB", maxFileSize/(1024*1024)), nil) 30 | return 31 | } 32 | 33 | // 打开文件 34 | src, err := file.Open() 35 | if err != nil { 36 | response.Fail(ctx, "无法打开文件", err.Error()) 37 | return 38 | } 39 | defer src.Close() 40 | 41 | // 读取文件内容 42 | fileContent, err := io.ReadAll(src) 43 | if err != nil { 44 | response.Fail(ctx, "无法读取文件内容", err.Error()) 45 | return 46 | } 47 | 48 | // 使用 mimetype 库获取文件的真实类型 49 | mime := mimetype.Detect(fileContent) 50 | fileType := mime.String() 51 | 52 | // 检查文件类型 53 | allowedTypes := map[string]bool{ 54 | "image/jpeg": true, 55 | "image/png": true, 56 | "image/gif": true, 57 | //..... 58 | } 59 | 60 | if !allowedTypes[fileType] { 61 | response.Fail(ctx, "不支持的文件类型", nil) 62 | return 63 | } 64 | 65 | // 获取当前日期 66 | now := time.Now() 67 | timeStr := now.Format("20060101") 68 | 69 | // 创建保存文件的目标路径,包含年月日子文件夹 70 | dstDir := filepath.Join("storage", "uploads", "img", timeStr) 71 | 72 | // 判断文件夹是否存在,如果不存在则创建 73 | if _, err := os.Stat(dstDir); os.IsNotExist(err) { 74 | err := os.MkdirAll(dstDir, os.ModePerm) 75 | if err != nil { 76 | response.Fail(ctx, "创建文件夹失败", err.Error()) 77 | return 78 | } 79 | } 80 | 81 | // 文件重命名 82 | id := snow.Node().Generate() 83 | ext := filepath.Ext(file.Filename) // 获取文件的后缀 84 | newFileName := strconv.FormatInt(int64(id), 10) + ext 85 | dst := filepath.Join(dstDir, newFileName) 86 | respUrl := "/storage/uploads/img/" + timeStr + "/" + newFileName 87 | 88 | // 打开上传的文件【上一次的读取操作会将文件的读写指针移到文件末尾】 89 | src, err = file.Open() 90 | if err != nil { 91 | response.Fail(ctx, "打开文件失败", err.Error()) 92 | return 93 | } 94 | defer src.Close() 95 | 96 | // 创建目标文件 97 | out, err := os.Create(dst) 98 | if err != nil { 99 | response.Fail(ctx, "创建目标文件失败", err.Error()) 100 | return 101 | } 102 | defer out.Close() 103 | 104 | // 将上传的文件内容复制到目标文件 105 | _, err = io.Copy(out, src) 106 | if err != nil { 107 | response.Fail(ctx, "保存文件失败", err.Error()) 108 | return 109 | } 110 | imgDomain := global.App.Config.App.ImgDomain 111 | response.Success(ctx, "文件上传成功", gin.H{ 112 | "dbUrl": respUrl, 113 | "fileUrl": imgDomain + respUrl, 114 | }, nil) 115 | 116 | } 117 | -------------------------------------------------------------------------------- /app/Upload/Api/VideoUpload.go: -------------------------------------------------------------------------------- 1 | package Upload 2 | 3 | import ( 4 | "fmt" 5 | "github.com/gabriel-vasile/mimetype" 6 | "github.com/gin-gonic/gin" 7 | "io" 8 | "os" 9 | "path/filepath" 10 | "strconv" 11 | "time" 12 | "vgo/core/global" 13 | "vgo/core/response" 14 | "vgo/core/snow" 15 | ) 16 | 17 | // VideoUpload 视频上传 18 | func VideoUpload(ctx *gin.Context) { 19 | // 获取上传的文件 20 | file, err := ctx.FormFile("file") 21 | if err != nil { 22 | response.Fail(ctx, "获取文件失败", err.Error(), nil) 23 | return 24 | } 25 | 26 | // 检查文件大小 27 | const maxFileSize = 50 * 1024 * 1024 // 50MB 28 | if file.Size > maxFileSize { 29 | response.Fail(ctx, fmt.Sprintf("文件大小不能超过 %d MB", maxFileSize/(1024*1024)), nil) 30 | return 31 | } 32 | 33 | // 打开文件 34 | src, err := file.Open() 35 | if err != nil { 36 | response.Fail(ctx, "无法打开文件", err.Error()) 37 | return 38 | } 39 | defer src.Close() 40 | 41 | // 读取 42 | fileContent, err := io.ReadAll(src) 43 | if err != nil { 44 | response.Fail(ctx, "无法读取文件内容", err.Error()) 45 | return 46 | } 47 | 48 | // 获取文件的真实类型 49 | mime := mimetype.Detect(fileContent) 50 | fileType := mime.String() 51 | 52 | // 检查文件类型 53 | allowedTypes := map[string]bool{ 54 | "video/mp4": true, 55 | //..... 56 | } 57 | 58 | if !allowedTypes[fileType] { 59 | response.Fail(ctx, "不支持的文件类型", nil) 60 | return 61 | } 62 | 63 | // 获取当前日期 64 | now := time.Now() 65 | timeStr := now.Format("20060101") 66 | 67 | // 创建保存文件的目标路径,包含年月日子文件夹 68 | dstDir := filepath.Join("storage", "uploads", "video", timeStr) 69 | 70 | // 判断文件夹是否存在,如果不存在则创建 71 | if _, err := os.Stat(dstDir); os.IsNotExist(err) { 72 | err := os.MkdirAll(dstDir, os.ModePerm) 73 | if err != nil { 74 | response.Fail(ctx, "创建文件夹失败", err.Error()) 75 | return 76 | } 77 | } 78 | 79 | // 文件重命名 80 | id := snow.Node().Generate() 81 | ext := filepath.Ext(file.Filename) // 获取文件的后缀 82 | newFileName := strconv.FormatInt(int64(id), 10) + ext 83 | dst := filepath.Join(dstDir, newFileName) 84 | respUrl := "/storage/uploads/video/" + timeStr + "/" + newFileName 85 | 86 | // 打开上传的文件【上一次的读取操作会将文件的读写指针移到文件末尾】 87 | src, err = file.Open() 88 | if err != nil { 89 | response.Fail(ctx, "打开文件失败", err.Error()) 90 | return 91 | } 92 | defer src.Close() 93 | 94 | // 创建目标文件 95 | out, err := os.Create(dst) 96 | if err != nil { 97 | response.Fail(ctx, "创建目标文件失败", err.Error()) 98 | return 99 | } 100 | defer out.Close() 101 | 102 | // 将上传的文件内容复制到目标文件 103 | _, err = io.Copy(out, src) 104 | if err != nil { 105 | response.Fail(ctx, "保存文件失败", err.Error()) 106 | return 107 | } 108 | imgDomain := global.App.Config.App.ImgDomain 109 | response.Success(ctx, "文件上传成功", gin.H{ 110 | "dbUrl": respUrl, 111 | "fileUrl": imgDomain + respUrl, 112 | }, nil) 113 | 114 | } 115 | -------------------------------------------------------------------------------- /app/Upload/Router/Upload.go: -------------------------------------------------------------------------------- 1 | package Upload 2 | 3 | import ( 4 | Upload "vgo/app/Upload/Api" 5 | "vgo/core/router" 6 | ) 7 | 8 | func CollectRoutes() []router.BaseRoute { 9 | return []router.BaseRoute{ 10 | {"POST", "/upload/img", Upload.ImgUpload}, // 图片上传 11 | {"POST", "/upload/video", Upload.VideoUpload}, // 视频上传 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/User/Api/User.go: -------------------------------------------------------------------------------- 1 | package User 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | User "vgo/app/User/Model" 6 | "vgo/core/db" 7 | "vgo/core/helper" 8 | "vgo/core/middle/auth" 9 | "vgo/core/response" 10 | "vgo/core/trans" 11 | "vgo/core/validate" 12 | ) 13 | 14 | // Register 注册 15 | func Register(ctx *gin.Context) { 16 | var user User.User 17 | if err := helper.VgoShouldBindJSON(ctx, &user); err != nil { 18 | response.Fail(ctx, "参数错误", err.Error(), nil) 19 | return 20 | } 21 | 22 | // 验证规则 23 | rules := map[string]map[string]string{ 24 | "Phone": { 25 | "required": trans.Trans("手机号不能为空", "哈哈哈", 666), 26 | }, 27 | "Password": { 28 | "required": "密码不能为空66666", 29 | }, 30 | } 31 | // 验证 32 | if res, err := validate.Do(user, rules); !res { 33 | response.Fail(ctx, err, nil) 34 | return 35 | } 36 | 37 | // 插入数据 38 | if err := db.Con().Create(&user).Error; err != nil { 39 | response.Fail(ctx, "注册失败", err.Error(), nil) 40 | return 41 | } 42 | response.Success(ctx, "成功", user, nil) 43 | } 44 | 45 | // GetToken 获取token 46 | func GetToken(ctx *gin.Context) { 47 | res, err := auth.GenUserToken(ctx, 12) 48 | if err != nil { 49 | response.Fail(ctx, "获取失败", nil) 50 | } 51 | response.Success(ctx, "成功", res) 52 | } 53 | 54 | // Setback 设置黑名单 55 | func Setback(ctx *gin.Context) { 56 | back := ctx.PostForm("back") 57 | auth.PutApiTokenInvalidateToken(ctx, back) 58 | response.Success(ctx, "成功", nil) 59 | } 60 | 61 | // Personal 用户信息 62 | func Personal(ctx *gin.Context) { 63 | userID := ctx.GetString("userID") 64 | response.Success(ctx, "成功", map[string]interface{}{ 65 | "userID": userID, 66 | "message": "pong", 67 | }, nil) 68 | } 69 | -------------------------------------------------------------------------------- /app/User/Model/User.go: -------------------------------------------------------------------------------- 1 | package User 2 | 3 | import ( 4 | Common "vgo/app/Common/Model" 5 | ) 6 | 7 | // User 用户 8 | type User struct { 9 | Common.Model 10 | Phone string `gorm:"column:phone;default:'';type:varchar(11);not null;comment:手机" validate:"required" json:"phone"` 11 | Password string `gorm:"column:password;default:'';not null;comment:密码" validate:"required" json:"password"` 12 | PId uint64 `gorm:"column:pid;type:bigint;not null;default:0;comment:父ID" validate:"required" json:"pid"` 13 | RealName string `gorm:"column:real_name;default:'';type:varchar(255);not null;comment:真实姓名" validate:"required" json:"real_name"` 14 | IdCard string `gorm:"column:id_card;default:'';type:varchar(255);not null;comment:身份证号码" validate:"required" json:"id_card"` 15 | } 16 | -------------------------------------------------------------------------------- /app/User/Router/User.go: -------------------------------------------------------------------------------- 1 | package User 2 | 3 | import ( 4 | User "vgo/app/User/Api" 5 | "vgo/core/router" 6 | ) 7 | 8 | func CollectRoutes() []router.BaseRoute { 9 | return []router.BaseRoute{ 10 | {"GET", "/user/personal", User.Personal}, 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /app/Ws/Ws.go: -------------------------------------------------------------------------------- 1 | package Ws 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "github.com/gin-gonic/gin" 7 | "net/http" 8 | "strconv" 9 | "strings" 10 | "sync" 11 | "time" 12 | "vgo/core/global" 13 | "vgo/core/helper" 14 | "vgo/core/response" 15 | "vgo/core/snow" 16 | 17 | "github.com/gorilla/websocket" 18 | ) 19 | 20 | var ( 21 | upgrader = websocket.Upgrader{ 22 | HandshakeTimeout: time.Second * 10, 23 | ReadBufferSize: 1024, 24 | WriteBufferSize: 1024, 25 | CheckOrigin: func(r *http.Request) bool { 26 | origins := global.App.Config.App.ApiOrigins 27 | allowedOrigins := strings.Split(origins, ",") 28 | // 逗号分隔的字符串 29 | origin := r.Header.Get("Origin") 30 | for _, allowedOrigin := range allowedOrigins { 31 | if origin == allowedOrigin { 32 | return true 33 | } 34 | } 35 | return false 36 | }, 37 | } 38 | Connections = make(map[int64]*websocket.Conn) 39 | mu sync.Mutex 40 | ) 41 | 42 | // Link 链接WebSocket 43 | func Link(ctx *gin.Context) { 44 | ws, err := upgrader.Upgrade(ctx.Writer, ctx.Request, nil) 45 | if err != nil { 46 | fmt.Println(err) 47 | return 48 | } 49 | defer func() { 50 | err := ws.Close() 51 | if err != nil { 52 | fmt.Println(err) 53 | } 54 | }() 55 | 56 | // 生成唯一ID 57 | id := snow.Node().Generate() 58 | 59 | // 存储连接 60 | mu.Lock() 61 | Connections[int64(id)] = ws 62 | mu.Unlock() 63 | 64 | // 通知客户端其ID 65 | err = ws.WriteMessage(websocket.TextMessage, []byte("Your ID: "+strconv.FormatInt(int64(id), 10))) 66 | if err != nil { 67 | fmt.Println(err) 68 | return 69 | } 70 | 71 | // 处理WebSocket消息 72 | for { 73 | messageType, p, err := ws.ReadMessage() 74 | if err != nil { 75 | fmt.Println(err) 76 | mu.Lock() 77 | delete(Connections, int64(id)) 78 | mu.Unlock() 79 | return 80 | } 81 | switch messageType { 82 | case websocket.TextMessage: 83 | fmt.Printf("处理文本消息, %s\n", string(p)) 84 | err := ws.WriteMessage(websocket.TextMessage, p) 85 | if err != nil { 86 | fmt.Println(err) 87 | return 88 | } 89 | case websocket.BinaryMessage: 90 | fmt.Println("处理二进制消息") 91 | case websocket.CloseMessage: 92 | fmt.Println("关闭websocket连接") 93 | mu.Lock() 94 | delete(Connections, int64(id)) 95 | mu.Unlock() 96 | return 97 | case websocket.PingMessage: 98 | fmt.Println("处理ping消息") 99 | err := ws.WriteMessage(websocket.PongMessage, []byte("ping")) 100 | if err != nil { 101 | fmt.Println(err) 102 | return 103 | } 104 | case websocket.PongMessage: 105 | fmt.Println("处理pong消息") 106 | err := ws.WriteMessage(websocket.PongMessage, []byte("pong")) 107 | if err != nil { 108 | fmt.Println(err) 109 | return 110 | } 111 | default: 112 | fmt.Printf("未知消息类型: %d\n", messageType) 113 | return 114 | } 115 | } 116 | } 117 | 118 | // sendMessageToClient 发送消息给客户端 119 | func sendMessageToClient(id int64, message []byte) error { 120 | mu.Lock() 121 | defer mu.Unlock() 122 | if conn, ok := Connections[id]; ok { 123 | return conn.WriteMessage(websocket.TextMessage, message) 124 | } 125 | return fmt.Errorf("连接ID %v 不存在", id) 126 | } 127 | 128 | // Send 发送消息 129 | func Send(ctx *gin.Context) { 130 | var params struct { 131 | ID int64 `json:"id"` 132 | Message string `json:"message"` 133 | } 134 | if err := helper.VgoShouldBindJSON(ctx, ¶ms); err != nil { 135 | response.Fail(ctx, "参数错误", err.Error(), nil) 136 | return 137 | } 138 | err := sendMessageToClient(params.ID, []byte(params.Message)) 139 | if err != nil { 140 | response.Fail(ctx, err.Error(), nil) 141 | return 142 | } else { 143 | response.Success(ctx, "发送成功", nil) 144 | return 145 | } 146 | } 147 | 148 | // SendToAll 发送所有消息 149 | func SendToAll(ctx *gin.Context) { 150 | var params struct { 151 | Type string `json:"type"` 152 | KeyWords string `json:"key_words"` 153 | TimeOut uint64 `json:"time_out"` 154 | } 155 | if err := helper.VgoShouldBindJSON(ctx, ¶ms); err != nil { 156 | response.Fail(ctx, "参数错误", err.Error(), nil) 157 | return 158 | } 159 | 160 | byteParams, err := json.Marshal(params) 161 | if err != nil { 162 | response.Fail(ctx, "参数错误", err.Error(), nil) 163 | return 164 | } 165 | 166 | mu.Lock() 167 | defer mu.Unlock() 168 | for id, conn := range Connections { 169 | if err := conn.WriteMessage(websocket.TextMessage, byteParams); err != nil { 170 | fmt.Printf("发送消息到客户端 %d 失败: %v\n", id, err) 171 | } 172 | } 173 | 174 | response.Success(ctx, "发送成功", nil) 175 | } 176 | -------------------------------------------------------------------------------- /app/Ws/testWs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 | 7 |公告1
', ''); 199 | INSERT INTO `notices` VALUES (2, '2024-08-30 10:11:10.500', '2024-09-02 16:43:15.248', '2024-09-02 17:09:33.554', '公告222', 0, 1, '公告222公告222公告222公告222公告222
', ''); 200 | INSERT INTO `notices` VALUES (3, '2024-08-30 10:11:30.438', '2024-08-30 10:11:30.438', '2024-08-30 10:11:33.181', '哈哈哈哈', 0, 1, '哈哈哈哈哈哈哈哈哈哈哈哈
', ''); 201 | INSERT INTO `notices` VALUES (4, '2024-08-30 10:12:53.230', '2024-08-30 10:12:53.230', '2024-08-30 10:12:56.246', '山东省', 0, 1, '山东省山东省山东省
', ''); 202 | INSERT INTO `notices` VALUES (5, '2024-09-02 16:48:58.452', '2024-09-02 16:48:58.452', '2024-09-02 16:49:01.192', '颠三倒四多', 0, 1, '是的是的
', ''); 203 | INSERT INTO `notices` VALUES (6, '2024-09-02 16:52:58.634', '2024-09-02 16:52:58.634', '2024-09-02 17:09:44.025', '大啊大大', 0, 1, '颠三倒四多
', ''); 204 | INSERT INTO `notices` VALUES (7, '2024-09-02 17:09:41.514', '2024-09-02 17:09:41.514', '2024-09-02 17:10:50.537', '防守打法收到', 0, 1, '防守打法收到防守打法收到防守打法收到防守打法收到防守打法收到
', ''); 205 | INSERT INTO `notices` VALUES (8, '2024-09-02 17:10:48.682', '2024-09-02 17:10:48.682', '2024-09-02 17:16:03.498', '4443434', 0, 1, '都是
', ''); 206 | INSERT INTO `notices` VALUES (9, '2024-09-02 17:16:01.679', '2024-09-09 08:53:50.063', NULL, '是的是的', 0, 1, '颠三倒四
', ''); 207 | INSERT INTO `notices` VALUES (10, '2024-09-02 17:17:11.721', '2024-09-02 17:17:11.721', '2024-09-02 17:17:13.786', '撒旦法水电费', 0, 1, '发的范德萨发的
', ''); 208 | INSERT INTO `notices` VALUES (11, '2024-09-03 11:45:46.071', '2024-09-03 11:45:46.071', '2024-09-03 11:45:48.224', '是多少颠三倒四', 0, 1, '但是时代大厦
', ''); 209 | 210 | -- ---------------------------- 211 | -- Table structure for role_menus 212 | -- ---------------------------- 213 | DROP TABLE IF EXISTS `role_menus`; 214 | CREATE TABLE `role_menus` ( 215 | `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT, 216 | `created_at` datetime(3) NULL DEFAULT NULL, 217 | `updated_at` datetime(3) NULL DEFAULT NULL, 218 | `deleted_at` datetime(3) NULL DEFAULT NULL, 219 | `role_id` bigint UNSIGNED NOT NULL DEFAULT 0 COMMENT '角色ID', 220 | `menu_id` bigint UNSIGNED NOT NULL DEFAULT 0 COMMENT '菜单ID', 221 | PRIMARY KEY (`id`) USING BTREE, 222 | INDEX `idx_role_menus_deleted_at`(`deleted_at` ASC) USING BTREE 223 | ) ENGINE = InnoDB AUTO_INCREMENT = 481 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; 224 | 225 | -- ---------------------------- 226 | -- Records of role_menus 227 | -- ---------------------------- 228 | INSERT INTO `role_menus` VALUES (1, '2024-09-03 15:08:36.527', '2024-09-03 15:08:36.527', '2024-09-03 15:25:37.773', 4, 1); 229 | INSERT INTO `role_menus` VALUES (2, '2024-09-03 15:25:37.780', '2024-09-03 15:25:37.780', '2024-09-03 15:25:52.072', 4, 1); 230 | INSERT INTO `role_menus` VALUES (3, '2024-09-03 15:25:52.074', '2024-09-03 15:25:52.074', '2024-09-03 15:27:12.192', 4, 1); 231 | INSERT INTO `role_menus` VALUES (4, '2024-09-03 15:27:12.194', '2024-09-03 15:27:12.194', '2024-09-03 15:27:44.558', 4, 1); 232 | INSERT INTO `role_menus` VALUES (5, '2024-09-03 15:27:44.576', '2024-09-03 15:27:44.576', '2024-09-03 15:28:01.480', 4, 1); 233 | INSERT INTO `role_menus` VALUES (6, '2024-09-03 15:27:44.577', '2024-09-03 15:27:44.577', '2024-09-03 15:28:01.480', 4, 2); 234 | INSERT INTO `role_menus` VALUES (7, '2024-09-03 15:28:01.482', '2024-09-03 15:28:01.482', '2024-09-03 15:29:06.654', 4, 1); 235 | INSERT INTO `role_menus` VALUES (8, '2024-09-03 15:28:01.484', '2024-09-03 15:28:01.484', '2024-09-03 15:29:06.654', 4, 2); 236 | INSERT INTO `role_menus` VALUES (9, '2024-09-03 15:28:01.485', '2024-09-03 15:28:01.485', '2024-09-03 15:29:06.654', 4, 3); 237 | INSERT INTO `role_menus` VALUES (10, '2024-09-03 15:28:01.486', '2024-09-03 15:28:01.486', '2024-09-03 15:29:06.654', 4, 4); 238 | INSERT INTO `role_menus` VALUES (11, '2024-09-03 15:28:01.488', '2024-09-03 15:28:01.488', '2024-09-03 15:29:06.654', 4, 5); 239 | INSERT INTO `role_menus` VALUES (12, '2024-09-03 15:28:01.489', '2024-09-03 15:28:01.489', '2024-09-03 15:29:06.654', 4, 12); 240 | INSERT INTO `role_menus` VALUES (13, '2024-09-03 15:28:01.490', '2024-09-03 15:28:01.490', '2024-09-03 15:29:06.654', 4, 13); 241 | INSERT INTO `role_menus` VALUES (14, '2024-09-03 15:28:01.491', '2024-09-03 15:28:01.491', '2024-09-03 15:29:06.654', 4, 30); 242 | INSERT INTO `role_menus` VALUES (15, '2024-09-03 15:28:01.492', '2024-09-03 15:28:01.492', '2024-09-03 15:29:06.654', 4, 31); 243 | INSERT INTO `role_menus` VALUES (16, '2024-09-03 15:28:28.346', '2024-09-03 15:28:28.346', '2024-09-03 15:47:22.679', 1, 1); 244 | INSERT INTO `role_menus` VALUES (17, '2024-09-03 15:28:28.348', '2024-09-03 15:28:28.348', '2024-09-03 15:47:22.679', 1, 34); 245 | INSERT INTO `role_menus` VALUES (18, '2024-09-03 15:28:28.349', '2024-09-03 15:28:28.349', '2024-09-03 15:47:22.679', 1, 35); 246 | INSERT INTO `role_menus` VALUES (19, '2024-09-03 15:28:28.350', '2024-09-03 15:28:28.350', '2024-09-03 15:47:22.679', 1, 2); 247 | INSERT INTO `role_menus` VALUES (20, '2024-09-03 15:28:28.351', '2024-09-03 15:28:28.351', '2024-09-03 15:47:22.679', 1, 3); 248 | INSERT INTO `role_menus` VALUES (21, '2024-09-03 15:28:28.352', '2024-09-03 15:28:28.352', '2024-09-03 15:47:22.679', 1, 4); 249 | INSERT INTO `role_menus` VALUES (22, '2024-09-03 15:28:28.354', '2024-09-03 15:28:28.354', '2024-09-03 15:47:22.679', 1, 5); 250 | INSERT INTO `role_menus` VALUES (23, '2024-09-03 15:28:28.355', '2024-09-03 15:28:28.355', '2024-09-03 15:47:22.679', 1, 12); 251 | INSERT INTO `role_menus` VALUES (24, '2024-09-03 15:28:28.356', '2024-09-03 15:28:28.356', '2024-09-03 15:47:22.679', 1, 13); 252 | INSERT INTO `role_menus` VALUES (25, '2024-09-03 15:28:28.357', '2024-09-03 15:28:28.357', '2024-09-03 15:47:22.679', 1, 30); 253 | INSERT INTO `role_menus` VALUES (26, '2024-09-03 15:28:28.358', '2024-09-03 15:28:28.358', '2024-09-03 15:47:22.679', 1, 31); 254 | INSERT INTO `role_menus` VALUES (27, '2024-09-03 15:29:06.656', '2024-09-03 15:29:06.656', '2024-09-03 15:39:10.875', 4, 1); 255 | INSERT INTO `role_menus` VALUES (28, '2024-09-03 15:29:06.657', '2024-09-03 15:29:06.657', '2024-09-03 15:39:10.875', 4, 34); 256 | INSERT INTO `role_menus` VALUES (29, '2024-09-03 15:29:06.658', '2024-09-03 15:29:06.658', '2024-09-03 15:39:10.875', 4, 35); 257 | INSERT INTO `role_menus` VALUES (30, '2024-09-03 15:29:06.660', '2024-09-03 15:29:06.660', '2024-09-03 15:39:10.875', 4, 2); 258 | INSERT INTO `role_menus` VALUES (31, '2024-09-03 15:29:06.661', '2024-09-03 15:29:06.661', '2024-09-03 15:39:10.875', 4, 3); 259 | INSERT INTO `role_menus` VALUES (32, '2024-09-03 15:29:06.662', '2024-09-03 15:29:06.662', '2024-09-03 15:39:10.875', 4, 4); 260 | INSERT INTO `role_menus` VALUES (33, '2024-09-03 15:29:06.663', '2024-09-03 15:29:06.663', '2024-09-03 15:39:10.875', 4, 5); 261 | INSERT INTO `role_menus` VALUES (34, '2024-09-03 15:29:06.664', '2024-09-03 15:29:06.664', '2024-09-03 15:39:10.875', 4, 12); 262 | INSERT INTO `role_menus` VALUES (35, '2024-09-03 15:29:06.666', '2024-09-03 15:29:06.666', '2024-09-03 15:39:10.875', 4, 13); 263 | INSERT INTO `role_menus` VALUES (36, '2024-09-03 15:29:06.667', '2024-09-03 15:29:06.667', '2024-09-03 15:39:10.875', 4, 30); 264 | INSERT INTO `role_menus` VALUES (37, '2024-09-03 15:29:06.668', '2024-09-03 15:29:06.668', '2024-09-03 15:39:10.875', 4, 31); 265 | INSERT INTO `role_menus` VALUES (38, '2024-09-03 15:39:10.896', '2024-09-03 15:39:10.896', '2024-09-03 15:39:21.631', 4, 1); 266 | INSERT INTO `role_menus` VALUES (39, '2024-09-03 15:39:10.899', '2024-09-03 15:39:10.899', '2024-09-03 15:39:21.631', 4, 34); 267 | INSERT INTO `role_menus` VALUES (40, '2024-09-03 15:39:10.900', '2024-09-03 15:39:10.900', '2024-09-03 15:39:21.631', 4, 35); 268 | INSERT INTO `role_menus` VALUES (41, '2024-09-03 15:39:10.901', '2024-09-03 15:39:10.901', '2024-09-03 15:39:21.631', 4, 2); 269 | INSERT INTO `role_menus` VALUES (42, '2024-09-03 15:39:10.902', '2024-09-03 15:39:10.902', '2024-09-03 15:39:21.631', 4, 3); 270 | INSERT INTO `role_menus` VALUES (43, '2024-09-03 15:39:10.903', '2024-09-03 15:39:10.903', '2024-09-03 15:39:21.631', 4, 4); 271 | INSERT INTO `role_menus` VALUES (44, '2024-09-03 15:39:10.905', '2024-09-03 15:39:10.905', '2024-09-03 15:39:21.631', 4, 5); 272 | INSERT INTO `role_menus` VALUES (45, '2024-09-03 15:39:10.906', '2024-09-03 15:39:10.906', '2024-09-03 15:39:21.631', 4, 6); 273 | INSERT INTO `role_menus` VALUES (46, '2024-09-03 15:39:10.907', '2024-09-03 15:39:10.907', '2024-09-03 15:39:21.631', 4, 7); 274 | INSERT INTO `role_menus` VALUES (47, '2024-09-03 15:39:10.908', '2024-09-03 15:39:10.908', '2024-09-03 15:39:21.631', 4, 8); 275 | INSERT INTO `role_menus` VALUES (48, '2024-09-03 15:39:10.909', '2024-09-03 15:39:10.909', '2024-09-03 15:39:21.631', 4, 9); 276 | INSERT INTO `role_menus` VALUES (49, '2024-09-03 15:39:10.911', '2024-09-03 15:39:10.911', '2024-09-03 15:39:21.631', 4, 10); 277 | INSERT INTO `role_menus` VALUES (50, '2024-09-03 15:39:10.912', '2024-09-03 15:39:10.912', '2024-09-03 15:39:21.631', 4, 11); 278 | INSERT INTO `role_menus` VALUES (51, '2024-09-03 15:39:10.913', '2024-09-03 15:39:10.913', '2024-09-03 15:39:21.631', 4, 12); 279 | INSERT INTO `role_menus` VALUES (52, '2024-09-03 15:39:10.915', '2024-09-03 15:39:10.915', '2024-09-03 15:39:21.631', 4, 13); 280 | INSERT INTO `role_menus` VALUES (53, '2024-09-03 15:39:10.916', '2024-09-03 15:39:10.916', '2024-09-03 15:39:21.631', 4, 30); 281 | INSERT INTO `role_menus` VALUES (54, '2024-09-03 15:39:10.917', '2024-09-03 15:39:10.917', '2024-09-03 15:39:21.631', 4, 31); 282 | INSERT INTO `role_menus` VALUES (55, '2024-09-03 15:39:21.633', '2024-09-03 15:39:21.633', NULL, 4, 1); 283 | INSERT INTO `role_menus` VALUES (56, '2024-09-03 15:39:21.634', '2024-09-03 15:39:21.634', NULL, 4, 34); 284 | INSERT INTO `role_menus` VALUES (57, '2024-09-03 15:39:21.635', '2024-09-03 15:39:21.635', NULL, 4, 35); 285 | INSERT INTO `role_menus` VALUES (58, '2024-09-03 15:39:21.636', '2024-09-03 15:39:21.636', NULL, 4, 2); 286 | INSERT INTO `role_menus` VALUES (59, '2024-09-03 15:39:21.637', '2024-09-03 15:39:21.637', NULL, 4, 3); 287 | INSERT INTO `role_menus` VALUES (60, '2024-09-03 15:39:21.639', '2024-09-03 15:39:21.639', NULL, 4, 4); 288 | INSERT INTO `role_menus` VALUES (61, '2024-09-03 15:39:21.640', '2024-09-03 15:39:21.640', NULL, 4, 5); 289 | INSERT INTO `role_menus` VALUES (62, '2024-09-03 15:39:21.641', '2024-09-03 15:39:21.641', NULL, 4, 6); 290 | INSERT INTO `role_menus` VALUES (63, '2024-09-03 15:39:21.642', '2024-09-03 15:39:21.642', NULL, 4, 7); 291 | INSERT INTO `role_menus` VALUES (64, '2024-09-03 15:39:21.644', '2024-09-03 15:39:21.644', NULL, 4, 8); 292 | INSERT INTO `role_menus` VALUES (65, '2024-09-03 15:39:21.645', '2024-09-03 15:39:21.645', NULL, 4, 9); 293 | INSERT INTO `role_menus` VALUES (66, '2024-09-03 15:39:21.646', '2024-09-03 15:39:21.646', NULL, 4, 10); 294 | INSERT INTO `role_menus` VALUES (67, '2024-09-03 15:39:21.647', '2024-09-03 15:39:21.647', NULL, 4, 11); 295 | INSERT INTO `role_menus` VALUES (68, '2024-09-03 15:39:21.648', '2024-09-03 15:39:21.648', NULL, 4, 12); 296 | INSERT INTO `role_menus` VALUES (69, '2024-09-03 15:39:21.649', '2024-09-03 15:39:21.649', NULL, 4, 13); 297 | INSERT INTO `role_menus` VALUES (70, '2024-09-03 15:39:21.650', '2024-09-03 15:39:21.650', NULL, 4, 30); 298 | INSERT INTO `role_menus` VALUES (71, '2024-09-03 15:39:21.652', '2024-09-03 15:39:21.652', NULL, 4, 31); 299 | INSERT INTO `role_menus` VALUES (72, '2024-09-03 15:47:22.692', '2024-09-03 15:47:22.692', '2024-09-03 16:03:20.769', 1, 1); 300 | INSERT INTO `role_menus` VALUES (73, '2024-09-03 15:47:22.694', '2024-09-03 15:47:22.694', '2024-09-03 16:03:20.769', 1, 34); 301 | INSERT INTO `role_menus` VALUES (74, '2024-09-03 15:47:22.696', '2024-09-03 15:47:22.696', '2024-09-03 16:03:20.769', 1, 35); 302 | INSERT INTO `role_menus` VALUES (75, '2024-09-03 15:47:22.697', '2024-09-03 15:47:22.697', '2024-09-03 16:03:20.769', 1, 2); 303 | INSERT INTO `role_menus` VALUES (76, '2024-09-03 15:47:22.699', '2024-09-03 15:47:22.699', '2024-09-03 16:03:20.769', 1, 3); 304 | INSERT INTO `role_menus` VALUES (77, '2024-09-03 15:47:22.700', '2024-09-03 15:47:22.700', '2024-09-03 16:03:20.769', 1, 4); 305 | INSERT INTO `role_menus` VALUES (78, '2024-09-03 15:47:22.701', '2024-09-03 15:47:22.701', '2024-09-03 16:03:20.769', 1, 5); 306 | INSERT INTO `role_menus` VALUES (79, '2024-09-03 15:47:22.702', '2024-09-03 15:47:22.702', '2024-09-03 16:03:20.769', 1, 6); 307 | INSERT INTO `role_menus` VALUES (80, '2024-09-03 15:47:22.703', '2024-09-03 15:47:22.703', '2024-09-03 16:03:20.769', 1, 7); 308 | INSERT INTO `role_menus` VALUES (81, '2024-09-03 15:47:22.704', '2024-09-03 15:47:22.704', '2024-09-03 16:03:20.769', 1, 12); 309 | INSERT INTO `role_menus` VALUES (82, '2024-09-03 15:47:22.705', '2024-09-03 15:47:22.705', '2024-09-03 16:03:20.769', 1, 13); 310 | INSERT INTO `role_menus` VALUES (83, '2024-09-03 15:47:22.707', '2024-09-03 15:47:22.707', '2024-09-03 16:03:20.769', 1, 30); 311 | INSERT INTO `role_menus` VALUES (84, '2024-09-03 15:47:22.708', '2024-09-03 15:47:22.708', '2024-09-03 16:03:20.769', 1, 31); 312 | INSERT INTO `role_menus` VALUES (85, '2024-09-03 16:03:20.782', '2024-09-03 16:03:20.782', '2024-09-03 16:04:47.726', 1, 1); 313 | INSERT INTO `role_menus` VALUES (86, '2024-09-03 16:03:20.786', '2024-09-03 16:03:20.786', '2024-09-03 16:04:47.726', 1, 34); 314 | INSERT INTO `role_menus` VALUES (87, '2024-09-03 16:03:20.789', '2024-09-03 16:03:20.789', '2024-09-03 16:04:47.726', 1, 35); 315 | INSERT INTO `role_menus` VALUES (88, '2024-09-03 16:03:20.791', '2024-09-03 16:03:20.791', '2024-09-03 16:04:47.726', 1, 2); 316 | INSERT INTO `role_menus` VALUES (89, '2024-09-03 16:03:20.792', '2024-09-03 16:03:20.792', '2024-09-03 16:04:47.726', 1, 3); 317 | INSERT INTO `role_menus` VALUES (90, '2024-09-03 16:03:20.794', '2024-09-03 16:03:20.794', '2024-09-03 16:04:47.726', 1, 4); 318 | INSERT INTO `role_menus` VALUES (91, '2024-09-03 16:03:20.796', '2024-09-03 16:03:20.796', '2024-09-03 16:04:47.726', 1, 5); 319 | INSERT INTO `role_menus` VALUES (92, '2024-09-03 16:03:20.799', '2024-09-03 16:03:20.799', '2024-09-03 16:04:47.726', 1, 6); 320 | INSERT INTO `role_menus` VALUES (93, '2024-09-03 16:03:20.801', '2024-09-03 16:03:20.801', '2024-09-03 16:04:47.726', 1, 7); 321 | INSERT INTO `role_menus` VALUES (94, '2024-09-03 16:03:20.803', '2024-09-03 16:03:20.803', '2024-09-03 16:04:47.726', 1, 8); 322 | INSERT INTO `role_menus` VALUES (95, '2024-09-03 16:03:20.806', '2024-09-03 16:03:20.806', '2024-09-03 16:04:47.726', 1, 9); 323 | INSERT INTO `role_menus` VALUES (96, '2024-09-03 16:03:20.808', '2024-09-03 16:03:20.808', '2024-09-03 16:04:47.726', 1, 10); 324 | INSERT INTO `role_menus` VALUES (97, '2024-09-03 16:03:20.810', '2024-09-03 16:03:20.810', '2024-09-03 16:04:47.726', 1, 11); 325 | INSERT INTO `role_menus` VALUES (98, '2024-09-03 16:03:20.811', '2024-09-03 16:03:20.811', '2024-09-03 16:04:47.726', 1, 12); 326 | INSERT INTO `role_menus` VALUES (99, '2024-09-03 16:03:20.813', '2024-09-03 16:03:20.813', '2024-09-03 16:04:47.726', 1, 13); 327 | INSERT INTO `role_menus` VALUES (100, '2024-09-03 16:03:20.814', '2024-09-03 16:03:20.814', '2024-09-03 16:04:47.726', 1, 30); 328 | INSERT INTO `role_menus` VALUES (101, '2024-09-03 16:03:20.815', '2024-09-03 16:03:20.815', '2024-09-03 16:04:47.726', 1, 31); 329 | INSERT INTO `role_menus` VALUES (102, '2024-09-03 16:04:47.741', '2024-09-03 16:04:47.741', '2024-09-03 16:06:39.977', 1, 1); 330 | INSERT INTO `role_menus` VALUES (103, '2024-09-03 16:04:47.743', '2024-09-03 16:04:47.743', '2024-09-03 16:06:39.977', 1, 34); 331 | INSERT INTO `role_menus` VALUES (104, '2024-09-03 16:04:47.746', '2024-09-03 16:04:47.746', '2024-09-03 16:06:39.977', 1, 35); 332 | INSERT INTO `role_menus` VALUES (105, '2024-09-03 16:04:47.748', '2024-09-03 16:04:47.748', '2024-09-03 16:06:39.977', 1, 2); 333 | INSERT INTO `role_menus` VALUES (106, '2024-09-03 16:04:47.749', '2024-09-03 16:04:47.749', '2024-09-03 16:06:39.977', 1, 3); 334 | INSERT INTO `role_menus` VALUES (107, '2024-09-03 16:04:47.751', '2024-09-03 16:04:47.751', '2024-09-03 16:06:39.977', 1, 4); 335 | INSERT INTO `role_menus` VALUES (108, '2024-09-03 16:04:47.752', '2024-09-03 16:04:47.752', '2024-09-03 16:06:39.977', 1, 5); 336 | INSERT INTO `role_menus` VALUES (109, '2024-09-03 16:04:47.755', '2024-09-03 16:04:47.755', '2024-09-03 16:06:39.977', 1, 6); 337 | INSERT INTO `role_menus` VALUES (110, '2024-09-03 16:04:47.758', '2024-09-03 16:04:47.758', '2024-09-03 16:06:39.977', 1, 8); 338 | INSERT INTO `role_menus` VALUES (111, '2024-09-03 16:04:47.760', '2024-09-03 16:04:47.760', '2024-09-03 16:06:39.977', 1, 9); 339 | INSERT INTO `role_menus` VALUES (112, '2024-09-03 16:04:47.763', '2024-09-03 16:04:47.763', '2024-09-03 16:06:39.977', 1, 10); 340 | INSERT INTO `role_menus` VALUES (113, '2024-09-03 16:04:47.764', '2024-09-03 16:04:47.764', '2024-09-03 16:06:39.977', 1, 11); 341 | INSERT INTO `role_menus` VALUES (114, '2024-09-03 16:04:47.765', '2024-09-03 16:04:47.765', '2024-09-03 16:06:39.977', 1, 12); 342 | INSERT INTO `role_menus` VALUES (115, '2024-09-03 16:04:47.766', '2024-09-03 16:04:47.766', '2024-09-03 16:06:39.977', 1, 13); 343 | INSERT INTO `role_menus` VALUES (116, '2024-09-03 16:04:47.768', '2024-09-03 16:04:47.768', '2024-09-03 16:06:39.977', 1, 30); 344 | INSERT INTO `role_menus` VALUES (117, '2024-09-03 16:04:47.769', '2024-09-03 16:04:47.769', '2024-09-03 16:06:39.977', 1, 31); 345 | INSERT INTO `role_menus` VALUES (118, '2024-09-03 16:06:39.994', '2024-09-03 16:06:39.994', '2024-09-03 16:07:27.371', 1, 1); 346 | INSERT INTO `role_menus` VALUES (119, '2024-09-03 16:06:39.997', '2024-09-03 16:06:39.997', '2024-09-03 16:07:27.371', 1, 34); 347 | INSERT INTO `role_menus` VALUES (120, '2024-09-03 16:06:40.000', '2024-09-03 16:06:40.000', '2024-09-03 16:07:27.371', 1, 35); 348 | INSERT INTO `role_menus` VALUES (121, '2024-09-03 16:06:40.002', '2024-09-03 16:06:40.002', '2024-09-03 16:07:27.371', 1, 2); 349 | INSERT INTO `role_menus` VALUES (122, '2024-09-03 16:06:40.003', '2024-09-03 16:06:40.003', '2024-09-03 16:07:27.371', 1, 3); 350 | INSERT INTO `role_menus` VALUES (123, '2024-09-03 16:06:40.006', '2024-09-03 16:06:40.006', '2024-09-03 16:07:27.371', 1, 4); 351 | INSERT INTO `role_menus` VALUES (124, '2024-09-03 16:06:40.007', '2024-09-03 16:06:40.007', '2024-09-03 16:07:27.371', 1, 5); 352 | INSERT INTO `role_menus` VALUES (125, '2024-09-03 16:06:40.009', '2024-09-03 16:06:40.009', '2024-09-03 16:07:27.371', 1, 6); 353 | INSERT INTO `role_menus` VALUES (126, '2024-09-03 16:06:40.012', '2024-09-03 16:06:40.012', '2024-09-03 16:07:27.371', 1, 8); 354 | INSERT INTO `role_menus` VALUES (127, '2024-09-03 16:06:40.015', '2024-09-03 16:06:40.015', '2024-09-03 16:07:27.371', 1, 9); 355 | INSERT INTO `role_menus` VALUES (128, '2024-09-03 16:06:40.017', '2024-09-03 16:06:40.017', '2024-09-03 16:07:27.371', 1, 10); 356 | INSERT INTO `role_menus` VALUES (129, '2024-09-03 16:06:40.019', '2024-09-03 16:06:40.019', '2024-09-03 16:07:27.371', 1, 11); 357 | INSERT INTO `role_menus` VALUES (130, '2024-09-03 16:06:40.020', '2024-09-03 16:06:40.020', '2024-09-03 16:07:27.371', 1, 12); 358 | INSERT INTO `role_menus` VALUES (131, '2024-09-03 16:06:40.021', '2024-09-03 16:06:40.021', '2024-09-03 16:07:27.371', 1, 13); 359 | INSERT INTO `role_menus` VALUES (132, '2024-09-03 16:06:40.023', '2024-09-03 16:06:40.023', '2024-09-03 16:07:27.371', 1, 30); 360 | INSERT INTO `role_menus` VALUES (133, '2024-09-03 16:06:40.024', '2024-09-03 16:06:40.024', '2024-09-03 16:07:27.371', 1, 31); 361 | INSERT INTO `role_menus` VALUES (134, '2024-09-03 16:07:27.383', '2024-09-03 16:07:27.383', '2024-09-03 16:08:55.049', 1, 1); 362 | INSERT INTO `role_menus` VALUES (135, '2024-09-03 16:07:27.386', '2024-09-03 16:07:27.386', '2024-09-03 16:08:55.049', 1, 34); 363 | INSERT INTO `role_menus` VALUES (136, '2024-09-03 16:07:27.388', '2024-09-03 16:07:27.388', '2024-09-03 16:08:55.049', 1, 35); 364 | INSERT INTO `role_menus` VALUES (137, '2024-09-03 16:07:27.390', '2024-09-03 16:07:27.390', '2024-09-03 16:08:55.049', 1, 2); 365 | INSERT INTO `role_menus` VALUES (138, '2024-09-03 16:07:27.391', '2024-09-03 16:07:27.391', '2024-09-03 16:08:55.049', 1, 3); 366 | INSERT INTO `role_menus` VALUES (139, '2024-09-03 16:07:27.393', '2024-09-03 16:07:27.393', '2024-09-03 16:08:55.049', 1, 4); 367 | INSERT INTO `role_menus` VALUES (140, '2024-09-03 16:07:27.394', '2024-09-03 16:07:27.394', '2024-09-03 16:08:55.049', 1, 5); 368 | INSERT INTO `role_menus` VALUES (141, '2024-09-03 16:07:27.396', '2024-09-03 16:07:27.396', '2024-09-03 16:08:55.049', 1, 6); 369 | INSERT INTO `role_menus` VALUES (142, '2024-09-03 16:07:27.399', '2024-09-03 16:07:27.399', '2024-09-03 16:08:55.049', 1, 7); 370 | INSERT INTO `role_menus` VALUES (143, '2024-09-03 16:07:27.402', '2024-09-03 16:07:27.402', '2024-09-03 16:08:55.049', 1, 8); 371 | INSERT INTO `role_menus` VALUES (144, '2024-09-03 16:07:27.404', '2024-09-03 16:07:27.404', '2024-09-03 16:08:55.049', 1, 9); 372 | INSERT INTO `role_menus` VALUES (145, '2024-09-03 16:07:27.406', '2024-09-03 16:07:27.406', '2024-09-03 16:08:55.049', 1, 10); 373 | INSERT INTO `role_menus` VALUES (146, '2024-09-03 16:07:27.407', '2024-09-03 16:07:27.407', '2024-09-03 16:08:55.049', 1, 11); 374 | INSERT INTO `role_menus` VALUES (147, '2024-09-03 16:07:27.408', '2024-09-03 16:07:27.408', '2024-09-03 16:08:55.049', 1, 12); 375 | INSERT INTO `role_menus` VALUES (148, '2024-09-03 16:07:27.409', '2024-09-03 16:07:27.409', '2024-09-03 16:08:55.049', 1, 13); 376 | INSERT INTO `role_menus` VALUES (149, '2024-09-03 16:07:27.411', '2024-09-03 16:07:27.411', '2024-09-03 16:08:55.049', 1, 30); 377 | INSERT INTO `role_menus` VALUES (150, '2024-09-03 16:07:27.412', '2024-09-03 16:07:27.412', '2024-09-03 16:08:55.049', 1, 31); 378 | INSERT INTO `role_menus` VALUES (151, '2024-09-03 16:08:55.063', '2024-09-03 16:08:55.063', '2024-09-03 16:09:10.714', 1, 1); 379 | INSERT INTO `role_menus` VALUES (152, '2024-09-03 16:08:55.065', '2024-09-03 16:08:55.065', '2024-09-03 16:09:10.714', 1, 34); 380 | INSERT INTO `role_menus` VALUES (153, '2024-09-03 16:08:55.068', '2024-09-03 16:08:55.068', '2024-09-03 16:09:10.714', 1, 35); 381 | INSERT INTO `role_menus` VALUES (154, '2024-09-03 16:08:55.070', '2024-09-03 16:08:55.070', '2024-09-03 16:09:10.714', 1, 2); 382 | INSERT INTO `role_menus` VALUES (155, '2024-09-03 16:08:55.071', '2024-09-03 16:08:55.071', '2024-09-03 16:09:10.714', 1, 3); 383 | INSERT INTO `role_menus` VALUES (156, '2024-09-03 16:08:55.073', '2024-09-03 16:08:55.073', '2024-09-03 16:09:10.714', 1, 4); 384 | INSERT INTO `role_menus` VALUES (157, '2024-09-03 16:08:55.074', '2024-09-03 16:08:55.074', '2024-09-03 16:09:10.714', 1, 5); 385 | INSERT INTO `role_menus` VALUES (158, '2024-09-03 16:08:55.077', '2024-09-03 16:08:55.077', '2024-09-03 16:09:10.714', 1, 6); 386 | INSERT INTO `role_menus` VALUES (159, '2024-09-03 16:08:55.079', '2024-09-03 16:08:55.079', '2024-09-03 16:09:10.714', 1, 8); 387 | INSERT INTO `role_menus` VALUES (160, '2024-09-03 16:08:55.081', '2024-09-03 16:08:55.081', '2024-09-03 16:09:10.714', 1, 9); 388 | INSERT INTO `role_menus` VALUES (161, '2024-09-03 16:08:55.083', '2024-09-03 16:08:55.083', '2024-09-03 16:09:10.714', 1, 10); 389 | INSERT INTO `role_menus` VALUES (162, '2024-09-03 16:08:55.084', '2024-09-03 16:08:55.084', '2024-09-03 16:09:10.714', 1, 11); 390 | INSERT INTO `role_menus` VALUES (163, '2024-09-03 16:08:55.086', '2024-09-03 16:08:55.086', '2024-09-03 16:09:10.714', 1, 12); 391 | INSERT INTO `role_menus` VALUES (164, '2024-09-03 16:08:55.087', '2024-09-03 16:08:55.087', '2024-09-03 16:09:10.714', 1, 13); 392 | INSERT INTO `role_menus` VALUES (165, '2024-09-03 16:08:55.088', '2024-09-03 16:08:55.088', '2024-09-03 16:09:10.714', 1, 30); 393 | INSERT INTO `role_menus` VALUES (166, '2024-09-03 16:08:55.089', '2024-09-03 16:08:55.089', '2024-09-03 16:09:10.714', 1, 31); 394 | INSERT INTO `role_menus` VALUES (167, '2024-09-03 16:09:10.726', '2024-09-03 16:09:10.726', '2024-09-03 16:15:20.728', 1, 1); 395 | INSERT INTO `role_menus` VALUES (168, '2024-09-03 16:09:10.728', '2024-09-03 16:09:10.728', '2024-09-03 16:15:20.728', 1, 34); 396 | INSERT INTO `role_menus` VALUES (169, '2024-09-03 16:09:10.731', '2024-09-03 16:09:10.731', '2024-09-03 16:15:20.728', 1, 35); 397 | INSERT INTO `role_menus` VALUES (170, '2024-09-03 16:09:10.733', '2024-09-03 16:09:10.733', '2024-09-03 16:15:20.728', 1, 2); 398 | INSERT INTO `role_menus` VALUES (171, '2024-09-03 16:09:10.734', '2024-09-03 16:09:10.734', '2024-09-03 16:15:20.728', 1, 3); 399 | INSERT INTO `role_menus` VALUES (172, '2024-09-03 16:09:10.736', '2024-09-03 16:09:10.736', '2024-09-03 16:15:20.728', 1, 4); 400 | INSERT INTO `role_menus` VALUES (173, '2024-09-03 16:09:10.738', '2024-09-03 16:09:10.738', '2024-09-03 16:15:20.728', 1, 5); 401 | INSERT INTO `role_menus` VALUES (174, '2024-09-03 16:09:10.740', '2024-09-03 16:09:10.740', '2024-09-03 16:15:20.728', 1, 6); 402 | INSERT INTO `role_menus` VALUES (175, '2024-09-03 16:09:10.742', '2024-09-03 16:09:10.742', '2024-09-03 16:15:20.728', 1, 7); 403 | INSERT INTO `role_menus` VALUES (176, '2024-09-03 16:09:10.744', '2024-09-03 16:09:10.744', '2024-09-03 16:15:20.728', 1, 8); 404 | INSERT INTO `role_menus` VALUES (177, '2024-09-03 16:09:10.746', '2024-09-03 16:09:10.746', '2024-09-03 16:15:20.728', 1, 9); 405 | INSERT INTO `role_menus` VALUES (178, '2024-09-03 16:09:10.748', '2024-09-03 16:09:10.748', '2024-09-03 16:15:20.728', 1, 10); 406 | INSERT INTO `role_menus` VALUES (179, '2024-09-03 16:09:10.749', '2024-09-03 16:09:10.749', '2024-09-03 16:15:20.728', 1, 11); 407 | INSERT INTO `role_menus` VALUES (180, '2024-09-03 16:09:10.750', '2024-09-03 16:09:10.750', '2024-09-03 16:15:20.728', 1, 12); 408 | INSERT INTO `role_menus` VALUES (181, '2024-09-03 16:09:10.751', '2024-09-03 16:09:10.751', '2024-09-03 16:15:20.728', 1, 13); 409 | INSERT INTO `role_menus` VALUES (182, '2024-09-03 16:09:10.753', '2024-09-03 16:09:10.753', '2024-09-03 16:15:20.728', 1, 30); 410 | INSERT INTO `role_menus` VALUES (183, '2024-09-03 16:09:10.754', '2024-09-03 16:09:10.754', '2024-09-03 16:15:20.728', 1, 31); 411 | INSERT INTO `role_menus` VALUES (184, '2024-09-03 16:15:20.747', '2024-09-03 16:15:20.747', '2024-09-03 16:32:20.058', 1, 1); 412 | INSERT INTO `role_menus` VALUES (185, '2024-09-03 16:15:20.751', '2024-09-03 16:15:20.751', '2024-09-03 16:32:20.058', 1, 34); 413 | INSERT INTO `role_menus` VALUES (186, '2024-09-03 16:15:20.753', '2024-09-03 16:15:20.753', '2024-09-03 16:32:20.058', 1, 35); 414 | INSERT INTO `role_menus` VALUES (187, '2024-09-03 16:15:20.754', '2024-09-03 16:15:20.754', '2024-09-03 16:32:20.058', 1, 2); 415 | INSERT INTO `role_menus` VALUES (188, '2024-09-03 16:15:20.756', '2024-09-03 16:15:20.756', '2024-09-03 16:32:20.058', 1, 12); 416 | INSERT INTO `role_menus` VALUES (189, '2024-09-03 16:15:20.757', '2024-09-03 16:15:20.757', '2024-09-03 16:32:20.058', 1, 13); 417 | INSERT INTO `role_menus` VALUES (190, '2024-09-03 16:15:20.758', '2024-09-03 16:15:20.758', '2024-09-03 16:32:20.058', 1, 30); 418 | INSERT INTO `role_menus` VALUES (191, '2024-09-03 16:15:20.761', '2024-09-03 16:15:20.761', '2024-09-03 16:32:20.058', 1, 31); 419 | INSERT INTO `role_menus` VALUES (192, '2024-09-03 16:32:20.075', '2024-09-03 16:32:20.075', '2024-09-03 16:48:17.137', 1, 1); 420 | INSERT INTO `role_menus` VALUES (193, '2024-09-03 16:32:20.078', '2024-09-03 16:32:20.078', '2024-09-03 16:48:17.137', 1, 34); 421 | INSERT INTO `role_menus` VALUES (194, '2024-09-03 16:32:20.081', '2024-09-03 16:32:20.081', '2024-09-03 16:48:17.137', 1, 35); 422 | INSERT INTO `role_menus` VALUES (195, '2024-09-03 16:32:20.083', '2024-09-03 16:32:20.083', '2024-09-03 16:48:17.137', 1, 2); 423 | INSERT INTO `role_menus` VALUES (196, '2024-09-03 16:32:20.084', '2024-09-03 16:32:20.084', '2024-09-03 16:48:17.137', 1, 3); 424 | INSERT INTO `role_menus` VALUES (197, '2024-09-03 16:32:20.087', '2024-09-03 16:32:20.087', '2024-09-03 16:48:17.137', 1, 4); 425 | INSERT INTO `role_menus` VALUES (198, '2024-09-03 16:32:20.088', '2024-09-03 16:32:20.088', '2024-09-03 16:48:17.137', 1, 5); 426 | INSERT INTO `role_menus` VALUES (199, '2024-09-03 16:32:20.091', '2024-09-03 16:32:20.091', '2024-09-03 16:48:17.137', 1, 7); 427 | INSERT INTO `role_menus` VALUES (200, '2024-09-03 16:32:20.093', '2024-09-03 16:32:20.093', '2024-09-03 16:48:17.137', 1, 8); 428 | INSERT INTO `role_menus` VALUES (201, '2024-09-03 16:32:20.095', '2024-09-03 16:32:20.095', '2024-09-03 16:48:17.137', 1, 9); 429 | INSERT INTO `role_menus` VALUES (202, '2024-09-03 16:32:20.097', '2024-09-03 16:32:20.097', '2024-09-03 16:48:17.137', 1, 10); 430 | INSERT INTO `role_menus` VALUES (203, '2024-09-03 16:32:20.098', '2024-09-03 16:32:20.098', '2024-09-03 16:48:17.137', 1, 11); 431 | INSERT INTO `role_menus` VALUES (204, '2024-09-03 16:32:20.099', '2024-09-03 16:32:20.099', '2024-09-03 16:48:17.137', 1, 12); 432 | INSERT INTO `role_menus` VALUES (205, '2024-09-03 16:32:20.101', '2024-09-03 16:32:20.101', '2024-09-03 16:48:17.137', 1, 13); 433 | INSERT INTO `role_menus` VALUES (206, '2024-09-03 16:32:20.102', '2024-09-03 16:32:20.102', '2024-09-03 16:48:17.137', 1, 30); 434 | INSERT INTO `role_menus` VALUES (207, '2024-09-03 16:32:20.103', '2024-09-03 16:32:20.103', '2024-09-03 16:48:17.137', 1, 31); 435 | INSERT INTO `role_menus` VALUES (208, '2024-09-03 16:48:17.150', '2024-09-03 16:48:17.150', '2024-09-03 16:51:15.512', 1, 1); 436 | INSERT INTO `role_menus` VALUES (209, '2024-09-03 16:48:17.153', '2024-09-03 16:48:17.153', '2024-09-03 16:51:15.512', 1, 34); 437 | INSERT INTO `role_menus` VALUES (210, '2024-09-03 16:48:17.156', '2024-09-03 16:48:17.156', '2024-09-03 16:51:15.512', 1, 35); 438 | INSERT INTO `role_menus` VALUES (211, '2024-09-03 16:48:17.157', '2024-09-03 16:48:17.157', '2024-09-03 16:51:15.512', 1, 2); 439 | INSERT INTO `role_menus` VALUES (212, '2024-09-03 16:48:17.158', '2024-09-03 16:48:17.158', '2024-09-03 16:51:15.512', 1, 3); 440 | INSERT INTO `role_menus` VALUES (213, '2024-09-03 16:48:17.162', '2024-09-03 16:48:17.162', '2024-09-03 16:51:15.512', 1, 4); 441 | INSERT INTO `role_menus` VALUES (214, '2024-09-03 16:48:17.163', '2024-09-03 16:48:17.163', '2024-09-03 16:51:15.512', 1, 5); 442 | INSERT INTO `role_menus` VALUES (215, '2024-09-03 16:48:17.166', '2024-09-03 16:48:17.166', '2024-09-03 16:51:15.512', 1, 7); 443 | INSERT INTO `role_menus` VALUES (216, '2024-09-03 16:48:17.170', '2024-09-03 16:48:17.170', '2024-09-03 16:51:15.512', 1, 8); 444 | INSERT INTO `role_menus` VALUES (217, '2024-09-03 16:48:17.173', '2024-09-03 16:48:17.173', '2024-09-03 16:51:15.512', 1, 9); 445 | INSERT INTO `role_menus` VALUES (218, '2024-09-03 16:48:17.176', '2024-09-03 16:48:17.176', '2024-09-03 16:51:15.512', 1, 10); 446 | INSERT INTO `role_menus` VALUES (219, '2024-09-03 16:48:17.178', '2024-09-03 16:48:17.178', '2024-09-03 16:51:15.512', 1, 11); 447 | INSERT INTO `role_menus` VALUES (220, '2024-09-03 16:48:17.180', '2024-09-03 16:48:17.180', '2024-09-03 16:51:15.512', 1, 12); 448 | INSERT INTO `role_menus` VALUES (221, '2024-09-03 16:48:17.181', '2024-09-03 16:48:17.181', '2024-09-03 16:51:15.512', 1, 13); 449 | INSERT INTO `role_menus` VALUES (222, '2024-09-03 16:48:17.182', '2024-09-03 16:48:17.182', '2024-09-03 16:51:15.512', 1, 30); 450 | INSERT INTO `role_menus` VALUES (223, '2024-09-03 16:48:17.183', '2024-09-03 16:48:17.183', '2024-09-03 16:51:15.512', 1, 31); 451 | INSERT INTO `role_menus` VALUES (224, '2024-09-03 16:51:15.525', '2024-09-03 16:51:15.525', '2024-09-03 16:51:23.574', 1, 2); 452 | INSERT INTO `role_menus` VALUES (225, '2024-09-03 16:51:15.527', '2024-09-03 16:51:15.527', '2024-09-03 16:51:23.574', 1, 1); 453 | INSERT INTO `role_menus` VALUES (226, '2024-09-03 16:51:15.530', '2024-09-03 16:51:15.530', '2024-09-03 16:51:23.574', 1, 34); 454 | INSERT INTO `role_menus` VALUES (227, '2024-09-03 16:51:15.532', '2024-09-03 16:51:15.532', '2024-09-03 16:51:23.574', 1, 35); 455 | INSERT INTO `role_menus` VALUES (228, '2024-09-03 16:51:15.534', '2024-09-03 16:51:15.534', '2024-09-03 16:51:23.574', 1, 3); 456 | INSERT INTO `role_menus` VALUES (229, '2024-09-03 16:51:15.537', '2024-09-03 16:51:15.537', '2024-09-03 16:51:23.574', 1, 4); 457 | INSERT INTO `role_menus` VALUES (230, '2024-09-03 16:51:15.539', '2024-09-03 16:51:15.539', '2024-09-03 16:51:23.574', 1, 5); 458 | INSERT INTO `role_menus` VALUES (231, '2024-09-03 16:51:15.542', '2024-09-03 16:51:15.542', '2024-09-03 16:51:23.574', 1, 6); 459 | INSERT INTO `role_menus` VALUES (232, '2024-09-03 16:51:15.545', '2024-09-03 16:51:15.545', '2024-09-03 16:51:23.574', 1, 7); 460 | INSERT INTO `role_menus` VALUES (233, '2024-09-03 16:51:15.548', '2024-09-03 16:51:15.548', '2024-09-03 16:51:23.574', 1, 8); 461 | INSERT INTO `role_menus` VALUES (234, '2024-09-03 16:51:15.551', '2024-09-03 16:51:15.551', '2024-09-03 16:51:23.574', 1, 9); 462 | INSERT INTO `role_menus` VALUES (235, '2024-09-03 16:51:15.555', '2024-09-03 16:51:15.555', '2024-09-03 16:51:23.574', 1, 10); 463 | INSERT INTO `role_menus` VALUES (236, '2024-09-03 16:51:15.558', '2024-09-03 16:51:15.558', '2024-09-03 16:51:23.574', 1, 11); 464 | INSERT INTO `role_menus` VALUES (237, '2024-09-03 16:51:15.560', '2024-09-03 16:51:15.560', '2024-09-03 16:51:23.574', 1, 12); 465 | INSERT INTO `role_menus` VALUES (238, '2024-09-03 16:51:15.561', '2024-09-03 16:51:15.561', '2024-09-03 16:51:23.574', 1, 13); 466 | INSERT INTO `role_menus` VALUES (239, '2024-09-03 16:51:15.562', '2024-09-03 16:51:15.562', '2024-09-03 16:51:23.574', 1, 30); 467 | INSERT INTO `role_menus` VALUES (240, '2024-09-03 16:51:15.563', '2024-09-03 16:51:15.563', '2024-09-03 16:51:23.574', 1, 31); 468 | INSERT INTO `role_menus` VALUES (241, '2024-09-03 16:51:23.586', '2024-09-03 16:51:23.586', '2024-09-03 16:57:00.306', 1, 1); 469 | INSERT INTO `role_menus` VALUES (242, '2024-09-03 16:51:23.589', '2024-09-03 16:51:23.589', '2024-09-03 16:57:00.306', 1, 34); 470 | INSERT INTO `role_menus` VALUES (243, '2024-09-03 16:51:23.593', '2024-09-03 16:51:23.593', '2024-09-03 16:57:00.306', 1, 35); 471 | INSERT INTO `role_menus` VALUES (244, '2024-09-03 16:51:23.594', '2024-09-03 16:51:23.594', '2024-09-03 16:57:00.306', 1, 3); 472 | INSERT INTO `role_menus` VALUES (245, '2024-09-03 16:51:23.597', '2024-09-03 16:51:23.597', '2024-09-03 16:57:00.306', 1, 4); 473 | INSERT INTO `role_menus` VALUES (246, '2024-09-03 16:51:23.598', '2024-09-03 16:51:23.598', '2024-09-03 16:57:00.306', 1, 5); 474 | INSERT INTO `role_menus` VALUES (247, '2024-09-03 16:51:23.601', '2024-09-03 16:51:23.601', '2024-09-03 16:57:00.306', 1, 6); 475 | INSERT INTO `role_menus` VALUES (248, '2024-09-03 16:51:23.604', '2024-09-03 16:51:23.604', '2024-09-03 16:57:00.306', 1, 7); 476 | INSERT INTO `role_menus` VALUES (249, '2024-09-03 16:51:23.608', '2024-09-03 16:51:23.608', '2024-09-03 16:57:00.306', 1, 8); 477 | INSERT INTO `role_menus` VALUES (250, '2024-09-03 16:51:23.611', '2024-09-03 16:51:23.611', '2024-09-03 16:57:00.306', 1, 9); 478 | INSERT INTO `role_menus` VALUES (251, '2024-09-03 16:51:23.614', '2024-09-03 16:51:23.614', '2024-09-03 16:57:00.306', 1, 10); 479 | INSERT INTO `role_menus` VALUES (252, '2024-09-03 16:51:23.616', '2024-09-03 16:51:23.616', '2024-09-03 16:57:00.306', 1, 11); 480 | INSERT INTO `role_menus` VALUES (253, '2024-09-03 16:51:23.617', '2024-09-03 16:51:23.617', '2024-09-03 16:57:00.306', 1, 12); 481 | INSERT INTO `role_menus` VALUES (254, '2024-09-03 16:51:23.618', '2024-09-03 16:51:23.618', '2024-09-03 16:57:00.306', 1, 13); 482 | INSERT INTO `role_menus` VALUES (255, '2024-09-03 16:51:23.620', '2024-09-03 16:51:23.620', '2024-09-03 16:57:00.306', 1, 30); 483 | INSERT INTO `role_menus` VALUES (256, '2024-09-03 16:51:23.621', '2024-09-03 16:51:23.621', '2024-09-03 16:57:00.306', 1, 31); 484 | INSERT INTO `role_menus` VALUES (257, '2024-09-03 16:57:00.322', '2024-09-03 16:57:00.322', '2024-09-03 16:58:02.062', 1, 1); 485 | INSERT INTO `role_menus` VALUES (258, '2024-09-03 16:57:00.325', '2024-09-03 16:57:00.325', '2024-09-03 16:58:02.062', 1, 34); 486 | INSERT INTO `role_menus` VALUES (259, '2024-09-03 16:57:00.329', '2024-09-03 16:57:00.329', '2024-09-03 16:58:02.062', 1, 35); 487 | INSERT INTO `role_menus` VALUES (260, '2024-09-03 16:57:00.330', '2024-09-03 16:57:00.330', '2024-09-03 16:58:02.062', 1, 12); 488 | INSERT INTO `role_menus` VALUES (261, '2024-09-03 16:57:00.332', '2024-09-03 16:57:00.332', '2024-09-03 16:58:02.062', 1, 13); 489 | INSERT INTO `role_menus` VALUES (262, '2024-09-03 16:57:00.333', '2024-09-03 16:57:00.333', '2024-09-03 16:58:02.062', 1, 30); 490 | INSERT INTO `role_menus` VALUES (263, '2024-09-03 16:57:00.334', '2024-09-03 16:57:00.334', '2024-09-03 16:58:02.062', 1, 31); 491 | INSERT INTO `role_menus` VALUES (264, '2024-09-03 16:58:02.075', '2024-09-03 16:58:02.075', '2024-09-04 09:56:14.748', 1, 1); 492 | INSERT INTO `role_menus` VALUES (265, '2024-09-03 16:58:02.079', '2024-09-03 16:58:02.079', '2024-09-04 09:56:14.748', 1, 34); 493 | INSERT INTO `role_menus` VALUES (266, '2024-09-03 16:58:02.082', '2024-09-03 16:58:02.082', '2024-09-04 09:56:14.748', 1, 35); 494 | INSERT INTO `role_menus` VALUES (267, '2024-09-03 16:58:02.084', '2024-09-03 16:58:02.084', '2024-09-04 09:56:14.748', 1, 3); 495 | INSERT INTO `role_menus` VALUES (268, '2024-09-03 16:58:02.087', '2024-09-03 16:58:02.087', '2024-09-04 09:56:14.748', 1, 4); 496 | INSERT INTO `role_menus` VALUES (269, '2024-09-03 16:58:02.089', '2024-09-03 16:58:02.089', '2024-09-04 09:56:14.748', 1, 5); 497 | INSERT INTO `role_menus` VALUES (270, '2024-09-03 16:58:02.092', '2024-09-03 16:58:02.092', '2024-09-04 09:56:14.748', 1, 6); 498 | INSERT INTO `role_menus` VALUES (271, '2024-09-03 16:58:02.097', '2024-09-03 16:58:02.097', '2024-09-04 09:56:14.748', 1, 8); 499 | INSERT INTO `role_menus` VALUES (272, '2024-09-03 16:58:02.101', '2024-09-03 16:58:02.101', '2024-09-04 09:56:14.748', 1, 9); 500 | INSERT INTO `role_menus` VALUES (273, '2024-09-03 16:58:02.107', '2024-09-03 16:58:02.107', '2024-09-04 09:56:14.748', 1, 10); 501 | INSERT INTO `role_menus` VALUES (274, '2024-09-03 16:58:02.110', '2024-09-03 16:58:02.110', '2024-09-04 09:56:14.748', 1, 11); 502 | INSERT INTO `role_menus` VALUES (275, '2024-09-03 16:58:02.111', '2024-09-03 16:58:02.111', '2024-09-04 09:56:14.748', 1, 12); 503 | INSERT INTO `role_menus` VALUES (276, '2024-09-03 16:58:02.113', '2024-09-03 16:58:02.113', '2024-09-04 09:56:14.748', 1, 13); 504 | INSERT INTO `role_menus` VALUES (277, '2024-09-03 16:58:02.114', '2024-09-03 16:58:02.114', '2024-09-04 09:56:14.748', 1, 30); 505 | INSERT INTO `role_menus` VALUES (278, '2024-09-03 16:58:02.116', '2024-09-03 16:58:02.116', '2024-09-04 09:56:14.748', 1, 31); 506 | INSERT INTO `role_menus` VALUES (279, '2024-09-04 09:56:14.780', '2024-09-04 09:56:14.780', '2024-09-04 09:57:06.913', 1, 1); 507 | INSERT INTO `role_menus` VALUES (280, '2024-09-04 09:56:14.785', '2024-09-04 09:56:14.785', '2024-09-04 09:57:06.913', 1, 34); 508 | INSERT INTO `role_menus` VALUES (281, '2024-09-04 09:56:14.789', '2024-09-04 09:56:14.789', '2024-09-04 09:57:06.913', 1, 35); 509 | INSERT INTO `role_menus` VALUES (282, '2024-09-04 09:56:14.791', '2024-09-04 09:56:14.791', '2024-09-04 09:57:06.913', 1, 3); 510 | INSERT INTO `role_menus` VALUES (283, '2024-09-04 09:56:14.793', '2024-09-04 09:56:14.793', '2024-09-04 09:57:06.913', 1, 4); 511 | INSERT INTO `role_menus` VALUES (284, '2024-09-04 09:56:14.795', '2024-09-04 09:56:14.795', '2024-09-04 09:57:06.913', 1, 5); 512 | INSERT INTO `role_menus` VALUES (285, '2024-09-04 09:56:14.798', '2024-09-04 09:56:14.798', '2024-09-04 09:57:06.913', 1, 6); 513 | INSERT INTO `role_menus` VALUES (286, '2024-09-04 09:56:14.801', '2024-09-04 09:56:14.801', '2024-09-04 09:57:06.913', 1, 7); 514 | INSERT INTO `role_menus` VALUES (287, '2024-09-04 09:56:14.805', '2024-09-04 09:56:14.805', '2024-09-04 09:57:06.913', 1, 8); 515 | INSERT INTO `role_menus` VALUES (288, '2024-09-04 09:56:14.808', '2024-09-04 09:56:14.808', '2024-09-04 09:57:06.913', 1, 9); 516 | INSERT INTO `role_menus` VALUES (289, '2024-09-04 09:56:14.812', '2024-09-04 09:56:14.812', '2024-09-04 09:57:06.913', 1, 10); 517 | INSERT INTO `role_menus` VALUES (290, '2024-09-04 09:56:14.814', '2024-09-04 09:56:14.814', '2024-09-04 09:57:06.913', 1, 11); 518 | INSERT INTO `role_menus` VALUES (291, '2024-09-04 09:56:14.815', '2024-09-04 09:56:14.815', '2024-09-04 09:57:06.913', 1, 12); 519 | INSERT INTO `role_menus` VALUES (292, '2024-09-04 09:56:14.816', '2024-09-04 09:56:14.816', '2024-09-04 09:57:06.913', 1, 13); 520 | INSERT INTO `role_menus` VALUES (293, '2024-09-04 09:56:14.818', '2024-09-04 09:56:14.818', '2024-09-04 09:57:06.913', 1, 30); 521 | INSERT INTO `role_menus` VALUES (294, '2024-09-04 09:56:14.819', '2024-09-04 09:56:14.819', '2024-09-04 09:57:06.913', 1, 31); 522 | INSERT INTO `role_menus` VALUES (295, '2024-09-04 09:57:06.928', '2024-09-04 09:57:06.928', '2024-09-04 10:12:10.807', 1, 1); 523 | INSERT INTO `role_menus` VALUES (296, '2024-09-04 09:57:06.931', '2024-09-04 09:57:06.931', '2024-09-04 10:12:10.807', 1, 34); 524 | INSERT INTO `role_menus` VALUES (297, '2024-09-04 09:57:06.933', '2024-09-04 09:57:06.933', '2024-09-04 10:12:10.807', 1, 35); 525 | INSERT INTO `role_menus` VALUES (298, '2024-09-04 09:57:06.935', '2024-09-04 09:57:06.935', '2024-09-04 10:12:10.807', 1, 3); 526 | INSERT INTO `role_menus` VALUES (299, '2024-09-04 09:57:06.938', '2024-09-04 09:57:06.938', '2024-09-04 10:12:10.807', 1, 4); 527 | INSERT INTO `role_menus` VALUES (300, '2024-09-04 09:57:06.940', '2024-09-04 09:57:06.940', '2024-09-04 10:12:10.807', 1, 5); 528 | INSERT INTO `role_menus` VALUES (301, '2024-09-04 09:57:06.942', '2024-09-04 09:57:06.942', '2024-09-04 10:12:10.807', 1, 6); 529 | INSERT INTO `role_menus` VALUES (302, '2024-09-04 09:57:06.945', '2024-09-04 09:57:06.945', '2024-09-04 10:12:10.807', 1, 7); 530 | INSERT INTO `role_menus` VALUES (303, '2024-09-04 09:57:06.948', '2024-09-04 09:57:06.948', '2024-09-04 10:12:10.807', 1, 8); 531 | INSERT INTO `role_menus` VALUES (304, '2024-09-04 09:57:06.951', '2024-09-04 09:57:06.951', '2024-09-04 10:12:10.807', 1, 9); 532 | INSERT INTO `role_menus` VALUES (305, '2024-09-04 09:57:06.954', '2024-09-04 09:57:06.954', '2024-09-04 10:12:10.807', 1, 10); 533 | INSERT INTO `role_menus` VALUES (306, '2024-09-04 09:57:06.957', '2024-09-04 09:57:06.957', '2024-09-04 10:12:10.807', 1, 11); 534 | INSERT INTO `role_menus` VALUES (307, '2024-09-04 09:57:06.960', '2024-09-04 09:57:06.960', '2024-09-04 10:12:10.807', 1, 12); 535 | INSERT INTO `role_menus` VALUES (308, '2024-09-04 09:57:06.961', '2024-09-04 09:57:06.961', '2024-09-04 10:12:10.807', 1, 13); 536 | INSERT INTO `role_menus` VALUES (309, '2024-09-04 09:57:06.962', '2024-09-04 09:57:06.962', '2024-09-04 10:12:10.807', 1, 30); 537 | INSERT INTO `role_menus` VALUES (310, '2024-09-04 09:57:06.963', '2024-09-04 09:57:06.963', '2024-09-04 10:12:10.807', 1, 31); 538 | INSERT INTO `role_menus` VALUES (311, '2024-09-04 10:12:10.826', '2024-09-04 10:12:10.826', '2024-09-04 10:13:30.246', 1, 1); 539 | INSERT INTO `role_menus` VALUES (312, '2024-09-04 10:12:10.829', '2024-09-04 10:12:10.829', '2024-09-04 10:13:30.246', 1, 34); 540 | INSERT INTO `role_menus` VALUES (313, '2024-09-04 10:12:10.834', '2024-09-04 10:12:10.834', '2024-09-04 10:13:30.246', 1, 35); 541 | INSERT INTO `role_menus` VALUES (314, '2024-09-04 10:12:10.836', '2024-09-04 10:12:10.836', '2024-09-04 10:13:30.246', 1, 3); 542 | INSERT INTO `role_menus` VALUES (315, '2024-09-04 10:12:10.839', '2024-09-04 10:12:10.839', '2024-09-04 10:13:30.246', 1, 4); 543 | INSERT INTO `role_menus` VALUES (316, '2024-09-04 10:12:10.841', '2024-09-04 10:12:10.841', '2024-09-04 10:13:30.246', 1, 5); 544 | INSERT INTO `role_menus` VALUES (317, '2024-09-04 10:12:10.844', '2024-09-04 10:12:10.844', '2024-09-04 10:13:30.246', 1, 6); 545 | INSERT INTO `role_menus` VALUES (318, '2024-09-04 10:12:10.847', '2024-09-04 10:12:10.847', '2024-09-04 10:13:30.246', 1, 7); 546 | INSERT INTO `role_menus` VALUES (319, '2024-09-04 10:12:10.851', '2024-09-04 10:12:10.851', '2024-09-04 10:13:30.246', 1, 8); 547 | INSERT INTO `role_menus` VALUES (320, '2024-09-04 10:12:10.856', '2024-09-04 10:12:10.856', '2024-09-04 10:13:30.246', 1, 9); 548 | INSERT INTO `role_menus` VALUES (321, '2024-09-04 10:12:10.859', '2024-09-04 10:12:10.859', '2024-09-04 10:13:30.246', 1, 10); 549 | INSERT INTO `role_menus` VALUES (322, '2024-09-04 10:12:10.862', '2024-09-04 10:12:10.862', '2024-09-04 10:13:30.246', 1, 11); 550 | INSERT INTO `role_menus` VALUES (323, '2024-09-04 10:12:10.863', '2024-09-04 10:12:10.863', '2024-09-04 10:13:30.246', 1, 12); 551 | INSERT INTO `role_menus` VALUES (324, '2024-09-04 10:12:10.865', '2024-09-04 10:12:10.865', '2024-09-04 10:13:30.246', 1, 13); 552 | INSERT INTO `role_menus` VALUES (325, '2024-09-04 10:12:10.868', '2024-09-04 10:12:10.868', '2024-09-04 10:13:30.246', 1, 36); 553 | INSERT INTO `role_menus` VALUES (326, '2024-09-04 10:12:10.873', '2024-09-04 10:12:10.873', '2024-09-04 10:13:30.246', 1, 37); 554 | INSERT INTO `role_menus` VALUES (327, '2024-09-04 10:12:10.877', '2024-09-04 10:12:10.877', '2024-09-04 10:13:30.246', 1, 38); 555 | INSERT INTO `role_menus` VALUES (328, '2024-09-04 10:12:10.881', '2024-09-04 10:12:10.881', '2024-09-04 10:13:30.246', 1, 41); 556 | INSERT INTO `role_menus` VALUES (329, '2024-09-04 10:12:10.883', '2024-09-04 10:12:10.883', '2024-09-04 10:13:30.246', 1, 30); 557 | INSERT INTO `role_menus` VALUES (330, '2024-09-04 10:12:10.886', '2024-09-04 10:12:10.886', '2024-09-04 10:13:30.246', 1, 42); 558 | INSERT INTO `role_menus` VALUES (331, '2024-09-04 10:12:10.891', '2024-09-04 10:12:10.891', '2024-09-04 10:13:30.246', 1, 43); 559 | INSERT INTO `role_menus` VALUES (332, '2024-09-04 10:12:10.894', '2024-09-04 10:12:10.894', '2024-09-04 10:13:30.246', 1, 44); 560 | INSERT INTO `role_menus` VALUES (333, '2024-09-04 10:12:10.899', '2024-09-04 10:12:10.899', '2024-09-04 10:13:30.246', 1, 45); 561 | INSERT INTO `role_menus` VALUES (334, '2024-09-04 10:12:10.903', '2024-09-04 10:12:10.903', '2024-09-04 10:13:30.246', 1, 46); 562 | INSERT INTO `role_menus` VALUES (335, '2024-09-04 10:12:10.905', '2024-09-04 10:12:10.905', '2024-09-04 10:13:30.246', 1, 31); 563 | INSERT INTO `role_menus` VALUES (336, '2024-09-04 10:12:10.908', '2024-09-04 10:12:10.908', '2024-09-04 10:13:30.246', 1, 47); 564 | INSERT INTO `role_menus` VALUES (337, '2024-09-04 10:12:10.912', '2024-09-04 10:12:10.912', '2024-09-04 10:13:30.246', 1, 48); 565 | INSERT INTO `role_menus` VALUES (338, '2024-09-04 10:12:10.916', '2024-09-04 10:12:10.916', '2024-09-04 10:13:30.246', 1, 49); 566 | INSERT INTO `role_menus` VALUES (339, '2024-09-04 10:12:10.920', '2024-09-04 10:12:10.920', '2024-09-04 10:13:30.246', 1, 50); 567 | INSERT INTO `role_menus` VALUES (340, '2024-09-04 10:12:10.925', '2024-09-04 10:12:10.925', '2024-09-04 10:13:30.246', 1, 51); 568 | INSERT INTO `role_menus` VALUES (341, '2024-09-04 10:13:30.260', '2024-09-04 10:13:30.260', '2024-09-04 10:14:15.988', 1, 1); 569 | INSERT INTO `role_menus` VALUES (342, '2024-09-04 10:13:30.263', '2024-09-04 10:13:30.263', '2024-09-04 10:14:15.988', 1, 34); 570 | INSERT INTO `role_menus` VALUES (343, '2024-09-04 10:13:30.267', '2024-09-04 10:13:30.267', '2024-09-04 10:14:15.988', 1, 35); 571 | INSERT INTO `role_menus` VALUES (344, '2024-09-04 10:13:30.269', '2024-09-04 10:13:30.269', '2024-09-04 10:14:15.988', 1, 3); 572 | INSERT INTO `role_menus` VALUES (345, '2024-09-04 10:13:30.272', '2024-09-04 10:13:30.272', '2024-09-04 10:14:15.988', 1, 4); 573 | INSERT INTO `role_menus` VALUES (346, '2024-09-04 10:13:30.273', '2024-09-04 10:13:30.273', '2024-09-04 10:14:15.988', 1, 5); 574 | INSERT INTO `role_menus` VALUES (347, '2024-09-04 10:13:30.276', '2024-09-04 10:13:30.276', '2024-09-04 10:14:15.988', 1, 6); 575 | INSERT INTO `role_menus` VALUES (348, '2024-09-04 10:13:30.280', '2024-09-04 10:13:30.280', '2024-09-04 10:14:15.988', 1, 7); 576 | INSERT INTO `role_menus` VALUES (349, '2024-09-04 10:13:30.283', '2024-09-04 10:13:30.283', '2024-09-04 10:14:15.988', 1, 8); 577 | INSERT INTO `role_menus` VALUES (350, '2024-09-04 10:13:30.287', '2024-09-04 10:13:30.287', '2024-09-04 10:14:15.988', 1, 9); 578 | INSERT INTO `role_menus` VALUES (351, '2024-09-04 10:13:30.293', '2024-09-04 10:13:30.293', '2024-09-04 10:14:15.988', 1, 10); 579 | INSERT INTO `role_menus` VALUES (352, '2024-09-04 10:13:30.297', '2024-09-04 10:13:30.297', '2024-09-04 10:14:15.988', 1, 11); 580 | INSERT INTO `role_menus` VALUES (353, '2024-09-04 10:13:30.300', '2024-09-04 10:13:30.300', '2024-09-04 10:14:15.988', 1, 12); 581 | INSERT INTO `role_menus` VALUES (354, '2024-09-04 10:13:30.302', '2024-09-04 10:13:30.302', '2024-09-04 10:14:15.988', 1, 13); 582 | INSERT INTO `role_menus` VALUES (355, '2024-09-04 10:13:30.305', '2024-09-04 10:13:30.305', '2024-09-04 10:14:15.988', 1, 36); 583 | INSERT INTO `role_menus` VALUES (356, '2024-09-04 10:13:30.309', '2024-09-04 10:13:30.309', '2024-09-04 10:14:15.988', 1, 37); 584 | INSERT INTO `role_menus` VALUES (357, '2024-09-04 10:13:30.313', '2024-09-04 10:13:30.313', '2024-09-04 10:14:15.988', 1, 38); 585 | INSERT INTO `role_menus` VALUES (358, '2024-09-04 10:13:30.318', '2024-09-04 10:13:30.318', '2024-09-04 10:14:15.988', 1, 41); 586 | INSERT INTO `role_menus` VALUES (359, '2024-09-04 10:13:30.321', '2024-09-04 10:13:30.321', '2024-09-04 10:14:15.988', 1, 30); 587 | INSERT INTO `role_menus` VALUES (360, '2024-09-04 10:13:30.324', '2024-09-04 10:13:30.324', '2024-09-04 10:14:15.988', 1, 42); 588 | INSERT INTO `role_menus` VALUES (361, '2024-09-04 10:13:30.328', '2024-09-04 10:13:30.328', '2024-09-04 10:14:15.988', 1, 43); 589 | INSERT INTO `role_menus` VALUES (362, '2024-09-04 10:13:30.333', '2024-09-04 10:13:30.333', '2024-09-04 10:14:15.988', 1, 44); 590 | INSERT INTO `role_menus` VALUES (363, '2024-09-04 10:13:30.339', '2024-09-04 10:13:30.339', '2024-09-04 10:14:15.988', 1, 45); 591 | INSERT INTO `role_menus` VALUES (364, '2024-09-04 10:13:30.344', '2024-09-04 10:13:30.344', '2024-09-04 10:14:15.988', 1, 46); 592 | INSERT INTO `role_menus` VALUES (365, '2024-09-04 10:13:30.346', '2024-09-04 10:13:30.346', '2024-09-04 10:14:15.988', 1, 31); 593 | INSERT INTO `role_menus` VALUES (366, '2024-09-04 10:13:30.352', '2024-09-04 10:13:30.352', '2024-09-04 10:14:15.988', 1, 47); 594 | INSERT INTO `role_menus` VALUES (367, '2024-09-04 10:13:30.356', '2024-09-04 10:13:30.356', '2024-09-04 10:14:15.988', 1, 48); 595 | INSERT INTO `role_menus` VALUES (368, '2024-09-04 10:13:30.360', '2024-09-04 10:13:30.360', '2024-09-04 10:14:15.988', 1, 49); 596 | INSERT INTO `role_menus` VALUES (369, '2024-09-04 10:13:30.367', '2024-09-04 10:13:30.367', '2024-09-04 10:14:15.988', 1, 50); 597 | INSERT INTO `role_menus` VALUES (370, '2024-09-04 10:13:30.372', '2024-09-04 10:13:30.372', '2024-09-04 10:14:15.988', 1, 51); 598 | INSERT INTO `role_menus` VALUES (371, '2024-09-04 10:14:16.003', '2024-09-04 10:14:16.003', '2024-09-07 17:01:31.705', 1, 1); 599 | INSERT INTO `role_menus` VALUES (372, '2024-09-04 10:14:16.006', '2024-09-04 10:14:16.006', '2024-09-07 17:01:31.705', 1, 34); 600 | INSERT INTO `role_menus` VALUES (373, '2024-09-04 10:14:16.010', '2024-09-04 10:14:16.010', '2024-09-07 17:01:31.705', 1, 35); 601 | INSERT INTO `role_menus` VALUES (374, '2024-09-04 10:14:16.012', '2024-09-04 10:14:16.012', '2024-09-07 17:01:31.705', 1, 3); 602 | INSERT INTO `role_menus` VALUES (375, '2024-09-04 10:14:16.015', '2024-09-04 10:14:16.015', '2024-09-07 17:01:31.705', 1, 4); 603 | INSERT INTO `role_menus` VALUES (376, '2024-09-04 10:14:16.017', '2024-09-04 10:14:16.017', '2024-09-07 17:01:31.705', 1, 5); 604 | INSERT INTO `role_menus` VALUES (377, '2024-09-04 10:14:16.020', '2024-09-04 10:14:16.020', '2024-09-07 17:01:31.705', 1, 6); 605 | INSERT INTO `role_menus` VALUES (378, '2024-09-04 10:14:16.023', '2024-09-04 10:14:16.023', '2024-09-07 17:01:31.705', 1, 7); 606 | INSERT INTO `role_menus` VALUES (379, '2024-09-04 10:14:16.027', '2024-09-04 10:14:16.027', '2024-09-07 17:01:31.705', 1, 8); 607 | INSERT INTO `role_menus` VALUES (380, '2024-09-04 10:14:16.031', '2024-09-04 10:14:16.031', '2024-09-07 17:01:31.705', 1, 9); 608 | INSERT INTO `role_menus` VALUES (381, '2024-09-04 10:14:16.036', '2024-09-04 10:14:16.036', '2024-09-07 17:01:31.705', 1, 10); 609 | INSERT INTO `role_menus` VALUES (382, '2024-09-04 10:14:16.040', '2024-09-04 10:14:16.040', '2024-09-07 17:01:31.705', 1, 11); 610 | INSERT INTO `role_menus` VALUES (383, '2024-09-04 10:14:16.042', '2024-09-04 10:14:16.042', '2024-09-07 17:01:31.705', 1, 12); 611 | INSERT INTO `role_menus` VALUES (384, '2024-09-04 10:14:16.044', '2024-09-04 10:14:16.044', '2024-09-07 17:01:31.705', 1, 13); 612 | INSERT INTO `role_menus` VALUES (385, '2024-09-04 10:14:16.046', '2024-09-04 10:14:16.046', '2024-09-07 17:01:31.705', 1, 36); 613 | INSERT INTO `role_menus` VALUES (386, '2024-09-04 10:14:16.051', '2024-09-04 10:14:16.051', '2024-09-07 17:01:31.705', 1, 37); 614 | INSERT INTO `role_menus` VALUES (387, '2024-09-04 10:14:16.055', '2024-09-04 10:14:16.055', '2024-09-07 17:01:31.705', 1, 38); 615 | INSERT INTO `role_menus` VALUES (388, '2024-09-04 10:14:16.058', '2024-09-04 10:14:16.058', '2024-09-07 17:01:31.705', 1, 41); 616 | INSERT INTO `role_menus` VALUES (389, '2024-09-04 10:14:16.062', '2024-09-04 10:14:16.062', '2024-09-07 17:01:31.705', 1, 30); 617 | INSERT INTO `role_menus` VALUES (390, '2024-09-04 10:14:16.067', '2024-09-04 10:14:16.067', '2024-09-07 17:01:31.705', 1, 42); 618 | INSERT INTO `role_menus` VALUES (391, '2024-09-04 10:14:16.071', '2024-09-04 10:14:16.071', '2024-09-07 17:01:31.705', 1, 43); 619 | INSERT INTO `role_menus` VALUES (392, '2024-09-04 10:14:16.075', '2024-09-04 10:14:16.075', '2024-09-07 17:01:31.705', 1, 44); 620 | INSERT INTO `role_menus` VALUES (393, '2024-09-04 10:14:16.080', '2024-09-04 10:14:16.080', '2024-09-07 17:01:31.705', 1, 45); 621 | INSERT INTO `role_menus` VALUES (394, '2024-09-04 10:14:16.085', '2024-09-04 10:14:16.085', '2024-09-07 17:01:31.705', 1, 46); 622 | INSERT INTO `role_menus` VALUES (395, '2024-09-04 10:14:16.091', '2024-09-04 10:14:16.091', '2024-09-07 17:01:31.705', 1, 31); 623 | INSERT INTO `role_menus` VALUES (396, '2024-09-04 10:14:16.096', '2024-09-04 10:14:16.096', '2024-09-07 17:01:31.705', 1, 47); 624 | INSERT INTO `role_menus` VALUES (397, '2024-09-04 10:14:16.101', '2024-09-04 10:14:16.101', '2024-09-07 17:01:31.705', 1, 48); 625 | INSERT INTO `role_menus` VALUES (398, '2024-09-04 10:14:16.106', '2024-09-04 10:14:16.106', '2024-09-07 17:01:31.705', 1, 49); 626 | INSERT INTO `role_menus` VALUES (399, '2024-09-04 10:14:16.110', '2024-09-04 10:14:16.110', '2024-09-07 17:01:31.705', 1, 50); 627 | INSERT INTO `role_menus` VALUES (400, '2024-09-04 10:14:16.117', '2024-09-04 10:14:16.117', '2024-09-07 17:01:31.705', 1, 51); 628 | INSERT INTO `role_menus` VALUES (401, '2024-09-07 17:01:31.735', '2024-09-07 17:01:31.735', '2024-09-07 17:02:16.649', 1, 1); 629 | INSERT INTO `role_menus` VALUES (402, '2024-09-07 17:01:31.738', '2024-09-07 17:01:31.738', '2024-09-07 17:02:16.649', 1, 34); 630 | INSERT INTO `role_menus` VALUES (403, '2024-09-07 17:01:31.741', '2024-09-07 17:01:31.741', '2024-09-07 17:02:16.649', 1, 35); 631 | INSERT INTO `role_menus` VALUES (404, '2024-09-07 17:01:31.742', '2024-09-07 17:01:31.742', '2024-09-07 17:02:16.649', 1, 12); 632 | INSERT INTO `role_menus` VALUES (405, '2024-09-07 17:01:31.744', '2024-09-07 17:01:31.744', '2024-09-07 17:02:16.649', 1, 13); 633 | INSERT INTO `role_menus` VALUES (406, '2024-09-07 17:01:31.746', '2024-09-07 17:01:31.746', '2024-09-07 17:02:16.649', 1, 36); 634 | INSERT INTO `role_menus` VALUES (407, '2024-09-07 17:01:31.748', '2024-09-07 17:01:31.748', '2024-09-07 17:02:16.649', 1, 37); 635 | INSERT INTO `role_menus` VALUES (408, '2024-09-07 17:01:31.751', '2024-09-07 17:01:31.751', '2024-09-07 17:02:16.649', 1, 38); 636 | INSERT INTO `role_menus` VALUES (409, '2024-09-07 17:01:31.753', '2024-09-07 17:01:31.753', '2024-09-07 17:02:16.649', 1, 41); 637 | INSERT INTO `role_menus` VALUES (410, '2024-09-07 17:01:31.756', '2024-09-07 17:01:31.756', '2024-09-07 17:02:16.649', 1, 30); 638 | INSERT INTO `role_menus` VALUES (411, '2024-09-07 17:01:31.758', '2024-09-07 17:01:31.758', '2024-09-07 17:02:16.649', 1, 42); 639 | INSERT INTO `role_menus` VALUES (412, '2024-09-07 17:01:31.761', '2024-09-07 17:01:31.761', '2024-09-07 17:02:16.649', 1, 43); 640 | INSERT INTO `role_menus` VALUES (413, '2024-09-07 17:01:31.763', '2024-09-07 17:01:31.763', '2024-09-07 17:02:16.649', 1, 44); 641 | INSERT INTO `role_menus` VALUES (414, '2024-09-07 17:01:31.766', '2024-09-07 17:01:31.766', '2024-09-07 17:02:16.649', 1, 45); 642 | INSERT INTO `role_menus` VALUES (415, '2024-09-07 17:01:31.768', '2024-09-07 17:01:31.768', '2024-09-07 17:02:16.649', 1, 46); 643 | INSERT INTO `role_menus` VALUES (416, '2024-09-07 17:01:31.770', '2024-09-07 17:01:31.770', '2024-09-07 17:02:16.649', 1, 31); 644 | INSERT INTO `role_menus` VALUES (417, '2024-09-07 17:01:31.773', '2024-09-07 17:01:31.773', '2024-09-07 17:02:16.649', 1, 47); 645 | INSERT INTO `role_menus` VALUES (418, '2024-09-07 17:01:31.775', '2024-09-07 17:01:31.775', '2024-09-07 17:02:16.649', 1, 48); 646 | INSERT INTO `role_menus` VALUES (419, '2024-09-07 17:01:31.778', '2024-09-07 17:01:31.778', '2024-09-07 17:02:16.649', 1, 49); 647 | INSERT INTO `role_menus` VALUES (420, '2024-09-07 17:01:31.781', '2024-09-07 17:01:31.781', '2024-09-07 17:02:16.649', 1, 50); 648 | INSERT INTO `role_menus` VALUES (421, '2024-09-07 17:01:31.783', '2024-09-07 17:01:31.783', '2024-09-07 17:02:16.649', 1, 51); 649 | INSERT INTO `role_menus` VALUES (422, '2024-09-07 17:02:16.666', '2024-09-07 17:02:16.666', '2024-09-10 11:18:28.128', 1, 1); 650 | INSERT INTO `role_menus` VALUES (423, '2024-09-07 17:02:16.668', '2024-09-07 17:02:16.668', '2024-09-10 11:18:28.128', 1, 34); 651 | INSERT INTO `role_menus` VALUES (424, '2024-09-07 17:02:16.671', '2024-09-07 17:02:16.671', '2024-09-10 11:18:28.128', 1, 35); 652 | INSERT INTO `role_menus` VALUES (425, '2024-09-07 17:02:16.672', '2024-09-07 17:02:16.672', '2024-09-10 11:18:28.128', 1, 3); 653 | INSERT INTO `role_menus` VALUES (426, '2024-09-07 17:02:16.675', '2024-09-07 17:02:16.675', '2024-09-10 11:18:28.128', 1, 4); 654 | INSERT INTO `role_menus` VALUES (427, '2024-09-07 17:02:16.677', '2024-09-07 17:02:16.677', '2024-09-10 11:18:28.128', 1, 5); 655 | INSERT INTO `role_menus` VALUES (428, '2024-09-07 17:02:16.681', '2024-09-07 17:02:16.681', '2024-09-10 11:18:28.128', 1, 10); 656 | INSERT INTO `role_menus` VALUES (429, '2024-09-07 17:02:16.683', '2024-09-07 17:02:16.683', '2024-09-10 11:18:28.128', 1, 11); 657 | INSERT INTO `role_menus` VALUES (430, '2024-09-07 17:02:16.684', '2024-09-07 17:02:16.684', '2024-09-10 11:18:28.128', 1, 12); 658 | INSERT INTO `role_menus` VALUES (431, '2024-09-07 17:02:16.685', '2024-09-07 17:02:16.685', '2024-09-10 11:18:28.128', 1, 13); 659 | INSERT INTO `role_menus` VALUES (432, '2024-09-07 17:02:16.688', '2024-09-07 17:02:16.688', '2024-09-10 11:18:28.128', 1, 36); 660 | INSERT INTO `role_menus` VALUES (433, '2024-09-07 17:02:16.691', '2024-09-07 17:02:16.691', '2024-09-10 11:18:28.128', 1, 37); 661 | INSERT INTO `role_menus` VALUES (434, '2024-09-07 17:02:16.693', '2024-09-07 17:02:16.693', '2024-09-10 11:18:28.128', 1, 38); 662 | INSERT INTO `role_menus` VALUES (435, '2024-09-07 17:02:16.696', '2024-09-07 17:02:16.696', '2024-09-10 11:18:28.128', 1, 41); 663 | INSERT INTO `role_menus` VALUES (436, '2024-09-07 17:02:16.698', '2024-09-07 17:02:16.698', '2024-09-10 11:18:28.128', 1, 30); 664 | INSERT INTO `role_menus` VALUES (437, '2024-09-07 17:02:16.701', '2024-09-07 17:02:16.701', '2024-09-10 11:18:28.128', 1, 42); 665 | INSERT INTO `role_menus` VALUES (438, '2024-09-07 17:02:16.707', '2024-09-07 17:02:16.707', '2024-09-10 11:18:28.128', 1, 43); 666 | INSERT INTO `role_menus` VALUES (439, '2024-09-07 17:02:16.711', '2024-09-07 17:02:16.711', '2024-09-10 11:18:28.128', 1, 44); 667 | INSERT INTO `role_menus` VALUES (440, '2024-09-07 17:02:16.715', '2024-09-07 17:02:16.715', '2024-09-10 11:18:28.128', 1, 45); 668 | INSERT INTO `role_menus` VALUES (441, '2024-09-07 17:02:16.718', '2024-09-07 17:02:16.718', '2024-09-10 11:18:28.128', 1, 46); 669 | INSERT INTO `role_menus` VALUES (442, '2024-09-07 17:02:16.721', '2024-09-07 17:02:16.721', '2024-09-10 11:18:28.128', 1, 31); 670 | INSERT INTO `role_menus` VALUES (443, '2024-09-07 17:02:16.724', '2024-09-07 17:02:16.724', '2024-09-10 11:18:28.128', 1, 47); 671 | INSERT INTO `role_menus` VALUES (444, '2024-09-07 17:02:16.727', '2024-09-07 17:02:16.727', '2024-09-10 11:18:28.128', 1, 48); 672 | INSERT INTO `role_menus` VALUES (445, '2024-09-07 17:02:16.729', '2024-09-07 17:02:16.729', '2024-09-10 11:18:28.128', 1, 49); 673 | INSERT INTO `role_menus` VALUES (446, '2024-09-07 17:02:16.732', '2024-09-07 17:02:16.732', '2024-09-10 11:18:28.128', 1, 50); 674 | INSERT INTO `role_menus` VALUES (447, '2024-09-07 17:02:16.735', '2024-09-07 17:02:16.735', '2024-09-10 11:18:28.128', 1, 51); 675 | INSERT INTO `role_menus` VALUES (448, '2024-09-10 11:18:28.150', '2024-09-10 11:18:28.150', NULL, 1, 1); 676 | INSERT INTO `role_menus` VALUES (449, '2024-09-10 11:18:28.154', '2024-09-10 11:18:28.154', NULL, 1, 34); 677 | INSERT INTO `role_menus` VALUES (450, '2024-09-10 11:18:28.157', '2024-09-10 11:18:28.157', NULL, 1, 35); 678 | INSERT INTO `role_menus` VALUES (451, '2024-09-10 11:18:28.158', '2024-09-10 11:18:28.158', NULL, 1, 3); 679 | INSERT INTO `role_menus` VALUES (452, '2024-09-10 11:18:28.160', '2024-09-10 11:18:28.160', NULL, 1, 4); 680 | INSERT INTO `role_menus` VALUES (453, '2024-09-10 11:18:28.161', '2024-09-10 11:18:28.161', NULL, 1, 5); 681 | INSERT INTO `role_menus` VALUES (454, '2024-09-10 11:18:28.164', '2024-09-10 11:18:28.164', NULL, 1, 6); 682 | INSERT INTO `role_menus` VALUES (455, '2024-09-10 11:18:28.166', '2024-09-10 11:18:28.166', NULL, 1, 7); 683 | INSERT INTO `role_menus` VALUES (456, '2024-09-10 11:18:28.168', '2024-09-10 11:18:28.168', NULL, 1, 8); 684 | INSERT INTO `role_menus` VALUES (457, '2024-09-10 11:18:28.171', '2024-09-10 11:18:28.171', NULL, 1, 9); 685 | INSERT INTO `role_menus` VALUES (458, '2024-09-10 11:18:28.173', '2024-09-10 11:18:28.173', NULL, 1, 10); 686 | INSERT INTO `role_menus` VALUES (459, '2024-09-10 11:18:28.176', '2024-09-10 11:18:28.176', NULL, 1, 11); 687 | INSERT INTO `role_menus` VALUES (460, '2024-09-10 11:18:28.178', '2024-09-10 11:18:28.178', NULL, 1, 52); 688 | INSERT INTO `role_menus` VALUES (461, '2024-09-10 11:18:28.181', '2024-09-10 11:18:28.181', NULL, 1, 53); 689 | INSERT INTO `role_menus` VALUES (462, '2024-09-10 11:18:28.183', '2024-09-10 11:18:28.183', NULL, 1, 54); 690 | INSERT INTO `role_menus` VALUES (463, '2024-09-10 11:18:28.184', '2024-09-10 11:18:28.184', NULL, 1, 12); 691 | INSERT INTO `role_menus` VALUES (464, '2024-09-10 11:18:28.185', '2024-09-10 11:18:28.185', NULL, 1, 13); 692 | INSERT INTO `role_menus` VALUES (465, '2024-09-10 11:18:28.187', '2024-09-10 11:18:28.187', NULL, 1, 36); 693 | INSERT INTO `role_menus` VALUES (466, '2024-09-10 11:18:28.190', '2024-09-10 11:18:28.190', NULL, 1, 37); 694 | INSERT INTO `role_menus` VALUES (467, '2024-09-10 11:18:28.193', '2024-09-10 11:18:28.193', NULL, 1, 38); 695 | INSERT INTO `role_menus` VALUES (468, '2024-09-10 11:18:28.196', '2024-09-10 11:18:28.196', NULL, 1, 41); 696 | INSERT INTO `role_menus` VALUES (469, '2024-09-10 11:18:28.198', '2024-09-10 11:18:28.198', NULL, 1, 30); 697 | INSERT INTO `role_menus` VALUES (470, '2024-09-10 11:18:28.200', '2024-09-10 11:18:28.200', NULL, 1, 42); 698 | INSERT INTO `role_menus` VALUES (471, '2024-09-10 11:18:28.203', '2024-09-10 11:18:28.203', NULL, 1, 43); 699 | INSERT INTO `role_menus` VALUES (472, '2024-09-10 11:18:28.206', '2024-09-10 11:18:28.206', NULL, 1, 44); 700 | INSERT INTO `role_menus` VALUES (473, '2024-09-10 11:18:28.209', '2024-09-10 11:18:28.209', NULL, 1, 45); 701 | INSERT INTO `role_menus` VALUES (474, '2024-09-10 11:18:28.211', '2024-09-10 11:18:28.211', NULL, 1, 46); 702 | INSERT INTO `role_menus` VALUES (475, '2024-09-10 11:18:28.214', '2024-09-10 11:18:28.214', NULL, 1, 31); 703 | INSERT INTO `role_menus` VALUES (476, '2024-09-10 11:18:28.216', '2024-09-10 11:18:28.216', NULL, 1, 47); 704 | INSERT INTO `role_menus` VALUES (477, '2024-09-10 11:18:28.219', '2024-09-10 11:18:28.219', NULL, 1, 48); 705 | INSERT INTO `role_menus` VALUES (478, '2024-09-10 11:18:28.221', '2024-09-10 11:18:28.221', NULL, 1, 49); 706 | INSERT INTO `role_menus` VALUES (479, '2024-09-10 11:18:28.224', '2024-09-10 11:18:28.224', NULL, 1, 50); 707 | INSERT INTO `role_menus` VALUES (480, '2024-09-10 11:18:28.227', '2024-09-10 11:18:28.227', NULL, 1, 51); 708 | 709 | -- ---------------------------- 710 | -- Table structure for roles 711 | -- ---------------------------- 712 | DROP TABLE IF EXISTS `roles`; 713 | CREATE TABLE `roles` ( 714 | `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT, 715 | `created_at` datetime(3) NULL DEFAULT NULL, 716 | `updated_at` datetime(3) NULL DEFAULT NULL, 717 | `deleted_at` datetime(3) NULL DEFAULT NULL, 718 | `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '角色名称', 719 | `code` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '角色代码', 720 | PRIMARY KEY (`id`) USING BTREE, 721 | UNIQUE INDEX `uni_roles_code`(`code` ASC) USING BTREE, 722 | INDEX `idx_roles_deleted_at`(`deleted_at` ASC) USING BTREE 723 | ) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; 724 | 725 | -- ---------------------------- 726 | -- Records of roles 727 | -- ---------------------------- 728 | INSERT INTO `roles` VALUES (1, '2024-09-03 10:32:38.239', '2024-09-03 10:32:38.239', NULL, '管理员', 'admin'); 729 | INSERT INTO `roles` VALUES (2, '2024-09-03 11:22:58.693', '2024-09-03 11:22:58.693', NULL, '测试', 'test'); 730 | INSERT INTO `roles` VALUES (4, '2024-09-03 11:23:11.209', '2024-09-03 11:23:11.209', NULL, '测试2', 'test2'); 731 | 732 | -- ---------------------------- 733 | -- Table structure for users 734 | -- ---------------------------- 735 | DROP TABLE IF EXISTS `users`; 736 | CREATE TABLE `users` ( 737 | `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT, 738 | `created_at` datetime(3) NULL DEFAULT NULL, 739 | `updated_at` datetime(3) NULL DEFAULT NULL, 740 | `deleted_at` datetime(3) NULL DEFAULT NULL, 741 | `phone` varchar(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '手机', 742 | `password` varchar(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '密码', 743 | `pid` bigint NOT NULL DEFAULT 0 COMMENT '父ID', 744 | `real_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '真实姓名', 745 | `id_card` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '身份证号码', 746 | PRIMARY KEY (`id`) USING BTREE, 747 | INDEX `idx_users_deleted_at`(`deleted_at` ASC) USING BTREE 748 | ) ENGINE = InnoDB AUTO_INCREMENT = 9 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; 749 | 750 | -- ---------------------------- 751 | -- Records of users 752 | -- ---------------------------- 753 | 754 | SET FOREIGN_KEY_CHECKS = 1; 755 | -------------------------------------------------------------------------------- /job/TestJob.go: -------------------------------------------------------------------------------- 1 | package job 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "fmt" 7 | "github.com/hibiken/asynq" 8 | "go.uber.org/zap" 9 | "vgo/core/log" 10 | ) 11 | 12 | const ( 13 | TestJob = "test:job" 14 | ) 15 | 16 | // TestJobPayload 任务参数 17 | type TestJobPayload struct { 18 | UserID int 19 | TemplateID string 20 | } 21 | 22 | // NewTestJob 创建一个新的测试任务 23 | func NewTestJob(userID int, tmplID string) (*asynq.Task, error) { 24 | payload, err := json.Marshal(TestJobPayload{UserID: userID, TemplateID: tmplID}) 25 | if err != nil { 26 | return nil, err 27 | } 28 | return asynq.NewTask(TestJob, payload), nil 29 | } 30 | 31 | // HandleTestJobTask 处理测试任务 32 | func HandleTestJobTask(ctx context.Context, t *asynq.Task) error { 33 | var p TestJobPayload 34 | if err := json.Unmarshal(t.Payload(), &p); err != nil { 35 | log.GetLogger().Error("test:job-json.Unmarshal failed: %v", zap.Any("task-err", err), zap.Any("task-asynq", asynq.SkipRetry)) 36 | } 37 | fmt.Println(fmt.Sprintf("test:job to User: user_id=%d, template_id=%s", p.UserID, p.TemplateID)) 38 | return nil 39 | } 40 | 41 | // 使用示例: 42 | //func Index(ctx *gin.Context) { 43 | // client, err := queue.NewRedisClient() 44 | // if err != nil { 45 | // fmt.Println("Failed to create redis client:", err) 46 | // return 47 | // } 48 | // defer queue.CloseRedisClient(client) 49 | // task, err := job.NewTestJob(42, "666666") 50 | // if err != nil { 51 | // log.GetLogger().Error(fmt.Sprintf("could not create task: %v", err)) 52 | // } 53 | // info, err := client.Enqueue(task) 54 | // if err != nil { 55 | // log.GetLogger().Error(fmt.Sprintf("could not enqueue task: %v", err)) 56 | // } 57 | // log.GetLogger().Info(fmt.Sprintf("enqueued task: id=%s queue=%s", info.ID, info.Queue)) 58 | //} 59 | -------------------------------------------------------------------------------- /job/job.go: -------------------------------------------------------------------------------- 1 | package job 2 | 3 | import ( 4 | "github.com/hibiken/asynq" 5 | ) 6 | 7 | // JobMaps 任务处理器映射 8 | var JobMaps = map[string]asynq.HandlerFunc{ 9 | TestJob: HandleTestJobTask, 10 | // 添加其他任务处理对儿 11 | // "...": ..., 12 | } 13 | -------------------------------------------------------------------------------- /lang/en/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "用户名不能为空": "Username cannot be empty", 3 | "手机号不能为空" : "Phone number cannot be empty", 4 | "Token无效": "Invalid Token" 5 | } -------------------------------------------------------------------------------- /lang/zh-cn/zh-cn.json: -------------------------------------------------------------------------------- 1 | { 2 | "用户名不能为空": "用户名不能为空", 3 | "手机号不能为空" : "手机号不能为空-%s-%v", 4 | "Token无效": "Token无效" 5 | } -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "vgo/bootstrap" 5 | ) 6 | 7 | func main() { 8 | bootstrap.Start() 9 | } 10 | -------------------------------------------------------------------------------- /rbac.conf: -------------------------------------------------------------------------------- 1 | [request_definition] 2 | r = sub, obj 3 | 4 | [policy_definition] 5 | p = sub, obj 6 | 7 | [role_definition] 8 | g = _, _ 9 | 10 | [policy_effect] 11 | e = some(where (p.eft == allow)) 12 | 13 | [matchers] 14 | m = g(r.sub, p.sub) && keyMatch2(r.obj, p.obj) -------------------------------------------------------------------------------- /route/route.go: -------------------------------------------------------------------------------- 1 | package route 2 | 3 | import ( 4 | "github.com/gin-contrib/cors" 5 | "github.com/gin-gonic/gin" 6 | "strings" 7 | "time" 8 | AdminUserController "vgo/app/AdminUser/Bapi" 9 | AdminUser "vgo/app/AdminUser/Router" 10 | Common "vgo/app/Common/Bapi" 11 | Menu "vgo/app/Menu/Router" 12 | Notice "vgo/app/Notice/Router" 13 | Role "vgo/app/Role/Router" 14 | System "vgo/app/System/Bapi" 15 | "vgo/app/Test" 16 | Upload "vgo/app/Upload/Router" 17 | UserController "vgo/app/User/Api" 18 | User "vgo/app/User/Router" 19 | "vgo/app/Ws" 20 | "vgo/core/global" 21 | "vgo/core/middle/auth" 22 | "vgo/core/middle/casbin" 23 | "vgo/core/response" 24 | "vgo/core/router" 25 | ) 26 | 27 | // CollectRoute 注册路由 28 | func CollectRoute(app *gin.Engine) *gin.Engine { 29 | // 全局限流 30 | //app.Use(middle.RateLimiter(60, time.Second*60)) 31 | 32 | // 跨域处理 33 | origins := global.App.Config.App.ApiOrigins 34 | allowedOrigins := strings.Split(origins, ",") 35 | app.Use(cors.New(cors.Config{ 36 | AllowOrigins: allowedOrigins, 37 | AllowMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"}, 38 | AllowHeaders: []string{"Origin", "Authorization", "Content-Type"}, 39 | ExposeHeaders: []string{"Content-Length"}, 40 | AllowCredentials: true, 41 | MaxAge: 12 * time.Hour, 42 | })) 43 | 44 | // 找不到路由 45 | app.NoRoute(func(c *gin.Context) { 46 | response.Fail(c, "请求地址不存在!", nil) 47 | }) 48 | // 找不到方法 49 | app.NoMethod(func(c *gin.Context) { 50 | response.Fail(c, "请求方法不存在!", nil) 51 | }) 52 | 53 | app.GET("/test", Test.Index) 54 | app.POST("/test2", Test.Index2) 55 | 56 | app.GET("/ws/link", Ws.Link) 57 | app.POST("/ws/send", Ws.Send) 58 | app.POST("/ws/send_to_all", Ws.SendToAll) 59 | 60 | admin := app.Group("/admin") 61 | admin.GET("/common/get_gender", Common.GetGender) 62 | admin.GET("/system/getBingBackgroundImage", System.GetBingBackgroundImage) 63 | admin.POST("/admin_user/login", AdminUserController.Login) 64 | 65 | bapiRouters := router.CollectRoutesFromModules( 66 | Notice.CollectRoutes, 67 | Menu.CollectRoutes, 68 | AdminUser.CollectRoutes, 69 | Role.CollectRoutes, 70 | Upload.CollectRoutes, 71 | ) 72 | 73 | enforcer := casbin.SetupCasbin() 74 | admin.Use(auth.AdminAuthMiddleware(), casbin.CheckMiddleware(enforcer)) 75 | 76 | for _, route := range bapiRouters { 77 | admin.Handle(route.Method, route.Path, route.Handler) 78 | } 79 | 80 | api := app.Group("/api") 81 | api.POST("/user/register", UserController.Register) 82 | api.POST("/user/get_token", UserController.GetToken) 83 | api.POST("/user/set_back", UserController.Setback) 84 | apiRouters := router.CollectRoutesFromModules( 85 | User.CollectRoutes, 86 | ) 87 | api.Use(auth.UserAuthMiddleware()) 88 | { 89 | for _, route := range apiRouters { 90 | api.Handle(route.Method, route.Path, route.Handler) 91 | } 92 | } 93 | return app 94 | } 95 | -------------------------------------------------------------------------------- /storage/.gitignore: -------------------------------------------------------------------------------- 1 | !.gitignore 2 | -------------------------------------------------------------------------------- /storage/logs/.gitignore: -------------------------------------------------------------------------------- 1 | !.gitignore 2 | * -------------------------------------------------------------------------------- /vTools/tools/makeCurd.go: -------------------------------------------------------------------------------- 1 | package tools 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "io" 7 | "os" 8 | "path/filepath" 9 | "strings" 10 | ) 11 | 12 | func MakeCurd(moduleHandle *string, noteHandle *string) { 13 | // 获取模块名称 14 | module := *moduleHandle 15 | // 获取注释内容 16 | note := *noteHandle 17 | // 复制app目录下的指定文件夹并重命名保存 18 | newSrc := filepath.Join("app", module) 19 | if err := copyFolder("core/Tpl", newSrc); err != nil { 20 | fmt.Println(err.Error()) 21 | return 22 | } 23 | // 打开新的文件夹 24 | entries, err := os.ReadDir(newSrc) 25 | if err != nil { 26 | fmt.Println(err.Error()) 27 | return 28 | } 29 | var renamedPaths []string // 重命名的文件路径 30 | // 修改文件名 31 | for _, entry := range entries { 32 | if entry.IsDir() { 33 | renamedPaths = append(renamedPaths, newSrc+"\\"+entry.Name()+"\\"+module+".go") 34 | dirPath := filepath.Join(newSrc, entry.Name()) 35 | entries2, err := os.ReadDir(dirPath) 36 | if err != nil { 37 | fmt.Println(err.Error()) 38 | return 39 | } 40 | // 文件重命名 41 | for _, entry2 := range entries2 { 42 | oldName := filepath.Join(dirPath, entry2.Name()) 43 | newName := filepath.Join(dirPath, module+".go") 44 | if err := os.Rename(oldName, newName); err != nil { 45 | fmt.Println(err.Error()) 46 | return 47 | } 48 | } 49 | } 50 | } 51 | 52 | // 循环 renamedPaths 数组 53 | for _, path := range renamedPaths { 54 | // 打开文件并替换指定字符串 55 | lowerModule := strings.ToLower(module) 56 | replacements := []struct { 57 | oldString string 58 | newString string 59 | }{ 60 | {"Tpl", module}, 61 | {"tpl", lowerModule}, 62 | {"%模型名%", note}, 63 | } 64 | 65 | var err error 66 | for _, r := range replacements { 67 | err = replaceInFile(path, r.oldString, r.newString) 68 | if err != nil { 69 | break 70 | } 71 | } 72 | 73 | if err != nil { 74 | fmt.Println(err.Error()) 75 | return 76 | } 77 | } 78 | fmt.Println("代码生成成功,请手动注册路由~") 79 | } 80 | 81 | func copyFolder(src, dst string) error { 82 | // 获取源文件夹的信息 83 | srcInfo, err := os.Stat(src) 84 | if err != nil { 85 | return err 86 | } 87 | // 创建目标文件夹 88 | if err := os.MkdirAll(dst, srcInfo.Mode()); err != nil { 89 | return err 90 | } 91 | // 打开源文件夹 92 | entries, err := os.ReadDir(src) 93 | if err != nil { 94 | fmt.Println(err.Error()) 95 | return err 96 | } 97 | for _, entry := range entries { 98 | srcPath := filepath.Join(src, entry.Name()) 99 | dstPath := filepath.Join(dst, entry.Name()) 100 | if entry.Name() == "代码生成模板勿动.txt" { 101 | continue 102 | } 103 | if entry.IsDir() { 104 | // 递归复制子文件夹 105 | if err := copyFolder(srcPath, dstPath); err != nil { 106 | fmt.Println(err.Error()) 107 | return err 108 | } 109 | } else { 110 | // 复制文件 111 | if err := copyFile(srcPath, dstPath); err != nil { 112 | fmt.Println(err.Error()) 113 | return err 114 | } 115 | } 116 | } 117 | return nil 118 | } 119 | 120 | func copyFile(src, dst string) error { 121 | // 打开源文件 122 | srcFile, err := os.Open(src) 123 | if err != nil { 124 | return err 125 | } 126 | defer func(srcFile *os.File) { 127 | err := srcFile.Close() 128 | if err != nil { 129 | fmt.Println(err) 130 | panic(err) 131 | } 132 | }(srcFile) 133 | // 创建目标文件 134 | dstFile, err := os.Create(dst) 135 | if err != nil { 136 | return err 137 | } 138 | defer func(dstFile *os.File) { 139 | err := dstFile.Close() 140 | if err != nil { 141 | fmt.Println(err) 142 | panic(err) 143 | } 144 | }(dstFile) 145 | // 复制文件内容 146 | if _, err := io.Copy(dstFile, srcFile); err != nil { 147 | return err 148 | } 149 | // 同步文件 150 | if err := dstFile.Sync(); err != nil { 151 | return err 152 | } 153 | return nil 154 | } 155 | 156 | func replaceInFile(filePath, oldString, newString string) error { 157 | // 打开文件 158 | file, err := os.OpenFile(filePath, os.O_RDWR, 0644) 159 | if err != nil { 160 | return err 161 | } 162 | defer file.Close() 163 | 164 | // 读取文件内容 165 | scanner := bufio.NewScanner(file) 166 | var lines []string 167 | for scanner.Scan() { 168 | line := scanner.Text() 169 | // 替换指定字符串 170 | line = strings.Replace(line, oldString, newString, -1) 171 | lines = append(lines, line) 172 | } 173 | 174 | // 检查扫描错误 175 | if err := scanner.Err(); err != nil { 176 | return err 177 | } 178 | 179 | // 清空文件内容 180 | err = file.Truncate(0) 181 | if err != nil { 182 | return err 183 | } 184 | _, err = file.Seek(0, 0) 185 | if err != nil { 186 | return err 187 | } 188 | 189 | // 写入修改后的内容 190 | writer := bufio.NewWriter(file) 191 | for _, line := range lines { 192 | _, err := writer.WriteString(line + "\n") 193 | if err != nil { 194 | return err 195 | } 196 | } 197 | 198 | // 刷新缓冲区 199 | return writer.Flush() 200 | } 201 | -------------------------------------------------------------------------------- /vTools/vTools.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "vgo/vTools/tools" 7 | ) 8 | 9 | func main() { 10 | methodHandle := flag.String("method", "", "Curd") 11 | moduleHandle := flag.String("module", "", "模块") 12 | noteHandle := flag.String("note", "", "注释") 13 | flag.Parse() 14 | method := *methodHandle 15 | if method == "" { 16 | fmt.Println("请输入操作方法:例如,Curd") 17 | return 18 | } 19 | if method == "Curd" { 20 | if moduleHandle == nil || noteHandle == nil { 21 | fmt.Println("请输入模块和注释") 22 | return 23 | } 24 | fmt.Println("创建", *moduleHandle, "模块,注释:", *noteHandle) 25 | tools.MakeCurd(moduleHandle, noteHandle) 26 | return 27 | } 28 | 29 | fmt.Println("不受支持的操作方法") 30 | return 31 | } 32 | --------------------------------------------------------------------------------