LAPTOP-FO2T5SIU\35838 vor 9 Monaten
Ursprung
Commit
a56a06425d

+ 2 - 1
package.json

@@ -76,7 +76,8 @@
         "vuex": "3.1.0",
         "vuex-solidification": "^0.2.2",
         "webpack": "^4.43.0",
-        "xlsx": "^0.18.5"
+        "xlsx": "^0.18.5",
+        "xlsx-style-fixedver": "^1.0.3"
     },
     "devDependencies": {
         "@babel/core": "7.0.0",

BIN
src/assets/excelicon.png


+ 527 - 0
src/views/parkAssets/component/uploadCost.vue

@@ -0,0 +1,527 @@
+<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"
+      append-to-body
+      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="companyName">
+            <template v-slot="scope">
+              <span>{{ scope.row.qymc }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column align="center" label="统一信用代码" prop="unifiedCreditCode">
+            <template v-slot="scope">
+              <span>{{ scope.row.shxydm }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column align="center" label="注册资金" prop="taxation">
+            <template v-slot="scope">
+              <span>{{ scope.row.zczj }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column align="center" label="入驻类型" prop="revenue">
+            <template v-slot="scope">
+              <span>{{ scope.row.settleInType }}</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"
+          @click="importFile()"
+          class="ch-button-else"
+        >导入</el-button>
+        <el-button
+          v-if="isImport"
+          type="primary"
+          @click="exportError()"
+        >
+          下载失败记录
+        </el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+// import XLSX from 'xlsx'
+// import XLSXStyle from 'xlsx-style-fixedver'
+const XLSX = require('xlsx')
+const XLSXStyle = require('xlsx-style-fixedver')
+
+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: ''
+        }
+    },
+    methods: {
+        importFile() {
+            if (this.importType === 'groupInsert') {
+                this.importGroup()
+            }
+            if (this.importType === 'FQInsert') {
+                this.importFQ()
+            }
+        },
+        importGroup() {
+            this.loading = true
+            this.$axios({
+                headers: {
+                    'Content-Type': 'multipart/form-data'
+                },
+                method: 'post',
+                url: this.$constant.BASE_URI + '/ParkInfoController/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
+                    this.tableData = res.data.data.errorList || []
+                    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)
+            })
+        },
+        importFQ() {
+            this.loading = true
+            this.$axios({
+                headers: {
+                    'Content-Type': 'multipart/form-data'
+                },
+                method: 'post',
+                url: this.$constant.BASE_URI + '/ParkFloorDiscController/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
+                    this.tableData = res.data.data.errorList || []
+                    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() {
+            if (this.importType === 'FQInsert') {
+                this.exportErrorFQ()
+            }
+        },
+        exportErrorFQ() {
+            if (!this.tableData.length) {
+                this.$message.error('失败记录为空!')
+                return
+            }
+            const outData = []
+            const title = []
+            title.push('楼盘/小区名称')
+            title.push('分期名称')
+            title.push('房屋买卖单价(元/㎡)')
+            title.push('物业费单价(元/㎡)')
+            title.push('住宅专项维修资金(元/㎡)')
+            title.push('认购金(元)')
+            title.push('共持比例')
+            title.push('支付方式')
+            outData.push(title)
+            const errorFiled = []
+            this.tableData.forEach((item, index) => {
+                const jsonArray = []
+                jsonArray.push(item.groupName)
+                jsonArray.push(item.name)
+                jsonArray.push(item.unitPrice)
+                jsonArray.push(item.propertyUnitPrice)
+                jsonArray.push(item.maintenanceFunds)
+                jsonArray.push(item.subscriptionFunds)
+                jsonArray.push(item.proportion)
+                jsonArray.push(item.reason)
+                outData.push(jsonArray)
+            })
+            const outSize = []
+            title.forEach(item => {
+                if (item.length > 4) {
+                    outSize.push({
+                        wch: 30
+                    })
+                } else {
+                    outSize.push({
+                        wch: 15
+                    })
+                }
+            })
+            const fileName = '失败记录导出 ' + new Date().Format('yyyy-MM-dd hh:mm')
+            const ws = XLSX.utils.aoa_to_sheet(outData)
+            ws['!cols'] = outSize
+            ws['!rows'] = []
+            if (errorFiled.length) {
+                errorFiled.forEach(item => {
+                    if (!ws[item]) {
+                        ws[item] = {
+                            v: '',
+                            t: 's',
+                            s: {
+                                fill: {
+                                    bgColor: { indexed: 64 }, fgColor: { rgb: 'FF0000' }
+                                },
+                                font: {
+                                    color: { rgb: 'FFFFFF' }
+                                }
+                            }
+                        }
+                    } else {
+                        ws[item].s = {
+                            fill: {
+                                bgColor: { indexed: 64 }, fgColor: { rgb: 'FF0000' }
+                            },
+                            font: {
+                                color: { rgb: 'FFFFFF' }
+                            }
+                        }
+                    }
+                })
+            }
+            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)
+        },
+        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() {
+            if (this.importType === 'groupInsert') {
+                this.downloadGroupTemplate()
+            }
+            if (this.importType === 'FQInsert') {
+                this.downloadFQTemplate()
+            }
+        },
+        downloadGroupTemplate() {
+            const outData = []
+            const title = []
+            title.push('楼盘/小区名称')
+            title.push('性质')
+            title.push('预销售许可证编号')
+            title.push('开发公司')
+            title.push('总建筑面积(㎡)')
+            title.push('总用地面积(㎡)')
+            title.push('立项批文')
+            title.push('工程规划许可证')
+            title.push('施工许可证')
+            title.push('土地证号')
+            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
+                    })
+                }
+            })
+            let fileName = '模板'
+            if (this.importTitle.includes('批量导入')) {
+                fileName = '导入模板'
+            }
+            if (this.importTitle.includes('批量更新')) {
+                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)
+        },
+        downloadFQTemplate() {
+            const outData = []
+            const title = []
+            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
+                    })
+                }
+            })
+            let fileName = '模板'
+            if (this.importTitle === '批量导入') {
+                fileName = '导入模板'
+            }
+            if (this.importTitle === '批量更新') {
+                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
+        }
+    }
+}
+</script>
+<style lang="scss">
+.uploadCost {
+  .el-card__body {
+    padding: 0 !important;
+  }
+
+  .uploadtitle {
+    //color: #C5C5C5;
+    color: #303133;
+  }
+
+  .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;
+    }
+
+    .mgauto2 {
+        display: flex;
+        justify-content: center;
+        margin: 0 auto;
+    }
+
+    .mtmb16 {
+        margin-top: 16px;
+        margin-bottom: 16px;
+    }
+
+    .txtcenter {
+        text-align: center;
+    }
+
+}
+
+</style>

+ 35 - 7
src/views/parkAssets/parkFloorDisc/index.vue

@@ -37,8 +37,8 @@
         <el-row class="handle-box" style="margin-bottom: 10px">
           <el-col :span="24">
             <el-input v-model="queryParam.name" size="small" placeholder="楼盘名称" class="ch-input-size" @keyup.enter.native="handleSearch()" />
-            <el-button size="small" class="ch-button-add" style="float: right; margin-top: 4px; margin-right: 10px;" @click="handleAddFQ()"><i class="el-icon-menu" />&nbsp;楼盘分期导入</el-button>
-            <el-button size="small" class="ch-button-add" style="float: right; margin-top: 4px; margin-right: 10px;" @click="handleAdd()"><i class="el-icon-menu" />&nbsp;楼盘导入</el-button>
+            <el-button size="small" class="ch-button-add" style="float: right; margin-top: 4px; margin-right: 10px;" @click="batchFQImport()"><i class="el-icon-menu" />&nbsp;楼盘分期导入</el-button>
+            <el-button size="small" class="ch-button-add" style="float: right; margin-top: 4px; margin-right: 10px;" @click="batchImport()"><i class="el-icon-menu" />&nbsp;楼盘导入</el-button>
             <el-button size="small" class="ch-button-add" style="float: right; margin-top: 4px; margin-right: 10px;" @click="handleAddFQ()"><i class="el-icon-menu" />&nbsp;新增分期</el-button>
             <el-button size="small" class="ch-button-add" style="float: right; margin-top: 4px; margin-right: 10px;" @click="handleAdd()"><i class="el-icon-menu" />&nbsp;新增楼盘</el-button>
             <el-button size="small" class="ch-button" style="float: right;margin-top: 4px" @click="handleSearch()"><i class="el-icon-menu" />&nbsp;查询</el-button>
@@ -436,6 +436,15 @@
       </div>
     </el-dialog>
 
+    <!-- 批量导入 -->
+    <upload-cost
+      v-if="importVisible"
+      :dialog-visible="importVisible"
+      :import-type="importType"
+      :upload-title="uploadTitle"
+      :import-title="importTitle"
+      @cancelUpload="cancelImport"
+    />
   </div>
 </template>
 
@@ -444,13 +453,14 @@ import Base from '@/views/base/base'
 import BaseData from '@/views/base/baseData'
 import BaseDept from '@/views/base/baseDept'
 import { upload } from '@/static/utils/channel'
+import uploadCost from '@/views/parkAssets/component/uploadCost.vue'
 
 import Constant from '@/static/utils/constant'
 import common from '@/static/utils/common'
 // import textEdit from '../../textEdit/index'
 export default {
     name: 'User',
-    components: {},
+    components: {uploadCost},
     mixins: [Base, BaseData, BaseDept],
     data() {
         return {
@@ -489,7 +499,12 @@ export default {
             companyOptions: [],
             dialogVisible: false,
             dialogFQVisible: false,
-            isView: false
+            isView: false,
+            // 批量导入
+            importVisible: false,
+            importType: '',
+            importTitle: '',
+            uploadTitle: []
         }
     },
     mounted() {
@@ -771,12 +786,25 @@ export default {
             _this.baseFQRequest('getById', { id: val.id }).then((res) => {
                 _this.formLP = res.data
                 _this.formLP.paymentMethods = res.data.paymentMethods + ''
-                // res.data.houseTypeStr.forEach(item => {
-                //     console.log('item', item)
-                // })
                 _this.$set(_this.formLP, 'dynamicItem', JSON.parse(res.data.houseTypeStr))
             })
         },
+        batchImport() {
+            this.importVisible = true
+            this.importType = 'groupInsert'
+            this.importTitle = '小区批量导入'
+        },
+        batchFQImport() {
+            this.importVisible = true
+            this.importType = 'FQInsert'
+            this.importTitle = '分期批量导入'
+        },
+        cancelImport(refresh) {
+            this.importVisible = false
+            this.importType = ''
+            this.getTreeData()
+            this.getData()
+        },
         // 请求封装,继承类中调用,必须存在
         baseRequest: function(opUrl, postData) {
             return this.$channel.baseRequest('ParkInfoController', opUrl, postData, 'User')