作者 yangfu

add menu

@@ -14,7 +14,7 @@ type CreateMenuCommand struct { @@ -14,7 +14,7 @@ type CreateMenuCommand struct {
14 // 菜单编码 SYSTEM_USER_EDIT / 100101 (字符编码) 14 // 菜单编码 SYSTEM_USER_EDIT / 100101 (字符编码)
15 Code string `json:"code" valid:"Required"` 15 Code string `json:"code" valid:"Required"`
16 // 权限编码 users:edit 16 // 权限编码 users:edit
17 - AccessCode string `json:"accessCode" valid:"Required"` 17 + AccessCode string `json:"accessCode"`
18 // 菜单类型 (目录catalog、菜单menu、按钮button) 18 // 菜单类型 (目录catalog、菜单menu、按钮button)
19 MenuType string `json:"menuType" valid:"Required"` 19 MenuType string `json:"menuType" valid:"Required"`
20 // 菜单图标 20 // 菜单图标
@@ -24,7 +24,7 @@ type CreateMenuCommand struct { @@ -24,7 +24,7 @@ type CreateMenuCommand struct {
24 // 菜单说明 24 // 菜单说明
25 Desc string `json:"desc,omitempty"` 25 Desc string `json:"desc,omitempty"`
26 // 菜单是否公开状态,[0:隐藏],[1:显示],默认显示 26 // 菜单是否公开状态,[0:隐藏],[1:显示],默认显示
27 - IsPublish int `json:"isPublish" valid:"Required"` 27 + IsPublish int `json:"isPublish"`
28 } 28 }
29 29
30 func (createMenuCommand *CreateMenuCommand) Valid(validation *validation.Validation) { 30 func (createMenuCommand *CreateMenuCommand) Valid(validation *validation.Validation) {
@@ -9,10 +9,12 @@ import ( @@ -9,10 +9,12 @@ import (
9 type ListMenuQuery struct { 9 type ListMenuQuery struct {
10 // 菜单类别 web app 10 // 菜单类别 web app
11 MenuCategory string `json:"menuCategory,omitempty"` 11 MenuCategory string `json:"menuCategory,omitempty"`
12 - // 菜单父级id 0:查询所有 n:父级id为n的菜单列表  
13 - MenuParentId int64 `json:"parentId,omitempty"` 12 + // 菜单父级id 0:查询所有 n:parent_id为n的菜单列表
  13 + ParentId int64 `json:"parentId,omitempty"`
14 // 菜单名称过滤 14 // 菜单名称过滤
15 MenuName string `json:"menuName,omitempty"` 15 MenuName string `json:"menuName,omitempty"`
  16 + // 结构类型 树型:tree 列表型:list
  17 + StructType string `json:"structType,omitempty"`
16 // 查询偏离量 18 // 查询偏离量
17 Offset int `json:"offset"` 19 Offset int `json:"offset"`
18 // 查询限制 20 // 查询限制
@@ -8,6 +8,7 @@ import ( @@ -8,6 +8,7 @@ import (
8 "gitlab.fjmaimaimai.com/mmm-go-pp/terms/pkg/application/menu/command" 8 "gitlab.fjmaimaimai.com/mmm-go-pp/terms/pkg/application/menu/command"
9 "gitlab.fjmaimaimai.com/mmm-go-pp/terms/pkg/application/menu/query" 9 "gitlab.fjmaimaimai.com/mmm-go-pp/terms/pkg/application/menu/query"
10 "gitlab.fjmaimaimai.com/mmm-go-pp/terms/pkg/domain" 10 "gitlab.fjmaimaimai.com/mmm-go-pp/terms/pkg/domain"
  11 + "gitlab.fjmaimaimai.com/mmm-go-pp/terms/pkg/infrastructure/common"
11 "strconv" 12 "strconv"
12 ) 13 )
13 14
@@ -49,14 +50,24 @@ func (menuService *MenuService) CreateMenu(createMenuCommand *command.CreateMenu @@ -49,14 +50,24 @@ func (menuService *MenuService) CreateMenu(createMenuCommand *command.CreateMenu
49 } else { 50 } else {
50 menuRepository = value 51 menuRepository = value
51 } 52 }
  53 + // 1.菜单类型验证
  54 + if newMenu.ValidMenuType() {
  55 + return nil, application.ThrowError(application.ARG_ERROR, domain.ErrorMenuType.Error())
  56 + }
  57 + // 2.菜单编码验证
  58 + if menu, err := menuRepository.FindOne(map[string]interface{}{"code": createMenuCommand.Code}); err == nil && menu != nil {
  59 + return nil, application.ThrowError(application.ARG_ERROR, fmt.Sprintf("菜单编码:%v已重复,请重新输入", createMenuCommand.Code))
  60 + }
  61 + // 3.更新菜单路径
52 if newMenu.ParentId > 0 { 62 if newMenu.ParentId > 0 {
53 if pMenu, err := menuRepository.FindOne(map[string]interface{}{"menuId": newMenu.ParentId}); err != nil { 63 if pMenu, err := menuRepository.FindOne(map[string]interface{}{"menuId": newMenu.ParentId}); err != nil {
54 - return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error()) 64 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, "父级菜单不存在")
55 } else { 65 } else {
56 newMenu.ParentPath = pMenu.GetParentPath() 66 newMenu.ParentPath = pMenu.GetParentPath()
57 newMenu.Category = pMenu.GetCategory() 67 newMenu.Category = pMenu.GetCategory()
58 } 68 }
59 } 69 }
  70 + // 4.保存菜单项
60 if menu, err := menuRepository.Save(newMenu); err != nil { 71 if menu, err := menuRepository.Save(newMenu); err != nil {
61 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error()) 72 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
62 } else { 73 } else {
@@ -127,7 +138,7 @@ func (menuService *MenuService) ListMenu(listMenuQuery *query.ListMenuQuery) (in @@ -127,7 +138,7 @@ func (menuService *MenuService) ListMenu(listMenuQuery *query.ListMenuQuery) (in
127 } else { 138 } else {
128 menuRepository = value 139 menuRepository = value
129 } 140 }
130 - queryOptions := tool_funs.SimpleStructToMap(listMenuQuery) 141 + queryOptions := common.SimpleStructToMap(listMenuQuery)
131 if len(listMenuQuery.MenuCategory) > 0 { 142 if len(listMenuQuery.MenuCategory) > 0 {
132 queryOptions["code"] = "" 143 queryOptions["code"] = ""
133 if m, e := menuRepository.FindOne(map[string]interface{}{"code": listMenuQuery.MenuCategory}); e == nil && m != nil { 144 if m, e := menuRepository.FindOne(map[string]interface{}{"code": listMenuQuery.MenuCategory}); e == nil && m != nil {
@@ -140,6 +151,18 @@ func (menuService *MenuService) ListMenu(listMenuQuery *query.ListMenuQuery) (in @@ -140,6 +151,18 @@ func (menuService *MenuService) ListMenu(listMenuQuery *query.ListMenuQuery) (in
140 if err := transactionContext.CommitTransaction(); err != nil { 151 if err := transactionContext.CommitTransaction(); err != nil {
141 return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) 152 return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
142 } 153 }
  154 + // 树形返回
  155 + if listMenuQuery.StructType == domain.StructTree {
  156 + var treeNodes = make([]domain.TreeNode, len(menus))
  157 + for i := 0; i < len(menus); i++ {
  158 + treeNodes[i] = menus[i]
  159 + }
  160 + return map[string]interface{}{
  161 + "count": count,
  162 + "menus": domain.NewTrees(treeNodes).Nodes,
  163 + }, nil
  164 + }
  165 + // 列表返回
143 return map[string]interface{}{ 166 return map[string]interface{}{
144 "count": count, 167 "count": count,
145 "menus": menus, 168 "menus": menus,
@@ -170,6 +193,7 @@ func (menuService *MenuService) RemoveMenu(removeMenuCommand *command.RemoveMenu @@ -170,6 +193,7 @@ func (menuService *MenuService) RemoveMenu(removeMenuCommand *command.RemoveMenu
170 } else { 193 } else {
171 menuRepository = value 194 menuRepository = value
172 } 195 }
  196 + // 1.节点是否存在
173 menu, err := menuRepository.FindOne(map[string]interface{}{"menuId": removeMenuCommand.MenuId}) 197 menu, err := menuRepository.FindOne(map[string]interface{}{"menuId": removeMenuCommand.MenuId})
174 if err != nil { 198 if err != nil {
175 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error()) 199 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
@@ -177,6 +201,10 @@ func (menuService *MenuService) RemoveMenu(removeMenuCommand *command.RemoveMenu @@ -177,6 +201,10 @@ func (menuService *MenuService) RemoveMenu(removeMenuCommand *command.RemoveMenu
177 if menu == nil { 201 if menu == nil {
178 return nil, application.ThrowError(application.RES_NO_FIND_ERROR, fmt.Sprintf("%s", string(removeMenuCommand.MenuId))) 202 return nil, application.ThrowError(application.RES_NO_FIND_ERROR, fmt.Sprintf("%s", string(removeMenuCommand.MenuId)))
179 } 203 }
  204 + // 2. 是否存在子节点
  205 + if m, err := menuRepository.FindOne(map[string]interface{}{"parentId": menu.MenuId}); err == nil && m != nil {
  206 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, "下级菜单不为空")
  207 + }
180 if menu, err := menuRepository.Remove(menu); err != nil { 208 if menu, err := menuRepository.Remove(menu); err != nil {
181 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error()) 209 return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
182 } else { 210 } else {
@@ -217,7 +245,13 @@ func (menuService *MenuService) UpdateMenu(updateMenuCommand *command.UpdateMenu @@ -217,7 +245,13 @@ func (menuService *MenuService) UpdateMenu(updateMenuCommand *command.UpdateMenu
217 if menu == nil { 245 if menu == nil {
218 return nil, application.ThrowError(application.RES_NO_FIND_ERROR, fmt.Sprintf("%s", string(updateMenuCommand.MenuId))) 246 return nil, application.ThrowError(application.RES_NO_FIND_ERROR, fmt.Sprintf("%s", string(updateMenuCommand.MenuId)))
219 } 247 }
220 - // 父级节点有发生更新 248 + // 1.验证code是否有重复的情况
  249 + if menu.Code != updateMenuCommand.Code {
  250 + if m, e := menuRepository.FindOne(map[string]interface{}{"code": updateMenuCommand.Code}); e == nil && m.MenuId != menu.MenuId {
  251 + return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  252 + }
  253 + }
  254 + // 2.验证父级节点是否有发生更新
221 if updateMenuCommand.ParentId != menu.ParentId && (updateMenuCommand.ParentId != 0 && menu.ParentId != 0) { 255 if updateMenuCommand.ParentId != menu.ParentId && (updateMenuCommand.ParentId != 0 && menu.ParentId != 0) {
222 var oldParentFullPath, newParentFullPath = menu.GetFullPath(), menu.GetFullPath() 256 var oldParentFullPath, newParentFullPath = menu.GetFullPath(), menu.GetFullPath()
223 var oldParentPath = menu.ParentPath 257 var oldParentPath = menu.ParentPath
@@ -5,6 +5,7 @@ import "os" @@ -5,6 +5,7 @@ import "os"
5 const SERVICE_NAME = "terms.base" 5 const SERVICE_NAME = "terms.base"
6 6
7 var LOG_LEVEL = "debug" 7 var LOG_LEVEL = "debug"
  8 +var EnableCaching = false
8 9
9 func init() { 10 func init() {
10 if os.Getenv("LOG_LEVEL") != "" { 11 if os.Getenv("LOG_LEVEL") != "" {
1 package domain 1 package domain
2 2
3 import ( 3 import (
  4 + "errors"
4 "fmt" 5 "fmt"
5 "strconv" 6 "strconv"
6 "strings" 7 "strings"
7 ) 8 )
8 9
9 -var PathSegment = "," 10 +const PathSegment = ","
  11 +
  12 +var (
  13 + Catalog MenuType = "catalog" // 目录
  14 + Menu_ MenuType = "menu" // 菜单
  15 + Button MenuType = "button" // 按钮
  16 +)
  17 +
  18 +var (
  19 + ErrorMenuType = errors.New(fmt.Sprintf("菜单类型有误 可选值 %v、%v、%v", Catalog, Menu_, Button))
  20 +)
  21 +
  22 +// 菜单类型
  23 +type MenuType string
10 24
11 // 系统菜单 25 // 系统菜单
12 type Menu struct { 26 type Menu struct {
@@ -128,3 +142,19 @@ func (menu *Menu) UpdateParentPath(old, new string) { @@ -128,3 +142,19 @@ func (menu *Menu) UpdateParentPath(old, new string) {
128 } 142 }
129 menu.ParentPath = strings.Replace(menu.ParentPath, old, new, 1) 143 menu.ParentPath = strings.Replace(menu.ParentPath, old, new, 1)
130 } 144 }
  145 +
  146 +func (menu *Menu) ValidMenuType() bool {
  147 + mt := MenuType(menu.MenuType)
  148 + if mt == Catalog || mt == Menu_ || mt == Button {
  149 + return true
  150 + }
  151 + return false
  152 +}
  153 +
  154 +// 实现 TreeNode
  155 +func (menu *Menu) PID() string {
  156 + return menu.ParentPath
  157 +}
  158 +func (menu *Menu) ID() string {
  159 + return menu.GetFullPath()
  160 +}
  1 +package domain
  2 +
  3 +const (
  4 + StructTree = "tree"
  5 + StructList = "list"
  6 +)
  7 +
  8 +type TreeNode interface {
  9 + PID() string
  10 + ID() string
  11 +}
  12 +
  13 +type Tree struct {
  14 + Node TreeNode `json:"node"`
  15 + Nodes []*Tree `json:"nodes"`
  16 +}
  17 +
  18 +func traverse(tree *Tree, node TreeNode) bool {
  19 + list := tree.Nodes
  20 + var match bool = false
  21 + for i := range list {
  22 + id, pid := list[i].Node.ID(), node.PID() //list[i].Node.PID() == node.ID()
  23 + if pid == id {
  24 + list[i].Nodes = append(list[i].Nodes, NewTree(node))
  25 + return true
  26 + }
  27 + if match || traverse(list[i], node) {
  28 + match = true
  29 + break
  30 + }
  31 + }
  32 + return match
  33 +}
  34 +
  35 +func NewTrees(nodes []TreeNode) *Tree {
  36 + var tree = &Tree{
  37 + Node: nil,
  38 + Nodes: make([]*Tree, 0),
  39 + }
  40 + for i := range nodes {
  41 + match := traverse(tree, nodes[i])
  42 + if !match {
  43 + tree.Nodes = append(tree.Nodes, NewTree(nodes[i]))
  44 + }
  45 + }
  46 + return tree
  47 +}
  48 +
  49 +func NewTree(node TreeNode) *Tree {
  50 + return &Tree{
  51 + Node: node,
  52 + Nodes: make([]*Tree, 0),
  53 + }
  54 +}
  1 +package common
  2 +
  3 +import (
  4 + "github.com/linmadan/egglib-go/utils/string_convert"
  5 + "reflect"
  6 +)
  7 +
  8 +func SimpleStructToMap(toMapStruct interface{}) map[string]interface{} {
  9 + m := ObjectToMap(toMapStruct)
  10 + if pageNumber, ok := m["pageNumber"]; ok {
  11 + var pageSize int64
  12 + if _, ok := m["pageSize"]; ok {
  13 + pageSize = m["pageSize"].(int64)
  14 + } else {
  15 + pageSize = 20
  16 + }
  17 + m["offset"] = (pageNumber.(int64) - 1) * pageSize
  18 + m["limit"] = pageSize
  19 + }
  20 + return m
  21 +}
  22 +
  23 +func ObjectToMap(o interface{}) map[string]interface{} {
  24 + if o == nil {
  25 + return nil
  26 + }
  27 + value := reflect.ValueOf(o)
  28 + if value.Kind() != reflect.Ptr {
  29 + return nil
  30 + }
  31 + elem := value.Elem()
  32 + relType := elem.Type()
  33 + m := make(map[string]interface{})
  34 + for i := 0; i < relType.NumField(); i++ {
  35 + field := relType.Field(i)
  36 + if elem.Field(i).IsZero() {
  37 + continue
  38 + }
  39 + m[string_convert.CamelCase(field.Name, false, false)] = elem.Field(i).Interface()
  40 + }
  41 + return m
  42 +}
@@ -163,6 +163,7 @@ func (repository *MenuRepository) Find(queryOptions map[string]interface{}) (int @@ -163,6 +163,7 @@ func (repository *MenuRepository) Find(queryOptions map[string]interface{}) (int
163 if v, ok := queryOptions["menuName"]; ok { 163 if v, ok := queryOptions["menuName"]; ok {
164 query.Where(fmt.Sprintf("menu_name like '%%%v%%'", v)) 164 query.Where(fmt.Sprintf("menu_name like '%%%v%%'", v))
165 } 165 }
  166 + query.SetWhereByQueryOption("parent_id = ?", "parentId")
166 query.SetOffsetAndLimit(20) 167 query.SetOffsetAndLimit(20)
167 query.SetOrderDirect("menu_id", "asc") 168 query.SetOrderDirect("menu_id", "asc")
168 if count, err := query.SelectAndCount(); err != nil { 169 if count, err := query.SelectAndCount(); err != nil {
@@ -56,8 +56,9 @@ func (controller *MenuController) ListMenu() { @@ -56,8 +56,9 @@ func (controller *MenuController) ListMenu() {
56 limit, _ := controller.GetInt("limit") 56 limit, _ := controller.GetInt("limit")
57 listMenuQuery.Limit = limit 57 listMenuQuery.Limit = limit
58 listMenuQuery.MenuCategory = controller.GetString("menuCategory") 58 listMenuQuery.MenuCategory = controller.GetString("menuCategory")
59 - listMenuQuery.MenuParentId, _ = controller.GetInt64("parentId", 0) 59 + listMenuQuery.ParentId, _ = controller.GetInt64("parentId", 0)
60 listMenuQuery.MenuName = controller.GetString("menuName") 60 listMenuQuery.MenuName = controller.GetString("menuName")
  61 + listMenuQuery.StructType = controller.GetString("structType")
61 data, err := menuService.ListMenu(listMenuQuery) 62 data, err := menuService.ListMenu(listMenuQuery)
62 controller.Response(data, err) 63 controller.Response(data, err)
63 } 64 }