const FIRST_BUTTON_CLASS = 'erp-pagination-first'; const LAST_BUTTON_CLASS = 'erp-pagination-last'; const JUMP_BUTTON_CLASS = 'erp-pagination-jump'; const DEFAULT_PAGE_SIZE = 10; const DEFAULT_PAGE_SIZES = [10, 20, 50, 100]; const PAGE_KEY_PATTERN = /(^page$|Page$|^page[A-Z])/; const toNumber = value => { const number = Number(value); return Number.isFinite(number) ? number : 0; }; const getNativeInputValueSetter = input => { const prototype = Object.getPrototypeOf(input); const descriptor = Object.getOwnPropertyDescriptor(prototype, 'value'); return descriptor && descriptor.set; }; const setInputValue = (input, value) => { const setter = getNativeInputValueSetter(input); if (setter) { setter.call(input, value); } else { input.value = value; } input.dispatchEvent(new Event('input', { bubbles: true })); }; const getPaginationState = pagination => { const active = pagination.querySelector('.el-pager li.is-active'); const jumpInput = pagination.querySelector('.el-pagination__editor input'); const currentPage = toNumber( active && active.textContent ? active.textContent.trim() : jumpInput?.value ); const pageCount = toNumber(jumpInput?.getAttribute('max')); return { currentPage: currentPage || 1, pageCount: pageCount || 1, jumpInput, }; }; const changePage = (pagination, page) => { const { currentPage, pageCount, jumpInput } = getPaginationState(pagination); const targetPage = Math.min(Math.max(toNumber(page), 1), pageCount); if (!targetPage || targetPage === currentPage) return; const targetPager = Array.from(pagination.querySelectorAll('.el-pager li.number')).find( item => toNumber(item.textContent && item.textContent.trim()) === targetPage ); if (targetPager) { targetPager.click(); return; } if (jumpInput) { setInputValue(jumpInput, targetPage); jumpInput.dispatchEvent(new Event('change', { bubbles: true })); jumpInput.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true })); } }; const createPaginationButton = (className, text, onClick) => { const button = document.createElement('button'); button.type = 'button'; button.className = `erp-pagination-button ${className}`; button.textContent = text; button.addEventListener('click', onClick); return button; }; const setButtonDisabled = (button, disabled) => { if (!button || button.disabled === disabled) return; button.disabled = disabled; }; const isPageConfig = value => value && typeof value === 'object' && ('pageSize' in value || 'currentPage' in value || 'total' in value); const normalizePageConfig = page => { if (!isPageConfig(page)) return; page.pageSize = DEFAULT_PAGE_SIZES.includes(toNumber(page.pageSize)) ? toNumber(page.pageSize) : DEFAULT_PAGE_SIZE; page.pageSizes = DEFAULT_PAGE_SIZES; }; const normalizeComponentPageConfigs = pagination => { let component = pagination.__vueParentComponent; while (component) { [component.data, component.setupState].forEach(state => { if (!state) return; Object.keys(state) .filter(key => PAGE_KEY_PATTERN.test(key)) .forEach(key => normalizePageConfig(state[key])); }); component = component.parent; } }; const updatePaginationButtons = pagination => { const { currentPage, pageCount, jumpInput } = getPaginationState(pagination); const firstButton = pagination.querySelector(`.${FIRST_BUTTON_CLASS}`); const lastButton = pagination.querySelector(`.${LAST_BUTTON_CLASS}`); const jumpButton = pagination.querySelector(`.${JUMP_BUTTON_CLASS}`); setButtonDisabled(firstButton, currentPage <= 1); setButtonDisabled(lastButton, currentPage >= pageCount); setButtonDisabled(jumpButton, !jumpInput || jumpInput.disabled); }; const enhancePagination = pagination => { const prevButton = pagination.querySelector('.btn-prev'); const nextButton = pagination.querySelector('.btn-next'); const jumpWrapper = pagination.querySelector('.el-pagination__jump'); normalizeComponentPageConfigs(pagination); if (prevButton && !pagination.querySelector(`.${FIRST_BUTTON_CLASS}`)) { const firstButton = createPaginationButton(FIRST_BUTTON_CLASS, '首页', () => { changePage(pagination, 1); }); prevButton.before(firstButton); } if (nextButton && !pagination.querySelector(`.${LAST_BUTTON_CLASS}`)) { const lastButton = createPaginationButton(LAST_BUTTON_CLASS, '尾页', () => { const { pageCount } = getPaginationState(pagination); changePage(pagination, pageCount); }); nextButton.after(lastButton); } if (jumpWrapper && !pagination.querySelector(`.${JUMP_BUTTON_CLASS}`)) { const jumpButton = createPaginationButton(JUMP_BUTTON_CLASS, '跳转', () => { const { jumpInput } = getPaginationState(pagination); if (!jumpInput) return; changePage(pagination, jumpInput.value); }); jumpWrapper.after(jumpButton); } updatePaginationButtons(pagination); }; const enhanceAllPaginations = () => { document.querySelectorAll('.el-pagination').forEach(enhancePagination); }; export const setupPaginationEnhancer = () => { if (typeof window === 'undefined' || typeof document === 'undefined') return; const scheduleEnhance = () => { window.requestAnimationFrame(enhanceAllPaginations); }; scheduleEnhance(); const observer = new MutationObserver(scheduleEnhance); observer.observe(document.body, { attributes: true, attributeFilter: ['class', 'disabled'], childList: true, subtree: true, }); };