fix;合并修复问题

This commit is contained in:
ljy
2026-07-09 21:42:36 +08:00
parent 3d3588babb
commit 336116fbf2
18 changed files with 341 additions and 190 deletions
+57 -9
View File
@@ -1,34 +1,82 @@
import type { PartnerMe } from '@dukang/shared-types';
import { isOnAppPath, toAppPath } from '@dukang/weixin-sdk';
import { showPartnerToast } from './toast';
export const apiBase = '/api/v1';
export async function request<T>(clientApp: string, path: string, options: RequestInit = {}): Promise<T> {
const LAST_PHONE = 'partnerLastPhone';
const PARTNER_PROFILE = 'partnerProfile';
export type PartnerSessionProfile = Pick<PartnerMe, 'id' | 'name' | 'phone' | 'companyName'>;
export type PartnerAuthPayload = {
accessToken: string;
partner?: PartnerSessionProfile;
};
export type ApiRequestOptions = RequestInit & {
/** 为 true 时不弹出 toast(由调用方自行展示) */
silent?: boolean;
};
export function getLastPhone() {
return localStorage.getItem(LAST_PHONE) ?? '';
}
export function getPartnerProfile(): PartnerSessionProfile | null {
try {
const raw = localStorage.getItem(PARTNER_PROFILE);
return raw ? (JSON.parse(raw) as PartnerSessionProfile) : null;
} catch {
return null;
}
}
export async function request<T>(
clientApp: string,
path: string,
options: ApiRequestOptions = {},
): Promise<T> {
const { silent, ...fetchOptions } = options;
const token = localStorage.getItem('accessToken');
const headers: Record<string, string> = {
'Content-Type': 'application/json',
'X-Client-App': clientApp,
...(options.headers as Record<string, string>),
...(fetchOptions.headers as Record<string, string>),
};
if (token) headers.Authorization = `Bearer ${token}`;
const res = await fetch(`${apiBase}${path}`, { ...options, headers });
const res = await fetch(`${apiBase}${path}`, { ...fetchOptions, headers });
const json = await res.json().catch(() => ({ code: res.status, message: '网络异常' }));
const message = json.message || (res.status === 401 ? '登录已过期,请重新登录' : '请求失败');
if (res.status === 401 || json.code === 401) {
clearAuth();
if (typeof window !== 'undefined' && !isOnAppPath('/login')) {
window.location.href = toAppPath('/login');
if (token && localStorage.getItem('accessToken') === token) {
clearAuth();
if (!silent) showPartnerToast(message, 'error');
if (typeof window !== 'undefined' && !isOnAppPath('/login')) {
window.location.href = toAppPath('/login');
}
}
throw new Error(json.message || '登录已过期,请重新登录');
throw new Error(message);
}
if (json.code !== 0) {
if (!silent) showPartnerToast(message, 'error');
throw new Error(message);
}
if (json.code !== 0) throw new Error(json.message || '请求失败');
return json.data as T;
}
export function saveAuth(data: { accessToken: string }) {
export function saveAuth(data: PartnerAuthPayload) {
localStorage.setItem('accessToken', data.accessToken);
if (data.partner) {
localStorage.setItem(PARTNER_PROFILE, JSON.stringify(data.partner));
localStorage.setItem(LAST_PHONE, data.partner.phone);
}
}
export function clearAuth() {
localStorage.removeItem('accessToken');
localStorage.removeItem(PARTNER_PROFILE);
}
export function isLoggedIn() {
+23
View File
@@ -0,0 +1,23 @@
export type PartnerToastVariant = 'success' | 'error';
type PartnerToastListener = (message: string, variant: PartnerToastVariant) => void;
let listener: PartnerToastListener | null = null;
export function registerPartnerToastListener(fn: PartnerToastListener | null) {
listener = fn;
}
export function showPartnerToast(message: string, variant: PartnerToastVariant = 'error') {
const text = message.trim();
if (!text || !listener) return;
listener(text, variant);
}
export function toastError(message: string) {
showPartnerToast(message, 'error');
}
export function toastSuccess(message: string) {
showPartnerToast(message, 'success');
}
+6 -1
View File
@@ -1,4 +1,5 @@
import { apiBase, request } from './api';
import { showPartnerToast } from './toast';
export type OssMediaType = 'IMAGE' | 'VIDEO' | 'FILE';
@@ -32,9 +33,13 @@ export async function uploadFileToOss(
const json = await res.json();
if (json.code === 401) {
localStorage.removeItem('accessToken');
showPartnerToast('未登录', 'error');
throw new Error('未登录');
}
if (json.code !== 0) throw new Error(json.message || '上传失败');
if (json.code !== 0) {
showPartnerToast(json.message || '上传失败', 'error');
throw new Error(json.message || '上传失败');
}
const data = json.data as UploadFileResult;
return {
+13 -10
View File
@@ -41,6 +41,19 @@ export function handlePartnerWechatLoginResult(result: WechatLoginResult): boole
return true;
}
/** 微信登录成功后拉取并缓存合伙人资料,供一键登录页展示 */
export async function persistPartnerProfileAfterLogin(): Promise<void> {
try {
const profile = await fetchPartnerProfile();
saveAuth({
accessToken: localStorage.getItem('accessToken') ?? '',
partner: profile,
});
} catch {
/* ignore */
}
}
export async function handlePartnerWechatCallback(): Promise<WechatLoginResult | null> {
if (!isWechatEnv()) return null;
const config = await fetchClientConfig();
@@ -62,16 +75,6 @@ export async function loginPartnerWithWechat(): Promise<boolean | void> {
if (result) return handlePartnerWechatLoginResult(result);
}
/**
* 短信登录成功后于微信内自动发起 OAuth,将 openId 绑定到当前合伙人账号(便于同一微信后续免登)。
*/
export async function bindPartnerWechatAfterSmsLogin(): Promise<void> {
const config = await fetchClientConfig();
if (!isWxAuthorizeEnabled(config)) return;
if (!isWechatEnv()) return;
await weixinSdk.login();
}
export async function authorizePartnerWechat(): Promise<WechatLoginResult | void> {
const config = await fetchClientConfig();
if (!isWxAuthorizeEnabled(config)) return;