diff --git a/packages/designer/build.json b/packages/designer/build.json index 4fbf8701e..bd5cf18dd 100644 --- a/packages/designer/build.json +++ b/packages/designer/build.json @@ -1,8 +1,5 @@ { "plugins": [ - [ - "build-plugin-component" - ], - "./build.plugin.js" + "build-plugin-component" ] } diff --git a/packages/designer/build.plugin.js b/packages/designer/build.plugin.js deleted file mode 100644 index 49ec39f2d..000000000 --- a/packages/designer/build.plugin.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = ({ onGetJestConfig }) => { - // console.log('== test =='); - onGetJestConfig((jestConfig) => { - // console.log(jestConfig); - return jestConfig; - }); -}; diff --git a/packages/designer/build.test.json b/packages/designer/build.test.json new file mode 100644 index 000000000..93dfcd983 --- /dev/null +++ b/packages/designer/build.test.json @@ -0,0 +1,5 @@ +{ + "plugins": [ + "@ali/lowcode-test-mate/plugin/index.ts" + ] +} diff --git a/packages/designer/src/document/node/node.ts b/packages/designer/src/document/node/node.ts index 2c83d118f..df0ebef6e 100644 --- a/packages/designer/src/document/node/node.ts +++ b/packages/designer/src/document/node/node.ts @@ -22,6 +22,7 @@ import { TransformStage } from './transform-stage'; import { ReactElement } from 'react'; import { SettingTopEntry } from 'designer/src/designer'; import { EventEmitter } from 'events'; +import { includeSlot, removeSlot } from '../../utils/slot'; /** * 基础节点 @@ -709,6 +710,11 @@ export class Node { addSlot(slotNode: Node) { 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); } diff --git a/packages/designer/src/document/node/props/prop.ts b/packages/designer/src/document/node/props/prop.ts index b09eb787f..704a99ba6 100644 --- a/packages/designer/src/document/node/props/prop.ts +++ b/packages/designer/src/document/node/props/prop.ts @@ -6,7 +6,6 @@ import { valueToSource } from './value-to-source'; import { Props } from './props'; import { SlotNode, Node } from '../node'; import { TransformStage } from '../transform-stage'; -import { includesSlot } from '../../../utils/slot'; export const UNSET = Symbol.for('unset'); export type UNSET = typeof UNSET; @@ -118,7 +117,7 @@ export class Prop implements IPropParent { } if (type === 'slot') { - const schema = this._slotNode!.export(stage); + const schema = this._slotNode?.export(stage) || {}; if (stage === TransformStage.Render) { return { type: 'JSSlot', @@ -294,11 +293,9 @@ export class Prop implements IPropParent { this._slotNode.import(slotSchema); } else { const { owner } = this.props; - if (!includesSlot(owner, data.name)) { - this._slotNode = owner.document.createNode(slotSchema); - owner.addSlot(this._slotNode); - this._slotNode.internalSetSlotFor(this); - } + this._slotNode = owner.document.createNode(slotSchema); + owner.addSlot(this._slotNode); + this._slotNode.internalSetSlotFor(this); } this.dispose(); } diff --git a/packages/designer/src/utils/slot.ts b/packages/designer/src/utils/slot.ts index 3630c0c0e..9fe1ef5f7 100644 --- a/packages/designer/src/utils/slot.ts +++ b/packages/designer/src/utils/slot.ts @@ -1,8 +1,19 @@ 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; return slots.some(slot => { 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; + }); +} diff --git a/packages/designer/tests/project/project.test.ts b/packages/designer/tests/project/project.test.ts index c98c82592..7c0a7b121 100644 --- a/packages/designer/tests/project/project.test.ts +++ b/packages/designer/tests/project/project.test.ts @@ -1,3 +1,4 @@ +import set from 'lodash.set'; import '../fixtures/window'; import { Project } from '../../src/project/project'; // import { Node } from '../../../src/document/node/node'; @@ -27,39 +28,11 @@ jest.mock('../../src/designer/designer', () => { let designer = null; beforeAll(() => { - designer = new Designer({} as any); + designer = new Designer({}); }); -describe('schema 渲染测试', () => { - it('最简单的例子,练手用', () => { - 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', () => { +describe('schema 生成节点模型测试', () => { + it.only('block ❌ | component ❌ | slot ❌', () => { const project = new Project(designer, { componentsTree: [ formSchema, @@ -70,15 +43,15 @@ describe('schema 渲染测试', () => { const { currentDocument } = project; const { nodesMap } = currentDocument; const ids = getIdsFromSchema(formSchema); + const expectedNodeCnt = ids.length; + expect(nodesMap.size).toBe(expectedNodeCnt); ids.forEach(id => { 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); - // expect(nodesMap.has('page_id')).toBeTruthy; - // expect(nodesMap.has('div_id')).toBeTruthy; - // expect(mockCreateSettingEntry).toBeCalledTimes(2); - // console.log(currentDocument.export(3)); + + const exportSchema = currentDocument?.export(1); + expect(getIdsFromSchema(exportSchema).length).toBe(expectedNodeCnt); + expect(mockCreateSettingEntry).toBeCalledTimes(expectedNodeCnt); }); it('普通场景,无 block / component,有 slot', () => {}); diff --git a/packages/designer/tests/utils/index.ts b/packages/designer/tests/utils/index.ts index f8fb61e4e..70fce0af2 100644 --- a/packages/designer/tests/utils/index.ts +++ b/packages/designer/tests/utils/index.ts @@ -1,28 +1 @@ -export function getIdsFromSchema(schema, ids = []) { - 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; -} \ No newline at end of file +export { getIdsFromSchema, getNodeFromSchemaById } from '@ali/lowcode-test-mate/es/utils'; diff --git a/packages/react-renderer/package.json b/packages/react-renderer/package.json index 23a1c8ae2..d9dea8170 100644 --- a/packages/react-renderer/package.json +++ b/packages/react-renderer/package.json @@ -54,5 +54,5 @@ "publishConfig": { "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" }