package controllers import ( "encoding/json" "io" "server/models" "strconv" "strings" beego "github.com/beego/beego/v2/server/web" ) // AdminMenuController 后台菜单控制器 type AdminMenuController struct { beego.Controller } type menuPayload struct { Pid *int64 `json:"pid"` Title *string `json:"title"` Path *string `json:"path"` ComponentPath *string `json:"component_path"` Icon *string `json:"icon"` Sort *int64 `json:"sort"` Status *int8 `json:"status"` IsVisible *int8 `json:"is_visible"` IsPlatform *int8 `json:"is_platform"` Type *int8 `json:"type"` Permission *string `json:"permission"` } // GetMenu 获取指定用户可见的菜单列表(简化版:当前先忽略用户权限,返回全部启用且平台端菜单) // 路由示例:GET /platform/menu/1 func (c *AdminMenuController) GetMenu() { // 从路由参数中解析用户 ID,占位保留,方便后续按用户权限过滤 _ = c.Ctx.Input.Param(":id") // 查询所有启用且标记为平台端的菜单 var menus []models.SystemMenu qs := models.Orm. QueryTable(new(models.SystemMenu)). Filter("status", 1). Filter("is_platform", 1) _, err := qs.All(&menus) if err != nil { c.Data["json"] = map[string]interface{}{ "code": 500, "msg": "获取菜单失败: " + err.Error(), "data": nil, } _ = c.ServeJSON() return } // 将平铺的菜单列表构建为树形结构 menuTree := buildMenuTree(menus, 0) c.Data["json"] = map[string]interface{}{ "code": 200, "msg": "success", "data": menuTree, } _ = c.ServeJSON() } // GetAllMenus 获取平台端全部菜单(用于菜单管理界面) // 路由:GET /platform/allmenu func (c *AdminMenuController) GetAllMenus() { var menus []models.SystemMenu cid, _ := c.GetInt("cid") qs := models.Orm.QueryTable(new(models.SystemMenu)) // 菜单管理默认返回全量菜单;仅在明确传 cid 时按分类筛选 // cid: 1平台角色 -> 平台菜单;2租户角色 -> 租户菜单 if cid == 1 { qs = qs.Filter("is_platform", 1) } else if cid == 2 { qs = qs.Filter("is_platform", 0) } _, err := qs.All(&menus) if err != nil { c.Data["json"] = map[string]interface{}{ "code": 500, "msg": "获取菜单失败: " + err.Error(), "data": nil, } _ = c.ServeJSON() return } tree := buildMenuTree(menus, 0) c.Data["json"] = map[string]interface{}{ "code": 200, "msg": "success", "data": tree, } _ = c.ServeJSON() } // menuNode 用于 JSON 返回的菜单结构 type menuNode struct { ID uint64 `json:"id"` Pid int64 `json:"pid"` Title string `json:"title"` Path string `json:"path,omitempty"` ComponentPath string `json:"component_path,omitempty"` Icon string `json:"icon,omitempty"` Sort int64 `json:"sort"` Status int8 `json:"status"` IsVisible *int8 `json:"is_visible,omitempty"` IsPlatform *int8 `json:"is_platform,omitempty"` Type int8 `json:"type"` Permission string `json:"permission,omitempty"` Children []*menuNode `json:"children,omitempty"` } // buildMenuTree 将菜单列表构建成树结构 func buildMenuTree(menus []models.SystemMenu, pid int64) []*menuNode { var tree []*menuNode for _, m := range menus { if m.Pid == pid { node := &menuNode{ ID: m.ID, Pid: m.Pid, Title: m.Title, Sort: m.Sort, Status: m.Status, IsVisible: m.IsVisible, IsPlatform: m.IsPlatform, Type: m.Type, } if m.Path != nil { node.Path = *m.Path } if m.ComponentPath != nil { node.ComponentPath = *m.ComponentPath } if m.Icon != nil { node.Icon = *m.Icon } if m.Permission != nil { node.Permission = *m.Permission } // 递归查找子菜单 children := buildMenuTree(menus, int64(m.ID)) if len(children) > 0 { node.Children = children } tree = append(tree, node) } } return tree } // UpdateMenuStatus 更新菜单状态 // 路由:PATCH /platform/menu/status/:id func (c *AdminMenuController) UpdateMenuStatus() { id, err := strconv.ParseUint(c.Ctx.Input.Param(":id"), 10, 64) if err != nil || id == 0 { c.Data["json"] = map[string]interface{}{"code": 400, "msg": "无效菜单ID"} _ = c.ServeJSON() return } var body struct { Status *int8 `json:"status"` } rawBody, _ := io.ReadAll(c.Ctx.Request.Body) if err := json.Unmarshal(rawBody, &body); err != nil || body.Status == nil { c.Data["json"] = map[string]interface{}{"code": 400, "msg": "参数错误"} _ = c.ServeJSON() return } _, err = models.Orm.QueryTable(new(models.SystemMenu)). Filter("id", id). Update(map[string]interface{}{"status": *body.Status}) if err != nil { c.Data["json"] = map[string]interface{}{"code": 500, "msg": "更新失败: " + err.Error()} _ = c.ServeJSON() return } c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success", "success": true} _ = c.ServeJSON() } // CreateMenu 创建菜单 // 路由:POST /platform/createmenu func (c *AdminMenuController) CreateMenu() { payload, ok := c.parseMenuPayload(true) if !ok { return } menu := models.SystemMenu{ Pid: valueInt64(payload.Pid, 0), Title: strings.TrimSpace(valueString(payload.Title, "")), Sort: valueInt64(payload.Sort, 0), Status: valueInt8(payload.Status, 1), IsVisible: ptrInt8(valueInt8(payload.IsVisible, 1)), IsPlatform: ptrInt8(valueInt8(payload.IsPlatform, 1)), Type: valueInt8(payload.Type, 1), } menu.Path = ptrString(valueString(payload.Path, "")) menu.ComponentPath = ptrString(valueString(payload.ComponentPath, "")) menu.Icon = ptrString(valueString(payload.Icon, "")) menu.Permission = ptrString(valueString(payload.Permission, "")) id, err := models.Orm.Insert(&menu) if err != nil { c.Data["json"] = map[string]interface{}{"code": 500, "msg": "创建失败: " + err.Error()} _ = c.ServeJSON() return } c.Data["json"] = map[string]interface{}{ "code": 200, "msg": "创建成功", "data": map[string]interface{}{"id": id}, } _ = c.ServeJSON() } // UpdateMenu 更新菜单 // 路由:PUT /platform/updatemenu/:id func (c *AdminMenuController) UpdateMenu() { id, err := strconv.ParseUint(c.Ctx.Input.Param(":id"), 10, 64) if err != nil || id == 0 { c.Data["json"] = map[string]interface{}{"code": 400, "msg": "无效菜单ID"} _ = c.ServeJSON() return } payload, ok := c.parseMenuPayload(false) if !ok { return } update := map[string]interface{}{ "pid": valueInt64(payload.Pid, 0), "title": strings.TrimSpace(valueString(payload.Title, "")), "path": valueString(payload.Path, ""), "component_path": valueString(payload.ComponentPath, ""), "icon": valueString(payload.Icon, ""), "sort": valueInt64(payload.Sort, 0), "status": valueInt8(payload.Status, 1), "is_visible": valueInt8(payload.IsVisible, 1), "is_platform": valueInt8(payload.IsPlatform, 1), "type": valueInt8(payload.Type, 1), "permission": valueString(payload.Permission, ""), } _, err = models.Orm.QueryTable(new(models.SystemMenu)). Filter("id", id). Update(update) if err != nil { c.Data["json"] = map[string]interface{}{"code": 500, "msg": "更新失败: " + err.Error()} _ = c.ServeJSON() return } c.Data["json"] = map[string]interface{}{"code": 200, "msg": "更新成功"} _ = c.ServeJSON() } // DeleteMenu 删除菜单 // 路由:DELETE /platform/deletemenu/:id func (c *AdminMenuController) DeleteMenu() { id, err := strconv.ParseUint(c.Ctx.Input.Param(":id"), 10, 64) if err != nil || id == 0 { c.Data["json"] = map[string]interface{}{"code": 400, "msg": "无效菜单ID"} _ = c.ServeJSON() return } _, err = models.Orm.QueryTable(new(models.SystemMenu)).Filter("id", id).Delete() if err != nil { c.Data["json"] = map[string]interface{}{"code": 500, "msg": "删除失败: " + err.Error()} _ = c.ServeJSON() return } c.Data["json"] = map[string]interface{}{"code": 200, "msg": "删除成功", "success": true} _ = c.ServeJSON() } func (c *AdminMenuController) parseMenuPayload(needTitle bool) (*menuPayload, bool) { rawBody, _ := io.ReadAll(c.Ctx.Request.Body) var payload menuPayload if err := json.Unmarshal(rawBody, &payload); err != nil { c.Data["json"] = map[string]interface{}{"code": 400, "msg": "参数错误"} _ = c.ServeJSON() return nil, false } if needTitle && strings.TrimSpace(valueString(payload.Title, "")) == "" { c.Data["json"] = map[string]interface{}{"code": 400, "msg": "菜单名称不能为空"} _ = c.ServeJSON() return nil, false } return &payload, true } func valueString(v *string, def string) string { if v == nil { return def } return *v } func valueInt8(v *int8, def int8) int8 { if v == nil { return def } return *v } func valueInt64(v *int64, def int64) int64 { if v == nil { return def } return *v } func ptrString(v string) *string { return &v } func ptrInt8(v int8) *int8 { return &v }