parent
d0cbb5cbcd
commit
719693bf63
|
@ -130,7 +130,7 @@ export default () => {
|
||||||
case MsgEnum.HEADS.MSG_yh: // 疑惑
|
case MsgEnum.HEADS.MSG_yh: // 疑惑
|
||||||
hooksUpvote.trigger(2)
|
hooksUpvote.trigger(2)
|
||||||
break
|
break
|
||||||
case MsgEnum.HEADS.MSG_pushSreen_ImgList: // 推图片上屏
|
case MsgEnum.HEADS.MSG_pushSreen_ImgList: // 推图片上屏
|
||||||
const imgArray = content.ImgList.map((obj) => obj.url);
|
const imgArray = content.ImgList.map((obj) => obj.url);
|
||||||
emitter.emit('opengridPic',{arr:imgArray}) // 打开推图片上屏窗口
|
emitter.emit('opengridPic',{arr:imgArray}) // 打开推图片上屏窗口
|
||||||
break
|
break
|
||||||
|
|
|
@ -47,8 +47,9 @@
|
||||||
<IconListView class="tool-btn" v-tooltip="'演讲者视图'" @click="changeViewMode('presenter')" />
|
<IconListView class="tool-btn" v-tooltip="'演讲者视图'" @click="changeViewMode('presenter')" />
|
||||||
<IconOffScreenOne class="tool-btn" v-tooltip="'退出全屏'" v-if="fullscreenState" @click="manualExitFullscreen()" />
|
<IconOffScreenOne class="tool-btn" v-tooltip="'退出全屏'" v-if="fullscreenState" @click="manualExitFullscreen()" />
|
||||||
<IconFullScreenOne class="tool-btn" v-tooltip="'进入全屏'" v-else @click="enterFullscreen()" />
|
<IconFullScreenOne class="tool-btn" v-tooltip="'进入全屏'" v-else @click="enterFullscreen()" />
|
||||||
<IconPower class="tool-btn" v-tooltip="'结束放映'" @click="exitScreening()" />
|
<IconPower class="tool-btn" v-if="!classcourse" v-tooltip="'结束放映'" @click="exitScreening()" />
|
||||||
<IconPower class="tool-btn close" v-if="chat.groupid" v-tooltip="'结束课堂'" @click="exitCourse()" />
|
<IconPower class="tool-btn" v-else v-tooltip="'结束课堂'" @click="exitCourse()" size="30" fill="#d0021b" strokeLinecap="butt" />
|
||||||
|
<Share class="tool-btn" v-if="classcourse" v-tooltip="'分享'" @click="ShareCode()" />
|
||||||
</div>
|
</div>
|
||||||
<div :class="['tools-icon',{opacity:iconHide}]" @click.stop="toolTrigger('icon')">
|
<div :class="['tools-icon',{opacity:iconHide}]" @click.stop="toolTrigger('icon')">
|
||||||
<circle-double-down v-if="rightToolsVisible" theme="outline" size="30" fill="#409EFF"/>
|
<circle-double-down v-if="rightToolsVisible" theme="outline" size="30" fill="#409EFF"/>
|
||||||
|
@ -75,7 +76,8 @@ import WritingBoardTool from './WritingBoardTool.vue'
|
||||||
import CountdownTimer from './CountdownTimer.vue'
|
import CountdownTimer from './CountdownTimer.vue'
|
||||||
import emitter from '@/utils/mitt';
|
import emitter from '@/utils/mitt';
|
||||||
import Chat from '../../api/chat' // 聊天
|
import Chat from '../../api/chat' // 聊天
|
||||||
import { CircleDoubleDown, CircleDoubleUp } from '@icon-park/vue-next' // icon-park 图标库
|
import { CircleDoubleDown, CircleDoubleUp, Share } from '@icon-park/vue-next' // icon-park 图标库
|
||||||
|
import { ShareCode } from '@/utils/ppt' // ppt相关
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
changeViewMode: (mode: 'base' | 'presenter') => void
|
changeViewMode: (mode: 'base' | 'presenter') => void
|
||||||
|
@ -198,7 +200,7 @@ const contextmenus = (): ContextmenuItem[] => {
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
// 工具栏按钮触发
|
||||||
const toolTrigger = (type:string) => {
|
const toolTrigger = (type:string) => {
|
||||||
const curT = Date.now()
|
const curT = Date.now()
|
||||||
if (curT - timer.value < 200) return
|
if (curT - timer.value < 200) return
|
||||||
|
|
|
@ -10,9 +10,10 @@
|
||||||
<IconOffScreenOne class="tool-icon" v-else />
|
<IconOffScreenOne class="tool-icon" v-else />
|
||||||
<span>{{ fullscreenState ? '退出全屏' : '全屏' }}</span>
|
<span>{{ fullscreenState ? '退出全屏' : '全屏' }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="tool-btn" @click="ShareCode()"><Share class="tool-icon" /><span>分享</span></div>
|
||||||
<Divider class="divider" />
|
<Divider class="divider" />
|
||||||
<div class="tool-btn" @click="exitScreening()"><IconPower class="tool-icon" /><span>结束放映</span></div>
|
<div class="tool-btn" v-if="!classcourse" @click="exitScreening()"><IconPower class="tool-icon" /><span>结束放映</span></div>
|
||||||
<div class="tool-btn close" @click="exitCourse()" v-if="chat.groupid"><IconPower class="tool-icon" /><span>结束课堂</span></div>
|
<div class="tool-btn" v-else @click="exitCourse()" size="30" fill="#d0021b" strokeLinecap="butt"><IconPower class="tool-icon" /><span>结束课堂</span></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="content">
|
<div class="content">
|
||||||
|
@ -78,6 +79,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import { Share } from '@icon-park/vue-next' // icon-park 图标库
|
||||||
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
|
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
|
||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
import { useSlidesStore, useClasscourseStore } from '../../store'
|
import { useSlidesStore, useClasscourseStore } from '../../store'
|
||||||
|
@ -97,6 +99,7 @@ import CountdownTimer from './CountdownTimer.vue'
|
||||||
import Divider from '../../components/Divider.vue'
|
import Divider from '../../components/Divider.vue'
|
||||||
import emitter from '@/utils/mitt';
|
import emitter from '@/utils/mitt';
|
||||||
import Chat from '../../api/chat' // 聊天
|
import Chat from '../../api/chat' // 聊天
|
||||||
|
import { ShareCode } from '@/utils/ppt' // ppt相关
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
changeViewMode: (mode: 'base' | 'presenter') => void
|
changeViewMode: (mode: 'base' | 'presenter') => void
|
||||||
|
@ -125,7 +128,7 @@ const { slideWidth, slideHeight } = useSlideSize(slideListWrapRef)
|
||||||
const { exitScreening } = useScreening()
|
const { exitScreening } = useScreening()
|
||||||
const { slidesLoadLimit } = useLoadSlides()
|
const { slidesLoadLimit } = useLoadSlides()
|
||||||
const { fullscreenState, manualExitFullscreen } = useFullscreen()
|
const { fullscreenState, manualExitFullscreen } = useFullscreen()
|
||||||
const chat:any = Chat() // 聊天室
|
const chatApi:any = Chat() // 聊天室
|
||||||
|
|
||||||
const remarkFontSize = ref(16)
|
const remarkFontSize = ref(16)
|
||||||
const currentSlideRemark = computed(() => {
|
const currentSlideRemark = computed(() => {
|
||||||
|
@ -134,15 +137,20 @@ const currentSlideRemark = computed(() => {
|
||||||
|
|
||||||
// 切换到指定的幻灯片
|
// 切换到指定的幻灯片
|
||||||
const turnSlideTo = (index: number, e: PointerEvent) => {
|
const turnSlideTo = (index: number, e: PointerEvent) => {
|
||||||
// 课堂信息存在时,不允许翻页
|
const preInd = slideIndex.value
|
||||||
console.log('课堂信息', classcourse, index)
|
|
||||||
if (!!classcourse.value) return
|
|
||||||
turnSlideToIndex(index)
|
turnSlideToIndex(index)
|
||||||
|
if (!!classcourse.value) {// 上课中
|
||||||
|
if (preInd == index) return
|
||||||
|
const animationSteps = 0
|
||||||
|
const animation = index > preInd?'Nextsteps':'Previoustep'
|
||||||
|
const msg = { current:index, animation, animationSteps}
|
||||||
|
chatApi.slideFlapping(msg)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// 下课
|
// 下课
|
||||||
const exitCourse = async () => {
|
const exitCourse = async () => {
|
||||||
// console.log('下课', chat)
|
// console.log('下课', chat)
|
||||||
await chat.exitCourse() // 下课消息
|
await chatApi.exitCourse() // 下课消息
|
||||||
exitScreening() // 结束放映
|
exitScreening() // 结束放映
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -102,4 +102,16 @@ export function setPaging(data) {
|
||||||
data
|
data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* 获取分享码(邀请码)
|
||||||
|
* @param {*} id 课堂id
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function getShareCode(id) {
|
||||||
|
return request({
|
||||||
|
url: '/education/classcourse/refresh/code',
|
||||||
|
method: 'post',
|
||||||
|
data: { id }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,10 @@ import { toPng, toJpeg } from 'html-to-image' // 引入html-to-image库
|
||||||
import { PPTXFileToJson } from "@/AixPPTist/src/hooks/useImport"
|
import { PPTXFileToJson } from "@/AixPPTist/src/hooks/useImport"
|
||||||
import ThumbnailSlide from '@/AixPPTist/src/views/components/ThumbnailSlide/index.vue'
|
import ThumbnailSlide from '@/AixPPTist/src/views/components/ThumbnailSlide/index.vue'
|
||||||
import { useSlidesStore } from '@/AixPPTist/src/store'
|
import { useSlidesStore } from '@/AixPPTist/src/store'
|
||||||
|
import * as ElementPlus from 'element-plus'
|
||||||
|
import { sessionStore } from '@/utils/store' // electron-store 状态管理
|
||||||
|
import * as Http_Classcourse from '@/api/teaching/classcourse' // api接口
|
||||||
|
|
||||||
// 延时
|
// 延时
|
||||||
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
|
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
|
||||||
|
|
||||||
|
@ -84,4 +88,44 @@ export const slidesToImg = (slides = [], options) => {
|
||||||
export const pptToImg = async(file, options) => {
|
export const pptToImg = async(file, options) => {
|
||||||
const { slides } = await PPTXFileToJson(file)
|
const { slides } = await PPTXFileToJson(file)
|
||||||
return slidesToImg(slides, options)
|
return slidesToImg(slides, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 课堂-分享码
|
||||||
|
*/
|
||||||
|
export const ShareCode = async(code, cb) => {
|
||||||
|
let shareCode
|
||||||
|
if (typeof code =='string') shareCode = code
|
||||||
|
else { // 自动获取邀请码
|
||||||
|
const classcourse = sessionStore.get('curr.classcourse') // 课堂信息
|
||||||
|
if (!classcourse) return ElementPlus.ElMessage.warning('没有课堂信息')
|
||||||
|
const isRefresh = typeof code == 'boolean' && code // 是否刷新邀请码
|
||||||
|
shareCode = classcourse.shareCode
|
||||||
|
if (!shareCode || isRefresh) { // 获取邀请码
|
||||||
|
const res = await Http_Classcourse.getShareCode(classcourse.id)
|
||||||
|
shareCode = res.msg
|
||||||
|
// 更新邀请码
|
||||||
|
sessionStore.set('curr.classcourse.shareCode', shareCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const msg = h('div', [
|
||||||
|
h('h1', [`我的邀请码:`, h('b',{style:{color:'#F56C6C',fontSize:'1.5em'}}, shareCode)]),
|
||||||
|
h('div', {style:{color:'#E6A23C',fontSize:'13px'}}, `该邀请码1小时内有效,请在学生端填写邀请码后即可进入课堂。`)
|
||||||
|
])
|
||||||
|
return ElementPlus.ElMessageBox.alert(msg, '分享课程', {
|
||||||
|
confirmButtonText: '更新',
|
||||||
|
cancelButtonText: '关闭',
|
||||||
|
showCancelButton: true,
|
||||||
|
|
||||||
|
beforeClose: (action, instance, done) => {
|
||||||
|
if (action =='confirm') { // 更新
|
||||||
|
if (!!cb) { // 回调
|
||||||
|
cb({ h, instance, action, done }, done) && done()
|
||||||
|
} else { // 默认更新
|
||||||
|
ShareCode(true)
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
} else done()
|
||||||
|
}
|
||||||
|
}).catch(() => {})
|
||||||
}
|
}
|
|
@ -60,8 +60,8 @@
|
||||||
<template #item_mobile>
|
<template #item_mobile>
|
||||||
<div>
|
<div>
|
||||||
<div v-if="myClassActive.filetype=='apt'">开始新的课堂,需要点击先创建课堂,才能显示手机二维码</div>
|
<div v-if="myClassActive.filetype=='apt'">开始新的课堂,需要点击先创建课堂,才能显示手机二维码</div>
|
||||||
<div v-else>开始新的课堂,需要点击先创建课堂</div>
|
<div v-else>开始新的课堂</div>
|
||||||
<el-button type="warning" :loading="dt.loading" @click="createClasscourse()">创建课堂</el-button>
|
<!-- <el-button type="warning" :loading="dt.loading" @click="createClasscourse()">创建课堂</el-button> -->
|
||||||
<el-button type="success" @click="createClasscourse(true)">公屏上课</el-button>
|
<el-button type="success" @click="createClasscourse(true)">公屏上课</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -139,6 +139,8 @@ onMounted(() => {
|
||||||
* @param classObj 课程对象-用于继续上课
|
* @param classObj 课程对象-用于继续上课
|
||||||
*/
|
*/
|
||||||
const open = async (id, classObj) => {
|
const open = async (id, classObj) => {
|
||||||
|
dt.loading = false
|
||||||
|
dt.loadingDel = false
|
||||||
visible.value = true
|
visible.value = true
|
||||||
if (id) {
|
if (id) {
|
||||||
// 重置数据
|
// 重置数据
|
||||||
|
@ -167,6 +169,8 @@ const handleClose = async () => {
|
||||||
// await chat?.logout()
|
// await chat?.logout()
|
||||||
// chat = null
|
// chat = null
|
||||||
dt.ctCourse = null
|
dt.ctCourse = null
|
||||||
|
dt.loading = false
|
||||||
|
dt.loadingDel = false
|
||||||
emit('close')
|
emit('close')
|
||||||
}
|
}
|
||||||
// 初始化-数据
|
// 初始化-数据
|
||||||
|
@ -264,7 +268,7 @@ const createClasscourse = async (isPublic = false) => {
|
||||||
}
|
}
|
||||||
// teacherForm.form.classcourseid = 100
|
// teacherForm.form.classcourseid = 100
|
||||||
teacherForm.form.classcourseid = await Http_Classcourse.addClasscourseReturnId(params)
|
teacherForm.form.classcourseid = await Http_Classcourse.addClasscourseReturnId(params)
|
||||||
dt.loading = false
|
.finally(() => {dt.loading = false})
|
||||||
// getClasscourseList('update') // 更新列表
|
// getClasscourseList('update') // 更新列表
|
||||||
let msgEl = ElMessage.success('创建课程-成功')
|
let msgEl = ElMessage.success('创建课程-成功')
|
||||||
// 新版-pptList 打开公屏
|
// 新版-pptList 打开公屏
|
||||||
|
|
Loading…
Reference in New Issue