refactor(web): 迁移 3 个健康页面错误处理到 useApiRequest — 消除内联 catch/message.error
Some checks failed
CI / rust-check (push) Has been cancelled
CI / rust-test (push) Has been cancelled
CI / frontend-build (push) Has been cancelled
CI / security-audit (push) Has been cancelled

- PatientList: handleCreateOrEdit/handleDelete/openEditModal 使用 execute
- AppointmentList: handleStatusChange(2处)/handleSubmit 使用 execute
- FollowUpTaskList: handleCreate/handleRecordSubmit/handleAssign/handleDelete 使用 execute
- 移除不再需要的 message 导入(PatientList/FollowUpTaskList)
This commit is contained in:
iven
2026-04-28 19:24:07 +08:00
parent 40a71e5a1c
commit 679d83d3b6
3 changed files with 112 additions and 105 deletions

View File

@@ -28,6 +28,7 @@ import { DrawerForm } from '../../components/DrawerForm';
import { EntityName } from '../../components/EntityName';
import { formatDateTime } from '../../utils/format';
import { usePaginatedData } from '../../hooks/usePaginatedData';
import { useApiRequest } from '../../hooks/useApiRequest';
/** 预约类型选项 */
const APPOINTMENT_TYPE_OPTIONS = [
@@ -127,6 +128,8 @@ export default function AppointmentList() {
},
});
const { execute } = useApiRequest();
const handleFilterChange = useCallback(
(key: keyof AppointmentFilters, value: unknown) => {
setFilters((prev) => ({ ...prev, [key]: value }));
@@ -168,17 +171,15 @@ export default function AppointmentList() {
okText: '确认',
cancelText: '取消',
onOk: async () => {
try {
await appointmentApi.updateStatus(record.id, {
const result = await execute(
() => appointmentApi.updateStatus(record.id, {
status: newStatus,
version: record.version,
...(newStatus === 'cancelled' && { cancel_reason: cancelReason }),
});
message.success('状态更新成功');
refresh();
} catch {
message.error('状态更新失败');
}
}),
'状态更新成功',
);
if (result !== null) refresh();
},
});
} else {
@@ -188,16 +189,14 @@ export default function AppointmentList() {
okText: '确认',
cancelText: '取消',
onOk: async () => {
try {
await appointmentApi.updateStatus(record.id, {
const result = await execute(
() => appointmentApi.updateStatus(record.id, {
status: newStatus,
version: record.version,
});
message.success('状态更新成功');
refresh();
} catch {
message.error('状态更新失败');
}
}),
'状态更新成功',
);
if (result !== null) refresh();
},
});
}
@@ -246,27 +245,26 @@ export default function AppointmentList() {
message.warning('请选择医护');
return;
}
try {
setSubmitting(true);
const req: CreateAppointmentReq = {
patient_id: selectedPatientId,
doctor_id: selectedDoctorId,
appointment_date: (values.appointment_date as Dayjs).format('YYYY-MM-DD'),
start_time: (values.start_time as Dayjs).format('HH:mm'),
end_time: (values.end_time as Dayjs).format('HH:mm'),
appointment_type: (values.appointment_type as string) || 'outpatient',
notes: (values.notes as string) || undefined,
};
await appointmentApi.create(req);
message.success('预约创建成功');
setSubmitting(true);
const req: CreateAppointmentReq = {
patient_id: selectedPatientId,
doctor_id: selectedDoctorId,
appointment_date: (values.appointment_date as Dayjs).format('YYYY-MM-DD'),
start_time: (values.start_time as Dayjs).format('HH:mm'),
end_time: (values.end_time as Dayjs).format('HH:mm'),
appointment_type: (values.appointment_type as string) || 'outpatient',
notes: (values.notes as string) || undefined,
};
const result = await execute(
() => appointmentApi.create(req),
'预约创建成功',
);
setSubmitting(false);
if (result !== null) {
setDrawerOpen(false);
setSelectedPatientId(undefined);
setSelectedDoctorId(undefined);
refresh();
} catch {
message.error('创建预约失败');
} finally {
setSubmitting(false);
}
};

View File

@@ -9,7 +9,6 @@ import {
DatePicker,
Space,
Popconfirm,
message,
} from 'antd';
import { PlusOutlined, EditOutlined, SwapOutlined, DeleteOutlined } from '@ant-design/icons';
import type { ColumnsType, TablePaginationConfig } from 'antd/es/table';
@@ -24,6 +23,7 @@ import { EntityName } from '../../components/EntityName';
import { DrawerForm } from '../../components/DrawerForm';
import { formatDate, formatDateTime } from '../../utils/format';
import { usePaginatedData } from '../../hooks/usePaginatedData';
import { useApiRequest } from '../../hooks/useApiRequest';
const STATUS_OPTIONS = [
{ value: 'pending', label: '待处理' },
@@ -90,6 +90,8 @@ export default function FollowUpTaskList() {
defaultFilters: {},
});
const { execute } = useApiRequest();
// Create task modal
const [createOpen, setCreateOpen] = useState(false);
const [createLoading, setCreateLoading] = useState(false);
@@ -113,26 +115,30 @@ export default function FollowUpTaskList() {
// Create task
const handleCreate = async () => {
let values: CreateFollowUpTaskReq;
try {
const values = await createForm.validateFields();
setCreateLoading(true);
const plannedDate = values.planned_date;
await followUpApi.createTask({
values = await createForm.validateFields();
} catch (err: unknown) {
if (err && typeof err === 'object' && 'errorFields' in err) return;
return;
}
setCreateLoading(true);
const plannedDate = values.planned_date;
const result = await execute(
() => followUpApi.createTask({
patient_id: values.patient_id,
follow_up_type: values.follow_up_type,
planned_date: dayjs.isDayjs(plannedDate) ? plannedDate.format('YYYY-MM-DD') : plannedDate,
assigned_to: values.assigned_to,
content_template: values.content_template,
});
message.success('随访任务创建成功');
}),
'随访任务创建成功',
);
setCreateLoading(false);
if (result !== null) {
setCreateOpen(false);
createForm.resetFields();
refresh(page);
} catch (err: unknown) {
if (err && typeof err === 'object' && 'errorFields' in err) return; // form validation
message.error('创建随访任务失败');
} finally {
setCreateLoading(false);
}
};
@@ -144,9 +150,9 @@ export default function FollowUpTaskList() {
const handleRecordSubmit = async (values: Record<string, unknown>) => {
if (!activeTask) return;
try {
setRecordLoading(true);
await followUpApi.createRecord(activeTask.id, {
setRecordLoading(true);
const result = await execute(
() => followUpApi.createRecord(activeTask.id, {
executed_date: (values.executed_date as dayjs.Dayjs).format('YYYY-MM-DD'),
result: values.result as string,
patient_condition: values.patient_condition as string,
@@ -154,15 +160,14 @@ export default function FollowUpTaskList() {
next_follow_up_date: values.next_follow_up_date
? (values.next_follow_up_date as dayjs.Dayjs).format('YYYY-MM-DD')
: undefined,
});
message.success('随访记录填写成功');
}),
'随访记录填写成功',
);
setRecordLoading(false);
if (result !== null) {
setRecordOpen(false);
setActiveTask(null);
refresh(page);
} catch {
message.error('填写随访记录失败');
} finally {
setRecordLoading(false);
}
};
@@ -178,35 +183,37 @@ export default function FollowUpTaskList() {
const handleAssign = async () => {
if (!assignTask) return;
let values: { assigned_to: string };
try {
const values = await assignForm.validateFields();
setAssignLoading(true);
const req: UpdateFollowUpTaskReq & { version: number } = {
assigned_to: values.assigned_to,
version: assignTask.version,
};
await followUpApi.updateTask(assignTask.id, req);
message.success('分配成功');
values = await assignForm.validateFields();
} catch (err: unknown) {
if (err && typeof err === 'object' && 'errorFields' in err) return;
return;
}
setAssignLoading(true);
const req: UpdateFollowUpTaskReq & { version: number } = {
assigned_to: values.assigned_to,
version: assignTask.version,
};
const result = await execute(
() => followUpApi.updateTask(assignTask.id, req),
'分配成功',
);
setAssignLoading(false);
if (result !== null) {
setAssignOpen(false);
setAssignTask(null);
refresh(page);
} catch (err: unknown) {
if (err && typeof err === 'object' && 'errorFields' in err) return;
message.error('分配失败');
} finally {
setAssignLoading(false);
}
};
// Delete
const handleDelete = async (record: FollowUpTask) => {
try {
await followUpApi.deleteTask(record.id, record.version);
message.success('删除成功');
refresh(page);
} catch {
message.error('删除失败');
}
const result = await execute(
() => followUpApi.deleteTask(record.id, record.version),
'删除成功',
);
if (result !== null) refresh(page);
};
// --- Columns ---

View File

@@ -9,7 +9,6 @@ import {
Select,
Popconfirm,
DatePicker,
message,
} from 'antd';
import {
PlusOutlined,
@@ -29,6 +28,7 @@ import { AuthButton } from '../../components/AuthButton';
import { PageContainer } from '../../components/PageContainer';
import { DrawerForm } from '../../components/DrawerForm';
import { usePaginatedData } from '../../hooks/usePaginatedData';
import { useApiRequest } from '../../hooks/useApiRequest';
import { calcAge, formatDateTime } from '../../utils/format';
import { dayjs } from '../../utils/dayjs';
@@ -53,6 +53,9 @@ export default function PatientList() {
const [editingPatient, setEditingPatient] = useState<PatientDetail | null>(null);
const [selectedRowKeys, setSelectedRowKeys] = useState<string[]>([]);
// ---- API 请求 Hook ----
const { execute } = useApiRequest();
// ---- 分页数据 Hook ----
const {
data: patients,
@@ -125,39 +128,36 @@ export default function PatientList() {
notes: values.notes as string | undefined,
};
try {
if (editingPatient) {
const req: UpdatePatientReq & { version: number } = {
...payload,
version: editingPatient.version,
};
await patientApi.update(editingPatient.id, req);
message.success('患者信息更新成功');
} else {
const successMsg = editingPatient ? '患者信息更新成功' : '患者创建成功';
const result = await execute(
async () => {
if (editingPatient) {
const req: UpdatePatientReq & { version: number } = {
...payload,
version: editingPatient.version,
};
return patientApi.update(editingPatient.id, req);
}
const req: CreatePatientReq = payload;
await patientApi.create(req);
message.success('患者创建成功');
}
return patientApi.create(req);
},
successMsg,
'操作失败',
);
if (result !== null) {
closeModal();
refresh();
} catch (err: unknown) {
const errorMsg =
(err as { response?: { data?: { message?: string } } })?.response?.data
?.message || '操作失败';
message.error(errorMsg);
}
};
const handleDelete = async (id: string) => {
try {
const patient = patients.find((p) => p.id === id);
const version = patient?.version ?? 0;
await patientApi.delete(id, version);
message.success('患者已删除');
refresh();
} catch {
message.error('删除失败');
}
const patient = patients.find((p) => p.id === id);
const version = patient?.version ?? 0;
const result = await execute(
() => patientApi.delete(id, version),
'患者已删除',
);
if (result !== null) refresh();
};
const openCreateModal = () => {
@@ -166,12 +166,14 @@ export default function PatientList() {
};
const openEditModal = async (record: PatientListItem) => {
try {
const detail = await patientApi.get(record.id);
const detail = await execute(
() => patientApi.get(record.id),
undefined,
'获取患者详情失败',
);
if (detail) {
setEditingPatient(detail);
setModalOpen(true);
} catch {
message.error('获取患者详情失败');
}
};