菜单接口
This commit is contained in:
353
features/sys_menu/api_sys_menu.go
Normal file
353
features/sys_menu/api_sys_menu.go
Normal file
@@ -0,0 +1,353 @@
|
|||||||
|
package sysmenu
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"ems.agt/features/sys_menu/consts"
|
||||||
|
"ems.agt/features/sys_menu/model"
|
||||||
|
"ems.agt/features/sys_menu/service"
|
||||||
|
"ems.agt/lib/core/conf"
|
||||||
|
"ems.agt/lib/core/utils/ctx"
|
||||||
|
"ems.agt/lib/core/utils/regular"
|
||||||
|
"ems.agt/lib/core/vo/result"
|
||||||
|
"ems.agt/lib/midware"
|
||||||
|
"ems.agt/lib/services"
|
||||||
|
"ems.agt/restagent/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 菜单接口添加到路由
|
||||||
|
func Routers() []services.RouterItem {
|
||||||
|
// 实例化控制层 SysMenuApi 结构体
|
||||||
|
var apis = &SysMenuApi{
|
||||||
|
sysMenuService: service.NewServiceSysMenu,
|
||||||
|
}
|
||||||
|
|
||||||
|
rs := [...]services.RouterItem{
|
||||||
|
{
|
||||||
|
Method: "GET",
|
||||||
|
Pattern: "/menuManage/{apiVersion}/list",
|
||||||
|
Handler: apis.List,
|
||||||
|
Middleware: midware.Authorize(map[string][]string{
|
||||||
|
"hasPerms": {"system:menu:list"},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: "GET",
|
||||||
|
Pattern: "/menuManage/{apiVersion}/info/{menuId}",
|
||||||
|
Handler: apis.Info,
|
||||||
|
Middleware: midware.Authorize(map[string][]string{
|
||||||
|
"hasPerms": {"system:menu:query"},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: "POST",
|
||||||
|
Pattern: "/menuManage/{apiVersion}/add",
|
||||||
|
Handler: apis.Add,
|
||||||
|
Middleware: midware.Authorize(map[string][]string{
|
||||||
|
"hasPerms": {"system:menu:add"},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: "PUT",
|
||||||
|
Pattern: "/menuManage/{apiVersion}/edit",
|
||||||
|
Handler: apis.Edit,
|
||||||
|
Middleware: midware.Authorize(map[string][]string{
|
||||||
|
"hasPerms": {"system:menu:edit"},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: "DELETE",
|
||||||
|
Pattern: "/menuManage/{apiVersion}/del/{menuId}",
|
||||||
|
Handler: apis.Remove,
|
||||||
|
Middleware: midware.Authorize(map[string][]string{
|
||||||
|
"hasPerms": {"system:menu:edit"},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: "GET",
|
||||||
|
Pattern: "/menuManage/{apiVersion}/treeSelect",
|
||||||
|
Handler: apis.TreeSelect,
|
||||||
|
Middleware: midware.Authorize(map[string][]string{
|
||||||
|
"hasPerms": {"system:menu:list"},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: "GET",
|
||||||
|
Pattern: "/menuManage/{apiVersion}/roleMenuTreeSelect/{roleId}",
|
||||||
|
Handler: apis.RoleMenuTreeSelect,
|
||||||
|
Middleware: midware.Authorize(map[string][]string{
|
||||||
|
"hasPerms": {"system:menu:list"},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
// 添加更多的 Router 对象...
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成两组前缀路由
|
||||||
|
rsPrefix := []services.RouterItem{}
|
||||||
|
for _, v := range rs {
|
||||||
|
path := v.Pattern
|
||||||
|
// 固定前缀
|
||||||
|
v.Pattern = config.DefaultUriPrefix + path
|
||||||
|
rsPrefix = append(rsPrefix, v)
|
||||||
|
// 可配置
|
||||||
|
v.Pattern = config.UriPrefix + path
|
||||||
|
rsPrefix = append(rsPrefix, v)
|
||||||
|
}
|
||||||
|
return rsPrefix
|
||||||
|
}
|
||||||
|
|
||||||
|
// // 实例化控制层 SysMenuApi 结构体
|
||||||
|
// var NewSysMenu = &SysMenuApi{
|
||||||
|
// sysMenuService: NewServiceSysMenu,
|
||||||
|
// }
|
||||||
|
|
||||||
|
// 菜单信息
|
||||||
|
//
|
||||||
|
// PATH /menuManage
|
||||||
|
type SysMenuApi struct {
|
||||||
|
// 菜单服务
|
||||||
|
sysMenuService *service.ServiceSysMenu
|
||||||
|
}
|
||||||
|
|
||||||
|
// 菜单列表
|
||||||
|
//
|
||||||
|
// GET /list
|
||||||
|
func (s *SysMenuApi) List(w http.ResponseWriter, r *http.Request) {
|
||||||
|
query := model.SysMenu{}
|
||||||
|
if v := ctx.GetQuery(r, "menuName"); v != "" {
|
||||||
|
query.MenuName = v
|
||||||
|
}
|
||||||
|
if v := ctx.GetQuery(r, "status"); v != "" {
|
||||||
|
query.Status = v
|
||||||
|
}
|
||||||
|
|
||||||
|
userId := ctx.LoginUserToUserID(r)
|
||||||
|
if conf.IsAdmin(userId) {
|
||||||
|
userId = "*"
|
||||||
|
}
|
||||||
|
data := s.sysMenuService.SelectMenuList(query, userId)
|
||||||
|
ctx.JSON(w, 200, result.OkData(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 菜单信息
|
||||||
|
//
|
||||||
|
// GET /:menuId
|
||||||
|
func (s *SysMenuApi) Info(w http.ResponseWriter, r *http.Request) {
|
||||||
|
menuId := ctx.Param(r, "menuId")
|
||||||
|
if menuId == "" {
|
||||||
|
ctx.JSON(w, 400, result.CodeMsg(400, "参数错误"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
data := s.sysMenuService.SelectMenuById(menuId)
|
||||||
|
if data.MenuID == menuId {
|
||||||
|
ctx.JSON(w, 200, result.OkData(data))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.JSON(w, 200, result.Err(nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 菜单新增
|
||||||
|
//
|
||||||
|
// POST /
|
||||||
|
func (s *SysMenuApi) Add(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var body model.SysMenu
|
||||||
|
err := ctx.ShouldBindJSON(r, &body)
|
||||||
|
if err != nil || body.MenuID != "" {
|
||||||
|
ctx.JSON(w, 400, result.CodeMsg(400, "参数错误"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 目录和菜单检查地址唯一
|
||||||
|
if consts.TYPE_DIR == body.MenuType || consts.TYPE_MENU == body.MenuType {
|
||||||
|
uniqueNenuPath := s.sysMenuService.CheckUniqueMenuPath(body.Path, "")
|
||||||
|
if !uniqueNenuPath {
|
||||||
|
msg := fmt.Sprintf("菜单新增【%s】失败,菜单路由地址已存在", body.MenuName)
|
||||||
|
ctx.JSON(w, 200, result.ErrMsg(msg))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查名称唯一
|
||||||
|
uniqueNenuName := s.sysMenuService.CheckUniqueMenuName(body.MenuName, body.ParentID, "")
|
||||||
|
if !uniqueNenuName {
|
||||||
|
msg := fmt.Sprintf("菜单新增【%s】失败,菜单名称已存在", body.MenuName)
|
||||||
|
ctx.JSON(w, 200, result.ErrMsg(msg))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 外链菜单需要符合网站http(s)开头
|
||||||
|
if body.IsFrame == "0" && !regular.ValidHttp(body.Path) {
|
||||||
|
msg := fmt.Sprintf("菜单新增【%s】失败,非内部地址必须以http(s)://开头", body.MenuName)
|
||||||
|
ctx.JSON(w, 200, result.ErrMsg(msg))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
body.CreateBy = ctx.LoginUserToUserName(r)
|
||||||
|
insertId := s.sysMenuService.InsertMenu(body)
|
||||||
|
if insertId != "" {
|
||||||
|
ctx.JSON(w, 200, result.Ok(nil))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.JSON(w, 200, result.Err(nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 菜单修改
|
||||||
|
//
|
||||||
|
// PUT /
|
||||||
|
func (s *SysMenuApi) Edit(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var body model.SysMenu
|
||||||
|
err := ctx.ShouldBindJSON(r, &body)
|
||||||
|
if err != nil || body.MenuID == "" {
|
||||||
|
ctx.JSON(w, 400, result.CodeMsg(400, "参数错误"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 上级菜单不能选自己
|
||||||
|
if body.MenuID == body.ParentID {
|
||||||
|
msg := fmt.Sprintf("菜单修改【%s】失败,上级菜单不能选择自己", body.MenuName)
|
||||||
|
ctx.JSON(w, 200, result.ErrMsg(msg))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查数据是否存在
|
||||||
|
menuInfo := s.sysMenuService.SelectMenuById(body.MenuID)
|
||||||
|
if menuInfo.MenuID != body.MenuID {
|
||||||
|
ctx.JSON(w, 200, result.ErrMsg("没有权限访问菜单数据"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 父级ID不为0是要检查
|
||||||
|
if body.ParentID != "0" {
|
||||||
|
menuParent := s.sysMenuService.SelectMenuById(body.ParentID)
|
||||||
|
if menuParent.MenuID != body.ParentID {
|
||||||
|
ctx.JSON(w, 200, result.ErrMsg("没有权限访问菜单数据"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 目录和菜单检查地址唯一
|
||||||
|
if consts.TYPE_DIR == body.MenuType || consts.TYPE_MENU == body.MenuType {
|
||||||
|
uniqueNenuPath := s.sysMenuService.CheckUniqueMenuPath(body.Path, body.MenuID)
|
||||||
|
if !uniqueNenuPath {
|
||||||
|
msg := fmt.Sprintf("菜单修改【%s】失败,菜单路由地址已存在", body.MenuName)
|
||||||
|
ctx.JSON(w, 200, result.ErrMsg(msg))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查名称唯一
|
||||||
|
uniqueNenuName := s.sysMenuService.CheckUniqueMenuName(body.MenuName, body.ParentID, body.MenuID)
|
||||||
|
if !uniqueNenuName {
|
||||||
|
msg := fmt.Sprintf("菜单修改【%s】失败,菜单名称已存在", body.MenuName)
|
||||||
|
ctx.JSON(w, 200, result.ErrMsg(msg))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 外链菜单需要符合网站http(s)开头
|
||||||
|
if body.IsFrame == "0" && !regular.ValidHttp(body.Path) {
|
||||||
|
msg := fmt.Sprintf("菜单修改【%s】失败,非内部地址必须以http(s)://开头", body.MenuName)
|
||||||
|
ctx.JSON(w, 200, result.ErrMsg(msg))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
body.UpdateBy = ctx.LoginUserToUserName(r)
|
||||||
|
rows := s.sysMenuService.UpdateMenu(body)
|
||||||
|
if rows > 0 {
|
||||||
|
ctx.JSON(w, 200, result.Ok(nil))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.JSON(w, 200, result.Err(nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 菜单删除
|
||||||
|
//
|
||||||
|
// DELETE /:menuId
|
||||||
|
func (s *SysMenuApi) Remove(w http.ResponseWriter, r *http.Request) {
|
||||||
|
menuId := ctx.Param(r, "menuId")
|
||||||
|
if menuId == "" {
|
||||||
|
ctx.JSON(w, 400, result.CodeMsg(400, "参数错误"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查数据是否存在
|
||||||
|
menu := s.sysMenuService.SelectMenuById(menuId)
|
||||||
|
if menu.MenuID != menuId {
|
||||||
|
ctx.JSON(w, 200, result.ErrMsg("没有权限访问菜单数据!"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否存在子菜单
|
||||||
|
hasChild := s.sysMenuService.HasChildByMenuId(menuId)
|
||||||
|
if hasChild > 0 {
|
||||||
|
msg := fmt.Sprintf("不允许删除,存在子菜单数:%d", hasChild)
|
||||||
|
ctx.JSON(w, 200, result.ErrMsg(msg))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否分配给角色
|
||||||
|
existRole := s.sysMenuService.CheckMenuExistRole(menuId)
|
||||||
|
if existRole > 0 {
|
||||||
|
msg := fmt.Sprintf("不允许删除,菜单已分配给角色数:%d", existRole)
|
||||||
|
ctx.JSON(w, 200, result.ErrMsg(msg))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
rows := s.sysMenuService.DeleteMenuById(menuId)
|
||||||
|
if rows > 0 {
|
||||||
|
msg := fmt.Sprintf("删除成功:%d", rows)
|
||||||
|
ctx.JSON(w, 200, result.OkMsg(msg))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.JSON(w, 200, result.Err(nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 菜单树结构列表
|
||||||
|
//
|
||||||
|
// GET /treeSelect
|
||||||
|
func (s *SysMenuApi) TreeSelect(w http.ResponseWriter, r *http.Request) {
|
||||||
|
query := model.SysMenu{}
|
||||||
|
if v := ctx.GetQuery(r, "menuName"); v != "" {
|
||||||
|
query.MenuName = v
|
||||||
|
}
|
||||||
|
if v := ctx.GetQuery(r, "status"); v != "" {
|
||||||
|
query.Status = v
|
||||||
|
}
|
||||||
|
|
||||||
|
userId := ctx.LoginUserToUserID(r)
|
||||||
|
if conf.IsAdmin(userId) {
|
||||||
|
userId = "*"
|
||||||
|
}
|
||||||
|
data := s.sysMenuService.SelectMenuTreeSelectByUserId(query, userId)
|
||||||
|
ctx.JSON(w, 200, result.OkData(data))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 菜单树结构列表(指定角色)
|
||||||
|
//
|
||||||
|
// GET /roleMenuTreeSelect/:roleId
|
||||||
|
func (s *SysMenuApi) RoleMenuTreeSelect(w http.ResponseWriter, r *http.Request) {
|
||||||
|
roleId := ctx.Param(r, "roleId")
|
||||||
|
if roleId == "" {
|
||||||
|
ctx.JSON(w, 400, result.CodeMsg(400, "参数错误"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
query := model.SysMenu{}
|
||||||
|
if v := ctx.GetQuery(r, "menuName"); v != "" {
|
||||||
|
query.MenuName = v
|
||||||
|
}
|
||||||
|
if v := ctx.GetQuery(r, "status"); v != "" {
|
||||||
|
query.Status = v
|
||||||
|
}
|
||||||
|
|
||||||
|
userId := ctx.LoginUserToUserID(r)
|
||||||
|
if conf.IsAdmin(userId) {
|
||||||
|
userId = "*"
|
||||||
|
}
|
||||||
|
menuTreeSelect := s.sysMenuService.SelectMenuTreeSelectByUserId(query, userId)
|
||||||
|
checkedKeys := s.sysMenuService.SelectMenuListByRoleId(roleId)
|
||||||
|
ctx.JSON(w, 200, result.OkData(map[string]any{
|
||||||
|
"menus": menuTreeSelect,
|
||||||
|
"checkedKeys": checkedKeys,
|
||||||
|
}))
|
||||||
|
}
|
||||||
24
features/sys_menu/consts/consts_menu.go
Normal file
24
features/sys_menu/consts/consts_menu.go
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package consts
|
||||||
|
|
||||||
|
// 系统菜单常量信息
|
||||||
|
|
||||||
|
const (
|
||||||
|
// 组件布局类型-基础布局组件标识
|
||||||
|
COMPONENT_LAYOUT_BASIC = "BasicLayout"
|
||||||
|
// 组件布局类型-空白布局组件标识
|
||||||
|
COMPONENT_LAYOUT_BLANK = "BlankLayout"
|
||||||
|
// 组件布局类型-内链接布局组件标识
|
||||||
|
COMPONENT_LAYOUT_LINK = "LinkLayout"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// 菜单类型-目录
|
||||||
|
TYPE_DIR = "D"
|
||||||
|
// 菜单类型-菜单
|
||||||
|
TYPE_MENU = "M"
|
||||||
|
// 菜单类型-按钮
|
||||||
|
TYPE_BUTTON = "B"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 菜单内嵌地址标识-带/前缀
|
||||||
|
const PATH_INLINE = "/inline"
|
||||||
46
features/sys_menu/model/sys_menu.go
Normal file
46
features/sys_menu/model/sys_menu.go
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
// SysMenu 菜单权限对象 sys_menu
|
||||||
|
type SysMenu struct {
|
||||||
|
// 菜单ID
|
||||||
|
MenuID string `json:"menuId"`
|
||||||
|
// 菜单名称
|
||||||
|
MenuName string `json:"menuName" binding:"required"`
|
||||||
|
// 父菜单ID 默认0
|
||||||
|
ParentID string `json:"parentId" binding:"required"`
|
||||||
|
// 显示顺序
|
||||||
|
MenuSort int `json:"menuSort"`
|
||||||
|
// 路由地址
|
||||||
|
Path string `json:"path"`
|
||||||
|
// 组件路径
|
||||||
|
Component string `json:"component"`
|
||||||
|
// 是否内部跳转(0否 1是)
|
||||||
|
IsFrame string `json:"isFrame"`
|
||||||
|
// 是否缓存(0不缓存 1缓存)
|
||||||
|
IsCache string `json:"isCache"`
|
||||||
|
// 菜单类型(D目录 M菜单 B按钮)
|
||||||
|
MenuType string `json:"menuType" binding:"required"`
|
||||||
|
// 是否显示(0隐藏 1显示)
|
||||||
|
Visible string `json:"visible"`
|
||||||
|
// 菜单状态(0停用 1正常)
|
||||||
|
Status string `json:"status"`
|
||||||
|
// 权限标识
|
||||||
|
Perms string `json:"perms"`
|
||||||
|
// 菜单图标(#无图标)
|
||||||
|
Icon string `json:"icon"`
|
||||||
|
// 创建者
|
||||||
|
CreateBy string `json:"createBy"`
|
||||||
|
// 创建时间
|
||||||
|
CreateTime int64 `json:"createTime"`
|
||||||
|
// 更新者
|
||||||
|
UpdateBy string `json:"updateBy"`
|
||||||
|
// 更新时间
|
||||||
|
UpdateTime int64 `json:"updateTime"`
|
||||||
|
// 备注
|
||||||
|
Remark string `json:"remark"`
|
||||||
|
|
||||||
|
// ====== 非数据库字段属性 ======
|
||||||
|
|
||||||
|
// 子菜单
|
||||||
|
Children []SysMenu `json:"children,omitempty"`
|
||||||
|
}
|
||||||
452
features/sys_menu/service/repo_sys_menu.go
Normal file
452
features/sys_menu/service/repo_sys_menu.go
Normal file
@@ -0,0 +1,452 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"ems.agt/features/sys_menu/consts"
|
||||||
|
"ems.agt/features/sys_menu/model"
|
||||||
|
"ems.agt/lib/core/datasource"
|
||||||
|
"ems.agt/lib/core/utils/parse"
|
||||||
|
"github.com/go-admin-team/go-admin-core/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 实例化数据层 RepoSysMenu 结构体
|
||||||
|
var NewRepoSysMenu = &RepoSysMenu{
|
||||||
|
selectSql: `select
|
||||||
|
m.menu_id, m.menu_name, m.parent_id, m.menu_sort, m.path, m.component, m.is_frame, m.is_cache, m.menu_type, m.visible, m.status, ifnull(m.perms,'') as perms, m.icon, m.create_time, m.remark
|
||||||
|
from sys_menu m`,
|
||||||
|
|
||||||
|
selectSqlByUser: `select distinct
|
||||||
|
m.menu_id, m.menu_name, m.parent_id, m.menu_sort, m.path, m.component, m.is_frame, m.is_cache, m.menu_type, m.visible, m.status, ifnull(m.perms,'') as perms, m.icon, m.create_time, m.remark
|
||||||
|
from sys_menu m
|
||||||
|
left join sys_role_menu rm on m.menu_id = rm.menu_id
|
||||||
|
left join sys_user_role ur on rm.role_id = ur.role_id
|
||||||
|
left join sys_role ro on ur.role_id = ro.role_id`,
|
||||||
|
|
||||||
|
resultMap: map[string]string{
|
||||||
|
"menu_id": "MenuID",
|
||||||
|
"menu_name": "MenuName",
|
||||||
|
"parent_name": "ParentName",
|
||||||
|
"parent_id": "ParentID",
|
||||||
|
"path": "Path",
|
||||||
|
"menu_sort": "MenuSort",
|
||||||
|
"component": "Component",
|
||||||
|
"is_frame": "IsFrame",
|
||||||
|
"is_cache": "IsCache",
|
||||||
|
"menu_type": "MenuType",
|
||||||
|
"visible": "Visible",
|
||||||
|
"status": "Status",
|
||||||
|
"perms": "Perms",
|
||||||
|
"icon": "Icon",
|
||||||
|
"create_by": "CreateBy",
|
||||||
|
"create_time": "CreateTime",
|
||||||
|
"update_by": "UpdateBy",
|
||||||
|
"update_time": "UpdateTime",
|
||||||
|
"remark": "Remark",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// RepoSysMenu 菜单表 数据层处理
|
||||||
|
type RepoSysMenu struct {
|
||||||
|
// 查询视图对象SQL
|
||||||
|
selectSql string
|
||||||
|
// 查询视图用户对象SQL
|
||||||
|
selectSqlByUser string
|
||||||
|
// 结果字段与实体映射
|
||||||
|
resultMap map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertResultRows 将结果记录转实体结果组
|
||||||
|
func (r *RepoSysMenu) convertResultRows(rows []map[string]any) []model.SysMenu {
|
||||||
|
arr := make([]model.SysMenu, 0)
|
||||||
|
for _, row := range rows {
|
||||||
|
sysMenu := model.SysMenu{}
|
||||||
|
for key, value := range row {
|
||||||
|
if keyMapper, ok := r.resultMap[key]; ok {
|
||||||
|
datasource.SetFieldValue(&sysMenu, keyMapper, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
arr = append(arr, sysMenu)
|
||||||
|
}
|
||||||
|
return arr
|
||||||
|
}
|
||||||
|
|
||||||
|
// SelectMenuList 查询系统菜单列表
|
||||||
|
func (r *RepoSysMenu) SelectMenuList(sysMenu model.SysMenu, userId string) []model.SysMenu {
|
||||||
|
// 查询条件拼接
|
||||||
|
var conditions []string
|
||||||
|
var params []any
|
||||||
|
if sysMenu.MenuName != "" {
|
||||||
|
conditions = append(conditions, "m.menu_name like concat(?, '%')")
|
||||||
|
params = append(params, sysMenu.MenuName)
|
||||||
|
}
|
||||||
|
if sysMenu.Visible != "" {
|
||||||
|
conditions = append(conditions, "m.visible = ?")
|
||||||
|
params = append(params, sysMenu.Visible)
|
||||||
|
}
|
||||||
|
if sysMenu.Status != "" {
|
||||||
|
conditions = append(conditions, "m.status = ?")
|
||||||
|
params = append(params, sysMenu.Status)
|
||||||
|
}
|
||||||
|
|
||||||
|
fromSql := r.selectSql
|
||||||
|
|
||||||
|
// 个人菜单
|
||||||
|
if userId != "*" {
|
||||||
|
fromSql = r.selectSqlByUser
|
||||||
|
conditions = append(conditions, "ur.user_id = ?")
|
||||||
|
params = append(params, userId)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建查询条件语句
|
||||||
|
whereSql := ""
|
||||||
|
if len(conditions) > 0 {
|
||||||
|
whereSql += " where " + strings.Join(conditions, " and ")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询数据
|
||||||
|
orderSql := " order by m.parent_id, m.menu_sort"
|
||||||
|
querySql := fromSql + whereSql + orderSql
|
||||||
|
results, err := datasource.RawDB("", querySql, params)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("query err => %v", err)
|
||||||
|
return []model.SysMenu{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 转换实体
|
||||||
|
return r.convertResultRows(results)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SelectMenuPermsByUserId 根据用户ID查询权限
|
||||||
|
func (r *RepoSysMenu) SelectMenuPermsByUserId(userId string) []string {
|
||||||
|
querySql := `select distinct m.perms as 'str' from sys_menu m
|
||||||
|
left join sys_role_menu rm on m.menu_id = rm.menu_id
|
||||||
|
left join sys_user_role ur on rm.role_id = ur.role_id
|
||||||
|
left join sys_role r on r.role_id = ur.role_id
|
||||||
|
where m.status = '1' and m.perms != '' and r.status = '1' and ur.user_id = ? `
|
||||||
|
|
||||||
|
// 查询结果
|
||||||
|
results, err := datasource.RawDB("", querySql, []any{userId})
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("query err => %v", err)
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 读取结果
|
||||||
|
rows := make([]string, 0)
|
||||||
|
for _, m := range results {
|
||||||
|
rows = append(rows, fmt.Sprintf("%v", m["str"]))
|
||||||
|
}
|
||||||
|
return rows
|
||||||
|
}
|
||||||
|
|
||||||
|
// SelectMenuTreeByUserId 根据用户ID查询菜单
|
||||||
|
func (r *RepoSysMenu) SelectMenuTreeByUserId(userId string) []model.SysMenu {
|
||||||
|
var params []any
|
||||||
|
var querySql string
|
||||||
|
|
||||||
|
if userId == "*" {
|
||||||
|
// 管理员全部菜单
|
||||||
|
querySql = r.selectSql + ` where
|
||||||
|
m.menu_type in (?,?) and m.status = '1'
|
||||||
|
order by m.parent_id, m.menu_sort`
|
||||||
|
params = append(params, consts.TYPE_DIR)
|
||||||
|
params = append(params, consts.TYPE_MENU)
|
||||||
|
} else {
|
||||||
|
// 用户ID权限
|
||||||
|
querySql = r.selectSqlByUser + ` where
|
||||||
|
m.menu_type in (?, ?) and m.status = '1'
|
||||||
|
and ur.user_id = ? and ro.status = '1'
|
||||||
|
order by m.parent_id, m.menu_sort`
|
||||||
|
params = append(params, consts.TYPE_DIR)
|
||||||
|
params = append(params, consts.TYPE_MENU)
|
||||||
|
params = append(params, userId)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询结果
|
||||||
|
results, err := datasource.RawDB("", querySql, params)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("query err => %v", err)
|
||||||
|
return []model.SysMenu{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.convertResultRows(results)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SelectMenuListByRoleId 根据角色ID查询菜单树信息
|
||||||
|
func (r *RepoSysMenu) SelectMenuListByRoleId(roleId string, menuCheckStrictly bool) []string {
|
||||||
|
querySql := `select m.menu_id as 'str' from sys_menu m
|
||||||
|
left join sys_role_menu rm on m.menu_id = rm.menu_id
|
||||||
|
where rm.role_id = ? `
|
||||||
|
var params []any
|
||||||
|
params = append(params, roleId)
|
||||||
|
// 展开
|
||||||
|
if menuCheckStrictly {
|
||||||
|
querySql += ` and m.menu_id not in
|
||||||
|
(select m.parent_id from sys_menu m
|
||||||
|
inner join sys_role_menu rm on m.menu_id = rm.menu_id
|
||||||
|
and rm.role_id = ?) `
|
||||||
|
params = append(params, roleId)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询结果
|
||||||
|
results, err := datasource.RawDB("", querySql, params)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("query err => %v", err)
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(results) > 0 {
|
||||||
|
ids := make([]string, 0)
|
||||||
|
for _, v := range results {
|
||||||
|
ids = append(ids, fmt.Sprintf("%v", v["str"]))
|
||||||
|
}
|
||||||
|
return ids
|
||||||
|
}
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SelectMenuByIds 根据菜单ID查询信息
|
||||||
|
func (r *RepoSysMenu) SelectMenuByIds(menuIds []string) []model.SysMenu {
|
||||||
|
placeholder := datasource.KeyPlaceholderByQuery(len(menuIds))
|
||||||
|
querySql := r.selectSql + " where m.menu_id in (" + placeholder + ")"
|
||||||
|
parameters := datasource.ConvertIdsSlice(menuIds)
|
||||||
|
results, err := datasource.RawDB("", querySql, parameters)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("query err => %v", err)
|
||||||
|
return []model.SysMenu{}
|
||||||
|
}
|
||||||
|
// 转换实体
|
||||||
|
return r.convertResultRows(results)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasChildByMenuId 存在菜单子节点数量
|
||||||
|
func (r *RepoSysMenu) HasChildByMenuId(menuId string) int64 {
|
||||||
|
querySql := "select count(1) as 'total' from sys_menu where parent_id = ?"
|
||||||
|
results, err := datasource.RawDB("", querySql, []any{menuId})
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("query err => %v", err)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if len(results) > 0 {
|
||||||
|
return parse.Number(results[0]["total"])
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// InsertMenu 新增菜单信息
|
||||||
|
func (r *RepoSysMenu) InsertMenu(sysMenu model.SysMenu) string {
|
||||||
|
// 参数拼接
|
||||||
|
params := make(map[string]any)
|
||||||
|
if sysMenu.MenuID != "" {
|
||||||
|
params["menu_id"] = sysMenu.MenuID
|
||||||
|
}
|
||||||
|
if sysMenu.ParentID != "" {
|
||||||
|
params["parent_id"] = sysMenu.ParentID
|
||||||
|
}
|
||||||
|
if sysMenu.MenuName != "" {
|
||||||
|
params["menu_name"] = sysMenu.MenuName
|
||||||
|
}
|
||||||
|
if sysMenu.MenuSort > 0 {
|
||||||
|
params["menu_sort"] = sysMenu.MenuSort
|
||||||
|
}
|
||||||
|
if sysMenu.Path != "" {
|
||||||
|
params["path"] = sysMenu.Path
|
||||||
|
}
|
||||||
|
if sysMenu.Component != "" {
|
||||||
|
params["component"] = sysMenu.Component
|
||||||
|
}
|
||||||
|
if sysMenu.IsFrame != "" {
|
||||||
|
params["is_frame"] = sysMenu.IsFrame
|
||||||
|
}
|
||||||
|
if sysMenu.IsCache != "" {
|
||||||
|
params["is_cache"] = sysMenu.IsCache
|
||||||
|
}
|
||||||
|
if sysMenu.MenuType != "" {
|
||||||
|
params["menu_type"] = sysMenu.MenuType
|
||||||
|
}
|
||||||
|
if sysMenu.Visible != "" {
|
||||||
|
params["visible"] = sysMenu.Visible
|
||||||
|
}
|
||||||
|
if sysMenu.Status != "" {
|
||||||
|
params["status"] = sysMenu.Status
|
||||||
|
}
|
||||||
|
if sysMenu.Perms != "" {
|
||||||
|
params["perms"] = sysMenu.Perms
|
||||||
|
}
|
||||||
|
if sysMenu.Icon != "" {
|
||||||
|
params["icon"] = sysMenu.Icon
|
||||||
|
} else {
|
||||||
|
params["icon"] = "#"
|
||||||
|
}
|
||||||
|
if sysMenu.Remark != "" {
|
||||||
|
params["remark"] = sysMenu.Remark
|
||||||
|
}
|
||||||
|
if sysMenu.CreateBy != "" {
|
||||||
|
params["create_by"] = sysMenu.CreateBy
|
||||||
|
params["create_time"] = time.Now().UnixMilli()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据菜单类型重置参数
|
||||||
|
if sysMenu.MenuType == consts.TYPE_BUTTON {
|
||||||
|
params["component"] = ""
|
||||||
|
params["path"] = ""
|
||||||
|
params["icon"] = "#"
|
||||||
|
params["is_cache"] = "1"
|
||||||
|
params["is_frame"] = "1"
|
||||||
|
params["visible"] = "1"
|
||||||
|
params["status"] = "1"
|
||||||
|
}
|
||||||
|
if sysMenu.MenuType == consts.TYPE_DIR {
|
||||||
|
params["component"] = ""
|
||||||
|
params["perms"] = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建执行语句
|
||||||
|
keys, placeholder, values := datasource.KeyPlaceholderValueByInsert(params)
|
||||||
|
sql := "insert into sys_menu (" + strings.Join(keys, ",") + ")values(" + placeholder + ")"
|
||||||
|
|
||||||
|
// 执行插入
|
||||||
|
rows, err := datasource.ExecDB("", sql, values)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("insert row : %v", err.Error())
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprint(rows)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateMenu 修改菜单信息
|
||||||
|
func (r *RepoSysMenu) UpdateMenu(sysMenu model.SysMenu) int64 {
|
||||||
|
// 参数拼接
|
||||||
|
params := make(map[string]any)
|
||||||
|
if sysMenu.MenuID != "" {
|
||||||
|
params["menu_id"] = sysMenu.MenuID
|
||||||
|
}
|
||||||
|
if sysMenu.ParentID != "" {
|
||||||
|
params["parent_id"] = sysMenu.ParentID
|
||||||
|
}
|
||||||
|
if sysMenu.MenuName != "" {
|
||||||
|
params["menu_name"] = sysMenu.MenuName
|
||||||
|
}
|
||||||
|
if sysMenu.MenuSort > 0 {
|
||||||
|
params["menu_sort"] = sysMenu.MenuSort
|
||||||
|
}
|
||||||
|
if sysMenu.Path != "" {
|
||||||
|
params["path"] = sysMenu.Path
|
||||||
|
}
|
||||||
|
if sysMenu.Component != "" {
|
||||||
|
params["component"] = sysMenu.Component
|
||||||
|
}
|
||||||
|
if sysMenu.IsFrame != "" {
|
||||||
|
params["is_frame"] = sysMenu.IsFrame
|
||||||
|
}
|
||||||
|
if sysMenu.IsCache != "" {
|
||||||
|
params["is_cache"] = sysMenu.IsCache
|
||||||
|
}
|
||||||
|
if sysMenu.MenuType != "" {
|
||||||
|
params["menu_type"] = sysMenu.MenuType
|
||||||
|
}
|
||||||
|
if sysMenu.Visible != "" {
|
||||||
|
params["visible"] = sysMenu.Visible
|
||||||
|
}
|
||||||
|
if sysMenu.Status != "" {
|
||||||
|
params["status"] = sysMenu.Status
|
||||||
|
}
|
||||||
|
if sysMenu.Perms != "" {
|
||||||
|
params["perms"] = sysMenu.Perms
|
||||||
|
}
|
||||||
|
if sysMenu.Icon != "" {
|
||||||
|
params["icon"] = sysMenu.Icon
|
||||||
|
} else {
|
||||||
|
params["icon"] = "#"
|
||||||
|
}
|
||||||
|
if sysMenu.Remark != "" {
|
||||||
|
params["remark"] = sysMenu.Remark
|
||||||
|
}
|
||||||
|
if sysMenu.UpdateBy != "" {
|
||||||
|
params["update_by"] = sysMenu.UpdateBy
|
||||||
|
params["update_time"] = time.Now().UnixMilli()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据菜单类型重置参数
|
||||||
|
if sysMenu.MenuType == consts.TYPE_BUTTON {
|
||||||
|
params["component"] = ""
|
||||||
|
params["path"] = ""
|
||||||
|
params["icon"] = "#"
|
||||||
|
params["is_cache"] = "1"
|
||||||
|
params["is_frame"] = "1"
|
||||||
|
params["visible"] = "1"
|
||||||
|
params["status"] = "1"
|
||||||
|
}
|
||||||
|
if sysMenu.MenuType == consts.TYPE_DIR {
|
||||||
|
params["component"] = ""
|
||||||
|
params["perms"] = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建执行语句
|
||||||
|
keys, values := datasource.KeyValueByUpdate(params)
|
||||||
|
sql := "update sys_menu set " + strings.Join(keys, ",") + " where menu_id = ?"
|
||||||
|
|
||||||
|
// 执行更新
|
||||||
|
values = append(values, sysMenu.MenuID)
|
||||||
|
rows, err := datasource.ExecDB("", sql, values)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("update row : %v", err.Error())
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return rows
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteMenuById 删除菜单管理信息
|
||||||
|
func (r *RepoSysMenu) DeleteMenuById(menuId string) int64 {
|
||||||
|
sql := "delete from sys_menu where menu_id = ?"
|
||||||
|
results, err := datasource.ExecDB("", sql, []any{menuId})
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("delete err => %v", err)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckUniqueMenu 校验菜单是否唯一
|
||||||
|
func (r *RepoSysMenu) CheckUniqueMenu(sysMenu model.SysMenu) string {
|
||||||
|
// 查询条件拼接
|
||||||
|
var conditions []string
|
||||||
|
var params []any
|
||||||
|
if sysMenu.MenuName != "" {
|
||||||
|
conditions = append(conditions, "menu_name = ?")
|
||||||
|
params = append(params, sysMenu.MenuName)
|
||||||
|
}
|
||||||
|
if sysMenu.ParentID != "" {
|
||||||
|
conditions = append(conditions, "parent_id = ?")
|
||||||
|
params = append(params, sysMenu.ParentID)
|
||||||
|
}
|
||||||
|
if sysMenu.Path != "" {
|
||||||
|
conditions = append(conditions, "path = ?")
|
||||||
|
params = append(params, sysMenu.Path)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建查询条件语句
|
||||||
|
whereSql := ""
|
||||||
|
if len(conditions) > 0 {
|
||||||
|
whereSql += " where " + strings.Join(conditions, " and ")
|
||||||
|
}
|
||||||
|
if whereSql == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询数据
|
||||||
|
querySql := "select menu_id as 'str' from sys_menu " + whereSql + " limit 1"
|
||||||
|
results, err := datasource.RawDB("", querySql, params)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("query err %v", err)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if len(results) > 0 {
|
||||||
|
return fmt.Sprintf("%v", results[0]["str"])
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
397
features/sys_menu/service/service_sys_menu.go
Normal file
397
features/sys_menu/service/service_sys_menu.go
Normal file
@@ -0,0 +1,397 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"ems.agt/features/sys_menu/consts"
|
||||||
|
"ems.agt/features/sys_menu/model"
|
||||||
|
sysRoleService "ems.agt/features/sys_role/service"
|
||||||
|
sysrolemenu "ems.agt/features/sys_role_menu"
|
||||||
|
"ems.agt/lib/core/utils/parse"
|
||||||
|
"ems.agt/lib/core/utils/regular"
|
||||||
|
"ems.agt/lib/core/vo"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 实例化服务层 ServiceSysMenu 结构体
|
||||||
|
var NewServiceSysMenu = &ServiceSysMenu{
|
||||||
|
sysMenuRepository: NewRepoSysMenu,
|
||||||
|
sysRoleMenuRepository: sysrolemenu.NewRepoSysRoleMenu,
|
||||||
|
sysRoleRepository: sysRoleService.NewRepoSysRole,
|
||||||
|
}
|
||||||
|
|
||||||
|
// ServiceSysMenu 菜单 服务层处理
|
||||||
|
type ServiceSysMenu struct {
|
||||||
|
// 菜单服务
|
||||||
|
sysMenuRepository *RepoSysMenu
|
||||||
|
// 角色与菜单关联服务
|
||||||
|
sysRoleMenuRepository *sysrolemenu.RepoSysRoleMenu
|
||||||
|
// 角色服务
|
||||||
|
sysRoleRepository *sysRoleService.RepoSysRole
|
||||||
|
}
|
||||||
|
|
||||||
|
// SelectMenuList 查询系统菜单列表
|
||||||
|
func (r *ServiceSysMenu) SelectMenuList(sysMenu model.SysMenu, userId string) []model.SysMenu {
|
||||||
|
return r.sysMenuRepository.SelectMenuList(sysMenu, userId)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SelectMenuPermsByUserId 根据用户ID查询权限
|
||||||
|
func (r *ServiceSysMenu) SelectMenuPermsByUserId(userId string) []string {
|
||||||
|
return r.sysMenuRepository.SelectMenuPermsByUserId(userId)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SelectMenuTreeByUserId 根据用户ID查询菜单
|
||||||
|
func (r *ServiceSysMenu) SelectMenuTreeByUserId(userId string) []model.SysMenu {
|
||||||
|
sysMenus := r.sysMenuRepository.SelectMenuTreeByUserId(userId)
|
||||||
|
return r.parseDataToTree(sysMenus)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SelectMenuTreeSelectByUserId 根据用户ID查询菜单树结构信息
|
||||||
|
func (r *ServiceSysMenu) SelectMenuTreeSelectByUserId(sysMenu model.SysMenu, userId string) []vo.TreeSelect {
|
||||||
|
sysMenus := r.sysMenuRepository.SelectMenuList(sysMenu, userId)
|
||||||
|
menus := r.parseDataToTree(sysMenus)
|
||||||
|
tree := make([]vo.TreeSelect, 0)
|
||||||
|
for _, menu := range menus {
|
||||||
|
tree = append(tree, sysMenuTreeSelect(menu))
|
||||||
|
}
|
||||||
|
return tree
|
||||||
|
}
|
||||||
|
|
||||||
|
// sysMenuTreeSelect 使用给定的 SysMenu 对象解析为 TreeSelect 对象
|
||||||
|
func sysMenuTreeSelect(sysMenu model.SysMenu) vo.TreeSelect {
|
||||||
|
t := vo.TreeSelect{}
|
||||||
|
t.ID = sysMenu.MenuID
|
||||||
|
t.Label = sysMenu.MenuName
|
||||||
|
|
||||||
|
if len(sysMenu.Children) > 0 {
|
||||||
|
for _, menu := range sysMenu.Children {
|
||||||
|
child := sysMenuTreeSelect(menu)
|
||||||
|
t.Children = append(t.Children, child)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
t.Children = []vo.TreeSelect{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
// SelectMenuListByRoleId 根据角色ID查询菜单树信息 TODO
|
||||||
|
func (r *ServiceSysMenu) SelectMenuListByRoleId(roleId string) []string {
|
||||||
|
roles := r.sysRoleRepository.SelectRoleByIds([]string{roleId})
|
||||||
|
if len(roles) > 0 {
|
||||||
|
role := roles[0]
|
||||||
|
if role.RoleID == roleId {
|
||||||
|
return r.sysMenuRepository.SelectMenuListByRoleId(
|
||||||
|
role.RoleID,
|
||||||
|
role.MenuCheckStrictly == "1",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SelectMenuById 根据菜单ID查询信息
|
||||||
|
func (r *ServiceSysMenu) SelectMenuById(menuId string) model.SysMenu {
|
||||||
|
if menuId == "" {
|
||||||
|
return model.SysMenu{}
|
||||||
|
}
|
||||||
|
menus := r.sysMenuRepository.SelectMenuByIds([]string{menuId})
|
||||||
|
if len(menus) > 0 {
|
||||||
|
return menus[0]
|
||||||
|
}
|
||||||
|
return model.SysMenu{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasChildByMenuId 存在菜单子节点数量
|
||||||
|
func (r *ServiceSysMenu) HasChildByMenuId(menuId string) int64 {
|
||||||
|
return r.sysMenuRepository.HasChildByMenuId(menuId)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckMenuExistRole 查询菜单是否存在角色
|
||||||
|
func (r *ServiceSysMenu) CheckMenuExistRole(menuId string) int64 {
|
||||||
|
return r.sysRoleMenuRepository.CheckMenuExistRole(menuId)
|
||||||
|
}
|
||||||
|
|
||||||
|
// InsertMenu 新增菜单信息
|
||||||
|
func (r *ServiceSysMenu) InsertMenu(sysMenu model.SysMenu) string {
|
||||||
|
return r.sysMenuRepository.InsertMenu(sysMenu)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateMenu 修改菜单信息
|
||||||
|
func (r *ServiceSysMenu) UpdateMenu(sysMenu model.SysMenu) int64 {
|
||||||
|
return r.sysMenuRepository.UpdateMenu(sysMenu)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteMenuById 删除菜单管理信息
|
||||||
|
func (r *ServiceSysMenu) DeleteMenuById(menuId string) int64 {
|
||||||
|
// 删除菜单与角色关联
|
||||||
|
r.sysRoleMenuRepository.DeleteMenuRole([]string{menuId})
|
||||||
|
return r.sysMenuRepository.DeleteMenuById(menuId)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckUniqueMenuName 校验菜单名称是否唯一
|
||||||
|
func (r *ServiceSysMenu) CheckUniqueMenuName(menuName, parentId, menuId string) bool {
|
||||||
|
uniqueId := r.sysMenuRepository.CheckUniqueMenu(model.SysMenu{
|
||||||
|
MenuName: menuName,
|
||||||
|
ParentID: parentId,
|
||||||
|
})
|
||||||
|
if uniqueId == menuId {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return uniqueId == ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckUniqueMenuPath 校验路由地址是否唯一(针对目录和菜单)
|
||||||
|
func (r *ServiceSysMenu) CheckUniqueMenuPath(path, menuId string) bool {
|
||||||
|
uniqueId := r.sysMenuRepository.CheckUniqueMenu(model.SysMenu{
|
||||||
|
Path: path,
|
||||||
|
})
|
||||||
|
if uniqueId == menuId {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return uniqueId == ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// BuildRouteMenus 构建前端路由所需要的菜单
|
||||||
|
func (r *ServiceSysMenu) BuildRouteMenus(sysMenus []model.SysMenu, prefix string) []vo.Router {
|
||||||
|
routers := []vo.Router{}
|
||||||
|
for _, item := range sysMenus {
|
||||||
|
router := vo.Router{}
|
||||||
|
router.Name = r.getRouteName(item)
|
||||||
|
router.Path = r.getRouterPath(item)
|
||||||
|
router.Component = r.getComponent(item)
|
||||||
|
router.Meta = r.getRouteMeta(item)
|
||||||
|
|
||||||
|
// 子项菜单 目录类型 非路径链接
|
||||||
|
cMenus := item.Children
|
||||||
|
if len(cMenus) > 0 && item.MenuType == consts.TYPE_DIR && !regular.ValidHttp(item.Path) {
|
||||||
|
// 获取重定向地址
|
||||||
|
redirectPrefix, redirectPath := r.getRouteRedirect(
|
||||||
|
cMenus,
|
||||||
|
router.Path,
|
||||||
|
prefix,
|
||||||
|
)
|
||||||
|
router.Redirect = redirectPath
|
||||||
|
// 子菜单进入递归
|
||||||
|
router.Children = r.BuildRouteMenus(cMenus, redirectPrefix)
|
||||||
|
} else if item.ParentID == "0" && item.IsFrame == "1" && item.MenuType == consts.TYPE_MENU {
|
||||||
|
// 父菜单 内部跳转 菜单类型
|
||||||
|
menuPath := "/" + item.MenuID
|
||||||
|
childPath := menuPath + r.getRouterPath(item)
|
||||||
|
children := vo.Router{
|
||||||
|
Name: r.getRouteName(item),
|
||||||
|
Path: childPath,
|
||||||
|
Component: item.Component,
|
||||||
|
Meta: r.getRouteMeta(item),
|
||||||
|
}
|
||||||
|
router.Meta.HideChildInMenu = true
|
||||||
|
router.Children = append(router.Children, children)
|
||||||
|
router.Name = item.MenuID
|
||||||
|
router.Path = menuPath
|
||||||
|
router.Redirect = childPath
|
||||||
|
router.Component = consts.COMPONENT_LAYOUT_BASIC
|
||||||
|
} else if item.ParentID == "0" && item.IsFrame == "1" && regular.ValidHttp(item.Path) {
|
||||||
|
// 父菜单 内部跳转 路径链接
|
||||||
|
menuPath := "/" + item.MenuID
|
||||||
|
childPath := menuPath + r.getRouterPath(item)
|
||||||
|
children := vo.Router{
|
||||||
|
Name: r.getRouteName(item),
|
||||||
|
Path: childPath,
|
||||||
|
Component: consts.COMPONENT_LAYOUT_LINK,
|
||||||
|
Meta: r.getRouteMeta(item),
|
||||||
|
}
|
||||||
|
router.Meta.HideChildInMenu = true
|
||||||
|
router.Children = append(router.Children, children)
|
||||||
|
router.Name = item.MenuID
|
||||||
|
router.Path = menuPath
|
||||||
|
router.Redirect = childPath
|
||||||
|
router.Component = consts.COMPONENT_LAYOUT_BASIC
|
||||||
|
}
|
||||||
|
|
||||||
|
routers = append(routers, router)
|
||||||
|
}
|
||||||
|
return routers
|
||||||
|
}
|
||||||
|
|
||||||
|
// getRouteName 获取路由名称 路径英文首字母大写
|
||||||
|
func (r *ServiceSysMenu) getRouteName(sysMenu model.SysMenu) string {
|
||||||
|
routerName := parse.FirstUpper(sysMenu.Path)
|
||||||
|
// 路径链接
|
||||||
|
if regular.ValidHttp(sysMenu.Path) {
|
||||||
|
return routerName[:5] + "Link" + sysMenu.MenuID
|
||||||
|
}
|
||||||
|
return routerName
|
||||||
|
}
|
||||||
|
|
||||||
|
// getRouterPath 获取路由地址
|
||||||
|
func (r *ServiceSysMenu) getRouterPath(sysMenu model.SysMenu) string {
|
||||||
|
routerPath := sysMenu.Path
|
||||||
|
|
||||||
|
// 显式路径
|
||||||
|
if routerPath == "" || strings.HasPrefix(routerPath, "/") {
|
||||||
|
return routerPath
|
||||||
|
}
|
||||||
|
|
||||||
|
// 路径链接 内部跳转
|
||||||
|
if regular.ValidHttp(routerPath) && sysMenu.IsFrame == "1" {
|
||||||
|
routerPath = regular.Replace(routerPath, `/^http(s)?:\/\/+/`, "")
|
||||||
|
routerPath = base64.StdEncoding.EncodeToString([]byte(routerPath))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 父菜单 内部跳转
|
||||||
|
if sysMenu.ParentID == "0" && sysMenu.IsFrame == "1" {
|
||||||
|
routerPath = "/" + routerPath
|
||||||
|
}
|
||||||
|
|
||||||
|
return routerPath
|
||||||
|
}
|
||||||
|
|
||||||
|
// getComponent 获取组件信息
|
||||||
|
func (r *ServiceSysMenu) getComponent(sysMenu model.SysMenu) string {
|
||||||
|
// 内部跳转 路径链接
|
||||||
|
if sysMenu.IsFrame == "1" && regular.ValidHttp(sysMenu.Path) {
|
||||||
|
return consts.COMPONENT_LAYOUT_LINK
|
||||||
|
}
|
||||||
|
|
||||||
|
// 非父菜单 目录类型
|
||||||
|
if sysMenu.ParentID != "0" && sysMenu.MenuType == consts.TYPE_DIR {
|
||||||
|
return consts.COMPONENT_LAYOUT_BLANK
|
||||||
|
}
|
||||||
|
|
||||||
|
// 组件路径 内部跳转 菜单类型
|
||||||
|
if sysMenu.Component != "" && sysMenu.IsFrame == "1" && sysMenu.MenuType == consts.TYPE_MENU {
|
||||||
|
// 父菜单套外层布局
|
||||||
|
if sysMenu.ParentID == "0" {
|
||||||
|
return consts.COMPONENT_LAYOUT_BASIC
|
||||||
|
}
|
||||||
|
return sysMenu.Component
|
||||||
|
}
|
||||||
|
|
||||||
|
return consts.COMPONENT_LAYOUT_BASIC
|
||||||
|
}
|
||||||
|
|
||||||
|
// getRouteMeta 获取路由元信息
|
||||||
|
func (r *ServiceSysMenu) getRouteMeta(sysMenu model.SysMenu) vo.RouterMeta {
|
||||||
|
meta := vo.RouterMeta{}
|
||||||
|
if sysMenu.Icon == "#" {
|
||||||
|
meta.Icon = ""
|
||||||
|
} else {
|
||||||
|
meta.Icon = sysMenu.Icon
|
||||||
|
}
|
||||||
|
meta.Title = sysMenu.MenuName
|
||||||
|
meta.HideChildInMenu = false
|
||||||
|
meta.HideInMenu = sysMenu.Visible == "0"
|
||||||
|
meta.Cache = sysMenu.IsCache == "1"
|
||||||
|
meta.Target = ""
|
||||||
|
|
||||||
|
// 路径链接 非内部跳转
|
||||||
|
if regular.ValidHttp(sysMenu.Path) && sysMenu.IsFrame == "0" {
|
||||||
|
meta.Target = "_blank"
|
||||||
|
}
|
||||||
|
|
||||||
|
return meta
|
||||||
|
}
|
||||||
|
|
||||||
|
// getRouteRedirect 获取路由重定向地址(针对目录)
|
||||||
|
//
|
||||||
|
// cMenus 子菜单数组
|
||||||
|
// routerPath 当前菜单路径
|
||||||
|
// prefix 菜单重定向路径前缀
|
||||||
|
func (r *ServiceSysMenu) getRouteRedirect(cMenus []model.SysMenu, routerPath string, prefix string) (string, string) {
|
||||||
|
redirectPath := ""
|
||||||
|
|
||||||
|
// 重定向为首个显示并启用的子菜单
|
||||||
|
var firstChild *model.SysMenu
|
||||||
|
for _, item := range cMenus {
|
||||||
|
if item.IsFrame == "1" && item.Visible == "1" {
|
||||||
|
firstChild = &item
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查内嵌隐藏菜单是否可做重定向
|
||||||
|
if firstChild == nil {
|
||||||
|
for _, item := range cMenus {
|
||||||
|
if item.IsFrame == "1" && item.Visible == "1" && strings.Contains(item.Path, consts.PATH_INLINE) {
|
||||||
|
firstChild = &item
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if firstChild != nil {
|
||||||
|
firstChildPath := r.getRouterPath(*firstChild)
|
||||||
|
if strings.HasPrefix(firstChildPath, "/") {
|
||||||
|
redirectPath = firstChildPath
|
||||||
|
} else {
|
||||||
|
// 拼接追加路径
|
||||||
|
if !strings.HasPrefix(routerPath, "/") {
|
||||||
|
prefix += "/"
|
||||||
|
}
|
||||||
|
prefix = prefix + routerPath
|
||||||
|
redirectPath = prefix + "/" + firstChildPath
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return prefix, redirectPath
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseDataToTree 将数据解析为树结构,构建前端所需要下拉树结构
|
||||||
|
func (r *ServiceSysMenu) parseDataToTree(sysMenus []model.SysMenu) []model.SysMenu {
|
||||||
|
// 节点分组
|
||||||
|
nodesMap := make(map[string][]model.SysMenu)
|
||||||
|
// 节点id
|
||||||
|
treeIds := []string{}
|
||||||
|
// 树节点
|
||||||
|
tree := []model.SysMenu{}
|
||||||
|
|
||||||
|
for _, item := range sysMenus {
|
||||||
|
parentID := item.ParentID
|
||||||
|
// 分组
|
||||||
|
mapItem, ok := nodesMap[parentID]
|
||||||
|
if !ok {
|
||||||
|
mapItem = []model.SysMenu{}
|
||||||
|
}
|
||||||
|
mapItem = append(mapItem, item)
|
||||||
|
nodesMap[parentID] = mapItem
|
||||||
|
// 记录节点ID
|
||||||
|
treeIds = append(treeIds, item.MenuID)
|
||||||
|
}
|
||||||
|
|
||||||
|
for key, value := range nodesMap {
|
||||||
|
// 选择不是节点ID的作为树节点
|
||||||
|
found := false
|
||||||
|
for _, id := range treeIds {
|
||||||
|
if id == key {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
tree = append(tree, value...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, node := range tree {
|
||||||
|
iN := r.parseDataToTreeComponet(node, &nodesMap)
|
||||||
|
tree[i] = iN
|
||||||
|
}
|
||||||
|
|
||||||
|
return tree
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseDataToTreeComponet 递归函数处理子节点
|
||||||
|
func (r *ServiceSysMenu) parseDataToTreeComponet(node model.SysMenu, nodesMap *map[string][]model.SysMenu) model.SysMenu {
|
||||||
|
id := node.MenuID
|
||||||
|
children, ok := (*nodesMap)[id]
|
||||||
|
if ok {
|
||||||
|
node.Children = children
|
||||||
|
}
|
||||||
|
if len(node.Children) > 0 {
|
||||||
|
for i, child := range node.Children {
|
||||||
|
icN := r.parseDataToTreeComponet(child, nodesMap)
|
||||||
|
node.Children[i] = icN
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return node
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user