diff --git a/www/app.js b/www/app.js index 143aae4..8a01ed6 100644 --- a/www/app.js +++ b/www/app.js @@ -115,6 +115,36 @@ function showConversationList() { + + + + + + + + `; + 置顶 + +
+ + 删除 +
+ + `; @@ -126,6 +156,71 @@ function showConversationList() { newChatBtn.addEventListener('click', createNewConversation); } + // 搜索功能 + const searchToggleBtn = document.getElementById('searchToggleBtn'); + const searchBar = document.getElementById('searchBar'); + const searchInput = document.getElementById('searchInput'); + const searchCloseBtn = document.getElementById('searchCloseBtn'); + const searchResults = document.getElementById('searchResults'); + + if (searchToggleBtn) { + searchToggleBtn.addEventListener('click', () => { + if (searchBar) { + searchBar.classList.add('show'); + if (searchInput) { + searchInput.focus(); + } + } + }); + } + + if (searchCloseBtn) { + searchCloseBtn.addEventListener('click', () => { + hideSearchBar(); + }); + } + + if (searchInput) { + searchInput.addEventListener('input', (e) => { + const keyword = e.target.value.trim(); + if (keyword) { + searchConversations(keyword); + } else { + if (searchResults) searchResults.innerHTML = ''; + } + }); + + searchInput.addEventListener('keydown', (e) => { + if (e.key === 'Escape') { + hideSearchBar(); + } + }); + } + + // 点击搜索结果 + if (searchResults) { + searchResults.addEventListener('click', (e) => { + const item = e.target.closest('.search-result-item'); + if (item) { + const id = item.getAttribute('data-id'); + hideSearchBar(); + openConversation(id); + } + }); + } + + function hideSearchBar() { + if (searchBar) { + searchBar.classList.remove('show'); + } + if (searchInput) { + searchInput.value = ''; + } + if (searchResults) { + searchResults.innerHTML = ''; + } + } + const conversationList = document.getElementById('conversationList'); const actionMenu = document.getElementById('actionMenu'); let longPressTimer = null; @@ -224,6 +319,52 @@ function sortConversations() { }); } +// 搜索对话 +function searchConversations(keyword) { + const searchResults = document.getElementById('searchResults'); + if (!searchResults) return; + + keyword = keyword.toLowerCase(); + + // 搜索标题和消息内容 + const results = conversations.filter(conv => { + // 搜索标题 + if (conv.title.toLowerCase().includes(keyword)) return true; + + // 搜索消息内容 + if (conv.messages.some(m => m.content.toLowerCase().includes(keyword))) return true; + + return false; + }); + + if (results.length === 0) { + searchResults.innerHTML = '
未找到相关对话
'; + return; + } + + searchResults.innerHTML = results.map(conv => { + // 找到匹配的消息片段 + let matchSnippet = ''; + const matchedMsg = conv.messages.find(m => m.content.toLowerCase().includes(keyword)); + if (matchedMsg) { + const content = matchedMsg.content; + const idx = content.toLowerCase().indexOf(keyword); + const start = Math.max(0, idx - 30); + const end = Math.min(content.length, idx + keyword.length + 30); + matchSnippet = (start > 0 ? '...' : '') + content.slice(start, end) + (end < content.length ? '...' : ''); + } + + return ` +
+ ${conv.is_pinned ? '📌' : ''} +
${escapeHtml(conv.title)}
+ ${matchSnippet ? `
${escapeHtml(matchSnippet)}
` : ''} +
${conv.messages.length} 条消息 · ${formatTime(conv.updatedAt)}
+
+ `; + }).join(''); +} + // 显示操作菜单 function showActionMenu(convId) { const actionMenu = document.getElementById('actionMenu'); diff --git a/www/index.html b/www/index.html index a8a62d7..57682c1 100644 --- a/www/index.html +++ b/www/index.html @@ -8,12 +8,12 @@ AI助手 - +
- - + + \ No newline at end of file diff --git a/www/style.css b/www/style.css index 2260682..fa958cd 100644 --- a/www/style.css +++ b/www/style.css @@ -261,6 +261,143 @@ body { background: rgba(229, 62, 62, 0.1); } +/* 搜索栏 */ +.search-bar { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0,0,0,0.5); + display: none; + z-index: 1100; +} + +.search-bar.show { + display: flex; + flex-direction: column; +} + +.search-input-wrapper { + display: flex; + align-items: center; + gap: 12px; + padding: 12px 16px; + background: white; + border-bottom: 1px solid var(--border-color); +} + +.search-input-wrapper svg { + color: var(--text-light); +} + +.search-input-wrapper input { + flex: 1; + font-size: 16px; + border: none; + outline: none; + background: transparent; +} + +.search-close-btn { + padding: 8px; + background: transparent; + border: none; + color: var(--text-light); + cursor: pointer; +} + +.search-close-btn:hover { + color: var(--text-color); +} + +.search-results { + flex: 1; + background: white; + overflow-y: auto; + padding: 8px 16px; +} + +.search-empty { + padding: 40px 20px; + text-align: center; + color: var(--text-light); +} + +.search-result-item { + display: flex; + flex-direction: column; + gap: 4px; + padding: 12px 16px; + background: white; + border: 1px solid var(--border-color); + border-radius: 12px; + margin-bottom: 8px; + cursor: pointer; + transition: all 0.2s; +} + +.search-result-item:hover { + border-color: var(--primary); + background: rgba(102, 126, 234, 0.05); +} + +.search-result-item.pinned { + border-color: var(--primary); + background: rgba(102, 126, 234, 0.08); +} + +.search-result-title { + font-size: 16px; + font-weight: 500; + color: var(--text-color); +} + +.search-result-snippet { + font-size: 14px; + color: var(--text-light); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.search-result-meta { + font-size: 12px; + color: var(--text-light); +} + +/* 底部工具栏 */ +.list-footer { + display: flex; + justify-content: center; + padding: 12px 16px; + background: white; + border-top: 1px solid var(--border-color); +} + +.footer-btn { + display: flex; + align-items: center; + gap: 6px; + padding: 10px 20px; + background: white; + border: 1px solid var(--border-color); + border-radius: 20px; + font-size: 14px; + color: var(--text-light); + cursor: pointer; + transition: all 0.2s; +} + +.footer-btn:hover { + border-color: var(--primary); + color: var(--primary); +} + +.footer-btn:active { + background: rgba(102, 126, 234, 0.1); +} + /* ==================== 对话页面 ==================== */ #chatPage {