import { useEffect, useState } from 'react'; import { Link, useNavigate, useSearchParams } from 'react-router-dom'; import { isWxAuthorizeEnabled } from '@dukang/shared-types'; import { WECHAT_INAPP_REQUIRED_MSG } from '@dukang/weixin-sdk'; import { getLastPhone, getPartnerProfile, hasPartnerWxSession, request, saveAuth, type PartnerSessionPayload, } from '../lib/api'; import { usePartnerSession } from '../contexts/PartnerSessionContext'; import { partnerHomePath } from '../lib/partnerAccess'; import { bindPartnerWechatAfterSmsLogin, canPartnerUseWechatLogin, fetchClientConfig, loginPartnerWithWechat, PARTNER_WECHAT_LOGIN_HINT, } from '../lib/wechat-auth'; import { isWechatEnv } from '../lib/weixin'; const REMEMBER_PHONE_KEY = 'partner_remember_phone'; const REMEMBER_FLAG_KEY = 'partner_remember_account'; function maskPhone(phone: string) { if (phone.length < 7) return phone; return `${phone.slice(0, 3)} **** ${phone.slice(-4)}`; } function loadRememberedPhone(): { phone: string; remember: boolean } { try { const remember = localStorage.getItem(REMEMBER_FLAG_KEY) === '1'; const phone = remember ? localStorage.getItem(REMEMBER_PHONE_KEY) || '' : ''; return { phone, remember }; } catch { return { phone: '', remember: false }; } } function formatPartnerError(e: unknown): string { const text = e instanceof Error ? e.message : '操作失败'; if (text.includes('合伙人账号不存在') || text.includes('未找到合伙人账号')) { return '未找到合伙人账号'; } if (text.includes('合伙人账号已停用')) { return '合伙人账号已停用'; } return text; } function formatWechatError(e: unknown): string { const text = e instanceof Error ? e.message : '微信登录失败'; if (text.includes('首次登录') || text.includes('手机验证码')) { return '该微信尚未绑定合伙人账号,请先使用手机验证码登录,登录后将自动关联微信'; } return text; } export default function LoginPage() { const navigate = useNavigate(); const { applySession, refresh, account } = usePartnerSession(); const [params] = useSearchParams(); const quick = params.get('quick') === '1'; const savedProfile = getPartnerProfile(); const remembered = loadRememberedPhone(); const [phone, setPhone] = useState(remembered.phone || getLastPhone()); const [code, setCode] = useState(''); const [rememberAccount, setRememberAccount] = useState(remembered.remember); const [agreed, setAgreed] = useState(false); const [loading, setLoading] = useState(false); const [wxLoading, setWxLoading] = useState(false); const [msg, setMsg] = useState(''); const [codeCooldown, setCodeCooldown] = useState(0); const [wxAuthorize, setWxAuthorize] = useState(false); useEffect(() => { fetchClientConfig() .then((config) => setWxAuthorize(isWxAuthorizeEnabled(config))) .catch(() => setWxAuthorize(false)); }, []); const quickName = savedProfile?.name ?? '城市合伙人'; const quickCompany = savedProfile?.companyName ?? ''; const quickPhone = savedProfile?.phone || phone; function ensureAgreed() { if (!agreed) { setMsg('请先勾选并同意用户协议'); return false; } return true; } function persistRememberAccount(nextPhone: string) { try { if (rememberAccount) { localStorage.setItem(REMEMBER_FLAG_KEY, '1'); localStorage.setItem(REMEMBER_PHONE_KEY, nextPhone); } else { localStorage.removeItem(REMEMBER_FLAG_KEY); localStorage.removeItem(REMEMBER_PHONE_KEY); } } catch { /* ignore */ } } async function sendCode() { if (!ensureAgreed()) return; setMsg(''); try { await request('PARTNER_H5', '/partner/auth/sms/send', { method: 'POST', body: JSON.stringify({ phone, scene: 'PARTNER_LOGIN' }), silent: true, }); setMsg('验证码已发送'); setCodeCooldown(60); const timer = setInterval(() => { setCodeCooldown((s) => { if (s <= 1) { clearInterval(timer); return 0; } return s - 1; }); }, 1000); } catch (e) { setMsg(formatPartnerError(e)); } } async function finishLoginNavigate() { const me = await refresh(); navigate(partnerHomePath(me ?? account ?? savedProfile)); } async function login() { if (!ensureAgreed()) return; setLoading(true); setMsg(''); try { const data = await request('PARTNER_H5', '/partner/auth/login/sms', { method: 'POST', body: JSON.stringify({ phone, code }), silent: true, }); saveAuth(data); applySession(data); persistRememberAccount(phone); if (isWechatEnv() && wxAuthorize) { setMsg('登录成功,正在关联微信…'); await bindPartnerWechatAfterSmsLogin(); return; } await finishLoginNavigate(); } catch (e) { setMsg(formatPartnerError(e)); } finally { setLoading(false); } } async function wechatLogin() { if (!ensureAgreed()) return; setMsg(''); if (!isWechatEnv()) { setMsg(WECHAT_INAPP_REQUIRED_MSG); return; } const canUseWechat = await canPartnerUseWechatLogin({ profile: savedProfile, phone, }); if (!canUseWechat) { setMsg(PARTNER_WECHAT_LOGIN_HINT); return; } setWxLoading(true); try { const session = await loginPartnerWithWechat(); if (session) { applySession(session); await finishLoginNavigate(); } } catch (e) { setMsg(formatWechatError(e)); } finally { setWxLoading(false); } } if (quick) { const canWechatQuick = wxAuthorize && isWechatEnv() && hasPartnerWxSession() && !!savedProfile && savedProfile.hasWechat === true; return (
wine_bar

杜康好客

城市合伙人端

已识别账号
person

{quickName} {quickCompany ? ( ({quickCompany}) ) : null}

{quickPhone ? maskPhone(quickPhone) : '暂无已保存账号'}

verified_user {canWechatQuick ? '微信验证 · 7 天内免登录' : 'Secured by Dukang Heritage'}
); } return (
wine_bar

杜康好客

城市合伙人端

城市合伙人登录

smartphone { setPhone(e.target.value); setMsg(''); }} />
shield setCode(e.target.value)} />
{msg &&

{msg}

} {wxAuthorize && ( <>
其他登录方式
)}
{hasPartnerWxSession() && savedProfile?.hasWechat && ( 微信快捷登录 )}
); }