Main.js 115 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360
  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 = MWF.xApplication.IMV2 || {};
  5. MWF.xApplication.IMV2.options.multitask = false; //多窗口
  6. MWF.xApplication.IMV2.Main = new Class({
  7. Extends: MWF.xApplication.Common.Main,
  8. Implements: [Options, Events],
  9. options: {
  10. "style": "default",
  11. "name": "IMV2",
  12. "mvcStyle": "style.css",
  13. "icon": "icon.png",
  14. "width": "1024",
  15. "height": "768",
  16. "isResize": true,
  17. "isMax": true,
  18. "title": MWF.xApplication.IMV2.LP.title,
  19. "openConversation": null,
  20. "conversationId": "", // 传入的当前会话id
  21. "mode": "default" // 展现模式:default onlyChat 。 onlyChat的模式需要传入conversationId 会打开这个会话的聊天窗口并隐藏左边的会话列表
  22. },
  23. onQueryLoad: function () {
  24. this.lp = MWF.xApplication.IMV2.LP;
  25. this.app = this;
  26. this.conversationNodeItemList = [];
  27. this.messageList = [];
  28. this.emojiV2TypeList = ["smile", "animals", "food", "activities", "travel", "objects","symbol"];
  29. this.emojiV2Object = {}; // 新版字符表情对象 对象里面按照上面 emojiV2TypeList里面的名称进行分类
  30. this.emojiList = [];
  31. //添加87个表情
  32. for (var i = 1; i < 88; i++) {
  33. var emoji = {
  34. "key": i > 9 ? "[" + i + "]" : "[0" + i + "]",
  35. "path": i > 9 ? "/x_component_IMV2/$Main/emotions/im_emotion_" + i + ".png" : "/x_component_IMV2/$Main/emotions/im_emotion_0" + i + ".png",
  36. };
  37. this.emojiList.push(emoji);
  38. }
  39. if (!this.status) {
  40. this.conversationId = this.options.conversationId || "";
  41. this.openConversation = this.options.openConversation;
  42. this.mode = this.options.mode || "default";
  43. } else {
  44. this.conversationId = this.status.conversationId || "";
  45. this.openConversation = this.status.openConversation;
  46. this.mode = this.status.mode || "default";
  47. }
  48. },
  49. // 加载新版本的 emoji 字符表情
  50. _loadNewEmoji: function () {
  51. const emojiJsonPath = this.path + this.options.style + "/emoji.json";
  52. // 使用 fetch 获取 JSON 数据
  53. fetch(emojiJsonPath)
  54. .then(response => {
  55. if (!response.ok) {
  56. console.error('网络响应错误, emoji.json读取错误');
  57. }
  58. return response.json(); // 解析为 JSON
  59. })
  60. .then(data => {
  61. this.emojiV2Object = data;
  62. })
  63. .catch(error => {
  64. console.error('请求失败:', error);
  65. });
  66. },
  67. // 刷新的时候缓存数据
  68. recordStatus: function(){
  69. return {"conversationId": this.conversationId, "mode": this.mode};
  70. },
  71. onQueryClose: function () {
  72. // this.closeListening();
  73. },
  74. // 获取组件名称
  75. loadComponentName: function () {
  76. o2.Actions.load("x_component_assemble_control").ComponentAction.get("IMV2", function (json) {
  77. var imComponent = json.data;
  78. if (imComponent && imComponent.title) {
  79. this.setTitle(imComponent.title);
  80. }
  81. }.bind(this), function (err) {
  82. console.error(err);
  83. })
  84. },
  85. // 加载应用
  86. loadApplication: function (callback) {
  87. // 判断xadmin 打开聊天功能
  88. if (layout.session.user && layout.session.user.name == "xadmin") {
  89. console.log("xadmin can not open IMV2");
  90. this.app.notice(this.lp.messageXadminNotSupport, "error");
  91. return;
  92. }
  93. this._loadNewEmoji(); // 加载 emoji json 对象
  94. // 先加载配置文件 放入imConfig对象
  95. MWF.xDesktop.loadConfig(function () {
  96. this.imConfig = layout.config.imConfig || {}
  97. var url = this.path + this.options.style + "/im.html";
  98. this.content.loadHtml(url, { "bind": { "lp": this.lp, "data": {} }, "module": this }, function () {
  99. //设置content
  100. this.app.content = this.o2ImMainNode;
  101. // 给websocket 添加撤回消息回调函数
  102. if (layout.desktop && layout.desktop.socket && layout.desktop.socket.addImListener) {
  103. layout.desktop.socket.addImListener("im_revoke", this.revokeMsgCallback.bind(this));
  104. layout.desktop.socket.addImListener("im_create", this.createNewMsgCallback.bind(this));
  105. layout.desktop.socket.addImListener("im_conversation", this.conversationMsgCallback.bind(this));
  106. }
  107. //启动监听
  108. // this.startListening();
  109. // 处理窗口模式
  110. if (this.mode === "onlyChat" && this.conversationId !== "") {
  111. this.o2ConversationListNode.setStyle("display", "none");
  112. this.chatContainerNode.setStyle("margin-left", "2px");
  113. } else {
  114. this.o2ConversationListNode.setStyle("display", "flex");
  115. this.chatContainerNode.setStyle("margin-left", "259px");
  116. }
  117. //获取会话列表
  118. this.conversationNodeItemList = [];
  119. o2.Actions.load("x_message_assemble_communicate").ImAction.myConversationList(function (json) {
  120. if (json.data && json.data instanceof Array) {
  121. this.loadConversationList(json.data);
  122. }
  123. }.bind(this));
  124. // 管理员可见设置按钮
  125. if (MWF.AC.isAdministrator()) {
  126. this.o2ImAdminSettingNode.removeAttribute("style");
  127. } else {
  128. this.o2ImAdminSettingNode.setStyle("display", "none");
  129. }
  130. }.bind(this));
  131. }.bind(this));
  132. this.loadComponentName();
  133. },
  134. openCollectionListPage: function () {
  135. if (this.chatNodeBox) {
  136. this.chatNodeBox.openMyCollection();
  137. }
  138. },
  139. // 撤回消息回调
  140. revokeMsgCallback: function(msg) {
  141. if (this.chatNodeBox) {
  142. this.chatNodeBox._checkRevokeMsg(msg);
  143. }
  144. },
  145. // websocket过来的新消息回调
  146. createNewMsgCallback: function(msg) {
  147. console.log('=======> msg ', msg)
  148. this.reciveNewMessage();
  149. },
  150. // 接收新的消息 会话列表更新 或者 聊天窗口更新
  151. reciveNewMessage: function () {
  152. //查询会话数据
  153. this._checkConversationMessage();
  154. //查询聊天数据
  155. if (this.chatNodeBox) {
  156. this.chatNodeBox._checkNewMessage();
  157. }
  158. },
  159. // 收到会话变更或删除消息
  160. conversationMsgCallback: function(conv) {
  161. console.debug("会话消息处理", conv);
  162. if (conv && conv.id) {
  163. // 查询会话
  164. o2.Actions.load("x_message_assemble_communicate").ImAction.conversation(conv.id, function (json) {
  165. if (json && json.data) {
  166. var newConv = json.data;
  167. var personList = newConv.personList || [];
  168. var distinguishedName = layout.session.user.distinguishedName;
  169. if (personList.indexOf(distinguishedName) > -1) { // 成员存在 更新会话
  170. for (var i = 0; i < this.conversationNodeItemList.length; i++) {
  171. var cv = this.conversationNodeItemList[i];
  172. if (cv.data.id == conv.id) {
  173. cv.refreshData(conv);
  174. }
  175. }
  176. } else { // 被踢出了 删除会话
  177. this._deleteConversation(conv)
  178. }
  179. }
  180. }.bind(this), function(err){
  181. console.error(err);
  182. // 出错 可能是会话删除了
  183. this._deleteConversation(conv);
  184. return true;
  185. }.bind(this));
  186. }
  187. },
  188. // 删除会话
  189. _deleteConversation(conv) {
  190. for (var i = 0; i < this.conversationNodeItemList.length; i++) {
  191. var item = this.conversationNodeItemList[i];
  192. if (item.data.id === conv.id) {
  193. item.node.destroy();
  194. this.conversationNodeItemList.splice(i, 1);
  195. break;
  196. }
  197. }
  198. // 当前聊天窗口 关闭
  199. if (this.conversationId && this.conversationId === conv.id) {
  200. this.chatContainerNode.empty();
  201. this.conversationId = null;
  202. }
  203. },
  204. //加载会话列表
  205. loadConversationList: function (list) {
  206. let openChat = false
  207. for (var i = 0; i < list.length; i++) {
  208. var chat = list[i];
  209. var itemNode = this._createConvItemNode(chat);
  210. this.conversationNodeItemList.push(itemNode);
  211. if (this.openConversation && this.openConversation.id && this.openConversation.id === chat.id) {
  212. openChat = true;
  213. this.tapConv(chat);
  214. } else if (this.conversationId && this.conversationId === chat.id) {
  215. openChat = true;
  216. this.tapConv(chat);
  217. }
  218. }
  219. // 列表里面没有这个会话 有可能是单聊会话 没有消息的情况
  220. if (!openChat && this.openConversation) {
  221. const newConv = this.openConversation;
  222. newConv.isNew = true; // 新建的 放在列表的前面
  223. const itemNode = this._createConvItemNode(newConv);
  224. this.conversationNodeItemList.unshift(itemNode);
  225. openChat = true;
  226. this.tapConv(newConv);
  227. }
  228. // 初始情况 打开第一个
  229. if(!openChat && this.conversationNodeItemList.length > 0) {
  230. this.tapConv(this.conversationNodeItemList[0].data);
  231. }
  232. },
  233. // 点击设置按钮
  234. tapOpenSettings: function() {
  235. this.openSettingsDialog();
  236. },
  237. // 打开IM配置文件
  238. openSettingsDialog: function () {
  239. var settingNode = new Element("div", {"style":"padding:10px;background-color:#fff;"});
  240. var lineNode = new Element("div", {"style":"height:24px;line-height: 24px;"}).inject(settingNode);
  241. var isClearEnableNode = new Element("input", {"type":"checkbox", "name": "clearEnable"}).inject(lineNode);
  242. isClearEnableNode.checked = this.imConfig.enableClearMsg || false
  243. new Element("span", { "text": this.lp.settingsClearMsg}).inject(lineNode);
  244. var line2Node = new Element("div", {"style":"height:24px;line-height: 24px;margin-top: 10px;"}).inject(settingNode);
  245. var isRevokeEnableNode = new Element("input", {"type":"checkbox", "name": "revokeEnable"}).inject(line2Node);
  246. isRevokeEnableNode.checked = this.imConfig.enableRevokeMsg || false;
  247. new Element("span", { "text": this.lp.settingsRevokeMsg}).inject(line2Node);
  248. var line3Node = new Element("div", {"style":"height:24px;line-height: 24px;margin-top: 10px;"}).inject(settingNode);
  249. var revokeOutMinuteNode = new Element("input", {"type":"number", "value": this.imConfig.revokeOutMinute ?? 2, "name": "revokeEnable"}).inject(line3Node);
  250. new Element("span", { "text": this.lp.settingsRevokeOutMinuteMsg}).inject(line3Node);
  251. var line4Node = new Element("div", {"style":"height:24px;line-height: 24px;margin-top: 10px;"}).inject(settingNode);
  252. var conversationCheckInvokeNode = new Element("input", {"type":"text", "value": this.imConfig.conversationCheckInvoke ?? "", "name": "revokeEnable"}).inject(line4Node);
  253. new Element("span", { "text": this.lp.settingsConversationCheckInvokeMsg}).inject(line4Node);
  254. var line5Node = new Element("div", {"style":"height:24px;line-height: 24px;margin-top: 10px;"}).inject(settingNode);
  255. var enableOnlyOfficePreviewNode = new Element("input", {"type":"checkbox", "name": "enableOnlyOfficePreview"}).inject(line5Node);
  256. enableOnlyOfficePreviewNode.checked = this.imConfig.enableOnlyOfficePreview || false
  257. new Element("span", { "text": this.lp.settingsEnableOnlyOfficePreviewMsg}).inject(line5Node);
  258. var dlg = o2.DL.open({
  259. "title": this.lp.setting,
  260. "mask": true,
  261. "width": '500',
  262. "height": "310",
  263. "content": settingNode,
  264. "onQueryClose": function () {
  265. settingNode.destroy();
  266. }.bind(this),
  267. "buttonList": [
  268. {
  269. "type": "ok",
  270. "text": this.lp.ok,
  271. "action": function () {
  272. this.imConfig.enableClearMsg = isClearEnableNode.checked;
  273. this.imConfig.enableRevokeMsg = isRevokeEnableNode.checked;
  274. this.imConfig.enableOnlyOfficePreview = enableOnlyOfficePreviewNode.checked;
  275. this.imConfig.revokeOutMinute = revokeOutMinuteNode.get("value") ?? 2;
  276. if (this.imConfig.revokeOutMinute <= 0 ) {
  277. this.imConfig.revokeOutMinute = 2;
  278. }
  279. this.imConfig.conversationCheckInvoke = (conversationCheckInvokeNode.get("value") ?? "").trim();
  280. console.debug(this.imConfig)
  281. this.postIMConfig(this.imConfig);
  282. // 保存配置文件
  283. dlg.close();
  284. }.bind(this)
  285. },
  286. {
  287. "type": "cancel",
  288. "text": this.lp.close,
  289. "action": function () { dlg.close(); }
  290. }
  291. ],
  292. "onPostShow": function () {
  293. dlg.reCenter();
  294. }.bind(this),
  295. "onPostClose": function(){
  296. dlg = null;
  297. }.bind(this)
  298. });
  299. },
  300. // 保存IM配置文件
  301. postIMConfig: function (imConfig) {
  302. o2.Actions.load("x_message_assemble_communicate").ImAction.config(imConfig, function (json) {
  303. this.refresh();//重新加载整个IM应用
  304. }.bind(this), function (error) {
  305. console.error(error);
  306. this.app.notice(error, "error", this.app.content);
  307. }.bind(this));
  308. },
  309. // 外部调用
  310. tapConvOutside: function (conv) {
  311. if (conv && conv.id) {
  312. let openChat = false
  313. for (let i = 0; i < this.conversationNodeItemList.length; i++) {
  314. const cv = this.conversationNodeItemList[i];
  315. if (cv.data.id === conv.id) {
  316. openChat = true;
  317. this.tapConv(conv);
  318. }
  319. }
  320. if (!openChat) {
  321. const newConv = conv;
  322. newConv.isNew = true; // 新建的 放在列表的前面
  323. const itemNode = this._createConvItemNode(newConv);
  324. this.conversationNodeItemList.unshift(itemNode);
  325. this.tapConv(newConv);
  326. }
  327. }
  328. },
  329. //点击会话
  330. tapConv: function (conv) {
  331. this._setCheckNode(conv);
  332. this.conversationId = conv.id;
  333. // new ChatNodeBox
  334. this.chatNodeBox = new MWF.xApplication.IMV2.ChatNodeBox(conv, this);
  335. },
  336. tapChoosePerson: function() {
  337. MWF.requireApp("Selector","package", function(){
  338. new MWF.O2Selector(document.body, {
  339. "type": 'identity',
  340. "count": 0,
  341. "title": '通讯录',
  342. "firstLevelSelectable": true,
  343. "resultType": "person",
  344. "onPostLoadContent": function () {
  345. this.titleTextNode.set("text", '通讯录')
  346. },
  347. "onComplete": function(items) {
  348. console.log(items)
  349. if (items && items.length > 0) {
  350. let personList = items.map(i => i.data.distinguishedName)
  351. const me = layout.session.user.distinguishedName;
  352. personList = personList.filter(p => p !== me)
  353. if (personList.length === 0 ) {
  354. this.app.notice(this.lp.msgNeedChoosePerson, "error");
  355. } else {
  356. this.newConversation(personList, personList.length === 1 ? "single" : "group")
  357. }
  358. }
  359. }.bind(this)
  360. })
  361. }.bind(this));
  362. },
  363. //点击创建单聊按钮
  364. tapCreateSingleConv: function () {
  365. // var form = new MWF.xApplication.IMV2.SingleForm(this, {}, {}, { app: this.app });
  366. // form.create()
  367. var form = new MWF.xApplication.IMV2.CreateConversationForm(this, {}, { "title": this.lp.createSingle, "personCount": 1 }, { app: this.app });
  368. form.create()
  369. },
  370. //点击创建群聊按钮
  371. tapCreateGroupConv: function () {
  372. var form = new MWF.xApplication.IMV2.CreateConversationForm(this, {}, { "title": this.lp.createGroup, "personCount": 0, "personSelected": [] }, { app: this.app });
  373. form.create()
  374. },
  375. //更新群名
  376. updateConversationTitle: function (title, convId) {
  377. var conv = {
  378. id: convId,
  379. title: title,
  380. };
  381. var _self = this;
  382. o2.Actions.load("x_message_assemble_communicate").ImAction.update(conv, function (json) {
  383. var newConv = json.data;
  384. //点击会话 刷新聊天界面
  385. // _self.tapConv(newConv);
  386. // //刷新会话列表的title
  387. // for (var i = 0; i < this.conversationNodeItemList.length; i++) {
  388. // var cv = this.conversationNodeItemList[i];
  389. // if (cv.data.id == convId) {
  390. // //刷新
  391. // cv.refreshConvTitle(title);
  392. // }
  393. // }
  394. // 列表上的数据也要刷新
  395. _self.reciveNewMessage();
  396. }.bind(this), function (error) {
  397. console.error(error);
  398. }.bind(this))
  399. },
  400. //更新群成员
  401. updateConversationMembers: function (members, convId) {
  402. var conv = {
  403. id: convId,
  404. personList: members,
  405. };
  406. var _self = this;
  407. o2.Actions.load("x_message_assemble_communicate").ImAction.update(conv, function (json) {
  408. var newConv = json.data;
  409. //_self.tapConv(newConv);
  410. // 列表上的数据也要刷新
  411. _self.reciveNewMessage();
  412. }.bind(this), function (error) {
  413. console.error(error);
  414. }.bind(this))
  415. },
  416. /**
  417. * 创建会话
  418. * @param {*} persons 人员列表
  419. * @param {*} cType 会话类型 "single" "group"
  420. */
  421. newConversation: function (persons, cType) {
  422. var conv = {
  423. type: cType,
  424. personList: persons,
  425. };
  426. MWF.require("MWF.widget.Mask", function () {
  427. this.mask = new MWF.widget.Mask({ "style": "desktop", "zIndex": 50000 });
  428. this.mask.loadNode(this.app.content);
  429. o2.Actions.load("x_message_assemble_communicate").ImAction.create(conv, function (json) {
  430. var newConv = json.data;
  431. var isOld = false;
  432. for (var i = 0; i < this.conversationNodeItemList.length; i++) {
  433. var c = this.conversationNodeItemList[i];
  434. if (newConv.id === c.data.id) {
  435. isOld = true;
  436. this.tapConv(c.data);
  437. break;
  438. }
  439. }
  440. if (!isOld) {
  441. newConv.isNew = true; // 新建的 放在列表的前面
  442. var itemNode = this._createConvItemNode(newConv);
  443. this.conversationNodeItemList.unshift(itemNode);
  444. this.tapConv(newConv);
  445. }
  446. if (this.mask) { this.mask.hide(); this.mask = null; }
  447. }.bind(this), function (error) {
  448. console.error(error);
  449. if (this.mask) { this.mask.hide(); this.mask = null; }
  450. }.bind(this));
  451. }.bind(this));
  452. },
  453. //创建会话ItemNode
  454. _createConvItemNode: function (conv) {
  455. return new MWF.xApplication.IMV2.ConversationItem(conv, this);
  456. },
  457. //会话ItemNode 点击背景色
  458. _setCheckNode: function (conv) {
  459. for (var i = 0; i < this.conversationNodeItemList.length; i++) {
  460. var item = this.conversationNodeItemList[i];
  461. if (item.data.id === conv.id) {
  462. item.addCheckClass();
  463. } else {
  464. item.removeCheckClass();
  465. }
  466. }
  467. },
  468. //刷新会话Item里面的最后消息内容
  469. _refreshConvMessage: function (msg) {
  470. var isIn = false;
  471. for (var i = 0; i < this.conversationNodeItemList.length; i++) {
  472. var node = this.conversationNodeItemList[i];
  473. if (node.data.id === msg.conversationId) {
  474. node.refreshLastMsg(msg);
  475. isIn = true;
  476. }
  477. }
  478. if (!isIn) {
  479. this.reciveNewMessage();
  480. }
  481. },
  482. //检查会话列表是否有更新
  483. _checkConversationMessage: function () {
  484. o2.Actions.load("x_message_assemble_communicate").ImAction.myConversationList(function (json) {
  485. if (json.data && json.data instanceof Array) {
  486. var newConList = json.data;
  487. for (var j = 0; j < newConList.length; j++) {
  488. var nCv = newConList[j];
  489. var isNew = true;
  490. for (var i = 0; i < this.conversationNodeItemList.length; i++) {
  491. var cv = this.conversationNodeItemList[i];
  492. if (cv.data.id == nCv.id) {
  493. isNew = false;
  494. //刷新
  495. cv.refreshLastMsg(nCv.lastMessage);
  496. cv.refreshData(nCv);
  497. // if (this.conversationId === nCv.id) {
  498. // this.tapConv(nCv);
  499. // }
  500. }
  501. }
  502. //新会话 创建
  503. if (isNew) {
  504. nCv.isNew = true; // 新建的 放在列表的前面
  505. var itemNode = this._createConvItemNode(nCv);
  506. this.conversationNodeItemList.unshift(itemNode);
  507. }
  508. }
  509. //this.loadConversationList(json.data);
  510. }
  511. }.bind(this));
  512. },
  513. //用户头像
  514. _getIcon: function (id) {
  515. var orgAction = MWF.Actions.get("x_organization_assemble_control")
  516. var url = (id) ? orgAction.getPersonIcon(id) : "../x_component_IMV2/$Main/default/icons/group.png";
  517. return url + "?" + (new Date().getTime());
  518. },
  519. //输出特殊的时间格式
  520. _friendlyTime: function (date) {
  521. var day = date.getDate();
  522. var monthIndex = date.getMonth();
  523. var year = date.getFullYear();
  524. var time = date.getTime();
  525. var today = new Date();
  526. var todayDay = today.getDate();
  527. var todayMonthIndex = today.getMonth();
  528. var todayYear = today.getFullYear();
  529. var todayTime = today.getTime();
  530. var retTime = "";
  531. //同一天
  532. if (day === todayDay && monthIndex === todayMonthIndex && year === todayYear) {
  533. var hour = 0;
  534. if (todayTime > time) {
  535. hour = parseInt((todayTime - time) / 3600000);
  536. if (hour == 0) {
  537. retTime = Math.max(parseInt((todayTime - time) / 60000), 1) + this.lp.minutesBefore
  538. } else {
  539. retTime = hour + this.lp.hoursBefore
  540. }
  541. }
  542. return retTime;
  543. }
  544. var dates = parseInt(time / 86400000);
  545. var todaydates = parseInt(todayTime / 86400000);
  546. if (todaydates > dates) {
  547. var days = (todaydates - dates);
  548. if (days == 1) {
  549. retTime = this.lp.yesterday;
  550. } else if (days == 2) {
  551. retTime = this.lp.beforeYesterday;
  552. } else if (days > 2 && days < 31) {
  553. retTime = days + this.lp.daysBefore;
  554. } else if (days >= 31 && days <= 2 * 31) {
  555. retTime = this.lp.monthAgo;
  556. } else if (days > 2 * 31 && days <= 3 * 31) {
  557. retTime = this.lp.towMonthAgo;
  558. } else if (days > 3 * 31 && days <= 4 * 31) {
  559. retTime = this.lp.threeMonthAgo;
  560. } else {
  561. retTime = this._formatDate(date);
  562. }
  563. }
  564. return retTime;
  565. },
  566. //yyyy-MM-dd
  567. _formatDate: function (date) {
  568. var month = date.getMonth() + 1;
  569. var day = date.getDate();
  570. month = (month.toString().length == 1) ? ("0" + month) : month;
  571. day = (day.toString().length == 1) ? ("0" + day) : day;
  572. return date.getFullYear() + '-' + month + '-' + day;
  573. }
  574. });
  575. // 聊天窗口
  576. MWF.xApplication.IMV2.ChatNodeBox = new Class({
  577. initialize: function (data, main) {
  578. this.data = data;
  579. this.main = main;
  580. this.app = main.app;
  581. this.container = this.main.chatContainerNode;
  582. this.lp = this.main.lp;
  583. this.path = this.main.path;
  584. this.options = this.main.options;
  585. this.pageSize = 20;
  586. this.page = 1;
  587. this.isLoading = false; // 正在加载
  588. this.hasMoreMsgData = false; // 是否还有更多的消息 翻页
  589. this.selectMode = false; // 选择模式
  590. this.selectMsgList = []; // 选择的列表
  591. this.quoteMessage = null; // 引用消息
  592. this.load();
  593. },
  594. htmlSymbols: function() {
  595. return {
  596. '"': '&quot;',
  597. '\'': '&#039;',
  598. '>': '&gt;',
  599. '¡': '&iexcl;',
  600. '£': '&pound;',
  601. '¥': '&yen;',
  602. '§': '&sect;',
  603. '©': '&copy;',
  604. '«': '&laquo;',
  605. '®': '&reg;',
  606. '¯': '&macr;',
  607. '±': '&plusmn;',
  608. '³': '&sup3;',
  609. 'µ': '&micro;',
  610. '·': '&middot;',
  611. '¹': '&sup1;',
  612. '»': '&raquo;',
  613. '½': '&frac12;',
  614. '¿': '&iquest;',
  615. 'Á': '&Aacute;',
  616. 'Ã': '&Atilde;',
  617. 'Å': '&Aring;',
  618. 'Ç': '&Ccedil;',
  619. 'É': '&Eacute;',
  620. 'Ë': '&Euml;',
  621. 'Í': '&Iacute;',
  622. 'Ï': '&Iuml;',
  623. 'Ñ': '&Ntilde;',
  624. 'Ó': '&Oacute;',
  625. 'Õ': '&Otilde;',
  626. '×': '&times;',
  627. 'Ù': '&Ugrave;',
  628. 'Û': '&Ucirc;',
  629. 'Ý': '&Yacute;',
  630. 'ß': '&szlig;',
  631. 'á': '&aacute;',
  632. 'ã': '&atilde;',
  633. 'å': '&aring;',
  634. 'ç': '&ccedil;',
  635. 'é': '&eacute;',
  636. 'ë': '&euml;',
  637. 'í': '&iacute;',
  638. 'ï': '&iuml;',
  639. 'ñ': '&ntilde;',
  640. 'ó': '&oacute;',
  641. 'õ': '&otilde;',
  642. '÷': '&divide;',
  643. 'ù': '&ugrave;',
  644. 'û': '&ucirc;',
  645. 'ý': '&yacute;',
  646. 'ÿ': '&yuml;',
  647. 'œ': '&oelig;',
  648. 'š': '&scaron;',
  649. 'ƒ': '&fnof;',
  650. '˜': '&tilde;',
  651. 'Β': '&Beta;',
  652. 'Δ': '&Delta;',
  653. 'Ζ': '&Zeta;',
  654. 'Θ': '&Theta;',
  655. 'Κ': '&Kappa;',
  656. 'Μ': '&Mu;',
  657. 'Ξ': '&Xi;',
  658. 'Π': '&Pi;',
  659. 'Σ': '&Sigma;',
  660. 'Υ': '&Upsilon;',
  661. 'Χ': '&Chi;',
  662. 'Ω': '&Omega;',
  663. 'β': '&beta;',
  664. 'δ': '&delta;',
  665. 'ζ': '&zeta;',
  666. 'θ': '&theta;',
  667. 'κ': '&kappa;',
  668. 'μ': '&mu;',
  669. 'ξ': '&xi;',
  670. 'π': '&pi;',
  671. 'ς': '&sigmaf;',
  672. 'τ': '&tau;',
  673. 'φ': '&phi;',
  674. 'ψ': '&psi;',
  675. 'ϑ': '&thetasym;',
  676. 'ϖ': '&piv;',
  677. '–': '&ndash;',
  678. '‘': '&lsquo;',
  679. '‚': '&sbquo;',
  680. '”': '&rdquo;',
  681. '†': '&dagger;',
  682. '•': '&bull;',
  683. '‰': '&permil;',
  684. '″': '&Prime;',
  685. '›': '&rsaquo;',
  686. '⁄': '&frasl;',
  687. 'ℑ': '&image;',
  688. 'ℜ': '&real;',
  689. 'ℵ': '&alefsym;',
  690. '↑': '&uarr;',
  691. '↓': '&darr;',
  692. '↵': '&crarr;',
  693. '⇑': '&uArr;',
  694. '⇓': '&dArr;',
  695. '∀': '&forall;',
  696. '∃': '&exist;',
  697. '∇': '&nabla;',
  698. '∉': '&notin;',
  699. '∏': '&prod;',
  700. '−': '&minus;',
  701. '√': '&radic;',
  702. '∞': '&infin;',
  703. '∧': '&and;',
  704. '∩': '&cap;',
  705. '∫': '&int;',
  706. '∼': '&sim;',
  707. '≈': '&asymp;',
  708. '≡': '&equiv;',
  709. '≥': '&ge;',
  710. '⊃': '&sup;',
  711. '⊆': '&sube;',
  712. '⊕': '&oplus;',
  713. '⊥': '&perp;',
  714. '⌈': '&lceil;',
  715. '⌊': '&lfloor;',
  716. '⟨': '&lang;',
  717. '◊': '&loz;',
  718. '♣': '&clubs;',
  719. '♦': '&diams;',
  720. '&': '&amp;',
  721. '<': '&lt;',
  722. ' ': '&nbsp;',
  723. '¢': '&cent;',
  724. '¤': '&curren;',
  725. '¦': '&brvbar;',
  726. '¨': '&uml;',
  727. 'ª': '&ordf;',
  728. '¬': '&not;',
  729. '°': '&deg;',
  730. '²': '&sup2;',
  731. '´': '&acute;',
  732. '¶': '&para;',
  733. '¸': '&cedil;',
  734. 'º': '&ordm;',
  735. '¼': '&frac14;',
  736. '¾': '&frac34;',
  737. 'À': '&Agrave;',
  738. 'Â': '&Acirc;',
  739. 'Ä': '&Auml;',
  740. 'Æ': '&AElig;',
  741. 'È': '&Egrave;',
  742. 'Ê': '&Ecirc;',
  743. 'Ì': '&Igrave;',
  744. 'Î': '&Icirc;',
  745. 'Ð': '&ETH;',
  746. 'Ò': '&Ograve;',
  747. 'Ô': '&Ocirc;',
  748. 'Ö': '&Ouml;',
  749. 'Ø': '&Oslash;',
  750. 'Ú': '&Uacute;',
  751. 'Ü': '&Uuml;',
  752. 'Þ': '&THORN;',
  753. 'à': '&agrave;',
  754. 'â': '&acirc;',
  755. 'ä': '&auml;',
  756. 'æ': '&aelig;',
  757. 'è': '&egrave;',
  758. 'ê': '&ecirc;',
  759. 'ì': '&igrave;',
  760. 'î': '&icirc;',
  761. 'ð': '&eth;',
  762. 'ò': '&ograve;',
  763. 'ô': '&ocirc;',
  764. 'ö': '&ouml;',
  765. 'ø': '&oslash;',
  766. 'ú': '&uacute;',
  767. 'ü': '&uuml;',
  768. 'þ': '&thorn;',
  769. 'Œ': '&OElig;',
  770. 'Š': '&Scaron;',
  771. 'Ÿ': '&Yuml;',
  772. 'ˆ': '&circ;',
  773. 'Α': '&Alpha;',
  774. 'Γ': '&Gamma;',
  775. 'Ε': '&Epsilon;',
  776. 'Η': '&Eta;',
  777. 'Ι': '&Iota;',
  778. 'Λ': '&Lambda;',
  779. 'Ν': '&Nu;',
  780. 'Ο': '&Omicron;',
  781. 'Ρ': '&Rho;',
  782. 'Τ': '&Tau;',
  783. 'Φ': '&Phi;',
  784. 'Ψ': '&Psi;',
  785. 'α': '&alpha;',
  786. 'γ': '&gamma;',
  787. 'ε': '&epsilon;',
  788. 'η': '&eta;',
  789. 'ι': '&iota;',
  790. 'λ': '&lambda;',
  791. 'ν': '&nu;',
  792. 'ο': '&omicron;',
  793. 'ρ': '&rho;',
  794. 'σ': '&sigma;',
  795. 'υ': '&upsilon;',
  796. 'χ': '&chi;',
  797. 'ω': '&omega;',
  798. 'ϒ': '&upsih;',
  799. '—': '&mdash;',
  800. '’': '&rsquo;',
  801. '“': '&ldquo;',
  802. '„': '&bdquo;',
  803. '‡': '&Dagger;',
  804. '…': '&hellip;',
  805. '′': '&prime;',
  806. '‹': '&lsaquo;',
  807. '‾': '&oline;',
  808. '€': '&euro;',
  809. '℘': '&weierp;',
  810. '™': '&trade;',
  811. '←': '&larr;',
  812. '→': '&rarr;',
  813. '↔': '&harr;',
  814. '⇐': '&lArr;',
  815. '⇒': '&rArr;',
  816. '⇔': '&hArr;',
  817. '∂': '&part;',
  818. '∅': '&empty;',
  819. '∈': '&isin;',
  820. '∋': '&ni;',
  821. '∑': '&sum;',
  822. '∗': '&lowast;',
  823. '∝': '&prop;',
  824. '∠': '&ang;',
  825. '∨': '&or;',
  826. '∪': '&cup;',
  827. '∴': '&there4;',
  828. '≅': '&cong;',
  829. '≠': '&ne;',
  830. '≤': '&le;',
  831. '⊂': '&sub;',
  832. '⊄': '&nsub;',
  833. '⊇': '&supe;',
  834. '⊗': '&otimes;',
  835. '⋅': '&sdot;',
  836. '⌉': '&rceil;',
  837. '⌋': '&rfloor;',
  838. '⟩': '&rang;',
  839. '♠': '&spades;',
  840. '♥': '&hearts;'
  841. };
  842. },
  843. contentEscapeBackToSymbol: function(text) {
  844. if (!text || text === "") {
  845. return "";
  846. }
  847. var newText = text+"";
  848. for (const [key, value] of Object.entries(this.htmlSymbols())) {
  849. if (newText.includes(value)) {
  850. newText = newText.replaceAll(value, key);
  851. }
  852. }
  853. return newText;
  854. },
  855. // 创建聊天窗口
  856. load: function() {
  857. const url = this.path + this.options.style + "/chat.html";
  858. this.conversationId = this.data.id;
  859. this.container.empty();
  860. if (this.emojiBoxNode) {
  861. this.emojiBoxNode.destroy();
  862. this.emojiBoxNode = null;
  863. }
  864. this.container.loadHtml(url, { "bind": { "convName": this.getChatTitle(), "lp": this.lp }, "module": this }, function () {
  865. const me = layout.session.user.distinguishedName;
  866. if (this.data.type === "group") {
  867. this.chatTitleMoreBtnNode.setStyle("display", "block");
  868. this.chatTitleMoreBtnNode.addEvents({
  869. "click": function (e) {
  870. var display = this.chatTitleMoreMenuNode.getStyle("display");
  871. if (display === "none") {
  872. this.chatTitleMoreMenuNode.setStyle("display", "block");
  873. this.chatTitleMoreMenuItem4Node.setStyle("display", "block");
  874. if (me === this.data.adminPerson) { // 群主有操作权限
  875. this.chatTitleMoreMenuItem1Node.setStyle("display", "block");
  876. this.chatTitleMoreMenuItem2Node.setStyle("display", "block");
  877. if (this.main.imConfig.enableClearMsg) {
  878. this.chatTitleMoreMenuItem3Node.setStyle("display", "block");
  879. } else {
  880. this.chatTitleMoreMenuItem3Node.setStyle("display", "none");
  881. }
  882. } else {
  883. this.chatTitleMoreMenuItem1Node.setStyle("display", "none");
  884. this.chatTitleMoreMenuItem2Node.setStyle("display", "none");
  885. this.chatTitleMoreMenuItem3Node.setStyle("display", "none");
  886. }
  887. } else {
  888. this.chatTitleMoreMenuNode.setStyle("display", "none");
  889. }
  890. }.bind(this)
  891. });
  892. } else if (this.data.type !== "group") {
  893. if (this.main.imConfig.enableClearMsg) {
  894. this.chatTitleMoreBtnNode.setStyle("display", "block");
  895. this.chatTitleMoreBtnNode.addEvents({
  896. "click": function (e) {
  897. var display = this.chatTitleMoreMenuNode.getStyle("display");
  898. if (display === "none") {
  899. this.chatTitleMoreMenuNode.setStyle("display", "block");
  900. this.chatTitleMoreMenuItem4Node.setStyle("display", "none");
  901. this.chatTitleMoreMenuItem1Node.setStyle("display", "none");
  902. this.chatTitleMoreMenuItem2Node.setStyle("display", "none");
  903. this.chatTitleMoreMenuItem3Node.setStyle("display", "block");
  904. } else {
  905. this.chatTitleMoreMenuNode.setStyle("display", "none");
  906. }
  907. }.bind(this)
  908. });
  909. } else {
  910. this.chatTitleMoreBtnNode.setStyle("display", "none");
  911. }
  912. }
  913. //获取聊天信息
  914. this.page = 1;
  915. this.loadMsgListByPage();
  916. var scrollFx = new Fx.Scroll(this.chatContentNode);
  917. scrollFx.toBottom();
  918. this.addChatEventListener()
  919. // 显示业务图标
  920. this.loadBusinessIcon();
  921. }.bind(this));
  922. },
  923. getChatTitle: function () {
  924. let title = this.data.title
  925. if (this.data.type && this.data.type === "single") {
  926. let chatPerson = "";
  927. if (this.data.personList && this.data.personList instanceof Array) {
  928. for (let j = 0; j < this.data.personList.length; j++) {
  929. const person = this.data.personList[j];
  930. if (person !== layout.session.user.distinguishedName) {
  931. chatPerson = person;
  932. }
  933. }
  934. }
  935. let name = chatPerson;
  936. if (chatPerson.indexOf("@") !== -1) {
  937. name = name.substring(0, chatPerson.indexOf("@"));
  938. }
  939. title = name;
  940. }
  941. return title
  942. },
  943. // 内部一些节点添加事件
  944. addChatEventListener: function () {
  945. // 消息输入框绑定回车事件
  946. this.chatBottomAreaTextareaNode.addEvents({
  947. "keyup": function (e) {
  948. // debugger;
  949. if (e.code === 13) {
  950. if (e.control === true) {
  951. var text = this.chatBottomAreaTextareaNode.value;
  952. this.chatBottomAreaTextareaNode.value = text + "\n";
  953. } else {
  954. this.sendMsg();
  955. }
  956. e.stopPropagation();
  957. }
  958. }.bind(this)
  959. });
  960. // 消息列表上绑定滚动事件
  961. this.chatContentNode.addEvents({
  962. "scroll": function(e) {
  963. //滑到顶部时触发下次数据加载
  964. if (this.chatContentNode.scrollTop == 0) {
  965. if (this.hasMoreMsgData) { // 有更多数据
  966. // 间隔1秒 防止频繁
  967. setTimeout(() => {
  968. //将scrollTop置为10以便下次滑到顶部
  969. this.chatContentNode.scrollTop = 10;
  970. //加载数据
  971. this.loadMoreMsgList();
  972. }, 1000);
  973. }
  974. }
  975. }.bind(this)
  976. });
  977. // 绑定拖拽事件,拖拽上传文件 发送文件消息
  978. // 阻止默认行为(防止文件打开)
  979. ["dragenter", "dragover", "dragleave", "drop"].forEach(eventName => {
  980. this.chatNode.addEventListener(eventName, (e)=> {
  981. e.preventDefault();
  982. e.stopPropagation();
  983. });
  984. });
  985. // 添加拖入/离开时的样式变化
  986. ["dragenter", "dragover"].forEach(eventName => {
  987. this.chatNode.addEventListener(eventName, (e) => this.dragEnterOverEvent(e));
  988. });
  989. ["dragleave", "drop"].forEach(eventName => {
  990. this.chatNode.addEventListener(eventName, (e) => this.dragLeaveEvent(e));
  991. });
  992. // 拖入文件发送消息
  993. this.chatNode.addEventListener("drop", (e) => this.dragDropFileSendMsg(e))
  994. // 从剪贴板 复制文件 发送消息
  995. this.chatNode.addEventListener("paste", (e) => this.pasteFileSendMsg(e))
  996. },
  997. // 如果有业务数据 头部展现应用图标 可以点击打开
  998. loadBusinessIcon: function() {
  999. if (this.data.businessId && this.data.businessBody) {
  1000. if (this.data.businessType && this.data.businessType === "process") {
  1001. var work = JSON.parse(this.data.businessBody);
  1002. var applicationId = work.application;
  1003. this.chatTitleBusinessBtnNode.setStyles({"background-image": "url(../x_component_process_ApplicationExplorer/$Main/default/icon/application.png)", "display":"block"});
  1004. this.chatTitleBusinessBtnNode.store("work", work);
  1005. this.chatTitleBusinessBtnNode.addEvents({
  1006. "click": function(e) {
  1007. this.loadProcessWork(e.target.retrieve("work"));
  1008. e.preventDefault();
  1009. }.bind(this),
  1010. "mouseover": function() {
  1011. if (this.businessTipsNode) {
  1012. this.businessTipsNode.setStyle("display", "block");
  1013. } else {
  1014. this.businessTipsNode = new Element("div", {
  1015. "style": "position: absolute;right: 0;top: 30px;width: 200px;border: 1px solid #dedede;border-radius: 5px;padding: 8px;background: #ffffff;color: #666;text-align: left;overflow:hidden;white-space: nowrap;text-overflow: ellipsis;"
  1016. }).inject(this.chatTitleBusinessBtnNode);
  1017. var work = this.chatTitleBusinessBtnNode.retrieve("work")
  1018. this.businessTipsNode.set("text", this.lp.chooseBusinessWorkTitle + "【"+work.processName+"】"+work.title);
  1019. this.businessTipsNode.setStyle("display", "block");
  1020. }
  1021. }.bind(this),
  1022. "mouseout": function() {
  1023. if (this.businessTipsNode) {this.businessTipsNode.setStyle("display", "none");}
  1024. }.bind(this)
  1025. });
  1026. o2.Actions.load("x_processplatform_assemble_surface").ApplicationAction.getIcon(applicationId, function(json) {
  1027. if (json.data && json.data.icon) {
  1028. this.chatTitleBusinessBtnNode.setStyles({"background-image": "url(data:image/png;base64," + json.data.icon + ")", "display":"block"});
  1029. }
  1030. }.bind(this));
  1031. }
  1032. }
  1033. },
  1034. // 获取工作对象
  1035. loadProcessWork(work) {
  1036. if (work && work.job) {
  1037. o2.Actions.load("x_processplatform_assemble_surface").JobAction.findWorkWorkCompleted(work.job, function(json){
  1038. if (json.data ) {
  1039. var workList = [];
  1040. if (json.data.workList && json.data.workList.length > 0) {
  1041. workList = json.data.workList
  1042. }
  1043. var workCompletedList = [];
  1044. if (json.data.workCompletedList && json.data.workCompletedList.length > 0) {
  1045. workCompletedList = json.data.workCompletedList
  1046. }
  1047. this.showProcessWorkDialog(workList, workCompletedList);
  1048. }
  1049. }.bind(this), function(error){
  1050. console.error(error);
  1051. }.bind(this));
  1052. }
  1053. },
  1054. // 打开关联工作
  1055. showProcessWorkDialog: function(workList, workCompletedList) {
  1056. if (workList.length > 0 || workCompletedList.length > 0) {
  1057. var url = this.path + this.options.style + "/chooseBusinessWork.html";
  1058. this.container.loadHtml(url, { "bind": { "lp": this.lp }, "module": this }, function(){
  1059. // 工作展现
  1060. if (workList.length > 0) {
  1061. for (let index = 0; index < workList.length; index++) {
  1062. const work = workList[index];
  1063. var workItemNode = new Element("div", {"class":"business-work-item"}).inject(this.businessWorkListNode);
  1064. var workProcessNameNode = new Element("div", {"style":"flex: 1;"}).inject(workItemNode);
  1065. var title = work.title
  1066. if (title === "") {
  1067. title = this.lp.noTitle
  1068. }
  1069. workProcessNameNode.set("text", "【"+work.processName+"】" + title);
  1070. var openBtnNode = new Element("div", {"class":"business-work-item-btn"}).inject(workItemNode);
  1071. openBtnNode.store("work", work);
  1072. openBtnNode.set("text", this.lp.open);
  1073. openBtnNode.addEvents({
  1074. "click": function(e) {
  1075. var thisWork = e.target.retrieve("work");
  1076. if (thisWork) {
  1077. // var opotions = {
  1078. // "workId": thisWork.id,
  1079. // }
  1080. // layout.openApplication(null, "process.Work", opotions);
  1081. o2.api.form.openWork(thisWork.id, "", thisWork.title || "" );
  1082. }
  1083. this.closeProcessWorkDialog();
  1084. e.preventDefault();
  1085. }.bind(this)
  1086. })
  1087. }
  1088. }
  1089. if (workCompletedList.length > 0) {
  1090. for (let index = 0; index < workCompletedList.length; index++) {
  1091. const workCompleted = workCompletedList[index];
  1092. var workItemNode = new Element("div", {"class":"business-work-item"}).inject(this.businessWorkListNode);
  1093. var workProcessNameNode = new Element("div", {"style":"flex: 1;"}).inject(workItemNode);
  1094. var title = workCompleted.title
  1095. if (title === "") {
  1096. title = this.lp.noTitle
  1097. }
  1098. workProcessNameNode.set("text", "【"+workCompleted.processName+"】" + title);
  1099. var openBtnNode = new Element("div", {"class":"business-work-item-btn"}).inject(workItemNode);
  1100. openBtnNode.store("work", workCompleted);
  1101. openBtnNode.set("text", this.lp.open);
  1102. openBtnNode.addEvents({
  1103. "click": function(e) {
  1104. var thisWork = e.target.retrieve("work");
  1105. if (thisWork) {
  1106. // var opotions = {
  1107. // "workCompletedId": thisWork.id,
  1108. // }
  1109. // layout.openApplication(null, "process.Work", opotions);
  1110. o2.api.form.openWork(thisWork.id, "", thisWork.title || "" );
  1111. }
  1112. this.closeProcessWorkDialog();
  1113. e.preventDefault();
  1114. }.bind(this)
  1115. })
  1116. }
  1117. }
  1118. // 关闭
  1119. this.businessWorkChooseCloseBtnNode.addEvents({
  1120. "click": function(e) {
  1121. this.closeProcessWorkDialog();
  1122. e.preventDefault();
  1123. }.bind(this)
  1124. })
  1125. }.bind(this));
  1126. }
  1127. },
  1128. //
  1129. closeProcessWorkDialog: function() {
  1130. if (this.businessWorkChooseDialogNode) {
  1131. this.businessWorkChooseDialogNode.destroy();
  1132. this.businessWorkChooseDialogNode = null;
  1133. }
  1134. },
  1135. //检查是否有新消息
  1136. _checkNewMessage: function () {
  1137. if (this.conversationId && this.conversationId !== "") {//是否有会话窗口
  1138. var data = { "conversationId": this.conversationId };
  1139. o2.Actions.load("x_message_assemble_communicate").ImAction.msgListByPaging(1, 10, data, function (json) {
  1140. var list = json.data;
  1141. if (list && list.length > 0) {
  1142. for (var i = 0; i < list.length; i++) {
  1143. var isnew = true;
  1144. var m = list[i];
  1145. for (var j = 0; j < this.messageList.length; j++) {
  1146. if (this.messageList[j].id === m.id) {
  1147. isnew = false;
  1148. }
  1149. }
  1150. if (isnew) {
  1151. this.messageList.push(m);
  1152. this._buildMsgNode(m, false);
  1153. // this._refreshConvMessage(m);
  1154. }
  1155. }
  1156. }
  1157. }.bind(this), function (error) {
  1158. console.error(error);
  1159. }.bind(this), false);
  1160. }
  1161. },
  1162. // 撤回消息
  1163. _checkRevokeMsg: function(msg) {
  1164. if (this.conversationId && this.conversationId !== "") {//是否有会话窗口
  1165. if (msg.conversationId && msg.conversationId === this.conversationId) {
  1166. // 删除数据
  1167. this.messageList.splice(this.messageList.findIndex(e => e.id === msg.id), 1);
  1168. this._removeMsgNode(msg);
  1169. }
  1170. }
  1171. },
  1172. // 加载更多
  1173. loadMoreMsgList: function() {
  1174. this.page += 1;
  1175. this.loadMsgListByPage();
  1176. },
  1177. //分页获取会话的消息列表数据
  1178. loadMsgListByPage: function () {
  1179. if (this.isLoading) {
  1180. console.log("正在加载中。。。。。。");
  1181. return ;
  1182. }
  1183. var data = { "conversationId": this.conversationId };
  1184. this.isLoading = true;
  1185. if (this.page === 1) {
  1186. this.messageList = [];
  1187. }
  1188. o2.Actions.load("x_message_assemble_communicate").ImAction.msgListByPaging(this.page, this.pageSize, data, function (json) {
  1189. var list = json.data;
  1190. var size = 0;
  1191. if (list && list.length > 0) {
  1192. size = list.length;
  1193. for (var i = 0; i < list.length; i++) {
  1194. if (this.page == 1) {
  1195. this.messageList.push(list[i]);
  1196. } else {
  1197. this.messageList.unshift(list[i]);
  1198. }
  1199. this._buildMsgNode(list[i], true);
  1200. }
  1201. }
  1202. this.isLoading = false;
  1203. if (size < this.pageSize) { // 没有更多数据了
  1204. this.noMoreDataNode = new Element("div", {"class": "chat-no-more-data"}).inject(this.chatContentNode, "top");
  1205. this.noMoreDataNode.set("text", this.lp.msgLoadNoMoreData);
  1206. this.hasMoreMsgData = false;
  1207. } else {
  1208. if (this.noMoreDataNode) {
  1209. this.noMoreDataNode.destroy();
  1210. this.noMoreDataNode = null;
  1211. }
  1212. this.hasMoreMsgData = true;
  1213. }
  1214. }.bind(this), function (error) {
  1215. console.error(error);
  1216. this.isLoading = false;
  1217. }.bind(this), false);
  1218. },
  1219. // 群信息
  1220. tapConvInfo: function() {
  1221. this.chatTitleMoreMenuNode.setStyle("display", "none");
  1222. var convObj = null;
  1223. for (var i = 0; i < this.main.conversationNodeItemList.length; i++) {
  1224. var c = this.main.conversationNodeItemList[i];
  1225. if (this.conversationId == c.data.id) {
  1226. convObj = c.data;
  1227. }
  1228. }
  1229. if (convObj) {
  1230. var infoContainerNode = new Element("div", {"style":"padding:10px;background-color:#fff;overflow:auto;"});
  1231. new Element("div", {"style":"font-size: 16px;line-height: 32px;margin: 10px 0 0;", "text": this.lp.groupName}).inject(infoContainerNode);
  1232. new Element("div", {"style":"font-size: 14px;line-height: 26px;margin: 10px 20px 0;", "text": convObj.title}).inject(infoContainerNode);
  1233. new Element("div", {"style":"font-size: 16px;line-height: 32px;margin: 10px 0 0;", "text": this.lp.groupMemberAdmin}).inject(infoContainerNode);
  1234. var adminPerson = convObj.adminPerson || "";
  1235. var adminName = adminPerson;
  1236. if (adminPerson.indexOf("@") != -1) {
  1237. adminName = adminPerson.substring(0, adminPerson.indexOf("@"));
  1238. }
  1239. new Element("div", {"style":"font-size: 14px;line-height: 26px;margin: 10px 20px 0;", "text": adminName}).inject(infoContainerNode);
  1240. new Element("div", {"style":"font-size: 16px;line-height: 32px;margin: 10px 0 0;", "text": this.lp.groupMember}).inject(infoContainerNode);
  1241. var memberListContainer = new Element("div", {"style":"margin: 10px 20px;display:flex; flex-wrap:wrap;"}).inject(infoContainerNode);
  1242. var personList = convObj.personList || [];
  1243. for (let index = 0; index < personList.length; index++) {
  1244. const person = personList[index];
  1245. var memberDiv = new Element("div", {"style":"display:flex; flex-direction: column;padding: 10px;align-items: center;"}).inject(memberListContainer);
  1246. var avatarUrl = this.main._getIcon(person);
  1247. new Element("img", { "src": avatarUrl, "style": "width:40px;height:40px;" }).inject(memberDiv);
  1248. var name = person;
  1249. if (person.indexOf("@") != -1) {
  1250. name = name.substring(0, person.indexOf("@"));
  1251. }
  1252. new Element("div", { "text": name, "style": "margin-top:10px;" }).inject(memberDiv);
  1253. }
  1254. var dlg = o2.DL.open({
  1255. "title": this.lp.openGroupInfo,
  1256. "mask": true,
  1257. "width": "500",
  1258. "height": "430",
  1259. "content": infoContainerNode,
  1260. "onQueryClose": function () {
  1261. infoContainerNode.destroy();
  1262. }.bind(this),
  1263. "buttonList": [
  1264. {
  1265. "type": "ok",
  1266. "text": this.lp.ok,
  1267. "action": function () {
  1268. dlg.close();
  1269. }.bind(this)
  1270. }
  1271. ],
  1272. "onPostShow": function () {
  1273. dlg.reCenter();
  1274. }.bind(this),
  1275. "onPostClose": function(){
  1276. dlg = null;
  1277. }.bind(this)
  1278. });
  1279. }
  1280. },
  1281. //修改群名
  1282. tapUpdateConvTitle: function () {
  1283. this.chatTitleMoreMenuNode.setStyle("display", "none");
  1284. var title = "";
  1285. for (var i = 0; i < this.main.conversationNodeItemList.length; i++) {
  1286. var c = this.main.conversationNodeItemList[i];
  1287. if (this.conversationId == c.data.id) {
  1288. title = c.data.title;
  1289. }
  1290. }
  1291. var form = new MWF.xApplication.IMV2.UpdateConvTitleForm(this.main, {}, {"defaultValue": title}, { app: this.main.app });
  1292. form.create();
  1293. },
  1294. //修改群成员
  1295. tapUpdateConvMembers: function () {
  1296. this.chatTitleMoreMenuNode.setStyle("display", "none");
  1297. var members = [];
  1298. for (var i = 0; i < this.main.conversationNodeItemList.length; i++) {
  1299. var c = this.main.conversationNodeItemList[i];
  1300. if (this.conversationId == c.data.id) {
  1301. members = c.data.personList;
  1302. }
  1303. }
  1304. var form = new MWF.xApplication.IMV2.CreateConversationForm(this.main, {}, { "title": this.lp.modifyMember, "personCount": 0, "personSelected": members, "isUpdateMember": true }, { app: this.main.app });
  1305. form.create()
  1306. },
  1307. // 点击菜单 删除会话
  1308. tapDeleteConversation: function(e) {
  1309. var _self = this;
  1310. var con = null;
  1311. for (var i = 0; i < this.main.conversationNodeItemList.length; i++) {
  1312. var c = this.main.conversationNodeItemList[i];
  1313. if (this.conversationId == c.data.id) {
  1314. con = c.data;
  1315. break;
  1316. }
  1317. }
  1318. if (con) {
  1319. var msg = this.lp.messageDeleteSingleConversationAlert;
  1320. if (con.type === "single") {
  1321. msg = this.lp.messageDeleteSingleConversationAlert;
  1322. } else {
  1323. msg = this.lp.messageDeleteGroupConversationAlert;
  1324. }
  1325. MWF.xDesktop.confirm("info", this.chatTitleNode, this.lp.alert, msg, 400, 150, function() {
  1326. if (con.type === "single") {
  1327. _self.deleteSingleConversation();
  1328. } else {
  1329. _self.deleteGroupConversation();
  1330. }
  1331. this.close();
  1332. }, function(){
  1333. this.close();
  1334. }, null, null, "o2");
  1335. } else {
  1336. console.error('没有找到会话对象。。。。。');
  1337. }
  1338. },
  1339. // 删除群聊
  1340. deleteGroupConversation: function() {
  1341. o2.Actions.load("x_message_assemble_communicate").ImAction.deleteGroupConversation(this.conversationId, function (json) {
  1342. this.main.refresh();
  1343. }.bind(this), function (error) {
  1344. console.error(error);
  1345. this.app.notice(error, "error", this.app.content);
  1346. }.bind(this));
  1347. },
  1348. deleteSingleConversation: function() {
  1349. o2.Actions.load("x_message_assemble_communicate").ImAction.deleteSingleConversation(this.conversationId, function (json) {
  1350. this.main.refresh();
  1351. }.bind(this), function (error) {
  1352. console.error(error);
  1353. this.app.notice(error, "error", this.app.content);
  1354. }.bind(this));
  1355. },
  1356. _reclickConv: function() {
  1357. for (var i = 0; i < this.main.conversationNodeItemList.length; i++) {
  1358. var c = this.main.conversationNodeItemList[i];
  1359. if (this.conversationId == c.data.id) {
  1360. this.main.tapConv(c.data);
  1361. }
  1362. }
  1363. },
  1364. //创建图片或文件消息
  1365. _newImageOrFileMsgAndSend: function (type, fileId, fileName, fileExt) {
  1366. var distinguishedName = layout.session.user.distinguishedName;
  1367. var time = this._currentTime();
  1368. var body = {
  1369. "body": type === "image" ? this.lp.msgTypeImage : this.lp.file,
  1370. "type": type,
  1371. "fileId": fileId,
  1372. "fileExtension": fileExt,
  1373. "fileName": fileName
  1374. };
  1375. var bodyJson = JSON.stringify(body);
  1376. var uuid = new MWF.widget.UUID().createTrueUUID();
  1377. var message = {
  1378. "id": uuid,
  1379. "conversationId": this.conversationId,
  1380. "body": bodyJson,
  1381. "createPerson": distinguishedName,
  1382. "createTime": time,
  1383. "sendStatus": 1
  1384. };
  1385. o2.Actions.load("x_message_assemble_communicate").ImAction.msgCreate(message,
  1386. function (json) {
  1387. console.log(this.lp.sendSuccess);
  1388. }.bind(this),
  1389. function (error) {
  1390. console.error(error);
  1391. }.bind(this));
  1392. this.messageList.push(message);
  1393. this._buildReceiver(body, distinguishedName, false, message);
  1394. this.main._refreshConvMessage(message);
  1395. },
  1396. //创建文本消息 并发送
  1397. _newAndSendTextMsg: function (text, type) {
  1398. var distinguishedName = layout.session.user.distinguishedName;
  1399. var time = this._currentTime();
  1400. var body = { "body": text, "type": type };
  1401. var bodyJson = JSON.stringify(body);
  1402. var uuid = new MWF.widget.UUID().createTrueUUID();
  1403. var textMessage = {
  1404. "id": uuid,
  1405. "conversationId": this.conversationId,
  1406. "body": bodyJson,
  1407. "createPerson": distinguishedName,
  1408. "createTime": time,
  1409. "sendStatus": 1
  1410. };
  1411. if (this.quoteMessage && this.quoteMessage.id) {
  1412. textMessage.quoteMessageId = this.quoteMessage.id;
  1413. textMessage.quoteMessage = this.quoteMessage;
  1414. }
  1415. o2.Actions.load("x_message_assemble_communicate").ImAction.msgCreate(textMessage,
  1416. function (json) {
  1417. console.log(this.lp.sendSuccess);
  1418. }.bind(this),
  1419. function (error) {
  1420. console.error(error);
  1421. }.bind(this));
  1422. this.messageList.push(textMessage);
  1423. this._buildReceiver(body, distinguishedName, false, textMessage);
  1424. this.main._refreshConvMessage(textMessage);
  1425. this.deleteQuoteMessage();
  1426. },
  1427. // 创建引用消息的 Node 节点
  1428. _newQuoteMessageElement: function (msg, parentNode) {
  1429. var name = msg.createPerson;
  1430. if (msg.createPerson.indexOf("@") !== -1) {
  1431. name = name.substring(0, msg.createPerson.indexOf("@"));
  1432. }
  1433. name += ": ";
  1434. var msgBody = JSON.parse(msg.body);
  1435. if (msgBody.type !== "emoji" && msgBody.type !== "image") {
  1436. name += this.contentEscapeBackToSymbol(msgBody.body)
  1437. if (msgBody.type === "file") {
  1438. name += " " + msgBody.fileName;
  1439. }
  1440. }
  1441. let quoteMessageNode = new Element("div", {"class": "quote-message-box"}).inject(parentNode);
  1442. new Element("div", {"text": name , "class": "quote-message-desc" }).inject(quoteMessageNode)
  1443. if (msgBody.type === "emoji") {
  1444. var img = "";
  1445. for (var i = 0; i < this.main.emojiList.length; i++) {
  1446. if (msgBody.body === this.main.emojiList[i].key) {
  1447. img = this.main.emojiList[i].path;
  1448. }
  1449. }
  1450. new Element("img", { "src": img, "class": "quote-message-emoji" }).inject(quoteMessageNode);
  1451. } else if (msgBody.type === "image") {
  1452. var url = this._getFileUrlWithWH(msgBody.fileId, 48, 48);
  1453. if (msgBody.fileExtension && msgBody.fileExtension.toLowerCase() === "webp") {
  1454. url = this._getFileDownloadUrl(msgBody.fileId);
  1455. }
  1456. new Element("img", { "src": url, "class": "quote-message-image" }).inject(quoteMessageNode);
  1457. }
  1458. return quoteMessageNode;
  1459. },
  1460. // 添加引用消息
  1461. addQuoteMessage: function (msg) {
  1462. if (this.quoteMessage) {
  1463. this.deleteQuoteMessage();
  1464. }
  1465. this.quoteMessage = msg;
  1466. if (!this.quoteMessage) {
  1467. console.error('引用消息为空!!!!');
  1468. return;
  1469. }
  1470. let node = this._newQuoteMessageElement(msg, this.chatBottomAreaQuoteMessageNode);
  1471. // var name = msg.createPerson;
  1472. // if (msg.createPerson.indexOf("@") !== -1) {
  1473. // name = name.substring(0, msg.createPerson.indexOf("@"));
  1474. // }
  1475. // name += ": ";
  1476. // var msgBody = JSON.parse(msg.body);
  1477. // if (msgBody.type !== "emoji") {
  1478. // name += this.contentEscapeBackToSymbol(msgBody.body)
  1479. // }
  1480. // let quoteMessageNode = new Element("div", {"class": "quote-message-box"}).inject(this.chatBottomAreaQuoteMessageNode);
  1481. // new Element("div", {"text": name , "class": "quote-message-desc" }).inject(quoteMessageNode)
  1482. // if (msgBody.type === "emoji") {
  1483. // var img = "";
  1484. // for (var i = 0; i < this.main.emojiList.length; i++) {
  1485. // if (msgBody.body === this.main.emojiList[i].key) {
  1486. // img = this.main.emojiList[i].path;
  1487. // }
  1488. // }
  1489. // new Element("img", { "src": img, "class": "quote-message-emoji" }).inject(quoteMessageNode);
  1490. // }
  1491. let closeNode = new Element("div", {"class": "quote-message-close", "title": "关闭"}).inject(node)
  1492. closeNode.addEvent("click", function (){
  1493. this.deleteQuoteMessage()
  1494. }.bind(this))
  1495. },
  1496. deleteQuoteMessage: function () {
  1497. this.quoteMessage = null;
  1498. for (const child of this.chatBottomAreaQuoteMessageNode.children) {
  1499. child.remove()
  1500. }
  1501. },
  1502. //点击发送消息
  1503. sendMsg: function () {
  1504. var text = this.chatBottomAreaTextareaNode.value;
  1505. if (text) {
  1506. this.chatBottomAreaTextareaNode.value = "";
  1507. this._newAndSendTextMsg(text, "text");
  1508. } else {
  1509. console.log(this.lp.noMessage);
  1510. this.app.notice(this.lp.noMessage, "error", this.app.content);
  1511. }
  1512. },
  1513. forwardMsgList: function (msgList) {
  1514. // 先选择会话
  1515. MWF.xDesktop.requireApp("IMV2", "Starter", function () {
  1516. var share = new MWF.xApplication.IMV2.ShareToConversation({
  1517. msgBody: {},
  1518. callback: function (conversation) {
  1519. console.debug("选择了会话 " + conversation.title)
  1520. this._forwardMsgList(conversation, msgList)
  1521. }.bind(this)
  1522. }, this.app);
  1523. share.load();
  1524. }.bind(this));
  1525. },
  1526. _forwardMsgList: function (conversation, msgList) {
  1527. var time = this._currentTime();
  1528. for (let i = 0; i < msgList.length; i++) {
  1529. let msg = msgList[i];
  1530. msg.id = new MWF.widget.UUID().createTrueUUID();
  1531. msg.conversationId = conversation.id;
  1532. msg.createTime = time;
  1533. o2.Actions.load("x_message_assemble_communicate").ImAction.msgCreate(msg,
  1534. function (json) {
  1535. console.log(this.lp.sendSuccess);
  1536. }.bind(this),
  1537. function (error) {
  1538. console.error(error);
  1539. }.bind(this));
  1540. if (conversation.id === this.conversationId) {
  1541. this.messageList.push(msg);
  1542. this._buildReceiver(JSON.parse(msg.body), msg.createPerson, false, msg);
  1543. }
  1544. this.main._refreshConvMessage(msg);
  1545. }
  1546. },
  1547. // 逐条转发
  1548. forwardOneByOne: function () {
  1549. if (this.selectMsgList.length < 1) {
  1550. this.app.notice(this.lp.msgNeedSelectMessage, "error", this.app.content);
  1551. return;
  1552. }
  1553. this.forwardMsgList(this.selectMsgList)
  1554. this.cancelSelectMode()
  1555. },
  1556. // 合并转发
  1557. forwardMerge: function () {
  1558. if (this.selectMsgList.length < 1) {
  1559. this.app.notice(this.lp.msgNeedSelectMessage, "error", this.app.content);
  1560. return;
  1561. }
  1562. let list = this.selectMsgList.slice();
  1563. // 倒序
  1564. list.sort(function (a, b) {
  1565. return new Date(b.createTime) - new Date(a.createTime);
  1566. })
  1567. var descList = [];
  1568. if (list.length > 4) {
  1569. descList = list.slice(0, 4);
  1570. } else {
  1571. descList = list.slice();
  1572. }
  1573. var desc = '';
  1574. for (var i = 0; i < descList.length; i++) {
  1575. var msg = descList[i];
  1576. var name = msg.createPerson;
  1577. if (msg.createPerson.indexOf("@") != -1) {
  1578. name = name.substring(0, msg.createPerson.indexOf("@"));
  1579. }
  1580. var body = JSON.parse(msg.body)
  1581. var content = body.body;
  1582. if (body.type === "text") {
  1583. content = this.contentEscapeBackToSymbol(body.body)
  1584. } else if (body.type === "emoji") {
  1585. content = this.lp.msgTypeEmoji;
  1586. }
  1587. desc += name + ": " + content + "\n"
  1588. }
  1589. var title = "群聊的聊天记录"
  1590. if (this.data.type === "single") {
  1591. title = this.data.personList.map((p) => {
  1592. var name = p;
  1593. if (p.indexOf("@") != -1) {
  1594. name = p.substring(0, p.indexOf("@"));
  1595. }
  1596. return name;
  1597. }).join(",") + "的聊天记录"
  1598. }
  1599. var distinguishedName = layout.session.user.distinguishedName;
  1600. var body = {
  1601. "body": this.lp.msgTypeHistory,
  1602. "type": "messageHistory",
  1603. "messageHistoryTitle":title,
  1604. "messageHistoryDesc":desc,
  1605. "messageHistoryIds": list.map((e)=> e.id)
  1606. };
  1607. var bodyJson = JSON.stringify(body);
  1608. var message = {
  1609. "id": "",
  1610. "conversationId": this.conversationId,
  1611. "body": bodyJson,
  1612. "createPerson": distinguishedName,
  1613. "createTime": "",
  1614. "sendStatus": 1
  1615. };
  1616. this.forwardMsgList([message])
  1617. this.cancelSelectMode()
  1618. },
  1619. // 收藏 选中的消息
  1620. collectionMsgs: function () {
  1621. if (this.selectMsgList.length < 1) {
  1622. this.app.notice(this.lp.msgNeedSelectMessage, "error", this.app.content);
  1623. return;
  1624. }
  1625. let list = this.selectMsgList.slice();
  1626. // 顺序
  1627. list.sort(function (a, b) {
  1628. return new Date(a.createTime) - new Date(b.createTime);
  1629. })
  1630. this.collectionMsgList(list);
  1631. this.cancelSelectMode()
  1632. },
  1633. collectionMsgList: function (msgList) {
  1634. var body = {
  1635. msgIdList: msgList.map((e) => e.id)
  1636. }
  1637. o2.Actions.load("x_message_assemble_communicate").ImAction.msgCollectionSave(body,
  1638. function (json) {
  1639. this.app.notice(this.lp.msgCollectionSuccess, "success", this.app.content);
  1640. }.bind(this),
  1641. function (error) {
  1642. console.error(error);
  1643. }.bind(this));
  1644. },
  1645. // 选择模式
  1646. openSelectMode: function(msg) {
  1647. this.selectMode = true;
  1648. this.selectMsgList = [];
  1649. const list = this.chatContentNode.querySelectorAll(".chat-msg-checkbox")
  1650. list.forEach(item => {
  1651. item.classList.remove("none")
  1652. item.classList.add("block")
  1653. })
  1654. this.chatBottomAreaNode.classList.remove("block")
  1655. this.chatBottomAreaNode.classList.add("none")
  1656. this.chatBottomSelectModeAreaNode.classList.remove("none")
  1657. this.chatBottomSelectModeAreaNode.classList.add("block")
  1658. this._selectOrUnSelectMsg(msg)
  1659. },
  1660. // 取消选择模式
  1661. cancelSelectMode: function () {
  1662. this.selectMode = false;
  1663. this.selectMsgList = [];
  1664. const list = this.chatContentNode.querySelectorAll(".chat-msg-checkbox")
  1665. debugger
  1666. list.forEach(item => {
  1667. item.classList.remove("block")
  1668. item.classList.add("none")
  1669. })
  1670. this.chatBottomSelectModeAreaNode.classList.remove("block")
  1671. this.chatBottomSelectModeAreaNode.classList.add("none")
  1672. this.chatBottomAreaNode.classList.remove("none")
  1673. this.chatBottomAreaNode.classList.add("block")
  1674. this._selectOrUnSelectMsg()
  1675. },
  1676. dragEnterOverEvent: function (e) {
  1677. this.chatNode.classList.add("drag-area");
  1678. },
  1679. dragLeaveEvent: function (e) {
  1680. this.chatNode.classList.remove("drag-area");
  1681. },
  1682. // 拖拽发送文件消息
  1683. dragDropFileSendMsg: function (e) {
  1684. console.log('拖拽了文件', e)
  1685. if (e && e.dataTransfer && e.dataTransfer.files) {
  1686. const files = e.dataTransfer.files
  1687. console.log('拖拽了文件', files);
  1688. [...files].forEach((file)=> {
  1689. if (file.type && file.type !== '') {
  1690. this.sendFileMsg(file)
  1691. }
  1692. });
  1693. }
  1694. },
  1695. // 从剪贴板 复制 文件上传并发送消息
  1696. pasteFileSendMsg: function (e) {
  1697. // 获取粘贴的内容
  1698. const items = e.clipboardData.items;
  1699. // 遍历剪贴板中的所有项目
  1700. for (let i = 0; i < items.length; i++) {
  1701. const item = items[i];
  1702. // 判断是否为文件类型
  1703. if (item.kind === 'file') {
  1704. const file = item.getAsFile();
  1705. if (file) {
  1706. console.log('粘贴的文件:', file);
  1707. this.sendFileMsg(file)
  1708. }
  1709. } else if (item.type.indexOf('image') > -1) {
  1710. // 处理图片类型,可以通过 getAsFile 获取 Blob 对象
  1711. const file = item.getAsFile();
  1712. if (file) {
  1713. console.log('粘贴的图片:', file);
  1714. this.sendFileMsg(file)
  1715. }
  1716. }
  1717. }
  1718. },
  1719. // 点击发送文件消息
  1720. showChooseFile: function () {
  1721. if (!this.uploadFileAreaNode) {
  1722. this.createUploadFileNode();
  1723. }
  1724. this.fileUploadNode.click();
  1725. },
  1726. // 检测浏览器是否支持WebP
  1727. _canUseWebP: function() {
  1728. var elem = document.createElement('canvas');
  1729. if (elem.getContext && elem.getContext('2d')) {
  1730. return elem.toDataURL('image/webp').indexOf('data:image/webp') === 0;
  1731. }
  1732. return false;
  1733. },
  1734. //创建文件选择框
  1735. createUploadFileNode: function () {
  1736. this.uploadFileAreaNode = new Element("div");
  1737. var html = "<input name=\"file\" type=\"file\" multiple/>";
  1738. this.uploadFileAreaNode.set("html", html);
  1739. this.fileUploadNode = this.uploadFileAreaNode.getFirst();
  1740. this.fileUploadNode.addEvent("change", function () {
  1741. var files = this.fileUploadNode.files;
  1742. if (files.length) {
  1743. var file = files.item(0);
  1744. this.sendFileMsg(file)
  1745. }
  1746. }.bind(this));
  1747. },
  1748. sendFileMsg: function (file) {
  1749. var formData = new FormData();
  1750. formData.append('file', file);
  1751. formData.append('fileName', file.name);
  1752. var fileExt = file.name.substring(file.name.lastIndexOf("."));
  1753. // 图片消息
  1754. var type = "file"
  1755. if (fileExt.toLowerCase() === ".webp" && this._canUseWebP()) {
  1756. type = "image"
  1757. } else if (fileExt.toLowerCase() === ".bmp" || fileExt.toLowerCase() === ".jpeg"
  1758. || fileExt.toLowerCase() === ".png" || fileExt.toLowerCase() === ".jpg") {
  1759. type = "image"
  1760. } else { // 文件消息
  1761. type = "file"
  1762. }
  1763. //上传文件
  1764. o2.Actions.load("x_message_assemble_communicate").ImAction.uploadFile(this.conversationId, type, formData, "{}", function (json) {
  1765. if (json.data) {
  1766. var fileId = json.data.id
  1767. var fileExtension = json.data.fileExtension
  1768. var fileName = json.data.fileName
  1769. this._newImageOrFileMsgAndSend(type, fileId, fileName, fileExtension)
  1770. }
  1771. }.bind(this), function (error) {
  1772. console.error(error);
  1773. }.bind(this))
  1774. },
  1775. //点击表情按钮
  1776. showEmojiBox: function (){
  1777. if (!this.emojiBoxNode) {
  1778. this.emojiBoxNode = new Element("div", { "class": "chat-emoji-box" }).inject(this.container);
  1779. var _self = this;
  1780. for (var i = 0; i < this.main.emojiList.length; i++) {
  1781. var emoji = this.main.emojiList[i];
  1782. var emojiNode = new Element("img", { "src": emoji.path, "class": "chat-emoji-img" }).inject(this.emojiBoxNode);
  1783. emojiNode.addEvents({
  1784. "mousedown": function (ev) {
  1785. _self.sendEmojiMsg(this.emoji);
  1786. _self.hideEmojiBox();
  1787. }.bind({ emoji: emoji })
  1788. });
  1789. }
  1790. }
  1791. this.emojiBoxNode.setStyle("display", "block");
  1792. this.hideFun = this.hideEmojiBox.bind(this);
  1793. document.body.addEvent("mousedown", this.hideFun);
  1794. },
  1795. hideEmojiBox: function () {
  1796. //关闭emojiBoxNode
  1797. this.emojiBoxNode.setStyle("display", "none");
  1798. document.body.removeEvent("mousedown", this.hideFun);
  1799. },
  1800. showEmojiV2: function () {
  1801. if (!this.isLoadEmojiV2) {
  1802. for (let i = 0; i < this.main.emojiV2TypeList.length; i++) {
  1803. let type = this.main.emojiV2TypeList[i];
  1804. let typeNode = new Element("div", {"class": "im-chat-emoji-item"}).inject(this.emojiTypeListContainerNode);
  1805. let className = "btn";
  1806. if (i === 0) {
  1807. className += " active"
  1808. }
  1809. let btnNode = new Element("div", {"class": className}).inject(typeNode);
  1810. new Element("img", {"src": "../x_component_IMV2/$Main/default/icons/emoji_type_" + type + ".png"}).inject(btnNode);
  1811. typeNode.store("type", type);
  1812. typeNode.addEvent("click", function (e){
  1813. this._clickEmojiV2TypeBtn(e)
  1814. }.bind(this))
  1815. }
  1816. this._renderEmojiV2List(this.main.emojiV2Object[this.main.emojiV2TypeList[0]]);
  1817. this.isLoadEmojiV2 = true;
  1818. }
  1819. this.emojiMaskNode.classList.remove('none');
  1820. },
  1821. _renderEmojiV2List: function (list) {
  1822. this.emojiListContainerNode.empty()
  1823. this.currentEmojiV2List = list;
  1824. for (let i = 0; i < this.currentEmojiV2List.length; i++) {
  1825. let emoji = this.currentEmojiV2List[i];
  1826. let emojiNode = new Element("div", {"class": "im-chat-emoji-item"}).inject(this.emojiListContainerNode);
  1827. emojiNode.set("text", emoji)
  1828. emojiNode.store("emoji", emoji)
  1829. emojiNode.addEvent("click", function (e){
  1830. this._clickEmojiV2Item(e)
  1831. }.bind(this))
  1832. }
  1833. },
  1834. // 点击表情类型
  1835. _clickEmojiV2TypeBtn: function (e) {
  1836. let target = e.event.currentTarget;
  1837. let type = target.retrieve("type");
  1838. console.debug('点击了 表情类型 ' + type);
  1839. this._renderEmojiV2List(this.main.emojiV2Object[type]);
  1840. let list = this.emojiTypeListContainerNode.children;
  1841. for (let i = 0; i < list.length; i++) {
  1842. let child = list[i];
  1843. child.firstChild.classList.remove('active');
  1844. }
  1845. target.firstChild.classList.add('active')
  1846. },
  1847. // 点击表情
  1848. _clickEmojiV2Item: function (e) {
  1849. let emoji = e.target.retrieve("emoji");
  1850. let text = this.chatBottomAreaTextareaNode.value;
  1851. this.chatBottomAreaTextareaNode.value = text + emoji;
  1852. // this.closeEmojiMaskV2()
  1853. },
  1854. closeEmojiMaskV2: function () {
  1855. this.emojiMaskNode.classList.add('none')
  1856. },
  1857. clickStopCloseEmojiMaskV2: function (e) {
  1858. e.stopPropagation()
  1859. },
  1860. //发送表情消息
  1861. sendEmojiMsg: function (emoji) {
  1862. this._newAndSendTextMsg(emoji.key, "emoji");
  1863. },
  1864. _selectOrUnSelectMsg: function (msg) {
  1865. if (msg) {
  1866. if (this.selectMsgList.findIndex( m => m.id === msg.id) > -1) {
  1867. this.selectMsgList.splice(this.selectMsgList.findIndex( m => m.id === msg.id), 1);
  1868. } else {
  1869. this.selectMsgList.push(msg);
  1870. }
  1871. }
  1872. var checkList = this.chatContentNode.querySelectorAll(".check-box-select-item")
  1873. checkList.forEach(item => {
  1874. var checkMsg = item.retrieve("msg")
  1875. if (this.selectMsgList.findIndex( m => m.id === checkMsg.id) > -1) {
  1876. item.checked = true
  1877. } else {
  1878. item.checked = false
  1879. }
  1880. })
  1881. },
  1882. // 点击消息 包含 选择 和 打开 消息
  1883. _clickMsgItem: function (e, isQuoteMsg) {
  1884. e.stopPropagation();
  1885. console.debug('点击消息,isQuoteMsg ' + isQuoteMsg);
  1886. var msg = e.event.currentTarget.retrieve("msg");
  1887. if (!msg || !msg.body) {
  1888. console.error('错误的 target!!!')
  1889. return;
  1890. }
  1891. if (this.selectMode) {
  1892. if (isQuoteMsg) {
  1893. return;
  1894. }
  1895. this._selectOrUnSelectMsg(msg)
  1896. } else {
  1897. this.openMsgItem(msg)
  1898. }
  1899. },
  1900. // 打开消息
  1901. openMsgItem: function (msg) {
  1902. var msgBody = JSON.parse(msg.body);
  1903. if (msgBody.type === "image") {
  1904. window.open(this._getFileDownloadUrl(msgBody.fileId));
  1905. } else if (msgBody.type === "process") {
  1906. o2.api.form.openWork(msgBody.work, "", title || "" );
  1907. } else if (msgBody.type === "messageHistory") {
  1908. console.debug('聊天记录点击')
  1909. this._openMessageHistory(msg)
  1910. } else if (msgBody.type === "file") {
  1911. // 有安装 onlyOffice
  1912. if (layout.serviceAddressList["x_onlyofficefile_assemble_control"]
  1913. && this.main.imConfig.enableOnlyOfficePreview && msgBody.fileExtension
  1914. && (msgBody.fileExtension.toLowerCase() === "docx" || msgBody.fileExtension.toLowerCase() === "doc"
  1915. || msgBody.fileExtension.toLowerCase() === "xls" || msgBody.fileExtension.toLowerCase() === "xlsx"
  1916. || msgBody.fileExtension.toLowerCase() === "ppt" || msgBody.fileExtension.toLowerCase() === "pptx"
  1917. || msgBody.fileExtension.toLowerCase() === "pdf" || msgBody.fileExtension.toLowerCase() === "csv"
  1918. || msgBody.fileExtension.toLowerCase() === "txt")) {
  1919. var onlyOfficeUrl = "../o2_lib/onlyoffice/index.html?fileName=" +msgBody.fileName+ "&file=" + this._getFileDownloadUrl(msgBody.fileId);
  1920. window.open(onlyOfficeUrl);
  1921. return;
  1922. } else if (msgBody.fileExtension && (msgBody.fileExtension.toLowerCase() === "mp4" || msgBody.fileExtension.toLowerCase() === "avi" || msgBody.fileExtension.toLowerCase() === "ogg")) {
  1923. console.log('视频文件无需下载!')
  1924. return;
  1925. }
  1926. window.open(this._getFileDownloadUrl(msgBody.fileId));
  1927. } else if (msgBody.type === "location") {
  1928. var url = this._getBaiduMapUrl(msgBody.latitude, msgBody.longitude, msgBody.address, msgBody.addressDetail);
  1929. window.open(url);
  1930. }
  1931. },
  1932. // 打开收藏的消息
  1933. openMyCollection: function () {
  1934. let id = 'myCollectionFlag';// 这个作为一个标识
  1935. let msg = {
  1936. id: id
  1937. }
  1938. if (!this.messageHistoryMap) {
  1939. this.messageHistoryMap = new Map();
  1940. }
  1941. // 遮罩层
  1942. if (!this.messageHistoryNode) {
  1943. this.messageHistoryNode = new Element("div", {"class": "chat-msg-list-container"}).inject(this.chatNode);
  1944. }
  1945. if (this.messageHistoryMap.has(msg.id)) {
  1946. this.closeMessageHistory(msg)
  1947. }
  1948. // collectionMode 标识收藏
  1949. const el = new MWF.xApplication.IMV2.ChatMessageList({title: this.lp.msgCollectionTitle, msg: msg, collectionMode: true}, this);
  1950. this.messageHistoryMap.set(msg.id, el)
  1951. },
  1952. // 打开一个聊天记录
  1953. _openMessageHistory: function (msg) {
  1954. if (!this.messageHistoryMap) {
  1955. this.messageHistoryMap = new Map();
  1956. }
  1957. // 遮罩层
  1958. if (!this.messageHistoryNode) {
  1959. this.messageHistoryNode = new Element("div", {"class": "chat-msg-list-container"}).inject(this.chatNode);
  1960. }
  1961. if (this.messageHistoryMap.has(msg.id)) {
  1962. this.closeMessageHistory(msg)
  1963. }
  1964. const el = new MWF.xApplication.IMV2.ChatMessageList({title: this.lp.msgHistory, msg: msg}, this);
  1965. this.messageHistoryMap.set(msg.id, el)
  1966. },
  1967. // 关闭某一个聊天记录
  1968. closeMessageHistory: function (msg) {
  1969. if (this.messageHistoryMap.has(msg.id)) {
  1970. this.messageHistoryMap.get(msg.id).deleteSelfNode()
  1971. this.messageHistoryMap.delete(msg.id) // 删除
  1972. }
  1973. // 关闭遮罩层
  1974. if (this.messageHistoryMap.size < 1 && this.messageHistoryNode) {
  1975. this.messageHistoryNode.destroy()
  1976. this.messageHistoryNode = null;
  1977. }
  1978. },
  1979. // 撤回、删除 消息
  1980. _removeMsgNode: function(msg) {
  1981. var itemNode = this.chatContentNode.getElement("#"+msg.id);
  1982. if (itemNode) {
  1983. var beforeNode = itemNode.getPrevious();
  1984. itemNode.destroy();
  1985. if (beforeNode) {
  1986. beforeNode.destroy();
  1987. }
  1988. }
  1989. },
  1990. //创建消息html节点
  1991. _buildMsgNode: function (msg, isTop) {
  1992. var createPerson = msg.createPerson;
  1993. var jsonbody = msg.body;
  1994. var body = JSON.parse(jsonbody);
  1995. var distinguishedName = layout.session.user.distinguishedName;
  1996. if (createPerson != distinguishedName) {
  1997. this._buildSender(body, createPerson, isTop, msg);
  1998. } else {
  1999. this._buildReceiver(body, createPerson, isTop, msg);
  2000. }
  2001. },
  2002. /**
  2003. * 消息接收对象
  2004. * 这里的方法名错了两者互换了无需理会
  2005. * @param msgBody 消息体
  2006. * @param createPerson 消息人员
  2007. * @param isTop 是否放在顶部
  2008. * @param msg 消息对象
  2009. */
  2010. _buildSender: function (msgBody, createPerson, isTop, msg) {
  2011. if (!isTop) {
  2012. // 添加消息时间
  2013. this._buildMsgTime(isTop, msg);
  2014. }
  2015. var msgItemNode = new Element("div", {"class": "chat-msg"}).inject(this.chatContentNode, isTop ? "top" : "bottom");
  2016. var checkBoxClass = "chat-msg-checkbox none"
  2017. if (this.selectMode) {
  2018. checkBoxClass = "chat-msg-checkbox block"
  2019. }
  2020. var msgItemCheckBoxNode = new Element("div", {"class": checkBoxClass}).inject(msgItemNode);
  2021. var msgItemCheckBoxInputNode = new Element("input", {"type": "checkbox", "class": "check-box-select-item"}).inject(msgItemCheckBoxNode);
  2022. msgItemCheckBoxInputNode.store("msg", msg)
  2023. msgItemCheckBoxInputNode.addEvents({
  2024. "click": function(e) {
  2025. this._clickMsgItem(e);
  2026. }.bind(this)
  2027. })
  2028. var receiverBodyNode = new Element("div", { "class": "chat-sender", "id": msg.id}).inject(msgItemNode);
  2029. this._addContextMenuEvent(receiverBodyNode, msg);
  2030. var avatarNode = new Element("div", {"class": "chat-sender-avatar"}).inject(receiverBodyNode);
  2031. var avatarUrl = this.main._getIcon(createPerson);
  2032. var name = createPerson;
  2033. if (createPerson.indexOf("@") != -1) {
  2034. name = name.substring(0, createPerson.indexOf("@"));
  2035. }
  2036. var avatarImg = new Element("img", { "src": avatarUrl }).inject(avatarNode);
  2037. var nameNode = new Element("div", { "text": name , "class": "chat-sender-name"}).inject(receiverBodyNode);
  2038. var lastNodeClass = "chat-sender-box"
  2039. if (msgBody.type === "process" || msgBody.type === "cms") {
  2040. lastNodeClass = "chat-sender-card-box"
  2041. }
  2042. var lastNode = new Element("div", {"class": lastNodeClass}).inject(receiverBodyNode);
  2043. lastNode.store("msg", msg);
  2044. lastNode.addEvents({
  2045. "click": function(e) {
  2046. this._clickMsgItem(e);
  2047. }.bind(this)
  2048. })
  2049. var lastFirstNode = new Element("div", { "class": "chat-left_triangle" }).inject(lastNode);
  2050. //text
  2051. if (msgBody.type === "emoji") { // 表情
  2052. var img = "";
  2053. for (var i = 0; i < this.main.emojiList.length; i++) {
  2054. if (msgBody.body === this.main.emojiList[i].key) {
  2055. img = this.main.emojiList[i].path;
  2056. }
  2057. }
  2058. new Element("img", { "src": img, "class": "chat-content-emoji" }).inject(lastNode);
  2059. } else if (msgBody.type === "image") {//image
  2060. var imgBox = new Element("div", { "class": "img-chat" }).inject(lastNode);
  2061. var url = this._getFileUrlWithWH(msgBody.fileId, 144, 192);
  2062. if (msgBody.fileExtension && msgBody.fileExtension.toLowerCase() === "webp") {
  2063. url = this._getFileDownloadUrl(msgBody.fileId);
  2064. }
  2065. new Element("img", { "src": url }).inject(imgBox);
  2066. } else if (msgBody.type === "audio") {
  2067. var url = this._getFileDownloadUrl(msgBody.fileId);
  2068. new Element("audio", { "src": url, "controls": "controls", "preload": "preload" }).inject(lastNode);
  2069. } else if (msgBody.type === "location") {
  2070. var mapBox = new Element("span", {"style": "display: flex;gap: 5px;align-items: center;"}).inject(lastNode);
  2071. new Element("img", { "src": "../x_component_IMV2/$Main/default/icons/location.png", "width": 24, "height": 24 }).inject(mapBox);
  2072. new Element("span", { "text": msgBody.address }).inject(mapBox);
  2073. } else if (msgBody.type === "file") { //文件
  2074. // 视频文件 mp4 avi ogg
  2075. if (msgBody.fileExtension
  2076. && (msgBody.fileExtension.toLowerCase() === "mp4" || msgBody.fileExtension.toLowerCase() === "avi" || msgBody.fileExtension.toLowerCase() === "ogg")) {
  2077. // var videoType = "video/" + msgBody.fileExtension.toLowerCase();
  2078. new Element("video", {"class": "chat-content-video", "src": this._getFileDownloadUrl(msgBody.fileId), "controls": "controls", "preload": "preload"}).inject(lastNode);
  2079. } else {
  2080. var mapBox = new Element("span", {"style": "display: flex;gap: 5px;align-items: center;"}).inject(lastNode);
  2081. var fileIcon = this._getFileIcon(msgBody.fileExtension);
  2082. new Element("img", { "src": "../x_component_IMV2/$Main/file_icons/" + fileIcon, "width": 48, "height": 48 }).inject(mapBox);
  2083. new Element("span", {"text": msgBody.fileName }).inject(mapBox);
  2084. }
  2085. } else if (msgBody.type === "process") {
  2086. var cardNode = new Element("div", {"class": "chat-card"}).inject(lastNode);
  2087. // 流程名称
  2088. new Element("div", {"class": "chat-card-type", "text": "【"+msgBody.processName+"】"}).inject(cardNode);
  2089. // 工作标题
  2090. var title = msgBody.title;
  2091. if (title == null || title === "") {
  2092. title = "【"+msgBody.processName+"】- " + this.lp.noTitle;
  2093. }
  2094. new Element("div", {"class": "chat-card-body", "text":title}).inject(cardNode);
  2095. var cardFooter = new Element("div", {"class": "chat-card-bottom"}).inject(cardNode);
  2096. var appIconNode = new Element("img", {"class": "chat-card-bottom-icon"}).inject(cardFooter);
  2097. this._loadProcessApplicationIcon(msgBody.application, function(appIcon) {
  2098. if (appIcon && appIcon.icon) {
  2099. appIconNode.set("src", "data:image/png;base64," + appIcon.icon);
  2100. } else {
  2101. console.log('没有找到应用图标');
  2102. appIconNode.set("src", "../x_component_process_ApplicationExplorer/$Main/default/icon/application.png");
  2103. }
  2104. })
  2105. new Element("div", { "class": "chat-card-bottom-name", "text": msgBody.applicationName }).inject(cardFooter);
  2106. } else if (msgBody.type === "cms") {
  2107. } else if (msgBody.type === "messageHistory") { // 聊天记录
  2108. var cardNode = new Element("div", {"class": "chat-card"}).inject(lastNode);
  2109. // title
  2110. new Element("div", {"class": "chat-card-type", "text": msgBody.messageHistoryTitle}).inject(cardNode);
  2111. // desc
  2112. new Element("div", {"class": "chat-card-body", "text": msgBody.messageHistoryDesc }).inject(cardNode);
  2113. var cardFooter = new Element("div", {"class": "chat-card-bottom"}).inject(cardNode);
  2114. new Element("div", { "class": "chat-card-bottom-name", "text": this.lp.msgHistory }).inject(cardFooter);
  2115. } else {//text
  2116. new Element("span", { "text": this.contentEscapeBackToSymbol(msgBody.body) }).inject(lastNode);
  2117. }
  2118. // 引用消息
  2119. if (msg.quoteMessage) {
  2120. let quoteMessage = msg.quoteMessage;
  2121. let node = this._newQuoteMessageElement(quoteMessage, receiverBodyNode);
  2122. node.classList.add("chat-sender-quote-msg");
  2123. node.store("msg", quoteMessage);
  2124. node.addEvents({
  2125. "click": function(e) {
  2126. this._clickMsgItem(e, true);
  2127. }.bind(this)
  2128. });
  2129. }
  2130. if (isTop) {
  2131. // 添加消息时间
  2132. this._buildMsgTime(isTop, msg);
  2133. }
  2134. if (!isTop) {
  2135. var scrollFx = new Fx.Scroll(this.chatContentNode);
  2136. scrollFx.toBottom();
  2137. }
  2138. },
  2139. /**
  2140. * 消息发送对象
  2141. * 这里的方法名错了两者互换了无需理会
  2142. * @param msgBody
  2143. * @param createPerson 消息人员
  2144. * @param isTop 是否放在顶部
  2145. * @param msg 消息对象
  2146. */
  2147. _buildReceiver: function (msgBody, createPerson, isTop, msg) {
  2148. if (!isTop) {
  2149. // 添加消息时间
  2150. this._buildMsgTime(isTop, msg);
  2151. }
  2152. var msgItemNode = new Element("div", {"class": "chat-msg"}).inject(this.chatContentNode, isTop ? "top" : "bottom");
  2153. var msgItemCheckBoxNode = new Element("div", {"class": "chat-msg-checkbox none"}).inject(msgItemNode);
  2154. var msgItemCheckBoxInputNode = new Element("input", {"type": "checkbox", "class": "check-box-select-item"}).inject(msgItemCheckBoxNode);
  2155. msgItemCheckBoxInputNode.store("msg", msg)
  2156. msgItemCheckBoxInputNode.addEvents({
  2157. "click": function(e) {
  2158. this._clickMsgItem(e);
  2159. }.bind(this)
  2160. })
  2161. var receiverBodyNode = new Element("div", { "class": "chat-receiver", "id": msg.id}).inject(msgItemNode);
  2162. this._addContextMenuEvent(receiverBodyNode, msg);
  2163. var avatarNode = new Element("div", {"class": "chat-receiver-avatar"}).inject(receiverBodyNode);
  2164. var avatarUrl = this.main._getIcon(createPerson);
  2165. var name = createPerson;
  2166. if (createPerson.indexOf("@") != -1) {
  2167. name = name.substring(0, createPerson.indexOf("@"));
  2168. }
  2169. var avatarImg = new Element("img", { "src": avatarUrl }).inject(avatarNode);
  2170. var nameNode = new Element("div", { "text": name , "class": "chat-receiver-name"}).inject(receiverBodyNode);
  2171. var lastNodeClass = "chat-receiver-box"
  2172. if (msgBody.type === "process" || msgBody.type === "cms") {
  2173. lastNodeClass = "chat-receiver-card-box"
  2174. }
  2175. var lastNode = new Element("div", {"class": lastNodeClass}).inject(receiverBodyNode);
  2176. lastNode.store("msg", msg);
  2177. lastNode.addEvent("click", function(e) {
  2178. this._clickMsgItem(e);
  2179. }.bind(this))
  2180. var lastFirstNode = new Element("div", { "class": "chat-right_triangle" }).inject(lastNode);
  2181. if (msgBody.type === "emoji") { // 表情
  2182. var img = "";
  2183. for (var i = 0; i < this.main.emojiList.length; i++) {
  2184. if (msgBody.body === this.main.emojiList[i].key) {
  2185. img = this.main.emojiList[i].path;
  2186. }
  2187. }
  2188. new Element("img", { "src": img, "class": "chat-content-emoji" }).inject(lastNode);
  2189. } else if (msgBody.type === "image") {//image
  2190. var imgBox = new Element("div", { "class": "img-chat" }).inject(lastNode);
  2191. var url = this._getFileUrlWithWH(msgBody.fileId, 144, 192);
  2192. if (msgBody.fileExtension && msgBody.fileExtension.toLowerCase() === "webp") {
  2193. url = this._getFileDownloadUrl(msgBody.fileId);
  2194. }
  2195. new Element("img", { "src": url }).inject(imgBox);
  2196. } else if (msgBody.type === "audio") {
  2197. var url = this._getFileDownloadUrl(msgBody.fileId);
  2198. new Element("audio", { "src": url, "controls": "controls", "preload": "preload" }).inject(lastNode);
  2199. } else if (msgBody.type === "location") {
  2200. var mapBox = new Element("span", {"style": "display: flex;gap: 5px;align-items: center;"}).inject(lastNode);
  2201. new Element("img", { "src": "../x_component_IMV2/$Main/default/icons/location.png", "width": 24, "height": 24 }).inject(mapBox);
  2202. new Element("span", { "text": msgBody.address }).inject(mapBox);
  2203. } else if (msgBody.type === "file") { //文件
  2204. // 视频文件 mp4 avi ogg
  2205. if (msgBody.fileExtension
  2206. && (msgBody.fileExtension.toLowerCase() === "mp4" || msgBody.fileExtension.toLowerCase() === "avi" || msgBody.fileExtension.toLowerCase() === "ogg")) {
  2207. //var videoType = "video/" + msgBody.fileExtension.toLowerCase();
  2208. new Element("video", {"class": "chat-content-video","src": this._getFileDownloadUrl(msgBody.fileId), "controls": "controls", "preload": "preload"}).inject(lastNode);
  2209. } else {
  2210. var mapBox = new Element("span", {"style": "display: flex;gap: 5px;align-items: center;"}).inject(lastNode);
  2211. var fileIcon = this._getFileIcon(msgBody.fileExtension);
  2212. new Element("img", { "src": "../x_component_IMV2/$Main/file_icons/" + fileIcon, "width": 48, "height": 48 }).inject(mapBox);
  2213. new Element("span", {"text": msgBody.fileName }).inject(mapBox);
  2214. }
  2215. } else if (msgBody.type === "process") {
  2216. var cardNode = new Element("div", {"class": "chat-card"}).inject(lastNode);
  2217. // 流程名称
  2218. new Element("div", {"class": "chat-card-type", "text": "【"+msgBody.processName+"】"}).inject(cardNode);
  2219. // 工作标题
  2220. var title = msgBody.title;
  2221. if (title == null || title === "") {
  2222. title = "【"+msgBody.processName+"】- " + this.lp.noTitle;
  2223. }
  2224. new Element("div", {"class": "chat-card-body", "text":title}).inject(cardNode);
  2225. var cardFooter = new Element("div", {"class": "chat-card-bottom"}).inject(cardNode);
  2226. var appIconNode = new Element("img", {"class": "chat-card-bottom-icon"}).inject(cardFooter);
  2227. this._loadProcessApplicationIcon(msgBody.application, function(appIcon) {
  2228. if (appIcon && appIcon.icon) {
  2229. appIconNode.set("src", "data:image/png;base64," + appIcon.icon);
  2230. } else {
  2231. console.log('没有找到应用图标');
  2232. appIconNode.set("src", "../x_component_process_ApplicationExplorer/$Main/default/icon/application.png");
  2233. }
  2234. })
  2235. new Element("div", { "class": "chat-card-bottom-name", "text": msgBody.applicationName }).inject(cardFooter);
  2236. } else if (msgBody.type == "cms") {
  2237. } else if (msgBody.type == "messageHistory") { // 聊天记录
  2238. var cardNode = new Element("div", {"class": "chat-card"}).inject(lastNode);
  2239. // title
  2240. new Element("div", {"class": "chat-card-type", "text": msgBody.messageHistoryTitle}).inject(cardNode);
  2241. // desc
  2242. new Element("div", {"class": "chat-card-body", "text": msgBody.messageHistoryDesc }).inject(cardNode);
  2243. var cardFooter = new Element("div", {"class": "chat-card-bottom"}).inject(cardNode);
  2244. new Element("div", { "class": "chat-card-bottom-name", "text": this.lp.msgHistory }).inject(cardFooter);
  2245. } else {//text
  2246. new Element("span", { "text": this.contentEscapeBackToSymbol(msgBody.body) }).inject(lastNode);
  2247. }
  2248. // 引用消息
  2249. if (msg.quoteMessage) {
  2250. let quoteMessage = msg.quoteMessage;
  2251. let node = this._newQuoteMessageElement(quoteMessage, receiverBodyNode);
  2252. node.classList.add("chat-receiver-quote-msg");
  2253. node.store("msg", quoteMessage);
  2254. node.addEvents({
  2255. "click": function(e) {
  2256. this._clickMsgItem(e, true);
  2257. }.bind(this)
  2258. });
  2259. }
  2260. if (isTop) {
  2261. // 添加消息时间
  2262. this._buildMsgTime(isTop, msg);
  2263. }
  2264. if (!isTop) {
  2265. var scrollFx = new Fx.Scroll(this.chatContentNode);
  2266. scrollFx.toBottom();
  2267. }
  2268. },
  2269. // 获取流程应用图标
  2270. _loadProcessApplicationIcon: function(appId, callback) {
  2271. if (!this.processApplications) {
  2272. this.processApplications = [];
  2273. }
  2274. if (this.processApplications[appId]) {
  2275. if (callback) callback(this.processApplications[appId]);
  2276. } else {
  2277. o2.Actions.load("x_processplatform_assemble_surface").ApplicationAction. getIcon(appId, function (json) {
  2278. if(json && json.data) {
  2279. this.processApplications[appId] = json.data;
  2280. if (callback) callback(json.data);
  2281. } else {
  2282. if (callback) callback();
  2283. }
  2284. }.bind(this), function (error) {
  2285. console.error(error);
  2286. if (callback) callback();
  2287. }.bind(this))
  2288. }
  2289. },
  2290. // 消息体上是否显示消息时间
  2291. _buildMsgTime: function(isTop, msg) {
  2292. var timeNode = new Element("div", { "class": "chat-msg-time"}).inject(this.chatContentNode, isTop ? "top" : "bottom");
  2293. timeNode.set("text", this._msgShowTime(o2.common.toDate(msg.createTime)))
  2294. },
  2295. // 消息时间
  2296. _msgShowTime: function (date) {
  2297. var day = date.getDate();
  2298. var monthIndex = date.getMonth();
  2299. var year = date.getFullYear();
  2300. var time = date.getTime();
  2301. var today = new Date();
  2302. var todayDay = today.getDate();
  2303. var todayMonthIndex = today.getMonth();
  2304. var todayYear = today.getFullYear();
  2305. var todayTime = today.getTime();
  2306. var retTime = "";
  2307. //同一天
  2308. if (day === todayDay && monthIndex === todayMonthIndex && year === todayYear) {
  2309. var hour = date.getHours() > 9 ? ""+date.getHours() : "0" + date.getHours();
  2310. var minute = date.getMinutes() > 9 ? ""+date.getMinutes() : "0" + date.getMinutes();
  2311. retTime = hour + ":" +minute;
  2312. return retTime;
  2313. }
  2314. var dates = parseInt(time / 86400000);
  2315. var todaydates = parseInt(todayTime / 86400000);
  2316. if (todaydates > dates) {
  2317. var days = (todaydates - dates);
  2318. if (days == 1) {
  2319. var hour = date.getHours() > 9 ? ""+date.getHours() : "0" + date.getHours();
  2320. var minute = date.getMinutes() > 9 ? ""+date.getMinutes() : "0" + date.getMinutes();
  2321. retTime = this.lp.yesterday + " " + hour + ":" +minute;
  2322. } else if (days == 2) {
  2323. var hour = date.getHours() > 9 ? ""+date.getHours() : "0" + date.getHours();
  2324. var minute = date.getMinutes() > 9 ? ""+date.getMinutes() : "0" + date.getMinutes();
  2325. retTime = this.lp.beforeYesterday + " " + hour + ":" +minute;
  2326. }else {
  2327. var month = date.getMonth() + 1;
  2328. var day = date.getDate();
  2329. month = (month.toString().length == 1) ? ("0" + month) : month;
  2330. day = (day.toString().length == 1) ? ("0" + day) : day;
  2331. var hour = date.getHours() > 9 ? ""+date.getHours() : "0" + date.getHours();
  2332. var minute = date.getMinutes() > 9 ? ""+date.getMinutes() : "0" + date.getMinutes();
  2333. retTime = month + '-' + day + " " + hour + ":" +minute;
  2334. }
  2335. }
  2336. return retTime;
  2337. },
  2338. // 绑定右键事件
  2339. _addContextMenuEvent: function(receiverBodyNode, msg) {
  2340. receiverBodyNode.store("msg", msg);
  2341. receiverBodyNode.addEvent("contextmenu", function(e) {
  2342. //取消默认的浏览器自带右键 很重要!!
  2343. e.preventDefault();
  2344. if (this.selectMode) return; // 选择模式不需要右键菜单
  2345. var menuleft=e.client.x+'px';
  2346. var menutop=e.client.y+'px';
  2347. var m = receiverBodyNode.retrieve("msg");
  2348. this._createMsgContextMenu(m, menuleft, menutop);
  2349. }.bind(this)
  2350. );
  2351. },
  2352. // 打开 消息体上 右键菜单
  2353. _createMsgContextMenu: function(msg, menuleft, menutop) {
  2354. var createPerson = msg.createPerson;
  2355. var distinguishedName = layout.session.user.distinguishedName;
  2356. var list = []; // 菜单列表
  2357. if (this.main.imConfig.enableRevokeMsg) { // 是否启用撤回消息
  2358. var revokeMinute = this.main.imConfig.revokeOutMinute ?? 2;
  2359. if (revokeMinute <= 0) {
  2360. revokeMinute = 2;
  2361. }
  2362. var createTime = o2.common.toDate(msg.createTime);
  2363. if ( revokeMinute > 0 && (new Date().getTime() - createTime.getTime()) < revokeMinute * 60 * 1000) {
  2364. if (createPerson !== distinguishedName) {
  2365. // 判断是否群主
  2366. var isGroupAdmin = false;
  2367. for (var i = 0; i < this.main.conversationNodeItemList.length; i++) {
  2368. var c = this.main.conversationNodeItemList[i];
  2369. if (this.conversationId === c.data.id) {
  2370. if (c.data.type === "group" && distinguishedName === c.data.adminPerson) {
  2371. isGroupAdmin = true;
  2372. }
  2373. }
  2374. }
  2375. if (isGroupAdmin) {
  2376. list.push({"id":"revokeMemberMsg", "text": this.lp.msgMenuItemRevokeMemberMsg});
  2377. }
  2378. } else {
  2379. list.push({"id":"revokeMsg", "text": this.lp.msgMenuItemRevokeMsg});
  2380. }
  2381. }
  2382. }
  2383. // 转发
  2384. list.push({"id":"forward", "text": this.lp.msgMenuItemForwardMsg});
  2385. // 收藏
  2386. list.push({"id":"collection", "text": this.lp.msgMenuItemCollectionMsg});
  2387. // 选择
  2388. list.push({"id":"select", "text": this.lp.msgMenuItemSelectMsg});
  2389. // 引用
  2390. list.push({"id":"quote", "text": this.lp.msgMenuItemQuoteMsg});
  2391. if (this.menuNode) {
  2392. this.menuNode.destroy();
  2393. this.menuNode = null;
  2394. }
  2395. if (list.length > 0) {
  2396. // 生成菜单
  2397. this.menuNode = new Element("ul", {"class": "chat-menulist", "styles": { "position": "fixed", "z-index": "9999", "top": menutop, "left": menuleft } }).inject(this.container);
  2398. for (let index = 0; index < list.length; index++) {
  2399. const element = list[index];
  2400. let menuItemNode = new Element("li", {"text": element.text}).inject(this.menuNode);
  2401. menuItemNode.store('menuItemData', element);
  2402. menuItemNode.store('menuItemMsgData', msg);
  2403. menuItemNode.addEvents({
  2404. "click": function(e) {
  2405. let menuItemData = e.target.retrieve('menuItemData'); // 菜单项数据
  2406. console.debug('点击菜单。。。。。。。。' + menuItemData.text)
  2407. let menuItemMsgData = e.target.retrieve('menuItemMsgData'); // 消息数据
  2408. this._clickMsgContextMenuItem(menuItemData, menuItemMsgData);
  2409. e.preventDefault();
  2410. }.bind(this)
  2411. });
  2412. }
  2413. // 添加关闭菜单事件
  2414. this.closeMsgContextMenuFun = function(e) {
  2415. if (this.menuNode) {
  2416. this.menuNode.destroy();
  2417. this.menuNode = null;
  2418. }
  2419. e.preventDefault();
  2420. if( this.closeMsgContextMenuFun )this.main.app.content.removeEvent( "click", this.closeMsgContextMenuFun );
  2421. }.bind(this);
  2422. this.main.app.content.addEvents({
  2423. "click": this.closeMsgContextMenuFun
  2424. });
  2425. }
  2426. },
  2427. // 点击 右键菜单项
  2428. _clickMsgContextMenuItem: function(menuItemData, msg) {
  2429. debugger
  2430. // 关闭菜单
  2431. if (this.menuNode) {
  2432. this.menuNode.destroy();
  2433. this.menuNode = null;
  2434. }
  2435. // 根据菜单不同处理不同内容
  2436. // 撤回
  2437. if (menuItemData.id === "revokeMemberMsg" || menuItemData.id === "revokeMsg") {
  2438. this._revokeMsg(msg);
  2439. }
  2440. if (menuItemData.id === "forward") {
  2441. this.forwardMsgList([msg])
  2442. }
  2443. if (menuItemData.id === "collection") {
  2444. this.collectionMsgList([msg])
  2445. }
  2446. if (menuItemData.id === "select") {
  2447. if (this.selectMode) {
  2448. this.cancelSelectMode()
  2449. } else {
  2450. this.openSelectMode(msg)
  2451. }
  2452. }
  2453. if (menuItemData.id === "quote") {
  2454. this.addQuoteMessage(msg)
  2455. }
  2456. },
  2457. // 撤回消息
  2458. _revokeMsg: function(msg) {
  2459. o2.Actions.load("x_message_assemble_communicate").ImAction.msgRevoke(msg.id, function(json) {
  2460. console.debug("撤回消息:", json);
  2461. // 删除消息
  2462. $(msg.id).destroy();
  2463. }.bind(this));
  2464. },
  2465. //图片 根据大小 url
  2466. _getFileUrlWithWH: function (id, width, height) {
  2467. var action = MWF.Actions.get("x_message_assemble_communicate").action;
  2468. var url = action.getAddress() + action.actions.imgFileDownloadWithWH.uri;
  2469. url = url.replace("{id}", encodeURIComponent(id));
  2470. url = url.replace("{width}", encodeURIComponent(width));
  2471. url = url.replace("{height}", encodeURIComponent(height));
  2472. return url;
  2473. },
  2474. //file 下载的url
  2475. _getFileDownloadUrl: function (id) {
  2476. var action = MWF.Actions.get("x_message_assemble_communicate").action;
  2477. var url = action.getAddress() + action.actions.imgFileDownload.uri;
  2478. url = url.replace("{id}", encodeURIComponent(id));
  2479. return url;
  2480. },
  2481. //百度地图打开地址
  2482. _getBaiduMapUrl: function (lat, longt, address, content) {
  2483. var url = "https://api.map.baidu.com/marker?location=" + lat + "," + longt + "&title=" + address + "&content=" + content + "&output=html&src=net.o2oa.map";
  2484. return url;
  2485. },
  2486. // 文件类型icon图
  2487. _getFileIcon: function (ext) {
  2488. if (ext) {
  2489. if (ext === "jpg" || ext === "jpeg") {
  2490. return "icon_file_jpeg.png";
  2491. } else if (ext === "gif") {
  2492. return "icon_file_gif.png";
  2493. } else if (ext === "png") {
  2494. return "icon_file_png.png";
  2495. } else if (ext === "tiff") {
  2496. return "icon_file_tiff.png";
  2497. } else if (ext === "bmp" || ext === "webp") {
  2498. return "icon_file_img.png";
  2499. } else if (ext === "ogg" || ext === "mp3" || ext === "wav" || ext === "wma") {
  2500. return "icon_file_mp3.png";
  2501. } else if (ext === "mp4") {
  2502. return "icon_file_mp4.png";
  2503. } else if (ext === "avi") {
  2504. return "icon_file_avi.png";
  2505. } else if (ext === "mov" || ext === "rm" || ext === "mkv") {
  2506. return "icon_file_rm.png";
  2507. } else if (ext === "doc" || ext === "docx") {
  2508. return "icon_file_word.png";
  2509. } else if (ext === "xls" || ext === "xlsx") {
  2510. return "icon_file_excel.png";
  2511. } else if (ext === "ppt" || ext === "pptx") {
  2512. return "icon_file_ppt.png";
  2513. } else if (ext === "html") {
  2514. return "icon_file_html.png";
  2515. } else if (ext === "pdf") {
  2516. return "icon_file_pdf.png";
  2517. } else if (ext === "txt" || ext === "json") {
  2518. return "icon_file_txt.png";
  2519. } else if (ext === "zip") {
  2520. return "icon_file_zip.png";
  2521. } else if (ext === "rar") {
  2522. return "icon_file_rar.png";
  2523. } else if (ext === "7z") {
  2524. return "icon_file_arch.png";
  2525. } else if (ext === "ai") {
  2526. return "icon_file_ai.png";
  2527. } else if (ext === "att") {
  2528. return "icon_file_att.png";
  2529. } else if (ext === "au") {
  2530. return "icon_file_au.png";
  2531. } else if (ext === "cad") {
  2532. return "icon_file_cad.png";
  2533. } else if (ext === "cdr") {
  2534. return "icon_file_cdr.png";
  2535. } else if (ext === "eps") {
  2536. return "icon_file_eps.png";
  2537. } else if (ext === "exe") {
  2538. return "icon_file_exe.png";
  2539. } else if (ext === "iso") {
  2540. return "icon_file_iso.png";
  2541. } else if (ext === "link") {
  2542. return "icon_file_link.png";
  2543. } else if (ext === "swf") {
  2544. return "icon_file_flash.png";
  2545. } else if (ext === "psd") {
  2546. return "icon_file_psd.png";
  2547. } else if (ext === "tmp") {
  2548. return "icon_file_tmp.png";
  2549. } else {
  2550. return "icon_file_unkown.png";
  2551. }
  2552. } else {
  2553. return "icon_file_unkown.png";
  2554. }
  2555. },
  2556. //当前时间 yyyy-MM-dd HH:mm:ss
  2557. _currentTime: function () {
  2558. var today = new Date();
  2559. var year = today.getFullYear(); //得到年份
  2560. var month = today.getMonth();//得到月份
  2561. var date = today.getDate();//得到日期
  2562. var hour = today.getHours();//得到小时
  2563. var minu = today.getMinutes();//得到分钟
  2564. var sec = today.getSeconds();//得到秒
  2565. month = month + 1;
  2566. if (month < 10) month = "0" + month;
  2567. if (date < 10) date = "0" + date;
  2568. if (hour < 10) hour = "0" + hour;
  2569. if (minu < 10) minu = "0" + minu;
  2570. if (sec < 10) sec = "0" + sec;
  2571. return year + "-" + month + "-" + date + " " + hour + ":" + minu + ":" + sec;
  2572. }
  2573. });
  2574. // 会话对象
  2575. MWF.xApplication.IMV2.ConversationItem = new Class({
  2576. initialize: function (data, main) {
  2577. this.data = data;
  2578. this.main = main;
  2579. this.container = this.main.chatItemListNode;
  2580. this.load();
  2581. },
  2582. load: function () {
  2583. var convData = this.getConversationData()
  2584. if (this.data.lastMessage) {
  2585. //todo 其它消息类型
  2586. var mBody = JSON.parse(this.data.lastMessage.body);
  2587. convData.lastMessage = mBody.body;
  2588. if (this.data.lastMessage.createTime) {
  2589. var time = this.main._friendlyTime(o2.common.toDate(this.data.lastMessage.createTime));
  2590. convData.time = time;
  2591. }
  2592. if (mBody.type) {
  2593. convData.lastMessageType = mBody.type;
  2594. if (mBody.type === "process") {
  2595. var title = mBody.title;
  2596. if (title == null || title == "") {
  2597. title = "【" + mBody.processName + "】- " + this.lp.noTitle;
  2598. }
  2599. convData.lastMessage = title;
  2600. } else if (mBody.type === "cms") {
  2601. convData.lastMessage = mBody.title || "";
  2602. }
  2603. }
  2604. }
  2605. this.node = new Element("div", { "class": "item" }).inject(this.container, this.data.isNew ? 'top' : '');
  2606. this.nodeBaseItem = new Element("div", { "class": "base" }).inject(this.node);
  2607. var avatarNode = new Element("div", { "class": "avatar" }).inject(this.nodeBaseItem);
  2608. new Element("img", { "src": convData.avatarUrl, "class": "img" }).inject(avatarNode);
  2609. var bodyNode = new Element("div", { "class": "body" }).inject(this.nodeBaseItem);
  2610. var bodyUpNode = new Element("div", { "class": "body_up" }).inject(bodyNode);
  2611. this.titleNode = new Element("div", { "class": "body_title", "text": convData.title }).inject(bodyUpNode);
  2612. this.messageTimeNode = new Element("div", { "class": "body_time", "text": convData.time }).inject(bodyUpNode);
  2613. if (convData.lastMessageType == "emoji") {
  2614. this.lastMessageNode = new Element("div", { "class": "body_down" }).inject(bodyNode);
  2615. var imgPath = "";
  2616. for (var i = 0; i < this.main.emojiList.length; i++) {
  2617. var emoji = this.main.emojiList[i];
  2618. if (emoji.key == convData.lastMessage) {
  2619. imgPath = emoji.path;
  2620. }
  2621. }
  2622. new Element("img", { "src": imgPath, "style": "width: 16px;height: 16px;" }).inject(this.lastMessageNode);
  2623. } else {
  2624. this.lastMessageNode = new Element("div", { "class": "body_down", "text": convData.lastMessage }).inject(bodyNode);
  2625. }
  2626. var _self = this;
  2627. this.node.addEvents({
  2628. "click": function () {
  2629. _self.main.tapConv(_self.data);
  2630. }
  2631. });
  2632. },
  2633. getConversationData: function () {
  2634. var avatarDefault = this.main._getIcon();
  2635. var convData = {
  2636. "id": this.data.id,
  2637. "avatarUrl": avatarDefault,
  2638. "title": this.data.title,
  2639. "time": "",
  2640. "lastMessage": "",
  2641. "lastMessageType": "text"
  2642. };
  2643. if (this.data.type && this.data.type === "single") {
  2644. var chatPerson = "";
  2645. if (this.data.personList && this.data.personList instanceof Array) {
  2646. for (var j = 0; j < this.data.personList.length; j++) {
  2647. var person = this.data.personList[j];
  2648. if (person !== layout.session.user.distinguishedName) {
  2649. chatPerson = person;
  2650. }
  2651. }
  2652. }
  2653. convData.avatarUrl = this.main._getIcon(chatPerson);
  2654. var name = chatPerson;
  2655. if (chatPerson.indexOf("@") !== -1) {
  2656. name = name.substring(0, chatPerson.indexOf("@"));
  2657. }
  2658. convData.title = name;
  2659. }
  2660. return convData;
  2661. },
  2662. /**
  2663. *
  2664. * 刷新会话列表的最后消息内容
  2665. * @param {*} lastMessage
  2666. */
  2667. refreshLastMsg: function (lastMessage) {
  2668. if (lastMessage) {
  2669. //目前是text 类型的消息
  2670. var jsonbody = lastMessage.body;
  2671. var body = JSON.parse(jsonbody);
  2672. if (this.lastMessageNode) {
  2673. if (body.type == "emoji") { //表情 消息
  2674. var imgPath = "";
  2675. for (var i = 0; i < this.main.emojiList.length; i++) {
  2676. var emoji = this.main.emojiList[i];
  2677. if (emoji.key == body.body) {
  2678. imgPath = emoji.path;
  2679. }
  2680. }
  2681. this.lastMessageNode.empty();
  2682. new Element("img", { "src": imgPath, "style": "width: 16px;height: 16px;" }).inject(this.lastMessageNode);
  2683. } else { //文本消息
  2684. this.lastMessageNode.empty();
  2685. this.lastMessageNode.set('text', body.body);
  2686. }
  2687. }
  2688. var time = this.main._friendlyTime(o2.common.toDate(lastMessage.createTime));
  2689. if (this.messageTimeNode) {
  2690. this.messageTimeNode.set("text", time);
  2691. }
  2692. }
  2693. },
  2694. // 更新聊天窗口上的标题 修改标题的时候使用 @Disuse 使用refreshData
  2695. refreshConvTitle: function (title) {
  2696. this.titleNode.set("text", title);
  2697. },
  2698. // 更新会话数据
  2699. refreshData: function (data) {
  2700. this.data = data;
  2701. // 更新聊天窗口上的标题 修改标题的时候使用
  2702. const convData = this.getConversationData()
  2703. this.titleNode.set("text", convData.title);
  2704. },
  2705. addCheckClass: function () {
  2706. if (this.nodeBaseItem) {
  2707. if (!this.nodeBaseItem.hasClass("check")) {
  2708. this.nodeBaseItem.addClass("check");
  2709. }
  2710. }
  2711. },
  2712. removeCheckClass: function () {
  2713. if (this.nodeBaseItem) {
  2714. if (this.nodeBaseItem.hasClass("check")) {
  2715. this.nodeBaseItem.removeClass("check");
  2716. }
  2717. }
  2718. }
  2719. });
  2720. //弹出窗 表单 单聊创建的form
  2721. MWF.xApplication.IMV2.SingleForm = new Class({
  2722. Extends: MPopupForm,
  2723. Implements: [Options, Events],
  2724. options: {
  2725. "style": "minder",
  2726. "width": 700,
  2727. //"height": 300,
  2728. "height": "200",
  2729. "hasTop": true,
  2730. "hasIcon": false,
  2731. "draggable": true,
  2732. "title": MWF.xApplication.IMV2.LP.createSingle
  2733. },
  2734. _createTableContent: function () {
  2735. var html = "<table width='100%' bordr='0' cellpadding='7' cellspacing='0' styles='formTable' style='margin-top: 20px; '>" +
  2736. "<tr><td styles='formTableTitle' lable='person' width='25%'></td>" +
  2737. " <td styles='formTableValue14' item='person' colspan='3'></td></tr>" +
  2738. "</table>";
  2739. this.formTableArea.set("html", html);
  2740. var me = layout.session.user.distinguishedName;
  2741. var exclude = [];
  2742. if (me) {
  2743. exclude = [me];
  2744. }
  2745. this.form = new MForm(this.formTableArea, this.data || {}, {
  2746. isEdited: true,
  2747. style: "minder",
  2748. hasColon: true,
  2749. itemTemplate: {
  2750. person: { text: MWF.xApplication.IMV2.LP.selectPerson, type: "org", orgType: "person", count: 0, notEmpty: true, exclude: exclude },
  2751. }
  2752. }, this.app);
  2753. this.form.load();
  2754. },
  2755. _createBottomContent: function () {
  2756. if (this.isNew || this.isEdited) {
  2757. this.okActionNode = new Element("button.inputOkButton", {
  2758. "styles": this.css.inputOkButton,
  2759. "text": MWF.xApplication.IMV2.LP.ok
  2760. }).inject(this.formBottomNode);
  2761. this.okActionNode.addEvent("click", function (e) {
  2762. this.save(e);
  2763. }.bind(this));
  2764. }
  2765. this.cancelActionNode = new Element("button.inputCancelButton", {
  2766. "styles": (this.isEdited || this.isNew || this.getEditPermission()) ? this.css.inputCancelButton : this.css.inputCancelButton_long,
  2767. "text": MWF.xApplication.IMV2.LP.close
  2768. }).inject(this.formBottomNode);
  2769. this.cancelActionNode.addEvent("click", function (e) {
  2770. this.close(e);
  2771. }.bind(this));
  2772. },
  2773. save: function () {
  2774. var data = this.form.getResult(true, null, true, false, true);
  2775. if (data) {
  2776. this.app.newConversation(data.person, "single");
  2777. this.close();
  2778. }
  2779. }
  2780. });
  2781. //创建聊天 弹出窗表单
  2782. MWF.xApplication.IMV2.CreateConversationForm = new Class({
  2783. Extends: MPopupForm,
  2784. Implements: [Options, Events],
  2785. options: {
  2786. "style": "minder",
  2787. "width": 700,
  2788. "height": "200",
  2789. "hasTop": true,
  2790. "hasIcon": false,
  2791. "draggable": true,
  2792. "title": MWF.xApplication.IMV2.LP.createSingle,
  2793. "personCount": 1, //1 是单选 0 是多选,
  2794. "personSelected": [],
  2795. "isUpdateMember": false
  2796. },
  2797. _createTableContent: function () {
  2798. var html = "<table width='100%' bordr='0' cellpadding='7' cellspacing='0' styles='formTable' style='margin-top: 20px; '>" +
  2799. "<tr><td styles='formTableTitle' lable='person' width='25%'></td>" +
  2800. " <td styles='formTableValue14' item='person' colspan='3'></td></tr>" +
  2801. "</table>";
  2802. this.formTableArea.set("html", html);
  2803. var me = layout.session.user.distinguishedName;
  2804. var exclude = [];
  2805. if (me) {
  2806. exclude = [me];
  2807. }
  2808. this.form = new MForm(this.formTableArea, this.data || {}, {
  2809. isEdited: true,
  2810. style: "minder",
  2811. hasColon: true,
  2812. itemTemplate: {
  2813. person: { text: MWF.xApplication.IMV2.LP.selectPerson, type: "org", orgType: "person", count: this.options["personCount"], notEmpty: true, exclude: exclude, value: this.options["personSelected"] },
  2814. }
  2815. }, this.app);
  2816. this.form.load();
  2817. },
  2818. _createBottomContent: function () {
  2819. if (this.isNew || this.isEdited) {
  2820. this.okActionNode = new Element("button.inputOkButton", {
  2821. "styles": this.css.inputOkButton,
  2822. "text": MWF.xApplication.IMV2.LP.ok
  2823. }).inject(this.formBottomNode);
  2824. this.okActionNode.addEvent("click", function (e) {
  2825. this.save(e);
  2826. }.bind(this));
  2827. }
  2828. this.cancelActionNode = new Element("button.inputCancelButton", {
  2829. "styles": (this.isEdited || this.isNew || this.getEditPermission()) ? this.css.inputCancelButton : this.css.inputCancelButton_long,
  2830. "text": MWF.xApplication.IMV2.LP.close
  2831. }).inject(this.formBottomNode);
  2832. this.cancelActionNode.addEvent("click", function (e) {
  2833. this.close(e);
  2834. }.bind(this));
  2835. },
  2836. save: function () {
  2837. var data = this.form.getResult(true, null, true, false, true);
  2838. if (data) {
  2839. if (this.options["isUpdateMember"] === true) {
  2840. this.app.updateConversationMembers(data.person, this.app.conversationId);
  2841. } else {
  2842. this.app.newConversation(data.person, this.options["personCount"] === 1 ? "single" : "group");
  2843. }
  2844. this.close();
  2845. }
  2846. }
  2847. });
  2848. //修改群名
  2849. MWF.xApplication.IMV2.UpdateConvTitleForm = new Class({
  2850. Extends: MPopupForm,
  2851. Implements: [Options, Events],
  2852. options: {
  2853. "style": "minder",
  2854. "width": 500,
  2855. "height": "200",
  2856. "hasTop": true,
  2857. "hasIcon": false,
  2858. "draggable": true,
  2859. "defaultValue": "", // 默认值
  2860. "title": MWF.xApplication.IMV2.LP.modifyGroupName
  2861. },
  2862. _createTableContent: function () {
  2863. var html = "<table width='100%' bordr='0' cellpadding='7' cellspacing='0' styles='formTable' style='margin-top: 20px; '>" +
  2864. "<tr><td styles='formTableTitle' lable='title' width='25%'></td>" +
  2865. " <td styles='formTableValue14' item='title' colspan='3'></td></tr>" +
  2866. "</table>";
  2867. this.formTableArea.set("html", html);
  2868. this.form = new MForm(this.formTableArea, this.data || {}, {
  2869. isEdited: true,
  2870. style: "minder",
  2871. hasColon: true,
  2872. itemTemplate: {
  2873. title: { text: MWF.xApplication.IMV2.LP.groupName, type: "text", notEmpty: true, value: this.options["defaultValue"] },
  2874. }
  2875. }, this.app);
  2876. this.form.load();
  2877. },
  2878. _createBottomContent: function () {
  2879. if (this.isNew || this.isEdited) {
  2880. this.okActionNode = new Element("button.inputOkButton", {
  2881. "styles": this.css.inputOkButton,
  2882. "text": MWF.xApplication.IMV2.LP.ok
  2883. }).inject(this.formBottomNode);
  2884. this.okActionNode.addEvent("click", function (e) {
  2885. this.save(e);
  2886. }.bind(this));
  2887. }
  2888. this.cancelActionNode = new Element("button.inputCancelButton", {
  2889. "styles": (this.isEdited || this.isNew || this.getEditPermission()) ? this.css.inputCancelButton : this.css.inputCancelButton_long,
  2890. "text": MWF.xApplication.IMV2.LP.close
  2891. }).inject(this.formBottomNode);
  2892. this.cancelActionNode.addEvent("click", function (e) {
  2893. this.close(e);
  2894. }.bind(this));
  2895. },
  2896. save: function () {
  2897. var data = this.form.getResult(true, null, true, false, true);
  2898. if (data) {
  2899. this.app.updateConversationTitle(data.title, this.app.conversationId);
  2900. this.close();
  2901. }
  2902. }
  2903. });
  2904. // 消息列表
  2905. MWF.xApplication.IMV2.ChatMessageList = new Class({
  2906. initialize: function (data, main) {
  2907. this.data = data;
  2908. this.main = main;
  2909. this.app = main.app;
  2910. this.container = main.messageHistoryNode; // 有专门的容器
  2911. this.lp = main.lp;
  2912. this.path = main.path;
  2913. this.options = main.options;
  2914. this.msg = data.msg; // 消息对象 里面的 id 作为标识
  2915. this.page = 1;
  2916. this.collectionMode = !!this.data.collectionMode; // 是否是收藏模式
  2917. this.selectMode = false; // 选择模式
  2918. this.hasMoreCollection = false; // 是否有更多收藏
  2919. this.isLoadingCollection = false; // 是否正在加载
  2920. this.selectMsgList = [];
  2921. this.collectionList = [];
  2922. this.load();
  2923. },
  2924. load: function () {
  2925. var url = this.path + this.options.style + "/messageList.html";
  2926. this.container.loadHtml(url, { "bind": { "thisTitle": this.data.title ?? this.lp.msgHistory, "lp": this.lp }, "module": this }, function () {
  2927. console.debug("加载完成");
  2928. this._layout();
  2929. if (this.collectionMode) {
  2930. this._addScrollListener();
  2931. this.page = 1;
  2932. this.loadMsgCollectionList();
  2933. } else {
  2934. this.loadMsgList();
  2935. }
  2936. }.bind(this));
  2937. },
  2938. // 删除当前节点 给上层调用的
  2939. deleteSelfNode: function () {
  2940. this.messageListBoxNode.destroy()
  2941. },
  2942. // 关闭 调用了上层的方法,为了关闭遮罩层
  2943. close: function () {
  2944. this.main.closeMessageHistory(this.msg);
  2945. },
  2946. _layout: function() {
  2947. if (this.collectionMode) {
  2948. this.messageListBoxNode.style.height = '90%';
  2949. this.messageListBoxNode.style['max-width'] = '700px';
  2950. this.messageListToolNode.classList.remove('none');
  2951. this.messageListToolNode.classList.add('block');
  2952. }
  2953. const rect = this.messageListBoxNode.parentElement.getBoundingClientRect()
  2954. this.parentElWidth = rect.width
  2955. this.parentElHeight = rect.height
  2956. const selfRect = this.messageListBoxNode.getBoundingClientRect()
  2957. this.selfElWidth = selfRect.width
  2958. this.selfElHeight = selfRect.height
  2959. const left = (rect.width - selfRect.width) / 2
  2960. const top = (rect.height - selfRect.height) / 2
  2961. this.messageListBoxNode.style.position = 'absolute';
  2962. this.messageListBoxNode.style.left = left + 'px';
  2963. this.messageListBoxNode.style.top = top + 'px';
  2964. console.debug("加载_layout完成")
  2965. this._draggable()
  2966. },
  2967. _draggable: function() {
  2968. this.messageListBoxHeaderNode.addEventListener('mousedown', (e) => {
  2969. this.offsetX = e.clientX - this.messageListBoxNode.offsetLeft
  2970. this.offsetY = e.clientY - this.messageListBoxNode.offsetTop
  2971. this.isDragging = true
  2972. })
  2973. this.messageListBoxHeaderNode.addEventListener('mousemove', (e) => {
  2974. if (this.isDragging) {
  2975. let left = e.clientX - this.offsetX
  2976. if (left < 0) {
  2977. left = 0
  2978. }
  2979. if (left > this.parentElWidth - this.selfElWidth) {
  2980. left = this.parentElWidth - this.selfElWidth
  2981. }
  2982. let top = e.clientY - this.offsetY
  2983. if (top < 0) {
  2984. top = 0
  2985. }
  2986. if (top > this.parentElHeight - this.selfElHeight) {
  2987. top = this.parentElHeight - this.selfElHeight
  2988. }
  2989. this.messageListBoxNode.style.left = left + 'px'
  2990. this.messageListBoxNode.style.top = top + 'px'
  2991. }
  2992. })
  2993. this.messageListBoxHeaderNode.addEventListener('mouseup', () => {
  2994. this.isDragging = false
  2995. })
  2996. console.debug("加载 _draggable 完成")
  2997. },
  2998. // 删除选中的收藏
  2999. deleteSelectedCollection: function () {
  3000. if (this.selectMsgList.length < 1) {
  3001. this.app.notice(this.lp.msgNeedSelectMessage, "error", this.app.content);
  3002. return;
  3003. }
  3004. let deleteIdList = [];
  3005. for (let i = 0; i < this.collectionList.length; i++) {
  3006. const collection = this.collectionList[i];
  3007. if ( this.selectMsgList.findIndex( m => m.id === collection.message.id) > -1) {
  3008. deleteIdList.push(collection.id)
  3009. }
  3010. }
  3011. if (deleteIdList.length < 1) {
  3012. return;
  3013. }
  3014. o2.Actions.load("x_message_assemble_communicate").ImAction.msgCollectionRemove({msgIdList: deleteIdList}, function (json) {
  3015. console.log('删除成功!');
  3016. this.page = 1;
  3017. this.cancelSelectMode();
  3018. this.loadMsgCollectionList();
  3019. }.bind(this), function (error) {
  3020. console.error(error);
  3021. }.bind(this));
  3022. },
  3023. // 选择模式
  3024. openSelectMode: function() {
  3025. this.selectMode = true;
  3026. this.messageListSelectBtnNode.classList.remove('block');
  3027. this.messageListSelectBtnNode.classList.add('none');
  3028. this.messageListCancelBtnNode.classList.remove('none');
  3029. this.messageListCancelBtnNode.classList.add('block');
  3030. this.messageListDeleteCollectionBtnNode.classList.remove('none');
  3031. this.messageListDeleteCollectionBtnNode.classList.add('block');
  3032. this.selectMsgList = [];
  3033. const list = this.messageListNode.querySelectorAll(".chat-msg-checkbox")
  3034. list.forEach(item => {
  3035. item.classList.remove("none")
  3036. item.classList.add("block")
  3037. })
  3038. },
  3039. // 取消选择模式
  3040. cancelSelectMode: function () {
  3041. this.selectMode = false;
  3042. this.messageListSelectBtnNode.classList.remove('none');
  3043. this.messageListSelectBtnNode.classList.add('block');
  3044. this.messageListCancelBtnNode.classList.remove('block');
  3045. this.messageListCancelBtnNode.classList.add('none');
  3046. this.messageListDeleteCollectionBtnNode.classList.remove('block');
  3047. this.messageListDeleteCollectionBtnNode.classList.add('none');
  3048. this.selectMsgList = [];
  3049. const list = this.messageListNode.querySelectorAll(".chat-msg-checkbox")
  3050. list.forEach(item => {
  3051. item.classList.remove("block")
  3052. item.classList.add("none")
  3053. })
  3054. this._selectOrUnSelectMsg()
  3055. },
  3056. _selectOrUnSelectMsg: function (msg) {
  3057. if (msg) {
  3058. if (this.selectMsgList.findIndex( m => m.id === msg.id) > -1) {
  3059. this.selectMsgList.splice(this.selectMsgList.findIndex( m => m.id === msg.id), 1);
  3060. } else {
  3061. this.selectMsgList.push(msg);
  3062. }
  3063. }
  3064. var checkList = this.messageListNode.querySelectorAll(".check-box-select-item")
  3065. checkList.forEach(item => {
  3066. var checkMsg = item.retrieve("msg")
  3067. if (this.selectMsgList.findIndex( m => m.id === checkMsg.id) > -1) {
  3068. item.checked = true
  3069. } else {
  3070. item.checked = false
  3071. }
  3072. })
  3073. },
  3074. _addScrollListener: function () {
  3075. console.debug('_addScrollListener ', this.messageListContainerNode);
  3076. this.messageListContainerNode.addEvents({
  3077. "scroll": function () {
  3078. // 检查是否滚动到底部
  3079. if (this.messageListContainerNode.scrollTop + this.messageListContainerNode.clientHeight >= this.messageListContainerNode.scrollHeight) {
  3080. this.loadMoreMsgCollectionList(); // 加载更多内容
  3081. }
  3082. }.bind(this)
  3083. });
  3084. },
  3085. // 加载更多
  3086. loadMoreMsgCollectionList: function () {
  3087. if (!this.hasMoreCollection) return;
  3088. this.page += 1;
  3089. this.loadMsgCollectionList()
  3090. },
  3091. // 分页查询收藏列表
  3092. loadMsgCollectionList: function () {
  3093. if (this.isLoadingCollection) return;
  3094. if (this.page === 1) {
  3095. while (this.messageListNode.firstChild) {
  3096. this.messageListNode.removeChild(
  3097. this.messageListNode.firstChild
  3098. )
  3099. }
  3100. this.collectionList = []
  3101. }
  3102. this.isLoadingCollection = true;
  3103. o2.Actions.load("x_message_assemble_communicate").ImAction.collectionListByPaging(''+this.page, '20', {}, function (json) {
  3104. let list = json.data;
  3105. if (list && list.length > 0) {
  3106. for (let i = 0; i < list.length; i++) {
  3107. const msg = list[i];
  3108. this._renderMsgItem(msg.message);
  3109. this.collectionList.push(msg); // 存储收藏列表
  3110. }
  3111. }
  3112. this.hasMoreCollection = (list && list.length === 20);
  3113. this.isLoadingCollection = false;
  3114. }.bind(this), function (error) {
  3115. console.error(error);
  3116. this.hasMoreCollection = false;
  3117. this.isLoadingCollection = false;
  3118. }.bind(this));
  3119. },
  3120. loadMsgList: function (){
  3121. var msgBody = JSON.parse(this.msg.body)
  3122. var messageHistoryIds = msgBody.messageHistoryIds;
  3123. if (messageHistoryIds && messageHistoryIds.length > 0) {
  3124. o2.Actions.load("x_message_assemble_communicate").ImAction.msgListObject({msgIdList: messageHistoryIds }, function (json) {
  3125. var list = json.data;
  3126. if (list && list.length > 0) {
  3127. for (let i = 0; i < list.length; i++) {
  3128. const msg = list[i];
  3129. this._renderMsgItem(msg)
  3130. }
  3131. }
  3132. }.bind(this), function (error) {
  3133. console.error(error);
  3134. }.bind(this));
  3135. }
  3136. },
  3137. clickMsgItem(e, quoteMessage) {
  3138. e.stopPropagation();
  3139. var msg = e.event.currentTarget.retrieve("msg");
  3140. if (!msg || !msg.body) {
  3141. console.error('错误的 target!!!');
  3142. return;
  3143. }
  3144. if (this.selectMode) {
  3145. if (quoteMessage) {
  3146. return;
  3147. }
  3148. this._selectOrUnSelectMsg(msg)
  3149. } else {
  3150. this.main.openMsgItem(msg);
  3151. }
  3152. },
  3153. _renderMsgItem: function (msg) {
  3154. var msgBody = JSON.parse(msg.body)
  3155. var msgItemNode = new Element("div", {"class": "chat-msg"}).inject(this.messageListNode);
  3156. msgItemNode.store("msg", msg);
  3157. msgItemNode.addEvents({
  3158. "click": function(e) {
  3159. this.clickMsgItem(e);
  3160. }.bind(this)
  3161. })
  3162. /// checkbox
  3163. var checkBoxClass = "chat-msg-checkbox none"
  3164. if (this.selectMode) {
  3165. checkBoxClass = "chat-msg-checkbox block"
  3166. }
  3167. var msgItemCheckBoxNode = new Element("div", {"class": checkBoxClass}).inject(msgItemNode);
  3168. var msgItemCheckBoxInputNode = new Element("input", {"type": "checkbox", "class": "check-box-select-item"}).inject(msgItemCheckBoxNode);
  3169. msgItemCheckBoxInputNode.store("msg", msg)
  3170. /// 消息体
  3171. var receiverBodyNode = new Element("div", { "class": "chat-sender", "id": msg.id}).inject(msgItemNode);
  3172. /// 消息时间
  3173. var timeNode = new Element("div", { "class": "chat-msg-time", "style": "width: 48px;"}).inject(msgItemNode);
  3174. timeNode.set("text", this.main._msgShowTime(o2.common.toDate(msg.createTime)))
  3175. var avatarNode = new Element("div", {"class": "chat-sender-avatar"}).inject(receiverBodyNode);
  3176. var avatarUrl = this.main.main._getIcon(msg.createPerson);
  3177. var name = msg.createPerson;
  3178. if (msg.createPerson.indexOf("@") > -1) {
  3179. name = name.substring(0, msg.createPerson.indexOf("@"));
  3180. }
  3181. new Element("img", { "src": avatarUrl }).inject(avatarNode);
  3182. new Element("div", { "text": name , "class": "chat-sender-name"}).inject(receiverBodyNode);
  3183. var lastNodeClass = "chat-sender-box"
  3184. if (msgBody.type === "process" || msgBody.type === "cms") {
  3185. lastNodeClass = "chat-sender-card-box"
  3186. }
  3187. var lastNode = new Element("div", {"class": lastNodeClass}).inject(receiverBodyNode);
  3188. var lastFirstNode = new Element("div", { "class": "chat-left_triangle" }).inject(lastNode);
  3189. //text
  3190. if (msgBody.type === "emoji") { // 表情
  3191. var img = "";
  3192. for (var i = 0; i < this.main.main.emojiList.length; i++) {
  3193. if (msgBody.body === this.main.main.emojiList[i].key) {
  3194. img = this.main.main.emojiList[i].path;
  3195. }
  3196. }
  3197. new Element("img", { "src": img, "class": "chat-content-emoji" }).inject(lastNode);
  3198. } else if (msgBody.type === "image") {//image
  3199. var imgBox = new Element("div", { "class": "img-chat" }).inject(lastNode);
  3200. var url = this.main._getFileUrlWithWH(msgBody.fileId, 144, 192);
  3201. if (msgBody.fileExtension && msgBody.fileExtension.toLowerCase() === "webp") {
  3202. url = this.main._getFileDownloadUrl(msgBody.fileId);
  3203. }
  3204. new Element("img", { "src": url }).inject(imgBox);
  3205. } else if (msgBody.type === "audio") {
  3206. var url = this.main._getFileDownloadUrl(msgBody.fileId);
  3207. new Element("audio", { "src": url, "controls": "controls", "preload": "preload" }).inject(lastNode);
  3208. } else if (msgBody.type === "location") {
  3209. var mapBox = new Element("span", {"style": "display: flex;gap: 5px;align-items: center;"}).inject(lastNode);
  3210. new Element("img", { "src": "../x_component_IMV2/$Main/default/icons/location.png", "width": 24, "height": 24 }).inject(mapBox);
  3211. new Element("span", { "text": msgBody.address }).inject(mapBox);
  3212. } else if (msgBody.type === "file") { //文件
  3213. // 视频文件 mp4 avi ogg
  3214. if (msgBody.fileExtension
  3215. && (msgBody.fileExtension.toLowerCase() === "mp4" || msgBody.fileExtension.toLowerCase() === "avi" || msgBody.fileExtension.toLowerCase() === "ogg")) {
  3216. // var videoType = "video/" + msgBody.fileExtension.toLowerCase();
  3217. new Element("video", {"class": "chat-content-video", "src": this.main._getFileDownloadUrl(msgBody.fileId), "controls": "controls", "preload": "preload"}).inject(lastNode);
  3218. } else {
  3219. var mapBox = new Element("span", {"style": "display: flex;gap: 5px;align-items: center;"}).inject(lastNode);
  3220. var fileIcon = this.main._getFileIcon(msgBody.fileExtension);
  3221. new Element("img", { "src": "../x_component_IMV2/$Main/file_icons/" + fileIcon, "width": 48, "height": 48 }).inject(mapBox);
  3222. new Element("span", {"text": msgBody.fileName }).inject(mapBox);
  3223. }
  3224. } else if (msgBody.type === "process") {
  3225. var cardNode = new Element("div", {"class": "chat-card"}).inject(lastNode);
  3226. // 流程名称
  3227. new Element("div", {"class": "chat-card-type", "text": "【"+msgBody.processName+"】"}).inject(cardNode);
  3228. // 工作标题
  3229. var title = msgBody.title;
  3230. if (title == null || title === "") {
  3231. title = "【"+msgBody.processName+"】- " + this.lp.noTitle;
  3232. }
  3233. new Element("div", {"class": "chat-card-body", "text":title}).inject(cardNode);
  3234. var cardFooter = new Element("div", {"class": "chat-card-bottom"}).inject(cardNode);
  3235. var appIconNode = new Element("img", {"class": "chat-card-bottom-icon"}).inject(cardFooter);
  3236. this.main._loadProcessApplicationIcon(msgBody.application, function(appIcon) {
  3237. if (appIcon && appIcon.icon) {
  3238. appIconNode.set("src", "data:image/png;base64," + appIcon.icon);
  3239. } else {
  3240. console.log('没有找到应用图标');
  3241. appIconNode.set("src", "../x_component_process_ApplicationExplorer/$Main/default/icon/application.png");
  3242. }
  3243. })
  3244. new Element("div", { "class": "chat-card-bottom-name", "text": msgBody.applicationName }).inject(cardFooter);
  3245. } else if (msgBody.type === "cms") {
  3246. } else if (msgBody.type === "messageHistory") { // 聊天记录
  3247. var cardNode = new Element("div", {"class": "chat-card"}).inject(lastNode);
  3248. // title
  3249. new Element("div", {"class": "chat-card-type", "text": msgBody.messageHistoryTitle}).inject(cardNode);
  3250. // desc
  3251. new Element("div", {"class": "chat-card-body", "text": msgBody.messageHistoryDesc }).inject(cardNode);
  3252. var cardFooter = new Element("div", {"class": "chat-card-bottom"}).inject(cardNode);
  3253. new Element("div", { "class": "chat-card-bottom-name", "text": this.lp.msgHistory }).inject(cardFooter);
  3254. } else {//text
  3255. new Element("span", { "text": this.main.contentEscapeBackToSymbol(msgBody.body) }).inject(lastNode);
  3256. }
  3257. // 引用消息
  3258. if (msg.quoteMessage) {
  3259. let quoteMessage = msg.quoteMessage;
  3260. let node = this.main._newQuoteMessageElement(quoteMessage, receiverBodyNode);
  3261. node.classList.add("chat-sender-quote-msg");
  3262. node.store("msg", quoteMessage);
  3263. node.addEvents({
  3264. "click": function(e) {
  3265. this.clickMsgItem(e, true);
  3266. }.bind(this)
  3267. });
  3268. }
  3269. }
  3270. });