From 0ec3e570af644eea0bf538da6bb9054c415098f1 Mon Sep 17 00:00:00 2001 From: wangdongbo <> Date: Tue, 22 Sep 2026 17:07:16 +0800 Subject: [PATCH] no message --- hooks/useGuard.js | 6 ++-- store/account.js | 25 ++++++++++++--- utils/api-base-config.js | 8 +++++ utils/http.js | 67 +++++++++++++++++++++++++++++++--------- 4 files changed, 84 insertions(+), 22 deletions(-) diff --git a/hooks/useGuard.js b/hooks/useGuard.js index 827d882..7388717 100644 --- a/hooks/useGuard.js +++ b/hooks/useGuard.js @@ -17,7 +17,7 @@ import { triggerPromise } from '@/utils'; export default function useGuard() { const { account } = storeToRefs(useAccount()); - const { login } = useAccount(); + const { login, hasValidMiniappSession } = useAccount(); const { resolve, promise } = triggerPromise(); const onShowEvents = ref([]); @@ -54,7 +54,7 @@ export default function useGuard() { const page = pages[pages.length - 1]; const route = routes.find(i => page && i.path === page.route); const requireLogin = route && route.meta && route.meta.login; - if (requireLogin && !account.value) { + if (requireLogin && (!account.value || !hasValidMiniappSession())) { const res = await login() if (res) { resolve() @@ -72,4 +72,4 @@ export default function useGuard() { }) return { useLoad, useShow } -} \ No newline at end of file +} diff --git a/store/account.js b/store/account.js index 73d4aa8..a3d46c9 100644 --- a/store/account.js +++ b/store/account.js @@ -4,7 +4,8 @@ import api from '@/utils/api'; import { toast } from '@/utils/widget'; import { initGlobalTIM, globalTimChatManager } from "@/utils/tim-chat.js"; import { globalUnreadListenerManager } from "@/utils/global-unread-listener.js"; -import { normalizeCorpId, normalizeCorpIdFields } from "@/utils/api-base-config"; +import { isSh6CorpId, normalizeCorpId, normalizeCorpIdFields, resolveApiContext } from "@/utils/api-base-config"; +import { setMiniappSessionRefresher } from "@/utils/http"; const env = __VITE_ENV__; export default defineStore("accountStore", () => { @@ -18,9 +19,16 @@ export default defineStore("accountStore", () => { const teams = ref([]); const teamsPromise = ref(null); + function hasValidMiniappSession() { + if (!isSh6CorpId(resolveApiContext().corpId)) return true; + const token = uni.getStorageSync("miniappSessionToken"); + const expiresAt = Number(uni.getStorageSync("miniappSessionExpiresAt")); + return Boolean(token && (!expiresAt || expiresAt > Date.now() + 30 * 1000)); + } + async function login(phoneCode = '', options = {}) { if (loading.value) return; - if (account.value && account.value.mobile && !options.forceVerify) { + if (account.value && account.value.mobile && !options.forceVerify && hasValidMiniappSession()) { return account.value } loading.value = true; @@ -38,7 +46,12 @@ export default defineStore("accountStore", () => { }); loading.value = false if (res.success && res.data) { - const normalizedAccount = normalizeCorpIdFields(res.data); + const { sessionToken, sessionExpiresAt, sessionKey, ...safeAccount } = res.data; + if (sessionToken) { + uni.setStorageSync("miniappSessionToken", sessionToken); + uni.setStorageSync("miniappSessionExpiresAt", sessionExpiresAt || 0); + } + const normalizedAccount = normalizeCorpIdFields(safeAccount); account.value = normalizedAccount; openid.value = normalizedAccount.openid; @@ -121,6 +134,8 @@ export default defineStore("accountStore", () => { // 清空账户信息 account.value = null; + uni.removeStorageSync("miniappSessionToken"); + uni.removeStorageSync("miniappSessionExpiresAt"); openid.value = ""; isIMInitialized.value = false; @@ -177,5 +192,7 @@ export default defineStore("accountStore", () => { } }, { immediate: true }) - return { account, teams, login, initIMAfterLogin, logout, openid, isIMInitialized, externalUserId, getExternalUserId, getTeams } + setMiniappSessionRefresher(() => login('', { forceVerify: true, silent: true })); + + return { account, teams, login, hasValidMiniappSession, initIMAfterLogin, logout, openid, isIMInitialized, externalUserId, getExternalUserId, getTeams } }) diff --git a/utils/api-base-config.js b/utils/api-base-config.js index d0e5706..3fe2051 100644 --- a/utils/api-base-config.js +++ b/utils/api-base-config.js @@ -12,6 +12,10 @@ export const CORP_ID_ALIAS_MAP = { "wpLgjyawAAeRkCPQMp9-z5q-xEzK64nA": "wwa54dfba0b5441ef1", }; +const SH6_CORP_IDS = new Set([ + "wpLgjyawAAxKtBH5GVT5DVhLefg246Ag", +]); + function normalizeBaseUrl(url) { return String(url || "").replace(/\/+$/, ""); } @@ -25,6 +29,10 @@ export function normalizeCorpId(corpId) { return CORP_ID_ALIAS_MAP[normalizedCorpId] || normalizedCorpId; } +export function isSh6CorpId(corpId) { + return SH6_CORP_IDS.has(normalizeCorpId(corpId)); +} + export function normalizeCorpIdFields(value) { if (Array.isArray(value)) { return value.map((item) => normalizeCorpIdFields(item)); diff --git a/utils/http.js b/utils/http.js index d6bf871..207d071 100644 --- a/utils/http.js +++ b/utils/http.js @@ -1,5 +1,5 @@ import { loading, hideLoading } from "./widget"; -import { buildApiUrl, getDefaultUploadUrl, normalizeCorpId } from "./api-base-config"; +import { buildApiUrl, getDefaultUploadUrl, isSh6CorpId, normalizeCorpId, resolveApiContext } from "./api-base-config"; const defaultOptions = { header: { @@ -9,6 +9,25 @@ const defaultOptions = { timeout: 1000 * 60, // 请求超时设置为60秒 }; const tasks = []; +let miniappSessionRefresher = null; +let miniappSessionRefreshPromise = null; + +export function setMiniappSessionRefresher(refresher) { + miniappSessionRefresher = typeof refresher === "function" ? refresher : null; +} + +async function refreshMiniappSession() { + if (!miniappSessionRefresher) return false; + if (!miniappSessionRefreshPromise) { + miniappSessionRefreshPromise = Promise.resolve() + .then(() => miniappSessionRefresher()) + .finally(() => { + miniappSessionRefreshPromise = null; + }); + } + await miniappSessionRefreshPromise; + return Boolean(uni.getStorageSync("miniappSessionToken")); +} // 是否正在刷新 token let isRefreshing = false; @@ -94,27 +113,29 @@ async function refreshAccessToken() { } const request = async (options = {}, showLoading = true) => { + const sessionRetried = options.__miniappSessionRetried === true; + const requestOptions = { ...options }; + delete requestOptions.__miniappSessionRetried; // 合并用户传入的配置和默认配置 - if (!options.data) options.data = {}; - if (options.data.corpId) { - options.data = { - ...options.data, - corpId: normalizeCorpId(options.data.corpId), + if (!requestOptions.data) requestOptions.data = {}; + if (requestOptions.data.corpId) { + requestOptions.data = { + ...requestOptions.data, + corpId: normalizeCorpId(requestOptions.data.corpId), }; } + const requestCorpId = requestOptions.data.corpId || resolveApiContext().corpId; + const requiresMiniappSession = isSh6CorpId(requestCorpId); const config = { ...defaultOptions, - ...options, - url: buildApiUrl(options.url, options.data.corpId), + ...requestOptions, + url: buildApiUrl(requestOptions.url, requestOptions.data.corpId), }; - - // 添加 token 到请求头 - // const accessToken = uni.getStorageSync("accessToken"); - // if (accessToken) { - // if (!config.header) config.header = {}; - // config.header.Authorization = `Bearer ${accessToken}`; - // } + const sessionToken = uni.getStorageSync("miniappSessionToken"); + if (requiresMiniappSession && sessionToken) { + config.header = { ...(config.header || {}), "X-Miniapp-Session": sessionToken }; + } const key = `${JSON.stringify(config)}_${Date.now()}`; if (showLoading) { @@ -128,6 +149,17 @@ const request = async (options = {}, showLoading = true) => { removeTask(key) } + if (requiresMiniappSession && res.statusCode === 401) { + uni.removeStorageSync("miniappSessionToken"); + uni.removeStorageSync("miniappSessionExpiresAt"); + if ( + !sessionRetried && + requestOptions.data.type !== "wxAppLogin" && + await refreshMiniappSession() + ) { + return request({ ...requestOptions, __miniappSessionRetried: true }, showLoading); + } + } // 如果返回 401,尝试刷新 token // if (res.statusCode === 401) { // if (showLoading) { @@ -214,10 +246,15 @@ export function getFullPath(path, corpId) { export function upload(path, corpId) { const normalizedCorpId = normalizeCorpId(corpId); + const uploadCorpId = normalizedCorpId || resolveApiContext().corpId; + const sessionToken = uni.getStorageSync("miniappSessionToken"); const currentUploadUrl = buildApiUrl("/upload", normalizedCorpId); return new Promise((resolve) => { uni.uploadFile({ url: currentUploadUrl, + header: isSh6CorpId(uploadCorpId) && sessionToken + ? { "X-Miniapp-Session": sessionToken } + : {}, filePath: path, name: 'file', fileType: 'image',