lanjianrong vor 3 Jahren
Ursprung
Commit
50ec5e34f4
100 geänderte Dateien mit 4661 neuen und 1 gelöschten Zeilen
  1. 2 1
      .eslintignore
  2. 1 0
      package.json
  3. 18 0
      src/pages/Schema/Designable/antd/common/Container/index.tsx
  4. 7 0
      src/pages/Schema/Designable/antd/common/Container/styles.less
  5. 18 0
      src/pages/Schema/Designable/antd/common/FormItemSwitcher/index.tsx
  6. 25 0
      src/pages/Schema/Designable/antd/common/LoadTemplate/index.tsx
  7. 79 0
      src/pages/Schema/Designable/antd/components/ArrayBase/index.ts
  8. 1 0
      src/pages/Schema/Designable/antd/components/ArrayCards/index.ts
  9. 248 0
      src/pages/Schema/Designable/antd/components/ArrayCards/preview.tsx
  10. 5 0
      src/pages/Schema/Designable/antd/components/ArrayCards/styles.less
  11. 1 0
      src/pages/Schema/Designable/antd/components/ArrayTable/index.ts
  12. 440 0
      src/pages/Schema/Designable/antd/components/ArrayTable/preview.tsx
  13. 5 0
      src/pages/Schema/Designable/antd/components/ArrayTable/styles.less
  14. 1 0
      src/pages/Schema/Designable/antd/components/Card/index.ts
  15. 46 0
      src/pages/Schema/Designable/antd/components/Card/preview.tsx
  16. 1 0
      src/pages/Schema/Designable/antd/components/Cascader/index.ts
  17. 33 0
      src/pages/Schema/Designable/antd/components/Cascader/preview.tsx
  18. 1 0
      src/pages/Schema/Designable/antd/components/Checkbox/index.ts
  19. 38 0
      src/pages/Schema/Designable/antd/components/Checkbox/preview.tsx
  20. 1 0
      src/pages/Schema/Designable/antd/components/DatePicker/index.ts
  21. 61 0
      src/pages/Schema/Designable/antd/components/DatePicker/preview.tsx
  22. 2 0
      src/pages/Schema/Designable/antd/components/Field/index.ts
  23. 161 0
      src/pages/Schema/Designable/antd/components/Field/preview.tsx
  24. 214 0
      src/pages/Schema/Designable/antd/components/Field/shared.ts
  25. 1 0
      src/pages/Schema/Designable/antd/components/Form/index.tsx
  26. 64 0
      src/pages/Schema/Designable/antd/components/Form/preview.tsx
  27. 34 0
      src/pages/Schema/Designable/antd/components/Form/styles.less
  28. 1 0
      src/pages/Schema/Designable/antd/components/FormCollapse/index.ts
  29. 177 0
      src/pages/Schema/Designable/antd/components/FormCollapse/preview.tsx
  30. 1 0
      src/pages/Schema/Designable/antd/components/FormGrid/index.ts
  31. 146 0
      src/pages/Schema/Designable/antd/components/FormGrid/preview.tsx
  32. 5 0
      src/pages/Schema/Designable/antd/components/FormGrid/styles.less
  33. 1 0
      src/pages/Schema/Designable/antd/components/FormLayout/index.ts
  34. 35 0
      src/pages/Schema/Designable/antd/components/FormLayout/preview.ts
  35. 1 0
      src/pages/Schema/Designable/antd/components/FormTab/index.ts
  36. 171 0
      src/pages/Schema/Designable/antd/components/FormTab/preview.tsx
  37. 1 0
      src/pages/Schema/Designable/antd/components/Input/index.ts
  38. 61 0
      src/pages/Schema/Designable/antd/components/Input/preview.ts
  39. 1 0
      src/pages/Schema/Designable/antd/components/NumberPicker/index.ts
  40. 35 0
      src/pages/Schema/Designable/antd/components/NumberPicker/preview.ts
  41. 1 0
      src/pages/Schema/Designable/antd/components/Object/index.ts
  42. 30 0
      src/pages/Schema/Designable/antd/components/Object/preview.tsx
  43. 1 0
      src/pages/Schema/Designable/antd/components/Password/index.ts
  44. 33 0
      src/pages/Schema/Designable/antd/components/Password/preview.tsx
  45. 1 0
      src/pages/Schema/Designable/antd/components/Radio/index.ts
  46. 38 0
      src/pages/Schema/Designable/antd/components/Radio/preview.tsx
  47. 1 0
      src/pages/Schema/Designable/antd/components/Rate/index.ts
  48. 34 0
      src/pages/Schema/Designable/antd/components/Rate/preview.tsx
  49. 1 0
      src/pages/Schema/Designable/antd/components/Select/index.ts
  50. 33 0
      src/pages/Schema/Designable/antd/components/Select/preview.tsx
  51. 1 0
      src/pages/Schema/Designable/antd/components/Slider/index.ts
  52. 34 0
      src/pages/Schema/Designable/antd/components/Slider/preview.tsx
  53. 1 0
      src/pages/Schema/Designable/antd/components/Space/index.ts
  54. 35 0
      src/pages/Schema/Designable/antd/components/Space/preview.tsx
  55. 1 0
      src/pages/Schema/Designable/antd/components/Switch/index.ts
  56. 34 0
      src/pages/Schema/Designable/antd/components/Switch/preview.tsx
  57. 1 0
      src/pages/Schema/Designable/antd/components/Text/index.ts
  58. 52 0
      src/pages/Schema/Designable/antd/components/Text/preview.tsx
  59. 10 0
      src/pages/Schema/Designable/antd/components/Text/styles.less
  60. 1 0
      src/pages/Schema/Designable/antd/components/TimePicker/index.ts
  61. 61 0
      src/pages/Schema/Designable/antd/components/TimePicker/preview.tsx
  62. 1 0
      src/pages/Schema/Designable/antd/components/Transfer/index.ts
  63. 33 0
      src/pages/Schema/Designable/antd/components/Transfer/preview.tsx
  64. 1 0
      src/pages/Schema/Designable/antd/components/TreeSelect/index.ts
  65. 33 0
      src/pages/Schema/Designable/antd/components/TreeSelect/preview.tsx
  66. 1 0
      src/pages/Schema/Designable/antd/components/Upload/index.ts
  67. 67 0
      src/pages/Schema/Designable/antd/components/Upload/preview.tsx
  68. 27 0
      src/pages/Schema/Designable/antd/components/index.ts
  69. 1 0
      src/pages/Schema/Designable/antd/hooks/index.ts
  70. 23 0
      src/pages/Schema/Designable/antd/hooks/useDropTemplate.ts
  71. 3 0
      src/pages/Schema/Designable/antd/index.ts
  72. 87 0
      src/pages/Schema/Designable/antd/locales/ArrayBase.ts
  73. 20 0
      src/pages/Schema/Designable/antd/locales/ArrayCards.ts
  74. 122 0
      src/pages/Schema/Designable/antd/locales/ArrayTable.ts
  75. 44 0
      src/pages/Schema/Designable/antd/locales/Card.ts
  76. 60 0
      src/pages/Schema/Designable/antd/locales/Cascader.ts
  77. 11 0
      src/pages/Schema/Designable/antd/locales/Checkbox.ts
  78. 53 0
      src/pages/Schema/Designable/antd/locales/Component.ts
  79. 88 0
      src/pages/Schema/Designable/antd/locales/DatePicker.ts
  80. 316 0
      src/pages/Schema/Designable/antd/locales/Field.ts
  81. 119 0
      src/pages/Schema/Designable/antd/locales/Form.ts
  82. 83 0
      src/pages/Schema/Designable/antd/locales/FormCollapse.ts
  83. 77 0
      src/pages/Schema/Designable/antd/locales/FormGrid.ts
  84. 122 0
      src/pages/Schema/Designable/antd/locales/FormLayout.ts
  85. 83 0
      src/pages/Schema/Designable/antd/locales/FormTab.ts
  86. 50 0
      src/pages/Schema/Designable/antd/locales/Input.ts
  87. 81 0
      src/pages/Schema/Designable/antd/locales/NumberPicker.ts
  88. 11 0
      src/pages/Schema/Designable/antd/locales/Object.ts
  89. 14 0
      src/pages/Schema/Designable/antd/locales/Password.ts
  90. 29 0
      src/pages/Schema/Designable/antd/locales/Radio.ts
  91. 32 0
      src/pages/Schema/Designable/antd/locales/Rate.ts
  92. 102 0
      src/pages/Schema/Designable/antd/locales/Select.ts
  93. 73 0
      src/pages/Schema/Designable/antd/locales/Slider.ts
  94. 50 0
      src/pages/Schema/Designable/antd/locales/Space.ts
  95. 11 0
      src/pages/Schema/Designable/antd/locales/Switch.ts
  96. 38 0
      src/pages/Schema/Designable/antd/locales/Text.ts
  97. 35 0
      src/pages/Schema/Designable/antd/locales/TextArea.ts
  98. 74 0
      src/pages/Schema/Designable/antd/locales/TimePicker.ts
  99. 38 0
      src/pages/Schema/Designable/antd/locales/Transfer.ts
  100. 0 0
      src/pages/Schema/Designable/antd/locales/TreeSelect.ts

+ 2 - 1
.eslintignore

@@ -5,4 +5,5 @@
 public
 dist
 .umi
-mock
+mock
+/src/pages/Schema/Designable/antd

+ 1 - 0
package.json

@@ -54,6 +54,7 @@
     "@ant-design/pro-layout": "6.32.2",
     "@ant-design/pro-table": "^2.30.8",
     "@designable/core": "^1.0.0-beta.43",
+    "@designable/formily-setters": "^1.0.0-beta.43",
     "@designable/formily-transformer": "^1.0.0-beta.43",
     "@designable/react": "^1.0.0-beta.43",
     "@designable/react-settings-form": "^1.0.0-beta.43",

+ 18 - 0
src/pages/Schema/Designable/antd/common/Container/index.tsx

@@ -0,0 +1,18 @@
+import React from 'react'
+import { observer } from '@formily/reactive-react'
+import { DroppableWidget } from '@designable/react'
+import './styles.less'
+
+export const Container: React.FC = observer(props => {
+  return <DroppableWidget>{props.children}</DroppableWidget>
+})
+
+export const withContainer = (Target: React.JSXElementConstructor<any>) => {
+  return (props: any) => {
+    return (
+      <DroppableWidget>
+        <Target {...props} />
+      </DroppableWidget>
+    )
+  }
+}

+ 7 - 0
src/pages/Schema/Designable/antd/common/Container/styles.less

@@ -0,0 +1,7 @@
+@import '~antd/lib/style/themes/default.less';
+
+.dn-form-container {
+  margin: 0 !important;
+  padding: 20px;
+  border: 1px solid @border-color-split;
+}

+ 18 - 0
src/pages/Schema/Designable/antd/common/FormItemSwitcher/index.tsx

@@ -0,0 +1,18 @@
+import React from 'react'
+import { Switch } from 'antd'
+
+export interface IFormItemSwitcherProps {
+  value?: string
+  onChange?: (value: string) => void
+}
+
+export const FormItemSwitcher: React.FC<IFormItemSwitcherProps> = props => {
+  return (
+    <Switch
+      checked={props.value === 'FormItem'}
+      onChange={value => {
+        props.onChange(value ? 'FormItem' : undefined)
+      }}
+    />
+  )
+}

+ 25 - 0
src/pages/Schema/Designable/antd/common/LoadTemplate/index.tsx

@@ -0,0 +1,25 @@
+import React from 'react'
+import { NodeActionsWidget } from '@designable/react'
+
+export interface ITemplateAction {
+  title: React.ReactNode
+  tooltip?: React.ReactNode
+  icon?: string | React.ReactNode
+  onClick: () => void
+}
+
+export interface ILoadTemplateProps {
+  className?: string
+  style?: React.CSSProperties
+  actions?: ITemplateAction[]
+}
+
+export const LoadTemplate: React.FC<ILoadTemplateProps> = props => {
+  return (
+    <NodeActionsWidget>
+      {props.actions?.map((action, key) => {
+        return <NodeActionsWidget.Action {...action} key={key} />
+      })}
+    </NodeActionsWidget>
+  )
+}

+ 79 - 0
src/pages/Schema/Designable/antd/components/ArrayBase/index.ts

@@ -0,0 +1,79 @@
+import { createBehavior } from '@designable/core'
+import { createFieldSchema, createVoidFieldSchema } from '../Field'
+import { AllSchemas } from '../../schemas'
+import { AllLocales } from '../../locales'
+
+export const createArrayBehavior = (name: string) => {
+  return createBehavior(
+    {
+      name,
+      extends: ['Field'],
+      selector: node => node.props['x-component'] === name,
+      designerProps: {
+        droppable: true,
+        propsSchema: createFieldSchema(AllSchemas[name])
+      },
+      designerLocales: AllLocales[name]
+    },
+    {
+      name: `${name}.Addition`,
+      extends: ['Field'],
+      selector: node => node.props['x-component'] === `${name}.Addition`,
+      designerProps: {
+        allowDrop(parent) {
+          return parent.props['x-component'] === name
+        },
+        propsSchema: createVoidFieldSchema(AllSchemas[name].Addition)
+      },
+      designerLocales: AllLocales.ArrayAddition
+    },
+    {
+      name: `${name}.Remove`,
+      extends: ['Field'],
+      selector: node => node.props['x-component'] === `${name}.Remove`,
+      designerProps: {
+        allowDrop(parent) {
+          return parent.props['x-component'] === name
+        },
+        propsSchema: createVoidFieldSchema()
+      },
+      designerLocales: AllLocales.ArrayRemove
+    },
+    {
+      name: `${name}.Index`,
+      extends: ['Field'],
+      selector: node => node.props['x-component'] === `${name}.Index`,
+      designerProps: {
+        allowDrop(parent) {
+          return parent.props['x-component'] === name
+        },
+        propsSchema: createVoidFieldSchema()
+      },
+      designerLocales: AllLocales.ArrayIndex
+    },
+    {
+      name: `${name}.MoveUp`,
+      extends: ['Field'],
+      selector: node => node.props['x-component'] === `${name}.MoveUp`,
+      designerProps: {
+        allowDrop(parent) {
+          return parent.props['x-component'] === name
+        },
+        propsSchema: createVoidFieldSchema()
+      },
+      designerLocales: AllLocales.ArrayMoveUp
+    },
+    {
+      name: `${name}.MoveDown`,
+      extends: ['Field'],
+      selector: node => node.props['x-component'] === `${name}.MoveDown`,
+      designerProps: {
+        allowDrop(parent) {
+          return parent.props['x-component'] === 'ArrayCards'
+        },
+        propsSchema: createVoidFieldSchema()
+      },
+      designerLocales: AllLocales.ArrayMoveDown
+    }
+  )
+}

+ 1 - 0
src/pages/Schema/Designable/antd/components/ArrayCards/index.ts

@@ -0,0 +1 @@
+export * from './preview'

+ 248 - 0
src/pages/Schema/Designable/antd/components/ArrayCards/preview.tsx

@@ -0,0 +1,248 @@
+import React, { Fragment } from 'react'
+import { Card, CardProps } from 'antd'
+import { TreeNode, createResource } from '@designable/core'
+import {
+  useTreeNode,
+  TreeNodeWidget,
+  DroppableWidget,
+  useNodeIdProps,
+  DnFC
+} from '@designable/react'
+import { ArrayBase } from '@formily/antd'
+import { observer } from '@formily/react'
+import { LoadTemplate } from '../../common/LoadTemplate'
+import { useDropTemplate } from '../../hooks'
+import {
+  hasNodeByComponentPath,
+  queryNodesByComponentPath,
+  createEnsureTypeItemsNode,
+  findNodeByComponentPath,
+  createNodeId
+} from '../../shared'
+import { createArrayBehavior } from '../ArrayBase'
+import cls from 'classnames'
+import './styles.less'
+
+const ensureObjectItemsNode = createEnsureTypeItemsNode('object')
+
+const isArrayCardsOperation = (name: string) =>
+  name === 'ArrayCards.Remove' || name === 'ArrayCards.MoveDown' || name === 'ArrayCards.MoveUp'
+
+export const ArrayCards: DnFC<CardProps> = observer(props => {
+  const node = useTreeNode()
+  const nodeId = useNodeIdProps()
+  const designer = useDropTemplate('ArrayCards', source => {
+    const indexNode = new TreeNode({
+      componentName: node.componentName,
+      props: {
+        type: 'void',
+        'x-component': 'ArrayCards.Index'
+      }
+    })
+    const additionNode = new TreeNode({
+      componentName: node.componentName,
+      props: {
+        type: 'void',
+        title: 'Addition',
+        'x-component': 'ArrayCards.Addition'
+      }
+    })
+    const removeNode = new TreeNode({
+      componentName: node.componentName,
+      props: {
+        type: 'void',
+        title: 'Addition',
+        'x-component': 'ArrayCards.Remove'
+      }
+    })
+    const moveDownNode = new TreeNode({
+      componentName: node.componentName,
+      props: {
+        type: 'void',
+        title: 'Addition',
+        'x-component': 'ArrayCards.MoveDown'
+      }
+    })
+    const moveUpNode = new TreeNode({
+      componentName: node.componentName,
+      props: {
+        type: 'void',
+        title: 'Addition',
+        'x-component': 'ArrayCards.MoveUp'
+      }
+    })
+
+    const objectNode = new TreeNode({
+      componentName: node.componentName,
+      props: {
+        type: 'object'
+      },
+      children: [indexNode, ...source, removeNode, moveDownNode, moveUpNode]
+    })
+    return [objectNode, additionNode]
+  })
+  const renderCard = () => {
+    if (node.children.length === 0) return <DroppableWidget />
+    const additions = queryNodesByComponentPath(node, ['ArrayCards', 'ArrayCards.Addition'])
+    const indexes = queryNodesByComponentPath(node, ['ArrayCards', '*', 'ArrayCards.Index'])
+    const operations = queryNodesByComponentPath(node, ['ArrayCards', '*', isArrayCardsOperation])
+    const children = queryNodesByComponentPath(node, [
+      'ArrayCards',
+      '*',
+      name => name.indexOf('ArrayCards.') === -1
+    ])
+    return (
+      <ArrayBase disabled>
+        <ArrayBase.Item index={0} record={null}>
+          <Card
+            {...props}
+            title={
+              <Fragment>
+                {indexes.map((node, key) => (
+                  <TreeNodeWidget key={key} node={node} />
+                ))}
+                <span data-content-editable="x-component-props.title">{props.title}</span>
+              </Fragment>
+            }
+            className={cls('ant-formily-array-cards-item', props.className)}
+            extra={
+              <Fragment>
+                {operations.map(node => (
+                  <TreeNodeWidget key={node.id} node={node} />
+                ))}
+                {props.extra}
+              </Fragment>
+            }
+          >
+            <div {...createNodeId(designer, ensureObjectItemsNode(node).id)}>
+              {children.length ? (
+                children.map(node => <TreeNodeWidget key={node.id} node={node} />)
+              ) : (
+                <DroppableWidget />
+              )}
+            </div>
+          </Card>
+        </ArrayBase.Item>
+        {additions.map(node => (
+          <TreeNodeWidget key={node.id} node={node} />
+        ))}
+      </ArrayBase>
+    )
+  }
+
+  return (
+    <div {...nodeId} className="dn-array-cards">
+      {renderCard()}
+      <LoadTemplate
+        actions={[
+          {
+            title: node.getMessage('addIndex'),
+            icon: 'AddIndex',
+            onClick: () => {
+              if (hasNodeByComponentPath(node, ['ArrayCards', '*', 'ArrayCards.Index'])) return
+              const indexNode = new TreeNode({
+                componentName: node.componentName,
+                props: {
+                  type: 'void',
+                  'x-component': 'ArrayCards.Index'
+                }
+              })
+              ensureObjectItemsNode(node).append(indexNode)
+            }
+          },
+
+          {
+            title: node.getMessage('addOperation'),
+            icon: 'AddOperation',
+            onClick: () => {
+              const oldAdditionNode = findNodeByComponentPath(node, [
+                'ArrayCards',
+                'ArrayCards.Addition'
+              ])
+              if (!oldAdditionNode) {
+                const additionNode = new TreeNode({
+                  componentName: node.componentName,
+                  props: {
+                    type: 'void',
+                    title: 'Addition',
+                    'x-component': 'ArrayCards.Addition'
+                  }
+                })
+                ensureObjectItemsNode(node).insertAfter(additionNode)
+              }
+              const oldRemoveNode = findNodeByComponentPath(node, [
+                'ArrayCards',
+                '*',
+                'ArrayCards.Remove'
+              ])
+              const oldMoveDownNode = findNodeByComponentPath(node, [
+                'ArrayCards',
+                '*',
+                'ArrayCards.MoveDown'
+              ])
+              const oldMoveUpNode = findNodeByComponentPath(node, [
+                'ArrayCards',
+                '*',
+                'ArrayCards.MoveUp'
+              ])
+              if (!oldRemoveNode) {
+                ensureObjectItemsNode(node).append(
+                  new TreeNode({
+                    componentName: node.componentName,
+                    props: {
+                      type: 'void',
+                      'x-component': 'ArrayCards.Remove'
+                    }
+                  })
+                )
+              }
+              if (!oldMoveDownNode) {
+                ensureObjectItemsNode(node).append(
+                  new TreeNode({
+                    componentName: node.componentName,
+                    props: {
+                      type: 'void',
+                      'x-component': 'ArrayCards.MoveDown'
+                    }
+                  })
+                )
+              }
+              if (!oldMoveUpNode) {
+                ensureObjectItemsNode(node).append(
+                  new TreeNode({
+                    componentName: node.componentName,
+                    props: {
+                      type: 'void',
+                      'x-component': 'ArrayCards.MoveUp'
+                    }
+                  })
+                )
+              }
+            }
+          }
+        ]}
+      />
+    </div>
+  )
+})
+
+ArrayBase.mixin(ArrayCards)
+
+ArrayCards.Behavior = createArrayBehavior('ArrayCards')
+
+ArrayCards.Resource = createResource({
+  icon: 'ArrayCardsSource',
+  elements: [
+    {
+      componentName: 'Field',
+      props: {
+        type: 'array',
+        'x-decorator': 'FormItem',
+        'x-component': 'ArrayCards',
+        'x-component-props': {
+          title: `Title`
+        }
+      }
+    }
+  ]
+})

+ 5 - 0
src/pages/Schema/Designable/antd/components/ArrayCards/styles.less

@@ -0,0 +1,5 @@
+@import '~antd/lib/style/themes/default.less';
+
+.dn-array-cards {
+  background-color: @component-background;
+}

+ 1 - 0
src/pages/Schema/Designable/antd/components/ArrayTable/index.ts

@@ -0,0 +1 @@
+export * from './preview'

+ 440 - 0
src/pages/Schema/Designable/antd/components/ArrayTable/preview.tsx

@@ -0,0 +1,440 @@
+import React from 'react'
+import { Table, TableProps } from 'antd'
+import { TreeNode, createBehavior, createResource } from '@designable/core'
+import {
+  useTreeNode,
+  TreeNodeWidget,
+  DroppableWidget,
+  useNodeIdProps,
+  DnFC
+} from '@designable/react'
+import { ArrayBase } from '@formily/antd'
+import { observer } from '@formily/react'
+import { LoadTemplate } from '../../common/LoadTemplate'
+import cls from 'classnames'
+import {
+  queryNodesByComponentPath,
+  hasNodeByComponentPath,
+  findNodeByComponentPath,
+  createEnsureTypeItemsNode
+} from '../../shared'
+import { useDropTemplate } from '../../hooks'
+import { createArrayBehavior } from '../ArrayBase'
+import './styles.less'
+import { createVoidFieldSchema } from '../Field'
+import { AllSchemas } from '../../schemas'
+import { AllLocales } from '../../locales'
+
+const ensureObjectItemsNode = createEnsureTypeItemsNode('object')
+
+const HeaderCell: React.FC = (props: any) => {
+  return (
+    <th {...props} data-designer-node-id={props.className.match(/data-id\:([^\s]+)/)?.[1]}>
+      {props.children}
+    </th>
+  )
+}
+
+const BodyCell: React.FC = (props: any) => {
+  return (
+    <td {...props} data-designer-node-id={props.className.match(/data-id\:([^\s]+)/)?.[1]}>
+      {props.children}
+    </td>
+  )
+}
+
+export const ArrayTable: DnFC<TableProps<any>> = observer(props => {
+  const node = useTreeNode()
+  const nodeId = useNodeIdProps()
+  useDropTemplate('ArrayTable', source => {
+    const sortHandleNode = new TreeNode({
+      componentName: 'Field',
+      props: {
+        type: 'void',
+        'x-component': 'ArrayTable.Column',
+        'x-component-props': {
+          title: `Title`
+        }
+      },
+      children: [
+        {
+          componentName: 'Field',
+          props: {
+            type: 'void',
+            'x-component': 'ArrayTable.SortHandle'
+          }
+        }
+      ]
+    })
+    const indexNode = new TreeNode({
+      componentName: 'Field',
+      props: {
+        type: 'void',
+        'x-component': 'ArrayTable.Column',
+        'x-component-props': {
+          title: `Title`
+        }
+      },
+      children: [
+        {
+          componentName: 'Field',
+          props: {
+            type: 'void',
+            'x-component': 'ArrayTable.Index'
+          }
+        }
+      ]
+    })
+    const columnNode = new TreeNode({
+      componentName: 'Field',
+      props: {
+        type: 'void',
+        'x-component': 'ArrayTable.Column',
+        'x-component-props': {
+          title: `Title`
+        }
+      },
+      children: source.map(node => {
+        node.props.title = undefined
+        return node
+      })
+    })
+
+    const operationNode = new TreeNode({
+      componentName: 'Field',
+      props: {
+        type: 'void',
+        'x-component': 'ArrayTable.Column',
+        'x-component-props': {
+          title: `Title`
+        }
+      },
+      children: [
+        {
+          componentName: 'Field',
+          props: {
+            type: 'void',
+            'x-component': 'ArrayTable.Remove'
+          }
+        },
+        {
+          componentName: 'Field',
+          props: {
+            type: 'void',
+            'x-component': 'ArrayTable.MoveDown'
+          }
+        },
+        {
+          componentName: 'Field',
+          props: {
+            type: 'void',
+            'x-component': 'ArrayTable.MoveUp'
+          }
+        }
+      ]
+    })
+    const objectNode = new TreeNode({
+      componentName: 'Field',
+      props: {
+        type: 'object'
+      },
+      children: [sortHandleNode, indexNode, columnNode, operationNode]
+    })
+    const additionNode = new TreeNode({
+      componentName: 'Field',
+      props: {
+        type: 'void',
+        title: 'Addition',
+        'x-component': 'ArrayTable.Addition'
+      }
+    })
+    return [objectNode, additionNode]
+  })
+  const columns = queryNodesByComponentPath(node, ['ArrayTable', '*', 'ArrayTable.Column'])
+  const additions = queryNodesByComponentPath(node, ['ArrayTable', 'ArrayTable.Addition'])
+  const defaultRowKey = () => {
+    return node.id
+  }
+
+  const renderTable = () => {
+    if (node.children.length === 0) return <DroppableWidget />
+    return (
+      <ArrayBase disabled>
+        <Table
+          size="small"
+          bordered
+          {...props}
+          scroll={{ x: '100%' }}
+          className={cls('ant-formily-array-table', props.className)}
+          style={{ marginBottom: 10, ...props.style }}
+          rowKey={defaultRowKey}
+          dataSource={[{ id: '1' }]}
+          pagination={false}
+          components={{
+            header: {
+              cell: HeaderCell
+            },
+            body: {
+              cell: BodyCell
+            }
+          }}
+        >
+          {columns.map(node => {
+            const children = node.children.map(child => {
+              return <TreeNodeWidget node={child} key={child.id} />
+            })
+            const props = node.props['x-component-props']
+            return (
+              <Table.Column
+                {...props}
+                title={<div data-content-editable="x-component-props.title">{props.title}</div>}
+                dataIndex={node.id}
+                className={`data-id:${node.id}`}
+                key={node.id}
+                render={(value, record, key) => {
+                  return (
+                    <ArrayBase.Item key={key} index={key} record={null}>
+                      {children.length > 0 ? children : 'Droppable'}
+                    </ArrayBase.Item>
+                  )
+                }}
+              />
+            )
+          })}
+          {columns.length === 0 && <Table.Column render={() => <DroppableWidget />} />}
+        </Table>
+        {additions.map(child => {
+          return <TreeNodeWidget node={child} key={child.id} />
+        })}
+      </ArrayBase>
+    )
+  }
+
+  useDropTemplate('ArrayTable.Column', source => {
+    return source.map(node => {
+      node.props.title = undefined
+      return node
+    })
+  })
+
+  return (
+    <div {...nodeId} className="dn-array-table">
+      {renderTable()}
+      <LoadTemplate
+        actions={[
+          {
+            title: node.getMessage('addSortHandle'),
+            icon: 'AddSort',
+            onClick: () => {
+              if (
+                hasNodeByComponentPath(node, [
+                  'ArrayTable',
+                  '*',
+                  'ArrayTable.Column',
+                  'ArrayTable.SortHandle'
+                ])
+              )
+                return
+              const tableColumn = new TreeNode({
+                componentName: 'Field',
+                props: {
+                  type: 'void',
+                  'x-component': 'ArrayTable.Column',
+                  'x-component-props': {
+                    title: `Title`
+                  }
+                },
+                children: [
+                  {
+                    componentName: 'Field',
+                    props: {
+                      type: 'void',
+                      'x-component': 'ArrayTable.SortHandle'
+                    }
+                  }
+                ]
+              })
+              ensureObjectItemsNode(node).prepend(tableColumn)
+            }
+          },
+          {
+            title: node.getMessage('addIndex'),
+            icon: 'AddIndex',
+            onClick: () => {
+              if (
+                hasNodeByComponentPath(node, [
+                  'ArrayTable',
+                  '*',
+                  'ArrayTable.Column',
+                  'ArrayTable.Index'
+                ])
+              )
+                return
+              const tableColumn = new TreeNode({
+                componentName: 'Field',
+                props: {
+                  type: 'void',
+                  'x-component': 'ArrayTable.Column',
+                  'x-component-props': {
+                    title: `Title`
+                  }
+                },
+                children: [
+                  {
+                    componentName: 'Field',
+                    props: {
+                      type: 'void',
+                      'x-component': 'ArrayTable.Index'
+                    }
+                  }
+                ]
+              })
+              const sortNode = findNodeByComponentPath(node, [
+                'ArrayTable',
+                '*',
+                'ArrayTable.Column',
+                'ArrayTable.SortHandle'
+              ])
+              if (sortNode) {
+                sortNode.parent.insertAfter(tableColumn)
+              } else {
+                ensureObjectItemsNode(node).prepend(tableColumn)
+              }
+            }
+          },
+          {
+            title: node.getMessage('addColumn'),
+            icon: 'AddColumn',
+            onClick: () => {
+              const operationNode = findNodeByComponentPath(node, [
+                'ArrayTable',
+                '*',
+                'ArrayTable.Column',
+                name => {
+                  return (
+                    name === 'ArrayTable.Remove' ||
+                    name === 'ArrayTable.MoveDown' ||
+                    name === 'ArrayTable.MoveUp'
+                  )
+                }
+              ])
+              const tableColumn = new TreeNode({
+                componentName: 'Field',
+                props: {
+                  type: 'void',
+                  'x-component': 'ArrayTable.Column',
+                  'x-component-props': {
+                    title: `Title`
+                  }
+                }
+              })
+              if (operationNode) {
+                operationNode.parent.insertBefore(tableColumn)
+              } else {
+                ensureObjectItemsNode(node).append(tableColumn)
+              }
+            }
+          },
+          {
+            title: node.getMessage('addOperation'),
+            icon: 'AddOperation',
+            onClick: () => {
+              const oldOperationNode = findNodeByComponentPath(node, [
+                'ArrayTable',
+                '*',
+                'ArrayTable.Column',
+                name => {
+                  return (
+                    name === 'ArrayTable.Remove' ||
+                    name === 'ArrayTable.MoveDown' ||
+                    name === 'ArrayTable.MoveUp'
+                  )
+                }
+              ])
+              const oldAdditionNode = findNodeByComponentPath(node, [
+                'ArrayTable',
+                'ArrayTable.Addition'
+              ])
+              if (!oldOperationNode) {
+                const operationNode = new TreeNode({
+                  componentName: 'Field',
+                  props: {
+                    type: 'void',
+                    'x-component': 'ArrayTable.Column',
+                    'x-component-props': {
+                      title: `Title`
+                    }
+                  },
+                  children: [
+                    {
+                      componentName: 'Field',
+                      props: {
+                        type: 'void',
+                        'x-component': 'ArrayTable.Remove'
+                      }
+                    },
+                    {
+                      componentName: 'Field',
+                      props: {
+                        type: 'void',
+                        'x-component': 'ArrayTable.MoveDown'
+                      }
+                    },
+                    {
+                      componentName: 'Field',
+                      props: {
+                        type: 'void',
+                        'x-component': 'ArrayTable.MoveUp'
+                      }
+                    }
+                  ]
+                })
+                ensureObjectItemsNode(node).append(operationNode)
+              }
+              if (!oldAdditionNode) {
+                const additionNode = new TreeNode({
+                  componentName: 'Field',
+                  props: {
+                    type: 'void',
+                    title: 'Addition',
+                    'x-component': 'ArrayTable.Addition'
+                  }
+                })
+                ensureObjectItemsNode(node).insertAfter(additionNode)
+              }
+            }
+          }
+        ]}
+      />
+    </div>
+  )
+})
+
+ArrayBase.mixin(ArrayTable)
+
+ArrayTable.Behavior = createBehavior(createArrayBehavior('ArrayTable'), {
+  name: 'ArrayTable.Column',
+  extends: ['Field'],
+  selector: node => node.props['x-component'] === 'ArrayTable.Column',
+  designerProps: {
+    droppable: true,
+    allowDrop: node =>
+      node.props['type'] === 'object' && node.parent?.props?.['x-component'] === 'ArrayTable',
+    propsSchema: createVoidFieldSchema(AllSchemas.ArrayTable.Column)
+  },
+  designerLocales: AllLocales.ArrayTableColumn
+})
+
+ArrayTable.Resource = createResource({
+  icon: 'ArrayTableSource',
+  elements: [
+    {
+      componentName: 'Field',
+      props: {
+        type: 'array',
+        'x-decorator': 'FormItem',
+        'x-component': 'ArrayTable'
+      }
+    }
+  ]
+})

+ 5 - 0
src/pages/Schema/Designable/antd/components/ArrayTable/styles.less

@@ -0,0 +1,5 @@
+@import '~antd/lib/style/themes/default.less';
+
+.dn-array-table {
+  background-color: @component-background;
+}

+ 1 - 0
src/pages/Schema/Designable/antd/components/Card/index.ts

@@ -0,0 +1 @@
+export * from './preview'

+ 46 - 0
src/pages/Schema/Designable/antd/components/Card/preview.tsx

@@ -0,0 +1,46 @@
+import React from 'react'
+import { Card as AntdCard } from 'antd'
+
+import { createBehavior, createResource } from '@designable/core'
+import { DnFC } from '@designable/react'
+import { createVoidFieldSchema } from '../Field'
+import { AllSchemas } from '../../schemas'
+import { AllLocales } from '../../locales'
+
+export const Card: DnFC<React.ComponentProps<typeof AntdCard>> = props => {
+  return (
+    <AntdCard
+      {...props}
+      title={<span data-content-editable="x-component-props.title">{props.title}</span>}
+    >
+      {props.children}
+    </AntdCard>
+  )
+}
+
+Card.Behavior = createBehavior({
+  name: 'Card',
+  extends: ['Field'],
+  selector: node => node.props['x-component'] === 'Card',
+  designerProps: {
+    droppable: true,
+    propsSchema: createVoidFieldSchema(AllSchemas.Card)
+  },
+  designerLocales: AllLocales.Card
+})
+
+Card.Resource = createResource({
+  icon: 'CardSource',
+  elements: [
+    {
+      componentName: 'Field',
+      props: {
+        type: 'void',
+        'x-component': 'Card',
+        'x-component-props': {
+          title: 'Title'
+        }
+      }
+    }
+  ]
+})

+ 1 - 0
src/pages/Schema/Designable/antd/components/Cascader/index.ts

@@ -0,0 +1 @@
+export * from './preview'

+ 33 - 0
src/pages/Schema/Designable/antd/components/Cascader/preview.tsx

@@ -0,0 +1,33 @@
+import React from 'react'
+import { Cascader as FormilyCascader } from '@formily/antd'
+import { createBehavior, createResource } from '@designable/core'
+import { DnFC } from '@designable/react'
+import { createFieldSchema } from '../Field'
+import { AllSchemas } from '../../schemas'
+import { AllLocales } from '../../locales'
+
+export const Cascader: DnFC<React.ComponentProps<typeof FormilyCascader>> = FormilyCascader
+
+Cascader.Behavior = createBehavior({
+  name: 'Cascader',
+  extends: ['Field'],
+  selector: node => node.props['x-component'] === 'Cascader',
+  designerProps: {
+    propsSchema: createFieldSchema(AllSchemas.Cascader)
+  },
+  designerLocales: AllLocales.Cascader
+})
+
+Cascader.Resource = createResource({
+  icon: 'CascaderSource',
+  elements: [
+    {
+      componentName: 'Field',
+      props: {
+        title: 'Cascader',
+        'x-decorator': 'FormItem',
+        'x-component': 'Cascader'
+      }
+    }
+  ]
+})

+ 1 - 0
src/pages/Schema/Designable/antd/components/Checkbox/index.ts

@@ -0,0 +1 @@
+export * from './preview'

+ 38 - 0
src/pages/Schema/Designable/antd/components/Checkbox/preview.tsx

@@ -0,0 +1,38 @@
+import React from 'react'
+import { Checkbox as FormilyCheckbox } from '@formily/antd'
+import { createBehavior, createResource } from '@designable/core'
+import { DnFC } from '@designable/react'
+import { createFieldSchema } from '../Field'
+import { AllSchemas } from '../../schemas'
+import { AllLocales } from '../../locales'
+
+export const Checkbox: DnFC<React.ComponentProps<typeof FormilyCheckbox>> = FormilyCheckbox
+
+Checkbox.Behavior = createBehavior({
+  name: 'Checkbox.Group',
+  extends: ['Field'],
+  selector: node => node.props['x-component'] === 'Checkbox.Group',
+  designerProps: {
+    propsSchema: createFieldSchema(AllSchemas.Checkbox.Group)
+  },
+  designerLocales: AllLocales.CheckboxGroup
+})
+
+Checkbox.Resource = createResource({
+  icon: 'CheckboxGroupSource',
+  elements: [
+    {
+      componentName: 'Field',
+      props: {
+        type: 'Array<string | number>',
+        title: 'Checkbox Group',
+        'x-decorator': 'FormItem',
+        'x-component': 'Checkbox.Group',
+        enum: [
+          { label: '选项1', value: 1 },
+          { label: '选项2', value: 2 }
+        ]
+      }
+    }
+  ]
+})

+ 1 - 0
src/pages/Schema/Designable/antd/components/DatePicker/index.ts

@@ -0,0 +1 @@
+export * from './preview'

+ 61 - 0
src/pages/Schema/Designable/antd/components/DatePicker/preview.tsx

@@ -0,0 +1,61 @@
+import React from 'react'
+import { DatePicker as FormilyDatePicker } from '@formily/antd'
+import { createBehavior, createResource } from '@designable/core'
+import { DnFC } from '@designable/react'
+import { createFieldSchema } from '../Field'
+import { AllSchemas } from '../../schemas'
+import { AllLocales } from '../../locales'
+
+export const DatePicker: DnFC<React.ComponentProps<typeof FormilyDatePicker>> = FormilyDatePicker
+
+DatePicker.Behavior = createBehavior(
+  {
+    name: 'DatePicker',
+    extends: ['Field'],
+    selector: node => node.props['x-component'] === 'DatePicker',
+    designerProps: {
+      propsSchema: createFieldSchema(AllSchemas.DatePicker)
+    },
+    designerLocales: AllLocales.DatePicker
+  },
+  {
+    name: 'DatePicker.RangePicker',
+    extends: ['Field'],
+    selector: node => node.props['x-component'] === 'DatePicker.RangePicker',
+    designerProps: {
+      propsSchema: createFieldSchema(AllSchemas.DatePicker.RangePicker)
+    },
+    designerLocales: AllLocales.DateRangePicker
+  }
+)
+
+DatePicker.Resource = createResource(
+  {
+    icon: 'DatePickerSource',
+    elements: [
+      {
+        componentName: 'Field',
+        props: {
+          type: 'string',
+          title: 'DatePicker',
+          'x-decorator': 'FormItem',
+          'x-component': 'DatePicker'
+        }
+      }
+    ]
+  },
+  {
+    icon: 'DateRangePickerSource',
+    elements: [
+      {
+        componentName: 'Field',
+        props: {
+          type: 'string[]',
+          title: 'DateRangePicker',
+          'x-decorator': 'FormItem',
+          'x-component': 'DatePicker.RangePicker'
+        }
+      }
+    ]
+  }
+)

+ 2 - 0
src/pages/Schema/Designable/antd/components/Field/index.ts

@@ -0,0 +1,2 @@
+export * from './preview'
+export * from './shared'

+ 161 - 0
src/pages/Schema/Designable/antd/components/Field/preview.tsx

@@ -0,0 +1,161 @@
+import React from 'react'
+import { FormPath } from '@formily/core'
+import { toJS } from '@formily/reactive'
+import {
+  ArrayField,
+  Field as InternalField,
+  ObjectField,
+  VoidField,
+  observer,
+  ISchema,
+  Schema
+} from '@formily/react'
+import { FormItem } from '@formily/antd'
+import { each, reduce } from '@formily/shared'
+import { createBehavior } from '@designable/core'
+import { useDesigner, useTreeNode, useComponents, DnFC } from '@designable/react'
+import { isArr, isStr } from '@designable/shared'
+import { Container } from '../../common/Container'
+import { AllLocales } from '../../locales'
+
+Schema.silent(true)
+
+const SchemaStateMap = {
+  title: 'title',
+  description: 'description',
+  default: 'value',
+  enum: 'dataSource',
+  readOnly: 'readOnly',
+  writeOnly: 'editable',
+  required: 'required',
+  'x-content': 'content',
+  'x-value': 'value',
+  'x-editable': 'editable',
+  'x-disabled': 'disabled',
+  'x-read-pretty': 'readPretty',
+  'x-read-only': 'readOnly',
+  'x-visible': 'visible',
+  'x-hidden': 'hidden',
+  'x-display': 'display',
+  'x-pattern': 'pattern'
+}
+
+const NeedShownExpression = {
+  title: true,
+  description: true,
+  default: true,
+  'x-content': true,
+  'x-value': true
+}
+
+const isExpression = (val: any) => isStr(val) && /^\{\{.*\}\}$/.test(val)
+
+const filterExpression = (val: any) => {
+  if (typeof val === 'object') {
+    const isArray = isArr(val)
+    const results = reduce(
+      val,
+      (buf: any, value, key) => {
+        if (isExpression(value)) {
+          return buf
+        } else {
+          const results = filterExpression(value)
+          if (results === undefined || results === null) return buf
+          if (isArray) {
+            return buf.concat([results])
+          }
+          buf[key] = results
+          return buf
+        }
+      },
+      isArray ? [] : {}
+    )
+    return results
+  }
+  if (isExpression(val)) {
+    return
+  }
+  return val
+}
+
+const toDesignableFieldProps = (
+  schema: ISchema,
+  components: any,
+  nodeIdAttrName: string,
+  id: string
+) => {
+  const results: any = {}
+  each(SchemaStateMap, (fieldKey, schemaKey) => {
+    const value = schema[schemaKey]
+    if (isExpression(value)) {
+      if (!NeedShownExpression[schemaKey]) return
+      if (value) {
+        results[fieldKey] = value
+        return
+      }
+    } else if (value) {
+      results[fieldKey] = filterExpression(value)
+    }
+  })
+  if (!components.FormItem) {
+    components.FormItem = FormItem
+  }
+  const decorator = schema['x-decorator'] && FormPath.getIn(components, schema['x-decorator'])
+  const component = schema['x-component'] && FormPath.getIn(components, schema['x-component'])
+  const decoratorProps = schema['x-decorator-props'] || {}
+  const componentProps = schema['x-component-props'] || {}
+
+  if (decorator) {
+    results.decorator = [decorator, toJS(decoratorProps)]
+  }
+  if (component) {
+    results.component = [component, toJS(componentProps)]
+  }
+  if (decorator) {
+    FormPath.setIn(results.decorator[1], nodeIdAttrName, id)
+  } else if (component) {
+    FormPath.setIn(results.component[1], nodeIdAttrName, id)
+  }
+  results.title = results.title && <span data-content-editable="title">{results.title}</span>
+  results.description = results.description && (
+    <span data-content-editable="description">{results.description}</span>
+  )
+  return results
+}
+
+export const Field: DnFC<ISchema> = observer(props => {
+  const designer = useDesigner()
+  const components = useComponents()
+  const node = useTreeNode()
+  if (!node) return null
+  const fieldProps = toDesignableFieldProps(
+    props,
+    components,
+    designer.props.nodeIdAttrName,
+    node.id
+  )
+  if (props.type === 'object') {
+    return (
+      <Container>
+        <ObjectField {...fieldProps} name={node.id}>
+          {props.children}
+        </ObjectField>
+      </Container>
+    )
+  } else if (props.type === 'array') {
+    return <ArrayField {...fieldProps} name={node.id} />
+  } else if (node.props.type === 'void') {
+    return (
+      <VoidField {...fieldProps} name={node.id}>
+        {props.children}
+      </VoidField>
+    )
+  }
+  return <InternalField {...fieldProps} name={node.id} />
+})
+
+Field.Behavior = createBehavior({
+  name: 'Field',
+  selector: 'Field',
+  designerLocales: AllLocales.Field
+})

+ 214 - 0
src/pages/Schema/Designable/antd/components/Field/shared.ts

@@ -0,0 +1,214 @@
+import { ISchema } from '@formily/json-schema'
+import { ReactionsSetter, DataSourceSetter, ValidatorSetter } from '@designable/formily-setters'
+import { FormItemSwitcher } from '../../common/FormItemSwitcher'
+import { AllSchemas } from '../../schemas'
+
+export const createComponentSchema = (component: ISchema, decorator: ISchema) => {
+  return {
+    'component-group': component && {
+      type: 'void',
+      'x-component': 'CollapseItem',
+      'x-reactions': {
+        fulfill: {
+          state: {
+            visible: '{{!!$form.values["x-component"]}}'
+          }
+        }
+      },
+      properties: {
+        'x-component-props': component
+      }
+    },
+    'decorator-group': decorator && {
+      type: 'void',
+      'x-component': 'CollapseItem',
+      'x-component-props': { defaultExpand: false },
+      'x-reactions': {
+        fulfill: {
+          state: {
+            visible: '{{!!$form.values["x-decorator"]}}'
+          }
+        }
+      },
+      properties: {
+        'x-decorator-props': decorator
+      }
+    },
+    'component-style-group': {
+      type: 'void',
+      'x-component': 'CollapseItem',
+      'x-component-props': { defaultExpand: false },
+      'x-reactions': {
+        fulfill: {
+          state: {
+            visible: '{{!!$form.values["x-component"]}}'
+          }
+        }
+      },
+      properties: {
+        'x-component-props.style': AllSchemas.CSSStyle
+      }
+    },
+    'decorator-style-group': {
+      type: 'void',
+      'x-component': 'CollapseItem',
+      'x-component-props': { defaultExpand: false },
+      'x-reactions': {
+        fulfill: {
+          state: {
+            visible: '{{!!$form.values["x-decorator"]}}'
+          }
+        }
+      },
+      properties: {
+        'x-decorator-props.style': AllSchemas.CSSStyle
+      }
+    }
+  }
+}
+
+export const createFieldSchema = (
+  component?: ISchema,
+  decorator: ISchema = AllSchemas.FormItem
+): ISchema => {
+  return {
+    type: 'object',
+    properties: {
+      'field-group': {
+        type: 'void',
+        'x-component': 'CollapseItem',
+        properties: {
+          name: {
+            type: 'string',
+            'x-decorator': 'FormItem',
+            'x-component': 'Input'
+          },
+          title: {
+            type: 'string',
+            'x-decorator': 'FormItem',
+            'x-component': 'Input'
+          },
+          description: {
+            type: 'string',
+            'x-decorator': 'FormItem',
+            'x-component': 'Input.TextArea'
+          },
+          'x-display': {
+            type: 'string',
+            enum: ['visible', 'hidden', 'none', ''],
+            'x-decorator': 'FormItem',
+            'x-component': 'Select',
+            'x-component-props': {
+              defaultValue: 'visible'
+            }
+          },
+          'x-pattern': {
+            type: 'string',
+            enum: ['editable', 'disabled', 'readOnly', 'readPretty', ''],
+            'x-decorator': 'FormItem',
+            'x-component': 'Select',
+            'x-component-props': {
+              defaultValue: 'editable'
+            }
+          },
+          default: {
+            'x-decorator': 'FormItem',
+            'x-component': 'ValueInput'
+          },
+          enum: {
+            'x-decorator': 'FormItem',
+            'x-component': DataSourceSetter
+          },
+          'x-reactions': {
+            'x-decorator': 'FormItem',
+            'x-component': ReactionsSetter
+          },
+          'x-validator': {
+            type: 'array',
+            'x-component': ValidatorSetter
+          },
+          required: {
+            type: 'boolean',
+            'x-decorator': 'FormItem',
+            'x-component': 'Switch'
+          }
+        }
+      },
+      ...createComponentSchema(component, decorator)
+    }
+  }
+}
+
+export const createVoidFieldSchema = (
+  component?: ISchema,
+  decorator: ISchema = AllSchemas.FormItem
+) => {
+  return {
+    type: 'object',
+    properties: {
+      'field-group': {
+        type: 'void',
+        'x-component': 'CollapseItem',
+        properties: {
+          name: {
+            type: 'string',
+            'x-decorator': 'FormItem',
+            'x-component': 'Input'
+          },
+          title: {
+            type: 'string',
+            'x-decorator': 'FormItem',
+            'x-component': 'Input',
+            'x-reactions': {
+              fulfill: {
+                state: {
+                  hidden: '{{$form.values["x-decorator"] !== "FormItem"}}'
+                }
+              }
+            }
+          },
+          description: {
+            type: 'string',
+            'x-decorator': 'FormItem',
+            'x-component': 'Input.TextArea',
+            'x-reactions': {
+              fulfill: {
+                state: {
+                  hidden: '{{$form.values["x-decorator"] !== "FormItem"}}'
+                }
+              }
+            }
+          },
+          'x-display': {
+            type: 'string',
+            enum: ['visible', 'hidden', 'none', ''],
+            'x-decorator': 'FormItem',
+            'x-component': 'Select',
+            'x-component-props': {
+              defaultValue: 'visible'
+            }
+          },
+          'x-pattern': {
+            type: 'string',
+            enum: ['editable', 'disabled', 'readOnly', 'readPretty', ''],
+            'x-decorator': 'FormItem',
+            'x-component': 'Select',
+            'x-component-props': {
+              defaultValue: 'editable'
+            }
+          },
+          'x-reactions': {
+            'x-decorator': 'FormItem',
+            'x-component': ReactionsSetter
+          },
+          'x-decorator': {
+            type: 'string',
+            'x-decorator': 'FormItem',
+            'x-component': FormItemSwitcher
+          }
+        }
+      },
+      ...createComponentSchema(component, decorator)
+    }
+  }
+}

+ 1 - 0
src/pages/Schema/Designable/antd/components/Form/index.tsx

@@ -0,0 +1 @@
+export * from './preview'

+ 64 - 0
src/pages/Schema/Designable/antd/components/Form/preview.tsx

@@ -0,0 +1,64 @@
+import React, { useMemo } from 'react'
+import { createBehavior, createResource } from '@designable/core'
+import { createForm } from '@formily/core'
+import { observer } from '@formily/react'
+import { Form as FormilyForm } from '@formily/antd'
+import { usePrefix, DnFC } from '@designable/react'
+import { AllSchemas } from '../../schemas'
+import { AllLocales } from '../../locales'
+import './styles.less'
+
+export const Form: DnFC<React.ComponentProps<typeof FormilyForm>> = observer(props => {
+  const prefix = usePrefix('designable-form')
+  const form = useMemo(
+    () =>
+      createForm({
+        designable: true
+      }),
+    []
+  )
+  return (
+    <FormilyForm {...props} style={{ ...props.style }} className={prefix} form={form}>
+      {props.children}
+    </FormilyForm>
+  )
+})
+
+Form.Behavior = createBehavior({
+  name: 'Form',
+  selector: node => node.componentName === 'Form',
+  designerProps(node) {
+    return {
+      draggable: !node.isRoot,
+      cloneable: !node.isRoot,
+      deletable: !node.isRoot,
+      droppable: true,
+      propsSchema: {
+        type: 'object',
+        properties: {
+          ...(AllSchemas.FormLayout.properties as any),
+          style: AllSchemas.CSSStyle
+        }
+      },
+      defaultProps: {
+        labelCol: 6,
+        wrapperCol: 12
+      }
+    }
+  },
+  designerLocales: AllLocales.Form
+})
+
+Form.Resource = createResource({
+  title: { 'zh-CN': '表单', 'en-US': 'Form' },
+  icon: 'FormLayoutSource',
+  elements: [
+    {
+      componentName: 'Field',
+      props: {
+        type: 'object',
+        'x-component': 'Form'
+      }
+    }
+  ]
+})

+ 34 - 0
src/pages/Schema/Designable/antd/components/Form/styles.less

@@ -0,0 +1,34 @@
+@import '~antd/lib/style/themes/default.less';
+
+.dn-designable-form {
+  .@{ant-prefix}-input,
+  .@{ant-prefix}-input-number,
+  .@{ant-prefix}-input-affix-wrapper,
+  .@{ant-prefix}-cascader-picker,
+  .@{ant-prefix}-picker-input,
+  .@{ant-prefix}-picker,
+  .@{ant-prefix}-cascader-picker-label,
+  .@{ant-prefix}-slider,
+  .@{ant-prefix}-checkbox,
+  .@{ant-prefix}-rate,
+  .@{ant-prefix}-switch,
+  .@{ant-prefix}-radio,
+  .@{ant-prefix}-radio-wrapper,
+  .@{ant-prefix}-checkbox-group,
+  .@{ant-prefix}-checkbox-wrapper,
+  .@{ant-prefix}-radio-group,
+  .@{ant-prefix}-upload,
+  .@{ant-prefix}-transfer,
+  .@{ant-prefix}-select,
+  .@{ant-prefix}-select-selector {
+    pointer-events: none !important;
+
+    input {
+      pointer-events: none !important;
+    }
+  }
+
+  .anticon svg {
+    pointer-events: none;
+  }
+}

+ 1 - 0
src/pages/Schema/Designable/antd/components/FormCollapse/index.ts

@@ -0,0 +1 @@
+export * from './preview'

+ 177 - 0
src/pages/Schema/Designable/antd/components/FormCollapse/preview.tsx

@@ -0,0 +1,177 @@
+import React, { Fragment, useState } from 'react'
+import { observer } from '@formily/react'
+import { Collapse } from 'antd'
+import { CollapseProps, CollapsePanelProps } from 'antd/lib/collapse'
+import { TreeNode, createBehavior, createResource } from '@designable/core'
+import {
+  useTreeNode,
+  useNodeIdProps,
+  DroppableWidget,
+  TreeNodeWidget,
+  DnFC
+} from '@designable/react'
+import { toArr } from '@formily/shared'
+import { LoadTemplate } from '../../common/LoadTemplate'
+import { useDropTemplate } from '../../hooks'
+import { createVoidFieldSchema } from '../Field'
+import { AllSchemas } from '../../schemas'
+import { AllLocales } from '../../locales'
+import { matchComponent } from '../../shared'
+
+const parseCollapse = (parent: TreeNode) => {
+  const tabs: TreeNode[] = []
+  parent.children.forEach(node => {
+    if (matchComponent(node, 'FormCollapse.CollapsePanel')) {
+      tabs.push(node)
+    }
+  })
+  return tabs
+}
+
+export const FormCollapse: DnFC<CollapseProps> & {
+  CollapsePanel?: React.FC<CollapsePanelProps>
+} = observer(props => {
+  const [activeKey, setActiveKey] = useState<string | string[]>([])
+  const node = useTreeNode()
+  const nodeId = useNodeIdProps()
+  const designer = useDropTemplate('FormCollapse', source => {
+    const panelNode = new TreeNode({
+      componentName: 'Field',
+      props: {
+        type: 'void',
+        'x-component': 'FormCollapse.CollapsePanel',
+        'x-component-props': {
+          header: `Unnamed Title`
+        }
+      },
+      children: source
+    })
+
+    setActiveKey(toArr(activeKey).concat(panelNode.id))
+    return [panelNode]
+  })
+  const getCorrectActiveKey = (activeKey: string[] | string, tabs: TreeNode[]) => {
+    if (!tabs.length || !activeKey?.length) {
+      if (props.accordion) {
+        return tabs[0]?.id
+      }
+      return tabs.map(item => item.id)
+    }
+    if (
+      tabs.some(node =>
+        Array.isArray(activeKey) ? activeKey.includes(node.id) : node.id === activeKey
+      )
+    )
+      return activeKey
+    return tabs[tabs.length - 1].id
+  }
+  const panels = parseCollapse(node)
+  const renderCollapse = () => {
+    if (!node.children?.length) return <DroppableWidget />
+    return (
+      <Collapse {...props} activeKey={getCorrectActiveKey(activeKey, panels)}>
+        {panels.map(panel => {
+          const props = panel.props['x-component-props'] || {}
+          return (
+            <Collapse.Panel
+              {...props}
+              style={{ ...props.style }}
+              header={
+                <span
+                  data-content-editable="x-component-props.header"
+                  data-content-editable-node-id={panel.id}
+                >
+                  {props.header}
+                </span>
+              }
+              key={panel.id}
+            >
+              {React.createElement(
+                'div',
+                {
+                  [designer.props.nodeIdAttrName]: panel.id,
+                  style: {
+                    padding: '20px 0'
+                  }
+                },
+                panel.children.length ? <TreeNodeWidget node={panel} /> : <DroppableWidget />
+              )}
+            </Collapse.Panel>
+          )
+        })}
+      </Collapse>
+    )
+  }
+  return (
+    <div {...nodeId}>
+      {renderCollapse()}
+      <LoadTemplate
+        actions={[
+          {
+            title: node.getMessage('addCollapsePanel'),
+            icon: 'AddPanel',
+            onClick: () => {
+              const tabPane = new TreeNode({
+                componentName: 'Field',
+                props: {
+                  type: 'void',
+                  'x-component': 'FormCollapse.CollapsePanel',
+                  'x-component-props': {
+                    header: `Unnamed Title`
+                  }
+                }
+              })
+              node.append(tabPane)
+              const keys = toArr(activeKey)
+              setActiveKey(keys.concat(tabPane.id))
+            }
+          }
+        ]}
+      />
+    </div>
+  )
+})
+
+FormCollapse.CollapsePanel = props => {
+  return <Fragment>{props.children}</Fragment>
+}
+
+FormCollapse.Behavior = createBehavior(
+  {
+    name: 'FormCollapse',
+    extends: ['Field'],
+    selector: node => node.props['x-component'] === 'FormCollapse',
+    designerProps: {
+      droppable: true,
+      allowAppend: (target, source) =>
+        target.children.length === 0 ||
+        source.every(node => node.props['x-component'] === 'FormCollapse.CollapsePanel'),
+      propsSchema: createVoidFieldSchema(AllSchemas.FormCollapse)
+    },
+    designerLocales: AllLocales.FormCollapse
+  },
+  {
+    name: 'FormCollapse.CollapsePanel',
+    extends: ['Field'],
+    selector: node => node.props['x-component'] === 'FormCollapse.CollapsePanel',
+    designerProps: {
+      droppable: true,
+      allowDrop: node => node.props['x-component'] === 'FormCollapse',
+      propsSchema: createVoidFieldSchema(AllSchemas.FormCollapse.CollapsePanel)
+    },
+    designerLocales: AllLocales.FormCollapsePanel
+  }
+)
+
+FormCollapse.Resource = createResource({
+  icon: 'CollapseSource',
+  elements: [
+    {
+      componentName: 'Field',
+      props: {
+        type: 'void',
+        'x-component': 'FormCollapse'
+      }
+    }
+  ]
+})

+ 1 - 0
src/pages/Schema/Designable/antd/components/FormGrid/index.ts

@@ -0,0 +1 @@
+export * from './preview'

+ 146 - 0
src/pages/Schema/Designable/antd/components/FormGrid/preview.tsx

@@ -0,0 +1,146 @@
+import React from 'react'
+import { FormGrid as FormilyGird } from '@formily/antd'
+import { TreeNode, createBehavior, createResource } from '@designable/core'
+import { DnFC, useTreeNode, useNodeIdProps, DroppableWidget } from '@designable/react'
+import { observer } from '@formily/reactive-react'
+import { LoadTemplate } from '../../common/LoadTemplate'
+import { createFieldSchema } from '../Field'
+import { AllSchemas } from '../../schemas'
+import { AllLocales } from '../../locales'
+import './styles.less'
+
+type formilyGrid = typeof FormilyGird
+
+export const FormGrid: DnFC<React.ComponentProps<formilyGrid>> & {
+  GridColumn?: React.FC<React.ComponentProps<formilyGrid['GridColumn']>>
+} = observer(props => {
+  const node = useTreeNode()
+  const nodeId = useNodeIdProps()
+  if (node.children.length === 0) return <DroppableWidget {...props} />
+  const totalColumns = node.children.reduce(
+    (buf, child) => buf + (child.props?.['x-component-props']?.gridSpan ?? 1),
+    0
+  )
+  return (
+    <div {...nodeId} className="dn-grid">
+      <FormilyGird {...props} key={totalColumns}>
+        {props.children}
+      </FormilyGird>
+      <LoadTemplate
+        actions={[
+          {
+            title: node.getMessage('addGridColumn'),
+            icon: 'AddColumn',
+            onClick: () => {
+              const column = new TreeNode({
+                componentName: 'Field',
+                props: {
+                  type: 'void',
+                  'x-component': 'FormGrid.GridColumn'
+                }
+              })
+              node.append(column)
+            }
+          }
+        ]}
+      />
+    </div>
+  )
+})
+
+FormGrid.GridColumn = observer(props => {
+  return (
+    <DroppableWidget
+      {...props}
+      data-span={props.gridSpan}
+      style={{
+        ...props['style'],
+        gridColumnStart: `span ${props.gridSpan || 1}`
+      }}
+    >
+      {props.children}
+    </DroppableWidget>
+  )
+})
+
+FormGrid.Behavior = createBehavior(
+  {
+    name: 'FormGrid',
+    extends: ['Field'],
+    selector: node => node.props['x-component'] === 'FormGrid',
+    designerProps: {
+      droppable: true,
+      allowDrop: node => node.props['x-component'] !== 'FormGrid',
+      propsSchema: createFieldSchema(AllSchemas.FormGrid)
+    },
+    designerLocales: AllLocales.FormGrid
+  },
+  {
+    name: 'FormGrid.GridColumn',
+    extends: ['Field'],
+    selector: node => node.props['x-component'] === 'FormGrid.GridColumn',
+    designerProps: {
+      droppable: true,
+      resizable: {
+        width(node) {
+          const span = Number(node.props['x-component-props']?.gridSpan ?? 1)
+          return {
+            plus: () => {
+              if (span + 1 > 12) return
+              node.props['x-component-props'] = node.props['x-component-props'] || {}
+              node.props['x-component-props'].gridSpan = span + 1
+            },
+            minus: () => {
+              if (span - 1 < 1) return
+              node.props['x-component-props'] = node.props['x-component-props'] || {}
+              node.props['x-component-props'].gridSpan = span - 1
+            }
+          }
+        }
+      },
+      resizeXPath: 'x-component-props.gridSpan',
+      resizeStep: 1,
+      resizeMin: 1,
+      resizeMax: 12,
+      allowDrop: node => node.props['x-component'] === 'FormGrid',
+      propsSchema: createFieldSchema(AllSchemas.FormGrid.GridColumn)
+    },
+    designerLocales: AllLocales.FormGridColumn
+  }
+)
+
+FormGrid.Resource = createResource({
+  icon: 'GridSource',
+  elements: [
+    {
+      componentName: 'Field',
+      props: {
+        type: 'void',
+        'x-component': 'FormGrid'
+      },
+      children: [
+        {
+          componentName: 'Field',
+          props: {
+            type: 'void',
+            'x-component': 'FormGrid.GridColumn'
+          }
+        },
+        {
+          componentName: 'Field',
+          props: {
+            type: 'void',
+            'x-component': 'FormGrid.GridColumn'
+          }
+        },
+        {
+          componentName: 'Field',
+          props: {
+            type: 'void',
+            'x-component': 'FormGrid.GridColumn'
+          }
+        }
+      ]
+    }
+  ]
+})

+ 5 - 0
src/pages/Schema/Designable/antd/components/FormGrid/styles.less

@@ -0,0 +1,5 @@
+.dn-grid-column {
+  min-height: 60px;
+  margin: 4px;
+  border: 1px dashed #aaa;
+}

+ 1 - 0
src/pages/Schema/Designable/antd/components/FormLayout/index.ts

@@ -0,0 +1 @@
+export * from './preview'

+ 35 - 0
src/pages/Schema/Designable/antd/components/FormLayout/preview.ts

@@ -0,0 +1,35 @@
+import React from 'react'
+import { FormLayout as FormilyFormLayout } from '@formily/antd'
+import { createBehavior, createResource } from '@designable/core'
+import { DnFC } from '@designable/react'
+import { withContainer } from '../../common/Container'
+import { createVoidFieldSchema } from '../Field'
+import { AllSchemas } from '../../schemas'
+import { AllLocales } from '../../locales'
+
+export const FormLayout: DnFC<React.ComponentProps<typeof FormilyFormLayout>> =
+  withContainer(FormilyFormLayout)
+
+FormLayout.Behavior = createBehavior({
+  name: 'FormLayout',
+  extends: ['Field'],
+  selector: node => node.props['x-component'] === 'FormLayout',
+  designerProps: {
+    droppable: true,
+    propsSchema: createVoidFieldSchema(AllSchemas.FormLayout)
+  },
+  designerLocales: AllLocales.FormLayout
+})
+
+FormLayout.Resource = createResource({
+  icon: 'FormLayoutSource',
+  elements: [
+    {
+      componentName: 'Field',
+      props: {
+        type: 'void',
+        'x-component': 'FormLayout'
+      }
+    }
+  ]
+})

+ 1 - 0
src/pages/Schema/Designable/antd/components/FormTab/index.ts

@@ -0,0 +1 @@
+export * from './preview'

+ 171 - 0
src/pages/Schema/Designable/antd/components/FormTab/preview.tsx

@@ -0,0 +1,171 @@
+import React, { Fragment, useState } from 'react'
+import { observer } from '@formily/react'
+import { Tabs } from 'antd'
+import { TabsProps, TabPaneProps } from 'antd/lib/tabs'
+import { TreeNode, createBehavior, createResource } from '@designable/core'
+import {
+  useNodeIdProps,
+  useTreeNode,
+  TreeNodeWidget,
+  DroppableWidget,
+  DnFC
+} from '@designable/react'
+import { LoadTemplate } from '../../common/LoadTemplate'
+import { useDropTemplate } from '../../hooks'
+import { createVoidFieldSchema } from '../Field'
+import { AllSchemas } from '../../schemas'
+import { AllLocales } from '../../locales'
+import { matchComponent } from '../../shared'
+
+const parseTabs = (parent: TreeNode) => {
+  const tabs: TreeNode[] = []
+  parent.children.forEach(node => {
+    if (matchComponent(node, 'FormTab.TabPane')) {
+      tabs.push(node)
+    }
+  })
+  return tabs
+}
+
+const getCorrectActiveKey = (activeKey: string, tabs: TreeNode[]) => {
+  if (tabs.length === 0) return
+  if (tabs.some(node => node.id === activeKey)) return activeKey
+  return tabs[tabs.length - 1].id
+}
+
+export const FormTab: DnFC<TabsProps> & {
+  TabPane?: React.FC<TabPaneProps>
+} = observer(props => {
+  const [activeKey, setActiveKey] = useState<string>()
+  const nodeId = useNodeIdProps()
+  const node = useTreeNode()
+  const designer = useDropTemplate('FormTab', source => {
+    return [
+      new TreeNode({
+        componentName: 'Field',
+        props: {
+          type: 'void',
+          'x-component': 'FormTab.TabPane',
+          'x-component-props': {
+            tab: `Unnamed Title`
+          }
+        },
+        children: source
+      })
+    ]
+  })
+  const tabs = parseTabs(node)
+  const renderTabs = () => {
+    if (!node.children?.length) return <DroppableWidget />
+    return (
+      <Tabs
+        {...props}
+        activeKey={getCorrectActiveKey(activeKey, tabs)}
+        onChange={id => {
+          setActiveKey(id)
+        }}
+      >
+        {tabs.map(tab => {
+          const props = tab.props['x-component-props'] || {}
+          return (
+            <Tabs.TabPane
+              {...props}
+              style={{ ...props.style }}
+              tab={
+                <span
+                  data-content-editable="x-component-props.tab"
+                  data-content-editable-node-id={tab.id}
+                >
+                  {props.tab}
+                </span>
+              }
+              key={tab.id}
+            >
+              {React.createElement(
+                'div',
+                {
+                  [designer.props.nodeIdAttrName]: tab.id,
+                  style: {
+                    padding: '20px 0'
+                  }
+                },
+                tab.children.length ? <TreeNodeWidget node={tab} /> : <DroppableWidget node={tab} />
+              )}
+            </Tabs.TabPane>
+          )
+        })}
+      </Tabs>
+    )
+  }
+  return (
+    <div {...nodeId}>
+      {renderTabs()}
+      <LoadTemplate
+        actions={[
+          {
+            title: node.getMessage('addTabPane'),
+            icon: 'AddPanel',
+            onClick: () => {
+              const tabPane = new TreeNode({
+                componentName: 'Field',
+                props: {
+                  type: 'void',
+                  'x-component': 'FormTab.TabPane',
+                  'x-component-props': {
+                    tab: `Unnamed Title`
+                  }
+                }
+              })
+              node.append(tabPane)
+              setActiveKey(tabPane.id)
+            }
+          }
+        ]}
+      />
+    </div>
+  )
+})
+
+FormTab.TabPane = props => {
+  return <Fragment>{props.children}</Fragment>
+}
+
+FormTab.Behavior = createBehavior(
+  {
+    name: 'FormTab',
+    extends: ['Field'],
+    selector: node => node.props['x-component'] === 'FormTab',
+    designerProps: {
+      droppable: true,
+      allowAppend: (target, source) =>
+        target.children.length === 0 ||
+        source.every(node => node.props['x-component'] === 'FormTab.TabPane'),
+      propsSchema: createVoidFieldSchema(AllSchemas.FormTab)
+    },
+    designerLocales: AllLocales.FormTab
+  },
+  {
+    name: 'FormTab.TabPane',
+    extends: ['Field'],
+    selector: node => node.props['x-component'] === 'FormTab.TabPane',
+    designerProps: {
+      droppable: true,
+      allowDrop: node => node.props['x-component'] === 'FormTab',
+      propsSchema: createVoidFieldSchema(AllSchemas.FormTab.TabPane)
+    },
+    designerLocales: AllLocales.FormTabPane
+  }
+)
+
+FormTab.Resource = createResource({
+  icon: 'TabSource',
+  elements: [
+    {
+      componentName: 'Field',
+      props: {
+        type: 'void',
+        'x-component': 'FormTab'
+      }
+    }
+  ]
+})

+ 1 - 0
src/pages/Schema/Designable/antd/components/Input/index.ts

@@ -0,0 +1 @@
+export * from './preview'

+ 61 - 0
src/pages/Schema/Designable/antd/components/Input/preview.ts

@@ -0,0 +1,61 @@
+import React from 'react'
+import { Input as FormilyInput } from '@formily/antd'
+import { createBehavior, createResource } from '@designable/core'
+import { DnFC } from '@designable/react'
+import { createFieldSchema } from '../Field'
+import { AllSchemas } from '../../schemas'
+import { AllLocales } from '../../locales'
+
+export const Input: DnFC<React.ComponentProps<typeof FormilyInput>> = FormilyInput
+
+Input.Behavior = createBehavior(
+  {
+    name: 'Input',
+    extends: ['Field'],
+    selector: node => node.props['x-component'] === 'Input',
+    designerProps: {
+      propsSchema: createFieldSchema(AllSchemas.Input)
+    },
+    designerLocales: AllLocales.Input
+  },
+  {
+    name: 'Input.TextArea',
+    extends: ['Field'],
+    selector: node => node.props['x-component'] === 'Input.TextArea',
+    designerProps: {
+      propsSchema: createFieldSchema(AllSchemas.Input.TextArea)
+    },
+    designerLocales: AllLocales.TextArea
+  }
+)
+
+Input.Resource = createResource(
+  {
+    icon: 'InputSource',
+    elements: [
+      {
+        componentName: 'Field',
+        props: {
+          type: 'string',
+          title: 'Input',
+          'x-decorator': 'FormItem',
+          'x-component': 'Input'
+        }
+      }
+    ]
+  },
+  {
+    icon: 'TextAreaSource',
+    elements: [
+      {
+        componentName: 'Field',
+        props: {
+          type: 'string',
+          title: 'TextArea',
+          'x-decorator': 'FormItem',
+          'x-component': 'Input.TextArea'
+        }
+      }
+    ]
+  }
+)

+ 1 - 0
src/pages/Schema/Designable/antd/components/NumberPicker/index.ts

@@ -0,0 +1 @@
+export * from './preview'

+ 35 - 0
src/pages/Schema/Designable/antd/components/NumberPicker/preview.ts

@@ -0,0 +1,35 @@
+import React from 'react'
+import { NumberPicker as FormilyNumberPicker } from '@formily/antd'
+import { createBehavior, createResource } from '@designable/core'
+import { DnFC } from '@designable/react'
+import { createFieldSchema } from '../Field'
+import { AllSchemas } from '../../schemas'
+import { AllLocales } from '../../locales'
+
+export const NumberPicker: DnFC<React.ComponentProps<typeof FormilyNumberPicker>> =
+  FormilyNumberPicker
+
+NumberPicker.Behavior = createBehavior({
+  name: 'NumberPicker',
+  extends: ['Field'],
+  selector: node => node.props['x-component'] === 'NumberPicker',
+  designerProps: {
+    propsSchema: createFieldSchema(AllSchemas.NumberPicker)
+  },
+  designerLocales: AllLocales.NumberPicker
+})
+
+NumberPicker.Resource = createResource({
+  icon: 'NumberPickerSource',
+  elements: [
+    {
+      componentName: 'Field',
+      props: {
+        type: 'number',
+        title: 'NumberPicker',
+        'x-decorator': 'FormItem',
+        'x-component': 'NumberPicker'
+      }
+    }
+  ]
+})

+ 1 - 0
src/pages/Schema/Designable/antd/components/Object/index.ts

@@ -0,0 +1 @@
+export * from './preview'

+ 30 - 0
src/pages/Schema/Designable/antd/components/Object/preview.tsx

@@ -0,0 +1,30 @@
+import React from 'react'
+import { createBehavior, createResource } from '@designable/core'
+import { DnFC } from '@designable/react'
+import { createFieldSchema } from '../Field'
+import { Container } from '../../common/Container'
+import { AllLocales } from '../../locales'
+
+export const ObjectContainer: DnFC<React.ComponentProps<typeof Container>> = Container
+ObjectContainer.Behavior = createBehavior({
+  name: 'Object',
+  extends: ['Field'],
+  selector: node => node.props.type === 'object',
+  designerProps: {
+    droppable: true,
+    propsSchema: createFieldSchema()
+  },
+  designerLocales: AllLocales.ObjectLocale
+})
+
+ObjectContainer.Resource = createResource({
+  icon: 'ObjectSource',
+  elements: [
+    {
+      componentName: 'Field',
+      props: {
+        type: 'object'
+      }
+    }
+  ]
+})

+ 1 - 0
src/pages/Schema/Designable/antd/components/Password/index.ts

@@ -0,0 +1 @@
+export * from './preview'

+ 33 - 0
src/pages/Schema/Designable/antd/components/Password/preview.tsx

@@ -0,0 +1,33 @@
+import React from 'react'
+import { Password as FormilyPassword } from '@formily/antd'
+import { createBehavior, createResource } from '@designable/core'
+import { DnFC } from '@designable/react'
+import { createFieldSchema } from '../Field'
+import { AllSchemas } from '../../schemas'
+import { AllLocales } from '../../locales'
+
+export const Password: DnFC<React.ComponentProps<typeof FormilyPassword>> = FormilyPassword
+
+Password.Behavior = createBehavior({
+  name: 'Password',
+  extends: ['Field'],
+  selector: node => node.props['x-component'] === 'Password',
+  designerProps: {
+    propsSchema: createFieldSchema(AllSchemas.Password)
+  },
+  designerLocales: AllLocales.Password
+})
+
+Password.Resource = createResource({
+  icon: 'PasswordSource',
+  elements: [
+    {
+      componentName: 'Field',
+      props: {
+        title: 'Password',
+        'x-decorator': 'FormItem',
+        'x-component': 'Password'
+      }
+    }
+  ]
+})

+ 1 - 0
src/pages/Schema/Designable/antd/components/Radio/index.ts

@@ -0,0 +1 @@
+export * from './preview'

+ 38 - 0
src/pages/Schema/Designable/antd/components/Radio/preview.tsx

@@ -0,0 +1,38 @@
+import React from 'react'
+import { Radio as FormilyRadio } from '@formily/antd'
+import { createBehavior, createResource } from '@designable/core'
+import { DnFC } from '@designable/react'
+import { createFieldSchema } from '../Field'
+import { AllSchemas } from '../../schemas'
+import { AllLocales } from '../../locales'
+
+export const Radio: DnFC<React.ComponentProps<typeof FormilyRadio>> = FormilyRadio
+
+Radio.Behavior = createBehavior({
+  name: 'Radio.Group',
+  extends: ['Field'],
+  selector: node => node.props['x-component'] === 'Radio.Group',
+  designerProps: {
+    propsSchema: createFieldSchema(AllSchemas.Radio.Group)
+  },
+  designerLocales: AllLocales.RadioGroup
+})
+
+Radio.Resource = createResource({
+  icon: 'RadioGroupSource',
+  elements: [
+    {
+      componentName: 'Field',
+      props: {
+        type: 'string | number',
+        title: 'Radio Group',
+        'x-decorator': 'FormItem',
+        'x-component': 'Radio.Group',
+        enum: [
+          { label: '选项1', value: 1 },
+          { label: '选项2', value: 2 }
+        ]
+      }
+    }
+  ]
+})

+ 1 - 0
src/pages/Schema/Designable/antd/components/Rate/index.ts

@@ -0,0 +1 @@
+export * from './preview'

+ 34 - 0
src/pages/Schema/Designable/antd/components/Rate/preview.tsx

@@ -0,0 +1,34 @@
+import React from 'react'
+import { Rate as AntdRate } from 'antd'
+import { createBehavior, createResource } from '@designable/core'
+import { DnFC } from '@designable/react'
+import { createFieldSchema } from '../Field'
+import { AllSchemas } from '../../schemas'
+import { AllLocales } from '../../locales'
+
+export const Rate: DnFC<React.ComponentProps<typeof AntdRate>> = AntdRate
+
+Rate.Behavior = createBehavior({
+  name: 'Rate',
+  extends: ['Field'],
+  selector: node => node.props['x-component'] === 'Rate',
+  designerProps: {
+    propsSchema: createFieldSchema(AllSchemas.Rate)
+  },
+  designerLocales: AllLocales.Rate
+})
+
+Rate.Resource = createResource({
+  icon: 'RateSource',
+  elements: [
+    {
+      componentName: 'Field',
+      props: {
+        type: 'number',
+        title: 'Rate',
+        'x-decorator': 'FormItem',
+        'x-component': 'Rate'
+      }
+    }
+  ]
+})

+ 1 - 0
src/pages/Schema/Designable/antd/components/Select/index.ts

@@ -0,0 +1 @@
+export * from './preview'

+ 33 - 0
src/pages/Schema/Designable/antd/components/Select/preview.tsx

@@ -0,0 +1,33 @@
+import React from 'react'
+import { Select as FormilySelect } from '@formily/antd'
+import { createBehavior, createResource } from '@designable/core'
+import { DnFC } from '@designable/react'
+import { createFieldSchema } from '../Field'
+import { AllSchemas } from '../../schemas'
+import { AllLocales } from '../../locales'
+
+export const Select: DnFC<React.ComponentProps<typeof FormilySelect>> = FormilySelect
+
+Select.Behavior = createBehavior({
+  name: 'Select',
+  extends: ['Field'],
+  selector: node => node.props['x-component'] === 'Select',
+  designerProps: {
+    propsSchema: createFieldSchema(AllSchemas.Select)
+  },
+  designerLocales: AllLocales.Select
+})
+
+Select.Resource = createResource({
+  icon: 'SelectSource',
+  elements: [
+    {
+      componentName: 'Field',
+      props: {
+        title: 'Select',
+        'x-decorator': 'FormItem',
+        'x-component': 'Select'
+      }
+    }
+  ]
+})

+ 1 - 0
src/pages/Schema/Designable/antd/components/Slider/index.ts

@@ -0,0 +1 @@
+export * from './preview'

+ 34 - 0
src/pages/Schema/Designable/antd/components/Slider/preview.tsx

@@ -0,0 +1,34 @@
+import React from 'react'
+import { Slider as AntdSlider } from 'antd'
+import { createBehavior, createResource } from '@designable/core'
+import { DnFC } from '@designable/react'
+import { createFieldSchema } from '../Field'
+import { AllSchemas } from '../../schemas'
+import { AllLocales } from '../../locales'
+
+export const Slider: DnFC<React.ComponentProps<typeof AntdSlider>> = AntdSlider
+
+Slider.Behavior = createBehavior({
+  name: 'Slider',
+  extends: ['Field'],
+  selector: node => node.props['x-component'] === 'Slider',
+  designerProps: {
+    propsSchema: createFieldSchema(AllSchemas.Slider)
+  },
+  designerLocales: AllLocales.Slider
+})
+
+Slider.Resource = createResource({
+  icon: 'SliderSource',
+  elements: [
+    {
+      componentName: 'Field',
+      props: {
+        type: 'number',
+        title: 'Slider',
+        'x-decorator': 'FormItem',
+        'x-component': 'Slider'
+      }
+    }
+  ]
+})

+ 1 - 0
src/pages/Schema/Designable/antd/components/Space/index.ts

@@ -0,0 +1 @@
+export * from './preview'

+ 35 - 0
src/pages/Schema/Designable/antd/components/Space/preview.tsx

@@ -0,0 +1,35 @@
+import React from 'react'
+import { Space as FormilySpace } from '@formily/antd'
+import { createBehavior, createResource } from '@designable/core'
+import { DnFC } from '@designable/react'
+import { createVoidFieldSchema } from '../Field'
+import { withContainer } from '../../common/Container'
+import { AllSchemas } from '../../schemas'
+import { AllLocales } from '../../locales'
+
+export const Space: DnFC<React.ComponentProps<typeof FormilySpace>> = withContainer(FormilySpace)
+
+Space.Behavior = createBehavior({
+  name: 'Space',
+  extends: ['Field'],
+  selector: node => node.props['x-component'] === 'Space',
+  designerProps: {
+    droppable: true,
+    inlineChildrenLayout: true,
+    propsSchema: createVoidFieldSchema(AllSchemas.Space)
+  },
+  designerLocales: AllLocales.Space
+})
+
+Space.Resource = createResource({
+  icon: 'SpaceSource',
+  elements: [
+    {
+      componentName: 'Field',
+      props: {
+        type: 'void',
+        'x-component': 'Space'
+      }
+    }
+  ]
+})

+ 1 - 0
src/pages/Schema/Designable/antd/components/Switch/index.ts

@@ -0,0 +1 @@
+export * from './preview'

+ 34 - 0
src/pages/Schema/Designable/antd/components/Switch/preview.tsx

@@ -0,0 +1,34 @@
+import React from 'react'
+import { Switch as AntdSwitch } from 'antd'
+import { createBehavior, createResource } from '@designable/core'
+import { DnFC } from '@designable/react'
+import { createFieldSchema } from '../Field'
+import { AllSchemas } from '../../schemas'
+import { AllLocales } from '../../locales'
+
+export const Switch: DnFC<React.ComponentProps<typeof AntdSwitch>> = AntdSwitch
+
+Switch.Behavior = createBehavior({
+  name: 'Switch',
+  extends: ['Field'],
+  selector: node => node.props['x-component'] === 'Switch',
+  designerProps: {
+    propsSchema: createFieldSchema(AllSchemas.Switch)
+  },
+  designerLocales: AllLocales.Switch
+})
+
+Switch.Resource = createResource({
+  icon: 'SwitchSource',
+  elements: [
+    {
+      componentName: 'Field',
+      props: {
+        type: 'boolean',
+        title: 'Switch',
+        'x-decorator': 'FormItem',
+        'x-component': 'Switch'
+      }
+    }
+  ]
+})

+ 1 - 0
src/pages/Schema/Designable/antd/components/Text/index.ts

@@ -0,0 +1 @@
+export * from './preview'

+ 52 - 0
src/pages/Schema/Designable/antd/components/Text/preview.tsx

@@ -0,0 +1,52 @@
+import React from 'react'
+import { createBehavior, createResource } from '@designable/core'
+import { DnFC } from '@designable/react'
+import { createVoidFieldSchema } from '../Field'
+import { AllSchemas } from '../../schemas'
+import { AllLocales } from '../../locales'
+import cls from 'classnames'
+import './styles.less'
+
+export interface IDesignableTextProps {
+  value?: string
+  content?: string
+  mode?: 'normal' | 'h1' | 'h2' | 'h3' | 'p'
+  style?: React.CSSProperties
+  className?: string
+}
+
+export const Text: DnFC<IDesignableTextProps> = props => {
+  const tagName = props.mode === 'normal' || !props.mode ? 'div' : props.mode
+  return React.createElement(
+    tagName,
+    {
+      ...props,
+      className: cls(props.className, 'dn-text'),
+      'data-content-editable': 'x-component-props.content'
+    },
+    props.content
+  )
+}
+
+Text.Behavior = createBehavior({
+  name: 'Text',
+  extends: ['Field'],
+  selector: node => node.props['x-component'] === 'Text',
+  designerProps: {
+    propsSchema: createVoidFieldSchema(AllSchemas.Text)
+  },
+  designerLocales: AllLocales.Text
+})
+
+Text.Resource = createResource({
+  icon: 'TextSource',
+  elements: [
+    {
+      componentName: 'Field',
+      props: {
+        type: 'string',
+        'x-component': 'Text'
+      }
+    }
+  ]
+})

+ 10 - 0
src/pages/Schema/Designable/antd/components/Text/styles.less

@@ -0,0 +1,10 @@
+.dn-text {
+  &:empty::before {
+    display: block;
+    opacity: 0.6;
+    content: 'Please Input';
+  }
+  &:focus {
+    padding: 4px;
+  }
+}

+ 1 - 0
src/pages/Schema/Designable/antd/components/TimePicker/index.ts

@@ -0,0 +1 @@
+export * from './preview'

+ 61 - 0
src/pages/Schema/Designable/antd/components/TimePicker/preview.tsx

@@ -0,0 +1,61 @@
+import React from 'react'
+import { TimePicker as FormilyTimePicker } from '@formily/antd'
+import { createBehavior, createResource } from '@designable/core'
+import { DnFC } from '@designable/react'
+import { createFieldSchema } from '../Field'
+import { AllSchemas } from '../../schemas'
+import { AllLocales } from '../../locales'
+
+export const TimePicker: DnFC<React.ComponentProps<typeof FormilyTimePicker>> = FormilyTimePicker
+
+TimePicker.Behavior = createBehavior(
+  {
+    name: 'TimePicker',
+    extends: ['Field'],
+    selector: node => node.props['x-component'] === 'TimePicker',
+    designerProps: {
+      propsSchema: createFieldSchema(AllSchemas.TimePicker)
+    },
+    designerLocales: AllLocales.TimePicker
+  },
+  {
+    name: 'TimePicker.RangePicker',
+    extends: ['Field'],
+    selector: node => node.props['x-component'] === 'TimePicker.RangePicker',
+    designerProps: {
+      propsSchema: createFieldSchema(AllSchemas.TimePicker.RangePicker)
+    },
+    designerLocales: AllLocales.TimeRangePicker
+  }
+)
+
+TimePicker.Resource = createResource(
+  {
+    icon: 'TimePickerSource',
+    elements: [
+      {
+        componentName: 'Field',
+        props: {
+          type: 'string',
+          title: 'TimePicker',
+          'x-decorator': 'FormItem',
+          'x-component': 'TimePicker'
+        }
+      }
+    ]
+  },
+  {
+    icon: 'TimeRangePickerSource',
+    elements: [
+      {
+        componentName: 'Field',
+        props: {
+          type: 'string[]',
+          title: 'TimeRangePicker',
+          'x-decorator': 'FormItem',
+          'x-component': 'TimePicker.RangePicker'
+        }
+      }
+    ]
+  }
+)

+ 1 - 0
src/pages/Schema/Designable/antd/components/Transfer/index.ts

@@ -0,0 +1 @@
+export * from './preview'

+ 33 - 0
src/pages/Schema/Designable/antd/components/Transfer/preview.tsx

@@ -0,0 +1,33 @@
+import React from 'react'
+import { Transfer as FormilyTransfer } from '@formily/antd'
+import { createBehavior, createResource } from '@designable/core'
+import { DnFC } from '@designable/react'
+import { createFieldSchema } from '../Field'
+import { AllSchemas } from '../../schemas'
+import { AllLocales } from '../../locales'
+
+export const Transfer: DnFC<React.ComponentProps<typeof FormilyTransfer>> = FormilyTransfer
+
+Transfer.Behavior = createBehavior({
+  name: 'Transfer',
+  extends: ['Field'],
+  selector: node => node.props['x-component'] === 'Transfer',
+  designerProps: {
+    propsSchema: createFieldSchema(AllSchemas.Transfer)
+  },
+  designerLocales: AllLocales.Transfer
+})
+
+Transfer.Resource = createResource({
+  icon: 'TransferSource',
+  elements: [
+    {
+      componentName: 'Field',
+      props: {
+        title: 'Transfer',
+        'x-decorator': 'FormItem',
+        'x-component': 'Transfer'
+      }
+    }
+  ]
+})

+ 1 - 0
src/pages/Schema/Designable/antd/components/TreeSelect/index.ts

@@ -0,0 +1 @@
+export * from './preview'

+ 33 - 0
src/pages/Schema/Designable/antd/components/TreeSelect/preview.tsx

@@ -0,0 +1,33 @@
+import React from 'react'
+import { TreeSelect as FormilyTreeSelect } from '@formily/antd'
+import { createBehavior, createResource } from '@designable/core'
+import { DnFC } from '@designable/react'
+import { createFieldSchema } from '../Field'
+import { AllSchemas } from '../../schemas'
+import { AllLocales } from '../../locales'
+
+export const TreeSelect: DnFC<React.ComponentProps<typeof FormilyTreeSelect>> = FormilyTreeSelect
+
+TreeSelect.Behavior = createBehavior({
+  name: 'TreeSelect',
+  extends: ['Field'],
+  selector: node => node.props['x-component'] === 'TreeSelect',
+  designerProps: {
+    propsSchema: createFieldSchema(AllSchemas.TreeSelect)
+  },
+  designerLocales: AllLocales.TreeSelect
+})
+
+TreeSelect.Resource = createResource({
+  icon: 'TreeSelectSource',
+  elements: [
+    {
+      componentName: 'Field',
+      props: {
+        title: 'TreeSelect',
+        'x-decorator': 'FormItem',
+        'x-component': 'TreeSelect'
+      }
+    }
+  ]
+})

+ 1 - 0
src/pages/Schema/Designable/antd/components/Upload/index.ts

@@ -0,0 +1 @@
+export * from './preview'

+ 67 - 0
src/pages/Schema/Designable/antd/components/Upload/preview.tsx

@@ -0,0 +1,67 @@
+import React from 'react'
+import { Upload as FormilyUpload } from '@formily/antd'
+import { createBehavior, createResource } from '@designable/core'
+import { DnFC } from '@designable/react'
+import { createFieldSchema } from '../Field'
+import { AllSchemas } from '../../schemas'
+import { AllLocales } from '../../locales'
+
+export const Upload: DnFC<React.ComponentProps<typeof FormilyUpload>> = FormilyUpload
+
+Upload.Behavior = createBehavior(
+  {
+    name: 'Upload',
+    extends: ['Field'],
+    selector: node => node.props['x-component'] === 'Upload',
+    designerProps: {
+      propsSchema: createFieldSchema(AllSchemas.Upload)
+    },
+    designerLocales: AllLocales.Upload
+  },
+  {
+    name: 'Upload.Dragger',
+    extends: ['Field'],
+    selector: node => node.props['x-component'] === 'Upload.Dragger',
+    designerProps: {
+      propsSchema: createFieldSchema(AllSchemas.Upload.Dragger)
+    },
+    designerLocales: AllLocales.UploadDragger
+  }
+)
+
+Upload.Resource = createResource(
+  {
+    icon: 'UploadSource',
+    elements: [
+      {
+        componentName: 'Field',
+        props: {
+          type: 'Array<object>',
+          title: 'Upload',
+          'x-decorator': 'FormItem',
+          'x-component': 'Upload',
+          'x-component-props': {
+            textContent: 'Upload'
+          }
+        }
+      }
+    ]
+  },
+  {
+    icon: 'UploadDraggerSource',
+    elements: [
+      {
+        componentName: 'Field',
+        props: {
+          type: 'Array<object>',
+          title: 'Drag Upload',
+          'x-decorator': 'FormItem',
+          'x-component': 'Upload.Dragger',
+          'x-component-props': {
+            textContent: 'Click or drag file to this area to upload'
+          }
+        }
+      }
+    ]
+  }
+)

+ 27 - 0
src/pages/Schema/Designable/antd/components/index.ts

@@ -0,0 +1,27 @@
+export * from './Field'
+export * from './Form'
+export * from './Input'
+export * from './Select'
+export * from './TreeSelect'
+export * from './Cascader'
+export * from './Radio'
+export * from './Checkbox'
+export * from './Slider'
+export * from './Rate'
+export * from './NumberPicker'
+export * from './Transfer'
+export * from './Password'
+export * from './DatePicker'
+export * from './TimePicker'
+export * from './Upload'
+export * from './Switch'
+export * from './Text'
+export * from './Card'
+export * from './Space'
+export * from './Object'
+export * from './ArrayCards'
+export * from './ArrayTable'
+export * from './FormTab'
+export * from './FormCollapse'
+export * from './FormGrid'
+export * from './FormLayout'

+ 1 - 0
src/pages/Schema/Designable/antd/hooks/index.ts

@@ -0,0 +1 @@
+export * from './useDropTemplate'

+ 23 - 0
src/pages/Schema/Designable/antd/hooks/useDropTemplate.ts

@@ -0,0 +1,23 @@
+import { AppendNodeEvent, TreeNode } from '@designable/core'
+import { useDesigner } from '@designable/react'
+import { matchComponent, matchChildComponent } from '../shared'
+
+export const useDropTemplate = (name: string, getChildren: (source: TreeNode[]) => TreeNode[]) => {
+  return useDesigner(designer => {
+    return designer.subscribeTo(AppendNodeEvent, event => {
+      const { source, target } = event.data
+      if (Array.isArray(target)) return
+      if (!Array.isArray(source)) return
+      if (
+        matchComponent(
+          target,
+          key => key === name && source.every(child => !matchChildComponent(child, name))
+        ) &&
+        target.children.length === 0
+      ) {
+        target.setChildren(...getChildren(source))
+        return false
+      }
+    })
+  })
+}

+ 3 - 0
src/pages/Schema/Designable/antd/index.ts

@@ -0,0 +1,3 @@
+export * from './components'
+export * from './schemas'
+export * from './locales'

+ 87 - 0
src/pages/Schema/Designable/antd/locales/ArrayBase.ts

@@ -0,0 +1,87 @@
+import { GlobalRegistry } from '@designable/core'
+
+GlobalRegistry.registerDesignerLocales({
+  'zh-CN': {
+    Previews: {
+      droppable: '可以拖入组件',
+      addTabPane: '添加选项卡',
+      addCollapsePanel: '添加手风琴卡片',
+      addTableColumn: '添加表格列',
+      addTableSortHandle: '添加排序',
+      addIndex: '添加索引',
+      addOperation: '添加操作'
+    }
+  }
+})
+
+export const ArrayAddition = {
+  'zh-CN': {
+    title: '添加按钮',
+    settings: {
+      'x-component-props': {
+        method: '方法',
+        defaultValue: '默认值'
+      }
+    }
+  }
+}
+
+export const ArrayRemove = {
+  'zh-CN': {
+    title: '删除按钮'
+  },
+  'en-US': {
+    title: 'Remove'
+  },
+  'ko-KR': {
+    title: '삭제'
+  }
+}
+
+export const ArrayMoveUp = {
+  'zh-CN': {
+    title: '上移按钮'
+  },
+  'en-US': {
+    title: 'Move Up'
+  },
+  'ko-KR': {
+    title: '위로 옮기기'
+  }
+}
+
+export const ArrayMoveDown = {
+  'zh-CN': {
+    title: '下移按钮'
+  },
+  'en-US': {
+    title: 'Move Down'
+  },
+  'ko-KR': {
+    title: '아래로 옮기기'
+  }
+}
+
+export const ArrayIndex = {
+  'zh-CN': {
+    title: '索引标识'
+  },
+  'en-US': {
+    title: 'Index'
+  },
+  'ko-KR': {
+    title: '색인'
+  }
+}
+
+export const ArraySortHandle = {
+  'zh-CN': {
+    title: '排序标识'
+  },
+  'en-US': {
+    title: 'Sort Handle'
+  },
+  'ko-KR': {
+    title: '정렬 핸들'
+  }
+}

+ 20 - 0
src/pages/Schema/Designable/antd/locales/ArrayCards.ts

@@ -0,0 +1,20 @@
+import { createLocales } from '@designable/core'
+import { Card } from './Card'
+
+export const ArrayCards = createLocales(Card, {
+  'zh-CN': {
+    title: '自增卡片',
+    addIndex: '添加索引',
+    addOperation: '添加操作'
+  },
+  'en-US': {
+    title: 'Array Cards',
+    addIndex: 'Add Index',
+    addOperation: 'Add Operations'
+  },
+  'ko-KR': {
+    title: '배열 카드',
+    addIndex: '색인 추가',
+    addOperation: '작업 추가'
+  }
+})

+ 122 - 0
src/pages/Schema/Designable/antd/locales/ArrayTable.ts

@@ -0,0 +1,122 @@
+export const ArrayTable = {
+  'zh-CN': {
+    title: '自增表格',
+    addSortHandle: '添加排序',
+    addColumn: '添加列',
+    addIndex: '添加索引',
+    addOperation: '添加操作',
+    settings: {
+      'x-component-props': {
+        showHeader: '显示头部',
+        sticky: '吸顶',
+        align: {
+          title: '对齐',
+          dataSource: ['左', '右', '居中']
+        },
+        colSpan: '跨列',
+        fixed: { title: '固定列', dataSource: ['左', '右', '无'] },
+        width: '宽度',
+        defaultValue: '默认值'
+      }
+    }
+  },
+  'en-US': {
+    title: 'Array Table',
+    addSortHandle: 'Add Sort Handle',
+    addColumn: 'Add Column',
+    addIndex: 'Add Index',
+    addOperation: 'Add Operations',
+    settings: {
+      'x-component-props': {
+        showHeader: 'Show Header',
+        sticky: 'Sticky',
+        align: {
+          title: 'Align',
+          dataSource: ['Left', 'Right', 'Center']
+        },
+        colSpan: 'Col Span',
+        fixed: { title: 'Fixed', dataSource: ['Left', 'Right', 'None'] },
+        width: 'Width',
+        defaultValue: 'Default Value'
+      }
+    }
+  },
+  'ko-KR': {
+    title: '배열 테이블',
+    addSortHandle: '정렬 핸들 추가',
+    addColumn: '열 추가',
+    addIndex: '색인 추가',
+    addOperation: '작업 추가',
+    settings: {
+      'x-component-props': {
+        showHeader: '헤더 보여주기',
+        sticky: '고정',
+        align: {
+          title: '정렬',
+          dataSource: ['왼쪽', '오른쪽', '가운데']
+        },
+        colSpan: 'colSpan',
+        fixed: { title: '고정', dataSource: ['왼쪽', '오른쪽', '없음'] },
+        width: '너비',
+        defaultValue: '기본 값'
+      }
+    }
+  }
+}
+
+export const ArrayTableColumn = {
+  'zh-CN': {
+    title: '表格列',
+    settings: {
+      'x-component-props': {
+        title: '标题',
+        align: {
+          title: '内容对齐',
+          dataSource: ['左', '右', '居中']
+        },
+        colSpan: '跨列',
+        width: '宽度',
+        fixed: {
+          title: '固定',
+          dataSource: ['左', '右', '无']
+        }
+      }
+    }
+  },
+  'en-US': {
+    title: 'Column',
+    settings: {
+      'x-component-props': {
+        title: 'Title',
+        align: {
+          title: 'Align',
+          dataSource: ['Left', 'Right', 'Center']
+        },
+        colSpan: 'Col Span',
+        width: 'Width',
+        fixed: {
+          title: 'Fixed',
+          dataSource: ['Left', 'Right', 'None']
+        }
+      }
+    }
+  },
+  'ko-KR': {
+    title: '열',
+    settings: {
+      'x-component-props': {
+        title: '제목',
+        align: {
+          title: '정렬',
+          dataSource: ['왼쪽', '오른쪽', '가운데']
+        },
+        colSpan: 'Col Span',
+        width: '너비',
+        fixed: {
+          title: '고정',
+          dataSource: ['왼쪽', '오른족', '없음']
+        }
+      }
+    }
+  }
+}

+ 44 - 0
src/pages/Schema/Designable/antd/locales/Card.ts

@@ -0,0 +1,44 @@
+export const Card = {
+  'zh-CN': {
+    title: '卡片',
+    settings: {
+      'x-component-props': {
+        type: '类型',
+        title: '标题',
+        extra: '右侧扩展',
+        cardTypes: [
+          { label: '内置', value: 'inner' },
+          { label: '默认', value: '' }
+        ]
+      }
+    }
+  },
+  'en-US': {
+    title: 'Card',
+    settings: {
+      'x-component-props': {
+        type: 'Type',
+        title: 'Title',
+        extra: 'Extra',
+        cardTypes: [
+          { label: 'Inner', value: 'inner' },
+          { label: 'Default', value: '' }
+        ]
+      }
+    }
+  },
+  'ko-KR': {
+    title: '카드',
+    settings: {
+      'x-component-props': {
+        type: '타입',
+        title: '제목',
+        extra: '추가 항목',
+        cardTypes: [
+          { label: '안쪽', value: 'inner' },
+          { label: '기본', value: '' }
+        ]
+      }
+    }
+  }
+}

+ 60 - 0
src/pages/Schema/Designable/antd/locales/Cascader.ts

@@ -0,0 +1,60 @@
+export const Cascader = {
+  'zh-CN': {
+    title: '联级选择',
+    settings: {
+      'x-component-props': {
+        changeOnSelect: {
+          title: '选择时触发',
+          tooltip: '点选每级菜单选项值都会发生变化'
+        },
+        displayRender: {
+          title: '渲染函数',
+          tooltip: '选择后展示的渲染函数,默认为label => label.join("/")	'
+        },
+        fieldNames: {
+          title: '自定义字段名',
+          tooltip: '默认值:{ label: "label", value: "value", children: "children" }'
+        }
+      }
+    }
+  },
+  'en-US': {
+    title: 'Cascader',
+    settings: {
+      'x-component-props': {
+        changeOnSelect: {
+          title: 'Change On Select',
+          tooltip: 'Click on each level of menu option value will change'
+        },
+        displayRender: {
+          title: 'Display Render',
+          tooltip:
+            'The rendering function displayed after selection, the default is label => label.join("/")	'
+        },
+        fieldNames: {
+          title: 'Field Names',
+          tooltip: 'Defaults:{ label: "label", value: "value", children: "children" }'
+        }
+      }
+    }
+  },
+  'ko-KR': {
+    title: 'Cascader',
+    settings: {
+      'x-component-props': {
+        changeOnSelect: {
+          title: '선택 시 변경',
+          tooltip: '메뉴 옵션 값의 레벨을 클릭하면 변경됩니다.'
+        },
+        displayRender: {
+          title: '디스플레이 렌더링',
+          tooltip: '선택 후 실행되는 렌더링 함수로 기본 값은 label => label.join("/")	'
+        },
+        fieldNames: {
+          title: '필드 이름',
+          tooltip: '기본 값:{ label: "label", value: "value", children: "children" }'
+        }
+      }
+    }
+  }
+}

+ 11 - 0
src/pages/Schema/Designable/antd/locales/Checkbox.ts

@@ -0,0 +1,11 @@
+export const CheckboxGroup = {
+  'zh-CN': {
+    title: '复选框组'
+  },
+  'en-US': {
+    title: 'Checkbox'
+  },
+  'ko-KR': {
+    title: '체크박스'
+  }
+}

+ 53 - 0
src/pages/Schema/Designable/antd/locales/Component.ts

@@ -0,0 +1,53 @@
+export const Component = {
+  'zh-CN': {
+    settings: {
+      style: {
+        width: '宽度',
+        height: '高度',
+        display: '展示',
+        background: '背景',
+        boxShadow: '阴影',
+        font: '字体',
+        margin: '外边距',
+        padding: '内边距',
+        borderRadius: '圆角',
+        border: '边框',
+        opacity: '透明度'
+      }
+    }
+  },
+  'en-US': {
+    settings: {
+      style: {
+        width: 'Width',
+        height: 'Height',
+        display: 'Display',
+        background: 'Background',
+        boxShadow: 'Box Shadow',
+        font: 'Font',
+        margin: 'Margin',
+        padding: 'Padding',
+        borderRadius: 'Radius',
+        border: 'Border',
+        opacity: 'Opacity'
+      }
+    }
+  },
+  'ko-KR': {
+    settings: {
+      style: {
+        width: '너비',
+        height: '높이',
+        display: '디스플레이',
+        background: '배경',
+        boxShadow: '쉐도우 박스',
+        font: '폰트',
+        margin: '마진',
+        padding: '패딩',
+        borderRadius: '테두리 굴곡',
+        border: '테두리',
+        opacity: '투명도'
+      }
+    }
+  }
+}

+ 88 - 0
src/pages/Schema/Designable/antd/locales/DatePicker.ts

@@ -0,0 +1,88 @@
+import { createLocales } from '@designable/core'
+
+export const DatePicker = {
+  'zh-CN': {
+    title: '日期选择',
+    settings: {
+      'x-component-props': {
+        disabledDate: {
+          title: '不可选日期',
+          tooltip: '格式 (currentDate: moment) => boolean'
+        },
+        disabledTime: {
+          title: '不可选时间',
+          tooltip: '格式 (currentDate: moment) => boolean'
+        },
+        inputReadOnly: '输入框只读',
+        format: '格式',
+        picker: {
+          title: '选择器类型',
+          dataSource: ['时间', '日期', '月份', '年', '季度', '财年']
+        },
+        showNow: '显示此刻',
+        showTime: '时间选择',
+        showToday: '显示今天'
+      }
+    }
+  },
+  'en-US': {
+    title: 'DatePicker',
+    settings: {
+      'x-component-props': {
+        disabledDate: {
+          title: 'Disabled Date',
+          tooltip: 'Format (currentDate: moment) => boolean'
+        },
+        disabledTime: {
+          title: 'Disabled Time',
+          tooltip: 'Format (currentDate: moment) => boolean'
+        },
+        inputReadOnly: 'Input ReadOnly',
+        format: 'Format',
+        picker: {
+          title: 'Picker Type',
+          dataSource: ['Time', 'Date', 'Month', 'Year', 'Quarter', 'Decade']
+        },
+        showNow: 'Show Now',
+        showTime: 'Show Time',
+        showToday: 'Show Today'
+      }
+    }
+  },
+  'ko-KR': {
+    title: '날짜 선택 상자',
+    settings: {
+      'x-component-props': {
+        disabledDate: {
+          title: '비활성화 된 날짜',
+          tooltip: '형식 (currentDate: moment) => boolean'
+        },
+        disabledTime: {
+          title: '비활성화 된 시간',
+          tooltip: '형식 (currentDate: moment) => boolean'
+        },
+        inputReadOnly: 'ReadOnly',
+        format: '포맷',
+        picker: {
+          title: '타입',
+          dataSource: ['시간', '날짜', '월', '년', '분기', '십년 단위']
+        },
+        showNow: '현재 시각 보기',
+        showTime: '시간 보기',
+        showToday: '오늘 보기'
+      }
+    }
+  }
+}
+
+export const DateRangePicker = createLocales(DatePicker, {
+  'zh-CN': {
+    title: '日期范围'
+  },
+  'en-US': {
+    title: 'DateRange'
+  },
+  'ko-KR': {
+    title: '날짜범위 선택 상자'
+  }
+})

+ 316 - 0
src/pages/Schema/Designable/antd/locales/Field.ts

@@ -0,0 +1,316 @@
+export const Field = {
+  'zh-CN': {
+    settings: {
+      name: '字段标识',
+      title: '标题',
+      required: '必填',
+      description: '描述',
+      default: '默认值',
+      enum: '可选项',
+      'x-display': {
+        title: '展示状态',
+        tooltip: '半隐藏只会隐藏UI,全隐藏会删除数据',
+        dataSource: ['显示', '半隐藏', '全隐藏', '继承']
+      },
+      'x-pattern': {
+        title: 'UI形态',
+        dataSource: ['可编辑', '禁用', '只读', '阅读', '继承']
+      },
+      'x-validator': '校验规则',
+      'x-decorator': '容器组件',
+      'x-reactions': '响应器规则',
+      'field-group': '字段属性',
+      'component-group': '组件属性',
+      'decorator-group': '容器属性',
+      'component-style-group': '组件样式',
+      'decorator-style-group': '容器样式',
+      'x-component-props': {
+        size: { title: '尺寸', dataSource: ['大', '小', '默认', '继承'] },
+        allowClear: '允许清除内容',
+        autoFocus: '自动获取焦点',
+        showSearch: '支持搜索',
+        notFoundContent: '空状态内容',
+        bordered: '是否有边框',
+        placeholder: '占位提示',
+        style: {
+          width: '宽度',
+          height: '高度',
+          display: '展示',
+          background: '背景',
+          boxShadow: '阴影',
+          font: '字体',
+          margin: '外边距',
+          padding: '内边距',
+          borderRadius: '圆角',
+          border: '边框',
+          opacity: '透明度'
+        }
+      },
+      'x-decorator-props': {
+        addonAfter: '后缀标签',
+        addonBefore: '前缀标签',
+        tooltip: '提示',
+        asterisk: '星号',
+        gridSpan: '网格跨列',
+        labelCol: '标签网格宽度',
+        wrapperCol: '组件网格宽度',
+        colon: '是否有冒号',
+        labelAlign: {
+          title: '标签对齐',
+          dataSource: ['左对齐', '右对齐', '继承']
+        },
+        wrapperAlign: {
+          title: '组件对齐',
+          dataSource: ['左对齐', '右对齐', '继承']
+        },
+        labelWrap: '标签换行',
+        wrapperWrap: '组件换行',
+        labelWidth: '标签宽度',
+        wrapperWidth: '组件宽度',
+        fullness: '组件占满',
+        inset: '内联布局',
+        shallow: '是否浅传递',
+        bordered: '是否有边框',
+        size: { title: '尺寸', dataSource: ['大', '小', '默认', '继承'] },
+        layout: { title: '布局', dataSource: ['垂直', '水平', '内联', '继承'] },
+        feedbackLayout: {
+          title: '反馈布局',
+          dataSource: ['宽松', '紧凑', '弹层', '无', '继承']
+        },
+        tooltipLayout: {
+          title: '提示布局',
+          dataSource: ['图标', '文本', '继承']
+        },
+        style: {
+          width: '宽度',
+          height: '高度',
+          display: '展示',
+          background: '背景',
+          boxShadow: '阴影',
+          font: '字体',
+          margin: '外边距',
+          padding: '内边距',
+          borderRadius: '圆角',
+          border: '边框',
+          opacity: '透明度'
+        }
+      }
+    }
+  },
+  'en-US': {
+    settings: {
+      name: 'Name',
+      title: 'Title',
+      required: 'Required',
+      description: 'Description',
+      default: 'Default',
+      enum: 'Options',
+      'x-display': {
+        title: 'Display State',
+        tooltip:
+          'When the display value is "None", the data will be "Hidden" and deleted. When the display value is hidden, only the UI will be hidden',
+        dataSource: ['Visible', 'Hidden', 'None', 'Inherit']
+      },
+      'x-pattern': {
+        title: 'UI Pattern',
+        dataSource: ['Editable', 'Disabled', 'ReadOnly', 'ReadPretty', 'Inherit']
+      },
+      'x-validator': 'Validator',
+      'x-decorator': 'Decorator',
+      'x-reactions': 'Reactions',
+      'field-group': 'Field Properties',
+      'component-group': 'Component Properties',
+      'decorator-group': 'Decorator Properties',
+      'component-style-group': 'Component Style',
+      'decorator-style-group': 'Decorator Style',
+      'x-component-props': {
+        size: {
+          title: 'Size',
+          dataSource: ['Large', 'Small', 'Default', 'Inherit']
+        },
+        allowClear: 'Allow Clear',
+        autoFocus: 'Auto Focus',
+        showSearch: 'Show Search',
+        notFoundContent: 'Not Found Content',
+        bordered: 'Bordered',
+        placeholder: 'Placeholder',
+        style: {
+          width: 'Width',
+          height: 'Height',
+          display: 'Display',
+          background: 'Background',
+          boxShadow: 'Box Shadow',
+          font: 'Font',
+          margin: 'Margin',
+          padding: 'Padding',
+          borderRadius: 'Radius',
+          border: 'Border',
+          opacity: 'Opacity'
+        }
+      },
+      'x-decorator-props': {
+        addonAfter: 'Addon After',
+        addonBefore: 'Addon Before',
+        tooltip: 'Tooltip',
+        asterisk: 'Asterisk',
+        gridSpan: 'Grid Span',
+        labelCol: 'Label Col',
+        wrapperCol: 'Wrapper Col',
+        colon: 'Colon',
+        labelAlign: {
+          title: 'Label Align',
+          dataSource: ['Left', 'Right', 'Inherit']
+        },
+        wrapperAlign: {
+          title: 'Wrapper Align',
+          dataSource: ['Left', 'Right', 'Inherit']
+        },
+        labelWrap: 'Label Wrap',
+        wrapperWrap: 'Wrapper Wrap',
+        labelWidth: 'Label Width',
+        wrapperWidth: 'Wrapper Width',
+        fullness: 'Fullness',
+        inset: 'Inset',
+        shallow: 'Shallow',
+        bordered: 'Bordered',
+        size: {
+          title: 'Size',
+          dataSource: ['Large', 'Small', 'Default', 'Inherit']
+        },
+        layout: {
+          title: 'Layout',
+          dataSource: ['Vertical', 'Horizontal', 'Inline', 'Inherit']
+        },
+        feedbackLayout: {
+          title: 'Feedback Layout',
+          dataSource: ['Loose', 'Terse', 'Popup', 'None', 'Inherit']
+        },
+        tooltipLayout: {
+          title: 'Tooltip Layout',
+          dataSource: ['Icon', 'Text', 'Inherit']
+        },
+        style: {
+          width: 'Width',
+          height: 'Height',
+          display: 'Display',
+          background: 'Background',
+          boxShadow: 'Box Shadow',
+          font: 'Font',
+          margin: 'Margin',
+          padding: 'Padding',
+          borderRadius: 'Radius',
+          border: 'Border',
+          opacity: 'Opacity'
+        }
+      }
+    }
+  },
+  'ko-KR': {
+    settings: {
+      name: '이름',
+      title: '제목',
+      required: '필수항목',
+      description: '설명',
+      default: '기본 값',
+      enum: 'Options',
+      'x-display': {
+        title: '디스플레이 상태',
+        tooltip:
+          '디스플레이 값이 "없음"이면 데이터가 "숨김"상태가 되고 삭제됩니다. 디스플레이 값이 숨김이면 UI만 숨겨집니다.',
+        dataSource: ['보임', '숨김', '없음', '상속']
+      },
+      'x-pattern': {
+        title: 'UI 패턴',
+        dataSource: ['수정 가능', '비활성화', 'ReadOnly', 'ReadPretty', '상속']
+      },
+      'x-validator': '유효성 검사 도구',
+      'x-decorator': '데코레이터',
+      'x-reactions': 'Reactions',
+      'field-group': '필드 속성',
+      'component-group': '컴포넌트 속성',
+      'decorator-group': '데코레이터 속성',
+      'component-style-group': '컴포넌트 스타일',
+      'decorator-style-group': '데코레이터 스타일',
+      'x-component-props': {
+        size: {
+          title: '크기',
+          dataSource: ['크게', '작게', '보통', '상속']
+        },
+        allowClear: '삭제 허용',
+        autoFocus: '오토 포커스',
+        showSearch: '검색 보기',
+        notFoundContent: '값을 찾을 수 없음',
+        bordered: 'Bordered',
+        placeholder: 'Placeholder',
+        style: {
+          width: '너비',
+          height: '높이',
+          display: '디스플레이',
+          background: '배경',
+          boxShadow: '그림자 박스',
+          font: '폰트',
+          margin: '마진',
+          padding: '패딩',
+          borderRadius: '테두리 굴곡',
+          border: '테두리',
+          opacity: '투명도'
+        }
+      },
+      'x-decorator-props': {
+        addonAfter: '에드온 뒤',
+        addonBefore: '에드온 전',
+        tooltip: '툴팁',
+        asterisk: '별표시',
+        gridSpan: 'Grid Span',
+        labelCol: 'Label Col',
+        wrapperCol: 'Wrapper Col',
+        colon: 'Colon',
+        labelAlign: {
+          title: 'Label 정렬',
+          dataSource: ['왼쪽', '오른쪽', '상속']
+        },
+        wrapperAlign: {
+          title: 'Wrapper 정렬',
+          dataSource: ['왼쪽', '오른쪽', '상속']
+        },
+        labelWrap: 'Label Wrap',
+        wrapperWrap: 'Wrapper Wrap',
+        labelWidth: 'Label Width',
+        wrapperWidth: 'Wrapper Width',
+        fullness: 'Fullness',
+        inset: 'Inset',
+        shallow: '얇게',
+        bordered: 'Bordered',
+        size: {
+          title: '크기',
+          dataSource: ['크게', '작게', '보통', '상속']
+        },
+        layout: {
+          title: '레이아웃',
+          dataSource: ['수직', '수평', '인라인', '상속']
+        },
+        feedbackLayout: {
+          title: '피드백 레이아웃',
+          dataSource: ['느슨하게', 'Terse', '팝업', '없음', '상속']
+        },
+        tooltipLayout: {
+          title: '툴팁 레이아웃',
+          dataSource: ['아이콘', '텍스트', '상속']
+        },
+        style: {
+          width: '너비',
+          height: '높이',
+          display: '디스플레이',
+          background: '배경',
+          boxShadow: '그림자 박수',
+          font: '폰트',
+          margin: '마진',
+          padding: '패딩',
+          borderRadius: '테두리 굴곡',
+          border: '테두리',
+          opacity: '투명도'
+        }
+      }
+    }
+  }
+}

+ 119 - 0
src/pages/Schema/Designable/antd/locales/Form.ts

@@ -0,0 +1,119 @@
+import { createLocales } from '@designable/core'
+import { Component } from './Component'
+
+export const Form = createLocales(Component, {
+  'zh-CN': {
+    title: '表单',
+    settings: {
+      labelCol: '标签网格宽度',
+      wrapperCol: '组件网格宽度',
+      colon: '是否有冒号',
+      labelAlign: {
+        title: '标签对齐',
+        dataSource: ['左对齐', '右对齐', '继承']
+      },
+      wrapperAlign: {
+        title: '组件对齐',
+        dataSource: ['左对齐', '右对齐', '继承']
+      },
+      labelWrap: '标签换行',
+      wrapperWrap: '组件换行',
+      labelWidth: '标签宽度',
+      wrapperWidth: '组件宽度',
+      fullness: '组件占满',
+      inset: '内联布局',
+      shallow: '是否浅传递',
+      bordered: '是否有边框',
+      size: { title: '尺寸', dataSource: ['大', '小', '默认', '继承'] },
+      layout: { title: '布局', dataSource: ['垂直', '水平', '内联', '继承'] },
+      feedbackLayout: {
+        title: '反馈布局',
+        dataSource: ['宽松', '紧凑', '弹层', '无', '继承']
+      },
+      tooltipLayout: {
+        title: '提示布局',
+        dataSource: ['图标', '文本', '继承']
+      }
+    }
+  },
+  'en-US': {
+    title: 'Form',
+    settings: {
+      labelCol: 'Label Col',
+      wrapperCol: 'Wrapper Col',
+      colon: 'Colon',
+      labelAlign: {
+        title: 'Label Align',
+        dataSource: ['Left', 'Right', 'Inherit']
+      },
+      wrapperAlign: {
+        title: 'Wrapper Align',
+        dataSource: ['Left', 'Right', 'Inherit']
+      },
+      labelWrap: 'Label Wrap',
+      wrapperWrap: 'Wrapper Wrap',
+      labelWidth: 'Label Width',
+      wrapperWidth: 'Wrapper Width',
+      fullness: 'Fullness',
+      inset: 'Inset',
+      shallow: 'Shallow',
+      bordered: 'Bordered',
+      size: {
+        title: 'Size',
+        dataSource: ['Large', 'Small', 'Default', 'Inherit']
+      },
+      layout: {
+        title: 'Layout',
+        dataSource: ['Vertical', 'Horizontal', 'Inline', 'Inherit']
+      },
+      feedbackLayout: {
+        title: 'Feedback Layout',
+        dataSource: ['Loose', 'Terse', 'Popup', 'None', 'Inherit']
+      },
+      tooltipLayout: {
+        title: 'Tooltip Layout',
+        dataSource: ['Icon', 'Text', 'Inherit']
+      }
+    }
+  },
+  'ko-KR': {
+    title: '폼',
+    settings: {
+      labelCol: 'Label Col',
+      wrapperCol: 'Wrapper Col',
+      colon: 'Colon',
+      labelAlign: {
+        title: 'Label 정렬',
+        dataSource: ['왼쪽', '오른쪽', '상속']
+      },
+      wrapperAlign: {
+        title: 'Wrapper 정렬',
+        dataSource: ['왼쪽', '오른쪽', '상속']
+      },
+      labelWrap: 'Label Wrap',
+      wrapperWrap: 'Wrapper Wrap',
+      labelWidth: 'Label Width',
+      wrapperWidth: 'Wrapper Width',
+      fullness: 'Fullness',
+      inset: 'Inset',
+      shallow: 'Shallow',
+      bordered: 'Bordered',
+      size: {
+        title: '크기',
+        dataSource: ['크게', '작게', '보통', '상속']
+      },
+      layout: {
+        title: '레이아웃',
+        dataSource: ['수직', '수평', '인라인', '상속']
+      },
+      feedbackLayout: {
+        title: '피드백 레이아웃',
+        dataSource: ['Loose', 'Terse', '팝업', '없음', '상속']
+      },
+      tooltipLayout: {
+        title: '툴팁 레이아웃',
+        dataSource: ['아이콘', '텍스트', '상속']
+      }
+    }
+  }
+})

+ 83 - 0
src/pages/Schema/Designable/antd/locales/FormCollapse.ts

@@ -0,0 +1,83 @@
+export const FormCollapse = {
+  'zh-CN': {
+    title: '折叠面板',
+    addCollapsePanel: '添加面板',
+    settings: {
+      'x-component-props': {
+        accordion: '手风琴模式',
+        collapsible: { title: '可折叠区域', dataSource: ['头部', '禁用'] },
+        ghost: '幽灵模式',
+        bordered: '是否有边框'
+      }
+    }
+  },
+  'en-US': {
+    title: 'Collapse',
+    addCollapsePanel: 'Add Panel',
+    settings: {
+      'x-component-props': {
+        accordion: 'Accordion Mode',
+        collapsible: {
+          title: 'Collapsible',
+          dataSource: ['Header', 'Disable']
+        },
+        ghost: 'Ghost Mode',
+        bordered: 'Bordered'
+      }
+    }
+  },
+  'ko-KR': {
+    title: '드롭다운',
+    addCollapsePanel: '패널 추가',
+    settings: {
+      'x-component-props': {
+        accordion: 'Accordion 모드',
+        collapsible: {
+          title: '드롭 여부',
+          dataSource: ['헤더', '비활성화']
+        },
+        ghost: '고스트 모드',
+        bordered: 'Bordered'
+      }
+    }
+  }
+}
+
+export const FormCollapsePanel = {
+  'zh-CN': {
+    title: '面板',
+    settings: {
+      'x-component-props': {
+        collapsible: { title: '是否可折叠', dataSource: ['头部', '禁用'] },
+        header: '标题',
+        extra: '扩展内容'
+      }
+    }
+  },
+  'en-US': {
+    title: 'Panel',
+    settings: {
+      'x-component-props': {
+        collapsible: {
+          title: 'Collapsible',
+          dataSource: ['Header', 'Disable']
+        },
+        header: 'Header Title',
+        extra: 'Extra Content'
+      }
+    }
+  },
+  'ko-KR': {
+    title: '패널',
+    settings: {
+      'x-component-props': {
+        collapsible: {
+          title: '드롭 여부',
+          dataSource: ['해더', '비활성화']
+        },
+        header: '헤더 제목',
+        extra: '추가 내용'
+      }
+    }
+  }
+}

+ 77 - 0
src/pages/Schema/Designable/antd/locales/FormGrid.ts

@@ -0,0 +1,77 @@
+export const FormGrid = {
+  'zh-CN': {
+    title: '网格布局',
+    addGridColumn: '添加网格列',
+    settings: {
+      'x-component-props': {
+        minWidth: '最小宽度',
+        minColumns: '最小列数',
+        maxWidth: '最大宽度',
+        maxColumns: '最大列数',
+        breakpoints: '响应式断点',
+        columnGap: '列间距',
+        rowGap: '行间距',
+        colWrap: '自动换行'
+      }
+    }
+  },
+  'en-US': {
+    title: 'Grid',
+    addGridColumn: 'Add Grid Column',
+    settings: {
+      'x-component-props': {
+        minWidth: 'Min Width',
+        minColumns: 'Min Columns',
+        maxWidth: 'Max Width',
+        maxColumns: 'Max Columns',
+        breakpoints: 'Breakpoints',
+        columnGap: 'Column Gap',
+        rowGap: 'Row Gap',
+        colWrap: 'Col Wrap'
+      }
+    }
+  },
+  'ko-KR': {
+    title: '그리드 열',
+    addGridColumn: '그리드 열 추가',
+    settings: {
+      'x-component-props': {
+        minWidth: '최소 너비',
+        minColumns: '최소 열 개수',
+        maxWidth: '최대 너비',
+        maxColumns: '최대 열 개수',
+        breakpoints: '중단점',
+        columnGap: '열 간격',
+        rowGap: '행 간격',
+        colWrap: '자동 줄바꿈'
+      }
+    }
+  }
+}
+
+export const FormGridColumn = {
+  'zh-CN': {
+    title: '网格列',
+    settings: {
+      'x-component-props': {
+        gridSpan: '跨列栏数'
+      }
+    }
+  },
+  'en-US': {
+    title: 'Grid Column',
+    settings: {
+      'x-component-props': {
+        gridSpan: 'Grid Span'
+      }
+    }
+  },
+  'ko-KR': {
+    title: '그리드 열',
+    settings: {
+      'x-component-props': {
+        gridSpan: '그리드 스팬'
+      }
+    }
+  }
+}

+ 122 - 0
src/pages/Schema/Designable/antd/locales/FormLayout.ts

@@ -0,0 +1,122 @@
+export const FormLayout = {
+  'zh-CN': {
+    title: '表单布局',
+    settings: {
+      'x-component-props': {
+        labelCol: '标签网格宽度',
+        wrapperCol: '组件网格宽度',
+        colon: '是否有冒号',
+        labelAlign: {
+          title: '标签对齐',
+          dataSource: ['左对齐', '右对齐', '继承']
+        },
+        wrapperAlign: {
+          title: '组件对齐',
+          dataSource: ['左对齐', '右对齐', '继承']
+        },
+        labelWrap: '标签换行',
+        wrapperWrap: '组件换行',
+        labelWidth: '标签宽度',
+        wrapperWidth: '组件宽度',
+        fullness: '组件占满',
+        inset: '内联布局',
+        shallow: '是否浅传递',
+        bordered: '是否有边框',
+        size: { title: '尺寸', dataSource: ['大', '小', '默认', '继承'] },
+        layout: { title: '布局', dataSource: ['水平', '垂直', '内联', '继承'] },
+        feedbackLayout: {
+          title: '反馈布局',
+          dataSource: ['宽松', '紧凑', '弹层', '无', '继承']
+        },
+        tooltipLayout: {
+          title: '提示布局',
+          dataSource: ['图标', '文本', '继承']
+        }
+      }
+    }
+  },
+  'en-US': {
+    title: 'Form Layout',
+    settings: {
+      'x-component-props': {
+        labelCol: 'Label Col',
+        wrapperCol: 'Wrapper Col',
+        colon: 'Colon',
+        labelAlign: {
+          title: 'Label Align',
+          dataSource: ['Left', 'Right', 'Inherit']
+        },
+        wrapperAlign: {
+          title: 'Wrapper Align',
+          dataSource: ['Left', 'Right', 'Inherit']
+        },
+        labelWrap: 'Label Wrap',
+        wrapperWrap: 'Wrapper Wrap',
+        labelWidth: 'Label Width',
+        wrapperWidth: 'Wrapper Width',
+        fullness: 'Fullness',
+        inset: 'Inset',
+        shallow: 'Shallow',
+        bordered: 'Bordered',
+        size: {
+          title: 'Size',
+          dataSource: ['Large', 'Small', 'Default', 'Inherit']
+        },
+        layout: {
+          title: 'Layout',
+          dataSource: ['Horizontal', 'Vertical', 'Inline', 'Inherit']
+        },
+        feedbackLayout: {
+          title: 'Feedback Layout',
+          dataSource: ['Loose', 'Terse', 'Popup', 'None', 'Inherit']
+        },
+        tooltipLayout: {
+          title: 'Tooltip Layout',
+          dataSource: ['Icon', 'Text', 'Inherit']
+        }
+      }
+    }
+  },
+  'ko-KR': {
+    title: '양식 레이아웃',
+    settings: {
+      'x-component-props': {
+        labelCol: '레이블 열',
+        wrapperCol: '래퍼 열',
+        colon: '콜론',
+        labelAlign: {
+          title: '레이블 정렬',
+          dataSource: ['왼쪽', '오른쪽', '상속']
+        },
+        wrapperAlign: {
+          title: '래퍼 정렬',
+          dataSource: ['왼쪽', '오른쪽', '상속']
+        },
+        labelWrap: '레이블 랩',
+        wrapperWrap: '래퍼 랩',
+        labelWidth: '레이블 너비',
+        wrapperWidth: '래퍼 너비',
+        fullness: '충만',
+        inset: '삽입',
+        shallow: '얕다',
+        bordered: '경계',
+        size: {
+          title: '크기',
+          dataSource: ['큰', '작은', '기본', '상속']
+        },
+        layout: {
+          title: '레이아웃',
+          dataSource: ['가로', '세로', '인라인', '상속']
+        },
+        feedbackLayout: {
+          title: '피드백 레이아웃',
+          dataSource: ['느슨한', '간단한', '팝업', '없음', '상속']
+        },
+        tooltipLayout: {
+          title: '도구 설명 레이아웃',
+          dataSource: ['아이콘', '텍스트', '상속']
+        }
+      }
+    }
+  }
+}

+ 83 - 0
src/pages/Schema/Designable/antd/locales/FormTab.ts

@@ -0,0 +1,83 @@
+export const FormTab = {
+  'zh-CN': {
+    title: '选项卡',
+    addTabPane: '添加选项卡',
+    settings: {
+      'x-component-props': {
+        animated: '启用动画过渡',
+        centered: '标签居中',
+        tab: '选项名称',
+        type: {
+          title: '类型',
+          dataSource: [
+            { label: '线框', value: 'line' },
+            { label: '卡片', value: 'card' }
+          ]
+        }
+      }
+    }
+  },
+  'en-US': {
+    title: 'Tabs',
+    addTabPane: 'Add Panel',
+    settings: {
+      'x-component-props': {
+        animated: 'Enable Animated',
+        centered: 'Label Centered',
+        tab: 'Tab Title',
+        type: {
+          title: 'Type',
+          dataSource: [
+            { label: 'Line', value: 'line' },
+            { label: 'Card', value: 'card' }
+          ]
+        }
+      }
+    }
+  },
+  'ko-KR': {
+    title: '탭',
+    addTabPane: '패널 추가',
+    settings: {
+      'x-component-props': {
+        animated: '애니메이션 활성화',
+        centered: '레이블을 가운데로',
+        tab: '텝 제목',
+        type: {
+          title: '타입',
+          dataSource: [
+            { label: '라인', value: 'line' },
+            { label: '카드', value: 'card' }
+          ]
+        }
+      }
+    }
+  }
+}
+
+export const FormTabPane = {
+  'zh-CN': {
+    title: '选项卡面板',
+    settings: {
+      'x-component-props': {
+        tab: '面板标题'
+      }
+    }
+  },
+  'en-US': {
+    title: 'Tab Panel',
+    settings: {
+      'x-component-props': {
+        tab: 'Panel Title'
+      }
+    }
+  },
+  'ko-KR': {
+    title: '탭 패널',
+    settings: {
+      'x-component-props': {
+        tab: '패널 제목'
+      }
+    }
+  }
+}

+ 50 - 0
src/pages/Schema/Designable/antd/locales/Input.ts

@@ -0,0 +1,50 @@
+export const Input = {
+  'zh-CN': {
+    title: '输入框',
+    settings: {
+      'x-component-props': {
+        addonAfter: '后缀标签',
+        addonBefore: '前缀标签',
+        maxLength: '最大长度',
+        prefix: '前缀',
+        suffix: '后缀',
+        autoSize: {
+          title: '自适应高度',
+          tooltip: '可设置为 true | false 或对象:{ minRows: 2, maxRows: 6 }'
+        },
+        showCount: '是否展示字数',
+        checkStrength: '检测强度'
+      }
+    }
+  },
+  'en-US': {
+    title: 'Input',
+    settings: {
+      'x-component-props': {
+        addonAfter: 'Addon After',
+        addonBefore: 'Addon Before',
+        maxLength: 'Max Length',
+        prefix: 'Prefix',
+        suffix: 'Suffix',
+        autoSize: 'Auto Size',
+        showCount: 'Show Count',
+        checkStrength: 'Check Strength'
+      }
+    }
+  },
+  'ko-KR': {
+    title: '입력',
+    settings: {
+      'x-component-props': {
+        addonAfter: '애드온 후',
+        addonBefore: '애드온 전',
+        maxLength: '최대 길이',
+        prefix: '접두사',
+        suffix: '접미사',
+        autoSize: '자동 크기 맞춤',
+        showCount: '개수 보여주기',
+        checkStrength: '강도 체크'
+      }
+    }
+  }
+}

+ 81 - 0
src/pages/Schema/Designable/antd/locales/NumberPicker.ts

@@ -0,0 +1,81 @@
+export const NumberPicker = {
+  'zh-CN': {
+    title: '数字输入',
+    settings: {
+      'x-component-props': {
+        formatter: {
+          title: '格式转换器',
+          tooltip: '格式:function(value: number | string): string'
+        },
+        keyboard: '启用快捷键',
+        parser: {
+          title: '格式解析器',
+          tooltip:
+            '指定从 格式转换器 里转换回数字的方式,和 格式转换器 搭配使用,格式:function(string): number'
+        },
+        decimalSeparator: '小数点',
+        precision: '数字精度',
+        max: '最大值',
+        min: '最小值',
+        step: '步长',
+        stringMode: {
+          title: '字符串格式',
+          tooltip: '开启后支持高精度小数。同时 onChange 将返回 string 类型'
+        }
+      }
+    }
+  },
+  'en-US': {
+    title: 'NumberInput',
+    settings: {
+      'x-component-props': {
+        formatter: {
+          title: 'Format Converter',
+          tooltip: 'Format:function(value: number | string): string'
+        },
+        keyboard: 'Enable Shortcut Keys',
+        parser: {
+          title: 'Format Parser',
+          tooltip:
+            'Specify the method of converting back to numbers from the format converter, and use it with the format converter, the format:function(string): number'
+        },
+        decimalSeparator: 'Decimal Separator',
+        precision: 'Precision',
+        max: 'Max',
+        min: 'Min',
+        step: 'Step',
+        stringMode: {
+          title: 'String Format',
+          tooltip:
+            'Support high-precision decimals after opening. At the same time onChange will return string type'
+        }
+      }
+    }
+  },
+  'ko-KR': {
+    title: '숫자 입력',
+    settings: {
+      'x-component-props': {
+        formatter: {
+          title: '포맷 컨버터',
+          tooltip: '형식: function(value: number | string): string'
+        },
+        keyboard: '숏컷 키 활성화',
+        parser: {
+          title: '포멧 파서',
+          tooltip:
+            '문자열을 숫자로 변환하는 포맷 컨버터를 만들고 사용하세요, 형식 :function(string): number'
+        },
+        decimalSeparator: '소수 구분 기호',
+        precision: '정밀도',
+        max: '최대값',
+        min: '최소값',
+        step: '스탭',
+        stringMode: {
+          title: '문자열 형식',
+          tooltip: '높은 정밀도 소수를 지원합니다. onChange에서 문자열 타입으로 반환됩니다.'
+        }
+      }
+    }
+  }
+}

+ 11 - 0
src/pages/Schema/Designable/antd/locales/Object.ts

@@ -0,0 +1,11 @@
+export const ObjectLocale = {
+  'zh-CN': {
+    title: '对象容器'
+  },
+  'en-US': {
+    title: 'Object'
+  },
+  'ko-KR': {
+    title: '오브젝트'
+  }
+}

+ 14 - 0
src/pages/Schema/Designable/antd/locales/Password.ts

@@ -0,0 +1,14 @@
+import { createLocales } from '@designable/core'
+import { Input } from './Input'
+
+export const Password = createLocales(Input, {
+  'zh-CN': {
+    title: '密码输入'
+  },
+  'en-US': {
+    title: 'Password'
+  },
+  'ko-KR': {
+    title: '비밀번호'
+  }
+})

+ 29 - 0
src/pages/Schema/Designable/antd/locales/Radio.ts

@@ -0,0 +1,29 @@
+export const RadioGroup = {
+  'zh-CN': {
+    title: '单选框组',
+    settings: {
+      'x-component-props': {
+        buttonStyle: { title: '按钮风格', dataSource: ['空心', '实心'] },
+        optionType: { title: '选项类型', dataSource: ['默认', '按钮'] }
+      }
+    }
+  },
+  'en-US': {
+    title: 'Radio',
+    settings: {
+      'x-component-props': {
+        buttonStyle: { title: 'Button style', dataSource: ['Hollow', 'Solid'] },
+        optionType: { title: 'Option type', dataSource: ['Default', 'Button'] }
+      }
+    }
+  },
+  'ko-KR': {
+    title: '라디오',
+    settings: {
+      'x-component-props': {
+        buttonStyle: { title: '버튼 스타일', dataSource: ['Hollow', 'Solid'] },
+        optionType: { title: '옵션 타입', dataSource: ['기본', '버튼'] }
+      }
+    }
+  }
+}

+ 32 - 0
src/pages/Schema/Designable/antd/locales/Rate.ts

@@ -0,0 +1,32 @@
+export const Rate = {
+  'zh-CN': {
+    title: '评分器',
+    settings: {
+      'x-component-props': {
+        allowHalf: '允许半选',
+        tooltips: { title: '提示信息', tooltip: '格式:string[]' },
+        count: '总数'
+      }
+    }
+  },
+  'en-US': {
+    title: 'Rate',
+    settings: {
+      'x-component-props': {
+        allowHalf: 'Allow Half',
+        tooltips: { title: 'Tooltips', tooltip: 'Format:string[]' },
+        count: 'Count'
+      }
+    }
+  },
+  'ko-KR': {
+    title: '비율',
+    settings: {
+      'x-component-props': {
+        allowHalf: '절반 허용',
+        tooltips: { title: '툴팁', tooltip: '형식:string[]' },
+        count: '개수'
+      }
+    }
+  }
+}

+ 102 - 0
src/pages/Schema/Designable/antd/locales/Select.ts

@@ -0,0 +1,102 @@
+export const Select = {
+  'zh-CN': {
+    title: '选择框',
+    settings: {
+      'x-component-props': {
+        mode: {
+          title: '模式',
+          dataSource: ['多选', '标签', '单选']
+        },
+        autoClearSearchValue: {
+          title: '选中自动清除',
+          tooltip: '仅在多选或者标签模式下支持'
+        },
+        defaultActiveFirstOption: '默认高亮第一个选项',
+        dropdownMatchSelectWidth: {
+          title: '下拉菜单和选择器同宽',
+          tooltip: '默认将设置 min-width,当值小于选择框宽度时会被忽略。false 时会关闭虚拟滚动'
+        },
+        defaultOpen: '默认展开',
+        filterOption: '选项筛选器',
+        filterSort: '选项排序器',
+        labelInValue: {
+          title: '标签值',
+          tooltip:
+            '是否把每个选项的 label 包装到 value 中,会把 Select 的 value 类型从 string 变为 { value: string, label: ReactNode } 的格式'
+        },
+        listHeight: '弹窗滚动高度',
+        maxTagCount: {
+          title: '最多标签数量',
+          tooltip: '最多显示多少个 tag,响应式模式会对性能产生损耗'
+        },
+        maxTagPlaceholder: {
+          title: '最多标签占位',
+          tooltip: '隐藏 tag 时显示的内容'
+        },
+        maxTagTextLength: '最多标签文本长度',
+        showArrow: '显示箭头',
+        virtual: '开启虚拟滚动'
+      }
+    }
+  },
+  'en-US': {
+    title: 'Select',
+    settings: {
+      'x-component-props': {
+        mode: {
+          title: 'Mode',
+          dataSource: ['Multiple', 'Tags', 'Single']
+        },
+        autoClearSearchValue: {
+          title: 'Auto Clear Search Value',
+          tooltip: 'Only used to multiple and tags mode'
+        },
+        defaultActiveFirstOption: 'Default Active First Option',
+        dropdownMatchSelectWidth: 'Dropdown Match Select Width',
+        defaultOpen: 'Default Open',
+        filterOption: 'Filter Option',
+        filterSort: 'Filter Sort',
+        labelInValue: 'label InValue',
+        listHeight: 'List Height',
+        maxTagCount: 'Max Tag Count',
+        maxTagPlaceholder: {
+          title: 'Max Tag Placeholder',
+          tooltip: 'Content displayed when tag is hidden'
+        },
+        maxTagTextLength: 'Max Tag Text Length',
+        showArrow: 'Show Arrow',
+        virtual: 'Use Virtual Scroll'
+      }
+    }
+  },
+  'ko-KR': {
+    title: '선택',
+    settings: {
+      'x-component-props': {
+        mode: {
+          title: '모드',
+          dataSource: ['다중', '태그', '단일']
+        },
+        autoClearSearchValue: {
+          title: '자동 검색 값 삭제',
+          tooltip: '다중 모드와 태그 모드만 사용할 수 있습니다.'
+        },
+        defaultActiveFirstOption: '기본으로 첫번째 옵션을 선택함',
+        dropdownMatchSelectWidth: '드롭다운 너비와 일치시킴',
+        defaultOpen: '기본 오픈',
+        filterOption: '옵션 필터',
+        filterSort: '정렬 필터',
+        labelInValue: '레이블 InValue',
+        listHeight: '리스트 높이',
+        maxTagCount: '최대 태그 개수',
+        maxTagPlaceholder: {
+          title: '최대 태그 Placeholder',
+          tooltip: '태그가 숨겨질때 보입니다.'
+        },
+        maxTagTextLength: '최대 태그 텍스트 길이',
+        showArrow: '화살표 보기',
+        virtual: '수직 스크롤 사용'
+      }
+    }
+  }
+}

+ 73 - 0
src/pages/Schema/Designable/antd/locales/Slider.ts

@@ -0,0 +1,73 @@
+export const Slider = {
+  'zh-CN': {
+    title: '滑动条',
+    settings: {
+      'x-component-props': {
+        dots: '刻度固定',
+        range: '双滑块',
+        reverse: '反向坐标系',
+        vertical: '垂直布局',
+        tooltipPlacement: {
+          title: '提示位置',
+          tooltip: '设置 提示 展示位置。参考 Tooltip'
+        },
+        tooltipVisible: {
+          title: '提示显示',
+          tooltip: '开启时,提示 将会始终显示;否则始终不显示,哪怕在拖拽及移入时'
+        },
+        max: '最大值',
+        min: '最小值',
+        step: '步长',
+        marks: '刻度标签'
+      }
+    }
+  },
+  'en-US': {
+    title: 'Slider',
+    settings: {
+      'x-component-props': {
+        dots: 'Fixed Scale',
+        range: 'Double Slider',
+        reverse: 'Reverse Coordinate System',
+        vertical: 'Vertical',
+        tooltipPlacement: {
+          title: 'Tooltip Placement',
+          tooltip: 'Set up prompt placement. Reference Tooltip'
+        },
+        tooltipVisible: {
+          title: 'Tooltip Visible',
+          tooltip:
+            'When turned on, the prompt will always be displayed; otherwise, it will always not be displayed, even when dragging and moving in'
+        },
+        max: 'Max',
+        min: 'Min',
+        step: 'Step',
+        marks: 'Marks'
+      }
+    }
+  },
+  'ko-KR': {
+    title: '슬라이더',
+    settings: {
+      'x-component-props': {
+        dots: '고정된 크기',
+        range: '더블 슬라이더',
+        reverse: '뒤집어진 좌표 시스템',
+        vertical: '수직',
+        tooltipPlacement: {
+          title: '툴팁 배치',
+          tooltip: '툴팁이 나오는 위치를 설정'
+        },
+        tooltipVisible: {
+          title: '툴팁 보기',
+          tooltip:
+            '이 옵션을 켜면 툴팁이 항상 표시됩니다. 그렇지 않으면 끌어서 이동할 때도 툴팁이 항상 표시되지 않습니다'
+        },
+        max: '최댓값',
+        min: '최솟값',
+        step: '스탭',
+        marks: '마크'
+      }
+    }
+  }
+}

+ 50 - 0
src/pages/Schema/Designable/antd/locales/Space.ts

@@ -0,0 +1,50 @@
+export const Space = {
+  'zh-CN': {
+    title: '弹性间距',
+    settings: {
+      'x-component-props': {
+        direction: { title: '方向', dataSource: ['垂直', '水平'] },
+        split: '分割内容',
+        wrap: '自动换行',
+        align: {
+          title: '对齐',
+          dataSource: ['头部', '尾部', '居中', '基准线']
+        }
+      }
+    }
+  },
+  'en-US': {
+    title: 'Space',
+    settings: {
+      'x-component-props': {
+        direction: {
+          title: 'Direction',
+          dataSource: ['Vertical', 'Horizontal']
+        },
+        split: 'Split',
+        wrap: 'Word Wrap',
+        align: {
+          title: 'Align',
+          dataSource: ['Start', 'End', 'Center', 'Baseline']
+        }
+      }
+    }
+  },
+  'ko-KR': {
+    title: '간격',
+    settings: {
+      'x-component-props': {
+        direction: {
+          title: '방향',
+          dataSource: ['수직', '수평']
+        },
+        split: '분할',
+        wrap: '자동 줄 바꿈',
+        align: {
+          title: '정렬',
+          dataSource: ['시작', '끝', '가운데', '기준선']
+        }
+      }
+    }
+  }
+}

+ 11 - 0
src/pages/Schema/Designable/antd/locales/Switch.ts

@@ -0,0 +1,11 @@
+export const Switch = {
+  'zh-CN': {
+    title: '开关'
+  },
+  'en-US': {
+    title: 'Switch'
+  },
+  'ko-KR': {
+    title: '스위치'
+  }
+}

+ 38 - 0
src/pages/Schema/Designable/antd/locales/Text.ts

@@ -0,0 +1,38 @@
+export const Text = {
+  'zh-CN': {
+    title: '文本',
+    settings: {
+      'x-component-props': {
+        content: '文本内容',
+        mode: {
+          title: '文本类型',
+          dataSource: ['H1', 'H2', 'H3', 'Paragraph', 'Normal']
+        }
+      }
+    }
+  },
+  'en-US': {
+    title: 'Text',
+    settings: {
+      'x-component-props': {
+        content: 'Text Content',
+        mode: {
+          title: 'Text Mode',
+          dataSource: ['H1', 'H2', 'H3', 'Paragraph', 'Normal']
+        }
+      }
+    }
+  },
+  'ko-KR': {
+    title: '텍스트',
+    settings: {
+      'x-component-props': {
+        content: '텍스트 내용',
+        mode: {
+          title: '텍스트 모드',
+          dataSource: ['H1', 'H2', 'H3', 'Paragraph', 'Normal']
+        }
+      }
+    }
+  }
+}

+ 35 - 0
src/pages/Schema/Designable/antd/locales/TextArea.ts

@@ -0,0 +1,35 @@
+export const TextArea = {
+  'zh-CN': {
+    title: '多行输入',
+    settings: {
+      'x-component-props': {
+        maxLength: '最大长度',
+        autoSize: {
+          title: '自适应高度',
+          tooltip: '可设置为 true | false 或对象:{ minRows: 2, maxRows: 6 }'
+        },
+        showCount: '是否展示字数'
+      }
+    }
+  },
+  'en-US': {
+    title: 'TextArea',
+    settings: {
+      'x-component-props': {
+        maxLength: 'Max Length',
+        autoSize: 'Auto Size',
+        showCount: 'Show Count'
+      }
+    }
+  },
+  'ko-KR': {
+    title: '텍스트 상자',
+    settings: {
+      'x-component-props': {
+        maxLength: '최대 길이',
+        autoSize: '자동 길이 변환',
+        showCount: '개수 보기'
+      }
+    }
+  }
+}

+ 74 - 0
src/pages/Schema/Designable/antd/locales/TimePicker.ts

@@ -0,0 +1,74 @@
+import { createLocales } from '@designable/core'
+import { DatePicker } from './DatePicker'
+
+export const TimePicker = createLocales(DatePicker, {
+  'zh-CN': {
+    title: '时间选择',
+    settings: {
+      'x-component-props': {
+        clearText: '清除提示',
+        disabledHours: '禁止小时',
+        disabledMinutes: '禁止分钟',
+        disabledSeconds: '禁止秒',
+        hideDisabledOptions: '隐藏禁止选项',
+        hourStep: '小时间隔',
+        minuteStep: '分钟间隔',
+        secondStep: '秒间隔',
+        use12Hours: '12小时制',
+        inputReadOnly: '输入框只读',
+        showNow: '显示此刻',
+        format: '格式'
+      }
+    }
+  },
+  'en-US': {
+    title: 'Time Picker',
+    settings: {
+      'x-component-props': {
+        clearText: 'Clear Text',
+        disabledHours: 'Disbaled Hours',
+        disabledMinutes: 'Disabled Minutes',
+        disabledSeconds: 'Disabled Seconds',
+        hideDisabledOptions: 'Hide Disabled Options',
+        hourStep: 'Hour Step',
+        minuteStep: 'Minute Step',
+        secondStep: 'Second Step',
+        use12Hours: 'Use 12-hour',
+        inputReadOnly: 'Input ReadOnly',
+        showNow: 'Show Now',
+        format: 'Format'
+      }
+    }
+  },
+  'ko-KR': {
+    title: '시간 선택',
+    settings: {
+      'x-component-props': {
+        clearText: '텍스트 삭제',
+        disabledHours: '시 비활성화',
+        disabledMinutes: '분 비활성화',
+        disabledSeconds: '초 비활성화',
+        hideDisabledOptions: '비황성화 옵션 숨기기',
+        hourStep: '시 스탭',
+        minuteStep: '분 스탭',
+        secondStep: '초 스탭',
+        use12Hours: '12시간 단위 사용',
+        inputReadOnly: 'ReadOnly',
+        showNow: '현재 시각 보여주기',
+        format: '포맷'
+      }
+    }
+  }
+})
+
+export const TimeRangePicker = createLocales(TimePicker, {
+  'zh-CN': {
+    title: '时间范围'
+  },
+  'en-US': {
+    title: 'Time Range'
+  },
+  'ko-KR': {
+    title: '시간 범위'
+  }
+})

+ 38 - 0
src/pages/Schema/Designable/antd/locales/Transfer.ts

@@ -0,0 +1,38 @@
+export const Transfer = {
+  'zh-CN': {
+    title: '穿梭框',
+    settings: {
+      'x-component-props': {
+        oneWay: '单向展示',
+        operations: { title: '操作文案集合', tooltip: '格式:string[]' },
+        titles: { title: '标题集合', tooltip: '格式:string[]' },
+        showSearchAll: '支持全选',
+        filterOption: '选项筛选器'
+      }
+    }
+  },
+  'en-US': {
+    title: 'Transfer',
+    settings: {
+      'x-component-props': {
+        oneWay: 'One Way',
+        operations: { title: 'Operations', tooltip: 'Format:string[]' },
+        titles: { title: 'Titles', tooltip: 'Format:string[]' },
+        showSearchAll: 'Show Search All',
+        filterOption: 'Filter Option'
+      }
+    }
+  },
+  'ko-KR': {
+    title: '전송',
+    settings: {
+      'x-component-props': {
+        oneWay: '하나의 방법',
+        operations: { title: '작업', tooltip: '형식:string[]' },
+        titles: { title: '제목', tooltip: '형식:string[]' },
+        showSearchAll: '모든 검색 결과 보여주기',
+        filterOption: '필터 옵션'
+      }
+    }
+  }
+}

+ 0 - 0
src/pages/Schema/Designable/antd/locales/TreeSelect.ts


Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.