/*
 * 呼叫中心电话工具条
 * author: easycallcenter365@126.com
 * 2025-04-08
*/

// 导入 jQuery
import $ from './jquery-1.11.0.js';

function _phoneBarObserver(){
	if(!(this instanceof _phoneBarObserver)){
		return new _phoneBarObserver();
	}
	this.listeners = {}
};
_phoneBarObserver.prototype = {
	on: function (key, callback) { this.addListener(key, callback); },
	off: function (key, callback) { this.removeListener(key, callback); },
	addListener: function (key, callback) {
		if(!this.listeners[key]) {
			this.listeners[key] = [];
		}
		this.listeners[key].push(callback);
	},
	removeListener: function (key, callback) {
		if(this.listeners[key]) {
			if(callback) {
				const index = this.listeners[key].indexOf(callback);
				if (index > -1) {
					this.listeners[key].splice(index, 1);
				}
			}else {
				this.listeners[key] = [];
			}
		}
	},
	notifyAll: function (key, info) {
		if(!this.listeners[key]) return;
		for (var i = 0; i < this.listeners[key].length; i++) {
			if (typeof this.listeners[key][i] === 'function') {
				this.listeners[key][i](info);
			}
		}
	},
	make: function (o) {
		for (var i in this) {
			o[i] = this[i];
			o.listeners = {}
		}
	}
};

//呼叫中心websocket通信对象
"use strict";
function ccPhoneBarSocket() {
	var observer = new _phoneBarObserver();
	observer.make(this);
	var _cc = this;
	var ws = null;
	var wsuri = null;
	var isConnected = false;
	/* 通话已建立 */
	var callConnected = false;
	/*
	 *  是否可以发送视频通话邀请;
	 */
	var canSendVideoReInvite = false;
	/**
	 * 是否开启了坐席状态列表订阅
	 * @type {boolean}
	 */
	this.subscribeAgentListStarted = false;
	this.iframe = null;
	this.callConfig = {
		 // 使用默认的UI，还是使用自定义的UI
		'useDefaultUi': false,
		//呼叫控制服务器地址
		'ipccServer': 'sip.ylrzcloud.com',
		//是否启用websocket安全连接
		'enableWss' : true,
		//语音编码
		'callCodec' : 'pcma',
		//是否发送心跳数据
		'enableHeartBeat' : true,
		//送心跳数据的时间间隔; 秒;
		'heartBeatIntervalSecs' : 16,
		// 工具条外呼时： 软电话和外呼通话，使用相同的语音编码，避免转码，从而提高性能;
		// 但是!： 如果客户端是网页电话，且外呼线路使用g729编码时，该参数需要设置为false，
		// 因为网页电话不支持g729编码; [此时会产生语音编码的转码]
		'useSameAudioCodeForOutbound' : true,
		// 令牌
		'loginToken' : '',

		 // 网关列表, 如果是注册模式： 网关地址参数则填写为网关名称;
		 // 安全起见，生产环境，需要把该参数加密为base64格式;
		'gatewayList' : [
			{
				uuid         :  '01',
				updateTime         :  1675953810492,
				gatewayAddr  : '113.207.68.30:5543;external', // 网关地址 + 外呼环境[可选参数，默认为external];
				callerNumber : '02386990208',    // 主叫号码
				calleePrefix : '',       // 被叫前缀
				priority     : 1,        // 优先级
				concurrency  : 1000,       // 并发数
				register     : false,    // 是否注册模式
				audioCodec   : 'g711'    // 语音编码，可用选择项 g711、g729
			}
		],

	    'gatewayEncrypted' : false,

		 // 分机注册配置;
		 //Freeswitch服务器地址
		 'fsServer' : '129.28.164.235:5060',
		 // 分机账户
		 'extnum' : '1001',
		 // 工号
		 'opnum' : 'admin',
		 //业务组编号
		 'groupId' : '1',
		 //全部业务组列表
		 'groups' : null,
		 //全部坐席人员列表
		 'agentList' : null,
		 'extPassword': '0406f9d44bb8fe195a1ee2557bbeebf7',  // 分机密码
		 'phoneType': 'EyeBeam',         // 电话类型
		 'webPhoneUrl' : 'None',

		 // 客户端软电话代理配置信息
		 'localHostProxyVersion' : 'v20221130_1736',  // 本地代理软件的版本信息
		 'localHostProxyPort' : 8888    // 本地代理软件端口;
	};

	/**
	 * 在指定html对象后追加新元素
	 * @param newElement
	 * @param targetElement
	 */
	this.insertAfter = function(newElement,targetElement)
	{
		var parent = targetElement.parentNode;
		if(parent.lastChild === targetElement)
		{
			parent.appendChild(newElement);
		}else{
			parent.insertBefore(newElement,targetElement.nextSibling);
		}
	};

	this.trim = function (str) {
		return str.replace(/^\s\s*/,'').replace(/\s\s*$/, '');
	};
    this.getIsConnected = function(){
    	return isConnected;
    };
    /**
     *  获取通话状态
     * @returns {boolean} true通话中，false通话未建立;
     */
    this.getCallConnected = function(){
        return callConnected;
    };
    /**
     *  设置通话状态;
     * @param value true通话中，false通话未建立
     * @returns {*}
     */
    this.setCallConnected = function(value){
        callConnected = value;
    };

	/**
	 *  设置一个标志，指示是否可以发起视频通话;
	 * 仅限通话为音频通话且通话已经接通时方可允许发起视频邀请；
	 * @param value
	 */
	this.setCanSendVideoReInvite = function(value){
		canSendVideoReInvite = value;
	};

	/**
	 *  设置一个标志，指示是否可以发起视频通话;
	 * @param value
	 */
	this.getCanSendVideoReInvite = function(){
	    return 	canSendVideoReInvite;
	};

	this.setHeartbeat = function()
	{
		setInterval(function(){
			//如果启用了心跳，而且用户已经登录上线,则发送心跳数据
			if(_cc.callConfig.enableHeartBeat && _cc.getIsConnected()){
				console.debug("try to send heartbeat.");
				var heartBeat = {};
				heartBeat.action="setHearBeat";
				heartBeat.body = "{}";
				_cc.sendMsg(heartBeat);
			}
		}, _cc.callConfig.heartBeatIntervalSecs * 1000);
	};

	this.loadScript = function(destUrl, callbackFunc){
		var script = document.createElement("script");
        script.type = "text/javascript";
        script.src = destUrl;
		if(null != callbackFunc){
		   script.onload=function(){callbackFunc();}
		}
		document.getElementsByTagName('head')[0].appendChild(script);
	};

    // 初始化websocket连接参数
	this.initConfig = function(config) {
		//把config中的属性全部拷贝到callConfig中;
		for(var element in config) {
			this.callConfig[element] = config[element];
		}

		var _loginToken = this.callConfig["loginToken"];
		if(typeof(_loginToken) == "undefined" && _loginToken === "") {
			alert("电话工具条：无法获取 loginToken!");
			return;
		}

        console.log("callConfig:", JSON.stringify(this.callConfig));
        //线上enableWss: true 本地调试为false
        if(_cc.callConfig.enableWss){
            wsuri = 'wss://' + this.callConfig.ipccServer +
                '/call-center/websocketServer?' +
                '&loginToken=' + this.callConfig.loginToken;
        }else{
            wsuri = 'ws://129.28.164.235:1081/call-center/websocketServer?' +
                '&loginToken=' + this.callConfig.loginToken;
        }
        console.log("ipccServer url: " + wsuri);
	    var ipccServerIpAddr = this.callConfig.ipccServer.split(":");
	    if(this.callConfig.enableWss &&  this.checkIP(ipccServerIpAddr)){
	    	var tipsError = "ERROR! 启用了wss之后，必须使用域名访问websocketServer! " + this.callConfig.ipccServer;
	    	console.log(tipsError);
	    	alert(tipsError);
		}
	    if(this.callConfig.enableHeartBeat) {
			_cc.setHeartbeat();
		}

		//var downLoadUrl = "http://192.168.66.71:81/soft/callcenter-soft/LocalHostProxy/LocalHostProxy-" +
							  _cc.callConfig["localHostProxyVersion"] + ".zip";
		//console.log("客户端代理软件的下载地址:", downLoadUrl);
        //this.createIframe("http://127.0.0.1:8888/getVersion");

        if(_cc.callConfig["useDefaultUi"]){
			this.initPhoneBarUI();
		}
	};

	//检测ip地址是否合法;
	this.checkIP = function (ip)
	{
	    var re =  /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/ ;
	    return re.test(ip);
	};

	//断开到呼叫控制服务器的连接
	this.disconnect = function(){
		// 检查 WebSocket 是否存在且连接正常
		if (!ws || ws.readyState !== WebSocket.OPEN) {
			console.log('WebSocket 未连接或已关闭，无需发送断开指令');
			return;
		}
		var cmdInfo = {};
		cmdInfo.action="setAgentStatus";
		cmdInfo.body = {"cmd" : "disconnect", "args" : { "msg" : "disconnection opt triggered by js client." } };
		ws.send(JSON.stringify(cmdInfo));
		// 立即关闭 WebSocket 连接
		ws.close();
	};

	/**
	 *  获取当前坐席登录的分机号码
	 * @returns {string|*}
	 */
	this.getExtNum = function(){
		return this.callConfig.extnum;
	};

	/**
	 *  获取当前坐席登录的工号
	 * @returns {string|*}
	 */
	this.getOpNum = function(){
		return this.callConfig.opnum;
	};

	/**
	 *  获取当前坐席的业务组编号
	 * @returns {string|*}
	 */
	this.getGroupId = function(){
		return this.callConfig.groupId;
	};


	/**
	 *  获取全部业务组列表
	 * @returns {string|*}
	 */
	this.getGroups = function(){
		return  JSON.parse(JSON.stringify(this.callConfig.groups));
	};

    this.findAgentByOpNum  = function (opnum){
    	if(_cc.callConfig.agentList == null) return null;

		for (var key in _cc.callConfig.agentList) {
			let item = _cc.callConfig.agentList[key];
            if(item["opnum"] === opnum){
            	//add _arrayIndex property to record index
            	item["_arrayIndex"] = key;
            	return item;
			}
		}
		return null;
	};

	this.updateAgentList = function (agentList) {
		for (var key in agentList) {
			let item = agentList[key];
            var existItem = this.findAgentByOpNum(item["opnum"]);
            if(existItem != null){
				var newStatus = item["agentStatus"];
				var oldStatus = existItem["agentStatus"];
				var logoutTime = item["logoutTime"];
				if(logoutTime > 0){
					//删除元素
					console.info("delete offline user",item["opnum"], "index=", key);
					_cc.callConfig.agentList.splice(existItem["_arrayIndex"], 1);
					continue;
				}
				if(newStatus != oldStatus){
					existItem["agentStatus"] = newStatus;
				}
			}else{
				if(_cc.callConfig.agentList != null) {
					_cc.callConfig.agentList.push(item);
				}
			}
		}
	};

	//连接到呼叫控制服务器
	this.connect = function() {
		// 如果已经在连接中，直接返回
		if (ws && ws.readyState === WebSocket.CONNECTING) {
			console.log('[connect] WebSocket 正在连接中，请勿重复操作');
			return;
		}

		// 先关闭旧的连接，避免重复登录
		if (ws) {
			console.log('[connect] 检测到旧连接存在，先关闭旧连接');
			try {
				ws.close();
			} catch(e) {
				console.error('[connect] 关闭旧连接失败:', e);
			}
			ws = null;
		}

		if ('WebSocket' in window)
			ws = new WebSocket(wsuri);
		else {
			console.log('您的浏览器不支持 websocket，您无法使用本页面的功能!');
			return;
		}
		//收到消息
		ws.onmessage = function(evt) {
			console.log("recv msg from websocket server: ", evt.data);
			var msg = JSON.parse(evt.data);
			console.log("parsed json data:", msg);
			var resp_status = msg["status"];
			switch(resp_status) {
				case 200:
					isConnected = true;
					_cc.callConfig.extnum = msg.object["extnum"];
					_cc.callConfig.opnum = msg.object["opnum"];
					_cc.callConfig.groupId = msg.object["groupId"];
					_cc.callConfig.groups = msg.object["groups"];
					console.log('ipcc 连接成功.', 'connected_ipcc_server');
					// WebSocket 连接成功后自动设置为置忙状态，以便可以外呼
					_cc.setStatus(ccPhoneBarSocket.agentStatusEnum.busy);
					_cc.notifyAll(ccPhoneBarSocket.eventList.ws_connected, msg);
					break;
				default:
					if (parseInt(resp_status) === parseInt(ccPhoneBarSocket.eventList.caller_hangup) ||
						parseInt(resp_status) === parseInt(ccPhoneBarSocket.eventList.CONFERENCE_MODERATOR_HANGUP)) {
						_cc.setCallConnected(false);
						_cc.setCanSendVideoReInvite(false);
						_cc.callConfig.agentList = null;
						_cc.unSubscribeAgentList();
						// 重置呼叫标志
						_cc.isCalling = false;
						console.log("caller_hangup")
					}
					if (parseInt(resp_status) === parseInt(ccPhoneBarSocket.eventList.callee_hangup)) {
						// 重置呼叫标志
						_cc.isCalling = false;
					}
					if (parseInt(resp_status) === parseInt(ccPhoneBarSocket.eventList.callee_answered)) {
						_cc.setCallConnected(true);
						console.log("callee_answered")
					}
					if (parseInt(resp_status) === parseInt(ccPhoneBarSocket.eventList.new_inbound_call)) {
						_cc.setCallConnected(true);
						console.log("new_inbound_call")
					}
					if (parseInt(resp_status) === parseInt(ccPhoneBarSocket.eventList.caller_answered) ||
						parseInt(resp_status) === parseInt(ccPhoneBarSocket.eventList.callee_answered)) {
						if (msg["object"]["callType"] === "audio") {
							_cc.setCanSendVideoReInvite(true);
							_cc.notifyAll(ccPhoneBarSocket.eventList.on_audio_call_connected, "audio call connected.")
							console.log("current callType is audio.")
						}
						if (msg["object"]["callType"] === "video") {
							_cc.setCanSendVideoReInvite(false);
							_cc.notifyAll(ccPhoneBarSocket.eventList.on_video_call_connected, "video call connected.")
							console.log("current callType is video.")
						}
					}

					if (parseInt(resp_status) === parseInt(ccPhoneBarSocket.eventList.customer_channel_hold)) {
						_cc.changeUiOnHold();
					}

					if (parseInt(resp_status) === parseInt(ccPhoneBarSocket.eventList.customer_channel_unhold)) {
						_cc.changeUiOnUnHold();
					}

					if (parseInt(resp_status) === parseInt(ccPhoneBarSocket.eventList.customer_on_hold_hangup)) {
						_cc.changeUiOnUnHold();
						$("#holdBtn").removeClass('on');
						$("#callStatus").text("保持的通话已挂机.");
					}

					if (parseInt(resp_status) === parseInt(ccPhoneBarSocket.eventList.customer_channel_call_wait)) {
						$("#stopCallWait").show();
						$("#doConsultationBtn").hide();
						$("#callStatus").text("客户电话等待中.");
						_cc.showTransferAreaUI();
					}

					if (parseInt(resp_status) === parseInt(ccPhoneBarSocket.eventList.customer_channel_off_call_wait)) {
						$("#stopCallWait").hide();
                        $("#transferCallWait").hide();
						_cc.hideTransferAreaUI();
						$("#callStatus").text("等待的电话已接回.");
					}

                    if (parseInt(resp_status) === parseInt(ccPhoneBarSocket.eventList.inner_consultation_start)) {
                        $("#callStatus").text("咨询已开始.");
                        $("#transferCallWait").show();
                    }

					if (parseInt(resp_status) === parseInt(ccPhoneBarSocket.eventList.inner_consultation_stop)) {
						$("#callStatus").text("咨询已结束.");
						$("#transferCallWait").hide();
					}

                    if (parseInt(resp_status) === parseInt(ccPhoneBarSocket.eventList.customer_on_call_wait_hangup)) {
						$("#stopCallWait").hide();
                        $("#transferCallWait").hide();
						$("#callStatus").text("等待的客户已挂机.");
					}

					if (parseInt(resp_status) === parseInt(ccPhoneBarSocket.eventList.inner_consultation_start)) {
						$("#holdBtn").removeClass('on');
						$("#hangUpBtn").removeClass('on');
						$("#transferBtn").removeClass('on');
					}

					if (parseInt(resp_status) === parseInt(ccPhoneBarSocket.eventList.transfer_call_success)) {
						var extNum = msg["object"]["callee"];
						if(extNum === _cc.getExtNum()) {
							$("#holdBtn").addClass('on');
							$("#hangUpBtn").addClass('on');
							$("#transferBtn").addClass('on');
						}

					}

					if (parseInt(resp_status) === parseInt(ccPhoneBarSocket.eventList.agent_status_data_changed)) {
						if(_cc.subscribeAgentListStarted) {
							if (_cc.callConfig.agentList == null) {
								_cc.callConfig.agentList = JSON.parse(msg.object);
							}else{
								// 更新列表;
                                _cc.updateAgentList(JSON.parse(msg.object));
							}
						}
					}
					_cc.notifyAll(resp_status, msg);
					break;
			}
		};
		//关闭连接时触发
		ws.onclose = function(evt) {
			isConnected = false;
			_cc.notifyAll(ccPhoneBarSocket.eventList.ws_disconnected, "ipccserver 连接断开.");
			console.log("ipcc连接断开.", "disconnected");
			console.log(evt);
			ws.close();
		};
		ws.onopen = function(evt) {
			console.log("ipccserver websocket onopen...");
		};
	};

	//发送消息给呼叫控制服务器
	this.sendMsg = function(jsonObject) {
		console.debug("ws.send:", jsonObject);
		ws.send(JSON.stringify(jsonObject));
	};

	this.changeUiOnHold = function() {
		$("#holdBtnLi").hide();
		$("#unHoldBtnLi").show();
		$("#unHoldBtn").addClass('on');
	};

	this.changeUiOnUnHold = function() {
		$("#holdBtnLi").show();
		$("#holdBtn").addClass('on');
		$("#unHoldBtnLi").hide();
	};

	this.hideTransferAreaUI = function(){
		var transferArea = document.getElementById("transfer_area");
		transferArea.style.display = "none";
	};

	this.showTransferAreaUI = function(){
		var transferArea = document.getElementById("transfer_area");
		transferArea.style.display = "block";
	};

	/**
	 *  设置状态为空闲
	 */
	this.setStatusFree = function(){
		this.setStatus(ccPhoneBarSocket.agentStatusEnum.free);
	};

	/**
	 *  设置状态为忙碌
	 */
	this.setStatusBusy = function(){
		this.setStatus(ccPhoneBarSocket.agentStatusEnum.busy);
	};

	ccPhoneBarSocket.utils = {

		/**
		 * 读取 URL 中的指定查询参数值
		 * @param {string} paramName - 要获取的参数名称
		 * @returns {string|null} 返回参数值，如果不存在则返回 null
		 */
		getQueryParam :	function (paramName) {
			const url = window.location.href; // 获取当前页面 URL
			const params = new URLSearchParams(new URL(url).search); // 创建 URLSearchParams 对象
			return params.get(paramName); // 获取指定参数值
		}
	};

	/**
	 *  座席状态枚举;
	 * @type {{rest: number, calling: number, busy: number, free: number, justLogin: number, meeting: number, train: number}}
	 */
	ccPhoneBarSocket.agentStatusEnum = {

		/**
		 *  刚刚上线，尚未就绪中;
		 */
		"justLogin" : 1,

		/**
		 * 空闲
		 */
		"free"  :  2,

		/**
		* 忙碌
		*/
		"busy"  :  3,

		/**
		 * 小休
		 */
		"busy_rest"  :  31,

		/**
		 * 线下会议
		 */
		"busy_meeting"  :  32,

		/**
		 * 培训
		 */
		"busy_training"  :  33,

		/**
		 * 通话中
		 */
		"incall" : 4,

		/**
		 * 话后处理，填写表单中
		 */
		"fill_form" : 5,

		/**
		 * 电话会议中
		 */
		"conference"  :  6
	};

	//定义视频level-id
	ccPhoneBarSocket.videoLevels = {
		"Smooth" :  { "levelId" : "42e00b",  "description" : "流畅"  },
		"Smooth2" :  { "levelId" : "42e00c",  "description" : "流畅+"  },
		"Smooth3" :  { "levelId" : "42e00d",  "description" : "流畅++"  },
		"Clear" : { "levelId" : "42e014",  "description" : "清晰"  },
		"Clear2" :  { "levelId" : "42e015",  "description" : "清晰+"  },
		"Clear3" :  { "levelId" : "42e016",  "description" : "清晰++"  },
		"HD" :   { "levelId" : "42e01e",  "description" : "高清"  },
		"HD2" :  { "levelId" : "42e01f",  "description" : "高清+"  }
	};


	/**
	 * 系统事件列表;
	 * @type {{}}
	 */
	ccPhoneBarSocket.eventList = {
		// 当音频通话已建立
		"on_audio_call_connected" : "100",
		"on_video_call_connected" : "101",

		// websocketServer连接成功
		"ws_connected": "200",
		// 当前用户已在其他设备登录;
		"user_login_on_other_device" : "201",
		// 用户下线
		"ws_disconnected" : "202",
		// 通话状态发生改变 [监听的数据]
		"call_session_status_data_changed" : "203",
        // 坐席状态列表发生改变
        "agent_status_data_changed" : "205",
		//请求参数错误
		"request_args_error" : "400",

		// unauthorized
		"unauthorized" : "401",

		//服务器内部错误
		"server_error" : "500",
		// 语音编码不匹配
		"server_error_audio_codec_not_match" : "501",
		// 主叫接通
		"caller_answered" : "600",
		//  主叫挂断
		"caller_hangup" : "601",
		// 主叫忙; 上一通电话未挂机
		"caller_busy" : "602",
		//主叫未登录
        "caller_not_login" : "603",
		//主叫应答超时
		"caller_respond_timeout" : "604",
		// 被叫接通
		"callee_answered" : "605",
        // 被叫挂断
		"callee_hangup" : "606",
		//被叫振铃
        "callee_ringing" : "607",
		// 座席状态改变
		"status_changed" : "608",
		// 一个完整的外呼任务结束： [可能尝试了一个或多个网关]
		"outbound_finished" : "611",

		// 预测外呼，分配的来电;
		"PREDICTIVE_CALL_INBOUND" : "612",

         // ACD队列分配的新来电
		"new_inbound_call" : "613",

         // 当前业务组实时排队人数
		"acd_group_queue_number" : "615",


		/**
		 * 收到转接的来电请求
		 */
		"transfer_call_recv" :  616,

		/**
		 * 锁定坐席失败
		 */
		"lock_agent_fail" :  617,

		/**
		 * 通话已经转接成功
		 */
		"transfer_call_success" :  618,

		/**
		 * 产生asr语音识别结果
		 */
		"asr_result_generate" :  619,

		/**
		 * ASR语音识别流程结束（坐席侧）
		 */
		"asr_process_end_agent" :  620,

		/**
		 * ASR语音识别流程结束（客户侧）
		 */
		"asr_process_end_customer" :  621,

		"asr_process_started" : 622,

		/**
		 * customer call session hold.
		 */
		"customer_channel_hold" : 623,

		/**
		 * customer call session unHold.
		 */
		"customer_channel_unhold" : 624,

		/**
		 * customer call session on hold is hangup.
		 */
		"customer_on_hold_hangup" : 625,

		"inner_consultation_request" : 626,

		/**
		 * customer call session on call-wait.
		 */
		"customer_channel_call_wait" : 627,

		/**
		 * customer call session off call-wait.
		 */
		"customer_channel_off_call_wait" : 628,

		/**
		 * customer call session on call-wait is hangup.
		 */
		"customer_on_call_wait_hangup" : 629,

		/**
		 *  extension on line event
		 */
		"extension_on_line" : 630,

		/**
		 * extension off line event
		 */
		"extension_off_line" : 631,

        /**
         * Notify the agent that the call consultation has started.
         */
        "inner_consultation_start" : 632,

        /**
         *  Notify the agent that the call consultation has stopped.
         */
        "inner_consultation_stop" : 633,


	    /**
		* 多人电话会议，重复的被叫 ,
		*/
		"conference_repeat_callee"  :  660 ,

		 /**
		 * 多人电话会议，呼叫成员超时 ,
		 */
		 "CONFERENCE_CALL_MODERATOR_TIMEOUT"  :  661 ,

		/**
		 * 多人电话会议，成员接通 ,
		 */
		"CONFERENCE_MEMBER_ANSWERED"  :  662 ,


		/**
		 * 多人电话会议，成员挂机 ,
		 */
		"CONFERENCE_MEMBER_HANGUP"  :  663 ,

		/**
		 * 多人电话会议，成员禁言成功 ,
		 */
		"CONFERENCE_MEMBER_MUTED_SUCCESS"  :  666 ,


		/**
		 * 多人电话会议，成员禁言失败 ,
		 */
		"CONFERENCE_MEMBER_MUTED_FAILED"  : 665  ,

		/**
		 * 多人电话会议，成员解除禁言成功 ,
		 */
		"CONFERENCE_MEMBER_UNMUTED_SUCCESS"  :  667 ,


		/**
		 * 多人电话会议，成员解除禁言失败 ,
		 */
		"CONFERENCE_MEMBER_UNMUTED_FAILED"  : 668  ,

		/**
		 * 多人电话会议，会议成员不存在，无法执行相关操作：
		 */
		"CONFERENCE_MEMBER_NOT_EXISTS"  : "669"  ,

		/**
		 * 多人电话会议，主持人重置会议 ,
		 */
		"CONFERENCE_MODERATOR_RESET"  : "670"  ,

		/**
		 * 多人电话会议，主持人接通 ,
		 */
		"CONFERENCE_MODERATOR_ANSWERED"  : "671"  ,


		/**
		 * 多人电话会议，主持人挂机，会议结束 ,
		 */
		"CONFERENCE_MODERATOR_HANGUP"  : "672",

		/*
		 * 成员视频禁用成功
		 */
		"CONFERENCE_MEMBER_VMUTED_SUCCESS" : "674",

		/*
		 * 成员解除视频禁用成功
		 */
		"CONFERENCE_MEMBER_UnVMUTED_SUCCESS" : "676",

		/**
		 * 多人电话会议，成员解除视频禁用失败;
		 */
		"CONFERENCE_MEMBER_UnVMUTED_FAILED"  : "677",

		/**
		 * 成功把通话转接到多人视频会议
		 */
		"CONFERENCE_TRANSFER_SUCCESS_FROM_EXISTED_CALL"  :  "678",

		/**
		 *  outbound start event
		 */
		"OUTBOUND_START" : "679"
	};

	this.createIframe = function(src){
        var _iframe = document.createElement("iframe");
        _iframe.style.width = '0';
        _iframe.style.height = '0';
        _iframe.style.margin = '0';
        _iframe.style.padding = '0';
        _iframe.style.overflow = 'hidden';
        _iframe.style.border = 'none';
        _iframe.src = src;
        document.body.appendChild(_iframe);
        _cc.iframe = _iframe;
    };

    this.openSoftPhone = function (){
		//打开软电话
		var softPhoneUrl = "http://127.0.0.1:" + _cc.callConfig["localHostProxyPort"] +
		                   "/autoSetExtension?server=" + encodeURIComponent(_cc.callConfig["fsServer"].split(':')[0]) +
						   "&port=" + _cc.callConfig["fsServer"].split(':')[1] +
						   "&extnum=" + _cc.callConfig["extnum"] +
						   "&pass=" + encodeURIComponent(_cc.callConfig["extPassword"]) +
						   "&phoneType=" + _cc.callConfig["phoneType"] +
						   "&version=" + encodeURIComponent(_cc.callConfig["localHostProxyVersion"]) +
						   "&webPhoneUrl=" + encodeURIComponent(_cc.callConfig["webPhoneUrl"]) +
						   "";
	  console.log("softPhoneUrl:", softPhoneUrl);
      _cc.iframe.src = softPhoneUrl;
	};

	/**
	 * 设置座席状态
	 * @param status  agentStatusEnum
	 */
	this.setStatus = function (status) {
		var cmdInfo = {};
		cmdInfo.action="setAgentStatus";
		cmdInfo.body = {"cmd" : "setStatus", "args" : { "status" : status } };
		ws.send(JSON.stringify(cmdInfo));
	};

	//注销登录;
	this.logOff = function () {
		var cmdInfo = {};
		cmdInfo.action="setAgentStatus";
		cmdInfo.body = {"cmd" : "disconnect", "args" : { "cause": "disconnect request from js client." }  };
		ws.send(JSON.stringify(cmdInfo));
	};

	/**
	 *  在咨询失败的情况下使用该按钮，接回处于等待中的电话
	 */
	this.stopCallWaitBtnClickUI = function () {
		var cmd = {};
		cmd.action="callWait";
		cmd.body = {"cmd" : "stop", "args" : {} };
		ws.send(JSON.stringify(cmd));
	};

    /**
     * 在咨询成功的情况下使用该按钮，把电话转接给专家坐席。
     */
	this.transferCallWaitBtnClickUI = function () {
        this.callControl("transferCallWait", {})
    };

	this.consultationBtnClickUI = function () {
        let transferType = "outer";
        let phoneNumber = $("#externalPhoneNumber").val().trim();
        if (phoneNumber === "") {
			transferType = "inner";
            var groupId = $("#transfer_to_groupIds").val();
            if ($.trim(groupId) == "") {
                alert("请选择业务组!");
                $("#transfer_to_groupIds").focus();
                return;
            }
            var member = $("#transfer_to_member").val();
            if ($.trim(member) == "") {
                alert("请选择要咨询的坐席成员!");
                $("#transfer_to_member").focus();
                return;
            }

            var selectText = $('#transfer_to_member option:selected').text();
            if (selectText.indexOf("空闲") == -1) {
                alert("请选择空闲的坐席成员!");
                $("#transfer_to_member").focus();
                return;
            }

            if (member == this.getOpNum()) {
                alert("不能咨询自己，请选择其他坐席成员!");
                return;
            }
            phoneNumber = member;
        }
        this.callControl("consultation", {"to": phoneNumber, "transferType": transferType});

    };

	/**
	 *  处理通话转接按钮点击事件
	 */
	this.transferBtnClickUI = function() {
	    let transferType = "outer";
	    let phoneNumber = $("#externalPhoneNumber").val().trim();
        if(phoneNumber === "") {
            transferType = "inner";
            var groupId = $("#transfer_to_groupIds").val();
            if ($.trim(groupId) === "") {
                alert("请选择转接的业务组!");
                $("#transfer_to_groupIds").focus();
                return;
            }
            var member = $("#transfer_to_member").val();
            if ($.trim(member) === "") {
                alert("请选择转接的坐席成员!");
                $("#transfer_to_member").focus();
                return;
            }

            var selectText = $('#transfer_to_member option:selected').text();
            if (selectText.indexOf("空闲") === -1) {
                alert("请选择空闲的坐席成员!");
                $("#transfer_to_member").focus();
                return;
            }
            if (member === this.getOpNum()) {
                alert("不能转给自己，请选择其他坐席成员!");
                return;
            }
            phoneNumber = member;
        }
        this.transferCall(phoneNumber, transferType);
	};

	/**
	 *  处理通话转接
     *  @param userCodeOrPhone 工号或者电话号码
     *  @param transferType 转接类型：工号还是外部号码（inner or outer）
	 */
	this.transferCall = function(userCodeOrPhone, transferType) {
	    if(transferType === "inner") {
            if (userCodeOrPhone !== this.getOpNum()) {
                this.callControl("transferCall", {"to": userCodeOrPhone, "transferType" : "inner" })
            } else {
                console.error("cant not transfer call to yourself.")
            }
        }else{
            this.callControl("transferCall", {"to": userCodeOrPhone, "transferType" : "outer" })
        }
	};

	//挂机
	this.hangup = function() {
		this.callControl("endSession", {})
	};

	// 呼叫控制相关操作;
	this.callControl = function(action, argsObject){
		var sessionControl = {};
		sessionControl.action="call";
		sessionControl.body = {"cmd" : action, "args" : argsObject };
		ws.send(JSON.stringify(sessionControl));
	};

	this.checkCallConfirmed = function () {
		if(!_cc.getIsConnected()){
			console.log('请先上线.');
			return false;
		}
		if(!_cc.getCallConnected()){
			console.log('当前没有通话.');
			return false;
		}
		return true;
	};

	/**
	 *  send and play mp4 video file.
	 */
	this.sendVideoFile = function (mp4FilePath) {
		if(!_cc.checkCallConfirmed()){
			return false;
		}
		if(typeof(mp4FilePath) == "undefined" || mp4FilePath.trim().length === 0){
			console.log("Parameter mp4FilePath is missing!")
			return false;
		}
		this.callControl(
			"playMp4File",
			{ "mp4FilePath" : mp4FilePath }
		);
		return true;
	};

	/**
	 *  发起视频通话邀请
	 */
	this.reInviteVideoCall = function(){
        if(!_cc.checkCallConfirmed()){
        	return false;
		}
		if(!_cc.getCanSendVideoReInvite()){
			console.log('cant not send video reInvite. ',
				'Precondition is:  Call is connected and  callType is audio.');
			return false;
		}
		this.callControl(
			"reInviteVideo",
			{}
		);
		return true;
	};

	/**
	 *  发起外呼
	 * @param phoneNumber 被叫号码
	 * @param callType 通话类型:视频通话、音频通话
	 * @param videoLevel 视频通话的profile-level-id
	 */
	this.call = function(phoneNumber, callType, videoLevel){
		// 防止重复调用
		if(_cc.isCalling) {
			console.log('正在呼叫中，请勿重复操作');
			return;
		}

		if(typeof(videoLevel) == "undefined" || videoLevel.trim().length === 0){
			videoLevel = ccPhoneBarSocket.videoLevels.HD.levelId;
			console.log("auto default set videoLevel=", videoLevel);
		}
		if(typeof(callType) == "undefined" || callType.trim().length === 0){
			callType = "audio";
			console.log("auto default set callType=", callType);
		}

		console.log("call config videoLevel=" + videoLevel + ", callType=" + callType);

		if(phoneNumber==null || phoneNumber.length===0) {
			console.log('请输入外呼号码！');
			return;
		}
		if(phoneNumber.trim().length < 3){
			alert('请输入正确格式的外呼号码！');
			return;
		}
		if(!_cc.getIsConnected()){
			console.log('请先上线.');
			return;
		}
		let outboundInfo = {
			"gatewayList": _cc.callConfig.gatewayList,
			'destPhone': phoneNumber,
			'gatewayEncrypted' : _cc.callConfig.gatewayEncrypted,
			'useSameAudioCodeForOutbound' : _cc.callConfig.useSameAudioCodeForOutbound,
			'callType' :  callType,
			'videoLevel' : videoLevel
		};
		this.callControl(
			"startSession",
			outboundInfo
		);
		// 设置呼叫标志
		_cc.isCalling = true;
	};

	this.callEx = function(phoneNumber){
		if(phoneNumber == null || phoneNumber.length === 0) {
			console.log('请输入外呼号码！');
			return;
		}
		if(!_cc.getIsConnected()){
			_cc.connect();
			_cc.on(ccPhoneBarSocket.eventList.ws_connected, function(){
				_cc.off(ccPhoneBarSocket.eventList.ws_connected); //取消事件订阅
				_cc.call(phoneNumber);
			});
			return;
		}
		_cc.call(phoneNumber);
	 };


	/************************  以下是网页工具条ui代码   ************************/

	/**
	 *  根据服务器响应状态码去查找action
	 * @param code
	 * @returns {string}
	 */
	ccPhoneBarSocket.findItemByCode = function(code){
		for(var item in ccPhoneBarSocket.eventListWithTextInfo ){
			if(ccPhoneBarSocket.eventListWithTextInfo[item].code === code){
				return ccPhoneBarSocket.eventListWithTextInfo[item];
			}
		}
	};

	/**
	 *  服务器响应状态枚举值;
	 */
	  ccPhoneBarSocket.eventListWithTextInfo = {
		"ws_connected": { "code": 200,  msg:"已签入",
			btn_text:[{id:"#onLineBtn",name:"签出"}],
			enabled_btn:['#setFree','#callBtn','#onLineBtn', '#consultationBtn']
		},
		"ws_disconnected": { "code" : 202, msg:"服务器连接断开",
			btn_text:[{id:"#onLineBtn",name:"签入"}],
			enabled_btn:['#onLineBtn']
		},
		"user_login_on_other_device": { "code" : 201, msg:"用户已在其他设备登录",
			btn_text:[{id:"#onLineBtn",name:"签入"}],
			enabled_btn:['#onLineBtn']
		},
		"request_args_error":{ "code" : 400, msg:"客户端请求参数错误",
			btn_text:[],
			enabled_btn:[]
		},
		"server_error":{ "code" : 500, msg:"服务器内部错误",
			btn_text:[],
			enabled_btn:[]
		},
		"caller_answered":{ "code" : 600, msg:"分机已接通",
			btn_text:[],
			enabled_btn:['#resetStatus', '#hangUpBtn', '#transferBtn', '#holdBtn', '#consultationBtn']
		},
		"caller_hangup":{ "code" : 601, msg:"分机已挂断",
			btn_text:[],
			enabled_btn:['#onLineBtn', '#resetStatus', '#callBtn', '#setFree', '#consultationBtn' ]
		},
		"caller_busy":{ "code" : 602, msg:"分机忙,上一通电话未挂断",
			btn_text:[],
			enabled_btn:['#onLineBtn', '#resetStatus', '#callBtn', '#setFree', '#consultationBtn']
		},
		"caller_not_login":{ "code" : 603, msg:"分机未登录，请检查",
			btn_text:[],
			enabled_btn:['#onLineBtn', '#resetStatus', '#callBtn', '#setFree', '#consultationBtn']
		},
		"caller_respond_timeout":{ "code" : 604, msg:"分机未应答超时，请重新打开分机",
			btn_text:[],
			enabled_btn:['#onLineBtn', '#resetStatus', '#callBtn', '#setFree', '#consultationBtn']
		},
		"callee_answered":{ "code" : 605, msg:"被叫已接通",
			btn_text:[],
			enabled_btn:['#resetStatus', '#hangUpBtn', '#transferBtn', '#holdBtn', '#consultationBtn' ]
		},
		"callee_hangup":{ "code" : 606, msg:"通话结束",
			btn_text:[],
			enabled_btn:['#onLineBtn', '#resetStatus', '#callBtn', '#setFree' , '#consultationBtn']
		},
		"callee_ringing":{ "code" : 607, msg:"被叫振铃中",
			btn_text:[],
			enabled_btn:['#resetStatus', '#hangUpBtn', '#transferBtn', '#consultationBtn']
		},
		"status_changed":{ "code" : 608, msg:"状态已改变",
			btn_text:[],
			enabled_btn:[ ]
		},
		"free":{ "code" : 0, msg:"空闲中",
			btn_text:[],
			enabled_btn:['#setBusy','#onLineBtn', '#consultationBtn']
		},
		"busy":{ "code" : 1, msg:"忙碌",
			btn_text:[],
			enabled_btn:['#setFree', '#onLineBtn',  '#callBtn', '#consultationBtn']  //  '#transferBtn'
		},
		"customer_channel_hold" : { "code" : 623, msg:"通话已保持.",
			btn_text:[],
			enabled_btn:['#setFree',  '#callBtn', '#unHoldBtn', '#consultationBtn' ]
		},
	   "customer_channel_unhold" : { "code" : 624, msg:"通话已接回.",
			  btn_text:[],
			  enabled_btn:[ '#hangUpBtn', '#holdBtn' ]
		}
	};

	ccPhoneBarSocket.phone_buttons = ['#setFree', '#setBusy', '#callBtn','#hangUpBtn' , '#resetStatus' ,'#onLineBtn', '#transferBtn', '#holdBtn', '#unHoldBtn', '#consultationBtn'];

	// 更新状态显示
	this.updatePhoneBar = function (msg, status_key) {
		if(!_cc.callConfig.useDefaultUi){
			console.log("callConfig.useDefaultUi = false ， 已禁用默认ui工具条按钮.");
			return;
		}

		if (msg) {
			$("#callStatus").text(msg.msg);
		}
		var status_info = ccPhoneBarSocket.findItemByCode(status_key);
		if (!status_info) {
			return;
		}

		if(status_info.code === ccPhoneBarSocket.eventListWithTextInfo.status_changed.code){
			if(msg.object.status === ccPhoneBarSocket.agentStatusEnum.free){
				status_info = ccPhoneBarSocket.eventListWithTextInfo.free;
			}else{
				status_info = ccPhoneBarSocket.eventListWithTextInfo.busy;
			}
		}
		// 判断当前是否为状态改变的事件;
		// 显示预设的消息;
		var msgSet = status_info.msg;

		if(msgSet && msgSet.length > 0){
			$("#callStatus").text(msgSet);
		}

		var btn_text = status_info.btn_text;
		var enabled_btn = status_info.enabled_btn;
		if (btn_text) {
			$.each(btn_text, function (i, d) {
				$(d.id).next().text(d.name);
			});
		}

		if (enabled_btn.length === 0) {
			return;
		}

		var all_btn = ccPhoneBarSocket.phone_buttons;
		for (var i in all_btn) {
			var idx = $.inArray(all_btn[i], enabled_btn);
			if (idx < 0) {
				$(all_btn[i]).removeClass('on');
			} else {
				$(enabled_btn[idx]).addClass('on');
			}
		}
	};

	/**
	 *  初始化电话工具条ui按钮;
	 */
	this.initPhoneBarUI = function () {

		window.onbeforeunload = function () {
			if (!confirm('关闭网页将导致您无法接听电话，确定要关闭吗 ?')) return false;
		};

		$("#unHoldBtnLi").hide();

		if(!_cc.callConfig.useDefaultUi){
			console.log("callConfig.useDefaultUi = false ， 已禁用默认ui工具条按钮.");
			return;
		}

        $('#conferenceBtn').on('click', function () {
                if(!_cc.getIsConnected()){
                    console.log('请先上线.');
                    return;
                }
                var confObjId = document.getElementById("conference_area");
                if(confObjId.style.display === "block"){
					confObjId.style.display = "none";
				}else{
					confObjId.style.display = "block";
				}

        });

		$('#callBtn').on('click', function () {
			if ($(this).hasClass('on')) {
				var destPhone = $.trim($("#ccphoneNumber").val());
				var videoLevel = document.getElementById("videoLevelSelect").value;
				var callType = document.forms[0].callType.value;
				_cc.call(destPhone, callType,  videoLevel);
			}
		});
		$('#setFree').on('click', function () {
			if ($(this).hasClass('on')) {
				_cc.setStatus(ccPhoneBarSocket.agentStatusEnum.free);
			}
		});
		$('#setBusy').on('click', function () {
			if ($(this).hasClass('on')) {
				_cc.setStatus(ccPhoneBarSocket.agentStatusEnum.busy);
			}
		});

		$('#setBusySubList').on('change', function () {
			 let itemValue = $('#setBusySubList').val();
			 console.log('set busy subStatus', itemValue);
			 _cc.setStatus(itemValue);
		});

		$('#hangUpBtn').on('click', function () {
			if ($(this).hasClass('on')) {
				_cc.hangup();
			}
		});

		$('#holdBtn').on('click', function () {
			if ($(this).hasClass('on')) {
				_cc.holdCall();
			}
		});

		$('#unHoldBtn').on('click', function () {
			if ($(this).hasClass('on')) {
				_cc.unHoldCall();
			}
		});

		$("#doTransferBtn").hide();

		/**
		 * 填充业务组选项
		 * 注意：该函数仅用于原始 HTML 版本，Vue + Element UI 版本中由 Vue 组件自行处理
		 */
		function populateGroupIdOptions() {
			var groups = _cc.callConfig.groups;
			if (groups) {
				var selectObj = document.getElementById("transfer_to_groupIds");
				if (selectObj) {
					// 检查是否为原生 select 元素
					if (selectObj.tagName.toLowerCase() === 'select') {
						// 清空现有选项（保留第一个"请选择"）
						var firstOption = selectObj.options[0];
						selectObj.innerHTML = '';
						selectObj.add(firstOption);

						// 添加业务组选项
						for (var i = 0; i < groups.length; i++) {
							var group = groups[i];
							var option = document.createElement("option");
							option.value = group.groupId;
							option.text = group.bizGroupName;
							selectObj.add(option);
						}

						// 默认选中第一个
						if (groups.length > 0 && selectObj.options.length > 1) {
							selectObj.selectedIndex = 1;
						}
					}
					// 如果是 el-select 组件，则不处理，由 Vue 数据绑定自动更新
				}
			}
		}

		$('#transferBtn').on('click', function () {
			if ($(this).hasClass('on')) {
				if(!_cc.getIsConnected()){
					console.log('请先上线.');
					return;
				}
				var transferArea = document.getElementById("transfer_area");
				if(transferArea.style.display === "block"){
					transferArea.style.display = "none";
					_cc.unSubscribeAgentList();
					$("#doTransferBtn").hide();
					$("#doConsultationBtn").hide();
				}else{
					transferArea.style.display = "block";
					populateGroupIdOptions();
					// 不再自动订阅坐席状态列表，由外部控制
					// _cc.subscribeAgentList();
					$("#doTransferBtn").show();
					$("#doConsultationBtn").hide();
				}
			}
		});

        $("#stopCallWait").hide();
        $("#transferCallWait").hide();
		$("#doConsultationBtn").hide();
		$('#consultationBtn').on('click', function () {
			if ($(this).hasClass('on')) {
				if(!_cc.getIsConnected()){
					console.log('请先上线.');
					return;
				}
				var transferArea = document.getElementById("transfer_area");
				if(transferArea.style.display === "block"){
					transferArea.style.display = "none";
					_cc.unSubscribeAgentList();
					$("#doConsultationBtn").hide();
					$("#doTransferBtn").hide();
				}else{
					transferArea.style.display = "block";
					populateGroupIdOptions();
					// 不再自动订阅坐席状态列表，由外部控制
					// _cc.subscribeAgentList();
					$("#doConsultationBtn").show();
					$("#doTransferBtn").hide();
				}
			}
		});

		$('#onLineBtn').on('click', function () {
			if ($(this).hasClass('on')) {
				if (_cc.getIsConnected()) {
					_cc.disconnect();
				} else {
					_cc.connect();
				}
			}else {
				alert('当前不允许签出!');
			}
		});

		$('#resetStatus').on('click', function () {
			window.onbeforeunload = null;
			location.reload();
		});

		//拨号文本框;收到键盘回车事件之后立即拨号
		$("#ccphoneNumber").keydown(function (e) {
			var curKey = e.which;
			if (curKey === 13) {
				var destPhone = $.trim($("#ccphoneNumber").val());
				var videoLevel = document.getElementById("videoLevelSelect").value;
				var callType = document.forms[0].callType.value;
				_cc.call(destPhone,callType, videoLevel);
				return false;
			}
		});

		//ESC按键挂机功能支持
		$(document).keyup(function (e) {
			var key = e.which;
			if (key === 27) {
				console.log('按下了ESC键, 即将发送挂机指令.');
				if(_cc.getIsConnected()){
					if(_cc.callConfig["useDefaultUi"]) {
						if ($('#hangUpBtn').hasClass('on')) {
							_cc.hangup();
						}
					}else{
						_cc.hangup();
					}
				}
			}
		});
	};

	/**
	 *  保持通话
	 */
	this.holdCall = function(){
		var cmd = {};
		cmd.action="callHold";
		cmd.body = {"cmd" : "hold", "args" : {} };
		ws.send(JSON.stringify(cmd));
	};

	/**
	 *  接回保持的通话
	 */
	this.unHoldCall = function(){
		var cmd = {};
		cmd.action="callHold";
		cmd.body = {"cmd" : "unhold", "args" : {} };
		ws.send(JSON.stringify(cmd));
	};

	/**
	 *  订阅坐席状态列表
	 */
	this.subscribeAgentList = function(){
		var cmd = {};
		cmd.action="pollAgentList";
		cmd.body = {"cmd" : "subscribe", "args" : {} };
		ws.send(JSON.stringify(cmd));
		_cc.subscribeAgentListStarted = true;
	};

	/**
	 *  取消订阅坐席状态列表
	 */
	this.unSubscribeAgentList = function(){
		if(_cc.subscribeAgentListStarted) {
			_cc.subscribeAgentListStarted = false;
			_cc.callConfig.agentList = null;
			var cmd = {};
			cmd.action = "pollAgentList";
			cmd.body = {"cmd": "unSubscribe", "args": {}};
			ws.send(JSON.stringify(cmd));
		}
	};

	/*************************  以下是电话会议相关  ***************************/

	/**
	 *  启动会议； 仅限使用默认UI场景下使用;
	 */
	this.conferenceStartBtnUI = function(customerName){
		var callType = document.getElementById("conf_call_type").value;
		var confTemplate = document.getElementById("conf_template").value;
		var layOut = document.getElementById("conf_layout").value;

		_cc.setStatusBusy();

		// 禁用外呼按钮
		$("#callBtn").removeClass('on');

		// 禁用置闲按钮
		$("#setFree").removeClass('on');

		// 禁用签出按钮
		$("#onLineBtn").removeClass('on');

		document.getElementById("startConference").setAttribute("disabled", "true");

		if(_cc.getCallConnected()) {
			let tips = "是否把当前通话转换为会议 ?";
			console.log(tips);
			if(confirm(tips)) {
				_cc.transferToConference(layOut, confTemplate, callType, customerName);
			}else{
				document.getElementById("startConference").removeAttribute("disabled");
			}
		}else {
			_cc.conferenceStart(layOut, confTemplate, callType);
		}
	};

	/**
	 *  添加会议成员； 仅限使用默认UI场景下使用;
	 */
	this.conferenceAddMemberBtnUI = function (reInvite, memberPhoneParam,  memberNameParam) {
		var memberName = "";
		var memberPhone = "";
		var memberCallType = $.trim(document.getElementById("member_call_type").value);
		var memberVideoLevel = $.trim(document.getElementById("member_video_level").value);

		if(reInvite === 0) {
			memberName = $("#member_name").val();
			memberPhone = $("#member_phone").val();
			if (memberName.length === 0 || $.trim(memberName) === "") {
				alert('请填写参会者姓名!');
				return;
			}
			if (memberPhone.length === 0 || $.trim(memberPhone) === "") {
				alert('请填写参会者手机号!');
				return;
			}

			memberName = $.trim(memberName);
			memberPhone = $.trim(memberPhone);
			// 使用会员成员html模版添加新成员
			var templateObj = document.getElementById("conf_member_template");

			var existMember = document.getElementById("conf_member_" + memberPhone) != null;
			if (existMember) {
				alert('会议成员已经存在，请不要重复添加!');
				return;
			}

			var memberHtmlItem = templateObj.innerHTML;
			memberHtmlItem = memberHtmlItem.replace(new RegExp("{member_name}", "gm"), memberName);
			memberHtmlItem = memberHtmlItem.replace(new RegExp("{member_phone}", "gm"), memberPhone);
			memberHtmlItem = memberHtmlItem.replace(new RegExp("{member_status}", "gm"), "即将呼叫");

			var li = document.createElement("li");
			li.setAttribute("id", "conf_member_" + memberPhone);
			li.setAttribute("class", "conf_member_item_row");
			li.innerHTML = memberHtmlItem;

			_cc.insertAfter(li, templateObj);

			$("#member_name").val('');
			$("#member_phone").val('');
		}else{
			memberName = memberNameParam;
			memberPhone = memberPhoneParam;
		}

		// 隐藏 mute及 vmute按钮
		var memberItemId = "#conf_member_" + memberPhone;
		$(".conf_mute", $(memberItemId)).find("img").hide();
		$(".conf_vmute", $(memberItemId)).find("img").hide();
		$(".conf_re_invite", $(memberItemId)).hide();
		$(".conf_status", $(memberItemId)).html("即将呼叫");

		_cc.conferenceAddMembers( [
			{"name": memberName, "phone": memberPhone, "callType" : memberCallType,  "videoLevel": memberVideoLevel}
		]);
	};

	/**
	 *  从现有通话添加会议成员；
	 */
	this.conferenceAddMemberFromExistCall = function (memberName, memberPhone) {
		if (memberName.length === 0 || $.trim(memberName) === "") {
			alert('请填写参会者姓名!');
			return;
		}
		if (memberPhone.length === 0 || $.trim(memberPhone) === "") {
			alert('请填写参会者手机号!');
			return;
		}
		memberName = $.trim(memberName);
		memberPhone = $.trim(memberPhone);

		// 使用html模版添加新成员
		var templateObj = document.getElementById("conf_member_template");
		var existMember = document.getElementById("conf_member_" + memberPhone) != null;
		if (existMember) {
			alert('会议成员已经存在，请不要重复添加!');
			return;
		}

		var memberHtmlItem = templateObj.innerHTML;
		memberHtmlItem = memberHtmlItem.replace(new RegExp("{member_name}", "gm"), memberName);
		memberHtmlItem = memberHtmlItem.replace(new RegExp("{member_phone}", "gm"), memberPhone);
		memberHtmlItem = memberHtmlItem.replace(new RegExp("{member_status}", "gm"), "即将呼叫");
		var li = document.createElement("li");
		li.setAttribute("id", "conf_member_" + memberPhone);
		li.setAttribute("class", "conf_member_item_row");
		li.innerHTML = memberHtmlItem;
		_cc.insertAfter(li, templateObj);

		// 隐藏 mute及 vmute按钮
		var memberItemId = "#conf_member_" + memberPhone;
		$(".conf_mute", $(memberItemId)).find("img").show();
		$(".conf_vmute", $(memberItemId)).find("img").show();
		$(".conf_re_invite", $(memberItemId)).hide();
		$(".conf_status", $(memberItemId)).html("通话中").css("color", "green");
	};

	/**
	 *  通话转为会议
	 * @param layOut
	 * @param confTemplate
	 * @param callType
	 * @param customerName
	 */
	this.transferToConference = function (layOut, confTemplate, callType, customerName) {
		console.log("try to transferToConference: ", layOut, confTemplate, callType, customerName);
		_cc.callControl(
			"transferToConference",
			{
				"layOut": layOut,
				'callType': callType,
				'confTemplate': confTemplate,
				'customerName' : customerName
			}
		);
	};


	/**
	 *  主持人启动电话会议
	 * @param layOut 会议布局
	 * @param confTemplate 会议模版
	 * @param callType 会议类型
	 */
	this.conferenceStart = function(layOut, confTemplate, callType) {
		console.log("正常发起多方通话");
		var cmd = {};
		cmd.action = "conference";
		cmd.body = {"method": "startconf", "args": {
				"layOut": layOut,
				'callType': callType,
				'confTemplate': confTemplate
			}};
		ws.send(JSON.stringify(cmd));
	};


	/**
	 *  VMute会议成员（不显示视频）;
	 **/
	this.conferenceVMuteMember = function(members) {
		// single phone
		if(typeof(members) === "string") {
			this.conferenceControl("vmute",
				[
					{"phone": members}
				]
			);
		}else{
			// multiple phones array, e.g.: [  {"phone": '15005600321'}, {"phone": '15005600323'} ]
			this.conferenceControl("vmute", members);
		}
	};


	/**
	 *  UnVMute会议成员（显示视频）;
	 **/
	this.conferenceUnVMuteMember = function(members) {
		// single phone
		if(typeof(members) === "string") {
			this.conferenceControl("unvmute",
				[
					{"phone": members}
				]
			);
		}else{
			// multiple phones array, e.g.: [  {"phone": '15005600321'}, {"phone": '15005600323'} ]
			this.conferenceControl("unvmute", members);
		}
	};

	/**
	 *  禁言会议成员
	 **/
	this.conferenceMuteMember = function(members) {
		// single phone
		if(typeof(members) === "string") {
			this.conferenceControl("mute",
				[
					{"phone": members}
				]
			);
		}else{
			// multiple phones array, e.g.: [  {"phone": '15005600321'}, {"phone": '15005600323'} ]
			this.conferenceControl("mute", members);
		}
	};

	/**
	 *  解禁会议成员
	 **/
	this.conferenceUnMuteMember = function(members) {
		// single phone
		if(typeof(members) === "string") {
			this.conferenceControl("unmute",
				[
					{"phone": members}
				]
			);
		}else{
			// multiple phones array, e.g.: [  {"phone": '15005600321'}, {"phone": '15005600323'} ]
			this.conferenceControl("unmute", members);
		}
	};

	/**
	 *  增加会议成员
	 **/
	this.conferenceAddMembers = function(members) {
		this.conferenceControl("add", members)
	};


	/**
	 *  移除会议成员
	 **/
	this.conferenceRemoveMembers = function(members) {
		// single phone
		if(typeof(members) === "string") {
			var memberItemObj = $("#conf_member_" + members);
			if($(".conf_status", memberItemObj).text() === "通话中") {
				this.conferenceControl("remove",
					[
						{"phone": members}
					]
				);
			}
			memberItemObj.remove();
		}else{
			// multiple phones array, e.g.: [  {"phone": '15005600321'}, {"phone": '15005600323'} ]
			this.conferenceControl("remove", members);
		}
	};

	/**
	 *  结束电话会议
	 **/
	this.conferenceEnd = function() {
		this.conferenceControl("endconf", [])
	};


	/**
	 *  电话会议控制相关操作
	 * @param action 操作
	 * @param phoneList 会议成员
	 */
	this.conferenceControl = function (action, phoneList) {
		var cmd = {};
		cmd.action = "conference";
		cmd.body = { "method": action, "memberList": phoneList };
		ws.send(JSON.stringify(cmd));
	};

    /*************************  以下是通话监听相关  ***************************/

    /**
     *   拉取监听的通话列表
     */
    this.callMonitorDataPull = function (){
        var cmd = {};
        cmd.action = "monitorData";
        cmd.body = {};
        ws.send(JSON.stringify(cmd));
    };

	/**
	 *   拉取排队中的电话列表
	 */
	this.inboundCallQueuePull = function (){
		var cmd = {};
		cmd.action = "inboundMonitorData";
		cmd.body = {};
		ws.send(JSON.stringify(cmd));
	};

    // 构造通话监听参数
    this.monitorControl = function(action, argsObject){
        var sessionControl = {};
        sessionControl.action="callMonitor";
        sessionControl.body = {"cmd" : action, "args" : argsObject };
        ws.send(JSON.stringify(sessionControl));
    };

    /**
     * 通话监听
     * @param { 通话id } callId
     * @returns
     */
    this.callMonitorStart = function(callId){
        if(callId == null || callId.length === 0) {
            console.log('请提供待监听电话的 callId ！');
            return;
        }

        if(!_cc.getIsConnected()){
            console.log('请先上线.');
            return;
        }

        this.monitorControl(
            "startMonitoring",
            {
                'callSpyId': callId
            }
        );
    };


    /**
     * 结束监听
     */
    this.callMonitorEnd = function(){
        if(!_cc.getIsConnected()){
            console.log('请先上线.');
            return;
        }

        this.monitorControl(
            "endMonitoring",{}
        );
    };

}

export default ccPhoneBarSocket;

