parent
69de4c5aad
commit
0466ee763f
|
|
@ -0,0 +1,74 @@
|
|||
import { clsn } from "~/utils";
|
||||
|
||||
interface PaginationProps {
|
||||
size: number;
|
||||
total: number;
|
||||
current: number;
|
||||
onClick: (page: number) => void;
|
||||
}
|
||||
|
||||
const genArr = (min: number, max: number) => {
|
||||
const arr = [];
|
||||
|
||||
while (min <= max) {
|
||||
arr.push(min);
|
||||
min++;
|
||||
}
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
const calc = (current: number, total: number, size: number) => {
|
||||
// 总页数
|
||||
const totalPage = Math.ceil(total / size);
|
||||
|
||||
// 左右分隔多少个出现小点点
|
||||
const offset = 1;
|
||||
|
||||
// 中间部分,只展示前后各一个分页数
|
||||
const prefixEnd = current - 1;
|
||||
const suffixStart = current + 1;
|
||||
const suffixEnd = current + offset > totalPage ? totalPage : current + offset;
|
||||
|
||||
const prefixs = current > 1 ? genArr(current - offset > 0 ? current - offset : 1, prefixEnd) : [];
|
||||
const suffixs = current < totalPage ? genArr(suffixStart, suffixEnd) : [];
|
||||
|
||||
const betweens = [
|
||||
...(current > offset + 1 ? [1, "..."] : []),
|
||||
...prefixs,
|
||||
current,
|
||||
...suffixs,
|
||||
...(current > totalPage - (offset + 1) ? [] : ["...", totalPage]),
|
||||
]
|
||||
|
||||
return betweens;
|
||||
}
|
||||
|
||||
function Pagination({ current = 3, total, size, onClick }: PaginationProps) {
|
||||
const arr = calc(current, total, size);
|
||||
|
||||
return (
|
||||
<div>
|
||||
{arr.map((item, index) => {
|
||||
if (typeof item === "string") {
|
||||
return <span className="p-2 mr-2">{item}</span>
|
||||
}
|
||||
|
||||
return (
|
||||
<span
|
||||
key={index}
|
||||
className={clsn(
|
||||
"inline-block w-10 h-10 leading-[2] md:w-14 md:h-14 md:leading-[3] cursor-pointer text-center mr-2 last:mr-0 rounded-xl border-4 border-transparent hover:bg-pink-400 hover:border-b-transparent hover:text-white transition-colors",
|
||||
current === item ? "bg-cyan-200 border-b-cyan-300 text-white font-bold" : "bg-white border-b-cyan-200"
|
||||
)}
|
||||
onClick={() => onClick(item)}
|
||||
>
|
||||
{item}
|
||||
</span>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Pagination;
|
||||
|
|
@ -1,7 +1,9 @@
|
|||
import { Link, useLoaderData } from "@remix-run/react";
|
||||
import { ChangeEvent, useEffect } from "react";
|
||||
import { Link, useLoaderData, useNavigate, useSearchParams } from "@remix-run/react";
|
||||
import { json, LoaderFunctionArgs, type MetaFunction } from "@remix-run/node";
|
||||
import Pagination from "~/components/common/pagination";
|
||||
import { clsn, siteTitle } from "~/utils";
|
||||
import { getFirstImage } from "~/utils/note";
|
||||
import { getFirstImage, years } from "~/utils/note";
|
||||
|
||||
export const meta: MetaFunction = () => {
|
||||
return [
|
||||
|
|
@ -17,11 +19,36 @@ export async function loader({ request }: LoaderFunctionArgs) {
|
|||
|
||||
const note = await fetch(`https://paul.ren/api/note/?page=${page}&year=${year}`).then((res) => res.json()) as API.PageResponse<API.Note.INoteData[]>;
|
||||
|
||||
return json({ note, page });
|
||||
return json({ note, page, year });
|
||||
}
|
||||
|
||||
export default function Note() {
|
||||
const { note } = useLoaderData<typeof loader>();
|
||||
const navigate = useNavigate();
|
||||
const [params, setParams] = useSearchParams();
|
||||
const { note, page, year } = useLoaderData<typeof loader>();
|
||||
|
||||
useEffect(() => {
|
||||
console.log(note);
|
||||
}, []);
|
||||
|
||||
const onChangeYear = (ev: ChangeEvent<HTMLSelectElement>) => {
|
||||
navigate({
|
||||
search: `?year=${ev.target.value}`,
|
||||
});
|
||||
};
|
||||
|
||||
const onChangePage = (value: number) => {
|
||||
const year = params.get("year");
|
||||
const nextParams: Record<string, string> = {
|
||||
page: `${value}`,
|
||||
};
|
||||
|
||||
if (year !== null) {
|
||||
nextParams.year = year;
|
||||
}
|
||||
|
||||
setParams(nextParams);
|
||||
};
|
||||
|
||||
return (
|
||||
<main className="px-2 py-24 max-w-3xl mx-auto">
|
||||
|
|
@ -54,6 +81,18 @@ export default function Note() {
|
|||
);
|
||||
})}
|
||||
</section>
|
||||
<section className="flex gap-4 flex-col-reverse justify-between md:flex-row items-center">
|
||||
<select
|
||||
className="cursor-pointer px-5 py-3 rounded-xl border-4 border-transparent border-b-cyan-200 mr-8"
|
||||
value={year}
|
||||
onChange={onChangeYear}
|
||||
>
|
||||
{years.map((year) => (
|
||||
<option value={year}>{year} 年</option>
|
||||
))}
|
||||
</select>
|
||||
<Pagination current={Number(page)} size={7} total={note.count} onClick={onChangePage} />
|
||||
</section>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,18 @@
|
|||
// 日记年份
|
||||
function getYears(startAt: number) {
|
||||
let years: number[] = [];
|
||||
let currentYear = new Date().getFullYear();
|
||||
|
||||
while (currentYear >= startAt) {
|
||||
years.push(currentYear);
|
||||
currentYear--;
|
||||
}
|
||||
|
||||
return years;
|
||||
}
|
||||
|
||||
export const years = getYears(2018);
|
||||
|
||||
// 获取第一张图片
|
||||
export const getFirstImage = (note: API.Note.INoteData) => {
|
||||
if (note.media && note.media.length > 0) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue