Files
fe-manage/src/components/growthpath/ImportStu.vue
Pengxiansen 01ab826dcf 提交
2025-02-21 14:04:17 +08:00

772 lines
24 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>
<a-drawer
:visible="AddImpStuvisible"
class="drawerStyle AddLevelImpStu"
placement="right"
width="800px"
@after-visible-change="afterVisibleChange"
>
<div class="drawerMain">
<div class="header">
<div class="headerTitle">导入学员</div>
<img
style="width: 29px; height: 29px; cursor: pointer"
src="../../assets/images/basicinfo/close.png"
@click="closeDrawer(false)"
/>
</div>
<div class="main">
<div class="minatitl">
<div class="up1">请下载</div>
<span class="up2" style="cursor: pointer" @click="downloadTemplate"
>模板</span
>
<div class="up1">按要求填写数据并导入</div>
</div>
<div class="upload">
<div class="text">上传</div>
<div class="right">
<div style="height: 176px; margin-bottom: 20px">
<a-upload-dragger
v-model:fileList="fileList"
:action="importStudent"
name="file"
:headers="headers"
:multiple="false"
@change="handleChange"
:data="{
growthId: Number(courseId),
type: courseType,
}"
:showUploadList="false"
>
<p class="ant-upload-drag-icon">
<inbox-outlined></inbox-outlined>
</p>
<p class="ant-upload-text">点击或将文件拖拽到此处上传</p>
<p class="ant-upload-hint">支持扩展名.xls/.xlsx</p>
</a-upload-dragger>
</div>
<!-- <div class="load">
<div class="cloud"></div>
<div class="tip">点击或将文件拖拽到此处上传</div>
<div class="tipz">支持扩展名.xls/.xlsx</div>
</div> -->
<div class="loadstate">
<div v-if="uploadpercent !== -1" class="loadborder">
<div class="content">
<div class="img"></div>
<div class="timebox">
<div class="timetop">
<div class="tit" :title="fileName">{{ fileName }}</div>
<div
v-if="uploadErr"
class="stateloading"
style="color: red"
>
上传失败
</div>
<div v-else class="stateloading">
{{ uploadpercent == 100 ? "上传成功" : "正在上传" }}
</div>
</div>
<div class="prog">
<div
class="inprogloading"
:style="{
width: uploadpercent == -1 ? 0 : uploadpercent + '%',
background: uploadErr ? '#ff7474' : '#35ae69',
}"
></div>
</div>
</div>
<div class="curloading">
<div class="cur">
{{ uploadpercent == -1 ? 0 : uploadpercent }}%
</div>
<div
class="cancel"
style="margin-left: 20px; cursor: pointer"
@click="removeUpload"
>
删除
</div>
<div class="cancel" style="margin-left: 15px"></div>
</div>
<!-- <div v-if="downloadErrUrl !== ''" class="defeat">
<div class="detext" @click="downloadEeeorData">
下载失败数据
</div>
</div> -->
<!-- <div
v-if="notMatchUrl != ''"
:style="{ left: downloadErrUrl !== '' ? '181px' : '46px' }"
class="defeat2"
>
<div class="detext" @click="notDown">下载不匹配的学员</div>
</div> -->
</div>
</div>
<!-- <div
v-if="showBottomBar"
:class="downloadErrUrl == '' ? 'succebox' : 'defeatbox'"
>
<div class="lefimg"></div>
<div class="tacl">
{{ succNum }}条数据解析成功{{
downloadErrUrl == "" ? 0 : errNum
}}条数据解析失败
</div>
</div> -->
<!-- <div v-if="showBottomBar && notMatchUrl != ''" class="group_data">
<div class="icon">
<RightCircleFilled style="color: #4ea6ff; fontsize: 18px" />
</div>
<div class="text">
待导入学员的岗位与本专业力必修的要求不匹配是否导入
</div>
<div class="right"> -->
<!-- <a-radio-group size="small" v-model:value="groupValue" button-style="solid">
<a-radio-button style="margin-right:20px;width: 50px;text-align: center;" value="1"></a-radio-button>
<a-radio-button style="width: 50px;text-align: center;" value="0"></a-radio-button>
</a-radio-group> -->
<!-- <a-switch
v-model:checked="groupValue"
checkedChildren="是"
unCheckedChildren="否"
/>
</div>
</div> -->
<!-- <div class="loadborder">
<div class="content">
<div class="img"></div>
<div class="timebox">
<div class="timetop">
<div class="tit">{{ fileName }}</div>
<div class="statedefeat">上传失败</div>
</div>
<div class="prog">
<div class="inprogdefeat"></div>
</div>
</div>
<div class="curloading">
<div class="cur">55%</div>
<div class="cancel" style="margin-left: 20px">重传</div>
<div class="cancel" style="margin-left: 15px">取消</div>
</div>
<div class="defeat">
<div class="detext">下载失败数据</div>
</div>
</div>
</div>
<div class="defeatbox">
<div class="lefimg"></div>
<div class="tacl">20条数据导入成功5条数据导入失败</div>
</div>
<div class="loadborder">
<div class="content">
<div class="img"></div>
<div class="timebox">
<div class="timetop">
<div class="tit">{{ fileName }}</div>
<div class="statesucce">上传成功</div>
</div>
<div class="prog">
<div class="inprogsucce"></div>
</div>
</div>
<div class="curloading">
<div class="cur">55%</div>
<div class="cancel" style="margin-left: 20px">删除</div>
</div>
</div>
</div>
<div class="succebox">
<div class="lefimg"></div>
<div class="tacl">20条数据导入成功5条数据导入失败</div>
</div> -->
</div>
</div>
</div>
</div>
<div class="btnn">
<button class="btn2" @click="closeDrawer(false)">取消</button>
<button class="btn2" @click="closeDrawer(true)">确定</button>
</div>
</div>
<!-- 加载动画 -->
<div class="aeLoading" :style="{ display: addLoading ? 'flex' : 'none' }">
<a-spin :spinning="addLoading" tip="" />
</div>
</a-drawer>
</template>
<script>
import { computed, reactive, toRefs } from "vue";
import { message } from "ant-design-vue";
import {
// getImportStatus,
saveStudent,
downLoadImpTemplate,
} from "@/api/growthpath";
import { useStore } from "vuex";
import { getCookieForName } from "@/api/method";
import { RightCircleFilled } from "@ant-design/icons-vue";
export default {
name: "ImportStu",
props: {
AddImpStuvisible: {
type: Boolean,
default: false,
},
courseId: {
type: String,
default: "",
},
courseType: {
type: String,
default: "",
},
},
components: {
RightCircleFilled,
},
setup(props, ctx) {
const store = useStore();
const state = reactive({
redisKey: "",
importStudent: `${process.env.VUE_APP_BOE_API_URL}${
process.env.VUE_APP_BASE_API_GROWTH || ""
}/professional/allocation/importLearner`,
timers: "", // 定时器,用于清空定时器使用
isAddStudent: false, // 用于判断用户是否关闭弹框需要重新获取学员列表
uploadpercent: -1,
uploadErr: false, //上传失败
addLoading: false,
fileList: [],
succNum: 0, //成功数据数
errNum: 0, //失败数据数
downloadErrUrl: "",
notMatchUrl: "",
showBottomBar: false, // 显示底部成功条数和失败条数
fileName: "",
groupValue: true,
});
const headers = { token: getCookieForName("token") };
const userInfo = computed(() => store.state.userInfo);
const closeDrawer = (item) => {
clearInterval(state.timers);
state.fileList = [];
state.uploadpercent = -1;
state.addLoading = false;
state.uploadErr = false; //上传失败
state.showBottomBar = false;
state.downloadErrUrl = "";
state.notMatchUrl = "";
if (state.redisKey && state.succNum != 0 && item) {
saveStudent({
redisKey: state.redisKey,
growId: props.courseId,
isImportNotMatchStudent: state.groupValue ? 1 : 0,
})
.then((res) => {
console.log(res, "res");
// 通知父组件重新获取学员列表
message.success("导入成功");
ctx.emit("update:AddImpStuvisible", false);
ctx.emit("AddImpStuvisibleClose", true);
})
.catch((err) => {
message.error("导入失败");
ctx.emit("update:AddImpStuvisible", false);
ctx.emit("AddImpStuvisibleClose", false);
});
} else {
ctx.emit("update:AddImpStuvisible", false);
ctx.emit("AddImpStuvisibleClose", false);
}
state.redisKey = "";
state.succNum = 0;
state.errNum = 0;
state.isAddStudent = false;
};
const downloadTemplate = () => {
window.open(
`${process.env.VUE_APP_BOE_API_URL}${
process.env.VUE_APP_BASE_API_GROWTH || ""
}/professional/allocation/downloadTemplate.do`
);
// window.open(
// `http://192.168.18.141:32002/professional/allocation/downloadTemplate.do`
// );
};
const afterVisibleChange = (bool) => {
console.log("state", bool);
console.log("store", store.state.userInfo);
};
//上传文件
const handleChange = (info) => {
console.log("info", info);
if (info) {
var FileExt = info.file.name.replace(/.+\./, "");
if (["xls", "xlsx"].indexOf(FileExt.toLowerCase()) === -1) {
state.fileList = [];
state.uploadpercent = -1;
message.destroy();
message.error("文件格式错误");
return;
}
if (info.file.size > 50000000) {
state.fileList = [];
state.uploadpercent = -1;
message.destroy();
message.error("文件大小超出50M请重新上传");
return;
}
}
state.addLoading = true;
state.uploadErr = false;
state.uploadpercent = parseInt(info.file.percent);
console.log("我是文件上传的进度---------->", info.file.percent);
const status = info.file.status;
if (status !== "uploading") {
console.log(info.file, info.fileList);
state.addLoading = false;
}
if (status === "done") {
console.log("上传成功返回的UUID", info.file.response.data);
console.log("上传成功返回的UUID----->", info);
console.log("我是导入学员接口传递的参数", {
file: info.file.originFileObj,
targetId: props.courseId,
type: 14,
});
state.fileName = info.file.name;
let i = 0;
message.success("上传成功");
if (info.file.response.code == 1) {
state.fileList = [];
state.addLoading = false;
state.uploadpercent = -1;
message.destroy();
message.error(info.file.response.msg);
return;
}
// state.timers = setInterval(() => {
// state.redisKey = info.file.response.data;
// getImportStatus({ redisKey: state.redisKey })
// .then((res) => {
// console.log("查询导入状态", res);
// if (res.data.code === 200) {
// if (res.data.data.status !== "START") {
// i++;
// if (i === 1) {
// message.destroy();
// // message.success(`${info.file.name}解析成功`);
// state.showBottomBar = true;
// state.addLoading = false;
// state.isAddStudent = true;
// }
// state.succNum = res.data.data.successNum;
// state.errNum = res.data.data.failedNum;
// state.downloadErrUrl = res.data.data.url;
// state.notMatchUrl = res.data.data.notMatchUrl;
// clearInterval(state.timers);
// }
// }
// })
// .catch((err) => {
// clearInterval(state.timers);
// state.showBottomBar = true;
// state.addLoading = false;
// console.log("查询导入状态失败", err);
// });
// }, 500);
} else if (status === "error") {
state.addLoading = false;
state.uploadErr = true;
message.error(`文件解析失败,请联系管理员`);
}
};
// 下载失败数据
const downloadEeeorData = () => {
if (state.downloadErrUrl !== "") {
window.open(
process.env.VUE_APP_BOE_API_URL +
"/upload/boe/file" +
state.downloadErrUrl
);
}
};
const notDown = () => {
if (state.notMatchUrl !== "") {
window.open(
process.env.VUE_APP_BOE_API_URL +
"/upload/boe/file" +
state.notMatchUrl
);
}
};
//删除
const removeUpload = () => {
state.isAddStudent = false;
state.showBottomBar = false;
state.fileList = [];
state.uploadpercent = -1;
state.addLoading = false;
state.uploadErr = false; //上传失败
state.succNum = 0;
state.redisKey = "";
state.errNum = 0;
state.downloadErrUrl = "";
state.notMatchUrl = "";
};
return {
...toRefs(state),
afterVisibleChange,
userInfo,
closeDrawer,
// change,
headers,
handleChange,
downloadEeeorData,
notDown,
removeUpload,
downloadTemplate,
};
},
};
</script>
<style lang="scss">
.AddLevelImpStu > .ant-drawer-content-wrapper {
min-width: 800px !important;
width: 800px !important;
}
.AddLevelImpStu {
.drawerMain {
min-width: 450px;
margin: 0px 32px 0px 32px;
display: flex;
flex-direction: column;
.header {
height: 73px;
border-bottom: 1px solid #e8e8e8;
display: flex;
justify-content: space-between;
align-items: center;
flex-shrink: 0;
// background-color: red;
margin-bottom: 20px;
.headerTitle {
font-size: 18px;
font-weight: 600;
color: #333333;
line-height: 25px;
// margin-left: 24px;
}
}
.main {
overflow: auto;
.minatitl {
display: flex;
.up1 {
font-size: 16px;
font-weight: 400;
color: #333333;
}
.up2 {
font-size: 16px;
font-weight: 400;
color: #4ea6ff;
margin-left: 4px;
}
}
.upload {
margin-top: 32px;
display: flex;
.text {
font-size: 14px;
font-weight: 400;
color: #333333;
white-space: nowrap;
}
.right {
margin-left: 6px;
.load {
width: 500px;
height: 176px;
background: #f5f9fd;
border-radius: 4px;
// opacity: 0.3;
border: 1px dashed #caddfd;
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 20px;
.cloud {
margin-top: 52px;
width: 28px;
height: 28px;
background-image: url(../../assets/images/basicinfo/cloud.png);
}
.tip {
font-size: 14px;
font-weight: 400;
color: #4ea6ff;
margin-top: 15px;
cursor: pointer;
}
.tipz {
font-size: 14px;
font-weight: 400;
color: #999999;
margin-top: 10px;
}
}
.group_data {
display: flex;
align-items: center;
background-color: #d9ecff;
height: 40px;
margin-top: 12px;
.icon {
margin: 0 20px;
}
.text {
margin-right: 20px;
}
}
.loadstate {
width: 500px;
margin-bottom: 100px;
.loadborder {
width: 500px;
height: 173px;
border-radius: 4px;
border: 1px dashed #eaeaea;
margin-bottom: 10px;
margin-top: 10px;
display: flex;
align-items: center;
.content {
display: flex;
margin-left: 20px;
position: relative;
.defeat {
position: absolute;
left: 46px;
top: 42px;
font-size: 14px;
font-weight: 500;
width: 120px;
height: 32px;
border-radius: 2px;
border: 1px solid #387df7;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
.detext {
font-size: 14px;
font-weight: 400;
color: #387df7;
}
}
.defeat2 {
position: absolute;
left: 181px;
top: 42px;
font-size: 14px;
font-weight: 500;
width: 160px;
height: 32px;
border-radius: 2px;
border: 1px solid #387df7;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
.detext {
font-size: 14px;
font-weight: 400;
color: #387df7;
}
}
.img {
width: 30px;
height: 34px;
background-image: url(../../assets/images/basicinfo/exl.png);
}
.timebox {
margin-left: 15px;
margin-top: -5px;
.timetop {
display: flex;
width: 262px;
justify-content: space-between;
margin-bottom: 8px;
.tit {
font-size: 14px;
font-weight: 400;
color: #333333;
width: 200px;
height: 21px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.stateloading {
font-size: 14px;
font-weight: 400;
color: #4ea6ff;
}
.statedefeat {
font-size: 14px;
font-weight: 400;
color: #ff7474;
}
.statesucce {
font-size: 14px;
font-weight: 400;
color: #35ae69;
}
}
.prog {
width: 262px;
height: 5px;
background: #eaf1fe;
border-radius: 4px;
.inprogloading {
width: 55%;
height: 5px;
border-radius: 4px;
background: #4ea6ff;
}
//下载失败条
.inprogdefeat {
width: 55%;
height: 5px;
border-radius: 4px;
background: #ff7474;
}
//下载成功条
.inprogsucce {
width: 100%;
height: 5px;
border-radius: 4px;
background: #57c887;
}
}
}
.curloading {
margin-left: 15px;
margin-top: 15px;
display: flex;
.cur {
font-size: 14px;
font-weight: 400;
color: #333333;
}
.cancel {
font-size: 14px;
font-weight: 400;
color: #387df7;
}
}
}
}
.defeatbox {
width: 500px;
height: 40px;
background: rgba(255, 116, 116, 0.1);
border: 1px solid #ff7474;
display: flex;
align-items: center;
.lefimg {
width: 14px;
height: 14px;
margin-left: 17px;
margin-right: 8px;
background-image: url(../../assets/images/leveladd/nodone.png);
background-size: 100%;
}
.tacl {
font-size: 14px;
font-weight: 400;
color: #ff7474;
}
}
.succebox {
width: 500px;
height: 40px;
background: rgba(53, 174, 105, 0.1);
border: 1px solid #35ae69;
display: flex;
align-items: center;
.lefimg {
width: 14px;
height: 14px;
margin-left: 17px;
margin-right: 8px;
background-image: url(../../assets/images/leveladd/done.png);
background-size: 100%;
}
.tacl {
font-size: 14px;
font-weight: 400;
color: rgba(0, 0, 0, 0.65);
}
}
}
}
}
}
.btnn {
height: 72px;
width: 100%;
position: absolute;
background-color: #fff;
bottom: 0;
left: 0;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0px 1px 35px 0px rgba(118, 136, 166, 0.16);
.btn1 {
width: 100px;
height: 40px;
border: 1px solid #4ea6ff;
border-radius: 8px;
color: #4ea6ff;
background-color: #fff;
cursor: pointer;
}
.btn2 {
cursor: pointer;
width: 100px;
height: 40px;
background: #4ea6ff;
border-radius: 8px;
border: 0;
margin-left: 15px;
color: #fff;
}
}
}
}
</style>