Newer
Older
DH_Apicture / src / views / RongyunCommunication / RongYunBox / index.vue
@ZZJ ZZJ 28 days ago 25 KB 更新融云样式
<template>
  <div class="RongYun" id="RongYun">
    <div class="rong-container" id="rongContainer">
      <div class="rong-action" id="rong-action">
        <div class="textDiv2">
          <div class="textTitle">
            <span class="dote"></span>
            <span>接收用户:</span>
          </div>
          <div class="userList" v-if="allData.userList.length > 0">
            <template v-for="(item, index) in allData.userList" :key="index">
              <div class="user" v-if="item.phone != userId">
                <div class="userInfoClass">
                  <span class="username">{{ item.name }}:</span>
                  <div class="ceninfoBox">
                    <div class="userphone" v-if="item.phone">
                      {{ geTel(item.phone) }}
                    </div>
                    <div class="userphone userdept">{{ item.deptName }}</div>
                  </div>
                </div>
                <div>
                  <span style="margin-left: 10px" :class="'classType' + item.ClassType">{{ item.typeFont }}</span>
                </div>
              </div>
            </template>
          </div>
        </div>
        <div class="textDiv">
          <span class="dote"></span>
          <div class="text">
            <span>发起人:</span><span class="Rightvalue" @click="getToken()">{{ userinfo.userName }}</span>
          </div>
        </div>
        <div class="textDiv">
          <span class="dote"></span>
          <div class="text">
            <span>当前登录用户 ID:</span><span id="userId" class="Rightvalue" @click="getToken()">{{ userId + '_web' }}</span>
          </div>
        </div>

        <div class="textDiv">
          <span class="dote"></span>
          <div class="text">
            <span>通话类型:</span>

            <el-radio-group
              v-model="mediaType"
              style="display: flex; justify-content: center; align-items: center"
              @change="changeMediaType"
            >
              <el-radio :label="2">视频</el-radio>
              <el-radio :label="1">语音</el-radio>
            </el-radio-group>
          </div>
        </div>
        <div id="inviteList" class="textDiv">
          <span class="dote"></span>
          <div class="text">
            <span>选择邀请人:</span>

            <el-select
              v-model="Getidinvite"
              placeholder="选择被邀请人"
              filterable
              multiple
              collapse-tags
              :popper-append-to-body="true"
              popper-class="eloption"
            >
              <el-option v-for="dict in inviteuserIdsList" :key="dict.id" :label="dict.name" :value="dict.id"></el-option>
            </el-select>
          </div>
        </div>
        <div class="rong-login-box">
          <div class="btn callBtn" id="call" @click="callHandler()">
            <img src="/src/assets/images/rongYunImg/callic.png" alt="" />
            发起通话
          </div>
          <div class="btn hunupBtn hangBtn" id="hunup" @click="hungup()">
            <img src="/src/assets/images/rongYunImg/hangic.png" alt="" />
            挂断
          </div>
          <div class="btn inviteBtn hunupBtn" id="invite" @click="inviteCall()">邀请</div>
        </div>
      </div>
      <div id="videoView" class="rong-video-box newbox"></div>
    </div>
  </div>
</template>
<script setup>
import moment from 'moment';
import useUserStore from '@/store/modules/user';
import { ElMessageBox } from 'element-plus';

import bus from '@/utils/util';
import rongyunStore from '@/store/modules/rongyunStore';
import {
  listrcloudUnitUser,
  getUserStatus,
  rongyunGroupSave,
  groupJoinUsers,
  batchAdd,
  answer,
  hangUp,
} from '@/views/RongyunCommunication/rongyunjs/rongyunApi.js';
import { findCurrentTreeObj } from '@/utils/ruoyi';

import { RCCallErrorCode } from '@rongcloud/plugin-call';

const appStore = useUserStore();
const useRongyunStore = rongyunStore();
const { proxy } = getCurrentInstance();
const inviteuserIdsList = ref([]); //被邀请人的列表
const Getidinvite = ref([]);
const allData = reactive({
  typeList: [
    {
      label: '视频',
      value: 2,
    },
    {
      label: '语音',
      value: 1,
    },
  ],
  userId: appStore.userInfo.phonenumber,
  userName: '',
  mediaType: useRongyunStore.mediaType,
  userList: [],
  idList: [],
  userinfo: appStore.userInfo,
  unitArr: [],
});
const { typeList, userId, userName, mediaType, userList, idList, userinfo, unitArr } = toRefs(allData);
const props = defineProps({
  ryUser: Object,
  callType: Number,
});

const paramSave = ref({
  groupId: undefined, //群聊Id
  promoterThridUserId: appStore.userInfo.phonenumber + '_web', //发起人id
  answerThridUserIds: '', //接收人id
  type: '', //通话类型  1是视频 2是语音
  createBy: localStorage.getItem('userNo'),
});

onMounted(() => {
  nextTick(() => {
    initGroupData();
  });
  bus.on('removeEle', e => {
    removeVideoEl();
  });
});

onBeforeUnmount(() => {
  close();
});
const geTel = tel => {
  var reg = /^(\d{3})\d{4}(\d{4})$/;
  return tel.replace(reg, '$1****$2');
};

// 处理群呼数据
const initGroupData = () => {
  console.log('props.ryUser 处理群呼/单呼数据', props.ryUser);
  allData.userList = [];
  if (props.callType == 2) {
    let arr = [].concat(props.ryUser.userList);
    arr.forEach(v => {
      allData.userList.push({
        name: v.name,
        phone: v.registerThridUserId,
        typeFont: null,
        ClassType: null,
      });
    });
  } else {
    allData.userList.push({
      name: props.ryUser.name,
      phone: props.ryUser.phone,
      typeFont: null,
      ClassType: null,
    });
  }
  console.log('allData.userList', allData.userList);
};

const getDom = key => {
  return document.querySelector(key);
};
const changeMediaType = value => {
  console.log('value', value);
  useRongyunStore.SET_MediaType(value);
};
/**
 * CallSession 事件
 */
const getCallSessionEvent = () => {
  return {
    onRinging: sender => {
      // 当远端用户已开始响铃, 该函数有 2 个参数: sender 是发送者,session 是通话实例。这时用户可以在业务层做响铃的 UI 展示。
      // ;
      proxy.$modal.msgWarning(` ${sender.userId} 振铃`);
      allData.userList.forEach(element => {
        if (element.phone == sender.userId) {
          element.typeFont = '对方已响铃';
          element.ClassType = 1;
        }
      });
    },
    onAccept: sender => {
      // 当远端用户已同意接听, 该函数有 2 个参数: sender 是发送者,session 是通话实例。这时用户可以把 UI 的‘响铃’变成‘通话中’。
      proxy.$modal.msgWarning(` ${sender.userId} 已接听`);
      console.log('接听监听,', allData.userList, sender);
      allData.userList.forEach(element => {
        if (element.phone == sender.userId) {
          element.typeFont = '已接听';
          element.ClassType = 2;
          element.answerType = 4;
          acceptApi(element);
        }
      });
    },
    onHungup: (sender, reason) => {
      // 当有远端用户挂断, 该函数有 3 个参数: sender 是发送者,reason 是挂断原因,session 是通话实例。这时用户可以在 UI 层提示‘xxx已挂断’。
      proxy.$modal.msgWarning(` ${sender.userId} 已挂断`);
      console.log('挂断监听,', allData.userList, sender);
      console.log('挂断监听挂断原因,', reason);

      allData.userList.forEach(element => {
        if (element.phone == sender.userId) {
          element.typeFont = '已挂断';
          element.answerType = reason;
          // 挂断原因转义成后端所需字段
          //  1.未响铃  2.响铃未接听 3.响铃后挂断 4.已接听

          // 响铃后挂断
          // if (reason == 12) {
          //   element.answerType = 3;
          // }

          // // 响铃未接听
          // if (reason == 15) {
          //   element.answerType = 2;
          // }

          // // 已接听
          // if (reason == 13) {
          //   element.answerType = 4;
          // }

          hungupApi(element);
        }
      });
      // 群组中移除相应节点
      const videoViewDom = getDom('#videoView');
      const videoDom = getDom(`#video-${sender.userId}`);
      videoDom && videoViewDom.removeChild(videoDom);
      const itemdomList = document.getElementsByClassName('video-item');
      if (itemdomList.length <= 1) {
        restore();
      }
    },
    onTrackReady: track => {
      // 当本端资源或远端资源已获取, 该函数有 2 个参数:track 是本端资源或远端资源, session 是通话实例。这时用户可以用拿到的 track 播放音频、视频。
      setTimeout(() => {
        appendVideoEl(track);
      }, 1500);
      // 当本端资源或远端资源已获取, 该函数有 2 个参数:track 是本端资源或远端资源, session 是通话实例。这时用户可以用拿到的 track 播放音频、视频。
      if (!track.isLocalTrack()) {
        proxy.$modal.msgWarning('通话已建立');
      }
    },
    onMemberModify: (sender, invitedUsers, session) => {
      console.log('触发邀请监听', sender, invitedUsers, session);
      console.log('触发邀请监听', 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(` ${sender.userId} 已静音`);
    },
    onVideoMuteChange: muteUser => {
      // 对方禁用视频后触发, 该函数有2个参数: muteUser 是已禁用视频的用户, session 是通话实例。这时用户可以在 UI 层提示‘xxx已禁用视频’。
      proxy.$modal.msgWarning(` ${sender.userId} 已禁用视频`);
    },
  };
};
/**
 * callSession 事件注册
 */
const registerCallSessionEvent = session => {
  const events = getCallSessionEvent();
  session.registerSessionListener(events);
};
const callHandler = () => {
  console.log('..??', props);
  props.callType == 1 ? rongYunCall() : groupCall();
};
// 单呼
const call = () => {
  getDom('#call').style.display = 'none';
  getDom('#hunup').style.display = 'block';
  const events = getCallSessionEvent();
  console.log('props.ryUser', props.ryUser);
  console.log('props.ryUser.phone2', props.ryUser.phone);
  // 这里是传给融云拨打电话的传递userid
  const params = {
    targetId: props.ryUser.phone,
    mediaType: useRongyunStore.mediaType,
    listener: events,
  };
  useRongyunStore.callClient.call(params).then(({ code, session }) => {
    if (code === 10000) {
      registerCallSessionEvent(session);
      useRongyunStore.SET_CALLSESSION(session);

      saveOnAccept();
    } else {
      proxy.$modal.msgWarning(`呼叫失败,错误原因:${code}`);
    }
  });
};
//单呼前判登录用户在线状态
const rongYunCall = async item => {
  console.log('allData.userId', allData.userId, appStore.userInfo);
  let params = {
    registerThridUserId: allData.userId + '_web',
  };

  let res1 = await getUserStatus(params);
  let flag1 = null;
  if (res1.code == 200) {
    flag1 = JSON.parse(res1.data);
  }
  if (flag1 != 1) {
    ElMessageBox.confirm(`${appStore.userInfo.userName || '当前'}用户视频会商不在线,是否重新连接?, "提示"`, {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning',
    })
      .then(() => {
        setTimeout(() => {
          bus.emit('rystatus');
          getCallStatus();
        }, 1500);
      })
      .catch(() => {});
  } else {
    setTimeout(() => {
      getCallStatus();
    }, 1500);
  }
};
//单呼前判对方用户在线状态
const getCallStatus = async () => {
  let params = {
    registerThridUserId: props.ryUser.phone,
  };

  let res = await getUserStatus(params);
  let flag = null;
  if (res.code == 200) {
    flag = JSON.parse(res.data);
  }
  if (flag != 1) {
    return proxy.$modal.msgWarning(`${props.ryUser.name}用户视频会商不在线!`);
  } else {
    call();
  }
};
//群呼
const groupCall = () => {
  getDom('#call').style.display = 'none';
  getDom('#hunup').style.display = 'block';
  getDom('#invite').style.display = 'block';
  getDom('#inviteList').style.visibility = 'visible';

  console.log('allData.userList', allData.userList, props.ryUser);
  allData.userList.forEach(v => {
    v.typeFont = '已拨号';
    v.ClassType = 0;
    v.answerType = 1;
  });

  const events = getCallSessionEvent();
  const params = {
    targetId: props.ryUser.groupId,
    userIds: props.ryUser.userIds.split(','),
    mediaType: useRongyunStore.mediaType,
    listener: events,
  };
  console.log('param', params);
  useRongyunStore.callClient.callInGroup(params).then(({ code, session }) => {
    if (code === 10000) {
      registerCallSessionEvent(session);
      useRongyunStore.SET_CALLSESSION(session);
      saveOnAccept();
      GetallOnline();
    } else {
      const reason = code === RCCallErrorCode.NOT_IN_GROUP ? '当前用户未加入群组' : code;
      proxy.$modal.msgWarning(`呼叫失败,错误原因:${code}`);
      removeVideoEl();
    }
  });
};
let endids = ref([]);

// 邀请用户加入当前通话(仅限群组)
const inviteCall = () => {
  if (Getidinvite.value && Getidinvite.value.length) {
    console.log('点击了邀请', Getidinvite.value, inviteuserIdsList.value);
    let ids = [];
    let GetuserList = [];
    Getidinvite.value.map(item => {
      inviteuserIdsList.value.map(p => {
        if (item == p.id) {
          GetuserList.push(p);
        }
      });
    });
    console.log('点击了邀请', GetuserList);

    GetuserList.map(item => {
      item.userTokenList.length &&
        item.userTokenList.map(p => {
          if (p.isOnlion) {
            ids.push(p.registerThridUserId);
          }
        });
    });

    endids.value = ids;

    let params = {
      groupId: props.ryUser.groupId,
      ids: ids.join(','),
    };
    groupJoinUsers(params).then(res => {
      console.log(res);

      console.log('点击了邀请', ids);
      useRongyunStore.callSession.invite(ids).then(({ code }) => {
        console.log(code);
        if (code === 10000) {
          proxy.$modal.msgSuccess(`邀请成功`);
        } else {
          proxy.$modal.msgWarning(`邀请失败,错误原因:${code}`);
        }
      });
    });
  } else {
    proxy.$modal.msgWarning(`请选择邀请人`);
  }
};

// 批量新增融合通讯通话
const saveOnAccept = () => {
  console.log('批量新增', props.ryUser);
  paramSave.value.type = useRongyunStore.mediaType;
  paramSave.value.groupId = props.callType == 1 ? -1 : props.ryUser.groupId;
  paramSave.value.answerThridUserIds = props.ryUser.phone || props.ryUser.userIds;
  //接听人单呼就是phone userIds 两个  数据不一样

  console.log('paramSave.value', paramSave.value, props.ryUser);

  batchAdd(paramSave.value).then(res => {
    if (res.code == 200) {
      console.log('批量新增融合通讯通话');
    }
  });
};

// 接听后端接口
const acceptApi = item => {
  console.log('调取了接听接口', item);

  let params = {
    promoterThridUserId: appStore.userInfo.phonenumber + '_web', //发起人 当前登陆人
    answerThridUserId: item.phone, //接听人
    updateBy: localStorage.getItem('userNo'), //当前登录用户
  };
  answer(params).then(res => {
    console.log('调取了接听接口', res);
  });
};

// 挂断融合通讯通话
const hungupApi = item => {
  console.log('调取了挂断接口', item);
  let params = {
    promoterThridUserId: appStore.userInfo.phonenumber + '_web', //发起人
    answerThridUserId: item.phone, //接听人
    updateBy: localStorage.getItem('userNo'),
    answerType: item.answerType || null,
  };

  hangUp(params).then(res => {
    console.log('调取了挂断接口', res);
  });
};

// 获取所有注册用户
const GetallOnline = item => {
  inviteuserIdsList.value = [];
  console.log('被邀请人', props.ryUser);
  // let havaUser = [];

  // props.ryUser.userIds.map(item => {
  //   havaUser.push(item.split('_')[0]);
  // });

  // console.log('被邀请人', havaUser);

  listrcloudUnitUser().then(res => {
    res.data.map(item => {
      if (item.isOnlion && !props.ryUser.userIds.includes(item.phone)) {
        inviteuserIdsList.value.push(item);
      }
    });
    console.log('被邀请人', inviteuserIdsList.value, props.ryUser.userIds);
  });
};

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

    let length = allData.userList.length + endids.value.length;
    console.log('什么东西xxxxx', allData.userId, uid, props.callType, length);

    // 根据人数判断渲染不同的视图样式
    if (allData.userId + '_web' == uid && length <= 2) {
      // 判断是当前用户 人数小于等于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);
      const videoEl = document.getElementById(`${track.getUserId()}`);
      track.play(videoEl);
    }
    const targetElements = document.querySelectorAll('.video-item');
    console.log('targetElements', targetElements);

    targetElements.forEach(target => {
      target.classList.remove('video-item-4');
      target.classList.remove('video-item-8');

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

/**
 * 挂断当前 callSession
 */
const hungup = () => {
  // console.log("1231------------------------", useRongyunStore.callSession);
  useRongyunStore.callSession.hungup().then(({ code }) => {
    if (code === 10000) {
      // proxy.$modal.msgWarning("挂断成功");
      getDom('#call').style.display = 'block';
      getDom('#hunup').style.display = 'none';
      getDom('#invite').style.display = 'none';
      getDom('#inviteList').style.visibility = 'hidden';

      removeVideoEl();
      restore();
    } else {
      proxy.$modal.msgWarning(`挂断失败,错误原因:${code}`);
    }

    allData.userList.forEach(element => {
      element.typeFont = '已挂断';
      element.ClassType = 3;
      element.answerType = code;
      hungupApi(element);
    });
  });
};
const removeVideoEl = () => {
  getDom('#videoView').innerHTML = '';
  getDom('#videoView').style = '';
  getDom('#call').style.display = 'block';
  getDom('#hunup').style.display = 'none';
  getDom('#invite').style.display = 'none';
  getDom('#inviteList').style.visibility = 'hidden';
  allData.idList = [];
};
const close = () => {
  if (useRongyunStore.callSession != null) {
    hungup();
  }
  restore();
};
// 输出组件的方法,让外部组件可以调用
defineExpose({
  close,
});

// 还原
const restore = () => {
  let style = { width: '934px' };
  getDom('#rong-action').style.display = 'block';
  const dom = getDom('#RongYun');
  const dom1 = getDom('#videoView');
  getDom('#videoView').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;
    }
  });
};
</script>
<style lang="scss">
@import '@/views/RongyunCommunication/rongyuncss/index.scss';
.rong-container {
  padding: 0 20px;
  display: flex;
  width: 100%;
  height: 100%;

  .rong-action {
    width: 35%;
    display: flex;
    flex-direction: column;
    margin-right: 20px;

    #inviteList {
      visibility: hidden;
    }

    .textDiv {
      min-height: 38px;
      line-height: 38px;
      display: flex;
      align-items: center;
      :deep(.el-radio) {
        color: #fff;
      }
      .dote {
        display: block;
        margin-right: 20px;
        width: 10px;
        height: 10px;
        background: #58fdff;
        border-radius: 10px;
      }

      .text {
        display: flex;
        flex: 1;
        justify-content: space-between;
        font-size: 16px;
        font-family: Alibaba PuHuiTi;
        font-weight: 500;
        color: #81b6d4;
      }
      .Rightvalue {
        max-width: 160px;
        overflow: hidden; //溢出隐藏
        text-overflow: ellipsis; //超出显示省略号
        white-space: nowrap; //强制文本在一行内显示
        color: #fff;
      }
    }

    .textDiv2 {
      // min-height: 45px;
      // line-height: 45px;

      .dote {
        display: block;
        margin-right: 20px;
        width: 10px;
        height: 10px;
        background: #58fdff;
        border-radius: 10px;
      }

      .textTitle {
        height: 40px;
        line-height: 40px;
        display: flex;
        align-items: center;
        font-size: 16px;
        font-weight: 500;
        color: #81b6d4;
      }

      .userList {
        max-height: 220px;
        overflow-y: auto;
        .user {
          // background-color: #14306a;
          // padding: 0 10px;
          // margin-left: 20px;
          // border-bottom: 1px solid #0a0a0a;
          display: flex;
          justify-content: space-between;
          background: #093a73;
          align-items: center;
          border-radius: 1px;
          padding: 2px 8px;
        }
        .username {
          min-width: 52px;
          font-weight: 500;
          color: #13bfff;
        }
        .userphone {
          font-weight: bold;
          color: #ffffff;
        }
        .userInfoClass {
          display: flex;
          align-items: center;
        }
        .ceninfoBox {
          padding-left: 5px;
          .userdept {
            max-width: 140px;
            font-size: 12px;
            text-align: center;
          }
        }
      }
    }

    .rong-login-box {
      // margin-left: 20px;
      display: flex;
      width: 300px;
      height: 40px;
      align-items: center;
      margin-top: 50px;
      .btn {
        margin-right: 20px;
        background: #14306a;
        border-radius: 4px;
        padding: 6px 10px;
        font-size: 16px;
        font-family: Alibaba PuHuiTi;
        font-weight: 400;
        display: flex;
        justify-content: space-around;
        align-items: center;
        color: #fff;
        margin: 0 auto;
        cursor: pointer;
        img {
          width: 18px;
          height: 18px;
        }
      }
      .callBtn {
        background: #67c23a;
      }
      .hangBtn {
        background: #ff3a5a;
      }

      .inviteBtn {
        background: #158bd2;
      }

      .hunupBtn {
        display: none;
      }

      .acceptBtn {
        display: none;
      }
    }
  }

  .rong-video-box {
    width: 70%;
    height: 600px;
    display: flex;
    flex-wrap: wrap;
    overflow: auto;
    position: relative;

    .video-item {
      box-sizing: border-box;
      width: 100%;
      height: calc(100% - 10px);
      position: relative;

      .video-user-id {
        position: absolute;
        top: 5px;
        padding: 0 5px;
        border-radius: 2px;
        z-index: 100;
        font-size: 14px;
        color: #58fdff;
        display: inline-block;
        width: 100%;
        text-align: center;
      }

      .video-media-type {
        position: absolute;
        top: 30px;
        left: 0;
        display: block;
        width: 100%;
        height: calc(100% - 30px);
        background: url('@/assets/images/rongYunImg/yuyin_bg.png') no-repeat;
        background-size: 100% 100%;
      }

      video {
        width: 100%;
        height: 100%;
      }
    }

    .video-item-4 {
      width: 50%;
      height: calc(50% - 10px);
    }

    .video-item-8 {
      width: 25%;
      height: calc(50% - 10px);
    }

    .first-child {
      position: absolute;
      right: 0px;
      top: 0;
      width: 40%;
      height: 30%;
      z-index: 999;
    }
  }
}

.eloption {
  z-index: 20000 !important;
}
</style>

<style lang="scss" scoped>
.RongYun {
  width: 100%;
  height: calc(100% - 40px);
  position: relative;

  .closeIcon {
    position: absolute;
    right: 0px;
    top: -30px;

    &:hover {
      color: chocolate;
    }
  }
}
</style>