ImportDialog.vue 5.76 KB
<template>
  <el-dialog title="导入考勤数据" :visible.sync="visible" width="500px" :close-on-click-modal="false" @close="close">
    <div>
      <el-form label-width="100px" label-position="right">
        <el-form-item label="选择文件">
          <el-upload ref="upload" :action="uploadUrl" :headers="uploadHeaders" :data="uploadData" :file-list="fileList"
            :before-upload="beforeUpload" :on-success="onUploadSuccess" :on-error="onUploadError"
            :on-change="handleFileChange" :auto-upload="false" :limit="1" :on-exceed="handleExceed" accept=".xlsx,.xls"
            drag>
            <i class="el-icon-upload"></i>
            <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
            <div class="el-upload__tip" slot="tip">只能上传一个xlsx/xls文件,且不超过10MB</div>
          </el-upload>
        </el-form-item>
      </el-form>

      <div v-if="uploadResult" class="upload-result">
        <el-alert :title="uploadResult.title" :type="uploadResult.type" :description="uploadResult.description"
          show-icon :closable="false" />
      </div>
    </div>

    <div slot="footer" class="dialog-footer">
      <el-button @click="close">取消</el-button>
      <el-button type="primary" @click="submitUpload" :loading="uploading">
        确定导入
      </el-button>
    </div>
  </el-dialog>
</template>

<script>
import request from '@/utils/request'

export default {
  name: 'ImportDialog',
  data() {
    return {
      visible: false,
      uploading: false,
      fileList: [],
      uploadUrl: '',
      uploadHeaders: {},
      uploadData: {},
      uploadResult: null
    }
  },
  methods: {
    init() {
      this.visible = true
      this.resetForm()
    },
    resetForm() {
      this.fileList = []
      this.uploadResult = null
      this.uploading = false
    },
    beforeUpload(file) {
      const isExcel = file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' ||
        file.type === 'application/vnd.ms-excel'
      const isLt10M = file.size / 1024 / 1024 < 10

      if (!isExcel) {
        this.$message.error('只能上传Excel文件!')
        return false
      }
      if (!isLt10M) {
        this.$message.error('上传文件大小不能超过 10MB!')
        return false
      }
      return true
    },
    submitUpload() {
      if (!this.fileList.length || !this.fileList[0]) {
        this.$message.warning('请选择要上传的文件')
        return
      }

      const file = this.fileList[0]

      if (!file.raw) {
        this.$message.warning('文件信息异常,请重新选择文件')
        return
      }

      this.uploading = true
      this.uploadResult = null

      const formData = new FormData()
      formData.append('file', file.raw)

      request({
        url: '/api/Extend/lqattendancesummary/ImportAttendanceDataFromExcel',
        method: 'POST',
        data: formData,
        headers: {
          'Content-Type': 'multipart/form-data'
        }
      }).then(res => {
        this.uploading = false
        if (res.code === 200) {
          const result = (res.data && res.data.data) || {}
          const successCount = result.successCount || 0
          const failCount = result.failCount || 0
          const totalCount = result.totalCount || 0
          const errors = result.errorMessages || []
          const errorPreview = errors.slice(0, 5).join(';')
          const moreErrors = errors.length > 5 ? `等共 ${errors.length} 条` : ''

          if (successCount === 0) {
            this.uploadResult = {
              type: 'error',
              title: '导入失败',
              description: errorPreview || res.msg || '没有成功导入任何数据,请检查 Excel 内容'
            }
            this.$message.error('导入失败,请查看失败原因')
            return
          }

          const desc = `共 ${totalCount} 条,成功 ${successCount} 条` +
            (failCount > 0 ? `,失败 ${failCount} 条` : '') +
            ';当月仅保留本次导入的人员汇总' +
            (errorPreview ? `。失败示例:${errorPreview}${moreErrors}` : '')

          this.uploadResult = {
            type: failCount > 0 ? 'warning' : 'success',
            title: failCount > 0 ? '部分导入成功' : '导入成功',
            description: desc
          }
          this.$message({
            type: failCount > 0 ? 'warning' : 'success',
            message: failCount > 0 ? '部分数据导入成功' : '导入成功',
            duration: 2000
          })
          setTimeout(() => {
            this.close()
            this.$emit('refresh', true)
          }, failCount > 0 ? 4000 : 2000)
        } else {
          this.uploadResult = {
            type: 'error',
            title: '导入失败',
            description: res.msg || '数据导入失败,请检查文件格式'
          }
        }
      }).catch(err => {
        this.uploading = false
        this.uploadResult = {
          type: 'error',
          title: '导入失败',
          description: err.message || '网络错误,请重试'
        }
        this.$message.error('导入失败')
      })
    },
    onUploadSuccess() {
      // 手动上传,此处无需处理
    },
    onUploadError() {
      this.uploading = false
      this.uploadResult = {
        type: 'error',
        title: '上传失败',
        description: '文件上传失败,请重试'
      }
    },
    handleExceed() {
      this.$message.warning('只能上传一个文件,请先删除已选择的文件')
    },
    handleFileChange(file, fileList) {
      this.fileList = fileList
    },
    close() {
      this.visible = false
      this.resetForm()
    }
  }
}
</script>

<style scoped>
.upload-result {
  margin-top: 20px;
}

.el-upload-dragger {
  width: 100%;
}
</style>