2026-04-23 16:37:14 +08:00
|
|
|
|
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'
|
2026-04-27 23:32:48 +08:00
|
|
|
|
import useOrg from "~/store/org";
|
2026-04-23 16:37:14 +08:00
|
|
|
|
import cookie from "~/utils/cookie";
|
2026-04-27 23:32:48 +08:00
|
|
|
|
import {CurrentOrgId, CurrentUserRole, HtyAuthToken, HtySudoToken, HtyUnionIDToken, pad} from "~/utils";
|
2026-04-23 16:37:14 +08:00
|
|
|
|
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(':')
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-27 23:32:48 +08:00
|
|
|
|
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, '/');
|
2026-04-27 23:55:24 +08:00
|
|
|
|
const payloadRawWithPadding = payloadRaw.padEnd(Math.ceil(payloadRaw.length / 4) * 4, '=');
|
2026-04-27 23:32:48 +08:00
|
|
|
|
const payloadJson = decodeURIComponent(
|
2026-04-27 23:55:24 +08:00
|
|
|
|
atob(payloadRawWithPadding)
|
2026-04-27 23:32:48 +08:00
|
|
|
|
.split('')
|
|
|
|
|
|
.map((char) => `%${(`00${char.charCodeAt(0).toString(16)}`).slice(-2)}`)
|
|
|
|
|
|
.join('')
|
|
|
|
|
|
);
|
2026-04-28 00:05:49 +08:00
|
|
|
|
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;
|
2026-04-27 23:32:48 +08:00
|
|
|
|
} catch (_error) {
|
|
|
|
|
|
return undefined;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-04-23 16:37:14 +08:00
|
|
|
|
router.beforeEach(async (to, from , next) => {
|
2026-05-02 18:29:54 +08:00
|
|
|
|
try {
|
2026-04-23 16:37:14 +08:00
|
|
|
|
document.title = to.meta.title as string;
|
2026-04-27 23:40:16 +08:00
|
|
|
|
let { store, read, login, logout, chooseRole, getUnreadTongzhis, set_editing } = useUser();
|
2026-05-02 18:29:54 +08:00
|
|
|
|
let { store: orgStore, loadMyOrgs, switchOrg, loadMyDepartments, switchDepartment } = useOrg();
|
2026-04-23 16:37:14 +08:00
|
|
|
|
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
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-04-26 15:58:56 +08:00
|
|
|
|
// switched unionid(URL 与当前会话不一致时)
|
2026-04-23 16:37:14 +08:00
|
|
|
|
if (to.query.unionid && store.unionid !== to.query.unionid) {
|
2026-04-26 15:58:56 +08:00
|
|
|
|
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);
|
2026-04-23 16:37:14 +08:00
|
|
|
|
logout();
|
2026-04-26 15:58:56 +08:00
|
|
|
|
await login(qUnionStr);
|
|
|
|
|
|
next();
|
2026-04-23 16:37:14 +08:00
|
|
|
|
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)
|
2026-04-26 17:09:42 +08:00
|
|
|
|
} else if (to.path !== '/') {
|
2026-04-23 16:37:14 +08:00
|
|
|
|
await router.replace('/')
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} else if (enabled && is_registered) {
|
|
|
|
|
|
getUnreadTongzhis();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-04-27 23:32:48 +08:00
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
}
|
2026-04-27 23:40:16 +08:00
|
|
|
|
const currentAuthToken = window.localStorage.getItem(HtyAuthToken);
|
|
|
|
|
|
if (currentAuthToken) {
|
|
|
|
|
|
window.localStorage.setItem(HtySudoToken, currentAuthToken);
|
|
|
|
|
|
}
|
2026-05-02 16:37:32 +08:00
|
|
|
|
await loadMyDepartments();
|
2026-05-02 18:29:54 +08:00
|
|
|
|
if (orgStore.departments.length === 1 && orgStore.currentDepartmentId) {
|
|
|
|
|
|
await switchDepartment(orgStore.currentDepartmentId);
|
|
|
|
|
|
}
|
2026-04-27 23:32:48 +08:00
|
|
|
|
} else if (organizations.length > 1) {
|
|
|
|
|
|
await router.replace('/org/select');
|
|
|
|
|
|
next();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
} else if (!orgStore.currentOrgId) {
|
|
|
|
|
|
window.localStorage.setItem(CurrentOrgId, tokenOrgId);
|
|
|
|
|
|
orgStore.currentOrgId = tokenOrgId;
|
|
|
|
|
|
}
|
2026-05-02 16:37:32 +08:00
|
|
|
|
if (orgStore.currentOrgId && orgStore.departments.length === 0) {
|
|
|
|
|
|
await loadMyDepartments();
|
2026-05-02 18:29:54 +08:00
|
|
|
|
if (orgStore.departments.length === 1 && orgStore.currentDepartmentId) {
|
|
|
|
|
|
await switchDepartment(orgStore.currentDepartmentId);
|
|
|
|
|
|
}
|
2026-05-02 16:37:32 +08:00
|
|
|
|
}
|
2026-04-27 23:32:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-23 16:37:14 +08:00
|
|
|
|
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();
|
2026-05-02 18:29:54 +08:00
|
|
|
|
} catch (e: any) {
|
|
|
|
|
|
window.localStorage.setItem('__guardError', e?.message || String(e));
|
|
|
|
|
|
next();
|
|
|
|
|
|
}
|
2026-04-23 16:37:14 +08:00
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
createApp(App).use(router).use(weixin).mount('#app')
|