2025-09-27 17:41:14 +08:00
|
|
|
|
<script setup>
|
2025-10-24 17:08:42 +08:00
|
|
|
|
import { RouterLink, RouterView, useRouter } from "vue-router";
|
2025-09-27 17:41:14 +08:00
|
|
|
|
const { isWeChat } = useEnv();
|
|
|
|
|
|
import { useAgentStore } from "@/stores/agentStore";
|
|
|
|
|
|
import { useUserStore } from "@/stores/userStore";
|
|
|
|
|
|
import { useDialogStore } from "@/stores/dialogStore";
|
2025-10-24 17:08:42 +08:00
|
|
|
|
import { useAuthStore } from "@/stores/authStore";
|
|
|
|
|
|
import { useWeixinShare } from "@/composables/useWeixinShare";
|
2025-09-27 17:41:14 +08:00
|
|
|
|
|
2025-10-24 17:08:42 +08:00
|
|
|
|
const router = useRouter();
|
2025-09-27 17:41:14 +08:00
|
|
|
|
const agentStore = useAgentStore();
|
|
|
|
|
|
const userStore = useUserStore();
|
|
|
|
|
|
const dialogStore = useDialogStore();
|
2025-10-24 17:08:42 +08:00
|
|
|
|
const authStore = useAuthStore();
|
|
|
|
|
|
const { configWeixinShare, setDynamicShare } = useWeixinShare();
|
2025-09-27 17:41:14 +08:00
|
|
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
|
// 检查token版本,如果版本不匹配则清除旧token
|
|
|
|
|
|
checkTokenVersion()
|
2025-10-24 17:08:42 +08:00
|
|
|
|
|
|
|
|
|
|
// 恢复微信授权状态(页面刷新后)
|
|
|
|
|
|
authStore.restoreFromStorage();
|
|
|
|
|
|
|
|
|
|
|
|
// 检查是否是微信授权回调
|
|
|
|
|
|
const url = new URL(window.location.href);
|
|
|
|
|
|
const hasWeixinCode = url.searchParams.has('code') && url.searchParams.has('state');
|
|
|
|
|
|
|
|
|
|
|
|
if (hasWeixinCode) {
|
|
|
|
|
|
// 如果是授权回调,标记为正在授权
|
|
|
|
|
|
authStore.startWeixinAuth();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-27 17:41:14 +08:00
|
|
|
|
RefreshToken();
|
|
|
|
|
|
const token = localStorage.getItem("token");
|
|
|
|
|
|
if (token) {
|
|
|
|
|
|
agentStore.fetchAgentStatus();
|
|
|
|
|
|
userStore.fetchUserInfo();
|
|
|
|
|
|
}
|
2025-10-24 17:08:42 +08:00
|
|
|
|
|
|
|
|
|
|
// 配置微信分享
|
|
|
|
|
|
// 延迟执行,确保微信SDK已加载
|
|
|
|
|
|
setTimeout(async () => {
|
|
|
|
|
|
if (isWeChat.value && window.jWeixin) {
|
|
|
|
|
|
await setDynamicShare();
|
|
|
|
|
|
}
|
|
|
|
|
|
}, 500);
|
|
|
|
|
|
|
|
|
|
|
|
// 监听路由变化,更新微信分享配置
|
|
|
|
|
|
router.afterEach(() => {
|
|
|
|
|
|
setTimeout(async () => {
|
|
|
|
|
|
if (isWeChat.value && window.jWeixin) {
|
|
|
|
|
|
await setDynamicShare();
|
|
|
|
|
|
}
|
|
|
|
|
|
}, 300);
|
|
|
|
|
|
});
|
2025-09-27 17:41:14 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const checkTokenVersion = () => {
|
|
|
|
|
|
// 设置新的token版本号(当后端token格式改变时,修改这个版本号)
|
|
|
|
|
|
const CURRENT_TOKEN_VERSION = '2.1'
|
|
|
|
|
|
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 () => {
|
|
|
|
|
|
if (isWeChat.value) {
|
|
|
|
|
|
h5WeixinLogin();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
const token = localStorage.getItem("token");
|
|
|
|
|
|
const refreshAfter = localStorage.getItem("refreshAfter");
|
|
|
|
|
|
const accessExpire = localStorage.getItem("accessExpire");
|
|
|
|
|
|
const currentTime = new Date().getTime();
|
|
|
|
|
|
|
|
|
|
|
|
if (accessExpire) {
|
|
|
|
|
|
const accessExpireInMilliseconds = parseInt(accessExpire) * 1000; // 转换为毫秒级
|
|
|
|
|
|
if (currentTime > accessExpireInMilliseconds) {
|
|
|
|
|
|
if (isWeChat.value) {
|
|
|
|
|
|
h5WeixinLogin();
|
|
|
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
// 1. 如果没有 token,直接返回
|
|
|
|
|
|
if (!token) {
|
|
|
|
|
|
if (isWeChat.value) {
|
|
|
|
|
|
h5WeixinLogin();
|
|
|
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 2. 如果有 refreshAfter,检查当前时间是否超过 refreshAfter(refreshAfter 是秒级,需要转换为毫秒级)
|
|
|
|
|
|
if (refreshAfter) {
|
|
|
|
|
|
const refreshAfterInMilliseconds = parseInt(refreshAfter) * 1000; // 转换为毫秒级
|
|
|
|
|
|
if (currentTime < refreshAfterInMilliseconds) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
// 3. 如果没有 refreshAfter 或者时间超过 refreshAfter,执行刷新 token 的请求
|
|
|
|
|
|
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");
|
2025-10-24 17:08:42 +08:00
|
|
|
|
|
2025-09-27 17:41:14 +08:00
|
|
|
|
if (code && state) {
|
2025-10-24 17:08:42 +08:00
|
|
|
|
// 这是微信授权回调,处理授权结果
|
2025-09-27 17:41:14 +08:00
|
|
|
|
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);
|
|
|
|
|
|
|
2025-10-24 17:08:42 +08:00
|
|
|
|
// 标记微信授权完成
|
|
|
|
|
|
authStore.completeWeixinAuth();
|
|
|
|
|
|
|
|
|
|
|
|
// 获取用户和代理信息
|
|
|
|
|
|
await Promise.all([
|
|
|
|
|
|
agentStore.fetchAgentStatus(),
|
|
|
|
|
|
userStore.fetchUserInfo()
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
// 如果有待处理的路由,跳转到该路由
|
|
|
|
|
|
if (authStore.pendingRoute) {
|
|
|
|
|
|
router.replace(authStore.pendingRoute);
|
|
|
|
|
|
authStore.clearPendingRoute();
|
|
|
|
|
|
}
|
2025-09-27 17:41:14 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
2025-10-24 17:08:42 +08:00
|
|
|
|
// 没有授权参数,需要开始微信授权
|
|
|
|
|
|
// 保存当前路由作为授权完成后的目标路由
|
|
|
|
|
|
const currentRoute = router.currentRoute.value;
|
|
|
|
|
|
authStore.startWeixinAuth(currentRoute);
|
2025-09-27 17:41:14 +08:00
|
|
|
|
h5WeixinGetCode();
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
const h5WeixinGetCode = () => {
|
|
|
|
|
|
const currentUrl = window.location.href;
|
|
|
|
|
|
let redirectUri = encodeURIComponent(currentUrl);
|
|
|
|
|
|
let appId = "wxa581992dc74d860e";
|
|
|
|
|
|
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 />
|
|
|
|
|
|
<BindPhoneDialog />
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<style scoped></style>
|