隐藏上传文件入口,交叉评查的文件查看添加防抖点击,升级pdf加载组件版本优化清晰度
This commit is contained in:
@@ -9,6 +9,7 @@ import { LoadingIndicator } from '../ui/SkeletonScreen';
|
||||
import { updateDocumentAuditStatus, type TaskDocument } from '~/api/cross-checking/cross-files'; // 更新导入
|
||||
import { toastService } from '../ui/Toast';
|
||||
import { formatDate } from '~/utils';
|
||||
import {useRef, useState} from "react";
|
||||
|
||||
// 导出样式链接
|
||||
export const links = () => [];
|
||||
@@ -42,7 +43,16 @@ export function DocumentListModal({
|
||||
onPageChange,
|
||||
onPageSizeChange
|
||||
}: DocumentListModalProps) {
|
||||
|
||||
// 查看按钮防抖
|
||||
const [isnavigating,setIsnavigating] = useState(false)
|
||||
const viewDebounceRef = useRef<number | null>(null)
|
||||
const handleViewClickDebounced = (fileId: string, auditStatus: number | null) => {
|
||||
if(viewDebounceRef.current) return;
|
||||
viewDebounceRef.current = window.setTimeout(()=>{
|
||||
viewDebounceRef.current = null;
|
||||
},1000);
|
||||
void handleReviewFileClick(fileId, auditStatus);
|
||||
}
|
||||
// 查看评查文件
|
||||
const handleReviewFileClick = async (fileId: string, auditStatus: number | null) => {
|
||||
// 检查audit_status是否为0,如果是则更新为2
|
||||
@@ -61,6 +71,7 @@ export function DocumentListModal({
|
||||
|
||||
// 如果有自定义的查看处理函数,则调用它
|
||||
if (onViewFile) {
|
||||
setIsnavigating(true)
|
||||
onViewFile(fileId);
|
||||
}
|
||||
};
|
||||
@@ -250,11 +261,11 @@ export function DocumentListModal({
|
||||
type="default"
|
||||
size="small"
|
||||
icon="ri-eye-line"
|
||||
onClick={() => handleReviewFileClick(file.document_id.toString(), file.audit_status)}
|
||||
onClick={() => handleViewClickDebounced(file.document_id.toString(), file.audit_status)}
|
||||
disabled={file.status !== 'Processed'}
|
||||
className="mr-2"
|
||||
>
|
||||
查看
|
||||
{isnavigating ? '跳转中...' : '查看'}
|
||||
</Button>
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -334,8 +334,8 @@ export function FilePreview({ fileContent, activeReviewPointResultId, targetPage
|
||||
{/* 渲染PDF页面组件 */}
|
||||
<Page
|
||||
pageNumber={i} // 当前页码
|
||||
renderTextLayer={true} // 启用文本层,使文本可选择
|
||||
renderAnnotationLayer={true} // 启用注释层,显示PDF内置注释
|
||||
renderTextLayer={false} // 停用文本层,使文本可选择
|
||||
renderAnnotationLayer={false} // 停用注释层,显示PDF内置注释
|
||||
className="border border-gray-300 shadow-md" // 添加边框和阴影样式
|
||||
/>
|
||||
|
||||
|
||||
@@ -240,6 +240,18 @@ export function Sidebar({ onToggle, collapsed, userRole, selectedApp = '' }: Sid
|
||||
return true;
|
||||
});
|
||||
|
||||
// filteredMenuItems = filteredMenuItems.map(item => {
|
||||
// if(item.children && item.children.length > 0){
|
||||
// const children = item.children.filter(child => {
|
||||
// const isUploadByPath = child.path === '/files/upload' || child.path?.startsWith('/files/upload')
|
||||
// const isUploadByTitle = child.title === '文件上传'
|
||||
// return !(isUploadByPath || isUploadByTitle)
|
||||
// })
|
||||
// return { ...item, children}
|
||||
// }
|
||||
// return item
|
||||
// })
|
||||
|
||||
return (
|
||||
<div className={`sidebar ${collapsed ? 'collapsed' : ''}`}>
|
||||
<div className="py-6 px-4 border-b border-gray-100 flex justify-between items-center">
|
||||
@@ -333,7 +345,7 @@ export function Sidebar({ onToggle, collapsed, userRole, selectedApp = '' }: Sid
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault();
|
||||
toggleMenu(item.id, e as unknown as React.MouseEvent);
|
||||
toggleMenu(item.id, (e as unknown) as React.MouseEvent);
|
||||
}
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -8,6 +8,7 @@ import { DOCUMENT_URL } from '~/api/axios-client';
|
||||
|
||||
// 设置worker路径为public目录下的worker文件
|
||||
// 使用已经下载的兼容版本 (pdfjs-dist v2.12.313)
|
||||
// 2025/09/28 使用新版本的pdfjs-dist v4.8.69
|
||||
pdfjs.GlobalWorkerOptions.workerSrc = '/pdf.worker.js';
|
||||
|
||||
// 导入统一的ReviewPoint类型
|
||||
@@ -324,8 +325,8 @@ export function FilePreview({ fileContent, activeReviewPointResultId, targetPage
|
||||
<div
|
||||
className="page-wrapper"
|
||||
style={{
|
||||
transform: `scale(${zoomFactor})`, // 根据zoomLevel应用缩放
|
||||
transformOrigin: 'top center', // 缩放原点设置为顶部中心
|
||||
// transform: `scale(${zoomFactor})`, // 根据zoomLevel应用缩放
|
||||
// transformOrigin: 'top center', // 缩放原点设置为顶部中心
|
||||
position: 'relative', // 相对定位,作为评查点高亮的定位参考
|
||||
display: 'inline-block', // 内联块级元素,宽度由内容决定
|
||||
margin: '0 auto', // 水平居中
|
||||
@@ -334,8 +335,10 @@ export function FilePreview({ fileContent, activeReviewPointResultId, targetPage
|
||||
{/* 渲染PDF页面组件 */}
|
||||
<Page
|
||||
pageNumber={i} // 当前页码
|
||||
renderTextLayer={true} // 启用文本层,使文本可选择
|
||||
renderAnnotationLayer={true} // 启用注释层,显示PDF内置注释
|
||||
scale={zoomLevel / 100}
|
||||
devicePixelRatio={window.devicePixelRatio || 1} //根据设备像素比渲染
|
||||
renderTextLayer={false} // 停用文本层,使文本可选择
|
||||
renderAnnotationLayer={false} // 停用注释层,显示PDF内置注释
|
||||
className="border border-gray-300 shadow-md" // 添加边框和阴影样式
|
||||
/>
|
||||
|
||||
@@ -405,7 +408,8 @@ export function FilePreview({ fileContent, activeReviewPointResultId, targetPage
|
||||
style={{
|
||||
...styles.pdfContainer,
|
||||
// 当缩放大于100%时设置最小宽度,确保出现横向滚动条
|
||||
minWidth: zoomLevel > 100 ? `${zoomLevel}%` : '100%',
|
||||
// minWidth: zoomLevel > 100 ? `${zoomLevel}%` : '100%',
|
||||
width: '100%',
|
||||
overflow: 'visible'
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -73,9 +73,9 @@ const portConfigs: Record<string, Partial<ApiConfig>> = {
|
||||
// 主要
|
||||
// 梅州
|
||||
'51703': {
|
||||
baseUrl: 'http://10.79.97.17:8000',
|
||||
documentUrl: 'http://10.79.97.17:8000/docauditai/',
|
||||
uploadUrl: 'http://10.79.97.17:8000/admin/documents'
|
||||
baseUrl: 'http://nas.7bm.co:8873',
|
||||
documentUrl: 'http://nas.7bm.co:8873/docauditai/',
|
||||
uploadUrl: 'http://nas.7bm.co:8873/admin/documents'
|
||||
},
|
||||
|
||||
|
||||
@@ -139,12 +139,12 @@ const configs: Record<string, ApiConfig> = {
|
||||
|
||||
// 测试环境
|
||||
testing: {
|
||||
baseUrl: 'http://172.16.0.55:8008',
|
||||
// baseUrl: 'http://172.16.0.81:3000',
|
||||
baseUrl: 'http://nas.7bm.co:8873',
|
||||
// baseUrl: 'http://172.16.0.58:8873',
|
||||
// baseUrl: 'http://nas.7bm.co:3000',
|
||||
// documentUrl: 'http://172.16.0.81:9000/docauditai/',
|
||||
documentUrl: 'http://172.16.0.55:8008/docauditai/',
|
||||
uploadUrl: 'http://172.16.0.55:8008/admin/documents',
|
||||
documentUrl: 'http://nas.7bm.co:8873/docauditai/',
|
||||
uploadUrl: 'http://nas.7bm.co:8873/admin/documents',
|
||||
// uploadUrl: 'http://172.16.0.58:8008/admin/documents',
|
||||
// uploadUrl: 'http://172.16.0.58:8008/admin/documents',
|
||||
oauth: {
|
||||
|
||||
@@ -207,7 +207,7 @@ export default function CrossCheckingUpload() {
|
||||
const [taskInfo, setTaskInfo] = useState({
|
||||
name: '',
|
||||
date: '',
|
||||
type: '市局交叉评查',
|
||||
type: '市局间交叉评查',
|
||||
});
|
||||
// 步骤2状态
|
||||
const [groupChecked, setGroupChecked] = useState<string[]>(userInfo?.user_id ? [`user_${userInfo.user_id}`] : []);
|
||||
@@ -681,13 +681,15 @@ export default function CrossCheckingUpload() {
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<label htmlFor="task-type">任务类型</label>
|
||||
<input
|
||||
<select
|
||||
id="task-type"
|
||||
className="form-input"
|
||||
className="form-select"
|
||||
value={taskInfo.type}
|
||||
onChange={e => setTaskInfo({ ...taskInfo, type: e.target.value })}
|
||||
placeholder="请输入任务类型"
|
||||
/>
|
||||
>
|
||||
<option value="市局间交叉评查">市局间交叉评查</option>
|
||||
<option value="区局间交叉评查">区局间交叉评查</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className="flex justify-between items-center mt-6">
|
||||
<Button
|
||||
|
||||
@@ -375,8 +375,8 @@ export default function DocumentEdit() {
|
||||
{/* 渲染PDF页面组件 */}
|
||||
<Page
|
||||
pageNumber={i} // 当前页码
|
||||
renderTextLayer={true} // 启用文本层,使文本可选择
|
||||
renderAnnotationLayer={true} // 启用注释层,显示PDF内置注释
|
||||
renderTextLayer={false} // 停用文本层,使文本可选择
|
||||
renderAnnotationLayer={false} // 停用注释层,显示PDF内置注释
|
||||
className="border border-gray-300 shadow-md" // 添加边框和阴影样式
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -25,6 +25,7 @@ import {
|
||||
} from "~/api/files/files-upload";
|
||||
import { updateDocumentAuditStatus } from "~/api/evaluation_points/rules-files";
|
||||
import { links as fileTypeTagLinks } from "~/components/ui/FileTypeTag";
|
||||
import { useRevalidator} from "react-router-dom";
|
||||
|
||||
export function links() {
|
||||
return [
|
||||
@@ -34,11 +35,11 @@ export function links() {
|
||||
}
|
||||
|
||||
// 面包屑导航
|
||||
export const handle = {
|
||||
breadcrumb: () => {
|
||||
return '上传文件'
|
||||
}
|
||||
}
|
||||
// export const handle = {
|
||||
// breadcrumb: () => {
|
||||
// return '上传文件'
|
||||
// }
|
||||
// }
|
||||
|
||||
export const meta: MetaFunction = () => {
|
||||
return [
|
||||
@@ -286,6 +287,10 @@ export async function loader({ request }: LoaderFunctionArgs) {
|
||||
|
||||
// 文件上传页面组件
|
||||
export default function FilesUpload() {
|
||||
|
||||
const [isNavigating, setIsNavigating] = useState(false)
|
||||
const revalidator = useRevalidator()
|
||||
|
||||
// 获取 sessionStorage 中的 reviewType 值
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const [reviewType, setReviewType] = useState<string | null>(null);
|
||||
@@ -2084,12 +2089,21 @@ export default function FilesUpload() {
|
||||
}
|
||||
];
|
||||
|
||||
// 返回上一级防抖处理
|
||||
const handleBackClick = () =>{
|
||||
if(isNavigating) return;
|
||||
setIsNavigating(true)
|
||||
navigate(-1)
|
||||
revalidator.revalidate()
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<div className="file-upload-page">
|
||||
{/* 页面头部 */}
|
||||
<div className="page-header">
|
||||
<h2 className="page-title">待审核文件上传</h2>
|
||||
<button className="ant-btn ant-btn-default flex items-center my-2" onClick={()=>handleBackClick()}><i className="ri-arrow-left-line"></i>{isNavigating ? '返回中...' : '返回'}</button>
|
||||
</div>
|
||||
|
||||
{/* 文件类型选择和上传表单 */}
|
||||
|
||||
@@ -325,8 +325,8 @@ export default function Documents() {
|
||||
<div className="text-center text-gray-500 text-sm mb-2">第 {i} 页</div>
|
||||
<Page
|
||||
pageNumber={i}
|
||||
renderTextLayer={true}
|
||||
renderAnnotationLayer={true}
|
||||
renderTextLayer={false}
|
||||
renderAnnotationLayer={false}
|
||||
className="border border-gray-300 shadow-md"
|
||||
/>
|
||||
</div>
|
||||
|
||||
Vendored
+44
-44
@@ -1,44 +1,44 @@
|
||||
declare module 'react-pdf' {
|
||||
import * as React from 'react';
|
||||
|
||||
interface TextItem {
|
||||
str: string;
|
||||
transform: number[];
|
||||
width: number;
|
||||
height: number;
|
||||
fontName: string;
|
||||
}
|
||||
|
||||
export interface DocumentProps {
|
||||
file: string | Uint8Array | ArrayBuffer;
|
||||
onLoadSuccess?: ({ numPages }: { numPages: number }) => void;
|
||||
onLoadError?: (error: Error) => void;
|
||||
className?: string;
|
||||
error?: React.ReactNode;
|
||||
noData?: React.ReactNode;
|
||||
loading?: React.ReactNode;
|
||||
children?: React.ReactNode;
|
||||
}
|
||||
|
||||
export interface PageProps {
|
||||
pageNumber: number;
|
||||
renderTextLayer?: boolean;
|
||||
renderAnnotationLayer?: boolean;
|
||||
className?: string;
|
||||
customTextRenderer?: (textItem: TextItem) => string;
|
||||
}
|
||||
|
||||
export const Document: React.FC<DocumentProps>;
|
||||
export const Page: React.FC<PageProps>;
|
||||
export const pdfjs: {
|
||||
GlobalWorkerOptions: {
|
||||
workerSrc: string;
|
||||
};
|
||||
version: string;
|
||||
};
|
||||
}
|
||||
|
||||
declare module '*.css' {
|
||||
const content: Record<string, string>;
|
||||
export default content;
|
||||
}
|
||||
// declare module 'react-pdf' {
|
||||
// import * as React from 'react';
|
||||
//
|
||||
// interface TextItem {
|
||||
// str: string;
|
||||
// transform: number[];
|
||||
// width: number;
|
||||
// height: number;
|
||||
// fontName: string;
|
||||
// }
|
||||
//
|
||||
// export interface DocumentProps {
|
||||
// file: string | Uint8Array | ArrayBuffer;
|
||||
// onLoadSuccess?: ({ numPages }: { numPages: number }) => void;
|
||||
// onLoadError?: (error: Error) => void;
|
||||
// className?: string;
|
||||
// error?: React.ReactNode;
|
||||
// noData?: React.ReactNode;
|
||||
// loading?: React.ReactNode;
|
||||
// children?: React.ReactNode;
|
||||
// }
|
||||
//
|
||||
// export interface PageProps {
|
||||
// pageNumber: number;
|
||||
// renderTextLayer?: boolean;
|
||||
// renderAnnotationLayer?: boolean;
|
||||
// className?: string;
|
||||
// customTextRenderer?: (textItem: TextItem) => string;
|
||||
// }
|
||||
//
|
||||
// export const Document: React.FC<DocumentProps>;
|
||||
// export const Page: React.FC<PageProps>;
|
||||
// export const pdfjs: {
|
||||
// GlobalWorkerOptions: {
|
||||
// workerSrc: string;
|
||||
// };
|
||||
// version: string;
|
||||
// };
|
||||
// }
|
||||
//
|
||||
// declare module '*.css' {
|
||||
// const content: Record<string, string>;
|
||||
// export default content;
|
||||
// }
|
||||
Generated
+2724
-3647
File diff suppressed because it is too large
Load Diff
+1
-5
@@ -19,9 +19,6 @@
|
||||
"@ant-design/icons": "^5.6.1",
|
||||
"@codemirror/lang-javascript": "^6.2.3",
|
||||
"@codemirror/theme-one-dark": "^6.1.2",
|
||||
"@react-pdf-viewer/core": "^3.12.0",
|
||||
"@react-pdf-viewer/highlight": "^3.12.0",
|
||||
"@react-pdf-viewer/search": "^3.12.0",
|
||||
"@remix-run/node": "^2.16.2",
|
||||
"@remix-run/react": "^2.16.2",
|
||||
"@remix-run/serve": "^2.16.2",
|
||||
@@ -43,14 +40,13 @@
|
||||
"katex": "^0.16.22",
|
||||
"mammoth": "^1.9.0",
|
||||
"pdf-lib": "^1.17.1",
|
||||
"pdfjs-dist": "^3.11.174",
|
||||
"pg": "^8.14.1",
|
||||
"pm2": "^6.0.8",
|
||||
"prismjs": "^1.30.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-markdown": "^10.1.0",
|
||||
"react-pdf": "^5.7.2",
|
||||
"react-pdf": "^9.2.1",
|
||||
"rehype-katex": "^7.0.1",
|
||||
"remark-breaks": "^4.0.0",
|
||||
"remark-gfm": "^4.0.1",
|
||||
|
||||
Vendored
+4
-5
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user