Przeglądaj źródła

Merge branch 'feature/im2_ws' into 'develop'

移动端图片控件无法使用的bug修复

See merge request o2oa/o2oa!509
楼国栋 5 lat temu
rodzic
commit
a7e6a9331a

+ 20 - 2
o2web/source/x_component_IMV2/$Main/default/chat.html

@@ -1,3 +1,21 @@
-<div>
-  this is Chat !!!
+<!-- title -->
+<div class="chat-title" data-o2-element="chatTitleNode">
+  <span>{{$.convName}}</span>
+</div>
+<!-- 聊天内容 -->
+<div class="chat-content" data-o2-element="chatContentNode">
+</div>
+<!-- 聊天操作 -->
+<div class="chat-bottom-area" data-o2-element="chatBottomAreaNode">
+  <div class="chat-bottom-area-tool" data-o2-element="chatBottomAreaToolNode">
+    <img src="/x_component_IMV2/$Main/default/icons/icon-emoji.png" data-o2-element="chatBottomAreaToolEmojiNode" />
+  </div>
+  <div class="chat-bottom-area-textarea">
+    <textarea data-o2-element="chatBottomAreaTextareaNode" placeholder="输入消息内容"></textarea>
+  </div>
+  <div class="chat-bottom-area-send-space">
+    <div class="chat-bottom-area-send" data-o2-element="chatBottomAreaSendAreaNode">
+      <span class="chat-bottom-area-send-btn" data-o2-element="chatBottomAreaSendBtnNode" data-o2-events="click:sendMsg">发送</span>
+    </div>
+  </div>
 </div>
 </div>

+ 337 - 0
o2web/source/x_component_IMV2/$Main/default/chattest.html

@@ -0,0 +1,337 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <title>聊天</title>
+  <style>
+    body {
+      padding: 0;
+      margin: 0;
+      font-family: -apple-system;
+      font-family: "-apple-system", "Helvetica Neue", "Roboto", "Segoe UI", sans-serif;
+    }
+
+    .chat-title {
+      height: 50px;
+      width: 100%;
+      text-align: center;
+      padding-top: 15px;
+      padding-bottom: 15px;
+      background-color: #ffffff;
+      border-bottom: 1px solid #F1F1F1;
+    }
+
+    .chat-title span {
+      line-height: 50px;
+    }
+
+    .chat-content {
+      background-color: #ebebeb;
+      overflow: auto;
+      position: absolute;
+      bottom: 156px;
+      top: 85px;
+      left: 0px;
+      width: 100%;
+    }
+
+    .chat-bottom-area {
+      height: 155px;
+      overflow: hidden;
+      border-top: 1px solid #F1F1F1;
+      display: block;
+      position: absolute;
+      bottom: 0px;
+      background: #ffffff;
+      width: 100%;
+      z-index: 100;
+    }
+
+    .chat-bottom-area-tool {
+      position: relative;
+      padding: 0 8px;
+      height: 38px;
+      line-height: 38px;
+      font-size: 0;
+    }
+
+    .chat-bottom-area-tool img {
+      margin: 7px 10px;
+    }
+
+    .chat-bottom-area-textarea {
+      margin-left: 10px;
+    }
+
+    .chat-bottom-area-textarea textarea {
+      display: block;
+      width: 100%;
+      padding: 5px 0 0;
+      height: 68px;
+      line-height: 20px;
+      border: none;
+      overflow: auto;
+      resize: none;
+      background: 0 0;
+    }
+
+    .chat-bottom-area-send-space {
+      position: relative;
+      height: 46px;
+    }
+
+    .chat-bottom-area-send {
+      position: absolute;
+      right: 15px;
+      top: 3px;
+      height: 32px;
+      line-height: 32px;
+      cursor: pointer;
+    }
+
+    .chat-bottom-area-send-btn {
+      border-radius: 3px 0 0 3px;
+    }
+
+    .chat-bottom-area-send span {
+      display: inline-block;
+      vertical-align: top;
+      font-size: 14px;
+      line-height: 32px;
+      margin-left: 5px;
+      padding: 0 20px;
+      background-color: #5FB878;
+      color: #fff;
+      border-radius: 3px;
+    }
+
+
+    .chat-sender {
+      clear: both;
+      font-size: 80%;
+    }
+
+    .chat-sender div:nth-of-type(1) {
+      float: left;
+    }
+
+    .chat-sender div:nth-of-type(2) {
+      margin: 0 50px 2px 50px;
+      padding: 0px;
+      color: #848484;
+      font-size: 70%;
+      text-align: left;
+    }
+
+    .chat-sender div:nth-of-type(3) {
+      background-color: white;
+      /*float: left;*/
+      margin: 0 50px 10px 50px;
+      padding: 10px 10px 10px 10px;
+      border-radius: 7px;
+      text-indent: -12px;
+    }
+
+    .chat-receiver {
+      clear: both;
+      font-size: 80%;
+    }
+
+    .chat-receiver div:nth-of-type(1) {
+      float: right;
+    }
+
+    .chat-receiver div:nth-of-type(2) {
+      margin: 0px 50px 2px 50px;
+      padding: 0px;
+      color: #848484;
+      font-size: 70%;
+      text-align: right;
+    }
+
+    .chat-receiver div:nth-of-type(3) {
+      /*float:right;*/
+      background-color: #b2e281;
+      margin: 0px 50px 10px 50px;
+      padding: 10px 10px 10px 10px;
+      border-radius: 7px;
+    }
+
+    .chat-receiver div:first-child img,
+    .chat-sender div:first-child img {
+      width: 40px;
+      height: 40px;
+      /*border-radius: 10%;*/
+    }
+
+    .chat-left_triangle {
+      height: 0px;
+      width: 0px;
+      border-width: 6px;
+      border-style: solid;
+      border-color: transparent white transparent transparent;
+      position: relative;
+      left: -22px;
+      top: 3px;
+    }
+
+    .chat-right_triangle {
+      height: 0px;
+      width: 0px;
+      border-width: 6px;
+      border-style: solid;
+      border-color: transparent transparent transparent #b2e281;
+      position: relative;
+      right: -22px;
+      top: 3px;
+    }
+
+    .chat-notice {
+      clear: both;
+      font-size: 70%;
+      color: white;
+      text-align: center;
+      margin-top: 15px;
+      margin-bottom: 15px;
+    }
+
+    .chat-notice span {
+      background-color: #cecece;
+      line-height: 25px;
+      border-radius: 5px;
+      padding: 5px 10px;
+    }
+  </style>
+</head>
+
+<body>
+  <!-- title -->
+  <div class="chat-title">
+    <span>姓名或群名</span>
+  </div>
+  <div class="chat-content">
+    <!-- Left -->
+    <div class="chat-sender">
+      <div><img src="https://git.o2oa.net/uploads/-/system/project/avatar/20/logo_o2_1000_round.png?width=64"></div>
+      <div>阿奔 Ben</div>
+      <div>
+        <div class="chat-left_triangle"></div>
+        <span> 苹果增加三款配件的颜色选项</span>
+      </div>
+    </div>
+    <!-- Right -->
+    <div class="chat-receiver">
+      <div><img src="img/max.png"></div>
+      <div>好人·马克思</div>
+      <div>
+        <div class="chat-right_triangle"></div>
+        <span> 但是如果你正在再发新的APP跨平台项目,我建议你考虑一下Ionic2/Ionic3。 ionic2/Ionic3的架构使得“单一职责原则”得到了体现,组件、页面之间相互独立,有利于内聚和解耦。</span>
+      </div>
+    </div>
+    <!-- Right -->
+    <div class="chat-sender">
+      <div><img src="img/adam.jpg"></div>
+      <div>阿达姆 Adam</div>
+      <div>
+        <div class="chat-left_triangle"></div>
+        <span> 一款接近原生的Html5移动App开发框架</span>
+      </div>
+    </div>
+    <!-- Notice/Center -->
+    <div class="chat-notice">
+      <span>2017年12月10日 23:13</span>
+    </div>
+    <!-- Left -->
+    <div class="chat-sender">
+      <div><img src="img/perry.png" /></div>
+      <div>佩里 Perry</div>
+      <div>
+        <div class="chat-left_triangle"></div>
+        <span> Ionic遵循视图控制模式,通俗的理解和 Cocoa 触摸框架相似。在视图控制模式中,我们将界面的不同部分分为子视图或包含其他视图的子视图控制器。</span>
+      </div>
+    </div>
+    <!-- Left -->
+    <div class="chat-sender">
+      <div><img src="img/mike.png"></div>
+      <div>麦克</div>
+      <div>
+        <div class="chat-left_triangle"></div>
+        <span> 你可以用ionRefresher指令实现拉动刷新,并可以用ionInfiniteScroll指令实现无限滚动。</span>
+      </div>
+    </div>
+    <!-- Right -->
+    <div class="chat-receiver">
+      <div><img src="img/max.png"></div>
+      <div>好人·马克思</div>
+      <div>
+        <div class="chat-right_triangle"></div>
+        <span> 最后但并非最不重要的是</span>
+      </div>
+    </div>
+    <!-- Notice/Center -->
+    <div class="chat-notice">
+      <span>你被群主移除群聊</span>
+    </div>
+    <!-- Left -->
+    <div class="chat-sender">
+      <div><img src="img/mike.png"></div>
+      <div>麦克</div>
+      <div>
+        <div class="chat-left_triangle"></div>
+        <span> 你可以用ionRefresher指令实现拉动刷新,并可以用ionInfiniteScroll指令实现无限滚动。</span>
+      </div>
+    </div>
+    <!-- Right -->
+    <div class="chat-receiver">
+      <div><img src="img/max.png"></div>
+      <div>好人·马克思</div>
+      <div>
+        <div class="chat-right_triangle"></div>
+        <span> 最后但并非最不重要的是</span>
+      </div>
+    </div>
+    <!-- Notice/Center -->
+    <div class="chat-notice">
+      <span>你被群主移除群聊</span>
+    </div>
+    <!-- Left -->
+    <div class="chat-sender">
+      <div><img src="img/mike.png"></div>
+      <div>麦克</div>
+      <div>
+        <div class="chat-left_triangle"></div>
+        <span> 你可以用ionRefresher指令实现拉动刷新,并可以用ionInfiniteScroll指令实现无限滚动。</span>
+      </div>
+    </div>
+    <!-- Right -->
+    <div class="chat-receiver">
+      <div><img src="img/max.png"></div>
+      <div>好人·马克思</div>
+      <div>
+        <div class="chat-right_triangle"></div>
+        <span> 最后但并非最不重要的是</span>
+      </div>
+    </div>
+    <!-- Notice/Center -->
+    <div class="chat-notice">
+      <span>你被群主移除群聊</span>
+    </div>
+  </div>
+
+
+  <div class="chat-bottom-area">
+    <div class="chat-bottom-area-tool">
+      <img src="./icons/icon-emoji.png" />
+    </div>
+    <div class="chat-bottom-area-textarea"><textarea></textarea></div>
+    <div class="chat-bottom-area-send-space">
+      <div class="chat-bottom-area-send">
+        <span class="chat-bottom-area-send-btn">发送</span>
+      </div>
+    </div>
+  </div>
+</body>
+
+</html>

BIN
o2web/source/x_component_IMV2/$Main/default/icons/icon-emoji.png


+ 2 - 2
o2web/source/x_component_IMV2/$Main/default/im.html

@@ -1,8 +1,8 @@
-<div class="o2_im_out">
+<div class="o2_im_out" data-o2-element="o2ImMainNode">
   <div class="o2_im_chat_list">
   <div class="o2_im_chat_list">
     <!--top-->
     <!--top-->
     <div class="o2_im_chat_list_top">
     <div class="o2_im_chat_list_top">
-      <div class="add"></div>
+      <div class="add" data-o2-element="o2ImConvCreateNode" data-o2-events="click:tapCreateSingleConv"></div>
       <div class="search_out">
       <div class="search_out">
         <div title="搜索" class="search_icon"></div>
         <div title="搜索" class="search_icon"></div>
         <div class="search_input_out">
         <div class="search_input_out">

+ 190 - 1
o2web/source/x_component_IMV2/$Main/default/style.css

@@ -152,4 +152,193 @@
     overflow: hidden; 
     overflow: hidden; 
     background-color: rgb(255, 255, 255); 
     background-color: rgb(255, 255, 255); 
     opacity: 1;
     opacity: 1;
-}
+    display: flex;
+    display: -webkit-box;
+    display: -webkit-flex;
+    flex-direction: column;
+    -ms-flex-direction: column;
+}
+
+
+/* 聊天界面 */
+
+.chat-title {
+    height: 30px;
+    text-align: center;
+    padding-top: 15px;
+    padding-bottom: 15px;
+    background-color: #ffffff;
+    border-bottom: 1px solid #F1F1F1;
+  }
+
+  .chat-title span {
+    line-height: 30px;
+  }
+
+  .chat-content {
+    background-color: #ebebeb;
+    overflow: auto;
+    flex:1;
+  }
+
+  .chat-bottom-area {
+    height: 155px;
+    overflow: hidden;
+    border-top: 1px solid #F1F1F1;
+    background: #ffffff;
+  }
+
+  .chat-bottom-area-tool {
+    position: relative;
+    padding: 0 8px;
+    height: 38px;
+    line-height: 38px;
+    font-size: 0;
+  }
+
+  .chat-bottom-area-tool img {
+    margin: 7px 10px;
+  }
+
+  .chat-bottom-area-textarea {
+    margin-left: 10px;
+  }
+
+  .chat-bottom-area-textarea textarea {
+    display: block;
+    width: 100%;
+    padding: 5px 0 0;
+    height: 68px;
+    line-height: 20px;
+    border: none;
+    overflow: auto;
+    resize: none;
+    background: 0 0;
+  }
+
+  .chat-bottom-area-send-space {
+    position: relative;
+    height: 46px;
+  }
+
+  .chat-bottom-area-send {
+    position: absolute;
+    right: 15px;
+    top: 3px;
+    height: 32px;
+    line-height: 32px;
+    cursor: pointer;
+  }
+
+  .chat-bottom-area-send-btn {
+    border-radius: 3px 0 0 3px;
+  }
+
+  .chat-bottom-area-send span {
+    display: inline-block;
+    vertical-align: top;
+    font-size: 14px;
+    line-height: 32px;
+    margin-left: 5px;
+    padding: 0 20px;
+    background-color: #5FB878;
+    color: #fff;
+    border-radius: 3px;
+  }
+
+
+  .chat-sender {
+    clear: both;
+    /* font-size: 80%; */
+  }
+
+  .chat-sender div:nth-of-type(1) {
+    float: left;
+  }
+
+  .chat-sender div:nth-of-type(2) {
+    margin: 0 50px 2px 50px;
+    padding: 0px;
+    color: #848484;
+    /* font-size: 70%; */
+    text-align: left;
+  }
+
+  .chat-sender div:nth-of-type(3) {
+    background-color: white;
+    /*float: left;*/
+    margin: 0 50px 10px 50px;
+    padding: 10px 10px 10px 10px;
+    border-radius: 7px;
+    text-indent: -12px;
+  }
+
+  .chat-receiver {
+    clear: both;
+    /* font-size: 80%; */
+  }
+
+  .chat-receiver div:nth-of-type(1) {
+    float: right;
+  }
+
+  .chat-receiver div:nth-of-type(2) {
+    margin: 0px 50px 2px 50px;
+    padding: 0px;
+    color: #848484;
+    /* font-size: 70%; */
+    text-align: right;
+  }
+
+  .chat-receiver div:nth-of-type(3) {
+    /*float:right;*/
+    background-color: #b2e281;
+    margin: 0px 50px 10px 50px;
+    padding: 10px 10px 10px 10px;
+    border-radius: 7px;
+  }
+
+  .chat-receiver div:first-child img,
+  .chat-sender div:first-child img {
+    width: 40px;
+    height: 40px;
+    /*border-radius: 10%;*/
+  }
+
+  .chat-left_triangle {
+    height: 0px;
+    width: 0px;
+    border-width: 6px;
+    border-style: solid;
+    border-color: transparent white transparent transparent;
+    position: relative;
+    left: -22px;
+    top: 3px;
+  }
+
+  .chat-right_triangle {
+    height: 0px;
+    width: 0px;
+    border-width: 6px;
+    border-style: solid;
+    border-color: transparent transparent transparent #b2e281;
+    position: relative;
+    right: -22px;
+    top: 3px;
+  }
+
+  .chat-notice {
+    clear: both;
+    font-size: 70%;
+    color: white;
+    text-align: center;
+    margin-top: 15px;
+    margin-bottom: 15px;
+  }
+
+  .chat-notice span {
+    background-color: #cecece;
+    line-height: 25px;
+    border-radius: 5px;
+    padding: 5px 10px;
+  }

+ 373 - 47
o2web/source/x_component_IMV2/Main.js

@@ -1,3 +1,6 @@
+MWF.require("MWF.widget.UUID", null, false);
+MWF.xDesktop.requireApp("Template", "MForm", null, false);
+MWF.xDesktop.requireApp("Template", "MPopupForm", null, false);
 MWF.xApplication.IMV2.options.multitask = true;
 MWF.xApplication.IMV2.options.multitask = true;
 MWF.xApplication.IMV2.Main = new Class({
 MWF.xApplication.IMV2.Main = new Class({
 	Extends: MWF.xApplication.Common.Main,
 	Extends: MWF.xApplication.Common.Main,
@@ -8,20 +11,25 @@ MWF.xApplication.IMV2.Main = new Class({
 		"name": "IMV2",
 		"name": "IMV2",
 		"mvcStyle": "style.css",
 		"mvcStyle": "style.css",
 		"icon": "icon.png",
 		"icon": "icon.png",
-		"width": "1200",
-		"height": "700",
+		"width": "1024",
+		"height": "768",
 		"isResize": true,
 		"isResize": true,
 		"isMax": true,
 		"isMax": true,
 		"title": MWF.xApplication.IMV2.LP.title
 		"title": MWF.xApplication.IMV2.LP.title
 	},
 	},
 	onQueryLoad: function () {
 	onQueryLoad: function () {
 		this.lp = MWF.xApplication.IMV2.LP;
 		this.lp = MWF.xApplication.IMV2.LP;
+		this.app = this;
 		this.conversationList = [];
 		this.conversationList = [];
+		this.conversationNodeItemList = [];
+		this.conversationId = "";
 	},
 	},
 	loadApplication: function (callback) {
 	loadApplication: function (callback) {
 		var url = this.path + this.options.style + "/im.html";
 		var url = this.path + this.options.style + "/im.html";
 		this.content.loadHtml(url, { "bind": { "lp": this.lp, "data": {} }, "module": this }, function () {
 		this.content.loadHtml(url, { "bind": { "lp": this.lp, "data": {} }, "module": this }, function () {
+			this.app.content = this.o2ImMainNode;
 			//获取会话列表
 			//获取会话列表
+			this.conversationNodeItemList = [];
 			o2.Actions.load("x_message_assemble_communicate").ImAction.myConversationList(function (json) {
 			o2.Actions.load("x_message_assemble_communicate").ImAction.myConversationList(function (json) {
 				if (json.data && json.data instanceof Array) {
 				if (json.data && json.data instanceof Array) {
 					this.conversationList = json.data;
 					this.conversationList = json.data;
@@ -35,61 +43,196 @@ MWF.xApplication.IMV2.Main = new Class({
 	loadConversationList: function (list) {
 	loadConversationList: function (list) {
 		for (var i = 0; i < list.length; i++) {
 		for (var i = 0; i < list.length; i++) {
 			var chat = list[i];
 			var chat = list[i];
-			var url = this.path + this.options.style + "/conversationItem.html";
-			var avatarDefault = this._getIcon();
-			var data = {
-				"id": chat.id,
-				"avatarUrl": avatarDefault,
-				"title": chat.title,
-				"time": "",
-				"lastMessage": ""
-			};
-			var distinguishedName = layout.session.user.distinguishedName;
-			if (chat.type && chat.type === "single") {
-				var chatPerson = "";
-				if (chat.personList && chat.personList instanceof Array) {
-					for (var i = 0; i < chat.personList.length; i++) {
-						var person = chat.personList[i];
-						if (person !== distinguishedName) {
-							chatPerson = person;
-						}
-					}
-				}
-				data.avatarUrl = this._getIcon(chatPerson);
-				var name = chatPerson;
-				if (chatPerson.indexOf("@") != -1) {
-					name = name.substring(0, chatPerson.indexOf("@"));
-				}
-				data.title = name;
-			}
-			if (chat.lastMessage) {
-				//todo 其它消息类型
-				var mBody = JSON.parse(chat.lastMessage.body);
-				data.lastMessage = mBody.body;
-				if (chat.lastMessage.createTime) {
-					var time = this._friendlyTime(o2.common.toDate(chat.lastMessage.createTime));
-					data.time = time;
-				}
-			}
-			this.chatItemListNode.loadHtml(url, { "bind": data, "module": this }, function (html) {
-				//bind event
-
-				console.log(html);
-			}.bind(this));
+			var itemNode = this._createConvItemNode(chat);
+			this.conversationNodeItemList.push(itemNode);
 		}
 		}
+		if (list.length > 0) {
+			this.tapConv(list[0]);
+		}
+		
 		console.log("结束");
 		console.log("结束");
 	},
 	},
+	//分页获取会话的消息列表数据
+	loadMsgListByConvId: function (page, size, convId) {
+		var data = { "conversationId": convId };
+		o2.Actions.load("x_message_assemble_communicate").ImAction.msgListByPaging(page, size, data, function (json) {
+			var list = json.data;
+			for (var i = 0; i < list.length; i++) {
+				this._buildMsgNode(list[i]);
+			}
+			console.log("聊天信息添加结束!");
+		}.bind(this), function (error) {
+			console.log(error);
+		}.bind(this), false);
+	},
 	//点击
 	//点击
-	tapConv: function (e) {
+	tapConv: function (conv) {
 		console.log("clickConversationvvvvvv");
 		console.log("clickConversationvvvvvv");
-		console.log(e);
+		this._setCheckNode(conv);
 		var url = this.path + this.options.style + "/chat.html";
 		var url = this.path + this.options.style + "/chat.html";
-		this.chatNode.loadHtml(url, { "bind": {}, "module": this }, function () {
+		var data = { "convName": conv.title };
+		this.conversationId = conv.id;
+		this.chatNode.empty();
+		this.chatNode.loadHtml(url, { "bind": data, "module": this }, function () {
+			//获取聊天信息
+			this.loadMsgListByConvId(1, 20, conv.id);
+			console.log("开始滚动!!!");
+			var scrollFx = new Fx.Scroll(this.chatContentNode);
+			scrollFx.toBottom();
 		}.bind(this));
 		}.bind(this));
 	},
 	},
+	//点击发送消息
+	sendMsg: function () {
+		console.log("click send Msg btn................");
+		var text = this.chatBottomAreaTextareaNode.value;
+		console.log(text);
+		if (text) {
+			this.chatBottomAreaTextareaNode.value = "";
+			this._newAndSendTextMsg(text);
+			var scrollFx = new Fx.Scroll(this.chatContentNode);
+			scrollFx.toBottom();
+		} else {
+			console.log("没有消息内容!");
+		}
+	},
+	tapCreateSingleConv: function () {
+		console.log("click tapCreateSingleConv................");
+		var form = new MWF.xApplication.IMV2.SingleForm(this, {}, {}, { app: this.app });
+		form.create()
+	},
 
 
 
 
-
+	/**
+	 * 	创建会话
+	 * @param {*} persons 人员列表
+	 * @param {*} cType 会话类型 "single" "group"
+	 */
+	newConversation: function (persons, cType) {
+		var conv = {
+			type: cType,
+			personList: persons,
+		};
+		var _self = this;
+		o2.Actions.load("x_message_assemble_communicate").ImAction.create(conv, function (json) {
+			var newConv = json.data;
+			console.log(newConv);
+			var isOld = false;
+			for (var i = 0; i < _self.conversationNodeItemList.length; i++) {
+				var c = _self.conversationNodeItemList[i];
+				if (newConv.id  == c.id) {
+					isOld = true;
+					_self.tapConv(c);
+				}
+			}
+			if(!isOld) {
+				var itemNode = _self._createConvItemNode(newConv);
+				_self.conversationNodeItemList.push(itemNode);
+				_self.tapConv(newConv);
+			}
+			console.log("创建会话 结束。。。。。");
+		}.bind(this), function (error) {
+			console.log(error);
+		}.bind(this))
+	},
+	_createConvItemNode: function (conv) {
+		return new MWF.xApplication.IMV2.ConversationItem(conv, this);
+	},
+	_setCheckNode: function (conv) {
+		for (var i = 0; i < this.conversationNodeItemList.length; i++) {
+			var item = this.conversationNodeItemList[i];
+			if (item.data.id == conv.id) {
+				item.addCheckClass();
+			} else {
+				item.removeCheckClass();
+			}
+		}
+	},
+	//创建文本消息 并发送
+	_newAndSendTextMsg: function (text) {
+		var distinguishedName = layout.session.user.distinguishedName;
+		var time = this._currentTime();
+		var body = { "body": text };
+		var bodyJson = JSON.stringify(body);
+		var uuid = (new MWF.widget.UUID).toString();
+		var textMessage = {
+			"id": uuid,
+			"conversationId": this.conversationId,
+			"body": bodyJson,
+			"createPerson": distinguishedName,
+			"createTime": time,
+			"sendStatus": 1
+		};
+		o2.Actions.load("x_message_assemble_communicate").ImAction.msgCreate(textMessage,
+			function (json) {
+				//data = json.data;
+				console.log("消息发送成功!");
+			}.bind(this),
+			function (error) {
+				console.log(error);
+			}.bind(this));
+		this._buildSender(body, distinguishedName, false);
+		for (var i = 0; i < this.conversationNodeItemList.length; i++) {
+			var node = this.conversationNodeItemList[i];
+			if (node.data.id == this.conversationId) {
+				node.refreshLastMsg(textMessage);
+			}
+		}
+	},
+	//创建消息html节点
+	_buildMsgNode: function (msg) {
+		var createPerson = msg.createPerson;
+		var jsonbody = msg.body;
+		var body = JSON.parse(jsonbody);//todo 目前只有一种text类型
+		var distinguishedName = layout.session.user.distinguishedName;
+		if (createPerson != distinguishedName) {
+			this._buildReceiver(body, createPerson, true);
+		} else {
+			this._buildSender(body, createPerson, true);
+		}
+	},
+	/**
+	 * 消息发送体
+	 * @param  msgBody 消息体
+	 * @param createPerson 消息人员
+	 * @param isTop 是否放在顶部
+	 */
+	_buildSender: function (msgBody, createPerson, isTop) {
+		var receiverBodyNode = new Element("div", { "class": "chat-sender" }).inject(this.chatContentNode, isTop ? "top" : "bottom");
+		var avatarNode = new Element("div").inject(receiverBodyNode);
+		var avatarUrl = this._getIcon(createPerson);
+		var name = createPerson;
+		if (createPerson.indexOf("@") != -1) {
+			name = name.substring(0, createPerson.indexOf("@"));
+		}
+		var avatarImg = new Element("img", { "src": avatarUrl }).inject(avatarNode);
+		var nameNode = new Element("div", { "text": name }).inject(receiverBodyNode);
+		var lastNode = new Element("div").inject(receiverBodyNode);
+		var lastFirstNode = new Element("div", { "class": "chat-left_triangle" }).inject(lastNode);
+		//text
+		var lastSecNode = new Element("span", { "text": msgBody.body }).inject(lastNode);
+	},
+	/**
+	 * 消息接收体
+	 * @param  msgBody 
+	 * @param createPerson 消息人员
+	 * @param isTop 是否放在顶部
+	 */
+	_buildReceiver: function (msgBody, createPerson, isTop) {
+		var receiverBodyNode = new Element("div", { "class": "chat-receiver" }).inject(this.chatContentNode, isTop ? "top" : "bottom");
+		var avatarNode = new Element("div").inject(receiverBodyNode);
+		var avatarUrl = this._getIcon(createPerson);
+		var name = createPerson;
+		if (createPerson.indexOf("@") != -1) {
+			name = name.substring(0, createPerson.indexOf("@"));
+		}
+		var avatarImg = new Element("img", { "src": avatarUrl }).inject(avatarNode);
+		var nameNode = new Element("div", { "text": name }).inject(receiverBodyNode);
+		var lastNode = new Element("div").inject(receiverBodyNode);
+		var lastFirstNode = new Element("div", { "class": "chat-right_triangle" }).inject(lastNode);
+		//text
+		var lastSecNode = new Element("span", { "text": msgBody.body }).inject(lastNode);
+	},
+	//用户头像
 	_getIcon: function (id) {
 	_getIcon: function (id) {
 		var orgAction = MWF.Actions.get("x_organization_assemble_control")
 		var orgAction = MWF.Actions.get("x_organization_assemble_control")
 		var url = (id) ? orgAction.getPersonIcon(id) : "/x_component_IMV2/$Main/default/icons/group.png";
 		var url = (id) ? orgAction.getPersonIcon(id) : "/x_component_IMV2/$Main/default/icons/group.png";
@@ -153,7 +296,190 @@ MWF.xApplication.IMV2.Main = new Class({
 		month = (month.toString().length == 1) ? ("0" + month) : month;
 		month = (month.toString().length == 1) ? ("0" + month) : month;
 		day = (day.toString().length == 1) ? ("0" + day) : day;
 		day = (day.toString().length == 1) ? ("0" + day) : day;
 		return date.getFullYear() + '-' + month + '-' + day;
 		return date.getFullYear() + '-' + month + '-' + day;
+	},
+	_currentTime: function () {
+		var today = new Date();
+		var year = today.getFullYear(); //得到年份
+		var month = today.getMonth();//得到月份
+		var date = today.getDate();//得到日期
+		var hour = today.getHours();//得到小时
+		var minu = today.getMinutes();//得到分钟
+		var sec = today.getSeconds();//得到秒
+		month = month + 1;
+		if (month < 10) month = "0" + month;
+		if (date < 10) date = "0" + date;
+		if (hour < 10) hour = "0" + hour;
+		if (minu < 10) minu = "0" + minu;
+		if (sec < 10) sec = "0" + sec;
+		return year + "-" + month + "-" + date + " " + hour + ":" + minu + ":" + sec;
 	}
 	}
 
 
 
 
 });
 });
+
+//会话对象
+MWF.xApplication.IMV2.ConversationItem = new Class({
+	initialize: function (data, main) {
+		this.data = data;
+		this.main = main;
+		this.container = this.main.chatItemListNode;
+
+		this.load();
+	},
+	load: function () {
+		var avatarDefault = this.main._getIcon();
+		var convData = {
+			"id": this.data.id,
+			"avatarUrl": avatarDefault,
+			"title": this.data.title,
+			"time": "",
+			"lastMessage": ""
+		};
+		var distinguishedName = layout.session.user.distinguishedName;
+		if (this.data.type && this.data.type === "single") {
+			var chatPerson = "";
+			if (this.data.personList && this.data.personList instanceof Array) {
+				for (var j = 0; j < this.data.personList.length; j++) {
+					var person = this.data.personList[j];
+					if (person !== distinguishedName) {
+						chatPerson = person;
+					}
+				}
+			}
+			convData.avatarUrl = this.main._getIcon(chatPerson);
+			var name = chatPerson;
+			if (chatPerson.indexOf("@") != -1) {
+				name = name.substring(0, chatPerson.indexOf("@"));
+			}
+			convData.title = name;
+		}
+		if (this.data.lastMessage) {
+			//todo 其它消息类型
+			var mBody = JSON.parse(this.data.lastMessage.body);
+			convData.lastMessage = mBody.body;
+			if (this.data.lastMessage.createTime) {
+				var time = this.main._friendlyTime(o2.common.toDate(this.data.lastMessage.createTime));
+				convData.time = time;
+			}
+		}
+		this.node = new Element("div", { "class": "item" }).inject(this.container);
+		this.nodeBaseItem = new Element("div", { "class": "base" }).inject(this.node);
+		var avatarNode = new Element("div", { "class": "avatar" }).inject(this.nodeBaseItem);
+		new Element("img", { "src": convData.avatarUrl, "class": "img" }).inject(avatarNode);
+		var bodyNode = new Element("div", { "class": "body" }).inject(this.nodeBaseItem);
+		var bodyUpNode = new Element("div", { "class": "body_up" }).inject(bodyNode);
+		new Element("div", { "class": "body_title", "text": convData.title }).inject(bodyUpNode);
+		this.messageTimeNode = new Element("div", { "class": "body_time", "text": convData.time }).inject(bodyUpNode);
+		this.lastMessageNode = new Element("div", { "class": "body_down", "text": convData.lastMessage }).inject(bodyNode);
+		var _self = this;
+		this.node.addEvents({
+			"click": function () {
+				_self.main.tapConv(_self.data);
+			}
+		});
+	},
+	/**
+	 * {
+			"id": uuid,
+			"conversationId": this.conversationId,
+			"body": bodyJson,
+			"createPerson": distinguishedName,
+			"createTime": time,
+			"sendStatus": 1
+		};
+	 * 刷新会话列表的最后消息内容 
+	 * @param {*} lastMessage 
+	 */
+	refreshLastMsg: function(lastMessage) {
+		//目前是text 类型的消息
+		var jsonbody = lastMessage.body;
+		var body = JSON.parse(jsonbody);//todo 目前只有一种text类型
+		if(this.lastMessageNode) {
+			this.lastMessageNode.set('text', body.body);
+		}
+		var time = this.main._friendlyTime(o2.common.toDate(lastMessage.createTime));
+		if(this.messageTimeNode) {
+			this.messageTimeNode.set("text", time);
+		}
+	},
+	addCheckClass: function () {
+		if (this.nodeBaseItem) {
+			if (!this.nodeBaseItem.hasClass("check")) {
+				this.nodeBaseItem.addClass("check");
+			}
+		}
+	},
+	removeCheckClass: function () {
+		if (this.nodeBaseItem) {
+			if (this.nodeBaseItem.hasClass("check")) {
+				this.nodeBaseItem.removeClass("check");
+			}
+		}
+	}
+
+});
+
+//弹出窗 表单 单聊创建的form
+MWF.xApplication.IMV2.SingleForm = new Class({
+	Extends: MPopupForm,
+	Implements: [Options, Events],
+	options: {
+		"style": "minder",
+		"width": 700,
+		//"height": 300,
+		"height": "200",
+		"hasTop": true,
+		"hasIcon": false,
+		"draggable": true,
+		"title": "创建单聊"
+	},
+	_createTableContent: function () {
+		var html = "<table width='100%' bordr='0' cellpadding='7' cellspacing='0' styles='formTable' style='margin-top: 20px; '>" +
+			"<tr><td styles='formTableTitle' lable='person' width='25%'></td>" +
+			"    <td styles='formTableValue14' item='person' colspan='3'></td></tr>" +
+			"</table>";
+		this.formTableArea.set("html", html);
+		var me = layout.session.user.distinguishedName;
+		var exclude = [];
+		if (me) {
+			exclude = [me];
+		}
+		this.form = new MForm(this.formTableArea, this.data || {}, {
+			isEdited: true,
+			style: "minder",
+			hasColon: true,
+			itemTemplate: {
+				person: { text: "选择人员", type: "org", orgType: "person", notEmpty: true, exclude: exclude },
+			}
+		}, this.app);
+		this.form.load();
+
+	},
+	_createBottomContent: function () {
+		if (this.isNew || this.isEdited) {
+			this.okActionNode = new Element("button.inputOkButton", {
+				"styles": this.css.inputOkButton,
+				"text": "确定"
+			}).inject(this.formBottomNode);
+			this.okActionNode.addEvent("click", function (e) {
+				this.save(e);
+			}.bind(this));
+		}
+		this.cancelActionNode = new Element("button.inputCancelButton", {
+			"styles": (this.isEdited || this.isNew || this.getEditPermission()) ? this.css.inputCancelButton : this.css.inputCancelButton_long,
+			"text": "关闭"
+		}).inject(this.formBottomNode);
+		this.cancelActionNode.addEvent("click", function (e) {
+			this.close(e);
+		}.bind(this));
+
+	},
+	save: function () {
+		var data = this.form.getResult(true, null, true, false, true);
+		if (data) {
+			console.log(data);
+			this.app.newConversation(data.person, "single");
+			this.close();
+		}
+	}
+});

+ 6 - 1
o2web/source/x_component_process_Xform/ImageClipper.js

@@ -66,8 +66,13 @@ MWF.xApplication.process.Xform.ImageClipper = MWF.APPImageClipper =  new Class({
                 });
                 });
                 if( window.o2android && window.o2android.uploadImage2FileStorage ){
                 if( window.o2android && window.o2android.uploadImage2FileStorage ){
                     window.o2android.uploadImage2FileStorage(jsonString)
                     window.o2android.uploadImage2FileStorage(jsonString)
-                }else{
+                }else if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.uploadImage2FileStorage){
                     window.webkit.messageHandlers.uploadImage2FileStorage.postMessage(jsonString);
                     window.webkit.messageHandlers.uploadImage2FileStorage.postMessage(jsonString);
+                }else {
+                    this.selectImage( d, function(data){
+                        this.setData( data ? data.id : "" );
+                        this.validation();
+                    }.bind(this));
                 }
                 }
             }else{
             }else{
                 this.selectImage( d, function(data){
                 this.selectImage( d, function(data){

+ 102 - 51
o2web/source/x_component_process_Xform/widget/ImageClipper.js

@@ -29,8 +29,12 @@ MWF.xApplication.process.Xform.widget.ImageClipper = new Class({
         var height = "510";
         var height = "510";
         width = width.toInt();
         width = width.toInt();
         height = height.toInt();
         height = height.toInt();
-
-        var size = this.app.content.getSize();
+        
+        var outBody = this.app.content;
+        if (layout.mobile){
+            outBody = $(document.body);
+        }
+        var size = outBody.getSize();
         var x = (size.x-width)/2;
         var x = (size.x-width)/2;
         var y = (size.y-height)/2;
         var y = (size.y-height)/2;
         if (x<0) x = 0;
         if (x<0) x = 0;
@@ -39,62 +43,109 @@ MWF.xApplication.process.Xform.widget.ImageClipper = new Class({
             x = 20;
             x = 20;
             y = 0;
             y = 0;
         }
         }
-
         var _self = this;
         var _self = this;
-        MWF.require("MWF.xDesktop.Dialog", function() {
-            var dlg = new MWF.xDesktop.Dialog({
-                "title": this.options.title || "Select Image",
-                "style": options.style || "image",
-                "top": y,
-                "left": x - 20,
-                "fromTop": y,
-                "fromLeft": x - 20,
-                "width": width,
-                "height": height,
-                "html": "<div></div>",
-                "maskNode": this.app.content,
-                "container": this.app.content,
-                "buttonList": [
-                    {
-                        "text": MWF.LP.process.button.ok,
-                        "action": function () {
-                            if( _self.image.getResizedImage() ){
-                                _self.image.uploadImage( function( json ){
-                                    _self.imageSrc = MWF.xDesktop.getImageSrc( json.id );
-                                    _self.imageId = json.id;
+        if (layout.mobile) { //移动端直接选择图片
+            this.fileNode = new Element("input.file", {
+				"type" : "file",
+                "accept":" .jpeg, .jpg, .png",
+                "multiple": false,
+				"styles" : {"display":"none"}
+            }).inject(outBody);
+			this.fileNode.addEvent("change", function(event){
+				var file=this.fileNode.files[0];
+                if(file) {
+                    this.uploadImageForH5(file);
+                }
+                this.fileNode.destroy();
+                this.fileNode = null;
+            }.bind(this));
+            setTimeout( function(){ this.fileNode.click(); }.bind(this), 100);
+        }else {
+            MWF.require("MWF.xDesktop.Dialog", function() {
+                var dlg = new MWF.xDesktop.Dialog({
+                    "title": this.options.title || "Select Image",
+                    "style": options.style || "image",
+                    "top": y,
+                    "left": x - 20,
+                    "fromTop": y,
+                    "fromLeft": x - 20,
+                    "width": width,
+                    "height": height,
+                    "html": "<div></div>",
+                    "maskNode": outBody,
+                    "container": outBody,
+                    "buttonList": [
+                        {
+                            "text": MWF.LP.process.button.ok,
+                            "action": function () {
+                                if( _self.image.getResizedImage() ){
+                                    _self.image.uploadImage( function( json ){
+                                        _self.imageSrc = MWF.xDesktop.getImageSrc( json.id );
+                                        _self.imageId = json.id;
+                                        _self.fireEvent("change");
+                                        this.close();
+                                    }.bind(this));
+                                }else{
+                                    _self.imageSrc = "";
+                                    _self.imageId = "";
                                     _self.fireEvent("change");
                                     _self.fireEvent("change");
                                     this.close();
                                     this.close();
-                                }.bind(this));
-                            }else{
-                                _self.imageSrc = "";
-                                _self.imageId = "";
-                                _self.fireEvent("change");
+                                }
+                            }
+                        },
+                        {
+                            "text": MWF.LP.process.button.cancel,
+                            "action": function () {
                                 this.close();
                                 this.close();
                             }
                             }
                         }
                         }
-                    },
-                    {
-                        "text": MWF.LP.process.button.cancel,
-                        "action": function () {
-                            this.close();
-                        }
-                    }
-                ]
-            });
-            dlg.show();
+                    ]
+                });
+                dlg.show();
+    
+                this.image = new MWF.widget.ImageClipper(dlg.content.getFirst(), {
+                    "aspectRatio": this.options.aspectRatio,
+                    "description" : this.options.description,
+                    "imageUrl" : this.options.imageUrl,
+                    "resultMaxSize" : this.options.resultMaxSize,
+                    "reference" : this.options.reference,
+                    "referenceType": this.options.referenceType,
+                    "resetEnable" : true
+                });
+                this.image.load(this.data);
+            }.bind(this));
+        }
 
 
-            this.image = new MWF.widget.ImageClipper(dlg.content.getFirst(), {
-                "aspectRatio": this.options.aspectRatio,
-                "description" : this.options.description,
-                "imageUrl" : this.options.imageUrl,
-                "resultMaxSize" : this.options.resultMaxSize,
-                "reference" : this.options.reference,
-                "referenceType": this.options.referenceType,
-                "resetEnable" : true
-            });
-            this.image.load(this.data);
-        }.bind(this))
-	}
+    },
+    //移动端h5 上传图片
+    uploadImageForH5:function(file) {
+        //公共图片上传服务
+        var maxSize = this.options.resultMaxSize ? this.options.resultMaxSize : 800;
+        var formData = new FormData();
+		formData.append('file', file, file.name);
+		// if( this.options.data ){
+		// 	Object.each(this.options.data, function(v, k){
+		// 		formData.append(k, v)
+		// 	});
+		// }
+        o2.xDesktop.uploadImageByScale(
+            this.options.reference,
+            this.options.referenceType,
+            maxSize,
+            formData,
+            file,
+            function(json){
+                this.imageSrc = MWF.xDesktop.getImageSrc( json.id );
+                this.imageId = json.id;
+                this.fireEvent("change");
+            }.bind(this),
+            function(json) {
+                this.imageSrc = "";
+                this.imageId = "";
+                this.fireEvent("change");
+            }.bind(this)
+        );
+    }
 	
 	
 });
 });