diff --git a/package-lock.json b/package-lock.json index 5075944..42fb52f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "license": "MIT", "dependencies": { "@element-plus/icons-vue": "^2.0.10", + "@msgpack/msgpack": "^3.1.2", "autoprefixer": "^10.4.21", "axios": "^0.27.2", "code-inspector-plugin": "^0.20.12", @@ -602,6 +603,14 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@msgpack/msgpack": { + "version": "3.1.2", + "resolved": "https://registry.npmmirror.com/@msgpack/msgpack/-/msgpack-3.1.2.tgz", + "integrity": "sha512-JEW4DEtBzfe8HvUYecLU9e6+XJnKDlUAIve8FvPzF3Kzs6Xo/KuZkZJsDH0wJXl/qEZbeeE7edxDNY3kMs39hQ==", + "engines": { + "node": ">= 18" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmmirror.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", diff --git a/package.json b/package.json index 4d3ec57..54fbabe 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ }, "dependencies": { "@element-plus/icons-vue": "^2.0.10", + "@msgpack/msgpack": "^3.1.2", "autoprefixer": "^10.4.21", "axios": "^0.27.2", "code-inspector-plugin": "^0.20.12", diff --git a/src/api/coordinate.js b/src/api/coordinate.js new file mode 100644 index 0000000..d5cb84f --- /dev/null +++ b/src/api/coordinate.js @@ -0,0 +1,19 @@ +import request from '@/utils/request' + +// 获取组织列表 +export function getDirectories(data) { + return request({ + url: `/api/v1/auth/directories`, + method: 'get', + params:data + }) +} + +// 获取指定目录下的用户列表 +export function getDirectoriesUsers(directory_uuid,data) { + return request({ + url: `/api/v1/auth/directories/${directory_uuid}/users`, + method: 'get', + params:data + }) +} \ No newline at end of file diff --git a/src/api/login.js b/src/api/login.js index adc2381..f4ba5c9 100644 --- a/src/api/login.js +++ b/src/api/login.js @@ -22,7 +22,7 @@ export function login(username, password) { // 获取用户详细信息 export function getInfo(userUid) { return request({ - url: `/api/v1/auth/user/${userUid}`, + url: `/api/v1/auth/users/${userUid}`, method: 'get' }) } diff --git a/src/assets/images/cooponents-tab1.png b/src/assets/images/cooponents-tab1.png new file mode 100644 index 0000000..4a07fa4 Binary files /dev/null and b/src/assets/images/cooponents-tab1.png differ diff --git a/src/assets/images/cooponents-tab2.png b/src/assets/images/cooponents-tab2.png new file mode 100644 index 0000000..d577d75 Binary files /dev/null and b/src/assets/images/cooponents-tab2.png differ diff --git a/src/assets/images/cooponents-tab3.png b/src/assets/images/cooponents-tab3.png new file mode 100644 index 0000000..2559afc Binary files /dev/null and b/src/assets/images/cooponents-tab3.png differ diff --git a/src/assets/images/cooponents-tab4.png b/src/assets/images/cooponents-tab4.png new file mode 100644 index 0000000..9244574 Binary files /dev/null and b/src/assets/images/cooponents-tab4.png differ diff --git a/src/assets/images/profile.jpg b/src/assets/images/profile.jpg new file mode 100644 index 0000000..996f640 Binary files /dev/null and b/src/assets/images/profile.jpg differ diff --git a/src/assets/images/user-information1.png b/src/assets/images/user-information1.png new file mode 100644 index 0000000..aa8b146 Binary files /dev/null and b/src/assets/images/user-information1.png differ diff --git a/src/assets/images/user-information2.png b/src/assets/images/user-information2.png new file mode 100644 index 0000000..621fb21 Binary files /dev/null and b/src/assets/images/user-information2.png differ diff --git a/src/assets/images/user-information3.png b/src/assets/images/user-information3.png new file mode 100644 index 0000000..2ac4573 Binary files /dev/null and b/src/assets/images/user-information3.png differ diff --git a/src/assets/images/user-information4.png b/src/assets/images/user-information4.png new file mode 100644 index 0000000..0fe03f0 Binary files /dev/null and b/src/assets/images/user-information4.png differ diff --git a/src/assets/images/userlist-icon1.png b/src/assets/images/userlist-icon1.png new file mode 100644 index 0000000..066497d Binary files /dev/null and b/src/assets/images/userlist-icon1.png differ diff --git a/src/assets/images/userlist-icon2.png b/src/assets/images/userlist-icon2.png new file mode 100644 index 0000000..66b08e0 Binary files /dev/null and b/src/assets/images/userlist-icon2.png differ diff --git a/src/router/index.js b/src/router/index.js index d28b7d2..ae93e0d 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -20,6 +20,16 @@ const router = createRouter({ path: "/login", component: () => import("@/views/login.vue"), }, + { + path: "/coordinate", + children: [ + { + path: '', + name: "Coordinate", + component: () => import("@/views/coordinate/personnelList/index.vue") + } + ] + }, // 错误页面路由 { path: "/:pathMatch(.*)*", diff --git a/src/utils/mqtt.js b/src/utils/mqtt.js index 0bb9795..29d9a48 100644 --- a/src/utils/mqtt.js +++ b/src/utils/mqtt.js @@ -33,13 +33,14 @@ class MQTTClient { this.client.on("error", (error) => reject(error)) // 消息分发 - this.client.on("message", (topic, payload) => { + this.client.on("message", (topic, payload) => { try { - const message = JSON.parse(payload.toString()) + // const message = JSON.parse(payload.toString()) // 遍历所有订阅主题,执行通配符匹配 this.messageHandlers.forEach((handlers, subTopic) => { if (this.topicMatch(subTopic, topic)) { - handlers.forEach((handler) => handler(message, topic)) + // handlers.forEach((handler) => handler(message, topic)) + handlers.forEach((handler) => handler(payload, topic)) } }) } catch (err) { diff --git a/src/utils/request.js b/src/utils/request.js index a71a0be..7eab37d 100644 --- a/src/utils/request.js +++ b/src/utils/request.js @@ -99,11 +99,13 @@ service.interceptors.request.use( service.interceptors.response.use( (response) => { + console.log(response,'response') // 1. 检查响应是否存在 if (!response) { ElMessage.error('无响应数据'); return Promise.reject(new Error('无响应数据')); } + console.log(response.data,'response.data') // 2. 安全获取响应数据和状态码 const responseData = response.data || {}; const statusCode = response.status; @@ -124,6 +126,7 @@ service.interceptors.response.use( return Promise.resolve(responseData); case 401: + console.log('未授权', responseData) return handleUnauthorized().then(() => { return Promise.reject({ code: 401, message: '未授权' }); }); @@ -143,6 +146,13 @@ service.interceptors.response.use( console.error('请求错误:', error); let { message } = error; let code = error?.response?.status || -1; + console.log(code,'code') + + if(code == 401) { + return handleUnauthorized().then(() => { + return Promise.reject({ code: 401, message: '未授权' }); + }); + } if (message == 'Network Error') { message = '后端接口连接异常'; diff --git a/src/utils/whiteboardSync.js b/src/utils/whiteboardSync.js index 590df84..e0fdabc 100644 --- a/src/utils/whiteboardSync.js +++ b/src/utils/whiteboardSync.js @@ -1,6 +1,7 @@ import { mqttClient } from "./mqtt"; import { getWhiteboardShapes, getWhiteboardHistory } from "@/views/custom/api"; import { useMeterStore } from '@/stores/modules/meter'; +import { encode, decode } from '@msgpack/msgpack' const meterStore = useMeterStore(); meterStore.initUdid(); @@ -42,12 +43,15 @@ export const WhiteboardSync = { // 订阅当前房间 const topic = `xSynergy/ROOM/${roomUid}/whiteboard/#`; - mqttClient.subscribe(topic, async (shapeData) => { + mqttClient.subscribe(topic, async (shapeData) => { + // console.log(shapeData, 'shapeData++格式装换') + const shapeDataNew = decode(shapeData); + // console.log(shapeDataNew, '格式解码') try { isRemote = true; // 如果 shape 来自本地用户,则跳过 - if (shapeData.user_uid === localUid) return; - const res = await getWhiteboardHistory({ after_timestamp: shapeData.created_at }, roomUid); + 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 { @@ -62,7 +66,7 @@ export const WhiteboardSync = { console.log("✅ 已订阅:", topic); } catch (err) { - console.log("初始化多人同步失败:",err) + console.log("初始化多人同步失败:", err) // console.error("❌ 连接或订阅失败:", err); } @@ -72,10 +76,9 @@ export const WhiteboardSync = { 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; + if (shape.user_uid && shape.user_uid === localUid) return; + shape.room_uid = roomUid; try { await getWhiteboardShapes(shape, roomUid); } catch (err) { @@ -85,7 +88,7 @@ export const WhiteboardSync = { // 监听画布事件:清空 canvas.on('clear', async () => { - if (!isRemote) { + if (!isRemote) { try { // TODO: 调用接口,后端再发 MQTT // await clearWhiteboard(roomUid); diff --git a/src/views/coordinate/personnelList/components/leftTab/index.vue b/src/views/coordinate/personnelList/components/leftTab/index.vue new file mode 100644 index 0000000..b223d74 --- /dev/null +++ b/src/views/coordinate/personnelList/components/leftTab/index.vue @@ -0,0 +1,596 @@ + + + + + + \ No newline at end of file diff --git a/src/views/coordinate/personnelList/index.vue b/src/views/coordinate/personnelList/index.vue new file mode 100644 index 0000000..bdba8b0 --- /dev/null +++ b/src/views/coordinate/personnelList/index.vue @@ -0,0 +1,755 @@ + + + + + + \ No newline at end of file diff --git a/src/views/login.vue b/src/views/login.vue index 3200bf7..680c391 100644 --- a/src/views/login.vue +++ b/src/views/login.vue @@ -112,7 +112,8 @@ function requestNotificationPermission() { onMounted(async () => { try { loginView.value = true - await getInfo("self"); + const arr = await getInfo("self"); + console.log(arr,'身份信息') showLogin.value = false; router.push({ path: '/whiteboard',