| ---
|
| import type { Page } from "astro";
|
| import { Icon } from "astro-icon/components";
|
| import I18nKey from "@/i18n/i18nKey";
|
| import { i18n } from "@/i18n/translation";
|
| import { url } from "@/utils/url-utils";
|
|
|
| interface Props {
|
| page: Page;
|
| class?: string;
|
| style?: string;
|
| }
|
|
|
| const { page, style } = Astro.props;
|
|
|
| const HIDDEN = -1;
|
|
|
| const className = Astro.props.class;
|
|
|
| const ADJ_DIST = 2;
|
| const VISIBLE = ADJ_DIST * 2 + 1;
|
|
|
|
|
| let count = 1;
|
| let l = page.currentPage;
|
| let r = page.currentPage;
|
| while (0 < l - 1 && r + 1 <= page.lastPage && count + 2 <= VISIBLE) {
|
| count += 2;
|
| l--;
|
| r++;
|
| }
|
| while (0 < l - 1 && count < VISIBLE) {
|
| count++;
|
| l--;
|
| }
|
| while (r + 1 <= page.lastPage && count < VISIBLE) {
|
| count++;
|
| r++;
|
| }
|
|
|
| let pages: number[] = [];
|
| if (l > 1) pages.push(1);
|
| if (l === 3) pages.push(2);
|
| if (l > 3) pages.push(HIDDEN);
|
| for (let i = l; i <= r; i++) pages.push(i);
|
| if (r < page.lastPage - 2) pages.push(HIDDEN);
|
| if (r === page.lastPage - 2) pages.push(page.lastPage - 1);
|
| if (r < page.lastPage) pages.push(page.lastPage);
|
|
|
| const getPageUrl = (p: number) => {
|
| if (p === 1) return "/";
|
| return `/${p}/`;
|
| };
|
| ---
|
|
|
| <div class:list={[className, "flex flex-col gap-4 items-center"]} style={style}>
|
| <!-- 分页信息 - 已禁用 -->
|
| <!--
|
| {
|
| page.lastPage > 1 && (
|
| <div class="text-sm text-(--text-secondary) text-center">
|
| 第 {page.currentPage} 页,共 {page.lastPage} 页
|
| </div>
|
| )
|
| }
|
| -->
|
|
|
| <!-- 分页控件 -->
|
| <div class="flex flex-row gap-3 justify-center" role="navigation" aria-label={i18n(I18nKey.postList)}>
|
| <a
|
| href={page.url.prev || "#"}
|
| aria-label={i18n(I18nKey.paginationPrev)}
|
| aria-disabled={page.url.prev === undefined ? "true" : "false"}
|
| tabindex={page.url.prev === undefined ? "-1" : "0"}
|
| class:list={[
|
| "btn-card overflow-hidden rounded-lg text-(--primary) w-11 h-11",
|
| { disabled: page.url.prev == undefined },
|
| ]}
|
| >
|
| <Icon
|
| name="material-symbols:chevron-left-rounded"
|
| class="text-[1.75rem]"
|
| aria-hidden="true"
|
| />
|
| </a>
|
| <div
|
| class="bg-(--card-bg) flex flex-row rounded-lg items-center text-neutral-700 dark:text-neutral-300 font-bold"
|
| >
|
| {
|
| pages.map((p) => {
|
| if (p == HIDDEN)
|
| return <Icon name="material-symbols:more-horiz" class="mx-1" aria-hidden="true" />;
|
| if (p == page.currentPage)
|
| return (
|
| <div
|
| class="h-11 w-11 rounded-lg bg-(--primary) flex items-center justify-center
|
| font-bold text-white dark:text-black/70"
|
| aria-current="page"
|
| >
|
| {p}
|
| </div>
|
| );
|
| return (
|
| <a
|
| href={url(getPageUrl(p))}
|
| aria-label={`${i18n(I18nKey.paginationPage)} ${p}`}
|
| class="btn-card w-11 h-11 rounded-lg overflow-hidden active:scale-[0.85]"
|
| >
|
| {p}
|
| </a>
|
| );
|
| })
|
| }
|
| </div>
|
| <a
|
| href={page.url.next || "#"}
|
| aria-label={i18n(I18nKey.paginationNext)}
|
| aria-disabled={page.url.next === undefined ? "true" : "false"}
|
| tabindex={page.url.next === undefined ? "-1" : "0"}
|
| class:list={[
|
| "btn-card overflow-hidden rounded-lg text-(--primary) w-11 h-11",
|
| { disabled: page.url.next == undefined },
|
| ]}
|
| >
|
| <Icon
|
| name="material-symbols:chevron-right-rounded"
|
| class="text-[1.75rem]"
|
| aria-hidden="true"
|
| />
|
| </a>
|
| </div>
|
| </div>
|
|
|