<template>
    <div class="device-page p-2">
        <!-- 头部信息栏 -->
        <div class="header-bar">
            <div>设备名称：{{ deviceDetail.deviceName }}</div>
            <div>设备型号：{{ deviceDetail.deviceImei }}</div>
            <div class="device-status">设备状态：
                <span :class="{ online: deviceDetail.onlineStatus === 1, offline: deviceDetail?.onlineStatus === 0 }">
                    {{ deviceDetail.onlineStatus === 1 ? '在线' : '离线' }}
                </span>
            </div>
            <div>电量：{{ deviceDetail.batteryPercentage || 0 }}%</div>
            <div>续航：{{ deviceDetail.batteryRemainingTime || "0" }} 分钟</div>
        </div>

        <!-- 主体内容区域 -->
        <div class="content-wrapper">
            <!-- 第一行：灯光模式 + 灯光亮度、强制报警、位置信息 -->
            <el-row :gutter="20" class="content-row">
                <el-col :lg="9" :xs="24">
                    <div class="content-card">
                        <h4 class="section-title">报警模式</h4>
                        <div class="light-mode">
                            <!-- 使用v-for循环渲染灯光模式卡片 -->
                            <div class="mode-card" @click.stop="handleVoiceType(mode.id)" v-for="mode in sta_VoiceType"
                                :key="mode.id">
                                <div class="mode_2" :class="{ 'active': mode.active }">
                                    <img :src="mode.active ? mode.activeIcon : mode.icon" :alt="mode.name"
                                        class="mode-icon" />
                                    <div class="mode-name">{{ mode.name }}</div>
                                </div>

                                <el-switch v-model="mode.switchStatusVioice" />
                            </div>
                        </div>
                    </div>
                </el-col>
                <el-col :lg="9" :xs="24">
                    <div class="content-card1">
                        <h4 class="section-title">警示灯爆闪</h4>
                        <div class="light-mode1">
                            <!-- 使用v-for循环渲染灯光模式卡片 -->
                            <div class="mode-card" @click.stop="handleModeClick(mode.id)" v-for="mode in lightModes"
                                :key="mode.id">
                                <div class="mode_2" :class="{ 'active': mode.active }">
                                    <img :src="mode.active ? mode.activeIcon : mode.icon" :alt="mode.name"
                                        class="mode-icon" />
                                    <div class="mode-name">{{ mode.name }}</div>
                                </div>

                                <el-switch v-model="mode.switchStatus" />
                            </div>
                        </div>
                    </div>
                    <div class="content-card2" style="margin-top: 8px;">
                        <h4 class="section-title">语音播报</h4>
                        <div class="voice-play-section">
                            <div class="current-voice">
                                <span class="voice-label">当前语音</span>
                                <div class="voice-select">
                                    <el-select v-model="currentVoiceId" placeholder="请选择语音" style="width: 100%;">
                                        <el-option v-for="item in voiceList" :key="item.id" :label="item.fileNameExt"
                                            :value="item.id" ite>
                                        </el-option>
                                    </el-select>
                                </div>
                                <el-button type="primary" class="play-btn" @click="playCurrentVoice(1)"
                                    v-if="deviceDetail.voiceBroadcast !== 1">
                                    播放</el-button>
                                <el-button v-else type="info" class="play-btn" @click="playCurrentVoice(0)"> 暂停
                                </el-button>
                            </div>
                            <div class="voice-manage-section">
                                <span class="voice-label">语音管理</span>
                                <div class="voice-manage-btns">
                                    <div class="voice-btn-item" @click="handleRecordVoice">
                                        <img src="@/assets/images/组 62.png" alt="">
                                        <span>录制语音</span>
                                    </div>
                                    <div class="voice-btn-item" @click="handleUploadVoice">
                                        <img src="@/assets/images/组 62.png" alt="">
                                        <span>上传语音</span>
                                    </div>
                                    <div class="voice-btn-item" @click="handleTextToVoice">
                                        <img src="@/assets/images/组 62.png" alt="">
                                        <span>文字转语音</span>
                                    </div>
                                    <div class="voice-btn-item" @click="handleAllVoice">
                                        <img src="@/assets/images/组 62.png" alt="">
                                        <span>所有语音</span>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </el-col>
                <el-col :lg="6" :xs="24">
                    <div class="brightness-alarm alarm-btn-wrapper">
                        <el-button type="danger" class="alarm-btn" @click="forceAlarm" :loading="forceAlarmLoading"
                            :loading-text="forceAlarmLoading ? '报警中...' : '强制报警'"> {{ deviceDetail.voiceStrobeAlarm ===
                                1 ? '报警中' : '强制报警' }}</el-button>
                        <el-button type="default" class="alarm-btn cancel" @click="showClose">解除报警</el-button>
                    </div>
                    <div class="content-card_gps">
                        <h4 class="section-title">位置信息</h4>
                        <div class="location-info">
                            <div class="location-item">
                                <span class="location-icon">
                                    <img src="@/assets/images/jwd.png" alt="">
                                </span>
                                <div style="font-weight: 600; font-size: 14px;">经纬度
                                    <div style="margin-top: 10px;">{{ deviceDetail && deviceDetail.longitude ?
                                        Number(deviceDetail.longitude).toFixed(4) : '0.00' }}
                                        {{ deviceDetail && deviceDetail.latitude ?
                                            Number(deviceDetail.latitude).toFixed(4)
                                            : '0.00' }} </div>
                                </div>
                            </div>
                            <div class="location-item1">
                                <div> <img src="@/assets/images/dw.png" alt="">&nbsp;&nbsp;地址</div>
                                <el-button link type="primary" class="view-btn"
                                    @click="lookMap(deviceDetail)">查看</el-button>
                            </div>
                            <div class="lacatin_gps">{{ deviceDetail.address || "未获取到地址" }}</div>
                        </div>
                    </div>
                    <div class="content-card_gps" style="margin-top: 20px;">
                        <div>
                            <h4 class="section-title">调节</h4>
                            <div class="brightness-alarm">
                                <div class="brightness-control">
                                    <div class="brightness-label">灯光亮度</div>
                                    <el-input class="inputTFT" v-model="deviceDetail.lightBrightness" :min="10"
                                        :max="100" :step="1" />
                                    <div class="brightness-value">%</div>
                                    <el-button type="primary" link class="save-btn" v-loading="lightModesLoading"
                                        @click="saveBtnlight">保存 </el-button>
                                </div>
                            </div>
                            <div class="brightness-alarm">
                                <div class="brightness-control">
                                    <div class="brightness-label">音 量</div>
                                    <el-input class="inputTFT" v-model="deviceDetail.volume" :min="10" :max="100"
                                        :step="1" />
                                    <div class="brightness-value">%</div>
                                    <el-button type="primary" link class="save-btn" @click="saveBtnVolume">保存
                                    </el-button>
                                </div>
                            </div>
                            <div class="brightness-alarm">
                                <div class="brightness-control">
                                    <div class="brightness-label">爆闪频率</div>
                                    <el-input class="inputTFT" v-model="deviceDetail.strobeFrequency" :min="0.5"
                                        :max="10" :step="1" />
                                    <div class="brightness-value">%</div>
                                    <el-button type="primary" link class="save-btn" @click="saveBtnstrobe">保存
                                    </el-button>
                                </div>
                            </div>
                        </div>
                    </div>
                </el-col>
            </el-row>
        </div>

        <!-- 录制语音弹窗（对齐UI） -->
        <el-dialog title="录制语音" v-model="recordVoiceDialog" width="480px" class="voice-dialog" :show-close="true">
            <div class="record-content">
                <!-- 波形图 -->
                <div class="waveform-container">
                    <img src="@/assets/images/lz.png" alt="">
                </div>
                <!-- 录制控制区 -->
                <div class="record-control">
                    <div class="mic-icon" :class="{ recording: isRecording }">
                        <img src="@/assets/images/ly.png" alt="">
                    </div>
                    <div class="record-time">{{ formatTime(recordDuration) }}</div>
                    <div class="record-play-btn">
                        <div v-if="isRecording" circle @click="stopRecordVoice">
                            <img src="@/assets/images/zt.png" alt="">
                        </div>
                        <div v-else circle @click="startRecordVoice">
                            <img src="@/assets/images/zk.png" alt="">
                        </div>
                    </div>

                </div>
                <!-- 底部操作 -->
                <div class="record-footer">
                    <el-button link type="info" @click="resetRecord" :disabled="isRecording">重新录制</el-button>
                    <el-button v-if="isRecording" type="info" @click="stopRecordVoice">暂停</el-button>
                    <el-button v-else type="danger" class="record-cancel-btn" @click="startRecordVoice">开始录制</el-button>
                    <el-button link type="primary" class="record-confirm" @click="saveRecordVoice">完成</el-button>

                </div>
            </div>
        </el-dialog>

        <!-- 上传语音弹窗 -->
        <el-dialog title="上传语音" v-model="uploadVoiceDialog" width="480px" class="voice-dialog" :show-close="true">
            <div class="upload-content">
                <div class="upload-area" :class="{ dragOver: isDragOver }" @dragover.prevent="isDragOver = true"
                    @dragleave.prevent="isDragOver = false" @drop.prevent="handleDrop" @click="triggerFileInput">
                    <div class="upload-icon">
                        <el-icon>
                            <Document />
                        </el-icon>
                    </div>
                    <el-button type="primary" class="select-file-btn" @click="triggerFileInput">选择文件</el-button>
                    <div class="upload-tip">将文件拖拽至此区域</div>
                    <div class="upload-file-info" v-if="uploadFile">
                        <span class="file-name">{{ uploadFile.name }}</span>
                        <span class="file-size">{{ (uploadFile.size / 1024).toFixed(2) }} KB</span>
                    </div>
                </div>
                <input ref="uploadFileInput" type="file" accept="audio/*" style="display: none"
                    @change="handleFileUpload" />
            </div>
            <template #footer>
                <el-button @click="uploadVoiceDialog = false">取消</el-button>
                <el-button type="primary" @click="confirmUploadVoice" :disabled="!uploadFile">确认</el-button>
            </template>
        </el-dialog>

        <!-- 文字转语音弹窗 -->
        <el-dialog title="文字转语音" v-model="textToVoiceDialog" width="520px" class="voice-dialog" :show-close="true">
            <div class="tts-content">
                <el-input v-model="textToVoiceForm.content" type="textarea" placeholder="请输入要转换的文字内容"
                    class="tts-textarea"></el-input>
                <div class="tts-actions">
                    <!-- <el-button link type="primary" @click="handleUploadText">上传文本</el-button> -->
                    <el-button type="primary" @click="convertTextToVoice" :loading="ttsLoading">开始转换</el-button>
                </div>
                <!-- 转换后预览 -->
                <div class="tts-preview" v-if="ttsResultUrl">
                    <div class="waveform-container">
                        <div class="waveform">
                            <span v-for="i in 30" :key="i" class="wave-bar"
                                :style="{ height: `${Math.random() * 40 + 10}px` }"></span>
                        </div>
                    </div>
                    <div class="audio-player">
                        <el-slider v-model="ttsCurrentTime" :max="ttsDuration" :show-tooltip="false"
                            style="flex: 1;"></el-slider>
                        <div class="time-info">
                            <span>{{ formatTime(ttsCurrentTime) }}</span>
                            <span>{{ formatTime(ttsDuration) }}</span>
                        </div>
                    </div>
                    <div class="player-controls">
                        <el-button circle @click="toggleTtsPlay">
                            <el-icon>
                                <VideoPlay v-if="!ttsPlaying" />
                                <!-- <Pause v-else /> -->
                            </el-icon>
                        </el-button>
                    </div>
                    <div class="preview-actions">
                        <el-button link type="primary" @click="saveTtsResult">保存</el-button>
                        <el-button type="primary" @click="useTtsResult">使用</el-button>
                    </div>
                </div>
            </div>
        </el-dialog>

        <!-- 所有语音列表弹窗 -->
        <el-dialog title="所有语音" v-model="allVoiceDialog" width="560px" class="voice-dialog" :show-close="true">
            <div class="all-voice-content">
                <div class="voice-list">
                    <div class="voice-item" v-for="item in voiceList" :key="item.id">
                        <div class="voice-info">
                            <el-icon>
                                <Document />
                            </el-icon>
                            <span class="voice-name">{{ item.fileNameExt }}</span>
                            <span>{{ item.duration }}秒</span>
                        </div>
                        <div class="voice-actions">
                            <el-button link type="primary" @click="toggleVoicePlay(item.id)">
                                {{ playingVoiceId === item.id && voicePlaying ? '暂停' : '播放' }}
                            </el-button>
                            <el-button link type="danger" @click="deleteVoiceById(item.fileId)">删除</el-button>
                            <el-button link type="primary" @click="renameVoice(item)">重命名</el-button>
                            <el-button link type="primary"
                                :class="{ 'active': item.useStatus, 'btn-default': !item.useStatus }"
                                :disabled="item.useStatus == 1" @click="useVoice(item.id)">
                                {{ item.useStatus == 1 ? '使用中' : '使用' }}
                            </el-button>
                        </div>
                    </div>
                </div>
            </div>
        </el-dialog>

        <!-- 充电提示框 -->
        <el-dialog title="充电提示" v-model="centerDialogVisible" width="15%">
            <div style="display: flex; align-items: center;">
                <h3 style="color: rgba(224, 52, 52, 1)">设备电量低于20%</h3>
            </div>
            <div>请及时充电</div>
            <span slot="footer" class="dialog-footer" style="text-align: right;display: block;">
                <el-button type="primary" @click="centerDialogVisible = false">确 定</el-button>
            </span>
        </el-dialog>
    </div>
</template>

<script setup name="DeviceControl" lang="ts">
import { useRoute, useRouter } from 'vue-router';
import { useMqtt } from '@/utils/mqtt';
import api from '@/api/controlCenter/controlPanel/100J';
import { DeviceDetail, LightMode } from '@/api/controlCenter/controlPanel/types';

// 路由和实例
const route = useRoute();
const router = useRouter();
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
// 导入图片资源
import rb from '@/assets/images/rg1.png';
import rbAc from '@/assets/images/rg1Ac.png';
import sg from '@/assets/images/hb.png';
import sgAc from '@/assets/images/hbAc.png';
// 基础状态
const forceAlarmLoading = ref(false);
const lightModesLoading = ref(false);
const centerDialogVisible = ref(false);
const currentVoiceId = ref(''); // 当前选中的语音ID
const voiceList = ref<any[]>([]); // 语音列表

// ====================== 录制语音 ======================
import Recorder from 'recorder-core';
// 引入 MP3 编码器（核心：生成标准 MP3）
import 'recorder-core/src/engine/mp3';
import 'recorder-core/src/engine/mp3-engine';
const recordVoiceDialog = ref(false);
const isRecording = ref(false);
const recordDuration = ref(0);
const recorderIns = ref<any>(null); // Recorder 实例
let recordTimer: NodeJS.Timeout | null = null;
const recordedBlob = ref()

const formatTime = (seconds: number) => {
    const min = String(Math.floor(seconds / 60)).padStart(2, '0');
    const sec = String(seconds % 60).padStart(2, '0');
    return `${min}:${sec}`;
};

// ------------- 开始录制语音上传 -------------
const startRecordVoice = async () => {
    try {
        // 1. 重置状态
        resetRecord();
        recorderIns.value = Recorder({
            type: 'mp3', // 直接录制为 MP3
            sampleRate: 44100, // 标准采样率
            bitRate: 128, // 128kbps（微信兼容）
            onProcess: (buffers: any, power: number, bufferDuration: number, bufferSampleRate: number) => {
            }
        });
        recorderIns.value.open(() => {
            // 权限申请成功，开始录制
            recorderIns.value.start();
            isRecording.value = true;
            recordDuration.value = 0;
            recordTimer = setInterval(() => recordDuration.value++, 1000);
            // proxy?.$modal.msgSuccess('开始录制语音...');
        }, (err: any) => {
            // 权限申请失败
            proxy?.$modal.msgError(`麦克风权限申请失败`);
            resetRecord();
        });
    } catch (err) {
        proxy?.$modal.msgError('录制异常，请重试');
        resetRecord();
    }
};

// ------------- 停止录制 -------------
const stopRecordVoice = () => {
    if (!recorderIns.value || !isRecording.value) {
        proxy?.$modal.msgWarning('未在录制状态');
        return;
    }

    try {
        // 停止录制并获取 MP3 Blob
        recorderIns.value.stop((blob: Blob, duration: number) => {
            // blob 是标准 MP3 格式（微信100%兼容）
            recordedBlob.value = blob;
            console.log('标准 MP3 生成成功：', blob);

            isRecording.value = false;
            if (recordTimer) clearInterval(recordTimer);
            proxy?.$modal.msgSuccess(`录制完成，时长：${Math.round(duration)}秒`);

            // 释放资源
            recorderIns.value.close();
        }, (err: any) => {
            // proxy?.$modal.msgError(`停止录制失败：${err.msg}`);
            resetRecord();
        });
    } catch (err) {
        proxy?.$modal.msgError('停止录制异常');
        resetRecord();
    }
};

// ------------- 重置录制状态 -------------
const resetRecord = () => {
    isRecording.value = false;
    recordDuration.value = 0;
    recordedBlob.value = null;
    if (recordTimer) {
        clearInterval(recordTimer);
        recordTimer = null;
    }
    // 释放 Recorder 资源
    if (recorderIns.value) {
        recorderIns.value.close();
        recorderIns.value = null;
    }
};
// ------------- 保存/上传标准 MP3 文件 -------------
const saveRecordVoice = () => {
    // 1. 校验 MP3 Blob 是否有效
    if (!recordedBlob.value || recordedBlob.value.size === 0) {
        proxy?.$modal.msgWarning('暂无有效录制的 MP3 文件');
        return;
    }
    // 2. 校验 deviceId
    const deviceId = route?.params?.deviceId;
    if (!deviceId || typeof deviceId !== 'string') {
        return;
    }
    try {
        // 3. 构建 FormData（上传标准 MP3）
        const formData = new FormData();
        formData.append('deviceId', deviceId);
        const fileName = `${new Date().getTime()}.mp3`;
        formData.append('file', recordedBlob.value, fileName);
        // 4. 上传接口
        proxy?.$modal.loading('保存中...');
        api.uploadAudioToOss(formData).then(res => {
            proxy?.$modal.closeLoading();
            if (res.code === 200) {
                proxy?.$modal.msgSuccess('保存成功');
                recordVoiceDialog.value = false;
                queryAudioFileInfo();
                resetRecord();
            } else {
                proxy?.$modal.msgError('保存语音失败');
            }
        }).catch(err => {
            proxy?.$modal.closeLoading();
            proxy?.$modal.msgError('保存语音失败');
        });
    } catch (err) {

    }
};

const handleRecordVoice = () => {
    recordVoiceDialog.value = true;
    resetRecord();
};

// ====================== 上传语音 ======================
const uploadVoiceDialog = ref(false);
const isDragOver = ref(false);
const uploadFile = ref<File | null>(null);
const uploadFileInput = ref<HTMLInputElement | null>(null);

const triggerFileInput = () => uploadFileInput.value?.click();

const handleDrop = (e: DragEvent) => {
    isDragOver.value = false;
    const files = e.dataTransfer?.files;
    if (files && files.length > 0) {
        const file = files[0];
        if (file.type.startsWith('audio/')) uploadFile.value = file;
        else proxy?.$modal.msgError('请上传音频文件');
    }
};

const handleFileUpload = (e: Event) => {
    const target = e.target as HTMLInputElement;
    const files = target.files;
    if (files && files.length > 0) {
        const file = files[0];
        if (file.type.startsWith('audio/')) uploadFile.value = file;
        else proxy?.$modal.msgError('请上传音频文件');
    }
    target.value = '';
};

const confirmUploadVoice = () => {
    if (!uploadFile.value) return;
    const formData = new FormData();
    formData.append('file', uploadFile.value);
    formData.append('deviceId', route.params.deviceId as string);
    proxy?.$modal.loading('上传中...');
    api.uploadAudioToOss(formData).then(res => {
        proxy?.$modal.closeLoading();
        if (res.code === 200) {
            proxy?.$modal.msgSuccess('语音上传成功');
            uploadVoiceDialog.value = false;
            uploadFile.value = null;
            queryAudioFileInfo();
        } else {
            proxy?.$modal.msgError('上传失败：' + res.msg);
        }
    }).catch(err => {
        proxy?.$modal.closeLoading();
        proxy?.$modal.msgError('上传失败');
    });
};

const handleUploadVoice = () => {
    uploadVoiceDialog.value = true;
    uploadFile.value = null;
};

// ====================== 文字转语音 ======================
const textToVoiceDialog = ref(false);
const textToVoiceForm = ref({ content: '' });
const ttsLoading = ref(false);
const ttsResultUrl = ref('');
const ttsPlaying = ref(false);
const ttsCurrentTime = ref(0);
const ttsDuration = ref(0);
let ttsAudio: HTMLAudioElement | null = null;
const convertTextToVoice = async () => {
    if (!textToVoiceForm.value.content.trim()) {
        proxy?.$modal.msgWarning('请输入要转换的文字内容');
        return;
    }
    ttsLoading.value = true;
    try {
        const res = await api.videTtsToOss({
            deviceId: route.params.deviceId,
            text: textToVoiceForm.value.content
        });
        if (res.code === 200) {
            ttsResultUrl.value = res.data;
            ttsDuration.value = res.data;
            proxy?.$modal.msgSuccess('文字转语音成功');
            textToVoiceDialog.value = false
        } else {
            proxy?.$modal.msgError(res.msg);
        }
    } catch (err) {
    } finally {
        ttsLoading.value = false;
    }
};

const toggleTtsPlay = () => {
    if (!ttsResultUrl.value) return;
    if (!ttsAudio) {
        ttsAudio = new Audio(ttsResultUrl.value);
        ttsAudio.ontimeupdate = () => ttsCurrentTime.value = Math.floor(ttsAudio!.currentTime);
        ttsAudio.onended = () => {
            ttsPlaying.value = false;
            ttsCurrentTime.value = 0;
        };
    }
    if (ttsPlaying.value) {
        // ttsAudio.pause();
        ttsPlaying.value = false;
    } else {
        ttsAudio.play();
        ttsPlaying.value = true;
    }
};

const saveTtsResult = () => {
    proxy?.$modal.msgSuccess('语音已保存');
    queryAudioFileInfo();
    textToVoiceDialog.value = false;
};

const useTtsResult = () => {
    proxy?.$modal.msgSuccess('语音已设置为当前使用');
    textToVoiceDialog.value = false;
};
// 上传语音
const handleTextToVoice = () => {
    textToVoiceDialog.value = true;
    textToVoiceForm.value = { content: '' };
    ttsResultUrl.value = '';
    ttsPlaying.value = false;
    ttsCurrentTime.value = 0;
};

// ====================== 所有语音 ======================
const allVoiceDialog = ref(false);
const playingVoiceId = ref('');
const voicePlaying = ref(false);
let voiceAudio: HTMLAudioElement | null = null;
// 播放弹框
const toggleVoicePlay = async (voiceId: string) => {
    // 如果当前点击的是正在播放的语音，直接暂停
    if (playingVoiceId.value === voiceId && voicePlaying.value) {
        voiceAudio?.pause();
        voicePlaying.value = false;
        return;
    }
    // 如果有其他语音正在播放，先暂停
    if (voicePlaying.value && voiceAudio) {
        voiceAudio.pause();
        voicePlaying.value = false;
    }
    // 播放当前选中的语音
    const voice = voiceList.value.find(v => v.id === voiceId);
    if (!voice || !voice.fileUrl) {
        proxy?.$modal.msgWarning('语音文件不存在');
        return;
    }
    try {
        playingVoiceId.value = voiceId;
        voiceAudio = new Audio(voice.fileUrl);
        // 仅保留播放结束后的状态重置
        voiceAudio.onended = () => {
            voicePlaying.value = false;
            playingVoiceId.value = '';
        };
        await voiceAudio.play();
        voicePlaying.value = true;
    } catch (err: any) {
        proxy?.$modal.msgError(err.msg);
        playingVoiceId.value = '';
        voicePlaying.value = false;
    }
};
// 删除语音
const deleteVoiceById = async (fileId: string) => {
    try {
        await ElMessageBox.confirm('确定要删除该语音？', '提示');
        const res = await api.deviceDeleteAudioFile({ deviceId: route.params.deviceId, fileId });
        if (res.code === 200) {
            proxy?.$modal.msgSuccess(res.msg);
            queryAudioFileInfo();
        } else {
            proxy?.$modal.msgError(res.msg);
        }
    } catch (err) { }
};
// 重命名
const renameVoice = async (item: any) => {
    const { value } = await ElMessageBox.prompt('请输入新名称', '重命名', { inputPlaceholder: '请输入新名称' });
    if (value) {
        const res = await api.videRenameAudioFile({ deviceId: route.params.deviceId, fileId: item.fileId, fileName: value });
        if (res.code === 200) {
            proxy?.$modal.msgSuccess(res.msg);
            queryAudioFileInfo();
        } else {
            proxy?.$modal.msgError(res.msg);
        }
    }
};
// 使用
const useVoice = async (voiceId: string) => {
    const res = await api.deviceUpdateVoice({ id: voiceId });
    if (res.code === 200) {
        proxy?.$modal.msgSuccess(res.msg);
        currentVoiceId.value = voiceId;
        await queryAudioFileInfo()
    } else {
        proxy?.$modal.msgError('设置失败');
    }
};

const handleAllVoice = () => {
    allVoiceDialog.value = true;
    queryAudioFileInfo();
};

// ====================== 原有功能 ======================
const sta_VoiceType = ref([
    { id: '0', name: '公安', icon: sg, activeIcon: sgAc, switchStatusVioice: true, active: true },
    { id: '1', name: '消防', icon: sg, activeIcon: sgAc, switchStatusVioice: false, active: false },
    { id: '2', name: '应急', icon: sg, activeIcon: sgAc, switchStatusVioice: false, active: false },
    { id: '3', name: '交警', icon: sg, activeIcon: sgAc, switchStatusVioice: false, active: false },
    { id: '4', name: '市政', icon: sg, activeIcon: sgAc, switchStatusVioice: false, active: false },
    { id: '5', name: '铁路', icon: sg, activeIcon: sgAc, switchStatusVioice: false, active: false },
    { id: '6', name: '医疗', icon: sg, activeIcon: sgAc, switchStatusVioice: false, active: false },
    // { id: '7', name: '部队', icon: sg, activeIcon: sgAc, switchStatusVioice: false, active: false },
    // { id: '8', name: '水利', icon: sg, activeIcon: sgAc, switchStatusVioice: false, active: false },
]);

const lightModes = ref<LightMode[]>([
    { id: 'redBlueAlternate', name: '红蓝交替', icon: rb, activeIcon: rbAc, switchStatus: true, instructValue: '6', active: true },
    { id: 'redFlash', name: '红闪', icon: rb, activeIcon: rbAc, switchStatus: false, instructValue: '0', active: false },
    { id: 'yellowFlash', name: '黄闪', icon: rb, activeIcon: rbAc, switchStatus: false, instructValue: '2', active: false },
    { id: 'blueFlash', name: '蓝闪', icon: rb, activeIcon: rbAc, switchStatus: false, instructValue: '1', active: false },
    { id: 'redClockwise', name: '红色顺时针', icon: rb, activeIcon: rbAc, switchStatus: false, instructValue: '3', active: false },
    { id: 'yellowClockwise', name: '黄色顺时针', icon: rb, activeIcon: rbAc, switchStatus: false, instructValue: '4', active: false },
    { id: 'redBlueClockwise', name: '红蓝顺时针', icon: rb, activeIcon: rbAc, switchStatus: false, instructValue: '5', active: false },
]);

const deviceDetail = ref<DeviceDetail & { typeName: string }>({
    lightBrightness: '20',
    deviceName: '',
    deviceImei: '',
    onlineStatus: 1,
    batteryPercentage: 80,
    batteryRemainingTime: '',
    longitude: '',
    latitude: '',
    address: '',
    sendMsg: '',
    chargeState: '0',
    typeName: '',
    alarmStatus: 0,
    strobeFrequency: '10',
    volume: '50',
    voiceStrobeAlarm: 0,
    voiceBroadcast: 0
});

const isUpdatingStatus = ref(false);
const isSyncingStatus = ref(false);

const queryAudioFileInfo = () => {
    api.queryAudioFileList({ deviceId: route.params.deviceId }).then(res => {
        if (res.code == 200) {
            voiceList.value = res.data || [];
            const activeVoice = voiceList.value.find(item => item.useStatus === 1);
            if (activeVoice) {
                currentVoiceId.value = activeVoice.id;
            }
        }

    }).catch(err => proxy?.$modal.msgError('获取语音列表失败'));
};
// 报警模式
const handleVoiceType = async (targetId: string) => {
    const deviceId = route.params.deviceId as string;
    if (!deviceId) return;
    const targetMode = sta_VoiceType.value.find(mode => mode.id === targetId);
    if (!targetMode) return;

    //切换选中状态
    const isCurrentlyActive = targetMode.active;
    sta_VoiceType.value.forEach(mode => {
        mode.active = false;
        mode.switchStatusVioice = false;
    });
    // 如果当前是未选中状态，则选中；如果是选中状态，则取消
    if (!isCurrentlyActive) {
        targetMode.active = true;
        targetMode.switchStatusVioice = true;
    }
    // 只有在报警中时，才发送请求
    if (deviceDetail.value.voiceStrobeAlarm == 1) {
        const params = {
            deviceIds: [deviceId],
            voiceStrobeAlarm: 1,
            mode: isCurrentlyActive ? '' : targetId
        };
        try {
            const res = await api.SosSetting(params);
            if (res.code === 200) proxy?.$modal.msgSuccess(res.msg);
        } catch (error) {
            await getList();
        }
    }
};

// 警示灯爆闪模
const handleModeClick = async (modeId: string) => {
    if (isUpdatingStatus.value || isSyncingStatus.value) return;
    try {
        const deviceId = route.params.deviceId as string;
        if (!deviceId) return;
        const targetMode = lightModes.value.find(m => m.id === modeId);
        if (!targetMode || !targetMode.instructValue) return;
        isUpdatingStatus.value = true;
        const isCurrentlyActive = targetMode.active;
        const enable = isCurrentlyActive ? 0 : 1; // 选中则关闭，未选中则开启
        //关闭时传 enable:0，开启时传 enable:1 
        const res = await api.strobeMode({
            deviceId,
            mode: targetMode.instructValue,
            enable
        });

        if (res.code === 200) {
            ElMessage.closeAll();
            proxy?.$modal.msgSuccess(res.msg);
            if (enable === 0) {
                lightModes.value.forEach(mode => {
                    mode.active = false;
                    mode.switchStatus = false;
                });
            } else {
                setActiveLightMode(modeId);
            }
        } else {
            proxy?.$modal.msgError(res.msg);
            const prevActiveMode = lightModes.value.find(m => m.active);
            if (prevActiveMode) setActiveLightMode(prevActiveMode.id);
        }
    } catch (error) {
        const prevActiveMode = lightModes.value.find(m => m.active);
        if (prevActiveMode) setActiveLightMode(prevActiveMode.id);
    } finally {
        isUpdatingStatus.value = false;
    }
};
// 全局性的方法
const setActiveLightMode = (targetModeId: string) => {
    isSyncingStatus.value = true;
    lightModes.value.forEach(mode => {
        mode.active = mode.id === targetModeId;
        mode.switchStatus = mode.active;
    });
    isSyncingStatus.value = false;
};

// 列表详情
const getList = async () => {
    try {
        const deviceId = route.params.deviceId;
        if (!deviceId) return;
        const res = await api.deviceDeatil(deviceId as string);
        deviceDetail.value = res.data;
        // 警示灯模式初始化
        const mainLightMode = String(res.data.strobeMode);
        const matchedMode = lightModes.value.find(mode => mode.instructValue === mainLightMode);
        if (matchedMode) setActiveLightMode(matchedMode.id);

        // 报警模式初始化
        const alarmMode = String(res.data.alarmMode);
        const voiceStrobeAlarm = String(res.data.voiceStrobeAlarm);
        sta_VoiceType.value.forEach(mode => {
            mode.active = false;
            mode.switchStatusVioice = false;
        });
        //如果接口返回无选中，默认选中第一个
        let hasActiveMode = false;
        if (voiceStrobeAlarm === '1') {
            const matchedVoiceMode = sta_VoiceType.value.find(mode => mode.id === alarmMode);
            if (matchedVoiceMode) {
                matchedVoiceMode.active = true;
                matchedVoiceMode.switchStatusVioice = true;
                hasActiveMode = true;
            }
        }
        // 无选中时默认选中第一个
        if (!hasActiveMode) {
            sta_VoiceType.value[0].active = true;
            sta_VoiceType.value[0].switchStatusVioice = true;
        }
    } catch (error) { console.log('获取设备详情失败:', error); }
};
// 灯光亮度
const saveBtnlight = () => {
    lightModesLoading.value = true;
    const data = { deviceId: route.params.deviceId, brightness: deviceDetail.value.lightBrightness };
    api.lightModeSettings(data).then(res => {
        if (res.code === 200) proxy?.$modal.msgSuccess(res.msg);
        else proxy?.$modal.msgError(res.msg);
        lightModesLoading.value = false;
    }).catch(() => lightModesLoading.value = false);
};

// 爆闪频率
const saveBtnstrobe = () => {
    const data = { deviceId: route.params.deviceId, frequency: deviceDetail.value.strobeFrequency };
    api.staticPowerSetting(data).then(res => {
        if (res.code === 200) proxy?.$modal.msgSuccess(res.msg);
    }).catch(err => proxy?.$modal.msgError('保存爆闪频率失败'));
};

// 音 量
const saveBtnVolume = () => {
    const data = { deviceId: route.params.deviceId, volume: deviceDetail.value.volume };
    api.settingUpdateVolume(data).then(res => {
        if (res.code === 200) proxy?.$modal.msgSuccess(res.msg);
    }).catch(err => proxy?.$modal.msgError('保存音量失败'));
};

// 解除报警
const showClose = async () => {
    try {
        await proxy?.$modal.confirm('确定要对该设备解除报警？', '提示');
        // 获取当前选中的mode
        const currentMode = sta_VoiceType.value.find(mode => mode.active)?.id || '0';
        const data = {
            deviceIds: [route.params.deviceId],
            voiceStrobeAlarm: 0,
            mode: currentMode
        };
        const res = await api.SosSetting(data);
        if (res.code === 200) {
            deviceDetail.value.voiceStrobeAlarm = 0;
            proxy?.$modal.msgSuccess(res.msg);
            //await getList();
        }
    } catch (error: any) {
        proxy?.$modal.msgError(error.msg);
    }
};

// 强制报警
const forceAlarm = async () => {
    try {
        await proxy?.$modal.confirm('确定要对该设备开启强制报警？', '提示');
        forceAlarmLoading.value = true;
        // 获取当前选中的mode
        const currentMode = sta_VoiceType.value.find(mode => mode.active)?.id || '0';
        const data = {
            deviceIds: [route.params.deviceId],
            voiceStrobeAlarm: 1,
            mode: currentMode
        };
        const res = await api.SosSetting(data);
        if (res.code === 200) {
            deviceDetail.value.voiceStrobeAlarm = 1;
            proxy?.$modal.msgSuccess(res.msg);

            //  await getList();
        }
    } catch (error: any) {
        proxy?.$modal.msgError(error.msg);
    } finally {
        forceAlarmLoading.value = false;
    }
};
// 查看跳转到地图设备
const lookMap = (row: any) => {
    router.push({ path: '/controlCenter/controlPanel', query: { view: 'map', deviceId: row.deviceId } });
};
// 播放如果，在强制报警中，点击播放的时候描会报警语音，如果没有报警中，就是的单纯的播放语音这个逻辑
const playCurrentVoice = async () => {
    // 1. 报警中场景：播放/切换报警语音
    if (deviceDetail.value.voiceStrobeAlarm === 1) {
        try {
            const currentMode = sta_VoiceType.value.find(mode => mode.active)?.id || '0';
            const data = {
                deviceIds: [route.params.deviceId],
                voiceStrobeAlarm: 1,
                mode: currentMode
            };
            const res = await api.SosSetting(data);
            if (res.code === 200) {
                proxy?.$modal.msgSuccess(res.msg);
                await getList();
            } else {
                proxy?.$modal.msgError(res.msg);
            }
        } catch (err: any) {
            //  proxy?.$modal.msgError(err.msg);
        }
    }
    // 2. 非报警中场景：单纯播放/暂停语音
    else {
        const targetStatus = deviceDetail.value.voiceBroadcast === 1 ? 0 : 1;
        try {
            const res = await api.deviceVoiceBroadcast({
                deviceId: route.params.deviceId,
                voiceBroadcast: targetStatus
            });
            if (res.code === 200) {
                deviceDetail.value.voiceBroadcast = targetStatus;
                proxy?.$modal.msgSuccess(res.msg);
                await getList();
            } else {
                proxy?.$modal.msgError(res.msg);
            }
        } catch (err: any) {
            // proxy?.$modal.msgError(err.msg);
        }
    }
};

onMounted(async () => {
    await getList();
    queryAudioFileInfo();
});

onUnmounted(() => {
    disconnect();
    if (recordTimer) clearInterval(recordTimer);
    if (mediaRecorder.value && isRecording.value) mediaRecorder.value.stop();
    if (audioStream) audioStream.getTracks().forEach(track => track.stop());
    //  if (ttsAudio) ttsAudio.pause();
    if (voiceAudio) voiceAudio.pause();
});
</script>

<style lang="scss" scoped>
.p-2 {
    background: rgba(247, 248, 252, 1);
    min-height: 100vh;
    box-sizing: border-box;
    padding: 15px;
}

.device-page {
    .header-bar {
        border-radius: 8px;
        background: linear-gradient(135deg, #3400e7, #009bff);
        color: white;
        padding: 20px;
        margin-bottom: 20px;
        display: flex;
        justify-content: space-between;
        align-items: center;
        font-weight: 600;

        .device-status {
            .online {
                color: #00ff00;
            }

            .offline {
                color: rgb(224, 52, 52);
            }
        }
    }

    .content-wrapper {
        .content-row {
            margin-bottom: 20px;
        }

        .content-card {
            border-radius: 8px;
            box-shadow: 0 2px 12px rgba(0, 34, 96, 0.1);
            background: white;
            padding: 1px 20px;
            border: 1px solid #ebeef5;
            min-height: 700px;
        }

        .content-card1 {
            border-radius: 8px;
            box-shadow: 0 2px 12px rgba(0, 34, 96, 0.1);
            background: white;
            padding: 1px 20px;
            border: 1px solid #ebeef5;
            height: 440px;
        }

        .content-card2 {
            border-radius: 8px;
            box-shadow: 0 2px 12px rgba(0, 34, 96, 0.1);
            background: white;
            padding: 1px 20px;
            border: 1px solid #ebeef5;
            height: 250px;
        }

        .content-card_gps {
            border-radius: 8px;
            box-shadow: 0 2px 12px rgba(0, 34, 96, 0.1);
            background: white;
            padding: 20px;
            border: 1px solid #ebeef5;
            min-height: 240px;
        }

        .section-title {
            font-size: 16px;
            font-weight: 600;
            margin-bottom: 20px;
            color: #303133;
        }

        .light-mode {
            display: grid;
            grid-template-columns: repeat(3, 1fr);
            gap: 15px;
        }

        .light-mode1 {
            display: grid;
            grid-template-columns: repeat(4, 1fr);
            gap: 15px;
        }

        .lacatin_gps {
            height: 70px;
            background: #F7F8FC;
            border-radius: 4px 4px 4px 4px;
            width: 100%;
            padding: 10px;
            word-break: break-all;
            margin-top: 15px;
        }

        .mode_2 {
            padding: 15px;
            border: 1px solid #dcdfe6;
            border-radius: 8px;
            width: 105px;
            text-align: center;


        }

        .active {
            border-radius: 4px 4px 4px 4px;
            border: 1px solid #027CFB;
            background: rgba(2, 124, 251, 0.06);
        }


        .mode-card {
            display: flex;
            flex-direction: column;
            align-items: center;
            border-radius: 8px;
            width: 125px;
            cursor: pointer;
            transition: all 0.3s ease;
            margin-bottom: 20px;

            &.active {
                border-color: #409eff;
                background-color: rgba(64, 158, 255, 0.05);
            }

            .mode-icon {
                width: 48px;
                margin-bottom: 10px;
                transition: all 0.3s ease;
                object-fit: scale-down;
                height: 50px;
            }

            .mode-name {
                font-size: 14px;
                margin-bottom: 12px;
                color: #606266;
            }

            .el-switch {
                --el-switch-on-color: #409eff;
                --el-switch-off-color: #dcdfe6;
            }
        }

        .alarm-btn-wrapper {
            display: flex;
            gap: 10px;
            margin-bottom: 10px;
            height: 100px;
        }

        .brightness-alarm {
            align-items: center;
            margin-bottom: 10px;

            .brightness-control {
                display: flex;
                align-items: center;
                gap: 8px;
                border-radius: 39px;
                background: rgba(255, 255, 255, 1);
                width: 100%;
                padding: 8px 15px;
                margin-top: 10px;

                .brightness-label {
                    font-size: 14px;
                    color: #606266;
                    min-width: 75px;
                }

                .brightness-value {
                    font-size: 14px;
                    color: #409eff;
                    font-weight: 500;
                }

                .save-btn {
                    padding: 6px 20px;
                    border-radius: 29px;
                    //   background: rgba(2, 124, 251, 1);
                    border: none;
                }

                .inputTFT {
                    flex: 1;
                    min-width: 80px;
                    height: 40px;
                }
            }

            .alarm-btn {
                background-color: rgba(224, 52, 52, 1);
                border-color: rgba(224, 52, 52, 1);
                padding: 20px 20px;
                border-radius: 30px;

                &.cancel {
                    background-color: rgba(224, 52, 52, 0.08);
                    border-color: rgba(224, 52, 52, 0.08);
                    color: rgba(224, 52, 52, 1);
                }
            }
        }

        .location-info {
            .location-item1 {
                display: flex;
                justify-content: space-between;
                color: #38404F;
            }

            .location-item {
                display: flex;
                // align-items: center;
                margin-bottom: 15px;
                font-size: 14px;
                color: #606266;

                .location-icon {
                    margin-right: 8px;
                    font-weight: bold;
                    color: #409eff;
                }

                .view-btn {
                    margin: 0 8px;
                    padding: 0;
                    font-size: 13px;
                }
            }
        }

        .voice-play-section {
            .current-voice {
                display: flex;
                align-items: center;
                gap: 10px;
                margin-bottom: 20px;

                .voice-label {
                    font-size: 14px;
                    color: #606266;
                    min-width: 80px;
                }

                .voice-select {
                    flex: 1;
                    display: flex;
                    align-items: center;
                    justify-content: space-between;
                    border-radius: 4px;
                    cursor: pointer;
                }

                .play-btn {
                    padding: 8px 20px;
                    border-radius: 20px;
                }
            }

            .voice-manage-section {
                .voice-label {
                    font-size: 14px;
                    color: #606266;
                    display: block;
                    margin-bottom: 15px;
                }

                .voice-manage-btns {
                    display: grid;
                    grid-template-columns: repeat(4, 1fr);
                    gap: 10px;

                    .voice-btn-item {
                        display: flex;
                        flex-direction: column;
                        align-items: center;
                        padding: 10px;
                        // border: 1px solid #dcdfe6;
                        border-radius: 8px;
                        cursor: pointer;
                        transition: all 0.3s;

                        &:hover {
                            border-color: #409eff;
                            background-color: rgba(64, 158, 255, 0.05);
                        }

                        .el-icon {
                            font-size: 24px;
                            margin-bottom: 5px;
                            color: #027CFB;
                            border: 1px solid rgba(2, 124, 251, 0.2);
                            border-radius: 6px 6px 6px 6px;
                            width: 37px;
                            height: 37px;
                        }

                        span {
                            font-size: 14px;
                            color: #027CFB;
                            margin-top: 5px;
                        }
                    }
                }
            }
        }
    }

    // 弹窗通用样式
    .voice-dialog {
        :deep(.el-dialog) {
            border-radius: 8px;
            overflow: hidden;
        }

        :deep(.el-dialog__header) {
            padding: 16px 20px;
            border-bottom: 1px solid #ebeef5;
            margin: 0;
        }

        :deep(.el-dialog__headerbtn) {
            top: 16px;
            right: 20px;
        }

        :deep(.el-dialog__body) {
            padding: 20px;
        }

        :deep(.el-dialog__footer) {
            padding: 16px 20px;
            border-top: 1px solid #ebeef5;
        }
    }

    // 录制语音弹窗样式
    .record-content {
        text-align: center;

        .waveform-container {
            height: 60px;
            display: flex;
            align-items: center;
            justify-content: center;
            margin-bottom: 20px;

            .waveform {
                display: flex;
                gap: 3px;
                align-items: center;
                height: 100%;

                .wave-bar {
                    width: 3px;
                    background: #409eff;
                    border-radius: 2px;
                    transition: height 0.2s;
                }
            }

            .waveform-placeholder {
                width: 100%;
                height: 2px;
                background: #dcdfe6;
            }
        }

        .record-control {
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: 10px;
            margin-bottom: 20px;

            .mic-icon {
                width: 60px;
                height: 60px;
                // border-radius: 50%;
                // background: rgba(64, 158, 255, 0.1);
                display: flex;
                align-items: center;
                justify-content: center;
                font-size: 28px;
                color: #409eff;
                transition: all 0.3s;

                &.recording {
                    animation: pulse 1s infinite;
                }
            }

            .record-time {
                font-size: 18px;
                font-weight: 500;
                color: #303133;
            }
        }

        .record-footer {
            display: flex;
            justify-content: space-between;
            align-items: center;

            .record-confirm {
                padding: 8px 30px;
                border-radius: 20px;
            }
        }
    }

    // 上传语音弹窗样式
    .upload-content {
        .upload-area {
            border: 2px dashed #dcdfe6;
            border-radius: 8px;
            padding: 40px 20px;
            text-align: center;
            transition: all 0.3s;
            cursor: pointer;

            &.dragOver {
                border-color: #409eff;
                background: rgba(64, 158, 255, 0.05);
            }

            .upload-icon {
                font-size: 48px;
                color: #409eff;
                margin-bottom: 15px;
            }

            .select-file-btn {
                margin-bottom: 10px;
            }

            .upload-tip {
                font-size: 12px;
                color: #909399;
            }

            .upload-file-info {
                margin-top: 15px;
                padding: 10px;
                background: #f5f7fa;
                border-radius: 4px;
                text-align: left;

                .file-name {
                    font-weight: 500;
                    color: #303133;
                }

                .file-size {
                    font-size: 12px;
                    color: #909399;
                    margin-left: 10px;
                }
            }
        }
    }

    // 文字转语音弹窗样式
    .tts-content {
        .tts-textarea {
            margin-bottom: 15px;
        }

        .tts-actions {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 20px;
        }

        .tts-preview {
            .waveform-container {
                height: 60px;
                display: flex;
                align-items: center;
                justify-content: center;
                margin-bottom: 15px;

                .waveform {
                    display: flex;
                    gap: 3px;
                    align-items: center;
                    height: 100%;

                    .wave-bar {
                        width: 3px;
                        background: #409eff;
                        border-radius: 2px;
                    }
                }
            }

            .audio-player {
                display: flex;
                align-items: center;
                gap: 10px;
                margin-bottom: 15px;

                .time-info {
                    display: flex;
                    gap: 10px;
                    font-size: 12px;
                    color: #909399;
                }
            }

            .player-controls {
                display: flex;
                justify-content: center;
                margin-bottom: 15px;
            }

            .preview-actions {
                display: flex;
                justify-content: flex-end;
                gap: 20px;
            }
        }
    }

    // 所有语音弹窗样式
    .all-voice-content {
        .voice-list {
            max-height: 400px;
            overflow-y: auto;

            .voice-item {
                padding: 15px 0;
                border-bottom: 1px solid #ebeef5;

                &:last-child {
                    border-bottom: none;
                }

                .voice-info {
                    display: flex;
                    align-items: center;
                    gap: 10px;
                    margin-bottom: 10px;

                    .voice-name {
                        font-weight: 500;
                        color: #303133;
                    }
                }

                .voice-player {
                    display: flex;
                    align-items: center;
                    gap: 10px;
                    margin-bottom: 10px;

                    .time-info {
                        display: flex;
                        gap: 10px;
                        font-size: 12px;
                        color: #909399;
                    }
                }

                .voice-actions {
                    display: flex;
                    justify-content: flex-end;
                    gap: 15px;
                }
            }
        }
    }
}

.staticRwo {
    border-radius: 8px;
    box-shadow: 0 2px 12px rgba(0, 34, 96, 0.1);
    background: white;
    border: 1px solid #ebeef5;
    height: auto;
    line-height: 36px;
    box-sizing: border-box;
    text-indent: 15px;
    color: #ff0000;
    font-weight: bold;
    font-size: 17px;
    margin-bottom: 5px;
}

.displayNone {
    display: none !important;
}

@keyframes pulse {
    0% {
        transform: scale(1);
        box-shadow: 0 0 0 0 rgba(64, 158, 255, 0.7);
    }

    70% {
        transform: scale(1.05);
        box-shadow: 0 0 0 10px rgba(64, 158, 255, 0);
    }

    100% {
        transform: scale(1);
        box-shadow: 0 0 0 0 rgba(64, 158, 255, 0);
    }
}

.active {
    color: #3333;
}
</style>