feat: improve filter action
This commit is contained in:
parent
c776229540
commit
2dbbe29223
@ -28,8 +28,9 @@ class ApiClient {
|
||||
const proxy: any = new Proxy({}, {
|
||||
get(target, method, receiver) {
|
||||
return (params: ActionParams = {}) => {
|
||||
const { associatedKey, resourceKey, filter, ...restParams } = params;
|
||||
let { associatedKey, resourceKey, filter, sorter, sort = [], ...restParams } = params;
|
||||
let url = `/${name}`;
|
||||
sort = sort || [];
|
||||
let options: any = {
|
||||
params: {},
|
||||
};
|
||||
@ -51,6 +52,21 @@ class ApiClient {
|
||||
if (filter) {
|
||||
options.params['filter'] = JSON.stringify(filter);
|
||||
}
|
||||
if (sorter) {
|
||||
const arr = Array.isArray(sorter) ? sorter : [sorter];
|
||||
arr.forEach(({order, field}) => {
|
||||
if (order === 'descend') {
|
||||
sort.push(`-${field}`);
|
||||
} else if (order === 'ascend') {
|
||||
sort.push(field);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (sort.length === 0) {
|
||||
delete options.params['sort'];
|
||||
} else {
|
||||
options.params['sort'] = sort.join(',');
|
||||
}
|
||||
console.log({url, params});
|
||||
return request(url, options);
|
||||
};
|
||||
|
@ -42,6 +42,7 @@ export function Filter(props) {
|
||||
<div className={'popover-button-mask'} onClick={() => setVisible(false)}></div>
|
||||
<ViewFactory
|
||||
{...props}
|
||||
setVisible={setVisible}
|
||||
viewName={'filter'}
|
||||
{...params}
|
||||
/>
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Button, Select, Input, Space, Form, InputNumber, DatePicker } from 'antd';
|
||||
import { ArrowUpOutlined, ArrowDownOutlined } from '@ant-design/icons';
|
||||
import { PlusCircleOutlined, CloseCircleOutlined } from '@ant-design/icons';
|
||||
import useDynamicList from './useDynamicList';
|
||||
import { connect } from '@formily/react-schema-renderer'
|
||||
import { mapStyledProps } from '../shared'
|
||||
@ -13,8 +13,19 @@ export function FilterGroup(props: any) {
|
||||
type: 'item',
|
||||
},
|
||||
]);
|
||||
let style: any = {
|
||||
position: 'relative',
|
||||
};
|
||||
if (showDeleteButton) {
|
||||
style = {
|
||||
...style,
|
||||
marginBottom: 14,
|
||||
padding: 14,
|
||||
border: '1px dashed #dedede',
|
||||
}
|
||||
}
|
||||
return (
|
||||
<div style={{marginBottom: 14, padding: 14, border: '1px dashed #dedede'}}>
|
||||
<div style={style}>
|
||||
<div style={{marginBottom: 14}}>
|
||||
满足组内
|
||||
{' '}
|
||||
@ -32,7 +43,7 @@ export function FilterGroup(props: any) {
|
||||
// console.log(item);
|
||||
const Component = item.type === 'group' ? FilterGroup : FilterItem;
|
||||
return (
|
||||
<div style={{marginBottom: 14}}>
|
||||
<div style={{marginBottom: 8}}>
|
||||
{<Component
|
||||
fields={fields}
|
||||
dataSource={item}
|
||||
@ -58,7 +69,7 @@ export function FilterGroup(props: any) {
|
||||
</div>
|
||||
<div>
|
||||
<Space>
|
||||
<Button onClick={() => {
|
||||
<Button style={{padding: 0}} type={'link'} onClick={() => {
|
||||
const data = {
|
||||
type: 'item'
|
||||
};
|
||||
@ -67,28 +78,33 @@ export function FilterGroup(props: any) {
|
||||
newList.push(data);
|
||||
onChange({...dataSource, list: newList});
|
||||
}}>
|
||||
添加条件
|
||||
<PlusCircleOutlined /> 添加条件
|
||||
</Button>
|
||||
<Button onClick={() => {
|
||||
const data = {
|
||||
type: 'group',
|
||||
list: [
|
||||
{
|
||||
type: 'item',
|
||||
},
|
||||
],
|
||||
};
|
||||
push(data);
|
||||
const newList = [...list];
|
||||
newList.push(data);
|
||||
onChange({...dataSource, list: newList});
|
||||
}}>
|
||||
添加条件组
|
||||
{' '}
|
||||
<Button
|
||||
style={{padding: 0}}
|
||||
type={'link'}
|
||||
onClick={() => {
|
||||
const data = {
|
||||
type: 'group',
|
||||
list: [
|
||||
{
|
||||
type: 'item',
|
||||
},
|
||||
],
|
||||
};
|
||||
push(data);
|
||||
const newList = [...list];
|
||||
newList.push(data);
|
||||
onChange({...dataSource, list: newList});
|
||||
}}
|
||||
>
|
||||
<PlusCircleOutlined /> 添加条件组
|
||||
</Button>
|
||||
{showDeleteButton && <Button onClick={(e) => {
|
||||
{showDeleteButton && <Button style={{padding: 0, position: 'absolute', top: 0, right: 0, width: 32}} type={'link'} onClick={(e) => {
|
||||
onDelete && onDelete(e);
|
||||
}}>
|
||||
删除组
|
||||
<CloseCircleOutlined />
|
||||
</Button>}
|
||||
</Space>
|
||||
</div>
|
||||
@ -169,7 +185,9 @@ const op = {
|
||||
string: OP_MAP.string,
|
||||
textarea: OP_MAP.string,
|
||||
number: OP_MAP.number,
|
||||
percent: OP_MAP.number,
|
||||
datetime: OP_MAP.datetime,
|
||||
date: OP_MAP.datetime,
|
||||
};
|
||||
|
||||
const StringInput = (props) => {
|
||||
@ -186,7 +204,7 @@ const controls = {
|
||||
textarea: StringInput,
|
||||
number: InputNumber,
|
||||
// datetime: DatePicker,
|
||||
datetime: (props) => {
|
||||
date: (props) => {
|
||||
const { value, onChange, ...restProps } = props;
|
||||
const m = moment(value, 'YYYY-MM-DD HH:mm:ss');
|
||||
return (
|
||||
@ -204,14 +222,15 @@ export function FilterItem(props: FilterItemProps) {
|
||||
useEffect(() => {
|
||||
const field = fields.find(field => field.name === dataSource.column);
|
||||
if (field) {
|
||||
setType(field.interface);
|
||||
setType(field.component.type);
|
||||
}
|
||||
}, [
|
||||
dataSource,
|
||||
]);
|
||||
console.log({type});
|
||||
const ValueControl = controls[type]||controls.string;
|
||||
return (
|
||||
<Input.Group compact>
|
||||
<Space>
|
||||
<Select value={dataSource.column}
|
||||
onChange={(value) => {
|
||||
const field = fields.find(field => field.name === value);
|
||||
@ -220,7 +239,8 @@ export function FilterItem(props: FilterItemProps) {
|
||||
}
|
||||
onChange({...dataSource, column: value});
|
||||
}}
|
||||
style={{ width: '30%' }} placeholder={'选择字段'}>
|
||||
style={{ width: 120 }}
|
||||
placeholder={'选择字段'}>
|
||||
{fields.map(field => (
|
||||
<Select.Option value={field.name}>{field.title}</Select.Option>
|
||||
))}
|
||||
@ -236,16 +256,33 @@ export function FilterItem(props: FilterItemProps) {
|
||||
</Select>
|
||||
<ValueControl value={dataSource.value} onChange={(value) => {
|
||||
onChange({...dataSource, value: value});
|
||||
}} style={{ width: '30%' }}/>
|
||||
}}
|
||||
style={{ width: 180 }}
|
||||
/>
|
||||
{showDeleteButton && (
|
||||
<Button onClick={(e) => {
|
||||
<Button type={'link'} style={{padding: 0}} onClick={(e) => {
|
||||
onDelete && onDelete(e);
|
||||
}}>删除</Button>
|
||||
}}><CloseCircleOutlined /></Button>
|
||||
)}
|
||||
</Input.Group>
|
||||
</Space>
|
||||
);
|
||||
}
|
||||
|
||||
function toFilter(values: any) {
|
||||
let filter: any;
|
||||
const { type, andor = 'and', list = [], column, op, value } = values;
|
||||
if (type === 'group') {
|
||||
filter = {
|
||||
[andor]: list.map(value => toFilter(value)).filter(Boolean)
|
||||
}
|
||||
} else if (type === 'item' && column && op) {
|
||||
filter = {
|
||||
[`${column}`]: {[op]: value},
|
||||
}
|
||||
}
|
||||
return filter;
|
||||
}
|
||||
|
||||
export const Filter = connect({
|
||||
getProps: mapStyledProps,
|
||||
})((props) => {
|
||||
@ -257,7 +294,10 @@ export const Filter = connect({
|
||||
}
|
||||
],
|
||||
};
|
||||
return <FilterGroup dataSource={dataSource} {...props}/>
|
||||
const { value, onChange, ...restProps } = props;
|
||||
return <FilterGroup dataSource={dataSource} onChange={(values) => {
|
||||
onChange(toFilter(values));
|
||||
}} {...restProps}/>
|
||||
});
|
||||
|
||||
export default Filter;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { Tooltip, Card } from 'antd';
|
||||
import { Tooltip, Button } from 'antd';
|
||||
import {
|
||||
SchemaForm,
|
||||
SchemaMarkupField as Field,
|
||||
@ -15,7 +15,8 @@ import {
|
||||
import { QuestionCircleOutlined } from '@ant-design/icons';
|
||||
|
||||
export function FilterForm(props: any) {
|
||||
const actions = createFormActions();
|
||||
const actions = createAsyncFormActions();
|
||||
const { setVisible, onTrigger } = props;
|
||||
const { title, fields: properties ={} } = props.schema||{};
|
||||
return (
|
||||
<SchemaForm
|
||||
@ -23,6 +24,15 @@ export function FilterForm(props: any) {
|
||||
layout={'vertical'}
|
||||
initialValues={{}}
|
||||
actions={actions}
|
||||
onReset={() => {
|
||||
setVisible && setVisible(false);
|
||||
}}
|
||||
onSubmit={async (values) => {
|
||||
if (onTrigger) {
|
||||
await onTrigger(values);
|
||||
}
|
||||
setVisible && setVisible(false);
|
||||
}}
|
||||
schema={{
|
||||
type: 'object',
|
||||
properties,
|
||||
@ -44,10 +54,7 @@ export function FilterForm(props: any) {
|
||||
>
|
||||
<FormButtonGroup>
|
||||
<Reset>取消</Reset>
|
||||
<Submit onClick={async () => {
|
||||
const { values = {} } = await actions.submit();
|
||||
console.log(values);
|
||||
}}>确定</Submit>
|
||||
<Submit>确定</Submit>
|
||||
</FormButtonGroup>
|
||||
</SchemaForm>
|
||||
);
|
||||
|
@ -4,7 +4,6 @@ import { Actions } from '@/components/actions';
|
||||
import ViewFactory from '@/components/views';
|
||||
import { useRequest } from 'umi';
|
||||
import api from '@/api-client';
|
||||
import get from 'lodash/get';
|
||||
import { components, fields2columns } from './SortableTable';
|
||||
|
||||
export interface SimpleTableProps {
|
||||
@ -30,12 +29,13 @@ export function SimpleTable(props: SimpleTableProps) {
|
||||
const { sourceKey = 'id' } = activeTab.field||{};
|
||||
const drawerRef = useRef<any>();
|
||||
const name = associatedName ? `${associatedName}.${resourceName}` : resourceName;
|
||||
const { data, loading, pagination, mutate, refresh } = useRequest((params = {}) => {
|
||||
const { current, pageSize, ...restParams } = params;
|
||||
const { data, loading, pagination, mutate, refresh, params, run } = useRequest((params = {}) => {
|
||||
const { current, pageSize, sorter, ...restParams } = params;
|
||||
return api.resource(name).list({
|
||||
associatedKey,
|
||||
page: paginated ? current : 1,
|
||||
perPage: paginated ? pageSize : -1,
|
||||
sorter,
|
||||
})
|
||||
.then(({data = [], meta = {}}) => {
|
||||
return {
|
||||
@ -72,6 +72,11 @@ export function SimpleTable(props: SimpleTableProps) {
|
||||
refresh();
|
||||
}}
|
||||
onTrigger={{
|
||||
async filter(values) {
|
||||
console.log('filter', values);
|
||||
// @ts-ignore
|
||||
run({...params[0], filter: values.filter});
|
||||
},
|
||||
async destroy() {
|
||||
await api.resource(name).destroy({
|
||||
associatedKey,
|
||||
@ -81,7 +86,7 @@ export function SimpleTable(props: SimpleTableProps) {
|
||||
});
|
||||
await refresh();
|
||||
console.log('destroy.onTrigger', selectedRowKeys);
|
||||
}
|
||||
},
|
||||
}}
|
||||
/>
|
||||
<ViewFactory
|
||||
@ -98,6 +103,9 @@ export function SimpleTable(props: SimpleTableProps) {
|
||||
loading={loading}
|
||||
columns={fields2columns(fields)}
|
||||
dataSource={data?.list||(data as any)}
|
||||
onChange={(pagination, filters, sorter, extra) => {
|
||||
run({...params[0], sorter});
|
||||
}}
|
||||
components={components({
|
||||
data,
|
||||
mutate,
|
||||
|
@ -46,12 +46,16 @@ export function Table(props: TableProps) {
|
||||
// associatedKey,
|
||||
// }));
|
||||
const name = associatedName ? `${associatedName}.${resourceName}` : resourceName;
|
||||
const { data, loading, pagination, mutate, refresh } = useRequest((params = {}) => {
|
||||
const { current, pageSize, ...restParams } = params;
|
||||
const { data, loading, pagination, mutate, refresh, run, params } = useRequest((params = {}, ...args) => {
|
||||
const { current, pageSize, sorter, filter, ...restParams } = params;
|
||||
console.log('paramsparamsparamsparamsparams', params, args);
|
||||
return api.resource(name).list({
|
||||
associatedKey,
|
||||
page: paginated ? current : 1,
|
||||
perPage: paginated ? pageSize : -1,
|
||||
sorter,
|
||||
filter,
|
||||
// ...args2,
|
||||
})
|
||||
.then(({data = [], meta = {}}) => {
|
||||
return {
|
||||
@ -88,6 +92,11 @@ export function Table(props: TableProps) {
|
||||
refresh();
|
||||
}}
|
||||
onTrigger={{
|
||||
async filter(values) {
|
||||
// @ts-ignore
|
||||
run({...params[0], filter: values.filter});
|
||||
console.log('filter', values);
|
||||
},
|
||||
async destroy() {
|
||||
await api.resource(name).destroy({
|
||||
associatedKey,
|
||||
@ -104,6 +113,9 @@ export function Table(props: TableProps) {
|
||||
rowKey={rowKey}
|
||||
columns={fields2columns(fields)}
|
||||
dataSource={data?.list||(data as any)}
|
||||
onChange={(pagination, filters, sorter, extra) => {
|
||||
run({...params[0], sorter});
|
||||
}}
|
||||
components={components({
|
||||
data,
|
||||
mutate,
|
||||
|
Loading…
Reference in New Issue
Block a user