mirror of
https://gitee.com/baidu/amis.git
synced 2024-12-04 21:08:55 +08:00
feat: 核心组件相关改动 (#6025)
* feat: 核心组件相关改动 * table2 列搜索自定义schema问题修复 * table2 column 不将title传递下去 * 不能传递 valueField 给table,否则table中的表单项valueField 会被覆盖
This commit is contained in:
parent
522d9c06c8
commit
45dc93c07f
@ -219,6 +219,8 @@ export interface ApiObject extends BaseApiObject {
|
||||
query?: PlainObject;
|
||||
adaptor?: (payload: object, response: fetcherResult, api: ApiObject) => any;
|
||||
requestAdaptor?: (api: ApiObject) => ApiObject;
|
||||
/** 是否过滤为空字符串的 query 参数 */
|
||||
filterEmptyQuery?: boolean;
|
||||
}
|
||||
export type ApiString = string;
|
||||
export type Api = ApiString | ApiObject;
|
||||
|
@ -129,6 +129,19 @@ export function buildApi(
|
||||
);
|
||||
};
|
||||
|
||||
// 是否过滤空字符串 query
|
||||
const queryStringify = (query: any) =>
|
||||
qsstringify(
|
||||
query,
|
||||
(api as ApiObject)?.filterEmptyQuery
|
||||
? {
|
||||
filter: (key: string, value: any) => {
|
||||
return value === '' ? undefined : value;
|
||||
}
|
||||
}
|
||||
: undefined
|
||||
);
|
||||
|
||||
if (~idx) {
|
||||
const hashIdx = url.indexOf('#');
|
||||
const params = qsparse(
|
||||
@ -146,10 +159,13 @@ export function buildApi(
|
||||
});
|
||||
|
||||
const left = replaceExpression(url.substring(0, idx), 'raw', '');
|
||||
|
||||
// 追加
|
||||
Object.assign(params, api.query);
|
||||
api.url =
|
||||
left +
|
||||
(~left.indexOf('?') ? '&' : '?') +
|
||||
qsstringify(
|
||||
queryStringify(
|
||||
(api.query = dataMapping(params, data, undefined, api.convertKeyToPath))
|
||||
) +
|
||||
(~hashIdx && hashIdx > idx
|
||||
@ -178,13 +194,22 @@ export function buildApi(
|
||||
api.body = api.data = data;
|
||||
}
|
||||
|
||||
// 给 query 做数据映射
|
||||
if (api.query) {
|
||||
api.query = dataMapping(api.query, data, undefined, api.convertKeyToPath);
|
||||
}
|
||||
|
||||
// get 类请求,把 data 附带到 url 上。
|
||||
if (api.method === 'get' || api.method === 'jsonp' || api.method === 'js') {
|
||||
if (
|
||||
!api.data &&
|
||||
((!~raw.indexOf('$') && autoAppend) || api.forceAppendDataToQuery)
|
||||
) {
|
||||
api.query = api.data = data;
|
||||
api.data = data;
|
||||
api.query = {
|
||||
...api.query,
|
||||
...data
|
||||
};
|
||||
} else if (
|
||||
api.attachDataToQuery === false &&
|
||||
api.data &&
|
||||
@ -194,12 +219,13 @@ export function buildApi(
|
||||
if (~idx) {
|
||||
let params = (api.query = {
|
||||
...qsparse(api.url.substring(idx + 1)),
|
||||
...api.query,
|
||||
...data
|
||||
});
|
||||
api.url = api.url.substring(0, idx) + '?' + qsstringify(params);
|
||||
api.url = api.url.substring(0, idx) + '?' + queryStringify(params);
|
||||
} else {
|
||||
api.query = data;
|
||||
const query = qsstringify(data);
|
||||
api.query = {...api.query, ...data};
|
||||
const query = queryStringify(data);
|
||||
if (query) {
|
||||
api.url = `${api.url}?${query}`;
|
||||
}
|
||||
@ -211,12 +237,13 @@ export function buildApi(
|
||||
if (~idx) {
|
||||
let params = (api.query = {
|
||||
...qsparse(api.url.substring(idx + 1)),
|
||||
...api.query,
|
||||
...api.data
|
||||
});
|
||||
api.url = api.url.substring(0, idx) + '?' + qsstringify(params);
|
||||
api.url = api.url.substring(0, idx) + '?' + queryStringify(params);
|
||||
} else {
|
||||
api.query = api.data;
|
||||
const query = qsstringify(api.data);
|
||||
api.query = {...api.query, ...api.data};
|
||||
const query = queryStringify(api.query);
|
||||
if (query) {
|
||||
api.url = `${api.url}?${query}`;
|
||||
}
|
||||
@ -224,6 +251,22 @@ export function buildApi(
|
||||
delete api.data;
|
||||
}
|
||||
}
|
||||
// 非 get 类请求也可以携带参数到 url,只要 query 有值
|
||||
else if (api.method) {
|
||||
const idx = api.url.indexOf('?');
|
||||
if (~idx) {
|
||||
let params = (api.query = {
|
||||
...qsparse(api.url.substring(idx + 1)),
|
||||
...api.query
|
||||
});
|
||||
api.url = api.url.substring(0, idx) + '?' + queryStringify(params);
|
||||
} else {
|
||||
const query = queryStringify(api.query);
|
||||
if (query) {
|
||||
api.url = `${api.url}?${query}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (api.graphql) {
|
||||
if (api.method === 'get') {
|
||||
|
@ -5,7 +5,7 @@ export function getVariable(
|
||||
key: string | undefined,
|
||||
canAccessSuper: boolean = true
|
||||
): any {
|
||||
if (!data || !key) {
|
||||
if (!data || !key || typeof data !== 'object') {
|
||||
return undefined;
|
||||
} else if (canAccessSuper ? key in data : data.hasOwnProperty(key)) {
|
||||
return data[key];
|
||||
|
@ -21,7 +21,9 @@ export function normalizeOptions(
|
||||
|
||||
const option = {
|
||||
label: item,
|
||||
value: item
|
||||
// 添加 option 的 value 根据 valueField 来
|
||||
// 否则某些情况下多余字段会有影响
|
||||
[valueField]: item
|
||||
};
|
||||
|
||||
share.values.push(option.value);
|
||||
@ -41,10 +43,10 @@ export function normalizeOptions(
|
||||
|
||||
const option = {
|
||||
label: item,
|
||||
value: item
|
||||
[valueField]: item
|
||||
};
|
||||
|
||||
share.values.push(option.value);
|
||||
share.values.push(option[valueField]);
|
||||
share.options.push(option);
|
||||
|
||||
return option;
|
||||
@ -64,7 +66,7 @@ export function normalizeOptions(
|
||||
|
||||
const option = {
|
||||
...item,
|
||||
value
|
||||
[valueField]: value
|
||||
};
|
||||
|
||||
if (typeof option.children !== 'undefined') {
|
||||
@ -85,7 +87,7 @@ export function normalizeOptions(
|
||||
|
||||
const option = {
|
||||
label: (options as {[propName: string]: string})[key] as string,
|
||||
value: key
|
||||
[valueField]: key
|
||||
};
|
||||
|
||||
share.values.push(option.value);
|
||||
|
@ -18,6 +18,7 @@ import {ColumnProps} from './index';
|
||||
export interface Props extends ThemeProps, LocaleProps {
|
||||
column: ColumnProps;
|
||||
onSort?: Function;
|
||||
active?: boolean;
|
||||
classnames: ClassNamesFn;
|
||||
}
|
||||
|
||||
@ -36,31 +37,46 @@ export class HeadCellSort extends React.Component<Props, State> {
|
||||
};
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: Readonly<Props>): void {
|
||||
const props = this.props;
|
||||
// 失效后重置,同时只能有一列在排序
|
||||
if (
|
||||
props?.active !== undefined &&
|
||||
!props?.active &&
|
||||
props.active !== prevProps?.active
|
||||
) {
|
||||
this.setState({orderBy: '', order: ''});
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const {column, onSort, classnames: cx} = this.props;
|
||||
const {active, column, onSort, classnames: cx} = this.props;
|
||||
|
||||
return (
|
||||
<span
|
||||
className={cx('TableCell-sortBtn')}
|
||||
onClick={async () => {
|
||||
let sortPayload = {};
|
||||
let sortPayload: State = {
|
||||
orderBy: '',
|
||||
order: ''
|
||||
};
|
||||
if (column.name === this.state.orderBy) {
|
||||
if (this.state.order === 'descend') {
|
||||
if (this.state.order === 'desc') {
|
||||
// 降序改为取消
|
||||
sortPayload = {orderBy: '', order: 'ascend'};
|
||||
sortPayload = {orderBy: '', order: ''};
|
||||
} else {
|
||||
// 升序之后降序
|
||||
sortPayload = {order: 'descend'};
|
||||
sortPayload = {orderBy: column.name, order: 'desc'};
|
||||
}
|
||||
} else {
|
||||
// 默认先升序
|
||||
sortPayload = {orderBy: column.name, order: 'ascend'};
|
||||
sortPayload = {orderBy: column.name, order: 'asc'};
|
||||
}
|
||||
|
||||
if (onSort) {
|
||||
const prevented = await onSort({
|
||||
orderBy: this.state.orderBy,
|
||||
order: this.state.order
|
||||
orderBy: sortPayload.orderBy,
|
||||
order: sortPayload.order
|
||||
});
|
||||
if (prevented) {
|
||||
return;
|
||||
@ -73,9 +89,7 @@ export class HeadCellSort extends React.Component<Props, State> {
|
||||
<i
|
||||
className={cx(
|
||||
'TableCell-sortBtn--down',
|
||||
this.state.orderBy === column.name && this.state.order === 'descend'
|
||||
? 'is-active'
|
||||
: ''
|
||||
active && this.state.order === 'desc' ? 'is-active' : ''
|
||||
)}
|
||||
>
|
||||
<Icon icon="sort-desc" className="icon" />
|
||||
@ -83,9 +97,7 @@ export class HeadCellSort extends React.Component<Props, State> {
|
||||
<i
|
||||
className={cx(
|
||||
'TableCell-sortBtn--up',
|
||||
this.state.orderBy === column.name && this.state.order === 'ascend'
|
||||
? 'is-active'
|
||||
: ''
|
||||
active && this.state.order === 'asc' ? 'is-active' : ''
|
||||
)}
|
||||
>
|
||||
<Icon icon="sort-asc" className="icon" />
|
||||
@ -93,7 +105,7 @@ export class HeadCellSort extends React.Component<Props, State> {
|
||||
<i
|
||||
className={cx(
|
||||
'TableCell-sortBtn--default',
|
||||
this.state.orderBy === column.name ? '' : 'is-active'
|
||||
active ? '' : 'is-active'
|
||||
)}
|
||||
>
|
||||
<Icon icon="sort-default" className="icon" />
|
||||
|
@ -42,7 +42,7 @@ export interface ColumnProps {
|
||||
fixed?: boolean | string;
|
||||
width?: number | string;
|
||||
sorter?: (a: any, b: any) => number | boolean; // 设置为true时,执行onSort,否则执行前端排序
|
||||
sortOrder?: string; // 升序ascend、降序descend
|
||||
sortOrder?: string; // 升序asc、降序desc
|
||||
filters?: Array<any>; // 筛选数据源,配置了数据源才展示
|
||||
filterMode?: string; // menu/tree 默认menu 先只支持menu
|
||||
filterMultiple?: boolean; // 是否支持多选
|
||||
@ -173,6 +173,7 @@ export interface TableState {
|
||||
record: any;
|
||||
target: HTMLTableRowElement;
|
||||
} | null;
|
||||
sort?: SortProps;
|
||||
}
|
||||
|
||||
function getMaxLevelThRowSpan(columns: Array<ColumnProps>) {
|
||||
@ -1048,24 +1049,32 @@ export class Table extends React.PureComponent<TableProps, TableState> {
|
||||
sort = (
|
||||
<HeadCellSort
|
||||
column={item}
|
||||
onSort={
|
||||
onSort
|
||||
? onSort
|
||||
: (payload: SortProps) => {
|
||||
if (typeof item.sorter === 'function') {
|
||||
if (payload.orderBy) {
|
||||
const sortList = [...this.state.dataSource];
|
||||
this.setState({
|
||||
dataSource: sortList.sort(
|
||||
item.sorter as (a: any, b: any) => number
|
||||
)
|
||||
});
|
||||
} else {
|
||||
this.setState({dataSource: [...dataSource]});
|
||||
}
|
||||
}
|
||||
}
|
||||
active={
|
||||
this.state.sort?.orderBy &&
|
||||
this.state.sort.orderBy === item?.name
|
||||
}
|
||||
onSort={(payload: SortProps) => {
|
||||
this.setState({
|
||||
sort: payload
|
||||
});
|
||||
|
||||
if (onSort) {
|
||||
onSort(payload);
|
||||
} else {
|
||||
if (typeof item.sorter === 'function') {
|
||||
if (payload.orderBy) {
|
||||
const sortList = [...this.state.dataSource];
|
||||
this.setState({
|
||||
dataSource: sortList.sort(
|
||||
item.sorter as (a: any, b: any) => number
|
||||
)
|
||||
});
|
||||
} else {
|
||||
this.setState({dataSource: [...dataSource]});
|
||||
}
|
||||
}
|
||||
}
|
||||
}}
|
||||
></HeadCellSort>
|
||||
);
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ import {ListSchema} from './List';
|
||||
import {TableSchema2} from './Table2';
|
||||
import {isPureVariable, resolveVariableAndFilter} from 'amis-core';
|
||||
import {SchemaCollection} from '../Schema';
|
||||
import {upperFirst} from 'lodash';
|
||||
import upperFirst from 'lodash/upperFirst';
|
||||
|
||||
export type CRUDRendererEvent = 'search';
|
||||
|
||||
@ -425,9 +425,12 @@ export default class CRUD2 extends React.Component<CRUD2Props, any> {
|
||||
replaceQuery?: boolean;
|
||||
}) {
|
||||
const {store, syncLocation, env, pageField, perPageField} = this.props;
|
||||
let {query, resetQuery, replaceQuery} = data;
|
||||
let {query, resetQuery, replaceQuery} = data || {};
|
||||
|
||||
query = syncLocation ? qsparse(qsstringify(query, undefined, true)) : query;
|
||||
query =
|
||||
syncLocation && query
|
||||
? qsparse(qsstringify(query, undefined, true))
|
||||
: query;
|
||||
|
||||
store.updateQuery(
|
||||
resetQuery ? this.props.store.pristineQuery : query,
|
||||
@ -917,7 +920,7 @@ export default class CRUD2 extends React.Component<CRUD2Props, any> {
|
||||
doAction(action: Action, data: object, throwErrors: boolean = false) {
|
||||
if (
|
||||
action.actionType &&
|
||||
~['stopAutoRefresh', 'reload', 'search', 'startAutoRefresh'].includes(
|
||||
['stopAutoRefresh', 'reload', 'search', 'startAutoRefresh'].includes(
|
||||
action.actionType
|
||||
)
|
||||
) {
|
||||
@ -1159,14 +1162,14 @@ export default class CRUD2 extends React.Component<CRUD2Props, any> {
|
||||
: undefined,
|
||||
keepItemSelectionOnPageChange,
|
||||
maxKeepItemSelectionLength,
|
||||
valueField: valueField || primaryField,
|
||||
// valueField: valueField || primaryField,
|
||||
primaryField: primaryField,
|
||||
items: store.data.items,
|
||||
query: store.query,
|
||||
orderBy: store.query.orderBy,
|
||||
orderDir: store.query.orderDir,
|
||||
popOverContainer,
|
||||
onSave: this.handleSave,
|
||||
onSave: this.handleSave.bind(this),
|
||||
onSaveOrder: this.handleSaveOrder,
|
||||
onSearch: this.handleTableQuery,
|
||||
onSort: this.handleTableQuery,
|
||||
|
@ -73,6 +73,8 @@ export class HeadCellSearchDropDown extends React.Component<
|
||||
? searchable.controls.concat()
|
||||
: undefined
|
||||
};
|
||||
} else if (searchable?.type === 'form') {
|
||||
schema = searchable;
|
||||
} else {
|
||||
schema = {
|
||||
title: '',
|
||||
@ -128,6 +130,8 @@ export class HeadCellSearchDropDown extends React.Component<
|
||||
...schema,
|
||||
type: 'form',
|
||||
wrapperComponent: 'div',
|
||||
wrapWithPanel: true,
|
||||
title: false,
|
||||
actions: [
|
||||
{
|
||||
type: 'button',
|
||||
|
@ -579,7 +579,9 @@ export default class Table2 extends React.Component<Table2Props, object> {
|
||||
// table2的拆开了 就不需要再设置div的width了
|
||||
// 否则加上padding 就超出单元格的区域了
|
||||
// children属性在schema里是一个关键字 在渲染器schema中 自定义的children没有用 去掉
|
||||
const {width, children, ...rest} = schema;
|
||||
|
||||
// title 需要去掉,否则部分组件会将其渲染出来
|
||||
const {width, children, title, ...rest} = schema;
|
||||
return render(
|
||||
'cell-field',
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user