| |
| |
| |
| |
|
|
| class Paginator { |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| constructor(prefix, options = {}) { |
| this.prefix = prefix; |
| this.currentPage = options.initialPage || 1; |
| this.pageSize = options.initialPageSize || 20; |
| this.totalCount = 0; |
| this.onPageChange = options.onPageChange || (() => {}); |
| this.onPageSizeChange = options.onPageSizeChange || (() => {}); |
|
|
| |
| this.container = document.getElementById(`${prefix}PaginationContainer`); |
| this.info = document.getElementById(`${prefix}PaginationInfo`); |
| this.pageNumbers = document.getElementById(`${prefix}PageNumbers`); |
| this.prevBtn = document.getElementById(`${prefix}PrevPage`); |
| this.nextBtn = document.getElementById(`${prefix}NextPage`); |
| this.pageSizeSelect = document.getElementById(`${prefix}PageSize`); |
|
|
| |
| this.initEventListeners(); |
| } |
|
|
| |
| |
| |
| initEventListeners() { |
| if (this.prevBtn) { |
| this.prevBtn.addEventListener('click', () => { |
| this.goToPreviousPage(); |
| }); |
| } |
|
|
| if (this.nextBtn) { |
| this.nextBtn.addEventListener('click', () => { |
| this.goToNextPage(); |
| }); |
| } |
|
|
| if (this.pageSizeSelect) { |
| this.pageSizeSelect.addEventListener('change', (e) => { |
| this.setPageSize(parseInt(e.target.value)); |
| }); |
| } |
| } |
|
|
| |
| |
| |
| |
| setPage(page) { |
| const totalPages = this.getTotalPages(); |
| if (page >= 1 && page <= totalPages) { |
| this.currentPage = page; |
| this.render(); |
| this.onPageChange(this.currentPage, this.pageSize); |
| } |
| } |
|
|
| |
| |
| |
| |
| setPageSize(pageSize) { |
| this.pageSize = pageSize; |
| this.currentPage = 1; |
| this.render(); |
| this.onPageSizeChange(this.pageSize); |
| } |
|
|
| |
| |
| |
| |
| setTotalCount(totalCount) { |
| this.totalCount = totalCount; |
| this.render(); |
| } |
|
|
| |
| |
| |
| |
| getTotalPages() { |
| return Math.ceil(this.totalCount / this.pageSize); |
| } |
|
|
| |
| |
| |
| |
| getSkip() { |
| return (this.currentPage - 1) * this.pageSize; |
| } |
|
|
| |
| |
| |
| |
| getLimit() { |
| return this.pageSize; |
| } |
|
|
| |
| |
| |
| reset() { |
| this.currentPage = 1; |
| this.render(); |
| } |
|
|
| |
| |
| |
| goToPreviousPage() { |
| if (this.currentPage > 1) { |
| this.setPage(this.currentPage - 1); |
| } |
| } |
|
|
| |
| |
| |
| goToNextPage() { |
| const totalPages = this.getTotalPages(); |
| if (this.currentPage < totalPages) { |
| this.setPage(this.currentPage + 1); |
| } |
| } |
|
|
| |
| |
| |
| |
| goToPage(page) { |
| this.setPage(page); |
| } |
|
|
| |
| |
| |
| render() { |
| if (!this.container || !this.info) { |
| return; |
| } |
|
|
| if (this.totalCount === 0) { |
| this.container.style.display = 'none'; |
| return; |
| } |
|
|
| this.container.style.display = 'flex'; |
| this.container.style.flexDirection = 'row'; |
|
|
| const totalPages = this.getTotalPages(); |
| const startIndex = (this.currentPage - 1) * this.pageSize + 1; |
| const endIndex = Math.min(this.currentPage * this.pageSize, this.totalCount); |
|
|
| |
| if (this.info) { |
| const text = window.t ? window.t('pagination.info', { |
| total: this.totalCount, |
| start: startIndex, |
| end: endIndex |
| }) : `共 ${this.totalCount} 条,显示第 ${startIndex}-${endIndex} 条`; |
| this.info.textContent = text; |
| } |
|
|
| |
| if (this.prevBtn) { |
| this.prevBtn.disabled = this.currentPage <= 1; |
| if (this.prevBtn.disabled) { |
| this.prevBtn.style.opacity = '0.5'; |
| this.prevBtn.style.cursor = 'not-allowed'; |
| } else { |
| this.prevBtn.style.opacity = '1'; |
| this.prevBtn.style.cursor = 'pointer'; |
| } |
| } |
|
|
| if (this.nextBtn) { |
| this.nextBtn.disabled = this.currentPage >= totalPages; |
| if (this.nextBtn.disabled) { |
| this.nextBtn.style.opacity = '0.5'; |
| this.nextBtn.style.cursor = 'not-allowed'; |
| } else { |
| this.nextBtn.style.opacity = '1'; |
| this.nextBtn.style.cursor = 'pointer'; |
| } |
| } |
|
|
| |
| if (this.pageNumbers) { |
| this.renderPageNumbers(totalPages); |
| } |
| } |
|
|
| |
| |
| |
| |
| renderPageNumbers(totalPages) { |
| this.pageNumbers.innerHTML = ''; |
| const maxVisiblePages = 7; |
| let startPage = Math.max(1, this.currentPage - Math.floor(maxVisiblePages / 2)); |
| let endPage = Math.min(totalPages, startPage + maxVisiblePages - 1); |
|
|
| if (endPage - startPage < maxVisiblePages - 1) { |
| startPage = Math.max(1, endPage - maxVisiblePages + 1); |
| } |
|
|
| |
| if (startPage > 1) { |
| const btn = this.createPageButton(1); |
| this.pageNumbers.appendChild(btn); |
|
|
| if (startPage > 2) { |
| const ellipsis = document.createElement('span'); |
| ellipsis.textContent = '...'; |
| ellipsis.style.cssText = 'padding: 6px 4px; color: #666;'; |
| this.pageNumbers.appendChild(ellipsis); |
| } |
| } |
|
|
| |
| for (let i = startPage; i <= endPage; i++) { |
| const btn = this.createPageButton(i, i === this.currentPage); |
| this.pageNumbers.appendChild(btn); |
| } |
|
|
| |
| if (endPage < totalPages) { |
| if (endPage < totalPages - 1) { |
| const ellipsis = document.createElement('span'); |
| ellipsis.textContent = '...'; |
| ellipsis.style.cssText = 'padding: 6px 4px; color: #666;'; |
| this.pageNumbers.appendChild(ellipsis); |
| } |
|
|
| const btn = this.createPageButton(totalPages); |
| this.pageNumbers.appendChild(btn); |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| createPageButton(page, isActive = false) { |
| const btn = document.createElement('button'); |
| btn.className = 'btn btn-sm'; |
| btn.style.cssText = 'padding: 6px 12px; min-width: 36px;'; |
| btn.textContent = page.toString(); |
|
|
| if (isActive) { |
| btn.classList.add('btn-primary'); |
| } else { |
| btn.classList.add('btn-secondary'); |
| btn.addEventListener('click', () => { |
| this.goToPage(page); |
| }); |
| } |
|
|
| return btn; |
| } |
|
|
| |
| |
| |
| |
| |
| adjustPageAfterDelete(deletedCount = 1) { |
| |
| this.totalCount = Math.max(0, this.totalCount - deletedCount); |
|
|
| |
| if (this.currentPage > 1 && (this.currentPage - 1) * this.pageSize >= this.totalCount) { |
| this.currentPage--; |
| } |
|
|
| this.render(); |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| function createPaginator(prefix, options = {}) { |
| return new Paginator(prefix, options); |
| } |
|
|