Files

1308 lines
53 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* The Web UI Theme-v4.1.0
* LayIM 是一个基于 Layui 的即时通讯模块,主要功能包括:
联系人管理:支持好友、群组和历史会话的展示和管理
实时聊天:支持一对一聊天和群聊
消息系统:支持文本、表情、图片、文件、音视频等多种消息类型
聊天记录:本地保存聊天记录,支持查看历史消息
状态管理:在线/离线状态显示,隐身模式等
自定义主题:支持浅色和深色主题切换
扩展功能:支持自定义聊天工具栏,如表情、文件上传等
通知系统:浏览器桌面通知,消息盒子提醒
搜索功能:支持联系人搜索
群成员查看:可以查看群成员列表并直接发起私聊
这个模块设计得非常完整,提供了构建即时通讯应用所需的核心功能。
*/
layui.define(["layer", "laytpl", "form", "util", "upload", "dropdown", "code"], function(e) {
// 构造函数 a - 主要接口
function a() {
this.v = "4.1.0";
}
// 模板渲染函数 s
function s(a) {
return (a = a || {}).item = a.item || "d." + a.type,
["{{# var length = 0; layui.each(" + a.item + ", function(i, data){ length++; }}",
'<li layim-event="chat" data-type="' + a.type + '" data-index="{{= ' + (a.index || "i") + ' }}" class="layim-' + ("history" === a.type ? "{{=i}}" : a.type + "{{=data.id}}") + ' {{= data.status === "offline" ? "layim-list-gray" : "" }}"><img src="{{= data.avatar || layui.layim.cache().options.defaultAvatar }}"><span>{{= data.username||data.groupname||data.username||"匿名" }}</span><p>{{= data.remark||data.sign||"" }}</p><span class="layim-msg-status">new</span></li>',
"{{# }); if(length === 0){ }}",
'<li class="layim-null">' + ({friend:"该分组下暂无好友",group:"暂无群组",history:"暂无历史会话"}[a.type]||"暂无数据")+"</li>",
"{{# } }}"
].join("");
}
// 内容解析函数 d
function d(a) {
var e = A("contentParser");
return (e || Y)(a);
}
// AJAX 请求封装 u
function u(a, e) {
var i = (a = f.extend({type: "get", dataType: "json", error: console.error}, a)).success;
return a.success = function(a) {
"function" == typeof e && e(a.data || {}),
"function" == typeof i && i.apply(null, arguments)
},
f.ajax(a);
}
// 插入文本到输入框 n
function n(a, e) {
var i, t = a.value;
a.focus(),
document.selection ? (i = document.selection.createRange(), document.selection.empty(), i.text = e) : (i = [t.substring(0, a.selectionStart), e, t.substr(a.selectionEnd)], a.focus(), a.value = i.join(""));
}
// 变量声明
var r, l, y, c, m, p,
f = layui.$,
h = layui.layer,
g = layui.laytpl,
o = layui.form,
t = layui.util,
v = layui.device(),
b = "layim",
x = "layui-show",
C = "layim-this",
k = "pending",
w = {
callback: {},
chat: [],
message: {}
},
A = (a.prototype.config = function(a) {
// 配置方法
var e = {showFriend: !0, showGroup: !0},
i = a.defaultAvatar || L("images/default.png");
if (!0 === (a = f.extend(!0, {
contactsPanel: e,
backgroundImage: !1,
voice: "default.mp3",
LOCAL_TABLE: "layim",
LOCAL_MAX_CHATLOG: 20,
chatTimeout: 1e4,
defaultAvatar: i
}, a)).contactsPanel && (a.contactsPanel = e),
f.extend(!0, w, {options: a}),
window.JSON && window.JSON.parse) return D(w.options), this;
},
a.prototype.on = function(a, e) {
// 事件监听
return layui.onevent.call(this, b, a, e);
},
a.prototype.cache = function() {
// 获取缓存
return w;
},
a.prototype.setChatStatus = function(a) {
// 设置聊天状态
var e = S();
if (e) return e.elem.find(".layim-chat-status").html(a), this;
},
a.prototype.notice = function(a) {
// 通知
return aa(a), this;
},
a.prototype.setFriendStatus = function(a, e) {
// 设置好友状态
f(".layim-friend" + a)["online" === e ? "removeClass" : "addClass"]("layim-list-gray");
},
a.prototype.extendChatTools = function(l) {
// 扩展聊天工具
var a = w.options,
e = a.chatTools || [];
l = "array" !== layui.type(l) ? [l] : l,
layui.each(l, function(i, t) {
layui.each(e, function(a, e) {
t.name && t.name === e.name && (f.extend(!0, e, t), l.splice(i, 1));
});
}),
a.chatTools = e.concat(l);
},
a.prototype.callback = function(a, e) {
// 回调函数管理
var i = w.callback;
if ("function" != typeof e) return i[a];
i[a] = e, w.callback = i;
}),
L = function(a) {
return layui.cache.layimResPath + a;
};
// 主界面模板 F
var F = ['<div class="layui-layim-main">', ...].join("");
// 设置面板模板 q
var q = ['<div class="layui-form" lay-filter="layim-set">', ...].join("");
// 聊天窗口模板 G
var G = ['<div class="layim-chat layim-chat-{{=d.data.type}}{{=d.first ? " layui-show" : ""}}">', ...].join("");
// 添加好友/群组面板模板 N
var N = ['<div class="layim-add-box">', ...].join("");
// 消息模板 T
var T = ['<li {{= d.user ? "class=layim-chat-role-user" : "" }} {{# if(d.mid){ }}data-mid="{{=d.mid}}"{{# } }} {{= d.status || "" }}>', ...].join("");
// 聊天列表项模板 K
var K = '<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 || layui.layim.cache().options.defaultAvatar }}"><span>{{= d.data.username||"匿名" }}</span><i class="layui-icon layui-icon-close-fill" layim-event="closeChat"></i></li>';
// 内容解析器 Y
var Y = w.callback.contentParser = function(a) {
return a = (a || "").replace(/&(?!#?[a-zA-Z0-9]+;)/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/'/g, "&#39;")
.replace(/"/g, "&quot;")
.replace(/.+\n?/g, function(a) {
var e = a.trim().replace(/\s/g, "");
return /^-(\-+)-$/.test(e) ? "<hr>" : /^>.*$/.test(e) ? a.replace(/^.*>(.*)\n?$/, "<blockquote>$1</blockquote>") : a;
})
.replace(/!\[(.*?)\]\((.*?)\)/g, function(a, e, i) {
return '<img src="' + i + '" alt="' + e + '">';
})
.replace(/!file\[(.*?)\]\((.*?)\)/g, function(a, e, i) {
return ['<a class="layui-layim-file" href="' + i + '" download target="_blank">',
'<i class="layui-icon layui-icon-layim-download"></i>',
"<cite>" + e + "</cite>",
"</a>"
].join("");
})
.replace(/!audio\((.*?)\)/g, function(a, e) {
return ['<div class="layui-unselect layui-layim-audio" layim-event="playAudio" data-src="' + e + '">',
'<i class="layui-icon layui-icon-play"></i>',
"<p>语音消息</p>",
"</div>"
].join("");
})
.replace(/!video\((.*?)\)/g, function(a, e) {
return ['<div class="layui-unselect layui-layim-video" layim-event="playVideo" data-src="' + e + '">',
'<i class="layui-icon layui-icon-play"></i>',
"</div>"
].join("");
})
.replace(/\[(.*?)\]\((.+?)\)/g, function(a, e, i) {
return '<a href="' + i + '" target="_blank">' + ((e = e.replace(/^\s+|\s+$/g, "")) || i) + "</a>";
})
.replace(/\*\*(?!\s)([^\*\r\n]+?)(?<!\s)\*\*/g, function(a, e) {
return "<strong>" + e + "</strong>";
})
.replace(/\*(?!\s)([^\*\r\n]+?)(?<!\s)\*/g, function(a, e) {
return "<em>" + e + "</em>";
})
.replace(/(?<!#)(#{1,6}) +(.+)\n?/g, function(a, e, i) {
e = "h" + e.length;
return "<" + e + ">" + i + "</" + e + ">";
})
.replace(/\`{3}(\w*)\n([\s\S]*?)\`{3}/g, function(a, e, i) {
return '<pre><code class="' + (e = e ? "language-" + e : "") + '">' + i.replace(/\n/g, "\\KN") + "</code></pre>";
})
.replace(/\n/g, "<br>")
.replace(/\\KN/g, "\n");
};
// 初始化配置 D
var D = function(t) {
function a(a) {
var e = a.user || {},
i = _(e.id);
o(e, {
friend: a.friend || [],
group: a.group || [],
history: i.history || {}
}),
R(g(F).render(w)),
(i.close || n.minStatus) && X(),
l(a);
}
function l(a) {
var e = a.user || {},
e = _(e.id),
i = t.theme || e.theme;
$(i),
e.theme = i,
layui.data(t.LOCAL_TABLE, {
key: w.user.id,
value: e
}),
layui.event.call(a, b, "ready", w);
}
var e = t.init || {},
i = e.user || {},
n = t.contactsPanel,
o = function a(e, i) {
return f.extend(!0, w, {
options: t,
user: e
}, i), a;
}(i);
if (i = [{
name: "face",
title: "插入表情",
icon: "layui-icon-face-smile-fine"
}], (t.pageurl || {}).chatlog && i.push({
name: "chatlog",
title: "聊天记录",
icon: "layui-icon-log layim-tool-log"
}), t.chatTools = t.chatTools || i, !t.contactsPanel) return l(e);
e.url ? u(e, a) : a(e);
};
// 渲染主界面 R
var R = function(a) {
var i = w.options,
t = i.contactsPanel;
return h.open({
type: 1,
area: ["260px", "518px"],
skin: "layui-layim layui-layim-layer",
title: "&#8203;",
offset: "rb",
id: "layui-layim",
shade: !1,
anim: 2,
resize: !1,
content: a,
success: function(a) {
Z(r = a),
l && h.close(l.attr("times"));
var e = [],
a = a.find(".layim-list-history");
a.find("li").each(function() {
e.push(f(this).prop("outerHTML"));
}),
0 < e.length && (e.reverse(), a.html(e.join(""))),
V(),
z.sign(),
"function" == typeof t.done && t.done.apply(null, arguments);
},
cancel: function(a) {
X();
var e = _();
return e.close = !0,
layui.data(i.LOCAL_TABLE, {
key: w.user.id,
value: e
}),
!1;
}
});
};
// 获取本地数据 _
var _ = a.prototype.getLocalData = function(a) {
var e = w.user || {};
return a = null == a ? e.id : a,
layui.data(w.options.LOCAL_TABLE)[a] || {};
};
// 主题切换 $
var $ = a.prototype.theme = function(a) {
var e = "LAYIM-THEME",
i = ".layui-layim";
if ("light" === a) return f("#LAY-STYLE-" + e).remove();
"dark" === a && lay.style({
id: e,
target: f(i)[0] ? i : "body",
text: g([...]).render({...})
});
};
// 右键菜单处理 V
var V = function() {
r.on("contextmenu", function(a) {
return a.cancelBubble = !0, a.returnValue = !1;
});
function t() {
h.closeAll("tips");
}
r.find(".layim-list-history").on("contextmenu", "li", function(a) {
var e = f(this),
i = '<ul data-id="' + e[0].id + '" data-index="' + e.data("index") + '"><li layim-event="menuHistory" data-type="one">移除该会话</li><li layim-event="menuHistory" data-type="all">清空全部会话列表</li></ul>';
e.hasClass("layim-null") || (h.tips(i, this, {
tips: 1,
time: 0,
anim: 5,
fixed: !0,
skin: "layui-layim-contextmenu",
success: function(a) {
a.off("mousedown", layui.stope).on("mousedown", layui.stope);
}
}), f(document).off("mousedown", t).on("mousedown", t), f(window).off("resize", t).on("resize", t));
});
};
// 最小化主界面 X
var X = function(a) {
var i = w.options,
e = w.user || {},
t = i.contactsPanel;
return l && h.close(l.attr("times")),
r && r.hide(),
h.open({
type: 1,
title: !1,
id: "layui-layim-close",
skin: "layui-layim-min layui-layim-close layui-layim-layer",
shade: !1,
closeBtn: !1,
anim: 2,
offset: "rb",
resize: !1,
content: ['<img src="' + (e.avatar || i.defaultAvatar) + '">', (a = a || e.username) ? "<span>" + a + "</span>" : ""].join(""),
move: "#layui-layim-close img",
success: function(a, e) {
(l = a).on("click", function() {
h.close(e),
r.show();
var a = _();
delete a.close,
layui.data(i.LOCAL_TABLE, {
key: w.user.id,
value: a
});
}),
"function" == typeof t.done && t.done.apply(null, arguments);
}
});
};
// 聊天窗口 E
var E = a.prototype.chat = function(t) {
t = t || {};
function l(a) {
a.data("receiver", t);
}
var a, e, i, n = "layim-chat-box",
o = f("#layui-layim-chat"),
s = {
data: t,
options: w.options,
local: _()
};
if (!t.id) return console.error("未传入必要参数:id");
if (t.new && (o.closest(".layui-layim-chat").remove(), delete o[0]), o[0]) return e = (a = y.find(".layim-chat-list")).find(".layim-chatlist-" + t.type + t.id), i = y.find(".layui-layer-max").hasClass("layui-layer-maxmin"), o = o.children("." + n), "none" === y.css("display") && y.show(), c && h.close(c.attr("times")), 1 !== a.find("li").length || e[0] || (i || y.addClass("layui-layim-chat-more").css("width", 800), a.css({
height: y.height()
}).show(), o.css("margin-left", "200px"), m && m.offset()), e[0] || (a.append(g(K).render(s)), o.append(g(G).render(s)), l(o.children(".layim-chat:last")), J(t), O()), P(a.find(".layim-chatlist-" + t.type + t.id)), e[0] || la(), Q(t), na(), p;
s.first = !0;
var r = p = h.open(f.extend({
type: 1,
area: "600px",
skin: "layui-layim-chat layui-layim-layer",
id: "layui-layim-chat",
title: "&#8203;",
shade: !1,
maxmin: !0,
offset: "auto",
anim: 5,
content: g('<ul class="layui-unselect layim-scrollbar layim-chat-list">' + K + '</ul><div class="' + n + '">' + G + "</div>").render(s),
success: function(a, e, i) {
m = i,
(y = a).css({
"min-width": "500px",
"min-height": "450px"
}),
l(a.find("." + n).children(".layim-chat:last")),
J(t),
na(),
Z(a),
Q(t),
la(),
U(),
a.on("dblclick", ".layim-chat-text img", function() {
var a = this.src;
h.close(E.photosIndex),
h.photos({
photos: {
data: [{
alt: "大图模式",
src: a
}]
},
anim: 5,
resize: !1,
success: function(a, e) {
E.photosIndex = e;
}
});
});
i = S();
layui.event.call(i.elem, b, "chatChange", i),
layui.event.call(i.elem, b, "chatInit", i),
"function" == typeof t.success && t.success.apply(t, arguments);
},
full: function(a) {
h.style(r, {
width: "100%",
height: "100%"
}, !0),
O();
},
resizing: O,
restore: O,
min: function() {
return H(), !1;
},
end: function() {
h.closeAll("tips"),
y = null;
}
}, t.layer));
return r;
};
// 好友状态处理 J
var J = function(a) {
f(".layim-" + a.type + a.id).each(function() {
f(this).hasClass("layim-list-gray") && layui.layim.setFriendStatus(a.id, "offline");
});
};
// 聊天窗口尺寸调整 O
var O = function() {
var a = y.find(".layim-chat-list"),
e = y.find(".layim-chat-main"),
i = y.height();
y.find(".layui-layer-title").outerHeight(),
y.find(".layim-chat-footer").outerHeight();
a.css({
height: i
}),
e.css({
height: i - 52 - 150
});
};
// 最小化聊天窗口 H
var H = a.prototype.setChatMin = function(i) {
var a = i || S().data;
layui.layim.cache().options;
y && !i && y.hide(),
h.close(H.index),
H.index = h.open(f.extend({
type: 1,
title: !1,
skin: "layui-layim-min layui-layim-layer",
shade: !1,
closeBtn: !1,
anim: 2,
offset: "b",
move: "#layui-layim-min",
resize: !1,
content: '<img id="layui-layim-min" src="' + (a.avatar || w.options.defaultAvatar) + '"><span>' + a.username + "</span>",
success: function(a, e) {
i || (c = a),
a.find(".layui-layer-content span").on("click", function() {
h.close(e),
i ? layui.each(w.chat, function(a, e) {
E(e);
}) : y.show(),
i && (w.chat = [], M());
}),
a.find(".layui-layer-content img").on("click", function(a) {
layui.stope(a);
});
}
}, i && i.layer));
};
// 打开添加联系人面板 i
var i = a.prototype.openRequestContactsPanel = function(t, a) {
t = t || {};
var e = "addFriend" === a ? "同意添加好友" : {
friend: "申请好友",
group: "申请群聊"
}[t.type] || "";
return h.close(i.index),
i.index = h.open({
type: 1,
area: "430px",
title: e,
shade: !1,
resize: !1,
btn: a ? ["确认", "取消"] : ["发送申请", "关闭"],
content: g(N).render({
data: {
username: t.username || t.groupname,
avatar: t.avatar || w.options.defaultAvatar,
group: t.group || parent.layui.layim.cache().friend || [],
type: t.type
},
type: a
}),
yes: function(a, e) {
var i = e.find("#LAY_layimGroup"),
e = e.find("#LAY_layimRemark"),
i = {
gid: i.val(),
note: e.val(),
index: a
};
"function" == typeof t.onConfirm && t.onConfirm(i);
},
btn1: function(a, e) {
"function" == typeof t.onCancel && t.onCancel({
index: a
});
}
});
};
// 打开添加好友面板
a.prototype.openAddFriendPanel = function(a) {
return i(a, "addFriend"), this;
};
// 切换聊天标签 P
var P = function(a, e) {
var i = -1 === (a = a || f(".layim-chat-list ." + C)).index() ? 0 : a.index(),
t = ".layim-chat",
l = y.find(t).eq(i),
n = y.find(".layui-layer-max").hasClass("layui-layer-maxmin");
if (e) return a.hasClass(C) && P(0 === i ? a.next() : a.prev()), 1 === (e = y.find(t).length) ? h.close(p) : (a.remove(), l.remove(), 2 === e && (y.find(".layim-chat-list").hide(), n || y.removeClass("layui-layim-chat-more").css("width", "600px"), y.find(".layim-chat-box").css("margin-left", 0), m) && m.offset(), !1);
a.addClass(C).siblings().removeClass(C),
l.addClass(x).siblings(t).removeClass(x),
l.find(".layim-loading")[0] || l.find("textarea").focus();
i = S();
layui.event.call(i.elem, b, "chatChange", i),
U();
};
// 更新未读消息 U
var U = function() {
var a = S();
w.message[a.data.type + a.data.id] && delete w.message[a.data.type + a.data.id];
};
// 获取当前聊天窗口 S
var S = a.prototype.currentChat = function(a) {
var e, i;
if (y) return a = void 0 === a ? f(".layim-chat-list ." + C).index() : a,
e = (a = y.find(".layim-chat").eq(a)).find(".layim-chat-textarea>textarea"),
i = a.data("receiver"),
{
elem: a,
data: i,
textarea: e
};
};
// 设置背景 Z
var Z = function(a) {
var e = w.options,
i = _().backgroundImage;
a.css({
"background-image": i ? "url(" + i + ")" : e.backgroundImage ? "url(" + L("images/background/" + e.backgroundImage) + ")" : "none"
});
};
// 记录聊天历史 Q
var Q = function(a) {
var e, i = w.options,
t = _(),
l = {},
n = t.history || {},
o = n[a.type + a.id];
r && (e = r.find(".layim-list-history"),
a.historyTime = (new Date).getTime(),
n[a.type + a.id] = a,
t.history = n,
layui.data(i.LOCAL_TABLE, {
key: w.user.id,
value: t
}),
o || (l[a.type + a.id] = a,
n = g(s({
type: "history",
item: "d.data"
})).render({
data: l
}),
e.prepend(n),
e.find(".layim-null").remove()));
};
// 发送消息 I
var I = a.prototype.sendMessage = function(a) {
var e = w.options,
i = {
username: w.user ? w.user.username : "访客",
avatar: w.user ? w.user.avatar : e.defaultAvatar,
id: w.user ? w.user.id : null,
user: !0
},
t = S(),
l = t.data,
n = "ai" === l.type,
o = t.elem.find(".layim-chat-main > ul"),
s = t.textarea;
i.content = a = String(a || s.val()),
"" !== a.replace(/\s/g, "") && (o.append(g(T).render(f.extend({}, i, {
content: d(a)
}))), j(o.children("li:last-child")), n && W(), o = {
user: i,
receiver: l
}, i = {
username: i.username,
avatar: i.avatar || e.defaultAvatar,
id: l.id,
type: l.type,
content: a,
timestamp: (new Date).getTime(),
user: !0
}, ta(i), layui.event.call(t.elem, b, "sendMessage", o)),
M(),
s.val(""),
n ? s.blur() : s.focus();
};
// AI 思考中 W
var W = function(a, e) {
function i() {
return o.children("li[" + k + "]").children(".layim-chat-text");
}
var t = w.options,
a = S(a),
l = a.data,
n = a.elem,
o = a.elem.find(".layim-chat-main > ul"),
a = n.find(".layim-loading");
clearTimeout(o.data("timer")),
"function" == typeof e ? e(i(), a) : (n.append('<div class="layim-loading"></div>'), o.append(g(T).render(f.extend({}, l, {
content: '<i class="layui-icon layui-icon-loading-1 layui-anim layui-anim-rotate layui-anim-loop"></i> 正在思考中…',
status: k
}))), o.data("timer", setTimeout(function() {
i().html("<strong>Error:</strong> Message timeout"),
n.find(".layim-loading").remove();
}, t.chatTimeout)));
};
// 浏览器通知 aa
var aa = function(a) {
a = a || {},
window.Notification && ("granted" === Notification.permission ? new Notification(a.title || "", {
body: a.content || "",
icon: a.avatar || w.options.defaultAvatar
}) : Notification.requestPermission());
};
// 接收消息 ea
var ea = a.prototype.getMessage = function(i) {
i = f.extend({
finished: !0,
saveLocalChatlog: !0
}, i);
var t, l, n, o, a = w.options, e = w.user, s = (_(), "ai" === i.type), r = f(".layim-chatlist-" + i.type + i.id), c = {}, u = r.index();
if ((i.timestamp = i.timestamp || (new Date).getTime(), "group" === i.type ? i.uid === e.id && (i.user = !0) : i.id === e.id && (i.user = !0), i.finished) && (i.saveLocalChatlog && ta(i), a.voice && !s && (f("body").trigger("click"), ea.init ? v.ie && v.ie < 9 || ((e = document.createElement("audio")).src = L("voice/" + w.options.voice), e.play()) : ea.init = !0), (!y && i.content || -1 === u) && (w.message[i.type + i.id] ? w.message[i.type + i.id].push(i) : (w.message[i.type + i.id] = [i], "friend" === i.type ? (layui.each(w.friend, function(a, e) {
if (layui.each(e.list, function(a, e) {
if (e.id == i.id) return e.type = "friend", e.username = e.username, w.chat.push(e), t = !0;
}), t) return !0;
}), t || (i.temporary = !0, w.chat.push(i))) : "group" === i.type ? (layui.each(w.group, function(a, e) {
if (e.id == i.id) return c.avatar = e.avatar || w.options.defaultAvatar, !0;
}), l || (i.username = i.groupname, w.chat.push(i))) : (i.username = i.username || i.groupname, w.chat.push(i))), "group" === i.type && layui.each(w.group, function(a, e) {
if (e.id == i.id) return c.avatar = e.avatar || w.options.defaultAvatar, !0;
}), !i.system))) return a.notice && !s && aa({
title: "来自 " + i.username + " 的消息",
content: i.content,
avatar: c.avatar || i.avatar || a.defaultAvatar
}), H({
username: "收到新消息",
avatar: c.avatar || i.avatar || a.defaultAvatar,
anim: 6
});
y && (e = S(), i.finished && e.data.type + e.data.id !== i.type + i.id && (r.addClass("layui-anim layer-anim-06"), setTimeout(function() {
r.removeClass("layui-anim layer-anim-06");
}, 300)), n = y.find(".layim-chat").eq(u).find(".layim-chat-main > ul"), s = e.textarea, a = i.content, i.system ? -1 !== u && n.append('<li class="layim-chat-system"><span' + (i.saveChatlog ? ' class="layui-font-green"' : "") + ">" + a + "</span></li>") : (o = d(a), W(u, function(a, e) {
a[0] ? a.html(o) : n.append(g(T).render(f.extend({}, i, {
content: o
}))), i.finished && (a.closest("li[" + k + "]").removeAttr(k), e.remove());
})), M(), s.focus(), j(n.children("li:last-child")));
};
// 代码高亮 j
var j = function(a) {
var e = w.options,
i = _();
layui.code({
elem: a.find("pre>code"),
theme: e.theme || i.theme || ""
});
};
// 消息盒子计数 ia
var ia = "layui-anim-loop layer-anim-05";
// 保存聊天记录 ta
var ta = (a.prototype.setMsgboxCount = function(a) {
r.find(".layim-tool-msgbox").find("span").addClass(ia).html(a);
}, function(i) {
var t, a = w.options, e = _(), l = (S() || {}).data || {};
"enableLocalChatlog" in l && !l.enableLocalChatlog || (e.chatlog = e.chatlog || {}, (l = e.chatlog[i.type + i.id]) ? (layui.each(l, function(a, e) {
e.timestamp === i.timestamp && e.type === i.type && e.id === i.id && e.content === i.content && (t = !0);
}), t || i.fromid == w.user.id || l.push(i), l.length > a.LOCAL_MAX_CHATLOG && l.shift()) : e.chatlog[i.type + i.id] = [i], layui.data(a.LOCAL_TABLE, {
key: w.user.id,
value: e
}));
});
// 加载聊天记录 la
var la = function(t) {
w.options;
function a(a) {
var e = l.elem.find(".layim-chat-main ul"),
i = [];
"array" === layui.type(a) && (layui.each(a, function(a, e) {
e.system ? i.push('<li class="layim-chat-system"><span class="layui-font-green">' + e.content + "</span></li>") : i.push(g(T).render(f.extend({}, e, {
content: d(e.content)
})));
}), e.append(i.join("")), M(), j(l.elem), "function" == typeof t && t());
}
var e = _(),
l = S(),
i = l.data,
e = (e.chatlog || {})[i.type + i.id],
n = A("chatlog");
if ("function" == typeof n) return (n = n({
user: w.user,
receiver: i
})) && "function" == typeof n.then ? n.then(a, console.error) : a(n);
a(e);
};
// 滚动到底部 M
var M = (a.prototype.addContacts = function(i) {
var t, a, e, l = {}, n = r.find(".layim-list-" + i.type);
if (w[i.type]) if ("friend" === i.type) layui.each(w.friend, function(a, e) {
if (i.gid == e.id) return layui.each(w.friend[a].list, function(a, e) {
if (e.id == i.id) return t = !0;
}), t ? h.msg("好友 [" + (i.username || "") + "] 已经存在列表中", {
anim: 6
}) : (w.friend[a].list = w.friend[a].list || [], (l[w.friend[a].list.length] = i).groupIndex = a, w.friend[a].list.push(i), !0);
}); else if ("group" === i.type) {
if (layui.each(w.group, function(a, e) {
if (e.id == i.id) return t = !0;
}), t) return h.msg("您已是 [" + (i.groupname || "") + "] 的群成员", {
anim: 6
});
l[w.group.length] = i, w.group.push(i);
}
t || (a = g(s({
type: i.type,
item: "d.data",
index: "friend" === i.type ? "data.groupIndex" : null
})).render({
data: l
}), "friend" === i.type ? ((e = n.find(">li").eq(i.groupIndex)).find(".layui-layim-list").append(a), e.find(".layim-count").html(w.friend[i.groupIndex].list.length), e.find(".layim-null")[0] && e.find(".layim-null").remove()) : "group" === i.type && (n.append(a), n.find(".layim-null")[0]) && n.find(".layim-null").remove());
}, a.prototype.removeContacts = function(t) {
var l = r.find(".layim-list-" + t.type);
w[t.type] && ("friend" === t.type ? layui.each(w.friend, function(i, a) {
layui.each(a.list, function(a, e) {
if (t.id == e.id) return (e = l.find(">li").eq(i)).find(".layui-layim-list>li"), e.find(".layui-layim-list>li").eq(a).remove(), w.friend[i].list.splice(a, 1), e.find(".layim-count").html(w.friend[i].list.length), 0 === w.friend[i].list.length && e.find(".layui-layim-list").html('<li class="layim-null">该分组下已无好友了</li>'), !0;
});
}) : "group" === t.type && layui.each(w.group, function(a, e) {
if (t.id == e.id) return l.find(">li").eq(a).remove(), w.group.splice(a, 1), 0 === w.group.length && l.html('<li class="layim-null">暂无群组</li>'), !0;
}));
}, function() {
var a, e = w.options, i = S().elem.find(".layim-chat-main"), t = i.children("ul"), l = t.children("li"), n = l.length, e = e.LOCAL_MAX_CHATLOG;
e <= n && (a = l.eq(0), t.prev().hasClass("layim-chat-system") || t.before('<div class="layim-chat-system"><span layim-event="chatlog">…</span></div>'), e < n) && a.remove(),
i.scrollTop(i[0].scrollHeight + 1e3),
l.last().find("img").on("load", function() {
i.scrollTop(i[0].scrollHeight + 1e3);
});
});
// 输入框事件处理 na
var na = function() {
var t = S().textarea;
t.focus(),
t.off("keydown").on("keydown", function(a) {
var e = _(),
i = a.keyCode;
if ("Ctrl+Enter" === e.sendHotKey) a.ctrlKey && 13 === i && I();
else if (13 === i) {
if (a.ctrlKey) return t.val(t.val() + "\n");
a.shiftKey || (a.preventDefault(), I());
}
});
};
// 表情包 oa
var oa = {
"呵呵": "^O^",
"惊讶": "w(?Д?)w",
"不屑": " ( ̄_, ̄ )",
"好耶": "ヽ(✿゚▽゚)",
"亲": "o(*≧3≦)o",
"棒": "(ง•̀ω•́)ง",
"涨": " ( ̄▽ ̄)↗",
"得意": "<( ̄▽ ̄)>",
"挖鼻孔": " (*≧r≦)",
"惊": "⊙・⊙",
"飞": "ヾ(≧▽≦*)o",
"呵呵呵": "o( ̄▽ ̄o#)",
"好滴": " (u‿u✿)",
"啊啊": "(≧口≦)",
"啦啦": "♪(^▽^*)",
"惊喜": "┗(≧▽≦)┛",
"酷": " o(*^^*)o",
"陶醉": "( *≧▽≦)",
"喂": " (#`O)",
"愣住": " (°ー°〃)",
"放屁": " ◎| ̄|_ =3",
"可爱": "(=。=)",
"生气": " (`ε´)",
"满足": " o(*≧▽≦*)o",
"崩溃": "o(≧口≦)o",
"嘻嘻嘻": "(⊙▽⊙)",
"晕": "XX",
"哼": " ━┳━ ━━",
"哭星星": " (=。•ω•。=)m",
"呜呜": " ≡ω≡",
"熊": "(*≧∀≦*)",
"害羞": " (✿•ᴗ•✿)",
good: " o(≧▽≦)d",
"可爱": "*^-^*",
"爆笑": "≧(≧▽≦*)o",
"卖萌": "=ω="
};
// 动画效果 B
var B = "layui-anim-upbit";
// 事件处理器 z
var z = {
status: function(a, e) {
function i() {
a.next().hide().removeClass(B);
}
var t = a.attr("lay-type");
"show" === t ? (layui.stope(e), a.next().show().addClass(B), f(document).off("click", i).on("click", i)) : (e = a.parent().prev(), a.addClass(C).siblings().removeClass(C), e.html(a.find("cite").html()), e.removeClass("layim-status-" + ("online" === t ? "hide" : "online")).addClass("layim-status-" + t), layui.event.call(a[0], b, "online", {
status: t
}));
},
sign: function() {
var a = r.find(".layui-layim-remark");
a.on("change", function() {
var a = this.value;
layui.event.call(this, b, "sign", {
value: a
});
}),
a.on("keyup", function(a) {
13 === a.keyCode && this.blur();
});
},
tab: function(a) {
var e, i = ".layim-tab-content",
t = r.find(".layui-layim-tab>li");
"number" == typeof a ? (e = a, a = t.eq(e)) : e = a.index(),
(2 < e ? t : (z.tab.index = e, a.addClass(C).siblings())).removeClass(C),
r.find(i).eq(e).addClass(x).siblings(i).removeClass(x);
},
spread: function(a) {
var e = a.attr("lay-type"),
i = "true" === e ? "false" : "true",
t = w.options,
l = _();
a.next()["true" === e ? "removeClass" : "addClass"](x),
l["spread" + a.parent().index()] = i,
layui.data(t.LOCAL_TABLE, {
key: w.user.id,
value: l
}),
a.attr("lay-type", i),
a.find(".layui-icon").html("true" == i ? "&#xe61a;" : "&#xe602;");
},
search: function(a) {
function e(a) {
var e = d.val().replace(/\s/);
if ("" === e) z.tab(0 | z.tab.index);
else {
for (var i = [], t = w.friend || [], l = w.group || [], n = "", o = 0; o < t.length; o++)
for (var s = 0; s < (t[o].list || []).length; s++) -1 !== t[o].list[s].username.indexOf(e) && (t[o].list[s].type = "friend", t[o].list[s].index = o, t[o].list[s].list = s, i.push(t[o].list[s]));
for (var r = 0; r < l.length; r++) -1 !== l[r].groupname.indexOf(e) && (l[r].type = "group", l[r].index = r, l[r].list = r, i.push(l[r]));
if (0 < i.length)
for (var c = 0; c < i.length; c++) n += '<li layim-event="chat" data-type="' + i[c].type + '" data-index="' + i[c].index + '" data-list="' + i[c].list + '"><img src="' + (i[c].avatar || w.options.defaultAvatar) + '"><span>' + (i[c].username || i[c].groupname || "匿名") + "</span><p>" + (i[c].remark || i[c].sign || "") + "</p></li>";
else n = '<li class="layim-null">无搜索结果</li>';
u.html(n),
z.tab(3);
}
}
var i = r.find(".layui-layim-search"),
u = r.find("#layui-layim-search"),
d = i.find("input"),
t = w.options.contactsPanel;
!t.showFriend && t.showGroup ? z.tab.index = 1 : t.showFriend || t.showGroup || (z.tab.index = 2),
i.show(),
d.focus(),
d.off("keyup", e).on("keyup", e);
},
closeSearch: function(a) {
a.parent().hide(),
z.tab(0 | z.tab.index);
},
msgbox: function() {
var a = r.find(".layim-tool-msgbox"),
e = w.options,
i = e.pageurl || {},
e = "function" == typeof i.msgbox ? i.msgbox({
config: e,
user: w.user
}) : i.msgbox;
if ("string" == typeof e) return h.close(z.msgbox.index),
a.find("span").removeClass(ia).html(""),
z.msgbox.index = h.open({
type: 2,
title: "消息盒子",
shade: !1,
maxmin: !0,
area: ["600px", "518px"],
skin: "layui-layer-border",
resize: !1,
content: e
});
},
find: function() {
var a = w.options,
e = a.pageurl || {},
a = "function" == typeof e.find ? e.find({
config: a,
user: w.user
}) : e.find;
if ("string" == typeof a) return h.close(z.find.index),
z.find.index = h.open({
type: 2,
title: "查找",
shade: !1,
maxmin: !0,
area: ["1000px", "518px"],
skin: "layui-layer-border",
resize: !1,
content: a
});
},
set: function() {
var e, n = w.options,
a = (e = [], layui.each(Array(5), function(a) {
e.push(L("images/background/" + (a + 1) + ".jpg"));
}), e);
h.open({
type: 1,
title: "设置",
shade: !1,
area: "260px",
anim: 5,
skin: "layui-layer-border layui-layim-layer",
id: "layui-layim-set",
zIndex: h.zIndex + 999999,
resize: !1,
content: g(q).render({
backgroundImages: a
}),
success: function(a, e, i) {
o.render(a.find(".layui-form"));
function t(a) {
if (a) {
if (v.ie) return;
l.theme = "dark",
o.val("layim-set", {
theme: !0
});
} else delete l.theme;
layui.data(n.LOCAL_TABLE, {
key: w.user.id,
value: l
});
}
var l = _();
t("dark" === l.theme),
o.on("switch(layim-theme-mode)", function(a) {
var e = a.elem.checked;
t(a.elem.checked),
$("dark" === e ? "dark" : "light");
});
}
});
},
setBackgroundImage: function(a) {
var e = a.attr("src"),
i = w.options,
t = _();
(t.backgroundImage = e) || delete t.backgroundImage,
layui.data(i.LOCAL_TABLE, {
key: w.user.id,
value: t
});
try {
r.css({
"background-image": e ? "url(" + e + ")" : "none"
}),
y.css({
"background-image": e ? "url(" + e + ")" : "none"
});
} catch (a) {}
i = (e || "").replace(L("images/background"), "");
layui.event.call(a[0], b, "backgroundImage", {
filename: i,
src: e
});
},
chat: function(a) {
var e = _(),
i = a.data("type"),
t = a.data("index"),
a = a.attr("data-list") || a.index(),
l = {};
"friend" === i ? l = w[i][t].list[a] : "group" === i ? l = w[i][a] : "history" === i && (l = (e.history || {})[t] || {}),
l.username = l.username || l.groupname,
"history" !== i && (l.type = i),
E(l);
},
tabChat: function(a) {
P(a);
},
closeChat: function(a, e) {
P(a.parent(), 1),
layui.stope(e);
},
closeThisChat: function() {
P(null, 1);
},
groupMembers: function(s, a) {
function r() {
e.html("&#xe61a;"),
s.data("down", null),
h.close(z.groupMembers.index);
}
var e = s.find(".layui-icon"),
c = ".layim.open.members";
s.data("down") ? r() : (e.html("&#xe619;"), s.data("down", !0), z.groupMembers.index = h.tips('<ul class="layim-members-list layim-border"></ul>', s, {
tips: 3,
time: 0,
anim: 5,
isOutAnim: !1,
fixed: !0,
skin: "layui-layim-members layui-layim-layer",
success: function(a) {
var e = S(),
i = a.find(".layim-members-list"),
t = [],
l = {},
n = y.find(".layui-layer-max").hasClass("layui-layer-maxmin"),
o = "none" === y.find(".layim-chat-list").css("display");
n && i.css({
width: f(window).width() - 22 - (o || 200)
}),
n = "layui-layim-loading",
(o = i).html('<span class="' + n + '"><i class="layui-icon layui-icon-loading-1 layui-anim layui-anim-rotate layui-anim-loop"></i></span>'),
o.children("." + n),
layui.event.call(s[0], b, "viewMmembers", {
ajax: u,
layero: a,
receiver: e.data,
render: function(a) {
a && (layui.each(a.list, function(a, e) {
t.push(['<li data-uid="' + e.id + '">',
'<a href="javascript:;">',
'<img src="' + (e.avatar || w.options.defaultAvatar) + '">',
"<cite>" + e.username + "</cite>",
"</a>",
"</li>"
].join("")),
l[e.id] = e);
}),
i.html(t.join("")),
s.find(".layim-chat-members").html(a.members || (a.list || []).length + "人"),
i.find("li").on("click", function() {
var a = f(this).data("uid"),
a = l[a];
E({
username: a.username,
type: "friend",
avatar: a.avatar || w.options.defaultAvatar,
id: a.id
}),
r();
}));
}
});
a.on("mousedown" + c, function(a) {
layui.stope(a);
});
}
})),
f(document).off("mousedown" + c).on("mousedown" + c, r),
f(window).off("resize" + c).on("resize" + c, r),
s.off("mousedown" + c).on("mousedown" + c, layui.stope);
},
send: function() {
I();
},
setSend: function(a, e) {
var i = w.options,
t = z.setSend.box = a.siblings(".layim-menu-box"),
l = a.attr("lay-type");
"show" === l ? (layui.stope(e), t.show().addClass(B), f(document).off("click", z.setSendHide).on("click", z.setSendHide)) : (t = _(), a.addClass(C).siblings().removeClass(C), t.sendHotKey = l, layui.data(i.LOCAL_TABLE, {
key: w.user.id,
value: t
}), z.setSendHide(e, a.parent()));
},
setSendHide: function(a, e) {
(e || z.setSend.box).hide().removeClass(B);
},
face: function(a, e) {
var i, t = "",
l = S();
for (i in oa) t += '<li title="' + i + '">' + oa[i] + "</li>";
z.face.index = h.tips(t = '<ul class="layui-clear layim-face-list">' + t + "</ul>", a, {
tips: 1,
time: 0,
fixed: !0,
anim: 5,
skin: "layui-layim-face",
success: function(a) {
a.find(".layim-face-list>li").on("mousedown", function(a) {
layui.stope(a);
}).on("click", function() {
n(l.textarea[0], this.innerHTML + " "),
h.close(z.face.index);
});
}
});
a = ".layim.chatTools.face";
f(document).off("mousedown" + a, z.faceHide).on("mousedown" + a, z.faceHide),
f(window).off("resize" + a, z.faceHide).on("resize" + a, z.faceHide),
layui.stope(e);
},
faceHide: function() {
h.close(z.face.index);
},
file: function(a) {
var t = a.data("chat-toolname"),
l = S(),
e = (w.options.chatTools.filter(function(a) {
return a.name === t;
})[0] || {}).ajax;
layui.upload.render(f.extend({
elem: a.find("input")[0],
accept: t,
done: function(a) {
var e, i;
0 == a.code ? (e = (i = a.data = a.data || {}).filename || "", i = i.src, "image" === t ? n(l.textarea[0], "![](" + i + ")") : "file" === t && n(l.textarea[0], "!file[" + (e || "下载文件") + "](" + i + ")"), I()) : h.msg(a.msg || "上传失败");
}
}, e));
},
remoteMedia: function(a) {
var i = a.data("chat-toolname"),
t = S();
h.prompt({
title: "请输入远程" + {
audio: "音频",
video: "视频"
}[i] + " URL",
shade: !1,
anim: 5,
id: "LAYIM-LAYER-CHAT-TOOL-" + i,
offset: [a.offset().top - f(window).scrollTop() - 168 + "px", a.offset().left + "px"]
}, function(a, e) {
n(t.textarea[0], "!" + i + "(" + a + ")"),
I(),
h.close(e);
});
},
extendChatTool: function(a) {
var i, t = a.data("chat-toolname"),
e = S(),
l = w.options.chatTools,
l = (layui.each(l, function(a, e) {
if (e.name === t) return i = e, !0;
}), i);
l && "function" == typeof l.onClick && l.onClick({
data: e,
elem: a,
insert: function(a) {
n(e.textarea[0], a);
}
});
},
playAudio: function(a) {
function e() {
t.pause(),
a.removeAttr("status"),
a.find("i").addClass("layui-icon-play").removeClass("layui-icon-pause");
}
var i = a.data("audio"),
t = i || document.createElement("audio");
return a.data("error") ? h.msg("播放音频源异常") : t.play ? void(a.attr("status") ? e() : (i || (t.src = a.data("src")), t.play(), a.attr("status", "pause"), a.data("audio", t), a.find("i").addClass("layui-icon-pause").removeClass("layui-icon-play"), t.onended = function() {
e();
}, t.onerror = function() {
h.msg("播放音频源异常"),
a.data("error", !0),
e();
})) : h.msg("您的浏览器不支持 audio");
},
playVideo: function(a) {
a = a.data("src");
if (!document.createElement("video").play) return h.msg("您的浏览器不支持video");
h.close(z.playVideo.index),
z.playVideo.index = h.open({
type: 1,
title: "播放视频",
area: ["460px", "300px"],
maxmin: !0,
shade: !1,
skin: "layui-layim-layer",
content: '<div style="background-color: #000; height: 100%;"><video style="position: absolute; width: 100%; height: 100%;" src="' + a + '" loop="loop" autoplay="autoplay"></video></div>'
});
},
chatlog: function(a) {
var e = w.options,
i = e.pageurl || {},
t = S();
return i.chatlog ? "string" == typeof(e = "function" == typeof i.chatlog ? i.chatlog({
config: e,
user: w.user,
receiver: t.data
}) : i.chatlog) ? (h.close(z.chatlog.index),
z.chatlog.index = h.open({
type: 2,
maxmin: !0,
title: "与 <strong>" + t.data.username + "</strong> 的聊天记录",
area: ["450px", "100%"],
shade: !1,
offset: "r",
anim: "slideLeft",
id: "layui-layim-chatlog",
content: e
})) : void 0 : h.msg("未开启更多聊天记录");
},
menuHistory: function(a, e) {
var i, t = w.options,
l = _(),
n = a.parent(),
a = a.data("type"),
o = r.find(".layim-list-history"),
s = '<li class="layim-null">暂无历史会话</li>';
"one" === a ? (delete(i = l.history)[n.data("index")], l.history = i, layui.data(t.LOCAL_TABLE, {
key: w.user.id,
value: l
}), f(".layim-list-history li.layim-" + n.data("index")).remove(), 0 === o.find("li").length && o.html(s)) : "all" === a && (delete l.history, layui.data(t.LOCAL_TABLE, {
key: w.user.id,
value: l
}), o.html(s)),
h.closeAll("tips");
}
};
// 绑定事件
t.on("layim-event", z),
e(b, new a);
}).link(layui.cache.layimResPath + "layim.css", "skinlayimcss");