From fba30743118f108fe539ba978a2907cd07b104e0 Mon Sep 17 00:00:00 2001 From: wanglinfang2014 Date: Mon, 8 Jan 2024 20:57:24 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9EmaxItemSelectionLengt?= =?UTF-8?q?h=E6=94=AF=E6=8C=81=E5=8D=95=E7=8B=AC=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E5=BD=93=E5=89=8D=E9=A1=B5=E6=9C=80=E5=A4=A7=E5=8B=BE=E9=80=89?= =?UTF-8?q?=E6=95=B0=20(#9249)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: wanglinfang --- docs/zh-CN/components/crud.md | 273 ++++++++++++++---- packages/amis-core/src/store/table.ts | 40 ++- .../__snapshots__/CRUD.test.tsx.snap | 3 +- packages/amis/src/renderers/CRUD.tsx | 6 +- packages/amis/src/renderers/Table/index.tsx | 6 +- 5 files changed, 248 insertions(+), 80 deletions(-) diff --git a/docs/zh-CN/components/crud.md b/docs/zh-CN/components/crud.md index d273d58cd..5f6a88616 100755 --- a/docs/zh-CN/components/crud.md +++ b/docs/zh-CN/components/crud.md @@ -2060,75 +2060,220 @@ interface CRUDMatchFunc { **保留条目选择** -默认分页、搜素后,用户选择条目会被清空,配置`keepItemSelectionOnPageChange`属性后会保留用户选择,可以实现跨页面批量操作。 +默认分页、搜索后,用户选择条目会被清空,配置`keepItemSelectionOnPageChange`属性后会保留用户选择,可以实现跨页面批量操作。 同时可以通过配置`maxKeepItemSelectionLength`属性限制最大勾选数 ```schema: scope="body" { - "type": "crud", - "syncLocation": false, - "api": "/api/mock2/sample", - "headerToolbar": [ - "bulkActions" - ], - "keepItemSelectionOnPageChange": true, - "maxKeepItemSelectionLength": 4, - "bulkActions": [ - { - "label": "批量删除", - "actionType": "ajax", - "api": "delete:/api/mock2/sample/${ids|raw}", - "confirmText": "确定要批量删除?" - }, - { - "label": "批量修改", - "actionType": "dialog", - "dialog": { - "title": "批量编辑", - "body": { - "type": "form", - "api": "/api/mock2/sample/bulkUpdate2", - "body": [ - { - "type": "hidden", - "name": "ids" - }, - { - "type": "input-text", - "name": "engine", - "label": "Engine" - } - ] - } + "type": "crud", + "syncLocation": false, + "api": "/api/mock2/sample", + "headerToolbar": [ + "bulkActions" + ], + "keepItemSelectionOnPageChange": true, + "maxKeepItemSelectionLength": 4, + "bulkActions": [ + { + "label": "批量删除", + "actionType": "ajax", + "api": "delete:/api/mock2/sample/${ids|raw}", + "confirmText": "确定要批量删除?" + }, + { + "label": "批量修改", + "actionType": "dialog", + "dialog": { + "title": "批量编辑", + "body": { + "type": "form", + "api": "/api/mock2/sample/bulkUpdate2", + "body": [ + { + "type": "hidden", + "name": "ids" + }, + { + "type": "input-text", + "name": "engine", + "label": "Engine" } + ] } - ], - "columns": [ - { - "name": "id", - "label": "ID" - }, - { - "name": "engine", - "label": "Rendering engine" - }, - { - "name": "browser", - "label": "Browser" - }, - { - "name": "platform", - "label": "Platform(s)" - }, - { - "name": "version", - "label": "Engine version" - }, - { - "name": "grade", - "label": "CSS grade" + } + } + ], + "columns": [ + { + "name": "id", + "label": "ID" + }, + { + "name": "engine", + "label": "Rendering engine" + }, + { + "name": "browser", + "label": "Browser" + }, + { + "name": "platform", + "label": "Platform(s)" + }, + { + "name": "version", + "label": "Engine version" + }, + { + "name": "grade", + "label": "CSS grade" + } + ] +} +``` + +**当前页最大勾选数** + +如果不需要在分页、搜索后,保留用户选择,即不需要配置`keepItemSelectionOnPageChange`,可以通过配置`maxItemSelectionLength`属性限制当前页条目的最大勾选数 + +```schema: scope="body" +{ + "type": "crud", + "syncLocation": false, + "api": "/api/mock2/sample", + "headerToolbar": [ + "bulkActions" + ], + "maxItemSelectionLength": 4, + "bulkActions": [ + { + "label": "批量删除", + "actionType": "ajax", + "api": "delete:/api/mock2/sample/${ids|raw}", + "confirmText": "确定要批量删除?" + }, + { + "label": "批量修改", + "actionType": "dialog", + "dialog": { + "title": "批量编辑", + "body": { + "type": "form", + "api": "/api/mock2/sample/bulkUpdate2", + "body": [ + { + "type": "hidden", + "name": "ids" + }, + { + "type": "input-text", + "name": "engine", + "label": "Engine" + } + ] } - ] + } + } + ], + "columns": [ + { + "name": "id", + "label": "ID" + }, + { + "name": "engine", + "label": "Rendering engine" + }, + { + "name": "browser", + "label": "Browser" + }, + { + "name": "platform", + "label": "Platform(s)" + }, + { + "name": "version", + "label": "Engine version" + }, + { + "name": "grade", + "label": "CSS grade" + } + ], + "itemCheckableOn": "this.index !== 2" +} +``` + +`maxItemSelectionLength`也可以和`keepItemSelectionOnPageChange`搭配使用,起到和`maxKeepItemSelectionLength`一样的效果 + +```schema: scope="body" +{ + "type": "crud", + "syncLocation": false, + "api": "/api/mock2/sample", + "headerToolbar": [ + "bulkActions" + ], + "keepItemSelectionOnPageChange": true, + "maxItemSelectionLength": 4, + "bulkActions": [ + { + "label": "批量删除", + "actionType": "ajax", + "api": "delete:/api/mock2/sample/${ids|raw}", + "confirmText": "确定要批量删除?" + }, + { + "label": "批量修改", + "actionType": "dialog", + "dialog": { + "title": "批量编辑", + "body": { + "type": "form", + "api": "/api/mock2/sample/bulkUpdate2", + "body": [ + { + "type": "hidden", + "name": "ids" + }, + { + "type": "input-text", + "name": "engine", + "label": "Engine" + } + ] + } + } + } + ], + "columns": [ + { + "name": "id", + "label": "ID" + }, + { + "name": "engine", + "label": "Rendering engine" + }, + { + "name": "browser", + "label": "Browser" + }, + { + "name": "platform", + "label": "Platform(s)" + }, + { + "name": "version", + "label": "Engine version" + }, + { + "name": "grade", + "label": "CSS grade" + } + ], + "itemCheckableOn": "this.index !== 2 && this.index !== 5" } ``` @@ -3665,8 +3810,10 @@ itemAction 里的 onClick 还能通过 `data` 参数拿到当前行的数据, | hideQuickSaveBtn | `boolean` | `false` | 隐藏顶部快速保存提示 | | autoJumpToTopOnPagerChange | `boolean` | `false` | 当切分页的时候,是否自动跳顶部。 | | syncResponse2Query | `boolean` | `true` | 将返回数据同步到过滤器上。 | -| keepItemSelectionOnPageChange | `boolean` | `true` | 保留条目选择,默认分页、搜素后,用户选择条目会被清空,开启此选项后会保留用户选择,可以实现跨页面批量操作。 | +| keepItemSelectionOnPageChange | `boolean` | `true` | 保留条目选择,默认分页、搜索后,用户选择条目会被清空,开启此选项后会保留用户选择,可以实现跨页面批量操作。 | | labelTpl | `string` | | 单条描述模板,`keepItemSelectionOnPageChange`设置为`true`后会把所有已选择条目列出来,此选项可以用来定制条目展示文案。 | +| maxKeepItemSelectionLength | `number` | `true` | 和`keepItemSelectionOnPageChange`搭配使用,限制最大勾选数。 | +| maxItemSelectionLength | `number` | `true` | 可单独使用限制当前页的最大勾选数,也可以和`keepItemSelectionOnPageChange`搭配使用达到和 maxKeepItemSelectionLength 一样的效果。 | | headerToolbar | Array | `['bulkActions', 'pagination']` | 顶部工具栏配置 | | footerToolbar | Array | `['statistics', 'pagination']` | 底部工具栏配置 | | alwaysShowPagination | `boolean` | `false` | 是否总是显示分页 | diff --git a/packages/amis-core/src/store/table.ts b/packages/amis-core/src/store/table.ts index 15dd5a946..829e190b9 100644 --- a/packages/amis-core/src/store/table.ts +++ b/packages/amis-core/src/store/table.ts @@ -339,13 +339,10 @@ export const Row = types */ get isCheckAvaiableOnClick(): boolean { const table = getParent(self, self.depth * 2) as ITableStore; - const keepItemSelectionOnPageChange = - table?.keepItemSelectionOnPageChange; - const selectionUpperLimit = table?.maxKeepItemSelectionLength; + const selectionUpperLimit = table.getSelectionUpperLimit(); // 如果未做配置,或者配置不合法直接通过检查 if ( - !keepItemSelectionOnPageChange || !Number.isInteger(selectionUpperLimit) || selectionUpperLimit === Infinity ) { @@ -524,6 +521,7 @@ export const TableStore = iRendererStore formsRef: types.optional(types.array(types.frozen()), []), maxKeepItemSelectionLength: Infinity, keepItemSelectionOnPageChange: false, + maxItemSelectionLength: Infinity, // 导出 Excel 按钮的 loading 状态 exportExcelLoading: false, searchFormExpanded: false, // 用来控制搜索框是否展开了,那个自动根据 searchable 生成的表单 autoGenerateFilter @@ -776,7 +774,19 @@ export const TableStore = iRendererStore return self.columns.filter(column => column.searchable); } + function getSelectionUpperLimit() { + const keep = self.keepItemSelectionOnPageChange; + const selectionUpperLimit = keep + ? self.maxKeepItemSelectionLength !== Infinity + ? self.maxKeepItemSelectionLength + : self.maxItemSelectionLength + : self.maxItemSelectionLength; + + return selectionUpperLimit; + } + return { + getSelectionUpperLimit, get columnsData() { return getColumnsExceptBuiltinTypes(); }, @@ -819,6 +829,11 @@ export const TableStore = iRendererStore }, get allChecked(): boolean { + const selectionUpperLimit = getSelectionUpperLimit(); + + if (selectionUpperLimit !== Infinity) { + return (self as ITableStore).isSelectionThresholdReached; + } // 只要selectedRows中包含checkableRows中的全部数据,就认为是全选 return (self as ITableStore).checkableRows.every(item => self.selectedRows.includes(item) @@ -879,9 +894,9 @@ export const TableStore = iRendererStore /** 已选择item是否达到数量上限 */ get isSelectionThresholdReached() { const selectedLength = self.data?.selectedItems?.length; - const maxLength = self.maxKeepItemSelectionLength; + const maxLength = getSelectionUpperLimit(); - if (!self.data || !self.keepItemSelectionOnPageChange || !maxLength) { + if (!self.data || maxLength === Infinity) { return false; } @@ -1073,6 +1088,8 @@ export const TableStore = iRendererStore config.keepItemSelectionOnPageChange !== undefined && (self.keepItemSelectionOnPageChange = config.keepItemSelectionOnPageChange); + config.maxItemSelectionLength !== undefined && + (self.maxItemSelectionLength = config.maxItemSelectionLength); config.exportExcelLoading !== undefined && (self.exportExcelLoading = config.exportExcelLoading); @@ -1556,14 +1573,11 @@ export const TableStore = iRendererStore } function getSelectedRows() { - const maxLength = self.maxKeepItemSelectionLength; - const keep = self.keepItemSelectionOnPageChange; - + const maxLength = self.getSelectionUpperLimit(); const selectedItems = self.data?.selectedItems; if ( - keep && - maxLength && + maxLength !== Infinity && selectedItems && maxLength >= selectedItems.length ) { @@ -1704,11 +1718,11 @@ export const TableStore = iRendererStore if (!self.data) { return; } - const maxLength = self.maxKeepItemSelectionLength; + const maxLength = self.getSelectionUpperLimit(); const selectedItems = self.data.selectedItems; self.selectedRows.map(item => item.setCheckdisable(false)); - if (maxLength && maxLength <= selectedItems.length) { + if (maxLength !== Infinity && maxLength <= selectedItems.length) { self.unSelectedRows.map( item => !item.checked && item.setCheckdisable(true) ); diff --git a/packages/amis/__tests__/renderers/__snapshots__/CRUD.test.tsx.snap b/packages/amis/__tests__/renderers/__snapshots__/CRUD.test.tsx.snap index 1355a7ffb..dd91ad120 100644 --- a/packages/amis/__tests__/renderers/__snapshots__/CRUD.test.tsx.snap +++ b/packages/amis/__tests__/renderers/__snapshots__/CRUD.test.tsx.snap @@ -2891,11 +2891,10 @@ exports[`13. enderer: crud keepItemSelectionOnPageChange & maxKeepItemSelectionL style="left: 0px;" >