Commit a4867188 authored by 罗超's avatar 罗超

教室管理

parent 9de1fefc
......@@ -24,6 +24,7 @@
"cos-js-sdk-v5": "^1.1.5",
"echarts": "^5.1.2",
"element-ui": "^2.14.1",
"flv.js": "^1.6.2",
"html2canvas": "^1.3.2",
"js-md5": "^0.7.3",
"jsencrypt": "^3.2.1",
......@@ -36,6 +37,8 @@
"quasar": "^1.0.0",
"relation-graph": "^1.0.8",
"v-viewer": "^1.5.1",
"videojs-flash": "^2.2.1",
"videojs-swf": "^5.4.2",
"vue-amap": "^0.5.10",
"vue-apexcharts": "^1.6.2",
"vue-draggable-resizable": "^1.7.2",
......
......@@ -51,11 +51,14 @@ module.exports = function (ctx) {
// API: 'http://192.168.10.46:8300/api',
// API: 'https://eduapi.oytour.com/api',
API_ZC: 'http://192.168.10.17:8087/api',
API_SK: 'ws:192.168.10.214:'
API_SK: 'ws:192.168.10.214:',
API_SIG: 'http://localhost:5001/messagecenter'
} : {
API: 'https://eduapi.oytour.com/api',
API_ZC: 'http://propertyedu.oytour.com/api',
API_SK: 'ws://47.96.23.199:'
API_SK: 'ws://47.96.23.199:',
API_SK_WSS: 'wss://sk.kookaku.com',
API_SIG: 'http://eduapi.oytour.com/messagecenter'
},
// transpile: false,
......@@ -75,12 +78,11 @@ module.exports = function (ctx) {
// https://quasar.dev/quasar-cli/handling-webpack
extendWebpack(cfg) {
// cfg.module.rules.push({
// enforce: 'pre',
// test: /\.(js|vue)$/,
// loader: 'eslint-loader',
// exclude: /node_modules/
// })
cfg.module.rules.push({
enforce: 'pre',
test: /\.swf$/,
loader: 'url-loader'
})
}
},
......@@ -252,7 +254,7 @@ module.exports = function (ctx) {
// More info: https://quasar.dev/quasar-cli/developing-electron-apps/node-integration
nodeIntegration: true,
extendWebpack( /* cfg */ ) {
extendWebpack( /* cfg */) {
// do something with Electron main process Webpack cfg
// chainWebpack also available besides this extendWebpack
}
......
......@@ -25,7 +25,7 @@ export default {
</script>
<style>
@import url("//at.alicdn.com/t/font_2077629_0n6sqaodu4f.css");
@import url("//at.alicdn.com/t/font_2077629_s183916p0bb.css");
@font-face {
font-family: "din";
src: url("./assets/font/DIN-Bold.otf") format("opentype");
......
......@@ -2,7 +2,12 @@
font-family: 'perfectFont';
src: url('../font/MicrosoftYaHeiLight.woff') format('woff');
}
@font-face {
font-family: 'pingfang';
src: url('../font/PingFang2.ttf');
}
.perfectFont {
font-family: 'perfectFont' !important;
}
......@@ -389,7 +389,7 @@ export default {
that.injectTCCC(
r.Data.Token,
1400617921,
this.userInfo.Email,
that.userInfo.Email,
r.Data.SdkURL
);
}
......
<template>
<div class="page-body room-list" v-loading="loading">
<div v-for="item in classdata" :key="item.Key" class="school-item">
<div class="school-name">{{item.SchoolName}}</div>
<div class="classroom-box">
<div v-for="(_item,_index) in item.RoomList" :key="item.RoomId" >
<div class="classroom-item q-mr-lg q-mb-lg" :class="{'classroom-item-noUse':_item.UserRate==0}" >
<div @click="goUrl(item,_item)">
<div class="divCalssRoom"> <el-image class="classroom-img" :src="_item.RoomPicList[0]" fit="cover" >
<div slot="error" class="image-slot">
<img src="../../assets/images/classroom/bg-img.jpg" alt="" srcset="" style=" opacity: 0.8;">
<div v-for="(item, i) in classdata" :key="item.Key">
<template
v-if="
item.SchoolName.indexOf('武侯') == -1 &&
item.SchoolName.indexOf('眉山') == -1
"
>
<div class="row items-center">
<div class="text-h6 col">{{ item.SchoolName }}</div>
<div v-if="i == 0" class="f12">只看在线:</div>
<div v-if="i == 0">
<el-switch
v-model="queryStatus"
@change="changeViewStatusHandler"
></el-switch>
</div>
</el-image></div>
</div>
<div class="classroom-name" >{{_item.RoomName}}
<!-- <img src="../../assets/images/classroom/warning.png" class="q-ml-sm" v-if="_item.warn">
<img src="../../assets/images/classroom/normal.png" class="q-ml-sm" v-if="!_item.warn"> -->
</div>
<q-knob
show-value
font-size="0.1rem"
v-model="_item.user"
size="50px"
:thickness="0.1"
color="primary"
track-color="grey-3"
class="q-ma-md classroom-user"
readonly
style="text-align: center"
<div class="q-mt-md q-mb-lg row">
<template v-for="(x, xi) in item.RoomList">
<div
class="class-room"
style="width:calc(20% - 10px);margin-right:10px;margin-bottom:10px;"
v-if="queryStatus == 0 || (queryStatus == 1 && x.StatusInfo)"
:key="xi"
>
<div class="img-box">
<q-img
:src="x.RoomPicList[0]"
height="100%"
fit="fill"
spinner-color="primary"
spinner-size="30px"
v-if="x.RoomPicList && x.RoomPicList.length > 0"
/>
<q-img
src="../../assets/images/classroom/bg-img.jpg"
fit="fill"
height="100%"
spinner-color="primary"
spinner-size="30px"
v-else
/>
</div>
<div class="xuhua"></div>
<div class="q-pa-md">
<div class="row items-end">
<div style="font-size:18px;" class="col">
{{ x.RoomName }}
</div>
<div class="f12 q-ml-md text-grey-5">
<div class="text-right">时段</div>
<div class="text-dark">
{{ x.StartTime }} - {{ x.EndTime }}
</div>
</div>
</div>
<div class="q-mt-lg f12 row items-center">
<div class="text-grey-6 f12 col">
<span
class="q-px-xs text-white q-mr-md inline-block text-weight-bold"
style="border-radius:4px;font-size:15;"
:class="{
'bg-grey-3': !x.StatusInfo,
'bg-negative': x.StatusInfo
}"
>
LIVE
</span>
<span class="text-grey-6" v-if="!x.StatusInfo"
>设备离线</span
>
{{ _item.UserRate}}%
<br/>
使用率
</q-knob>
<div class="classroom-info">
<div v-if="_item.TimeList.length>0">
<q-carousel
v-model="_item.slide"
animated
:navigation="false"
height="75px"
class=" text-white shadow-1 rounded-borders"
arrows
control-color="grey-1"
control-text-color="primary"
control-type="unelevated"
<span
class="text-grey-6"
v-else-if="x.StatusInfo.UnLockUserName == 'lock'"
>设备在线,未解锁</span
>
<span class="text-grey-6" v-else
>{{ x.StatusInfo.UnLockUserName }}正在使用</span
>
<q-carousel-slide v-for="(slide,slideIndex) in _item.TimeList" :key="slideIndex" :name="slideIndex" >
<div class="info-box">
<div class="time">{{ slide.StartTime }}</div>
<div class="info">{{slide.TeacherName}}{{slide.ClassName}}</div>
</div>
</q-carousel-slide>
</q-carousel>
<div v-if="x.StatusInfo">
<q-btn
color="primary"
dense
class="f12"
flat
label="链接"
@click="openVideo(x)"
/>
</div>
<div v-if="_item.TimeList.length===0" class="no-data">
暂无课程安排
</div>
</div>
</div>
</template>
</div>
</template>
</div>
<q-dialog v-model="showVideo" @hide="clearVideo">
<q-card
class="my-card"
style="width:60vw !important;max-width:60vw !important;max-height:unset !important;"
flat
>
<!-- <q-card-section>
<div class="text-h6" v-if="currentRoom">
{{ currentRoom.RoomName }}
</div>
</q-card-section> -->
<q-card-section>
<video
id="my_video"
class="video-js vjs-default-skin"
controls
preload
v-if="showVideo"
></video>
</q-card-section>
</q-card>
</q-dialog>
</div>
</template>
<script>
import {
getUseClassRoomList
} from '../../api/classroom/index';
export default {
import { getUseClassRoomList } from "../../api/classroom/index";
import * as signalR from "@aspnet/signalr";
import videojs from "video.js";
import "videojs-contrib-hls";
export default {
meta: {
title: "教室状态"
},
data() {
return {
classdata:[
{
SchoolName:"锦江校区一",
list:[
{
slide:0,
img:"",
classroom:'樱花教室',
user:80,
warn:0,
course:[]
classdata: [],
loading: true,
showVideo: false,
videoObj: null,
currentRoom: null,
queryStatus: 0,
connection: "", //signalr连接
roomStatusList: [] //返回消息
};
},
]
}
],
loading: true,
created() {
let thisVue = this;
console.log(process.env.API_SIG);
this.connection = new signalR.HubConnectionBuilder()
.withUrl(process.env.API_SIG, {
skipNegotiation: true,
transport: signalR.HttpTransportType.WebSockets
})
.configureLogging(signalR.LogLevel.Information)
.build();
this.connection.on("RoomStatusChange", function(message) {
thisVue.roomStatusList = JSON.parse(message);
console.log(thisVue.roomStatusList);
thisVue.changeStatus();
});
this.connection.onclose(async () => {
setTimeout(() => {
thisVue.linkHub();
}, 3000);
});
};
this.linkHub();
},
mounted(){
mounted() {
this.getList();
//this.openVideo();
},
methods:{
goUrl(x,y){
this.$router.push({
path:"/classroom/useRecord",
query:{
key:x.Key,
roomId:y.RoomId
methods: {
changeViewStatusHandler() {},
clearVideo() {
this.videoObj.dispose();
this.showVideo = false;
},
openVideo(item) {
this.showVideo = true;
this.currentRoom = item;
this.$nextTick(() => {
this.videoObj = videojs("my_video", {
controls: true, //是否显示播放器控件
autoplay: true, //是否自动播放
sources: [
{
type: "application/x-mpegURL",
src: `http://47.96.12.235:5000/live/${item.RoomId}.m3u8`
}
]
});
this.videoObj.play();
setTimeout(() => {
document
.getElementById("my_video_html5_api")
.setAttribute("controls", "controls");
}, 2000);
});
},
changeStatus() {
this.initStatus();
if (this.roomStatusList && this.roomStatusList.length > 0) {
this.roomStatusList.forEach(x => {
this.classdata.forEach(y => {
y.RoomList.forEach(z => {
if (z.RoomId == x.RoomId) {
z.StatusInfo = x;
}
});
});
});
}
this.$forceUpdate();
},
initStatus() {
this.classdata.forEach(y => {
y.RoomList.forEach(z => {
this.classdata.forEach(y => {
y.RoomList.forEach(z => {
z.StatusInfo = null;
});
});
});
});
this.$forceUpdate();
},
linkHub() {
let thatVue = this;
this.connection
.start()
.then(() => {
console.log("linke success");
thatVue.connection.invoke("RegistErp", "IMERP");
})
.catch(e => {
console.log(e);
setTimeout(() => {
thatVue.linkHub();
}, 3000);
});
},
goUrl(x, y) {
this.$router.push({
path: "/classroom/useRecord",
query: {
key: x.Key,
roomId: y.RoomId
}
});
},
getList() {
getUseClassRoomList({}).then(res => {
this.loading = false
if(res.Code===1){
getUseClassRoomList({})
.then(res => {
this.loading = false;
if (res.Code === 1) {
res.Data.forEach(e => {
e.RoomList.forEach(_e=>{
_e.slide=0
})
e.RoomList.forEach(_e => {
_e.slide = 0;
});
});
this.classdata=res.Data
this.classdata = res.Data;
this.changeStatus();
}
}).catch(() => {
this.loading = false;
})
},
.catch(() => {
this.loading = false;
});
}
};
</script>
<style lang="scss" scoped>
.school-item{
margin-bottom: 10px;
.school-name{
font-size: 16px;
font-family: Microsoft YaHei;
font-weight: bold;
color: #000000;
margin-bottom: 30px;
}
.classroom-box{
width: 1680px;
display: flex;
// justify-content: space-between;
flex-wrap: wrap;
.classroom-item-noUse{
opacity:0.8;
}
.classroom-item{
width: 390px;
height: 235px;
background: #FFFFFF;
border: 1px solid #EBEBEB;
box-shadow: 0px 1px 1px 0px #E4E7FB;
border-radius: 16px;
};
</script>
<style>
.class-room {
border: 1px solid #f5f5f5;
border-radius: 10px;
position: relative;
overflow: hidden;
.classroom-img{
display: block;
width: 390px;
// height: 160px;
// border-radius: 16px;
background-color: #333;
overflow: hidden;
}
.divCalssRoom{
height: 160px;
border-radius: 16px;
overflow: hidden;
}
.classroom-name{
position: absolute;
top: 20px;
left: 20px;
z-index: 5999;
font-size: 20px;
font-family: PingFang SC;
font-weight: 800;
color: #FFFFFF;
display: flex;
align-items: center;
}
.classroom-user{
}
.class-room .img-box {
height: 80px;
}
.class-room .xuhua {
position: absolute;
top: 10px;
right: 10px;
z-index: 5999;
color: #FFFFFF;
}
.classroom-info{
width: 390px;
height: 75px;
// background-color: tomato;
.info-box{
height: 43px;
display: flex;
align-items: center;
justify-content: flex-start;
box-sizing: border-box;
padding: 0 40px;
.time{
font-size: 14px;
font-family: PingFang SC;
font-weight: bold;
color: #6D97FF;
margin-right: 10px;
}
.info{
// width: 225px;
height: 100%;
font-size: 14px;
font-family: PingFang SC;
display: flex;
align-items: center;
color: #000000;
}
}
}
}
}
top: 0;
height: 80px;
left: 0;
right: 0;
backdrop-filter: blur(4px);
}
.no-data{
.class-room:hover .xuhua {
backdrop-filter: none;
}
.no-data {
height: 75px;
font-size: 14px;
color: #000000;
......@@ -239,7 +300,23 @@ import {
justify-content: center;
align-items: center;
}
.room-list{
overflow: scroll;
.video-js div,
.video-js button {
display: none !important;
}
.video-js {
width: 100%;
}
.video-js video {
width: 100%;
}
.video-js .no-video {
display: flex;
height: 100%;
font-size: 14px;
text-align: center;
justify-content: center;
align-items: center;
background: #000;
}
</style>
......@@ -191,6 +191,11 @@ export default {
immediate: true
}
},
mounted() {
if (tccc && tccc.Agent) {
tccc.Agent.offline();
}
},
methods: {
callBackUserInfo(code) {
setUserCodeCallBack({
......@@ -228,7 +233,7 @@ export default {
const s = document.createElement("script");
s.type = "text/javascript";
s.src =
"http://wwcdn.weixin.qq.com/node/wework/wwopen/js/wwLogin-1.2.5.js";
"https://wwcdn.weixin.qq.com/node/wework/wwopen/js/wwLogin-1.2.5.js";
const wxElement = document.body.appendChild(s);
// 调用企业微信二维码方法
wxElement.onload = function() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment