迁移快捷好友操作事件
This commit is contained in:
@@ -267,19 +267,20 @@ class FriendController extends Controller
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据操作类型和互相状态生成不同文案(含内联快捷操作链接)
|
// 根据操作类型和互相状态生成不同文案(含前端代理快捷操作链接)
|
||||||
$btnStyle = 'font-weight:bold;text-decoration:underline;margin-left:6px;';
|
$btnStyle = 'font-weight:bold;text-decoration:underline;margin-left:6px;';
|
||||||
$btnAdd = "<a href='#' onclick=\"quickFriendAction('add','{$fromUsername}',this);return false;\" style='color:#16a34a;{$btnStyle}'>➕ 回加好友</a>";
|
$safeUsername = e($fromUsername);
|
||||||
$btnRemove = "<a href='#' onclick=\"quickFriendAction('remove','{$fromUsername}',this);return false;\" style='color:#6b7280;{$btnStyle}'>🗑️ 同步移除</a>";
|
$btnAdd = "<a href='#' data-quick-friend-action='add' data-quick-friend-username='{$safeUsername}' style='color:#16a34a;{$btnStyle}'>➕ 回加好友</a>";
|
||||||
|
$btnRemove = "<a href='#' data-quick-friend-action='remove' data-quick-friend-username='{$safeUsername}' style='color:#6b7280;{$btnStyle}'>🗑️ 同步移除</a>";
|
||||||
|
|
||||||
$content = match ($action) {
|
$content = match ($action) {
|
||||||
'added' => $mutual
|
'added' => $mutual
|
||||||
? "💚 <b>{$fromUsername}</b> 将你加为好友了!你们现在互为好友 🎉"
|
? "💚 <b>{$safeUsername}</b> 将你加为好友了!你们现在互为好友 🎉"
|
||||||
: "💚 <b>{$fromUsername}</b> 将你加为好友了!但你还没有添加对方为好友。{$btnAdd}",
|
: "💚 <b>{$safeUsername}</b> 将你加为好友了!但你还没有添加对方为好友。{$btnAdd}",
|
||||||
'removed' => $mutual
|
'removed' => $mutual
|
||||||
? "💔 <b>{$fromUsername}</b> 已将你从好友列表移除。你的好友列表中仍保留对方。{$btnRemove}"
|
? "💔 <b>{$safeUsername}</b> 已将你从好友列表移除。你的好友列表中仍保留对方。{$btnRemove}"
|
||||||
: "💔 <b>{$fromUsername}</b> 已将你从他的好友列表移除。",
|
: "💔 <b>{$safeUsername}</b> 已将你从他的好友列表移除。",
|
||||||
'online' => "🟢 你的好友 <b>{$fromUsername}</b> 上线啦!",
|
'online' => "🟢 你的好友 <b>{$safeUsername}</b> 上线啦!",
|
||||||
default => '',
|
default => '',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ export { bindGlobalDialogControls } from "./chat-room/dialog.js";
|
|||||||
export { bindDailySignInControls } from "./chat-room/daily-sign-in.js";
|
export { bindDailySignInControls } from "./chat-room/daily-sign-in.js";
|
||||||
export { applyFontSize, bindChatFontSizeControl, CHAT_FONT_SIZE_STORAGE_KEY, restoreChatFontSize } from "./chat-room/font-size.js";
|
export { applyFontSize, bindChatFontSizeControl, CHAT_FONT_SIZE_STORAGE_KEY, restoreChatFontSize } from "./chat-room/font-size.js";
|
||||||
export { bindChatImageUploadControl } from "./chat-room/image-upload.js";
|
export { bindChatImageUploadControl } from "./chat-room/image-upload.js";
|
||||||
export { bindFriendPanelControls, closeFriendPanel, friendSearch, loadFriends, openFriendPanel } from "./chat-room/friend-panel.js";
|
export { bindFriendPanelControls, closeFriendPanel, friendSearch, loadFriends, openFriendPanel, quickFriendAction } from "./chat-room/friend-panel.js";
|
||||||
export { closeChatImageLightbox, initChatImageLightboxEvents, openChatImageLightbox } from "./chat-room/lightbox.js";
|
export { closeChatImageLightbox, initChatImageLightboxEvents, openChatImageLightbox } from "./chat-room/lightbox.js";
|
||||||
export {
|
export {
|
||||||
bindMobileDrawerControls,
|
bindMobileDrawerControls,
|
||||||
@@ -75,7 +75,7 @@ import { bindGlobalDialogControls } from "./chat-room/dialog.js";
|
|||||||
import { bindDailySignInControls } from "./chat-room/daily-sign-in.js";
|
import { bindDailySignInControls } from "./chat-room/daily-sign-in.js";
|
||||||
import { applyFontSize, bindChatFontSizeControl, CHAT_FONT_SIZE_STORAGE_KEY, restoreChatFontSize } from "./chat-room/font-size.js";
|
import { applyFontSize, bindChatFontSizeControl, CHAT_FONT_SIZE_STORAGE_KEY, restoreChatFontSize } from "./chat-room/font-size.js";
|
||||||
import { bindChatImageUploadControl } from "./chat-room/image-upload.js";
|
import { bindChatImageUploadControl } from "./chat-room/image-upload.js";
|
||||||
import { bindFriendPanelControls, closeFriendPanel, friendSearch, loadFriends, openFriendPanel } from "./chat-room/friend-panel.js";
|
import { bindFriendPanelControls, closeFriendPanel, friendSearch, loadFriends, openFriendPanel, quickFriendAction } from "./chat-room/friend-panel.js";
|
||||||
import { closeChatImageLightbox, initChatImageLightboxEvents, openChatImageLightbox } from "./chat-room/lightbox.js";
|
import { closeChatImageLightbox, initChatImageLightboxEvents, openChatImageLightbox } from "./chat-room/lightbox.js";
|
||||||
import {
|
import {
|
||||||
bindMobileDrawerControls,
|
bindMobileDrawerControls,
|
||||||
@@ -154,6 +154,7 @@ if (typeof window !== "undefined") {
|
|||||||
friendSearch,
|
friendSearch,
|
||||||
loadFriends,
|
loadFriends,
|
||||||
openFriendPanel,
|
openFriendPanel,
|
||||||
|
quickFriendAction,
|
||||||
bindMobileDrawerControls,
|
bindMobileDrawerControls,
|
||||||
closeMobileDrawer,
|
closeMobileDrawer,
|
||||||
loadMobileRoomList,
|
loadMobileRoomList,
|
||||||
@@ -220,6 +221,7 @@ if (typeof window !== "undefined") {
|
|||||||
window.closeFriendPanel = closeFriendPanel;
|
window.closeFriendPanel = closeFriendPanel;
|
||||||
window.friendSearch = friendSearch;
|
window.friendSearch = friendSearch;
|
||||||
window.openFriendPanel = openFriendPanel;
|
window.openFriendPanel = openFriendPanel;
|
||||||
|
window.quickFriendAction = quickFriendAction;
|
||||||
window.closeMobileDrawer = closeMobileDrawer;
|
window.closeMobileDrawer = closeMobileDrawer;
|
||||||
window.loadMobileRoomList = loadMobileRoomList;
|
window.loadMobileRoomList = loadMobileRoomList;
|
||||||
window.openMobileDrawer = openMobileDrawer;
|
window.openMobileDrawer = openMobileDrawer;
|
||||||
|
|||||||
@@ -286,6 +286,59 @@ async function friendAction(action, username, button) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 聊天消息和横幅内的快捷好友操作。
|
||||||
|
*
|
||||||
|
* @param {"add"|"remove"|string} action 操作类型
|
||||||
|
* @param {string} username 目标用户名
|
||||||
|
* @param {HTMLElement} element 触发元素
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
export async function quickFriendAction(action, username, element) {
|
||||||
|
if (!["add", "remove"].includes(action) || !username || !(element instanceof HTMLElement)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element.dataset.done) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
element.dataset.done = "1";
|
||||||
|
element.textContent = "处理中…";
|
||||||
|
element.style.pointerEvents = "none";
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 消息内链接来自后端 HTML,用户名进入 path 前仍必须编码。
|
||||||
|
const response = await fetch(`/friend/${encodeURIComponent(username)}/${action}`, {
|
||||||
|
method: action === "add" ? "POST" : "DELETE",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"X-CSRF-TOKEN": csrf(),
|
||||||
|
Accept: "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
room_id: roomId(),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
if (data.status === "success") {
|
||||||
|
element.textContent = action === "add" ? "✅ 已回加" : "✅ 已移除";
|
||||||
|
element.style.color = "#16a34a";
|
||||||
|
element.style.textDecoration = "none";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
element.textContent = `❌ ${data.message || "操作失败"}`;
|
||||||
|
element.style.color = "#cc4444";
|
||||||
|
} catch (error) {
|
||||||
|
element.textContent = "❌ 网络错误";
|
||||||
|
element.style.color = "#cc4444";
|
||||||
|
delete element.dataset.done;
|
||||||
|
element.style.pointerEvents = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通过搜索框按用户名添加好友,具体校验仍交给后端。
|
* 通过搜索框按用户名添加好友,具体校验仍交给后端。
|
||||||
*
|
*
|
||||||
@@ -370,6 +423,18 @@ export function bindFriendPanelControls() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const quickAction = event.target.closest("[data-quick-friend-action]");
|
||||||
|
if (quickAction) {
|
||||||
|
event.preventDefault();
|
||||||
|
// 后端系统消息只输出 data 属性,具体请求仍统一走模块方法。
|
||||||
|
void quickFriendAction(
|
||||||
|
quickAction.getAttribute("data-quick-friend-action") || "",
|
||||||
|
quickAction.getAttribute("data-quick-friend-username") || "",
|
||||||
|
quickAction,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const panel = event.target.closest("#friend-panel");
|
const panel = event.target.closest("#friend-panel");
|
||||||
// 只在点击遮罩本身时关闭,避免点击内容区误关。
|
// 只在点击遮罩本身时关闭,避免点击内容区误关。
|
||||||
if (panel && event.target === panel) {
|
if (panel && event.target === panel) {
|
||||||
|
|||||||
@@ -1563,7 +1563,7 @@
|
|||||||
label: '➕ 回加好友',
|
label: '➕ 回加好友',
|
||||||
color: '#10b981',
|
color: '#10b981',
|
||||||
onClick: async (btn, close) => {
|
onClick: async (btn, close) => {
|
||||||
await quickFriendAction('add', fromUsername, btn);
|
await window.quickFriendAction?.('add', fromUsername, btn);
|
||||||
if (btn.textContent.startsWith('✅')) {
|
if (btn.textContent.startsWith('✅')) {
|
||||||
setTimeout(close, 1500);
|
setTimeout(close, 1500);
|
||||||
}
|
}
|
||||||
@@ -1579,52 +1579,4 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 聊天区悄悄话内嵌链接的快捷好友操作。
|
|
||||||
* 由后端生成的 onclick="quickFriendAction('add'/'remove', username, this)" 调用。
|
|
||||||
*
|
|
||||||
* @param {string} act 'add' | 'remove'
|
|
||||||
* @param {string} username 目标用户名
|
|
||||||
* @param {HTMLElement} el 被点击的 <a> 元素,用于更新显示状态
|
|
||||||
*/
|
|
||||||
window.quickFriendAction = async function (act, username, el) {
|
|
||||||
if (el.dataset.done) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
el.dataset.done = '1';
|
|
||||||
|
|
||||||
el.textContent = '处理中…';
|
|
||||||
el.style.pointerEvents = 'none';
|
|
||||||
|
|
||||||
try {
|
|
||||||
const method = act === 'add' ? 'POST' : 'DELETE';
|
|
||||||
const url = `/friend/${encodeURIComponent(username)}/${act === 'add' ? 'add' : 'remove'}`;
|
|
||||||
const csrf = document.querySelector('meta[name="csrf-token"]')?.content ?? '';
|
|
||||||
const res = await fetch(url, {
|
|
||||||
method,
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'X-CSRF-TOKEN': csrf,
|
|
||||||
'Accept': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
room_id: window.chatContext?.roomId
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
const data = await res.json();
|
|
||||||
if (data.status === 'success') {
|
|
||||||
el.textContent = act === 'add' ? '✅ 已回加' : '✅ 已移除';
|
|
||||||
el.style.color = '#16a34a';
|
|
||||||
el.style.textDecoration = 'none';
|
|
||||||
} else {
|
|
||||||
el.textContent = '❌ ' + (data.message || '操作失败');
|
|
||||||
el.style.color = '#cc4444';
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
el.textContent = '❌ 网络错误';
|
|
||||||
el.style.color = '#cc4444';
|
|
||||||
delete el.dataset.done;
|
|
||||||
el.style.pointerEvents = '';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user