先上效果图哈:
方案一、
.先处理最简单的
原始数据大概是这样:
let fileArr = [
{
progress: 100,
status: '成功',
type: '通号',
webkitRelativePath: "六捷数据2023-05-04 163909/G163/Abis口详细信息_(G163)(380BL3544-0)(14984173988)(2018-01-24 174431.0740—2018-01-24 180347.9070).xls"
},
{
progress: 100,
status: '成功',
type: '通号',
webkitRelativePath: "六捷数据2023-05-04 163909/G163/A口详细信息_(G163)(380BL3544-0)(14984173988)(2018-01-24 174431.4760—2018-01-24 180346.8490).xls"
},
{
progress: 100,
status: '成功',
type: '六捷',
webkitRelativePath:'六捷数据2023-05-04 163909/DJ5908 (2022-11-16)/PRI接口/PRI 信令(14985174166).xlsx'
},
{
progress: 100,
status: '成功',
type: '六捷',
webkitRelativePath: '六捷数据2023-05-04 163909/DJ5908 (2022-11-16)/A接口/A 呼叫记录.xlsx'
},
{
progress: 100,
status: '成功',
type: '六捷',
webkitRelativePath: '六捷数据2023-05-04 163909/DJ5908 (2022-11-16)/Abis接口/Abis 信令(14985174166).xlsx'
},
{
progress: 100,
status: '成功',
type: '六捷',
webkitRelativePath: '六捷数据2023-05-04 163909/DJ5908 (2022-11-16)/Abis接口/Abis 呼叫记录.xlsx'
},
{
progress: 100,
status: '成功',
type: '无',
webkitRelativePath: '六捷数据2023-05-04 163909/dahhdahadab.xls'
}
]
处理方法:
let oraginArr = fileArr.map(v => ({ path: v.webkitRelativePath.split("/"), type: v.type, status: v.status, progress: v.progress}))
function genDirTree(arr){
let result = []
if(arr.length === 0) return []
let treeRoots =[...new Set(arr.map(v => v.path[0])) ]
if(treeRoots.length === 0) return
treeRoots.map((v, i) =>{
let temp = {
name: v
}
let children = []
arr.map((value, j) => {
if(value.path && value.path[0] === v){
let tempV = [...value.path]
tempV.shift()
if(tempV.length>0){
children.push({ path: tempV, status: value.status, type: value.type, progress:value.progress})
}
temp.status = value.status
temp.type = value.type
temp.progress = value.progress
}
})
if(children.length > 0){
temp.children = genDirTree(children)
}
result.push(temp)
} )
return result
}
genDirTree(oraginArr)
console.log('genDirTree:', genDirTree(oraginArr))
打印结果:
效果图展示:
全部代码如下:
<template>
<div>
<el-table
:data="tableData"
style="width: 100%;margin-bottom: 20px;"
row-key="name"
border
default-expand-all
:tree-props="{children: 'children', hasChildren: 'hasChildren'}">
<el-table-column prop="name" label="文件名" min-width="500"></el-table-column>
<el-table-column prop="status" label="状态"></el-table-column>
<el-table-column prop="type" label="厂家类型"></el-table-column>
<el-table-column prop="webkitRelativePath" label="原始文件名"></el-table-column>
</el-table>
</div>
</template>
<script>
export default {
data () {
return {
tableData: [],
fileArr: [
{
progress: 100,
status: '成功',
type: '通号',
webkitRelativePath: "六捷数据2023-05-04 163909/G163/Abis口详细信息_(G163)(380BL3544-0)(14984173988)(2018-01-24 174431.0740—2018-01-24 180347.9070).xls"
},
{
progress: 100,
status: '成功',
type: '通号',
webkitRelativePath: "六捷数据2023-05-04 163909/G163/A口详细信息_(G163)(380BL3544-0)(14984173988)(2018-01-24 174431.4760—2018-01-24 180346.8490).xls"
},
{
progress: 100,
status: '成功',
type: '六捷',
webkitRelativePath:'六捷数据2023-05-04 163909/DJ5908 (2022-11-16)/PRI接口/PRI 信令(14985174166).xlsx'
},
{
id: 226,
progress: 100,
status: '成功',
type: '六捷',
webkitRelativePath: '六捷数据2023-05-04 163909/DJ5908 (2022-11-16)/A接口/A 呼叫记录.xlsx'
},
{
progress: 100,
status: '成功',
type: '六捷',
webkitRelativePath: '六捷数据2023-05-04 163909/DJ5908 (2022-11-16)/Abis接口/Abis 信令(14985174166).xlsx'
},
{
progress: 100,
status: '成功',
type: '六捷',
webkitRelativePath: '六捷数据2023-05-04 163909/DJ5908 (2022-11-16)/Abis接口/Abis 呼叫记录.xlsx'
},
{
progress: 100,
status: '成功',
type: '无',
webkitRelativePath: '六捷数据2023-05-04 163909/dahhdahadab.xls'
}
]
}
},
methods: {
genDirTree(arr) {
let result = []
if (arr.length === 0) return []
let treeRoots = [...new Set(arr.map(v => v.path[0]))]
if (treeRoots.length === 0) return
treeRoots.map((v, i) =>{
let temp = {
name: v
}
let children = []
arr.map((value, j) => {
if (value.path && value.path[0] === v) {
let tempV = [...value.path]
tempV.shift()
if (tempV.length > 0) {
children.push({ path: tempV, status: value.status, type: value.type, progress: value.progress})
} else {
// 最后文件一层 push 其他变量
temp.status = value.status
temp.type = value.type
temp.progress = value.progress
}
}
})
if (children.length > 0) {
temp.children = this.genDirTree(children)
}
result.push(temp)
})
return result
}
},
created() {
let oraginArr = this.fileArr.map(v => ({ path: v.webkitRelativePath.split("/"), type: v.type, status: v.status, progress: v.progress}))
console.log('oraginArr:', oraginArr)
console.log('genDirTree:', this.genDirTree(oraginArr))
this.tableData = this.genDirTree(oraginArr)
},
mounted() {
}
}
</script>
方案二、
elment-ui el-upload 实现先选择文件夹 后,所有文件扫描存储显示在table表格里面,然后再点击上传按钮,才去真正的上传调后台的接口,这时候怎么拿到之前的所有file文件呢,可以用:
this.$refs.uploadMutiple.submit() // 提交调用uploadFile函数
这个方法去获取文件夹里面的所有文件,然后上传文件需要 阻止冒泡出现选择文件的弹窗,
<el-button v-if="uploadFlag" style="margin-left: 10px;" size="small" type="success" @click.stop="submitUpload">
上传
</el-button>
@click.stop="submitUpload" 方法
全部代码如下:
<template>
<div>
<el-upload
class="upload-demo"
ref="uploadMutiple"
action="/" multiple
:on-change="handleChange"
:file-list="fileList"
:show-file-list="false"
:auto-upload="false"
:http-request="uploadFile"
>
<el-button size="small" type="primary">选取文件</el-button>
<el-button v-if="uploadFlag" style="margin-left: 10px;" size="small" type="success" @click.stop="submitUpload">
上传
</el-button>
</el-upload>
<el-table :data="tableTreeData && tableTreeData.length > 0 ? tableTreeData : uploadFilesList" row-key="name"
default-expand-all :tree-props="{ children: 'children', hasChildren: 'hasChildren' }" height="500"
:header-cell-style="{ background: '#f8f8f8', color: '#606266' }" style="width: 100%;">
<el-table-column prop="name" :show-overflow-tooltip="true" label="文件名称" min-width="500" />
<el-table-column prop="btsFactoryName" label="文件所属厂家" align="center" width="100" />
<el-table-column prop="status" label="是否成功" width="160">
<template slot-scope="scope">
<template v-if="!scope.row.children">
<template v-if="scope.row.status === 'wait'">
<span style="color: #333;"> 待上传 </span>
</template>
<template v-else-if="scope.row.status === 'success'">
<span style="color: green;"> 上传成功</span>
</template>
<template v-else-if="scope.row.status === 'error'">
<span style="color: red; margin-right: 5px;"> 上传失败 </span>
<el-button type="text" @click="uploadFile1(scope.row, scope.row.file)">重新上传</el-button>
</template>
<el-progress v-else :percentage="scope.row.progress" />
</template>
</template>
</el-table-column>
<el-table-column width="120" prop="size" label="大小">
<template slot-scope="scope">
<span>{{ scope.row.children ? '' : scope.row.size }}</span>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
import { isIncludesFileName, formatBtsFactoryName } from '@/views/C3Module/reportModule/btsFactoryFileNameRule.js'
import axios from 'axios'
export default {
data() {
return {
size: 3 * 1024 * 1024, // 每片的大小
uploadFilesList: [],
tableTreeData: [], // 文件夹里面树结构数据
uploadStatus: 0, // 初始化状态
uploadFlag: false,
form: {
bureauNum: null,
btsFactoryCode: 0,
imgSavePath: ''
},
// 文件上传
fileList: [] // upload多文件数组
}
},
mounted() {
this.$nextTick(() => {
// 让el-upload支持上传文件夹
this.$refs.uploadMutiple.$children[0].$refs.input.webkitdirectory = true
})
},
methods: {
// 覆盖上传事件,选择文件之后触发的事件
uploadFile(file) {
console.log('上传文件前:', file.file)
if (file.file.name) {
const uploadLimit = 200
const uploadTypes = ['xls', 'xlsx', 'umb', 'rxl']
const filetype = file.file.name.replace(/.+\./, '')
const isRightSize = (file.file.size || 0) / 1024 / 1024 < uploadLimit
if (!isRightSize) {
this.$message.error(`'上文件: ${file.file.name} 的大小超过 '` + uploadLimit + 'MB')
return false
}
if (uploadTypes.indexOf(filetype.toLowerCase()) === -1) {
this.$message.warning({
message: '请上传后缀名为xls、xlsx、umb或rxl的文件'
})
return false
}
// 封装上传的文件
const doUpload = () => {
// this.uploadStatus = 1
var webkitRelativePath = file.file.webkitRelativePath
this.form.imgSavePath = webkitRelativePath.split("/")[0]
const fileList = {}
for (const key in file.file) {
fileList[key] = file.file[key]
}
// status: uploading、success、error 文件上传状态
// progress 文件上传进度
this.uploadFilesList.push({ ...fileList, progress: 0, status: 'uploading' })
this.httpRequest(file.file, parms => {
this.showProgress(fileList, parms)
})
}
// 三接口厂家
isIncludesFileName(this.form.btsFactoryCode, file.file, doUpload)
// 阻止 el-upload的默认上传
return false
}
},
showProgress(file, parms) {
const { progress, status } = parms
const arr = [...this.uploadFilesList].map(items => {
// console.log('items', items, file)
if (items.uid === file.uid) {
items.file = file
items.btsFactoryName = formatBtsFactoryName(file.name)
items.progress = progress
items.status = status
}
return items
})
this.uploadFilesList = [...arr]
let oraginArr = this.uploadFilesList.map(v => ({
path: v.webkitRelativePath.split("/"), type: v.type, file: v.file, btsFactoryName: v.btsFactoryName, status: v.status, uid: v.uid, size: v.size, progress: v.progress
}))
console.log('oraginArr:', oraginArr)
this.tableTreeData = this.genDirTree(oraginArr)
console.log('uploadFilesList:', this.tableTreeData)
},
async httpRequest(file, callback) {
try {
// 如果文件小于3MB,直接上传
if (file.size < 3 * 1024 * 1024) {
const formData = new FormData()
formData.append("file", file)
formData.append("filename", file.name)
formData.append("name", file.name)
formData.append("chunkNumber", 1)
formData.append("fileType", 1)
formData.append("chunkSize", file.size)
formData.append("accidentId", '27831872067208537')
formData.append("bureauId", 57)
formData.append("webkitRelativePath", file.webkitRelativePath)
let progress = 0
axios({
headers: {
'Authorization': this.$store.state.user.token,
'Content-Type': 'multipart/form-data'
},
method: 'post',
url: 'http://10.21.23.251/c3/oss/upload',
data: formData,
onUploadProgress: progressEvent => { // 获取文件上传进度 axios自带的
progress = (progressEvent.loaded / progressEvent.total * 100) | 0
callback({ progress, status: 'uploading' })
}
}).then(() => { // 成功状态
callback({ progress, status: 'success' })
}).catch(() => { // 失败状态
callback({ progress, status: 'error' })
})
} else {
// 如果文件大于等于3MB,分片上传
let fileArr = this.sliceFile(file) // 获取到文件
// console.log('fileArr:', fileArr)
fileArr.forEach((e, i) => { // 循环每片
const formData1 = new FormData() // 创建formdata对象
formData1.append("file", file)
formData1.append("filename", file.name)
formData1.append("name", file.name)
formData1.append("chunkNumber", fileArr.length)
formData1.append("fileType", 1)
formData1.append("chunkSize", fileArr[i].size)
formData1.append("accidentId", '27831872067208537')
formData1.append("bureauId", 57)
formData1.append("webkitRelativePath", file.webkitRelativePath)
let progress = 0
axios({
headers: {
'Authorization': this.$store.state.user.token,
'Content-Type': 'multipart/form-data'
},
method: 'post',
url: 'http://10.21.23.251/c3/oss/upload',
data: formData1,
onUploadProgress: progressEvent => { // 获取文件上传进度 axios自带的
progress = (progressEvent.loaded / progressEvent.total * 100) | 0
callback({ progress, status: 'uploading' })
}
}).then(() => { // 成功状态
console.log('分片上传成功')
callback({ progress, status: 'success' })
}).catch(() => { // 失败状态
callback({ progress, status: 'error' })
})
})
}
} catch (error) {
return error
}
// 上传成功之后清除历史记录
this.$refs.uploadMutiple.clearFiles()
this.fileList = []
},
// 分片上传分片
sliceFile(file) {
const chunks = []
let start = 0
let end
while (start < file.size) {
end = Math.min(start + this.size, file.size)
chunks.push(file.slice(start, end))
console.log(file.slice(start, end))
console.log(start, end)
start = end
}
return chunks
},
// 继续上传
uploadFile1(item, file) {
this.uploadFilesList = this.uploadFilesList.filter(v => item.name !== v.name)
// console.log('3333333:', this.uploadFilesList)
setTimeout(() => {
this.beforeUpload(file)
}, 300)
},
// 组装成树结构数组
genDirTree(arr) {
let result = []
if (arr.length === 0) return []
let treeRoots = [...new Set(arr.map(v => v.path[0]))]
if (treeRoots.length === 0) return
treeRoots.map((v, i) => {
let temp = {
name: v
}
let children = []
arr.map((value, j) => {
if (value.path && value.path[0] === v) {
let tempV = [...value.path]
tempV.shift()
if (tempV && tempV.length > 0) {
children.push({ path: tempV, file: value.file, btsFactoryName: value.btsFactoryName, status: value.status, uid: value.uid, size: value.size, progress: value.progress })
} else {
// 最后文件一层 push 其他变量
// temp.type = value.type
temp.file = value.file
temp.btsFactoryName = value.btsFactoryName
temp.status = value.status
temp.uid = value.uid
temp.size = value.size
temp.progress = value.progress
}
}
})
if (children.length > 0) {
temp.children = this.genDirTree(children)
}
result.push(temp)
})
return result
},
// 点击上传后触发的事件
submitUpload() {
if (this.form.imgSavePath === '') {
this.$message({
message: '请输入名称',
type: 'warning'
})
} else {
this.$refs.uploadMutiple.submit() // 提交调用uploadFile函数
}
},
// 监控上传文件列表
handleChange(file, fileList) {
console.log('file:', file)
var webkitRelativePath = file.raw.webkitRelativePath
this.form.imgSavePath = webkitRelativePath.split("/")[0]
// let existFile = fileList.slice(0, fileList.length - 1).find(f => f.name === file.name)
// if (existFile) {
// this.$message.error('当前文件已经存在!')
// fileList.pop()
// }
this.fileList = fileList
this.uploadFlag = true
}
}
}
</script>