<template>
    <div v-if="showLogin">
     <!-- 登录界面 -->
     <Login @loginSuccess="handleLoginSuccess" />
    </div>
    <div v-else>
        <!-- 音频元素 -->
        <audio ref="localAudio" autoplay muted class="audio-element"></audio>
        <div id="audio"></div>
        <div class="livekit-container">
            <div v-if="!status" class="meeting-container"> 
                <!-- 视频容器 -->
                <div class="video-layout" :class="{ 
                    'screen-sharing-active': hasActiveScreenShare || isWhiteboardActive || enlargedParticipant,
                    'enlarged-mode': enlargedParticipant
                }">
                    <!-- 左侧共享屏幕/白板/放大视频区域 -->
                    <div class="screen-share-area" v-if="hasActiveScreenShare || isWhiteboardActive || enlargedParticipant">
                        <div class="screen-share-header">
                            <h3 v-if="enlargedParticipant">
                                <span v-if="enlargedParticipant.identity === hostUid">我的放大视频</span>
                                <span v-else>放大视图 - {{ enlargedParticipant.identity }}</span>
                            </h3>
                            <h3 v-else-if="isWhiteboardActive">共享白板</h3>
                            <h3 v-else>共享屏幕</h3>
                            <div class="sharing-user" v-if="!enlargedParticipant">
                                <span v-if="isWhiteboardActive || hasActiveScreenShare">
                                    由 {{ screenSharingUser }} 共享
                                </span>
                            </div>
                            <!-- v-if="enlargedParticipant && enlargedParticipant.identity === hostUid" -->
                            <el-button 
                                v-if="enlargedParticipant"
                                @click="closeEnlargedView"
                                type="info"
                                size="small"
                                class="close-enlarge-btn"
                            >
                                关闭放大
                            </el-button>
                        </div>
                        <div class="screen-share-video">
                            <!-- 放大视频模式 -->
                            <div v-if="enlargedParticipant" class="enlarged-video-container">
                                <div class="video-wrapper enlarged-video-wrapper">
                                           <!-- 激光笔 Canvas -->
                                    <canvas 
                                        v-if="isLaserPointerActive && enlargedParticipant"
                                        ref="enlargedLaserPointerCanvas"
                                        class="laser-pointer-canvas enlarged-laser-canvas"
                                        @dblclick="handleEnlargedCanvasDoubleClick"
                                        @mousedown="handleEnlargedCanvasMouseDown"
                                        @mousemove="handleEnlargedCanvasMouseMove"
                                        @mouseup="handleEnlargedCanvasMouseUp"
                                        @mouseleave="handleEnlargedCanvasMouseLeave"  
                                    ></canvas>
                                    <video 
                                        v-if="enlargedParticipant.hasCameraTrack"
                                        :ref="el => setEnlargedVideoRef(el)"
                                        autoplay 
                                        playsinline 
                                        class="enlarged-video-element"
                                        @loadedmetadata="handleEnlargedVideoLoaded">
                                    </video>
                                    <!-- 如果没有视频轨道，显示提示 -->
                                    <div v-if="!enlargedParticipant.hasCameraTrack" class="video-placeholder">
                                        <i class="el-icon-user"></i>
                                        <span>暂无视频流</span>
                                    </div>
                                    <div class="video-overlay">
                                        <span class="participant-name">
                                            {{ enlargedParticipant.identity === hostUid ? '我' : enlargedParticipant.identity }}
                                        </span>
                                        <span class="audio-indicator" :class="{ 'muted': !enlargedParticipant.audioEnabled }">
                                            <i :class="enlargedParticipant.audioEnabled ? 'el-icon-microphone' : 'el-icon-turn-off-microphone'"></i>
                                        </span>
                                    </div>
                                </div>
                            </div>
                            
                            <!-- 白板模式 -->
                            <div v-else-if="isWhiteboardActive" class="whiteboard-container">
                                <tabulaRase 
                                    ref="whiteboardRef"
                                    :roomId="roomId"
                                    :userId="hostUid"
                                    class="whiteboard-component"
                                />
                            </div>
                            
                            <!-- 屏幕共享模式 --> 
                            <div v-else class="video-wrapper screen-share-wrapper">
                                <!-- 激光笔 Canvas -->
                                <canvas 
                                    ref="laserPointerCanvas"
                                    class="laser-pointer-canvas"
                                    @dblclick="handleCanvasDoubleClick"
                                    @mousedown="handleCanvasMouseDown"
                                    @mousemove="handleCanvasMouseMove"
                                    @mouseup="handleCanvasMouseUp"
                                    @mouseleave="handleCanvasMouseLeave"  
                                ></canvas>
                                <div class="video-tracks">
                                    <!-- 屏幕共享视频 -->
                                    <video 
                                        v-if="activeScreenShareTrack"
                                        :ref="el => setScreenShareVideoRef(el)"
                                        autoplay 
                                        playsinline 
                                        class="screen-share-element" 
                                        @loadedmetadata="handleScreenShareLoaded">
                                    </video>
                                    <!-- 如果没有屏幕共享，显示提示 -->
                                    <div v-if="!activeScreenShareTrack" class="video-placeholder">
                                        <i class="el-icon-monitor"></i>
                                        <span>暂无屏幕共享</span>
                                    </div>
                                </div>
                                <div class="video-overlay">
                                    <span class="participant-name">{{ screenSharingUser }}</span>
                                    <!-- 激光笔状态指示 -->
                                    <span v-if="isLaserPointerActive" class="laser-pointer-indicator">
                                        <i class="el-icon-aim"></i> 激光笔模式中
                                    </span>
                                </div> 
                            </div>
                        </div>
                    </div>

                    <!-- 右侧视频区域 -->
                    <div class="participants-area" :class="{ 
                        'with-screen-share': hasActiveScreenShare || isWhiteboardActive || enlargedParticipant 
                    }">
                        <div class="participants-header">
                            <h3>会议名称：{{ roomName }}</h3>
                            <h3>参会者 ({{ participantCount }})</h3>
                        </div>
                        <div class="video-grid" :class="{ 
                            'grid-layout': !hasActiveScreenShare && !enlargedParticipant && participantCount > 1 
                        }">
                            <!-- 本地视频 -->
                            <div class="participant-card local-participant" :class="{ 'enlarged': enlargedParticipant && enlargedParticipant.identity === hostUid }"> 
                                <div class="participant-header">
                                    <h3>我的视频 ({{ hostUid }})</h3>
                                    <div class="status-indicator"> 
                                        <el-icon :class="{ 'audio-on': microphoneEnabled, 'audio-off': !microphoneEnabled }">
                                            <Microphone v-if="microphoneEnabled" />
                                            <Mute v-else />
                                        </el-icon> 
                                    </div>
                                    <div class="participant-actions" v-if="participantCount > 1 && shouldShowEnlargeButtons && !enlargedParticipant">
                                    <el-button 
                                        @click="enlargeParticipant({ identity: hostUid, hasCameraTrack: cameraEnabled, audioEnabled: microphoneEnabled })"
                                        type="link"
                                        size="small"
                                        class="enlarge-btn"
                                        title="放大视图"
                                    >
                                        <i class="el-icon-zoom-in"></i>
                                        放大
                                    </el-button>
                                </div>
                                </div>
                                <div class="video-wrapper">
                                    <video ref="localVideo" autoplay muted playsinline class="video-element"></video>
                                    <div class="video-overlay">
                                        <span class="participant-name">{{ hostUid }}</span>
                                        <span class="audio-indicator" :class="{ 'muted': !microphoneEnabled }">
                                            <i :class="microphoneEnabled ? 'el-icon-microphone' : 'el-icon-turn-off-microphone'"></i>
                                        </span>
                                    </div>
                                    <!-- 视频占位符 -->
                                    <div v-if="!cameraEnabled" class="video-placeholder">
                                        <i class="el-icon-user"></i>
                                        <span>摄像头已关闭</span>
                                    </div>
                                </div> 
                            </div>

                            <!-- 远程视频-->
                            <div class="participant-card" 
                                v-for="participant in remoteParticipantsArray" 
                                :key="participant.identity"
                                :class="{ 'enlarged': enlargedParticipant && enlargedParticipant.identity === participant.identity }"
                            >
                                <div class="participant-header">
                                    <h3>{{ participant.identity }}</h3> 
                                    <div class="status-indicator"> 
                                        <el-icon :class="{ 'audio-on': participant.audioEnabled, 'audio-off': !participant.audioEnabled }">
                                            <Microphone v-if="participant.audioEnabled" />
                                            <Mute v-else />
                                        </el-icon> 
                                    </div>
                                </div>
                                <div class="video-wrapper">
                                    <div class="video-tracks"> 
                                        <!-- 摄像头视频 - 使用 ref 绑定 -->
                                        <video 
                                            v-if="participant.hasCameraTrack"
                                            :ref="el => setParticipantVideoRef(el, participant.identity, 'camera')"
                                            autoplay 
                                            playsinline 
                                            class="video-element"
                                            @loadedmetadata="() => handleVideoLoaded(participant.identity, 'camera')">
                                        </video>
                                        <!-- 如果没有视频轨道，显示提示 -->
                                        <div v-if="!participant.hasCameraTrack" class="video-placeholder">
                                            <i class="el-icon-user"></i>
                                            <span>摄像头已关闭</span>
                                        </div>
                                    </div>
                                    <div class="video-overlay">
                                        <span class="participant-name">{{ participant.identity }}</span>
                                        <span class="audio-indicator" :class="{ 'muted': !participant.audioEnabled }">
                                            <i :class="participant.audioEnabled ? 'el-icon-microphone' : 'el-icon-turn-off-microphone'"></i>
                                        </span>
                                    </div>
                                </div>
                                <!-- 远程参与者音频元素 -->
                                <audio 
                                    :ref="el => setParticipantAudioRef(el, participant.identity)"
                                    autoplay 
                                    class="participant-audio"
                                /> 
                            </div>
                        </div>  
                    </div>
                </div>
                
                <!-- 固定在底部的控制按钮 -->
                <div class="fixed-controls">
                    <div class="controls-container"> 
                        <div class="microphone-control-group">
                            <el-button @click="toggleCamera" :type="cameraEnabled ? 'danger' : 'info'" class="control-btn microphone-btn" size="large">
                                {{ cameraEnabled ? '关闭摄像头' : '开启摄像头' }}
                            </el-button>
                            <!-- 摄像头选择下拉菜单 -->
                            <el-dropdown trigger="click" @command="handleCameraCommand" @visible-change="handleCameraVisibleChange" class="control-dropdown microphone-dropdown">
                                <el-button :type="cameraEnabled ? 'danger' : 'info'" class="control-btn dropdown-btn" size="large">
                                    <el-icon class="el-icon--right"><arrow-down /></el-icon>
                                </el-button>
                                <template #dropdown>
                                    <el-dropdown-menu>
                                        <el-dropdown-item 
                                            v-for="device in cameraDevices" 
                                            :key="device.deviceId" 
                                            :command="device.deviceId"
                                            :class="{ 'selected-device': selectedCameraId === device.deviceId }"
                                        >
                                            <i class="el-icon-video-camera"></i>
                                            {{ device.label || `摄像头 ${cameraDevices.indexOf(device) + 1}` }}
                                            <el-icon v-if="selectedCameraId === device.deviceId" class="check-icon"><check /></el-icon>
                                        </el-dropdown-item>
                                        <el-dropdown-item divided command="refresh">
                                            <el-icon><refresh /></el-icon>
                                            刷新设备列表
                                        </el-dropdown-item>
                                    </el-dropdown-menu>
                                </template>
                            </el-dropdown>
                        </div>
                        <div class="microphone-control-group">
                            <el-button @click="toggleMicrophone" :type="microphoneEnabled ? 'danger' : 'info'" class="control-btn microphone-btn" size="large">
                                {{ microphoneEnabled ? '关闭麦克风' : '开启麦克风' }}
                            </el-button> 
                            <!-- 麦克风选择下拉菜单 -->
                            <el-dropdown trigger="click" @command="handleMicrophoneCommand" @visible-change="handleMicrophoneVisibleChange" class="control-dropdown microphone-dropdown">
                                <el-button :type="microphoneEnabled ? 'danger' : 'info'" class="control-btn dropdown-btn" size="large">
                                    <el-icon class="el-icon--right"><arrow-down /></el-icon>
                                </el-button>
                                <template #dropdown>
                                    <el-dropdown-menu>
                                        <el-dropdown-item 
                                            v-for="device in microphoneDevices" 
                                            :key="device.deviceId" 
                                            :command="device.deviceId"
                                            :class="{ 'selected-device': selectedMicrophoneId === device.deviceId }"
                                        >
                                            <i class="el-icon-microphone"></i>
                                            {{ device.label || `麦克风 ${microphoneDevices.indexOf(device) + 1}` }}
                                            <el-icon v-if="selectedMicrophoneId === device.deviceId" class="check-icon"><check /></el-icon>
                                        </el-dropdown-item>
                                        <el-dropdown-item divided command="refresh">
                                            <el-icon><refresh /></el-icon>
                                            刷新设备列表
                                        </el-dropdown-item>
                                    </el-dropdown-menu>
                                </template>
                            </el-dropdown>
                        </div> 
                        <el-button 
                            @click="toggleScreenShare" 
                            :type="isScreenSharing ? 'danger' : (isGlobalScreenSharing ? 'primary' : 'info')" 
                            :disabled="(isGlobalScreenSharing && !isScreenSharing) || !canScreenShare"
                            class="control-btn" 
                            size="large"
                        > 
                            <span v-if="isScreenSharing">停止共享</span>
                            <span v-else-if="isGlobalScreenSharing">他人共享中</span>
                            <span v-else>共享屏幕</span>
                        </el-button>
                        <el-button 
                            @click="toggleWhiteboard"  
                            :type="isWhiteboardActive ? 'danger' : 'info'"  
                            :disabled="cameraEnabled || !canWhiteboardShare"
                            class="control-btn" 
                            size="large"
                        >
                            {{ isWhiteboardActive ? '退出白板' : '共享白板' }}
                        </el-button>
                        <el-button  
                            @click="toggleLaserPointer" 
                            :type="isLaserPointerActive ? 'danger' : 'info'" 
                            :disabled="!canUseLaserPointer"
                            class="control-btn" 
                            size="large"
                        >
                            {{ isLaserPointerActive ? '关闭激光笔' : '激光笔' }}
                        </el-button>
                        <el-button @click="fileUploadHandle" type="info" class="control-btn" size="large">
                            文件
                        </el-button>
                        <el-button @click="inviterJoinRoom" type="info" class="control-btn" size="large">
                            邀请人员
                        </el-button>
                        <el-button @click="leaveRoomHandle" type="info" class="control-btn" size="large">
                            离开会议
                        </el-button>
                    </div>
                </div>
            </div> 
            <!-- 邀请人员组件 -->
            <InviterJoinRoom ref="inviterJoinRoomRef" @confirmSelection="handleConfirmSelection" />
            <!-- 上传文件 -->
            <FileList ref="fileListRef" :roomId="roomId"/>
        </div>
    </div>
</template>

<script setup>
import { reactive, ref, onMounted, onUnmounted, nextTick, computed, watch } from "vue";  
import { ElMessage ,ElMessageBox} from 'element-plus';
import { ArrowDown, Refresh, Check } from '@element-plus/icons-vue';
import { getRoomToken, getRoomList ,getInvite,getTokenApi,exitRoomApi,getRoomInfoApi} from "@/api/conferencingRoom.js"
import { Room, RoomEvent, ParticipantEvent, Track } from "livekit-client";
import { errorHandling ,handleDataReceived ,handleReconnected,getDeviceName,handleVideoLoaded,handleConnectionStateChanged,drawSmoothCurve,simpleDeepEqual,generateElementId} from './business/index.js'
import { useRoute, useRouter } from 'vue-router'
import { useRoomStore } from '@/stores/modules/room.js'
import { useUserStore } from '@/stores/modules/user.js'
import tabulaRase from '@/views/custom/tabulaRase/index.vue'
import { mqttClient } from "@/utils/mqtt.js"; 
import { emitter } from "@/utils/bus.js";
import Login from "@/components/Login/index.vue";

import InviterJoinRoom from "@/views/conferencingRoom/components/InviterJoinRoom/index.vue"
import FileList from "@/views/conferencingRoom/components/fileUpload/fileList.vue"

const userStore = useUserStore()
const roomStore = useRoomStore() 
const route = useRoute();
const router = useRouter()
// LiveKit 服务器配置
const wsURL = "wss://meeting.cnsdt.com:443";
const hostUid = ref('')
const status = ref(true); 
const roomName = ref('')
const roomId = ref('')
// 音视频相关引用和数据
const localVideo = ref(null);
const localAudio = ref(null);
const cameraEnabled = ref(false);
const microphoneEnabled = ref(false);
const isScreenSharing = ref(false);
const isLocalSpeaking = ref(false);
// 设备列表
const cameraDevices = ref([]);
const microphoneDevices = ref([]);
const selectedCameraId = ref('');
const selectedMicrophoneId = ref('');
// 远程参与者管理
const remoteParticipants = ref(new Map());
const videoElementsMap = ref(new Map());
const audioElementsMap = ref(new Map());
// 屏幕共享相关
const screenSharingUser = ref('');
const activeScreenShareTrack = ref(null);
const screenShareVideo = ref(null);//屏幕共享视频元素
const globalScreenSharingUser = ref(''); // 当前正在共享屏幕的用户
const isGlobalScreenSharing = ref(false); // 是否有用户正在共享屏幕
//共享白板
const isWhiteboardActive = ref(false);
const whiteboardRef = ref(null);
const isGlobalWhiteboardSharing = ref(false); // 是否有用户正在共享白板
//当前房间信息
const roomInfo = ref('') 
//邀请参会人员
const inviterJoinRoomRef = ref()
// 共享屏幕激光笔相关状态
const isLaserPointerActive = ref(false);
const laserPointerCanvas = ref(null);
const laserPointerContext = ref(null);
const laserPointerElements = ref(new Map()); // 改为 Map 结构，key 为时间戳
const laserPointerTimeouts = ref(new Map()); // 管理每个元素的定时器
const canvasSizeObserver = ref(null);
const screenShareVideoElement = ref(null);
// 激光笔相关状态放大视屏
const enlargedLaserPointerCanvas = ref(null);
const enlargedLaserPointerContext = ref(null);
const enlargedLaserPointerElements = ref(new Map());
const enlargedLaserPointerTimeouts = ref(new Map());
const enlargedCanvasSizeObserver = ref(null);
//文件上传
const fileListRef = ref()
//mqtt相关
const isMqttFileuploadSucc = ref(false)
const isMqttFilePreview = ref(false)
const isMqttFileConversionStatus = ref(false)
const isMqttEnlargeVideo = ref(false)
const showLogin = ref(false); // 是否显示登录页面
// 放大视图相关
const enlargedParticipant = ref(null); // 当前放大的参与者
const enlargedVideo = ref(null); // 放大视频元素引用

// 路径更新节流处理
let lastPublishTime = 0;
const publishThrottleTime = 100; // 100ms 节流

// 鼠标状态跟踪
const mouseState = reactive({
    isDrawing: false,
    startX: 0,
    startY: 0
});
// 放大视频鼠标状态跟踪
const enlargedMouseState = reactive({
    isDrawing: false,
    startX: 0,
    startY: 0
});
// 激光笔样式配置
const laserPointerConfig = reactive({
    color: '#ff0000', // 红色激光
    thickness: 3,
    duration: 2000, // 2秒后消失
    fadeDuration: 300 // 淡出动画时间
});
 
// 白板消息类型
const WHITEBOARD_MESSAGE_TYPES = {
    OPEN: 'open_whiteboard',
    CLOSE: 'close_whiteboard',
    SYNC: 'sync_whiteboard'
}; 
// 在 script 中添加激光笔消息类型和同步功能
const LASER_POINTER_MESSAGE_TYPES = {
    DRAW: 'laser_draw',
    CLEAR: 'laser_clear'
};
//视屏缩放类型
const VIDEO_ENLARGE_MESSAGE_TYPES = {
    ENLARGE: 'enlarge_video',
    SHRINK: 'shrink_video'
};

const participantCount = computed(() => {
    return remoteParticipants.value.size + 1; // 包括自己
});
// 计算远程参与者数组
const remoteParticipantsArray = computed(() => {
    return Array.from(remoteParticipants.value.values());
});
// 计算是否有活跃的屏幕共享 
const hasActiveScreenShare = computed(() => {
    return screenSharingUser.value !== '' || isScreenSharing.value;
});

// 添加激光笔可用性计算属性
const canUseLaserPointer = computed(() => {
    return cameraEnabled.value || hasActiveScreenShare.value || enlargedParticipant.value;
});
// 是否显示放大按钮（当有屏幕共享时隐藏）
const shouldShowEnlargeButtons = computed(() => {
  return !hasActiveScreenShare.value;
});

// 是否允许屏幕共享（当有放大视频时禁用）
const canScreenShare = computed(() => {
  return !enlargedParticipant.value;
});
// 是否允许白板共享（当有放大视频时禁用）
const canWhiteboardShare = computed(() => {
  return !enlargedParticipant.value;
}); 
// 添加一个计算属性来显示屏幕共享状态提示
const screenShareStatusText = computed(() => {
    if (isGlobalScreenSharing.value) {
        if (globalScreenSharingUser.value === hostUid.value) {
            return '您正在共享屏幕';
        } else {
            return `${globalScreenSharingUser.value} 正在共享屏幕`;
        }
    }
    return '暂无屏幕共享';
}); 

// 创建 Room 实例
const room = new Room({
    adaptiveStream: true,
    dynacast: true,
    // 音频捕获配置
    audioCaptureDefaults: {
        echoCancellation: true,
        noiseSuppression: true,
        autoGainControl: true,
    },
    videoCaptureDefaults: {
        resolution: { width: 1280, height: 720 },
    },
    publishDefaults: {
        screenShareEncoding: {
            maxBitrate: 3_000_000,
            maxFramerate: 30,
        },
        videoEncoding: {
            maxBitrate: 2_500_000,
            maxFramerate: 30,
        },
        // 音频发布配置
        audioEncoding: {
            maxBitrate: 64000,
        },
        // dtx: true, // 不连续传输，节省带宽
        red: true, // 冗余编码，提高抗丢包能力
    }
});

emitter.on('whiteboardFailed',whiteboardFailedHandle);

/** 登录成功回调 */
function handleLoginSuccess() {
    showLogin.value = false;
}

function whiteboardFailedHandle(e){
    showLogin.value = e;
}

// 放大参与者视频
function enlargeParticipant(participant) { 
    // 只允许放大自己的视频
    if (participant.identity !== hostUid.value) {
        ElMessage.warning('只能放大自己的视频');
        return;
    }
    
    if (participantCount.value <= 1) {
        ElMessage.warning('需要至少2名参与者才能使用放大功能');
        return;
    } 
    
    if (!cameraEnabled.value) {
        ElMessage.warning('请先打开摄像头');
        return;
    }
        // 如果正在屏幕共享，自动停止
    if (isScreenSharing.value) {
        room.localParticipant.setScreenShareEnabled(false);
        isScreenSharing.value = false;
        ElMessage.info('已自动停止屏幕共享，开启视频放大模式');
    }
        // 如果正在使用白板，自动退出
    if (isWhiteboardActive.value) {
        exitWhiteboard();
        ElMessage.info('已自动退出白板，开启视频放大模式');
    }

    // 如果正在放大其他用户，先关闭
    if (enlargedParticipant.value && enlargedParticipant.value.identity !== hostUid.value) {
        closeEnlargedView();
    }

    enlargedParticipant.value = participant;
    ElMessage.success(`已放大您的视频`);
    
    // 发布放大消息给其他用户
    publishEnlargeVideoMessage(VIDEO_ENLARGE_MESSAGE_TYPES.ENLARGE, {
        participant: {
            identity: participant.identity,
            hasCameraTrack: participant.hasCameraTrack,
            audioEnabled: participant.audioEnabled
        }
    });
}

// 关闭放大视图
function closeEnlargedView() {
    // 如果当前放大的是自己的视频，发送缩小消息
    if (enlargedParticipant.value && enlargedParticipant.value.identity === hostUid.value) {
        publishEnlargeVideoMessage(VIDEO_ENLARGE_MESSAGE_TYPES.SHRINK, {
            participant: {
                identity: hostUid.value
            }
        });
    }
    enlargedParticipant.value = null;
    ElMessage.info('已关闭放大视图');
}
// 设置放大视频引用
function setEnlargedVideoRef(el) {
    if (!el) return;
    enlargedVideo.value = el;
    
    // 如果已经有轨道数据，立即附加
    if (enlargedParticipant.value) {
        if (enlargedParticipant.value.identity === hostUid.value) {
            // 本地视频
            if (localVideo.value && localVideo.value.srcObject) {
                el.srcObject = localVideo.value.srcObject;
            }
        } else {
            // 远程参与者
            const participantData = remoteParticipants.value.get(enlargedParticipant.value.identity);
            if (participantData && participantData.cameraTrack) {
                attachTrackToVideo(el, participantData.cameraTrack);
            }
        }
    }
}

// 处理放大视频加载
function handleEnlargedVideoLoaded() {
    console.log('放大视频已加载');
    // initLaserPointerCanvas(); 
}

//订阅视屏缩放
async function initMqttEnlargeVideo(){
    try { 
    if (isMqttEnlargeVideo.value) return 
    const clientId = `enlargeVideo_${Date.now()}`
    await mqttClient.connect(clientId)
    isMqttEnlargeVideo.value = true  
    // 订阅主题
    subscribeToEnlargeVideoTopic()
  } catch (error) {
    console.error('MQTT连接失败:', error)
    ElMessage.error('视屏缩放服务连接失败')
  }
}

function subscribeToEnlargeVideoTopic() {
    try {
        mqttClient.subscribe(`xSynergy/enlarge_video/${room.name}`, handleEnlargeVideoMessage);
    } catch (error) {
        console.error('订阅激光笔主题失败:', error);
    }
}
//接收视屏缩放消息
function handleEnlargeVideoMessage(payload, topic) {
    try {
        
        const messageStr = payload.toString();
        const data = JSON.parse(messageStr); 
        console.log('data视屏缩放的mqtt消息',data)
        // 只处理当前房间的消息
        if (data.roomId !== room.name) return; 
        
        // 忽略自己发送的消息
        if (data.sender === hostUid.value) return;  
        console.log(data.type,'data.type')
        switch (data.type) {
            case VIDEO_ENLARGE_MESSAGE_TYPES.ENLARGE:
                handleRemoteVideoEnlarge(data);
                break;
            case VIDEO_ENLARGE_MESSAGE_TYPES.SHRINK:
                handleRemoteVideoShrink(data);
                break;
            default:
                console.warn('未知的视频放大消息类型:', data.type);
        }
    } catch (error) {
        console.error('处理视频放大消息失败:', error);
    }
}

// 处理远程视频放大
function handleRemoteVideoEnlarge(data) {
    const { participant } = data.payload;
    
    // 确保参与者存在
    if (!remoteParticipants.value.has(participant.identity)) {
        console.warn('收到放大消息，但参与者不存在:', participant.identity);
        return;
    }
        // 如果当前正在屏幕共享，自动停止
    if (isScreenSharing.value) {
        room.localParticipant.setScreenShareEnabled(false);
        isScreenSharing.value = false;
        ElMessage.info('其他用户开启了视频放大，已自动停止屏幕共享');
    }
    
    // 如果当前正在使用白板，自动退出
    if (isWhiteboardActive.value) {
        exitWhiteboard();
        ElMessage.info('其他用户开启了视频放大，已自动退出白板');
    }

    // 如果当前正在放大其他用户，先关闭
    if (enlargedParticipant.value && enlargedParticipant.value.identity !== participant.identity) {
        closeEnlargedView();
    }

    // 放大远程参与者的视频
    enlargedParticipant.value = {
        identity: participant.identity,
        hasCameraTrack: participant.hasCameraTrack,
        audioEnabled: participant.audioEnabled
    };

    ElMessage.info(`${participant.identity} 放大了自己的视频`);
    
    // 确保视频轨道已附加
    nextTick(() => {
        const participantData = remoteParticipants.value.get(participant.identity);
        if (participantData && participantData.cameraTrack && enlargedVideo.value) {
            attachTrackToVideo(enlargedVideo.value, participantData.cameraTrack);
        }
    });
}

// 处理远程视频缩小
function handleRemoteVideoShrink(data) {
    const { participant } = data.payload;
    
    // 如果当前放大的正是这个用户，关闭放大视图
    if (enlargedParticipant.value && enlargedParticipant.value.identity === participant.identity) {
        enlargedParticipant.value = null;
        ElMessage.info(`${participant.identity} 关闭了放大视图`);
    }
}

//发送视屏缩放消息
function publishEnlargeVideoMessage(type, payload = {}) {
    try {
        const message = {
            type: type,
            roomId: room.name,
            sender: hostUid.value,
            timestamp: Date.now(),
            payload: payload
        };
        mqttClient.publish(`xSynergy/enlarge_video/${room.name}`, message);
        return true;
    } catch (error) {
        console.error('发布视频放大消息失败:', error);
        return false;
    }
}

// 初始化MQTT连接 文件上传成功
async function initMqttFileUploadSucc(){
    try { 
    if (isMqttFileuploadSucc.value) return 
    const clientId = `fileUpload_${Date.now()}`
    await mqttClient.connect(clientId)
    isMqttFileuploadSucc.value = true  
    // 订阅主题
    emitter.emit('subscribeToFileUploadTopic',{roomId:roomId.value})
  } catch (error) {
    console.error('MQTT连接失败:', error)
    ElMessage.error('文件上传服务连接失败')
  }
}

//文件预览MQTT链接
async function initMqttFilePreview(){
    try { 
    if (isMqttFilePreview.value) return 
    const clientId = `filePreview_${Date.now()}`
    await mqttClient.connect(clientId)
    isMqttFilePreview.value = true  
    // 订阅主题
    emitter.emit('subscribeToFilePreviewTopic',{roomId:roomId.value})
  } catch (error) {
    console.error('MQTT连接失败:', error)
    ElMessage.error('文件上传服务连接失败')
  }
}
//订阅文件状态主题
async function initMqttFileConversionStatus(){
    try { 
    if (isMqttFileConversionStatus.value) return 
    const clientId = `fileConversionStatus_${Date.now()}`
    await mqttClient.connect(clientId)
    isMqttFileConversionStatus.value = true  
    // 订阅主题
    emitter.emit('subscribeToFileConversionStatusTopic',{roomId:roomId.value})
  } catch (error) {
    console.error('MQTT连接失败:', error)
    ElMessage.error('文件上传服务连接失败')
  }
}

// 激光笔功能
function toggleLaserPointer() {
    if (!canUseLaserPointer.value) {
        ElMessage.warning('请在屏幕共享或放大视图模式下使用激光笔');
        return;
    }
    
    isLaserPointerActive.value = !isLaserPointerActive.value; 
    if (isLaserPointerActive.value) {
        initLaserPointerCanvas();
        ElMessage.success('激光笔已开启，双击添加标记，拖拽绘制线条');
    } else {
        cleanupAllLaserElements();
        ElMessage.info('激光笔已关闭');
    }
}

// 清理所有激光笔元素
function cleanupAllLaserElements() {
    // 清理屏幕共享的激光笔元素
    cleanupLaserElements(laserPointerTimeouts, laserPointerElements);
    
    // 清理放大视频的激光笔元素
    cleanupLaserElements(enlargedLaserPointerTimeouts, enlargedLaserPointerElements);
    
    // 清除画布
    if (laserPointerContext.value && laserPointerCanvas.value) {
        laserPointerContext.value.clearRect(0, 0, laserPointerCanvas.value.width, laserPointerCanvas.value.height);
    }
    if (enlargedLaserPointerContext.value && enlargedLaserPointerCanvas.value) {
        enlargedLaserPointerContext.value.clearRect(0, 0, enlargedLaserPointerCanvas.value.width, enlargedLaserPointerCanvas.value.height);
    }
    
    mouseState.isDrawing = false;
    enlargedMouseState.isDrawing = false;
}
function cleanupLaserElements(timeoutsMap, elementsMap) {
    // 清除所有定时器
    timeoutsMap.value.forEach((timeoutId, elementId) => {
        clearTimeout(timeoutId);
    });
    timeoutsMap.value.clear();
    
    // 清空所有元素
    elementsMap.value.clear();
}
// 添加新的激光笔元素
function addLaserElement(element, elementsMap = laserPointerElements, timeoutsMap = laserPointerTimeouts) {
    const elementId = generateElementId();
    element.id = elementId;
    element.timestamp = Date.now();
    
    elementsMap.value.set(elementId, element);
    
    // 为每个元素设置独立的定时器
    const timeoutId = setTimeout(() => {
        removeLaserElement(elementId, elementsMap, timeoutsMap);
    }, laserPointerConfig.duration);
    
    timeoutsMap.value.set(elementId, timeoutId);
    
    // 重新绘制所有元素
    redrawLaserElements();
    
    return elementId;
}

// 移除单个激光笔元素
function removeLaserElement(elementId, elementsMap = laserPointerElements, timeoutsMap = laserPointerTimeouts) {
    // 清除定时器
    if (timeoutsMap.value.has(elementId)) {
        clearTimeout(timeoutsMap.value.get(elementId));
        timeoutsMap.value.delete(elementId);
    }
    
    // 移除元素
    elementsMap.value.delete(elementId);
    
    // 重新绘制
    redrawLaserElements();
}

function handleScreenShareLoaded() { 
     // 视频加载完成后初始化激光笔 Canvas
     initLaserPointerCanvas();
}

// 初始化激光笔 Canvas
function initLaserPointerCanvas() {
    let targetElement, canvasRef, contextRef;
    
    if (hasActiveScreenShare.value) {
        // 屏幕共享模式
        targetElement = document.querySelector('.screen-share-element');
        canvasRef = laserPointerCanvas;
        contextRef = laserPointerContext;
        screenShareVideoElement.value = targetElement;
    } else if (enlargedParticipant.value) {
        // 放大视频模式
        targetElement = document.querySelector('.enlarged-video-element');
        canvasRef = enlargedLaserPointerCanvas;
        contextRef = enlargedLaserPointerContext;
        screenShareVideoElement.value = targetElement;
    }
    
    if (!targetElement || !canvasRef.value) return; 
    
    // 设置 Canvas 尺寸与目标元素一致
    updateCanvasSize(targetElement, canvasRef.value);
    
    // 获取上下文
    contextRef.value = canvasRef.value.getContext('2d'); 
    
    // 设置 Canvas 样式
    canvasRef.value.style.position = 'absolute';
    canvasRef.value.style.top = '0';
    canvasRef.value.style.left = '0';
    canvasRef.value.style.zIndex = '10';
    canvasRef.value.style.cursor = 'crosshair';
    canvasRef.value.style.pointerEvents = isLaserPointerActive.value ? 'auto' : 'none';
    
    // 初始化观察器监听目标元素大小变化
    initResizeObserver(targetElement, canvasRef, contextRef);
}

// 更新 Canvas 尺寸
function updateCanvasSize(targetElement, canvas) {
    if (!canvas || !targetElement) return;
    
    const rect = targetElement.getBoundingClientRect();
    canvas.width = rect.width;
    canvas.height = rect.height;
    canvas.style.width = `${rect.width}px`;
    canvas.style.height = `${rect.height}px`;
    
    // 重新绘制所有元素
    redrawLaserElements();
}

//  监听元素大小变化
function initResizeObserver(targetElement, canvasRef, contextRef) {
    // 先清理之前的观察器
    if (canvasSizeObserver.value) {
        canvasSizeObserver.value.disconnect();
    }
    
    canvasSizeObserver.value = new ResizeObserver((entries) => {
        for (let entry of entries) {
            if (entry.target === targetElement) {
                updateCanvasSize(targetElement, canvasRef.value);
                // 重新设置上下文
                contextRef.value = canvasRef.value.getContext('2d');
                redrawLaserElements();
            }
        }
    });
    
    canvasSizeObserver.value.observe(targetElement);
}

// 清理激光笔
function cleanupLaserPointer() {
    if (laserPointerTimeout.value) {
        clearTimeout(laserPointerTimeout.value);
        laserPointerTimeout.value = null;
    }
    
    if (laserPointerContext.value && laserPointerCanvas.value) {
        laserPointerContext.value.clearRect(0, 0, laserPointerCanvas.value.width, laserPointerCanvas.value.height);
    }
    
    laserPointerElements.value = [];
    mouseState.isDrawing = false; 
}

// 获取鼠标坐标（转换为百分比坐标）
function getMouseCoordinates(e, canvas) {
    if (!canvas) return { x: 0, y: 0 };
    
    const rect = canvas.getBoundingClientRect();
    return {
        x: ((e.clientX - rect.left) / canvas.width).toFixed(4),
        y: ((e.clientY - rect.top) / canvas.height).toFixed(4)
    };
}

// 获取实际像素坐标
function getPixelCoordinates(e, canvas) {
    if (!canvas) return { x: 0, y: 0 };
    
    const rect = canvas.getBoundingClientRect();
    return {
        x: e.clientX - rect.left,
        y: e.clientY - rect.top
    };
}

// Canvas 事件处理  双击
function handleCanvasDoubleClick(e) { 
    if (!isLaserPointerActive.value) return;  
    const coords = getMouseCoordinates(e); // 使用归一化坐标 
    // 创建圆形标记元素 - 只存储归一化坐标
    const circleElement = {
        type: 'circle',
        data: {
            color: laserPointerConfig.color,
            center: coords, 
            thickness: laserPointerConfig.thickness
        }
    }; 
    
    const elementId = addLaserElement(circleElement);
    publishLaserPointerData({
        ...circleElement,
        id: elementId
    });
}

function handleCanvasMouseDown(e) {
    if (!isLaserPointerActive.value) return;
    
    const pixelCoords = getPixelCoordinates(e);
    mouseState.isDrawing = true;
    mouseState.startX = pixelCoords.x;
    mouseState.startY = pixelCoords.y;
}

function handleCanvasMouseMove(e) {
 
}

function handleCanvasMouseUp(e) {
    if (!isLaserPointerActive.value || !mouseState.isDrawing) return;
    
    const endCoords = getMouseCoordinates(e);
    const startCoords = getMouseCoordinates({
        clientX: mouseState.startX + laserPointerCanvas.value.getBoundingClientRect().left,
        clientY: mouseState.startY + laserPointerCanvas.value.getBoundingClientRect().top
    });
    
    // 创建线条元素
    const lineElement = {
        type: 'line',
        data: {
            color: laserPointerConfig.color,
            start: startCoords,
            end: endCoords,
            thickness: laserPointerConfig.thickness
        }
    };
    
    const startPixel = getPixelFromPercentage(lineElement.data.start);
    const endPixel = getPixelFromPercentage(lineElement.data.end);
    
    // 只有当起点和终点不同时才创建线条
    if (!simpleDeepEqual(lineElement.data.start, lineElement.data.end)) {
        const elementId = addLaserElement(lineElement);
        publishLaserPointerData({
            ...lineElement,
            id: elementId
        });
    }
    
    mouseState.isDrawing = false;
}

function handleCanvasMouseLeave() {
    mouseState.isDrawing = false;
}

// 放大视频 Canvas 事件处理
function handleEnlargedCanvasDoubleClick(e) { 
    if (!isLaserPointerActive.value || !enlargedParticipant.value) return;  
    const coords = getMouseCoordinates(e, enlargedLaserPointerCanvas.value); 
    
    const circleElement = {
        type: 'circle',
        data: {
            color: laserPointerConfig.color,
            center: coords, 
            thickness: laserPointerConfig.thickness
        }
    }; 
    
    const elementId = addLaserElement(circleElement, enlargedLaserPointerElements, enlargedLaserPointerTimeouts);
    publishLaserPointerData({
        ...circleElement,
        id: elementId
    });
}

function handleEnlargedCanvasMouseDown(e) {
    if (!isLaserPointerActive.value || !enlargedParticipant.value) return;
    
    const pixelCoords = getPixelCoordinates(e, enlargedLaserPointerCanvas.value);
    enlargedMouseState.isDrawing = true;
    enlargedMouseState.startX = pixelCoords.x;
    enlargedMouseState.startY = pixelCoords.y;
}

function handleEnlargedCanvasMouseMove(e) {
    // 可以添加实时绘制预览
}
function handleEnlargedCanvasMouseUp(e) {
    if (!isLaserPointerActive.value || !enlargedMouseState.isDrawing || !enlargedParticipant.value) return;
    
    const endCoords = getMouseCoordinates(e, enlargedLaserPointerCanvas.value);
    const startCoords = getMouseCoordinates({
        clientX: enlargedMouseState.startX + enlargedLaserPointerCanvas.value.getBoundingClientRect().left,
        clientY: enlargedMouseState.startY + enlargedLaserPointerCanvas.value.getBoundingClientRect().top
    }, enlargedLaserPointerCanvas.value);
    
    // 创建线条元素
    const lineElement = {
        type: 'line',
        data: {
            color: laserPointerConfig.color,
            start: startCoords,
            end: endCoords,
            thickness: laserPointerConfig.thickness
        }
    };
    
    // 只有当起点和终点不同时才创建线条
    if (!simpleDeepEqual(lineElement.data.start, lineElement.data.end)) {
        const elementId = addLaserElement(lineElement, enlargedLaserPointerElements, enlargedLaserPointerTimeouts);
        publishLaserPointerData({
            ...lineElement,
            id: elementId
        });
    }
    
    enlargedMouseState.isDrawing = false;
}
function handleEnlargedCanvasMouseLeave() {
    enlargedMouseState.isDrawing = false;
}

// 绘制函数
function drawCircle(ctx, centerPixel) {
    if (!ctx) return; 
    ctx.beginPath();
    ctx.arc(centerPixel.x, centerPixel.y, laserPointerConfig.thickness, 0, Math.PI * 2);
    ctx.fillStyle = laserPointerConfig.color;
    ctx.fill();
    ctx.stroke();
}

function drawLine(ctx, startX, startY, endX, endY) {
    if (!ctx) return;
    
    ctx.beginPath();
    ctx.moveTo(startX, startY);
    ctx.lineTo(endX, endY);
    ctx.strokeStyle = laserPointerConfig.color;
    ctx.lineWidth = laserPointerConfig.thickness;
    ctx.lineCap = 'round';
    ctx.stroke();
}
// 重绘所有元素
function redrawLaserElements() {
    // 重绘屏幕共享的激光笔元素
    if (laserPointerContext.value && laserPointerCanvas.value) {
        redrawLaserElementsForCanvas(laserPointerContext.value, laserPointerCanvas.value, laserPointerElements.value);
    }
    
    // 重绘放大视频的激光笔元素
    if (enlargedLaserPointerContext.value && enlargedLaserPointerCanvas.value) {
        redrawLaserElementsForCanvas(enlargedLaserPointerContext.value, enlargedLaserPointerCanvas.value, enlargedLaserPointerElements.value);
    }
}

function redrawLaserElementsForCanvas(context, canvas, elements) {
    context.clearRect(0, 0, canvas.width, canvas.height);
    
    // 绘制所有活跃的元素
    elements.forEach(element => {
        if (element.type === 'circle') { 
            const centerPixel = getPixelFromPercentage(element.data.center, canvas);
            drawCircle(context, centerPixel);
        } else if (element.type === 'line') {
            const startPixel = getPixelFromPercentage(element.data.start, canvas);
            const endPixel = getPixelFromPercentage(element.data.end, canvas);
            drawLine(context, startPixel.x, startPixel.y, endPixel.x, endPixel.y);
        }
    });
}


// 从百分比坐标转换为像素坐标
function getPixelFromPercentage(percentageCoords, canvas) {
    if (!canvas) return { x: 0, y: 0 };
    
    return {
        x: parseFloat(percentageCoords.x) * canvas.width,
        y: parseFloat(percentageCoords.y) * canvas.height
    };
}

// 安排清理
function scheduleCleanup() {
    if (laserPointerTimeout.value) {
        clearTimeout(laserPointerTimeout.value);
    }
    
    laserPointerTimeout.value = setTimeout(() => {
        const now = Date.now();
        laserPointerElements.value = laserPointerElements.value.filter(
            element => now - element.data.timestamp < laserPointerConfig.duration
        );
        redrawLaserElements();
        
        // 如果还有元素，继续清理
        if (laserPointerElements.value.length > 0) {
            scheduleCleanup();
        }
    }, laserPointerConfig.duration);
}

// 响应式调整 Canvas 大小
function resizeLaserPointerCanvas() {
    if (!isLaserPointerActive.value || !laserPointerCanvas.value) return;
    
    let targetElement;
    if (hasActiveScreenShare.value) {
        targetElement = document.querySelector('.screen-share-element');
    } else if (enlargedParticipant.value) {
        targetElement = document.querySelector('.enlarged-video-element');
    }
    
    if (targetElement) {
        updateCanvasSize(targetElement);
    }
}


// 监听窗口大小变化
window.addEventListener('resize', resizeLaserPointerCanvas);

// 在初始化 MQTT 时订阅激光笔主题
function subscribeToLaserPointerTopic() {
    try {
        mqttClient.subscribe(`xSynergy/laserPointer/${room.name}`, handleLaserPointerMessage);
    } catch (error) {
        console.error('订阅激光笔主题失败:', error);
    }
} 

// 发布激光笔数据
function publishLaserPointerData(element) {
    try {
        const message = {
            type: LASER_POINTER_MESSAGE_TYPES.DRAW,
            roomId: roomId.value,
            sender: hostUid.value,
            timestamp: Date.now(),
            element: element
        };
        
        mqttClient.publish(`xSynergy/laserPointer/${room.name}`, message);
    } catch (error) {
        console.error('发布激光笔数据失败:', error);
    }
}
// 处理接收到的激光笔数据
function handleLaserPointerMessage(payload, topic) {
    try {
        const messageStr = payload.toString();
        const data = JSON.parse(messageStr);
        
        // 只处理当前房间的消息
        if (data.roomId !== room.name) return;
        
        // 忽略自己发送的消息
        if (data.sender === hostUid.value) return; 
        
        switch (data.type) {
            case LASER_POINTER_MESSAGE_TYPES.DRAW:
                handleRemoteLaserDraw(data);
                break;
                
            case LASER_POINTER_MESSAGE_TYPES.CLEAR:
                cleanupAllLaserElements();
                break;
        }
    } catch (error) {
        console.error('处理激光笔消息失败:', error);
    }
}

function handleRemoteLaserDraw(data) {
    const { element } = data;
    
    // 根据当前模式决定添加到哪个元素集合
    let elementsMap, timeoutsMap;
    
    if (hasActiveScreenShare.value) {
        elementsMap = laserPointerElements;
        timeoutsMap = laserPointerTimeouts;
    } else if (enlargedParticipant.value) {
        elementsMap = enlargedLaserPointerElements;
        timeoutsMap = enlargedLaserPointerTimeouts;
    } else {
        return; // 不在激光笔模式下，忽略消息
    }
    
    // 如果元素已存在，更新它；否则添加新元素
    if (element.id && elementsMap.value.has(element.id)) {
        elementsMap.value.set(element.id, element);
    } else {
        // 为远程元素生成新的ID（避免ID冲突）
        const newElementId = generateElementId();
        element.id = newElementId;
        element.timestamp = Date.now();
        
        elementsMap.value.set(newElementId, element);
        
        // 为远程元素设置定时器
        const timeoutId = setTimeout(() => {
            removeLaserElement(newElementId, elementsMap, timeoutsMap);
        }, laserPointerConfig.duration);
        
        timeoutsMap.value.set(newElementId, timeoutId);
    }
    
    // 重新绘制
    redrawLaserElements();
}

//文件上传
async function fileUploadHandle(){
    fileListRef.value.show()
}

//摄像头打开下拉框触发
async function handleCameraVisibleChange(e){
    try {
        if(e){ 
            // 请求摄像头权限
            const stream = await navigator.mediaDevices.getUserMedia({ video: true });
            // 获取设备列表
            const devices = await navigator.mediaDevices.enumerateDevices();
            // 过滤摄像头设备
            cameraDevices.value = devices.filter(device => device.kind === 'videoinput');
             // 重要：立即停止临时媒体流，避免占用摄像头
             stream.getTracks().forEach(track => {
                track.stop();
                console.log('临时摄像头轨道已停止');
            });
        }  
    } catch (error) {
        console.error('摄像头访问失败:', error); 
        // 使用更友好的方式提示用户
        errorHandling(error,'摄像头'); 
        // 清空设备列表
        cameraDevices.value = [];
    }
} 

// 处理摄像头设备选择
async function handleCameraCommand(deviceId) { 
    if (deviceId === 'refresh') {
        await handleCameraVisibleChange(true);
        ElMessage.success('设备列表已刷新');
        return;
    } 
    selectedCameraId.value = deviceId; 
    // 如果摄像头已经开启，重新开启以应用新设备
    if (cameraEnabled.value) {
        await switchCameraDevice(deviceId);
    } else {
        // 如果摄像头未开启，直接开启选中的设备
        await enableCameraWithDevice(deviceId);
    } 
    ElMessage.success(`已切换到摄像头: ${getDeviceName(cameraDevices.value, deviceId)}`);
}

//麦克风打开下拉框触发
async function handleMicrophoneVisibleChange(e){
    try {
        if(e){ 
            // 请求麦克风权限
            const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); 
            // 获取设备列表
            const devices = await navigator.mediaDevices.enumerateDevices(); 
           // 过滤麦克风设备
            microphoneDevices.value = devices.filter(device => device.kind === 'audioinput');
            // 停止所有轨道来关闭临时的麦克风访问
            stream.getTracks().forEach(track => track.stop()); 
        }  
    } catch (error) {
        console.error('麦克风访问失败:', error); 
        // 使用更友好的方式提示用户
        errorHandling(error,'麦克风'); 
        // 清空设备列表
        microphoneDevices.value = [];
    }
}

// 处理麦克风设备选择
async function handleMicrophoneCommand(deviceId) {
    if (deviceId === 'refresh') {
        await handleMicrophoneVisibleChange();
        ElMessage.success('设备列表已刷新');
        return;
    } 
    selectedMicrophoneId.value = deviceId; 
    // 如果麦克风已经开启，重新开启以应用新设备
    if (microphoneEnabled.value) {
        await switchMicrophoneDevice(deviceId);
    } else {
        // 如果麦克风未开启，直接开启选中的设备
        await enableMicrophoneWithDevice(deviceId);
    } 
    ElMessage.success(`已切换到麦克风: ${getDeviceName(microphoneDevices.value, deviceId)}`);
}

// 使用指定设备开启摄像头
async function enableCameraWithDevice(deviceId) {
    try {
        // 更新设备配置
        room.options.videoCaptureDefaults.deviceId = deviceId; 
        // 开启摄像头
        await room.localParticipant.setCameraEnabled(true);
        cameraEnabled.value = true; 
        // 手动获取并附加视频轨道
        setTimeout(() => {
            attachLocalCameraTrack();
        }, 200); 
        return true;
    } catch (error) {
        ElMessage.error(`使用指定设备开启摄像头失败`);
        try {
            if (cameraEnabled.value) {
                await room.localParticipant.setCameraEnabled(true);
            }
        } catch (e) {
            cameraEnabled.value = false;
            selectedCameraId.value = '';
        } 
        throw error;
    }
}

// 使用指定设备开启麦克风
async function enableMicrophoneWithDevice(deviceId) {
    try {
        // 更新设备配置
        room.options.audioCaptureDefaults.deviceId = deviceId; 
        // 开启麦克风
        await room.localParticipant.setMicrophoneEnabled(true);
        microphoneEnabled.value = true; 
        return true;
    } catch (error) {
        console.error('使用指定设备开启麦克风失败:', error);
        microphoneEnabled.value = false;
        throw error;
    }
}

// 切换摄像头设备
async function switchCameraDevice(deviceId) {
    try {
        // 先关闭当前摄像头
        await room.localParticipant.setCameraEnabled(false); 
        // 更新设备配置
        room.options.videoCaptureDefaults.deviceId = deviceId; 
        // 重新开启摄像头
        await room.localParticipant.setCameraEnabled(true); 
        // 手动获取并附加视频轨道
        setTimeout(() => {
            attachLocalCameraTrack();
        }, 200); 
        return true;
    } catch (error) {
        console.error('切换摄像头设备失败:', error);
        // 如果切换失败，尝试重新开启之前的设备
        try {
            await room.localParticipant.setCameraEnabled(true);
        } catch (e) {
            cameraEnabled.value = false;
        }
        throw error;
    }
}

// 切换麦克风设备
async function switchMicrophoneDevice(deviceId) {
    try {
        // 先关闭当前麦克风
        await room.localParticipant.setMicrophoneEnabled(false); 
        // 更新设备配置
        room.options.audioCaptureDefaults.deviceId = deviceId; 
        // 重新开启麦克风
        await room.localParticipant.setMicrophoneEnabled(true); 
        return true;
    } catch (error) {
        console.error('切换麦克风设备失败:', error);
        // 如果切换失败，尝试重新开启之前的设备
        try {
            await room.localParticipant.setMicrophoneEnabled(true);
        } catch (e) {
            microphoneEnabled.value = false;
        }
        throw error;
    }
}

// 初始化白板MQTT连接
async function initMqtt() {
    try {
        // 使用随机客户端ID连接
        const clientId = `whiteboard_${Date.now()}`;
        await mqttClient.connect(clientId); 
        console.log('MQTT连接成功，客户端ID:', clientId); 
        // 订阅白板主题
        subscribeToWhiteboardTopic();  
    } catch (error) {
        console.error('MQTT连接失败:', error);
        ElMessage.error('白板同步连接失败');
    }
}

// 订阅白板主题
function subscribeToWhiteboardTopic() {
    try {
        mqttClient.subscribe(`xSynergy/shareWhiteboard/${room.name}`, handleWhiteboardMessage);
    } catch (error) {
        console.error('订阅白板主题失败:', error);
    }
} 

// 初始化激光笔MQTT连接
async function initToLaserPointerMqtt() {
    try {
        // 使用随机客户端ID连接
        const clientId = `toLaserPointer_${Date.now()}`;
        await mqttClient.connect(clientId); 
        console.log('MQTT连接(toLaserPointer)成功，客户端ID:', clientId);  
        //订阅激光笔主题
        subscribeToLaserPointerTopic()
    } catch (error) {
        console.error('MQTT连接失败:', error);
        ElMessage.error('激光笔同步连接失败');
    }
}

// 处理白板消息
function handleWhiteboardMessage(payload, topic) {
    try {
        const messageStr = payload.toString();
        const data = JSON.parse(messageStr); 
        // 只处理当前房间的消息
        if (data.roomId !== room.name) return; 
        // 忽略自己发送的消息
        if (data.sender === hostUid.value) return; 
        switch (data.type) {
            case WHITEBOARD_MESSAGE_TYPES.OPEN:
                handleRemoteWhiteboardOpen(data);
                break; 
            case WHITEBOARD_MESSAGE_TYPES.CLOSE:
                handleRemoteWhiteboardClose(data);
                break; 
            case WHITEBOARD_MESSAGE_TYPES.SYNC:
                handleWhiteboardSync(data);
                break; 
            default:
                console.warn('未知的白板消息类型:', data.type);
        }
    } catch (error) {
        console.error('处理白板消息失败:', error);
    }
}

// 处理远程打开白板
function handleRemoteWhiteboardOpen(data) {
    ElMessage.info(`${data.senderName || data.sender} 开启了白板`);
    isWhiteboardActive.value = true; 
    // 如果正在屏幕共享，自动停止
    if (isScreenSharing.value) {
        room.localParticipant.setScreenShareEnabled(false);
        isScreenSharing.value = false;
    }
    // 如果正在放大视图，自动关闭
    if (enlargedParticipant.value) {
        closeEnlargedView();
    }
}

// 处理远程关闭白板
function handleRemoteWhiteboardClose(data) { 
    ElMessage.info(`${data.senderName || data.sender} 关闭了白板`); 
    if(data.roomType == '1'){  
        isWhiteboardActive.value = false;
    } 
}

// 处理白板同步消息
function handleWhiteboardSync(data) {
    // 这里可以处理白板内容的同步
    if (whiteboardRef.value && data.payload) {
        // 调用白板组件的同步方法
        if (whiteboardRef.value.syncData) {
            whiteboardRef.value.syncData(data.payload);
        }
    }
}

//邀请进入房间
async function inviterJoinRoom(){
    inviterJoinRoomRef.value.show()
}

// 确认选择房间 
async function handleConfirmSelection(userInfo){ 
    if(userInfo.length < 0){
        ElMessage.error('请选择加入房间的人员')
        return
    }
    const joinUserIds = userInfo.map(item => item.uid) 
    await getInvite(room.name,{user_uids:joinUserIds, participant_role: "participant"})
}

function publishWhiteboardMessage(type, payload = {}) {
    try {
        const message = {
            type,
            roomType: route.query.type,//用于判断是参与者还是发起者
            roomId: roomId.value,
            sender: hostUid.value,
            senderName: hostUid.value,
            timestamp: Date.now(),
            payload
        }; 
        mqttClient.publish(`xSynergy/shareWhiteboard/${room.name}`, message); 
        return true;
    } catch (error) {
        console.error('发布白板消息失败:', error);
        ElMessage.warning('消息发送失败，但白板功能正常');
        return false;
    }
}

async function toggleWhiteboard() {
    // if(cameraEnabled.value) {
    //     ElMessage.error('请先关闭摄像头才能使用白板');
    //     return;
    // }
    
    if(hasActiveScreenShare.value){
        ElMessage.error('请先关闭屏幕共享');
        return;
    } 
    
    // roomId.value = room.name
    if (isWhiteboardActive.value) {
        // 如果白板已经激活，点击则退出白板
        await exitWhiteboard();
    } else {
        // 否则开启白板
        await startWhiteboard();
    }
}

async function startWhiteboard() { 
    try {
        // 如果正在屏幕共享，先停止
        if (isScreenSharing.value) {
            await room.localParticipant.setScreenShareEnabled(false);
            isScreenSharing.value = false;
            ElMessage.info('已停止屏幕共享，开启白板');
        }  
        // 如果正在放大视图，先关闭
        if (enlargedParticipant.value) {
            closeEnlargedView();
        }
        
        // 激活白板状态
        isWhiteboardActive.value = true; 
        const success = publishWhiteboardMessage(WHITEBOARD_MESSAGE_TYPES.OPEN, {
            action: 'open',
            whiteboardId: roomId.value,
            roomName: roomName.value
        }); 
        if (success) {
            ElMessage.success('白板已开启，已通知其他参会者');
        } else {
            ElMessage.success('白板已开启');
        } 
    } catch (error) {
        console.error('开启白板失败:', error);
        ElMessage.error('开启白板失败');
    }
}

async function exitWhiteboard() {
    try {
         // 发布关闭白板消息
         publishWhiteboardMessage(WHITEBOARD_MESSAGE_TYPES.CLOSE, {
            action: 'close',
            whiteboardId: roomId.value,
            roomName: roomName.value
        }); 
        // 执行退出白板逻辑
        isWhiteboardActive.value = false; 
        // 可以在这里添加白板清理逻辑
        if (whiteboardRef.value && whiteboardRef.value.cleanup) {
            whiteboardRef.value.cleanup();
        } 
        ElMessage.success('已退出白板'); 
    } catch (error) {
        if (error !== 'cancel') {
            console.error('退出白板失败:', error);
            ElMessage.error('退出白板失败');
        }
    }
}

// 设置视频元素引用
function setParticipantVideoRef(el, identity, type) {
    if (!el) return; 
    if (!videoElementsMap.value.has(identity)) {
        videoElementsMap.value.set(identity, {});
    } 
    const elements = videoElementsMap.value.get(identity);
    elements[type] = el;
    videoElementsMap.value.set(identity, elements); 
    // 如果已经有轨道数据，立即附加
    const participantData = remoteParticipants.value.get(identity); 
    if (participantData) {
        if (type === 'camera' && participantData.cameraTrack) {
            attachTrackToVideo(el, participantData.cameraTrack);
        } else if (type === 'screen' && participantData.screenTrack) {
            attachTrackToVideo(el, participantData.screenTrack);
        }
    }
}

// 设置音频元素引用
function setParticipantAudioRef(el, identity) {
    if (!el) return; 
    audioElementsMap.value.set(identity, el); 
    // 如果已经有音频轨道数据，立即附加
    const participantData = remoteParticipants.value.get(identity);
    if (participantData && participantData.audioTrack) {
        attachTrackToAudio(el, participantData.audioTrack);
    }
}

// 设置屏幕共享视频引用
function setScreenShareVideoRef(el) {
    if (!el) return;
    screenShareVideo.value = el; 
    // 如果已经有屏幕共享轨道，立即附加
    if (activeScreenShareTrack.value) {
        attachTrackToVideo(el, activeScreenShareTrack.value);
    } 
    // 初始化激光笔 Canvas
    nextTick(() => {
        initLaserPointerCanvas();
    });
}

// 设置事件监听器
function setupRoomListeners() {
    room.removeAllListeners();
    room
    .on(RoomEvent.Connected, handleConnected)
    .on(RoomEvent.Disconnected, handleDisconnected)
    .on(RoomEvent.Reconnected, handleReconnected)
    .on(RoomEvent.TrackSubscribed, handleTrackSubscribed)
    .on(RoomEvent.TrackUnsubscribed, handleTrackUnsubscribed)
    .on(RoomEvent.ParticipantConnected, handleParticipantConnected)
    .on(RoomEvent.ParticipantDisconnected, handleParticipantDisconnected)
    .on(RoomEvent.LocalTrackPublished, handleLocalTrackPublished)
    .on(RoomEvent.LocalTrackUnpublished, handleLocalTrackUnpublished)
    .on(RoomEvent.TrackMuted, handleTrackMuted)
    .on(RoomEvent.TrackUnmuted, handleTrackUnmuted)
    .on(RoomEvent.ActiveSpeakersChanged, handleActiveSpeakersChanged)
    .on(RoomEvent.DataReceived, handleDataReceived)
    .on(RoomEvent.ConnectionStateChanged, handleConnectionStateChanged);
}

// 事件处理函数
async function handleConnected() { 
    roomId.value = room.name 
    await initMqtt();
    await initToLaserPointerMqtt();
    await initMqttFileUploadSucc() ;
    await initMqttFileConversionStatus();
    await initMqttFilePreview();
    await initMqttEnlargeVideo(); 
    status.value = false;  
    ElMessage.success('已成功连接到房间'); 
    console.log('房间连接成功', {
        localParticipant: room.localParticipant.identity,
        remoteParticipants: room.remoteParticipants.size
    });
    // 初始化现有远程参与者
    room.remoteParticipants.forEach(participant => {
        addRemoteParticipant(participant);
        setupParticipantListeners(participant);
        // 立即检查并更新参与者的轨道状态
        updateParticipantTracks(participant);
    });
}

function handleDisconnected(reason) {
    status.value = true;
    cameraEnabled.value = false;
    microphoneEnabled.value = false;
    isScreenSharing.value = false;
    remoteParticipants.value.clear();
    videoElementsMap.value.clear();
    audioElementsMap.value.clear();
    screenSharingUser.value = '';
    activeScreenShareTrack.value = null;
    enlargedParticipant.value = null;
    ElMessage.error('连接已断开');
}

// 处理轨道订阅事件
function handleTrackSubscribed(track, publication, participant) {   
    if (track) {
        if (track.kind === Track.Kind.Video) {
            console.log(`视频轨道订阅: ${participant.identity} - ${publication.source}`, {
                track: track,
                publication: publication
            });
            
            // 更新参与者轨道信息
            updateParticipantTrack(participant, publication.source, track); 
            
            // 如果是屏幕共享，更新屏幕共享状态
            if (publication.source === Track.Source.ScreenShare) {
                updateScreenShareState(participant, track);
                // 设置全局屏幕共享用户
                globalScreenSharingUser.value = participant.identity;
                isGlobalScreenSharing.value = true;
            } 
            
            // 立即附加到视频元素（如果元素已存在）
            attachTrackToParticipantVideo(participant.identity, publication.source, track); 
            
        } else if (track.kind === Track.Kind.Audio) {
            // 处理音频轨道订阅
            updateParticipantAudioTrack(participant, track);
            attachTrackToParticipantAudio(participant.identity, track);
        }
    } 
    // 更新参与者的轨道状态
    updateParticipantTracks(participant);
}

function handleTrackUnsubscribed(track, publication, participant) { 
    // 移除对应的轨道信息
    if (track.kind === Track.Kind.Video) {
        removeParticipantTrack(participant, publication.source);
        // 清理视频元素
        detachTrackFromParticipantVideo(participant.identity, publication.source); 
        
        // 如果是屏幕共享，更新屏幕共享状态
        if (publication.source === Track.Source.ScreenShare) {
            updateScreenShareState(participant, null);
            // 清除全局屏幕共享状态
            if (globalScreenSharingUser.value === participant.identity) {
                globalScreenSharingUser.value = '';
                isGlobalScreenSharing.value = false;
            }
        }
        
        // 重要：立即更新参与者轨道状态
        updateParticipantTracks(participant);
        
    } else if (track.kind === Track.Kind.Audio) {
        // 处理音频轨道取消订阅
        removeParticipantAudioTrack(participant);
        detachTrackFromParticipantAudio(participant.identity);
        // 立即更新参与者轨道状态
        updateParticipantTracks(participant);
    }
}

function handleParticipantConnected(participant) {
    addRemoteParticipant(participant);
    setupParticipantListeners(participant);
    // 立即检查参与者的轨道状态
    updateParticipantTracks(participant);
    ElMessage.info(`新用户加入: ${participant.identity}`);
}

function handleParticipantDisconnected(participant) {
    // 如果离开的用户是屏幕共享者，清除屏幕共享状态
    if (participant.identity === screenSharingUser.value) {
        screenSharingUser.value = '';
        activeScreenShareTrack.value = null;
        if (screenShareVideo.value && screenShareVideo.value.srcObject) {
            screenShareVideo.value.srcObject = null;
        }
    } 
     // 如果离开的用户是全局屏幕共享者，清除全局状态
     if (participant.identity === globalScreenSharingUser.value) {
        globalScreenSharingUser.value = '';
        isGlobalScreenSharing.value = false;
    } 
    
    // 如果离开的用户是当前放大的用户，关闭放大视图
    if (enlargedParticipant.value && enlargedParticipant.value.identity === participant.identity) {
        closeEnlargedView();
    }
    
    removeRemoteParticipant(participant);
    ElMessage.info(`用户离开: ${participant.identity}`);
}

function handleLocalTrackPublished(publication) {
    if (publication.track) {
        if (publication.kind === Track.Kind.Video) {
            if (publication.source === Track.Source.Camera) {
                attachLocalVideoTrack(publication.track);
            } else if (publication.source === Track.Source.ScreenShare) {
                // 本地用户开始屏幕共享
                screenSharingUser.value = room.localParticipant.identity;
                activeScreenShareTrack.value = publication.track; 
                // 设置全局屏幕共享状态
                globalScreenSharingUser.value = room.localParticipant.identity;
                isGlobalScreenSharing.value = true; 
                if (screenShareVideo.value) {
                    attachTrackToVideo(screenShareVideo.value, publication.track);
                }
            }
        } else if (publication.kind === Track.Kind.Audio) {
            // 本地音频轨道发布
            microphoneEnabled.value = true;
            console.log('本地音频轨道已发布');
        }
    }
}

function handleLocalTrackUnpublished(publication) { 
    if (publication.kind === Track.Kind.Video) {
        if (publication.source === Track.Source.Camera) {
            cameraEnabled.value = false;
        } else if (publication.source === Track.Source.ScreenShare) {
            // 本地用户停止屏幕共享
            if (screenSharingUser.value === room.localParticipant.identity) {
                isScreenSharing.value = false;
                screenSharingUser.value = '';
                activeScreenShareTrack.value = null;
                   // 清除全局屏幕共享状态
                if (globalScreenSharingUser.value === room.localParticipant.identity) {
                    globalScreenSharingUser.value = '';
                    isGlobalScreenSharing.value = false;
                }
                if (screenShareVideo.value && screenShareVideo.value.srcObject) {
                    screenShareVideo.value.srcObject = null;
                }
            }
        }
    } else if (publication.kind === Track.Kind.Audio) {
        microphoneEnabled.value = false;
    }
}

function handleTrackMuted(publication, participant) {
    updateParticipantTracks(participant);
}

// 处理轨道取消静音事件
function handleTrackUnmuted(publication, participant) {
    updateParticipantTracks(participant);
}

// 设置参与者事件监听器
function setupParticipantListeners(participant) {
    participant
    .on(ParticipantEvent.TrackSubscribed, (track, publication) => {
        // console.log(`轨道订阅: ${publication.source} - ${participant.identity}`);
        handleTrackSubscribed(track, publication, participant);
    })
    .on(ParticipantEvent.TrackUnsubscribed, (track, publication) => {
        // console.log(`轨道取消订阅: ${publication.source} - ${participant.identity}`);
        handleTrackUnsubscribed(track, publication, participant);
    })
    .on(ParticipantEvent.TrackMuted, (publication) => {
        // console.log(`轨道静音: ${publication.source} - ${participant.identity}`);
        handleTrackMuted(publication, participant);
    })
    .on(ParticipantEvent.TrackUnmuted, (publication) => {
        // console.log(`轨道取消静音: ${publication.source} - ${participant.identity}`);
        handleTrackUnmuted(publication, participant);
    })
    .on(ParticipantEvent.IsSpeakingChanged, (speaking) => {
        updateParticipantSpeaking(participant, speaking);
    })
    // 添加轨道发布状态变化监听
    .on(ParticipantEvent.TrackPublished, (publication) => { 
        updateParticipantTracks(participant);
    })
    .on(ParticipantEvent.TrackUnpublished, (publication) => { 
        updateParticipantTracks(participant);
    });
}

// 处理活动说话者变化事件
function handleActiveSpeakersChanged(speakers) {
    // 更新本地说话状态
    const localIsSpeaking = speakers.some(speaker => speaker.identity === room.localParticipant.identity);
    isLocalSpeaking.value = localIsSpeaking; 
    // 更新远程参与者说话状态
    remoteParticipants.value.forEach((data, identity) => {
        const isSpeaking = speakers.some(speaker => speaker.identity === identity);
        if (data.isSpeaking !== isSpeaking) {
            data.isSpeaking = isSpeaking;
            remoteParticipants.value.set(identity, { ...data });
        }
    });
}

// 更新屏幕共享状态
function updateScreenShareState(participant, track) {
    if (track) {
        // 有新的屏幕共享轨道
        screenSharingUser.value = participant.identity;
        activeScreenShareTrack.value = track; 
        // 附加到屏幕共享视频元素
        if (screenShareVideo.value) {
            attachTrackToVideo(screenShareVideo.value, track);
        }
    } else {
        // 如果当前屏幕共享者是该参与者，清除屏幕共享状态
        if (participant.identity === screenSharingUser.value) {
            screenSharingUser.value = '';
            activeScreenShareTrack.value = null;
            if (screenShareVideo.value && screenShareVideo.value.srcObject) {
                screenShareVideo.value.srcObject = null;
            }
        }
    }
}

// 参与者管理函数
function addRemoteParticipant(participant) {
    if (!participant || participant.identity === room.localParticipant?.identity) {
        return;
    }
    const participantData = {
        identity: participant.identity,
        cameraTrack: null,
        screenTrack: null,
        audioTrack: null,
        hasCameraTrack: false,
        hasScreenTrack: false,
        audioEnabled: false,
        videoEnabled: participant.isCameraEnabled,
        isSpeaking: false
    };
    remoteParticipants.value.set(participant.identity, participantData);
    // console.log("添加远程参与者:", participant.identity);
}

function removeRemoteParticipant(participant) {
    if (remoteParticipants.value.has(participant.identity)) {
        // 清理音视频元素
        const identity = participant.identity;
        detachTrackFromParticipantVideo(identity, 'camera');
        detachTrackFromParticipantVideo(identity, 'screen');
        detachTrackFromParticipantAudio(identity);
        remoteParticipants.value.delete(identity);
        videoElementsMap.value.delete(identity);
        audioElementsMap.value.delete(identity);
    }
}

// 更新参与者轨道信息
function updateParticipantTrack(participant, source, track) {
    const data = remoteParticipants.value.get(participant.identity);
    if (!data) return;
    if (source === Track.Source.Camera) {
        data.cameraTrack = track;
        data.hasCameraTrack = true;
    } else if (source === Track.Source.ScreenShare) {
        data.screenTrack = track;
        data.hasScreenTrack = true;
    }
    remoteParticipants.value.set(participant.identity, { ...data });
}

function removeParticipantTrack(participant, source) {
    const data = remoteParticipants.value.get(participant.identity);
    if (!data) return;
    if (source === Track.Source.Camera) {
        data.cameraTrack = null;
        data.hasCameraTrack = false;
    } else if (source === Track.Source.ScreenShare) {
        data.screenTrack = null;
        data.hasScreenTrack = false;
    }
    remoteParticipants.value.set(participant.identity, { ...data });
}

// 更新参与者音频轨道信息
function updateParticipantAudioTrack(participant, track) {
    const data = remoteParticipants.value.get(participant.identity);
    if (!data) return;
    data.audioTrack = track;
    data.audioEnabled = true;
    remoteParticipants.value.set(participant.identity, { ...data });
}

function removeParticipantAudioTrack(participant) {
    const data = remoteParticipants.value.get(participant.identity);
    if (!data) return;
    data.audioTrack = null;
    data.audioEnabled = false;
    remoteParticipants.value.set(participant.identity, { ...data });
}

// 附加轨道到视频元素
function attachTrackToVideo(videoElement, track) {
    if (!videoElement || !track) return;
    try {
        // 使用 MediaStream 方式附加轨道
        const mediaStream = new MediaStream();
        mediaStream.addTrack(track.mediaStreamTrack);
        videoElement.srcObject = mediaStream;
    } catch (error) {
        console.error('附加轨道到视频元素失败:', error);
    }
}

// 附加轨道到音频元素
function attachTrackToAudio(audioElement, track) {
    if (!audioElement || !track) return;
    try {
        const mediaStream = new MediaStream();
        mediaStream.addTrack(track.mediaStreamTrack);
        audioElement.srcObject = mediaStream;
        // 确保音频元素可以播放
        audioElement.play().catch(error => {
            console.warn('音频播放失败:', error);
        });
    } catch (error) {
        console.error('附加轨道到音频元素失败:', error);
    }
}

// 附加轨道到参与者的视频元素
function attachTrackToParticipantVideo(identity, source, track) {
    const videoElements = videoElementsMap.value.get(identity);
    if (!videoElements) return;
    const type = source === Track.Source.Camera ? 'camera' : 'screen';
    const videoElement = videoElements[type];
    if (videoElement) {
        attachTrackToVideo(videoElement, track);
    }
}

// 附加轨道到参与者的音频元素
function attachTrackToParticipantAudio(identity, track) {
    const audioElement = audioElementsMap.value.get(identity);
    if (audioElement) {
        attachTrackToAudio(audioElement, track);
    }
}

// 从参与者的视频元素分离轨道
function detachTrackFromParticipantVideo(identity, source) {
    const videoElements = videoElementsMap.value.get(identity);
    if (!videoElements) return;
    const type = source === Track.Source.Camera ? 'camera' : 'screen';
    const videoElement = videoElements[type];
    if (videoElement && videoElement.srcObject) {
        videoElement.srcObject = null;
    }
}

// 从参与者的音频元素分离轨道
function detachTrackFromParticipantAudio(identity) {
    const audioElement = audioElementsMap.value.get(identity);
    if (audioElement && audioElement.srcObject) {
        audioElement.srcObject = null;
    }
}

function updateParticipantTracks(participant) {
    const data = remoteParticipants.value.get(participant.identity);
    if (!data) return;
    
    // 重置轨道状态
    let hasCamera = false;
    let hasScreen = false;
    let hasAudio = false;
    
    // 检查已发布的轨道 - 只统计已订阅且未静音的轨道
    participant.videoTrackPublications.forEach(publication => {
        if (publication.isSubscribed && publication.track && !publication.isMuted) {
            if (publication.source === Track.Source.Camera) {
                hasCamera = true;
                // 确保轨道信息更新
                if (!data.cameraTrack) {
                    data.cameraTrack = publication.track;
                }
            } else if (publication.source === Track.Source.ScreenShare) {
                hasScreen = true;
                if (!data.screenTrack) {
                    data.screenTrack = publication.track;
                }
            }
        }
    });
    
    // 检查音频轨道 - 只统计已订阅且未静音的轨道
    participant.audioTrackPublications.forEach(publication => {
        if (publication.isSubscribed && publication.track && !publication.isMuted) {
            hasAudio = true;
            if (!data.audioTrack) {
                data.audioTrack = publication.track;
            }
        }
    });
    
    // 更新数据
    data.hasCameraTrack = hasCamera;
    data.hasScreenTrack = hasScreen;
    data.audioEnabled = hasAudio;
    data.videoEnabled = participant.isCameraEnabled;
    
    // 如果没有摄像头轨道，清空相关数据
    if (!hasCamera) {
        data.cameraTrack = null;
    }
    
    // 如果没有屏幕共享轨道，清空相关数据
    if (!hasScreen) {
        data.screenTrack = null;
    }
    
    // 如果没有音频轨道，清空相关数据
    if (!hasAudio) {
        data.audioTrack = null;
    }
    
    remoteParticipants.value.set(participant.identity, { ...data });
    
    console.log(`更新参与者轨道状态: ${participant.identity}`, {
        hasCameraTrack: data.hasCameraTrack,
        hasScreenTrack: data.hasScreenTrack,
        audioEnabled: data.audioEnabled
    });
}

function updateParticipantSpeaking(participant, speaking) {
    const data = remoteParticipants.value.get(participant.identity);
    if (data && data.isSpeaking !== speaking) {
        data.isSpeaking = speaking;
        remoteParticipants.value.set(participant.identity, { ...data });
    }
} 

// 视频轨道处理函数
function attachLocalVideoTrack(track) {
    if (localVideo.value && track) {
        try {
            const mediaStream = new MediaStream();
            mediaStream.addTrack(track.mediaStreamTrack);
            localVideo.value.srcObject = mediaStream;
            cameraEnabled.value = true;
            
            // 确保视频可以播放
            localVideo.value.play().catch(error => {
                console.warn('本地视频播放失败:', error);
            });
            
            console.log('本地视频轨道已附加', track);
        } catch (error) {
            console.error('附加本地视频轨道失败:', error);
        }
    }
}

// 媒体控制函数
async function enableCamera() {
    try {
        await room.localParticipant.setCameraEnabled(true);
        cameraEnabled.value = true;
        return true;
    } catch (error) {
        console.error('开启摄像头失败:', error);
        cameraEnabled.value = false;
        throw error;
    }
}

async function enableMicrophone() {
    try {
        await room.localParticipant.setMicrophoneEnabled(true);
        microphoneEnabled.value = true;
        return true;
    } catch (error) {
        console.error('开启麦克风失败:', error);
        microphoneEnabled.value = false;
        throw error;
    }
}

async function toggleCamera() {
    try {
        if (cameraEnabled.value) {
            // 关闭摄像头
            await room.localParticipant.setCameraEnabled(false);
            cameraEnabled.value = false;
            // 清理本地视频元素
            if (localVideo.value && localVideo.value.srcObject) {
                localVideo.value.srcObject.getTracks().forEach(track => track.stop());
                localVideo.value.srcObject = null;
            }
            // 清空选中的视屏设备ID
            selectedCameraId.value = '';
            ElMessage.info('摄像头已关闭');
            if (enlargedParticipant.value) {
                closeEnlargedView();
            }
            // 强制更新一次本地参与者状态
            updateParticipantTracks(room.localParticipant);
        } else {
            // 确保视频元素存在
            if (!localVideo.value) {
                console.warn('本地视频元素未找到，等待DOM更新');
                await nextTick();
            }  
            // 开启摄像头
            // 确保有视屏输入设备权限和设备列表
            if (cameraDevices.value.length === 0) {
                // 如果没有设备列表，先获取
                await handleCameraVisibleChange(true);
            }
            if (cameraDevices.value.length === 0) {
                ElMessage.error('未找到可用的摄像头设备');
                return;
            } 
            
            // 自动选择第一个可用设备（如果当前没有选中设备）
            let deviceToUse = selectedCameraId.value;
            if (!deviceToUse && cameraDevices.value.length > 0) {
                deviceToUse = cameraDevices.value[0].deviceId;
                selectedCameraId.value = deviceToUse;
            }
            
            if (deviceToUse) {
                await enableCameraWithDevice(deviceToUse);
                ElMessage.success(`摄像头已开启 - ${getDeviceName(cameraDevices.value, deviceToUse)}`);
            } else {
                // 使用默认方式开启
                await room.localParticipant.setCameraEnabled(true);
                cameraEnabled.value = true;
                // 手动获取并附加视频轨道
                setTimeout(() => {
                    attachLocalCameraTrack();
                }, 200);
                ElMessage.success('摄像头已开启');
            }
            
            // 重要：确保轨道正确发布给其他用户
            await ensureCameraTrackPublished();
        }
    } catch (error) {
        errorHandling(error,'摄像头');
    }
}

// 确保摄像头轨道正确发布
async function ensureCameraTrackPublished() {
    try {
        // 等待轨道发布
        await new Promise(resolve => setTimeout(resolve, 500));
        
        const videoPublications = Array.from(room.localParticipant.videoTrackPublications.values());
        const cameraPublication = videoPublications.find(pub => 
            pub.source === Track.Source.Camera && pub.track
        );
        
        if (cameraPublication) {
            console.log('摄像头轨道发布状态:', {
                isSubscribed: cameraPublication.isSubscribed,
                isEnabled: cameraPublication.isEnabled,
                track: cameraPublication.track
            });
            
            // 如果轨道存在但未正确附加，重新附加
            if (cameraPublication.track && localVideo.value) {
                attachLocalVideoTrack(cameraPublication.track);
            }
        } else {
            console.warn('未找到摄像头发布轨道');
        }
    } catch (error) {
        console.error('确保摄像头轨道发布失败:', error);
    }
}

async function attachLocalCameraTrack() {
    try {
        // 等待一小段时间确保轨道已经创建
        await new Promise(resolve => setTimeout(resolve, 100));
        // 获取本地参与者的摄像头轨道发布
        const videoPublications = Array.from(room.localParticipant.videoTrackPublications.values());
        const cameraPublication = videoPublications.find(pub => 
            pub.source === Track.Source.Camera && pub.track
        );
        if (cameraPublication && cameraPublication.track) {
            attachLocalVideoTrack(cameraPublication.track);
        } else {
            // 如果没有找到，等待更长时间再检查
            setTimeout(() => {
                const videoPublications = Array.from(room.localParticipant.videoTrackPublications.values());
                const cameraPublication = videoPublications.find(pub => 
                    pub.source === Track.Source.Camera && pub.track
                );
                if (cameraPublication && cameraPublication.track) {
                    attachLocalVideoTrack(cameraPublication.track);
                } else {
                    console.warn('最终未找到摄像头轨道');
                }
            }, 1000);
        }
    } catch (error) {
        console.error('手动附加摄像头轨道失败:', error);
    }
}

async function toggleMicrophone() {
    try {
        if (microphoneEnabled.value) {
            await room.localParticipant.setMicrophoneEnabled(false);
            microphoneEnabled.value = false;
            // 停止所有音频轨道
            const audioPublications = Array.from(room.localParticipant.audioTrackPublications.values());
            for (const publication of audioPublications) {
                if (publication.track) {
                    publication.track.stop(); // 停止轨道
                }
            }
            // 清空选中的麦克风设备ID
            selectedMicrophoneId.value = '';
            ElMessage.info('麦克风已关闭');
        } else {
  // 开启麦克风
            // 确保有音频输入设备权限和设备列表
            if (microphoneDevices.value.length === 0) {
                // 如果没有设备列表，先获取
                await handleMicrophoneVisibleChange(true);
            } 
            if (microphoneDevices.value.length === 0) {
                // ElMessage.error('未找到可用的麦克风设备');
                return;
            } 
            // 自动选择第一个可用设备（如果当前没有选中设备）
            let deviceToUse = selectedMicrophoneId.value;
            if (!deviceToUse && microphoneDevices.value.length > 0) {
                deviceToUse = microphoneDevices.value[0].deviceId;
                selectedMicrophoneId.value = deviceToUse;
            } 
            if (deviceToUse) {
                await enableMicrophoneWithDevice(deviceToUse);
                ElMessage.success(`麦克风已开启 - ${getDeviceName(microphoneDevices.value, deviceToUse)}`);
            } else {
                // 使用默认方式开启
                await room.localParticipant.setMicrophoneEnabled(true);
                microphoneEnabled.value = true;
                ElMessage.success('麦克风已开启');
            } 
            ElMessage.success('麦克风已开启');
        }
    } catch (error) {
        errorHandling(error, '麦克风');
         // 如果开启失败，确保状态正确
         if (!microphoneEnabled.value) {
            selectedMicrophoneId.value = '';
        }
    }
}

async function toggleScreenShare() {
    try { 
        // 检查是否处于放大视频模式
        if (enlargedParticipant.value) {
            ElMessage.error('当前处于视频放大模式，无法进行屏幕共享');
            return;
        } 
        if(isWhiteboardActive.value){
            ElMessage.error('请先关闭白板');
            return;
        }   
        // 检查是否已经有其他用户在共享屏幕
        if (!isScreenSharing.value && isGlobalScreenSharing.value && globalScreenSharingUser.value !== hostUid.value) {
            ElMessage.error(`当前 ${globalScreenSharingUser.value} 正在共享屏幕，请等待其结束后再共享`);
            return;
        } 
        if (isScreenSharing.value) {
            await room.localParticipant.setScreenShareEnabled(false);
            isScreenSharing.value = false;
            // 清除全局屏幕共享状态
            if (globalScreenSharingUser.value === hostUid.value) {
                globalScreenSharingUser.value = '';
                isGlobalScreenSharing.value = false;
            }
            ElMessage.info('屏幕共享已停止');
        } else { 
            await room.localParticipant.setScreenShareEnabled(true); 
            isScreenSharing.value = true;
            // 设置全局屏幕共享状态
            globalScreenSharingUser.value = hostUid.value;
            isGlobalScreenSharing.value = true;   
            ElMessage.success('屏幕共享已开始');
        }
    } catch (error) {
        errorHandling(error,'屏幕共享'); 
    }
}

function handleScreenShareEnded() {
    // console.log('用户通过浏览器控件停止了屏幕共享');
    isScreenSharing.value = false;
    ElMessage.info('屏幕共享已停止'); 
    // 移除事件监听器
    room.localParticipant.off('screenShareEnded', handleScreenShareEnded);
}

async function joinRoomBtn() {
    try {
        const res = await getRoomToken({max_participants: 20}); 
        if(res.meta.code != 200){
            ElMessage.error(res.meta.message);
            return;
        }
        const token = res.data.access_token;
        roomName.value = res.data.room.name
        if (!token) {
            throw new Error('获取 token 失败');
        } 
        setupRoomListeners();
        await room.connect(wsURL, token, {
            autoSubscribe: true,
        });  
    } catch (error) { 
        ElMessage.error(`连接失败: ${error.message}`);
        status.value = true;
    }
}

// 离开会议函数
async function leaveRoom() {
    try {
                // 如果正在放大视频，发送缩小消息
        if (enlargedParticipant.value && enlargedParticipant.value.identity === hostUid.value) {
            publishEnlargeVideoMessage(VIDEO_ENLARGE_MESSAGE_TYPES.SHRINK, {
                participant: {
                    identity: hostUid.value
                }
            });
        }
        // 如果白板正在运行，先退出白板
        if (isWhiteboardActive.value) {
            publishWhiteboardMessage(WHITEBOARD_MESSAGE_TYPES.CLOSE, {
                action: 'close',
                reason: 'host_left',
                roomName: roomName.value
            });
            isWhiteboardActive.value = false;
            if (whiteboardRef.value && whiteboardRef.value.cleanup) {
                whiteboardRef.value.cleanup();
            }
        }  
          // 断开MQTT连接
        mqttClient.disconnect(); 
        // const res = await exitRoomApi(room.name) 
        // 停止屏幕共享（如果正在共享）
        if (isScreenSharing.value) {
            await room.localParticipant.setScreenShareEnabled(false);
        } 
        // 关闭摄像头和麦克风
        await room.localParticipant.setCameraEnabled(false);
        await room.localParticipant.setMicrophoneEnabled(false);
        microphoneEnabled.value = false;
        cameraEnabled.value = false;
        selectedMicrophoneId.value = '';
        selectedCameraId.value = ''
        // 断开与房间的连接
        await room.disconnect(); 
        // 重置所有状态
        resetRoomState(); 
        ElMessage.success('已离开会议');   
        
    } catch (error) {
        console.error('离开会议失败:', error);
        ElMessage.error('离开会议失败');
    }
}

async function leaveRoomHandle(){
    await leaveRoom()
    router.push({
            path: '/coordinate', 
        }) 
}

// 重置房间状态函数
function resetRoomState() {
    // 重置本地状态
    globalScreenSharingUser.value = '';
    isGlobalScreenSharing.value = false;
    isWhiteboardActive.value = false;
    cameraEnabled.value = false;
    microphoneEnabled.value = false;
    isScreenSharing.value = false;
    isLocalSpeaking.value = false;
    status.value = true;
    hostUid.value = ''; 
    selectedMicrophoneId.value = '';
    selectedCameraId.value = ''
    microphoneDevices.value = [];
    cameraDevices.value = [];
    enlargedParticipant.value = null;

    // 断开MQTT连接
    mqttClient.disconnect();
    
    // 重置远程参与者
    remoteParticipants.value.clear();
    videoElementsMap.value.clear();
    audioElementsMap.value.clear();
    
    // 重置屏幕共享状态
    screenSharingUser.value = '';
    activeScreenShareTrack.value = null;
    
    // 清理视频元素
    if (localVideo.value && localVideo.value.srcObject) {
        localVideo.value.srcObject.getTracks().forEach(track => track.stop());
        localVideo.value.srcObject = null;
    }
    
    // 清理音频元素
    if (localAudio.value && localAudio.value.srcObject) {
        localAudio.value.srcObject.getTracks().forEach(track => track.stop());
        localAudio.value.srcObject = null;
    }
    
    if (screenShareVideo.value && screenShareVideo.value.srcObject) {
        screenShareVideo.value.srcObject.getTracks().forEach(track => track.stop());
        screenShareVideo.value.srcObject = null;
    }
    
    // 清理所有远程参与者的音视频元素
    videoElementsMap.value.forEach((elements, identity) => {
        if (elements.camera && elements.camera.srcObject) {
            elements.camera.srcObject.getTracks().forEach(track => track.stop());
            elements.camera.srcObject = null;
        }
        if (elements.screen && elements.screen.srcObject) {
            elements.screen.srcObject.getTracks().forEach(track => track.stop());
            elements.screen.srcObject = null;
        }
    });
    
    audioElementsMap.value.forEach((audioElement, identity) => {
        if (audioElement && audioElement.srcObject) {
            audioElement.srcObject.getTracks().forEach(track => track.stop());
            audioElement.srcObject = null;
        }
    });
}

watch([() => hasActiveScreenShare.value, () => isScreenSharing.value], ([newHasActiveScreenShare, newIsScreenSharing]) => {
    // 如果屏幕共享被关闭（包括本地停止共享或远程共享结束）
    if (!newHasActiveScreenShare && !newIsScreenSharing) {
        // 检查激光笔是否处于开启状态
        if (isLaserPointerActive.value) {
            // console.log('屏幕共享已结束，自动关闭激光笔');
            // 自动关闭激光笔
            closeLaserPointer();
        }
    }
}, { immediate: true });

// 在摄像头关闭时，如果正在放大自己的视频，自动关闭放大视图
watch(cameraEnabled, (newVal) => {
    if (!newVal) {
        // 摄像头关闭时，如果正在放大自己的视频，自动关闭
        if (enlargedParticipant.value && enlargedParticipant.value.identity === hostUid.value) {
            closeEnlargedView();
        }
    }
});

watch([hasActiveScreenShare, enlargedParticipant], ([newHasActiveScreenShare, newEnlargedParticipant]) => {
    if (isLaserPointerActive.value) {
        // 延迟执行，确保 DOM 已更新
        nextTick(() => {
            initLaserPointerCanvas();
        });
    }
});
// 在激光笔激活时初始化 Canvas
watch(isLaserPointerActive, (newVal) => {
    if (newVal) {
        nextTick(() => {
            initLaserPointerCanvas();
        });
    } else {
        // 清理观察器
        if (canvasSizeObserver.value) {
            canvasSizeObserver.value.disconnect();
            canvasSizeObserver.value = null;
        }
    }
});
// 添加专门的关闭激光笔函数
function closeLaserPointer() {
    isLaserPointerActive.value = false;
    cleanupLaserPointer();
    
    // 重置Canvas样式
    if (laserPointerCanvas.value) {
        laserPointerCanvas.value.style.pointerEvents = 'none';
        laserPointerCanvas.value.style.cursor = 'default';
    }
    
    ElMessage.info('屏幕共享已结束，激光笔已自动关闭');
}

// 在组件卸载时也清理资源
onUnmounted(() => {
    window.removeEventListener('resize', resizeLaserPointerCanvas);
    if (canvasSizeObserver.value) {
        canvasSizeObserver.value.disconnect();
    }
    cleanupAllLaserElements();
    if (isWhiteboardActive.value && whiteboardRef.value && whiteboardRef.value.cleanup) {
        whiteboardRef.value.cleanup();
    }
    mqttClient.disconnect();
    if (room && room.state === 'connected') {
        leaveRoom();
    }
});
onMounted(async () => { 
    if(route.query.type == '1'){ 
        await joinRoomBtn()
        hostUid.value = roomStore.userUid
        // 邀请用户参与房间
        await getInvite(room.name,{user_uids:[roomStore.detailUid], participant_role: "participant"})
    } else { 
        const res = await getTokenApi(route.query.room_uid)
        if(res.meta.code == 200){ 
            const token = res.data.access_token; 
            hostUid.value = res.data.user_uid
            await nextTick(); 
            setupRoomListeners();
            await room.connect(wsURL, token, {
                autoSubscribe: true,
            });  
        }else{
            ElMessage.error(res.meta.message);
            return;
        }  
    }
});
</script>

<style lang="scss" scoped>
.enlarged-laser-canvas {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 10;
    pointer-events: auto;
    cursor: crosshair;
}

.enlarged-video-container {
    position: relative;
    width: 100%;
    height: 100%;
}

.enlarged-video-wrapper {
    position: relative;
    width: 100%;
    height: 100%;
}
.audio-on {
    color: #67c23a; /* 绿色表示在线 */
}

.audio-off {
    color: #f56c6c; /* 红色表示离线 */
}

.status-indicator .el-icon {
    margin-right: 4px;
    font-size: 18px;
}

/* 参与者操作按钮 */
.participant-actions {
    display: flex;
    gap: 4px;
}

.enlarge-btn {
    padding: 4px;
    color: #a0a0b0;
    transition: all 0.3s ease;
}

.enlarge-btn:hover {
    color: #409eff;
    background: rgba(64, 158, 255, 0.1);
}

.close-enlarge-btn {
    margin-left: auto;
}

/* 放大视频容器样式 */
.enlarged-video-container {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
}

.enlarged-video-wrapper {
    width: 100%;
    height: 100%;
    max-width: 100%;
    max-height: 100%;
    position: relative;
}

.enlarged-video-element {
    width: 100%;
    height: 100%;
    object-fit: contain;
    background: #000;
    border-radius: 8px;
}

/* 激光笔 Canvas 样式 */
.laser-pointer-canvas {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 10;
    pointer-events: auto;
    cursor: crosshair;
}
/* 激光笔状态指示器 */
.laser-pointer-indicator {
    color: #ff0000;
    font-size: 12px;
    display: flex;
    align-items: center;
    gap: 4px;
    margin-left: 12px;
}
.laser-pointer-indicator i {
    font-size: 14px;
    animation: pulse 1.5s infinite;
}
@keyframes pulse {
    0% { opacity: 1; }
    50% { opacity: 0.5; }
    100% { opacity: 1; }
}
/* 屏幕共享包装器需要相对定位 */
.screen-share-wrapper {
    position: relative;
}
/* 白板容器样式 */
.whiteboard-container {
    width: 100%;
    height: 100%;
    background: #f8f9fa;
    border-radius: 8px;
    overflow: hidden;
}
.whiteboard-component {
    width: 100%;
    height: 100%;
}
/* 添加音频状态指示器样式 */
.audio-indicator {
    margin-left: 8px;
    font-size: 12px;
}
.audio-indicator.muted {
    color: #f56c6c;
}
.audio-indicator:not(.muted) {
    color: #67c23a;
} 
@keyframes pulse {
    0% { opacity: 1; }
    50% { opacity: 0.5; }
    100% { opacity: 1; }
}
/* 隐藏音频元素，不显示在页面上 */
.audio-element, .participant-audio {
    display: none;
}
/* 控制下拉菜单样式 */
.control-dropdown {
    margin: 0;
}
.control-dropdown .el-button {
    display: flex;
    align-items: center;
    gap: 4px;
}
/* 选中的设备样式 */
.selected-device {
    background-color: #f0f9ff;
    color: #409eff;
    font-weight: 500;
}
.check-icon {
    margin-left: auto;
    color: #67c23a;
}
/* 全局样式 */
* {
    box-sizing: border-box;
}
body {
    margin: 0;
    padding: 0;
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    background: #0f0f1a;
    color: #e0e0e0;
}
.livekit-container {
    min-height: 100vh;
    padding: 20px;
    background: linear-gradient(135deg, #0f0f1a 0%, #1a1a2e 100%);
} 
/* 会议界面样式 */
.meeting-container {
    width: calc(100vw - 42px) ;
    margin: 0 auto;
    padding: 20px;
}
/* 视频布局 */
.video-layout {
    display: flex;
    flex-direction: column;
    gap: 20px;
    height: calc(100vh - 80px);
}
/* 当有屏幕共享时的布局 */
.video-layout.screen-sharing-active {
    flex-direction: row;
    gap: 20px;
}
/* 屏幕共享区域 */
.screen-share-area {
    flex: 3;
    background: rgba(255, 255, 255, 0.05);
    backdrop-filter: blur(10px);
    border-radius: 16px;
    border: 1px solid rgba(255, 255, 255, 0.1);
    overflow: hidden;
    display: flex;
    flex-direction: column;
}
.screen-share-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 16px 20px;
    background: rgba(0, 0, 0, 0.2);
    border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}
.screen-share-header h3 {
    margin: 0;
    font-size: 18px;
    font-weight: 600;
    color: #ffffff;
}
.sharing-user {
    color: #a0a0b0;
    font-size: 14px;
}
.screen-share-video {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px; 
}
.screen-share-wrapper {
    width: 100%;
    height: calc(100% - 36px) ;
    max-height: 100%;
}
.screen-share-element {
    width: 100%;
    height: 100%;
    object-fit: contain;
    background: #000;
    border-radius: 8px;
}
/* 参会者区域 */
.participants-area {
    flex: 1;
    background: rgba(255, 255, 255, 0.05);
    backdrop-filter: blur(10px);
    border-radius: 16px;
    border: 1px solid rgba(255, 255, 255, 0.1);
    overflow: hidden;
    display: flex;
    flex-direction: column;
}
.participants-area.with-screen-share {
    max-width: 400px;
}
.participants-header {
    padding: 16px 20px;
    background: rgba(0, 0, 0, 0.2);
    border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}
.participants-header h3 {
    margin: 0;
    font-size: 18px;
    font-weight: 600;
    color: #ffffff;
}
.video-grid {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 16px;
    padding: 16px;
    overflow-y: auto;
    max-height: calc(100vh - 200px); /* 为底部控制栏留出空间 */
    margin-bottom: 80px; /* 确保内容不被底部控制栏遮挡 */
}
.video-grid.grid-layout {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 16px;
    align-items: start;
}
.participant-card {
    background: rgba(255, 255, 255, 0.05);
    backdrop-filter: blur(10px);
    border-radius: 12px;
    border: 1px solid rgba(255, 255, 255, 0.1);
    overflow: hidden;
    transition: all 0.3s ease;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
    display: flex;
    flex-direction: column;
    min-height: 280px; /* 统一最小高度 */
}
.video-grid.grid-layout .video-wrapper {
    height: 200px; /* 在网格布局中也保持相同高度 */
}
.participant-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.3);
}
.local-participant {
    border: 2px solid rgba(74, 108, 247, 0.5);
}
.participant-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 12px 16px;
    background: rgba(0, 0, 0, 0.2);
    border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}
.participant-header h3 {
    margin: 0;
    font-size: 14px;
    font-weight: 600;
    color: #ffffff;
}
.status-indicator {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    color: #a0a0b0;
} 
.video-wrapper {
    position: relative;
    width: 100%;
    height:calc(100% - 36px) ; /* 固定高度 */ 
    overflow: hidden;
    background: #000; /* 统一背景色 */
    border-radius: 8px;  
}
.video-element {
    width: 100%;
    height: 100%;
    object-fit: cover;
    background: #000; 
}
.video-overlay {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    padding: 8px 12px;
    background: linear-gradient(transparent, rgba(0, 0, 0, 0.7));
    color: white;
    display: flex;
    justify-content: space-between;
    align-items: center;
    z-index: 2;
}
.participant-name {
    font-size: 12px;
    font-weight: 500;
} 
.video-placeholder {
    width: 100%;
    height: 100%;
    background: linear-gradient(135deg, #2a2a3a 0%, #1a1a2a 100%);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    color: #a0a0b0;
    font-size: 14px;
    position: absolute;
    top: 0;
    left: 0;
}
.video-placeholder i {
    font-size: 32px;
    margin-bottom: 8px;
    color: #4a4a5a;
}
.fixed-controls {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    background: rgba(15, 15, 26, 0.95);
    backdrop-filter: blur(20px);
    border-top: 1px solid rgba(255, 255, 255, 0.1);
    padding: 16px 20px;
    z-index: 1000;
}
.controls-container {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 16px;
    max-width: 1200px;
    margin: 0 auto;
} 
.control-btn {
    border-radius: 12px;
    border: none;
    font-weight: 600;
    transition: all 0.3s ease;
    padding: 12px 24px;
    font-size: 14px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}
.control-btn:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.3);
}
.control-btn i {
    margin-right: 8px;
    font-size: 16px;
}  
.dropdown-btn {
    width: 40px;
    height: 40px; 
    display: flex;
    align-items: center;
    justify-content: center;
}
.selected-device {
    background-color: #f0f7ff;
    color: #409eff;
}
.check-icon {
    margin-left: 8px;
    color: #67c23a;
}
.microphone-control-group {
    display: flex;
    align-items: center;
    background: rgba(255, 255, 255, 0.05);
    border-radius: 12px;
    overflow: hidden;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
    border: 1px solid rgba(255, 255, 255, 0.1);
}
.microphone-control-group .microphone-btn {
    border-radius: 12px 0 0 12px;
    border: none;
    box-shadow: none;
    margin: 0;
}
.microphone-control-group .microphone-dropdown {
    margin: 0;
}
.microphone-control-group .dropdown-btn {
    border-radius: 0 12px 12px 0;
    border: none;
    border-left: 1px solid rgba(255, 255, 255, 0.1);
    box-shadow: none;
    width: 44px;
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
}
/* 悬停效果 */
.microphone-control-group:hover {
    border-color: rgba(255, 255, 255, 0.2);
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.3);
}
.microphone-control-group .control-btn:hover {
    transform: none; /* 取消单独的悬停位移 */
}
/* 响应式调整 */
@media (max-width: 768px) {
    .microphone-control-group {
        flex: 1;
        min-width: 160px;
    }
    .microphone-control-group .microphone-btn {
        flex: 1;
    }
    .microphone-control-group .dropdown-btn {
        width: 40px;
        height: 40px;
    }
    .whiteboard-container {
        height: 300px; /* 在移动端限制白板高度 */
    } 
    .video-layout.screen-sharing-active {
        flex-direction: column;
    }
    .participants-area.with-screen-share {
        max-width: 100%;
    }
    /* 在小屏幕上使用单列布局 */
    .video-grid.grid-layout {
        grid-template-columns: 1fr;
    }
    /* 移动端控制栏调整 */
    .fixed-controls {
        padding: 12px 16px;
    }
    .controls-container {
        gap: 8px;
        flex-wrap: wrap;
    }
    .control-btn {
        padding: 10px 16px;
        font-size: 12px;
        flex: 1;
        min-width: 120px;
    }
    .control-btn i {
        margin-right: 6px;
        font-size: 14px;
    }
}
/* 中等屏幕上的网格布局 */
@media (min-width: 769px) and (max-width: 1200px) {
    .video-grid.grid-layout {
        grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
    }
}
/* 大屏幕上的网格布局 */
@media (min-width: 1201px) {
    .video-grid.grid-layout {
        grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    }
}
/* 超小屏幕调整 */
@media (max-width: 480px) {
    .microphone-control-group {
        min-width: 140px;
    }
    .microphone-control-group .microphone-btn {
        font-size: 11px;
        padding: 8px 10px;
    }
    .microphone-control-group .dropdown-btn {
        width: 36px;
        height: 36px;
    }
    .controls-container {
        gap: 6px;
    }
    .control-btn {
        padding: 8px 12px;
        font-size: 11px;
        min-width: 100px;
    }
    .control-btn i {
        margin-right: 4px;
        font-size: 12px;
    }
}
</style>