xw_admin/src/components/scImport/index.vue
2025-05-12 10:28:28 +08:00

301 lines
7.0 KiB
Vue

<template>
<slot name="header"></slot>
<el-dialog v-bind="$attrs" :title="title" v-model="visible" :width="560" destroy-on-close draggable @closed="closeVisible">
<div class="importBody">
<el-upload
class="upload"
:action="oss.host"
:data="upload_data"
:show-file-list="false"
:on-success="handleSuccess"
:on-error="handleError"
:before-upload="beforeUpload"
:http-request="uploadFile"
drag
:disabled="importDis"
>
<div v-if="!importTrue">
<el-icon class="el-icon--upload"><sc-icon-UploadExcel /></el-icon>
<div class="el-upload__text">
<span class="laText">请将Excel拖到此处</span>
<span class="tipText">,或点击上传</span><em> Excel</em>
</div>
</div>
<div v-else>
<div class="el-upload__text">
<el-icon class="trueIcon el-icon&#45;&#45;upload">
<sc-icon-FormXls />
<div class="deleteFile" @click="deleteFile" v-if="!progressTrue"><el-icon class="icon"><el-icon-Close/></el-icon></div>
</el-icon>
<div class="el-upload__text">{{text}}</div>
</div>
</div>
<template #tip>
<div class="el-upload__tip">
<span class="tip">
<!--如果数据导入中途业务出错,请不要刷新页面,修改后继续点击导入-->
<slot name="cover"></slot>
</span>
<span class="btn">
<slot name="download"></slot>
</span>
</div>
<div class="importBox" v-if="progressShow">
<div class="name">导入进度</div>
<el-progress class="exportPopover" :text-inside="true" :stroke-width="12" :percentage="importInfo.rate" />
</div>
<div class="errText" v-if="errorShow">
<div class="deleteErr" @click="errorClick"><el-icon class="icon"><el-icon-Close/></el-icon></div>
<el-scrollbar ref="scrollbar" max-height="120px">
<div v-for="em in errorList" :key="em">
<div :class="em.status==0?'text danger':'text success'" v-html="em.msg"></div>
</div>
</el-scrollbar>
</div>
</template>
</el-upload>
</div>
<template #footer>
<el-button @click="closeVisible"> </el-button>
<el-button type="primary" :disabled="!importTrue || progressTrue || httpDisabled" @click="save">确定导入</el-button>
</template>
</el-dialog>
</template>
<script>
import {eventBus} from "@/utils/eventBus"
export default {
name: "import",
emits: ['parentParams', 'closed', "importSuccess"],
props:{
size:{type:String, default:'small'},
title:{type:String, default: ""},
type:{type:[String, Number], default: ""},
httpDisabled:{type:Boolean, default:false}
},
data(){
return{
visible: false,
text:"",
oss:{
host:''
},
upload_data:{},
fileShow:false,
params:{},
importDis:false,
importTrue:false,
progressShow:false,
progressTrue:false,
errorShow:false,
importInfo:{},
errorList:[],
// 按数组的形式展示
}
},
setup(){
},
watch:{
},
mounted() {
eventBus.$on('sockBack', this.getWsResult);
},
unmounted() {
eventBus.$off('sockBack', this.getWsResult);
},
methods:{
getWsResult(res){
if(res.data && (res.data.type == 4 || res.data.type == 5 || res.data.type == 10 || res.data.type == 17 || res.data.type == 18 || res.data.type == 27 || res.data.type == 28 || res.data.type == 31 || res.data.type == 42 || res.data.type == 44 || res.data.type == 45 || res.data.type == 48)){
if(this.type == res.data.type){
this.importInfo = res.data;
this.progressShow = true;
this.progressTrue = true;
this.importTrue = true;
if(res.data.status == 0 || res.data.status == 1){
this.errorShow = true;
let text = res.data;
this.errorList.push(text);
this.scrollDown();
}
if(res.data.rate == 100){
// this.progressShow = false;
this.progressTrue = false;
this.$emit('importSuccess');
}
}
}
},
// 导入文件
importFile(){
this.visible = true;
},
// 上传前
beforeUpload(file){
const text = file.name.split('.').pop();
if(!['xls','xlsx'].includes(text)){
this.$message.warning(`只能选择的excel文件类型`);
return false;
}
this.text = file.name;
return true
},
async uploadFile({ file }) {
try {
const formData = new FormData();
formData.append('file', file);
for (const key in this.upload_data) {
formData.append(key, this.upload_data[key]);
}
this.params = formData;
this.importTrue = true;
this.importDis = true;
this.progressShow = false;
} catch (error) {
console.log(error)
}
},
deleteFile(){
this.importTrue = false;
setTimeout(()=>{
this.importDis = false;
this.$emit('importSuccess',{refresh:false});
this.errorClick();
},100)
},
errorClick(){
this.errorShow= false;
this.errorList= []
},
closeVisible(){
this.visible = false;
this.progressShow = false;
this.importTrue = false;
},
save(){
this.errorClick();
this.$emit('parentParams',this.params);
},
// 上传成功
handleSuccess(){
},
// 上传失败
handleError(){
this.$message.warning('上传失败请重新上传');
},
scrollDown() {
this.$nextTick(() => {
const wrap = this.$refs.scrollbar;
if(wrap){
const e = wrap.$el.querySelector('.el-scrollbar__wrap')
if(e){
e.scrollTop = e.scrollHeight;
}
}
})
},
}
}
</script>
<style scoped lang="scss">
.importBody{
padding: 0 20px;
}
.upload .el-icon--upload{
width: 54px;height: 54px;
}
.upload ::v-deep .el-upload__text{
.trueIcon{
position: relative;
border: 1px solid var(--el-border-color);
border-radius: 4px;
}
.laText{
color: var(--el-color-dark);
}
.tipText{
color: var(--el-text-color-placeholder);
}
.deleteFile{
position: absolute;
right: -6px;
top: -10px;
width: 16px;
height: 16px;
border-radius: 50%;
background: var(--el-color-danger);
display: flex;
align-items: center;
justify-content: center;
.icon{
width: 12px;height: 12px;
color: var(--el-color-white);
}
}
}
.upload ::v-deep .el-upload__tip{
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 15px;
color: var(--el-text-color-placeholder);
.btn{
color: var(--el-color-primary);
cursor: pointer;
}
}
.importBox{
border: 1px solid var(--el-border-color);
padding: 10px 5px;
margin: 15px 0;
border-radius: 4px;
.name{margin-bottom: 8px;font-size: 13px;}
.exportPopover ::v-deep .el-progress-bar__innerText{
height: 100%;
display: flex;align-items: center;justify-content: flex-end;
font-size: 10px;
}
}
.errText{
margin: 15px 0 0 0;
padding: 10px;
border-radius: 6px;
background: var(--el-color-danger-light-9);
position: relative;
::v-deep .text{
font-size: 12px;
line-height: 20px;
text-align: left;
}
.danger{
color: var(--el-color-danger);
}
.success{
color: var(--el-color-success);
}
.deleteErr{
position: absolute;
right: 4px;
top: 4px;
z-index: 20;
cursor: pointer;
.icon{
font-size: 16px;
}
}
}
</style>