添加合同和卷宗数据隔离

This commit is contained in:
2025-06-03 12:16:31 +08:00
parent b02978508d
commit 0397139ad8
20 changed files with 1190 additions and 437 deletions
+120 -57
View File
@@ -1,6 +1,6 @@
import { type MetaFunction, type LoaderFunctionArgs } from "@remix-run/node";
import { useLoaderData, useSearchParams, useNavigate } from "@remix-run/react";
import { useEffect } from "react";
import { useEffect, useState, useCallback } from "react";
import { Button } from "~/components/ui/Button";
import { Card } from "~/components/ui/Card";
import { FileIcon } from "~/components/ui/FileIcon";
@@ -13,7 +13,8 @@ import rulesFilesStyles from "~/styles/pages/rules-files.css?url";
import {
getReviewFiles,
type ReviewFileUI,
updateDocumentAuditStatus
updateDocumentAuditStatus,
type DocumentSearchParams
} from "~/api/evaluation_points/rules-files";
import { getDocumentTypes } from "~/api/document-types/document-types";
import { toastService } from "~/components/ui/Toast";
@@ -55,14 +56,8 @@ export const REVIEW_STATUS_LABELS: Record<string, string> = {
// 加载评查文件列表
export async function loader({ request }: LoaderFunctionArgs) {
// 获取分页参数
const url = new URL(request.url);
const fileType = url.searchParams.get("fileType") || "";
const reviewStatus = url.searchParams.get("reviewStatus") || "";
const dateRange = url.searchParams.get("dateRange") || "";
const dateFrom = url.searchParams.get("dateFrom") || "";
const dateTo = url.searchParams.get("dateTo") || "";
const keyword = url.searchParams.get("keyword") || "";
const sortOrder = url.searchParams.get("sortOrder") || "upload_time_desc";
const currentPage = parseInt(url.searchParams.get("page") || "1", 10);
const pageSize = parseInt(url.searchParams.get("pageSize") || "10", 10);
@@ -71,36 +66,14 @@ export async function loader({ request }: LoaderFunctionArgs) {
const typesResponse = await getDocumentTypes({pageSize:500});
const documentTypes = typesResponse.data?.types || [];
// 获取文件列表
const searchParams = {
fileType,
reviewStatus,
dateRange,
dateFrom,
dateTo,
keyword,
sortOrder,
page: currentPage,
pageSize,
};
// console.log('rules-filessearchParams-----',searchParams);
const filesResponse = await getReviewFiles(searchParams);
if (filesResponse.error) {
console.error('获取评查文件列表失败:', filesResponse.error);
return Response.json({ result: false, message: filesResponse.error }, { status: filesResponse.status || 500 });
}
const files = filesResponse.data?.files || [];
const totalCount = filesResponse.data?.total || 0;
// 返回初始空数据,客户端将根据 sessionStorage 中的 reviewType 加载实际数据
return Response.json({
files,
files: [],
documentTypes,
totalCount,
totalCount: 0,
currentPage,
pageSize,
initialLoad: true
});
} catch (error) {
console.error('加载评查文件列表失败:', error);
@@ -110,10 +83,17 @@ export async function loader({ request }: LoaderFunctionArgs) {
export default function RulesFiles() {
const navigate = useNavigate();
const { files, documentTypes, totalCount, currentPage, pageSize, result, message } = useLoaderData<typeof loader>();
const { files: initialFiles, documentTypes: allDocumentTypes, totalCount: initialTotal, currentPage, pageSize, result, message } = useLoaderData<typeof loader>();
const [searchParams, setSearchParams] = useSearchParams();
const dateFrom = searchParams.get('dateFrom') || '';
const dateTo = searchParams.get('dateTo') || '';
// 添加状态管理
const [files, setFiles] = useState<ReviewFileUI[]>(initialFiles);
const [documentTypes, setDocumentTypes] = useState(allDocumentTypes);
const [totalCount, setTotalCount] = useState(initialTotal);
const [isLoading, setIsLoading] = useState(true);
const [reviewType, setReviewType] = useState<string | null>(null);
// 处理初始加载数据loader的错误
useEffect(() => {
@@ -122,6 +102,87 @@ export default function RulesFiles() {
}
}, [result, message]);
// 客户端数据请求
const fetchData = useCallback(async (params: Record<string, string>) => {
setIsLoading(true);
try {
// 构建搜索参数
const searchParams: DocumentSearchParams = {
fileType: params.fileType || undefined,
reviewStatus: params.reviewStatus || undefined,
dateFrom: params.dateFrom || undefined,
dateTo: params.dateTo || undefined,
keyword: params.keyword || undefined,
sortOrder: params.sortOrder || 'upload_time_desc',
page: parseInt(params.page || "1", 10),
pageSize: parseInt(params.pageSize || "10", 10)
};
// 根据 reviewType 添加类型过滤
if (reviewType === 'contract') {
searchParams.fileType = '1';
} else if (reviewType === 'record') {
// 在 API 层处理 type_id 为 2 或 3 的过滤
searchParams.fileType = 'record';
}
// 如果用户手动选择了文件类型,优先使用用户选择的
if (params.fileType) {
searchParams.fileType = params.fileType;
}
// 获取文件列表
const filesResponse = await getReviewFiles(searchParams);
if (filesResponse.error) {
throw new Error(filesResponse.error);
}
setFiles(filesResponse.data?.files || []);
setTotalCount(filesResponse.data?.total || 0);
} catch (error) {
console.error('获取评查文件列表失败:', error);
toastService.error('获取评查文件列表失败: ' + (error instanceof Error ? error.message : '未知错误'));
} finally {
setIsLoading(false);
}
}, [reviewType]);
// 在组件挂载时从 sessionStorage 获取 reviewType 并加载数据
useEffect(() => {
try {
if (typeof window !== 'undefined') {
const storedReviewType = sessionStorage.getItem('reviewType');
setReviewType(storedReviewType);
// 根据 reviewType 过滤文档类型选项
if (storedReviewType) {
if (storedReviewType === 'contract') {
// 只保留 id=1 的选项
const filteredTypes = allDocumentTypes.filter((type: {id: number}) => type.id === 1);
setDocumentTypes(filteredTypes);
} else if (storedReviewType === 'record') {
// 只保留 id=2 和 id=3 的选项
const filteredTypes = allDocumentTypes.filter((type: {id: number}) => type.id === 2 || type.id === 3);
setDocumentTypes(filteredTypes);
}
// 加载数据
fetchData(Object.fromEntries(searchParams.entries()));
}
}
} catch (error) {
console.error('获取 sessionStorage 中的 reviewType 失败:', error);
}
}, [allDocumentTypes, fetchData, searchParams]);
// 监听 URL 参数变化,重新获取数据
useEffect(() => {
if (reviewType) {
fetchData(Object.fromEntries(searchParams.entries()));
}
}, [searchParams, fetchData, reviewType]);
// 处理筛选条件变更
const handleFilterChange = (e: React.ChangeEvent<HTMLSelectElement | HTMLInputElement>) => {
const { name, value } = e.target;
@@ -512,28 +573,30 @@ export default function RulesFiles() {
</FilterPanel>
{/* 文件列表 */}
<Card >
<Table
columns={columns}
dataSource={files}
rowKey="id"
emptyText="暂无文件数据"
className="files-table table-auto-height"
/>
{/* 分页组件 */}
{totalCount > 0 && (
<Pagination
currentPage={currentPage}
total={totalCount}
pageSize={pageSize}
onChange={handlePageChange}
onPageSizeChange={handlePageSizeChange}
showTotal={true}
showPageSizeChanger={true}
pageSizeOptions={[10, 20, 30, 50]}
<Card>
<div className={isLoading ? "opacity-70 pointer-events-none transition-opacity" : ""}>
<Table
columns={columns}
dataSource={files}
rowKey="id"
emptyText="暂无文件数据"
className="files-table table-auto-height"
/>
)}
{/* 分页组件 */}
{totalCount > 0 && (
<Pagination
currentPage={currentPage}
total={totalCount}
pageSize={pageSize}
onChange={handlePageChange}
onPageSizeChange={handlePageSizeChange}
showTotal={true}
showPageSizeChanger={true}
pageSizeOptions={[10, 20, 30, 50]}
/>
)}
</div>
</Card>
</div>
);