Critical fixes: 1. Compute column: Add Chinese comma support in formula validation - Problem: Formula with Chinese comma failed validation - Fix: Add Chinese comma character to allowed_chars regex - Example: Support formulas like 'col1(kg)+ col2,col3' 2. Binning operation: Fix NaN serialization error - Problem: 'Out of range float values are not JSON compliant: nan' - Fix: Enhanced NaN/inf handling in binning endpoint - Added np.inf/-np.inf replacement before JSON serialization - Added manual JSON serialization with NaN->null conversion 3. Enhanced all operation endpoints for consistency - Updated conditional, dropna endpoints with same NaN/inf handling - Ensures all operations return JSON-compliant data Modified files: - extraction_service/operations/compute.py: Add Chinese comma to regex - extraction_service/main.py: Enhanced NaN handling in binning/conditional/dropna Status: Hotfix complete, ready for testing
120 lines
2.2 KiB
TypeScript
120 lines
2.2 KiB
TypeScript
/**
|
|
* 全文复筛结果Hook
|
|
*
|
|
* 功能:
|
|
* 1. 获取结果列表
|
|
* 2. 分页支持
|
|
* 3. 筛选支持
|
|
* 4. 人工复核
|
|
*/
|
|
|
|
import { useState } from 'react';
|
|
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
|
import { message } from 'antd';
|
|
import { aslApi } from '../api';
|
|
|
|
interface UseFulltextResultsOptions {
|
|
taskId: string;
|
|
page?: number;
|
|
pageSize?: number;
|
|
filter?: 'all' | 'conflict' | 'pending' | 'reviewed';
|
|
enabled?: boolean;
|
|
}
|
|
|
|
export function useFulltextResults({
|
|
taskId,
|
|
page = 1,
|
|
pageSize = 20,
|
|
filter = 'all',
|
|
enabled = true,
|
|
}: UseFulltextResultsOptions) {
|
|
const queryClient = useQueryClient();
|
|
|
|
// 获取结果列表
|
|
const {
|
|
data,
|
|
isLoading,
|
|
error,
|
|
refetch,
|
|
} = useQuery({
|
|
queryKey: ['fulltextResults', taskId, page, pageSize, filter],
|
|
queryFn: async () => {
|
|
const response = await aslApi.getFulltextTaskResults(taskId, {
|
|
page,
|
|
pageSize,
|
|
filter,
|
|
});
|
|
return response.data;
|
|
},
|
|
enabled: enabled && !!taskId,
|
|
retry: 1,
|
|
});
|
|
|
|
// 人工复核Mutation
|
|
const reviewMutation = useMutation({
|
|
mutationFn: async ({
|
|
resultId,
|
|
decision,
|
|
note,
|
|
}: {
|
|
resultId: string;
|
|
decision: 'include' | 'exclude';
|
|
note?: string;
|
|
}) => {
|
|
const exclusionReason = decision === 'exclude' ? note || '未提供原因' : undefined;
|
|
await aslApi.updateFulltextDecision(resultId, {
|
|
finalDecision: decision,
|
|
exclusionReason,
|
|
reviewNotes: note,
|
|
});
|
|
},
|
|
onSuccess: () => {
|
|
message.success('复核提交成功');
|
|
// 刷新结果列表
|
|
queryClient.invalidateQueries({ queryKey: ['fulltextResults', taskId] });
|
|
},
|
|
onError: (error: Error) => {
|
|
message.error('复核提交失败: ' + error.message);
|
|
},
|
|
});
|
|
|
|
const results = data?.results || [];
|
|
const total = data?.total || 0;
|
|
const summary = data?.summary || {
|
|
totalResults: 0,
|
|
conflictCount: 0,
|
|
pendingReview: 0,
|
|
reviewed: 0,
|
|
};
|
|
|
|
return {
|
|
results,
|
|
total,
|
|
summary,
|
|
isLoading,
|
|
error,
|
|
refetch,
|
|
review: reviewMutation.mutate,
|
|
isReviewing: reviewMutation.isPending,
|
|
};
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|