附件图片双击放大显示

This commit is contained in:
2026-07-22 15:12:14 +08:00
parent 1889b3b71b
commit 2feb6004b8
2 changed files with 33 additions and 3 deletions

View File

@@ -368,6 +368,14 @@
document.body.appendChild(overlay);
}
function onImgThumbDblClick(img) {
const overlay = document.createElement('div');
overlay.className = 'fullscreen-overlay';
overlay.innerHTML = `<img src="${img.src}" style="max-width:100%;max-height:100%;object-fit:contain" alt="">`;
overlay.addEventListener('click', () => overlay.remove());
document.body.appendChild(overlay);
}
function onBubbleDblClick(e) {
e.stopPropagation();
const bubble = e.currentTarget;
@@ -382,7 +390,7 @@
document.body.appendChild(overlay);
}
// 临时输入中...气泡
// 临时"输入中..."气泡
function insertTempBubble() {
clearTempBubble();
const tempId = 'temp_' + Date.now();
@@ -391,10 +399,30 @@
messagesContainer.insertAdjacentHTML('beforeend', renderMessageHTML(tempMsg));
scrollToBottom();
tempBubbleTimer = setTimeout(() => { clearTempBubble(); }, 8000);
// 降级轮询:如果 WebSocket 消息丢失,定时从服务端拉取
if (pollTimer) clearInterval(pollTimer);
let pollCount = 0;
pollTimer = setInterval(async () => {
pollCount++;
if (!currentRoom || pollCount > 5) { clearInterval(pollTimer); pollTimer = null; return; }
try {
const token = getToken();
const res = await fetch(API + `/api/rooms/${currentRoom}/messages`, { headers: { 'Authorization': `Bearer ${token}` } });
const msgs = await res.json();
const lastCacheId = messageCache.filter(m => !m.isTemp && !m.isPlaceholder).slice(-1)[0]?.id;
const newMsgs = msgs.filter(m => !lastCacheId || m.id > lastCacheId);
if (newMsgs.length) {
clearInterval(pollTimer); pollTimer = null;
clearTempBubble();
newMsgs.forEach(m => appendMessage(m));
}
} catch(e) {}
}, 2000);
}
function clearTempBubble() {
if (tempBubbleTimer) { clearTimeout(tempBubbleTimer); tempBubbleTimer = null; }
if (pollTimer) { clearInterval(pollTimer); pollTimer = null; }
messageCache = messageCache.filter(m => !m.isTemp);
const tempEls = messagesContainer.querySelectorAll('[data-msg-id^="temp_"]');
tempEls.forEach(el => el.remove());
@@ -404,6 +432,7 @@
let wsReconnectTimer = null;
let reconnectAttempts = 0;
const MAX_RECONNECT_DELAY = 30000;
let pollTimer = null; // 降级轮询定时器
function initWebSocket() {
const token = getToken();
@@ -417,6 +446,7 @@
};
ws.onmessage = (e) => {
const data = JSON.parse(e.data);
console.log('📩 WS 收到:', data.type);
if (data.type === 'new_message') {
const msg = data.message;
if (currentRoom === msg.room_id) {
@@ -733,7 +763,7 @@
const p = await res.json();
document.getElementById('detail-title').textContent = p.item;
let attachHtml = '';
if (p.attachments?.length) attachHtml = '<div class="attachments">' + p.attachments.map(a => `<img class="img-thumb" src="${a.file_path}" alt="${a.file_path}">`).join('') + '</div>';
if (p.attachments?.length) attachHtml = '<div class="attachments">' + p.attachments.map(a => `<img class="img-thumb" src="${a.file_path}" alt="${a.file_path}" ondblclick="onImgThumbDblClick(this)">`).join('') + '</div>';
const historyHtml = p.history?.map(h => `<li><span class="history-time">${h.timestamp}</span> ${h.user}: ${h.action}</li>`).join('') || '';
document.getElementById('detail-content').innerHTML = `
<div class="detail-row"><strong>数量:</strong>${p.quantity}</div>

View File

@@ -236,7 +236,7 @@ app.get('/api/rooms/:roomId/purchases/export', auth, (req, res) => {
// WebSocket
const clients = new Map();
wss.on('connection', (ws, req) => {
//console.log('✅ WebSocket 客户端已连接');
console.log('✅ WebSocket 客户端已连接');
const url = new URL(req.url, 'http://localhost');
const token = url.searchParams.get('token');
if (!token) return ws.close();