diff --git a/packages/amis-editor/src/index.tsx b/packages/amis-editor/src/index.tsx
index 2e59af6d8..8f3a1f02d 100644
--- a/packages/amis-editor/src/index.tsx
+++ b/packages/amis-editor/src/index.tsx
@@ -155,6 +155,7 @@ import './renderer/DataMappingControl';
import './renderer/DataPickerControl';
import './renderer/event-control/index';
import './renderer/TreeOptionControl';
+import './renderer/TransferTableControl';
export * from './component/BaseControl';
export * from './icons/index';
diff --git a/packages/amis-editor/src/plugin/AnchorNav.tsx b/packages/amis-editor/src/plugin/AnchorNav.tsx
index d6c1422ba..3ce94d665 100644
--- a/packages/amis-editor/src/plugin/AnchorNav.tsx
+++ b/packages/amis-editor/src/plugin/AnchorNav.tsx
@@ -84,6 +84,9 @@ export class AnchorNavPlugin extends BasePlugin {
draggable: true,
minLength: 1,
addButtonText: '添加锚点',
+ deleteBtn: {
+ icon: 'fa fa-trash'
+ },
items: [
{
type: 'input-text',
@@ -150,7 +153,8 @@ export class AnchorNavPlugin extends BasePlugin {
value: '1'
}
]
- }
+ },
+ getSchemaTpl('status')
])
},
{
diff --git a/packages/amis-editor/src/plugin/Dialog.tsx b/packages/amis-editor/src/plugin/Dialog.tsx
index 610904f56..6af6e616c 100644
--- a/packages/amis-editor/src/plugin/Dialog.tsx
+++ b/packages/amis-editor/src/plugin/Dialog.tsx
@@ -1,14 +1,16 @@
import React from 'react';
-import {registerEditorPlugin} from 'amis-editor-core';
import {
+ registerEditorPlugin,
BaseEventContext,
BasePlugin,
RegionConfig,
- RendererInfo
+ RendererInfo,
+ getSchemaTpl,
+ noop
} from 'amis-editor-core';
-import {defaultValue, getSchemaTpl} from 'amis-editor-core';
-import {noop} from 'amis-editor-core';
+import {cloneDeep, assign} from 'lodash';
import {getEventControlConfig} from '../renderer/event-control/helper';
+import {tipedLabel} from '../component/BaseControl';
export class DialogPlugin extends BasePlugin {
// 关联渲染器名字
@@ -83,108 +85,152 @@ export class DialogPlugin extends BasePlugin {
];
panelTitle = '弹框';
+ panelJustify = true;
panelBodyCreator = (context: BaseEventContext) => {
return getSchemaTpl('tabs', [
{
- title: '常规',
- body: [
+ title: '属性',
+ body: getSchemaTpl('collapseGroup', [
{
- label: '标题',
- type: 'input-text',
- name: 'title'
- },
-
- getSchemaTpl('switch', {
- label: '数据映射',
- name: 'data',
- className: 'block m-b-xs',
- pipeIn: (value: any) => !!value,
- pipeOut: (value: any) => (value ? {'&': '$$'} : null)
- }),
-
- {
- type: 'tpl',
- visibleOn: '!this.data',
- tpl:
- '
当没开启数据映射时,弹框中默认会拥有触发打开弹框按钮所在环境的所有数据。
'
- },
-
- {
- type: 'input-kv',
- syncDefaultValue: false,
- name: 'data',
- visibleOn: 'this.data',
- descriptionClassName: 'help-block text-xs m-b-none',
- description:
- '当开启数据映射时,弹框中的数据只会包含设置的部分,请绑定数据。如:{"a": "\\${a}", "b": 2}
如果希望在默认的基础上定制,请先添加一个 Key 为 `&` Value 为 `\\$$` 作为第一行。
当值为 __undefined
时,表示删除对应的字段,可以结合{"&": "\\$$"}
来达到黑名单效果。
',
- messages: {
- validateFailed: '数据映射中存在错误,请仔细检查'
- }
- },
-
- getSchemaTpl('switch', {
- label: '按 Esc 关闭弹框',
- name: 'closeOnEsc',
- value: false
- }),
-
- getSchemaTpl('switch', {
- label: '点击弹框外区域关闭弹框',
- name: 'closeOnOutside',
- value: false
- })
- ]
+ title: '基本',
+ body: [
+ {
+ label: '标题',
+ type: 'input-text',
+ name: 'title'
+ },
+ {
+ label: '尺寸',
+ type: 'button-group-select',
+ value: 'md',
+ name: 'size',
+ size: 'sm',
+ options: [
+ {
+ label: '小',
+ value: 'sm'
+ },
+ {
+ label: '中',
+ value: 'md'
+ },
+ {
+ label: '大',
+ value: 'lg'
+ },
+ {
+ label: '超大',
+ value: 'xl'
+ }
+ ]
+ },
+ getSchemaTpl('switch', {
+ label: '展示关闭按钮',
+ name: 'showCloseButton',
+ value: true
+ }),
+ getSchemaTpl('switch', {
+ label: '可按 Esc 关闭',
+ name: 'closeOnEsc',
+ value: false
+ }),
+ getSchemaTpl('switch', {
+ label: '左下角展示报错消息',
+ name: 'showErrorMsg',
+ value: true
+ }),
+ getSchemaTpl('switch', {
+ label: '左下角展示loading动画',
+ name: 'showLoading',
+ value: true
+ }),
+ getSchemaTpl('switch', {
+ label: tipedLabel(
+ '数据映射',
+ ' 当开启数据映射时,弹框中的数据只会包含设置的部分,请绑定数据。如:{"a": "${a}", "b": 2}。
'
+ + '当值为 __undefined时,表示删除对应的字段,可以结合{"&": "$$"}来达到黑名单效果。
'
+ ),
+ name: 'dataMapSwitch',
+ value: false,
+ className: 'm-b-xs',
+ onChange: (value: any, oldValue: any, model: any, form: any) => {
+ const newDataValue = value ? {} : null;
+ form.setValues({
+ __dataMap: newDataValue,
+ data: newDataValue
+ });
+ }
+ }),
+ {
+ type: 'alert',
+ level: 'info',
+ visibleOn: 'this.dataMapSwitch',
+ className: 'relative',
+ body: [
+ {
+ type: 'tpl',
+ tpl: '${data["&"] ? "已开启定制参数功能,可点击关闭该功能。" : "如果需要在默认数据的基础上定制参数,请配置开启参数定制再定义key和value。"}'
+ },
+ {
+ type: 'button',
+ label: '${data["&"] ? "立即关闭" : "立即开启"}',
+ level: 'link',
+ className: 'absolute bottom-3 right-10',
+ onClick: (e: any, props: any) => {
+ const newData = props.data.data?.['&'] === '$$' ? {} : {'&': '$$'};
+ // 用onBulkChange保证代码视图和编辑区域数据保持同步
+ props.onBulkChange({
+ data: newData,
+ __dataMap: {}
+ });
+ }
+ }
+ ],
+ showCloseButton: true
+ },
+ getSchemaTpl('combo-container', {
+ type: 'input-kv',
+ syncDefaultValue: false,
+ name: '__dataMap',
+ value: null,
+ visibleOn: 'this.dataMapSwitch',
+ className: 'block -mt-5',
+ deleteBtn: {
+ icon: 'fa fa-trash'
+ },
+ onChange: (value: any, oldValue: any, model: any, form: any) => {
+ // 用assign保证'&'第一个被遍历到
+ const newDataMap = form.data.data?.['&'] ?
+ assign({'&': '$$'}, value) : cloneDeep(value);
+ form.setValues({
+ data: newDataMap
+ });
+ form.setValues({
+ data: newDataMap
+ });
+ }
+ }),
+ ]
+ }
+ ])
},
{
title: '外观',
- body: [
+ body: getSchemaTpl('collapseGroup', [
{
- label: '尺寸',
- type: 'button-group-select',
- name: 'size',
- size: 'sm',
- className: 'block',
- pipeIn: defaultValue(''),
- options: [
- {
- label: '小',
- value: 'sm'
- },
- {
- label: '默认',
- value: ''
- },
- {
- label: '中',
- value: 'md'
- },
- {
- label: '大',
- value: 'lg'
- },
- {
- label: '超大',
- value: 'xl'
- }
+ title: 'CSS类名',
+ body: [
+ getSchemaTpl('className', {
+ name: 'className',
+ label: '外层'
+ }),
+ getSchemaTpl('className', {
+ name: 'bodyClassName',
+ label: '内容区域'
+ })
]
- },
-
- getSchemaTpl('switch', {
- label: '是否显示关闭按钮',
- name: 'showCloseButton',
- value: true
- }),
-
- getSchemaTpl('className', {
- name: 'headerClassName',
- label: '顶部 CSS 类名'
- }),
-
- getSchemaTpl('className', {
- name: 'bodyClassName',
- label: '内容 CSS 类名'
- })
- ]
+ }
+ ])
},
{
title: '事件',
diff --git a/packages/amis-editor/src/plugin/Drawer.tsx b/packages/amis-editor/src/plugin/Drawer.tsx
index 785a52165..342bd5872 100644
--- a/packages/amis-editor/src/plugin/Drawer.tsx
+++ b/packages/amis-editor/src/plugin/Drawer.tsx
@@ -1,14 +1,17 @@
-import {registerEditorPlugin} from 'amis-editor-core';
import {
+ registerEditorPlugin,
BaseEventContext,
BasePlugin,
RegionConfig,
- RendererInfo
+ RendererInfo,
+ defaultValue,
+ getSchemaTpl,
+ noop
} from 'amis-editor-core';
-import {defaultValue, getSchemaTpl} from 'amis-editor-core';
-import {noop} from 'amis-editor-core';
+import {assign, cloneDeep} from 'lodash';
import {getEventControlConfig} from '../renderer/event-control/helper';
import {InlineModal} from './Dialog';
+import {tipedLabel} from '../component/BaseControl';
export class DrawerPlugin extends BasePlugin {
// 关联渲染器名字
@@ -83,153 +86,213 @@ export class DrawerPlugin extends BasePlugin {
];
panelTitle = '弹框';
+ panelJustify = true;
panelBodyCreator = (context: BaseEventContext) => {
return getSchemaTpl('tabs', [
{
- title: '常规',
- body: [
+ title: '属性',
+ body: getSchemaTpl('collapseGroup', [
{
- label: '标题',
- type: 'input-text',
- name: 'title'
- },
-
- // {
- // children: (
- //
- // )
- // },
-
- {
- type: 'divider'
- },
-
- {
- label: '位置',
- type: 'button-group-select',
- name: 'position',
- value: 'right',
- size: 'sm',
- mode: 'inline',
- className: 'block',
- options: [
+ title: '基本',
+ body: [
{
- label: '左',
- value: 'left'
+ label: '标题',
+ type: 'input-text',
+ name: 'title'
},
{
- label: '上',
- value: 'top'
+ type: 'button-group-select',
+ name: 'position',
+ label: '位置',
+ value: 'right',
+ mode: 'horizontal',
+ options: [
+ {
+ label: '左',
+ value: 'left'
+ },
+ {
+ label: '上',
+ value: 'top'
+ },
+ {
+ label: '右',
+ value: 'right'
+ },
+ {
+ label: '下',
+ value: 'bottom'
+ }
+ ]
},
{
- label: '右',
- value: 'right'
+ type: 'button-group-select',
+ name: 'size',
+ label: '尺寸',
+ value: 'md',
+ size: 'sm',
+ mode: 'horizontal',
+ options: [
+ {
+ label: '超小',
+ value: 'xs'
+ },
+ {
+ label: '小',
+ value: 'sm'
+ },
+ {
+ label: '中',
+ value: 'md'
+ },
+ {
+ label: '大',
+ value: 'lg'
+ },
+ {
+ label: '超大',
+ value: 'xl'
+ }
+ ]
},
+ getSchemaTpl('switch', {
+ name: 'overlay',
+ label: '显示蒙层',
+ pipeIn: defaultValue(true)
+ }),
+ getSchemaTpl('switch', {
+ name: 'showCloseButton',
+ label: '展示关闭按钮',
+ pipeIn: defaultValue(true)
+ }),
+ getSchemaTpl('switch', {
+ name: 'closeOnOutside',
+ label: '点击外部关闭'
+ }),
+ getSchemaTpl('switch', {
+ label: '可按 Esc 关闭',
+ name: 'closeOnEsc'
+ }),
+ getSchemaTpl('switch', {
+ name: 'resizable',
+ label: '可拖拽抽屉大小',
+ value: false
+ }),
+ getSchemaTpl('switch', {
+ label: tipedLabel(
+ '数据映射',
+ ' 当开启数据映射时,弹框中的数据只会包含设置的部分,请绑定数据。如:{"a": "${a}", "b": 2}。
'
+ + '当值为 __undefined时,表示删除对应的字段,可以结合{"&": "$$"}来达到黑名单效果。
'
+ ),
+ name: 'dataMapSwitch',
+ value: false,
+ className: 'm-b-xs',
+ onChange: (value: any, oldValue: any, model: any, form: any) => {
+ const newDataValue = value ? {} : null;
+ form.setValues({
+ __dataMap: newDataValue,
+ data: newDataValue
+ });
+ }
+ }),
{
- label: '下',
- value: 'bottom'
- }
- ],
- description: '定义弹框从什么位置呼出'
- },
-
- getSchemaTpl('switch', {
- label: '数据映射',
- name: 'data',
- className: 'm-b-xs',
- pipeIn: (value: any) => !!value,
- pipeOut: (value: any) => (value ? {'&': '$$'} : null)
- }),
-
- {
- type: 'tpl',
- visibleOn: '!this.data',
- tpl:
- '当没开启数据映射时,弹框中默认会拥有触发打开弹框按钮所在环境的所有数据。
'
- },
-
- {
- type: 'input-kv',
- syncDefaultValue: false,
- name: 'data',
- visibleOn: 'this.data',
- descriptionClassName: 'help-block text-xs m-b-none',
- description:
- '当开启数据映射时,弹框中的数据只会包含设置的部分,请绑定数据。如:{"a": "\\${a}", "b": 2}
如果希望在默认的基础上定制,请先添加一个 Key 为 `&` Value 为 `\\$$` 作为第一行。
当值为 __undefined
时,表示删除对应的字段,可以结合{"&": "\\$$"}
来达到黑名单效果。
'
- },
-
- getSchemaTpl('switch', {
- name: 'closeOnOutside',
- label: '点击外部关闭弹框'
- }),
-
- getSchemaTpl('switch', {
- label: '按 Esc 可关闭',
- name: 'closeOnEsc'
- })
- ]
+ type: 'alert',
+ level: 'info',
+ visibleOn: 'this.dataMapSwitch',
+ className: 'relative',
+ body: [
+ {
+ type: 'tpl',
+ tpl: '${data["&"] ? "已开启定制参数功能,可点击关闭该功能。" : "如果需要在默认数据的基础上定制参数,请配置开启参数定制再定义key和value。"}'
+ },
+ {
+ type: 'button',
+ label: '${data["&"] ? "立即关闭" : "立即开启"}',
+ level: 'link',
+ className: 'absolute bottom-3 right-10',
+ onClick: (e: any, props: any) => {
+ const newData = props.data.data?.['&'] === '$$' ? {} : {'&': '$$'};
+ // 用onBulkChange保证代码视图和编辑区域数据保持同步
+ props.onBulkChange({
+ data: newData,
+ __dataMap: {}
+ });
+ }
+ }
+ ],
+ showCloseButton: true
+ },
+ getSchemaTpl('combo-container', {
+ type: 'input-kv',
+ syncDefaultValue: false,
+ name: '__dataMap',
+ value: null,
+ visibleOn: 'this.dataMapSwitch',
+ className: 'block -mt-5',
+ deleteBtn: {
+ icon: 'fa fa-trash'
+ },
+ onChange: (value: any, oldValue: any, model: any, form: any) => {
+ // 用assign保证'&'第一个被遍历到
+ const newDataMap = form.data.data?.['&'] ?
+ assign({'&': '$$'}, value) : cloneDeep(value);
+ form.setValues({
+ data: newDataMap
+ });
+ }
+ })
+ ]
+ }
+ ])
},
{
title: '外观',
- body: [
+ body: getSchemaTpl('collapseGroup', [
{
- label: '尺寸',
- type: 'button-group-select',
- name: 'size',
- size: 'sm',
- mode: 'inline',
- className: 'block',
- options: [
+ title: '基本',
+ body: [
{
- label: '超小',
- value: 'xs'
+ type: 'input-text',
+ name: 'width',
+ label: tipedLabel(
+ '宽度',
+ '位置为 "左" 或 "右" 时生效。 默认宽度为"尺寸"字段配置的宽度,值单位默认为 px,也支持百分比等单位 ,如:100%'
+ ),
+ disabledOn: 'this.position === "top" || this.position === "bottom"',
+ tooltip: '位置为 为 "左" 或 "右" 时生效'
},
{
- label: '小',
- value: 'sm'
- },
- {
- label: '中',
- value: 'md'
- },
- {
- label: '大',
- value: 'lg'
- },
- {
- label: '超大',
- value: 'xl'
+ type: 'input-text',
+ name: 'height',
+ label: tipedLabel(
+ '高度',
+ '位置为 "上" 或 "下" 时生效。 默认宽度为"尺寸"字段配置的高度,值单位默认为 px,也支持百分比等单位 ,如:100%'
+ ),
+ disabledOn: 'this.position === "left" || this.position === "right"'
}
]
},
-
- getSchemaTpl('switch', {
- name: 'overlay',
- label: '是否显示蒙层',
- pipeIn: defaultValue(true)
- }),
-
- getSchemaTpl('switch', {
- name: 'resizable',
- label: '可拉拽',
- description: '定义弹框是否可拉拽调整大小',
- pipeIn: defaultValue(false)
- }),
-
- getSchemaTpl('className'),
- getSchemaTpl('className', {
- label: 'bodyClassName 类名',
- name: 'bodyClassName'
- })
- ]
+ {
+ title: 'CSS类名',
+ body: [
+ getSchemaTpl('className', {
+ label: '外层'
+ }),
+ getSchemaTpl('className', {
+ label: '标题区域',
+ name: 'headClassName'
+ }),
+ getSchemaTpl('className', {
+ label: '内容区域',
+ name: 'bodyClassName'
+ }),
+ getSchemaTpl('className', {
+ label: '页脚区域',
+ name: 'footClassName'
+ })
+ ]
+ }
+ ])
},
{
title: '事件',
diff --git a/packages/amis-editor/src/plugin/Form/ButtonToolbar.tsx b/packages/amis-editor/src/plugin/Form/ButtonToolbar.tsx
index 03483b56c..5ccf27e06 100644
--- a/packages/amis-editor/src/plugin/Form/ButtonToolbar.tsx
+++ b/packages/amis-editor/src/plugin/Form/ButtonToolbar.tsx
@@ -59,58 +59,90 @@ export class ButtonToolbarControlPlugin extends BasePlugin {
panelTitle = '工具栏';
+ panelJustify = true;
+
panelBodyCreator = (context: BaseEventContext) => {
- return formItemControl(
+ return getSchemaTpl('tabs', [
{
- common: {
- replace: true,
- body: [
- getSchemaTpl('formItemName', {
- required: true
- }),
- getSchemaTpl('label'),
- getSchemaTpl('remark'),
- getSchemaTpl('labelRemark'),
- getSchemaTpl('description')
- ]
- },
- option: {
- title: '按钮管理',
- replace: true,
- body: [
+ title: '属性',
+ body: [
+ getSchemaTpl('collapseGroup', [
{
- name: 'buttons',
- type: 'combo',
- label: '',
- multiple: true,
- addable: true,
- minLength: 1,
- draggable: true,
- draggableTip: '',
- editable: false,
- visibleOn: 'this.buttons && this.buttons.length',
- items: [
- {
- type: 'tpl',
- inline: false,
- tpl:
- '<% if (data.type === "button-group") { %> 按钮组 <% } else { %><%= data.label %><% if (data.icon) { %><% }%><% } %>'
- }
- ],
- addButtonText: '新增按钮',
- scaffold: {
- type: 'button',
- label: '按钮'
- }
- }
- ]
- },
- event: {
- hidden: false
- }
+ title: '基本',
+ body: [
+ getSchemaTpl('formItemName', {
+ required: true
+ }),
+ getSchemaTpl('label'),
+ getSchemaTpl('valueFormula', {
+ rendererSchema: {
+ type: 'input-text'
+ }
+ }),
+ getSchemaTpl('labelRemark'),
+ getSchemaTpl('remark'),
+ getSchemaTpl('description'),
+ getSchemaTpl('combo-container', {
+ type: 'combo',
+ label: '按钮管理',
+ name: 'buttons',
+ mode: 'normal',
+ multiple: true,
+ addable: true,
+ minLength: 1,
+ draggable: true,
+ editable: false,
+ items: [
+ {
+ type: 'tpl',
+ inline: false,
+ className: 'p-t-xs',
+ tpl: '<% if (data.type === "button-group") { %> 按钮组 <% } else { %><%= data.label %><% if (data.icon) { %><% }%><% } %>'
+ }
+ ],
+ addButtonText: '新增按钮',
+ scaffold: {
+ type: 'button',
+ label: '按钮'
+ }
+ }),
+ ]
+ },
+ getSchemaTpl('status', {
+ isFormItem: true,
+ })
+ ]),
+ ]
},
- context
- );
+ {
+ title: '外观',
+ body: [
+ getSchemaTpl('collapseGroup', [
+ {
+ title: '基本',
+ body: [
+ getSchemaTpl('formItemMode'),
+ getSchemaTpl('horizontal', {
+ label: '',
+ visibleOn:
+ 'data.mode == "horizontal" && data.label !== false && data.horizontal'
+ }),
+ ]
+ },
+ getSchemaTpl('style:classNames', {
+ isFormItem: true,
+ schema: [
+ getSchemaTpl('className', {
+ label: '描述',
+ name: 'descriptionClassName',
+ visibleOn: "this.description"
+ })
+ ]
+ }),
+ ])
+ ]
+ }
+ ]);
};
}
diff --git a/packages/amis-editor/src/plugin/Form/TabsTransfer.tsx b/packages/amis-editor/src/plugin/Form/TabsTransfer.tsx
index 586e4fefd..39fccede9 100644
--- a/packages/amis-editor/src/plugin/Form/TabsTransfer.tsx
+++ b/packages/amis-editor/src/plugin/Form/TabsTransfer.tsx
@@ -218,6 +218,10 @@ export class TabsTransferPlugin extends BasePlugin {
}
];
+ notRenderFormZone = true;
+
+ panelJustify = true;
+
panelDefinitions = {
options: {
label: '选项 Options',
@@ -269,65 +273,64 @@ export class TabsTransferPlugin extends BasePlugin {
{
title: '属性',
body: getSchemaTpl('collapseGroup', [
- getSchemaTpl('switchDefaultValue'),
-
{
- type: 'select',
- name: 'value',
- label: '默认值',
- source: '${options}',
- multiple: true,
- visibleOn: 'typeof this.value !== "undefined"'
- },
+ title: '基本',
+ body: [
+ getSchemaTpl('formItemName', {
+ required: true
+ }),
+ getSchemaTpl('label'),
- getSchemaTpl('searchable'),
-
- getSchemaTpl('api', {
- label: '检索接口',
- name: 'searchApi'
- }),
-
- {
- label: '查询时勾选展示模式',
- name: 'searchResultMode',
- type: 'select',
- mode: 'inline',
- className: 'w-full',
- options: [
+ getSchemaTpl('searchable'),
+
+ getSchemaTpl('api', {
+ label: '检索接口',
+ name: 'searchApi'
+ }),
+
{
- label: '列表形式',
- value: 'list'
+ label: '查询时勾选展示模式',
+ name: 'searchResultMode',
+ type: 'select',
+ mode: 'normal',
+ options: [
+ {
+ label: '列表形式',
+ value: 'list'
+ },
+ {
+ label: '表格形式',
+ value: 'table'
+ },
+ {
+ label: '树形选择形式',
+ value: 'tree'
+ },
+ {
+ label: '级联选择形式',
+ value: 'chained'
+ }
+ ]
},
- {
- label: '表格形式',
- value: 'table'
- },
- {
- label: '树形选择形式',
- value: 'tree'
- },
- {
- label: '级联选择形式',
- value: 'chained'
- }
+
+ getSchemaTpl('sortable'),
+
+ getSchemaTpl('formulaControl', {
+ label: '左侧选项标题',
+ name: 'selectTitle',
+ type: 'input-text',
+ inputClassName: 'is-inline '
+ }),
+
+ getSchemaTpl('formulaControl', {
+ label: '右侧结果标题',
+ name: 'resultTitle',
+ type: 'input-text',
+ inputClassName: 'is-inline '
+ })
]
},
-
- getSchemaTpl('sortable'),
-
{
- label: '左侧的标题文字',
- name: 'selectTitle',
- type: 'input-text'
- },
-
- {
- label: '右侧结果的标题文字',
- name: 'resultTitle',
- type: 'input-text'
- },
-
- getSchemaTpl('fieldSet', {
title: '选项',
body: [
{
@@ -340,7 +343,8 @@ export class TabsTransferPlugin extends BasePlugin {
getSchemaTpl('extractValue'),
getSchemaTpl('autoFill')
]
- })
+ },
+ getSchemaTpl('status', {isFormItem: true})
])
},
{
diff --git a/packages/amis-editor/src/plugin/Form/Transfer.tsx b/packages/amis-editor/src/plugin/Form/Transfer.tsx
index 8190e1779..bdc2004ac 100644
--- a/packages/amis-editor/src/plugin/Form/Transfer.tsx
+++ b/packages/amis-editor/src/plugin/Form/Transfer.tsx
@@ -7,6 +7,9 @@ import {
RendererPluginEvent
} from 'amis-editor-core';
+import {ValidatorTag} from '../../validator';
+import {tipedLabel} from '../../component/BaseControl';
+
export class TransferPlugin extends BasePlugin {
// 关联渲染器名字
rendererName = 'transfer';
@@ -26,43 +29,28 @@ export class TransferPlugin extends BasePlugin {
name: 'transfer',
options: [
{
- label: '法师',
- children: [
- {
- label: '诸葛亮',
- value: 'zhugeliang'
- }
- ]
+ label: '诸葛亮',
+ value: 'zhugeliang'
},
{
- label: '战士',
- children: [
- {
- label: '曹操',
- value: 'caocao'
- },
- {
- label: '钟无艳',
- value: 'zhongwuyan'
- }
- ]
+ label: '曹操',
+ value: 'caocao'
},
{
- label: '打野',
- children: [
- {
- label: '李白',
- value: 'libai'
- },
- {
- label: '韩信',
- value: 'hanxin'
- },
- {
- label: '云中君',
- value: 'yunzhongjun'
- }
- ]
+ label: '钟无艳',
+ value: 'zhongwuyan'
+ },
+ {
+ label: '李白',
+ value: 'libai'
+ },
+ {
+ label: '韩信',
+ value: 'hanxin'
+ },
+ {
+ label: '云中君',
+ value: 'yunzhongjun'
}
]
};
@@ -181,7 +169,9 @@ export class TransferPlugin extends BasePlugin {
}
};
- // notRenderFormZone = true;
+ notRenderFormZone = true;
+
+ panelJustify = true;
panelBodyCreator = (context: BaseEventContext) => {
const renderer: any = context.info.renderer;
@@ -190,231 +180,150 @@ export class TransferPlugin extends BasePlugin {
{
title: '属性',
body: getSchemaTpl('collapseGroup', [
- getSchemaTpl('switchDefaultValue'),
-
{
- type: 'select',
- name: 'value',
- label: '默认值',
- source: '${options}',
- visibleOn: '!data.multiple && typeof this.value !== "undefined"'
- },
-
- {
- type: 'select',
- name: 'value',
- label: '默认值',
- source: '${options}',
- multiple: true,
- visibleOn: ' data.multiple && typeof this.value !== "undefined"'
- },
-
- {
- label: '勾选展示模式',
- name: 'selectMode',
- type: 'select',
- mode: 'inline',
- className: 'w-full',
- options: [
- {
- label: '列表形式',
- value: 'list'
- },
- {
- label: '表格形式',
- value: 'table'
- },
- {
- label: '树形选择形式',
- value: 'tree'
- },
- {
- label: '级联选择形式',
- value: 'chained'
- },
- {
- label: '关联选择形式',
- value: 'associated'
- }
+ title: '基本',
+ body: [
+ getSchemaTpl('formItemName', {
+ required: true
+ }),
+ getSchemaTpl('label'),
+ getSchemaTpl('labelRemark'),
+ getSchemaTpl('remark'),
+ getSchemaTpl('placeholder'),
+ getSchemaTpl('description'),
+ getSchemaTpl('switch', {
+ label: '统计数据',
+ name: 'statistics'
+ })
]
},
-
{
- name: 'columns',
- type: 'combo',
- multiple: true,
- label: false,
- strictMode: false,
- addButtonText: '新增一列',
- draggable: false,
- visibleOn: 'data.selectMode === "table"',
- items: [
- {
- type: 'input-text',
- name: 'label',
- placeholder: '标题'
- },
- {
- type: 'input-text',
- name: 'name',
- placeholder: '绑定字段名'
- },
+ title: '左侧选项面板',
+ body: [
+
{
+ label: '展示形式',
+ name: 'selectMode',
type: 'select',
- name: 'type',
- placeholder: '类型',
- value: 'input-text',
options: [
{
- value: 'text',
- label: '纯文本'
+ label: '列表形式',
+ value: 'list'
},
{
- value: 'tpl',
- label: '模板'
+ label: '表格形式',
+ value: 'table'
},
{
- value: 'image',
- label: '图片'
- },
- {
- value: 'date',
- label: '日期'
- },
- {
- value: 'progress',
- label: '进度'
- },
- {
- value: 'status',
- label: '状态'
- },
- {
- value: 'mapping',
- label: '映射'
- },
- {
- value: 'operation',
- label: '操作栏'
+ label: '树形形式',
+ value: 'tree'
}
- ]
- }
- ]
- },
-
- {
- $ref: 'options',
- label: '左边的选项集',
- name: 'leftOptions',
- visibleOn: 'data.selectMode === "associated"'
- },
-
- {
- label: '左侧选择形式',
- name: 'leftMode',
- type: 'select',
- mode: 'inline',
- className: 'w-full',
- visibleOn: 'data.selectMode === "associated"',
- options: [
- {
- label: '列表形式',
- value: 'list'
+ ],
+ onChange: (value: any, origin: any, item: any, form: any) => {
+ form.setValueByName('options', undefined);
+ }
},
- {
- label: '树形选择形式',
- value: 'tree'
- }
- ]
- },
- {
- label: '右侧选择形式',
- name: 'rightMode',
- type: 'select',
- mode: 'inline',
- className: 'w-full',
- visibleOn: 'data.selectMode === "associated"',
- options: [
+ getSchemaTpl('optionControl', {
+ visibleOn: 'data.selectMode === "list"',
+ multiple: true
+ }),
+
{
- label: '列表形式',
- value: 'list'
+ type: 'ae-transferTableControl',
+ name: 'options',
+ label: '数据',
+ visibleOn: 'data.selectMode === "table"',
+ mode: 'normal'
},
- {
- label: '树形选择形式',
- value: 'tree'
- }
- ]
+
+ getSchemaTpl('treeOptionControl', {
+ visibleOn: 'data.selectMode === "tree"',
+ }),
+
+ getSchemaTpl('switch', {
+ label: '可检索',
+ name: 'searchable'
+ }),
+
+ getSchemaTpl('menuTpl', {
+ label: tipedLabel('模板', '左侧选项渲染模板,支持JSX,变量使用\\${xx}')
+ }),
+
+ getSchemaTpl('formulaControl', {
+ label: '标题',
+ name: 'selectTitle',
+ type: 'input-text',
+ inputClassName: 'is-inline '
+ })
+ ],
},
-
- getSchemaTpl('searchable'),
-
- getSchemaTpl('api', {
- label: '检索接口',
- name: 'searchApi'
- }),
-
{
- label: '查询时勾选展示模式',
- name: 'searchResultMode',
- type: 'select',
- mode: 'inline',
- className: 'w-full',
- options: [
- {
- label: '列表形式',
- value: 'list'
- },
- {
- label: '表格形式',
- value: 'table'
- },
- {
- label: '树形选择形式',
- value: 'tree'
- },
- {
- label: '级联选择形式',
- value: 'chained'
- }
- ]
- },
-
- getSchemaTpl('sortable'),
-
- getSchemaTpl('selectFirst'),
-
- getSchemaTpl('switch', {
- label: '是否显示统计数据',
- name: 'statistics'
- }),
-
- {
- label: '左侧的标题文字',
- name: 'selectTitle',
- type: 'input-text'
- },
-
- {
- label: '右侧结果的标题文字',
- name: 'resultTitle',
- type: 'input-text'
- },
-
- getSchemaTpl('fieldSet', {
- title: '选项',
+ title: '右侧结果面板',
body: [
{
- $ref: 'options',
- name: 'options'
+ type: 'button-group-select',
+ label: '展示形式',
+ name: 'resultListModeFollowSelect',
+ inputClassName: 'items-center',
+ options: [
+ {label: '列表形式', value: false},
+ {label: '跟随左侧', value: true},
+ ],
},
- getSchemaTpl('source'),
- getSchemaTpl('joinValues'),
- getSchemaTpl('delimiter'),
- getSchemaTpl('extractValue'),
- getSchemaTpl('autoFill')
+
+ getSchemaTpl('switch', {
+ label: tipedLabel(
+ '可检索',
+ '查询功能目前只支持根据名称或值来模糊匹配查询'
+ ),
+ name: 'resultSearchable'
+ }),
+
+ getSchemaTpl('sortable', {
+ label: '支持排序',
+ mode: 'horizontal',
+ horizontal: {
+ justify: true,
+ left: 8
+ },
+ inputClassName: 'is-inline',
+ visibleOn: 'data.selectMode === "list" && !data.resultListModeFollowSelect',
+ }),
+
+ getSchemaTpl('menuTpl', {
+ name: 'valueTpl',
+ label: tipedLabel('模板', '结果选项渲染模板,支持JSX,变量使用\\${xx}')
+ }),
+
+ getSchemaTpl('formulaControl', {
+ label: '标题',
+ name: 'resultTitle',
+ type: 'input-text',
+ inputClassName: 'is-inline '
+ })
]
- })
+ },
+ getSchemaTpl('status', {isFormItem: true}),
+ getSchemaTpl('validation', {tag: ValidatorTag.MultiSelect})
+ ])
+ },
+ {
+ title: '外观',
+ body: getSchemaTpl('collapseGroup', [
+ getSchemaTpl('style:formItem', renderer),
+ getSchemaTpl('style:classNames', [
+ getSchemaTpl('className', {
+ label: '描述',
+ name: 'descriptionClassName',
+ visibleOn: 'this.description'
+ }),
+ getSchemaTpl('className', {
+ name: 'addOn.className',
+ label: 'AddOn',
+ visibleOn: 'this.addOn && this.addOn.type === "text"'
+ })
+ ])
])
},
{
diff --git a/packages/amis-editor/src/renderer/TransferTableControl.tsx b/packages/amis-editor/src/renderer/TransferTableControl.tsx
new file mode 100644
index 000000000..5eb7acba1
--- /dev/null
+++ b/packages/amis-editor/src/renderer/TransferTableControl.tsx
@@ -0,0 +1,459 @@
+/**
+ * @file Transfer的表格对应选项
+ */
+
+import React from 'react';
+import { render as amisRender, FormItem } from 'amis';
+import { omit } from 'lodash';
+import { SchemaApi } from 'amis/lib/Schema';
+import { autobind, getSchemaTpl } from 'amis-editor-core';
+import cx from 'classnames';
+import { tipedLabel } from '../component/BaseControl';
+
+import type { FormControlProps } from 'amis-core';
+import type { Option } from 'amis';
+
+interface OptionControlProps extends FormControlProps {
+ className?: string;
+}
+
+interface OptionControlState {
+ api: SchemaApi;
+ labelField: string;
+ valueField: string;
+ source: 'custom' | 'api' | 'form';
+};
+
+function BaseOptionControl(Cmpt: React.JSXElementConstructor) {
+ return class extends React.Component {
+
+ $comp: string; // 记录一下路径,不再从外部同步内部,只从内部同步外部
+
+ internalProps = ['checked', 'editing'];
+
+ constructor(props: OptionControlProps) {
+ super(props);
+
+ this.state = {
+ api: props.data.source,
+ labelField: props.data.labelField,
+ valueField: props.data.valueField,
+ source: props.data.source ? 'api' : 'custom'
+ };
+
+ this.handleSourceChange = this.handleSourceChange.bind(this);
+ this.handleAPIChange = this.handleAPIChange.bind(this);
+ this.handleLableFieldChange = this.handleLableFieldChange.bind(this);
+ this.handleValueFieldChange = this.handleValueFieldChange.bind(this);
+ this.onChange = this.onChange.bind(this);
+ }
+
+ /**
+ * 更新options字段的统一出口
+ */
+ onChange() {
+ const { source } = this.state;
+ const { onBulkChange } = this.props;
+
+ const data: Partial = {
+ source: undefined,
+ options: undefined,
+ labelField: undefined,
+ valueField: undefined
+ };
+
+ if (source === 'api') {
+ const { api, labelField, valueField } = this.state;
+ data.source = api;
+ data.labelField = labelField;
+ data.valueField = valueField;
+ }
+
+ onBulkChange && onBulkChange(data);
+ return;
+ }
+
+ /**
+ * 切换选项类型
+ */
+ handleSourceChange(source: 'custom' | 'api' | 'form') {
+ this.setState({ source: source }, this.onChange);
+ }
+
+ handleAPIChange(source: SchemaApi) {
+ this.setState({ api: source }, this.onChange);
+ }
+
+ handleLableFieldChange(labelField: string) {
+ this.setState({ labelField }, this.onChange);
+ }
+
+ handleValueFieldChange(valueField: string) {
+ this.setState({ valueField }, this.onChange);
+ }
+
+ buildBatchAddSchema() {
+ return {
+ type: 'action',
+ actionType: 'dialog',
+ label: '批量添加',
+ dialog: {
+ title: '批量添加选项',
+ headerClassName: 'font-bold',
+ closeOnEsc: true,
+ closeOnOutside: false,
+ showCloseButton: true,
+ body: [
+ {
+ type: 'alert',
+ level: 'warning',
+ body: [
+ {
+ type: 'tpl',
+ tpl: '每个选项单列一行,将所有值不重复的项加为新的选项;
每行可通过空格来分别设置label和value,例:"张三 zhangsan"'
+ }
+ ],
+ showIcon: true,
+ className: 'mb-2.5'
+ },
+ {
+ type: 'form',
+ wrapWithPanel: false,
+ mode: 'normal',
+ wrapperComponent: 'div',
+ resetAfterSubmit: true,
+ autoFocus: true,
+ preventEnterSubmit: true,
+ horizontal: {
+ left: 0,
+ right: 12
+ },
+ body: [
+ {
+ name: 'batchOption',
+ type: 'textarea',
+ label: '',
+ placeholder: '请输入选项内容',
+ trimContents: true,
+ minRows: 10,
+ maxRows: 50,
+ required: true
+ }
+ ]
+ }
+ ]
+ }
+ };
+ }
+
+ renderHeader() {
+ const { render, label, labelRemark, useMobileUI, env, popOverContainer } =
+ this.props;
+ const classPrefix = env?.theme?.classPrefix;
+ const { source } = this.state;
+ const optionSourceList = (
+ [
+ {
+ label: '自定义选项',
+ value: 'custom'
+ },
+ {
+ label: '接口获取',
+ value: 'api'
+ }
+ ] as Array<{
+ label: string;
+ value: 'custom' | 'api' | 'form';
+ }>
+ ).map(item => ({
+ ...item,
+ onClick: () => this.handleSourceChange(item.value)
+ }));
+
+ return (
+
+
+
+ {render(
+ 'validation-control-addBtn',
+ {
+ type: 'dropdown-button',
+ level: 'link',
+ size: 'sm',
+ label: '${selected}',
+ align: 'right',
+ closeOnClick: true,
+ closeOnOutside: true,
+ buttons: optionSourceList
+ },
+ {
+ popOverContainer: null,
+ data: {
+ selected: optionSourceList.find(item => item.value === source)!
+ .label
+ }
+ }
+ )}
+
+
+ );
+ }
+
+ renderApiPanel() {
+ const { render } = this.props;
+ const { source, api, labelField, valueField } = this.state;
+ if (source !== 'api') {
+ return null;
+ }
+
+ return render(
+ 'api',
+ getSchemaTpl('apiControl', {
+ label: '接口',
+ name: 'source',
+ className: 'ae-ExtendMore',
+ visibleOn: 'data.autoComplete !== false',
+ value: api,
+ onChange: this.handleAPIChange,
+ footer: [
+ {
+ label: tipedLabel(
+ '显示字段',
+ '选项文本对应的数据字段,多字段合并请通过模板配置'
+ ),
+ type: 'input-text',
+ name: 'labelField',
+ value: labelField,
+ placeholder: '选项文本对应的字段',
+ onChange: this.handleLableFieldChange
+ },
+ {
+ label: '值字段',
+ type: 'input-text',
+ name: 'valueField',
+ value: valueField,
+ placeholder: '值对应的字段',
+ onChange: this.handleValueFieldChange
+ }
+ ]
+ })
+ );
+ }
+
+ render() {
+ const { source, api, labelField, valueField } = this.state;
+ const { className } = this.props;
+ const cmptProps = {
+ ...this.props,
+ data: {
+ api,
+ labelField,
+ valueField,
+ ...this.props?.data
+ },
+ }
+
+ return (
+
+ {this.renderHeader()}
+
+ {source === 'custom' ? (
+
+ ) : null}
+
+ {this.renderApiPanel()}
+
+ );
+ }
+ }
+}
+
+const renderInput = (
+ name: string,
+ placeholder: string,
+ required: boolean = true
+) => {
+ return {
+ type: 'input-text',
+ name,
+ placeholder: placeholder,
+ required
+ }
+}
+
+export default class TransferTableOption extends React.Component {
+
+ addColumns() {
+ const { columns = [{ type: 'text' }] } = this.props.data;
+ return {
+ type: 'action',
+ actionType: 'dialog',
+ label: '添加表格列',
+ level: 'enhance',
+ dialog: {
+ title: '设置表格列选项',
+ headerClassName: 'font-bold',
+ closeOnEsc: true,
+ closeOnOutside: false,
+ showCloseButton: true,
+ body: [
+ {
+ name: 'columns',
+ type: 'combo',
+ multiple: true,
+ label: false,
+ strictMode: false,
+ addButtonText: '新增一列',
+ draggable: false,
+ value: columns,
+ onChange: (value: Array