fix(admin): UX improvements — silent fetch failures, empty states, batch loading guards, dashboard refresh
- Replace console.error-only catches with message.error user-facing notifications
across Bills, Classes, ClassroomRentals, ClassroomSchedule, Classrooms, Deposits,
Expenses, OperationLogs, Permissions, Roles, RoomVisual, Rooms, Students,
Tenants, Users
- Add Empty component via Table locale prop on list pages: Bills, Classes,
ClassroomRentals, Classrooms, Deposits, Expenses (room+personal), Occupancies,
Rooms, Students, Tenants, Roles
- Add batchLoading state to batch delete/update operations: Bills (batchDelete,
batchUpdateStatus), Expenses (batchDeleteRoom, batchDeletePersonal),
Occupancies (batchCheckOut, batchDelete), Rooms (batchDelete),
Students (batchDelete)
- Add refreshLoading indicator to Dashboard header when re-fetching data
- Consistent error pattern: catch (e: unknown) { const err = e as { message?: string }; message.error(...); }
This commit is contained in:
@@ -15,6 +15,7 @@ import {
|
||||
Upload,
|
||||
Drawer,
|
||||
Tabs,
|
||||
Empty,
|
||||
} from 'antd';
|
||||
import type { UploadRequestError, UploadRequestOption } from '@rc-component/upload/lib/interface';
|
||||
import {
|
||||
@@ -88,8 +89,10 @@ const RoomsPage: React.FC = () => {
|
||||
const [lockerForm] = Form.useForm();
|
||||
const [savingBed, setSavingBed] = useState(false);
|
||||
const [savingLocker, setSavingLocker] = useState(false);
|
||||
const [batchLoading, setBatchLoading] = useState(false);
|
||||
|
||||
const handleBatchDelete = async () => {
|
||||
setBatchLoading(true);
|
||||
try {
|
||||
const res: any = await api.post('/rooms/batch-delete', { ids: selectedRowKeys });
|
||||
message.success(res?.message || `已批量归档 ${selectedRowKeys.length} 间`);
|
||||
@@ -97,6 +100,8 @@ const RoomsPage: React.FC = () => {
|
||||
fetchData();
|
||||
} catch (e: any) {
|
||||
message.error(e?.message || '批量归档失败');
|
||||
} finally {
|
||||
setBatchLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -109,8 +114,9 @@ const RoomsPage: React.FC = () => {
|
||||
setArchivedCount(archived.length);
|
||||
const filtered = showArchived ? res : res.filter((r: any) => r.status !== 'archived');
|
||||
setData(filtered);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
} catch (e: unknown) {
|
||||
const err = e as { message?: string };
|
||||
message.error(err?.message || '加载失败,请稍后重试');
|
||||
}
|
||||
setLoading(false);
|
||||
};
|
||||
@@ -162,14 +168,20 @@ const RoomsPage: React.FC = () => {
|
||||
try {
|
||||
const res = await api.get(`/rooms/${roomId}/beds`);
|
||||
setBeds(res);
|
||||
} catch (e) { console.error(e); }
|
||||
} catch (e: unknown) {
|
||||
const err = e as { message?: string };
|
||||
message.error(err?.message || '加载床位失败');
|
||||
}
|
||||
}, []);
|
||||
|
||||
const fetchLockers = useCallback(async (roomId: number) => {
|
||||
try {
|
||||
const res = await api.get(`/rooms/${roomId}/lockers`);
|
||||
setLockers(res);
|
||||
} catch (e) { console.error(e); }
|
||||
} catch (e: unknown) {
|
||||
const err = e as { message?: string };
|
||||
message.error(err?.message || '加载柜子失败');
|
||||
}
|
||||
}, []);
|
||||
|
||||
const handleSaveBed = async () => {
|
||||
@@ -425,7 +437,13 @@ const RoomsPage: React.FC = () => {
|
||||
cancelText="取消"
|
||||
disabled={selectedRowKeys.length === 0}
|
||||
>
|
||||
<PermissionButton permission="room:delete" danger icon={<DeleteOutlined />} disabled={selectedRowKeys.length === 0}>
|
||||
<PermissionButton
|
||||
permission="room:delete"
|
||||
danger
|
||||
icon={<DeleteOutlined />}
|
||||
disabled={selectedRowKeys.length === 0}
|
||||
loading={batchLoading}
|
||||
>
|
||||
批量归档
|
||||
</PermissionButton>
|
||||
</Popconfirm>
|
||||
@@ -486,6 +504,7 @@ const RoomsPage: React.FC = () => {
|
||||
rowKey="id"
|
||||
scroll={{ x: 1200 }}
|
||||
loading={loading}
|
||||
locale={{ emptyText: <Empty description="暂无数据" /> }}
|
||||
pagination={{ pageSize: 20, showTotal: (total) => `共 ${total} 间` }}
|
||||
rowClassName={(record) => (record.status === 'archived' ? 'archived-row' : '')}
|
||||
rowSelection={{
|
||||
|
||||
Reference in New Issue
Block a user