19 changed files with 799 additions and 1198 deletions
@ -0,0 +1,354 @@
@@ -0,0 +1,354 @@
|
||||
package controller |
||||
|
||||
import ( |
||||
"net/http" |
||||
"strconv" |
||||
"gofaster/internal/auth/model" |
||||
"gofaster/internal/auth/service" |
||||
"gofaster/internal/shared/response" |
||||
|
||||
"github.com/gin-gonic/gin" |
||||
"go.uber.org/zap" |
||||
) |
||||
|
||||
// MenuGroupController 菜单分组控制器
|
||||
type MenuGroupController struct { |
||||
menuGroupService *service.MenuGroupService |
||||
logger *zap.Logger |
||||
} |
||||
|
||||
// NewMenuGroupController 创建菜单分组控制器实例
|
||||
func NewMenuGroupController(menuGroupService *service.MenuGroupService, logger *zap.Logger) *MenuGroupController { |
||||
return &MenuGroupController{ |
||||
menuGroupService: menuGroupService, |
||||
logger: logger, |
||||
} |
||||
} |
||||
|
||||
// CreateMenuGroup 创建菜单分组
|
||||
// @Summary 创建菜单分组
|
||||
// @Description 创建新的菜单分组
|
||||
// @Tags 菜单分组管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param menuGroup body model.MenuGroup true "菜单分组信息"
|
||||
// @Success 200 {object} response.Response{data=model.MenuGroup}
|
||||
// @Failure 400 {object} response.Response
|
||||
// @Failure 500 {object} response.Response
|
||||
// @Router /api/menu-groups [post]
|
||||
func (c *MenuGroupController) CreateMenuGroup(ctx *gin.Context) { |
||||
var menuGroup model.MenuGroup |
||||
if err := ctx.ShouldBindJSON(&menuGroup); err != nil { |
||||
response.Error(ctx, http.StatusBadRequest, "请求参数错误", err.Error()) |
||||
return |
||||
} |
||||
|
||||
// 验证必填字段
|
||||
if menuGroup.Name == "" { |
||||
response.Error(ctx, http.StatusBadRequest, "请求参数错误", "分组名称不能为空") |
||||
return |
||||
} |
||||
|
||||
if err := c.menuGroupService.CreateMenuGroup(&menuGroup); err != nil { |
||||
response.Error(ctx, http.StatusInternalServerError, "创建菜单分组失败", err.Error()) |
||||
return |
||||
} |
||||
|
||||
response.Success(ctx, "创建菜单分组成功", menuGroup) |
||||
} |
||||
|
||||
// GetMenuGroup 获取菜单分组详情
|
||||
// @Summary 获取菜单分组详情
|
||||
// @Description 根据ID获取菜单分组详情
|
||||
// @Tags 菜单分组管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "菜单分组ID"
|
||||
// @Success 200 {object} response.Response{data=model.MenuGroup}
|
||||
// @Failure 400 {object} response.Response
|
||||
// @Failure 404 {object} response.Response
|
||||
// @Failure 500 {object} response.Response
|
||||
// @Router /api/menu-groups/{id} [get]
|
||||
func (c *MenuGroupController) GetMenuGroup(ctx *gin.Context) { |
||||
idStr := ctx.Param("id") |
||||
id, err := strconv.ParseUint(idStr, 10, 32) |
||||
if err != nil { |
||||
response.Error(ctx, http.StatusBadRequest, "请求参数错误", "ID格式错误") |
||||
return |
||||
} |
||||
|
||||
menuGroup, err := c.menuGroupService.GetMenuGroupByID(uint(id)) |
||||
if err != nil { |
||||
response.Error(ctx, http.StatusNotFound, "菜单分组不存在", err.Error()) |
||||
return |
||||
} |
||||
|
||||
response.Success(ctx, "获取菜单分组成功", menuGroup) |
||||
} |
||||
|
||||
// ListMenuGroups 获取菜单分组列表
|
||||
// @Summary 获取菜单分组列表
|
||||
// @Description 获取所有菜单分组列表
|
||||
// @Tags 菜单分组管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param status query int false "状态筛选" Enums(0,1)
|
||||
// @Success 200 {object} response.Response{data=[]model.MenuGroup}
|
||||
// @Failure 500 {object} response.Response
|
||||
// @Router /api/menu-groups [get]
|
||||
func (c *MenuGroupController) ListMenuGroups(ctx *gin.Context) { |
||||
statusStr := ctx.Query("status") |
||||
|
||||
var menuGroups []*model.MenuGroup |
||||
var err error |
||||
|
||||
if statusStr != "" { |
||||
status, parseErr := strconv.Atoi(statusStr) |
||||
if parseErr != nil { |
||||
response.Error(ctx, http.StatusBadRequest, "请求参数错误", "状态参数格式错误") |
||||
return |
||||
} |
||||
menuGroups, err = c.menuGroupService.ListMenuGroupsByStatus(status) |
||||
} else { |
||||
menuGroups, err = c.menuGroupService.ListMenuGroups() |
||||
} |
||||
|
||||
if err != nil { |
||||
response.Error(ctx, http.StatusInternalServerError, "获取菜单分组列表失败", err.Error()) |
||||
return |
||||
} |
||||
|
||||
response.Success(ctx, "获取菜单分组列表成功", menuGroups) |
||||
} |
||||
|
||||
// UpdateMenuGroup 更新菜单分组
|
||||
// @Summary 更新菜单分组
|
||||
// @Description 更新菜单分组信息
|
||||
// @Tags 菜单分组管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "菜单分组ID"
|
||||
// @Param menuGroup body model.MenuGroup true "菜单分组信息"
|
||||
// @Success 200 {object} response.Response{data=model.MenuGroup}
|
||||
// @Failure 400 {object} response.Response
|
||||
// @Failure 404 {object} response.Response
|
||||
// @Failure 500 {object} response.Response
|
||||
// @Router /api/menu-groups/{id} [put]
|
||||
func (c *MenuGroupController) UpdateMenuGroup(ctx *gin.Context) { |
||||
idStr := ctx.Param("id") |
||||
id, err := strconv.ParseUint(idStr, 10, 32) |
||||
if err != nil { |
||||
response.Error(ctx, http.StatusBadRequest, "请求参数错误", "ID格式错误") |
||||
return |
||||
} |
||||
|
||||
var menuGroup model.MenuGroup |
||||
if err := ctx.ShouldBindJSON(&menuGroup); err != nil { |
||||
response.Error(ctx, http.StatusBadRequest, "请求参数错误", err.Error()) |
||||
return |
||||
} |
||||
|
||||
// 验证必填字段
|
||||
if menuGroup.Name == "" { |
||||
response.Error(ctx, http.StatusBadRequest, "请求参数错误", "分组名称不能为空") |
||||
return |
||||
} |
||||
|
||||
menuGroup.ID = uint(id) |
||||
|
||||
if err := c.menuGroupService.UpdateMenuGroup(&menuGroup); err != nil { |
||||
response.Error(ctx, http.StatusInternalServerError, "更新菜单分组失败", err.Error()) |
||||
return |
||||
} |
||||
|
||||
response.Success(ctx, "更新菜单分组成功", menuGroup) |
||||
} |
||||
|
||||
// DeleteMenuGroup 删除菜单分组
|
||||
// @Summary 删除菜单分组
|
||||
// @Description 根据ID删除菜单分组
|
||||
// @Tags 菜单分组管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "菜单分组ID"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.Response
|
||||
// @Failure 404 {object} response.Response
|
||||
// @Failure 500 {object} response.Response
|
||||
// @Router /api/menu-groups/{id} [delete]
|
||||
func (c *MenuGroupController) DeleteMenuGroup(ctx *gin.Context) { |
||||
idStr := ctx.Param("id") |
||||
id, err := strconv.ParseUint(idStr, 10, 32) |
||||
if err != nil { |
||||
response.Error(ctx, http.StatusBadRequest, "请求参数错误", "ID格式错误") |
||||
return |
||||
} |
||||
|
||||
if err := c.menuGroupService.DeleteMenuGroup(uint(id)); err != nil { |
||||
response.Error(ctx, http.StatusInternalServerError, "删除菜单分组失败", err.Error()) |
||||
return |
||||
} |
||||
|
||||
response.Success(ctx, "删除菜单分组成功", nil) |
||||
} |
||||
|
||||
// BatchDeleteMenuGroups 批量删除菜单分组
|
||||
// @Summary 批量删除菜单分组
|
||||
// @Description 批量删除菜单分组
|
||||
// @Tags 菜单分组管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param ids body []uint true "菜单分组ID列表"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.Response
|
||||
// @Failure 500 {object} response.Response
|
||||
// @Router /api/menu-groups/batch-delete [post]
|
||||
func (c *MenuGroupController) BatchDeleteMenuGroups(ctx *gin.Context) { |
||||
var request struct { |
||||
IDs []uint `json:"ids" binding:"required"` |
||||
} |
||||
|
||||
if err := ctx.ShouldBindJSON(&request); err != nil { |
||||
response.Error(ctx, http.StatusBadRequest, "请求参数错误", err.Error()) |
||||
return |
||||
} |
||||
|
||||
if len(request.IDs) == 0 { |
||||
response.Error(ctx, http.StatusBadRequest, "请求参数错误", "ID列表不能为空") |
||||
return |
||||
} |
||||
|
||||
if err := c.menuGroupService.BatchDeleteMenuGroups(request.IDs); err != nil { |
||||
response.Error(ctx, http.StatusInternalServerError, "批量删除菜单分组失败", err.Error()) |
||||
return |
||||
} |
||||
|
||||
response.Success(ctx, "批量删除菜单分组成功", nil) |
||||
} |
||||
|
||||
// UpdateMenuGroupStatus 更新菜单分组状态
|
||||
// @Summary 更新菜单分组状态
|
||||
// @Description 更新菜单分组状态
|
||||
// @Tags 菜单分组管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "菜单分组ID"
|
||||
// @Param request body map[string]int true "状态信息" SchemaExample({"status": 1})
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.Response
|
||||
// @Failure 404 {object} response.Response
|
||||
// @Failure 500 {object} response.Response
|
||||
// @Router /api/menu-groups/{id}/status [put]
|
||||
func (c *MenuGroupController) UpdateMenuGroupStatus(ctx *gin.Context) { |
||||
idStr := ctx.Param("id") |
||||
id, err := strconv.ParseUint(idStr, 10, 32) |
||||
if err != nil { |
||||
response.Error(ctx, http.StatusBadRequest, "请求参数错误", "ID格式错误") |
||||
return |
||||
} |
||||
|
||||
var request struct { |
||||
Status int `json:"status" binding:"required"` |
||||
} |
||||
|
||||
if err := ctx.ShouldBindJSON(&request); err != nil { |
||||
response.Error(ctx, http.StatusBadRequest, "请求参数错误", err.Error()) |
||||
return |
||||
} |
||||
|
||||
if err := c.menuGroupService.UpdateMenuGroupStatus(uint(id), request.Status); err != nil { |
||||
response.Error(ctx, http.StatusInternalServerError, "更新菜单分组状态失败", err.Error()) |
||||
return |
||||
} |
||||
|
||||
response.Success(ctx, "更新菜单分组状态成功", nil) |
||||
} |
||||
|
||||
// UpdateMenuGroupSort 更新菜单分组排序
|
||||
// @Summary 更新菜单分组排序
|
||||
// @Description 更新菜单分组排序
|
||||
// @Tags 菜单分组管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "菜单分组ID"
|
||||
// @Param request body map[string]int true "排序信息" SchemaExample({"sort": 1})
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.Response
|
||||
// @Failure 404 {object} response.Response
|
||||
// @Failure 500 {object} response.Response
|
||||
// @Router /api/menu-groups/{id}/sort [put]
|
||||
func (c *MenuGroupController) UpdateMenuGroupSort(ctx *gin.Context) { |
||||
idStr := ctx.Param("id") |
||||
id, err := strconv.ParseUint(idStr, 10, 32) |
||||
if err != nil { |
||||
response.Error(ctx, http.StatusBadRequest, "请求参数错误", "ID格式错误") |
||||
return |
||||
} |
||||
|
||||
var request struct { |
||||
Sort int `json:"sort" binding:"required"` |
||||
} |
||||
|
||||
if err := ctx.ShouldBindJSON(&request); err != nil { |
||||
response.Error(ctx, http.StatusBadRequest, "请求参数错误", err.Error()) |
||||
return |
||||
} |
||||
|
||||
if err := c.menuGroupService.UpdateMenuGroupSort(uint(id), request.Sort); err != nil { |
||||
response.Error(ctx, http.StatusInternalServerError, "更新菜单分组排序失败", err.Error()) |
||||
return |
||||
} |
||||
|
||||
response.Success(ctx, "更新菜单分组排序成功", nil) |
||||
} |
||||
|
||||
// BatchUpdateMenuGroupSort 批量更新菜单分组排序
|
||||
// @Summary 批量更新菜单分组排序
|
||||
// @Description 批量更新菜单分组排序
|
||||
// @Tags 菜单分组管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param request body map[uint]int true "排序信息" SchemaExample({"1": 1, "2": 2})
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.Response
|
||||
// @Failure 500 {object} response.Response
|
||||
// @Router /api/menu-groups/batch-sort [put]
|
||||
func (c *MenuGroupController) BatchUpdateMenuGroupSort(ctx *gin.Context) { |
||||
var request map[uint]int |
||||
|
||||
if err := ctx.ShouldBindJSON(&request); err != nil { |
||||
response.Error(ctx, http.StatusBadRequest, "请求参数错误", err.Error()) |
||||
return |
||||
} |
||||
|
||||
if len(request) == 0 { |
||||
response.Error(ctx, http.StatusBadRequest, "请求参数错误", "排序数据不能为空") |
||||
return |
||||
} |
||||
|
||||
if err := c.menuGroupService.BatchUpdateMenuGroupSort(request); err != nil { |
||||
response.Error(ctx, http.StatusInternalServerError, "批量更新菜单分组排序失败", err.Error()) |
||||
return |
||||
} |
||||
|
||||
response.Success(ctx, "批量更新菜单分组排序成功", nil) |
||||
} |
||||
|
||||
// GetMenuGroupStats 获取菜单分组统计信息
|
||||
// @Summary 获取菜单分组统计信息
|
||||
// @Description 获取菜单分组统计信息
|
||||
// @Tags 菜单分组管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {object} response.Response{data=map[string]interface{}}
|
||||
// @Failure 500 {object} response.Response
|
||||
// @Router /api/menu-groups/stats [get]
|
||||
func (c *MenuGroupController) GetMenuGroupStats(ctx *gin.Context) { |
||||
stats, err := c.menuGroupService.GetMenuGroupStats() |
||||
if err != nil { |
||||
response.Error(ctx, http.StatusInternalServerError, "获取菜单分组统计信息失败", err.Error()) |
||||
return |
||||
} |
||||
|
||||
response.Success(ctx, "获取菜单分组统计信息成功", stats) |
||||
} |
@ -1,366 +0,0 @@
@@ -1,366 +0,0 @@
|
||||
package controller |
||||
|
||||
import ( |
||||
"net/http" |
||||
"strconv" |
||||
|
||||
"gofaster/internal/auth/model" |
||||
"gofaster/internal/auth/service" |
||||
"gofaster/internal/shared/response" |
||||
|
||||
"github.com/gin-gonic/gin" |
||||
"go.uber.org/zap" |
||||
) |
||||
|
||||
// MenuRouteController 菜单路由关联表控制器
|
||||
type MenuRouteController struct { |
||||
menuRouteService *service.MenuRouteService |
||||
log *zap.Logger |
||||
} |
||||
|
||||
// NewMenuRouteController 创建菜单路由关联表控制器
|
||||
func NewMenuRouteController(menuRouteService *service.MenuRouteService, log *zap.Logger) *MenuRouteController { |
||||
return &MenuRouteController{ |
||||
menuRouteService: menuRouteService, |
||||
log: log, |
||||
} |
||||
} |
||||
|
||||
// CreateMenuRoute 创建菜单路由关联
|
||||
// @Summary 创建菜单路由关联
|
||||
// @Description 创建菜单与路由的多对多关联关系
|
||||
// @Tags 菜单路由关联
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param menuRoute body model.MenuRoute true "菜单路由关联信息"
|
||||
// @Success 200 {object} response.Response{data=model.MenuRoute}
|
||||
// @Failure 400 {object} response.Response
|
||||
// @Router /api/menu-routes [post]
|
||||
func (c *MenuRouteController) CreateMenuRoute(ctx *gin.Context) { |
||||
var menuRoute model.MenuRoute |
||||
if err := ctx.ShouldBindJSON(&menuRoute); err != nil { |
||||
response.Error(ctx, http.StatusBadRequest, "请求参数错误", err.Error()) |
||||
return |
||||
} |
||||
|
||||
if err := c.menuRouteService.CreateMenuRoute(&menuRoute); err != nil { |
||||
response.Error(ctx, http.StatusInternalServerError, "创建菜单路由关联失败", err.Error()) |
||||
return |
||||
} |
||||
|
||||
response.Success(ctx, "创建菜单路由关联成功", menuRoute) |
||||
} |
||||
|
||||
// CreateMenuRoutes 批量创建菜单路由关联
|
||||
// @Summary 批量创建菜单路由关联
|
||||
// @Description 为指定菜单批量创建路由关联
|
||||
// @Tags 菜单路由关联
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param menuID path int true "菜单ID"
|
||||
// @Param routeMappingIDs body []uint true "路由映射ID列表"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.Response
|
||||
// @Router /api/menus/{menuID}/routes [post]
|
||||
func (c *MenuRouteController) CreateMenuRoutes(ctx *gin.Context) { |
||||
menuIDStr := ctx.Param("menuID") |
||||
menuID, err := strconv.ParseUint(menuIDStr, 10, 32) |
||||
if err != nil { |
||||
response.Error(ctx, http.StatusBadRequest, "菜单ID格式错误", err.Error()) |
||||
return |
||||
} |
||||
|
||||
var routeMappingIDs []uint |
||||
if err := ctx.ShouldBindJSON(&routeMappingIDs); err != nil { |
||||
response.Error(ctx, http.StatusBadRequest, "请求参数错误", err.Error()) |
||||
return |
||||
} |
||||
|
||||
if err := c.menuRouteService.CreateMenuRoutes(uint(menuID), routeMappingIDs); err != nil { |
||||
response.Error(ctx, http.StatusInternalServerError, "批量创建菜单路由关联失败", err.Error()) |
||||
return |
||||
} |
||||
|
||||
response.Success(ctx, "批量创建菜单路由关联成功", nil) |
||||
} |
||||
|
||||
// GetMenuRoutes 获取菜单的路由关联
|
||||
// @Summary 获取菜单的路由关联
|
||||
// @Description 获取指定菜单的所有路由关联
|
||||
// @Tags 菜单路由关联
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param menuID path int true "菜单ID"
|
||||
// @Success 200 {object} response.Response{data=[]model.MenuRoute}
|
||||
// @Failure 400 {object} response.Response
|
||||
// @Router /api/menus/{menuID}/routes [get]
|
||||
func (c *MenuRouteController) GetMenuRoutes(ctx *gin.Context) { |
||||
menuIDStr := ctx.Param("menuID") |
||||
menuID, err := strconv.ParseUint(menuIDStr, 10, 32) |
||||
if err != nil { |
||||
response.Error(ctx, http.StatusBadRequest, "菜单ID格式错误", err.Error()) |
||||
return |
||||
} |
||||
|
||||
menuRoutes, err := c.menuRouteService.GetMenuRoutes(uint(menuID)) |
||||
if err != nil { |
||||
response.Error(ctx, http.StatusInternalServerError, "获取菜单路由关联失败", err.Error()) |
||||
return |
||||
} |
||||
|
||||
response.Success(ctx, "获取菜单路由关联成功", menuRoutes) |
||||
} |
||||
|
||||
// GetRouteMenus 获取路由的菜单关联
|
||||
// @Summary 获取路由的菜单关联
|
||||
// @Description 获取指定路由的所有菜单关联
|
||||
// @Tags 菜单路由关联
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param routeMappingID path int true "路由映射ID"
|
||||
// @Success 200 {object} response.Response{data=[]model.MenuRoute}
|
||||
// @Failure 400 {object} response.Response
|
||||
// @Router /api/route-mappings/{routeMappingID}/menus [get]
|
||||
func (c *MenuRouteController) GetRouteMenus(ctx *gin.Context) { |
||||
routeMappingIDStr := ctx.Param("routeMappingID") |
||||
routeMappingID, err := strconv.ParseUint(routeMappingIDStr, 10, 32) |
||||
if err != nil { |
||||
response.Error(ctx, http.StatusBadRequest, "路由映射ID格式错误", err.Error()) |
||||
return |
||||
} |
||||
|
||||
menuRoutes, err := c.menuRouteService.GetRouteMenus(uint(routeMappingID)) |
||||
if err != nil { |
||||
response.Error(ctx, http.StatusInternalServerError, "获取路由菜单关联失败", err.Error()) |
||||
return |
||||
} |
||||
|
||||
response.Success(ctx, "获取路由菜单关联成功", menuRoutes) |
||||
} |
||||
|
||||
// GetMenuWithRoutes 获取菜单及其关联的路由信息
|
||||
// @Summary 获取菜单及其关联的路由信息
|
||||
// @Description 获取菜单详细信息及其关联的所有路由
|
||||
// @Tags 菜单路由关联
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param menuID path int true "菜单ID"
|
||||
// @Success 200 {object} response.Response{data=map[string]interface{}}
|
||||
// @Failure 400 {object} response.Response
|
||||
// @Router /api/menus/{menuID}/routes/detail [get]
|
||||
func (c *MenuRouteController) GetMenuWithRoutes(ctx *gin.Context) { |
||||
menuIDStr := ctx.Param("menuID") |
||||
menuID, err := strconv.ParseUint(menuIDStr, 10, 32) |
||||
if err != nil { |
||||
response.Error(ctx, http.StatusBadRequest, "菜单ID格式错误", err.Error()) |
||||
return |
||||
} |
||||
|
||||
menu, routes, err := c.menuRouteService.GetMenuWithRoutes(uint(menuID)) |
||||
if err != nil { |
||||
response.Error(ctx, http.StatusInternalServerError, "获取菜单及路由信息失败", err.Error()) |
||||
return |
||||
} |
||||
|
||||
result := map[string]interface{}{ |
||||
"menu": menu, |
||||
"routes": routes, |
||||
} |
||||
|
||||
response.Success(ctx, "获取菜单及路由信息成功", result) |
||||
} |
||||
|
||||
// GetRouteWithMenus 获取路由及其关联的菜单信息
|
||||
// @Summary 获取路由及其关联的菜单信息
|
||||
// @Description 获取路由详细信息及其关联的所有菜单
|
||||
// @Tags 菜单路由关联
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param routeMappingID path int true "路由映射ID"
|
||||
// @Success 200 {object} response.Response{data=map[string]interface{}}
|
||||
// @Failure 400 {object} response.Response
|
||||
// @Router /api/route-mappings/{routeMappingID}/menus/detail [get]
|
||||
func (c *MenuRouteController) GetRouteWithMenus(ctx *gin.Context) { |
||||
routeMappingIDStr := ctx.Param("routeMappingID") |
||||
routeMappingID, err := strconv.ParseUint(routeMappingIDStr, 10, 32) |
||||
if err != nil { |
||||
response.Error(ctx, http.StatusBadRequest, "路由映射ID格式错误", err.Error()) |
||||
return |
||||
} |
||||
|
||||
route, menus, err := c.menuRouteService.GetRouteWithMenus(uint(routeMappingID)) |
||||
if err != nil { |
||||
response.Error(ctx, http.StatusInternalServerError, "获取路由及菜单信息失败", err.Error()) |
||||
return |
||||
} |
||||
|
||||
result := map[string]interface{}{ |
||||
"route": route, |
||||
"menus": menus, |
||||
} |
||||
|
||||
response.Success(ctx, "获取路由及菜单信息成功", result) |
||||
} |
||||
|
||||
// UpdateMenuRoute 更新菜单路由关联
|
||||
// @Summary 更新菜单路由关联
|
||||
// @Description 更新菜单路由关联信息
|
||||
// @Tags 菜单路由关联
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "关联ID"
|
||||
// @Param menuRoute body model.MenuRoute true "菜单路由关联信息"
|
||||
// @Success 200 {object} response.Response{data=model.MenuRoute}
|
||||
// @Failure 400 {object} response.Response
|
||||
// @Router /api/menu-routes/{id} [put]
|
||||
func (c *MenuRouteController) UpdateMenuRoute(ctx *gin.Context) { |
||||
idStr := ctx.Param("id") |
||||
id, err := strconv.ParseUint(idStr, 10, 32) |
||||
if err != nil { |
||||
response.Error(ctx, http.StatusBadRequest, "ID格式错误", err.Error()) |
||||
return |
||||
} |
||||
|
||||
var menuRoute model.MenuRoute |
||||
if err := ctx.ShouldBindJSON(&menuRoute); err != nil { |
||||
response.Error(ctx, http.StatusBadRequest, "请求参数错误", err.Error()) |
||||
return |
||||
} |
||||
|
||||
menuRoute.ID = uint(id) |
||||
if err := c.menuRouteService.UpdateMenuRoute(&menuRoute); err != nil { |
||||
response.Error(ctx, http.StatusInternalServerError, "更新菜单路由关联失败", err.Error()) |
||||
return |
||||
} |
||||
|
||||
response.Success(ctx, "更新菜单路由关联成功", menuRoute) |
||||
} |
||||
|
||||
// DeleteMenuRoute 删除菜单路由关联
|
||||
// @Summary 删除菜单路由关联
|
||||
// @Description 删除指定的菜单路由关联
|
||||
// @Tags 菜单路由关联
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "关联ID"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.Response
|
||||
// @Router /api/menu-routes/{id} [delete]
|
||||
func (c *MenuRouteController) DeleteMenuRoute(ctx *gin.Context) { |
||||
idStr := ctx.Param("id") |
||||
id, err := strconv.ParseUint(idStr, 10, 32) |
||||
if err != nil { |
||||
response.Error(ctx, http.StatusBadRequest, "ID格式错误", err.Error()) |
||||
return |
||||
} |
||||
|
||||
if err := c.menuRouteService.DeleteMenuRoute(uint(id)); err != nil { |
||||
response.Error(ctx, http.StatusInternalServerError, "删除菜单路由关联失败", err.Error()) |
||||
return |
||||
} |
||||
|
||||
response.Success(ctx, "删除菜单路由关联成功", nil) |
||||
} |
||||
|
||||
// DeleteMenuRoutes 删除菜单的所有路由关联
|
||||
// @Summary 删除菜单的所有路由关联
|
||||
// @Description 删除指定菜单的所有路由关联
|
||||
// @Tags 菜单路由关联
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param menuID path int true "菜单ID"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.Response
|
||||
// @Router /api/menus/{menuID}/routes [delete]
|
||||
func (c *MenuRouteController) DeleteMenuRoutes(ctx *gin.Context) { |
||||
menuIDStr := ctx.Param("menuID") |
||||
menuID, err := strconv.ParseUint(menuIDStr, 10, 32) |
||||
if err != nil { |
||||
response.Error(ctx, http.StatusBadRequest, "菜单ID格式错误", err.Error()) |
||||
return |
||||
} |
||||
|
||||
if err := c.menuRouteService.DeleteMenuRoutes(uint(menuID)); err != nil { |
||||
response.Error(ctx, http.StatusInternalServerError, "删除菜单路由关联失败", err.Error()) |
||||
return |
||||
} |
||||
|
||||
response.Success(ctx, "删除菜单路由关联成功", nil) |
||||
} |
||||
|
||||
// SyncMenuRoutes 同步菜单路由关联
|
||||
// @Summary 同步菜单路由关联
|
||||
// @Description 同步菜单的路由关联(删除现有关联并创建新关联)
|
||||
// @Tags 菜单路由关联
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param menuID path int true "菜单ID"
|
||||
// @Param routeMappingIDs body []uint true "路由映射ID列表"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.Response
|
||||
// @Router /api/menus/{menuID}/routes/sync [post]
|
||||
func (c *MenuRouteController) SyncMenuRoutes(ctx *gin.Context) { |
||||
menuIDStr := ctx.Param("menuID") |
||||
menuID, err := strconv.ParseUint(menuIDStr, 10, 32) |
||||
if err != nil { |
||||
response.Error(ctx, http.StatusBadRequest, "菜单ID格式错误", err.Error()) |
||||
return |
||||
} |
||||
|
||||
var routeMappingIDs []uint |
||||
if err := ctx.ShouldBindJSON(&routeMappingIDs); err != nil { |
||||
response.Error(ctx, http.StatusBadRequest, "请求参数错误", err.Error()) |
||||
return |
||||
} |
||||
|
||||
if err := c.menuRouteService.SyncMenuRoutes(uint(menuID), routeMappingIDs); err != nil { |
||||
response.Error(ctx, http.StatusInternalServerError, "同步菜单路由关联失败", err.Error()) |
||||
return |
||||
} |
||||
|
||||
response.Success(ctx, "同步菜单路由关联成功", nil) |
||||
} |
||||
|
||||
// ListMenuRoutes 获取菜单路由关联列表
|
||||
// @Summary 获取菜单路由关联列表
|
||||
// @Description 分页获取菜单路由关联列表
|
||||
// @Tags 菜单路由关联
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param page query int false "页码" default(1)
|
||||
// @Param pageSize query int false "每页数量" default(10)
|
||||
// @Success 200 {object} response.Response{data=map[string]interface{}}
|
||||
// @Failure 400 {object} response.Response
|
||||
// @Router /api/menu-routes [get]
|
||||
func (c *MenuRouteController) ListMenuRoutes(ctx *gin.Context) { |
||||
pageStr := ctx.DefaultQuery("page", "1") |
||||
pageSizeStr := ctx.DefaultQuery("pageSize", "10") |
||||
|
||||
page, err := strconv.Atoi(pageStr) |
||||
if err != nil { |
||||
response.Error(ctx, http.StatusBadRequest, "页码格式错误", err.Error()) |
||||
return |
||||
} |
||||
|
||||
pageSize, err := strconv.Atoi(pageSizeStr) |
||||
if err != nil { |
||||
response.Error(ctx, http.StatusBadRequest, "每页数量格式错误", err.Error()) |
||||
return |
||||
} |
||||
|
||||
menuRoutes, total, err := c.menuRouteService.ListMenuRoutes(page, pageSize) |
||||
if err != nil { |
||||
response.Error(ctx, http.StatusInternalServerError, "获取菜单路由关联列表失败", err.Error()) |
||||
return |
||||
} |
||||
|
||||
result := map[string]interface{}{ |
||||
"list": menuRoutes, |
||||
"total": total, |
||||
"page": page, |
||||
"pageSize": pageSize, |
||||
"pageCount": (total + int64(pageSize) - 1) / int64(pageSize), |
||||
} |
||||
|
||||
response.Success(ctx, "获取菜单路由关联列表成功", result) |
||||
} |
@ -1,27 +0,0 @@
@@ -1,27 +0,0 @@
|
||||
package model |
||||
|
||||
import ( |
||||
"gofaster/internal/shared/model" |
||||
) |
||||
|
||||
// Menu 菜单模型
|
||||
type Menu struct { |
||||
model.BaseModel |
||||
Name string `json:"name"` // 菜单名称
|
||||
Path string `json:"path"` // 前台路由路径
|
||||
Component string `json:"component"` // Vue组件路径
|
||||
Icon string `json:"icon"` // 图标
|
||||
Sort int `json:"sort"` // 排序
|
||||
ParentID *uint `json:"parent_id"` // 父菜单ID
|
||||
Level int `json:"level"` // 菜单层级
|
||||
IsVisible bool `json:"is_visible"` // 是否可见
|
||||
IsExternal bool `json:"is_external"` // 是否外部链接
|
||||
Meta string `json:"meta"` // 元数据(JSON)
|
||||
Module string `json:"module"` // 所属模块
|
||||
Status int `gorm:"default:1" json:"status"` // 状态:1-启用,0-禁用
|
||||
} |
||||
|
||||
// TableName 指定表名
|
||||
func (Menu) TableName() string { |
||||
return "menus" |
||||
} |
@ -0,0 +1,20 @@
@@ -0,0 +1,20 @@
|
||||
package model |
||||
|
||||
import ( |
||||
"time" |
||||
) |
||||
|
||||
// MenuGroup 菜单分组模型
|
||||
type MenuGroup struct { |
||||
ID uint `gorm:"primarykey" json:"id"` |
||||
UpdatedAt time.Time `json:"updated_at"` |
||||
Name string `json:"name"` // 分组名称
|
||||
Description string `json:"description"` // 分组描述
|
||||
Sort int `gorm:"default:0" json:"sort"` // 排序
|
||||
Status int `gorm:"default:1" json:"status"` // 状态:1-启用,0-禁用
|
||||
} |
||||
|
||||
// TableName 指定表名
|
||||
func (MenuGroup) TableName() string { |
||||
return "menu_groups" |
||||
} |
@ -1,20 +0,0 @@
@@ -1,20 +0,0 @@
|
||||
package model |
||||
|
||||
import ( |
||||
"gofaster/internal/shared/model" |
||||
) |
||||
|
||||
// MenuRoute 菜单路由关联表(多对多关系)
|
||||
type MenuRoute struct { |
||||
model.BaseModel |
||||
MenuID uint `gorm:"primaryKey;index" json:"menu_id"` // 菜单ID
|
||||
RouteMappingID uint `gorm:"primaryKey;index" json:"route_mapping_id"` // 路由映射ID
|
||||
Sort int `gorm:"default:0" json:"sort"` // 排序
|
||||
IsDefault bool `gorm:"default:false" json:"is_default"` // 是否为默认路由
|
||||
Status int `gorm:"default:1" json:"status"` // 状态:1-启用,0-禁用
|
||||
} |
||||
|
||||
// TableName 指定表名
|
||||
func (MenuRoute) TableName() string { |
||||
return "menu_routes" |
||||
} |
@ -1,22 +0,0 @@
@@ -1,22 +0,0 @@
|
||||
package model |
||||
|
||||
import ( |
||||
"time" |
||||
) |
||||
|
||||
// RouteMapping 路由映射模型
|
||||
type RouteMapping struct { |
||||
ID uint `gorm:"primarykey" json:"id"` |
||||
UpdatedAt time.Time `json:"updated_at"` |
||||
BackendRoute string `json:"backend_route"` // 后台API路径
|
||||
HTTPMethod string `json:"http_method"` // HTTP方法
|
||||
ResourceID *uint `json:"resource_id"` // 关联的资源ID
|
||||
Module string `json:"module"` // 所属模块
|
||||
Description string `json:"description"` // 描述
|
||||
Status int `gorm:"default:1" json:"status"` // 状态:1-启用,0-禁用
|
||||
} |
||||
|
||||
// TableName 指定表名
|
||||
func (RouteMapping) TableName() string { |
||||
return "route_mappings" |
||||
} |
@ -0,0 +1,127 @@
@@ -0,0 +1,127 @@
|
||||
package repository |
||||
|
||||
import ( |
||||
"gofaster/internal/auth/model" |
||||
|
||||
"gorm.io/gorm" |
||||
) |
||||
|
||||
// MenuGroupRepository 菜单分组仓库
|
||||
type MenuGroupRepository struct { |
||||
db *gorm.DB |
||||
} |
||||
|
||||
// NewMenuGroupRepository 创建菜单分组仓库实例
|
||||
func NewMenuGroupRepository(db *gorm.DB) *MenuGroupRepository { |
||||
return &MenuGroupRepository{db: db} |
||||
} |
||||
|
||||
// Create 创建菜单分组
|
||||
func (r *MenuGroupRepository) Create(menuGroup *model.MenuGroup) error { |
||||
return r.db.Create(menuGroup).Error |
||||
} |
||||
|
||||
// FindByID 根据ID查找菜单分组
|
||||
func (r *MenuGroupRepository) FindByID(id uint) (*model.MenuGroup, error) { |
||||
var menuGroup model.MenuGroup |
||||
err := r.db.Where("id = ?", id).First(&menuGroup).Error |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
return &menuGroup, nil |
||||
} |
||||
|
||||
// FindByName 根据名称查找菜单分组
|
||||
func (r *MenuGroupRepository) FindByName(name string) (*model.MenuGroup, error) { |
||||
var menuGroup model.MenuGroup |
||||
err := r.db.Where("name = ?", name).First(&menuGroup).Error |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
return &menuGroup, nil |
||||
} |
||||
|
||||
// List 获取菜单分组列表
|
||||
func (r *MenuGroupRepository) List() ([]*model.MenuGroup, error) { |
||||
var menuGroups []*model.MenuGroup |
||||
err := r.db.Order("sort ASC, id ASC").Find(&menuGroups).Error |
||||
return menuGroups, err |
||||
} |
||||
|
||||
// ListByStatus 根据状态获取菜单分组列表
|
||||
func (r *MenuGroupRepository) ListByStatus(status int) ([]*model.MenuGroup, error) { |
||||
var menuGroups []*model.MenuGroup |
||||
err := r.db.Where("status = ?", status).Order("sort ASC, id ASC").Find(&menuGroups).Error |
||||
return menuGroups, err |
||||
} |
||||
|
||||
// Update 更新菜单分组
|
||||
func (r *MenuGroupRepository) Update(menuGroup *model.MenuGroup) error { |
||||
return r.db.Save(menuGroup).Error |
||||
} |
||||
|
||||
// Delete 删除菜单分组
|
||||
func (r *MenuGroupRepository) Delete(id uint) error { |
||||
return r.db.Delete(&model.MenuGroup{}, id).Error |
||||
} |
||||
|
||||
// BatchDelete 批量删除菜单分组
|
||||
func (r *MenuGroupRepository) BatchDelete(ids []uint) error { |
||||
return r.db.Where("id IN ?", ids).Delete(&model.MenuGroup{}).Error |
||||
} |
||||
|
||||
// UpdateStatus 更新菜单分组状态
|
||||
func (r *MenuGroupRepository) UpdateStatus(id uint, status int) error { |
||||
return r.db.Model(&model.MenuGroup{}).Where("id = ?", id).Update("status", status).Error |
||||
} |
||||
|
||||
// UpdateSort 更新菜单分组排序
|
||||
func (r *MenuGroupRepository) UpdateSort(id uint, sort int) error { |
||||
return r.db.Model(&model.MenuGroup{}).Where("id = ?", id).Update("sort", sort).Error |
||||
} |
||||
|
||||
// BatchUpdateSort 批量更新菜单分组排序
|
||||
func (r *MenuGroupRepository) BatchUpdateSort(sorts map[uint]int) error { |
||||
for id, sort := range sorts { |
||||
if err := r.UpdateSort(id, sort); err != nil { |
||||
return err |
||||
} |
||||
} |
||||
return nil |
||||
} |
||||
|
||||
// GetStats 获取菜单分组统计信息
|
||||
func (r *MenuGroupRepository) GetStats() (map[string]interface{}, error) { |
||||
var total int64 |
||||
var statusStats []struct { |
||||
Status int `json:"status"` |
||||
Count int64 `json:"count"` |
||||
} |
||||
|
||||
if err := r.db.Model(&model.MenuGroup{}).Count(&total).Error; err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
if err := r.db.Model(&model.MenuGroup{}). |
||||
Select("status, count(*) as count"). |
||||
Group("status"). |
||||
Scan(&statusStats).Error; err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
return map[string]interface{}{ |
||||
"total": total, |
||||
"status_stats": statusStats, |
||||
}, nil |
||||
} |
||||
|
||||
// ExistsByName 检查名称是否存在(排除指定ID)
|
||||
func (r *MenuGroupRepository) ExistsByName(name string, excludeID ...uint) bool { |
||||
query := r.db.Model(&model.MenuGroup{}).Where("name = ?", name) |
||||
if len(excludeID) > 0 && excludeID[0] > 0 { |
||||
query = query.Where("id != ?", excludeID[0]) |
||||
} |
||||
var count int64 |
||||
query.Count(&count) |
||||
return count > 0 |
||||
} |
@ -1,89 +0,0 @@
@@ -1,89 +0,0 @@
|
||||
package repository |
||||
|
||||
import ( |
||||
"gofaster/internal/auth/model" |
||||
"gofaster/internal/shared/repository" |
||||
|
||||
"gorm.io/gorm" |
||||
) |
||||
|
||||
// MenuRepository 菜单仓库
|
||||
type MenuRepository struct { |
||||
repository.BaseRepo |
||||
} |
||||
|
||||
// NewMenuRepository 创建菜单仓库实例
|
||||
func NewMenuRepository(db *gorm.DB) *MenuRepository { |
||||
return &MenuRepository{ |
||||
BaseRepo: *repository.NewBaseRepo(db), |
||||
} |
||||
} |
||||
|
||||
// Create 创建菜单
|
||||
func (r *MenuRepository) Create(menu *model.Menu) error { |
||||
return r.DB().Create(menu).Error |
||||
} |
||||
|
||||
// Update 更新菜单
|
||||
func (r *MenuRepository) Update(menu *model.Menu) error { |
||||
return r.DB().Save(menu).Error |
||||
} |
||||
|
||||
// Delete 删除菜单
|
||||
func (r *MenuRepository) Delete(id uint) error { |
||||
return r.DB().Delete(&model.Menu{}, id).Error |
||||
} |
||||
|
||||
// FindByID 根据ID查找菜单
|
||||
func (r *MenuRepository) FindByID(id uint) (*model.Menu, error) { |
||||
var menu model.Menu |
||||
err := r.DB().First(&menu, id).Error |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
return &menu, nil |
||||
} |
||||
|
||||
// FindByPath 根据路径查找菜单
|
||||
func (r *MenuRepository) FindByPath(path string) (*model.Menu, error) { |
||||
var menu model.Menu |
||||
err := r.DB().Where("path = ?", path).First(&menu).Error |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
return &menu, nil |
||||
} |
||||
|
||||
// FindAll 查找所有菜单
|
||||
func (r *MenuRepository) FindAll() ([]model.Menu, error) { |
||||
var menus []model.Menu |
||||
err := r.DB().Order("sort ASC, id ASC").Find(&menus).Error |
||||
return menus, err |
||||
} |
||||
|
||||
// FindByModule 根据模块查找菜单
|
||||
func (r *MenuRepository) FindByModule(module string) ([]model.Menu, error) { |
||||
var menus []model.Menu |
||||
err := r.DB().Where("module = ?", module).Order("sort ASC, id ASC").Find(&menus).Error |
||||
return menus, err |
||||
} |
||||
|
||||
// FindByParentID 根据父ID查找子菜单
|
||||
func (r *MenuRepository) FindByParentID(parentID *uint) ([]model.Menu, error) { |
||||
var menus []model.Menu |
||||
query := r.DB() |
||||
if parentID == nil { |
||||
query = query.Where("parent_id IS NULL") |
||||
} else { |
||||
query = query.Where("parent_id = ?", *parentID) |
||||
} |
||||
err := query.Order("sort ASC, id ASC").Find(&menus).Error |
||||
return menus, err |
||||
} |
||||
|
||||
// FindTree 查找菜单树
|
||||
func (r *MenuRepository) FindTree() ([]model.Menu, error) { |
||||
var menus []model.Menu |
||||
err := r.DB().Order("sort ASC, id ASC").Find(&menus).Error |
||||
return menus, err |
||||
} |
@ -1,142 +0,0 @@
@@ -1,142 +0,0 @@
|
||||
package repository |
||||
|
||||
import ( |
||||
"gofaster/internal/auth/model" |
||||
|
||||
"gorm.io/gorm" |
||||
) |
||||
|
||||
// MenuRouteRepository 菜单路由关联表仓储
|
||||
type MenuRouteRepository struct { |
||||
db *gorm.DB |
||||
} |
||||
|
||||
// NewMenuRouteRepository 创建菜单路由关联表仓储
|
||||
func NewMenuRouteRepository(db *gorm.DB) *MenuRouteRepository { |
||||
return &MenuRouteRepository{db: db} |
||||
} |
||||
|
||||
// Create 创建菜单路由关联
|
||||
func (r *MenuRouteRepository) Create(menuRoute *model.MenuRoute) error { |
||||
return r.db.Create(menuRoute).Error |
||||
} |
||||
|
||||
// CreateBatch 批量创建菜单路由关联
|
||||
func (r *MenuRouteRepository) CreateBatch(menuRoutes []*model.MenuRoute) error { |
||||
return r.db.CreateInBatches(menuRoutes, 100).Error |
||||
} |
||||
|
||||
// GetByID 根据ID获取菜单路由关联
|
||||
func (r *MenuRouteRepository) GetByID(id uint) (*model.MenuRoute, error) { |
||||
var menuRoute model.MenuRoute |
||||
err := r.db.Where("id = ?", id).First(&menuRoute).Error |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
return &menuRoute, nil |
||||
} |
||||
|
||||
// GetByMenuAndRoute 根据菜单ID和路由ID获取关联
|
||||
func (r *MenuRouteRepository) GetByMenuAndRoute(menuID, routeMappingID uint) (*model.MenuRoute, error) { |
||||
var menuRoute model.MenuRoute |
||||
err := r.db.Where("menu_id = ? AND route_mapping_id = ?", menuID, routeMappingID).First(&menuRoute).Error |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
return &menuRoute, nil |
||||
} |
||||
|
||||
// GetByMenuID 根据菜单ID获取所有关联的路由
|
||||
func (r *MenuRouteRepository) GetByMenuID(menuID uint) ([]*model.MenuRoute, error) { |
||||
var menuRoutes []*model.MenuRoute |
||||
err := r.db.Where("menu_id = ?", menuID).Order("sort ASC").Find(&menuRoutes).Error |
||||
return menuRoutes, err |
||||
} |
||||
|
||||
// GetByRouteMappingID 根据路由映射ID获取所有关联的菜单
|
||||
func (r *MenuRouteRepository) GetByRouteMappingID(routeMappingID uint) ([]*model.MenuRoute, error) { |
||||
var menuRoutes []*model.MenuRoute |
||||
err := r.db.Where("route_mapping_id = ?", routeMappingID).Order("sort ASC").Find(&menuRoutes).Error |
||||
return menuRoutes, err |
||||
} |
||||
|
||||
// List 获取菜单路由关联列表
|
||||
func (r *MenuRouteRepository) List(page, pageSize int) ([]*model.MenuRoute, int64, error) { |
||||
var menuRoutes []*model.MenuRoute |
||||
var total int64 |
||||
|
||||
// 获取总数
|
||||
if err := r.db.Model(&model.MenuRoute{}).Count(&total).Error; err != nil { |
||||
return nil, 0, err |
||||
} |
||||
|
||||
// 获取分页数据
|
||||
offset := (page - 1) * pageSize |
||||
err := r.db.Offset(offset).Limit(pageSize).Order("created_at DESC").Find(&menuRoutes).Error |
||||
return menuRoutes, total, err |
||||
} |
||||
|
||||
// Update 更新菜单路由关联
|
||||
func (r *MenuRouteRepository) Update(menuRoute *model.MenuRoute) error { |
||||
return r.db.Save(menuRoute).Error |
||||
} |
||||
|
||||
// Delete 删除菜单路由关联
|
||||
func (r *MenuRouteRepository) Delete(id uint) error { |
||||
return r.db.Delete(&model.MenuRoute{}, id).Error |
||||
} |
||||
|
||||
// DeleteByMenuID 根据菜单ID删除所有关联
|
||||
func (r *MenuRouteRepository) DeleteByMenuID(menuID uint) error { |
||||
return r.db.Where("menu_id = ?", menuID).Delete(&model.MenuRoute{}).Error |
||||
} |
||||
|
||||
// DeleteByRouteMappingID 根据路由映射ID删除所有关联
|
||||
func (r *MenuRouteRepository) DeleteByRouteMappingID(routeMappingID uint) error { |
||||
return r.db.Where("route_mapping_id = ?", routeMappingID).Delete(&model.MenuRoute{}).Error |
||||
} |
||||
|
||||
// DeleteByMenuAndRoute 根据菜单ID和路由ID删除关联
|
||||
func (r *MenuRouteRepository) DeleteByMenuAndRoute(menuID, routeMappingID uint) error { |
||||
return r.db.Where("menu_id = ? AND route_mapping_id = ?", menuID, routeMappingID).Delete(&model.MenuRoute{}).Error |
||||
} |
||||
|
||||
// GetMenuWithRoutes 获取菜单及其关联的路由信息
|
||||
func (r *MenuRouteRepository) GetMenuWithRoutes(menuID uint) (*model.Menu, []*model.RouteMapping, error) { |
||||
var menu model.Menu |
||||
var routeMappings []*model.RouteMapping |
||||
|
||||
// 获取菜单信息
|
||||
if err := r.db.First(&menu, menuID).Error; err != nil { |
||||
return nil, nil, err |
||||
} |
||||
|
||||
// 获取关联的路由映射
|
||||
err := r.db.Table("route_mappings"). |
||||
Joins("JOIN menu_routes ON route_mappings.id = menu_routes.route_mapping_id"). |
||||
Where("menu_routes.menu_id = ?", menuID). |
||||
Order("menu_routes.sort ASC"). |
||||
Find(&routeMappings).Error |
||||
|
||||
return &menu, routeMappings, err |
||||
} |
||||
|
||||
// GetRouteWithMenus 获取路由及其关联的菜单信息
|
||||
func (r *MenuRouteRepository) GetRouteWithMenus(routeMappingID uint) (*model.RouteMapping, []*model.Menu, error) { |
||||
var routeMapping model.RouteMapping |
||||
var menus []*model.Menu |
||||
|
||||
// 获取路由映射信息
|
||||
if err := r.db.First(&routeMapping, routeMappingID).Error; err != nil { |
||||
return nil, nil, err |
||||
} |
||||
|
||||
// 获取关联的菜单
|
||||
err := r.db.Table("menus"). |
||||
Joins("JOIN menu_routes ON menus.id = menu_routes.menu_id"). |
||||
Where("menu_routes.route_mapping_id = ?", routeMappingID). |
||||
Order("menu_routes.sort ASC"). |
||||
Find(&menus).Error |
||||
|
||||
return &routeMapping, menus, err |
||||
} |
@ -1,108 +0,0 @@
@@ -1,108 +0,0 @@
|
||||
package repository |
||||
|
||||
import ( |
||||
"gofaster/internal/auth/model" |
||||
"gofaster/internal/shared/repository" |
||||
|
||||
"gorm.io/gorm" |
||||
) |
||||
|
||||
// RouteMappingRepository 路由映射仓库
|
||||
type RouteMappingRepository struct { |
||||
repository.BaseRepo |
||||
} |
||||
|
||||
// NewRouteMappingRepository 创建路由映射仓库实例
|
||||
func NewRouteMappingRepository(db *gorm.DB) *RouteMappingRepository { |
||||
return &RouteMappingRepository{ |
||||
BaseRepo: *repository.NewBaseRepo(db), |
||||
} |
||||
} |
||||
|
||||
// Create 创建路由映射
|
||||
func (r *RouteMappingRepository) Create(mapping *model.RouteMapping) error { |
||||
return r.DB().Create(mapping).Error |
||||
} |
||||
|
||||
// Update 更新路由映射
|
||||
func (r *RouteMappingRepository) Update(mapping *model.RouteMapping) error { |
||||
return r.DB().Save(mapping).Error |
||||
} |
||||
|
||||
// Delete 删除路由映射
|
||||
func (r *RouteMappingRepository) Delete(id uint) error { |
||||
return r.DB().Delete(&model.RouteMapping{}, id).Error |
||||
} |
||||
|
||||
// FindByID 根据ID查找路由映射
|
||||
func (r *RouteMappingRepository) FindByID(id uint) (*model.RouteMapping, error) { |
||||
var mapping model.RouteMapping |
||||
err := r.DB().First(&mapping, id).Error |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
return &mapping, nil |
||||
} |
||||
|
||||
// FindByBackendRoute 根据后台路由查找映射
|
||||
func (r *RouteMappingRepository) FindByBackendRoute(backendRoute, httpMethod string) (*model.RouteMapping, error) { |
||||
var mapping model.RouteMapping |
||||
err := r.DB().Where("backend_route = ? AND http_method = ?", backendRoute, httpMethod).First(&mapping).Error |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
return &mapping, nil |
||||
} |
||||
|
||||
// FindByFrontendRoute 根据前台路由查找映射
|
||||
func (r *RouteMappingRepository) FindByFrontendRoute(frontendRoute string) ([]model.RouteMapping, error) { |
||||
var mappings []model.RouteMapping |
||||
err := r.DB().Where("frontend_route = ?", frontendRoute).Find(&mappings).Error |
||||
return mappings, err |
||||
} |
||||
|
||||
// FindAll 查找所有路由映射
|
||||
func (r *RouteMappingRepository) FindAll() ([]model.RouteMapping, error) { |
||||
var mappings []model.RouteMapping |
||||
err := r.DB().Order("id ASC").Find(&mappings).Error |
||||
return mappings, err |
||||
} |
||||
|
||||
// FindByModule 根据模块查找路由映射
|
||||
func (r *RouteMappingRepository) FindByModule(module string) ([]model.RouteMapping, error) { |
||||
var mappings []model.RouteMapping |
||||
err := r.DB().Where("module = ?", module).Order("id ASC").Find(&mappings).Error |
||||
return mappings, err |
||||
} |
||||
|
||||
// FindByResourceID 根据资源ID查找路由映射
|
||||
func (r *RouteMappingRepository) FindByResourceID(resourceID uint) ([]model.RouteMapping, error) { |
||||
var mappings []model.RouteMapping |
||||
err := r.DB().Where("resource_id = ?", resourceID).Find(&mappings).Error |
||||
return mappings, err |
||||
} |
||||
|
||||
// FindByMenuID 根据菜单ID查找路由映射
|
||||
func (r *RouteMappingRepository) FindByMenuID(menuID uint) ([]model.RouteMapping, error) { |
||||
var mappings []model.RouteMapping |
||||
err := r.DB().Where("menu_id = ?", menuID).Find(&mappings).Error |
||||
return mappings, err |
||||
} |
||||
|
||||
// CreateOrUpdate 创建或更新路由映射(用于增量同步)
|
||||
func (r *RouteMappingRepository) CreateOrUpdate(mapping *model.RouteMapping) error { |
||||
var existing model.RouteMapping |
||||
err := r.DB().Where("backend_route = ? AND http_method = ?", mapping.BackendRoute, mapping.HTTPMethod).First(&existing).Error |
||||
|
||||
if err != nil { |
||||
if err == gorm.ErrRecordNotFound { |
||||
// 不存在则创建
|
||||
return r.Create(mapping) |
||||
} |
||||
return err |
||||
} |
||||
|
||||
// 存在则更新
|
||||
mapping.ID = existing.ID |
||||
return r.Update(mapping) |
||||
} |
@ -0,0 +1,45 @@
@@ -0,0 +1,45 @@
|
||||
package routes |
||||
|
||||
import ( |
||||
"gofaster/internal/auth/controller" |
||||
"gofaster/internal/auth/repository" |
||||
"gofaster/internal/auth/service" |
||||
"gofaster/internal/shared/middleware" |
||||
|
||||
"github.com/gin-gonic/gin" |
||||
"go.uber.org/zap" |
||||
"gorm.io/gorm" |
||||
) |
||||
|
||||
func RegisterMenuGroupRoutes(router *gin.RouterGroup, db *gorm.DB, logger *zap.Logger) { |
||||
// 初始化依赖
|
||||
menuGroupRepo := repository.NewMenuGroupRepository(db) |
||||
menuGroupService := service.NewMenuGroupService(menuGroupRepo, logger) |
||||
menuGroupController := controller.NewMenuGroupController(menuGroupService, logger) |
||||
|
||||
// 菜单分组管理路由组
|
||||
menuGroupGroup := router.Group("/menu-groups") |
||||
{ |
||||
// 需要权限验证的路由
|
||||
menuGroupGroup.Use(middleware.JWTAuth()) // 暂时只检查JWT,不检查权限
|
||||
{ |
||||
// 菜单分组CRUD操作
|
||||
menuGroupGroup.GET("", menuGroupController.ListMenuGroups) // 获取菜单分组列表
|
||||
menuGroupGroup.POST("", menuGroupController.CreateMenuGroup) // 创建菜单分组
|
||||
menuGroupGroup.GET("/:id", menuGroupController.GetMenuGroup) // 获取菜单分组详情
|
||||
menuGroupGroup.PUT("/:id", menuGroupController.UpdateMenuGroup) // 更新菜单分组
|
||||
menuGroupGroup.DELETE("/:id", menuGroupController.DeleteMenuGroup) // 删除菜单分组
|
||||
|
||||
// 批量操作
|
||||
menuGroupGroup.POST("/batch-delete", menuGroupController.BatchDeleteMenuGroups) // 批量删除菜单分组
|
||||
menuGroupGroup.PUT("/batch-sort", menuGroupController.BatchUpdateMenuGroupSort) // 批量更新排序
|
||||
|
||||
// 状态和排序管理
|
||||
menuGroupGroup.PUT("/:id/status", menuGroupController.UpdateMenuGroupStatus) // 更新状态
|
||||
menuGroupGroup.PUT("/:id/sort", menuGroupController.UpdateMenuGroupSort) // 更新排序
|
||||
|
||||
// 统计信息
|
||||
menuGroupGroup.GET("/stats", menuGroupController.GetMenuGroupStats) // 获取统计信息
|
||||
} |
||||
} |
||||
} |
@ -1,52 +0,0 @@
@@ -1,52 +0,0 @@
|
||||
package routes |
||||
|
||||
import ( |
||||
"gofaster/internal/auth/controller" |
||||
"gofaster/internal/shared/middleware" |
||||
|
||||
"github.com/gin-gonic/gin" |
||||
) |
||||
|
||||
// RegisterMenuRouteRoutes 注册菜单路由关联表路由
|
||||
func RegisterMenuRouteRoutes(r *gin.RouterGroup, menuRouteController *controller.MenuRouteController) { |
||||
// 菜单路由关联表路由组
|
||||
menuRouteGroup := r.Group("/menu-routes") |
||||
{ |
||||
// 需要认证的接口
|
||||
menuRouteGroup.Use(middleware.JWTAuth()) |
||||
{ |
||||
// 基础CRUD操作
|
||||
menuRouteGroup.POST("", menuRouteController.CreateMenuRoute) // 创建菜单路由关联
|
||||
menuRouteGroup.GET("", menuRouteController.ListMenuRoutes) // 获取菜单路由关联列表
|
||||
menuRouteGroup.PUT("/:id", menuRouteController.UpdateMenuRoute) // 更新菜单路由关联
|
||||
menuRouteGroup.DELETE("/:id", menuRouteController.DeleteMenuRoute) // 删除菜单路由关联
|
||||
} |
||||
} |
||||
|
||||
// 菜单相关路由
|
||||
menuGroup := r.Group("/menus") |
||||
{ |
||||
// 需要认证的接口
|
||||
menuGroup.Use(middleware.JWTAuth()) |
||||
{ |
||||
// 菜单路由关联操作
|
||||
menuGroup.POST("/:menuID/routes", menuRouteController.CreateMenuRoutes) // 批量创建菜单路由关联
|
||||
menuGroup.GET("/:menuID/routes", menuRouteController.GetMenuRoutes) // 获取菜单的路由关联
|
||||
menuGroup.GET("/:menuID/routes/detail", menuRouteController.GetMenuWithRoutes) // 获取菜单及其关联的路由信息
|
||||
menuGroup.DELETE("/:menuID/routes", menuRouteController.DeleteMenuRoutes) // 删除菜单的所有路由关联
|
||||
menuGroup.POST("/:menuID/routes/sync", menuRouteController.SyncMenuRoutes) // 同步菜单路由关联
|
||||
} |
||||
} |
||||
|
||||
// 路由映射相关路由
|
||||
routeMappingGroup := r.Group("/route-mappings") |
||||
{ |
||||
// 需要认证的接口
|
||||
routeMappingGroup.Use(middleware.JWTAuth()) |
||||
{ |
||||
// 路由菜单关联操作
|
||||
routeMappingGroup.GET("/:routeMappingID/menus", menuRouteController.GetRouteMenus) // 获取路由的菜单关联
|
||||
routeMappingGroup.GET("/:routeMappingID/menus/detail", menuRouteController.GetRouteWithMenus) // 获取路由及其关联的菜单信息
|
||||
} |
||||
} |
||||
} |
@ -0,0 +1,229 @@
@@ -0,0 +1,229 @@
|
||||
package service |
||||
|
||||
import ( |
||||
"fmt" |
||||
"gofaster/internal/auth/model" |
||||
"gofaster/internal/auth/repository" |
||||
|
||||
"go.uber.org/zap" |
||||
) |
||||
|
||||
// MenuGroupService 菜单分组服务
|
||||
type MenuGroupService struct { |
||||
menuGroupRepo *repository.MenuGroupRepository |
||||
logger *zap.Logger |
||||
} |
||||
|
||||
// NewMenuGroupService 创建菜单分组服务实例
|
||||
func NewMenuGroupService(menuGroupRepo *repository.MenuGroupRepository, logger *zap.Logger) *MenuGroupService { |
||||
return &MenuGroupService{ |
||||
menuGroupRepo: menuGroupRepo, |
||||
logger: logger, |
||||
} |
||||
} |
||||
|
||||
// CreateMenuGroup 创建菜单分组
|
||||
func (s *MenuGroupService) CreateMenuGroup(menuGroup *model.MenuGroup) error { |
||||
s.logger.Info("开始创建菜单分组", zap.String("name", menuGroup.Name)) |
||||
|
||||
// 检查名称是否已存在
|
||||
if s.menuGroupRepo.ExistsByName(menuGroup.Name) { |
||||
return fmt.Errorf("菜单分组名称已存在: %s", menuGroup.Name) |
||||
} |
||||
|
||||
// 设置默认值
|
||||
if menuGroup.Sort == 0 { |
||||
menuGroup.Sort = 999 // 默认排序值
|
||||
} |
||||
if menuGroup.Status == 0 { |
||||
menuGroup.Status = 1 // 默认启用
|
||||
} |
||||
|
||||
if err := s.menuGroupRepo.Create(menuGroup); err != nil { |
||||
s.logger.Error("创建菜单分组失败", zap.Error(err)) |
||||
return fmt.Errorf("创建菜单分组失败: %w", err) |
||||
} |
||||
|
||||
s.logger.Info("菜单分组创建成功", zap.String("name", menuGroup.Name), zap.Uint("id", menuGroup.ID)) |
||||
return nil |
||||
} |
||||
|
||||
// GetMenuGroupByID 根据ID获取菜单分组
|
||||
func (s *MenuGroupService) GetMenuGroupByID(id uint) (*model.MenuGroup, error) { |
||||
menuGroup, err := s.menuGroupRepo.FindByID(id) |
||||
if err != nil { |
||||
s.logger.Error("获取菜单分组失败", zap.Uint("id", id), zap.Error(err)) |
||||
return nil, fmt.Errorf("获取菜单分组失败: %w", err) |
||||
} |
||||
return menuGroup, nil |
||||
} |
||||
|
||||
// GetMenuGroupByName 根据名称获取菜单分组
|
||||
func (s *MenuGroupService) GetMenuGroupByName(name string) (*model.MenuGroup, error) { |
||||
menuGroup, err := s.menuGroupRepo.FindByName(name) |
||||
if err != nil { |
||||
s.logger.Error("获取菜单分组失败", zap.String("name", name), zap.Error(err)) |
||||
return nil, fmt.Errorf("获取菜单分组失败: %w", err) |
||||
} |
||||
return menuGroup, nil |
||||
} |
||||
|
||||
// ListMenuGroups 获取菜单分组列表
|
||||
func (s *MenuGroupService) ListMenuGroups() ([]*model.MenuGroup, error) { |
||||
menuGroups, err := s.menuGroupRepo.List() |
||||
if err != nil { |
||||
s.logger.Error("获取菜单分组列表失败", zap.Error(err)) |
||||
return nil, fmt.Errorf("获取菜单分组列表失败: %w", err) |
||||
} |
||||
return menuGroups, nil |
||||
} |
||||
|
||||
// ListMenuGroupsByStatus 根据状态获取菜单分组列表
|
||||
func (s *MenuGroupService) ListMenuGroupsByStatus(status int) ([]*model.MenuGroup, error) { |
||||
menuGroups, err := s.menuGroupRepo.ListByStatus(status) |
||||
if err != nil { |
||||
s.logger.Error("根据状态获取菜单分组列表失败", zap.Int("status", status), zap.Error(err)) |
||||
return nil, fmt.Errorf("根据状态获取菜单分组列表失败: %w", err) |
||||
} |
||||
return menuGroups, nil |
||||
} |
||||
|
||||
// UpdateMenuGroup 更新菜单分组
|
||||
func (s *MenuGroupService) UpdateMenuGroup(menuGroup *model.MenuGroup) error { |
||||
s.logger.Info("开始更新菜单分组", zap.Uint("id", menuGroup.ID), zap.String("name", menuGroup.Name)) |
||||
|
||||
// 检查菜单分组是否存在
|
||||
existing, err := s.menuGroupRepo.FindByID(menuGroup.ID) |
||||
if err != nil { |
||||
s.logger.Error("菜单分组不存在", zap.Uint("id", menuGroup.ID), zap.Error(err)) |
||||
return fmt.Errorf("菜单分组不存在: %w", err) |
||||
} |
||||
|
||||
// 检查名称是否已被其他记录使用
|
||||
if s.menuGroupRepo.ExistsByName(menuGroup.Name, menuGroup.ID) { |
||||
return fmt.Errorf("菜单分组名称已存在: %s", menuGroup.Name) |
||||
} |
||||
|
||||
// 更新字段
|
||||
existing.Name = menuGroup.Name |
||||
existing.Description = menuGroup.Description |
||||
existing.Sort = menuGroup.Sort |
||||
existing.Status = menuGroup.Status |
||||
|
||||
if err := s.menuGroupRepo.Update(existing); err != nil { |
||||
s.logger.Error("更新菜单分组失败", zap.Error(err)) |
||||
return fmt.Errorf("更新菜单分组失败: %w", err) |
||||
} |
||||
|
||||
s.logger.Info("菜单分组更新成功", zap.Uint("id", menuGroup.ID)) |
||||
return nil |
||||
} |
||||
|
||||
// DeleteMenuGroup 删除菜单分组
|
||||
func (s *MenuGroupService) DeleteMenuGroup(id uint) error { |
||||
s.logger.Info("开始删除菜单分组", zap.Uint("id", id)) |
||||
|
||||
// 检查菜单分组是否存在
|
||||
_, err := s.menuGroupRepo.FindByID(id) |
||||
if err != nil { |
||||
s.logger.Error("菜单分组不存在", zap.Uint("id", id), zap.Error(err)) |
||||
return fmt.Errorf("菜单分组不存在: %w", err) |
||||
} |
||||
|
||||
if err := s.menuGroupRepo.Delete(id); err != nil { |
||||
s.logger.Error("删除菜单分组失败", zap.Error(err)) |
||||
return fmt.Errorf("删除菜单分组失败: %w", err) |
||||
} |
||||
|
||||
s.logger.Info("菜单分组删除成功", zap.Uint("id", id)) |
||||
return nil |
||||
} |
||||
|
||||
// BatchDeleteMenuGroups 批量删除菜单分组
|
||||
func (s *MenuGroupService) BatchDeleteMenuGroups(ids []uint) error { |
||||
s.logger.Info("开始批量删除菜单分组", zap.Uints("ids", ids)) |
||||
|
||||
if len(ids) == 0 { |
||||
return fmt.Errorf("删除ID列表不能为空") |
||||
} |
||||
|
||||
if err := s.menuGroupRepo.BatchDelete(ids); err != nil { |
||||
s.logger.Error("批量删除菜单分组失败", zap.Error(err)) |
||||
return fmt.Errorf("批量删除菜单分组失败: %w", err) |
||||
} |
||||
|
||||
s.logger.Info("批量删除菜单分组成功", zap.Uints("ids", ids)) |
||||
return nil |
||||
} |
||||
|
||||
// UpdateMenuGroupStatus 更新菜单分组状态
|
||||
func (s *MenuGroupService) UpdateMenuGroupStatus(id uint, status int) error { |
||||
s.logger.Info("开始更新菜单分组状态", zap.Uint("id", id), zap.Int("status", status)) |
||||
|
||||
// 检查菜单分组是否存在
|
||||
_, err := s.menuGroupRepo.FindByID(id) |
||||
if err != nil { |
||||
s.logger.Error("菜单分组不存在", zap.Uint("id", id), zap.Error(err)) |
||||
return fmt.Errorf("菜单分组不存在: %w", err) |
||||
} |
||||
|
||||
// 验证状态值
|
||||
if status != 0 && status != 1 { |
||||
return fmt.Errorf("状态值无效,只能是0或1") |
||||
} |
||||
|
||||
if err := s.menuGroupRepo.UpdateStatus(id, status); err != nil { |
||||
s.logger.Error("更新菜单分组状态失败", zap.Error(err)) |
||||
return fmt.Errorf("更新菜单分组状态失败: %w", err) |
||||
} |
||||
|
||||
s.logger.Info("菜单分组状态更新成功", zap.Uint("id", id), zap.Int("status", status)) |
||||
return nil |
||||
} |
||||
|
||||
// UpdateMenuGroupSort 更新菜单分组排序
|
||||
func (s *MenuGroupService) UpdateMenuGroupSort(id uint, sort int) error { |
||||
s.logger.Info("开始更新菜单分组排序", zap.Uint("id", id), zap.Int("sort", sort)) |
||||
|
||||
// 检查菜单分组是否存在
|
||||
_, err := s.menuGroupRepo.FindByID(id) |
||||
if err != nil { |
||||
s.logger.Error("菜单分组不存在", zap.Uint("id", id), zap.Error(err)) |
||||
return fmt.Errorf("菜单分组不存在: %w", err) |
||||
} |
||||
|
||||
if err := s.menuGroupRepo.UpdateSort(id, sort); err != nil { |
||||
s.logger.Error("更新菜单分组排序失败", zap.Error(err)) |
||||
return fmt.Errorf("更新菜单分组排序失败: %w", err) |
||||
} |
||||
|
||||
s.logger.Info("菜单分组排序更新成功", zap.Uint("id", id), zap.Int("sort", sort)) |
||||
return nil |
||||
} |
||||
|
||||
// BatchUpdateMenuGroupSort 批量更新菜单分组排序
|
||||
func (s *MenuGroupService) BatchUpdateMenuGroupSort(sorts map[uint]int) error { |
||||
s.logger.Info("开始批量更新菜单分组排序", zap.Any("sorts", sorts)) |
||||
|
||||
if len(sorts) == 0 { |
||||
return fmt.Errorf("排序数据不能为空") |
||||
} |
||||
|
||||
if err := s.menuGroupRepo.BatchUpdateSort(sorts); err != nil { |
||||
s.logger.Error("批量更新菜单分组排序失败", zap.Error(err)) |
||||
return fmt.Errorf("批量更新菜单分组排序失败: %w", err) |
||||
} |
||||
|
||||
s.logger.Info("批量更新菜单分组排序成功") |
||||
return nil |
||||
} |
||||
|
||||
// GetMenuGroupStats 获取菜单分组统计信息
|
||||
func (s *MenuGroupService) GetMenuGroupStats() (map[string]interface{}, error) { |
||||
stats, err := s.menuGroupRepo.GetStats() |
||||
if err != nil { |
||||
s.logger.Error("获取菜单分组统计信息失败", zap.Error(err)) |
||||
return nil, fmt.Errorf("获取菜单分组统计信息失败: %w", err) |
||||
} |
||||
return stats, nil |
||||
} |
@ -1,180 +0,0 @@
@@ -1,180 +0,0 @@
|
||||
package service |
||||
|
||||
import ( |
||||
"fmt" |
||||
"gofaster/internal/auth/model" |
||||
"gofaster/internal/auth/repository" |
||||
|
||||
"go.uber.org/zap" |
||||
) |
||||
|
||||
// MenuRouteService 菜单路由关联表服务
|
||||
type MenuRouteService struct { |
||||
menuRouteRepo *repository.MenuRouteRepository |
||||
menuRepo *repository.MenuRepository |
||||
routeRepo *repository.RouteMappingRepository |
||||
log *zap.Logger |
||||
} |
||||
|
||||
// NewMenuRouteService 创建菜单路由关联表服务
|
||||
func NewMenuRouteService( |
||||
menuRouteRepo *repository.MenuRouteRepository, |
||||
menuRepo *repository.MenuRepository, |
||||
routeRepo *repository.RouteMappingRepository, |
||||
log *zap.Logger, |
||||
) *MenuRouteService { |
||||
return &MenuRouteService{ |
||||
menuRouteRepo: menuRouteRepo, |
||||
menuRepo: menuRepo, |
||||
routeRepo: routeRepo, |
||||
log: log, |
||||
} |
||||
} |
||||
|
||||
// CreateMenuRoute 创建菜单路由关联
|
||||
func (s *MenuRouteService) CreateMenuRoute(menuRoute *model.MenuRoute) error { |
||||
// 验证菜单是否存在
|
||||
if _, err := s.menuRepo.FindByID(menuRoute.MenuID); err != nil { |
||||
return fmt.Errorf("菜单不存在") |
||||
} |
||||
|
||||
// 验证路由映射是否存在
|
||||
if _, err := s.routeRepo.FindByID(menuRoute.RouteMappingID); err != nil { |
||||
return fmt.Errorf("路由映射不存在") |
||||
} |
||||
|
||||
// 检查关联是否已存在
|
||||
if existing, err := s.menuRouteRepo.GetByMenuAndRoute(menuRoute.MenuID, menuRoute.RouteMappingID); err == nil && existing != nil { |
||||
return fmt.Errorf("菜单路由关联已存在") |
||||
} |
||||
|
||||
return s.menuRouteRepo.Create(menuRoute) |
||||
} |
||||
|
||||
// CreateMenuRoutes 批量创建菜单路由关联
|
||||
func (s *MenuRouteService) CreateMenuRoutes(menuID uint, routeMappingIDs []uint) error { |
||||
// 验证菜单是否存在
|
||||
if _, err := s.menuRepo.FindByID(menuID); err != nil { |
||||
return fmt.Errorf("菜单不存在") |
||||
} |
||||
|
||||
// 验证所有路由映射是否存在
|
||||
for _, routeID := range routeMappingIDs { |
||||
if _, err := s.routeRepo.FindByID(routeID); err != nil { |
||||
return fmt.Errorf("路由映射不存在") |
||||
} |
||||
} |
||||
|
||||
// 删除现有关联
|
||||
if err := s.menuRouteRepo.DeleteByMenuID(menuID); err != nil { |
||||
return err |
||||
} |
||||
|
||||
// 创建新关联
|
||||
var menuRoutes []*model.MenuRoute |
||||
for i, routeID := range routeMappingIDs { |
||||
menuRoute := &model.MenuRoute{ |
||||
MenuID: menuID, |
||||
RouteMappingID: routeID, |
||||
Sort: i, |
||||
IsDefault: i == 0, // 第一个设为默认
|
||||
Status: 1, |
||||
} |
||||
menuRoutes = append(menuRoutes, menuRoute) |
||||
} |
||||
|
||||
return s.menuRouteRepo.CreateBatch(menuRoutes) |
||||
} |
||||
|
||||
// GetMenuRoutes 获取菜单的路由关联
|
||||
func (s *MenuRouteService) GetMenuRoutes(menuID uint) ([]*model.MenuRoute, error) { |
||||
return s.menuRouteRepo.GetByMenuID(menuID) |
||||
} |
||||
|
||||
// GetRouteMenus 获取路由的菜单关联
|
||||
func (s *MenuRouteService) GetRouteMenus(routeMappingID uint) ([]*model.MenuRoute, error) { |
||||
return s.menuRouteRepo.GetByRouteMappingID(routeMappingID) |
||||
} |
||||
|
||||
// GetMenuWithRoutes 获取菜单及其关联的路由信息
|
||||
func (s *MenuRouteService) GetMenuWithRoutes(menuID uint) (*model.Menu, []*model.RouteMapping, error) { |
||||
return s.menuRouteRepo.GetMenuWithRoutes(menuID) |
||||
} |
||||
|
||||
// GetRouteWithMenus 获取路由及其关联的菜单信息
|
||||
func (s *MenuRouteService) GetRouteWithMenus(routeMappingID uint) (*model.RouteMapping, []*model.Menu, error) { |
||||
return s.menuRouteRepo.GetRouteWithMenus(routeMappingID) |
||||
} |
||||
|
||||
// UpdateMenuRoute 更新菜单路由关联
|
||||
func (s *MenuRouteService) UpdateMenuRoute(menuRoute *model.MenuRoute) error { |
||||
// 验证关联是否存在
|
||||
if _, err := s.menuRouteRepo.GetByID(menuRoute.ID); err != nil { |
||||
return fmt.Errorf("菜单路由关联不存在") |
||||
} |
||||
|
||||
return s.menuRouteRepo.Update(menuRoute) |
||||
} |
||||
|
||||
// DeleteMenuRoute 删除菜单路由关联
|
||||
func (s *MenuRouteService) DeleteMenuRoute(id uint) error { |
||||
return s.menuRouteRepo.Delete(id) |
||||
} |
||||
|
||||
// DeleteMenuRoutes 删除菜单的所有路由关联
|
||||
func (s *MenuRouteService) DeleteMenuRoutes(menuID uint) error { |
||||
return s.menuRouteRepo.DeleteByMenuID(menuID) |
||||
} |
||||
|
||||
// DeleteRouteMenus 删除路由的所有菜单关联
|
||||
func (s *MenuRouteService) DeleteRouteMenus(routeMappingID uint) error { |
||||
return s.menuRouteRepo.DeleteByRouteMappingID(routeMappingID) |
||||
} |
||||
|
||||
// DeleteMenuRouteByMenuAndRoute 根据菜单ID和路由ID删除关联
|
||||
func (s *MenuRouteService) DeleteMenuRouteByMenuAndRoute(menuID, routeMappingID uint) error { |
||||
return s.menuRouteRepo.DeleteByMenuAndRoute(menuID, routeMappingID) |
||||
} |
||||
|
||||
// ListMenuRoutes 获取菜单路由关联列表
|
||||
func (s *MenuRouteService) ListMenuRoutes(page, pageSize int) ([]*model.MenuRoute, int64, error) { |
||||
return s.menuRouteRepo.List(page, pageSize) |
||||
} |
||||
|
||||
// SyncMenuRoutes 同步菜单路由关联(用于批量操作)
|
||||
func (s *MenuRouteService) SyncMenuRoutes(menuID uint, routeMappingIDs []uint) error { |
||||
s.log.Info("开始同步菜单路由关联", zap.Uint("menuID", menuID), zap.Any("routeMappingIDs", routeMappingIDs)) |
||||
|
||||
// 删除现有关联
|
||||
if err := s.menuRouteRepo.DeleteByMenuID(menuID); err != nil { |
||||
s.log.Error("删除现有菜单路由关联失败", zap.Error(err)) |
||||
return err |
||||
} |
||||
|
||||
// 如果没有新的路由映射,直接返回
|
||||
if len(routeMappingIDs) == 0 { |
||||
s.log.Info("没有新的路由映射,同步完成") |
||||
return nil |
||||
} |
||||
|
||||
// 创建新关联
|
||||
var menuRoutes []*model.MenuRoute |
||||
for i, routeID := range routeMappingIDs { |
||||
menuRoute := &model.MenuRoute{ |
||||
MenuID: menuID, |
||||
RouteMappingID: routeID, |
||||
Sort: i, |
||||
IsDefault: i == 0, // 第一个设为默认
|
||||
Status: 1, |
||||
} |
||||
menuRoutes = append(menuRoutes, menuRoute) |
||||
} |
||||
|
||||
if err := s.menuRouteRepo.CreateBatch(menuRoutes); err != nil { |
||||
s.log.Error("创建菜单路由关联失败", zap.Error(err)) |
||||
return err |
||||
} |
||||
|
||||
s.log.Info("菜单路由关联同步完成", zap.Int("关联数量", len(menuRoutes))) |
||||
return nil |
||||
} |
Loading…
Reference in new issue