This commit is contained in:
2023-09-13 18:29:35 +08:00
commit 4ac8391a9a
126 changed files with 15555 additions and 0 deletions

83
src/router/frontEnd.js Normal file
View File

@@ -0,0 +1,83 @@
import router from "./index.js";
import { staticRoutes, asyncRoutes } from "@/router/routes.js";
import { useRoutes } from "@/store/routes.js";
import { useUser } from "@/store/user.js";
/**
* @description: 初始化路由
* @param {Array} roles: 用户权限
*/
export async function initFrontEndRoutes() {
const storeUser = useUser();
// 触发初始化用户信息
await storeUser.setUserInfo();
const roles = [storeUser.userInfo.userType]; // 权限
// if (roles?.length <= 0) {}; 无权限时的处理
let addRoutes;
if (roles.includes("MG")) {
// 管理员权限包含所有的路由权限
addRoutes = asyncRoutes || [];
} else {
addRoutes = filterAsyncRoutes(asyncRoutes, roles);
}
setAddRoute(addRoutes);
const storeRoutes = useRoutes();
storeRoutes.setRoutesList([...staticRoutes[0].children, ...addRoutes]);
storeRoutes.setAllRoutes(router.getRoutes());
}
/**
* @description: 通过递归过滤异步路由表
* @param {Array} routes: 异步路由
* @param {Array} roles: 用户的所有权限
* @return {Array} 符合权限的异步路由
*/
function filterAsyncRoutes(routes, roles) {
const res = [];
routes.forEach((route) => {
if (hasPermission(route, roles)) {
if (route.children) {
route.children = filterAsyncRoutes(route.children, roles);
}
res.push(route);
}
});
return res;
}
/**
* @description: 判断路由 `meta.roles` 中是否包含当前登录用户权限字段
* @param {Array} route: 路由
* @param {Array} roles: 用户的所有权限
* @return {Boolean} 是否有权限
*/
function hasPermission(route, roles) {
if (route.meta && route.meta.roles) {
return roles.some((role) => route.meta.roles.includes(role));
} else {
return true;
}
}
/**
* @description: 添加动态路由
* @param {Array} addRoutes: 要添加的路由列表
*/
function setAddRoute(addRoutes) {
addRoutes.forEach((route) => {
// 添加嵌套路由
router.addRoute("/", route);
});
}
/**
* @description: 重置路由
* @param {Array} roles: 用户权限
*/
export function resetFrontEndRoute(roles) {
// 获取用户可以访问的权限路由后
const routes = filterAsyncRoutes(asyncRoutes, roles);
// 通过重新添加路由来覆盖
setAddRoute(routes);
}

48
src/router/index.js Normal file
View File

@@ -0,0 +1,48 @@
import { createRouter, createWebHistory } from "vue-router";
import { notFoundAndNoPower, fullScreenRouting, staticRoutes } from "./routes.js";
import { initFrontEndRoutes } from "./frontEnd.js";
import _hook from "@/hooks/index.js";
import { useRoutes } from "@/store/routes.js";
import NProgress from "nprogress";
import "nprogress/nprogress.css";
const router = createRouter({
history: createWebHistory(),
routes: [...notFoundAndNoPower, ...fullScreenRouting, ...staticRoutes],
});
NProgress.configure({ showSpinner: false });
router.beforeEach(async (to, from, next) => {
NProgress.start();
const token = _hook.useLocalStorage.get("token");
if (to.path === "/login" && !token) {
next();
NProgress.done();
} else {
if (!token) {
next("/login");
_hook.useLocalStorage.clear();
} else if (token && to.path === "/login") {
next("/home");
NProgress.done();
} else {
const storeRoutes = useRoutes();
if (storeRoutes.routesList.length === 0) {
await initFrontEndRoutes(); // 初始化前端路由
storeRoutes.setNavbar("/home"); // 每次初始化时都添加首页
next({ path: to.path, query: to.query });
NProgress.done();
} else {
storeRoutes.setNavbar(to.path);
next();
NProgress.done();
}
}
}
});
router.afterEach((to, from, next) => {
NProgress.done();
});
export default router;

524
src/router/routes.js Normal file
View File

@@ -0,0 +1,524 @@
import bridge from "@/views/layout/bridge.vue"; // 多级路由
import layout from "@/views/layout/layout.vue" // 只需要展示一页
/**
* 路由参数说明
*
* path: !!! 路由 path 路径需完整,因为菜单中所有路由跳转均使用 path 跳转。
* 如:
* 父路由 path:'/home'
* 子路由 path:'/home/page'
* 孙路由 path:'/home/page/index'
* 首页 path 必须为 '/home'
* path 路径作为菜单唯一标识不可重复, 且在没有配置 meta.title 时使用 path 作为标题.
* meta: {
* title: 菜单的标题 ( 缺少 title 时会使用路由的 path 作为标题)
* isHide: 是否隐藏此路由
* isKeepAlive: 是否缓存路由
* roles: 当前路由权限标识,取角色管理。控制路由显示、隐藏。
* icon: 图标 elementUI
* activeMenu: 需要保持高亮的菜单
* }
*/
/**
* 定义404、401界面
*/
export const notFoundAndNoPower = [
{
path: "/:pathMatch(.*)*",
name: "notFound",
component: () => import("@/views/error/404.vue"),
meta: {
title: "404",
isHide: true,
},
},
{
path: "/401",
name: "noPower",
component: () => import("@/views/error/401.vue"),
meta: {
title: "401",
isHide: true,
},
},
];
/**
* 全屏路由页面
* 此处的页面会占满浏览器的整个屏幕
*/
export const fullScreenRouting = [
{
path: "/login",
name: "login",
component: () => import("@/views/login/login.vue"),
meta: {
title: "登录",
isHide: true,
},
},
];
/**
* 静态路由
* 没有权限要求的基本页面
* 所有角色都可以访问
*/
export const staticRoutes = [
{
path: "/",
name: "/",
component: layout,
redirect: "/home",
meta: {
isHide: true,
},
children: [
{
path: "/home",
component: () => import("@/views/home.vue"),
meta: {
title: "首页",
icon: "House",
// isKeepAlive: true,
},
},
// {
// path: "/makes",
// component: bridge,
// redirect: "/makes/svgIcon",
// meta: {
// title: "组件封装",
// icon: "Edit",
// },
// children: [
// {
// path: "/makes/svgIcon",
// component: () => import("@/views/makes/svgIcon.vue"),
// meta: {
// title: "SvgIcon",
// },
// },
// ],
// },
// {
// path: "/tools",
// component: bridge,
// redirect: "/tools/editor",
// meta: {
// title: "工具",
// icon: "Flag",
// },
// children: [
// {
// path: "/tools/editor",
// component: () => import("@/views/tools/editor.vue"),
// meta: {
// title: "编辑器",
// icon: "Edit",
// },
// },
// ],
// },
// {
// path: "/other",
// component: bridge,
// redirect: "/other/watermark",
// meta: {
// title: "其他",
// icon: "Box",
// },
// children: [
// {
// path: "/other/watermark",
// component: () => import("@/views/other/watermark.vue"),
// meta: {
// title: "水印",
// },
// },
// {
// path: "/other/resize",
// component: () => import("@/views/other/resize.vue"),
// meta: {
// title: "监控元素尺寸变化",
// },
// },
// ],
// },
],
},
];
/**
* 异步路由
* 需要根据用户角色动态加载的路由
*/
export const asyncRoutes = [
// {
// path: "/demo",
// component: bridge,
// redirect: "/demo/demo1/demo11",
// meta: {
// title: "权限路由",
// icon: "Edit",
// },
// children: [
// {
// path: "demo1",
// component: bridge,
// meta: {
// title: "用户1路由-1",
// icon: "Edit",
// roles: ["yonghu1"],
// },
// children: [
// {
// path: "/demo/demo1/demo11",
// component: () => import("@/views/demo/demo11.vue"),
// name: "demo11",
// meta: {
// title: "用户1路由-11",
// },
// },
// {
// path: "/demo/demo1/demo12",
// component: () => import("@/views/demo/demo12.vue"),
// name: "demo12",
// meta: {
// title: "用户1路由-12",
// },
// children: [
// {
// path: "/demo/demo1/demo121",
// component: () => import("@/views/demo/demo121.vue"),
// name: "demo121",
// meta: {
// title: "用户1路由-121",
// },
// },
// {
// path: "/demo/demo1/demo122",
// component: () => import("@/views/demo/demo122.vue"),
// name: "demo122",
// meta: {
// title: "用户1路由-122",
// },
// },
// ],
// },
// {
// path: "/demo/demo1/demo13",
// component: () => import("@/views/demo/demo13.vue"),
// name: "demo13",
// meta: {
// title: "用户1路由-13",
// },
// },
// ],
// },
// {
// path: "/demo/demo2",
// component: bridge,
// meta: {
// title: "用户2路由-2",
// icon: "Edit",
// roles: ["yonghu2"],
// },
// children: [
// {
// path: "/demo/demo2/demo21",
// component: () => import("@/views/demo/demo21.vue"),
// meta: {
// title: "用户2路由-21",
// icon: "Edit",
// },
// },
// {
// path: "/demo/demo2/demo22",
// component: () => import("@/views/demo/demo22.vue"),
// meta: {
// title: "用户2路由-22",
// icon: "Edit",
// },
// },
// {
// path: "/demo/demo2/demo23",
// component: () => import("@/views/demo/demo23.vue"),
// meta: {
// title: "用户2路由-23",
// icon: "Edit",
// },
// },
// ],
// },
// ],
// },
// {
// path: '/system',
// component: bridge,
// redirect: '/system/menu_manage',
// meta: {
// title: '系统管理',
// icon: 'Setting',
// roles: ['FO']
// },
// children: [
// {
// path: '/system/menu_manage',
// component: () => import('@/views/system/menuMange.vue'),
// meta: {
// title: '菜单管理',
// icon: 'Stopwatch'
// }
// }
// ]
// },
{
path: '/organization',
component: layout,
meta: {
title: '大机构管理',
roles: ['MG'],
isHide: true
},
redirect: '/organization/big_organization',
children: [
{
path: '/organization/big_organization',
component: () => import('@/views/organization/big_organization.vue'),
meta: {
title: '大机构',
icon: 'Tickets'
}
}
]
},
{
path: '/mini_organization_manage',
component: layout,
meta: {
title: '小机构管理',
roles: ['FO'],
isHide: true
},
redirect: '/mini_organization_manage/mini_organization',
children: [
{
path: '/mini_organization/mini_organization',
component: () => import('@/views/organization/mini_organization.vue'),
meta: {
title: '小机构',
icon: 'SetUp'
}
}
]
},
{
path: '/agent_manage',
component: layout,
meta: {
title: '大代理管理',
roles: ['FO', 'SO'],
isHide: true
},
redirect: '/agent_manage/agent_list',
children: [
{
path: '/agent_manage/agent_list',
component: () => import('@/views/organization/agent_list.vue'),
meta: {
title: '大代理',
icon: 'Discount'
}
}
]
},
{
path: '/promotion_manage',
component: layout,
meta: {
title: '代理',
icon: 'Connection',
},
redirect: '/promotion_manage/one_promotion_list',
children: [
{
path: '/promotion_manage/one_promotion_list',
component: () => import('@/views/organization/one_promotion_list.vue'),
meta: {
title: '一级代理',
icon: 'User',
roles: ['FO', 'SO', 'AG']
}
},
{
path: '/promotion_manage/two_promotion_list',
component: () => import('@/views/organization/two_promotion_list.vue'),
meta: {
title: '二级代理',
icon: 'User',
roles: ['FO', 'SO', 'AG', 'FB']
}
}
]
},
{
path: '/shop_manage',
component: layout,
meta: {
title: '商家管理',
roles: ['FO', 'SO', 'AG', 'FB', 'SB'],
icon: 'Handbag'
},
redirect: '/shop_manage/shop_list',
children: [
{
path: '/shop_manage/shop_list',
name: 'shop_list',
component: () => import('@/views/organization/shop_list.vue'),
meta: {
title: '商家列表',
icon: 'Tickets'
}
},
{
path: '/shop_manage/shop_detail',
name: 'shop_detail',
component: () => import('@/views/organization/shop_detail.vue'),
meta: {
title: '详情',
isHide: true,
activeMenu: '/shop_manage/shop_list'
}
},
{
path: '/shop_manage/maker_apply',
component: () => import('@/views/organization/maker_apply.vue'),
meta: {
title: '创客申请',
icon: 'User'
}
}
]
},
{
path: '/withdraw_manage',
component: layout,
meta: {
title: '提现管理',
roles: ['FO', 'SO'],
isHide: true
},
redirect: '/withdraw_manage/withdraw_list',
children: [
{
path: '/withdraw_manage/withdraw_list',
component: () => import('@/views/withdraw/withdraw_list.vue'),
meta: {
title: '提现申请',
icon: 'CreditCard'
}
}
]
},
{
path: '/device_manage',
component: layout,
meta: {
title: '设备管理',
isHide: true
},
redirect: '/device_manage/device_list',
children: [
{
path: '/device_manage/device_list',
component: () => import('@/views/device/device_list.vue'),
meta: {
title: '设备列表',
icon: 'TakeawayBox'
}
}
]
},
{
path: '/total_earnings',
component: layout,
meta: {
title: '累计收益管理',
isHide: true
},
redirect: '/total_earnings/total_earnings_list',
children: [
{
path: '/total_earnings/total_earnings_list',
component: () => import('@/views/total_earnings/total_earnings_list.vue'),
meta: {
title: '累计收益',
icon: 'Coin'
}
}
]
},
{
path: '/promotion',
component: layout,
meta: {
title: '推广图片管理',
isHide: true,
roles: ['MG']
},
redirect: '/promotion/promotion_list',
children: [
{
path: '/promotion/promotion_list',
component: () => import('@/views/promotion/promotion_list.vue'),
meta: {
title: '推广图片',
icon: 'PictureRounded'
}
}
]
},
{
path: '/app_manage',
component: layout,
meta: {
title: 'APP管理',
icon: 'Iphone',
roles: ['MG']
},
redirect: '/app_manage/menu_list',
children: [
{
path: '/app_manage/menu_list',
component: () => import('@/views/app_manage/menu_list.vue'),
meta: {
title: '菜单管理',
icon: 'Tickets'
}
}
]
},
{
path: '/setting',
component: layout,
meta: {
title: '系统设置',
icon: 'Setting',
roles: ['MG']
},
redirect: '/setting/appid_manage',
children: [
{
path: '/setting/appid_manage',
component: () => import('@/views/setting/appid_manage.vue'),
meta: {
title: 'Appid管理',
icon: 'Tickets'
}
}
]
}
];