Files
SortMeow/frontend/src/components/Pagination.tsx
T
2026-07-14 16:12:29 +08:00

214 lines
7.3 KiB
TypeScript

import { useState, useEffect } from 'preact/hooks'
interface IPagination {
total: number
onChange: (page: number) => void
page: number
pagesize: number
}
const Pagination = ({
total,
onChange,
page,
pagesize,
}: IPagination) => {
const [value, setValue] = useState<string>('1')
const [num, setNum] = useState<number>(1)
const [seqNums, setSeqNums] = useState<[number, number][]>([])
useEffect(() => {
setValue('1')
setNum(1)
}, [])
useEffect(() => {
if (page) {
setValue(page.toString());
let nums: [number, number][] = []
for (let i = 1; i < total / pagesize + 1; i++) {
if (i === 1) {
nums.push([1, 1])
} else {
nums.push([i, 0])
}
}
setSeqNums(nums)
calSeqNums(nums, page)
}
}, [total, page])
const handleChange = (e: Event) => {
const target = e.target as HTMLInputElement
setValue(target.value)
}
const handleEnterPress = (e: KeyboardEvent) => {
if (e.key === 'Enter') {
if (parseInt(value) <= seqNums.length && parseInt(value) > 0) {
handleChangeNum(parseInt(value))
} else if (parseInt(value) >= seqNums.length) {
handleChangeNum(seqNums.length)
} else if (parseInt(value) < seqNums.length) {
handleChangeNum(1)
} else {
handleChangeNum(1)
}
}
}
const calSeqNums = (seqNums: [number, number][], num: number) => {
const seqNumsTemp = seqNums.map((item): [number, number] =>
item[0] === num ? [item[0], 1] : [item[0], 0],
)
setSeqNums(seqNumsTemp)
setNum(num)
}
const handleChangeNum = (val: number|string) => {
if (typeof val === 'number') {
setValue(String(val))
if (val !== num) onChange(val)
calSeqNums(seqNums, val)
} else if (typeof val === 'string') {
if (val === 'pre') {
if (num > 1) {
calSeqNums(seqNums, num - 1)
setValue(String(num - 1))
onChange(num - 1)
}
} else if (val === 'next') {
if (num < seqNums.length) {
calSeqNums(seqNums, num + 1)
setValue(String(num + 1))
onChange(num + 1)
}
}
}
}
const calPaginationDom = () => {
return seqNums.map((item) => (
<span
key={item[0]}
className={`pagination-num${
item[1] === 1 ? ' pagination-num-selected' : ''
}`}
onClick={() => handleChangeNum(item[0])}
>
{item[0]}
</span>
))
}
const calPaginationDomEtc = () => {
return (
<>
{num < 5 && (
<>
{seqNums.slice(0, 5).map((item) => (
<span
key={item[0]}
className={`pagination-num${
item[1] === 1 ? ' pagination-num-selected' : ''
}`}
onClick={() => handleChangeNum(item[0])}
>
{item[0]}
</span>
))}
<span className="pagination-etc"> ... </span>
<span
className="pagination-num"
onClick={() => handleChangeNum(seqNums.length)}
>
{seqNums.length}
</span>
</>
)}
{num >= 5 && num <= seqNums.length - 4 && (
<>
<span className="pagination-num" onClick={() => handleChangeNum(1)}>
1
</span>
<span className="pagination-etc"> ... </span>
{seqNums.slice(num - 3, num + 2).map((item) => (
<span
key={item[0]}
className={`pagination-num${
item[1] === 1 ? ' pagination-num-selected' : ''
}`}
onClick={() => handleChangeNum(item[0])}
>
{item[0]}
</span>
))}
<span className="pagination-etc"> ... </span>
<span
className="pagination-num"
onClick={() => handleChangeNum(seqNums.length)}
>
{seqNums.length}
</span>
</>
)}
{num > seqNums.length - 4 && (
<>
<span
key={1}
className="pagination-num"
onClick={() => handleChangeNum(1)}
>
1
</span>
<span className="pagination-etc"> ... </span>
{seqNums.slice(seqNums.length - 5, seqNums.length).map((item) => (
<span
key={item[0]}
className={`pagination-num${
item[1] === 1 ? ' pagination-num-selected' : ''
}`}
onClick={() => handleChangeNum(item[0])}
>
{item[0]}
</span>
))}
</>
)}
</>
)
}
return (
<div className="div-pagination">
<div className="div-pagination-core unselect">
<span
className="pagination-icon"
onClick={() => handleChangeNum('pre')}
>
{/* <img src="../static/images/page_left.svg" alt="" /> */}
</span>
{seqNums.length < 10 ? calPaginationDom() : calPaginationDomEtc()}
<span
className="pagination-icon"
onClick={() => handleChangeNum('next')}
>
{/* <img src="../static/images/page_right.svg" alt="" /> */}
</span>
<span className="pagination-word" style={{ marginLeft: 16 }}>
</span>
<input
value={value}
onChange={handleChange}
onKeyDown={handleEnterPress}
/>
<span className="pagination-word"></span>
</div>
</div>
)
}
export default Pagination