diff --git a/packages/editor/src/Editor.vue b/packages/editor/src/Editor.vue index bc45e017..fe087c71 100644 --- a/packages/editor/src/Editor.vue +++ b/packages/editor/src/Editor.vue @@ -65,7 +65,7 @@ diff --git a/packages/editor/src/layouts/sidebar/code-block/CodeBlockEditor.vue b/packages/editor/src/layouts/sidebar/code-block/CodeBlockEditor.vue index 0b86a4eb..f4f70dac 100644 --- a/packages/editor/src/layouts/sidebar/code-block/CodeBlockEditor.vue +++ b/packages/editor/src/layouts/sidebar/code-block/CodeBlockEditor.vue @@ -9,7 +9,7 @@ > - + => { try { // 代码内容 - const codeContent = codeEditor.value.getEditor().getValue(); + const codeContent = codeEditor.value.getEditor()?.getValue(); /* eslint no-eval: "off" */ codeConfig.value.content = eval(codeContent); } catch (e: any) { diff --git a/packages/editor/src/layouts/sidebar/code-block/CodeBlockList.vue b/packages/editor/src/layouts/sidebar/code-block/CodeBlockList.vue index 7073974d..f3730f5b 100644 --- a/packages/editor/src/layouts/sidebar/code-block/CodeBlockList.vue +++ b/packages/editor/src/layouts/sidebar/code-block/CodeBlockList.vue @@ -25,21 +25,51 @@ :data="state.codeList" :highlight-current="true" :filter-node-method="filterNode" + @node-click="toggleCombineRelation" > {{ data.name }}({{ data.id }}) + - + + + + - + + + + + + + {{ comp.name }} + @@ -54,41 +84,104 @@ diff --git a/packages/editor/src/services/codeBlock.ts b/packages/editor/src/services/codeBlock.ts index a22d4831..4eff83dd 100644 --- a/packages/editor/src/services/codeBlock.ts +++ b/packages/editor/src/services/codeBlock.ts @@ -17,11 +17,13 @@ */ import { reactive } from 'vue'; -import { keys, omit, pick } from 'lodash-es'; +import { forIn, isEmpty, keys, omit, pick } from 'lodash-es'; + +import { Id } from '@tmagic/schema'; import editorService from '../services/editor'; import type { CodeBlockContent, CodeBlockDSL, CodeState, CompRelation } from '../type'; -import { EditorMode } from '../type'; +import { CodeEditorMode } from '../type'; import { info } from '../utils/logger'; import BaseService from './BaseService'; @@ -32,7 +34,7 @@ class CodeBlock extends BaseService { codeDsl: null, id: '', editable: true, - mode: EditorMode.EDITOR, + mode: CodeEditorMode.EDITOR, combineIds: [], compRelation: {}, undeletableList: [], @@ -191,18 +193,18 @@ class CodeBlock extends BaseService { /** * 获取当前模式 - * @returns {EditorMode} + * @returns {CodeEditorMode} */ - public getMode(): EditorMode { + public getMode(): CodeEditorMode { return this.state.mode; } /** * 设置当前模式 - * @param {EditorMode} mode 模式 + * @param {CodeEditorMode} mode 模式 * @returns {void} */ - public async setMode(mode: EditorMode): Promise { + public async setMode(mode: CodeEditorMode): Promise { this.state.mode = mode; } @@ -232,6 +234,7 @@ class CodeBlock extends BaseService { public async setCompRelation(compId: number | string, codeIds: string[]) { if (!compId) return; this.state.compRelation = { + ...this.state.compRelation, [compId]: codeIds, }; } @@ -244,6 +247,22 @@ class CodeBlock extends BaseService { return this.state.compRelation; } + /** + * 获取代码块与组件的绑定关系 + * @param {string} codeId 代码块id + * @returns {Id[]} 该代码块绑定的组件id数组 + */ + public getCodeRelationById(codeId: string): Id[] { + const codeRelation = reactive([]); + const compRelation = this.getCompRelation(); + forIn(compRelation, (value, key) => { + if (value.includes(codeId)) { + codeRelation.push(key); + } + }); + return codeRelation; + } + /** * 获取不可删除列表 * @returns {string[]} @@ -286,12 +305,39 @@ class CodeBlock extends BaseService { return await this.getUniqueId(); } + /** + * 一对一解除绑定关系 + * @param {string} compId 组件id + * @param {string} codeId 代码块id + * @param {string[]} codeHooks 代码块挂载hook名称 + * @returns {boolean} 结果 + */ + public async unbind(compId: Id, codeId: string, codeHooks: string[]): Promise { + const nodeInfo = editorService.getNodeById(compId); + if (!nodeInfo) return false; + // 更新node节点信息 + codeHooks.forEach((hook) => { + if (!isEmpty(nodeInfo[hook])) { + const newHookInfo = nodeInfo[hook].filter((item: string) => item !== codeId); + nodeInfo[hook] = newHookInfo; + editorService.update(nodeInfo); + } + }); + // 更新绑定关系 + const oldRelation = await this.getCompRelation(); + const oldCodeIds = oldRelation[compId]; + // 不能直接splice修改原数组,会导致绑定关系更新错乱 + const newCodeIds = oldCodeIds.filter((item) => item !== codeId); + this.setCompRelation(compId, newCodeIds); + return true; + } + public destroy() { this.state.isShowCodeEditor = false; this.state.codeDsl = null; this.state.id = ''; this.state.editable = true; - this.state.mode = EditorMode.EDITOR; + this.state.mode = CodeEditorMode.EDITOR; this.state.combineIds = []; this.state.compRelation = {}; this.state.undeletableList = []; diff --git a/packages/editor/src/theme/code-block.scss b/packages/editor/src/theme/code-block.scss index 14aacb0d..04ea4d71 100644 --- a/packages/editor/src/theme/code-block.scss +++ b/packages/editor/src/theme/code-block.scss @@ -1,5 +1,8 @@ .m-editor-code-block-list { margin-top: 5px; + .el-tree-node__content { + height: auto; + } .code-header-wrapper { display: flex; align-items: center; @@ -47,6 +50,25 @@ margin-right: 60px; } } + .code-comp-map-wrapper { + display: flex; + align-items: center; + flex-wrap: wrap; + margin-left: 20px; + margin-bottom: 5px; + .arrow-left { + transform: rotate(-45deg); + width: 20px; + height: 20px; + } + .code-comp { + margin-left: 5px; + padding: 5px; + .comp-delete-icon { + margin-left: 3px; + } + } + } } } diff --git a/packages/editor/src/type.ts b/packages/editor/src/type.ts index 4bcdcc20..12f0411a 100644 --- a/packages/editor/src/type.ts +++ b/packages/editor/src/type.ts @@ -329,7 +329,7 @@ export type CodeState = { /** 代码块是否可编辑 */ editable: boolean; /** 代码编辑面板的展示模式 */ - mode: EditorMode; + mode: CodeEditorMode; /** list模式下左侧展示的代码列表 */ combineIds: string[]; /** 组件和代码块的绑定关系 */ @@ -338,7 +338,7 @@ export type CodeState = { undeletableList: string[]; }; -export enum EditorMode { +export enum CodeEditorMode { /** 左侧菜单,右侧代码 */ LIST = 'list', /** 全屏代码 */ @@ -347,7 +347,7 @@ export enum EditorMode { export type CompRelation = { /** 代码块绑定关系:组件id-代码块id数组 */ - [compId: string | number]: string[]; + [compId: Id]: string[]; }; export interface CodeDslList { @@ -357,13 +357,21 @@ export interface CodeDslList { name: string; /** 代码块函数内容 */ content: any; + /** 是否展示代码绑定关系 */ + showRelation?: boolean; } + export interface ListState { /** 代码块列表 */ codeList: CodeDslList[]; + /** 与代码块绑定的组件id信息 */ + bindComps: { + /** 代码块id : 组件信息 */ + [id: string]: MNode[]; + }; } -export enum ErrorType { +export enum CodeDeleteErrorType { /** 代码块存在于不可删除列表中 */ UNDELETEABLE = 'undeleteable', /** 代码块存在绑定关系 */ diff --git a/packages/editor/src/utils/props.ts b/packages/editor/src/utils/props.ts index 76a2cb58..77ea7db0 100644 --- a/packages/editor/src/utils/props.ts +++ b/packages/editor/src/utils/props.ts @@ -229,6 +229,12 @@ export const fillConfig = (config: FormConfig = []) => [ type: 'code-select', labelWidth: '100px', }, + { + name: 'mounted', + text: 'mounted', + type: 'code-select', + labelWidth: '100px', + }, ], }, ], diff --git a/playground/src/configs/dsl.ts b/playground/src/configs/dsl.ts index 36f8b5fb..c5fc7829 100644 --- a/playground/src/configs/dsl.ts +++ b/playground/src/configs/dsl.ts @@ -26,6 +26,11 @@ export default { // eslint-disable-next-line no-eval content: eval(`(vm) => {\n console.log("this is getData function")\n}`), }, + code_5316: { + name: 'getList', + // eslint-disable-next-line no-eval + content: eval(`(vm) => {\n console.log("this is getList function")\n}`), + }, }, items: [ { @@ -51,7 +56,8 @@ export default { fontWeight: '', }, events: [], - created: ['code_5336'], + created: ['code_5316'], + mounted: ['code_5336'], items: [ { type: 'text', @@ -76,7 +82,7 @@ export default { text: 'Tmagic editor 营销活动编辑器', multiple: true, events: [], - created: [], + created: ['code_5316'], }, { type: 'qrcode',