功能:好友悄悄话内嵌快捷操作链接
后端: - notifyOnlineUser 生成带内联 <a> 标签的内容 - added 未互相 → 嵌入 '➕ 回加好友' 链接 - removed 互相 → 嵌入 '🗑️ 同步移除' 链接 - 链接调用全局 quickFriendAction(act, username, el) 前端: - 新增 window.quickFriendAction() 全局函数 - 防重复点击(dataset.done 标记) - 成功后更新链接文字 '✅ 已回加' / '✅ 已移除',不刷新页面
This commit is contained in:
@@ -220,13 +220,17 @@ class FriendController extends Controller
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据操作类型和互相状态生成不同文案
|
// 根据操作类型和互相状态生成不同文案(含内联快捷操作链接)
|
||||||
|
$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>";
|
||||||
|
$btnRemove = "<a href=\'#\' onclick=\"quickFriendAction(\'remove\',\'{$fromUsername}\',this);return false;\" style=\'color:#6b7280;{$btnStyle}\'>🗑️ 同步移除</a>";
|
||||||
|
|
||||||
$content = match ($action) {
|
$content = match ($action) {
|
||||||
'added' => $mutual
|
'added' => $mutual
|
||||||
? "💚 <b>{$fromUsername}</b> 将你加为好友了!你们现在互为好友 🎉"
|
? "💚 <b>{$fromUsername}</b> 将你加为好友了!你们现在互为好友 🎉"
|
||||||
: "💚 <b>{$fromUsername}</b> 将你加为好友了!但你还没有添加对方为好友。",
|
: "💚 <b>{$fromUsername}</b> 将你加为好友了!但你还没有添加对方为好友。{$btnAdd}",
|
||||||
'removed' => $mutual
|
'removed' => $mutual
|
||||||
? "💔 <b>{$fromUsername}</b> 已将你从好友列表移除。你的好友列表中仍保留对方。"
|
? "💔 <b>{$fromUsername}</b> 已将你从好友列表移除。你的好友列表中仍保留对方。{$btnRemove}"
|
||||||
: "💔 <b>{$fromUsername}</b> 已将你从他的好友列表移除。",
|
: "💔 <b>{$fromUsername}</b> 已将你从他的好友列表移除。",
|
||||||
'online' => "🟢 你的好友 <b>{$fromUsername}</b> 上线啦!",
|
'online' => "🟢 你的好友 <b>{$fromUsername}</b> 上线啦!",
|
||||||
default => '',
|
default => '',
|
||||||
|
|||||||
@@ -712,6 +712,55 @@
|
|||||||
* @param {string} color 左边框 / 主题颜色
|
* @param {string} color 左边框 / 主题颜色
|
||||||
* @param {object|null} action 可选操作按钮 { label, username, action:'add'|'remove' }
|
* @param {object|null} action 可选操作按钮 { label, username, action:'add'|'remove' }
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 聊天区悄悄话内嵌链接的快捷好友操作。
|
||||||
|
* 由后端生成的 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';
|
||||||
|
|
||||||
|
const origText = el.textContent;
|
||||||
|
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 = '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
function showFriendToast(html, color = '#16a34a', action = null) {
|
function showFriendToast(html, color = '#16a34a', action = null) {
|
||||||
const toast = document.createElement('div');
|
const toast = document.createElement('div');
|
||||||
toast.style.cssText = `
|
toast.style.cssText = `
|
||||||
@@ -1541,7 +1590,8 @@
|
|||||||
if (!res.ok || data.status !== 'success') {
|
if (!res.ok || data.status !== 'success') {
|
||||||
const errDiv = document.createElement('div');
|
const errDiv = document.createElement('div');
|
||||||
errDiv.className = 'msg-line';
|
errDiv.className = 'msg-line';
|
||||||
errDiv.innerHTML = `<span style="color: #dc2626;">🤖【AI小班长】${data.message || '回复失败,请稍后重试'}</span>`;
|
errDiv.innerHTML =
|
||||||
|
`<span style="color: #dc2626;">🤖【AI小班长】${data.message || '回复失败,请稍后重试'}</span>`;
|
||||||
container.appendChild(errDiv);
|
container.appendChild(errDiv);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
Reference in New Issue
Block a user