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

View File

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

View File

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