DrawerSelect, Filter ...
This commit is contained in:
parent
9cc5363f49
commit
d39a7d822d
@ -30,7 +30,6 @@ import { Checkbox } from '../checkbox';
|
|||||||
import { ColorSelect } from '../color-select';
|
import { ColorSelect } from '../color-select';
|
||||||
import { DatabaseField } from '../database-field';
|
import { DatabaseField } from '../database-field';
|
||||||
import { DatePicker } from '../date-picker';
|
import { DatePicker } from '../date-picker';
|
||||||
import { DrawerSelect } from '../drawer-select';
|
|
||||||
import { Filter } from '../filter';
|
import { Filter } from '../filter';
|
||||||
import { Form } from '../form';
|
import { Form } from '../form';
|
||||||
import { Grid } from '../grid';
|
import { Grid } from '../grid';
|
||||||
@ -97,7 +96,6 @@ export const components = {
|
|||||||
ColorSelect,
|
ColorSelect,
|
||||||
DatabaseField,
|
DatabaseField,
|
||||||
DatePicker,
|
DatePicker,
|
||||||
DrawerSelect,
|
|
||||||
Filter,
|
Filter,
|
||||||
Form,
|
Form,
|
||||||
Grid,
|
Grid,
|
||||||
|
@ -116,13 +116,13 @@ const BaseAction = observer((props: any) => {
|
|||||||
const { run } = useAction();
|
const { run } = useAction();
|
||||||
const { DesignableBar } = useDesignableBar();
|
const { DesignableBar } = useDesignableBar();
|
||||||
const { setVisible } = useVisibleContext();
|
const { setVisible } = useVisibleContext();
|
||||||
// const schema = useFieldSchema();
|
const fieldSchema = useFieldSchema();
|
||||||
const { schema } = useDesignable();
|
const { schema } = useDesignable();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
field.componentProps.setVisible = setVisible;
|
field.componentProps.setVisible = setVisible;
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
console.log('BaseAction', { field, schema }, field.title);
|
console.log('BaseAction', { field, schema, fieldSchema }, field.title);
|
||||||
|
|
||||||
const renderButton = () => (
|
const renderButton = () => (
|
||||||
<ButtonComponent
|
<ButtonComponent
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
---
|
|
||||||
title: DrawerSelect - 抽屉选择器
|
|
||||||
nav:
|
|
||||||
title: 组件
|
|
||||||
path: /client
|
|
||||||
group:
|
|
||||||
order: 1
|
|
||||||
title: Schemas
|
|
||||||
path: /client/schemas
|
|
||||||
---
|
|
||||||
|
|
||||||
# DrawerSelect - 抽屉选择器
|
|
@ -1,135 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { connect, mapProps, mapReadPretty } from '@formily/react';
|
|
||||||
import { Select, Tag } from 'antd';
|
|
||||||
import { LoadingOutlined } from '@ant-design/icons';
|
|
||||||
import Drawer from '../../components/Drawer';
|
|
||||||
import { useRequest } from 'ahooks';
|
|
||||||
import { isArr, isValid } from '@formily/shared';
|
|
||||||
|
|
||||||
function getFieldName(field: any) {
|
|
||||||
if (typeof field === 'string') {
|
|
||||||
return field;
|
|
||||||
}
|
|
||||||
if (typeof field === 'object') {
|
|
||||||
return field.name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const DrawerSelect = connect(
|
|
||||||
(props) => {
|
|
||||||
const {
|
|
||||||
value,
|
|
||||||
dataRequest,
|
|
||||||
labelField: lf,
|
|
||||||
valueField: vf,
|
|
||||||
renderTag,
|
|
||||||
renderOptions,
|
|
||||||
onChange,
|
|
||||||
...others
|
|
||||||
} = props;
|
|
||||||
const labelField = getFieldName(lf);
|
|
||||||
const valueField = getFieldName(vf);
|
|
||||||
const getValues = () => {
|
|
||||||
if (!isValid(value)) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
return isArr(value) ? value : [value];
|
|
||||||
}
|
|
||||||
const getOptionValue = () => {
|
|
||||||
const values = getValues().map((item) => {
|
|
||||||
return {
|
|
||||||
value: item[valueField],
|
|
||||||
label: item[labelField],
|
|
||||||
};
|
|
||||||
});
|
|
||||||
if (props.mode === 'multiple' || props.mode === 'tags') {
|
|
||||||
return values;
|
|
||||||
}
|
|
||||||
return values.length ? values[0] : null;
|
|
||||||
};
|
|
||||||
return (
|
|
||||||
<Select
|
|
||||||
{...others}
|
|
||||||
labelInValue
|
|
||||||
open={false}
|
|
||||||
value={getOptionValue()}
|
|
||||||
options={[]}
|
|
||||||
onChange={(selectValue) => {
|
|
||||||
const getSelectValue = () => {
|
|
||||||
const selected = isArr(selectValue) ? selectValue : [selectValue];
|
|
||||||
return selected.map((item: any) => item.value);
|
|
||||||
}
|
|
||||||
const selected = getSelectValue();
|
|
||||||
const values = getValues().filter(item => {
|
|
||||||
return selected.includes(item[valueField]);
|
|
||||||
});
|
|
||||||
onChange(values);
|
|
||||||
}}
|
|
||||||
onClick={(e) => {
|
|
||||||
Drawer.open({
|
|
||||||
title: '选择数据',
|
|
||||||
content: (contentProps) => {
|
|
||||||
return renderOptions ? renderOptions({ ...contentProps, onChange }) : null;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
mapProps((props, field) => {
|
|
||||||
return {
|
|
||||||
...props,
|
|
||||||
suffix: (
|
|
||||||
<span>
|
|
||||||
{field?.['loading'] || field?.['validating'] ? (
|
|
||||||
<LoadingOutlined />
|
|
||||||
) : (
|
|
||||||
props.suffix
|
|
||||||
)}
|
|
||||||
</span>
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
mapReadPretty((props) => {
|
|
||||||
const {
|
|
||||||
value,
|
|
||||||
dataRequest,
|
|
||||||
labelField: lf,
|
|
||||||
valueField: vf,
|
|
||||||
renderItem,
|
|
||||||
renderTag,
|
|
||||||
...others
|
|
||||||
} = props;
|
|
||||||
const labelField = getFieldName(lf);
|
|
||||||
const valueField = getFieldName(vf);
|
|
||||||
const getValues = () => {
|
|
||||||
if (!isValid(value)) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
return isArr(value) ? value : [value];
|
|
||||||
}
|
|
||||||
const values = getValues();
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
{values.map((item) => (
|
|
||||||
<a
|
|
||||||
onClick={() => {
|
|
||||||
Drawer.open({
|
|
||||||
title: item[labelField],
|
|
||||||
content: (contentProps) => {
|
|
||||||
return renderItem
|
|
||||||
? renderItem({ ...contentProps, item })
|
|
||||||
: null;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{renderTag ? renderTag(item) : item[labelField]}
|
|
||||||
</a>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
export default DrawerSelect;
|
|
@ -1,7 +1,7 @@
|
|||||||
import React, { useMemo, useState } from 'react';
|
import React, { useContext, useMemo, useState } from 'react';
|
||||||
import { SchemaField } from '..';
|
import { SchemaField } from '..';
|
||||||
import { createForm, onFieldChange, onFieldReact } from '@formily/core'
|
import { createForm, onFieldChange, onFieldReact } from '@formily/core';
|
||||||
import { FormProvider, FormConsumer } from '@formily/react'
|
import { FormProvider, FormConsumer, useFieldSchema, Schema, SchemaOptionsContext, ISchema } from '@formily/react';
|
||||||
import { Field } from '@formily/core/esm/models/Field';
|
import { Field } from '@formily/core/esm/models/Field';
|
||||||
import { Form } from '@formily/core/esm/models/Form';
|
import { Form } from '@formily/core/esm/models/Form';
|
||||||
import {
|
import {
|
||||||
@ -11,105 +11,127 @@ import {
|
|||||||
FormButtonGroup,
|
FormButtonGroup,
|
||||||
Submit,
|
Submit,
|
||||||
Space,
|
Space,
|
||||||
} from '@formily/antd'
|
} from '@formily/antd';
|
||||||
import { CloseCircleOutlined } from '@ant-design/icons'
|
import { CloseCircleOutlined } from '@ant-design/icons';
|
||||||
|
import { get } from 'lodash';
|
||||||
|
|
||||||
|
function useFilterColumns(): Schema[] {
|
||||||
|
const schema = useFieldSchema();
|
||||||
|
const columns = schema.reduceProperties((columns, current) => {
|
||||||
|
if (current['x-component'] === 'Filter.Column') {
|
||||||
|
return [...columns, current];
|
||||||
|
}
|
||||||
|
return [...columns];
|
||||||
|
}, []);
|
||||||
|
return columns;
|
||||||
|
}
|
||||||
|
|
||||||
export const FilterItem = (props) => {
|
export const FilterItem = (props) => {
|
||||||
const { initialValues = {}, fields, onRemove } = props;
|
const { initialValues = {}, onRemove } = props;
|
||||||
|
|
||||||
|
const options = useContext(SchemaOptionsContext);
|
||||||
|
|
||||||
const { key } = initialValues;
|
const { key } = initialValues;
|
||||||
|
const columns = useFilterColumns();
|
||||||
|
console.log('useFilterColumns', columns);
|
||||||
|
|
||||||
|
const Remove = (props) => {
|
||||||
|
return (
|
||||||
|
onRemove && (
|
||||||
|
<a onClick={() => onRemove()}>
|
||||||
|
<CloseCircleOutlined />
|
||||||
|
</a>
|
||||||
|
)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getComponent = (column: ISchema) => {
|
||||||
|
const field = Object.values(column.properties).shift();
|
||||||
|
return field ? get(options.components, field['x-component']) : null;
|
||||||
|
}
|
||||||
|
|
||||||
const form = useMemo(
|
const form = useMemo(
|
||||||
() =>
|
() =>
|
||||||
createForm({
|
createForm({
|
||||||
initialValues,
|
initialValues,
|
||||||
effects: (form) => {
|
effects: (form) => {
|
||||||
onFieldChange('key', (field: Field, form: Form) => {
|
onFieldChange('column', (field: Field, form: Form) => {
|
||||||
form.setFieldState('value', state => {
|
const column = (field.value || {}) as ISchema;
|
||||||
state.value = null;
|
const operations = column?.['x-component-props']?.['operations']||[];
|
||||||
|
field.query('operation').take((f: Field) => {
|
||||||
|
f.setDataSource(operations);
|
||||||
|
f.initialValue = get(operations, [0]);
|
||||||
|
});
|
||||||
|
field.query('value').take((f: Field) => {
|
||||||
|
f.value = null;
|
||||||
|
const component = getComponent(column);
|
||||||
|
console.log({ component });
|
||||||
|
f.setComponent(component, {});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
onFieldReact('op', (field: Field) => {
|
onFieldReact('operation', (field: Field) => {
|
||||||
const key = field.query('key').get('value');
|
console.log('operation', field.value);
|
||||||
const schema = fields.find(field => field.name === key) || {};
|
const operation = field.value || {};
|
||||||
if (schema['x-operations']) {
|
field.query('value').take((f: Field) => {
|
||||||
field.value = schema['x-operations'][0].value;
|
f.visible = !operation.noValue;
|
||||||
field.dataSource = schema['x-operations'].map(item => ({
|
});
|
||||||
label: item.label,
|
|
||||||
value: item.value,
|
|
||||||
}));
|
|
||||||
console.log({key, schema}, schema['x-operations'][0].value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
onFieldReact('value', (field: Field, form: Form) => {
|
|
||||||
const key = field.query('key').get('value');
|
|
||||||
const op = field.query('op').get('value');
|
|
||||||
const schema = fields.find(field => field.name === key) || {};
|
|
||||||
if (schema['x-operations']) {
|
|
||||||
const operation = schema['x-operations'].find(operation => operation.value === op)
|
|
||||||
field.visible = operation.noValue ? false : true;
|
|
||||||
} else {
|
|
||||||
field.visible = true;
|
|
||||||
}
|
|
||||||
// field.setComponent(getFieldComponent(schema['x-component']));
|
|
||||||
// field.visible = opValue ? !opValue.noValue : true;
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
[],
|
[],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FormProvider form={form}>
|
<FormProvider form={form}>
|
||||||
<FormLayout layout={'inline'}>
|
<FormLayout layout={'inline'}>
|
||||||
<SchemaField>
|
<SchemaField components={{ Remove }}>
|
||||||
<SchemaField.Void
|
<SchemaField.Void x-component="Space">
|
||||||
x-decorator="FormItem"
|
|
||||||
x-decorator-props={{
|
|
||||||
asterisk: true,
|
|
||||||
feedbackLayout: 'none',
|
|
||||||
addonAfter: onRemove && (
|
|
||||||
<a onClick={() => onRemove()}><CloseCircleOutlined/></a>
|
|
||||||
),
|
|
||||||
}}
|
|
||||||
x-component="Space"
|
|
||||||
>
|
|
||||||
<SchemaField.String
|
<SchemaField.String
|
||||||
name="key"
|
name="column"
|
||||||
x-decorator="FormItem"
|
x-decorator="FormItem"
|
||||||
x-component="Select"
|
x-decorator-props={{
|
||||||
x-reactions={[
|
asterisk: true,
|
||||||
|
feedbackLayout: 'none',
|
||||||
]}
|
}}
|
||||||
|
x-component="Select.Object"
|
||||||
|
x-reactions={[]}
|
||||||
x-component-props={{
|
x-component-props={{
|
||||||
style: {
|
style: {
|
||||||
width: 100,
|
width: 100,
|
||||||
},
|
},
|
||||||
|
fieldNames: {
|
||||||
|
label: 'title',
|
||||||
|
value: 'name',
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
enum={fields.map(field => ({
|
enum={columns.map((column) => column.toJSON())}
|
||||||
label: field.title,
|
|
||||||
value: field.name,
|
|
||||||
}))}
|
|
||||||
required
|
|
||||||
/>
|
/>
|
||||||
<SchemaField.String
|
<SchemaField.String
|
||||||
name="op"
|
name="operation"
|
||||||
x-decorator="FormItem"
|
x-decorator="FormItem"
|
||||||
x-component="Select"
|
x-decorator-props={{
|
||||||
|
asterisk: true,
|
||||||
|
feedbackLayout: 'none',
|
||||||
|
}}
|
||||||
|
x-component="Select.Object"
|
||||||
x-component-props={{
|
x-component-props={{
|
||||||
style: {
|
style: {
|
||||||
width: 100,
|
width: 100,
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
enum={[]}
|
enum={[]}
|
||||||
required
|
|
||||||
/>
|
/>
|
||||||
<SchemaField.String
|
<SchemaField.String
|
||||||
name="value"
|
name="value"
|
||||||
x-decorator="FormItem"
|
x-decorator="FormItem"
|
||||||
|
x-decorator-props={{
|
||||||
|
asterisk: true,
|
||||||
|
feedbackLayout: 'none',
|
||||||
|
}}
|
||||||
x-component="Input"
|
x-component="Input"
|
||||||
required
|
|
||||||
/>
|
/>
|
||||||
|
<SchemaField.Void x-component="Remove" />
|
||||||
</SchemaField.Void>
|
</SchemaField.Void>
|
||||||
</SchemaField>
|
</SchemaField>
|
||||||
</FormLayout>
|
</FormLayout>
|
||||||
@ -122,6 +144,6 @@ export const FilterItem = (props) => {
|
|||||||
</FormConsumer> */}
|
</FormConsumer> */}
|
||||||
</FormProvider>
|
</FormProvider>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default FilterItem;
|
export default FilterItem;
|
||||||
|
@ -1,83 +0,0 @@
|
|||||||
import React, { createContext, useContext, useEffect } from 'react';
|
|
||||||
import { connect, mapProps, mapReadPretty } from '@formily/react';
|
|
||||||
import { CloseCircleOutlined } from '@ant-design/icons';
|
|
||||||
import { useDynamicList } from 'ahooks';
|
|
||||||
import { Select } from 'antd';
|
|
||||||
import { FilterItem } from './FilterItem';
|
|
||||||
import './style.less';
|
|
||||||
|
|
||||||
export const FilterSourceFieldsContext = createContext([]);
|
|
||||||
export const FilterTargetFieldsContext = createContext([]);
|
|
||||||
|
|
||||||
export function Group(props) {
|
|
||||||
const { onRemove } = props;
|
|
||||||
return (
|
|
||||||
<div className={'filter-group'}>
|
|
||||||
{onRemove && (
|
|
||||||
<a onClick={() => onRemove()}>
|
|
||||||
<CloseCircleOutlined />
|
|
||||||
</a>
|
|
||||||
)}
|
|
||||||
<div style={{ marginBottom: 14 }}>
|
|
||||||
满足组内{' '}
|
|
||||||
<Select
|
|
||||||
style={{ width: 80 }}
|
|
||||||
onChange={value => {
|
|
||||||
}}
|
|
||||||
defaultValue={'and'}
|
|
||||||
>
|
|
||||||
<Select.Option value={'and'}>全部</Select.Option>
|
|
||||||
<Select.Option value={'or'}>任意</Select.Option>
|
|
||||||
</Select>{' '}
|
|
||||||
条件
|
|
||||||
</div>
|
|
||||||
<List
|
|
||||||
initialValue={[{}]}
|
|
||||||
onChange={(list) => {
|
|
||||||
console.log({ list });
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function List(props) {
|
|
||||||
const { initialValue } = props;
|
|
||||||
const { list, push, remove } = useDynamicList<any>(initialValue || []);
|
|
||||||
useEffect(() => {
|
|
||||||
props.onChange && props.onChange(list);
|
|
||||||
}, [list]);
|
|
||||||
const fields = useContext(FilterSourceFieldsContext);
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
{list.map((item, index) => {
|
|
||||||
if (item.type === 'group') {
|
|
||||||
return <Group key={index} onRemove={() => remove(index)} />;
|
|
||||||
}
|
|
||||||
return <FilterItem key={index} fields={fields} onRemove={() => remove(index)} />;
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
<a
|
|
||||||
onClick={() => {
|
|
||||||
push({
|
|
||||||
type: 'item',
|
|
||||||
key: new Date().toTimeString(),
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
添加条件
|
|
||||||
</a>{' '}
|
|
||||||
<a
|
|
||||||
onClick={() => {
|
|
||||||
push({
|
|
||||||
type: 'group',
|
|
||||||
key: new Date().toTimeString(),
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
添加条件组
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
@ -8,3 +8,66 @@ group:
|
|||||||
title: Schemas
|
title: Schemas
|
||||||
path: /client/schemas
|
path: /client/schemas
|
||||||
---
|
---
|
||||||
|
|
||||||
|
<!-- <Filter>
|
||||||
|
<Filter.Column title={'字段1'} operations={[]}>
|
||||||
|
<Input/>
|
||||||
|
</Filter.Column>
|
||||||
|
<Filter.Column title={'字段2'}>
|
||||||
|
<Input/>
|
||||||
|
</Filter.Column>
|
||||||
|
</Filter> -->
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import React from 'react';
|
||||||
|
import { SchemaRenderer } from '../';
|
||||||
|
|
||||||
|
const schema = {
|
||||||
|
name: 'filter',
|
||||||
|
type: 'object',
|
||||||
|
'x-component': 'Filter',
|
||||||
|
properties: {
|
||||||
|
column1: {
|
||||||
|
type: 'void',
|
||||||
|
title: '字段1',
|
||||||
|
'x-component': 'Filter.Column',
|
||||||
|
'x-component-props': {
|
||||||
|
operations: [
|
||||||
|
{ label: '等于', value: 'eq' },
|
||||||
|
{ label: '不等于', value: 'ne' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
field1: {
|
||||||
|
type: 'string',
|
||||||
|
'x-component': 'Input',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
column2: {
|
||||||
|
type: 'void',
|
||||||
|
title: '字段2',
|
||||||
|
'x-component': 'Filter.Column',
|
||||||
|
'x-component-props': {
|
||||||
|
operations: [
|
||||||
|
{ label: '大于', value: 'gt' },
|
||||||
|
{ label: '小于', value: 'lt' },
|
||||||
|
{ label: '非空', value: 'notNull', noValue: true },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
field1: {
|
||||||
|
type: 'number',
|
||||||
|
'x-component': 'InputNumber',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
return (
|
||||||
|
<SchemaRenderer schema={schema} />
|
||||||
|
);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
@ -1,16 +1,93 @@
|
|||||||
import React, { useEffect } from 'react'
|
import React, { useEffect } from 'react';
|
||||||
import { connect, mapProps, mapReadPretty, useFieldSchema } from '@formily/react'
|
import {
|
||||||
import { LoadingOutlined } from '@ant-design/icons'
|
connect,
|
||||||
|
mapProps,
|
||||||
|
mapReadPretty,
|
||||||
|
} from '@formily/react';
|
||||||
|
import { LoadingOutlined } from '@ant-design/icons';
|
||||||
import { useDynamicList } from 'ahooks';
|
import { useDynamicList } from 'ahooks';
|
||||||
import { Group, FilterSourceFieldsContext } from './Group'
|
import { Select } from 'antd';
|
||||||
|
import { CloseCircleOutlined } from '@ant-design/icons';
|
||||||
|
import { FilterItem } from './FilterItem';
|
||||||
|
import './style.less';
|
||||||
|
|
||||||
|
export function FilterGroup(props) {
|
||||||
|
const { onRemove } = props;
|
||||||
|
return (
|
||||||
|
<div className={'nb-filter-group'}>
|
||||||
|
{onRemove && (
|
||||||
|
<a className={'nb-filter-group-close'} onClick={() => onRemove()}>
|
||||||
|
<CloseCircleOutlined />
|
||||||
|
</a>
|
||||||
|
)}
|
||||||
|
<div style={{ marginBottom: 14 }}>
|
||||||
|
满足组内{' '}
|
||||||
|
<Select
|
||||||
|
style={{ width: 80 }}
|
||||||
|
onChange={(value) => {}}
|
||||||
|
defaultValue={'and'}
|
||||||
|
>
|
||||||
|
<Select.Option value={'and'}>全部</Select.Option>
|
||||||
|
<Select.Option value={'or'}>任意</Select.Option>
|
||||||
|
</Select>{' '}
|
||||||
|
条件
|
||||||
|
</div>
|
||||||
|
<FilterList
|
||||||
|
initialValue={[{}]}
|
||||||
|
onChange={(list) => {
|
||||||
|
console.log({ list });
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function FilterList(props) {
|
||||||
|
const { initialValue } = props;
|
||||||
|
const { list, push, remove } = useDynamicList<any>(initialValue || []);
|
||||||
|
useEffect(() => {
|
||||||
|
props.onChange && props.onChange(list);
|
||||||
|
}, [list]);
|
||||||
|
return (
|
||||||
|
<div className={'nb-filter-list'}>
|
||||||
|
<div>
|
||||||
|
{list.map((item, index) => {
|
||||||
|
if (item.type === 'group') {
|
||||||
|
return <FilterGroup key={index} onRemove={() => remove(index)} />;
|
||||||
|
}
|
||||||
|
return <FilterItem key={index} onRemove={() => remove(index)} />;
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
<a
|
||||||
|
onClick={() => {
|
||||||
|
push({
|
||||||
|
type: 'item',
|
||||||
|
key: new Date().toTimeString(),
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
添加条件
|
||||||
|
</a>{' '}
|
||||||
|
<a
|
||||||
|
onClick={() => {
|
||||||
|
push({
|
||||||
|
type: 'group',
|
||||||
|
key: new Date().toTimeString(),
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
添加条件组
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export const Filter = connect(
|
export const Filter = connect(
|
||||||
(props) => {
|
(props) => {
|
||||||
const schema = useFieldSchema();
|
|
||||||
return (
|
return (
|
||||||
<FilterSourceFieldsContext.Provider value={schema['x-source-fields']}>
|
<div>
|
||||||
<Group/>
|
<FilterGroup />
|
||||||
</FilterSourceFieldsContext.Provider>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
mapProps((props, field) => {
|
mapProps((props, field) => {
|
||||||
@ -25,12 +102,11 @@ export const Filter = connect(
|
|||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
),
|
),
|
||||||
}
|
};
|
||||||
}),
|
}),
|
||||||
mapReadPretty((props) => {
|
mapReadPretty((props) => {
|
||||||
return null;
|
return null;
|
||||||
})
|
}),
|
||||||
)
|
);
|
||||||
|
|
||||||
export default Filter;
|
export default Filter;
|
||||||
|
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
.filter-group {
|
.nb-filter-group {
|
||||||
position: relative;
|
position: relative;
|
||||||
margin-bottom: 14px;
|
margin-bottom: 14px;
|
||||||
padding: 14px;
|
padding: 14px;
|
||||||
border: 1px dashed rgb(222, 222, 222);
|
border: 1px dashed rgb(222, 222, 222);
|
||||||
|
&-close {
|
||||||
|
position: absolute;
|
||||||
|
right: 10px;
|
||||||
|
}
|
||||||
}
|
}
|
@ -362,7 +362,7 @@ export default () => {
|
|||||||
```tsx
|
```tsx
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { SchemaRenderer } from '../';
|
import { SchemaRenderer } from '../';
|
||||||
import { useSelect } from './';
|
import { useSelect, useOptionTagValues } from './';
|
||||||
|
|
||||||
console.log({ useSelect })
|
console.log({ useSelect })
|
||||||
|
|
||||||
@ -519,9 +519,15 @@ const schema = {
|
|||||||
form: {
|
form: {
|
||||||
type: 'void',
|
type: 'void',
|
||||||
'x-component': 'Form',
|
'x-component': 'Form',
|
||||||
|
'x-component-props': {
|
||||||
|
useValues: '{{ useOptionTagValues }}',
|
||||||
|
},
|
||||||
properties: {
|
properties: {
|
||||||
input: {
|
title: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
|
title: '标题',
|
||||||
|
'x-read-pretty': true,
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
'x-component': 'Input',
|
'x-component': 'Input',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -535,7 +541,7 @@ const schema = {
|
|||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
return (
|
return (
|
||||||
<SchemaRenderer scope={{ useSelect, useValues }} schema={schema} />
|
<SchemaRenderer scope={{ useSelect, useValues, useOptionTagValues }} schema={schema} />
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
@ -17,7 +17,7 @@ import { useState } from 'react';
|
|||||||
import { useDesignable } from '../DesignableSchemaField';
|
import { useDesignable } from '../DesignableSchemaField';
|
||||||
import { createContext } from 'react';
|
import { createContext } from 'react';
|
||||||
import { useContext } from 'react';
|
import { useContext } from 'react';
|
||||||
import { useTableContext } from '../table';
|
import { SelectedRowKeysContext, useTableContext } from '../table';
|
||||||
|
|
||||||
export const Select: any = connect(
|
export const Select: any = connect(
|
||||||
(props) => {
|
(props) => {
|
||||||
@ -128,8 +128,9 @@ Select.Object = connect(
|
|||||||
{...others}
|
{...others}
|
||||||
value={optionValue}
|
value={optionValue}
|
||||||
onChange={(selectValue: any) => {
|
onChange={(selectValue: any) => {
|
||||||
if (!selectValue) {
|
if (!isValid(selectValue)) {
|
||||||
onChange(null);
|
onChange(null);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if (isArr(selectValue)) {
|
if (isArr(selectValue)) {
|
||||||
const selectValues = selectValue.map((s) => s.value);
|
const selectValues = selectValue.map((s) => s.value);
|
||||||
@ -273,6 +274,10 @@ Select.Drawer = connect(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const selectedKeys = toArr(optionValue).map(item => item.value);
|
||||||
|
|
||||||
|
console.log({ selectedKeys })
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<AntdSelect
|
<AntdSelect
|
||||||
@ -300,23 +305,26 @@ Select.Drawer = connect(
|
|||||||
width={'50%'}
|
width={'50%'}
|
||||||
visible={visible}
|
visible={visible}
|
||||||
onClose={() => setVisible(false)}
|
onClose={() => setVisible(false)}
|
||||||
|
destroyOnClose
|
||||||
>
|
>
|
||||||
<SelectContext.Provider
|
<SelectedRowKeysContext.Provider value={selectedKeys}>
|
||||||
value={{
|
<SelectContext.Provider
|
||||||
onChange(selectValue) {
|
value={{
|
||||||
onFieldChange(selectValue);
|
onChange(selectValue) {
|
||||||
setVisible(false);
|
onFieldChange(selectValue);
|
||||||
},
|
setVisible(false);
|
||||||
}}
|
},
|
||||||
>
|
|
||||||
<RecursionField
|
|
||||||
onlyRenderProperties
|
|
||||||
schema={schema}
|
|
||||||
filterProperties={(s) => {
|
|
||||||
return s['x-component'] === 'Select.Options';
|
|
||||||
}}
|
}}
|
||||||
/>
|
>
|
||||||
</SelectContext.Provider>
|
<RecursionField
|
||||||
|
onlyRenderProperties
|
||||||
|
schema={schema}
|
||||||
|
filterProperties={(s) => {
|
||||||
|
return s['x-component'] === 'Select.Options';
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</SelectContext.Provider>
|
||||||
|
</SelectedRowKeysContext.Provider>
|
||||||
</Drawer>
|
</Drawer>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
@ -386,6 +394,11 @@ export function useSelect() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function useOptionTagValues() {
|
||||||
|
const { data } = useContext(OptionTagContext);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
Select.OptionTag = observer((props) => {
|
Select.OptionTag = observer((props) => {
|
||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
const { data, fieldNames } = useContext(OptionTagContext);
|
const { data, fieldNames } = useContext(OptionTagContext);
|
||||||
|
@ -240,7 +240,9 @@ export function useTableUpdateAction() {
|
|||||||
const [TableContextProvider, useTableContext] = constate(() => {
|
const [TableContextProvider, useTableContext] = constate(() => {
|
||||||
const field = useField<Formily.Core.Models.ArrayField>();
|
const field = useField<Formily.Core.Models.ArrayField>();
|
||||||
const schema = useFieldSchema();
|
const schema = useFieldSchema();
|
||||||
const [selectedRowKeys, setSelectedRowKeys] = useState([]);
|
const defaultSelectedRowKeys = useContext(SelectedRowKeysContext);
|
||||||
|
const [selectedRowKeys, setSelectedRowKeys] = useState(defaultSelectedRowKeys || []);
|
||||||
|
console.log({ defaultSelectedRowKeys })
|
||||||
const pagination = usePaginationProps();
|
const pagination = usePaginationProps();
|
||||||
const response = useRequest<{
|
const response = useRequest<{
|
||||||
list: any[];
|
list: any[];
|
||||||
@ -284,6 +286,8 @@ const [TableContextProvider, useTableContext] = constate(() => {
|
|||||||
|
|
||||||
export { TableContextProvider, useTableContext };
|
export { TableContextProvider, useTableContext };
|
||||||
|
|
||||||
|
export const SelectedRowKeysContext = createContext([]);
|
||||||
|
|
||||||
const TableContainer = observer((props) => {
|
const TableContainer = observer((props) => {
|
||||||
const field = useField<Formily.Core.Models.ArrayField>();
|
const field = useField<Formily.Core.Models.ArrayField>();
|
||||||
const schema = useFieldSchema();
|
const schema = useFieldSchema();
|
||||||
|
Loading…
Reference in New Issue
Block a user