diff --git a/web/static/js/chat.js b/web/static/js/chat.js index d0527938..e989e567 100644 --- a/web/static/js/chat.js +++ b/web/static/js/chat.js @@ -6441,13 +6441,44 @@ let conversationsPagination = { page: 1, pageSize: getConversationsPageSize(), total: 0, - lastRenderedPage: null, - /** 用户翻页方向:-1 上一页,1 下一页;0 表示后台刷新等非导航加载 */ - skipEmptyDirection: 0, - _emptySkipCount: 0, + visibleCount: 0, }; let conversationsSearchQuery = ''; -const CONVERSATIONS_EMPTY_PAGE_SKIP_MAX = 20; +let conversationsPaginationEventsBound = false; + +function getConversationsTotalPages() { + const { total, pageSize } = conversationsPagination; + return Math.max(1, Math.ceil((total || 0) / pageSize) || 1); +} + +function clampConversationsPageToTotal() { + const totalPages = getConversationsTotalPages(); + if (conversationsPagination.page > totalPages) { + conversationsPagination.page = totalPages; + return true; + } + if (conversationsPagination.page < 1) { + conversationsPagination.page = 1; + return true; + } + return false; +} + +function initConversationsPaginationEvents() { + if (conversationsPaginationEventsBound) return; + const el = document.getElementById('conversations-pagination'); + if (!el) return; + conversationsPaginationEventsBound = true; + el.addEventListener('click', (e) => { + const btn = e.target.closest('[data-conv-page]'); + if (!btn || btn.disabled) return; + e.preventDefault(); + const page = parseInt(btn.getAttribute('data-conv-page'), 10); + if (Number.isFinite(page)) { + goConversationsPage(page); + } + }); +} function parseListTotalValue(raw, itemsLength) { if (typeof raw === 'number' && Number.isFinite(raw) && raw >= 0) return raw; @@ -6484,6 +6515,9 @@ function parseConversationsListResponse(data) { async function resolveConversationsListTotal(params, parsed, pageSize, offset) { const serverTotal = parsed.total; + if (!parsed.isLegacyArray && typeof serverTotal === 'number' && Number.isFinite(serverTotal) && serverTotal >= 0) { + return serverTotal; + } if (!parsed.isLegacyArray && serverTotal > offset + parsed.items.length) { return serverTotal; } @@ -6536,59 +6570,24 @@ function getConversationListEmptyHtml() { return '
'; } -function clearConversationsPageNavigationState() { - conversationsPagination.skipEmptyDirection = 0; - conversationsPagination._emptySkipCount = 0; -} - -/** 服务端分页 + 客户端分组过滤可能导致当前页无可见项;仅在用户主动翻页时沿翻页方向跳过空页 */ -function trySkipEmptyFilteredConversationsPage(searchQuery, parsed, pageSize, visibleCount, hasSearchQuery) { - if (hasSearchQuery || visibleCount > 0 || !parsed.items.length) { - return false; - } - const dir = conversationsPagination.skipEmptyDirection; - if (!dir) { - return false; - } - const totalPages = Math.max(1, Math.ceil(conversationsPagination.total / pageSize)); - const skipCount = conversationsPagination._emptySkipCount || 0; - if (skipCount >= CONVERSATIONS_EMPTY_PAGE_SKIP_MAX) { - return false; - } - if (dir < 0 && conversationsPagination.page > 1) { - conversationsPagination.page -= 1; - conversationsPagination._emptySkipCount = skipCount + 1; - loadConversationsWithGroups(searchQuery); - return true; - } - if (dir > 0 && conversationsPagination.page < totalPages) { - conversationsPagination.page += 1; - conversationsPagination._emptySkipCount = skipCount + 1; - loadConversationsWithGroups(searchQuery); - return true; - } - return false; -} - function renderConversationsPagination(visibleCount) { const el = document.getElementById('conversations-pagination'); if (!el) return; const { page, pageSize, total } = conversationsPagination; - conversationsPagination.lastRenderedPage = page; - clearConversationsPageNavigationState(); - const count = typeof visibleCount === 'number' ? visibleCount : (conversationsPagination.visibleCount || 0); - conversationsPagination.visibleCount = count; + if (typeof visibleCount === 'number') { + conversationsPagination.visibleCount = visibleCount; + } - if (count === 0 || total === 0) { + if (!total) { el.innerHTML = ''; el.hidden = true; return; } - const totalPages = Math.max(1, Math.ceil(total / pageSize) || 1); + const totalPages = getConversationsTotalPages(); const navDisabled = totalPages <= 1; el.hidden = false; - const start = (page - 1) * pageSize + 1; + const start = total === 0 ? 0 : (page - 1) * pageSize + 1; const end = Math.min(page * pageSize, total); const tFn = typeof window.t === 'function' ? window.t.bind(window) : null; const infoText = tFn @@ -6600,13 +6599,15 @@ function renderConversationsPagination(visibleCount) { const perPageLabel = tFn ? tFn('chat.paginationPerPage') : 'Per page'; const prevLabel = tFn ? tFn('chat.paginationPrev') : 'Prev'; const nextLabel = tFn ? tFn('chat.paginationNext') : 'Next'; + const prevPage = page - 1; + const nextPage = page + 1; el.innerHTML = `