mirror of https://github.com/veops/cmdb.git
fix(cmdb-ui):batch upload cancel bug && download error (#306)
This commit is contained in:
parent
67d64abf42
commit
32e073f3fd
|
@ -16,12 +16,14 @@ export function processFile(fileObj) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function uploadData(ciId, data) {
|
export function uploadData(ciId, data) {
|
||||||
data.ci_type = ciId
|
|
||||||
data.exist_policy = 'replace'
|
|
||||||
return axios({
|
return axios({
|
||||||
url: '/v0.1/ci',
|
url: '/v0.1/ci',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
data,
|
data: {
|
||||||
|
...data,
|
||||||
|
ci_type: ciId,
|
||||||
|
exist_policy: 'replace'
|
||||||
|
},
|
||||||
isShowMessage: false
|
isShowMessage: false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="cmdb-batch-upload" :style="{ height: `${windowHeight - 64}px` }">
|
<div class="cmdb-batch-upload" :style="{ height: `${windowHeight - 64}px` }">
|
||||||
<div id="title">
|
<div id="title">
|
||||||
<ci-type-choice @getCiTypeAttr="showCiType" />
|
<ci-type-choice ref="ciTypeChoice" @getCiTypeAttr="showCiType" />
|
||||||
</div>
|
</div>
|
||||||
<a-row>
|
<a-row>
|
||||||
<a-col :span="12">
|
<a-col :span="12">
|
||||||
<upload-file-form :ciType="ciType" ref="uploadFileForm" @uploadDone="uploadDone"></upload-file-form>
|
<upload-file-form
|
||||||
|
:isUploading="isUploading"
|
||||||
|
:ciType="ciType"
|
||||||
|
ref="uploadFileForm"
|
||||||
|
@uploadDone="uploadDone"
|
||||||
|
></upload-file-form>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :span="24" v-if="ciType && uploadData.length">
|
<a-col :span="24" v-if="ciType && uploadData.length">
|
||||||
<CiUploadTable :ciTypeAttrs="ciTypeAttrs" ref="ciUploadTable" :uploadData="uploadData"></CiUploadTable>
|
<CiUploadTable :ciTypeAttrs="ciTypeAttrs" ref="ciUploadTable" :uploadData="uploadData"></CiUploadTable>
|
||||||
|
@ -13,15 +18,19 @@
|
||||||
<a-space size="large">
|
<a-space size="large">
|
||||||
<a-button type="primary" ghost @click="handleCancel">取消</a-button>
|
<a-button type="primary" ghost @click="handleCancel">取消</a-button>
|
||||||
<a-button @click="handleUpload" type="primary">上传</a-button>
|
<a-button @click="handleUpload" type="primary">上传</a-button>
|
||||||
|
<a-button v-if="hasError && !isUploading" @click="downloadError" type="primary">失败下载</a-button>
|
||||||
</a-space>
|
</a-space>
|
||||||
</div>
|
</div>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :span="24">
|
<a-col :span="24" v-if="ciType">
|
||||||
<upload-result
|
<upload-result
|
||||||
ref="uploadResult"
|
ref="uploadResult"
|
||||||
:upLoadData="uploadData"
|
:upLoadData="uploadData"
|
||||||
:ciType="ciType"
|
:ciType="ciType"
|
||||||
:unique-field="uniqueField"
|
:unique-field="uniqueField"
|
||||||
|
:isUploading="isUploading"
|
||||||
|
@uploadResultDone="uploadResultDone"
|
||||||
|
@uploadResultError="uploadResultError"
|
||||||
></upload-result>
|
></upload-result>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
|
@ -52,7 +61,8 @@ export default {
|
||||||
ciType: 0,
|
ciType: 0,
|
||||||
uniqueField: '',
|
uniqueField: '',
|
||||||
uniqueId: 0,
|
uniqueId: 0,
|
||||||
displayUpload: true,
|
isUploading: false,
|
||||||
|
hasError: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -60,13 +70,12 @@ export default {
|
||||||
windowHeight: (state) => state.windowHeight,
|
windowHeight: (state) => state.windowHeight,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
inject: ['reload'],
|
|
||||||
methods: {
|
methods: {
|
||||||
showCiType(message) {
|
showCiType(message) {
|
||||||
this.ciTypeAttrs = message
|
this.ciTypeAttrs = message ?? {}
|
||||||
this.ciType = message.type_id
|
this.ciType = message?.type_id ?? 0
|
||||||
this.uniqueField = message.unique
|
this.uniqueField = message?.unique ?? ''
|
||||||
this.uniqueId = message.unique_id
|
this.uniqueId = message?.unique_id ?? 0
|
||||||
},
|
},
|
||||||
uploadDone(dataList) {
|
uploadDone(dataList) {
|
||||||
const _uploadData = filterNull(dataList).map((item, i) => {
|
const _uploadData = filterNull(dataList).map((item, i) => {
|
||||||
|
@ -77,13 +86,13 @@ export default {
|
||||||
const _find = this.ciTypeAttrs.attributes.find(
|
const _find = this.ciTypeAttrs.attributes.find(
|
||||||
(attr) => attr.alias === dataList[0][j] || attr.name === dataList[0][j]
|
(attr) => attr.alias === dataList[0][j] || attr.name === dataList[0][j]
|
||||||
)
|
)
|
||||||
if (_find?.value_type === '4') {
|
if (_find?.value_type === '4' && typeof ele === 'number') {
|
||||||
_ele[dataList[0][j]] = moment(Math.round((ele - 25569) * 86400 * 1000 - 28800000)).format('YYYY-MM-DD')
|
_ele[dataList[0][j]] = moment(Math.round((ele - 25569) * 86400 * 1000 - 28800000)).format('YYYY-MM-DD')
|
||||||
} else if (_find?.value_type === '3') {
|
} else if (_find?.value_type === '3' && typeof ele === 'number') {
|
||||||
_ele[dataList[0][j]] = moment(Math.round((ele - 25569) * 86400 * 1000 - 28800000)).format(
|
_ele[dataList[0][j]] = moment(Math.round((ele - 25569) * 86400 * 1000 - 28800000)).format(
|
||||||
'YYYY-MM-DD HH:mm:ss'
|
'YYYY-MM-DD HH:mm:ss'
|
||||||
)
|
)
|
||||||
} else if (_find?.value_type === '5') {
|
} else if (_find?.value_type === '5' && typeof ele === 'number') {
|
||||||
_ele[dataList[0][j]] = moment(Math.round(ele * 86400 * 1000 - 28800000)).format('HH:mm:ss')
|
_ele[dataList[0][j]] = moment(Math.round(ele * 86400 * 1000 - 28800000)).format('HH:mm:ss')
|
||||||
} else {
|
} else {
|
||||||
_ele[dataList[0][j]] = ele
|
_ele[dataList[0][j]] = ele
|
||||||
|
@ -95,6 +104,9 @@ export default {
|
||||||
return item
|
return item
|
||||||
})
|
})
|
||||||
this.uploadData = _uploadData.slice(1)
|
this.uploadData = _uploadData.slice(1)
|
||||||
|
this.hasError = false
|
||||||
|
this.isUploading = false
|
||||||
|
this.$refs.uploadResult.visible = false
|
||||||
},
|
},
|
||||||
handleUpload() {
|
handleUpload() {
|
||||||
if (!this.ciType) {
|
if (!this.ciType) {
|
||||||
|
@ -102,6 +114,7 @@ export default {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (this.uploadData && this.uploadData.length > 0) {
|
if (this.uploadData && this.uploadData.length > 0) {
|
||||||
|
this.isUploading = true
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.$refs.uploadResult.upload2Server()
|
this.$refs.uploadResult.upload2Server()
|
||||||
})
|
})
|
||||||
|
@ -110,7 +123,24 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleCancel() {
|
handleCancel() {
|
||||||
this.reload()
|
if (!this.isUploading) {
|
||||||
|
this.showCiType(null)
|
||||||
|
this.$refs.ciTypeChoice.selectNum = null
|
||||||
|
this.hasError = false
|
||||||
|
} else {
|
||||||
|
this.$message.warning('批量上传已取消')
|
||||||
|
this.isUploading = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
uploadResultDone() {
|
||||||
|
this.isUploading = false
|
||||||
|
},
|
||||||
|
uploadResultError(index) {
|
||||||
|
this.hasError = true
|
||||||
|
this.$refs.ciUploadTable.uploadResultError(index)
|
||||||
|
},
|
||||||
|
downloadError() {
|
||||||
|
this.$refs.ciUploadTable.downloadError()
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
:style="{ width: '300px' }"
|
:style="{ width: '300px' }"
|
||||||
class="ops-select"
|
class="ops-select"
|
||||||
:filter-option="filterOption"
|
:filter-option="filterOption"
|
||||||
|
v-model="selectNum"
|
||||||
>
|
>
|
||||||
<a-select-option v-for="ciType in ciTypeList" :key="ciType.name" :value="ciType.id">{{
|
<a-select-option v-for="ciType in ciTypeList" :key="ciType.name" :value="ciType.id">{{
|
||||||
ciType.alias
|
ciType.alias
|
||||||
|
@ -99,7 +100,7 @@ export default {
|
||||||
return {
|
return {
|
||||||
ciTypeList: [],
|
ciTypeList: [],
|
||||||
ciTypeName: '',
|
ciTypeName: '',
|
||||||
selectNum: 0,
|
selectNum: null,
|
||||||
selectCiTypeAttrList: [],
|
selectCiTypeAttrList: [],
|
||||||
visible: false,
|
visible: false,
|
||||||
checkedAttrs: [],
|
checkedAttrs: [],
|
||||||
|
@ -131,7 +132,6 @@ export default {
|
||||||
methods: {
|
methods: {
|
||||||
selectCiType(el) {
|
selectCiType(el) {
|
||||||
// 当选择好模板类型时的回调函数
|
// 当选择好模板类型时的回调函数
|
||||||
this.selectNum = el
|
|
||||||
getCITypeAttributesById(el).then((res) => {
|
getCITypeAttributesById(el).then((res) => {
|
||||||
this.$emit('getCiTypeAttr', res)
|
this.$emit('getCiTypeAttr', res)
|
||||||
this.selectCiTypeAttrList = res
|
this.selectCiTypeAttrList = res
|
||||||
|
@ -155,7 +155,6 @@ export default {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
this.parentsType = res.parents.filter((parent) => this.canEdit[parent.id])
|
this.parentsType = res.parents.filter((parent) => this.canEdit[parent.id])
|
||||||
|
|
||||||
const _parentsForm = {}
|
const _parentsForm = {}
|
||||||
res.parents.forEach((item) => {
|
res.parents.forEach((item) => {
|
||||||
const _find = item.attributes.find((attr) => attr.id === item.unique_id)
|
const _find = item.attributes.find((attr) => attr.id === item.unique_id)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="cmdb-batch-upload-table">
|
<div class="cmdb-batch-upload-table">
|
||||||
<vxe-table
|
<vxe-table
|
||||||
|
ref="xTable"
|
||||||
stripe
|
stripe
|
||||||
show-header-overflow
|
show-header-overflow
|
||||||
show-overflow=""
|
show-overflow=""
|
||||||
|
@ -9,6 +10,7 @@
|
||||||
:max-height="200"
|
:max-height="200"
|
||||||
:data="dataSource"
|
:data="dataSource"
|
||||||
resizable
|
resizable
|
||||||
|
:row-style="rowStyle"
|
||||||
>
|
>
|
||||||
<vxe-column type="seq" width="40" />
|
<vxe-column type="seq" width="40" />
|
||||||
<vxe-column
|
<vxe-column
|
||||||
|
@ -37,7 +39,9 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {}
|
return {
|
||||||
|
errorIndexList: [],
|
||||||
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
columns() {
|
columns() {
|
||||||
|
@ -65,7 +69,33 @@ export default {
|
||||||
return _.cloneDeep(this.uploadData)
|
return _.cloneDeep(this.uploadData)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {},
|
watch: {
|
||||||
|
uploadData() {
|
||||||
|
this.errorIndexList = []
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
uploadResultError(index) {
|
||||||
|
const _errorIndexList = _.cloneDeep(this.errorIndexList)
|
||||||
|
_errorIndexList.push(index)
|
||||||
|
this.errorIndexList = _errorIndexList
|
||||||
|
},
|
||||||
|
rowStyle({ rowIndex }) {
|
||||||
|
if (this.errorIndexList.includes(rowIndex)) {
|
||||||
|
return 'color:red;'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
downloadError() {
|
||||||
|
const data = this.uploadData.filter((item, index) => this.errorIndexList.includes(index))
|
||||||
|
this.$refs.xTable.exportData({
|
||||||
|
data,
|
||||||
|
type: 'xlsx',
|
||||||
|
columnFilterMethod({ column }) {
|
||||||
|
return column.property
|
||||||
|
},
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
accept=".xls,.xlsx"
|
accept=".xls,.xlsx"
|
||||||
:showUploadList="false"
|
:showUploadList="false"
|
||||||
:fileList="fileList"
|
:fileList="fileList"
|
||||||
:disabled="!ciType"
|
:disabled="!ciType || isUploading"
|
||||||
>
|
>
|
||||||
<img :style="{ width: '80px', height: '80px' }" src="@/assets/file_upload.png" />
|
<img :style="{ width: '80px', height: '80px' }" src="@/assets/file_upload.png" />
|
||||||
<p class="ant-upload-text">点击或拖拽文件至此上传!</p>
|
<p class="ant-upload-text">点击或拖拽文件至此上传!</p>
|
||||||
|
@ -29,7 +29,11 @@ export default {
|
||||||
ciType: {
|
ciType: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: 0,
|
default: 0,
|
||||||
}
|
},
|
||||||
|
isUploading: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -40,7 +44,20 @@ export default {
|
||||||
percent: 0,
|
percent: 0,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
ciType: {
|
||||||
|
handler(newValue) {
|
||||||
|
if (!newValue) {
|
||||||
|
this.ciItemNum = 0
|
||||||
|
this.fileList = []
|
||||||
|
this.dataList = []
|
||||||
|
this.progressStatus = 'active'
|
||||||
|
this.percent = 0
|
||||||
|
this.$emit('uploadDone', this.dataList)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
customRequest(data) {
|
customRequest(data) {
|
||||||
this.fileList = [data.file]
|
this.fileList = [data.file]
|
||||||
|
|
|
@ -34,6 +34,10 @@ export default {
|
||||||
required: true,
|
required: true,
|
||||||
type: String,
|
type: String,
|
||||||
},
|
},
|
||||||
|
isUploading: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
data: function() {
|
data: function() {
|
||||||
return {
|
return {
|
||||||
|
@ -51,13 +55,6 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async sleep(n) {
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
setTimeout(() => {
|
|
||||||
resolve()
|
|
||||||
}, n || 5)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
async upload2Server() {
|
async upload2Server() {
|
||||||
this.visible = true
|
this.visible = true
|
||||||
this.success = 0
|
this.success = 0
|
||||||
|
@ -65,22 +62,31 @@ export default {
|
||||||
this.errorItems = []
|
this.errorItems = []
|
||||||
const floor = Math.ceil(this.total / 6)
|
const floor = Math.ceil(this.total / 6)
|
||||||
for (let i = 0; i < floor; i++) {
|
for (let i = 0; i < floor; i++) {
|
||||||
const itemList = this.upLoadData.slice(6 * i, 6 * i + 6)
|
if (this.isUploading) {
|
||||||
const promises = itemList.map((x) => uploadData(this.ciType, x))
|
const itemList = this.upLoadData.slice(6 * i, 6 * i + 6)
|
||||||
await Promise.allSettled(promises)
|
const promises = itemList.map((x) => uploadData(this.ciType, x))
|
||||||
.then((res) => {
|
await Promise.allSettled(promises)
|
||||||
res.forEach((r) => {
|
.then((res) => {
|
||||||
if (r.status === 'fulfilled') {
|
res.forEach((r, j) => {
|
||||||
this.success += 1
|
if (r.status === 'fulfilled') {
|
||||||
} else {
|
this.success += 1
|
||||||
this.errorItems.push(r?.reason?.response?.data.message ?? '请求出现错误,请稍后再试')
|
} else {
|
||||||
this.errorNum += 1
|
this.errorItems.push(r?.reason?.response?.data.message ?? '请求出现错误,请稍后再试')
|
||||||
}
|
this.errorNum += 1
|
||||||
|
this.$emit('uploadResultError', 6 * i + j)
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
.finally(() => {
|
||||||
.finally(() => {
|
this.complete += 6
|
||||||
this.complete += 6
|
})
|
||||||
})
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.isUploading) {
|
||||||
|
this.$emit('uploadResultDone')
|
||||||
|
this.$message.success('批量上传已完成')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue