mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-08 20:42:30 +08:00
feat: delete the added model #503 and display an error message when the requested file fails to parse #684 (#708)
### What problem does this PR solve? feat: delete the added model #503 feat: display an error message when the requested file fails to parse #684 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
281
web/src/pages/document-viewer/docx/index.less
Normal file
281
web/src/pages/document-viewer/docx/index.less
Normal file
@ -0,0 +1,281 @@
|
||||
// Copyright (c) 2017 PlanGrid, Inc.
|
||||
|
||||
.docxViewerWrapper {
|
||||
overflow-y: scroll;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
.box {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
:global(.document-container) {
|
||||
padding: 30px;
|
||||
width: 700px;
|
||||
background: white;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
html,
|
||||
bodyaddress,
|
||||
blockquote,
|
||||
body,
|
||||
dd,
|
||||
div,
|
||||
dl,
|
||||
dt,
|
||||
fieldset,
|
||||
form,
|
||||
frame,
|
||||
frameset,
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6,
|
||||
noframes,
|
||||
ol,
|
||||
p,
|
||||
ul,
|
||||
center,
|
||||
dir,
|
||||
hr,
|
||||
menu,
|
||||
pre {
|
||||
display: block;
|
||||
unicode-bidi: embed;
|
||||
}
|
||||
li {
|
||||
display: list-item;
|
||||
list-style-type: disc;
|
||||
}
|
||||
head {
|
||||
display: none;
|
||||
}
|
||||
table {
|
||||
display: table;
|
||||
}
|
||||
img {
|
||||
width: 100%;
|
||||
}
|
||||
tr {
|
||||
display: table-row;
|
||||
}
|
||||
thead {
|
||||
display: table-header-group;
|
||||
}
|
||||
tbody {
|
||||
display: table-row-group;
|
||||
}
|
||||
tfoot {
|
||||
display: table-footer-group;
|
||||
}
|
||||
col {
|
||||
display: table-column;
|
||||
}
|
||||
colgroup {
|
||||
display: table-column-group;
|
||||
}
|
||||
th {
|
||||
display: table-cell;
|
||||
}
|
||||
td {
|
||||
display: table-cell;
|
||||
border-bottom: 1px solid #ccc;
|
||||
border-right: 1px solid #ccc;
|
||||
padding: 0.2em 0.5em;
|
||||
}
|
||||
caption {
|
||||
display: table-caption;
|
||||
}
|
||||
th {
|
||||
font-weight: bolder;
|
||||
text-align: center;
|
||||
}
|
||||
caption {
|
||||
text-align: center;
|
||||
}
|
||||
body {
|
||||
margin: 8px;
|
||||
}
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
h2 {
|
||||
font-size: 1.5em;
|
||||
margin: 0.75em 0;
|
||||
}
|
||||
h3 {
|
||||
font-size: 1.17em;
|
||||
margin: 0.83em 0;
|
||||
}
|
||||
h4,
|
||||
p,
|
||||
blockquote,
|
||||
ul,
|
||||
fieldset,
|
||||
form,
|
||||
ol,
|
||||
dl,
|
||||
dir,
|
||||
menu {
|
||||
margin: 1.12em 0;
|
||||
}
|
||||
h5 {
|
||||
font-size: 0.83em;
|
||||
margin: 1.5em 0;
|
||||
}
|
||||
h6 {
|
||||
font-size: 0.75em;
|
||||
margin: 1.67em 0;
|
||||
}
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6,
|
||||
b,
|
||||
strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
blockquote {
|
||||
margin-left: 40px;
|
||||
margin-right: 40px;
|
||||
}
|
||||
i,
|
||||
cite,
|
||||
em,
|
||||
var,
|
||||
address {
|
||||
font-style: italic;
|
||||
}
|
||||
pre,
|
||||
tt,
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-family: monospace;
|
||||
}
|
||||
pre {
|
||||
white-space: pre;
|
||||
}
|
||||
button,
|
||||
textarea,
|
||||
input,
|
||||
select {
|
||||
display: inline-block;
|
||||
}
|
||||
big {
|
||||
font-size: 1.17em;
|
||||
}
|
||||
small,
|
||||
sub,
|
||||
sup {
|
||||
font-size: 0.83em;
|
||||
}
|
||||
sub {
|
||||
vertical-align: sub;
|
||||
}
|
||||
sup {
|
||||
vertical-align: super;
|
||||
}
|
||||
table {
|
||||
border-spacing: 2px;
|
||||
}
|
||||
thead,
|
||||
tbody,
|
||||
tfoot {
|
||||
vertical-align: middle;
|
||||
}
|
||||
td,
|
||||
th,
|
||||
tr {
|
||||
vertical-align: inherit;
|
||||
}
|
||||
s,
|
||||
strike,
|
||||
del {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
hr {
|
||||
border: 1px inset;
|
||||
}
|
||||
ol,
|
||||
ul,
|
||||
dir,
|
||||
menu,
|
||||
dd {
|
||||
margin-left: 40px;
|
||||
}
|
||||
ol {
|
||||
list-style-type: decimal;
|
||||
}
|
||||
ol ul,
|
||||
ol ul,
|
||||
ul ol,
|
||||
ul ol,
|
||||
ul ul,
|
||||
ul ul,
|
||||
ol ol,
|
||||
ol ol {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
u,
|
||||
ins {
|
||||
text-decoration: underline;
|
||||
}
|
||||
br:before {
|
||||
content: '\A';
|
||||
white-space: pre-line;
|
||||
}
|
||||
center {
|
||||
text-align: center;
|
||||
}
|
||||
:link,
|
||||
:visited {
|
||||
text-decoration: underline;
|
||||
}
|
||||
:focus {
|
||||
outline: thin dotted invert;
|
||||
}
|
||||
/* Begin bidirectionality settings (do not change) */
|
||||
BDO[DIR='ltr'] {
|
||||
direction: ltr;
|
||||
unicode-bidi: bidi-override;
|
||||
}
|
||||
BDO[DIR='rtl'] {
|
||||
direction: rtl;
|
||||
unicode-bidi: bidi-override;
|
||||
}
|
||||
*[DIR='ltr'] {
|
||||
direction: ltr;
|
||||
unicode-bidi: embed;
|
||||
}
|
||||
*[DIR='rtl'] {
|
||||
direction: rtl;
|
||||
unicode-bidi: embed;
|
||||
}
|
||||
@media print {
|
||||
h1 {
|
||||
page-break-before: always;
|
||||
}
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
page-break-after: avoid;
|
||||
}
|
||||
ul,
|
||||
ol,
|
||||
dl {
|
||||
page-break-before: avoid;
|
||||
}
|
||||
}
|
||||
}
|
||||
25
web/src/pages/document-viewer/docx/index.tsx
Normal file
25
web/src/pages/document-viewer/docx/index.tsx
Normal file
@ -0,0 +1,25 @@
|
||||
import { Spin } from 'antd';
|
||||
import FileError from '../file-error';
|
||||
|
||||
import { useFetchDocx } from '../hooks';
|
||||
import styles from './index.less';
|
||||
|
||||
const Docx = ({ filePath }: { filePath: string }) => {
|
||||
const { succeed, containerRef } = useFetchDocx(filePath);
|
||||
|
||||
return (
|
||||
<>
|
||||
{succeed ? (
|
||||
<section className={styles.docxViewerWrapper}>
|
||||
<div id="docx" ref={containerRef} className={styles.box}>
|
||||
<Spin />
|
||||
</div>
|
||||
</section>
|
||||
) : (
|
||||
<FileError></FileError>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Docx;
|
||||
@ -1,35 +1,19 @@
|
||||
import jsPreviewExcel from '@js-preview/excel';
|
||||
import '@js-preview/excel/lib/index.css';
|
||||
import { useEffect } from 'react';
|
||||
import FileError from '../file-error';
|
||||
import { useFetchExcel } from '../hooks';
|
||||
|
||||
const Excel = ({ filePath }: { filePath: string }) => {
|
||||
const fetchDocument = async () => {
|
||||
const myExcelPreviewer = jsPreviewExcel.init(
|
||||
document.getElementById('excel'),
|
||||
);
|
||||
const jsonFile = new XMLHttpRequest();
|
||||
jsonFile.open('GET', filePath, true);
|
||||
jsonFile.send();
|
||||
jsonFile.responseType = 'arraybuffer';
|
||||
jsonFile.onreadystatechange = () => {
|
||||
if (jsonFile.readyState === 4 && jsonFile.status === 200) {
|
||||
myExcelPreviewer
|
||||
.preview(jsonFile.response)
|
||||
.then((res: any) => {
|
||||
console.log('succeed');
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log('failed', e);
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
const { status, containerRef } = useFetchExcel(filePath);
|
||||
|
||||
useEffect(() => {
|
||||
fetchDocument();
|
||||
}, []);
|
||||
|
||||
return <div id="excel" style={{ height: '100%' }}></div>;
|
||||
return (
|
||||
<div
|
||||
id="excel"
|
||||
ref={containerRef}
|
||||
style={{ height: '100%', width: '100%' }}
|
||||
>
|
||||
{status || <FileError></FileError>}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Excel;
|
||||
|
||||
4
web/src/pages/document-viewer/file-error/index.less
Normal file
4
web/src/pages/document-viewer/file-error/index.less
Normal file
@ -0,0 +1,4 @@
|
||||
.errorWrapper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
15
web/src/pages/document-viewer/file-error/index.tsx
Normal file
15
web/src/pages/document-viewer/file-error/index.tsx
Normal file
@ -0,0 +1,15 @@
|
||||
import { Alert, Flex } from 'antd';
|
||||
|
||||
import { useTranslate } from '@/hooks/commonHooks';
|
||||
import styles from './index.less';
|
||||
|
||||
const FileError = () => {
|
||||
const { t } = useTranslate('fileManager');
|
||||
return (
|
||||
<Flex align="center" justify="center" className={styles.errorWrapper}>
|
||||
<Alert type="error" message={<h1>{t('fileError')}</h1>}></Alert>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
export default FileError;
|
||||
78
web/src/pages/document-viewer/hooks.ts
Normal file
78
web/src/pages/document-viewer/hooks.ts
Normal file
@ -0,0 +1,78 @@
|
||||
import jsPreviewExcel from '@js-preview/excel';
|
||||
import axios from 'axios';
|
||||
import mammoth from 'mammoth';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
|
||||
const useFetchDocument = () => {
|
||||
const fetchDocument = useCallback((api: string) => {
|
||||
return axios.get(api, { responseType: 'arraybuffer' });
|
||||
}, []);
|
||||
|
||||
return fetchDocument;
|
||||
};
|
||||
|
||||
export const useFetchExcel = (filePath: string) => {
|
||||
const [status, setStatus] = useState(true);
|
||||
const fetchDocument = useFetchDocument();
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const fetchDocumentAsync = useCallback(async () => {
|
||||
let myExcelPreviewer;
|
||||
if (containerRef.current) {
|
||||
myExcelPreviewer = jsPreviewExcel.init(containerRef.current);
|
||||
}
|
||||
const jsonFile = await fetchDocument(filePath);
|
||||
myExcelPreviewer
|
||||
?.preview(jsonFile.data)
|
||||
.then(() => {
|
||||
console.log('succeed');
|
||||
setStatus(true);
|
||||
})
|
||||
.catch((e) => {
|
||||
console.warn('failed', e);
|
||||
myExcelPreviewer.destroy();
|
||||
setStatus(false);
|
||||
});
|
||||
}, [filePath, fetchDocument]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchDocumentAsync();
|
||||
}, [fetchDocumentAsync]);
|
||||
|
||||
return { status, containerRef };
|
||||
};
|
||||
|
||||
export const useFetchDocx = (filePath: string) => {
|
||||
const [succeed, setSucceed] = useState(true);
|
||||
const fetchDocument = useFetchDocument();
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const fetchDocumentAsync = useCallback(async () => {
|
||||
const jsonFile = await fetchDocument(filePath);
|
||||
mammoth
|
||||
.convertToHtml(
|
||||
{ arrayBuffer: jsonFile.data },
|
||||
{ includeDefaultStyleMap: true },
|
||||
)
|
||||
.then((result) => {
|
||||
setSucceed(true);
|
||||
const docEl = document.createElement('div');
|
||||
docEl.className = 'document-container';
|
||||
docEl.innerHTML = result.value;
|
||||
const container = containerRef.current;
|
||||
if (container) {
|
||||
container.innerHTML = docEl.outerHTML;
|
||||
}
|
||||
})
|
||||
.catch((a) => {
|
||||
setSucceed(false);
|
||||
console.warn('alexei: something went wrong', a);
|
||||
});
|
||||
}, [filePath, fetchDocument]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchDocumentAsync();
|
||||
}, [fetchDocumentAsync]);
|
||||
|
||||
return { succeed, containerRef };
|
||||
};
|
||||
@ -1,8 +1,8 @@
|
||||
import { ExceptiveType, Images } from '@/constants/common';
|
||||
import { Images } from '@/constants/common';
|
||||
import { api_host } from '@/utils/api';
|
||||
import { Flex, Image } from 'antd';
|
||||
import FileViewer from 'react-file-viewer';
|
||||
import { useParams, useSearchParams } from 'umi';
|
||||
import Docx from './docx';
|
||||
import Excel from './excel';
|
||||
import Pdf from './pdf';
|
||||
|
||||
@ -10,18 +10,12 @@ import styles from './index.less';
|
||||
|
||||
// TODO: The interface returns an incorrect content-type for the SVG.
|
||||
|
||||
const isNotExceptiveType = (ext: string) => ExceptiveType.indexOf(ext) === -1;
|
||||
|
||||
const DocumentViewer = () => {
|
||||
const { id: documentId } = useParams();
|
||||
const api = `${api_host}/file/get/${documentId}`;
|
||||
const [currentQueryParameters] = useSearchParams();
|
||||
const ext = currentQueryParameters.get('ext');
|
||||
|
||||
const onError = (e: any) => {
|
||||
console.error(e, 'error in file-viewer');
|
||||
};
|
||||
|
||||
return (
|
||||
<section className={styles.viewerWrapper}>
|
||||
{Images.includes(ext!) && (
|
||||
@ -31,9 +25,8 @@ const DocumentViewer = () => {
|
||||
)}
|
||||
{ext === 'pdf' && <Pdf url={api}></Pdf>}
|
||||
{(ext === 'xlsx' || ext === 'xls') && <Excel filePath={api}></Excel>}
|
||||
{isNotExceptiveType(ext!) && (
|
||||
<FileViewer fileType={ext} filePath={api} onError={onError} />
|
||||
)}
|
||||
|
||||
{ext === 'docx' && <Docx filePath={api}></Docx>}
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { Skeleton } from 'antd';
|
||||
import { PdfHighlighter, PdfLoader } from 'react-pdf-highlighter';
|
||||
import FileError from '../file-error';
|
||||
|
||||
interface IProps {
|
||||
url: string;
|
||||
@ -9,11 +10,15 @@ const DocumentPreviewer = ({ url }: IProps) => {
|
||||
const resetHash = () => {};
|
||||
|
||||
return (
|
||||
<div style={{ width: '100%' }}>
|
||||
<div style={{ width: '100%', height: '100%' }}>
|
||||
<PdfLoader
|
||||
url={url}
|
||||
beforeLoad={<Skeleton active />}
|
||||
workerSrc="/pdfjs-dist/pdf.worker.min.js"
|
||||
errorMessage={<FileError></FileError>}
|
||||
onError={(e) => {
|
||||
console.warn(e);
|
||||
}}
|
||||
>
|
||||
{(pdfDocument) => {
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user