完善文档预览的效果修改
This commit is contained in:
+130
-37
@@ -1,4 +1,4 @@
|
||||
import { useState } from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
import { useLoaderData, useActionData, useNavigate, Form } from "@remix-run/react";
|
||||
import { redirect, type ActionFunctionArgs, type LoaderFunctionArgs, type MetaFunction } from "@remix-run/node";
|
||||
import { Card } from "~/components/ui/Card";
|
||||
@@ -7,6 +7,10 @@ import documentEditStyles from "~/styles/pages/documents_edit.css?url";
|
||||
import { getDocument, updateDocument } from "~/api/files/documents";
|
||||
import { getDocumentTypes } from "~/api/document-types/document-types";
|
||||
import { FileTag } from "~/components/ui/FileTag";
|
||||
import { toastService } from "~/components/ui/Toast";
|
||||
import { Document, Page , pdfjs } from "react-pdf";
|
||||
|
||||
pdfjs.GlobalWorkerOptions.workerSrc = '/pdf.worker.js';
|
||||
|
||||
export function links() {
|
||||
return [{ rel: "stylesheet", href: documentEditStyles }];
|
||||
@@ -19,6 +23,10 @@ export const meta: MetaFunction = () => {
|
||||
];
|
||||
};
|
||||
|
||||
export const handle = {
|
||||
breadcrumb: "文档编辑"
|
||||
};
|
||||
|
||||
|
||||
|
||||
// 文档审核状态定义
|
||||
@@ -106,31 +114,31 @@ export async function action({ request }: ActionFunctionArgs) {
|
||||
const formData = await request.formData();
|
||||
|
||||
// 从表单数据中提取字段
|
||||
const type = formData.get("type_id") as string;
|
||||
// const type = formData.get("type_id") as string;
|
||||
const documentNumber = formData.get("document_number") as string;
|
||||
const auditStatus = parseInt(formData.get("audit_status") as string);
|
||||
const isTest = formData.get("is_test_document") === "on";
|
||||
const remark = formData.get("remark") as string;
|
||||
|
||||
|
||||
// 验证必填字段
|
||||
if (!type || auditStatus === undefined || isNaN(auditStatus)) {
|
||||
return Response.json(
|
||||
{
|
||||
error: "缺少必填字段",
|
||||
fieldErrors: {
|
||||
type_id: !type ? "文档类型不能为空" : null,
|
||||
audit_status: (auditStatus === undefined || isNaN(auditStatus)) ? "审核状态不能为空" : null
|
||||
}
|
||||
},
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
// if (!type || auditStatus === undefined || isNaN(auditStatus)) {
|
||||
// return Response.json(
|
||||
// {
|
||||
// error: "缺少必填字段",
|
||||
// fieldErrors: {
|
||||
// type_id: !type ? "文档类型不能为空" : null,
|
||||
// audit_status: (auditStatus === undefined || isNaN(auditStatus)) ? "审核状态不能为空" : null
|
||||
// }
|
||||
// },
|
||||
// { status: 400 }
|
||||
// );
|
||||
// }
|
||||
|
||||
console.log('提交更新:', { type, documentNumber, auditStatus, isTest, remark });
|
||||
// console.log('提交更新:', { type, documentNumber, auditStatus, isTest, remark });
|
||||
|
||||
// 更新文档
|
||||
const updateResponse = await updateDocument(id, {
|
||||
type,
|
||||
// type,
|
||||
documentNumber,
|
||||
auditStatus,
|
||||
isTest,
|
||||
@@ -138,17 +146,23 @@ export async function action({ request }: ActionFunctionArgs) {
|
||||
});
|
||||
|
||||
if (updateResponse.error) {
|
||||
console.error('更新文档失败:', updateResponse.error);
|
||||
console.error('更新文档失败1:', updateResponse.error);
|
||||
return Response.json({
|
||||
error: updateResponse.error,
|
||||
message: "更新文档失败,请检查提交的数据是否正确"
|
||||
}, { status: updateResponse.status || 500 });
|
||||
}
|
||||
|
||||
// toastService.success('更新文档成功');
|
||||
|
||||
// 重定向回文档列表
|
||||
return redirect("/documents");
|
||||
// return redirect("/documents");
|
||||
return Response.json({
|
||||
success: true,
|
||||
message: "更新文档成功"
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("更新文档失败:", error);
|
||||
console.error("更新文档失败2:", error);
|
||||
return Response.json({
|
||||
error: "更新文档失败",
|
||||
message: error instanceof Error ? error.message : "发生未知错误"
|
||||
@@ -160,8 +174,96 @@ export async function action({ request }: ActionFunctionArgs) {
|
||||
export default function DocumentEdit() {
|
||||
const { document, documentTypes } = useLoaderData<typeof loader>();
|
||||
const actionData = useActionData<typeof action>();
|
||||
const [numPages, setNumPages] = useState(0);
|
||||
const [loadError, setLoadError] = useState<string | null>(null);
|
||||
const navigate = useNavigate();
|
||||
|
||||
useEffect(() => {
|
||||
// console.log('actionData', actionData);
|
||||
if (actionData?.error) {
|
||||
toastService.error('更新文档失败:' + actionData.error);
|
||||
}
|
||||
if (actionData?.success) {
|
||||
toastService.success('更新文档成功');
|
||||
}
|
||||
}, [actionData]);
|
||||
|
||||
const onDocumentLoadSuccess = ({numPages}: {numPages: number}) => {
|
||||
setNumPages(numPages);
|
||||
console.log('文档加载成功', numPages);
|
||||
}
|
||||
|
||||
const renderDocumentContent = () => {
|
||||
return (
|
||||
<div className="preview-content relative overflow-y-auto max-h-[1000px]">
|
||||
<Document
|
||||
file={'http://172.18.0.100:9000/docauditai/'+document.path}
|
||||
onLoadSuccess={onDocumentLoadSuccess}
|
||||
onLoadError={(error) => {
|
||||
console.error("PDF加载错误:", error);
|
||||
setLoadError("PDF文档加载失败:" + (error.message || "未知错误"));
|
||||
}}
|
||||
className="flex flex-col items-center w-full"
|
||||
error={<div className="text-red-500">PDF文档加载失败,请检查链接或网络连接。</div>}
|
||||
noData={<div>无数据</div>}
|
||||
loading={<div className="text-center py-10">PDF加载中...</div>}
|
||||
>
|
||||
{renderAllPages()}
|
||||
</Document>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const renderAllPages = () => {
|
||||
// 如果还没有获取到PDF总页数,返回null
|
||||
if (!numPages) return null;
|
||||
|
||||
// 用于存储所有页面组件的数组
|
||||
const pages = [];
|
||||
const styles = {
|
||||
pageContainer: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column' as const,
|
||||
alignItems: 'center',
|
||||
width: '100%',
|
||||
position: 'relative' as const,
|
||||
}
|
||||
};
|
||||
|
||||
// 遍历每一页,生成对应的页面组件
|
||||
for (let i = 1; i <= numPages; i++) {
|
||||
// 为每一页创建组件
|
||||
pages.push(
|
||||
<div key={i} id={`page-${i}`} style={styles.pageContainer}>
|
||||
{/* 页码标识,显示在页面上方 */}
|
||||
<div className="text-center text-gray-500 text-sm mb-2">第 {i} 页</div>
|
||||
|
||||
{/* 页面容器,应用缩放变换,设置相对定位用于放置评查点高亮 */}
|
||||
<div
|
||||
className="page-wrapper flex justify-center"
|
||||
style={{
|
||||
// transform: `scale(${zoomFactor})`, // 根据zoomLevel应用缩放
|
||||
transformOrigin: 'top center', // 缩放原点设置为顶部中心
|
||||
position: 'relative', // 相对定位,作为评查点高亮的定位参考
|
||||
maxWidth: '100%', // 限制最大宽度
|
||||
}}
|
||||
>
|
||||
{/* 渲染PDF页面组件 */}
|
||||
<Page
|
||||
pageNumber={i} // 当前页码
|
||||
renderTextLayer={true} // 启用文本层,使文本可选择
|
||||
renderAnnotationLayer={true} // 启用注释层,显示PDF内置注释
|
||||
className="border border-gray-300 shadow-md" // 添加边框和阴影样式
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// 返回所有页面组件数组
|
||||
return pages;
|
||||
};
|
||||
|
||||
// 定义类型
|
||||
interface DocType {
|
||||
id: string | number;
|
||||
@@ -275,7 +377,8 @@ export default function DocumentEdit() {
|
||||
name="type_id"
|
||||
className="form-select"
|
||||
defaultValue={document.type}
|
||||
disabled={document.fileStatus !== 'Processed'}
|
||||
// disabled={document.fileStatus !== 'Processed'}
|
||||
disabled={true}
|
||||
required
|
||||
>
|
||||
{documentTypes.map((type: DocType) => (
|
||||
@@ -384,22 +487,12 @@ export default function DocumentEdit() {
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="preview-content">
|
||||
<div className="preview-placeholder">
|
||||
<i className={`ri-file-${document.fileType}-line`}></i>
|
||||
<p>预览功能暂不可用</p>
|
||||
<p className="text-xs mt-2">点击"在新窗口打开"查看完整文档</p>
|
||||
<Button
|
||||
type="primary"
|
||||
size="small"
|
||||
icon="ri-external-link-line"
|
||||
className="mt-4"
|
||||
onClick={openPreview}
|
||||
>
|
||||
在新窗口打开
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
{/* 预览窗口 */}
|
||||
{loadError ?(<div className="text-red-500">
|
||||
{loadError}
|
||||
</div>):(
|
||||
renderDocumentContent()
|
||||
)}
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ 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 { messageService } from "~/components/ui/MessageModal";
|
||||
import {
|
||||
getTodayDocuments,
|
||||
getDocumentTypes,
|
||||
@@ -323,6 +324,18 @@ export default function FilesUpload() {
|
||||
// 获取action返回的数据
|
||||
const actionData = useActionData<ActionData>();
|
||||
|
||||
// 添加一个本地状态来跟踪文件类型错误
|
||||
const [fileTypeError, setFileTypeError] = useState<string | null>(
|
||||
actionData?.errors?.fileType || null
|
||||
);
|
||||
|
||||
// 监听actionData变化,当有fileType错误时更新fileTypeError状态
|
||||
useEffect(() => {
|
||||
if (actionData?.errors?.fileType) {
|
||||
setFileTypeError(actionData.errors.fileType);
|
||||
}
|
||||
}, [actionData]);
|
||||
|
||||
// 状态检查定时器引用
|
||||
const statusCheckIntervalRef = useRef<NodeJS.Timeout | null>(null);
|
||||
|
||||
@@ -402,6 +415,8 @@ export default function FilesUpload() {
|
||||
// 确保只有选择了有效的文件类型才进行设置
|
||||
if (value) {
|
||||
setFileType(value as FileType);
|
||||
// 立即清除错误状态
|
||||
setFileTypeError(null);
|
||||
|
||||
// 如果已经有选中的文件,且选择了文件类型,则开始上传
|
||||
if (currentFiles.length > 0) {
|
||||
@@ -409,6 +424,8 @@ export default function FilesUpload() {
|
||||
}
|
||||
} else {
|
||||
setFileType("");
|
||||
// 如果用户选择了空选项,显示错误信息
|
||||
setFileTypeError("上传文件之前请选择文件类型");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -535,6 +552,7 @@ export default function FilesUpload() {
|
||||
const errorSteps = [...processingSteps];
|
||||
errorSteps[0].status = "error";
|
||||
errorSteps[0].description = `上传文件失败: ${error instanceof Error ? error.message : '未知错误'}`;
|
||||
|
||||
setProcessingSteps(errorSteps);
|
||||
|
||||
// 清除进度定时器
|
||||
@@ -542,7 +560,13 @@ export default function FilesUpload() {
|
||||
clearInterval(progressIntervalRef.current);
|
||||
}
|
||||
|
||||
alert(`文件上传失败: ${error instanceof Error ? error.message : '未知错误'}`);
|
||||
// 显示错误提示
|
||||
messageService.error('文件上传失败:只能上传pdf文件。', {
|
||||
title: '文件上传失败',
|
||||
onConfirm: () => {
|
||||
resetUpload();
|
||||
}
|
||||
});
|
||||
resetUpload();
|
||||
}
|
||||
};
|
||||
@@ -924,7 +948,7 @@ export default function FilesUpload() {
|
||||
<select
|
||||
id="file-type-select"
|
||||
name="fileType"
|
||||
className={`form-select ${actionData?.errors?.fileType ? 'border-red-500' : ''}`}
|
||||
className={`form-select ${fileTypeError ? 'border-red-500' : ''}`}
|
||||
value={fileType}
|
||||
onChange={handleFileTypeChange}
|
||||
disabled={uploadStage !== "idle"}
|
||||
@@ -935,8 +959,8 @@ export default function FilesUpload() {
|
||||
))}
|
||||
</select>
|
||||
|
||||
{actionData?.errors?.fileType && (
|
||||
<div className="text-red-500 text-sm mt-1">{actionData.errors.fileType}</div>
|
||||
{fileTypeError && (
|
||||
<div className="text-red-500 text-sm mt-1">{fileTypeError}</div>
|
||||
)}
|
||||
|
||||
<div className="form-tip">不同类型的文档将应用不同的审核规则</div>
|
||||
@@ -1000,8 +1024,9 @@ export default function FilesUpload() {
|
||||
ref={uploadAreaRef}
|
||||
onFilesSelected={handleFilesSelected}
|
||||
multiple={true}
|
||||
accept=".pdf,.doc,.docx,.xls,.xlsx,.jpg,.jpeg,.png"
|
||||
tipText="支持单个或批量上传,文件格式:PDF、Word、Excel、图片"
|
||||
// accept=".pdf,.doc,.docx,.xls,.xlsx,.jpg,.jpeg,.png"
|
||||
accept=".pdf"
|
||||
tipText="支持单个或多个pdf文件上传,文件格式:PDF"
|
||||
shouldPreventFileSelect={!fileType}
|
||||
/>
|
||||
|
||||
@@ -1021,17 +1046,28 @@ export default function FilesUpload() {
|
||||
{/* 高级上传设置 */}
|
||||
{ showAdvancedOptions && (
|
||||
<div className="advanced-options">
|
||||
<div
|
||||
<button
|
||||
className={`advanced-options-toggle ${showAdvancedOptions ? 'open' : ''}`}
|
||||
onClick={() => setShowAdvancedOptions(!showAdvancedOptions)}
|
||||
aria-expanded={showAdvancedOptions}
|
||||
aria-controls="advanced-options-content"
|
||||
type="button"
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault();
|
||||
setShowAdvancedOptions(!showAdvancedOptions);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<span>高级上传设置</span>
|
||||
<i className="ri-arrow-down-s-line"></i>
|
||||
</div>
|
||||
<i className="ri-arrow-down-s-line" aria-hidden="true"></i>
|
||||
</button>
|
||||
|
||||
<div
|
||||
id="advanced-options-content"
|
||||
className="advanced-options-content"
|
||||
style={{ display: showAdvancedOptions ? 'block' : 'none' }}
|
||||
aria-hidden={!showAdvancedOptions}
|
||||
>
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div className="form-group">
|
||||
|
||||
+18
-15
@@ -30,6 +30,7 @@ import { useState, useEffect } from "react";
|
||||
import { useNavigate, useLoaderData } from "@remix-run/react";
|
||||
import reviewsStyles from "~/styles/reviews.css?url";
|
||||
import { getReviewPoints, updateReviewResult, confirmReviewResults } from "~/api/evaluation_points/reviews";
|
||||
import { toastService } from "~/components/ui/Toast";
|
||||
|
||||
// 导入评查详情页面组件
|
||||
import {
|
||||
@@ -208,7 +209,7 @@ export async function loader({ request }: LoaderFunctionArgs) {
|
||||
const reviewData = await getReviewPoints(id);
|
||||
|
||||
// console.log("documentData-------",JSON.stringify(documentData.data,null,2));
|
||||
console.log("reviewData-------",JSON.stringify('data' in reviewData ? reviewData.data : '',null,2));
|
||||
// console.log("reviewData-------",JSON.stringify('data' in reviewData ? reviewData.data : '',null,2));
|
||||
if ('error' in reviewData && reviewData.error) {
|
||||
console.error("获取评查点数据错误:", reviewData.error);
|
||||
return Response.json({ error: reviewData.error }, { status: reviewData.status || 500 });
|
||||
@@ -357,31 +358,34 @@ export default function ReviewDetails() {
|
||||
};
|
||||
});
|
||||
|
||||
alert('评审数据已更新');
|
||||
toastService.success('评审数据已更新');
|
||||
} else {
|
||||
console.error('返回的数据格式不正确');
|
||||
alert('刷新评审数据失败: 返回的数据格式不正确');
|
||||
toastService.error('刷新评审数据失败: 返回的数据格式不正确');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('刷新评审数据失败:', error);
|
||||
alert(`刷新评审数据失败: ${error instanceof Error ? error.message : '未知错误'}`);
|
||||
toastService.error(`刷新评审数据失败: ${error instanceof Error ? error.message : '未知错误'}`);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
// 处理评审点状态变更
|
||||
const handleReviewPointStatusChange = async (reviewPointResultId: string, newStatus: string, message: string) => {
|
||||
const handleReviewPointStatusChange = async (reviewPointResultId: string, editAuditStatusId: string | number, newStatus: string, message: string) => {
|
||||
// 将字符串的布尔值转换为布尔类型
|
||||
const boolResult = newStatus === 'true';
|
||||
let boolResult = 'review';
|
||||
if(newStatus !== 'review'){
|
||||
boolResult = newStatus === 'true' ? 'true' : 'false';
|
||||
}
|
||||
|
||||
try {
|
||||
// 调用 API 更新评查结果
|
||||
const response = await updateReviewResult(reviewPointResultId, boolResult, message);
|
||||
const response = await updateReviewResult(reviewPointResultId, editAuditStatusId, boolResult, message);
|
||||
|
||||
if (response.error) {
|
||||
console.error('更新评查结果失败:', response.error);
|
||||
alert(`更新评查结果失败: ${response.error}`);
|
||||
toastService.error(`更新评查结果失败: ${response.error}`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -396,8 +400,7 @@ export default function ReviewDetails() {
|
||||
const updatedReviewPoints = reviewData.reviewPoints.map(point =>
|
||||
point.id === reviewPointResultId ? {
|
||||
...point,
|
||||
result: boolResult,
|
||||
status: boolResult ? 'success' : 'error',
|
||||
result: newStatus === 'true' ? true : (newStatus === 'false' ? false : point.result),
|
||||
message: message
|
||||
} : point
|
||||
);
|
||||
@@ -416,13 +419,13 @@ export default function ReviewDetails() {
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('更新评查结果出错:', error);
|
||||
alert('更新评查结果失败,请稍后重试');
|
||||
toastService.error('更新评查结果失败,请稍后重试');
|
||||
}
|
||||
};
|
||||
|
||||
const handleConfirmResults = async () => {
|
||||
if (!document || !document.id) {
|
||||
alert('文档数据不完整,无法确认评查结果');
|
||||
toastService.error('文档数据不完整,无法确认评查结果');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -435,18 +438,18 @@ export default function ReviewDetails() {
|
||||
|
||||
if (response.error) {
|
||||
console.error('确认评查结果失败:', response.error);
|
||||
alert(`确认评查结果失败: ${response.error}`);
|
||||
toastService.error(`确认评查结果失败: ${response.error}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// 显示成功消息
|
||||
alert('评查结果已确认,文档审核状态已更新');
|
||||
toastService.success('评查结果已确认,文档审核状态已更新');
|
||||
|
||||
// 导航到文档列表页
|
||||
navigate('/documents');
|
||||
} catch (error) {
|
||||
console.error('确认评查结果出错:', error);
|
||||
alert(`确认评查结果失败: ${error instanceof Error ? error.message : '未知错误'}`);
|
||||
toastService.error(`确认评查结果失败: ${error instanceof Error ? error.message : '未知错误'}`);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ export async function loader({ request }: LoaderFunctionArgs) {
|
||||
pageSize,
|
||||
};
|
||||
|
||||
console.log('rules-filessearchParams-----',searchParams);
|
||||
// console.log('rules-filessearchParams-----',searchParams);
|
||||
|
||||
const filesResponse = await getReviewFiles(searchParams);
|
||||
if (filesResponse.error) {
|
||||
@@ -343,16 +343,47 @@ export default function RulesFiles() {
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "评查状态",
|
||||
title: "评查统计",
|
||||
key: "reviewStatus",
|
||||
width: "12%",
|
||||
render: (_: unknown, file: ReviewFileUI) =>
|
||||
// 要文件切分处理完之后,再显示评查统计
|
||||
file.status === 'Processed' ? (
|
||||
<StatusBadge
|
||||
status={file.reviewStatus}
|
||||
text={`${REVIEW_STATUS_LABELS[file.reviewStatus]}${file.issueCount>0?'('+file.issueCount+')':''}`}
|
||||
showIcon={true}
|
||||
/>
|
||||
<div>
|
||||
{file.passCount > 0 && (
|
||||
<StatusBadge
|
||||
status="pass"
|
||||
text={`通过(${file.passCount})`}
|
||||
showIcon={true}
|
||||
className="my-2"
|
||||
/>
|
||||
)}
|
||||
{file.warningCount > 0 && (
|
||||
<StatusBadge
|
||||
status="warning"
|
||||
text={`警告(${file.warningCount})`}
|
||||
showIcon={true}
|
||||
className="my-2"
|
||||
/>
|
||||
)}
|
||||
{file.failCount > 0 && (
|
||||
<StatusBadge
|
||||
status="fail"
|
||||
text={`不通过(${file.failCount})`}
|
||||
showIcon={true}
|
||||
className="my-2"
|
||||
/>
|
||||
)}
|
||||
{file.manualCount > 0 && (
|
||||
<StatusBadge
|
||||
status="pending"
|
||||
text={`需人工(${file.manualCount})`}
|
||||
showIcon={true}
|
||||
className="my-2"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
) : (
|
||||
<div className="text-sm">
|
||||
-
|
||||
@@ -451,10 +482,10 @@ export default function RulesFiles() {
|
||||
/>
|
||||
<SearchFilter
|
||||
label="搜索"
|
||||
placeholder="搜索文件名、合同编号或关键词"
|
||||
placeholder="搜索文件名、合同编号"
|
||||
value={searchParams.get('keyword') || ''}
|
||||
onSearch={handleSearch}
|
||||
buttonText=""
|
||||
buttonText="搜索"
|
||||
className="mr-2 flex-1"
|
||||
/>
|
||||
</FilterPanel>
|
||||
|
||||
@@ -706,6 +706,11 @@ export default function RuleNew() {
|
||||
const id = searchParams.get('id');
|
||||
const mode = searchParams.get('mode');
|
||||
|
||||
// 编辑或复制模式下设置加载状态
|
||||
if (id || mode === 'copy') {
|
||||
setIsLoading(true);
|
||||
}
|
||||
|
||||
// 设置编辑模式
|
||||
if (mode && mode === 'copy') {
|
||||
setIsEditMode(false);
|
||||
|
||||
Reference in New Issue
Block a user