Quick login required agreement without a checkbox; move the consent row above CTAs across partner/shop/user/mini login pages so it stays visible on short screens. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useEffect, useRef, useState, type RefObject } 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';
|
||||
@@ -24,6 +24,32 @@ import { isWechatEnv } from '../lib/weixin';
|
||||
const REMEMBER_PHONE_KEY = 'partner_remember_phone';
|
||||
const REMEMBER_FLAG_KEY = 'partner_remember_account';
|
||||
|
||||
function AgreementCheckbox({
|
||||
agreed,
|
||||
onChange,
|
||||
inputRef,
|
||||
}: {
|
||||
agreed: boolean;
|
||||
onChange: (next: boolean) => void;
|
||||
inputRef?: RefObject<HTMLLabelElement | null>;
|
||||
}) {
|
||||
return (
|
||||
<label className="partner-checkbox-row partner-checkbox-row--agreement" ref={inputRef}>
|
||||
<input type="checkbox" checked={agreed} onChange={(e) => onChange(e.target.checked)} />
|
||||
<span>
|
||||
我已阅读并同意{' '}
|
||||
<Link to="/legal/user-agreement" className="text-primary" style={{ fontWeight: 600 }} onClick={(e) => e.stopPropagation()}>
|
||||
《用户协议》
|
||||
</Link>{' '}
|
||||
与{' '}
|
||||
<Link to="/legal/privacy-policy" className="text-primary" style={{ fontWeight: 600 }} onClick={(e) => e.stopPropagation()}>
|
||||
《隐私政策》
|
||||
</Link>
|
||||
</span>
|
||||
</label>
|
||||
);
|
||||
}
|
||||
|
||||
function maskPhone(phone: string) {
|
||||
if (phone.length < 7) return phone;
|
||||
return `${phone.slice(0, 3)} **** ${phone.slice(-4)}`;
|
||||
@@ -74,6 +100,7 @@ export default function LoginPage() {
|
||||
const [msg, setMsg] = useState('');
|
||||
const [codeCooldown, setCodeCooldown] = useState(0);
|
||||
const [wxAuthorize, setWxAuthorize] = useState(false);
|
||||
const agreementRef = useRef<HTMLLabelElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
fetchClientConfig()
|
||||
@@ -88,6 +115,7 @@ export default function LoginPage() {
|
||||
function ensureAgreed() {
|
||||
if (!agreed) {
|
||||
setMsg('请先勾选并同意用户协议');
|
||||
agreementRef.current?.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -230,10 +258,16 @@ export default function LoginPage() {
|
||||
|
||||
<nav style={{ width: '100%', maxWidth: 384, marginTop: 16 }}>
|
||||
{msg && <p className="partner-auth-msg" style={{ color: 'var(--color-error, #d33)', fontSize: 13, textAlign: 'center', marginBottom: 12 }}>{msg}</p>}
|
||||
<AgreementCheckbox
|
||||
agreed={agreed}
|
||||
onChange={setAgreed}
|
||||
inputRef={agreementRef}
|
||||
/>
|
||||
{canWechatQuick ? (
|
||||
<button
|
||||
type="button"
|
||||
className="partner-btn-primary"
|
||||
style={{ marginTop: 16 }}
|
||||
disabled={wxLoading}
|
||||
onClick={() => void wechatLogin()}
|
||||
>
|
||||
@@ -241,7 +275,7 @@ export default function LoginPage() {
|
||||
<span>{wxLoading ? '登录中...' : '微信一键登录'}</span>
|
||||
</button>
|
||||
) : (
|
||||
<p className="partner-auth-msg" style={{ textAlign: 'center', marginBottom: 12 }}>
|
||||
<p className="partner-auth-msg" style={{ textAlign: 'center', marginTop: 12, marginBottom: 12 }}>
|
||||
{wxAuthorize && !isWechatEnv()
|
||||
? '请在微信内打开以使用一键登录'
|
||||
: '请使用验证码登录并绑定微信后,即可 7 天内免登录'}
|
||||
@@ -321,6 +355,12 @@ export default function LoginPage() {
|
||||
<span>记住账号</span>
|
||||
</label>
|
||||
|
||||
<AgreementCheckbox
|
||||
agreed={agreed}
|
||||
onChange={setAgreed}
|
||||
inputRef={agreementRef}
|
||||
/>
|
||||
|
||||
{msg && <p className="partner-auth-msg" style={{ color: 'var(--color-error, #d33)', fontSize: 13, textAlign: 'center' }}>{msg}</p>}
|
||||
|
||||
<button type="button" className="partner-btn-primary" onClick={() => void login()} disabled={loading}>
|
||||
@@ -339,20 +379,6 @@ export default function LoginPage() {
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
|
||||
<label className="partner-checkbox-row">
|
||||
<input type="checkbox" checked={agreed} onChange={(e) => setAgreed(e.target.checked)} />
|
||||
<span>
|
||||
我已阅读并同意{' '}
|
||||
<Link to="/legal/user-agreement" className="text-primary" style={{ fontWeight: 600 }} onClick={(e) => e.stopPropagation()}>
|
||||
《用户协议》
|
||||
</Link>{' '}
|
||||
与{' '}
|
||||
<Link to="/legal/privacy-policy" className="text-primary" style={{ fontWeight: 600 }} onClick={(e) => e.stopPropagation()}>
|
||||
《隐私政策》
|
||||
</Link>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
|
||||
@@ -13,13 +13,23 @@ html {
|
||||
/* ── Partner auth ── */
|
||||
.partner-auth-page {
|
||||
min-height: 100vh;
|
||||
min-height: 100dvh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 48px var(--space-page) var(--space-page);
|
||||
justify-content: flex-start;
|
||||
padding: 48px var(--space-page) calc(24px + env(safe-area-inset-bottom, 0px));
|
||||
background-color: var(--color-background);
|
||||
background-image: url("https://www.transparenttextures.com/patterns/natural-paper.png");
|
||||
box-sizing: border-box;
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
@media (min-height: 720px) {
|
||||
.partner-auth-page {
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.partner-auth-page--quick {
|
||||
@@ -166,14 +176,27 @@ html {
|
||||
|
||||
.partner-checkbox-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
margin-top: var(--space-md);
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
color: var(--color-on-surface-variant);
|
||||
}
|
||||
|
||||
.partner-checkbox-row input { margin-top: 0; accent-color: var(--color-heritage-red); }
|
||||
.partner-checkbox-row input {
|
||||
margin-top: 2px;
|
||||
flex-shrink: 0;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
accent-color: var(--color-heritage-red);
|
||||
}
|
||||
|
||||
.partner-checkbox-row--agreement {
|
||||
margin-top: 8px;
|
||||
margin-bottom: 4px;
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
.partner-auth-footer {
|
||||
margin-top: var(--space-lg);
|
||||
|
||||
Reference in New Issue
Block a user