Main.js 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094
  1. MWF.require("MWF.widget.UUID", null, false);
  2. MWF.xDesktop.requireApp("Template", "MForm", null, false);
  3. MWF.xDesktop.requireApp("Template", "MPopupForm", null, false);
  4. MWF.xApplication.IMV2.Main = new Class({
  5. Extends: MWF.xApplication.Common.Main,
  6. Implements: [Options, Events],
  7. options: {
  8. "style": "default",
  9. "name": "IMV2",
  10. "mvcStyle": "style.css",
  11. "icon": "icon.png",
  12. "width": "1024",
  13. "height": "768",
  14. "isResize": true,
  15. "isMax": true,
  16. "title": MWF.xApplication.IMV2.LP.title,
  17. "conversationId": ""
  18. },
  19. onQueryLoad: function () {
  20. this.lp = MWF.xApplication.IMV2.LP;
  21. this.app = this;
  22. this.conversationNodeItemList = [];
  23. this.conversationId = this.options.conversationId || "";
  24. this.messageList = [];
  25. this.emojiList = [];
  26. //添加87个表情
  27. for (var i = 1; i < 88; i++) {
  28. var emoji = {
  29. "key": i > 9 ? "[" + i + "]" : "[0" + i + "]",
  30. "path": i > 9 ? "/x_component_IMV2/$Main/emotions/im_emotion_" + i + ".png" : "/x_component_IMV2/$Main/emotions/im_emotion_0" + i + ".png",
  31. };
  32. this.emojiList.push(emoji);
  33. }
  34. },
  35. onQueryClose: function () {
  36. this.closeListening()
  37. },
  38. loadApplication: function (callback) {
  39. var url = this.path + this.options.style + "/im.html";
  40. this.content.loadHtml(url, { "bind": { "lp": this.lp, "data": {} }, "module": this }, function () {
  41. //设置content
  42. this.app.content = this.o2ImMainNode;
  43. //启动监听
  44. this.startListening();
  45. //获取会话列表
  46. this.conversationNodeItemList = [];
  47. o2.Actions.load("x_message_assemble_communicate").ImAction.myConversationList(function (json) {
  48. if (json.data && json.data instanceof Array) {
  49. this.loadConversationList(json.data);
  50. }
  51. }.bind(this));
  52. }.bind(this));
  53. },
  54. startListening: function () {
  55. if (layout.desktop && layout.desktop.message) {
  56. this.messageNumber = layout.desktop.message.items.length;
  57. //查询ws消息 如果增加
  58. if (this.listener) {
  59. clearInterval(this.listener);
  60. }
  61. this.listener = setInterval(function () {
  62. var newNumber = layout.desktop.message.items.length;
  63. //判断是否有新的ws消息
  64. if (newNumber > this.messageNumber) {
  65. this.reciveNewMessage();
  66. this.messageNumber = newNumber;
  67. }
  68. }.bind(this), 1000);
  69. }
  70. },
  71. closeListening: function () {
  72. if (this.listener) {
  73. clearInterval(this.listener);
  74. }
  75. },
  76. // 接收新的消息 会话列表更新 或者 聊天窗口更新
  77. reciveNewMessage: function() {
  78. //查询会话数据
  79. this._checkConversationMessage();
  80. //查询聊天数据
  81. this._checkNewMessage();
  82. },
  83. //加载会话列表
  84. loadConversationList: function (list) {
  85. for (var i = 0; i < list.length; i++) {
  86. var chat = list[i];
  87. var itemNode = this._createConvItemNode(chat);
  88. this.conversationNodeItemList.push(itemNode);
  89. if (this.conversationId && this.conversationId == chat.id) {
  90. this.tapConv(chat);
  91. }
  92. }
  93. },
  94. //分页获取会话的消息列表数据
  95. loadMsgListByConvId: function (page, size, convId) {
  96. var data = { "conversationId": convId };
  97. o2.Actions.load("x_message_assemble_communicate").ImAction.msgListByPaging(page, size, data, function (json) {
  98. var list = json.data;
  99. for (var i = 0; i < list.length; i++) {
  100. this.messageList.push(list[i]);
  101. this._buildMsgNode(list[i], true);
  102. }
  103. }.bind(this), function (error) {
  104. console.log(error);
  105. }.bind(this), false);
  106. },
  107. //点击会话
  108. tapConv: function (conv) {
  109. this._setCheckNode(conv);
  110. var url = this.path + this.options.style + "/chat.html";
  111. var data = { "convName": conv.title };
  112. this.conversationId = conv.id;
  113. this.chatNode.empty();
  114. this.chatNode.loadHtml(url, { "bind": data, "module": this }, function () {
  115. var me = layout.session.user.distinguishedName;
  116. if (conv.type === "group" && me === conv.adminPerson) {
  117. this.chatTitleMoreBtnNode.setStyle("display", "block");
  118. this.chatTitleMoreBtnNode.addEvents({
  119. "click": function (e) {
  120. var display = this.chatTitleMoreMenuNode.getStyle("display");
  121. if (display === "none") {
  122. this.chatTitleMoreMenuNode.setStyle("display", "block");
  123. } else {
  124. this.chatTitleMoreMenuNode.setStyle("display", "none");
  125. }
  126. }.bind(this)
  127. });
  128. } else {
  129. this.chatTitleMoreBtnNode.setStyle("display", "none");
  130. }
  131. //获取聊天信息
  132. this.messageList = [];
  133. this.loadMsgListByConvId(1, 20, conv.id);
  134. var scrollFx = new Fx.Scroll(this.chatContentNode);
  135. scrollFx.toBottom();
  136. }.bind(this));
  137. },
  138. //修改群名
  139. tapUpdateConvTitle: function() {
  140. this.chatTitleMoreMenuNode.setStyle("display", "none");
  141. var form = new MWF.xApplication.IMV2.UpdateConvTitleForm(this, {}, {}, { app: this.app });
  142. form.create();
  143. },
  144. //修改群成员
  145. tapUpdateConvMembers: function() {
  146. this.chatTitleMoreMenuNode.setStyle("display", "none");
  147. var members = [];
  148. for (var i = 0; i < this.conversationNodeItemList.length; i++) {
  149. var c = this.conversationNodeItemList[i];
  150. if (this.conversationId == c.data.id) {
  151. members = c.data.personList;
  152. }
  153. }
  154. var form = new MWF.xApplication.IMV2.CreateConversationForm(this, {}, { "title": "修改成员", "personCount": 0, "personSelected": members, "isUpdateMember": true }, { app: this.app });
  155. form.create()
  156. },
  157. //点击发送消息
  158. sendMsg: function () {
  159. var text = this.chatBottomAreaTextareaNode.value;
  160. if (text) {
  161. this.chatBottomAreaTextareaNode.value = "";
  162. this._newAndSendTextMsg(text, "text");
  163. } else {
  164. console.log("没有消息内容!");
  165. }
  166. },
  167. //点击表情按钮
  168. showEmojiBox: function () {
  169. if (!this.emojiBoxNode) {
  170. this.emojiBoxNode = new Element("div", { "class": "chat-emoji-box" }).inject(this.chatNode);
  171. var _self = this;
  172. for (var i = 0; i < this.emojiList.length; i++) {
  173. var emoji = this.emojiList[i];
  174. var emojiNode = new Element("img", { "src": emoji.path, "class": "chat-emoji-img" }).inject(this.emojiBoxNode);
  175. emojiNode.addEvents({
  176. "mousedown": function (ev) {
  177. _self.sendEmojiMsg(this.emoji);
  178. _self.hideEmojiBox();
  179. }.bind({ emoji: emoji })
  180. });
  181. }
  182. }
  183. this.emojiBoxNode.setStyle("display", "block");
  184. this.hideFun = this.hideEmojiBox.bind(this);
  185. document.body.addEvent("mousedown", this.hideFun);
  186. },
  187. // 点击发送文件消息
  188. showChooseFile: function() {
  189. if (!this.uploadFileAreaNode){
  190. this.createUploadFileNode();
  191. }
  192. this.fileUploadNode.click();
  193. },
  194. //创建文件选择框
  195. createUploadFileNode: function(){
  196. this.uploadFileAreaNode = new Element("div");
  197. var html = "<input name=\"file\" type=\"file\" multiple/>";
  198. this.uploadFileAreaNode.set("html", html);
  199. this.fileUploadNode = this.uploadFileAreaNode.getFirst();
  200. this.fileUploadNode.addEvent("change", function(){
  201. var files = this.fileUploadNode.files;
  202. if (files.length) {
  203. var file = files.item(0);
  204. var formData = new FormData();
  205. formData.append('file', file);
  206. formData.append('fileName', file.name);
  207. var fileExt = file.name.substring(file.name.lastIndexOf("."));
  208. // 图片消息
  209. var type = "file"
  210. if (fileExt.toLowerCase() == ".bmp" || fileExt.toLowerCase() == ".jpeg"
  211. || fileExt.toLowerCase() == ".png" || fileExt.toLowerCase() == ".jpg") {
  212. type = "image"
  213. }else { // 文件消息
  214. type = "file"
  215. }
  216. //上传文件
  217. o2.Actions.load("x_message_assemble_communicate").ImAction.uploadFile(this.conversationId, type, formData, "{}", function (json) {
  218. if (json.data) {
  219. var fileId = json.data.id
  220. var fileExtension = json.data.fileExtension
  221. var fileName = json.data.fileName
  222. this._newImageOrFileMsgAndSend(type, fileId, fileName, fileExtension)
  223. }
  224. }.bind(this), function (error) {
  225. console.log(error);
  226. }.bind(this))
  227. }
  228. }.bind(this));
  229. },
  230. hideEmojiBox: function () {
  231. //关闭emojiBoxNode
  232. this.emojiBoxNode.setStyle("display", "none");
  233. document.body.removeEvent("mousedown", this.hideFun);
  234. },
  235. //发送表情消息
  236. sendEmojiMsg: function (emoji) {
  237. this._newAndSendTextMsg(emoji.key, "emoji");
  238. },
  239. //点击创建单聊按钮
  240. tapCreateSingleConv: function () {
  241. // var form = new MWF.xApplication.IMV2.SingleForm(this, {}, {}, { app: this.app });
  242. // form.create()
  243. var form = new MWF.xApplication.IMV2.CreateConversationForm(this, {}, { "title": "创建单聊", "personCount": 1 }, { app: this.app });
  244. form.create()
  245. },
  246. //点击创建群聊按钮
  247. tapCreateGroupConv: function () {
  248. var form = new MWF.xApplication.IMV2.CreateConversationForm(this, {}, { "title": "创建群聊", "personCount": 0, "personSelected": [] }, { app: this.app });
  249. form.create()
  250. },
  251. //更新群名
  252. updateConversationTitle: function(title, convId) {
  253. var conv = {
  254. id: convId,
  255. title: title,
  256. };
  257. var _self = this;
  258. o2.Actions.load("x_message_assemble_communicate").ImAction.update(conv, function (json) {
  259. var newConv = json.data;
  260. //点击会话 刷新聊天界面
  261. _self.tapConv(newConv);
  262. //刷新会话列表的title
  263. for (var i = 0; i < this.conversationNodeItemList.length; i++) {
  264. var cv = this.conversationNodeItemList[i];
  265. if (cv.data.id == convId) {
  266. //刷新
  267. cv.refreshConvTitle(title);
  268. }
  269. }
  270. }.bind(this), function (error) {
  271. console.log(error);
  272. }.bind(this))
  273. },
  274. //更新群成员
  275. updateConversationMembers: function(members, convId) {
  276. var conv = {
  277. id: convId,
  278. personList: members,
  279. };
  280. var _self = this;
  281. o2.Actions.load("x_message_assemble_communicate").ImAction.update(conv, function (json) {
  282. var newConv = json.data;
  283. _self.tapConv(newConv);
  284. }.bind(this), function (error) {
  285. console.log(error);
  286. }.bind(this))
  287. },
  288. /**
  289. * 创建会话
  290. * @param {*} persons 人员列表
  291. * @param {*} cType 会话类型 "single" "group"
  292. */
  293. newConversation: function (persons, cType) {
  294. var conv = {
  295. type: cType,
  296. personList: persons,
  297. };
  298. var _self = this;
  299. o2.Actions.load("x_message_assemble_communicate").ImAction.create(conv, function (json) {
  300. var newConv = json.data;
  301. var isOld = false;
  302. for (var i = 0; i < _self.conversationNodeItemList.length; i++) {
  303. var c = _self.conversationNodeItemList[i];
  304. if (newConv.id == c.data.id) {
  305. isOld = true;
  306. _self.tapConv(c);
  307. }
  308. }
  309. if (!isOld) {
  310. var itemNode = _self._createConvItemNode(newConv);
  311. _self.conversationNodeItemList.push(itemNode);
  312. _self.tapConv(newConv);
  313. }
  314. }.bind(this), function (error) {
  315. console.log(error);
  316. }.bind(this))
  317. },
  318. //创建会话ItemNode
  319. _createConvItemNode: function (conv) {
  320. return new MWF.xApplication.IMV2.ConversationItem(conv, this);
  321. },
  322. //会话ItemNode 点击背景色
  323. _setCheckNode: function (conv) {
  324. for (var i = 0; i < this.conversationNodeItemList.length; i++) {
  325. var item = this.conversationNodeItemList[i];
  326. if (item.data.id == conv.id) {
  327. item.addCheckClass();
  328. } else {
  329. item.removeCheckClass();
  330. }
  331. }
  332. },
  333. //创建图片或文件消息
  334. _newImageOrFileMsgAndSend: function(type, fileId, fileName, fileExt) {
  335. var distinguishedName = layout.session.user.distinguishedName;
  336. var time = this._currentTime();
  337. var body = {
  338. "body": "[文件]",
  339. "type": type,
  340. "fileId": fileId,
  341. "fileExtension": fileExt,
  342. "fileName": fileName
  343. };
  344. var bodyJson = JSON.stringify(body);
  345. var uuid = (new MWF.widget.UUID).toString();
  346. var message = {
  347. "id": uuid,
  348. "conversationId": this.conversationId,
  349. "body": bodyJson,
  350. "createPerson": distinguishedName,
  351. "createTime": time,
  352. "sendStatus": 1
  353. };
  354. o2.Actions.load("x_message_assemble_communicate").ImAction.msgCreate(message,
  355. function (json) {
  356. console.log("消息发送成功!");
  357. }.bind(this),
  358. function (error) {
  359. console.log(error);
  360. }.bind(this));
  361. this.messageList.push(message);
  362. this._buildSender(body, distinguishedName, false);
  363. this._refreshConvMessage(message);
  364. },
  365. //创建文本消息 并发送
  366. _newAndSendTextMsg: function (text, type) {
  367. var distinguishedName = layout.session.user.distinguishedName;
  368. var time = this._currentTime();
  369. var body = { "body": text, "type": type };
  370. var bodyJson = JSON.stringify(body);
  371. var uuid = (new MWF.widget.UUID).toString();
  372. var textMessage = {
  373. "id": uuid,
  374. "conversationId": this.conversationId,
  375. "body": bodyJson,
  376. "createPerson": distinguishedName,
  377. "createTime": time,
  378. "sendStatus": 1
  379. };
  380. o2.Actions.load("x_message_assemble_communicate").ImAction.msgCreate(textMessage,
  381. function (json) {
  382. //data = json.data;
  383. console.log("消息发送成功!");
  384. }.bind(this),
  385. function (error) {
  386. console.log(error);
  387. }.bind(this));
  388. this.messageList.push(textMessage);
  389. this._buildSender(body, distinguishedName, false);
  390. this._refreshConvMessage(textMessage);
  391. },
  392. //刷新会话Item里面的最后消息内容
  393. _refreshConvMessage: function (msg) {
  394. for (var i = 0; i < this.conversationNodeItemList.length; i++) {
  395. var node = this.conversationNodeItemList[i];
  396. if (node.data.id == this.conversationId) {
  397. node.refreshLastMsg(msg);
  398. }
  399. }
  400. },
  401. //检查会话列表是否有更新
  402. _checkConversationMessage: function () {
  403. o2.Actions.load("x_message_assemble_communicate").ImAction.myConversationList(function (json) {
  404. if (json.data && json.data instanceof Array) {
  405. var newConList = json.data;
  406. for (var j = 0; j < newConList.length; j++) {
  407. var nCv = newConList[j];
  408. var isNew = true;
  409. for (var i = 0; i < this.conversationNodeItemList.length; i++) {
  410. var cv = this.conversationNodeItemList[i];
  411. if (cv.data.id == nCv.id) {
  412. isNew = false;
  413. //刷新
  414. cv.refreshLastMsg(nCv.lastMessage);
  415. }
  416. }
  417. //新会话 创建
  418. if (isNew) {
  419. var itemNode = this._createConvItemNode(nCv);
  420. this.conversationNodeItemList.push(itemNode);
  421. }
  422. }
  423. //this.loadConversationList(json.data);
  424. }
  425. }.bind(this));
  426. },
  427. //检查是否有新消息
  428. _checkNewMessage: function () {
  429. if (this.conversationId && this.conversationId != "") {//是否有会话窗口
  430. var data = { "conversationId": this.conversationId };
  431. o2.Actions.load("x_message_assemble_communicate").ImAction.msgListByPaging(1, 10, data, function (json) {
  432. var list = json.data;
  433. if (list && list.length > 0) {
  434. var msg = list[0];
  435. //检查聊天框是否有变化
  436. if (this.conversationId == msg.conversationId) {
  437. for (var i = 0; i < list.length; i++) {
  438. var isnew = true;
  439. var m = list[i];
  440. for (var j = 0; j < this.messageList.length; j++) {
  441. if (this.messageList[j].id == m.id) {
  442. isnew = false;
  443. }
  444. }
  445. if (isnew) {
  446. this.messageList.push(m);
  447. this._buildMsgNode(m, false);
  448. // this._refreshConvMessage(m);
  449. }
  450. }
  451. }
  452. }
  453. }.bind(this), function (error) {
  454. console.log(error);
  455. }.bind(this), false);
  456. }
  457. },
  458. //创建消息html节点
  459. _buildMsgNode: function (msg, isTop) {
  460. var createPerson = msg.createPerson;
  461. var jsonbody = msg.body;
  462. var body = JSON.parse(jsonbody);//todo 目前只有一种text类型
  463. var distinguishedName = layout.session.user.distinguishedName;
  464. if (createPerson != distinguishedName) {
  465. this._buildReceiver(body, createPerson, isTop);
  466. } else {
  467. this._buildSender(body, createPerson, isTop);
  468. }
  469. },
  470. /**
  471. * 消息发送体
  472. * @param msgBody 消息体
  473. * @param createPerson 消息人员
  474. * @param isTop 是否放在顶部
  475. */
  476. _buildSender: function (msgBody, createPerson, isTop) {
  477. var receiverBodyNode = new Element("div", { "class": "chat-sender" }).inject(this.chatContentNode, isTop ? "top" : "bottom");
  478. var avatarNode = new Element("div").inject(receiverBodyNode);
  479. var avatarUrl = this._getIcon(createPerson);
  480. var name = createPerson;
  481. if (createPerson.indexOf("@") != -1) {
  482. name = name.substring(0, createPerson.indexOf("@"));
  483. }
  484. var avatarImg = new Element("img", { "src": avatarUrl }).inject(avatarNode);
  485. var nameNode = new Element("div", { "text": name }).inject(receiverBodyNode);
  486. var lastNode = new Element("div").inject(receiverBodyNode);
  487. var lastFirstNode = new Element("div", { "class": "chat-left_triangle" }).inject(lastNode);
  488. //text
  489. if (msgBody.type == "emoji") { // 表情
  490. var img = "";
  491. for (var i = 0; i < this.emojiList.length; i++) {
  492. if (msgBody.body == this.emojiList[i].key) {
  493. img = this.emojiList[i].path;
  494. }
  495. }
  496. new Element("img", { "src": img, "class": "chat-content-emoji" }).inject(lastNode);
  497. } else if (msgBody.type == "image") {//image
  498. var imgBox = new Element("div", { "class": "img-chat" }).inject(lastNode);
  499. var url = this._getFileUrlWithWH(msgBody.fileId, 144, 192);
  500. new Element("img", { "src": url }).inject(imgBox);
  501. imgBox.addEvents({
  502. "click": function (e) {
  503. var downloadUrl = this._getFileDownloadUrl(msgBody.fileId);
  504. window.open(downloadUrl);
  505. }.bind(this)
  506. });
  507. } else if (msgBody.type == "audio") {
  508. var url = this._getFileDownloadUrl(msgBody.fileId);
  509. new Element("audio", { "src": url, "controls": "controls", "preload": "preload" }).inject(lastNode);
  510. } else if (msgBody.type == "location") {
  511. var mapBox = new Element("span").inject(lastNode);
  512. new Element("img", { "src": "../x_component_IMV2/$Main/default/icons/location.png", "width": 24, "height": 24 }).inject(mapBox);
  513. var url = this._getBaiduMapUrl(msgBody.latitude, msgBody.longitude, msgBody.address, msgBody.addressDetail);
  514. new Element("a", { "href": url, "target": "_blank", "text": msgBody.address }).inject(mapBox);
  515. } else if (msgBody.type == "file") { //文件
  516. var mapBox = new Element("span").inject(lastNode);
  517. var fileIcon = this._getFileIcon(msgBody.fileExtension);
  518. new Element("img", { "src": "../x_component_IMV2/$Main/file_icons/"+fileIcon, "width": 48, "height": 48 }).inject(mapBox);
  519. var downloadUrl = this._getFileDownloadUrl(msgBody.fileId);
  520. new Element("a", { "href": downloadUrl, "target": "_blank", "text": msgBody.fileName }).inject(mapBox);
  521. } else {//text
  522. new Element("span", { "text": msgBody.body }).inject(lastNode);
  523. }
  524. if (!isTop) {
  525. var scrollFx = new Fx.Scroll(this.chatContentNode);
  526. scrollFx.toBottom();
  527. }
  528. },
  529. /**
  530. * 消息接收体
  531. * @param msgBody
  532. * @param createPerson 消息人员
  533. * @param isTop 是否放在顶部
  534. */
  535. _buildReceiver: function (msgBody, createPerson, isTop) {
  536. var receiverBodyNode = new Element("div", { "class": "chat-receiver" }).inject(this.chatContentNode, isTop ? "top" : "bottom");
  537. var avatarNode = new Element("div").inject(receiverBodyNode);
  538. var avatarUrl = this._getIcon(createPerson);
  539. var name = createPerson;
  540. if (createPerson.indexOf("@") != -1) {
  541. name = name.substring(0, createPerson.indexOf("@"));
  542. }
  543. var avatarImg = new Element("img", { "src": avatarUrl }).inject(avatarNode);
  544. var nameNode = new Element("div", { "text": name }).inject(receiverBodyNode);
  545. var lastNode = new Element("div").inject(receiverBodyNode);
  546. var lastFirstNode = new Element("div", { "class": "chat-right_triangle" }).inject(lastNode);
  547. if (msgBody.type == "emoji") { // 表情
  548. var img = "";
  549. for (var i = 0; i < this.emojiList.length; i++) {
  550. if (msgBody.body == this.emojiList[i].key) {
  551. img = this.emojiList[i].path;
  552. }
  553. }
  554. new Element("img", { "src": img, "class": "chat-content-emoji" }).inject(lastNode);
  555. } else if (msgBody.type == "image") {//image
  556. var imgBox = new Element("div", { "class": "img-chat" }).inject(lastNode);
  557. var url = this._getFileUrlWithWH(msgBody.fileId, 144, 192);
  558. new Element("img", { "src": url }).inject(imgBox);
  559. imgBox.addEvents({
  560. "click": function (e) {
  561. var downloadUrl = this._getFileDownloadUrl(msgBody.fileId);
  562. window.open(downloadUrl);
  563. }.bind(this)
  564. });
  565. } else if (msgBody.type == "audio") {
  566. var url = this._getFileDownloadUrl(msgBody.fileId);
  567. new Element("audio", { "src": url, "controls": "controls", "preload": "preload" }).inject(lastNode);
  568. } else if (msgBody.type == "location") {
  569. var mapBox = new Element("span").inject(lastNode);
  570. new Element("img", { "src": "../x_component_IMV2/$Main/default/icons/location.png", "width": 24, "height": 24 }).inject(mapBox);
  571. var url = this._getBaiduMapUrl(msgBody.latitude, msgBody.longitude, msgBody.address, msgBody.addressDetail);
  572. new Element("a", { "href": url, "target": "_blank", "text": msgBody.address }).inject(mapBox);
  573. } else if (msgBody.type == "file") { //文件
  574. var mapBox = new Element("span").inject(lastNode);
  575. var fileIcon = this._getFileIcon(msgBody.fileExtension);
  576. new Element("img", { "src": "../x_component_IMV2/$Main/file_icons/"+fileIcon, "width": 48, "height": 48 }).inject(mapBox);
  577. var downloadUrl = this._getFileDownloadUrl(msgBody.fileId);
  578. new Element("a", { "href": downloadUrl, "target": "_blank", "text": msgBody.fileName }).inject(mapBox);
  579. } else {//text
  580. new Element("span", { "text": msgBody.body }).inject(lastNode);
  581. }
  582. if (!isTop) {
  583. var scrollFx = new Fx.Scroll(this.chatContentNode);
  584. scrollFx.toBottom();
  585. }
  586. },
  587. //图片 根据大小 url
  588. _getFileUrlWithWH: function (id, width, height) {
  589. var action = MWF.Actions.get("x_message_assemble_communicate").action;
  590. var url = action.getAddress() + action.actions.imgFileDownloadWithWH.uri;
  591. url = url.replace("{id}", encodeURIComponent(id));
  592. url = url.replace("{width}", encodeURIComponent(width));
  593. url = url.replace("{height}", encodeURIComponent(height));
  594. return url;
  595. },
  596. //file 下载的url
  597. _getFileDownloadUrl: function (id) {
  598. var action = MWF.Actions.get("x_message_assemble_communicate").action;
  599. var url = action.getAddress() + action.actions.imgFileDownload.uri;
  600. url = url.replace("{id}", encodeURIComponent(id));
  601. return url;
  602. },
  603. //百度地图打开地址
  604. _getBaiduMapUrl: function (lat, longt, address, content) {
  605. var url = "https://api.map.baidu.com/marker?location=" + lat + "," + longt + "&title=" + address + "&content=" + content + "&output=html&src=net.o2oa.map";
  606. return url;
  607. },
  608. //用户头像
  609. _getIcon: function (id) {
  610. var orgAction = MWF.Actions.get("x_organization_assemble_control")
  611. var url = (id) ? orgAction.getPersonIcon(id) : "../x_component_IMV2/$Main/default/icons/group.png";
  612. return url + "?" + (new Date().getTime());
  613. },
  614. // 文件类型icon图
  615. _getFileIcon: function (ext) {
  616. if (ext) {
  617. if (ext === "jpg" || ext === "jpeg") {
  618. return "icon_file_jpeg.png";
  619. } else if (ext === "gif") {
  620. return "icon_file_gif.png";
  621. } else if (ext === "png") {
  622. return "icon_file_png.png";
  623. } else if (ext === "tiff") {
  624. return "icon_file_tiff.png";
  625. } else if (ext === "bmp" || ext === "webp") {
  626. return "icon_file_img.png";
  627. } else if (ext === "ogg" || ext === "mp3" || ext === "wav" || ext === "wma") {
  628. return "icon_file_mp3.png";
  629. } else if (ext === "mp4") {
  630. return "icon_file_mp4.png";
  631. } else if (ext === "avi") {
  632. return "icon_file_avi.png";
  633. } else if (ext === "mov" || ext === "rm" || ext === "mkv") {
  634. return "icon_file_rm.png";
  635. } else if (ext === "doc" || ext === "docx") {
  636. return "icon_file_word.png";
  637. } else if (ext === "xls" || ext === "xlsx") {
  638. return "icon_file_excel.png";
  639. } else if (ext === "ppt" || ext === "pptx") {
  640. return "icon_file_ppt.png";
  641. } else if (ext === "html") {
  642. return "icon_file_html.png";
  643. } else if (ext === "pdf") {
  644. return "icon_file_pdf.png";
  645. } else if (ext === "txt" || ext === "json") {
  646. return "icon_file_txt.png";
  647. } else if (ext === "zip") {
  648. return "icon_file_zip.png";
  649. } else if (ext === "rar") {
  650. return "icon_file_rar.png";
  651. } else if (ext === "7z") {
  652. return "icon_file_arch.png";
  653. } else if (ext === "ai") {
  654. return "icon_file_ai.png";
  655. } else if (ext === "att") {
  656. return "icon_file_att.png";
  657. } else if (ext === "au") {
  658. return "icon_file_au.png";
  659. } else if (ext === "cad") {
  660. return "icon_file_cad.png";
  661. } else if (ext === "cdr") {
  662. return "icon_file_cdr.png";
  663. } else if (ext === "eps") {
  664. return "icon_file_eps.png";
  665. } else if (ext === "exe") {
  666. return "icon_file_exe.png";
  667. } else if (ext === "iso") {
  668. return "icon_file_iso.png";
  669. } else if (ext === "link") {
  670. return "icon_file_link.png";
  671. } else if (ext === "swf") {
  672. return "icon_file_flash.png";
  673. } else if (ext === "psd") {
  674. return "icon_file_psd.png";
  675. } else if (ext === "tmp") {
  676. return "icon_file_tmp.png";
  677. }else {
  678. return "icon_file_unkown.png";
  679. }
  680. }else {
  681. return "icon_file_unkown.png";
  682. }
  683. },
  684. //输出特殊的时间格式
  685. _friendlyTime: function (date) {
  686. var day = date.getDate();
  687. var monthIndex = date.getMonth();
  688. var year = date.getFullYear();
  689. var time = date.getTime();
  690. var today = new Date();
  691. var todayDay = today.getDate();
  692. var todayMonthIndex = today.getMonth();
  693. var todayYear = today.getFullYear();
  694. var todayTime = today.getTime();
  695. var retTime = "";
  696. //同一天
  697. if (day === todayDay && monthIndex === todayMonthIndex && year === todayYear) {
  698. var hour = 0;
  699. if (todayTime > time) {
  700. hour = parseInt((todayTime - time) / 3600000);
  701. if (hour == 0) {
  702. retTime = Math.max(parseInt((todayTime - time) / 60000), 1) + "分钟前"
  703. } else {
  704. retTime = hour + "小时前"
  705. }
  706. }
  707. return retTime;
  708. }
  709. var dates = parseInt(time / 86400000);
  710. var todaydates = parseInt(todayTime / 86400000);
  711. if (todaydates > dates) {
  712. var days = (todaydates - dates);
  713. if (days == 1) {
  714. retTime = "昨天";
  715. } else if (days == 2) {
  716. retTime = "前天 ";
  717. } else if (days > 2 && days < 31) {
  718. retTime = days + "天前";
  719. } else if (days >= 31 && days <= 2 * 31) {
  720. retTime = "一个月前";
  721. } else if (days > 2 * 31 && days <= 3 * 31) {
  722. retTime = "2个月前";
  723. } else if (days > 3 * 31 && days <= 4 * 31) {
  724. retTime = "3个月前";
  725. } else {
  726. retTime = this._formatDate(date);
  727. }
  728. }
  729. return retTime;
  730. },
  731. //yyyy-MM-dd
  732. _formatDate: function (date) {
  733. var month = date.getMonth() + 1;
  734. var day = date.getDate();
  735. month = (month.toString().length == 1) ? ("0" + month) : month;
  736. day = (day.toString().length == 1) ? ("0" + day) : day;
  737. return date.getFullYear() + '-' + month + '-' + day;
  738. },
  739. //当前时间 yyyy-MM-dd HH:mm:ss
  740. _currentTime: function () {
  741. var today = new Date();
  742. var year = today.getFullYear(); //得到年份
  743. var month = today.getMonth();//得到月份
  744. var date = today.getDate();//得到日期
  745. var hour = today.getHours();//得到小时
  746. var minu = today.getMinutes();//得到分钟
  747. var sec = today.getSeconds();//得到秒
  748. month = month + 1;
  749. if (month < 10) month = "0" + month;
  750. if (date < 10) date = "0" + date;
  751. if (hour < 10) hour = "0" + hour;
  752. if (minu < 10) minu = "0" + minu;
  753. if (sec < 10) sec = "0" + sec;
  754. return year + "-" + month + "-" + date + " " + hour + ":" + minu + ":" + sec;
  755. }
  756. });
  757. //会话对象
  758. MWF.xApplication.IMV2.ConversationItem = new Class({
  759. initialize: function (data, main) {
  760. this.data = data;
  761. this.main = main;
  762. this.container = this.main.chatItemListNode;
  763. this.load();
  764. },
  765. load: function () {
  766. var avatarDefault = this.main._getIcon();
  767. var convData = {
  768. "id": this.data.id,
  769. "avatarUrl": avatarDefault,
  770. "title": this.data.title,
  771. "time": "",
  772. "lastMessage": "",
  773. "lastMessageType": "text"
  774. };
  775. var distinguishedName = layout.session.user.distinguishedName;
  776. if (this.data.type && this.data.type === "single") {
  777. var chatPerson = "";
  778. if (this.data.personList && this.data.personList instanceof Array) {
  779. for (var j = 0; j < this.data.personList.length; j++) {
  780. var person = this.data.personList[j];
  781. if (person !== distinguishedName) {
  782. chatPerson = person;
  783. }
  784. }
  785. }
  786. convData.avatarUrl = this.main._getIcon(chatPerson);
  787. var name = chatPerson;
  788. if (chatPerson.indexOf("@") != -1) {
  789. name = name.substring(0, chatPerson.indexOf("@"));
  790. }
  791. convData.title = name;
  792. }
  793. if (this.data.lastMessage) {
  794. //todo 其它消息类型
  795. var mBody = JSON.parse(this.data.lastMessage.body);
  796. convData.lastMessage = mBody.body;
  797. if (this.data.lastMessage.createTime) {
  798. var time = this.main._friendlyTime(o2.common.toDate(this.data.lastMessage.createTime));
  799. convData.time = time;
  800. }
  801. if (mBody.type) {
  802. convData.lastMessageType = mBody.type;
  803. }
  804. }
  805. this.node = new Element("div", { "class": "item" }).inject(this.container);
  806. this.nodeBaseItem = new Element("div", { "class": "base" }).inject(this.node);
  807. var avatarNode = new Element("div", { "class": "avatar" }).inject(this.nodeBaseItem);
  808. new Element("img", { "src": convData.avatarUrl, "class": "img" }).inject(avatarNode);
  809. var bodyNode = new Element("div", { "class": "body" }).inject(this.nodeBaseItem);
  810. var bodyUpNode = new Element("div", { "class": "body_up" }).inject(bodyNode);
  811. this.titleNode = new Element("div", { "class": "body_title", "text": convData.title }).inject(bodyUpNode);
  812. this.messageTimeNode = new Element("div", { "class": "body_time", "text": convData.time }).inject(bodyUpNode);
  813. if (convData.lastMessageType == "emoji") {
  814. this.lastMessageNode = new Element("div", { "class": "body_down" }).inject(bodyNode);
  815. var imgPath = "";
  816. for (var i = 0; i < this.main.emojiList.length; i++) {
  817. var emoji = this.main.emojiList[i];
  818. if (emoji.key == convData.lastMessage) {
  819. imgPath = emoji.path;
  820. }
  821. }
  822. new Element("img", { "src": imgPath, "style": "width: 16px;height: 16px;" }).inject(this.lastMessageNode);
  823. } else {
  824. this.lastMessageNode = new Element("div", { "class": "body_down", "text": convData.lastMessage }).inject(bodyNode);
  825. }
  826. var _self = this;
  827. this.node.addEvents({
  828. "click": function () {
  829. _self.main.tapConv(_self.data);
  830. }
  831. });
  832. },
  833. /**
  834. *
  835. * 刷新会话列表的最后消息内容
  836. * @param {*} lastMessage
  837. */
  838. refreshLastMsg: function (lastMessage) {
  839. //目前是text 类型的消息
  840. var jsonbody = lastMessage.body;
  841. var body = JSON.parse(jsonbody);
  842. if (this.lastMessageNode) {
  843. if (body.type == "emoji") { //表情 消息
  844. var imgPath = "";
  845. for (var i = 0; i < this.main.emojiList.length; i++) {
  846. var emoji = this.main.emojiList[i];
  847. if (emoji.key == body.body) {
  848. imgPath = emoji.path;
  849. }
  850. }
  851. this.lastMessageNode.empty();
  852. new Element("img", { "src": imgPath, "style": "width: 16px;height: 16px;" }).inject(this.lastMessageNode);
  853. } else { //文本消息
  854. this.lastMessageNode.empty();
  855. this.lastMessageNode.set('text', body.body);
  856. }
  857. }
  858. var time = this.main._friendlyTime(o2.common.toDate(lastMessage.createTime));
  859. if (this.messageTimeNode) {
  860. this.messageTimeNode.set("text", time);
  861. }
  862. },
  863. refreshConvTitle: function(title) {
  864. this.titleNode.set("text", title);
  865. },
  866. addCheckClass: function () {
  867. if (this.nodeBaseItem) {
  868. if (!this.nodeBaseItem.hasClass("check")) {
  869. this.nodeBaseItem.addClass("check");
  870. }
  871. }
  872. },
  873. removeCheckClass: function () {
  874. if (this.nodeBaseItem) {
  875. if (this.nodeBaseItem.hasClass("check")) {
  876. this.nodeBaseItem.removeClass("check");
  877. }
  878. }
  879. }
  880. });
  881. //弹出窗 表单 单聊创建的form
  882. MWF.xApplication.IMV2.SingleForm = new Class({
  883. Extends: MPopupForm,
  884. Implements: [Options, Events],
  885. options: {
  886. "style": "minder",
  887. "width": 700,
  888. //"height": 300,
  889. "height": "200",
  890. "hasTop": true,
  891. "hasIcon": false,
  892. "draggable": true,
  893. "title": "创建单聊"
  894. },
  895. _createTableContent: function () {
  896. var html = "<table width='100%' bordr='0' cellpadding='7' cellspacing='0' styles='formTable' style='margin-top: 20px; '>" +
  897. "<tr><td styles='formTableTitle' lable='person' width='25%'></td>" +
  898. " <td styles='formTableValue14' item='person' colspan='3'></td></tr>" +
  899. "</table>";
  900. this.formTableArea.set("html", html);
  901. var me = layout.session.user.distinguishedName;
  902. var exclude = [];
  903. if (me) {
  904. exclude = [me];
  905. }
  906. this.form = new MForm(this.formTableArea, this.data || {}, {
  907. isEdited: true,
  908. style: "minder",
  909. hasColon: true,
  910. itemTemplate: {
  911. person: { text: "选择人员", type: "org", orgType: "person", count: 0, notEmpty: true, exclude: exclude },
  912. }
  913. }, this.app);
  914. this.form.load();
  915. },
  916. _createBottomContent: function () {
  917. if (this.isNew || this.isEdited) {
  918. this.okActionNode = new Element("button.inputOkButton", {
  919. "styles": this.css.inputOkButton,
  920. "text": "确定"
  921. }).inject(this.formBottomNode);
  922. this.okActionNode.addEvent("click", function (e) {
  923. this.save(e);
  924. }.bind(this));
  925. }
  926. this.cancelActionNode = new Element("button.inputCancelButton", {
  927. "styles": (this.isEdited || this.isNew || this.getEditPermission()) ? this.css.inputCancelButton : this.css.inputCancelButton_long,
  928. "text": "关闭"
  929. }).inject(this.formBottomNode);
  930. this.cancelActionNode.addEvent("click", function (e) {
  931. this.close(e);
  932. }.bind(this));
  933. },
  934. save: function () {
  935. var data = this.form.getResult(true, null, true, false, true);
  936. if (data) {
  937. this.app.newConversation(data.person, "single");
  938. this.close();
  939. }
  940. }
  941. });
  942. //创建聊天 弹出窗表单
  943. MWF.xApplication.IMV2.CreateConversationForm = new Class({
  944. Extends: MPopupForm,
  945. Implements: [Options, Events],
  946. options: {
  947. "style": "minder",
  948. "width": 700,
  949. "height": "200",
  950. "hasTop": true,
  951. "hasIcon": false,
  952. "draggable": true,
  953. "title": "创建单聊",
  954. "personCount": 1, //1 是单选 0 是多选,
  955. "personSelected": [],
  956. "isUpdateMember": false
  957. },
  958. _createTableContent: function () {
  959. var html = "<table width='100%' bordr='0' cellpadding='7' cellspacing='0' styles='formTable' style='margin-top: 20px; '>" +
  960. "<tr><td styles='formTableTitle' lable='person' width='25%'></td>" +
  961. " <td styles='formTableValue14' item='person' colspan='3'></td></tr>" +
  962. "</table>";
  963. this.formTableArea.set("html", html);
  964. var me = layout.session.user.distinguishedName;
  965. var exclude = [];
  966. if (me) {
  967. exclude = [me];
  968. }
  969. this.form = new MForm(this.formTableArea, this.data || {}, {
  970. isEdited: true,
  971. style: "minder",
  972. hasColon: true,
  973. itemTemplate: {
  974. person: { text: "选择人员", type: "org", orgType: "person", count: this.options["personCount"], notEmpty: true, exclude: exclude, value: this.options["personSelected"] },
  975. }
  976. }, this.app);
  977. this.form.load();
  978. },
  979. _createBottomContent: function () {
  980. if (this.isNew || this.isEdited) {
  981. this.okActionNode = new Element("button.inputOkButton", {
  982. "styles": this.css.inputOkButton,
  983. "text": "确定"
  984. }).inject(this.formBottomNode);
  985. this.okActionNode.addEvent("click", function (e) {
  986. this.save(e);
  987. }.bind(this));
  988. }
  989. this.cancelActionNode = new Element("button.inputCancelButton", {
  990. "styles": (this.isEdited || this.isNew || this.getEditPermission()) ? this.css.inputCancelButton : this.css.inputCancelButton_long,
  991. "text": "关闭"
  992. }).inject(this.formBottomNode);
  993. this.cancelActionNode.addEvent("click", function (e) {
  994. this.close(e);
  995. }.bind(this));
  996. },
  997. save: function () {
  998. var data = this.form.getResult(true, null, true, false, true);
  999. if (data) {
  1000. if (this.options["isUpdateMember"] === true) {
  1001. this.app.updateConversationMembers(data.person, this.app.conversationId);
  1002. }else {
  1003. this.app.newConversation(data.person, this.options["personCount"] === 1 ? "single": "group");
  1004. }
  1005. this.close();
  1006. }
  1007. }
  1008. });
  1009. //修改群名
  1010. MWF.xApplication.IMV2.UpdateConvTitleForm = new Class({
  1011. Extends: MPopupForm,
  1012. Implements: [Options, Events],
  1013. options: {
  1014. "style": "minder",
  1015. "width": 500,
  1016. "height": "200",
  1017. "hasTop": true,
  1018. "hasIcon": false,
  1019. "draggable": true,
  1020. "title": "修改群名"
  1021. },
  1022. _createTableContent: function () {
  1023. var html = "<table width='100%' bordr='0' cellpadding='7' cellspacing='0' styles='formTable' style='margin-top: 20px; '>" +
  1024. "<tr><td styles='formTableTitle' lable='title' width='25%'></td>" +
  1025. " <td styles='formTableValue14' item='title' colspan='3'></td></tr>" +
  1026. "</table>";
  1027. this.formTableArea.set("html", html);
  1028. this.form = new MForm(this.formTableArea, this.data || {}, {
  1029. isEdited: true,
  1030. style: "minder",
  1031. hasColon: true,
  1032. itemTemplate: {
  1033. title: {text: "群名", type: "text", notEmpty: true },
  1034. }
  1035. }, this.app);
  1036. this.form.load();
  1037. },
  1038. _createBottomContent: function () {
  1039. if (this.isNew || this.isEdited) {
  1040. this.okActionNode = new Element("button.inputOkButton", {
  1041. "styles": this.css.inputOkButton,
  1042. "text": "确定"
  1043. }).inject(this.formBottomNode);
  1044. this.okActionNode.addEvent("click", function (e) {
  1045. this.save(e);
  1046. }.bind(this));
  1047. }
  1048. this.cancelActionNode = new Element("button.inputCancelButton", {
  1049. "styles": (this.isEdited || this.isNew || this.getEditPermission()) ? this.css.inputCancelButton : this.css.inputCancelButton_long,
  1050. "text": "关闭"
  1051. }).inject(this.formBottomNode);
  1052. this.cancelActionNode.addEvent("click", function (e) {
  1053. this.close(e);
  1054. }.bind(this));
  1055. },
  1056. save: function () {
  1057. var data = this.form.getResult(true, null, true, false, true);
  1058. if (data) {
  1059. this.app.updateConversationTitle(data.title, this.app.conversationId);
  1060. this.close();
  1061. }
  1062. }
  1063. });