修改文档列表
This commit is contained in:
+119
-34
@@ -1,5 +1,5 @@
|
||||
import { useState, useEffect, useRef } from "react";
|
||||
import { MetaFunction, ActionFunctionArgs, json } from "@remix-run/node";
|
||||
import { MetaFunction, ActionFunctionArgs } from "@remix-run/node";
|
||||
import { Form, useActionData, useLoaderData } from "@remix-run/react";
|
||||
import { Card } from "~/components/ui/Card";
|
||||
import { Button } from "~/components/ui/Button";
|
||||
@@ -8,8 +8,17 @@ import { UploadArea, UploadAreaRef } from "~/components/ui/UploadArea";
|
||||
import { FileProgress} from "~/components/ui/FileProgress";
|
||||
import { ProcessingSteps, Step } from "~/components/ui/ProcessingSteps";
|
||||
import uploadStyles from "~/styles/pages/files_upload.css?url";
|
||||
import { getTodayDocuments, getDocumentTypes, getDocumentsStatus, type Document, type DocumentType, DocumentStatus } from "~/api/files/files-upload";
|
||||
import { uploadFileToBinary, uploadDocumentToServer } from "~/api/files";
|
||||
import {
|
||||
getTodayDocuments,
|
||||
getDocumentTypes,
|
||||
getDocumentsStatus,
|
||||
uploadFileToBinary,
|
||||
uploadDocumentToServer,
|
||||
type Document,
|
||||
type DocumentType,
|
||||
type FileUploadResponse,
|
||||
DocumentStatus
|
||||
} from "~/api/files/files-upload";
|
||||
|
||||
export function links() {
|
||||
return [
|
||||
@@ -74,6 +83,20 @@ export enum StepStatus {
|
||||
COMPLETED = "completed"
|
||||
}
|
||||
|
||||
// 模拟API支持的存储类型
|
||||
const STORAGE_TYPES = [
|
||||
{ id: "minio", name: "MinIO对象存储" },
|
||||
{ id: "local", name: "本地文件系统" },
|
||||
{ id: "s3", name: "Amazon S3" }
|
||||
];
|
||||
|
||||
// 文件上传完成后的操作选项
|
||||
const AFTER_UPLOAD_OPTIONS = [
|
||||
{ id: "list", name: "返回文档列表" },
|
||||
{ id: "stay", name: "留在当前页面" },
|
||||
{ id: "audit", name: "立即开始审核" }
|
||||
];
|
||||
|
||||
// 上传的文件信息接口
|
||||
export interface UploadedFile {
|
||||
id: number;
|
||||
@@ -90,26 +113,6 @@ export interface UploadedFile {
|
||||
};
|
||||
}
|
||||
|
||||
// 文件上传响应接口
|
||||
interface FileUploadResponse {
|
||||
success: boolean;
|
||||
result?: {
|
||||
id: number;
|
||||
file_name: string;
|
||||
file_size: number;
|
||||
file_url: string;
|
||||
type_id: number;
|
||||
type_description: string;
|
||||
document_number: string | null;
|
||||
storage_type: string;
|
||||
is_test_document: boolean;
|
||||
remark: string | null;
|
||||
background_processing: boolean;
|
||||
evaluation_level: string;
|
||||
};
|
||||
error: string | null;
|
||||
}
|
||||
|
||||
// 模拟上传文件到服务器的API
|
||||
async function uploadFileToServer(
|
||||
binaryData: ArrayBuffer,
|
||||
@@ -122,7 +125,7 @@ async function uploadFileToServer(
|
||||
isTestDocument: boolean
|
||||
): Promise<FileUploadResponse> {
|
||||
// 在实际应用中,这里会使用fetch或axios发送请求到后端API
|
||||
console.log(`[模拟API] 上传文件: ${fileName}, 大小: ${binaryData.byteLength} 字节`);
|
||||
console.log(`[API] 上传文件: ${fileName}, 大小: ${binaryData.byteLength} 字节`);
|
||||
|
||||
try {
|
||||
// 使用封装的上传函数
|
||||
@@ -137,9 +140,26 @@ async function uploadFileToServer(
|
||||
isTestDocument
|
||||
);
|
||||
|
||||
return response;
|
||||
if (response.error) {
|
||||
console.error('[API] 上传错误:', response.error);
|
||||
return {
|
||||
success: false,
|
||||
error: response.error
|
||||
};
|
||||
}
|
||||
|
||||
// 确保返回有效的FileUploadResponse对象
|
||||
if (response.data) {
|
||||
return response.data;
|
||||
}
|
||||
|
||||
// 如果没有数据,则返回错误
|
||||
return {
|
||||
success: false,
|
||||
error: '上传失败,未获取到响应数据'
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('[模拟API] 上传错误:', error);
|
||||
console.error('[API] 上传错误:', error);
|
||||
return {
|
||||
success: false,
|
||||
error: error instanceof Error ? error.message : '上传失败'
|
||||
@@ -183,7 +203,7 @@ export async function action({ request }: ActionFunctionArgs) {
|
||||
|
||||
// 如果有错误,返回错误信息
|
||||
if (Object.keys(errors).length > 0) {
|
||||
return json({ errors });
|
||||
return Response.json({ errors });
|
||||
}
|
||||
|
||||
// 获取文件信息
|
||||
@@ -195,7 +215,7 @@ export async function action({ request }: ActionFunctionArgs) {
|
||||
// 这里的代码仅用于模拟。在前端组件中,我们将实现实际的文件处理逻辑。
|
||||
|
||||
// 模拟文件上传成功响应
|
||||
return json({
|
||||
return Response.json({
|
||||
success: true,
|
||||
message: "文件上传请求已接收",
|
||||
fileId: `file_${Date.now()}`,
|
||||
@@ -204,7 +224,7 @@ export async function action({ request }: ActionFunctionArgs) {
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("文件上传失败:", error);
|
||||
return json(
|
||||
return Response.json(
|
||||
{ success: false, error: "文件上传失败,请重试" },
|
||||
{ status: 500 }
|
||||
);
|
||||
@@ -254,6 +274,8 @@ export default function FilesUpload() {
|
||||
const { documents, documentTypes } = useLoaderData<LoaderData>();
|
||||
|
||||
// 状态管理
|
||||
// 高级上传设置
|
||||
const [showAdvancedOptions, setShowAdvancedOptions] = useState(false);
|
||||
const [isTestDocument, setIsTestDocument] = useState(false);
|
||||
const [fileType, setFileType] = useState<FileType | "">("");
|
||||
const [priority, setPriority] = useState<Priority>(Priority.NORMAL);
|
||||
@@ -262,7 +284,7 @@ export default function FilesUpload() {
|
||||
const [currentFiles, setCurrentFiles] = useState<File[]>([]);
|
||||
const [uploadProgress, setUploadProgress] = useState(0);
|
||||
const [uploadSpeed, setUploadSpeed] = useState("0KB/s");
|
||||
const [uploadStage, setUploadStage] = useState<"idle" | "uploading" | "processing" | "completed">("idle");
|
||||
const [uploadStage, setUploadStage] = useState<"idle" | "uploading" | "processing" | "completed" | "hadden">("idle");
|
||||
const [processingSteps, setProcessingSteps] = useState<Step[]>([
|
||||
{ title: "文件上传", description: "等待上传文件到服务器...", status: "waiting" },
|
||||
{ title: "文档转换拆分", description: "转换文档格式,拆分文档内容", status: "waiting" },
|
||||
@@ -310,7 +332,8 @@ export default function FilesUpload() {
|
||||
useEffect(() => {
|
||||
console.log('设置上传队列状态检查定时器');
|
||||
|
||||
// 设置定时器检查队列中文件的状态
|
||||
// 设置定时器检查队列中文件的状态,初始先加载一次查询
|
||||
checkQueueStatus();
|
||||
statusCheckIntervalRef.current = setInterval(checkQueueStatus, 10000);
|
||||
|
||||
// 只在组件卸载时清除
|
||||
@@ -745,7 +768,6 @@ export default function FilesUpload() {
|
||||
};
|
||||
|
||||
|
||||
|
||||
// 格式化文件大小显示
|
||||
const formatFileSize = (bytes: number) => {
|
||||
if (bytes === 0) return '0 Bytes';
|
||||
@@ -805,6 +827,11 @@ export default function FilesUpload() {
|
||||
let statusText = "";
|
||||
|
||||
switch(record.status) {
|
||||
case DocumentStatus.WAITING:
|
||||
statusClass = "status-processing";
|
||||
statusIcon = "ri-loader-4-line";
|
||||
statusText = "等待中";
|
||||
break;
|
||||
case DocumentStatus.CUTTING:
|
||||
statusClass = "status-processing";
|
||||
statusIcon = "ri-loader-4-line";
|
||||
@@ -950,7 +977,9 @@ export default function FilesUpload() {
|
||||
tipText="支持单个或批量上传,文件格式:PDF、Word、Excel、图片"
|
||||
shouldPreventFileSelect={!fileType}
|
||||
/>
|
||||
<div className="switch-container">
|
||||
|
||||
{/* 测试文档标记 */}
|
||||
<div className="switch-container mb-4">
|
||||
<label className="switch" aria-label="标记为测试文档">
|
||||
<input
|
||||
type="checkbox"
|
||||
@@ -961,6 +990,61 @@ export default function FilesUpload() {
|
||||
</label>
|
||||
<span>标记为测试文档(不计入正式统计)</span>
|
||||
</div>
|
||||
|
||||
{/* 高级上传设置 */}
|
||||
{ showAdvancedOptions && (
|
||||
<div className="advanced-options">
|
||||
<div
|
||||
className={`advanced-options-toggle ${showAdvancedOptions ? 'open' : ''}`}
|
||||
onClick={() => setShowAdvancedOptions(!showAdvancedOptions)}
|
||||
>
|
||||
<span>高级上传设置</span>
|
||||
<i className="ri-arrow-down-s-line"></i>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="advanced-options-content"
|
||||
style={{ display: showAdvancedOptions ? 'block' : 'none' }}
|
||||
>
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div className="form-group">
|
||||
<label className="form-label" htmlFor="storageType">存储方式</label>
|
||||
<select
|
||||
id="storageType"
|
||||
name="storageType"
|
||||
className="form-select w-full"
|
||||
defaultValue="minio"
|
||||
>
|
||||
{STORAGE_TYPES.map(type => (
|
||||
<option key={type.id} value={type.id}>
|
||||
{type.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<div className="form-tip">选择文档的存储位置</div>
|
||||
</div>
|
||||
|
||||
<div className="form-group">
|
||||
<label className="form-label" htmlFor="afterUpload">上传后操作</label>
|
||||
<select
|
||||
id="afterUpload"
|
||||
name="afterUpload"
|
||||
className="form-select w-full"
|
||||
defaultValue="list"
|
||||
>
|
||||
{AFTER_UPLOAD_OPTIONS.map(option => (
|
||||
<option key={option.id} value={option.id}>
|
||||
{option.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<div className="form-tip">上传完成后自动执行的操作</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -982,7 +1066,8 @@ export default function FilesUpload() {
|
||||
)}
|
||||
|
||||
{/* 文件信息显示 - 上传完成后显示 */}
|
||||
{uploadStage !== "idle" && completedFiles.length > 0 && (
|
||||
{/* {uploadStage !== "idle" && completedFiles.length > 0 && ( */}
|
||||
{uploadStage === "hadden" && completedFiles.length > 0 && (
|
||||
<div className="file-info-grid">
|
||||
<div>
|
||||
<h4 className="font-medium mb-3">文件信息</h4>
|
||||
|
||||
Reference in New Issue
Block a user