// 任信客户端API文件保存路径
var TaskMsgClientAPIDir = "/inc/taskmsg/";
// 是否启用调试
var TaskMsgIsDebug = false;

//身份验证对象
var taskMsgAuthObj = null;

/**
 * 任讯权限管理类
 */
function TaskMsgAuthClass() {
  //以下变量为私有变量，不能暴露在外面
  var _sessionId;
  var _loginname;
  var _orgCode;
  var _orgKey;
  var _userId;
  var _pwd;

  this.isLoaded = false;

  this.loadAuthData = function() {
    var authData = sessionStorage.getItem("d");
    if(authData) {
      var authTs = sessionStorage.getItem("t");
      _sessionId = sessionStorage.getItem("s");
      _loginname = sessionStorage.getItem("l");
      _pwd = sessionStorage.getItem("p");
      var ivData = [_loginname, _pwd, 'web', parseInt(authTs)];
      var iv = hex_md5(JSON.stringify(ivData)).substr(0, 16);
      ivData.push(iv);
      var key = hex_md5(JSON.stringify(ivData));
      var data = CryptoJS.AES.decrypt(authData, 
        CryptoJS.enc.Utf8.parse(key), {   
          iv: CryptoJS.enc.Utf8.parse(iv),
          mode: CryptoJS.mode.CBC 
      }).toString(CryptoJS.enc.Utf8);
      var arr = JSON.parse(data);
      _orgCode = arr[0];
      _userId = arr[1];
      _orgKey = arr[2];
      arr = null;
      data = null;
      ivData = null;
      this.isLoaded = true;
    }
  };

  this.setAuthData = function(service) {
    if(!_orgCode || !_orgKey || !this.isLoaded) {
      return;
    }
    if(!service.args) service.args = {};
    service.args.sessionId = _sessionId;
    service.args._auth_ts = (new Date()).getTime();
    service.args._auth_org = _orgCode;
    var signData = [_orgCode, _orgKey, service.args._auth_ts];
    var iv = hex_md5(JSON.stringify(signData)).substr(0, 16);
    signData.push(iv);
    var key = hex_md5(JSON.stringify(signData));
    var loginData = ['userid', _userId, 'web'];
    signData.push(_pwd);
    //暂时不对请求参数进行签名，因为服务器端怎么校验还没想清楚
    //for(p in msg) {
      //signData.push(msg[p]);
    //}
    loginData.push(hex_md5(JSON.stringify(signData)));
    signData = null;
    if(service.encArgs) loginData.push(JSON.stringify(service.encArgs));
    service.args._auth_data = CryptoJS.AES.encrypt(JSON.stringify(loginData), 
      CryptoJS.enc.Utf8.parse(key), {   
        iv: CryptoJS.enc.Utf8.parse(iv),
        mode: CryptoJS.mode.CBC 
    }).toString();
  };

  this.getAuthUrl = function(url) {
    if(!_orgCode || !_orgKey || !this.isLoaded) {
      return url;
    }
    var ret = url;
    if(ret.indexOf('?')<0) ret += "?";
    if(ret.indexOf('sessionId')<0) ret += "&sessionId="+_sessionId;
    var ts = (new Date()).getTime();
    ret += "&_auth_ts="+ts+"&_auth_org="+_orgCode;
    var signData = [_orgCode, _orgKey, ts];
    var iv = hex_md5(JSON.stringify(signData)).substr(0, 16);
    signData.push(iv);
    var key = hex_md5(JSON.stringify(signData));
    var loginData = ['userid', _userId, 'web'];
    signData.push(_pwd);
    //暂时不对请求参数进行签名，因为服务器端怎么校验还没想清楚
    //for(p in msg) {
      //signData.push(msg[p]);
    //}
    loginData.push(hex_md5(JSON.stringify(signData)));
    signData = null;
    var auth_data = CryptoJS.AES.encrypt(JSON.stringify(loginData), 
      CryptoJS.enc.Utf8.parse(key), {   
        iv: CryptoJS.enc.Utf8.parse(iv),
        mode: CryptoJS.mode.CBC 
    }).toString();
    ret += "&_auth_data="+encodeURIComponent(auth_data);
    return ret;
  };
};

//身份验证对象
taskMsgAuthObj = new TaskMsgAuthClass();
try {
  taskMsgAuthObj.loadAuthData();
} catch(err) {
  console.log(err);
}

/**
 * 转换日期
 * @param  {[type]} str [description]
 * @return {[type]}     [description]
 */
Date.from = function (str) {
  if (str)
    return new Date(str.replace(/-/g, "\/"));
  else
    return new Date();
};

/**
 * 格式化日期
 * @param  {[type]} style [description]
 * @return {[type]}       [description]
 */
Date.prototype.format = function (style) {
  var y = this.getFullYear();
  var M = "0" + (this.getMonth() + 1);
  M = M.substring(M.length - 2);
  var d = "0" + this.getDate();
  d = d.substring(d.length - 2);
  var h = "0" + this.getHours();
  h = h.substring(h.length - 2);
  var m = "0" + this.getMinutes();
  m = m.substring(m.length - 2);
  var s = "0" + this.getSeconds();
  s = s.substring(s.length - 2);
  return style.replace('yyyy', y).replace('yy', (y + '').substring(2)).replace('MM', M).replace('dd', d).replace('hh', h).replace('mm', m).replace('ss', s).replace('S', this.getMilliseconds());
};

/**
 * 日期计算
 * @param  {[type]} strInterval [description]
 * @param  {[type]} Number      [description]
 * @return {[type]}             [description]
 */
Date.prototype.add = function (strInterval, Number) {
  var dtTmp = this;
  switch (strInterval) {
    case 's':
      return new Date(Date.parse(dtTmp) + (1000 * Number));
    case 'n':
      return new Date(Date.parse(dtTmp) + (60000 * Number));
    case 'h':
      return new Date(Date.parse(dtTmp) + (3600000 * Number));
    case 'd':
      return new Date(Date.parse(dtTmp) + (86400000 * Number));
    case 'w':
      return new Date(Date.parse(dtTmp) + ((86400000 * 7) * Number));
    case 'q':
      return new Date(dtTmp.getFullYear(), (dtTmp.getMonth()) + Number * 3, dtTmp.getDate(), dtTmp.getHours(), dtTmp.getMinutes(), dtTmp.getSeconds());
    case 'm':
      return new Date(dtTmp.getFullYear(), (dtTmp.getMonth()) + Number, dtTmp.getDate(), dtTmp.getHours(), dtTmp.getMinutes(), dtTmp.getSeconds());
    case 'y':
      return new Date((dtTmp.getFullYear() + Number), dtTmp.getMonth(), dtTmp.getDate(), dtTmp.getHours(), dtTmp.getMinutes(), dtTmp.getSeconds());
  }
};

/**
 * 判断字符串是否以指定的子字符串开头
 * @param  {[type]} prefix [description]
 * @return {[type]}        [description]
 */
String.prototype.startWith = String.prototype.startsWith = function (prefix) {
  return this.indexOf(prefix) === 0;
};

/**
 * 判断字符串是否以指定的子字符串结尾
 * @param  {[type]} suffix [description]
 * @return {[type]}        [description]
 */
String.prototype.endWith = String.prototype.endsWith = function (suffix) {
  return this.match(suffix + "$") == suffix;
};

/**
 * 全部替换
 * @param  {[type]} s1 [description]
 * @param  {[type]} s2 [description]
 * @return {[type]}    [description]
 */
String.prototype.replaceAll = function (s1, s2) {
  return this.replace(new RegExp(s1, "gm"), s2);
};

String.prototype.trim = function () {
  return this.replace(/(^\s*)|(\s*$)/g, "");
};

String.prototype.toDate = function () {
  return new Date(this.replace(/-/g, '/'));
};

/**
 * 判断数组中是否存在指定的元素
 * @param  {[type]} obj [description]
 * @return {[type]}     [description]
 */
Array.prototype.contains = function (obj) {
  var i = this.length;
  while (i--) {
    if (this[i] === obj) {
      return true;
    }
  }
  return false;
};

/**
 * 删除数组中指定的元素
 * @param  {[type]} obj [description]
 * @return {[type]}     [description]
 */
Array.prototype.remove = Array.prototype.deleteMember = function (obj) {
  for (var i = 0; i < this.length; i++) {
    if (this[i] === obj) {
      this.splice(i, 1);
      return;
    }
  }
};

/**
 * 判断是否是有效的手机号
 * @param  {String}  num 手机号字符串
 * @return {Boolean}     判断结果
 */
isMobile = function (num) {
  var partten = /^1\d{10}$/;
  if (partten.test(num)) return true;
  return false;
};

/**
 * 判断是否是有效的邮箱地址
 * @param  {String}  mail 邮箱地址字符串
 * @return {Boolean}      判断结果
 */
isEmail = function (mail) {
  var partten = /^[a-z0-9]+([._\\-]*[a-z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/;
  if (partten.test(mail)) return true;
  return false;
};

/**
 * 判断是否为邮政编码
 * @param  {String}  str 输入值
 * @return {Boolean}     判断结果
 */
isPostCode = function (str) {
  var result = str.match(/[1-9]\d{5}(?!\d)/);
  if (result === null) return false;
  return true;
};

/**
 * 是否是固定电话
 * @param  {String}  str 输入值
 * @return {Boolean}     判断结果
 */
isTel = function (str) {
  var result = str.match(/\d{3}-\d{8}|\d{4}-\d{7}/);
  if (result === null) return false;
  return true;
};

/**
 * 是否是身份证号
 * @param  {String}  str 输入值
 * @return {Boolean}     判断结果
 */
isIdCard = function (str) {
  var result = str.match(/\d{15}|\d{18}/);
  if (result === null) return false;
  return true;
};

/**
 * 判断是否是整数
 * @param  {[type]}  i [description]
 * @return {Boolean}   [description]
 */
isInt = function (i) {
  return i == parseInt(i);
};

/**
 * 是否存在指定函数
 * @param  {[type]}  funcName [description]
 * @return {Boolean}          [description]
 */
isExitsFunction = function (funcName) {
  try {
    if (typeof (eval(funcName)) == "function") {
      return true;
    }
  } catch (e) {}
  return false;
};

/**
 * 格式化金额
 * @param  {[type]} s 输入值
 * @param  {[type]} n 小数点位数
 * @return {[type]}   返回值
 */
formatMoney = function (s, n) {
  n = n > 0 && n <= 20 ? n : 2;
  s = parseFloat((s + "").replace(/[^\d\.-]/g, "")).toFixed(n) + "";
  var l = s.split(".")[0].split("").reverse();
  var r = s.split(".")[1];
  var t = "";
  for (var i = 0; i < l.length; i++) {
    t += l[i] + ((i + 1) % 3 === 0 && (i + 1) != l.length ? "," : "");
  }
  return t.split("").reverse().join("") + "." + r;
};

/**
 * 格式化日期
 * @param  {[type]} d 输入值
 * @param  {[type]} f 格式
 * @return {[type]}   返回值
 */
formatDate = function (d, f) {
  if (typeof (d) == "number")
    return (new Date(d)).format(f);
  else
    return (new Date(Date.parse(d.replace("T", " ").replace("+08:00", " ").replace(/-/g, "/")))).format(f);
};

/**
 * 格式化文件大小
 * @param  {[type]} bytes [description]
 * @return {[type]}       [description]
 */
formatFileSize = function (bytes) {
  if (bytes === 0) return '0 B';
  var k = 1000, // or 1024
    sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
    i = Math.floor(Math.log(bytes) / Math.log(k));
  if (i == -1) return '0.1 B';
  return (bytes / Math.pow(k, i)).toPrecision(3) + ' ' + sizes[i];
};

/**
 * 获得样式中的像素值，将px字母删掉，转换为整数
 * @param  {[type]} value [description]
 * @return {[type]}       [description]
 */
getPixel = function (value) {
  return parseInt((new String(value)).replace("px", ""));
};

/**
 * 获得URL中的所有参数
 * @param  {[type]} url [description]
 * @return {[type]}     [description]
 */
getUrlArgs = function (url) {
  var args = {};
  var start = url.indexOf("?");
  if (start < 0) return args;
  var str = url.substr(start + 1);
  if (str.indexOf("&") < 0) {
    var strArr = str.split("=");
    args[strArr[0]] = strArr[1];
    return args;
  }
  var strArr = str.split("&");
  for (var i = 0; i < strArr.length; i++) {
    var strArr2 = strArr[i].split("=");
    args[strArr2[0]] = strArr2[1];
  }
  return args;
};

/**
 * 获得URL中的指定参数的值
 * @param  {[type]} argName [description]
 * @return {[type]}         [description]
 */
getUrlArg = function (argName) {
  var url = window.location.href;
  //console.log(url);
  //if(typeof(MPhone) != "undefined") {
  //url = MPhone.GetRealUrl();
  //}
  var start = url.indexOf("?");
  if (start < 0) return null;
  var str = url.substr(start + 1);
  if (str.indexOf("&") < 0) {
    var strArr = str.split("=");
    if (strArr[0] == argName) return decodeURIComponent(strArr[1]);
    return null;
  }
  var strArr = str.split("&");
  for (var i = 0; i < strArr.length; i++) {
    var strArr2 = strArr[i].split("=");
    if (strArr2[0] == argName) return decodeURIComponent(strArr2[1]);
  }
  return null;
};

/**
 * 替换字段变量
 * @param  {[type]} obj     [description]
 * @param  {[type]} str     [description]
 * @return {[type]}         [description]
 */
replaceDataField = function (obj, str) {
  var start = str.indexOf("{");
  if (start < 0) return str;
  var end = str.indexOf("}", start);
  if (end < 0) return str;
  var fieldStr = str.substr(start + 1, end - start - 1);
  var fieldName = fieldStr;
  var format = "";
  if (fieldStr.indexOf(",") > 0) {
    format = fieldStr.substr(fieldStr.indexOf(",") + 1);
    fieldName = fieldStr.substr(0, fieldStr.indexOf(","));
  }
  if (fieldName in obj && (obj[fieldName] || obj[fieldName] == 0)) {
    if (format == "datetime") {
      if ((obj[fieldName] + '').indexOf("T") > 0) {
        str = str.replace("{" + fieldStr + "}", (new Date(obj[fieldName] + '')).format("yyyy-MM-dd hh:mm"));
      } else {
        str = str.replace("{" + fieldStr + "}", (new Date((obj[fieldName] + '').replace(/-/g, '/'))).format("yyyy-MM-dd hh:mm"));
      }
    } else if (format == "date") {
      if ((obj[fieldName] + '').indexOf("T") > 0) {
        str = str.replace("{" + fieldStr + "}", (new Date(obj[fieldName] + '')).format("yyyy-MM-dd"));
      } else {
        str = str.replace("{" + fieldStr + "}", (new Date((obj[fieldName] + '').replace(/-/g, '/'))).format("yyyy-MM-dd"));
      }
    } else if (format == "time") {
      if ((obj[fieldName] + '').indexOf("T") > 0) {
        str = str.replace("{" + fieldStr + "}", (new Date(obj[fieldName] + '')).format("hh:mm:ss"));
      } else {
        str = str.replace("{" + fieldStr + "}", (new Date((obj[fieldName] + '').replace(/-/g, '/'))).format("hh:mm:ss"));
      }
    } else if ((format.indexOf("\"") >= 0 || format.indexOf("'") >= 0) &&
      (format.indexOf("yy") >= 0 || format.indexOf("MM") >= 0 ||
        format.indexOf("dd") >= 0 || format.indexOf("hh") >= 0 ||
        format.indexOf("ss") >= 0)) {
      format = format.replace(/"/g, "").replace(/'/g, "");
      var dateStr = obj[fieldName] + '';
      if (dateStr.indexOf("T") < 0) dateStr = dateStr.replace(/-/g, '/');
      str = str.replace("{" + fieldStr + "}", (new Date(dateStr)).format(format));
    } else if (format == "int") {
      str = str.replace("{" + fieldStr + "}", formatNumber(obj[fieldName], 0));
    } else if (format == "money") {
      str = str.replace("{" + fieldStr + "}", formatMoney(obj[fieldName], 2));
    } else if (format == "filesize") {
      str = str.replace("{" + fieldStr + "}", formatFileSize(obj[fieldName]));
    } else {
      str = str.replace("{" + fieldStr + "}", (obj[fieldName] + "").replace(/\{/g, "`(`").replace(/\}/g, "`)`"));
    }
  } else {
    str = str.replace("{" + fieldStr + "}", "");
  }
  return replaceDataField(obj, str);
};

/**
 * 执行表达式
 * @param  {[type]} str     [description]
 * @return {[type]}         [description]
 */
exeExpress = function (str) {
  var start = str.indexOf("#[");
  if (start < 0) return str.replace(/\`\(\`/g, "{").replace(/\`\)\`/g, "}");
  var end = str.indexOf("]", start);
  if (end < 0) return str;
  var express = str.substr(start + 2, end - start - 2);
  var value = eval(express);
  var newStr = "";
  if (start > 0) newStr += str.substr(0, start);
  newStr += eval(express);
  if (end < (str.length - 1)) newStr += str.substr(end + 1);
  return exeExpress(newStr);
};

/**
 * 获取请求对象
 * @return {[type]}         [description]
 */
function getHttpRequest() {
  var httpRequest;
  if (window.XMLHttpRequest) {
    httpRequest = new XMLHttpRequest();
  } else if (window.ActiveXObject) {
    httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
    if (!httpRequest) {
      httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
    }
  }
  if (!httpRequest) {
    alert("您的浏览器不支持Ajax，无法执行该操作！");
    return null;
  }
  return httpRequest;
}

/**
 * 引用
 * @param  {[type]} url     [description]
 * @return {[type]}         [description]
 */
function require(url) {
  if (!url) return;
  var fileType = "";
  if (url.toLowerCase().lastIndexOf(".js") > 0) {
    fileType = "js";
  } else if (url.toLowerCase().lastIndexOf(".css") > 0) {
    fileType = "css";
  } else {
    alert("不支持对路径[" + url + "]的引用！");
    return;
  }

  var isExist = false;
  if (fileType == "js") {
    $("script").each(function () {
      if ($(this).attr("src") == url) {
        isExist = true;
        return false;
      }
    });
  } else {
    $("link").each(function () {
      if ($(this).attr("href") == url) {
        isExist = true;
        return false;
      }
    });
  }
  if (isExist) return;

  var httpRequest = getHttpRequest();
  httpRequest.onreadystatechange = function () {
    if (httpRequest.readyState == 4) {
      if (httpRequest.status == 200 || httpRequest.status == 304) {
        if (!httpRequest.responseText) return;
        if (fileType == "js") {
          $("head").append("<script type=\"text/javascript\">" + httpRequest.responseText + "</script>");
        } else {
          $("head").append("<style>" + httpRequest.responseText + "</style>");
        }
      } else {
        alert("发送http请求时发生意外错误：" + httpRequest.statusText + "(" + httpRequest.status + ")");
      }
    }
  };
  httpRequest.open('GET', url, false);
  httpRequest.send(null);
}

/**
 * 服务对象
 * @param string serviceTagId 服务标签的编号
 */
function TaskMsgService(serviceTagId) {
  this.onError = null; //处理错误的回调函数
  this.autoShowErr = true; //是否自动显示错误提示
  this.srcElement = null; //请求服务的源节点
  this.serviceTag = null; //定义服务信息的标签
  this.app = null; //
  this.path = null; //服务的路径
  this.onResponse = null; //服务器端返回响应信息之后执行的回调函数
  this.notSessionId = false;

  /**
   * 显示错误信息
   * @param  {[type]} msg [description]
   * @return {[type]}     [description]
   */
  this.showError = function (msg) {
    tmClient.debug(msg);
    if (this.autoShowErr) alert(msg);
    if (this.onError) this.onError(msg);
  };

  /**
   * 设置请求参数
   * @param {[type]} argName [description]
   * @param {[type]} val     [description]
   */
  this.setArg = function (argName, val) {
    $("#" + serviceTagId).find("arg").each(function () {
      if ($(this).attr("name") == argName) {
        $(this).attr("type", "");
        if (typeof (val) == "string" ||
          typeof (val) == "number" ||
          typeof (val) == "boolean") {
          $(this).attr("value", val);
        } else {
          $(this).attr("value", JSON.parse(val));
        }
      }
    });
  };

  /**
   * 设置对象型请求参数
   * @param {[type]} obj [description]
   */
  this.setArgs = function (obj) {
    $("#" + serviceTagId).find("arg").each(function () {
      var val = obj[$(this).attr("name")];
      if (!val) val = "";
      $(this).attr("type", "");
      if (typeof (val) == "string" ||
        typeof (val) == "number" ||
        typeof (val) == "boolean") {
        $(this).attr("value", val);
      } else {
        $(this).attr("value", JSON.parse(val));
      }
    });
  };

  /**
   * 请求
   * @param  {[type]} args       [description]
   * @param  {[type]} onResponse [description]
   * @return {[type]}            [description]
   */
  this.request = function (args, onResponse) {
    if (serviceTagId) {
      this.serviceTag = $("#" + serviceTagId);
      this.app = this.serviceTag.attr("app");
      if (this.serviceTag.attr("path"))
        this.path = this.serviceTag.attr("path");
      else
        this.path = this.serviceTag.data("path");
      if (this.serviceTag.attr("onResponse"))
        this.onResponse = this.serviceTag.attr("onResponse");
    }
    if (!this.path) {
      this.showError("请提供服务路径！");
      return;
    }
    
    if (window.event) this.srcElement = window.event.srcElement;
    if (onResponse) this.onResponse = onResponse;

    if (!args) args = {};
    if (this.app) args.app = this.app;

    if (this.serviceTag && this.serviceTag.children().length > 0) {
      this.serviceTag.find("arg").each(function () {
        if ($(this).attr("type") == "queryString") {
          args[$(this).attr("name")] = getUrlArg($(this).attr("field"));
        } else if ($(this).attr("type") == "formInput") {
          var formId = $(this).attr("form");
          var inputId = $(this).attr("input");
          if (formId) {
            var form = taskMsgForms[formId];
            if (form.inputs[inputId]) {
              args[$(this).attr("name")] = form.inputs[inputId].getValue();
            }
          } else {
            for (var _formId in taskMsgForms) {
              var form = taskMsgForms[_formId];
              if (form.inputs[inputId]) {
                args[$(this).attr("name")] = form.inputs[inputId].getValue();
                break;
              }
            }
          }
        } else {
          args[$(this).attr("name")] = $(this).attr("value");
        }
      });
    }
    
    this.args = args;
    if(taskMsgAuthObj.isLoaded) {
      taskMsgAuthObj.setAuthData(this);
    }
    //var encryptUserInfo = getUrlArg("encryptUserInfo");
    //if (encryptUserInfo) this.args["encryptUserInfo"] = encryptUserInfo;

    if ("undefined" != typeof RDASServiceHandlerPath) {
      this.requestRDASService(this.path, args, onResponse);
    } else if (args.noTmClient) {
      this.sendRequest();
    } else {
      if (tmClient) {
        if (tmClient.sessionId) {
          this.sendRequest();
        } else {
          if (tmClient.clientOSType == "iOS") {
            tmClient.waitProcessServices.push(this);
          } else {
            try {
              tmClient.getSessionId();
            } catch (e) {}
            this.sendRequest();
          }
        }
      } else {
        console.log("tmClient undefined");
      }
    }
  };

  /**
   * 请求RDAS服务
   * @param  {[type]}   servicePath [description]
   * @param  {[type]}   serviceArgs [description]
   * @param  {Function} cb          [description]
   * @return {[type]}               [description]
   */
  this.requestRDASService = function (servicePath, serviceArgs, cb) {
    var request = new ServiceRequest();
    if (cb) request.cb = cb;
    if (serviceArgs) {
      request.args = serviceArgs;
      tmClient.debug("发送请求：\r\n" + JSON.stringify(serviceArgs));
    }
    if (serviceArgs) {
      for (objId in serviceArgs) {
        var obj = serviceArgs[objId];
        if (!obj || typeof (obj) == "undefined" || typeof (obj) == "function") continue;
        if (typeof (obj) == "number" || typeof (obj) == "string" || typeof (obj) == "boolean") {
          request.add(objId, obj);
        } else if (obj.constructor == Array) {
          request.addObjects(objId, obj);
        } else if (obj instanceof Date) {
          request.add(objId, formatDate(obj, "yyyy-MM-dd hh:mm:ss"));
        } else {
          request.addObject(objId, obj);
        }
      }
    }
    request.notResponseOnError = false;
    request.send(servicePath, this.onRDASResponse);
  };

  /**
   * 处理RDAS响应
   * @param  {[type]} request  [description]
   * @param  {[type]} response [description]
   * @return {[type]}          [description]
   */
  this.onRDASResponse = function (request, response) {
    var res = response.getJsonObject();
    tmClient.debug("接收响应：\r\n" + JSON.stringify(res));
    if (request.cb) {
      if (typeof request.cb == "function") {
        request.cb(request, res);
      } else {
        eval(request.cb + "(request, res)");
      }
    }
  };

  /**
   * 发送请求
   * @return {[type]} [description]
   */
  this.sendRequest = function () {
    if (!this.notSessionId && !this.args.encryptUserInfo &&
      this.path != 'sys/service/login' && tmClient.sessionId &&
      !(tmClient.sessionId == "(null)" || tmClient.sessionId == "undefined" || tmClient.sessionId == ""))
      this.args.sessionId = tmClient.sessionId;
    this.args.service = this.path;

    var httpRequest = getHttpRequest();
    try {
      var self = this;
      httpRequest.onreadystatechange = function () {
        if (httpRequest.readyState == 4) {
          if (httpRequest.status == 200) {
            // tmClient.debug("接收响应：\r\n"+httpRequest.responseText);
            var response = JSON.parse(httpRequest.responseText);
            if (response.code === 0) {
              if (self.onResponse) {
                if (self.srcElement) self.args.srcElement = self.srcElement;
                if (typeof self.onResponse == "function") {
                  self.onResponse(self.args, response);
                } else {
                  if (self.onResponse.indexOf(".") < 0 && self.onResponse.indexOf(" ") < 0 &&
                    self.onResponse.indexOf("=") < 0 && self.onResponse.indexOf("(") < 0 &&
                    self.onResponse.indexOf(")") < 0) {
                    eval(self.onResponse + "(self.args, response)");
                  } else {
                    eval(self.onResponse);
                  }
                }
              }
            } else {
              if (response.code == 501) {
                if (tmClient.clientOSType == "PC") top.location = "/";
                return;
              }
              self.showError(response.message);
            }
          } else if (httpRequest.status == 404) {
            self.showError("请求的服务不存在！");
          } else {
            if (httpRequest.status !== 0)
              self.showError("向服务器发送请求时发生意外错误！\r\n错误代码：" + httpRequest.status);
          }
        }
      };

      var serverPath = top.location.toString();
      serverPath = serverPath.substr(0, serverPath.indexOf("/", 8) + 1);
      httpRequest.open("POST", serverPath + "Service", true);
      httpRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
      //tmClient.debug("发送请求：\r\n"+JSON.stringify(this.args));
      //console.log(JSON.stringify(this.args));
      httpRequest.send(JSON.stringify(this.args));
    } catch (e) {
      this.showError("向服务器发送请求时发生意外错误！\r\n错误描述：" + e.message);
    }
  };
}

var taskMsgDetailInfos = {};

/**
 * 详细信息控件
 */
function TaskMsgDetailInfo() {
  this.getDataService = null; //获得数据的服务
  this.dataMember = null; //表单对应的数据源对象名
  this.dataSource = null; //数据源对象
  this.onLoadData = null; //加载数据前执行的回调函数
  this.onBindData = null; //加载数据后执行的回调函数
  this.jQueryObj = null; //jQuery对象

  var that = this;

  /**
   * 初始化控件
   * @param  {[type]} obj [description]
   * @return {[type]}     [description]
   */
  this.init = function (obj) {
    this.jQueryObj = obj;
    if (obj.attr("getDataService")) this.getDataService = obj.attr("getDataService");
    if (obj.attr("dataMember")) this.dataMember = obj.attr("dataMember");
    if (obj.attr("onLoadData")) this.onLoadData = obj.attr("onLoadData");
    if (obj.attr("onBindData")) this.onBindData = obj.attr("onBindData");
    if (this.getDataService) {
      var service = new TaskMsgService(this.getDataService);
      service.request(null, function (req, res) {
        that.dataBind(req, res);
      });
    }
  };

  /**
   * 绑定数据
   * @param  {[type]} req [description]
   * @param  {[type]} res [description]
   */
  this.dataBind = function (req, res) {
    if (this.onLoadData) eval(this.onLoadData + "(req, res)");
    if (this.dataMember && res[this.dataMember]) {
      this.dataSource = res[this.dataMember];
    }
    var strHtml = replaceDataField(this.dataSource, this.jQueryObj.get(0).innerHTML);
    strHtml = exeExpress(strHtml);
    this.jQueryObj.empty();
    this.jQueryObj.append(strHtml);
    this.jQueryObj.show();
    if (this.onBindData) eval(this.onBindData + "(req, res)");
  };
}

$(function () {
  $(".TaskMsgDetailInfo").each(function (index) {
    var info = new TaskMsgDetailInfo();
    if ($(this).attr("id")) {
      info.id = $(this).attr("id");
    } else {
      info.id = "TaskMsgDetailInfo_" + index;
    }
    taskMsgDetailInfos[info.id] = info;
    info.init($(this));
  });
});


/**
 * IOS 13以上版本
 */
function TaskMsgIOSClient() {
  this.Alert = function (msg) {
    window.webkit.messageHandlers.Alert.postMessage(msg);
  };
  
  this.SetMoreMenu = function(menuInfo) {
    window.webkit.messageHandlers.SetMoreMenu.postMessage(menuInfo);
  };
}

/**
 * 任信客户端
 */
function TaskMsgClient() {
  this.version = "0.2.1"; //版本号
  this.waitProcessServices = []; //等待处理的服务请求
  this.sessionId = null; //会话编号
  this.TMiOSClientIsInit = false; //iOS客户端是否已初始化
  this.isDisableGoBack = false; //是否禁止退回
  this.AndroidClientCallBackFuncIndex = 1000; //安卓客户端回调函数索引
  this.clientOSType = null; //客户端类型
  this.iOSClientInitScript = []; //iOS客户端初始化脚本

  /**
   * 初始化客户端对象
   * @return {[type]} [description]
   */
  this.init = function () {
    //获得客户端类型
    if (navigator.userAgent.indexOf("iPhone") > 0) {
      this.clientOSType = "iOS";
    } else if (navigator.userAgent.indexOf("Windows") > 0 || navigator.userAgent.indexOf("Mac OS") > 0) {
      this.clientOSType = "PC";
      this.sessionId = localStorage.getItem("Simulator_TaskMsgSessionId");
    } else {
      this.clientOSType = "Android";
    }
    //如果手机上的链接是在新窗口里打开，则用浏览器扩展打开新窗口
    /*
    if(tmClient.clientOSType!="PC") {
      document.onclick = function(e) {
        e = window.event || e;
        var srcElement = e.srcElement || e.target;
        if (srcElement.tagName == 'A') {
          console.log(e); 
        }
      };
    }
    */
  };

  /**
   * 处理等待的服务请求
   * @return {[type]} [description]
   */
  this.processWaitServices = function () {
    for (var i = 0; i < this.waitProcessServices.length; i++) {
      var service = this.waitProcessServices[i];
      service.sendRequest();
    }
    this.waitProcessServices = [];
  };

  /**
   * 获得模拟器窗口
   * @return {[type]} [description]
   */
  this.getSimulator = function () {
    var p = parent;
    while (p && !p.isSimulator) {
      if (p == top) return null;
      p = p.parent;
    }
    return p;
  };

  /**
   * 清除通知栏提醒
   * @param  {[type]} tag [description]
   * @param  {[type]} id  [description]
   * @return {[type]}     [description]
   */
  this.cancelNotification = function (tag, id) {
    if (!tag) {
      alert("请提供通知栏标签。");
      return;
    }

    if (!id) {
      alert("请提供通知栏编号。");
      return;
    }

    if (this.clientOSType == "iOS") {
      //
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.cancelNotification(tag, id);
    }
  };

  /**
   * 获得会话编号
   * @param  {[type]} callbackFunc [description]
   * @return {[type]}              [description]
   */
  this.getSessionId = function (callbackFunc) {
    var callback = "onGetSessionId";
    if (callbackFunc) callback = callbackFunc;

    var sId = getUrlArg("sessionId");
    if (sId && sId != "undefined" && sId != "null" && sId != "") {
      this.sessionId = sId;
      if (isExitsFunction(callback)) eval(callback + "('" + this.sessionId + "')");
      return sId;
    }
    if (this.clientOSType == "iOS") {
      if (this.TMiOSClientIsInit) {
        if(this.sessionId) return this.sessionId;
        this.sessionId = TMiOSClient.GetSessionId();
        if (isExitsFunction(callback)) eval(callback + "('" + this.sessionId + "')");
      } else {
        this.iOSClientInitScript.push("tmClient.sessionId = TMiOSClient.GetSessionId('" + callback + "')");
      }
    } else if (this.clientOSType == "Android") {
      this.sessionId = TMAndroidClient.getSessionId();
      if (isExitsFunction(callback)) eval(callback + "('" + this.sessionId + "')");
    } else {
      this.sessionId = localStorage.getItem("Simulator_TaskMsgSessionId");
      if (isExitsFunction(callback)) eval(callback + "('" + this.sessionId + "')");
    }
    return this.sessionId;
  };

  /**
   * 获得用户目录路径
   * @param  {[type]} callbackFunc [description]
   * @return {[type]}              [description]
   */
  this.getUserDir = function (callbackFunc) {
    var callback = "onGetUserDir";
    if (callbackFunc) callback = callbackFunc;

    var dir = null;
    if (this.clientOSType == "iOS") {
      dir = TMiOSClient.GetUserDir();
    } else if (this.clientOSType == "Android") {
      dir = TMAndroidClient.getUserDir();
    }
    if (isExitsFunction(callback)) eval(callback + "('" + dir + "')");
    return dir;
  };

  /**
   * 显示用户选择窗口
   * @param  {[type]}  callbackFunc  [description]
   * @param  {Boolean} isMutiSelect  [description]
   * @param  {[type]}  canSelectSelf [description]
   * @param  {[type]}  title         [description]
   * @param  {[type]}  defaultValue  [description]
   * @param  {[type]}  range         [description]
   * @return {[type]}                [description]
   */
  this.showUserPicker = function (callbackFunc, isMutiSelect, canSelectSelf, title, defaultValue, range) {
    var callback = "onSelectUsers";
    if (callbackFunc) callback = callbackFunc;

    var args = {};
    args.callback = callback;
    if (isMutiSelect) args.isMutiSelect = isMutiSelect;
    if (canSelectSelf) args.canSelectSelf = canSelectSelf;
    if (title) args.title = title;
    if (defaultValue) args.defaultValue = defaultValue;
    if (range) args.range = range;

    if (this.clientOSType == "iOS") {
      TMiOSClient.ShowUserPicker(JSON.stringify(args));
    } else if (this.clientOSType == "Android") {
      args.requestCode = this.AndroidClientCallBackFuncIndex;
      this.AndroidClientCallBackFuncIndex++;
      TMAndroidClient.showUserPicker(JSON.stringify(args));
    }
  };

  /**
   * 显示部门选择窗口
   * @param  {[type]}  callbackFunc [description]
   * @param  {Boolean} isMutiSelect [description]
   * @return {[type]}               [description]
   */
  this.showDepPicker = function (callbackFunc, isMutiSelect) {
    var callback = "onSelectDeps";
    if (callbackFunc) callback = callbackFunc;
    var args = {};
    args.callback = callback;
    if (isMutiSelect) args.isMutiSelect = isMutiSelect;

    if (this.clientOSType == "iOS") {
      TMiOSClient.ShowDepPicker(JSON.stringify(args));
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.showDepPicker(JSON.stringify(args));
    }
  };

  /**
   * 打开网盘
   * @param  {[type]}  args         [description]
   * @return {[type]}               [description]
   */
  this.openNetDisk = function (args) {
    if (!args) {
      alert("请提供必要参数。");
      return;
    }
    if (!args.type) {
      alert("请提供类型。");
      return;
    }
    if (this.clientOSType == "iOS") {
      TMiOSClient.OpenNetDisk(JSON.stringify(args));
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.openNetDisk(JSON.stringify(args));
    }
  };

  /**
   * 显示树形选择窗口
   * @param  {[type]}  callbackFunc [description]
   * @param  {Boolean} isMutiSelect [description]
   * @param  {Boolean} isSelectAll  [description]
   * @param  {[type]}  title        [description]
   * @param  {[type]}  defaultValue [description]
   * @param  {[type]}  dep          [description]
   * @param  {[type]}  user         [description]
   * @return {[type]}               [description]
   */
  this.showTreePicker = function (callbackFunc, isMutiSelect, isSelectAll, title, defaultValue, dep, user) {
    var callback = "onSelectTrees";
    if (callbackFunc) callback = callbackFunc;
    var args = {};
    args.callback = callback;

    if (isMutiSelect) args.isMutiSelect = isMutiSelect;
    if (isSelectAll) args.isSelectAll = isSelectAll;
    if (title) args.title = title;
    if (defaultValue) args.defaultValue = defaultValue;
    if (dep) args.dep = dep;
    if (user) args.user = user;
    if (this.clientOSType == "iOS") {
      TMiOSClient.ShowTreePicker(JSON.stringify(args));
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.showTreePicker(JSON.stringify(args));
    }
  };

  /**
   * 显示时间选择窗口
   * @param  {[type]} callbackFunc   [description]
   * @param  {[type]} dateType       [description]
   * @param  {[type]} defaultValue   [description]
   * @param  {[type]} cancelCallback [description]
   * @param  {[type]} cleanCallback  [description]
   * @return {[type]}                [description]
   */
  this.showDateTimePicker = function (callbackFunc, dateType, defaultValue, cancelCallback, cleanCallback) {
    var callback = "onSelectDateTime";
    if (callbackFunc) callback = callbackFunc;
    var args = {};
    args.callback = callback;
    args.dateType = "datetime";
    if (dateType) args.dateType = dateType;
    if (defaultValue) args.defaultValue = defaultValue;

    if (this.clientOSType == "iOS") {
      TMiOSClient.ShowDateTimePicker(JSON.stringify(args));
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.showDateTimePicker(JSON.stringify(args));
    }
  };

  /**
   * 显示扫一扫窗口
   * @param  {[type]} callbackFunc [description]
   * @param  {[type]} isMulti      [description]
   * @param  {[type]} isRepetition [description]
   * @return {[type]}              [description]
   */
  this.showCodeScanner = function (callbackFunc, isMulti, isRepetition, canAlbum) {
    var callback = "onCodeScaned";
    if (callbackFunc) callback = callbackFunc;
    var args = {};
    args.callback = callback;

    if (isMulti) args.isMulti = isMulti;
    if (isRepetition) args.isRepetition = isRepetition;
    if (canAlbum) args.canAlbum = canAlbum;
    if (this.clientOSType == "iOS") {
      if (this.TMiOSClientIsInit) {
        TMiOSClient.ShowCodeScanner(JSON.stringify(args));
      } else {
        this.iOSClientInitScript.push("TMiOSClient.ShowCodeScanner('" + JSON.stringify(args) + "')");
      }
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.showBarcodeScanner(JSON.stringify(args));
    }
  };

  /**
   * 显示扫一扫条形码窗口
   * @param  {[type]} callbackFunc [description]
   * @param  {[type]} isMulti      [description]
   * @param  {[type]} isRepetition [description]
   * @return {[type]}              [description]
   */
  this.showBarCodeScanner = function (callbackFunc, isMulti, isRepetition, canAlbum) {
    var callback = "onCodeScaned";
    if (callbackFunc) callback = callbackFunc;
    var args = {};
    args.callback = callback;

    if (isMulti) args.isMulti = isMulti;
    if (isRepetition) args.isRepetition = isRepetition;
    if (canAlbum) args.canAlbum = canAlbum;
    args.codeType = 1;
    if (this.clientOSType == "iOS") {
      TMiOSClient.ShowBarCodeScanner(JSON.stringify(args));
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.showBarcodeScanner(JSON.stringify(args));
    }
  };

  /**
   * 显示扫一扫二维码窗口
   * @param  {[type]} callbackFunc [description]
   * @param  {[type]} isMulti      [description]
   * @param  {[type]} isRepetition [description]
   * @return {[type]}              [description]
   */
  this.showQRCodeScanner = function (callbackFunc, isMulti, isRepetition, canAlbum) {
    var callback = "onCodeScaned";
    if (callbackFunc) callback = callbackFunc;
    var args = {};
    args.callback = callback;

    if (isMulti) args.isMulti = isMulti;
    if (isRepetition) args.isRepetition = isRepetition;
    if (canAlbum) args.canAlbum = canAlbum;
    args.codeType = 2;
    if (this.clientOSType == "iOS") {
      TMiOSClient.ShowQRCodeScanner(JSON.stringify(args));
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.showBarcodeScanner(JSON.stringify(args));
    }
  };

  /**
   * 显示商品扫一扫条形码窗口（定制）
   * @param  {[type]} callbackFunc [description]
   * @param  {[type]} list         [description]
   * @return {[type]}              [description]
   */
  this.showProductBarCodeScanner = function (callbackFunc, list, isTransf) {
    var alist = [];
    if (isTransf) {
      for (var i = 0; i < list.length; i++) {
        alist.push({
          "id": list[i].item_id + "|" + list[i].sku_id + "|" + list[i].iInvSPrice + "|" + list[i].iInvLSCost + "|" + list[i].iInvSCost,
          "name": list[i].cInvName + " " + list[i].cInvStd,
          "code": list[i].barcode
        });
      }
    } else {
      alist = list;
    }
    var callback = "onCodeScaned";
    if (callbackFunc) callback = callbackFunc;
    var args = {};
    args.callback = callback;
    args.list = alist;
    if (this.clientOSType == "iOS") {
      TMiOSClient.ShowProductBarCodeScanner(JSON.stringify(args));
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.showProductBarCodeScanner(JSON.stringify(args));
    }
  };

  /**
   * 微信支付（客户端直接支付）
   * @param  {[type]} callbackFunc [description]
   * @param  {[type]} out_trade_no 订单号
   * @param  {[type]} total_fee    金额
   * @param  {[type]} notify_url   回调地址
   * @return {[type]}              [description]
   */
  this.showWxPayByMobile = function (callbackFunc, out_trade_no, total_fee, notify_url) {
    var callback = "onWxPay";
    if (callbackFunc) callback = callbackFunc;
    var args = {};
    args.callback = callback;

    if (out_trade_no) args.out_trade_no = out_trade_no;
    if (total_fee) args.total_fee = total_fee;
    if (notify_url) args.notify_url = notify_url;
    if (this.clientOSType == "iOS") {
      TMiOSClient.ShowWxPayByMobile(JSON.stringify(args));
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.showWxPayByMobile(JSON.stringify(args));
    }
  };

  /**
   * 微信支付
   * @param  {[type]} callbackFunc    [description]
   * @param  {[type]} appid           应用APPID
   * @param  {[type]} partnerid       商户号
   * @param  {[type]} prepayid        预支付回话标识
   * @param  {[type]} package         扩展字段
   * @param  {[type]} noncestr        随机字符串
   * @param  {[type]} timestamp       时间戳
   * @param  {[type]} sign            签名
   * @return {[type]}                 [description]
   */
  this.showWxPayByServer = function (callbackFunc, appid, partnerid, prepayid, package, noncestr, timestamp, sign) {
    var callback = "onWxPay";
    if (callbackFunc) callback = callbackFunc;
    var args = {};
    args.callback = callback;

    if (appid) args.appid = appid;
    if (partnerid) args.partnerid = partnerid;
    if (prepayid) args.prepayid = prepayid;
    if (package) args.package = package;
    if (noncestr) args.noncestr = noncestr;
    if (timestamp) args.timestamp = timestamp;
    if (sign) args.sign = sign;
    if (this.clientOSType == "iOS") {
      TMiOSClient.ShowWxPayByServer(JSON.stringify(args));
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.showWxPayByServer(JSON.stringify(args));
    }
  };

  /**
   * 签章（北京CA）
   * @param  {[password]} password    [description]
   */
  this.getSingStamp = function (callbackFunc, password, id) {
    var callback = "onSingStamp";
    if (callbackFunc) callback = callbackFunc;
    var args = {};
    args.callback = callback;
    args.password = password;
    args.id = id;
    if (this.clientOSType == "iOS") {
      TMiOSClient.GetSingStamp(JSON.stringify(args));
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.getSingStamp(JSON.stringify(args));
    }
  };

  /**
   * 登录
   * @param  {[type]} orgCode      [description]
   * @param  {[type]} loginName    [description]
   * @param  {[type]} password     [description]
   * @param  {[type]} callbackFunc [description]
   * @return {[type]}              [description]
   */
  this.Login = function (orgCode, loginName, password, callbackFunc) {
    var args = {};
    args.orgCode = orgCode;
    args.loginName = loginName;
    args.password = password;
    args.callbackFunc = callbackFunc;
    if (this.clientOSType == "iOS") {
      if (this.TMiOSClientIsInit) {
        TMiOSClient.Login(JSON.stringify(args));
      } else {
        this.iOSClientInitScript.push("TMiOSClient.Login('" + JSON.stringify(args) + "')");
      }
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.login(JSON.stringify(args));
    }
  };

  /**
   * 微信分享
   * @param  {[type]} title        标题
   * @param  {[type]} description  内容
   * @param  {[type]} url          路径
   * @param  {[type]} callbackFunc 回调
   * @return {[type]}              [description]
   */
  this.showWxShare = function (title,description,url,callbackFunc) {
    var args = {};
    args.title = title;
    args.description = description;
    args.url = url;
    args.callback = callbackFunc;
    if (this.clientOSType == "iOS") {
      if (this.TMiOSClientIsInit) {
        TMiOSClient.WeixinShare(JSON.stringify(args));
      } else {
        this.iOSClientInitScript.push("TMiOSClient.WeixinShare('" + JSON.stringify(args) + "')");
      }
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.weixinShare(JSON.stringify(args));
    }
  };

  /**
   * 打开设置
   * @param  {[type]} type    [description]
   */
  this.openSetting = function (type) {
    var args = {};
    args.type = type;
    if (this.clientOSType == "iOS") {
      if (this.TMiOSClientIsInit) {
        TMiOSClient.OpenSetting(JSON.stringify(args));
      } else {
        this.iOSClientInitScript.push("TMiOSClient.OpenSetting('" + JSON.stringify(args) + "')");
      }
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.openSetting(JSON.stringify(args));
    }
  };

  /**
   * 设置本地缓存
   * @param  {[type]} key       [description]
   * @param  {[type]} source    [description]
   */
  this.setLocalSource = function (key, source) {
    if (this.clientOSType == "iOS") {
      if (this.TMiOSClientIsInit) {
        TMiOSClient.SetLocalSource(key, JSON.stringify(source));
      } else {
        this.iOSClientInitScript.push("TMiOSClient.SetLocalSource('" + kry + "','" +
          JSON.stringify(source).replace(/\'/g, "\\\'") + "')");
      }
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.setLocalSource(key, JSON.stringify(source));
    }
  };

  /**
   * 获取本地缓存
   * @param  {[type]} key             [description]
   * @param  {[type]} callbackFunc    [description]
   */
  this.getLocalSource = function (key, callbackFunc) {
    if (this.clientOSType == "iOS") {
      if (this.TMiOSClientIsInit) {
        TMiOSClient.GetLocalSource(key, callbackFunc);
      } else {
        this.iOSClientInitScript.push("TMiOSClient.GetLocalSource('" + key + "','" + callbackFunc + "')");
      }
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.getLocalSource(key, callbackFunc);
    }
  };

  /**
   * 显示文件选择窗口
   * @param  {[type]}  callbackFunc [description]
   * @param  {Boolean} isMutiSelect [description]
   * @param  {Boolean} exFunc       [description]
   * @param  {Boolean} params       [description]
   * @return {[type]}               [description]
   */
  this.showFilePicker = function (callbackFunc, isMutiSelect, exFunc, params) {
    var callback = "onSelectFiles";
    if (callbackFunc) callback = callbackFunc;
    var mutiSelect = false;
    if (isMutiSelect) mutiSelect = true;
    var args = {};
    args.callback = callback;
    args.isMutiSelect = mutiSelect;
    args.exFunc = exFunc;
    args.params = params;

    if (this.clientOSType == "iOS") {
      if (this.TMiOSClientIsInit) {
        TMiOSClient.ShowFilePicker(JSON.stringify(args));
      } else {
        this.iOSClientInitScript.push("TMiOSClient.ShowFilePicker('" + JSON.stringify(args) + "')");
      }
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.showFilePicker(JSON.stringify(args));
    }
  };

  /**
   * 显示图片选择窗口
   * @param  {[type]}  callbackFunc [description]
   * @param  {Boolean} isMutiSelect [description]
   * @param  {Boolean} isCompress   [description]
   * @param  {[type]}  maxCount     [description]
   * @param  {[type]}  exFunc       [description]
   * @param  {[type]}  params       [description]
   * @return {[type]}               [description]
   */
  this.showImagePicker = function (callbackFunc, isMutiSelect, isCompress, maxCount, exFunc, params) {
    var callback = "onSelectImages";
    if (callbackFunc) callback = callbackFunc;

    var compress = true;
    if (isCompress != null) compress = isCompress;

    var mutiSelect = false;
    if (isMutiSelect) mutiSelect = true;

    var args = {};
    args.callback = callback;
    args.isMutiSelect = mutiSelect;
    args.isCompress = compress;
    args.exFunc = exFunc;
    args.params = params;

    if (maxCount) args.maxCount = maxCount;
    if (this.clientOSType == "iOS") {
      if (this.TMiOSClientIsInit) {
        TMiOSClient.ShowImagePickerOrTakePhoto(JSON.stringify(args));
      } else {
        this.iOSClientInitScript.push("TMiOSClient.ShowImagePickerOrTakePhoto('" + JSON.stringify(args) + "')");
      }
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.showImagePicker(JSON.stringify(args));
    }
  };

  /**
   * 拍照
   * @param  {[type]}  callbackFunc [description]
   * @param  {Boolean} isCompress   [description]
   * @param  {Boolean} watermark    [description]
   * @return {[type]}               [description]
   */
  this.takePhoto = function (callbackFunc, isCompress, watermark) {
    var callback = "onTakePhoto";
    if (callbackFunc) callback = callbackFunc;

    var compress = true;
    if (isCompress != null) compress = isCompress;

    var args = {};
    args.isCompress = compress;
    args.callback = callback;
    if (watermark)
      args.watermark = watermark;

    if (this.clientOSType == "iOS") {
      TMiOSClient.TakePhoto(JSON.stringify(args));
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.takePhoto(JSON.stringify(args));
    }
  };

  /**
   * 获得当前位置
   * @param  {[type]} callbackFunc [description]
   * @param  {[type]} errorFunc    [description]
   * @param  {[type]} getDetail    [description]
   * @return {[type]}              [description]
   */
  this.getLocation = function (callbackFunc, errorFunc, getDetail) {
    var callback = "onGetLocation";
    if (callbackFunc) callback = callbackFunc;

    var args = {};
    args.callback = callback;
    args.getDetail = true;
    if (!getDetail) args.getDetail = false;

    if (this.clientOSType == "iOS") {
      if (this.TMiOSClientIsInit) {
        TMiOSClient.GetLocation(JSON.stringify(args));
      } else {
        this.iOSClientInitScript.push("TMiOSClient.GetLocation('" + JSON.stringify(args) + "')");
      }
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.getLocation(JSON.stringify(args));
    }
  };

  /**
   * 显示录音窗口
   * @param  {[type]} callbackFunc [description]
   * @return {[type]}              [description]
   */
  this.showAudioRecorder = function (callbackFunc) {
    var callback = "onAudioRecord";
    if (callbackFunc) callback = callbackFunc;
    var args = {};
    args.callback = callback;

    if (this.clientOSType == "iOS") {
      TMiOSClient.ShowAudioRecorder(JSON.stringify(args));
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.showAudioRecorder(JSON.stringify(args));
    }
  };

  /**
   * 播放音频
   * @param  {[type]} filePath [description]
   * @param  {[type]} fileCode [description]
   * @return {[type]}          [description]
   */
  this.playAudio = function (filePath, fileCode) {
    if (!filePath && !fileCode) {
      alert("请提供文件路径或代码。");
      return;
    }
    var args = {};
    if (filePath) args.filePath = filePath;
    if (fileCode) args.fileCode = fileCode;

    if (this.clientOSType == "iOS") {
      TMiOSClient.PlayAudio(JSON.stringify(args));
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.playAudio(JSON.stringify(args));
    }
  };

  /**
   * 播放视频
   * @param  {[type]} args     [description]
   * @return {[type]}          [description]
   */
  this.playVideo = function (args) {
    if (!args || !args.url) {
      alert("请提供视频路径。");
      return;
    }
    if (this.clientOSType == "iOS") {
      TMiOSClient.PlayVideo(JSON.stringify(args));
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.playVideo(JSON.stringify(args));
    }
  };

  /**
   * 显示图片
   * @param  {[type]} imagePath [description]
   * @param  {[type]} imageCode [description]
   * @return {[type]}           [description]
   */
  this.showImage = function (imagePath, imageCode) {
    if (!imagePath && !imageCode) {
      alert("请提供图片路径或代码。");
      return;
    }
    var args = {};
    if (imagePath) {
      args.imagePath = imagePath;
    }
    if (imageCode) args.imageCode = imageCode;
    args.serverProtocol = location.protocol;
    args.serverAddress = location.hostname;
    args.serverPort = location.port;
    if(getUrlArg("sessionId")) args.sessionId = getUrlArg("sessionId");
    if(getUrlArg("encryptUserInfo")) args.encryptUserInfo = getUrlArg("encryptUserInfo");
    if (this.clientOSType == "iOS") {
      return TMiOSClient.ShowImage(JSON.stringify(args));
    } else if (this.clientOSType == "Android") {
      return TMAndroidClient.showImage(JSON.stringify(args));
    }
  };

  /**
   * 显示PDF
   * @param  {[type]} pdfPath [description]
   * @param  {[type]} pdfCode [description]
   * @return {[type]}           [description]
   */
  this.showPdf = function (pdfPath, pdfCode) {
    if (!pdfPath && !pdfCode) {
      alert("请提供PDF路径或代码。");
      return;
    }
    var args = {};
    if (pdfPath) {
      args.pdfPath = pdfPath;
    }
    if (pdfCode) args.pdfCode = pdfCode;
    if (this.clientOSType == "iOS") {
      return TMiOSClient.ShowPdf(JSON.stringify(args));
    } else if (this.clientOSType == "Android") {
      return TMAndroidClient.showPdf(JSON.stringify(args));
    }
  };

  /**
   * 打开文件
   * @param  {[type]} filePath [description]
   * @return {[type]}          [description]
   */
  this.openFile = function (filePath) {
    if (!filePath) {
      alert("请提供文件路径。");
      return;
    }
    var args = {};
    args.filePath = filePath;

    if (this.clientOSType == "iOS") {
      TMiOSClient.OpenFile(JSON.stringify(args));
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.openFile(JSON.stringify(args));
    }
  };

  /**
   * 打开网页
   * @param  {[type]}   url                [description]
   * @param  {Boolean}  isRemotePath       [description]
   * @param  {[type]}   openBySysBrowser   [description]
   * @param  {[type]}   title              [description]
   * @param  {[type]}   leftNavButtonTitle [description]
   * @param  {Function} callback           [description]
   * @param  {[type]}   screenMode         [description]
   * @param  {[type]}   enableZoom         [description]
   * @return {[type]}                      [description]
   */
  this.openWebPage = function (url, isRemotePath, openBySysBrowser, title, leftNavButtonTitle, callback, screenMode, enableZoom) {
    if (!url) {
      alert("请提供URL路径。");
      return;
    }

    var _openBySysBrowser = false;
    if (openBySysBrowser) _openBySysBrowser = openBySysBrowser;

    var isRemote = true;
    if (isRemotePath != null) isRemote = isRemotePath;
    var args = {};
    args.url = url;
    //     if(url.startsWith('http://') || url.startsWith('https://'))
    //       args.url = url;
    //     else{
    //       args.url = location.protocol+'//'+location.host+(url.startsWith('/')?'':'/')+url;
    //     }
    args.isRemotePath = isRemote;
    args.openBySysBrowser = openBySysBrowser;
    if (title) args.title = title;
    if (leftNavButtonTitle) args.leftNavButtonTitle = leftNavButtonTitle;
    if (callback) args.callback = callback;
    if (screenMode) args.screenMode = screenMode; //  h/v,e/d   默认横还是竖,是否自动旋转
    args.enableZoom = false;
    if (enableZoom) args.enableZoom = true;

    if (this.clientOSType == "iOS") {
      TMiOSClient.OpenWebPage(JSON.stringify(args));
    } else if (this.clientOSType == "Android") {
      if (callback) {
        args.requestCode = this.AndroidClientCallBackFuncIndex;
        this.AndroidClientCallBackFuncIndex++;
      }
      TMAndroidClient.openWebPage(JSON.stringify(args));
    } else {
      var s = this.getSimulator();
      if (s) {
        s.openApp(title, url, window, callback);
      }
    }
  };

  /**
   * 切换屏幕模式 h/v,e/d   横(h)还是竖(v),是(e)否(d)自动旋转
   * @param  {[type]} screenMode [description]
   * @return {[type]}            [description]
   */
  this.changeScreenMode = function (screenMode) {
    if (this.clientOSType == "iOS") {
      TMiOSClient.ChangeScreenMode(JSON.stringify(args));
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.changeScreenMode(screenMode);
    }
  };

  /**
   * 调用Opener的回调函数
   * @param  {[type]} arg [description]
   * @return {[type]}     [description]
   */
  this.invokeOpenerCallbackFunc = function (arg) {
    if (this.clientOSType == "iOS") {
      if (typeof (arg) == "object") {
        TMiOSClient.InvokeOpenerCallbackFunc(JSON.stringify(arg));
      } else {
        TMiOSClient.InvokeOpenerCallbackFunc(arg);
      }
      this.close();
    } else if (this.clientOSType == "Android") {
      if (typeof (arg) == "object") {
        TMAndroidClient.invokeOpenerCallbackFunc(JSON.stringify(arg));
      } else {
        TMAndroidClient.invokeOpenerCallbackFunc(arg);
      }
    } else {
      var s = this.getSimulator();
      if (s) {
        s.invokeOpenerCallbackFunc(arg);
      }
    }
  };

  /**
   * 执行Opener中的脚本
   * @param  {[type]} js [description]
   * @return {[type]}    [description]
   */
  this.evalOpenerScript = function (js) {
    if (this.clientOSType == "iOS") {
      if (this.TMiOSClientIsInit) {
        TMiOSClient.EvalOpenerScript(js);
      } else {
        this.iOSClientInitScript.push("TMiOSClient.EvalOpenerScript('" + js + "')");
      }
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.evalOpenerScript(js);
    } else {
      var s = this.getSimulator();
      if (s) {
        s.evalOpenerScript(js);
      }
    }
  };

  /**
   * 上传附件
   * @param  {[type]}  callbackFunc   [description]
   * @param  {[type]}  filePath       [description]
   * @param  {[type]}  appCode        [description]
   * @param  {[type]}  appDataId      [description]
   * @param  {Boolean} isShowProgress [description]
   * @param  {Boolean} retainExt      [description]
   * @return {[type]}                 [description]
   */
  this.uploadAttach = function (callbackFunc, filePath, appCode, appDataId, isShowProgress, retainExt) {
    var callback = "onUploadFile";
    if (callbackFunc) callback = callbackFunc;

    if (!filePath) {
      alert("请提供文件路径。");
      return;
    }

    if (!appCode) {
      alert("请提供应用代码。");
      return;
    }
    var args = {};
    args.callback = callback;
    args.filePath = filePath;
    args.appCode = appCode;
    args.isShowProgress = true;
    args.retainExt = retainExt;
    args.serverProtocol = location.protocol;
    args.serverAddress = location.hostname;
    args.serverPort = location.port;
    if(getUrlArg("sessionId")) args.sessionId = getUrlArg("sessionId");
    if(getUrlArg("encryptUserInfo")) args.encryptUserInfo = getUrlArg("encryptUserInfo");
    if (isShowProgress == false) args.isShowProgress = isShowProgress;
    if (appDataId) args.appDataId = appDataId;
    if (this.clientOSType == "iOS") {
      TMiOSClient.UploadAttach(JSON.stringify(args));
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.uploadAttach(JSON.stringify(args));
    }
  };

  /**
   * 上传附件到指定url
   * @param  {[type]}  url            [description]
   * @param  {[type]}  filePath       [description]
   * @param  {[type]}  showProgress   [description]
   * @param  {[type]}  callbackFunc   [description]
   * @return {[type]}                 [description]
   */
  this.uploadToUrl = function (url, filePath, showProgress, callbackFunc) {
    if (!url) {
      alert("请提供文件上传路径。");
      return;
    }

    if (!filePath) {
      alert("请提供文件保存路径。");
      return;
    }
    var callback = "onUploadToUrl";
    if (callbackFunc) callback = callbackFunc;
    var args = {};
    args.url = url;
    args.filePath = filePath;
    args.callback = callback;
    args.showProgress = true;
    if (showProgress !== null) args.showProgress = showProgress;
    if (this.clientOSType == "iOS") {
      if (this.TMiOSClientIsInit) {
        TMiOSClient.UploadToUrl(JSON.stringify(args));
      } else {
        this.iOSClientInitScript.push("TMiOSClient.UploadToUrl('" + JSON.stringify(args) + "')");
      }
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.uploadToUrl(JSON.stringify(args));
    }
  };

  /**
   * 上传多个附件
   * @param  {[type]}  callbackFunc   [description]
   * @param  {[type]}  files          [description]
   * @param  {Boolean} isShowProgress [description]
   * @return {[type]}                 [description]
   */
  this.uploadAttachs = function (callbackFunc, files, isShowProgress) {
    var callback = "onUploadFiles";
    if (callbackFunc) callback = callbackFunc;

    if (!files) {
      alert("请提供文件信息。");
      return;
    }

    var args = {};
    args.callback = callback;
    args.files = files;
    args.isShowProgress = true;
    args.serverProtocol = location.protocol;
    args.serverAddress = location.hostname;
    args.serverPort = location.port;
    if(getUrlArg("sessionId")) args.sessionId = getUrlArg("sessionId");
    if(getUrlArg("encryptUserInfo")) args.encryptUserInfo = getUrlArg("encryptUserInfo");
    if (isShowProgress != null) args.isShowProgress = isShowProgress;
    if (this.clientOSType == "iOS") {
      TMiOSClient.UploadAttachs(JSON.stringify(args));
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.uploadAttachs(JSON.stringify(args));
    }
  };

  /**
   * 获得附件的物理路径
   * @param  {[type]} fileCode [description]
   * @param  {[type]} fileName [description]
   * @param  {[type]} fileType [description]
   * @return {[type]}          [description]
   */
  this.getAttachPath = function (fileCode, fileName, fileType) {
    if (!fileCode) {
      alert("请提供文件代码。");
      return;
    }

    if (!fileName) {
      alert("请提供文件名称。");
      return;
    }

    if (!fileType) {
      alert("请提供文件类型，支持：image、voice、video、file。");
      return;
    }
    var args = {};
    args.fileCode = fileCode;
    args.fileName = fileName;
    args.fileType = fileType;

    if (this.clientOSType == "iOS") {
      return TMiOSClient.GetAttachPath(JSON.stringify(args));
    } else if (this.clientOSType == "Android") {
      return TMAndroidClient.getAttachPath(JSON.stringify(args));
    }
  };

  /**
   * 下载附件
   * @param  {[type]}  callbackFunc     [description]
   * @param  {[type]}  fileCode         [description]
   * @param  {[type]}  fileName         [description]
   * @param  {[type]}  appCode          [description]
   * @param  {[type]}  appDataId        [description]
   * @param  {Boolean} isShowProgress   [description]
   * @param  {[type]}  progressCallback [description]
   * @return {[type]}                   [description]
   */
  this.downAttach = function (callbackFunc, fileCode, fileName, appCode, appDataId, isShowProgress, progressCallback) {
    var callback = "onDownFile";
    if (callbackFunc) callback = callbackFunc;
    if (!fileName) {
      alert("请提供文件保存路径。");
      return;
    }
    var args = {};
    args.callback = callback;
    args.fileName = fileName;
    //if(fileId) args.fileId = fileId;
    if (fileCode) args.fileCode = fileCode;
    if (appCode) args.appCode = appCode;
    if (appDataId) args.appDataId = appDataId;
    args.isShowProgress = true;
    args.serverProtocol = location.protocol;
    args.serverAddress = location.hostname;
    args.serverPort = location.port;
    if(getUrlArg("sessionId")) args.sessionId = getUrlArg("sessionId");
    if(getUrlArg("encryptUserInfo")) args.encryptUserInfo = getUrlArg("encryptUserInfo");
    if (isShowProgress !== null) args.isShowProgress = isShowProgress;
    if (progressCallback) args.progressCallback = progressCallback;

    if (this.clientOSType == "iOS") {
      TMiOSClient.DownAttach(JSON.stringify(args));
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.downAttach(JSON.stringify(args));
    }
  };

  /**
   * 从指定url下载附件
   * @param  {[type]}  url              [description]
   * @param  {[type]}  fileCode         [description]
   * @param  {[type]}  fileName         [description]
   * @param  {[type]}  appCode          [description]
   * @param  {[type]}  appDataId        [description]
   * @param  {Boolean} showProgress     [description]
   * @param  {[type]}  callbackFunc     [description]
   */
  this.downFromUrl = function (url, fileCode, fileName, appCode, appDataId, showProgress, callbackFunc) {
    if (!url) {
      alert("请提供文件下载路径。");
      return;
    }
    if (!fileName) {
      alert("请提供文件保存路径。");
      return;
    }
    var callback = "onDownFromUrl";
    if (callbackFunc) callback = callbackFunc;
    var args = {};
    args.url = url;
    args.fileName = fileName;
    args.callback = callback;
    if (fileCode) args.fileCode = fileCode;
    if (appCode) args.appCode = appCode;
    if (appDataId) args.appDataId = appDataId;
    args.showProgress = true;
    if (!showProgress) args.showProgress = showProgress;

    if (this.clientOSType == "iOS") {
      TMiOSClient.DownFromUrl(JSON.stringify(args));
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.downFromUrl(JSON.stringify(args));
    }
  };

  /**
   * 发送文字聊天信息
   * @param  {[type]} msgGroupType [description]
   * @param  {[type]} msgGroupId   [description]
   * @param  {[type]} content      [description]
   * @param  {[type]} msgGroupName [description]
   * @return {[type]}              [description]
   */
  this.sendTextChatMsg = function (msgGroupType, msgGroupId, content, msgGroupName) {
    if (!msgGroupType) {
      alert("请提供消息分组类型。");
      return;
    }

    if (!msgGroupId) {
      alert("请提供消息分组编号。");
      return;
    }

    if (!content) {
      alert("请提供消息内容。");
      return;
    }
    var args = {};
    args.msgGroupType = "chat/" + msgGroupType;
    args.msgGroupId = msgGroupId;
    args.content = content;
    if (msgGroupName) args.title = msgGroupName;

    if (this.clientOSType == "iOS") {
      TMiOSClient.SendTextChatMsg(JSON.stringify(args));
    } else if (this.clientOSType == "Android") {
      var groupType = null;
      if (msgGroupType == "userGroup")
        groupType = "user";
      else if (msgGroupType == "depGroup" || msgGroupType == "dep")
        groupType = "dep";
      else if (msgGroupType == "roleGroup" || msgGroupType == "role")
        groupType = "role";
      else if (msgGroupType == "tempGroup")
        groupType = "temp";
      else if (msgGroupType == "appGroup")
        groupType = "app";

      if (groupType) args.msgGroupType = groupType;
      TMAndroidClient.sendTextChatMsg(JSON.stringify(args));
    }
  };

  /**
   * 在消息中心添加新消息
   * @param  {[type]} receiversId  [description]
   * @param  {[type]} appCode      [description]
   * @param  {[type]} appDataId    [description]
   * @param  {[type]} appDataType  [description]
   * @param  {[type]} title        [description]
   * @param  {[type]} detail       [description]
   * @param  {[type]} sendtime     [description]
   * @return {[type]}              [description]
   */
  this.sendAppMsg = this.addAppMsg = function (receiversId, appCode, appDataId, appDataType, title, detail, sendtime) {
    if (!receiversId) {
      alert("请提供接收人编号。");
      return;
    }

    if (!appCode) {
      alert("请提供应用代码。");
      return;
    }

    if (!title) {
      alert("请提供消息主题。");
      return;
    }

    if (!detail) {
      alert("请提供消息摘要。");
      return;
    }

    var args = {};
    args.receiversId = receiversId;
    args.appCode = appCode;
    args.title = title;
    args.detail = detail;
    args.appDataId = 0;
    if (appDataId) args.appDataId = parseInt(appDataId);
    if (appDataType) args.appDataType = appDataType;
    if (sendtime) args.sendtime = sendtime;

    try {
      if (this.clientOSType == "iOS") {
        TMiOSClient.AddAppMsg(JSON.stringify(args));
      } else if (this.clientOSType == "Android") {
        TMAndroidClient.addAppMsg(JSON.stringify(args));
      }
    } catch (e) {}
  };

  /**
   * 在地图上显示位置
   * @param  {[type]}   longitude [description]
   * @param  {[type]}   latitude  [description]
   * @param  {Function} callback  [description]
   * @param  {Function} callback  [description]
   * @return {[type]}             [description]
   */
  this.showLocation = function (longitude, latitude, callback, tolerance) {
    var args = {};
    if (longitude) args.longitude = longitude;
    if (latitude) args.latitude = latitude;
    if (callback) args.callback = callback;
    if (tolerance) args.tolerance = tolerance;
    if (this.clientOSType == "iOS") {
      TMiOSClient.ShowLocation(JSON.stringify(args));
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.showLocation(JSON.stringify(args));
    }
  };

  /**
   * 显示用户信息
   * @param  {[type]} userId [description]
   * @return {[type]}        [description]
   */
  this.showUserInfo = function (userId) {
    if (!userId) {
      alert("请提供用户编号。");
      return;
    }
    var args = {};
    args.userId = userId;

    if (this.clientOSType == "iOS") {
      TMiOSClient.ShowUserInfo(JSON.stringify(args));
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.showUserInfo(JSON.stringify(args));
    }
  };

  /**
   * 显示聊天窗口(单人)
   * @param  {[type]} msgGroupType [description]
   * @param  {[type]} msgGroupId   [description]
   * @param  {[type]} msgGroupName [description]
   * @return {[type]}              [description]
   */
  this.showChat = function (msgGroupType, msgGroupId, msgGroupName) {
    if (!msgGroupType) {
      alert("请提供消息分组类型。");
      return;
    }

    if (!msgGroupId) {
      alert("请提供消息分组编号。");
      return;
    }
    var args = {};
    args.msgGroupType = msgGroupType;
    args.msgGroupId = msgGroupId;
    if (msgGroupName) args.title = msgGroupName;
    if (this.clientOSType == "iOS") {
      args.msgGroupType = args.msgGroupType +"/user";

      if (this.TMiOSClientIsInit) {
        TMiOSClient.ShowChatView(JSON.stringify(args));
      } else {
        this.iOSClientInitScript.push("TMiOSClient.ShowChatView('" + JSON.stringify(args) + "')");
      }
    } else if (this.clientOSType == "Android") {
      var args2 = {};
      args2.msgGroupId = msgGroupId;
      if (msgGroupName) args2.title = msgGroupName;

      TMAndroidClient.showChatView(JSON.stringify(args2));
    }
  };
  
  /**
   * 显示聊天窗口(群组)
   * @param  {[type]} msgGroupType [description]
   * @param  {[type]} msgGroupId   [description]
   * @param  {[type]} msgGroupName [description]
   * @return {[type]}              [description]
   */
  this.showChatView = function (msgGroupType, msgGroupId, msgGroupName) {
    if (!msgGroupType) {
      alert("请提供消息分组类型。");
      return;
    }

    if (!msgGroupId) {
      alert("请提供消息分组编号。");
      return;
    }
    var args = {};
    args.msgGroupType = msgGroupType;
    args.msgGroupId = msgGroupId;
    if (msgGroupName) args.title = msgGroupName;
    if (this.clientOSType == "iOS") {
      args.msgGroupType = "chat/" + args.msgGroupType;
      if (this.TMiOSClientIsInit) {
        TMiOSClient.ShowChatView(JSON.stringify(args));
      } else {
        this.iOSClientInitScript.push("TMiOSClient.ShowChatView('" + JSON.stringify(args) + "')");
      }
    } else if (this.clientOSType == "Android") {
      var groupType = null;
      if (msgGroupType == "userGroup")
        groupType = "user";
      else if (msgGroupType == "depGroup")
        groupType = "dep";
      else if (msgGroupType == "roleGroup")
        groupType = "role";
      else if (msgGroupType == "tempGroup")
        groupType = "temp";
      else if (msgGroupType == "appGroup")
        groupType = "app";
      if (groupType) args.msgGroupType = groupType;
      TMAndroidClient.showChatView(JSON.stringify(args));
    }
  };

  /**
   * 关闭当前窗口
   * @return {[type]} [description]
   */
  this.close = function () {
    if (this.clientOSType == "iOS") {
      if (this.TMiOSClientIsInit) {
        TMiOSClient.Close();
      } else {
        this.iOSClientInitScript.push("TMiOSClient.Close()");
      }
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.close();
    } else {
      var s = this.getSimulator();
      if (s) s.closeCurView();
    }
  };

  /**
   * 禁用浏览器标题栏按钮
   * @return {[type]} [description]
   */
  this.disableTitleButton = function () {
    if (this.clientOSType == "iOS") {
      TMiOSClient.DisableNavBar();
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.disableTitleButton();
    }
  };

  /**
   * 启用浏览器标题栏按钮
   * @return {[type]} [description]
   */
  this.enableTitleButton = function () {
    if (this.clientOSType == "iOS") {
      TMiOSClient.EnableNavBar();
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.enableTitleButton();
    }
  };

  /**
   * 禁止浏览器后退到历史页面，点击后退时直接关闭当前窗口
   * @return {[type]} [description]
   */
  this.disableGoBack = function () {
    if (this.clientOSType == "iOS") {
      this.isDisableGoBack = true;
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.disableGoBack();
    }
  };

  /**
   * 允许浏览器后退到历史页面
   * @return {[type]} [description]
   */
  this.enableGoBack = function () {
    if (this.clientOSType == "iOS") {
      this.isDisableGoBack = false;
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.enableGoBack();
    }
  };

  /**
   * 禁止浏览器左右滑动
   * @return {[type]} [description]
   */
  this.disableSlide = function () {
    if (this.clientOSType == "iOS") {
      //
    } else if (this.clientOSType == "Android") {
      MPhone.SetFlingEnable(false);
    }
  };

  /**
   * 设置在Android手机上按后退键时执行的回调函数
   * @param {[type]} callbackFunc [description]
   */
  this.setBackKeyOnClickCallback = function (callbackFunc) {
    var callback = "backKeyOnClick";
    if (callbackFunc) callback = callbackFunc;

    if (this.clientOSType == "iOS") {
      //不支持，因为iPhone没有物理的后退键
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.setBackKeyOnClickCallback(callback);
    }
  };

  /**
   * 设置窗口标题
   * @param {[type]} title [description]
   */
  this.setTitle = function (title) {
    if (!title) {
      alert("请提供标题。");
      return;
    }

    if (this.clientOSType == "iOS") {
      var args = {};
      args.title = title;
      if (this.TMiOSClientIsInit) {
        TMiOSClient.SetTitle(JSON.stringify(args));
      } else {
        this.iOSClientInitScript.push("TMiOSClient.SetTitle('" + JSON.stringify(args) + "')");
      }
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.setTitle(title);
    } else {
      var s = this.getSimulator();
      if (s) s.setCurViewTitle(title);
    }
  };

  /**
   * 设置更多菜单
   * @param {[type]} menuInfo [description]
   */
  this.setMoreMenu = function (menuInfo) {
    if (!menuInfo) {
      alert("请提供菜单信息。");
      return;
    }

    if (this.clientOSType == "iOS") {
      if (this.TMiOSClientIsInit) {
        TMiOSClient.SetMoreMenu(JSON.stringify(menuInfo));
      } else {
        this.iOSClientInitScript.push("TMiOSClient.SetMoreMenu('" +
          JSON.stringify(menuInfo).replace(/\'/g, "\\\'") + "')");
      }
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.setMoreMenu(JSON.stringify(menuInfo));
    } else {
      var s = this.getSimulator();
      if (s) s.setCurViewMoreMenu(menuInfo);
    }
  };

  /**
   * 显示键盘
   * @return {[type]} [description]
   */
  this.showKeyboard = function () {
    if (this.clientOSType == "iOS") {
      //
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.showKeyboard();
    }
  };

  /**
   * 隐藏键盘
   * @return {[type]} [description]
   */
  this.hideKeyboard = function () {
    if (this.clientOSType == "iOS") {
      TMiOSClient.HideKeyboard();
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.hideKeyboard();
    }
  };

  /**
   * 注册摇一摇回调函数
   * @param  {[type]} callbackFunc [description]
   * @return {[type]}              [description]
   */
  this.registerShakeCallback = function (callbackFunc) {
    var args = {};
    args.callback = "onShake";
    if (callbackFunc) args.callback = callbackFunc;

    if (this.clientOSType == "iOS") {
      TMiOSClient.RegisterShakeCallback(JSON.stringify(args));
    } else if (this.clientOSType == "Android") {
      return TMAndroidClient.registerShakeCallback(JSON.stringify(args));
    }
  };

  /**
   * 获得运营商名称
   * @param  {[type]} callbackFunc [description]
   * @return {[type]}              [description]
   */
  this.getOperatorName = function (callbackFunc) {
    var callback = "onGetOperatorName";
    if (callbackFunc) callback = callbackFunc;

    if (this.clientOSType == "iOS") {
      TMiOSClient.GetOperatorName(callback);
    } else if (this.clientOSType == "Android") {
      return TMAndroidClient.getOperatorName(callback);
    }
  };

  /**
   * 获得网络类型：2G、3G、4G、Wifi
   * @param  {[type]} callbackFunc [description]
   * @return {[type]}              [description]
   */
  this.getNetState = function (callbackFunc) {
    var callback = "onGetNetState";
    if (callbackFunc) callback = callbackFunc;

    if (this.clientOSType == "iOS") {
      TMiOSClient.GetNetState(callback);
    } else if (this.clientOSType == "Android") {
      return TMAndroidClient.getNetState(callback);
    }
  };

  /**
   * 获得Wifi信息
   * @param  {[type]} inUse [description]
   * @return {[type]} callbackFunc [description]
   */
  this.getWifiInfo = function (inUse, callbackFunc) {
    var callback = "onGetWifiInfo";
    if (callbackFunc) callback = callbackFunc;
    var args = {};
    args.callback = callback;
    args.inUse = inUse;
    if (this.clientOSType == "iOS") {
      if (this.TMiOSClientIsInit) {
        TMiOSClient.GetWifiInfo(inUse, callback);
      } else {
        this.iOSClientInitScript.push("TMiOSClient.GetWifiInfo(" + inUse + ",'" + callback + "')");
      }
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.getWifiInfo(inUse, callback);
    }
  };

  /**
   * 获得设备唯一标识
   * @param  {[type]} callbackFunc [description]
   * @return {[type]}              [description]
   */
  this.getDeviceId = function (callbackFunc) {
    var callback = "onGetDeviceId";
    if (callbackFunc) callback = callbackFunc;

    if (this.clientOSType == "iOS") {
      return TMiOSClient.GetDeviceId(callback);
    } else if (this.clientOSType == "Android") {
      return TMAndroidClient.getDeviceId(callback);
    }
  };

  /**
   * 获得当前用户信息
   * @param  {[type]} callbackFunc [description]
   * @return {[type]}              [description]
   */
  this.getCurUserInfo = function (callbackFunc) {
    var callback = "onGetCurUserInfo";
    if (callbackFunc) callback = callbackFunc;

    if (this.clientOSType == "iOS") {
      TMiOSClient.GetCurUserInfo(callback);
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.getCurUserInfo(callback);
    }
  };

  /**
   * 获得当前组织信息
   * @param  {[type]} callbackFunc [description]
   * @return {[type]}              [description]
   */
  this.getOrgInfo = function (callbackFunc) {
    var callback = "onGetOrgInfo";
    if (callbackFunc) callback = callbackFunc;

    if (this.clientOSType == "iOS") {
      var args = {};
      args.callback = callback;
      if (this.TMiOSClientIsInit) {
        TMiOSClient.GetOrgInfo(args);
      } else {
        this.iOSClientInitScript.push("TMiOSClient.GetOrgInfo('" + JSON.stringify(args) + "')");
      }
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.getOrgInfo(callback);
    }
  };

  //获取本地图片base64值
  this.getLocalImageBase64Str = function (imagePath) {
    if (this.clientOSType == "iOS") {
      return TMiOSClient.GetLocalImageBase64Str(imagePath);
    } else if (this.clientOSType == "Android") {
      return TMAndroidClient.getLocalImageBase64Str(imagePath);
    }
  };

  /**
   * 获得指定用户的头像
   * @param  {[type]} userId [description]
   * @return {[type]}        [description]
   */
  this.getUserHeadBase64Str = function (userId) {
    if (this.clientOSType == "iOS") {
      return TMiOSClient.GetUserHeadBase64Str(userId);
    } else if (this.clientOSType == "Android") {
      return TMAndroidClient.getUserHeadBase64Str(userId);
    }
  };
  
  /**
   * 获得设备sn码
   */
  this.getDeviceSn = function () {
    if (this.clientOSType == "iOS") {
      return TMiOSClient.GetDeviceSn();
    } else if (this.clientOSType == "Android") {
      return TMAndroidClient.getDeviceSn();
    }
  };
  
  this.setCache = function (key,value) {
    if (this.clientOSType == "iOS") {
      return TMiOSClient.SetCache(key,value);
    } else if (this.clientOSType == "Android") {
      return TMAndroidClient.setCache(key,value);
    }
  };
  
  this.getCache = function (key) {
    if (this.clientOSType == "iOS") {
      return TMiOSClient.GetCache(key);
    } else if (this.clientOSType == "Android") {
      return TMAndroidClient.getCache(key);
    }
  };

  /**
   * 输出调试信息
   * @param  {[type]} msg [description]
   * @return {[type]}     [description]
   */
  this.debug = function (msg) {
    if (this.clientOSType == "iOS") {
      if (this.TMiOSClientIsInit) TMiOSClient.Debug(msg);
    } else if (this.clientOSType == "Android") {
      //
    } else {
      var s = this.getSimulator();
      if (s) {
        s.showDebugInfo(msg);
      } else if (parent.appendContent) {
        parent.appendContent(msg);
      }
      if (TaskMsgIsDebug) console.log(msg);
    }
  };

  /**
   * 复制到手机剪贴板
   * @param  {[type]} content [description]
   * @return {[type]}         [description]
   */
  this.copyToClipBoard = function (content) {
    if (this.clientOSType == "iOS") {
      TMiOSClient.CopyToClipBoard(content);
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.copyToClipBoard(content);
    }
  };

  /**
   * 打开任务详细界面
   * @param  {[type]} taskid  [description]
   * @param  {[type]} lookAll [description]
   * @return {[type]}         [description]
   */
  this.showTaskDetail = function (taskid, lookAll) {
    if (!taskid) {
      alert("请提供任务编号");
      return;
    }
    var canLookAll = 0;
    if (lookAll)
      canLookAll = 1;
    if (this.clientOSType == "iOS") {
      TMiOSClient.ShowTaskDetail(taskid, canLookAll);
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.showTaskDetail(taskid, canLookAll);
    }
  };

  /**
   * 显示附件列表
   * @param  {[type]} appCode   [description]
   * @param  {[type]} appDataId [description]
   */
  this.showAttachList = function (appCode, appDataId) {
    if (!appCode) {
      alert("请提供应用代码。");
      return;
    }
    var args = {};
    args.appCode = appCode;
    args.appDataId = 0;
    if (appDataId) args.appDataId = parseInt(appDataId);
    if (this.clientOSType == "iOS") {
      TMiOSClient.ShowAttachList(JSON.stringify(args));
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.showAttachList(JSON.stringify(args));
    }
  };

  /**
   * 执行iOS客户端初始化脚本
   * @return {[type]} [description]
   */
  this.exeiOSClientInitScript = function (iosVerion, sId) {
    //window.alert = function(msg) {
    //  TMiOSClient.Alert(msg);
    //};
    if(iosVerion && iosVerion>=13) {
      tmClient.iosVerion = iosVerion;
      this.sessionId = sId;
      global.TMiOSClient = new TaskMsgIOSClient();
    } else {
      if (!this.sessionId) this.sessionId = TMiOSClient.GetSessionId();
    }
    this.processWaitServices();
    for (var i = 0; i < this.iOSClientInitScript.length; i++) {
      eval(this.iOSClientInitScript[i]);
    }
    this.iOSClientInitScript = [];
    this.TMiOSClientIsInit = true;
  };

  /**
   * 刷新应用的未读消息数
   * @param  {[type]} appCode   [description]
   */
  this.refreshAppBadge = function (appCode) {
    if (!appCode) {
      alert("请提供应用代码。");
      return;
    }
    var args = {};
    args.appCode = appCode;
    if (this.clientOSType == "iOS") {
      if (this.TMiOSClientIsInit) {
        TMiOSClient.RefreshAppBadge(JSON.stringify(args));
      } else {
        this.iOSClientInitScript.push("TMiOSClient.RefreshAppBadge('" + JSON.stringify(args) + "')");
      }
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.refreshAppBadge(JSON.stringify(args));
    }
  };

  /**
   * 修改消息中心指定消息的未读状态
   * @param  {[type]} appCode     [description]
   * @param  {[type]} appDataType [description]
   * @param  {[type]} appDataId   [description]
   */
  this.setMsgHaveRead = function (appCode, appDataType, appDataId) {
    if (!appCode) {
      alert("请提供应用代码。");
      return;
    }
    var args = {};
    args.appCode = appCode;
    if (appDataType) args.appDataType = appDataType;
    if (appDataId) args.appDataId = appDataId;
    if (this.clientOSType == "iOS") {
      if (this.TMiOSClientIsInit) {
        TMiOSClient.SetMsgHaveRead(JSON.stringify(args));
      } else {
        this.iOSClientInitScript.push("TMiOSClient.SetMsgHaveRead('" + JSON.stringify(args) + "')");
      }
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.setMsgHaveRead(JSON.stringify(args));
    }
  };

  /**
   * 修改消息中心指定消息的未读状态
   * @param  {[type]} options     [description]
   */
  this.showMultiFuncsInputBar = function (options) {
    var args = {};
    if (options) args = options;
    if (!args.onSendText) args.onSendText = "onSendText";
    if (!args.onTakePhoto) args.onTakePhoto = "onTakePhoto";
    if (!args.onSelectImages) args.onSelectImages = "onSelectImages";
    if (!args.onSelectFiles) args.onSelectFiles = "onSelectFiles";
    if (!args.onGetLocation) args.onGetLocation = "onGetLocation";
    if (!args.onAudioRecord) args.onAudioRecord = "onAudioRecord";
    if (!args.onVideoRecord) args.onVideoRecord = "onVideoRecord";
    if (!args.onScanBarCode) args.onScanBarCode = "onScanBarCode";
    if (!args.canTakePhoto) args.canTakePhoto = false;
    if (!args.canSelectImages) args.canSelectImages = false;
    if (!args.canSelectFiles) args.canSelectFiles = false;
    if (!args.canGetLocation) args.canGetLocation = false;
    if (!args.canAudioRecord) args.canAudioRecord = false;
    if (!args.canVideoRecord) args.canVideoRecord = false;
    if (!args.canScanBarCode) args.canScanBarCode = false;
    if (this.clientOSType == "iOS") {
      if (this.TMiOSClientIsInit) {
        TMiOSClient.ShowMultiFuncsInputBar(args);
      } else {
        this.iOSClientInitScript.push("TMiOSClient.ShowMultiFuncsInputBar('" + JSON.stringify(args) + "')");
      }
    } else if (this.clientOSType == "Android") {
      TMAndroidClient.showMultiFuncsInputBar(args);
    }
  };

  /**
   * 显示提示消息
   * @param  {[type]} msg   [description]
   */
  this.alert = function (msg) {
    if (!msg) {
      //alert("请提供提示消息。");
      return;
    }
    if (this.clientOSType == "iOS") {
      TMiOSClient.Alert(msg);
    } else if (this.clientOSType == "Android") {
      alert(msg);
    }
  };
}

/**
 * 任信客户端浏览器扩展对象
 * @type {TaskMsgClient}
 */
var tmClient = new TaskMsgClient();
tmClient.init();
if (top.location == parent.location && top.location != location && top.tmClient) tmClient = top.tmClient;