chore: 简单分页新增方向变量让后端知道是应该取after 还是取 before Close: #7196

This commit is contained in:
2betop 2023-09-19 09:59:37 +08:00
parent bebddab158
commit 7d975e5b77
6 changed files with 172 additions and 18 deletions

View File

@ -3066,6 +3066,7 @@ itemAction 里的 onClick 还能通过 `data` 参数拿到当前行的数据,
| defaultParams | `Object` | | 设置默认 filter 默认参数,会在查询的时候一起发给后端 |
| pageField | `string` | `"page"` | 设置分页页码字段名。 |
| perPageField | `string` | `"perPage"` | 设置分页一页显示的多少条数据的字段名。注意:最好与 defaultParams 一起使用,请看下面例子。 |
| pageDirectionField | `string` | `"pageDir"` | 分页方向字段名可能是 forward 或者 backward |
| perPageAvailable | `Array<number>` | `[5, 10, 20, 50, 100]` | 设置一页显示多少条数据下拉框可选条数。 |
| orderField | `string` | | 设置用来确定位置的字段名,设置后新的顺序将被赋值到该字段中。 |
| hideQuickSaveBtn | `boolean` | `false` | 隐藏顶部快速保存提示 |
@ -3145,17 +3146,17 @@ itemAction 里的 onClick 还能通过 `data` 参数拿到当前行的数据,
当前组件会对外派发以下事件,可以通过`onEvent`来监听这些事件,并通过`actions`来配置执行的动作,在`actions`中可以通过`${事件参数名}`或`${event.data.[事件参数名]}`来获取事件产生的数据,详细查看[事件动作](../../docs/concepts/event-action)。
| 事件名称 | 事件参数 | 说明 |
| -------------- | ----------------------------------------------------------------------- | -------------------- |
| selectedChange | `selectedItems: item[]` 已选择行<br/>`unSelectedItems: item[]` 未选择行 | 手动选择表格项时触发 |
| columnSort | `orderBy: string` 列排序列名<br/>`orderDir: string` 列排序值 | 点击列排序时触发 |
| columnFilter | `filterName: string` 列筛选列名<br/>`filterValue: string \| undefined` 列筛选值 | 点击列筛选时触发,点击重置后事件参数`filterValue`为`undefined` |
| columnSearch | `searchName: string` 列搜索列名<br/>`searchValue: object` 列搜索数据 | 点击列搜索时触发 |
| orderChange | `movedItems: item[]` 已排序数据 | 手动拖拽行排序时触发 |
| columnToggled | `columns: item[]` 当前显示的列配置数据 | 点击自定义列时触发 |
| rowClick | `item: object` 行点击数据<br/>`index: number` 行索引 | 点击整行时触发 |
| rowMouseEnter | `item: object` 行移入数据<br/>`index: number` 行索引 | 移入整行时触发 |
| rowMouseLeave | `item: object` 行移出数据<br/>`index: number` 行索引 | 移出整行时触发 |
| 事件名称 | 事件参数 | 说明 |
| -------------- | ------------------------------------------------------------------------------- | -------------------------------------------------------------- |
| selectedChange | `selectedItems: item[]` 已选择行<br/>`unSelectedItems: item[]` 未选择行 | 手动选择表格项时触发 |
| columnSort | `orderBy: string` 列排序列名<br/>`orderDir: string` 列排序值 | 点击列排序时触发 |
| columnFilter | `filterName: string` 列筛选列名<br/>`filterValue: string \| undefined` 列筛选值 | 点击列筛选时触发,点击重置后事件参数`filterValue`为`undefined` |
| columnSearch | `searchName: string` 列搜索列名<br/>`searchValue: object` 列搜索数据 | 点击列搜索时触发 |
| orderChange | `movedItems: item[]` 已排序数据 | 手动拖拽行排序时触发 |
| columnToggled | `columns: item[]` 当前显示的列配置数据 | 点击自定义列时触发 |
| rowClick | `item: object` 行点击数据<br/>`index: number` 行索引 | 点击整行时触发 |
| rowMouseEnter | `item: object` 行移入数据<br/>`index: number` 行索引 | 移入整行时触发 |
| rowMouseLeave | `item: object` 行移出数据<br/>`index: number` 行索引 | 移出整行时触发 |
### selectedChange
@ -4269,7 +4270,7 @@ value 结构说明:
### setValue
通过`setValue`更新指定CRUD的数据。
通过`setValue`更新指定 CRUD 的数据。
#### 合并数据
@ -4406,6 +4407,7 @@ value 结构说明:
}
]
```
#### 更新列表记录
```schema: scope="body"

View File

@ -0,0 +1,48 @@
export default {
title: '简单分页,返回 hasNext 属性指示是否有下一页',
body: {
type: 'crud',
draggable: true,
api: {
method: 'get',
url: '/api/sample/simpleList?page=${page}&pageDir=${pageDir}&after=${items[items.length - 1].id}&before=${items[0].id}',
// 因为 before 和 after 的值每次请求完后都会变
// 触发了接口的自动刷新,所以这里需要通过 trackExpression 自定义刷新条件
trackExpression: '${page}-${pageDir}'
},
columns: [
{
name: 'id',
label: 'ID',
type: 'text',
remark: 'Bla bla Bla'
},
{
name: 'engine',
label: 'Rendering engine',
type: 'text'
},
{
name: 'browser',
label: 'Browser',
type: 'text'
},
{
name: 'platform',
label: 'Platform(s)',
type: 'text'
},
{
name: 'version',
label: 'Engine version',
type: 'text',
classNameExpr: "<%= data.version < 5 ? 'bg-danger' : '' %>"
},
{
type: 'text',
name: 'grade',
label: 'CSS grade'
}
]
}
};

View File

@ -56,6 +56,7 @@ import HeaderHideSchema from './CRUD/HeaderHide';
import LoadOnceTableCrudSchema from './CRUD/LoadOnce';
import ExportCSVExcelSchema from './CRUD/ExportCSVExcel';
import CRUDDynamicSchema from './CRUD/Dynamic';
import CRUDSimplePagerSchema from './CRUD/SimplePager';
import ItemActionchema from './CRUD/ItemAction';
import SdkTest from './Sdk/Test';
import JSONSchemaForm from './Form/Schem';
@ -454,6 +455,11 @@ export const examples = [
label: '动态列',
path: '/examples/crud/dynamic',
component: makeSchemaRenderer(CRUDDynamicSchema)
},
{
label: '简单分页',
path: '/examples/crud/simple-pager',
component: makeSchemaRenderer(CRUDSimplePagerSchema)
}
// {
// label: '',

View File

@ -31,6 +31,8 @@ module.exports = function (req, res) {
return res.json({myItems: DB.concat()});
} else if (pathname === 'sample/arrayInData') {
return res.json({data: DB.concat()});
} else if (pathname === 'sample/simpleList') {
return indexSimple(req, res);
}
return index(req, res);
@ -99,6 +101,73 @@ function index(req, res) {
return response();
}
function indexSimple(req, res) {
const perPage = 10;
const page = parseInt(req.query.page, 10) || 1;
const dir = req.query.pageDir;
const after = req.query.after;
const before = req.query.before;
let items = DB.concat();
// 制造点随机内容不然还以为没刷新
items = items.map(item => {
return {
...item,
engine: item.engine + ' - ' + Math.random().toString(36).substring(7)
};
});
if (req.query.keywords && !req.query.loadDataOnce) {
const keywords = req.query.keywords;
items = items.filter(function (item) {
return ~JSON.stringify(item).indexOf(keywords);
});
}
if (req.query.engine && !req.query.loadDataOnce) {
const keywords = req.query.engine;
items = items.filter(function (item) {
return ~JSON.stringify(item.engine).indexOf(keywords);
});
}
if (req.query.orderBy && !req.query.loadDataOnce) {
const field = req.query.orderBy;
const direction = req.query.orderDir === 'desc' ? -1 : 1;
items = items.sort(function (a, b) {
a = String(a[field]);
b = String(b[field]);
if (/^\d+$/.test(a) && /^\d+$/.test(b)) {
a = parseInt(a, 10);
b = parseInt(b, 10);
return (a > b ? 1 : a < b ? -1 : 0) * direction;
}
return a.localeCompare(b) * direction;
});
}
let idx = 0;
if (dir === 'forward' && after) {
idx = items.findIndex(item => item.id === parseInt(after, 10)) + 1;
} else if (dir === 'backward' && before) {
idx = items.findIndex(item => item.id === parseInt(before, 10)) - perPage;
} else if (page) {
idx = (page - 1) * perPage;
}
idx = Math.max(Math.min(idx, items.length - 1), 0);
res.json({
status: 0,
msg: 'ok',
data: {
hasNext: idx + perPage < items.length,
rows: items.splice(idx, perPage)
}
});
}
function store(req, res) {
const data = Object.assign({}, req.body);

View File

@ -93,7 +93,7 @@ export interface BasicPaginationProps {
*/
popOverContainerSelector?: string;
onPageChange?: (page: number, perPage?: number) => void;
onPageChange?: (page: number, perPage?: number, dir?: string) => void;
}
export interface PaginationProps
extends BasicPaginationProps,
@ -139,13 +139,17 @@ export class Pagination extends React.Component<
}
}
handlePageNumChange(page: number, perPage?: number) {
handlePageNumChange(page: number, perPage?: number, dir?: string) {
const {disabled, onPageChange} = this.props;
if (disabled) {
return;
}
onPageChange?.(isNaN(Number(page)) || Number(page) < 1 ? 1 : page, perPage);
onPageChange?.(
isNaN(Number(page)) || Number(page) < 1 ? 1 : page,
perPage,
dir
);
}
/**
@ -306,7 +310,11 @@ export class Pagination extends React.Component<
if (activePage < 2) {
return e.preventDefault();
}
return this.handlePageNumChange(activePage - 1);
return this.handlePageNumChange(
activePage - 1,
undefined,
'backward'
);
}}
key="prev"
>
@ -322,7 +330,11 @@ export class Pagination extends React.Component<
if (!hasNext) {
return e.preventDefault();
}
return this.handlePageNumChange(activePage + 1, perPage);
return this.handlePageNumChange(
activePage + 1,
perPage,
'forward'
);
}}
key="next"
>

View File

@ -214,6 +214,12 @@ export interface CRUDCommonSchema extends BaseSchema, SpinnerExtraProps {
*/
perPageField?: string;
/**
*
* @default pageDir
*/
pageDirectionField?: string;
/**
* API
*/
@ -408,6 +414,7 @@ export default class CRUD extends React.Component<CRUDProps, any> {
'perPageAvailable',
'pageField',
'perPageField',
'pageDirectionField',
'hideQuickSaveBtn',
'autoJumpToTopOnPagerChange',
'interval',
@ -455,6 +462,7 @@ export default class CRUD extends React.Component<CRUDProps, any> {
syncLocation: true,
pageField: 'page',
perPageField: 'perPage',
pageDirectionField: 'pageDir',
hideQuickSaveBtn: false,
autoJumpToTopOnPagerChange: true,
silentPolling: false,
@ -1305,13 +1313,18 @@ export default class CRUD extends React.Component<CRUDProps, any> {
return this.search(values, true, clearSelection, forceReload);
}
handleChangePage(page: number, perPage?: number) {
handleChangePage(
page: number,
perPage?: number,
dir?: 'forward' | 'backward'
) {
const {
store,
syncLocation,
env,
pageField,
perPageField,
pageDirectionField,
autoJumpToTopOnPagerChange,
affixOffsetTop
} = this.props;
@ -1320,6 +1333,10 @@ export default class CRUD extends React.Component<CRUDProps, any> {
[pageField || 'page']: page
};
if (dir) {
query[pageDirectionField || 'pageDir'] = dir;
}
if (perPage) {
query[perPageField || 'perPage'] = perPage;
}