fix:提交修复6个问题
This commit is contained in:
@@ -1,367 +1,929 @@
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
|
||||
import { useNavigate, useSearchParams } from 'react-router-dom';
|
||||
|
||||
import PageHeader from '@dukang/shared-ui/PageHeader';
|
||||
|
||||
import ChinaRegionPicker from '../components/ChinaRegionPicker';
|
||||
|
||||
import OssUploadField from '../components/OssUploadField';
|
||||
|
||||
import { request } from '../lib/api';
|
||||
|
||||
import { resolveRegionBinding } from '../lib/china-region';
|
||||
|
||||
import { checkStorePhoneAvailable } from '../lib/storePhone';
|
||||
|
||||
import { fetchPartnerCities, type OpenCityOption } from '../lib/upload';
|
||||
|
||||
import {
|
||||
|
||||
fetchPartnerProfile,
|
||||
|
||||
handlePartnerWechatCallback,
|
||||
|
||||
savePartnerWechatAuth,
|
||||
|
||||
} from '../lib/wechat-auth';
|
||||
|
||||
import { isWechatEnv, weixinSdk } from '../lib/weixin';
|
||||
|
||||
import { stripOAuthParamsFromLocation } from '@dukang/weixin-sdk';
|
||||
|
||||
import {
|
||||
|
||||
clearStoreDraft,
|
||||
|
||||
defaultStoreForm,
|
||||
|
||||
loadStoreDraft,
|
||||
|
||||
saveStoreDraft,
|
||||
|
||||
type StoreDraftForm,
|
||||
|
||||
validateStoreStep1,
|
||||
|
||||
validateStoreStep2,
|
||||
|
||||
validateStoreStep3,
|
||||
|
||||
} from '../lib/storeDraft';
|
||||
|
||||
|
||||
|
||||
const STEPS = ['基本信息', '照片上传', '结算资质'] as const;
|
||||
|
||||
|
||||
|
||||
type FieldErrors = {
|
||||
|
||||
phone?: string;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
function isPhoneConflictMessage(message: string) {
|
||||
|
||||
return message.includes('手机号已绑定');
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
export default function StoreCreatePage() {
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [params, setParams] = useSearchParams();
|
||||
|
||||
const saved = loadStoreDraft();
|
||||
|
||||
const [form, setForm] = useState<StoreDraftForm>(saved?.form ?? defaultStoreForm());
|
||||
const [error, setError] = useState('');
|
||||
|
||||
const [submitError, setSubmitError] = useState('');
|
||||
|
||||
const [fieldErrors, setFieldErrors] = useState<FieldErrors>({});
|
||||
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
|
||||
const [checkingPhone, setCheckingPhone] = useState(false);
|
||||
|
||||
const [cities, setCities] = useState<OpenCityOption[]>([]);
|
||||
|
||||
const [citiesError, setCitiesError] = useState('');
|
||||
|
||||
const [wechatReady, setWechatReady] = useState(false);
|
||||
|
||||
|
||||
|
||||
const stepFromUrl = Number(params.get('step') || 0);
|
||||
|
||||
const step = stepFromUrl >= 1 && stepFromUrl <= 3 ? stepFromUrl : (saved?.step ?? 1);
|
||||
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
if (!stepFromUrl && saved?.step) {
|
||||
|
||||
setParams({ step: String(saved.step) }, { replace: true });
|
||||
|
||||
}
|
||||
|
||||
}, [stepFromUrl, saved?.step, setParams]);
|
||||
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
saveStoreDraft({ step, form });
|
||||
|
||||
}, [step, form]);
|
||||
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
if (step !== 2 || !isWechatEnv()) return;
|
||||
|
||||
void fetchPartnerProfile()
|
||||
|
||||
.then((me) => setWechatReady(!!me.hasWechat))
|
||||
|
||||
.catch(() => setWechatReady(false));
|
||||
|
||||
void weixinSdk.init().catch(() => {
|
||||
|
||||
/* OssUploadField 点击时会再次初始化 */
|
||||
|
||||
});
|
||||
|
||||
}, [step]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isWechatEnv() || !params.get('code')) return;
|
||||
void handlePartnerWechatCallback()
|
||||
.then((result) => {
|
||||
if (result && savePartnerWechatAuth(result)) {
|
||||
setWechatReady(true);
|
||||
}
|
||||
})
|
||||
.catch((e) => setError(e instanceof Error ? e.message : '微信授权失败'));
|
||||
}, [params]);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
void fetchPartnerCities()
|
||||
.then((items) => {
|
||||
setCities(items);
|
||||
if (!items.length) setCitiesError('暂无开城城市,请联系总部在后台配置');
|
||||
|
||||
if (!isWechatEnv() || !params.get('code')) return;
|
||||
|
||||
void handlePartnerWechatCallback()
|
||||
|
||||
.then((result) => {
|
||||
|
||||
if (result && savePartnerWechatAuth(result)) {
|
||||
|
||||
setWechatReady(true);
|
||||
|
||||
}
|
||||
|
||||
stripOAuthParamsFromLocation();
|
||||
|
||||
const next = new URLSearchParams(params);
|
||||
|
||||
next.delete('code');
|
||||
|
||||
next.delete('state');
|
||||
|
||||
setParams(next, { replace: true });
|
||||
|
||||
void weixinSdk.init().catch(() => {
|
||||
|
||||
/* OssUploadField 点击时会再次初始化 */
|
||||
|
||||
});
|
||||
|
||||
})
|
||||
|
||||
.catch((e) => setSubmitError(e instanceof Error ? e.message : '微信授权失败'));
|
||||
|
||||
}, [params, setParams]);
|
||||
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
void fetchPartnerCities()
|
||||
|
||||
.then((items) => {
|
||||
|
||||
setCities(items);
|
||||
|
||||
if (!items.length) setCitiesError('暂无开城城市,请联系总部在后台配置');
|
||||
|
||||
})
|
||||
|
||||
.catch((e) => setCitiesError(e instanceof Error ? e.message : '加载开城城市失败'));
|
||||
|
||||
}, []);
|
||||
|
||||
|
||||
|
||||
const regionBindingHint = useMemo(() => {
|
||||
|
||||
if (!form.regionCodes.length) return null;
|
||||
|
||||
const binding = resolveRegionBinding(form.regionCodes, cities);
|
||||
|
||||
if (!binding) return null;
|
||||
|
||||
if (binding.cityId && binding.matchedCity) {
|
||||
|
||||
return `已匹配开城城市:${binding.matchedCity.name}`;
|
||||
|
||||
}
|
||||
|
||||
return '所选地区暂未开城,请联系总部配置对应区划';
|
||||
|
||||
}, [form.regionCodes, cities]);
|
||||
|
||||
|
||||
|
||||
function patchForm(patch: Partial<StoreDraftForm>) {
|
||||
|
||||
setForm((prev) => ({ ...prev, ...patch }));
|
||||
setError('');
|
||||
|
||||
setSubmitError('');
|
||||
|
||||
if ('phone' in patch) {
|
||||
|
||||
setFieldErrors((prev) => ({ ...prev, phone: undefined }));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function bindRegionSelection(codes: string[]) {
|
||||
|
||||
const binding = resolveRegionBinding(codes, cities);
|
||||
|
||||
if (!binding) {
|
||||
|
||||
patchForm({ regionCodes: codes, cityId: '', province: '', city: '', district: '' });
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
patchForm({
|
||||
|
||||
regionCodes: codes,
|
||||
|
||||
cityId: binding.cityId ?? '',
|
||||
|
||||
province: binding.region.province,
|
||||
|
||||
city: binding.region.city,
|
||||
|
||||
district: binding.region.district,
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function goStep(n: number) {
|
||||
|
||||
setParams({ step: String(n) });
|
||||
setError('');
|
||||
|
||||
setSubmitError('');
|
||||
|
||||
}
|
||||
|
||||
function handleNext() {
|
||||
|
||||
|
||||
async function handleNext() {
|
||||
|
||||
if (step === 1) {
|
||||
|
||||
const msg = validateStoreStep1(form);
|
||||
if (msg) { setError(msg); return; }
|
||||
|
||||
if (msg) {
|
||||
|
||||
setSubmitError(msg);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
setCheckingPhone(true);
|
||||
|
||||
setSubmitError('');
|
||||
|
||||
setFieldErrors({});
|
||||
|
||||
try {
|
||||
|
||||
const phoneCheck = await checkStorePhoneAvailable(form.phone.trim());
|
||||
|
||||
if (!phoneCheck.available) {
|
||||
|
||||
setFieldErrors({
|
||||
|
||||
phone: phoneCheck.message ?? '该手机号已绑定门店,请更换',
|
||||
|
||||
});
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
|
||||
setSubmitError(e instanceof Error ? e.message : '手机号校验失败');
|
||||
|
||||
return;
|
||||
|
||||
} finally {
|
||||
|
||||
setCheckingPhone(false);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (step === 2) {
|
||||
|
||||
const msg = validateStoreStep2(form);
|
||||
|
||||
if (msg) {
|
||||
|
||||
setSubmitError(msg);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
goStep(step + 1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
async function submit() {
|
||||
|
||||
const msg = validateStoreStep3(form);
|
||||
if (msg) { setError(msg); return; }
|
||||
|
||||
if (msg) {
|
||||
|
||||
setSubmitError(msg);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
const step1Msg = validateStoreStep1(form);
|
||||
if (step1Msg) { setError(step1Msg); return; }
|
||||
|
||||
if (step1Msg) {
|
||||
|
||||
setSubmitError(step1Msg);
|
||||
|
||||
goStep(1);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
const step2Msg = validateStoreStep2(form);
|
||||
|
||||
if (step2Msg) {
|
||||
|
||||
setSubmitError(step2Msg);
|
||||
|
||||
goStep(2);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
setSubmitting(true);
|
||||
setError('');
|
||||
|
||||
setSubmitError('');
|
||||
|
||||
setFieldErrors({});
|
||||
|
||||
try {
|
||||
|
||||
const phoneCheck = await checkStorePhoneAvailable(form.phone.trim());
|
||||
|
||||
if (!phoneCheck.available) {
|
||||
|
||||
setFieldErrors({
|
||||
|
||||
phone: phoneCheck.message ?? '该手机号已绑定门店,请更换',
|
||||
|
||||
});
|
||||
|
||||
goStep(1);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
const envPhotoUrls = form.envPhotoUrls.map((u) => u.trim()).filter(Boolean);
|
||||
|
||||
const result = await request<{ store: { id: string } }>('PARTNER_H5', '/partner/stores', {
|
||||
|
||||
method: 'POST',
|
||||
|
||||
body: JSON.stringify({
|
||||
|
||||
cityId: form.cityId,
|
||||
|
||||
province: form.province,
|
||||
|
||||
city: form.city,
|
||||
|
||||
name: form.name.trim(),
|
||||
|
||||
phone: form.phone.trim(),
|
||||
|
||||
district: form.district.trim(),
|
||||
|
||||
address: form.address.trim(),
|
||||
|
||||
intro: form.intro.trim() || undefined,
|
||||
|
||||
coverUrl: form.coverUrl.trim() || undefined,
|
||||
|
||||
envPhotoUrls: envPhotoUrls.length ? envPhotoUrls : undefined,
|
||||
|
||||
contractUrl: form.contractUrl.trim() || undefined,
|
||||
|
||||
bankAccountName: form.bankAccountName.trim(),
|
||||
|
||||
bankAccountNo: form.bankAccountNo.replace(/\s/g, ''),
|
||||
|
||||
bankBranch: form.bankBranch.trim(),
|
||||
|
||||
}),
|
||||
|
||||
});
|
||||
|
||||
clearStoreDraft();
|
||||
|
||||
navigate(`/stores/${result.store.id}`);
|
||||
|
||||
} catch (e) {
|
||||
setError(e instanceof Error ? e.message : '提交失败');
|
||||
|
||||
const message = e instanceof Error ? e.message : '提交失败';
|
||||
|
||||
if (isPhoneConflictMessage(message)) {
|
||||
|
||||
setFieldErrors({ phone: message });
|
||||
|
||||
goStep(1);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
setSubmitError(message);
|
||||
|
||||
} finally {
|
||||
|
||||
setSubmitting(false);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
const progress = step === 1 ? 0 : step === 2 ? 50 : 100;
|
||||
|
||||
const nextDisabled = submitting || checkingPhone;
|
||||
|
||||
|
||||
|
||||
return (
|
||||
|
||||
<div className="partner-page-sticky">
|
||||
|
||||
<PageHeader title="录入新门店" onBack={() => navigate('/stores')} />
|
||||
|
||||
|
||||
|
||||
<nav className="partner-stepper">
|
||||
|
||||
<div className="partner-stepper-inner">
|
||||
|
||||
<div className="partner-stepper-line" aria-hidden>
|
||||
|
||||
<div className="partner-stepper-line-fill" style={{ width: `${progress}%` }} />
|
||||
|
||||
</div>
|
||||
|
||||
{STEPS.map((label, i) => {
|
||||
|
||||
const n = i + 1;
|
||||
|
||||
const done = step > n;
|
||||
|
||||
const active = step === n;
|
||||
|
||||
return (
|
||||
|
||||
<div key={label} className="partner-step">
|
||||
|
||||
<div className={`partner-step-circle${done ? ' partner-step-circle--done' : ''}${active ? ' partner-step-circle--active' : ''}`}>
|
||||
|
||||
{done ? <span className="material-symbols-outlined" style={{ fontSize: 16, fontVariationSettings: "'FILL' 1" }}>check</span> : n}
|
||||
|
||||
</div>
|
||||
|
||||
<span className={`partner-step-label${active || done ? ' partner-step-label--active' : ''}`}>{label}</span>
|
||||
|
||||
</div>
|
||||
|
||||
);
|
||||
|
||||
})}
|
||||
|
||||
</div>
|
||||
|
||||
</nav>
|
||||
|
||||
{(error || citiesError) && (
|
||||
<p className="partner-form-error" role="alert">{error || citiesError}</p>
|
||||
|
||||
|
||||
{(submitError || citiesError) && (
|
||||
|
||||
<p className="partner-form-error" role="alert">{submitError || citiesError}</p>
|
||||
|
||||
)}
|
||||
|
||||
|
||||
|
||||
{step === 1 && (
|
||||
|
||||
<>
|
||||
|
||||
<section className="partner-form-card">
|
||||
|
||||
<div className="partner-section-title">
|
||||
|
||||
<div className="partner-section-bar" />
|
||||
|
||||
<h2 className="headline-md">门店基本信息</h2>
|
||||
|
||||
</div>
|
||||
|
||||
<div className="partner-field">
|
||||
|
||||
<label>所在地区 <span className="text-primary">*</span></label>
|
||||
|
||||
<ChinaRegionPicker value={form.regionCodes} onChange={bindRegionSelection} />
|
||||
|
||||
{regionBindingHint && (
|
||||
|
||||
<p className={`label-md${form.cityId ? ' text-muted' : ' text-primary'}`} style={{ marginTop: 8 }}>
|
||||
|
||||
{regionBindingHint}
|
||||
|
||||
</p>
|
||||
|
||||
)}
|
||||
|
||||
</div>
|
||||
|
||||
<div className="partner-field">
|
||||
|
||||
<label>门店名称 <span className="text-primary">*</span></label>
|
||||
|
||||
<div className="partner-field-input">
|
||||
|
||||
<span className="material-symbols-outlined">store</span>
|
||||
|
||||
<input placeholder="请输入门店名称" value={form.name} onChange={(e) => patchForm({ name: e.target.value })} />
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div className="partner-field">
|
||||
|
||||
<label>联系电话(门店登录账号) <span className="text-primary">*</span></label>
|
||||
|
||||
<div className="partner-field-input">
|
||||
|
||||
<span className="material-symbols-outlined">call</span>
|
||||
<input type="tel" placeholder="请输入11位手机号" value={form.phone} onChange={(e) => patchForm({ phone: e.target.value })} />
|
||||
|
||||
<input
|
||||
|
||||
type="tel"
|
||||
|
||||
placeholder="请输入11位手机号"
|
||||
|
||||
value={form.phone}
|
||||
|
||||
onChange={(e) => patchForm({ phone: e.target.value })}
|
||||
|
||||
/>
|
||||
|
||||
</div>
|
||||
|
||||
{fieldErrors.phone && (
|
||||
|
||||
<p className="partner-field-error" role="alert">{fieldErrors.phone}</p>
|
||||
|
||||
)}
|
||||
|
||||
</div>
|
||||
|
||||
<div className="partner-field">
|
||||
|
||||
<label>详细地址 <span className="text-primary">*</span></label>
|
||||
|
||||
<textarea rows={2} placeholder="请输入详细门牌号" value={form.address} onChange={(e) => patchForm({ address: e.target.value })} />
|
||||
|
||||
</div>
|
||||
|
||||
<div className="partner-field">
|
||||
|
||||
<label>门店简介</label>
|
||||
|
||||
<textarea rows={4} placeholder="请输入门店简介 (10-500字)" value={form.intro} onChange={(e) => patchForm({ intro: e.target.value })} />
|
||||
|
||||
<div style={{ textAlign: 'right', marginTop: 4 }}>
|
||||
|
||||
<span className="label-md text-muted">{form.intro.length} / 500</span>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
<div className="partner-info-banner">
|
||||
|
||||
<div className="partner-bills-icon">
|
||||
|
||||
<span className="material-symbols-outlined">verified_user</span>
|
||||
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
||||
<h3 className="body-md text-primary" style={{ fontWeight: 700 }}>杜康合伙人身份认证</h3>
|
||||
|
||||
<p className="label-md text-variant" style={{ marginTop: 4, lineHeight: 1.4 }}>
|
||||
|
||||
填写内容将自动保存,退出后可继续录入。
|
||||
|
||||
</p>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</>
|
||||
|
||||
)}
|
||||
|
||||
|
||||
|
||||
{step === 2 && (
|
||||
|
||||
<>
|
||||
|
||||
<div className="partner-section-title" style={{ padding: '0 20px', marginBottom: 16 }}>
|
||||
|
||||
<div className="partner-bills-icon" style={{ background: '#ffdad7', borderRadius: 8, width: 40, height: 40 }}>
|
||||
|
||||
<span className="material-symbols-outlined text-primary">photo_library</span>
|
||||
|
||||
</div>
|
||||
|
||||
<h2 className="headline-md">门店图片上传</h2>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<section className="partner-form-card">
|
||||
<h3 className="headline-md">门头照</h3>
|
||||
<p className="label-md text-muted" style={{ margin: '4px 0 12px' }}>建议至少 1 张,需包含完整招牌</p>
|
||||
|
||||
<h3 className="headline-md">门头照 <span className="text-primary">*</span></h3>
|
||||
|
||||
<p className="label-md text-muted" style={{ margin: '4px 0 12px' }}>至少 1 张,需包含完整招牌</p>
|
||||
|
||||
<OssUploadField
|
||||
|
||||
wide
|
||||
|
||||
bizType="STORE_TITLE"
|
||||
|
||||
mediaType="IMAGE"
|
||||
|
||||
value={form.coverUrl}
|
||||
|
||||
wechatReady={wechatReady}
|
||||
|
||||
onWechatReadyChange={setWechatReady}
|
||||
|
||||
onChange={(coverUrl) => patchForm({ coverUrl })}
|
||||
|
||||
label="点击或拖拽上传"
|
||||
|
||||
/>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
<section className="partner-form-card">
|
||||
<h3 className="headline-md">环境照片</h3>
|
||||
<p className="label-md text-muted" style={{ margin: '4px 0 12px' }}>建议至少 3 张,展示店内整洁环境</p>
|
||||
|
||||
<h3 className="headline-md">环境照片 <span className="text-primary">*</span></h3>
|
||||
|
||||
<p className="label-md text-muted" style={{ margin: '4px 0 12px' }}>至少 3 张,展示店内整洁环境</p>
|
||||
|
||||
<div className="partner-upload-grid">
|
||||
|
||||
{form.envPhotoUrls.map((url, index) => (
|
||||
|
||||
<OssUploadField
|
||||
|
||||
key={index}
|
||||
|
||||
compact
|
||||
|
||||
bizType="STORE_ENV"
|
||||
|
||||
mediaType="IMAGE"
|
||||
|
||||
value={url}
|
||||
|
||||
wechatReady={wechatReady}
|
||||
|
||||
onWechatReadyChange={setWechatReady}
|
||||
label="添加照片"
|
||||
|
||||
onChange={(nextUrl) => {
|
||||
|
||||
const envPhotoUrls = [...form.envPhotoUrls];
|
||||
|
||||
envPhotoUrls[index] = nextUrl;
|
||||
|
||||
patchForm({ envPhotoUrls });
|
||||
|
||||
}}
|
||||
|
||||
/>
|
||||
|
||||
))}
|
||||
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
<section className="partner-form-card">
|
||||
<h3 className="headline-md">签约合同</h3>
|
||||
|
||||
<h3 className="headline-md">签约合同 <span className="text-primary">*</span></h3>
|
||||
|
||||
<p className="label-md text-muted" style={{ margin: '4px 0 12px' }}>拍照上传签约协议首页与盖章页</p>
|
||||
|
||||
<OssUploadField
|
||||
|
||||
bizType="STORE_CONTRACT"
|
||||
|
||||
mediaType="FILE"
|
||||
|
||||
accept="image/*,.pdf"
|
||||
|
||||
value={form.contractUrl}
|
||||
|
||||
wechatReady={wechatReady}
|
||||
|
||||
onWechatReadyChange={setWechatReady}
|
||||
|
||||
onChange={(contractUrl) => patchForm({ contractUrl })}
|
||||
|
||||
label="上传合同副本"
|
||||
|
||||
/>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
<div className="partner-info-banner" style={{ background: 'rgba(254,214,91,0.2)', borderColor: 'rgba(254,214,91,0.5)' }}>
|
||||
|
||||
<span className="material-symbols-outlined text-secondary" style={{ fontSize: 18 }}>info</span>
|
||||
|
||||
<p className="label-md" style={{ lineHeight: 1.5, color: 'var(--color-on-secondary-container)' }}>
|
||||
照片与合同将上传至 OSS 存储;与总部后台一致,选填项可跳过直接下一步。
|
||||
|
||||
温馨提示:请确保照片清晰无反光,避免遮挡关键信息。如上传失败,请检查网络或联系客户经理。
|
||||
|
||||
</p>
|
||||
|
||||
</div>
|
||||
|
||||
</>
|
||||
|
||||
)}
|
||||
|
||||
|
||||
|
||||
{step === 3 && (
|
||||
|
||||
<>
|
||||
|
||||
<div className="partner-section-title" style={{ padding: '0 20px', marginBottom: 16 }}>
|
||||
|
||||
<span className="material-symbols-outlined text-primary">account_balance</span>
|
||||
|
||||
<h2 className="headline-md">结算信息配置</h2>
|
||||
|
||||
</div>
|
||||
<section className="partner-form-card">
|
||||
<div className="partner-field">
|
||||
<label>户主姓名 *</label>
|
||||
<input className="partner-field-input partner-field-input--block" placeholder="请输入银行卡实名姓名" value={form.bankAccountName} onChange={(e) => patchForm({ bankAccountName: e.target.value })} />
|
||||
</div>
|
||||
<div className="partner-field">
|
||||
<label>银行卡号 *</label>
|
||||
<input className="partner-field-input partner-field-input--block" placeholder="请输入16-19位银行卡号" value={form.bankAccountNo} onChange={(e) => patchForm({ bankAccountNo: e.target.value })} />
|
||||
</div>
|
||||
<div className="partner-field">
|
||||
<label>开户支行 *</label>
|
||||
<input className="partner-field-input partner-field-input--block" placeholder="例如:中国工商银行洛阳分行" value={form.bankBranch} onChange={(e) => patchForm({ bankBranch: e.target.value })} />
|
||||
|
||||
<section className="partner-form-card partner-store-phone-summary">
|
||||
|
||||
<div className="partner-store-phone-summary-main">
|
||||
|
||||
<span className="label-md text-muted">门店登录手机号</span>
|
||||
|
||||
<span className="body-md">{form.phone.trim() || '未填写'}</span>
|
||||
|
||||
</div>
|
||||
|
||||
<button type="button" className="partner-weekly-link" onClick={() => goStep(1)}>
|
||||
|
||||
修改
|
||||
|
||||
</button>
|
||||
|
||||
</section>
|
||||
|
||||
<section className="partner-form-card">
|
||||
|
||||
<div className="partner-field">
|
||||
|
||||
<label>户主姓名 *</label>
|
||||
|
||||
<input className="partner-field-input partner-field-input--block" placeholder="请输入银行卡实名姓名" value={form.bankAccountName} onChange={(e) => patchForm({ bankAccountName: e.target.value })} />
|
||||
|
||||
</div>
|
||||
|
||||
<div className="partner-field">
|
||||
|
||||
<label>银行卡号 *</label>
|
||||
|
||||
<input className="partner-field-input partner-field-input--block" placeholder="请输入16-19位银行卡号" value={form.bankAccountNo} onChange={(e) => patchForm({ bankAccountNo: e.target.value })} />
|
||||
|
||||
</div>
|
||||
|
||||
<div className="partner-field">
|
||||
|
||||
<label>开户支行 *</label>
|
||||
|
||||
<input className="partner-field-input partner-field-input--block" placeholder="例如:中国工商银行洛阳分行" value={form.bankBranch} onChange={(e) => patchForm({ bankBranch: e.target.value })} />
|
||||
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
<div className="partner-info-banner" style={{ background: 'rgba(254,214,91,0.15)', borderColor: 'rgba(254,214,91,0.3)' }}>
|
||||
|
||||
<span className="material-symbols-outlined text-secondary">info</span>
|
||||
|
||||
<p className="body-md" style={{ color: 'var(--color-on-secondary-container)' }}>
|
||||
|
||||
请确保银行卡信息准确,以免影响每月的餐费结算。
|
||||
|
||||
</p>
|
||||
|
||||
</div>
|
||||
|
||||
</>
|
||||
|
||||
)}
|
||||
|
||||
|
||||
|
||||
<footer className="partner-sticky-footer">
|
||||
|
||||
{step > 1 && (
|
||||
<button type="button" className="partner-btn-outline" onClick={() => goStep(step - 1)} disabled={submitting}>上一步</button>
|
||||
|
||||
<button type="button" className="partner-btn-outline" onClick={() => goStep(step - 1)} disabled={nextDisabled}>上一步</button>
|
||||
|
||||
)}
|
||||
|
||||
{step < 3 ? (
|
||||
<button type="button" className="partner-btn-primary" onClick={handleNext}>
|
||||
<span>下一步</span>
|
||||
|
||||
<button type="button" className="partner-btn-primary" onClick={() => void handleNext()} disabled={nextDisabled}>
|
||||
|
||||
<span>{checkingPhone ? '校验中…' : '下一步'}</span>
|
||||
|
||||
<span className="material-symbols-outlined" style={{ fontSize: 20 }}>navigate_next</span>
|
||||
|
||||
</button>
|
||||
|
||||
) : (
|
||||
|
||||
<button type="button" className="partner-btn-primary" onClick={() => void submit()} disabled={submitting}>
|
||||
|
||||
{submitting ? '提交中…' : '提交'}
|
||||
|
||||
</button>
|
||||
|
||||
)}
|
||||
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user