smart-bid-web/src/views/template/templateInfo/components/child/SectionFile.vue

366 lines
9.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="file-container">
<div class="basic-info-title">
<div class="title-content">
<img src="@/assets/enterpriseLibrary/basic-info.png" alt="标段文件">
<span>{{ title }}</span>
</div>
<el-button
type="text"
icon="el-icon-plus"
class="add-tab-btn"
@click="handleAddTab"
:disabled="fileTabs.length >= 10"
>
添加文件
</el-button>
</div>
<el-tabs
v-model="activeTabIndex"
type="card"
class="file-tabs"
@tab-remove="handleRemoveTab"
v-on="isEditMode ? { 'tab-click': handleTabChange } : {}"
>
<el-tab-pane
v-for="(tab, index) in fileTabs"
:key="index"
:label="tab.formData.fileName || ('文件 ' + (index + 1))"
:name="index.toString()"
closable
>
<el-form
:model="tab.formData"
:rules="rules"
:ref="'sectionFileForm_' + index"
label-width="120px"
label-position="top"
class="file-form"
>
<el-row :gutter="24">
<el-col :span="8">
<el-form-item label="组成文件名称" prop="fileName">
<el-input
v-model="tab.formData.fileName"
placeholder="请输入"
maxlength="128"
@input="handleFileNameChange(index)"
@change="handleFileNameChange(index)"
></el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="文件类型" prop="compositionFileType">
<el-select
v-model="tab.formData.compositionFileType"
placeholder="请选择文件类型"
clearable
@change="handleTypeChange(index)"
>
<el-option
v-for="item in compositionFileTypeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="8">
<el-form-item label="文件" prop="fileList">
<UploadFile
:fileList="tab.formData.fileList"
:fileUploadRule="fileUploadRule"
@file-change="(files, type) => handleFileChange(files, index)"
@del-file="(file) => handleDelFile(file, index)"
:uploadType="uploadType"
:maxFileTips="maxFileTips"
type="section_file"
:limitUploadNum="1"
:show-file-list="true"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-tab-pane>
</el-tabs>
</div>
</template>
<script>
import UploadFile from '@/views/common/UploadFile.vue'
export default {
name: 'SectionFile',
components: { UploadFile },
props: {
title: {
type: String,
default: '模板组成-标段/标包文件'
},
isEditMode: {
type: Boolean,
default: false
}
},
data() {
return {
uploadType: 'doc、docx、pdf、xls、xlsx、wps',
maxFileTips: '50MB',
fileUploadRule: { fileUploadType: 'section_file', suffix: 'template' },
activeTabIndex: '0',
fileTabs: [
{
formData: {
compositionType: '2',
fileName: '',
compositionFileType: '',
fileList: [],
delFileList: []
}
}
],
rules: {
fileName: [
{ required: true, message: '请输入组成文件名称', trigger: 'blur' }
],
compositionFileType: [
{ required: true, message: '请选择文件类型', trigger: 'change' }
],
fileList: [
{ required: true, message: '请上传文件', trigger: 'change' }
]
},
compositionFileTypeOptions: []
}
},
created() {
this.loadFileTypeDict()
},
methods: {
loadFileTypeDict() {
this.getDicts('file_type').then(response => {
this.compositionFileTypeOptions = response.data.map(item => ({
label: item.dictLabel,
value: item.dictLabel
}))
}).catch(error => {
console.error('加载文件类型字典失败:', error)
})
},
handleAddTab() {
this.fileTabs.push({
formData: {
compositionType: '2',
fileName: '',
compositionFileType: '',
fileList: [],
delFileList: []
}
})
this.activeTabIndex = (this.fileTabs.length - 1).toString()
},
handleRemoveTab(index) {
if (this.fileTabs.length <= 1) {
this.$message.warning('至少保留一个文件')
return
}
this.fileTabs.splice(index, 1)
// 如果删除的是当前激活的tab需要重新设置激活态
if (this.activeTabIndex === index.toString()) {
this.activeTabIndex = this.fileTabs.length > 0 ? (this.fileTabs.length - 1).toString() : '0';
}
},
handleFileChange(files, index) {
this.fileTabs[index].formData.fileList = files;
if (files.length > 0 && files[0].status === 'success') {
const currentTab = this.fileTabs[index];
files[0].compositionName = currentTab.formData.fileName;
files[0].compositionFileType = currentTab.formData.compositionFileType;
if (files[0].response) {
files[0].response.businessType = 'section_file';
}
}
},
handleDelFile(file, index) {
// 核心修改:统一从 response.fileRes.filePath 获取路径
const filePath = file.response?.fileRes?.filePath || file.filePath || '';
if (filePath) {
const delFileList = this.fileTabs[index].formData.delFileList;
if (!delFileList.includes(filePath)) {
delFileList.push(filePath)
}
}
},
handleFileNameChange(index) {
const currentTab = this.fileTabs[index];
const fileList = currentTab.formData.fileList;
if (fileList.length > 0) {
fileList[0].compositionName = currentTab.formData.fileName;
}
},
handleTypeChange(index) {
const currentTab = this.fileTabs[index];
const fileList = currentTab.formData.fileList;
if (fileList.length > 0) {
fileList[0].compositionFileType = currentTab.formData.compositionFileType;
}
},
// 切换Tab时不再执行任何操作
handleTabChange(tab, event) {
// 可以保留日志用于调试
const index = tab.index;
console.log(`切换到了第 ${index + 1} 个 tab`);
},
setFormData(sectionFiles) {
// 直接清空并重建 fileTabs
this.fileTabs = [];
if (!sectionFiles || sectionFiles.length === 0) {
this.fileTabs.push({
formData: {
compositionType: '2',
fileName: '',
compositionFileType: '',
fileList: [],
delFileList: []
}
})
this.activeTabIndex = '0';
return;
}
sectionFiles.forEach((file) => {
const formattedFile = {
name: file.fileName || file.name,
size: file.size,
status: 'success',
percentage: 100,
filePath: file.filePath,
lsFilePath: file.lsFilePath,
url: file.lsFilePath,
compositionName: file.compositionName || file.fileName || '',
compositionFileType: file.compositionFileType || '',
compositionType: '2',
businessType: 'section_file',
};
this.fileTabs.push({
formData: {
compositionType: '2',
fileName: formattedFile.compositionName,
compositionFileType: formattedFile.compositionFileType,
fileList: [formattedFile],
delFileList: []
}
})
})
this.activeTabIndex = sectionFiles.length > 0 ? '0' : '0';
},
validate() {
return new Promise(async (resolve, reject) => {
try {
const allFormData = []
for (let i = 0; i < this.fileTabs.length; i++) {
const formRef = this.$refs[`sectionFileForm_${i}`]?.[0]
if (!formRef) continue
await new Promise((validResolve, validReject) => {
formRef.validate((valid) => {
if (valid) {
validResolve()
} else {
this.activeTabIndex = i.toString()
validReject(new Error(`文件 ${i + 1} 信息填写不完整`))
}
})
})
allFormData.push({ ...this.fileTabs[i].formData })
}
resolve(allFormData)
} catch (error) {
reject(error)
}
})
}
}
}
</script>
<style scoped lang="scss">
/* 样式部分保持不变 */
.file-container {
width: 100%;
}
.basic-info-title {
display: flex;
align-items: center;
justify-content: space-between;
margin: 10px 0 20px;
.title-content {
display: flex;
align-items: center;
}
span {
margin-left: 8px;
font-size: 18px;
font-weight: 500;
color: #1d2129;
}
img {
width: 20px;
height: 20px;
object-fit: contain;
}
}
.file-tabs {
margin-bottom: 20px;
width: 100%;
}
.add-tab-btn {
color: #409EFF;
border: 1px dashed #409EFF;
padding: 6px 12px;
border-radius: 4px;
white-space: nowrap;
}
.file-form {
padding: 20px 10px 0;
}
::v-deep .el-tabs__item {
padding: 0 20px;
}
::v-deep .el-tabs__close-btn {
margin-left: 8px;
}
</style>