/**********************************************************************
* CXMLClientKf事件说明
***********************************************************************/
/*
OnLogin(errCode)
OnSrvRsp(errCode)
OnRecvStaffList(errCode, staffArray)
OnRecvInnerTalkMsg(srvid, kfName, isBroadcast, msg)
OnRecvVisitorList(visitorArray)
OnVisitorOnline(visitor)
OnVisitorOffline(visitor)
OnVisitorStatusChange(visitor)
OnTrace(vid, traceArray)
OnLinkOpen(visitor, lastTalk)
OnLinkClose(visitor)
OnRecvTalkMsg(tid, msg)
OnTyping(tid, msg)
OnRecvFile(tid, fileName)
OnRecvOnlineStaff(gid, staffArray)
OnSwitchTalkOut(visitor)
OnSwitchTalkIn(visitor, lastTalk)
OnAddComPhrase(errCode, id)
OnEditComPhrase(errCode, id)
OnDelComPhrase(errCode, id)
OnRecvVisitorInfo(errCode, infos)
OnEditVisitorInfo(errCode, gid, rename)
OnDisconnect()
OnErr(errCode, message)
OnDebug(dbgInfo)
*/


/**********************************************************************
* CXMLClientKh事件说明
***********************************************************************/
/*
OnLogin(errCode)
OnLinkOpen(errCode, errMsg)
OnLinkClose()
OnRecvTalkMsg(msg)
OnTyping()
OnSetupTyping(mode)
OnRecvFile(fileName)
OnErr(errCode, message)
OnDebug(dbgInfo)
*/


/**********************************************************************
* 常数定义
**********************************************************************/
CONST_SRV_STATE_OFFLINE = 0;
CONST_SRV_STATE_ONLINE = 1;
CONST_SRV_STATE_AWAY = 2;
CONST_TYPE_MODE_WITHOUT_MSG = 0;
CONST_TYPE_MODE_WITH_MSG = 1;
CONST_LNK_TYPE_ALWAYS_NEW = 0;
CONST_LNK_TYPE_KEEP_EXIST = 1;
CONST_REPOST_TIMEOUT = 100000;


/**********************************************************************
* 公共函数
**********************************************************************/
/* 从XML文本中解析Response列表 */
function XMLParseRsp(dom)
{
    try
    {
        if(browser == "firefox")
        {
          return dom.getElementsByTagName("Response");
        }


        if (0 == dom.parseError.errorCode)
        {
            return dom.getElementsByTagName("Response");
        }
        else
        {
            return null;
        }
        
    }
    catch(e)
    {
        return null;
    }
}
/* 从Response节点中解析出指定名称的头信息 */
function XMLGetRspHead(rspNode, headName)
{
    return XMLGetNamedAttr(rspNode, headName);
}

/* 从Response节点中解析出指定名称的头信息--不解码 */
function XMLGetRspHeadRaw(rspNode, headName)
{
    return XMLGetNamedAttrRaw(rspNode, headName);
}

/* 从Response节点中解析出数据体 */
function XMLGetRspData(rspNode)
{
    try
    {
        if (null == rspNode)
        {
            return null;
        }
        else
        {
            if(browser == "firefox")
            {
              return rspNode.getElementsByTagName("Data");
            }
            else
            {
              return rspNode.selectSingleNode("Data");
            }
        }
    }
    catch(e)
    {
        return null;
    }
}

/* 从DOM节点中解析出指定名称的属性 */
function XMLGetNamedAttr(node, attrName)
{
    try
    {
        if (null == node)
        {
            return "";
        }
        else
        {
            if(browser == "firefox")
            {
              return node.attributes.getNamedItem(attrName).textContent;
            }
            else
            {
              return node.attributes.getNamedItem(attrName).nodeValue;
            }
        }
    }
    catch(e)
    {
        return "";
    }
}

/* 从DOM节点中解析出指定名称的属性--不解码 */
function XMLGetNamedAttrRaw(node, attrName)
{
    try
    {
        if (null == node)
        {
            return "";
        }
        else
        {
            if(browser == "firefox")
            {
              return node.attributes.getNamedItem(attrName).textContent;
            }
            else
            {
              return node.attributes.getNamedItem(attrName).nodeValue;
            }
        }
    }
    catch(e)
    {
        return "";
    }
}

/* 检测某个URL是否存在 */
function XMLCheckStatus(url)
{
    try
    {
        var req = new CXMLRequest();
        var ajax = req.GetXmlHttp();
        
        ajax.open("HEAD", url, false);
        ajax.send();
        return ajax.status;
    }
    catch(e)
    {
        return 9999;
    }
}
//获取tagName 的节点列表
function XMLGetNodes(xml,tagName)
{
  try
  {
    if(null != xml)
        return xml.getElementsByTagName(tagName);
    else
        return null;
  }
  catch(e)
  {
      return null;
  }
}

//获取tagName 的节点数目
function XMLGetNodesLength(xml)
{
  try
  {
      if(null != xml)
          return xml.length;
      else
          return 0;
  }
  catch(e)
  {
      return 0;
  }
}

//获取tagName 的指定节点
function XMLGetNode(xml,i)
{
    if(null != xml)
        return xml.item(i);
    else
        return null;
}


/**********************************************************************
* 客服人员类
**********************************************************************/
function CStaff(id6d, account, name, state)
{
    var SRV_STATE_OFFLINE = 0;
    var SRV_STATE_ONLINE = 1;
    var SRV_STATE_AWAY = 2;
     
    /* 客服类的基本属性 */
    this.id6d;
    this.account;
    this.name;
    this.state;
    this.linkNum;

    if (undefined != id6d)
    {
        this.id6d = id6d;
    }
    
    if (undefined != account)
    {
        this.account = account;
    }
    
    if (undefined != name)
    {
        this.name = name;
    }
    
    if (state == SRV_STATE_OFFLINE || state == SRV_STATE_ONLINE || state == SRV_STATE_AWAY)
    {
        this.state = state;
    }
    
    /* 合并客服信息 */
    this.Combine = function(comb)
    {
        if (undefined != comb.id6d)
        {
            this.id6d = comb.id6d;
        }
        
        if (undefined != comb.account)
        {
            this.account = comb.account;
        }
        
        if (undefined != comb.name)
        {
            this.name = comb.name;
        }
        
        if (undefined != comb.state)
        {
            this.state = comb.state;
        }
    }
    
    /* 克隆客服信息 */
    this.Clone = function()
    {
        var cl = new CStaff();
        
        cl.Combine(this);
        return cl;
    }
}


/**********************************************************************
* 访客类
**********************************************************************/
function CVisitor(gid, tid)
{
    /* 访客类的基本属性 */
    this.gid;
    this.tid;
    this.linkID;
    this.serving;
    this.nick;
    this.remark;
    this.ip;
    this.ipAddr;
    this.from;
    this.talkpage;
    this.keyword;
    this.status;
    this.gid_ip;
    this.last_url;

    if (undefined != gid)
    {
        this.gid = gid;
    }
    
    if (undefined != tid)
    {
        this.tid = tid;
    }
    
    /* 自动生成访客称呼 */
    this.GetMark = function()
    {
        if (undefined == this.nick || "" == this.nick)
        {
            if (this.gid > 0)
            {
                return (this.gid);
            }
            else
            {
                return ("新的访客");
            }
        }
        else
        {
            return this.nick;
        }
    }

    /* 合并访客信息 */
    this.Combine = function(comb)
    {
        if (undefined != comb.gid)
        {
            this.gid = comb.gid;
        }
        
        if (undefined != comb.tid)
        {
            this.tid = comb.tid;
        }
        
        if (undefined != comb.linkID)
        {
            this.linkID = comb.linkID;
        }
        
        if (undefined != comb.serving)
        {
            this.serving = comb.serving;
        }
        
        if (undefined != comb.nick)
        {
            this.nick = comb.nick;
        }
        
        if (undefined != comb.remark)
        {
            this.remark = comb.remark;
        }
        
        if (undefined != comb.ip)
        {
            this.ip = comb.ip;
        }
        
        if (undefined != comb.ipAddr)
        {
            this.ipAddr = comb.ipAddr;
        }
        
        if (undefined != comb.from)
        {
            this.from = comb.from;
        }

        if (undefined != comb.talkpage)
        {
            this.talkpage = comb.talkpage;
        }

        if (undefined != comb.keyword)
        {
            this.keyword = comb.keyword;
        }

        if (undefined != comb.status)
        {
            this.status = comb.status;
        }

        if (undefined != comb.gid_ip)
        {
            this.gid_ip = comb.gid_ip;
        }

        if (undefined != comb.last_url)
        {
            this.last_url = comb.last_url;
        }
    }
    
    /* 克隆访客信息 */
    this.Clone = function()
    {
        var cl = new CVisitor();
        
        cl.Combine(this);
        return cl;
    }
}


/**********************************************************************
* Ajax请求类
**********************************************************************/
function CXMLRequest(tag, client)
{
    var me = this;
    var m_tag = tag;
    var m_client = client;        
    var m_url = "";
    var m_postData = "";
    var m_isSubmit = false;
    var m_repostTime = 0;
    try
    {
     var m_xmlHttp = new ActiveXObject("MSXML2.XMLHTTP");
     // var m_xmlHttp = new ActiveXObject("MSXML2.ServerXMLHTTP");
      
    }
    catch(e)
    {
		//alert(e);
      var m_xmlHttp = new XMLHttpRequest();
    }
    
    /* Ajax异步处理函数 */
    this.AjaxHandler = function()
    {
		
        if (4 == m_xmlHttp.readyState)
        {   
            if (200 == m_xmlHttp.status)
            {
                m_client.RequestHandler(me);
                m_xmlHttp = null;
                me = null;
                m_client.Repost();
            }
            else
            {
                var cmdArray = new Array('QST','SRV','LNK');
                var cmd = getStringField(getStringField(m_postData, '&', 1), '=', 2);
                if (0 <= cmdArray.search(cmd))
                {

					
                    if (0 == me.GetRepostTime())
                    {
                        m_client.RepostQueueFoot(me);
                    }
                    else
                    {
						
                        m_client.RepostQueueHead(me);
                    }
                    //m_client.Repost();
                }
               // alert(1111);
                m_xmlHttp = null;
                me = null;
            }
        }
    }
    
    /* 发送请求函数 */
    this.SendReq = function()
    {
        if (!m_isSubmit)
        {
			//alert(m_postData);
            m_xmlHttp.open("POST", m_url, true);
            m_xmlHttp.setRequestHeader("CONTENT-TYPE", "application/x-www-form-urlencoded");
            m_xmlHttp.send(m_postData);
            
            //alert(m_postData);
			//if(m_postData.indexOf('QST')>-1)
			//	document.getElementById("input1").value += m_postData+"\n";
            
            
            m_isSubmit = true;
        }
    }
    
    /* 设置请求的URL */
    this.SetURL = function(URL)
    {
        if ("" == m_url)
        {
            m_url = URL;
        }
        
    }
    
    /* 添加请求中附带的POST参数 */
    this.AddPostData = function(name, value)
    {
        m_postData += name + "=" + value + "&";
    }
    
    /* 设置请求中附带的POST参数 */
    this.SetPostData = function(value)
    {
        m_postData = value;
    }
    
    /* 获取请求中附带的POST参数 */
    this.GetPostData = function(value)
    {
        return m_postData;
    }
    
    /* 获取本次请求的标识号 */
    this.GetTag = function()
    {
        return m_tag;
    }
    
    /* 获取本次请求的Ajax对象 */
    this.GetXmlHttp = function()
    {
        return m_xmlHttp;
    }
    
    /* 设置本次请求的重发时间 */
    this.SetRepostTime = function(value)
    {
        m_repostTime = value;
    }
    
    /* 获取本次请求的重发时间 */
    this.GetRepostTime = function()
    {
        return m_repostTime;
    }

    
    m_xmlHttp.onreadystatechange = this.AjaxHandler;
        
}


/**********************************************************************
* 基于Ajax的客服端通讯模块类
**********************************************************************/
function CXMLClientKf(srvAddr, cmdAddr, debug)
{
    var SRV_STATE_OFFLINE = 0;
    var SRV_STATE_ONLINE = 1;
    var SRV_STATE_AWAY = 2;
    
    var me = this;
    var m_cmdAddr = "";
    var m_srvAddr = srvAddr;
    var m_debug = debug;
    var m_addNo = 1;
    var m_srvid = 0;
    var m_session = "";
    var m_arg = "";
    var m_company = "";
    var m_kfName = "";
    var m_counter = 0;
    var m_lastGetTime = 0;
    var m_lastGetTag = 0;
    var m_lastSessionTime = 0;
    var m_shutdown = false;
    var m_repostDataArray = new Array();
    var m_repostTimeArray = new Array();
    
    /* CXMLClientKf类最后一个实例对象 */
    CXMLClientKf.prototype.lastInstance = this;
    
    /* 触发通讯对象的超时判断 */
    CXMLClientKf.prototype.ClientTimeout = function()
    {
        CXMLClientKf.prototype.lastInstance.Timeout();
    }
    
    if (undefined == cmdAddr)
    {
        m_cmdAddr = "/sendmsg.jsp";
    }
    else
    {
        m_cmdAddr = cmdAddr;
    }
    
    /* 关闭/启用通讯模块 */
    this.ShutDown = function(isDown)
    {
        m_shutdown = isDown;
        
        if (isDown)
        {
            m_lastGetTime = 0;
            m_lastSessionTime = 0;
        }
        else
        {
            m_lastGetTime = new Date().getTime();
            m_lastSessionTime = new Date().getTime();
        }
    }
    
    /* GET连接定时重连 */
    this.Timeout = function()
    {
        if (m_lastGetTime > 0)
        {
            var nowTime = new Date().getTime();
            
            if ((nowTime - m_lastGetTime) > 20000)
            {
                this.GetCmd(true);
            }
        }
        
        if (m_lastSessionTime > 0)
        {
            var nowTime = new Date().getTime();
            
            if ((nowTime - m_lastSessionTime) > 120000)
            {
                this.KeepSession();
            }
        }
    }
    
    /* 设置工号登录信息 */
    this.SetLoginInfo = function(srvid, session, arg, company, kfName)
    {
        m_srvid = srvid;
        m_session = session;
        m_arg = arg;
        m_company = company;
        m_kfName = kfName;
    }
    
    /* 创建Ajax请求对象 */
    this.CreateRequest = function()
    {
        if (m_shutdown)
        {
            return null;
        }
        else
        {
            var req = new CXMLRequest(++m_counter, me);
            return req;
        } 
    }
    
    /* XML返回数据处理函数（供CXMLRequest对象回调） */
    this.RequestHandler = function(request)
    {
        var ajax = request.GetXmlHttp();
        //alert("12313213L:"+ajax.responseText);
        //if(m_postData.indexOf('QST')>-1)
		//	document.getElementById("input1").value += "回答："+ajax.responseText+"\n";
         
        if (m_debug)
        {
            this.OnDebug(ajax.responseText);
        }
        var rspList = XMLParseRsp(ajax.responseXML);
        var rspLength = XMLGetNodesLength(rspList);

        if (rspLength > 0)
        {
            for(var i=0; i<rspLength; i++)
            {
              var rsp = XMLGetNode(rspList,i);
              this.RspProc(request.GetTag(), rsp);
            }
            
        }
        else
        {
            m_addNo++;
            insertErrorInfos("1", "xmlParse", ajax.responseText);
            this.OnErr(0, "Parse rsp error!");
        }
    }
    
    /* 处理Response */
    this.RspProc = function(tag, rsp)
    {
        var cmd;
        var errCode = 0;
        var node;
        var nodeList;
        var data;
        
        if (null == rsp)
        {
            return;
        }
        
        try
        {
            cmd = XMLGetRspHead(rsp, "cmd");
            switch (cmd)
            {
                case "LOG":
                    this.SetLoginInfo(XMLGetRspHead(rsp, "srvid"), XMLGetRspHead(rsp, "sessid"), XMLGetRspHead(rsp, "arg"), XMLGetRspHead(rsp, "company_id"));
                    this.OnLogin(XMLGetRspHead(rsp, "ecode"));
                    break;
                case "SRV":
                    errCode = XMLGetRspHead(rsp, "ecode");
                    
                    if (0 == errCode)
                    {
                        CXMLClientKf.prototype.timerID = setInterval("CXMLClientKf.prototype.ClientTimeout()",2000);
                    }
                    else
                    {
                        this.ShutDown(true);
                    }
                    
                    this.OnSrvRsp(errCode);
                    break;
                case "ADDN":
                    m_addNo++;
                    break;
                case "GET":
                    if (tag == m_lastGetTag)
                    {
                        this.GetCmd();
                    }
                    break;
                case "SHD":
                    this.ShutDown(true);
                    this.OnDisconnect();
                    break;
                case "WLST":
                    errCode = XMLGetRspHead(rsp, "ecode");
                    
                    if (0 == errCode)
                    {
                        var staffArray = new Array();

                        nodeList = XMLGetNodes(rsp, "Data");
                        var node = XMLGetNode(nodeList, 0);

                        var rowList = XMLGetNodes(node,"row");
                        var rowLength = XMLGetNodesLength(rowList);
                        for(var i=0; i<rowLength; i++)
                        {
                            var node = XMLGetNode(rowList,i);
                            var staff = new CStaff();
                            
                            staff.id6d = XMLGetNamedAttr(node, "kfid");
                            staff.account = XMLGetNamedAttr(node, "worker_id");
                            staff.name = XMLGetNamedAttr(node, "kfname");
                            staff.state = XMLGetNamedAttr(node, "state");
                            
                            staffArray.push(staff);
                            staff = null;
                        }

                        this.OnRecvStaffList(errCode, staffArray);
                        staffArray = null;
                    }
                    
                    break;
                case "ITK":
                    var isBroadcast;
                    
                    if (XMLGetRspHead(rsp, "type") == 0)
                    {
                        isBroadcast = true;
                    }
                    else
                    {
                        isBroadcast = false;
                    }
                    
                    this.OnRecvInnerTalkMsg(XMLGetRspHead(rsp, "sid"), XMLGetRspHead(rsp, "kfname"), isBroadcast, XMLGetRspHead(rsp, "msg"));
                    break;
                case "ACL":
                    var visitorArray = new Array();

                    nodeList = XMLGetNodes(rsp, "Data");
                    var node = XMLGetNode(nodeList, 0);

                    var rowList = XMLGetNodes(node, "row");
                    var rowLength = XMLGetNodesLength(rowList);

                    for(var i=0; i<rowLength; i++)
                    {
                        var node = XMLGetNode(rowList, i);

                        var visitor = new CVisitor();
                        
                        visitor.gid = XMLGetNamedAttr(node, "khid");
                        visitor.tid = XMLGetNamedAttr(node, "khtmpid");
                        visitor.ip = XMLGetNamedAttr(node, "ip");
                        visitor.ipAddr = XMLGetNamedAttr(node, "area");
                        visitor.serving = XMLGetNamedAttr(node, "kfname");
                        visitor.from = XMLGetNamedAttrRaw(node, "from");
                        visitor.nick = XMLGetNamedAttr(node, "khname");
                        visitor.keyword = XMLGetNamedAttr(node, "keyword");
                        visitor.status = XMLGetNamedAttr(node, "status");
                        visitor.card = XMLGetNamedAttr(node, "card");
                        visitor.last_url = XMLGetNamedAttr(node, "last_url");

                        visitor.gid_ip = XMLGetNamedAttr(node, "khid")+"_"+XMLGetNamedAttr(node, "ip");

                        visitorArray.push(visitor);
                        visitor = null;
                    }
                    this.OnRecvVisitorList(visitorArray);
                    visitorArray = null;

                    break;
                case "ACC":
                    var visitor = new CVisitor();

                    visitor.gid = XMLGetRspHead(rsp, "khid");
                    visitor.tid = XMLGetRspHead(rsp, "khtmpid");                        
                    visitor.ip = XMLGetRspHead(rsp, "ip");
                    visitor.ipAddr = XMLGetRspHead(rsp, "area");
                    visitor.serving = XMLGetRspHead(rsp, "kfname");
                    visitor.from = XMLGetRspHeadRaw(rsp, "from");
                    visitor.nick = XMLGetRspHead(rsp, "khname");
                    visitor.keyword = XMLGetRspHead(rsp, "keyword");
                    visitor.status = XMLGetRspHead(rsp, "status");
                    visitor.card = XMLGetRspHead(rsp, "card");
                    visitor.last_url = XMLGetRspHead(rsp, "last_url");

                    visitor.gid_ip = XMLGetRspHead(rsp, "khid")+"_"+XMLGetRspHead(rsp, "ip");

                    this.OnVisitorOnline(visitor);
                    visitor = null;

                    break;
                case "LEV":
                    var visitor = new CVisitor();
                    visitor.gid = XMLGetRspHead(rsp, "khid");
                    visitor.ip = XMLGetRspHead(rsp, "ip");

                    visitor.gid_ip = XMLGetRspHead(rsp, "khid")+"_"+XMLGetRspHead(rsp, "ip");

                    this.OnVisitorOffline(visitor);
                    visitor = null;

                    break;
                case "IOK":
                    var visitor = new CVisitor();

                    visitor.gid = XMLGetRspHead(rsp, "khid");
                    visitor.tid = XMLGetRspHead(rsp, "khtmpid");
                    visitor.ip = XMLGetRspHead(rsp, "ip");
                    visitor.serving = XMLGetRspHead(rsp, "kfname");
                    visitor.nick = XMLGetRspHead(rsp, "khname");
                    visitor.status = XMLGetRspHead(rsp, "status");
                    visitor.card = XMLGetRspHead(rsp, "card");

                    visitor.gid_ip = XMLGetRspHead(rsp, "khid")+"_"+XMLGetRspHead(rsp, "ip");

                    this.OnVisitorStatusChange(visitor);
                    visitor = null;

                    break;
                case "ACT":
                    var traceArray = new Array();

                    nodeList = XMLGetNodes(rsp,"Data");
                    var node = XMLGetNode(nodeList,0);

                    var rowList = XMLGetNodes(node,"row");
                    var rowLength = XMLGetNodesLength(rowList);

                    for(var i=0; i<rowLength; i++)
                    {
                        var node=XMLGetNode(rowList, i);
                        var trace = new Object();
                        
                        trace.time = XMLGetNamedAttr(node, "time");
                        trace.url = XMLGetNamedAttrRaw(node, "referer");

                        traceArray.push(trace);
                        trace = null;
                    }
                    this.OnTrace(XMLGetRspHead(rsp, "khid"), XMLGetRspHead(rsp, "ip"), traceArray);
                    traceArray = null;

                    break;
                case "LOK":
					//alert("lok111");
                    var visitor = new CVisitor();
                    
                    visitor.gid = XMLGetRspHead(rsp, "khid");
                    visitor.tid = XMLGetRspHead(rsp, "khtmpid");
                    visitor.linkID = XMLGetRspHead(rsp, "link");
                    visitor.ip = XMLGetRspHead(rsp, "ip");
                    visitor.ipAddr = XMLGetRspHead(rsp, "area");
                    visitor.nick = XMLGetRspHead(rsp, "khname");
                    visitor.from = XMLGetRspHeadRaw(rsp, "from");
                    visitor.talkpage = XMLGetRspHeadRaw(rsp, "talkpage");
                    visitor.keyword = XMLGetRspHead(rsp, "keyword");
                    visitor.card = XMLGetRspHead(rsp, "card");
                    
                    var lastTalk = new Object();

                    data = XMLGetNodes(rsp,"Data");
                    data = XMLGetNode(data,0);

                    lastTalk.kfName = XMLGetNamedAttr(data, "kfname");
                    lastTalk.talkDate = XMLGetNamedAttr(data, "date");
                    lastTalk.msgArray = new Array();

                    nodeList = XMLGetNodes(data,"row");
                    var nodeLength = XMLGetNodesLength(nodeList);
                    
                    for(var i=0; i<nodeLength; i++)
                    {
                      var node=XMLGetNode(nodeList,i);
                      var msg = new Object();
                      
                      msg.time = XMLGetNamedAttr(node, "time");
                      //msg.id6d = XMLGetNamedAttr(node, "id6d");
                      msg.kfName = XMLGetNamedAttr(node, "kfname");
                      msg.type = XMLGetNamedAttr(node, "type");
                      msg.text = XMLGetNamedAttr(node, "msg");

                      lastTalk.msgArray.push(msg);
                      msg = null;
                    }
                    
                    this.OnLinkOpen(visitor, lastTalk);
                    lastTalk = null;

                    break;
                case "ULN":
                    var visitor = new CVisitor();
                    visitor.tid = XMLGetRspHead(rsp, "sid");

                    this.OnLinkClose(visitor);
                    break;
                case "FLN":
                    var visitor = new CVisitor();
                    visitor.tid = XMLGetRspHead(rsp, "sid");

                    this.OnLinkClose(visitor);
                    visitor = null;

                    break;
                case "QST":
                    this.OnRecvTalkMsg(XMLGetRspHead(rsp, "sid"), XMLGetRspHead(rsp, "msg"));
                    break;
                case "TYP":
                    this.OnTyping(XMLGetRspHead(rsp, "sid"), XMLGetRspHead(rsp, "msg"));
                    break;
                case "FIL":
                    this.OnRecvFile(XMLGetRspHead(rsp, "sid"), XMLGetRspHead(rsp, "filename"));
                    break;
                case "LST":
                    var staffArray = new Array();
                    
                    var dataList = XMLGetNodes(rsp,"Data");
                    var data = XMLGetNode(dataList,0);
                    
                    var groupNodeList=XMLGetNodes(data,"Group");
                    var groupNodeLength = XMLGetNodesLength(groupNodeList);

                    for(var i=0; i<groupNodeLength; i++)
                    {
                      var groupNode = XMLGetNode(groupNodeList,i);
                      var id = XMLGetNamedAttr(groupNode, "id");
                      var name = XMLGetNamedAttr(groupNode, "name");

                      var nodeList = XMLGetNodes(groupNode,"row");
                      var nodeLength = XMLGetNodesLength(nodeList);

                      for(var j=0;j<nodeLength;j++)
                      {
                          var node=XMLGetNode(nodeList,j);
                          var staff = new Object();
                          
                          staff.id = id;
                          staff.name = name;
                          staff.kfid = XMLGetNamedAttr(node, "kfid");
                          staff.kfname = XMLGetNamedAttr(node, "kfname");
                          staff.cnt = XMLGetNamedAttr(node, "cnt");
                          
                          staffArray.push(staff);
                          staff = null;
                      }
                    }
                    
                    this.OnRecvOnlineStaff(staffArray);
                    staffArray = null;

                    break;
                case "SWO":
                    errCode = XMLGetRspHead(rsp, "ecode");
                    
                    if (0 == errCode)
                    {
                        var visitor = new CVisitor();
                        visitor.linkID = XMLGetRspHead(rsp, "link");
                        this.OnSwitchTalkOut(visitor);
                    }
                    else
                    {
                        this.OnErr(0, "SWO Error. ecode:" + errCode);
                    }
                    
                    break;
                case "SWI":
                    var visitor = new CVisitor();

                    visitor.tid = XMLGetRspHead(rsp, "khtmpid");
                    visitor.gid = XMLGetRspHead(rsp, "khid");
                    visitor.linkID = XMLGetRspHead(rsp, "link");
                    visitor.ip = XMLGetRspHead(rsp, "ip");
                    visitor.ipAddr = XMLGetRspHead(rsp, "area");
                    visitor.nick = XMLGetRspHead(rsp, "khname");
                    visitor.from = XMLGetRspHeadRaw(rsp, "from");
                    visitor.talkpage = XMLGetRspHeadRaw(rsp, "talkpage");
                    visitor.keyword = XMLGetRspHead(rsp, "keyword");
                    visitor.card = XMLGetRspHead(rsp, "card");

                    var lastTalk = new Object();
                    data = XMLGetNodes(rsp,"Data");
                    data = XMLGetNode(data,0);
                    lastTalk.kfName = XMLGetNamedAttr(data, "kfname");
                    lastTalk.talkDate = XMLGetNamedAttr(data, "date");
                    lastTalk.msgArray = new Array();
                    
                    nodeList = XMLGetNodes(data,"row");
                    var nodeLength = XMLGetNodesLength(nodeList);
                    
                    for(var i=0;i<nodeLength;i++)
                    {
                        var node=XMLGetNode(nodeList,i);
                        var msg = new Object();
                        
                        msg.time = XMLGetNamedAttr(node, "time");
                        //msg.id6d = XMLGetNamedAttr(node, "id6d");
                        msg.kfName = XMLGetNamedAttr(node, "kfname");
                        msg.type = XMLGetNamedAttr(node, "type");
                        msg.text = XMLGetNamedAttr(node, "msg");

                        lastTalk.msgArray.push(msg);
                        msg = null;
                    }
                   
                    this.OnSwitchTalkIn(visitor, lastTalk);
                    lastTalk = null;

                    break;
                case "CYY":
                    errCode = XMLGetRspHead(rsp, "ecode");
                    switch (XMLGetRspHead(rsp, "action"))
                    {
                        case "group":
                            var groupList = new Array();
                            var data = XMLGetNodes(rsp, "Data");
                            data = XMLGetNode(data, 0);
                            var nodeList = XMLGetNodes(data, "Group");
                            var nodeLength = XMLGetNodesLength(nodeList);
                                                
                            for(var i=0;i<nodeLength;i++)
                            {
                              var node = XMLGetNode(nodeList, i);
                              var group = new Object();

                              group.id = XMLGetNamedAttr(node, "id");
                              group.name = XMLGetNamedAttr(node, "name");
                              group.kfid = XMLGetNamedAttr(node, "kfid");

                              groupList.push(group);
                              group = null;
                            }

                            this.OnGetPhraseGroup(errCode, groupList);
                            groupList = null;

                            break;
                        case "add":
                            this.OnAddComPhrase(errCode, XMLGetRspHead(rsp, "id"));
                            break;
                        case "edit":
                            this.OnEditComPhrase(errCode, XMLGetRspHead(rsp, "id"));
                            break;
                        case "del":
                            this.OnDelComPhrase(errCode, XMLGetRspHead(rsp, "id"));
                            break;
                    }
                    
                    break;
                case "INFO":
                    errCode = XMLGetRspHead(rsp, "ecode");
                    
                    switch (XMLGetRspHead(rsp, "action"))
                    {
                        case "addnotes":
                            this.OnAddRemark(errCode, XMLGetRspHead(rsp, "khid"));
                            break;
                        case "create":
                            this.OnCreateVisitorInfo(errCode, XMLGetRspHead(rsp, "khid"), XMLGetRspHead(rsp, "kfid"), XMLGetRspHead(rsp, "name"));
                            break;
                        case "get":
                            if (0 == errCode)
                            {
                                //node = XMLGetRspData(rsp).firstChild;
                                node = XMLGetNodes(rsp, "Data");
                                node = XMLGetNode(node, 0);
                                
                                if (null != node)
                                {
                                    var infos = new Object(); 
                                    
                                    infos.gid = XMLGetRspHead(rsp, "khid");

                                    infos.name = XMLGetNamedAttr(node, "name");
                                    infos.company = XMLGetNamedAttr(node, "company");
                                    infos.job = XMLGetNamedAttr(node, "job");
                                    infos.sex = XMLGetNamedAttr(node, "sex");
                                    infos.age = XMLGetNamedAttr(node, "age");
                                    infos.birthday = XMLGetNamedAttr(node, "birthday");
                                    infos.tel = XMLGetNamedAttr(node, "tel");
                                    infos.email = XMLGetNamedAttr(node, "email");
                                    infos.mobile = XMLGetNamedAttr(node, "mobile");
                                    infos.industry = XMLGetNamedAttr(node, "industry");
                                    infos.qq = XMLGetNamedAttr(node, "qq");
                                    infos.msn = XMLGetNamedAttr(node, "msn");
                                    infos.province= XMLGetNamedAttr(node, "province");
                                    infos.city= XMLGetNamedAttr(node, "city");
                                    infos.addr= XMLGetNamedAttr(node, "addr");
                                    infos.notes= XMLGetNamedAttr(node, "notes");
                                    infos.kfid= XMLGetRspHead(rsp, "kfid");
                                    infos.kfname= XMLGetNamedAttr(node, "kfname");
                                }
                            }
                            this.OnRecvVisitorInfo(errCode, infos);
                            visitor = null;

                            break;
                        case "edit":
                            this.OnEditVisitorInfo(errCode, XMLGetRspHead(rsp, "khid"), XMLGetRspHead(rsp, "kfid"), XMLGetRspHead(rsp, "name"), XMLGetRspHead(rsp, "rename"));
                            break;
                    }
                    
                    break;
                case "TIP":
                    this.OnRecvAttachMsg(XMLGetRspHead(rsp, "sid"), XMLGetRspHead(rsp, "msg"));
                    break;
                case "WAT":
                    this.OnWaitCount(XMLGetRspHead(rsp, "count"));
                    break;
                case "SYS":
                    var bulletinArray = new Array();

                    var data = XMLGetNodes(rsp,"Data");
                    data = XMLGetNode(data,0);
                    var nodeList = XMLGetNodes(data,"row");
                    var nodeLength = XMLGetNodesLength(nodeList);
                                        
                    for(var i=0;i<nodeLength;i++)
                    {
                      var node=XMLGetNode(nodeList,i);

                      var bulletin = new Object();
                      bulletin.type = XMLGetNamedAttr(node, "type");
                      bulletin.msg = XMLGetNamedAttr(node, "msg");
                      
                      bulletinArray.push(bulletin);
                      bulletin = null;
                    }
                    this.OnRecvSysBulletin(bulletinArray);
                    bulletinArray = null;

                    break;
                case "REG":
                    this.OnRegSuccess(XMLGetRspHead(rsp, "sid"));
                    break;
                case "MEET":
                    var contactArray = new Array();

                    nodeList = XMLGetNodes(rsp, "Data");
                    var node = XMLGetNode(nodeList, 0);

                    var rowList = XMLGetNodes(node, "row");
                    var rowLength = XMLGetNodesLength(rowList);

                    for(var i=0; i<rowLength; i++)
                    {
                        var node = XMLGetNode(rowList, i);
                        var contact = new Object();
                        
                        contact.id = XMLGetNamedAttr(node, "id");
                        contact.time = XMLGetNamedAttr(node, "time");
                        contact.id6d = XMLGetNamedAttr(node, "id6d");
                        contact.kfname = XMLGetNamedAttr(node, "kfname");
                        contact.state = XMLGetNamedAttr(node, "state");
                        
                        contactArray.push(contact);
                        contact = null;
                    }

                    this.OnContact(XMLGetRspHead(rsp, "khid"), contactArray);
                    contactArray = null;

                    break;
                case "OK":
                    break;
                default:
                    this.OnErr(0, "unknown rsp:" + cmd);
            }
        }
        catch(e)
        {
			alert(e.message);
            this.OnErr(e.name, e.message);
            return;
        }
    }

    /* 可自定义的事件处理函数 */
    this.OnLogin = function(errCode){}
    this.OnSrvRsp = function(errCode){}
    this.OnRecvStaffList = function(errCode, staffArray){}
    this.OnRecvInnerTalkMsg = function(srvid, kfName, isBroadcast, msg){}
    this.OnRecvVisitorList = function(visitorArray){}
    this.OnVisitorOnline = function(visitor){}
    this.OnVisitorOffline = function(visitor){}
    this.OnVisitorStatusChange = function(visitor){}
    this.OnTrace = function(gid, ip, traceArray){}
    this.OnLinkOpen = function(visitor, lastTalk){}
    this.OnLinkClose = function(visitor){}
    this.OnRecvTalkMsg = function(tid, msg){}
    this.OnTyping = function(tid, msg){}
    this.OnRecvFile = function(tid, fileName){}
    this.OnRecvOnlineStaff = function(tid, staffArray){}
    this.OnSwitchTalkOut = function(visitor){}
    this.OnSwitchTalkIn = function(visitor, lastTalk){}
    this.OnGetPhraseGroup = function(errCode, groupList){}
    this.OnAddComPhrase = function(errCode, id){}
    this.OnEditComPhrase = function(errCode, id){}
    this.OnDelComPhrase = function(errCode, id){}
    this.OnCreateVisitorInfo = function(errCode, gid, kfid, name){}
    this.OnRecvVisitorInfo = function(errCode, infos){}
    this.OnEditVisitorInfo = function(errCode, gid, kfid, name, rename){}
    this.OnAddRemark = function(errCode, gid){}
    this.OnDisconnect = function(){}
    this.OnErr = function(errCode, message){}
    this.OnDebug = function(dbgInfo){}

    this.OnRecvAttachMsg = function(msg){}
    this.OnWaitCount = function(cnt){}
    this.OnRecvSysBulletin = function(bulletinArray){}
    this.OnRegSuccess = function(tid){}
    this.OnContact = function(gid, contactArray){}
    
    /* 帐号验证 */
    this.Login = function(co, kf, pw, ver)
    {
        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + "/bglogin.php");
        
        req.AddPostData("domain_name", co);
        req.AddPostData("name", kf);
        req.AddPostData("password", pw);
        req.AddPostData("ver", ver);
        
        req.SendReq();
        
        return req.GetTag();
    }
    
    /* 登录CMD服务(SRV) */
    this.SendSrv = function()
    {
        this.ShutDown(false);
        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + m_cmdAddr);

        m_lastGetTime = new Date().getTime();
        req.AddPostData("cmd", "SRV");
        req.AddPostData("sid", m_srvid);
        req.AddPostData("did", "11");
        req.AddPostData("time", m_lastGetTime);
        
        req.SendReq();
        m_lastGetTag = req.GetTag();

        return req.GetTag();
    }
    
    /* 发送GET请求(GET) */
    this.GetCmd = function(reconnect)
    {
        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + m_cmdAddr);

        if (reconnect)
        {
            m_addNo++;
            req.AddPostData("did", "11");
            this.OnDebug("Reconnect");
        }
        else
        {
            req.AddPostData("did", "0");
        }
        
        m_lastGetTime = new Date().getTime();
        req.AddPostData("cmd", "GET");
        req.AddPostData("sid", m_srvid);
        req.AddPostData("msg", m_addNo);
        req.AddPostData("time", m_lastGetTime);
        
        req.SendReq();
        m_lastGetTag = req.GetTag();

        return req.GetTag();
    }
    
    /* 发送状态变化请求(STE) */
    this.ChangeState = function(state)
    {
        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + m_cmdAddr);
        
        req.AddPostData("cmd", "STE");
        req.AddPostData("sid", m_srvid);
        req.AddPostData("did", "11");
        req.AddPostData("dwid", m_company);
        req.AddPostData("state", state);
        req.AddPostData("time", new Date().getTime());
        
        req.SendReq();
        
        if (state == SRV_STATE_OFFLINE)
        {
            this.ShutDown(true);
        }

        return req.GetTag();
    }
    
    /* 保持Session */
    this.KeepSession = function()
    {
        //var req = this.CreateRequest();
        
        //if (null == req)
        //{
        //    return;
        //}
        
        //req.SetURL(m_srvAddr + "/keep_session.php");
        
        //req.AddPostData("sessid", m_session);
        //req.AddPostData("arg", m_arg);
        
        //req.SendReq();
        
        //m_lastSessionTime = new Date().getTime();
        
        //return req.GetTag();
    }
    
    /* 获取在线客服列表(WLST) */
    this.GetStaffList = function()
    {
        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + "/getdata.php");
        
        req.AddPostData("cmd", "WLST");
        req.AddPostData("sessid", m_session);
        req.AddPostData("arg", m_arg);
        
        req.SendReq();
        
        return req.GetTag();
    }
    
    /* 发送内部对话消息(ITK) */
    this.SendInnerTalkMsg = function(did, msg, isBroadcast)
    {
        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + m_cmdAddr);
        
        req.AddPostData("cmd", "ITK");
        req.AddPostData("sid", m_srvid);
        req.AddPostData("kfname", m_kfName);
        req.AddPostData("did", did);
        req.AddPostData("msg", msg);
        req.AddPostData("time", new Date().getTime());
        
        if (isBroadcast)
        {
            req.AddPostData("type", 0);
        }
        else
        {
            req.AddPostData("type", 1);
        }
        
        req.SendReq();
        
        return req.GetTag();
    }
    
    /* 获取完整访客列表(ACL) */
    this.GetVisitorList = function()
    {
        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + m_cmdAddr);
        
        req.AddPostData("cmd", "ACL");
        req.AddPostData("sid", m_srvid);
        req.AddPostData("did", "11");
        req.AddPostData("time", new Date().getTime());
        
        req.SendReq();
        
        return req.GetTag();
    }
    
    /* 邀请对话(IVT) */
    this.InviteTalk = function(gid, msg, ip, isAsk)
    {
      
        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + m_cmdAddr);
        
        req.AddPostData("cmd", "IVT");
        req.AddPostData("sid", m_srvid);
        req.AddPostData("khid", gid);
        req.AddPostData("ip", ip);
        req.AddPostData("time", new Date().getTime());
        
        if (undefined == msg)
        {
            req.AddPostData("msg", "客服 [" + m_kfName + "] 想邀请您对话");
        }
        else
        {
            req.AddPostData("msg", msg);
        }
        
        if (false == isAsk)
        {
            req.AddPostData("type", 2);
        }
        else
        {
            req.AddPostData("type", 1);
        }
        
        req.SendReq();
        
        return req.GetTag();
        
    }
    
    /* 获取完整访问轨迹(ACT) */
    this.TraceVisitor = function(gid, ip)
    {
        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + m_cmdAddr);
        
        req.AddPostData("cmd", "ACT");
        req.AddPostData("sid", m_srvid);
        req.AddPostData("did", "11");
        req.AddPostData("khid", gid);
        req.AddPostData("ip", ip);
        req.AddPostData("time", new Date().getTime());
        
        req.SendReq();
        
        return req.GetTag();
    }
    
    /* 结束对话(ULN) */
    this.TerminateLink = function(tid, robid)
    {
        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + m_cmdAddr);
        
        req.AddPostData("cmd", "ULN");
        req.AddPostData("sid", m_srvid);
        req.AddPostData("did", tid);
        req.AddPostData("robid", robid);
        req.AddPostData("time", new Date().getTime());
        
        req.SendReq();
        
        //var visitor = new CVisitor();
        //visitor.tid = tid;
        //this.OnLinkClose(visitor);
        
        return req.GetTag();
    }
    
    /* 发送对话消息(QST) */
    this.SendTalkMsg = function(tid, gid, msg)
    {
        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + m_cmdAddr);
        
        req.AddPostData("cmd", "QST");
        req.AddPostData("sid", m_srvid);
        req.AddPostData("did", tid);
        req.AddPostData("khid", gid);
        req.AddPostData("dwid", m_company);
        req.AddPostData("msg", msg);
        req.AddPostData("time", new Date().getTime() + 1);
        
        req.SendReq();

        return req.GetTag();
    }
    
    /* 发送消息预知(TYP) */
    this.SendTyping = function(tid)
    {
        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + m_cmdAddr);
        
        req.AddPostData("cmd", "TYP");
        req.AddPostData("sid", m_srvid);
        req.AddPostData("did", tid);
        req.AddPostData("msg", "");
        req.AddPostData("time", new Date().getTime());
        
        req.SendReq();
        
        return req.GetTag();
    }
    
    /* 设置消息预知模式(TYP) */
    this.SetTypeMode = function(tid, mode, prefix)
    {
        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + m_cmdAddr);
        
        req.AddPostData("cmd", "TYP");
        req.AddPostData("sid", m_srvid);
        req.AddPostData("did", tid);
        req.AddPostData("msg", mode);
        req.AddPostData("time", new Date().getTime() + prefix);
        
        req.SendReq();
        
        return req.GetTag();
    }
    
    /* 发送文件(FIL) */
    this.SendFile = function(tid, gid, fileName)
    {

        var req = this.CreateRequest();

        if (null == req)
        {
            return;
        }

        req.SetURL(m_srvAddr + m_cmdAddr);
        
        req.AddPostData("cmd", "FIL");
        req.AddPostData("sid", m_srvid);
        req.AddPostData("did", tid);
        req.AddPostData("khid", gid);
        req.AddPostData("dwid", m_company);
        req.AddPostData("msg", fileName);
        req.AddPostData("time", new Date().getTime());
        
        req.SendReq();

        return req.GetTag();
    }
    
    /* 访客阻止(BLK) */
    this.BlockVisitor = function(gid, ip, time, reason)
    {
        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + m_cmdAddr);
        
        req.AddPostData("cmd", "BLK");
        req.AddPostData("sid", m_srvid);
        req.AddPostData("did", gid);
        req.AddPostData("guest_ip", ip);
        req.AddPostData("msg", reason);
        req.AddPostData("time", time);
        
        req.SendReq();
        
        return req.GetTag();
    }
    
    /* 获取可转接客服列表(LST) */
    this.GetOnlineStaff = function(gid)
    {
        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + m_cmdAddr);
        
        req.AddPostData("cmd", "LST");
        req.AddPostData("sid", m_srvid);
        req.AddPostData("did", "11");
        req.AddPostData("khid", gid);
        req.AddPostData("dwid", m_company);
        req.AddPostData("time", new Date().getTime());
        
        req.SendReq();
        
        return req.GetTag();
    }
    
    /* 转接对话(SWH) */
    this.SwitchTalk = function(gid, tid, did)
    {
        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + m_cmdAddr);
        
        req.AddPostData("cmd", "SWH");
        req.AddPostData("sid", m_srvid);
        req.AddPostData("did", did);
        req.AddPostData("khid", gid);
        req.AddPostData("khtmpid", tid);
        req.AddPostData("time", new Date().getTime());
        
        req.SendReq();
        
        return req.GetTag();
    }
    
    /* 获取常用语列表(CYY) */
    /*
    this.ListComPhrase = function()
    {
        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + "/getdata.php");
        
        req.AddPostData("cmd", "CYY");
        req.AddPostData("action", "");
        req.AddPostData("sessid", m_session);
        req.AddPostData("arg", m_arg);
        
        req.SendReq();
        
        return req.GetTag();
    }
    */


    /* 获取常用语组(CYY) */
    this.GetPhraseGroup = function()
    {
        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + "/getdata.php");
        
        req.AddPostData("cmd", "CYY");
        req.AddPostData("action", "group");
        req.AddPostData("sessid", m_session);
        req.AddPostData("arg", m_arg);
        
        req.SendReq();
        
        return req.GetTag();
    }
    
    /* 添加常用语(CYY) */
    this.AddComPhrase = function(group, title, phrase)
    {
        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + "/getdata.php");
        
        req.AddPostData("cmd", "CYY");
        req.AddPostData("action", "add");
        req.AddPostData("group", group);
        req.AddPostData("title", title);
        req.AddPostData("msg", phrase);
        req.AddPostData("sessid", m_session);
        req.AddPostData("arg", m_arg);
        
        req.SendReq();
        
        return req.GetTag();
    }
    
    /* 编辑常用语(CYY) */
    this.EditComPhrase = function(id, group, title, phrase)
    {
        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + "/getdata.php");
        
        req.AddPostData("cmd", "CYY");
        req.AddPostData("action", "edit");
        req.AddPostData("id", id);
        req.AddPostData("group", group);
        req.AddPostData("title", title);
        req.AddPostData("msg", phrase);
        req.AddPostData("sessid", m_session);
        req.AddPostData("arg", m_arg);
        
        req.SendReq();
        
        return req.GetTag();
    }
    
    /* 删除常用语(CYY) */
    this.DelComPhrase = function(id)
    {
        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + "/getdata.php");
        
        req.AddPostData("cmd", "CYY");
        req.AddPostData("action", "del");
        req.AddPostData("id", id);

        req.AddPostData("sessid", m_session);
        req.AddPostData("arg", m_arg);
        
        req.SendReq();
        
        return req.GetTag();
    }
    
    /* 创建访客信息(INFO) */
    this.CreateVisitorInfo = function(infos)
    {
        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + "/getdata.php");
        
        req.AddPostData("cmd", "INFO");
        req.AddPostData("action", "create");

        req.AddPostData("khid", infos.gid);
        req.AddPostData("dwid", m_company);
        req.AddPostData("kfid", infos.kfid);

        if(infos.name!=undefined)
        {
          req.AddPostData("name", infos.name);
        }
        if(infos.company!=undefined)
        {
          req.AddPostData("company", infos.company);
        }
        if(infos.job!=undefined)
        {
          req.AddPostData("job", infos.job);
        }
        if(infos.sex!=undefined)
        {
          req.AddPostData("sex", infos.sex);
        }
        if(infos.age!=undefined)
        {
          req.AddPostData("age", infos.age);
        }
        if(infos.birthday!=undefined)
        {
          req.AddPostData("birthday", infos.birthday);
        }
        if(infos.tel!=undefined)
        {
          req.AddPostData("tel", infos.tel);
        }
        if(infos.email!=undefined)
        {
          req.AddPostData("email", infos.email);
        }
        if(infos.mobile!=undefined)
        {
          req.AddPostData("mobile", infos.mobile);
        }
        if(infos.industry!=undefined)
        {
          req.AddPostData("industry", infos.industry);
        }
        if(infos.qq!=undefined)
        {
          req.AddPostData("qq", infos.qq);
        }
        if(infos.msn!=undefined)
        {
          req.AddPostData("msn", infos.msn);
        }
        if(infos.province!=undefined)
        {
          req.AddPostData("province", infos.province);
        }
        if(infos.city!=undefined)
        {
          req.AddPostData("city", infos.city);
        }
        if(infos.addr!=undefined)
        {
          req.AddPostData("addr", infos.addr);
        }
        if(infos.notes!=undefined)
        {
          req.AddPostData("notes", infos.notes);
        }

        req.AddPostData("sessid", m_session);
        req.AddPostData("arg", m_arg);
        req.AddPostData("time", new Date().getTime());
        
        req.SendReq();
        
        return req.GetTag();
    }

    /* 编辑访客信息(INFO) */
    this.EditVisitorInfo = function(infos)
    {
        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + "/getdata.php");
        
        req.AddPostData("cmd", "INFO");
        req.AddPostData("action", "edit");

        req.AddPostData("khid", infos.gid);
        req.AddPostData("dwid", m_company);

        if(infos.name!=undefined)
        {
          req.AddPostData("name", infos.name);
        }
        if(infos.company!=undefined)
        {
          req.AddPostData("company", infos.company);
        }
        if(infos.job!=undefined)
        {
          req.AddPostData("job", infos.job);
        }
        if(infos.sex!=undefined)
        {
          req.AddPostData("sex", infos.sex);
        }
        if(infos.age!=undefined)
        {
          req.AddPostData("age", infos.age);
        }
        if(infos.birthday!=undefined)
        {
          req.AddPostData("birthday", infos.birthday);
        }
        if(infos.tel!=undefined)
        {
          req.AddPostData("tel", infos.tel);
        }
        if(infos.email!=undefined)
        {
          req.AddPostData("email", infos.email);
        }
        if(infos.mobile!=undefined)
        {
          req.AddPostData("mobile", infos.mobile);
        }
        if(infos.industry!=undefined)
        {
          req.AddPostData("industry", infos.industry);
        }
        if(infos.qq!=undefined)
        {
          req.AddPostData("qq", infos.qq);
        }
        if(infos.msn!=undefined)
        {
          req.AddPostData("msn", infos.msn);
        }
        if(infos.province!=undefined)
        {
          req.AddPostData("province", infos.province);
        }
        if(infos.city!=undefined)
        {
          req.AddPostData("city", infos.city);
        }
        if(infos.addr!=undefined)
        {
          req.AddPostData("addr", infos.addr);
        }
        if(infos.notes!=undefined)
        {
          req.AddPostData("notes", infos.notes);
        }

        req.AddPostData("sessid", m_session);
        req.AddPostData("arg", m_arg);
        req.AddPostData("time", new Date().getTime());
        
        req.SendReq();
        
        return req.GetTag();
    }
    
    /* 增补访客备注(INFO) */
    this.AppendRemark = function(gid, remark)
    {
        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + "/getdata.php");
        
        req.AddPostData("cmd", "INFO");
        req.AddPostData("action", "addnotes");
        req.AddPostData("khid", gid);
        req.AddPostData("dwid", m_company);
        req.AddPostData("notes", remark);
        req.AddPostData("sessid", m_session);
        req.AddPostData("arg", m_arg);
        req.AddPostData("time", new Date().getTime());
        
        req.SendReq();
        
        return req.GetTag();
    }
    
    /* 获取访客信息(INFO) */
    this.GetVisitorInfo = function(gid)
    {
        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }

        req.SetURL(m_srvAddr + "/getdata.php");
        
        req.AddPostData("cmd", "INFO");
        req.AddPostData("action", "get");
        req.AddPostData("khid", gid);
        req.AddPostData("dwid", m_company);
        req.AddPostData("sessid", m_session);
        req.AddPostData("arg", m_arg);
        req.AddPostData("time", new Date().getTime());
        req.SendReq();
        
        return req.GetTag();
    }

    /* 名片更新通知(UPINFO) */
    this.VisitorNameUpdate = function(gid, kfid, name)
    {
        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }

        req.SetURL(m_srvAddr + m_cmdAddr);
        
        req.AddPostData("cmd", "UPINFO");
        req.AddPostData("sid", m_srvid);
        req.AddPostData("did", "11");
        req.AddPostData("khid", gid);
        req.AddPostData("kfid", kfid);
        req.AddPostData("name", name);
        req.AddPostData("dwid", m_company);
        req.AddPostData("time", new Date().getTime());
        req.SendReq();
        
        return req.GetTag();
    }

    /* 编辑访客昵称(NAM) */
    this.EditVisitorNick = function(gid, nick)
    {
        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + m_cmdAddr);
        
        req.AddPostData("cmd", "NAM");
        req.AddPostData("sid", m_srvid);
        req.AddPostData("did", "11");
        req.AddPostData("khid", gid);
        req.AddPostData("dwid", m_company);
        req.AddPostData("khname", nick);
        req.AddPostData("time", new Date().getTime());
        
        req.SendReq();
        
        return req.GetTag();
    }

    /* 获取联系记录(MEET) */
    this.ContactVisitor = function(gid)
    {
        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + "/getdata.php");
        
        req.AddPostData("cmd", "MEET");
        req.AddPostData("khid", gid);
        req.AddPostData("dwid", m_company);
        req.AddPostData("sessid", m_session);
        req.AddPostData("arg", m_arg);
        req.AddPostData("time", new Date().getTime());

        req.SendReq();
        
        return req.GetTag();
    }

    /*添加到重发队列头部*/
    this.RepostQueueHead = function (req)
    {
        var repostData = req.GetPostData();
        var repostTime = req.GetRepostTime();
        if (0 <= m_repostDataArray.search(repostData))
        {
            return;
        }
        m_repostDataArray.unshift(repostData);
        m_repostTimeArray.unshift(repostTime);
    }

    /*添加到重发队列尾部*/
    this.RepostQueueFoot = function (req)
    {
        var repostData = req.GetPostData();
        var repostTime = req.GetRepostTime();
        if (0 <= m_repostDataArray.search(repostData))
        {
            return;
        }
        m_repostDataArray.push(repostData);
        m_repostTimeArray.push(repostTime);
    }

    /*重发消息*/
    this.Repost = function ()
    {
        if (0 == m_repostDataArray.length)
        {
            return;
        }
        var repostData = m_repostDataArray.shift();
        var repostTime = m_repostTimeArray.shift();
        if (0 == repostTime)
        {
            repostTime = new Date().getTime();
        }
        else
        {
            if (new Date().getTime() - CONST_REPOST_TIMEOUT > repostTime)
            {
                this.Repost();
                return;
            }
        }

        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + m_cmdAddr);
        req.SetRepostTime(repostTime);
        req.SetPostData(repostData);
        req.SendReq();
        
        return req.GetTag();
    }

}


/**********************************************************************
* 基于Ajax的访客端通讯模块类
**********************************************************************/
function CXMLClientKh(srvAddr, cmdAddr, debug)
{
    var me = this;
    var m_cmdAddr = "";
    var m_srvAddr = srvAddr;
    var m_debug = debug;
    var m_addNo = 1;
    var m_gid = 0;
    var m_vid = 0;
    var m_tid = 0;
    var m_link = 0;
    var m_dwid = 0;
    var m_kfid = 0;
    var m_kfName = "";
    var m_from = "";
    var m_kfPage = "";
    //var m_session = "";
    //var m_arg = "";
    //var m_company = "";
    //var m_kfName = "";
    var m_counter = 0;
    var m_lastGetTime = 0;
    var m_lastGetTag = 0;
    //var m_lastSessionTime = 0;
    var m_shutdown = false;
    var m_repostDataArray = new Array();
    var m_repostTimeArray = new Array();
    
    /* 获取gid */
    this.GetGid = function()
    {
        return m_gid;
    }
    
    /* 获取tid */
    this.GetTid = function()
    {
        return m_tid;
    }
    
    /* 获取vid */
    this.GetVid = function()
    {
        return m_vid;
    }
    
    /* 获取正在对话的客服ID */
    this.GetKfid = function()
    {
        return m_kfid;
    }
    
    /* 获取正在对话的客服姓名 */
    this.GetKfname = function()
    {
        return m_kfName;
    }
    
    /* CXMLClientKh类最后一个实例对象 */
    CXMLClientKh.prototype.lastInstance = this;
    
    /* 触发通讯对象的超时判断 */
    CXMLClientKh.prototype.ClientTimeout = function()
    {
        CXMLClientKh.prototype.lastInstance.Timeout();
    }
    
    if (undefined == cmdAddr)
    {
        m_cmdAddr = "/sendmsg.jsp";
    }
    else
    {
        m_cmdAddr = cmdAddr;
    }
    
    /* 关闭/启用通讯模块 */
    this.ShutDown = function(isDown)
    {
        m_shutdown = isDown;
        
        if (isDown)
        {
            m_lastGetTime = 0;
            m_lastSessionTime = 0;
        }
        else
        {
            m_lastGetTime = new Date().getTime();
            m_lastSessionTime = new Date().getTime();
        }
    }
    
    /* GET连接定时重连 */
    this.Timeout = function()
    {
        if (m_lastGetTime > 0)
        {
            var nowTime = new Date().getTime();
            
            if ((nowTime - m_lastGetTime) > 20000)
            //if ((nowTime - m_lastGetTime) > 1000)
            {
                this.GetCmd(true);
            }
        }
        
        /*
        if (m_lastSessionTime > 0)
        {
            var nowTime = new Date().getTime();
            
            if ((nowTime - m_lastSessionTime) > 120000)
            {
                this.KeepSession();
            }
        }
        */
    }
    
    /* 设置访客信息 */
    this.SetKhInfo = function(gid, frompage, talkpage)
    {
        m_gid = gid;
        m_from = frompage;
        m_talkPage = talkpage;
        //m_session = session;
        //m_arg = arg;
        //m_company = company;
        //m_kfName = kfName;
    }
    
    /* 创建Ajax请求对象 */
    this.CreateRequest = function()
    {
        if (m_shutdown)
        {
            return null;
        }
        else
        {
            var req = new CXMLRequest(++m_counter, me);
            return req;
        } 
    }
          
    /* XML返回数据处理函数（供CXMLRequest对象回调） */
    this.RequestHandler = function(request)
    {   
        var ajax = request.GetXmlHttp();
        if (m_debug)
        {
            this.OnDebug(ajax.responseText);
        }
        //alert("abc:"+ajax.responseText);
        //if(m_postData.indexOf('QST')>-1)
			//document.getElementById("input1").value += "回答："+ajax.responseText+"\n";
        var rspList = XMLParseRsp(ajax.responseXML);
        var rspLength = XMLGetNodesLength(rspList);
        if (0 != rspLength)
        {            
            for(var i=0; i<rspLength; i++)
            {
              var rsp = XMLGetNode(rspList,i);
              this.RspProc(request.GetTag(), rsp);
            }
        }
        else
        {
            m_addNo++;
            this.OnErr(0, "Parse rsp error!");
        }
    }
    
    /* 处理Response */
    this.RspProc = function(tag, rsp)
    {
		
        var cmd;
        var errCode = 0;
        var node;
        var nodeList;
        var data;
        var msg;
        
        if (null == rsp)
        {
            return;
        }
        
        try
        {
            cmd = XMLGetRspHead(rsp, "cmd");
            switch (cmd)
            {
                case "LNK":
                    errCode = XMLGetRspHead(rsp, "ecode");
                    
                    m_kfid = XMLGetRspHead(rsp, "kfid");
                    m_kfName = XMLGetRspHead(rsp, "kfname");
                    m_tid = XMLGetRspHead(rsp, "khtmpid");
                    m_gid = XMLGetRspHead(rsp, "khid");
                    if (0 == errCode)
                    {
                        CXMLClientKh.prototype.timerID = setInterval("CXMLClientKh.prototype.ClientTimeout()",2000);
                    }
                    else if ((3 != errCode) && (2 != errCode))
                    {
                        this.ShutDown(true);
                    }
   
                    this.OnLinkOpen(errCode, XMLGetRspHead(rsp, "emsg"));
                    break;
                case "ADDN":
                    m_addNo++;
                    break;
                case "GET":
                    if (tag = m_lastGetTag)
                    {
                        this.GetCmd();
                    }
                    break;
                case "ULN":
                    this.OnLinkClose(XMLGetRspHead(rsp, "robid"));
                    break;
                case "FLN":
                    this.OnTimeOverClose(XMLGetRspHead(rsp, "link"));
                    break;
                case "QST":
                    this.OnRecvTalkMsg(XMLGetRspHead(rsp, "msg"));
                    break;
                case "TYP":
                    msg = XMLGetRspHead(rsp, "msg"); 
                    
                    if ("" == msg)
                    {
                        this.OnTyping();
                    }
                    else
                    {
                        this.OnSetupTyping(msg);
                    }
                    
                    break;
                case "FIL":
                    this.OnRecvFile(XMLGetRspHead(rsp, "filename"));
                    break;
                case "WAT":
                    m_tid = XMLGetRspHead(rsp, "khtmpid");

                    this.OnWaitCount(XMLGetRspHead(rsp, "count"));
                    break;
                case "OK":
                    break;
                default:
                    this.OnErr(0, "unknown rsp:" + cmd);
            }
        }
        catch(e)
        {
			alert(e.message);
            this.OnErr(e.name, e.message);
            return;
        }
    }

    /* 可自定义的事件处理函数 */
    this.OnLogin = function(errCode){}
    this.OnLinkOpen = function(errCode, errMsg){}
    this.OnLinkClose = function(robid){}
    this.OnTimeOverClose = function(link){}
    this.OnRecvTalkMsg = function(msg){}
    this.OnTyping = function(){}
    this.OnSetupTyping = function(mode){}
    this.OnRecvFile = function(fileName){}
    this.OnErr = function(errCode, message){}
    this.OnDebug = function(dbgInfo){}

    this.OnWaitCount = function(cnt){}
    
    /* 发起会话(LNK) */
    this.OpenLink = function(dwid, kfList, type, autotips, khname, dwname, khinfo, khcontact, question)
    {
        this.ShutDown(false);
        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + m_cmdAddr);
        
        m_lastGetTime = new Date().getTime();
        req.AddPostData("cmd", "LNK");
        req.AddPostData("sid", "");
        req.AddPostData("did", "11");
        req.AddPostData("khid", m_gid);
        req.AddPostData("dwid", dwid);
        req.AddPostData("type", type);
        req.AddPostData("kf_list", kfList);
        req.AddPostData("from", m_from);
        req.AddPostData("talkpage", m_talkPage);
		
		
        if (autotips != undefined)
        {
            req.AddPostData("autotips", autotips);
        }     
        
        if (khname != undefined)
        {
            req.AddPostData("khname", khname);
        }

        if (dwname != undefined)
        {
            req.AddPostData("dwname", dwname);
        }

        if (khinfo != undefined)
        {
            req.AddPostData("khinfo", khinfo);
        }
        
        if (khcontact != undefined)
        {
            req.AddPostData("khcontact", khcontact);
        }
        
        if (question != undefined)
        {
            req.AddPostData("question", question);
        }
        
		
        req.AddPostData("time", m_lastGetTime);
        
        //alert("send");
        req.SendReq();
        
         
        m_lastGetTag = req.GetTag();
        
        m_dwid = dwid;
        
         
         
        return req.GetTag();
    }
    
    /* 发送GET请求(GET) */
    this.GetCmd = function(reconnect)
    {
        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + m_cmdAddr);

        if (reconnect)
        {
            m_addNo++;
            req.AddPostData("did", "11");
            this.OnDebug("Reconnect");
        }
        else
        {
            req.AddPostData("did", "0");
        }
        
        m_lastGetTime = new Date().getTime();
        req.AddPostData("cmd", "GET");
        req.AddPostData("sid", m_tid);
        req.AddPostData("msg", m_addNo);
        req.AddPostData("time", m_lastGetTime);
        
        req.SendReq();
        m_lastGetTag = req.GetTag();

        return req.GetTag();
    }
    
    /* 结束对话(ULN) */
    this.TerminateLink = function()
    {
        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + m_cmdAddr);
        
        req.AddPostData("cmd", "ULN");
        req.AddPostData("sid", m_tid);
        req.AddPostData("did", m_kfid);
        req.AddPostData("time", new Date().getTime());
        
        req.SendReq();
        
        this.OnLinkClose("");
        return req.GetTag();
    }

    /* 退出队列(WAT) */
    this.QuitWait = function()
    {
        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + m_cmdAddr);

        req.AddPostData("cmd", "WAT");
        req.AddPostData("sid", m_tid);
        req.AddPostData("did", 11);
        req.AddPostData("time", new Date().getTime());
        
        req.SendReq();

        return req.GetTag();
    }

    /* 注册成功(REG) */
    this.RegSuccess = function(gid)
    {
        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + m_cmdAddr);

        req.AddPostData("cmd", "REG");
        req.AddPostData("sid", m_tid);
        req.AddPostData("did", m_kfid);
        req.AddPostData("dwid", m_dwid);
        req.AddPostData("khid", gid);
        req.AddPostData("time", new Date().getTime());
        
        req.SendReq();

        return req.GetTag();
    }
    
    /* 发送对话消息(QST) */
    this.SendTalkMsg = function(msg)
    {
        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + m_cmdAddr);
        
        req.AddPostData("cmd", "QST");
        req.AddPostData("sid", m_tid);
        req.AddPostData("did", m_kfid);
        req.AddPostData("dwid", m_dwid);
        req.AddPostData("msg", msg);
        req.AddPostData("time", new Date().getTime()+1);
        
        req.SendReq();

        return req.GetTag();
    }

    /* 发送接通提示(TIP) */
    this.SendAttachMsg = function(msg)
    {
        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + m_cmdAddr);
        
        req.AddPostData("cmd", "TIP");
        req.AddPostData("sid", m_tid);
        req.AddPostData("did", m_kfid);
        req.AddPostData("dwid", m_dwid);
        req.AddPostData("msg", msg);
        req.AddPostData("time", new Date().getTime());
        
        req.SendReq();
        
        return req.GetTag();
    }
    
    /* 发送消息预知(TYP) */
    this.SendTyping = function(msg)
    {
        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + m_cmdAddr);
        
        req.AddPostData("cmd", "TYP");
        req.AddPostData("sid", m_tid);
        req.AddPostData("did", m_kfid);
        req.AddPostData("msg", msg);
        req.AddPostData("time", new Date().getTime());
        
        req.SendReq();
        
        return req.GetTag();
    }
    
    /* 发送文件(FIL) */
    this.SendFile = function(fileURL)
    {
        var req = this.CreateRequest();

        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + m_cmdAddr);
        
        req.AddPostData("cmd", "FIL");
        req.AddPostData("sid", m_tid);
        req.AddPostData("did", m_kfid);
        req.AddPostData("dwid", m_dwid);
        req.AddPostData("msg", fileURL);
        req.AddPostData("time", new Date().getTime());
        
        req.SendReq();

        return req.GetTag();
    }

    /*添加到重发队列头部*/
    this.RepostQueueHead = function (req)
    {
        var repostData = req.GetPostData();
        var repostTime = req.GetRepostTime();
        if (0 <= m_repostDataArray.search(repostData))
        {
            return;
        }
        m_repostDataArray.unshift(repostData);
        m_repostTimeArray.unshift(repostTime);
    }

    /*添加到重发队列尾部*/
    this.RepostQueueFoot = function (req)
    {
		//alert("RepostQueueFoot1");
        var repostData = req.GetPostData();
        var repostTime = req.GetRepostTime();
        if (0 <= m_repostDataArray.search(repostData))
        {
            return;
        }
        m_repostDataArray.push(repostData);
        m_repostTimeArray.push(repostTime);
        //alert("RepostQueueFootend");
    }

    /*重发消息*/
    this.Repost = function ()
    {
        if (0 == m_repostDataArray.length)
        {
            return;
        }
        var repostData = m_repostDataArray.shift();
        var repostTime = m_repostTimeArray.shift();
        if (0 == repostTime)
        {
            repostTime = new Date().getTime();
        }
        else
        {
            if (new Date().getTime() - CONST_REPOST_TIMEOUT > repostTime)
            {
                this.Repost();
                return;
            }
        }

        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + m_cmdAddr);
        req.SetRepostTime(repostTime);
        req.SetPostData(repostData);
        req.SendReq();
        
        return req.GetTag();
    }
}