Files
mosr-web/src/components/AttachmentUpload.vue
dj 7fcfc992fb refactor(project-management): 统一经费预算单位
- 在多个组件中将"预估经费预算"和"实际经费预算"的标签添加单位"(元)"
-调整部分组件的标签宽度以适应新的单位
- 此修改统一了经费预算的显示格式,提高了用户体验
2025-04-24 15:30:14 +08:00

555 lines
16 KiB
Vue

<template>
<el-form :model="formData" ref="applyForm" :rules="rules" :label-position="labelPosition" :style="{marginLeft: label==='项目验收附件'?'25px': label==='项目立项附件'?'25px':'5px'}">
<el-row>
<!-- <el-col :span="24">-->
<!-- <el-form-item :label="label" prop="attachment" >-->
<!-- <template v-if="preview">-->
<!-- <file-upload @getFile="getAttachment" :multiple="false"-->
<!-- :disabled="singleFileArray?.length>0?true:false" title="如需修改需求申请书附件,请先删除文件再上传!"/>-->
<!-- <fvTable style="width: 100%;max-height: 80px;" height="80" v-if="singleFileArray?.length>0"-->
<!-- :tableConfig="editSingleTableConfig"-->
<!-- :data="singleFileArray" :isSettingCol="false" :pagination="false">-->
<!-- </fvTable>-->
<!-- </template>-->
<!-- <template v-else-if="!preview">-->
<!-- <file-upload @getFile="getAttachment" :multiple="false"-->
<!-- :disabled="isSingleFile"/>-->
<!-- <fvTable style="width: 100%;max-height: 80px;" v-if="showSingleTable" height="80"-->
<!-- :tableConfig="singleTableConfig"-->
<!-- :data="_singleFileValue" :isSettingCol="false" :pagination="false">-->
<!-- </fvTable>-->
<!-- </template>-->
<!-- </el-form-item>-->
<!-- </el-col>-->
<el-col :span="24">
<el-form-item :label="label" prop="" required>
<file-upload @getFile="getOtherFile"/>
<el-button color="#DED0B2" v-if="templateDownloadBtnShow" @click="handleImportTemplateDownload"
style="margin-left: 10px">模板下载
</el-button>
<fvTable style="width: 100%;" :height="label=='项目立项附件'?'160':'160'" :scrollbar-always-on="true" :style="{maxHeight:label=='项目立项附件'?'160px':'160px',height:label=='项目立项附件'?'160px':'160px'}" v-if="showTable" :tableConfig="tableConfig"
:data="allFileList" :isSettingCol="false" :pagination="false">
<template #empty>
<el-empty :image-size="55" description="暂无数据" style="padding: 0"/>
</template>
</fvTable>
</el-form-item>
</el-col>
</el-row>
</el-form>
<file-preview ref="filePreviewRef" v-if="filePreviewShow" :fileName="filePreviewParam.fileName"
:fileUrl="filePreviewParam.fileUrl"
:fileType="filePreviewParam.fileType"/>
</template>
<script setup lang="jsx">
import FileUpload from '@/components/FileUpload.vue'
import {deleteFile, downloadFile, downloadTemplate, downloadTemplateZip} from "@/api/project-demand";
import {ElMessageBox, ElNotification} from "element-plus";
const props = defineProps({
showFileList: {
type: Boolean,
default: false
},
label: {
type: String,
default: '项目附件'
},
showTable: {
type: Boolean,
default: false
},
showSingleTable: {
type: Boolean,
default: false
},
preview: {
type: Boolean,
default: false
},
//是否显示模板下载按钮
templateDownloadBtnShow: {
type: Boolean,
default: false
},
//模板下载时的文件名
templateName: {
type: String,
default: ''
},
singleList: {
type: Array,
default: []
},
otherFileList: {
type: Array,
default: []
},
formData: {
type: Object,
default: {}
},
labelPosition: {
type: String,
default: ''
},
tag: {
type: String,
default: ''
}
})
const emit = defineEmits(["getAttachment", "getOtherFile", "update:singleList"])
const baseTableConf = reactive(
[
{
prop: 'index',
type: 'index',
label: '序号',
align: 'center',
width: '80',
},
{
prop: 'originalFileName',
label: '文件名',
align: 'center',
width: 400,
currentRender: ({row, index}) => (
<div style="color: #2a99ff;cursor: pointer;"
onClick={() => clickToPreview(row)}>{row.originalFileName}</div>)
},
{
prop: 'tag',
label: '标签',
align: 'center',
// currentRender: ({row, index}) => (
// <el-input placeholder={row.tag} onClick={() => {}}></el-input>)
},
{
prop: 'size',
label: '文件大小',
align: 'center',
currentRender: ({row, index}) => (parseInt(row.size / 1024) + 'KB')
},
]
)
const tableConfig = reactive({
columns: [
...baseTableConf,
{
prop: 'oper',
label: '操作',
align: 'center',
showOverflowTooltip: false,
currentRender: ({row, index}) => {
let btn = []
btn.push({label: '下载', func: () => handleDownload(row), type: 'primary'})
// if (row.newFile) {
// btn.push({label: '删除', func: () => handleDelete(row), type: 'primary'})
// }
return (
<div style={{width: '100%'}}>
{
btn.map(item => (
<el-button
type={item.type}
onClick={() => item.func()}
link
>
{item.label}
</el-button>
))
}
{
row.newFile || props.preview || !props.preview ?
<popover-delete name={row.originalFileName} type={'文件'} btnType={'danger'}
// perm={['']}
onDelete={() => handleDelete(row)}/>
: ''
}
</div>
)
}
}
]
})
const singleTableConfig = reactive({
columns: [
...baseTableConf,
{
prop: 'oper',
label: '操作',
align: 'center',
showOverflowTooltip: false,
currentRender: ({row, index}) => {
let btn = []
btn.push({label: '下载', func: () => handleDownload(row), type: 'primary'})
// if (row.newFile) {
// btn.push({label: '删除', func: () => handleDelete(row), type: 'primary'})
// }
return (
<div style={{width: '100%'}}>
{
btn.map(item => (
<el-button
type={item.type}
onClick={() => item.func()}
link
>
{item.label}
</el-button>
))
}
{
row.newFile || props.preview || !props.preview ?
<popover-delete name={row.originalFileName} type={'文件'} btnType={'danger'}
// perm={['']}
onDelete={() => handleSingleDelete(row)}/>
: ''
}
</div>
)
}
}
]
})
const editSingleTableConfig = reactive({
columns: [
...baseTableConf,
{
prop: 'oper',
label: '操作',
align: 'center',
showOverflowTooltip: false,
currentRender: ({row, index}) => {
let btn = []
btn.push({label: '下载', func: () => handleDownload(row), type: 'primary'})
// if (row.newFile) {
// btn.push({label: '删除', func: () => handleDelete(row), type: 'primary'})
// }
return (
<div style={{width: '100%'}}>
{
btn.map(item => (
<el-button
type={item.type}
onClick={() => item.func()}
link
>
{item.label}
</el-button>
))
}
{
row.newFile || props.preview || !props.preview ?
<popover-delete name={row.originalFileName} type={'文件'} btnType={'danger'}
// perm={['']}
onDelete={() => deleteSingleFile(row, 1)}/>
: ''
}
</div>
)
}
}
]
})
const singleFileArray = ref([])
const rules = reactive({
// attachment: [{required: true, message: '请上传附件', trigger: ['blur', 'change']}],
})
const applyForm = ref()
const singleFile = ref({})
const isSingleFile = ref(false)
const isHaveOneFile = ref(false)
const allFileList = ref([])
if (localStorage.getItem('singleFile')) {
singleFileArray.value.push(JSON.parse(localStorage.getItem('singleFile')))
singleFile.value = JSON.parse(localStorage.getItem('singleFile'))
}
const filePreviewParam = ref({
fileUrl: '',
fileName: '',
fileType: 'pdf'
})
const filePreviewRef = ref()
const filePreviewShow = ref(false)
const _singleFileValue = computed({
get() {
return props.singleList;
},
set(value) {
emit('update:singleList', value)
}
})
const _otherFileListValue = computed({
get() {
return props.otherFileList;
},
set(value) {
emit('update:otherFileList', value)
}
})
if (_otherFileListValue.value && _otherFileListValue.value.length > 0) {
isHaveOneFile.value = true
_otherFileListValue.value.forEach(item => {
allFileList.value.push(item)
})
}
// watch(() => props.showSingleTable, (newVal) => {
// props.showSingleTable = newVal
// }, {deep: true})
watch(() => props.formData.fileList, (newVal) => {
if (props.preview) {
newVal?.forEach(item => {
isHaveOneFile.value = true
allFileList.value.push(item)
})
}
}, {immediate: true})
watch(() => props.formData.singleFile, (newVal) => {
props.formData.singleFile = newVal
if (newVal != null) {
singleFileArray.value.push(newVal)
} else {
singleFileArray.value = []
}
singleFile.value = newVal
}, {immediate: true})
// watch(() => props.otherFileList, (newVal) => {
// props.otherFileList=newVal
// if (props.preview) {
// console.log('newotherFileList', newVal,props.preview,props.formData.fileList)
// if (props.formData.fileList === null || props.formData.fileList?.length === 0) {
// allFileList.value = newVal
// } else {
// console.log('props.otherFileList',props.otherFileList)
// // props.otherFileList?.forEach(item => {
// // allFileList.value.push(item)
// // })
// }
// } else {
// allFileList.value = newVal
// }
// }, {deep: true})
watch(() => props.showTable, (newVal) => {
props.showTable = newVal
}, {deep: true})
// watch(() => props.singleList, (newVal) => {
// console.log('singleFile', newVal)
// singleFileList.value = newVal
// }, {deep: true})
watch(() => isSingleFile.value, (newVal) => {
isSingleFile.value = newVal
}, {deep: true})
watch(() => isHaveOneFile.value, (newVal) => {
isHaveOneFile.value = newVal
}, {deep: true})
// watch(() => singleFile.value, (newVal) => {
// singleFile.value = newVal
// }, {deep: true})
const handleImportTemplateDownload = async () => {
console.info("🚀 ~method:handleImportTemplateDownload -----", props.tag)
let templateType = ''
let templateTypeList = ''
let isZip = false
if (props.tag === '需求上报') {
templateType = '2'
isZip = false
} else if (props.tag === '项目立项') {
templateTypeList = '5,6'
isZip = true
} else if (props.tag === '项目验收') {
templateType = '7'
isZip = false
} else if (props.tag === '阶段变更') {
templateTypeList = '8,9'
isZip = true
}
let res = ''
if (isZip) {
res = await downloadTemplateZip(templateTypeList)
let fileName = props.templateName +'.zip'
const blob = new Blob([res.data])
let a = document.createElement('a')
a.href = URL.createObjectURL(blob)
a.download = fileName
a.click()
} else {
res = await downloadTemplate(templateType)
const blob = new Blob([res])
let a = document.createElement('a')
a.href = URL.createObjectURL(blob)
a.download = props.templateName + ".docx"
a.click()
}
}
const clickToPreview = (row) => {
filePreviewShow.value = false
console.log('clickToPreview', row, row.fileType)
filePreviewParam.value = {
fileUrl: row.url,
fileName: row.originalFileName,
fileType: row.fileType
}
nextTick(() => {
filePreviewShow.value = true
})
// filePreviewRef.value.show()
}
const handleDelete = (row, type) => {
// deleteFile(row.fileId).then(res => {
// ElNotification({
// title: '提示',
// message: res.msg,
// type: res.code === 1000 ? 'success' : 'error'
// })
// if (res.code === 1000) {
if (type === 'single') {
_singleFileValue.value.splice(_singleFileValue.value.findIndex((item) => item.fileId === row.fileId), 1);
isSingleFile.value = false
} else {
allFileList.value.splice(allFileList.value.findIndex((item) => item.fileId === row.fileId), 1);
isHaveOneFile.value = !(allFileList.value && allFileList.value?.length == 0);
console.log('allFileList.value',allFileList.value)
if (localStorage.getItem('collectData')) {
let collectData = JSON.parse(localStorage.getItem('collectData'))
collectData.fileList = allFileList.value
localStorage.setItem('collectData', JSON.stringify(collectData))
}
if (localStorage.getItem('otherFileList')) {
localStorage.setItem('otherFileList', JSON.stringify(allFileList.value))
}
}
// }
// });
}
const handleSingleDelete = (row) => {
handleDelete(row, 'single')
}
const getAttachment = (val) => {
isSingleFile.value = true
emit('getAttachment', val)
}
const compositeParam = (item) => {
return {
fileId: item.id,
size: item.size,
originalFileName: item.originalFilename,
fileType: item.fileType,
url: item.url,
newFile: true,
tag: props.tag
}
}
const getOtherFile = (val) => {
if (props.preview) {
allFileList.value.push(compositeParam(val))
} else {
allFileList.value = _otherFileListValue.value
}
isHaveOneFile.value = true
emit('getOtherFile', val)
}
const deleteAttachment = (val) => {
deleteFile(val).then(res => {
if (res.code === 1000) {
ElNotification({
title: '提示',
message: "删除成功",
type: 'success'
})
isSingleFile.value = false
singleFile.value = null
singleFileArray.value = []
}
});
}
const deleteSingleFile = (row, type) => {
ElMessageBox.confirm(`确认删除名称为${row.originalFileName}的文件吗?`, '系统提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
deleteFile(row.fileId).then(res => {
ElNotification({
title: '提示',
message: res.msg,
type: res.code === 1000 ? 'success' : 'error'
})
if (res.code === 1000) {
isSingleFile.value = false
if (type === 1) {
singleFile.value = null
singleFileArray.value = []
} else {
props.otherFileList.splice(props.otherFileList.findIndex((item) => item.fileId === row.fileId), 1);
}
}
});
}).catch(() => {
ElNotification({
title: '提示',
message: "用户取消删除! ",
type: 'warning'
})
})
}
const handleDownload = (row) => {
downloadFile(row.fileId).then(res => {
const blob = new Blob([res])
let a = document.createElement('a')
a.href = URL.createObjectURL(blob)
a.download = row.originalFileName
a.click()
})
}
defineExpose({
validate() {
return applyForm.value.validate()
},
clearValidate() {
return applyForm.value.clearValidate()
},
allFileList,
singleFile,
isSingleFile,
isHaveOneFile,
})
</script>
<style lang="scss" scoped>
:deep(.el-table--fit ) {
height: 160px !important;
}
:deep(.el-table__header) {
.is-leaf:first-child {
.cell {
margin-left: -22px !important;
}
}
}
:deep(.el-table__body) {
.el-table__cell:first-child {
.cell {
margin-left: -11px !important;
}
}
}
</style>