添加学生日历功能

This commit is contained in:
yangjun 2024-12-19 15:01:39 +08:00
parent f6d813dff4
commit 3e3f55612c
4 changed files with 133 additions and 147 deletions

View File

@ -27,54 +27,28 @@
</div> </div>
</template> </template>
<div style="padding: 1rem;"> <div style="padding: 1rem;">
<a-row> <div style="font-size: 16px;float: left;">{{ mainVideoCardBoxTitle || '' }}</div>
<a-col :span="24"> <!-- <div style="float: right;">
<div style="font-size: 16px;float: left;font-weight: 600;">{{ mainVideoCardBoxTitle || '' }}</div> AI识别出勤率{{ calcPercentage((ktangInfo?.detectionMain?.averageNum || 0),(ktangInfo?.jiaoshirongliang?.jsrl || 0))}}&nbsp;&nbsp;
<div style="float: right;"> <template v-if="ktangInfo?.jiaoshirongliang?.jsrl">本教室容量{{ktangInfo?.jiaoshirongliang?.jsrl}}座位</template>
<span>本教室容量</span><span style="font-size: 14px; color:#1c84c6 ;">{{ktangInfo?.jiaoshirongliang?.jsrl || ' '}}座位</span> </div> -->
<span style="margin-left:15px;">选课人数</span><span style="font-size: 14px; color:#1c84c6 ;">{{ ktangInfo.xkrs || ' ' }}</span> <div style="float: right;">
<span style="margin-left:15px;">AI识别出勤人数: <a @click="handleZqrs(ktangInfo)">{{ ktangInfo?.kcDetectionDetailed?.num||'-' }}</a></span> <span>本教室容量{{ktangInfo?.jiaoshirongliang?.jsrl || ' '}}座位</span>
<span style="margin-left:15px;"> <span style="margin-left:15px;">选课人数{{ ktangInfo.xkrs || ' ' }}</span>
<a-tooltip placement="topRight"> <span style="margin-left:15px;">AI识别出勤人数: <a @click="handleZqrs(ktangInfo)">{{ ktangInfo?.kcDetectionDetailed?.num||'-' }}</a></span>
<template #title> <span style="margin-left:15px;">
<span>平台分别在三个时间节点上课后10分钟课中50分钟下课前10分钟抓取学生全景图片进行AI人流量识别当前显示的人数为最近一个时间的人数识别</span> <a-tooltip placement="topRight">
</template> <template #title>
<!-- <Icon icon="ant-design:question-circle-outlined" /> --> <span>平台分别在三个时间节点上课后10分钟课中50分钟下课前10分钟抓取学生全景图片进行AI人流量识别当前显示的人数为最近一个时间的人数识别目前部分教室摄像头拍摄画面广角待更新AI识别出勤人数仅供参考</span>
<span class="helpClass">?</span> </template>
</a-tooltip> <!-- <Icon icon="ant-design:question-circle-outlined" /> -->
</span> <span class="helpClass">?</span>
</a-tooltip>
</div> </span>
</a-col>
<a-col :span="24"> </div>
<div style="width:100%;display: block;text-align: right;font-size:12px; color: #ccc;">
说明目前部分教室摄像头拍摄画面无法覆盖到全体学生AI识别出勤人数仅供参考
</div>
</a-col>
</a-row>
<a-row>
<a-col :span="fpxsShow=='1'?24:12">
<div v-if="fpxsShow != '1'" class="fptitle">教师近景</div>
<div style="height: 1px;background-color: black;width:100%;">&nbsp;</div>
<bVideo ref="mainVideo" videoId="mainVideo" :videoOption="{ autoplay: true }" @load-end="mainVideoLoadEnd"/>
</a-col>
<a-col :span="12" v-show="fpxsShow=='2' || fpxsShow=='3' || fpxsShow=='4'">
<div class="fptitle">学生全景</div>
<div style="height: 1px;background-color: black;width:100%;">&nbsp;</div>
<bVideo ref="main2Video" videoId="main2Video" :videoOption="{ autoplay: true }" @load-end="loadEnd"/>
</a-col>
<a-col :span="12" v-show="fpxsShow=='3' || fpxsShow=='4'">
<div class="fptitle">PPT</div>
<div style="height: 1px;background-color: black;width:100%;">&nbsp;</div>
<bVideo ref="main3Video" videoId="main3Video" :videoOption="{ autoplay: true }" @load-end="loadEnd"/>
</a-col>
<a-col :span="12" v-show="fpxsShow=='4'">
<div class="fptitle">教师全景</div>
<div style="height: 1px;background-color: black;width:100%;">&nbsp;</div>
<bVideo ref="main4Video" videoId="main4Video" :videoOption="{ autoplay: true }" @load-end="loadEnd"/>
</a-col>
</a-row>
<bVideo ref="mainVideo" videoId="mainVideo" :videoOption="{ autoplay: true }" @load-end="mainVideoLoadEnd"/>
<div class="jxDiv"> <div class="jxDiv">
<a-space> <a-space>
<div v-if="ktangInfo?.zyJxdg?.filePath"> <div v-if="ktangInfo?.zyJxdg?.filePath">
@ -103,46 +77,20 @@
</a-col> </a-col>
<a-col :xs="{ span: 24 }" :sm="{ span: 5 }" :lg="{ span: 5 }"> <a-col :xs="{ span: 24 }" :sm="{ span: 5 }" :lg="{ span: 5 }">
<a-row> <a-row>
<a-col :span="24" v-for="(item,index) of tableData" style="text-align: center;" :key="'col-'+index" @click="changeLive(item)"> <a-col :span="24" v-for="(item,index) of tableData" style="text-align: center;" :key="'col-'+index">
<a-card :class="`handClass`"> <a-card>
<div> <div>
<div style="margin-bottom: .5rem;"> <div style="margin-bottom: .5rem;">
<span class="smallTxt miniButton" :class="item.id == curentPlayerVideo.id && fpxsShow=='1'?'activte':''"> <span class="smallTxt miniButton" :class="item.id == curentPlayerVideo.id?'activte':''" @click="changeLive(item)">
<i class="fa-solid fa-right-left"></i>{{ item?.xm }} <i class="fa-solid fa-right-left"></i>{{ item?.xm }}
</span> </span>
<!-- <span class="smallTxt miniButton miniButtonRight" v-show="!item.isShow" @click="(item.isShow = true,initVideo('other-'+item.id))"><i class="fa-solid fa-film"></i>显示缩略窗口</span> --> <span class="smallTxt miniButton miniButtonRight" v-show="!item.isShow" @click="(item.isShow = true,initVideo('other-'+item.id))"><i class="fa-solid fa-film"></i>显示缩略窗口</span>
<!-- <span class="smallTxt miniButton miniButtonRight" v-show="item.isShow" @click="item.isShow = false"><i class="fa-solid fa-film"></i>隐藏缩略窗口</span> --> <span class="smallTxt miniButton miniButtonRight" v-show="item.isShow" @click="item.isShow = false"><i class="fa-solid fa-film"></i>隐藏缩略窗口</span>
</div> </div>
<div style="height: 2rem;">&nbsp;</div> <div style="height: 2rem;">&nbsp;</div>
<!-- <div v-show="item.isShow" :key="'other-div-'+index"> <div v-show="item.isShow" :key="'other-div-'+index">
<!-- <bVideo :key="'other-'+index" :ref="el=> bVideoRefs['other-'+item.id] = el" :videoId="'other-'+item.id" :src="'http://127.0.0.1/hls/a.m3u8'" :videoOption="{ autoplay: true, controls: false }" @load-end="loadEnd"/> -->
<bVideo :key="'other-'+index" :ref="el=> bVideoRefs['other-'+item.id] = el" :videoId="'other-'+item.id" :src="item.pullUrl" :videoOption="{ autoplay: true, controls: false }" @load-end="loadEnd"/> <bVideo :key="'other-'+index" :ref="el=> bVideoRefs['other-'+item.id] = el" :videoId="'other-'+item.id" :src="item.pullUrl" :videoOption="{ autoplay: true, controls: false }" @load-end="loadEnd"/>
</div> -->
</div>
</a-card>
</a-col>
<a-col :span="24">
<a-card @click="changeJfpLive('2')" :class="`handClass`">
<div>
<div style="margin-bottom: .5rem;">
<span :class="`smallTxt miniButton ${fpxsShow=='2'?'activte':''}`" ><i class="fa-solid fa-film"></i>二分屏</span>
</div>
</div>
</a-card>
</a-col>
<a-col :span="24">
<a-card @click="changeJfpLive('3')" class="handClass">
<div >
<div style="margin-bottom: .5rem;">
<span :class="`smallTxt miniButton ${fpxsShow=='3'?'activte':''}`" ><i class="fa-solid fa-film"></i>三分屏</span>
</div>
</div>
</a-card>
</a-col>
<a-col :span="24">
<a-card @click="changeJfpLive('4')" class="handClass">
<div >
<div style="margin-bottom: .5rem;">
<span :class="`smallTxt miniButton ${fpxsShow=='4'?'activte':''}`" ><i class="fa-solid fa-film"></i>四分屏</span>
</div> </div>
</div> </div>
</a-card> </a-card>
@ -218,7 +166,6 @@ const suibiList = ref<Recordable>([])
const isError = ref(false); const isError = ref(false);
const tkbjVisible = ref(false); const tkbjVisible = ref(false);
const playStatus = ref(false); const playStatus = ref(false);
const fpxsShow = ref<any>('1');
const model = reactive<Record<string, any>>({ notes:'' }); const model = reactive<Record<string, any>>({ notes:'' });
@ -255,7 +202,6 @@ onMounted(() => {
//, //,
list({ pageSize: -1, sfyx: '0', jsbh: route.query.id }).then(res => { list({ pageSize: -1, sfyx: '0', jsbh: route.query.id }).then(res => {
let list = (res?.records) ?? []; let list = (res?.records) ?? [];
console.log("🚀 ~ list ~ list:", list)
tableData.value = list; tableData.value = list;
tableData.value.forEach(x => x.isShow = true);// tableData.value.forEach(x => x.isShow = true);//
let zjData = tableData.value.find(x => x.xm == '教师近景') || {}; let zjData = tableData.value.find(x => x.xm == '教师近景') || {};
@ -320,11 +266,11 @@ function funpingjia(record) {
*/ */
function loadEnd(player){ function loadEnd(player){
nextTick(() => { nextTick(() => {
// player.on('play',() => { player.on('play',() => {
// setTimeout(() => { setTimeout(() => {
// player.pause(); player.pause();
// },2000); },2000);
// }) })
}) })
} }
@ -336,7 +282,6 @@ function initVideo(key){
} }
function changeLive(item:any){ function changeLive(item:any){
fpxsShow.value = '1'
let url = item.pullUrl let url = item.pullUrl
let mainVideo = document.querySelector<any>('#mainVideo'); let mainVideo = document.querySelector<any>('#mainVideo');
// mainVideo?.player?.src([{ type:'application/x-mpegURL',src: 'http://127.0.0.1/live_hls/a.m3u8' }]) // mainVideo?.player?.src([{ type:'application/x-mpegURL',src: 'http://127.0.0.1/live_hls/a.m3u8' }])
@ -359,56 +304,6 @@ function changeLive(item:any){
// }) // })
} }
function changeJfpLive(type){
fpxsShow.value = type;
let item= tableData.value.find(x => x.xm == '教师近景') || {};
let url = item.pullUrl
let mainVideo = document.querySelector<any>('#mainVideo');
mainVideo?.player?.src([{ type:'application/x-mpegURL',src: url }])
if(type==2){
let item2= tableData.value.find(x => x.xm == '学生全景') || {};
let url2 = item2.pullUrl
let main2Video = document.querySelector<any>('#main2Video');
main2Video?.player?.src([{ type:'application/x-mpegURL',src: url2 }])
mainVideoCardBoxTitle.value = "二分屏";
}else if(type == 3){
let item2= tableData.value.find(x => x.xm == '学生全景') || {};
let url2 = item2.pullUrl
let main2Video = document.querySelector<any>('#main2Video');
main2Video?.player?.src([{ type:'application/x-mpegURL',src: url2 }])
mainVideoCardBoxTitle.value = "二分屏";
let item3 = tableData.value.find(x => x.xm == 'PPT') || {};
let url3 = item3.pullUrl
let main3Video = document.querySelector<any>('#main3Video');
main3Video?.player?.src([{ type:'application/x-mpegURL',src: url3 }])
mainVideoCardBoxTitle.value = "三分屏";
}else if(type == 4){
let item2= tableData.value.find(x => x.xm == '学生全景') || {};
let url2 = item2.pullUrl
let main2Video = document.querySelector<any>('#main2Video');
main2Video?.player?.src([{ type:'application/x-mpegURL',src: url2 }])
mainVideoCardBoxTitle.value = "二分屏";
let item3 = tableData.value.find(x => x.xm == 'PPT') || {};
let url3 = item3.pullUrl
let main3Video = document.querySelector<any>('#main3Video');
main3Video?.player?.src([{ type:'application/x-mpegURL',src: url3 }])
mainVideoCardBoxTitle.value = "三分屏";
let item4 = tableData.value.find(x => x.xm == '教师全景') || {};
let url4 = item4.pullUrl
let main4Video = document.querySelector<any>('#main4Video');
main4Video?.player?.src([{ type:'application/x-mpegURL',src: url4 }])
mainVideoCardBoxTitle.value = "四分屏";
}
}
function mainVideoLoadEnd(player){ function mainVideoLoadEnd(player){
setTimeout(() => { setTimeout(() => {
setTimeout(() => { setTimeout(() => {
@ -668,13 +563,4 @@ video::-webkit-media-controls-timeline {
border: 1px #1c84c6 solid; border: 1px #1c84c6 solid;
cursor: pointer; cursor: pointer;
} }
.handClass{
cursor: pointer;
}
.fptitle{
background: black;
color: white;
font-weight: 700;
text-align: center;
}
</style> </style>

View File

@ -0,0 +1,88 @@
<template>
<a-alert :message="`当前时间: ${tday}`" />
<a-calendar v-model:value="value" @panelChange="onPanelChange">
<template #dateCellRender="{ current }" >
<ul class="events">
<li v-for="item in getListData(current)" :key="item.content" @click="handleKecheng(item)">
<a-badge :status="item.type" :text="item.content" />
</li>
</ul>
</template>
<!-- 去掉头部年月切换 -->
<template #headerRender="{current}">
</template>
</a-calendar>
</template>
<script lang="ts" setup>
import { defineComponent, ref, onMounted } from 'vue';
import { Dayjs } from 'dayjs';
import { defHttp } from '/@/utils/http/axios';
import { dateFormat } from '/@/utils/common/compUtils';
const value = ref<Dayjs>();
const tday = ref<string>('');
const studentKclist = ref<any>([]);
const getListData = (value: Dayjs) => {
let listData;
var vdays = value.date()
for(var i=0;i<studentKclist.value.length;i++){
var item = studentKclist.value[i]
if(item.days == vdays){
listData = item.list;
}
}
return listData || [];
};
const onPanelChange = (value: Dayjs) => {
tday.value = dateFormat(value,"yyyy-MM");
};
//
function handleKecheng(record){
console.log("🚀 ~ handleKecheng ~ record:", record)
}
//
onMounted(() => {
tday.value = dateFormat(new Date(),"yyyy-MM");
studentKclist.value = [{'days':'3','list':[
{ type: 'warning', content: '课程名称1' },
{ type: 'success', content: '课程名称2' },
]}]
defHttp.get({ url: '/ktgl/kcKetangbiao/getStudentRiliKclist' }).then((res) => {
// dataSource.value = res.records;
console.log("🚀 ~ defHttp.get ~ res.records:", res)
studentKclist.value = [{'days':'3','list':[
{ type: 'warning', content: '课程名称1' },
{ type: 'success', content: '课程名称2' },
]}]
});
});
</script>
<style scoped>
.events {
list-style: none;
margin: 0;
padding: 0;
}
.events .ant-badge-status {
overflow: hidden;
white-space: nowrap;
width: 100%;
text-overflow: ellipsis;
font-size: 12px;
}
.notes-month {
text-align: center;
font-size: 28px;
}
.notes-month section {
font-size: 28px;
}
</style>

View File

@ -3,6 +3,11 @@
<div style="margin-top: 20px"> <div style="margin-top: 20px">
<span style="margin-left: 30px; font-size: 24px; font-weight: 600">我的课程</span> <span style="margin-left: 30px; font-size: 24px; font-weight: 600">我的课程</span>
</div> </div>
<!-- <div>
<studentRili></studentRili>
</div> -->
<div style="text-align: right; width: 100%; padding-right:20px"> <div style="text-align: right; width: 100%; padding-right:20px">
<a-switch style="margin-top:-60px" v-model:checked="checked1" checkedChildren="卡片" unCheckedChildren="列表" /> <a-switch style="margin-top:-60px" v-model:checked="checked1" checkedChildren="卡片" unCheckedChildren="列表" />
</div> </div>
@ -92,6 +97,8 @@ import { defHttp } from '/@/utils/http/axios';
import { ref, onMounted } from 'vue'; import { ref, onMounted } from 'vue';
import { getSysConfig } from '/@/views/site/utils/index'; import { getSysConfig } from '/@/views/site/utils/index';
import studentRili from '/@/views/site/studentWdkc/studentRili.vue';
const checked1 = ref(true); const checked1 = ref(true);
const dataSource = ref([]); const dataSource = ref([]);
// //

View File

@ -25,6 +25,7 @@
<span v-else-if="item.evaluationver=='2'" class="hand" style="padding-left: .5rem;color: #337ab7;">线上听课</span> <span v-else-if="item.evaluationver=='2'" class="hand" style="padding-left: .5rem;color: #337ab7;">线上听课</span>
<span v-else-if="item.evaluationver=='3'" class="hand" style="padding-left: .5rem;color: #337ab7;">听课记录</span> <span v-else-if="item.evaluationver=='3'" class="hand" style="padding-left: .5rem;color: #337ab7;">听课记录</span>
<span v-else-if="item.evaluationver=='4'" class="hand" style="padding-left: .5rem;color: #337ab7;">同行专家</span> <span v-else-if="item.evaluationver=='4'" class="hand" style="padding-left: .5rem;color: #337ab7;">同行专家</span>
<span v-else-if="item.evaluationver=='5'" class="hand" style="padding-left: .5rem;color: #337ab7;">思政评价</span>
<span v-if="item.source != null" class="hand" style="padding-left: .5rem;color: #337ab7;"></span> <span v-if="item.source != null" class="hand" style="padding-left: .5rem;color: #337ab7;"></span>
<span v-if="item.suibiNotes" class="hand" style="padding-left: .5rem;color: #337ab7;"> <span v-if="item.suibiNotes" class="hand" style="padding-left: .5rem;color: #337ab7;">
@ -111,6 +112,10 @@ watch(
function txpjFun(item){ function txpjFun(item){
if(item.kkdw=="马列教研室"){
item.szkc = "1";
}
let ketangbiaoid = item.ketangbiaoid; let ketangbiaoid = item.ketangbiaoid;
let userid = item.userid; let userid = item.userid;
listTkjlApi({ userid: userid, ketangbiaoid:ketangbiaoid,startDate:getSysConfig().bxqkssj,endDate:getSysConfig().bxqjssj}).then(res => { listTkjlApi({ userid: userid, ketangbiaoid:ketangbiaoid,startDate:getSysConfig().bxqkssj,endDate:getSysConfig().bxqjssj}).then(res => {