Files
dvcp_v2_webapp/ui/packages/basic/AiImport.vue
2022-12-01 09:35:20 +08:00

322 lines
8.4 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<section class="ai-import">
<a v-if="$slots.default" class="custom-clicker" @click="dialog = true">
<slot/>
</a>
<el-button v-else size="small" @click="dialog=true" icon="iconfont iconImport">导入</el-button>
<ai-dialog
:title="dialogTitle"
:visible.sync="dialog"
:destroy-on-close="true"
width="800px"
customFooter
:close-on-click-modal="false"
@closed="onClose">
<el-form size="small" ref="importForm" label-width="0" class="import-form" :model="fileForm"
:rules="fileRules">
<el-form-item class="ai-import__tips">
<h2>导入说明</h2>
<p class="ai-import__content">
1您正在进行{{ name }}批量导入操作请先
<span @click="downloadFile" title="下载导入模板" class="ai-link" v-text="'【点击下载导入模板】'"/>
并规范填写</p>
<p class="ai-import__content">2填写完成后上传您编辑完成的模板文件</p>
<div class="ai-import__text">
<template v-if="$slots.tips">
<div>请注意</div>
<slot name="tips"/>
</template>
<el-row type="flex" v-else-if="!!dict">
<div v-text="'请注意:'"/>
<span v-text="dict.getLabel('importTips',type)"/>
</el-row>
</div>
</el-form-item>
<el-form-item prop="file" style="width: 100%">
<ai-uploader isImport :instance="instance" v-model="fileForm.file" fileType="file" :limit="1"
acceptType=".xls,.xlsx" @change="onChange" :clearable="false">
<template #trigger>
<el-button icon="iconfont iconfangda">选择文件</el-button>
</template>
<template #tips>最多上传1个文件,单个文件最大10MB仅支持Excel格式</template>
</ai-uploader>
</el-form-item>
</el-form>
<div slot="footer" style="text-align: center;">
<el-button @click="dialog=false">取消</el-button>
<el-button type="primary" @click="onClick">立即导入</el-button>
</div>
</ai-dialog>
<div class="ai-import__loading" v-if="isHasLoadingSlot && isLoading">
<slot name="loading"/>
</div>
</section>
</template>
<script>
export default {
name: 'AiImport',
props: {
title: String,
name: {
type: String,
required: true
},
instance: {
type: Function
},
importUrl: {
type: String,
},
importParams: {
type: Object
},
suffixName: {
type: String,
default: 'xls'
},
tplParams: Object,
url: {
type: String,
},
timeout: {
type: Number,
default: 10 * 60 * 1000
},
customError: {
type: Boolean,
default: false
},
type: String,
dict: Object
},
computed: {
isHasLoadingSlot() {
return this.$slots.loading
},
actions() {
return {
url: this.importUrl || `/app/${this.type}/import`,//导入接口
tpl: this.url || `/app/${this.type}/downloadTemplate`,//下载模板接口
}
},
dialogTitle() {
return this.title || `${this.name}数据导入`
}
},
data() {
return {
dialog: false,
fileForm: {
file: []
},
loading: null,
isLoading: false,
fileRules: {
file: [{required: true, message: '请上传相关文件', trigger: 'change'}]
}
}
},
methods: {
onChange(e) {
if (e.length) {
this.$refs.importForm.clearValidate()
} else {
this.$refs.importForm.validate()
}
},
onClick() {
this.$refs.importForm.validate(v => {
if (v) {
const data = new FormData()
data.append('file', this.fileForm.file[0].raw)
if (!this.isHasLoadingSlot) {
this.loading = this.$loading({
lock: true,
text: '导入中',
background: 'rgba(0, 0, 0, 0.5)'
})
} else {
this.isLoading = true
}
this.instance.post(this.actions.url, data, {
params: this.importParams,
timeout: this.timeout
}).then(res => {
if (!this.isHasLoadingSlot) {
this.loading?.close()
} else {
this.isLoading = false
}
if (res?.data?.importStatus == 1) {
this.dialog = false
const h = this.$createElement
this.$emit('onSuccess', res)
this.$emit('success', res)
if (this.customError) {
this.$emit('error')
} else this.$confirm('导入失败数据具体原因请', {
type: 'success',
title: '数据导入完成',
closeOnClickModal: false,
customClass: 'message-wrapper',
showConfirmButton: false,
cancelButtonText: '关闭',
message: h('div', {
class: 'importResult'
}, [
h('span', null, '成功新增'),
h('a', {
style: 'color: #2EA222;'
}, `${res.data.addCount}`),
h('span', null, '条数据,更新'),
h('a', {
style: 'color: #26f;'
}, `${res.data.updateCount}`),
h('span', null, '条数据,导入失败'),
h('a', {
style: 'color: #f46;'
}, `${res.data.failCount}`),
h('span', null, '条数据。'),
h('div', {class: 'gap'}),
h('div', {style: `display:${res.data.errorFileURL ? 'block' : 'none'}`}, [
h('span', null, '点此'),
h('a', {
class: 'tips-link',
attrs: {
href: res.data.errorFileURL
}
}, '下载异常数据')
])
])
})
} else if (res?.data?.importStatus == 0) {
this.$message.error(res?.data?.errorMsg)
}
}).catch(() => {
if (!this.isHasLoadingSlot) {
this.loading?.close()
} else {
this.isLoading = false
}
})
}
})
},
onClose() {
this.loading?.close()
this.fileForm.file = []
},
downloadFile() {
this.instance.post(this.actions.tpl, null, {
responseType: 'blob',
params: this.tplParams
}).then((res) => {
const link = document.createElement('a')
let blob = new Blob([res], {type: 'application/vnd.ms-excel'})
link.style.display = 'none'
link.href = URL.createObjectURL(blob)
link.setAttribute('download', this.name + '模板.' + this.suffixName)
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
})
},
hide() {
this.dialog = false
}
},
created() {
this.dict?.load("importTips")
}
}
</script>
<style lang="scss" scoped>
.ai-import {
.empty-input {
opacity: 0;
position: absolute;
z-index: -1;
visibility: hidden;
}
.custom-clicker {
display: flex;
align-items: center;
}
.ai-import__loading {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.6);
}
:deep( .el-message-box ){
width: 720px !important;
}
.ai-import__content {
line-height: 22px;
}
.ai-import__tips {
line-height: 1;
:deep(.el-form-item__content ){
line-height: 1;
}
h2 {
margin-top: 4px;
color: #333333;
font-size: 16px;
font-weight: 700;
}
p {
margin-top: 8px;
color: #424242;
font-size: 14px;
}
.ai-link {
cursor: pointer;
color: $primaryColor;
}
.ai-import__text {
font-size: 12px;
margin-top: 8px;
line-height: 16px;
color: #999999;
}
}
}
</style>
<style lang="scss">
.message-wrapper {
width: 560px !important;
.importResult {
color: #222222;
font-size: 16px;
line-height: 24px;
font-weight: bold;
.gap {
width: 100%;
height: 8px;
}
.tips-link {
color: $primaryColor;
text-decoration: unset;
}
}
}
</style>