<template>
|
<div class="classPage">
|
<div class="headerBox">
|
<div class="searchBox">
|
<el-input v-model="searchKey" @clear="searchData()" clearable placeholder="请输入关键字">
|
<template #append>
|
<el-button type="primary" class="searchBtn" :icon="Search" @click="searchData()" />
|
</template>
|
</el-input>
|
</div>
|
<el-button type="primary" class="applyStartClasses" @click="applyClass">申请开班</el-button>
|
</div>
|
<div class="classListBox" v-loading="pages.loading">
|
<div class="classItem" v-for="(item, index) in classList" :key="index">
|
<div class="itemHeader">
|
<div class="title">{{ item.name }}</div>
|
<div class="classId">(ID:{{ item.id }})</div>
|
<div class="copyIdBtn" v-if="item.applyState == 'Normal'" @click="copy(item.refCode)">
|
复制邀请码
|
</div>
|
<div
|
class="copyIdBtn"
|
style="background: transparent; padding: 0"
|
v-if="item.applyState == 'Reject'"
|
>
|
<el-icon @click="delClass(item)" style="color: red; font-size: 14px"
|
><Delete
|
/></el-icon>
|
</div>
|
</div>
|
<div class="itemInfo" @click="groupDetail(item)">
|
<div class="infoBox">
|
<p>
|
状态:<span v-if="item.applyState == 'WaitAudit'" style="color: #ef9f29">
|
审核中 </span
|
><span v-if="item.applyState == 'Normal'" style="color: #1dbd11"> 进行中 </span
|
><span v-if="item.applyState == 'Reject'" style="color: red"> 未通过 </span>
|
</p>
|
<p v-if="item.applyState == 'Reject'">
|
拒绝原因:<span style="color: red">{{ item.reason != '' ? item.reason : '-' }}</span>
|
</p>
|
<p>班级人数:{{ item.memberCount }} / {{ item.maxUserCount }}</p>
|
<p>
|
有效期:{{ moment(item.beginDate).format('YYYY-MM-DD') }} -
|
{{ moment(item.endDate).format('YYYY-MM-DD') }}
|
</p>
|
</div>
|
</div>
|
</div>
|
</div>
|
<div class="pagination-box" v-if="classList.length > 0">
|
<el-pagination
|
v-model:current-page="pages.page"
|
v-model:page-size="pages.pageSize"
|
:background="false"
|
layout="total, prev, pager, next"
|
:total="pages.count"
|
@current-change="pageChange"
|
@size-change="handleSizeChange"
|
/>
|
</div>
|
<div class="nullBox" v-if="!pages.loading && classList.length == 0">
|
<el-empty />
|
</div>
|
<!-- 申请开班弹框 -->
|
<el-dialog v-model="applyClassDialog" width="450" align-center>
|
<template #title>申请开班</template>
|
<el-form :model="formData" label-position="left" ref="dialogFormRef" label-width="100px">
|
<el-form-item
|
label="班级名称"
|
prop="name"
|
:rules="[{ required: true, message: '请输入班级名称' }]"
|
>
|
<el-input v-model="formData.name" placeholder="请输入班级名称" />
|
</el-form-item>
|
<el-form-item
|
label="班级人数"
|
prop="num"
|
:rules="[{ required: true, message: '请输入班级人数' }]"
|
>
|
<el-input-number v-model="formData.num" :min="1" :step="1" :precision="0" />
|
</el-form-item>
|
<el-form-item
|
label="班级有效期"
|
prop="date"
|
:rules="[{ required: true, message: '请选择班级有效期' }]"
|
>
|
<el-date-picker
|
v-model="formData.date"
|
type="daterange"
|
range-separator="-"
|
start-placeholder="开始时间"
|
end-placeholder="结束时间"
|
/>
|
</el-form-item>
|
</el-form>
|
<template #footer>
|
<div class="dialog-footer">
|
<el-button @click="applyClassDialog = false">取消</el-button>
|
<el-button type="primary" @click="submit" :loading="submitLoading">提交</el-button>
|
</div>
|
</template>
|
</el-dialog>
|
</div>
|
</template>
|
|
<script setup lang="ts">
|
import { defineProps, reactive, ref, onMounted, inject, watch } from 'vue'
|
import { Search } from '@element-plus/icons-vue'
|
import { ElMessage } from 'element-plus'
|
import { getPublicImage } from '@/assets/js/middleGround/tool.js'
|
import moment from 'moment'
|
import { useRouter } from 'vue-router'
|
import useClipboard from 'vue-clipboard3'
|
|
const { toClipboard } = useClipboard()
|
const uRouter = useRouter()
|
const MG: any = inject('MG')
|
const props = defineProps<{
|
courseId: number
|
bookInfo: any
|
}>()
|
|
const emit = defineEmits(['refreshParent'])
|
|
// 申请开班防抖loading
|
const submitLoading = ref(false)
|
|
const classList: any = ref([])
|
|
onMounted(() => {
|
getData()
|
})
|
|
const searchKey = ref('')
|
const pages = reactive({
|
page: 1,
|
pageSize: 6,
|
count: 0,
|
loading: true
|
})
|
|
const searchData = () => {
|
pages.page = 1
|
pages.pageSize = 10
|
getData()
|
}
|
|
// 获取班级
|
const getData = () => {
|
pages.loading = true
|
MG.edu
|
.getCourseClassList({
|
courseId: props.courseId,
|
start: (pages.page - 1) * pages.pageSize,
|
size: pages.pageSize,
|
sort: {
|
type: 'Desc',
|
field: 'CreateDate'
|
},
|
filterList: [],
|
searchList: searchKey.value
|
? [
|
{
|
keywords: searchKey.value,
|
field: 'Name',
|
compareType: 'Contains'
|
}
|
]
|
: []
|
})
|
.then((res: any) => {
|
pages.loading = false
|
pages.count = res.totalSize;
|
classList.value = res.datas.map((item: any) => {
|
return {
|
...item,
|
name: item.name,
|
id: item.id,
|
icon: item.icon ? getPublicImage(item.icon, 80) : '',
|
introduction: item.description,
|
reason: item.applyReturnMsg ? JSON.parse(item.applyReturnMsg).reason : ''
|
}
|
})
|
refreshParent()
|
})
|
}
|
|
// 加入班级
|
const applyClass = () => {
|
formData.value = {
|
name: '',
|
num: '',
|
date: ''
|
}
|
applyClassDialog.value = true
|
}
|
|
// 刷新父组件数据
|
const refreshParent = () => {
|
emit('refreshParent', 'del')
|
}
|
|
const applyClassDialog = ref(false)
|
const formData = ref({
|
name: '',
|
num: '',
|
date: ''
|
})
|
|
const submit = () => {
|
submitLoading.value = true
|
MG.edu
|
.newCourseClass({
|
courseId: props.courseId,
|
name: formData.value.name,
|
description: '',
|
icon: '',
|
type: 'class',
|
beginDate: moment(formData.value.date[0]).format('YYYY-MM-DD'),
|
endDate: moment(formData.value.date[1]).format('YYYY-MM-DD'),
|
config: '',
|
price: 0,
|
maxUserCount: formData.value.num
|
})
|
.then((res: any) => {
|
if (res) {
|
setTimeout(() => {
|
submitLoading.value = false
|
ElMessage.success('开班已申请,等待管理员审核。')
|
applyClassDialog.value = false
|
getData()
|
}, 1000)
|
}
|
})
|
.catch((err: any) => {
|
ElMessage.error('开班申请出错,请稍后再试')
|
setTimeout(() => {
|
submitLoading.value = false
|
}, 1000)
|
})
|
}
|
|
// 复制
|
const copy = async (text: string) => {
|
try {
|
await toClipboard(text)
|
ElMessage({
|
message: '复制成功',
|
type: 'success'
|
})
|
} catch (e) {
|
console.error(e)
|
}
|
}
|
|
// 删除班级
|
const delClass = (item: any) => {
|
const data = {
|
ids: [item.id]
|
}
|
MG.edu
|
.delCourseClass(data)
|
.then((res: any) => {
|
if (res) {
|
ElMessage({
|
message: '已删除',
|
type: 'success'
|
})
|
getData()
|
}
|
})
|
.catch((err: any) => {
|
ElMessage({
|
message: '删除失败',
|
type: 'error'
|
})
|
console.log(err)
|
})
|
}
|
|
// 获取审核通过的课程
|
const coursePages = reactive({
|
page: 1,
|
pageSize: 10,
|
count: 0,
|
loading: false
|
})
|
const courseListData = ref([])
|
|
// const getCourse = () => {
|
// coursePages.loading = true
|
// const searchData = [
|
// {
|
// keywords: 'jsek_digitalTextbooks',
|
// field: 'ProductType'
|
// }
|
// ]
|
// const data = {
|
// Size: coursePages.pageSize,
|
// Start: coursePages.pageSize * coursePages.page - coursePages.pageSize,
|
// sort: {
|
// type: 'Desc',
|
// field: 'CreateDate'
|
// },
|
// searchList: searchData
|
// }
|
// MG.store
|
// .getPurchasedProductList(data)
|
// .then((res: any) => {
|
// coursePages.count = res.totalSize
|
// courseListData.value = res.datas.map((item: any) => {
|
// return {
|
// ...item,
|
// img: item.product.icon ? getPublicImage(item.product.icon, 80) : ''
|
// }
|
// })
|
// coursePages.loading = false
|
// })
|
// .catch(() => {
|
// coursePages.loading = false
|
// })
|
// }
|
|
const pageChange = (val: number) => {
|
pages.page = val
|
getData()
|
}
|
const handleSizeChange = (val: number) => {
|
pages.pageSize = val
|
getData()
|
}
|
|
const groupDetail = (item: any) => {
|
if (item.applyState == 'WaitAudit') {
|
ElMessage({
|
message: '正在审核中....',
|
type: 'warning'
|
})
|
return false
|
}
|
if (item.applyState == 'Reject') {
|
ElMessage({
|
message: '审核未通过',
|
type: 'warning'
|
})
|
return false
|
}
|
const bookData = item.linkProductDto.product
|
let classinfo: any = {
|
id: item.id,
|
name: item.name,
|
courseId: props.courseId,
|
icon: bookData.icon,
|
rootCmsItemId: bookData.rootCmsItemId,
|
bookId: bookData.id,
|
author: bookData.author,
|
isbn: bookData.isbn,
|
bookRefCode: bookData.refCode
|
}
|
let page = uRouter.resolve({
|
path: '/classManage',
|
query: {
|
classInfo: JSON.stringify(classinfo)
|
}
|
})
|
window.open(page.href, '_blank')
|
}
|
</script>
|
|
<style lang="less" scoped>
|
.classPage {
|
.headerBox {
|
margin-bottom: 10px;
|
overflow: hidden;
|
.searchBox {
|
width: 300px;
|
float: left;
|
.searchBtn {
|
background-color: var(--el-color-primary);
|
color: #fff;
|
border-top-left-radius: 0;
|
border-bottom-left-radius: 0;
|
}
|
}
|
.applyStartClasses {
|
float: right;
|
}
|
}
|
.classListBox {
|
overflow: hidden;
|
min-height: 200px;
|
.classItem {
|
float: left;
|
width: 49%;
|
margin-bottom: 16px;
|
margin-right: 1%;
|
border-radius: 8px;
|
border: 1px solid #efefef;
|
overflow: hidden;
|
|
&:nth-child(2n) {
|
margin-left: 1%;
|
margin-right: 0;
|
}
|
.itemHeader {
|
height: 40px;
|
line-height: 40px;
|
padding: 0 20px;
|
background-color: #f8f8f8;
|
div {
|
display: inline-block;
|
}
|
.classId {
|
margin-left: 6px;
|
font-size: 12px;
|
color: #999;
|
}
|
.copyIdBtn {
|
float: right;
|
height: 20px;
|
line-height: 20px;
|
margin-top: 10px;
|
font-size: 12px;
|
background-color: #fff;
|
color: #3b93fe;
|
padding: 0 6px;
|
border-radius: 50px;
|
overflow: hidden;
|
cursor: pointer;
|
}
|
}
|
.itemInfo {
|
height: 128px;
|
padding: 20px;
|
flex: 1;
|
display: flex;
|
cursor: pointer;
|
.infoBox {
|
flex: 1;
|
font-size: 12px;
|
p {
|
margin-bottom: 10px;
|
}
|
}
|
}
|
}
|
}
|
}
|
|
.courseList {
|
overflow: hidden;
|
margin-bottom: 20px;
|
|
.courseItem {
|
float: left;
|
width: 100px;
|
margin: 10px;
|
position: relative;
|
|
.checkBox {
|
position: absolute;
|
right: 0;
|
top: 0;
|
height: 14px;
|
|
::v-deep {
|
.el-checkbox__inner {
|
border-color: #888;
|
}
|
}
|
}
|
|
.imgBox {
|
width: 100px;
|
height: 110px;
|
margin-bottom: 10px;
|
}
|
|
p {
|
line-height: 1.2;
|
display: -webkit-box;
|
-webkit-line-clamp: 2;
|
-webkit-box-orient: vertical;
|
overflow: hidden;
|
}
|
}
|
}
|
|
.pagination-box {
|
padding: 10px 0;
|
display: flex;
|
justify-content: center;
|
}
|
|
.nullBox {
|
text-align: center;
|
margin-top: 30px;
|
font-size: 20px;
|
color: #ccc;
|
}
|
</style>
|