import { createRouter, createWebHistory } from 'vue-router' import { useAuthStore } from '@/stores/auth' import { isMobile } from '@/utils' const router = createRouter({ history: createWebHistory(), routes: [ { path: '/login', name: 'Login', component: () => import('@/views/Login.vue'), meta: { public: true }, }, { path: '/bind-wecom', name: 'BindWecom', component: () => import('@/views/BindWecom.vue'), meta: { public: true }, }, { path: '/bind-wechat', name: 'BindWechat', component: () => import('@/views/BindWechat.vue'), meta: { public: true }, }, { path: '/wecom-bind', name: 'WecomBind', component: () => import('@/views/WecomBind.vue'), meta: { public: true }, }, // Mobile routes (manager-facing) { path: '/m', component: () => import('@/components/MobileLayout.vue'), children: [ { path: '', name: 'MobileHome', component: () => import('@/views/mobile/Home.vue') }, { path: 'work', name: 'WorkCenter', component: () => import('@/views/mobile/WorkCenter.vue') }, { path: 'visit/new', name: 'VisitForm', component: () => import('@/views/mobile/VisitForm.vue') }, { path: 'visit/:id/edit', name: 'VisitEdit', component: () => import('@/views/mobile/VisitForm.vue') }, { path: 'work-plan/new', name: 'WorkPlanForm', component: () => import('@/views/mobile/WorkPlanForm.vue') }, { path: 'work-plan/:id/edit', name: 'WorkPlanEdit', component: () => import('@/views/mobile/WorkPlanForm.vue') }, { path: 'mini-biz/new', name: 'MiniBusinessForm', component: () => import('@/views/mobile/MiniBusinessForm.vue') }, { path: 'mini-biz/:id/edit', name: 'MiniBusinessEdit', component: () => import('@/views/mobile/MiniBusinessForm.vue') }, { path: 'key-visit/new', name: 'KeyVisitForm', component: () => import('@/views/mobile/KeyVisitForm.vue') }, { path: 'key-visit/:id/edit', name: 'KeyVisitEdit', component: () => import('@/views/mobile/KeyVisitForm.vue') }, { path: 'note/new', name: 'DailyNoteForm', component: () => import('@/views/mobile/DailyNoteForm.vue') }, { path: 'note/:id/edit', name: 'DailyNoteEdit', component: () => import('@/views/mobile/DailyNoteForm.vue') }, { path: 'visits', name: 'VisitsList', component: () => import('@/views/mobile/VisitsList.vue') }, { path: 'notes', name: 'NotesList', component: () => import('@/views/mobile/NotesList.vue') }, { path: 'plans', name: 'PlansList', component: () => import('@/views/mobile/PlansList.vue') }, { path: 'mini-biz', name: 'MiniBizList', component: () => import('@/views/mobile/MiniBizList.vue') }, { path: 'key-visits', name: 'KeyVisitsList', component: () => import('@/views/mobile/KeyVisitsList.vue') }, { path: 'leaves', name: 'LeavesList', component: () => import('@/views/mobile/LeavesList.vue') }, { path: 'leave/new', name: 'LeaveForm', component: () => import('@/views/mobile/LeaveForm.vue') }, { path: 'leave/:id/edit', name: 'LeaveEdit', component: () => import('@/views/mobile/LeaveForm.vue') }, ], }, // Desktop routes (director/leader-facing) { path: '/', component: () => import('@/components/DesktopLayout.vue'), children: [ { path: '', name: 'Dashboard', component: () => import('@/views/desktop/Dashboard.vue') }, { path: 'weekly-report', name: 'WeeklyReport', component: () => import('@/views/desktop/WeeklyReport.vue') }, { path: 'light-board', name: 'LightBoard', component: () => import('@/views/desktop/LightBoard.vue') }, { path: 'work-plans', name: 'WorkPlans', component: () => import('@/views/desktop/WorkPlans.vue') }, { path: 'mini-business', name: 'MiniBusiness', component: () => import('@/views/desktop/MiniBusiness.vue') }, { path: 'key-visits', name: 'KeyVisits', component: () => import('@/views/desktop/KeyVisits.vue') }, { path: 'leaves', name: 'Leaves', component: () => import('@/views/desktop/Leaves.vue') }, { path: 'workspace', name: 'ManagerWorkspace', component: () => import('@/views/desktop/ManagerWorkspace.vue') }, { path: 'customers', name: 'CustomerManage', component: () => import('@/views/desktop/CustomerManage.vue') }, { path: 'users', name: 'UserManage', component: () => import('@/views/desktop/UserManage.vue') }, { path: 'audit-log', name: 'AuditLog', component: () => import('@/views/desktop/AuditLog.vue') }, { path: 'settings', name: 'Settings', component: () => import('@/views/desktop/Settings.vue') }, ], }, ], }) router.beforeEach((to, _from, next) => { const auth = useAuthStore() // Handle WeChat Work OAuth silent login callback: ?token=JWT // Only strip the token if it's a valid JWT — bind tokens (UUID hex) must // survive so pages like WecomBind can read them. const tokenParam = to.query.token as string if (tokenParam && tokenParam.split('.').length === 3) { // Save token to auth store (the JWT contains user_id, name, role, theme) try { const payload = JSON.parse(atob(tokenParam.split('.')[1])) auth.saveLogin({ access_token: tokenParam, user_id: payload.user_id, name: payload.name, role: payload.role, theme: payload.theme, }) // Remove token from URL only on successful JWT decode const cleanQuery = { ...to.query } delete cleanQuery.token next({ path: to.path, query: cleanQuery, replace: true }) return } catch (_) { /* invalid JWT — leave token for page to handle */ } } if (to.meta.public) { next() return } if (!auth.isLoggedIn) { next('/login') return } // Auto-redirect on FIRST entry only (no previous route = fresh page load) // Don't interfere with manual navigation (user clicked switch button) const viewOverride = to.query.view as string if (!viewOverride && !_from.name) { const onMobile = isMobile() if (onMobile && to.path === '/') { next('/m') return } if (!onMobile && to.path.startsWith('/m')) { next('/') return } } next() }) export default router