fix;合并修复问题
This commit is contained in:
@@ -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() {
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user