动态路由

This commit is contained in:
tanyp 2023-04-06 17:20:37 +08:00
parent 964ca18c53
commit e6c56ebbb1
18 changed files with 287 additions and 183 deletions

View File

@ -11,7 +11,7 @@
Target Server Version : 50721
File Encoding : 65001
Date: 28/03/2023 17:24:19
Date: 06/04/2023 17:20:01
*/
SET NAMES utf8mb4;
@ -39,6 +39,10 @@ CREATE TABLE `sys_dic` (
INDEX `group_name`(`group_name`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '字典表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of sys_dic
-- ----------------------------
-- ----------------------------
-- Table structure for sys_login_log
-- ----------------------------
@ -53,10 +57,14 @@ CREATE TABLE `sys_login_log` (
`address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '地理位置',
`ip` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT 'ip地址',
`token` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT 'token',
`create_date` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of sys_login_log
-- ----------------------------
-- ----------------------------
-- Table structure for sys_menu
-- ----------------------------
@ -74,14 +82,24 @@ CREATE TABLE `sys_menu` (
`component` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '组件名称',
`open_mode` int(1) NULL DEFAULT 0 COMMENT '打开方式0、默认1、iframe2、新标签页',
`is_del` int(1) NULL DEFAULT 0 COMMENT '是否删除0、未删除1、已删除',
`keep_alive` int(1) NULL DEFAULT 1 COMMENT '是否缓存0、不缓存1、缓存',
`remarks` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '描述',
`keep_alive` int(1) NULL DEFAULT NULL COMMENT '是否缓存0、不缓存1、缓存',
`is_show` int(1) NULL DEFAULT NULL COMMENT '是否显示1显示0不显示',
`update_date` datetime NULL DEFAULT NULL COMMENT '更新时间',
`create_date` datetime NULL DEFAULT NULL COMMENT '创建时间',
`update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
`create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
`remarks` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '描述',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '菜单表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of sys_menu
-- ----------------------------
INSERT INTO `sys_menu` VALUES ('10001dsgf', 'b1851d1b13594e71840103c11a37a002', 'Iframe', 'https://www.bing.com/?mkt=zh-CN', 'Grid', 'Iframe测试', 'User', NULL, 6, NULL, 0, 0, 0, 1, '2023-03-29 08:57:50', '2023-03-29 08:57:52', NULL);
INSERT INTO `sys_menu` VALUES ('b1851d1b13594e71840103c11a37a002', '0', 'system', '/system', 'Grid', '系统管理', 'System', NULL, 1, NULL, 0, 0, 0, 1, '2023-03-29 08:57:50', '2023-03-29 08:57:52', NULL);
INSERT INTO `sys_menu` VALUES ('b1851d1b13594e71840103c11a37a003', 'b1851d1b13594e71840103c11a37a002', 'menu', '/system/Menu', 'Grid', '菜单管理', 'Menu', NULL, 2, NULL, 0, 0, 0, 1, '2023-03-29 08:57:50', '2023-03-29 08:57:52', NULL);
INSERT INTO `sys_menu` VALUES ('b1851d1b13594e71840103c11a37a004', 'b1851d1b13594e71840103c11a37a002', 'org', '/system/Org', 'QuestionFilled', '组织管理', 'Org', NULL, 3, NULL, 0, 0, 0, 1, '2023-03-29 08:57:50', '2023-03-29 08:57:52', NULL);
INSERT INTO `sys_menu` VALUES ('b1851d1b13594e71840103c11a37a005', 'b1851d1b13594e71840103c11a37a002', 'role', '/system/Role', 'Grid', '权限管理', 'Role', NULL, 4, NULL, 0, 0, 0, 1, '2023-03-29 08:57:50', '2023-03-29 08:57:52', NULL);
INSERT INTO `sys_menu` VALUES ('b1851d1b13594e71840103c11a37a006', 'b1851d1b13594e71840103c11a37a002', 'user', '/system/User', 'Grid', '用户管理', 'User', NULL, 5, NULL, 0, 0, 0, 1, '2023-03-29 08:57:50', '2023-03-29 08:57:52', NULL);
-- ----------------------------
-- Table structure for sys_oper_log
-- ----------------------------
@ -104,6 +122,10 @@ CREATE TABLE `sys_oper_log` (
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '操作日志' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of sys_oper_log
-- ----------------------------
-- ----------------------------
-- Table structure for sys_org
-- ----------------------------
@ -121,6 +143,11 @@ CREATE TABLE `sys_org` (
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '组织' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of sys_org
-- ----------------------------
INSERT INTO `sys_org` VALUES ('534a37c366ec47878a6b0c85703d0bc4', '0', '总公司', 'SO00001', 0, 0, '2023-03-29 08:53:41', '2023-03-29 08:53:43', NULL);
-- ----------------------------
-- Table structure for sys_role
-- ----------------------------
@ -133,12 +160,17 @@ CREATE TABLE `sys_role` (
`sort` int(1) NULL DEFAULT NULL COMMENT '排序',
`is_del` int(1) NULL DEFAULT 0 COMMENT '是否删除0未删除1已删除',
`create_by` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人',
`update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
`create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
`remarks` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '描述',
`update_date` datetime NULL DEFAULT NULL COMMENT '更新时间',
`create_date` datetime NULL DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '角色表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of sys_role
-- ----------------------------
INSERT INTO `sys_role` VALUES ('534a37c366ec47878a6b0c85703d0bc3', '管理员', 'SR000001', '0', 0, 0, NULL, '2023-03-29 08:51:36', '2023-03-29 08:51:39', NULL);
-- ----------------------------
-- Table structure for sys_role_menu
-- ----------------------------
@ -149,6 +181,15 @@ CREATE TABLE `sys_role_menu` (
PRIMARY KEY (`role_id`, `menu_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '角色和菜单关联表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of sys_role_menu
-- ----------------------------
INSERT INTO `sys_role_menu` VALUES ('534a37c366ec47878a6b0c85703d0bc3', 'b1851d1b13594e71840103c11a37a002');
INSERT INTO `sys_role_menu` VALUES ('534a37c366ec47878a6b0c85703d0bc3', 'b1851d1b13594e71840103c11a37a003');
INSERT INTO `sys_role_menu` VALUES ('534a37c366ec47878a6b0c85703d0bc3', 'b1851d1b13594e71840103c11a37a004');
INSERT INTO `sys_role_menu` VALUES ('534a37c366ec47878a6b0c85703d0bc3', 'b1851d1b13594e71840103c11a37a005');
INSERT INTO `sys_role_menu` VALUES ('534a37c366ec47878a6b0c85703d0bc3', 'b1851d1b13594e71840103c11a37a006');
-- ----------------------------
-- Table structure for sys_role_org
-- ----------------------------
@ -159,6 +200,11 @@ CREATE TABLE `sys_role_org` (
PRIMARY KEY (`org_id`, `role_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户组织机构关联表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of sys_role_org
-- ----------------------------
INSERT INTO `sys_role_org` VALUES ('534a37c366ec47878a6b0c85703d0bc4', '534a37c366ec47878a6b0c85703d0bc3');
-- ----------------------------
-- Table structure for sys_user
-- ----------------------------
@ -180,12 +226,17 @@ CREATE TABLE `sys_user` (
`id_card` varchar(18) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '身份证号码',
`email` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '邮箱',
`create_by` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人',
`update_date` datetime NULL DEFAULT NULL COMMENT '更新时间',
`create_date` datetime NULL DEFAULT NULL COMMENT '创建时间',
`update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
`create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
`remarks` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`id`, `username`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户表' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of sys_user
-- ----------------------------
INSERT INTO `sys_user` VALUES ('534a37c366ec47878a6b0c85703d0bc2', 'admin', '管理员', '8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92', 1, NULL, NULL, 0, '2023-03-29', NULL, 0, '', '', '', '', NULL, '2023-03-29 08:49:24', '2023-03-29 08:49:27', NULL);
-- ----------------------------
-- Table structure for sys_user_role
-- ----------------------------
@ -196,4 +247,9 @@ CREATE TABLE `sys_user_role` (
PRIMARY KEY (`user_id`, `role_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户角色' ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of sys_user_role
-- ----------------------------
INSERT INTO `sys_user_role` VALUES ('534a37c366ec47878a6b0c85703d0bc2', '534a37c366ec47878a6b0c85703d0bc3');
SET FOREIGN_KEY_CHECKS = 1;

View File

@ -16,13 +16,11 @@
"vue-router": "^4.1.6"
},
"devDependencies": {
"@iconify-json/ep": "^1.1.4",
"@types/node": "^18.14.0",
"@vitejs/plugin-vue": "^4.0.0",
"sass": "^1.52.1",
"typescript": "^4.7.2",
"unocss": "^0.49.7",
"unplugin-vue-components": "^0.24.0",
"vite": "^4.1.2",
"vite-ssg": "^0.22.1",
"vue-tsc": "^1.1.3"

View File

@ -2,6 +2,7 @@ import request from '@/utils/request'
const userKey:string = 'tansci_boot_user'
const tokenKey:string = 'tansci_boot_token'
const menuKey:string = 'tansci_boot_menu'
// token信息
export function getToken() {
@ -16,7 +17,8 @@ export function removeToken() {
// 用户信息
export function getUser() {
return sessionStorage.getItem(userKey);
let user = sessionStorage.getItem(userKey);
return user ? JSON.parse(user) : null;
}
export function setUser(data:any) {
return sessionStorage.setItem(userKey, JSON.stringify(data));
@ -25,6 +27,17 @@ export function removeUser() {
return sessionStorage.removeItem(userKey);
}
// 菜单信息
export function getMenus() {
let menu = sessionStorage.getItem(menuKey);
return menu ? JSON.parse(menu) : null;
}
// 菜单信息
export function setMenus(menus:any) {
return sessionStorage.setItem(menuKey, JSON.stringify(menus));
}
// 登录
export function login(data:any){
return new Promise((resolve, reject) => {

View File

@ -102,10 +102,13 @@
</el-tab-pane>
</el-tabs>
<el-dropdown trigger="hover">
<el-button size="small" type="primary">
<!-- <el-button size="small" type="primary">
<span>更多</span>
<el-icon class="el-icon--right"><arrow-down /></el-icon>
</el-button>
</el-button> -->
<span class="el-dropdown-link" style="cursor: pointer;">
<el-icon :size="18"><Tools /></el-icon>
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item icon="CircleCloseFilled" @click="onCloseCurrentTab">关闭当前</el-dropdown-item>

View File

@ -1,18 +1,17 @@
<script setup lang="ts">
import { reactive, onMounted, onBeforeMount, onDeactivated } from "vue"
import { isDark, toggleDark } from '@/composables'
import { useRouter } from 'vue-router'
import { getUser, getMenus, logout } from "@/api/auth"
import Submenu from "@/components/Submenu.vue"
import TabsMenu from "@/components/TabsMenu.vue"
const router = useRouter()
const logo = new URL('../../assets/image/logo.png', import.meta.url).href
const state = reactive({
headerHeight: '52px',
asideWidth: '180px',
routers: [],
defaultHeight: null,
username: '未登录'
})
onBeforeMount(() => {
@ -22,17 +21,20 @@
onMounted(()=>{
//
let routers:any = [];
let _routes = router.options.routes;
console.log("_routes:",_routes)
let _routes:any = getMenus();
_routes.forEach((item:any)=>{
if(item.children && item.type == 0){
if(item.children && item.isShow){
routers.push(item)
}
})
state.routers = routers
let user:any = getUser()
if(user){
state.username = user.nickname
}
window.addEventListener('resize', onDefaultHeight);
})
@ -43,6 +45,13 @@
function onDefaultHeight(){
state.defaultHeight = window.innerHeight
}
function onHeaderCommand(command:any){
if('logout' === command){
logout()
} else if('password' === command){
}
}
</script>
<template>
@ -56,17 +65,24 @@
<div class="header-dark">
<el-button @click="toggleDark()" link type="primary">
<template #icon>
<el-icon><Sunny v-show="!isDark"/></el-icon>
<el-icon><Moon v-show="isDark"/></el-icon>
<el-icon :size="20"><Sunny v-show="!isDark"/></el-icon>
<el-icon :size="20"><Moon v-show="isDark"/></el-icon>
</template>
</el-button>
</div>
<div class="header-login">
<el-button circle>
<template #icon>
<el-icon><UserFilled /></el-icon>
<el-dropdown @command="onHeaderCommand">
<span class="el-dropdown-link">
<span>{{state.username}}</span>
<el-icon class="el-icon--right"><arrow-down /></el-icon>
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="password">修改密码</el-dropdown-item>
<el-dropdown-item command="logout">退出</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-button>
</el-dropdown>
</div>
</div>
</el-header>
@ -109,6 +125,15 @@
.header-content{
display: flex;
justify-content: right;
.header-dark{
padding-right: 1rem;
}
.header-login{
.el-dropdown{
cursor: pointer;
line-height: 52px;
}
}
}
}
.el-aside{

View File

@ -24,17 +24,17 @@ export default[
{
path: '/index',
name: 'index',
type: 0,
icon: 'HomeFilled',
meta: { title: "首页" },
isShow: true,
component: () => import("@/components/layout/Index.vue"),
children: [
{
path: '/index',
name: 'index',
type: 0,
icon: 'HomeFilled',
meta: { title: "首页" },
isShow: true,
component: () => import('@/views/Index.vue')
}
]

View File

@ -1,16 +1,13 @@
import { createRouter, createWebHistory } from "vue-router"
import { ElMessage } from 'element-plus'
import { getToken, removeToken, removeUser } from "@/api/auth"
import { getToken, removeToken, removeUser, setMenus } from "@/api/auth"
import { generateRoutes } from "./permission"
// import routers from './routers'
import common from './common'
const router = createRouter({
history: createWebHistory(),
routes: [
...common,
// ...routers
...common
]
})
@ -25,9 +22,9 @@ router.beforeEach(async (to:any, from:any, next) => {
}
if(getToken()){
if(to.path === '/login'){
next({ path: '/index' })
} else {
// if(to.path === '/login'){
// next({ path: '/index' })
// } else {
if(load){
next()
} else {
@ -35,9 +32,13 @@ router.beforeEach(async (to:any, from:any, next) => {
try {
// 获取菜单
await generateRoutes().then( (accessRoutes:any) => {
accessRoutes.push({path:'/:pathMatch(.*)*', redirect:'/404'})
accessRoutes.forEach( (item:any) => {
router.addRoute(item)
})
let routers = common.concat(accessRoutes)
setMenus([...routers])
})
next({ ...to, replace: true })
@ -48,7 +49,7 @@ router.beforeEach(async (to:any, from:any, next) => {
next(`/login`)
}
}
}
// }
} else {
if(whiteList.indexOf(to.path) !== -1){
next()

View File

@ -1,50 +1,40 @@
import request from '@/utils/request'
import common from '@/utils/common'
import Layout from '@/components/layout/Index.vue'
const viewModules = import.meta.glob("../views/**/**.vue")
const modules = import.meta.glob('../views/**/**.vue')
const layoutModules = import.meta.glob("../components/layout/**.vue")
// 根据菜单构建动态路由
export const filterAsyncRouter = (routers:any, level:any) => {
export const filterRouter = (routers:any, level:any) => {
level = level || 0
const accessedRouters = routers.filter( (router:any) => {
if (router.isShow === 1) {
if (router.isShow) {
var setIframe = () => {
router.component = loadView(`/common/Iframe`)
router.props = { url: router.url }
router.path = "/" + router.url
router.props = { url: router.path }
router.path = "/" + common.uuid()
}
if(router.url && router.url.startsWith('http')){
if(router.openMode == '0'){
if(router.path && router.path.startsWith('http') && router.meta.openMode === 0){
setIframe()
}
} else if(router.url && router.url.startsWith('/') && router.url.indexOf('.htm') != -1) {
if(router.openMode == '0'){
} else if(router.path && router.path.startsWith('/') && router.path.indexOf('.htm') != -1){
if(router.meta.openMode === 0){
setIframe()
} else {
router.path = location.href.substring(0, location.href.indexOf('/', location.href.indexOf('/', location.href.indexOf('/') + 1) + 1)) + router.path
}
} else if (router.componentName) {
router.props = {
name: router.componentName,
id :router.id
}
// 根据组件类型渲染
router.component = loadView(`/common/Component`)
} else if (router.component) { // 如果是现成组件
const component:any = router.component
} else if(router.component){
const component = router.component
if(component === 'Layout'){
router.path = "/" + common.uuid()
router.component = level > 0 ? layoutModules[`../components/layout/None.vue`] : loadLayoutView()
router.component = level > 0 ? loadView(router.path) : Layout
} else {
router.path = router.path.startsWith('/') ? router.path : '/' + router.path
router.component = loadView(component) || layoutModules[`../components/layout/Empty.vue`]
}
}
if (router.children && router.children.length) {
router.children = filterAsyncRouter(router.children, level + 1)
router.children = filterRouter(router.children, level + 1)
}
return true
}
@ -53,45 +43,22 @@ export const filterAsyncRouter = (routers:any, level:any) => {
return accessedRouters
}
export const loadLayoutView = () => {
return layoutModules[`../components/layout/Index.vue`]
}
export const loadView = (view:any) => {
view = view.substring(0, 1) === '/' ? view : '/' + view
return viewModules[`../views${view}.vue`]
return modules[`../views${view}.vue`]
}
// 获取当前用户的权限菜单
export function generateRoutes(){
return new Promise((resolve, reject) => {
request({
url: '/tansci/sysmenu/tree',
url: '/tansci/sysmenu/menus',
method: 'get'
}).then( (res:any) => {
let data = recastData(res.data.result, [])
console.log(data)
const asyncRouter = filterAsyncRouter(data, 0)
resolve(asyncRouter)
})
})
}
const routers = filterRouter(res.data.result, 0)
export function recastData(data:any, arr:any){
data.forEach( (item:any) => {
arr.push({
path: item.url,
name: item.url,
icon: item.icon,
isShow: item.isShow,
component: item.component,
meta: {
title: item.chineseName,
keepAlive: item.keepAlive
}
console.log(routers)
resolve(routers)
})
})
if (item.children && item.children.length) {
recastData(item.children, arr);
}
});
}

View File

@ -1,84 +0,0 @@
import Layout from '@/components/layout/Index.vue'
export default[
{
path: '/index',
name: 'index',
type: 0,
icon: 'HomeFilled',
meta: { title: "首页" },
component: () => Layout,
children: [
{
path: '/index',
name: 'index',
type: 0,
icon: 'HomeFilled',
meta: { title: "首页" },
component: () => import('@/views/Index.vue')
}
]
},
{
path: '/system',
name: 'system',
type: 0,
icon: 'Grid',
meta: { title: "系统管理" },
children: [
{
path: '/menu',
name: 'menu',
type: 0,
icon: 'Grid',
meta: { title: "菜单管理" },
component: () => Layout,
children: [
{
path: '/menu',
name: 'menu',
type: 0,
icon: 'Grid',
meta: { title: "菜单管理" },
component: () => import('@/views/system/Manu.vue')
},
]
},
{
path: '/org',
name: 'org',
type: 0,
icon: 'QuestionFilled',
meta: { title: "组织管理" },
component: () => Layout,
children: [
{
path: '/org',
name: 'org',
type: 0,
icon: 'QuestionFilled',
meta: { title: "组织管理" },
component: () => import('@/views/system/Org.vue')
}
]
},
{
path: '/user',
name: 'user',
type: 0,
icon: 'QuestionFilled',
meta: { title: "用户管理" },
component: () => Layout,
children: [
{
path: '/user',
name: 'user',
type: 0,
icon: 'QuestionFilled',
meta: { title: "用户管理" },
component: () => import('@/views/system/User.vue')
}
]
},
]
},
]

View File

@ -14,8 +14,8 @@
<style scoped>
iframe{
position: absolute;
left: 0;
top: 0;
left: 180px;
top: 100px;
right: 0;
bottom: 0;
}

View File

@ -0,0 +1,5 @@
<template>
<div>
App
</div>
</template>

View File

@ -9,10 +9,11 @@
"useDefineForClassFields": true,
"module": "esnext",
"moduleResolution": "node",
"strict": true,
"strict": false,
"jsx": "preserve",
"sourceMap": true,
"resolveJsonModule": true,
"isolatedModules": true,
"esModuleInterop": true,
"lib": ["esnext", "dom"],
"paths": {

View File

@ -3,6 +3,7 @@ package com.tansci.controller;
import com.tansci.common.WrapMapper;
import com.tansci.common.Wrapper;
import com.tansci.domain.SysMenu;
import com.tansci.domain.vo.SysMenuVo;
import com.tansci.service.SysMenuService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@ -30,10 +31,16 @@ public class SysMenuController {
@Autowired
private SysMenuService sysMenuService;
@ApiOperation(value = "菜单树", notes = "菜单树")
@ApiOperation(value = "当前用户权限菜单树", notes = "当前用户权限菜单树")
@GetMapping("/tree")
public Wrapper<List<SysMenu>> tree(SysMenu menu) {
return WrapMapper.wrap(Wrapper.SUCCESS_CODE, Wrapper.SUCCESS_MESSAGE, sysMenuService.tree(menu));
}
@ApiOperation(value = "当前用户权限菜单列表", notes = "当前用户权限菜单列表")
@GetMapping("/menus")
public Wrapper<List<SysMenuVo>> menus() {
return WrapMapper.wrap(Wrapper.SUCCESS_CODE, Wrapper.SUCCESS_MESSAGE, sysMenuService.menus());
}
}

View File

@ -0,0 +1,57 @@
package com.tansci.domain.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
import java.util.Map;
/**
* @ClassName SysMenuVo.java
* @ClassPath com.tansci.domain.SysMenuVo.java
* @Description 菜单
* @Author tanyp
* @Date 2023/03/20 10:38
**/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(value = "菜单")
public class SysMenuVo {
@ApiModelProperty(value = "主键id")
private String id;
@ApiModelProperty(value = "父菜单ID")
private String parentId;
@ApiModelProperty(value = "菜单名称")
private String name;
@ApiModelProperty(value = "菜单链接")
private String path;
@ApiModelProperty(value = "图标")
private String icon;
@ApiModelProperty(value = "排序")
private Integer sort;
@ApiModelProperty(value = "组件名称")
private String component;
@ApiModelProperty(value = "是否显示0、不显示1、显示")
private Boolean isShow;
@ApiModelProperty(value = "meta对象")
private Map<String, Object> meta;
@ApiModelProperty(value = "子级菜单")
private List<SysMenuVo> children;
}

View File

@ -1,5 +1,6 @@
package com.tansci.handler;
import cn.dev33.satoken.exception.NotLoginException;
import com.tansci.common.WrapMapper;
import com.tansci.common.Wrapper;
import com.tansci.common.exception.BusinessException;
@ -35,6 +36,9 @@ public class GlobalExceptionHandler {
MethodArgumentNotValidException ex = (MethodArgumentNotValidException) e;
log.error("参数校验异常:{}", ex.getBindingResult().getFieldError().getDefaultMessage());
return WrapMapper.wrap(Wrapper.ILLEGAL_ARGUMENT_CODE_, "参数有误:" + ex.getBindingResult().getFieldError().getDefaultMessage(), null);
} else if (e instanceof NotLoginException) {
NotLoginException ne = (NotLoginException) e;
return WrapMapper.wrap(Wrapper.AUTHORIZATION_CODE, Wrapper.AUTHORIZATION_MESSAGE, ne.getMessage());
} else {
log.error("统一系统异常:{}", e);
return WrapMapper.wrap(Wrapper.ERROR_CODE, e.getMessage(), null);

View File

@ -2,6 +2,7 @@ package com.tansci.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.tansci.domain.SysMenu;
import com.tansci.domain.vo.SysMenuVo;
import java.util.List;
@ -16,4 +17,6 @@ public interface SysMenuService extends IService<SysMenu> {
List<SysMenu> tree(SysMenu menu);
List<SysMenuVo> menus();
}

View File

@ -7,6 +7,7 @@ import com.google.common.collect.Lists;
import com.tansci.common.constant.Constants;
import com.tansci.domain.SysMenu;
import com.tansci.domain.SysRoleMenu;
import com.tansci.domain.vo.SysMenuVo;
import com.tansci.domain.vo.SysUserSessionVo;
import com.tansci.mapper.SysMenuMapper;
import com.tansci.service.SysMenuService;
@ -60,4 +61,51 @@ public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> impl
return menuList;
}
@Override
public List<SysMenuVo> menus() {
// 菜单权限
String userId = String.valueOf(StpUtil.getLoginId());
SysUserSessionVo sessionVo = (SysUserSessionVo) StpUtil.getSession().get(userId);
List<String> menuIds = Lists.newArrayList();
if (Objects.nonNull(sessionVo) && Objects.nonNull(sessionVo.getRoleIds()) && sessionVo.getRoleIds().size() > 0) {
List<SysRoleMenu> menus = sysRoleMenuService.list(Wrappers.<SysRoleMenu>lambdaQuery().eq(SysRoleMenu::getRoleId, sessionVo.getRoleIds()));
menuIds.addAll(menus.stream().map(SysRoleMenu::getMenuId).collect(Collectors.toList()));
}
List<SysMenu> list = this.baseMapper.selectList(
Wrappers.<SysMenu>lambdaQuery()
.eq(SysMenu::getIsDel, Constants.NOT_DEL_FALG)
.eq(Objects.nonNull(menuIds) && menuIds.size() > 0, SysMenu::getId, menuIds)
);
List<SysMenuVo> newList = new ArrayList<>();
for (SysMenu menu : list) {
Map<String, Object> meta = new HashMap<>();
meta.put("title", menu.getChineseName());
meta.put("keepAlive", Objects.equals(1, menu.getKeepAlive()) ? true : false);
meta.put("isShow", Objects.equals(1, menu.getIsShow()) ? true : false);
meta.put("id", menu.getId());
meta.put("openMode", menu.getOpenMode());
newList.add(
SysMenuVo.builder()
.id(menu.getId())
.parentId(menu.getParentId())
.name(menu.getName())
.path(menu.getUrl())
.icon(menu.getIcon())
.sort(menu.getSort())
.component(Objects.nonNull(menu.getComponent()) ? menu.getComponent() : "Layout")
.isShow(Objects.equals(1, menu.getIsShow()) ? true : false)
.meta(meta)
.build()
);
}
newList = newList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(SysMenuVo::getId))), ArrayList::new));
Map<String, List<SysMenuVo>> map = newList.stream().collect(Collectors.groupingBy(SysMenuVo::getParentId, Collectors.toList()));
newList.stream().forEach(item -> item.setChildren(map.get(item.getId())));
List<SysMenuVo> menuList = map.get("0").stream().sorted(Comparator.comparing(SysMenuVo::getSort)).collect(Collectors.toList());
return menuList;
}
}