mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-06-21 22:14:02 +08:00
✨ feat(datagrid): 增加分页跳页并适配窄屏
- 分页条新增跳页输入与提交按钮,支持回车和点击跳转 - 跳页页码自动限制在有效页码范围内,避免越界分页请求 - 为 v2 状态栏增加容器级响应式规则,适配 AI 面板打开后的窄宽场景 - 分页区域增加横向滚动兜底,避免小尺寸屏幕下控件被挤压变形 - 补充 DataGrid 布局回归测试,覆盖跳页控件和窄屏样式规则
This commit is contained in:
@@ -104,6 +104,9 @@ describe('DataGrid layout', () => {
|
||||
expect(markup).toContain('data-grid-v2-page-chip="true"');
|
||||
expect(markup).toContain('data-grid-v2-pagination-prev="true"');
|
||||
expect(markup).toContain('data-grid-v2-pagination-next="true"');
|
||||
expect(markup).toContain('data-grid-pagination-jump="true"');
|
||||
expect(markup).toContain('跳页');
|
||||
expect(markup).toContain('跳转页码');
|
||||
expect(markup).not.toContain('class="ant-pagination');
|
||||
expect(markup).not.toContain('class="data-grid-pagination-kicker"');
|
||||
expect(markup).toContain('当前页查找...');
|
||||
@@ -545,9 +548,19 @@ describe('DataGrid layout', () => {
|
||||
expect(secondaryActionsSource.indexOf('{pageFindContent}')).toBeLessThan(secondaryActionsSource.indexOf('gn-v2-data-grid-status-center'));
|
||||
expect(css).toContain('width: 66px !important;');
|
||||
expect(css).toContain('grid-template-columns: 160px 26px 26px !important;');
|
||||
expect(css).toContain('container-name: gn-v2-data-grid-statusbar;');
|
||||
expect(css).toContain('body[data-ui-version="v2"] .gn-v2-data-grid-status-right::-webkit-scrollbar');
|
||||
expect(css).toContain('body[data-ui-version="v2"] .gn-v2-data-grid-pagination-wrap::-webkit-scrollbar');
|
||||
expect(css).toContain('@container gn-v2-data-grid-statusbar (max-width: 960px)');
|
||||
expect(css).toContain('@container gn-v2-data-grid-statusbar (max-width: 760px)');
|
||||
expect(css).toContain('.data-grid-pagination-size-select.ant-select-focused .ant-select-selector');
|
||||
expect(css).toContain('overflow-x: auto;');
|
||||
expect(paginationBarSource).toContain("label: `${value}/页`");
|
||||
expect(paginationBarSource).toContain('const maxJumpPage = Math.max(1, paginationTotalPages);');
|
||||
expect(paginationBarSource).toContain('Math.min(maxJumpPage, Math.max(1, Math.trunc(Number(jumpPage))))');
|
||||
expect(paginationBarSource).toContain('onPressEnter={submitJumpPage}');
|
||||
expect(paginationBarSource).toContain('data-grid-pagination-jump="true"');
|
||||
expect(css).toContain('.data-grid-pagination-jump-input.ant-input-number-focused');
|
||||
expect(css).toContain('background: transparent !important;');
|
||||
});
|
||||
|
||||
|
||||
@@ -2913,6 +2913,57 @@ const DataGrid: React.FC<DataGridProps> = ({
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.${gridId} .data-grid-pagination-jump {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
height: 34px;
|
||||
color: ${paginationSecondaryTextColor};
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.${gridId} .data-grid-pagination-jump-label {
|
||||
color: ${paginationSecondaryTextColor};
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
.${gridId} .data-grid-pagination-jump-input,
|
||||
.${gridId} .data-grid-pagination-jump-input.ant-input-number {
|
||||
width: 64px;
|
||||
min-width: 64px;
|
||||
height: 34px;
|
||||
display: inline-flex;
|
||||
align-items: stretch;
|
||||
}
|
||||
.${gridId} .data-grid-pagination-jump-input .ant-input-number-input-wrap,
|
||||
.${gridId} .data-grid-pagination-jump-input .ant-input-number-input {
|
||||
height: 100%;
|
||||
}
|
||||
.${gridId} .data-grid-pagination-jump-input .ant-input-number-input {
|
||||
padding: 0 10px;
|
||||
text-align: center;
|
||||
color: ${paginationPrimaryTextColor};
|
||||
font-weight: 600;
|
||||
font-variant-numeric: tabular-nums;
|
||||
line-height: 34px;
|
||||
}
|
||||
.${gridId} .data-grid-pagination-jump-input.ant-input-number {
|
||||
border-radius: 12px;
|
||||
border: 1px solid ${paginationChipBorderColor};
|
||||
background: ${paginationChipBg};
|
||||
box-shadow: none;
|
||||
}
|
||||
.${gridId} .data-grid-pagination-jump-button.ant-btn {
|
||||
height: 34px;
|
||||
min-width: 34px;
|
||||
padding: 0 10px;
|
||||
border-radius: 12px;
|
||||
border-color: ${paginationChipBorderColor};
|
||||
background: ${paginationChipBg};
|
||||
color: ${paginationPrimaryTextColor};
|
||||
font-weight: 700;
|
||||
box-shadow: none;
|
||||
}
|
||||
.${gridId} .data-grid-pagination-size-select {
|
||||
width: 72px;
|
||||
min-width: 72px;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { Button, Pagination, Select } from 'antd';
|
||||
import { Button, InputNumber, Pagination, Select } from 'antd';
|
||||
import { LeftOutlined, RightOutlined } from '@ant-design/icons';
|
||||
|
||||
interface DataGridPaginationState {
|
||||
@@ -38,10 +38,53 @@ const DataGridPaginationBar: React.FC<DataGridPaginationBarProps> = ({
|
||||
onPageSizeChange,
|
||||
onV2PageStep,
|
||||
}) => {
|
||||
const [jumpPage, setJumpPage] = React.useState<number | null>(pagination?.current ?? null);
|
||||
|
||||
React.useEffect(() => {
|
||||
setJumpPage(pagination?.current ?? null);
|
||||
}, [pagination?.current]);
|
||||
|
||||
if (!pagination) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const maxJumpPage = Math.max(1, paginationTotalPages);
|
||||
const normalizedJumpPage = Number.isFinite(Number(jumpPage)) && Number(jumpPage) > 0
|
||||
? Math.min(maxJumpPage, Math.max(1, Math.trunc(Number(jumpPage))))
|
||||
: null;
|
||||
const jumpDisabled = !onPageChange || normalizedJumpPage === null || normalizedJumpPage === pagination.current;
|
||||
const submitJumpPage = () => {
|
||||
if (!onPageChange || normalizedJumpPage === null) return;
|
||||
if (normalizedJumpPage === pagination.current) return;
|
||||
onPageChange(normalizedJumpPage, pagination.pageSize);
|
||||
};
|
||||
const jumpPageControl = (
|
||||
<div className="data-grid-pagination-jump" data-grid-pagination-jump="true">
|
||||
<span className="data-grid-pagination-jump-label">跳页</span>
|
||||
<InputNumber
|
||||
size="small"
|
||||
min={1}
|
||||
max={maxJumpPage}
|
||||
precision={0}
|
||||
controls={false}
|
||||
value={jumpPage}
|
||||
onChange={(value) => setJumpPage(typeof value === 'number' && Number.isFinite(value) ? value : null)}
|
||||
onPressEnter={submitJumpPage}
|
||||
className="data-grid-pagination-jump-input"
|
||||
aria-label="跳转页码"
|
||||
disabled={!onPageChange}
|
||||
/>
|
||||
<Button
|
||||
size="small"
|
||||
className="data-grid-pagination-jump-button"
|
||||
disabled={jumpDisabled}
|
||||
onClick={submitJumpPage}
|
||||
>
|
||||
跳
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`${isV2Ui ? 'gn-v2-data-grid-pagination-wrap ' : ''}data-grid-pagination-wrap`}
|
||||
@@ -71,6 +114,7 @@ const DataGridPaginationBar: React.FC<DataGridPaginationBarProps> = ({
|
||||
disabled={!onPageChange || pagination.current >= paginationTotalPages}
|
||||
onClick={() => onV2PageStep('next')}
|
||||
/>
|
||||
{jumpPageControl}
|
||||
<Select
|
||||
size="small"
|
||||
popupMatchSelectWidth={false}
|
||||
@@ -105,6 +149,7 @@ const DataGridPaginationBar: React.FC<DataGridPaginationBarProps> = ({
|
||||
return originalElement;
|
||||
}}
|
||||
/>
|
||||
{jumpPageControl}
|
||||
<Select
|
||||
size="small"
|
||||
popupMatchSelectWidth={false}
|
||||
|
||||
Reference in New Issue
Block a user