<template>
  <div class="voiceBroadcast">
    <div class="null-box" @click="offButton()"></div>
    <p class="get-button"
      v-if="showPermissionButton"
      @click="handlePermissionCheck"
    >点击获取麦克风权限</p>
    <div class="broadcast" v-if="!showPermissionButton">
      <p class="broadcast_t">语音广播<span>选择喇叭位置</span></p>
      <!-- 按钮部分 -->
      <div class="trumpet-max-box">
        <div @click="trumpetClick(index)" class="trumpet-for-box"
             :class="item.type?'trumpet-color-a':'trumpet-color-b'" v-for="(item,index) in trumpetList" :key="index">
          <img :src="imagesUrl('commonality/icon_sskz_zc.png')" v-if="!item.type">
          <img :src="imagesUrl('commonality/icon_sskz_xz.png')" v-if="item.type">
          {{item.deviceName}}
        </div>
      </div>
      <div class="broadcast_m no-long-press">
        <div class="broadcast_m_t no-long-press"
             :class="liveType?'broadcast_m_t_back_a':'broadcast_m_t_back_b'"
             @touchstart="handleTouchStart"
             @touchmove="handleTouchMove"
             @touchend="handleTouchEnd"
             @touchcancel="handleTouchEnd"
             @contextmenu.prevent="handleContextMenu">
        </div>
        <p class="broadcast_m_b no-long-press" v-if="!liveType">按住说话，录入广播内容</p>
        <p class="broadcast_m_b no-long-press" v-if="liveType">松开发送，向上滑动取消发送</p>
      </div>
    </div>
  </div>
</template>
<script>
  import { Toast,Dialog } from 'vant';
  import Recorder from 'recorder-core';
  import 'recorder-core/src/engine/mp3';
  import 'recorder-core/src/engine/mp3-engine';
  import { systemFileUpload,iotAppSpeakerPlayVoice } from "@/api/index";
  export default {
    name: 'voiceBroadcast',
    props: {
      trumpetList:{
        type: Array,
        default: () => []
      },
    },
    data () {
      return {
        //广播相关
        voiceType:false,
        liveType: false,
        sendLock: true, //发送锁，当为true时上锁，false时解锁发送
        isEvacuate: true, //疏散按钮控制，当为true时候执行疏散
        //H5
        recording: false,
        isInitializing: false, // 新增：防止重复初始化
        recorder: null,
        audioBlob: null,
        audioPath: null,
        //H5 拖拽
        touchStartY: 0,
        isLongPress: false,
        hasMoved: false,
        longPressTimer: null,
        moveDirection: null,
        hasTriggeredMethod3: false, // 确保方法3只触发一次
        //麦克风权限相关
        showPermissionButton:true,
        permissionStatus: null,     // 保存权限状态
        stream:null,
      }
    },
    created(){

    },
    mounted(){

    },
    methods:{
      offButton(){
        this.$parent.voiceButton();
      },
      handleTouchStart(event) {
        let self = this;
        // 彻底阻止所有默认行为
        event.preventDefault();
        event.stopPropagation();

        this.touchStartY = event.touches[0].clientY;
        this.hasMoved = false;
        this.moveDirection = null;
        this.hasTriggeredMethod3 = false;

        Promise.all([
          //获取开发配置
          self.delRecord(),
        ]).then((result) => {
          // 设置长按定时器
          self.longPressTimer = setTimeout(() => {
            self.isLongPress = true;
            self.startRecord(); // 执行方法1
          }, 300); // 300ms触发长按
        }).catch((error) => {})
      },
      // 触摸移动
      handleTouchMove(event) {
        // 彻底阻止所有默认行为
        event.preventDefault();
        event.stopPropagation();

        if (!this.isLongPress) return;

        const currentY = event.touches[0].clientY;
        const deltaY = currentY - this.touchStartY;

        // 检测滑动方向（向上滑动为负值）
        if (Math.abs(deltaY) > 75) { // 增加阈值避免误触
          this.hasMoved = true;
          this.moveDirection = deltaY < 0 ? 'up' : 'down';

          // 向上滑动执行方法3（确保只触发一次）
          if (this.moveDirection === 'up' && !this.hasTriggeredMethod3) {
            this.hasTriggeredMethod3 = true;
            this.delRecord();
          }
        }
      },
      // 触摸结束
      handleTouchEnd() {
        // 清除长按定时器
        clearTimeout(this.longPressTimer);

        if (this.isLongPress) {
          this.stopRecord(); // 执行方法2
        }

        // 重置状态
        this.isLongPress = false;
        this.hasMoved = false;
        this.moveDirection = null;
      },
      // 关键：禁用上下文菜单（长按菜单）
      handleContextMenu(e) {
        e.preventDefault();
        return false;
      },
      //获取权限并且初始化
      async initRecorder() {
        try {
          // 获取麦克风权限
          this.stream = await navigator.mediaDevices.getUserMedia({ audio: true });
          this.recorder = new Recorder({
            type: "mp3", // 输出格式
            bitRate: 128, // 比特率
            sampleRate: 44100 // 采样率
          });

          this.recorder.open(() => {
            // console.log("录音器初始化成功");
            this.recorder.start(); // 初始化后立即开始录音
          }, (error) => {
            console.error("录音器初始化失败:", error);
            Toast.fail('麦克风权限获取失败,请允许麦克风权限');
          });
        } catch (err) {
          console.error("获取麦克风失败:", err);
          Toast.fail('请允许麦克风权限');
        }
      },
      // 开始录音
      async startRecord() {
        let self = this;
        let num = 0;
        for (let i = 0; i < self.trumpetList.length; i++) {
          if (self.trumpetList[i].type) {
            num++
          }
        }
        if (num == 0) {
          Toast.fail('请选择喇叭');
          return
        }
        if (!this.recorder) {
          await this.initRecorder();
          this.startRecord();
          return;
        }
        this.recorder.start(); // 初始化后立即开始录音
        this.recording = true;
        this.liveType = true;
        Toast('录音开始');
      },
      // 停止录音
      stopRecord() {
        if (!this.recorder || !this.recording) return;
        this.recorder.stop((blob, duration) => {
          this.recording = false;
          this.liveType = false;
          this.audioBlob = blob;
          // 生成临时文件路径
          this.audioPath = URL.createObjectURL(blob);
          this.uploadAudio();
        }, (error) => {
          console.error("录音失败:", error);
          Toast('录音失败');
        });
      },
      delRecord(){
        console.log('delRecord1',this.recorder)
        if(this.recorder){
          console.log('delRecord22',this.recorder)
          this.recorder.stop((blob, duration) => {
            this.$set(this,'recording',false);
            this.$set(this,'liveType',false);
            this.$set(this,'audioBlob',null);
            this.$set(this,'audioPath',null);
          })
          this.$set(this,'recorder',null);
        }
      },
      // 上传录音文件
      uploadAudio() {
        let self = this;
        if (!this.audioBlob) return;
        // 1. 通过fetch获取Blob数据
        fetch(this.audioPath)
          .then(response => response.blob())
          .then(blob => {
            // 2. 将Blob转换为File对象
            const file = new File([blob], 'audio.mp3', { type: 'audio/mp3' });
            let formData = new FormData();
            formData.append("file", file);
            formData.append("ifAsy", false);
            systemFileUpload(formData).then(response => {
              console.log('response',response)
              let url = localStorage.getItem('fileBrowseEnvironment') + '/' + response.data.url;
              self.iotAppSpeakerPlayVoice(url);
            });
          })
          .catch(error => {
            console.error('获取Blob数据失败', error);
          });
      },
      iotAppSpeakerPlayVoice(text){
        let self = this;
        let list = [];
        for (let i = 0; i < self.trumpetList.length; i++) {
          if (self.trumpetList[i].type) {
            list.push(self.trumpetList[i].deviceNo)
          }
        }
        let obj = {
          deviceNo: list.join(','),
          voiceUrls: text,
          cycle: 1,
          level: 1000,
        };
        iotAppSpeakerPlayVoice(obj).then(response => {
          Toast.success('发送成功');
        });
      },
      //点击选择喇叭
      trumpetClick(index) {
        this.trumpetList[index].type = !this.trumpetList[index].type;
      },
      imagesUrl(imgUrl) {
        return 'https://zj-wechat.oss-cn-beijing.aliyuncs.com/xcx_images/xcx_v3/' + imgUrl
      },
      /*=====================获取权限=====================*/
      //麦克风权限相关
      async checkPermission() {
        // 检查浏览器支持性[citation:4][citation:7]
        if (!navigator.permissions || !navigator.permissions.query) {
          console.warn("浏览器不支持 Permissions API");
          return 'unsupported';
        }

        try {
          // 查询麦克风权限状态[citation:2][citation:4][citation:7]
          const permissionStatus = await navigator.permissions.query({ name: 'microphone' });
          return permissionStatus.state;
        } catch (error) {
          console.error("查询麦克风权限时发生错误:", error);
          return 'error';
        }
      },
      async handlePermissionCheck() {
        this.preInitRecorder();
        const status = await this.checkPermission();
        this.permissionStatus = status;

        switch (status) {
          case 'granted':
            // 已授权，隐藏按钮[citation:7]
            this.showPermissionButton = false;
            // 这里可以触发后续的录音操作
            break;

          case 'denied':
            // 已拒绝，显示按钮但需要特殊处理[citation:7]
            this.showPermissionButton = true;
            // 可以在这里显示引导用户去设置页面开启权限的提示
            this.showSettingsGuide();
            break;

          case 'prompt':
            // 尝试请求权限[citation:1][citation:2]
            try {
              await this.requestMicrophonePermission();
            } catch (error) {
            }
            break;

          default:
            this.showPermissionButton = true;
        }
      },
        // 预初始化录音器（不开始录音）
      async preInitRecorder() {
        if (this.isInitializing || this.recorder) return;

        this.isInitializing = true;
        try {
          this.recorder = new Recorder({
            type: "mp3",
            bitRate: 128,
            sampleRate: 44100
          });

          await new Promise((resolve, reject) => {
            this.recorder.open(() => {
              console.log("录音器预初始化成功");
              this.isInitializing = false;
              resolve();
            }, (error) => {
              console.error("录音器预初始化失败:", error);
              this.isInitializing = false;
              this.recorder = null;
              reject(error);
            });
          });
        } catch (error) {
          console.error("预初始化失败:", error);
          Toast.fail('麦克风权限获取失败,请允许麦克风权限');
        }
      },
      async requestMicrophonePermission() {
        try {
          // 请求麦克风权限[citation:1][citation:2][citation:5]
          this.stream = await navigator.mediaDevices.getUserMedia({ audio: true });
          // 权限获取成功，隐藏按钮
          this.showPermissionButton = false;
          this.permissionStatus = 'granted';
          // 立即停止流，避免占用麦克风[citation:2]
          this.stream.getTracks().forEach(track => track.stop());
        } catch (error) {
          this.permissionStatus = 'denied';
          this.showPermissionButton = true;

          // 处理不同的错误类型[citation:2]
          if (error.name === 'NotAllowedError') {
            Toast.fail('用户拒绝授予麦克风权限');
          } else if (error.name === 'NotFoundError') {
            Toast.fail('未找到麦克风设备');
          } else if (error.name === 'NotReadableError') {
            Toast.fail('麦克风被其他应用占用');
          } else {
            Toast.fail('获取麦克风权限失败');
          }
        }
      },
      showSettingsGuide() {
        Toast.fail('请允许麦克风访问权限');
      },
    },
  }
</script>
<style scoped lang="scss">
  .voiceBroadcast{
    height: 100%;
    width: 100%;
    position: fixed;
    top: 0;
    display: flex;
    flex-direction: column;
    z-index: 10;
    background: rgba(0, 0, 0, 0.4);
    .null-box {
      flex: 1;
    }
    .get-button{
      width:500px;
      height:80px;
      line-height:80px;
      font-size:32px;
      color:#fff;
      background-color: #0183FA;
      border-radius:6px;
      margin:300px 125px;
    }
    .broadcast {
      width: 100%;
      background: #FFFFFF;
      border-top-left-radius: 20px;
      border-top-right-radius: 20px;
      padding: 22px 30px 30px;
      box-sizing: border-box;
      margin-top: 20px;
      position: absolute;
      bottom: 0;

      .broadcast_t {
        font-size: 30px;
        font-family: PingFang SC;
        font-weight: 500;
        color: #333333;
        line-height: 30px;

        >label {
          font-size: 24px;
          font-family: PingFang SC;
          font-weight: 500;
          color: #999999;
          line-height: 30px;
          margin-left: 16px;
        }
      }

      .trumpet-max-box {
        display: flex;
        justify-content: flex-start;
        margin-top: 22px;
        flex-wrap: wrap;

        .trumpet-for-box {
          display: inline-block;
          width: auto;
          height: 60px;
          line-height: 60px;
          font-size: 24px;
          text-align: center;
          cursor: pointer;
          overflow: hidden;
          border: 1px solid #E0E0E0;
          border-radius: 10px;
          color: #E0E0E0;
          display: flex;
          justify-content: center;
          margin-right: 20px;
          margin-bottom: 10px;
          padding: 0 12px;
          box-sizing: border-box;

          >img {
            width: 36px;
            height: 34px;
            margin: 12px 20px 0 25px;
          }
        }

        .trumpet-color-a {
          border: 1px solid #0183FA;
          color: #0183FA;
        }

        .trumpet-color-b {
          border: 1px solid #CCCCCC;
          color: #999;
        }
      }
      .no-long-press{
        // -webkit-touch-callout: none !important;
        // -webkit-user-select: none !important;
        // -khtml-user-select: none !important;
        // -moz-user-select: none !important;
        // -ms-user-select: none !important;
        // user-select: none !important;
      }
      .broadcast_m {
        width: 100%;

        .broadcast_m_t {
          width: 142px;
          height: 142px;
          margin: 30px 0 0 258px;
          position: relative;
          font-size: 24px;
          font-family: PingFang SC;
          font-weight: 500;
          line-height: 170px;
          text-align: center;

          >img {
            width: 142px;
            height: 142px;
            position: absolute;

          }

          >label {
            width: 100%;
            font-size: 24px;
            font-family: PingFang SC;
            font-weight: 500;
            color: #0183FA;
            line-height: 24px;
            display: inline-block;
            text-align: center;
            position: absolute;
            top: 76px;
          }

          /* 按下 */
          .press_color {
            color: #FFFFFF;
          }

          /* 松开 */
          .slip_color {
            color: #0183FA;
          }
        }

        .broadcast_m_b {
          font-size: 24px;
          font-family: PingFang SC;
          font-weight: 500;
          color: #999999;
          line-height: 24px;
          text-align: center;
          margin-top: 14px;
        }
        .broadcast_m_t_back_a {
          background: url('https://zj-wechat.oss-cn-beijing.aliyuncs.com/xcx_images/xcx_v3/commonality/icon_sskz_skfs_1.png') no-repeat center 0px;
          background-size: 100%;
          color: #FFFFFF;
        }

        .broadcast_m_t_back_b {
          background: url('https://zj-wechat.oss-cn-beijing.aliyuncs.com/xcx_images/xcx_v3/commonality/icon_sskz_azsh_1.png') no-repeat center 0px;
          background-size: 100%;
          color: #0183FA;
        }
      }

      /* 疏散按钮 */
      .evacuation-button-box {
        width: 650px;
        height: 100px;
        background: #0183FA;
        color: #fff;
        text-align:center;
        line-height: 100px;
        font-size: 28px;
        margin: 88px auto 0;
        border-radius: 20px;
      }
    }
  }
</style>
