xiaohuo 8 months ago
commit 5b1c29e8d4
  1. 1
      ALOps_sys_fe/alops-ui/package.json
  2. 435
      ALOps_sys_fe/alops-ui/src/views/QandA/knowledge/index.vue

@ -39,6 +39,7 @@
"js-cookie": "3.0.1",
"jsencrypt": "3.0.0-rc.1",
"lodash": "^4.17.21",
"mammoth": "^1.11.0",
"nprogress": "0.2.0",
"quill": "2.0.2",
"screenfull": "5.0.2",

@ -90,6 +90,7 @@ import Treeselect from "@riophae/vue-treeselect"
import "@riophae/vue-treeselect/dist/vue-treeselect.css"
import { Splitpanes, Pane } from "splitpanes"
import "splitpanes/dist/splitpanes.css"
import mammoth from 'mammoth'
export default {
name: "User",
@ -384,74 +385,402 @@ export default {
this.$refs.upload.submit()
},
// -
previewFile(row) {
async previewFile(row) {
// token
const token = this.$store.getters.token;
// URL使
const previewUrl = `${this.appBase}/QandA/knowledge/file/download/${row.id}`;
// XMLHttpRequest
const xhr = new XMLHttpRequest();
xhr.open('GET', previewUrl, true);
//
xhr.setRequestHeader('Authorization', `Bearer ${token}`);
//
if (row.format === 'txt') {
xhr.responseType = 'text'; //
} else if (['png', 'jpg', 'jpeg', 'gif', 'bmp'].includes(row.format.toLowerCase())) {
xhr.responseType = 'blob'; // Blob
} else if (row.format === 'pdf') {
xhr.responseType = 'blob'; // PDFBlob
} else {
//
xhr.responseType = 'text';
}
//
xhr.onload = function() {
if (xhr.status === 200) {
// XMLHttpRequestPromise
const getFileContent = () => {
return new Promise((resolve, reject) => {
// XMLHttpRequest
const xhr = new XMLHttpRequest();
xhr.open('GET', previewUrl, true);
//
xhr.setRequestHeader('Authorization', `Bearer ${token}`);
//
if (row.format === 'txt') {
//
this.previewTextFile(xhr.response, row.source);
xhr.responseType = 'text'; //
} else if (['png', 'jpg', 'jpeg', 'gif', 'bmp'].includes(row.format.toLowerCase())) {
//
this.previewImageFile(xhr.response, row.source);
xhr.responseType = 'blob'; // Blob
} else if (row.format === 'pdf') {
// PDF
this.previewPdfFile(xhr.response, row.source);
xhr.responseType = 'blob'; // PDFBlob
} else if (row.format === 'docx') {
// Word - 使线
const docxUrl = URL.createObjectURL(new Blob([xhr.response]));
const onlinePreviewUrl = `https://view.officeapps.live.com/op/view.aspx?src=${encodeURIComponent(docxUrl)}`;
window.open(onlinePreviewUrl, '_blank');
xhr.responseType = 'arraybuffer'; // WordArrayBuffer
} else {
//
try {
const textContent = xhr.response;
if (textContent && textContent.length > 0) {
this.previewTextFile(textContent, row.source);
} else {
this.$message.info('暂不支持此文件格式的预览');
}
} catch (e) {
this.$message.info('暂不支持此文件格式的预览');
//
xhr.responseType = 'text';
}
//
xhr.onload = function() {
if (xhr.status === 200) {
resolve(xhr.response);
} else {
reject(new Error('文件获取失败,状态码: ' + xhr.status));
}
};
//
xhr.onerror = function() {
reject(new Error('网络错误,文件获取失败'));
};
//
xhr.send();
});
};
try {
const response = await getFileContent();
if (row.format === 'txt') {
// - 使WordHTML
const blob = new Blob([response], { type: 'text/plain;charset=utf-8' });
const txtUrl = URL.createObjectURL(blob);
// 使Word
const previewWindow = window.open('', '_blank', 'width=1000,height=800');
previewWindow.document.write(`
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>文件预览 - ${row.source}</title>
<style>
body {
font-family: 'Microsoft YaHei', sans-serif;
margin: 0;
padding: 20px;
background-color: #f5f7fa;
}
.container {
max-width: 900px;
margin: 0 auto;
background-color: white;
padding: 30px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
h1 {
color: #333;
margin-bottom: 20px;
font-size: 24px;
}
.file-info {
background-color: #f9f9f9;
padding: 15px;
border-radius: 4px;
margin-bottom: 20px;
font-size: 14px;
}
.file-content {
line-height: 1.8;
color: #333;
margin-bottom: 30px;
padding: 20px;
background-color: #f9f9f9;
border-radius: 4px;
max-height: 600px;
overflow-y: auto;
font-family: 'Courier New', monospace;
white-space: pre-wrap;
}
.download-btn {
display: inline-block;
background-color: #409EFF;
color: white;
text-decoration: none;
padding: 10px 20px;
border-radius: 4px;
font-size: 16px;
transition: background-color 0.3s;
}
.download-btn:hover {
background-color: #66b1ff;
}
.note {
color: #999;
font-size: 14px;
margin-top: 20px;
}
</style>
</head>
<body>
<div class="container">
<h1>文件预览</h1>
<div class="file-info">
<p><strong>文件名</strong>${row.source}</p>
<p><strong>文件格式</strong>TXT (纯文本文件)</p>
</div>
<div class="file-content">
${response.replace(/</g, '&lt;').replace(/>/g, '&gt;')}
</div>
<a href="${txtUrl}" download="${row.source}" class="download-btn">下载原始文件</a>
</div>
</body>
</html>
`);
previewWindow.document.close();
// URL
previewWindow.addEventListener('beforeunload', () => {
URL.revokeObjectURL(txtUrl);
});
} else if (['png', 'jpg', 'jpeg', 'gif', 'bmp'].includes(row.format.toLowerCase())) {
//
this.previewImageFile(response, row.source);
} else if (row.format === 'pdf') {
// PDF
this.previewPdfFile(response, row.source);
} else if (row.format === 'docx') {
// Word - 使mammoth.jsWordHTML
//
if (!response || response.byteLength < 100) {
console.error('Word文档数据不完整');
this.$message.error('Word文档数据不完整,请尝试下载查看');
return;
}
try {
// 使mammoth.jsWordHTML
const result = await mammoth.convertToHtml({ arrayBuffer: response });
const htmlContent = result.value;
const blob = new Blob([response], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
const docxUrl = URL.createObjectURL(blob);
//
const previewWindow = window.open('', '_blank', 'width=1000,height=800');
previewWindow.document.write(`
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>文件预览 - ${row.source}</title>
<style>
body {
font-family: 'Microsoft YaHei', sans-serif;
margin: 0;
padding: 20px;
background-color: #f5f7fa;
}
.container {
max-width: 900px;
margin: 0 auto;
background-color: white;
padding: 30px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
h1 {
color: #333;
margin-bottom: 20px;
font-size: 24px;
}
.file-info {
background-color: #f9f9f9;
padding: 15px;
border-radius: 4px;
margin-bottom: 20px;
font-size: 14px;
}
.file-content {
line-height: 1.8;
color: #333;
margin-bottom: 30px;
padding: 20px;
background-color: #f9f9f9;
border-radius: 4px;
max-height: 600px;
overflow-y: auto;
}
.file-content h1 {
font-size: 28px;
margin-top: 0;
}
.file-content h2 {
font-size: 24px;
}
.file-content h3 {
font-size: 20px;
}
.file-content p {
margin: 15px 0;
}
.file-content ul, .file-content ol {
margin: 15px 0;
padding-left: 30px;
}
.file-content li {
margin: 5px 0;
}
.download-btn {
display: inline-block;
background-color: #409EFF;
color: white;
text-decoration: none;
padding: 10px 20px;
border-radius: 4px;
font-size: 16px;
transition: background-color 0.3s;
}
.download-btn:hover {
background-color: #66b1ff;
}
.error-message {
color: #f56c6c;
background-color: #fef0f0;
padding: 15px;
border-radius: 4px;
margin-bottom: 20px;
border: 1px solid #fbc4c4;
}
.note {
color: #999;
font-size: 14px;
margin-top: 20px;
}
</style>
</head>
<body>
<div class="container">
<h1>文件预览</h1>
<div class="file-info">
<p><strong>文件名</strong>${row.source}</p>
<p><strong>文件格式</strong>DOCX (Word文档)</p>
</div>
<div class="file-content">
${htmlContent}
</div>
<a href="${docxUrl}" download="${row.source}" class="download-btn">下载原始文件</a>
<p class="note">注意预览可能与原始文件格式略有差异完整格式请下载原始文件查看</p>
</div>
</body>
</html>
`);
previewWindow.document.close();
// URL
previewWindow.addEventListener('beforeunload', () => {
URL.revokeObjectURL(docxUrl);
});
} catch (err) {
console.error('Word文档转换失败:', err);
const blob = new Blob([response], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
const docxUrl = URL.createObjectURL(blob);
//
const errorWindow = window.open('', '_blank', 'width=800,height=600');
errorWindow.document.write(`
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>文件预览 - ${row.source}</title>
<style>
body {
font-family: 'Microsoft YaHei', sans-serif;
margin: 0;
padding: 20px;
background-color: #f5f7fa;
}
.container {
max-width: 600px;
margin: 0 auto;
background-color: white;
padding: 30px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
h1 {
color: #333;
margin-bottom: 20px;
font-size: 24px;
}
.file-info {
background-color: #f9f9f9;
padding: 15px;
border-radius: 4px;
margin-bottom: 20px;
font-size: 14px;
}
.error-message {
color: #f56c6c;
background-color: #fef0f0;
padding: 15px;
border-radius: 4px;
margin-bottom: 20px;
border: 1px solid #fbc4c4;
}
.download-btn {
display: inline-block;
background-color: #409EFF;
color: white;
text-decoration: none;
padding: 10px 20px;
border-radius: 4px;
font-size: 16px;
transition: background-color 0.3s;
}
.download-btn:hover {
background-color: #66b1ff;
}
</style>
</head>
<body>
<div class="container">
<h1>文件预览</h1>
<div class="file-info">
<p><strong>文件名</strong>${row.source}</p>
<p><strong>文件格式</strong>DOCX (Word文档)</p>
</div>
<div class="error-message">
<p>抱歉Word文档预览失败可能的原因</p>
<ul>
<li>文档文件损坏或不完整</li>
<li>文档格式不受支持</li>
<li>浏览器内存不足</li>
</ul>
</div>
<a href="${docxUrl}" download="${row.source}" class="download-btn">下载原始文件查看</a>
</div>
</body>
</html>
`);
errorWindow.document.close();
// URL
errorWindow.addEventListener('beforeunload', () => {
URL.revokeObjectURL(docxUrl);
});
}
} else {
this.$message.error('文件预览失败,请重试');
//
try {
const textContent = response;
if (textContent && textContent.length > 0) {
this.previewTextFile(textContent, row.source);
} else {
this.$message.info('暂不支持此文件格式的预览');
}
} catch (e) {
this.$message.info('暂不支持此文件格式的预览');
}
}
}.bind(this);
//
xhr.onerror = function() {
this.$message.error('网络错误,文件预览失败');
}.bind(this);
//
xhr.send();
} catch (error) {
console.error('文件预览失败:', error);
this.$message.error('文件预览失败: ' + error.message);
}
},
//

Loading…
Cancel
Save