layim.js 72 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324
  1. /**
  2. @Name:layim v3.9.1 Pro 商用版
  3. @Author:贤心
  4. @Site:http://layim.layui.com
  5. @License:LGPL
  6. */
  7. layui.define(['layer', 'laytpl', 'upload'], function(exports) {
  8. var v = '3.9.1';
  9. var $ = layui.$;
  10. var layer = layui.layer;
  11. var laytpl = layui.laytpl;
  12. var device = layui.device();
  13. var SHOW = 'layui-show',
  14. THIS = 'layim-this',
  15. MAX_ITEM = 20;
  16. //回调
  17. var call = {};
  18. //对外API
  19. var LAYIM = function() {
  20. this.v = v;
  21. $('body').on('click', '*[layim-event]', function(e) {
  22. var othis = $(this),
  23. methid = othis.attr('layim-event');
  24. events[methid] ? events[methid].call(this, othis, e) : '';
  25. });
  26. };
  27. //基础配置
  28. LAYIM.prototype.config = function(options) {
  29. var skin = [];
  30. layui.each(Array(5), function(index) {
  31. skin.push(layui.cache.dir + 'css/modules/layim/skin/' + (index + 1) + '.jpg')
  32. });
  33. options = options || {};
  34. options.skin = options.skin || [];
  35. layui.each(options.skin, function(index, item) {
  36. skin.unshift(item);
  37. });
  38. options.skin = skin;
  39. options = $.extend({
  40. isfriend: !0,
  41. isgroup: !0,
  42. voice: 'default.mp3'
  43. }, options);
  44. if (!window.JSON || !window.JSON.parse) return;
  45. init(options);
  46. return this;
  47. };
  48. //监听事件
  49. LAYIM.prototype.on = function(events, callback) {
  50. if (typeof callback === 'function') {
  51. call[events] ? call[events].push(callback) : call[events] = [callback];
  52. }
  53. return this;
  54. };
  55. //获取所有缓存数据
  56. LAYIM.prototype.cache = function() {
  57. return cache;
  58. };
  59. //打开一个自定义的会话界面
  60. LAYIM.prototype.chat = function(data) {
  61. if (!window.JSON || !window.JSON.parse) return;
  62. return popchat(data), this;
  63. };
  64. //设置聊天界面最小化
  65. LAYIM.prototype.setChatMin = function() {
  66. return setChatMin(), this;
  67. };
  68. //设置当前会话状态
  69. LAYIM.prototype.setChatStatus = function(str) {
  70. var thatChat = thisChat();
  71. if (!thatChat) return;
  72. var status = thatChat.elem.find('.layim-chat-status');
  73. return status.html(str), this;
  74. };
  75. //接受消息
  76. LAYIM.prototype.getMessage = function(data) {
  77. return getMessage(data), this;
  78. };
  79. //桌面消息通知
  80. LAYIM.prototype.notice = function(data) {
  81. return notice(data), this;
  82. };
  83. //打开添加好友/群组面板
  84. LAYIM.prototype.add = function(data) {
  85. return popAdd(data), this;
  86. };
  87. //好友分组面板
  88. LAYIM.prototype.setFriendGroup = function(data) {
  89. return popAdd(data, 'setGroup'), this;
  90. };
  91. //消息盒子的提醒
  92. LAYIM.prototype.msgbox = function(nums) {
  93. return msgbox(nums), this;
  94. };
  95. //添加好友/群
  96. LAYIM.prototype.addList = function(data) {
  97. return addList(data), this;
  98. };
  99. //删除好友/群
  100. LAYIM.prototype.removeList = function(data) {
  101. return removeList(data), this;
  102. };
  103. //设置好友在线/离线状态
  104. LAYIM.prototype.setFriendStatus = function(id, type) {
  105. var list = $('.layim-friend' + id);
  106. list[type === 'online' ? 'removeClass' : 'addClass']('layim-list-gray');
  107. };
  108. //解析聊天内容
  109. LAYIM.prototype.content = function(content) {
  110. return layui.data.content(content);
  111. };
  112. //主模板
  113. var listTpl = function(options) {
  114. var nodata = {
  115. friend: "该分组下暂无好友",
  116. group: "暂无群组",
  117. history: "暂无历史会话"
  118. };
  119. options = options || {};
  120. options.item = options.item || ('d.' + options.type);
  121. return ['{{# var length = 0; layui.each(' + options.item + ', function(i, data){ length++; }}',
  122. '<li layim-event="chat" data-type="' + options.type + '" data-index="{{ ' + (options
  123. .index || 'i') + ' }}" class="layim-' + (options.type === 'history' ? '{{i}}' : options
  124. .type + '{{data.id}}') +
  125. ' {{ data.status === "offline" ? "layim-list-gray" : "" }}"><img src="{{ data.avatar }}"><span>{{ data.username||data.groupname||data.name||"佚名" }}</span><p>{{ data.remark||data.sign||"" }}</p><span class="layim-msg-status">new</span></li>',
  126. '{{# }); if(length === 0){ }}', '<li class="layim-null">' + (nodata[options.type] ||
  127. "暂无数据") + '</li>', '{{# } }}'
  128. ].join('');
  129. };
  130. var elemTpl = ['<div class="layui-layim-main">', '<div class="layui-layim-info">',
  131. '<div class="layui-layim-user">{{ d.mine.username }}</div>', '<div class="layui-layim-status">',
  132. '{{# if(d.mine.status === "online"){ }}',
  133. '<span class="layui-icon layim-status-online" layim-event="status" lay-type="show">&#xe617;</span>',
  134. '{{# } else if(d.mine.status === "hide") { }}',
  135. '<span class="layui-icon layim-status-hide" layim-event="status" lay-type="show">&#xe60f;</span>',
  136. '{{# } }}', '<ul class="layui-anim layim-menu-box">',
  137. '<li {{d.mine.status === "online" ? "class=layim-this" : ""}} layim-event="status" lay-type="online"><i class="layui-icon">&#xe605;</i><cite class="layui-icon layim-status-online">&#xe617;</cite>在线</li>',
  138. '<li {{d.mine.status === "hide" ? "class=layim-this" : ""}} layim-event="status" lay-type="hide"><i class="layui-icon">&#xe605;</i><cite class="layui-icon layim-status-hide">&#xe60f;</cite>隐身</li>',
  139. '</ul>', '</div>',
  140. '<input class="layui-layim-remark" placeholder="编辑签名" value="{{ d.mine.remark||d.mine.sign||"" }}">',
  141. '</div>',
  142. '<ul class="layui-unselect layui-layim-tab{{# if(!d.base.isfriend || !d.base.isgroup){ }}',
  143. ' layim-tab-two', '{{# } }}">', '<li class="layui-icon', '{{# if(!d.base.isfriend){ }}',
  144. ' layim-hide', '{{# } else { }}', ' layim-this', '{{# } }}',
  145. '" title="联系人" layim-event="tab" lay-type="friend">&#xe612;</li>', '<li class="layui-icon',
  146. '{{# if(!d.base.isgroup){ }}', ' layim-hide', '{{# } else if(!d.base.isfriend) { }}', ' layim-this',
  147. '{{# } }}', '" title="群组" layim-event="tab" lay-type="group">&#xe613;</li>',
  148. '<li class="layui-icon" title="历史会话" layim-event="tab" lay-type="history">&#xe611;</li>', '</ul>',
  149. '<ul class="layui-unselect layim-tab-content {{# if(d.base.isfriend){ }}layui-show{{# } }} layim-list-friend">',
  150. '{{# layui.each(d.friend, function(index, item){ var spread = d.local["spread"+index]; }}', '<li>',
  151. '<h5 layim-event="spread" lay-type="{{ spread }}" data-ind="{{index}}"><i class="layui-icon">{{# if(spread === "true"){ }}&#xe61a;{{# } else { }}&#xe602;{{# } }}</i><span>{{ item.groupname||"未命名分组"+index }}</span><em>(<cite class="layim-count" style="color:#000;"> {{ (item.list||[]).length }}</cite>)</em></h5>',
  152. '<ul class="layui-layim-list {{# if(spread === "true"){ }}', ' layui-show', '{{# } }}">', listTpl({
  153. type: "friend",
  154. item: "item.list",
  155. index: "index"
  156. }), '</ul>', '</li>', '{{# }); if(d.friend.length === 0){ }}',
  157. '<li><ul class="layui-layim-list layui-show"><li class="layim-null">暂无联系人</li></ul>', '{{# } }}',
  158. '</ul>',
  159. '<ul class="layui-unselect layim-tab-content {{# if(!d.base.isfriend && d.base.isgroup){ }}layui-show{{# } }}">',
  160. '<li>', '<ul class="layui-layim-list layui-show layim-list-group">', listTpl({
  161. type: 'group'
  162. }), '</ul>', '</li>', '</ul>',
  163. '<ul class="layui-unselect layim-tab-content {{# if(!d.base.isfriend && !d.base.isgroup){ }}layui-show{{# } }}">',
  164. '<li>', '<ul class="layui-layim-list layui-show layim-list-history">', listTpl({
  165. type: 'history'
  166. }), '</ul>', '</li>', '</ul>', '<ul class="layui-unselect layim-tab-content">', '<li>',
  167. '<ul class="layui-layim-list layui-show" id="layui-layim-search"></ul>', '</li>', '</ul>',
  168. '<ul class="layui-unselect layui-layim-tool">',
  169. '<li class="layui-icon layim-tool-search" layim-event="search" title="搜索">&#xe615;</li>',
  170. '{{# if(d.base.msgbox){ }}',
  171. '<li class="layui-icon layim-tool-msgbox" layim-event="msgbox" title="消息盒子">&#xe645;<span class="layui-anim"></span></li>',
  172. '{{# } }}', '{{# if(d.base.find){ }}',
  173. '<li class="layui-icon layim-tool-find" layim-event="find" title="查找">&#xe608;</li>', '{{# } }}',
  174. '<li class="layui-icon layim-tool-skin" layim-event="skin" title="更换背景">&#xe61b;</li>',
  175. '{{# if(!d.base.copyright){ }}',
  176. '<li class="layui-icon layim-tool-about" layim-event="about" title="关于">&#xe60b;</li>', '{{# } }}',
  177. '</ul>',
  178. '<div class="layui-layim-search"><input><label class="layui-icon" layim-event="closeSearch">&#x1007;</label></div>',
  179. '</div>'
  180. ].join('');
  181. //换肤模版
  182. var elemSkinTpl = ['<ul class="layui-layim-skin">', '{{# layui.each(d.skin, function(index, item){ }}',
  183. '<li><img layim-event="setSkin" src="{{ item }}"></li>', '{{# }); }}',
  184. '<li layim-event="setSkin"><cite>简约</cite></li>', '</ul>'
  185. ].join('');
  186. //聊天主模板
  187. var elemChatTpl = ['<div class="layim-chat layim-chat-{{d.data.type}}{{d.first ? " layui-show" : ""}}">',
  188. '<div class="layui-unselect layim-chat-title">', '<div class="layim-chat-other">',
  189. '<img class="layim-{{ d.data.type }}{{ d.data.id }}" src="{{ d.data.avatar }}"><span class="layim-chat-username" layim-event="{{ d.data.type==="group" ? \"groupMembers\" : \"\" }}">{{ d.data.name||"佚名" }} {{d.data.temporary ? "<cite>临时会话</cite>" : ""}} {{# if(d.data.type==="group"){ }} <em class="layim-chat-members"></em><i class="layui-icon">&#xe61a;</i> {{# } }}</span>',
  190. '<p class="layim-chat-status"></p>', '</div>', '</div>', '<div class="layim-chat-main">',
  191. '<ul></ul>', '</div>', '<div class="layim-chat-footer">',
  192. '<div class="layui-unselect layim-chat-tool" data-json="{{encodeURIComponent(JSON.stringify(d.data))}}">',
  193. '<span class="layui-icon layim-tool-face" title="选择表情" layim-event="face">&#xe60c;</span>',
  194. '{{# if(d.base && d.base.uploadImage){ }}',
  195. '<span class="layui-icon layim-tool-image" title="上传图片" layim-event="image">&#xe60d;<input type="file" name="file"></span>',
  196. '{{# }; }}', '{{# if(d.base && d.base.uploadFile){ }}',
  197. '<span class="layui-icon layim-tool-image" title="发送文件" layim-event="image" data-type="file">&#xe61d;<input type="file" name="file"></span>',
  198. '{{# }; }}', '{{# if(d.base && d.base.isAudio){ }}',
  199. '<span class="layui-icon layim-tool-audio" title="发送网络音频" layim-event="media" data-type="audio">&#xe6fc;</span>',
  200. '{{# }; }}', '{{# if(d.base && d.base.isVideo){ }}',
  201. '<span class="layui-icon layim-tool-video" title="发送网络视频" layim-event="media" data-type="video">&#xe6ed;</span>',
  202. '{{# }; }}', '{{# layui.each(d.base.tool, function(index, item){ }}',
  203. '<span class="layui-icon layim-tool-{{item.alias}}" title="{{item.title}}" layim-event="extend" lay-filter="{{ item.alias }}">{{item.icon}}</span>',
  204. '{{# }); }}', '{{# if(d.base && d.base.chatLog){ }}',
  205. '<span class="layim-tool-log" layim-event="chatLog"><i class="layui-icon">&#xe60e;</i>聊天记录</span>',
  206. '{{# }; }}', '</div>', '<div class="layim-chat-textarea"><textarea></textarea></div>',
  207. '<div class="layim-chat-bottom">', '<div class="layim-chat-send">', '{{# if(!d.base.brief){ }}',
  208. '<span class="layim-send-close" layim-event="closeThisChat">关闭</span>', '{{# } }}',
  209. '<span class="layim-send-btn" layim-event="send">发送</span>',
  210. '<span class="layim-send-set" layim-event="setSend" lay-type="show"><em class="layui-edge"></em></span>',
  211. '<ul class="layui-anim layim-menu-box">',
  212. '<li {{d.local.sendHotKey !== "Ctrl+Enter" ? "class=layim-this" : ""}} layim-event="setSend" lay-type="Enter"><i class="layui-icon">&#xe605;</i>按Enter键发送消息</li>',
  213. '<li {{d.local.sendHotKey === "Ctrl+Enter" ? "class=layim-this" : ""}} layim-event="setSend" lay-type="Ctrl+Enter"><i class="layui-icon">&#xe605;</i>按Ctrl+Enter键发送消息</li>',
  214. '</ul>', '</div>', '</div>', '</div>', '</div>'
  215. ].join('');
  216. //添加好友群组模版
  217. var elemAddTpl = ['<div class="layim-add-box">',
  218. '<div class="layim-add-img"><img class="layui-circle" src="{{ d.data.avatar }}"><p>{{ d.data.name||"" }}</p></div>',
  219. '<div class="layim-add-remark">', '{{# if(d.data.type === "friend" && d.type === "setGroup"){ }}',
  220. '<p>选择分组</p>', '{{# } if(d.data.type === "friend"){ }}',
  221. '<select class="layui-select" id="LAY_layimGroup">',
  222. '{{# layui.each(d.data.group, function(index, item){ }}',
  223. '<option value="{{ item.id }}">{{ item.groupname }}</option>', '{{# }); }}', '</select>',
  224. '{{# } }}', '{{# if(d.data.type === "group"){ }}', '<p>请输入验证信息</p>',
  225. '{{# } if(d.type !== "setGroup"){ }}',
  226. '<textarea id="LAY_layimRemark" placeholder="验证信息" class="layui-textarea"></textarea>', '{{# } }}',
  227. '</div>', '</div>'
  228. ].join('');
  229. //聊天内容列表模版
  230. var elemChatMain = [
  231. '<li {{ d.mine ? "class=layim-chat-mine" : "" }} {{# if(d.cid){ }}data-cid="{{d.cid}}"{{# } }}>',
  232. '<div class="layim-chat-user"><img src="{{ d.avatar }}"><cite>', '{{# if(d.mine){ }}',
  233. '<i style="color:#ccc;">{{ layui.data.date(d.timestamp) }}</i>{{ d.username||"佚名" }}', '{{# } else { }}',
  234. '{{ d.username||"佚名" }}<i style="color:#ccc;">{{ layui.data.date(d.timestamp) }}</i>', '{{# } }}', '</cite></div>',
  235. '<div class="layim-chat-text">{{ layui.data.content(d.content||"&nbsp") }}</div>', '</li>'
  236. ].join('');
  237. var elemChatList =
  238. '<li class="layim-{{ d.data.type }}{{ d.data.id }} layim-chatlist-{{ d.data.type }}{{ d.data.id }} layim-this" layim-event="tabChat"><img src="{{ d.data.avatar }}"><span>{{ d.data.name||"佚名" }}</span>{{# if(!d.base.brief){ }}<i class="layui-icon" layim-event="closeChat">&#x1007;</i>{{# } }}</li>';
  239. //补齐数位
  240. var digit = function(num) {
  241. return num < 10 ? '0' + (num | 0) : num;
  242. };
  243. //转换时间
  244. layui.data.date = function(timestamp) {
  245. var d = new Date(timestamp || new Date());
  246. return d.getFullYear() + '-' + digit(d.getMonth() + 1) + '-' + digit(d.getDate()) +
  247. ' ' + digit(d.getHours()) + ':' + digit(d.getMinutes()) + ':' + digit(d.getSeconds());
  248. };
  249. //转换内容
  250. layui.data.content = function(content) {
  251. //支持的html标签
  252. var html = function(end) {
  253. return new RegExp('\\n*\\[' + (end || '') +
  254. '(code|pre|div|span|p|table|thead|th|tbody|tr|td|ul|li|ol|li|dl|dt|dd|h2|h3|h4|h5)([\\s\\S]*?)\\]\\n*',
  255. 'g');
  256. };
  257. content = (content || '').replace(/&(?!#?[a-zA-Z0-9]+;)/g, '&amp;')
  258. .replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/'/g, '&#39;').replace(/"/g,
  259. '&quot;') //XSS
  260. .replace(/@(\S+)(\s+?|$)/g, '@<a href="javascript:;">$1</a>$2') //转义@
  261. .replace(/face\[([^\s\[\]]+?)\]/g, function(face) { //转义表情
  262. var alt = face.replace(/^face/g, '');
  263. return '<img alt="' + alt + '" title="' + alt + '" src="' + faces[alt] + '">';
  264. })
  265. .replace(/img\[([^\s]+?)\]/g, function(img) { //转义图片
  266. return '<img class="layui-layim-photos" src="' + img.replace(/(^img\[)|(\]$)/g, '') +
  267. '">';
  268. })
  269. .replace(/file\([\s\S]+?\)\[[\s\S]*?\]/g, function(str) { //转义文件
  270. var href = (str.match(/file\(([\s\S]+?)\)\[/) || [])[1];
  271. var text = (str.match(/\)\[([\s\S]*?)\]/) || [])[1];
  272. if (!href) return str;
  273. return '<a class="layui-layim-file" href="' + href +
  274. '" download target="_blank"><i class="layui-icon">&#xe61e;</i><cite>' + (text ||
  275. href) + '</cite></a>';
  276. })
  277. .replace(/audio\[([^\s]+?)\]/g, function(audio) { //转义音频
  278. return '<div class="layui-unselect layui-layim-audio" layim-event="playAudio" data-src="' +
  279. audio.replace(/(^audio\[)|(\]$)/g, '') +
  280. '"><i class="layui-icon">&#xe652;</i><p>音频消息</p></div>';
  281. })
  282. .replace(/video\[([^\s]+?)\]/g, function(video) { //转义音频
  283. return '<div class="layui-unselect layui-layim-video" layim-event="playVideo" data-src="' +
  284. video.replace(/(^video\[)|(\]$)/g, '') +
  285. '"><i class="layui-icon">&#xe652;</i></div>';
  286. })
  287. .replace(/a\([\s\S]+?\)\[[\s\S]*?\]/g, function(str) { //转义链接
  288. var href = (str.match(/a\(([\s\S]+?)\)\[/) || [])[1];
  289. var text = (str.match(/\)\[([\s\S]*?)\]/) || [])[1];
  290. if (!href) return str;
  291. return '<a href="' + href + '" target="_blank">' + (text || href) + '</a>';
  292. }).replace(html(), '\<$1 $2\>').replace(html('/'), '\</$1\>') //转移HTML代码
  293. .replace(/\n/g, '<br>') //转义换行
  294. return content;
  295. };
  296. //Ajax
  297. var post = function(options, callback, tips) {
  298. options = options || {};
  299. return $.ajax({
  300. url: options.url,
  301. type: options.type || 'get',
  302. data: options.data,
  303. dataType: options.dataType || 'json',
  304. cache: false,
  305. success: function(res) {
  306. res.code == 0 ?
  307. callback && callback(res.data || {}) :
  308. layer.msg(res.msg || ((tips || 'Error') + ': LAYIM_NOT_GET_DATA'), {
  309. time: 5000
  310. });
  311. },
  312. error: function(err, msg) {
  313. window.console && console.log && console.error('LAYIM_DATE_ERROR:' + msg);
  314. }
  315. });
  316. };
  317. let typesData = "";
  318. var groupIdLi=[];
  319. var getallName=function(){
  320. var userId=localStorage.getItem("user_id")||getCookie("user_id");
  321. $.post("/friendTypeController/getFriendType",{"userId":userId},function (res) {
  322. let data = eval("("+res+")");
  323. $.each(data,function(k,v){
  324. typesData+=v.typeName+",";
  325. });
  326. })
  327. $.post("/api/qun/getGroupByUserId",{"userId":userId},function (res) {
  328. var data = eval("("+res+")");
  329. $.each(data,function (k,v) {
  330. groupIdLi.push({"groupId":v.id,"groupMaster":v.userId});
  331. })
  332. })
  333. }
  334. getallName();
  335. //处理初始化信息
  336. var cache = {
  337. message: {},
  338. chat: []
  339. },
  340. init = function(options) {
  341. var init = options.init || {}
  342. mine = init.mine || {}, local = layui.data('layim')[mine.id] || {}, obj = {
  343. base: options,
  344. local: local,
  345. mine: mine,
  346. history: local.history || {}
  347. }, create = function(data) {
  348. var mine = data.mine || {};
  349. var local = layui.data('layim')[mine.id] || {},
  350. obj = {
  351. base: options //基础配置信息
  352. ,
  353. local: local //本地数据
  354. ,
  355. mine: mine //我的用户信息
  356. ,
  357. friend: data.friend || [] //联系人信息
  358. ,
  359. group: data.group || [] //群组信息
  360. ,
  361. history: local.history || {} //历史会话信息
  362. ,
  363. allName:typesData
  364. ,
  365. allGroupId:groupIdLi
  366. };
  367. cache = $.extend(cache, obj);
  368. popim(laytpl(elemTpl).render(obj));
  369. if (local.close || options.min) {
  370. popmin();
  371. }
  372. layui.each(call.ready, function(index, item) {
  373. item && item(obj);
  374. });
  375. };
  376. cache = $.extend(cache, obj);
  377. if (options.brief) {
  378. return layui.each(call.ready, function(index, item) {
  379. item && item(obj);
  380. });
  381. };
  382. init.url ? post(init, create, 'INIT') : create(init);
  383. };
  384. //显示主面板
  385. var layimMain, popim = function(content) {
  386. return layer.open({
  387. type: 1,
  388. area: ['260px', '520px'],
  389. skin: 'layui-box layui-layim',
  390. title: '&#8203;',
  391. offset: 'rb',
  392. id: 'layui-layim',
  393. shade: false,
  394. anim: 2,
  395. resize: false,
  396. content: content,
  397. success: function(layero) {
  398. layimMain = layero;
  399. setSkin(layero);
  400. if (cache.base.right) {
  401. layero.css('margin-left', '-' + cache.base.right);
  402. }
  403. if (layimClose) {
  404. layer.close(layimClose.attr('times'));
  405. }
  406. //按最新会话重新排列
  407. var arr = [],
  408. historyElem = layero.find('.layim-list-history');
  409. historyElem.find('li').each(function() {
  410. arr.push($(this).prop('outerHTML'))
  411. });
  412. if (arr.length > 0) {
  413. arr.reverse();
  414. historyElem.html(arr.join(''));
  415. }
  416. banRightMenu();
  417. events.sign();
  418. },
  419. cancel: function(index) {
  420. popmin();
  421. var local = layui.data('layim')[cache.mine.id] || {};
  422. local.close = true;
  423. layui.data('layim', {
  424. key: cache.mine.id,
  425. value: local
  426. });
  427. return false;
  428. }
  429. });
  430. };
  431. //屏蔽主面板右键菜单
  432. var banRightMenu = function() {
  433. layimMain.on('contextmenu', function(event) {
  434. event.cancelBubble = true
  435. event.returnValue = false;
  436. return false;
  437. });
  438. var hide = function() {
  439. layer.closeAll('tips');
  440. };
  441. //自定义历史会话右键菜单
  442. layimMain.find('.layim-list-history').on('contextmenu', 'li', function(e) {
  443. var othis = $(this);
  444. var html = '<ul data-id="' + othis[0].id + '" data-index="' + othis.data('index') +
  445. '"><li layim-event="menuHistory" data-type="one">移除该会话</li><li layim-event="menuHistory" data-type="all">清空全部会话列表</li></ul>';
  446. if (othis.hasClass('layim-null')) return;
  447. layer.tips(html, this, {
  448. tips: 1,
  449. time: 0,
  450. anim: 5,
  451. fixed: true,
  452. skin: 'layui-box layui-layim-contextmenu',
  453. success: function(layero) {
  454. var stopmp = function(e) {
  455. stope(e);
  456. };
  457. layero.off('mousedown', stopmp).on('mousedown', stopmp);
  458. }
  459. });
  460. $(document).off('mousedown', hide).on('mousedown', hide);
  461. $(window).off('resize', hide).on('resize', hide);
  462. });
  463. //自定义好友列表会话右键菜单
  464. layimMain.find('.layim-list-friend .layui-layim-list>li').on('contextmenu', '', function(e) {
  465. var othis = $(this);
  466. let oind = othis.index();
  467. var html = '<ul data-id="' + othis[0].id + '" data-index="' + othis.data('index') +
  468. '" data-yzind="' + oind +
  469. '"><li layim-event="chat" data-type="friend">发送消息</li><li layim-event="chatLog" data-type="friend">消息记录</li><li layim-event="menuFriend" data-type="delfriend">删除好友</li></ul>';
  470. if (othis.hasClass('layim-null')) return;
  471. layer.tips(html, this, {
  472. tips: 1,
  473. time: 0,
  474. anim: 5,
  475. fixed: true,
  476. skin: 'layui-box layui-layim-contextmenu',
  477. success: function(layero) {
  478. var stopmp = function(e) {
  479. stope(e);
  480. };
  481. layero.off('mousedown', stopmp).on('mousedown', stopmp);
  482. }
  483. });
  484. $(document).off('mousedown', hide).on('mousedown', hide);
  485. $(window).off('resize', hide).on('resize', hide);
  486. });
  487. //自定义好友列表会话右键菜单
  488. layimMain.find('.layim-list-friend>li').on('contextmenu', 'h5', function(e) {
  489. var othis = $(this);
  490. var html = '<ul data-id="' + othis[0].id + '" data-index="' + othis.data('ind')+'"><li layim-event="menuFriend" data-type="resetname">重命名</li><li layim-event="menuFriend" data-type="delete">删除分组</li><li layim-event="menuFriend" data-type="newadd">新建分组</li></ul>';
  491. if (othis.hasClass('layim-null')) return;
  492. layer.tips(html, this, {
  493. tips: 1,
  494. time: 0,
  495. anim: 5,
  496. fixed: true,
  497. skin: 'layui-box layui-layim-contextmenu',
  498. success: function(layero) {
  499. var stopmp = function(e) {
  500. stope(e);
  501. };
  502. layero.off('mousedown', stopmp).on('mousedown', stopmp);
  503. }
  504. });
  505. $(document).off('mousedown', hide).on('mousedown', hide);
  506. $(window).off('resize', hide).on('resize', hide);
  507. });
  508. //
  509. //自定义群列表会话右键菜单
  510. layimMain.find('.layim-list-group').on('contextmenu', 'li', function(e) {
  511. var othis = $(this);
  512. let oind = othis.index();
  513. let _obj=cache.allGroupId;
  514. let _id=cache["group"][oind].id;
  515. var userId = cache.mine.id;
  516. var html =`<ul data-id="${othis[0].id }" data-index="${othis.data('index')}" data-yzgroup="${oind }">
  517. <li layim-event="chat" data-type="group">发送消息</li>
  518. <li layim-event="chatLog" data-type="group">消息记录</li>
  519. <li layim-event="menuGroup" data-type="newadd">新建一个群</li>
  520. <li layim-event="menuGroup" data-type="dropout">退出群</li></ul>`;
  521. for(var i=0;i<_obj.length;i++){
  522. if(_id==_obj[i].groupId){
  523. if(userId==_obj[i].groupMaster){
  524. html=`<ul data-id="${othis[0].id }" data-index="${othis.data('index')}" data-yzgroup="${oind }">
  525. <li layim-event="chat" data-type="group">发送消息</li>
  526. <li layim-event="chatLog" data-type="group">消息记录</li>
  527. <li layim-event="menuGroup" data-type="newadd">新建一个群</li>
  528. <li layim-event="menuGroup" data-type="editinfo">修改群信息</li>
  529. <li layim-event="menuGroup" data-type="dissolve">解散群</li></ul>`;
  530. break;
  531. }
  532. }
  533. }
  534. if (othis.hasClass('layim-null')) return;
  535. layer.tips(html, this, {
  536. tips: 1,
  537. time: 0,
  538. anim: 5,
  539. fixed: true,
  540. skin: 'layui-box layui-layim-contextmenu',
  541. success: function(layero) {
  542. var stopmp = function(e) {
  543. stope(e);
  544. };
  545. layero.off('mousedown', stopmp).on('mousedown', stopmp);
  546. }
  547. });
  548. $(document).off('mousedown', hide).on('mousedown', hide);
  549. $(window).off('resize', hide).on('resize', hide);
  550. });
  551. }
  552. //主面板最小化状态
  553. var layimClose, popmin = function(content) {
  554. if (layimClose) {
  555. layer.close(layimClose.attr('times'));
  556. }
  557. if (layimMain) {
  558. layimMain.hide();
  559. }
  560. cache.mine = cache.mine || {};
  561. return layer.open({
  562. type: 1,
  563. title: false,
  564. id: 'layui-layim-close',
  565. skin: 'layui-box layui-layim-min layui-layim-close',
  566. shade: false,
  567. closeBtn: false,
  568. anim: 2,
  569. offset: 'rb',
  570. resize: false,
  571. content: '<img src="' + (cache.mine.avatar || (layui.cache
  572. .dir + 'css/pc/layim/skin/logo.jpg')) + '"><span>' + (content || cache.base
  573. .title || '我的LayIM') + '</span>',
  574. move: '#layui-layim-close img',
  575. success: function(layero, index) {
  576. layimClose = layero;
  577. if (cache.base.right) {
  578. layero.css('margin-left', '-' + cache.base.right);
  579. }
  580. layero.on('click', function() {
  581. layer.close(index);
  582. layimMain.show();
  583. var local = layui.data('layim')[cache.mine.id] || {};
  584. delete local.close;
  585. layui.data('layim', {
  586. key: cache.mine.id,
  587. value: local
  588. });
  589. });
  590. }
  591. });
  592. };
  593. //显示聊天面板
  594. var layimChat, layimMin, chatIndex, To = {},
  595. popchat = function(data) {
  596. data = data || {};
  597. var chat = $('#layui-layim-chat'),
  598. render = {
  599. data: data,
  600. base: cache.base,
  601. local: cache.local
  602. };
  603. if (!data.id) {
  604. return layer.msg('非法用户');
  605. }
  606. if (chat[0]) {
  607. var list = layimChat.find('.layim-chat-list');
  608. var listThat = list.find('.layim-chatlist-' + data.type + data.id);
  609. var hasFull = layimChat.find('.layui-layer-max').hasClass('layui-layer-maxmin');
  610. var chatBox = chat.children('.layim-chat-box');
  611. //如果是最小化,则还原窗口
  612. if (layimChat.css('display') === 'none') {
  613. layimChat.show();
  614. }
  615. if (layimMin) {
  616. layer.close(layimMin.attr('times'));
  617. }
  618. //如果出现多个聊天面板
  619. if (list.find('li').length === 1 && !listThat[0]) {
  620. hasFull || layimChat.css('width', 800);
  621. list.css({
  622. height: layimChat.height()
  623. }).show();
  624. chatBox.css('margin-left', '200px');
  625. }
  626. //打开的是非当前聊天面板,则新增面板
  627. if (!listThat[0]) {
  628. list.append(laytpl(elemChatList).render(render));
  629. chatBox.append(laytpl(elemChatTpl).render(render));
  630. syncGray(data);
  631. resizeChat();
  632. }
  633. changeChat(list.find('.layim-chatlist-' + data.type + data.id));
  634. listThat[0] || viewChatlog();
  635. setHistory(data);
  636. hotkeySend();
  637. return chatIndex;
  638. }
  639. render.first = !0;
  640. var index = chatIndex = layer.open({
  641. type: 1,
  642. area: '600px',
  643. skin: 'layui-box layui-layim-chat',
  644. id: 'layui-layim-chat',
  645. title: '&#8203;',
  646. shade: false,
  647. maxmin: true,
  648. offset: data.offset || 'auto',
  649. anim: data.anim || 0,
  650. closeBtn: cache.base.brief ? false : 1,
  651. content: laytpl('<ul class="layui-unselect layim-chat-list">' + elemChatList +
  652. '</ul><div class="layim-chat-box">' + elemChatTpl + '</div>').render(render),
  653. success: function(layero) {
  654. layimChat = layero;
  655. layero.css({
  656. 'min-width': '500px',
  657. 'min-height': '420px'
  658. });
  659. syncGray(data);
  660. typeof data.success === 'function' && data.success(layero);
  661. hotkeySend();
  662. setSkin(layero);
  663. setHistory(data);
  664. viewChatlog();
  665. showOffMessage();
  666. //聊天窗口的切换监听
  667. layui.each(call.chatChange, function(index, item) {
  668. item && item(thisChat());
  669. });
  670. //查看大图
  671. layero.on('dblclick', '.layui-layim-photos', function() {
  672. var src = this.src;
  673. layer.close(popchat.photosIndex);
  674. layer.photos({
  675. photos: {
  676. data: [{
  677. "alt": "大图模式",
  678. "src": src
  679. }]
  680. },
  681. shade: 0.01,
  682. closeBtn: 2,
  683. anim: 0,
  684. resize: false,
  685. success: function(layero, index) {
  686. popchat.photosIndex = index;
  687. }
  688. });
  689. });
  690. },
  691. full: function(layero) {
  692. layer.style(index, {
  693. width: '100%',
  694. height: '100%'
  695. }, true);
  696. resizeChat();
  697. },
  698. resizing: resizeChat,
  699. restore: resizeChat,
  700. min: function() {
  701. setChatMin();
  702. return false;
  703. },
  704. end: function() {
  705. layer.closeAll('tips');
  706. layimChat = null;
  707. }
  708. });
  709. return index;
  710. };
  711. //同步置灰状态
  712. var syncGray = function(data) {
  713. $('.layim-' + data.type + data.id).each(function() {
  714. if ($(this).hasClass('layim-list-gray')) {
  715. layui.layim.setFriendStatus(data.id, 'offline');
  716. }
  717. });
  718. };
  719. //重置聊天窗口大小
  720. var resizeChat = function() {
  721. var list = layimChat.find('.layim-chat-list'),
  722. chatMain = layimChat.find('.layim-chat-main'),
  723. chatHeight = layimChat.height();
  724. list.css({
  725. height: chatHeight
  726. });
  727. chatMain.css({
  728. height: chatHeight - 20 - 80 - 158
  729. })
  730. };
  731. //设置聊天窗口最小化 & 新消息提醒
  732. var setChatMin = function(newMsg) {
  733. var thatChat = newMsg || thisChat().data,
  734. base = layui.layim.cache().base;
  735. if (layimChat && !newMsg) {
  736. layimChat.hide();
  737. }
  738. layer.close(setChatMin.index);
  739. setChatMin.index = layer.open({
  740. type: 1,
  741. title: false,
  742. skin: 'layui-box layui-layim-min',
  743. shade: false,
  744. closeBtn: false,
  745. anim: thatChat.anim || 2,
  746. offset: 'b',
  747. move: '#layui-layim-min',
  748. resize: false,
  749. area: ['182px', '50px'],
  750. content: '<img id="layui-layim-min" src="' + thatChat.avatar + '"><span>' + thatChat
  751. .name + '</span>',
  752. success: function(layero, index) {
  753. if (!newMsg) layimMin = layero;
  754. if (base.minRight) {
  755. layer.style(index, {
  756. left: $(window).width() - layero.outerWidth() - parseFloat(base
  757. .minRight)
  758. });
  759. }
  760. layero.find('.layui-layer-content span').on('click', function() {
  761. layer.close(index);
  762. newMsg ? layui.each(cache.chat, function(i, item) {
  763. popchat(item);
  764. }) : layimChat.show();
  765. if (newMsg) {
  766. cache.chat = [];
  767. chatListMore();
  768. }
  769. });
  770. layero.find('.layui-layer-content img').on('click', function(e) {
  771. stope(e);
  772. });
  773. }
  774. });
  775. };
  776. //打开添加好友、群组面板、好友分组面板
  777. var popAdd = function(data, type) {
  778. data = data || {};
  779. layer.close(popAdd.index);
  780. return popAdd.index = layer.open({
  781. type: 1,
  782. area: '430px',
  783. title: {
  784. friend: '添加好友',
  785. group: '加入群组'
  786. } [data.type] || '',
  787. shade: false,
  788. resize: false,
  789. btn: type ? ['确认', '取消'] : ['发送申请', '关闭'],
  790. content: laytpl(elemAddTpl).render({
  791. data: {
  792. name: data.username || data.groupname,
  793. avatar: data.avatar,
  794. group: data.group || parent.layui.layim.cache().friend || [],
  795. type: data.type
  796. },
  797. type: type
  798. }),
  799. yes: function(index, layero) {
  800. var groupElem = layero.find('#LAY_layimGroup'),
  801. remarkElem = layero.find('#LAY_layimRemark')
  802. if (type) {
  803. data.submit && data.submit(groupElem.val(), index);
  804. } else {
  805. data.submit && data.submit(groupElem.val(), remarkElem.val(), index);
  806. }
  807. }
  808. });
  809. };
  810. //切换聊天
  811. var changeChat = function(elem, del) {
  812. elem = elem || $('.layim-chat-list .' + THIS);
  813. var index = elem.index() === -1 ? 0 : elem.index();
  814. var str = '.layim-chat',
  815. cont = layimChat.find(str).eq(index);
  816. var hasFull = layimChat.find('.layui-layer-max').hasClass('layui-layer-maxmin');
  817. if (del) {
  818. //如果关闭的是当前聊天,则切换聊天焦点
  819. if (elem.hasClass(THIS)) {
  820. changeChat(index === 0 ? elem.next() : elem.prev());
  821. }
  822. var length = layimChat.find(str).length;
  823. //关闭聊天界面
  824. if (length === 1) {
  825. return layer.close(chatIndex);
  826. }
  827. elem.remove();
  828. cont.remove();
  829. //只剩下1个列表,隐藏左侧区块
  830. if (length === 2) {
  831. layimChat.find('.layim-chat-list').hide();
  832. if (!hasFull) {
  833. layimChat.css('width', '600px');
  834. }
  835. layimChat.find('.layim-chat-box').css('margin-left', 0);
  836. }
  837. return false;
  838. }
  839. elem.addClass(THIS).siblings().removeClass(THIS);
  840. cont.addClass(SHOW).siblings(str).removeClass(SHOW);
  841. cont.find('textarea').focus();
  842. //聊天窗口的切换监听
  843. layui.each(call.chatChange, function(index, item) {
  844. item && item(thisChat());
  845. });
  846. showOffMessage();
  847. };
  848. //展示存在队列中的消息
  849. var showOffMessage = function() {
  850. var thatChat = thisChat();
  851. var message = cache.message[thatChat.data.type + thatChat.data.id];
  852. if (message) {
  853. //展现后,删除队列中消息
  854. delete cache.message[thatChat.data.type + thatChat.data.id];
  855. }
  856. };
  857. //获取当前聊天面板
  858. var thisChat = LAYIM.prototype.thisChat = function() {
  859. if (!layimChat) return;
  860. var index = $('.layim-chat-list .' + THIS).index();
  861. var cont = layimChat.find('.layim-chat').eq(index);
  862. var to = JSON.parse(decodeURIComponent(cont.find('.layim-chat-tool').data('json')));
  863. return {
  864. elem: cont,
  865. data: to,
  866. textarea: cont.find('textarea')
  867. };
  868. };
  869. //记录初始背景
  870. var setSkin = function(layero) {
  871. var local = layui.data('layim')[cache.mine.id] || {},
  872. skin = local.skin;
  873. layero.css({
  874. 'background-image': skin ? 'url(' + skin + ')' : function() {
  875. return cache.base.initSkin ?
  876. 'url(' + (layui.cache.dir + 'css/modules/layim/skin/' + cache.base
  877. .initSkin) + ')' :
  878. 'none';
  879. }()
  880. });
  881. };
  882. //记录历史会话
  883. var setHistory = function(data) {
  884. var local = layui.data('layim')[cache.mine.id] || {};
  885. var obj = {},
  886. history = local.history || {};
  887. var is = history[data.type + data.id];
  888. if (!layimMain) return;
  889. var historyElem = layimMain.find('.layim-list-history');
  890. data.historyTime = new Date().getTime();
  891. history[data.type + data.id] = data;
  892. local.history = history;
  893. layui.data('layim', {
  894. key: cache.mine.id,
  895. value: local
  896. });
  897. if (is) return;
  898. obj[data.type + data.id] = data;
  899. var historyList = laytpl(listTpl({
  900. type: 'history',
  901. item: 'd.data'
  902. })).render({
  903. data: obj
  904. });
  905. historyElem.prepend(historyList);
  906. historyElem.find('.layim-null').remove();
  907. };
  908. //发送消息
  909. var sendMessage = function() {
  910. var data = {
  911. username: cache.mine ? cache.mine.username : '访客',
  912. avatar: cache.mine ? cache.mine.avatar : (layui.cache.dir + 'css/pc/layim/skin/logo.jpg'),
  913. id: cache.mine ? cache.mine.id : null,
  914. mine: true
  915. };
  916. var thatChat = thisChat(),
  917. ul = thatChat.elem.find('.layim-chat-main ul');
  918. var maxLength = cache.base.maxLength || 3000;
  919. data.content = thatChat.textarea.val();
  920. if (data.content.replace(/\s/g, '') !== '') {
  921. if (data.content.length > maxLength) {
  922. return layer.msg('内容最长不能超过' + maxLength + '个字符')
  923. }
  924. ul.append(laytpl(elemChatMain).render(data));
  925. var param = {
  926. mine: data,
  927. to: thatChat.data
  928. },
  929. message = {
  930. username: param.mine.username,
  931. avatar: param.mine.avatar,
  932. id: param.to.id,
  933. type: param.to.type,
  934. content: param.mine.content,
  935. timestamp: new Date().getTime(),
  936. mine: true
  937. };
  938. pushChatlog(message);
  939. layui.each(call.sendMessage, function(index, item) {
  940. item && item(param);
  941. });
  942. }
  943. chatListMore();
  944. thatChat.textarea.val('').focus();
  945. };
  946. //桌面消息提醒
  947. var notice = function(data) {
  948. data = data || {};
  949. if (window.Notification) {
  950. if (Notification.permission === 'granted') {
  951. var notification = new Notification(data.title || '', {
  952. body: data.content || '',
  953. icon: data.avatar || 'http://tp2.sinaimg.cn/5488749285/50/5719808192/1'
  954. });
  955. } else {
  956. Notification.requestPermission();
  957. };
  958. }
  959. };
  960. //消息声音提醒
  961. var voice = function() {
  962. if (device.ie && device.ie < 9) return;
  963. var audio = document.createElement("audio");
  964. audio.src = layui.cache.dir + 'css/modules/layim/voice/' + cache.base.voice;
  965. audio.play();
  966. };
  967. //接受消息
  968. var messageNew = {},
  969. getMessage = function(data) {
  970. data = data || {};
  971. var elem = $('.layim-chatlist-' + data.type + data.id);
  972. var group = {},
  973. index = elem.index();
  974. data.timestamp = data.timestamp || new Date().getTime();
  975. if (data.fromid == cache.mine.id) {
  976. data.mine = true;
  977. }
  978. data.system || pushChatlog(data);
  979. messageNew = JSON.parse(JSON.stringify(data));
  980. if (cache.base.voice) {
  981. voice();
  982. }
  983. if ((!layimChat && data.content) || index === -1) {
  984. if (cache.message[data.type + data.id]) {
  985. cache.message[data.type + data.id].push(data)
  986. } else {
  987. cache.message[data.type + data.id] = [data];
  988. //记录聊天面板队列
  989. if (data.type === 'friend') {
  990. var friend;
  991. layui.each(cache.friend, function(index1, item1) {
  992. layui.each(item1.list, function(index, item) {
  993. if (item.id == data.id) {
  994. item.type = 'friend';
  995. item.name = item.username;
  996. cache.chat.push(item);
  997. return friend = true;
  998. }
  999. });
  1000. if (friend) return true;
  1001. });
  1002. if (!friend) {
  1003. data.name = data.username;
  1004. data.temporary = true; //临时会话
  1005. cache.chat.push(data);
  1006. }
  1007. } else if (data.type === 'group') {
  1008. var isgroup;
  1009. layui.each(cache.group, function(index, item) {
  1010. if (item.id == data.id) {
  1011. item.type = 'group';
  1012. item.name = item.groupname;
  1013. cache.chat.push(item);
  1014. return isgroup = true;
  1015. }
  1016. });
  1017. if (!isgroup) {
  1018. data.name = data.groupname;
  1019. cache.chat.push(data);
  1020. }
  1021. } else {
  1022. data.name = data.name || data.username || data.groupname;
  1023. cache.chat.push(data);
  1024. }
  1025. }
  1026. if (data.type === 'group') {
  1027. layui.each(cache.group, function(index, item) {
  1028. if (item.id == data.id) {
  1029. group.avatar = item.avatar;
  1030. return true;
  1031. }
  1032. });
  1033. }
  1034. if (!data.system) {
  1035. if (cache.base.notice) {
  1036. notice({
  1037. title: '来自 ' + data.username + ' 的消息',
  1038. content: data.content,
  1039. avatar: group.avatar || data.avatar
  1040. });
  1041. }
  1042. return setChatMin({
  1043. name: '收到新消息',
  1044. avatar: group.avatar || data.avatar,
  1045. anim: 6
  1046. });
  1047. }
  1048. }
  1049. if (!layimChat) return;
  1050. //接受到的消息不在当前Tab
  1051. var thatChat = thisChat();
  1052. if (thatChat.data.type + thatChat.data.id !== data.type + data.id) {
  1053. elem.addClass('layui-anim layer-anim-06');
  1054. setTimeout(function() {
  1055. elem.removeClass('layui-anim layer-anim-06')
  1056. }, 300);
  1057. }
  1058. var cont = layimChat.find('.layim-chat').eq(index);
  1059. var ul = cont.find('.layim-chat-main ul');
  1060. //系统消息
  1061. if (data.system) {
  1062. if (index !== -1) {
  1063. ul.append('<li class="layim-chat-system"><span>' + data.content + '</span></li>');
  1064. }
  1065. } else if (data.content.replace(/\s/g, '') !== '') {
  1066. ul.append(laytpl(elemChatMain).render(data));
  1067. }
  1068. chatListMore();
  1069. };
  1070. //消息盒子的提醒
  1071. var ANIM_MSG = 'layui-anim-loop layer-anim-05',
  1072. msgbox = function(num) {
  1073. var msgboxElem = layimMain.find('.layim-tool-msgbox');
  1074. msgboxElem.find('span').addClass(ANIM_MSG).html(num);
  1075. };
  1076. //存储最近MAX_ITEM条聊天记录到本地
  1077. var pushChatlog = function(message) {
  1078. var local = layui.data('layim')[cache.mine.id] || {};
  1079. local.chatlog = local.chatlog || {};
  1080. var thisChatlog = local.chatlog[message.type + message.id];
  1081. if (thisChatlog) {
  1082. //避免浏览器多窗口时聊天记录重复保存
  1083. var nosame;
  1084. layui.each(thisChatlog, function(index, item) {
  1085. if ((item.timestamp === message.timestamp &&
  1086. item.type === message.type &&
  1087. item.id === message.id &&
  1088. item.content === message.content)) {
  1089. nosame = true;
  1090. }
  1091. });
  1092. if (!(nosame || message.fromid == cache.mine.id)) {
  1093. thisChatlog.push(message);
  1094. }
  1095. if (thisChatlog.length > MAX_ITEM) {
  1096. thisChatlog.shift();
  1097. }
  1098. } else {
  1099. local.chatlog[message.type + message.id] = [message];
  1100. }
  1101. layui.data('layim', {
  1102. key: cache.mine.id,
  1103. value: local
  1104. });
  1105. };
  1106. //渲染本地最新聊天记录到相应面板
  1107. var viewChatlog = function() {
  1108. var local = layui.data('layim')[cache.mine.id] || {},
  1109. thatChat = thisChat(),
  1110. chatlog = local.chatlog || {},
  1111. ul = thatChat.elem.find('.layim-chat-main ul');
  1112. layui.each(chatlog[thatChat.data.type + thatChat.data.id], function(index, item) {
  1113. ul.append(laytpl(elemChatMain).render(item));
  1114. });
  1115. chatListMore();
  1116. };
  1117. //添加好友或群
  1118. var addList = function(data) {
  1119. var obj = {},
  1120. has, listElem = layimMain.find('.layim-list-' + data.type);
  1121. if (cache[data.type]) {
  1122. if (data.type === 'friend') {
  1123. layui.each(cache.friend, function(index, item) {
  1124. if (data.groupid == item.id) {
  1125. //检查好友是否已经在列表中
  1126. layui.each(cache.friend[index].list, function(idx, itm) {
  1127. if (itm.id == data.id) {
  1128. return has = true
  1129. }
  1130. });
  1131. if (has) return layer.msg('好友 [' + (data.username || '') + '] 已经存在列表中', {
  1132. anim: 6
  1133. });
  1134. cache.friend[index].list = cache.friend[index].list || [];
  1135. obj[cache.friend[index].list.length] = data;
  1136. data.groupIndex = index;
  1137. cache.friend[index].list.push(data); //在cache的friend里面也增加好友
  1138. return true;
  1139. }
  1140. });
  1141. } else if (data.type === 'group') {
  1142. //检查群组是否已经在列表中
  1143. layui.each(cache.group, function(idx, itm) {
  1144. if (itm.id == data.id) {
  1145. return has = true
  1146. }
  1147. });
  1148. if (has) return layer.msg('您已是 [' + (data.groupname || '') + '] 的群成员', {
  1149. anim: 6
  1150. });
  1151. obj[cache.group.length] = data;
  1152. cache.group.push(data);
  1153. }
  1154. }
  1155. if (has) return;
  1156. var list = laytpl(listTpl({
  1157. type: data.type,
  1158. item: 'd.data',
  1159. index: data.type === 'friend' ? 'data.groupIndex' : null
  1160. })).render({
  1161. data: obj
  1162. });
  1163. if (data.type === 'friend') {
  1164. var li = listElem.find('>li').eq(data.groupIndex);
  1165. li.find('.layui-layim-list').append(list);
  1166. li.find('.layim-count').html(cache.friend[data.groupIndex].list.length); //刷新好友数量
  1167. //如果初始没有好友
  1168. if (li.find('.layim-null')[0]) {
  1169. li.find('.layim-null').remove();
  1170. }
  1171. } else if (data.type === 'group') {
  1172. listElem.append(list);
  1173. //如果初始没有群组
  1174. if (listElem.find('.layim-null')[0]) {
  1175. listElem.find('.layim-null').remove();
  1176. }
  1177. }
  1178. };
  1179. //移出好友或群
  1180. var removeList = function(data) {
  1181. var listElem = layimMain.find('.layim-list-' + data.type);
  1182. var obj = {};
  1183. if (cache[data.type]) {
  1184. if (data.type === 'friend') {
  1185. layui.each(cache.friend, function(index1, item1) {
  1186. layui.each(item1.list, function(index, item) {
  1187. if (data.id == item.id) {
  1188. var li = listElem.find('>li').eq(index1);
  1189. var list = li.find('.layui-layim-list>li');
  1190. li.find('.layui-layim-list>li').eq(index).remove();
  1191. cache.friend[index1].list.splice(index,
  1192. 1); //从cache的friend里面也删除掉好友
  1193. li.find('.layim-count').html(cache.friend[index1].list
  1194. .length); //刷新好友数量
  1195. //如果一个好友都没了
  1196. if (cache.friend[index1].list.length === 0) {
  1197. li.find('.layui-layim-list').html(
  1198. '<li class="layim-null">该分组下已无好友了</li>');
  1199. }
  1200. return true;
  1201. }
  1202. });
  1203. });
  1204. } else if (data.type === 'group') {
  1205. layui.each(cache.group, function(index, item) {
  1206. if (data.id == item.id) {
  1207. listElem.find('>li').eq(index).remove();
  1208. cache.group.splice(index, 1); //从cache的group里面也删除掉数据
  1209. //如果一个群组都没了
  1210. if (cache.group.length === 0) {
  1211. listElem.html('<li class="layim-null">暂无群组</li>');
  1212. }
  1213. return true;
  1214. }
  1215. });
  1216. }
  1217. }
  1218. };
  1219. //查看更多记录
  1220. var chatListMore = function() {
  1221. var thatChat = thisChat(),
  1222. chatMain = thatChat.elem.find('.layim-chat-main');
  1223. var ul = chatMain.find('ul');
  1224. var length = ul.find('li').length;
  1225. if (length >= MAX_ITEM) {
  1226. var first = ul.find('li').eq(0);
  1227. if (!ul.prev().hasClass('layim-chat-system')) {
  1228. ul.before('<div class="layim-chat-system"><span layim-event="chatLog">查看更多记录</span></div>');
  1229. }
  1230. if (length > MAX_ITEM) {
  1231. first.remove();
  1232. }
  1233. }
  1234. chatMain.scrollTop(chatMain[0].scrollHeight + 1000);
  1235. chatMain.find('ul li:last').find('img').load(function() {
  1236. chatMain.scrollTop(chatMain[0].scrollHeight + 1000);
  1237. });
  1238. };
  1239. //快捷键发送
  1240. var hotkeySend = function() {
  1241. var thatChat = thisChat(),
  1242. textarea = thatChat.textarea;
  1243. textarea.focus();
  1244. textarea.off('keydown').on('keydown', function(e) {
  1245. var local = layui.data('layim')[cache.mine.id] || {};
  1246. var keyCode = e.keyCode;
  1247. if (local.sendHotKey === 'Ctrl+Enter') {
  1248. if (e.ctrlKey && keyCode === 13) {
  1249. sendMessage();
  1250. }
  1251. return;
  1252. }
  1253. if (keyCode === 13) {
  1254. if (e.ctrlKey) {
  1255. return textarea.val(textarea.val() + '\n');
  1256. }
  1257. if (e.shiftKey) return;
  1258. e.preventDefault();
  1259. sendMessage();
  1260. }
  1261. });
  1262. };
  1263. //表情库
  1264. var faces = function() {
  1265. var alt = ["[微笑]", "[嘻嘻]", "[哈哈]", "[可爱]", "[可怜]", "[挖鼻]", "[吃惊]", "[害羞]", "[挤眼]", "[闭嘴]", "[鄙视]",
  1266. "[爱你]", "[泪]", "[偷笑]", "[亲亲]", "[生病]", "[太开心]", "[白眼]", "[右哼哼]", "[左哼哼]", "[嘘]", "[衰]",
  1267. "[委屈]", "[吐]", "[哈欠]", "[抱抱]", "[怒]", "[疑问]", "[馋嘴]", "[拜拜]", "[思考]", "[汗]", "[困]", "[睡]",
  1268. "[钱]", "[失望]", "[酷]", "[色]", "[哼]", "[鼓掌]", "[晕]", "[悲伤]", "[抓狂]", "[黑线]", "[阴险]", "[怒骂]",
  1269. "[互粉]", "[心]", "[伤心]", "[猪头]", "[熊猫]", "[兔子]", "[ok]", "[耶]", "[good]", "[NO]", "[赞]",
  1270. "[来]", "[弱]", "[草泥马]", "[神马]", "[囧]", "[浮云]", "[给力]", "[围观]", "[威武]", "[奥特曼]", "[礼物]",
  1271. "[钟]", "[话筒]", "[蜡烛]", "[蛋糕]"
  1272. ],
  1273. arr = {};
  1274. layui.each(alt, function(index, item) {
  1275. arr[item] = layui.cache.dir + 'images/face/' + index + '.gif';
  1276. });
  1277. return arr;
  1278. }();
  1279. var stope = layui.stope; //组件事件冒泡
  1280. //在焦点处插入内容
  1281. var focusInsert = function(obj, str) {
  1282. var result, val = obj.value;
  1283. obj.focus();
  1284. if (document.selection) { //ie
  1285. result = document.selection.createRange();
  1286. document.selection.empty();
  1287. result.text = str;
  1288. } else {
  1289. result = [val.substring(0, obj.selectionStart), str, val.substr(obj.selectionEnd)];
  1290. obj.focus();
  1291. obj.value = result.join('');
  1292. }
  1293. };
  1294. //事件
  1295. var anim = 'layui-anim-upbit',
  1296. events = {
  1297. //在线状态
  1298. status: function(othis, e) {
  1299. var hide = function() {
  1300. othis.next().hide().removeClass(anim);
  1301. };
  1302. var type = othis.attr('lay-type');
  1303. if (type === 'show') {
  1304. stope(e);
  1305. othis.next().show().addClass(anim);
  1306. $(document).off('click', hide).on('click', hide);
  1307. } else {
  1308. var prev = othis.parent().prev();
  1309. othis.addClass(THIS).siblings().removeClass(THIS);
  1310. prev.html(othis.find('cite').html());
  1311. prev.removeClass('layim-status-' + (type === 'online' ? 'hide' : 'online'))
  1312. .addClass('layim-status-' + type);
  1313. layui.each(call.online, function(index, item) {
  1314. item && item(type);
  1315. });
  1316. }
  1317. }
  1318. //编辑签名
  1319. ,
  1320. sign: function() {
  1321. var input = layimMain.find('.layui-layim-remark');
  1322. input.on('change', function() {
  1323. var value = this.value;
  1324. layui.each(call.sign, function(index, item) {
  1325. item && item(value);
  1326. });
  1327. });
  1328. input.on('keyup', function(e) {
  1329. var keyCode = e.keyCode;
  1330. if (keyCode === 13) {
  1331. this.blur();
  1332. }
  1333. });
  1334. }
  1335. //大分组切换
  1336. ,
  1337. tab: function(othis) {
  1338. var index, main = '.layim-tab-content';
  1339. var tabs = layimMain.find('.layui-layim-tab>li');
  1340. typeof othis === 'number' ? (
  1341. index = othis, othis = tabs.eq(index)
  1342. ) : (
  1343. index = othis.index()
  1344. );
  1345. index > 2 ? tabs.removeClass(THIS) : (
  1346. events.tab.index = index, othis.addClass(THIS).siblings().removeClass(THIS)
  1347. )
  1348. layimMain.find(main).eq(index).addClass(SHOW).siblings(main).removeClass(SHOW);
  1349. }
  1350. //展开联系人分组
  1351. ,
  1352. spread: function(othis) {
  1353. var type = othis.attr('lay-type');
  1354. var spread = type === 'true' ? 'false' : 'true';
  1355. var local = layui.data('layim')[cache.mine.id] || {};
  1356. othis.next()[type === 'true' ? 'removeClass' : 'addClass'](SHOW);
  1357. local['spread' + othis.parent().index()] = spread;
  1358. layui.data('layim', {
  1359. key: cache.mine.id,
  1360. value: local
  1361. });
  1362. othis.attr('lay-type', spread);
  1363. othis.find('.layui-icon').html(spread === 'true' ? '&#xe61a;' : '&#xe602;');
  1364. }
  1365. //搜索
  1366. ,
  1367. search: function(othis) {
  1368. var search = layimMain.find('.layui-layim-search');
  1369. var main = layimMain.find('#layui-layim-search');
  1370. var input = search.find('input'),
  1371. find = function(e) {
  1372. var val = input.val().replace(/\s/);
  1373. if (val === '') {
  1374. events.tab(events.tab.index | 0);
  1375. } else {
  1376. var data = [],
  1377. friend = cache.friend || [];
  1378. var group = cache.group || [],
  1379. html = '';
  1380. for (var i = 0; i < friend.length; i++) {
  1381. for (var k = 0; k < (friend[i].list || []).length; k++) {
  1382. if (friend[i].list[k].username.indexOf(val) !== -1) {
  1383. friend[i].list[k].type = 'friend';
  1384. friend[i].list[k].index = i;
  1385. friend[i].list[k].list = k;
  1386. data.push(friend[i].list[k]);
  1387. }
  1388. }
  1389. }
  1390. for (var j = 0; j < group.length; j++) {
  1391. if (group[j].groupname.indexOf(val) !== -1) {
  1392. group[j].type = 'group';
  1393. group[j].index = j;
  1394. group[j].list = j;
  1395. data.push(group[j]);
  1396. }
  1397. }
  1398. if (data.length > 0) {
  1399. for (var l = 0; l < data.length; l++) {
  1400. html += '<li layim-event="chat" data-type="' + data[l].type +
  1401. '" data-index="' + data[l].index + '" data-list="' + data[l].list +
  1402. '"><img src="' + data[l].avatar + '"><span>' + (data[l].username ||
  1403. data[l].groupname || '佚名') + '</span><p>' + (data[l].remark ||
  1404. data[l].sign || '') + '</p></li>';
  1405. }
  1406. main.html(html);
  1407. } else {
  1408. getInpVal(val,function(_data){
  1409. if(_data.length){
  1410. html = '<li class="layim-null">无本地搜索结果</li>'+
  1411. '<li class="layim-null" style="text-align:left;padding:20px 10px 4px;color:#000;">陌生人</li>';
  1412. $.each(_data,function (k,v) {
  1413. html += '<li style="height:60px" data-uid="'+v.id+'">'+
  1414. '<img src="' + v.avatar + '" style="top:16px;">'+
  1415. '<span name="nick">昵称:' + (v.nickName ||v.groupname || '佚名') + '</span>'+
  1416. '<p name="user">账号:' + (v.userName ||'') + '</p>'+
  1417. '<p name="sign">' + (v.remark ||v.sign || '') + '</p>'+
  1418. ' <button type="button" class="layui-btn layui-btn-xs searchlibtn" layim-event="yzSearch">'+
  1419. ' <i class="layui-icon" style="margin:0;">&#xe61f;</i>'+
  1420. '</button></li>';
  1421. })
  1422. }else{
  1423. html = '<li class="layim-null">无搜索结果</li>'
  1424. }
  1425. main.html(html);
  1426. });
  1427. }
  1428. events.tab(3);
  1429. }
  1430. };
  1431. if (!cache.base.isfriend && cache.base.isgroup) {
  1432. events.tab.index = 1;
  1433. } else if (!cache.base.isfriend && !cache.base.isgroup) {
  1434. events.tab.index = 2;
  1435. }
  1436. search.show();
  1437. input.focus();
  1438. input.off('keyup', find).on('keyup', find);
  1439. }
  1440. //关闭搜索
  1441. ,
  1442. closeSearch: function(othis) {
  1443. othis.parent().hide();
  1444. events.tab(events.tab.index | 0);
  1445. },
  1446. yzSearch:function(othis){
  1447. let paren=othis.parent();
  1448. let _id=paren.data("uid");
  1449. let _img=paren.find('img').attr("src");
  1450. let _nick=paren.find('span[name="nick"]').text();
  1451. let _user=paren.find('p[name="user"]').text();
  1452. let _sign=paren.find('p[name="sign"]').text();
  1453. let _html='<ul class="layui-layim-list" style="border:1px solid #ccc;border-radius:4px;"><li style="height:60px" data-uid="'+v.id+'">'+
  1454. '<img src="' + _img + '" style="top:16px;">'+
  1455. '<span name="nick">昵称:' + _nick + '</span>'+
  1456. '<p name="user">账号:' + _user + '</p>'+
  1457. '<p name="sign">' + _sign + '</p>'+
  1458. '</li></ul>'+
  1459. '<textarea type="text" id="yanzremark" style="border:1px solid #ccc;border-radius:4px;width:97%;padding:4px;margin-top:10px;" rows="5" placeholder="请输入验证信息"></textarea>';
  1460. let index14 = layer.open({
  1461. type: 1,
  1462. title: '添加好友',
  1463. offset: 'auto',
  1464. area: ["30%", "auto"],
  1465. id: 'layerDemo2',
  1466. content: `<div style="padding:14px">
  1467. ${_html}
  1468. </div>`,
  1469. btn: ['添加', '取消'],
  1470. yes: function() {
  1471. let _remark=$("#yanzremark").val();
  1472. addNewFriend(_remark,_id,function(){layer.close(index14);},2);
  1473. },
  1474. no: function() {
  1475. layer.close(index14);
  1476. }
  1477. })
  1478. },
  1479. //消息盒子
  1480. msgbox: function() {
  1481. var msgboxElem = layimMain.find('.layim-tool-msgbox');
  1482. layer.close(events.msgbox.index);
  1483. msgboxElem.find('span').removeClass(ANIM_MSG).html('');
  1484. return events.msgbox.index = layer.open({
  1485. type: 2,
  1486. title: '消息盒子',
  1487. shade: false,
  1488. maxmin: true,
  1489. area: ['600px', '520px'],
  1490. skin: 'layui-box layui-layer-border',
  1491. resize: false,
  1492. content: cache.base.msgbox
  1493. });
  1494. }
  1495. //弹出查找页面
  1496. ,
  1497. find: function() {
  1498. layer.close(events.find.index);
  1499. return events.find.index = layer.open({
  1500. type: 2,
  1501. title: '系统管理',
  1502. shade: false,
  1503. maxmin: true,
  1504. area: ['1000px', '520px'],
  1505. skin: 'layui-box layui-layer-border',
  1506. resize: false,
  1507. content: cache.base.find
  1508. });
  1509. }
  1510. //弹出更换背景
  1511. ,
  1512. skin: function() {
  1513. layer.open({
  1514. type: 1,
  1515. title: '更换背景',
  1516. shade: false,
  1517. area: '300px',
  1518. skin: 'layui-box layui-layer-border',
  1519. id: 'layui-layim-skin',
  1520. zIndex: 66666666,
  1521. resize: false,
  1522. content: laytpl(elemSkinTpl).render({
  1523. skin: cache.base.skin
  1524. })
  1525. });
  1526. }
  1527. //关于
  1528. ,
  1529. about: function() {
  1530. layer.alert('版权所有: ' + "易站科技服务有限公司" +
  1531. '<br>易站科技官网:<a href="http:www.enstation.com" target="_blank">http:www.enstation.com</a>', {
  1532. title: '关于易聊',
  1533. shade: false
  1534. });
  1535. }
  1536. //生成换肤
  1537. ,
  1538. setSkin: function(othis) {
  1539. var src = othis.attr('src');
  1540. var local = layui.data('layim')[cache.mine.id] || {};
  1541. local.skin = src;
  1542. if (!src) delete local.skin;
  1543. layui.data('layim', {
  1544. key: cache.mine.id,
  1545. value: local
  1546. });
  1547. try {
  1548. layimMain.css({
  1549. 'background-image': src ? 'url(' + src + ')' : 'none'
  1550. });
  1551. layimChat.css({
  1552. 'background-image': src ? 'url(' + src + ')' : 'none'
  1553. });
  1554. } catch (e) {}
  1555. layui.each(call.setSkin, function(index, item) {
  1556. var filename = (src || '').replace(layui.cache.dir + 'css/modules/layim/skin/',
  1557. '');
  1558. item && item(filename, src);
  1559. });
  1560. }
  1561. //弹出聊天面板
  1562. ,
  1563. chat: function(othis) {
  1564. var local = layui.data('layim')[cache.mine.id] || {};
  1565. var type = othis.data('type'),
  1566. index = othis.data('index');
  1567. var list = othis.attr('data-list') || othis.index(),
  1568. data = {};
  1569. let parind = othis.parent();
  1570. if (parind.data('yzind') != undefined) {
  1571. list = parind.data('yzind');
  1572. index = parind.data('index');
  1573. }
  1574. if(parind.data('yzgroup') != undefined){
  1575. list = parind.data('yzgroup');
  1576. index = parind.data('index');
  1577. }
  1578. console.log(list)
  1579. if (type === 'friend') {
  1580. data = cache[type][index].list[list];
  1581. } else if (type === 'group') {
  1582. data = cache[type][list];
  1583. } else if (type === 'history') {
  1584. data = (local.history || {})[index] || {};
  1585. }
  1586. data.name = data.name || data.username || data.groupname;
  1587. if (type !== 'history') {
  1588. data.type = type;
  1589. }
  1590. popchat(data);
  1591. }
  1592. //切换聊天
  1593. ,
  1594. tabChat: function(othis) {
  1595. changeChat(othis);
  1596. }
  1597. //关闭聊天列表
  1598. ,
  1599. closeChat: function(othis, e) {
  1600. changeChat(othis.parent(), 1);
  1601. stope(e);
  1602. },
  1603. closeThisChat: function() {
  1604. changeChat(null, 1);
  1605. }
  1606. //展开群组成员
  1607. ,
  1608. groupMembers: function(othis, e) {
  1609. var icon = othis.find('.layui-icon'),
  1610. hide = function() {
  1611. icon.html('&#xe61a;');
  1612. othis.data('down', null);
  1613. layer.close(events.groupMembers.index);
  1614. },
  1615. stopmp = function(e) {
  1616. stope(e)
  1617. };
  1618. if (othis.data('down')) {
  1619. hide();
  1620. } else {
  1621. icon.html('&#xe619;');
  1622. othis.data('down', true);
  1623. events.groupMembers.index = layer.tips('<ul class="layim-members-list"></ul>', othis, {
  1624. tips: 3,
  1625. time: 0,
  1626. anim: 5,
  1627. fixed: true,
  1628. skin: 'layui-box layui-layim-members',
  1629. success: function(layero) {
  1630. var members = cache.base.members || {},
  1631. thatChat = thisChat(),
  1632. ul = layero.find('.layim-members-list'),
  1633. li = '',
  1634. membersCache = {},
  1635. hasFull = layimChat.find('.layui-layer-max').hasClass(
  1636. 'layui-layer-maxmin'),
  1637. listNone = layimChat.find('.layim-chat-list').css('display') ===
  1638. 'none';
  1639. if (hasFull) {
  1640. ul.css({
  1641. width: $(window).width() - 22 - (listNone || 200)
  1642. });
  1643. }
  1644. members.data = $.extend(members.data, {
  1645. id: thatChat.data.id
  1646. });
  1647. post(members, function(res) {
  1648. layui.each(res.list, function(index, item) {
  1649. li += '<li data-uid="' + item.id +
  1650. '"><a href="javascript:;"><img src="' +
  1651. item.avatar + '"><cite style="color:#000;">' + item
  1652. .username + '</cite></a></li>';
  1653. membersCache[item.id] = item;
  1654. });
  1655. ul.html(li);
  1656. //获取群员
  1657. othis.find('.layim-chat-members').html(res.members || (
  1658. res.list || []).length + '人');
  1659. //私聊
  1660. ul.find('li').on('click', function() {
  1661. var uid = $(this).data('uid'),
  1662. info = membersCache[uid]
  1663. popchat({
  1664. name: info.username,
  1665. type: 'friend',
  1666. avatar: info.avatar,
  1667. id: info.id
  1668. });
  1669. hide();
  1670. });
  1671. layui.each(call.members, function(index, item) {
  1672. item && item(res);
  1673. });
  1674. });
  1675. layero.on('mousedown', function(e) {
  1676. stope(e);
  1677. });
  1678. }
  1679. });
  1680. $(document).off('mousedown', hide).on('mousedown', hide);
  1681. $(window).off('resize', hide).on('resize', hide);
  1682. othis.off('mousedown', stopmp).on('mousedown', stopmp);
  1683. }
  1684. }
  1685. //发送聊天内容
  1686. ,
  1687. send: function() {
  1688. sendMessage();
  1689. }
  1690. //设置发送聊天快捷键
  1691. ,
  1692. setSend: function(othis, e) {
  1693. var box = events.setSend.box = othis.siblings('.layim-menu-box'),
  1694. type = othis.attr('lay-type');
  1695. if (type === 'show') {
  1696. stope(e);
  1697. box.show().addClass(anim);
  1698. $(document).off('click', events.setSendHide).on('click', events.setSendHide);
  1699. } else {
  1700. othis.addClass(THIS).siblings().removeClass(THIS);
  1701. var local = layui.data('layim')[cache.mine.id] || {};
  1702. local.sendHotKey = type;
  1703. layui.data('layim', {
  1704. key: cache.mine.id,
  1705. value: local
  1706. });
  1707. events.setSendHide(e, othis.parent());
  1708. }
  1709. },
  1710. setSendHide: function(e, box) {
  1711. (box || events.setSend.box).hide().removeClass(anim);
  1712. }
  1713. //表情
  1714. ,
  1715. face: function(othis, e) {
  1716. var content = '',
  1717. thatChat = thisChat();
  1718. for (var key in faces) {
  1719. content += '<li title="' + key + '"><img src="' + faces[key] + '"></li>';
  1720. }
  1721. content = '<ul class="layui-clear layim-face-list">' + content + '</ul>';
  1722. events.face.index = layer.tips(content, othis, {
  1723. tips: 1,
  1724. time: 0,
  1725. fixed: true,
  1726. skin: 'layui-box layui-layim-face',
  1727. success: function(layero) {
  1728. layero.find('.layim-face-list>li').on('mousedown', function(e) {
  1729. stope(e);
  1730. }).on('click', function() {
  1731. focusInsert(thatChat.textarea[0], 'face' + this.title +
  1732. ' ');
  1733. layer.close(events.face.index);
  1734. });
  1735. }
  1736. });
  1737. $(document).off('mousedown', events.faceHide).on('mousedown', events.faceHide);
  1738. $(window).off('resize', events.faceHide).on('resize', events.faceHide);
  1739. stope(e);
  1740. },
  1741. faceHide: function() {
  1742. layer.close(events.face.index);
  1743. }
  1744. //图片或一般文件
  1745. ,
  1746. image: function(othis) {
  1747. var type = othis.data('type') || 'images',
  1748. api = {
  1749. images: 'uploadImage',
  1750. file: 'uploadFile'
  1751. },
  1752. thatChat = thisChat(),
  1753. conf = cache.base[api[type]] || {};
  1754. layui.upload.render({
  1755. url: conf.url || '',
  1756. method: conf.type,
  1757. elem: othis.find('input')[0],
  1758. accept: type,
  1759. done: function(res) {
  1760. if (res.code == 0) {
  1761. res.data = res.data || {};
  1762. if (type === 'images') {
  1763. focusInsert(thatChat.textarea[0], 'img[' + (res.data.src ||
  1764. '') + ']');
  1765. } else if (type === 'file') {
  1766. focusInsert(thatChat.textarea[0], 'file(' + (res.data.src ||
  1767. '') + ')[' + (res.data.name || '下载文件') + ']');
  1768. }
  1769. sendMessage();
  1770. } else {
  1771. layer.msg(res.msg || '上传失败');
  1772. }
  1773. }
  1774. });
  1775. }
  1776. //音频和视频
  1777. ,
  1778. media: function(othis) {
  1779. var type = othis.data('type'),
  1780. text = {
  1781. audio: '音频',
  1782. video: '视频'
  1783. },
  1784. thatChat = thisChat()
  1785. layer.prompt({
  1786. title: '请输入网络' + text[type] + '地址',
  1787. shade: false,
  1788. offset: [
  1789. othis.offset().top - $(window).scrollTop() - 158 + 'px', othis.offset()
  1790. .left + 'px'
  1791. ]
  1792. }, function(src, index) {
  1793. focusInsert(thatChat.textarea[0], type + '[' + src + ']');
  1794. sendMessage();
  1795. layer.close(index);
  1796. });
  1797. }
  1798. //扩展工具栏
  1799. ,
  1800. extend: function(othis) {
  1801. var filter = othis.attr('lay-filter'),
  1802. thatChat = thisChat();
  1803. layui.each(call['tool(' + filter + ')'], function(index, item) {
  1804. item && item.call(othis, function(content) {
  1805. focusInsert(thatChat.textarea[0], content);
  1806. }, sendMessage, thatChat);
  1807. });
  1808. }
  1809. //播放音频
  1810. ,
  1811. playAudio: function(othis) {
  1812. var audioData = othis.data('audio'),
  1813. audio = audioData || document.createElement('audio'),
  1814. pause = function() {
  1815. audio.pause();
  1816. othis.removeAttr('status');
  1817. othis.find('i').html('&#xe652;');
  1818. };
  1819. if (othis.data('error')) {
  1820. return layer.msg('播放音频源异常');
  1821. }
  1822. if (!audio.play) {
  1823. return layer.msg('您的浏览器不支持audio');
  1824. }
  1825. if (othis.attr('status')) {
  1826. pause();
  1827. } else {
  1828. audioData || (audio.src = othis.data('src'));
  1829. audio.play();
  1830. othis.attr('status', 'pause');
  1831. othis.data('audio', audio);
  1832. othis.find('i').html('&#xe651;');
  1833. //播放结束
  1834. audio.onended = function() {
  1835. pause();
  1836. };
  1837. //播放异常
  1838. audio.onerror = function() {
  1839. layer.msg('播放音频源异常');
  1840. othis.data('error', true);
  1841. pause();
  1842. };
  1843. }
  1844. }
  1845. //播放视频
  1846. ,
  1847. playVideo: function(othis) {
  1848. var videoData = othis.data('src'),
  1849. video = document.createElement('video');
  1850. if (!video.play) {
  1851. return layer.msg('您的浏览器不支持video');
  1852. }
  1853. layer.close(events.playVideo.index);
  1854. events.playVideo.index = layer.open({
  1855. type: 1,
  1856. title: '播放视频',
  1857. area: ['460px', '300px'],
  1858. maxmin: true,
  1859. shade: false,
  1860. content: '<div style="background-color: #000; height: 100%;"><video style="position: absolute; width: 100%; height: 100%;" src="' +
  1861. videoData + '" loop="loop" autoplay="autoplay"></video></div>'
  1862. });
  1863. }
  1864. //聊天记录
  1865. ,
  1866. chatLog: function(othis) {
  1867. var thatChat = thisChat();
  1868. let parind = othis.parent();
  1869. var type = othis.data('type')
  1870. if (parind.data("yzind") != undefined) {
  1871. var list = parind.data('yzind');
  1872. var index = parind.data('index');
  1873. var _str = cache[type][index].list[list];
  1874. _str.name = _str.username;
  1875. _str.type = type;
  1876. thatChat = {
  1877. data: _str
  1878. };
  1879. }
  1880. if(parind.data("yzgroup") != undefined){
  1881. var list = parind.data('yzgroup');
  1882. var index = parind.data('index');
  1883. var _str = cache[type][index];
  1884. _str.name = _str.groupname;
  1885. _str.type = type;
  1886. thatChat = {
  1887. data: _str
  1888. };
  1889. }
  1890. if (!cache.base.chatLog) {
  1891. return layer.msg('未开启更多聊天记录');
  1892. }
  1893. layer.close(events.chatLog.index);
  1894. return events.chatLog.index = layer.open({
  1895. type: 2,
  1896. maxmin: true,
  1897. title: '与 ' + thatChat.data.name + ' 的聊天记录',
  1898. area: ['450px', '100%'],
  1899. shade: false,
  1900. offset: 'rb',
  1901. skin: 'layui-box',
  1902. anim: 2,
  1903. id: 'layui-layim-chatlog',
  1904. content: cache.base.chatLog + '?id=' + thatChat.data.id + '&type=' + thatChat
  1905. .data.type
  1906. });
  1907. }
  1908. //历史会话右键菜单操作
  1909. ,
  1910. menuHistory: function(othis, e) {
  1911. var local = layui.data('layim')[cache.mine.id] || {};
  1912. var parent = othis.parent(),
  1913. type = othis.data('type');
  1914. var hisElem = layimMain.find('.layim-list-history');
  1915. var none = '<li class="layim-null">暂无历史会话</li>'
  1916. if (type === 'one') {
  1917. var history = local.history;
  1918. delete history[parent.data('index')];
  1919. local.history = history;
  1920. layui.data('layim', {
  1921. key: cache.mine.id,
  1922. value: local
  1923. });
  1924. //删除 DOM
  1925. $('.layim-list-history li.layim-' + parent.data('index')).remove();
  1926. if (hisElem.find('li').length === 0) {
  1927. hisElem.html(none);
  1928. }
  1929. } else if (type === 'all') {
  1930. delete local.history;
  1931. layui.data('layim', {
  1932. key: cache.mine.id,
  1933. value: local
  1934. });
  1935. hisElem.html(none);
  1936. }
  1937. layer.closeAll('tips');
  1938. }
  1939. //好友列表右键菜单操作
  1940. ,
  1941. menuFriend: function(othis, e) {
  1942. var local = layui.data('layim')[cache.mine.id] || {};
  1943. var parent = othis.parent(),
  1944. type = othis.data('type');
  1945. var list = parent.data('yzind');
  1946. var index = parent.data('index');
  1947. var userId = cache.mine.id;
  1948. var hisElem = layimMain.find('.layim-list-friend');
  1949. var none = '<li class="layim-null">暂无好友</li>'
  1950. if(type=="delfriend"){
  1951. var friendId = cache["friend"][index].list[list].id;
  1952. let index1 = layer.open({
  1953. type: 1,
  1954. title: '删除好友',
  1955. offset: 'auto',
  1956. area: ["30%", "auto"],
  1957. id: 'layerDemo2',
  1958. content: '<div style="text-align:center;padding:14px">删除后你也将从对方联系人列表中消失,且以后不再接收此人的会话消息。</div>',
  1959. btn: ['确定', '取消'],
  1960. yes: function() {
  1961. $.post('/friendController/delFriend', {
  1962. "userId": userId,
  1963. "friendId": friendId
  1964. }, function(result) {
  1965. if (result > 0) {
  1966. layim.removeList({
  1967. type: 'friend',
  1968. id: friendId
  1969. });
  1970. var local = layui.data('layim')[cache.mine.id] || {};
  1971. var hisElem = layimMain.find('.layim-list-history');
  1972. var history = local.history;
  1973. delete history["friend"+friendId];
  1974. local.history = history;
  1975. layui.data('layim', {
  1976. key: cache.mine.id,
  1977. value: local
  1978. });
  1979. //删除 DOM
  1980. $('.layim-list-history li.layim-' + parent.data('index')).remove();
  1981. if (hisElem.find('li').length === 0) {
  1982. hisElem.html('<li class="layim-null">暂无历史会话</li>');
  1983. }
  1984. layer.msg('删除成功!');
  1985. } else {
  1986. layer.msg('删除失败!');
  1987. }
  1988. });
  1989. layer.close(index1);
  1990. },
  1991. no: function() {
  1992. layer.close(index1);
  1993. }
  1994. })
  1995. }else if(type=="resetname"){
  1996. var tId = cache["friend"][index].id;
  1997. let index2 = layer.open({
  1998. type: 1,
  1999. title: '分组重命名',
  2000. offset: 'auto',
  2001. area: ["30%", "auto"],
  2002. id: 'layerDemo2',
  2003. content: '<div style="text-align:center;padding:14px"><input type="text" style="width:73%;padding: 10px;border:1px solid #ccc;border-radius:4px;" id="addname" placeholder="请输入新的分组名"></div>',
  2004. btn: ['确定', '取消'],
  2005. yes: function() {
  2006. let _key=$("#addname").val();
  2007. resetName(_key,tId,cache.allName,function callback(){layer.close(index2)});
  2008. },
  2009. no: function() {
  2010. layer.close(index2);
  2011. }
  2012. })
  2013. }else if(type=="delete"){
  2014. var tId = cache["friend"][index].id;
  2015. let index1 = layer.open({
  2016. type: 1,
  2017. title: '删除分组',
  2018. offset: 'auto',
  2019. area: ["30%", "auto"],
  2020. id: 'layerDemo2',
  2021. content: '<div style="text-align:center;padding:14px">删除该分组后,其下好友将移到默认[好友]分组,确定要删除吗?</div>',
  2022. btn: ['删除', '取消'],
  2023. yes: function() {
  2024. $.post("/friendTypeController/deleteById",{"id":tId},function(result) {
  2025. if(result>0){
  2026. window.location.reload();
  2027. layer.msg('删除成功!');
  2028. }else{
  2029. layer.msg('删除失败!');
  2030. }
  2031. })
  2032. layer.close(index1);
  2033. },
  2034. no: function() {
  2035. layer.close(index1);
  2036. }
  2037. })
  2038. }else if(type=="newadd"){
  2039. let index3 = layer.open({
  2040. type: 1,
  2041. title: '添加分组',
  2042. offset: 'auto',
  2043. area: ["30%", "auto"],
  2044. id: 'layerDemo2',
  2045. content: '<div style="text-align:center;padding:14px"><input type="text" style="width:73%;padding:10px;border:1px solid #ccc;border-radius:4px;" id="newname" placeholder="请输入新的分组名"></div>',
  2046. btn: ['添加', '取消'],
  2047. yes: function() {
  2048. let _key=$("#newname").val().trim();
  2049. addNewName(_key,cache.allName,function callback(){layer.close(index3)});
  2050. },
  2051. no: function() {
  2052. layer.close(index3);
  2053. }
  2054. })
  2055. }
  2056. //删除 DOM
  2057. if (hisElem.find('li').length === 0) {
  2058. hisElem.html(none);
  2059. }
  2060. layer.closeAll('tips');
  2061. }
  2062. //群列表右键菜单操作
  2063. ,menuGroup: function(othis, e) {
  2064. var local = layui.data('layim')[cache.mine.id] || {};
  2065. var type = othis.data("type");
  2066. var parent = othis.parent();
  2067. var index = parent.data('index');
  2068. var _str = cache["group"][index];
  2069. var userId = cache.mine.id;
  2070. var none = '<li class="layim-null">暂无好友</li>'
  2071. if (type === 'newadd') {
  2072. let _url=cache.base.find.replace("myFriends","myGroups");
  2073. let index1 = layer.open({
  2074. type: 2,
  2075. title: '系统管理',
  2076. shade: false,
  2077. maxmin: true,
  2078. area: ['1000px', '520px'],
  2079. skin: 'layui-box layui-layer-border',
  2080. resize: false,
  2081. content: _url
  2082. });
  2083. }else if(type === 'dissolve'){
  2084. if(confirm("确定要解散该群吗?")){
  2085. $.post(baseUrl+"/groupController/delete",{"groupId":_str.id},function(result) {
  2086. //alert(result);
  2087. if(result>0){
  2088. window.location.reload();
  2089. }else{
  2090. layer.msg('删除失败!');
  2091. }
  2092. })
  2093. }else{
  2094. return;
  2095. }
  2096. }else if(type === 'dropout'){
  2097. if(confirm("确定要退出群吗?")){
  2098. $.post(baseUrl+'/groupController/quit',{"groupId":_str.id,"userId":userId},function(result){
  2099. if(result>0){
  2100. window.location.reload();
  2101. }else{
  2102. layer.msg('退出失败!');
  2103. }
  2104. });
  2105. }else{
  2106. return;
  2107. }
  2108. }else if(type==="editinfo"){
  2109. let index4 = layer.open({
  2110. type: 1,
  2111. title: '修改群信息',
  2112. offset: 'auto',
  2113. area: ["30%", "auto"],
  2114. id: 'layerDemo2',
  2115. content: `<div style="text-align:center;padding:14px">
  2116. <div style="margin-bottom:10px">
  2117. <span>群名称:</span><input type="text" style="width:60%;padding:8px;border:1px solid #ccc;border-radius:4px;" id="newgrname" placeholder="请输入新的群名">
  2118. </div>
  2119. <div>
  2120. <span>群简介:</span><textarea id="newgrremark" style="resize:none;width:60%;padding:8px;border:1px solid #ccc;border-radius:4px;" rows="3"></textarea>
  2121. </div>
  2122. </div>`,
  2123. btn: ['添加', '取消'],
  2124. yes: function() {
  2125. let _key=$("#newgrname").val();
  2126. let _remark=$("#newgrremark").val();
  2127. resetgroupname(_str.id,_key,_remark,function(){layer.close(index4);});
  2128. },
  2129. no: function() {
  2130. layer.close(index4);
  2131. }
  2132. })
  2133. }
  2134. layer.closeAll('tips');
  2135. }
  2136. };
  2137. //暴露接口
  2138. exports('layim', new LAYIM());
  2139. }).addcss(
  2140. 'modules/layim/layim.css?v=3.9.1', 'skinlayimcss'
  2141. );