355 lines
9.1 KiB
Go
355 lines
9.1 KiB
Go
package sysmenu
|
||
|
||
import (
|
||
"fmt"
|
||
"net/http"
|
||
|
||
"nms_nbi/features/sys_menu/consts"
|
||
"nms_nbi/features/sys_menu/model"
|
||
"nms_nbi/features/sys_menu/service"
|
||
"nms_nbi/lib/core/utils/ctx"
|
||
"nms_nbi/lib/core/utils/regular"
|
||
"nms_nbi/lib/core/vo/result"
|
||
"nms_nbi/lib/midware"
|
||
"nms_nbi/lib/services"
|
||
"nms_nbi/restagent/config"
|
||
srcConfig "nms_nbi/src/framework/config"
|
||
)
|
||
|
||
// 菜单接口添加到路由
|
||
func Routers() []services.RouterItem {
|
||
// 实例化控制层 SysMenuApi 结构体
|
||
var apis = &SysMenuApi{
|
||
sysMenuService: service.NewServiceSysMenu,
|
||
}
|
||
|
||
rs := [...]services.RouterItem{
|
||
{
|
||
Method: "GET",
|
||
Pattern: "/menus",
|
||
Handler: apis.List,
|
||
Middleware: midware.Authorize(nil),
|
||
},
|
||
{
|
||
Method: "GET",
|
||
Pattern: "/menu/{menuId}",
|
||
Handler: apis.Info,
|
||
Middleware: midware.Authorize(nil),
|
||
},
|
||
{
|
||
Method: "POST",
|
||
Pattern: "/menu",
|
||
Handler: apis.Add,
|
||
Middleware: midware.Authorize(nil),
|
||
},
|
||
{
|
||
Method: "PUT",
|
||
Pattern: "/menu",
|
||
Handler: apis.Edit,
|
||
Middleware: midware.Authorize(nil),
|
||
},
|
||
{
|
||
Method: "DELETE",
|
||
Pattern: "/menu/{menuId}",
|
||
Handler: apis.Remove,
|
||
Middleware: midware.Authorize(nil),
|
||
},
|
||
{
|
||
Method: "GET",
|
||
Pattern: "/menus/treeSelect",
|
||
Handler: apis.TreeSelect,
|
||
Middleware: midware.Authorize(nil),
|
||
},
|
||
{
|
||
Method: "GET",
|
||
Pattern: "/menu/roleMenuTreeSelect/{roleId}",
|
||
Handler: apis.RoleMenuTreeSelect,
|
||
Middleware: midware.Authorize(nil),
|
||
},
|
||
// 添加更多的 Router 对象...
|
||
}
|
||
|
||
// 生成两组前缀路由
|
||
rsPrefix := []services.RouterItem{}
|
||
for _, v := range rs {
|
||
path := "/menuManage/{apiVersion}" + 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 srcConfig.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, "parameter error"))
|
||
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, "parameter error"))
|
||
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, "parameter error"))
|
||
return
|
||
}
|
||
|
||
// 上级菜单不能选自己
|
||
if body.MenuID == body.ParentID {
|
||
msg := fmt.Sprintf("Menu modification failed for [%s], parent menu cannot select itself", 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("No permission to access menu data"))
|
||
return
|
||
}
|
||
// 父级ID不为0是要检查
|
||
if body.ParentID != "0" {
|
||
menuParent := s.sysMenuService.SelectMenuById(body.ParentID)
|
||
if menuParent.MenuID != body.ParentID {
|
||
ctx.JSON(w, 200, result.ErrMsg("No permission to access menu data"))
|
||
return
|
||
}
|
||
// 禁用菜单时检查父菜单是否使用
|
||
if body.Status == "1" && menuParent.Status == "0" {
|
||
ctx.JSON(w, 200, result.ErrMsg("Parent menu not enabled!"))
|
||
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
|
||
}
|
||
|
||
// 禁用菜单时检查子菜单是否使用
|
||
if body.Status == "0" {
|
||
hasStatus := s.sysMenuService.HasChildByMenuIdAndStatus(body.MenuID, "1")
|
||
if hasStatus > 0 {
|
||
msg := fmt.Sprintf("不允许禁用,存在使用子菜单数:%d", hasStatus)
|
||
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, "parameter error"))
|
||
return
|
||
}
|
||
|
||
// 检查数据是否存在
|
||
menu := s.sysMenuService.SelectMenuById(menuId)
|
||
if menu.MenuID != menuId {
|
||
ctx.JSON(w, 200, result.ErrMsg("No permission to access menu data!"))
|
||
return
|
||
}
|
||
|
||
// 检查是否存在子菜单
|
||
hasChild := s.sysMenuService.HasChildByMenuIdAndStatus(menuId, "")
|
||
if hasChild > 0 {
|
||
msg := fmt.Sprintf("Deletion not allowed, there are sub orders: %d", hasChild)
|
||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
||
return
|
||
}
|
||
|
||
// 检查是否分配给角色
|
||
existRole := s.sysMenuService.CheckMenuExistRole(menuId)
|
||
if existRole > 0 {
|
||
msg := fmt.Sprintf("Deletion not allowed, menu already assigned to roles: %d", existRole)
|
||
ctx.JSON(w, 200, result.ErrMsg(msg))
|
||
return
|
||
}
|
||
|
||
rows := s.sysMenuService.DeleteMenuById(menuId)
|
||
if rows > 0 {
|
||
msg := fmt.Sprintf("Successfully deleted: %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 srcConfig.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, "parameter error"))
|
||
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 srcConfig.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,
|
||
}))
|
||
}
|