Files
xSynergy-manage/src/utils/whiteboardSync.js
2025-11-24 10:10:26 +08:00

100 lines
3.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { mqttClient } from "./mqtt";
import { getWhiteboardShapes, getWhiteboardHistory } from "@/views/custom/api";
import { useMeterStore } from '@/stores/modules/meter';
import { encode, decode } from '@msgpack/msgpack'
import { ElMessage } from 'element-plus';
import { emitter } from "@/utils/bus.js";
const meterStore = useMeterStore();
meterStore.initUdid();
let isRemote = false;
let canvasInstance = null;
// 获取本地缓存 userData
function getLocalUserData() {
const dataStr = sessionStorage.getItem('userData');
if (!dataStr) return null;
try {
return JSON.parse(dataStr);
} catch (e) {
console.error("解析 userData 失败:", e);
return null;
}
}
export const WhiteboardSync = {
async init(canvas, roomUid) {
if (!canvas || !roomUid) return;
canvasInstance = canvas;
const localUser = getLocalUserData();
const localUid = localUser?.uid;
try {
// 先连接 MQTT
await mqttClient.connect(meterStore.getSudid());
// 获取历史数据
const res = await getWhiteboardHistory({ after_timestamp: 0 }, roomUid);
if (res.meta.code === 200 && res.data.shapes.length > 0) {
canvasInstance.addShape(res.data.shapes);
}else if(res.meta.code === 401){
emitter.emit('whiteboardFailed',true);
}
// 订阅当前房间
const topic = `xsynergy/room/${roomUid}/whiteboard/#`;
mqttClient.subscribe(topic, async (shapeData) => {
const shapeDataNew = JSON.parse(shapeData.toString())
// const shapeDataNew = decode(message);
try {
isRemote = true;
// 如果 shape 来自本地用户,则跳过
if (shapeDataNew.user_uid === localUid) return;
const res = await getWhiteboardHistory({ after_timestamp: shapeDataNew.created_at }, roomUid);
if (res.meta.code === 200) {
canvasInstance.addShape(res.data.shapes);
} else {
ElMessage.error("获取历史数据失败");
console.error("获取历史数据失败");
}
} catch (e) {
console.error("处理MQTT数据失败:", e);
} finally {
isRemote = false;
}
});
} catch (err) {
console.log("初始化多人同步失败:", err)
// console.error("❌ 连接或订阅失败:", err);
}
// 监听画布事件:新增图形
canvas.on('drawingEnd', async (shape) => {
// 如果来自远程,或不是需要同步的类型,跳过
if (isRemote || !['pencil', 'line', 'rectangle', 'circle', 'eraser'].includes(shape.type)) return;
// 如果是本地用户自己的 shape则不调用接口
if (shape.user_uid && shape.user_uid === localUid) return;
shape.room_uid = roomUid;
try {
await getWhiteboardShapes(shape, roomUid);
} catch (err) {
ElMessage.error("提交形状失败");
console.error("提交形状失败:", err);
}
});
// 监听画布事件:清空
canvas.on('clear', async () => {
if (!isRemote) {
try {
// TODO: 调用接口,后端再发 MQTT
// await clearWhiteboard(roomUid);
} catch (err) {
console.error("提交清空失败:", err);
}
}
});
},
};