feat(v3.4.16): partner UX, package pricing, CS gate, HQ list polish
Stop auto ST from validation_error; show package prices with right-aligned layout; partner store list status/filter and onboard CS QR gate; HQ store table truncation/fixed actions; expose CS config in wechat_mini settings; bind local servers for LAN. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -8,6 +8,7 @@ import OssUploadField from '../components/OssUploadField';
|
||||
import MultiOssUploadField from '../components/MultiOssUploadField';
|
||||
|
||||
import { request } from '../lib/api';
|
||||
import { fetchClientConfig } from '../lib/wechat-auth';
|
||||
import { toastError, toastSuccess } from '../lib/toast';
|
||||
|
||||
import { resolveRegionBinding } from '../lib/china-region';
|
||||
@@ -48,6 +49,9 @@ import { normalizePackageFormItems, validatePackageFormItems } from '../lib/stor
|
||||
|
||||
const STEPS = ['基本信息', '照片上传', '结算资质', '门店套餐'] as const;
|
||||
|
||||
const DEFAULT_PARTNER_ONBOARD_CS_HINT =
|
||||
'使用问题、提现问题等随时可联系【杜康好客】客服';
|
||||
|
||||
type StoreCategoryNode = {
|
||||
id: string;
|
||||
name: string;
|
||||
@@ -98,6 +102,10 @@ export default function StoreCreatePage() {
|
||||
const [fieldErrors, setFieldErrors] = useState<FieldErrors>({});
|
||||
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
const [csAdded, setCsAdded] = useState(false);
|
||||
const [csQrUrl, setCsQrUrl] = useState<string | null>(null);
|
||||
const [csHint, setCsHint] = useState(DEFAULT_PARTNER_ONBOARD_CS_HINT);
|
||||
const [csConfigLoading, setCsConfigLoading] = useState(false);
|
||||
|
||||
const [cities, setCities] = useState<OpenCityOption[]>([]);
|
||||
|
||||
@@ -149,6 +157,29 @@ export default function StoreCreatePage() {
|
||||
});
|
||||
}, [step]);
|
||||
|
||||
useEffect(() => {
|
||||
if (step !== 4) return;
|
||||
let cancelled = false;
|
||||
setCsConfigLoading(true);
|
||||
void fetchClientConfig()
|
||||
.then((cfg) => {
|
||||
if (cancelled) return;
|
||||
setCsQrUrl((cfg.partnerOnboardCsQrUrl ?? '').trim() || null);
|
||||
setCsHint((cfg.partnerOnboardCsHint ?? '').trim() || DEFAULT_PARTNER_ONBOARD_CS_HINT);
|
||||
})
|
||||
.catch(() => {
|
||||
if (cancelled) return;
|
||||
setCsQrUrl(null);
|
||||
setCsHint(DEFAULT_PARTNER_ONBOARD_CS_HINT);
|
||||
})
|
||||
.finally(() => {
|
||||
if (!cancelled) setCsConfigLoading(false);
|
||||
});
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [step]);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
void fetchPartnerCities()
|
||||
@@ -342,6 +373,15 @@ export default function StoreCreatePage() {
|
||||
|
||||
|
||||
async function submit(skipPackages = false) {
|
||||
const qr = (csQrUrl ?? '').trim();
|
||||
if (!qr) {
|
||||
reportFormError('客服二维码暂未配置,请联系总部');
|
||||
return;
|
||||
}
|
||||
if (!csAdded) {
|
||||
reportFormError('请先勾选「我已添加【杜康好客】客服」');
|
||||
return;
|
||||
}
|
||||
|
||||
const msg = validateStoreStep3(form);
|
||||
|
||||
@@ -537,6 +577,7 @@ export default function StoreCreatePage() {
|
||||
|
||||
const progress = step === 1 ? 0 : step === 2 ? 33 : step === 3 ? 66 : 100;
|
||||
|
||||
const canSubmitOnboard = !!csQrUrl?.trim() && csAdded && !submitting && !csConfigLoading;
|
||||
const nextDisabled = submitting;
|
||||
|
||||
|
||||
@@ -1153,6 +1194,37 @@ export default function StoreCreatePage() {
|
||||
|
||||
{step === 4 && (
|
||||
<>
|
||||
<section className="partner-form-card partner-onboard-cs-card">
|
||||
<div className="partner-section-title">
|
||||
<div className="partner-section-bar" />
|
||||
<h2 className="headline-md">添加客服</h2>
|
||||
</div>
|
||||
<p className="label-md text-muted" style={{ marginBottom: 16, lineHeight: 1.5 }}>
|
||||
{csHint}
|
||||
</p>
|
||||
{csConfigLoading ? (
|
||||
<p className="body-md text-muted">加载客服二维码…</p>
|
||||
) : csQrUrl ? (
|
||||
<img
|
||||
className="partner-onboard-cs-qr"
|
||||
src={csQrUrl}
|
||||
alt="杜康好客企微客服二维码"
|
||||
/>
|
||||
) : (
|
||||
<p className="partner-form-error" role="alert">
|
||||
客服二维码暂未配置,请联系总部
|
||||
</p>
|
||||
)}
|
||||
<label className="partner-onboard-cs-check">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={csAdded}
|
||||
disabled={!csQrUrl || submitting}
|
||||
onChange={(e) => setCsAdded(e.target.checked)}
|
||||
/>
|
||||
<span>我已添加【杜康好客】客服</span>
|
||||
</label>
|
||||
</section>
|
||||
<section className="partner-form-card">
|
||||
<div className="partner-section-title">
|
||||
<div className="partner-section-bar" />
|
||||
@@ -1198,13 +1270,21 @@ export default function StoreCreatePage() {
|
||||
) : (
|
||||
|
||||
<>
|
||||
<button type="button" className="partner-btn-outline" onClick={() => void submit(true)} disabled={submitting}>
|
||||
<button
|
||||
type="button"
|
||||
className="partner-btn-outline"
|
||||
onClick={() => void submit(true)}
|
||||
disabled={!canSubmitOnboard}
|
||||
>
|
||||
跳过
|
||||
</button>
|
||||
<button type="button" className="partner-btn-primary" onClick={() => void submit(false)} disabled={submitting}>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className="partner-btn-primary"
|
||||
onClick={() => void submit(false)}
|
||||
disabled={!canSubmitOnboard}
|
||||
>
|
||||
{submitting ? '提交中…' : '提交'}
|
||||
|
||||
</button>
|
||||
</>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user