Newer
Older
urbanLifeline_YanAn / src / views / RongyunCommunication / index.vue
@zhangqy zhangqy on 12 Nov 16 KB 样式调整
<template>
  <!-- 接听来电提醒 -->
  <el-dialog
    v-model="allData.showTip"
    id="tipModal"
    append-to-body
    :close-on-click-modal="false"
    class="responseDialog"
  >
    <template #header>
      <div class="tipsHeader">来电提示</div>
    </template>
    <div style="line-height: 80px; text-align: center; font-size: 16px; color: #fff">
      收到来自 {{ allData.fromCalluser }} 的{{
        useRongyunStore.mediaType == 2 ? "视频" : "语音"
      }}邀请,是否接听???
    </div>
    <template #footer>
      <div class="dialog-footer">
        <el-button size="small" @click="hungup()">挂断</el-button>
        <el-button size="small" type="primary" @click="accept">确 定 </el-button>
      </div>
    </template>
  </el-dialog>
  <!-- 视图渲染弹窗 -->
  <el-dialog
    v-model="allData.showVideo"
    center
    id="ryAcceptModal"
    append-to-body
    :close-on-click-modal="false"
    :show-close="false"
  >
    <template #header>
      <div class="titleRy">
        远程会商
        <img
          @click="hungup()"
          src="/src/assets/images/rongYunImg/gb_btn.png"
          class="rybtn"
        />
      </div>
    </template>

    <div class="rong-container-app" id="rongContainer">
      <div id="videoViewAPP" class="rong-video-box-app"></div>
      <div id="videoActionAPP" class="rong-action-app">
        <img
          class="hunupBtn"
          id="hunup"
          src="/src/assets/images/rongYunImg/call-off.png"
          alt=""
          @click="hungup()"
        />
      </div>
    </div>
  </el-dialog>
  <div class="voiceDilog" v-if="allData.showVoice">
    <div class="voiceHeader">
      <img class="vioceIcon" src="/src/assets/images/rongYunImg/voice.png" alt="" />
      请开启声音权限
    </div>
    <el-button class="submit" type="primary" @click="allData.showVoice = false"
      >确定</el-button
    >
  </div>
</template>
<script setup>
import { ref, reactive, toRefs, onMounted, nextTick } from "vue";
import { getToken } from "@/utils/auth";
import {
  listrcloudUnitUser,
  getUserStatus,
  queryToken,
  hangUp,
} from "@/views/RongyunCommunication/rongyunjs/rongyunApi.js";
import { getInfo } from "@/api/login";
import rongyunStore from "@/store/modules/rongyunStore";
const useRongyunStore = rongyunStore();
import bus from "@/utils/util";
import * as RongIMLib from "@rongcloud/imlib-next";
// 导入 RTCLib、CallLib
import {
  installer as rtcInstaller,
  RCRTCClient,
  RCTrack,
  RCFrameRate,
  RCResolution,
} from "@rongcloud/plugin-rtc";
import useAppStore from "@/store/modules/app";
const appStore = useAppStore();

import {
  installer as callInstaller,
  RCCallClient,
  RCCallSession,
  RCCallErrorCode,
  RCCallLanguage,
  RCCallEndReason,
  RCCallMediaType,
  RCCallSessionState,
} from "@rongcloud/plugin-call";
const { proxy } = getCurrentInstance();
const audio = new Audio();
const successUrl =
  "https://192.168.100.18:10000/image/newfiber-standard-region-project/ring.mp3";

const allData = reactive({
  showVoice: false,
  // 实例化一个音频播放器对象

  tokenRy: "",
  appkey: "pkfcgjjue28x8",
  navi: "https://jingkai.wh-nf.cn:11444",
  phone: "",
  userName: "",
  showTip: false,
  fromCalluser: null,
  showVideo: false,
  styleRY: {
    width: "900px",
    height: "600px",
  },
  conversationType: null, //接收类型
  remoteUser: [], //房间人员列表
  idList: [], //视频id-dom列表
  timer: null,
  acceptType: "",
});
const GetpromoterThridUserId = ref("");

onMounted(() => {
  bus.off("showRy");
  bus.on("showRy", (e) => {
    console.log("打开融云弹框");
    if (getToken()) {
      GetuserInfo();
    }
  });
  bus.off("rystatus");
  bus.on("rystatus", (e) => {
    console.log("拨打调用", e);
    if (getToken()) {
      reconnect();
    }
  });
  console.log("getToken()", getToken());

  if (getToken()) {
    GetuserInfo();
  }
});
// 播放音频
const PlayAudio = () => {
  let music1 = new Audio(); //建立一个music1对象
  music1 = "https://jingkai.wh-nf.cn:8900/resources/videos/ring.mp3"; //通过require引入音频
  this.$refs.audio.src = music1; //此处的audio为代码ref="audio"中的audio
  this.$refs.audio.play(); //play()为播放函数
};
// 重连融云
const reconnect = () => {
  allData.tokenRy && connectIM();
  useRongyunStore.SET_online(false);
  proxy.$modal.msgWarning("视频会商已离线,重新连接中!");
};
const getStaus = (time = 0) => {
  clearInterval(allData.timer);
  allData.timer = setInterval(async () => {
    useRongyunStore.SET_online(false);

    let params = {
      registerThridUserId: allData.phone + "_web",
    };

    let res = await getUserStatus(params);
    console.log("轮询,", res);
    let flag = null;
    if (res.code == 200) {
      flag = JSON.parse(res.data);
    }
    if (flag != 1) {
      allData.tokenRy && connectIM();
      proxy.$modal.msgWarning("视频会商已离线,重新连接中!");
    } else {
      useRongyunStore.SET_online(true);
    }
  }, time);
};

const GetuserInfo = () => {
  console.log("1111111111111");
  getInfo().then((res) => {
    console.log("当前登陆人信息", res);
    localStorage.setItem("userNo", res.data.user.userName);
    allData.phone = res.data.user.phonenumber;
    getQueryToken();
  });
};

// 获取融云token
const getQueryToken = async () => {
  let params = {
    registerThridUserId: allData.phone + "_web",
  };
  let res = await queryToken(params);

  if (res.code == 200) {
    allData.tokenRy = res.data && res.data[0]?.thridToken;

    if (allData.tokenRy) {
      useRongyunStore.SET_haveRYtoken(true);
      getStaus(60000);
      allData.tokenRy && connectIM();
    }
  } else {
    useRongyunStore.SET_haveRYtoken(false);
    useRongyunStore.SET_online(false);
    proxy.$modal.msgWarning("获取通讯token失败");
  }
};
// 获取元素
const getDom = (key) => {
  return document.querySelector(key);
};
const connectEvents = (Events) => {
  /**
   * 正在链接的事件状态
   */
  RongIMLib.addEventListener(Events.CONNECTING, () => {
    console.log("正在链接...");
  });

  /**
   * 链接到服务器会触发这个事件
   */
  RongIMLib.addEventListener(Events.CONNECTED, () => {
    console.log("连接成功");
  });

  /**
   * 手动调用 disconnect 方法或者用户被踢下线 会触发这个事件
   */
  RongIMLib.addEventListener(Events.DISCONNECT, (code) => {
    console.log("连接中断,需要业务层进行重连处理 ->", code);
  });

  /**
   * 链接出问题时,内部进行重新链接,会触发这个事件
   */
  RongIMLib.addEventListener(Events.SUSPEND, (code) => {
    console.log("链接中断,SDK 会尝试重连,业务层无需关心");
    // 5.1.2 版本开始,事件回调中会引起中断的 code 状态码
    console.log(`code -> ${code}`);
  });
};
// IM 实例
const connectIM = () => {
  console.log("初始化connectIM", allData.appkey);
  console.log("初始化connectIM22", allData.navi);
  console.log("初始化connectIM22", allData.tokenRy);
  RongIMLib.init({
    appkey: allData.appkey,
    navigators: [allData.navi],
  });

  initRTC();
  initCall();
  const token = allData.tokenRy;
  RongIMLib.connect(token)
    .then((data) => {
      console.log("*-*-", data);
      // 监听融云状态
      connectEvents(RongIMLib.Events);
      useRongyunStore.SET_online(true);
      proxy.$message.success(`用户 ${data.data.userId} IM 链接成功 ✌🏻`);
    })
    .catch((error) => {
      console.log(error);
      useRongyunStore.SET_online(false);
      proxy.$modal.msgWarning("IM 链接失败,请检查网络后再试");
    });
};
// RTC
const initRTC = () => {
  let rtcClient = RongIMLib.installPlugin(rtcInstaller);
  useRongyunStore.SET_RTC(rtcClient);
};
// Rcall
const initCall = () => {
  console.log("aaaa");
  console.log(callInstaller, "callInstaller");
  console.log("useRongyunStore.rtcClient", useRongyunStore.rtcClient);
  console.log(toRaw(useRongyunStore.rtcClient), "useRongyunStore.rtcClient");
  let callClient = RongIMLib.installPlugin(callInstaller, {
    rtcClient: toRaw(useRongyunStore.rtcClient),
    /**
     * 被动收到邀请 (收到一个远端发起的新会话), 会产生一个新的 session 对象 (必填)
     */

    onSession: (session, extra) => {
      console.log("来电拉来电拉", session, extra);
      allData.conversationType = session.getConversationType();
      allData.remoteUser = session.getRemoteUsers();
      allData.acceptType = session;
      useRongyunStore.SET_CALLSESSION(session);
      useRongyunStore.SET_MediaType(session.getMediaType());
      registerCallSessionEvent(toRaw(useRongyunStore.callSession));
      let callerId = session.getCallerId();
      queryformUserName(callerId);
      GetpromoterThridUserId.value = callerId;
      audio.autoplay = true;
      audio.muted = false;
      audio.loop = true;
      audio.src = successUrl;
      proxy.$modal.msgWarning(`收到 ${session.getCallerId()} 的通话邀请`);
      allData.showTip = true;
      console.log("allData.showTip", allData.showTip);
    },
    /**
     *  以下三条只要满足一条,就会触发onSessionClose
     *  1、本端用户自己主动挂断
     *  2、服务端把本端用户踢出 RTC 房间
     *  3、房间里小于2个人
     *
     *  @param {RCCallSession} session 被结束的 session 对象
     *  @param summaryInfo 结束一个 session 的后汇总信息
     */
    onSessionClose: (session, summaryInfo) => {
      console.log("通话已结束", summaryInfo);
      audio.pause();
      proxy.$modal.msgWarning("通话已结束");
      allData.showTip = false;
      //清除拨号界面的video视图
      bus.emit("removeEle");
      allData.showVideo = false;
    },
  });
  console.log(callClient, "callClient");
  useRongyunStore.SET_CALL(callClient);
};
/**
 * CallSession 事件
 */
const getCallSessionEvent = () => {
  return {
    onRinging: (sender) => {
      proxy.$modal.msgWarning(` ${sender.userId} 振铃`);
    },
    onAccept: (sender) => {
      proxy.$modal.msgWarning(` ${sender.userId} 已接听`);
    },
    onHungup: (sender, reason) => {
      proxy.$modal.msgWarning(` ${sender.userId} 已挂断`);
      const videoViewDom = getDom("#videoViewAPP");
      const videoDom = getDom(`#video-${sender.userId}`);
      videoDom && videoViewDom.removeChild(videoDom);
      const itemdomList = document.getElementsByClassName("video-item");
      if (itemdomList.length <= 1) {
        restore();
        removeVideoEl();
        allData.showVideo = false;
      }
    },
    onTrackReady: (track) => {
      appendVideoEl(track);
      // 暂停
      // 当本端资源或远端资源已获取, 该函数有 2 个参数:track 是本端资源或远端资源, session 是通话实例。这时用户可以用拿到的 track 播放音频、视频。
      // 当本端资源或远端资源已获取, 该函数有 2 个参数:track 是本端资源或远端资源, session 是通话实例。这时用户可以用拿到的 track 播放音频、视频。
      if (!track.isLocalTrack()) {
        //
        audio.pause();
        proxy.$modal.msgWarning("通话已建立");
      }
    },
    onMemberModify: (sender, invitedUsers, session) => {
      console.log("触发邀请监听1111", sender, invitedUsers, session);
      console.log("触发邀请监听1111", allData.userList);

      // 群组通话中有其他人被邀请加入, 该函数有 3 个参数: sender 是发送者,invitedUsers 是被邀请的用户列表, session 是通话实例。这时用户可以在 UI 层提示‘xxx加入通话’。
    },
    onMediaModify: (sender) => {
      // 通话类型改变时触发, 该函数有3个参数: sender 是发送者,mediaType 通话类型, session 是通话实例。这时用户可以在 UI 层提示‘已降级成音频通话’。
    },
    onAudioMuteChange: (muteUser) => {
      // 对方静音后触发, 该函数有2个参数: muteUser 是已静音的用户, session 是通话实例。这时用户可以在 UI 层提示‘xxx已静音’。
      proxy.$modal.msgWarning(` ${muteUser.userId} 已静音`);
    },
    onVideoMuteChange: (muteUser) => {
      // 对方禁用视频后触发, 该函数有2个参数: muteUser 是已禁用视频的用户, session 是通话实例。这时用户可以在 UI 层提示‘xxx已禁用视频’。
      proxy.$modal.msgWarning(` ${muteUser.userId} 已禁用视频`);
    },
  };
};
/**
 * callSession 事件注册
 */
const registerCallSessionEvent = (session) => {
  const events = getCallSessionEvent();
  session.registerSessionListener(events);
};
/**
 * 接听当前 callSession
 */
const accept = () => {
  toRaw(useRongyunStore.callSession)
    .accept()
    .then(({ code }) => {
      if (code === RCCallErrorCode.SUCCESS) {
        proxy.$modal.msgWarning("接听成功");
        allData.showTip = false;
        allData.showVideo = true;
      } else {
        proxy.$modal.msgWarning(`接听失败,错误原因:${code}`);
        hungupApi(code);
      }
    });
};
/**
 * 挂断当前 callSession
 */
const hungup = () => {
  toRaw(useRongyunStore.callSession)
    .hungup()
    .then(({ code }) => {
      if (code === RCCallErrorCode.SUCCESS) {
        // proxy.$modal.msgWarning("挂断成功");
        removeVideoEl();
        restore();
        allData.idList = [];
        allData.showTip = false;
        allData.showVideo = false;
      } else {
        proxy.$modal.msgWarning(`挂断失败,错误原因:${code}`);
        removeVideoEl();
        allData.showTip = false;
        allData.showVideo = false;
        hungupApi(code);
      }
    });
};

// 接听或者挂断失败后都调 融合通讯通话
const hungupApi = (code) => {
  console.log("调取了挂断接口xxxx", GetpromoterThridUserId.value);
  let params = {
    promoterThridUserId: GetpromoterThridUserId.value, //发起人
    answerThridUserId: allData.phone + "_web", //接听人 当前登录人
    updateBy: localStorage.getItem("userNo"),
    answerType: code || null,
  };
  console.log("调取了挂断接口xxxx", params);
  hangUp(params).then((res) => {
    console.log("调取了挂断接口xxxx", res);
  });
};

/**
 * video 视图渲染
 */
const appendVideoEl = async (track) => {
  const container = getDom("#videoViewAPP");
  const uid = track.getUserId();
  let mediaType = toRaw(useRongyunStore.mediaType);
  let videoTpl = null;
  let params = {
    phone: uid.split("_")[0],
  };
  let res = await listrcloudUnitUser(params);
  let data = res.data[0];
  if (res.code == 200) {
    const node = document.createElement("div");
    node.setAttribute("id", `video-${uid}`);
    if (allData.idList.findIndex((i) => i == `video-${uid}`) == -1) {
      allData.idList.push(`video-${uid}`);
    }
    if (mediaType == 1) {
      videoTpl = `<span class="video-user-id">${data.name} :${uid} </span><span class="video-media-type"></span><video id="${uid}"></video>`;
    } else {
      videoTpl = `<span class="video-user-id">${data.name} :${uid} </span><video id="${uid}"></video>`;
    }
    node.innerHTML = videoTpl;
    node.classList.add("video-item");
    let length = allData.remoteUser.length + 1;
    console.log("什么东西", allData.conversationType, length);

    // 根据人数判断渲染不同的视图样式
    if (allData.phone + "_web" == uid && length <= 2) {
      node.classList.add("first-child");
    }

    if (length > 2 && length <= 4) {
      node.classList.add("video-item-4");
    }
    if (length > 4 && length <= 8) {
      node.classList.add("video-item-8");
    }

    if (track.isAudioTrack()) {
      if (mediaType == 1) {
        container.appendChild(node);
      }

      track.play();
    } else {
      container.appendChild(node);
      let videoEl = document.getElementById(uid);
      track.play(videoEl);
    }
  }
};
//关闭视频弹窗
const close = () => {
  // hungup();
};

//还原
const restore = () => {
  allData.styleRY = {
    width: "900px",
    height: "600px",
  };
  const dom1 = getDom("#videoViewAPP");
  if (!dom1) return false;
  dom1.style = "";
  allData.idList.forEach((item, index) => {
    let videodom = getDom(`#${item}`);
    if (videodom) {
      videodom.style = null;
    }

    const titledom = getDom(`#${item} .video-user-id`);
    if (titledom) {
      titledom.style = null;
    }
  });
};

// 通过userPhone匹配用户名称
const queryformUserName = async (callerId) => {
  console.log("callerId匹配用户名称", callerId);

  let params = {
    phone: callerId.split("_")[0],
  };
  let res = await listrcloudUnitUser(params);
  console.log("res获取用户", res);
  if (res && res.code == 200) {
    let name = res.data[0].name;
    allData.fromCalluser = `${name}`;
  }
};
const removeVideoEl = () => {
  if (!getDom("#videoViewAPP")) return false;
  getDom("#videoViewAPP").innerHTML = "";
  getDom("#videoViewAPP").style = "";
};

onBeforeUnmount(() => {
  RongIMLib.disconnect().then(() => console.log("断开链接成功"));
});
</script>
<style lang="scss">
@import "@/views/RongyunCommunication/rongyuncss/index.scss";
</style>
<style lang="scss" scoped>
.rybtn {
  cursor: pointer;
  position: absolute;
  right: 35px;
  top: 22px;
}
</style>