mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-01-19 22:58:15 +00:00
fix: 处理 slot 开启/关闭操作中, 无法正常创建 slot 的bug
feat: 支持 didDropOut 特性
This commit is contained in:
parent
5c141e8eb0
commit
3e86d09160
@ -1,8 +1,5 @@
|
|||||||
{
|
{
|
||||||
"plugins": [
|
"plugins": [
|
||||||
[
|
|
||||||
"build-plugin-component"
|
"build-plugin-component"
|
||||||
],
|
|
||||||
"./build.plugin.js"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +0,0 @@
|
|||||||
module.exports = ({ onGetJestConfig }) => {
|
|
||||||
// console.log('== test ==');
|
|
||||||
onGetJestConfig((jestConfig) => {
|
|
||||||
// console.log(jestConfig);
|
|
||||||
return jestConfig;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
5
packages/designer/build.test.json
Normal file
5
packages/designer/build.test.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"plugins": [
|
||||||
|
"@ali/lowcode-test-mate/plugin/index.ts"
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -22,6 +22,7 @@ import { TransformStage } from './transform-stage';
|
|||||||
import { ReactElement } from 'react';
|
import { ReactElement } from 'react';
|
||||||
import { SettingTopEntry } from 'designer/src/designer';
|
import { SettingTopEntry } from 'designer/src/designer';
|
||||||
import { EventEmitter } from 'events';
|
import { EventEmitter } from 'events';
|
||||||
|
import { includeSlot, removeSlot } from '../../utils/slot';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 基础节点
|
* 基础节点
|
||||||
@ -709,6 +710,11 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
|
|||||||
|
|
||||||
addSlot(slotNode: Node) {
|
addSlot(slotNode: Node) {
|
||||||
slotNode.internalSetParent(this as ParentalNode, true);
|
slotNode.internalSetParent(this as ParentalNode, true);
|
||||||
|
const slotName = slotNode?.getExtraProp('name')?.getAsString();
|
||||||
|
// 一个组件下的所有 slot,相同 slotName 的 slot 应该是唯一的
|
||||||
|
if (includeSlot(this, slotName)) {
|
||||||
|
removeSlot(this, slotName);
|
||||||
|
}
|
||||||
this._slots.push(slotNode);
|
this._slots.push(slotNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,6 @@ import { valueToSource } from './value-to-source';
|
|||||||
import { Props } from './props';
|
import { Props } from './props';
|
||||||
import { SlotNode, Node } from '../node';
|
import { SlotNode, Node } from '../node';
|
||||||
import { TransformStage } from '../transform-stage';
|
import { TransformStage } from '../transform-stage';
|
||||||
import { includesSlot } from '../../../utils/slot';
|
|
||||||
|
|
||||||
export const UNSET = Symbol.for('unset');
|
export const UNSET = Symbol.for('unset');
|
||||||
export type UNSET = typeof UNSET;
|
export type UNSET = typeof UNSET;
|
||||||
@ -118,7 +117,7 @@ export class Prop implements IPropParent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (type === 'slot') {
|
if (type === 'slot') {
|
||||||
const schema = this._slotNode!.export(stage);
|
const schema = this._slotNode?.export(stage) || {};
|
||||||
if (stage === TransformStage.Render) {
|
if (stage === TransformStage.Render) {
|
||||||
return {
|
return {
|
||||||
type: 'JSSlot',
|
type: 'JSSlot',
|
||||||
@ -294,12 +293,10 @@ export class Prop implements IPropParent {
|
|||||||
this._slotNode.import(slotSchema);
|
this._slotNode.import(slotSchema);
|
||||||
} else {
|
} else {
|
||||||
const { owner } = this.props;
|
const { owner } = this.props;
|
||||||
if (!includesSlot(owner, data.name)) {
|
|
||||||
this._slotNode = owner.document.createNode<SlotNode>(slotSchema);
|
this._slotNode = owner.document.createNode<SlotNode>(slotSchema);
|
||||||
owner.addSlot(this._slotNode);
|
owner.addSlot(this._slotNode);
|
||||||
this._slotNode.internalSetSlotFor(this);
|
this._slotNode.internalSetSlotFor(this);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
this.dispose();
|
this.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,19 @@
|
|||||||
import { Node } from '../document/node/node';
|
import { Node } from '../document/node/node';
|
||||||
|
|
||||||
export function includesSlot(node: Node, slotName: string | undefined): boolean {
|
export function includeSlot(node: Node, slotName: string | undefined): boolean {
|
||||||
const { slots = [] } = node;
|
const { slots = [] } = node;
|
||||||
return slots.some(slot => {
|
return slots.some(slot => {
|
||||||
return slotName && slotName === slot?.getExtraProp('name')?.getAsString();
|
return slotName && slotName === slot?.getExtraProp('name')?.getAsString();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function removeSlot(node: Node, slotName: string | undefined): boolean {
|
||||||
|
const { slots = [] } = node;
|
||||||
|
return slots.some((slot, idx) => {
|
||||||
|
if (slotName && slotName === slot?.getExtraProp('name')?.getAsString()) {
|
||||||
|
slots.splice(idx, 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import set from 'lodash.set';
|
||||||
import '../fixtures/window';
|
import '../fixtures/window';
|
||||||
import { Project } from '../../src/project/project';
|
import { Project } from '../../src/project/project';
|
||||||
// import { Node } from '../../../src/document/node/node';
|
// import { Node } from '../../../src/document/node/node';
|
||||||
@ -27,39 +28,11 @@ jest.mock('../../src/designer/designer', () => {
|
|||||||
|
|
||||||
let designer = null;
|
let designer = null;
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
designer = new Designer({} as any);
|
designer = new Designer({});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('schema 渲染测试', () => {
|
describe('schema 生成节点模型测试', () => {
|
||||||
it('最简单的例子,练手用', () => {
|
it.only('block ❌ | component ❌ | slot ❌', () => {
|
||||||
const project = new Project(designer, {
|
|
||||||
componentsTree: [{
|
|
||||||
componentName: 'Page',
|
|
||||||
id: 'page_id',
|
|
||||||
props: {
|
|
||||||
name: 'haha',
|
|
||||||
},
|
|
||||||
children: [{
|
|
||||||
componentName: 'Div',
|
|
||||||
id: 'div_id',
|
|
||||||
props: {
|
|
||||||
name: 'div from haha',
|
|
||||||
},
|
|
||||||
}],
|
|
||||||
}],
|
|
||||||
} as any);
|
|
||||||
project.open();
|
|
||||||
expect(project).toBeTruthy();
|
|
||||||
const { currentDocument } = project;
|
|
||||||
const { nodesMap } = currentDocument;
|
|
||||||
// console.log(project.currentDocument.nodesMap.get('div_id').props.items);
|
|
||||||
expect(nodesMap.has('page_id')).toBeTruthy;
|
|
||||||
expect(nodesMap.has('div_id')).toBeTruthy;
|
|
||||||
expect(mockCreateSettingEntry).toBeCalledTimes(2);
|
|
||||||
// console.log(currentDocument.export(3));
|
|
||||||
});
|
|
||||||
|
|
||||||
it.only('普通场景,无 block / component,无 slot', () => {
|
|
||||||
const project = new Project(designer, {
|
const project = new Project(designer, {
|
||||||
componentsTree: [
|
componentsTree: [
|
||||||
formSchema,
|
formSchema,
|
||||||
@ -70,15 +43,15 @@ describe('schema 渲染测试', () => {
|
|||||||
const { currentDocument } = project;
|
const { currentDocument } = project;
|
||||||
const { nodesMap } = currentDocument;
|
const { nodesMap } = currentDocument;
|
||||||
const ids = getIdsFromSchema(formSchema);
|
const ids = getIdsFromSchema(formSchema);
|
||||||
|
const expectedNodeCnt = ids.length;
|
||||||
|
expect(nodesMap.size).toBe(expectedNodeCnt);
|
||||||
ids.forEach(id => {
|
ids.forEach(id => {
|
||||||
expect(nodesMap.get(id).componentName).toBe(getNodeFromSchemaById(formSchema, id).componentName);
|
expect(nodesMap.get(id).componentName).toBe(getNodeFromSchemaById(formSchema, id).componentName);
|
||||||
});
|
});
|
||||||
// console.log(nodesMap.get('node_k1ow3cb9').componentName, getNodeFromSchemaById(formSchema, 'node_k1ow3cb9').componentName)
|
|
||||||
console.log(nodesMap.size);
|
const exportSchema = currentDocument?.export(1);
|
||||||
// expect(nodesMap.has('page_id')).toBeTruthy;
|
expect(getIdsFromSchema(exportSchema).length).toBe(expectedNodeCnt);
|
||||||
// expect(nodesMap.has('div_id')).toBeTruthy;
|
expect(mockCreateSettingEntry).toBeCalledTimes(expectedNodeCnt);
|
||||||
// expect(mockCreateSettingEntry).toBeCalledTimes(2);
|
|
||||||
// console.log(currentDocument.export(3));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('普通场景,无 block / component,有 slot', () => {});
|
it('普通场景,无 block / component,有 slot', () => {});
|
||||||
|
|||||||
@ -1,28 +1 @@
|
|||||||
export function getIdsFromSchema(schema, ids = []) {
|
export { getIdsFromSchema, getNodeFromSchemaById } from '@ali/lowcode-test-mate/es/utils';
|
||||||
if (!schema) return ids;
|
|
||||||
const { componentName, id, children } = schema;
|
|
||||||
if (componentName) {
|
|
||||||
ids.push(id);
|
|
||||||
}
|
|
||||||
if (Array.isArray(children) && children.length > 0) {
|
|
||||||
children.forEach(node => getIdsFromSchema(node, ids));
|
|
||||||
}
|
|
||||||
return ids;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getNodeFromSchemaById(schema, _id) {
|
|
||||||
if (!schema) return null;
|
|
||||||
const { id, children } = schema;
|
|
||||||
let retNode = null;
|
|
||||||
if (_id === id) return schema;
|
|
||||||
if (Array.isArray(children) && children.length > 0) {
|
|
||||||
children.some(node => {
|
|
||||||
retNode = getNodeFromSchemaById(node, _id);
|
|
||||||
if (retNode) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return retNode;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -54,5 +54,5 @@
|
|||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"registry": "http://registry.npm.alibaba-inc.com"
|
"registry": "http://registry.npm.alibaba-inc.com"
|
||||||
},
|
},
|
||||||
"homepage": "https://unpkg.alibaba-inc.com/@ali/lowcode-react-renderer@0.13.1-6/build/index.html"
|
"homepage": "https://unpkg.alibaba-inc.com/@ali/lowcode-react-renderer@0.13.1-7/build/index.html"
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user