import {createApp} from 'vue' import {createRouter, createWebHistory} from "vue-router"; import routes from "~/routes"; // @ts-ignore import wx from 'weixin-js-sdk'; import App from './App.vue' import 'vant/lib/index.css' import 'leaflet/dist/leaflet.css' import '~/fontawesome/all.css'; import './index.less' // @ts-ignore import useUser from '~/store/user' import useOrg from "~/store/org"; import cookie from "~/utils/cookie"; import {CurrentOrgId, CurrentUserRole, HtyAuthToken, HtySudoToken, HtyUnionIDToken, pad} from "~/utils"; import {HtyRoles, HtyStates, UserStates} from "~/types"; import useTimer from "~/store/timer"; const router = createRouter({ history: createWebHistory(), routes }) const weixin = { // @ts-ignore install: app => { // @ts-ignore app.config.globalProperties.$weixin = wx; } } // @ts-ignore Date.prototype.toJSON = function () { let year = this.getFullYear(), month = this.getMonth() + 1, date = this.getDate(), hour = this.getHours(), minute = this.getMinutes(), second = this.getSeconds(); return [year, pad(month), pad(date)].join('-') + 'T' + [pad(hour), pad(minute), pad(second)].join(':') } const parseCurrentOrgIdFromToken = (token: string | null): string | undefined => { if (!token) return undefined; try { const tokenParts = token.split('.'); if (tokenParts.length < 2) return undefined; const payloadRaw = tokenParts[1].replace(/-/g, '+').replace(/_/g, '/'); const payloadRawWithPadding = payloadRaw.padEnd(Math.ceil(payloadRaw.length / 4) * 4, '='); const payloadJson = decodeURIComponent( atob(payloadRawWithPadding) .split('') .map((char) => `%${(`00${char.charCodeAt(0).toString(16)}`).slice(-2)}`) .join('') ); const payload = JSON.parse(payloadJson) as Record; if (typeof payload.current_org_id === 'string' && payload.current_org_id) { return payload.current_org_id; } if (typeof payload.sub === 'string' && payload.sub.length > 0) { const subjectPayload = JSON.parse(payload.sub) as Record; if (typeof subjectPayload.current_org_id === 'string' && subjectPayload.current_org_id) { return subjectPayload.current_org_id; } } return undefined; } catch (_error) { return undefined; } }; router.beforeEach(async (to, from , next) => { try { document.title = to.meta.title as string; let { store, read, login, logout, chooseRole, getUnreadTongzhis, set_editing } = useUser(); let { store: orgStore, loadMyOrgs, switchOrg, loadMyDepartments, switchDepartment } = useOrg(); set_editing(false) store.unionid = (store.unionid || cookie.get(HtyUnionIDToken) || '').toString(); if (!store.current.hty_id) { if (window.localStorage.getItem(HtyAuthToken) && window.localStorage.getItem(HtySudoToken)) { await read(); } else { window.localStorage.removeItem(HtyAuthToken); window.localStorage.removeItem(HtySudoToken); let userStatus = Number(to.query.status || UserStates.Anonymous); if (userStatus === UserStates.Registered) { // 已注册,登录获取用户信息 let new_unionid = to.query.unionid; if(!store.unionid || (new_unionid && new_unionid !== store.unionid)) { if(new_unionid) { cookie.set(HtyUnionIDToken, new_unionid); await login(new_unionid.toString()) } } else { await login(store.unionid) } } else { if (to.path !== '/' && !to.path.startsWith('/guest')) { await router.replace('/') } next() return } } } // switched unionid(URL 与当前会话不一致时) if (to.query.unionid && store.unionid !== to.query.unionid) { const rawQ = to.query.unionid; const qUnionStr = String(Array.isArray(rawQ) ? rawQ[0] : rawQ || ''); // 已登录且 URL 中的 unionid 与当前用户不同:多为带毒分享链接,剥离身份参数而非 logout if (store.current.hty_id && qUnionStr) { const cur = store.current as { union_id?: string }; const currentUnion = String( cur.union_id != null && cur.union_id !== '' ? cur.union_id : store.unionid || '' ); if (currentUnion && qUnionStr !== currentUnion) { const nextQuery = { ...to.query } as Record; delete nextQuery.unionid; delete nextQuery.openid; delete nextQuery.status; await router.replace({ path: to.path, query: nextQuery }); next(); return; } } cookie.set(HtyUnionIDToken, qUnionStr); logout(); await login(qUnionStr); next(); return; } let {enabled, is_registered, roles, union_id} = store.current; console.log(enabled, is_registered, to.path); // 未启用、未注册 用户进入首页操作 if ((!enabled || !is_registered) && to.path !== '/' && !to.path.startsWith('/guest')) { if (store.currentRole){ delete store.currentRole } window.localStorage.removeItem(CurrentUserRole) await router.replace('/') } else { if (!store.currentRole) { let prev_role = window.localStorage.getItem(CurrentUserRole) // check if prev role is still valid if (prev_role && roles && roles.some(r => r.role_key === prev_role && r.role_status === HtyStates.ACTIVE)) { chooseRole(prev_role as HtyRoles) } else { window.localStorage.removeItem(CurrentUserRole); let activeRoles = roles?.filter(r => r.role_status === HtyStates.ACTIVE) if(activeRoles?.length === 1) { chooseRole(activeRoles[0].role_key) } else if (to.path !== '/') { await router.replace('/') } } } else if (enabled && is_registered) { getUnreadTongzhis(); } } if (enabled && is_registered && to.path !== '/' && to.path !== '/org/select') { const authToken = window.localStorage.getItem(HtyAuthToken); const tokenOrgId = parseCurrentOrgIdFromToken(authToken); if (!tokenOrgId) { const organizations = await loadMyOrgs(); if (organizations.length === 1) { const switched = await switchOrg(organizations[0].id); if (!switched) { next(false); return; } const currentAuthToken = window.localStorage.getItem(HtyAuthToken); if (currentAuthToken) { window.localStorage.setItem(HtySudoToken, currentAuthToken); } await loadMyDepartments(); if (orgStore.departments.length === 1 && orgStore.currentDepartmentId) { await switchDepartment(orgStore.currentDepartmentId); } } else if (organizations.length > 1) { await router.replace('/org/select'); next(); return; } } else if (!orgStore.currentOrgId) { window.localStorage.setItem(CurrentOrgId, tokenOrgId); orgStore.currentOrgId = tokenOrgId; } if (orgStore.currentOrgId && orgStore.departments.length === 0) { await loadMyDepartments(); if (orgStore.departments.length === 1 && orgStore.currentDepartmentId) { await switchDepartment(orgStore.currentDepartmentId); } } } let {stopTimer} = useTimer() stopTimer(); if (to.path.endsWith("/profile") && store.currentRole && !to.path.includes(store.currentRole.toLowerCase())) { await router.replace("/" + store.currentRole.toLowerCase() + "/profile") } next(); } catch (e: any) { window.localStorage.setItem('__guardError', e?.message || String(e)); next(); } }) createApp(App).use(router).use(weixin).mount('#app')