ppt上课

This commit is contained in:
zdg 2024-12-10 10:08:53 +08:00
parent 97962d591f
commit 38c041465e
10 changed files with 84 additions and 28 deletions

View File

@ -17,8 +17,8 @@ VITE_APP_RES_FILE_PATH = 'https://file.ysaix.com:7868/src/assets/textbook/booktx
VITE_APP_BUILD_BASE_PATH = 'https://file.ysaix.com:7868/' VITE_APP_BUILD_BASE_PATH = 'https://file.ysaix.com:7868/'
# websocket 地址 # websocket 地址
# VITE_APP_WS_URL = 'wss://file.ysaix.com:7868' VITE_APP_WS_URL = 'wss://file.ysaix.com:7868'
VITE_APP_WS_URL = 'ws://192.168.2.16:7865' # VITE_APP_WS_URL = 'ws://192.168.2.16:7865'
# 是否显示开发工具 # 是否显示开发工具
VITE_SHOW_DEV_TOOLS = 'true' VITE_SHOW_DEV_TOOLS = 'true'

View File

@ -27,8 +27,8 @@ import msgUtils from '@/plugins/modal' // 消息工具
import * as API_entpcoursefile from '@/api/education/entpcoursefile' // api import * as API_entpcoursefile from '@/api/education/entpcoursefile' // api
import { PPTApi } from './api' import { PPTApi } from './api'
import { sessionStore } from '@/utils/store' // electron-store import { sessionStore } from '@/utils/store' // electron-store
import './api/watcher' //
import './api/classcourse' // import './api/classcourse' //
import './api/watcher' //
const loading = ref(true) const loading = ref(true)
const _isPC = isPC() const _isPC = isPC()

View File

@ -2,20 +2,20 @@
* @author zdg * @author zdg
* @description * @description
*/ */
import type { Classcourse } from './types' // import type { Classcourse } from './types'
import { sessionStore } from '@/utils/store' // electron-store 状态管理 import { sessionStore } from '@/utils/store' // electron-store 状态管理
import * as useStore from '../store' // pptist-状态管理 import * as useStore from '../store' // pptist-状态管理
import { ChatWs } from '@/plugins/socket' // 聊天socket import ChatWs from '@/plugins/socket' // 聊天socket
const screenStore = useStore.useScreenStore() // 全屏-状态管理 const screenStore = useStore.useScreenStore() // 全屏-状态管理
const classcourseStore = useStore.useClasscourseStore() // 课堂信息-状态管理 const classcourseStore = useStore.useClasscourseStore() // 课堂信息-状态管理
const classcourse: Classcourse = sessionStore.get('curr.classcourse') // 课堂信息 const classcourse = sessionStore.get('curr.classcourse') // 课堂信息
// 如果课堂信息有值则连接socket // 如果课堂信息有值则连接socket
if (!!classcourse) { if (!!classcourse) {
// 连接socket // 连接socket
const ws = new ChatWs() if (!ChatWs.ws) ChatWs.init()
console.log('ws- ',ws) ChatWs.id = classcourse.timgroupid // 群组id
// ChatWs.connect(classcourse.id) console.log('ws- ',ws, classcourse)
classcourseStore.setClasscourse(classcourse) classcourseStore.setClasscourse(classcourse)
} }
// 打开全屏 // 打开全屏

View File

@ -3,7 +3,7 @@
* @author zdg * @author zdg
* @date 2024-11-26 * @date 2024-11-26
*/ */
import { toRaw } from 'vue' import { toRaw, nextTick } from 'vue'
import type { Result } from './types' // 接口类型 import type { Result } from './types' // 接口类型
import msgUtils from '@/plugins/modal' // 消息工具 import msgUtils from '@/plugins/modal' // 消息工具
import * as API_entpcoursefile from '@/api/education/entpcoursefile' // 相关api import * as API_entpcoursefile from '@/api/education/entpcoursefile' // 相关api
@ -12,6 +12,8 @@ import * as useStore from '../store' // pptist-状态管理
import { sessionStore } from '@/utils/store' // electron-store 状态管理 import { sessionStore } from '@/utils/store' // electron-store 状态管理
import useUserStore from '@/store/modules/user' // 外部-用户信息 import useUserStore from '@/store/modules/user' // 外部-用户信息
import { toPng, toJpeg } from 'html-to-image' // 引入html-to-image库
const slidesStore = useStore.useSlidesStore() const slidesStore = useStore.useSlidesStore()
const userStore = useUserStore() const userStore = useUserStore()
@ -142,6 +144,8 @@ export class PPTApi {
// 更新幻灯片 // 更新幻灯片
static updateSlide(data: object): Promise<Boolean> { static updateSlide(data: object): Promise<Boolean> {
return new Promise(async (resolve, reject) => { return new Promise(async (resolve, reject) => {
const thumUrl = await this.getSlideThumUrl()
data.base64Code = thumUrl // 更新缩略图
const res: Result = await API_entpcoursefile.updateEntpcoursefileNew(data) const res: Result = await API_entpcoursefile.updateEntpcoursefileNew(data)
if (res.code === 200) { if (res.code === 200) {
resolve(true) resolve(true)
@ -184,6 +188,21 @@ export class PPTApi {
else msgUtils.msgError(res.msg || '更新失败');return false else msgUtils.msgError(res.msg || '更新失败');return false
}) })
} }
// thumbnail-slide thumbnail
static getSlideThumUrl(): Promise<Boolean> {
return nextTick().then(async() => {
const slideIndex = slidesStore.slideIndex
const elements = document.querySelectorAll('.thumbnail-slide')
if (elements.length && slideIndex >= 0) {
const element = elements[slideIndex]
return await toPng(element)
}
return null
})
// return API_smarttalk.updateThumbnail().then(res => {
// if (res.code === 200) return true
// else msgUtils.msgError(res.msg || '更新失败');return false
}
} }
export default PPTApi export default PPTApi

View File

@ -19,6 +19,7 @@ export interface Classcourse {
entpcoursefileid?: number|string, // 课程文件id entpcoursefileid?: number|string, // 课程文件id
classid?: number|string, // 班级id classid?: number|string, // 班级id
entpcourseid?: number|string, // 章节中间表id entpcourseid?: number|string, // 章节中间表id
timgroupid?: number|string, // ws 群组id
plandate?: string, // 计划时间 plandate?: string, // 计划时间
opendate?: string, // 开课时间 opendate?: string, // 开课时间
} }

View File

@ -6,6 +6,7 @@ import { watch } from 'vue'
import { PPTApi } from './index' import { PPTApi } from './index'
import * as store from '../store' import * as store from '../store'
import { sessionStore } from '@/utils/store' // electron-store 状态管理 import { sessionStore } from '@/utils/store' // electron-store 状态管理
import ChatWs from '@/plugins/socket' // 聊天socket
const slidesStore = store.useSlidesStore() const slidesStore = store.useSlidesStore()
const resource = sessionStore.get('curr.resource') // apt 资源 const resource = sessionStore.get('curr.resource') // apt 资源
const smarttalk = sessionStore.get('curr.smarttalk') // 备课资源 const smarttalk = sessionStore.get('curr.smarttalk') // 备课资源
@ -24,6 +25,19 @@ watch(() => slidesStore.title, (newVal, oldVal) => {
updatePPT({title: newVal}) updatePPT({title: newVal})
}) })
// 消息监听ws
if (ChatWs.ws) {
ChatWs.watch((msg, e) => {
try {
handleMessage(JSON.parse(msg))
} catch (error) {
console.error('socket 解析异常 ', error, e)
handleMessage(msg)
}
})
}
// 更新ppt内容
const updatePPT = async (data) => { const updatePPT = async (data) => {
if (!resource) return if (!resource) return
data.id = resource.id data.id = resource.id
@ -37,3 +51,19 @@ const updatePPT = async (data) => {
sessionStore.set('curr.smarttalk.fileShowName', params.fileShowName) sessionStore.set('curr.smarttalk.fileShowName', params.fileShowName)
} }
} }
// ws消息处理
const handleMessage = (msg) => {
if (typeof msg === 'object'){
const { head, content, ...other } = msg
console.log('ws-msg', head, content, other)
switch (head) {
case 'chat':
break
case 'update':
break
default:
break
}
}
}

View File

@ -2,7 +2,7 @@ import { defineStore } from 'pinia'
import type { Classcourse } from '../api/types' import type { Classcourse } from '../api/types'
export interface ClasscourseState { export interface ClasscourseState {
classcourse: Classcourse classcourse: Classcourse | any, // 课堂信息
} }
export const useClasscourseStore = defineStore('classcourse', { export const useClasscourseStore = defineStore('classcourse', {

View File

@ -8,6 +8,7 @@ import useUserStore from '@/store/modules/user' // 用户信息
export class ChatWs { export class ChatWs {
instance = null; // 实例 instance = null; // 实例
id = null; // 群聊id || 单聊id-用户id(userId) id = null; // 群聊id || 单聊id-用户id(userId)
url = null; // ws地址
closed = false; // 关闭状态 closed = false; // 关闭状态
onmessage = null; // 自定义处理 onmessage = null; // 自定义处理
errCount = 5; // 重连次数 (ms) 暂时不使用 errCount = 5; // 重连次数 (ms) 暂时不使用
@ -19,12 +20,16 @@ export class ChatWs {
beat: 'heart_beat', // 心跳 beat: 'heart_beat', // 心跳
} }
static base = 'wss://file.ysaix.com:7868' static base = 'wss://file.ysaix.com:7868'
constructor() {
// 构造函数 是否自动连接
constructor(bool = true) {
if (!ChatWs.instance) { if (!ChatWs.instance) {
const userStore = useUserStore() // 用户信息 if (bool) { // 是否自动连接
const wsBase = import.meta.env.VITE_APP_WS_URL; // ws地址 const userStore = useUserStore() // 用户信息
const url = `${wsBase||ChatWs.base}/ws/websocket/${userStore.id}`; const wsBase = import.meta.env.VITE_APP_WS_URL; // ws地址
this.init(url); this.url = `${wsBase||ChatWs.base}/ws/websocket/${userStore.id}`;
// this.init(url);
}
ChatWs.instance = this; ChatWs.instance = this;
} }
return ChatWs.instance; return ChatWs.instance;
@ -32,7 +37,7 @@ export class ChatWs {
// 初始化 // 初始化
init(url) { init(url) {
this.url = url; !!url && (this.url = url);
this.ws = null; this.ws = null;
const _this = this const _this = this
this.heartCheck = { this.heartCheck = {
@ -78,10 +83,9 @@ export class ChatWs {
// 拿到任何消息都说明当前连接是正常的 // 拿到任何消息都说明当前连接是正常的
const isBeat = e.data == 'pong' const isBeat = e.data == 'pong'
isBeat && self.heartCheck.reset().start(); isBeat && self.heartCheck.reset().start();
const exts = ['sessionId', 'pong'] // 不处理的消息头
const isEmpty = !e.data const isEmpty = !e.data
const isExts = exts.some(item => e.data.includes(item)) const isExts = e.data.includes('sessionId') || e.data == ('pong')
if (isEmpty && isExts) return; if (isEmpty || isExts) return;
// 自定义处理 // 自定义处理
self.onmessage && self.onmessage(e.data, e); self.onmessage && self.onmessage(e.data, e);
}; };
@ -137,7 +141,7 @@ export class ChatWs {
* @param {*} id 群聊id || 单聊id-用户id(userId) * @param {*} id 群聊id || 单聊id-用户id(userId)
*/ */
getMsgObj(msg, chatType = 'group', id) { getMsgObj(msg, chatType = 'group', id) {
if (typeof msg === "object") msg = JSON.stringify(msg) // if (typeof msg === "object") msg = JSON.stringify(msg)
const res = {msg, chatType} const res = {msg, chatType}
// if (!id) throw new Error(`${type=='group'?'群ID':'用户ID'} is not null`) // if (!id) throw new Error(`${type=='group'?'群ID':'用户ID'} is not null`)
if (chatType == 'group') res.groupId = id || this.id || '' if (chatType == 'group') res.groupId = id || this.id || ''
@ -160,5 +164,6 @@ export class ChatWs {
} }
// 连接socket // 连接socket
export const connect = () => new ChatWs() export const connect = () => new ChatWs()
export const getInstance = () => new ChatWs(false)
// 默认实例 // 默认实例
export default new ChatWs() export default new ChatWs()

View File

@ -199,8 +199,8 @@ const HTTP_SERVER_API = (type, params = {}) => {
case 'addSmarttalk': { // case 'addSmarttalk': { //
const def = { const def = {
fileId: '', // id - Entpcoursefile id fileId: '', // id - Entpcoursefile id
fileFlag: 'aptist', fileFlag: 'aippt',
fileShowName: courseObj.coursetitle + '.aptist', fileShowName: courseObj.coursetitle + '.aippt',
textbookId: courseObj.textbookId, textbookId: courseObj.textbookId,
levelFirstId: courseObj.levelFirstId, levelFirstId: courseObj.levelFirstId,
levelSecondId: courseObj.levelSecondId, levelSecondId: courseObj.levelSecondId,

View File

@ -267,10 +267,10 @@ const createClasscourse = async () => {
setTimeout(() => { setTimeout(() => {
msgEl.close() msgEl.close()
msgEl = ElMessage.warning({message:'正在打开公屏,请稍后...',duration: 0}) msgEl = ElMessage.warning({message:'正在打开公屏,请稍后...',duration: 0})
setTimeout(() => { setTimeout(async() => {
msgEl.close() msgEl.close()
const classcourse = {...params, id: teacherForm.form.classcourseid} const res = await Http_Classcourse.getClasscourse(teacherForm.form.classcourseid)
openPublicScreen(classcourse) openPublicScreen(res.data)
}, 2000); }, 2000);
}, 1000); }, 1000);
} }
@ -303,9 +303,10 @@ const classTeachingStart = async () => {
// -pptList // -pptList
if (myClassActive.value.filetype == 'aptist') { if (myClassActive.value.filetype == 'aptist') {
const msgEl = ElMessage.warning({message:'正在打开公屏,请稍后...',duration: 0}) const msgEl = ElMessage.warning({message:'正在打开公屏,请稍后...',duration: 0})
setTimeout(() => { setTimeout(async () => {
msgEl.close() msgEl.close()
openPublicScreen({id}) const res = await Http_Classcourse.getClasscourse(teacherForm.form.classcourseid)
openPublicScreen(res.data)
}, 2000); }, 2000);
}else { }else {
const url = `/teaching/classteaching?classcourseid=${id}&actor=classTeachingOnPublicScreen` const url = `/teaching/classteaching?classcourseid=${id}&actor=classTeachingOnPublicScreen`