index.js 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118
  1. /*!
  2. * 社区主入口
  3. */
  4. layui.define(['lay', 'layer', 'laytpl', 'form', 'element', 'upload', 'util'], function(exports){
  5. var $ = layui.jquery
  6. ,layer = layui.layer
  7. ,laytpl = layui.laytpl
  8. ,form = layui.form
  9. ,element = layui.element
  10. ,upload = layui.upload
  11. ,util = layui.util
  12. ,device = layui.device()
  13. ,DISABLED = 'layui-btn-disabled';
  14. //阻止IE7以下访问
  15. if(device.ie && device.ie < 10){
  16. layer.alert('如果您非得使用 IE 浏览器访问Fly社区,那么请使用 IE11');
  17. }
  18. //全局设置 form
  19. form.set({
  20. autocomplete: 'off' //全局禁用 autocomplete
  21. });
  22. form.render('input');
  23. //在焦点处插入内容
  24. layui.focusInsert = function(obj, str){
  25. var result, val = obj.value;
  26. obj.focus();
  27. if(document.selection){ //ie
  28. result = document.selection.createRange();
  29. document.selection.empty();
  30. result.text = str;
  31. } else {
  32. result = [val.substring(0, obj.selectionStart), str, val.substr(obj.selectionEnd)];
  33. //obj.focus();
  34. obj.value = result.join('');
  35. }
  36. };
  37. //数字前置补零
  38. layui.laytpl.digit = function(num, length, end){
  39. var str = '';
  40. num = String(num);
  41. length = length || 2;
  42. for(var i = num.length; i < length; i++){
  43. str += '0';
  44. }
  45. return num < Math.pow(10, length) ? str + (num|0) : num;
  46. };
  47. var fly = {
  48. dir: layui.cache.dir + '/public/static/lay/modules/fly/' //模块路径
  49. //Ajax
  50. ,json: function(url, data, success, options){
  51. var that = this, type = typeof data === 'function';
  52. if(type){
  53. options = success
  54. success = data;
  55. data = {};
  56. }
  57. options = options || {};
  58. return $.ajax({
  59. type: options.type || 'post',
  60. dataType: options.dataType || 'json',
  61. data: data,
  62. url: url,
  63. success: function(res){
  64. res.status = 'status' in res ? res.status : res.code;
  65. if(res.status === 0) {
  66. success && success(res);
  67. } else if(res.status === 2){ //未绑定手机号
  68. that.setPhoneNotice();
  69. } else if(res.status === 3){ //未激活邮箱
  70. that.setEmailNotice();
  71. } else {
  72. layer.msg(res.msg || res.code, {shift: 6});
  73. options.error && options.error(res);
  74. }
  75. }, error: function(e){
  76. layer.msg('请求异常,请重试', {shift: 6});
  77. options.error && options.error(e);
  78. }
  79. });
  80. }
  81. //计算字符长度
  82. ,charLen: function(val){
  83. var arr = val.split(''), len = 0;
  84. for(var i = 0; i < val.length ; i++){
  85. arr[i].charCodeAt(0) < 299 ? len++ : len += 2;
  86. }
  87. return len;
  88. }
  89. ,form: {}
  90. //简易编辑器
  91. ,layEditor: function(options){
  92. var html = ['<div class="layui-unselect fly-edit">'
  93. ,'<span type="face" title="表情"><i class="iconfont icon-yxj-expression" style="top: 1px;"></i></span>'
  94. ,'<span type="picture" title="图片:img[src]"><i class="iconfont icon-tupian"></i></span>'
  95. ,'<span type="href" title="超链接格式:a(href)[text]"><i class="iconfont icon-lianjie"></i></span>'
  96. ,'<span type="quote" title="引用"><i class="iconfont icon-yinyong" style="top: 1px;"></i></span>'
  97. ,'<span type="code" title="插入代码" class="layui-hide-xs"><i class="iconfont icon-emwdaima" style="top: 1px;"></i></span>'
  98. ,'<span type="hr" title="水平线">hr</span>'
  99. ,'<span type="preview" title="预览"><i class="iconfont icon-yulan1"></i></span>'
  100. ,'</div>'].join('');
  101. var closeTips = function(){
  102. layer.close(mod.face.index);
  103. };
  104. var log = {}, mod = {
  105. face: function(editor, self){ //插入表情
  106. var str = '', ul, face = fly.faces;
  107. for(var key in face){
  108. str += '<li title="'+ key +'"><img src="'+ face[key] +'"></li>';
  109. }
  110. str = '<ul id="LAY-editface" class="layui-clear" style="margin: -10px 0 0 -1px;">'+ str +'</ul>';
  111. layer.close(mod.face.index);
  112. mod.face.index = layer.tips(str, self, {
  113. tips: 3
  114. ,time: 0
  115. ,skin: 'layui-edit-face'
  116. ,tipsMore: true
  117. });
  118. $(document).off('click', closeTips).on('click', closeTips);
  119. $('#LAY-editface li').on('click', function(){
  120. var title = $(this).attr('title') + ' ';
  121. layui.focusInsert(editor[0], 'face' + title);
  122. editor.trigger('keyup');
  123. });
  124. }
  125. ,picture: function(editor){ //插入图片
  126. layer.open({
  127. type: 1
  128. ,id: 'fly-jie-upload'
  129. ,title: '插入图片'
  130. ,area: 'auto'
  131. ,shade: false
  132. ,area: '465px'
  133. ,fixed: false
  134. ,offset: [
  135. editor.offset().top - $(window).scrollTop() + 'px'
  136. ,editor.offset().left + 'px'
  137. ]
  138. ,skin: 'layui-layer-border'
  139. ,content: ['<ul class="layui-form layui-form-pane" style="margin: 20px;">'
  140. ,'<li class="layui-form-item">'
  141. ,'<label class="layui-form-label">URL</label>'
  142. ,'<div class="layui-input-inline">'
  143. ,'<input required name="image" placeholder="支持直接粘贴远程图片地址" value="" class="layui-input">'
  144. ,'</div>'
  145. ,'<button type="button" class="layui-btn layui-btn-primary" id="uploadImg"><i class="layui-icon">&#xe67c;</i>上传图片</button>'
  146. ,'</li>'
  147. ,'<li class="layui-form-item" style="text-align: center;">'
  148. ,'<button type="button" lay-submit lay-filter="uploadImages" class="layui-btn">确认</button>'
  149. ,'</li>'
  150. ,'</ul>'].join('')
  151. ,success: function(layero, index){
  152. var image = layero.find('input[name="image"]');
  153. //执行上传实例
  154. upload.render({
  155. elem: '#uploadImg'
  156. ,url: '/api/upload/'
  157. ,size: 300000000
  158. ,done: function(res){
  159. if(res.status == 0){
  160. image.val(res.url);
  161. } else {
  162. layer.msg(res.msg, {icon: 5});
  163. }
  164. }
  165. });
  166. form.on('submit(uploadImages)', function(data){
  167. var field = data.field;
  168. if(!field.image) return image.focus();
  169. layui.focusInsert(editor[0], 'img['+ field.image + '] ');
  170. layer.close(index);
  171. editor.trigger('keyup');
  172. });
  173. }
  174. });
  175. }
  176. ,href: function(editor){ //超链接
  177. layer.prompt({
  178. title: '请输入合法链接'
  179. ,shade: false
  180. ,fixed: false
  181. ,id: 'LAY_flyedit_href'
  182. ,offset: [
  183. editor.offset().top - $(window).scrollTop() + 1 + 'px'
  184. ,editor.offset().left + 1 + 'px'
  185. ]
  186. }, function(val, index, elem){
  187. if(!/^http(s*):\/\/[\S]/.test(val)){
  188. layer.tips('请务必 http 或 https 开头', elem, {tips:1})
  189. return;
  190. }
  191. layui.focusInsert(editor[0], ' a('+ val +')['+ val + '] ');
  192. layer.close(index);
  193. editor.trigger('keyup');
  194. });
  195. }
  196. ,quote: function(editor){ //引用
  197. layer.prompt({
  198. title: '请输入引用内容'
  199. ,formType: 2
  200. ,maxlength: 10000
  201. ,shade: false
  202. ,id: 'LAY_flyedit_quote'
  203. ,offset: [
  204. editor.offset().top - $(window).scrollTop() + 1 + 'px'
  205. ,editor.offset().left + 1 + 'px'
  206. ]
  207. ,area: ['300px', '100px']
  208. }, function(val, index, elem){
  209. layui.focusInsert(editor[0], '[quote]\n '+ val + '\n[/quote]\n');
  210. layer.close(index);
  211. editor.trigger('keyup');
  212. });
  213. }
  214. ,code: function(editor){ //插入代码
  215. layer.prompt({
  216. title: '请贴入代码'
  217. ,formType: 2
  218. ,maxlength: 10000
  219. ,shade: false
  220. ,id: 'LAY_flyedit_code'
  221. ,area: ['800px', '360px']
  222. }, function(val, index, elem){
  223. layui.focusInsert(editor[0], '[pre]\n'+ val + '\n[/pre]\n');
  224. layer.close(index);
  225. editor.trigger('keyup');
  226. });
  227. }
  228. ,hr: function(editor){ //插入水平分割线
  229. layui.focusInsert(editor[0], '[hr]\n');
  230. editor.trigger('keyup');
  231. }
  232. ,preview: function(editor, span){ //预览
  233. var othis = $(span), getContent = function(){
  234. var content = editor.val();
  235. return /^\{html\}/.test(content)
  236. ? content.replace(/^\{html\}/, '')
  237. : fly.content(content)
  238. }, isMobile = device.ios || device.android;
  239. if(mod.preview.isOpen) return layer.close(mod.preview.index);
  240. mod.preview.index = layer.open({
  241. type: 1
  242. ,title: '预览'
  243. ,shade: false
  244. ,offset: 'r'
  245. ,id: 'LAY_flyedit_preview'
  246. ,area: [
  247. isMobile ? '100%' : '775px'
  248. ,'100%'
  249. ]
  250. ,scrollbar: isMobile ? false : true
  251. ,anim: -1
  252. ,isOutAnim: false
  253. ,content: '<div class="detail-body layui-text" style="margin:20px;">'+ getContent() +'</div>'
  254. ,success: function(layero){
  255. editor.on('keyup', function(val){
  256. layero.find('.detail-body').html(getContent());
  257. });
  258. mod.preview.isOpen = true;
  259. othis.addClass('layui-this');
  260. }
  261. ,end: function(){
  262. delete mod.preview.isOpen;
  263. othis.removeClass('layui-this');
  264. }
  265. });
  266. }
  267. };
  268. layui.use('face', function(face){
  269. options = options || {};
  270. fly.faces = face;
  271. $(options.elem).each(function(index){
  272. var that = this, othis = $(that), parent = othis.parent();
  273. parent.prepend(html);
  274. parent.find('.fly-edit span').on('click', function(event){
  275. var type = $(this).attr('type');
  276. mod[type].call(that, othis, this);
  277. if(type === 'face'){
  278. event.stopPropagation()
  279. }
  280. });
  281. });
  282. });
  283. }
  284. ,escape: function(html){
  285. return String(html||'').replace(/&(?!#?[a-zA-Z0-9]+;)/g, '&amp;')
  286. .replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/'/g, '&#39;').replace(/"/g, '&quot;');
  287. }
  288. //内容转义
  289. ,content: function(content){
  290. var util = fly
  291. ,item = fly.faces;
  292. //支持的html标签
  293. var html = function(end){
  294. return new RegExp('\\n*\\|\\-'+ (end||'') +'(div|span|p|button|table|thead|th|tbody|tr|td|ul|li|ol|li|dl|dt|dd|h2|h3|h4|h5)([\\s\\S]*?)\\-\\|\\n*', 'g');
  295. };
  296. //XSS
  297. content = util.escape(content||'')
  298. //转义图片
  299. .replace(/img\[([^\s]+?)\]/g, function(img){
  300. return '<img src="' + img.replace(/(^img\[)|(\]$)/g, '') + '">';
  301. })
  302. //转义@
  303. .replace(/@(\S+)(\s+?|$)/g, '@<a href="javascript:;" class="fly-aite">$1</a>$2')
  304. //转义表情
  305. .replace(/face\[([^\s\[\]]+?)\]/g, function(face){
  306. var alt = face.replace(/^face/g, '');
  307. return '<img alt="'+ alt +'" title="'+ alt +'" src="' + item[alt] + '">';
  308. })
  309. //转义脚本
  310. .replace(/a(\(javascript:)(.+)(;*\))/g, 'a(javascript:layer.msg(\'非法脚本\');)')
  311. //转义链接
  312. .replace(/a\([\s\S]+?\)\[[\s\S]*?\]/g, function(str){
  313. var href = (str.match(/a\(([\s\S]+?)\)\[/)||[])[1];
  314. var text = (str.match(/\)\[([\s\S]*?)\]/)||[])[1];
  315. if(!href) return str;
  316. var rel = /^(http(s)*:\/\/)\b(?!(\w+\.)*(sentsin.com|layui.com))\b/.test(href.replace(/\s/g, ''));
  317. return '<a href="'+ href +'" target="_blank"'+ (rel ? ' rel="nofollow"' : '') +'>'+ (text||href) +'</a>';
  318. })
  319. //转义横线
  320. .replace(/\[hr\]\n*/g, '<hr>')
  321. //转义表格
  322. .replace(/\[table\]([\s\S]*)\[\/table\]\n*/g, function(str){
  323. return str.replace(/\[(thead|th|tbody|tr|td)\]\n*/g, '<$1>')
  324. .replace(/\n*\[\/(thead|th|tbody|tr|td)\]\n*/g, '</$1>')
  325. .replace(/\[table\]\n*/g, '<table class="layui-table">')
  326. .replace(/\n*\[\/table\]\n*/g, '</table>');
  327. })
  328. //转义 div/span
  329. .replace(/\n*\[(div|span)([\s\S]*?)\]([\s\S]*?)\[\/(div|span)\]\n*/g, function(str){
  330. return str.replace(/\[(div|span)([\s\S]*?)\]\n*/g, '<$1 $2>')
  331. .replace(/\n*\[\/(div|span)\]\n*/g, '</$1>');
  332. })
  333. //转义列表
  334. .replace(/\[ul\]([\s\S]*)\[\/ul\]\n*/g, function(str){
  335. return str.replace(/\[li\]\n*/g, '<li>')
  336. .replace(/\n*\[\/li\]\n*/g, '</li>')
  337. .replace(/\[ul\]\n*/g, '<ul>')
  338. .replace(/\n*\[\/ul\]\n*/g, '</ul>');
  339. })
  340. //转义代码
  341. .replace(/\[pre\]([\s\S]*)\[\/pre\]\n*/g, function(str){
  342. return str.replace(/\[pre\]\n*/g, '<pre>')
  343. .replace(/\n*\[\/pre\]\n*/g, '</pre>');
  344. })
  345. //转义引用
  346. .replace(/\[quote\]([\s\S]*)\[\/quote\]\n*/g, function(str){
  347. return str.replace(/\[quote\]\n*/g, '<div class="layui-elem-quote">')
  348. .replace(/\n*\[\/quote\]\n*/g, '</div>');
  349. })
  350. //转义换行
  351. .replace(/\n/g, '<br>')
  352. return content;
  353. }
  354. //发送验证码
  355. ,sendAuthCode: function(options){
  356. options = $.extend({
  357. seconds: 60
  358. ,elemPhone: $('#L_phone')
  359. ,elemVercode: $('#L_vercode')
  360. ,elemImagecode: $('#L_imagecode')
  361. ,elemImage: $('.fly-imagecode')
  362. }, options);
  363. var seconds = options.seconds
  364. ,btn = $(options.elem)
  365. ,token = null
  366. ,sendType = 'phone'
  367. ,timer, countDown = function(loop){
  368. seconds--;
  369. if(seconds < 0){
  370. btn.removeClass(DISABLED).html('获取验证码');
  371. seconds = options.seconds;
  372. clearInterval(timer);
  373. } else {
  374. btn.addClass(DISABLED).html(seconds + '秒后可重新获取');
  375. }
  376. if(!loop){
  377. timer = setInterval(function(){
  378. countDown(true);
  379. }, 1000);
  380. }
  381. };
  382. //发送渠道名称
  383. var getTypeName = function(type){
  384. return ({
  385. phone: '手机'
  386. ,email: '邮箱'
  387. })[type];
  388. };
  389. //校验手机或邮箱合法性
  390. var checkPhoneEmail = function(value, callback){
  391. var that = this
  392. ,fn = function(type){
  393. typeof callback === 'function' && callback(type);
  394. };
  395. if(/^1\d{10}$/.test(value)){
  396. return fn('phone');
  397. } else if(/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/.test(value)){
  398. return fn('email');
  399. }
  400. return '请输入正确的'+ (options.elemPhone.parent().prev('label').text() || '值');
  401. };
  402. //点击获取验证码按钮
  403. btn.on('click', function(){
  404. var elemPhone = options.elemPhone
  405. ,value = elemPhone.val() //手机或邮箱
  406. ,elemImagecode = options.elemImagecode
  407. ,valueImage = elemImagecode.val();
  408. if(seconds !== options.seconds) return;
  409. //校验手机号和邮箱
  410. var phoneEmail = checkPhoneEmail(value, function(type){
  411. sendType = type;
  412. });
  413. if(phoneEmail){
  414. elemPhone.focus();
  415. return layer.msg(phoneEmail);
  416. };
  417. //校验图形验证码
  418. if(!valueImage){
  419. elemImagecode.focus();
  420. return layer.msg('请输入图形验证码');
  421. };
  422. //发送请求
  423. fly.json('/auth/code', {
  424. value: value
  425. ,imagecode: valueImage
  426. }, function(res){
  427. layer.msg('验证码已发送至您的'+ getTypeName(sendType) +',请注意查收', {
  428. icon: 1
  429. ,shade: 0
  430. });
  431. options.elemImagecode.val('')
  432. options.elemVercode.focus();
  433. options.elemImage.trigger('click');
  434. countDown();
  435. });
  436. });
  437. }
  438. //新消息通知
  439. ,newmsg: function(){
  440. var elemNotice = $('#FLY-notice')
  441. ,url = layui.url();
  442. //如果已经在消息页面,则不请求
  443. if(url.pathname[0] === 'user' && url.pathname[1] === 'message'){
  444. //return;
  445. }
  446. if(layui.cache.user.uid !== -1 && elemNotice[0]){
  447. fly.json('/message/nums/', {
  448. _: new Date().getTime()
  449. }, function(res){
  450. if(res.status === 0 && res.count > 0){
  451. var msg = $('<a href="/user/message/" class="layui-badge fly-nav-msg">'+ res.count +'</a>');
  452. elemNotice.append(msg);
  453. msg.on('click', function(){
  454. var thisA = this;
  455. //标记所有消息为已读
  456. fly.json('/message/read/', {}, function(res){
  457. location.href = thisA.href;
  458. });
  459. return false;
  460. })
  461. }
  462. });
  463. }
  464. return arguments.callee;
  465. }
  466. //手机绑定弹窗
  467. ,setPhoneNotice: function(){
  468. layer.open({
  469. type: 1
  470. ,id: 'LAY_Notice_add'
  471. ,title: '手机号绑定通知'
  472. ,content: '<div class="layui-text" style="padding: 20px;">您需要绑定手机号后,才可进行发帖/回帖等操作。</div>'
  473. ,btnAlign: 'c'
  474. ,btn: ['立即绑定', '朕偏不!']
  475. ,yes: function(){
  476. location.href = '/user/set/'
  477. }
  478. ,btn2: function(){
  479. layer.msg('少年,我看好你!');
  480. }
  481. });
  482. }
  483. //邮箱激活提示
  484. ,setEmailNotice: function(){
  485. layer.open({
  486. type: 1
  487. ,id: 'LAY_Notice_add'
  488. ,title: '邮箱激活通知'
  489. ,content: '<div class="layui-text" style="padding: 20px;">您需要激活邮箱后,才可进行发帖/回帖等操作。</div>'
  490. ,btnAlign: 'c'
  491. ,btn: ['前往激活', '朕偏不!']
  492. ,yes: function(){
  493. location.href = '/user/set/'
  494. }
  495. ,btn2: function(){
  496. layer.msg('少年,我看好你!');
  497. }
  498. });
  499. }
  500. };
  501. //加载扩展模块
  502. layui.config({
  503. base: fly.dir
  504. }).extend({
  505. im: 'im'
  506. ,face: 'face'
  507. });
  508. //点击事件
  509. util.event('fly-active', {
  510. //发送系统消息
  511. sendMessage: function(othis){
  512. var parentElem = othis.parent()
  513. ,userInfo = JSON.parse(decodeURIComponent(parentElem.data('user')));
  514. layer.prompt({
  515. formType: 2
  516. ,title: '发送消息'
  517. ,shade: false
  518. ,id: 'fly-layer-user-sendMessage'
  519. }, function(value){
  520. fly.json('/message/send', {
  521. content: value
  522. ,uid: userInfo.id
  523. }, function(res){
  524. layer.msg('发送消息成功', {icon: 1, shade: 0.5, time: 1000}, function(){
  525. location.reload();
  526. });
  527. });
  528. });
  529. }
  530. //用户状态
  531. ,updateUserStatus: function(othis){
  532. var parentElem = othis.parent()
  533. ,userInfo = JSON.parse(decodeURIComponent(parentElem.data('user')));
  534. layer.open({
  535. type: 1
  536. ,id: 'fly-layer-user-update'
  537. ,title: '更改用户帐号状态'
  538. ,area: 'auto'
  539. ,maxWidth: 1000
  540. ,shade: false
  541. ,content: ['<ul class="layui-form layui-form-pane" style="margin: 20px;">'
  542. ,'<li class="layui-form-item">'
  543. ,'<label class="layui-form-label">昵称</label>'
  544. ,'<div class="layui-input-block">'
  545. ,'<input lay-verify="required" name="username" value="'+ userInfo.username +'" class="layui-input">'
  546. ,'</div>'
  547. ,'</li>'
  548. ,'<li class="layui-form-item">'
  549. ,'<label class="layui-form-label">用户状态</label>'
  550. ,'<div class="layui-input-block" style="width: 200px;">'
  551. ,'<select name="auth">'
  552. ,'<option value="-1" '+ (userInfo.auth == -1 ? 'selected' : '') +'>锁定</option>'
  553. ,'<option value="0" '+ (userInfo.auth >= 0 ? 'selected' : '') +'>正常</option>'
  554. ,'<select>'
  555. ,'</div>'
  556. ,'</li>'
  557. ,'<li class="layui-form-item layui-form-text">'
  558. ,'<label class="layui-form-label">签名</label>'
  559. ,'<div class="layui-input-block">'
  560. ,'<textarea name="sign" autocomplete="off" class="layui-textarea" style="min-height: 100px;">'+ (userInfo.sign || '') +'</textarea>'
  561. ,'</div>'
  562. ,'</li>'
  563. ,'<li class="layui-form-item" style="text-align: center;">'
  564. ,'<button type="submit" lay-submit lay-filter="updateUserInfo" class="layui-btn">提交</button>'
  565. ,'</li>'
  566. ,'</ul>'].join('')
  567. ,success: function(layero){
  568. form.render().on('submit(updateUserInfo)', function(data){
  569. var field = data.field;
  570. field.id = userInfo.id;
  571. fly.json('/brain/updateUserInfo/', field, function(res){
  572. layer.msg(res.msg, {
  573. shade: 0.5,
  574. icon: 1
  575. ,time: 1000
  576. }, function(){
  577. location.reload();
  578. });
  579. });
  580. });
  581. }
  582. });
  583. }
  584. });
  585. var _body = $('body');
  586. //头像
  587. if(device.android || device.ios){
  588. $('#LAY_header_avatar').on('click', function(){
  589. return false;
  590. })
  591. }
  592. //刷新图形验证码
  593. $('body').on('click', '.fly-imagecode', function(){
  594. this.src = '/auth/imagecode?t='+ new Date().getTime();
  595. });
  596. //头条轮播
  597. if($('#FLY_topline')[0]){
  598. layui.use('carousel', function(){
  599. var carousel = layui.carousel;
  600. var ins = carousel.render({
  601. elem: '#FLY_topline'
  602. ,width: '100%'
  603. ,height: '172px'
  604. ,anim: 'fade'
  605. });
  606. var resizeTopline = function(){
  607. var width = $(this).prop('innerWidth');
  608. if(width >= 1200){
  609. ins.reload({
  610. height: '172px'
  611. });
  612. } else if(width >= 992){
  613. ins.reload({
  614. height: '141px'
  615. });
  616. } else if(width >= 768){
  617. ins.reload({
  618. height: '166px'
  619. });
  620. }
  621. };
  622. resizeTopline()
  623. $(window).on('resize', resizeTopline);
  624. });
  625. }
  626. //签到
  627. var tplSignin = ['{{# if(d.signed){ }}'
  628. ,'<button class="layui-btn layui-btn-disabled">今日已签到</button>'
  629. ,'<span>获得了<cite>{{ d.experience }}</cite>飞吻</span>'
  630. ,'{{# } else { }}'
  631. ,'<button class="layui-btn layui-btn-danger" id="LAY_signin">今日签到</button>'
  632. ,'<span>可获得<cite>{{ d.experience }}</cite>飞吻</span>'
  633. ,'{{# } }}'].join('')
  634. ,tplSigninDay = '已连续签到<cite>{{ d.days }}</cite>天'
  635. ,signRender = function(data){
  636. laytpl(tplSignin).render(data, function(html){
  637. elemSigninMain.html(html);
  638. });
  639. laytpl(tplSigninDay).render(data, function(html){
  640. elemSigninDays.html(html);
  641. });
  642. }
  643. ,elemSigninHelp = $('#LAY_signinHelp')
  644. ,elemSigninTop = $('#LAY_signinTop')
  645. ,elemSigninMain = $('.fly-signin-main')
  646. ,elemSigninDays = $('.fly-signin-days');
  647. if(elemSigninMain[0]){
  648. fly.json('/sign/status', function(res){
  649. if(!res.data) return;
  650. signRender.token = res.data.token;
  651. signRender(res.data);
  652. });
  653. }
  654. $('body').on('click', '#LAY_signin', function(){
  655. var othis = $(this);
  656. if(othis.hasClass(DISABLED)) return;
  657. fly.json('/sign/in', {
  658. token: signRender.token || 1
  659. }, function(res){
  660. signRender(res.data);
  661. }, {
  662. error: function(){
  663. othis.removeClass(DISABLED);
  664. }
  665. });
  666. othis.addClass(DISABLED);
  667. });
  668. //签到说明
  669. elemSigninHelp.on('click', function(){
  670. layer.open({
  671. type: 1
  672. ,title: '签到说明'
  673. ,area: '300px'
  674. ,shade: 0.8
  675. ,shadeClose: true
  676. ,content: ['<div class="layui-text" style="padding: 20px;">'
  677. ,'<blockquote class="layui-elem-quote">“签到”可获得社区飞吻,规则如下</blockquote>'
  678. ,'<table class="layui-table">'
  679. ,'<thead>'
  680. ,'<tr><th>连续签到天数</th><th>每天可获飞吻</th></tr>'
  681. ,'</thead>'
  682. ,'<tbody>'
  683. ,'<tr><td><5</td><td>5</td></tr>'
  684. ,'<tr><td>≥5</td><td>10</td></tr>'
  685. ,'<tr><td>≥15</td><td>15</td></tr>'
  686. ,'<tr><td>≥30</td><td>20</td></tr>'
  687. ,'<tr><td>≥100</td><td>30</td></tr>'
  688. ,'<tr><td>≥365</td><td>50</td></tr>'
  689. ,'</tbody>'
  690. ,'</table>'
  691. ,'<ul style="padding-top: 0; padding-bottom: 0;">'
  692. ,'<li>中间若有间隔,则连续天数重新计算</li>'
  693. ,'<li style="color: #FF5722;">不可利用程序自动签到,否则飞吻清零</li>'
  694. ,'</ul>'
  695. ,'</div>'].join('')
  696. });
  697. });
  698. //签到活跃榜
  699. var tplSigninTop = ['{{# layui.each(d.data, function(index, item){ }}'
  700. ,'<li>'
  701. ,'<a href="/u/{{item.uid}}" target="_blank">'
  702. ,'<img src="{{item.user.avatar}}">'
  703. ,'<cite class="fly-link">{{item.user.username}}</cite>'
  704. ,'</a>'
  705. ,'{{# var date = new Date(item.time); if(d.index < 2){ }}'
  706. ,'<span class="fly-grey">签到于 {{ layui.laytpl.digit(date.getHours()) + ":" + layui.laytpl.digit(date.getMinutes()) + ":" + layui.laytpl.digit(date.getSeconds()) }}</span>'
  707. ,'{{# } else { }}'
  708. ,'<span class="fly-grey">已连续签到 <i>{{ item.days }}</i> 天</span>'
  709. ,'{{# } }}'
  710. ,'</li>'
  711. ,'{{# }); }}'
  712. ,'{{# if(d.data.length === 0) { }}'
  713. ,'{{# if(d.index < 2) { }}'
  714. ,'<li class="fly-none fly-grey">今天还没有人签到</li>'
  715. ,'{{# } else { }}'
  716. ,'<li class="fly-none fly-grey">还没有签到记录</li>'
  717. ,'{{# } }}'
  718. ,'{{# } }}'].join('');
  719. elemSigninTop.on('click', function(){
  720. var loadIndex = layer.load(1, {shade: 0.8});
  721. fly.json('/top/signin/', function(res){
  722. var tpl = $(['<div class="layui-tab layui-tab-brief" style="margin: 5px 0 0;">'
  723. ,'<ul class="layui-tab-title">'
  724. ,'<li class="layui-this">最新签到</li>'
  725. ,'<li>今日最快</li>'
  726. ,'<li>总签到榜</li>'
  727. ,'</ul>'
  728. ,'<div class="layui-tab-content fly-signin-list" id="LAY_signin_list">'
  729. ,'<ul class="layui-tab-item layui-show"></ul>'
  730. ,'<ul class="layui-tab-item">2</ul>'
  731. ,'<ul class="layui-tab-item">3</ul>'
  732. ,'</div>'
  733. ,'</div>'].join(''))
  734. ,signinItems = tpl.find('.layui-tab-item');
  735. layer.close(loadIndex);
  736. layui.each(signinItems, function(index, item){
  737. var html = laytpl(tplSigninTop).render({
  738. data: res.data[index]
  739. ,index: index
  740. });
  741. $(item).html(html);
  742. });
  743. layer.open({
  744. type: 1
  745. ,title: '签到活跃榜 - TOP 20'
  746. ,area: '300px'
  747. ,shade: 0.8
  748. ,shadeClose: true
  749. ,id: 'layer-pop-signintop'
  750. ,content: tpl.prop('outerHTML')
  751. });
  752. });
  753. });
  754. //回帖榜
  755. var tplReply = ['{{# layui.each(d.data, function(index, item){ }}'
  756. ,'<dd>'
  757. ,'<a>'
  758. ,'<img src="{{item.user.avatar}}">'
  759. ,'<cite>{{item.user.username}}</cite>'
  760. ,'<i>{{item["count(*)"]}}次回答</i>'
  761. ,'</a>'
  762. ,'</dd>'
  763. ,'{{# }); }}'
  764. ,'{{# if(d.data.length === 0){ }}'
  765. ,'<dt class="fly-none" style="height: auto; font-size: 14px; min-height: 0;">没有相关数据</dt>'
  766. ,'{{# } }}'].join('')
  767. ,elemReply = $('#LAY_replyRank');
  768. if(elemReply[0]){
  769. fly.json('/top/reply/', {
  770. limit: 20
  771. }, function(res){
  772. var html = laytpl(tplReply).render(res);
  773. elemReply.find('dl').html(html);
  774. });
  775. };
  776. //技术客服
  777. var tplCustomerService = ['{{# layui.each(d.data, function(index, item){ }}'
  778. ,'<dd>'
  779. ,'<a href1="/u/{{item.uid}}">'
  780. ,'<img src="{{item.user.avatar}}">'
  781. ,'<i>{{item.user.username}}</i>'
  782. ,'</a>'
  783. ,'</dd>'
  784. ,'{{# }); }}'
  785. ,'{{# if(d.data.length === 0){ }}'
  786. ,'<dt class="fly-none" style="height: auto; font-size: 14px; min-height: 0;">没有相关数据</dt>'
  787. ,'{{# } }}'].join('')
  788. ,elemCustomerService = $('#LAY_customerService');
  789. if(elemCustomerService[0]){
  790. fly.json('/role/list/', {
  791. authProduct: elemCustomerService.data('product')
  792. ,authType: 'customerService'
  793. }, function(res){
  794. var html = laytpl(tplCustomerService).render(res);
  795. elemCustomerService.find('dl').html(html);
  796. });
  797. };
  798. //相册
  799. if($(window).width() > 750){
  800. layer.photos({
  801. photos: '.photos'
  802. ,zIndex: 9999999999
  803. ,anim: -1
  804. });
  805. } else {
  806. $('body').on('click', '.photos img', function(){
  807. window.open(this.src);
  808. });
  809. }
  810. //监听搜索引擎外部搜索
  811. var searchAll = function(form){
  812. $(form).submit(function(){
  813. var input = $(this).find('input[name="q"]')
  814. ,val = input.val();
  815. if(val.replace(/\s/g, '') === ''){
  816. return false;
  817. }
  818. input.val('site:layui.com '+ input.val());
  819. });
  820. };
  821. searchAll('.fly-search-form');
  822. //弹出搜索框
  823. $('.LAY_search').on('click', function(){
  824. layer.open({
  825. type: 1
  826. ,title: false
  827. ,closeBtn: false
  828. //,shade: [0.1, '#fff']
  829. ,shadeClose: true
  830. ,maxWidth: 10000
  831. ,skin: 'fly-layer-search'
  832. ,content: ['<form action="https://www2.bing.com/search">'
  833. ,'<input autocomplete="off" placeholder="搜索内容,回车跳转" type="text" name="q">'
  834. ,'</form>'].join('')
  835. ,success: function(layero){
  836. var input = layero.find('input');
  837. input.focus();
  838. searchAll(layero.find('form'));
  839. }
  840. })
  841. });
  842. //执行发送验证码
  843. fly.sendAuthCode({
  844. elem: '#FLY-getvercode'
  845. });
  846. //新消息通知
  847. fly.newmsg();
  848. //发送激活邮件
  849. fly.activate = function(email, secret){
  850. fly.json('/api/activate/', {
  851. secret: secret
  852. }, function(res){
  853. if(res.status === 0){
  854. layer.alert('已成功将激活链接发送到了您的邮箱。<br>接受可能会稍有延迟,请注意查收。', {
  855. icon: 1
  856. });
  857. };
  858. });
  859. };
  860. $('#LAY-activate').on('click', function(){
  861. var othis = $(this);
  862. fly.activate(othis.attr('email'), othis.attr('secret'));
  863. });
  864. //点击@
  865. $('body').on('click', '.fly-aite', function(){
  866. var othis = $(this), text = othis.text();
  867. if(othis.attr('href') !== 'javascript:;'){
  868. return;
  869. }
  870. text = text.replace(/^@|([\s\S]+?)/g, '');
  871. othis.attr({
  872. href: '/jump?username='+ text
  873. ,target: '_blank'
  874. });
  875. });
  876. //表单提交
  877. fly.onFormSubmit = function(filter, callback){
  878. form.on('submit('+ (filter || '*') +')', function(data){
  879. var action = $(data.form).attr('action')
  880. ,method = $(data.form).attr('method')
  881. ,button = $(data.elem);
  882. fly.json(action, data.field, function(res){
  883. var end = function(){
  884. if(typeof callback === 'function') return callback(data, res);
  885. if(res.action){
  886. location.href = res.action;
  887. } else {
  888. fly.form[action||button.attr('key')](data.field, data.form, res);
  889. }
  890. };
  891. if(res.status == 0){
  892. button.attr('alert') ? layer.alert(res.msg, {
  893. icon: 1,
  894. time: 10*1000,
  895. end: end
  896. }) : end();
  897. };
  898. }, {
  899. type: (filter && method) ? method : 'post'
  900. });
  901. return false;
  902. });
  903. };
  904. fly.onFormSubmit();
  905. //加载特定模块
  906. if(layui.cache.page && layui.cache.page !== 'index'){
  907. var extend = {};
  908. extend[layui.cache.page] = layui.cache.page;
  909. layui.extend(extend);
  910. layui.use(layui.cache.page);
  911. }
  912. //加载IM
  913. if(!device.android && !device.ios){
  914. //layui.use('im');
  915. }
  916. //加载编辑器
  917. fly.layEditor({
  918. elem: '.fly-editor'
  919. });
  920. //手机设备的简单适配
  921. var treeMobile = $('.site-tree-mobile')
  922. ,shadeMobile = $('.site-mobile-shade')
  923. treeMobile.on('click', function(){
  924. $('body').addClass('site-mobile');
  925. });
  926. shadeMobile.on('click', function(){
  927. $('body').removeClass('site-mobile');
  928. });
  929. //获取统计数据
  930. $('.fly-handles').each(function(){
  931. var othis = $(this);
  932. $.get('/api/handle?alias='+ othis.data('alias'), function(res){
  933. othis.html('(下载量:'+ res.number +')');
  934. })
  935. });
  936. //tips
  937. _body.on('mouseenter', '*[lay-tips]', function(){
  938. var that = this
  939. ,othis = $(that)
  940. ,options = lay.options(that);
  941. if(othis.parent().hasClass('layui-nav-item')) return;
  942. that.timer = setTimeout(function(){
  943. var tips = options.content || othis.attr('lay-tips')
  944. ,marginLeft = options.marginLeft
  945. ,direction = options.direction
  946. ,bgcolor = options.bgcolor || '#24262F'
  947. ,index = layer.tips(tips, that, {
  948. tips: [direction || 3, bgcolor]
  949. ,time: -1
  950. ,anim: 5
  951. ,success: function(layero, index){
  952. if(marginLeft){
  953. layero.css('margin-left', marginLeft + 'px');
  954. }
  955. }
  956. })
  957. othis.data('index', index);
  958. }, options.delay || 300);
  959. }).on('mouseleave', '*[lay-tips]', function(){
  960. layer.close($(this).data('index'));
  961. clearTimeout(this.timer);
  962. delete this.timer;
  963. });
  964. //固定Bar
  965. (function(){
  966. if($('#LAY_brain')[0]){
  967. return;
  968. }
  969. util.fixbar({
  970. });
  971. }())
  972. exports('fly', fly);
  973. });