mirror of
https://github.com/Tencent/tmagic-editor.git
synced 2025-04-06 03:57:56 +08:00
feat(editor): 代码块功能增加删除,完善一些边界情况的交互
This commit is contained in:
parent
0c25cf795f
commit
2f803c963a
@ -8,7 +8,14 @@
|
|||||||
:size="size"
|
:size="size"
|
||||||
@change="changeHandler"
|
@change="changeHandler"
|
||||||
></m-fields-select>
|
></m-fields-select>
|
||||||
<el-button type="primary" :icon="View" :size="size" @click="viewHandler">查看</el-button>
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
:icon="View"
|
||||||
|
:size="size"
|
||||||
|
@click="viewHandler"
|
||||||
|
:disabled="props.model[props.name].length === 0"
|
||||||
|
>查看</el-button
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -35,6 +42,9 @@ const props = defineProps<{
|
|||||||
}>();
|
}>();
|
||||||
|
|
||||||
const changeHandler = (value: any) => {
|
const changeHandler = (value: any) => {
|
||||||
|
// 记录组件与代码块的绑定关系
|
||||||
|
const { id = '' } = services?.editorService.get('node') || {};
|
||||||
|
services?.codeBlockService.setCompRelation(id, value);
|
||||||
emit('change', value);
|
emit('change', value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -7,13 +7,14 @@
|
|||||||
:append-to-body="true"
|
:append-to-body="true"
|
||||||
>
|
>
|
||||||
<template v-if="mode === EditorMode.LIST">
|
<template v-if="mode === EditorMode.LIST">
|
||||||
<el-menu default-active="0" class="el-menu-vertical-demo code-editor-side-menu">
|
<el-menu :default-active="selectedIds[0]" class="el-menu-vertical-demo code-editor-side-menu">
|
||||||
<el-menu-item v-for="(value, key) in selectedValue" :index="key" :key="key" @click="menuSelectHandler">
|
<el-menu-item v-for="(value, key) in selectedValue" :index="key" :key="key" @click="menuSelectHandler">
|
||||||
<template #title>{{ value.name }}({{ key }})</template>
|
<template #title>{{ value.name }}({{ key }})</template>
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
</el-menu>
|
</el-menu>
|
||||||
</template>
|
</template>
|
||||||
<div
|
<div
|
||||||
|
v-if="!isEmpty(codeConfig)"
|
||||||
:class="[
|
:class="[
|
||||||
mode === EditorMode.LIST ? 'm-editor-code-block-editor-panel-list-mode' : '',
|
mode === EditorMode.LIST ? 'm-editor-code-block-editor-panel-list-mode' : '',
|
||||||
'm-editor-code-block-editor-panel',
|
'm-editor-code-block-editor-panel',
|
||||||
@ -55,6 +56,7 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, inject, ref, watchEffect } from 'vue';
|
import { computed, inject, ref, watchEffect } from 'vue';
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
|
import { isEmpty } from 'lodash-es';
|
||||||
|
|
||||||
import type { CodeBlockContent, Services } from '../../../type';
|
import type { CodeBlockContent, Services } from '../../../type';
|
||||||
import { EditorMode } from '../../../type';
|
import { EditorMode } from '../../../type';
|
||||||
@ -70,11 +72,10 @@ const isShowCodeBlockEditor = computed(() => codeConfig.value && services?.codeB
|
|||||||
const mode = computed(() => services?.codeBlockService.getMode());
|
const mode = computed(() => services?.codeBlockService.getMode());
|
||||||
const id = computed(() => services?.codeBlockService.getId() || '');
|
const id = computed(() => services?.codeBlockService.getId() || '');
|
||||||
const editable = computed(() => services?.codeBlockService.getEditStatus());
|
const editable = computed(() => services?.codeBlockService.getEditStatus());
|
||||||
|
// 当前选中组件绑定的代码块id数组
|
||||||
|
const selectedIds = computed(() => services?.codeBlockService.getCombineIds() || []);
|
||||||
// select选择的内容(CodeBlockDSL)
|
// select选择的内容(CodeBlockDSL)
|
||||||
const selectedValue = computed(() => {
|
const selectedValue = computed(() => services?.codeBlockService.getCodeDslByIds(selectedIds.value));
|
||||||
const selectedIds = services?.codeBlockService.getCombineIds() || [];
|
|
||||||
return services?.codeBlockService.getCodeDslByIds(selectedIds);
|
|
||||||
});
|
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
codeConfig.value = services?.codeBlockService.getCodeContentById(id.value) ?? null;
|
codeConfig.value = services?.codeBlockService.getCodeContentById(id.value) ?? null;
|
||||||
|
@ -8,14 +8,17 @@
|
|||||||
</slot>
|
</slot>
|
||||||
|
|
||||||
<!-- 代码块列表 -->
|
<!-- 代码块列表 -->
|
||||||
<div class="list-container" v-if="codeList">
|
<div class="list-container" v-if="!isEmpty(codeList)">
|
||||||
<div v-for="(value, key) in codeList" :key="key">
|
<div v-for="(value, key) in codeList" :key="key">
|
||||||
<div class="list-item">
|
<div class="list-item">
|
||||||
<div class="code-name">{{ value.name }}({{ key }})</div>
|
<div class="code-name">{{ value.name }}({{ key }})</div>
|
||||||
<div class="right-tool">
|
<div class="right-tool">
|
||||||
<el-tooltip effect="dark" content="编辑代码" placement="top">
|
<el-tooltip effect="dark" content="编辑" placement="top">
|
||||||
<el-icon class="edit-icon" @click="editCode(key)"><Edit /></el-icon>
|
<el-icon class="edit-icon" @click="editCode(key)"><Edit /></el-icon>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
|
<el-tooltip effect="dark" content="删除" placement="top">
|
||||||
|
<el-icon class="edit-icon" @click="deleteCode(key)"><Close /></el-icon>
|
||||||
|
</el-tooltip>
|
||||||
<slot name="code-block-panel-tool" :id="key"></slot>
|
<slot name="code-block-panel-tool" :id="key"></slot>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -33,8 +36,9 @@
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, inject } from 'vue';
|
import { computed, inject } from 'vue';
|
||||||
import { Edit } from '@element-plus/icons-vue';
|
import { Close, Edit } from '@element-plus/icons-vue';
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
|
import { flattenDeep, isEmpty, values } from 'lodash-es';
|
||||||
|
|
||||||
import type { CodeBlockContent, Services } from '../../../type';
|
import type { CodeBlockContent, Services } from '../../../type';
|
||||||
import { EditorMode } from '../../../type';
|
import { EditorMode } from '../../../type';
|
||||||
@ -58,7 +62,7 @@ const createCodeBlock = () => {
|
|||||||
name: '代码块',
|
name: '代码块',
|
||||||
content: `() => {\n // place your code here\n}`,
|
content: `() => {\n // place your code here\n}`,
|
||||||
};
|
};
|
||||||
services?.codeBlockService.setMode(EditorMode.EDITOR);
|
codeBlockService.setMode(EditorMode.EDITOR);
|
||||||
const id = codeBlockService.getUniqueId();
|
const id = codeBlockService.getUniqueId();
|
||||||
codeBlockService.setCodeDslById(id, codeConfig);
|
codeBlockService.setCodeDslById(id, codeConfig);
|
||||||
codeBlockService.setCodeEditorContent(true, id);
|
codeBlockService.setCodeEditorContent(true, id);
|
||||||
@ -69,4 +73,17 @@ const editCode = (key: string) => {
|
|||||||
services?.codeBlockService.setMode(EditorMode.EDITOR);
|
services?.codeBlockService.setMode(EditorMode.EDITOR);
|
||||||
services?.codeBlockService.setCodeEditorContent(true, key);
|
services?.codeBlockService.setCodeEditorContent(true, key);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 删除代码块
|
||||||
|
const deleteCode = (key: string) => {
|
||||||
|
const compRelation = services?.codeBlockService.getCompRelation();
|
||||||
|
const codeIds = flattenDeep(values(compRelation));
|
||||||
|
const undeleteableList = services?.codeBlockService.getUndeletableList() || [];
|
||||||
|
if (!codeIds.includes(key) && !undeleteableList.includes(key)) {
|
||||||
|
// 无绑定关系,且不在不可删除列表中
|
||||||
|
services?.codeBlockService.deleteCodeDslByIds([key]);
|
||||||
|
} else {
|
||||||
|
ElMessage.error('代码块删除失败');
|
||||||
|
}
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@ -17,9 +17,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { reactive } from 'vue';
|
import { reactive } from 'vue';
|
||||||
import { keys, pick } from 'lodash-es';
|
import { keys, omit, pick } from 'lodash-es';
|
||||||
|
|
||||||
import type { CodeBlockContent, CodeBlockDSL, CodeState } from '../type';
|
import type { CodeBlockContent, CodeBlockDSL, CodeState, CompRelation } from '../type';
|
||||||
import { EditorMode } from '../type';
|
import { EditorMode } from '../type';
|
||||||
import { info } from '../utils/logger';
|
import { info } from '../utils/logger';
|
||||||
|
|
||||||
@ -33,6 +33,8 @@ class CodeBlock extends BaseService {
|
|||||||
editable: true,
|
editable: true,
|
||||||
mode: EditorMode.EDITOR,
|
mode: EditorMode.EDITOR,
|
||||||
combineIds: [],
|
combineIds: [],
|
||||||
|
compRelation: {},
|
||||||
|
undeletableList: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -185,7 +187,7 @@ class CodeBlock extends BaseService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置当前已关联绑定的代码块id数组
|
* 设置当前选中组件已关联绑定的代码块id数组
|
||||||
* @param {string[]} ids 代码块id数组
|
* @param {string[]} ids 代码块id数组
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
@ -194,13 +196,63 @@ class CodeBlock extends BaseService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取当前已关联绑定的代码块id数组
|
* 获取当前选中组件已关联绑定的代码块id数组
|
||||||
* @returns {string[]}
|
* @returns {string[]}
|
||||||
*/
|
*/
|
||||||
public getCombineIds(): string[] {
|
public getCombineIds(): string[] {
|
||||||
return this.state.combineIds;
|
return this.state.combineIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置组件与代码块的绑定关系
|
||||||
|
* @param {number | string} compId 组件id
|
||||||
|
* @param {string[]} codeIds 代码块id数组
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
public setCompRelation(compId: number | string, codeIds: string[]) {
|
||||||
|
if (!compId) return;
|
||||||
|
this.state.compRelation = {
|
||||||
|
[compId]: codeIds,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取组件与代码块的绑定关系
|
||||||
|
* @returns {CompRelation}
|
||||||
|
*/
|
||||||
|
public getCompRelation(): CompRelation {
|
||||||
|
return this.state.compRelation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取不可删除列表
|
||||||
|
* @returns {string[]}
|
||||||
|
*/
|
||||||
|
public getUndeletableList(): string[] {
|
||||||
|
return this.state.undeletableList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置不可删除列表:为业务逻辑预留的不可删除的代码块列表,由业务逻辑维护(如代码块上线后不可删除)
|
||||||
|
* @param {string[]} codeIds 代码块id数组
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
public setUndeleteableList(codeIds: string[]): void {
|
||||||
|
this.state.undeletableList = codeIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在dsl数据源中删除指定id的代码块
|
||||||
|
* @param {string[]} codeIds 需要删除的代码块id数组
|
||||||
|
* @returns {CodeBlockDSL} 删除后的code dsl
|
||||||
|
*/
|
||||||
|
public deleteCodeDslByIds(codeIds: string[]): CodeBlockDSL {
|
||||||
|
const currentDsl = this.getCodeDsl();
|
||||||
|
const newDsl = omit(currentDsl, codeIds);
|
||||||
|
this.setCodeDsl(newDsl);
|
||||||
|
return newDsl;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生成代码块唯一id
|
* 生成代码块唯一id
|
||||||
* @returns {string} 代码块唯一id
|
* @returns {string} 代码块唯一id
|
||||||
|
@ -328,11 +328,23 @@ export type CodeState = {
|
|||||||
id: string;
|
id: string;
|
||||||
/** 代码块是否可编辑 */
|
/** 代码块是否可编辑 */
|
||||||
editable: boolean;
|
editable: boolean;
|
||||||
|
/** 代码编辑面板的展示模式 */
|
||||||
mode: EditorMode;
|
mode: EditorMode;
|
||||||
|
/** list模式下左侧展示的代码列表 */
|
||||||
combineIds: string[];
|
combineIds: string[];
|
||||||
|
/** 组件和代码块的绑定关系 */
|
||||||
|
compRelation: CompRelation;
|
||||||
|
/** 为业务逻辑预留的不可删除的代码块列表,由业务逻辑维护(如代码块上线后不可删除) */
|
||||||
|
undeletableList: string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export enum EditorMode {
|
export enum EditorMode {
|
||||||
|
/** 左侧菜单,右侧代码 */
|
||||||
LIST = 'list',
|
LIST = 'list',
|
||||||
|
/** 全屏代码 */
|
||||||
EDITOR = 'editor',
|
EDITOR = 'editor',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type CompRelation = {
|
||||||
|
[compId: string | number]: string[];
|
||||||
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user