feat: improve code

This commit is contained in:
chenos 2021-08-30 18:27:39 +08:00
parent 10861d3c1c
commit 3c8c2d71e3
7 changed files with 242 additions and 41 deletions

View File

@ -3,8 +3,10 @@ import React from 'react';
import { FormItem } from '@formily/antd';
import { action } from '@formily/reactive';
import { useCollectionsContext } from '../../constate/Collections';
import { Field } from '@formily/core';
export const useAsyncDataSource = (service: any) => (field: any) => {
console.log('loadCollectionFields');
field.loading = true;
service(field).then(
action.bound((data: any) => {
@ -24,6 +26,22 @@ export default () => {
}));
};
const loadCollectionFields = async (field: Field) => {
const target = field.query('....target').get('value');
const f = field.query('....target').take();
console.log('loadCollectionFields', f, field);
const collection = collections?.find((item) => item.name === target);
if (!collection) {
return [];
}
return collection?.generalFields
?.filter((item) => item?.uiSchema?.title)
?.map((item) => ({
label: item?.uiSchema?.title || item.name,
value: item.name,
}));
};
const schema = {
type: 'array',
name: 'collections',
@ -56,7 +74,7 @@ export default () => {
};
return (
<SchemaRenderer
scope={{ loadCollections, useAsyncDataSource }}
scope={{ loadCollections, loadCollectionFields, useAsyncDataSource }}
components={{ FormItem }}
schema={schema}
/>

View File

@ -6,9 +6,14 @@ const [CollectionsProvider, useCollectionsContext] = constate(() => {
formatResult: (result) => result?.data,
});
return {
...result, collections: result.data || [], findCollection(name) {
...result, collections: result.data || [],
findCollection(name) {
return result?.data?.find((item) => item.name === name);
}
},
getFieldsByCollection(collectionName) {
const collection = result?.data?.find((item) => item.name === collectionName);
return collection?.generalFields;
},
};
});

View File

@ -1437,12 +1437,13 @@ AddNew.FormItem = observer((props: any) => {
default: [],
'x-component-props': {
rowKey: 'id',
defaultSelectedRowKeys:
'{{ Select.useSelectedRowKeys() }}',
useSelectedRowKeys:
'{{ Select.useSelectedRowKeys }}',
onSelect: '{{ Select.useSelect() }}',
useRowSelection: '{{ Select.useRowSelection }}',
collectionName: field.target,
// dragSort: true,
showIndex: true,
// showIndex: true,
refreshRequestOnChange: true,
pagination: {
pageSize: 10,

View File

@ -20,7 +20,7 @@ import {
updateSchema,
} from '../';
import get from 'lodash/get';
import { Button, Dropdown, Menu, Modal, Space, Switch } from 'antd';
import { Button, Dropdown, Menu, Modal, Select, Space, Switch } from 'antd';
import { MenuOutlined, DragOutlined } from '@ant-design/icons';
import cls from 'classnames';
import { FormDialog, FormLayout } from '@formily/antd';
@ -33,19 +33,25 @@ import { useEffect } from 'react';
import { uid } from '@formily/shared';
import { getSchemaPath } from '../../components/schema-renderer';
import { RandomNameContext } from '.';
import { useCollectionContext, useDisplayedMapContext } from '../../constate';
import {
useCollectionContext,
useCollectionsContext,
useDisplayedMapContext,
} from '../../constate';
import SwitchMenuItem from '../../components/SwitchMenuItem';
import { DragHandle } from '../../components/Sortable';
import { set } from 'lodash';
export const FieldDesignableBar = observer((props) => {
const field = useField();
const { schema, deepRemove } = useDesignable();
const { schema, deepRemove, refresh } = useDesignable();
const [visible, setVisible] = useState(false);
const { dragRef } = useContext(DraggableBlockContext);
const randomName = useContext(RandomNameContext);
const displayed = useDisplayedMapContext();
const fieldName = schema['x-component-props']?.['fieldName'];
const { getField } = useCollectionContext();
const { getFieldsByCollection } = useCollectionsContext();
const collectionField = getField(fieldName);
@ -124,6 +130,59 @@ export const FieldDesignableBar = observer((props) => {
>
</Menu.Item>
{collectionField.interface === 'linkTo' && (
<Menu.Item>
<div
style={{
display: 'flex',
justifyContent: 'space-between',
}}
>
{' '}
<Select
value={
schema?.['x-component-props']?.['fieldNames']?.[
'label'
]
}
placeholder={'默认为 ID 字段'}
onChange={async (value) => {
set(
schema['x-component-props'],
'fieldNames.label',
value,
);
refresh();
const fieldNames = {
label: value,
value:
get(
schema['x-component-props'],
'fieldNames.value',
) || 'id',
};
// realField.componentProps.fieldNames = fieldNames;
await updateSchema({
key: schema['key'],
'x-component-props': {
fieldNames,
},
});
// await service.refresh();
}}
bordered={false}
size={'small'}
style={{ marginLeft: 16, minWidth: 120 }}
options={getFieldsByCollection(collectionField.target)
.filter((f) => f?.uiSchema?.title)
.map((field) => ({
label: field?.uiSchema?.title || field.name,
value: field.name,
}))}
/>
</div>
</Menu.Item>
)}
<Menu.Item
style={{ minWidth: 150 }}
onClick={async () => {

View File

@ -29,7 +29,7 @@ import { DraggableBlockContext } from '../../components/drag-and-drop';
import { isGridRowOrCol } from '../grid';
import constate from 'constate';
import { useEffect } from 'react';
import { uid } from '@formily/shared';
import { uid, merge } from '@formily/shared';
import { getSchemaPath } from '../../components/schema-renderer';
import { DesignableBar } from './DesignableBar';
import { FieldDesignableBar } from './Field.DesignableBar';
@ -183,7 +183,15 @@ Form.Field = observer((props: any) => {
const required = schema['required'] || collectionField?.uiSchema?.required;
const description =
schema['description'] || collectionField?.uiSchema?.description;
console.log('schema.properties', schema.properties)
console.log('schema.properties', schema.properties);
const componentProps = merge(
collectionField?.uiSchema?.['x-component-props'] || {},
schema?.['x-component-props'] || {},
{
arrayMerge: (t, s) => s,
},
);
return (
<CollectionFieldContext.Provider value={collectionField}>
<RecursionField
@ -199,6 +207,7 @@ Form.Field = observer((props: any) => {
required,
description,
'x-decorator': 'FormilyFormItem',
'x-component-props': componentProps,
properties: {
...schema.properties,
},

View File

@ -18,7 +18,7 @@ import { useState } from 'react';
import { useDesignable } from '../';
import { createContext } from 'react';
import { useContext } from 'react';
import { isEmpty } from 'lodash';
import { get, isEmpty } from 'lodash';
import { Field, isArrayField, isField } from '@formily/core';
import { Action } from '../action';
import { BlockSchemaContext, VisibleContext } from '../../context';
@ -28,6 +28,7 @@ import { CollectionFieldContext } from '../table';
import { CollectionProvider, useCollectionContext } from '../../constate';
import { Resource } from '../../resource';
import { useRequest } from 'ahooks';
import constate from 'constate';
export const Select: any = connect(
(props) => {
@ -236,11 +237,11 @@ Select.Object = connect(
const OptionTagContext = createContext(null);
const SelectedRowKeysContext = createContext([]);
const SelectedRowsContext = createContext<any>(null);
Select.useOkAction = () => {
const { props } = useContext(SelectContext);
const [selectedRows] = useContext(SelectedRowKeysContext);
const { selectedRows } = useContext(SelectedRowsContext);
return {
async run() {
props.onChange(selectedRows);
@ -249,38 +250,63 @@ Select.useOkAction = () => {
};
};
Select.useRowSelection = () => {
const { props } = useContext(SelectContext);
return {
type: props.multiple ? 'checkbox' : 'radio',
};
};
Select.useSelect = () => {
const [, setSelectedRows] = useContext(SelectedRowKeysContext);
const { setSelectedRows } = useContext(SelectedRowsContext);
return (keys, rows) => {
setSelectedRows(rows);
console.log('Select.onSelect', keys, rows);
};
};
Select.useSelectedRowKeys = () => {
const [selectedRows] = useContext(SelectedRowKeysContext);
return selectedRows?.map((row) => row.id) || [];
export const useSelectedRowKeys = () => {
const { selectedRows } = useContext(SelectedRowsContext);
const [selectedRowKeys, setSelectedRowKeys] = useState<any>([]);
useEffect(() => {
setSelectedRowKeys(selectedRows.map((row) => row.id));
}, [selectedRows]);
return { selectedRowKeys, setSelectedRowKeys };
};
Select.useSelectedRowKeys = useSelectedRowKeys;
const SelectContext = createContext(null);
Select.Drawer = connect(
(props) => {
const field = useField<Field>();
const {
value,
onChange,
fieldNames = {
label: 'id',
value: 'id',
},
// fieldNames = {
// label: 'id',
// value: 'id',
// },
...others
} = props;
let value = props.value;
const [visible, setVisible] = useState(false);
const { schema } = useDesignable();
const fieldNames = {
label: 'id',
value: 'id',
...(get(schema['x-component-props'], 'fieldNames') || {}),
};
const options = field?.['dataSource'] || props.options || [];
if (props.multiple) {
Object.assign(others, {
mode: 'multiple',
});
}
let optionValue = undefined;
if (props.multiple) {
value = toArr(value);
}
if (isArr(value)) {
optionValue = value.map((val) => {
return {
@ -294,6 +320,7 @@ Select.Drawer = connect(
value: value[fieldNames.value],
};
}
const [selectedRows, setSelectedRows] = useState(toArr(field.value));
const onFieldChange = (selectValue) => {
if (!isValid(selectValue)) {
@ -323,9 +350,9 @@ Select.Drawer = connect(
options.find((option) => option[fieldNames.value] === selectValue),
);
}
setSelectedRows(toArr(field.value));
};
// const selectedKeys = toArr(optionValue).map((item) => item.value);
const [selectedRows, setSelectedRows] = useState(toArr(field.value));
console.log({ optionValue, value });
const collectionField = useContext(CollectionFieldContext);
return (
@ -352,8 +379,8 @@ Select.Drawer = connect(
}
}}
></AntdSelect>
<SelectedRowKeysContext.Provider
value={[selectedRows, setSelectedRows]}
<SelectedRowsContext.Provider
value={{ selectedRows, setSelectedRows }}
>
<CollectionProvider collectionName={collectionField?.target}>
<RecursionField
@ -364,7 +391,7 @@ Select.Drawer = connect(
}}
/>
</CollectionProvider>
</SelectedRowKeysContext.Provider>
</SelectedRowsContext.Provider>
</VisibleContext.Provider>
</SelectContext.Provider>
);
@ -391,9 +418,14 @@ Select.Drawer = connect(
observer((props: any) => {
const collectionField = useContext(CollectionFieldContext);
const field = useField<Formily.Core.Models.Field>();
const { fieldNames = { label: 'id' }, ...others } = props;
const { ...others } = props;
const value = field.value || field.initialValue;
const { schema } = useDesignable();
const fieldNames = {
label: 'id',
value: 'id',
...(get(schema['x-component-props'], 'fieldNames') || {}),
};
console.log({ fieldNames, field, value });
if (!value) {
return null;
@ -437,7 +469,7 @@ Select.Drawer.useResource = ({ onSuccess }) => {
resourceName: collection?.name,
resourceKey: ctx.data.id,
});
console.log('OptionTagContext', ctx.data.id)
console.log('OptionTagContext', ctx.data.id);
const { schema } = useDesignable();
const fieldFields = (schema: Schema) => {
const names = [];
@ -473,7 +505,7 @@ Select.Drawer.useResource = ({ onSuccess }) => {
}
}, [visible]);
return { resource, service, initialValues: service.data, ...service };
}
};
Select.Options = observer((props) => {
return <>{props.children}</>;

View File

@ -19,7 +19,7 @@ import {
createCollectionField,
ISchema,
} from '..';
import { uid } from '@formily/shared';
import { uid, merge } from '@formily/shared';
import useRequest from '@ahooksjs/use-request';
import { BaseResult } from '@ahooksjs/use-request/lib/types';
import cls from 'classnames';
@ -30,7 +30,6 @@ import {
useSortable,
verticalListSortingStrategy,
} from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';
import { Select, Dropdown, Menu, Switch, Button, Space } from 'antd';
import { PlusOutlined, SettingOutlined } from '@ant-design/icons';
import './style.less';
@ -54,6 +53,7 @@ import {
DisplayedMapProvider,
useCollection,
useCollectionContext,
useCollectionsContext,
useDisplayedMapContext,
} from '../../constate';
import { useResource as useGeneralResource } from '../../hooks/useResource';
@ -140,7 +140,7 @@ function useTableCreateAction() {
const form = useForm();
return {
async run() {
console.log('useTableCreateAction', resource)
console.log('useTableCreateAction', resource);
if (refreshRequestOnChange) {
await resource.create(form.values);
await form.reset();
@ -457,11 +457,13 @@ function AddColumn() {
default: [],
'x-component-props': {
rowKey: 'id',
defaultSelectedRowKeys: '{{ Select.useSelectedRowKeys() }}',
useRowSelection: '{{ Select.useRowSelection }}',
useSelectedRowKeys:
'{{ Select.useSelectedRowKeys }}',
onSelect: '{{ Select.useSelect() }}',
collectionName: field.target,
// dragSort: true,
showIndex: true,
// showIndex: true,
refreshRequestOnChange: true,
pagination: {
pageSize: 10,
@ -634,6 +636,12 @@ function AddColumn() {
);
}
const useDefaultRowSelection = () => {
return {
type: 'checkbox',
};
};
const useDataSource = () => {
const {
pagination,
@ -657,13 +665,20 @@ const TableMain = () => {
setSelectedRowKeys,
service,
field,
props: { rowKey, dragSort, showIndex, onSelect },
props: {
rowKey,
dragSort,
showIndex,
onSelect,
useRowSelection = useDefaultRowSelection,
},
refresh,
} = useTable();
const columns = useTableColumns();
const dataSource = useDataSource();
const actionBars = useTableActionBars();
const [html, setHtml] = useState('');
const { type } = useRowSelection();
return (
<div className={'nb-table'}>
<DndContext
@ -744,7 +759,7 @@ const TableMain = () => {
},
}}
rowSelection={{
type: 'checkbox',
type: type || 'checkbox',
selectedRowKeys,
onChange: (rowKeys, rows) => {
setSelectedRowKeys(rowKeys);
@ -815,20 +830,25 @@ const usePagination = () => {
];
};
const useDefaultSelectedRowKeys = () => {
const [selectedRowKeys, setSelectedRowKeys] = useState<any>([]);
return { selectedRowKeys, setSelectedRowKeys };
};
const TableProvider = (props: any) => {
const {
rowKey = 'id',
dataRequest,
useResource = useGeneralResource,
defaultSelectedRowKeys,
useSelectedRowKeys = useDefaultSelectedRowKeys,
...others
} = props;
const { schema } = useDesignable();
const field = useField<Formily.Core.Models.ArrayField>();
const [pagination, setPagination] = usePagination();
const [selectedRowKeys, setSelectedRowKeys] = useState<any>(
defaultSelectedRowKeys || [],
);
const { selectedRowKeys, setSelectedRowKeys } = useSelectedRowKeys();
console.log('props.useSelectedRowKeys', selectedRowKeys);
const [, refresh] = useState(uid());
const { resource } = useResource();
const { sortableField } = useCollectionContext();
@ -1968,6 +1988,14 @@ Table.Cell = observer((props: any) => {
uiSchema = cloneDeepWith(uiSchema);
set(uiSchema, 'x-component-props.size', 'small');
}
const componentProps = merge(
uiSchema?.['x-component-props'] || {},
schema?.['x-component-props'] || {},
{
arrayMerge: (t, s) => s,
},
);
console.log('Table.Cell', collectionField?.interface, componentProps);
return (
<div className={`field-interface-${collectionField?.interface}`}>
<RecursionField
@ -1985,6 +2013,7 @@ Table.Cell = observer((props: any) => {
feedbackLayout: 'popover',
},
'x-decorator': 'FormilyFormItem',
'x-component-props': componentProps,
properties: {
...schema?.properties,
},
@ -2018,10 +2047,12 @@ Table.Column = observer((props: any) => {
Table.Column.DesignableBar = () => {
const field = useField();
const { service, refresh: refreshTable } = useTable();
// const fieldSchema = useFieldSchema();
const { schema, remove, refresh, insertAfter } = useDesignable();
const [visible, setVisible] = useState(false);
const displayed = useDisplayedMapContext();
const { getFieldsByCollection } = useCollectionsContext();
const collectionField = useContext(CollectionFieldContext);
console.log('displayed.map', displayed.map);
return (
@ -2088,6 +2119,52 @@ Table.Column.DesignableBar = () => {
>
</Menu.Item>
{collectionField.interface === 'linkTo' && (
<Menu.Item>
<div
style={{
display: 'flex',
justifyContent: 'space-between',
}}
>
{' '}
<Select
value={
schema?.['x-component-props']?.['fieldNames']?.[
'label'
]
}
placeholder={'默认为 ID 字段'}
onChange={async (value) => {
set(
schema['x-component-props'],
'fieldNames.label',
value,
);
await updateSchema({
key: schema['key'],
'x-component-props': {
fieldNames: {
label: value,
},
},
});
refreshTable();
// await service.refresh();
}}
bordered={false}
size={'small'}
style={{ marginLeft: 16, minWidth: 120 }}
options={getFieldsByCollection(collectionField.target)
.filter((f) => f?.uiSchema?.title)
.map((field) => ({
label: field?.uiSchema?.title || field.name,
value: field.name,
}))}
/>
</div>
</Menu.Item>
)}
<Menu.Divider />
<Menu.Item
onClick={async () => {