添加jwt验证,添加交叉评查首页加载对接接口,评查任务文档列表对接接口,意见列表对接接口
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { type MetaFunction, type LoaderFunctionArgs } from "@remix-run/node";
|
||||
import { type MetaFunction, type LoaderFunctionArgs, type ActionFunctionArgs } from "@remix-run/node";
|
||||
import { useLoaderData, useSearchParams, useNavigate, useFetcher } from "@remix-run/react";
|
||||
import { Button } from '~/components/ui/Button';
|
||||
import { Card } from '~/components/ui/Card';
|
||||
@@ -17,12 +17,12 @@ import {
|
||||
deleteCrossCheckingTask,
|
||||
getCrossCheckingTaskDetail,
|
||||
type CrossCheckingTask,
|
||||
type TaskDocument,
|
||||
type TaskListParams,
|
||||
CrossCheckingTaskStatus,
|
||||
CrossCheckingTaskType,
|
||||
CrossCheckingDocType
|
||||
} from '~/api/cross-checking/cross-files';
|
||||
import type { ReviewFileUI } from '~/api/evaluation_points/rules-files';
|
||||
|
||||
export const links = () => [
|
||||
{ rel: "stylesheet", href: crossCheckingStyles }
|
||||
@@ -68,10 +68,14 @@ export async function loader({ request }: LoaderFunctionArgs) {
|
||||
};
|
||||
|
||||
try {
|
||||
// 获取任务列表和统计数据
|
||||
// 获取用户会话信息
|
||||
const { getUserSession } = await import("~/api/login/auth.server");
|
||||
const { userInfo, frontendJWT } = await getUserSession(request);
|
||||
|
||||
// 获取任务列表和统计数据,传递用户信息和JWT
|
||||
const [tasksResponse, statsResponse] = await Promise.all([
|
||||
getCrossCheckingTasks(params),
|
||||
getCrossCheckingStats()
|
||||
getCrossCheckingTasks(params, userInfo, frontendJWT),
|
||||
getCrossCheckingStats(userInfo, frontendJWT)
|
||||
]);
|
||||
|
||||
if (!tasksResponse.success) {
|
||||
@@ -108,17 +112,13 @@ export async function loader({ request }: LoaderFunctionArgs) {
|
||||
}
|
||||
}
|
||||
|
||||
export async function action({ request }: LoaderFunctionArgs) {
|
||||
export async function action({ request }: ActionFunctionArgs) {
|
||||
const formData = await request.formData();
|
||||
const _action = formData.get('_action');
|
||||
const taskId = formData.get('taskId');
|
||||
|
||||
if (!taskId) {
|
||||
return Response.json({ result: false, message: "缺少任务ID" }, { status: 400 });
|
||||
}
|
||||
|
||||
try {
|
||||
if (_action === 'delete') {
|
||||
if (_action === 'delete' && taskId) {
|
||||
try {
|
||||
const deleteResponse = await deleteCrossCheckingTask(Number(taskId));
|
||||
|
||||
if (!deleteResponse.success) {
|
||||
@@ -129,13 +129,57 @@ export async function action({ request }: LoaderFunctionArgs) {
|
||||
}
|
||||
|
||||
return Response.json({ result: true, message: "任务删除成功" }, { status: 200 });
|
||||
} catch (error) {
|
||||
console.error('操作任务失败:', error);
|
||||
return Response.json({
|
||||
result: false,
|
||||
message: error instanceof Error ? error.message : "操作失败"
|
||||
}, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
if (_action === 'getTaskDetail') {
|
||||
try {
|
||||
// 获取用户会话信息
|
||||
const { getUserSession } = await import("~/api/login/auth.server");
|
||||
const { frontendJWT } = await getUserSession(request);
|
||||
|
||||
const page = parseInt(formData.get('page') as string || '1', 10);
|
||||
const pageSize = parseInt(formData.get('pageSize') as string || '10', 10);
|
||||
|
||||
if (!taskId) {
|
||||
return Response.json({
|
||||
success: false,
|
||||
error: "缺少必要参数"
|
||||
}, { status: 400 });
|
||||
}
|
||||
|
||||
const response = await getCrossCheckingTaskDetail(
|
||||
Number(taskId),
|
||||
page,
|
||||
pageSize,
|
||||
frontendJWT
|
||||
);
|
||||
|
||||
if (response.error) {
|
||||
return Response.json({
|
||||
success: false,
|
||||
error: response.error
|
||||
}, { status: 500 });
|
||||
}
|
||||
|
||||
// console.log('用户任务详情返回:', response.data);
|
||||
return Response.json({
|
||||
success: true,
|
||||
data: response.data
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('获取任务详情失败:', error);
|
||||
return Response.json({
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : "获取任务详情失败"
|
||||
}, { status: 500 });
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('操作任务失败:', error);
|
||||
return Response.json({
|
||||
result: false,
|
||||
message: error instanceof Error ? error.message : "操作失败"
|
||||
}, { status: 500 });
|
||||
}
|
||||
|
||||
return Response.json({ result: false, message: "无效的操作" }, { status: 400 });
|
||||
@@ -174,7 +218,7 @@ export default function CrossCheckingIndex() {
|
||||
const [modalState, setModalState] = useState<{
|
||||
isOpen: boolean;
|
||||
title: string;
|
||||
files: ReviewFileUI[];
|
||||
files: TaskDocument[];
|
||||
loading: boolean;
|
||||
// 分页相关状态
|
||||
currentPage: number;
|
||||
@@ -198,9 +242,9 @@ export default function CrossCheckingIndex() {
|
||||
};
|
||||
|
||||
// 处理查看结果 - 打开文档列表模态框
|
||||
const handleViewResult = async (taskId: number, documentIds: number[]) => {
|
||||
const handleViewResult = async (taskId: number) => {
|
||||
// 存储任务信息用于分页
|
||||
setCurrentTaskInfo({ taskId, documentIds });
|
||||
setCurrentTaskInfo({ taskId });
|
||||
|
||||
// 打开模态框
|
||||
setModalState(prev => ({
|
||||
@@ -211,7 +255,7 @@ export default function CrossCheckingIndex() {
|
||||
}));
|
||||
|
||||
// 加载第一页数据
|
||||
await loadModalData(taskId, documentIds, 1, 10);
|
||||
await loadModalData(taskId, 1, 10);
|
||||
};
|
||||
|
||||
// 关闭模态框
|
||||
@@ -236,35 +280,24 @@ export default function CrossCheckingIndex() {
|
||||
// 存储当前任务信息用于分页
|
||||
const [currentTaskInfo, setCurrentTaskInfo] = useState<{
|
||||
taskId: number;
|
||||
documentIds: number[];
|
||||
} | null>(null);
|
||||
|
||||
// 加载分页数据
|
||||
const loadModalData = async (taskId: number, documentIds: number[], page: number = 1, pageSize: number = 10) => {
|
||||
const loadModalData = async (taskId: number, page: number = 1, pageSize: number = 10) => {
|
||||
try {
|
||||
setModalState(prev => ({
|
||||
...prev,
|
||||
loading: true
|
||||
}));
|
||||
|
||||
// 调用支持分页的API,传递分页参数
|
||||
const response = await getCrossCheckingTaskDetail(taskId, documentIds, page, pageSize);
|
||||
|
||||
if (response.error) {
|
||||
throw new Error(response.error);
|
||||
}
|
||||
// 使用 fetcher 调用 action 来获取任务详情
|
||||
const formData = new FormData();
|
||||
formData.append('_action', 'getTaskDetail');
|
||||
formData.append('taskId', taskId.toString());
|
||||
formData.append('page', page.toString());
|
||||
formData.append('pageSize', pageSize.toString());
|
||||
|
||||
const { task, files, total } = response.data!;
|
||||
|
||||
setModalState(prev => ({
|
||||
...prev,
|
||||
loading: false,
|
||||
title: `${task.taskName} - 文档列表`,
|
||||
files: files,
|
||||
total: total,
|
||||
currentPage: page,
|
||||
pageSize: pageSize
|
||||
}));
|
||||
fetcher.submit(formData, { method: "POST" });
|
||||
|
||||
} catch (error) {
|
||||
console.error('获取任务文档列表失败:', error);
|
||||
@@ -280,14 +313,14 @@ export default function CrossCheckingIndex() {
|
||||
// 处理模态框分页变化
|
||||
const handleModalPageChange = (page: number) => {
|
||||
if (currentTaskInfo) {
|
||||
loadModalData(currentTaskInfo.taskId, currentTaskInfo.documentIds, page, modalState.pageSize);
|
||||
loadModalData(currentTaskInfo.taskId, page, modalState.pageSize);
|
||||
}
|
||||
};
|
||||
|
||||
// 处理模态框每页大小变化
|
||||
const handleModalPageSizeChange = (size: number) => {
|
||||
if (currentTaskInfo) {
|
||||
loadModalData(currentTaskInfo.taskId, currentTaskInfo.documentIds, 1, size);
|
||||
loadModalData(currentTaskInfo.taskId, 1, size);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -315,7 +348,7 @@ export default function CrossCheckingIndex() {
|
||||
type="primary"
|
||||
size="small"
|
||||
className="operation-btn primary"
|
||||
onClick={() => handleViewResult(task.id, task.documentIds)}
|
||||
onClick={() => handleViewResult(task.id)}
|
||||
>
|
||||
<i className="ri-play-line"></i>
|
||||
去评查
|
||||
@@ -327,7 +360,7 @@ export default function CrossCheckingIndex() {
|
||||
type="default"
|
||||
size="small"
|
||||
className="operation-btn secondary"
|
||||
onClick={() => handleViewResult(task.id, task.documentIds)}
|
||||
onClick={() => handleViewResult(task.id)}
|
||||
>
|
||||
<i className="ri-eye-line"></i>
|
||||
进行中
|
||||
@@ -339,7 +372,7 @@ export default function CrossCheckingIndex() {
|
||||
type="default"
|
||||
size="small"
|
||||
className="operation-btn secondary"
|
||||
onClick={() => handleViewResult(task.id, task.documentIds)}
|
||||
onClick={() => handleViewResult(task.id)}
|
||||
>
|
||||
<i className="ri-file-text-line"></i>
|
||||
查看结果
|
||||
@@ -425,7 +458,7 @@ export default function CrossCheckingIndex() {
|
||||
|
||||
|
||||
|
||||
// 监听fetcher状态变化
|
||||
// 监听fetcher状态变化 - 删除操作
|
||||
useEffect(() => {
|
||||
if (fetcher.data && fetcher.state === 'idle' && isDeleting) {
|
||||
setIsDeleting(false);
|
||||
@@ -441,6 +474,44 @@ export default function CrossCheckingIndex() {
|
||||
}
|
||||
}, [fetcher.data, fetcher.state, isDeleting]);
|
||||
|
||||
// 监听fetcher状态变化 - 获取任务详情
|
||||
useEffect(() => {
|
||||
if (fetcher.data && fetcher.state === 'idle' && !isDeleting && modalState.loading) {
|
||||
const data = fetcher.data as {
|
||||
success?: boolean;
|
||||
data?: {
|
||||
files: TaskDocument[];
|
||||
total: number;
|
||||
currentPage: number;
|
||||
pageSize: number;
|
||||
};
|
||||
error?: string;
|
||||
};
|
||||
|
||||
if (data.success && data.data) {
|
||||
const { files, total, currentPage, pageSize: returnedPageSize } = data.data;
|
||||
|
||||
setModalState(prev => ({
|
||||
...prev,
|
||||
loading: false,
|
||||
title: `任务 ${currentTaskInfo?.taskId || ''} - 文档列表`,
|
||||
files: files || [],
|
||||
total: total || 0,
|
||||
currentPage: currentPage || prev.currentPage,
|
||||
pageSize: returnedPageSize || prev.pageSize
|
||||
}));
|
||||
} else {
|
||||
console.error('获取任务文档列表失败:', data.error);
|
||||
toastService.error(`获取任务文档列表失败: ${data.error || '未知错误'}`);
|
||||
|
||||
setModalState(prev => ({
|
||||
...prev,
|
||||
loading: false
|
||||
}));
|
||||
}
|
||||
}
|
||||
}, [fetcher.data, fetcher.state, isDeleting, modalState.loading, currentTaskInfo?.taskId]);
|
||||
|
||||
// 定义表格列配置
|
||||
const columns = [
|
||||
{
|
||||
@@ -479,7 +550,7 @@ export default function CrossCheckingIndex() {
|
||||
align: "center" as const,
|
||||
width: "8%",
|
||||
render: (_: unknown, record: CrossCheckingTask) => {
|
||||
const config = docTypeConfig[record.docType];
|
||||
const config = docTypeConfig[record.docType as keyof typeof docTypeConfig] || { label: record.docType, color: 'gray' as const };
|
||||
return (
|
||||
<Tag color={config.color}>
|
||||
{config.label}
|
||||
@@ -521,7 +592,7 @@ export default function CrossCheckingIndex() {
|
||||
align: "center" as const,
|
||||
width: "auto",
|
||||
render: (_: unknown, record: CrossCheckingTask) => {
|
||||
const config = statusConfig[record.status];
|
||||
const config = statusConfig[record.status as keyof typeof statusConfig] || { label: record.status, color: 'gray' as const };
|
||||
return (
|
||||
<Tag color={config.color}>
|
||||
{config.label}
|
||||
@@ -653,8 +724,8 @@ export default function CrossCheckingIndex() {
|
||||
pageSize={pageSize}
|
||||
onChange={handlePageChange}
|
||||
onPageSizeChange={handlePageSizeChange}
|
||||
showTotal={false}
|
||||
showPageSizeChanger={false}
|
||||
showTotal={true}
|
||||
showPageSizeChanger={true}
|
||||
pageSizeOptions={[10, 20, 30, 50]}
|
||||
/>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user