feat: 增加环境切换

This commit is contained in:
R524809
2026-10-19 17:49:19 +08:00
parent 997042789d
commit fe1074e3f0
21 changed files with 968 additions and 123 deletions
+32 -13
View File
@@ -1,4 +1,4 @@
import { getApiConfig } from '../config/api';
import { getApiConfig, apiContextKey, isCurrentApiConfig } from '../config/api';
import { ApiRequestError, requestApi } from './api-transport';
export interface ServerUser {
@@ -32,7 +32,7 @@ export function getAuthContext() {
if (!appId) throw new ApiRequestError('无法识别小程序身份');
return {
...config,
key: `doodle_auth_v1:${encodeURIComponent(appId)}:${encodeURIComponent(config.baseUrl)}`,
key: `doodle_auth_v2:${apiContextKey(config)}`,
};
}
@@ -70,7 +70,18 @@ function readState(context: Context): SessionState {
generation: 0,
};
try {
const stored = wx.getStorageSync(context.key);
// 旧版会话只迁入原默认环境,不能复制到同址的 staging/production 开发配置。
const legacyDefault =
context.version === 'develop'
? context.environment === 'local'
: context.environment === 'production';
const stored =
wx.getStorageSync(context.key) ||
(legacyDefault
? wx.getStorageSync(
`doodle_auth_v1:${encodeURIComponent(wx.getAccountInfoSync().miniProgram.appId)}:${encodeURIComponent(context.baseUrl)}`,
)
: null);
if (stored) {
state.history = 'used';
if (
@@ -145,7 +156,7 @@ export async function ensureSession(
force = false,
explicitStart = false,
): Promise<AuthSession> {
if (getAuthContext().key !== context.key)
if (!isCurrentApiConfig(context))
throw new ApiRequestError('接口环境已变化,请重新操作');
const state = readState(context);
if (state.history === 'blocked' && !explicitStart)
@@ -184,11 +195,13 @@ export async function ensureSession(
);
break;
} catch (error) {
if (!(
error instanceof ApiRequestError &&
error.reason === 'WECHAT_CODE_INVALID' &&
attempt === 0
))
if (
!(
error instanceof ApiRequestError &&
error.reason === 'WECHAT_CODE_INVALID' &&
attempt === 0
)
)
throw error;
}
}
@@ -210,10 +223,7 @@ export async function ensureSession(
user: parseServerUser(result.user),
};
// 清理、切换环境期间迟到的登录响应不得恢复会话或写入当前界面。
if (
state.generation !== generation ||
getAuthContext().key !== context.key
)
if (state.generation !== generation || !isCurrentApiConfig(context))
throw new ApiRequestError('登录状态已变化,请重新操作');
state.session = session;
state.history = 'used';
@@ -222,6 +232,7 @@ export async function ensureSession(
} catch (error) {
if (
state.generation === generation &&
isCurrentApiConfig(context) &&
error instanceof ApiRequestError &&
[
'ACCOUNT_NOT_FOUND',
@@ -244,6 +255,14 @@ export async function ensureSession(
}
}
/** 保留各环境已保存会话和账户历史,只作废尚未完成的登录任务。 */
export function invalidatePendingAuthentication() {
for (const state of states.values()) {
state.generation++;
state.flight = undefined;
}
}
/** 同一原请求只恢复一次;迟到的旧 401 直接复用较新凭证。 */
export async function recoverSession(context: Context, failed: AuthSession) {
const state = readState(context);