merge pre-release

Change-Id: Icc0954d0d7f8fc9f9a1577da20cad732e7b7be60
This commit is contained in:
yangwei9012 2022-07-27 17:56:04 +08:00
commit 83b937f5f7
61 changed files with 1523 additions and 1184 deletions

View File

@ -1,6 +1,6 @@
{
"name": "amis-editor",
"version": "5.2.0-beta.21",
"version": "5.2.0-beta.26",
"description": "amis 可视化编辑器",
"main": "lib/index.js",
"module": "esm/index.js",
@ -53,10 +53,10 @@
"@types/sortablejs": "^1.10.7",
"@types/tinycolor2": "^1.4.3",
"ajv": "^8.8.2",
"amis": "^2.0.0-rc.16",
"amis-core": "^2.0.0-rc.16",
"amis-formula": "^2.0.0-rc.15",
"amis-ui": "^2.0.0-rc.16",
"amis": "^2.0.2",
"amis-core": "^2.0.2",
"amis-formula": "^2.0.2",
"amis-ui": "^2.0.2",
"axios": "0.21.1",
"concurrently": "^6.2.0",
"css-loader": "^6.2.0",

View File

@ -3,13 +3,9 @@
*/
import flatten from 'lodash/flatten';
import {getEventControlConfig} from '../util';
import {
getSchemaTpl,
isObject,
BaseEventContext,
tipedLabel
} from 'amis-editor-core';
import {getEventControlConfig} from '../renderer/event-control/helper';
import {getSchemaTpl, isObject, tipedLabel} from 'amis-editor-core';
import type {BaseEventContext} from 'amis-editor-core';
// 默认动作
export const BUTTON_DEFAULT_ACTION = {

View File

@ -173,9 +173,8 @@ export class AvatarPlugin extends BasePlugin {
visibleOn: 'data.showtype === "text"'
}
]
}
// TODO 临时关闭,目前角标功能还没完善,待完善后再开启
// getSchemaTpl('badge')
},
getSchemaTpl('badge')
]
},
getSchemaTpl('status')

View File

@ -9,7 +9,7 @@ import {
} from 'amis-editor-core';
import {defaultValue, getSchemaTpl} from 'amis-editor-core';
import {BUTTON_DEFAULT_ACTION} from '../component/BaseControl';
import {getEventControlConfig} from '../util';
import {getEventControlConfig} from '../renderer/event-control/helper';
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
import {SchemaObject} from 'amis/lib/Schema';
import {getOldActionSchema} from '../renderer/event-control/helper';
@ -96,6 +96,7 @@ export class ButtonPlugin extends BasePlugin {
type: 'button-group-select',
name: 'type',
size: 'sm',
visibleOn: 'type === "submit" || type === "reset" ',
options: [
{
label: '按钮',

View File

@ -392,7 +392,7 @@ export class CRUDPlugin extends BasePlugin {
valueSchema.bulkActions = [];
/** 统一api格式 */
valueSchema.api = normalizeApi(valueSchema.api);
valueSchema.api = typeof valueSchema.api === 'string' ? valueSchema.api : normalizeApi(valueSchema.api);
hasFeatures &&
features.forEach((item: string) => {
if (itemBtns.includes(item)) {

View File

@ -14,7 +14,7 @@ import {
} from 'amis-editor-core';
import {defaultValue, getSchemaTpl} from 'amis-editor-core';
import {diff, JSONPipeOut, repeatArray} from 'amis-editor-core';
import {getEventControlConfig} from '../util';
import {getEventControlConfig} from '../renderer/event-control/helper';
export class CardsPlugin extends BasePlugin {
// 关联渲染器名字
@ -66,7 +66,7 @@ export class CardsPlugin extends BasePlugin {
panelBodyCreator = (context: BaseEventContext) => {
const isCRUDBody = ['crud', 'crud2'].includes(context.schema.type);
return getSchemaTpl('tabs', [
{
title: '属性',
@ -101,15 +101,15 @@ export class CardsPlugin extends BasePlugin {
name: 'source',
type: 'input-text',
label: tipedLabel('数据', '可绑定当前页面数据'),
pipeIn: defaultValue('${items}'),
pipeIn: defaultValue('${items}')
// visible: !isCRUDBody
},
{
name: 'valueField',
type: 'input-text',
label: '值字段',
label: '值字段'
// visible: isInForm && !isCRUDBody
},
}
]
},
getSchemaTpl('status', {
@ -155,10 +155,12 @@ export class CardsPlugin extends BasePlugin {
label: '内容'
}),
getSchemaTpl('className', {
pipeIn: defaultValue('Grid-col--sm6 Grid-col--md4 Grid-col--lg3'),
pipeIn: defaultValue(
'Grid-col--sm6 Grid-col--md4 Grid-col--lg3'
),
name: 'itemClassName',
label: '卡片'
}),
})
]
})
])
@ -249,26 +251,30 @@ export class CardsPlugin extends BasePlugin {
let value = Array.isArray(props.value)
? props.value
: typeof props.source === 'string'
? resolveVariable(props.source, data)
: resolveVariable('items', data);
value = !Array.isArray(value) ? [] : value;
if (value.length < 5) {
const mockedData: any = value.length ? value[0] : {
id: 666,
title: '假数据',
description: '假数据',
a: '假数据',
b: '假数据'
};
? resolveVariable(props.source, data)
: resolveVariable('items', data);
value = value.concat(repeatArray(mockedData, 3).map((item, index) => ({
...item,
id: index + 1
})));
value = !Array.isArray(value) ? [] : value;
if (value.length < 5) {
const mockedData: any = value.length
? value[0]
: {
id: 666,
title: '假数据',
description: '假数据',
a: '假数据',
b: '假数据'
};
value = value.concat(
repeatArray(mockedData, 3).map((item, index) => ({
...item,
id: index + 1
}))
);
}
value = value.slice(0, 4);
return {
@ -278,12 +284,7 @@ export class CardsPlugin extends BasePlugin {
}
overrides = {
renderCard(
this: any,
index: number,
card: any,
...rest: any[]
) {
renderCard(this: any, index: number, card: any, ...rest: any[]) {
return this.super(
index,
// 使第一个卡片元素可以选择并编辑schema
@ -291,7 +292,7 @@ export class CardsPlugin extends BasePlugin {
...rest
);
}
}
};
getRendererInfo(
context: RendererInfoResolveEventContext

View File

@ -8,7 +8,7 @@ import {
} from 'amis-editor-core';
import {defaultValue, getSchemaTpl} from 'amis-editor-core';
import {noop} from 'amis-editor-core';
import {getEventControlConfig} from '../util';
import {getEventControlConfig} from '../renderer/event-control/helper';
export class DialogPlugin extends BasePlugin {
// 关联渲染器名字

View File

@ -7,7 +7,7 @@ import {
} from 'amis-editor-core';
import {defaultValue, getSchemaTpl} from 'amis-editor-core';
import {noop} from 'amis-editor-core';
import {getEventControlConfig} from '../util';
import {getEventControlConfig} from '../renderer/event-control/helper';
import {InlineModal} from './Dialog';
export class DrawerPlugin extends BasePlugin {

View File

@ -7,7 +7,7 @@ import {
tipedLabel
} from 'amis-editor-core';
import {getSchemaTpl, defaultValue} from 'amis-editor-core';
import {getEventControlConfig} from '../../util';
import {getEventControlConfig} from '../../renderer/event-control/helper';
export class ButtonGroupControlPlugin extends BasePlugin {
// 关联渲染器名字

View File

@ -12,7 +12,7 @@ import {
defaultValue
} from 'amis-editor-core';
import {ValidatorTag} from '../../validator';
import {getEventControlConfig} from '../../util';
import {getEventControlConfig} from '../../renderer/event-control/helper';
export class ChainedSelectControlPlugin extends BasePlugin {
// 关联渲染器名字

View File

@ -14,9 +14,11 @@ import {
tipedLabel
} from 'amis-editor-core';
import {ValidatorTag} from '../../validator';
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
import {getEventControlConfig} from '../../util';
import {
RendererPluginAction,
RendererPluginEvent
} from 'amis-editor-core';
import {getEventControlConfig} from '../../renderer/event-control/helper';
setSchemaTpl('option', {
name: 'option',

View File

@ -18,7 +18,7 @@ import {
RendererPluginAction,
RendererPluginEvent
} from 'amis-editor-core';
import {getEventControlConfig} from '../../util';
import {getEventControlConfig} from '../../renderer/event-control/helper';
export class CheckboxesControlPlugin extends BasePlugin {
// 关联渲染器名字

View File

@ -9,7 +9,7 @@ import {
RendererPluginEvent,
RendererPluginAction
} from 'amis-editor-core';
import {getEventControlConfig} from '../../util';
import {getEventControlConfig} from '../../renderer/event-control/helper';
export class CodeEditorControlPlugin extends BasePlugin {
// 关联渲染器名字

View File

@ -10,7 +10,7 @@ import {BasePlugin} from 'amis-editor-core';
import type {BaseEventContext} from 'amis-editor-core';
import {ValidatorTag} from '../../validator';
import {getEventControlConfig} from '../../util';
import {getEventControlConfig} from '../../renderer/event-control/helper';
import {
RendererPluginEvent,
RendererPluginAction

View File

@ -18,7 +18,7 @@ import {
jsonToJsonSchema,
EditorNodeType
} from 'amis-editor-core';
import {getEventControlConfig} from '../../util';
import {getEventControlConfig} from '../../renderer/event-control/helper';
import {FormSchema} from 'amis/lib/Schema';
import {clone, cloneDeep, flatten} from 'lodash';

View File

@ -1,8 +1,8 @@
import {registerEditorPlugin, tipedLabel} from 'amis-editor-core';
import {getSchemaTpl} from 'amis-editor-core';
import {registerEditorPlugin} from 'amis-editor-core';
import {defaultValue, getSchemaTpl, tipedLabel} from 'amis-editor-core';
import {ValidatorTag} from '../../validator';
import {BasePlugin, BaseEventContext} from 'amis-editor-core';
import {getEventControlConfig} from '../../util';
import {getEventControlConfig} from '../../renderer/event-control/helper';
import tinyColor from 'tinycolor2';
function convertColor(value: string[], format: string): string[];

View File

@ -3,8 +3,11 @@ import {defaultValue, getSchemaTpl} from 'amis-editor-core';
import {BasePlugin, BaseEventContext, tipedLabel} from 'amis-editor-core';
import {ValidatorTag} from '../../validator';
import {getEventControlConfig} from '../../util';
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
import {getEventControlConfig} from '../../renderer/event-control/helper';
import {
RendererPluginAction,
RendererPluginEvent
} from 'amis-editor-core';
const formatX = [
{

View File

@ -3,7 +3,7 @@ import {registerEditorPlugin} from 'amis-editor-core';
import {BasePlugin, BaseEventContext} from 'amis-editor-core';
import {ValidatorTag} from '../../validator';
import {getEventControlConfig} from '../../util';
import {getEventControlConfig} from '../../renderer/event-control/helper';
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
const DateType: {
@ -284,17 +284,26 @@ export class DateRangeControlPlugin extends BasePlugin {
label: tipedLabel('最大值', tipedLabelText)
}),
getSchemaTpl('formulaControl', {
getSchemaTpl('valueFormula', {
name: 'minDuration',
label: tipedLabel('最小跨度', '例如 2days'),
placeholder: '请输入最小跨度',
inputClassName: 'is-inline'
rendererSchema: {
...context?.schema,
value: context?.schema.minDuration,
type: 'input-text'
},
needDeleteProps: ['minDuration'], // 避免自我限制
label: tipedLabel('最小跨度', '例如 2days')
}),
getSchemaTpl('formulaControl', {
getSchemaTpl('valueFormula', {
name: 'maxDuration',
label: tipedLabel('最大跨度', '例如 1year'),
placeholder: '请输入最大跨度',
inputClassName: 'is-inline'
rendererSchema: {
...context?.schema,
value: context?.schema.maxDuration,
type: 'input-text'
},
needDeleteProps: ['maxDuration'], // 避免自我限制
label: tipedLabel('最大跨度', '例如 1year')
}),
getSchemaTpl('dateShortCutControl', {
mode: 'normal',
@ -322,7 +331,7 @@ export class DateRangeControlPlugin extends BasePlugin {
type: 'input-text',
name: 'endPlaceholder',
label: '后占位提示',
pipeIn: defaultValue('选择结束时间')
pipeIn: defaultValue('结束时间')
},
getSchemaTpl('autoFillApi')
]

View File

@ -2,7 +2,7 @@ import {defaultValue, getSchemaTpl, valuePipeOut} from 'amis-editor-core';
import {registerEditorPlugin, tipedLabel} from 'amis-editor-core';
import {BasePlugin, BaseEventContext} from 'amis-editor-core';
import {ValidatorTag} from '../../validator';
import {getEventControlConfig} from '../../util';
import {getEventControlConfig} from '../../renderer/event-control/helper';
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
export class FileControlPlugin extends BasePlugin {
@ -21,7 +21,11 @@ export class FileControlPlugin extends BasePlugin {
scaffold = {
type: 'input-file',
label: '文件上传',
name: 'file'
name: 'file',
receiver: {
url: 'object-upload://default',
method: 'post'
}
};
previewSchema: any = {
type: 'form',
@ -330,6 +334,15 @@ export class FileControlPlugin extends BasePlugin {
visibleOn:
'data.submitType === "asUpload" && data.uploadType === "fileReceptor" && !data.useChunk'
}),
{
type: 'input-text',
value: '',
name: 'accept',
label: tipedLabel(
'文件类型',
'请填入文件的后缀,多个类型用<code>,</code>隔开'
)
},
getSchemaTpl('fileUrl', {
name: 'templateUrl',
label: tipedLabel(

View File

@ -34,7 +34,6 @@ export class ImageControlPlugin extends BasePlugin {
}
]
};
notRenderFormZone = true;
// 事件定义
events: RendererPluginEvent[] = [

View File

@ -12,7 +12,7 @@ import {
} from 'amis-editor-core';
import {defaultValue, getSchemaTpl, tipedLabel} from 'amis-editor-core';
import {ValidatorTag} from '../../validator';
import {getEventControlConfig} from '../../util';
import {getEventControlConfig} from '../../renderer/event-control/helper';
export class NumberControlPlugin extends BasePlugin {
// 关联渲染器名字

View File

@ -3,7 +3,7 @@ import {defaultValue, getSchemaTpl, tipedLabel} from 'amis-editor-core';
import {registerEditorPlugin} from 'amis-editor-core';
import {BasePlugin, BaseEventContext} from 'amis-editor-core';
import {ValidatorTag} from '../../validator';
import {getEventControlConfig} from '../../util';
import {getEventControlConfig} from '../../renderer/event-control/helper';
export class RangeControlPlugin extends BasePlugin {
// 关联渲染器名字

View File

@ -7,8 +7,11 @@ import {
import {registerEditorPlugin} from 'amis-editor-core';
import {BasePlugin, BaseEventContext, tipedLabel} from 'amis-editor-core';
import {ValidatorTag} from '../../validator';
import {getEventControlConfig} from '../../util';
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
import {getEventControlConfig} from '../../renderer/event-control/helper';
import {
RendererPluginAction,
RendererPluginEvent
} from 'amis-editor-core';
export class RateControlPlugin extends BasePlugin {
// 关联渲染器名字

View File

@ -8,7 +8,7 @@ import {
} from 'amis-editor-core';
import {defaultValue, getSchemaTpl, tipedLabel} from 'amis-editor-core';
import {ValidatorTag} from '../../validator';
import {getEventControlConfig} from '../../util';
import {getEventControlConfig} from '../../renderer/event-control/helper';
const isText = 'data.type === "input-text"';
const isPassword = 'data.type === "input-password"';

View File

@ -3,8 +3,10 @@ import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
import {defaultValue, getSchemaTpl} from 'amis-editor-core';
import {registerEditorPlugin} from 'amis-editor-core';
import {BaseEventContext, BasePlugin} from 'amis-editor-core';
import {getEventControlConfig} from '../../util';
import {getArgsWrapper} from '../../renderer/event-control/helper';
import {
getArgsWrapper,
getEventControlConfig
} from '../../renderer/event-control/helper';
export class TreeControlPlugin extends BasePlugin {
// 关联渲染器名字

View File

@ -9,8 +9,11 @@ import {
tipedLabel
} from 'amis-editor-core';
import {ValidatorTag} from '../../validator';
import {getEventControlConfig} from '../../util';
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
import {getEventControlConfig} from '../../renderer/event-control/helper';
import {
RendererPluginAction,
RendererPluginEvent
} from 'amis-editor-core';
export class MatrixControlPlugin extends BasePlugin {
// 关联渲染器名字

View File

@ -12,7 +12,7 @@ import {
tipedLabel
} from 'amis-editor-core';
import {ValidatorTag} from '../../validator';
import {getEventControlConfig} from '../../util';
import {getEventControlConfig} from '../../renderer/event-control/helper';
export class NestedSelectControlPlugin extends BasePlugin {
// 关联渲染器名字
@ -242,7 +242,7 @@ export class NestedSelectControlPlugin extends BasePlugin {
},
{
type: 'container',
className: 'ae-ExtendMore',
className: 'ae-ExtendMore mb-3',
visibleOn: 'this.multiple',
body: [
{

View File

@ -3,8 +3,11 @@ import {registerEditorPlugin} from 'amis-editor-core';
import {BasePlugin, BaseEventContext} from 'amis-editor-core';
import {ValidatorTag} from '../../validator';
import {getEventControlConfig} from '../../util';
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
import {getEventControlConfig} from '../../renderer/event-control/helper';
import {
RendererPluginAction,
RendererPluginEvent
} from 'amis-editor-core';
export class RadiosControlPlugin extends BasePlugin {
// 关联渲染器名字

View File

@ -3,8 +3,11 @@ import {registerEditorPlugin} from 'amis-editor-core';
import {BasePlugin, BaseEventContext} from 'amis-editor-core';
import {ValidatorTag} from '../../validator';
import {getEventControlConfig} from '../../util';
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
import {getEventControlConfig} from '../../renderer/event-control/helper';
import {
RendererPluginAction,
RendererPluginEvent
} from 'amis-editor-core';
export class SelectControlPlugin extends BasePlugin {
// 关联渲染器名字
@ -205,7 +208,7 @@ export class SelectControlPlugin extends BasePlugin {
getSchemaTpl('clearable'),
getSchemaTpl('searchable'),
getSchemaTpl('multiple', {
popMore: [
body: [
getSchemaTpl('switch', {
label: '单行显示选中值',
name: 'valuesNoWrap'
@ -214,8 +217,7 @@ export class SelectControlPlugin extends BasePlugin {
}),
getSchemaTpl('checkAll'),
getSchemaTpl('valueFormula', {
rendererSchema: context?.schema,
visibleOn: 'this.options && this.options.length > 0'
rendererSchema: context?.schema
}),
getSchemaTpl('labelRemark'),
getSchemaTpl('remark'),

View File

@ -4,7 +4,7 @@ import {defaultValue, getSchemaTpl} from 'amis-editor-core';
import {registerEditorPlugin} from 'amis-editor-core';
import {BaseEventContext, BasePlugin} from 'amis-editor-core';
import {EditorNodeType} from 'amis-editor-core';
import {mockValue, tipedLabel} from 'amis-editor-core';
import {mockValue} from 'amis-editor-core';
export class StaticControlPlugin extends BasePlugin {
// 关联渲染器名字

View File

@ -2,8 +2,11 @@ import {getSchemaTpl, valuePipeOut} from 'amis-editor-core';
import {registerEditorPlugin, tipedLabel} from 'amis-editor-core';
import {BasePlugin, BaseEventContext} from 'amis-editor-core';
import {ValidatorTag} from '../../validator';
import {getEventControlConfig} from '../../util';
import type {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
import {getEventControlConfig} from '../../renderer/event-control/helper';
import type {
RendererPluginAction,
RendererPluginEvent
} from 'amis-editor-core';
export class SwitchControlPlugin extends BasePlugin {
// 关联渲染器名字

View File

@ -3,8 +3,11 @@ import {getSchemaTpl} from 'amis-editor-core';
import {registerEditorPlugin} from 'amis-editor-core';
import {BasePlugin, BaseEventContext} from 'amis-editor-core';
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
import {getEventControlConfig} from '../../util';
import {
RendererPluginAction,
RendererPluginEvent
} from 'amis-editor-core';
import {getEventControlConfig} from '../../renderer/event-control/helper';
export class TabsTransferPlugin extends BasePlugin {
// 关联渲染器名字

View File

@ -4,8 +4,11 @@ import {BasePlugin, tipedLabel} from 'amis-editor-core';
import type {BaseEventContext} from 'amis-editor-core';
import {ValidatorTag} from '../../validator';
import {getEventControlConfig} from '../../util';
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
import {getEventControlConfig} from '../../renderer/event-control/helper';
import {
RendererPluginAction,
RendererPluginEvent
} from 'amis-editor-core';
export class TextareaControlPlugin extends BasePlugin {
// 关联渲染器名字

View File

@ -1,8 +1,11 @@
import {getSchemaTpl} from 'amis-editor-core';
import {registerEditorPlugin} from 'amis-editor-core';
import {BasePlugin, BaseEventContext} from 'amis-editor-core';
import {getEventControlConfig} from '../../util';
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
import {getEventControlConfig} from '../../renderer/event-control/helper';
import {
RendererPluginAction,
RendererPluginEvent
} from 'amis-editor-core';
export class TransferPlugin extends BasePlugin {
// 关联渲染器名字

View File

@ -2,7 +2,7 @@ import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
import {defaultValue, getSchemaTpl} from 'amis-editor-core';
import {registerEditorPlugin} from 'amis-editor-core';
import {BaseEventContext, BasePlugin} from 'amis-editor-core';
import {getEventControlConfig} from '../../util';
import {getEventControlConfig} from '../../renderer/event-control/helper';
export class TreeSelectControlPlugin extends BasePlugin {
// 关联渲染器名字

View File

@ -2,9 +2,6 @@ import {registerEditorPlugin} from 'amis-editor-core';
import {BasePlugin, RegionConfig, RendererInfo} from 'amis-editor-core';
import {defaultValue, getSchemaTpl} from 'amis-editor-core';
import {tipedLabel} from 'amis-editor-core';
import {ValidatorTag} from '../validator';
import {getEventControlConfig} from '../util';
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
export class LinkPlugin extends BasePlugin {
// 关联渲染器名字

View File

@ -13,7 +13,7 @@ import {
} from 'amis-editor-core';
import {defaultValue, getSchemaTpl} from 'amis-editor-core';
import {diff, JSONPipeOut, repeatArray} from 'amis-editor-core';
import {getEventControlConfig} from '../util';
import {getEventControlConfig} from '../renderer/event-control/helper';
import {ListItemSchema} from 'amis/lib/renderers/List';
export class ListPlugin extends BasePlugin {

View File

@ -13,7 +13,7 @@ import {
} from 'amis-editor-core';
import {defaultValue, getSchemaTpl} from 'amis-editor-core';
import {VRenderer} from 'amis-editor-core';
import { getEventControlConfig } from '../util';
import {getEventControlConfig} from '../renderer/event-control/helper';
export class ListItemPlugin extends BasePlugin {
// 关联渲染器名字

View File

@ -2,7 +2,7 @@ import {ContainerWrapper} from 'amis-editor-core';
import {registerEditorPlugin} from 'amis-editor-core';
import {BaseEventContext, BasePlugin} from 'amis-editor-core';
import {getSchemaTpl} from 'amis-editor-core';
import {getEventControlConfig} from '../util';
import {getEventControlConfig} from '../renderer/event-control/helper';
import {
RendererPluginAction,
RendererPluginEvent

View File

@ -1,14 +1,10 @@
import {getEventControlConfig} from '../util';
import {
getSchemaTpl,
defaultValue,
tipedLabel,
BasePlugin,
RendererPluginEvent,
RegionConfig,
BaseEventContext,
registerEditorPlugin
} from 'amis-editor-core';
import {registerEditorPlugin} from 'amis-editor-core';
import {BasePlugin, RegionConfig, BaseEventContext, tipedLabel} from 'amis-editor-core';
import {ValidatorTag} from '../validator';
import {getEventControlConfig} from '../renderer/event-control/helper';
import {RendererPluginEvent} from 'amis-editor-core';
import {defaultValue, getSchemaTpl} from 'amis-editor-core';
export class PaginationPlugin extends BasePlugin {
// 关联渲染器名字

View File

@ -3,7 +3,7 @@ import {BaseEventContext, BasePlugin} from 'amis-editor-core';
import {defaultValue, getSchemaTpl} from 'amis-editor-core';
import {tipedLabel} from 'amis-editor-core';
import {ValidatorTag} from '../validator';
import {getEventControlConfig} from '../util';
import {getEventControlConfig} from '../renderer/event-control/helper';
export class ProgressPlugin extends BasePlugin {
// 关联渲染器名字

View File

@ -1,6 +1,6 @@
import {Button} from 'amis';
import React from 'react';
import {getEventControlConfig} from '../util';
import {getEventControlConfig} from '../renderer/event-control/helper';
import {
getSchemaTpl,

View File

@ -21,7 +21,7 @@ import {
RendererPluginAction,
RendererPluginEvent
} from 'amis-editor-core';
import {getEventControlConfig} from '../util';
import {getEventControlConfig} from '../renderer/event-control/helper';
import {SchemaObject} from 'amis/lib/Schema';
import {getArgsWrapper} from '../renderer/event-control/helper';

View File

@ -1,8 +1,5 @@
import {resolveVariable} from 'amis';
import {
RendererPluginAction,
RendererPluginEvent
} from 'amis-editor-core';
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
import {setVariable} from 'amis-core';
import {registerEditorPlugin, repeatArray} from 'amis-editor-core';
@ -21,8 +18,10 @@ import {defaultValue, getSchemaTpl} from 'amis-editor-core';
import {mockValue} from 'amis-editor-core';
import {EditorNodeType} from 'amis-editor-core';
import {SchemaObject} from 'amis/lib/Schema';
import {getEventControlConfig} from '../util';
import { getArgsWrapper } from '../renderer/event-control/helper';
import {
getArgsWrapper,
getEventControlConfig
} from '../renderer/event-control/helper';
export class TablePlugin extends BasePlugin {
// 关联渲染器名字

View File

@ -18,8 +18,10 @@ import {RegionWrapper as Region} from 'amis-editor-core';
import {Tab} from 'amis';
import {tipedLabel} from 'amis-editor-core';
import {ValidatorTag} from '../validator';
import {getEventControlConfig} from '../util';
import {getArgsWrapper} from '../renderer/event-control/helper';
import {
getArgsWrapper,
getEventControlConfig
} from '../renderer/event-control/helper';
export class TabsPlugin extends BasePlugin {
// 关联渲染器名字
@ -153,7 +155,17 @@ export class TabsPlugin extends BasePlugin {
),
visibleOn: isNewTabMode,
clearValueOnHidden: true
})
}),
{
label: tipedLabel(
'默认选项卡',
'默认显示某个选项卡选项卡配置hash时使用hash否则使用索引值支持获取变量<code>tab\\${id}</code>、<code>\\${id}</code>'
),
type: 'input-text',
name: 'activeKey',
pipeOut: (data: string) => data === '' || isNaN(Number(data)) ? data : Number(data)
},
]
},
getSchemaTpl('status'),

View File

@ -3,7 +3,6 @@ import {BaseEventContext, BasePlugin} from 'amis-editor-core';
import {defaultValue, getSchemaTpl, setSchemaTpl} from 'amis-editor-core';
import {tipedLabel} from 'amis-editor-core';
import {ValidatorTag} from '../validator';
import {getEventControlConfig} from '../util';
setSchemaTpl('tpl:content', {
label: tipedLabel(
@ -25,7 +24,8 @@ setSchemaTpl('tpl:rich-text', {
buttons: [
'paragraphFormat',
'quote',
'color',
'textColor',
'backgroundColor',
'|',
'bold',
'italic',

View File

@ -12,12 +12,11 @@ import {VRenderer} from 'amis-editor-core';
import {mapReactElement} from 'amis-editor-core';
import {RegionWrapper as Region} from 'amis-editor-core';
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
import {
RendererPluginAction,
RendererPluginEvent
} from 'amis-editor-core';
import {getEventControlConfig} from '../util';
import { getArgsWrapper } from '../renderer/event-control/helper';
getArgsWrapper,
getEventControlConfig
} from '../renderer/event-control/helper';
export class WizardPlugin extends BasePlugin {
// 关联渲染器名字

View File

@ -9,7 +9,7 @@ import mapKeys from 'lodash/mapKeys';
import {FormItem, Switch} from 'amis';
import {autobind, isObject, isEmpty, anyChanged} from 'amis-editor-core';
import {defaultValue} from 'amis-editor-core';
import {defaultValue, tipedLabel} from 'amis-editor-core';
import type {FormControlProps} from 'amis-core';
import type {SchemaExpression} from 'amis/lib/Schema';
@ -33,7 +33,7 @@ export interface BadgeControlProps extends FormControlProps {
/**
* position
*/
offset?: [number | string, number | string];
offset?: [number, number];
/**
*
@ -87,7 +87,7 @@ interface BadgeForm
| 'level'
>
> {
offset: {x: number; y: number};
offset: [number, number];
}
export default class BadgeControl extends React.Component<
@ -140,12 +140,12 @@ export default class BadgeControl extends React.Component<
const badge = ctx?.badge ?? {};
// 避免获取到上层的size
const size = ctx?.badge?.size;
const offset = {x: 0, y: 0};
const offset = [0, 0];
// 转换成combo可以识别的格式
if (Array.isArray(badge?.offset) && badge?.offset.length >= 2) {
offset.x = badge?.offset[0];
offset.y = badge?.offset[1];
offset[0] = badge.offset[0];
offset[1] = badge.offset[1];
}
return {...badge, size, offset};
@ -153,22 +153,13 @@ export default class BadgeControl extends React.Component<
normalizeBadgeValue(form: BadgeForm) {
const offset =
isObject(form?.offset) && form?.offset?.x && form?.offset?.y
? {offset: [form.offset.x, form.offset.y]}
: {};
const style =
isObject(form?.style) && !isEmpty(form?.style)
? {
style: mapKeys(form?.style, (value, key) => {
return camelCase(key);
})
}
isObject(form?.offset) && form?.offset?.[0] && form?.offset?.[1]
? {offset: [form.offset[0], form.offset[1]]}
: {};
return {
...form,
...offset,
...style
...offset
};
}
@ -213,7 +204,7 @@ export default class BadgeControl extends React.Component<
label: '类型',
name: 'mode',
type: 'button-group-select',
size: 'xs',
size: 'sm',
mode: 'row',
tiled: true,
className: 'ae-BadgeControl-buttonGroup',
@ -229,13 +220,18 @@ export default class BadgeControl extends React.Component<
name: 'text',
type: 'input-text',
mode: 'row',
visibleOn: "data.mode !== 'dot'"
visibleOn: "data.mode !== 'dot'",
pipeOut: (value: any) => {
return Number.isNaN(Number(value)) || value === ''
? value
: Number(value);
}
},
{
label: '角标主题色',
label: '角标主题',
name: 'level',
type: 'button-group-select',
size: 'xs',
size: 'sm',
mode: 'row',
tiled: true,
className: 'ae-BadgeControl-buttonGroup',
@ -251,31 +247,31 @@ export default class BadgeControl extends React.Component<
label: '角标位置',
name: 'position',
type: 'button-group-select',
size: 'xs',
size: 'sm',
mode: 'row',
tiled: true,
className: 'ae-BadgeControl-buttonGroup',
options: [
{
label: '左上',
label: '',
value: 'top-left',
icon: 'fa fa-long-arrow-alt-up',
className: 'ae-BadgeControl-position--antiClockwise'
},
{
label: '右上',
label: '',
value: 'top-right',
icon: 'fa fa-long-arrow-alt-up',
className: 'ae-BadgeControl-position--clockwise'
},
{
label: '左下',
label: '',
value: 'bottom-left',
icon: 'fa fa-long-arrow-alt-down',
className: 'ae-BadgeControl-position--clockwise'
},
{
label: '右下',
label: '',
value: 'bottom-right',
icon: 'fa fa-long-arrow-alt-down',
className: 'ae-BadgeControl-position--antiClockwise'
@ -284,22 +280,32 @@ export default class BadgeControl extends React.Component<
pipeIn: defaultValue('top-right')
},
{
type: 'group',
className: 'ae-BadgeControl-offset',
type: 'input-group',
mode: 'row',
inputClassName: 'inline-flex justify-right flex-row-reverse',
label: tipedLabel('偏移量', '角标位置相对”水平“、”垂直“的偏移量'),
body: [
{
label: '水平偏移量',
name: 'offset.x',
type: 'input-number',
name: 'offset',
suffix: 'px',
step: 1
pipeIn: (value: any) =>
Array.isArray(value) ? value[0] || 0 : 0,
pipeOut: (value: any, oldValue: any, data: any) => [
value,
data.offset[1]
]
},
{
label: '垂直偏移量',
name: 'offset.y',
type: 'input-number',
name: 'offset',
suffix: 'px',
step: 1
pipeIn: (value: any) =>
Array.isArray(value) ? value[1] || 0 : 0,
pipeOut: (value: any, oldValue: any, data: any) => [
data.offset[0],
value
]
}
]
},
@ -332,7 +338,7 @@ export default class BadgeControl extends React.Component<
pipeIn: (value: any) => (typeof value === 'number' ? value : 0)
},
{
label: '封顶数字',
label: tipedLabel('封顶数字', '尽在文本内容为数字下生效'),
name: 'overflowCount',
type: 'input-number',
size: 'sm',
@ -356,13 +362,8 @@ export default class BadgeControl extends React.Component<
}
render() {
const {
classPrefix,
className,
labelClassName,
label,
disabled
} = this.props;
const {classPrefix, className, labelClassName, label, disabled} =
this.props;
const {checked} = this.state;
return (

View File

@ -128,7 +128,7 @@ export default class FormulaControl extends React.Component<
this.state = {
variables: this.normalizeVariables(props.variables), // 备注: 待沟通
variableMode: 'tabs',
evalMode: false
evalMode: true
};
}
@ -335,9 +335,13 @@ export default class FormulaControl extends React.Component<
if (this.props.needDeleteProps) {
deleteProps.push(...this.props.needDeleteProps);
}
if (name) {
// 剔除自身配置的影响
deleteProps.push(name);
if (name && name === 'min') {
// 避免min影响自身默认值设置
deleteProps.push('min');
}
if (name && name === 'max') {
// 避免max影响自身默认值设置
deleteProps.push('max');
}
curRendererSchema = omit(curRendererSchema, deleteProps);
@ -362,7 +366,7 @@ export default class FormulaControl extends React.Component<
@autobind
renderFormulaValue(item: any) {
const html = {__html: item.html};
// bca-disable-line
// bca-disable-next-line
return <span dangerouslySetInnerHTML={html}></span>;
}

View File

@ -571,7 +571,7 @@ export default class OptionControl extends React.Component<
label: '删除',
onClick: () => this.handleDelete(index)
}
]
];
// 单选模式,选中时增加取消操作
if (!closeDefaultCheck && !isMultiple && checked) {
@ -580,7 +580,7 @@ export default class OptionControl extends React.Component<
className: 'ae-OptionControlItem-action',
label: '取消选中',
onClick: () => this.handleToggleDefaultValue(index, false)
})
});
}
return (
@ -596,7 +596,9 @@ export default class OptionControl extends React.Component<
className="ae-OptionControlItem-checkbox"
checked={checked}
type={isMultiple ? 'checkbox' : 'radio'}
onChange={(newChecked: any, shift?: boolean) => this.handleToggleDefaultValue(index, newChecked, shift)}
onChange={(newChecked: any, shift?: boolean) =>
this.handleToggleDefaultValue(index, newChecked, shift)
}
/>
</span>
)}

View File

@ -15,7 +15,7 @@ import type {FormSchema} from 'amis/lib/schema';
export interface StatusControlProps extends FormControlProps {
name: string;
expressioName: string;
expressionName: string;
trueValue?: boolean;
falseValue?: boolean;
options?: Option[];
@ -23,8 +23,15 @@ export interface StatusControlProps extends FormControlProps {
messages?: Pick<FormSchema, 'messages'>;
}
type StatusFormData = {
statusType: number;
expression: string;
};
interface StatusControlState {
checked: boolean;
formData: StatusFormData;
}
export class StatusControl extends React.Component<
@ -42,9 +49,19 @@ export class StatusControl extends React.Component<
}
initState() {
const {data: ctx = {}, expressioName, name, trueValue} = this.props;
const {data: ctx = {}, expressionName, name, trueValue} = this.props;
const formData: StatusFormData = {
statusType: 1,
expression: '',
};
if (ctx[expressionName] || ctx[expressionName]=== "") {
formData.statusType = 2;
formData.expression = ctx[expressionName];
}
return {
checked: ctx[name] == trueValue || typeof ctx[expressioName] === 'string'
checked:
ctx[name] == trueValue || typeof ctx[expressionName] === 'string',
formData
};
}
@ -59,34 +76,40 @@ export class StatusControl extends React.Component<
handleSwitch(value: boolean) {
const {trueValue, falseValue} = this.props;
this.setState({checked: value == trueValue ? true : false}, () => {
const {onBulkChange, expressioName, name} = this.props;
onBulkChange &&
onBulkChange({
[name]: value == trueValue ? trueValue : falseValue,
[expressioName]: undefined
});
const {onBulkChange, expressionName, name} = this.props;
onBulkChange &&
onBulkChange({
[name]: value == trueValue ? trueValue : falseValue,
[expressionName]: undefined,
});
});
}
@autobind
handleSubmit(values: any) {
const {onBulkChange, name, expressioName} = this.props;
values[name] = !values[name] ? undefined : values[name];
values[expressioName] = !values[expressioName]
? undefined
: values[expressioName];
onBulkChange && onBulkChange(values);
handleFormSubmit(
values: StatusFormData
) {
const {onBulkChange, name, expressionName} = this.props;
const data: Record<string, any> = {
[name]: undefined,
[expressionName]: undefined
};
this.setState({formData: values});
switch (values.statusType) {
case 1:
data[name] = true;
break;
case 2:
data[expressionName] = values.expression;
break;
}
onBulkChange && onBulkChange(data);
}
@autobind
handleSelect(value: true | '') {
const {onBulkChange, name, expressioName} = this.props;
onBulkChange &&
onBulkChange({
[value ? expressioName : name]: undefined,
[(!value && expressioName) || '']: ''
});
}
render() {
const {className, data: ctx = {}, trueValue, falseValue, env} = this.props;
@ -117,11 +140,12 @@ export class StatusControl extends React.Component<
label,
data: ctx = {},
name,
expressioName,
expressionName,
options,
children,
messages
} = this.props;
const {formData} = this.state;
return (
<div className="ae-StatusControl-content">
@ -149,8 +173,7 @@ export class StatusControl extends React.Component<
{
type: 'select',
label: '条件',
name: name,
value: `typeof this.${expressioName} === "string" ? 2 : 1`,
name: 'statusType',
options: options || [
{
label: '静态',
@ -160,26 +183,20 @@ export class StatusControl extends React.Component<
label: '表达式',
value: 2
}
],
pipeIn: (value: any) => (typeof value === 'boolean' ? 1 : 2),
pipeOut: (value: any) => (value === 1 ? true : ''),
onChange: this.handleSelect
]
},
{
type: 'ae-formulaControl',
name: 'expression',
label: '表达式',
placeholder: `请输入${label}条件`,
visibleOn: 'this.statusType === 2'
},
...(Array.isArray(children)
? children
: [
children || {
type: 'ae-formulaControl',
name: expressioName,
label: '表达式',
placeholder: `请输入${label}条件`,
visibleOn: `typeof this.${name} !== "boolean"`
}
])
]
},
{
onSubmit: this.handleSubmit
data: formData,
onSubmit: this.handleFormSubmit
}
)}
</div>

View File

@ -262,6 +262,10 @@ export default class TreeOptionControl extends React.Component<
}
@autobind
addChildOption(pathStr: string) {
if (pathStr.split('-').length >= 7) {
toast.warning('层级过深,建议使用【接口获取】管理选项', {closeButton: true});
return;
}
const options = cloneDeep(this.state.options);
const {path} = this.getNodePath(pathStr);
const node = get(options, path) || [];
@ -337,7 +341,7 @@ export default class TreeOptionControl extends React.Component<
type: 'dropdown-button',
className: 'ae-TreeOptionControlItem-dropdown fa-sm',
btnClassName: 'px-2',
icon: 'fa fa-plus',
icon: 'add',
hideCaret: true,
closeOnClick: true,
trigger: 'hover',

View File

@ -8,7 +8,7 @@ import React from 'react';
import {ActionConfig, ComponentInfo} from './types';
import ActionConfigPanel from './action-config-panel';
import {BASE_ACTION_PROPS} from './comp-action-select';
import { findActionNode } from './helper';
import {findActionNode} from './helper';
interface ActionDialogProp {
show: boolean;
@ -36,7 +36,11 @@ export default class ActionDialog extends React.Component<ActionDialogProp> {
return tree;
}
let result: any[] = [];
const getSearchList = (result: any[], array: RendererPluginAction[], keywords: string) => {
const getSearchList = (
result: any[],
array: RendererPluginAction[],
keywords: string
) => {
array.forEach(node => {
if (node.children) {
getSearchList(result, node.children, keywords);
@ -73,17 +77,12 @@ export default class ActionDialog extends React.Component<ActionDialogProp> {
labelField: 'actionLabel',
valueField: 'actionType',
inputClassName: 'no-border action-tree-control',
onChange: (
value: string,
oldVal: any,
data: any,
form: any
) => {
onChange: (value: string, oldVal: any, data: any, form: any) => {
// 因为不知道动作都有哪些字段,这里只保留基础配置
let removeKeys: {
[key: string]: any;
} = {};
let __cmptActionType = '';
let groupType = '';
Object.keys(form.data).forEach((key: string) => {
if (!BASE_ACTION_PROPS.includes(key)) {
@ -93,34 +92,27 @@ export default class ActionDialog extends React.Component<ActionDialogProp> {
if (
value === 'openDialog' &&
!['dialog', 'drawer'].includes(__cmptActionType)
!['dialog', 'drawer'].includes(groupType)
) {
__cmptActionType = 'dialog';
groupType = 'dialog';
}
if (
value === 'closeDialog' &&
!['closeDialog', 'closeDrawer'].includes(
__cmptActionType
)
!['closeDialog', 'closeDrawer'].includes(groupType)
) {
__cmptActionType = 'closeDialog';
groupType = 'closeDialog';
}
if (
value === 'visibility' &&
!['show', 'hidden'].includes(__cmptActionType)
) {
__cmptActionType = 'show';
if (value === 'visibility' && !['show', 'hidden'].includes(groupType)) {
groupType = 'show';
}
if (
value === 'usability' &&
!['enabled', 'disabled'].includes(
__cmptActionType
)
!['enabled', 'disabled'].includes(groupType)
) {
__cmptActionType = 'enabled';
groupType = 'enabled';
}
const actionNode = findActionNode(actionTree, value);
@ -129,11 +121,9 @@ export default class ActionDialog extends React.Component<ActionDialogProp> {
...removeKeys,
__keywords: form.data.__keywords,
__resultActionTree: form.data.__resultActionTree,
componentId: form.data.componentId
? ''
: undefined,
componentId: form.data.componentId ? '' : undefined,
args: {},
__cmptActionType,
groupType,
__actionDesc: actionNode?.description,
__actionSchema: actionNode?.schema,
__subActions: actionNode?.actions,
@ -142,18 +132,18 @@ export default class ActionDialog extends React.Component<ActionDialogProp> {
: []
});
}
}
};
if (isSearch) {
return {
...inputTreeSchema,
source: '${__resultActionTree}',
highlightTxt: '${__keywords}'
}
};
} else {
return {
...inputTreeSchema,
options: actionTree,
}
options: actionTree
};
}
}
@ -170,145 +160,151 @@ export default class ActionDialog extends React.Component<ActionDialogProp> {
} = this.props;
return amisRender(
{
type: 'dialog',
title: '动作配置',
headerClassName: 'font-bold',
className: 'action-config-dialog',
closeOnEsc: true,
closeOnOutside: false,
show,
showCloseButton: true,
size: 'lg',
body: [
{
type: 'dialog',
title: '动作配置',
headerClassName: 'font-bold',
className: 'action-config-dialog',
closeOnEsc: true,
closeOnOutside: false,
show,
showCloseButton: true,
size: 'lg',
type: 'form',
title: '',
mode: 'normal',
wrapperComponent: 'div',
submitText: '保存',
autoFocus: true,
data: {
__keywords: '',
__resultActionTree: []
},
preventEnterSubmit: true,
// debug: true,
onSubmit: this.props.onSubmit?.bind(this, type),
body: [
{
type: 'form',
title: '',
mode: 'normal',
wrapperComponent: 'div',
submitText: '保存',
autoFocus: true,
data: {
__keywords: '',
__resultActionTree: []
},
preventEnterSubmit: true,
// debug: true,
onSubmit: this.props.onSubmit?.bind(this, type),
body: [
type: 'grid',
className: 'h-full',
columns: [
{
type: 'grid',
className: 'h-full',
columns: [
body: [
{
body: [
{
type: 'tpl',
tpl: '执行动作',
className: 'action-panel-title',
inline: false
},
{
type: 'input-text',
name: '__keywords',
className: 'action-tree-search',
placeholder: '请搜索执行动作',
clearable: true,
onChange: (
value: string,
oldVal: any,
data: any,
form: any
) => {
if (value) {
const list = this.getTreeSearchList(actionTree, value);
form.setValueByName('__resultActionTree', list);
} else {
form.setValueByName('__resultActionTree', actionTree);
}
}
},
// actionTree中包含function及class类型的属性直接传入form的data中解析会报错
// 故采用两棵树分别使用静态及动态选项组
this.getInputTreeSchema(false, actionTree, getComponents),
this.getInputTreeSchema(true, actionTree, getComponents)
],
md: 3,
columnClassName: 'left-panel'
type: 'tpl',
tpl: '执行动作',
className: 'action-panel-title',
inline: false
},
{
type: 'input-text',
name: '__keywords',
className: 'action-tree-search',
placeholder: '请搜索执行动作',
clearable: true,
onChange: (
value: string,
oldVal: any,
data: any,
form: any
) => {
if (value) {
const list = this.getTreeSearchList(
actionTree,
value
);
form.setValueByName('__resultActionTree', list);
} else {
form.setValueByName(
'__resultActionTree',
actionTree
);
}
}
},
// actionTree中包含function及class类型的属性直接传入form的data中解析会报错
// 故采用两棵树分别使用静态及动态选项组
this.getInputTreeSchema(false, actionTree, getComponents),
this.getInputTreeSchema(true, actionTree, getComponents)
],
md: 3,
columnClassName: 'left-panel'
},
{
body: [
{
type: 'tpl',
tpl: '动作说明',
className: 'action-panel-title',
visibleOn: 'data.actionType',
inline: false
},
{
type: 'tpl',
className: 'action-desc',
tpl: '${__actionDesc}',
visibleOn: 'data.actionType'
},
{
type: 'tpl',
tpl: '基础设置',
className: 'action-panel-title',
visibleOn: 'data.actionType',
inline: false
},
{
type: 'container',
className: 'right-panel-container',
body: [
{
type: 'tpl',
tpl: '动作说明',
className: 'action-panel-title',
visibleOn: 'data.actionType',
inline: false
asFormItem: true,
component: ActionConfigPanel,
pluginActions,
commonActions
},
{
type: 'tpl',
className: 'action-desc',
tpl: '${__actionDesc}',
tpl: '高级设置',
inline: false,
className: 'action-panel-title',
visibleOn: 'data.actionType'
},
{
type: 'tpl',
tpl: '基础设置',
className: 'action-panel-title',
visibleOn: 'data.actionType',
inline: false
},
{
type: 'container',
className: 'right-panel-container',
body: [
{
asFormItem: true,
component: ActionConfigPanel,
pluginActions,
commonActions
},
{
type: 'tpl',
tpl: '高级设置',
inline: false,
className: 'action-panel-title',
visibleOn: 'data.actionType'
},
{
name: 'expression',
title: '',
type: 'input-formula',
variableMode: 'tabs',
inputMode: 'input-group',
variables: '${variables}',
className: 'action-exec-on',
label: '执行条件',
mode: 'horizontal',
size: 'lg',
placeholder: '默认执行该动作',
visibleOn: 'data.actionType'
}
]
name: 'expression',
title: '',
type: 'input-formula',
variableMode: 'tabs',
inputMode: 'input-group',
variables: '${variables}',
className: 'action-exec-on',
label: '执行条件',
mode: 'horizontal',
size: 'lg',
placeholder: '默认执行该动作',
visibleOn: 'data.actionType'
}
],
columnClassName: 'right-panel'
]
}
]
],
columnClassName: 'right-panel'
}
],
style: {
borderStyle: 'solid'
},
className: 'action-config-panel'
]
}
],
onClose
},
{
data // 必须这样,不然变量会被当作数据映射处理掉
style: {
borderStyle: 'solid'
},
className: 'action-config-panel'
}
)
],
onClose
},
{
data // 必须这样,不然变量会被当作数据映射处理掉
}
);
// : null;
}
}

View File

@ -13,7 +13,7 @@ export default class ActionConfigPanel extends React.Component<RendererProps> {
render() {
const {data, onBulkChange, render, pluginActions, actionConfigItemsMap} = this.props;
const actionType = data.__subActions
? data.__cmptActionType
? data.groupType
: data.actionType;
const commonActionConfig = {
...COMMON_ACTION_SCHEMA_MAP,
@ -26,8 +26,8 @@ export default class ActionConfigPanel extends React.Component<RendererProps> {
const subActionSchema =
pluginActions?.[data.__rendererName]?.find(
(item: RendererPluginAction) =>
item.actionType === data.__cmptActionType
)?.schema ?? commonActionConfig[data.__cmptActionType]?.schema;
item.actionType === data.groupType
)?.schema ?? commonActionConfig[data.groupType]?.schema;
const baseSchema = renderCmptActionSelect('选择组件', true);
// 追加到基础配置
schema = [
@ -63,4 +63,4 @@ export default class ActionConfigPanel extends React.Component<RendererProps> {
</div>
);
}
}
}

View File

@ -5,10 +5,12 @@ import {
RendererPluginAction
} from 'amis-editor-core';
import React from 'react';
import {normalizeApi} from 'amis-core';
import {
FORMITEM_CMPTS,
getArgsWrapper,
IS_DATA_CONTAINER,
SHOW_SELECT_PROP,
renderCmptActionSelect,
renderCmptSelect,
SUPPORT_DISABLED_CMPTS
@ -153,7 +155,7 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
{
type: 'radios',
label: '类型',
name: '__cmptActionType',
name: 'groupType',
mode: 'horizontal',
value: 'dialog',
required: true,
@ -180,7 +182,7 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
body: '<p>对,你刚刚点击了</p>'
}),
asFormItem: true,
visibleOn: 'data.__cmptActionType === "dialog"',
visibleOn: 'data.groupType === "dialog"',
children: ({value, onChange, data}: any) => (
<Button
size="sm"
@ -208,7 +210,7 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
body: '<p>对,你刚刚点击了</p>'
}),
asFormItem: true,
visibleOn: 'data.__cmptActionType === "drawer"',
visibleOn: 'data.groupType === "drawer"',
children: ({value, onChange, data}: any) => (
<Button
size="sm"
@ -239,7 +241,7 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
{
type: 'radios',
label: '类型',
name: '__cmptActionType',
name: 'groupType',
mode: 'horizontal',
value: 'closeDialog',
required: true,
@ -286,10 +288,7 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
descDetail: (info: any) => {
return (
<div>
<span className="variable-right">
{MSG_TYPES[info?.args?.msgType] || ''}
</span>
{MSG_TYPES[info?.args?.msgType] || ''}
<span className="variable-left">{info?.args?.msg}</span>
</div>
);
@ -409,28 +408,71 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
actionLabel: '发送请求',
actionType: 'ajax',
description: '配置并发送API请求',
innerArgs: ['api'],
innerArgs: ['api', 'options'],
descDetail: (info: any) => {
let apiInfo = info?.args?.api;
if (typeof apiInfo === 'string'){
apiInfo = normalizeApi(apiInfo);
}
return (
<div>
<span className="variable-right variable-left">
{info?.args?.api?.method}
{apiInfo?.method}
</span>
<span className="variable-left">{info?.args?.api?.url}</span>
<span className="variable-left">{apiInfo?.url}</span>
</div>
);
},
schema: {
type: 'wrapper',
style: {padding: '0'},
className: "p-none",
body: [
getArgsWrapper(
getSchemaTpl('apiControl', {
name: 'api'
})
)
[
getSchemaTpl('apiControl', {
name: 'api',
label: '配置请求',
mode: 'horizontal',
size: 'lg',
required: true
}),
{
name: 'options',
type: 'combo',
label: false,
mode: 'horizontal',
items: [
{
type: 'checkbox',
name: 'silent',
option: '静默模式',
remark: {
className: 'ae-BaseRemark',
icon: 'fa fa-question-circle',
trigger: ['hover', 'click'],
placement: 'left',
content: '勾选后,服务请求将以静默模式发送,即不会弹出成功或报错提示。'
},
mode: 'inline',
className: 'm-r-none',
value: false
}
]
}
]
),
{
name: 'outputVar',
type: 'input-text',
label: '请求出参',
placeholder: '请输入存储请求结果的变量名称',
description: '后面的动作可以通过\\${event.data.请求出参名称}来获取本次请求的返回结果',
mode: 'horizontal',
size: 'lg',
required: true
}
]
}
},
@ -469,7 +511,7 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
<div>
<span className="variable-left variable-right">
{info?.__rendererLabel}
{info?.rendererLabel}
</span>
</div>
@ -483,7 +525,7 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
<div>
<span className="variable-left variable-right">
{info?.__rendererLabel}
{info?.rendererLabel}
</span>
</div>
@ -497,7 +539,7 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
{
type: 'radios',
label: '显示/隐藏',
name: '__cmptActionType',
name: 'groupType',
mode: 'horizontal',
value: 'show',
required: true,
@ -527,7 +569,7 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
<div>
<span className="variable-left variable-right">
{info?.__rendererLabel}
{info?.rendererLabel}
</span>
</div>
@ -541,7 +583,7 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
<div>
<span className="variable-left variable-right">
{info?.__rendererLabel}
{info?.rendererLabel}
</span>
</div>
@ -555,7 +597,7 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
{
type: 'radios',
label: '启用/禁用',
name: '__cmptActionType',
name: 'groupType',
mode: 'horizontal',
value: 'enabled',
required: true,
@ -582,7 +624,7 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
<div>
<span className="variable-left variable-right">
{info?.__rendererLabel}
{info?.rendererLabel}
</span>
</div>
@ -595,13 +637,13 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
actionLabel: '设置组件数据',
actionType: 'setValue',
description: '设置数据容器或表单项的数据',
innerArgs: ['value', 'valueInput'],
innerArgs: ['value', 'index', '__valueInput', '__comboType'],
descDetail: (info: any) => {
return (
<div>
<span className="variable-left variable-right">
{info?.__rendererLabel}
{info?.rendererLabel}
</span>
{/*
@ -615,11 +657,43 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
},
supportComponents: [],
schema: [
...renderCmptSelect('选择组件', true),
...renderCmptActionSelect('选择组件', true),
getArgsWrapper({
type: 'wrapper',
className: 'p-none',
body: [
{
type: 'radios',
required: true,
name: '__comboType',
mode: 'horizontal',
label: '赋值方式',
visibleOn: `data.__rendererName && __rendererName === 'combo'`,
options: [
{
label: '全量',
value: 'all'
},
{
label: '指定序号',
value: 'appoint',
}
],
onChange: (value: string, oldVal: any, data: any, form: any) => {
form.setValueByName('index', undefined);
form.setValueByName('value', []);
form.setValueByName('__valueInput', undefined);
}
},
{
type: 'input-number',
required: true,
name: 'index',
mode: 'horizontal',
label: '输入序号',
placeholder: '请输入待更新序号',
visibleOn: `data.__comboType && __comboType === 'appoint'`
},
{
type: 'combo',
name: 'value',
@ -632,11 +706,22 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
canAccessSuperData: true,
mode: 'horizontal',
items: [
{
name: 'key',
type: 'select',
placeholder: '变量名',
source: '${__setValueDs}',
labelField: 'label',
valueField: 'value',
required: true,
visibleOn: `data.__rendererName && ${SHOW_SELECT_PROP}`,
},
{
name: 'key',
type: 'input-text',
placeholder: '字段名',
required: true
placeholder: '变量名',
required: true,
visibleOn: `data.__rendererName && !${SHOW_SELECT_PROP} && __comboType === 'appoint'`
},
{
name: 'val',
@ -648,7 +733,7 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
inputMode: 'input-group'
}
],
visibleOn: `data.__rendererName && ${IS_DATA_CONTAINER}`
visibleOn: `data.__rendererName && ${IS_DATA_CONTAINER} || (data.__comboType && __comboType === 'appoint')`
},
{
type: 'combo',
@ -676,10 +761,21 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
className: 'm-l',
mode: 'horizontal',
items: [
{
name: 'key',
type: 'select',
source: '${__setValueDs}',
labelField: 'label',
valueField: 'name',
required: true,
visibleOn: `data.__rendererName && ${SHOW_SELECT_PROP}`,
},
{
name: 'key',
type: 'input-text',
required: true
required: true,
placeholder: '变量名',
visibleOn: `data.__rendererName && !${SHOW_SELECT_PROP}`
},
{
name: 'val',
@ -692,10 +788,10 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
]
}
],
visibleOn: `data.__rendererName && __rendererName === 'combo'`
visibleOn: `data.__rendererName && __rendererName === 'combo' && data.__comboType && __comboType === 'all'`
},
{
name: 'valueInput',
name: '__valueInput',
type: 'input-formula',
variables: '${variables}',
evalMode: false,
@ -714,13 +810,13 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
{
actionLabel: '提交表单',
actionType: 'submit',
description: '提交表单数据至数据源',
description: '触发表单提交',
descDetail: (info: any) => {
return (
<div>
<span className="variable-right">
{info?.__rendererLabel}
<span className="variable-left variable-right">
{info?.rendererLabel}
</span>
</div>
@ -737,8 +833,8 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
return (
<div>
<span className="variable-right">
{info?.__rendererLabel}
<span className="variable-left variable-right">
{info?.rendererLabel}
</span>
</div>
@ -755,8 +851,8 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
return (
<div>
<span className="variable-right">
{info?.__rendererLabel}
<span className="variable-left variable-right">
{info?.rendererLabel}
</span>
</div>
@ -773,8 +869,8 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
return (
<div>
<span className="variable-right">
{info?.__rendererLabel}
<span className="variable-left variable-right">
{info?.rendererLabel}
</span>
</div>
@ -788,7 +884,6 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
actionType: 'component',
description: '触发所选组件的特性动作',
supportComponents: '*',
actions: [],
schema: renderCmptActionSelect('选择组件', true)
}
]
@ -826,6 +921,7 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
label: '内容模板',
mode: 'horizontal',
size: 'lg',
visibleOn: 'data.actionType === "copy"',
required: true
},
{
@ -860,6 +956,18 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
name: 'script',
label: '自定义JS',
mode: 'horizontal',
options: {
automaticLayout: true,
lineNumbers: 'off',
glyphMargin: false,
tabSize: 2,
wordWrap: 'on',
lineDecorationsWidth: 0,
lineNumbersMinChars: 0,
selectOnLineNumbers: true,
scrollBeyondLastLine: false,
folding: true
},
className: 'ae-event-control-action-js-editor',
value: `/* 自定义JS使用说明
* 1.doAction
@ -914,4 +1022,4 @@ doAction({
];
};
export default ACTION_TYPE_TREE;
export default ACTION_TYPE_TREE;

View File

@ -30,7 +30,6 @@ export default class CmptActionSelect extends React.Component<RendererProps> {
...BASE_ACTION_PROPS,
'componentId',
'__rendererName',
'__rendererLabel',
'__cmptTreeSource'
].includes(key)
) {
@ -41,7 +40,7 @@ export default class CmptActionSelect extends React.Component<RendererProps> {
formStore.setValues({
...removeKeys,
args: undefined,
__cmptActionType: option.value,
groupType: option.value,
__cmptActionDesc: option.description
});
@ -54,7 +53,7 @@ export default class CmptActionSelect extends React.Component<RendererProps> {
return (
<Select
value={formStore.data.__cmptActionType}
value={formStore.data.groupType}
className="cmpt-action-select"
options={actions.map((item: any) => ({
label: item.actionLabel,
@ -66,4 +65,4 @@ export default class CmptActionSelect extends React.Component<RendererProps> {
/>
);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -3,14 +3,22 @@ import {findDOMNode} from 'react-dom';
import cx from 'classnames';
import Sortable from 'sortablejs';
import {DataSchema, FormItem, Icon, TooltipWrapper} from 'amis';
import {FormControlProps, autobind, render as amisRender} from 'amis-core';
import cloneDeep from 'lodash/cloneDeep';
import {
FormControlProps,
autobind,
render as amisRender,
findTree
} from 'amis-core';
import ActionDialog from './action-config-dialog';
import {
findActionNode,
findSubActionNode,
getActionType,
getEventDesc,
getEventLabel,
getPropOfAcion
getPropOfAcion,
SELECT_PROPS_CONTAINER
} from './helper';
import {
ActionConfig,
@ -62,11 +70,12 @@ interface EventControlState {
pluginActions: PluginActions;
getContextSchemas?: (id?: string, withoutSuper?: boolean) => DataSchema;
rawVariables: ContextVariables[];
__cmptActionType?: string;
groupType?: string;
__actionDesc?: string;
__cmptTreeSource?: ComponentInfo[];
__actionSchema?: any;
__subActions?: SubRendererPluginAction[];
__setValueDs?: any[];
}
| undefined;
type: 'update' | 'add';
@ -303,10 +312,17 @@ export class EventControl extends React.Component<
* @param {*} config
* @memberof EventControl
*/
updateValue(event: string, index: number, config: any) {
async updateValue(event: string, index: number, config: any) {
const {onEvent} = this.state;
let emptyEventAcion = {...onEvent};
let onEventConfig = {...onEvent};
emptyEventAcion[event] = {
actions: onEvent[event].actions.map((item, actionIndex) => {
return actionIndex === index ? {actionType: ''} : item;
}),
weight: onEvent[event].weight
};
onEventConfig[event] = {
actions: onEvent[event].actions.map((item, actionIndex) => {
return actionIndex === index
@ -320,11 +336,9 @@ export class EventControl extends React.Component<
}),
weight: onEvent[event].weight
};
this.setState({
onEvent: onEventConfig
});
this.props.onChange && this.props.onChange(onEventConfig);
}
@ -383,7 +397,7 @@ export class EventControl extends React.Component<
} else {
parent.appendChild(e.item);
}
let onEventConfig = {...this.state.onEvent};
let onEventConfig = cloneDeep(this.state.onEvent);
const newEvent = onEventConfig[eventKey];
let options = newEvent?.actions.concat();
// 从后往前移
@ -420,6 +434,66 @@ export class EventControl extends React.Component<
});
}
getEventVariables(
activeData: Pick<
EventControlState,
'showAcionDialog' | 'type' | 'actionData'
>
) {
const {events, onEvent} = this.state;
const {actionTree, pluginActions, commonActions} = this.props;
// 收集当前事件已有ajax动作的请求返回结果作为事件变量
let oldActions = onEvent[activeData.actionData!.eventKey].actions;
if (activeData.type === 'update') {
oldActions = oldActions.slice(
0,
activeData.actionData!.actionIndex || oldActions?.length
);
}
const withOutputVarActions = oldActions?.filter(item => item.outputVar);
const withOutputVarVariables = withOutputVarActions?.map(
(item: any, index: number) => {
const actionLabel = getPropOfAcion(
item,
'actionLabel',
actionTree,
pluginActions,
commonActions
);
return {
label: `${
item.outputVar
? item.outputVar + `${actionLabel}结果)`
: `${actionLabel}结果`
}`,
tag: 'object',
type: 'object',
value: `${
item.outputVar ? 'event.data.' + item.outputVar : 'event.data'
}`
};
}
);
const eventVariables: ContextVariables[] = [
{
label: '事件变量',
children: withOutputVarVariables || []
}
];
const eventConfig = events.find(
item => item.eventName === activeData.actionData!.eventKey
);
eventConfig?.dataSchema?.forEach((ds: any) => {
const dataSchema = new DataSchema(ds || []);
eventVariables[0].children = [
...eventVariables[0].children!,
...dataSchema.getDataPropsAsOptions()
];
});
return eventVariables;
}
// 唤起动作配置弹窗
activeActionDialog(
data: Pick<EventControlState, 'showAcionDialog' | 'type' | 'actionData'>
@ -431,27 +505,9 @@ export class EventControl extends React.Component<
getComponents,
actionTree
} = this.props;
const {events, rawVariables} = this.state;
const {rawVariables} = this.state;
// 收集事件变量
let eventVariables: ContextVariables[] = [
{
label: '事件变量',
children: []
}
];
const eventConfig = events.find(
item => item.eventName === data.actionData!.eventKey
);
eventConfig?.dataSchema?.forEach((ds: any) => {
const dataSchema = new DataSchema(ds || []);
eventVariables[0].children = [
...eventVariables[0].children!,
...dataSchema.getDataPropsAsOptions()
];
});
const eventVariables = this.getEventVariables(data);
const variables = [...eventVariables, ...rawVariables];
// 编辑操作,需要格式化动作配置
@ -460,7 +516,23 @@ export class EventControl extends React.Component<
const actionConfig = actionConfigInitFormatter?.(action);
const actionNode = findActionNode(actionTree, actionConfig?.actionType!);
const hasSubActionNode = findSubActionNode(actionTree, action.actionType);
const cmpts = getComponents(actionNode!);
const node = findTree(cmpts, item => item.value === action.componentId);
let setValueDs: any = null;
if (actionConfig?.actionType === 'setValue') {
const rendererType = node?.type;
const rendererName = node?.label;
// todo:这里会闪一下需要从amis查下问题
if (SELECT_PROPS_CONTAINER.includes(rendererType || '')) {
const curVariable = rawVariables.find(
item => item.label === `${rendererName}变量`
);
setValueDs = curVariable?.children?.filter(
item => item.value !== '$$id'
);
}
}
data.actionData = {
eventKey: data.actionData!.eventKey,
actionIndex: data.actionData!.actionIndex,
@ -469,16 +541,24 @@ export class EventControl extends React.Component<
getContextSchemas,
rawVariables,
...actionConfig,
__cmptActionType:
hasSubActionNode || action.componentId ? action.actionType : '',
groupType: action.actionType,
__actionDesc: actionNode!.description!, // 树节点描述
__actionSchema: actionNode!.schema, // 树节点schema
__subActions: hasSubActionNode?.actions, // 树节点子动作
__cmptTreeSource: actionConfig?.componentId ? getComponents?.(actionNode!) ?? [] : []
__cmptTreeSource: actionConfig?.componentId
? getComponents?.(actionNode!) ?? []
: [],
__setValueDs: setValueDs
// broadcastId: action.actionType === 'broadcast' ? action.eventName : ''
};
// 选中项自动滚动至可见位置
setTimeout(() => document.querySelector('.action-tree .cxd-Tree-item--isLeaf .is-checked')?.scrollIntoView(), 0);
setTimeout(
() =>
document
.querySelector('.action-tree .cxd-Tree-item--isLeaf .is-checked')
?.scrollIntoView(),
0
);
} else {
data.actionData = {
eventKey: data.actionData!.eventKey,
@ -494,7 +574,12 @@ export class EventControl extends React.Component<
// 渲染描述信息
renderDesc(action: ActionConfig) {
const {actions: pluginActions, actionTree, commonActions} = this.props;
const {
actions: pluginActions,
actionTree,
commonActions,
getComponents
} = this.props;
const desc = getPropOfAcion(
action,
'descDetail',
@ -502,9 +587,25 @@ export class EventControl extends React.Component<
pluginActions,
commonActions
);
let info = {...action};
// 根据子动作类型获取动作树节点的配置
const hasSubActionNode = findSubActionNode(actionTree, action.actionType);
const actionType = getActionType(action, hasSubActionNode);
const actionNode = actionType && findActionNode(actionTree, actionType);
if (action.componentId && actionNode) {
const cmpts = getComponents(actionNode);
const node = findTree(cmpts, item => item.value === action.componentId);
if (node) {
info = {
...info,
rendererLabel: node.label
};
}
}
return typeof desc === 'function' ? (
<div className="action-control-content">{desc?.(action) || '-'}</div>
<div className="action-control-content">{desc?.(info) || '-'}</div>
) : null;
}
@ -527,7 +628,12 @@ export class EventControl extends React.Component<
}
render() {
const {actionTree, actions: pluginActions, commonActions, getComponents} = this.props;
const {
actionTree,
actions: pluginActions,
commonActions,
getComponents
} = this.props;
const {
onEvent,
events,
@ -536,37 +642,41 @@ export class EventControl extends React.Component<
type,
actionData
} = this.state;
const enventSnapshot = cloneDeep(onEvent);
const {showOldEntry} = this.props;
const eventKeys = Object.keys(onEvent);
const eventKeys = Object.keys(enventSnapshot);
return (
<div className="ae-event-control">
<header
className={cx({
'ae-event-control-header': true,
'ae-event-control-header-oldentry': showOldEntry,
'no-bd-btm': !eventKeys.length
})}
>
{amisRender({
type: 'dropdown-button',
level: 'enhance',
label: '添加事件',
disabled: false,
className: 'block w-full add-event-dropdown',
closeOnClick: true,
buttons: events.map(item => ({
type: 'button',
actionType: '',
label: item.eventLabel,
onClick: this.addEvent.bind(this, item)
}))
})}
</header>
<ul className={cx({
'ae-event-control-content': true,
'ae-event-control-content-oldentry': showOldEntry
})} ref={this.dragRef}>
<header
className={cx({
'ae-event-control-header': true,
'ae-event-control-header-oldentry': showOldEntry,
'no-bd-btm': !eventKeys.length
})}
>
{amisRender({
type: 'dropdown-button',
level: 'enhance',
label: '添加事件',
disabled: false,
className: 'block w-full add-event-dropdown',
closeOnClick: true,
buttons: events.map(item => ({
type: 'button',
actionType: '',
label: item.eventLabel,
onClick: this.addEvent.bind(this, item)
}))
})}
</header>
<ul
className={cx({
'ae-event-control-content': true,
'ae-event-control-content-oldentry': showOldEntry
})}
ref={this.dragRef}
>
{eventKeys.length ? (
eventKeys.map((eventKey, eventIndex) => {
return (
@ -575,7 +685,7 @@ export class EventControl extends React.Component<
className={cx({
'event-item-header': true,
'no-bd-btm': !(
onEvent[eventKey].actions?.length &&
enventSnapshot[eventKey].actions?.length &&
eventPanelActive[eventKey]
)
})}
@ -620,66 +730,74 @@ export class EventControl extends React.Component<
</div>
</div>
</div>
{onEvent[eventKey].actions.length &&
{enventSnapshot[eventKey].actions.length &&
eventPanelActive[eventKey] ? (
<ul className="item-content">
{onEvent[eventKey].actions.map((action, actionIndex) => {
return (
<li
className="ae-option-control-item"
key={`item-content_${actionIndex}`}
>
<div className="action-control-header">
<div className="action-control-header-left">
<div className="ae-option-control-item-dragBar">
<Icon
icon="drag-six-circle-btn"
className="icon"
/>
</div>
<div className="action-item-actiontype">
{getPropOfAcion(
action,
'actionLabel',
actionTree,
pluginActions,
commonActions
) || action.actionType}
</div>
</div>
<div className="action-control-header-right">
<div
onClick={this.activeActionDialog.bind(this, {
showAcionDialog: true,
type: 'update',
actionData: {
{enventSnapshot[eventKey].actions.map(
(action, actionIndex) => {
return (
<li
className="ae-option-control-item"
key={`item-content_${actionIndex}`}
>
<div className="action-control-header">
<div className="action-control-header-left">
<div className="ae-option-control-item-dragBar">
<Icon
icon="drag-six-circle-btn"
className="icon"
/>
</div>
<div className="action-item-actiontype">
{getPropOfAcion(
action,
eventKey,
actionIndex
}
})}
>
<Icon className="icon" icon="edit-full-btn" />
'actionLabel',
actionTree,
pluginActions,
commonActions
) || action.actionType}
</div>
</div>
<div
onClick={this.delAction.bind(
this,
eventKey,
action,
actionIndex
)}
>
<Icon
className="icon"
icon="delete-easy-btn"
/>
<div className="action-control-header-right">
<div
onClick={this.activeActionDialog.bind(
this,
{
showAcionDialog: true,
type: 'update',
actionData: {
action,
eventKey,
actionIndex
}
}
)}
>
<Icon
className="icon"
icon="edit-full-btn"
/>
</div>
<div
onClick={this.delAction.bind(
this,
eventKey,
action,
actionIndex
)}
>
<Icon
className="icon"
icon="delete-easy-btn"
/>
</div>
</div>
</div>
</div>
{this.renderDesc(action)}
</li>
);
})}
{this.renderDesc(action)}
</li>
);
}
)}
</ul>
) : null}
</li>

View File

@ -361,6 +361,7 @@ setSchemaTpl(
useSelectMode?: boolean; // 是否使用Select选择设置模式需要确保 rendererSchema.options 不为 undefined
valueType?: string; // 用于设置期望数值类型
visibleOn?: string; // 用于控制显示的表达式
evalMode?: boolean; // 为false时则会用 ${这里面才是表达式} 包裹变量
}) => {
let curRendererSchema = config?.rendererSchema;
if (
@ -388,7 +389,8 @@ setSchemaTpl(
rendererSchema: curRendererSchema,
rendererWrapper: config?.rendererWrapper,
needDeleteValue: config?.needDeleteValue,
valueType: config?.valueType
valueType: config?.valueType,
evalMode: config?.evalMode ?? false // 默认需要${}包裹变量
}
]
};
@ -402,7 +404,8 @@ setSchemaTpl(
rendererWrapper: config?.rendererWrapper,
needDeleteValue: config?.needDeleteValue,
valueType: config?.valueType,
visibleOn: config?.visibleOn
visibleOn: config?.visibleOn,
evalMode: config?.evalMode ?? false // 默认需要${}包裹变量
};
}
}
@ -609,6 +612,7 @@ setSchemaTpl(
return {
title: '状态',
body: [
getSchemaTpl('newVisible'),
getSchemaTpl('hidden'),
config?.readonly ? getSchemaTpl('readonly') : null,
config?.disabled || config?.isFormItem
@ -663,7 +667,7 @@ setSchemaTpl('disabled', {
label: '禁用',
mode: 'normal',
name: 'disabled',
expressioName: 'disabledOn'
expressionName: 'disabledOn'
});
setSchemaTpl('readonly', {
@ -671,7 +675,7 @@ setSchemaTpl('readonly', {
label: '只读',
mode: 'normal',
name: 'readOnly',
expressioName: 'readOnlyOn'
expressionName: 'readOnlyOn'
});
setSchemaTpl('visible', {
@ -679,7 +683,18 @@ setSchemaTpl('visible', {
label: '可见',
mode: 'normal',
name: 'visible',
expressioName: 'visibleOn'
expressionName: 'visibleOn'
});
// 新版配置面板兼容 [可见] 状态
setSchemaTpl('newVisible', {
type: 'ae-StatusControl',
label: '可见',
mode: 'normal',
name: 'visible',
expressionName: 'visibleOn',
visibleOn:"data.visible || data.visible === false || data.visibleOn !== undefined"
});
setSchemaTpl('hidden', {
@ -687,7 +702,7 @@ setSchemaTpl('hidden', {
label: '隐藏',
mode: 'normal',
name: 'hidden',
expressioName: 'hiddenOn'
expressionName: 'hiddenOn'
});
setSchemaTpl('maximum', {
@ -768,7 +783,8 @@ setSchemaTpl('richText', {
buttons: [
'paragraphFormat',
'quote',
'color',
'textColor',
'backgroundColor',
'|',
'bold',
'italic',
@ -1014,39 +1030,25 @@ setSchemaTpl('app-page', {
});
setSchemaTpl('app-page-args', {
type: 'combo',
type: 'ae-DataMappingControl',
name: 'params',
label: '页面参数',
multiple: true,
mode: 'horizontal',
items: [
{
name: 'key',
placeholder: '参数名',
type: 'input-text',
mode: 'inline',
size: 'xs'
},
{
name: 'val',
placeholder: '参数值',
type: 'input-formula',
variableMode: 'tabs',
size: 'xs',
variables: '${variables}'
}
]
schema: {"type": "object", "properties":{}},
mode: 'horizontal'
});
setSchemaTpl('iconLink', (schema: {name: 'icon' | 'rightIcon', visibleOn: boolean}) => {
const {name, visibleOn} = schema;
return {
name: name,
visibleOn,
label: '图标',
type: 'icon-picker',
placeholder: '点击选择图标',
clearable: true,
description: ''
setSchemaTpl(
'iconLink',
(schema: {name: 'icon' | 'rightIcon'; visibleOn: boolean}) => {
const {name, visibleOn} = schema;
return {
name: name,
visibleOn,
label: '图标',
type: 'icon-picker',
placeholder: '点击选择图标',
clearable: true,
description: ''
};
}
});
);

View File

@ -128,7 +128,7 @@ setSchemaTpl('multiple', (schema: any = {}) => {
getSchemaTpl('joinValues'),
getSchemaTpl('delimiter'),
getSchemaTpl('extractValue'),
...[schema.body || []]
...(schema?.body || [])
]
}
};

View File

@ -1,270 +0,0 @@
import {
BaseEventContext,
EditorManager,
RendererPluginAction
} from 'amis-editor-core';
import {filterTree, mapTree} from 'amis';
import ACTION_TYPE_TREE from './renderer/event-control/actions';
import {ActionConfig, ComponentInfo} from './renderer/event-control/types';
import {
COMMON_ACTION_SCHEMA_MAP,
findActionNode,
findSubActionNode,
FORMITEM_CMPTS,
getActionType,
getPropOfAcion,
hasActionType
} from './renderer/event-control/helper';
/**
*
*/
export const getEventControlConfig = (
manager: EditorManager,
context: BaseEventContext
) => {
// 通用动作配置
const commonActions =
manager?.config.actionOptions?.customActionGetter?.(manager);
// 动作树
const actionTree = manager?.config.actionOptions?.actionTreeGetter
? manager?.config.actionOptions?.actionTreeGetter(ACTION_TYPE_TREE(manager))
: ACTION_TYPE_TREE(manager);
const commonActionConfig = {
...COMMON_ACTION_SCHEMA_MAP,
...commonActions
};
return {
showOldEntry:
manager?.config.actionOptions?.showOldEntry !== false &&
(!!context.schema.actionType ||
['submit', 'reset'].includes(context.schema.type)),
actions: manager?.pluginActions,
events: manager?.pluginEvents,
actionTree,
commonActions,
owner: '',
addBroadcast: manager?.addBroadcast,
removeBroadcast: manager?.removeBroadcast,
getContextSchemas: async (id?: string, withoutSuper?: boolean) => {
const dataSchema = await manager.getContextSchemas(
id ?? context!.id,
withoutSuper
);
// 存在指定id时只需要当前层上下文
if (id) {
return dataSchema;
}
return manager.dataSchema;
},
getComponents: (action: RendererPluginAction) => {
const actionType = action.actionType!;
const components = filterTree(
mapTree(
manager?.store?.outline ?? [],
(item: any) => {
const schema = manager?.store?.getSchema(item.id);
return {
id: item.id,
label: item.label,
value: schema?.id ?? item.id,
type: schema?.type ?? item.type,
schema,
disabled: !!item.region,
children: item?.children
};
},
1,
true
),
node => {
const actions = manager?.pluginActions[node.type];
let isSupport = false;
if (typeof action.supportComponents === 'string') {
isSupport =
action.supportComponents === '*' ||
action.supportComponents === node.type;
} else if (Array.isArray(action.supportComponents)) {
isSupport = action.supportComponents.includes(node.type);
}
if (['reload', 'setValue'].includes(actionType)) {
isSupport = hasActionType(actionType, actions);
}
if (actionType === 'component' && !actions?.length) {
node.disabled = true;
}
if (isSupport) {
return true;
} else if (!isSupport && !!node.children?.length) {
node.disabled = true;
return true;
}
return false;
},
1,
true
);
return components;
},
actionConfigInitFormatter: (action: ActionConfig) => {
let config = {...action};
if (
['setValue', 'url', 'link'].includes(action.actionType) &&
action.args
) {
const prop = action.actionType === 'setValue' ? 'value' : 'params';
!config.args && (config.args = {});
if (Array.isArray(action.args[prop])) {
config.args[prop] = action.args[prop].reduce(
(arr: any, valueItem: any, index: number) => {
if (!arr[index]) {
arr[index] = {};
}
arr[index].item = Object.entries(valueItem).map(([key, val]) => ({
key,
val
}));
return arr;
},
[]
);
} else if (typeof action.args[prop] === 'object') {
config.args[prop] = Object.keys(action.args[prop]).map(key => ({
key,
val: action.args?.[prop][key]
}));
} else if (
action.actionType === 'setValue' &&
typeof action.args[prop] === 'string'
) {
config.args['valueInput'] = config.args['value'];
delete config.args?.value;
}
}
// 获取动作专有配置参数
const innerArgs: any = getPropOfAcion(
action,
'innerArgs',
actionTree,
manager.pluginActions,
commonActions
);
// 还原args为可视化配置结构(args + addOnArgs)
if (config.args) {
if (innerArgs) {
let tmpArgs = {};
config.addOnArgs = [];
Object.keys(config.args).forEach(key => {
// 筛选出附加配置参数
if (!innerArgs.includes(key)) {
config.addOnArgs = [
...config.addOnArgs,
{
key: key,
val: config.args?.[key]
}
];
} else {
tmpArgs = {
...tmpArgs,
[key]: config.args?.[key]
};
}
});
config.args = tmpArgs;
}
}
// 获取左侧命中的动作节点
const hasSubActionNode = findSubActionNode(actionTree, action.actionType);
return {
...config,
actionType: getActionType(action, hasSubActionNode)
};
},
actionConfigSubmitFormatter: (config: ActionConfig) => {
let action = {...config};
action.__title = findActionNode(
actionTree,
config.actionType
)?.actionLabel;
// 修正动作名称
if (config.actionType === 'component') {
// 标记一下组件特性动作
action.__isCmptAction = true;
action.actionType = config.__cmptActionType;
}
const hasSubActionNode = findSubActionNode(
actionTree,
config.__cmptActionType
);
if (hasSubActionNode) {
// 修正动作
action.actionType = config.__cmptActionType;
}
// 合并附加的动作参数
if (config.addOnArgs) {
config.addOnArgs.forEach((args: any) => {
action.args = action.args ?? {};
action.args = {
...action.args,
[args.key]: args.val
};
});
delete action.addOnArgs;
}
// 转换下格式
if (['setValue', 'url', 'link'].includes(action.actionType)) {
const propName = action.actionType === 'setValue' ? 'value' : 'params';
if (Array.isArray(config.args?.[propName])) {
action.args = action.args ?? {};
if (action.__rendererName === 'combo') {
// combo特殊处理
let tempArr: any = [];
config.args?.[propName].forEach((valueItem: any, index: number) => {
valueItem.item.forEach((item: any) => {
if (!tempArr[index]) {
tempArr[index] = {};
}
tempArr[index][item.key] = item.val;
});
});
action.args = {
...action.args,
[propName]: tempArr
};
} else {
let tmpObj: any = {};
config.args?.[propName].forEach((item: any) => {
tmpObj[item.key] = item.val;
});
action.args = {
...action.args,
[propName]: tmpObj
};
}
} else if (action.actionType === 'setValue') {
// 处理变量赋值非数组的情况
action.args = {
...action.args,
value: config.args?.['valueInput']
};
}
}
delete action.config;
return action;
}
};
};