|
@@ -0,0 +1,341 @@
|
|
|
+<template>
|
|
|
+ <div class="uploadCost">
|
|
|
+ <el-dialog
|
|
|
+ v-loading="loading"
|
|
|
+ :before-close="closeUpload"
|
|
|
+ :close-on-click-modal="false"
|
|
|
+ :close-on-press-escape="false"
|
|
|
+ :title="importTitle"
|
|
|
+ :visible.sync="dialogVisible"
|
|
|
+ class="statistic_base"
|
|
|
+ :append-to-body="true"
|
|
|
+ :modal-append-to-body="true"
|
|
|
+ custom-class="tagdialog"
|
|
|
+ width="50%"
|
|
|
+ >
|
|
|
+ <!-- :title="isImport?'导入结果':'批量导入'"-->
|
|
|
+ <div v-if="!isImport">
|
|
|
+ <!-- <p v-for="(item, index) in uploadTitle" :key="index" class="uploadtitle">-->
|
|
|
+ <!-- {{ item }}-->
|
|
|
+ <!-- </p>-->
|
|
|
+ <el-card style="padding-top: 10px;padding-bottom: 10px">
|
|
|
+
|
|
|
+ <div style="width: 50%;float:left;">
|
|
|
+ <p class="uploadtitle txtcenter">1.下载模板按要求填写</p>
|
|
|
+ <img class="mtmb16 mgauto" src="@/assets/excelicon.png" width="50px">
|
|
|
+ <div style="width: 100%">
|
|
|
+ <el-button class="mtmb16 mgauto" size="small" type="primary" @click="downloadTemplate()">下载模板
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div style="width: 50%;float:left;">
|
|
|
+ <p class="uploadtitle txtcenter">2.上传填写好的文件</p>
|
|
|
+ <img class="mtmb16 mgauto" src="@/assets/excelicon.png" width="50px">
|
|
|
+ <div class="mgauto2">
|
|
|
+ <el-upload
|
|
|
+ :file-list="fileUrlList"
|
|
|
+ :http-request="uploadFile"
|
|
|
+ :limit="1"
|
|
|
+ accept=".xlsx"
|
|
|
+ action="#"
|
|
|
+ >
|
|
|
+ <el-button class="mtmb16" size="small" style="margin-top: 0;height: 33px" type="primary">上传文件</el-button>
|
|
|
+ <div slot="file" slot-scope="{file}">
|
|
|
+ <a :href="file.url">{{ file.name }}</a>
|
|
|
+ <span class="el-upload-list__item-actions">
|
|
|
+ <i class="el-icon-delete" @click="handlePictureRemove(file,fileUrlList)" />
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ </el-upload>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ </el-card>
|
|
|
+ </div>
|
|
|
+ <div v-if="isImport" style="margin:10px">
|
|
|
+ <p>导入成功 <span>{{ successCount }} 条</span> ,失败 <span>{{ errorCount }}</span> 条 </p>
|
|
|
+ <p>您可以下载失败记录,修改后重新上传。以下标红为校验失败项</p>
|
|
|
+ <el-table
|
|
|
+ :data="tableData"
|
|
|
+ style="width: 100%;"
|
|
|
+ >
|
|
|
+ <el-table-column align="center" label="小区-分期" prop="groupDiscName">
|
|
|
+ <template v-slot="scope">
|
|
|
+ <span>{{ scope.row.groupNameStr + '-' + scope.row.discNameStr }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column align="center" label="批次号" prop="batchNumber">
|
|
|
+ <template v-slot="scope">
|
|
|
+ <span>{{ scope.row.batchNumberStr }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column align="center" label="选房号" prop="roomSelectionNumber">
|
|
|
+ <template v-slot="scope">
|
|
|
+ <span>{{ scope.row.roomSelectionNumberStr }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column align="center" label="买受人" prop="buyerName">
|
|
|
+ <template v-slot="scope">
|
|
|
+ <span>{{ scope.row.buyerNameStr }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column align="center" label="异常原因" prop="reason">
|
|
|
+ <template v-slot="scope">
|
|
|
+ <span style="color: red">{{ scope.row.reason }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ </div>
|
|
|
+ <span slot="footer" class="dialog-footer">
|
|
|
+ <el-button @click="closeUpload()">取 消</el-button>
|
|
|
+ <el-button
|
|
|
+ v-if="!isImport"
|
|
|
+ :disabled="fileUrlList.length===0"
|
|
|
+ type="primary"
|
|
|
+ class="ch-button-else"
|
|
|
+ @click="importFile()"
|
|
|
+ >导入</el-button>
|
|
|
+ <el-button
|
|
|
+ v-if="isImport"
|
|
|
+ type="primary"
|
|
|
+ :loading="excelFlag"
|
|
|
+ @click="exportError()"
|
|
|
+ >
|
|
|
+ 下载失败记录
|
|
|
+ </el-button>
|
|
|
+ </span>
|
|
|
+ </el-dialog>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+// import XLSX from 'xlsx'
|
|
|
+// import XLSXStyle from 'xlsx-style-fixedver'
|
|
|
+import constant from '@/static/utils/constant'
|
|
|
+
|
|
|
+const XLSX = require('xlsx')
|
|
|
+const XLSXStyle = require('xlsx-style-fixedver')
|
|
|
+import axios from 'axios'
|
|
|
+import qs from 'qs'
|
|
|
+
|
|
|
+const defaultTitle = '批量导入'
|
|
|
+export default {
|
|
|
+ props: {
|
|
|
+ // 弹框状态
|
|
|
+ dialogVisible: { type: Boolean, default: false },
|
|
|
+ // 类型
|
|
|
+ importType: { type: String, default: '' },
|
|
|
+ // 上传说明
|
|
|
+ uploadTitle: { type: Array, default: () => ([]) },
|
|
|
+ // 名称
|
|
|
+ importTitle: { type: String, default: '' }
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ fileUrlList: [],
|
|
|
+ tableData: [],
|
|
|
+ title: defaultTitle.repeat(1),
|
|
|
+ loading: false,
|
|
|
+ isImport: false,
|
|
|
+ file: null,
|
|
|
+ successCount: 0,
|
|
|
+ errorCount: '',
|
|
|
+ excelFlag: false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ importFile() {
|
|
|
+ this.loading = true
|
|
|
+ this.$axios({
|
|
|
+ headers: {
|
|
|
+ 'Content-Type': 'multipart/form-data'
|
|
|
+ },
|
|
|
+ method: 'post',
|
|
|
+ url: this.$constant.BASE_URI + '/CustomerManagementController/handleImport',
|
|
|
+ data: this.file
|
|
|
+ }).then((res) => {
|
|
|
+ this.loading = false
|
|
|
+ if (res.data.code === 200) {
|
|
|
+ this.$message({
|
|
|
+ message: '上传成功',
|
|
|
+ type: 'success'
|
|
|
+ })
|
|
|
+ // this.$emit('cancelUpload', true)
|
|
|
+ this.successCount = res.data.data.successCount
|
|
|
+ this.errorCount = res.data.data.errorCount
|
|
|
+ res.data.data.errorList.forEach(item => {
|
|
|
+ const json = this.getItemJson(item)
|
|
|
+ this.tableData.push(json)
|
|
|
+ })
|
|
|
+ this.isImport = true
|
|
|
+ console.log('上传成功....')
|
|
|
+ } else {
|
|
|
+ this.$message({
|
|
|
+ message: res.data.msg,
|
|
|
+ type: 'error'
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }).catch((err, x) => {
|
|
|
+ console.log('biz user list error', err, x)
|
|
|
+ })
|
|
|
+ },
|
|
|
+ closeUpload() {
|
|
|
+ // 关闭弹窗
|
|
|
+ this.$emit('cancelUpload')
|
|
|
+ },
|
|
|
+ uploadFile(param) {
|
|
|
+ const formParam = new FormData()
|
|
|
+ formParam.append('file', param.file)
|
|
|
+ this.file = formParam
|
|
|
+ this.fileUrlList.push({ name: param.file.name })
|
|
|
+ },
|
|
|
+ handlePictureRemove(file, fileUrlList) {
|
|
|
+ const index = fileUrlList.indexOf(file)
|
|
|
+ fileUrlList.splice(index, 1)
|
|
|
+ this.file = null
|
|
|
+ },
|
|
|
+ exportError() {
|
|
|
+
|
|
|
+ },
|
|
|
+ s2ab(s) {
|
|
|
+ var cuf
|
|
|
+ var i
|
|
|
+ if (typeof ArrayBuffer !== 'undefined') {
|
|
|
+ cuf = new ArrayBuffer(s.length)
|
|
|
+ var view = new Uint8Array(cuf)
|
|
|
+ for (i = 0; i !== s.length; i++) {
|
|
|
+ view[i] = s.charCodeAt(i) & 0xFF
|
|
|
+ }
|
|
|
+ return cuf
|
|
|
+ } else {
|
|
|
+ cuf = new Array(s.length)
|
|
|
+ for (i = 0; i !== s.length; ++i) {
|
|
|
+ cuf[i] = s.charCodeAt(i) & 0xFF
|
|
|
+ }
|
|
|
+ return cuf
|
|
|
+ }
|
|
|
+ },
|
|
|
+ downloadTemplate() {
|
|
|
+ const outData = []
|
|
|
+ const title = []
|
|
|
+ title.push('小区名称')
|
|
|
+ title.push('分期名称')
|
|
|
+ title.push('选房日')
|
|
|
+ title.push('批次号')
|
|
|
+ title.push('选房号')
|
|
|
+ title.push('姓名')
|
|
|
+ title.push('身份证号')
|
|
|
+ title.push('手机号')
|
|
|
+ title.push('关系')
|
|
|
+ title.push('顺序号')
|
|
|
+ outData.push(title)
|
|
|
+ const outSize = []
|
|
|
+ title.forEach(item => {
|
|
|
+ if (item.length > 4) {
|
|
|
+ outSize.push({
|
|
|
+ wch: 30
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ outSize.push({
|
|
|
+ wch: 15
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ const fileName = '导入模版'
|
|
|
+ const ws = XLSX.utils.aoa_to_sheet(outData)
|
|
|
+ ws['!cols'] = outSize
|
|
|
+ ws['!rows'] = []
|
|
|
+ const wb = XLSX.utils.book_new()
|
|
|
+ XLSX.utils.book_append_sheet(wb, ws, fileName)
|
|
|
+ const tmpDown = new Blob([
|
|
|
+ this.s2ab(
|
|
|
+ XLSXStyle.write(wb, {
|
|
|
+ bookType: 'xlsx',
|
|
|
+ bookSST: true,
|
|
|
+ type: 'binary',
|
|
|
+ cellStyles: true
|
|
|
+ })
|
|
|
+ )
|
|
|
+ ])
|
|
|
+ const elink = document.createElement('a')
|
|
|
+ elink.download = decodeURIComponent(fileName + '.xlsx')
|
|
|
+ elink.style.display = 'none'
|
|
|
+ elink.href = URL.createObjectURL(tmpDown)
|
|
|
+ document.body.appendChild(elink)
|
|
|
+ elink.click()
|
|
|
+ URL.revokeObjectURL(elink.href) // 释放URL 对象
|
|
|
+ document.body.removeChild(elink)
|
|
|
+ },
|
|
|
+ handleClose() {
|
|
|
+ this.dialogVisible = false
|
|
|
+ },
|
|
|
+ downloadExcel(blobPart, filename) {
|
|
|
+ const blob = new Blob([blobPart], {
|
|
|
+ type: 'application/vnd.ms-excel'
|
|
|
+ })
|
|
|
+ // console.log('downloadExcel', blob.size)
|
|
|
+ // 创建一个超链接,将文件流赋进去,然后实现这个超链接的单击事件
|
|
|
+ const elink = document.createElement('a')
|
|
|
+ elink.download = decodeURIComponent(filename)
|
|
|
+ elink.style.display = 'none'
|
|
|
+ elink.href = URL.createObjectURL(blob)
|
|
|
+ document.body.appendChild(elink)
|
|
|
+ elink.click()
|
|
|
+ URL.revokeObjectURL(elink.href) // 释放URL 对象
|
|
|
+ document.body.removeChild(elink)
|
|
|
+ },
|
|
|
+ getItemJson(item) {
|
|
|
+ item.groupNameStr = item.groupName.replace('{', '').replace('}', '')
|
|
|
+ item.discNameStr = item.discName ? item.discName.replace('{', '').replace('}', '') : ''
|
|
|
+ item.batchNumberStr = item.batchNumber ? item.batchNumber.replace('{', '').replace('}', '') : ''
|
|
|
+ item.roomSelectionNumberStr = item.roomSelectionNumber ? item.roomSelectionNumber.replace('{', '').replace('}', '') : ''
|
|
|
+ item.buyerNameStr = item.buyerName ? item.buyerName.replace('{', '').replace('}', '') : ''
|
|
|
+ return item
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+<style lang="scss">
|
|
|
+.uploadCost {
|
|
|
+ .el-card__body {
|
|
|
+ padding: 0 !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ .uploadtitle {
|
|
|
+ color: #C5C5C5;
|
|
|
+ }
|
|
|
+
|
|
|
+ .el-dialog__body {
|
|
|
+ padding: 15px !important;
|
|
|
+ color: #606266 !important;
|
|
|
+ font-size: 14px !important;
|
|
|
+ word-break: break-all !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ .el-upload {
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+
|
|
|
+ .el-upload-list {
|
|
|
+ li {
|
|
|
+ text-align: center;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .mgauto {
|
|
|
+ display: block;
|
|
|
+ margin: 0 auto;
|
|
|
+ }
|
|
|
+
|
|
|
+ .mtmb16 {
|
|
|
+ margin-top: 16px;
|
|
|
+ margin-bottom: 16px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .txtcenter {
|
|
|
+ text-align: center;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+</style>
|