Files
fe-manage/src/components/drawers/InitiateRecommend.vue
2023-06-21 19:04:57 +08:00

744 lines
19 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 class="recommend" :visible="visible" width="80%" :title="title" @close="closeDrawer" :maskClosable="false">
<!-- 搜索框及按钮 -->
<div class="filter">
<div class="filterItems">
<div class="select">
<a-input v-model:value="searchDataInfo.keyWord" style="width: 270px; height: 40px; border-radius: 8px"
placeholder="请输入案例标题" />
</div>
<div class="select">
<a-input v-model:value="searchDataInfo.authorName" style="width: 270px; height: 40px; border-radius: 8px"
placeholder="请输入作者名字" />
</div>
<div style="display: flex; margin-bottom: 20px">
<div class="btn btn1" @click="handleSearch(1)">
<div class="search"></div>
<div class="btnText">搜索</div>
</div>
<div class="btn btn1" @click="handleRest" style="width: 105px">
<div class="search"></div>
<div class="btnText">重置</div>
</div>
<div class="btn btn1" @click="handleImportInfo" style="width: 105px">
<div class=""></div>
<div class="btnText">导入</div>
</div>
</div>
</div>
<div class="btns">
<div class="btnText">已选择 <span style="color:#4ea6ff ;">{{ state.selectedRowKeys.length }}</span> 条案例</div>
</div>
</div>
<!-- 表格 -->
<div style="display: flex; overflow-x: auto; overflow-y: auto;justify-content: space-between;">
<div class="tableBox" style="margin-top: 30px;min-height: 800px;overflow: hidden;">
<a-table style="border: 1px solid #f2f6fe;" :columns="state.columns" :data-source="state.dataSource"
:loading="!loading" :row-selection="rowSelection" :pagination="pagination" />
</div>
<div class="right1" style="min-width: 200px">
<div class="onerow">
<div class="onleft">
<div class="already">已选</div>
</div>
</div>
<div :style="{ 'max-height': state.screenHeight - 240 + 'px' }" style="overflow-y: auto">
<div class="selecteds">
<div v-for="(item, i) in state.selectedRow" :key="i">
<div v-if="i < 11">
<div class="chose">
{{ item.title.length > 6 ? item.title.slice(0, 6) + '...' : item.title }}
<div class="ch" @click="() => {
state.selectedRow.splice(i, 1);
state.selectedRowKeys.splice(i, 1);
}"></div>
</div>
</div>
<div v-else>
<div v-if="state.member">
<div class="chose">
{{ item.title.length > 6 ? item.title.slice(0, 6) + '...' : item.title }}
<div class="ch" @click="() => {
state.selectedRow.splice(i, 1);
state.selectedRowKeys.splice(i, 1);
}"></div>
</div>
</div>
</div>
</div>
<div v-if="!state.member && state.selectedRow?.length > 10" class="ifsw">
<div @click="state.member = !state.member" class="“sw”">查看更多></div>
</div>
<div v-if="state.member && state.selectedRow?.length > 10" class="ifsw">
<div @click="state.member = !state.member" class="sw">收起&lt;</div>
</div>
</div>
</div>
</div>
</div>
<!-- 底部按钮和下一步的弹窗 -->
<div class="btnn">
<button class="btn2" @click="closeDrawer">取消</button>
<CommonRecommend :type="state.type" :id="state.selectedRowKeys" @finash="submitCall" :stage="state.stage">
<a-button class="btn2">
下一步
</a-button>
</CommonRecommend>
</div>
</a-drawer>
<!-- 导入的提示框 -->
<a-modal class="modal" v-model:visible="state.AMvisible" :closable="false" :maskClosable="false" ok-text="确定"
cancel-text="取消" @ok="hideModal" @cancel="closeModal">
<div class="importInfo" style="padding: 24px;">
<div class="imptHeader">
<span>导入</span>
<div class="defeat">
<div class="detext" @click="downloadEeeorData(1)">
下载导入模版
</div>
</div>
<div class="defeat">
<div class="detext" @click="downloadEeeorData(2)">
下载最新案例模版
</div>
</div>
</div>
<div class="upload">
<a-upload :file-list="state.fileList" :action="state.uploadAction" name="file" @change="handleChange"
:showUploadList="false" :multiple="false">
<a-button style="width: 150px;">
上传文件
</a-button>
</a-upload>
<span class="ant-upload-hint">支持文件格式.xls/.xlsx</span>
</div>
<div class="progress" v-if="state.status">
<div class="nameAndProgress" style="display: flex;justify-content: space-between;padding-right: 36px;">
<span>{{ state.fileName }}</span>
<span>{{ state.status }}</span>
</div>
<a-progress :percent="state.uploadpercent" status="active" :strokeColor="state.progressColor" />
</div>
<div class="importDetail" style="display: flex;flex-direction: column;" v-if="state.status">
<span>导入 1039 成功 1007 失败 <span style="color: red;">32</span> </span>
<div class="defeat">
<div class="detext" @click="downloadErrorInfo">
下载失败数据
</div>
</div>
</div>
</div>
</a-modal>
<!-- 下一步添加学员 -->
</template>
<script setup>
import { reactive, ref, computed, nextTick } from 'vue';
import { Form, message } from "ant-design-vue";
import { downloadErrorData,isTopList } from '@/api/case'
import useDownload from '@/hooks/useDownload'
import CommonRecommend from "@/components/CaseManage/CommonRecommend";
defineProps({
visible: {
type: Boolean,
default: false
},
title: {
type: String,
default: '添加案例'
}
})
const emit = defineEmits(['update:visible'])
const loading = ref(false)
const state = reactive({
status:'',//上传的状态
progressColor: '',//进度条颜色
type: 1,//添加学员
stage: '',//
importId: '',//导入id
selectedRowKeys: [],//案例标题的id
selectedRow: [],//选择的每一行数据
dataSource: [],//表格的数据
AMvisible: false,//导入modal框显示隐藏
uploadpercent: -1,//导入进度
fileName: '',//下载的名字
uploadAction: process.env.VUE_APP_NEW_API + '/xboe/m/boe/cases/recommend/import',//下载地址
fileList: [],//上传列表
member: false,//收起和展开
screenHeight: document.body.clientHeight,//高度
columns: [
{
title: "案例标题",
dataIndex: "title",
key: "title",
align: "left",
className: "h",
width: '75%',
ellipsis: true,
},
{
title: "作者名称",
dataIndex: "authorName",
key: "authorName",
width: '20%',
align: "center",
className: "h",
ellipsis: true,
}
]
})
// 下一步返回的刷新列表
function submitCall(flag) {
flag && getTopList()
}
// 查询数据
const searchDataInfo = reactive({
pageIndex: 1,
pageSize: 10,
keyWord: "",
authorName: '',
});
const total = ref(0)
// 分页
const pagination = computed(() => ({
total: total.value,
showSizeChanger: false,
current: searchDataInfo.pageIndex,
pageSize: searchDataInfo.pageSize,
onChange: changePagination,
}));
const changePagination = (e) => {
console.log(e);
loading.value = false
searchDataInfo.pageIndex = e
nextTick(getTopList);
};
// 计算全选
const rowSelection = computed(() => {
return {
selectedRowKeys: state.selectedRowKeys,
onChange: onSelectChange,
preserveSelectedRowKeys: true,
}
});
const onSelectChange = (selectedRowKeys, selectedRow) => {
console.log("selectedRowKeys", selectedRowKeys);
state.selectedRowKeys = selectedRowKeys
state.selectedRow = selectedRow
};
// 请求列表数据是formdata类型的
const getTopList = () => {
// axios({
// method: "post",
// url: "/systemapi/xboe/m/boe/cases/isTopList",
// data: { ...searchDataInfo },
// headers: {
// token: Cookies.get("token"),
// 'Content-Type': 'application/x-www-form-urlencoded',
// },
// })
isTopList(searchDataInfo).then((res) => {
loading.value = true;
console.log(res);
res?.data?.result?.list?.forEach(element => {
element.key = element.id
});
state.dataSource = res?.data?.result?.list || []
total.value = res?.data?.result?.count
}).catch((err) => {
message.error(err);
loading.value = false;
})
}
getTopList()
// 搜索
const handleSearch = (num) => {
if (num == 1) searchDataInfo.pageIndex = 1
console.log(searchDataInfo);
getTopList()
}
//错误案例下载
const downloadErrorInfo = () => {
if (!state.importId) {
message.warn('暂无失败数据')
return
}
downloadErrorData({ importId: state.importId }).then((res) => {
if (res.status != 200) return
useDownload(res, '失败数据.xsl')
}).catch((error) => {
console.log(error);
})
}
const { resetFields } = Form.useForm(searchDataInfo, {});
//重置
const handleRest = () => {
resetFields()
getTopList()
}
// 取消抽屉
const closeDrawer = () => {
state.selectedRowKeys=[]
state.selectedRow=[]
resetFields()
emit('update:visible', false)
}
//导入按钮
const handleImportInfo = () => {
state.AMvisible = true
}
//model确定按钮
const hideModal = () => {
state.fileList = []
state.status='',
state.progressColor='',
state.importId='',
state.AMvisible = false
}
// modal取消按钮
const closeModal = () => {
console.log('取消');
state.fileList = []
state.status='',
state.progressColor='',
state.importId='',
state.AMvisible = false
}
//上传文件
const handleChange = (info) => {
console.log("info", info);
console.log("info", info.file.percent);
state.status = '正在上传'
state.progressColor = ''
state.fileList = []
state.fileList = info.fileList
state.fileName = info.file.name;
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;
}
}
state.uploadpercent = parseInt(info.file.percent);
const status = info.file.status;
if (status !== "uploading") {
console.log(info.file, info.fileList);
}
if (status === "done") {
state.importId = info.file.response.result
message.success(`${info.file.name}上传成功`);
state.progressColor = '#52c41a'
state.status = '上传成功'
// let i = 0;
// state.timers = setInterval(() => {
// let uid = info.file.response.data;
// caseImport(uid)
// .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;
// clearInterval(state.timers);
// }
// }
// })
// .catch((err) => {
// clearInterval(state.timers);
// state.showBottomBar = true;
// state.addLoading = false;
// console.log("查询导入状态失败", err);
// });
// }, 500);
} else if (status === "error") {
state.progressColor = 'red'
state.status = '上传失败'
message.error(`${info.file.name}上传失败`);
}
};
</script>
<style lang="scss" scoped>
//上传
.modal {
:global(.ant-modal-header) {
border: 0;
}
:global(.ant-modal-footer) {
border: 0;
}
.importInfo {
.imptHeader {
display: flex;
margin-bottom: 40px;
.defeat {
margin-left: 40px;
color: #0982ff;
text-decoration: underline;
cursor: pointer;
}
}
.upload {
display: flex;
align-items: center;
margin-bottom: 40px;
.ant-upload-hint {
margin-left: 20px;
}
}
.importDetail {
margin-top: 40px;
.defeat {
color: #0982ff;
text-decoration: underline;
cursor: pointer;
}
}
}
}
.recommend {
:global(.ant-drawer-header-title) {
flex-direction: row-reverse !important;
}
:global(.ant-drawer-close) {
margin-right: 0;
}
.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;
}
}
// 头部
.filter {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
.filterItems {
display: flex;
flex-wrap: wrap;
.select {
margin-right: 20px;
margin-bottom: 20px;
}
.btn {
padding: 0 26px 0 26px;
height: 38px;
background: #4ea6ff;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
margin-right: 14px;
flex-shrink: 0;
cursor: pointer;
.search {
background-size: 100%;
}
.btnText {
font-size: 14px;
font-weight: 400;
color: #ffffff;
line-height: 36px;
margin-left: 5px;
}
}
.btnn {
padding: 0 26px 0 26px;
height: 38px;
background: #4ea6ff;
border-radius: 8px;
border: 1px solid rgba(64, 158, 255, 1);
display: flex;
align-items: center;
justify-content: center;
margin-right: 14px;
flex-shrink: 0;
cursor: pointer;
.search {
background-size: 100%;
}
.btnText {
font-size: 14px;
font-weight: 400;
color: #fff;
line-height: 36px;
margin-left: 5px;
}
}
.btn1 {
.search {
width: 15px;
height: 17px;
background-image: url("../../assets/images/courseManage/search0.png");
}
}
.btn2 {
.search {
width: 16px;
height: 18px;
background-image: url("../../assets/images/courseManage/reset0.png");
}
}
.btn1:active {
background: #0982ff;
}
.btn2:active {
background: rgba(64, 158, 255, 0.2);
}
}
.btns {
display: flex;
.btn {
padding: 0 26px;
height: 38px;
background: #4ea6ff;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
margin-right: 14px;
flex-shrink: 0;
cursor: pointer;
.search {
background-size: 100%;
}
.btnText {
font-size: 14px;
font-weight: 400;
color: #ffffff;
line-height: 36px;
margin-left: 5px;
}
}
.btn3 {
margin-right: 0;
.search {
width: 17px;
height: 18px;
background-image: url("../../assets/images/courseManage/add0.png");
}
}
.btn3:active {
background: #0982ff;
}
}
}
//底部
.right1 {
border-left: 1px solid #f2f6fe;
margin-left: 20px;
.onerow {
display: flex;
justify-content: space-between;
align-items: center;
margin-right: 40px;
flex-wrap: wrap;
width: 100%;
.onleft {
display: flex;
text-align: center;
.already {
color: rgba(51, 51, 51, 1);
font-size: 16px;
font-weight: 500;
margin-left: 32px;
white-space: nowrap;
// margin-bottom: 20px;
}
.count {
color: #4ea6ff;
font-size: 16px;
margin: 0 6px;
}
.peo {
color: rgba(51, 51, 51, 1);
font-size: 16px;
font-weight: 500;
}
}
.clbox {
margin-right: 50px;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
width: 104px;
height: 32px;
border-radius: 4px;
background: #4ea6ff;
.colose {
width: 16px;
height: 16px;
background-image: url(../../assets/images/basicinfo/ch.png);
background-size: 100%;
margin-right: 4px;
}
.allclear {
color: rgba(255, 255, 255, 1);
font-size: 14px;
}
}
}
.selecteds {
display: flex;
flex-wrap: wrap;
margin-left: 32px;
.person {
width: 100%;
margin-top: 20px;
border-top: 1px solid #f2f6fe;
}
.chose {
min-width: 64px;
height: 24px;
margin-top: 25px;
margin-right: 25px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 2px;
border: 1px solid rgba(56, 139, 225, 1);
color: rgba(56, 139, 225, 1);
font-size: 12px;
position: relative;
padding: 0 10px;
.ch {
position: absolute;
width: 18px;
height: 18px;
background-image: url(../../assets/images/basicinfo/ch.png);
right: -8px;
top: -8px;
}
}
.ifsw {
display: flex;
align-items: end;
justify-content: center;
color: #4ea6ff;
}
.sw {
display: flex;
align-items: center;
justify-content: center;
text-align: justify;
color: #4ea6ff;
margin-top: 23px;
margin-left: 10px;
}
.dept {
width: 100%;
margin-top: 30px;
border-top: 1px solid #f2f6fe;
}
}
}
}
</style>