|
|
|
@ -27,8 +27,10 @@ |
|
|
|
</el-table-column> |
|
|
|
</el-table-column> |
|
|
|
<el-table-column label="操作" align="center" width="240" class-name="small-padding fixed-width"> |
|
|
|
<el-table-column label="操作" align="center" width="240" class-name="small-padding fixed-width"> |
|
|
|
<template slot-scope="scope" v-if="scope.row.id !== 1"> |
|
|
|
<template slot-scope="scope" v-if="scope.row.id !== 1"> |
|
|
|
<el-button size="mini" type="text" icon="el-icon-view" @click="previewFile(scope.row)" v-hasPermi="['QandA:knowledge:preview']">预览</el-button> |
|
|
|
<el-button size="mini" type="text" icon="el-icon-view" @click="previewFile(scope.row)" v-hasPermi="['QandA:knowledge:filepreview']">预览</el-button> |
|
|
|
<el-button size="mini" type="text" icon="el-icon-download" @click="downloadFile(scope.row)" v-hasPermi="['QandA:knowledge:filedownload']">下载</el-button> |
|
|
|
<a href="javascript:void(0)" class="el-button el-button--text el-button--mini" @click="downloadFile(scope.row)" v-hasPermi="['QandA:knowledge:filedownload']"> |
|
|
|
|
|
|
|
<i class="el-icon el-icon-download"></i> 下载 |
|
|
|
|
|
|
|
</a> |
|
|
|
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['QandA:knowledge:update']">修改</el-button> |
|
|
|
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['QandA:knowledge:update']">修改</el-button> |
|
|
|
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['QandA:knowledge:del']">删除</el-button> |
|
|
|
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['QandA:knowledge:del']">删除</el-button> |
|
|
|
</template> |
|
|
|
</template> |
|
|
|
@ -82,7 +84,7 @@ |
|
|
|
</template> |
|
|
|
</template> |
|
|
|
|
|
|
|
|
|
|
|
<script> |
|
|
|
<script> |
|
|
|
import { list, del, add, update, permanentKnowledgeList, uploadedFilesList, downloadFile } from "@/api/QandA/knowledge" |
|
|
|
import { list, del, add, update, permanentKnowledgeList, uploadedFilesList } from "@/api/QandA/knowledge" |
|
|
|
import { getToken } from "@/utils/auth" |
|
|
|
import { getToken } from "@/utils/auth" |
|
|
|
import Treeselect from "@riophae/vue-treeselect" |
|
|
|
import Treeselect from "@riophae/vue-treeselect" |
|
|
|
import "@riophae/vue-treeselect/dist/vue-treeselect.css" |
|
|
|
import "@riophae/vue-treeselect/dist/vue-treeselect.css" |
|
|
|
@ -381,40 +383,195 @@ export default { |
|
|
|
submitFileForm() { |
|
|
|
submitFileForm() { |
|
|
|
this.$refs.upload.submit() |
|
|
|
this.$refs.upload.submit() |
|
|
|
}, |
|
|
|
}, |
|
|
|
// 预览文件 |
|
|
|
// 预览文件 - 基于二进制数据的预览 |
|
|
|
previewFile(row) { |
|
|
|
previewFile(row) { |
|
|
|
// 构建完整的文件路径 |
|
|
|
// 获取token |
|
|
|
const filePath = this.appBase + row.filePath; |
|
|
|
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'; // PDF文件获取Blob对象 |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
// 其他格式,先尝试获取文本,不行再提示 |
|
|
|
|
|
|
|
xhr.responseType = 'text'; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 请求完成处理函数 |
|
|
|
|
|
|
|
xhr.onload = function() { |
|
|
|
|
|
|
|
if (xhr.status === 200) { |
|
|
|
if (row.format === 'txt') { |
|
|
|
if (row.format === 'txt') { |
|
|
|
// 对于txt文件,可以通过新窗口打开直接预览 |
|
|
|
// 文本文件预览 |
|
|
|
window.open(filePath, '_blank'); |
|
|
|
this.previewTextFile(xhr.response, row.source); |
|
|
|
|
|
|
|
} else if (['png', 'jpg', 'jpeg', 'gif', 'bmp'].includes(row.format.toLowerCase())) { |
|
|
|
|
|
|
|
// 图片文件预览 |
|
|
|
|
|
|
|
this.previewImageFile(xhr.response, row.source); |
|
|
|
|
|
|
|
} else if (row.format === 'pdf') { |
|
|
|
|
|
|
|
// PDF文件预览 |
|
|
|
|
|
|
|
this.previewPdfFile(xhr.response, row.source); |
|
|
|
} else if (row.format === 'docx') { |
|
|
|
} else if (row.format === 'docx') { |
|
|
|
// 对于docx文件,可以使用在线预览服务或通过新窗口打开 |
|
|
|
// Word文件预览 - 使用在线预览服务 |
|
|
|
// 这里使用新窗口打开的方式 |
|
|
|
const docxUrl = URL.createObjectURL(new Blob([xhr.response])); |
|
|
|
window.open(filePath, '_blank'); |
|
|
|
const onlinePreviewUrl = `https://view.officeapps.live.com/op/view.aspx?src=${encodeURIComponent(docxUrl)}`; |
|
|
|
// 也可以使用在线预览服务,例如: |
|
|
|
window.open(onlinePreviewUrl, '_blank'); |
|
|
|
// const previewUrl = `https://view.officeapps.live.com/op/view.aspx?src=${encodeURIComponent(filePath)}`; |
|
|
|
} else { |
|
|
|
// window.open(previewUrl, '_blank'); |
|
|
|
// 尝试文本预览 |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
const textContent = xhr.response; |
|
|
|
|
|
|
|
if (textContent && textContent.length > 0) { |
|
|
|
|
|
|
|
this.previewTextFile(textContent, row.source); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
// 其他文件格式的处理 |
|
|
|
|
|
|
|
this.$message.info('暂不支持此文件格式的预览'); |
|
|
|
this.$message.info('暂不支持此文件格式的预览'); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} catch (e) { |
|
|
|
|
|
|
|
this.$message.info('暂不支持此文件格式的预览'); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
this.$message.error('文件预览失败,请重试'); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}.bind(this); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 网络错误处理 |
|
|
|
|
|
|
|
xhr.onerror = function() { |
|
|
|
|
|
|
|
this.$message.error('网络错误,文件预览失败'); |
|
|
|
|
|
|
|
}.bind(this); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 发送请求 |
|
|
|
|
|
|
|
xhr.send(); |
|
|
|
}, |
|
|
|
}, |
|
|
|
// 下载文件 |
|
|
|
|
|
|
|
|
|
|
|
// 预览文本文件 |
|
|
|
|
|
|
|
previewTextFile(content, fileName) { |
|
|
|
|
|
|
|
// 创建预览窗口 |
|
|
|
|
|
|
|
const previewWindow = window.open('', '_blank', 'width=800,height=600'); |
|
|
|
|
|
|
|
previewWindow.document.write(` |
|
|
|
|
|
|
|
<html> |
|
|
|
|
|
|
|
<head> |
|
|
|
|
|
|
|
<title>${fileName} - 预览</title> |
|
|
|
|
|
|
|
<style> |
|
|
|
|
|
|
|
body { font-family: Arial, sans-serif; padding: 20px; margin: 0; background-color: #f5f5f5; } |
|
|
|
|
|
|
|
.container { max-width: 100%; margin: 0 auto; background: white; padding: 20px; border-radius: 5px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); } |
|
|
|
|
|
|
|
pre { white-space: pre-wrap; word-wrap: break-word; font-family: 'Courier New', monospace; font-size: 14px; line-height: 1.5; } |
|
|
|
|
|
|
|
h1 { margin-top: 0; color: #333; font-size: 20px; } |
|
|
|
|
|
|
|
</style> |
|
|
|
|
|
|
|
</head> |
|
|
|
|
|
|
|
<body> |
|
|
|
|
|
|
|
<div class="container"> |
|
|
|
|
|
|
|
<h1>${fileName}</h1> |
|
|
|
|
|
|
|
<pre>${content}</pre> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
</body> |
|
|
|
|
|
|
|
</html> |
|
|
|
|
|
|
|
`); |
|
|
|
|
|
|
|
previewWindow.document.close(); |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 预览图片文件 |
|
|
|
|
|
|
|
previewImageFile(blob, fileName) { |
|
|
|
|
|
|
|
// 创建图片URL |
|
|
|
|
|
|
|
const imageUrl = URL.createObjectURL(blob); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 创建预览窗口 |
|
|
|
|
|
|
|
const previewWindow = window.open('', '_blank', 'width=800,height=600'); |
|
|
|
|
|
|
|
previewWindow.document.write(` |
|
|
|
|
|
|
|
<html> |
|
|
|
|
|
|
|
<head> |
|
|
|
|
|
|
|
<title>${fileName} - 预览</title> |
|
|
|
|
|
|
|
<style> |
|
|
|
|
|
|
|
body { margin: 0; padding: 20px; background-color: #f5f5f5; display: flex; justify-content: center; align-items: center; min-height: 100vh; } |
|
|
|
|
|
|
|
.container { max-width: 100%; max-height: 100%; text-align: center; } |
|
|
|
|
|
|
|
img { max-width: 100%; max-height: 80vh; border-radius: 5px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); } |
|
|
|
|
|
|
|
h1 { color: #333; font-size: 20px; margin-bottom: 20px; } |
|
|
|
|
|
|
|
</style> |
|
|
|
|
|
|
|
</head> |
|
|
|
|
|
|
|
<body> |
|
|
|
|
|
|
|
<div class="container"> |
|
|
|
|
|
|
|
<h1>${fileName}</h1> |
|
|
|
|
|
|
|
<img src="${imageUrl}" alt="${fileName}"> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
</body> |
|
|
|
|
|
|
|
</html> |
|
|
|
|
|
|
|
`); |
|
|
|
|
|
|
|
previewWindow.document.close(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 清理URL对象 |
|
|
|
|
|
|
|
previewWindow.onunload = function() { |
|
|
|
|
|
|
|
URL.revokeObjectURL(imageUrl); |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 预览PDF文件 |
|
|
|
|
|
|
|
previewPdfFile(blob, fileName) { |
|
|
|
|
|
|
|
// 创建PDF URL |
|
|
|
|
|
|
|
const pdfUrl = URL.createObjectURL(blob); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 创建预览窗口 |
|
|
|
|
|
|
|
const previewWindow = window.open('', '_blank', 'width=800,height=600'); |
|
|
|
|
|
|
|
previewWindow.document.write(` |
|
|
|
|
|
|
|
<html> |
|
|
|
|
|
|
|
<head> |
|
|
|
|
|
|
|
<title>${fileName} - 预览</title> |
|
|
|
|
|
|
|
<style> |
|
|
|
|
|
|
|
body { margin: 0; padding: 0; height: 100vh; overflow: hidden; } |
|
|
|
|
|
|
|
iframe { width: 100%; height: 100%; border: none; } |
|
|
|
|
|
|
|
</style> |
|
|
|
|
|
|
|
</head> |
|
|
|
|
|
|
|
<body> |
|
|
|
|
|
|
|
<iframe src="${pdfUrl}"></iframe> |
|
|
|
|
|
|
|
</body> |
|
|
|
|
|
|
|
</html> |
|
|
|
|
|
|
|
`); |
|
|
|
|
|
|
|
previewWindow.document.close(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 清理URL对象 |
|
|
|
|
|
|
|
previewWindow.onunload = function() { |
|
|
|
|
|
|
|
URL.revokeObjectURL(pdfUrl); |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
// 下载文件 - 使用XMLHttpRequest处理二进制响应 |
|
|
|
downloadFile(row) { |
|
|
|
downloadFile(row) { |
|
|
|
// 使用导入的API函数进行文件下载 |
|
|
|
// 获取token |
|
|
|
downloadFile(row.id).then(response => { |
|
|
|
const token = this.$store.getters.token; |
|
|
|
// 获取文件名,如果响应头中没有则使用row.source |
|
|
|
|
|
|
|
|
|
|
|
// 构建下载URL |
|
|
|
|
|
|
|
const downloadUrl = `${this.appBase}/QandA/knowledge/file/download/${row.id}`; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 创建XMLHttpRequest对象 |
|
|
|
|
|
|
|
const xhr = new XMLHttpRequest(); |
|
|
|
|
|
|
|
xhr.open('GET', downloadUrl, true); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 设置请求头 |
|
|
|
|
|
|
|
xhr.setRequestHeader('Authorization', `Bearer ${token}`); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 设置响应类型为blob |
|
|
|
|
|
|
|
xhr.responseType = 'blob'; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 请求完成处理函数 |
|
|
|
|
|
|
|
xhr.onload = function() { |
|
|
|
|
|
|
|
if (xhr.status === 200) { |
|
|
|
|
|
|
|
// 获取响应头中的文件名 |
|
|
|
let fileName = row.source; |
|
|
|
let fileName = row.source; |
|
|
|
const contentDisposition = response.headers['content-disposition']; |
|
|
|
const contentDisposition = xhr.getResponseHeader('content-disposition'); |
|
|
|
if (contentDisposition && contentDisposition.indexOf('filename=') !== -1) { |
|
|
|
if (contentDisposition && contentDisposition.indexOf('filename=') !== -1) { |
|
|
|
fileName = decodeURIComponent(contentDisposition.split('filename=')[1]); |
|
|
|
fileName = decodeURIComponent(contentDisposition.split('filename=')[1]); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 创建Blob对象 |
|
|
|
// 创建Blob对象 |
|
|
|
const blob = new Blob([response.data]); |
|
|
|
const blob = new Blob([xhr.response]); |
|
|
|
|
|
|
|
|
|
|
|
// 创建下载链接 |
|
|
|
// 创建下载链接 |
|
|
|
const link = document.createElement('a'); |
|
|
|
const link = document.createElement('a'); |
|
|
|
@ -428,14 +585,26 @@ export default { |
|
|
|
|
|
|
|
|
|
|
|
// 清理 |
|
|
|
// 清理 |
|
|
|
document.body.removeChild(link); |
|
|
|
document.body.removeChild(link); |
|
|
|
URL.revokeObjectURL(link.href); // 释放URL对象 |
|
|
|
URL.revokeObjectURL(link.href); |
|
|
|
|
|
|
|
|
|
|
|
// 显示下载成功提示 |
|
|
|
// 显示下载成功提示 |
|
|
|
this.$message.success('文件下载成功'); |
|
|
|
this.$message.success('文件下载成功'); |
|
|
|
}).catch(error => { |
|
|
|
} else { |
|
|
|
console.error('文件下载失败:', error); |
|
|
|
// 显示下载失败提示 |
|
|
|
this.$message.error('文件下载失败,请重试'); |
|
|
|
this.$message.error('文件下载失败,请重试'); |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
}.bind(this); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 网络错误处理 |
|
|
|
|
|
|
|
xhr.onerror = function() { |
|
|
|
|
|
|
|
this.$message.error('网络错误,文件下载失败'); |
|
|
|
|
|
|
|
}.bind(this); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 发送请求 |
|
|
|
|
|
|
|
xhr.send(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 显示下载开始提示 |
|
|
|
|
|
|
|
this.$message.success('正在下载文件...'); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|