fix: 1. 重新对齐交叉评查的接口。

2. 确认评查结果的接口对接。 3. 新增评查点适配省级创建的响应数据和其他用户创建的单条响应数据。  4. 文档列表的文档类型通过通用的查询接口查询文档类型。优化加载状态的时机。
This commit is contained in:
2025-12-11 11:16:50 +08:00
parent ba517d7b9c
commit d8bba607fc
18 changed files with 3435 additions and 1086 deletions
+30 -29
View File
@@ -11,10 +11,9 @@ import { FilterPanel, FilterSelect, SearchFilter, DateRangeFilter } from "~/comp
import { TableRowSkeleton, LoadingIndicator, NumberSkeleton } from '~/components/ui/SkeletonScreen';
import documentsIndexStyles from "~/styles/pages/documents_index.css?url";
import documentVersionStyles from "~/styles/components/document-version.css?url";
import { deleteDocument, getDocumentsListFromAPI, type DocumentUI, type DocumentVersionUI } from "~/api/files/documents";
import { getDocumentTypesByIds, deleteDocument, getDocumentsListFromAPI, type DocumentUI, type DocumentVersionUI } from "~/api/files/documents";
// import { IssuesDiff } from "~/components/ui/IssuesDiff";
import { ResultStats } from "~/components/ui/ResultStats";
import { getDocumentTypes } from "~/api/document-types/document-types";
import { updateDocumentAuditStatus } from "~/api/evaluation_points/rules-files";
import { appendContractAttachments, uploadContractTemplate } from "~/api/files/files-upload";
import { toastService } from "~/components/ui/Toast";
@@ -50,12 +49,12 @@ export const loader = async ({ request }: LoaderFunctionArgs) => {
const pageSize = parseInt(url.searchParams.get("pageSize") || "10", 10);
// 获取文档类型列表(服务端需要显式传递 token,客户端依赖 axios 拦截器)
const typesResponse = await getDocumentTypes({ pageSize: 500 }, frontendJWT);
const documentTypes = typesResponse.data?.types || [];
const documentTypeOptions = documentTypes.map(type => ({
value: type.id,
label: type.name
}));
// const typesResponse = await getDocumentTypes(frontendJWT);
// const documentTypes = typesResponse.data?.types || [];
// const documentTypeOptions = documentTypes.map(type => ({
// value: type.id,
// label: type.name
// }));
// 初始返回空数据,将在客户端根据 sessionStorage 中的 documentTypeIds 加载实际数据
return Response.json({
@@ -63,7 +62,7 @@ export const loader = async ({ request }: LoaderFunctionArgs) => {
total: 0,
page,
pageSize,
documentTypeOptions,
documentTypeOptions: [],
userInfo, // 传递用户信息到客户端
frontendJWT, // 传递 JWT 到客户端
initialLoad: true // 标记这是初始加载
@@ -190,6 +189,8 @@ export default function DocumentsIndex() {
// 添加页面加载状态管理
const [isLoadingData, setIsLoadingData] = useState(true);
// 是否已完成初始化(区分"还没开始加载"和"加载完成但没有数据")
const [hasInitialized, setHasInitialized] = useState(false);
const [documents, setDocuments] = useState<DocumentUI[]>([]);
const [total, setTotal] = useState(0);
const [filteredDocumentTypeOptions, setFilteredDocumentTypeOptions] = useState(loaderData.documentTypeOptions);
@@ -314,10 +315,7 @@ export default function DocumentsIndex() {
setTotal(result.data.total);
// 获取经过过滤的文档类型列表
const filteredTypesResponse = await getDocumentTypes({
pageSize: 500,
documentTypeIds: typeIds
}, jwtToken);
const filteredTypesResponse = await getDocumentTypesByIds(typeIds, jwtToken);
const filteredDocumentTypes = filteredTypesResponse.data?.types || [];
const filteredOptions = filteredDocumentTypes.map(type => ({
value: type.id,
@@ -330,6 +328,7 @@ export default function DocumentsIndex() {
toastService.error('获取文档列表失败: ' + (error instanceof Error ? error.message : '未知错误'));
} finally {
setIsLoadingData(false);
setHasInitialized(true); // 标记初始化完成
loadingBarService.hide();
}
}, [search, documentNumber, documentType, auditStatus, fileStatus, dateFrom, dateTo, currentPage, pageSize, loaderData.frontendJWT]);
@@ -344,14 +343,22 @@ export default function DocumentsIndex() {
console.log('📋 [useEffect] 从 sessionStorage 获取文档类型IDs:', typeIds);
setDocumentTypeIds(typeIds);
// 加载数据
// 加载数据(fetchData 中会自动获取并设置过滤后的文档类型选项)
fetchData(typeIds);
} else {
console.warn('⚠️ [useEffect] sessionStorage 中没有 documentTypeIds');
// 没有 documentTypeIds 时,标记初始化完成但无数据
setIsLoadingData(false);
setHasInitialized(true);
loadingBarService.hide();
}
}
} catch (error) {
console.error('❌ [useEffect] 获取 sessionStorage 中的 documentTypeIds 失败:', error);
// 出错时也标记初始化完成
setIsLoadingData(false);
setHasInitialized(true);
loadingBarService.hide();
}
}, [fetchData]);
@@ -394,23 +401,16 @@ export default function DocumentsIndex() {
}
}, [documents, expandedRows]);
// 使用并更新缓存数据
// 更新缓存数据并处理 loader 错误
useEffect(() => {
// 如果有缓存数据,先显示缓存,再在后台加载新数据
if (dataCache.current) {
setIsLoadingData(false);
} else {
// 显示加载状态 - 确保显示加载条
loadingBarService.show();
setIsLoadingData(true);
}
// 设置缓存数据
// 设置缓存数据(用于后续可能的优化)
dataCache.current = loaderData;
// 处理loader错误
if (loaderData.error) {
toastService.error(loaderData.error);
setIsLoadingData(false);
setHasInitialized(true);
}
}, [loaderData]);
@@ -1490,7 +1490,7 @@ export default function DocumentsIndex() {
<div className="flex justify-between items-center mb-4">
<div className="flex items-center">
<h2 className="text-xl font-medium"></h2>
{isLoadingData ? (
{!hasInitialized || isLoadingData ? (
<div className="ml-4">
<NumberSkeleton />
</div>
@@ -1622,11 +1622,12 @@ export default function DocumentsIndex() {
</div>
<div className="overflow-x-auto">
{isLoadingData && documents.length === 0 ? (
{/* 未初始化完成时显示骨架屏,初始化完成后根据数据显示内容或"暂无数据" */}
{!hasInitialized || (isLoadingData && documents.length === 0) ? (
<TableRowSkeleton count={5} />
) : documents.length === 0 ? (
<div className="text-center py-8 text-gray-500">
{isLoadingData ? "加载中..." : "暂无数据"}
</div>
) : (
<table className="w-full border-collapse">