融云相关代码

本文档介绍了如何在Vue.js项目中集成融云SDK,实现本地调试、设置跨域、配置AppKey和Token,以及创建和管理音视频通话。涉及到的关键步骤包括设置Vue.config.js的代理、封装API获取Token、处理融云弹框样式和JavaScript逻辑,以及处理各种通话状态变化。此外,还展示了HTML和CSS代码用于UI布局和样式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

其实重点不是单页面代码
注意点:本地调试的时候记得localhost调试哦 IP拨打电话会报错误

然后就是引入的html三个固定的版本js

  <!-- 融云相关 -->
  <script src="https://cdn.ronghub.com/RongIMLib-4.5.latest.js"></script>
  <script src="https://cdn.ronghub.com/RCRTC-5.2.latest.js"></script>
  <script src="https://cdn.ronghub.com/RCCall-5.0.latest.js"></script>
  
然后JS样式就自己写一下咯

融云服务提供的
AppKey: '提供的',
AppSecret: '提供的',

在vue.config里面配置一下转发
  "/RongYunsAPI": {
        target: "https://api-cn.ronghub.com",
        changeOrigin: true,
        pathRewrite: {
          '^/RongYunsAPI': '' //需要rewrite重写的,
        }
      },

axios请求头配置
      
   if (config.url.includes('RongYunsAPI')) {
      let NonceV = Math.floor(Math.random() * 10)
      let TimestampV = +new Date()
      let SignatureV = 'AppSecret' + NonceV + TimestampV
      config.headers["App-Key"] = 'AppKey'
      config.headers["Nonce"] = NonceV
      config.headers["Timestamp"] = TimestampV
      config.headers["Signature"] = sha1(SignatureV)
    }


这一步其实是在融云管网获取key 然后我们省略内置前端跨域去解决这个问题
其实这一步是需要后端去转发成接口比较好
自己封装一下获得token
export const userGetToken = (params) => {
    return request({
        url: `/RongYunsAPI/user/getToken.json`,
        method: "post",
        data: params
    });
};
      <!-- 融云弹框 -->
      <div class="RYdia"
           v-show="rongyuntype&&TitleIndex!=4&&TitleIndex!=5">
        <div class="closeBtn"
             @click="rongyuntype=false">X</div>
        <RongYunPage v-if="rongyuntype"
                     :Getphone='GetFXphone'
                     :getmediaType='getmediaType'
                     :RYtype='RYtype'></RongYunPage>
      </div>

.RYdia {
  position: absolute;
  padding-top: 20px;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  z-index: 4;
  background: #0b0c0b;
  border-radius: 5px;
}

.closeBtn {
  position: absolute;
  cursor: pointer;
  width: 40px;
  height: 40px;
  line-height: 40px;
  right: 0px;
  top: 0px;
  color: #fff;
  text-align: center;
}

<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 { userGetToken } from "@/services";
// import configs from "@/config.js";
import {
  userGetToken
} from "@/api/floodControlDrainage/floodControlDrainage.js";

import { mapGetters } from "vuex";

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


export default {
  name: "RongYun",
  props: {
    Getphone: {
      type: String,
      default: () => ""
    },
    RYtype: {
      type: String,
      default: () => ""
    },
    getmediaType: {
      type: Number,
      default: () => 1
    }
  },
  data () {
    return {
      targetIdvalue: '',
      userinfo: {},
      names: '姓名',
      numbs: 'XXX',
      AppKey: 'AppKey',
      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 () {
      // debugger;
      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 () {
      // debugger;
      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} 振铃`);
          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) {
      console.log(this.callClient, params, "this.callClient");
      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}`);
          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("挂断成功");

            if (this.RYtype == 'FX') {
              this.bus.$emit('closeFX')
            }
          } else {
            this.RCToast(`挂断失败,错误原因:${code}`);
          }
        });
      }

    },

    /**
     * video 视图渲染
     */
    appendVideoEl (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">${uid}</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 => {
        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) {
        if (val) {
          this.targetIdvalue = val
        }
      },
      immediate: true
    }
  },
  mounted () {
    this.GetuserInfo()
  },
  beforeDestroy () {
    this.hungup()
  }
};
</script>
<style lang="less" scoped>
@import "./css/style.css";
#RongYun {
  width: 100%;
  height: 100%;
}

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

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

下面是基本的CSS样式 可以自己写

html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
}
a:link {color: #2da2ea} /* 未被访问的链接 蓝色 */
a:visited {color: #2da2ea} /* 已被访问过的链接 蓝色 */
a:hover {color: #2da2ea} /* 鼠标悬浮在上的链接 蓝色 */
a:active {color: #2da2ea} /* 鼠标点中激活链接 蓝色 */

#RongYun {
  border-radius: 5px;
}

.rong-container {
  background: #0b0c0b;
  min-height: 100%;
  color: #FFF;
  font-size: 18px;
  width: 350px;
}
.rong-container .rong-title {
  margin: 0;
  padding: 25px 0 10px;
  text-align: center;
  color: #fff;
  font-size: 30px;
}
.rong-container .rong-user {
  display: none;
  text-align: center;
}
.rong-container button {
  width: 150px;
  height: 30px;
  border-radius: 2px;
  background: #2da2ea;
  border: none;
  color: #fff;
  box-shadow: 1px 1px 6px #00000069;
  cursor: pointer;
}
.rong-container button:active {
  width: 150px;
  height: 30px;
  border-radius: 2px;
  background: #0f93e4;
  border: none;
  color: #fff;
  box-shadow: 1px 1px 6px #00000069;
  cursor: pointer;
  /* opacity: .8; */
}
.rong-container .rong-im {
  background: #0b0c0b;
  width: 850px;
  border-radius: 2px;
  display: inline-block;
}
.rong-container .rong-im .im-item {
  text-align: center;
  margin-bottom: 10px;
  height: 50px;
  position: relative;
}
.rong-container .rong-im .im-tips {
  width: 100px;
}
.rong-container .rong-im .im-item label {
  display: inline-block;
  width: 150px;
  text-align: right;
}
.rong-container .rong-im .im-item input {
  border: 1px solid #ccc;
  border-radius: 2px;
  height: 25px;
  width: 600px;
}
.rong-container .rong-im .im-item p {
  margin: 0px;
  display: inline-block;
  position: absolute;
  left: 200px;
  top: 30px;
  color: #fff;
  font-size: 13px;
}
.rong-container .rong-call {
  text-align: center;
  margin-bottom: 10px;
}
.rong-container .rong-call .call-param {
  /* padding: 10px; */
  background: #0b0c0b;
  width: 650px;
  border-radius: 2px;
  display: inline-block;
}
.rong-container .rong-call select {
  background: #4285F4;
  width: 450px;
  height: 30px;
  border-radius: 2px;
  border: none;
  color: #fff;
  text-align: center;
}

.rong-container .rong-call label {
  display: inline-block;
  width: 150px;
  text-align: right;
}
.rong-container .rong-call input {
  border: 1px solid #ccc;
  border-radius: 2px;
  height: 25px;
  width: 450px;
}

.rong-container .rong-call .call-item,
.rong-container .rong-call .call-param,
.rong-container .rong-call .opt-btn {
  background: #0b0c0b;
  margin-bottom: 10px;
}
.rong-container .rong-call .opt-btn {
  margin-bottom: 10px;
  display: flex;
 justify-content: center;
}

.rong-container .rong-call .call-param .param-item {
  margin-bottom: 15px;
}

.rong-container .rong-call .call-param .param-item {
  height: 50px;
  position: relative;
}
.rong-container .rong-call .call-param .param-item p {
  margin: 0px;
  display: inline-block;
  position: absolute;
  left: 180px;
  top: 30px;
  color: #fff;
  font-size: 13px;
  text-align: left;
}
.rong-container .rong-call .opt-btn .btn-accept, .rong-container .rong-call .opt-btn .btn-hungup {
  display: none;
}

.rong-container .rong-call .video-view .video-item {
  width: 320px;
  height: 240px;
  /* background: #1a7cb9; */
  position: relative;
  border-radius: 2px;
  display: inline-block;
  margin: 8px;
}

.rong-container .rong-call .video-view {
  /* display: flex; */
}


.rong-container .rong-call .video-view .video-item .video-user-id {
  /* background: #a8d8ea9c; */
  position: absolute;
  left: 2px;
  top: -20px;
  /* left: 2px; */
  /* left: 50%; */
  /* top: 50%; */
  /* transform: translate(-50%,-50%); */
  display: inline-block;
  padding: 0 5px;
  border-radius: 2px;
}
.rong-container .rong-call .video-view .video-item .video-media-type {
  position: absolute;
  top: 41%;
  right: 42%;
}
.rong-container .rong-call .video-view video {
  width: 320px;
  height: 240px;
  border-radius: 2px;
}


/* toast */
.toast-wrap {
  display: inline-block;
  opacity: 0;
  position: fixed;
  top: -30px;
  color: #fff;
  width: 100%;
  text-align: center;
}
.toast-msg {
  background-color: rgba(89, 148, 236, 0.918);
  border-radius: 2px;
  padding: 10px 15px;
}
.toastAnimate {
  animation: toastKF 2s;
}
@keyframes toastKF {
  0%   {opacity: 0;}
  25%  {opacity: 1; z-index: 9999}
  50%  {opacity: 1; z-index: 9999}
  75%  {opacity: 1; z-index: 9999}
  100% {opacity: 0; z-index: 0}
}

.btn-hungup {
  cursor: pointer;
  width: 32px;
  height: 32px;
  background: url("~@/assets/images/siping-fangxun/call-off.png") no-repeat;;
  background-size: 100% 100%;
}

.btn-call,
.btn-accept {
  cursor: pointer;
  width: 32px;
  height: 32px;
  background: url("~@/assets/images/siping-fangxun/call.png") no-repeat;;
  background-size: 100% 100%;
}

.btn-hungup:hover,
.btn-call:hover,
.btn-accept{
  opacity: 0.7;
}



#videoView {
  border-radius: 5px;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值