fix(h5-shop): tip unbound WeChat login to use phone first

This commit is contained in:
2026-08-02 13:15:47 +08:00
parent 45d3d8164d
commit ab3b230d01
4 changed files with 53 additions and 13 deletions
@@ -20,6 +20,9 @@ import {
fetchClientConfig,
handleShopWechatCallback,
handleShopWechatLoginResult,
isShopWechatUnboundError,
SHOP_WX_NEED_PHONE_LOGIN_MSG,
stashShopWechatLoginHint,
} from '../lib/wechat-auth';
import { isWechatEnv } from '../lib/weixin';
@@ -83,7 +86,11 @@ export function StoreSessionProvider({ children }: { children: ReactNode }) {
}
stripOAuthParamsFromLocation();
}
} catch {
} catch (e) {
const raw = e instanceof Error ? e.message : '';
if (isShopWechatUnboundError(raw)) {
stashShopWechatLoginHint(SHOP_WX_NEED_PHONE_LOGIN_MSG);
}
stripOAuthParamsFromLocation();
}
}
+34
View File
@@ -15,6 +15,40 @@ export type ShopAccountProfile = {
store?: { name: string };
};
/** 微信未绑定门店账号时的登录提示 */
export const SHOP_WX_NEED_PHONE_LOGIN_MSG = '请先用手机号登录';
const SHOP_WX_LOGIN_HINT_KEY = 'shop_wx_login_hint';
export function isShopWechatUnboundError(message: string): boolean {
return message.includes('首次登录') || message.includes('手机验证码') || message.includes('请先用手机号');
}
export function formatShopWechatError(e: unknown): string {
const text = e instanceof Error ? e.message : '微信登录失败';
if (isShopWechatUnboundError(text)) return SHOP_WX_NEED_PHONE_LOGIN_MSG;
return text;
}
/** OAuth 在启动层失败时暂存提示,供登录页展示 */
export function stashShopWechatLoginHint(message: string): void {
try {
sessionStorage.setItem(SHOP_WX_LOGIN_HINT_KEY, message);
} catch {
/* ignore */
}
}
export function consumeShopWechatLoginHint(): string | null {
try {
const hint = sessionStorage.getItem(SHOP_WX_LOGIN_HINT_KEY);
if (hint) sessionStorage.removeItem(SHOP_WX_LOGIN_HINT_KEY);
return hint;
} catch {
return null;
}
}
export async function fetchClientConfig(): Promise<ClientRuntimeConfig> {
return request<ClientRuntimeConfig>('SHOP_H5', '/common/client-config');
}
+10 -11
View File
@@ -15,7 +15,9 @@ import {
import { routeAfterShopLogin } from './SelectStorePage';
import {
bindShopWechatAfterSmsLogin,
consumeShopWechatLoginHint,
fetchClientConfig,
formatShopWechatError,
handleShopWechatCallback,
handleShopWechatLoginResult,
loginShopWithWechat,
@@ -27,14 +29,6 @@ function maskPhone(phone: string) {
return `${phone.slice(0, 3)} **** ${phone.slice(-4)}`;
}
function formatWechatError(e: unknown): string {
const text = e instanceof Error ? e.message : '微信登录失败';
if (text.includes('首次登录') || text.includes('手机验证码')) {
return '该微信尚未绑定门店账号,请先使用手机验证码登录,登录后将自动关联微信';
}
return text;
}
function ShopAgreementCheckbox({
agreed,
onChange,
@@ -76,7 +70,7 @@ export default function LoginPage() {
const [agreed, setAgreed] = useState(false);
const [loading, setLoading] = useState(false);
const [wxLoading, setWxLoading] = useState(false);
const [msg, setMsg] = useState('');
const [msg, setMsg] = useState(() => consumeShopWechatLoginHint() ?? '');
const [codeCooldown, setCodeCooldown] = useState(0);
const [wxAuthorize, setWxAuthorize] = useState(false);
const agreementRef = useRef<HTMLLabelElement>(null);
@@ -87,6 +81,11 @@ export default function LoginPage() {
.catch(() => setWxAuthorize(false));
}, []);
useEffect(() => {
const hint = consumeShopWechatLoginHint();
if (hint) setMsg(hint);
}, []);
useEffect(() => {
if (!isWechatEnv() || !wxAuthorize || !params.get('code')) return;
void handleShopWechatCallback()
@@ -100,7 +99,7 @@ export default function LoginPage() {
routeAfterShopLogin(session, navigate);
}
})
.catch((e) => setMsg(formatWechatError(e)));
.catch((e) => setMsg(formatShopWechatError(e)));
}, [applySession, navigate, params, setSearchParams, wxAuthorize]);
const quickStoreName = savedProfile?.storeName ?? '门店管理中心';
@@ -178,7 +177,7 @@ export default function LoginPage() {
routeAfterShopLogin(session, navigate);
}
} catch (e) {
setMsg(formatWechatError(e));
setMsg(formatShopWechatError(e));
} finally {
setWxLoading(false);
}
@@ -1538,7 +1538,7 @@ export class AuthService {
});
if (!account) {
throw new BadRequestException('首次登录请使用手机验证码,登录后将自动关联微信');
throw new BadRequestException('请先用手机号登录');
}
account = await this.prisma.storeAccount.update({