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 { ApprovalTemplateType } from '../../component/ApprovalTemplateType';
|
||||
import { PendingStatus } from '../../constants';
|
||||
import { useTodosContext } from '../provider/todosContext';
|
||||
import { TabApplicantType } from './TabApplicantType';
|
||||
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 { 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 { MInput } from '../Input';
|
||||
|
||||
import './style';
|
||||
|
||||
import {
|
||||
BlockItem,
|
||||
CollectionProvider_deprecated,
|
||||
CollectionProvider,
|
||||
SchemaComponent,
|
||||
useAPIClient,
|
||||
useCollection,
|
||||
useCollectionField,
|
||||
useCollectionManager,
|
||||
useDesignable,
|
||||
useRequest,
|
||||
} from '@tachybase/client';
|
||||
import { isArray } from '@tachybase/utils/client';
|
||||
|
||||
import { getMobileColor } from '../../../CustomColor';
|
||||
import { MobileProvider } from '../../../provider';
|
||||
import { MInput } from '../Input';
|
||||
import { CreateRecordAction } from './CreateRecordAction';
|
||||
import { useInsertSchema } from './hook/hooks';
|
||||
import schema from './schema';
|
||||
import { useStyles } from './style';
|
||||
|
||||
export const AntdSelect = observer((props) => {
|
||||
@ -30,13 +32,21 @@ export const AntdSelect = observer((props) => {
|
||||
const [options, setOptions] = useState([]);
|
||||
const fieldSchema = useFieldSchema();
|
||||
const cm = useCollectionManager();
|
||||
const [visibleValue, setVisibleValue] = useState({});
|
||||
const collection = useCollection();
|
||||
const [filter, setFilter] = useState(service?.params?.filter);
|
||||
const api = useAPIClient();
|
||||
const field = useField();
|
||||
const { insertAfterBegin } = useDesignable();
|
||||
const insertAddNewer = useInsertSchema('AddNewer', fieldSchema, insertAfterBegin);
|
||||
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(
|
||||
{
|
||||
resource: collectionName,
|
||||
@ -57,8 +67,8 @@ export const AntdSelect = observer((props) => {
|
||||
const dataOption = data['data']?.map((value) => {
|
||||
return {
|
||||
...value,
|
||||
label: value[fieldNames.label],
|
||||
value: value[fieldNames.value],
|
||||
label: value[fieldNamesLabel],
|
||||
value: value[fieldNamesValue],
|
||||
};
|
||||
});
|
||||
setOptions(dataOption);
|
||||
@ -71,13 +81,12 @@ export const AntdSelect = observer((props) => {
|
||||
} else {
|
||||
const field = cm.getCollectionField(fieldSchema['x-collection-field']);
|
||||
const data = field.uiSchema?.enum;
|
||||
setVisibleValue(data.find((item) => item.value === value) || '');
|
||||
setOptions(data);
|
||||
}
|
||||
};
|
||||
|
||||
const addData = () => {
|
||||
api
|
||||
const addData = (data) => {
|
||||
data[fieldNamesLabel] = api
|
||||
.request({
|
||||
url: collectionName + ':create',
|
||||
method: 'post',
|
||||
@ -96,7 +105,7 @@ export const AntdSelect = observer((props) => {
|
||||
});
|
||||
}
|
||||
const paramsFilter = { ...filter };
|
||||
delete paramsFilter[fieldNames.label];
|
||||
delete paramsFilter[fieldNamesLabel];
|
||||
setFilter(paramsFilter);
|
||||
setSearchValue('');
|
||||
setPopupVisible(false);
|
||||
@ -107,65 +116,34 @@ export const AntdSelect = observer((props) => {
|
||||
};
|
||||
const quickAdd = () => {
|
||||
const data = {};
|
||||
data[fieldNames.label] = searchValue;
|
||||
addData();
|
||||
};
|
||||
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,
|
||||
});
|
||||
data[fieldNamesLabel] = searchValue;
|
||||
addData(data);
|
||||
};
|
||||
return (
|
||||
<CollectionProvider name={collectionName || collection.name}>
|
||||
<BlockItem>
|
||||
{!value || typeof value === 'object' ? (
|
||||
<div
|
||||
onClick={() => {
|
||||
if (fieldSchema['x-disabled']) return;
|
||||
setPopupVisible(true);
|
||||
checkedPopup();
|
||||
}}
|
||||
style={{ color: '#c5c5c5' }}
|
||||
>
|
||||
{isArray(value) && value.length ? (
|
||||
value.map((item, index) => (
|
||||
<Space key={index}>{`${item.label}${value.length - 1 === index ? '' : ','}`}</Space>
|
||||
))
|
||||
{value?.length || (value && !isArray(value)) ? (
|
||||
<MInput value={inputValue} disabled={fieldSchema['x-disabled']} />
|
||||
) : (
|
||||
<Space>{value?.label || '请选择内容'}</Space>
|
||||
<Space>{fieldSchema['x-disabled'] ? '' : '请选择内容'}</Space>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<Tag color={'default'}>{value?.['label']}</Tag>
|
||||
)}
|
||||
|
||||
<Popup visible={popupVisible} className={`${styles['PopupStyle']}`} closeOnMaskClick>
|
||||
<MobileProvider>
|
||||
<SearchBar
|
||||
placeholder="请输入内容"
|
||||
value={searchValue}
|
||||
onChange={(value) => {
|
||||
const paramsFilter = { ...filter };
|
||||
paramsFilter[fieldNames.label] = { $includes: value };
|
||||
paramsFilter[fieldNamesLabel] = { $includes: value };
|
||||
setFilter(paramsFilter);
|
||||
setSearchValue(value);
|
||||
}}
|
||||
@ -208,11 +186,17 @@ export const AntdSelect = observer((props) => {
|
||||
)}
|
||||
|
||||
<Space justify="evenly" align="center">
|
||||
{/* {addMode === 'modalAdd' ? (
|
||||
<Button color="primary" fill="outline" onClick={modalAdd}>
|
||||
添加
|
||||
</Button>
|
||||
) : null} */}
|
||||
{addMode === 'modalAdd' ? (
|
||||
<SchemaComponent
|
||||
components={{ CreateRecordAction }}
|
||||
schema={{
|
||||
type: 'void',
|
||||
name: 'CreateRecord',
|
||||
'x-component': 'CreateRecordAction',
|
||||
'x-component-props': { fieldSchema },
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
<Button
|
||||
color="primary"
|
||||
onClick={() => {
|
||||
@ -231,7 +215,9 @@ export const AntdSelect = observer((props) => {
|
||||
确定
|
||||
</Button>
|
||||
</Space>
|
||||
</MobileProvider>
|
||||
</Popup>
|
||||
</BlockItem>
|
||||
</CollectionProvider>
|
||||
);
|
||||
});
|
||||
|
@ -1,29 +1,55 @@
|
||||
import React, { useState } from 'react';
|
||||
import {
|
||||
CollectionProvider,
|
||||
CollectionProvider_deprecated,
|
||||
useActionContext,
|
||||
useCollectionManager,
|
||||
useCollectionManager_deprecated,
|
||||
} from '@tachybase/client';
|
||||
import { RecursionField } from '@tachybase/schema';
|
||||
import { css, SchemaComponentOptions, useApp, useCollection } from '@tachybase/client';
|
||||
import { observer, RecursionField, useField, useFieldSchema } from '@tachybase/schema';
|
||||
|
||||
import { useInsertSchema } from './hook/hooks';
|
||||
import schema from './schema';
|
||||
import { Button, CenterPopup, Modal, Popup } from 'antd-mobile';
|
||||
|
||||
export const CreateRecordAction = ({ field, fieldSchema, targetCollection }) => {
|
||||
const [currentCollection, setCurrentCollection] = useState(targetCollection?.name);
|
||||
const [currentDataSource, setCurrentDataSource] = useState(targetCollection?.dataSource);
|
||||
return (
|
||||
<CollectionProvider_deprecated name={currentCollection} dataSource={currentDataSource}>
|
||||
<RecursionField
|
||||
onlyRenderProperties
|
||||
basePath={field.address}
|
||||
schema={fieldSchema}
|
||||
filterProperties={(s) => {
|
||||
return s['x-component'] === 'AssociationField.AddNewer';
|
||||
}}
|
||||
/>
|
||||
</CollectionProvider_deprecated>
|
||||
);
|
||||
import { MobileProvider } from '../../../provider';
|
||||
|
||||
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 (
|
||||
<div>
|
||||
<Button color="primary" fill="outline" onClick={modalAdd}>
|
||||
添加
|
||||
</Button>
|
||||
|
||||
<Popup
|
||||
visible={visible}
|
||||
onMaskClick={() => {
|
||||
setVisible(false);
|
||||
}}
|
||||
className={css`
|
||||
.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 cm = useCollectionManager();
|
||||
const collection = cm.getCollection(fieldSchema['x-collection-field']);
|
||||
const field = useField<any>();
|
||||
const collectionField = useCollectionField();
|
||||
const dataSource = field.dataSource || collectionField?.uiSchema.enum || [];
|
||||
|
||||
if (collection) {
|
||||
filterProps['collectionName'] = collection.name;
|
||||
}
|
||||
if (typeof filterProps['value'] !== 'object') {
|
||||
filterProps['value'] = dataSource.filter((item) => item.value.toString() === filterProps['value']);
|
||||
}
|
||||
return { ...filterProps };
|
||||
}),
|
||||
mapReadPretty((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 isSlectField = ['multipleSelect', 'select'].includes(collectionField.interface);
|
||||
const field = useField<any>();
|
||||
const dataSource = field.dataSource || collectionField?.uiSchema.enum || [];
|
||||
const options =
|
||||
typeof value === 'object'
|
||||
? value
|
||||
.map((item) => {
|
||||
if (dataSource.find((dataItem) => dataItem.value === item.value)) {
|
||||
return item;
|
||||
const fieldNamesLabel = fieldNames?.label || 'label';
|
||||
if (isSlectField) {
|
||||
const option = [];
|
||||
if (!isArray(value)) {
|
||||
if (typeof value === 'object') {
|
||||
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 (
|
||||
<div>
|
||||
{options.map((option, key) => (
|
||||
<Tag key={key} color={getMobileColor(option.color)} style={{ margin: '5px' }}>
|
||||
{option.label}
|
||||
{option.map((item, index) => (
|
||||
<Tag key={index} color={getMobileColor(item.color)}>
|
||||
{item.label}
|
||||
</Tag>
|
||||
))}
|
||||
</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