fix: 修复表单快速添加和弹窗添加功能 (#1141)
Reviewed-on: daoyoucloud/tachybase#1141 Reviewed-by: sealday <zhanglin@daoyoucloud.com> Co-authored-by: wjh <wwwjh0710@163.com> Co-committed-by: wjh <wwwjh0710@163.com>
This commit is contained in:
parent
c2c0ec7724
commit
9d98941267
@ -6,7 +6,6 @@ import { Space } from 'antd-mobile';
|
|||||||
|
|
||||||
import { ApprovalReachDataType } from '../../component/ApprovalReachDataType';
|
import { ApprovalReachDataType } from '../../component/ApprovalReachDataType';
|
||||||
import { ApprovalTemplateType } from '../../component/ApprovalTemplateType';
|
import { ApprovalTemplateType } from '../../component/ApprovalTemplateType';
|
||||||
import { PendingStatus } from '../../constants';
|
|
||||||
import { useTodosContext } from '../provider/todosContext';
|
import { useTodosContext } from '../provider/todosContext';
|
||||||
import { TabApplicantType } from './TabApplicantType';
|
import { TabApplicantType } from './TabApplicantType';
|
||||||
import { TabApprovalItem } from './TabApprovalItem';
|
import { TabApprovalItem } from './TabApprovalItem';
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
import { createContext, useContext } from 'react';
|
|
||||||
|
|
||||||
export const AntdPopupContext = createContext({});
|
|
||||||
|
|
||||||
export const useAntdPopupContext = () => {
|
|
||||||
return useContext(AntdPopupContext);
|
|
||||||
};
|
|
@ -1,25 +1,27 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { observer, RecursionField, useField, useFieldSchema, useForm } from '@tachybase/schema';
|
import { observer, RecursionField, Schema, useField, useFieldSchema, useForm } from '@tachybase/schema';
|
||||||
|
|
||||||
import { Button, CheckList, Divider, Modal, PickerView, Popup, SearchBar, Space, Tag, Toast } from 'antd-mobile';
|
import { Button, CheckList, Divider, Modal, PickerView, Popup, SearchBar, Space, Tag, Toast } from 'antd-mobile';
|
||||||
|
|
||||||
import { MInput } from '../Input';
|
|
||||||
|
|
||||||
import './style';
|
import './style';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
BlockItem,
|
BlockItem,
|
||||||
CollectionProvider_deprecated,
|
CollectionProvider,
|
||||||
|
SchemaComponent,
|
||||||
useAPIClient,
|
useAPIClient,
|
||||||
|
useCollection,
|
||||||
|
useCollectionField,
|
||||||
useCollectionManager,
|
useCollectionManager,
|
||||||
useDesignable,
|
useDesignable,
|
||||||
useRequest,
|
useRequest,
|
||||||
} from '@tachybase/client';
|
} from '@tachybase/client';
|
||||||
import { isArray } from '@tachybase/utils/client';
|
import { isArray } from '@tachybase/utils/client';
|
||||||
|
|
||||||
|
import { getMobileColor } from '../../../CustomColor';
|
||||||
|
import { MobileProvider } from '../../../provider';
|
||||||
|
import { MInput } from '../Input';
|
||||||
import { CreateRecordAction } from './CreateRecordAction';
|
import { CreateRecordAction } from './CreateRecordAction';
|
||||||
import { useInsertSchema } from './hook/hooks';
|
|
||||||
import schema from './schema';
|
|
||||||
import { useStyles } from './style';
|
import { useStyles } from './style';
|
||||||
|
|
||||||
export const AntdSelect = observer((props) => {
|
export const AntdSelect = observer((props) => {
|
||||||
@ -30,13 +32,21 @@ export const AntdSelect = observer((props) => {
|
|||||||
const [options, setOptions] = useState([]);
|
const [options, setOptions] = useState([]);
|
||||||
const fieldSchema = useFieldSchema();
|
const fieldSchema = useFieldSchema();
|
||||||
const cm = useCollectionManager();
|
const cm = useCollectionManager();
|
||||||
const [visibleValue, setVisibleValue] = useState({});
|
const collection = useCollection();
|
||||||
const [filter, setFilter] = useState(service?.params?.filter);
|
const [filter, setFilter] = useState(service?.params?.filter);
|
||||||
const api = useAPIClient();
|
const api = useAPIClient();
|
||||||
const field = useField();
|
|
||||||
const { insertAfterBegin } = useDesignable();
|
|
||||||
const insertAddNewer = useInsertSchema('AddNewer', fieldSchema, insertAfterBegin);
|
|
||||||
const [selectValue, setSelectValue] = useState(value);
|
const [selectValue, setSelectValue] = useState(value);
|
||||||
|
const fieldNamesLabel = fieldNames?.label || 'label';
|
||||||
|
const fieldNamesValue = fieldNames?.value || 'value';
|
||||||
|
let inputValue = '';
|
||||||
|
if (isArray(value)) {
|
||||||
|
value.forEach((item, index) => {
|
||||||
|
inputValue += `${item.label}${value.length - 1 === index ? '' : ','}`;
|
||||||
|
});
|
||||||
|
} else if (value && typeof value === 'object') {
|
||||||
|
inputValue = value[fieldNamesLabel];
|
||||||
|
}
|
||||||
|
|
||||||
const { data, run } = useRequest(
|
const { data, run } = useRequest(
|
||||||
{
|
{
|
||||||
resource: collectionName,
|
resource: collectionName,
|
||||||
@ -57,8 +67,8 @@ export const AntdSelect = observer((props) => {
|
|||||||
const dataOption = data['data']?.map((value) => {
|
const dataOption = data['data']?.map((value) => {
|
||||||
return {
|
return {
|
||||||
...value,
|
...value,
|
||||||
label: value[fieldNames.label],
|
label: value[fieldNamesLabel],
|
||||||
value: value[fieldNames.value],
|
value: value[fieldNamesValue],
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
setOptions(dataOption);
|
setOptions(dataOption);
|
||||||
@ -71,13 +81,12 @@ export const AntdSelect = observer((props) => {
|
|||||||
} else {
|
} else {
|
||||||
const field = cm.getCollectionField(fieldSchema['x-collection-field']);
|
const field = cm.getCollectionField(fieldSchema['x-collection-field']);
|
||||||
const data = field.uiSchema?.enum;
|
const data = field.uiSchema?.enum;
|
||||||
setVisibleValue(data.find((item) => item.value === value) || '');
|
|
||||||
setOptions(data);
|
setOptions(data);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const addData = () => {
|
const addData = (data) => {
|
||||||
api
|
data[fieldNamesLabel] = api
|
||||||
.request({
|
.request({
|
||||||
url: collectionName + ':create',
|
url: collectionName + ':create',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
@ -96,7 +105,7 @@ export const AntdSelect = observer((props) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
const paramsFilter = { ...filter };
|
const paramsFilter = { ...filter };
|
||||||
delete paramsFilter[fieldNames.label];
|
delete paramsFilter[fieldNamesLabel];
|
||||||
setFilter(paramsFilter);
|
setFilter(paramsFilter);
|
||||||
setSearchValue('');
|
setSearchValue('');
|
||||||
setPopupVisible(false);
|
setPopupVisible(false);
|
||||||
@ -107,65 +116,34 @@ export const AntdSelect = observer((props) => {
|
|||||||
};
|
};
|
||||||
const quickAdd = () => {
|
const quickAdd = () => {
|
||||||
const data = {};
|
const data = {};
|
||||||
data[fieldNames.label] = searchValue;
|
data[fieldNamesLabel] = searchValue;
|
||||||
addData();
|
addData(data);
|
||||||
};
|
|
||||||
const modalAdd = () => {
|
|
||||||
const collectionField = cm.getCollectionField(fieldSchema['x-collection-field']);
|
|
||||||
// console.log('🚀 ~ modalAdd ~ collectionField:', collectionField);
|
|
||||||
const targetCollection = cm.getCollection(collectionField?.target);
|
|
||||||
|
|
||||||
// insertAddNewer(schema.AddNewer);
|
|
||||||
// const props = {
|
|
||||||
// fieldSchema,
|
|
||||||
// field,
|
|
||||||
// targetCollection,
|
|
||||||
// };
|
|
||||||
Modal.show({
|
|
||||||
content: (
|
|
||||||
<CollectionProvider_deprecated name={targetCollection?.name}>
|
|
||||||
<RecursionField
|
|
||||||
onlyRenderProperties
|
|
||||||
basePath={field.address}
|
|
||||||
schema={fieldSchema}
|
|
||||||
filterProperties={(s) => {
|
|
||||||
return s['x-component'] === 'AssociationField.AddNewer';
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</CollectionProvider_deprecated>
|
|
||||||
),
|
|
||||||
showCloseButton: true,
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
|
<CollectionProvider name={collectionName || collection.name}>
|
||||||
<BlockItem>
|
<BlockItem>
|
||||||
{!value || typeof value === 'object' ? (
|
|
||||||
<div
|
<div
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
if (fieldSchema['x-disabled']) return;
|
||||||
setPopupVisible(true);
|
setPopupVisible(true);
|
||||||
checkedPopup();
|
checkedPopup();
|
||||||
}}
|
}}
|
||||||
style={{ color: '#c5c5c5' }}
|
style={{ color: '#c5c5c5' }}
|
||||||
>
|
>
|
||||||
{isArray(value) && value.length ? (
|
{value?.length || (value && !isArray(value)) ? (
|
||||||
value.map((item, index) => (
|
<MInput value={inputValue} disabled={fieldSchema['x-disabled']} />
|
||||||
<Space key={index}>{`${item.label}${value.length - 1 === index ? '' : ','}`}</Space>
|
|
||||||
))
|
|
||||||
) : (
|
) : (
|
||||||
<Space>{value?.label || '请选择内容'}</Space>
|
<Space>{fieldSchema['x-disabled'] ? '' : '请选择内容'}</Space>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
|
||||||
<Tag color={'default'}>{value?.['label']}</Tag>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Popup visible={popupVisible} className={`${styles['PopupStyle']}`} closeOnMaskClick>
|
<Popup visible={popupVisible} className={`${styles['PopupStyle']}`} closeOnMaskClick>
|
||||||
|
<MobileProvider>
|
||||||
<SearchBar
|
<SearchBar
|
||||||
placeholder="请输入内容"
|
placeholder="请输入内容"
|
||||||
value={searchValue}
|
value={searchValue}
|
||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
const paramsFilter = { ...filter };
|
const paramsFilter = { ...filter };
|
||||||
paramsFilter[fieldNames.label] = { $includes: value };
|
paramsFilter[fieldNamesLabel] = { $includes: value };
|
||||||
setFilter(paramsFilter);
|
setFilter(paramsFilter);
|
||||||
setSearchValue(value);
|
setSearchValue(value);
|
||||||
}}
|
}}
|
||||||
@ -208,11 +186,17 @@ export const AntdSelect = observer((props) => {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<Space justify="evenly" align="center">
|
<Space justify="evenly" align="center">
|
||||||
{/* {addMode === 'modalAdd' ? (
|
{addMode === 'modalAdd' ? (
|
||||||
<Button color="primary" fill="outline" onClick={modalAdd}>
|
<SchemaComponent
|
||||||
添加
|
components={{ CreateRecordAction }}
|
||||||
</Button>
|
schema={{
|
||||||
) : null} */}
|
type: 'void',
|
||||||
|
name: 'CreateRecord',
|
||||||
|
'x-component': 'CreateRecordAction',
|
||||||
|
'x-component-props': { fieldSchema },
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
<Button
|
<Button
|
||||||
color="primary"
|
color="primary"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@ -231,7 +215,9 @@ export const AntdSelect = observer((props) => {
|
|||||||
确定
|
确定
|
||||||
</Button>
|
</Button>
|
||||||
</Space>
|
</Space>
|
||||||
|
</MobileProvider>
|
||||||
</Popup>
|
</Popup>
|
||||||
</BlockItem>
|
</BlockItem>
|
||||||
|
</CollectionProvider>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -1,29 +1,55 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import {
|
import { css, SchemaComponentOptions, useApp, useCollection } from '@tachybase/client';
|
||||||
CollectionProvider,
|
import { observer, RecursionField, useField, useFieldSchema } from '@tachybase/schema';
|
||||||
CollectionProvider_deprecated,
|
|
||||||
useActionContext,
|
|
||||||
useCollectionManager,
|
|
||||||
useCollectionManager_deprecated,
|
|
||||||
} from '@tachybase/client';
|
|
||||||
import { RecursionField } from '@tachybase/schema';
|
|
||||||
|
|
||||||
import { useInsertSchema } from './hook/hooks';
|
import { Button, CenterPopup, Modal, Popup } from 'antd-mobile';
|
||||||
import schema from './schema';
|
|
||||||
|
|
||||||
export const CreateRecordAction = ({ field, fieldSchema, targetCollection }) => {
|
import { MobileProvider } from '../../../provider';
|
||||||
const [currentCollection, setCurrentCollection] = useState(targetCollection?.name);
|
|
||||||
const [currentDataSource, setCurrentDataSource] = useState(targetCollection?.dataSource);
|
export const CreateRecordAction = observer(
|
||||||
|
(props) => {
|
||||||
|
const { fieldSchema } = props as any;
|
||||||
|
|
||||||
|
const [visible, setVisible] = useState(false);
|
||||||
|
const addNew = fieldSchema.reduceProperties((buf, schema) => {
|
||||||
|
const found = schema.reduceProperties((buf, schema) => {
|
||||||
|
if (schema['x-component'] === 'AssociationField.AddNewer') {
|
||||||
|
return schema;
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
});
|
||||||
|
if (found) {
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}, {});
|
||||||
|
const modalAdd = () => {
|
||||||
|
setVisible(true);
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<CollectionProvider_deprecated name={currentCollection} dataSource={currentDataSource}>
|
<div>
|
||||||
<RecursionField
|
<Button color="primary" fill="outline" onClick={modalAdd}>
|
||||||
onlyRenderProperties
|
添加
|
||||||
basePath={field.address}
|
</Button>
|
||||||
schema={fieldSchema}
|
|
||||||
filterProperties={(s) => {
|
<Popup
|
||||||
return s['x-component'] === 'AssociationField.AddNewer';
|
visible={visible}
|
||||||
|
onMaskClick={() => {
|
||||||
|
setVisible(false);
|
||||||
}}
|
}}
|
||||||
/>
|
className={css`
|
||||||
</CollectionProvider_deprecated>
|
.adm-popup-body {
|
||||||
|
height: 80vh;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
>
|
||||||
|
<MobileProvider>
|
||||||
|
<RecursionField schema={addNew} onlyRenderProperties />
|
||||||
|
</MobileProvider>
|
||||||
|
</Popup>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
};
|
},
|
||||||
|
{ displayName: 'CreateRecordAction' },
|
||||||
|
);
|
||||||
|
@ -15,48 +15,59 @@ export const MSelect = connect(
|
|||||||
const fieldSchema = useFieldSchema();
|
const fieldSchema = useFieldSchema();
|
||||||
const cm = useCollectionManager();
|
const cm = useCollectionManager();
|
||||||
const collection = cm.getCollection(fieldSchema['x-collection-field']);
|
const collection = cm.getCollection(fieldSchema['x-collection-field']);
|
||||||
|
const field = useField<any>();
|
||||||
|
const collectionField = useCollectionField();
|
||||||
|
const dataSource = field.dataSource || collectionField?.uiSchema.enum || [];
|
||||||
|
|
||||||
if (collection) {
|
if (collection) {
|
||||||
filterProps['collectionName'] = collection.name;
|
filterProps['collectionName'] = collection.name;
|
||||||
}
|
}
|
||||||
|
if (typeof filterProps['value'] !== 'object') {
|
||||||
|
filterProps['value'] = dataSource.filter((item) => item.value.toString() === filterProps['value']);
|
||||||
|
}
|
||||||
return { ...filterProps };
|
return { ...filterProps };
|
||||||
}),
|
}),
|
||||||
mapReadPretty((props) => {
|
mapReadPretty((props) => {
|
||||||
const { value, fieldNames } = props;
|
const { value, fieldNames } = props;
|
||||||
const isCollectionField = typeof value === 'object' && fieldNames;
|
|
||||||
if (isCollectionField) {
|
|
||||||
const isArrayField = isArray(value);
|
|
||||||
return isArrayField ? (
|
|
||||||
<div>
|
|
||||||
{value.map((item, index) => (
|
|
||||||
<Space key={index}>{`${item?.[fieldNames.label] || ''}${value.length - 1 === index ? '' : ','}`}</Space>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<Space>{value?.[fieldNames.label] || ''}</Space>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
const field = useField<any>();
|
|
||||||
const collectionField = useCollectionField();
|
const collectionField = useCollectionField();
|
||||||
|
const isSlectField = ['multipleSelect', 'select'].includes(collectionField.interface);
|
||||||
|
const field = useField<any>();
|
||||||
const dataSource = field.dataSource || collectionField?.uiSchema.enum || [];
|
const dataSource = field.dataSource || collectionField?.uiSchema.enum || [];
|
||||||
const options =
|
const fieldNamesLabel = fieldNames?.label || 'label';
|
||||||
typeof value === 'object'
|
if (isSlectField) {
|
||||||
? value
|
const option = [];
|
||||||
.map((item) => {
|
if (!isArray(value)) {
|
||||||
if (dataSource.find((dataItem) => dataItem.value === item.value)) {
|
if (typeof value === 'object') {
|
||||||
return item;
|
option.push(value);
|
||||||
|
} else {
|
||||||
|
option.push(dataSource.find((item) => item.value === value));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
option.push(...value);
|
||||||
}
|
}
|
||||||
})
|
|
||||||
.filter(Boolean)
|
|
||||||
: dataSource.filter((item) => item.value.toString() === value);
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{options.map((option, key) => (
|
{option.map((item, index) => (
|
||||||
<Tag key={key} color={getMobileColor(option.color)} style={{ margin: '5px' }}>
|
<Tag key={index} color={getMobileColor(item.color)}>
|
||||||
{option.label}
|
{item.label}
|
||||||
</Tag>
|
</Tag>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
let redValue = '';
|
||||||
|
if (isArray(value)) {
|
||||||
|
redValue = value.reduce((prev, curr) => {
|
||||||
|
return prev + curr[fieldNamesLabel];
|
||||||
|
}, '');
|
||||||
|
} else {
|
||||||
|
redValue = value[fieldNamesLabel];
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Space>{redValue}</Space>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
import { useCallback } from 'react';
|
|
||||||
import { useDesignable } from '@tachybase/client';
|
|
||||||
import { GeneralField, reaction, useField, useFieldSchema } from '@tachybase/schema';
|
|
||||||
import { flatten, getValuesByPath } from '@tachybase/utils/client';
|
|
||||||
|
|
||||||
import _, { isString } from 'lodash';
|
|
||||||
import cloneDeep from 'lodash/cloneDeep';
|
|
||||||
|
|
||||||
export const useInsertSchema = (component, fieldSchema, insertAfterBegin) => {
|
|
||||||
const insert = (ss) => {
|
|
||||||
const schema = fieldSchema.reduceProperties((buf, s) => {
|
|
||||||
if (s['x-component'] === 'AssociationField.' + component) {
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
return buf;
|
|
||||||
}, null);
|
|
||||||
if (!schema) {
|
|
||||||
insertAfterBegin(cloneDeep(ss));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return insert;
|
|
||||||
};
|
|
Loading…
Reference in New Issue
Block a user