(function webpackUniversalModuleDefinition(root, factory) {
	if(typeof exports === 'object' && typeof module === 'object')
		module.exports = factory();
	else if(typeof define === 'function' && define.amd)
		define([], factory);
	else if(typeof exports === 'object')
		exports["IMKITModule"] = factory();
	else
		root["IMKITModule"] = factory();
})(this, function() {
return /******/ (function(modules) { // webpackBootstrap
/******/ 	// install a JSONP callback for chunk loading
/******/ 	var parentJsonpFunction = window["webpackJsonpIMKITModule"];
/******/ 	window["webpackJsonpIMKITModule"] = function webpackJsonpCallback(chunkIds, moreModules) {
/******/ 		// add "moreModules" to the modules object,
/******/ 		// then flag all "chunkIds" as loaded and fire callback
/******/ 		var moduleId, chunkId, i = 0, callbacks = [];
/******/ 		for(;i < chunkIds.length; i++) {
/******/ 			chunkId = chunkIds[i];
/******/ 			if(installedChunks[chunkId])
/******/ 				callbacks.push.apply(callbacks, installedChunks[chunkId]);
/******/ 			installedChunks[chunkId] = 0;
/******/ 		}
/******/ 		for(moduleId in moreModules) {
/******/ 			modules[moduleId] = moreModules[moduleId];
/******/ 		}
/******/ 		if(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules);
/******/ 		while(callbacks.length)
/******/ 			callbacks.shift().call(null, __webpack_require__);
/******/ 		if(moreModules[0]) {
/******/ 			installedModules[0] = 0;
/******/ 			return __webpack_require__(0);
/******/ 		}
/******/ 	};

/******/ 	// The module cache
/******/ 	var installedModules = {};

/******/ 	// object to store loaded and loading chunks
/******/ 	// "0" means "already loaded"
/******/ 	// Array means "loading", array contains callbacks
/******/ 	var installedChunks = {
/******/ 		1:0
/******/ 	};

/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {

/******/ 		// Check if module is in cache
/******/ 		if(installedModules[moduleId])
/******/ 			return installedModules[moduleId].exports;

/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = installedModules[moduleId] = {
/******/ 			exports: {},
/******/ 			id: moduleId,
/******/ 			loaded: false
/******/ 		};

/******/ 		// Execute the module function
/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);

/******/ 		// Flag the module as loaded
/******/ 		module.loaded = true;

/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}

/******/ 	// This file contains only the entry chunk.
/******/ 	// The chunk loading function for additional chunks
/******/ 	__webpack_require__.e = function requireEnsure(chunkId, callback) {
/******/ 		// "0" is the signal for "already loaded"
/******/ 		if(installedChunks[chunkId] === 0)
/******/ 			return callback.call(null, __webpack_require__);

/******/ 		// an array means "currently loading".
/******/ 		if(installedChunks[chunkId] !== undefined) {
/******/ 			installedChunks[chunkId].push(callback);
/******/ 		} else {
/******/ 			// start chunk loading
/******/ 			installedChunks[chunkId] = [callback];
/******/ 			var head = document.getElementsByTagName('head')[0];
/******/ 			var script = document.createElement('script');
/******/ 			script.type = 'text/javascript';
/******/ 			script.charset = 'utf-8';
/******/ 			script.async = true;

/******/ 			script.src = __webpack_require__.p + "" + {"0":"2a7ced1343aa39215aab"}[chunkId] + ".js";
/******/ 			head.appendChild(script);
/******/ 		}
/******/ 	};

/******/ 	// expose the modules object (__webpack_modules__)
/******/ 	__webpack_require__.m = modules;

/******/ 	// expose the module cache
/******/ 	__webpack_require__.c = installedModules;

/******/ 	// __webpack_public_path__
/******/ 	__webpack_require__.p = "build";

/******/ 	// Load entry module and return exports
/******/ 	return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ({

/***/ 0:
/***/ function(module, exports, __webpack_require__) {

	__webpack_require__(14);
	__webpack_require__(26);
	module.exports = __webpack_require__(5);


/***/ },

/***/ 5:
/***/ function(module, exports, __webpack_require__) {

	(function webpackUniversalModuleDefinition(root, factory) {
		if(true)
			module.exports = factory();
		else if(typeof define === 'function' && define.amd)
			define([], factory);
		else if(typeof exports === 'object')
			exports["IMKIT"] = factory();
		else
			root["IMKIT"] = factory();
	})(this, function() {
	return /******/ (function(modules) { // webpackBootstrap
	/******/ 	// The module cache
	/******/ 	var installedModules = {};
	/******/
	/******/ 	// The require function
	/******/ 	function __webpack_require__(moduleId) {
	/******/
	/******/ 		// Check if module is in cache
	/******/ 		if(installedModules[moduleId])
	/******/ 			return installedModules[moduleId].exports;
	/******/
	/******/ 		// Create a new module (and put it into the cache)
	/******/ 		var module = installedModules[moduleId] = {
	/******/ 			exports: {},
	/******/ 			id: moduleId,
	/******/ 			loaded: false
	/******/ 		};
	/******/
	/******/ 		// Execute the module function
	/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
	/******/
	/******/ 		// Flag the module as loaded
	/******/ 		module.loaded = true;
	/******/
	/******/ 		// Return the exports of the module
	/******/ 		return module.exports;
	/******/ 	}
	/******/
	/******/
	/******/ 	// expose the modules object (__webpack_modules__)
	/******/ 	__webpack_require__.m = modules;
	/******/
	/******/ 	// expose the module cache
	/******/ 	__webpack_require__.c = installedModules;
	/******/
	/******/ 	// __webpack_public_path__
	/******/ 	__webpack_require__.p = "build";
	/******/
	/******/ 	// Load entry module and return exports
	/******/ 	return __webpack_require__(0);
	/******/ })
	/************************************************************************/
	/******/ ([
	/* 0 */
	/***/ function(module, exports, __webpack_require__) {

		module.exports = __webpack_require__(1);


	/***/ },
	/* 1 */
	/***/ function(module, exports, __webpack_require__) {

		'use strict';
		
		Object.defineProperty(exports, "__esModule", {
			value: true
		});
		
		var _util = __webpack_require__(2);
		
		var _util2 = _interopRequireDefault(_util);
		
		var _cache = __webpack_require__(3);
		
		var _cache2 = _interopRequireDefault(_cache);
		
		var _eventemitter = __webpack_require__(4);
		
		var _eventemitter2 = _interopRequireDefault(_eventemitter);
		
		var _log = __webpack_require__(5);
		
		var _log2 = _interopRequireDefault(_log);
		
		var _plugin = __webpack_require__(6);
		
		var _plugin2 = _interopRequireDefault(_plugin);
		
		var _actioncreator = __webpack_require__(7);
		
		var _actioncreator2 = _interopRequireDefault(_actioncreator);
		
		function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
		
		exports.default = {
			Base: {
				Util: _util2.default,
				Cache: _cache2.default,
				Event: _eventemitter2.default,
				Log: _log2.default,
				Plugin: _plugin2.default,
				ActionCreator: _actioncreator2.default
			}
		};
		module.exports = exports['default'];

	/***/ },
	/* 2 */
	/***/ function(module, exports) {

		'use strict';
		
		Object.defineProperty(exports, "__esModule", {
		  value: true
		});
		
		function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
		
		var __GUID = parseInt(Math.random() * 1000000000);
		exports.default = {
		  /**
		      * 生成一个随机的唯一值
		      * @return {Number}
		      */
		  guid: function guid() {
		    return __GUID++;
		  },
		
		  /**
		   * 对一些特殊字符做转码，防止xss
		   * @param   {String} e 需要转码的字符串
		   * @return  {String} e 转码后的字符串
		   */
		  htmlEncode: function htmlEncode(e) {
		    e = e.replace(/&/g, '&amp;');
		    e = e.replace(/>/g, '&gt;');
		    e = e.replace(/</g, '&lt;');
		    e = e.replace(/"/g, '&quot;');
		    e = e.replace(/'/g, '&#39;');
		
		    return e;
		  },
		
		  getParam: function getParam(s) {
		    var result = {};
		
		    if (s) {
		      var sArr = s.split('&'),
		          kvArr = void 0;
		
		      sArr.forEach(function (kv) {
		        kvArr = kv.split('=');
		        try {
		          result[kvArr[0]] = decodeURIComponent(kvArr[1]);
		        } catch (e) {
		          result[kvArr[0]] = kvArr[1];
		        }
		      });
		    }
		
		    return result;
		  },
		
		  /**
		   * 根据字符串生成一个可用的Fragment
		   * @param tpl
		   * @returns {DocumentFragment}
		   */
		  createFragment: function createFragment(tpl) {
		    var div = document.createElement('div');
		    var fragment = document.createDocumentFragment();
		
		    div.innerHTML = tpl;
		
		    while (div.childNodes[0]) {
		      fragment.appendChild(div.childNodes[0]);
		    }
		
		    div = null;
		
		    return fragment;
		  },
		
		  /**
		   * 根据传入的target, 获取class为cls的父元素
		   * @param target
		   * @param cls
		   * @returns {*}
		   */
		  parents: function parents(target, cls) {
		    if (!target || !cls) return null;
		
		    var parent = target;
		
		    while (parent) {
		
		      if (parent.classList && parent.classList.contains(cls)) break;
		
		      parent = parent.parentNode;
		
		      if (!parent || !parent.tagName || parent.tagName.toUpperCase() === 'BODY') {
		        parent = null;
		        break;
		      }
		    }
		
		    return parent;
		  },
		
		  /**
		   * 根据传入的聊天对象,生成长nick字符串
		   * @param cid
		   * @returns {*}
		   */
		  getUid: function getUid(cid) {
		    if (!cid) return '';
		    // 人
		    if (cid.appkey && cid.nick) {
		      return cid.appkey + cid.nick;
		    }
		    // 群
		    else if (cid.tribeid) {
		        return cid.tribeid;
		      }
		
		    return '';
		  },
		
		  /**
		   * 设置cid的类型
		   * @param {[type]} cid [description]
		   */
		  setCidType: function setCidType(cid) {
		    if (!cid) return null;
		
		    if (cid.type) return cid;
		
		    if (cid.appkey && cid.nick) {
		      cid.type = 1;
		    } else if (cid.tribeid && cid.tribeid !== '0') {
		      cid.type = 2;
		    } else {
		      cid = null;
		    }
		
		    return cid;
		  },
		  /**
		   * 根据聊天对象获取消息类型
		   * @param cid
		   * @returns {*}
		   */
		  getLabel: function getLabel(cid) {
		    if (!cid) return '';
		    // 如果有appkey跟nick,那么是单聊
		    if (cid.appkey && cid.nick) {
		      return 'chat';
		    }
		    // 如果有tribeid,那么是群聊
		    else if (cid.tribeid) {
		        return 'tribe';
		      }
		
		    return '';
		  },
		
		  stopScrollToBottom: function stopScrollToBottom() {
		    this.toBottomTimer && clearTimeout(this.toBottomTimer);
		  },
		
		  scrollToBottom: function scrollToBottom(container, els, to) {
		    var hasTo = typeof to !== 'undefined';
		    // 如果存在消息元素, 则需要遍历消息元素中的图片/视频, 保证图片/视频下载成功后,还会执行滚动到底部的操作
		    if (els && els.length) {
		      var t = void 0;
		
		      els.forEach(function (el) {
		
		        if (!el.querySelectorAll) return;
		        [].concat(_toConsumableArray(el.querySelectorAll('img'))).forEach(function (img) {
		          img.onload = img.onerror = function () {
		
		            this.onload = img.onerror = null;
		            clearTimeout(t);
		            // 设置图片高度, 防止切换回来的时候图片跳动
		            //this.height = this.height;
		            if (document.getElementById(img.id)) {
		              t = setTimeout(function () {
		                container.scrollTop = hasTo ? to : container.scrollHeight;
		              }, 400);
		            }
		          };
		        });
		
		        [].concat(_toConsumableArray(el.querySelectorAll('video'))).forEach(function (video) {
		          video.oncanplay = function () {
		            this.oncanplay = null;
		            clearTimeout(t);
		            // 设置视频高度,防止切换回来的时候视频位置跳动
		            this.height = this.clientHeight;
		
		            t = setTimeout(function () {
		              container.scrollTop = hasTo ? to : container.scrollHeight;
		            }, 400);
		          };
		        });
		      });
		    }
		
		    // 清除滚动到底部的定时器
		    clearTimeout(this.toBottomTimer);
		
		    // 再重新设置一个, 以防没有滚动到指定的位置
		    this.toBottomTimer = setTimeout(function () {
		      container.scrollTop = hasTo ? to : container.scrollHeight;
		    }, 200);
		    container.scrollTop = hasTo ? to : container.scrollHeight;
		  }
		};
		module.exports = exports['default'];

	/***/ },
	/* 3 */
	/***/ function(module, exports) {

		"use strict";
		
		Object.defineProperty(exports, "__esModule", {
			value: true
		});
		var __CACHE = {};
		
		exports.default = {
			set: function set(key, value) {
				var o = this.get(key);
		
				__CACHE[key] = Object.assign(o, value);
		
				return this;
			},
			setAll: function setAll(value) {
				for (var k in __CACHE) {
					__CACHE[k] = Object.assign(__CACHE[k], value);
				}
		
				return this;
			},
			get: function get(key) {
				return __CACHE[key] || {};
			},
			getAll: function getAll(key) {
				var result = [],
				    item;
		
				for (var k in __CACHE) {
					if (__CACHE[k][key]) {
						item = {};
						// item['key'] = k;
						item[key] = __CACHE[k][key];
						result.push(item);
					}
				}
		
				return result;
			},
			getExactly: function getExactly(key) {
				return __CACHE[key];
			},
			clear: function clear(key) {
				key ? delete __CACHE[key] : __CACHE = {};
				return this;
			},
			clearInKey: function clearInKey(key, inkey) {
				var v = this.get(key);
		
				delete v[inkey];
			}
		};
		module.exports = exports["default"];

	/***/ },
	/* 4 */
	/***/ function(module, exports, __webpack_require__) {

		'use strict';
		
		var has = Object.prototype.hasOwnProperty;
		
		//
		// We store our EE objects in a plain object whose properties are event names.
		// If `Object.create(null)` is not supported we prefix the event names with a
		// `~` to make sure that the built-in object properties are not overridden or
		// used as an attack vector.
		// We also assume that `Object.create(null)` is available when the event name
		// is an ES6 Symbol.
		//
		var prefix = typeof Object.create !== 'function' ? '~' : false;
		
		/**
		 * Representation of a single EventEmitter function.
		 *
		 * @param {Function} fn Event handler to be called.
		 * @param {Mixed} context Context for function execution.
		 * @param {Boolean} [once=false] Only emit once
		 * @api private
		 */
		function EE(fn, context, once) {
		  this.fn = fn;
		  this.context = context;
		  this.once = once || false;
		}
		
		/**
		 * Minimal EventEmitter interface that is molded against the Node.js
		 * EventEmitter interface.
		 *
		 * @constructor
		 * @api public
		 */
		function EventEmitter() {} /* Nothing to set */
		
		/**
		 * Hold the assigned EventEmitters by name.
		 *
		 * @type {Object}
		 * @private
		 */
		EventEmitter.prototype._events = undefined;
		
		/**
		 * Return an array listing the events for which the emitter has registered
		 * listeners.
		 *
		 * @returns {Array}
		 * @api public
		 */
		EventEmitter.prototype.eventNames = function eventNames() {
		  var events = this._events,
		      names = [],
		      name;
		
		  if (!events) return names;
		
		  for (name in events) {
		    if (has.call(events, name)) names.push(prefix ? name.slice(1) : name);
		  }
		
		  if (Object.getOwnPropertySymbols) {
		    return names.concat(Object.getOwnPropertySymbols(events));
		  }
		
		  return names;
		};
		
		/**
		 * Return a list of assigned event listeners.
		 *
		 * @param {String} event The events that should be listed.
		 * @param {Boolean} exists We only need to know if there are listeners.
		 * @returns {Array|Boolean}
		 * @api public
		 */
		EventEmitter.prototype.listeners = function listeners(event, exists) {
		  var evt = prefix ? prefix + event : event,
		      available = this._events && this._events[evt];
		
		  if (exists) return !!available;
		  if (!available) return [];
		  if (available.fn) return [available.fn];
		
		  for (var i = 0, l = available.length, ee = new Array(l); i < l; i++) {
		    ee[i] = available[i].fn;
		  }
		
		  return ee;
		};
		
		/**
		 * Emit an event to all registered event listeners.
		 *
		 * @param {String} event The name of the event.
		 * @returns {Boolean} Indication if we've emitted an event.
		 * @api public
		 */
		EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) {
		  var evt = prefix ? prefix + event : event;
		
		  if (!this._events || !this._events[evt]) return false;
		
		  var listeners = this._events[evt],
		      len = arguments.length,
		      args,
		      i;
		
		  if ('function' === typeof listeners.fn) {
		    if (listeners.once) this.removeListener(event, listeners.fn, undefined, true);
		
		    switch (len) {
		      case 1:
		        return listeners.fn.call(listeners.context), true;
		      case 2:
		        return listeners.fn.call(listeners.context, a1), true;
		      case 3:
		        return listeners.fn.call(listeners.context, a1, a2), true;
		      case 4:
		        return listeners.fn.call(listeners.context, a1, a2, a3), true;
		      case 5:
		        return listeners.fn.call(listeners.context, a1, a2, a3, a4), true;
		      case 6:
		        return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true;
		    }
		
		    for (i = 1, args = new Array(len - 1); i < len; i++) {
		      args[i - 1] = arguments[i];
		    }
		
		    listeners.fn.apply(listeners.context, args);
		  } else {
		    var length = listeners.length,
		        j;
		
		    for (i = 0; i < length; i++) {
		      if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true);
		
		      switch (len) {
		        case 1:
		          listeners[i].fn.call(listeners[i].context);break;
		        case 2:
		          listeners[i].fn.call(listeners[i].context, a1);break;
		        case 3:
		          listeners[i].fn.call(listeners[i].context, a1, a2);break;
		        default:
		          if (!args) for (j = 1, args = new Array(len - 1); j < len; j++) {
		            args[j - 1] = arguments[j];
		          }
		
		          listeners[i].fn.apply(listeners[i].context, args);
		      }
		    }
		  }
		
		  return true;
		};
		
		/**
		 * Register a new EventListener for the given event.
		 *
		 * @param {String} event Name of the event.
		 * @param {Function} fn Callback function.
		 * @param {Mixed} [context=this] The context of the function.
		 * @api public
		 */
		EventEmitter.prototype.on = function on(event, fn, context) {
		  var listener = new EE(fn, context || this),
		      evt = prefix ? prefix + event : event;
		
		  if (!this._events) this._events = prefix ? {} : Object.create(null);
		  if (!this._events[evt]) this._events[evt] = listener;else {
		    if (!this._events[evt].fn) this._events[evt].push(listener);else this._events[evt] = [this._events[evt], listener];
		  }
		
		  return this;
		};
		
		/**
		 * Add an EventListener that's only called once.
		 *
		 * @param {String} event Name of the event.
		 * @param {Function} fn Callback function.
		 * @param {Mixed} [context=this] The context of the function.
		 * @api public
		 */
		EventEmitter.prototype.once = function once(event, fn, context) {
		  var listener = new EE(fn, context || this, true),
		      evt = prefix ? prefix + event : event;
		
		  if (!this._events) this._events = prefix ? {} : Object.create(null);
		  if (!this._events[evt]) this._events[evt] = listener;else {
		    if (!this._events[evt].fn) this._events[evt].push(listener);else this._events[evt] = [this._events[evt], listener];
		  }
		
		  return this;
		};
		
		/**
		 * Remove event listeners.
		 *
		 * @param {String} event The event we want to remove.
		 * @param {Function} fn The listener that we need to find.
		 * @param {Mixed} context Only remove listeners matching this context.
		 * @param {Boolean} once Only remove once listeners.
		 * @api public
		 */
		EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) {
		  var evt = prefix ? prefix + event : event;
		
		  if (!this._events || !this._events[evt]) return this;
		
		  var listeners = this._events[evt],
		      events = [];
		
		  if (fn) {
		    if (listeners.fn) {
		      if (listeners.fn !== fn || once && !listeners.once || context && listeners.context !== context) {
		        events.push(listeners);
		      }
		    } else {
		      for (var i = 0, length = listeners.length; i < length; i++) {
		        if (listeners[i].fn !== fn || once && !listeners[i].once || context && listeners[i].context !== context) {
		          events.push(listeners[i]);
		        }
		      }
		    }
		  }
		
		  //
		  // Reset the array, or remove it completely if we have no more listeners.
		  //
		  if (events.length) {
		    this._events[evt] = events.length === 1 ? events[0] : events;
		  } else {
		    delete this._events[evt];
		  }
		
		  return this;
		};
		
		/**
		 * Remove all listeners or only the listeners for the specified event.
		 *
		 * @param {String} event The event want to remove all listeners for.
		 * @api public
		 */
		EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) {
		  if (!this._events) return this;
		
		  if (event) delete this._events[prefix ? prefix + event : event];else this._events = prefix ? {} : Object.create(null);
		
		  return this;
		};
		
		//
		// Alias methods names because people roll like that.
		//
		EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
		EventEmitter.prototype.addListener = EventEmitter.prototype.on;
		
		//
		// This function doesn't apply anymore.
		//
		EventEmitter.prototype.setMaxListeners = function setMaxListeners() {
		  return this;
		};
		
		//
		// Expose the prefix.
		//
		EventEmitter.prefixed = prefix;
		
		//
		// Expose the module.
		//
		if (true) {
		  module.exports = EventEmitter;
		}

	/***/ },
	/* 5 */
	/***/ function(module, exports) {

		'use strict';
		
		Object.defineProperty(exports, "__esModule", {
			value: true
		});
		
		var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
		
		if (!window.console) {
			window.console = {
				log: function log() {},
				warning: function warning() {},
				error: function error() {},
				info: function info() {}
			};
		}
		var Log = {
			prefix: '',
			level: -1,
			__nick: '',
		
			__glCache: {},
		
			setNick: function setNick(nick) {
				this.__nick = nick;
			},
		
			goldLog: function goldLog(logkey, param, nick) {
				var _that = this,
				    paramStr = '',
				    hold = +new Date(),
				    img = new Image(),
				    n = typeof nick === 'string' ? nick : this.__nick;
		
				this.__glCache[hold] = img;
		
				if ((typeof param === 'undefined' ? 'undefined' : _typeof(param)) === 'object') {
					for (var k in param) {
						try {
							paramStr += '&' + k + '=' + encodeURIComponent(param[k]);
						} catch (e) {}
					}
				}
		
				img.src = 'https://gm.mmstat.com/' + logkey + '?cache=' + Math.floor(Math.random() * (1111111 - 9999999) + 9999999) + '&nick=' + n + paramStr;
		
				img.onload = img.onerror = function () {
					img.onload = null;
					img.onerror = null;
					img = null;
					_that.__glCache[hold] = null;
					delete _that.__glCache[hold];
				};
			},
		
			setPrefix: function setPrefix(str) {
				this.prefix = str;
			},
		
			setLogLevel: function setLogLevel(n) {
				this.level = n;
			},
		
			addLocalLog: function addLocalLog() {
				if (!window.workbench) return;
				var logs = [];
				var args = Array.prototype.slice.call(arguments);
		
				args.forEach(function (arg) {
					if (typeof arg !== 'string') {
						try {
							logs.push(JSON.stringify(arg));
						} catch (e) {}
					} else {
						logs.push(arg);
					}
				});
		
				workbench.im.log(this.level, this.prefix + '=========>' + logs.join('\n         '));
			}
		};
		var colors = ['orange', 'blue', 'green', 'red', 'darkblue'];
		
		colors.forEach(function (color) {
			Log[color] = function () {
				var args = Array.prototype.slice.call(arguments);
		
				if (Log.level === 0) {
					Log.addLocalLog.apply(Log, args);
				}
		
				if (typeof args[0] === 'string') {
					args[0] = '%c' + args[0];
					args.splice(1, 0, 'color:' + color + ';font-size:14px;');
				}
		
				window.console.log.apply(console, args);
			};
		});
		
		exports.default = Log;
		module.exports = exports['default'];

	/***/ },
	/* 6 */
	/***/ function(module, exports) {

		'use strict';
		
		Object.defineProperty(exports, "__esModule", {
			value: true
		});
		
		var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
		
		function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
		
		var Plugin = function () {
			function Plugin() {
				_classCallCheck(this, Plugin);
		
				// 事件插件缓存
				this.__EventPluginList = {};
				// 普通插件缓存
				this.__PluginList = {};
			}
		
			_createClass(Plugin, [{
				key: 'init',
				value: function init(context) {
					this.context = context;
		
					this.use();
		
					if (!context || !context.container) return this;
		
					var handler = void 0,
					    obj = void 0;
		
					for (var e in this.__EventPluginList) {
						obj = this.__EventPluginList[e];
		
						(function (o) {
							context.container.addEventListener(e, function (ev) {
								for (var cls in o) {
									if (cls === '*') {
										console.log('is *');
										continue;
									}
		
									if (ev && ev.target && ev.target.classList && ev.target.classList.contains(cls)) {
										o[cls].forEach(function (h) {
											h.call(null, ev);
										});
		
										break;
									}
								}
		
								if (o['*'] && o['*'].length) {
									o['*'].forEach(function (h) {
										h.call(null, ev);
									});
								}
							});
						})(obj);
					}
		
					return this;
				}
			}, {
				key: '__listener',
				value: function __listener(e) {
					var list = this.__EventPluginList;
					return function (ev) {
						var obj = list[e],
						    handler = void 0;
						for (var cls in obj) {
							if (cls === '*') return;
		
							if (ev && ev.target && ev.target.classList && ev.target.classList.contains(cls)) {
								obj[cls].forEach(function (h) {
									h.call(null, ev);
								});
		
								break;
							}
						}
		
						if (obj['*'] && obj['*'].length) {
							obj['*'].forEach(function (h) {
								h.call(null, ev);
							});
						}
					};
				}
			}, {
				key: 'addEventPlugin',
				value: function addEventPlugin(event, clses, handler) {
		
					if (typeof clses !== 'string') {
						handler = clses;
						clses = '*';
					}
		
					if (!handler) return this;
		
					var list = this.__EventPluginList;
					!list[event] && (list[event] = {});
		
					clses = clses.split(/\s+/);
		
					clses.forEach(function (cls) {
						if (!cls) return;
		
						!list[event][cls] && (list[event][cls] = []);
						list[event][cls].push(handler);
					});
		
					return this;
				}
			}, {
				key: 'removeEventPlugin',
				value: function removeEventPlugin(event, clses, handler) {
					if (!arguments.length) {
						this.__EventPluginList = {};
						return this;
					}
		
					if (typeof clses !== 'string') {
						handler = clses;
						clses = '*';
					}
		
					var list = this.__EventPluginList;
					if (!list[event]) return this;
		
					clses = clses.split(/\s+/);
		
					clses.forEach(function (cls) {
						if (!cls) return;
		
						if (!handler) {
							delete list[event][cls];
						} else if (list[event][cls]) {
							list[event][cls].forEach(function (h, index) {
								if (h === handler) {
									list[event][cls].splice(index, 1);
								}
							});
						}
					});
		
					return this;
				}
			}, {
				key: 'addPlugin',
				value: function addPlugin(name, handler) {
					this.__PluginList[name] = handler;
		
					return this;
				}
			}, {
				key: 'removePlugin',
				value: function removePlugin(name) {
					var handler = void 0;
					if (name) {
						handler = this.__PluginList[name];
						handler && handler.destroy && handler.destroy(this.context);
						delete this.__PluginList[name];
					} else {
						for (name in this.__PluginList) {
							handler = this.__PluginList[name];
							handler && handler.destroy && handler.destroy(this.context);
						}
		
						this.__PluginList = {};
					}
					return this;
				}
			}, {
				key: 'use',
				value: function use(name) {
					var handler = void 0;
					if (name) {
						handler = this.__PluginList[name];
						try {
							handler && handler.init && handler.init(this.context);
						} catch (e) {
							console.error(e);
						}
					} else {
						for (name in this.__PluginList) {
							this.use(name);
						}
					}
		
					return this;
				}
			}, {
				key: 'getPlugin',
				value: function getPlugin(name) {
					return this.__PluginList[name];
				}
			}]);
		
			return Plugin;
		}();
		
		exports.default = Plugin;
		module.exports = exports['default'];

	/***/ },
	/* 7 */
	/***/ function(module, exports) {

		'use strict';
		
		Object.defineProperty(exports, "__esModule", {
			value: true
		});
		
		var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
		
		function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
		
		var Slice = Array.prototype.slice;
		
		var ActionCreator = function () {
			function ActionCreator() {
				_classCallCheck(this, ActionCreator);
		
				this.__beforeList = [];
				this.__afterList = [];
				this.actionType = 'sync';
			}
		
			_createClass(ActionCreator, [{
				key: '__clearOnce',
				value: function __clearOnce() {
					var _this = this;
		
					var bList = [];
					var aList = [];
					var i = 0;
					if (this.__beforeList.length) {
						this.__beforeList.forEach(function (obj, index) {
							if (obj.once) {
								bList.push(index);
							}
						});
					}
		
					if (this.__afterList.length) {
						this.__afterList.forEach(function (obj, index) {
							if (obj.once) {
								aList.push(index);
							}
						});
					}
		
					bList.length && bList.forEach(function (index) {
						_this.__beforeList.splice(index - i, 1);
						i--;
					});
		
					i = 0;
		
					aList.length && aList.forEach(function (index) {
						_this.__afterList.splice(index - i, 1);
						i--;
					});
				}
			}, {
				key: 'doSync',
				value: function doSync() {
					return this;
				}
			}, {
				key: 'doAsync',
				value: function doAsync() {
					return new Promise(function () {});
				}
			}, {
				key: 'action',
				value: function action() {
					var args = Slice.call(arguments);
		
					return this.actionType !== 'async' ? this.actionSync.apply(this, args) : this.actionAsync.apply(this, args);
				}
			}, {
				key: 'actionSync',
				value: function actionSync() {
					var _that = this,
					    args = Slice.call(arguments),
					    context = {};
		
					args.unshift(context);
					var stop = false;
					if (this.__beforeList.length) {
						try {
							var result = void 0;
							this.__beforeList.forEach(function (obj) {
								if (stop) return;
								try {
									result = obj.handler.apply(_that, args);
								} catch (e) {
									console.error('in actionSync:before error', e);
								}
		
								if (result === false) {
									stop = true;
								}
							});
						} catch (e) {
							_that.error(e);
						}
					}
		
					if (stop) return this;
		
					try {
						this.doSync.apply(this, args);
					} catch (e) {
						_that.error(e);
					}
		
					if (this.__afterList.length) {
						try {
							var _stop = false,
							    _result = void 0;
							this.__afterList.forEach(function (obj) {
								if (_stop) return;
								try {
									_result = obj.handler.apply(_that, args);
								} catch (e) {
									console.error('in actionSync:after error', e);
								}
								if (_result === false) {
									_stop = true;
								}
							});
						} catch (e) {
							_that.error(e);
						}
					}
		
					this.__clearOnce();
		
					return this;
				}
			}, {
				key: 'actionAsync',
				value: function actionAsync() {
					var _that = this,
					    args = Slice.call(arguments),
					    context = {},
					    promises = [];
		
					args.unshift(context);
		
					if (this.__beforeList.length) {
						var result = void 0;
						this.__beforeList.forEach(function (obj) {
							try {
								result = obj.handler.apply(_that, args);
							} catch (e) {
								console.error('in actionAsync:before error', e);
							}
		
							if (!(result instanceof Promise)) {
		
								result = new Promise(function (resolve, reject) {
									result === false ? reject() : resolve(result);
								});
							}
		
							promises.push(result);
						});
		
						Promise.all(promises).then(function () {
							_that.doAsync.apply(_that, args).then(function () {
								args = Slice.call(arguments);
								args.unshift(context);
								if (_that.__afterList.length) {
									var stop = false,
									    _result2 = void 0;
									_that.__afterList.forEach(function (obj) {
										if (stop) return;
		
										try {
											_result2 = obj.handler.apply(_that, args);
										} catch (e) {
											console.error('in actionAsync:after error', e);
										}
		
										if (_result2 === false) {
											stop = true;
										}
									});
								}
								_that.__clearOnce();
							}).catch(function (err) {
								_that.error(err);
							});
						}).catch(function (err) {
							_that.error(err);
						});
					} else {
						_that.doAsync.apply(_that, args).then(function () {
							args = Slice.call(arguments);
							args.unshift(context);
							if (_that.__afterList.length) {
								var stop = false,
								    _result3 = void 0;
								_that.__afterList.forEach(function (obj) {
									if (stop) return;
									try {
										_result3 = obj.handler.apply(_that, args);
									} catch (e) {
										console.error('in actionAsync:after error', e);
									}
		
									if (_result3 === false) {
										stop = true;
									}
								});
							}
							_that.__clearOnce();
						}).catch(function (err) {
							_that.error(err);
						});
					}
		
					return this;
				}
			}, {
				key: 'error',
				value: function error() {
					return this;
				}
			}, {
				key: 'spliceBefore',
				value: function spliceBefore(s, index, handler) {
					this.__beforeList.splice(s, index, { handler: handler });return this;
				}
			}, {
				key: 'spliceAfter',
				value: function spliceAfter(s, index, handler) {
					this.__afterList.splice(s, index, { handler: handler });return this;
				}
			}, {
				key: 'before',
				value: function before(handler) {
					this.__beforeList.push({ handler: handler });return this;
				}
			}, {
				key: 'after',
				value: function after(handler) {
					this.__afterList.push({ handler: handler });return this;
				}
			}, {
				key: 'spliceBeforeOnce',
				value: function spliceBeforeOnce(s, index, handler) {
					this.__beforeList.splice(s, index, { handler: handler, once: 1 });return this;
				}
			}, {
				key: 'spliceAfterOnce',
				value: function spliceAfterOnce(s, index, handler) {
					this.__afterList.splice(s, index, { handler: handler, once: 1 });return this;
				}
			}, {
				key: 'beforeOnce',
				value: function beforeOnce(handler) {
					this.__beforeList.push({ handler: handler, once: 1 });return this;
				}
			}, {
				key: 'afterOnce',
				value: function afterOnce(handler) {
					this.__afterList.push({ handler: handler, once: 1 });return this;
				}
			}]);
		
			return ActionCreator;
		}();
		
		exports.default = ActionCreator;
		module.exports = exports['default'];

	/***/ }
	/******/ ])
	});
	;
	//# sourceMappingURL=data:application/json;base64, 

/***/ },

/***/ 14:
/***/ function(module, exports) {

	/* WEBPACK VAR INJECTION */(function(global) {/*
	    ********** Juicer **********
	    ${A Fast template engine}
	    Project Home: http://juicer.name

	    Author: Guokai
	    Gtalk: badkaikai@gmail.com
	    Blog: http://benben.cc
	    Licence: MIT License
	    Version: 0.6.15
	*/

	(function() {

	    // This is the main function for not only compiling but also rendering.
	    // there's at least two parameters need to be provided, one is the tpl, 
	    // another is the data, the tpl can either be a string, or an id like #id.
	    // if only tpl was given, it'll return the compiled reusable function.
	    // if tpl and data were given at the same time, it'll return the rendered 
	    // result immediately.

	    var juicer = function() {
	        var args = [].slice.call(arguments);

	        args.push(juicer.options);

	        if(args[0].match(/^\s*#([\w:\-\.]+)\s*$/igm)) {
	            args[0].replace(/^\s*#([\w:\-\.]+)\s*$/igm, function($, $id) {
	                var _document = document;
	                var elem = _document && _document.getElementById($id);
	                args[0] = elem ? (elem.value || elem.innerHTML) : $;
	            });
	        }

	        if(juicer.documentHTML) {
	            juicer.compile.call(juicer, juicer.documentHTML);
	            juicer.documentHTML = '';
	        }

	        if(arguments.length == 1) {
	            return juicer.compile.apply(juicer, args);
	        }

	        if(arguments.length >= 2) {
	            return juicer.to_html.apply(juicer, args);
	        }
	    };

	    var __escapehtml = {
	        escapehash: {
	            '<': '&lt;',
	            '>': '&gt;',
	            '&': '&amp;',
	            '"': '&quot;',
	            "'": '&#x27;',
	            '/': '&#x2f;'
	        },
	        escapereplace: function(k) {
	            return __escapehtml.escapehash[k];
	        },
	        escaping: function(str) {
	            return typeof(str) !== 'string' ? str : str.replace(/[&<>"']/igm, this.escapereplace);
	        },
	        detection: function(data) {
	            return typeof(data) === 'undefined' ? '' : data;
	        }
	    };

	    var __throw = function(error) {
	        if(typeof(console) !== 'undefined') {
	            if(console.warn) {
	                console.warn(error);
	                return;
	            }

	            if(console.log) {
	                console.log(error);
	                return;
	            }
	        }

	        throw(error);
	    };

	    var __creator = function(o, proto) {
	        o = o !== Object(o) ? {} : o;

	        if(o.__proto__) {
	            o.__proto__ = proto;
	            return o;
	        }

	        var empty = function() {};
	        var n = Object.create ? 
	            Object.create(proto) : 
	            new(empty.prototype = proto, empty);

	        for(var i in o) {
	            if(o.hasOwnProperty(i)) {
	                n[i] = o[i];
	            }
	        }

	        return n;
	    };

	    var annotate = function(fn) {
	        var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
	        var FN_ARG_SPLIT = /,/;
	        var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
	        var FN_BODY = /^function[^{]+{([\s\S]*)}/m;
	        var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
	        var args = [],
	            fnText,
	            fnBody,
	            argDecl;

	        if (typeof fn === 'function') {
	            if (fn.length) {
	                fnText = fn.toString();
	            }
	        } else if(typeof fn === 'string') {
	            fnText = fn;
	        }

	        fnText = fnText.trim();
	        argDecl = fnText.match(FN_ARGS);
	        fnBody = fnText.match(FN_BODY)[1].trim();

	        for(var i = 0; i < argDecl[1].split(FN_ARG_SPLIT).length; i++) {
	            var arg = argDecl[1].split(FN_ARG_SPLIT)[i];
	            arg.replace(FN_ARG, function(all, underscore, name) {
	                args.push(name);
	            });
	        }

	        return [args, fnBody];
	    };

	    juicer.__cache = {};
	    juicer.version = '0.6.15';
	    juicer.settings = {};
	    juicer.documentHTML = '';

	    juicer.tags = {
	        operationOpen: '{@',
	        operationClose: '}',
	        interpolateOpen: '\\${',
	        interpolateClose: '}',
	        noneencodeOpen: '\\$\\${',
	        noneencodeClose: '}',
	        commentOpen: '\\{#',
	        commentClose: '\\}'
	    };

	    juicer.options = {
	        cache: true,
	        strip: true,
	        errorhandling: true,
	        detection: true,
	        _method: __creator({
	            __escapehtml: __escapehtml,
	            __throw: __throw,
	            __juicer: juicer
	        }, {})
	    };

	    juicer.tagInit = function() {
	        var forstart = juicer.tags.operationOpen + 'each\\s*([^}]*?)\\s*as\\s*(\\w*?)\\s*(,\\s*\\w*?)?' + juicer.tags.operationClose;
	        var forend = juicer.tags.operationOpen + '\\/each' + juicer.tags.operationClose;
	        var ifstart = juicer.tags.operationOpen + 'if\\s*([^}]*?)' + juicer.tags.operationClose;
	        var ifend = juicer.tags.operationOpen + '\\/if' + juicer.tags.operationClose;
	        var elsestart = juicer.tags.operationOpen + 'else' + juicer.tags.operationClose;
	        var elseifstart = juicer.tags.operationOpen + 'else if\\s*([^}]*?)' + juicer.tags.operationClose;
	        var interpolate = juicer.tags.interpolateOpen + '([\\s\\S]+?)' + juicer.tags.interpolateClose;
	        var noneencode = juicer.tags.noneencodeOpen + '([\\s\\S]+?)' + juicer.tags.noneencodeClose;
	        var inlinecomment = juicer.tags.commentOpen + '[^}]*?' + juicer.tags.commentClose;
	        var rangestart = juicer.tags.operationOpen + 'each\\s*(\\w*?)\\s*in\\s*range\\(([^}]+?)\\s*,\\s*([^}]+?)\\)' + juicer.tags.operationClose;
	        var include = juicer.tags.operationOpen + 'include\\s*([^}]*?)\\s*,\\s*([^}]*?)' + juicer.tags.operationClose;
	        var helperRegisterStart = juicer.tags.operationOpen + 'helper\\s*([^}]*?)\\s*' + juicer.tags.operationClose;
	        var helperRegisterBody = '([\\s\\S]*?)';
	        var helperRegisterEnd = juicer.tags.operationOpen + '\\/helper' + juicer.tags.operationClose;

	        juicer.settings.forstart = new RegExp(forstart, 'igm');
	        juicer.settings.forend = new RegExp(forend, 'igm');
	        juicer.settings.ifstart = new RegExp(ifstart, 'igm');
	        juicer.settings.ifend = new RegExp(ifend, 'igm');
	        juicer.settings.elsestart = new RegExp(elsestart, 'igm');
	        juicer.settings.elseifstart = new RegExp(elseifstart, 'igm');
	        juicer.settings.interpolate = new RegExp(interpolate, 'igm');
	        juicer.settings.noneencode = new RegExp(noneencode, 'igm');
	        juicer.settings.inlinecomment = new RegExp(inlinecomment, 'igm');
	        juicer.settings.rangestart = new RegExp(rangestart, 'igm');
	        juicer.settings.include = new RegExp(include, 'igm');
	        juicer.settings.helperRegister = new RegExp(helperRegisterStart + helperRegisterBody + helperRegisterEnd, 'igm');
	    };

	    juicer.tagInit();

	    // Using this method to set the options by given conf-name and conf-value,
	    // you can also provide more than one key-value pair wrapped by an object.
	    // this interface also used to custom the template tag delimater, for this
	    // situation, the conf-name must begin with tag::, for example: juicer.set
	    // ('tag::operationOpen', '{@').

	    juicer.set = function(conf, value) {
	        var that = this;

	        var escapePattern = function(v) {
	            return v.replace(/[\$\(\)\[\]\+\^\{\}\?\*\|\.]/igm, function($) {
	                return '\\' + $;
	            });
	        };

	        var set = function(conf, value) {
	            var tag = conf.match(/^tag::(.*)$/i);

	            if(tag) {
	                that.tags[tag[1]] = escapePattern(value);
	                that.tagInit();
	                return;
	            }

	            that.options[conf] = value;
	        };

	        if(arguments.length === 2) {
	            set(conf, value);
	            return;
	        }

	        if(conf === Object(conf)) {
	            for(var i in conf) {
	                if(conf.hasOwnProperty(i)) {
	                    set(i, conf[i]);
	                }
	            }
	        }
	    };

	    // Before you're using custom functions in your template like ${name | fnName},
	    // you need to register this fn by juicer.register('fnName', fn).

	    juicer.register = function(fname, fn) {
	        var _method = this.options._method;

	        if(_method.hasOwnProperty(fname)) {
	            return false;
	        }

	        return _method[fname] = fn;
	    };

	    // remove the registered function in the memory by the provided function name.
	    // for example: juicer.unregister('fnName').

	    juicer.unregister = function(fname) {
	        var _method = this.options._method;

	        if(_method.hasOwnProperty(fname)) {
	            return delete _method[fname];
	        }
	    };

	    juicer.template = function(options) {
	        var that = this;

	        this.options = options;

	        this.__interpolate = function(_name, _escape, options) {
	            var _define = _name.split('|'), _fn = _define[0] || '', _cluster;

	            if(_define.length > 1) {
	                _name = _define.shift();
	                _cluster = _define.shift().split(',');
	                _fn = '_method.' + _cluster.shift() + '.call(this, ' + [_name].concat(_cluster) + ')';
	            }

	            return '<%= ' + (_escape ? '_method.__escapehtml.escaping' : '') + '(' +
	                        (!options || options.detection !== false ? '_method.__escapehtml.detection' : '') + '(' +
	                            _fn +
	                        ')' +
	                    ')' +
	                ' %>';
	        };

	        this.__removeShell = function(tpl, options) {
	            var _counter = 0;

	            tpl = tpl
	                // inline helper register
	                .replace(juicer.settings.helperRegister, function($, helperName, fnText) {
	                    var anno = annotate(fnText);
	                    var fnArgs = anno[0];
	                    var fnBody = anno[1];
	                    var fn = new Function(fnArgs.join(','), fnBody);

	                    juicer.register(helperName, fn);
	                    return $;
	                })

	                // for expression
	                .replace(juicer.settings.forstart, function($, _name, alias, key) {
	                    var alias = alias || 'value', key = key && key.substr(1);
	                    var _iterate = 'i' + _counter++;
	                    return '<% ~function() {' +
	                                'for(var ' + _iterate + ' in ' + _name + ') {' +
	                                    'if(' + _name + '.hasOwnProperty(' + _iterate + ')) {' +
	                                        'var ' + alias + '=' + _name + '[' + _iterate + '];' +
	                                        (key ? ('var ' + key + '=' + _iterate + ';') : '') +
	                            ' %>';
	                })
	                .replace(juicer.settings.forend, '<% }}}(); %>')

	                // if expression
	                .replace(juicer.settings.ifstart, function($, condition) {
	                    return '<% if(' + condition + ') { %>';
	                })
	                .replace(juicer.settings.ifend, '<% } %>')

	                // else expression
	                .replace(juicer.settings.elsestart, function($) {
	                    return '<% } else { %>';
	                })

	                // else if expression
	                .replace(juicer.settings.elseifstart, function($, condition) {
	                    return '<% } else if(' + condition + ') { %>';
	                })

	                // interpolate without escape
	                .replace(juicer.settings.noneencode, function($, _name) {
	                    return that.__interpolate(_name, false, options);
	                })

	                // interpolate with escape
	                .replace(juicer.settings.interpolate, function($, _name) {
	                    return that.__interpolate(_name, true, options);
	                })

	                // clean up comments
	                .replace(juicer.settings.inlinecomment, '')

	                // range expression
	                .replace(juicer.settings.rangestart, function($, _name, start, end) {
	                    var _iterate = 'j' + _counter++;
	                    return '<% ~function() {' +
	                                'for(var ' + _iterate + '=' + start + ';' + _iterate + '<' + end + ';' + _iterate + '++) {{' +
	                                    'var ' + _name + '=' + _iterate + ';' +
	                            ' %>';
	                })

	                // include sub-template
	                .replace(juicer.settings.include, function($, tpl, data) {
	                    // compatible for node.js
	                    if(tpl.match(/^file\:\/\//igm)) return $;
	                    return '<%= _method.__juicer(' + tpl + ', ' + data + '); %>';
	                });

	            // exception handling
	            if(!options || options.errorhandling !== false) {
	                tpl = '<% try { %>' + tpl;
	                tpl += '<% } catch(e) {_method.__throw("Juicer Render Exception: "+e.message);} %>';
	            }

	            return tpl;
	        };

	        this.__toNative = function(tpl, options) {
	            return this.__convert(tpl, !options || options.strip);
	        };

	        this.__lexicalAnalyze = function(tpl) {
	            var buffer = [];
	            var method = [];
	            var prefix = '';
	            var reserved = [
	                'if', 'each', '_', '_method', 'console', 
	                'break', 'case', 'catch', 'continue', 'debugger', 'default', 'delete', 'do', 
	                'finally', 'for', 'function', 'in', 'instanceof', 'new', 'return', 'switch', 
	                'this', 'throw', 'try', 'typeof', 'var', 'void', 'while', 'with', 'null', 'typeof', 
	                'class', 'enum', 'export', 'extends', 'import', 'super', 'implements', 'interface', 
	                'let', 'package', 'private', 'protected', 'public', 'static', 'yield', 'const', 'arguments', 
	                'true', 'false', 'undefined', 'NaN'
	            ];

	            var indexOf = function(array, item) {
	                if (Array.prototype.indexOf && array.indexOf === Array.prototype.indexOf) {
	                    return array.indexOf(item);
	                }

	                for(var i=0; i < array.length; i++) {
	                    if(array[i] === item) return i;
	                }

	                return -1;
	            };

	            var variableAnalyze = function($, statement) {
	                statement = statement.match(/\w+/igm)[0];

	                if(indexOf(buffer, statement) === -1 && indexOf(reserved, statement) === -1 && indexOf(method, statement) === -1) {

	                    // avoid re-declare native function, if not do this, template 
	                    // `{@if encodeURIComponent(name)}` could be throw undefined.

	                    if(typeof(window) !== 'undefined' && typeof(window[statement]) === 'function' && window[statement].toString().match(/^\s*?function \w+\(\) \{\s*?\[native code\]\s*?\}\s*?$/i)) {
	                        return $;
	                    }

	                    // compatible for node.js
	                    if(typeof(global) !== 'undefined' && typeof(global[statement]) === 'function' && global[statement].toString().match(/^\s*?function \w+\(\) \{\s*?\[native code\]\s*?\}\s*?$/i)) {
	                        return $;
	                    }

	                    // avoid re-declare registered function, if not do this, template 
	                    // `{@if registered_func(name)}` could be throw undefined.

	                    if(typeof(juicer.options._method[statement]) === 'function' || juicer.options._method.hasOwnProperty(statement)) {
	                        method.push(statement);
	                        return $;
	                    }

	                    // avoid SyntaxError: Unexpected number

	                    if(statement.match(/^\d+/igm)) {
	                        return $;
	                    }

	                    buffer.push(statement); // fuck ie
	                }

	                return $;
	            };

	            tpl.replace(juicer.settings.forstart, variableAnalyze).
	                replace(juicer.settings.interpolate, variableAnalyze).
	                replace(juicer.settings.ifstart, variableAnalyze).
	                replace(juicer.settings.elseifstart, variableAnalyze).
	                replace(juicer.settings.include, variableAnalyze).
	                replace(/[\+\-\*\/%!\?\|\^&~<>=,\(\)\[\]]\s*([A-Za-z_0-9]+)/igm, variableAnalyze);

	            for(var i = 0; i < buffer.length; i++) {
	                prefix += 'var ' + buffer[i] + '=_.' + buffer[i] + ';';
	            }

	            for(var i = 0; i < method.length; i++) {
	                prefix += 'var ' + method[i] + '=_method.' + method[i] + ';';
	            }

	            return '<% ' + prefix + ' %>';
	        };

	        this.__convert=function(tpl, strip) {
	            var buffer = [].join('');

	            buffer += "'use strict';"; // use strict mode
	            buffer += "var _=_||{};";
	            buffer += "var _out='';_out+='";

	            if(strip !== false) {
	                buffer += tpl
	                    .replace(/\\/g, "\\\\")
	                    .replace(/[\r\t\n]/g, " ")
	                    .replace(/'(?=[^%]*%>)/g, "\t")
	                    .split("'").join("\\'")
	                    .split("\t").join("'")
	                    .replace(/<%=(.+?)%>/g, "';_out+=$1;_out+='")
	                    .split("<%").join("';")
	                    .split("%>").join("_out+='")+
	                    "';return _out;";

	                return buffer;
	            }

	            buffer += tpl
	                    .replace(/\\/g, "\\\\")
	                    .replace(/[\r]/g, "\\r")
	                    .replace(/[\t]/g, "\\t")
	                    .replace(/[\n]/g, "\\n")
	                    .replace(/'(?=[^%]*%>)/g, "\t")
	                    .split("'").join("\\'")
	                    .split("\t").join("'")
	                    .replace(/<%=(.+?)%>/g, "';_out+=$1;_out+='")
	                    .split("<%").join("';")
	                    .split("%>").join("_out+='")+
	                    "';return _out.replace(/[\\r\\n]\\s+[\\r\\n]/g, '\\r\\n');";

	            return buffer;
	        };

	        this.parse = function(tpl, options) {
	            var _that = this;

	            if(!options || options.loose !== false) {
	                tpl = this.__lexicalAnalyze(tpl) + tpl;
	            }

	            tpl = this.__removeShell(tpl, options);
	            tpl = this.__toNative(tpl, options);

	            this._render = new Function('_, _method', tpl);

	            this.render = function(_, _method) {
	                if(!_method || _method !== that.options._method) {
	                    _method = __creator(_method, that.options._method);
	                }

	                return _that._render.call(this, _, _method);
	            };

	            return this;
	        };
	    };

	    juicer.compile = function(tpl, options) {
	        if(!options || options !== this.options) {
	            options = __creator(options, this.options);
	        }

	        var that = this;
	        var cacheStore = {
	            get: function(tpl) {
	                if(options.cachestore) {
	                    return options.cachestore.get(tpl);
	                }

	                return that.__cache[tpl];
	            },

	            set: function(tpl, val) {
	                if(options.cachestore) {
	                    return options.cachestore.set(tpl, val);
	                }

	                return that.__cache[tpl] = val;
	            }
	        };

	        try {
	            var engine = cacheStore.get(tpl) ? 
	                cacheStore.get(tpl) : 
	                new this.template(this.options).parse(tpl, options);

	            if(!options || options.cache !== false) {
	                cacheStore.set(tpl, engine);
	            }

	            return engine;

	        } catch(e) {
	            __throw('Juicer Compile Exception: ' + e.message);

	            return {
	                render: function() {} // noop
	            };
	        }
	    };

	    juicer.to_html = function(tpl, data, options) {
	        if(!options || options !== this.options) {
	            options = __creator(options, this.options);
	        }

	        return this.compile(tpl, options).render(data, options._method);
	    };

	    // avoid memory leak for node.js
	    if(typeof(global) !== 'undefined' && typeof(window) === 'undefined') {
	        juicer.set('cache', false);
	    }

	    if(typeof(document) !== 'undefined' && document.body) {
	        juicer.documentHTML = document.body.innerHTML;
	    }

	    typeof(module) !== 'undefined' && module.exports ? module.exports = juicer : this.juicer = juicer;

	})();

	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))

/***/ },

/***/ 26:
/***/ function(module, exports, __webpack_require__) {

	var __WEBPACK_AMD_DEFINE_RESULT__;/**
	 * ----------------------------------
	 * @file: @ali/im.sdk
	 * @desc: 旺旺SDK
	 * @license MIT License
	 * ----------------------------------
	 */

	!(function(global, factory) {
	    'use strict';
	    if (true) {
	        !(__WEBPACK_AMD_DEFINE_RESULT__ = function() {
	            return factory(global)
	        }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
	    } else if (typeof exports === 'object') {
	        module.exports = factory(global);
	    } else {
	        global.imsdk = factory(global);
	    }
	})(window, function(global) {
	    'use strict';

	    // 调试模式
	    var IS_DEBUG = (global.location && location.href && /debug=true/i.test(location.href)) || (global.localStorage && !!localStorage.getItem('WW_DEBUG'));

	    // 普通日志
	    var _log = function() {
	        if ((IS_DEBUG || global.DEBUG) && global.console) {
	            console.log.apply(console, Array.prototype.slice.apply(arguments));
	        }
	    };

	    // 错误日志
	    var _errorLog = function () {
	        global.console && console.log.apply(console, Array.prototype.slice.apply(arguments));
	    }

	    // 是否是在imsdk容器中，非imsdk容器中的部分方法或参数有区别
	    var _isInIMSDKClient = /WW_IMSDK/i.test(navigator.userAgent);

	    /*--------------------------  TASK  ----------------------------*/

	    var TASK_CACHE = {};

	    function Task(namespace, config) {
	        this.id = workbench.createSequenceId();
	        this.namespace = namespace;
	        this.config = config || {};
	        this.cmd = this.config.cmd;
	        this.param = this.config.param || '';

	        if (this.param && this.param.__other) {
	            this.other = this.param.__other;
	            delete this.param.__other;
	        }

	        TASK_CACHE[this.id] = this;
	    }

	    Task.prototype = {
	        constructor: Task,

	        bindCallback: function(name, callback) {
	            var that = this;

	            this[name] = function(result) {
	                clearTimeout(that.timmer);
	                callback.call(that, result, that.cmd, that.param);

	                // 在当前任务上加一个已销毁的标记，8秒之后再销毁
	                that.destroyed = true;
	                setTimeout(function () {delete TASK_CACHE[that.id]}, 8000)
	            };

	            return this;
	        },

	        success: function(callback) {
	            if (!callback || (!typeof callback === 'function')) return this;

	            this.bindCallback('onSuccess', callback);

	            return this;
	        },

	        failure: function(callback) {
	            if (!callback || (!typeof callback === 'function')) return this;

	            this.bindCallback('onFailure', callback);

	            return this;
	        },

	        timeout: function(time) {
	            var that = this;
	            time = parseInt(time);

	            time && (this.timmer = setTimeout(function() {
	                that.onFailure && that.onFailure({ret: 'TIMEOUT'});
	            }, time));

	            return this;
	        },

	        run: function() {
	            var param = this.param;
	            if (typeof param !== 'string') {
	                try {
	                    param = JSON.stringify(param);
	                } catch (err) {
	                    param = '';
	                }
	            }

	            try {
	                if (!this.other) {
	                    this.namespace.invoke(this.id, this.cmd, param);
	                } else {
	                    this.namespace.invoke(this.id, this.cmd, param, this.other);
	                }
	            } catch (err) {
	                _errorLog('%cError in Task.run: ' + this.cmd, 'color:red', err);
	            }

	            return this;
	        },

	        request: function (requestMethod) {
	            requestMethod = requestMethod || 'CommitHttpRequest';
	            var options = {
	                url: this.config.url,
	                method: this.config.method || 'get',
	                param: this.param
	            };

	            options = JSON.stringify(options);
	            try {
	                workbench.httprequest.invoke(this.id, requestMethod, options);
	            } catch (err) {
	                _errorLog('%cError in Task.request: ' + this.config.url, 'color:red', err);
	            }
	            return this;
	        }
	    };

	    /*--------------------------  SDK  ----------------------------*/

	    var SDK = {};

	    /**
	     * 调用客户端方法
	     * @param   {String}      fn              方法名
	     * @param   {Object}      config          配置项
	     * @param   {Object}      config.param    客户端方法的入参
	     * @param   {Function}    config.success  成功的回调
	     * @param   {Function}    config.failure  失败的回调
	     * @param   {Number}      config.timeout  超时时间
	     * @return  {Object}      SDK
	     * @example
	     * SDK.invoke('util.GetUserNick', {
	     *     param: {uid: 'uid'},
	     *     success: function() {},
	     *     failure: function() {},
	     *     timeout: 5000,
	     * });
	     */
	    SDK.invoke = function(fn, config) {
	        if (typeof fn !== 'string') {
	            return _errorLog('%cError in SDK.invoke: fn must be string', 'color:red', fn);
	        }

	        fn = fn.split('.');

	        var cmd = fn.pop(),
	            namespace = workbench;

	        try {
	            fn.forEach(function(n) {
	                namespace = namespace[n];
	            });
	        } catch (err) {
	            return _errorLog('%cError in SDK.invoke', 'color:red', err);
	        }

	        config = config || {};
	        config.cmd = cmd;

	        new Task(namespace, config)
	            .success(config.success)
	            .failure(config.failure)
	            .timeout(config.timeout)
	            .run();

	        return this;
	    };

	    /**
	     * 客户端代理的http请求
	     * @param   {object} config
	     * @param   {string} config.url
	     * @param   {string} [config.method = 'get']
	     * @param   {object} [config.param] 入参
	     * @param   {string} [requestMethod = 'CommitHttpRequest']
	     * @return  {object} SDK
	     * @example
	     * SDK.ajax({
	     *      url: 'http://www.taobao.com/xxxx',
	     *      param: {id: 100},
	     *      success: function (result) {
	     *          // do something...
	     *      }
	     * }, 'QintaoRequest')
	     */
	    SDK.ajax = function (config, requestMethod) {
	        new Task(null, config)
	            .success(config.success)
	            .failure(config.failure)
	            .timeout(config.timeout)
	            .request(requestMethod);

	        return this
	    };

	    // ------------ 事件 -------------------
	    var EVENT_CACHE = {};
	    var REGISTER_CACHE = {};
	    var SCOPE_REGISTER_CACHE = {};

	    SDK.registerInScope = function(name) {
	        if (!name) return this;
	        if (typeof name === 'string') name = [name];

	        name = name.filter(function (n) {return !SCOPE_REGISTER_CACHE[n]});

	        if (!name.length) return this;
	        try {
	            name.forEach(function (n) {
	                workbench.regScopeEvent(workbench.createSequenceId(), n, '');
	                SCOPE_REGISTER_CACHE[n] = true;
	            });
	        } catch (err) {
	            _errorLog('%cError in SDK.register', 'color:red;', name);
	        }

	        return this;
	    }

	    SDK.unregisterInScope = function(name) {
	        if (!name) name = REGISTER_CACHE.slice();
	        if (typeof name === 'string') name = [name];

	        if (!name.length) return this;
	        try {
	            name.forEach(function (n) {
	                workbench.unregPageEvent(workbench.createSequenceId(), n, '');
	                delete REGISTER_CACHE[n]
	            });
	        } catch (err) {
	            _errorLog('%cError in SDK.' +
	                '', 'color:red', err);
	        }
	        return this;
	    }
	    /**
	     * 注册事件
	     * @param {String|Array}    name   事件名称，多个事件以数组格式
	     * @return {Object}         this
	     * @example
	     * SDK.register('MSG_RECEIVED')
	     */
	    SDK.register = function (name) {
	        if (!name) return this;
	        if (typeof name === 'string') name = [name];

	        name = name.filter(function (n) {return !REGISTER_CACHE[n]});

	        if (!name.length) return this;
	        try {
	            workbench.im.event_register('', JSON.stringify(name), '');
	            name.forEach(function (n) {REGISTER_CACHE[n] = true});
	        } catch (err) {
	            _errorLog('%cError in SDK.register', 'color:red;', name);
	        }

	        return this;
	    }

	    /**
	     * 反注册事件
	     * @param {String|Array}    [name]  事件名称，多个事件以数组形式
	     * @param {Object}          this
	     * @example
	     * SDK.unregister();
	     * SDK.unregister('MSG_RECEIVED');
	     */
	    SDK.unregister = function (name) {
	        if (!name) name = REGISTER_CACHE.slice();
	        if (typeof name === 'string') name = [name];

	        if (!name.length) return this;
	        try {
	            workbench.im.event_unregister('', JSON.stringify(name), '');
	            name.forEach(function (n) {delete REGISTER_CACHE[n]});
	        } catch (err) {
	            _errorLog('%cError in SDK.' +
	                '', 'color:red', err);
	        }

	        return this;
	    }

	    /**
	     * 监听事件
	     * @param   {String}      name            事件名称，多个事件名称以,或者空格隔开，命名空间以::分隔
	     * @param   {Function}    callback        事件触发回调
	     * @return  {Object}      this
	     * @example
	     * function callbackHandler(data) {
	     *     console.log(data);
	     * }
	     * SDK.on('MSG_RECEIVED', callbackHandler);
	     */
	    SDK.on = function(name, callback, scope) {
	        if (!name || !callback) return this;

	        var events = name.split(/,?\s+/);
	        var that = this;

	        events.forEach(function(event) {
	            if (!event) return;
	            // 分离出命名空间
	            var originEvent = event.split('::').pop();
	            if (!originEvent) return;

	            if (!EVENT_CACHE[event]) {
	                EVENT_CACHE[event] = {};
	                EVENT_CACHE[event].callbacks = [];
	                EVENT_CACHE[event].handle = function(e) {
	                    EVENT_CACHE[event].callbacks.forEach(function(cb) {
	                        try {
	                            cb.call(this, e.detail);
	                        } catch(ex) {
	                            console.error('Error in handle ' + event, ex);
	                        }
	                    });
	                };
	                document.addEventListener(originEvent, EVENT_CACHE[event].handle, false);
	                !scope ? that.register(originEvent) : that.registerInScope(originEvent);
	            }

	            EVENT_CACHE[event].callbacks.push(callback);

	        });

	        return this;
	    };

	    SDK.scopeOn = function() {
	        var args = Array.prototype.slice.call(arguments);
	        args.push(true);
	        return SDK.on.apply(SDK, args);
	    };

	    SDK.scopeOff = function() {
	        var args = Array.prototype.slice.call(arguments);

	        if(args.length === 0) {
	            args = [undefined, undefined, undefined, true];
	        }else if (args.length === 1) {
	            args = args.concat([undefined, undefined, true]);
	        }else if(args.length === 2) {
	            args = args.concat([undefined, true]);
	        }else {
	            args.push(true);
	        }

	        return SDK.off.apply(SDK, args);
	    };

	    /**
	     * 取消监听事件
	     * @param   {String}      [name]            [可选]事件名称，多个事件名称以,或者空格隔开
	     * @param   {Function}    [callback]        [可选]事件触发回调
	     * @param   {Boolean}     [canUnregister=true]      [可选]是否可以自行反注册事件，默认为true
	     * @return  {Object}      SDK
	     * @example
	     * SDK.off();
	     * SDK.off('MSG_RECEIVED');
	     * SDK.off('MSG_RECEIVED', callbackHandler);
	     * SDK.off('MSG_RECEIVED', false);
	     */
	    SDK.off = function(name, callback, canUnregister, scope) {
	        var events, originEvent;
	        var that = this;

	        if (canUnregister === undefined && typeof callback === 'boolean') {
	            canUnregister = callback;
	            callback = undefined;
	        } else if (callback === undefined && typeof name === 'boolean') {
	            canUnregister = name;
	            name = undefined;
	        }
	        // 默认为true
	        canUnregister = canUnregister !== false;

	        if (name) {
	            events = name.split(/,?\s+/);

	            events.forEach(function(event) {
	                if (!event) return;

	                originEvent = event.split('::').pop();
	                if (!originEvent) return;

	                if (!EVENT_CACHE[event]) return;

	                var shouldClear = true;
	                if (typeof callback === 'function') {
	                    EVENT_CACHE[event].callbacks.some(function(cb, i) {
	                        if (cb === callback) return EVENT_CACHE[event].callbacks.splice(i, 1), true;
	                    });
	                    shouldClear = !EVENT_CACHE[event].callbacks.length;
	                }

	                if (shouldClear) {
	                    document.removeEventListener(originEvent, EVENT_CACHE[event].handle);
	                    delete EVENT_CACHE[event];
	                    // NOTE 有BUG，如果清空的是命名空间的事件，会移除掉另一个事件，所以加了一个canUnregister的选项
	                    canUnregister && (scope ? that.unregister(originEvent) : that.unregisterInScope(originEvent));
	                }
	            });
	        } else {
	            events = [];
	            for (var event in EVENT_CACHE) {
	                originEvent = event.split('::').pop();
	                events.push(originEvent);
	                document.removeEventListener(originEvent, EVENT_CACHE[event].handle);
	                delete EVENT_CACHE[event];
	            }
	            (scope ? that.unregister(events) : that.unregisterInScope(events));
	        }

	        return this;
	    };

	    /**
	     * 触发某个监听事件
	     * @param   {String}      name            事件名称
	     * @param   {Object}      data            带给事件绑定回调的数据
	     * @return  {Object}      this
	     * @example
	     * SDK.fire('MSG_RECEIVED', {msgs: []});
	     */
	    SDK.fire = (function() {
	        var that = this;

	        // W3C标准
	        if (global.CustomEvent) {
	            return function(name, data, fromEvent) {
	                if (!name) return;
	                var event = new CustomEvent(name, {detail: data});
	                document.dispatchEvent(event);
	                !fromEvent && _log('%cSDK.fire: ' + name, 'color:pink', data);
	                return that
	            }
	        } else {
	            return function(name, data, fromEvent) {
	                if (!name) return;
	                var e = document.createEvent('HTMLEvents');
	                e.initEvent(name, false, true);
	                e.detail = data;
	                document.dispatchEvent(e);
	                !fromEvent && _log('%cSDK.fire: ' + name, 'color:pink', data);
	                return that
	            }
	        }
	    })();

	    SDK.emit = SDK.fire;

	    /**
	     * 广播
	     * @param {string} event
	     * @param {*} data
	     */
	    SDK.broadcast = function(event, data) {
	        var param = '';
	        try {
	            data && (param = JSON.stringify(data));
	        } catch(e) {}

	        workbench.im.event_notify('', event, param);
	    };

	    SDK.Binder = Binder;

	    /*--------------------------  Binder  ----------------------------*/
	    /**
	     * 用于更方便的解绑通过Binder绑定的事件
	     */
	    function Binder() {
	        this.bindList = [];
	    }

	    Binder.prototype = {
	        constructor: Binder,

	        on: function(name, callback) {
	            Array.prototype.push.apply(this.bindList, name.split(/,?\s+/));
	            SDK.on(name, callback);

	            return this;
	        },

	        clear: function(name, callback) {
	            SDK.off(this.bindList.join(' '));
	            this.bindList = [];

	            return this;
	        }
	    }

	    /*--------------------------  暴露给客户端的全局函数  ----------------------------*/
	    /*----------------------  客户端通过调用这些函数与前端通信  ------------------------*/
	    /**
	     * SDK.invoke方法的通信函数
	     * @param   {String}      sid           随机数，用来找到调用时生成的task
	     * @param   {Object}      status        接口调用状态，此状态仅表示接口是否通，与具体的接口返回无关
	     * @return  {Object}      response      接口返回的数据
	     */
	    global.onInvokeNotify = function(sid, status, response) {
	        if (!sid) return _log('%cEMPTY sid in onInvokeNotify, status: ' + status, 'color:#aaaaaa', response);
	        var task = TASK_CACHE[sid];
	        if (!task) return _errorLog('%cWARNGIN: 未找到sid: [' + sid + '] 对应的task!', 'color:#ff9900;font-weight:bold');
	        if (task.destroyed) return _errorLog('%cWARNGIN: sid: [' + sid + '] 对应的task已销毁！', 'color:#ff4400;font-weight:bold', task.config.fn);

	        try {
	            response = (!response || /^\d+$/.test(response)) ? response : JSON.parse(response)
	        } catch (e) {}

	        if (status === 0) {
	            task.onSuccess && task.onSuccess(response);
	        } else {
	            task.onFailure && task.onFailure(response);
	        }
	    };

	    /**
	     * SDK.on方法的通信函数
	     * @param   {String}      name          事件名称
	     * @return  {Object}      response      事件返回的数据
	     */
	    global.onEventNotify = function(name, response) {

	        var args = Array.prototype.slice.call(arguments);

	        if(args.length > 2) {
	            name = args[1];
	            response = args[3];
	        }

	        try {
	            response = (!response || /^\d+$/.test(response)) ? response : JSON.parse(response)
	        } catch (e) {}

	        _log('%conEventNotify ' + name, 'color:blue;font-weight:bold', response);

	        SDK.fire && SDK.fire(name, response, true);
	    };

	    /*--------------------------  一些调用方式的提升  ----------------------------*/

	    // ============== 将方法用Promise重新封装 ================
	    SDK._overrideWithPromise = function () {
	        if (SDK.__hasOverride) return this;

	        var _invoke = SDK.invoke;

	        /**
	         * 调用客户端方法
	         * @param   {String}      fn              方法名
	         * @param   {Object}      param           客户端方法的入参
	         * @param   {Number}      timeout  超时时间
	         * @return  {Object}      promise
	         * @example
	         * SDK.invoke('util.GetUserNick', {uid: 'uid'}, 5000).then(function(data) {
	         *     console.log(data)
	         * }).catch(function(error) {
	         *     console.log(error);
	         * })
	         */
	        SDK.invoke = function(fn, param, timeout) {
	            var _b = Date.now();

	            return new Promise(function(resolve, reject) {
	                _invoke(fn, {
	                    fn: fn,
	                    param: param,
	                    timeout: timeout,
	                    success: function(response) {
	                        var _t = Date.now() - _b;
	                        global.__WPO && __WPO.retCode(fn, true, _t, 'SUCCESS');
	                        resolve(response);
	                    },
	                    failure: function(error) {
	                        var _t = Date.now() - _b;

	                        if (typeof error !== 'string') {
	                            try {
	                                error = JSON.stringify(error);
	                            } catch (e) {
	                                error += '';
	                            }
	                        }
	                        global.__WPO && __WPO.retCode(fn, true, _t, error.substring(0, 50));
	                        reject(error);
	                    }
	                })
	            });
	        };

	        var _ajax = SDK.ajax;

	        SDK.ajaxSetup = {
	            // ajax方法返回后，业务层校验规则，仅用于数据打点
	            validRule: function (result) {
	                return true
	            }
	        };

	        /**
	         * 带promise的ajax调用方式
	         * @param  {object} config config
	         * @property {string} config.url
	         * @property {string} [config.method='get']
	         * @property {object} [config.param] 入参
	         * @property {number} [config.timeout] timeout
	         * @property {function} [config.validRule] 校验规则，仅用于数据打点
	         * @param  {string} [requestMethod='CommitHttpRequest']
	         * @return {Promise}
	         * @example
	         * SDK.ajax({
	         *     url: 'http://abc.com',
	         *     param: {id: 1001}
	         * }).then(function (result) {
	         *     // do something...
	         * })
	         */
	        SDK.ajax = function (config, requestMethod) {
	            var _begin = Date.now();
	            config.validRule = config.validRule || SDK.ajaxSetup.validRule;

	            return new Promise(function (resolve, reject) {
	                config.success = function (response) {
	                    var _time = Date.now() - _begin;
	                    var _flag = 'SUCCESS';
	                    try {
	                        if (!config.validRule(response)) _flag = 'WARNING'
	                    } catch (e) {
	                        _flag = 'WARNING'
	                    }
	                    global.__WPO && __WPO.retCode(config.api || config.apiKey || config.url, true, _time, _flag);
	                    resolve(response);
	                }
	                config.failure = function (error) {
	                    var _time = Date.now() - _begin;
	                    if (typeof error !== 'string') {
	                        try {
	                            error = JSON.stringify(error);
	                        } catch (e) {
	                            error += '';
	                        }
	                    }
	                    global.__WPO && __WPO.retCode(config.api || config.apiKey || config.url, false, _time, error.substring(0, 50));
	                    reject(error);
	                }
	                _ajax(config, requestMethod)
	            })
	        }

	        SDK.__hasOverride = true;
	    }

	    var _invoke = SDK.invoke;

	    if (global.Promise) SDK._overrideWithPromise();

	    /**
	     * 初始化主题
	     */
	    SDK.initTheme = function() {
	        var less = global.less;
	        if (!less) {
	            return;
	        }
	        var titleBarHeight = 31;

	        function genPalette(color, count) {
	            var i, cl = [], step, pos;
	            count = count || 25;
	            var hsl = color.toHSL();

	            step = (100 / count);
	            pos = count - Math.ceil(hsl.l * 100 / step);

	            for (i = 0; i < count; i++) {
	                if (i == pos) {
	                    cl.push(color);
	                } else {
	                    cl.push(less.tree.functions.hsla(hsl.h, hsl.s, (100 - i * step) / 100, hsl.a));
	                }
	            }

	            return {list: cl, pos: pos};
	        }

	        function changeTheme(theme) {
	            var color = new less.tree.Color(theme.rgb);
	            // https://img.alicdn.com/tps/i1/TB10CHwHXXXXXciXXXXb4A9VXXX-1200-900.jpg
	            // 前端noschema改造地址过滤
	            theme.backgroundImageUrl = theme.backgroundImageUrl.replace(/http:\/\/gtms0\d+/g, '\/\/img');
	            var i, len,
	                vars = {
	                    '@color-base': color.toRGB(),
	                    '@theme-background-image': 'url(' + theme.backgroundImageUrl + ')',
	                    '@theme-bg-img': 'url(' + theme.backgroundImageUrl + ')',
	                    '@theme-bg-url': '"' + theme.backgroundImageUrl + '"',
	                    '@theme-bg-x': theme.backgroundPositionX || 'left',
	                    '@title-bar-height': titleBarHeight + 'px'
	                };

	            var list = genPalette(color).list;
	            len = list.length;
	            for (i = 1; i <= len; i++) {
	                vars['@palette-color-' + i] = list[i - 1].toRGB();
	            }

	            if (less && less.modifyVars) {
	                less.globalResetDefaultVars = vars;
	                less.modifyVars(vars);
	            }
	        }

	        _invoke('im.uiutil.GetSkinTheme', {
	            param: {},
	            success: function(rsp) {
	                rsp = rsp.result;
	                titleBarHeight = Number(rsp.titleBarHeight || 31) || 31;
	                changeTheme(rsp);
	            }
	        });

	        SDK.on('im.uiutil.onSkinThemeChange', function(rsp) {
	            //rsp = JSON.parse(rsp);
	            changeTheme(rsp);
	        });
	    };

	    return SDK;
	});


/***/ }

/******/ })
});
;