();
if (loading) {
return ;
}
+ const findProperties = (schema: Schema): Schema[] => {
+ if (!schema) {
+ return [];
+ }
+ return schema.reduceProperties((items, current) => {
+ if (current['key'] == match.params.name) {
+ return [...items, current];
+ }
+ return [...items, ...findProperties(current)];
+ }, []);
+ }
+ const current = findProperties(new Schema(data)).shift();
+ const defaultSelectedKeys = [current?.name];
+ let parent = current?.parent;
+ while(parent) {
+ if (parent['x-component'] === 'Menu') {
+ break;
+ }
+ defaultSelectedKeys.unshift(parent.name);
+ parent = parent.parent;
+ }
+
+ console.log('current?.title', current, current?.title, defaultSelectedKeys);
+
return (
-
-
+ {/* @ts-ignore */}
+
+
diff --git a/packages/client/src/components/schema-renderer/index.tsx b/packages/client/src/components/schema-renderer/index.tsx
index de9c67b3f1..a5547afa9a 100644
--- a/packages/client/src/components/schema-renderer/index.tsx
+++ b/packages/client/src/components/schema-renderer/index.tsx
@@ -51,7 +51,7 @@ import { CardItem } from '../../schemas/card-item';
import { DragAndDrop } from '../../schemas/drag-and-drop';
import { TreeSelect } from '../../schemas/tree-select';
import { Page } from '../../schemas/page';
-import { Chart } from '../../schemas/chart';
+// import { Chart } from '../../schemas/chart';
import { useCollectionContext, useSwithDesignableContext } from '../../schemas';
export const BlockContext = createContext({ dragRef: null });
@@ -72,7 +72,7 @@ export const SchemaField = createSchemaField({
Div,
Space,
Page,
- Chart,
+ // Chart,
ArrayCollapse,
ArrayTable,
diff --git a/packages/client/src/schemas/add-new/index.tsx b/packages/client/src/schemas/add-new/index.tsx
index 0232c7f272..18b626f0ee 100644
--- a/packages/client/src/schemas/add-new/index.tsx
+++ b/packages/client/src/schemas/add-new/index.tsx
@@ -882,8 +882,9 @@ AddNew.PaneItem = observer((props: any) => {
placement={'bottomCenter'}
overlay={
}
>
diff --git a/packages/client/src/schemas/chart/index.tsx b/packages/client/src/schemas/chart/index.tsx
index 3d91cc8403..72b2be7008 100644
--- a/packages/client/src/schemas/chart/index.tsx
+++ b/packages/client/src/schemas/chart/index.tsx
@@ -1,111 +1,111 @@
-import React, { useContext } from 'react';
-import {
- Column,
- ColumnConfig,
- Line,
- LineConfig,
- Pie,
- PieConfig,
- Bar,
- BarConfig,
-} from '@ant-design/charts';
-import {
- connect,
- mapProps,
- observer,
- useField,
- useFieldSchema,
- mapReadPretty,
-} from '@formily/react';
-import { Button, Dropdown, Input as AntdInput, Menu, Space } from 'antd';
-import { InputProps, TextAreaProps } from 'antd/lib/input';
-import { Display } from '../display';
-import { LoadingOutlined, MenuOutlined, DragOutlined } from '@ant-design/icons';
-import micromark from 'micromark';
-import { useDesignable } from '../../components/schema-renderer';
-import { useState } from 'react';
-import AddNew from '../add-new';
-import cls from 'classnames';
-import { DraggableBlockContext } from '../../components/drag-and-drop';
-import { uid } from '@formily/shared';
-import { removeSchema, updateSchema } from '..';
-import { isGridRowOrCol } from '../grid';
+// import React, { useContext } from 'react';
+// import {
+// Column,
+// ColumnConfig,
+// Line,
+// LineConfig,
+// Pie,
+// PieConfig,
+// Bar,
+// BarConfig,
+// } from '@ant-design/charts';
+// import {
+// connect,
+// mapProps,
+// observer,
+// useField,
+// useFieldSchema,
+// mapReadPretty,
+// } from '@formily/react';
+// import { Button, Dropdown, Input as AntdInput, Menu, Space } from 'antd';
+// import { InputProps, TextAreaProps } from 'antd/lib/input';
+// import { Display } from '../display';
+// import { LoadingOutlined, MenuOutlined, DragOutlined } from '@ant-design/icons';
+// import micromark from 'micromark';
+// import { useDesignable } from '../../components/schema-renderer';
+// import { useState } from 'react';
+// import AddNew from '../add-new';
+// import cls from 'classnames';
+// import { DraggableBlockContext } from '../../components/drag-and-drop';
+// import { uid } from '@formily/shared';
+// import { removeSchema, updateSchema } from '..';
+// import { isGridRowOrCol } from '../grid';
-export const Chart: any = {};
+// export const Chart: any = {};
-Chart.Column = observer((props: any) => {
- return ;
-});
+// Chart.Column = observer((props: any) => {
+// return ;
+// });
-Chart.Line = observer((props: any) => {
- return ;
-});
+// Chart.Line = observer((props: any) => {
+// return ;
+// });
-Chart.Pie = observer((props: any) => {
- return ;
-});
+// Chart.Pie = observer((props: any) => {
+// return ;
+// });
-Chart.Bar = observer((props: any) => {
- return ;
-});
+// Chart.Bar = observer((props: any) => {
+// return ;
+// });
-Chart.DesignableBar = observer((props) => {
- const field = useField();
- const { designable, schema, refresh, deepRemove } = useDesignable();
- const [visible, setVisible] = useState(false);
- const { dragRef } = useContext(DraggableBlockContext);
- if (!designable) {
- return null;
- }
- return (
-
-
{
- e.stopPropagation();
- }}
- className={cls('designable-bar-actions', { active: visible })}
- >
-
-
- {dragRef && }
- {
- setVisible(visible);
- }}
- overlay={
-
- }
- >
-
-
-
-
-
- );
-});
\ No newline at end of file
+// Chart.DesignableBar = observer((props) => {
+// const field = useField();
+// const { designable, schema, refresh, deepRemove } = useDesignable();
+// const [visible, setVisible] = useState(false);
+// const { dragRef } = useContext(DraggableBlockContext);
+// if (!designable) {
+// return null;
+// }
+// return (
+//
+//
{
+// e.stopPropagation();
+// }}
+// className={cls('designable-bar-actions', { active: visible })}
+// >
+//
+//
+// {dragRef && }
+// {
+// setVisible(visible);
+// }}
+// overlay={
+//
+// }
+// >
+//
+//
+//
+//
+//
+// );
+// });
\ No newline at end of file
diff --git a/packages/client/src/schemas/database-field/index.tsx b/packages/client/src/schemas/database-field/index.tsx
index 08395d3a01..6970077ed4 100644
--- a/packages/client/src/schemas/database-field/index.tsx
+++ b/packages/client/src/schemas/database-field/index.tsx
@@ -26,7 +26,7 @@ import {
message,
Spin,
} from 'antd';
-import { options, interfaces } from './interfaces';
+import { options, interfaces, getDefaultFields } from './interfaces';
import {
DeleteOutlined,
DatabaseOutlined,
@@ -53,16 +53,21 @@ export const DatabaseCollection = observer((props) => {
const [activeIndex, setActiveIndex] = useState(0);
const form = useForm();
const [newValue, setNewValue] = useState('');
- const { refresh } = useCollectionContext();
+ const { loading, refresh, data } = useCollectionContext();
- const { run, loading } = useRequest('collections:findAll', {
- formatResult: (result) => result?.data,
- onSuccess(data) {
- field.setValue(data);
- console.log('onSuccess', data);
- },
- manual: true,
- });
+ useEffect(() => {
+ field.setValue(data);
+ console.log('onSuccess', data);
+ }, [data]);
+
+ // const { run, loading } = useRequest('collections:findAll', {
+ // formatResult: (result) => result?.data,
+ // onSuccess(data) {
+ // // field.setValue(data);
+ // // console.log('onSuccess', data);
+ // },
+ // manual: true,
+ // });
return (
@@ -74,12 +79,12 @@ export const DatabaseCollection = observer((props) => {
}}
onClick={async () => {
setVisible(true);
- await run();
+ // await run();
if (field.value?.length === 0) {
field.push({
name: `t_${uid()}`,
unsaved: true,
- fields: [],
+ fields: getDefaultFields(),
});
}
}}
@@ -127,7 +132,7 @@ export const DatabaseCollection = observer((props) => {
const data = {
name: `t_${uid()}`,
title: value,
- fields: [],
+ fields: getDefaultFields(),
};
field.push(data);
setActiveIndex(field.value.length - 1);
@@ -160,28 +165,30 @@ export const DatabaseCollection = observer((props) => {
>
{item.title || '未命名'}{' '}
{item.unsaved ? '(未保存)' : ''}
- {
- e.stopPropagation();
- field.remove(index);
- if (field.value?.length === 0) {
- field.push({
- name: `t_${uid()}`,
- unsaved: true,
- fields: [],
- });
- }
- if (activeIndex === index) {
- setActiveIndex(0);
- } else if (activeIndex > index) {
- setActiveIndex(activeIndex - 1);
- }
- if (item.name) {
- await deleteCollection(item.name);
- await refresh();
- }
- }}
- />
+ {item.privilege !== 'undelete' && (
+ {
+ e.stopPropagation();
+ field.remove(index);
+ if (field.value?.length === 0) {
+ field.push({
+ name: `t_${uid()}`,
+ unsaved: true,
+ fields: getDefaultFields(),
+ });
+ }
+ if (activeIndex === index) {
+ setActiveIndex(0);
+ } else if (activeIndex > index) {
+ setActiveIndex(activeIndex - 1);
+ }
+ if (item.name) {
+ await deleteCollection(item.name);
+ await refresh();
+ }
+ }}
+ />
+ )}
);
@@ -206,24 +213,20 @@ export const DatabaseCollection = observer((props) => {
} catch (error) {}
}}
>
- {loading ? (
-
- ) : (
-
-
- {/*
+
+
+ {/*
{(form) => {JSON.stringify(form.values, null, 2)}
}
*/}
-
- )}
+
);
@@ -237,7 +240,6 @@ export const DatabaseField: any = observer((props) => {
}
}, []);
const [activeKey, setActiveKey] = useState(null);
- console.log('DatabaseField', field);
return (
{
accordion
>
{field.value?.map((item, index) => {
+ if (!item.interface) {
+ return;
+ }
const schema = cloneDeep(interfaces.get(item.interface));
+ if (!schema) {
+ console.error('schema invalid');
+ return;
+ }
const path = field.address.concat(index);
const errors = field.form.queryFeedbacks({
type: 'error',
address: `*(${path},${path}.*)`,
});
- console.log('item.key', item.key);
return (
{
{(item.uiSchema && item.uiSchema.title) || (
未命名
)}{' '}
- {schema.title}
+
+ {schema.title}
+
{item.name}
>
}
- extra={[
- ,
- {
- e.stopPropagation();
- field.remove(index);
- }}
- />,
- ]}
+ extra={
+ item.privilege === 'undelete'
+ ? []
+ : [
+ ,
+ {
+ e.stopPropagation();
+ field.remove(index);
+ }}
+ />,
+ ]
+ }
key={item.key}
>
{
name: `f_${uid()}`,
interface: info.key,
};
+ if (schema.initialize) {
+ schema.initialize(data);
+ }
field.push(data);
setActiveKey(data.key);
console.log('info.key', field.value);
diff --git a/packages/client/src/schemas/database-field/interfaces/checkbox.ts b/packages/client/src/schemas/database-field/interfaces/checkbox.ts
index bc477cf523..396e159283 100644
--- a/packages/client/src/schemas/database-field/interfaces/checkbox.ts
+++ b/packages/client/src/schemas/database-field/interfaces/checkbox.ts
@@ -1,4 +1,5 @@
import { ISchema } from '@formily/react';
+import { omit } from 'lodash';
import { defaultProps } from './properties';
export const checkbox: ISchema = {
diff --git a/packages/client/src/schemas/database-field/interfaces/createdAt.ts b/packages/client/src/schemas/database-field/interfaces/createdAt.ts
index 0124cbac17..beea03a6ad 100644
--- a/packages/client/src/schemas/database-field/interfaces/createdAt.ts
+++ b/packages/client/src/schemas/database-field/interfaces/createdAt.ts
@@ -1,5 +1,5 @@
import { ISchema } from '@formily/react';
-import { defaultProps } from './properties';
+import { dateTimeProps, defaultProps } from './properties';
export const createdAt: ISchema = {
name: 'createdAt',
@@ -13,7 +13,7 @@ export const createdAt: ISchema = {
// name,
uiSchema: {
type: 'datetime',
- // title,
+ title: '创建时间',
'x-component': 'DatePicker',
'x-component-props': {},
'x-read-pretty': true,
@@ -23,6 +23,7 @@ export const createdAt: ISchema = {
},
properties: {
...defaultProps,
+ ...dateTimeProps,
},
operations: [
{ label: '等于', value: 'eq' },
diff --git a/packages/client/src/schemas/database-field/interfaces/createdBy.ts b/packages/client/src/schemas/database-field/interfaces/createdBy.ts
index 86113c5152..48e86f92c3 100644
--- a/packages/client/src/schemas/database-field/interfaces/createdBy.ts
+++ b/packages/client/src/schemas/database-field/interfaces/createdBy.ts
@@ -14,7 +14,7 @@ export const createdBy: ISchema = {
// name,
uiSchema: {
type: 'object',
- // title,
+ title: '创建人',
'x-component': 'Select.Drawer',
'x-component-props': {},
'x-decorator': 'FormItem',
diff --git a/packages/client/src/schemas/database-field/interfaces/datetime.ts b/packages/client/src/schemas/database-field/interfaces/datetime.ts
index 94c87de91d..d1218e9a5f 100644
--- a/packages/client/src/schemas/database-field/interfaces/datetime.ts
+++ b/packages/client/src/schemas/database-field/interfaces/datetime.ts
@@ -1,5 +1,5 @@
import { ISchema } from '@formily/react';
-import { defaultProps } from './properties';
+import { dateTimeProps, defaultProps } from './properties';
export const datetime: ISchema = {
name: 'datetime',
@@ -14,13 +14,16 @@ export const datetime: ISchema = {
type: 'datetime',
// title,
'x-component': 'DatePicker',
- 'x-component-props': {},
+ 'x-component-props': {
+ showTime: false,
+ },
'x-decorator': 'FormItem',
'x-designable-bar': 'DatePicker.DesignableBar',
} as ISchema,
},
properties: {
...defaultProps,
+ ...dateTimeProps,
},
operations: [
{ label: '等于', value: 'eq' },
diff --git a/packages/client/src/schemas/database-field/interfaces/index.ts b/packages/client/src/schemas/database-field/interfaces/index.ts
index 8e1e8d3eda..39273b612f 100644
--- a/packages/client/src/schemas/database-field/interfaces/index.ts
+++ b/packages/client/src/schemas/database-field/interfaces/index.ts
@@ -1,12 +1,26 @@
import { ISchema } from '@formily/react';
-import { set } from 'lodash';
+import { cloneDeep, set } from 'lodash';
import * as types from './types';
+import { uid } from '@formily/shared';
export const interfaces = new Map();
const fields = {};
const groupLabels = {};
+export function getDefaultFields() {
+ const defaults = ['createdAt', 'updatedAt', 'createdBy', 'updatedBy'];
+ return defaults.map(key => {
+ return {
+ interface: key,
+ key: uid(),
+ name: uid(),
+ privilege: 'undelete',
+ ...cloneDeep(interfaces.get(key)?.default),
+ }
+ });
+}
+
export function registerField(group: string, type: string, schema) {
fields[group] = fields[group] || {};
set(fields, [group, type], schema);
@@ -25,6 +39,7 @@ Object.keys(types).forEach((type) => {
registerGroupLabel('basic', '基本类型');
registerGroupLabel('choices', '选择类型');
registerGroupLabel('media', '多媒体类型');
+registerGroupLabel('datetime', '日期和时间');
registerGroupLabel('relation', '关系类型');
registerGroupLabel('systemInfo', '系统信息');
registerGroupLabel('others', '其他类型');
diff --git a/packages/client/src/schemas/database-field/interfaces/linkTo.ts b/packages/client/src/schemas/database-field/interfaces/linkTo.ts
index d0a99901bb..b415c4f2a3 100644
--- a/packages/client/src/schemas/database-field/interfaces/linkTo.ts
+++ b/packages/client/src/schemas/database-field/interfaces/linkTo.ts
@@ -1,5 +1,6 @@
import { ISchema } from '@formily/react';
import { defaultProps } from './properties';
+import { uid } from '@formily/shared';
export const linkTo: ISchema = {
name: 'linkTo',
@@ -19,8 +20,41 @@ export const linkTo: ISchema = {
'x-designable-bar': 'Select.Drawer.DesignableBar',
} as ISchema,
},
+ initialize: (values: any) => {
+ if (values.dataType === 'belongsToMany') {
+ if (!values.through) {
+ values.through = `t_${uid()}`;
+ }
+ if (!values.foreignKey) {
+ values.foreignKey = `f_${uid()}`;
+ }
+ if (!values.otherKey) {
+ values.otherKey = `f_${uid()}`;
+ }
+ if (!values.sourceKey) {
+ values.sourceKey = 'id';
+ }
+ if (!values.targetKey) {
+ values.targetKey = 'id';
+ }
+ }
+ },
properties: {
...defaultProps,
+ target: {
+ type: 'string',
+ title: '要关联的数据表',
+ required: true,
+ 'x-reactions': ['{{useAsyncDataSource(loadCollections)}}'],
+ 'x-decorator': 'FormItem',
+ 'x-component': 'Select',
+ },
+ 'uiSchema.x-component-props.multiple': {
+ type: 'boolean',
+ 'x-content': '允许关联多条记录',
+ 'x-decorator': 'FormItem',
+ 'x-component': 'Checkbox',
+ },
},
operations: [
{ label: '等于', value: 'eq' },
diff --git a/packages/client/src/schemas/database-field/interfaces/multipleSelect.ts b/packages/client/src/schemas/database-field/interfaces/multipleSelect.ts
index 0430ad21b2..dc58c79d99 100644
--- a/packages/client/src/schemas/database-field/interfaces/multipleSelect.ts
+++ b/packages/client/src/schemas/database-field/interfaces/multipleSelect.ts
@@ -14,7 +14,9 @@ export const multipleSelect: ISchema = {
type: 'array',
// title,
'x-component': 'Select',
- 'x-component-props': {},
+ 'x-component-props': {
+ mode: 'multiple',
+ },
'x-decorator': 'FormItem',
'x-designable-bar': 'Select.DesignableBar',
enum: [],
diff --git a/packages/client/src/schemas/database-field/interfaces/number.ts b/packages/client/src/schemas/database-field/interfaces/number.ts
index 3224ed5692..6db0b9b449 100644
--- a/packages/client/src/schemas/database-field/interfaces/number.ts
+++ b/packages/client/src/schemas/database-field/interfaces/number.ts
@@ -14,12 +14,31 @@ export const number: ISchema = {
type: 'number',
// title,
'x-component': 'InputNumber',
+ 'x-component-props': {
+ stringMode: true,
+ step: '0',
+ },
'x-decorator': 'FormItem',
'x-designable-bar': 'InputNumber.DesignableBar',
} as ISchema,
},
properties: {
...defaultProps,
+ 'uiSchema.x-component-props.step': {
+ type: 'string',
+ title: '精度',
+ 'x-component': 'Select',
+ 'x-decorator': 'FormItem',
+ default: '0',
+ enum: [
+ { value: '0', label: '1' },
+ { value: '0.1', label: '1.0' },
+ { value: '0.01', label: '1.00' },
+ { value: '0.001', label: '1.000' },
+ { value: '0.0001', label: '1.0000' },
+ { value: '0.00001', label: '1.00000' },
+ ],
+ },
},
operations: [
{ label: '等于', value: 'eq' },
diff --git a/packages/client/src/schemas/database-field/interfaces/percent.ts b/packages/client/src/schemas/database-field/interfaces/percent.ts
index bb55a04b8b..bd82c22b89 100644
--- a/packages/client/src/schemas/database-field/interfaces/percent.ts
+++ b/packages/client/src/schemas/database-field/interfaces/percent.ts
@@ -14,12 +14,31 @@ export const percent: ISchema = {
type: 'string',
// title,
'x-component': 'InputNumber',
+ 'x-component-props': {
+ stringMode: true,
+ step: '0',
+ },
'x-decorator': 'FormItem',
'x-designable-bar': 'InputNumber.DesignableBar',
} as ISchema,
},
properties: {
- ...defaultProps
+ ...defaultProps,
+ 'uiSchema.x-component-props.step': {
+ type: 'string',
+ title: '精度',
+ 'x-component': 'Select',
+ 'x-decorator': 'FormItem',
+ default: '0',
+ enum: [
+ { value: '0', label: '1' },
+ { value: '0.1', label: '1.0' },
+ { value: '0.01', label: '1.00' },
+ { value: '0.001', label: '1.000' },
+ { value: '0.0001', label: '1.0000' },
+ { value: '0.00001', label: '1.00000' },
+ ]
+ },
},
operations: [
{ label: '等于', value: 'eq' },
diff --git a/packages/client/src/schemas/database-field/interfaces/properties/index.ts b/packages/client/src/schemas/database-field/interfaces/properties/index.ts
index 8399b90697..7990af7d7e 100644
--- a/packages/client/src/schemas/database-field/interfaces/properties/index.ts
+++ b/packages/client/src/schemas/database-field/interfaces/properties/index.ts
@@ -1,9 +1,10 @@
-import { ISchema } from "@formily/react";
+import { ISchema } from '@formily/react';
export const dataType: ISchema = {
type: 'string',
title: '数据类型',
required: true,
+ 'x-disabled': true,
'x-decorator': 'FormItem',
'x-component': 'Select',
enum: [
@@ -24,7 +25,61 @@ export const dataType: ISchema = {
{ label: 'BelongsTo', value: 'belongsTo' },
{ label: 'BelongsToMany', value: 'belongsToMany' },
],
-}
+};
+
+export const dateTimeProps: { [key: string]: ISchema } = {
+ dateFormat: {
+ type: 'string',
+ title: '日期格式',
+ 'x-component': 'Radio.Group',
+ 'x-decorator': 'FormItem',
+ default: 'YYYY-MM-DD',
+ enum: [
+ {
+ label: '年/月/日',
+ value: 'YYYY/MM/DD',
+ },
+ {
+ label: '年-月-日',
+ value: 'YYYY-MM-DD',
+ },
+ {
+ label: '日/月/年',
+ value: 'DD/MM/YYYY',
+ },
+ ],
+ },
+ showTime: {
+ type: 'boolean',
+ 'x-decorator': 'FormItem',
+ 'x-component': 'Checkbox',
+ 'x-content': '显示时间',
+ 'x-reactions': [
+ `{{(field) => {
+ field.query('..[].timeFormat').take(f => {
+ f.display = field.value ? 'visible' : 'none';
+ });
+ }}}`,
+ ],
+ },
+ timeFormat: {
+ type: 'string',
+ title: '时间格式',
+ 'x-component': 'Radio.Group',
+ 'x-decorator': 'FormItem',
+ default: 'HH:mm:ss',
+ enum: [
+ {
+ label: '24小时制',
+ value: 'HH:mm:ss',
+ },
+ {
+ label: '12小时制',
+ value: 'hh:mm:ss a',
+ },
+ ],
+ },
+};
export const dataSource: ISchema = {
type: 'array',
@@ -53,7 +108,7 @@ export const dataSource: ISchema = {
type: 'void',
'x-component': 'ArrayTable.Column',
'x-component-props': { title: '选项值' },
- "x-hidden": true,
+ 'x-hidden': true,
properties: {
value: {
type: 'string',
diff --git a/packages/client/src/schemas/database-field/interfaces/subTable.ts b/packages/client/src/schemas/database-field/interfaces/subTable.ts
index b85d2bb45c..1a4fc8ace9 100644
--- a/packages/client/src/schemas/database-field/interfaces/subTable.ts
+++ b/packages/client/src/schemas/database-field/interfaces/subTable.ts
@@ -1,5 +1,6 @@
import { ISchema } from '@formily/react';
import { defaultProps } from './properties';
+import { uid } from '@formily/shared';
export const subTable: ISchema = {
name: 'subTable',
@@ -20,6 +21,14 @@ export const subTable: ISchema = {
enum: [],
} as ISchema,
},
+ initialize: (values: any) => {
+ if (!values.target) {
+ values.target = `t_${uid()}`;
+ }
+ if (!values.foreignKey) {
+ values.foreignKey = `f_${uid()}`;
+ }
+ },
properties: {
...defaultProps,
'children': {
diff --git a/packages/client/src/schemas/database-field/interfaces/time.ts b/packages/client/src/schemas/database-field/interfaces/time.ts
index b6929663a8..7866bdd8b2 100644
--- a/packages/client/src/schemas/database-field/interfaces/time.ts
+++ b/packages/client/src/schemas/database-field/interfaces/time.ts
@@ -20,6 +20,23 @@ export const time: ISchema = {
},
properties: {
...defaultProps,
+ 'uiSchema.x-component-props.format': {
+ type: 'string',
+ title: '时间格式',
+ 'x-component': 'Radio.Group',
+ 'x-decorator': 'FormItem',
+ default: 'HH:mm:ss',
+ enum: [
+ {
+ label: '24小时制',
+ value: 'HH:mm:ss',
+ },
+ {
+ label: '12小时制',
+ value: 'hh:mm:ss a',
+ },
+ ],
+ },
},
operations: [
{ label: '等于', value: 'eq' },
diff --git a/packages/client/src/schemas/database-field/interfaces/updatedAt.ts b/packages/client/src/schemas/database-field/interfaces/updatedAt.ts
index 593011bbc1..909e803ce2 100644
--- a/packages/client/src/schemas/database-field/interfaces/updatedAt.ts
+++ b/packages/client/src/schemas/database-field/interfaces/updatedAt.ts
@@ -1,5 +1,5 @@
import { ISchema } from '@formily/react';
-import { defaultProps } from './properties';
+import { dateTimeProps, defaultProps } from './properties';
export const updatedAt: ISchema = {
name: 'updatedAt',
@@ -13,7 +13,7 @@ export const updatedAt: ISchema = {
// name,
uiSchema: {
type: 'datetime',
- // title,
+ title: '最后更新时间',
'x-component': 'DatePicker',
'x-component-props': {},
'x-read-pretty': true,
@@ -23,6 +23,7 @@ export const updatedAt: ISchema = {
},
properties: {
...defaultProps,
+ ...dateTimeProps,
},
operations: [
{ label: '等于', value: 'eq' },
diff --git a/packages/client/src/schemas/database-field/interfaces/updatedBy.ts b/packages/client/src/schemas/database-field/interfaces/updatedBy.ts
index fae2389ac9..066a1a6ca7 100644
--- a/packages/client/src/schemas/database-field/interfaces/updatedBy.ts
+++ b/packages/client/src/schemas/database-field/interfaces/updatedBy.ts
@@ -14,7 +14,7 @@ export const updatedBy: ISchema = {
// name,
uiSchema: {
type: 'object',
- // title,
+ title: '最后修改人',
'x-component': 'Select.Drawer',
'x-component-props': {},
'x-decorator': 'FormItem',
diff --git a/packages/client/src/schemas/database-field/style.less b/packages/client/src/schemas/database-field/style.less
index b8accb89dc..08ad171557 100644
--- a/packages/client/src/schemas/database-field/style.less
+++ b/packages/client/src/schemas/database-field/style.less
@@ -21,3 +21,8 @@
overflow: auto;
}
}
+
+.ant-tag.disabled {
+ color: rgba(0, 0, 0, 0.25);
+ cursor: not-allowed;
+}
\ No newline at end of file
diff --git a/packages/client/src/schemas/form/Field.DesignableBar.tsx b/packages/client/src/schemas/form/Field.DesignableBar.tsx
index 3bd7edd3e4..2163cade3c 100644
--- a/packages/client/src/schemas/form/Field.DesignableBar.tsx
+++ b/packages/client/src/schemas/form/Field.DesignableBar.tsx
@@ -55,7 +55,7 @@ export const FieldDesignableBar = observer((props) => {
className={cls('designable-bar-actions', { active: visible })}
>
-
+
{dragRef && }
{
- return useState(null);
+const [PageTitleContextProvider, usePageTitleContext] = constate(({ defaultPageTitle }) => {
+ return useState(defaultPageTitle);
});
export { PageTitleContextProvider, usePageTitleContext };
diff --git a/packages/client/src/schemas/menu/index.tsx b/packages/client/src/schemas/menu/index.tsx
index a409647156..b8171c43d9 100644
--- a/packages/client/src/schemas/menu/index.tsx
+++ b/packages/client/src/schemas/menu/index.tsx
@@ -72,7 +72,7 @@ import { onFieldChange } from '@formily/core';
export const MenuModeContext = createContext(null);
const SideMenu = (props: any) => {
- const { selectedKey, onSelect, path } = props;
+ const { selectedKey, defaultSelectedKeys, onSelect, path } = props;
const { schema } = useDesignable();
if (!selectedKey) {
return null;
@@ -101,11 +101,11 @@ const SideMenu = (props: any) => {
};
export const Menu: any = observer((props: any) => {
- const { mode, onSelect, sideMenuRef, ...others } = props;
+ const { mode, onSelect, sideMenuRef, defaultSelectedKeys = [], ...others } = props;
const { designable, schema } = useDesignable();
const fieldSchema = useFieldSchema();
console.log('Menu.schema', schema, fieldSchema);
- const [selectedKey, setSelectedKey] = useState(null);
+ const [selectedKey, setSelectedKey] = useState(defaultSelectedKeys[0]||null);
const ref = useRef();
const path = useSchemaPath();
const child = schema.properties && schema.properties[selectedKey];
@@ -133,6 +133,7 @@ export const Menu: any = observer((props: any) => {
return (
{
@@ -163,12 +164,13 @@ export const Menu: any = observer((props: any) => {
{
- const keyPath = [selectedKey, ...info.keyPath];
+ const keyPath = [selectedKey, ...[...info.keyPath].reverse()];
const selectedSchema = findPropertyByPath(schema, keyPath);
console.log('keyPath', keyPath, selectedSchema);
onSelect &&
onSelect({ ...info, keyPath, schema: selectedSchema });
}}
+ defaultSelectedKeys={defaultSelectedKeys||[]}
selectedKey={selectedKey}
sideMenuRef={sideMenuRef}
/>
diff --git a/packages/database/src/fields/field-types.ts b/packages/database/src/fields/field-types.ts
index 8e54f459fd..eb27f4d70a 100644
--- a/packages/database/src/fields/field-types.ts
+++ b/packages/database/src/fields/field-types.ts
@@ -423,10 +423,11 @@ export abstract class Relation extends Field {
public targetTableInit() {
const { target, fields = [] } = this.options;
- if (target && fields.length) {
+ const children = fields.concat(this.options.children || []);
+ if (target && children.length) {
this.context.database.table({
name: target,
- fields,
+ fields: children,
});
}
}
diff --git a/packages/plugin-collections/src/actions/fields.ts b/packages/plugin-collections/src/actions/fields.ts
index c418e8587b..15c0b2c016 100644
--- a/packages/plugin-collections/src/actions/fields.ts
+++ b/packages/plugin-collections/src/actions/fields.ts
@@ -7,6 +7,6 @@ export const create = async (ctx: actions.Context, next: actions.Next) => {
await actions.common.create(ctx, async () => {});
const { associated } = ctx.action.params;
await associated.migrate();
- console.log('associated.migrate');
+ // console.log('associated.migrate');
await next();
}
diff --git a/packages/plugin-collections/src/actions/index.ts b/packages/plugin-collections/src/actions/index.ts
index 9212d91286..c3e0cf845f 100644
--- a/packages/plugin-collections/src/actions/index.ts
+++ b/packages/plugin-collections/src/actions/index.ts
@@ -32,7 +32,7 @@ export const createOrUpdate = async (ctx: actions.Context, next: actions.Next) =
await collection.updateAssociations(values);
await collection.migrate();
} catch (error) {
- console.log('error.errors', error.errors)
+ // console.log('error.errors', error.errors)
throw error;
}
ctx.body = collection;
diff --git a/packages/plugin-collections/src/collections/collections.ts b/packages/plugin-collections/src/collections/collections.ts
index 7237430e8f..dcfd98654f 100644
--- a/packages/plugin-collections/src/collections/collections.ts
+++ b/packages/plugin-collections/src/collections/collections.ts
@@ -20,6 +20,10 @@ export default {
name: 'title',
required: true,
},
+ {
+ type: 'string',
+ name: 'privilege',
+ },
{
type: 'json',
name: 'options',
@@ -30,5 +34,10 @@ export default {
name: 'fields',
sourceKey: 'name',
},
+ {
+ type: 'belongsTo',
+ name: 'uiSchema',
+ target: 'ui_schemas',
+ },
],
} as TableOptions;
diff --git a/packages/plugin-collections/src/collections/fields.ts b/packages/plugin-collections/src/collections/fields.ts
index 419302ba56..6da0e297c0 100644
--- a/packages/plugin-collections/src/collections/fields.ts
+++ b/packages/plugin-collections/src/collections/fields.ts
@@ -31,6 +31,10 @@ export default {
type: 'string',
name: 'dataType',
},
+ {
+ type: 'string',
+ name: 'privilege',
+ },
{
type: 'hasMany',
name: 'children',
@@ -49,7 +53,6 @@ export default {
type: 'belongsTo',
name: 'uiSchema',
target: 'ui_schemas',
- defaultValue: {},
},
{
type: 'json',
diff --git a/packages/plugin-collections/src/models/collection.ts b/packages/plugin-collections/src/models/collection.ts
index 3f3fbf9689..e6c2b50505 100644
--- a/packages/plugin-collections/src/models/collection.ts
+++ b/packages/plugin-collections/src/models/collection.ts
@@ -41,7 +41,9 @@ export class Collection extends Model {
}
async getNestedFields() {
- const fields = await this.getFields();
+ const fields = await this.getFields({
+ order: [['sort', 'asc']],
+ });
const items = [];
for (const field of fields) {
items.push(await field.toProps());
@@ -58,7 +60,7 @@ export class Collection extends Model {
*/
async loadTableOptions(opts: any = {}) {
const options = await this.toProps();
- console.log(JSON.stringify(options, null, 2));
+ // console.log(JSON.stringify(options, null, 2));
const table = this.database.table(options);
return table;
}
diff --git a/packages/plugin-collections/src/models/field.ts b/packages/plugin-collections/src/models/field.ts
index f335849f3c..793d24f531 100644
--- a/packages/plugin-collections/src/models/field.ts
+++ b/packages/plugin-collections/src/models/field.ts
@@ -3,7 +3,6 @@ import { Model } from '@nocobase/database';
export class Field extends Model {
static async create(value?: any, options?: any): Promise {
- // console.log({ value });
const attributes = this.toAttributes(value);
// @ts-ignore
const model: Model = await super.create(attributes, options);
@@ -11,13 +10,16 @@ export class Field extends Model {
}
static toAttributes(value = {}): any {
- const data = _.cloneDeep(value);
+ const data: any = _.cloneDeep(value);
const keys = [
...Object.keys(this.rawAttributes),
...Object.keys(this.associations),
];
+ if (!data.dataType && data.type) {
+ data.dataType = data.type;
+ }
const attrs = _.pick(data, keys);
- const options = _.omit(data, keys);
+ const options = _.omit(data, [...keys, 'type']);
return { ...attrs, options };
}
diff --git a/packages/plugin-collections/src/server.ts b/packages/plugin-collections/src/server.ts
index 3cc7f1b577..b20a8f5b58 100644
--- a/packages/plugin-collections/src/server.ts
+++ b/packages/plugin-collections/src/server.ts
@@ -11,10 +11,86 @@ export default async function (this: Application, options = {}) {
database.import({
directory: path.resolve(__dirname, 'collections'),
});
- database.getModel('fields').beforeCreate((model) => {
+ const [Collection, Field] = database.getModels(['collections', 'fields']);
+ Field.beforeCreate(async (model) => {
if (!model.get('name')) {
model.set('name', model.get('key'));
}
+ if (!model.get('collection_name') && model.get('parentKey')) {
+ const field = await Field.findByPk(model.get('parentKey'));
+ if (field) {
+ const { target } = field.get('options') || {};
+ if (target) {
+ model.set('collection_name', target);
+ }
+ }
+ }
+ });
+ Field.beforeUpdate(async (model) => {
+ if (!model.get('collection_name') && model.get('parentKey')) {
+ const field = await Field.findByPk(model.get('parentKey'));
+ if (field) {
+ const { target } = field.get('options') || {};
+ if (target) {
+ model.set('collection_name', target);
+ }
+ }
+ }
+ });
+ Field.afterCreate(async (model) => {
+ console.log('afterCreate');
+ if (model.get('interface') !== 'subTable') {
+ return;
+ }
+ const { target } = model.get('options') || {};
+ // const uiSchemaKey = model.get('ui_schema_key');
+ // console.log({ uiSchemaKey })
+ try {
+ let collection = await Collection.findOne({
+ where: {
+ name: target,
+ },
+ });
+ if (!collection) {
+ collection = await Collection.create({
+ name: target,
+ // ui_schema_key: uiSchemaKey,
+ });
+ }
+ // if (model.get('ui_schema_key')) {
+ // collection.set('ui_schema_key', model.get('ui_schema_key'));
+ // await collection.save({ hooks: false });
+ // }
+ await collection.migrate();
+ } catch (error) {
+ throw error;
+ }
+ });
+ Field.afterUpdate(async (model) => {
+ console.log('afterUpdate');
+ if (model.get('interface') !== 'subTable') {
+ return;
+ }
+ const { target } = model.get('options') || {};
+ try {
+ let collection = await Collection.findOne({
+ where: {
+ name: target,
+ },
+ });
+ if (!collection) {
+ collection = await Collection.create({
+ name: target,
+ });
+ }
+ // if (model.get('ui_schema_key')) {
+ // collection.set('ui_schema_key', model.get('ui_schema_key'));
+ // await collection.save({ hooks: false });
+ // }
+ await collection.migrate();
+ } catch (error) {
+ throw error;
+ }
});
this.resourcer.registerActionHandler('collections.fields:create', create);
this.resourcer.registerActionHandler('collections:findAll', findAll);
diff --git a/packages/plugin-ui-schema/src/models/ui-schema.ts b/packages/plugin-ui-schema/src/models/ui-schema.ts
index 5d9f80b951..0c95ea6312 100644
--- a/packages/plugin-ui-schema/src/models/ui-schema.ts
+++ b/packages/plugin-ui-schema/src/models/ui-schema.ts
@@ -1,12 +1,12 @@
import _ from 'lodash';
import { Model } from '@nocobase/database';
-import deepmerge from 'deepmerge';
+import { merge } from '../utils';
export class UISchema extends Model {
static async create(value?: any, options?: any): Promise {
// console.log({ value });
const attributes = this.toAttributes(_.cloneDeep(value));
- console.log({ attributes })
+ // console.log({ attributes })
// @ts-ignore
const model: Model = await super.create(attributes, options);
if (!attributes.children) {
@@ -34,7 +34,9 @@ export class UISchema extends Model {
];
const attrs = _.pick(data, keys);
const options = _.omit(data, keys);
- return { ...attrs, options: deepmerge(opts, options) };
+ return {
+ ...attrs, options: merge(opts, options)
+ };
}
static properties2children(properties = []) {
diff --git a/packages/plugin-users/src/collections/users.ts b/packages/plugin-users/src/collections/users.ts
index 03419fe36b..63fe72d44e 100644
--- a/packages/plugin-users/src/collections/users.ts
+++ b/packages/plugin-users/src/collections/users.ts
@@ -7,165 +7,67 @@ export default {
// internal: true,
createdBy: false,
updatedBy: false,
+ privilege: 'undelete',
fields: [
{
interface: 'string',
type: 'string',
- name: 'username',
- title: '用户名',
- unique: true,
- required: true,
- createOnly: true,
- component: {
+ name: 'nickname',
+ uiSchema: {
type: 'string',
- showInTable: true,
- showInDetail: true,
- showInForm: true,
+ title: '昵称',
+ 'x-component': 'Input',
},
},
{
interface: 'email',
type: 'string',
name: 'email',
- title: '邮箱',
unique: true,
- required: true,
- createOnly: true,
- component: {
+ privilege: 'undelete',
+ uiSchema: {
type: 'string',
- showInTable: true,
- showInDetail: true,
- showInForm: true,
- },
- },
- {
- interface: 'string',
- type: 'string',
- name: 'nickname',
- title: '昵称',
- required: true,
- component: {
- type: 'string',
- showInTable: true,
- showInDetail: true,
- showInForm: true,
- },
- },
- {
- interface: 'phone',
- type: 'string',
- name: 'phone',
- unique: true,
- title: '手机号',
- component: {
- type: 'string',
- showInTable: true,
- showInDetail: true,
- showInForm: true,
+ title: '邮箱',
+ 'x-component': 'Input',
+ require: true,
},
},
{
interface: 'password',
type: 'password',
name: 'password',
- title: '密码',
- hidden: true,
- component: {
- type: 'password',
- showInForm: true,
+ privilege: 'undelete',
+ uiSchema: {
+ type: 'string',
+ title: '密码',
+ 'x-component': 'Password',
},
},
{
- interface: 'string',
+ interface: 'password',
type: 'string',
name: 'token',
- title: 'Token',
unique: true,
hidden: true,
- filterable: false,
- developerMode: true,
+ privilege: 'undelete',
+ uiSchema: {
+ type: 'string',
+ title: 'Token',
+ 'x-component': 'Password',
+ },
},
{
- interface: 'string',
+ interface: 'password',
type: 'string',
name: 'reset_token',
- title: 'Reset Token',
unique: true,
hidden: true,
- filterable: false,
- developerMode: true,
- },
- ],
- actions: [
- {
- type: 'list',
- name: 'list',
- title: '查看',
- },
- {
- type: 'destroy',
- name: 'destroy',
- title: '删除',
- },
- {
- type: 'create',
- name: 'create',
- title: '新增',
- viewName: 'form',
- },
- {
- type: 'update',
- name: 'update',
- title: '编辑',
- viewName: 'form',
- },
- ],
- views_v2: [
- {
- developerMode: true,
- type: 'table',
- name: 'table',
- title: '全部数据',
- labelField: 'nickname',
- actions: [
- {
- name: 'create',
- type: 'create',
- title: '新增',
- viewName: 'form',
- },
- {
- name: 'destroy',
- type: 'destroy',
- title: '删除',
- },
- ],
- fields: ['email', 'nickname', 'phone', 'roles'],
- detailsOpenMode: 'drawer', // window
- details: ['form'],
- sort: ['id'],
- },
- {
- developerMode: true,
- type: 'descriptions',
- name: 'descriptions',
- title: '详情',
- fields: ['email', 'nickname', 'phone', 'roles'],
- actions: [
- {
- name: 'update',
- type: 'update',
- title: '编辑',
- viewName: 'form',
- },
- ],
- },
- {
- developerMode: true,
- type: 'form',
- name: 'form',
- title: '表单',
- fields: ['email', 'nickname', 'phone', 'password', 'roles'],
+ privilege: 'undelete',
+ uiSchema: {
+ type: 'string',
+ title: 'Reset Token',
+ 'x-component': 'Password',
+ },
},
],
} as TableOptions;