
1.組件,導入數據,一定要先下載模版,然后點擊導入數據,會提示導入成功條數,失敗條數
<template>
<div class="excel" >
<el-dialog
:visible.sync="centerDialogVisible"
:title="titleName"
:close-on-click-modal="false"
:before-close="beforePausClose"
width="1040px"
>
<div style="min-height: 550px;padding: 0 20px">
<div class="excel-header">
<el-select v-show="templateShow" v-model="value" placeholder="請選擇導入的模板" @change="changeTemplate($event)">
<el-option
v-for="item in options"
:key="item.template_table_name"
:label="item.template_description"
:value="item.template_table_name"/>
</el-select>
<el-button :disabled="selectPower" class="diybut" @click="btnClick">選擇Excel文件</el-button>
<el-button :disabled="exportBtn" class="diybut" @click="exportExcel">下載模板</el-button>
<el-checkbox v-show="checkBoxMutiplian" v-model="picSubmitShow">將圖片保存到系統中</el-checkbox>
<div style="margin: 0 auto;display: inline-block;float: right">
<el-button :disabled="exportPower" class="diybut" @click="saveDataBase">導入</el-button>
<el-button :disabled="canclePower" class="diybut" @click="cancleTemplate">關閉</el-button>
</div>
</div>
<div v-show="errorPromptShow" class="error-prompt" style="max-height: 100px;overflow-y: auto">
<p v-for="(item, index) in errorList" :key="index" style="color: red;height: 20px;line-height: 14px;margin: 0">
{{ item }}
</p>
</div>
<!-- 手動編寫的滾動條-->
<div v-show="progressDebugShow" style="width: 100%;height: 20px;background: #4FA6E0;position: relative;border-radius: 5px;line-height: 20px;margin-bottom: 20px;overflow: hidden">
<div class="slider" style=" position:absolute;left: 10px;top: 1px;">
<div style="width: 10px;height: 10px;line-height: 10px;border-radius: 5px;background: white;display: inline-block" />
<div style="width: 10px;height: 10px;line-height: 10px;border-radius: 5px;background: white;display: inline-block" />
<div style="width: 10px;height: 10px;line-height: 10px;border-radius: 5px;background: white;display: inline-block" />
</div>
</div>
<div>
<p v-show="resultShow" style="height: 30px;line-height: 30px;margin-top: 10px">
<span>成功:{{ successCount }}條</span>
<span style="margin: 0 20px">失敗:{{ failCount }}條</span>
<el-button v-show="failCount !== 0" type="text" @click="exportFailData">下載導入失敗數據</el-button>
</p>
</div>
<!-- 表格-->
<div
v-loading="loading"
style="width:100%;overflow-x: auto;min-height: 425px"
element-loading-text="保存中,請稍等"
element-loading-spinner="el-icon-loading">
<table
border="1px solid gray"
style="border-collapse: collapse;width: 960px"
>
<!--顯示數據庫查出來的標題-->
<tr style="text-align: center;height: 30px;line-height: 0;width: 1000px;background: #F4F4F4">
<td v-for="(item ,index) in arr" :key="index" style=" height: 40px;">
<div class="tableWidth" style="min-width: 100px;white-space:nowrap;">
<span v-show="templateAllData[index].attribute_not_null" style="color: red">*</span>{{ item }}
<input v-show="picSubmitShow" ref="mutiCheck" :value="item" v-model="checked" type="checkbox" style="margin-left: 10px;display: inline-block;position: relative;top: 3px">
</div>
</td>
</tr>
<!--從excel中獲取的標題-->
<tr style="height: 40px;overflow: hidden;line-height: 0">
<td v-for="(item ,index) in arr" :key="index" style="width: 30px;white-space:nowrap;">
<select v-model="changeList[item]" :value="item" class="selectedList" @change="changeListValue(index)">
<option v-for="(item1, index1) in arr1" :key="index1" :value="item1" >
{{ item1 }}
</option>
</select>
</td>
</tr>
<!--excel中獲取的具體數據展示-->
<tr v-for="(item, index) in tableData" :key="index">
<td v-for="(item1, index1) in arr" :key="index1" style="height: 34px;">
<div :title="item[item1]" style="width: 150px;white-space:nowrap;overflow: hidden;line-height: 2;height: 20px">
{{ item[item1] }}
</div>
</td>
</tr>
<tr v-show="tableShow" class="tableShow">
<td v-for="(item1, index1) in arr" :key="index1" style="height: 34px;" />
</tr>
<tr v-show="tableShow" class="tableShow">
<td v-for="(item1, index1) in arr" :key="index1" style="height: 34px;" />
</tr>
<tr v-show="tableShow" class="tableShow">
<td v-for="(item1, index1) in arr" :key="index1" style="height: 34px;" />
</tr>
<tr v-show="tableShow" class="tableShow">
<td v-for="(item1, index1) in arr" :key="index1" style="height: 34px;" />
</tr>
<tr v-show="tableShow" class="tableShow">
<td v-for="(item1, index1) in arr" :key="index1" style="height: 34px;" />
</tr>
<tr v-show="tableShow" class="tableShow">
<td v-for="(item1, index1) in arr" :key="index1" style="height: 34px;" />
</tr>
<tr v-show="tableShow" class="tableShow">
<td v-for="(item1, index1) in arr" :key="index1" style="height: 34px;" />
</tr>
<tr v-show="tableShow" class="tableShow">
<td v-for="(item1, index1) in arr" :key="index1" style="height: 34px;" />
</tr>
<tr v-show="tableShow" class="tableShow">
<td v-for="(item1, index1) in arr" :key="index1" style="height: 34px;" />
</tr>
<tr v-show="tableShow" class="tableShow">
<td v-for="(item1, index1) in arr" :key="index1" style="height: 34px;" />
</tr>
</table>
</div>
<p style="text-align: center;line-height: 50px;margin-bottom: 0">(預覽數據)</p>
</div>
</el-dialog>
<input
accept=".csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel"
class="input-file"
type="file"
@change="exportData"
>
<el-button
:type="buttonType"
:disabled="disabled"
:icon="buttonIcon"
:size="buttonSize"
@click="getAllTemplateData">
{{ titleName }}
</el-button>
<el-dialog
:visible.sync="centerDialogVisibleTwo"
title="導入結果"
width="40%"
center>
<p style="text-align: center">成功條數:{{ successCount }}</p>
<p style="text-align: center">失敗條數:{{ failCount }}</p>
<span slot="footer" class="dialog-footer">
<el-button @click="centerDialogVisibleTwo = false">關閉</el-button>
<el-button v-show="exportFale" type="primary" @click="exportFailData">導出失敗數據</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { getTemplate, getTemplateHeader, saveExcel, uploadPicToQn, getFailData } from '@/api/excel'
import XLSX from 'xlsx'
import { mapGetters } from 'vuex'
import $ from 'jquery'
export default {
props: {
disabled: {
type: Boolean,
default: false // 是否有禁用權限
},
titleName: {
type: String,
default: '批量導入商品信息' // 傳入不同的標題
},
actionName: {
type: String,
default: 'commodity' // commodity商品,commodity_specification商品規格,sales_team,銷售組 customer_department 客戶單位 customer客戶 根據不同使用傳入不同的數據
},
buttonType: {
type: String,
default: '' // 控制Button的類型
},
buttonIcon: {
type: String,
default: '' // 控制Button中的圖標 (僅支持element-ui中自帶圖標)
},
buttonSize: {
type: String,
default: '' // 控制Button的尺寸
}
},
data() {
return {
arr: [], // 放從數據庫獲取的標題
arr1: [], // 導入的excel中的標題
tableData: [], // 用於循環展示的值
copyTableData: [], // 用於保存最初的json數據。以便進行數據更換
changeList: {}, // 動態綁定下拉框的值
submitLastValue: [], // 最終提交的值
centerDialogVisible: false, // 對話框1顯示
centerDialogVisibleTwo: false, // 對話框2顯示
options: [], // 模板列表
value: '', // 選擇的模板值
templateAllData: [],
checked: [], // 用於圖片轉換的輸入框列表
debugCount: 0,
copyTableDataTwo: [], // 用於下拉框切換時的數據展示
picSubmitShow: false, // 是否顯示圖片轉換輸入框
template: [],
oneArr: 0, // 用於在圖片轉換時判斷是否轉換完成
twoArr: 0, // 用於在圖片轉換時判斷是否轉換完成
count: 0,
loading: false, // 加載圖標
successCount: 0, // 成功條數
failCount: 0, // 失敗條數
exportBtn: true, // 導入按鈕權限
exportFale: true, // 用於判斷是否導出失敗數據
templateShow: true,
checkBoxMutiplian: false,
progressTimer: '',
errorList: [], // 前端校驗錯誤提示
progress: 0, // 進度條百分比
progressDebugShow: false, // 滾動條是否顯示
errorPromptShow: false, // 校驗失敗提示是否顯示
resultShow: false, // 控制導入結果顯示
selectPower: false, // 選擇模板權限
exportPower: false, // 導入按鈕權限
canclePower: false, // 關閉按鈕權限
iconClickPower: 0, // 控制點擊對話框關閉圖標是否執行
tableShow: true // 顯示空表格
}
},
computed: {
...mapGetters([
'business_group_id'
])
},
watch: {
debugCount: function(newV, oldV) {
// if (newV === this.submitLastValue.length * this.checked.length) {
// this.saveResult()
// }
},
twoArr: function(newV, oldV) {
if (this.checked.length > 0) {
setTimeout(this.PicTransfer, 100)
}
},
tableData: function(newV, oldV) {
// if (this.tableData.length > 0) {
// this.tableShow = false
// } else {
// this.tableShow = true
// }
}
},
beforeDestroy() {
clearInterval(this.progressTimer)
},
methods: {
getAllTemplateData: function() {
this.arr1 = []
this.arr = []
this.value = ''
this.tableData = []
this.copyTableDataTwo = []
this.copyTableData = []
this.centerDialogVisible = true
this.progressDebugShow = false
this.resultShow = false
this.count = 0
this.oneArr = 0
this.twoArr = 0
this.checked = []
this.picSubmitShow = false
this.getDefaultArr()
},
// 獲取數據庫模板數據
getDefaultArr: function() {
let group_id = ''
if (this.actionName === 'commodity') {
group_id = this.business_group_id
}
getTemplate(group_id, this.actionName)
.then(res => {
this.options = res.data
if (this.options.length === 1) {
this.value = this.options[0].template_table_name
this.templateShow = false
this.changeTemplate(this.value)
}
})
.catch(() => {})
},
// 點擊對話框的X圖標事件
beforePausClose() {
if (this.iconClickPower === 1) {
return
} else {
this.centerDialogVisible = false
}
},
// 取消
cancleTemplate: function() {
this.value = ''
this.arr = []
this.arr1 = []
this.value = ''
this.tableData = []
this.centerDialogVisible = false
this.centerDialogVisibleTwo = false
this.exportBtn = true
clearInterval(this.progressTimer)
document.querySelector('.input-file').value = ''
},
// 切換模板時
changeTemplate: function(data) {
if (data !== '') {
this.arr = []
getTemplateHeader(data)
.then(res => {
this.templateAllData = res.data.data
this.checkBoxMutiplian = res.data.need_save_pictures
this.template = []
const obj = {}
res.data.data.forEach((item, index) => {
obj[item.attribute_name] = ''
this.arr.push(item.attribute_name)
})
this.template.push(obj)
this.exportBtn = false
// 動態添加changeList的值
for (let i = 0; i < this.arr.length; i++) {
this.changeList[this.arr[i]] = this.arr[i]
}
})
.catch(() => {})
}
},
// 圖片轉換 將有src屬性並且為img的值時,將src中的值改變為后台傳過來的值
PicTransfer: function() {
const a = this.submitLastValue[this.twoArr][this.checked[this.oneArr]]
if (typeof a === 'string' && a.indexOf('<img') > -1 && a.indexOf('src') > -1) {
const arrimg = []
// 截取出相應的src屬性值
a.replace(/<img [^>]*src=['"]([^'"]+)[^>]*>/gi, function(match, capture) {
arrimg.push(capture)
})
uploadPicToQn(arrimg)
.then(res => {
for (let h = 0; h < arrimg.length; h++) {
// this.tableData[j][this.checked[i]] = this.tableData[j][this.checked[i]].replace(arrimg[h], res.data[h].pic_name)
this.submitLastValue[this.twoArr][this.checked[this.oneArr]] = this.submitLastValue[this.twoArr][this.checked[this.oneArr]].replace(arrimg[h], res.data[h].pic_name)
this.count += 1
}
this.debugCount += 1
if (this.oneArr === this.checked.length - 1 && this.twoArr === this.submitLastValue.length - 1) { // 判斷src的值是否轉換完成
this.saveResult()
} else if (this.twoArr < this.submitLastValue.length - 1) {
this.twoArr += 1
} else {
this.oneArr += 1
this.twoArr = 0
}
})
.catch(() => {
if (this.oneArr === this.checked.length - 1 && this.twoArr === this.submitLastValue.length - 1) {
this.saveResult()
} else if (this.twoArr < this.submitLastValue.length - 1) {
this.twoArr += 1
} else {
this.oneArr += 1
this.twoArr = 0
}
})
} else {
this.debugCount += 1
if (this.oneArr === this.checked.length - 1 && this.twoArr === this.submitLastValue.length - 1) {
this.saveResult()
} else if (this.twoArr < this.submitLastValue.length - 1) {
this.twoArr += 1
} else {
this.oneArr += 1
this.twoArr = 0
}
}
// this.debugCount = 0
// for (let i = 0; i < this.checked.length; i++) {
// for (let j = 0; j < this.submitLastValue.length; j++) {
// const a = this.submitLastValue[j][this.checked[i]]
// if (typeof a === 'string' && a.indexOf('<img') > -1 && a.indexOf('src') > -1) {
// const arrimg = []
// // 截取出相應的src屬性值
// a.replace(/<img [^>]*src=['"]([^'"]+)[^>]*>/gi, function(match, capture) {
// arrimg.push(capture)
// })
// uploadPicToQn(arrimg)
// .then(res => {
// for (let h = 0; h < arrimg.length; h++) {
// // this.tableData[j][this.checked[i]] = this.tableData[j][this.checked[i]].replace(arrimg[h], res.data[h].pic_name)
// this.submitLastValue[j][this.checked[i]] = this.submitLastValue[j][this.checked[i]].replace(arrimg[h], res.data[h].pic_name)
// }
// this.debugCount += 1
// // this.resultData()
// })
// .catch(() => {})
// } else {
// this.debugCount += 1
// }
// }
// }
},
btnClick() {
if (this.value) {
this.progressDebugShow = false
clearInterval(this.progressTimer)
this.resultShow = false
document.querySelector('.input-file').click()
} else {
this.$message.warning('請先選擇模板')
}
},
// 導入本地文件后取值
exportData(event) {
if (!event.currentTarget.files.length) {
return
}
const that = this
// 拿取文件對象
const f = event.currentTarget.files[0]
document.querySelector('.input-file').value = ''
// 用FileReader來讀取
const reader = new FileReader()
// 重寫FileReader上的readAsBinaryString方法
FileReader.prototype.readAsBinaryString = function(f) {
let binary = ''
let wb = '' // 讀取完成的數據
let outdata = [] // 你需要的數據
const reader = new FileReader()
reader.onload = function(e) {
// 讀取成Uint8Array,再轉換為Unicode編碼(Unicode占兩個字節)
var bytes = new Uint8Array(reader.result)
var length = bytes.byteLength
for (let i = 0; i < length; i++) {
binary += String.fromCharCode(bytes[i])
}
// 接下來就是xlsx了,具體可看api
wb = XLSX.read(binary, {
type: 'binary'
})
that.arr1 = []
that.tableData = []
that.copyTableDataTwo = []
that.copyTableData = []
outdata = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]])
// 獲取excel表格中的所有標題
for (let i = 0; i < outdata.length; i++) {
for (const j in outdata[i]) {
let num = 0
for (let k = 0; k < that.arr1.length; k++) {
if (that.arr1[k] === j) {
num += 1
}
}
if (num === 0) {
that.arr1.push(j)
}
}
}
that.arr1.unshift(' ')
// 字段不存在或者沒有值時,則將它的值設置為空
for (let i = 0; i < outdata.length; i++) {
for (let j = 0; j < that.arr.length; j++) {
if (!outdata[i][that.arr[j]] && outdata[i][that.arr[j]] !== 0) {
outdata[i][that.arr[j]] = ''
}
}
}
// that.arr1 = []
// for (const i in outdata[0]) {
// that.arr1.push(i)
// }
// console.log(outdata[0])
// console.log(that.arr1)
for (let i = 0; i < 10 && i < outdata.length; i++) {
const changeValue = JSON.stringify(outdata[i])
that.tableData.push(JSON.parse(changeValue))
that.copyTableData.push(JSON.parse(changeValue))
}
// that.tableData = outdata
// 由於數組和對象是引用類型,在賦值時候會將地址也一起賦值,當改變一個值得時候會將另外一個值也改變,所以先轉為字符串再轉回來(基本類型只會傳值不會傳地址)
// that.copyTableData = JSON.stringify(outdata)
that.copyTableDataTwo = JSON.stringify(outdata)
// that.copyTableData = JSON.parse(that.copyTableData)
that.copyTableDataTwo = JSON.parse(that.copyTableDataTwo)
// 如果少於10行的補空格顯示十行
$('.tableShow').removeClass('hideTr')
if (outdata.length < 10) {
for (let i = 0; i < outdata.length; i++) {
$('.tableShow').eq(i).addClass('hideTr')
}
} else {
$('.tableShow').addClass('hideTr')
}
that.resultData()
that.centerDialogVisible = true
// 自定義方法向父組件傳遞數據
}
reader.readAsArrayBuffer(f)
}
reader.readAsBinaryString(f)
},
// 下拉框的值改變后改變對應的值
changeListValue(index) {
// console.log(index) // 下標
// console.log(this.arr[index])
// console.log(this.changeList[this.arr[index]]) // 下拉框改變后的值
for (var i = 0; i < this.tableData.length; i++) {
this.tableData[i][this.arr[index]] = this.copyTableData[i][this.changeList[this.arr[index]]]
}
// console.log(this.tableData)
this.resultData()
},
resultData() {
this.submitLastValue = []
for (let i = 0; i < this.tableData.length; i++) {
const list = {}
for (let j = 0; j < this.arr.length; j++) {
if (!this.tableData[i][this.arr[j]]) {
list[this.arr[j]] = ''
} else {
list[this.arr[j]] = this.tableData[i][this.arr[j]]
}
}
this.submitLastValue.push(list)
}
},
// 設置進度條定時器
setTimerProgress() {
const that = this
clearInterval(that.progressTimer)
that.progress = 0
that.progressTimer = setInterval(function() {
if (that.progress === 960) {
that.progress = 0
} else {
that.progress += 3
$('.slider').css('left', that.progress + 'px')
}
}, 20)
},
// 保存到數據庫中
saveDataBase() {
this.selectPower = true
this.canclePower = true
this.exportPower = true
this.loading = true
this.iconClickPower = 1
this.submitLastValue = []
this.resultShow = false
this.progressDebugShow = false
clearInterval(this.progressTimer)
for (let j = 0; j < this.copyTableDataTwo.length; j++) {
const obj = {}
for (let i = 0; i < this.arr.length; i++) {
if (this.copyTableDataTwo[j][this.changeList[this.arr[i]]] || this.copyTableDataTwo[j][this.changeList[this.arr[i]]] === 0) {
obj[this.arr[i]] = this.copyTableDataTwo[j][this.changeList[this.arr[i]]]
} else {
obj[this.arr[i]] = ''
}
}
this.submitLastValue.push(obj)
}
if (this.checked.length && this.checked.length !== 0) {
this.PicTransfer()
} else {
this.saveResult()
}
},
// 校驗上傳數據
saveResult: function() {
// 上傳數據校驗
if (this.submitLastValue.length === 0) {
this.$message.warning('當前暫無數據')
this.loading = false
this.iconClickPower = 0
this.selectPower = false
this.canclePower = false
this.exportPower = false
return
}
this.errorList = []
for (let i = 0; i < this.templateAllData.length; i++) {
for (let j = 0; j < this.submitLastValue.length; j++) {
if (this.templateAllData[i].attribute_not_null === true && !this.submitLastValue[j][this.templateAllData[i].attribute_name] && this.submitLastValue[j][this.templateAllData[i].attribute_name] !== 0) {
// this.$message.error(this.templateAllData[i].attribute_name + '不能為空')
// this.loading = false
// return
this.errorList.push(this.templateAllData[i].attribute_name + '不能為空')
}
if ((this.templateAllData[i].attribute_not_null === 'true' || this.templateAllData[i].attribute_not_null === true) && this.templateAllData[i].attribute_type === 'int4' && (!(/(^[0-9]\d*$)/.test(this.submitLastValue[j][this.templateAllData[i].attribute_name])))) {
// 判斷長度 this.submitLastValue[j][this.templateAllData[i].attribute_name].toString().length > this.templateAllData[i].attribute_length
// this.$message.error(this.templateAllData[i].attribute_name + '傳輸類型應為整形')
// this.loading = false
// return
this.errorList.push(this.templateAllData[i].attribute_name + '傳輸類型應為整形')
}
if (this.templateAllData[i].attribute_type === 'numeric' && this.submitLastValue[j][this.templateAllData[i].attribute_name] && typeof this.submitLastValue[j][this.templateAllData[i].attribute_name] !== 'number') {
// this.$message.error(this.templateAllData[i].attribute_name + '傳輸類型為數字')
// this.loading = false
// return
this.errorList.push(this.templateAllData[i].attribute_name + '傳輸類型為數字')
}
if (this.templateAllData[i].attribute_type === 'date' && this.submitLastValue[j][this.templateAllData[i].attribute_name]) {
this.submitLastValue[j][this.templateAllData[i].attribute_name] = this.submitLastValue[j][this.templateAllData[i].attribute_name].toString()
this.submitLastValue[j][this.templateAllData[i].attribute_name] = this.submitLastValue[j][this.templateAllData[i].attribute_name].replace('年', '-')
this.submitLastValue[j][this.templateAllData[i].attribute_name] = this.submitLastValue[j][this.templateAllData[i].attribute_name].replace('月', '-')
this.submitLastValue[j][this.templateAllData[i].attribute_name] = this.submitLastValue[j][this.templateAllData[i].attribute_name].replace('日', '')
if (isNaN(Date.parse(this.submitLastValue[j][this.templateAllData[i].attribute_name]))) {
// this.$message.error(this.templateAllData[i].attribute_name + '格式有誤')
// this.loading = false
// return
this.errorList.push(this.templateAllData[i].attribute_name + '格式有誤')
}
}
if (this.templateAllData[i].attribute_type === 'bool') {
if (this.submitLastValue[j][this.templateAllData[i].attribute_name] === '是' ||
this.submitLastValue[j][this.templateAllData[i].attribute_name].toString().toLowerCase() === 't' ||
this.submitLastValue[j][this.templateAllData[i].attribute_name].toString().toLowerCase() === 'true' ||
this.submitLastValue[j][this.templateAllData[i].attribute_name].toString().toLowerCase() === 'yes' ||
this.submitLastValue[j][this.templateAllData[i].attribute_name].toString().toLowerCase() === '1') {
this.submitLastValue[j][this.templateAllData[i].attribute_name] = true
continue
}
if (this.submitLastValue[j][this.templateAllData[i].attribute_name] === '否' ||
this.submitLastValue[j][this.templateAllData[i].attribute_name].toString().toLowerCase() === 'f' ||
this.submitLastValue[j][this.templateAllData[i].attribute_name].toString().toLowerCase() === 'false' ||
this.submitLastValue[j][this.templateAllData[i].attribute_name].toString().toLowerCase() === 'no' ||
this.submitLastValue[j][this.templateAllData[i].attribute_name].toString().toLowerCase() === '0') {
this.submitLastValue[j][this.templateAllData[i].attribute_name] = false
continue
}
if (this.submitLastValue[j][this.templateAllData[i].attribute_name] === '') {
continue
}
// this.$message.error(this.templateAllData[i].attribute_name + '傳輸類型為布爾值')
// this.loading = false
// return
this.errorList.push(this.templateAllData[i].attribute_name + '傳輸類型為布爾值')
}
}
}
if (this.errorList.length === 0) {
this.progressDebugShow = true
this.setTimerProgress()
saveExcel(this.value, this.submitLastValue)
.then(res => {
this.successCount = parseInt(res.data.success)
this.failCount = parseInt(res.data.fail)
this.loading = false
this.iconClickPower = 0
this.selectPower = false
this.canclePower = false
this.exportPower = false
// this.tableData = []
// this.arr1 = []
// this.arr = []
// this.copyTableData = []
// this.copyTableDataTwo = []
// this.centerDialogVisible = false
// this.centerDialogVisibleTwo = true
this.resultShow = true
clearInterval(this.progressTimer)
this.progressDebugShow = false
if (parseInt(this.failCount) === 0) {
this.exportFale = false
} else {
this.exportFale = true
}
this.$emit('refleshParent') // 導入完成時在父組件刷新頁面
})
.catch(() => {
this.$message({
message: '上傳失敗',
type: 'error',
duration: 2 * 1000
})
this.loading = false
this.iconClickPower = 0
clearInterval(this.progressTimer)
this.progressDebugShow = false
})
} else {
// 數組去重
const saveArr = []
for (let i = 0; i < this.errorList.length; i++) {
let num = 0
for (let j = 0; j < i; j++) {
if (this.errorList[j] === this.errorList[i]) {
num = 1
break
}
}
if (num === 0) {
saveArr.push(this.errorList[i])
}
}
this.errorList = saveArr
this.errorPromptShow = true
this.loading = false
this.iconClickPower = 0
this.selectPower = false
this.canclePower = false
this.exportPower = false
}
},
// 獲取保存失敗的數據
exportFailData: function() {
getFailData(this.value)
.then(res => {
this.JSONToExcelConvertor(res.data, '未導入成功的數據')
// this.value = ''
}).catch()
},
// 導出數據到excel
exportExcel() {
let titleExcel = ''
// 獲取表格標題
for (let i = 0; i < this.options.length; i++) {
if (this.options[i].template_table_name === this.value) {
titleExcel = this.options[i].template_description
}
}
// this.tableToExcel(this.template)
this.JSONToExcelConvertor(this.template, titleExcel)
// this.exportPathMethod(this.template)
// this.JSONToExcelConvertor(this.submitLastValue, 'report', this.arr, ['id'])
},
exportPathMethod(data) {
// 要導出的json數據
var jsonData = []
// for (var i = 0; i < data.length; i++) {
// jsonData.push({
// index: i + 1,
// title: data[i].title,
// url: data[i].url,
// createTime: data[i].createTime
// })
// }
// 列標題,逗號隔開,每一個逗號就是隔開一個單元格
let str = `序號,標題,地址,時間\n`
// 增加\t為了不讓表格顯示科學計數法或者其他格式
for (let i = 0; i < jsonData.length; i++) {
for (const item in jsonData[i]) {
str += `${jsonData[i][item] + '\t'},`
}
str += '\n'
}
// encodeURIComponent解決中文亂碼
const uri = 'data:text/csv;charset=utf-8,\ufeff' + encodeURIComponent(str)
// 通過創建a標簽實現
var link = document.createElement('a')
link.href = uri
// 對下載的文件命名
link.download = 'json數據表.xls'
document.body.appendChild(link)
link.click()
},
// 只轉出excel標題
JSONToExcelConvertor(JSONData, FileName, title, filter) {
if (!JSONData) { return }
var arrData = typeof JSONData !== 'object' ? JSON.parse(JSONData) : JSONData
var excel = '<table>'
var row = '<tr>'
if (title) {
for (const i in title) {
row += "<th align='center'>" + title[i] + '</th>'
}
} else {
for (const i in arrData[0]) {
let num = 0
for (let j = 0; j < this.templateAllData.length; j++) {
if (i === this.templateAllData[j].attribute_name && this.templateAllData[j].attribute_not_null === true) {
num += 1
}
}
if (num === 0) {
row += "<th align='center'>" + '</span>' + i + '</th>'
} else {
// 導出時必填的有*號 row += "<th align='center'><span style='color: red'>" + '*' + '</span>' + i + '</th>'
row += "<th align='center'> " + i + '</th>'
}
}
}
excel += row + '</tr>'
// 如果有需要過濾的項則過濾
for (var i = 0; i < arrData.length; i++) {
let row = '<tr>'
for (var index in arrData[i]) {
if (filter) {
if (filter.indexOf(index) === -1) {
var value = arrData[i][index] == null ? '' : arrData[i][index]
row += '<td>' + value + '</td>'
}
} else {
const value = arrData[i][index] == null ? '' : arrData[i][index]
row += "<td align='center'>" + value + '</td>'
}
}
excel += row + '</tr>'
}
excel += '</table>'
var excelFile = "<html xmlns:o='urn:schemas-microsoft-com:office:office' xmlns:x='urn:schemas-microsoft-com:office:excel' xmlns='http://www.w3.org/TR/REC-html40'>"
excelFile += '<meta http-equiv="content-type" content="application/vnd.ms-excel; charset=UTF-8">'
excelFile += '<meta http-equiv="content-type" content="application/vnd.ms-excel'
excelFile += '; charset=UTF-8">'
excelFile += '<head>'
excelFile += '<!--[if gte mso 9]>'
excelFile += '<xml>'
excelFile += '<x:ExcelWorkbook>'
excelFile += '<x:ExcelWorksheets>'
excelFile += '<x:ExcelWorksheet>'
excelFile += '<x:Name>'
excelFile += '{worksheet}'
excelFile += '</x:Name>'
excelFile += '<x:WorksheetOptions>'
excelFile += '<x:DisplayGridlines/>'
excelFile += '</x:WorksheetOptions>'
excelFile += '</x:ExcelWorksheet>'
excelFile += '</x:ExcelWorksheets>'
excelFile += '</x:ExcelWorkbook>'
excelFile += '</xml>'
excelFile += '<![endif]-->'
excelFile += '</head>'
excelFile += '<body>'
excelFile += excel
excelFile += '</body>'
excelFile += '</html>'
var uri = 'data:application/vnd.ms-excel;charset=utf-8,' + encodeURIComponent(excelFile)
var link = document.createElement('a')
link.href = uri
link.style = 'visibility:hidden'
link.download = FileName + '.xls'
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
},
// 轉出標題和數據
tableToExcel: function(jsonData) {
// 列標題
let str = '<tr>'
for (let i = 0; i < this.arr.length; i++) {
str += `<td>${this.arr[i] + '\t'}</td>`
}
str += '</tr>'
// 循環遍歷,每行加入tr標簽,每個單元格加td標簽
for (let i = 0; i < jsonData.length; i++) {
str += '<tr>'
for (const item in jsonData[i]) {
// 增加\t為了不讓表格顯示科學計數法或者其他格式
str += `<td>${jsonData[i][item] + '\t'}</td>`
}
str += '</tr>'
}
// Worksheet名
const worksheet = 'Sheet1'
// 下載的表格模板數據
const template = `<html xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns="http://www.w3.org/TR/REC-html40">
<head><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet>
<x:Name>${worksheet}</x:Name>
<x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet>
</x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]-->
</head><body><table>${str}</table></body></html>`
// 下載模板
window.location.href = 'data:application/vnd.ms-excel;base64,' + this.base64(template)
},
base64: function(s) { return window.btoa(unescape(encodeURIComponent(s))) }
}
}
</script>
<style scoped>
.excel{
display: inline-block;
/*position: relative;*/
/*right: 90px;*/
}
.input-file {
display: none;
}
.selectedList{
display: block;
width: 100%;
height: 34px;
padding: 0px 0;
font-size: 14px;
line-height: 1.42857143;
color: #555;
background-color: #fff;
background-image: none;
border: 1px solid #ccc;
border-radius: 4px;
}
.diybut{
display: inline-block;
width: 135px;
height: 40px;
}
.error-prompt{
margin: 15px 0;
}
.correct-prompt{
margin: 15px 0;
}
.hideTr{
display: none;
}
tr:nth-child(odd) {
background: #F4F4F4;
}
</style>
<style>
.excel .el-dialog__header{
padding: 20px 20px 10px 40px;
}
</style>
2,引用,注冊,這里不多說了
3.調用
<excelData :title-name="titleName" :action-name="actionName" :disabled="!operate_action.import_customer" style="margin-left: -1px" @refleshParent="exportData"/>
備注:
titleName: '導入數據',是按鈕的文字,
actionName: 'customer',是向后端傳入的參數,后端會返回對於上圖的表格的顯示的字段,
exportData:是導入成功的時候需要做的處理
