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',
|
||||
})
|
||||
}
|
||||
|
||||
BIN
src/assets/images/amplify.png
Normal file
BIN
src/assets/images/amplify.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.0 KiB |
BIN
src/assets/images/shrink.png
Normal file
BIN
src/assets/images/shrink.png
Normal file
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)}`;
|
||||
}
|
||||
@@ -1,11 +1,10 @@
|
||||
<template>
|
||||
<el-drawer v-model="drawerVisible" direction="rtl" title="请选择要加入房间的人员" size="40%">
|
||||
<template #header>
|
||||
<h4>请选择要加入房间的人员</h4>
|
||||
<h4>请选择要加入房间的人员</h4>
|
||||
</template>
|
||||
|
||||
<div class="drawer-content">
|
||||
<!-- 搜索框 -->
|
||||
<!-- 搜索框 -->
|
||||
<div class="search-section">
|
||||
<el-input
|
||||
v-model="searchKeyword"
|
||||
@@ -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,12 +57,13 @@
|
||||
<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>
|
||||
</el-tree>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<div class="footer-actions">
|
||||
@@ -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() {
|
||||
@@ -144,30 +171,54 @@ import {
|
||||
|
||||
// 加载树节点
|
||||
const handleLoadNode = async (node, resolve) => {
|
||||
if (node?.level === 0) {
|
||||
loadNode(resolve);
|
||||
} else if (node?.level === 1) {
|
||||
loadNode(resolve, node.data.directory_uid);
|
||||
if(node?.level === 0){
|
||||
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 });
|
||||
if (res.meta.code == 200) {
|
||||
resolve(res.data);
|
||||
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);
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
// 处理复选框选择变化
|
||||
const handleCheckChange = (checkedNode, checkedNodesInfo) => {
|
||||
// 获取所有选中的节点
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
3547
src/views/conferencingRoom/latest.vue
Normal file
3547
src/views/conferencingRoom/latest.vue
Normal file
File diff suppressed because it is too large
Load Diff
3175
src/views/conferencingRoom/pathTransit.vue
Normal file
3175
src/views/conferencingRoom/pathTransit.vue
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
3325
src/views/conferencingRoom/transit.vue
Normal file
3325
src/views/conferencingRoom/transit.vue
Normal file
File diff suppressed because it is too large
Load Diff
3326
src/views/conferencingRoom/transits.vue
Normal file
3326
src/views/conferencingRoom/transits.vue
Normal file
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,22 +306,22 @@ 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})
|
||||
let res = await getDirectories({level:1})
|
||||
if(res.meta.code == 200){
|
||||
resolve(res.data)
|
||||
}
|
||||
state.leftListLoading = false
|
||||
@@ -331,6 +331,27 @@ const loadNode = async(resolve,id)=>{
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
state.leftListLoading = false
|
||||
}
|
||||
}
|
||||
|
||||
// try {
|
||||
// if (userList.data.sub_units?.length) {
|
||||
// state.dataList = userList.data.sub_units
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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