/**********************************************************************
* 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;

/**********************************************************************
* 公共函数
**********************************************************************/
/* 从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;
}

//获取发送数据中第position个&的值
function GetPostDataValue(postData, position)
{
  return getStringField(getStringField(postData, '&', position), '=', 2);
}

/**********************************************************************
* 客服人员类
**********************************************************************/
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_xmlHttp = null;
    var m_retryNum = 1;

    /* Ajax异步处理函数 */
    this.AjaxHandler = function()
    {
        if (4 == m_xmlHttp.readyState)
        {   
            if (200 == m_xmlHttp.status)
            {
                m_client.RequestHandler(me);
                m_xmlHttp = null;
                me = null;
            }
            else
            {
                var cmdArray = new Array('LNK', 'REG', 'QST', 'FIL', 'SRV', 'NAM', 'NTS', 'TIP');
                var cmd = GetPostDataValue(m_postData, 1);
                if (cmdArray.search(cmd) >= 0)
                {
                    if(m_retryNum > 0)
                    {
                        m_retryNum--;
                        me.Repost();
                    }
                    else
                    {
                        m_client.RequestHandler(me);
                    }
                }
            }
        }
    }
    
    /* 发送请求函数 */
    this.SendReq = function()
    {
        if (!m_isSubmit)
        {
            m_xmlHttp.open("POST", m_url, true);
            m_xmlHttp.setRequestHeader("CONTENT-TYPE", "application/x-www-form-urlencoded");
            m_xmlHttp.send(m_postData);
            //document.getElementById("input1").value = m_retryNum+" "+m_postData;
            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;
    }

    // 创建ajax对象
    this.CreateAjax = function()
    {
        try
        {
          m_xmlHttp = new ActiveXObject("MSXML2.XMLHTTP");
        }
        catch(e)
        {
          m_xmlHttp = new XMLHttpRequest();
        }

        m_xmlHttp.onreadystatechange = this.AjaxHandler;
    }

    // 重发消息
    this.Repost = function()
    {
        m_isSubmit = false;

        this.CreateAjax();
        this.SendReq();
    }
    
    this.CreateAjax();
}


/**********************************************************************
* 基于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_kftmpid = 0;
    var m_counter = 0;
    var m_lastGetTime = 0;
    var m_lastGetTag = 0;
    var m_lastSessionTime = 0;
    var m_shutdown = false;
    var m_lastRecvTime = 0;
    
    /* 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;
            m_lastRecvTime = 0;
        }
        else
        {
            m_lastGetTime = new Date().getTime();
            m_lastSessionTime = new Date().getTime();
            m_lastRecvTime = 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();
            }
        }

        if (m_lastRecvTime > 0)
        {
          var nowTime = new Date().getTime();

          if ((nowTime - m_lastRecvTime) > 60000)
          {
              this.OnNetInterrupt();
              m_lastRecvTime = 0;
          }
        }
    }
    
    /* 设置工号登录信息 */
    this.SetLoginInfo = function(srvid, session, arg, company, kfName, kfTempId)
    {
        m_srvid = srvid;
        m_session = session;
        m_arg = arg;
        m_company = company;
        m_kfName = kfName;
        m_kftmpid = kfTempId;
    }
    
    /* 创建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(ajax.status == 200)
        {
            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!");
            }
        }
        else
        {
            var postData = request.GetPostData();
            var cmd = GetPostDataValue(postData, 1);
            switch(cmd)
            {
                case "SRV":
                  this.OnSrvFail();
                  break;
                case "QST":
                  var gid = GetPostDataValue(postData, 4);
                  var msg = GetPostDataValue(postData, 6);
                  this.OnQstFail(gid, msg);
                  break;
                case "FIL":
                  var gid = GetPostDataValue(postData, 4);
                  this.OnFilFail(gid);
                  break;
                default:
                  break;
            }
        }
    }
    
    /* 处理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");
                    
                    var visitorArray = new Array();
                    
                    if (0 == errCode)
                    {
                        if(CXMLClientKf.prototype.timerID == undefined)
                        {
                          CXMLClientKf.prototype.timerID = setInterval("CXMLClientKf.prototype.ClientTimeout()",2000);
                        }

                        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.linkID = XMLGetNamedAttr(node, "link");
                            
                            visitorArray.push(visitor);
                            visitor = null;
                        }
                    }
                    else
                    {
                        this.ShutDown(true);
                    }
                    
                    this.OnSrvRsp(errCode, visitorArray);
                    break;
                case "ADDN":
                    m_addNo++;
                    break;
                case "GET":
                    m_lastRecvTime = new Date().getTime();
                    if (tag == m_lastGetTag)
                    {
                        this.GetCmd();
                    }
                    break;
                case "SHD":
                    kftmpid = XMLGetRspHead(rsp, "kftmpid");
                    if(kftmpid!=m_kftmpid)
                    {
                      this.ShutDown(true);
                      this.OnDisconnect();
                    }
                    break;
                case "WLST":
                    errCode = XMLGetRspHead(rsp, "ecode");
     
                    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 "IFIL":
                    var isBroadcast;
                    
                    if (XMLGetRspHead(rsp, "type") == 0)
                    {
                        isBroadcast = true;
                    }
                    else
                    {
                        isBroadcast = false;
                    }
                    this.OnRecvInnerFile(XMLGetRspHead(rsp, "sid"), XMLGetRspHead(rsp, "kfname"), isBroadcast, XMLGetRspHead(rsp, "filename"));
                    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":
                    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.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.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":
                            node = XMLGetNodes(rsp, "Data");
                            node = XMLGetNode(node, 0);

                            khid = XMLGetRspHead(rsp, "khid");

                            if (null != node)
                            {
                                var infos = new Object();
                                
                                infos.gid = 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":
                    errCode = XMLGetRspHead(rsp, "ecode");
                    
                    switch (XMLGetRspHead(rsp, "action"))
                    {
                        case "get":
                            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, "kfid");
                                contact.kfname = XMLGetNamedAttr(node, "kfname");
                                contact.state  = XMLGetNamedAttr(node, "state");
                                contact.type  = XMLGetNamedAttr(node, "type");
                                contact.text  = XMLGetNamedAttr(node, "text");
                                contact.notes  = XMLGetNamedAttr(node, "notes");
                                
                                contactArray.push(contact);
                                contact = null;
                            }

                            this.OnGetVisitorMeet(errCode, XMLGetRspHead(rsp, "khid"), contactArray);
                            contactArray = null;
                            break;
                        case "add":
                            this.OnAddVisitorMeet(errCode, XMLGetRspHead(rsp, "khid"));
                            break;
                        case "edit":
                            this.OnEditVisitorMeet(errCode, XMLGetRspHead(rsp, "khid"));
                            break;
                        case "del":
                            this.OnDelVisitorMeet(errCode, XMLGetRspHead(rsp, "khid"));
                            break;
                    }

                    break;
                case "OK":
                    break;
                default:
                    this.OnErr(0, "unknown rsp:" + cmd);
            }
        }
        catch(e)
        {
            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.OnRecvInnerFile = function(srvid, kfName, isBroadcast, fileName){}
    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.OnNetInterrupt = function(){}
    this.OnSrvFail = function(){}
    this.OnQstFail = function(gid, msg){}
    this.OnFilFail = function(gid){}

    this.OnGetVisitorMeet = function(errCode, gid, contactArray){}
    this.OnAddVisitorMeet = function(errCode, gid){}
    this.OnEditVisitorMeet = function(errCode, gid){}
    this.OnDelVisitorMeet = function(errCode, gid){}

    /* 帐号验证 */
    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("kftmpid", m_kftmpid);
        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();
        
        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();
    }

    /* 内部对话发送文件(IFIL) */
    this.SendInnerFile = function(did, fileName, isBroadcast)
    {
        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + m_cmdAddr);
        
        req.AddPostData("cmd", "IFIL");
        req.AddPostData("sid", m_srvid);
        req.AddPostData("kfname", m_kfName);
        req.AddPostData("did", did);
        req.AddPostData("msg", fileName);
        req.AddPostData("time", new Date().getTime());
        
        if (isBroadcast)
        {
            req.AddPostData("type", 0);
        }
        else
        {
            req.AddPostData("type", 1);
        }
        
        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.GetVisitorMeet = function(gid)
    {
        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + "/getdata.php");
        
        req.AddPostData("cmd", "MEET");
        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();
    }

    /* 添加联系记录(MEET) */
    this.AddVisitorMeet = function(meet)
    {
        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + "/getdata.php");
        
        req.AddPostData("cmd", "MEET");
        req.AddPostData("action", "add");

        req.AddPostData("khid", meet.gid);
        req.AddPostData("dwid", m_company);

        if(meet.time!=undefined)
        {
          req.AddPostData("ltime", meet.time);
        }
        if(meet.type!=undefined)
        {
          req.AddPostData("type", meet.type);
        }
        if(meet.text!=undefined)
        {
          req.AddPostData("text", meet.text);
        }
        if(meet.state!=undefined)
        {
          req.AddPostData("state", meet.state);
        }
        if(meet.notes!=undefined)
        {
          req.AddPostData("notes", meet.notes);
        }

        req.AddPostData("sessid", m_session);
        req.AddPostData("arg", m_arg);
        req.AddPostData("time", new Date().getTime());
        
        req.SendReq();
        
        return req.GetTag();
    }

    /* 编辑联系记录(MEET) */
    this.EditVisitorMeet = function(id, meet)
    {
        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + "/getdata.php");
        
        req.AddPostData("cmd", "MEET");
        req.AddPostData("action", "edit");

        req.AddPostData("id", id);
        req.AddPostData("khid", meet.gid);
        req.AddPostData("dwid", m_company);

        if(meet.time!=undefined)
        {
          req.AddPostData("ltime", meet.time);
        }
        if(meet.type!=undefined)
        {
          req.AddPostData("type", meet.type);
        }
        if(meet.text!=undefined)
        {
          req.AddPostData("text", meet.text);
        }
        if(meet.state!=undefined)
        {
          req.AddPostData("state", meet.state);
        }
        if(meet.notes!=undefined)
        {
          req.AddPostData("notes", meet.notes);
        }

        req.AddPostData("sessid", m_session);
        req.AddPostData("arg", m_arg);
        req.AddPostData("time", new Date().getTime());
        
        req.SendReq();
        
        return req.GetTag();
    }

    /* 删除联系记录(MEET) */
    this.DelVisitorMeet = function(gid, id)
    {
        var req = this.CreateRequest();
        
        if (null == req)
        {
            return;
        }
        
        req.SetURL(m_srvAddr + "/getdata.php");
        
        req.AddPostData("cmd", "MEET");
        req.AddPostData("action", "del");

        req.AddPostData("khid", gid);
        req.AddPostData("id", id);

        req.AddPostData("sessid", m_session);
        req.AddPostData("arg", m_arg);
        
        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_lnkParam = "";

    var m_counter = 0;
    var m_lastGetTime = 0;
    var m_lastGetTag = 0;

    var m_shutdown = false;
    
    /* 获取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)
            {
                this.GetCmd(true);
            }
        }
    }
    
    /* 设置访客信息 */
    this.SetKhInfo = function(gid, frompage, talkpage, lnkparam)
    {
        m_gid = gid;
        m_from = frompage;
        m_talkPage = talkpage;
        m_lnkParam = lnkparam;
    }
    
    /* 创建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(ajax.status == 200)
        {
            if (m_debug)
            {
                this.OnDebug(ajax.responseText);
            }
            
            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!");
            }
        }
        else
        {
            var postData = request.GetPostData();
            var cmd = GetPostDataValue(postData, 1);
            switch(cmd)
            {
                case "LNK":
                  this.OnLnkFail();
                  break;
                case "QST":
                  var msg = GetPostDataValue(postData, 5);
                  this.OnQstFail(msg);
                  break;
                case "FIL":
                  this.OnFilFail();
                  break;
                default:
                  break;
            }
        }
    }
    
    /* 处理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 "RLK":
                    this.OnRecvRlk();
                    break;
                case "OK":
                    break;
                default:
                    this.OnErr(0, "unknown rsp:" + cmd);
            }
        }
        catch(e)
        {
            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){}
    
    this.OnRecvRlk = function(){}
    this.OnLnkFail = function(){}
    this.OnQstFail = function(msg){}
    this.OnFilFail = function(){}
    
    /* 发起会话(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);
        req.AddPostData("lnkparam", m_lnkParam);
        
        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);
        
        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();
    }
}