|
|
@@ -570,6 +570,10 @@ const yMessage = ref<any | null>(null)
|
|
|
const yTimerState = ref<any | null>(null)
|
|
|
const yLaserState = ref<any | null>(null)
|
|
|
const yWritingBoardState = ref<any | null>(null)
|
|
|
+// 独立的数组存储特殊类型的消息
|
|
|
+const yTimerMessages = ref<any | null>(null)
|
|
|
+const yLaserMessages = ref<any | null>(null)
|
|
|
+const yWritingBoardMessages = ref<any | null>(null)
|
|
|
const providerSocket = ref<WebsocketProvider | null>(null)
|
|
|
// 学生端画图同步数据
|
|
|
const writingBoardSyncDataURL = ref<string | null>(null)
|
|
|
@@ -1206,11 +1210,26 @@ const clearAllSyncStates = () => {
|
|
|
if (props.type == '1' && isCreator.value && docSocket.value) {
|
|
|
console.log('🧹 创建老师退出,清空所有同步状态')
|
|
|
docSocket.value.transact(() => {
|
|
|
- // 清空消息
|
|
|
+ // 清空普通消息
|
|
|
const messageArray = docSocket.value?.getArray?.('message')
|
|
|
if (messageArray) {
|
|
|
messageArray.delete(0, messageArray.length)
|
|
|
}
|
|
|
+ // 清空计时器消息数组
|
|
|
+ const timerMessagesArray = docSocket.value?.getArray?.('timerMessages')
|
|
|
+ if (timerMessagesArray) {
|
|
|
+ timerMessagesArray.delete(0, timerMessagesArray.length)
|
|
|
+ }
|
|
|
+ // 清空激光笔消息数组
|
|
|
+ const laserMessagesArray = docSocket.value?.getArray?.('laserMessages')
|
|
|
+ if (laserMessagesArray) {
|
|
|
+ laserMessagesArray.delete(0, laserMessagesArray.length)
|
|
|
+ }
|
|
|
+ // 清空画图消息数组
|
|
|
+ const writingBoardMessagesArray = docSocket.value?.getArray?.('writingBoardMessages')
|
|
|
+ if (writingBoardMessagesArray) {
|
|
|
+ writingBoardMessagesArray.delete(0, writingBoardMessagesArray.length)
|
|
|
+ }
|
|
|
// 清空计时器状态
|
|
|
const timerStateMap = docSocket.value?.getMap?.('timerState')
|
|
|
if (timerStateMap) {
|
|
|
@@ -2515,87 +2534,135 @@ const checkIsCreator = () => {
|
|
|
* 初始化消息监听
|
|
|
*/
|
|
|
const messageInit = () => {
|
|
|
+ if (!docSocket.value) return
|
|
|
|
|
|
-
|
|
|
- if (docSocket.value && !yMessage.value) {
|
|
|
- console.log('获取message', docSocket.value, yMessage.value)
|
|
|
+ // 初始化普通消息数组(只保留最后一条)
|
|
|
+ if (!yMessage.value) {
|
|
|
+ console.log('初始化普通消息数组')
|
|
|
yMessage.value = docSocket.value.getArray('message')
|
|
|
yMessage.value.observe((e: any) => {
|
|
|
- // 执行清空数据
|
|
|
- // 数据同步完成后,清理超过40分钟的消息数据
|
|
|
- const messages = yMessage.value.toArray()
|
|
|
- console.log('messages', messages)
|
|
|
- console.log('messagesLength', messages.length)
|
|
|
- // 如果是首次进入且是创建者,清空所有同步状态
|
|
|
- if ((isFirstEnter.value || messages.length > 2000) && isCreator.value && docSocket.value) {
|
|
|
- console.log('🧹 首次进入且为创建者或消息条数超2000,保留最新2000条消息,其他同步状态全部清空')
|
|
|
+ e.changes.added.forEach((i: any) => {
|
|
|
+ const message = i.content.getContent()[0]
|
|
|
+ console.log('yMessage', message)
|
|
|
+ if (message.mId !== mId.value) {
|
|
|
+ getMessages(message)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ // 初始化计时器消息数组
|
|
|
+ if (!yTimerMessages.value) {
|
|
|
+ console.log('初始化计时器消息数组')
|
|
|
+ yTimerMessages.value = docSocket.value.getArray('timerMessages')
|
|
|
+ yTimerMessages.value.observe((e: any) => {
|
|
|
+ // 检查数组长度,如果超过2000条,清理旧数据
|
|
|
+ if (yTimerMessages.value && yTimerMessages.value.length > 2000 && isCreator.value && docSocket.value) {
|
|
|
+ const excessCount = yTimerMessages.value.length - 2000
|
|
|
docSocket.value.transact(() => {
|
|
|
- // 只保留最新2000条消息
|
|
|
- const messageArray = docSocket.value?.getArray?.('message')
|
|
|
- if (messageArray && messageArray.length > 2000) {
|
|
|
- messageArray.delete(0, messageArray.length - 2000)
|
|
|
- }
|
|
|
- // 清空计时器状态
|
|
|
- const timerStateMap = docSocket.value?.getMap?.('timerState')
|
|
|
- if (timerStateMap) {
|
|
|
- timerStateMap.clear()
|
|
|
- }
|
|
|
- // 清空激光笔状态
|
|
|
- const laserStateMap = docSocket.value?.getMap?.('laserState')
|
|
|
- if (laserStateMap) {
|
|
|
- laserStateMap.clear()
|
|
|
- }
|
|
|
- // 清空画图状态
|
|
|
- const writingBoardStateMap = docSocket.value?.getMap?.('writingBoardState')
|
|
|
- if (writingBoardStateMap) {
|
|
|
- writingBoardStateMap.clear()
|
|
|
- }
|
|
|
+ yTimerMessages.value.delete(0, excessCount)
|
|
|
})
|
|
|
- // 标记已不再是首次进入
|
|
|
- isFirstEnter.value = false
|
|
|
+ console.log(`🧹 清理了 ${excessCount} 条计时器消息,保留最新2000条`)
|
|
|
}
|
|
|
- if (messages.length > 0) {
|
|
|
- const now = Date.now()
|
|
|
- const messagesToKeep: any[] = []
|
|
|
-
|
|
|
- for (let i = messages.length - 1; i >= 0; i--) {
|
|
|
- const message = messages[i]
|
|
|
- if (message && typeof message === 'object' && message.timestamp) {
|
|
|
- const messageTime = new Date(message.timestamp).getTime()
|
|
|
- if (now - messageTime <= SYNC_DATA_MAX_AGE) {
|
|
|
- messagesToKeep.unshift(message)
|
|
|
- }
|
|
|
- }
|
|
|
+
|
|
|
+ e.changes.added.forEach((i: any) => {
|
|
|
+ const message = i.content.getContent()[0]
|
|
|
+ if (message.mId !== mId.value) {
|
|
|
+ getMessages(message)
|
|
|
}
|
|
|
+ })
|
|
|
+ })
|
|
|
+ }
|
|
|
|
|
|
- // 如果有需要清理的消息
|
|
|
- if (messagesToKeep.length < messages.length) {
|
|
|
- // 修复报错:docSocket.value 可能为 null
|
|
|
- if (docSocket.value) {
|
|
|
- docSocket.value.transact(() => {
|
|
|
- yMessage.value.delete(0, messages.length)
|
|
|
- messagesToKeep.forEach((msg: any) => yMessage.value.push([msg]))
|
|
|
- })
|
|
|
- console.log(`🧹 清理了 ${messages.length - messagesToKeep.length} 条超过40分钟的消息`)
|
|
|
- }
|
|
|
- }
|
|
|
+ // 初始化激光笔消息数组
|
|
|
+ if (!yLaserMessages.value) {
|
|
|
+ console.log('初始化激光笔消息数组')
|
|
|
+ yLaserMessages.value = docSocket.value.getArray('laserMessages')
|
|
|
+ yLaserMessages.value.observe((e: any) => {
|
|
|
+ // 检查数组长度,如果超过2000条,清理旧数据
|
|
|
+ if (yLaserMessages.value && yLaserMessages.value.length > 2000 && isCreator.value && docSocket.value) {
|
|
|
+ const excessCount = yLaserMessages.value.length - 2000
|
|
|
+ docSocket.value.transact(() => {
|
|
|
+ yLaserMessages.value.delete(0, excessCount)
|
|
|
+ })
|
|
|
+ console.log(`🧹 清理了 ${excessCount} 条激光笔消息,保留最新2000条`)
|
|
|
}
|
|
|
+
|
|
|
+ e.changes.added.forEach((i: any) => {
|
|
|
+ const message = i.content.getContent()[0]
|
|
|
+ if (message.mId !== mId.value) {
|
|
|
+ getMessages(message)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ })
|
|
|
+ }
|
|
|
|
|
|
+ // 初始化画图消息数组
|
|
|
+ if (!yWritingBoardMessages.value) {
|
|
|
+ console.log('初始化画图消息数组')
|
|
|
+ yWritingBoardMessages.value = docSocket.value.getArray('writingBoardMessages')
|
|
|
+ yWritingBoardMessages.value.observe((e: any) => {
|
|
|
+ // 检查数组长度,如果超过2000条,清理旧数据
|
|
|
+ if (yWritingBoardMessages.value && yWritingBoardMessages.value.length > 2000 && isCreator.value && docSocket.value) {
|
|
|
+ const excessCount = yWritingBoardMessages.value.length - 2000
|
|
|
+ docSocket.value.transact(() => {
|
|
|
+ yWritingBoardMessages.value.delete(0, excessCount)
|
|
|
+ })
|
|
|
+ console.log(`🧹 清理了 ${excessCount} 条画图消息,保留最新2000条`)
|
|
|
+ }
|
|
|
+
|
|
|
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秒内且不是自己发的消息
|
|
|
+ if (message.mId !== mId.value) {
|
|
|
getMessages(message)
|
|
|
}
|
|
|
})
|
|
|
})
|
|
|
}
|
|
|
+
|
|
|
+ // 如果是首次进入且是创建者,清空所有同步状态
|
|
|
+ if (isFirstEnter.value && isCreator.value && docSocket.value) {
|
|
|
+ console.log('🧹 首次进入且为创建者,清空所有同步状态')
|
|
|
+ docSocket.value.transact(() => {
|
|
|
+ // 清空普通消息(只保留最后一条的逻辑在 sendMessage 中处理)
|
|
|
+ const messageArray = docSocket.value?.getArray?.('message')
|
|
|
+ if (messageArray) {
|
|
|
+ messageArray.delete(0, messageArray.length)
|
|
|
+ }
|
|
|
+ // 清空计时器消息数组
|
|
|
+ const timerMessagesArray = docSocket.value?.getArray?.('timerMessages')
|
|
|
+ if (timerMessagesArray) {
|
|
|
+ timerMessagesArray.delete(0, timerMessagesArray.length)
|
|
|
+ }
|
|
|
+ // 清空激光笔消息数组
|
|
|
+ const laserMessagesArray = docSocket.value?.getArray?.('laserMessages')
|
|
|
+ if (laserMessagesArray) {
|
|
|
+ laserMessagesArray.delete(0, laserMessagesArray.length)
|
|
|
+ }
|
|
|
+ // 清空画图消息数组
|
|
|
+ const writingBoardMessagesArray = docSocket.value?.getArray?.('writingBoardMessages')
|
|
|
+ if (writingBoardMessagesArray) {
|
|
|
+ writingBoardMessagesArray.delete(0, writingBoardMessagesArray.length)
|
|
|
+ }
|
|
|
+ // 清空计时器状态
|
|
|
+ const timerStateMap = docSocket.value?.getMap?.('timerState')
|
|
|
+ if (timerStateMap) {
|
|
|
+ timerStateMap.clear()
|
|
|
+ }
|
|
|
+ // 清空激光笔状态
|
|
|
+ const laserStateMap = docSocket.value?.getMap?.('laserState')
|
|
|
+ if (laserStateMap) {
|
|
|
+ laserStateMap.clear()
|
|
|
+ }
|
|
|
+ // 清空画图状态
|
|
|
+ const writingBoardStateMap = docSocket.value?.getMap?.('writingBoardState')
|
|
|
+ if (writingBoardStateMap) {
|
|
|
+ writingBoardStateMap.clear()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ // 标记已不再是首次进入
|
|
|
+ isFirstEnter.value = false
|
|
|
+ }
|
|
|
// 初始化计时器状态 Map 并监听
|
|
|
if (docSocket.value && !yTimerState.value) {
|
|
|
yTimerState.value = docSocket.value.getMap('timerState')
|
|
|
@@ -2657,18 +2724,66 @@ const messageInit = () => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * 判断是否为特殊类型的消息(计时器、激光笔、画图)
|
|
|
+ */
|
|
|
+const isSpecialMessageType = (type: string): boolean => {
|
|
|
+ const timerTypes = ['timer_start', 'timer_pause', 'timer_reset', 'timer_stop', 'timer_finish', 'timer_update']
|
|
|
+ const laserTypes = ['laser_toggle', 'laser_move']
|
|
|
+ const writingBoardTypes = ['writing_board_update', 'writing_board_close', 'writing_board_blackboard']
|
|
|
+ return timerTypes.includes(type) || laserTypes.includes(type) || writingBoardTypes.includes(type)
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 获取消息类型对应的数组
|
|
|
+ */
|
|
|
+const getMessageArrayByType = (type: string): any | null => {
|
|
|
+ const timerTypes = ['timer_start', 'timer_pause', 'timer_reset', 'timer_stop', 'timer_finish', 'timer_update']
|
|
|
+ const laserTypes = ['laser_toggle', 'laser_move']
|
|
|
+ const writingBoardTypes = ['writing_board_update', 'writing_board_close', 'writing_board_blackboard']
|
|
|
+
|
|
|
+ if (timerTypes.includes(type)) {
|
|
|
+ return yTimerMessages.value
|
|
|
+ }
|
|
|
+ if (laserTypes.includes(type)) {
|
|
|
+ return yLaserMessages.value
|
|
|
+ }
|
|
|
+ if (writingBoardTypes.includes(type)) {
|
|
|
+ return yWritingBoardMessages.value
|
|
|
+ }
|
|
|
+ return null
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* 发送消息
|
|
|
*/
|
|
|
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])
|
|
|
- })
|
|
|
- }
|
|
|
+ if (!docSocket.value) return
|
|
|
+
|
|
|
+ const message = obj
|
|
|
+ message.timestamp = new Date().toISOString()
|
|
|
+ message.mId = mId.value
|
|
|
+
|
|
|
+ const messageType = message.type
|
|
|
+ const isSpecial = isSpecialMessageType(messageType)
|
|
|
+
|
|
|
+ docSocket.value.transact(() => {
|
|
|
+ if (isSpecial) {
|
|
|
+ // 特殊类型消息:存储到对应的独立数组
|
|
|
+ const targetArray = getMessageArrayByType(messageType)
|
|
|
+ if (targetArray) {
|
|
|
+ targetArray.push([message])
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ // 普通消息:只保留最后一条
|
|
|
+ if (yMessage.value) {
|
|
|
+ // 清空数组,只保留新消息
|
|
|
+ yMessage.value.delete(0, yMessage.value.length)
|
|
|
+ yMessage.value.push([message])
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
}
|
|
|
|
|
|
/**
|