/
s_menu.go
280 lines (240 loc) · 8.72 KB
/
s_menu.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
package schema
import (
"strings"
"time"
"github.com/ops-cn/common/util"
)
// Menu 菜单对象
type Menu struct {
ID string `json:"id"` // 唯一标识
Name string `json:"name" binding:"required"` // 菜单名称
Sequence int `json:"sequence"` // 排序值
Icon string `json:"icon"` // 菜单图标
Router string `json:"router"` // 访问路由
ParentID string `json:"parent_id"` // 父级ID
ParentPath string `json:"parent_path"` // 父级路径
ShowStatus int `json:"show_status" binding:"required,max=2,min=1"` // 显示状态(1:显示 2:隐藏)
Status int `json:"status" binding:"required,max=2,min=1"` // 状态(1:启用 2:禁用)
Memo string `json:"memo"` // 备注
Creator string `json:"creator"` // 创建者
CreatedAt time.Time `json:"created_at"` // 创建时间
UpdatedAt time.Time `json:"updated_at"` // 更新时间
Actions MenuActions `json:"actions"` // 动作列表
}
func (a *Menu) String() string {
return util.JSONMarshalToString(a)
}
// MenuQueryParam 查询条件
type MenuQueryParam struct {
PaginationParam
IDs []string `form:"-"` // 唯一标识列表
Name string `form:"-"` // 菜单名称
PrefixParentPath string `form:"-"` // 父级路径(前缀模糊查询)
QueryValue string `form:"queryValue"` // 模糊查询
ParentID *string `form:"parentID"` // 父级内码
ShowStatus int `form:"showStatus"` // 显示状态(1:显示 2:隐藏)
Status int `form:"status"` // 状态(1:启用 2:禁用)
}
// MenuQueryOptions 查询可选参数项
type MenuQueryOptions struct {
OrderFields []*OrderField // 排序字段
}
// MenuQueryResult 查询结果
type MenuQueryResult struct {
Data Menus
PageResult *PaginationResult
}
// Menus 菜单列表
type Menus []*Menu
func (a Menus) Len() int {
return len(a)
}
func (a Menus) Less(i, j int) bool {
return a[i].Sequence > a[j].Sequence
}
func (a Menus) Swap(i, j int) {
a[i], a[j] = a[j], a[i]
}
// ToMap 转换为键值映射
func (a Menus) ToMap() map[string]*Menu {
m := make(map[string]*Menu)
for _, item := range a {
m[item.ID] = item
}
return m
}
// SplitParentIDs 拆分父级路径的唯一标识列表
func (a Menus) SplitParentIDs() []string {
idList := make([]string, 0, len(a))
mIDList := make(map[string]struct{})
for _, item := range a {
if _, ok := mIDList[item.ID]; ok || item.ParentPath == "" {
continue
}
for _, pp := range strings.Split(item.ParentPath, "/") {
if _, ok := mIDList[pp]; ok {
continue
}
idList = append(idList, pp)
mIDList[pp] = struct{}{}
}
}
return idList
}
// ToTree 转换为菜单树
func (a Menus) ToTree() MenuTrees {
list := make(MenuTrees, len(a))
for i, item := range a {
list[i] = &MenuTree{
ID: item.ID,
Name: item.Name,
Icon: item.Icon,
Router: item.Router,
ParentID: item.ParentID,
ParentPath: item.ParentPath,
Sequence: item.Sequence,
ShowStatus: item.ShowStatus,
Status: item.Status,
Actions: item.Actions,
}
}
return list.ToTree()
}
// FillMenuAction 填充菜单动作列表
func (a Menus) FillMenuAction(mActions map[string]MenuActions) Menus {
for _, item := range a {
if v, ok := mActions[item.ID]; ok {
item.Actions = v
}
}
return a
}
// ----------------------------------------MenuTree--------------------------------------
// MenuTree 菜单树
type MenuTree struct {
ID string `yaml:"-" json:"id"` // 唯一标识
Name string `yaml:"name" json:"name"` // 菜单名称
Icon string `yaml:"icon" json:"icon"` // 菜单图标
Router string `yaml:"router,omitempty" json:"router"` // 访问路由
ParentID string `yaml:"-" json:"parent_id"` // 父级ID
ParentPath string `yaml:"-" json:"parent_path"` // 父级路径
Sequence int `yaml:"sequence" json:"sequence"` // 排序值
ShowStatus int `yaml:"-" json:"show_status"` // 显示状态(1:显示 2:隐藏)
Status int `yaml:"-" json:"status"` // 状态(1:启用 2:禁用)
Actions MenuActions `yaml:"actions,omitempty" json:"actions"` // 动作列表
Children *MenuTrees `yaml:"children,omitempty" json:"children,omitempty"` // 子级树
}
// MenuTrees 菜单树列表
type MenuTrees []*MenuTree
// ToTree 转换为树形结构
func (a MenuTrees) ToTree() MenuTrees {
mi := make(map[string]*MenuTree)
for _, item := range a {
mi[item.ID] = item
}
var list MenuTrees
for _, item := range a {
if item.ParentID == "" {
list = append(list, item)
continue
}
if pitem, ok := mi[item.ParentID]; ok {
if pitem.Children == nil {
children := MenuTrees{item}
pitem.Children = &children
continue
}
*pitem.Children = append(*pitem.Children, item)
}
}
return list
}
// ----------------------------------------MenuAction--------------------------------------
// MenuAction 菜单动作对象
type MenuAction struct {
ID string `yaml:"-" json:"id"` // 唯一标识
MenuID string `yaml:"-" binding:"required" json:"menu_id"` // 菜单ID
Code string `yaml:"code" binding:"required" json:"code"` // 动作编号
Name string `yaml:"name" binding:"required" json:"name"` // 动作名称
Resources MenuActionResources `yaml:"resources,omitempty" json:"resources"` // 资源列表
}
// MenuActionQueryParam 查询条件
type MenuActionQueryParam struct {
PaginationParam
MenuID string // 菜单ID
IDs []string // 唯一标识列表
}
// MenuActionQueryOptions 查询可选参数项
type MenuActionQueryOptions struct {
OrderFields []*OrderField // 排序字段
}
// MenuActionQueryResult 查询结果
type MenuActionQueryResult struct {
Data MenuActions
PageResult *PaginationResult
}
// MenuActions 菜单动作管理列表
type MenuActions []*MenuAction
// ToMap 转换为map
func (a MenuActions) ToMap() map[string]*MenuAction {
m := make(map[string]*MenuAction)
for _, item := range a {
m[item.Code] = item
}
return m
}
// FillResources 填充资源数据
func (a MenuActions) FillResources(mResources map[string]MenuActionResources) {
for i, item := range a {
a[i].Resources = mResources[item.ID]
}
}
// ToMenuIDMap 转换为菜单ID映射
func (a MenuActions) ToMenuIDMap() map[string]MenuActions {
m := make(map[string]MenuActions)
for _, item := range a {
m[item.MenuID] = append(m[item.MenuID], item)
}
return m
}
// ----------------------------------------MenuActionResource--------------------------------------
// MenuActionResource 菜单动作关联资源对象
type MenuActionResource struct {
ID string `yaml:"-" json:"id"` // 唯一标识
ActionID string `yaml:"-" json:"action_id"` // 菜单动作ID
Method string `yaml:"method" binding:"required" json:"method"` // 资源请求方式(支持正则)
Path string `yaml:"path" binding:"required" json:"path"` // 资源请求路径(支持/:id匹配)
}
// MenuActionResourceQueryParam 查询条件
type MenuActionResourceQueryParam struct {
PaginationParam
MenuID string // 菜单ID
MenuIDs []string // 菜单ID列表
}
// MenuActionResourceQueryOptions 查询可选参数项
type MenuActionResourceQueryOptions struct {
OrderFields []*OrderField // 排序字段
}
// MenuActionResourceQueryResult 查询结果
type MenuActionResourceQueryResult struct {
Data MenuActionResources
PageResult *PaginationResult
}
// MenuActionResources 菜单动作关联资源管理列表
type MenuActionResources []*MenuActionResource
// ToMap 转换为map
func (a MenuActionResources) ToMap() map[string]*MenuActionResource {
m := make(map[string]*MenuActionResource)
for _, item := range a {
m[item.Method+item.Path] = item
}
return m
}
// ToActionIDMap 转换为动作ID映射
func (a MenuActionResources) ToActionIDMap() map[string]MenuActionResources {
m := make(map[string]MenuActionResources)
for _, item := range a {
m[item.ActionID] = append(m[item.ActionID], item)
}
return m
}