first commit
This commit is contained in:
97
app/main/api/internal/logic/admin_menu/createmenulogic.go
Normal file
97
app/main/api/internal/logic/admin_menu/createmenulogic.go
Normal file
@@ -0,0 +1,97 @@
|
||||
package admin_menu
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"hm-server/app/main/api/internal/svc"
|
||||
"hm-server/app/main/api/internal/types"
|
||||
"hm-server/app/main/model"
|
||||
"hm-server/common/xerr"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type CreateMenuLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewCreateMenuLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateMenuLogic {
|
||||
return &CreateMenuLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *CreateMenuLogic) CreateMenu(req *types.CreateMenuReq) (resp *types.CreateMenuResp, err error) {
|
||||
// 1. 参数验证
|
||||
if req.Name == "" {
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg("菜单名称不能为空"), "菜单名称不能为空")
|
||||
}
|
||||
if req.Type == "menu" && req.Component == "" {
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg("组件路径不能为空"), "组件路径不能为空")
|
||||
}
|
||||
|
||||
// 2. 检查名称和路径是否重复
|
||||
exists, err := l.svcCtx.AdminMenuModel.FindOneByNamePath(l.ctx, req.Name, req.Path)
|
||||
if err != nil && !errors.Is(err, model.ErrNotFound) {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询菜单失败, err: %v", err)
|
||||
}
|
||||
if exists != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg("菜单名称或路径已存在"), "菜单名称或路径已存在")
|
||||
}
|
||||
|
||||
// 3. 检查父菜单是否存在(如果不是根菜单)
|
||||
if req.Pid > 0 {
|
||||
parentMenu, err := l.svcCtx.AdminMenuModel.FindOne(l.ctx, req.Pid)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询父菜单失败, id: %d, err: %v", req.Pid, err)
|
||||
}
|
||||
if parentMenu == nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "父菜单不存在, id: %d", req.Pid)
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 将类型标签转换为值
|
||||
typeValue, err := l.svcCtx.DictService.GetDictValue(l.ctx, "admin_menu_type", req.Type)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "菜单类型无效: %v", err)
|
||||
}
|
||||
|
||||
// 5. 创建菜单记录
|
||||
menu := &model.AdminMenu{
|
||||
Pid: req.Pid,
|
||||
Name: req.Name,
|
||||
Path: req.Path,
|
||||
Component: req.Component,
|
||||
Redirect: sql.NullString{String: req.Redirect, Valid: req.Redirect != ""},
|
||||
Status: req.Status,
|
||||
Type: typeValue,
|
||||
Sort: req.Sort,
|
||||
CreateTime: time.Now(),
|
||||
UpdateTime: time.Now(),
|
||||
}
|
||||
|
||||
// 将Meta转换为JSON字符串
|
||||
metaJson, err := json.Marshal(req.Meta)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "Meta数据格式错误: %v", err)
|
||||
}
|
||||
menu.Meta = string(metaJson)
|
||||
|
||||
// 6. 保存到数据库
|
||||
_, err = l.svcCtx.AdminMenuModel.Insert(l.ctx, nil, menu)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "创建菜单失败, err: %v", err)
|
||||
}
|
||||
|
||||
return &types.CreateMenuResp{
|
||||
Id: menu.Id,
|
||||
}, nil
|
||||
}
|
||||
75
app/main/api/internal/logic/admin_menu/deletemenulogic.go
Normal file
75
app/main/api/internal/logic/admin_menu/deletemenulogic.go
Normal file
@@ -0,0 +1,75 @@
|
||||
package admin_menu
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"hm-server/app/main/api/internal/svc"
|
||||
"hm-server/app/main/api/internal/types"
|
||||
"hm-server/common/xerr"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type DeleteMenuLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewDeleteMenuLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteMenuLogic {
|
||||
return &DeleteMenuLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *DeleteMenuLogic) DeleteMenu(req *types.DeleteMenuReq) (resp *types.DeleteMenuResp, err error) {
|
||||
// 1. 参数验证
|
||||
if req.Id <= 0 {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.PARAM_VERIFICATION_ERROR),
|
||||
"菜单ID必须大于0, id: %d", req.Id)
|
||||
}
|
||||
|
||||
// 2. 查询菜单是否存在
|
||||
menu, err := l.svcCtx.AdminMenuModel.FindOne(l.ctx, req.Id)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR),
|
||||
"查找菜单失败, err: %v, id: %d", err, req.Id)
|
||||
}
|
||||
|
||||
// 3. 检查是否有子菜单
|
||||
childMenuBuilder := l.svcCtx.AdminMenuModel.SelectBuilder().Where("pid = ?", req.Id)
|
||||
childMenus, err := l.svcCtx.AdminMenuModel.FindAll(l.ctx, childMenuBuilder, "")
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR),
|
||||
"查询子菜单失败, err: %v, parent_id: %d", err, req.Id)
|
||||
}
|
||||
if len(childMenus) > 0 {
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg("该菜单下还有子菜单,无法删除"),
|
||||
"该菜单下还有子菜单,无法删除, id: %d", req.Id)
|
||||
}
|
||||
|
||||
// 4. 检查是否有角色关联该菜单
|
||||
roleMenuBuilder := l.svcCtx.AdminRoleMenuModel.SelectBuilder().Where("menu_id = ?", req.Id)
|
||||
roleMenus, err := l.svcCtx.AdminRoleMenuModel.FindAll(l.ctx, roleMenuBuilder, "")
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR),
|
||||
"查询角色菜单关联失败, err: %v, menu_id: %d", err, req.Id)
|
||||
}
|
||||
if len(roleMenus) > 0 {
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg("该菜单已被角色使用,无法删除"),
|
||||
"该菜单已被角色使用,无法删除, id: %d", req.Id)
|
||||
}
|
||||
|
||||
// 5. 执行软删除
|
||||
err = l.svcCtx.AdminMenuModel.DeleteSoft(l.ctx, nil, menu)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR),
|
||||
"删除菜单失败, err: %v, id: %d", err, req.Id)
|
||||
}
|
||||
|
||||
// 6. 返回成功结果
|
||||
return &types.DeleteMenuResp{Success: true}, nil
|
||||
}
|
||||
250
app/main/api/internal/logic/admin_menu/getmenualllogic.go
Normal file
250
app/main/api/internal/logic/admin_menu/getmenualllogic.go
Normal file
@@ -0,0 +1,250 @@
|
||||
package admin_menu
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sort"
|
||||
"strconv"
|
||||
|
||||
"hm-server/app/main/api/internal/svc"
|
||||
"hm-server/app/main/api/internal/types"
|
||||
"hm-server/common/ctxdata"
|
||||
"hm-server/common/xerr"
|
||||
|
||||
"github.com/Masterminds/squirrel"
|
||||
"github.com/bytedance/sonic"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/samber/lo"
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
"github.com/zeromicro/go-zero/core/mr"
|
||||
)
|
||||
|
||||
type GetMenuAllLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewGetMenuAllLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetMenuAllLogic {
|
||||
return &GetMenuAllLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *GetMenuAllLogic) GetMenuAll(req *types.GetMenuAllReq) (resp *[]types.GetMenuAllResp, err error) {
|
||||
userId, err := ctxdata.GetUidFromCtx(l.ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取用户ID失败, %+v", err)
|
||||
}
|
||||
|
||||
// 使用MapReduceVoid并发获取用户角色
|
||||
var roleIds []int64
|
||||
var permissions []*struct {
|
||||
RoleId int64
|
||||
}
|
||||
|
||||
type UserRoleResult struct {
|
||||
RoleId int64
|
||||
}
|
||||
|
||||
err = mr.MapReduceVoid(
|
||||
func(source chan<- interface{}) {
|
||||
adminUserRoleBuilder := l.svcCtx.AdminUserRoleModel.SelectBuilder().Where(squirrel.Eq{"user_id": userId})
|
||||
source <- adminUserRoleBuilder
|
||||
},
|
||||
func(item interface{}, writer mr.Writer[*UserRoleResult], cancel func(error)) {
|
||||
builder := item.(squirrel.SelectBuilder)
|
||||
result, err := l.svcCtx.AdminUserRoleModel.FindAll(l.ctx, builder, "role_id DESC")
|
||||
if err != nil {
|
||||
cancel(errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取用户角色信息失败, %+v", err))
|
||||
return
|
||||
}
|
||||
|
||||
for _, r := range result {
|
||||
writer.Write(&UserRoleResult{RoleId: r.RoleId})
|
||||
}
|
||||
},
|
||||
func(pipe <-chan *UserRoleResult, cancel func(error)) {
|
||||
for item := range pipe {
|
||||
permissions = append(permissions, &struct{ RoleId int64 }{RoleId: item.RoleId})
|
||||
}
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, permission := range permissions {
|
||||
roleIds = append(roleIds, permission.RoleId)
|
||||
}
|
||||
|
||||
// 使用MapReduceVoid并发获取角色菜单
|
||||
var menuIds []int64
|
||||
var roleMenus []*struct {
|
||||
MenuId int64
|
||||
}
|
||||
|
||||
type RoleMenuResult struct {
|
||||
MenuId int64
|
||||
}
|
||||
|
||||
err = mr.MapReduceVoid(
|
||||
func(source chan<- interface{}) {
|
||||
getRoleMenuBuilder := l.svcCtx.AdminRoleMenuModel.SelectBuilder().Where(squirrel.Eq{"role_id": roleIds})
|
||||
source <- getRoleMenuBuilder
|
||||
},
|
||||
func(item interface{}, writer mr.Writer[*RoleMenuResult], cancel func(error)) {
|
||||
builder := item.(squirrel.SelectBuilder)
|
||||
result, err := l.svcCtx.AdminRoleMenuModel.FindAll(l.ctx, builder, "id DESC")
|
||||
if err != nil {
|
||||
cancel(errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取角色菜单信息失败, %+v", err))
|
||||
return
|
||||
}
|
||||
|
||||
for _, r := range result {
|
||||
writer.Write(&RoleMenuResult{MenuId: r.MenuId})
|
||||
}
|
||||
},
|
||||
func(pipe <-chan *RoleMenuResult, cancel func(error)) {
|
||||
for item := range pipe {
|
||||
roleMenus = append(roleMenus, &struct{ MenuId int64 }{MenuId: item.MenuId})
|
||||
}
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, roleMenu := range roleMenus {
|
||||
menuIds = append(menuIds, roleMenu.MenuId)
|
||||
}
|
||||
|
||||
// 使用MapReduceVoid并发获取菜单
|
||||
type AdminMenuStruct struct {
|
||||
Id int64
|
||||
Pid int64
|
||||
Name string
|
||||
Path string
|
||||
Component string
|
||||
Redirect struct {
|
||||
String string
|
||||
Valid bool
|
||||
}
|
||||
Meta string
|
||||
Sort int64
|
||||
Type int64
|
||||
Status int64
|
||||
}
|
||||
|
||||
var menus []*AdminMenuStruct
|
||||
|
||||
err = mr.MapReduceVoid(
|
||||
func(source chan<- interface{}) {
|
||||
adminMenuBuilder := l.svcCtx.AdminMenuModel.SelectBuilder().Where(squirrel.Eq{"id": menuIds})
|
||||
source <- adminMenuBuilder
|
||||
},
|
||||
func(item interface{}, writer mr.Writer[*AdminMenuStruct], cancel func(error)) {
|
||||
builder := item.(squirrel.SelectBuilder)
|
||||
result, err := l.svcCtx.AdminMenuModel.FindAll(l.ctx, builder, "sort ASC")
|
||||
if err != nil {
|
||||
cancel(errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取菜单信息失败, %+v", err))
|
||||
return
|
||||
}
|
||||
|
||||
for _, r := range result {
|
||||
menu := &AdminMenuStruct{
|
||||
Id: r.Id,
|
||||
Pid: r.Pid,
|
||||
Name: r.Name,
|
||||
Path: r.Path,
|
||||
Component: r.Component,
|
||||
Redirect: r.Redirect,
|
||||
Meta: r.Meta,
|
||||
Sort: r.Sort,
|
||||
Type: r.Type,
|
||||
Status: r.Status,
|
||||
}
|
||||
writer.Write(menu)
|
||||
}
|
||||
},
|
||||
func(pipe <-chan *AdminMenuStruct, cancel func(error)) {
|
||||
for item := range pipe {
|
||||
menus = append(menus, item)
|
||||
}
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 转换为types.Menu结构并存储到映射表
|
||||
menuMap := make(map[string]types.GetMenuAllResp)
|
||||
for _, menu := range menus {
|
||||
// 只处理状态正常的菜单
|
||||
if menu.Status != 1 {
|
||||
continue
|
||||
}
|
||||
|
||||
meta := make(map[string]interface{})
|
||||
err = sonic.Unmarshal([]byte(menu.Meta), &meta)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "解析菜单Meta信息失败, %+v", err)
|
||||
}
|
||||
|
||||
redirect := func() string {
|
||||
if menu.Redirect.Valid {
|
||||
return menu.Redirect.String
|
||||
}
|
||||
return ""
|
||||
}()
|
||||
|
||||
menuId := strconv.FormatInt(menu.Id, 10)
|
||||
menuMap[menuId] = types.GetMenuAllResp{
|
||||
Name: menu.Name,
|
||||
Path: menu.Path,
|
||||
Redirect: redirect,
|
||||
Component: menu.Component,
|
||||
Sort: menu.Sort,
|
||||
Meta: meta,
|
||||
Children: make([]types.GetMenuAllResp, 0),
|
||||
}
|
||||
}
|
||||
|
||||
// 按ParentId将菜单分组
|
||||
menuGroups := lo.GroupBy(menus, func(item *AdminMenuStruct) int64 {
|
||||
return item.Pid
|
||||
})
|
||||
|
||||
// 递归构建菜单树
|
||||
var buildMenuTree func(parentId int64) []types.GetMenuAllResp
|
||||
buildMenuTree = func(parentId int64) []types.GetMenuAllResp {
|
||||
children := make([]types.GetMenuAllResp, 0)
|
||||
|
||||
childMenus, ok := menuGroups[parentId]
|
||||
if !ok {
|
||||
return children
|
||||
}
|
||||
|
||||
// 按Sort排序
|
||||
sort.Slice(childMenus, func(i, j int) bool {
|
||||
return childMenus[i].Sort < childMenus[j].Sort
|
||||
})
|
||||
|
||||
for _, childMenu := range childMenus {
|
||||
menuId := strconv.FormatInt(childMenu.Id, 10)
|
||||
if menu, exists := menuMap[menuId]; exists && childMenu.Status == 1 {
|
||||
// 递归构建子菜单
|
||||
menu.Children = buildMenuTree(childMenu.Id)
|
||||
children = append(children, menu)
|
||||
}
|
||||
}
|
||||
|
||||
return children
|
||||
}
|
||||
|
||||
// 从根菜单开始构建(ParentId为0的是根菜单)
|
||||
menuTree := buildMenuTree(0)
|
||||
|
||||
return &menuTree, nil
|
||||
}
|
||||
30
app/main/api/internal/logic/admin_menu/getmenudetaillogic.go
Normal file
30
app/main/api/internal/logic/admin_menu/getmenudetaillogic.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package admin_menu
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"hm-server/app/main/api/internal/svc"
|
||||
"hm-server/app/main/api/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type GetMenuDetailLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewGetMenuDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetMenuDetailLogic {
|
||||
return &GetMenuDetailLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *GetMenuDetailLogic) GetMenuDetail(req *types.GetMenuDetailReq) (resp *types.GetMenuDetailResp, err error) {
|
||||
// todo: add your logic here and delete this line
|
||||
|
||||
return
|
||||
}
|
||||
109
app/main/api/internal/logic/admin_menu/getmenulistlogic.go
Normal file
109
app/main/api/internal/logic/admin_menu/getmenulistlogic.go
Normal file
@@ -0,0 +1,109 @@
|
||||
package admin_menu
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
"hm-server/app/main/api/internal/svc"
|
||||
"hm-server/app/main/api/internal/types"
|
||||
"hm-server/common/xerr"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type GetMenuListLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewGetMenuListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetMenuListLogic {
|
||||
return &GetMenuListLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *GetMenuListLogic) GetMenuList(req *types.GetMenuListReq) (resp []types.MenuListItem, err error) {
|
||||
// 构建查询条件
|
||||
builder := l.svcCtx.AdminMenuModel.SelectBuilder()
|
||||
|
||||
// 添加筛选条件
|
||||
if len(req.Name) > 0 {
|
||||
builder = builder.Where("name LIKE ?", "%"+req.Name+"%")
|
||||
}
|
||||
if len(req.Path) > 0 {
|
||||
builder = builder.Where("path LIKE ?", "%"+req.Path+"%")
|
||||
}
|
||||
if req.Status != -1 {
|
||||
builder = builder.Where("status = ?", req.Status)
|
||||
}
|
||||
if req.Type != "" {
|
||||
builder = builder.Where("type = ?", req.Type)
|
||||
}
|
||||
|
||||
// 排序但不分页,获取所有符合条件的菜单
|
||||
builder = builder.OrderBy("sort ASC")
|
||||
|
||||
// 获取所有菜单
|
||||
menus, err := l.svcCtx.AdminMenuModel.FindAll(l.ctx, builder, "id ASC")
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询菜单失败, err: %v", err)
|
||||
}
|
||||
|
||||
// 将菜单按ID存入map
|
||||
menuMap := make(map[int64]types.MenuListItem)
|
||||
for _, menu := range menus {
|
||||
var meta map[string]interface{}
|
||||
err := json.Unmarshal([]byte(menu.Meta), &meta)
|
||||
if err != nil {
|
||||
logx.Errorf("解析Meta字段失败: %v", err)
|
||||
meta = make(map[string]interface{})
|
||||
}
|
||||
menuType, err := l.svcCtx.DictService.GetDictLabel(l.ctx, "admin_menu_type", menu.Type)
|
||||
if err != nil {
|
||||
logx.Errorf("获取菜单类型失败: %v", err)
|
||||
menuType = ""
|
||||
}
|
||||
item := types.MenuListItem{
|
||||
Id: menu.Id,
|
||||
Pid: menu.Pid,
|
||||
Name: menu.Name,
|
||||
Path: menu.Path,
|
||||
Component: menu.Component,
|
||||
Redirect: menu.Redirect.String,
|
||||
Meta: meta,
|
||||
Status: menu.Status,
|
||||
Type: menuType,
|
||||
Sort: menu.Sort,
|
||||
CreateTime: menu.CreateTime.Format("2006-01-02 15:04:05"),
|
||||
Children: make([]types.MenuListItem, 0),
|
||||
}
|
||||
menuMap[menu.Id] = item
|
||||
}
|
||||
|
||||
// 构建父子关系
|
||||
for _, menu := range menus {
|
||||
if menu.Pid > 0 {
|
||||
// 找到父菜单
|
||||
if parent, exists := menuMap[menu.Pid]; exists {
|
||||
// 添加当前菜单到父菜单的子菜单列表
|
||||
children := append(parent.Children, menuMap[menu.Id])
|
||||
parent.Children = children
|
||||
menuMap[menu.Pid] = parent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 提取顶级菜单(ParentId为0)到响应列表
|
||||
result := make([]types.MenuListItem, 0)
|
||||
for _, menu := range menus {
|
||||
if menu.Pid == 0 {
|
||||
result = append(result, menuMap[menu.Id])
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
96
app/main/api/internal/logic/admin_menu/updatemenulogic.go
Normal file
96
app/main/api/internal/logic/admin_menu/updatemenulogic.go
Normal file
@@ -0,0 +1,96 @@
|
||||
package admin_menu
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
|
||||
"hm-server/app/main/api/internal/svc"
|
||||
"hm-server/app/main/api/internal/types"
|
||||
"hm-server/app/main/model"
|
||||
"hm-server/common/xerr"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type UpdateMenuLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewUpdateMenuLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateMenuLogic {
|
||||
return &UpdateMenuLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *UpdateMenuLogic) UpdateMenu(req *types.UpdateMenuReq) (resp *types.UpdateMenuResp, err error) {
|
||||
// 1. 检查菜单是否存在
|
||||
menu, err := l.svcCtx.AdminMenuModel.FindOne(l.ctx, req.Id)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询菜单失败, id: %d, err: %v", req.Id, err)
|
||||
}
|
||||
if menu == nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "菜单不存在, id: %d", req.Id)
|
||||
}
|
||||
|
||||
// 2. 将类型标签转换为值
|
||||
typeValue, err := l.svcCtx.DictService.GetDictValue(l.ctx, "admin_menu_type", req.Type)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "菜单类型无效: %v", err)
|
||||
}
|
||||
|
||||
// 3. 检查父菜单是否存在(如果不是根菜单)
|
||||
if req.Pid > 0 {
|
||||
parentMenu, err := l.svcCtx.AdminMenuModel.FindOne(l.ctx, req.Pid)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询父菜单失败, id: %d, err: %v", req.Pid, err)
|
||||
}
|
||||
if parentMenu == nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "父菜单不存在, id: %d", req.Pid)
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 检查名称和路径是否重复
|
||||
if req.Name != menu.Name || req.Path != menu.Path {
|
||||
exists, err := l.svcCtx.AdminMenuModel.FindOneByNamePath(l.ctx, req.Name, req.Path)
|
||||
if err != nil && !errors.Is(err, model.ErrNotFound) {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询菜单失败, err: %v", err)
|
||||
}
|
||||
if exists != nil && exists.Id != req.Id {
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg("菜单名称或路径已存在"), "菜单名称或路径已存在")
|
||||
}
|
||||
}
|
||||
|
||||
// 5. 更新菜单信息
|
||||
|
||||
menu.Pid = req.Pid
|
||||
menu.Name = req.Name
|
||||
menu.Path = req.Path
|
||||
menu.Component = req.Component
|
||||
menu.Redirect = sql.NullString{String: req.Redirect, Valid: req.Redirect != ""}
|
||||
menu.Status = req.Status
|
||||
menu.Type = typeValue
|
||||
menu.Sort = req.Sort
|
||||
|
||||
// 将Meta转换为JSON字符串
|
||||
metaJson, err := json.Marshal(req.Meta)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "Meta数据格式错误: %v", err)
|
||||
}
|
||||
menu.Meta = string(metaJson)
|
||||
|
||||
// 6. 保存更新
|
||||
_, err = l.svcCtx.AdminMenuModel.Update(l.ctx, nil, menu)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "更新菜单失败, err: %v", err)
|
||||
}
|
||||
|
||||
return &types.UpdateMenuResp{
|
||||
Success: true,
|
||||
}, nil
|
||||
}
|
||||
Reference in New Issue
Block a user