first commit

This commit is contained in:
2026-04-01 15:35:40 +08:00
commit 562a9b5172
479 changed files with 68351 additions and 0 deletions

226
src/App.vue Normal file
View File

@@ -0,0 +1,226 @@
<script setup>
import { RouterLink, RouterView, useRouter } from "vue-router";
const { isWeChat } = useEnv();
import { useAgentStore } from "@/stores/agentStore";
import { useUserStore } from "@/stores/userStore";
import { useDialogStore } from "@/stores/dialogStore";
import { useAuthStore } from "@/stores/authStore";
import { useWeixinShare } from "@/composables/useWeixinShare";
import WechatOverlay from "@/components/WechatOverlay.vue";
// import MaintenanceDialog from "@/components/MaintenanceDialog.vue";
const router = useRouter();
const agentStore = useAgentStore();
const userStore = useUserStore();
const dialogStore = useDialogStore();
const authStore = useAuthStore();
const { configWeixinShare, setDynamicShare } = useWeixinShare();
onMounted(() => {
// 检查token版本如果版本不匹配则清除旧token
checkTokenVersion()
// 恢复微信授权状态(页面刷新后)
authStore.restoreFromStorage();
// 检查是否是微信授权回调
const url = new URL(window.location.href);
const hasWeixinCode = url.searchParams.has('code') && url.searchParams.has('state');
if (hasWeixinCode) {
// 如果是授权回调,标记为正在授权
authStore.startWeixinAuth();
}
RefreshToken();
const token = localStorage.getItem("token");
if (token) {
agentStore.fetchAgentStatus();
userStore.fetchUserInfo();
}
// 配置微信分享
// 延迟执行确保微信SDK已加载
setTimeout(async () => {
if (isWeChat.value && window.jWeixin) {
await setDynamicShare();
}
}, 500);
// 监听路由变化,更新微信分享配置
router.afterEach(() => {
setTimeout(async () => {
if (isWeChat.value && window.jWeixin) {
await setDynamicShare();
}
}, 300);
});
});
const checkTokenVersion = () => {
// 设置新的token版本号当后端token格式改变时修改这个版本号
const CURRENT_TOKEN_VERSION =
import.meta.env.VITE_TOKEN_VERSION;
if (!CURRENT_TOKEN_VERSION) {
throw new Error("缺少环境变量: VITE_TOKEN_VERSION");
}
const storedTokenVersion = localStorage.getItem('tokenVersion')
if (!storedTokenVersion || storedTokenVersion !== CURRENT_TOKEN_VERSION) {
// 清除所有旧的认证信息
clearAuthData()
// 设置新的token版本
localStorage.setItem('tokenVersion', CURRENT_TOKEN_VERSION)
console.log('Token version updated, cleared old authentication data')
}
}
// 统一清除认证数据的工具函数
const clearAuthData = () => {
localStorage.removeItem('token')
localStorage.removeItem('refreshAfter')
localStorage.removeItem('accessExpire')
localStorage.removeItem('userInfo')
localStorage.removeItem('agentInfo')
}
const RefreshToken = async () => {
const url = new URL(window.location.href);
const hasOAuthCallback =
url.searchParams.has("code") && url.searchParams.has("state");
// 微信 OAuth 回调页:只处理 code 换票,避免无 code 时重复跳转授权
if (isWeChat.value && hasOAuthCallback) {
await h5WeixinLogin();
return;
}
const token = localStorage.getItem("token");
const refreshAfter = localStorage.getItem("refreshAfter");
const accessExpire = localStorage.getItem("accessExpire");
const currentTime = Date.now();
if (accessExpire) {
const accessExpireInMilliseconds = parseInt(accessExpire, 10) * 1000;
if (currentTime > accessExpireInMilliseconds) {
if (isWeChat.value) {
h5WeixinLogin();
}
return;
}
}
if (!token) {
if (isWeChat.value) {
h5WeixinLogin();
}
return;
}
if (refreshAfter) {
const refreshAfterInMilliseconds = parseInt(refreshAfter, 10) * 1000;
if (currentTime < refreshAfterInMilliseconds) {
return;
}
}
refreshToken();
};
const mpWeixinLogin = () => { };
const refreshToken = async () => {
const { data, error } = await useApiFetch("/user/getToken").post().json();
if (data.value && !error.value) {
if (data.value.code === 200) {
localStorage.setItem("token", data.value.data.accessToken);
localStorage.setItem("refreshAfter", data.value.data.refreshAfter);
localStorage.setItem("accessExpire", data.value.data.accessExpire);
}
}
};
const h5WeixinLogin = async () => {
// 获取当前URL
const url = new URL(window.location.href);
// 获取参数
const params = new URLSearchParams(url.search);
// 获取特定参数值
const code = params.get("code");
const state = params.get("state");
if (code && state) {
// 这是微信授权回调,处理授权结果
const { data, error } = await useApiFetch("/user/wxh5Auth")
.post({ code })
.json();
if (data.value && !error.value) {
if (data.value.code === 200) {
localStorage.setItem("token", data.value.data.accessToken);
localStorage.setItem(
"refreshAfter",
data.value.data.refreshAfter
);
localStorage.setItem(
"accessExpire",
data.value.data.accessExpire
);
params.delete("code");
params.delete("state");
// 更新 URL不刷新页面
const newUrl = `${url.origin}${url.pathname
}?${params.toString()}`;
window.history.replaceState({}, "", newUrl);
// 标记微信授权完成
authStore.completeWeixinAuth();
// 获取用户和代理信息
await Promise.all([
agentStore.fetchAgentStatus(),
userStore.fetchUserInfo()
]);
// 如果有待处理的路由,跳转到该路由
if (authStore.pendingRoute) {
router.replace(authStore.pendingRoute);
authStore.clearPendingRoute();
}
}
}
} else {
// 没有授权参数,需要开始微信授权
// 保存当前路由作为授权完成后的目标路由
const currentRoute = router.currentRoute.value;
authStore.startWeixinAuth(currentRoute);
h5WeixinGetCode();
}
};
const h5WeixinGetCode = () => {
const currentUrl = window.location.href;
let redirectUri = encodeURIComponent(currentUrl);
const appId = import.meta.env.VITE_WECHAT_APP_ID;
if (!appId) {
throw new Error("缺少环境变量: VITE_WECHAT_APP_ID");
}
let state = "snsapi_base";
let scope = "snsapi_base";
let authUrl = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}&redirect_uri=${redirectUri}&response_type=code&scope=${scope}&state=${state}#wechat_redirect`;
// 跳转到授权URL
window.location.href = authUrl;
};
</script>
<template>
<RouterView />
<WechatOverlay />
<BindPhoneDialog />
<!-- <MaintenanceDialog /> -->
</template>
<style scoped></style>