This commit is contained in:
小新 2020-12-05 03:56:48 -08:00 committed by GitHub
commit 8558134293
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 358 additions and 2 deletions

View File

@ -0,0 +1,221 @@
<template>
<div class="button-wrapper" @click="setTotal">
<slot>
<el-button :loading="loading" :disabled="disabled" icon="md-download" type="primary">{{ title }}</el-button>
</slot>
<processModal
v-if="modal"
v-model="processModalShow"
:current-number="currentNumber"
:exporting="exporting"
:percent="percent"
:total="cloneTotal"
@startExport="startExport"
/>
</div>
</template>
<script>
import processModal from './processModal'
import { export_json_to_excel } from '@/vendor/Export2Excel'
export default {
name: 'ExportButton',
components: {
processModal
},
props: {
request: {
type: Function,
required: false
},
total: {
type: Number,
default() {
return 0
}
},
getTotal: Function,
pageSize: {
default: 20,
type: Number
},
loading: {
type: Boolean,
default() {
return false
}
},
disabled: {
type: Boolean,
default() {
return false
}
},
modal: {
type: Boolean,
default() {
return true
}
},
data: {
type: Array,
default() {
return []
}
},
filename: {
type: String,
default() {
return '导出文件'
}
},
title: {
type: String,
default: '数据导出'
},
columns: {
type: Array,
required: true
},
autoWidth: {
type: Boolean,
default() {
return true
}
},
bookType: {
type: String,
default() {
return 'xlsx'
}
}
},
data() {
return {
cloneTotal: 0,
percent: 0,
currentNumber: 0,
processModalShow: false,
exporting: false
}
},
watch: {
processModalShow(newVal) {
console.log('processModalShow', newVal)
}
},
methods: {
async setTotal() {
this.reset()
if (this.loading || this.disabled) {
return
}
if (this.data.length > 0) {
const tHeader = []
const filterVal = []
this.columns.forEach(item => {
tHeader.push(item.title)
filterVal.push(item.key)
})
const data = this.formatJson(filterVal, this.data)
export_json_to_excel({
multiHeader: [],
header: tHeader,
data,
merges: [],
filename: this.filename,
autoWidth: this.autoWidth,
bookType: this.bookType
})
} else if (this.total > 0) {
this.cloneTotal = this.total
this.processModalShow = true
} else {
const num = await this.getTotal()
this.cloneTotal = num
this.processModalShow = true
}
},
getData(times) {
return new Promise(resolve => {
const data = []
let i = 1
const self = this
function request() {
const requestArr = []
while (i <= times) {
requestArr.push(self.request(i, self.pageSize))
i++
}
Promise.all(requestArr).then(res => {
res.forEach(item => {
data.push(...item)
})
resolve(data)
})
}
request()
})
},
async startExport() {
//
const times = Math.ceil(this.cloneTotal / this.pageSize)
let data = await this.getData(times)
const tHeader = []
const filterVal = []
this.columns.forEach(item => {
tHeader.push(item.title)
filterVal.push(item.key)
})
data = this.formatJson(filterVal, data)
export_json_to_excel({
multiHeader: [],
header: tHeader,
data,
merges: [],
filename: this.filename,
autoWidth: this.autoWidth,
bookType: 'xlsx'
})
setTimeout(() => {
this.processModalShow = false
this.exporting = false
}, 1000)
},
formatJson(filterVal, jsonData) {
return jsonData.map(v =>
filterVal.map(j => {
return v[j]
})
)
},
// num
addPercent() {
const per = 100 / Math.ceil(this.cloneTotal / this.pageSize)
this.percent += per
},
reset() {
this.cloneTotal = 0
this.percent = 0
this.currentNumber = 0
}
}
}
</script>
<style scoped>
.button-wrapper {
display: inline-block;
}
</style>

View File

@ -0,0 +1,90 @@
<template>
<el-dialog
:mask-closable="false"
:title="modalTitle"
:visible.sync="show"
>
<div class="content">
<div class="number">
<span class="number-first">{{ currentNumber }}</span>
<span class="number-op">/</span>
<span class="number-total">{{ total }}</span>
</div>
<Progress :percent="percent|numberFormat" />
</div>
<div slot="footer">
<el-button :loading="exporting" type="primary" @click="startExport">{{ buttonName }}</el-button>
</div>
</el-dialog>
</template>
<script>
export default {
filters: {
numberFormat(value) {
return Number(value.toFixed(2))
}
},
props: {
value: Boolean,
total: Number,
percent: Number,
exporting: Boolean,
currentNumber: Number,
modalTitle: {
type: String,
default() {
return '数据导出'
}
}
},
data() {
return {
// show: false
}
},
computed: {
buttonName() {
if (this.currentNumber === 0) {
return '开始导出'
} else if (this.currentNumber < this.total) {
return '数据获取中'
} else {
return '已下载'
}
},
show: {
get() {
console.log('get', this.value)
return this.value
},
set(newVal) {
console.log('set', newVal)
this.$emit('input', newVal)
}
}
},
watch: {
// show(newVal) {
// this.$emit("input", newVal);
// },
// value(newVal) {
// this.show = newVal;
// }
},
methods: {
startExport() {
this.$emit('startExport')
}
}
}
</script>
<style scoped>
.content{
text-align: center;
}
.number{
font-size: 28px;
}
</style>

View File

@ -20,6 +20,11 @@
<el-button v-waves :loading="downloadLoading" class="filter-item" type="primary" icon="el-icon-download" @click="handleDownload">
Export
</el-button>
<export-button class="filter-item" :columns="exportColumns" :total="total" :request="request">
<el-button type="primary" icon="el-icon-download">
async export
</el-button>
</export-button>
<el-checkbox v-model="showReviewer" class="filter-item" style="margin-left:15px;" @change="tableKey=tableKey+1">
reviewer
</el-checkbox>
@ -151,6 +156,7 @@ import { fetchList, fetchPv, createArticle, updateArticle } from '@/api/article'
import waves from '@/directive/waves' // waves directive
import { parseTime } from '@/utils'
import Pagination from '@/components/Pagination' // secondary package based on el-pagination
import ExportButton from '@/components/ExportButton/index'
const calendarTypeOptions = [
{ key: 'CN', display_name: 'China' },
@ -167,7 +173,10 @@ const calendarTypeKeyValue = calendarTypeOptions.reduce((acc, cur) => {
export default {
name: 'ComplexTable',
components: { Pagination },
components: {
Pagination,
ExportButton
},
directives: { waves },
filters: {
statusFilter(status) {
@ -223,7 +232,29 @@ export default {
timestamp: [{ type: 'date', required: true, message: 'timestamp is required', trigger: 'change' }],
title: [{ required: true, message: 'title is required', trigger: 'blur' }]
},
downloadLoading: false
downloadLoading: false,
exportColumns: [
{
title: 'timestamp',
key: 'timestamp'
},
{
title: 'title',
key: 'title'
},
{
title: 'type',
key: 'type'
},
{
title: 'importance',
key: 'importance'
},
{
title: 'status',
key: 'status'
}
]
}
},
created() {
@ -242,6 +273,20 @@ export default {
}, 1.5 * 1000)
})
},
//
request(page, pageSize) {
const listQuery = JSON.parse(JSON.stringify(this.listQuery))
listQuery.page = page
listQuery.pageSize = pageSize
return new Promise(resolve => {
fetchList(listQuery).then(response => {
response.data.items.map(item => {
item.timestamp = parseTime(item.timestamp, '{y}-{m}-{d} {h}:{i}')
})
resolve(response.data.items)
})
})
},
handleFilter() {
this.listQuery.page = 1
this.getList()