You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
320 lines
11 KiB
320 lines
11 KiB
import { createRouter, createWebHashHistory } from 'vue-router';
|
|
import axios from "axios";
|
|
import request from "@/util/http.js";
|
|
import {ref} from "vue";
|
|
|
|
// 路由定义(包含权限映射 meta.permissionId)
|
|
const routes = [
|
|
// {
|
|
|
|
// path: '/workspace',
|
|
// name: "workspace",
|
|
// component: () => import("../views/workspace/audit.vue"),
|
|
// meta: { permissionId: 10 } // 对应"工作台展示"id=10
|
|
// },
|
|
{
|
|
path: '/',
|
|
redirect: "/login"
|
|
},
|
|
{
|
|
path: "/login",
|
|
name: "login",
|
|
component: () => import("../views/login.vue"),
|
|
},
|
|
{
|
|
meta: { requireAuth: true },
|
|
path: '/',
|
|
component: () => import("../views/home.vue"),
|
|
children: [
|
|
// 工作台
|
|
{
|
|
path: '/workspace',
|
|
name: "workspace",
|
|
component: () => import("../views/workspace/index.vue"),
|
|
meta: { permissionId: 10 } // 对应"工作台展示"id=10
|
|
},
|
|
|
|
|
|
// 审核
|
|
{
|
|
path: '/audit',
|
|
name: "audit",
|
|
component: () => import("../views/audit/audit.vue"),
|
|
meta: { permissionId: 40 },
|
|
// redirect: '/index',
|
|
children: [
|
|
// 充值审核========================================
|
|
{
|
|
path: 'rechargeAudit',
|
|
name: "rechargeAudit",
|
|
component: () => import("../views/audit/rechargeAudit.vue"),
|
|
meta: { permissionId: [11, 12] } // 对应"查看充值审核"id=11、"充值审批"id=12
|
|
},
|
|
// 退款审核
|
|
{
|
|
path: 'refundAudit',
|
|
name: "refundAudit",
|
|
component: () => import("../views/audit/refundAudit.vue"),
|
|
meta: { permissionId: [13, 14] } // 对应"查看退款审核"id=13、"退款审批"id=14
|
|
},
|
|
]
|
|
},
|
|
|
|
|
|
|
|
// 金币消耗
|
|
{
|
|
path: '/coinConsume',
|
|
name: "coinConsume",
|
|
component: () => import("../views/consume/coinConsume.vue"),
|
|
// redirect: '/coinConsume/add',
|
|
meta: { permissionId: 6 },
|
|
children: [
|
|
// 金币新增消耗
|
|
{
|
|
path: 'add',
|
|
name: "addCoinConsume",
|
|
component: () => import("../views/consume/addCoinConsume.vue"),
|
|
meta: { permissionId: 19 } // 对应"提交金币消耗"id=19
|
|
},
|
|
// 金币消耗明细详情
|
|
{
|
|
path: 'detail',
|
|
name: "coinConsumeDetail",
|
|
component: () => import("../views/consume/coinConsumeDetail.vue"),
|
|
meta: { permissionId: 20 } // 对应"查看金币消耗明细"id=20
|
|
}
|
|
]
|
|
},
|
|
|
|
// 汇率管理
|
|
{
|
|
path: '/rate',
|
|
name: "rate",
|
|
component: () => import("../views/managerecharge/rate.vue"),
|
|
meta: { permissionId: [15, 16] } // 对应"汇率查看"id=15、"汇率修改"id=16
|
|
},
|
|
// 金币充值
|
|
{
|
|
path: '/coinRecharge',
|
|
name: "coinRecharge",
|
|
component: () => import("../views/recharge/coinRecharge.vue"),
|
|
// redirect: '/coinRecharge/add',
|
|
children: [
|
|
// 金币新增充值
|
|
{
|
|
path: 'add',
|
|
name: "addCoinRecharge",
|
|
component: () => import("../views/recharge/addCoinRecharge.vue"),
|
|
meta: { permissionId: 17 } // 对应"提交金币充值"id=17
|
|
},
|
|
// 金币充值明细详情
|
|
{
|
|
path: 'detail',
|
|
name: "coinRechargeDetail",
|
|
component: () => import("../views/recharge/coinRechargeDetail.vue"),
|
|
meta: { permissionId: 18 } // 对应"查看金币充值明细"id=18
|
|
}
|
|
]
|
|
},
|
|
|
|
// 金币退款
|
|
{
|
|
path: '/coinRefund',
|
|
name: "coinRefund",
|
|
component: () => import("../views/refund/coinRefund.vue"),
|
|
// redirect: '/coinRefund/add',
|
|
meta: { permissionId: 7 },
|
|
children: [
|
|
// 金币新增退款
|
|
{
|
|
path: 'add',
|
|
name: "addCoinRefund",
|
|
component: () => import("../views/refund/addCoinRefund.vue"),
|
|
meta: { permissionId: 21 } // 对应"提交金币退款"id=21
|
|
},
|
|
// 金币退款明细详情
|
|
{
|
|
path: 'detail',
|
|
name: "coinRefundDetail",
|
|
component: () => import("../views/refund/coinRefundDetail.vue"),
|
|
meta: { permissionId: 22 } // 对应"查看金币退款明细"id=22
|
|
}
|
|
]
|
|
},
|
|
|
|
// 客户账户明细
|
|
{
|
|
path: '/usergold',
|
|
name: "usergold",
|
|
component: () => import("../views/usergold/clientCount.vue"),
|
|
// redirect: '/usergold/detail',
|
|
meta: { permissionId: 8 },
|
|
children: [
|
|
// 金币明细
|
|
{
|
|
path: 'detail',
|
|
name: "clientCountDetail",
|
|
component: () => import("../views/usergold/clientCountDetail.vue"),
|
|
meta: { permissionId: 23 } // 对应"查看金币明细"id=23
|
|
},
|
|
// 金币余额
|
|
{
|
|
path: 'balance',
|
|
name: "clientCountBalance",
|
|
component: () => import("../views/usergold/clientCountBalance.vue"),
|
|
meta: { permissionId: 24 } // 对应"查看金币余额"id=24
|
|
},
|
|
]
|
|
},
|
|
// 权限管理
|
|
{
|
|
path: '/permissions',
|
|
name: "permissions",
|
|
component: () => import("../views/permissions/permission.vue"),
|
|
meta: { permissionId: [25, 26, 27, 28, 29] } // 对应权限管理下的所有操作
|
|
},
|
|
// 没有权限
|
|
{
|
|
path: '/noPermission',
|
|
name: "noPermission",
|
|
component: () => import("../views/noPermissionPage.vue")
|
|
}
|
|
]
|
|
},
|
|
// 跳转页面(无需权限)
|
|
{
|
|
path: '/PasswordSuccess',
|
|
name: "PasswordSuccess",
|
|
component: () => import("../components/PasswordSuccess.vue")
|
|
}
|
|
];
|
|
|
|
// 创建路由实例
|
|
const router = createRouter({
|
|
history: createWebHashHistory(),
|
|
routes
|
|
});
|
|
|
|
// 全局拦截器:token过期处理
|
|
axios.interceptors.response.use(
|
|
response => response,
|
|
error => {
|
|
if (error.response && error.response.status === 401) {
|
|
localStorage.removeItem('token');
|
|
router.push({
|
|
name: 'login',
|
|
query: {
|
|
machineId: localStorage.getItem('machineId'),
|
|
expired: true
|
|
}
|
|
});
|
|
}
|
|
return Promise.reject(error);
|
|
}
|
|
);
|
|
|
|
// 工具函数:从菜单树提取所有权限ID
|
|
const getAllPermissionIds = (menuTree) => {
|
|
let permissionIds = [];
|
|
const traverse = (menuList) => {
|
|
menuList.forEach(menu => {
|
|
permissionIds.push(menu.id);
|
|
if (menu.children && menu.children.length > 0) {
|
|
traverse(menu.children);
|
|
}
|
|
});
|
|
};
|
|
traverse(menuTree);
|
|
return permissionIds;
|
|
};
|
|
|
|
// 存储管理员信息(全局可访问)
|
|
const adminData = ref(null);
|
|
|
|
// 获取管理员信息(返回Promise,方便路由守卫中使用)
|
|
export const getAdminData = async function () {
|
|
try {
|
|
const result = await request({
|
|
url: "/admin/userinfo",
|
|
|
|
});
|
|
adminData.value = result; // 存储管理员信息(包含roleId)
|
|
return result; // 返回结果,供路由守卫使用
|
|
} catch (error) {
|
|
console.log("获取管理员信息失败", error);
|
|
throw error; // 抛出错误,让路由守卫捕获
|
|
}
|
|
};
|
|
|
|
// 全局路由守卫
|
|
router.beforeEach(async (to, from, next) => {
|
|
const token = localStorage.getItem("token");
|
|
const machineId = localStorage.getItem("machineId");
|
|
|
|
// 1. 未登录:强制跳转到登录页
|
|
if (to.name !== "login" && !token) {
|
|
next(`/login?machineId=${machineId || ''}`);
|
|
return;
|
|
}
|
|
|
|
// 2. 已登录:处理权限验证
|
|
if (token) {
|
|
|
|
// 获取管理员信息
|
|
let roleId = null;
|
|
console.log('adminData:', adminData)
|
|
try {
|
|
await getAdminData(); // 等待管理员信息获取完成
|
|
roleId = adminData.value.roleId;
|
|
if (!roleId) {
|
|
throw new Error("未获取到roleId");
|
|
}
|
|
} catch (error) {
|
|
localStorage.removeItem('token'); // 清除token,强制重新登录
|
|
next(`/login?machineId=${machineId || ''}`);
|
|
return;
|
|
}
|
|
|
|
|
|
let userPermissionIds = [];
|
|
try {
|
|
const response = await request( {url: "/menu/tree",
|
|
data:{id: roleId}
|
|
});
|
|
console.log('roleId:', roleId)
|
|
console.log('response:', response)
|
|
console.log('userPermissionIds:', userPermissionIds)
|
|
if (response.code === 200 && response.data) {
|
|
userPermissionIds = getAllPermissionIds(response.data); // 提取权限id
|
|
console.log('userPermissionIds:', userPermissionIds)
|
|
}
|
|
} catch (error) {
|
|
console.error('获取菜单树失败:', error);
|
|
localStorage.removeItem('token');
|
|
next(`/login?machineId=${machineId || ''}`);
|
|
return;
|
|
}
|
|
|
|
// 2.4 权限验证(逻辑不变)
|
|
console.log('to.meta:',to.meta)
|
|
|
|
|
|
const requiresPermission = to.meta && to.meta.permissionId;
|
|
if (requiresPermission) {
|
|
const hasPermission = Array.isArray(requiresPermission)
|
|
? requiresPermission.some(id => userPermissionIds.includes(id))
|
|
: userPermissionIds.includes(requiresPermission);
|
|
|
|
if (!hasPermission) {
|
|
next('/noPermission');
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 3. 正常跳转
|
|
next();
|
|
});
|
|
|
|
export default router;
|