<template>
|
<div class="coursePage">
|
<div class="personalPage-title">我的班级</div>
|
<div class="tabs">
|
<el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
|
<el-tab-pane :label="'当前班级(' + calssList.length + ')'" name="1"></el-tab-pane>
|
<!-- <el-tab-pane label="历史班级(5)" name="2"></el-tab-pane> -->
|
</el-tabs>
|
</div>
|
<div class="headerBox">
|
<div class="searchBox">
|
<el-input v-model="searchKey" clearable @clear="searchList()" placeholder="请输入关键字">
|
<template #append>
|
<el-button type="primary" class="searchBtn" @click="searchList()" :icon="Search" />
|
</template>
|
</el-input>
|
</div>
|
<el-button type="primary" class="applyStartClasses" @click="openJoin()">加入班级</el-button>
|
<el-dialog v-model="dialogVisible" title="加入班级" width="500">
|
<div class="codeContent">
|
<span>邀请码:</span>
|
<el-input style="width: 330px" v-model="codeText" placeholder="请输入邀请码" />
|
<el-button type="primary" @click="getClassDetail">确认</el-button>
|
</div>
|
<div class="classInfo" v-if="classDetail?.name">
|
<div class="itemCon">
|
<span>班级名称:</span>
|
<span>{{ classDetail.name }}</span>
|
</div>
|
<div class="itemCon">
|
<span>班级人数:</span>
|
<span>{{ classDetail.memberCount }} / {{ classDetail.maxUserCount }}</span>
|
</div>
|
<div class="itemCon">
|
<span>开课时间:</span>
|
<span
|
>{{ moment(classDetail.beginDate).format('YYYY-MM-DD') }} -
|
{{ moment(classDetail.endDate).format('YYYY-MM-DD') }}</span
|
>
|
</div>
|
</div>
|
<template #footer>
|
<div class="dialog-footer">
|
<el-button @click="dialogVisible = false"> 取消 </el-button>
|
<el-button type="primary" @click="joinClass()"> 确认 </el-button>
|
</div>
|
</template>
|
</el-dialog>
|
</div>
|
<div class="courseListBox" v-if="calssList.length > 0 && !isLoading">
|
<div class="courseItem" v-for="(item, index) in calssList" :key="index">
|
<div class="itemHeader">
|
<div class="title">{{ item.name }}</div>
|
<div class="courseId">(ID:{{ item.id }})</div>
|
<!-- <div class="copyIdBtn" @click="copy(item.refCode)">复制邀请码</div> -->
|
</div>
|
<div class="itemInfo" @click="goClassManage(item)">
|
<div class="infoBox">
|
<p>
|
状态:<span v-if="item.userState == 'WaitValid'" style="color: #ef9f29"> 审核中 </span
|
><span v-if="item.userState == 'Normal'" style="color: #1dbd11"> 进行中 </span
|
><span v-if="item.userState == 'Reject'" style="color: red"> 未通过 </span>
|
</p>
|
<p>班级人数:{{ item.memberCount }} / {{ item.maxUserCount }}</p>
|
<p>有效期:{{ item.classTime }}</p>
|
</div>
|
</div>
|
</div>
|
</div>
|
<el-empty description="暂无数据" v-if="calssList.length == 0 && !isLoading" />
|
<div style="min-height: 200px" v-if="isLoading" v-loading="isLoading"></div>
|
<div class="pageBox">
|
<el-pagination
|
v-model:current-page="pages.currentPage"
|
:page-size="pages.pageSize"
|
:size="'small'"
|
:disabled="pages.count <= 1"
|
layout="total, prev, pager, next"
|
:total="pages.count"
|
@size-change="handleSizeChange"
|
@current-change="handleCurrentChange"
|
/>
|
</div>
|
</div>
|
</template>
|
|
<script setup lang="ts">
|
import { reactive, ref, onMounted, inject, watch } from 'vue'
|
import { Search } from '@element-plus/icons-vue'
|
import { useRouter } from 'vue-router'
|
import { ElMessage } from 'element-plus'
|
import { getPublicImage } from '@/assets/js/middleGround/tool.js'
|
import moment from 'moment'
|
import useClipboard from 'vue-clipboard3'
|
|
const { toClipboard } = useClipboard()
|
const MG: any = inject('MG')
|
const config: any = inject('config')
|
const router = useRouter()
|
const activeName = ref('1')
|
|
interface ClassItem {
|
id: string
|
name: string
|
memberCount: number
|
maxUserCount: number
|
userState: string
|
beginDate: string
|
endDate: string
|
classTime: string
|
linkProductDto: {
|
product: {
|
name: string
|
icon: string
|
}
|
}
|
}
|
|
const calssList = ref<ClassItem[]>([])
|
const searchKey = ref('')
|
const codeText = ref('')
|
const dialogVisible = ref(false)
|
const classDetail = ref()
|
const isLoading = ref(true)
|
|
let pages = reactive({
|
currentPage: 1,
|
page: 1,
|
pageSize: 6,
|
count: 0,
|
loading: false,
|
})
|
|
onMounted(() => {
|
getCurrentClassList()
|
})
|
|
// 分页
|
const handleSizeChange = (val: number) => {
|
pages.pageSize = val
|
getCurrentClassList()
|
}
|
|
const handleCurrentChange = (val: number) => {
|
pages.page = val
|
pages.currentPage = val
|
getCurrentClassList()
|
}
|
|
const handleClick = (val: any) => {
|
activeName.value = val
|
}
|
|
const openJoin = () => {
|
dialogVisible.value = true
|
classDetail.value = null
|
codeText.value = ''
|
}
|
|
// 搜索
|
const searchList = () => {
|
pages.page = 1
|
pages.currentPage = 1
|
getCurrentClassList()
|
}
|
|
// 复制
|
const copy = async (text: string) => {
|
try {
|
await toClipboard(text)
|
ElMessage({
|
message: '复制成功',
|
type: 'success',
|
})
|
} catch (e) {
|
console.error(e)
|
}
|
}
|
|
// 加入班级
|
const joinClass = () => {
|
if (!codeText.value) {
|
ElMessage({
|
message: '无效的邀请码',
|
type: 'error',
|
})
|
return false
|
}
|
const data = { refCode: codeText.value }
|
MG.identity.joinGroupByRefCode(data).then((res: any) => {
|
if (res == '组不存在') {
|
ElMessage({
|
message: '无效的班级',
|
type: 'error',
|
})
|
}
|
if (res == '组成员数量已最大,不能加入') {
|
ElMessage({
|
message: '班级成员数量已最大,不能加入',
|
type: 'error',
|
})
|
}
|
if (res == '已经申请过加入此组') {
|
ElMessage({
|
message: '已经申请过加入此班级',
|
type: 'error',
|
})
|
}
|
dialogVisible.value = false
|
getCurrentClassList()
|
})
|
}
|
|
// 获取当前班级列表
|
const getCurrentClassList = () => {
|
isLoading.value = true
|
const data = {
|
start: (pages.page - 1) * pages.pageSize,
|
size: pages.pageSize,
|
sort: {
|
type: 'Desc',
|
field: 'CreateDate',
|
subSorts: [],
|
},
|
filterList: [],
|
searchList: searchKey.value
|
? [
|
{
|
keywords: searchKey.value,
|
field: 'Name',
|
compareType: 'Contains',
|
},
|
]
|
: [],
|
}
|
MG.identity.joinedGroupByList(data).then((res: any) => {
|
isLoading.value = false
|
pages.count = res.totalSize
|
if (res.datas) {
|
calssList.value = res.datas.map((item: any) => {
|
return {
|
...item,
|
classTime:
|
moment(item.beginDate).format('YYYY.MM.DD') +
|
'--' +
|
moment(item.endDate).format('YYYY.MM.DD'),
|
bookName: item.linkProductDto.product.name,
|
bookIcon: getPublicImage(item.linkProductDto.product.icon, 100),
|
}
|
})
|
}
|
})
|
}
|
|
// 跳转班级管理
|
const goClassManage = async (item: any) => {
|
if (item.userState == 'WaitValid') {
|
ElMessage({
|
message: '正在审核中....',
|
type: 'warning',
|
})
|
return false
|
}
|
if (item.userState == 'Reject') {
|
ElMessage({
|
message: '审核未通过',
|
type: 'warning',
|
})
|
return false
|
}
|
const bookInfo = await getBookDetail(item.linkProductDto?.product)
|
let info = {
|
id: item.id,
|
name: item.name,
|
icon: bookInfo.icon,
|
rootCmsItemId: bookInfo.rootCmsItemId,
|
bookId: bookInfo.id,
|
author: bookInfo.author,
|
isbn: bookInfo.isbn,
|
bookRefCode: bookInfo.refCode,
|
}
|
let page = router.resolve({
|
path: '/classManage',
|
query: {
|
classInfo: JSON.stringify(info),
|
},
|
})
|
window.open(page.href, '_blank')
|
// router.push({
|
// path: '/classManage',
|
// query: {
|
// classInfo: JSON.stringify(info)
|
// }
|
// })
|
}
|
|
// 获取教材详情
|
const getBookDetail = async (item: any) => {
|
const path = item.refCode ? '*' : config.goodsStore
|
let query = {
|
path,
|
queryType: '*',
|
productId: String(item.id),
|
coverSize: {
|
height: 300,
|
width: 210,
|
},
|
fields: {
|
author: [],
|
isbn: [],
|
},
|
}
|
const res = await MG.store.getProductDetail(query)
|
return res.datas ?? null
|
}
|
|
// 通过code查询班级
|
const getClassDetail = () => {
|
if (codeText.value == '') {
|
ElMessage({
|
message: '请输入邀请码',
|
type: 'warning',
|
})
|
return false
|
}
|
const data = {
|
classIdOrRefCode: codeText.value,
|
}
|
MG.edu
|
.getCourseClass(data)
|
.then((res: any) => {
|
classDetail.value = res
|
})
|
.catch((err: any) => {
|
console.log(err)
|
})
|
}
|
</script>
|
|
<style lang="less" scoped>
|
.coursePage {
|
.tabs {
|
padding: 0 20px;
|
}
|
.headerBox {
|
padding: 5px 20px;
|
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;
|
}
|
}
|
.courseListBox {
|
overflow: hidden;
|
.courseItem {
|
float: left;
|
width: 45%;
|
margin: 0 2% 20px;
|
border-radius: 8px;
|
border: 1px solid #efefef;
|
overflow: hidden;
|
.itemHeader {
|
height: 40px;
|
line-height: 40px;
|
padding: 0 20px;
|
// color: #fff;
|
background-color: #f8f8f8;
|
box-sizing: border-box;
|
.title {
|
font-weight: 600;
|
}
|
div {
|
display: inline-block;
|
}
|
.courseId {
|
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 {
|
padding: 15px;
|
box-sizing: border-box;
|
flex: 1;
|
display: flex;
|
cursor: pointer;
|
.imgBox {
|
width: 90px;
|
height: 120px;
|
margin-right: 20px;
|
}
|
.infoBox {
|
flex: 1;
|
font-size: 12px;
|
padding: 10px 0;
|
p {
|
margin-bottom: 10px;
|
}
|
}
|
}
|
}
|
}
|
.codeContent {
|
width: 100%;
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
padding-bottom: 30px;
|
}
|
.classInfo {
|
padding: 30px 0;
|
border-top: 2px dashed #ccc;
|
|
.itemCon {
|
margin-bottom: 20px;
|
}
|
}
|
.pageBox {
|
padding: 10px 0;
|
display: flex;
|
justify-content: center;
|
}
|
}
|
</style>
|