fix(health): 身份证号18位校验位验证 + 手机号1[3-9]格式校验

后端:
- validation.rs: 新增 validate_id_number(含加权校验位)和 validate_phone(1[3-9]\d{9})
- patient_dto.rs: CreatePatientReq/UpdatePatientReq/FamilyMemberReq 添加 Validate derive
- patient_handler.rs: create/update/family_member handler 调用格式校验

前端:
- PatientList/PatientDetail/FamilyMembersTab: Form.Item 添加 pattern rules + maxLength

测试:15 个新测试用例全部通过
This commit is contained in:
iven
2026-05-21 18:16:41 +08:00
parent 58afc59676
commit 8e616f2210
6 changed files with 176 additions and 17 deletions

View File

@@ -409,8 +409,10 @@ export default function PatientDetail() {
<Form.Item name="birth_date" label="出生日期">
<DatePicker style={{ width: '100%' }} placeholder="请选择" />
</Form.Item>
<Form.Item name="id_number" label="身份证号">
<Input placeholder="请输入身份证号" />
<Form.Item name="id_number" label="身份证号" rules={[
{ pattern: /^[1-9]\d{5}(?:19|20)\d{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/, message: '请输入有效的18位身份证号' },
]}>
<Input placeholder="请输入身份证号" maxLength={18} />
</Form.Item>
<Form.Item name="allergy_history" label="过敏史">
<Input.TextArea rows={2} placeholder="请输入过敏史" />
@@ -422,8 +424,10 @@ export default function PatientDetail() {
<Form.Item name="emergency_contact_name" label="紧急联系人" style={{ flex: 1 }}>
<Input placeholder="联系人姓名" />
</Form.Item>
<Form.Item name="emergency_contact_phone" label="紧急联系电话" style={{ flex: 1 }}>
<Input placeholder="联系电话" />
<Form.Item name="emergency_contact_phone" label="紧急联系电话" style={{ flex: 1 }} rules={[
{ pattern: /^1[3-9]\d{9}$/, message: '请输入有效的11位手机号' },
]}>
<Input placeholder="联系电话" maxLength={11} />
</Form.Item>
</div>
<Form.Item name="notes" label="备注">

View File

@@ -441,8 +441,10 @@ export default function PatientList() {
title: '联系方式',
fields: (
<>
<Form.Item name="id_number" label="身份证号">
<Input placeholder="请输入身份证号" />
<Form.Item name="id_number" label="身份证号" rules={[
{ pattern: /^[1-9]\d{5}(?:19|20)\d{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/, message: '请输入有效的18位身份证号' },
]}>
<Input placeholder="请输入身份证号" maxLength={18} />
</Form.Item>
<Form.Item name="source" label="来源">
<Input placeholder="请输入患者来源" />
@@ -473,8 +475,10 @@ export default function PatientList() {
<Form.Item name="emergency_contact_name" label="联系人姓名">
<Input placeholder="请输入紧急联系人姓名" />
</Form.Item>
<Form.Item name="emergency_contact_phone" label="联系电话">
<Input placeholder="请输入紧急联系人电话" />
<Form.Item name="emergency_contact_phone" label="联系电话" rules={[
{ pattern: /^1[3-9]\d{9}$/, message: '请输入有效的11位手机号' },
]}>
<Input placeholder="请输入紧急联系人电话" maxLength={11} />
</Form.Item>
</>
),

View File

@@ -37,6 +37,7 @@ export function FamilyMembersTab({ patientId }: Props) {
setLoading(false);
}, [patientId]);
// eslint-disable-next-line react-hooks/set-state-in-effect
useEffect(() => { fetchMembers(); }, [fetchMembers]);
const handleSubmit = async (values: CreateFamilyMemberReq) => {
@@ -139,11 +140,15 @@ export function FamilyMembersTab({ patientId }: Props) {
<Form.Item name="relationship" label="关系" rules={[{ required: true, message: '请选择关系' }]}>
<Select options={RELATIONSHIP_OPTIONS} placeholder="选择关系" />
</Form.Item>
<Form.Item name="phone" label="电话">
<Input />
<Form.Item name="phone" label="电话" rules={[
{ pattern: /^1[3-9]\d{9}$/, message: '请输入有效的11位手机号' },
]}>
<Input maxLength={11} />
</Form.Item>
<Form.Item name="id_number" label="身份证号">
<Input />
<Form.Item name="id_number" label="身份证号" rules={[
{ pattern: /^[1-9]\d{5}(?:19|20)\d{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/, message: '请输入有效的18位身份证号' },
]}>
<Input maxLength={18} />
</Form.Item>
<Form.Item name="notes" label="备注">
<Input.TextArea rows={2} />