门店账号管理修改

This commit is contained in:
2026-07-07 00:01:16 +08:00
parent e85c4b9bcb
commit 7ca9fc8a35
25 changed files with 599 additions and 134 deletions
+27 -16
View File
@@ -1,24 +1,33 @@
import { useState } from 'react';
import { Link, useNavigate, useSearchParams } from 'react-router-dom';
import AppImage from '@dukang/shared-ui/AppImage';
import { request, saveAuth } from '../lib/api';
import { useStoreSession } from '../contexts/StoreSessionContext';
import { getLastPhone, getStoreProfile, request, type ShopSessionPayload } from '../lib/api';
function maskPhone(phone: string) {
if (phone.length < 7) return phone;
return `${phone.slice(0, 3)} **** ${phone.slice(-4)}`;
}
const DEV_DEFAULT_PHONE = import.meta.env.DEV ? '13900000001' : '';
const DEV_DEFAULT_CODE = import.meta.env.DEV ? '123456' : '';
export default function LoginPage() {
const navigate = useNavigate();
const { applySession } = useStoreSession();
const [params] = useSearchParams();
const quick = params.get('quick') === '1';
const [phone, setPhone] = useState('13900000001');
const [code, setCode] = useState('123456');
const savedProfile = getStoreProfile();
const [phone, setPhone] = useState(getLastPhone() || DEV_DEFAULT_PHONE);
const [code, setCode] = useState(DEV_DEFAULT_CODE);
const [agreed, setAgreed] = useState(false);
const [loading, setLoading] = useState(false);
const [msg, setMsg] = useState('');
const [codeCooldown, setCodeCooldown] = useState(0);
const quickStoreName = savedProfile?.storeName ?? '门店管理中心';
const quickPhone = savedProfile?.phone || phone;
function ensureAgreed() {
if (!agreed) {
setMsg('请先阅读并同意用户协议');
@@ -35,7 +44,7 @@ export default function LoginPage() {
method: 'POST',
body: JSON.stringify({ phone, scene: 'STORE_LOGIN' }),
});
setMsg('验证码已发送(Mock: 123456');
setMsg(import.meta.env.DEV ? '验证码已发送(Mock: 123456' : '验证码已发送');
setCodeCooldown(60);
const timer = setInterval(() => {
setCodeCooldown((c) => {
@@ -51,20 +60,22 @@ export default function LoginPage() {
}
}
async function login() {
if (!ensureAgreed()) return;
async function login(options?: { quick?: boolean }) {
if (!options?.quick && !ensureAgreed()) return;
setLoading(true);
setMsg('');
try {
await request('SHOP_H5', '/shop/auth/sms/send', {
if (options?.quick) {
await request('SHOP_H5', '/shop/auth/sms/send', {
method: 'POST',
body: JSON.stringify({ phone: quickPhone, scene: 'STORE_LOGIN' }),
});
}
const data = await request<ShopSessionPayload>('SHOP_H5', '/shop/auth/login/sms', {
method: 'POST',
body: JSON.stringify({ phone, scene: 'STORE_LOGIN' }),
body: JSON.stringify({ phone: options?.quick ? quickPhone : phone, code }),
});
const data = await request<{ accessToken: string }>('SHOP_H5', '/shop/auth/login/sms', {
method: 'POST',
body: JSON.stringify({ phone, code }),
});
saveAuth(data);
applySession(data);
navigate('/');
} catch (e) {
setMsg(e instanceof Error ? e.message : '登录失败');
@@ -93,8 +104,8 @@ export default function LoginPage() {
<span className="material-symbols-outlined shop-fill-icon">storefront</span>
</div>
<div>
<h2 className="shop-quick-store-name"></h2>
<p className="shop-quick-store-phone">{maskPhone(phone)}</p>
<h2 className="shop-quick-store-name">{quickStoreName}</h2>
<p className="shop-quick-store-phone">{maskPhone(quickPhone)}</p>
</div>
<span className="shop-quick-verified">
<span className="material-symbols-outlined shop-fill-icon" style={{ fontSize: 14 }}>verified_user</span>
@@ -115,7 +126,7 @@ export default function LoginPage() {
type="button"
className="shop-quick-login-btn"
disabled={loading}
onClick={login}
onClick={() => void login({ quick: true })}
>
<span>{loading ? '登录中...' : '一键登录'}</span>
{!loading && <span className="material-symbols-outlined">arrow_forward</span>}