From 5f00696dfb25bc90034448ceb634ed1ef256681a Mon Sep 17 00:00:00 2001 From: qiyunfeng-create <1940665526@qq.com> Date: 星期四, 21 八月 2025 21:13:35 +0800 Subject: [PATCH] Merge branch 'master' of http://182.92.203.7:2001/r/xiehe_website --- src/views/classManage/classHome.vue | 778 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 778 insertions(+), 0 deletions(-) diff --git a/src/views/classManage/classHome.vue b/src/views/classManage/classHome.vue new file mode 100644 index 0000000..762b46d --- /dev/null +++ b/src/views/classManage/classHome.vue @@ -0,0 +1,778 @@ +<template> + <div class="classManagePage-box"> + <div class="classManagePage-nav" v-if="classInfo"> + <el-breadcrumb :separator-icon="ArrowRight"> + <el-breadcrumb-item>鎴戠殑鐝骇</el-breadcrumb-item> + <el-breadcrumb-item>{{ classInfo?.name }}</el-breadcrumb-item> + <el-breadcrumb-item>鐝骇棣栭〉</el-breadcrumb-item> + </el-breadcrumb> + </div> + <div class="classManagePage-content"> + <div class="content-left fl"> + <div class="classOverview mainBorder"> + <div class=""> + <div class="title mainbg">鐝骇姒傝</div> + </div> + <div class="bodyBox" v-if="currentClass?.name && !classLoading"> + <div class="classInfo"> + <div class="name">{{ currentClass?.name }}</div> + <!-- <div class="time">鎶ュ悕鏃堕棿:2024.7.30--2024-8.03</div> --> + <div class="time">寮�璇炬椂闂�: {{ currentClass?.classTime }}</div> + </div> + <div class="line"></div> + <div class="classInfoBox"> + <div class="iconBox"> + <img :src="currentClass?.bookIcon ? currentClass?.bookIcon : defaultImg" /> + </div> + <div class="infoBox"> + <div class="main">{{ currentClass?.bookName }}</div> + <div class="job">浣滆�咃細{{ classInfo?.author ?? '-' }}</div> + <div class="job">ISBN锛歿{ classInfo?.isbn ?? '-' }}</div> + </div> + </div> + <div class="line"></div> + <div class="classInfo"> + <div class="name">鐝骇浜烘暟</div> + <div class="con"> + <span class="main">{{ currentClass?.memberCount }}</span + >/{{ currentClass?.maxUserCount }} + </div> + </div> + <div class="line"></div> + <div class="classInfo"> + <div class="name">浣滀笟娆℃暟</div> + <div class="con"> + <span class="main">{{ homeworkCount }}</span> + </div> + </div> + <!-- <div class="line"></div> + <div class="classInfo"> + <div class="name">鏁欏杩涘害</div> + <div class="con"><span class="main">0</span>/0</div> + </div> --> + </div> + <div + class="bodyBox" + style="display: flex; justify-content: center; align-items: center" + v-if="classLoading" + > + <div v-loading="classLoading"></div> + </div> + <div v-if="!currentClass && !classLoading"> + <el-empty style="padding: 0" :image-size="100" /> + </div> + </div> + <div class="classNotice"> + <div class="titleBox"> + <div class="border mainbg"></div> + <div class="title"> + <span>鐝骇閫氱煡</span> + <el-icon + style="cursor: pointer" + color="#FF6D00" + v-if="noticeList.length > 0 && userInfo.role == 'Teacher'" + @click="toInfo" + > + <ArrowRightBold /> + </el-icon> + </div> + </div> + <div class="noticeList" v-if="noticeList.length > 0 && !noticeLoading"> + <div class="noticeItem" v-for="(item, index) in noticeList" :key="index"> + <div class="noticeContent"> + <span class="title">{{ item.name }}锛�</span> + <div class="contentText">{{ item.content }}</div> + </div> + <span class="time">{{ item.createDate }}</span> + </div> + </div> + <div v-if="noticeLoading" v-loading="noticeLoading"></div> + <div v-if="noticeList.length == 0 && !noticeLoading" class="notBox"> + <el-empty :image-size="100" /> + </div> + </div> + <div class="classTalk"> + <div class="titleBox"> + <div class="border mainbg"></div> + <div class="title"> + <span>鐝粍璇濋</span> + <el-icon + style="cursor: pointer" + color="#FF6D00" + v-if="messageList.length > 0" + @click="toTalk" + > + <ArrowRightBold /> + </el-icon> + </div> + </div> + <div class="noticeList" v-if="messageList.length > 0 && !messageLoading"> + <div class="noticeItem" v-for="(item, index) in messageList" :key="index"> + <div class="noticeContent"> + <span class="title">{{ item.name }}</span> + <div class="content" v-if="item.publicText"> + <span>{{ item.publicText.publishRole }}锛�</span> + <span>{{ item.publicText.publisher }}</span> + </div> + <span>鏈�杩戝洖澶嶏細{{ item.updateDate }}</span> + </div> + <span class="time">{{ item.createDate }}</span> + </div> + </div> + <div v-if="messageLoading" v-loading="messageLoading"></div> + <div v-if="messageList.length == 0 && !messageLoading" class="notBox"> + <el-empty :image-size="100" /> + </div> + </div> + <div class="classTask"> + <div class="titleBox" style="margin-bottom: 5px"> + <div class="border mainbg"></div> + <div class="title"> + <span>鐝骇浣滀笟姒傝</span> + <!-- <el-icon + style="cursor: pointer" + color="#FF6D00" + v-if="tableData.length > 0" + @click="toWorkList" + > + <ArrowRightBold /> + </el-icon> --> + </div> + </div> + <div class="tableWall"> + <el-table :data="tableData" border style="width: 100%; font-size: 14px" size="small"> + <el-table-column prop="name" label="鍚嶇О" /> + <el-table-column prop="beginDate" label="寮�濮嬫椂闂�" /> + <el-table-column prop="endDate" label="鎴鏃堕棿" /> + <el-table-column prop="submitCount" label="瀹屾垚鎯呭喌(鎻愪氦浜烘暟)" width="180" /> + </el-table> + </div> + </div> + <!-- <div class="classTask"> + <div class="titleBox" style="margin-bottom: 5px"> + <div class="border mainbg"></div> + <div class="title"> + <span>鏁欏浜掑姩</span> + <el-icon + style="cursor: pointer" + color="#FF6D00" + v-if="tableData.length > 0" + @click="toTeaching" + > + <ArrowRightBold /> + </el-icon> + </div> + </div> + <div class="tableWall"> + <el-table :data="[]" border style="width: 100%; font-size: 14px" size="small"> + <el-table-column prop="index" label="搴忓彿" /> + <el-table-column prop="name" label="鏍囬" /> + <el-table-column prop="beginDate" label="浜掑姩瀛︾敓鏁�(宸蹭簰鍔�/鍏ㄩ儴瀛︾敓)" /> + <el-table-column prop="endDate" label="鏈�鍚庢彁浜ゆ椂闂�" /> + </el-table> + </div> + </div> --> + </div> + <div class="content-right fr"> + <div class="assistant"> + <div class="titleBox"> + <div class="border mainbg"></div> + <div class="title">鍔╂暀鍒楄〃</div> + <div class="options"> + <!-- <div class="optionsItem">绉婚櫎</div> --> + <div class="copyIdBtn" @click="copy(currentClass)">澶嶅埗閭�璇风爜</div> + </div> + </div> + <div class="avatarList" style="max-height: 147px; overflow-y: auto"> + <div class="avatarItem" v-for="(item, index) in teacherList" :key="index"> + <el-avatar v-if="item.appUser?.icon" :size="35" :src="item.appUser?.icon" /> + <el-avatar v-else :size="35" :icon="UserFilled" /> + <el-tooltip :content="item.appUser?.name" placement="top" effect="light"> + <span class="userName">{{ item.appUser?.name }}</span> + </el-tooltip> + </div> + <div class="nullBox" v-if="!Sloading && teacherList.length == 0"> + <el-empty :image-size="100" /> + </div> + </div> + </div> + <div class="student"> + <div class="titleBox"> + <div class="border mainbg"></div> + <div class="title">瀛︾敓鍒楄〃</div> + <div class="options"> + <div class="copyIdBtn" @click="copy(currentClass)">澶嶅埗閭�璇风爜</div> + </div> + </div> + <div class="avatarList" style="max-height: 570px; overflow-y: auto"> + <div class="avatarItem02" v-for="(item, index) in studentList" :key="index"> + <el-avatar v-if="item.appUser?.icon" :size="35" :src="item.appUser?.icon" /> + <el-avatar v-else :size="35" :icon="UserFilled" /> + <el-tooltip :content="item.appUser?.name" placement="top" effect="light"> + <span class="userName">{{ item.appUser?.name }}</span> + </el-tooltip> + </div> + <div class="nullBox" v-if="!Sloading && studentList.length == 0"> + <el-empty :image-size="100" /> + </div> + </div> + </div> + </div> + </div> + </div> +</template> + +<script setup lang="ts"> +import { useRoute, useRouter } from 'vue-router' +import { getPublicImage } from '@/assets/js/middleGround/tool.js' +import useClipboard from 'vue-clipboard3' +import { inject, onMounted, ref } from 'vue' +import moment from 'moment' +import { ElMessage } from 'element-plus' +import { ArrowRight, UserFilled } from '@element-plus/icons-vue' +import defaultImg from '@/assets/images/default-book-img.png' + +const { toClipboard } = useClipboard() +const route: any = useRoute() +const router: any = useRouter() +const classInfo = JSON.parse(route.query.classInfo) +const MG: any = inject('MG') +const config: any = inject('config') +const userInfo: any = ref() + +const currentClass = ref() +const classLoading = ref(true) +const messageTopicInfo = ref() +const talkTopicInfo = ref() +const noticeList: any = ref([]) +const noticeLoading = ref(true) +const messageList: any = ref([]) +const messageLoading = ref(true) +const tableData: any = ref([]) +const homeworkCount = ref(0) +const studentList: any = ref([]) +const teacherList: any = ref([]) +const Sloading = ref(false) + +onMounted(() => { + const userCache: any = localStorage.getItem(config.userInfoKey) + if (userCache) { + userInfo.value = JSON.parse(userCache) + } + getData() + getStudentList() + getTaskList() +}) + +// 澶嶅埗 +const copy = async (val: any) => { + try { + await toClipboard(val.refCode) + ElMessage({ + message: '澶嶅埗鎴愬姛', + type: 'success' + }) + } catch (e) { + console.error(e) + } +} + +// 鑾峰彇鐝骇 +const getData = () => { + MG.edu + .getCourseClass({ + ClassIdOrRefCode: String(classInfo.id) + }) + .then((res: any) => { + if (res) { + res.bookName = res.linkProductDto.product.name + res.bookIcon = getPublicImage(res.linkProductDto.product.icon, 100) + res.classTime = + moment(res.beginDate).format('YYYY.MM.DD') + + '--' + + moment(res.endDate).format('YYYY.MM.DD') + } + currentClass.value = res + classLoading.value = false + getTopicInfo() + }) +} + +// 鑾峰彇topic +const getTopicInfo = () => { + const pramas = { + classId: classInfo.id, + refCodes: [config.refCodes.message, config.refCodes.talk] + } + MG.edu.getClassTopic(pramas).then((res: any) => { + const list = res + messageTopicInfo.value = list.find((item: any) => item.refCode == config.refCodes.message) + if (messageTopicInfo.value.id) { + sessionStorage.messageId = messageTopicInfo.value.id + noticeLoading.value = true + getNotice() + } + talkTopicInfo.value = list.find((item: any) => item.refCode == config.refCodes.talk) + if (talkTopicInfo.value.id) { + sessionStorage.talkId = talkTopicInfo.value.id + messageLoading.value = true + getMessage() + } + }) +} + +// 鑾峰彇鐝骇閫氱煡 +const getNotice = () => { + const data = { + start: 0, + size: 3, + appRefCode: config.appRefCode, + topicIdOrRefCode: String(messageTopicInfo.value.id), + sort: { + type: 'Desc', + field: 'CreateDate', + subSorts: [] + } + } + MG.ugc.getTopicMessageList(data).then((res: any) => { + noticeLoading.value = false + const list = res.datas + noticeList.value = list.map((item: any) => { + return { + ...item, + createDate: moment(item.createDate).format('YYYY-MM-DD') + } + }) + }) +} + +// 鑾峰彇鐝骇璇濋 +const getMessage = () => { + const data = { + start: 0, + size: 3, + appRefCode: config.appRefCode, + topicIdOrRefCode: String(talkTopicInfo.value.id), + sort: { + type: 'Desc', + field: 'CreateDate', + subSorts: [] + } + } + MG.ugc.getTopicMessageList(data).then((res: any) => { + messageLoading.value = false + const list = res.datas + messageList.value = list.map((item: any, i: number) => { + const str = item.content.indexOf('publisher') + if (str > -1) { + item.publicText = JSON.parse(item.content) + if (item.publicText && item.publicText.publishRole) { + item.publicText.publishRole = item.publicText.publishRole == 'Teacher' ? '鍔╂暀' : '瀛︾敓' + } + } + return { + ...item, + index: i + 1, + createDate: moment(item.createDate).format('YYYY-MM-DD HH:mm:ss'), + updateDate: moment(item.updateDate).format('YYYY-MM-DD HH:mm:ss') + } + }) + }) +} + +// 鑾峰彇鏁欏笀/瀛︾敓鍒楄〃 +const getStudentList = () => { + Sloading.value = true + const data = { + start: 0, + size: 999, + groupId: classInfo.id, + filterList: [ + { + value: 'Normal', + field: 'State', + subFilters: [] + } + ] + } + MG.identity.getGroupUserList(data).then((res: any) => { + const { datas } = res + Sloading.value = false + let list: any = [] + if (datas.length > 0) { + list = datas.map((item: any, index: number) => { + if (item.linkType == 'Creator') { + const userInfo = item.appUser?.infoList?.find((citem: any) => citem.type == 'teacherInfo') + item.appUser.name = userInfo.name + item.appUser.icon = userInfo.icon + if (userInfo?.data) { + const iconData = JSON.parse(userInfo.data) + item.appUser.icon = getPublicImage(iconData?.relevantCertificates[0]?.md5, 100) ?? '' + } + } + if (item.linkType == 'RefCode' || item.linkType == 'Teacher') { + let userInfo = null + const wechatData = item.appUser?.infoList?.find((citem: any) => citem.type == 'WeChat') + const defaultData = item.appUser?.infoList?.find((citem: any) => citem.type == 'Default') + userInfo = defaultData + if (wechatData?.name) { + userInfo = wechatData + } + item.appUser.name = userInfo.name + item.appUser.icon = userInfo.icon + } + return { + ...item, + index: index + 1, + createDate: moment(item.createDate).format('YYYY-MM-DD') + } + }) + } + teacherList.value = list.filter((item: any) => item.linkType != 'RefCode') + studentList.value = list.filter((item: any) => item.linkType == 'RefCode') + }) +} + +// 鍓嶅線璇濋 +const toTalk = () => { + classInfo.index = 5 + if (userInfo.value?.role != 'Teacher') { + classInfo.index = 3 + } + router.push({ + path: '/talkingPoint', + query: { + classInfo: JSON.stringify(classInfo) + } + }) +} + +// 鍓嶅線閫氱煡 +const toInfo = () => { + classInfo.index = 0 + router.push({ + path: '/info', + query: { + classInfo: JSON.stringify(classInfo) + } + }) +} + +// 鏁欏浜掑姩 +const toTeaching = () => {} + +// 鐝骇浣滀笟姒傝 +const getTaskList = () => { + const data = { + start: 0, + size: 3, + sort: { + type: 'Desc', + field: 'CreateDate', + subSorts: [] + }, + filterList: [ + // { + // value: 'Normal', + // field: 'State', + // subFilters: [] + // }, + { + value: config.taskType.homeWork, + field: 'Type', + subFilters: [] + } + ], + groupId: classInfo?.id + } + MG.edu + .getTaskList(data) + .then((res: any) => { + let list: any = [] + if (res.datas.length > 0) { + list = res.datas + ?.map((item: any) => { + return { + ...item, + beginDate: moment(item.beginDate).format('YYYY-MM-DD'), + endDate: moment(item.endDate).format('YYYY-MM-DD') + } + }) + .slice(0, 3) + } + tableData.value = list + homeworkCount.value = res.totalSize + }) + .catch((e: any) => { + console.log(e) + }) +} +</script> + +<style lang="less" scoped> +.nullBox { + width: 100%; + display: flex; + justify-content: center; +} +.classManagePage-box { + padding: 20px; + .classManagePage-nav { + padding-bottom: 20px; + border-bottom: 1px solid #e6e8ed; + } + .classManagePage-content { + display: flex; + justify-content: space-between; + .content-left { + width: 70%; + min-width: 950px; + .classOverview { + height: 190px; + margin-top: 30px; + border-radius: 10px; + .title { + width: 80px; + text-align: center; + padding: 7px; + border-radius: 8px 0 8px 0; + } + .bodyBox { + display: flex; + justify-content: space-between; + margin-top: 20px; + padding: 0 20px; + .classInfoBox { + padding: 0 20px; + display: flex; + .iconBox { + width: 90px; + height: 120px; + img { + width: 100%; + height: 100%; + object-fit: contain; + } + } + .infoBox { + flex: 1; + padding-left: 10px; + .main { + font-size: 16px; + line-height: 20px; + } + .job { + // padding:10px; + margin-top: 20px; + } + } + } + .line { + width: 1px; + height: 130px; + background: linear-gradient( + 180deg, + rgba(255, 255, 255, 0) 0%, + #b7b7b7 51%, + rgba(255, 255, 255, 0) 100% + ); + } + .classInfo { + padding: 0 20px; + font-size: 16px; + min-width: 120px; + .name { + font-weight: bold; + margin-bottom: 20px; + text-align: center; + } + .con { + margin-top: 40px; + font-size: 22px; + text-align: center; + } + .time { + line-height: 30px; + } + } + } + } + .classNotice { + height: 200px; + margin-top: 20px; + border-radius: 20px; + background: linear-gradient(180deg, #fffcf1 0%, #ffffff 100%); + border: 1px solid rgba(249, 200, 35, 0.2); + } + .classTalk { + height: 200px; + margin-top: 20px; + border-radius: 20px; + background: linear-gradient(180deg, #edf0ff 0%, #ffffff 100%); + border: 1px solid rgba(154, 171, 251, 0.2); + } + .classTask { + min-height: 200px; + margin-top: 20px; + border-radius: 20px; + border: 1px solid #e8ebf5; + .tableWall { + width: 100%; + padding: 10px 5px; + box-sizing: border-box; + } + } + .titleBox { + display: flex; + align-items: center; + margin: 20px 0; + font-size: 16px; + .title { + width: 100%; + display: flex; + justify-content: space-between; + align-items: center; + padding-right: 10px; + } + .border { + width: 4px; + height: 23px; + border-radius: 0px 10px 10px 0px; + margin-right: 10px; + } + } + } + .content-right { + width: 28%; + margin-left: 20px; + min-width: 270px; + + .assistant { + min-height: 160px; + margin-top: 30px; + border-radius: 10px; + border: 1px solid #e8ebf5; + overflow: hidden; + } + .student { + height: 640px; + margin-top: 20px; + border-radius: 10px; + border: 1px solid #e8ebf5; + overflow: hidden; + } + .titleBox { + display: flex; + align-items: center; + margin: 10px 0; + .border { + width: 4px; + height: 23px; + border-radius: 0px 10px 10px 0px; + margin-right: 10px; + } + } + } + .notBox { + width: 100%; + height: 100px; + display: flex; + align-items: center; + justify-content: center; + } + } + .options { + flex: 1; + display: flex; + align-items: center; + justify-content: flex-end; + padding-right: 10px; + .optionsItem { + color: #999; + margin-right: 10px; + cursor: pointer; + } + .copyIdBtn { + background-color: #fff; + color: #3b93fe; + padding: 0 6px; + border-radius: 50px; + overflow: hidden; + cursor: pointer; + } + } + .avatarList { + display: flex; + flex-wrap: wrap; + width: 100%; + padding: 0 20px; + box-sizing: border-box; + .avatarItem, + .avatarItem02 { + width: 68px; + max-height: 88px; + display: flex; + flex-direction: column; + align-items: center; + padding: 6px 4px; + position: relative; + margin-left: 1px; + + .userName { + width: 100%; + margin: 3px 0; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + text-align: center; + min-height: 30px; + line-height: 30px; + font-size: 12px; + } + } + // .avatarItem:hover { + // background-image: url('@/assets/images/class/avabg.png'); + // background-size: 100% 100%; + // background-position: center; + // background-repeat: no-repeat; + // cursor: pointer; + // } + .avatarItem:hover, + .avatarItem02:hover { + background: #eee; + } + } + .noticeList { + width: 100%; + height: calc(100% - 63px); + padding: 5px 25px; + overflow: auto; + .noticeItem { + display: flex; + justify-content: space-between; + font-family: PingFang SC; + font-weight: 400; + font-size: 14px; + line-height: 32px; + .noticeContent { + display: flex; + justify-content: space-between; + color: #000000; + max-width: 800px; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + .title { + margin-right: 30px; + } + .content { + margin-right: 30px; + } + } + .time { + color: #b7b7b7; + } + } + } +} +</style> -- Gitblit v1.9.1