const messagesEl = document.getElementById("messages"); const inputEl = document.getElementById("input"); const sendBtn = document.getElementById("sendBtn"); const newChatBtn = document.getElementById("newChatBtn"); const chatListEl = document.getElementById("chatList"); const clearBtn = document.getElementById("clearBtn"); const sidebarToggleBtn = document.getElementById("sidebarToggle"); const appRootEl = document.querySelector(".app"); let chats = JSON.parse(localStorage.getItem("ds_chats") || "{}"); let currentChatId = localStorage.getItem("ds_current_chat"); let sidebarHidden = localStorage.getItem("ds_sidebar_hidden") === "1"; /** ---------- 时间格式化 ---------- */ function formatChatDate(ts) { try { return new Intl.DateTimeFormat("zh-CN", { year: "numeric", month: "2-digit", day: "2-digit", }).format(new Date(ts)); } catch { const d = new Date(ts); const y = d.getFullYear(); const m = String(d.getMonth() + 1).padStart(2, "0"); const day = String(d.getDate()).padStart(2, "0"); return `${y}-${m}-${day}`; } } function formatMsgDateTime(ts) { try { return new Intl.DateTimeFormat("zh-CN", { year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit", }).format(new Date(ts)); } catch { const d = new Date(ts); const y = d.getFullYear(); const m = String(d.getMonth() + 1).padStart(2, "0"); const day = String(d.getDate()).padStart(2, "0"); const hh = String(d.getHours()).padStart(2, "0"); const mm = String(d.getMinutes()).padStart(2, "0"); const ss = String(d.getSeconds()).padStart(2, "0"); return `${y}-${m}-${day} ${hh}:${mm}:${ss}`; } } /** ---------- 兼容旧数据:补齐 createdAt/updatedAt/ts ---------- */ function normalizeData() { const now = Date.now(); for (const id of Object.keys(chats)) { const chat = chats[id] || {}; if (!chat.title) chat.title = "New Chat"; if (!Array.isArray(chat.messages)) chat.messages = []; if (!chat.createdAt) { const first = chat.messages[0]; chat.createdAt = first?.ts || now; } if (!chat.updatedAt) { const last = chat.messages[chat.messages.length - 1]; chat.updatedAt = last?.ts || chat.createdAt; } for (const m of chat.messages) { if (!m.ts) m.ts = chat.createdAt; } chats[id] = chat; } } normalizeData(); /** ---------- 保存 ---------- */ function save() { localStorage.setItem("ds_chats", JSON.stringify(chats)); localStorage.setItem("ds_current_chat", currentChatId || ""); localStorage.setItem("ds_sidebar_hidden", sidebarHidden ? "1" : "0"); } /** ---------- 侧栏显示/隐藏 ---------- */ function applySidebarState() { if (!appRootEl) return; appRootEl.classList.toggle("sidebar-hidden", sidebarHidden); } applySidebarState(); if (sidebarToggleBtn) { sidebarToggleBtn.onclick = () => { sidebarHidden = !sidebarHidden; applySidebarState(); save(); }; } /** ---------- Chat 操作 ---------- */ function newChat() { const now = Date.now(); currentChatId = crypto.randomUUID(); chats[currentChatId] = { title: "New Chat", createdAt: now, updatedAt: now, messages: [], }; save(); renderChatList(); renderMessages(); } function deleteChat(id) { if (!id || !chats[id]) return; const title = chats[id].title || "This chat"; const ok = confirm(`Delete "${title}" ?`); if (!ok) return; delete chats[id]; // ✅ 关键:允许删除最后一个。删完后不自动 newChat() if (currentChatId === id) { const remainingIds = Object.keys(chats); currentChatId = remainingIds[0] || null; } save(); renderChatList(); renderMessages(); } /** ---------- 渲染左侧列表(显示创建日期 + 删除按钮 + 按更新时间排序)---------- */ function renderChatList() { chatListEl.innerHTML = ""; const entries = Object.entries(chats); entries.sort((a, b) => (b[1].updatedAt || 0) - (a[1].updatedAt || 0)); // 如果没有任何 chat,列表保持空(不用提示,提示放在右侧 messages) if (entries.length === 0) return; for (const [id, chat] of entries) { const li = document.createElement("li"); li.className = "chat-item"; if (id === currentChatId) li.classList.add("active"); const left = document.createElement("div"); left.className = "chat-item-left"; const title = document.createElement("div"); title.className = "chat-title"; title.textContent = chat.title || "New Chat"; const date = document.createElement("div"); date.className = "chat-date"; date.textContent = formatChatDate(chat.createdAt || Date.now()); left.appendChild(title); left.appendChild(date); const del = document.createElement("button"); del.className = "chat-del"; del.type = "button"; del.title = "Delete"; del.textContent = "🗑"; del.onclick = (e) => { e.stopPropagation(); deleteChat(id); }; li.appendChild(left); li.appendChild(del); li.onclick = () => { currentChatId = id; save(); renderChatList(); renderMessages(); }; chatListEl.appendChild(li); } } /** ---------- 空状态 UI ---------- */ function renderEmptyState(kind) { // kind: "no-chat" | "no-messages" const div = document.createElement("div"); div.className = "empty-state"; if (kind === "no-chat") { div.innerHTML = `
+ 创建新会话☰Enter 发送;Shift+Enter 换行。