QALoop / qa_annotate /static /js /pagination.js
jackkuo's picture
Add Hugging Face Space deployment
35e7795
Raw
History Blame Contribute Delete
9.04 kB
/**
* 通用分页模块
* 提供分页状态管理和UI渲染功能
*/
class Paginator {
/**
* 创建分页器实例
* @param {string} prefix - 分页控件的前缀ID (例如: 'users', 'datasets')
* @param {Object} options - 配置选项
* @param {number} options.initialPage - 初始页码,默认1
* @param {number} options.initialPageSize - 初始每页数量,默认20
* @param {Function} options.onPageChange - 页码改变时的回调函数
* @param {Function} options.onPageSizeChange - 每页数量改变时的回调函数
*/
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 || (() => {});
// 绑定DOM元素
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));
});
}
}
/**
* 设置当前页码
* @param {number} page - 页码
*/
setPage(page) {
const totalPages = this.getTotalPages();
if (page >= 1 && page <= totalPages) {
this.currentPage = page;
this.render();
this.onPageChange(this.currentPage, this.pageSize);
}
}
/**
* 设置每页数量
* @param {number} pageSize - 每页数量
*/
setPageSize(pageSize) {
this.pageSize = pageSize;
this.currentPage = 1; // 重置到第一页
this.render();
this.onPageSizeChange(this.pageSize);
}
/**
* 设置总数
* @param {number} totalCount - 总记录数
*/
setTotalCount(totalCount) {
this.totalCount = totalCount;
this.render();
}
/**
* 获取总页数
* @returns {number}
*/
getTotalPages() {
return Math.ceil(this.totalCount / this.pageSize);
}
/**
* 获取跳过的记录数 (用于API请求的skip参数)
* @returns {number}
*/
getSkip() {
return (this.currentPage - 1) * this.pageSize;
}
/**
* 获取限制数量 (用于API请求的limit参数)
* @returns {number}
*/
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);
}
}
/**
* 跳转到指定页
* @param {number} page - 页码
*/
goToPage(page) {
this.setPage(page);
}
/**
* 渲染分页UI
*/
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);
}
}
/**
* 渲染页码按钮
* @param {number} 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);
}
}
/**
* 创建页码按钮
* @param {number} page - 页码
* @param {boolean} isActive - 是否为当前页
* @returns {HTMLElement}
*/
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;
}
/**
* 检查删除后是否需要调整页码
* 如果当前页没有数据了,自动回到上一页
* @param {number} deletedCount - 删除的项目数量,默认为1
*/
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();
}
}
/**
* 创建分页器实例的便捷函数
* @param {string} prefix - 分页控件的前缀ID
* @param {Object} options - 配置选项
* @returns {Paginator}
*/
function createPaginator(prefix, options = {}) {
return new Paginator(prefix, options);
}