Newer
Older
Nanping_sponge_SJJC / src / components / rongYun / rongyun.vue
@liyingjing liyingjing on 25 Oct 19 KB 数据检测
<template>
  <div id="RongYun">
    <div class="rong-container">
      <div id="rongUser" class="rong-user" v-show="false">
        <span>用户 ID:</span>
        <span id="rongUserId"></span>
      </div>

      <div class="rong-im" v-show="false" id="rongIM">
        <p>请先进行 IM 连接</p>
        <!--appkey-->
        <div class="im-item">
          <label>App Key</label>
          <input
            type="text"
            id="appkey"
            :value="AppKey"
            placeholder="请输入 App Key"
          />
        </div>
        <!--token-->
        <div class="im-item">
          <label>Token</label>
          <input
            type="text"
            id="token"
            :value="tokens"
            placeholder="请输入 Token"
          />
        </div>
        <!--navi-->
        <div class="im-item">
          <label>Navi</label>
          <input type="text" id="navi" placeholder="请输入 Navi 地址" />
          <p>非必填;私有云环境必填</p>
        </div>
        <!--mediaServer-->
        <div class="im-item">
          <label>MediaServer</label>
          <input
            type="text"
            id="mediaServer"
            placeholder="请输入 MediaServer 地址"
          />
          <p>非必填;音视频服务地址</p>
        </div>
        <!--连接-->
        <div class="im-item">
          <button id="DengLuBTN" ref="DengLuBTN" @click="connectIM()">
            连接
          </button>
        </div>
      </div>

      <div class="rong-call" id="rongCall" style="display: none">
        <!--呼叫选项-->
        <div id="callParam" class="call-param">
          <!--选择通话类型-->
          <div class="param-item" v-show="false">
            <label>通话类型</label>
            <select name="" id="callType" @change="callTypeChange()">
              <option value="1">单聊</option>
              <option value="3">群聊</option>
            </select>
            <p>必选</p>
          </div>
          <!--this.mediaType-->
          <div class="param-item" v-show="false">
            <label>媒体类型</label>
            <select name="" id="callMediaType" @change="callMediaTypeChange()">
              <option value="1">音频</option>
              <option value="2">音视频</option>
            </select>
            <p>必选</p>
          </div>
          <!--targetId-->
          <div id="paramPrivate" v-show="false" class="param-item">
            <label>对方 ID</label>
            <input
              id="targetId"
              type="text"
              placeholder="对方 userId"
              v-model="targetIdvalue"
            />
            <p>
              必填;对方的 userId,可通过<a
                target="_blank"
                href="https://developer.rongcloud.cn/"
                >[开发者后台] -> [服务管理] -> [API 调用] -> [用户服务] -> [获取
                token]</a
              >获取,且登录成功
            </p>
          </div>
          <!--targetId-->
          <div id="paramGroupId" class="param-item" style="display: none">
            <label>群组 ID</label>
            <input id="groupId" type="text" value="q1" placeholder="群组 ID" />
            <p>
              必填;可通过
              <a target="_blank" href="https://developer.rongcloud.cn/"
                >[开发者后台] -> [服务管理] -> [API 调用] -> [群组服务] ->
                [加入群组]</a
              >
              加入群组后获取
            </p>
          </div>
          <!--userIds 只有群显示-->
          <div id="paramInvitedIds" class="param-item" style="display: none">
            <label>被邀请者 ID</label>
            <input
              id="userIds"
              type="text"
              placeholder="多个 userId 用英文半角逗号分开"
              :value="UserList"
            />
            <p>
              必填;需加入群后,方可收到邀请。多个 userId 用英文半角逗号分开
            </p>
          </div>
        </div>
        <!--通话视图展示-->
        <div id="videoView" class="video-view"></div>
        <!--通话操作按钮-->
        <div class="opt-btn" id="btn-div">
          <!-- <button id="callBtn"
                  class="btn-call"
                  @click="call()">呼叫</button> -->
          <div id="callBtn" class="btn-call" @click="call()"></div>

          <!-- <button id="acceptBtn"
                  class="btn-accept"
                  @click="accept()">
            接听 -->
          <div id="acceptBtn" class="btn-accept" @click="accept()"></div>

          <div id="hungupBtn" class="btn-hungup" @click="hungup()"></div>
        </div>
      </div>
    </div>
    <div class="toast-wrap">
      <span class="toast-msg"></span>
    </div>
  </div>
</template>
<script>
import { mapGetters } from "vuex";

import { userGetToken } from "@/api/paishuiSys/patrol/patrolMange/wayManage";

import { getUserInfo } from "@/api/system/user";

export default {
  name: "RongYun",
  props: {
    Getphone: {
      type: String,
      default: () => "",
    },
    getmediaType: {
      type: Number,
      default: () => 2,
    },
  },
  data() {
    return {
      targetIdvalue: "13407245473",
      userinfo: {},
      names: "姓名",
      numbs: "XXX",
      AppKey: "25wehl3u2en6w",
      tokens: "",
      DengLuBTN: null,
      value: "",
      UserList: "11,22",
      imClient: "",

      callSession: "",
      callType: RongIMLib.ConversationType.PRIVATE,
      mediaType: RCCall.RCCallMediaType.AUDIO,
      rtcClient: undefined,
      callClient: undefined,

      RCDom: {
        get: (id) => {
          return document.getElementById(id);
        },
        show: (id) => {
          var rongIMDom = document.getElementById(id);
          rongIMDom.setAttribute("style", "display:block;");
        },
        showBlock: (id) => {
          var rongIMDom = document.getElementById(id);
          rongIMDom.setAttribute("style", "display:block;");
        },
        hide: (id) => {
          var rongIMDom = document.getElementById(id);
          rongIMDom.setAttribute("style", "display:none;");
        },
      },
      RCToast: (msg) => {
        setTimeout(function () {
          document
            .getElementsByClassName("toast-wrap")[0]
            .getElementsByClassName("toast-msg")[0].innerHTML = msg;
          var toastTag = document.getElementsByClassName("toast-wrap")[0];
          toastTag.className = toastTag.className.replace("toastAnimate", "");
          setTimeout(function () {
            toastTag.className = toastTag.className + " toastAnimate";
          }, 10);
        }, 10);
      },
      RCCallView: {
        connectedIM: () => {
          // this.RCDom.show("rongUser");
        },
        readyToCall: () => {
          this.RCDom.hide("rongIM");
          this.RCDom.show("rongCall");
        },
        outgoing: () => {
          this.RCDom.hide("callParam");
          this.RCDom.hide("callBtn");
          this.RCDom.show("hungupBtn");
        },
        incomming: () => {
          this.RCDom.hide("callParam");
          this.RCDom.hide("callBtn");
          this.RCDom.show("acceptBtn");
          this.RCDom.show("hungupBtn");
        },
        inTheCall: () => {
          this.RCDom.hide("acceptBtn");
          this.RCDom.hide("callParam");
          this.RCDom.show("hungupBtn");
        },
        end: () => {
          this.RCDom.show("callParam");
          this.RCDom.show("callBtn");
          this.RCDom.hide("acceptBtn");
          this.RCDom.hide("hungupBtn");
        },
      },
    };
  },
  computed: {},
  methods: {
    connectIM() {
      const appkey = this.RCDom.get("appkey").value;
      const token = this.RCDom.get("token").value;
      const navi = this.RCDom.get("navi").value;

      if (!appkey) {
        this.RCToast("请输入 App Key");
        return;
      }
      if (!token) {
        this.RCToast("请输入 Token");
        return;
      }

      // IM 客户端初始化
      this.imClient = RongIMLib.init({
        appkey,
        navigators: navi ? [navi] : undefined,
        logLevel: 1,
      });

      // 初始化 RTC CallLib
      this.initRTC();
      this.initCall();

      this.imClient.watch({
        // 监听 IM 连接状态变化
        status(evt) {
          console.log("connection status change:", evt.status);
        },
      });

      // this.RCToast("正在链接 IM ... ☕️");
      this.imClient
        .connect({ token })
        .then((user) => {
          this.RCCallView.connectedIM();
          this.RCCallView.readyToCall();
          this.RCDom.get("rongUserId").innerText = user.id;
          // this.RCToast(`用户 ${user.id} IM 链接成功 ✌🏻`);
          this.callTypeChange();
          this.callMediaTypeChange();

          setTimeout(() => {
            this.call()
          }, 0);
        })
        .catch((error) => {
          console.log(error);
          this.RCToast("IM 链接失败,请检查网络后再试");
        });
    },
    /**
     * RTC 初始化
     * 在 IM 初始化后进行初始化 (具体位置:im.js)
     */
    initRTC() {
      const mediaServer = this.RCDom.get("mediaServer").value;
      this.rtcClient = this.imClient.install(RCRTC.installer, {
        mediaServer: mediaServer || undefined,
        timeout: 30 * 1000,
        logLevel: window.RCEngine.LogLevel.DEBUG,
      });

      console.log("this.rtcClient", this.rtcClient);
    },

    /**
     * CallLib 初始化
     * 在 IM 初始化后进行初始化 (具体位置:im.js)
     */
    initCall() {
      this.callClient = this.imClient.install(window.RCCall.installer, {
        rtcClient: this.rtcClient,
        onSession: (session) => {
          this.callSession = session;
          this.mediaType = session.getMediaType();
          this.registerCallSessionEvent(this.callSession);
          this.RCToast(`收到 ${session.getCallerId()} 的通话邀请`);
          // this.RCCallView.incomming();
        },
        onSessionClose: (session, summary) => {
          this.RCToast("通话已结束");
          this.RCCallView.end();
          this.removeVideoEl();
        },
      });

      console.log("this.callClient", this.callClient);
    },

    /**
     * 通话类型监听
     */
    callTypeChange() {
     
      const callTypeDom = this.RCDom.get("callType");
      this.callType = Number(callTypeDom.value);
      if (this.callType === RongIMLib.ConversationType.GROUP) {
        this.RCDom.showBlock("paramGroupId");
        this.RCDom.showBlock("paramInvitedIds");
        this.RCDom.hide("paramPrivate");
      } else {
        this.RCDom.hide("paramGroupId");
        this.RCDom.hide("paramInvitedIds");
        // this.RCDom.showBlock("paramPrivate");
      }
      // // 默认多人通话
      // this.RCDom.showBlock("paramGroupId");
      // this.RCDom.showBlock("paramInvitedIds");
      // this.RCDom.hide("paramPrivate");
    },

    /**
     * 媒体类型监听
     */
    callMediaTypeChange() {
    
      const mediaTypeDom = this.RCDom.get("callMediaType");
      this.mediaType = Number(mediaTypeDom.value);
      // this.mediaType = 2;
    },

    /**
     * CallSession 事件
     */
    getCallSessionEvent() {
      return {
        onRinging: (sender) => {
          // 当远端用户已开始响铃, 该函数有 2 个参数: sender 是发送者,session 是通话实例。这时用户可以在业务层做响铃的 UI 展示。
          this.RCToast(`收到 ${sender.userId} 振铃`);
          console.log(`收到 ${sender.userId} 振铃`);
          // message.info(`收到 ${sender.userId} 振铃`);
        },
        onAccept: (sender) => {
          // 当远端用户已同意接听, 该函数有 2 个参数: sender 是发送者,session 是通话实例。这时用户可以把 UI 的‘响铃’变成‘通话中’。
          this.RCToast(`${sender.userId} 已接听`);
        },
        onHungup: (sender) => {
          // 当有远端用户挂断, 该函数有 3 个参数: sender 是发送者,reason 是挂断原因,session 是通话实例。这时用户可以在 UI 层提示‘xxx已挂断’。
          this.RCToast(`${sender.userId} 已挂断`);
          // 群组中移除相应节点
          const videoViewDom = this.RCDom.get("videoView");
          const videoDom = this.RCDom.get(`video-${sender.userId}`);
          videoDom && videoViewDom.removeChild(videoDom);
        },
        onTrackReady: (track) => {
          // 当本端资源或远端资源已获取, 该函数有 2 个参数:track 是本端资源或远端资源, session 是通话实例。这时用户可以用拿到的 track 播放音频、视频。
          this.appendVideoEl(track);
          if (!track.isLocalTrack()) {
            this.RCToast("通话已建立");
            this.RCCallView.inTheCall();
          }
        },
        onMemberModify: (sender, invitedUsers) => {
          // 群组通话中有其他人被邀请加入, 该函数有 3 个参数: sender 是发送者,invitedUsers 是被邀请的用户列表, session 是通话实例。这时用户可以在 UI 层提示‘xxx加入通话’。
        },
        onMediaModify: (sender) => {
          // 通话类型改变时触发, 该函数有3个参数: sender 是发送者,mediaType 通话类型, session 是通话实例。这时用户可以在 UI 层提示‘已降级成音频通话’。
        },
        onAudioMuteChange: (muteUser) => {
          // 对方静音后触发, 该函数有2个参数: muteUser 是已静音的用户, session 是通话实例。这时用户可以在 UI 层提示‘xxx已静音’。
        },
        onVideoMuteChange: (muteUser) => {
          // 对方禁用视频后触发, 该函数有2个参数: muteUser 是已禁用视频的用户, session 是通话实例。这时用户可以在 UI 层提示‘xxx已禁用视频’。
        },
      };
    },

    /**
     * callSession 事件注册
     */
    registerCallSessionEvent(session) {
      const events = this.getCallSessionEvent();
      session.registerSessionListener(events);
    },

    /**
     * callSession 呼叫
     */
    call() {
      this.mediaType = this.getmediaType;

      console.log("this.getmediaType", this.getmediaType);

      const events = this.getCallSessionEvent();
      const isPrivateCall =
        this.callType === RongIMLib.ConversationType.PRIVATE;
      const params = {
        targetId: this.RCDom.get(`${isPrivateCall ? "targetId" : "groupId"}`)
          .value,
        mediaType: this.mediaType,
        listener: events,
      };
      if (isPrivateCall) {
        if (!this.RCDom.get("targetId").value) {
          this.RCToast("请输入对方 ID");
          return;
        }
        this.privateCall(params);
      } else {
        if (!this.RCDom.get("groupId").value) {
          this.RCToast("请输入群组 ID");
          return;
        }
        if (!this.RCDom.get("userIds").value) {
          this.RCToast("请输入被邀请者 ID");
          return;
        }
        this.groupCall(params);
      }
    },

    /**
     * 单呼
     */
    privateCall(params) {
      this.callClient.call(params).then(({ code, session }) => {

        console.log(code, session);
        if (code === RCCall.RCCallErrorCode.SUCCESS) {
          this.registerCallSessionEvent(session);
          this.callSession = session;
          this.RCCallView.outgoing();
        } else {
          this.RCToast(`呼叫失败,错误原因:${code}`);
        }
      });
    },

    /**
     * 群呼
     */
    groupCall(params) {
      params.userIds = (this.RCDom.get("userIds").value || []).split(",");
      this.callClient.callInGroup(params).then(({ code, session }) => {
        if (code === RCCall.RCCallErrorCode.SUCCESS) {
          this.registerCallSessionEvent(session);
          this.callSession = session;
          this.RCCallView.outgoing();
        } else {
          const reason =
            code === RCCall.RCCallErrorCode.NOT_IN_GROUP
              ? "当前用户未加入群组"
              : code;
          this.RCToast(`呼叫失败,错误原因:${reason}`);
          this.removeVideoEl();
        }
      });
    },

    /**
     * 接听当前 callSession
     */
    accept() {
      this.callSession.accept().then(({ code }) => {
        if (code === RCCall.RCCallErrorCode.SUCCESS) {
          this.RCToast("接听成功");
        } else {
          this.RCToast(`接听失败,错误原因:${code}`);
        }
      });
    },

    /**
     * 挂断当前 callSession
     */
    hungup() {
      if (this.callSession) {
        this.callSession.hungup().then(({ code }) => {
          if (code === RCCall.RCCallErrorCode.SUCCESS) {
            this.RCToast("挂断成功");
            this.bus.$emit("closeFX");
          } else {
            this.RCToast(`挂断失败,错误原因:${code}`);
          }
        });
      }
    },

    /**
     * video 视图渲染
     */
    appendVideoEl(track) {
      console.log(track);
      const container = this.RCDom.get("videoView");
      if (track.isAudioTrack()) {
        const uid = track.getUserId();
        const node = document.createElement("div");
        node.setAttribute("id", `video-${uid}`);
        const videoTpl = `<span class="video-user-id">ID: ${uid}</span>
      <span class="video-media-type">${this.mediaType === 1 ? "音频" : ""}</span>
      <video id="${uid}"></video>`;
        //   const videoTpl = `<span class="video-user-id">${uid}</span>
        // <span class="video-media-type">${this.mediaType === 1 ? "音频" : ""}</span>
        // <video id="${uid}"></video>`;
        node.innerHTML = videoTpl;
        node.classList = "video-item";

        const rongCall = document.getElementById("rongCall");
        const btndiv = document.getElementById("btn-div");

        container.appendChild(node);
        // rongCall.insertBefore(node, btndiv);

        track.play();
      } else {
        const videoEl = this.RCDom.get(track.getUserId());
        track.play(videoEl);
      }
    },

    /**
     * 通话结束后,清除所有 video 标签
     */
    removeVideoEl() {
      this.RCDom.get("videoView").innerHTML = "";
    },

    // GetuserInfo 获取用户信息
    GetuserInfo() {
      getUserInfo().then((res) => {
        console.log(res);
        this.userinfo = res.data.data;
        console.log(this.userinfo);

        this.numbs = res.data.data.phone;
        this.names = res.data.data.name;

        this.$nextTick(() => {
          this.Dengl();
        });
      });
    },

    // 默认登录,获取当前电脑用户PCUser的通话token
    Dengl() {
      userGetToken(`userId=${this.numbs}&name=${this.names}`).then((res) => {
        console.log(res);
        if (res.data.code == 200) {
          console.log("res.data.token", res.data.token);
          this.tokens = res.data.token;

          this.$nextTick(() => {
            this.connectIM();
          });
        }
      });
    },
  },
  // computed: {
  //   ...mapGetters([
  //     "userInfo",
  //   ]),
  // },
  watch: {
    Getphone: {
      handler(val) {
        console.log(val);
        if (val) {
          this.targetIdvalue = val;
        }
      },
      // immediate: true
    },
  },
  mounted() {
    this.GetuserInfo();
  },
  beforeDestroy() {
    this.hungup();
  },
};
</script>
<style lang="scss" scoped>
@import "./rongyun.css";
#RongYun {
  width: 100%;
  height: 100%;
}

.rong-call input {
  color: #000 !important;
}

input:-internal-autofill-selected {
  -webkit-text-fill-color: #000 !important;
}
</style>