| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283 |
- <script lang="ts">
- import { getContext } from 'svelte';
- import Icon from '../icon/Icon.svelte';
- import Page from './Page.svelte';
- import SecondPageNext from './SecondPageNext.svelte';
- import SecondPagePre from './SecondPagePre.svelte';
- import { zh_CN, type LangProps } from '../../lang';
- import type { PaginationProps } from '../../types';
- // 当前语言
- // current language
- const currentLang: LangProps = getContext('STDF_lang') || zh_CN;
- const commonLang: LangProps['common'] = currentLang.common;
- const paginationLang: LangProps['pagination'] = currentLang.pagination;
- let {
- total = 0,
- pageSize = 10,
- current = $bindable(1),
- maxShowPage = 7,
- radius = 'md',
- type = 'bold',
- pageCol = 3,
- showNextOmitPage = $bindable(false),
- showPreOmitPage = $bindable(false),
- injClass = '',
- noDataText = commonLang.noData,
- onePageText = paginationLang.defaultOnlyOnePage,
- continuous = false,
- onchange,
- onnext,
- onpre,
- }: PaginationProps = $props();
- // 总页数
- // totalPage
- let totalPage = $derived(Math.ceil(total / pageSize));
- // 当前页码大于等于 maxShowPage-3 时,不显示前面的省略号
- // current >= maxShowPage-3, not show pre ellipsis
- let showPreEllipsis = $derived(current > maxShowPage - 2);
- // 当前页码小于等于 totalPage - (maxShowPage-3) 时,不显示后面的省略号
- // current <= totalPage - (maxShowPage-3), not show next ellipsis
- let showNextEllipsis = $derived(current <= maxShowPage - 2 || current <= totalPage - (maxShowPage - 3));
- // 当显示前面的省略号时,中间显示的页码数 middleShowPage 个数为 maxShowPage - 4,内容为当前页码(maxShowPage为5)或者当前页码和前后一项(maxShowPage为7)或者当前页码和前后两项(maxShowPage为9)
- // when show pre ellipsis, middleShowPage length is maxShowPage - 4, content is current page (maxShowPage is 5) or current page and pre/next one (maxShowPage is 7) or current page and pre/next two (maxShowPage is 9)
- let middleShowPage = $state([]);
- // 前省略号内页码数组
- // pre ellipsis page array
- let preEllipsisPages = $state([]);
- // 后省略号内页码数组
- // next ellipsis page array
- let nextEllipsisPages = $state([]);
- $effect(() => {
- // 当页码变化时对一系列数据动态计算
- // Dynamic calculation of a series of data when the page number changes
- if (showPreEllipsis && showNextEllipsis) {
- if (maxShowPage === 5) {
- middleShowPage = [current];
- } else if (maxShowPage === 7) {
- middleShowPage = [current - 1, current, current + 1];
- } else if (maxShowPage === 9) {
- middleShowPage = [current - 2, current - 1, current, current + 1, current + 2];
- } else if (maxShowPage === 11) {
- middleShowPage = [current - 3, current - 2, current - 1, current, current + 1, current + 2, current + 3];
- }
- } else {
- middleShowPage = [];
- }
- });
- $effect(() => {
- // 当仅显示后省略号时
- // when only show next ellipsis
- if (!showPreEllipsis && showNextEllipsis) {
- // 此时 nextEllipsisPages 为 maxShowPage - 2 到 总页码数 - 1
- // nextEllipsisPages is maxShowPage - 2 to total page - 1
- nextEllipsisPages = Array.from({ length: totalPage }, (v, k) => k + 1).slice(maxShowPage - 2, totalPage - 1);
- }
- });
- $effect(() => {
- // 当仅显示前省略号时
- // when only show pre ellipsis
- if (showPreEllipsis && !showNextEllipsis) {
- // 此时 preEllipsisPages 为 2 到 总页码数 - (maxShowPage-2)
- // preEllipsisPages is 2 to total page - (maxShowPage-2)
- preEllipsisPages = Array.from({ length: totalPage }, (v, k) => k + 1).slice(1, totalPage - (maxShowPage - 2));
- }
- });
- $effect(() => {
- // 当显示前后省略号时
- // when show pre and next ellipsis
- if (showPreEllipsis && showNextEllipsis) {
- // 此时 nextEllipsisPages 为 middleShowPage 最后一项 +1 ,到总页码数组的最后第二项
- // nextEllipsisPages is middleShowPage last item +1, to total page array last second item
- nextEllipsisPages = Array.from({ length: totalPage }, (v, k) => k + 1).slice(
- middleShowPage[middleShowPage.length - 1],
- totalPage - 1,
- );
- // 此时 preEllipsisPages 为 2 到 middleShowPage 第一项 -1
- // preEllipsisPages is 2 to middleShowPage first item -1
- preEllipsisPages = Array.from({ length: totalPage }, (v, k) => k + 1).slice(1, middleShowPage[0] - 1);
- }
- });
- $effect(() => {
- // 特殊情况处理
- // Special case handling
- if (totalPage <= maxShowPage) {
- showNextOmitPage = false;
- }
- });
- // 点击后省略号事件
- // click next ellipsis event
- const clickNextEllipsisFunc = () => {
- if (nextEllipsisPages.length > 0) {
- showNextOmitPage = !showNextOmitPage;
- }
- };
- // 点击前省略号事件
- // click pre ellipsis event
- const clickPreEllipsisFunc = () => {
- if (preEllipsisPages.length > 0) {
- showPreOmitPage = !showPreOmitPage;
- }
- };
- // 页码改变的回调,参数是改变后的页码及每页条数
- // onChange
- const onChangeFn = () => {
- showNextOmitPage = false;
- showPreOmitPage = false;
- onchange && onchange(current);
- };
- // 点击下一页
- // click next page
- const nextFunc = () => {
- if (current < totalPage) {
- current++;
- onnext && onnext(current);
- onChangeFn();
- }
- };
- // 点击上一页
- // click pre page
- const preFunc = () => {
- if (current > 1) {
- current--;
- onpre && onpre(current);
- onChangeFn();
- }
- };
- // 点击页码
- // click page
- const clickItemFunc = index => {
- current = index;
- onChangeFn();
- };
- // 点击省略页码事件
- // click second page item event
- const clickSecondPageItemFunc = index => {
- current = index;
- showNextOmitPage = false;
- showPreOmitPage = false;
- onChangeFn();
- };
- // 类型样式
- // type class
- const typeClass = {
- border: 'border-primary dark:border-dark text-primary dark:text-dark',
- block: 'bg-primary text-white dark:bg-dark dark:text-black',
- bold: 'font-bold text-primary dark:text-dark border-transparent',
- };
- // 圆角样式
- // radius class
- const radiusClass = { base: 'rounded', md: 'rounded-md', lg: 'rounded-lg', xl: 'rounded-xl', full: 'rounded-full', none: 'rounded-none' };
- </script>
- <div class="py-1 bg-white dark:bg-black flex justify-between text-center text-sm relative {injClass}">
- <button
- class="flex-1 py-2 border border-transparent transition-all {current > 1
- ? 'text-primary dark:text-dark'
- : 'text-primary/30 dark:text-dark/30'} {radiusClass[radius] || radiusClass.base} active:scale-75"
- onclick={preFunc}
- >
- <Icon name="ri-arrow-left-s-line" size={18} />
- </button>
- {#if totalPage === 0}
- <div class="flex-1 py-2 border border-transparent">{noDataText}</div>
- {:else if totalPage === 1}
- <div class="flex-1 py-2 border border-transparent">{onePageText}</div>
- {:else if totalPage > 1 && totalPage <= maxShowPage}
- {#each new Array(totalPage) as item, index}
- <Page active={current === index + 1} {type} {radius} onclick={() => !continuous && clickItemFunc(index + 1)}>
- {index + 1}
- </Page>
- {/each}
- {:else}
- <Page active={current === 1} {type} {radius} onclick={() => !continuous && clickItemFunc(1)}>1</Page>
- {#if showPreEllipsis}
- <button
- class="flex-1 py-2 border {showPreOmitPage
- ? typeClass[type] || typeClass.border
- : 'border-transparent' + (type === 'bold' ? ' opacity-50' : '')} {radiusClass[radius] || radiusClass.base}"
- onclick={!continuous && clickPreEllipsisFunc}
- >
- {#if type === 'bold' && showPreOmitPage}
- <Icon name="ri-more-fill" size={18} />
- {:else}
- <Icon name="ri-more-line" size={18} />
- {/if}
- </button>
- {/if}
- {#if !showPreEllipsis && current <= maxShowPage - 1}
- {#each new Array(maxShowPage - 3) as item, index}
- <Page active={current === index + 2} {type} {radius} onclick={() => !continuous && clickItemFunc(index + 2)}>
- {index + 2}
- </Page>
- {/each}
- {/if}
- {#if middleShowPage.length > 0}
- {#each middleShowPage as item, index}
- <Page active={index === (middleShowPage.length - 1) / 2} {type} {radius} onclick={() => !continuous && clickItemFunc(item)}>
- {item}
- </Page>
- {/each}
- {/if}
- {#if !showNextEllipsis && current > totalPage - (maxShowPage - 3)}
- {#each new Array(maxShowPage - 3) as item, index}
- <Page
- active={current === totalPage + index + 3 - maxShowPage}
- {type}
- {radius}
- onclick={() => !continuous && clickItemFunc(totalPage + index + 3 - maxShowPage)}
- >
- {totalPage + index + 3 - maxShowPage}
- </Page>
- {/each}
- {/if}
- {#if showNextEllipsis}
- <button
- class="flex-1 py-2 border {showNextOmitPage
- ? typeClass[type] || typeClass.border
- : 'border-transparent' + (type === 'bold' ? ' opacity-50' : '')} {radiusClass[radius] || radiusClass.base}"
- onclick={!continuous && clickNextEllipsisFunc}
- >
- {#if type === 'bold' && showNextOmitPage}
- <Icon name="ri-more-fill" size={18} />
- {:else}
- <Icon name="ri-more-line" size={18} />
- {/if}
- </button>
- {/if}
- <Page active={current === totalPage} {type} {radius} onclick={() => !continuous && clickItemFunc(totalPage)}>{totalPage}</Page>
- {/if}
- <button
- class="flex-1 py-2 border border-transparent transition-all {current < totalPage
- ? 'text-primary dark:text-dark'
- : 'text-primary/30 dark:text-dark/30'} {radiusClass[radius] || radiusClass.base} active:scale-75"
- onclick={nextFunc}
- >
- <Icon name="ri-arrow-right-s-line" size={20} />
- </button>
- {#if showNextOmitPage}
- <SecondPageNext {pageCol} Pages={nextEllipsisPages} {type} {radius} onclickItem={clickSecondPageItemFunc} {maxShowPage} />
- {/if}
- {#if showPreOmitPage}
- <SecondPagePre {pageCol} Pages={preEllipsisPages} {type} {radius} onclickItem={clickSecondPageItemFunc} {maxShowPage} />
- {/if}
- </div>
|