diff --git a/client/renderer/app.js b/client/renderer/app.js
index 561b0e2..28e1e2f 100644
--- a/client/renderer/app.js
+++ b/client/renderer/app.js
@@ -326,6 +326,122 @@ async function showRecentServers() {
});
}
+// ===== Room Detail Modal =====
+let currentModalRoomId = null;
+let modalRefreshTimer = null;
+
+function openRoomModal(roomId) {
+ currentModalRoomId = roomId;
+ $('#modal-overlay').classList.remove('hidden');
+ refreshModalRoom();
+ modalRefreshTimer = setInterval(refreshModalRoom, 5000);
+}
+
+function closeRoomModal() {
+ currentModalRoomId = null;
+ $('#modal-overlay').classList.add('hidden');
+ if (modalRefreshTimer) { clearInterval(modalRefreshTimer); modalRefreshTimer = null; }
+}
+
+$('#modal-close').addEventListener('click', closeRoomModal);
+$('#modal-overlay').addEventListener('click', (e) => {
+ if (e.target === $('#modal-overlay')) closeRoomModal();
+});
+
+async function refreshModalRoom() {
+ if (!currentModalRoomId || !isConnected) return;
+ const result = await window.funmc.getRoomDetail(currentModalRoomId);
+ if (!result || !result.success) return;
+ const room = result.data.room;
+ const players = result.data.players || [];
+
+ $('#modal-room-name').textContent = `${room.name} ${room.password ? '🔒' : ''}`;
+ $('#modal-room-info').innerHTML = [
+ { l: '房间号', v: room.id },
+ { l: '房主', v: room.hostName },
+ { l: '版本', v: `${room.gameEdition === 'java' ? 'Java' : '基岩'} ${room.gameVersion}` },
+ { l: '玩家', v: `${room.currentPlayers}/${room.maxPlayers}` },
+ ].map(i => `
`).join('');
+
+ $('#modal-player-count').textContent = `(${players.length})`;
+ if (players.length === 0) {
+ $('#modal-player-list').innerHTML = '暂无玩家在线
';
+ } else {
+ $('#modal-player-list').innerHTML = players.map(p => `
+
+
+ 👤 ${escapeHtml(p.name)}
+ ${formatTimeSince(p.joinedAt)}
+
+
+
+ `).join('');
+ }
+}
+
+async function kickPlayer(roomId, playerId) {
+ if (!confirm('确定要踢出该玩家吗?')) return;
+ const result = await window.funmc.kickPlayer(roomId, playerId);
+ if (result && result.success) {
+ refreshModalRoom();
+ } else {
+ alert('踢出失败: ' + (result?.error || '未知错误'));
+ }
+}
+
+$('#modal-join-btn').addEventListener('click', () => {
+ if (currentModalRoomId) {
+ closeRoomModal();
+ quickJoin(currentModalRoomId);
+ }
+});
+
+$('#modal-delete-btn').addEventListener('click', async () => {
+ if (!currentModalRoomId) return;
+ if (!confirm('确定要删除此房间吗?此操作不可撤销。')) return;
+ const result = await window.funmc.deleteRoom(currentModalRoomId);
+ if (result && result.success) {
+ closeRoomModal();
+ loadRooms();
+ } else {
+ alert('删除失败: ' + (result?.error || '未知错误'));
+ }
+});
+
+// Chat in modal
+$('#modal-chat-send').addEventListener('click', sendChatMessage);
+$('#modal-chat-input').addEventListener('keydown', (e) => {
+ if (e.key === 'Enter') sendChatMessage();
+});
+
+async function sendChatMessage() {
+ const input = $('#modal-chat-input');
+ const msg = input.value.trim();
+ if (!msg || !currentModalRoomId) return;
+ input.value = '';
+ const sender = appSettings.playerName || 'Player';
+ appendChatMessage(sender, msg);
+ await window.funmc.sendChat(currentModalRoomId, sender, msg);
+}
+
+function appendChatMessage(sender, text, time) {
+ const container = $('#modal-chat-messages');
+ const t = time || new Date().toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' });
+ const div = document.createElement('div');
+ div.className = 'chat-msg';
+ div.innerHTML = `${escapeHtml(sender)} ${escapeHtml(text)}${t}`;
+ container.appendChild(div);
+ container.scrollTop = container.scrollHeight;
+}
+
+// Make room cards open modal
+document.addEventListener('click', (e) => {
+ const card = e.target.closest('.room-card');
+ if (card && !e.target.classList.contains('room-btn-join')) {
+ openRoomModal(card.dataset.id);
+ }
+});
+
// ===== Utilities =====
function showMsg(selector, text, type) {
const el = $(selector);
@@ -347,3 +463,11 @@ function formatUptime(seconds) {
if (m > 0) return `${m}分${s}秒`;
return `${s}秒`;
}
+
+function formatTimeSince(dateStr) {
+ const ms = Date.now() - new Date(dateStr).getTime();
+ const m = Math.floor(ms / 60000);
+ if (m < 1) return '刚刚';
+ if (m < 60) return `${m}分钟前`;
+ return `${Math.floor(m / 60)}小时前`;
+}
diff --git a/client/renderer/index.html b/client/renderer/index.html
index 07ec59a..8c5fac5 100644
--- a/client/renderer/index.html
+++ b/client/renderer/index.html
@@ -57,7 +57,7 @@
ℹ️ 关于
-
+
@@ -233,7 +233,7 @@
@@ -273,6 +273,35 @@
+
+
+