|
|
@@ -10,9 +10,10 @@ import { formatCurrency, formatDate } from '@/client/utils/utils';
|
|
|
import { logger } from '@/client/utils/logger';
|
|
|
|
|
|
// 定义日志记录器
|
|
|
-const apiLogger = logger('frontend:api:expenses');
|
|
|
-const errorLogger = logger('frontend:error:expenses');
|
|
|
-const uiLogger = logger('frontend:ui:expenses');
|
|
|
+import debug from 'debug';
|
|
|
+const apiLogger = debug('frontend:api:expenses');
|
|
|
+const errorLogger = debug('frontend:error:expenses');
|
|
|
+const uiLogger = debug('frontend:ui:expenses');
|
|
|
|
|
|
// 定义类型
|
|
|
type ExpenseItem = InferResponseType<typeof expenseClient.$get, 200>['data'][0];
|
|
|
@@ -48,9 +49,11 @@ const Expenses: React.FC = () => {
|
|
|
queryKey: ['clients'],
|
|
|
queryFn: async () => {
|
|
|
apiLogger('Fetching clients list');
|
|
|
- const response = await clientClient.$get({ query: { page: 1, pageSize: 1000 } }) as Promise<InferResponseType<typeof clientClient.$get, 200>>;
|
|
|
- apiLogger(`Fetched ${response.data.length} clients`);
|
|
|
- return response;
|
|
|
+ const response = await clientClient.$get({ query: { page: 1, pageSize: 1000 } });
|
|
|
+ if (!response.ok) throw new Error('Failed to fetch clients');
|
|
|
+ const data = await response.json();
|
|
|
+ apiLogger(`Fetched ${data.data.length} clients`);
|
|
|
+ return data;
|
|
|
},
|
|
|
onSuccess: (result) => {
|
|
|
setClients(result.data);
|
|
|
@@ -74,9 +77,11 @@ const Expenses: React.FC = () => {
|
|
|
if (filters.dateRange?.[0]) queryParams.startDate = filters.dateRange[0].format('YYYY-MM-DD');
|
|
|
if (filters.dateRange?.[1]) queryParams.endDate = filters.dateRange[1].format('YYYY-MM-DD');
|
|
|
|
|
|
- const response = await expenseClient.$get({ query: queryParams }) as Promise<ExpenseListResponse>;
|
|
|
- apiLogger(`Fetched ${response.data.length} expenses, total: ${response.pagination.total}`);
|
|
|
- return response;
|
|
|
+ const response = await expenseClient.$get({ query: queryParams });
|
|
|
+ if (!response.ok) throw new Error('Failed to fetch expenses');
|
|
|
+ const data = await response.json();
|
|
|
+ apiLogger(`Fetched ${data.data.length} expenses, total: ${data.pagination.total}`);
|
|
|
+ return data;
|
|
|
};
|
|
|
|
|
|
const { data, isLoading: isExpensesLoading, refetch } = useQuery({
|
|
|
@@ -111,7 +116,7 @@ const Expenses: React.FC = () => {
|
|
|
|
|
|
// 更新费用记录
|
|
|
const updateExpense = useMutation({
|
|
|
- mutationFn: ({ id, data }: { id: string; data: UpdateExpenseRequest }) => expenseClient[':id'].$put({ param: { id }, json: data }),
|
|
|
+ mutationFn: ({ id, data }: { id: number; data: UpdateExpenseRequest }) => expenseClient[':id'].$put({ param: { id }, json: data }),
|
|
|
onSuccess: () => {
|
|
|
apiLogger('Expense updated successfully');
|
|
|
antdMessage.success('费用记录更新成功');
|
|
|
@@ -125,7 +130,7 @@ const Expenses: React.FC = () => {
|
|
|
|
|
|
// 删除费用记录
|
|
|
const deleteExpense = useMutation({
|
|
|
- mutationFn: (id: string) => expenseClient[':id'].$delete({ param: { id } }),
|
|
|
+ mutationFn: (id: number) => expenseClient[':id'].$delete({ param: { id } }),
|
|
|
onSuccess: () => {
|
|
|
apiLogger('Expense deleted successfully');
|
|
|
antdMessage.success('费用记录删除成功');
|
|
|
@@ -188,7 +193,7 @@ const Expenses: React.FC = () => {
|
|
|
invoiceNumber: record.invoiceNumber,
|
|
|
currency: record.currency || 'CNY',
|
|
|
exchangeRate: record.exchangeRate || 1,
|
|
|
- foreignAmount: record.foreignAmount ? parseFloat(record.foreignAmount) : undefined,
|
|
|
+ foreignAmount: record.foreignAmount,
|
|
|
});
|
|
|
} else {
|
|
|
setEditingKey(null);
|
|
|
@@ -370,7 +375,7 @@ const Expenses: React.FC = () => {
|
|
|
type="link"
|
|
|
danger
|
|
|
icon={<DeleteOutlined />}
|
|
|
- onClick={() => handleDelete(record.id.toString())}
|
|
|
+ onClick={() => handleDelete(record.id)}
|
|
|
>
|
|
|
删除
|
|
|
</Button>
|
|
|
@@ -424,7 +429,7 @@ const Expenses: React.FC = () => {
|
|
|
</Button>
|
|
|
<Button
|
|
|
icon={<ReloadOutlined />}
|
|
|
- onClick={refetch}
|
|
|
+ onClick={() => refetch()}
|
|
|
loading={isExpensesLoading}
|
|
|
>
|
|
|
刷新
|
|
|
@@ -466,7 +471,7 @@ const Expenses: React.FC = () => {
|
|
|
label="客户"
|
|
|
name="clientId"
|
|
|
initialValue={filters.clientId}
|
|
|
- onChange={([value]) => setFilters(prev => ({ ...prev, clientId: value }))}
|
|
|
+ getValueFromEvent={(value) => { setFilters(prev => ({ ...prev, clientId: value })); return value; }}
|
|
|
>
|
|
|
<Select placeholder="请选择客户" style={{ width: '100%' }}>
|
|
|
{clients.map(client => (
|
|
|
@@ -481,7 +486,7 @@ const Expenses: React.FC = () => {
|
|
|
label="费用类型"
|
|
|
name="type"
|
|
|
initialValue={filters.type}
|
|
|
- onChange={([value]) => setFilters(prev => ({ ...prev, type: value }))}
|
|
|
+ getValueFromEvent={(value) => { setFilters(prev => ({ ...prev, type: value })); return value; }}
|
|
|
>
|
|
|
<Select placeholder="请选择费用类型" style={{ width: '100%' }}>
|
|
|
{expenseTypeOptions.map(option => (
|
|
|
@@ -496,7 +501,7 @@ const Expenses: React.FC = () => {
|
|
|
label="费用状态"
|
|
|
name="status"
|
|
|
initialValue={filters.status}
|
|
|
- onChange={([value]) => setFilters(prev => ({ ...prev, status: value }))}
|
|
|
+ getValueFromEvent={(value) => { setFilters(prev => ({ ...prev, status: value })); return value; }}
|
|
|
>
|
|
|
<Select placeholder="请选择费用状态" style={{ width: '100%' }}>
|
|
|
{expenseStatusOptions.map(option => (
|
|
|
@@ -511,7 +516,7 @@ const Expenses: React.FC = () => {
|
|
|
label="日期范围"
|
|
|
name="dateRange"
|
|
|
initialValue={filters.dateRange}
|
|
|
- onChange={([value]) => setFilters(prev => ({ ...prev, dateRange: value }))}
|
|
|
+ getValueFromEvent={(value) => { setFilters(prev => ({ ...prev, dateRange: value })); return value; }}
|
|
|
className="md:col-span-3"
|
|
|
>
|
|
|
<DatePicker.RangePicker
|
|
|
@@ -626,7 +631,6 @@ const Expenses: React.FC = () => {
|
|
|
<Input
|
|
|
type="number"
|
|
|
placeholder="请输入费用金额"
|
|
|
- precision={2}
|
|
|
style={{ width: '100%' }}
|
|
|
/>
|
|
|
</Form.Item>
|