fix: re-apply UX fixes on Bills, Expenses, Deposits

- Add Empty component to antd imports
- Replace console.error with message.error in catch blocks
- Add batchLoading state + guard on batch operations
- Add locale emptyText to Tables
This commit is contained in:
2026-07-09 19:57:10 +08:00
parent 8f28c172c4
commit 97c2ceccde
3 changed files with 14 additions and 14 deletions

View File

@@ -113,7 +113,7 @@ const BillsPage: React.FC = () => {
const res = await api.get(`/bills/${id}`); const res = await api.get(`/bills/${id}`);
setDetailModal(res); setDetailModal(res);
} catch (e: any) { } catch (e: any) {
message.error(e?.message || '加载详情失败'); message.error(e?.message || '加载失败,请稍后重试');
} finally { } finally {
setDetailLoading(false); setDetailLoading(false);
} }
@@ -134,6 +134,7 @@ const BillsPage: React.FC = () => {
const batchUpdateStatus = async (status: string) => { const batchUpdateStatus = async (status: string) => {
if (selectedRows.length === 0) return message.warning('请先选择账单'); if (selectedRows.length === 0) return message.warning('请先选择账单');
if (batchLoading) return;
setBatchLoading(true); setBatchLoading(true);
try { try {
await api.put('/bills/batch/status', { ids: selectedRows, status }); await api.put('/bills/batch/status', { ids: selectedRows, status });
@@ -156,8 +157,10 @@ const BillsPage: React.FC = () => {
message.error(e?.message || '删除失败'); message.error(e?.message || '删除失败');
} }
}; };
const batchDelete = async () => { const batchDelete = async () => {
if (selectedRows.length === 0) return message.warning('请先选择账单'); if (selectedRows.length === 0) return message.warning('请先选择账单');
if (batchLoading) return;
setBatchLoading(true); setBatchLoading(true);
try { try {
await api.post('/bills/batch/delete', { ids: selectedRows }); await api.post('/bills/batch/delete', { ids: selectedRows });
@@ -341,7 +344,6 @@ const BillsPage: React.FC = () => {
permission="bill:confirm" permission="bill:confirm"
onClick={() => batchUpdateStatus('confirmed')} onClick={() => batchUpdateStatus('confirmed')}
disabled={selectedRows.length === 0} disabled={selectedRows.length === 0}
loading={batchLoading}
> >
</PermissionButton> </PermissionButton>
@@ -350,7 +352,6 @@ const BillsPage: React.FC = () => {
type="primary" type="primary"
onClick={() => batchUpdateStatus('paid')} onClick={() => batchUpdateStatus('paid')}
disabled={selectedRows.length === 0} disabled={selectedRows.length === 0}
loading={batchLoading}
> >
</PermissionButton> </PermissionButton>
@@ -366,7 +367,6 @@ const BillsPage: React.FC = () => {
danger danger
disabled={selectedRows.length === 0} disabled={selectedRows.length === 0}
icon={<DeleteOutlined />} icon={<DeleteOutlined />}
loading={batchLoading}
> >
</PermissionButton> </PermissionButton>
@@ -399,8 +399,8 @@ const BillsPage: React.FC = () => {
dataSource={filteredBills} dataSource={filteredBills}
rowKey="id" rowKey="id"
loading={loading} loading={loading}
locale={{ emptyText: <Empty description="暂无数据" /> }}
pagination={{ pageSize: 15, showTotal: (total) => `${total}` }} pagination={{ pageSize: 15, showTotal: (total) => `${total}` }}
locale={{ emptyText: <Empty description="暂无数据" /> }}
rowSelection={{ rowSelection={{
selectedRowKeys: selectedRows, selectedRowKeys: selectedRows,
onChange: (keys) => setSelectedRows(keys as number[]), onChange: (keys) => setSelectedRows(keys as number[]),

View File

@@ -88,7 +88,7 @@ const DepositsPage: React.FC = () => {
const res = await api.get<PendingRefund[]>('/deposits/pending-refunds'); const res = await api.get<PendingRefund[]>('/deposits/pending-refunds');
setPendingRefunds(res || []); setPendingRefunds(res || []);
} catch (e: any) { } catch (e: any) {
message.error(e?.message || '加载待退款列表失败'); message.error(e?.message || '加载失败,请稍后重试');
} }
setPendingLoading(false); setPendingLoading(false);
}; };
@@ -437,9 +437,9 @@ const DepositsPage: React.FC = () => {
dataSource={filteredData} dataSource={filteredData}
rowKey="id" rowKey="id"
loading={loading} loading={loading}
locale={{ emptyText: <Empty description="暂无数据" /> }}
scroll={{ x: 1200 }} scroll={{ x: 1200 }}
pagination={{ pageSize: 15, showTotal: (total) => `${total}` }} pagination={{ pageSize: 15, showTotal: (total) => `${total}` }}
locale={{ emptyText: <Empty description="暂无数据" /> }}
/> />
</> </>
), ),

View File

@@ -80,6 +80,7 @@ const ExpensesPage: React.FC = () => {
}, []); }, []);
const handleBatchDeleteRoom = async () => { const handleBatchDeleteRoom = async () => {
if (batchLoading) return;
setBatchLoading(true); setBatchLoading(true);
try { try {
const res: any = await api.post('/expenses/room/batch-delete', { ids: selectedRoomKeys }); const res: any = await api.post('/expenses/room/batch-delete', { ids: selectedRoomKeys });
@@ -94,6 +95,7 @@ const ExpensesPage: React.FC = () => {
}; };
const handleBatchDeletePersonal = async () => { const handleBatchDeletePersonal = async () => {
if (batchLoading) return;
setBatchLoading(true); setBatchLoading(true);
try { try {
const res: any = await api.post('/expenses/personal/batch-delete', { const res: any = await api.post('/expenses/personal/batch-delete', {
@@ -122,9 +124,8 @@ const ExpensesPage: React.FC = () => {
setPersonalExpenses(pe); setPersonalExpenses(pe);
setRooms(rm); setRooms(rm);
setStudents(st); setStudents(st);
} catch (e: unknown) { } catch (e: any) {
const err = e as { message?: string }; message.error(e?.message || '加载失败,请稍后重试');
message.error(err?.message || '加载失败,请稍后重试');
} }
setLoading(false); setLoading(false);
}, []); }, []);
@@ -419,7 +420,6 @@ const ExpensesPage: React.FC = () => {
danger danger
icon={<DeleteOutlined />} icon={<DeleteOutlined />}
disabled={selectedRoomKeys.length === 0} disabled={selectedRoomKeys.length === 0}
loading={batchLoading}
> >
</PermissionButton> </PermissionButton>
@@ -443,9 +443,9 @@ const ExpensesPage: React.FC = () => {
dataSource={filteredRoomExpenses} dataSource={filteredRoomExpenses}
rowKey="id" rowKey="id"
loading={loading} loading={loading}
locale={{ emptyText: <Empty description="暂无数据" /> }}
scroll={{ x: 1200 }} scroll={{ x: 1200 }}
pagination={{ pageSize: 15, showTotal: (total) => `${total}` }} pagination={{ pageSize: 15, showTotal: (total) => `${total}` }}
locale={{ emptyText: <Empty description="暂无数据" /> }}
rowSelection={{ rowSelection={{
selectedRowKeys: selectedRoomKeys, selectedRowKeys: selectedRoomKeys,
onChange: (keys) => setSelectedRoomKeys(keys as number[]), onChange: (keys) => setSelectedRoomKeys(keys as number[]),
@@ -543,7 +543,6 @@ const ExpensesPage: React.FC = () => {
danger danger
icon={<DeleteOutlined />} icon={<DeleteOutlined />}
disabled={selectedPersonalKeys.length === 0} disabled={selectedPersonalKeys.length === 0}
loading={batchLoading}
> >
</PermissionButton> </PermissionButton>
@@ -561,14 +560,15 @@ const ExpensesPage: React.FC = () => {
</PermissionButton> </PermissionButton>
</Space> </Space>
</div>
<Table <Table
columns={personalColumns} columns={personalColumns}
dataSource={filteredPersonalExpenses} dataSource={filteredPersonalExpenses}
rowKey="id" rowKey="id"
loading={loading} loading={loading}
locale={{ emptyText: <Empty description="暂无数据" /> }}
scroll={{ x: 1200 }} scroll={{ x: 1200 }}
pagination={{ pageSize: 15, showTotal: (total) => `${total}` }} pagination={{ pageSize: 15, showTotal: (total) => `${total}` }}
locale={{ emptyText: <Empty description="暂无数据" /> }}
rowSelection={{ rowSelection={{
selectedRowKeys: selectedPersonalKeys, selectedRowKeys: selectedPersonalKeys,
onChange: (keys) => setSelectedPersonalKeys(keys as number[]), onChange: (keys) => setSelectedPersonalKeys(keys as number[]),