|
@@ -237,6 +237,9 @@ import ChoiceWorkModal from './components/ChoiceWorkModal.vue'
|
|
|
import AIWorkModal from './components/AIWorkModal.vue'
|
|
|
import DialoguePanel from './components/DialoguePanel.vue'
|
|
|
import ChoiceStatistics from './components/ChoiceStatistics.vue'
|
|
|
+import * as Y from 'yjs'
|
|
|
+import { WebsocketProvider } from 'y-websocket'
|
|
|
+
|
|
|
|
|
|
// 导入图片资源
|
|
|
import homeworkIcon from '@/assets/img/homework.png'
|
|
@@ -344,6 +347,10 @@ const unsubmittedStudents = computed(() => {
|
|
|
return studentArray.value.filter((student: any) => !submittedNames.includes(student.name))
|
|
|
})
|
|
|
|
|
|
+const docSocket = ref<Y.Doc | null>(null)
|
|
|
+const yMessage = ref<any | null>(null)
|
|
|
+const providerSocket = ref<WebsocketProvider | null>(null)
|
|
|
+const mId = ref<string | null>(null)
|
|
|
|
|
|
|
|
|
// 切换到作业区
|
|
@@ -596,11 +603,13 @@ watch(() => slideIndex.value, (newIndex, oldIndex) => {
|
|
|
console.log('当前页面无iframe,停止作业更新定时器')
|
|
|
stopWorkTimer()
|
|
|
}
|
|
|
- if (isFollowModeActive.value && isCreator.value) {
|
|
|
+ if (props.type == '1' && isFollowModeActive.value && isCreator.value) {
|
|
|
api.updateCourseFollowC(newIndex, props.courseid as string)
|
|
|
+ sendMessage({slideIndex: newIndex, courseid: props.courseid, type: 'slideIndex'})
|
|
|
}
|
|
|
// 自动切换到可用的面板
|
|
|
autoSwitchToAvailablePanel()
|
|
|
+
|
|
|
}
|
|
|
}, { immediate: false, deep: false })
|
|
|
|
|
@@ -711,6 +720,7 @@ const processIframeLinks = async () => {
|
|
|
// 检查是否是iframe元素
|
|
|
if (element.type === ElementTypes.FRAME && element.url) {
|
|
|
const iframeSrc = element.url
|
|
|
+ const toolType = element.toolType
|
|
|
|
|
|
if (iframeSrc.includes('workPage')) {
|
|
|
hasIframe = true
|
|
@@ -756,7 +766,7 @@ const processIframeLinks = async () => {
|
|
|
return element
|
|
|
}
|
|
|
}
|
|
|
- else if (iframeSrc.includes('.html') || iframeSrc.includes('.htm')) {
|
|
|
+ else if (toolType == 45) {
|
|
|
hasIframe = true
|
|
|
|
|
|
// 先尝试获取iframe的contentWindow,如果获取不到再使用HTML方式
|
|
@@ -1403,6 +1413,7 @@ const toggleFollowMode = async () => {
|
|
|
// 调用API更新跟随状态
|
|
|
const res = await api.updateCourseFollow(sopen, props.courseid as string)
|
|
|
console.log('更新跟随模式状态:', res)
|
|
|
+ sendMessage({sopen: newFollowState, courseid: props.courseid, type: 'sopen'})
|
|
|
|
|
|
if (res) {
|
|
|
isFollowModeActive.value = newFollowState
|
|
@@ -1433,6 +1444,60 @@ const checkIsCreator = () => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+/**
|
|
|
+ * 初始化消息监听
|
|
|
+ */
|
|
|
+const messageInit = () => {
|
|
|
+ if (docSocket.value && !yMessage.value) {
|
|
|
+ console.log('获取message', docSocket.value, yMessage.value)
|
|
|
+ yMessage.value = docSocket.value.getArray('message')
|
|
|
+ yMessage.value.observe((e: any) => {
|
|
|
+ e.changes.added.forEach((i: any) => {
|
|
|
+ const message = i.content.getContent()[0]
|
|
|
+ console.log('yMessage', message)
|
|
|
+ const _nowTime = new Date()
|
|
|
+ const _msgTime = new Date(message.timestamp)
|
|
|
+ if (
|
|
|
+ (_nowTime as any) - (_msgTime as any) <= 1000 * 10 &&
|
|
|
+ message.mId !== mId.value
|
|
|
+ ) {
|
|
|
+ // 10秒内且不是自己发的消息
|
|
|
+ getMessages(message)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ })
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 发送消息
|
|
|
+ */
|
|
|
+const sendMessage = (obj: any) => {
|
|
|
+ if (docSocket.value && yMessage.value) {
|
|
|
+ const message = obj
|
|
|
+ obj.timestamp = new Date().toISOString()
|
|
|
+ obj.mId = mId.value
|
|
|
+ docSocket.value.transact(() => {
|
|
|
+ yMessage.value.push([message])
|
|
|
+ })
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 处理收到的消息
|
|
|
+ */
|
|
|
+const getMessages = (msgObj: any) => {
|
|
|
+ console.log('message', msgObj)
|
|
|
+ if (props.type == '2' && msgObj.slideIndex && msgObj.type === 'slideIndex') {
|
|
|
+ goToSlide(msgObj.slideIndex)
|
|
|
+ }
|
|
|
+ if (props.type == '2' && msgObj.type === 'sopen') {
|
|
|
+ selectCourseSLook()
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
onMounted(() => {
|
|
|
document.addEventListener('keydown', handleKeydown)
|
|
|
|
|
@@ -1497,6 +1562,24 @@ onMounted(() => {
|
|
|
|
|
|
console.log('PPTist Student View 已加载,可通过 window.PPTistStudent 访问功能')
|
|
|
console.log('URL参数:', { courseid: props.courseid, type: props.type })
|
|
|
+
|
|
|
+ if (api.yweb_socket && !docSocket.value) {
|
|
|
+
|
|
|
+ docSocket.value = new Y.Doc()
|
|
|
+ providerSocket.value = new WebsocketProvider(api.yweb_socket,
|
|
|
+ 'PPT' + props.courseid,
|
|
|
+ docSocket.value
|
|
|
+ )
|
|
|
+
|
|
|
+ providerSocket.value.on('status', (event: any) => {
|
|
|
+ console.log('👉', event.status)
|
|
|
+ if (event.status === 'connected') {
|
|
|
+ console.log('👉连接成功websocket(teachingMode)')
|
|
|
+ mId.value = Math.random().toString(36).substr(2, 9)
|
|
|
+ messageInit()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
})
|
|
|
|
|
|
|