import { createRouter, createWebHistory } from "vue-router"; import { useAuthStore } from "../stores/auth"; const routes = [ { path: "/login", name: "login", component: () => import("../views/LoginView.vue") }, { path: "/", component: () => import("../layout/MainLayout.vue"), meta: { requiresAuth: true }, children: [ { path: "", name: "home", component: () => import("../views/HomeView.vue"), meta: { roles: ["SYS_ADMIN", "SALES", "LICENSE_OPS"] }, }, { path: "customers/:id", name: "customer-detail", component: () => import("../views/CustomerDetailView.vue"), meta: { roles: ["SYS_ADMIN", "SALES"], title: "客户详情" }, }, { path: "customers", name: "customers", component: () => import("../views/CustomersView.vue"), meta: { roles: ["SYS_ADMIN", "SALES"] }, }, { path: "projects", name: "projects", component: () => import("../views/ProjectsView.vue"), meta: { roles: ["SYS_ADMIN", "SALES"] }, }, { path: "deliveries/new", name: "delivery-new", component: () => import("../views/DeliveryBatchWizardView.vue"), meta: { roles: ["SYS_ADMIN", "SALES", "DELIVERY"], title: "新建交付批次" }, }, { path: "deliveries/:id", name: "delivery-detail", component: () => import("../views/DeliveryBatchDetailView.vue"), meta: { roles: ["SYS_ADMIN", "SALES", "DELIVERY"], title: "交付批次详情" }, }, { path: "deliveries", name: "deliveries", component: () => import("../views/DeliveriesView.vue"), meta: { roles: ["SYS_ADMIN", "SALES", "DELIVERY"], title: "交付管理" }, }, { path: "licenses/sn/new", name: "license-sn-new", component: () => import("../views/LicenseSnWizardView.vue"), meta: { roles: ["SYS_ADMIN", "SALES"], title: "新建许可 SN" }, }, { path: "licenses/sn/:id", name: "license-sn-detail", component: () => import("../views/LicenseSnDetailView.vue"), meta: { roles: ["SYS_ADMIN", "SALES"], title: "许可 SN 详情" }, }, { path: "licenses/sn", name: "license-sn-list", component: () => import("../views/LicenseSnListView.vue"), meta: { roles: ["SYS_ADMIN", "SALES"], title: "许可 SN" }, }, { path: "integration/environments", name: "integration-environments", component: () => import("../views/IntegrationEnvironmentsView.vue"), meta: { roles: ["SYS_ADMIN", "SALES", "LICENSE_OPS"], title: "集成环境" }, }, { path: "integration/product-lines", name: "integration-product-lines", component: () => import("../views/IntegrationProductLinesView.vue"), meta: { roles: ["SYS_ADMIN", "SALES", "LICENSE_OPS"], title: "产品线" }, }, { path: "integration/id-mappings", name: "integration-id-mappings", component: () => import("../views/IntegrationIdMappingView.vue"), meta: { roles: ["SYS_ADMIN", "SALES"], title: "ID 映射" }, }, { path: "integration/sku-mappings", name: "integration-sku-mappings", component: () => import("../views/IntegrationSkuMappingView.vue"), meta: { roles: ["SYS_ADMIN"], title: "SKU 映射" }, }, { path: "integration/feature-mappings", name: "integration-feature-mappings", component: () => import("../views/IntegrationFeatureMappingView.vue"), meta: { roles: ["SYS_ADMIN"], title: "特征映射" }, }, { path: "integration/json-templates", name: "integration-json-templates", component: () => import("../views/IntegrationJsonTemplateView.vue"), meta: { roles: ["SYS_ADMIN"], title: "JSON 模板" }, }, { path: "callbacks/:id", name: "callback-inbox-detail", component: () => import("../views/CallbackInboxDetailView.vue"), meta: { roles: ["SYS_ADMIN", "LICENSE_OPS"], title: "Callback 详情" }, }, { path: "callbacks", name: "callback-inbox", component: () => import("../views/CallbackInboxView.vue"), meta: { roles: ["SYS_ADMIN", "LICENSE_OPS"], title: "Callback 收件箱" }, }, { path: "contracts/new", name: "contract-new", component: () => import("../views/ContractWizardView.vue"), meta: { roles: ["SYS_ADMIN", "SALES"], title: "新建合同" }, }, { path: "contracts/:id", name: "contract-detail", component: () => import("../views/ContractDetailView.vue"), meta: { roles: ["SYS_ADMIN", "SALES"], title: "合同详情" }, }, { path: "contracts", name: "contracts", component: () => import("../views/ContractsView.vue"), meta: { roles: ["SYS_ADMIN", "SALES"], title: "合同管理" }, }, { path: "license-compare", name: "license-compare", component: () => import("../views/LayoutCompareView.vue"), meta: { roles: ["SYS_ADMIN", "SALES"] }, }, { path: "licenses", name: "licenses", component: () => import("../views/LicenseList.vue"), meta: { roles: ["SYS_ADMIN", "SALES"], title: "许可证管理" }, }, { path: "devices/:id", name: "device-detail", component: () => import("../views/DeviceDetailView.vue"), meta: { roles: ["SYS_ADMIN", "SALES", "LICENSE_OPS", "DELIVERY"], title: "设备详情" }, }, { path: "devices", name: "devices", component: () => import("../views/DeviceListView.vue"), meta: { roles: ["SYS_ADMIN", "SALES", "LICENSE_OPS", "DELIVERY"], title: "设备管理" }, }, { path: "todos", name: "todos", component: () => import("../views/TodoCenterView.vue"), meta: { roles: ["SYS_ADMIN", "SALES", "LICENSE_OPS"], title: "待办中心" }, }, { path: "notifications/settings", name: "notification-settings", component: () => import("../views/NotificationSettingsView.vue"), meta: { roles: ["SYS_ADMIN"], title: "通知设置" }, }, { path: "reports/contract-sn", name: "contract-sn-report", component: () => import("../views/ContractSnReportView.vue"), meta: { roles: ["SYS_ADMIN", "SALES"], title: "合同 SN 报表" }, }, { path: "reports/callback-stats", name: "callback-stats", component: () => import("../views/CallbackStatsView.vue"), meta: { roles: ["SYS_ADMIN", "LICENSE_OPS"], title: "Callback 统计" }, }, { path: "profile", name: "profile", component: () => import("../views/ProfileView.vue"), meta: { roles: ["SYS_ADMIN", "SALES", "LICENSE_OPS"], title: "个人设置" }, }, { path: "reports/project-health", name: "project-health", component: () => import("../views/ProjectHealthView.vue"), meta: { roles: ["SYS_ADMIN"], title: "项目健康度" }, }, { path: "audit", name: "audit", component: () => import("../views/AuditSearchView.vue"), meta: { roles: ["SYS_ADMIN"], title: "审计日志" }, }, ], }, { path: "/403", name: "forbidden", component: () => import("../views/ForbiddenView.vue") }, { path: "/layout-compare", name: "layout-compare", component: () => import("../views/LayoutCompareView.vue") }, { path: "/:pathMatch(.*)*", name: "notfound", component: () => import("../views/NotFoundView.vue") }, ]; const router = createRouter({ history: createWebHistory(), routes, }); function hasRoleAccess(metaRoles, userRoles) { if (!metaRoles || metaRoles.length === 0) return true; const set = new Set(userRoles || []); return metaRoles.some((r) => set.has(r)); } router.beforeEach((to) => { const auth = useAuthStore(); if (to.meta.requiresAuth && !auth.token) { return { name: "login", query: { redirect: to.fullPath } }; } if (to.meta.requiresAuth && to.meta.roles && !hasRoleAccess(to.meta.roles, auth.roles)) { return { name: "forbidden" }; } return true; }); export default router;