updates...

This commit is contained in:
chenos 2021-07-23 12:34:15 +08:00
parent 07fa09e412
commit 19cbcd1e94
41 changed files with 1031 additions and 338 deletions

View File

@ -1,6 +1,6 @@
{
"watch": ["packages/", ".env"],
"ignore": ["packages/app"],
"ignore": ["packages/app", "packages/client"],
"ext": "ts",
"exec": "ts-node -r dotenv/config ./packages/api/src/index.ts"
}

View File

@ -1,21 +1,60 @@
import React, { useEffect } from 'react';
import 'antd/dist/antd.css'
import { useRequest } from 'ahooks';
import { Spin } from 'antd';
import React, { useMemo } from 'react';
import {
RouteSwitch,
useGlobalAction,
loadBlocks,
loadTemplates,
templates,
MemoryRouter as Router,
} from 'react-router-dom';
import {
createRouteSwitch,
AdminLayout,
AuthLayout,
RouteSchemaRenderer,
} from '@nocobase/client';
import { UseRequestProvider } from 'ahooks';
import { extend } from 'umi-request';
loadBlocks();
loadTemplates();
const request = extend({
prefix: 'http://localhost:23003/api/',
timeout: 1000,
});
// console.log = () => {}
const RouteSwitch = createRouteSwitch({
components: {
AdminLayout,
AuthLayout,
RouteSchemaRenderer,
},
});
const App = () => {
const { data, loading } = useRequest('routes:getAccessible', {
formatResult: (result) => result?.data,
});
if (loading) {
return <Spin/>
}
return (
<div>
{/* <Router initialEntries={['/admin']}> */}
<RouteSwitch routes={data} />
{/* </Router> */}
</div>
);
};
export default function IndexPage() {
const { data, loading } = useGlobalAction('routes:getAccessible');
console.log({ data });
if (loading) {
return <Spin />;
}
return <RouteSwitch components={templates} routes={data} />;
return (
<UseRequestProvider
value={{
requestMethod: (service) => request(service),
}}
>
<App />
</UseRequestProvider>
);
}

View File

@ -1,4 +1,4 @@
import { SchemaRenderer } from '@nocobase/client/lib';
import { SchemaRenderer } from '../../';
import React from 'react';
export default () => {

View File

@ -92,7 +92,7 @@ function LayoutWithMenu({ schema }) {
theme={'light'}
width={200}
></Layout.Sider>
<Layout.Content>
<Layout.Content style={{ minHeight: 'calc(100vh - 46px)' }}>
{activeKey && <Content activeKey={activeKey} />}
</Layout.Content>
</Layout>

View File

@ -19,9 +19,10 @@ import { useMemo } from 'react';
import { CodeOutlined } from '@ant-design/icons';
import Editor from '@monaco-editor/react';
import { ArrayCollapse, ArrayTable, FormLayout, FormItem as FormilyFormItem } from '@formily/antd';
import { ArrayCollapse, FormLayout, FormItem as FormilyFormItem } from '@formily/antd';
import { Space, Card, Modal, Spin } from 'antd';
import { ArrayTable } from '../../schemas/array-table';
import { Action } from '../../schemas/action';
import { AddNew } from '../../schemas/add-new';
import { Cascader } from '../../schemas/cascader';

View File

@ -727,7 +727,9 @@ AddNew.FormItem = observer((props: any) => {
</Menu.ItemGroup>
<Menu.Divider />
<Menu.SubMenu title={'新建字段'}>
{options.map((option) => (
{options.map(
(option) =>
option.children.length > 0 && (
<Menu.ItemGroup title={option.label}>
{option.children.map((item) => (
<Menu.Item
@ -778,7 +780,8 @@ AddNew.FormItem = observer((props: any) => {
</Menu.Item>
))}
</Menu.ItemGroup>
))}
),
)}
</Menu.SubMenu>
{/* <Menu.Divider /> */}
<Menu.Item

View File

@ -0,0 +1,63 @@
import React from 'react';
import { ArrayTable as Table } from '@formily/antd';
import { useField, Schema } from '@formily/react';
import { Button } from 'antd';
import cls from 'classnames';
import { isValid, uid } from '@formily/shared';
import { PlusOutlined } from '@ant-design/icons';
import { usePrefixCls } from '@formily/antd/lib/__builtins__';
export const ArrayTable = Table;
const getDefaultValue = (defaultValue: any, schema: Schema) => {
if (isValid(defaultValue)) return defaultValue;
if (Array.isArray(schema?.items))
return getDefaultValue(defaultValue, schema.items[0]);
if (schema?.items?.type === 'array') return [];
if (schema?.items?.type === 'boolean') return true;
if (schema?.items?.type === 'date') return '';
if (schema?.items?.type === 'datetime') return '';
if (schema?.items?.type === 'number') return 0;
if (schema?.items?.type === 'object') return {};
if (schema?.items?.type === 'string') return '';
return null;
};
ArrayTable.Addition = (props: any) => {
const { randomValue } = props;
const self = useField();
const array = Table.useArray();
const prefixCls = usePrefixCls('formily-array-base');
if (!array) return null;
if (array.field?.pattern !== 'editable') return null;
return (
<Button
type="dashed"
block
{...props}
className={cls(`${prefixCls}-addition`, props.className)}
onClick={(e) => {
if (array.props?.disabled) return;
const defaultValue = getDefaultValue(props.defaultValue, array.schema);
if (randomValue) {
defaultValue.value = uid();
}
if (props.method === 'unshift') {
array.field?.unshift?.(defaultValue);
array.props?.onAdd?.(0);
} else {
array.field?.push?.(defaultValue);
array.props?.onAdd?.(array?.field?.value?.length - 1);
}
if (props.onClick) {
props.onClick(e);
}
}}
icon={<PlusOutlined />}
>
{props.title || self.title}
</Button>
);
};
export default ArrayTable;

View File

@ -39,7 +39,11 @@ import Modal from 'antd/lib/modal/Modal';
import { clone, cloneDeep, get } from 'lodash';
import { useEffect } from 'react';
import { useRequest } from 'ahooks';
import { createOrUpdateCollection, deleteCollection, useCollectionContext } from '..';
import {
createOrUpdateCollection,
deleteCollection,
useCollectionContext,
} from '..';
export const DatabaseCollection = observer((props) => {
const field = useField<Formily.Core.Models.ArrayField>();
@ -84,6 +88,10 @@ export const DatabaseCollection = observer((props) => {
<DatabaseOutlined />
</Button>
<Modal
bodyStyle={{
overflow: 'auto',
maxHeight: 'calc(100vh - 300px)',
}}
title={
<div style={{ textAlign: 'center' }}>
<Select
@ -149,7 +157,8 @@ export const DatabaseCollection = observer((props) => {
alignItems: 'center',
}}
>
{item.title || '未命名'} {item.unsaved ? '(未保存)' : ''}
{item.title || '未命名'}{' '}
{item.unsaved ? '(未保存)' : ''}
<DeleteOutlined
onClick={async (e) => {
e.stopPropagation();
@ -210,9 +219,7 @@ export const DatabaseCollection = observer((props) => {
}
/>
{/* <FormConsumer>
{form => (
<pre>{JSON.stringify(form.values, null, 2)}</pre>
)}
{(form) => <pre>{JSON.stringify(form.values, null, 2)}</pre>}
</FormConsumer> */}
</FormLayout>
)}
@ -227,7 +234,7 @@ export const DatabaseField: any = observer((props) => {
if (!field.value) {
field.setValue([]);
}
}, [])
}, []);
const [activeKey, setActiveKey] = useState(null);
console.log('DatabaseField', field);
return (
@ -241,7 +248,7 @@ export const DatabaseField: any = observer((props) => {
accordion
>
{field.value?.map((item, index) => {
const schema = interfaces.get(item.interface);
const schema = cloneDeep(interfaces.get(item.interface));
const path = field.address.concat(index);
const errors = field.form.queryFeedbacks({
type: 'error',
@ -319,13 +326,16 @@ export const DatabaseField: any = observer((props) => {
console.log('info.key', field.value);
}}
>
{options.map((option) => (
{options.map(
(option) =>
option.children.length > 0 && (
<Menu.ItemGroup title={option.label}>
{option.children.map((item) => (
<Menu.Item key={item.name}>{item.title}</Menu.Item>
))}
</Menu.ItemGroup>
))}
),
)}
</Menu>
}
>

View File

@ -0,0 +1,28 @@
import { ISchema } from '@formily/react';
import { defaultProps } from './properties';
export const attachment: ISchema = {
name: 'attachment',
type: 'object',
group: 'media',
title: '附件',
default: {
dataType: 'belongsToMany',
target: 'attachments',
// name,
uiSchema: {
type: 'array',
// title,
'x-component': 'Upload',
'x-decorator': 'FormItem',
'x-designable-bar': 'Upload.DesignableBar',
} as ISchema,
},
properties: {
...defaultProps,
},
operations: [
{ label: '等于', value: 'eq' },
{ label: '不等于', value: 'ne' },
],
};

View File

@ -0,0 +1,28 @@
import { ISchema } from '@formily/react';
import { defaultProps } from './properties';
export const checkbox: ISchema = {
name: 'checkbox',
type: 'object',
group: 'choices',
order: 1,
title: '勾选',
default: {
dataType: 'boolean',
// name,
uiSchema: {
type: 'boolean',
// title,
'x-component': 'Checkbox',
'x-decorator': 'FormItem',
'x-designable-bar': 'Checkbox.DesignableBar',
} as ISchema,
},
properties: {
...defaultProps,
},
operations: [
{ label: '等于', value: 'eq' },
{ label: '不等于', value: 'ne' },
],
};

View File

@ -0,0 +1,30 @@
import { ISchema } from '@formily/react';
import { defaultProps, dataSource } from './properties';
export const checkboxGroup: ISchema = {
name: 'checkboxGroup',
type: 'object',
group: 'choices',
order: 5,
title: '复选框',
default: {
interface: 'checkboxGroup',
dataType: 'json',
// name,
uiSchema: {
type: 'string',
// title,
'x-component': 'Checkbox.Group',
'x-decorator': 'FormItem',
'x-designable-bar': 'Checkbox.Group.DesignableBar',
} as ISchema,
},
properties: {
...defaultProps,
'uiSchema.enum': dataSource,
},
operations: [
{ label: '等于', value: 'eq' },
{ label: '不等于', value: 'ne' },
],
};

View File

@ -0,0 +1,31 @@
import { ISchema } from '@formily/react';
import { defaultProps } from './properties';
export const chinaRegion: ISchema = {
name: 'chinaRegion',
type: 'object',
group: 'choices',
order: 7,
title: '中国行政区划',
default: {
dataType: 'belongsToMany',
target: 'china_regions',
targetKey: 'code',
// name,
uiSchema: {
type: 'array',
// title,
'x-component': 'Cascader',
'x-component-props': {},
'x-decorator': 'FormItem',
'x-designable-bar': 'Cascader.DesignableBar',
} as ISchema,
},
properties: {
...defaultProps,
},
operations: [
{ label: '等于', value: 'eq' },
{ label: '不等于', value: 'ne' },
],
};

View File

@ -0,0 +1,31 @@
import { ISchema } from '@formily/react';
import { defaultProps } from './properties';
export const createdAt: ISchema = {
name: 'createdAt',
type: 'object',
group: 'systemInfo',
order: 1,
title: '创建时间',
default: {
dataType: 'date',
field: 'created_at',
// name,
uiSchema: {
type: 'datetime',
// title,
'x-component': 'DatePicker',
'x-component-props': {},
'x-read-pretty': true,
'x-decorator': 'FormItem',
'x-designable-bar': 'DatePicker.DesignableBar',
} as ISchema,
},
properties: {
...defaultProps,
},
operations: [
{ label: '等于', value: 'eq' },
{ label: '不等于', value: 'ne' },
],
};

View File

@ -0,0 +1,32 @@
import { ISchema } from '@formily/react';
import { defaultProps } from './properties';
export const createdBy: ISchema = {
name: 'createdBy',
type: 'object',
group: 'systemInfo',
order: 3,
title: '创建人',
default: {
dataType: 'belongsTo',
target: 'users',
foreignKey: 'created_by_id',
// name,
uiSchema: {
type: 'object',
// title,
'x-component': 'Select.Drawer',
'x-component-props': {},
'x-decorator': 'FormItem',
'x-read-pretty': true,
'x-designable-bar': 'Select.Drawer.DesignableBar',
} as ISchema,
},
properties: {
...defaultProps,
},
operations: [
{ label: '等于', value: 'eq' },
{ label: '不等于', value: 'ne' },
],
};

View File

@ -0,0 +1,29 @@
import { ISchema } from '@formily/react';
import { defaultProps } from './properties';
export const datetime: ISchema = {
name: 'datetime',
type: 'object',
group: 'datetime',
order: 1,
title: '日期',
default: {
dataType: 'date',
// name,
uiSchema: {
type: 'datetime',
// title,
'x-component': 'DatePicker',
'x-component-props': {},
'x-decorator': 'FormItem',
'x-designable-bar': 'DatePicker.DesignableBar',
} as ISchema,
},
properties: {
...defaultProps,
},
operations: [
{ label: '等于', value: 'eq' },
{ label: '不等于', value: 'ne' },
],
};

View File

@ -0,0 +1,29 @@
import { ISchema } from '@formily/react';
import { defaultProps } from './properties';
export const email: ISchema = {
name: 'email',
type: 'object',
group: 'basic',
order: 4,
title: '电子邮箱',
default: {
dataType: 'string',
// name,
uiSchema: {
type: 'string',
// title,
'x-component': 'Input',
'x-decorator': 'FormItem',
'x-validator': 'email',
'x-designable-bar': 'Input.DesignableBar',
} as ISchema,
},
properties: {
...defaultProps,
},
operations: [
{ label: '等于', value: 'eq' },
{ label: '不等于', value: 'ne' },
],
};

View File

@ -0,0 +1,24 @@
import { ISchema } from '@formily/react';
import { defaultProps } from './properties';
export const icon: ISchema = {
name: 'icon',
type: 'object',
group: 'basic',
order: 8,
title: '图标',
default: {
dataType: 'string',
// name,
uiSchema: {
type: 'string',
// title,
'x-component': 'IconPicker',
'x-decorator': 'FormItem',
'x-designable-bar': 'IconPicker.DesignableBar',
} as ISchema,
},
properties: {
...defaultProps,
},
};

View File

@ -1,10 +1,6 @@
import { ISchema } from '@formily/react';
import { set } from 'lodash';
import { select } from './select';
import { string } from './string';
import { subTable } from './subTable';
import { textarea } from './textarea';
import * as types from './types';
export const interfaces = new Map<string, ISchema>();
@ -21,20 +17,26 @@ export function registerGroupLabel(key: string, label: string) {
groupLabels[key] = label;
}
registerField('basic', 'string', string);
registerField('basic', 'textarea', textarea);
registerField('choices', 'select', select);
registerField('relation', 'subTable', subTable);
Object.keys(types).forEach((type) => {
const schema = types[type];
registerField(schema.group || 'others', type, { order: 0, ...schema });
});
registerGroupLabel('basic', '基本类型');
registerGroupLabel('choices', '选择类型');
registerGroupLabel('media', '多媒体类型');
registerGroupLabel('relation', '关系类型');
registerGroupLabel('systemInfo', '系统信息');
registerGroupLabel('others', '其他类型');
export const options = Object.keys(fields).map((groupName) => {
export const options = Object.keys(groupLabels).map(groupName => {
return {
label: groupLabels[groupName],
children: Object.keys(fields[groupName]).map((type) => {
return fields[groupName][type];
}),
children: Object.keys(fields[groupName] || {}).map((type) => {
return {
name: type,
...fields[groupName][type],
};
}).sort((a, b) => a.order - b.order),
}
});

View File

@ -0,0 +1,29 @@
import { ISchema } from '@formily/react';
import { defaultProps } from './properties';
export const linkTo: ISchema = {
name: 'linkTo',
type: 'object',
group: 'relation',
order: 1,
title: '关联字段',
default: {
dataType: 'belongsToMany',
// name,
uiSchema: {
type: 'array',
// title,
'x-component': 'Select.Drawer',
'x-component-props': {},
'x-decorator': 'FormItem',
'x-designable-bar': 'Select.Drawer.DesignableBar',
} as ISchema,
},
properties: {
...defaultProps,
},
operations: [
{ label: '等于', value: 'eq' },
{ label: '不等于', value: 'ne' },
],
};

View File

@ -0,0 +1,27 @@
import { ISchema } from '@formily/react';
import { defaultProps } from './properties';
export const markdown: ISchema = {
name: 'markdown',
type: 'object',
title: 'Markdown',
group: 'media',
default: {
dataType: 'text',
// name,
uiSchema: {
type: 'string',
// title,
'x-component': 'Markdown',
'x-decorator': 'FormItem',
'x-designable-bar': 'Markdown.DesignableBar',
} as ISchema,
},
properties: {
...defaultProps,
},
operations: [
{ label: '等于', value: 'eq' },
{ label: '不等于', value: 'ne' },
],
};

View File

@ -0,0 +1,31 @@
import { ISchema } from '@formily/react';
import { defaultProps, dataSource } from './properties';
export const multipleSelect: ISchema = {
name: 'multipleSelect',
type: 'object',
group: 'choices',
order: 3,
title: '下拉选择(多选)',
default: {
dataType: 'json',
// name,
uiSchema: {
type: 'array',
// title,
'x-component': 'Select',
'x-component-props': {},
'x-decorator': 'FormItem',
'x-designable-bar': 'Select.DesignableBar',
enum: [],
} as ISchema,
},
properties: {
...defaultProps,
'uiSchema.enum': dataSource,
},
operations: [
{ label: '等于', value: 'eq' },
{ label: '不等于', value: 'ne' },
],
};

View File

@ -0,0 +1,28 @@
import { ISchema } from '@formily/react';
import { defaultProps } from './properties';
export const number: ISchema = {
name: 'number',
type: 'object',
group: 'basic',
order: 5,
title: '数字',
default: {
dataType: 'float',
// name,
uiSchema: {
type: 'number',
// title,
'x-component': 'InputNumber',
'x-decorator': 'FormItem',
'x-designable-bar': 'InputNumber.DesignableBar',
} as ISchema,
},
properties: {
...defaultProps,
},
operations: [
{ label: '等于', value: 'eq' },
{ label: '不等于', value: 'ne' },
],
};

View File

@ -0,0 +1,28 @@
import { ISchema } from '@formily/react';
import { defaultProps } from './properties';
export const password: ISchema = {
name: 'password',
type: 'object',
group: 'basic',
order: 7,
title: '密码',
default: {
dataType: 'password',
// name,
uiSchema: {
type: 'string',
// title,
'x-component': 'Password',
'x-decorator': 'FormItem',
'x-designable-bar': 'Password.DesignableBar',
} as ISchema,
},
properties: {
...defaultProps,
},
operations: [
{ label: '等于', value: 'eq' },
{ label: '不等于', value: 'ne' },
],
};

View File

@ -0,0 +1,28 @@
import { ISchema } from '@formily/react';
import { defaultProps } from './properties';
export const percent: ISchema = {
name: 'percent',
type: 'object',
group: 'basic',
order: 6,
title: '百分比',
default: {
dataType: 'float',
// name,
uiSchema: {
type: 'string',
// title,
'x-component': 'InputNumber',
'x-decorator': 'FormItem',
'x-designable-bar': 'InputNumber.DesignableBar',
} as ISchema,
},
properties: {
...defaultProps
},
operations: [
{ label: '等于', value: 'eq' },
{ label: '不等于', value: 'ne' },
],
};

View File

@ -0,0 +1,29 @@
import { ISchema } from '@formily/react';
import { defaultProps } from './properties';
export const phone: ISchema = {
name: 'phone',
type: 'object',
group: 'basic',
order: 3,
title: '手机号码',
default: {
dataType: 'string',
// name,
uiSchema: {
type: 'string',
// title,
'x-component': 'Input',
'x-decorator': 'FormItem',
"x-validator": 'phone',
'x-designable-bar': 'Input.DesignableBar',
} as ISchema,
},
properties: {
...defaultProps,
},
operations: [
{ label: '等于', value: 'eq' },
{ label: '不等于', value: 'ne' },
],
};

View File

@ -0,0 +1,147 @@
import { ISchema } from "@formily/react";
export const dataType: ISchema = {
type: 'string',
title: '数据类型',
required: true,
'x-decorator': 'FormItem',
'x-component': 'Select',
enum: [
{ label: 'Boolean', value: 'boolean' },
{ label: 'String', value: 'string' },
{ label: 'Text', value: 'text' },
{ label: 'Integer', value: 'integer' },
{ label: 'Float', value: 'float' },
{ label: 'Decimal', value: 'decimal' },
{ label: 'Date', value: 'date' },
{ label: 'DateOnly', value: 'dateonly' },
{ label: 'Time', value: 'time' },
{ label: 'Virtual', value: 'virtual' },
{ label: 'JSON', value: 'json' },
{ label: 'Password', value: 'password' },
{ label: 'HasOne', value: 'hasOne' },
{ label: 'HasMany', value: 'hasMany' },
{ label: 'BelongsTo', value: 'belongsTo' },
{ label: 'BelongsToMany', value: 'belongsToMany' },
],
}
export const dataSource: ISchema = {
type: 'array',
title: '可选项',
'x-decorator': 'FormItem',
'x-component': 'ArrayTable',
'x-component-props': {
pagination: false,
// scroll: { x: '100%' },
},
items: {
type: 'object',
properties: {
column1: {
type: 'void',
'x-component': 'ArrayTable.Column',
'x-component-props': { width: 50, title: '', align: 'center' },
properties: {
sort: {
type: 'void',
'x-component': 'ArrayTable.SortHandle',
},
},
},
column2: {
type: 'void',
'x-component': 'ArrayTable.Column',
'x-component-props': { title: '选项值' },
"x-hidden": true,
properties: {
value: {
type: 'string',
'x-decorator': 'FormItem',
'x-component': 'Input',
},
},
},
column3: {
type: 'void',
'x-component': 'ArrayTable.Column',
'x-component-props': { title: '选项' },
properties: {
label: {
type: 'string',
'x-decorator': 'FormItem',
'x-component': 'Input',
},
},
},
column4: {
type: 'void',
'x-component': 'ArrayTable.Column',
'x-component-props': { title: '颜色' },
properties: {
color: {
type: 'string',
'x-decorator': 'FormItem',
'x-component': 'ColorSelect',
},
},
},
column5: {
type: 'void',
'x-component': 'ArrayTable.Column',
'x-component-props': {
title: '',
dataIndex: 'operations',
fixed: 'right',
},
properties: {
item: {
type: 'void',
'x-component': 'FormItem',
properties: {
remove: {
type: 'void',
'x-component': 'ArrayTable.Remove',
},
},
},
},
},
},
},
properties: {
add: {
type: 'void',
'x-component': 'ArrayTable.Addition',
'x-component-props': {
randomValue: true,
},
title: '添加可选项',
},
},
};
export const defaultProps = {
'uiSchema.title': {
type: 'string',
title: '字段名称',
required: true,
'x-decorator': 'FormItem',
'x-component': 'Input',
},
name: {
type: 'string',
title: '字段标识',
required: true,
'x-disabled': true,
'x-decorator': 'FormItem',
'x-component': 'Input',
},
dataType,
// 'uiSchema.required': {
// type: 'string',
// title: '必填',
// 'x-decorator': 'FormItem',
// 'x-component': 'Checkbox',
// },
};

View File

@ -0,0 +1,29 @@
import { ISchema } from '@formily/react';
import { defaultProps, dataSource } from './properties';
export const radioGroup: ISchema = {
name: 'radioGroup',
type: 'object',
group: 'choices',
order: 4,
title: '单选框',
default: {
dataType: 'string',
// name,
uiSchema: {
type: 'string',
// title,
'x-component': 'Radio.Group',
'x-decorator': 'FormItem',
'x-designable-bar': 'Radio.DesignableBar',
} as ISchema,
},
properties: {
...defaultProps,
'uiSchema.enum': dataSource,
},
operations: [
{ label: '等于', value: 'eq' },
{ label: '不等于', value: 'ne' },
],
};

View File

@ -1,12 +1,13 @@
import { ISchema } from '@formily/react';
import { defaultProps, dataSource } from './properties';
export const select: ISchema = {
name: 'select',
type: 'object',
title: '下拉选择',
group: 'choices',
order: 2,
title: '下拉选择(单选)',
default: {
interface: 'select',
dataType: 'string',
// name,
uiSchema: {
@ -14,133 +15,13 @@ export const select: ISchema = {
// title,
'x-component': 'Select',
'x-decorator': 'FormItem',
'x-designable-bar': 'Markdown.DesignableBar',
'x-designable-bar': 'Select.DesignableBar',
enum: [],
} as ISchema,
},
properties: {
'uiSchema.title': {
type: 'string',
required: true,
title: '字段名称',
'x-decorator': 'FormItem',
'x-component': 'Input',
},
name: {
type: 'string',
required: true,
title: '字段标识',
'x-disabled': true,
'x-decorator': 'FormItem',
'x-component': 'Input',
},
dataType: {
type: 'string',
title: '数据类型',
required: true,
'x-decorator': 'FormItem',
'x-component': 'Select',
enum: [
{ label: 'String', value: 'string' },
{ label: 'Text', value: 'text' },
],
},
'uiSchema.enum': {
type: 'array',
title: '可选项',
'x-decorator': 'FormItem',
'x-component': 'ArrayTable',
'x-component-props': {
pagination: false,
// scroll: { x: '100%' },
},
items: {
type: 'object',
properties: {
column1: {
type: 'void',
'x-component': 'ArrayTable.Column',
'x-component-props': { width: 50, title: '', align: 'center' },
properties: {
sort: {
type: 'void',
'x-component': 'ArrayTable.SortHandle',
},
},
},
column2: {
type: 'void',
'x-component': 'ArrayTable.Column',
'x-component-props': { title: '选项值' },
properties: {
value: {
type: 'string',
'x-decorator': 'FormItem',
'x-component': 'Input',
},
},
},
column3: {
type: 'void',
'x-component': 'ArrayTable.Column',
'x-component-props': { title: '选项' },
properties: {
label: {
type: 'string',
'x-decorator': 'FormItem',
'x-component': 'Input',
},
},
},
column4: {
type: 'void',
'x-component': 'ArrayTable.Column',
'x-component-props': { title: '颜色' },
properties: {
color: {
type: 'string',
'x-decorator': 'FormItem',
'x-component': 'ColorSelect',
},
},
},
column5: {
type: 'void',
'x-component': 'ArrayTable.Column',
'x-component-props': {
title: '',
dataIndex: 'operations',
fixed: 'right',
},
properties: {
item: {
type: 'void',
'x-component': 'FormItem',
properties: {
remove: {
type: 'void',
'x-component': 'ArrayTable.Remove',
},
},
},
},
},
},
},
properties: {
add: {
type: 'void',
'x-component': 'ArrayTable.Addition',
title: '添加可选项',
},
},
},
'uiSchema.required': {
type: 'string',
title: '必填',
'x-decorator': 'FormItem',
'x-component': 'Checkbox',
},
...defaultProps,
'uiSchema.enum': dataSource,
},
operations: [
{ label: '等于', value: 'eq' },

View File

@ -1,10 +1,12 @@
import { ISchema } from '@formily/react';
import { defaultProps } from './properties';
export const string: ISchema = {
name: 'string',
type: 'object',
title: '单行文本',
group: 'basic',
order: 1,
title: '单行文本',
default: {
interface: 'string',
dataType: 'string',
@ -18,38 +20,7 @@ export const string: ISchema = {
} as ISchema,
},
properties: {
'uiSchema.title': {
type: 'string',
title: '字段名称',
required: true,
'x-decorator': 'FormItem',
'x-component': 'Input',
},
name: {
type: 'string',
title: '字段标识',
required: true,
'x-disabled': true,
'x-decorator': 'FormItem',
'x-component': 'Input',
},
dataType: {
type: 'string',
title: '数据类型',
required: true,
'x-decorator': 'FormItem',
'x-component': 'Select',
enum: [
{ label: 'String', value: 'string' },
{ label: 'Text', value: 'text' },
],
},
'uiSchema.required': {
type: 'string',
title: '必填',
'x-decorator': 'FormItem',
'x-component': 'Checkbox',
},
...defaultProps,
},
operations: [
{ label: '等于', value: 'eq' },

View File

@ -1,50 +1,27 @@
import { ISchema } from '@formily/react';
import { defaultProps } from './properties';
export const subTable: ISchema = {
name: 'subTable',
type: 'object',
title: '子表格',
group: 'relation',
order: 2,
title: '子表格',
default: {
interface: 'subTable',
dataType: 'hasMany',
// name,
uiSchema: {
type: 'string',
type: 'array',
// title,
'x-decorator': 'FormItem',
'x-component': 'Table',
'x-designable-bar': 'Markdown.DesignableBar',
'x-component-props': {},
'x-designable-bar': 'Table.DesignableBar',
enum: [],
} as ISchema,
},
properties: {
'uiSchema.title': {
type: 'string',
required: true,
title: '字段名称',
'x-decorator': 'FormItem',
'x-component': 'Input',
},
name: {
type: 'string',
required: true,
title: '字段标识',
'x-disabled': true,
'x-decorator': 'FormItem',
'x-component': 'Input',
},
dataType: {
type: 'string',
title: '数据类型',
required: true,
'x-decorator': 'FormItem',
'x-component': 'Select',
enum: [
{ label: 'String', value: 'string' },
{ label: 'Text', value: 'text' },
{ label: 'HasMany', value: 'hasMany' },
],
},
...defaultProps,
'children': {
type: 'array',
title: '子表格字段',

View File

@ -1,10 +1,12 @@
import { ISchema } from '@formily/react';
import { defaultProps } from './properties';
export const textarea: ISchema = {
name: 'textarea',
type: 'object',
title: '多行文本',
group: 'basic',
order: 2,
title: '多行文本',
default: {
dataType: 'text',
// name,
@ -13,42 +15,11 @@ export const textarea: ISchema = {
// title,
'x-decorator': 'FormItem',
'x-component': 'Input.TextArea',
'x-designable-bar': 'Markdown.DesignableBar',
'x-designable-bar': 'Input.DesignableBar',
} as ISchema,
},
properties: {
'uiSchema.title': {
type: 'string',
required: true,
title: '字段名称',
'x-decorator': 'FormItem',
'x-component': 'Input',
},
name: {
type: 'string',
required: true,
title: '字段标识',
'x-disabled': true,
'x-decorator': 'FormItem',
'x-component': 'Input',
},
dataType: {
type: 'string',
title: '数据类型',
required: true,
'x-decorator': 'FormItem',
'x-component': 'Select',
enum: [
{ label: 'String', value: 'string' },
{ label: 'Text', value: 'text' },
],
},
'uiSchema.required': {
type: 'string',
title: '必填',
'x-decorator': 'FormItem',
'x-component': 'Checkbox',
},
...defaultProps,
},
operations: [
{ label: '等于', value: 'eq' },

View File

@ -0,0 +1,28 @@
import { ISchema } from '@formily/react';
import { defaultProps } from './properties';
export const time: ISchema = {
name: 'time',
type: 'object',
group: 'datetime',
order: 2,
title: '时间',
default: {
dataType: 'time',
// name,
uiSchema: {
type: 'string',
// title,
'x-component': 'TimePicker',
'x-decorator': 'FormItem',
'x-designable-bar': 'TimePicker.DesignableBar',
} as ISchema,
},
properties: {
...defaultProps,
},
operations: [
{ label: '等于', value: 'eq' },
{ label: '不等于', value: 'ne' },
],
};

View File

@ -0,0 +1,24 @@
export * from './attachment';
export * from './checkbox';
export * from './checkboxGroup';
export * from './chinaRegion';
export * from './createdAt';
export * from './createdBy';
export * from './datetime';
export * from './email';
export * from './icon';
export * from './linkTo';
export * from './markdown';
export * from './multipleSelect';
export * from './number';
export * from './password';
export * from './percent';
export * from './phone';
export * from './radioGroup';
export * from './select';
export * from './string';
export * from './subTable';
export * from './textarea';
export * from './time';
export * from './updatedAt';
export * from './updatedBy';

View File

@ -0,0 +1,31 @@
import { ISchema } from '@formily/react';
import { defaultProps } from './properties';
export const updatedAt: ISchema = {
name: 'updatedAt',
type: 'object',
group: 'systemInfo',
order: 2,
title: '最后更新时间',
default: {
dataType: 'date',
field: 'updated_at',
// name,
uiSchema: {
type: 'datetime',
// title,
'x-component': 'DatePicker',
'x-component-props': {},
'x-read-pretty': true,
'x-decorator': 'FormItem',
'x-designable-bar': 'DatePicker.DesignableBar',
} as ISchema,
},
properties: {
...defaultProps,
},
operations: [
{ label: '等于', value: 'eq' },
{ label: '不等于', value: 'ne' },
],
};

View File

@ -0,0 +1,32 @@
import { ISchema } from '@formily/react';
import { defaultProps } from './properties';
export const updatedBy: ISchema = {
name: 'updatedBy',
type: 'object',
group: 'systemInfo',
order: 4,
title: '最后修改人',
default: {
dataType: 'belongsTo',
target: 'users',
foreignKey: 'updated_by_id',
// name,
uiSchema: {
type: 'object',
// title,
'x-component': 'Select.Drawer',
'x-component-props': {},
'x-decorator': 'FormItem',
'x-read-pretty': true,
'x-designable-bar': 'Select.Drawer.DesignableBar',
} as ISchema,
},
properties: {
...defaultProps,
},
operations: [
{ label: '等于', value: 'eq' },
{ label: '不等于', value: 'ne' },
],
};

View File

@ -26,6 +26,7 @@ export function generateDefaultSchema(component) {
properties: {
[uid()]: {
type: 'void',
async: true,
'x-component': 'Page',
properties: {
[uid()]: {

View File

@ -86,7 +86,11 @@ const SideMenu = (props: any) => {
<AntdMenu mode={'inline'} onSelect={onSelect}>
<RecursionField schema={child} onlyRenderProperties />
<Menu.AddNew key={uid()} path={[...path, selectedKey]}>
<Button className={'nb-add-new-menu-item'} block type={'dashed'}>
<Button
block
type={'dashed'}
className={`nb-add-new-menu-item menu-mode-inline`}
>
<PlusOutlined />
</Button>
</Menu.AddNew>
@ -519,8 +523,15 @@ Menu.DesignableBar = (props) => {
const field = useField();
const [visible, setVisible] = useState(false);
const { designable, schema, remove, refresh, insertAfter, insertBefore, appendChild } =
useDesignable();
const {
designable,
schema,
remove,
refresh,
insertAfter,
insertBefore,
appendChild,
} = useDesignable();
const formConfig = schemas[schema['x-component']];
const isSubMenu = schema['x-component'] === 'Menu.SubMenu';
@ -626,7 +637,7 @@ Menu.DesignableBar = (props) => {
parent = parent.parent;
}
console.log({ menuSchema })
console.log({ menuSchema });
const toTreeData = (s: Schema) => {
const items = [];
@ -720,10 +731,7 @@ Menu.DesignableBar = (props) => {
};
const data = schema.toJSON();
remove();
const source = methods[values.method](
data,
values.path,
);
const source = methods[values.method](data, values.path);
await updateSchema(source);
}}
>

View File

@ -924,7 +924,12 @@ Table.Action.DesignableBar = () => {
</Menu.Item>
)}
{inActionBar && <Menu.Item></Menu.Item>}
{inActionBar ? (
<Menu.Item></Menu.Item>
) : (
<Menu.Item> &nbsp;&nbsp;<Switch size={'small'} defaultChecked/></Menu.Item>
)}
<Menu.Divider />
<Menu.Item></Menu.Item>
</Menu>

View File

@ -43,10 +43,10 @@ export const create = async (ctx: actions.Context, next: actions.Next) => {
payload: 'replace',
},
);
console.log(ctx.action.params.values);
// console.log(ctx.action.params.values);
await middlewares.associated(ctx, async () => { });
await sort(ctx, async () => { });
console.log(ctx.body.toJSON());
// console.log(ctx.body.toJSON());
}
await next();
};
@ -91,10 +91,10 @@ export const update = async (ctx: actions.Context, next: actions.Next) => {
payload: 'replace',
},
);
console.log(ctx.action.params.values);
// console.log(ctx.action.params.values);
await middlewares.associated(ctx, async () => { });
await sort(ctx, async () => { });
console.log(ctx.body.toJSON());
// console.log(ctx.body.toJSON());
}
await next();
};
@ -117,7 +117,7 @@ export const getTree = async (ctx: actions.Context, next: actions.Next) => {
sort: ['sort'],
}),
);
console.log({ schemas });
// console.log({ schemas });
let properties = {};
for (const schema of schemas) {
const property = schema.toProperty();

View File

@ -32,6 +32,11 @@ export default {
name: 'options',
defaultValue: {},
},
{
type: 'boolean',
name: 'async',
defaultValue: false,
},
{
type: 'hasMany',
name: 'children',

View File

@ -69,6 +69,9 @@ export class UISchema extends Model {
async getProperties() {
const properties = {};
const children: UISchema[] = await this.getChildren({
where: {
async: false,
},
order: [['sort', 'asc']],
});
for (const child of children) {