| 2426 | } |
| 2427 | |
| 2428 | function PaginationControls(props: { |
| 2429 | page: number; |
| 2430 | pageSize: number; |
| 2431 | totalCount: number; |
| 2432 | className?: string; |
| 2433 | onPageChange: (page: number) => void; |
| 2434 | }) { |
| 2435 | const { t } = useI18n(); |
| 2436 | const pageCount = Math.max(1, Math.ceil(props.totalCount / props.pageSize)); |
| 2437 | const from = props.totalCount === 0 ? 0 : (props.page - 1) * props.pageSize + 1; |
| 2438 | const to = Math.min(props.page * props.pageSize, props.totalCount); |
| 2439 | return ( |
| 2440 | <div className={cn("flex flex-wrap items-center justify-between gap-2 border-t border-border pt-3", props.className)}> |
| 2441 | <div className="text-xs text-muted-foreground"> |
| 2442 | {t(`第 ${props.page}/${pageCount} 页 · ${from}-${to} / ${props.totalCount} 条`, `Page ${props.page}/${pageCount} · ${from}-${to} / ${props.totalCount}`)} |
| 2443 | </div> |
| 2444 | <div className="flex items-center gap-2"> |
| 2445 | <Button |
| 2446 | variant="outline" |
| 2447 | size="sm" |
| 2448 | disabled={props.page <= 1} |
| 2449 | onClick={() => props.onPageChange(Math.max(1, props.page - 1))} |
| 2450 | > |
| 2451 | <ChevronLeft className="h-4 w-4" /> |
| 2452 | {t("上一页", "Previous")} |
| 2453 | </Button> |
| 2454 | <Button |
| 2455 | variant="outline" |
| 2456 | size="sm" |
| 2457 | disabled={props.page >= pageCount} |
| 2458 | onClick={() => props.onPageChange(Math.min(pageCount, props.page + 1))} |
| 2459 | > |
| 2460 | {t("下一页", "Next")} |
| 2461 | <ChevronRight className="h-4 w-4" /> |
| 2462 | </Button> |
| 2463 | </div> |
| 2464 | </div> |
| 2465 | ); |
| 2466 | } |
| 2467 | |
| 2468 | function ChunksPanel({ chunks, hasFilter }: { chunks: ChunkRecord[]; hasFilter?: boolean }) { |
| 2469 | const { t } = useI18n(); |