|
@@ -0,0 +1,430 @@
|
|
|
+<template>
|
|
|
+ <div class="upload">
|
|
|
+ <div class="upload-wrapper">
|
|
|
+ <header class="upload-header">
|
|
|
+ <div class="manageTitle">{{ title }}</div>
|
|
|
+ <el-upload
|
|
|
+ ref="upload"
|
|
|
+ action="#"
|
|
|
+ multiple
|
|
|
+ :loading="exceed"
|
|
|
+ :accept="acceptTypesStr"
|
|
|
+ :show-file-list="false"
|
|
|
+ :http-request="uploadHandler"
|
|
|
+ :before-upload="beforeUpload"
|
|
|
+ >
|
|
|
+ <el-button
|
|
|
+ slot="trigger"
|
|
|
+ type="primary"
|
|
|
+ size="small"
|
|
|
+ >
|
|
|
+ 上传文件
|
|
|
+ </el-button>
|
|
|
+ </el-upload>
|
|
|
+ </header>
|
|
|
+ <main class="upload-main">
|
|
|
+ <ul
|
|
|
+ v-if="totalProgressList.length"
|
|
|
+ class="upload-list"
|
|
|
+ >
|
|
|
+ <li
|
|
|
+ v-for="(item, index) in totalProgressList"
|
|
|
+ :key="item.key"
|
|
|
+ class="upload-list-item"
|
|
|
+ >
|
|
|
+ <div class="upload-list-item-wrapper">
|
|
|
+ <div class="upload-list-item-image">
|
|
|
+ <img
|
|
|
+ src="@/assets/nav/ic_ex.png"
|
|
|
+ :alt="item.fileName"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div class="upload-list-item-details">
|
|
|
+ <div>
|
|
|
+ <span class="upload-list-item-name">{{ item.fileName }}</span>
|
|
|
+ <span
|
|
|
+ class="upload-list-item-state"
|
|
|
+ :class="stateClass(item.state)"
|
|
|
+ >{{ stateFormat(item.state) }}</span
|
|
|
+ >
|
|
|
+ <i
|
|
|
+ v-show="item.state === 2"
|
|
|
+ class="upload-list-item-retry el-icon-refresh-right"
|
|
|
+ @click="retry(item)"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <span class="upload-list-item-time">{{ item.time }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <el-divider v-if="index !== totalProgressList.length - 1" />
|
|
|
+ </li>
|
|
|
+ </ul>
|
|
|
+ <NoData
|
|
|
+ v-else
|
|
|
+ :image-width="230"
|
|
|
+ :image-height="160"
|
|
|
+ />
|
|
|
+ </main>
|
|
|
+ </div>
|
|
|
+ <div class="upload-wrapper">
|
|
|
+ <header class="upload-header">
|
|
|
+ <div class="manageTitle">{{ title2 }}</div>
|
|
|
+ <el-date-picker
|
|
|
+ v-model="flightDate"
|
|
|
+ size="small"
|
|
|
+ type="daterange"
|
|
|
+ value-format="yyyy-MM-dd"
|
|
|
+ start-placeholder="开始日期"
|
|
|
+ end-placeholder="结束日期"
|
|
|
+ :picker-options="dateRangePickerOptions"
|
|
|
+ :clearable="false"
|
|
|
+ />
|
|
|
+ </header>
|
|
|
+ <main
|
|
|
+ v-loading="loading"
|
|
|
+ element-loading-text="拼命加载中"
|
|
|
+ element-loading-spinner="el-icon-loading"
|
|
|
+ element-loading-background="rgba(0, 0, 0, 0.8)"
|
|
|
+ class="upload-main"
|
|
|
+ >
|
|
|
+ <el-table
|
|
|
+ :data="tableData"
|
|
|
+ border
|
|
|
+ stripe
|
|
|
+ fit
|
|
|
+ height="100%"
|
|
|
+ class="upload-table"
|
|
|
+ >
|
|
|
+ <el-table-column
|
|
|
+ v-for="column in tableColumns"
|
|
|
+ :key="column.key"
|
|
|
+ :prop="column.prop"
|
|
|
+ :label="column.prop"
|
|
|
+ />
|
|
|
+ <template #empty>
|
|
|
+ <NoData
|
|
|
+ :image-width="230"
|
|
|
+ :image-height="160"
|
|
|
+ />
|
|
|
+ </template>
|
|
|
+ </el-table>
|
|
|
+ </main>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import { parseTime } from '@/utils'
|
|
|
+import { UploadFile, WhatQuery } from '@/api/dataIntegration'
|
|
|
+import NoData from '@/components/nodata/index.vue'
|
|
|
+
|
|
|
+const acceptTypes = ['xlsx', 'xls']
|
|
|
+const acceptTypesStr = acceptTypes.reduce((prevStr, currStr) => {
|
|
|
+ return `${prevStr}${prevStr ? ',' : ''}.${currStr}`
|
|
|
+}, '')
|
|
|
+
|
|
|
+const units = ['B', 'KB', 'MB', 'GB']
|
|
|
+const getUnit = (size, callTime = 0) => {
|
|
|
+ if (size < 1024) {
|
|
|
+ return `${size}${units[callTime]}`
|
|
|
+ }
|
|
|
+ return getUnit(size / 1024, callTime + 1)
|
|
|
+}
|
|
|
+const maxSize = 20 * 1024 * 1024
|
|
|
+const short = getUnit(maxSize)
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: 'Upload',
|
|
|
+ components: { NoData },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ title: '速运行李上传',
|
|
|
+ acceptTypesStr: acceptTypesStr,
|
|
|
+ totalProgressList: [],
|
|
|
+ limit: 3,
|
|
|
+ title2: '速运行李数据',
|
|
|
+ flightDate: new Array(2).fill(parseTime(new Date(), '{y}-{m}-{d}')),
|
|
|
+ dateRangePickerOptions: {
|
|
|
+ onPick: this.dateRangePickHandler,
|
|
|
+ disabledDate: this.dateRangeDisabled
|
|
|
+ },
|
|
|
+ tableColumns: [
|
|
|
+ {
|
|
|
+ prop: 'C0'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prop: 'C1'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prop: 'C2'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prop: 'C3'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prop: 'C4'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prop: 'C5'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prop: 'C6'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prop: 'C7'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prop: 'C8'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prop: 'C9'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ prop: 'createtime'
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ tableData: [],
|
|
|
+ loading: false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ currentProgressNum() {
|
|
|
+ return this.totalProgressList.reduce((prevCount, currentProgress) => {
|
|
|
+ return currentProgress.state > 0 ? prevCount : prevCount + 1
|
|
|
+ }, 0)
|
|
|
+ },
|
|
|
+ exceed() {
|
|
|
+ return this.currentProgressNum >= this.limit
|
|
|
+ }
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ flightDate: {
|
|
|
+ handler() {
|
|
|
+ this.getTableData()
|
|
|
+ },
|
|
|
+ deep: true,
|
|
|
+ immediate: true
|
|
|
+ }
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ beforeUpload(file) {
|
|
|
+ const progress = this.getProgress(file)
|
|
|
+ if (progress && progress.state === 0) {
|
|
|
+ this.$message.warning(`${file.name} 上传中,请勿重复上传`)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (this.exceed) {
|
|
|
+ this.$message.warning(`${file.name} 上传出错:超出最大同时上传数量,最多同时上传 ${this.limit} 个文件`)
|
|
|
+ }
|
|
|
+ const extensionName = file.name.split('.').pop()
|
|
|
+ const acceptExtention = acceptTypes.includes(extensionName)
|
|
|
+ if (!acceptExtention) {
|
|
|
+ this.$message.warning(`${file.name} 上传出错:上传文件只能是 ${acceptTypes.join('/')} 格式`)
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ if (file.size > maxSize) {
|
|
|
+ this.$message.warning(`${file.name} 上传出错:上传文件大小不能超过 ${short}`)
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ uploadHandler({ file }) {
|
|
|
+ if (!this.exceed) {
|
|
|
+ this.uploadFile(file)
|
|
|
+ }
|
|
|
+ const progress = this.getProgress(file)
|
|
|
+ if (progress) {
|
|
|
+ progress.state = this.exceed ? 2 : 0
|
|
|
+ return
|
|
|
+ }
|
|
|
+ const newProgress = {
|
|
|
+ file,
|
|
|
+ key: `${file.name}${file.lastModified}`,
|
|
|
+ fileName: file.name,
|
|
|
+ state: this.exceed ? 2 : 0,
|
|
|
+ time: parseTime(Date.now(), '{y}-{m}-{d} {h}:{i}:{s}')
|
|
|
+ }
|
|
|
+ this.totalProgressList.push(newProgress)
|
|
|
+ },
|
|
|
+ stateClass(state) {
|
|
|
+ const classMap = ['pending', 'success', 'failure']
|
|
|
+ return `upload-list-item-state-${classMap[state]}`
|
|
|
+ },
|
|
|
+ stateFormat(state) {
|
|
|
+ const textMap = ['上传中···', '上传成功', '上传失败']
|
|
|
+ return textMap[state]
|
|
|
+ },
|
|
|
+ setState(file, state) {
|
|
|
+ const progress = this.getProgress(file)
|
|
|
+ if (progress) {
|
|
|
+ progress.state = state
|
|
|
+ }
|
|
|
+ },
|
|
|
+ getProgress(file) {
|
|
|
+ const key = `${file.name}${file.lastModified}`
|
|
|
+ return this.totalProgressList.find(progress => progress.key === key)
|
|
|
+ },
|
|
|
+ retry(progress) {
|
|
|
+ if (this.exceed) {
|
|
|
+ this.$message.warning('已达到最大同时上传数量,请稍后再试')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.uploadFile(progress.file)
|
|
|
+ progress.state = 0
|
|
|
+ },
|
|
|
+ async uploadFile(file) {
|
|
|
+ try {
|
|
|
+ const formData = new FormData()
|
|
|
+ formData.append('file', file)
|
|
|
+ formData.append('serviceId', SERVICE_ID.expressTransportation)
|
|
|
+ const { code } = await UploadFile(formData)
|
|
|
+ if (Number(code) !== 0) {
|
|
|
+ throw new Error('失败')
|
|
|
+ }
|
|
|
+ this.$message.success(`${file.name} 上传成功`)
|
|
|
+ this.setState(file, 1)
|
|
|
+ } catch (error) {
|
|
|
+ this.$message.error(`${file.name} 上传失败`)
|
|
|
+ this.setState(file, 2)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ dateRangePickHandler({ maxDate, minDate }) {
|
|
|
+ if (!maxDate) {
|
|
|
+ this.pickedDate = minDate
|
|
|
+ } else {
|
|
|
+ this.pickedDate = null
|
|
|
+ }
|
|
|
+ },
|
|
|
+ dateRangeDisabled(date) {
|
|
|
+ return this.pickedDate ? Math.abs(date - this.pickedDate) > 2 * 24 * 60 * 60 * 1000 : false
|
|
|
+ },
|
|
|
+ async getTableData() {
|
|
|
+ this.loading = true
|
|
|
+ try {
|
|
|
+ const dataContent = [this.flightDate[0], this.flightDate[1]]
|
|
|
+ const {
|
|
|
+ code,
|
|
|
+ returnData: { listValues }
|
|
|
+ } = await WhatQuery({
|
|
|
+ id: DATACONTENT_ID.expressTransportation,
|
|
|
+ dataContent
|
|
|
+ })
|
|
|
+ if (Number(code) !== 0) {
|
|
|
+ throw new Error('失败')
|
|
|
+ }
|
|
|
+ this.tableData = listValues
|
|
|
+ } catch (error) {
|
|
|
+ this.$message.error('查询表格失败')
|
|
|
+ }
|
|
|
+ this.loading = false
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style
|
|
|
+ lang="scss"
|
|
|
+ scoped
|
|
|
+>
|
|
|
+.upload {
|
|
|
+ width: 100%;
|
|
|
+ height: calc(100vh - 100px);
|
|
|
+ padding: 24px 24px 0;
|
|
|
+ &-wrapper {
|
|
|
+ width: 100%;
|
|
|
+ padding: 24px 24px 0;
|
|
|
+ background-color: #fff;
|
|
|
+ &:nth-child(1) {
|
|
|
+ height: calc(24px + 32px + 30px + 3 * 63px + 26px);
|
|
|
+ }
|
|
|
+ &:nth-child(2) {
|
|
|
+ height: calc(100% - (24px + 32px + 30px + 3 * 63px + 26px));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ &-header {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ }
|
|
|
+ &-main {
|
|
|
+ height: calc(100% - 32px);
|
|
|
+ padding-top: 30px;
|
|
|
+ }
|
|
|
+ &-list {
|
|
|
+ margin: 0;
|
|
|
+ padding: 0;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ overflow-x: hidden;
|
|
|
+ overflow-y: auto;
|
|
|
+ &-item {
|
|
|
+ &-wrapper {
|
|
|
+ display: flex;
|
|
|
+ justify-content: flex-start;
|
|
|
+ align-items: center;
|
|
|
+ }
|
|
|
+ &-image {
|
|
|
+ margin-right: 16px;
|
|
|
+ }
|
|
|
+ &-details {
|
|
|
+ font-size: 14px;
|
|
|
+ font-family: Helvetica, 'Microsoft YaHei';
|
|
|
+ > div {
|
|
|
+ height: 16px;
|
|
|
+ line-height: 16px;
|
|
|
+ &:first-child {
|
|
|
+ margin-bottom: 6px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ &-name {
|
|
|
+ color: #303133;
|
|
|
+ margin-right: 16px;
|
|
|
+ }
|
|
|
+ &-state {
|
|
|
+ &-success {
|
|
|
+ color: #40a349;
|
|
|
+ }
|
|
|
+ &-failure {
|
|
|
+ color: #d53e3e;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ &-retry {
|
|
|
+ width: 16px;
|
|
|
+ height: 16px;
|
|
|
+ text-align: center;
|
|
|
+ line-height: 16px;
|
|
|
+ border-radius: 50%;
|
|
|
+ margin-left: 16px;
|
|
|
+ font-size: 14px;
|
|
|
+ color: #2d67e3;
|
|
|
+ cursor: pointer;
|
|
|
+ &:hover {
|
|
|
+ background-color: #2d67e3;
|
|
|
+ color: #fff;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ &-time {
|
|
|
+ color: #afb4bf;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ::v-deep &-table {
|
|
|
+ width: 100%;
|
|
|
+ .cell {
|
|
|
+ padding: 0;
|
|
|
+ text-align: center;
|
|
|
+ font-size: 14px;
|
|
|
+ font-family: Helvetica, 'Microsoft YaHei';
|
|
|
+ letter-spacing: 0;
|
|
|
+ }
|
|
|
+ .el-table__header-wrapper,
|
|
|
+ .el-table__fixed-header-wrapper {
|
|
|
+ .cell {
|
|
|
+ font-weight: bold;
|
|
|
+ color: #101116;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|