feat:修改文件上传,白板关闭不影响其他用户等
This commit is contained in:
@@ -121,3 +121,11 @@ export function getConvertStatusApi(taskId,roomId) {
|
||||
})
|
||||
}
|
||||
|
||||
//获取当前会议中所有参与者信息
|
||||
export function getParticipantsApi(roomId) {
|
||||
return request({
|
||||
url: `/api/v1/meeting/${ roomId }/participants`,
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 5.0 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 5.2 KiB |
@@ -135,14 +135,14 @@ service.interceptors.response.use(
|
||||
return Promise.resolve(responseData);
|
||||
case 401:
|
||||
// return Promise.resolve(responseData);
|
||||
const currentPath = router.currentRoute.value.name;
|
||||
if(currentPath == 'ConferencingRoom'){
|
||||
return Promise.resolve(responseData);
|
||||
}else{
|
||||
// const currentPath = router.currentRoute.value.name;
|
||||
// if(currentPath == 'ConferencingRoom'){
|
||||
// return Promise.resolve(responseData);
|
||||
// }else{
|
||||
return handleUnauthorized().then(() => {
|
||||
return Promise.reject({ code: 401, message: '未授权' });
|
||||
});
|
||||
}
|
||||
// }
|
||||
case 500:
|
||||
const serverErrorMsg = responseData.meta?.message || '服务器内部错误';
|
||||
ElMessage({ message: serverErrorMsg, type: 'error' });
|
||||
@@ -211,8 +211,6 @@ function handleUnauthorized() {
|
||||
import('vue').then(({ nextTick }) => {
|
||||
nextTick(() => {
|
||||
const currentPath = router.currentRoute.value.fullPath;
|
||||
console.log('当前路由:', currentPath);
|
||||
|
||||
if (router.currentRoute.value.path !== '/login') {
|
||||
router.push({
|
||||
path: '/login',
|
||||
|
||||
@@ -25,7 +25,6 @@ function getLocalUserData() {
|
||||
export const WhiteboardSync = {
|
||||
async init(canvas, roomUid) {
|
||||
if (!canvas || !roomUid) return;
|
||||
console.log('初始化多人同步:', roomUid);
|
||||
canvasInstance = canvas;
|
||||
|
||||
const localUser = getLocalUserData();
|
||||
@@ -33,8 +32,6 @@ export const WhiteboardSync = {
|
||||
try {
|
||||
// 先连接 MQTT
|
||||
await mqttClient.connect(meterStore.getSudid());
|
||||
console.log("✅ MQTT 已连接");
|
||||
|
||||
// 获取历史数据
|
||||
const res = await getWhiteboardHistory({ after_timestamp: 0 }, roomUid);
|
||||
if (res.meta.code === 200 && res.data.shapes.length > 0) {
|
||||
@@ -48,7 +45,6 @@ export const WhiteboardSync = {
|
||||
mqttClient.subscribe(topic, async (shapeData) => {
|
||||
const shapeDataNew = JSON.parse(shapeData.toString())
|
||||
// const shapeDataNew = decode(message);
|
||||
// console.log(shapeDataNew, '格式解码')
|
||||
try {
|
||||
isRemote = true;
|
||||
// 如果 shape 来自本地用户,则跳过
|
||||
@@ -66,8 +62,6 @@ export const WhiteboardSync = {
|
||||
isRemote = false;
|
||||
}
|
||||
});
|
||||
|
||||
console.log("✅ 已订阅:", topic);
|
||||
} catch (err) {
|
||||
console.log("初始化多人同步失败:", err)
|
||||
// console.error("❌ 连接或订阅失败:", err);
|
||||
|
||||
@@ -43,11 +43,11 @@ export function getDeviceName(devices, deviceId) {
|
||||
}
|
||||
|
||||
export function handleVideoLoaded(identity, type) {
|
||||
console.log(`视频加载完成: ${identity}的${type}视频`);
|
||||
// console.log(`视频加载完成: ${identity}的${type}视频`);
|
||||
}
|
||||
|
||||
export function handleConnectionStateChanged(state) {
|
||||
console.log('连接状态改变:', state);
|
||||
// console.log('连接状态改变:', state);
|
||||
}
|
||||
|
||||
// 平滑曲线绘制函数
|
||||
@@ -100,3 +100,8 @@ export async function calculateFileSHA1(file) {
|
||||
export function simpleDeepEqual(obj1, obj2) {
|
||||
return JSON.stringify(obj1) === JSON.stringify(obj2);
|
||||
}
|
||||
|
||||
// 生成唯一ID
|
||||
export function generateElementId() {
|
||||
return `laser_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
||||
}
|
||||
@@ -3,7 +3,6 @@
|
||||
<template #header>
|
||||
<h4>请选择要加入房间的人员</h4>
|
||||
</template>
|
||||
|
||||
<div class="drawer-content">
|
||||
<!-- 搜索框 -->
|
||||
<div class="search-section">
|
||||
@@ -36,7 +35,7 @@
|
||||
</div>
|
||||
|
||||
<!-- 树形结构 -->
|
||||
<el-scrollbar class="left-list-scrollbar" height="calc(100vh - 240px)">
|
||||
<el-scrollbar v-loading="leftListLoading" class="left-list-scrollbar" height="calc(100vh - 240px)">
|
||||
<el-tree
|
||||
ref="treeRef"
|
||||
lazy
|
||||
@@ -58,6 +57,7 @@
|
||||
<span v-else class="dept-icon">📁</span>
|
||||
<span class="tree-item-text">{{ data.name }}</span>
|
||||
<span v-if="data.users_count" class="user-count">({{ data.users_count }})</span>
|
||||
<!-- <span v-if="isNodeDisabled(data)" class="already-joined-tag">已在房间中</span> -->
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -81,6 +81,7 @@ import {
|
||||
getDirectories,
|
||||
getDirectoriesUsers
|
||||
} from '@/api/coordinate.js'
|
||||
import { getParticipantsApi } from '@/api/conferencingRoom.js'
|
||||
import { nextTick, reactive, toRefs, watch, onMounted, ref } from "vue";
|
||||
|
||||
// 定义 emit
|
||||
@@ -100,27 +101,48 @@ import {
|
||||
const searchKeyword = ref('');
|
||||
const selectedUsers = ref([]);
|
||||
const checkedNodes = ref([]);
|
||||
|
||||
const leftListLoading = ref(false)
|
||||
const joinedUserIds = ref([]); // 存储已在房间中的用户ID
|
||||
// 树形配置
|
||||
const treeProps = reactive({
|
||||
children: 'users',
|
||||
label: 'name',
|
||||
value: 'uid',
|
||||
disabled: (data) => {
|
||||
// 只有人员节点(有uid)且该用户已在房间中时才禁用
|
||||
return data.uid && joinedUserIds.value.includes(data.uid);
|
||||
},
|
||||
isLeaf: (node) => {
|
||||
return !!node.uid; // 有 uid 的为叶子节点(人员)
|
||||
},
|
||||
});
|
||||
|
||||
const isNodeDisabled = (data) => {
|
||||
// 只有人员节点(有uid)且该用户已在房间中时才禁用
|
||||
return data.uid && joinedUserIds.value.includes(data.uid);
|
||||
};
|
||||
|
||||
|
||||
// 显示抽屉
|
||||
function show() {
|
||||
async function show(roomId) {
|
||||
drawerVisible.value = true;
|
||||
// 重置选择状态
|
||||
selectedUsers.value = [];
|
||||
checkedNodes.value = [];
|
||||
searchKeyword.value = '';
|
||||
|
||||
// 获取已在房间中的用户
|
||||
try {
|
||||
const res = await getParticipantsApi(roomId);
|
||||
// 提取状态为1(在房间中)的用户ID
|
||||
joinedUserIds.value = res.data
|
||||
.filter(item => item.status == 1)
|
||||
.map(item => item.user_uid);
|
||||
} catch (error) {
|
||||
console.error('获取房间参与者失败:', error);
|
||||
joinedUserIds.value = [];
|
||||
}
|
||||
|
||||
// 延迟加载树形数据,确保 DOM 已渲染
|
||||
nextTick(() => {
|
||||
if (treeRef.value) {
|
||||
@@ -128,6 +150,11 @@ import {
|
||||
}
|
||||
});
|
||||
}
|
||||
async function getJoinUsers(){
|
||||
const res = await getParticipantsApi(roomId)
|
||||
const joinUsers = res.data.filter(item => item.status == 1).map(item => item.user_uid)
|
||||
return joinUsers;
|
||||
}
|
||||
|
||||
// 确认选择
|
||||
function confirmClick() {
|
||||
@@ -145,26 +172,50 @@ import {
|
||||
// 加载树节点
|
||||
const handleLoadNode = async (node, resolve) => {
|
||||
if(node?.level === 0){
|
||||
loadNode(resolve);
|
||||
} else if (node?.level === 1) {
|
||||
loadNode(resolve, node.data.directory_uid);
|
||||
loadNode(resolve,'',node?.level)
|
||||
}else if(node?.level > 0){
|
||||
if(node.data.directory_uid){
|
||||
loadUserNode(resolve,node.data.directory_uid,node?.level)
|
||||
}else{
|
||||
resolve(resolve)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// 加载节点数据
|
||||
const loadNode = async (resolve, id) => {
|
||||
try {
|
||||
if (!id) {
|
||||
let res = await getDirectories({ level: 1 });
|
||||
leftListLoading.value = true
|
||||
let res = await getDirectories({level:1})
|
||||
if(res.meta.code == 200){
|
||||
resolve(res.data);
|
||||
}
|
||||
} else {
|
||||
let res = await getDirectoriesUsers(id, { directory_uuid: id });
|
||||
resolve(res.data);
|
||||
resolve(res.data)
|
||||
}
|
||||
leftListLoading.value = false
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
console.log(error)
|
||||
leftListLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const loadUserNode = async(resolve,id,level)=>{
|
||||
try {
|
||||
leftListLoading.value = true
|
||||
let userData = []
|
||||
let orgData = []
|
||||
const resOrg = await getDirectories({level: 1,parent_uuid:id})
|
||||
if(resOrg?.data){
|
||||
orgData = resOrg.data
|
||||
}
|
||||
if(id){
|
||||
const res = await getDirectoriesUsers(id,{directory_uuid:id})
|
||||
userData = res.data
|
||||
}
|
||||
resolve([...orgData, ...userData])
|
||||
leftListLoading.value = false
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
leftListLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,8 +228,10 @@ import {
|
||||
// 获取所有选中节点数据
|
||||
const allCheckedNodes = treeRef.value.getCheckedNodes(false, true);
|
||||
|
||||
// 筛选出人员节点(有 uid 的节点)
|
||||
const userNodes = allCheckedNodes.filter(node => node.uid);
|
||||
// 筛选出人员节点(有 uid 的节点)且不在已加入用户列表中的
|
||||
const userNodes = allCheckedNodes.filter(node =>
|
||||
node.uid && !joinedUserIds.value.includes(node.uid)
|
||||
);
|
||||
|
||||
// 更新已选用户列表
|
||||
selectedUsers.value = userNodes;
|
||||
|
||||
@@ -156,6 +156,22 @@
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<el-dialog
|
||||
v-model="dialogFileVisible"
|
||||
title="文件转换"
|
||||
width="50%"
|
||||
class="file-preview-dialog"
|
||||
>
|
||||
<div class="preview-container">
|
||||
<div class="loading-container">
|
||||
<el-icon class="is-loading" size="48">
|
||||
<Loading />
|
||||
</el-icon>
|
||||
<p>正在下载文件,请稍候...</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -208,6 +224,8 @@ const fileName = ref('')
|
||||
const textContent = ref('')
|
||||
const currentFileData = ref(null)
|
||||
const convertTaskId = ref('')
|
||||
const dialogFileVisible = ref(false)
|
||||
|
||||
|
||||
// PDF相关状态
|
||||
const pdfSource = ref('')
|
||||
@@ -261,7 +279,12 @@ onMounted(async () => {
|
||||
emitter.on('subscribeToFileConversionStatusTopic',subscribeToFileConversionStatusTopic)
|
||||
emitter.on('fileUploadStatus',fileUploadStatus)
|
||||
emitter.on('subscribeToFilePreviewTopic',subscribeToFilePreviewTopic)
|
||||
emitter.on('fileSuccess',fileSuccess)
|
||||
|
||||
function fileSuccess(){
|
||||
dialogFileVisible.value = true
|
||||
}
|
||||
//
|
||||
function subscribeToFileConversionStatusTopic(data){
|
||||
try {
|
||||
const userId = JSON.parse(sessionStorage.getItem('userData'))?.uid
|
||||
@@ -286,12 +309,9 @@ function subscribeToFilePreviewTopic(data){
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//提交转换任务,但文件暂未转换完成
|
||||
function fileUploadStatus(data){
|
||||
if(!dialogFormVisible.value){
|
||||
|
||||
}
|
||||
// console.log('文件上传成功mqtt消息')
|
||||
}
|
||||
|
||||
// 初始化MQTT连接 pdf转换成功
|
||||
@@ -328,8 +348,13 @@ function handleFileUploadMessage(payload, topic){
|
||||
try {
|
||||
const messageStr = payload.toString()
|
||||
const data = JSON.parse(messageStr)
|
||||
emitter.emit('fileUploadStatus')
|
||||
if(dialogFormVisible.value){
|
||||
// emitter.emit('fileUploadStatus')
|
||||
console.log(data,'data文件转换完成,预览通知')
|
||||
const userId = JSON.parse(sessionStorage.getItem('userData'))?.uid
|
||||
if(dialogFileVisible.value){
|
||||
dialogFileVisible.value = false
|
||||
}
|
||||
if(dialogFormVisible.value && userId != data.user_uid){
|
||||
// 显示确认对话框
|
||||
ElMessageBox.confirm(
|
||||
`用户${data.user_uid}上传了${data.file_name}文件,是否立即预览?`,
|
||||
|
||||
@@ -78,7 +78,6 @@ const props = defineProps({
|
||||
|
||||
emitter.on('fileUploadStatus',async ()=>{
|
||||
if(drawerVisible.value){
|
||||
console.log('更新啦')
|
||||
await getFileList()
|
||||
}
|
||||
})
|
||||
@@ -161,7 +160,7 @@ async function getFileList(){
|
||||
}
|
||||
fileList.value = res.data.files || [];
|
||||
} catch (error) {
|
||||
console.error('获取文件列表失败:', error);
|
||||
// console.error('获取文件列表失败:', error);
|
||||
ElMessage.error('获取文件列表失败');
|
||||
} finally {
|
||||
loading.value = false;
|
||||
|
||||
@@ -419,7 +419,7 @@
|
||||
}
|
||||
|
||||
const handlePdfRendered = () => {
|
||||
console.log('PDF页面渲染完成')
|
||||
// console.log('PDF页面渲染完成')
|
||||
}
|
||||
|
||||
const handlePdfError = (error) => {
|
||||
|
||||
@@ -203,6 +203,8 @@ const handleHttpRequest = async (file) => {
|
||||
// 上传成功,取消loading
|
||||
uploadLoading.value = false
|
||||
dialogFormVisible.value = false
|
||||
|
||||
emitter.emit('fileSuccess')
|
||||
return true
|
||||
} catch (error) {
|
||||
console.error('上传文件失败:', error)
|
||||
@@ -234,7 +236,7 @@ function publishFileUploadData(fileData) {
|
||||
};
|
||||
mqttClient.publish(`xSynergy/File/Upload/${roomId.value}`, message);
|
||||
} catch (error) {
|
||||
console.error('发布激光笔数据失败:', error);
|
||||
console.error('发布文件数据失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1085
-339
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+1231
-363
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -235,7 +235,7 @@ const searchList = () => {
|
||||
state.dataList = []
|
||||
getList()
|
||||
} else {
|
||||
console.log('treeRef.filter',state.treeRef)
|
||||
// console.log('treeRef.filter',state.treeRef)
|
||||
state.treeRef.filter(state.queryFrom.nickName)
|
||||
}
|
||||
}
|
||||
@@ -306,24 +306,45 @@ const getList = async () => {
|
||||
*/
|
||||
const HandleLoadNode = async (node, resolve) => {
|
||||
if(node?.level === 0){
|
||||
loadNode(resolve)
|
||||
}else if(node?.level === 1){
|
||||
loadNode(resolve,node.data.directory_uid)
|
||||
loadNode(resolve,'',node?.level)
|
||||
}else if(node?.level > 0){
|
||||
if(node.data.directory_uid){
|
||||
loadUserNode(resolve,node.data.directory_uid,node?.level)
|
||||
}else{
|
||||
resolve(resolve)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
const loadNode = async(resolve,id)=>{
|
||||
const loadNode = async(resolve,id,level)=>{
|
||||
try {
|
||||
state.leftListLoading = true
|
||||
if(!id){
|
||||
let res = await getDirectories({level:1})
|
||||
if(res.meta.code == 200){
|
||||
resolve(res.data)
|
||||
}
|
||||
}else{
|
||||
let res = await getDirectoriesUsers(id,{directory_uuid:id})
|
||||
resolve(res.data)
|
||||
state.leftListLoading = false
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
state.leftListLoading = false
|
||||
}
|
||||
}
|
||||
|
||||
const loadUserNode = async(resolve,id,level)=>{
|
||||
try {
|
||||
state.leftListLoading = true
|
||||
let userData = []
|
||||
let orgData = []
|
||||
const resOrg = await getDirectories({level: 1,parent_uuid:id})
|
||||
if(resOrg?.data){
|
||||
orgData = resOrg.data
|
||||
}
|
||||
if(id){
|
||||
const res = await getDirectoriesUsers(id,{directory_uuid:id})
|
||||
userData = res.data
|
||||
}
|
||||
resolve([...orgData, ...userData])
|
||||
state.leftListLoading = false
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
|
||||
@@ -447,7 +447,7 @@ onMounted(async () => {
|
||||
const res = await userStore.getInfo()
|
||||
const topic = `xSynergy/ROOM/+/rooms/${res.uid}`;
|
||||
mqttClient.subscribe(topic, async (shapeData) => {
|
||||
console.log(shapeData.toString(),'shapeData发送邀请')
|
||||
// console.log(shapeData.toString(),'shapeData发送邀请')
|
||||
processingSocket(shapeData.toString())
|
||||
});
|
||||
})
|
||||
|
||||
@@ -54,7 +54,7 @@ async function joinWhiteboard() {
|
||||
try {
|
||||
const clientId = `whiteboard-${uuidv4()}`;
|
||||
await mqttClient.connect(clientId);
|
||||
console.log("✅ 已连接 MQTT:", clientId);
|
||||
// console.log("✅ 已连接 MQTT:", clientId);
|
||||
|
||||
hasJoined.value = true;
|
||||
|
||||
|
||||
+3
-5
@@ -50,10 +50,9 @@ const redirect = ref(undefined);
|
||||
const loginView = ref(true)
|
||||
|
||||
// 监听路由变化,获取重定向参数
|
||||
// watch(() => route, (newRoute) => {
|
||||
// redirect.value = newRoute.query && newRoute.query.redirect;
|
||||
// console.log('重定向路径:', redirect.value);
|
||||
// }, { immediate: true });
|
||||
watch(() => route, (newRoute) => {
|
||||
redirect.value = newRoute.query && newRoute.query.redirect;
|
||||
}, { immediate: true });
|
||||
|
||||
const loginForm = ref({
|
||||
username: '',
|
||||
@@ -110,7 +109,6 @@ const loading = ref(false)
|
||||
try {
|
||||
// 如果有重定向路径且不是登录页,则跳转到重定向页面
|
||||
if (redirect.value && redirect.value !== '/login') {
|
||||
console.log('跳转到重定向页面:', redirect.value);
|
||||
|
||||
// 确保路由存在,如果不存在则跳转到默认页面
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user