fix(mini-user): address review blockers
CI / verify (pull_request) Has been cancelled

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-21 13:03:02 +08:00
parent eb96b36d0b
commit bdf80e577b
14 changed files with 280 additions and 106 deletions
+1 -18
View File
@@ -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 || '登录已过期,请重新登录');
+18 -3
View File
@@ -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 页,或回退 / 首页 */
+36 -8
View File
@@ -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;
}