diff --git a/.jshintrc b/.jshintrc
new file mode 100644
index 0000000..bbf058a
--- /dev/null
+++ b/.jshintrc
@@ -0,0 +1,21 @@
+{
+ "es3": true,
+ "strict": true,
+ "globalstrict": true,
+ "browser":true,
+ "curly": true,
+ "forin": true,
+ "eqeqeq": true,
+ "eqnull": true,
+ "undef": true,
+ "unused": true,
+ "noarg": true,
+ "globals": {
+ "__comment": "true means read-write, false means read-only",
+ "window": true,
+ "console": false,
+ "JSON": false,
+ "module": true,
+ "require": false
+ }
+}
\ No newline at end of file
diff --git a/dist/uiKit.css b/dist/uiKit.css
new file mode 100644
index 0000000..70d42b1
--- /dev/null
+++ b/dist/uiKit.css
@@ -0,0 +1,134 @@
+.m-panel .emoji {
+ width: 20px;
+ height: 20px;
+ vertical-align: middle;
+ float: none;
+}
+.m-panel .empty{
+ padding: 10px 5px;
+}
+.m-panel .list {
+ height: 100%;
+ width: 100%;
+ position: relative;
+ overflow-y: auto;
+ background-color: #fff;
+ border-radius: 0 0 5px 5px;
+}
+.m-panel .list>p, .m-panel .list>ul>p {
+ padding: 10px;
+}
+.m-panel li,.m-panel .item{
+ clear:both;
+ border-bottom:1px solid #eaeeef;
+ overflow:hidden;
+ height:61px;
+ padding:8px 10px;
+ box-sizing:border-box;
+ -webkit-box-sizing:border-box;
+ -moz-box-sizing:border-box;
+ cursor:default;
+ cursor: pointer;
+}
+.m-panel li:hover, .teams li:hover,.m-panel .item::hover{
+ background-color: #f5f5f5;
+}
+.m-panel li.active,.m-panel .item.active{
+ background-color: #f5f5f5;
+}
+.m-panel li.active .count{
+ display: none;
+}
+.m-panel li img,.m-panel .item img{
+ float: left;
+ width: 44px;
+ height: 44px;
+ border-radius: 50%;
+ -webkit-border-radius: 50%;
+ -moz-border-radius: 50%;
+ -ms-border-radius: 50%;
+}
+.m-panel .text {
+ margin-left: 60px;
+ padding:3px 0;
+ position: relative;
+ height: 45px;
+ overflow: hidden
+}
+.m-panel .tag{
+ float: left;
+ line-height: 40px;
+ margin-left:16px;
+}
+.m-panel .text span, .m-panel .first-msg {
+ width: 60%;
+ display: inline-block;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ -webkit-text-overflow: ellipsis;
+ -moz-text-overflow: ellipsis;
+ -ms-text-overflow: ellipsis;
+ white-space: nowrap;
+}
+.m-panel .text .time{
+ position: absolute;
+ right:0;
+ top:5px;
+ font-size: 12px;
+ color: #999;
+}
+.m-panel .text .nick {
+ line-height: 61px;
+ height:61px;
+ font-size: 13px;
+ color:#999;
+ margin: -11px 0;
+}
+.m-panel .text .nick, .m-panel .text .message {
+ position: relative;
+ color:#666;
+}
+.m-panel .text .nick span, .m-panel .text .message span {
+ display: inline-block;
+ width: 80%;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ -webkit-text-overflow: ellipsis;
+ -moz-text-overflow: ellipsis;
+ -ms-text-overflow: ellipsis;
+ overflow: hidden;
+}
+.m-panel .text .nick time {
+ position: absolute;
+ right: 0;
+ top: 0;
+ color:#aaa;
+}
+.m-panel .text .first-msg {
+ display: inline-block;
+ width: 80%;
+ color:#6b8299;
+ font-size: 12px;
+ height: 20px;
+ line-height: 20px;
+}
+.m-panel .text p{
+ height: 20px;
+}
+
+.m-panel .text .message span {
+ width: 80%;
+}
+.m-panel .text .count {
+ position: absolute;
+ background-color: #f24c3d;
+ display: inline-block;
+ font-size: 12px;
+ color: #fff;
+ border-radius: 10px;
+ right: 0;
+ top: 24px;
+ text-align: center;
+ padding: 0 5px;
+ width: 20px;
+}
\ No newline at end of file
diff --git a/dist/uiKit.js b/dist/uiKit.js
new file mode 100644
index 0000000..e243029
--- /dev/null
+++ b/dist/uiKit.js
@@ -0,0 +1,826 @@
+(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["NIMUIKit"] = factory();
+ else
+ root["NIMUIKit"] = 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 = "";
+
+/******/ // Load entry module and return exports
+/******/ return __webpack_require__(0);
+/******/ })
+/************************************************************************/
+/******/ ([
+/* 0 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /**
+ * ------------------------------------------------------------
+ * NIM_UI 云信web UI库
+ * ------------------------------------------------------------
+ */
+
+ 'use strict';
+
+ var uiKit = {};
+
+ /**
+ * list
+ */
+
+ uiKit.SessionList = __webpack_require__(1);
+ uiKit.FriendList = __webpack_require__(4);
+ uiKit.TeamList = __webpack_require__(5);
+
+
+ module.exports = uiKit;
+
+/***/ },
+/* 1 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /**
+ * ------------------------------------------------------------
+ * SesstionList 会话面板UI
+ * ------------------------------------------------------------
+ */
+
+ 'use strict';
+ var util = __webpack_require__(2);
+ var ACCOUNT;
+
+ /**
+ * 判断会话的对象
+ * @param {Object} msg 消息
+ * @return {String} 会话的对象
+ */
+ function switchConversationUser(msg){
+ return msg.to === ACCOUNT ? msg.from : msg.to;
+ }
+ /**
+ * 会话列表控件
+ * @param {Object} options 控件初始化参数
+ * @property {String||Node} parent 父节点
+ * @property {String} clazz 样式名称
+ * @property {Function} onclickitem 点击列表回调
+ * @property {Function} onclickavatar 点击列表头像回调
+ * @property {Object} data 消息数据 data.msgs 消息数据 data.unreadmsgs 未读数据 data.unreadmsgs['iostest']={count:99} data.userinfo 用户信息 data.teamInfo 群信息
+ */
+ var SessionList = function(options){
+ var parent = options.parent,
+ data = options.data,
+ cbClickList = options.onclickitem||function(account,type){console.log('account:'+account+'---type:'+type);},
+ cbClickPortrait = options.onclickavatar||function(account,type){console.log('account:'+account+'---type:'+type);};
+ ACCOUNT = data.account;
+ this._body = document.createElement('ul');
+ this._body.className = options.clazz||"m-panel" +" j-session";
+
+ util.addEvent(this._body,'click',function(e){
+ var self = this,
+ evt = e||window.event,
+ account,
+ type,
+ target = evt.srcElement||evt.target;
+ while(self!==target){
+ if (target.tagName.toLowerCase() === "img") {
+ var item = target.parentNode;
+ account = item.getAttribute("data-account");
+ type = item.getAttribute("data-type");
+ cbClickPortrait(account,type);
+ return;
+ }else if(target.tagName.toLowerCase() === "li"){
+ account = target.getAttribute("data-account");
+ type = target.getAttribute("data-type");
+ util.removeClass(util.getNode(".j-session li.active"),'active');
+ util.addClass(target,"active");
+ var countNode = target.querySelector('.count');
+ util.addClass(countNode,"hide");
+ countNode.innerHTML = 0;
+ cbClickList(account,type);
+ return;
+ }
+ target = target.parentNode;
+ }
+ });
+ this.update(data);
+ if(!!parent){
+ this.inject(parent);
+ }
+ };
+ /** --------------------------public------------------------------ */
+
+ /**
+ * 插入控件
+ * @param {Node|String} node 插入控件的节点
+ * @return {Void}
+ */
+ SessionList.prototype.inject = function(node){
+ var injectNode = util.getNode(node);
+ injectNode.innerHTML = "";
+ injectNode.appendChild(this._body);
+ };
+
+ /**
+ * 更新视图
+ * @param {Object} data
+ * @return {Void}
+ */
+ SessionList.prototype.update = function(data){
+ var html = '',
+ msgs = data.msgs,
+ unreadMsg = data.unreadmsgs,
+ info = data.userinfo,
+ team = data.teamInfo,
+ msg,nick,type,avatar,time,who,
+ count,isShow;
+ if (msgs.length === 0) {
+ html += '
暂无最近联系人哦
';
+ }else{
+ for (var i = 0;i 99 ? '99+' : unreadMsg[who].count;
+ }
+ isShow = count === '99+' || count > 0;
+ if (msg.scene === 'team') {
+ nick = team[who].name||who;
+ type = team[who].type||'normal';
+ avatar = "images/"+type+".png";
+ } else {
+ nick = info[who].nick;
+ avatar = util.getAvatar(info[who].avatar);
+ }
+ var str = ['',
+ '',
+ '',
+ '
',
+ '' + nick + '',
+ '' + util.transTime2(msg.time) + '',
+ '
',
+ '
',
+ '' + buildSessionMsg(msg,info,ACCOUNT) + '',
+ '' + count + '',
+ '
',
+ '
',
+ ''].join("");
+ html += str;
+ }
+ }
+ this._body.innerHTML = html;
+ };
+
+ /**
+ * 控件销毁
+ * @return {void}
+ */
+ SessionList.prototype.destory = function(){
+ //预留
+ };
+
+ /**
+ * 构造第一条消息,显示在最近联系人昵称的下面
+ * @param msg:消息对象
+ */
+ var buildSessionMsg = function(msg,info,account) {
+ var text = (msg.scene!=='p2p'?msg.fromNick+":":""), type = msg.type;
+ if (!/text|image|file|audio|video|geo|custom|notification/i.test(type)){
+ return '';
+ }
+ switch (type) {
+ case 'text':
+ text += util.safeHtml(msg.text);
+ text = util.buildEmoji(text);
+ break;
+ case 'image':
+ text += '[图片]';
+ break;
+ case 'file':
+ if (!/exe|bat/i.test(msg.file.ext)) {
+ text += '[文件]';
+ } else {
+ text += '[非法文件,已被本站拦截]';
+ }
+ break;
+ case 'audio':
+ text += '[语音]';
+ break;
+ case 'video':
+ text += '[视频]';
+ break;
+ case 'geo':
+ text += '[位置]';
+ break;
+ case 'custom':
+ var content = JSON.parse(msg.content);
+ if(content.type===1){
+ text += '[猜拳]';
+ }else if(content.type===2){
+ text +='[阅后即焚]';
+ }else if(content.type===3){
+ text +='[贴图]';
+ }else if(content.type===4){
+ text +='[白板]';
+ }else{
+ text += '[自定义消息]';
+ }
+ break;
+ case 'notification':
+ text = '['+util.transNotification(msg,info,account)+']';
+ break;
+ default:
+ text += '[未知消息类型]';
+ break;
+ }
+ return text;
+ };
+
+
+
+
+ module.exports = SessionList;
+
+/***/ },
+/* 2 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /**
+ * ------------------------------------------------------------
+ * util 工具库
+ * ------------------------------------------------------------
+ */
+
+ 'use strict';
+ var CONST = __webpack_require__(3),
+ emoji = CONST.emoji;
+
+ var util = {
+ getNode: function(ipt){
+ if(this.isString(ipt)){
+ return document.querySelector(ipt);
+ }else if(this.isElement(ipt)){
+ return ipt;
+ }else{
+ console.error("输入参数必须为node||String");
+ }
+ },
+ getNodes: function(string){
+ return document.querySelectorAll(string);
+ },
+ isString: function(data){
+ return typeof(data)==='string';
+ },
+ isElement:function(obj){
+ return !!(obj && obj.nodeType === 1);
+ },
+ isArray:Array.isArray|| function(obj) {
+ return Object.prototype.toString.call(obj) === '[object Array]';
+ },
+
+ addEvent: function(node,type,callback){
+ if(window.addEventListener){
+ node.addEventListener(type,callback,false);
+ }else{
+ node.attachEvent("on"+type,callback);
+ }
+ },
+
+ hasClass: function(elem, cls){
+ cls = cls || '';
+ if(cls.replace(/\s/g, '').length === 0){
+ return false;
+ }
+ return new RegExp(' ' + cls + ' ').test(' ' + elem.className + ' ');
+ },
+
+ addClass: function(elem, cls){
+ if(!elem){
+ return;
+ }
+ if(!this.hasClass(elem, cls)){
+ elem.className += ' ' + cls;
+ }
+ },
+ removeClass: function(elem, cls){
+ if(!elem){
+ return;
+ }
+ if(this.hasClass(elem, cls)){
+ var newClass = ' ' + elem.className.replace(/[\t\r\n]/g, '') + ' ';
+ while(newClass.indexOf(' ' + cls + ' ') >= 0){
+ newClass = newClass.replace(' ' + cls + ' ', ' ');
+ }
+ elem.className = newClass.replace(/^\s+|\s+$/g, '');
+ }
+ },
+ safeHtml: (function(){
+ var reg = /
$/,
+ map = {
+ r:/<|>|\&|\r|\n|\s|\'|\"/g,
+ '<':'<','>':'>','&':'&',' ':' ',
+ '"':'"',"'":''','\n':'
','\r':''
+ };
+ return function(content){
+ content = _$encode(map,content);
+ return content.replace(reg,'
');
+ };
+ })(),
+ getAvatar:function(url){
+ var re=/^((http|https|ftp):\/\/)?(\w(\:\w)?@)?([0-9a-z_-]+\.)*?([a-z0-9-]+\.[a-z]{2,6}(\.[a-z]{2})?(\:[0-9]{2,6})?)((\/[^?#<>\/\\*":]*)+(\?[^#]*)?(#.*)?)?$/i;
+ if(re.test(url)){
+ return url;
+ }else{
+ return "images/default-icon.png";
+ }
+ },
+ /**
+ * 通过正则替换掉文本消息中的emoji表情
+ * @param text:文本消息内容
+ */
+ buildEmoji:function(text) {
+ var re = /\[([^\]\[]*)\]/g;
+ var matches = text.match(re) || [];
+ for (var j = 0, len = matches.length; j < len; ++j) {
+ if(emoji[matches[j]]){
+ text = text.replace(matches[j], '');
+ }
+ }
+ return text;
+ },
+ /**
+ * 群通知处理
+ * @param {Object} item
+ * @return {String}
+ */
+ transNotification:function(item,info,myAccount) {
+ var type = item.attach.type,
+ from = (item.from === myAccount?true:false),
+ str,
+ accounts,
+ member=[],
+ i;
+ switch (type) {
+ case 'addTeamMembers':
+ accounts = item.attach.accounts;
+ for(i = 0;i=check[0]){
+ return dateFormat(time,"HH:mm");
+ }else if(time=check[1]){
+ return dateFormat(time,"MM-dd HH:mm");
+ }else{
+ return dateFormat(time,"yyyy-MM-dd HH:mm");
+ }
+ };
+ })(),
+ /**
+ * 时间戳转化为日期(用于左边面板)
+ * @return {string} 转化后的日期
+ */
+ transTime2 :(function(){
+ var getDayPoint = function(time){
+ time.setMinutes(0);
+ time.setSeconds(0);
+ time.setMilliseconds(0);
+ time.setHours(0);
+ var today = time.getTime();
+ time.setMonth(1);
+ time.setDate(1);
+ var yearDay = time.getTime();
+ return [today,yearDay];
+ };
+ return function(time){
+ var check = getDayPoint(new Date());
+ if (time>=check[0]){
+ return dateFormat(time,"HH:mm");
+ }else if(time>=check[0]-60*1000*60*24){
+ return "昨天";
+ }else if(time>=(check[0]-2*60*1000*60*24)){
+ return "前天";
+ }else if(time>=(check[0]-7*60*1000*60*24)){
+ return "星期"+dateFormat(time,"w");
+ }else if(time>=check[1]){
+ return dateFormat(time,"MM-dd");
+ }else{
+ return dateFormat(time,"yyyy-MM-dd");
+ }
+ };
+ })()
+ };
+ var _$encode = function(_map,_content){
+ _content = ''+_content;
+ if (!_map||!_content){
+ return _content||'';
+ }
+ return _content.replace(_map.r,function($1){
+ var _result = _map[!_map.i?$1.toLowerCase():$1];
+ return _result!=null?_result:$1;
+ });
+ };
+ /**
+ * 日期格式化
+ * @return string
+ */
+ var dateFormat = (function(){
+ var _map = {i:!0,r:/\byyyy|yy|MM|cM|eM|M|dd|d|HH|H|mm|ms|ss|m|s|w|ct|et\b/g},
+ _12cc = ['上午','下午'],
+ _12ec = ['A.M.','P.M.'],
+ _week = ['日','一','二','三','四','五','六'],
+ _cmon = ['一','二','三','四','五','六','七','八','九','十','十一','十二'],
+ _emon = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sept','Oct','Nov','Dec'];
+ var _fmtnmb = function(_number){
+ _number = parseInt(_number,10)||0;
+ return (_number<10?'0':'')+_number;
+ };
+ var _fmtclc = function(_hour){
+ return _hour<12?0:1;
+ };
+ return function(_time,_format,_12time){
+ if (!_time||!_format){
+ return '';
+ }
+ _time = new Date(_time);
+ _map.yyyy = _time.getFullYear();
+ _map.yy = (''+_map.yyyy).substr(2);
+ _map.M = _time.getMonth()+1;
+ _map.MM = _fmtnmb(_map.M);
+ _map.eM = _emon[_map.M-1];
+ _map.cM = _cmon[_map.M-1];
+ _map.d = _time.getDate();
+ _map.dd = _fmtnmb(_map.d);
+ _map.H = _time.getHours();
+ _map.HH = _fmtnmb(_map.H);
+ _map.m = _time.getMinutes();
+ _map.mm = _fmtnmb(_map.m);
+ _map.s = _time.getSeconds();
+ _map.ss = _fmtnmb(_map.s);
+ _map.ms = _time.getMilliseconds();
+ _map.w = _week[_time.getDay()];
+ var _cc = _fmtclc(_map.H);
+ _map.ct = _12cc[_cc];
+ _map.et = _12ec[_cc];
+ if (!!_12time){
+ _map.H = _map.H%12;
+ }
+ return _$encode(_map,_format);
+ };
+ })();
+
+ module.exports = util;
+
+/***/ },
+/* 3 */
+/***/ function(module, exports) {
+
+ /**
+ * ------------------------------------------------------------
+ * const 常量
+ * ------------------------------------------------------------
+ */
+
+ 'use strict';
+
+ var CONST = {};
+ CONST.emoji={"[大笑]":{file:"emoji_0.png"},"[可爱]":{file:"emoji_01.png"},"[色]":{file:"emoji_02.png"},"[嘘]":{file:"emoji_03.png"},"[亲]":{file:"emoji_04.png"},"[呆]":{file:"emoji_05.png"},"[口水]":{file:"emoji_06.png"},"[汗]":{file:"emoji_145.png"},"[呲牙]":{file:"emoji_07.png"},"[鬼脸]":{file:"emoji_08.png"},"[害羞]":{file:"emoji_09.png"},"[偷笑]":{file:"emoji_10.png"},"[调皮]":{file:"emoji_11.png"},"[可怜]":{file:"emoji_12.png"},"[敲]":{file:"emoji_13.png"},"[惊讶]":{file:"emoji_14.png"},"[流感]":{file:"emoji_15.png"},"[委屈]":{file:"emoji_16.png"},"[流泪]":{file:"emoji_17.png"},"[嚎哭]":{file:"emoji_18.png"},"[惊恐]":{file:"emoji_19.png"},"[怒]":{file:"emoji_20.png"},"[酷]":{file:"emoji_21.png"},"[不说]":{file:"emoji_22.png"},"[鄙视]":{file:"emoji_23.png"},"[阿弥陀佛]":{file:"emoji_24.png"},"[奸笑]":{file:"emoji_25.png"},"[睡着]":{file:"emoji_26.png"},"[口罩]":{file:"emoji_27.png"},"[努力]":{file:"emoji_28.png"},"[抠鼻孔]":{file:"emoji_29.png"},"[疑问]":{file:"emoji_30.png"},"[怒骂]":{file:"emoji_31.png"},"[晕]":{file:"emoji_32.png"},"[呕吐]":{file:"emoji_33.png"},"[拜一拜]":{file:"emoji_160.png"},"[惊喜]":{file:"emoji_161.png"},"[流汗]":{file:"emoji_162.png"},"[卖萌]":{file:"emoji_163.png"},"[默契眨眼]":{file:"emoji_164.png"},"[烧香拜佛]":{file:"emoji_165.png"},"[晚安]":{file:"emoji_166.png"},"[强]":{file:"emoji_34.png"},"[弱]":{file:"emoji_35.png"},"[OK]":{file:"emoji_36.png"},"[拳头]":{file:"emoji_37.png"},"[胜利]":{file:"emoji_38.png"},"[鼓掌]":{file:"emoji_39.png"},"[握手]":{file:"emoji_200.png"},"[发怒]":{file:"emoji_40.png"},"[骷髅]":{file:"emoji_41.png"},"[便便]":{file:"emoji_42.png"},"[火]":{file:"emoji_43.png"},"[溜]":{file:"emoji_44.png"},"[爱心]":{file:"emoji_45.png"},"[心碎]":{file:"emoji_46.png"},"[钟情]":{file:"emoji_47.png"},"[唇]":{file:"emoji_48.png"},"[戒指]":{file:"emoji_49.png"},"[钻石]":{file:"emoji_50.png"},"[太阳]":{file:"emoji_51.png"},"[有时晴]":{file:"emoji_52.png"},"[多云]":{file:"emoji_53.png"},"[雷]":{file:"emoji_54.png"},"[雨]":{file:"emoji_55.png"},"[雪花]":{file:"emoji_56.png"},"[爱人]":{file:"emoji_57.png"},"[帽子]":{file:"emoji_58.png"},"[皇冠]":{file:"emoji_59.png"},"[篮球]":{file:"emoji_60.png"},"[足球]":{file:"emoji_61.png"},"[垒球]":{file:"emoji_62.png"},"[网球]":{file:"emoji_63.png"},"[台球]":{file:"emoji_64.png"},"[咖啡]":{file:"emoji_65.png"},"[啤酒]":{file:"emoji_66.png"},"[干杯]":{file:"emoji_67.png"},"[柠檬汁]":{file:"emoji_68.png"},"[餐具]":{file:"emoji_69.png"},"[汉堡]":{file:"emoji_70.png"},"[鸡腿]":{file:"emoji_71.png"},"[面条]":{file:"emoji_72.png"},"[冰淇淋]":{file:"emoji_73.png"},"[沙冰]":{file:"emoji_74.png"},"[生日蛋糕]":{file:"emoji_75.png"},"[蛋糕]":{file:"emoji_76.png"},"[糖果]":{file:"emoji_77.png"},"[葡萄]":{file:"emoji_78.png"},"[西瓜]":{file:"emoji_79.png"},"[光碟]":{file:"emoji_80.png"},"[手机]":{file:"emoji_81.png"},"[电话]":{file:"emoji_82.png"},"[电视]":{file:"emoji_83.png"},"[声音开启]":{file:"emoji_84.png"},"[声音关闭]":{file:"emoji_85.png"},"[铃铛]":{file:"emoji_86.png"},"[锁头]":{file:"emoji_87.png"},"[放大镜]":{file:"emoji_88.png"},"[灯泡]":{file:"emoji_89.png"},"[锤头]":{file:"emoji_90.png"},"[烟]":{file:"emoji_91.png"},"[炸弹]":{file:"emoji_92.png"},"[枪]":{file:"emoji_93.png"},"[刀]":{file:"emoji_94.png"},"[药]":{file:"emoji_95.png"},"[打针]":{file:"emoji_96.png"},"[钱袋]":{file:"emoji_97.png"},"[钞票]":{file:"emoji_98.png"},"[银行卡]":{file:"emoji_99.png"},"[手柄]":{file:"emoji_100.png"},"[麻将]":{file:"emoji_101.png"},"[调色板]":{file:"emoji_102.png"},"[电影]":{file:"emoji_103.png"},"[麦克风]":{file:"emoji_104.png"},"[耳机]":{file:"emoji_105.png"},"[音乐]":{file:"emoji_106.png"},"[吉他]":{file:"emoji_107.png"},"[火箭]":{file:"emoji_108.png"},"[飞机]":{file:"emoji_109.png"},"[火车]":{file:"emoji_110.png"},"[公交]":{file:"emoji_111.png"},"[轿车]":{file:"emoji_112.png"},"[出租车]":{file:"emoji_113.png"},"[警车]":{file:"emoji_114.png"},"[自行车]":{file:"emoji_115.png"}};
+
+ module.exports = CONST;
+
+/***/ },
+/* 4 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /**
+ * ------------------------------------------------------------
+ * FriendList 好友列表UI
+ * ------------------------------------------------------------
+ */
+
+ 'use strict';
+ var util = __webpack_require__(2);
+
+ var ACCOUNT;
+
+ /**
+ * 好友列表控件
+ * @param {Object} options 控件初始化参数
+ * @property {String||Node} parent 父节点
+ * @property {String} clazz 样式名称
+ * @property {Function} onclickitem 点击列表回调
+ * @property {Function} onclickavatar 点击列表头像回调
+ * @property {Object} data 消息数据 data.friends 好友数据 data.friends data.userinfo 用户信息
+ */
+ var FriendList = function(options){
+ var parent = options.parent,
+ data = options.data,
+ cbClickList = options.onclickitem||function(account,type){console.log('account:'+account+'---type:'+type);},
+ cbClickPortrait = options.onclickavatar||function(account,type){console.log('account:'+account+'---type:'+type);};
+ ACCOUNT = data.account;
+ this._body = document.createElement('ul');
+ this._body.className = options.clazz||"m-panel" +" j-friend";
+
+ util.addEvent(this._body,'click',function(e){
+ var self = this,
+ evt = e||window.event,
+ account,
+ type,
+ target = evt.srcElement||evt.target;
+ while(self!==target){
+ if (target.tagName.toLowerCase() === "img") {
+ var item = target.parentNode;
+ account = item.getAttribute("data-account");
+ type = item.getAttribute("data-type");
+ cbClickPortrait(account,type);
+ return;
+ }else if(target.tagName.toLowerCase() === "li"){
+ account = target.getAttribute("data-account");
+ type = target.getAttribute("data-type");
+ util.removeClass(util.getNode(".j-friend li.active"),'active');
+ util.addClass(target,"active");
+ cbClickList(account,type);
+ return;
+ }
+ target = target.parentNode;
+ }
+ });
+ this.update(data);
+ if(!!parent){
+ this.inject(parent);
+ }
+ };
+ /** --------------------------public------------------------------ */
+
+ /**
+ * 插入控件
+ * @param {Node|String} node 插入控件的节点
+ * @return {Void}
+ */
+ FriendList.prototype.inject = function(node){
+ var injectNode = util.getNode(node);
+ injectNode.innerHTML = "";
+ injectNode.appendChild(this._body);
+ };
+
+ /**
+ * 更新视图
+ * @param {Object} data
+ * @return {Void}
+ */
+ FriendList.prototype.update = function(data){
+ var html="",
+ list = data.friends;
+ for (var i = 0; i < list.length; i++) {
+ if (list[i].account !== ACCOUNT) {
+ html += ['',
+ '',
+ '',
+ '
',
+ '' + list[i].nick+'',
+ '
',
+ '
',
+ ''].join("");
+ }
+ }
+ this._body.innerHTML = html;
+ };
+
+ /**
+ * 控件销毁
+ * @return {void}
+ */
+ FriendList.prototype.destory = function(){
+ //预留
+ };
+
+
+
+
+ module.exports = FriendList;
+
+/***/ },
+/* 5 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /**
+ * ------------------------------------------------------------
+ * TeamList 群组列表UI
+ * ------------------------------------------------------------
+ */
+
+ 'use strict';
+ var util = __webpack_require__(2);
+
+ /**
+ * 群组列表控件
+ * @param {Object} options 控件初始化参数
+ * @property {String||Node} parent 父节点
+ * @property {String} clazz 样式名称
+ * @property {Function} onclickitem 点击列表回调
+ * @property {Function} onclickavatar 点击列表头像回调
+ * @property {Object} data 消息数据 data.teams 群组数据
+ */
+ var TeamList = function(options){
+ var parent = options.parent,
+ data = options.data,
+ cbClickList = options.onclickitem||function(account,type){console.log('account:'+account+'---type:'+type);},
+ cbClickPortrait = options.onclickavatar||function(account,type){console.log('account:'+account+'---type:'+type);};
+
+ this._body = document.createElement('ul');
+ this._body.className = options.clazz||"m-panel" +" j-team";
+
+ util.addEvent(this._body,'click',function(e){
+ var self = this,
+ evt = e||window.event,
+ account,
+ type,
+ target = evt.srcElement||evt.target;
+ while(self!==target){
+ if (target.tagName.toLowerCase() === "img") {
+ var item = target.parentNode;
+ account = item.getAttribute("data-account");
+ type = item.getAttribute("data-type");
+ cbClickPortrait(account,type);
+ return;
+ }else if(target.tagName.toLowerCase() === "li"){
+ account = target.getAttribute("data-account");
+ type = target.getAttribute("data-type");
+ util.removeClass(util.getNode(".j-team li.active"),'active');
+ util.addClass(target,"active");
+ cbClickList(account,type);
+ return;
+ }
+ target = target.parentNode;
+ }
+ });
+ this.update(data);
+ if(!!parent){
+ this.inject(parent);
+ }
+ };
+
+ /** --------------------------public------------------------------ */
+
+ /**
+ * 插入控件
+ * @param {Node|String} node 插入控件的节点
+ * @return {Void}
+ */
+ TeamList.prototype.inject = function(node){
+ var injectNode = util.getNode(node);
+ injectNode.innerHTML = "";
+ injectNode.appendChild(this._body);
+ };
+
+ /**
+ * 更新视图
+ * @param {Object} data
+ * @return {Void}
+ */
+ TeamList.prototype.update = function(data){
+ var tmp1 = '普通群
',
+ tmp2 = '高级群
',
+ flag1 = false,
+ flag2 = false,
+ html = '',
+ teams = data.teams;
+ if (teams && teams.length > 0) {
+ for (var i = 0, l = teams.length; i < l; ++i) {
+ if (teams[i].type === 'normal') {
+ flag1 = true;
+ tmp1 += '';
+ tmp1 += '
' + teams[i].name||teams[i].teamId + '
';
+ } else if (teams[i].type === 'advanced') {
+ flag2 = true;
+ tmp2 += '';
+ tmp2 += '
' + teams[i].name||teams[i].teamId + '
';
+ }
+ }
+ tmp1 += '
';
+ tmp2 += '
';
+ if (flag1 && flag2) {
+ html = tmp2 + tmp1;
+ } else if (flag1 && !flag2) {
+ html = tmp1;
+ } else if (!flag1 && flag2) {
+ html = tmp2;
+ } else {
+ html = '暂时还没有群哦
';
+ }
+ } else {
+ html = '暂时还没有群哦
';
+ }
+ this._body.innerHTML = html;
+ };
+
+ /**
+ * 控件销毁
+ * @return {void}
+ */
+ TeamList.prototype.destory = function(){
+ //预留
+ };
+
+
+
+
+ module.exports = TeamList;
+
+/***/ }
+/******/ ])
+});
+;
\ No newline at end of file
diff --git a/dist/uiKit.min.js b/dist/uiKit.min.js
new file mode 100644
index 0000000..ff3d84b
--- /dev/null
+++ b/dist/uiKit.min.js
@@ -0,0 +1 @@
+!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.NIMUIKit=t():e.NIMUIKit=t()}(this,function(){return function(e){function t(n){if(i[n])return i[n].exports;var o=i[n]={exports:{},id:n,loaded:!1};return e[n].call(o.exports,o,o.exports,t),o.loaded=!0,o.exports}var i={};return t.m=e,t.c=i,t.p="",t(0)}([function(e,t,i){"use strict";var n={};n.SessionList=i(1),n.FriendList=i(4),n.TeamList=i(5),e.exports=n},function(e,t,i){"use strict";function n(e){return e.to===o?e.from:e.to}var o,a=i(2),r=function(e){var t=e.parent,i=e.data,n=e.onclickitem||function(e,t){console.log("account:"+e+"---type:"+t)},r=e.onclickavatar||function(e,t){console.log("account:"+e+"---type:"+t)};o=i.account,this._body=document.createElement("ul"),this._body.className=e.clazz||"m-panel j-session",a.addEvent(this._body,"click",function(e){for(var t,i,o=this,s=e||window.event,l=s.srcElement||s.target;o!==l;){if("img"===l.tagName.toLowerCase()){var p=l.parentNode;return t=p.getAttribute("data-account"),i=p.getAttribute("data-type"),void r(t,i)}if("li"===l.tagName.toLowerCase()){t=l.getAttribute("data-account"),i=l.getAttribute("data-type"),a.removeClass(a.getNode(".j-session li.active"),"active"),a.addClass(l,"active");var c=l.querySelector(".count");return a.addClass(c,"hide"),c.innerHTML=0,void n(t,i)}l=l.parentNode}}),this.update(i),t&&this.inject(t)};r.prototype.inject=function(e){var t=a.getNode(e);t.innerHTML="",t.appendChild(this._body)},r.prototype.update=function(e){var t,i,r,l,p,c,m,f,g="",d=e.msgs,u=e.unreadmsgs,j=e.userinfo,_=e.teamInfo;if(0===d.length)g+='暂无最近联系人哦
';else for(var v=0;v99?"99+":u[c].count),f="99+"===m||m>0,"team"===t.scene?(i=_[c].name||c,r=_[c].type||"normal",l="images/"+r+".png"):(i=j[c].nick,l=a.getAvatar(j[c].avatar));var y=['','','',"
",""+i+"",''+a.transTime2(t.time)+"","
","
",''+s(t,j,o)+"",''+m+"","
","
",""].join("");g+=y}this._body.innerHTML=g},r.prototype.destory=function(){};var s=function(e,t,i){var n="p2p"!==e.scene?e.fromNick+":":"",o=e.type;if(!/text|image|file|audio|video|geo|custom|notification/i.test(o))return"";switch(o){case"text":n+=a.safeHtml(e.text),n=a.buildEmoji(n);break;case"image":n+="[图片]";break;case"file":n+=/exe|bat/i.test(e.file.ext)?"[非法文件,已被本站拦截]":"[文件]";break;case"audio":n+="[语音]";break;case"video":n+="[视频]";break;case"geo":n+="[位置]";break;case"custom":var r=JSON.parse(e.content);n+=1===r.type?"[猜拳]":2===r.type?"[阅后即焚]":3===r.type?"[贴图]":4===r.type?"[白板]":"[自定义消息]";break;case"notification":n="["+a.transNotification(e,t,i)+"]";break;default:n+="[未知消息类型]"}return n};e.exports=r},function(e,t,i){"use strict";var n=i(3),o=n.emoji,a={getNode:function(e){return this.isString(e)?document.querySelector(e):this.isElement(e)?e:void console.error("输入参数必须为node||String")},getNodes:function(e){return document.querySelectorAll(e)},isString:function(e){return"string"==typeof e},isElement:function(e){return!(!e||1!==e.nodeType)},isArray:Array.isArray||function(e){return"[object Array]"===Object.prototype.toString.call(e)},addEvent:function(e,t,i){window.addEventListener?e.addEventListener(t,i,!1):e.attachEvent("on"+t,i)},hasClass:function(e,t){return t=t||"",0===t.replace(/\s/g,"").length?!1:new RegExp(" "+t+" ").test(" "+e.className+" ")},addClass:function(e,t){e&&(this.hasClass(e,t)||(e.className+=" "+t))},removeClass:function(e,t){if(e&&this.hasClass(e,t)){for(var i=" "+e.className.replace(/[\t\r\n]/g,"")+" ";i.indexOf(" "+t+" ")>=0;)i=i.replace(" "+t+" "," ");e.className=i.replace(/^\s+|\s+$/g,"")}},safeHtml:function(){var e=/
$/,t={r:/<|>|\&|\r|\n|\s|\'|\"/g,"<":"<",">":">","&":"&"," ":" ",'"':""","'":"'","\n":"
","\r":""};return function(i){return i=r(t,i),i.replace(e,"
")}}(),getAvatar:function(e){var t=/^((http|https|ftp):\/\/)?(\w(\:\w)?@)?([0-9a-z_-]+\.)*?([a-z0-9-]+\.[a-z]{2,6}(\.[a-z]{2})?(\:[0-9]{2,6})?)((\/[^?#<>\/\\*":]*)+(\?[^#]*)?(#.*)?)?$/i;return t.test(e)?e:"images/default-icon.png"},buildEmoji:function(e){for(var t=/\[([^\]\[]*)\]/g,i=e.match(t)||[],n=0,a=i.length;a>n;++n)o[i[n]]&&(e=e.replace(i[n],''));return e},transNotification:function(e,t,i){var n,o,a,r=e.attach.type,s=e.from===i?!0:!1,l=[];switch(r){case"addTeamMembers":for(o=e.attach.accounts,a=0;a=i[0]?s(t,"HH:mm"):t=i[1]?s(t,"MM-dd HH:mm"):s(t,"yyyy-MM-dd HH:mm")}}(),transTime2:function(){var e=function(e){e.setMinutes(0),e.setSeconds(0),e.setMilliseconds(0),e.setHours(0);var t=e.getTime();e.setMonth(1),e.setDate(1);var i=e.getTime();return[t,i]};return function(t){var i=e(new Date);return t>=i[0]?s(t,"HH:mm"):t>=i[0]-864e5?"昨天":t>=i[0]-1728e5?"前天":t>=i[0]-6048e5?"星期"+s(t,"w"):t>=i[1]?s(t,"MM-dd"):s(t,"yyyy-MM-dd")}}()},r=function(e,t){return t=""+t,e&&t?t.replace(e.r,function(t){var i=e[e.i?t:t.toLowerCase()];return null!=i?i:t}):t||""},s=function(){var e={i:!0,r:/\byyyy|yy|MM|cM|eM|M|dd|d|HH|H|mm|ms|ss|m|s|w|ct|et\b/g},t=["上午","下午"],i=["A.M.","P.M."],n=["日","一","二","三","四","五","六"],o=["一","二","三","四","五","六","七","八","九","十","十一","十二"],a=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sept","Oct","Nov","Dec"],s=function(e){return e=parseInt(e,10)||0,(10>e?"0":"")+e},l=function(e){return 12>e?0:1};return function(p,c,m){if(!p||!c)return"";p=new Date(p),e.yyyy=p.getFullYear(),e.yy=(""+e.yyyy).substr(2),e.M=p.getMonth()+1,e.MM=s(e.M),e.eM=a[e.M-1],e.cM=o[e.M-1],e.d=p.getDate(),e.dd=s(e.d),e.H=p.getHours(),e.HH=s(e.H),e.m=p.getMinutes(),e.mm=s(e.m),e.s=p.getSeconds(),e.ss=s(e.s),e.ms=p.getMilliseconds(),e.w=n[p.getDay()];var f=l(e.H);return e.ct=t[f],e.et=i[f],m&&(e.H=e.H%12),r(e,c)}}();e.exports=a},function(e,t){"use strict";var i={};i.emoji={"[大笑]":{file:"emoji_0.png"},"[可爱]":{file:"emoji_01.png"},"[色]":{file:"emoji_02.png"},"[嘘]":{file:"emoji_03.png"},"[亲]":{file:"emoji_04.png"},"[呆]":{file:"emoji_05.png"},"[口水]":{file:"emoji_06.png"},"[汗]":{file:"emoji_145.png"},"[呲牙]":{file:"emoji_07.png"},"[鬼脸]":{file:"emoji_08.png"},"[害羞]":{file:"emoji_09.png"},"[偷笑]":{file:"emoji_10.png"},"[调皮]":{file:"emoji_11.png"},"[可怜]":{file:"emoji_12.png"},"[敲]":{file:"emoji_13.png"},"[惊讶]":{file:"emoji_14.png"},"[流感]":{file:"emoji_15.png"},"[委屈]":{file:"emoji_16.png"},"[流泪]":{file:"emoji_17.png"},"[嚎哭]":{file:"emoji_18.png"},"[惊恐]":{file:"emoji_19.png"},"[怒]":{file:"emoji_20.png"},"[酷]":{file:"emoji_21.png"},"[不说]":{file:"emoji_22.png"},"[鄙视]":{file:"emoji_23.png"},"[阿弥陀佛]":{file:"emoji_24.png"},"[奸笑]":{file:"emoji_25.png"},"[睡着]":{file:"emoji_26.png"},"[口罩]":{file:"emoji_27.png"},"[努力]":{file:"emoji_28.png"},"[抠鼻孔]":{file:"emoji_29.png"},"[疑问]":{file:"emoji_30.png"},"[怒骂]":{file:"emoji_31.png"},"[晕]":{file:"emoji_32.png"},"[呕吐]":{file:"emoji_33.png"},"[拜一拜]":{file:"emoji_160.png"},"[惊喜]":{file:"emoji_161.png"},"[流汗]":{file:"emoji_162.png"},"[卖萌]":{file:"emoji_163.png"},"[默契眨眼]":{file:"emoji_164.png"},"[烧香拜佛]":{file:"emoji_165.png"},"[晚安]":{file:"emoji_166.png"},"[强]":{file:"emoji_34.png"},"[弱]":{file:"emoji_35.png"},"[OK]":{file:"emoji_36.png"},"[拳头]":{file:"emoji_37.png"},"[胜利]":{file:"emoji_38.png"},"[鼓掌]":{file:"emoji_39.png"},"[握手]":{file:"emoji_200.png"},"[发怒]":{file:"emoji_40.png"},"[骷髅]":{file:"emoji_41.png"},"[便便]":{file:"emoji_42.png"},"[火]":{file:"emoji_43.png"},"[溜]":{file:"emoji_44.png"},"[爱心]":{file:"emoji_45.png"},"[心碎]":{file:"emoji_46.png"},"[钟情]":{file:"emoji_47.png"},"[唇]":{file:"emoji_48.png"},"[戒指]":{file:"emoji_49.png"},"[钻石]":{file:"emoji_50.png"},"[太阳]":{file:"emoji_51.png"},"[有时晴]":{file:"emoji_52.png"},"[多云]":{file:"emoji_53.png"},"[雷]":{file:"emoji_54.png"},"[雨]":{file:"emoji_55.png"},"[雪花]":{file:"emoji_56.png"},"[爱人]":{file:"emoji_57.png"},"[帽子]":{file:"emoji_58.png"},"[皇冠]":{file:"emoji_59.png"},"[篮球]":{file:"emoji_60.png"},"[足球]":{file:"emoji_61.png"},"[垒球]":{file:"emoji_62.png"},"[网球]":{file:"emoji_63.png"},"[台球]":{file:"emoji_64.png"},"[咖啡]":{file:"emoji_65.png"},"[啤酒]":{file:"emoji_66.png"},"[干杯]":{file:"emoji_67.png"},"[柠檬汁]":{file:"emoji_68.png"},"[餐具]":{file:"emoji_69.png"},"[汉堡]":{file:"emoji_70.png"},"[鸡腿]":{file:"emoji_71.png"},"[面条]":{file:"emoji_72.png"},"[冰淇淋]":{file:"emoji_73.png"},"[沙冰]":{file:"emoji_74.png"},"[生日蛋糕]":{file:"emoji_75.png"},"[蛋糕]":{file:"emoji_76.png"},"[糖果]":{file:"emoji_77.png"},"[葡萄]":{file:"emoji_78.png"},"[西瓜]":{file:"emoji_79.png"},"[光碟]":{file:"emoji_80.png"},"[手机]":{file:"emoji_81.png"},"[电话]":{file:"emoji_82.png"},"[电视]":{file:"emoji_83.png"},"[声音开启]":{file:"emoji_84.png"},"[声音关闭]":{file:"emoji_85.png"},"[铃铛]":{file:"emoji_86.png"},"[锁头]":{file:"emoji_87.png"},"[放大镜]":{file:"emoji_88.png"},"[灯泡]":{file:"emoji_89.png"},"[锤头]":{file:"emoji_90.png"},"[烟]":{file:"emoji_91.png"},"[炸弹]":{file:"emoji_92.png"},"[枪]":{file:"emoji_93.png"},"[刀]":{file:"emoji_94.png"},"[药]":{file:"emoji_95.png"},"[打针]":{file:"emoji_96.png"},"[钱袋]":{file:"emoji_97.png"},"[钞票]":{file:"emoji_98.png"},"[银行卡]":{file:"emoji_99.png"},"[手柄]":{file:"emoji_100.png"},"[麻将]":{file:"emoji_101.png"},"[调色板]":{file:"emoji_102.png"},"[电影]":{file:"emoji_103.png"},"[麦克风]":{file:"emoji_104.png"},"[耳机]":{file:"emoji_105.png"},"[音乐]":{file:"emoji_106.png"},"[吉他]":{file:"emoji_107.png"},"[火箭]":{file:"emoji_108.png"},"[飞机]":{file:"emoji_109.png"},"[火车]":{file:"emoji_110.png"},"[公交]":{file:"emoji_111.png"},"[轿车]":{file:"emoji_112.png"},"[出租车]":{file:"emoji_113.png"},"[警车]":{file:"emoji_114.png"},"[自行车]":{file:"emoji_115.png"}},e.exports=i},function(e,t,i){"use strict";var n,o=i(2),a=function(e){var t=e.parent,i=e.data,a=e.onclickitem||function(e,t){console.log("account:"+e+"---type:"+t)},r=e.onclickavatar||function(e,t){console.log("account:"+e+"---type:"+t)};n=i.account,this._body=document.createElement("ul"),this._body.className=e.clazz||"m-panel j-friend",o.addEvent(this._body,"click",function(e){for(var t,i,n=this,s=e||window.event,l=s.srcElement||s.target;n!==l;){if("img"===l.tagName.toLowerCase()){var p=l.parentNode;return t=p.getAttribute("data-account"),i=p.getAttribute("data-type"),void r(t,i)}if("li"===l.tagName.toLowerCase())return t=l.getAttribute("data-account"),i=l.getAttribute("data-type"),o.removeClass(o.getNode(".j-friend li.active"),"active"),o.addClass(l,"active"),void a(t,i);l=l.parentNode}}),this.update(i),t&&this.inject(t)};a.prototype.inject=function(e){var t=o.getNode(e);t.innerHTML="",t.appendChild(this._body)},a.prototype.update=function(e){for(var t="",i=e.friends,a=0;a','','','
',""+i[a].nick+"","
","
",""].join(""));this._body.innerHTML=t},a.prototype.destory=function(){},e.exports=a},function(e,t,i){"use strict";var n=i(2),o=function(e){var t=e.parent,i=e.data,o=e.onclickitem||function(e,t){console.log("account:"+e+"---type:"+t)},a=e.onclickavatar||function(e,t){console.log("account:"+e+"---type:"+t)};this._body=document.createElement("ul"),this._body.className=e.clazz||"m-panel j-team",n.addEvent(this._body,"click",function(e){for(var t,i,r=this,s=e||window.event,l=s.srcElement||s.target;r!==l;){if("img"===l.tagName.toLowerCase()){var p=l.parentNode;return t=p.getAttribute("data-account"),i=p.getAttribute("data-type"),void a(t,i)}if("li"===l.tagName.toLowerCase())return t=l.getAttribute("data-account"),i=l.getAttribute("data-type"),n.removeClass(n.getNode(".j-team li.active"),"active"),n.addClass(l,"active"),void o(t,i);l=l.parentNode}}),this.update(i),t&&this.inject(t)};o.prototype.inject=function(e){var t=n.getNode(e);t.innerHTML="",t.appendChild(this._body)},o.prototype.update=function(e){var t='普通群
',i='高级群
',n=!1,o=!1,a="",r=e.teams;if(r&&r.length>0){for(var s=0,l=r.length;l>s;++s)"normal"===r[s].type?(n=!0,t+='',t+='
'+r[s].name||r[s].teamId+'
'):"advanced"===r[s].type&&(o=!0,i+='',i+='
'+r[s].name||r[s].teamId+'
');t+="
",i+="
",a=n&&o?i+t:n&&!o?t:!n&&o?i:"暂时还没有群哦
"}else a="暂时还没有群哦
";this._body.innerHTML=a},o.prototype.destory=function(){},e.exports=o}])});
\ No newline at end of file
diff --git a/gulpfile.js b/gulpfile.js
new file mode 100644
index 0000000..4080ea3
--- /dev/null
+++ b/gulpfile.js
@@ -0,0 +1,27 @@
+var gulp = require('gulp'),
+ jshint = require('gulp-jshint'),
+ webpack = require('gulp-webpack'),
+ uglify = require('gulp-uglify'),
+ rename = require('gulp-rename'),
+ concat = require('gulp-concat'),
+ webpackConfig = require('./webpack.config.js');
+
+gulp.task('lint', function () {
+ gulp.src(['./src/js/**/*.js','./src/js/*.js'])
+ .pipe(jshint())
+ .pipe(jshint.reporter('default'));
+});
+
+gulp.task('dist', function () {
+ gulp.src('./src/js/index.js')
+ .pipe(webpack(webpackConfig))
+ .pipe(gulp.dest('./dist/'))
+ .pipe(rename('uiKit.min.js'))
+ .pipe(uglify())
+ .pipe(gulp.dest('./dist'));
+ gulp.src('./src/css/*.css')
+ .pipe(concat('uiKit.css'))
+ .pipe(gulp.dest('./dist'))
+})
+
+gulp.task('default', ['lint','dist']);
\ No newline at end of file
diff --git a/package.json b/package.json
index cb23400..c9d631d 100644
--- a/package.json
+++ b/package.json
@@ -12,8 +12,19 @@
},
"author": "",
"license": "ISC",
+ "devDependencies": {
+ "webpack": "~1.12.2",
+ "gulp": "~3.9.0",
+ "gulp-rename": "~1.2.2",
+ "gulp-uglify": "~1.4.1",
+ "gulp-concat": "^2.6.0",
+ "gulp-webpack": "~1.5.0",
+ "gulp-jshint": "~1.11.2"
+ },
"bugs": {
"url": "https://github.com/netease-im/NIM_Web_UIKit/issues"
},
"homepage": "https://github.com/netease-im/NIM_Web_UIKit#readme"
}
+
+
diff --git a/src/css/list.css b/src/css/list.css
new file mode 100644
index 0000000..70d42b1
--- /dev/null
+++ b/src/css/list.css
@@ -0,0 +1,134 @@
+.m-panel .emoji {
+ width: 20px;
+ height: 20px;
+ vertical-align: middle;
+ float: none;
+}
+.m-panel .empty{
+ padding: 10px 5px;
+}
+.m-panel .list {
+ height: 100%;
+ width: 100%;
+ position: relative;
+ overflow-y: auto;
+ background-color: #fff;
+ border-radius: 0 0 5px 5px;
+}
+.m-panel .list>p, .m-panel .list>ul>p {
+ padding: 10px;
+}
+.m-panel li,.m-panel .item{
+ clear:both;
+ border-bottom:1px solid #eaeeef;
+ overflow:hidden;
+ height:61px;
+ padding:8px 10px;
+ box-sizing:border-box;
+ -webkit-box-sizing:border-box;
+ -moz-box-sizing:border-box;
+ cursor:default;
+ cursor: pointer;
+}
+.m-panel li:hover, .teams li:hover,.m-panel .item::hover{
+ background-color: #f5f5f5;
+}
+.m-panel li.active,.m-panel .item.active{
+ background-color: #f5f5f5;
+}
+.m-panel li.active .count{
+ display: none;
+}
+.m-panel li img,.m-panel .item img{
+ float: left;
+ width: 44px;
+ height: 44px;
+ border-radius: 50%;
+ -webkit-border-radius: 50%;
+ -moz-border-radius: 50%;
+ -ms-border-radius: 50%;
+}
+.m-panel .text {
+ margin-left: 60px;
+ padding:3px 0;
+ position: relative;
+ height: 45px;
+ overflow: hidden
+}
+.m-panel .tag{
+ float: left;
+ line-height: 40px;
+ margin-left:16px;
+}
+.m-panel .text span, .m-panel .first-msg {
+ width: 60%;
+ display: inline-block;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ -webkit-text-overflow: ellipsis;
+ -moz-text-overflow: ellipsis;
+ -ms-text-overflow: ellipsis;
+ white-space: nowrap;
+}
+.m-panel .text .time{
+ position: absolute;
+ right:0;
+ top:5px;
+ font-size: 12px;
+ color: #999;
+}
+.m-panel .text .nick {
+ line-height: 61px;
+ height:61px;
+ font-size: 13px;
+ color:#999;
+ margin: -11px 0;
+}
+.m-panel .text .nick, .m-panel .text .message {
+ position: relative;
+ color:#666;
+}
+.m-panel .text .nick span, .m-panel .text .message span {
+ display: inline-block;
+ width: 80%;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ -webkit-text-overflow: ellipsis;
+ -moz-text-overflow: ellipsis;
+ -ms-text-overflow: ellipsis;
+ overflow: hidden;
+}
+.m-panel .text .nick time {
+ position: absolute;
+ right: 0;
+ top: 0;
+ color:#aaa;
+}
+.m-panel .text .first-msg {
+ display: inline-block;
+ width: 80%;
+ color:#6b8299;
+ font-size: 12px;
+ height: 20px;
+ line-height: 20px;
+}
+.m-panel .text p{
+ height: 20px;
+}
+
+.m-panel .text .message span {
+ width: 80%;
+}
+.m-panel .text .count {
+ position: absolute;
+ background-color: #f24c3d;
+ display: inline-block;
+ font-size: 12px;
+ color: #fff;
+ border-radius: 10px;
+ right: 0;
+ top: 24px;
+ text-align: center;
+ padding: 0 5px;
+ width: 20px;
+}
\ No newline at end of file
diff --git a/src/js/base/const.js b/src/js/base/const.js
new file mode 100644
index 0000000..57adc3a
--- /dev/null
+++ b/src/js/base/const.js
@@ -0,0 +1,12 @@
+/**
+ * ------------------------------------------------------------
+ * const 常量
+ * ------------------------------------------------------------
+ */
+
+'use strict';
+
+var CONST = {};
+CONST.emoji={"[大笑]":{file:"emoji_0.png"},"[可爱]":{file:"emoji_01.png"},"[色]":{file:"emoji_02.png"},"[嘘]":{file:"emoji_03.png"},"[亲]":{file:"emoji_04.png"},"[呆]":{file:"emoji_05.png"},"[口水]":{file:"emoji_06.png"},"[汗]":{file:"emoji_145.png"},"[呲牙]":{file:"emoji_07.png"},"[鬼脸]":{file:"emoji_08.png"},"[害羞]":{file:"emoji_09.png"},"[偷笑]":{file:"emoji_10.png"},"[调皮]":{file:"emoji_11.png"},"[可怜]":{file:"emoji_12.png"},"[敲]":{file:"emoji_13.png"},"[惊讶]":{file:"emoji_14.png"},"[流感]":{file:"emoji_15.png"},"[委屈]":{file:"emoji_16.png"},"[流泪]":{file:"emoji_17.png"},"[嚎哭]":{file:"emoji_18.png"},"[惊恐]":{file:"emoji_19.png"},"[怒]":{file:"emoji_20.png"},"[酷]":{file:"emoji_21.png"},"[不说]":{file:"emoji_22.png"},"[鄙视]":{file:"emoji_23.png"},"[阿弥陀佛]":{file:"emoji_24.png"},"[奸笑]":{file:"emoji_25.png"},"[睡着]":{file:"emoji_26.png"},"[口罩]":{file:"emoji_27.png"},"[努力]":{file:"emoji_28.png"},"[抠鼻孔]":{file:"emoji_29.png"},"[疑问]":{file:"emoji_30.png"},"[怒骂]":{file:"emoji_31.png"},"[晕]":{file:"emoji_32.png"},"[呕吐]":{file:"emoji_33.png"},"[拜一拜]":{file:"emoji_160.png"},"[惊喜]":{file:"emoji_161.png"},"[流汗]":{file:"emoji_162.png"},"[卖萌]":{file:"emoji_163.png"},"[默契眨眼]":{file:"emoji_164.png"},"[烧香拜佛]":{file:"emoji_165.png"},"[晚安]":{file:"emoji_166.png"},"[强]":{file:"emoji_34.png"},"[弱]":{file:"emoji_35.png"},"[OK]":{file:"emoji_36.png"},"[拳头]":{file:"emoji_37.png"},"[胜利]":{file:"emoji_38.png"},"[鼓掌]":{file:"emoji_39.png"},"[握手]":{file:"emoji_200.png"},"[发怒]":{file:"emoji_40.png"},"[骷髅]":{file:"emoji_41.png"},"[便便]":{file:"emoji_42.png"},"[火]":{file:"emoji_43.png"},"[溜]":{file:"emoji_44.png"},"[爱心]":{file:"emoji_45.png"},"[心碎]":{file:"emoji_46.png"},"[钟情]":{file:"emoji_47.png"},"[唇]":{file:"emoji_48.png"},"[戒指]":{file:"emoji_49.png"},"[钻石]":{file:"emoji_50.png"},"[太阳]":{file:"emoji_51.png"},"[有时晴]":{file:"emoji_52.png"},"[多云]":{file:"emoji_53.png"},"[雷]":{file:"emoji_54.png"},"[雨]":{file:"emoji_55.png"},"[雪花]":{file:"emoji_56.png"},"[爱人]":{file:"emoji_57.png"},"[帽子]":{file:"emoji_58.png"},"[皇冠]":{file:"emoji_59.png"},"[篮球]":{file:"emoji_60.png"},"[足球]":{file:"emoji_61.png"},"[垒球]":{file:"emoji_62.png"},"[网球]":{file:"emoji_63.png"},"[台球]":{file:"emoji_64.png"},"[咖啡]":{file:"emoji_65.png"},"[啤酒]":{file:"emoji_66.png"},"[干杯]":{file:"emoji_67.png"},"[柠檬汁]":{file:"emoji_68.png"},"[餐具]":{file:"emoji_69.png"},"[汉堡]":{file:"emoji_70.png"},"[鸡腿]":{file:"emoji_71.png"},"[面条]":{file:"emoji_72.png"},"[冰淇淋]":{file:"emoji_73.png"},"[沙冰]":{file:"emoji_74.png"},"[生日蛋糕]":{file:"emoji_75.png"},"[蛋糕]":{file:"emoji_76.png"},"[糖果]":{file:"emoji_77.png"},"[葡萄]":{file:"emoji_78.png"},"[西瓜]":{file:"emoji_79.png"},"[光碟]":{file:"emoji_80.png"},"[手机]":{file:"emoji_81.png"},"[电话]":{file:"emoji_82.png"},"[电视]":{file:"emoji_83.png"},"[声音开启]":{file:"emoji_84.png"},"[声音关闭]":{file:"emoji_85.png"},"[铃铛]":{file:"emoji_86.png"},"[锁头]":{file:"emoji_87.png"},"[放大镜]":{file:"emoji_88.png"},"[灯泡]":{file:"emoji_89.png"},"[锤头]":{file:"emoji_90.png"},"[烟]":{file:"emoji_91.png"},"[炸弹]":{file:"emoji_92.png"},"[枪]":{file:"emoji_93.png"},"[刀]":{file:"emoji_94.png"},"[药]":{file:"emoji_95.png"},"[打针]":{file:"emoji_96.png"},"[钱袋]":{file:"emoji_97.png"},"[钞票]":{file:"emoji_98.png"},"[银行卡]":{file:"emoji_99.png"},"[手柄]":{file:"emoji_100.png"},"[麻将]":{file:"emoji_101.png"},"[调色板]":{file:"emoji_102.png"},"[电影]":{file:"emoji_103.png"},"[麦克风]":{file:"emoji_104.png"},"[耳机]":{file:"emoji_105.png"},"[音乐]":{file:"emoji_106.png"},"[吉他]":{file:"emoji_107.png"},"[火箭]":{file:"emoji_108.png"},"[飞机]":{file:"emoji_109.png"},"[火车]":{file:"emoji_110.png"},"[公交]":{file:"emoji_111.png"},"[轿车]":{file:"emoji_112.png"},"[出租车]":{file:"emoji_113.png"},"[警车]":{file:"emoji_114.png"},"[自行车]":{file:"emoji_115.png"}};
+
+module.exports = CONST;
\ No newline at end of file
diff --git a/src/js/base/util.js b/src/js/base/util.js
new file mode 100644
index 0000000..5b96c9e
--- /dev/null
+++ b/src/js/base/util.js
@@ -0,0 +1,276 @@
+/**
+ * ------------------------------------------------------------
+ * util 工具库
+ * ------------------------------------------------------------
+ */
+
+'use strict';
+var CONST = require("./const.js"),
+ emoji = CONST.emoji;
+
+var util = {
+ getNode: function(ipt){
+ if(this.isString(ipt)){
+ return document.querySelector(ipt);
+ }else if(this.isElement(ipt)){
+ return ipt;
+ }else{
+ console.error("输入参数必须为node||String");
+ }
+ },
+ getNodes: function(string){
+ return document.querySelectorAll(string);
+ },
+ isString: function(data){
+ return typeof(data)==='string';
+ },
+ isElement:function(obj){
+ return !!(obj && obj.nodeType === 1);
+ },
+ isArray:Array.isArray|| function(obj) {
+ return Object.prototype.toString.call(obj) === '[object Array]';
+ },
+
+ addEvent: function(node,type,callback){
+ if(window.addEventListener){
+ node.addEventListener(type,callback,false);
+ }else{
+ node.attachEvent("on"+type,callback);
+ }
+ },
+
+ hasClass: function(elem, cls){
+ cls = cls || '';
+ if(cls.replace(/\s/g, '').length === 0){
+ return false;
+ }
+ return new RegExp(' ' + cls + ' ').test(' ' + elem.className + ' ');
+ },
+
+ addClass: function(elem, cls){
+ if(!elem){
+ return;
+ }
+ if(!this.hasClass(elem, cls)){
+ elem.className += ' ' + cls;
+ }
+ },
+ removeClass: function(elem, cls){
+ if(!elem){
+ return;
+ }
+ if(this.hasClass(elem, cls)){
+ var newClass = ' ' + elem.className.replace(/[\t\r\n]/g, '') + ' ';
+ while(newClass.indexOf(' ' + cls + ' ') >= 0){
+ newClass = newClass.replace(' ' + cls + ' ', ' ');
+ }
+ elem.className = newClass.replace(/^\s+|\s+$/g, '');
+ }
+ },
+ safeHtml: (function(){
+ var reg = /
$/,
+ map = {
+ r:/<|>|\&|\r|\n|\s|\'|\"/g,
+ '<':'<','>':'>','&':'&',' ':' ',
+ '"':'"',"'":''','\n':'
','\r':''
+ };
+ return function(content){
+ content = _$encode(map,content);
+ return content.replace(reg,'
');
+ };
+ })(),
+ getAvatar:function(url){
+ var re=/^((http|https|ftp):\/\/)?(\w(\:\w)?@)?([0-9a-z_-]+\.)*?([a-z0-9-]+\.[a-z]{2,6}(\.[a-z]{2})?(\:[0-9]{2,6})?)((\/[^?#<>\/\\*":]*)+(\?[^#]*)?(#.*)?)?$/i;
+ if(re.test(url)){
+ return url;
+ }else{
+ return "images/default-icon.png";
+ }
+ },
+ /**
+ * 通过正则替换掉文本消息中的emoji表情
+ * @param text:文本消息内容
+ */
+ buildEmoji:function(text) {
+ var re = /\[([^\]\[]*)\]/g;
+ var matches = text.match(re) || [];
+ for (var j = 0, len = matches.length; j < len; ++j) {
+ if(emoji[matches[j]]){
+ text = text.replace(matches[j], '');
+ }
+ }
+ return text;
+ },
+ /**
+ * 群通知处理
+ * @param {Object} item
+ * @return {String}
+ */
+ transNotification:function(item,info,myAccount) {
+ var type = item.attach.type,
+ from = (item.from === myAccount?true:false),
+ str,
+ accounts,
+ member=[],
+ i;
+ switch (type) {
+ case 'addTeamMembers':
+ accounts = item.attach.accounts;
+ for(i = 0;i=check[0]){
+ return dateFormat(time,"HH:mm");
+ }else if(time=check[1]){
+ return dateFormat(time,"MM-dd HH:mm");
+ }else{
+ return dateFormat(time,"yyyy-MM-dd HH:mm");
+ }
+ };
+ })(),
+ /**
+ * 时间戳转化为日期(用于左边面板)
+ * @return {string} 转化后的日期
+ */
+ transTime2 :(function(){
+ var getDayPoint = function(time){
+ time.setMinutes(0);
+ time.setSeconds(0);
+ time.setMilliseconds(0);
+ time.setHours(0);
+ var today = time.getTime();
+ time.setMonth(1);
+ time.setDate(1);
+ var yearDay = time.getTime();
+ return [today,yearDay];
+ };
+ return function(time){
+ var check = getDayPoint(new Date());
+ if (time>=check[0]){
+ return dateFormat(time,"HH:mm");
+ }else if(time>=check[0]-60*1000*60*24){
+ return "昨天";
+ }else if(time>=(check[0]-2*60*1000*60*24)){
+ return "前天";
+ }else if(time>=(check[0]-7*60*1000*60*24)){
+ return "星期"+dateFormat(time,"w");
+ }else if(time>=check[1]){
+ return dateFormat(time,"MM-dd");
+ }else{
+ return dateFormat(time,"yyyy-MM-dd");
+ }
+ };
+ })()
+};
+var _$encode = function(_map,_content){
+ _content = ''+_content;
+ if (!_map||!_content){
+ return _content||'';
+ }
+ return _content.replace(_map.r,function($1){
+ var _result = _map[!_map.i?$1.toLowerCase():$1];
+ return _result!=null?_result:$1;
+ });
+};
+/**
+ * 日期格式化
+ * @return string
+ */
+var dateFormat = (function(){
+ var _map = {i:!0,r:/\byyyy|yy|MM|cM|eM|M|dd|d|HH|H|mm|ms|ss|m|s|w|ct|et\b/g},
+ _12cc = ['上午','下午'],
+ _12ec = ['A.M.','P.M.'],
+ _week = ['日','一','二','三','四','五','六'],
+ _cmon = ['一','二','三','四','五','六','七','八','九','十','十一','十二'],
+ _emon = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sept','Oct','Nov','Dec'];
+ var _fmtnmb = function(_number){
+ _number = parseInt(_number,10)||0;
+ return (_number<10?'0':'')+_number;
+ };
+ var _fmtclc = function(_hour){
+ return _hour<12?0:1;
+ };
+ return function(_time,_format,_12time){
+ if (!_time||!_format){
+ return '';
+ }
+ _time = new Date(_time);
+ _map.yyyy = _time.getFullYear();
+ _map.yy = (''+_map.yyyy).substr(2);
+ _map.M = _time.getMonth()+1;
+ _map.MM = _fmtnmb(_map.M);
+ _map.eM = _emon[_map.M-1];
+ _map.cM = _cmon[_map.M-1];
+ _map.d = _time.getDate();
+ _map.dd = _fmtnmb(_map.d);
+ _map.H = _time.getHours();
+ _map.HH = _fmtnmb(_map.H);
+ _map.m = _time.getMinutes();
+ _map.mm = _fmtnmb(_map.m);
+ _map.s = _time.getSeconds();
+ _map.ss = _fmtnmb(_map.s);
+ _map.ms = _time.getMilliseconds();
+ _map.w = _week[_time.getDay()];
+ var _cc = _fmtclc(_map.H);
+ _map.ct = _12cc[_cc];
+ _map.et = _12ec[_cc];
+ if (!!_12time){
+ _map.H = _map.H%12;
+ }
+ return _$encode(_map,_format);
+ };
+})();
+
+module.exports = util;
\ No newline at end of file
diff --git a/src/js/index.js b/src/js/index.js
new file mode 100644
index 0000000..d3bc30e
--- /dev/null
+++ b/src/js/index.js
@@ -0,0 +1,20 @@
+/**
+ * ------------------------------------------------------------
+ * NIM_UI 云信web UI库
+ * ------------------------------------------------------------
+ */
+
+'use strict';
+
+var uiKit = {};
+
+/**
+ * list
+ */
+
+uiKit.SessionList = require("./list/sessions.js");
+uiKit.FriendList = require("./list/friends.js");
+uiKit.TeamList = require("./list/teams.js");
+
+
+module.exports = uiKit;
\ No newline at end of file
diff --git a/src/js/list/friends.js b/src/js/list/friends.js
new file mode 100644
index 0000000..c7e6422
--- /dev/null
+++ b/src/js/list/friends.js
@@ -0,0 +1,106 @@
+/**
+ * ------------------------------------------------------------
+ * FriendList 好友列表UI
+ * ------------------------------------------------------------
+ */
+
+'use strict';
+var util = require("../base/util.js");
+
+var ACCOUNT;
+
+/**
+ * 好友列表控件
+ * @param {Object} options 控件初始化参数
+ * @property {String||Node} parent 父节点
+ * @property {String} clazz 样式名称
+ * @property {Function} onclickitem 点击列表回调
+ * @property {Function} onclickavatar 点击列表头像回调
+ * @property {Object} data 消息数据 data.friends 好友数据 data.friends data.userinfo 用户信息
+ */
+var FriendList = function(options){
+ var parent = options.parent,
+ data = options.data,
+ cbClickList = options.onclickitem||function(account,type){console.log('account:'+account+'---type:'+type);},
+ cbClickPortrait = options.onclickavatar||function(account,type){console.log('account:'+account+'---type:'+type);};
+ ACCOUNT = data.account;
+ this._body = document.createElement('ul');
+ this._body.className = options.clazz||"m-panel" +" j-friend";
+
+ util.addEvent(this._body,'click',function(e){
+ var self = this,
+ evt = e||window.event,
+ account,
+ type,
+ target = evt.srcElement||evt.target;
+ while(self!==target){
+ if (target.tagName.toLowerCase() === "img") {
+ var item = target.parentNode;
+ account = item.getAttribute("data-account");
+ type = item.getAttribute("data-type");
+ cbClickPortrait(account,type);
+ return;
+ }else if(target.tagName.toLowerCase() === "li"){
+ account = target.getAttribute("data-account");
+ type = target.getAttribute("data-type");
+ util.removeClass(util.getNode(".j-friend li.active"),'active');
+ util.addClass(target,"active");
+ cbClickList(account,type);
+ return;
+ }
+ target = target.parentNode;
+ }
+ });
+ this.update(data);
+ if(!!parent){
+ this.inject(parent);
+ }
+};
+/** --------------------------public------------------------------ */
+
+/**
+ * 插入控件
+ * @param {Node|String} node 插入控件的节点
+ * @return {Void}
+ */
+FriendList.prototype.inject = function(node){
+ var injectNode = util.getNode(node);
+ injectNode.innerHTML = "";
+ injectNode.appendChild(this._body);
+};
+
+/**
+ * 更新视图
+ * @param {Object} data
+ * @return {Void}
+ */
+FriendList.prototype.update = function(data){
+ var html="",
+ list = data.friends;
+ for (var i = 0; i < list.length; i++) {
+ if (list[i].account !== ACCOUNT) {
+ html += ['',
+ '',
+ '',
+ '
',
+ '' + list[i].nick+'',
+ '
',
+ '
',
+ ''].join("");
+ }
+ }
+ this._body.innerHTML = html;
+};
+
+/**
+ * 控件销毁
+ * @return {void}
+ */
+FriendList.prototype.destory = function(){
+ //预留
+};
+
+
+
+
+module.exports = FriendList;
\ No newline at end of file
diff --git a/src/js/list/sessions.js b/src/js/list/sessions.js
new file mode 100644
index 0000000..c5f5873
--- /dev/null
+++ b/src/js/list/sessions.js
@@ -0,0 +1,203 @@
+/**
+ * ------------------------------------------------------------
+ * SesstionList 会话面板UI
+ * ------------------------------------------------------------
+ */
+
+'use strict';
+var util = require("../base/util.js");
+var ACCOUNT;
+
+/**
+ * 判断会话的对象
+ * @param {Object} msg 消息
+ * @return {String} 会话的对象
+ */
+function switchConversationUser(msg){
+ return msg.to === ACCOUNT ? msg.from : msg.to;
+}
+/**
+ * 会话列表控件
+ * @param {Object} options 控件初始化参数
+ * @property {String||Node} parent 父节点
+ * @property {String} clazz 样式名称
+ * @property {Function} onclickitem 点击列表回调
+ * @property {Function} onclickavatar 点击列表头像回调
+ * @property {Object} data 消息数据 data.msgs 消息数据 data.unreadmsgs 未读数据 data.unreadmsgs['iostest']={count:99} data.userinfo 用户信息 data.teamInfo 群信息
+ */
+var SessionList = function(options){
+ var parent = options.parent,
+ data = options.data,
+ cbClickList = options.onclickitem||function(account,type){console.log('account:'+account+'---type:'+type);},
+ cbClickPortrait = options.onclickavatar||function(account,type){console.log('account:'+account+'---type:'+type);};
+ ACCOUNT = data.account;
+ this._body = document.createElement('ul');
+ this._body.className = options.clazz||"m-panel" +" j-session";
+
+ util.addEvent(this._body,'click',function(e){
+ var self = this,
+ evt = e||window.event,
+ account,
+ type,
+ target = evt.srcElement||evt.target;
+ while(self!==target){
+ if (target.tagName.toLowerCase() === "img") {
+ var item = target.parentNode;
+ account = item.getAttribute("data-account");
+ type = item.getAttribute("data-type");
+ cbClickPortrait(account,type);
+ return;
+ }else if(target.tagName.toLowerCase() === "li"){
+ account = target.getAttribute("data-account");
+ type = target.getAttribute("data-type");
+ util.removeClass(util.getNode(".j-session li.active"),'active');
+ util.addClass(target,"active");
+ var countNode = target.querySelector('.count');
+ util.addClass(countNode,"hide");
+ countNode.innerHTML = 0;
+ cbClickList(account,type);
+ return;
+ }
+ target = target.parentNode;
+ }
+ });
+ this.update(data);
+ if(!!parent){
+ this.inject(parent);
+ }
+};
+/** --------------------------public------------------------------ */
+
+/**
+ * 插入控件
+ * @param {Node|String} node 插入控件的节点
+ * @return {Void}
+ */
+SessionList.prototype.inject = function(node){
+ var injectNode = util.getNode(node);
+ injectNode.innerHTML = "";
+ injectNode.appendChild(this._body);
+};
+
+/**
+ * 更新视图
+ * @param {Object} data
+ * @return {Void}
+ */
+SessionList.prototype.update = function(data){
+ var html = '',
+ msgs = data.msgs,
+ unreadMsg = data.unreadmsgs,
+ info = data.userinfo,
+ team = data.teamInfo,
+ msg,nick,type,avatar,time,who,
+ count,isShow;
+ if (msgs.length === 0) {
+ html += '暂无最近联系人哦
';
+ }else{
+ for (var i = 0;i 99 ? '99+' : unreadMsg[who].count;
+ }
+ isShow = count === '99+' || count > 0;
+ if (msg.scene === 'team') {
+ nick = team[who].name||who;
+ type = team[who].type||'normal';
+ avatar = "images/"+type+".png";
+ } else {
+ nick = info[who].nick;
+ avatar = util.getAvatar(info[who].avatar);
+ }
+ var str = ['',
+ '',
+ '',
+ '
',
+ '' + nick + '',
+ '' + util.transTime2(msg.time) + '',
+ '
',
+ '
',
+ '' + buildSessionMsg(msg,info,ACCOUNT) + '',
+ '' + count + '',
+ '
',
+ '
',
+ ''].join("");
+ html += str;
+ }
+ }
+ this._body.innerHTML = html;
+};
+
+/**
+ * 控件销毁
+ * @return {void}
+ */
+SessionList.prototype.destory = function(){
+ //预留
+};
+
+/**
+* 构造第一条消息,显示在最近联系人昵称的下面
+* @param msg:消息对象
+*/
+var buildSessionMsg = function(msg,info,account) {
+ var text = (msg.scene!=='p2p'?msg.fromNick+":":""), type = msg.type;
+ if (!/text|image|file|audio|video|geo|custom|notification/i.test(type)){
+ return '';
+ }
+ switch (type) {
+ case 'text':
+ text += util.safeHtml(msg.text);
+ text = util.buildEmoji(text);
+ break;
+ case 'image':
+ text += '[图片]';
+ break;
+ case 'file':
+ if (!/exe|bat/i.test(msg.file.ext)) {
+ text += '[文件]';
+ } else {
+ text += '[非法文件,已被本站拦截]';
+ }
+ break;
+ case 'audio':
+ text += '[语音]';
+ break;
+ case 'video':
+ text += '[视频]';
+ break;
+ case 'geo':
+ text += '[位置]';
+ break;
+ case 'custom':
+ var content = JSON.parse(msg.content);
+ if(content.type===1){
+ text += '[猜拳]';
+ }else if(content.type===2){
+ text +='[阅后即焚]';
+ }else if(content.type===3){
+ text +='[贴图]';
+ }else if(content.type===4){
+ text +='[白板]';
+ }else{
+ text += '[自定义消息]';
+ }
+ break;
+ case 'notification':
+ text = '['+util.transNotification(msg,info,account)+']';
+ break;
+ default:
+ text += '[未知消息类型]';
+ break;
+ }
+ return text;
+};
+
+
+
+
+module.exports = SessionList;
\ No newline at end of file
diff --git a/src/js/list/teams.js b/src/js/list/teams.js
new file mode 100644
index 0000000..5ea2ef5
--- /dev/null
+++ b/src/js/list/teams.js
@@ -0,0 +1,123 @@
+/**
+ * ------------------------------------------------------------
+ * TeamList 群组列表UI
+ * ------------------------------------------------------------
+ */
+
+'use strict';
+var util = require("../base/util.js");
+
+/**
+ * 群组列表控件
+ * @param {Object} options 控件初始化参数
+ * @property {String||Node} parent 父节点
+ * @property {String} clazz 样式名称
+ * @property {Function} onclickitem 点击列表回调
+ * @property {Function} onclickavatar 点击列表头像回调
+ * @property {Object} data 消息数据 data.teams 群组数据
+ */
+var TeamList = function(options){
+ var parent = options.parent,
+ data = options.data,
+ cbClickList = options.onclickitem||function(account,type){console.log('account:'+account+'---type:'+type);},
+ cbClickPortrait = options.onclickavatar||function(account,type){console.log('account:'+account+'---type:'+type);};
+
+ this._body = document.createElement('ul');
+ this._body.className = options.clazz||"m-panel" +" j-team";
+
+ util.addEvent(this._body,'click',function(e){
+ var self = this,
+ evt = e||window.event,
+ account,
+ type,
+ target = evt.srcElement||evt.target;
+ while(self!==target){
+ if (target.tagName.toLowerCase() === "img") {
+ var item = target.parentNode;
+ account = item.getAttribute("data-account");
+ type = item.getAttribute("data-type");
+ cbClickPortrait(account,type);
+ return;
+ }else if(target.tagName.toLowerCase() === "li"){
+ account = target.getAttribute("data-account");
+ type = target.getAttribute("data-type");
+ util.removeClass(util.getNode(".j-team li.active"),'active');
+ util.addClass(target,"active");
+ cbClickList(account,type);
+ return;
+ }
+ target = target.parentNode;
+ }
+ });
+ this.update(data);
+ if(!!parent){
+ this.inject(parent);
+ }
+};
+
+/** --------------------------public------------------------------ */
+
+/**
+ * 插入控件
+ * @param {Node|String} node 插入控件的节点
+ * @return {Void}
+ */
+TeamList.prototype.inject = function(node){
+ var injectNode = util.getNode(node);
+ injectNode.innerHTML = "";
+ injectNode.appendChild(this._body);
+};
+
+/**
+ * 更新视图
+ * @param {Object} data
+ * @return {Void}
+ */
+TeamList.prototype.update = function(data){
+ var tmp1 = '普通群
',
+ tmp2 = '高级群
',
+ flag1 = false,
+ flag2 = false,
+ html = '',
+ teams = data.teams;
+ if (teams && teams.length > 0) {
+ for (var i = 0, l = teams.length; i < l; ++i) {
+ if (teams[i].type === 'normal') {
+ flag1 = true;
+ tmp1 += '';
+ tmp1 += '
' + teams[i].name||teams[i].teamId + '
';
+ } else if (teams[i].type === 'advanced') {
+ flag2 = true;
+ tmp2 += '';
+ tmp2 += '
' + teams[i].name||teams[i].teamId + '
';
+ }
+ }
+ tmp1 += '
';
+ tmp2 += '
';
+ if (flag1 && flag2) {
+ html = tmp2 + tmp1;
+ } else if (flag1 && !flag2) {
+ html = tmp1;
+ } else if (!flag1 && flag2) {
+ html = tmp2;
+ } else {
+ html = '暂时还没有群哦
';
+ }
+ } else {
+ html = '暂时还没有群哦
';
+ }
+ this._body.innerHTML = html;
+};
+
+/**
+ * 控件销毁
+ * @return {void}
+ */
+TeamList.prototype.destory = function(){
+ //预留
+};
+
+
+
+
+module.exports = TeamList;
\ No newline at end of file
diff --git a/webpack.config.js b/webpack.config.js
new file mode 100644
index 0000000..c68a5b7
--- /dev/null
+++ b/webpack.config.js
@@ -0,0 +1,7 @@
+module.exports = {
+ output: {
+ filename: 'uiKit.js',
+ library: "NIMUIKit",
+ libraryTarget: "umd"
+ }
+}
\ No newline at end of file