index.ts 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. import {
  2. createRouter,
  3. createWebHashHistory,
  4. type RouteRecordRaw
  5. } from 'vue-router'
  6. import { usePermissionStoreHook } from '@/stores/modules/permission'
  7. const Layouts = () => import('@/layouts/index.vue')
  8. /**
  9. * 路由 name 与 FunctionList key 的映射
  10. * 一级菜单: route name → FunctionList 一级 key
  11. * 二级菜单(Settings 子路由): route name → FunctionList Settings 下的 key
  12. */
  13. const menuPermissionMap: Record<string, string> = {
  14. // 一级菜单
  15. Settings: 'Settings',
  16. RemoteViewing: 'Remote',
  17. StandardProtocol: 'Protocol',
  18. }
  19. const subMenuPermissionMap: Record<string, string> = {
  20. // Settings 下的二级菜单
  21. SystemSettings: 'System_Settings',
  22. ImageDisplay: 'Image_Display',
  23. AudioVideo: 'Audio_Video',
  24. NetSettings: 'Network_Settings',
  25. AlarmSettings: 'Alarm_Settings',
  26. }
  27. export const constantRoutes: RouteRecordRaw[] = [
  28. {
  29. path: '/',
  30. name: 'PreviewLayout',
  31. component: Layouts,
  32. redirect: '/preview',
  33. children: [
  34. {
  35. path: '/preview',
  36. component: () => import('@/views/preview/index.vue'),
  37. name: 'Preview',
  38. meta: {
  39. title: 'Preview',
  40. isShow: true,
  41. icon: 'View'
  42. }
  43. }
  44. ]
  45. },
  46. {
  47. path: '/settings',
  48. name: 'Settings',
  49. component: Layouts,
  50. redirect: '/settings',
  51. meta: {
  52. title: 'Settings',
  53. isShow: true,
  54. icon: 'Setting'
  55. },
  56. children: [
  57. {
  58. path: '/settings/systemSettings',
  59. component: () => import('@/views/settings/systemSettings/index.vue'),
  60. name: 'SystemSettings',
  61. meta: {
  62. title: 'System Settings'
  63. }
  64. },
  65. {
  66. path: '/settings/imageDisplay',
  67. component: () => import('@/views/settings/imageDisplay/index.vue'),
  68. name: 'ImageDisplay',
  69. meta: {
  70. title: 'Image Display'
  71. }
  72. },
  73. {
  74. path: '/settings/audioVideo',
  75. component: () => import('@/views/settings/audioVideo/index.vue'),
  76. name: 'AudioVideo',
  77. meta: {
  78. title: 'Audio & Video'
  79. }
  80. },
  81. {
  82. path: '/settings/netSetting',
  83. component: () => import('@/views/settings/netSettings/index.vue'),
  84. name: 'NetSettings',
  85. meta: {
  86. title: 'Network Settings'
  87. }
  88. },
  89. {
  90. path: '/settings/alarmSettings',
  91. component: () => import('@/views/settings/alarmSettings/index.vue'),
  92. name: 'AlarmSettings',
  93. meta: {
  94. title: 'Alarm Settings'
  95. }
  96. }
  97. ]
  98. },
  99. {
  100. path: '/',
  101. name: 'RemoteLayout',
  102. component: Layouts,
  103. redirect: '/remoteViewing',
  104. children: [
  105. {
  106. path: '/remoteViewing',
  107. component: () => import('@/views/remoteViewing/index.vue'),
  108. name: 'RemoteViewing',
  109. meta: {
  110. title: 'Remote',
  111. isShow: true,
  112. icon: 'Monitor'
  113. }
  114. }
  115. ]
  116. },
  117. {
  118. path: '/',
  119. name: 'ProtocolLayout',
  120. component: Layouts,
  121. redirect: '/standardProtocol',
  122. children: [
  123. {
  124. path: '/standardProtocol',
  125. component: () => import('@/views/standardProtocol/index.vue'),
  126. name: 'StandardProtocol',
  127. meta: {
  128. title: 'Protocol',
  129. isShow: true,
  130. icon: 'Document'
  131. }
  132. }
  133. ]
  134. },
  135. ]
  136. export const history = createWebHashHistory()
  137. const router = createRouter({
  138. history,
  139. routes: [
  140. {
  141. path: '/login',
  142. component: () => import('@/views/login/index.vue'),
  143. name: 'Login'
  144. }
  145. ]
  146. })
  147. export default router
  148. /** 清除所有动态注册的路由 */
  149. function resetRouter() {
  150. // 移除所有 constantRoutes 中定义的路由(按 name 移除)
  151. const routeNames: string[] = []
  152. constantRoutes.forEach((route) => {
  153. if (route.name) {
  154. routeNames.push(route.name as string)
  155. }
  156. if (route.children) {
  157. route.children.forEach((child) => {
  158. if (child.name) {
  159. routeNames.push(child.name as string)
  160. }
  161. })
  162. }
  163. })
  164. routeNames.forEach((name) => {
  165. if (router.hasRoute(name)) {
  166. router.removeRoute(name)
  167. }
  168. })
  169. }
  170. /** 根据权限过滤路由并注册 */
  171. export function setRouter() {
  172. // 先清除旧路由,避免重复注册
  173. resetRouter()
  174. const permissionStore = usePermissionStoreHook()
  175. const filteredRoutes = constantRoutes
  176. .filter((route) => {
  177. // 对于有单个子路由的一级菜单(Preview / Remote / Protocol)
  178. if (route.children && route.children.length === 1) {
  179. const child = route.children[0]
  180. const routeName = child.name as string
  181. const permKey = menuPermissionMap[routeName]
  182. if (permKey && !permissionStore.isMenuVisible(permKey)) {
  183. return false
  184. }
  185. }
  186. // 对于 Settings 这种有多个子路由的一级菜单
  187. if (route.name && menuPermissionMap[route.name as string]) {
  188. const permKey = menuPermissionMap[route.name as string]
  189. if (!permissionStore.isMenuVisible(permKey)) {
  190. return false
  191. }
  192. }
  193. return true
  194. })
  195. .map((route) => {
  196. // 过滤 Settings 的子路由
  197. if (route.name === 'Settings' && route.children) {
  198. const filteredChildren = route.children.filter((child) => {
  199. const childName = child.name as string
  200. const subPermKey = subMenuPermissionMap[childName]
  201. if (subPermKey) {
  202. return permissionStore.isSubMenuVisible(subPermKey)
  203. }
  204. return true
  205. })
  206. return { ...route, children: filteredChildren }
  207. }
  208. return route
  209. })
  210. // 如果 Settings 的子路由全被过滤掉了,移除 Settings 本身
  211. .filter((route) => {
  212. if (route.name === 'Settings' && route.children && route.children.length === 0) {
  213. return false
  214. }
  215. return true
  216. })
  217. filteredRoutes.forEach((item) => {
  218. router.addRoute(item)
  219. })
  220. }