|
|
<template> <div class="erf-attachment-manager"> <!-- 操作按钮 --> <div style="margin-bottom: 10px"> <el-button type="primary" size="small" v-if="!disabled" @click="handleUpload"> 上传附件 </el-button> <el-button type="primary" size="small" @click="handleDownload"> 下载 </el-button> </div>
<!-- 附件列表表格 --> <el-table :height="height" :data="dataList" ref="table" v-loading="queryLoading" border @selection-change="handleSelectionChange" style="width: 100%;">
<el-table-column type="selection" width="55" align="center"/>
<el-table-column prop="fileName" label="文件名" min-width="200" align="left" header-align="center" show-overflow-tooltip> </el-table-column>
<el-table-column prop="fileType" label="文件类型" min-width="100" align="center" header-align="center"> </el-table-column>
<el-table-column prop="createdBy" label="上传人" min-width="100" align="center" header-align="center"> </el-table-column>
<el-table-column prop="createDate" label="上传时间" min-width="160" align="center" header-align="center"> </el-table-column>
<el-table-column prop="orderRef5" label="备注" min-width="160" align="center" header-align="center"> </el-table-column>
<el-table-column label="操作" width="150" align="center" header-align="center" fixed="right"> <template slot-scope="{row}"> <el-link style="cursor:pointer; margin-right: 10px;" @click="previewFile(row)"> 预览 </el-link> <el-link style="cursor:pointer; color: #F56C6C;" v-if="!disabled" @click="handleRemove(row)"> 删除 </el-link> </template> </el-table-column> </el-table>
<!-- 上传对话框 --> <el-dialog title="上传附件" :visible.sync="ossVisible" width="380px" append-to-body :close-on-click-modal="false">
<el-form :inline="true" label-position="top" label-width="80px"> <el-row> <el-form-item label="申请单号"> <el-input v-model="ossForm.orderRef2" readonly style="width: 310px"></el-input> </el-form-item> </el-row> </el-form>
<!-- 文件上传区域 --> <div style="margin: 15px 0;"> <div style="margin-bottom: 10px;"> 选择文件: <span style="color: #67C23A; font-size: 12px; margin-left: 10px;"> <i class="el-icon-picture-outline"></i> 可支持直接 Ctrl+V 粘贴图片,不需要点击上传按钮 </span> </div> <el-upload drag action="#" ref="upload" :file-list="fileList" :on-remove="onRemoveFile" :on-change="onChangeFile" multiple :auto-upload="false" style="text-align: left;"> <i class="el-icon-upload"></i> <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em>,或<em style="color: #67C23A;">Ctrl+V 粘贴图片</em></div> <div class="el-upload__tip" slot="tip"> 支持pdf、dwg、dxf、doc、docx、xls、xlsx、jpg、png格式 </div> </el-upload> </div>
<!-- 备注区域 --> <div style="margin: 15px 0;"> <div style="margin-bottom: 10px;">备注:</div> <el-input type="textarea" v-model="ossForm.remark" resize="none" :autosize="{minRows: 2, maxRows: 2}"> </el-input> </div>
<span slot="footer" class="dialog-footer"> <el-button type="primary" :loading="uploadLoading" @click="handleUploadFiles">保存</el-button> <el-button @click="ossVisible = false">关闭</el-button> </span> </el-dialog> </div></template>
<script>import { ossUpload, queryOss, removeOss, previewOssFileById, previewOssFileById2 } from '@/api/oss/oss'
export default { name: 'ErfAttachmentManager',
props: { // 申请单号
applyNo: { type: String, required: true }, // 是否禁用编辑
disabled: { type: Boolean, default: false }, // 表格高度
height: { type: [String, Number], default: '30vh' } },
data() { return { dataList: [], queryLoading: false, uploadLoading: false, selectionDataList: [], ossVisible: false, ossForm: { orderRef1: 'ERF', // 模块标识
orderRef2: '', // 申请单号
orderRef6: 'EXP_APPLY', // 业务类型标识
remark: '' }, fileList: [], pasteImageCounter: 0 // 粘贴图片计数器,用于生成文件名
} },
mounted() { this.handleQuery() },
watch: { applyNo(newVal) { if (newVal) { this.handleQuery() } }, // 监听对话框关闭,移除粘贴事件监听器
ossVisible(newVal) { if (!newVal) { document.removeEventListener('paste', this.handlePaste) } } },
beforeDestroy() { // 组件销毁时移除监听器
document.removeEventListener('paste', this.handlePaste) },
methods: { /** * 查询附件列表 */ handleQuery() { if (!this.applyNo) { return }
let params = { orderRef1: 'ERF', orderRef2: this.applyNo, orderRef6: 'EXP_APPLY' }
this.queryLoading = true queryOss(params).then(({data}) => { this.queryLoading = false if (data && data.code === 0) { this.dataList = data.rows || [] } else { this.dataList = [] this.$message.warning(data.msg || '查询失败') } }).catch(error => { this.queryLoading = false this.$message.error('查询异常') }) },
/** * 打开上传对话框 */ handleUpload() { this.$nextTick(() => { if (this.$refs.upload) { this.$refs.upload.clearFiles() } }) this.fileList = [] this.ossForm.orderRef2 = this.applyNo this.ossForm.remark = '' this.ossVisible = true this.pasteImageCounter = 0
// 添加粘贴事件监听器
this.$nextTick(() => { document.addEventListener('paste', this.handlePaste) }) },
/** * 文件选择变化 */ onRemoveFile(file, fileList) { this.fileList = fileList },
onChangeFile(file, fileList) { this.fileList = fileList },
/** * 处理粘贴事件(支持直接粘贴图片) */ handlePaste(event) { // 只在对话框打开时处理粘贴
if (!this.ossVisible) { return }
const items = (event.clipboardData || event.originalEvent.clipboardData).items
for (let i = 0; i < items.length; i++) { const item = items[i]
// 检查是否为图片类型
if (item.type.indexOf('image') !== -1) { event.preventDefault() // 阻止默认粘贴行为
const blob = item.getAsFile() if (!blob) continue
// 获取文件扩展名
const extension = blob.type.split('/')[1] || 'png'
// 尝试使用原始文件名,如果没有则使用简洁的默认名称
let fileName = blob.name if (!fileName || fileName === 'image.png' || fileName === 'blob') { // 截图或无名称的情况,使用简洁的默认名称
this.pasteImageCounter++ fileName = `粘贴图片${this.pasteImageCounter}.${extension}` }
// 创建 File 对象(保留原始文件名)
const file = new File([blob], fileName, { type: blob.type })
// 创建一个符合 el-upload 格式的文件对象
const uploadFile = { name: fileName, size: file.size, type: file.type, raw: file, uid: Date.now() + this.pasteImageCounter, status: 'ready' }
// 添加到文件列表
this.fileList.push(uploadFile)
// 手动触发 el-upload 的文件列表更新
if (this.$refs.upload) { this.$refs.upload.uploadFiles.push(uploadFile) }
this.$message.success(`已粘贴图片: ${fileName}`)
break // 只处理第一张图片
} } },
/** * 执行上传 */ handleUploadFiles() { if (this.fileList.length === 0) { this.$message.error('请选择文件') return }
let formData = new FormData() for (let i = 0; i < this.fileList.length; i++) { formData.append('file', this.fileList[i].raw) } formData.append('orderRef1', 'ERF') formData.append('orderRef2', this.ossForm.orderRef2) formData.append('orderRef6', 'EXP_APPLY') formData.append('createdBy', this.$store.state.user.name) formData.append('orderRef5', this.ossForm.remark)
this.uploadLoading = true ossUpload(formData).then(({data}) => { this.uploadLoading = false if (data && data.code === 0) { this.$message.success('上传成功') this.handleQuery() this.ossVisible = false } else { this.$message.warning(data.msg || '上传失败') } }).catch(error => { this.uploadLoading = false this.$message.error('上传异常') }) },
/** * 删除附件 */ handleRemove(row) { this.$confirm('确认删除该附件吗?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => { let ids = [row.id] removeOss(ids).then(({data}) => { if (data && data.code === 0) { this.$message.success('删除成功') this.handleQuery() } else { this.$message.warning(data.msg || '删除失败') } }).catch(error => { this.$message.error('删除异常') }) }).catch(() => {}) },
/** * 预览文件 */ previewFile(row) { let type = '' let fileType = row.fileType.toLowerCase()
// 图片类型
let image = ['jpg', 'jpeg', 'png', 'gif', 'bmp'] if (image.includes(fileType)) { type = 'image/' + fileType }
// 视频类型
let video = ['mp4', 'avi', 'mov', 'wmv', 'flv'] if (video.includes(fileType)) { type = 'video/' + fileType }
// 文本类型
if (fileType === 'txt') { type = 'text/plain;charset=utf-8' }
// Excel类型
if (fileType === 'xlsx' || fileType === 'xls') { type = 'excel' }
// Word类型
if (fileType === 'docx') { type = 'word' }
// PDF类型
if (fileType === 'pdf') { type = 'application/pdf;charset-UTF-8' }
// Office文件不支持预览
if (fileType === 'doc' || fileType === 'ppt' || fileType === 'pptx') { this.$message.warning('该文件格式暂不支持预览,请下载后查看') return }
// CAD文件不支持预览
if (fileType === 'dwg' || fileType === 'dxf') { this.$message.warning('CAD文件暂不支持预览,请下载后使用CAD软件查看') return }
if (type === '') { this.$message.warning('该文件格式暂不支持预览') return }
let params = { id: row.id, fileType: type }
previewOssFileById2(params).then(({data}) => { if (type === 'excel' || type === 'word') { type = 'application/pdf;charset=UTF-8' } const blob = new Blob([data], { type: type }) const fileURL = URL.createObjectURL(blob)
if (type === 'xls' || type === 'docx' || type === 'xlsx') { const { href } = this.$router.resolve({ name: 'pre', query: { src: fileURL, type: 'pdf' } }) window.open(href, '_blank') } else { // 在新标签页中打开文件预览
window.open(fileURL, '_blank') } }) },
/** * 选择变化 */ handleSelectionChange(val) { this.selectionDataList = val },
/** * 下载选中的附件 */ handleDownload() { if (this.selectionDataList.length === 0) { this.$message.warning('请选择要下载的附件') return }
let selectList = this.selectionDataList.map(item => ({ ...item })) for (let i = 0; i < selectList.length; i++) { let params = { id: selectList[i].id } previewOssFileById(params).then((response) => { const blob = new Blob([response.data], { type: response.headers['content-type'] }) const link = document.createElement('a') link.href = URL.createObjectURL(blob) link.setAttribute('download', selectList[i].fileName) link.target = '_blank' link.click() URL.revokeObjectURL(link.href) }) }
this.$refs.table.clearSelection() } }}</script>
<style scoped>.erf-attachment-manager {
}/* 表格样式优化 */.el-table >>> .el-table__header th { background-color: #F5F7FA; color: #606266; font-weight: bold;}
.el-table >>> .el-table__row td { padding: 8px 0;}</style>
|