adbf73891a
- Wrap entire beforeEach guard in try/catch to prevent crashes from breaking navigation and leaving a blank page - Add missing next() at end of try block so all code paths resolve - Integrate switchDepartment() after loadMyDepartments() when exactly 1 department is available, enabling transparent single-dept flow Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
212 lines
8.4 KiB
TypeScript
212 lines
8.4 KiB
TypeScript
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<string, unknown>;
|
||
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<string, unknown>;
|
||
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<string, string | string[] | undefined | null>;
|
||
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')
|