You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
537 lines
14 KiB
537 lines
14 KiB
<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>
|