2026-05-01 20:39:09 +08:00
|
|
|
import { createRouter, createWebHistory } from 'vue-router'
|
2026-04-28 11:33:17 +08:00
|
|
|
|
2026-05-14 13:12:42 +08:00
|
|
|
import { isChunkLoadError, reloadForStaleChunk } from '@/lib/chunk-reload'
|
2026-05-01 20:39:09 +08:00
|
|
|
import { useAuthStore } from '@/stores/auth'
|
|
|
|
|
import { pinia } from '@/stores/pinia'
|
2026-04-28 11:33:17 +08:00
|
|
|
|
|
|
|
|
export const router = createRouter({
|
|
|
|
|
history: createWebHistory(),
|
|
|
|
|
routes: [
|
|
|
|
|
{
|
2026-05-01 20:39:09 +08:00
|
|
|
path: '/login',
|
|
|
|
|
name: 'login',
|
|
|
|
|
component: () => import('@/views/LoginView.vue'),
|
|
|
|
|
meta: { title: '登录' },
|
2026-04-28 11:33:17 +08:00
|
|
|
},
|
|
|
|
|
{
|
2026-05-01 20:39:09 +08:00
|
|
|
path: '/',
|
|
|
|
|
component: () => import('@/layouts/AppShell.vue'),
|
2026-04-28 11:33:17 +08:00
|
|
|
meta: { requiresAuth: true },
|
|
|
|
|
children: [
|
2026-05-01 20:39:09 +08:00
|
|
|
{ path: '', redirect: '/admin-users' },
|
2026-04-29 00:02:46 +08:00
|
|
|
{
|
2026-05-01 20:39:09 +08:00
|
|
|
path: 'admin-users',
|
|
|
|
|
name: 'admin-users',
|
|
|
|
|
component: () => import('@/views/AdminUsersView.vue'),
|
|
|
|
|
meta: { title: '用户管理' },
|
2026-04-29 00:02:46 +08:00
|
|
|
},
|
2026-04-29 22:07:41 +08:00
|
|
|
{
|
2026-05-01 20:39:09 +08:00
|
|
|
path: 'kol-subscriptions',
|
|
|
|
|
name: 'kol-subscriptions',
|
|
|
|
|
component: () => import('@/views/KolSubscriptionsView.vue'),
|
|
|
|
|
meta: { title: '订阅包审批' },
|
2026-04-29 22:07:41 +08:00
|
|
|
},
|
2026-04-28 11:33:17 +08:00
|
|
|
{
|
2026-05-01 20:39:09 +08:00
|
|
|
path: 'accounts',
|
|
|
|
|
name: 'accounts',
|
|
|
|
|
component: () => import('@/views/AccountsView.vue'),
|
|
|
|
|
meta: { title: '操作员管理' },
|
2026-04-28 11:33:17 +08:00
|
|
|
},
|
|
|
|
|
{
|
2026-05-01 20:39:09 +08:00
|
|
|
path: 'audits',
|
|
|
|
|
name: 'audits',
|
|
|
|
|
component: () => import('@/views/AuditLogsView.vue'),
|
|
|
|
|
meta: { title: '审计日志' },
|
2026-04-28 11:33:17 +08:00
|
|
|
},
|
2026-05-06 12:56:39 +08:00
|
|
|
{
|
|
|
|
|
path: 'jobs',
|
|
|
|
|
name: 'jobs',
|
|
|
|
|
component: () => import('@/views/JobsView.vue'),
|
|
|
|
|
meta: { title: '任务中心' },
|
|
|
|
|
},
|
2026-05-20 10:46:49 +08:00
|
|
|
{
|
|
|
|
|
path: 'scheduler',
|
|
|
|
|
name: 'scheduler',
|
|
|
|
|
component: () => import('@/views/SchedulerView.vue'),
|
|
|
|
|
meta: { title: '调度中心' },
|
|
|
|
|
},
|
2026-04-29 17:10:17 +08:00
|
|
|
{
|
2026-05-01 20:39:09 +08:00
|
|
|
path: 'site-domain-mappings',
|
|
|
|
|
name: 'site-domain-mappings',
|
|
|
|
|
component: () => import('@/views/SiteDomainMappingsView.vue'),
|
|
|
|
|
meta: { title: '站点映射' },
|
2026-04-29 17:10:17 +08:00
|
|
|
},
|
2026-05-26 01:19:01 +08:00
|
|
|
{
|
|
|
|
|
path: 'object-storage',
|
|
|
|
|
name: 'object-storage',
|
|
|
|
|
component: () => import('@/views/ObjectStorageView.vue'),
|
|
|
|
|
meta: { title: '对象存储' },
|
|
|
|
|
},
|
2026-05-25 19:23:49 +08:00
|
|
|
{
|
|
|
|
|
path: 'desktop-client/releases',
|
|
|
|
|
name: 'desktop-client-releases',
|
|
|
|
|
component: () => import('@/views/DesktopClientReleasesView.vue'),
|
|
|
|
|
meta: { title: '客户端版本' },
|
|
|
|
|
},
|
2026-05-05 20:48:14 +08:00
|
|
|
{
|
|
|
|
|
path: 'compliance/policy',
|
|
|
|
|
name: 'compliance-policy',
|
|
|
|
|
component: () => import('@/views/compliance/CompliancePolicyView.vue'),
|
|
|
|
|
meta: { title: '全局合规策略' },
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
path: 'compliance/dictionaries',
|
|
|
|
|
name: 'compliance-dictionaries',
|
|
|
|
|
component: () => import('@/views/compliance/ComplianceDictionariesView.vue'),
|
|
|
|
|
meta: { title: '合规词库' },
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
path: 'compliance/dictionaries/new',
|
|
|
|
|
name: 'compliance-dictionary-new',
|
|
|
|
|
component: () => import('@/views/compliance/ComplianceDictionaryEditView.vue'),
|
|
|
|
|
meta: { title: '新建合规词库' },
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
path: 'compliance/dictionaries/:id/edit',
|
|
|
|
|
name: 'compliance-dictionary-edit',
|
|
|
|
|
component: () => import('@/views/compliance/ComplianceDictionaryEditView.vue'),
|
|
|
|
|
meta: { title: '编辑合规词库' },
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
path: 'compliance/manual-reviews',
|
|
|
|
|
name: 'compliance-manual-reviews',
|
|
|
|
|
component: () => import('@/views/compliance/ComplianceManualReviewsView.vue'),
|
|
|
|
|
meta: { title: '人工审阅' },
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
path: 'compliance/manual-reviews/:id',
|
|
|
|
|
name: 'compliance-manual-review-detail',
|
|
|
|
|
component: () => import('@/views/compliance/ComplianceManualReviewDetailView.vue'),
|
|
|
|
|
meta: { title: '人工审阅详情' },
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
path: 'compliance/records',
|
|
|
|
|
name: 'compliance-records',
|
|
|
|
|
component: () => import('@/views/compliance/ComplianceRecordsView.vue'),
|
|
|
|
|
meta: { title: '检测记录' },
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
path: 'compliance/stats',
|
|
|
|
|
name: 'compliance-stats',
|
|
|
|
|
component: () => import('@/views/compliance/ComplianceStatsView.vue'),
|
|
|
|
|
meta: { title: '合规统计' },
|
|
|
|
|
},
|
2026-04-28 11:33:17 +08:00
|
|
|
{
|
2026-05-01 20:39:09 +08:00
|
|
|
path: 'profile',
|
|
|
|
|
name: 'profile',
|
|
|
|
|
component: () => import('@/views/ProfileView.vue'),
|
|
|
|
|
meta: { title: '个人资料' },
|
2026-04-28 11:33:17 +08:00
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
{
|
2026-05-01 20:39:09 +08:00
|
|
|
path: '/:pathMatch(.*)*',
|
|
|
|
|
redirect: '/',
|
2026-04-28 11:33:17 +08:00
|
|
|
},
|
|
|
|
|
],
|
2026-05-01 20:39:09 +08:00
|
|
|
})
|
2026-04-28 11:33:17 +08:00
|
|
|
|
|
|
|
|
router.beforeEach((to) => {
|
2026-05-01 20:39:09 +08:00
|
|
|
const auth = useAuthStore(pinia)
|
2026-04-28 11:33:17 +08:00
|
|
|
if (!auth.initialized) {
|
2026-05-01 20:39:09 +08:00
|
|
|
auth.hydrate()
|
2026-04-28 11:33:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (to.meta.requiresAuth && !auth.isAuthenticated) {
|
|
|
|
|
return {
|
2026-05-01 20:39:09 +08:00
|
|
|
name: 'login',
|
|
|
|
|
query: to.fullPath !== '/' ? { redirect: to.fullPath } : undefined,
|
|
|
|
|
}
|
2026-04-28 11:33:17 +08:00
|
|
|
}
|
|
|
|
|
|
2026-05-01 20:39:09 +08:00
|
|
|
if (to.name === 'login' && auth.isAuthenticated) {
|
|
|
|
|
return { name: 'admin-users' }
|
2026-04-28 11:33:17 +08:00
|
|
|
}
|
|
|
|
|
|
2026-05-01 20:39:09 +08:00
|
|
|
return true
|
|
|
|
|
})
|
2026-04-28 11:33:17 +08:00
|
|
|
|
|
|
|
|
router.afterEach((to) => {
|
2026-05-01 20:39:09 +08:00
|
|
|
if (typeof document !== 'undefined') {
|
|
|
|
|
const t = (to.meta.title as string | undefined) ?? '运营后台'
|
|
|
|
|
document.title = `${t} · 省心推`
|
2026-04-28 11:33:17 +08:00
|
|
|
}
|
2026-05-01 20:39:09 +08:00
|
|
|
})
|
2026-05-14 13:12:42 +08:00
|
|
|
|
|
|
|
|
router.onError((err) => {
|
|
|
|
|
if (isChunkLoadError(err)) {
|
|
|
|
|
reloadForStaleChunk()
|
|
|
|
|
}
|
|
|
|
|
})
|