diff --git a/.env.development b/.env.development index b3a7114..422cd04 100644 --- a/.env.development +++ b/.env.development @@ -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/' # websocket 地址 -# VITE_APP_WS_URL = 'wss://file.ysaix.com:7868' -VITE_APP_WS_URL = 'ws://192.168.2.16:7865' +VITE_APP_WS_URL = 'wss://file.ysaix.com:7868' +# VITE_APP_WS_URL = 'ws://192.168.2.16:7865' # 是否显示开发工具 VITE_SHOW_DEV_TOOLS = 'true' diff --git a/src/renderer/src/AixPPTist/src/App.vue b/src/renderer/src/AixPPTist/src/App.vue index 77b800d..f90545d 100644 --- a/src/renderer/src/AixPPTist/src/App.vue +++ b/src/renderer/src/AixPPTist/src/App.vue @@ -27,8 +27,8 @@ import msgUtils from '@/plugins/modal' // 消息工具 import * as API_entpcoursefile from '@/api/education/entpcoursefile' // 相关api import { PPTApi } from './api' import { sessionStore } from '@/utils/store' // electron-store 状态管理 -import './api/watcher' // 监听 import './api/classcourse' // 课程相关 +import './api/watcher' // 监听 const loading = ref(true) const _isPC = isPC() diff --git a/src/renderer/src/AixPPTist/src/api/classcourse.ts b/src/renderer/src/AixPPTist/src/api/classcourse.ts index ca162e1..efa8df9 100644 --- a/src/renderer/src/AixPPTist/src/api/classcourse.ts +++ b/src/renderer/src/AixPPTist/src/api/classcourse.ts @@ -2,20 +2,20 @@ * @author zdg * @description 上课相关内容 */ -import type { Classcourse } from './types' +// import type { Classcourse } from './types' import { sessionStore } from '@/utils/store' // electron-store 状态管理 import * as useStore from '../store' // pptist-状态管理 -import { ChatWs } from '@/plugins/socket' // 聊天socket +import ChatWs from '@/plugins/socket' // 聊天socket const screenStore = useStore.useScreenStore() // 全屏-状态管理 const classcourseStore = useStore.useClasscourseStore() // 课堂信息-状态管理 -const classcourse: Classcourse = sessionStore.get('curr.classcourse') // 课堂信息 +const classcourse = sessionStore.get('curr.classcourse') // 课堂信息 // 如果课堂信息有值,则连接socket if (!!classcourse) { // 连接socket - const ws = new ChatWs() - console.log('ws- ',ws) - // ChatWs.connect(classcourse.id) + if (!ChatWs.ws) ChatWs.init() + ChatWs.id = classcourse.timgroupid // 群组id + console.log('ws- ',ws, classcourse) classcourseStore.setClasscourse(classcourse) } // 打开全屏 diff --git a/src/renderer/src/AixPPTist/src/api/index.ts b/src/renderer/src/AixPPTist/src/api/index.ts index b0c8239..57bc29e 100644 --- a/src/renderer/src/AixPPTist/src/api/index.ts +++ b/src/renderer/src/AixPPTist/src/api/index.ts @@ -3,7 +3,7 @@ * @author zdg * @date 2024-11-26 */ -import { toRaw } from 'vue' +import { toRaw, nextTick } from 'vue' import type { Result } from './types' // 接口类型 import msgUtils from '@/plugins/modal' // 消息工具 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 useUserStore from '@/store/modules/user' // 外部-用户信息 +import { toPng, toJpeg } from 'html-to-image' // 引入html-to-image库 + const slidesStore = useStore.useSlidesStore() const userStore = useUserStore() @@ -142,6 +144,8 @@ export class PPTApi { // 更新幻灯片 static updateSlide(data: object): Promise { return new Promise(async (resolve, reject) => { + const thumUrl = await this.getSlideThumUrl() + data.base64Code = thumUrl // 更新缩略图 const res: Result = await API_entpcoursefile.updateEntpcoursefileNew(data) if (res.code === 200) { resolve(true) @@ -184,6 +188,21 @@ export class PPTApi { else msgUtils.msgError(res.msg || '更新失败');return false }) } + // thumbnail-slide thumbnail + static getSlideThumUrl(): Promise { + 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 \ No newline at end of file diff --git a/src/renderer/src/AixPPTist/src/api/types.ts b/src/renderer/src/AixPPTist/src/api/types.ts index 8d4f81c..1f2de61 100644 --- a/src/renderer/src/AixPPTist/src/api/types.ts +++ b/src/renderer/src/AixPPTist/src/api/types.ts @@ -19,6 +19,7 @@ export interface Classcourse { entpcoursefileid?: number|string, // 课程文件id classid?: number|string, // 班级id entpcourseid?: number|string, // 章节中间表id + timgroupid?: number|string, // ws 群组id plandate?: string, // 计划时间 opendate?: string, // 开课时间 } \ No newline at end of file diff --git a/src/renderer/src/AixPPTist/src/api/watcher.ts b/src/renderer/src/AixPPTist/src/api/watcher.ts index f1f21ba..f515b8e 100644 --- a/src/renderer/src/AixPPTist/src/api/watcher.ts +++ b/src/renderer/src/AixPPTist/src/api/watcher.ts @@ -6,6 +6,7 @@ import { watch } from 'vue' import { PPTApi } from './index' import * as store from '../store' import { sessionStore } from '@/utils/store' // electron-store 状态管理 +import ChatWs from '@/plugins/socket' // 聊天socket const slidesStore = store.useSlidesStore() const resource = sessionStore.get('curr.resource') // apt 资源 const smarttalk = sessionStore.get('curr.smarttalk') // 备课资源 @@ -24,6 +25,19 @@ watch(() => slidesStore.title, (newVal, oldVal) => { 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) => { if (!resource) return data.id = resource.id @@ -36,4 +50,20 @@ const updatePPT = async (data) => { await PPTApi.updateSmarttalk(params) // 更新ppt内容 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 + } + } } \ No newline at end of file diff --git a/src/renderer/src/AixPPTist/src/store/classcourse.ts b/src/renderer/src/AixPPTist/src/store/classcourse.ts index 7abd3fe..bd77fbd 100644 --- a/src/renderer/src/AixPPTist/src/store/classcourse.ts +++ b/src/renderer/src/AixPPTist/src/store/classcourse.ts @@ -2,7 +2,7 @@ import { defineStore } from 'pinia' import type { Classcourse } from '../api/types' export interface ClasscourseState { - classcourse: Classcourse + classcourse: Classcourse | any, // 课堂信息 } export const useClasscourseStore = defineStore('classcourse', { diff --git a/src/renderer/src/plugins/socket/index.js b/src/renderer/src/plugins/socket/index.js index 968ac53..3edd643 100644 --- a/src/renderer/src/plugins/socket/index.js +++ b/src/renderer/src/plugins/socket/index.js @@ -8,6 +8,7 @@ import useUserStore from '@/store/modules/user' // 用户信息 export class ChatWs { instance = null; // 实例 id = null; // 群聊id || 单聊id-用户id(userId) + url = null; // ws地址 closed = false; // 关闭状态 onmessage = null; // 自定义处理 errCount = 5; // 重连次数 (ms) 暂时不使用 @@ -19,12 +20,16 @@ export class ChatWs { beat: 'heart_beat', // 心跳 } static base = 'wss://file.ysaix.com:7868' - constructor() { + + // 构造函数 是否自动连接 + constructor(bool = true) { if (!ChatWs.instance) { - const userStore = useUserStore() // 用户信息 - const wsBase = import.meta.env.VITE_APP_WS_URL; // ws地址 - const url = `${wsBase||ChatWs.base}/ws/websocket/${userStore.id}`; - this.init(url); + if (bool) { // 是否自动连接 + const userStore = useUserStore() // 用户信息 + const wsBase = import.meta.env.VITE_APP_WS_URL; // ws地址 + this.url = `${wsBase||ChatWs.base}/ws/websocket/${userStore.id}`; + // this.init(url); + } ChatWs.instance = this; } return ChatWs.instance; @@ -32,7 +37,7 @@ export class ChatWs { // 初始化 init(url) { - this.url = url; + !!url && (this.url = url); this.ws = null; const _this = this this.heartCheck = { @@ -78,10 +83,9 @@ export class ChatWs { // 拿到任何消息都说明当前连接是正常的 const isBeat = e.data == 'pong' isBeat && self.heartCheck.reset().start(); - const exts = ['sessionId', 'pong'] // 不处理的消息头 const isEmpty = !e.data - const isExts = exts.some(item => e.data.includes(item)) - if (isEmpty && isExts) return; + const isExts = e.data.includes('sessionId') || e.data == ('pong') + if (isEmpty || isExts) return; // 自定义处理 self.onmessage && self.onmessage(e.data, e); }; @@ -137,7 +141,7 @@ export class ChatWs { * @param {*} id 群聊id || 单聊id-用户id(userId) */ 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} // if (!id) throw new Error(`${type=='group'?'群ID':'用户ID'} is not null`) if (chatType == 'group') res.groupId = id || this.id || '' @@ -160,5 +164,6 @@ export class ChatWs { } // 连接socket export const connect = () => new ChatWs() +export const getInstance = () => new ChatWs(false) // 默认实例 export default new ChatWs() \ No newline at end of file diff --git a/src/renderer/src/views/model/index.vue b/src/renderer/src/views/model/index.vue index 3fe9bbc..b290275 100644 --- a/src/renderer/src/views/model/index.vue +++ b/src/renderer/src/views/model/index.vue @@ -199,8 +199,8 @@ const HTTP_SERVER_API = (type, params = {}) => { case 'addSmarttalk': { // 获取课程 const def = { fileId: '', // 文件id - Entpcoursefile 对应id - fileFlag: 'aptist', - fileShowName: courseObj.coursetitle + '.aptist', + fileFlag: 'aippt', + fileShowName: courseObj.coursetitle + '.aippt', textbookId: courseObj.textbookId, levelFirstId: courseObj.levelFirstId, levelSecondId: courseObj.levelSecondId, diff --git a/src/renderer/src/views/prepare/container/class-start.vue b/src/renderer/src/views/prepare/container/class-start.vue index 77eb615..08b3b7f 100644 --- a/src/renderer/src/views/prepare/container/class-start.vue +++ b/src/renderer/src/views/prepare/container/class-start.vue @@ -267,10 +267,10 @@ const createClasscourse = async () => { setTimeout(() => { msgEl.close() msgEl = ElMessage.warning({message:'正在打开公屏,请稍后...',duration: 0}) - setTimeout(() => { + setTimeout(async() => { msgEl.close() - const classcourse = {...params, id: teacherForm.form.classcourseid} - openPublicScreen(classcourse) + const res = await Http_Classcourse.getClasscourse(teacherForm.form.classcourseid) + openPublicScreen(res.data) }, 2000); }, 1000); } @@ -303,9 +303,10 @@ const classTeachingStart = async () => { // 新版-pptList 打开公屏 if (myClassActive.value.filetype == 'aptist') { const msgEl = ElMessage.warning({message:'正在打开公屏,请稍后...',duration: 0}) - setTimeout(() => { + setTimeout(async () => { msgEl.close() - openPublicScreen({id}) + const res = await Http_Classcourse.getClasscourse(teacherForm.form.classcourseid) + openPublicScreen(res.data) }, 2000); }else { const url = `/teaching/classteaching?classcourseid=${id}&actor=classTeachingOnPublicScreen`