菜单路由动态加载

This commit is contained in:
骑着蜗牛追导弹 2024-02-05 09:56:49 +08:00
parent 2993f28e59
commit 09a80bc7bc
18 changed files with 163 additions and 29 deletions

17
application-macDev.yml Normal file
View File

@ -0,0 +1,17 @@
server:
port: 8001
datasource:
host: 127.0.0.1
port: 3306
username: root
password: 123456
database: d2admin
redis:
host: 127.0.0.1
port: 6379
password: 123456
database: 1
pool:
size: 1024
jwt:
secret: 123456

View File

@ -1,2 +1,2 @@
active: dev active: macDev
debug: true debug: true

View File

@ -55,7 +55,7 @@ func RunServer() {
apiGroup := r.Group("/api/v1") apiGroup := r.Group("/api/v1")
apiGroup.Use(jwt.AuthMiddleware()) apiGroup.Use(jwt.AuthMiddleware())
{ {
routes := dao.ApiDao{}.GetAllRouter() routes := dao.ApiDao{}.GetAllApi()
for _, route := range routes { for _, route := range routes {
if route.ApiMethod == "GET" { if route.ApiMethod == "GET" {
apiGroup.GET(route.ApiPath, InnerRouters[route.ApiName]) apiGroup.GET(route.ApiPath, InnerRouters[route.ApiName])

View File

@ -8,9 +8,9 @@ import (
type ApiDao struct { type ApiDao struct {
} }
func (ApiDao) GetAllRouter() []domain.Api { func (ApiDao) GetAllApi() []domain.Api {
var routers []domain.Api var apis []domain.Api
// select * from system_router where router_status = 1 // select * from system_api where api_status = 1
database.DB.Model(domain.Api{ApiStatus: 1}).Find(&routers) database.DB.Model(domain.Api{ApiStatus: 1}).Find(&apis)
return routers return apis
} }

View File

@ -0,0 +1,16 @@
package dao
import (
"d2-admin-service/src/infra/database"
"d2-admin-service/src/modules/system/domain"
)
type MenuDao struct {
}
func (MenuDao) GetAllMenu() []domain.Menu {
var menus []domain.Menu
// select * from system_menu
database.DB.Find(&menus)
return menus
}

View File

@ -8,7 +8,7 @@ type Api struct {
ApiPath string `gorm:"not null;unique_index:index_npm"` // 接口路径, 例如: /api/v1/getUser ApiPath string `gorm:"not null;unique_index:index_npm"` // 接口路径, 例如: /api/v1/getUser
ApiMethod string `gorm:"not null;unique_index:index_npm"` // GET、POST ApiMethod string `gorm:"not null;unique_index:index_npm"` // GET、POST
ApiDesc string `gorm:"not null"` // 接口说明 ApiDesc string `gorm:"not null"` // 接口说明
ApiStatus int `gorm:"not null"` // 接口是否可用 ApiStatus uint `gorm:"not null"` // 接口是否可用
} }
func (Api) TableName() string { func (Api) TableName() string {

View File

@ -0,0 +1,15 @@
package dto
type MenuItem struct {
ID uint `json:"id"`
MenuParentId uint `json:"menuParentId"`
MenuTitle string `json:"menuTitle"`
MenuIcon string `json:"menuIcon"`
MenuPath string `json:"menuPath"`
RouterPath string `json:"routerPath"`
RouterName string `json:"routerName"`
RouterAuth uint `json:"routerAuth"`
RouterHidden uint `json:"routerHidden"`
RouterComponentPath string `json:"routerComponentPath"`
Children []*MenuItem `json:"children"` // 子菜单项
}

View File

@ -4,15 +4,15 @@ import "github.com/jinzhu/gorm"
type Menu struct { type Menu struct {
gorm.Model gorm.Model
MenuParentId int `gorm:"null"` MenuParentId uint `gorm:"null" json:"menuParentId"`
MenuTitle string `gorm:"not null"` MenuTitle string `gorm:"not null" json:"menuTitle"`
MenuIcon string `gorm:"not null;default:''"` MenuIcon string `gorm:"not null;default:''" json:"menuIcon"`
MenuPath string `gorm:"not null"` MenuPath string `gorm:"not null" json:"menuPath"`
RouterPath string `gorm:"not null"` RouterPath string `gorm:"not null" json:"routerPath"`
RouterName string `gorm:"not null"` RouterName string `gorm:"not null" json:"routerName"`
RouterAuth int `gorm:"not null"` RouterAuth uint `gorm:"not null" json:"routerAuth"`
RouterHidden int `gorm:"not null"` RouterHidden uint `gorm:"not null" json:"routerHidden"`
RouterComponentPath string `gorm:"not null"` RouterComponentPath string `gorm:"not null" json:"routerComponentPath"`
} }
func (Menu) TableName() string { func (Menu) TableName() string {

View File

@ -7,7 +7,7 @@ import (
"d2-admin-service/src/infra/redistool" "d2-admin-service/src/infra/redistool"
"d2-admin-service/src/infra/resp" "d2-admin-service/src/infra/resp"
"d2-admin-service/src/modules/system/dao" "d2-admin-service/src/modules/system/dao"
"d2-admin-service/src/modules/system/rest/dto" dto2 "d2-admin-service/src/modules/system/domain/dto"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"net/http" "net/http"
"time" "time"
@ -21,7 +21,7 @@ func (AuthController) Login(c *gin.Context) {
userDao := dao.UserDao{} userDao := dao.UserDao{}
// 声明接收的变量 // 声明接收的变量
var json dto.LoginDTO var json dto2.LoginDTO
// 将request的body中的数据自动按照json格式解析到结构体 // 将request的body中的数据自动按照json格式解析到结构体
if err := c.ShouldBindJSON(&json); err != nil { if err := c.ShouldBindJSON(&json); err != nil {
c.JSON(http.StatusBadRequest, resp.ResolveParamsError) c.JSON(http.StatusBadRequest, resp.ResolveParamsError)
@ -62,7 +62,7 @@ func (AuthController) KickOut(c *gin.Context) {
c.JSON(http.StatusBadRequest, resp.NoOperationPermissionError) c.JSON(http.StatusBadRequest, resp.NoOperationPermissionError)
return return
} }
var json dto.KickOutDTO var json dto2.KickOutDTO
if err := c.ShouldBindJSON(&json); err != nil { if err := c.ShouldBindJSON(&json); err != nil {
c.JSON(http.StatusBadRequest, resp.ResolveParamsError) c.JSON(http.StatusBadRequest, resp.ResolveParamsError)
return return

View File

@ -1,11 +1,98 @@
package rest package rest
import "github.com/gin-gonic/gin" import (
"d2-admin-service/src/infra/resp"
"d2-admin-service/src/modules/system/dao"
"d2-admin-service/src/modules/system/domain/dto"
"github.com/gin-gonic/gin"
"net/http"
)
type MenuController struct { type MenuController struct {
} }
func (MenuController) TreeMenu(c *gin.Context) {} func (MenuController) TreeMenu(c *gin.Context) {
menuDao := dao.MenuDao{}
menus := menuDao.GetAllMenu()
var newMenus []dto.MenuItem
for _, menu := range menus {
menuItem := dto.MenuItem{}
menuItem.ID = menu.ID
menuItem.MenuParentId = menu.MenuParentId
menuItem.MenuTitle = menu.MenuTitle
menuItem.MenuIcon = menu.MenuIcon
menuItem.MenuPath = menu.MenuPath
menuItem.RouterAuth = menu.RouterAuth
menuItem.RouterHidden = menu.RouterHidden
menuItem.RouterName = menu.RouterName
menuItem.RouterPath = menu.RouterPath
menuItem.RouterComponentPath = menu.RouterComponentPath
newMenus = append(newMenus, menuItem)
}
c.JSON(http.StatusOK, resp.Success(buildTree(newMenus)))
}
func (MenuController) CreateMenu(c *gin.Context) {} func (MenuController) CreateMenu(c *gin.Context) {}
func (MenuController) DeleteMenu(c *gin.Context) {} func (MenuController) DeleteMenu(c *gin.Context) {}
func (MenuController) ModifyMenu(c *gin.Context) {} func (MenuController) ModifyMenu(c *gin.Context) {}
// 递归构建无限级树结构
func buildTree(menuItems []dto.MenuItem) []*dto.MenuItem {
var rootNodes []*dto.MenuItem
for _, item := range menuItems {
if item.MenuParentId == 0 { // 根节点
rootNodes = append(rootNodes, &item)
} else {
// 查找并插入到相应父节点的子菜单中
insertIntoParent(&item, menuItems)
}
}
// 对每个根节点进行递归处理其子节点
for i := range rootNodes {
rootNodes[i].Children = buildChildren(rootNodes[i], menuItems)
}
return rootNodes
}
// 将一个菜单项插入到其父节点的子菜单列表中(如果父节点已存在于菜单列表中)
func insertIntoParent(item *dto.MenuItem, menuItems []dto.MenuItem) {
for i := range menuItems {
if menuItems[i].ID == item.MenuParentId {
menuItems[i].Children = append(menuItems[i].Children, item)
return
}
}
}
// 递归构建某个节点的所有子节点
func buildChildren(parent *dto.MenuItem, menuItems []dto.MenuItem) []*dto.MenuItem {
var children []*dto.MenuItem
processedIds := make(map[uint]bool)
for _, item := range menuItems {
if item.MenuParentId == parent.ID && !processedIds[item.ID] { // 防止重复和无限递归
child := item
processedIds[child.ID] = true // 标记为已处理
// 使用剩余未处理的菜单项构建子节点
child.Children = buildChildren(&child, filterUnprocessed(menuItems, processedIds)) // 递归处理子节点
children = append(children, &child)
}
}
return children
}
// 创建一个新的切片,其中不包含已处理过的菜单项
func filterUnprocessed(menuItems []dto.MenuItem, processedIds map[uint]bool) []dto.MenuItem {
var unprocessedItems []dto.MenuItem
for _, item := range menuItems {
if !processedIds[item.ID] {
unprocessedItems = append(unprocessedItems, item)
}
}
return unprocessedItems
}

View File

@ -1,12 +1,11 @@
export default ({ service, request, tools }) => ({ export default ({ service, request, tools }) => ({
/** /**
* @description 登录 * @description 获取所有菜单
* @param {Object} data 登录携带的信息
*/ */
login (data = {}) { queryAllMenus (data = {}) {
// 接口请求 // 接口请求
return request({ return request({
url: '/login', url: '/queryAllMenus',
method: 'post', method: 'post',
data data
}) })

View File

@ -74,7 +74,7 @@ const frameIn = [
auth: true auth: true
}, },
component: _import('demo/page3') component: _import('demo/page3')
}, }
] ]
} }
] ]

View File

@ -27,7 +27,7 @@ export default {
util.cookies.set('username', res.username) util.cookies.set('username', res.username)
util.cookies.set('name', res.name) util.cookies.set('name', res.name)
util.cookies.set('token', res.token) util.cookies.set('token', res.token)
console.log("=============== 设置用户token") console.log('=============== 设置用户token')
// 设置 vuex 用户信息 // 设置 vuex 用户信息
await dispatch('d2admin/user/set', { name: res.name }, { root: true }) await dispatch('d2admin/user/set', { name: res.name }, { root: true })
// 用户登录后从持久化数据加载一系列的设置 // 用户登录后从持久化数据加载一系列的设置

View File

@ -20,7 +20,7 @@ export default {
value: info, value: info,
user: true user: true
}, { root: true }) }, { root: true })
console.log("================ 配置用户信息") console.log('================ 配置用户信息')
}, },
/** /**
* @description 从数据库取用户数据 * @description 从数据库取用户数据