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.
 
 
 
 
 

313 lines
8.9 KiB

<template>
<div class="customer-css">
<el-dialog
title="导入IFS库存数据"
:close-on-click-modal="false"
:visible.sync="visible"
width="450px"
class="customer-dialog"
@close="handleDialogClose"
:show-close="!uploading">
<el-form :inline="true" label-position="top" label-width="80px">
<el-row>
<el-form-item label=" ">
<el-button
type="primary"
icon="el-icon-download"
:disabled="uploading"
@click="downloadTemplate">
下载 Excel 模板
</el-button>
</el-form-item>
</el-row>
<el-row>
<el-col :span="24">
<el-upload
class="customer-upload"
drag
action="javascript:void(0);"
ref="uploadFile"
:limit="1"
accept=".xlsx,.xls"
:before-upload="beforeUploadHandle"
:on-change="onChange"
:auto-upload="false"
:disabled="uploading"
style="text-align: left;">
<i class="el-icon-upload"></i>
<div class="el-upload__text">
{{ uploading ? '正在上传中,请稍候...' : '将文件拖到此处,或点击上传' }}
</div>
</el-upload>
</el-col>
</el-row>
<el-row style="margin-top: 15px;">
<el-alert
title="导入说明"
type="info"
:closable="false"
show-icon>
<div style="font-size: 12px; line-height: 1.8;">
1. 请先下载模板按模板格式填写数据<br/>
2. 必填字段SitePart NoLot/Batch NoLocation NoQty On Hand<br/>
3. A-K列库存信息保存到inventory_stock_ifs表<br/>
4. L-U列料件属性信息保存到part_attribute表可选填<br/>
5. 料件属性如已存在会自动跳过不会报错<br/>
6. 日期格式YYYY/M/D YYYY-MM-DD
</div>
</el-alert>
</el-row>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="saveUploadFile" :loading="uploading" :disabled="uploading">
{{ uploading ? '上传中...' : '开始导入' }}
</el-button>
<el-button @click="closeDialog" :disabled="uploading">关闭</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { uploadIfsInventoryExcel } from '@/api/warehouse/ifsInventoryInit.js'
export default {
name: 'ifsInventoryUploadExcel',
data() {
return {
visible: false,
fileList: [],
uploading: false // 上传状态标志
}
},
methods: {
/**
* 初始化组件
*/
init() {
this.fileList = []
this.uploading = false
this.visible = true
},
/**
* 上传之前的验证
*/
beforeUploadHandle(file) {
let extName = file.name.substring(file.name.lastIndexOf('.')).toLowerCase()
if (!(extName === '.xlsx' || extName === '.xls')) {
this.$message.error('数据导入失败,请选择正确的xlsx或xls格式的Excel文件')
return false
}
return true
},
/**
* 选择上传文件时
*/
onChange(file) {
// 清空之前的文件列表,确保只有一个文件
this.fileList = []
this.fileList.push(file)
},
/**
* 关闭弹窗
*/
closeDialog() {
this.deleteFile()
this.visible = false
},
/**
* 处理弹窗关闭事件(包括右上角X按钮)
*/
handleDialogClose() {
if (this.uploading) {
this.$message.warning('正在上传中,请稍候...')
return
}
this.deleteFile()
},
/**
* 清除文件
*/
deleteFile() {
this.fileList = []
this.uploading = false
// 清空文件上传记录
this.$refs.uploadFile.clearFiles()
// 刷新父页面
this.$emit('refreshTable')
},
/**
* 格式化错误信息为HTML列表
*/
formatErrorMessages(errorMessages) {
if (!errorMessages || errorMessages.length === 0) {
return ''
}
// 限制显示的错误数量(前20条)
const displayMessages = errorMessages.slice(0, 20)
const hasMore = errorMessages.length > 20
let html = '<div style="text-align: left; max-height: 400px; overflow-y: auto;">'
html += '<p style="color: #E6A23C; font-weight: bold; margin-bottom: 10px;">以下数据导入失败:</p>'
html += '<ol style="padding-left: 20px; line-height: 1.8;">'
displayMessages.forEach(msg => {
html += `<li style="color: #F56C6C; margin-bottom: 5px;">${msg}</li>`
})
html += '</ol>'
if (hasMore) {
html += `<p style="color: #909399; margin-top: 10px;">...还有 ${errorMessages.length - 20} 条错误</p>`
}
html += '</div>'
return html
},
/**
* 下载Excel模板
*/
downloadTemplate() {
const loading = this.$loading({
lock: true,
text: '正在下载模板...',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
})
this.$http({
url: this.$http.adornUrl('/ifsInventoryInit/downloadTemplate'),
method: 'get',
responseType: 'blob'
}).then(response => {
loading.close()
// 创建下载链接
const blob = new Blob([response.data], {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
})
const url = window.URL.createObjectURL(blob)
const link = document.createElement('a')
link.href = url
link.download = 'IFS库存导入模板.xlsx'
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
window.URL.revokeObjectURL(url)
this.$message.success('模板下载成功')
}).catch(error => {
loading.close()
console.error('模板下载失败:', error)
this.$message.error('模板下载失败,请联系管理员')
})
},
/**
* 保存上传文件
*/
saveUploadFile() {
// 判断文件是否上传
if (null == this.fileList || 0 === this.fileList.length) {
this.$message.error("请先选择要上传的Excel文件!")
return false
}
// 再次校验文件格式
const file = this.fileList[0].raw
const fileName = file.name
const fileExtension = fileName.substring(fileName.lastIndexOf('.')).toLowerCase()
if (!('.xls' === fileExtension || '.xlsx' === fileExtension)) {
this.$message.error('文件格式不正确,只支持.xls和.xlsx格式的Excel文件')
return false
}
// 设置上传状态
this.uploading = true
// 创建FormData对象
const formData = new FormData()
formData.append("file", file)
formData.append("site", localStorage.getItem('site'))
formData.append("uploadBy", this.$store.state.user.name)
// 调用上传接口
uploadIfsInventoryExcel(formData).then(({ data }) => {
if (data.code === 0) {
// 检查是否有错误信息
const errorMessages = data.errorMessages || []
if (errorMessages.length > 0) {
// 有错误信息,使用弹窗显示详细错误列表
const errorHtml = this.formatErrorMessages(errorMessages)
this.$alert(errorHtml, '导入完成(部分数据失败)', {
confirmButtonText: '确定',
dangerouslyUseHTMLString: true,
customClass: 'import-error-dialog'
}).then(() => {
// 关闭窗口并刷新页面
this.closeDialog()
})
} else {
// 完全成功,显示成功提示
this.$message({
message: data.msg || 'IFS库存数据导入成功',
type: 'success',
duration: 2000
})
// 关闭窗口并刷新页面
this.closeDialog()
}
} else {
this.$alert(data.msg, '错误', {
confirmButtonText: '确定'
})
}
}).catch(error => {
console.error('Excel上传异常:', error)
this.$message.error('Excel文件上传异常,请检查文件格式和内容')
}).finally(() => {
// 无论成功还是失败,都重置上传状态
this.uploading = false
})
}
}
}
</script>
<style scoped>
.customer-css .customer-upload {
width: 100%;
}
.customer-css .el-upload {
width: 100%;
}
.customer-css .el-upload-dragger {
width: 100%;
}
</style>
<style>
/* 导入错误弹窗样式 */
.import-error-dialog {
width: 600px !important;
}
.import-error-dialog .el-message-box__message {
max-height: 500px;
overflow-y: auto;
}
</style>