mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2025-12-14 21:12:53 +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
63c99bfaec
@ -8,17 +8,17 @@ import OffsetObserver from '../../../../designer/helper/offset-observer';
|
|||||||
import Node from '../../../../designer/document/node/node';
|
import Node from '../../../../designer/document/node/node';
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
export class OutlineSelectingInstance extends Component<{ observed: OffsetObserver; highlight?: boolean }> {
|
export class OutlineSelectingInstance extends Component<{
|
||||||
shouldComponentUpdate() {
|
observed: OffsetObserver;
|
||||||
return false;
|
highlight?: boolean;
|
||||||
}
|
dragging?: boolean;
|
||||||
|
}> {
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
this.props.observed.purge();
|
this.props.observed.purge();
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { observed, highlight } = this.props;
|
const { observed, highlight, dragging } = this.props;
|
||||||
if (!observed.hasOffset) {
|
if (!observed.hasOffset) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -33,6 +33,7 @@ export class OutlineSelectingInstance extends Component<{ observed: OffsetObserv
|
|||||||
|
|
||||||
const className = classNames('lc-outlines lc-outlines-selecting', {
|
const className = classNames('lc-outlines lc-outlines-selecting', {
|
||||||
highlight,
|
highlight,
|
||||||
|
dragging,
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -51,6 +52,10 @@ export class OutlineSelectingForNode extends Component<{ node: Node }> {
|
|||||||
return this.context;
|
return this.context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get dragging(): boolean {
|
||||||
|
return this.host.designer.dragon.dragging;
|
||||||
|
}
|
||||||
|
|
||||||
@computed get instances() {
|
@computed get instances() {
|
||||||
return this.host.getComponentInstances(this.props.node);
|
return this.host.getComponentInstances(this.props.node);
|
||||||
}
|
}
|
||||||
@ -77,7 +82,7 @@ export class OutlineSelectingForNode extends Component<{ node: Node }> {
|
|||||||
if (!observed) {
|
if (!observed) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return <OutlineSelectingInstance key={observed.id} observed={observed} />;
|
return <OutlineSelectingInstance key={observed.id} dragging={this.dragging} observed={observed} />;
|
||||||
})}
|
})}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
@ -92,12 +97,17 @@ export class OutlineSelecting extends Component {
|
|||||||
return this.context;
|
return this.context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get dragging(): boolean {
|
||||||
|
return this.host.designer.dragon.dragging;
|
||||||
|
}
|
||||||
|
|
||||||
@computed get selecting() {
|
@computed get selecting() {
|
||||||
const doc = this.host.document;
|
const doc = this.host.document;
|
||||||
if (doc.suspensed) {
|
if (doc.suspensed) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return doc.selection.getNodes();
|
const selection = doc.selection;
|
||||||
|
return this.dragging ? selection.getTopNodes() : selection.getNodes();
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldComponentUpdate() {
|
shouldComponentUpdate() {
|
||||||
|
|||||||
@ -22,7 +22,7 @@
|
|||||||
&&-hovering {
|
&&-hovering {
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
border-style: dashed;
|
border-style: dashed;
|
||||||
background: rgba(95, 240, 114, 0.04);
|
background: rgba(0,121,242,.04);
|
||||||
|
|
||||||
&.x-loop {
|
&.x-loop {
|
||||||
border-color: rgba(138, 93, 226, 0.8);
|
border-color: rgba(138, 93, 226, 0.8);
|
||||||
@ -44,6 +44,7 @@
|
|||||||
|
|
||||||
&&-selecting {
|
&&-selecting {
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
|
border-width: 2px;
|
||||||
|
|
||||||
&.x-loop {
|
&.x-loop {
|
||||||
border-color: rgba(147, 112, 219, 1.0);
|
border-color: rgba(147, 112, 219, 1.0);
|
||||||
@ -67,7 +68,6 @@
|
|||||||
&.dragging {
|
&.dragging {
|
||||||
background: rgba(182, 178, 178, 0.8);
|
background: rgba(182, 178, 178, 0.8);
|
||||||
border: none;
|
border: none;
|
||||||
pointer-events: all;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -145,9 +145,6 @@ export class SimulatorHost implements ISimulator<SimulatorProps> {
|
|||||||
readonly scroller = this.designer.createScroller(this.viewport);
|
readonly scroller = this.designer.createScroller(this.viewport);
|
||||||
|
|
||||||
mountViewport(viewport: Element | null) {
|
mountViewport(viewport: Element | null) {
|
||||||
if (!viewport) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.viewport.mount(viewport);
|
this.viewport.mount(viewport);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,10 +171,12 @@ export class SimulatorHost implements ISimulator<SimulatorProps> {
|
|||||||
|
|
||||||
readonly libraryMap: { [key: string]: string } = {};
|
readonly libraryMap: { [key: string]: string } = {};
|
||||||
|
|
||||||
|
private _iframe?: HTMLIFrameElement;
|
||||||
async mountContentFrame(iframe: HTMLIFrameElement | null) {
|
async mountContentFrame(iframe: HTMLIFrameElement | null) {
|
||||||
if (!iframe) {
|
if (!iframe || this._iframe === iframe) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
this._iframe = iframe;
|
||||||
|
|
||||||
this._contentWindow = iframe.contentWindow!;
|
this._contentWindow = iframe.contentWindow!;
|
||||||
|
|
||||||
@ -234,63 +233,88 @@ export class SimulatorHost implements ISimulator<SimulatorProps> {
|
|||||||
|
|
||||||
// TODO: think of lock when edit a node
|
// TODO: think of lock when edit a node
|
||||||
// 事件路由
|
// 事件路由
|
||||||
doc.addEventListener('mousedown', (downEvent: MouseEvent) => {
|
doc.addEventListener(
|
||||||
const nodeInst = this.getNodeInstanceFromElement(downEvent.target as Element);
|
'mousedown',
|
||||||
const node = nodeInst?.node || this.document.rootNode;
|
(downEvent: MouseEvent) => {
|
||||||
const isMulti = downEvent.metaKey || downEvent.ctrlKey;
|
// stop response document focus event
|
||||||
const isLeftButton = downEvent.which === 1 || downEvent.button === 0;
|
downEvent.stopPropagation();
|
||||||
const checkSelect = (e: MouseEvent) => {
|
downEvent.preventDefault();
|
||||||
doc.removeEventListener('mouseup', checkSelect, true);
|
|
||||||
if (!isShaken(downEvent, e)) {
|
|
||||||
const id = node.id;
|
|
||||||
designer.activeTracker.track(node);
|
|
||||||
if (isMulti && !isRootNode(node) && selection.has(id)) {
|
|
||||||
selection.remove(id);
|
|
||||||
} else {
|
|
||||||
selection.select(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (isLeftButton && !isRootNode(node)) {
|
const nodeInst = this.getNodeInstanceFromElement(downEvent.target as Element);
|
||||||
let nodes: Node[] = [node];
|
const node = nodeInst?.node || this.document.rootNode;
|
||||||
let ignoreUpSelected = false;
|
const isMulti = downEvent.metaKey || downEvent.ctrlKey;
|
||||||
// 排除根节点拖拽
|
const isLeftButton = downEvent.which === 1 || downEvent.button === 0;
|
||||||
selection.remove(this.document.rootNode.id);
|
const checkSelect = (e: MouseEvent) => {
|
||||||
if (isMulti) {
|
doc.removeEventListener('mouseup', checkSelect, true);
|
||||||
// multi select mode, directily add
|
if (!isShaken(downEvent, e)) {
|
||||||
if (!selection.has(node.id)) {
|
const id = node.id;
|
||||||
designer.activeTracker.track(node);
|
designer.activeTracker.track(node);
|
||||||
selection.add(node.id);
|
if (isMulti && !isRootNode(node) && selection.has(id)) {
|
||||||
ignoreUpSelected = true;
|
selection.remove(id);
|
||||||
|
} else {
|
||||||
|
selection.select(id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// 获得顶层 nodes
|
};
|
||||||
nodes = selection.getTopNodes();
|
|
||||||
} else if (selection.containsNode(node)) {
|
|
||||||
nodes = selection.getTopNodes();
|
|
||||||
} else {
|
|
||||||
// will clear current selection & select dragment in dragstart
|
|
||||||
}
|
|
||||||
designer.dragon.boost(
|
|
||||||
{
|
|
||||||
type: DragObjectType.Node,
|
|
||||||
nodes,
|
|
||||||
},
|
|
||||||
downEvent,
|
|
||||||
);
|
|
||||||
if (ignoreUpSelected) {
|
|
||||||
// multi select mode has add selected, should return
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
doc.addEventListener('mouseup', checkSelect, true);
|
if (isLeftButton && !isRootNode(node)) {
|
||||||
});
|
let nodes: Node[] = [node];
|
||||||
|
let ignoreUpSelected = false;
|
||||||
|
if (isMulti) {
|
||||||
|
// multi select mode, directily add
|
||||||
|
if (!selection.has(node.id)) {
|
||||||
|
designer.activeTracker.track(node);
|
||||||
|
selection.add(node.id);
|
||||||
|
ignoreUpSelected = true;
|
||||||
|
}
|
||||||
|
selection.remove(this.document.rootNode.id);
|
||||||
|
// 获得顶层 nodes
|
||||||
|
nodes = selection.getTopNodes();
|
||||||
|
} else if (selection.containsNode(node, true)) {
|
||||||
|
nodes = selection.getTopNodes();
|
||||||
|
} else {
|
||||||
|
// will clear current selection & select dragment in dragstart
|
||||||
|
}
|
||||||
|
designer.dragon.boost(
|
||||||
|
{
|
||||||
|
type: DragObjectType.Node,
|
||||||
|
nodes,
|
||||||
|
},
|
||||||
|
downEvent,
|
||||||
|
);
|
||||||
|
if (ignoreUpSelected) {
|
||||||
|
// multi select mode has add selected, should return
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
doc.addEventListener('mouseup', checkSelect, true);
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
|
doc.addEventListener(
|
||||||
|
'click',
|
||||||
|
e => {
|
||||||
|
// stop response document click event
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
// todo: catch link redirect
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
// cause edit
|
// cause edit
|
||||||
doc.addEventListener('dblclick', (e: MouseEvent) => {
|
doc.addEventListener(
|
||||||
// TODO:
|
'dblclick',
|
||||||
});
|
(e: MouseEvent) => {
|
||||||
|
// stop response document dblclick event
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
// todo: quick editing
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private disableHovering?: () => void;
|
private disableHovering?: () => void;
|
||||||
@ -443,18 +467,28 @@ export class SimulatorHost implements ISimulator<SimulatorProps> {
|
|||||||
let last: { x: number; y: number; r: number; b: number } | undefined;
|
let last: { x: number; y: number; r: number; b: number } | undefined;
|
||||||
let computed = false;
|
let computed = false;
|
||||||
const elems = elements.slice();
|
const elems = elements.slice();
|
||||||
|
const commonParent: Element | null = null;
|
||||||
while (true) {
|
while (true) {
|
||||||
if (!rects || rects.length < 1) {
|
if (!rects || rects.length < 1) {
|
||||||
const elem = elems.pop();
|
const elem = elems.pop();
|
||||||
if (!elem) {
|
if (!elem) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
if (!commonParent) {
|
||||||
|
commonParent = elem.parentElement;
|
||||||
|
} else if (elem.parentElement !== commonParent) {
|
||||||
|
continue;
|
||||||
|
}*/
|
||||||
rects = renderer.getClientRects(elem);
|
rects = renderer.getClientRects(elem);
|
||||||
}
|
}
|
||||||
const rect = rects.pop();
|
const rect = rects.pop();
|
||||||
if (!rect) {
|
if (!rect) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (rect.width === 0 && rect.height === 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (!last) {
|
if (!last) {
|
||||||
last = {
|
last = {
|
||||||
x: rect.left,
|
x: rect.left,
|
||||||
@ -677,8 +711,10 @@ export class SimulatorHost implements ISimulator<SimulatorProps> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const target = dropTarget;
|
const target = dropTarget;
|
||||||
const targetInstance = e.targetInstance as ReactInstance;
|
|
||||||
|
|
||||||
|
// FIXME: e.target is #document, etc., does not has e.targetInstance
|
||||||
|
|
||||||
|
const targetInstance = e.targetInstance as ReactInstance;
|
||||||
const parentInstance = this.getClosestNodeInstance(targetInstance, target.id);
|
const parentInstance = this.getClosestNodeInstance(targetInstance, target.id);
|
||||||
const edge = this.computeComponentInstanceRect(parentInstance?.instance as any);
|
const edge = this.computeComponentInstanceRect(parentInstance?.instance as any);
|
||||||
|
|
||||||
|
|||||||
@ -25,7 +25,7 @@ export default class Viewport implements IViewport {
|
|||||||
|
|
||||||
private viewportElement?: Element;
|
private viewportElement?: Element;
|
||||||
mount(viewportElement: Element | null) {
|
mount(viewportElement: Element | null) {
|
||||||
if (!viewportElement) {
|
if (!viewportElement || this.viewportElement === viewportElement) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.viewportElement = viewportElement;
|
this.viewportElement = viewportElement;
|
||||||
@ -54,7 +54,7 @@ export default class Viewport implements IViewport {
|
|||||||
/**
|
/**
|
||||||
* 缩放比例
|
* 缩放比例
|
||||||
*/
|
*/
|
||||||
get scale(): number {
|
@computed get scale(): number {
|
||||||
if (!this.rect || this.contentWidth === AutoFit) {
|
if (!this.rect || this.contentWidth === AutoFit) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -63,14 +63,14 @@ export default class Viewport implements IViewport {
|
|||||||
|
|
||||||
@obx.ref private _contentWidth: number | AutoFit = AutoFit;
|
@obx.ref private _contentWidth: number | AutoFit = AutoFit;
|
||||||
|
|
||||||
get contentHeight(): number | AutoFit {
|
@computed get contentHeight(): number | AutoFit {
|
||||||
if (!this.rect || this.scale === 1) {
|
if (!this.rect || this.scale === 1) {
|
||||||
return AutoFit;
|
return AutoFit;
|
||||||
}
|
}
|
||||||
return this.height / this.scale;
|
return this.height / this.scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
get contentWidth(): number | AutoFit {
|
@computed get contentWidth(): number | AutoFit {
|
||||||
if (!this.rect || (this._contentWidth !== AutoFit && this._contentWidth <= this.width)) {
|
if (!this.rect || (this._contentWidth !== AutoFit && this._contentWidth <= this.width)) {
|
||||||
return AutoFit;
|
return AutoFit;
|
||||||
}
|
}
|
||||||
@ -98,7 +98,7 @@ export default class Viewport implements IViewport {
|
|||||||
return this._scrollTarget;
|
return this._scrollTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
@obx private _scrolling: boolean = false;
|
@obx private _scrolling = false;
|
||||||
get scrolling(): boolean {
|
get scrolling(): boolean {
|
||||||
return this._scrolling;
|
return this._scrolling;
|
||||||
}
|
}
|
||||||
@ -120,6 +120,7 @@ export default class Viewport implements IViewport {
|
|||||||
this._scrolling = false;
|
this._scrolling = false;
|
||||||
}, 80);
|
}, 80);
|
||||||
});
|
});
|
||||||
|
target.addEventListener('resize', () => this.touch());
|
||||||
this._scrollTarget = scrollTarget;
|
this._scrollTarget = scrollTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,9 @@
|
|||||||
--font-size-btn-medium: @fontSize-4;
|
--font-size-btn-medium: @fontSize-4;
|
||||||
--font-size-btn-small: @fontSize-5;
|
--font-size-btn-small: @fontSize-5;
|
||||||
|
|
||||||
--color-brand-light: rgb(102, 188, 92);
|
--color-brand: #006cff;
|
||||||
|
--color-brand-light: #197aff;
|
||||||
|
--color-brand-dark: #0060e5;
|
||||||
--color-icon: rgba(255, 255, 255, 0.8);
|
--color-icon: rgba(255, 255, 255, 0.8);
|
||||||
--color-visited: rgba(179, 182, 201, 0.4);
|
--color-visited: rgba(179, 182, 201, 0.4);
|
||||||
--color-actived: #498ee6;
|
--color-actived: #498ee6;
|
||||||
|
|||||||
@ -61,9 +61,13 @@ export default class Designer {
|
|||||||
this.dragon.onDragstart(e => {
|
this.dragon.onDragstart(e => {
|
||||||
this.hovering.enable = false;
|
this.hovering.enable = false;
|
||||||
const { dragObject } = e;
|
const { dragObject } = e;
|
||||||
if (isDragNodeObject(dragObject) && dragObject.nodes.length === 1) {
|
if (isDragNodeObject(dragObject)) {
|
||||||
// ensure current selecting
|
if (dragObject.nodes.length === 1) {
|
||||||
dragObject.nodes[0].select();
|
// ensure current selecting
|
||||||
|
dragObject.nodes[0].select();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.currentSelection?.clear();
|
||||||
}
|
}
|
||||||
if (this.props?.onDragstart) {
|
if (this.props?.onDragstart) {
|
||||||
this.props.onDragstart(e);
|
this.props.onDragstart(e);
|
||||||
|
|||||||
@ -374,7 +374,7 @@ export default class Node {
|
|||||||
* 2 thisNode before or after otherNode
|
* 2 thisNode before or after otherNode
|
||||||
* 0 thisNode same as otherNode
|
* 0 thisNode same as otherNode
|
||||||
*/
|
*/
|
||||||
comparePosition(otherNode: Node): number {
|
comparePosition(otherNode: Node): PositionNO {
|
||||||
return comparePosition(this, otherNode);
|
return comparePosition(this, otherNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -455,31 +455,37 @@ export function contains(node1: Node, node2: Node): boolean {
|
|||||||
// 8 node1 contained_by node2
|
// 8 node1 contained_by node2
|
||||||
// 2 node1 before or after node2
|
// 2 node1 before or after node2
|
||||||
// 0 node1 same as node2
|
// 0 node1 same as node2
|
||||||
export function comparePosition(node1: Node, node2: Node): number {
|
export enum PositionNO {
|
||||||
|
Contains = 16,
|
||||||
|
ContainedBy = 8,
|
||||||
|
BeforeOrAfter = 2,
|
||||||
|
TheSame = 0,
|
||||||
|
}
|
||||||
|
export function comparePosition(node1: Node, node2: Node): PositionNO {
|
||||||
if (node1 === node2) {
|
if (node1 === node2) {
|
||||||
return 0;
|
return PositionNO.TheSame;
|
||||||
}
|
}
|
||||||
const l1 = node1.zLevel;
|
const l1 = node1.zLevel;
|
||||||
const l2 = node2.zLevel;
|
const l2 = node2.zLevel;
|
||||||
if (l1 === l2) {
|
if (l1 === l2) {
|
||||||
return 2;
|
return PositionNO.BeforeOrAfter;
|
||||||
}
|
}
|
||||||
|
|
||||||
let p: any;
|
let p: any;
|
||||||
if (l1 > l2) {
|
if (l1 < l2) {
|
||||||
p = getZLevelTop(node2, l1);
|
p = getZLevelTop(node2, l1);
|
||||||
if (p && p === node1) {
|
if (p && p === node1) {
|
||||||
return 16;
|
return PositionNO.Contains;
|
||||||
}
|
}
|
||||||
return 2;
|
return PositionNO.BeforeOrAfter;
|
||||||
}
|
}
|
||||||
|
|
||||||
p = getZLevelTop(node1, l2);
|
p = getZLevelTop(node1, l2);
|
||||||
if (p && p === node2) {
|
if (p && p === node2) {
|
||||||
return 8;
|
return PositionNO.ContainedBy;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 2;
|
return PositionNO.BeforeOrAfter;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function insertChild(container: NodeParent, thing: Node | NodeData, at?: number | null, copy?: boolean): Node {
|
export function insertChild(container: NodeParent, thing: Node | NodeData, at?: number | null, copy?: boolean): Node {
|
||||||
|
|||||||
@ -23,7 +23,7 @@ export default class PropStash implements IPropParent {
|
|||||||
}
|
}
|
||||||
const pending: Prop[] = [];
|
const pending: Prop[] = [];
|
||||||
for (const prop of this.space) {
|
for (const prop of this.space) {
|
||||||
if (!prop.isUnset()) {
|
if (!prop.isUnset() && !prop.isVirtual()) {
|
||||||
this.space.delete(prop);
|
this.space.delete(prop);
|
||||||
pending.push(prop);
|
pending.push(prop);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -225,6 +225,10 @@ export default class Prop implements IPropParent {
|
|||||||
return this._type === 'unset';
|
return this._type === 'unset';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isVirtual() {
|
||||||
|
return typeof this.key === 'string' && this.key.charAt(0) === '!';
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: improve this logic
|
// TODO: improve this logic
|
||||||
compare(other: Prop | null): number {
|
compare(other: Prop | null): number {
|
||||||
if (!other || other.isUnset()) {
|
if (!other || other.isUnset()) {
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import Node, { comparePosition } from './node/node';
|
import Node, { comparePosition, PositionNO } from './node/node';
|
||||||
import { obx } from '@recore/obx';
|
import { obx } from '@recore/obx';
|
||||||
import DocumentModel from './document-model';
|
import DocumentModel from './document-model';
|
||||||
import { EventEmitter } from 'events';
|
import { EventEmitter } from 'events';
|
||||||
@ -97,9 +97,12 @@ export class Selection {
|
|||||||
/**
|
/**
|
||||||
* 选区是否包含节点
|
* 选区是否包含节点
|
||||||
*/
|
*/
|
||||||
containsNode(node: Node) {
|
containsNode(node: Node, excludeRoot = false) {
|
||||||
for (const id of this._selected) {
|
for (const id of this._selected) {
|
||||||
const parent = this.doc.getNode(id);
|
const parent = this.doc.getNode(id);
|
||||||
|
if (excludeRoot && parent === this.doc.rootNode) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (parent?.contains(node)) {
|
if (parent?.contains(node)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -124,11 +127,12 @@ export class Selection {
|
|||||||
/**
|
/**
|
||||||
* 获取顶层选区节点, 场景:拖拽时,建立蒙层,只蒙在最上层
|
* 获取顶层选区节点, 场景:拖拽时,建立蒙层,只蒙在最上层
|
||||||
*/
|
*/
|
||||||
getTopNodes() {
|
getTopNodes(includeRoot = false) {
|
||||||
const nodes = [];
|
const nodes = [];
|
||||||
for (const id of this._selected) {
|
for (const id of this._selected) {
|
||||||
const node = this.doc.getNode(id);
|
const node = this.doc.getNode(id);
|
||||||
if (!node) {
|
// 排除根节点
|
||||||
|
if (!node || (!includeRoot && node === this.doc.rootNode)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let i = nodes.length;
|
let i = nodes.length;
|
||||||
@ -136,12 +140,12 @@ export class Selection {
|
|||||||
while (i-- > 0) {
|
while (i-- > 0) {
|
||||||
const n = comparePosition(nodes[i], node);
|
const n = comparePosition(nodes[i], node);
|
||||||
// nodes[i] contains node
|
// nodes[i] contains node
|
||||||
if (n === 16 || n === 0) {
|
if (n === PositionNO.Contains || n === PositionNO.TheSame) {
|
||||||
isTop = false;
|
isTop = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// node contains nodes[i], delete nodes[i]
|
// node contains nodes[i], delete nodes[i]
|
||||||
if (n === 8) {
|
if (n === PositionNO.ContainedBy) {
|
||||||
nodes.splice(i, 1);
|
nodes.splice(i, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,6 +28,10 @@ export default {
|
|||||||
name: 'type',
|
name: 'type',
|
||||||
propType: 'string'
|
propType: 'string'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'onClick',
|
||||||
|
propType: 'func'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'children',
|
name: 'children',
|
||||||
propType: 'string'
|
propType: 'string'
|
||||||
@ -66,6 +70,22 @@ export default {
|
|||||||
{
|
{
|
||||||
name: 'placeholder',
|
name: 'placeholder',
|
||||||
propType: 'string'
|
propType: 'string'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onChange',
|
||||||
|
propType: 'func'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onKeyDown',
|
||||||
|
propType: 'func'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onFocus',
|
||||||
|
propType: 'func'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onBlur',
|
||||||
|
propType: 'func'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -83,7 +103,11 @@ export default {
|
|||||||
{
|
{
|
||||||
name: 'device',
|
name: 'device',
|
||||||
propType: 'string'
|
propType: 'string'
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
name: 'onChange',
|
||||||
|
propType: 'func'
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
'Form.Item': {
|
'Form.Item': {
|
||||||
@ -126,6 +150,26 @@ export default {
|
|||||||
{
|
{
|
||||||
name: 'defaultValue',
|
name: 'defaultValue',
|
||||||
propType: 'number'
|
propType: 'number'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onChange',
|
||||||
|
propType: 'func'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onKeyDown',
|
||||||
|
propType: 'func'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onFocus',
|
||||||
|
propType: 'func'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onBlur',
|
||||||
|
propType: 'func'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onCorrect',
|
||||||
|
propType: 'func'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -151,6 +195,38 @@ export default {
|
|||||||
{
|
{
|
||||||
name: 'placeholder',
|
name: 'placeholder',
|
||||||
propType: 'string'
|
propType: 'string'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onChange',
|
||||||
|
propType: 'func'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onVisibleChange',
|
||||||
|
propType: 'func'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onToggleHighlightItem',
|
||||||
|
propType: 'func'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onSearch',
|
||||||
|
propType: 'func'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onSearchClear',
|
||||||
|
propType: 'func'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onRemove',
|
||||||
|
propType: 'func'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onFocus',
|
||||||
|
propType: 'func'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'onBlur',
|
||||||
|
propType: 'func'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { Component, isValidElement, ReactElement, ReactNode } from 'react';
|
import { Component, isValidElement, ReactElement, ReactNode } from 'react';
|
||||||
import { Radio, Menu, Table, Icon, Dialog } from '@alifd/next';
|
import { Radio, Menu, Table, Icon, Dialog } from '@alifd/next';
|
||||||
|
import {SettingField} from './main';
|
||||||
import nativeEvents from './native-events';
|
import nativeEvents from './native-events';
|
||||||
|
|
||||||
import './style.less';
|
import './style.less';
|
||||||
@ -19,7 +20,10 @@ const DEFINITION_EVENT_TYPE = {
|
|||||||
LIFE_CYCLE_EVENT: 'lifeCycleEvent',
|
LIFE_CYCLE_EVENT: 'lifeCycleEvent',
|
||||||
};
|
};
|
||||||
|
|
||||||
export default class EventsSetter extends Component<{}> {
|
export default class EventsSetter extends Component<{
|
||||||
|
value: any[];
|
||||||
|
onChange: (eventList: any[]) => void;
|
||||||
|
}> {
|
||||||
state = {
|
state = {
|
||||||
showEventList: false,
|
showEventList: false,
|
||||||
eventBtns: [],
|
eventBtns: [],
|
||||||
@ -34,6 +38,7 @@ export default class EventsSetter extends Component<{}> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
|
console.log(this.props);
|
||||||
this.initEventBtns();
|
this.initEventBtns();
|
||||||
this.initEventList();
|
this.initEventList();
|
||||||
}
|
}
|
||||||
@ -42,8 +47,7 @@ export default class EventsSetter extends Component<{}> {
|
|||||||
* 初始化事件按钮
|
* 初始化事件按钮
|
||||||
*/
|
*/
|
||||||
initEventBtns() {
|
initEventBtns() {
|
||||||
const { prop } = this.props;
|
const { definition } = this.props;
|
||||||
const { definition } = prop.extraProps;
|
|
||||||
let isRoot = false;
|
let isRoot = false;
|
||||||
definition.map(item => {
|
definition.map(item => {
|
||||||
if (item.type === DEFINITION_EVENT_TYPE.LIFE_CYCLE_EVENT) {
|
if (item.type === DEFINITION_EVENT_TYPE.LIFE_CYCLE_EVENT) {
|
||||||
@ -73,7 +77,7 @@ export default class EventsSetter extends Component<{}> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
initEventList() {
|
initEventList() {
|
||||||
const { definition } = this.props.prop.extraProps;
|
const { definition } = this.props;
|
||||||
let nativeEventList = [];
|
let nativeEventList = [];
|
||||||
definition.map(item => {
|
definition.map(item => {
|
||||||
if (item.type === DEFINITION_EVENT_TYPE.EVENTS) {
|
if (item.type === DEFINITION_EVENT_TYPE.EVENTS) {
|
||||||
@ -229,14 +233,18 @@ export default class EventsSetter extends Component<{}> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
submitDialog = (relatedEventName: String) => {
|
submitDialog = (relatedEventName: String) => {
|
||||||
const { bindEventName } = this.state;
|
const { bindEventName,eventDataList} = this.state;
|
||||||
const { eventDataList } = this.state;
|
|
||||||
eventDataList.map(item => {
|
eventDataList.map(item => {
|
||||||
if (item.name === bindEventName) {
|
if (item.name === bindEventName) {
|
||||||
item.relatedEventName = relatedEventName;
|
item.relatedEventName = relatedEventName;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
debugger;
|
||||||
|
this.props.onChange(eventDataList);
|
||||||
|
// field.setValue(eventDataList);
|
||||||
|
|
||||||
|
|
||||||
this.closeDialog();
|
this.closeDialog();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -270,7 +278,7 @@ export default class EventsSetter extends Component<{}> {
|
|||||||
{selectType && selectType != EVENT_CONTENTS.NATIVE_EVENT && (
|
{selectType && selectType != EVENT_CONTENTS.NATIVE_EVENT && (
|
||||||
<Menu defaultOpenKeys="sub-menu" className="event-menu" onItemClick={this.onEventMenuClick}>
|
<Menu defaultOpenKeys="sub-menu" className="event-menu" onItemClick={this.onEventMenuClick}>
|
||||||
{showEventList.map((item, index) => (
|
{showEventList.map((item, index) => (
|
||||||
<Item key={item.name} helper={item.title} disabled={item.disabled}>
|
<Item key={item.name} helper={item.description} disabled={item.disabled}>
|
||||||
{item.name}
|
{item.name}
|
||||||
</Item>
|
</Item>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@ -159,7 +159,7 @@ export interface FieldConfig extends FieldExtraProps {
|
|||||||
export class SettingField implements SettingTarget {
|
export class SettingField implements SettingTarget {
|
||||||
readonly isSettingField = true;
|
readonly isSettingField = true;
|
||||||
readonly id = uniqueId('field');
|
readonly id = uniqueId('field');
|
||||||
readonly type: 'field' | 'virtual-field' | 'group';
|
readonly type: 'field' | 'group';
|
||||||
readonly isRequired: boolean = false;
|
readonly isRequired: boolean = false;
|
||||||
readonly isGroup: boolean;
|
readonly isGroup: boolean;
|
||||||
private _name: string | number;
|
private _name: string | number;
|
||||||
@ -193,8 +193,6 @@ export class SettingField implements SettingTarget {
|
|||||||
const c = typeof name === 'string' ? name.substr(0, 1) : '';
|
const c = typeof name === 'string' ? name.substr(0, 1) : '';
|
||||||
if (c === '#') {
|
if (c === '#') {
|
||||||
this.type = 'group';
|
this.type = 'group';
|
||||||
} else if (c === '!') {
|
|
||||||
this.type = 'virtual-field';
|
|
||||||
} else {
|
} else {
|
||||||
this.type = 'field';
|
this.type = 'field';
|
||||||
}
|
}
|
||||||
|
|||||||
@ -178,7 +178,10 @@ registerMetadataTransducer(metadata => {
|
|||||||
|
|
||||||
metadata.props.forEach(prop => {
|
metadata.props.forEach(prop => {
|
||||||
const { name, propType } = prop;
|
const { name, propType } = prop;
|
||||||
if (name === 'children' && (component.isContainer || (propType === 'node' || propType === 'element' || propType === 'any'))) {
|
if (
|
||||||
|
name === 'children' &&
|
||||||
|
(component.isContainer || propType === 'node' || propType === 'element' || propType === 'any')
|
||||||
|
) {
|
||||||
if (component.isContainer !== false) {
|
if (component.isContainer !== false) {
|
||||||
component.isContainer = true;
|
component.isContainer = true;
|
||||||
return;
|
return;
|
||||||
@ -188,6 +191,7 @@ registerMetadataTransducer(metadata => {
|
|||||||
if (EVENT_RE.test(name) && (propType === 'func' || propType === 'any')) {
|
if (EVENT_RE.test(name) && (propType === 'func' || propType === 'any')) {
|
||||||
if (supportEvents) {
|
if (supportEvents) {
|
||||||
supportEvents.push(name);
|
supportEvents.push(name);
|
||||||
|
(events as any).supportEvents = supportEvents;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -209,7 +213,6 @@ registerMetadataTransducer(metadata => {
|
|||||||
props.push(propConfigToFieldConfig(prop));
|
props.push(propConfigToFieldConfig(prop));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...metadata,
|
...metadata,
|
||||||
configure: {
|
configure: {
|
||||||
@ -222,7 +225,7 @@ registerMetadataTransducer(metadata => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
registerMetadataTransducer((metadata) => {
|
registerMetadataTransducer(metadata => {
|
||||||
const { configure = {}, componentName } = metadata;
|
const { configure = {}, componentName } = metadata;
|
||||||
const { component = {} } = configure as any;
|
const { component = {} } = configure as any;
|
||||||
if (!component.nestingRule) {
|
if (!component.nestingRule) {
|
||||||
@ -262,107 +265,133 @@ registerMetadataTransducer((metadata) => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
registerMetadataTransducer((metadata) => {
|
registerMetadataTransducer(metadata => {
|
||||||
const { componentName, configure = {} } = metadata;
|
const { componentName, configure = {} } = metadata;
|
||||||
if (componentName === 'Leaf') {
|
if (componentName === 'Leaf') {
|
||||||
return {
|
return {
|
||||||
...metadata,
|
...metadata,
|
||||||
configure: {
|
configure: {
|
||||||
...configure,
|
...configure,
|
||||||
combined: [{
|
combined: [
|
||||||
name: 'children',
|
{
|
||||||
title: '内容设置',
|
name: 'children',
|
||||||
setter: {
|
title: '内容设置',
|
||||||
componentName: 'MixinSetter',
|
setter: {
|
||||||
props: {
|
componentName: 'MixinSetter',
|
||||||
setters: [{
|
props: {
|
||||||
componentName: 'StringSetter',
|
setters: [
|
||||||
props: {
|
{
|
||||||
// todo:
|
componentName: 'StringSetter',
|
||||||
multiline: true,
|
props: {
|
||||||
},
|
// todo:
|
||||||
initialValue: '',
|
multiline: true,
|
||||||
}, {
|
},
|
||||||
componentName: 'ExpressionSetter',
|
initialValue: '',
|
||||||
initialValue: {
|
},
|
||||||
type: 'JSExpression',
|
{
|
||||||
value: '',
|
componentName: 'ExpressionSetter',
|
||||||
},
|
initialValue: {
|
||||||
}],
|
type: 'JSExpression',
|
||||||
|
value: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}],
|
],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const { props, events, styles } = configure as any;
|
const { props, events, styles } = configure as any;
|
||||||
let supportEvents: any;
|
let eventsDefinition: any;
|
||||||
let isRoot: boolean = false;
|
let isRoot: boolean = false;
|
||||||
if (componentName === 'Page' || componentName === 'Component') {
|
if (componentName === 'Page' || componentName === 'Component') {
|
||||||
isRoot = true;
|
isRoot = true;
|
||||||
supportEvents = [{
|
// 平台配置的,一般只有根节点才会配置
|
||||||
description: '初始化时',
|
eventsDefinition = [
|
||||||
name: 'constructor'
|
{
|
||||||
}, {
|
type: 'lifeCycleEvent',
|
||||||
description: '装载后',
|
title: '生命周期',
|
||||||
name: 'componentDidMount'
|
list: [
|
||||||
}, {
|
{
|
||||||
description: '更新时',
|
description: '初始化时',
|
||||||
name: 'componentDidMount'
|
name: 'constructor',
|
||||||
}, {
|
},
|
||||||
description: '卸载时',
|
{
|
||||||
name: 'componentWillUnmount'
|
description: '装载后',
|
||||||
}]
|
name: 'componentDidMount',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: '更新时',
|
||||||
|
name: 'componentDidMount',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: '卸载时',
|
||||||
|
name: 'componentWillUnmount',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
} else {
|
} else {
|
||||||
supportEvents = (events?.supportEvents || []).map((event: any) => {
|
eventsDefinition = [
|
||||||
return typeof event === 'string' ? {
|
{
|
||||||
name: event,
|
type: 'events',
|
||||||
} : event;
|
title: '事件',
|
||||||
});
|
list: (events?.supportEvents || []).map((event: any) => (typeof event === 'string' ? { name: event } : event)),
|
||||||
|
},
|
||||||
|
];
|
||||||
}
|
}
|
||||||
// 通用设置
|
// 通用设置
|
||||||
const propsGroup = props || [];
|
const propsGroup = props || [];
|
||||||
propsGroup.push({
|
propsGroup.push({
|
||||||
name: '#generals',
|
name: '#generals',
|
||||||
title: '通用',
|
title: '通用',
|
||||||
items: [{
|
items: [
|
||||||
name: 'id',
|
{
|
||||||
title: 'ID',
|
name: 'id',
|
||||||
setter: 'StringSetter',
|
title: 'ID',
|
||||||
}, {
|
setter: 'StringSetter',
|
||||||
name: 'key',
|
},
|
||||||
title: 'Key',
|
{
|
||||||
// todo: use Mixin
|
name: 'key',
|
||||||
setter: 'StringSetter',
|
title: 'Key',
|
||||||
}, {
|
// todo: use Mixin
|
||||||
name: 'ref',
|
setter: 'StringSetter',
|
||||||
title: 'Ref',
|
},
|
||||||
setter: 'StringSetter',
|
{
|
||||||
}, {
|
name: 'ref',
|
||||||
name: '!more',
|
title: 'Ref',
|
||||||
title: '更多',
|
setter: 'StringSetter',
|
||||||
setter: 'PropertiesSetter'
|
},
|
||||||
}]
|
{
|
||||||
|
name: '!more',
|
||||||
|
title: '更多',
|
||||||
|
setter: 'PropertiesSetter',
|
||||||
|
},
|
||||||
|
],
|
||||||
});
|
});
|
||||||
const combined = [{
|
const combined = [
|
||||||
title: '属性',
|
{
|
||||||
name: '#props',
|
title: '属性',
|
||||||
items: propsGroup,
|
name: '#props',
|
||||||
}];
|
items: propsGroup,
|
||||||
|
},
|
||||||
|
];
|
||||||
const stylesGroup = [];
|
const stylesGroup = [];
|
||||||
if (styles?.supportClassName) {
|
if (styles?.supportClassName) {
|
||||||
stylesGroup.push({
|
stylesGroup.push({
|
||||||
name: 'className',
|
name: 'className',
|
||||||
title: '类名绑定',
|
title: '类名绑定',
|
||||||
setter: 'ClassNameSetter'
|
setter: 'ClassNameSetter',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (styles?.supportInlineStyle) {
|
if (styles?.supportInlineStyle) {
|
||||||
stylesGroup.push({
|
stylesGroup.push({
|
||||||
name: 'style',
|
name: 'style',
|
||||||
title: '行内样式',
|
title: '行内样式',
|
||||||
setter: 'StyleSetter'
|
setter: 'StyleSetter',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (stylesGroup.length > 0) {
|
if (stylesGroup.length > 0) {
|
||||||
@ -373,55 +402,35 @@ registerMetadataTransducer((metadata) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (supportEvents) {
|
if (eventsDefinition) {
|
||||||
combined.push({
|
combined.push({
|
||||||
name: '#events',
|
name: '#events',
|
||||||
title: '事件',
|
title: '事件',
|
||||||
items: [{
|
items: [
|
||||||
name: '!events',
|
{
|
||||||
title: '事件设置',
|
name: '!events',
|
||||||
setter: {
|
title: '事件设置',
|
||||||
componentName: 'EventsSetter',
|
setter: {
|
||||||
props: {
|
componentName: 'EventsSetter',
|
||||||
definition: []
|
props: {
|
||||||
}
|
definition: eventsDefinition,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
getValue(field: SettingField,val?:any[]) {
|
||||||
|
//console.log(value);
|
||||||
|
//return value;
|
||||||
|
return field.parent.getPropValue('eventDataList');
|
||||||
|
//return val;
|
||||||
|
},
|
||||||
|
|
||||||
|
setValue(field: SettingField, eventDataList: any[]) {
|
||||||
|
//return;
|
||||||
|
//console.info(eventDataList);
|
||||||
|
field.parent.setPropValue('eventDataList', eventDataList);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
],
|
||||||
// 先简单mock一下
|
|
||||||
definition:[
|
|
||||||
// {
|
|
||||||
// type: 'lifeCycleEvent', // 平台配置的,一般只有根节点才会配置
|
|
||||||
// title: '生命周期',
|
|
||||||
// list: [{
|
|
||||||
// title: '装载时',
|
|
||||||
// name: 'componentDidMount'
|
|
||||||
// },{
|
|
||||||
// title: '卸载时',
|
|
||||||
// name: 'componentWillUnmount'
|
|
||||||
// }]
|
|
||||||
// },
|
|
||||||
{
|
|
||||||
type: 'events', // 组件自定义的
|
|
||||||
list: [{
|
|
||||||
name:'onClick',
|
|
||||||
title:'点击回调'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name:'onChange',
|
|
||||||
title:'变更回调'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name:'onSubmit'
|
|
||||||
}]
|
|
||||||
}],
|
|
||||||
|
|
||||||
getValue(field: SettingField) {
|
|
||||||
return [];
|
|
||||||
},
|
|
||||||
setValue(field: SettingField) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -430,60 +439,71 @@ registerMetadataTransducer((metadata) => {
|
|||||||
combined.push({
|
combined.push({
|
||||||
name: '#advanced',
|
name: '#advanced',
|
||||||
title: '高级',
|
title: '高级',
|
||||||
items: []
|
items: [],
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
combined.push({
|
combined.push({
|
||||||
name: '#advanced',
|
name: '#advanced',
|
||||||
title: '高级',
|
title: '高级',
|
||||||
items: [{
|
items: [
|
||||||
name: '__condition',
|
{
|
||||||
title: '条件显示',
|
name: '__condition',
|
||||||
setter: 'ExpressionSetter'
|
title: '条件显示',
|
||||||
}, {
|
|
||||||
name: '#loop',
|
|
||||||
title: '循环',
|
|
||||||
items: [{
|
|
||||||
name: '__loop',
|
|
||||||
title: '循环数据',
|
|
||||||
setter: {
|
|
||||||
componentName: 'MixinSetter',
|
|
||||||
props: {
|
|
||||||
setters: [{
|
|
||||||
componentName: 'JSONSetter',
|
|
||||||
props: {
|
|
||||||
mode: 'popup',
|
|
||||||
placeholder: '编辑数据'
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
componentName: 'ExpressionSetter',
|
|
||||||
props: {
|
|
||||||
placeholder: '绑定数据'
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
name: '__loopArgs.0',
|
|
||||||
title: '迭代变量名',
|
|
||||||
setter: {
|
|
||||||
componentName: 'StringSetter',
|
|
||||||
placeholder: '默认为 item'
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
name: '__loopArgs.1',
|
|
||||||
title: '索引变量名',
|
|
||||||
setter: {
|
|
||||||
componentName: 'StringSetter',
|
|
||||||
placeholder: '默认为 index'
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
name: 'key',
|
|
||||||
title: 'Key',
|
|
||||||
setter: 'ExpressionSetter',
|
setter: 'ExpressionSetter',
|
||||||
}]
|
},
|
||||||
}]
|
{
|
||||||
})
|
name: '#loop',
|
||||||
|
title: '循环',
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
name: '__loop',
|
||||||
|
title: '循环数据',
|
||||||
|
setter: {
|
||||||
|
componentName: 'MixinSetter',
|
||||||
|
props: {
|
||||||
|
setters: [
|
||||||
|
{
|
||||||
|
componentName: 'JSONSetter',
|
||||||
|
props: {
|
||||||
|
mode: 'popup',
|
||||||
|
placeholder: '编辑数据',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
componentName: 'ExpressionSetter',
|
||||||
|
props: {
|
||||||
|
placeholder: '绑定数据',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '__loopArgs.0',
|
||||||
|
title: '迭代变量名',
|
||||||
|
setter: {
|
||||||
|
componentName: 'StringSetter',
|
||||||
|
placeholder: '默认为 item',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '__loopArgs.1',
|
||||||
|
title: '索引变量名',
|
||||||
|
setter: {
|
||||||
|
componentName: 'StringSetter',
|
||||||
|
placeholder: '默认为 index',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'key',
|
||||||
|
title: 'Key',
|
||||||
|
setter: 'ExpressionSetter',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user