Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import Taro from '@tarojs/taro';
|
||||
import { ClientApp } from '@dukang/shared-types';
|
||||
import { goLogin, forceReloadAfterAccountMerge } from './auth-nav';
|
||||
import { forceReloadAfterAccountMerge } from './auth-nav';
|
||||
|
||||
function resolveApiBase(): string {
|
||||
const origin =
|
||||
@@ -54,10 +54,6 @@ export function isLoggedIn(): boolean {
|
||||
return !!getToken();
|
||||
}
|
||||
|
||||
export function redirectToLogin() {
|
||||
goLogin();
|
||||
}
|
||||
|
||||
export function logout() {
|
||||
clearAuth();
|
||||
Taro.reLaunch({ url: '/pages/home/index' });
|
||||
@@ -76,17 +72,6 @@ function parseBody(data: unknown): { code?: number; message?: string } {
|
||||
return {};
|
||||
}
|
||||
|
||||
function isOnLoginPage(): boolean {
|
||||
try {
|
||||
const pages = Taro.getCurrentPages();
|
||||
const cur = pages[pages.length - 1] as { route?: string } | undefined;
|
||||
const route = cur?.route || '';
|
||||
return route.includes('pages/login');
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** 统一请求:注入 CLIENT_APP + Bearer,解包 { code, message, data } */
|
||||
export async function request<T = unknown>(path: string, options: ReqOptions = {}): Promise<T> {
|
||||
const header: Record<string, string> = {
|
||||
@@ -115,8 +100,6 @@ export async function request<T = unknown>(path: string, options: ReqOptions = {
|
||||
if (/账号已合并/.test(mergedMsg)) {
|
||||
// 合并后旧 JWT 失效:强制刷新,不引导「重新登录」
|
||||
forceReloadAfterAccountMerge();
|
||||
} else if (!isOnLoginPage()) {
|
||||
redirectToLogin();
|
||||
}
|
||||
}
|
||||
throw new Error(body?.message || '登录已过期,请重新登录');
|
||||
|
||||
@@ -7,6 +7,14 @@ const TAB_PAGES = new Set([
|
||||
'/pages/mine/index',
|
||||
]);
|
||||
|
||||
let loginNavigationPending = false;
|
||||
|
||||
function isLoginPageActive(): boolean {
|
||||
const pages = Taro.getCurrentPages();
|
||||
const current = pages[pages.length - 1] as { route?: string } | undefined;
|
||||
return !!current?.route?.includes('pages/login/');
|
||||
}
|
||||
|
||||
function currentPagePath(): string {
|
||||
const pages = Taro.getCurrentPages();
|
||||
const cur = pages[pages.length - 1] as
|
||||
@@ -25,6 +33,7 @@ function currentPagePath(): string {
|
||||
|
||||
/** 跳转登录页;默认带回当前页作为 return */
|
||||
export function goLogin(returnPath?: string, extras?: Record<string, string>) {
|
||||
if (loginNavigationPending || isLoginPageActive()) return;
|
||||
const returnTo = returnPath ?? currentPagePath();
|
||||
const parts: string[] = [];
|
||||
if (returnTo) parts.push(`return=${encodeURIComponent(returnTo)}`);
|
||||
@@ -34,9 +43,15 @@ export function goLogin(returnPath?: string, extras?: Record<string, string>) {
|
||||
}
|
||||
}
|
||||
const url = parts.length ? `/pages/login/index?${parts.join('&')}` : '/pages/login/index';
|
||||
Taro.navigateTo({ url }).catch(() => {
|
||||
Taro.redirectTo({ url });
|
||||
});
|
||||
loginNavigationPending = true;
|
||||
void Taro.navigateTo({ url })
|
||||
.catch(() => Taro.redirectTo({ url }))
|
||||
.finally(() => {
|
||||
// 等路由栈稳定后再释放,拦截同一轮请求触发的重复登录跳转。
|
||||
setTimeout(() => {
|
||||
loginNavigationPending = false;
|
||||
}, 500);
|
||||
});
|
||||
}
|
||||
|
||||
/** 登录成功后回到 return 页,或回退 / 首页 */
|
||||
|
||||
@@ -6,6 +6,17 @@ export type MiniWechatProfile = {
|
||||
avatarUrl?: string;
|
||||
};
|
||||
|
||||
export type MiniWechatProfileUpdate = MiniWechatProfile & {
|
||||
avatarResourceId?: string;
|
||||
};
|
||||
|
||||
export type UploadedAvatarResource = {
|
||||
resourceId: string;
|
||||
url: string;
|
||||
bucket: string;
|
||||
ossKey: string;
|
||||
};
|
||||
|
||||
const WX_PROFILE_CACHE_KEY = 'wx_mini_profile_cache';
|
||||
|
||||
export function cacheWxProfile(info: MiniWechatProfile) {
|
||||
@@ -55,8 +66,8 @@ export function mergeWxDisplayProfile(profile: UserProfile): UserProfile {
|
||||
};
|
||||
}
|
||||
|
||||
/** 上传 chooseAvatar 临时文件到 OSS,返回永久 URL */
|
||||
export async function uploadAvatarTempFile(tempFilePath: string): Promise<string> {
|
||||
/** 上传 chooseAvatar 临时文件到 OSS,并返回已登记到当前用户的真实资源。 */
|
||||
export async function uploadAvatarTempFile(tempFilePath: string): Promise<UploadedAvatarResource> {
|
||||
const { API_BASE, CLIENT_APP, getToken } = await import('./api');
|
||||
const token = getToken();
|
||||
if (!token) throw new Error('请先登录');
|
||||
@@ -75,7 +86,11 @@ export async function uploadAvatarTempFile(tempFilePath: string): Promise<string
|
||||
},
|
||||
});
|
||||
|
||||
let body: { code?: number; message?: string; data?: { url?: string } } = {};
|
||||
let body: {
|
||||
code?: number;
|
||||
message?: string;
|
||||
data?: { resourceId?: string; url?: string; bucket?: string; ossKey?: string };
|
||||
} = {};
|
||||
try {
|
||||
body = JSON.parse(String(res.data || '{}')) as typeof body;
|
||||
} catch {
|
||||
@@ -84,14 +99,26 @@ export async function uploadAvatarTempFile(tempFilePath: string): Promise<string
|
||||
if (res.statusCode === 401 || body.code === 401) {
|
||||
throw new Error(body.message || '登录已过期,请重新登录');
|
||||
}
|
||||
if (res.statusCode >= 400 || body.code !== 0 || !body.data?.url) {
|
||||
if (
|
||||
res.statusCode >= 400 ||
|
||||
body.code !== 0 ||
|
||||
!body.data?.resourceId ||
|
||||
!body.data.url ||
|
||||
!body.data.bucket ||
|
||||
!body.data.ossKey
|
||||
) {
|
||||
throw new Error(body.message || '头像上传失败');
|
||||
}
|
||||
return body.data.url;
|
||||
return {
|
||||
resourceId: body.data.resourceId,
|
||||
url: body.data.url,
|
||||
bucket: body.data.bucket,
|
||||
ossKey: body.data.ossKey,
|
||||
};
|
||||
}
|
||||
|
||||
export async function uploadMiniWechatProfile(info: MiniWechatProfile): Promise<UserProfile | null> {
|
||||
if (!info.nickname && !info.avatarUrl) return null;
|
||||
export async function uploadMiniWechatProfile(info: MiniWechatProfileUpdate): Promise<UserProfile | null> {
|
||||
if (!info.nickname && !info.avatarUrl && !info.avatarResourceId) return null;
|
||||
const { request } = await import('./api');
|
||||
const updated = await request<UserProfile>('/auth/wechat/mini-profile', {
|
||||
method: 'POST',
|
||||
@@ -124,6 +151,7 @@ export async function syncMiniWechatProfile(
|
||||
if (process.env.TARO_ENV !== 'weapp') return null;
|
||||
const info = prefetched?.nickname || prefetched?.avatarUrl ? prefetched : getCachedWxProfile();
|
||||
if (!info?.nickname && !info?.avatarUrl) return null;
|
||||
await uploadMiniWechatProfile(info);
|
||||
// 缓存头像 URL 可能来自历史微信资料,未经过当前 OSS 上传登记;这里只同步昵称。
|
||||
if (info.nickname) await uploadMiniWechatProfile({ nickname: info.nickname });
|
||||
return info;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user