Merge changes Ifbc9342c,I68883845,I3dad6252,I0253c53c,Iff01c432, ... into amis-saas-7944

* changes:
  Merge remote-tracking branch 'origin/feature-new-combo' into amis-saas-7944
  amis-saas-7978 Merge remote-tracking branch 'origin/amis-saas-7978' into amis-saas-7944
  amis-saas-7945 Merge remote-tracking branch 'origin/feat_input-city-improve' into amis-saas-7944
  amis-saas-7948 Merge remote-tracking branch 'origin/feat-log' into amis-saas-7944
  amis-saas-7974 Merge remote-tracking branch 'origin/amis-saas-7974' into amis-saas-7944
  amis-saas-7944 Merge remote-tracking branch 'origin/feat-tree-merge' into amis-saas-7944
This commit is contained in:
wutong25 2022-12-21 10:41:36 +08:00 committed by iCode
commit 00d330d73a
25 changed files with 2459 additions and 1614 deletions

View File

@ -128,6 +128,7 @@ import './plugin/Tasks';
import './plugin/Time'; import './plugin/Time';
import './plugin/Timeline'; import './plugin/Timeline';
import './plugin/Tpl'; import './plugin/Tpl';
import './plugin/Tag';
import './plugin/AnchorNav'; import './plugin/AnchorNav';
import './plugin/Video'; import './plugin/Video';
import './plugin/Wizard'; import './plugin/Wizard';
@ -149,6 +150,7 @@ import './plugin/Layout/Layout_free_container';
import {GridPlugin} from './plugin/Grid'; import {GridPlugin} from './plugin/Grid';
import './renderer/OptionControl'; import './renderer/OptionControl';
import './renderer/MapSourceControl';
import './renderer/TimelineItemControl'; import './renderer/TimelineItemControl';
import './renderer/APIControl'; import './renderer/APIControl';
import './renderer/ValidationControl'; import './renderer/ValidationControl';

View File

@ -26,11 +26,15 @@ export class DatePlugin extends BasePlugin {
}; };
panelTitle = '日期展示'; panelTitle = '日期展示';
panelJustify = true;
panelBodyCreator = (context: BaseEventContext) => { panelBodyCreator = (context: BaseEventContext) => {
return [ return [
getSchemaTpl('tabs', [ getSchemaTpl('tabs', [
{ {
title: '常规', title: '属性',
body: getSchemaTpl('collapseGroup', [
{
title: '基本',
body: [ body: [
{ {
type: 'input-date', type: 'input-date',
@ -51,22 +55,16 @@ export class DatePlugin extends BasePlugin {
description: '请参考 moment 中的格式用法。', description: '请参考 moment 中的格式用法。',
pipeIn: defaultValue('X') pipeIn: defaultValue('X')
}, },
{ getSchemaTpl('placeholder', {
name: 'placeholder',
type: 'input-text',
pipeIn: defaultValue('-'), pipeIn: defaultValue('-'),
label: '占位符' label: '占位符'
} })
] ]
}, },
{ getSchemaTpl('status')
title: '外观', ])
body: [getSchemaTpl('className')]
}, },
{ getSchemaTpl('onlyClassNameTab')
title: '显隐',
body: [getSchemaTpl('ref'), getSchemaTpl('visible')]
}
]) ])
]; ];
}; };

View File

@ -21,11 +21,15 @@ export class DatetimePlugin extends DatePlugin {
format: 'YYYY-MM-DD HH:mm:ss', format: 'YYYY-MM-DD HH:mm:ss',
value: Math.round(Date.now() / 1000) value: Math.round(Date.now() / 1000)
}; };
panelJustify = true;
panelBodyCreator = (context: BaseEventContext) => { panelBodyCreator = (context: BaseEventContext) => {
return [ return [
getSchemaTpl('tabs', [ getSchemaTpl('tabs', [
{ {
title: '常规', title: '属性',
body: getSchemaTpl('collapseGroup', [
{
title: '基本',
body: [ body: [
{ {
type: 'input-datetime', type: 'input-datetime',
@ -46,22 +50,16 @@ export class DatetimePlugin extends DatePlugin {
description: '请参考 moment 中的格式用法。', description: '请参考 moment 中的格式用法。',
pipeIn: defaultValue('X') pipeIn: defaultValue('X')
}, },
{ getSchemaTpl('placeholder', {
name: 'placeholder',
type: 'input-text',
pipeIn: defaultValue('-'), pipeIn: defaultValue('-'),
label: '占位符' label: '占位符'
} })
] ]
}, },
{ getSchemaTpl('status')
title: '外观', ])
body: [getSchemaTpl('className')]
}, },
{ getSchemaTpl('onlyClassNameTab')
title: '显隐',
body: [getSchemaTpl('ref'), getSchemaTpl('visible')]
}
]) ])
]; ];
}; };

View File

@ -1,23 +1,21 @@
import {Button} from 'amis';
import {registerEditorPlugin} from 'amis-editor-core';
import { import {
BaseEventContext, BaseEventContext,
BasePlugin, BasePlugin,
BasicSubRenderInfo, registerEditorPlugin,
BasicToolbarItem, defaultValue,
ContextMenuEventContext, getSchemaTpl,
ContextMenuItem, RendererPluginEvent,
RendererEventContext, RendererPluginAction,
SubRendererInfo tipedLabel,
mockValue,
RegionConfig
} from 'amis-editor-core'; } from 'amis-editor-core';
import {defaultValue, getSchemaTpl, valuePipeOut} from 'amis-editor-core';
import React from 'react';
import {diff, JSONPipeIn} from 'amis-editor-core';
import {JSONPipeOut} from 'amis-editor-core';
import {mockValue} from 'amis-editor-core';
import {RendererPluginEvent, RendererPluginAction} from 'amis-editor-core';
import {setVariable} from 'amis-core'; import {setVariable} from 'amis-core';
import {ValidatorTag} from '../../validator';
import {getArgsWrapper, getEventControlConfig} from '../../renderer/event-control/helper';
export class ComboControlPlugin extends BasePlugin { export class ComboControlPlugin extends BasePlugin {
// 关联渲染器名字 // 关联渲染器名字
rendererName = 'combo'; rendererName = 'combo';
@ -36,13 +34,21 @@ export class ComboControlPlugin extends BasePlugin {
label: '组合输入', label: '组合输入',
name: 'combo', name: 'combo',
multiple: true, multiple: true,
addable: true,
removable: true,
removableMode: 'icon',
addBtn: {
label: '新增',
icon: 'fa fa-plus',
level: 'primary',
size: 'sm'
},
items: [ items: [
{ {
type: 'input-text', type: 'input-text',
name: 'input-text', name: 'input-text',
placeholder: '文本' placeholder: '文本'
}, },
{ {
type: 'select', type: 'select',
name: 'select', name: 'select',
@ -153,6 +159,42 @@ export class ComboControlPlugin extends BasePlugin {
actionLabel: '重置', actionLabel: '重置',
description: '将值重置为resetValue若没有配置resetValue则清空' description: '将值重置为resetValue若没有配置resetValue则清空'
}, },
{
actionType: 'addItem',
actionLabel: '添加项',
description: '添加新的项',
innerArgs: ['item'],
schema: getArgsWrapper({
type: 'combo',
label: '添加项',
name: 'item',
draggable: false,
multiple: true,
removable: true,
required: true,
addable: true,
strictMode: false,
canAccessSuperData: true,
mode: 'horizontal',
items: [
{
name: 'key',
type: 'input-text',
required: true,
placeholder: '变量名',
source: '${__setValueDs}',
},
{
name: 'val',
type: 'input-formula',
variables: '${variables}',
evalMode: false,
variableMode: 'tabs',
inputMode: 'input-group'
}
]
})
},
{ {
actionType: 'setValue', actionType: 'setValue',
actionLabel: '赋值', actionLabel: '赋值',
@ -161,488 +203,417 @@ export class ComboControlPlugin extends BasePlugin {
]; ];
panelTitle = '组合输入'; panelTitle = '组合输入';
notRenderFormZone = true;
panelJustify = true;
panelBodyCreator = (context: BaseEventContext) => { panelBodyCreator = (context: BaseEventContext) => {
return [
{
name: 'conditions',
type: 'button-group-select',
size: 'sm',
mode: 'inline',
className: 'block',
options: [
{
label: '固定成员类型',
value: '1'
},
return getSchemaTpl('tabs', [
{ {
label: '多分支', title: '属性',
value: '2' body: [
} getSchemaTpl('collapseGroup', [
],
pipeIn: (value: any) => (value ? '2' : '1'),
pipeOut: (value: any) =>
value == 2
? [
{ {
label: '类型名称', className: 'p-none',
test: '', title: '常用',
items: [ body: [
{ getSchemaTpl('formItemName', {
type: 'input-text',
label: '文本',
name: 'text'
}
],
scaffold: {}
}
]
: undefined
},
{
name: 'conditions',
visibleOn: 'this.conditions',
type: 'combo',
label: '分支管理',
multiple: true,
multiLine: true,
minLength: 1,
items: [
{
label: '名称',
name: 'label',
type: 'input-text',
required: true required: true
}, }),
{ getSchemaTpl('label'),
label: '命中条件',
name: 'test',
required: true,
type: 'input-text',
placeholder: '比如: this.type === "text"',
description: '根据成员数据判断是否使用此分支'
},
{ getSchemaTpl('valueFormula', {
name: 'items', rendererSchema: {
asFormItem: true, ...context?.schema,
children: ({value, onChange}: any) => { type: 'input-text'
return (
<Button
size="sm"
level="danger"
className="m-b"
block
onClick={() =>
this.manager.openSubEditor({
title: '配置子表单项',
value: value,
slot: {
type: 'form',
mode: 'normal',
body: '$$',
wrapWithPanel: false,
className: 'wrapper'
}, },
onChange: onChange label: tipedLabel(
}) '默认值',
'支持 <code>now、+1day、-2weeks、+1hours、+2years</code>等这种相对值用法'
),
pipeOut: (value: any) => {
try {
return JSON.parse(value);
} }
> catch (err) {
return value;
</Button>
);
} }
},
{
type: 'textarea',
name: 'scaffold',
required: true,
label: '新增初始值',
pipeOut: valuePipeOut
} }
],
scaffold: {
label: '类型名称',
test: '',
items: [
{
type: 'input-text',
label: '文本',
name: 'text'
}
],
scaffold: {}
}
},
getSchemaTpl('switch', {
name: 'typeSwitchable',
visibleOn: 'this.conditions',
label: '是否可切换类型',
pipeIn: defaultValue(true)
}), }),
// 多选模式和条数绑定了,所以设定了多选,条数开启
{ getSchemaTpl('multiple', {
name: 'items', body: [
visibleOn: '!this.conditions',
asFormItem: true,
children: ({value, onChange}: any) => {
return (
<Button
size="sm"
level="danger"
className="m-b"
block
onClick={() => {
this.manager.openSubEditor({
title: '配置子表单集合',
value: value,
slot: {
type: 'form',
mode: 'normal',
body: '$$',
wrapWithPanel: false,
className: 'wrapper'
},
onChange: value => onChange(value)
});
}}
>
</Button>
);
}
},
getSchemaTpl('switchDefaultValue', {
visibleOn: '!this.defaultCheckAll'
}),
{
type: 'textarea',
name: 'value',
label: '默认值',
pipeOut: valuePipeOut,
visibleOn: 'typeof this.value !== "undefined"'
},
getSchemaTpl('switch', {
label: '多行模式',
name: 'multiLine',
value: false,
description: '即是否要换行'
}),
getSchemaTpl('multiple'),
getSchemaTpl('joinValues'),
getSchemaTpl('delimiter'),
getSchemaTpl('switch', {
name: 'flat',
label: '是否将值打平',
visibleOn:
'Array.isArray(data.items) && data.items.length === 1 && data.multiple',
description:
'默认数组内的数据结构为对象,如果只有一个表单项,可以配置将值打平,那么数组内放置的就是那个表单项的值'
}),
getSchemaTpl('switch', {
label: '是否可新增',
name: 'addable',
visibleOn: 'this.multiple',
pipeIn: defaultValue(true)
}),
{
type: 'textarea',
name: 'scaffold',
label: '新增初始值',
visibleOn: 'this.multiple && this.addable !== false',
pipeOut: valuePipeOut,
pipeIn: defaultValue({})
},
{
label: '新增按钮文字',
name: 'addButtonText',
type: 'input-text',
visibleOn: 'data.addable',
pipeIn: defaultValue('新增')
},
getSchemaTpl('switch', {
label: '是否可删除',
name: 'removable',
visibleOn: 'this.multiple',
pipeIn: defaultValue(true)
}),
getSchemaTpl('api', {
name: 'deleteApi',
label: '删除前的请求',
hiddenOn: '!data.removable'
}),
{
label: '删除确认提示',
name: 'deleteConfirmText',
type: 'input-text',
visibleOn: 'data.deleteApi',
pipeIn: defaultValue('确认要删除')
},
getSchemaTpl('switch', {
name: 'draggable',
label: '是否可拖拽排序',
visibleOn: 'this.multiple'
}),
{
label: '拖拽排序的提示文字',
name: 'draggableTip',
type: 'input-text',
visibleOn: 'data.draggable',
pipeIn: defaultValue('可通过拖动每行中的【交换】按钮进行顺序调整')
},
getSchemaTpl('switch', {
name: 'noBorder',
label: '去掉边框',
visibleOn: 'this.multiLine'
}),
{
name: 'minLength',
type: 'input-number',
label: '限制最小数量'
},
{ {
label: '最多条数',
name: 'maxLength', name: 'maxLength',
type: 'input-number', type: 'input-number',
label: '限制最大数量' visibleOn: 'data.multiple',
}, },
{
label: '最少条数',
name: 'minLength',
type: 'input-number',
visibleOn: 'data.multiple',
}
]
}),
// 可排序,排序和新增无关,和多选模式有关
getSchemaTpl('switch', {
name: 'draggable',
label: '可排序',
pipeIn: defaultValue(false),
visibleOn: 'data.multiple'
}),
{ {
label: '默认消息提示', type: 'container',
type: 'combo', className: 'ae-ExtendMore mb-3',
name: 'messages', visibleOn: 'data.draggable',
multiLine: true, body: [
description: '',
items: [
{ {
label: '有子表单项限制失败时提示',
type: 'input-text', type: 'input-text',
name: 'validateFailed' name: 'draggableTip',
}, label: tipedLabel(
'提示文字',
{ '拖拽排序的提示文字'
label: '最小长度验证失败时提示', )
type: 'input-text',
name: 'minLengthValidateFailed'
},
{
label: '最大长度验证失败时提示',
type: 'input-text',
name: 'maxLengthValidateFailed'
} }
] ]
}, },
// 可新增
getSchemaTpl('switch', { getSchemaTpl('switch', {
name: 'canAccessSuperData', name: 'addable',
label: '是否自动填充父级同名变量', label: tipedLabel(
pipeIn: defaultValue(false) '可新增',
'如需要拓展自定义的新增功能,可通过配置组件-新增项来拓展'
),
visibleOn: 'data.multiple',
pipeIn: defaultValue(false),
onChange: (value: any, oldValue: any, model: any, form: any) => {
if (value) {
form.setValueByName('addBtn', {
label: '新增',
icon: 'fa fa-plus',
level: 'primary',
size: 'sm'
});
}
}
}), }),
getSchemaTpl('switch', {
name: 'tabsMode',
label: '采用 Tabs 展示方式',
pipeIn: defaultValue(false)
}),
{ {
name: 'tabsStyle', type: 'container',
label: 'Tabs 的展示模式', className: 'ae-ExtendMore mb-3',
visibleOn: 'data.tabsMode', visibleOn: 'data.addable',
type: 'list-select', body: [
{
label: '文案',
name: 'addBtn.label',
type: 'input-text'
},
getSchemaTpl('icon', {
name: 'addBtn.icon',
label: '左侧图标'
}),
getSchemaTpl('buttonLevel', {
label: '样式',
name: 'addBtn.level'
}),
getSchemaTpl('size', {
name: 'addBtn.size',
label: '尺寸'
})
]
},
// 可删除
getSchemaTpl('switch', {
name: 'removable',
label: '可删除',
pipeIn: defaultValue(false),
visibleOn: 'data.multiple',
onChange: (value: any, oldValue: any, model: any, form: any) => {
if (value) {
form.setValueByName('removableMode', 'icon');
form.setValueByName('deleteIcon', 'fa fa-status-close');
}
}
}),
{
type: 'container',
className: 'ae-ExtendMore mb-3',
visibleOn: 'data.removable',
body: [
// 自定义新增按钮开关
{
type: 'button-group-select',
name: 'removableMode',
label: '按钮模式',
options: [ options: [
{ {
label: '正常', label: '图标',
value: 'normal' value: 'icon'
}, },
{ {
label: '水平', label: '按钮',
value: 'horizontal' value: 'button'
},
{
label: '内联',
value: 'inline'
} }
], ],
mode: 'inline', onChange: (value: any, oldValue: any, model: any, form: any) => {
className: 'w-full' if (!value) {
form.setValueByName('deleteBtn', undefined);
}
}
}, },
getSchemaTpl('icon', {
name: 'deleteIcon',
label: '图标',
visibleOn: 'data.removableMode === "icon"'
}),
{
label: '文案',
name: 'deleteBtn.label',
type: 'input-text',
visibleOn: 'data.removableMode === "button"'
},
getSchemaTpl('buttonLevel', {
label: '样式',
name: 'deleteBtn.level',
visibleOn: 'data.removableMode === "button"'
}),
getSchemaTpl('apiControl', {
name: 'deleteApi',
label: '删除',
renderLabel: false,
mode: 'normal'
}),
{
label: tipedLabel(
'确认文案',
'删除确认文案,当配置删除接口生效'
),
name: 'deleteConfirmText',
type: 'input-text',
pipeIn: defaultValue('确认要删除吗?')
}
]
},
getSchemaTpl('labelRemark'),
getSchemaTpl('remark'),
getSchemaTpl('placeholder'),
getSchemaTpl('description'),
{ {
name: 'tabsLabelTpl', type: 'container',
label: '选项卡标题的生成模板', className: 'ae-ExtendMore mb-3',
visibleOn: 'data.tabsMode', visibleOn: 'data.tabsMode',
type: 'input-text', body: [
mode: 'inline', {
className: 'w-full' type: 'ae-formulaControl',
}, name: 'tabsLabelTpl',
label: '标题模版'
getSchemaTpl('switch', {
name: 'lazyLoad',
label: '懒加载',
pipeIn: defaultValue(false),
labelRemark: {
className: 'm-l-xs',
trigger: 'click',
rootClose: true,
placement: 'left',
content: '如果数据比较多,比较卡顿时,可开启此配置项。'
} }
]
},
]
},
getSchemaTpl('status', {
isFormItem: true,
readonly: true
}),
getSchemaTpl('validation', {tag: ValidatorTag.MultiSelect}),
getSchemaTpl('collapseGroup', [
{
className: 'p-none',
title: '高级',
body: [
getSchemaTpl('switch', {
name: 'canAccessSuperData',
label: '自动填充父级变量',
pipeIn: defaultValue(false)
}), }),
getSchemaTpl('switch', { getSchemaTpl('switch', {
name: 'strictMode', name: 'strictMode',
label: '严格模式', label: tipedLabel(
pipeIn: defaultValue(true), '严格模式',
labelRemark: { '如果你希望环境变量的值实时透传到 Combo 中,请关闭此选项。'
className: 'm-l-xs', ),
trigger: 'click', value: true
rootClose: true,
placement: 'left',
content: '如果你希望环境变量的值实时透传到 Combo 中,请关闭此选项。'
}
}), }),
{ getSchemaTpl('combo-container', {
name: 'syncFields', name: 'syncFields',
visibleOn: '!data.strictMode', visibleOn: '!data.strictMode',
label: '配置同步字段', label: tipedLabel(
type: 'input-text', '同步字段',
multiple: true,
joinValues: false,
extractValue: true,
description:
'如果 Combo 层级比较深,底层的获取外层的数据可能不同步。但是给 combo 配置这个属性就能同步下来。' '如果 Combo 层级比较深,底层的获取外层的数据可能不同步。但是给 combo 配置这个属性就能同步下来。'
),
type: 'combo',
mode: 'normal',
multiple: true,
canAccessSuperData: true,
items: [
{
name: 'field',
type: 'input-text'
}
],
value: [],
pipeIn(value?: Array<string>) {
return (value ?? []).map(item => ({field: item}));
}, },
getSchemaTpl('switch', { pipeOut(value?: Array<{field: string}>) {
name: 'nullable', return (value ?? [])
label: '允许为空', .map(item => {
pipeIn: defaultValue(false), const keys = Object.keys(item);
labelRemark: { return keys.length > 0 ? item.field : '';
className: 'm-l-xs', });
trigger: 'click',
rootClose: true,
placement: 'left',
content:
'如果子表单项里面配置验证器,且又是单条模式。可以允许用户选择清空(不填)。'
} }
}), }),
getSchemaTpl('switch', {
name: 'lazyLoad',
label: tipedLabel(
'懒加载',
'如果数据比较多,比较卡顿时,可开启此配置项'
),
pipeIn: defaultValue(false),
visibleOn: 'data.multiple && !data.tabsMode',
})
]
}]
),
])
]
},
{ {
name: 'items', title: '外观',
label: '各列 CSS 配置', className: 'p-none',
hiddenOn: 'this.multiLine', body: getSchemaTpl('collapseGroup', [
type: 'combo',
addable: false,
removable: false,
multiple: true,
items: [
{ {
name: 'columnClassName', title: '基本',
placeholder: 'CSS 类名', visibleOn: 'data.multiple',
type: 'input-text' body: [
{
name: 'tabsMode',
label: '展示形式',
type: 'button-group-select',
inputClassName: 'items-center',
size: 'sm',
options: [
{label: '表单', value: false},
{label: '选项卡', value: true}
],
pipeIn: defaultValue(false),
onChange: (value: any, oldValue: any, model: any, form: any) => {
if (value) {
form.setValueByName('lazyLoad', undefined);
}
},
},
{
type: 'container',
className: 'ae-ExtendMore mb-3',
visibleOn: 'data.tabsMode',
body: [
{
type: 'button-group-select',
name: 'tabsStyle',
label: '展示形式',
options: [
{
value: 'normal',
label: '正常'
},
{
value: 'horizontal',
label: '水平'
},
{
value: 'inline',
label: '内联'
},
]
},
{
type: 'ae-formulaControl',
label: '标题模版',
name: 'tabsLabelTpl'
} }
] ]
}, },
getSchemaTpl('subFormItemMode', { // 表单多行展示
visibleOn: 'this.multiLine' getSchemaTpl('switch', {
name: 'multiLine',
label: '多行展示',
pipeIn: defaultValue(false),
onChange: (value: boolean, oldValue: any, model: any, form: any) => {
if (!value) {
form.setValueByName('subFormMode', undefined);
form.setValueByName('noBorder', undefined);
}
}
}), }),
getSchemaTpl('subFormHorizontalMode'), getSchemaTpl('switch', {
getSchemaTpl('subFormHorizontal') visibleOn: 'data.multiLine',
]; name: 'noBorder',
label: '去掉边框',
pipeIn: defaultValue(false)
}),
getSchemaTpl('subFormItemMode', {
visibleOn: 'data.multiLine',
label: '展示模式'
}),
]
},
getSchemaTpl('style:formItem', {renderer: context.info.renderer}),
getSchemaTpl('style:classNames'),
])
},
{
title: '事件',
className: 'p-none',
body: [
getSchemaTpl('eventControl', {
name: 'onEvent',
...getEventControlConfig(this.manager, context)
})
]
}
]);
}; };
filterProps(props: any) { filterProps(props: any) {
props = JSONPipeOut(props);
// 至少显示一个成员,否则啥都不显示。 // 至少显示一个成员,否则啥都不显示。
if (props.multiple && !props.value && !props.$ref) { if (props.multiple && !props.value && !props.$schema.value && !props.$ref) {
const mockedData = {}; const mockedData = {};
if (Array.isArray(props.items) && props.items.length === 0) {
if (Array.isArray(props.items)) {
props.items.forEach((control: any) => { props.items.forEach((control: any) => {
control.name && control.name &&
setVariable(mockedData, control.name, mockValue(control)); setVariable(mockedData, control.name, mockValue(control));
}); });
} }
props.value = [mockedData]; props.value = [mockedData];
return props;
} }
return props; return props;
} }
buildEditorToolbar( // 容器配置
{id, info, schema}: BaseEventContext, regions: Array<RegionConfig> = [
toolbars: Array<BasicToolbarItem> {
) { key: 'items',
if (info.renderer.name === 'combo' && !Array.isArray(schema.conditions)) { label: '内容区',
toolbars.push({ preferTag: '内容区',
icon: 'fa fa-expand', renderMethod: 'renderItems'
order: 100,
tooltip: '配置子表单项',
onClick: this.editDetail.bind(this, id)
});
}
}
buildEditorContextMenu(
{id, schema, region, info}: ContextMenuEventContext,
menus: Array<ContextMenuItem>
) {
if (info.renderer.name === 'combo' && !Array.isArray(schema.conditions)) {
menus.push('|', {
label: '配置成员渲染器',
onSelect: this.editDetail.bind(this, id)
});
}
}
editDetail(id: string) {
const manager = this.manager;
const store = manager.store;
const node = store.getNodeById(id);
const value = store.getValueOf(id);
node &&
value &&
this.manager.openSubEditor({
title: '配置子表单项',
value: value.items,
slot: {
type: 'form',
mode: 'normal',
body: '$$',
wrapWithPanel: false,
className: 'wrapper'
},
onChange: newValue => {
newValue = {
...value,
items: newValue
};
manager.panelChangeValue(newValue, diff(value, newValue));
}
});
} }
];
} }
registerEditorPlugin(ComboControlPlugin); registerEditorPlugin(ComboControlPlugin);

View File

@ -10,6 +10,7 @@ export class FormulaControlPlugin extends BasePlugin {
// 组件名称 // 组件名称
name = '公式'; name = '公式';
isBaseComponent = true; isBaseComponent = true;
disabledRendererPlugin = true;
icon = 'fa fa-calculator'; icon = 'fa fa-calculator';
pluginIcon = 'formula-plugin'; pluginIcon = 'formula-plugin';
description = '通过公式计算指定的变量值,并将其结果作用到指定的变量中'; description = '通过公式计算指定的变量值,并将其结果作用到指定的变量中';

View File

@ -7,6 +7,7 @@ import {
SubRendererInfo, SubRendererInfo,
BaseEventContext BaseEventContext
} from 'amis-editor-core'; } from 'amis-editor-core';
import cloneDeep from 'lodash/cloneDeep';
import {formItemControl} from '../../component/BaseControl'; import {formItemControl} from '../../component/BaseControl';
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core'; import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
@ -29,7 +30,10 @@ export class CityControlPlugin extends BasePlugin {
scaffold = { scaffold = {
type: 'input-city', type: 'input-city',
label: '城市选择', label: '城市选择',
name: 'city' name: 'city',
allowCity: true,
allowDistrict: true,
extractValue: true
}; };
previewSchema: any = { previewSchema: any = {
type: 'form', type: 'form',
@ -104,25 +108,64 @@ export class CityControlPlugin extends BasePlugin {
rendererWrapper: true, rendererWrapper: true,
mode: 'vertical' // 改成上下展示模式 mode: 'vertical' // 改成上下展示模式
}), }),
getSchemaTpl('switch', { {
name: 'allowDistrict', name: 'extractValue',
label: '允许选择区域', label: '值格式',
pipeIn: defaultValue(true) type: 'button-group-select',
}), size: 'sm',
options: [
{label: '行政编码', value: true},
{label: '对象结构', value: false}
]
},
getSchemaTpl('switch', { getSchemaTpl('switch', {
name: 'allowCity', name: 'allowCity',
label: '允许选择城市', label: '可选城市',
pipeIn: defaultValue(true) pipeIn: defaultValue(true),
onChange: (
value: string,
oldValue: string,
item: any,
form: any
) => {
if (!value) {
const schema = cloneDeep(form.data);
form.setValueByName('allowDistrict', undefined);
form.setValueByName('value', schema.extractValue ? '' : {});
}
}
}),
getSchemaTpl('switch', {
name: 'allowDistrict',
label: '可选区域',
visibleOn: 'data.allowCity',
pipeIn: defaultValue(true),
onChange: (
value: string,
oldValue: string,
item: any,
form: any
) => {
if (!value) {
const schema = cloneDeep(form.data);
form.setValueByName('value', schema.extractValue ? '' : {});
}
}
}), }),
getSchemaTpl('switch', { getSchemaTpl('switch', {
name: 'searchable', name: 'searchable',
label: '是否出搜索框', label: '可搜索',
pipeIn: defaultValue(false) pipeIn: defaultValue(false)
}), }),
getSchemaTpl('loadingConfig', {}, {context}) getSchemaTpl('loadingConfig', {}, {context}),
getSchemaTpl('labelRemark'),
getSchemaTpl('remark'),
getSchemaTpl('description'),
getSchemaTpl('autoFillApi')
] ]
}, },
getSchemaTpl('status', {isFormItem: true}), getSchemaTpl('status', {isFormItem: true}),

View File

@ -407,7 +407,7 @@ export class DateControlPlugin extends BasePlugin {
size: 'md', size: 'md',
label: '模式', label: '模式',
mode: 'row', mode: 'row',
value: false, pipeIn: defaultValue(false),
options: [ options: [
{ {
label: '浮层', label: '浮层',

View File

@ -416,7 +416,7 @@ export class DateRangeControlPlugin extends BasePlugin {
size: 'md', size: 'md',
label: '模式', label: '模式',
mode: 'row', mode: 'row',
value: false, pipeIn: defaultValue(false),
options: [ options: [
{ {
label: '浮层', label: '浮层',

View File

@ -20,8 +20,8 @@ export class TreeControlPlugin extends BasePlugin {
isBaseComponent = true; isBaseComponent = true;
icon = 'fa fa-list-alt'; icon = 'fa fa-list-alt';
pluginIcon = 'input-tree-plugin'; pluginIcon = 'input-tree-plugin';
description = description = '树型结构选择,支持 [内嵌模式] 与 [浮层模式] 的外观切换';
'树型结构来选择,可通过 options 来配置选项,也可通过 source 拉取选项'; searchKeywords = 'tree、树下拉、树下拉框、tree-select';
docLink = '/amis/zh-CN/components/form/input-tree'; docLink = '/amis/zh-CN/components/form/input-tree';
tags = ['表单项']; tags = ['表单项'];
scaffold = { scaffold = {
@ -55,9 +55,13 @@ export class TreeControlPlugin extends BasePlugin {
className: 'text-left', className: 'text-left',
mode: 'horizontal', mode: 'horizontal',
wrapWithPanel: false, wrapWithPanel: false,
body: { body: [
...this.scaffold {
...this.scaffold,
label: '树选择框 - 内嵌模式',
mode: 'normal'
} }
]
}; };
notRenderFormZone = true; notRenderFormZone = true;
@ -280,6 +284,34 @@ export class TreeControlPlugin extends BasePlugin {
required: true required: true
}), }),
getSchemaTpl('label'), getSchemaTpl('label'),
{
type: 'button-group-select',
name: 'type',
label: '模式',
pipeIn: defaultValue('input-tree'),
options: [
{
label: '内嵌',
value: 'input-tree'
},
{
label: '浮层',
value: 'tree-select'
}
]
},
getSchemaTpl('clearable', {
mode: 'horizontal',
horizontal: {
justify: true,
left: 8
},
inputClassName: 'is-inline ',
visibleOn: 'data.type === "tree-select"'
}),
getSchemaTpl('searchable', {
visibleOn: 'data.type === "tree-select"'
}),
getSchemaTpl('multiple', { getSchemaTpl('multiple', {
body: [ body: [
{ {
@ -404,7 +436,8 @@ export class TreeControlPlugin extends BasePlugin {
getSchemaTpl('valueFormula', { getSchemaTpl('valueFormula', {
name: 'highlightTxt', name: 'highlightTxt',
label: '高亮节点字符', label: '高亮节点字符',
type: 'input-text' type: 'input-text',
visibleOn: 'data.type === "input-tree"'
}), }),
{ {
type: 'ae-Switch-More', type: 'ae-Switch-More',
@ -445,8 +478,17 @@ export class TreeControlPlugin extends BasePlugin {
name: 'rootLabel' name: 'rootLabel'
} }
] ]
}
}, },
visibleOn: 'data.type === "input-tree"'
},
getSchemaTpl('switch', {
label: tipedLabel(
'选项文本仅显示选中节点',
'隐藏选择框中已选中节点的祖先节点的文本信息'
),
name: 'hideNodePathLabel',
visibleOn: 'data.type==="tree-select"'
}),
getSchemaTpl('switch', { getSchemaTpl('switch', {
label: '显示节点图标', label: '显示节点图标',
name: 'showIcon', name: 'showIcon',
@ -460,6 +502,10 @@ export class TreeControlPlugin extends BasePlugin {
name: 'showRadio', name: 'showRadio',
hiddenOn: 'data.multiple' hiddenOn: 'data.multiple'
}), }),
getSchemaTpl('switch', {
label: tipedLabel('显示层级展开线', '显示树层级展开线'),
name: 'showOutline'
}),
getSchemaTpl('switch', { getSchemaTpl('switch', {
name: 'withChildren', name: 'withChildren',
label: '数值是否携带子节点', label: '数值是否携带子节点',

View File

@ -1,91 +1,33 @@
import React from 'react'; import React from 'react';
import {Button} from 'amis'; import {Button} from 'amis';
import {defaultValue, getSchemaTpl} from 'amis-editor-core'; import {
defaultValue,
getSchemaTpl,
setSchemaTpl,
tipedLabel
} from 'amis-editor-core';
import {registerEditorPlugin} from 'amis-editor-core'; import {registerEditorPlugin} from 'amis-editor-core';
import {BaseEventContext, BasePlugin} from 'amis-editor-core'; import {BaseEventContext, BasePlugin} from 'amis-editor-core';
import {EditorNodeType} from 'amis-editor-core'; import {EditorNodeType} from 'amis-editor-core';
import {mockValue} from 'amis-editor-core'; import {mockValue} from 'amis-editor-core';
export class StaticControlPlugin extends BasePlugin { // 快速编辑
// 关联渲染器名字 setSchemaTpl('quickEdit', {
rendererName = 'static'; type: 'ae-switch-more',
$schema = '/schemas/StaticControlSchema.json'; mode: 'normal',
order = -390;
// 组件名称
name = '静态展示框';
isBaseComponent = true;
icon = 'fa fa-info';
pluginIcon = 'static-plugin';
description = '纯用来展示数据,可用来展示 json、date、image、progress 等数据';
docLink = '/amis/zh-CN/components/form/static';
tags = ['表单项'];
scaffold = {
type: 'static',
label: '描述'
};
previewSchema: any = {
type: 'form',
className: 'text-left',
mode: 'horizontal',
wrapWithPanel: false,
body: [
{
...this.scaffold,
value: '静态值'
}
]
};
multifactor = true;
notRenderFormZone = true;
panelTitle = '静态展示';
panelBodyCreator = (context: BaseEventContext) => {
const renderer: any = context.info.renderer;
return getSchemaTpl('tabs', [
{
title: '属性',
body: getSchemaTpl('collapseGroup', [
{
title: '基本',
body: [
getSchemaTpl('formItemName', {
required: false
}),
getSchemaTpl('label'),
// getSchemaTpl('value'),
/*
getSchemaTpl('valueFormula', {
name: 'tpl',
// rendererSchema: {
// ...context?.schema,
// type: 'textarea', // 改用多行文本编辑
// value: context?.schema.tpl // 避免默认值丢失
// },
mode: 'vertical' // 改成上下展示模式
}),
*/
{
type: 'ae-textareaFormulaControl',
label: '默认值',
name: 'tpl',
mode: 'normal'
},
getSchemaTpl('switch', {
name: 'quickEdit', name: 'quickEdit',
label: '可快速编辑', label: '可快速编辑',
pipeIn: (value: any) => !!value value: false,
}), hiddenOnDefault: true,
formType: 'extend',
pipeIn: (value: any) => !!value,
form: {
body: [
{ {
label: '快速编辑模式', label: '编辑模式',
name: 'quickEdit.mode', name: 'quickEdit.mode',
type: 'button-group-select', type: 'button-group-select',
size: 'sm', inputClassName: 'items-center',
mode: 'row',
className: 'ae-buttonGroupSelect--justify',
visibleOn: 'data.quickEdit', visibleOn: 'data.quickEdit',
pipeIn: defaultValue('popOver'), pipeIn: defaultValue('popOver'),
options: [ options: [
@ -101,28 +43,26 @@ export class StaticControlPlugin extends BasePlugin {
}, },
getSchemaTpl('switch', { getSchemaTpl('switch', {
name: 'quickEdit.saveImmediately', name: 'quickEdit.saveImmediately',
label: '立即保存', label: tipedLabel(
'立即保存',
'开启后修改即提交,而不是标记修改批量提交。'
),
visibleOn: 'data.quickEdit', visibleOn: 'data.quickEdit',
labelRemark: {
className: 'm-l-xs',
trigger: 'click',
rootClose: true,
placement: 'left',
content: '开启后修改即提交,而不是标记修改批量提交。'
},
pipeIn: (value: any) => !!value pipeIn: (value: any) => !!value
}), }),
getSchemaTpl('apiControl', { getSchemaTpl('apiControl', {
name: 'quickEdit.saveImmediately.api', name: 'quickEdit.saveImmediately.api',
label: '立即保存接口', label: '保存接口',
mode: 'row',
description: description:
'是否单独给立即保存配置接口如果不配置则默认使用quickSaveItemApi。', '单独给立即保存配置接口如果不配置则默认使用quickSaveItemApi。',
visibleOn: 'this.quickEdit && this.quickEdit.saveImmediately' visibleOn: 'this.quickEdit && this.quickEdit.saveImmediately'
}), }),
{ {
name: 'quickEdit', name: 'quickEdit',
asFormItem: true, asFormItem: true,
visibleOn: 'data.quickEdit', visibleOn: 'data.quickEdit',
mode: 'row',
children: ({value, onChange, data}: any) => { children: ({value, onChange, data}: any) => {
if (value === true) { if (value === true) {
value = {}; value = {};
@ -141,9 +81,8 @@ export class StaticControlPlugin extends BasePlugin {
return ( return (
<Button <Button
className="m-b ae-Button--enhance"
size="sm"
block block
level="primary"
onClick={() => { onClick={() => {
this.manager.openSubEditor({ this.manager.openSubEditor({
title: '配置快速编辑类型', title: '配置快速编辑类型',
@ -169,19 +108,27 @@ export class StaticControlPlugin extends BasePlugin {
</Button> </Button>
); );
} }
}, }
getSchemaTpl('switch', { ]
}
});
// 查看更多
setSchemaTpl('morePopOver', {
type: 'ae-switch-more',
mode: 'normal',
name: 'popOver', name: 'popOver',
label: '查看更多展示', label: '查看更多展示',
pipeIn: (value: any) => !!value value: false,
}), hiddenOnDefault: true,
formType: 'extend',
pipeIn: (value: any) => !!value,
form: {
body: [
{ {
label: '弹出模式', label: '弹出模式',
name: 'popOver.mode', name: 'popOver.mode',
type: 'button-group-select', type: 'button-group-select',
size: 'sm',
mode: 'row',
className: 'ae-buttonGroupSelect--justify',
visibleOn: 'data.popOver', visibleOn: 'data.popOver',
pipeIn: defaultValue('popOver'), pipeIn: defaultValue('popOver'),
options: [ options: [
@ -205,50 +152,42 @@ export class StaticControlPlugin extends BasePlugin {
name: 'popOver.position', name: 'popOver.position',
label: '浮层位置', label: '浮层位置',
type: 'select', type: 'select',
mode: 'row', visibleOn:
visibleOn: 'data.popOver && data.popOver.mode === "popOver"', 'data.popOver && (data.popOver.mode === "popOver" || !data.popOver.mode)',
pipeIn: defaultValue('center'), pipeIn: defaultValue('center'),
options: [ options: [
{
label: '目标中部',
value: 'center'
},
{ {
label: '目标左上角', label: '目标左上角',
value: 'left-top' value: 'left-top'
}, },
{ {
label: '目标右上角', label: '目标右上角',
value: 'right-top' value: 'right-top'
}, },
{
label: '目标中部',
value: 'center'
},
{ {
label: '目标左下角', label: '目标左下角',
value: 'left-bottom' value: 'left-bottom'
}, },
{ {
label: '目标右下角', label: '目标右下角',
value: 'right-bottom' value: 'right-bottom'
}, },
{ {
label: '页面左上角', label: '页面左上角',
value: 'fixed-left-top' value: 'fixed-left-top'
}, },
{ {
label: '页面右上角', label: '页面右上角',
value: 'fixed-right-top' value: 'fixed-right-top'
}, },
{ {
label: '页面左下角', label: '页面左下角',
value: 'fixed-left-bottom' value: 'fixed-left-bottom'
}, },
{ {
label: '页面右下角', label: '页面右下角',
value: 'fixed-right-bottom' value: 'fixed-right-bottom'
@ -258,6 +197,7 @@ export class StaticControlPlugin extends BasePlugin {
{ {
visibleOn: 'data.popOver', visibleOn: 'data.popOver',
name: 'popOver', name: 'popOver',
mode: 'row',
asFormItem: true, asFormItem: true,
children: ({value, onChange}: any) => { children: ({value, onChange}: any) => {
value = { value = {
@ -269,9 +209,8 @@ export class StaticControlPlugin extends BasePlugin {
return ( return (
<Button <Button
className="m-b ae-Button--enhance"
size="sm"
block block
level="primary"
onClick={() => { onClick={() => {
this.manager.openSubEditor({ this.manager.openSubEditor({
title: '配置查看更多展示内容', title: '配置查看更多展示内容',
@ -284,14 +223,23 @@ export class StaticControlPlugin extends BasePlugin {
</Button> </Button>
); );
} }
}, }
getSchemaTpl('borderMode'), ]
getSchemaTpl('switch', { }
});
// 可复制
setSchemaTpl('copyable', {
type: 'ae-switch-more',
mode: 'normal',
name: 'copyable', name: 'copyable',
label: '可复制', label: '可复制',
pipeIn: (value: any) => !!value value: false,
}), hiddenOnDefault: true,
formType: 'extend',
pipeIn: (value: any) => !!value,
form: {
body: [
{ {
label: '复制内容模板', label: '复制内容模板',
name: 'copyable.content', name: 'copyable.content',
@ -300,12 +248,84 @@ export class StaticControlPlugin extends BasePlugin {
maxRow: 2, maxRow: 2,
visibleOn: 'data.copyable', visibleOn: 'data.copyable',
description: '默认为当前字段值,可定制。' description: '默认为当前字段值,可定制。'
}
]
}
});
export class StaticControlPlugin extends BasePlugin {
// 关联渲染器名字
rendererName = 'static';
$schema = '/schemas/StaticControlSchema.json';
order = -390;
// 组件名称
name = '静态展示框';
isBaseComponent = false;
icon = 'fa fa-info';
pluginIcon = 'static-plugin';
description = '纯用来展示数据,可用来展示 json、date、image、progress 等数据';
docLink = '/amis/zh-CN/components/form/static';
tags = ['表单项'];
scaffold = {
type: 'static',
label: '描述'
};
previewSchema: any = {
type: 'form',
className: 'text-left',
mode: 'horizontal',
wrapWithPanel: false,
body: [
{
...this.scaffold,
value: '静态值'
}
]
};
multifactor = true;
notRenderFormZone = true;
panelTitle = '静态展示';
panelJustify = true;
panelBodyCreator = (context: BaseEventContext) => {
const renderer: any = context.info.renderer;
return getSchemaTpl('tabs', [
{
title: '属性',
body: getSchemaTpl('collapseGroup', [
{
title: '基本',
body: [
{
type: 'alert',
inline: false,
level: 'warning',
className: 'text-sm',
body: '<p>当前组件已停止维护,建议您使用<a href="https://baidu.gitee.io/amis/zh-CN/components/form/formitem#%E9%85%8D%E7%BD%AE%E9%9D%99%E6%80%81%E5%B1%95%E7%A4%BA" target="_blank">静态展示</a>新特性实现表单项的静态展示。</p>'
}, },
getSchemaTpl('formItemName', {
required: false
}),
getSchemaTpl('label')
// getSchemaTpl('value'),
/*
getSchemaTpl('valueFormula', {
name: 'tpl',
// rendererSchema: {
// ...context?.schema,
// type: 'textarea', // 改用多行文本编辑
// value: context?.schema.tpl // 避免默认值丢失
// }
}),
getSchemaTpl('quickEdit'),
getSchemaTpl('morePopOver'),
getSchemaTpl('copyable'),
getSchemaTpl('labelRemark'), getSchemaTpl('labelRemark'),
getSchemaTpl('remark'), getSchemaTpl('remark'),
getSchemaTpl('placeholder'), getSchemaTpl('placeholder'),
getSchemaTpl('description'), getSchemaTpl('description')
getSchemaTpl('autoFillApi')
/*{ /*{
children: ( children: (
<Button <Button
@ -321,14 +341,20 @@ export class StaticControlPlugin extends BasePlugin {
},*/ },*/
] ]
}, },
getSchemaTpl('status', {isFormItem: true}), getSchemaTpl('status', {
getSchemaTpl('validation', {tag: '1'}) isFormItem: true,
unsupportStatic: true
})
]) ])
}, },
{ {
title: '外观', title: '外观',
body: getSchemaTpl('collapseGroup', [ body: getSchemaTpl('collapseGroup', [
getSchemaTpl('style:formItem', {renderer}), getSchemaTpl('style:formItem', {renderer}),
{
title: '控件',
body: [getSchemaTpl('borderMode')]
},
{ {
title: 'CSS类名', title: 'CSS类名',
body: [ body: [

View File

@ -12,17 +12,18 @@ export class TreeSelectControlPlugin extends BasePlugin {
$schema = '/schemas/TreeSelectControlSchema.json'; $schema = '/schemas/TreeSelectControlSchema.json';
// 组件名称 // 组件名称
name = '树下拉框'; name = '树选择框';
isBaseComponent = true; isBaseComponent = true;
icon = 'fa fa-chevron-down'; disabledRendererPlugin = true;
icon = 'fa fa-list-alt';
pluginIcon = 'tree-select-plugin'; pluginIcon = 'tree-select-plugin';
description = '点击输入框,弹出树型选择框进行选择'; description = '树型结构选择,支持 [内嵌模式] 与 [浮层模式] 的外观切换';
docLink = '/amis/zh-CN/components/form/treeselect'; docLink = '/amis/zh-CN/components/form/treeselect';
tags = ['表单项']; tags = ['表单项'];
scaffold = { scaffold = {
type: 'tree-select', type: 'tree-select',
label: '树下拉框', label: '树下拉框',
name: 'tree-select', name: 'tree',
clearable: false, clearable: false,
options: [ options: [
{ {
@ -58,7 +59,7 @@ export class TreeSelectControlPlugin extends BasePlugin {
notRenderFormZone = true; notRenderFormZone = true;
panelTitle = '树下拉'; panelTitle = '树选择';
// 事件定义 // 事件定义
events: RendererPluginEvent[] = [ events: RendererPluginEvent[] = [
@ -265,16 +266,34 @@ export class TreeSelectControlPlugin extends BasePlugin {
required: true required: true
}), }),
getSchemaTpl('label'), getSchemaTpl('label'),
{
type: 'button-group-select',
name: 'type',
label: '模式',
pipeIn: defaultValue('tree-select'),
options: [
{
label: '内嵌',
value: 'input-tree'
},
{
label: '浮层',
value: 'tree-select'
}
]
},
getSchemaTpl('clearable', { getSchemaTpl('clearable', {
mode: 'horizontal', mode: 'horizontal',
horizontal: { horizontal: {
justify: true, justify: true,
left: 8 left: 8
}, },
inputClassName: 'is-inline ' inputClassName: 'is-inline ',
visibleOn: 'data.type === "tree-select"'
}),
getSchemaTpl('searchable', {
visibleOn: 'data.type === "tree-select"'
}), }),
getSchemaTpl('searchable'),
getSchemaTpl('multiple', { getSchemaTpl('multiple', {
body: [ body: [
{ {
@ -397,6 +416,12 @@ export class TreeSelectControlPlugin extends BasePlugin {
{ {
title: '高级', title: '高级',
body: [ body: [
getSchemaTpl('valueFormula', {
name: 'highlightTxt',
label: '高亮节点字符',
type: 'input-text',
visibleOn: 'data.type === "input-tree"'
}),
{ {
type: 'ae-Switch-More', type: 'ae-Switch-More',
mode: 'normal', mode: 'normal',
@ -418,34 +443,35 @@ export class TreeSelectControlPlugin extends BasePlugin {
] ]
} }
}, },
{
type: 'ae-Switch-More',
mode: 'normal',
name: 'hideRoot',
label: '显示顶级节点',
value: true,
trueValue: false,
falseValue: true,
formType: 'extend',
form: {
body: [
{
type: 'input-text',
label: '节点文案',
value: '顶级',
name: 'rootLabel'
}
]
},
visibleOn: 'data.type === "input-tree"'
},
getSchemaTpl('switch', { getSchemaTpl('switch', {
label: tipedLabel( label: tipedLabel(
'选项文本仅显示选中节点', '选项文本仅显示选中节点',
'隐藏选择框中已选中节点的祖先节点的文本信息' '隐藏选择框中已选中节点的祖先节点的文本信息'
), ),
name: 'hideNodePathLabel' name: 'hideNodePathLabel',
visibleOn: 'data.type==="tree-select"'
}), }),
// tree-select 该组件目前无此配置
// {
// type: 'ae-Switch-More',
// mode: 'normal',
// name: 'hideRoot',
// label: '显示顶级节点',
// value: true,
// trueValue: false,
// falseValue: true,
// formType: 'extend',
// form: {
// body: [
// {
// type: 'input-text',
// label: '节点文案',
// value: '顶级',
// name: 'rootLabel'
// }
// ]
// }
// },
getSchemaTpl('switch', { getSchemaTpl('switch', {
label: '显示节点图标', label: '显示节点图标',
name: 'showIcon', name: 'showIcon',
@ -463,6 +489,19 @@ export class TreeSelectControlPlugin extends BasePlugin {
label: tipedLabel('显示层级展开线', '显示树层级展开线'), label: tipedLabel('显示层级展开线', '显示树层级展开线'),
name: 'showOutline' name: 'showOutline'
}), }),
getSchemaTpl('switch', {
name: 'withChildren',
label: '数值是否携带子节点',
visibleOn: 'data.cascade !== true && data.multiple',
disabledOn: 'data.onlyChildren'
}),
getSchemaTpl('switch', {
name: 'onlyChildren',
label: '数值是否只包含子节点',
visibleOn: 'data.cascade !== true && data.multiple',
disabledOn: 'data.withChildren'
}),
{ {
type: 'ae-Switch-More', type: 'ae-Switch-More',
mode: 'normal', mode: 'normal',
@ -505,7 +544,7 @@ export class TreeSelectControlPlugin extends BasePlugin {
getSchemaTpl('style:classNames', { getSchemaTpl('style:classNames', {
schema: [ schema: [
getSchemaTpl('className', { getSchemaTpl('className', {
label: 'tree容器', label: '外层容器',
name: 'treeContainerClassName' name: 'treeContainerClassName'
}) })
] ]

View File

@ -32,12 +32,15 @@ export class ImagePlugin extends BasePlugin {
}; };
panelTitle = '图片'; panelTitle = '图片';
panelJustify = true;
panelBodyCreator = (context: BaseEventContext) => { panelBodyCreator = (context: BaseEventContext) => {
const isUnderField = /\/field\/\w+$/.test(context.path as string); const isUnderField = /\/field\/\w+$/.test(context.path as string);
return [ return getSchemaTpl('tabs', [
getSchemaTpl('tabs', [
{ {
title: '常规', title: '属性',
body: getSchemaTpl('collapseGroup', [
{
title: '基本',
body: [ body: [
{ {
name: 'imageMode', name: 'imageMode',
@ -96,31 +99,44 @@ export class ImagePlugin extends BasePlugin {
}) })
] ]
}, },
getSchemaTpl('status')
])
},
{ {
title: '外观', title: '外观',
body: getSchemaTpl('collapseGroup', [
{
title: '基本',
body: [ body: [
getSchemaTpl('switch', { {
type: 'ae-switch-more',
mode: 'normal',
name: 'enlargeAble', name: 'enlargeAble',
label: '开启图片放大功能' label: '图片放大功能',
}), value: false,
hiddenOnDefault: false,
formType: 'extend',
pipeIn: (value: any) => !!value,
form: {
body: [
getSchemaTpl('imageUrl', { getSchemaTpl('imageUrl', {
name: 'originalSrc', name: 'originalSrc',
visibleOn: 'this.enlargeAble',
label: '原图地址', label: '原图地址',
description: '如果不配置将默认使用缩略图地址。' description: '如果不配置将默认使用缩略图地址。'
}), })
]
}
},
getSchemaTpl('switch', { getSchemaTpl('switch', {
name: 'showDimensions', name: 'showDimensions',
label: '是否显示图片尺寸' label: '显示图片尺寸'
}), }),
{ {
name: 'thumbMode', name: 'thumbMode',
type: 'button-group-select', type: 'select',
label: '缩略图展示模式', label: '缩略图展示模式',
size: 'sm',
pipeIn: defaultValue('contain'), pipeIn: defaultValue('contain'),
options: [ options: [
{ {
@ -144,7 +160,6 @@ export class ImagePlugin extends BasePlugin {
} }
] ]
}, },
{ {
name: 'thumbRatio', name: 'thumbRatio',
type: 'button-group-select', type: 'button-group-select',
@ -167,37 +182,30 @@ export class ImagePlugin extends BasePlugin {
value: '16:9' value: '16:9'
} }
] ]
}
]
}, },
{
title: 'CSS类名',
body: [
getSchemaTpl('className', { getSchemaTpl('className', {
autoComplete: false label: '外层'
}),
getSchemaTpl('className', {
name: 'innerClassName',
label: '组件内层 CSS 类名'
}), }),
getSchemaTpl('className', { getSchemaTpl('className', {
name: 'imageClassName', name: 'imageClassName',
label: '图片 CSS 类名' label: '图片'
}), }),
getSchemaTpl('className', { getSchemaTpl('className', {
name: 'thumbClassName', name: 'thumbClassName',
label: '缩略图 CSS 类名' label: '缩略图'
}) })
] ]
},
{
title: '显隐',
body: [
// getSchemaTpl('ref'),
getSchemaTpl('visible')
]
} }
]) ])
]; }
]);
}; };
onActive(event: PluginEvent<ActiveEventContext>) { onActive(event: PluginEvent<ActiveEventContext>) {

View File

@ -37,15 +37,16 @@ export class ImagesPlugin extends BasePlugin {
}; };
panelTitle = '图片集'; panelTitle = '图片集';
panelJustify = true;
panelBodyCreator = (context: BaseEventContext) => { panelBodyCreator = (context: BaseEventContext) => {
const isUnderField = /\/field\/\w+$/.test(context.path as string); const isUnderField = /\/field\/\w+$/.test(context.path as string);
return [ return getSchemaTpl('tabs', [
getSchemaTpl('tabs', [
{ {
title: '常规', title: '属性',
body: (isUnderField body: getSchemaTpl('collapseGroup', [
? [] {
: [ title: '基本',
body: (isUnderField ? [] : [
{ {
type: 'formula', type: 'formula',
name: '__mode', name: '__mode',
@ -120,40 +121,53 @@ export class ImagesPlugin extends BasePlugin {
} }
] ]
} }
] ]).concat([
).concat([
getSchemaTpl('imageUrl', { getSchemaTpl('imageUrl', {
name: 'defaultImage', name: 'defaultImage',
label: '无数据时显示的图片' label: '无数据时显示的图片'
}) })
]) ])
}, },
getSchemaTpl('status')
])
},
{ {
title: '外观', title: '外观',
body: getSchemaTpl('collapseGroup', [
{
title: '基本',
body: [ body: [
getSchemaTpl('switch', { {
type: 'ae-switch-more',
mode: 'normal',
name: 'enlargeAble', name: 'enlargeAble',
label: '开启图片放大功能' label: '图片放大功能',
}), value: false,
hiddenOnDefault: false,
formType: 'extend',
pipeIn: (value: any) => !!value,
form: {
body: [
{ {
name: 'originalSrc', name: 'originalSrc',
visibleOn: 'this.enlargeAble', visibleOn: 'this.enlargeAble',
type: 'input-text', type: 'input-text',
label: '原图地址', label: '原图地址',
description: '如果不配置将默认使用缩略图地址。' description: '如果不配置将默认使用缩略图地址。'
}
]
}
}, },
getSchemaTpl('switch', { getSchemaTpl('switch', {
name: 'showDimensions', name: 'showDimensions',
label: '是否显示图片尺寸' label: '显示图片尺寸'
}), }),
{ {
name: 'thumbMode', name: 'thumbMode',
type: 'button-group-select', type: 'select',
label: '缩略图展示模式', label: '缩略图展示模式',
size: 'sm',
pipeIn: defaultValue('contain'), pipeIn: defaultValue('contain'),
options: [ options: [
{ {
@ -200,27 +214,26 @@ export class ImagesPlugin extends BasePlugin {
value: '16:9' value: '16:9'
} }
] ]
}
]
}, },
{
title: 'CSS类名',
body: [
getSchemaTpl('className', { getSchemaTpl('className', {
autoComplete: false autoComplete: false,
label: '外层'
}), }),
getSchemaTpl('className', { getSchemaTpl('className', {
name: 'listClassName', name: 'listClassName',
label: '图片列表 CSS 类名' label: '图片列表'
}) })
] ]
},
{
title: '显隐',
body: [
// getSchemaTpl('ref'),
getSchemaTpl('visible')
]
} }
]) ])
]; }
]);
}; };
} }

View File

@ -30,19 +30,23 @@ export class JsonPlugin extends BasePlugin {
}; };
panelTitle = 'JSON'; panelTitle = 'JSON';
panelJustify = true;
panelBodyCreator = (context: BaseEventContext) => { panelBodyCreator = (context: BaseEventContext) => {
const isUnderField = /\/field\/\w+$/.test(context.path as string); const isUnderField = /\/field\/\w+$/.test(context.path as string);
return [ return [
getSchemaTpl('tabs', [ getSchemaTpl('tabs', [
{ {
title: '常规', title: '属性',
body: flatten([ body: getSchemaTpl('collapseGroup', [
{
title: '基本',
body: [
isUnderField isUnderField
? { ? {
type: 'tpl', type: 'tpl',
inline: false, inline: false,
className: 'text-info text-sm', className: 'text-info text-sm',
tpl: '<p>当前为字段内容节点配置,选择上层还有更多配置</p>' tpl: '<p>当前为字段内容节点配置,选择上层还有更多配置</p>'
} }
: null, : null,
@ -52,16 +56,12 @@ export class JsonPlugin extends BasePlugin {
label: '默认展开级别', label: '默认展开级别',
pipeIn: defaultValue(1) pipeIn: defaultValue(1)
} }
]
},
getSchemaTpl('status')
]) ])
}, },
{ getSchemaTpl('onlyClassNameTab')
title: '外观',
body: flatten([getSchemaTpl('className')])
},
{
title: '显隐',
body: flatten([getSchemaTpl('ref'), getSchemaTpl('visible')])
}
]) ])
]; ];
}; };

View File

@ -55,12 +55,15 @@ export class ListPlugin extends BasePlugin {
}; };
panelTitle = '列表'; panelTitle = '列表';
panelJustify = true;
panelBodyCreator = (context: BaseEventContext) => { panelBodyCreator = (context: BaseEventContext) => {
const isCRUDBody = context.schema.type === 'crud'; const isCRUDBody = context.schema.type === 'crud';
return getSchemaTpl('tabs', [ return getSchemaTpl('tabs', [
{ {
title: '常规', title: '属性',
body: getSchemaTpl('collapseGroup', [
{
title: '基本',
body: [ body: [
{ {
children: ( children: (
@ -99,8 +102,14 @@ export class ListPlugin extends BasePlugin {
} }
] ]
}, },
getSchemaTpl('status')
])
},
{ {
title: '外观', title: '外观',
body: getSchemaTpl('collapseGroup', [
{
title: '基本',
body: [ body: [
getSchemaTpl('switch', { getSchemaTpl('switch', {
name: 'showHeader', name: 'showHeader',
@ -112,28 +121,30 @@ export class ListPlugin extends BasePlugin {
name: 'showFooter', name: 'showFooter',
label: '是否显示底部', label: '是否显示底部',
pipeIn: defaultValue(true) pipeIn: defaultValue(true)
}),
getSchemaTpl('className', {
label: 'CSS 类名'
}),
getSchemaTpl('className', {
name: 'listClassName',
label: 'List div CSS 类名'
}),
getSchemaTpl('className', {
name: 'headerClassName',
label: '头部 CSS 类名'
}),
getSchemaTpl('className', {
name: 'footerClassName',
label: '底部 CSS 类名'
}) })
] ]
}, },
{ {
title: '显隐', title: 'CSS类名',
body: [getSchemaTpl('ref'), getSchemaTpl('visible')] body: [
getSchemaTpl('className', {
label: '外层'
}),
getSchemaTpl('className', {
name: 'listClassName',
label: 'List'
}),
getSchemaTpl('className', {
name: 'headerClassName',
label: '头部'
}),
getSchemaTpl('className', {
name: 'footerClassName',
label: '底部'
})
]
}
])
} }
]); ]);
}; };

View File

@ -3,7 +3,7 @@
*/ */
import {registerEditorPlugin} from 'amis-editor-core'; import {registerEditorPlugin} from 'amis-editor-core';
import {BaseEventContext, BasePlugin} from 'amis-editor-core'; import {BaseEventContext, BasePlugin} from 'amis-editor-core';
import {getSchemaTpl} from 'amis-editor-core'; import {getSchemaTpl, tipedLabel} from 'amis-editor-core';
export class LogPlugin extends BasePlugin { export class LogPlugin extends BasePlugin {
// 关联渲染器名字 // 关联渲染器名字
@ -20,31 +20,123 @@ export class LogPlugin extends BasePlugin {
tags = ['展示']; tags = ['展示'];
previewSchema = { previewSchema = {
type: 'log', type: 'log',
height: 120 height: 120,
autoScroll: true
}; };
scaffold: any = { scaffold: any = {
type: 'log' type: 'log',
autoScroll: true,
height: 500,
encoding: 'utf-8'
}; };
panelJustify = true;
panelTitle = '日志'; panelTitle = '日志';
panelBodyCreator = (context: BaseEventContext) => { panelBodyCreator = (context: BaseEventContext) => {
const renderer: any = context.info.renderer;
return getSchemaTpl('tabs', [ return getSchemaTpl('tabs', [
{ {
title: '常规', title: '属性',
body: getSchemaTpl('collapseGroup', [
{
title: '基本',
body: [ body: [
getSchemaTpl('api', { getSchemaTpl('apiControl', {
label: '日志数据源', required: true,
name: 'source' name: 'source',
}) renderLabel: true,
label: tipedLabel('数据源', `返回日志信息的服务,后端需要通过流的方式返回结果。
<a target="_blank" href="https://baidu.github.io/amis/zh-CN/components/log#%E5%90%8E%E7%AB%AF%E5%AE%9E%E7%8E%B0%E5%8F%82%E8%80%83"></a>`)
}),
{
type: 'input-text',
label: tipedLabel('文本编码', '返回内容的字符编码,例如 UTF-8、ISO-8859-2、KOI8-R、GBK等等。默认UTF-8'),
name: 'encoding'
},
getSchemaTpl('placeholder', {
label: '加载提示',
placeholder: '加载中'
}),
{
type: 'switch',
label: tipedLabel('跟随底部', '自动滚动到底部,方便查看最新日志内容'),
name: 'autoScroll',
value: true,
inputClassName: 'is-inline'
},
{
label: tipedLabel('操作', '可在日志顶部添加以下操作按钮'),
type: 'checkboxes',
name: 'operation',
inline: false,
options: [
{
label: '停止',
value: 'stop'
},
{
label: '刷新',
value: 'restart'
},
{
label: '清空',
value: 'clear'
},
{
label: '隐藏行号',
value: 'showLineNumber'
},
{
label: '查询',
value: 'filter'
}
]
}
] ]
}, },
{ {
title: '外观', title: '性能优化',
body: [getSchemaTpl('className')] body: [
{
type: 'input-number',
label: tipedLabel('每行高度', `设置每行高度,这时就会默认启用虚拟渲染,避免渲染卡顿。
<ul><li></li>
<li></li></ul>
`),
name: 'rowHeight',
min: 1
}, },
{ {
title: '显隐', type: 'input-number',
body: [getSchemaTpl('ref'), getSchemaTpl('visible')] label: tipedLabel('显示行数', `限制最大显示行数,避免渲染卡顿,默认不限制。
<ul><li></li>
<li></li></ul>
`),
name: 'maxLength',
min: 1
}
]
},
getSchemaTpl('status', {isFormItem: false})
])
},
{
title: '外观',
body: getSchemaTpl('collapseGroup', [
{
title: '基本',
body: [
{
type: 'input-number',
label: tipedLabel('高度', '展示区域高度'),
name: 'height',
min: 1
}
]
},
getSchemaTpl('style:classNames', {
isFormItem: false
})
])
} }
]); ]);
}; };

View File

@ -1,7 +1,15 @@
import {registerEditorPlugin} from 'amis-editor-core'; import {
import {BaseEventContext, BasePlugin} from 'amis-editor-core'; registerEditorPlugin,
import {defaultValue, getSchemaTpl} from 'amis-editor-core'; BaseEventContext,
import {isObject} from 'amis-editor-core'; BasePlugin,
defaultValue,
getSchemaTpl,
diff,
JSONPipeOut,
BasicToolbarItem,
ContextMenuEventContext,
ContextMenuItem
} from 'amis-editor-core';
export class MappingPlugin extends BasePlugin { export class MappingPlugin extends BasePlugin {
// 关联渲染器名字 // 关联渲染器名字
@ -21,12 +29,15 @@ export class MappingPlugin extends BasePlugin {
type: 'mapping', type: 'mapping',
value: 2, value: 2,
map: { map: {
0: '<span class="label label-info">一</span>', 1: '开心',
1: '<span class="label label-success">二</span>', 2: '愤怒',
2: '<span class="label label-danger">三</span>', 3: '伤心',
3: '<span class="label label-warning">四</span>', 4: '冷漠',
4: '<span class="label label-primary">五</span>', '*': '一般'
'*': '<span class="label label-default">-</span>' },
itemSchema: {
type: 'tag',
label: '${item}'
} }
}; };
previewSchema = { previewSchema = {
@ -34,117 +45,158 @@ export class MappingPlugin extends BasePlugin {
}; };
panelTitle = '映射'; panelTitle = '映射';
panelJustify = true;
panelBodyCreator = (context: BaseEventContext) => { panelBodyCreator = (context: BaseEventContext) => {
const isUnderField = /\/field\/\w+$/.test(context.path as string); const isUnderField = /\/field\/\w+$/.test(context.path as string);
return [ return [
getSchemaTpl('tabs', [ getSchemaTpl('tabs', [
{ {
title: '常规', title: '属性',
body: getSchemaTpl('collapseGroup', [
{
title: '基本',
body: [ body: [
isUnderField isUnderField
? { ? {
type: 'tpl', type: 'tpl',
inline: false, inline: false,
className: 'text-info text-sm', className: 'text-info text-sm',
tpl: '<p>当前为字段内容节点配置,选择上层还有更多配置</p>' tpl: '<p>当前为字段内容节点配置,选择上层还有更多配置</p>'
} }
: null, : null,
{ {
type: 'ae-mapSourceControl',
label: '映射表', label: '映射表',
type: 'combo', mode: 'normal',
scaffold: { name: 'source'
key: 'key-{index}',
value: 'value-{index}'
}, },
required: true,
name: 'map',
descriptionClassName: 'help-block text-xs m-b-none',
description:
'<p>当值命中左侧 Key 时,展示右侧内容,当没有命中时,默认实现 Key 为 <code>*</code>的内容</div>(请确保key值唯一)',
multiple: true,
pipeIn: (value: any) => {
if (!isObject(value)) {
return [
{ {
key: '*', type: 'ae-switch-more',
value: '通配值' mode: 'normal',
} label: '自定义显示模板',
]; bulk: false,
} name: 'itemSchema',
formType: 'extend',
let arr: Array<any> = []; form: {
body: [
Object.keys(value).forEach(key => {
arr.push({
key: key || '',
value:
typeof value[key] === 'string'
? value[key]
: JSON.stringify(value[key])
});
});
return arr;
},
pipeOut: (value: any) => {
if (!Array.isArray(value)) {
return value;
}
let obj: any = {};
value.forEach((item: any, idx: number) => {
let key: string = item.key || '';
let value: any = item.value;
if (key === 'key-{index}' && value === 'value-{index}') {
key = key.replace('-{index}', `${idx}`);
value = value.replace('-{index}', `${idx}`);
}
try {
value = JSON.parse(value);
} catch (e) {}
obj[key] = value;
});
return obj;
},
items: [
{ {
placeholder: 'Key', type: 'button',
type: 'input-text', level: 'primary',
unique: true, size: 'sm',
name: 'key', block: true,
required: true, onClick: this.editDetail.bind(this, context.id),
columnClassName: 'w-xs' label: '配置显示模板'
},
{
placeholder: '内容',
type: 'input-text',
name: 'value'
} }
] ]
}, },
pipeIn: (value: any) => {
{ return value !== undefined;
name: 'placeholder', },
type: 'input-text', pipeOut: (value: any, originValue: any, data: any) => {
if (value === true) {
return {
type: 'tag',
label: `\${${data.labelField || 'item'} | default: "-"}`
};
}
return value ? value : undefined;
}
},
getSchemaTpl('valueFormula', {
pipeOut: (value: any) => {
return value == null || value === '' ? undefined : value;
}
}),
getSchemaTpl('placeholder', {
pipeIn: defaultValue('-'), pipeIn: defaultValue('-'),
label: '占位符' label: '占位符'
} })
] ]
}, },
getSchemaTpl('status')
])
},
{ {
title: '外观', title: '外观',
body: [getSchemaTpl('className')] body: getSchemaTpl('collapseGroup', [
},
{ {
title: '显隐', title: 'CSS类名',
body: [getSchemaTpl('ref'), getSchemaTpl('visible')] body: [
getSchemaTpl('className', {
label: '外层'
})
]
}
])
} }
]) ])
]; ];
}; };
filterProps(props: any) {
// 禁止选中子节点
props = JSONPipeOut(props);
return props;
}
buildEditorToolbar(
{id, info, schema}: BaseEventContext,
toolbars: Array<BasicToolbarItem>
) {
if (info.renderer.name === 'mapping') {
toolbars.push({
icon: 'fa fa-expand',
order: 100,
tooltip: '配置显示模板',
onClick: this.editDetail.bind(this, id)
});
}
}
buildEditorContextMenu(
{id, schema, region, info, selections}: ContextMenuEventContext,
menus: Array<ContextMenuItem>
) {
if (selections.length || info?.plugin !== this) {
return;
}
if (info.renderer.name === 'mapping') {
menus.push('|', {
label: '配置显示模板',
onSelect: this.editDetail.bind(this, id)
});
}
}
editDetail(id: string) {
const manager = this.manager;
const store = manager.store;
const node = store.getNodeById(id);
const value = store.getValueOf(id);
node &&
value &&
this.manager.openSubEditor({
title: '配置显示模板',
value: value.itemSchema || {
type: 'tag',
label: `\${${value.labelField ?? 'item'}}`
},
slot: {
type: 'container',
body: '$$'
},
onChange: (newValue: any) => {
newValue = {...value, itemSchema: newValue};
manager.panelChangeValue(newValue, diff(value, newValue));
},
data: {
[value.labelField || 'label']: '假数据',
[value.valueField || 'value']: '假数据',
item: '假数据'
}
});
}
} }
registerEditorPlugin(MappingPlugin); registerEditorPlugin(MappingPlugin);

View File

@ -29,53 +29,58 @@ export class PlainPlugin extends BasePlugin {
}; };
panelTitle = '纯文本'; panelTitle = '纯文本';
panelJustify = true;
panelBodyCreator = (context: BaseEventContext) => { panelBodyCreator = (context: BaseEventContext) => {
const isTableCell = context.info.renderer.name === 'table-cell'; const isTableCell = context.info.renderer.name === 'table-cell';
return [
return getSchemaTpl('tabs', [ getSchemaTpl('tabs', [
{ {
title: '常规', title: '属性',
body: getSchemaTpl('collapseGroup', [
{
title: '基本',
body: [ body: [
{ {
label: '内容', label: '内容',
type: 'textarea', type: 'textarea',
mode: 'col',
pipeIn: (value: any, data: any) => value || (data && data.text), pipeIn: (value: any, data: any) => value || (data && data.text),
name: 'tpl', name: 'tpl',
description: description:
'如果当前字段有值,请不要设置,否则覆盖。支持使用 <code>\\${xxx}</code> 来获取变量,或者用 lodash.template 语法来写模板逻辑。<a target="_blank" href="/amis/zh-CN/docs/concepts/template">详情</a>' '如果当前字段有值,请不要设置,否则覆盖。支持使用 <code>\\${xxx}</code> 来获取变量,或者用 lodash.template 语法来写模板逻辑。<a target="_blank" href="/amis/zh-CN/docs/concepts/template">详情</a>'
}, },
getSchemaTpl('placeholder', {
{ pipeIn: defaultValue('-'),
name: 'placeholder', label: '占位符'
label: '占位符', })
type: 'input-text',
pipeIn: defaultValue('-')
}
] ]
}, },
isTableCell ? null : getSchemaTpl('status')
isTableCell ])
? null },
: { isTableCell ? null : {
title: '外观', title: '外观',
body: getSchemaTpl('collapseGroup', [
{
title: '基本',
body: [ body: [
getSchemaTpl('switch', { getSchemaTpl('switch', {
name: 'inline', name: 'inline',
label: '内联模式', label: '内联模式',
value: true value: true
}), })
getSchemaTpl('className')
] ]
}, },
{
isTableCell title: 'CSS类名',
? null body: [
: { getSchemaTpl('className')
title: '显隐', ]
body: [getSchemaTpl('ref'), getSchemaTpl('visible')]
} }
]); ])
}
])
];
}; };
} }

View File

@ -333,13 +333,15 @@ export class TablePlugin extends BasePlugin {
description: '开启表格拖拽排序功能' description: '开启表格拖拽排序功能'
} }
]; ];
panelJustify = true;
panelBodyCreator = (context: BaseEventContext) => { panelBodyCreator = (context: BaseEventContext) => {
const isCRUDBody = context.schema.type === 'crud'; const isCRUDBody = context.schema.type === 'crud';
return getSchemaTpl('tabs', [ return getSchemaTpl('tabs', [
{ {
title: '常规', title: '属性',
body: getSchemaTpl('collapseGroup', [
{
title: '基本',
body: [ body: [
{ {
name: 'title', name: 'title',
@ -364,12 +366,6 @@ export class TablePlugin extends BasePlugin {
placeholder: '设置列数', placeholder: '设置列数',
description: description:
'设置从左到右多少列内启用自动合并单元格,根据字段值是否相同来决定是否合并。' '设置从左到右多少列内启用自动合并单元格,根据字段值是否相同来决定是否合并。'
},
isCRUDBody
? null
: {
type: 'divider'
} }
// { // {
@ -404,8 +400,14 @@ export class TablePlugin extends BasePlugin {
// } // }
] ]
}, },
getSchemaTpl('status')
])
},
{ {
title: '外观', title: '外观',
body: getSchemaTpl('collapseGroup', [
{
title: '基本',
body: [ body: [
{ {
name: 'columnsTogglable', name: 'columnsTogglable',
@ -498,35 +500,38 @@ export class TablePlugin extends BasePlugin {
type: 'input-text', type: 'input-text',
label: '行高亮规则', label: '行高亮规则',
placeholder: `支持模板语法,如 <%= data.id % 2 ? 'bg-success' : '' %>` placeholder: `支持模板语法,如 <%= data.id % 2 ? 'bg-success' : '' %>`
}
]
}, },
{
title: 'CSS类名',
body: [
getSchemaTpl('className', { getSchemaTpl('className', {
label: '外层 CSS 类名' label: '外层'
}), }),
getSchemaTpl('className', { getSchemaTpl('className', {
name: 'tableClassName', name: 'tableClassName',
label: '表格 CSS 类名' label: '表格'
}), }),
getSchemaTpl('className', { getSchemaTpl('className', {
name: 'headerClassName', name: 'headerClassName',
label: '顶部外层 CSS 类名' label: '顶部外层'
}), }),
getSchemaTpl('className', { getSchemaTpl('className', {
name: 'footerClassName', name: 'footerClassName',
label: '底部外层 CSS 类名' label: '底部外层'
}), }),
getSchemaTpl('className', { getSchemaTpl('className', {
name: 'toolbarClassName', name: 'toolbarClassName',
label: '工具栏 CSS 类名' label: '工具栏'
}) })
] ]
}, }
{ ])
title: '显隐',
body: [getSchemaTpl('ref'), getSchemaTpl('visible')]
}, },
isCRUDBody isCRUDBody
? null ? null

View File

@ -0,0 +1,127 @@
import {registerEditorPlugin} from 'amis-editor-core';
import {BaseEventContext, BasePlugin} from 'amis-editor-core';
import {undefinedPipeOut, getSchemaTpl} from 'amis-editor-core';
const presetColors = [
'#2468f2',
'#b8babf',
'#528eff',
'#30bf13',
'#f33e3e',
'#ff9326',
'#fff',
'#000',
]
export class TagPlugin extends BasePlugin {
// 关联渲染器名字
rendererName = 'tag';
$schema = '/schemas/TagSchema.json';
// 组件名称
name = '标签';
isBaseComponent = true;
icon = 'fa fa-tag';
pluginIcon = 'tag-plugin';
description = '用于标记和选择的标签';
docLink = '/amis/zh-CN/components/tag';
tags = ['展示'];
previewSchema = {
type: 'tag',
label: '普通标签',
color: 'processing'
};
scaffold: any = {
type: 'tag',
label: '普通标签',
color: 'processing'
};
panelTitle = '标签';
panelJustify = true;
panelBodyCreator = (context: BaseEventContext) => {
return getSchemaTpl('tabs', [
{
title: '属性',
body: getSchemaTpl('collapseGroup', [
{
title: '基本',
body: [
getSchemaTpl('label'),
{
type: 'button-group-select',
label: '模式',
name: 'displayMode',
value: 'normal',
size: 'md',
options: [
{
label: '普通',
value:'normal'
},
{
label: '圆角',
value:'rounded'
},
{
label: '状态',
value:'status'
}
]
},
getSchemaTpl('icon', {
visibleOn: 'data.displayMode === "status"',
label: '前置图标'
})
]
},
getSchemaTpl('status')
])
},
{
title: '外观',
body: getSchemaTpl('collapseGroup', [
{
title: '颜色',
body: [
{
type:'input-color',
label: '主题',
name: 'color',
presetColors,
pipeOut: undefinedPipeOut
},
{
type:'input-color',
label: '背景色',
name: 'style.backgroundColor',
presetColors,
pipeOut: undefinedPipeOut
},
{
type:'input-color',
label: '边框',
name: 'style.borderColor',
presetColors,
pipeOut: undefinedPipeOut
},
{
type:'input-color',
label: '文字',
name: 'style.color',
presetColors,
pipeOut: undefinedPipeOut
}
]
},
getSchemaTpl('style:classNames', {
isFormItem: false
})
])
}
]);
};
}
registerEditorPlugin(TagPlugin);

View File

@ -22,11 +22,15 @@ export class TimePlugin extends DatePlugin {
format: 'HH:mm:ss', format: 'HH:mm:ss',
value: Math.round(Date.now() / 1000) value: Math.round(Date.now() / 1000)
}; };
panelJustify = true;
panelBodyCreator = (context: BaseEventContext) => { panelBodyCreator = (context: BaseEventContext) => {
return [ return [
getSchemaTpl('tabs', [ getSchemaTpl('tabs', [
{ {
title: '常规', title: '属性',
body: getSchemaTpl('collapseGroup', [
{
title: '基本',
body: [ body: [
{ {
type: 'input-time', type: 'input-time',
@ -49,22 +53,16 @@ export class TimePlugin extends DatePlugin {
description: '请参考 moment 中的格式用法。', description: '请参考 moment 中的格式用法。',
pipeIn: defaultValue('X') pipeIn: defaultValue('X')
}, },
{ getSchemaTpl('placeholder', {
name: 'placeholder',
type: 'input-text',
pipeIn: defaultValue('-'), pipeIn: defaultValue('-'),
label: '占位符' label: '占位符'
} })
] ]
}, },
{ getSchemaTpl('status')
title: '外观', ])
body: [getSchemaTpl('className')]
}, },
{ getSchemaTpl('onlyClassNameTab')
title: '显隐',
body: [getSchemaTpl('ref'), getSchemaTpl('visible')]
}
]) ])
]; ];
}; };

View File

@ -985,7 +985,8 @@ export default class APIControl extends React.Component<
labelField = 'label', labelField = 'label',
useMobileUI, useMobileUI,
popOverContainer, popOverContainer,
env env,
renderLabel
} = this.props; } = this.props;
let {apiStr, selectedItem, loading} = this.state; let {apiStr, selectedItem, loading} = this.state;
selectedItem = selectedItem =
@ -1003,7 +1004,7 @@ export default class APIControl extends React.Component<
}) })
) : ( ) : (
<> <>
{this.renderHeader()} {!renderLabel && this.renderHeader()}
<div className="ae-ApiControl-content" key="content"> <div className="ae-ApiControl-content" key="content">
<div className={cx('ae-ApiControl-input')}> <div className={cx('ae-ApiControl-input')}>

View File

@ -0,0 +1,381 @@
/**
* @file mapping
*/
import React from 'react';
import cx from 'classnames';
import {FormItem} from 'amis';
import {autobind, getSchemaTpl, tipedLabel} from 'amis-editor-core';
import {FormControlProps, isObject} from 'amis-core';
import {SchemaApi} from 'amis/lib/Schema';
import debounce from 'lodash/debounce';
enum MapType {
CUSTOM = 'custom',
API = 'api'
}
export interface MapSourceControlProps extends FormControlProps {
className?: string;
}
export interface MapSourceControlState {
map: Object | Array<Object>;
source: SchemaApi;
labelField?: string;
valueField?: string;
mapType: MapType;
}
export default class MapSourceControl extends React.Component<
MapSourceControlProps,
MapSourceControlState
> {
$comp: string; // 记录一下路径,不再从外部同步内部,只从内部同步外部
constructor(props: MapSourceControlProps) {
super(props);
let mapType: MapType = MapType.CUSTOM;
if (props.data.hasOwnProperty('source') && props.data.source) {
mapType = MapType.API;
}
this.state = {
map: props.data.map,
source: props.data.source,
labelField: props.data.labelField,
valueField: props.data.valueField,
mapType
};
}
/**
* map字段的统一出口
*/
onChange() {
let {mapType, source, map, labelField, valueField} = this.state;
const {onBulkChange} = this.props;
labelField = labelField === '' ? undefined : labelField;
valueField = valueField === '' ? undefined : valueField;
if (mapType === MapType.CUSTOM) {
onBulkChange && onBulkChange({
map,
source: undefined,
labelField,
valueField
});
return;
}
if (mapType === MapType.API) {
onBulkChange && onBulkChange({
source,
map: undefined,
labelField,
valueField
});
return;
}
}
/**
*
*/
@autobind
handleMapTypeChange(mapType: MapType) {
this.setState({
mapType,
labelField: undefined,
valueField: undefined
}, this.onChange);
}
renderHeader() {
const {
render,
label,
labelRemark,
useMobileUI,
env,
popOverContainer,
} = this.props;
const classPrefix = env?.theme?.classPrefix;
const {mapType} = this.state;
const optionSourceList = (
[
{
label: '自定义选项',
value: MapType.CUSTOM
},
{
label: '外部接口',
value: MapType.API
},
] as Array<{
label: string;
value: MapType;
}>
).map(item => ({
...item,
onClick: () => this.handleMapTypeChange(item.value)
}));
return (
<header className="ae-OptionControl-header">
<label className={cx(`${classPrefix}Form-label`)} style={{marginBottom:0}}>
{label || ''}
{labelRemark
? render('label-remark', {
type: 'remark',
icon: labelRemark.icon || 'warning-mark',
tooltip: labelRemark,
className: cx(`Form-lableRemark`, labelRemark?.className),
useMobileUI,
container: popOverContainer
? popOverContainer
: env && env.getModalContainer
? env.getModalContainer
: undefined
})
: null}
</label>
<div>
{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 === mapType)!
.label
}
}
)}
</div>
</header>
);
}
@autobind
handleMapChange(map: any) {
this.setState({map}, this.onChange);
}
@autobind
handleAPIChange(source: SchemaApi) {
this.setState({source}, this.onChange);
}
@autobind
handleLabelFieldChange(labelField: string) {
this.setState({labelField}, this.onChange);
}
@autobind
handleValueFieldChange(valueField: string) {
this.setState({valueField}, this.onChange);
}
renderOtherFields() {
return [{
label: tipedLabel(
'值字段',
'映射表是数组对象且对象有多个key时用来匹配值的字段'
),
type: 'input-text',
name: 'valueField',
placeholder: '匹配值的字段',
onChange: this.handleValueFieldChange,
},
{
label: tipedLabel(
'显示字段',
'映射表是数组对象时,用作显示的字段,显示多字段请使用自定义显示模板'
),
type: 'input-text',
name: 'labelField',
placeholder: '用作显示的字段',
onChange: this.handleLabelFieldChange
}]
}
renderApiPanel() {
const {render} = this.props;
const {mapType, source, labelField, valueField} = this.state;
if (mapType === MapType.CUSTOM) {
return null;
}
return render(
'api',
getSchemaTpl('apiControl', {
label: '接口',
name: 'source',
mode: 'normal',
className: 'ae-ExtendMore',
visibleOn: 'data.autoComplete !== false',
value: source,
onChange: this.handleAPIChange,
sourceType: mapType,
footer: this.renderOtherFields()
})
);
}
renderObjectMap() {
const {render} = this.props;
return render('objectMap', getSchemaTpl('combo-container', {
label: '',
type: 'combo',
mode: 'normal',
scaffold: {
key: 'key-{index}',
value: 'value-{index}'
},
required: true,
name: 'map',
descriptionClassName: 'help-block text-xs m-b-none',
description:
'<p>当值命中左侧 Key 时,展示右侧内容<br />当没有命中时,默认展示 Key 为 <code>*</code>的内容</div><br />(请确保key值唯一)',
multiple: true,
pipeIn: (value: any) => {
if (!isObject(value)) {
return [
{
key: 'key0',
value: 'value1'
}
];
}
let arr: Array<any> = [];
Object.keys(value).forEach(key => {
arr.push({
key: key || '',
value:
typeof value[key] === 'string'
? value[key]
: JSON.stringify(value[key])
});
});
return arr;
},
pipeOut: (value: any) => {
if (!Array.isArray(value)) {
return value;
}
let obj: any = {};
value.forEach((item: any, idx: number) => {
let key: string = item.key || '';
let value: any = item.value;
if (key === 'key-{index}' && value === 'value-{index}') {
key = key.replace('-{index}', `${idx}`);
value = value.replace('-{index}', `${idx}`);
}
try {
value = JSON.parse(value);
} catch (e) {}
obj[key] = value;
});
return obj;
},
onChange: (value: any) => {
this.handleMapChange(value || {'*': '通配值'});
},
items: [
{
placeholder: 'Key',
type: 'input-text',
unique: true,
name: 'key',
required: true,
columnClassName: 'w-xs'
},
{
placeholder: '内容',
type: 'input-text',
name: 'value'
}
]
}));
}
handleMapItemChange(index: number, item: any) {
const {map = []} = this.state;
const newMap = (map as object[]).slice();
try {
item = JSON.parse(item);
} catch (e) {}
newMap.splice(index, 1, item);
this.handleMapChange(newMap);
}
renderArrayMap() {
const {render} = this.props;
return <div className='ae-ExtendMore'>
{render('arrayMap', [
{
type: 'json-editor',
name: 'map',
label: false,
placeholder: '请保持数组成员结构相同',
onChange: (value: any, ...args: any[]) => {
try {
const map = JSON.parse(value);
this.debounceMapChange(map)
}
catch (e) {
console.error();
}
}
},
...this.renderOtherFields()
])}
</div>;
}
debounceMapChange = debounce(this.handleMapChange, 250);
renderMap() {
const {map} = this.state;
if (map && Array.isArray(map)) {
return this.renderArrayMap();
}
return this.renderObjectMap();
}
render() {
const {mapType} = this.state;
const {className} = this.props;
return (
<div className={cx('ae-OptionControl', className)}>
{this.renderHeader()}
{mapType === MapType.CUSTOM ? this.renderMap() : this.renderApiPanel()}
</div>
);
}
}
@FormItem({
type: 'ae-mapSourceControl',
renderLabel: false
})
export class MapSourceControlRenderer extends MapSourceControl {}

View File

@ -1200,7 +1200,9 @@ export const getEventControlConfig = (
} }
} }
if (['show', 'hidden', 'enabled', 'disabled'].includes(action.actionType)) { if (
['show', 'hidden', 'enabled', 'disabled'].includes(action.actionType)
) {
// 兼容老逻辑初始化actionType // 兼容老逻辑初始化actionType
config.__statusType = action.actionType; config.__statusType = action.actionType;
config.__actionType = 'static'; config.__actionType = 'static';
@ -1263,6 +1265,17 @@ export const getEventControlConfig = (
delete config.data; delete config.data;
// 处理下 combo - addItem 的初始化
if (
action.actionType === 'addItem' &&
typeof action.args?.item === 'object'
) {
config.args = {
...config.args,
item: objectToComboArray(action.args?.item)
};
}
// 还原args为可视化配置结构(args + addOnArgs) // 还原args为可视化配置结构(args + addOnArgs)
if (config.args) { if (config.args) {
if (innerArgs) { if (innerArgs) {
@ -1434,10 +1447,11 @@ export const getEventControlConfig = (
value: action.__actionExpression value: action.__actionExpression
} }
: undefined; : undefined;
action.actionType === 'static' && (action.actionType = config.__statusType); action.actionType === 'static' &&
(action.actionType = config.__statusType);
delete action.__actionExpression; delete action.__actionExpression;
delete action.__statusType; delete action.__statusType;
}; }
delete action.config; delete action.config;

View File

@ -664,6 +664,20 @@ setSchemaTpl('className', (schema: any) => {
}; };
}); });
setSchemaTpl('onlyClassNameTab', (label = '外层') => {
return {
title: '外观',
body: getSchemaTpl('collapseGroup', [
{
title: 'CSS类名',
body: [
getSchemaTpl('className', {label})
]
}
])
}
});
/** /**
* combo * combo
*/ */