Initial CMPP frontend prototype

This commit is contained in:
hectorzhao
2026-06-30 16:09:46 +08:00
commit 2f3c274a30
98 changed files with 25255 additions and 0 deletions
+212
View File
@@ -0,0 +1,212 @@
import { useEffect, useMemo, useState } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import { ImagePlus } from 'lucide-react';
import { Button, Input, Select, Textarea } from '@/components/ui';
import {
cityOptionsByProvince,
createEnterprise,
getEnterpriseRecords,
initialEnterpriseForm,
provinceOptions,
toEnterpriseForm,
updateEnterprise,
type EnterpriseForm,
} from './adminEnterpriseMock';
type EnterpriseFormErrors = Partial<Record<keyof EnterpriseForm, string>>;
export function AdminCustomerFormPage() {
const navigate = useNavigate();
const { enterpriseId } = useParams();
const records = useMemo(() => getEnterpriseRecords(), []);
const editingRecord = useMemo(
() => records.find((record) => record.id === enterpriseId),
[enterpriseId, records],
);
const isEdit = Boolean(enterpriseId);
const [form, setForm] = useState<EnterpriseForm>(() => (
editingRecord ? toEnterpriseForm(editingRecord) : initialEnterpriseForm
));
const [errors, setErrors] = useState<EnterpriseFormErrors>({});
useEffect(() => {
setForm(editingRecord ? toEnterpriseForm(editingRecord) : initialEnterpriseForm);
setErrors({});
}, [editingRecord, enterpriseId]);
const cityOptions = [
{ label: '请选择市/区', value: '' },
...(cityOptionsByProvince[form.province] ?? []),
];
function updateForm<K extends keyof EnterpriseForm>(key: K, value: EnterpriseForm[K]) {
setForm((current) => ({
...current,
[key]: value,
...(key === 'province' ? { city: '' } : {}),
}));
setErrors((current) => ({ ...current, [key]: undefined }));
}
function validateForm() {
const nextErrors: EnterpriseFormErrors = {};
if (!form.name.trim()) {
nextErrors.name = '请填写企业名称';
}
if (!form.creditCode.trim()) {
nextErrors.creditCode = '请填写统一社会信用代码';
}
if (!form.contactName.trim()) {
nextErrors.contactName = '请填写联系人姓名';
}
if (!form.contactPhone.trim()) {
nextErrors.contactPhone = '请填写手机号';
}
setErrors(nextErrors);
return Object.keys(nextErrors).length === 0;
}
function submitForm() {
if (!validateForm()) {
return;
}
if (isEdit) {
updateEnterprise(form);
} else {
createEnterprise(form);
}
navigate('/admin/customers');
}
return (
<section className="page-stack enterprise-form-page">
<div className="page-heading">
<div>
<p className="eyebrow"> / {isEdit ? '编辑企业' : '创建企业'}</p>
<h1></h1>
<p></p>
</div>
</div>
<div className="surface enterprise-form-card">
<section className="ui-detail-section">
<div className="ui-detail-section__header">
<div>
<h3></h3>
<p></p>
</div>
</div>
<div className="enterprise-upload-panel">
<span></span>
<button type="button">
<ImagePlus size={28} />
</button>
<p> JPGPNG 5MB</p>
</div>
<div className="form-grid form-grid--two">
<Input
error={errors.name}
label="企业名称"
onChange={(event) => updateForm('name', event.target.value)}
placeholder="请填写企业全称"
required
value={form.name}
/>
<Input
error={errors.creditCode}
hint="修改此项将同步更新该企业在系统中的所有相关记录。"
label="统一社会信用代码"
onChange={(event) => updateForm('creditCode', event.target.value)}
placeholder="请填写统一社会信用代码或纳税识别号"
required
value={form.creditCode}
/>
</div>
<div className="form-grid form-grid--two">
<Select
label="省/直辖市"
onChange={(event) => updateForm('province', event.target.value)}
options={provinceOptions}
value={form.province}
/>
<Select
label="市/区"
onChange={(event) => updateForm('city', event.target.value)}
options={cityOptions}
value={form.city}
/>
</div>
<Textarea
hint="通讯地址可以与营业执照上的地址不一致。"
label="通讯地址"
onChange={(event) => updateForm('address', event.target.value)}
placeholder="请填写详细通讯地址"
rows={4}
value={form.address}
/>
</section>
<section className="ui-detail-section">
<div className="ui-detail-section__header">
<div>
<h3></h3>
<p></p>
</div>
</div>
<div className="enterprise-info-tip">
便
</div>
<div className="form-grid form-grid--two">
<Input
error={errors.contactName}
label="联系人姓名"
onChange={(event) => updateForm('contactName', event.target.value)}
placeholder="请填写企业联系人姓名"
required
value={form.contactName}
/>
<Input
label="身份证号"
onChange={(event) => updateForm('contactIdCard', event.target.value)}
placeholder="请填写企业联系人身份证号"
value={form.contactIdCard}
/>
</div>
<div className="form-grid form-grid--two">
<Input
error={errors.contactPhone}
label="手机号"
onChange={(event) => updateForm('contactPhone', event.target.value)}
placeholder="请填写企业联系人手机号"
required
value={form.contactPhone}
/>
<Input
label="电子邮箱"
onChange={(event) => updateForm('contactEmail', event.target.value)}
placeholder="请填写企业联系人邮箱"
type="email"
value={form.contactEmail}
/>
</div>
</section>
<div className="enterprise-form-footer">
<Button onClick={submitForm}>{isEdit ? '保存企业' : '创建企业'}</Button>
<Button onClick={() => navigate('/admin/customers')} variant="ghost">
</Button>
</div>
</div>
</section>
);
}