mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2025-12-15 05:36:39 +00:00
Merge branch 'feat/joint-editor' of gitlab.alibaba-inc.com:ali-lowcode/ali-lowcode-engine into feat/joint-editor
This commit is contained in:
commit
a5821af405
@ -314,7 +314,10 @@ export interface LibraryMap {
|
|||||||
function buildComponents(libraryMap: LibraryMap, componentsMap: { [componentName: string]: NpmInfo }) {
|
function buildComponents(libraryMap: LibraryMap, componentsMap: { [componentName: string]: NpmInfo }) {
|
||||||
const components: any = {};
|
const components: any = {};
|
||||||
Object.keys(componentsMap).forEach(componentName => {
|
Object.keys(componentsMap).forEach(componentName => {
|
||||||
components[componentName] = findComponent(libraryMap, componentName, componentsMap[componentName]);
|
const component = findComponent(libraryMap, componentName, componentsMap[componentName]);
|
||||||
|
if (component) {
|
||||||
|
components[componentName] = component;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
return components;
|
return components;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,6 +13,44 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
|
Page: {
|
||||||
|
componentName: 'Page',
|
||||||
|
title: '页面',
|
||||||
|
configure: {
|
||||||
|
events: {
|
||||||
|
supportedLifecycles: [
|
||||||
|
{
|
||||||
|
description: '初始化时',
|
||||||
|
name: 'constructor',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: '装载后',
|
||||||
|
name: 'componentDidMount',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: '更新时',
|
||||||
|
name: 'componentDidMount',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: '卸载时',
|
||||||
|
name: 'componentWillUnmount',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
component: {
|
||||||
|
isContainer: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Div: {
|
||||||
|
componentName: 'Div',
|
||||||
|
title: '容器',
|
||||||
|
configure: {
|
||||||
|
component: {
|
||||||
|
isContainer: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
Button: {
|
Button: {
|
||||||
componentName: 'Button',
|
componentName: 'Button',
|
||||||
title: '按钮',
|
title: '按钮',
|
||||||
@ -164,7 +202,15 @@ export default {
|
|||||||
name: 'children',
|
name: 'children',
|
||||||
propType: 'node'
|
propType: 'node'
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
configure: {
|
||||||
|
component: {
|
||||||
|
isContainer: true,
|
||||||
|
nestingRule: {
|
||||||
|
childWhitelist: 'Button'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
Input: {
|
Input: {
|
||||||
componentName: 'Input',
|
componentName: 'Input',
|
||||||
@ -446,7 +492,12 @@ export default {
|
|||||||
propType: 'bool',
|
propType: 'bool',
|
||||||
description: '是否开启预览态'
|
description: '是否开启预览态'
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
configure: {
|
||||||
|
component: {
|
||||||
|
isContainer: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
'Form.Item': {
|
'Form.Item': {
|
||||||
componentName: 'Form.Item',
|
componentName: 'Form.Item',
|
||||||
@ -743,7 +794,15 @@ export default {
|
|||||||
propType: 'func',
|
propType: 'func',
|
||||||
description: '预览态模式下渲染的内容\n@param {any} value 根据包裹的组件的 value 类型而决定'
|
description: '预览态模式下渲染的内容\n@param {any} value 根据包裹的组件的 value 类型而决定'
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
configure: {
|
||||||
|
component: {
|
||||||
|
isContainer: true,
|
||||||
|
nestingRule: {
|
||||||
|
parentWhitelist: 'Form'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
NumberPicker: {
|
NumberPicker: {
|
||||||
componentName: 'NumberPicker',
|
componentName: 'NumberPicker',
|
||||||
@ -1131,7 +1190,15 @@ export default {
|
|||||||
name: 'locale',
|
name: 'locale',
|
||||||
propType: 'object'
|
propType: 'object'
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
configure: {
|
||||||
|
component: {
|
||||||
|
isContainer: true,
|
||||||
|
nestingRule: {
|
||||||
|
childWhitelist: 'Select.Option'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
'Select.Option': {
|
'Select.Option': {
|
||||||
componentName: 'Select.Option',
|
componentName: 'Select.Option',
|
||||||
@ -1162,7 +1229,15 @@ export default {
|
|||||||
name: 'children',
|
name: 'children',
|
||||||
propType: 'any'
|
propType: 'any'
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
configure: {
|
||||||
|
component: {
|
||||||
|
isContainer: true,
|
||||||
|
nestingRule: {
|
||||||
|
parentWhitelist: 'Select'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
componentList: [
|
componentList: [
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
import { DatePicker, Input, Radio, Select, Switch } from '@alifd/next';
|
import { DatePicker, Input, Radio, Select, Switch, NumberPicker } from '@alifd/next';
|
||||||
import NumberSetter from '../../../plugin-setters/src/number-setter';
|
|
||||||
import ExpressionSetter from '../../../plugin-setters/src/expression-setter';
|
import ExpressionSetter from '../../../plugin-setters/src/expression-setter';
|
||||||
import MixinSetter from '../../../plugin-setters/src/mixin-setter';
|
import MixinSetter from '../../../plugin-setters/src/mixin-setter';
|
||||||
import EventsSetter from '../../../plugin-settings/src/builtin-setters/events-setter'
|
import EventsSetter from '../../../plugin-setters/src/events-setter';
|
||||||
import { registerSetter } from '../../../plugin-settings/src';
|
import { registerSetter } from '../../../plugin-settings/src';
|
||||||
import { createElement } from 'react';
|
import { createElement } from 'react';
|
||||||
|
|
||||||
@ -17,17 +16,20 @@ registerSetter('ClassNameSetter', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
registerSetter('EventsSetter', EventsSetter);
|
registerSetter('EventsSetter', EventsSetter);
|
||||||
|
registerSetter('StringSetter', { component: Input, defaultProps: { placeholder: '请输入' } });
|
||||||
registerSetter('StringSetter', { component: Input, props: { placeholder: '请输入' } });
|
registerSetter('NumberSetter', NumberPicker);
|
||||||
|
|
||||||
registerSetter('NumberSetter', NumberSetter as any);
|
|
||||||
|
|
||||||
registerSetter('StringSetter', { component: Input, props: { placeholder: '请输入' } });
|
|
||||||
registerSetter('ExpressionSetter', ExpressionSetter);
|
registerSetter('ExpressionSetter', ExpressionSetter);
|
||||||
registerSetter('MixinSetter', MixinSetter);
|
registerSetter('MixinSetter', MixinSetter);
|
||||||
registerSetter('BoolSetter', Switch);
|
registerSetter('BoolSetter', Switch);
|
||||||
registerSetter('RadioGroupSetter', Radio.RadioGroup);
|
registerSetter('RadioGroupSetter', {
|
||||||
|
component: Radio.Group,
|
||||||
|
defaultProps: {
|
||||||
|
shape: 'button'
|
||||||
|
}
|
||||||
|
});
|
||||||
registerSetter('SelectSetter', Select);
|
registerSetter('SelectSetter', Select);
|
||||||
|
|
||||||
|
// suggest: 做成 StringSetter 的一个参数,
|
||||||
registerSetter('TextAreaSetter', Input.TextArea);
|
registerSetter('TextAreaSetter', Input.TextArea);
|
||||||
registerSetter('DateSetter', DatePicker);
|
registerSetter('DateSetter', DatePicker);
|
||||||
registerSetter('DateYearSetter', DatePicker.YearPicker);
|
registerSetter('DateYearSetter', DatePicker.YearPicker);
|
||||||
|
|||||||
@ -34,7 +34,8 @@ export default class Mixin extends PureComponent {
|
|||||||
};
|
};
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
locale: 'zh-CN',
|
locale: 'zh-CN',
|
||||||
messages: zhCN
|
messages: zhCN,
|
||||||
|
types: ['StringSetter', 'ExpressionSetter', 'NumberSetter', 'BoolSetter', 'SelectSetter', 'RadioGroupSetter'],
|
||||||
};
|
};
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import Node from '../../designer/src/designer/document/node/node';
|
|||||||
import ArraySetter from './builtin-setters/array-setter';
|
import ArraySetter from './builtin-setters/array-setter';
|
||||||
import ObjectSetter from './builtin-setters/object-setter';
|
import ObjectSetter from './builtin-setters/object-setter';
|
||||||
import './register-transducer';
|
import './register-transducer';
|
||||||
|
import { TipContainer } from './tip';
|
||||||
|
|
||||||
export default class SettingsMainView extends Component {
|
export default class SettingsMainView extends Component {
|
||||||
private main: SettingsMain;
|
private main: SettingsMain;
|
||||||
@ -42,10 +43,10 @@ export default class SettingsMainView extends Component {
|
|||||||
|
|
||||||
let node: Node | null = this.main.nodes[0]!;
|
let node: Node | null = this.main.nodes[0]!;
|
||||||
const items = [];
|
const items = [];
|
||||||
let l = 4;
|
let l = 3;
|
||||||
while (l-- > 0 && node) {
|
while (l-- > 0 && node) {
|
||||||
const props =
|
const props =
|
||||||
l === 3
|
l === 2
|
||||||
? {}
|
? {}
|
||||||
: {
|
: {
|
||||||
onMouseOver: hoverNode.bind(null, node, true),
|
onMouseOver: hoverNode.bind(null, node, true),
|
||||||
@ -101,6 +102,7 @@ export default class SettingsMainView extends Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="lc-settings-main">
|
<div className="lc-settings-main">
|
||||||
|
<TipContainer />
|
||||||
<Tab
|
<Tab
|
||||||
navClassName="lc-settings-tabs"
|
navClassName="lc-settings-tabs"
|
||||||
animation={false}
|
animation={false}
|
||||||
|
|||||||
@ -535,7 +535,7 @@ export class SettingsMain implements SettingTarget {
|
|||||||
let theSame = true;
|
let theSame = true;
|
||||||
for (let i = 1; i < l; i++) {
|
for (let i = 1; i < l; i++) {
|
||||||
const other = this.nodes[i];
|
const other = this.nodes[i];
|
||||||
if ((other as any).componentType !== meta) {
|
if (other.componentMeta !== meta) {
|
||||||
theSame = false;
|
theSame = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,7 +11,13 @@ import { SetterType, FieldConfig, SettingField } from './main';
|
|||||||
import { registerMetadataTransducer } from '../../designer/src/designer/component-meta';
|
import { registerMetadataTransducer } from '../../designer/src/designer/component-meta';
|
||||||
|
|
||||||
export function propConfigToFieldConfig(propConfig: PropConfig): FieldConfig {
|
export function propConfigToFieldConfig(propConfig: PropConfig): FieldConfig {
|
||||||
|
const { name, description } = propConfig;
|
||||||
|
const title = {
|
||||||
|
label: description?.slice(0, 10) || name,
|
||||||
|
tip: description ? `${name} | ${description}` : undefined,
|
||||||
|
};
|
||||||
return {
|
return {
|
||||||
|
title,
|
||||||
...propConfig,
|
...propConfig,
|
||||||
setter: propTypeToSetter(propConfig.propType),
|
setter: propTypeToSetter(propConfig.propType),
|
||||||
};
|
};
|
||||||
@ -55,7 +61,7 @@ export function propTypeToSetter(propType: PropType): SetterType {
|
|||||||
value,
|
value,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
const componentName = dataSource.length > 4 ? 'SelectSetter' : 'RadioSetter';
|
const componentName = dataSource.length > 4 ? 'SelectSetter' : 'RadioGroupSetter';
|
||||||
return {
|
return {
|
||||||
componentName,
|
componentName,
|
||||||
props: { dataSource },
|
props: { dataSource },
|
||||||
@ -135,7 +141,8 @@ export function propTypeToSetter(propType: PropType): SetterType {
|
|||||||
return {
|
return {
|
||||||
componentName: 'MixinSetter',
|
componentName: 'MixinSetter',
|
||||||
props: {
|
props: {
|
||||||
setters: (propType as OneOfType).value.map(item => propTypeToSetter(item)),
|
// TODO:
|
||||||
|
// setters: (propType as OneOfType).value.map(item => propTypeToSetter(item)),
|
||||||
},
|
},
|
||||||
isRequired,
|
isRequired,
|
||||||
};
|
};
|
||||||
@ -163,21 +170,23 @@ registerMetadataTransducer(metadata => {
|
|||||||
return metadata as any;
|
return metadata as any;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { configure = {} } = metadata;
|
||||||
|
|
||||||
if (!metadata.props) {
|
if (!metadata.props) {
|
||||||
return {
|
return {
|
||||||
...metadata,
|
...metadata,
|
||||||
configure: {
|
configure: {
|
||||||
props: metadata.configure && Array.isArray(metadata.configure) ? metadata.configure : [],
|
...configure,
|
||||||
|
props: [],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const { configure = {} } = metadata;
|
|
||||||
const { props = [], component = {}, events = {}, styles = {} } = configure;
|
const { props = [], component = {}, events = {}, styles = {} } = configure;
|
||||||
const supportEvents: string[] | null = (events as any).supportEvents ? null : [];
|
const supportedEvents: any[] | null = (events as any).supportedEvents ? null : [];
|
||||||
|
|
||||||
metadata.props.forEach(prop => {
|
metadata.props.forEach(prop => {
|
||||||
const { name, propType } = prop;
|
const { name, propType, description } = prop;
|
||||||
if (
|
if (
|
||||||
name === 'children' &&
|
name === 'children' &&
|
||||||
(component.isContainer || propType === 'node' || propType === 'element' || propType === 'any')
|
(component.isContainer || propType === 'node' || propType === 'element' || propType === 'any')
|
||||||
@ -189,9 +198,12 @@ registerMetadataTransducer(metadata => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (EVENT_RE.test(name) && (propType === 'func' || propType === 'any')) {
|
if (EVENT_RE.test(name) && (propType === 'func' || propType === 'any')) {
|
||||||
if (supportEvents) {
|
if (supportedEvents) {
|
||||||
supportEvents.push(name);
|
supportedEvents.push({
|
||||||
(events as any).supportEvents = supportEvents;
|
name,
|
||||||
|
description,
|
||||||
|
});
|
||||||
|
(events as any).supportedEvents = supportedEvents;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -279,11 +291,12 @@ registerMetadataTransducer(metadata => {
|
|||||||
setter: {
|
setter: {
|
||||||
componentName: 'MixinSetter',
|
componentName: 'MixinSetter',
|
||||||
props: {
|
props: {
|
||||||
|
// TODO:
|
||||||
setters: [
|
setters: [
|
||||||
{
|
{
|
||||||
componentName: 'StringSetter',
|
componentName: 'StringSetter',
|
||||||
props: {
|
props: {
|
||||||
// todo:
|
// TODO: textarea mode
|
||||||
multiline: true,
|
multiline: true,
|
||||||
},
|
},
|
||||||
initialValue: '',
|
initialValue: '',
|
||||||
@ -304,17 +317,10 @@ registerMetadataTransducer(metadata => {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const { props, events, styles } = configure as any;
|
const { props, events = {}, styles } = configure as any;
|
||||||
let eventsDefinition: any;
|
const isRoot: boolean = componentName === 'Page' || componentName === 'Component';
|
||||||
let isRoot: boolean = false;
|
const eventsDefinition: any[] = [];
|
||||||
if (componentName === 'Page' || componentName === 'Component') {
|
const supportedLifecycles = events.supportedLifecycles || (isRoot ? [
|
||||||
isRoot = true;
|
|
||||||
// 平台配置的,一般只有根节点才会配置
|
|
||||||
eventsDefinition = [
|
|
||||||
{
|
|
||||||
type: 'lifeCycleEvent',
|
|
||||||
title: '生命周期',
|
|
||||||
list: [
|
|
||||||
{
|
{
|
||||||
description: '初始化时',
|
description: '初始化时',
|
||||||
name: 'constructor',
|
name: 'constructor',
|
||||||
@ -331,17 +337,20 @@ registerMetadataTransducer(metadata => {
|
|||||||
description: '卸载时',
|
description: '卸载时',
|
||||||
name: 'componentWillUnmount',
|
name: 'componentWillUnmount',
|
||||||
},
|
},
|
||||||
],
|
] : null);
|
||||||
},
|
if (supportedLifecycles) {
|
||||||
];
|
eventsDefinition.push({
|
||||||
} else {
|
type: 'lifeCycleEvent',
|
||||||
eventsDefinition = [
|
title: '生命周期',
|
||||||
{
|
list: supportedLifecycles.map((event: any) => (typeof event === 'string' ? { name: event } : event)),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (events.supportedEvents) {
|
||||||
|
eventsDefinition.push({
|
||||||
type: 'events',
|
type: 'events',
|
||||||
title: '事件',
|
title: '事件',
|
||||||
list: (events?.supportEvents || []).map((event: any) => (typeof event === 'string' ? { name: event } : event)),
|
list: (events.supportedEvents || []).map((event: any) => (typeof event === 'string' ? { name: event } : event)),
|
||||||
},
|
});
|
||||||
];
|
|
||||||
}
|
}
|
||||||
// 通用设置
|
// 通用设置
|
||||||
const propsGroup = props || [];
|
const propsGroup = props || [];
|
||||||
@ -402,7 +411,7 @@ registerMetadataTransducer(metadata => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eventsDefinition) {
|
if (eventsDefinition.length > 0) {
|
||||||
combined.push({
|
combined.push({
|
||||||
name: '#events',
|
name: '#events',
|
||||||
title: '事件',
|
title: '事件',
|
||||||
@ -416,15 +425,14 @@ registerMetadataTransducer(metadata => {
|
|||||||
definition: eventsDefinition,
|
definition: eventsDefinition,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
getValue(field: SettingField, val?: any[]) {
|
getValue(field: SettingField, val?: any[]) {
|
||||||
|
// todo:
|
||||||
return val;
|
return val;
|
||||||
},
|
},
|
||||||
|
|
||||||
setValue(field: SettingField, eventDataList: any[]) {
|
setValue(field: SettingField, eventDataList: any[]) {
|
||||||
|
// todo:
|
||||||
return;
|
return;
|
||||||
// console.info(eventDataList);
|
|
||||||
// field.parent.setPropValue('eventDataList', eventDataList);
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -432,7 +440,6 @@ registerMetadataTransducer(metadata => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isRoot) {
|
if (isRoot) {
|
||||||
// todo...
|
|
||||||
combined.push({
|
combined.push({
|
||||||
name: '#advanced',
|
name: '#advanced',
|
||||||
title: '高级',
|
title: '高级',
|
||||||
@ -458,6 +465,7 @@ registerMetadataTransducer(metadata => {
|
|||||||
setter: {
|
setter: {
|
||||||
componentName: 'MixinSetter',
|
componentName: 'MixinSetter',
|
||||||
props: {
|
props: {
|
||||||
|
// TODO:
|
||||||
setters: [
|
setters: [
|
||||||
{
|
{
|
||||||
componentName: 'JSONSetter',
|
componentName: 'JSONSetter',
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import './title.less';
|
|||||||
|
|
||||||
export interface IconConfig {
|
export interface IconConfig {
|
||||||
type: string;
|
type: string;
|
||||||
size?: number | "small" | "xxs" | "xs" | "medium" | "large" | "xl" | "xxl" | "xxxl" | "inherit";
|
size?: number | 'small' | 'xxs' | 'xs' | 'medium' | 'large' | 'xl' | 'xxl' | 'xxxl' | 'inherit';
|
||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,7 +51,12 @@ export default class Title extends Component<{ title: TitleContent; onClick?: ()
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classNames('lc-title', title.className)} onClick={this.props.onClick}>
|
<div
|
||||||
|
className={classNames('lc-title', title.className, {
|
||||||
|
'has-tip': !!tip,
|
||||||
|
})}
|
||||||
|
onClick={this.props.onClick}
|
||||||
|
>
|
||||||
{icon ? <div className="lc-title-icon">{icon}</div> : null}
|
{icon ? <div className="lc-title-icon">{icon}</div> : null}
|
||||||
{title.label ? <span className="lc-title-label">{title.label}</span> : null}
|
{title.label ? <span className="lc-title-label">{title.label}</span> : null}
|
||||||
{tip}
|
{tip}
|
||||||
|
|||||||
@ -7,6 +7,13 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
}
|
}
|
||||||
|
&.has-tip {
|
||||||
|
cursor: help;
|
||||||
|
text-decoration-line: underline;
|
||||||
|
text-decoration-style: dashed;
|
||||||
|
text-decoration-color: rgba(31, 56, 88, .3);
|
||||||
|
}
|
||||||
|
padding: 2px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.actived .lc-title {
|
.actived .lc-title {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user