100 lines
3.7 KiB
JavaScript
100 lines
3.7 KiB
JavaScript
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);
|
||
}
|
||
}
|
||
});
|
||
},
|
||
};
|