正在显示
9 个修改的文件
包含
174 行增加
和
9 行删除
@@ -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 | +} |
pkg/domain/tree.go
0 → 100644
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 | +} |
pkg/infrastructure/common/common.go
0 → 100644
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 | } |
-
请 注册 或 登录 后发表评论