fix: restore reviewsTest detail rendering

This commit is contained in:
wren
2026-05-06 10:01:21 +08:00
parent b36e102aa0
commit c3ef4dcefc
+70 -51
View File
@@ -155,6 +155,37 @@ interface ReviewData {
aiAnalysis: AnalysisData; aiAnalysis: AnalysisData;
} }
function buildReviewData(document: any, reviewPoints: ReviewPoint[], statistics: Statistics, reviewInfo: ReviewInfo): ReviewData | null {
if (!document) {
return null;
}
const mockData = getMockReviewData();
const typeValue = document.type ?? document.type_id;
return {
fileInfo: {
fileName: document.name || "未知文件名",
path: document.path || "未知路径",
contractNumber: document.documentNumber || document.document_number || "未知编号",
fileSize: document.size ? formatFileSize(document.size) : document.file_size ? formatFileSize(document.file_size) : "未知大小",
fileFormat: document.fileType ? document.fileType.toUpperCase() : "未知格式",
pageCount: document.pageCount || document.page_count || 0,
uploadTime: document.uploadTime || document.created_at || "未知时间",
uploadUser: document.uploadUser || "未知用户",
auditStatus: document.auditStatus || 0,
legalBasis: document.legalBasis || {},
fileType: typeValue !== undefined && typeValue !== null ? String(typeValue) : ""
},
contractInfo: mockData.contractInfo,
reviewInfo,
statistics,
fileContent: mockData.fileContent,
reviewPoints,
aiAnalysis: mockData.aiAnalysis,
};
}
export const meta: MetaFunction = () => { export const meta: MetaFunction = () => {
return [ return [
@@ -374,13 +405,32 @@ export async function action({ request }: ActionFunctionArgs) {
export default function ReviewDetails() { export default function ReviewDetails() {
const navigate = useNavigate(); const navigate = useNavigate();
const loaderData = useLoaderData<typeof loader>(); const loaderData = useLoaderData<typeof loader>();
const normalizedLoaderData =
loaderData &&
typeof loaderData === 'object' &&
'reviewPoints' in loaderData &&
loaderData.reviewPoints &&
typeof loaderData.reviewPoints === 'object' &&
'data' in loaderData.reviewPoints &&
'document' in loaderData.reviewPoints
? {
...loaderData,
document: (loaderData.reviewPoints as any).document,
reviewPoints: (loaderData.reviewPoints as any).data,
reviewInfo: (loaderData.reviewPoints as any).reviewInfo,
statistics: (loaderData.reviewPoints as any).stats,
comparison_document: (loaderData.reviewPoints as any).comparison_document,
scoring_proposals: (loaderData.reviewPoints as any).scoring_proposals ?? [],
}
: loaderData;
const fetcher = useFetcher(); const fetcher = useFetcher();
const { document, reviewPoints, statistics, reviewInfo, comparison_document, frontendJWT } = loaderData; const { document, reviewPoints, statistics, reviewInfo, comparison_document, frontendJWT } = normalizedLoaderData as any;
const fallbackReviewData = buildReviewData(document, reviewPoints, statistics, reviewInfo);
const [isLoading, setIsLoading] = useState(false); // 已经通过loader加载了数据,不需要再显示加载状态 const [isLoading, setIsLoading] = useState(false); // 已经通过loader加载了数据,不需要再显示加载状态
const [rightActiveTab, setRightActiveTab] = useState<'result' | 'fields' | 'info'>('result'); const [rightActiveTab, setRightActiveTab] = useState<'result' | 'fields' | 'info'>('result');
const [reviewData, setReviewData] = useState<ReviewData | null>(null); const [reviewData, setReviewData] = useState<ReviewData | null>(fallbackReviewData);
const [activeReviewPointResultId, setActiveReviewPointResultId] = useState<string | null>(null); const [activeReviewPointResultId, setActiveReviewPointResultId] = useState<string | null>(null);
const [targetPage, setTargetPage] = useState<number | undefined>(undefined); const [targetPage, setTargetPage] = useState<number | undefined>(undefined);
const [charPositions, setCharPositions] = useState<Array<{ box: number[][], char: string, score: number }> | undefined>(undefined); const [charPositions, setCharPositions] = useState<Array<{ box: number[][], char: string, score: number }> | undefined>(undefined);
@@ -461,45 +511,14 @@ export default function ReviewDetails() {
} }
}, [document?.id]); }, [document?.id]);
// 模拟获取评查数据 // 使用 loader 数据同步本地评查页状态,避免首屏空白。
useEffect(() => { useEffect(() => {
if (!document) return; setReviewData(buildReviewData(document, reviewPoints, statistics, reviewInfo));
// 构建文件信息对象
const fileInfo = {
fileName: document.name || "未知文件名",
path: document.path || "未知路径",
contractNumber: document.documentNumber || document.document_number || "未知编号",
fileSize: document.size ? formatFileSize(document.size) : document.file_size ? formatFileSize(document.file_size) : "未知大小",
// 文件格式类型
fileFormat: document.fileType ? document.fileType.toUpperCase() : "未知格式",
pageCount: document.pageCount || document.page_count || 0,
uploadTime: document.uploadTime || document.created_at || "未知时间",
uploadUser: document.uploadUser || "未知用户",
auditStatus: document.auditStatus || 0,
legalBasis: document.legalBasis || {},
// 文件类型(1:合同,2:卷宗。。。)
fileType: document.type || document.type_id ? document.type_id.toString() : ''
};
// 创建包含真实文档数据的评查数据对象
const reviewDataObj: ReviewData = {
// 使用真实文件信息
fileInfo: fileInfo,
// 其他字段暂时使用默认值
contractInfo: getMockReviewData().contractInfo,
reviewInfo: reviewInfo,
statistics: statistics,
fileContent: getMockReviewData().fileContent,
reviewPoints: reviewPoints,
aiAnalysis: getMockReviewData().aiAnalysis,
};
setReviewData(reviewDataObj);
setIsLoading(false); setIsLoading(false);
}, [document, reviewPoints, statistics, reviewInfo]); }, [document, reviewPoints, statistics, reviewInfo]);
const effectiveReviewData = reviewData ?? fallbackReviewData;
const handleTabChange = (tabKey: 'result' | 'fields' | 'info') => { const handleTabChange = (tabKey: 'result' | 'fields' | 'info') => {
setRightActiveTab(tabKey); setRightActiveTab(tabKey);
}; };
@@ -510,7 +529,7 @@ export default function ReviewDetails() {
setRightActiveTab('result'); setRightActiveTab('result');
// 查找评查点并尝试跳转到其页面 // 查找评查点并尝试跳转到其页面
const point = reviewData?.reviewPoints.find(p => p.id === id); const point = effectiveReviewData?.reviewPoints.find(p => p.id === id);
if (point) { if (point) {
console.log('跳转到评查点页面:', point); console.log('跳转到评查点页面:', point);
const page = getFirstPageFromPoint(point); const page = getFirstPageFromPoint(point);
@@ -822,7 +841,7 @@ export default function ReviewDetails() {
}; };
// 获取当前激活的评查点对象 // 获取当前激活的评查点对象
const activeReviewPoint = reviewData?.reviewPoints.find(p => p.id === activeReviewPointResultId) || null; const activeReviewPoint = effectiveReviewData?.reviewPoints.find(p => p.id === activeReviewPointResultId) || null;
// ── 模板上传相关函数 ── // ── 模板上传相关函数 ──
const handleOpenReuploadModal = () => { const handleOpenReuploadModal = () => {
@@ -892,7 +911,7 @@ export default function ReviewDetails() {
<button type="button" className="flex items-center gap-1 text-slate-600 hover:text-slate-900 text-[12.5px]" onClick={() => setShowComparison(false)}> <button type="button" className="flex items-center gap-1 text-slate-600 hover:text-slate-900 text-[12.5px]" onClick={() => setShowComparison(false)}>
<i className="ri-arrow-left-line" /> <i className="ri-arrow-left-line" />
</button> </button>
<span className="font-medium text-sm text-slate-800 truncate">{reviewData?.fileInfo?.fileName}</span> <span className="font-medium text-sm text-slate-800 truncate">{effectiveReviewData?.fileInfo?.fileName}</span>
</header> </header>
<div className="flex-1 min-h-0 overflow-auto"> <div className="flex-1 min-h-0 overflow-auto">
<Comparison comparison_document={comparison_document} /> <Comparison comparison_document={comparison_document} />
@@ -908,14 +927,14 @@ export default function ReviewDetails() {
<div className="loading-spinner"></div> <div className="loading-spinner"></div>
<span className="ml-3">...</span> <span className="ml-3">...</span>
</div> </div>
) : reviewData ? ( ) : effectiveReviewData ? (
<main className="flex-1 min-h-0 grid grid-cols-[22%,1fr,30%] p-2"> <main className="flex-1 min-h-0 grid grid-cols-[22%,1fr,30%] p-2">
{/* 左栏:规则目录 */} {/* 左栏:规则目录 */}
<RulesDirectory <RulesDirectory
reviewPoints={reviewData.reviewPoints} reviewPoints={effectiveReviewData.reviewPoints}
statistics={reviewData.statistics} statistics={effectiveReviewData.statistics}
activeReviewPointResultId={activeReviewPointResultId} activeReviewPointResultId={activeReviewPointResultId}
fileName={reviewData.fileInfo.fileName} fileName={effectiveReviewData.fileInfo.fileName}
onRuleSelect={handleRuleSelect} onRuleSelect={handleRuleSelect}
onBack={() => navigate(getReturnUrl())} onBack={() => navigate(getReturnUrl())}
/> />
@@ -929,10 +948,10 @@ export default function ReviewDetails() {
targetPage={targetPage} targetPage={targetPage}
charPositions={charPositions} charPositions={charPositions}
activeReviewPointResultId={activeReviewPointResultId} activeReviewPointResultId={activeReviewPointResultId}
reviewPoints={reviewData.reviewPoints} reviewPoints={effectiveReviewData.reviewPoints}
highlightValue={highlightValue} highlightValue={highlightValue}
aiSuggestionReplace={aiSuggestionReplace} aiSuggestionReplace={aiSuggestionReplace}
userInfo={(loaderData as any)?.userInfo} userInfo={(normalizedLoaderData as any)?.userInfo}
/> />
) : ( ) : (
<PdfPreviewTest <PdfPreviewTest
@@ -940,7 +959,7 @@ export default function ReviewDetails() {
targetPage={targetPage} targetPage={targetPage}
charPositions={charPositions} charPositions={charPositions}
activeReviewPointResultId={activeReviewPointResultId} activeReviewPointResultId={activeReviewPointResultId}
reviewPoints={reviewData.reviewPoints} reviewPoints={effectiveReviewData.reviewPoints}
/> />
)} )}
</section> </section>
@@ -950,15 +969,15 @@ export default function ReviewDetails() {
activeTab={rightActiveTab} activeTab={rightActiveTab}
onTabChange={handleTabChange} onTabChange={handleTabChange}
activeReviewPoint={activeReviewPoint} activeReviewPoint={activeReviewPoint}
reviewPoints={reviewData.reviewPoints} reviewPoints={effectiveReviewData.reviewPoints}
fileInfo={reviewData.fileInfo} fileInfo={effectiveReviewData.fileInfo}
reviewInfo={reviewData.reviewInfo} reviewInfo={effectiveReviewData.reviewInfo}
onReviewPointSelect={handleReviewPointSelect} onReviewPointSelect={handleReviewPointSelect}
onStatusChange={handleReviewPointStatusChange} onStatusChange={handleReviewPointStatusChange}
onConfirmResults={handleConfirmResults} onConfirmResults={handleConfirmResults}
onDownload={handleDownloadFile} onDownload={handleDownloadFile}
auditStatus={document?.auditStatus} auditStatus={document?.auditStatus}
fileFormat={reviewData.fileInfo.fileFormat} fileFormat={effectiveReviewData.fileInfo.fileFormat}
onUploadTemplate={handleOpenReuploadModal} onUploadTemplate={handleOpenReuploadModal}
onComparison={() => setShowComparison(true)} onComparison={() => setShowComparison(true)}
showComparisonButton={showComparisonButton} showComparisonButton={showComparisonButton}