smart-bid-web/src/views/common/ImportExcelDialog.vue

411 lines
10 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>
<el-dialog :title="title" :visible.sync="dialogVisible" width="450px" append-to-body @close="handleClose"
class="import-excel-dialog">
<div class="upload-container">
<el-upload ref="upload" :limit="1" accept=".xlsx, .xls" :headers="headers"
:action="uploadUrl + '?updateSupport=' + updateSupport" :disabled="isUploading"
:on-progress="handleFileUploadProgress" :on-success="handleFileSuccess" :on-error="handleFileError"
:before-upload="beforeUpload" :on-change="handleFileChange" :auto-upload="false" drag :data="params" class="custom-upload">
<div class="upload-content">
<i class="el-icon-upload upload-icon"></i>
<div class="upload-text">
<div class="main-text">将文件拖到此处</div>
<div class="sub-text"><em>点击上传</em></div>
</div>
</div>
<div class="upload-tip" slot="tip">
<i class="el-icon-info"></i>
<span>仅允许导入 xlsxlsx 格式文件单份文件大小上限 {{ maxFileTips }}</span>
</div>
</el-upload>
</div>
<div slot="footer" class="dialog-footer">
<el-button type="primary" class="confirm-btn" @click="handleSubmit" :loading="isUploading"
:disabled="isUploading">
<span v-if="!isUploading">确认</span>
<span v-else>上传中...</span>
</el-button>
<el-button class="cancel-btn" @click="handleClose">取消</el-button>
</div>
</el-dialog>
</template>
<script>
import { getToken } from '@/utils/auth'
export default {
name: 'ImportExcelDialog',
props: {
// 是否显示对话框
visible: {
type: Boolean,
default: false
},
// 对话框标题
title: {
type: String,
default: '数据导入'
},
// 上传地址
uploadUrl: {
type: String,
required: true
},
maxFileTips: {
type: String,
default: '20MB',
},
params:{
type:Object,
default:()=>{}
}
},
data() {
return {
dialogVisible: false,
isUploading: false,
updateSupport: 0,
headers: {
Authorization: 'Bearer ' + getToken()
},
fileList: []
}
},
watch: {
visible: {
immediate: true,
handler(val) {
this.dialogVisible = val
if (val) {
// 打开对话框时重置状态
this.resetState()
}
}
},
dialogVisible(val) {
this.$emit('update:visible', val)
}
},
computed: {
// 将 maxFileTips 转换为字节数
maxFileSize() {
const tips = this.maxFileTips.toUpperCase()
const match = tips.match(/(\d+)(MB|KB|GB)/)
if (!match) return 20 * 1024 * 1024 // 默认 20MB
const size = parseInt(match[1])
const unit = match[2]
switch (unit) {
case 'KB':
return size * 1024
case 'MB':
return size * 1024 * 1024
case 'GB':
return size * 1024 * 1024 * 1024
default:
return 20 * 1024 * 1024
}
}
},
methods: {
// 添加文件变化监听
handleFileChange(file, fileList) {
this.fileList = fileList
},
// 文件上传前的验证
beforeUpload(file) {
// 验证文件大小
if (file.size > this.maxFileSize) {
this.$message.error(`文件大小不能超过 ${this.maxFileTips}`)
return false
}
// 验证文件类型
const isExcel = file.type === 'application/vnd.ms-excel' ||
file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' ||
file.name.endsWith('.xls') ||
file.name.endsWith('.xlsx')
if (!isExcel) {
this.$message.error('只能上传 xls、xlsx 格式的文件!')
return false
}
return true
},
// 重置状态
resetState() {
this.isUploading = false
this.updateSupport = 0
if (this.$refs.upload) {
this.$refs.upload.clearFiles()
}
},
// 文件上传进度
handleFileUploadProgress(event, file, fileList) {
this.isUploading = true
this.$emit('upload-progress', event, file, fileList)
},
// 文件上传成功
handleFileSuccess(response, file, fileList) {
this.isUploading = false
this.$refs.upload.clearFiles()
this.$emit('upload-success', response, file, fileList)
// 显示导入结果
if (response && response.msg) {
this.$alert(
"<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>",
"导入结果",
{
dangerouslyUseHTMLString: true,
type: response.code === 200 ? 'success' : 'error'
}
)
}
// 成功后关闭对话框
if (response && response.code === 200) {
this.handleClose()
}
},
// 文件上传失败
handleFileError(error, file, fileList) {
this.isUploading = false
this.$message.error('文件上传失败,请稍后重试')
this.$emit('upload-error', error, file, fileList)
},
// 提交上传
handleSubmit() {
if (this.fileList.length > 0) {
this.$refs.upload.submit()
} else {
this.$message.warning('请先选择要上传的文件')
}
},
// 关闭对话框
handleClose() {
this.dialogVisible = false
this.resetState()
this.$emit('close')
}
}
}
</script>
<style scoped lang="scss">
// 对话框样式优化
::v-deep .import-excel-dialog {
.el-dialog {
border-radius: 8px;
overflow: hidden;
}
.el-dialog__header {
padding: 20px 24px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
.el-dialog__title {
color: #fff;
font-size: 18px;
font-weight: 600;
}
.el-dialog__close {
color: #fff;
font-size: 20px;
&:hover {
color: rgba(255, 255, 255, 0.8);
}
}
}
.el-dialog__body {
padding: 30px 24px 20px;
}
}
// 上传容器
.upload-container {
width: 100%;
}
// 自定义上传样式
::v-deep .custom-upload {
.el-upload-dragger {
width: 100%;
height: 200px;
border: 2px dashed #d9d9d9;
border-radius: 8px;
background: #fafafa;
transition: all 0.3s ease;
cursor: pointer;
&:hover {
border-color: #409EFF;
background: #f0f7ff;
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(64, 158, 255, 0.15);
}
&.is-dragover {
border-color: #409EFF;
background: #e6f4ff;
border-style: solid;
}
}
.el-upload__input {
display: none;
}
}
// 上传内容区域
.upload-content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
padding: 20px;
.upload-icon {
font-size: 64px;
color: #409EFF;
margin-bottom: 16px;
transition: all 0.3s ease;
}
.upload-text {
text-align: center;
.main-text {
font-size: 16px;
color: #333;
font-weight: 500;
margin-bottom: 8px;
}
.sub-text {
font-size: 14px;
color: #666;
em {
color: #409EFF;
font-style: normal;
font-weight: 500;
}
}
}
&:hover {
.upload-icon {
transform: scale(1.1);
color: #66b1ff;
}
}
}
// 上传提示
.upload-tip {
margin-top: 16px;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
color: #909399;
font-size: 13px;
i {
color: #909399;
font-size: 14px;
}
span {
line-height: 20px;
}
}
// 文件列表样式优化
::v-deep .el-upload-list {
margin-top: 16px;
.el-upload-list__item {
border-radius: 6px;
border: 1px solid #e4e7ed;
transition: all 0.3s ease;
&:hover {
border-color: #409EFF;
background: #f0f7ff;
}
.el-icon-document {
color: #409EFF;
}
.el-upload-list__item-name {
color: #333;
}
}
}
// 禁用状态
::v-deep .custom-upload.is-disabled {
.el-upload-dragger {
cursor: not-allowed;
opacity: 0.6;
&:hover {
border-color: #d9d9d9;
background: #fafafa;
transform: none;
box-shadow: none;
}
}
}
// 底部按钮样式(按照 ToolForm.vue 样式)
.dialog-footer {
text-align: center;
}
.confirm-btn {
width: 98px;
height: 36px;
background: #1F72EA;
box-shadow: 0px 4px 8px 0px rgba(51, 135, 255, 0.5);
border-radius: 4px;
color: #fff;
border: none;
font-size: 14px;
transition: all 0.3s;
&:hover {
background: #4A8BFF;
box-shadow: 0px 6px 12px 0px rgba(51, 135, 255, 0.6);
}
}
.cancel-btn {
width: 98px;
height: 36px;
background: #E5E5E5;
box-shadow: 0px 4px 8px 0px rgba(76, 76, 76, 0.2);
border-radius: 4px;
color: #333;
border: none;
font-size: 14px;
transition: all 0.3s;
&:hover {
background: #d0d0d0;
box-shadow: 0px 6px 12px 0px rgba(76, 76, 76, 0.3);
}
}
</style>