From 2dbbe29223571100ee75147699812ce97fb94260 Mon Sep 17 00:00:00 2001 From: chenos Date: Sat, 12 Dec 2020 16:32:18 +0800 Subject: [PATCH] feat: improve filter action --- packages/app/src/api-client.ts | 18 +++- .../app/src/components/actions/Filter.tsx | 1 + .../components/form.fields/filter/index.tsx | 102 ++++++++++++------ .../src/components/views/Form/FilterForm.tsx | 19 ++-- .../app/src/components/views/SimpleTable.tsx | 16 ++- packages/app/src/components/views/Table.tsx | 16 ++- 6 files changed, 128 insertions(+), 44 deletions(-) diff --git a/packages/app/src/api-client.ts b/packages/app/src/api-client.ts index 1fc7c44cc..bd25be8a9 100644 --- a/packages/app/src/api-client.ts +++ b/packages/app/src/api-client.ts @@ -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); }; diff --git a/packages/app/src/components/actions/Filter.tsx b/packages/app/src/components/actions/Filter.tsx index 2706842c2..9dc00fd8e 100644 --- a/packages/app/src/components/actions/Filter.tsx +++ b/packages/app/src/components/actions/Filter.tsx @@ -42,6 +42,7 @@ export function Filter(props) {
setVisible(false)}>
diff --git a/packages/app/src/components/form.fields/filter/index.tsx b/packages/app/src/components/form.fields/filter/index.tsx index 8714583e5..2780e5b99 100644 --- a/packages/app/src/components/form.fields/filter/index.tsx +++ b/packages/app/src/components/form.fields/filter/index.tsx @@ -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 ( -
+
满足组内 {' '} @@ -32,7 +43,7 @@ export function FilterGroup(props: any) { // console.log(item); const Component = item.type === 'group' ? FilterGroup : FilterItem; return ( -
+
{
- - - {showDeleteButton && }
@@ -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 ( - + { onChange({...dataSource, value: value}); - }} style={{ width: '30%' }}/> + }} + style={{ width: 180 }} + /> {showDeleteButton && ( - + }}> )} - + ); } +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 + const { value, onChange, ...restProps } = props; + return { + onChange(toFilter(values)); + }} {...restProps}/> }); export default Filter; diff --git a/packages/app/src/components/views/Form/FilterForm.tsx b/packages/app/src/components/views/Form/FilterForm.tsx index 1588e14a6..efce9b17d 100644 --- a/packages/app/src/components/views/Form/FilterForm.tsx +++ b/packages/app/src/components/views/Form/FilterForm.tsx @@ -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 ( { + 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) { > 取消 - { - const { values = {} } = await actions.submit(); - console.log(values); - }}>确定 + 确定 ); diff --git a/packages/app/src/components/views/SimpleTable.tsx b/packages/app/src/components/views/SimpleTable.tsx index 26eb239a1..f8d4c3fdc 100644 --- a/packages/app/src/components/views/SimpleTable.tsx +++ b/packages/app/src/components/views/SimpleTable.tsx @@ -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(); 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); - } + }, }} /> { + run({...params[0], sorter}); + }} components={components({ data, mutate, diff --git a/packages/app/src/components/views/Table.tsx b/packages/app/src/components/views/Table.tsx index 53118599e..5d196677d 100644 --- a/packages/app/src/components/views/Table.tsx +++ b/packages/app/src/components/views/Table.tsx @@ -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,