Main.js 34 KB

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