diff --git a/docs/zh-CN/components/crud.md b/docs/zh-CN/components/crud.md index 882fd4e67..8a8361e17 100755 --- a/docs/zh-CN/components/crud.md +++ b/docs/zh-CN/components/crud.md @@ -2183,6 +2183,60 @@ crud 组件支持通过配置`headerToolbar`和`footerToolbar`属性,实现在 } ``` +#### 指定导出行 + +> 3.2.0 及以上版本 + +可以通过配置 `rowSlice` 属性来控制导出哪些行 + +```schema: scope="body" +{ + "type": "crud", + "syncLocation": false, + "api": "/api/mock2/sample", + "headerToolbar": [{ + "type": "export-excel", + "label": "导出 1, 4, 5 行", + "rowSlice": "0,3:5" + }], + "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" + } + ] +} +``` + +`rowSlice` 支持以下写法 + +- 取单个值 '1,2,3',代表取 1、2、3 索引的内容 +- 取范围 '3:10',代表取 3-9 索引的内容 + - ':' 代表所有行 + - '1:' 代表从第二行开始到结束 + - 结束可以是负数 ':-1',代表除了最后一个元素的所有元素,开始为空代表 0 +- 前两种的组合 '1,3:10',代表取 1 索引和 3-9 索引的内容 + #### 通过 api 导出 Excel > 1.1.6 以上版本支持 diff --git a/packages/amis-core/__tests__/utils/arraySlice.test.ts b/packages/amis-core/__tests__/utils/arraySlice.test.ts new file mode 100644 index 000000000..d843ffe32 --- /dev/null +++ b/packages/amis-core/__tests__/utils/arraySlice.test.ts @@ -0,0 +1,11 @@ +import {arraySlice} from '../../src/utils/arraySlice'; + +test(`arrayslice:test`, () => { + const testArray = [0, 1, 2, 3, 4, 5]; + expect(arraySlice(testArray, ':')).toEqual([0, 1, 2, 3, 4, 5]); + expect(arraySlice(testArray, '0,3,4')).toEqual([0, 3, 4]); + expect(arraySlice(testArray, '1:2')).toEqual([1]); + expect(arraySlice(testArray, '0:-2')).toEqual([0, 1, 2, 3]); + expect(arraySlice(testArray, '1:-2')).toEqual([1, 2, 3]); + expect(arraySlice(testArray, '0,1:-2')).toEqual([0, 1, 2, 3]); +}); diff --git a/packages/amis-core/src/utils/arraySlice.ts b/packages/amis-core/src/utils/arraySlice.ts new file mode 100644 index 000000000..d420c6867 --- /dev/null +++ b/packages/amis-core/src/utils/arraySlice.ts @@ -0,0 +1,67 @@ +/** + * 使用字符串语法来切片数组,参考了 python 中的语法 + * 支持的语法有: + * * 取单个值 1,2,3 + * * 取范围 3:10 + * * 组合 1,2,3:10 + * * 范围是负数 :-1,代表除了最后一个元素的所有元素 + */ +import {toJS, isObservableArray} from 'mobx'; + +export function arraySlice(array: any[], slice: string) { + if (typeof slice !== 'string') { + return array; + } + if (isObservableArray(array)) { + array = toJS(array); + } + + slice = slice.trim(); + if (!slice || !Array.isArray(array)) { + return array; + } + const parts = slice.split(','); + const ret: any[] = []; + const arrayLength = array.length; + if (!arrayLength) { + return array; + } + for (const part of parts) { + // 普通的场景 + if (part.indexOf(':') === -1) { + const index = parseInt(part, 10); + if (!isNaN(index) && index < arrayLength) { + ret.push(array[index]); + } + } else { + const [start, end] = part.split(':'); + let startIndex = parseInt(start || '0', 10); + if (isNaN(startIndex) || startIndex < 0) { + startIndex = 0; + } + // 大于就没意义了 + if (startIndex >= arrayLength) { + continue; + } + let endIndex = parseInt(end, 10); + if (isNaN(endIndex)) { + endIndex = arrayLength; + } + // 负数就从后面开始取 + if (endIndex < 0) { + endIndex = arrayLength + endIndex; + } + // 小于没有意义 + if (endIndex < startIndex) { + continue; + } + if (endIndex > arrayLength) { + endIndex = arrayLength; + } + + ret.push(...array.slice(startIndex, endIndex)); + } + } + + return ret; +} diff --git a/packages/amis-core/src/utils/index.ts b/packages/amis-core/src/utils/index.ts index 063deee2c..665ad500e 100644 --- a/packages/amis-core/src/utils/index.ts +++ b/packages/amis-core/src/utils/index.ts @@ -54,6 +54,7 @@ export * from './toNumber'; export * from './decodeEntity'; export * from './style-helper'; export * from './resolveCondition'; +export * from './arraySlice'; import animation from './Animation'; diff --git a/packages/amis/src/renderers/Table/exportExcel.ts b/packages/amis/src/renderers/Table/exportExcel.ts index 85192a92c..e48fd6f2e 100644 --- a/packages/amis/src/renderers/Table/exportExcel.ts +++ b/packages/amis/src/renderers/Table/exportExcel.ts @@ -2,7 +2,7 @@ * 导出 Excel 功能 */ -import {filter, isEffectiveApi} from 'amis-core'; +import {filter, isEffectiveApi, arraySlice} from 'amis-core'; import './ColumnToggler'; import {TableStore} from 'amis-core'; import {saveAs} from 'file-saver'; @@ -261,6 +261,9 @@ export async function exportExcel( const remoteMappingCache: any = {}; // 数据从第二行开始 let rowIndex = 1; + if (toolbar.rowSlice) { + rows = arraySlice(rows, toolbar.rowSlice); + } for (const row of rows) { const rowData = createObject(data, row.data); rowIndex += 1; diff --git a/packages/amis/src/renderers/Table/index.tsx b/packages/amis/src/renderers/Table/index.tsx index eff5267ce..6e72c2df2 100644 --- a/packages/amis/src/renderers/Table/index.tsx +++ b/packages/amis/src/renderers/Table/index.tsx @@ -404,6 +404,7 @@ export type ExportExcelToolbar = SchemaNode & { api?: SchemaApi; columns?: string[]; exportColumns?: any[]; + rowSlice?: string; filename?: string; };