feat: CRUD表头过滤支持数据域

This commit is contained in:
lurunze1226 2023-11-10 15:19:06 +08:00
parent 01f2132847
commit 2589bbf005
5 changed files with 126 additions and 19 deletions

View File

@ -1072,6 +1072,51 @@ amis 只负责生成下拉选择器组件,并将搜索参数传递给接口,
你可以通过[数据映射](../../docs/concepts/data-mapping),在`api`中获取这些参数。
#### 下拉数据源
过滤器的数据域支持API接口和上下文数据(`3.6.0`及以上版本)
```schema
{
"type": "page",
"data": {
"options": [
{"label": "4", "value": 3},
{"label": "5", "value": 5},
{"label": "5.5", "value": 5.5},
{"label": "6", "value": 6}
]
},
"body": [
{
"type": "crud",
"syncLocation": false,
"api": "/api/mock2/sample",
"columns": [
{
"name": "id",
"label": "ID"
},
{
"name": "grade",
"label": "CSS grade",
"filterable": {
"source": "/api/mock2/crud/filterOptions"
}
},
{
"name": "version",
"label": "Version",
"filterable": {
"source": "${options}"
}
}
]
}
]
}
```
### 快速编辑
可以通过给列配置:`"quickEdit":true`和`quickSaveApi` 可以实现表格内快速编辑并批量保存的功能。
@ -3332,7 +3377,7 @@ itemAction 里的 onClick 还能通过 `data` 参数拿到当前行的数据,
除了 Table 组件默认支持的列配置CRUD 的列配置还额外支持以下属性:
| 属性名 | 类型 | 默认值 | 说明 |
| 属性名 | 类型 | 默认值 | 说明 | 版本 |
| ------------------ | --------------------------------------------------------------- | ------- | --------------------------------------------------------------------------- | --- |
| sortable | `boolean` | `false` | 是否可排序 |
| searchable | `boolean` \| `Schema` | `false` | 是否可快速搜索,开启`autoGenerateFilter`后,`searchable`支持配置`Schema` |
@ -3346,7 +3391,7 @@ itemAction 里的 onClick 还能通过 `data` 参数拿到当前行的数据,
| ------------- | ----------------------------- | ------- | -------------------------------------------------------- | ------- |
| options | `Array<any>` | - | 静态选项 | |
| multiple | `boolean` | `false` | 是否支持多选 | |
| source | [`Api`](../../docs/types/api) | - | 选项 API 接口 | |
| source | [`Api`](../../docs/types/api) \| `string` | - | 选项 API 接口 | `3.6.0`版本后支持上下文变量 |
| refreshOnOpen | `boolean` | `false` | 配置 source 前提下,每次展开筛选浮层是否重新加载选项数据 | `2.9.0` |
| strictMode | `boolean` | `false` | 严格模式,开启严格模式后,会采用 JavaScript 严格相等比较 | `2.3.0` |

View File

@ -24,4 +24,4 @@ export default {
aside: '边栏',
toolbar: '工具栏',
initApi: '/api/mock2/page/initDataError'
};
}

View File

@ -0,0 +1,32 @@
module.exports = function (req, res) {
const ret = {
status: 0,
msg: '',
data: {
options: [
{
"label": "A",
"value": "A"
},
{
"label": "B",
"value": "B"
},
{
"label": "C",
"value": "C"
},
{
"label": "D",
"value": "D"
},
{
"label": "X",
"value": "X"
}
]
}
};
res.json(ret);
};

View File

@ -1,23 +1,27 @@
import React from 'react';
import {RendererProps} from 'amis-core';
import {isApiOutdated, isEffectiveApi, normalizeApi} from 'amis-core';
import {Icon} from 'amis-ui';
import {Overlay} from 'amis-core';
import {PopOver} from 'amis-core';
import {findDOMNode} from 'react-dom';
import {Checkbox} from 'amis-ui';
import xor from 'lodash/xor';
import {findDOMNode} from 'react-dom';
import {
Overlay,
PopOver,
isApiOutdated,
isEffectiveApi,
normalizeApi,
normalizeOptions,
getVariable,
createObject,
isNumeric
isNumeric,
isPureVariable,
resolveVariableAndFilter
} from 'amis-core';
import type {Option} from 'amis-core';
import {Checkbox, Icon} from 'amis-ui';
import type {RendererProps, Option} from 'amis-core';
export interface QuickFilterConfig {
options: Array<any>;
// source: Api;
/** 数据源API或上下文变量 */
source: any;
multiple: boolean;
/* 是否开启严格对比模式 */
strictMode?: boolean;
@ -26,7 +30,10 @@ export interface QuickFilterConfig {
}
export interface HeadCellFilterProps extends RendererProps {
/** 所在的CRUD的Query数据 */
data: any;
/** 所在的CRUD的数据以及上层数据 */
superData: Record<string, any>;
name: string;
filterable: QuickFilterConfig;
onQuery: (
@ -57,11 +64,21 @@ export class HeadCellFilterDropDown extends React.Component<
}
componentDidMount() {
const {filterable} = this.props;
const {filterable, data} = this.props;
const {source, options} = filterable || {};
if (filterable.source) {
if (source && isPureVariable(source)) {
const datasource = resolveVariableAndFilter(
source,
this.props.superData,
'| raw'
);
this.setState({
filterOptions: this.alterOptions(datasource)
});
} else if (source && isEffectiveApi(source, data)) {
this.fetchOptions();
} else if (filterable.options?.length > 0) {
} else if (options?.length > 0) {
this.setState({
filterOptions: this.alterOptions(filterable.options)
});
@ -70,7 +87,6 @@ export class HeadCellFilterDropDown extends React.Component<
componentDidUpdate(prevProps: HeadCellFilterProps, prevState: any) {
const name = this.props.name;
const props = this.props;
this.sourceInvalid = false;
@ -186,10 +202,23 @@ export class HeadCellFilterDropDown extends React.Component<
}
async open() {
const {filterable} = this.props;
const {filterable, source} = this.props;
if (filterable.refreshOnOpen && filterable.source) {
if (source && isPureVariable(source)) {
const datasource = resolveVariableAndFilter(
source,
this.props.superData,
'| raw'
);
this.setState({
filterOptions: this.alterOptions(datasource)
});
} else {
await this.fetchOptions();
}
}
this.setState({
isOpened: true
});

View File

@ -2017,6 +2017,7 @@ export default class Table extends React.Component<TableProps, object> {
name={column.name}
type={column.type}
data={query}
superData={createObject(data, query)}
filterable={column.filterable}
popOverContainer={this.getPopOverContainer}
/>