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.

325 lines
11 KiB

2 months ago
2 months ago
2 months ago
1 month ago
1 month ago
1 month ago
1 month ago
  1. import {createRouter, createWebHashHistory} from 'vue-router';
  2. import axios from "axios";
  3. import {storeToRefs} from "pinia";
  4. import {useAdminStore} from "@/store/index.js";
  5. // 路由定义(包含权限映射 meta.permissionId)
  6. const routes = [
  7. {
  8. path: '/',
  9. redirect: "/login"
  10. },
  11. {
  12. path: "/login",
  13. name: "login",
  14. component: () => import("../views/login.vue"),
  15. },
  16. {
  17. meta: {requireAuth: true},
  18. path: '/',
  19. component: () => import("../views/home.vue"),
  20. children: [
  21. // 工作台
  22. {
  23. path: '/workspace',
  24. name: "workspace",
  25. component: () => import("../views/workspace/index.vue"),
  26. meta: {permissionId: 10} // 对应"工作台展示"id=10
  27. },
  28. // 审核
  29. {
  30. path: '/audit',
  31. name: "audit",
  32. component: () => import("../views/audit/audit.vue"),
  33. meta: {permissionId: 40},
  34. // redirect: '/index',
  35. children: [
  36. // 充值审核
  37. {
  38. path: 'rechargeAudit',
  39. name: "rechargeAudit",
  40. component: () => import("../views/audit/rechargeAudit.vue"),
  41. meta: {permissionId: [11, 12]} // 对应"查看充值审核"id=11、"充值审批"id=12
  42. },
  43. // 退款审核
  44. {
  45. path: 'refundAudit',
  46. name: "refundAudit",
  47. component: () => import("../views/audit/refundAudit.vue"),
  48. meta: {permissionId: [13, 14]} // 对应"查看退款审核"id=13、"退款审批"id=14
  49. },
  50. ]
  51. },
  52. // 金币消耗
  53. {
  54. path: '/coinConsume',
  55. name: "coinConsume",
  56. component: () => import("../views/consume/coinConsume.vue"),
  57. // redirect: '/coinConsume/add',
  58. meta: {permissionId: 6},
  59. children: [
  60. // 金币新增消耗
  61. {
  62. path: 'add',
  63. name: "addCoinConsume",
  64. component: () => import("../views/consume/addCoinConsume.vue"),
  65. meta: {permissionId: 19} // 对应"提交金币消耗"id=19
  66. },
  67. // 金币消耗明细详情
  68. {
  69. path: 'detail',
  70. name: "coinConsumeDetail",
  71. component: () => import("../views/consume/coinConsumeDetail.vue"),
  72. meta: {permissionId: 20} // 对应"查看金币消耗明细"id=20
  73. }
  74. ]
  75. },
  76. // 金豆消耗
  77. {
  78. path: '/beanConsume',
  79. name: "beanConsume",
  80. component: () => import("../views/consume/beanConsume.vue"),
  81. meta: {permissionId: 6},
  82. children: [
  83. // 金豆新增消耗
  84. {
  85. path: 'add',
  86. name: "addBeanConsume",
  87. component: () => import("../views/consume/addBeanConsume.vue"),
  88. meta: {permissionId: 23} // 对应"提交金豆消耗"id=?
  89. },
  90. // 直播
  91. {
  92. path: 'live',
  93. name: "liveStream",
  94. component: () => import("../views/consume/liveStream.vue"),
  95. meta: {permissionId: 24} // 对应"直播"id=?
  96. },
  97. // 铁粉
  98. {
  99. path: 'fan',
  100. name: "dieHardFan",
  101. component: () => import("../views/consume/dieHardFan.vue"),
  102. meta: {permissionId: 25} // 对应"铁粉"id=?
  103. },
  104. // 文章视频
  105. {
  106. path: 'article',
  107. name: "articleVideo",
  108. component: () => import("../views/consume/articleVideo.vue"),
  109. meta: {permissionId: 26} // 对应"文章视频"id=?
  110. }
  111. ]
  112. },
  113. // 汇率管理
  114. {
  115. path: '/rate',
  116. name: "rate",
  117. component: () => import("../views/managerecharge/rate.vue"),
  118. meta: {permissionId: [15, 16]} // 对应"汇率查看"id=15、"汇率修改"id=16
  119. },
  120. // 金币充值
  121. {
  122. path: '/coinRecharge',
  123. name: "coinRecharge",
  124. component: () => import("../views/recharge/coinRecharge.vue"),
  125. // redirect: '/coinRecharge/add',
  126. children: [
  127. // 金币新增充值
  128. {
  129. path: 'add',
  130. name: "addCoinRecharge",
  131. component: () => import("../views/recharge/addCoinRecharge.vue"),
  132. meta: {permissionId: 17} // 对应"提交金币充值"id=17
  133. },
  134. // 金币充值明细详情
  135. {
  136. path: 'detail',
  137. name: "coinRechargeDetail",
  138. component: () => import("../views/recharge/coinRechargeDetail.vue"),
  139. meta: {permissionId: 18} // 对应"查看金币充值明细"id=18
  140. }
  141. ]
  142. },
  143. // 金币退款
  144. {
  145. path: '/coinRefund',
  146. name: "coinRefund",
  147. component: () => import("../views/refund/coinRefund.vue"),
  148. // redirect: '/coinRefund/add',
  149. meta: {permissionId: 7},
  150. children: [
  151. // 金币新增退款
  152. {
  153. path: 'add',
  154. name: "addCoinRefund",
  155. component: () => import("../views/refund/addCoinRefund.vue"),
  156. meta: {permissionId: 21} // 对应"提交金币退款"id=21
  157. },
  158. // 金币退款明细详情
  159. {
  160. path: 'detail',
  161. name: "coinRefundDetail",
  162. component: () => import("../views/refund/coinRefundDetail.vue"),
  163. meta: {permissionId: 22} // 对应"查看金币退款明细"id=22
  164. }
  165. ]
  166. },
  167. // 客户账户明细
  168. {
  169. path: '/usergold',
  170. name: "usergold",
  171. component: () => import("../views/usergold/clientCount.vue"),
  172. // redirect: '/usergold/detail',
  173. meta: {permissionId: 8},
  174. children: [
  175. // 金币明细
  176. {
  177. path: 'detail',
  178. name: "clientCountDetail",
  179. component: () => import("../views/usergold/clientCountDetail.vue"),
  180. meta: {permissionId: 23} // 对应"查看金币明细"id=23
  181. },
  182. // 金币余额
  183. {
  184. path: 'balance',
  185. name: "clientCountBalance",
  186. component: () => import("../views/usergold/clientCountBalance.vue"),
  187. meta: {permissionId: 24} // 对应"查看金币余额"id=24
  188. },
  189. ]
  190. },
  191. // 权限管理
  192. {
  193. path: '/permissions',
  194. name: "permissions",
  195. component: () => import("../views/permissions/permission.vue"),
  196. meta: {permissionId: [25, 26, 27, 28, 29]} // 对应权限管理下的所有操作
  197. },
  198. // 没有权限
  199. {
  200. path: '/noPermission',
  201. name: "noPermission",
  202. component: () => import("../views/noPermissionPage.vue")
  203. }
  204. ]
  205. },
  206. // 跳转页面(无需权限)
  207. {
  208. path: '/PasswordSuccess',
  209. name: "PasswordSuccess",
  210. component: () => import("../components/PasswordSuccess.vue")
  211. }
  212. ];
  213. // 创建路由实例
  214. const router = createRouter({
  215. history: createWebHashHistory(),
  216. routes
  217. });
  218. // 全局拦截器:token过期处理
  219. axios.interceptors.response.use(
  220. response => response,
  221. error => {
  222. if (error.response && error.response.status === 401) {
  223. localStorage.removeItem('token');
  224. router.push({
  225. name: 'login',
  226. query: {
  227. machineId: localStorage.getItem('machineId'),
  228. expired: true
  229. }
  230. });
  231. }
  232. return Promise.reject(error);
  233. }
  234. );
  235. // 工具函数:从菜单树提取所有权限ID
  236. const getAllPermissionIds = (menuTree) => {
  237. let permissionIds = [];
  238. const traverse = (menuList) => {
  239. menuList.forEach(menu => {
  240. permissionIds.push(menu.id);
  241. if (menu.children && menu.children.length > 0) {
  242. traverse(menu.children);
  243. }
  244. });
  245. };
  246. traverse(menuTree);
  247. return permissionIds;
  248. };
  249. // 全局路由守卫
  250. router.beforeEach(async (to, from, next) => {
  251. const adminStore = useAdminStore()
  252. const { adminData, menuTree } = storeToRefs(adminStore)
  253. const token = localStorage.getItem("token");
  254. const machineId = localStorage.getItem("machineId");
  255. // 1. 未登录:强制跳转到登录页
  256. if (to.name !== "login" && !token) {
  257. next(`/login?machineId=${machineId || ''}`);
  258. return;
  259. }
  260. // 2. 已登录:处理权限验证
  261. if (token) {
  262. // 获取管理员信息
  263. let roleId = null;
  264. console.log('adminData:', adminData)
  265. try {
  266. roleId = adminData.value.roleId;
  267. if (!roleId) {
  268. localStorage.removeItem('token'); // 清除token,强制重新登录
  269. next(`/login?machineId=${machineId || ''}`);
  270. return;
  271. }
  272. } catch (error) {
  273. localStorage.removeItem('token'); // 清除token,强制重新登录
  274. adminStore.clearState()
  275. next(`/login?machineId=${machineId || ''}`);
  276. return;
  277. }
  278. let userPermissionIds = [];
  279. // 拿权限id
  280. userPermissionIds = getAllPermissionIds(menuTree.value)
  281. // 2.4 权限验证(逻辑不变)
  282. console.log('to.meta:', to.meta)
  283. const requiresPermission = to.meta && to.meta.permissionId;
  284. if (requiresPermission) {
  285. const hasPermission = Array.isArray(requiresPermission)
  286. ? requiresPermission.some(id => userPermissionIds.includes(id))
  287. : userPermissionIds.includes(requiresPermission);
  288. if (!hasPermission) {
  289. next('/noPermission');
  290. return;
  291. }
  292. }
  293. }
  294. // 3. 正常跳转
  295. next();
  296. });
  297. export default router;