|
@@ -0,0 +1,1084 @@
|
|
|
+<template>
|
|
|
+ <div class="fbky-container">
|
|
|
+ <div class="websocket">
|
|
|
+ <div class="websocket_left">
|
|
|
+ <div class="set_case">
|
|
|
+ <div class="set_split call_left set_call">
|
|
|
+ <div class="set_box">
|
|
|
+ <div class="set_item">
|
|
|
+ <div class="set_group">
|
|
|
+ <span class="set_name">呼出号码:</span>
|
|
|
+ <input
|
|
|
+ type="text"
|
|
|
+ class="set_ipt ipt_number"
|
|
|
+ id="destinationNumber"
|
|
|
+ :v-model="ringNumber"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div class="set_group">
|
|
|
+ <button class="btn cyan_btn" @click="dial(0)">
|
|
|
+ 语音呼出
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="set_split call_right">
|
|
|
+ <div class="set_box come_box">
|
|
|
+ <div class="set_item">
|
|
|
+ <div class="set_group">
|
|
|
+ <span class="set_name">当前来电:</span>
|
|
|
+ <span id="call_in_now" callID=""></span>
|
|
|
+ </div>
|
|
|
+ <div class="set_group group_right">
|
|
|
+ <button class="btn blue_btn margin" @click="callInAnswer(1)">
|
|
|
+ 视频接听
|
|
|
+ </button>
|
|
|
+ <button class="btn cyan_btn margin" @click="callInAnswer(0)">
|
|
|
+ 语音接听
|
|
|
+ </button>
|
|
|
+ <button class="btn white_btn" @click="callInHangup()">
|
|
|
+ 挂断
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="set_case">
|
|
|
+ <div class="set_split his_left">
|
|
|
+ <div class="set_box">
|
|
|
+ <div class="set_item call_box">
|
|
|
+ <span class="set_name" style="color: red"
|
|
|
+ >执行操作前,请选择正在通话列表(支持同时多路通话):</span
|
|
|
+ >
|
|
|
+ <div class="call_case">
|
|
|
+ <ul id="call_list"></ul>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="set_split his_right">
|
|
|
+ <div class="set_box">
|
|
|
+ <div class="set_item set_first">
|
|
|
+ <span class="set_name">call ID:</span>
|
|
|
+ <input
|
|
|
+ type="text"
|
|
|
+ class="set_ipt ipt_call"
|
|
|
+ id="callID"
|
|
|
+ readonly
|
|
|
+ />
|
|
|
+ <button class="btn blue_btn" @click="callHoldUnhold()">
|
|
|
+ 保持/取消保持指定通话
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ <div class="set_item">
|
|
|
+ <span
|
|
|
+ id="mute_off_status"
|
|
|
+ class="set_status off_status margin"
|
|
|
+ hidden=""
|
|
|
+ >己关闭</span
|
|
|
+ >
|
|
|
+ <span
|
|
|
+ id="mute_on_status"
|
|
|
+ class="set_status on_status margin"
|
|
|
+ hidden=""
|
|
|
+ >未关闭</span
|
|
|
+ >
|
|
|
+ <button class="btn blue_btn" @click="callMuteUnmute()">
|
|
|
+ 关闭/打开指定通话本地声音
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ <div class="set_item">
|
|
|
+ <span
|
|
|
+ id="mute_video_off_status"
|
|
|
+ class="set_status off_status margin"
|
|
|
+ hidden=""
|
|
|
+ >已关闭</span
|
|
|
+ >
|
|
|
+ <span
|
|
|
+ id="mute_video_on_status"
|
|
|
+ class="set_status on_status margin"
|
|
|
+ hidden=""
|
|
|
+ >未关闭</span
|
|
|
+ >
|
|
|
+ <button class="btn blue_btn" @click="callMuteUnmuteVideo()">
|
|
|
+ 关闭/打开指定通话本地视频
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ <div class="set_item">
|
|
|
+ <button class="btn blue_btn margin" @click="callHangup()">
|
|
|
+ 挂断指定通话
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="video_box">
|
|
|
+ <div class="video_left">
|
|
|
+ <div class="video_item video_item1">
|
|
|
+ <span class="video_name">local_video</span>
|
|
|
+ <video
|
|
|
+ class="video_tag"
|
|
|
+ id="local_video"
|
|
|
+ width="10%"
|
|
|
+ height="10%"
|
|
|
+ autoplay="true"
|
|
|
+ ></video>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="websocket_right">
|
|
|
+ <div class="set_box set_zhuce">
|
|
|
+ <div class="set_item">
|
|
|
+ <span class="set_name">登录状态:</span>
|
|
|
+ <span id="off_status" class="set_status off_status">未登录</span>
|
|
|
+ <span id="on_status" class="set_status on_status" hidden=""
|
|
|
+ >已登录</span
|
|
|
+ >
|
|
|
+ </div>
|
|
|
+ <div class="set_item">
|
|
|
+ <span class="set_name"><i class="must">*</i>Websocket URL:</span>
|
|
|
+ <input
|
|
|
+ type="text"
|
|
|
+ class="set_ipt"
|
|
|
+ v-model="socketUrl"
|
|
|
+ placeholder="wss://192.168.10.39:1443/webrtc"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div class="set_item">
|
|
|
+ <span class="set_name" style="flex: none"></span>
|
|
|
+ <span style="color: red"
|
|
|
+ >配置wss后,如果连接失败,请先查看是不是https证书问题
|
|
|
+ 可以通话访问对应的https页面,手动允许浏览器安全提示</span
|
|
|
+ >
|
|
|
+ </div>
|
|
|
+ <div class="set_item">
|
|
|
+ <span class="set_name">麦克风:</span>
|
|
|
+ <select class="set_slt" id="audioInputDev">
|
|
|
+ <option value="">请选择</option>
|
|
|
+ </select>
|
|
|
+ </div>
|
|
|
+ <div class="set_item">
|
|
|
+ <span class="set_name">摄像头:</span>
|
|
|
+ <select class="set_slt" id="videoInputDev">
|
|
|
+ <option value="">请选择</option>
|
|
|
+ </select>
|
|
|
+ </div>
|
|
|
+ <div class="set_item">
|
|
|
+ <span class="set_name">扬声器:</span>
|
|
|
+ <select class="set_slt" id="audioOutputDev">
|
|
|
+ <option value="">请选择</option>
|
|
|
+ </select>
|
|
|
+ </div>
|
|
|
+ <div class="set_item">
|
|
|
+ <span class="set_name"><i class="must">*</i>用户名:</span>
|
|
|
+ <input
|
|
|
+ type="text"
|
|
|
+ class="set_ipt"
|
|
|
+ v-model="login"
|
|
|
+ placeholder="8889"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div class="set_item">
|
|
|
+ <span class="set_name"><i class="must">*</i>密码:</span>
|
|
|
+ <input
|
|
|
+ type="text"
|
|
|
+ class="set_ipt"
|
|
|
+ v-model="password"
|
|
|
+ placeholder="123456"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div class="set_item">
|
|
|
+ <span class="set_name" style="flex: none"></span>
|
|
|
+ <span style="color: red"
|
|
|
+ >支持断线重连,通话中关闭网页,在重新登录后会恢复正在进行的通话</span
|
|
|
+ >
|
|
|
+ </div>
|
|
|
+ <div class="set_item">
|
|
|
+ <span class="set_name">自动登录:</span>
|
|
|
+ <label class="check_box">
|
|
|
+ <input v-model="autoReg" type="checkbox" class="check" />
|
|
|
+ <span>是</span>
|
|
|
+ </label>
|
|
|
+ </div>
|
|
|
+ <div class="set_item">
|
|
|
+ <span class="set_name">自动接听:</span>
|
|
|
+ <label class="check_box">
|
|
|
+ <input v-model="autoAnswer" type="checkbox" class="check" />
|
|
|
+ <span>是</span>
|
|
|
+ </label>
|
|
|
+ </div>
|
|
|
+ <div class="set_item">
|
|
|
+ <span class="set_name" style="flex: none"></span>
|
|
|
+ <span style="color: red"
|
|
|
+ >注意:每个通话都需要在页面中有一个独立的video标签做为载体,
|
|
|
+ 不管是纯音频通话还是音视频通话,
|
|
|
+ 多个通话同时使用一个video标签时,后者会覆盖前者通话的视频和音频,
|
|
|
+ 测试多路通话时,请每次切换不同的video标签</span
|
|
|
+ >
|
|
|
+ </div>
|
|
|
+ <div class="set_item">
|
|
|
+ <span class="set_name">下次通话视频位置:</span>
|
|
|
+ <select class="set_slt" id="peerTag">
|
|
|
+ <option value="video1">video1</option>
|
|
|
+ <option value="video2">video2</option>
|
|
|
+ <option value="video3">video3</option>
|
|
|
+ <option value="video4">video4</option>
|
|
|
+ <option value="video5">video5</option>
|
|
|
+ <option value="video6">video6</option>
|
|
|
+ <option value="video7">video7</option>
|
|
|
+ <option value="video8">video8</option>
|
|
|
+ </select>
|
|
|
+ </div>
|
|
|
+ <div class="set_item">
|
|
|
+ <button class="btn blue_btn margin" @click="initPerimeter()">
|
|
|
+ 载入登录
|
|
|
+ </button>
|
|
|
+ <button class="btn cyan_btn margin" @click="webRtcLogin()">
|
|
|
+ 登录
|
|
|
+ </button>
|
|
|
+ <button class="btn white_btn margin" @click="webRtcLogout()">
|
|
|
+ 登出
|
|
|
+ </button>
|
|
|
+ <button class="btn cyan_btn" @click="callHangupAll()">
|
|
|
+ 挂断所有
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="set_box set_equipment">
|
|
|
+ <div class="set_item">
|
|
|
+ <span class="set_name">本机IP:</span>
|
|
|
+ <input type="text" class="set_ipt" id="localIp" v-model="localIp" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <!-- <div class="set_box">
|
|
|
+ <div class="set_item set_his">
|
|
|
+ <span class="set_name">呼叫历史记录(本地缓存):</span>
|
|
|
+ <div class="his_case">
|
|
|
+ <ul id="his_list"></ul>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div> -->
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import { rtcHelper } from "@/plugins/tr-webrtc.min.js";
|
|
|
+import Dayjs from "dayjs";
|
|
|
+export default {
|
|
|
+ name: "Fbky",
|
|
|
+ props: {
|
|
|
+ curFbkyData: {
|
|
|
+ //分机登录参数
|
|
|
+ type: Object,
|
|
|
+ require: true,
|
|
|
+ default: () => ({}),
|
|
|
+ },
|
|
|
+ ringNumber: {
|
|
|
+ //号码参数
|
|
|
+ type: String,
|
|
|
+ require: true,
|
|
|
+ default: "809",
|
|
|
+ },
|
|
|
+ callDisable: {
|
|
|
+ //呼出或挂断控制
|
|
|
+ type: Boolean,
|
|
|
+ require: true,
|
|
|
+ default: false,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ login: "8889", //分机号
|
|
|
+ password: "123456", //分机密码
|
|
|
+ socketUrl: "wss://dispatcher:1443/webrtc", //webSocketURL
|
|
|
+ // socketUrl: "wss://192.168.10.39:1443/webrtc", //webSocketURL
|
|
|
+ localIp: "",
|
|
|
+ autoReg: false,
|
|
|
+ autoAnswer: false,
|
|
|
+ mic: "", //麦克风选择
|
|
|
+ cam: "", //摄像头选择
|
|
|
+ speak: "", //扬声器选择
|
|
|
+ call_in_now_d: null,
|
|
|
+ online: false,
|
|
|
+ callback: {
|
|
|
+ onRinging: function (d) {
|
|
|
+ // 来电
|
|
|
+ this.onRinging(d);
|
|
|
+ },
|
|
|
+ onCalling: function (d) {
|
|
|
+ // 外呼
|
|
|
+ this.onCalling(d);
|
|
|
+ },
|
|
|
+ onAnswer: function (d) {
|
|
|
+ // 通话中
|
|
|
+ this.onAnswer(d);
|
|
|
+ },
|
|
|
+ onHangup: function (d) {
|
|
|
+ // 挂机
|
|
|
+ this.onHangup(d);
|
|
|
+ },
|
|
|
+ onLogin: function () {
|
|
|
+ //登录回调
|
|
|
+ console.log("登录状态在线");
|
|
|
+ this.online = true;
|
|
|
+ document
|
|
|
+ .getElementById("off_status")
|
|
|
+ .setAttribute("hidden", "hidden");
|
|
|
+ document.getElementById("on_status").removeAttribute("hidden");
|
|
|
+ },
|
|
|
+ onLogout: function () {
|
|
|
+ //登出回调
|
|
|
+ console.log("登出状态离线回调");
|
|
|
+ this.online = false;
|
|
|
+ document.getElementById("on_status").setAttribute("hidden", "hidden");
|
|
|
+ document.getElementById("off_status").removeAttribute("hidden");
|
|
|
+ },
|
|
|
+ },
|
|
|
+ };
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ curFbkyData: {
|
|
|
+ handler(newValue, oldValue) {
|
|
|
+ this.callHangupAll();
|
|
|
+ this.webRtcLogout();
|
|
|
+ console.log("数据更新:", newValue, "旧数据:", oldValue);
|
|
|
+ if (newValue.url) {
|
|
|
+ this.login = newValue.admin;
|
|
|
+ this.password = newValue.password;
|
|
|
+ this.socketUrl = newValue.url;
|
|
|
+ this.localIp = newValue.localIp;
|
|
|
+ }
|
|
|
+ setTimeout(() => {
|
|
|
+ this.initPerimeter();
|
|
|
+ }, 1000);
|
|
|
+ },
|
|
|
+ deep: true,
|
|
|
+ },
|
|
|
+ ringNumber: {
|
|
|
+ handler(newValue) {
|
|
|
+ this.callHangupAll();
|
|
|
+ if (this.callDisable) {
|
|
|
+ this.dial(0);
|
|
|
+ }
|
|
|
+ console.log("拨打号码:", newValue);
|
|
|
+ },
|
|
|
+ deep: true,
|
|
|
+ },
|
|
|
+ callDisable: {
|
|
|
+ handler(newValue) {
|
|
|
+ if (newValue) {
|
|
|
+ this.dial(0);
|
|
|
+ console.log("拨号", this.ringNumber);
|
|
|
+ } else {
|
|
|
+ this.callHangupAll();
|
|
|
+ console.log("挂断");
|
|
|
+ }
|
|
|
+ },
|
|
|
+ deep: true,
|
|
|
+ },
|
|
|
+ online: {
|
|
|
+ handler(newValue) {
|
|
|
+ if (newValue) {
|
|
|
+ this.sendTo('true');
|
|
|
+ console.log("传值:true");
|
|
|
+ } else {
|
|
|
+ this.sendTo('false');
|
|
|
+ console.log("传值:false");
|
|
|
+ }
|
|
|
+ },
|
|
|
+ deep: true,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ created() {
|
|
|
+ this.initMediaDevices();
|
|
|
+ setTimeout(() => {
|
|
|
+ this.initPerimeter();
|
|
|
+ }, 500);
|
|
|
+ },
|
|
|
+ destroyed() {
|
|
|
+ this.callHangupAll();
|
|
|
+ setTimeout(() => {
|
|
|
+ this.webRtcLogout();
|
|
|
+ }, 500);
|
|
|
+ },
|
|
|
+ mounted() {},
|
|
|
+ methods: {
|
|
|
+ sendTo(m) {
|
|
|
+ this.$emit('onlineDis', m);
|
|
|
+ },
|
|
|
+ getVideoDiv() {
|
|
|
+ return document.getElementById("peerTag").value;
|
|
|
+ },
|
|
|
+ getValue(id) {
|
|
|
+ return document.getElementById(id).value;
|
|
|
+ },
|
|
|
+ setValue(id, value) {
|
|
|
+ document.getElementById(id).value = value;
|
|
|
+ },
|
|
|
+ //载入参数登录
|
|
|
+ initPerimeter() {
|
|
|
+ if (!this.login || !this.password || !this.socketUrl) {
|
|
|
+ alert("请填写必填参数");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 缓存配置
|
|
|
+ localStorage.verto_login = this.login; //分机账号
|
|
|
+ localStorage.verto_password = this.password; //分机密码
|
|
|
+ localStorage.verto_socketUrl = this.socketUrl; //webSocketURL
|
|
|
+ localStorage.verto_localIp = this.localIp;
|
|
|
+ localStorage.verto_autoReg = this.autoReg; //自动登录开关
|
|
|
+ localStorage.verto_autoAnswer = this.autoAnswer; //自动接听开关
|
|
|
+
|
|
|
+ rtcHelper.bootstrap(
|
|
|
+ this.login,
|
|
|
+ this.password,
|
|
|
+ this.socketUrl,
|
|
|
+ this.localIp,
|
|
|
+ this.getVideoDiv(),
|
|
|
+ "local_video",
|
|
|
+ this.callback,
|
|
|
+ this.mic,
|
|
|
+ this.speak,
|
|
|
+ this.cam
|
|
|
+ );
|
|
|
+ // console.log(
|
|
|
+ // "配置载入参数",
|
|
|
+ // this.login,
|
|
|
+ // this.password,
|
|
|
+ // this.socketUrl,
|
|
|
+ // this.localIp,
|
|
|
+ // this.getVideoDiv(),
|
|
|
+ // "local_video",
|
|
|
+ // this.callback,
|
|
|
+ // this.mic,
|
|
|
+ // this.speak,
|
|
|
+ // this.cam
|
|
|
+ // );
|
|
|
+ },
|
|
|
+ //获取音视频设备
|
|
|
+ initMediaDevices() {
|
|
|
+ rtcHelper.getMediaDevices().then((result) => {
|
|
|
+ try {
|
|
|
+ let microphone = result.audioInputDevices; //麦克风
|
|
|
+ let camera = result.videoDevices; //摄像头+
|
|
|
+ let loudspeaker = result.audioOutputDevices; //扬声器
|
|
|
+ let microphoneStr = "";
|
|
|
+ let cameraStr = "";
|
|
|
+ let loudspeakerStr = "";
|
|
|
+ for (let i = 0; i < microphone.length; i++) {
|
|
|
+ microphoneStr +=
|
|
|
+ '<option value="' +
|
|
|
+ microphone[i].deviceId +
|
|
|
+ '">' +
|
|
|
+ microphone[i].label +
|
|
|
+ "</option>";
|
|
|
+ }
|
|
|
+ document.getElementById("audioInputDev").innerHTML = microphoneStr;
|
|
|
+ for (let i = 0; i < camera.length; i++) {
|
|
|
+ cameraStr +=
|
|
|
+ '<option value="' +
|
|
|
+ microphone[i].deviceId +
|
|
|
+ '">' +
|
|
|
+ camera[i].label +
|
|
|
+ "</option>";
|
|
|
+ }
|
|
|
+ document.getElementById("videoInputDev").innerHTML = cameraStr;
|
|
|
+ for (let i = 0; i < loudspeaker.length; i++) {
|
|
|
+ loudspeakerStr +=
|
|
|
+ '<option value="' +
|
|
|
+ microphone[i].deviceId +
|
|
|
+ '">' +
|
|
|
+ loudspeaker[i].label +
|
|
|
+ "</option>";
|
|
|
+ }
|
|
|
+ document.getElementById("audioOutputDev").innerHTML = loudspeakerStr;
|
|
|
+ if (microphone.length > 0) {
|
|
|
+ this.mic = microphone[0].deviceId;
|
|
|
+ }
|
|
|
+ if (camera.length > 0) {
|
|
|
+ this.cam = camera[0].deviceId;
|
|
|
+ }
|
|
|
+ if (loudspeaker.length > 0) {
|
|
|
+ this.speak = loudspeaker[0].deviceId;
|
|
|
+ }
|
|
|
+ console.log("音视频设备:", result, this.mic, this.cam, this.speak);
|
|
|
+ } catch (e) {
|
|
|
+ console.error(e);
|
|
|
+ }
|
|
|
+ // 自动登录
|
|
|
+ // if (
|
|
|
+ // localStorage.verto_autoReg == "true" &&
|
|
|
+ // localStorage.verto_login &&
|
|
|
+ // localStorage.verto_password &&
|
|
|
+ // localStorage.verto_socketUrl
|
|
|
+ // ) {
|
|
|
+ // this.initPerimeter();
|
|
|
+ // }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ //登录
|
|
|
+ webRtcLogin() {
|
|
|
+ try {
|
|
|
+ rtcHelper.rtcLogin();
|
|
|
+ } catch (e) {
|
|
|
+ console.error(e);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ //登出
|
|
|
+ webRtcLogout() {
|
|
|
+ try {
|
|
|
+ rtcHelper.rtcLogout();
|
|
|
+ } catch (e) {
|
|
|
+ console.error(e);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 拨号外呼
|
|
|
+ dial(type) {
|
|
|
+ console.log("拨号号码:", this.ringNumber);
|
|
|
+ let destinationNumber = this.ringNumber;
|
|
|
+ if (!destinationNumber) {
|
|
|
+ alert("没有输入被叫号码");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (type === 1) {
|
|
|
+ // 视频呼出
|
|
|
+ rtcHelper.rtcDial(destinationNumber, true);
|
|
|
+ } else {
|
|
|
+ // 语音呼出
|
|
|
+ rtcHelper.rtcDial(destinationNumber, false);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ //历史记录
|
|
|
+ logRecords(callee, type) {
|
|
|
+ let log = "";
|
|
|
+ switch (type) {
|
|
|
+ case "ringing":
|
|
|
+ log = new Date().Format("yyyy-MM-dd HH:mm:ss") + " 呼入 " + callee;
|
|
|
+ break;
|
|
|
+ case "calling":
|
|
|
+ log = new Date().Format("yyyy-MM-dd HH:mm:ss") + " 呼出 " + callee;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (localStorage.verto_his_list) {
|
|
|
+ localStorage.verto_his_list += "," + log;
|
|
|
+ } else {
|
|
|
+ localStorage.verto_his_list = log;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // =================== 通话事件 start ====================
|
|
|
+ onRinging(d) {
|
|
|
+ let callee = d.cidString();
|
|
|
+ console.log("===========来电信息===========" + callee);
|
|
|
+ console.log("通话呼入事件", d);
|
|
|
+ // 判断是否自动接听
|
|
|
+ if (localStorage.verto_autoAnswer) {
|
|
|
+ console.log("自动接听");
|
|
|
+ if (d.params.wantVideo) {
|
|
|
+ // 选择是否有视频
|
|
|
+ let videoFlag = true;
|
|
|
+ rtcHelper.rtcAnswer(d, videoFlag);
|
|
|
+ } else {
|
|
|
+ rtcHelper.rtcAnswer(d, false);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ document.getElementById("call_in_now").innerHTML = callee;
|
|
|
+ document.getElementById("call_in_now").setAttribute("callID", d.callID);
|
|
|
+ this.call_in_now_d = d;
|
|
|
+ }
|
|
|
+ document.getElementById("call_list").innerHTML +=
|
|
|
+ "<li callID='" +
|
|
|
+ d.callID +
|
|
|
+ "' @click='checkCalling(this)'>" +
|
|
|
+ callee +
|
|
|
+ " 呼入</li>";
|
|
|
+ // 缓存历史呼入记录
|
|
|
+ this.logRecords(callee, "ringing");
|
|
|
+ },
|
|
|
+ onCalling(d) {
|
|
|
+ let callee = d.cidString();
|
|
|
+ console.log("通话呼出事件", d);
|
|
|
+ // 呼出通话启动
|
|
|
+ document.getElementById("call_list").innerHTML +=
|
|
|
+ "<li callID='" +
|
|
|
+ d.callID +
|
|
|
+ "' @click='checkCalling(this)'>" +
|
|
|
+ callee +
|
|
|
+ " 呼出</li>";
|
|
|
+ // 缓存历史呼出记录
|
|
|
+ this.logRecords(callee, "calling");
|
|
|
+ },
|
|
|
+ onAnswer(d) {
|
|
|
+ // 通话中处理
|
|
|
+ console.log("通话中事件", d);
|
|
|
+ },
|
|
|
+ onHangup(d) {
|
|
|
+ // 挂机处理 - 接通列表处理
|
|
|
+ // console.log("通话挂机事件", d);
|
|
|
+ },
|
|
|
+ // =================== 通话事件 end ====================
|
|
|
+
|
|
|
+ // =================== 呼入处理 start ====================
|
|
|
+ // 呼入接听
|
|
|
+ callInAnswer(type) {
|
|
|
+ if (!this.call_in_now_d) {
|
|
|
+ alert("当前无通话呼入");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (type === 1) {
|
|
|
+ if (this.call_in_now_d.params.wantVideo) {
|
|
|
+ // 选择是否有视频
|
|
|
+ let videoFlag = true;
|
|
|
+ rtcHelper.rtcAnswer(this.call_in_now_d, videoFlag);
|
|
|
+ } else {
|
|
|
+ rtcHelper.rtcAnswer(this.call_in_now_d, false);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ rtcHelper.rtcAnswer(this.call_in_now_d, false);
|
|
|
+ }
|
|
|
+ console.log("通话呼入");
|
|
|
+ document.getElementById("call_in_now").innerHTML = "";
|
|
|
+ this.call_in_now_d = null;
|
|
|
+ },
|
|
|
+
|
|
|
+ // 呼入挂断
|
|
|
+ callInHangup() {
|
|
|
+ if (!this.call_in_now_d) {
|
|
|
+ alert("当前无通话呼入");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ rtcHelper.rtcHangup(this.call_in_now_d.callID);
|
|
|
+ document.getElementById("call_in_now").innerHTML = "";
|
|
|
+ console.log("通话挂断");
|
|
|
+ this.call_in_now_d = null;
|
|
|
+ },
|
|
|
+
|
|
|
+ // =================== 呼入处理 end ====================
|
|
|
+
|
|
|
+ // =================== 通话功能 start ==================
|
|
|
+ checkCalling(e) {
|
|
|
+ let callID = e.getAttribute("callID");
|
|
|
+ console.log("设置", callID);
|
|
|
+ this.setValue("callID", callID);
|
|
|
+ this.getMuteState(callID);
|
|
|
+ this.getMuteVideoState(callID);
|
|
|
+ },
|
|
|
+
|
|
|
+ getMuteState(callID) {
|
|
|
+ if (rtcHelper.rtcGetMuteState(callID)) {
|
|
|
+ // 没有静音
|
|
|
+ console.log("非静音,本地声音状态打开");
|
|
|
+ document
|
|
|
+ .getElementById("mute_off_status")
|
|
|
+ .setAttribute("hidden", "hidden");
|
|
|
+ document.getElementById("mute_on_status").removeAttribute("hidden");
|
|
|
+ } else {
|
|
|
+ console.log("静音,本地声音状态关闭");
|
|
|
+ document.getElementById("mute_off_status").removeAttribute("hidden");
|
|
|
+ document
|
|
|
+ .getElementById("mute_on_status")
|
|
|
+ .setAttribute("hidden", "hidden");
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ getMuteVideoState(callID) {
|
|
|
+ if (rtcHelper.rtcGetMuteVideoState(callID)) {
|
|
|
+ // 没有静音
|
|
|
+ console.log("非静音,本地视频状态打开");
|
|
|
+ document
|
|
|
+ .getElementById("mute_video_off_status")
|
|
|
+ .setAttribute("hidden", "hidden");
|
|
|
+ document
|
|
|
+ .getElementById("mute_video_on_status")
|
|
|
+ .removeAttribute("hidden");
|
|
|
+ } else {
|
|
|
+ console.log("静音,本地视频状态关闭");
|
|
|
+ document
|
|
|
+ .getElementById("mute_video_off_status")
|
|
|
+ .removeAttribute("hidden");
|
|
|
+ document
|
|
|
+ .getElementById("mute_video_on_status")
|
|
|
+ .setAttribute("hidden", "hidden");
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ //保持或取消指定通话
|
|
|
+ callHoldUnhold(callID) {
|
|
|
+ if (callID) {
|
|
|
+ rtcHelper.rtcHoldUnhold(callID);
|
|
|
+ } else {
|
|
|
+ alert("未选择callID");
|
|
|
+ }
|
|
|
+ },
|
|
|
+ //关闭或打开通话本地声音
|
|
|
+ callMuteUnmute(callID) {
|
|
|
+ if (callID) {
|
|
|
+ rtcHelper.rtcMuteUnmute(callID);
|
|
|
+ this.getMuteState(callID);
|
|
|
+ } else {
|
|
|
+ alert("未选择callID");
|
|
|
+ }
|
|
|
+ },
|
|
|
+ //关闭或打开本地视频
|
|
|
+ callMuteUnmuteVideo(callID) {
|
|
|
+ if (callID) {
|
|
|
+ rtcHelper.rtcMuteUnmuteVideo(callID);
|
|
|
+ this.getMuteVideoState(callID);
|
|
|
+ } else {
|
|
|
+ alert("未选择callID");
|
|
|
+ }
|
|
|
+ },
|
|
|
+ //挂断指定callID通话
|
|
|
+ callHangup(callID) {
|
|
|
+ if (callID) {
|
|
|
+ rtcHelper.rtcHangup(callID);
|
|
|
+ alert("callID", callID);
|
|
|
+ } else {
|
|
|
+ alert("未选择callID");
|
|
|
+ }
|
|
|
+ },
|
|
|
+ //挂断所有通话
|
|
|
+ callHangupAll() {
|
|
|
+ rtcHelper.rtcHangupAll();
|
|
|
+ },
|
|
|
+ //向指定通话发送DTMF
|
|
|
+ callDtmf(callID, dtmfKey) {
|
|
|
+ if (callID) {
|
|
|
+ rtcHelper.rtcDtmf(callID, dtmfKey);
|
|
|
+ } else {
|
|
|
+ alert("未选择callID");
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // =================== 通话功能 end ==================
|
|
|
+ },
|
|
|
+};
|
|
|
+</script>
|
|
|
+<style lang="less" scoped>
|
|
|
+.fbky-container {
|
|
|
+ width: 100%;
|
|
|
+ .websocket {
|
|
|
+ width: 100%;
|
|
|
+ height: 60%;
|
|
|
+ display: flex;
|
|
|
+ padding: 20px;
|
|
|
+ background-color: #f1f4f7;
|
|
|
+ .websocket_left {
|
|
|
+ width: 70%;
|
|
|
+ padding-right: 20px;
|
|
|
+ .set_case {
|
|
|
+ display: flex;
|
|
|
+ .set_call .set_name {
|
|
|
+ width: 80px;
|
|
|
+ }
|
|
|
+ .set_item {
|
|
|
+ margin-bottom: 15px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ }
|
|
|
+ .call_left {
|
|
|
+ width: 50%;
|
|
|
+ display: flex;
|
|
|
+ padding-right: 20px;
|
|
|
+ }
|
|
|
+ .call_right {
|
|
|
+ width: 50%;
|
|
|
+ display: flex;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .video_box {
|
|
|
+ height: 200px;
|
|
|
+ display: flex;
|
|
|
+ .video_left,
|
|
|
+ .video_right {
|
|
|
+ width: 50%;
|
|
|
+ }
|
|
|
+ .video_left {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ }
|
|
|
+ .video_right {
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .websocket_right {
|
|
|
+ width: 30%;
|
|
|
+ .set_box {
|
|
|
+ width: 100%;
|
|
|
+ background-color: #fff;
|
|
|
+ padding: 20px;
|
|
|
+ margin-bottom: 20px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.set_box {
|
|
|
+ width: 100%;
|
|
|
+ background-color: #fff;
|
|
|
+ padding: 20px;
|
|
|
+ margin-bottom: 20px;
|
|
|
+}
|
|
|
+
|
|
|
+.set_item:last-child {
|
|
|
+ margin-bottom: 0;
|
|
|
+}
|
|
|
+.group_case {
|
|
|
+ justify-content: space-between;
|
|
|
+}
|
|
|
+
|
|
|
+.set_group {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+}
|
|
|
+
|
|
|
+.set_slt,
|
|
|
+.set_ipt {
|
|
|
+ flex: auto;
|
|
|
+ height: 30px;
|
|
|
+ line-height: 30px;
|
|
|
+ border: 1px solid #d1d1d1;
|
|
|
+ outline: none;
|
|
|
+ border-radius: 3px;
|
|
|
+ padding-left: 10px;
|
|
|
+ background-color: #fff !important;
|
|
|
+}
|
|
|
+
|
|
|
+.btn {
|
|
|
+ padding: 6px 12px;
|
|
|
+ border-radius: 3px;
|
|
|
+ cursor: pointer;
|
|
|
+ outline: none !important;
|
|
|
+ font-size: 12px !important;
|
|
|
+}
|
|
|
+
|
|
|
+.btn:hover {
|
|
|
+ opacity: 0.8;
|
|
|
+}
|
|
|
+
|
|
|
+.blue_btn {
|
|
|
+ background-color: #1890ff;
|
|
|
+ border: 1px solid #1890ff;
|
|
|
+ color: #fff !important;
|
|
|
+}
|
|
|
+
|
|
|
+.cyan_btn {
|
|
|
+ background-color: #00bcd4;
|
|
|
+ border: 1px solid #00bcd4;
|
|
|
+ color: #fff !important;
|
|
|
+}
|
|
|
+
|
|
|
+.white_btn {
|
|
|
+ background-color: #fafafa;
|
|
|
+ border: 1px solid #d1d1d1;
|
|
|
+}
|
|
|
+
|
|
|
+.video_box {
|
|
|
+ display: flex;
|
|
|
+}
|
|
|
+
|
|
|
+.video_left,
|
|
|
+.video_right {
|
|
|
+ width: 50%;
|
|
|
+}
|
|
|
+
|
|
|
+.video_left {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+}
|
|
|
+
|
|
|
+.video_right {
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+}
|
|
|
+
|
|
|
+.video_item {
|
|
|
+ position: relative;
|
|
|
+ background-color: #fff;
|
|
|
+ border: 1px solid #d1d1d1;
|
|
|
+}
|
|
|
+
|
|
|
+.video_item1 {
|
|
|
+ width: 100%;
|
|
|
+ flex: auto;
|
|
|
+}
|
|
|
+
|
|
|
+.video_item2 {
|
|
|
+ width: 100%;
|
|
|
+}
|
|
|
+
|
|
|
+.video_item3 {
|
|
|
+ width: 50%;
|
|
|
+}
|
|
|
+
|
|
|
+.video_name {
|
|
|
+ position: absolute;
|
|
|
+ top: 5px;
|
|
|
+ left: 5px;
|
|
|
+}
|
|
|
+
|
|
|
+.video_tag {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+}
|
|
|
+
|
|
|
+.set_case {
|
|
|
+ display: flex;
|
|
|
+}
|
|
|
+
|
|
|
+.set_status {
|
|
|
+ color: #fff;
|
|
|
+ border-radius: 10px;
|
|
|
+ padding: 4px 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.off_status {
|
|
|
+ background-color: #bbb;
|
|
|
+}
|
|
|
+
|
|
|
+.on_status {
|
|
|
+ background-color: #3fd672;
|
|
|
+}
|
|
|
+
|
|
|
+.must {
|
|
|
+ color: red;
|
|
|
+ font-size: 17px;
|
|
|
+ position: absolute;
|
|
|
+ left: -10px;
|
|
|
+ top: 0px;
|
|
|
+}
|
|
|
+
|
|
|
+.set_name {
|
|
|
+ position: relative;
|
|
|
+}
|
|
|
+
|
|
|
+.set_zhuce .set_name {
|
|
|
+ width: 140px;
|
|
|
+}
|
|
|
+
|
|
|
+.set_equipment .set_name {
|
|
|
+ width: 90px;
|
|
|
+}
|
|
|
+
|
|
|
+.margin {
|
|
|
+ margin-right: 20px;
|
|
|
+}
|
|
|
+
|
|
|
+.his_left {
|
|
|
+ width: 30%;
|
|
|
+ display: flex;
|
|
|
+}
|
|
|
+
|
|
|
+.his_right {
|
|
|
+ width: 70%;
|
|
|
+ display: flex;
|
|
|
+}
|
|
|
+
|
|
|
+.ipt_number {
|
|
|
+ flex: none;
|
|
|
+ width: 50%;
|
|
|
+}
|
|
|
+
|
|
|
+.call_box {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: flex-start;
|
|
|
+ height: 100%;
|
|
|
+}
|
|
|
+
|
|
|
+.call_box .set_name {
|
|
|
+ margin-bottom: 12px;
|
|
|
+}
|
|
|
+
|
|
|
+.call_case {
|
|
|
+ display: flex;
|
|
|
+ height: 135px;
|
|
|
+ overflow: hidden auto;
|
|
|
+ border: 1px solid #d1d1d1;
|
|
|
+ width: 100%;
|
|
|
+}
|
|
|
+
|
|
|
+.his_case {
|
|
|
+ display: flex;
|
|
|
+ height: 182px;
|
|
|
+ overflow: hidden auto;
|
|
|
+ border: 1px solid #d1d1d1;
|
|
|
+ width: 100%;
|
|
|
+}
|
|
|
+
|
|
|
+#call_list {
|
|
|
+ flex: auto;
|
|
|
+}
|
|
|
+
|
|
|
+#call_list > li,
|
|
|
+#his_list > li {
|
|
|
+ height: 30px;
|
|
|
+ line-height: 30px;
|
|
|
+ padding: 0 20px;
|
|
|
+ cursor: pointer;
|
|
|
+}
|
|
|
+
|
|
|
+#call_list > li:hover,
|
|
|
+#his_list > li:hover {
|
|
|
+ background-color: #eee;
|
|
|
+}
|
|
|
+
|
|
|
+.set_his {
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: flex-start;
|
|
|
+}
|
|
|
+
|
|
|
+.set_his .set_name {
|
|
|
+ margin-bottom: 15px;
|
|
|
+}
|
|
|
+
|
|
|
+#his_list {
|
|
|
+ width: 100%;
|
|
|
+}
|
|
|
+
|
|
|
+.set_speed {
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: flex-start;
|
|
|
+}
|
|
|
+
|
|
|
+#speed {
|
|
|
+ margin-top: 20px;
|
|
|
+}
|
|
|
+
|
|
|
+.ipt_call {
|
|
|
+ flex: none;
|
|
|
+ width: 30%;
|
|
|
+ margin-right: 15px;
|
|
|
+}
|
|
|
+
|
|
|
+.check_box {
|
|
|
+ cursor: pointer;
|
|
|
+ width: 20%;
|
|
|
+}
|
|
|
+
|
|
|
+.check {
|
|
|
+ position: relative;
|
|
|
+ top: 2px;
|
|
|
+}
|
|
|
+
|
|
|
+.come_box {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ justify-content: space-between;
|
|
|
+}
|
|
|
+
|
|
|
+.set_first {
|
|
|
+ margin-top: 30px;
|
|
|
+}
|
|
|
+
|
|
|
+.group_right {
|
|
|
+ margin-left: 20px;
|
|
|
+}
|
|
|
+</style>
|