d0cf9ba0ff26917d089637b77213c4d5.json 38 KB

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