From 968a7ec80f35894a0cc1f4a63ee3f56116fbb7f5 Mon Sep 17 00:00:00 2001 From: Semmy Date: Sun, 27 Feb 2022 01:49:56 +0800 Subject: [PATCH] feat: filter component finish --- .../hooks/useCollectionField.ts | 1 + .../schema-component/antd/calendar/Filter.tsx | 60 ++++--------- .../antd/calendar/demos/demo3.tsx | 36 +++++--- .../schema-component/antd/calendar/utils.ts | 52 +++++------ .../antd/filter/Filter.Action.tsx | 86 +++++++++++++++++++ .../antd/filter/Filter.DynamicValue.tsx | 61 +++++++++++++ .../schema-component/antd/filter/Filter.tsx | 75 ++-------------- .../schema-component/antd/filter/context.ts | 8 ++ .../src/schema-component/antd/filter/hooks.ts | 9 ++ .../antd/icon-picker/IconPicker.tsx | 1 + 10 files changed, 240 insertions(+), 149 deletions(-) create mode 100644 packages/client/src/schema-component/antd/filter/Filter.Action.tsx create mode 100644 packages/client/src/schema-component/antd/filter/Filter.DynamicValue.tsx create mode 100644 packages/client/src/schema-component/antd/filter/context.ts create mode 100644 packages/client/src/schema-component/antd/filter/hooks.ts diff --git a/packages/client/src/collection-manager/hooks/useCollectionField.ts b/packages/client/src/collection-manager/hooks/useCollectionField.ts index 10771ee27..4d7c51f4d 100644 --- a/packages/client/src/collection-manager/hooks/useCollectionField.ts +++ b/packages/client/src/collection-manager/hooks/useCollectionField.ts @@ -16,6 +16,7 @@ export const useCollectionField = () => { } const resourceName = `${ctx?.collectionName || collection?.name}.${ctx.name}`; const resource = api?.resource(resourceName, record[ctx.sourceKey]); + debugger; return { ...ctx, uiSchema: compile(ctx.uiSchema), diff --git a/packages/client/src/schema-component/antd/calendar/Filter.tsx b/packages/client/src/schema-component/antd/calendar/Filter.tsx index 437868425..8299b2258 100644 --- a/packages/client/src/schema-component/antd/calendar/Filter.tsx +++ b/packages/client/src/schema-component/antd/calendar/Filter.tsx @@ -1,14 +1,12 @@ -import { FormButtonGroup, Submit } from '@formily/antd'; import { createForm } from '@formily/core'; -import { FormProvider, observer, useFieldSchema } from '@formily/react'; -import { Button, Popover } from 'antd'; +import { observer, useFieldSchema } from '@formily/react'; import flatten from 'flat'; import React, { useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { SchemaComponent } from '../../core'; import { useDesignable } from '../../hooks'; import { useCompile } from '../../hooks/useCompile'; -import { IconPicker } from '../icon-picker'; +import { FilterContext } from '../filter/context'; export const Filter = observer((props: any) => { const { t } = useTranslation(); @@ -25,45 +23,19 @@ export const Filter = observer((props: any) => { properties[p.name] = p; }); return ( - - - - - { - const { filter } = form.values; - console.log('Table.Filter', form.values); - setVisible(false); - }} - > - {t('Submit')} - - - - - } - > - - + + + ); }); diff --git a/packages/client/src/schema-component/antd/calendar/demos/demo3.tsx b/packages/client/src/schema-component/antd/calendar/demos/demo3.tsx index 22389a530..1b949d102 100644 --- a/packages/client/src/schema-component/antd/calendar/demos/demo3.tsx +++ b/packages/client/src/schema-component/antd/calendar/demos/demo3.tsx @@ -7,6 +7,7 @@ import { uid } from '@formily/shared'; import { AntdSchemaComponentProvider, CollectionField, + CollectionManagerProvider, CollectionProvider, SchemaComponent, SchemaComponentProvider, @@ -56,6 +57,13 @@ const schema = { 'x-action': 'calendar:viewSelect', 'x-align': 'right', }, + filter: { + type: 'void', + title: '过滤', + 'x-align': 'right', + 'x-component': 'Calendar.Filter', + 'x-action': 'calendar:filter', + }, }, }, event: { @@ -98,9 +106,9 @@ const collection = { type: 'string', name: 'id', interface: 'input', + title: 'id', uiSchema: { type: 'string', - title: 'id', 'x-component': 'Input', }, }, @@ -108,9 +116,9 @@ const collection = { type: 'string', name: 'title', interface: 'input', + title: '标题', uiSchema: { type: 'string', - title: '标题', 'x-component': 'Input', }, }, @@ -118,9 +126,9 @@ const collection = { type: 'string', name: 'start', interface: 'datetime', + title: '开始时间', uiSchema: { type: 'string', - title: '开始时间', 'x-component': 'DatePicker', 'x-component-props': { dateFormat: 'YYYY-MM-DD', @@ -131,9 +139,9 @@ const collection = { type: 'string', name: 'end', interface: 'datetime', + title: '结束时间', uiSchema: { type: 'string', - title: '结束时间', 'x-component': 'DatePicker', 'x-component-props': { dateFormat: 'YYYY-MM-DD', @@ -144,14 +152,16 @@ const collection = { }; export default () => { return ( - - - - - - - - - + + + + + + + + + + + ); }; diff --git a/packages/client/src/schema-component/antd/calendar/utils.ts b/packages/client/src/schema-component/antd/calendar/utils.ts index 255eb53d1..46887cf6d 100644 --- a/packages/client/src/schema-component/antd/calendar/utils.ts +++ b/packages/client/src/schema-component/antd/calendar/utils.ts @@ -2,33 +2,33 @@ import { get } from 'lodash'; import { i18n } from '../../../i18n'; export const fieldsToFilterColumns = (fields: any[], options: any = {}) => { - // const { fieldNames = [] } = options; - // const properties = {}; - // fields.forEach((field, index) => { - // if (fieldNames?.length && !fieldNames.includes(field.name)) { - // return; - // } - // const fieldOption = interfaces.get(field.interface); - // if (!fieldOption?.operations) { - // return; - // } - // properties[`column${index}`] = { - // type: 'void', - // title: field?.uiSchema?.title, - // 'x-component': 'Filter.Column', - // 'x-component-props': { - // operations: fieldOption.operations, + // const { fieldNames = [] } = options; + // const properties = {}; + // fields.forEach((field, index) => { + // if (fieldNames?.length && !fieldNames.includes(field.name)) { + // return; + // } + // const fieldOption = interfaces.get(field.interface); + // if (!fieldOption?.operations) { + // return; + // } + // properties[`column${index}`] = { + // type: 'void', + // title: field?.uiSchema?.title, + // 'x-component': 'Filter.Column', + // 'x-component-props': { + // operations: fieldOption.operations, + // }, + // properties: { + // [field.name]: { + // ...field.uiSchema, + // 'x-decorator': 'FormilyFormItem', + // title: null, // }, - // properties: { - // [field.name]: { - // ...field.uiSchema, - // 'x-decorator': 'FormilyFormItem', - // title: null, - // }, - // }, - // }; - // }); - // return properties; + // }, + // }; + // }); + // return properties; }; export const toEvents = (data: any[], fieldNames: any) => { diff --git a/packages/client/src/schema-component/antd/filter/Filter.Action.tsx b/packages/client/src/schema-component/antd/filter/Filter.Action.tsx new file mode 100644 index 000000000..4eedfc1c1 --- /dev/null +++ b/packages/client/src/schema-component/antd/filter/Filter.Action.tsx @@ -0,0 +1,86 @@ +import { FilterOutlined } from '@ant-design/icons'; +import { FormButtonGroup, Submit } from '@formily/antd'; +import { createForm } from '@formily/core'; +import { FieldContext, FormContext, observer, useFieldSchema } from '@formily/react'; +import { uid } from '@formily/shared'; +import { Button, Popover } from 'antd'; +import flatten from 'flat'; +import React, { useMemo } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useCollection, useCollectionManager } from '../../../collection-manager'; +import { SchemaComponent } from '../../core'; +import { useDesignable } from '../../hooks'; +import { useCompile } from '../../hooks/useCompile'; +import { useFilterContext } from './hooks'; + +export const FilterAction = observer((props: any) => { + const { t } = useTranslation(); + const compile = useCompile(); + const { DesignableBar } = useDesignable(); + const filedSchema = useFieldSchema(); + const form = useMemo(() => createForm(), []); + const { visible, setVisible } = useFilterContext(); + const obj = flatten(form.values.filter || {}); + const count = Object.values(obj).filter((i) => (Array.isArray(i) ? i.length : i)).length; + const { fields } = useCollection(); + const { getInterface } = useCollectionManager(); + const properties = {}; + fields?.forEach((field) => { + const { operators } = getInterface(field.interface); + properties[uid()] = { + type: 'void', + title: field?.uiSchema?.title ?? field.title, + 'x-component': 'Filter.Column', + 'x-component-props': { + operations: [...operators], + }, + properties: { + [field.name ?? uid()]: { ...field?.uiSchema }, + }, + }; + }); + const schema = { + type: 'void', + properties: { + filter: { + type: 'array', + 'x-component': 'Filter', + properties, + }, + }, + }; + return ( + + + + + + { + const { filter } = form.values; + console.log('Table.Filter====', form.values); + debugger; + setVisible(false); + }} + > + {t('Submit')} + + + + + + } + > + + + ); +}); diff --git a/packages/client/src/schema-component/antd/filter/Filter.DynamicValue.tsx b/packages/client/src/schema-component/antd/filter/Filter.DynamicValue.tsx new file mode 100644 index 000000000..09b1e1673 --- /dev/null +++ b/packages/client/src/schema-component/antd/filter/Filter.DynamicValue.tsx @@ -0,0 +1,61 @@ +import { createForm, onFieldValueChange } from '@formily/core'; +import type { ISchema, Schema } from '@formily/react'; +import { connect } from '@formily/react'; +import deepmerge from 'deepmerge'; +import React, { useMemo } from 'react'; +import { SchemaComponent } from '../../core'; + +interface DynamicValueProps { + value?: any; + onChange?: any; + schema?: Schema; + operation?: any; +} + +export const FilterDynamicValue = connect((props: DynamicValueProps) => { + const { onChange, value, operation } = props; + const fieldName = Object.keys(props?.schema?.properties || {}).shift() ?? 'value'; + const fieldSchema = Object.values(props?.schema?.properties || {}).shift(); + const form = useMemo( + () => + createForm({ + initialValues: { + [fieldName]: value, + }, + effects(form) { + onFieldValueChange(fieldName, (field) => { + onChange(field.value); + }); + }, + }), + [], + ); + const extra: ISchema = deepmerge( + { + required: false, + 'x-read-pretty': false, + name: fieldName, + default: value, + 'x-decorator': 'FormilyFormItem', + 'x-decorator-props': { + asterisk: true, + feedbackLayout: 'none', + }, + 'x-component-props': { + style: { + minWidth: '150px', + }, + }, + }, + operation?.schema || {}, + ); + const schema = { + type: 'object', + properties: { + [fieldName]: deepmerge(fieldSchema, extra, { + arrayMerge: (target, source) => source, + }) as any, + }, + }; + return ; +}); diff --git a/packages/client/src/schema-component/antd/filter/Filter.tsx b/packages/client/src/schema-component/antd/filter/Filter.tsx index 00644b5b5..fd5a577e5 100644 --- a/packages/client/src/schema-component/antd/filter/Filter.tsx +++ b/packages/client/src/schema-component/antd/filter/Filter.tsx @@ -1,14 +1,15 @@ import { LoadingOutlined } from '@ant-design/icons'; -import { createForm, onFieldValueChange } from '@formily/core'; -import { connect, FieldContext, FormContext, ISchema, mapProps, mapReadPretty, Schema } from '@formily/react'; -import deepmerge from 'deepmerge'; -import React, { useMemo } from 'react'; -import { SchemaComponent } from '../../core'; +import { connect, mapProps, mapReadPretty } from '@formily/react'; +import React from 'react'; +import { FilterAction } from './Filter.Action'; +import { FilterDynamicValue } from './Filter.DynamicValue'; import { FilterGroup } from './FilterGroup'; import './style.less'; export const Filter: any = connect( - (props) => , + (props) => { + return ; + }, mapProps((props, field) => { return { ...props, @@ -20,65 +21,7 @@ export const Filter: any = connect( }), ); -interface DynamicValueProps { - value?: any; - onChange?: any; - schema?: Schema; - operation?: any; -} - -Filter.DynamicValue = connect((props: DynamicValueProps) => { - const { onChange, value, operation } = props; - const fieldName = Object.keys(props?.schema?.properties || {}).shift() ?? 'value'; - const fieldSchema = Object.values(props?.schema?.properties || {}).shift(); - const form = useMemo( - () => - createForm({ - initialValues: { - [fieldName]: value, - }, - effects(form) { - onFieldValueChange(fieldName, (field) => { - onChange(field.value); - }); - }, - }), - [], - ); - const extra: ISchema = deepmerge( - { - required: false, - 'x-read-pretty': false, - name: fieldName, - default: value, - 'x-decorator': 'FormilyFormItem', - 'x-decorator-props': { - asterisk: true, - feedbackLayout: 'none', - }, - 'x-component-props': { - style: { - minWidth: '150px', - }, - }, - }, - operation?.schema || {}, - ); - const schema = { - type: 'object', - properties: { - [fieldName]: deepmerge(fieldSchema, extra, { - arrayMerge: (target, source) => source, - }) as any, - }, - }; - return ( - - - - - - ); -}); +Filter.DynamicValue = FilterDynamicValue; +Filter.Action = FilterAction; export default Filter; diff --git a/packages/client/src/schema-component/antd/filter/context.ts b/packages/client/src/schema-component/antd/filter/context.ts new file mode 100644 index 000000000..25ac6b27a --- /dev/null +++ b/packages/client/src/schema-component/antd/filter/context.ts @@ -0,0 +1,8 @@ +import { createContext } from 'react'; + +export const FilterContext = createContext({}); + +export interface FilterContextProps { + visible?: boolean; + setVisible?: (v: boolean) => void; +} diff --git a/packages/client/src/schema-component/antd/filter/hooks.ts b/packages/client/src/schema-component/antd/filter/hooks.ts new file mode 100644 index 000000000..3f7798d17 --- /dev/null +++ b/packages/client/src/schema-component/antd/filter/hooks.ts @@ -0,0 +1,9 @@ +import { useContext } from 'react'; +import { FilterContext } from './context'; + +export const useFilterContext = () => { + const ctx = useContext(FilterContext); + return { + ...ctx, + }; +}; diff --git a/packages/client/src/schema-component/antd/icon-picker/IconPicker.tsx b/packages/client/src/schema-component/antd/icon-picker/IconPicker.tsx index 8dcd882bd..bf1935b95 100644 --- a/packages/client/src/schema-component/antd/icon-picker/IconPicker.tsx +++ b/packages/client/src/schema-component/antd/icon-picker/IconPicker.tsx @@ -65,6 +65,7 @@ export const IconPicker = connect( mapProps((props, field) => { return { ...props, + value: props.type, suffix: {field?.['loading'] || field?.['validating'] ? : props.suffix}, }; }),