mirror of
https://github.com/Tencent/tmagic-editor.git
synced 2025-08-28 00:03:35 +08:00
fix: 代码块结构改造完成
This commit is contained in:
parent
c4293f17a6
commit
c7a8552d9b
@ -20,8 +20,7 @@ import { EventEmitter } from 'events';
|
|||||||
|
|
||||||
import { isEmpty } from 'lodash-es';
|
import { isEmpty } from 'lodash-es';
|
||||||
|
|
||||||
import type { EventItemConfig, MComponent, MContainer, MPage } from '@tmagic/schema';
|
import { EventItemConfig, HookType, MComponent, MContainer, MPage } from '@tmagic/schema';
|
||||||
import { HookType } from '@tmagic/schema';
|
|
||||||
|
|
||||||
import type App from './App';
|
import type App from './App';
|
||||||
import type Page from './Page';
|
import type Page from './Page';
|
||||||
@ -87,7 +86,7 @@ class Node extends EventEmitter {
|
|||||||
|
|
||||||
private async runCodeBlock(hook: string) {
|
private async runCodeBlock(hook: string) {
|
||||||
if (this.data[hook]?.hookType !== HookType.CODE || !this.app.codeDsl || isEmpty(this.app?.codeDsl)) return;
|
if (this.data[hook]?.hookType !== HookType.CODE || !this.app.codeDsl || isEmpty(this.app?.codeDsl)) return;
|
||||||
for (const item of this.data[hook].data) {
|
for (const item of this.data[hook].hookData) {
|
||||||
const { codeId, params = {} } = item;
|
const { codeId, params = {} } = item;
|
||||||
if (this.app.codeDsl[codeId] && typeof this.app?.codeDsl[codeId]?.content === 'function') {
|
if (this.app.codeDsl[codeId] && typeof this.app?.codeDsl[codeId]?.content === 'function') {
|
||||||
await this.app.codeDsl[codeId].content(this, params);
|
await this.app.codeDsl[codeId].content(this, params);
|
||||||
|
@ -1,30 +1,26 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="m-fields-code-select" :key="fieldKey">
|
<div class="m-fields-code-select">
|
||||||
<TMagicCard shadow="never">
|
|
||||||
<m-form-table
|
<m-form-table
|
||||||
:config="tableConfig"
|
:config="tableConfig"
|
||||||
:model="model[name]"
|
:model="model[name]"
|
||||||
:name="tableConfig.name"
|
name="hookData"
|
||||||
:prop="prop"
|
:prop="prop"
|
||||||
:size="size"
|
:size="size"
|
||||||
@change="changeHandler"
|
@change="changeHandler"
|
||||||
>
|
>
|
||||||
</m-form-table>
|
</m-form-table>
|
||||||
</TMagicCard>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup name="MEditorCodeSelect">
|
<script lang="ts" setup name="MEditorCodeSelect">
|
||||||
import { computed, defineEmits, defineProps, inject, ref } from 'vue';
|
import { computed, defineEmits, defineProps, inject, watch } from 'vue';
|
||||||
import { map, xor } from 'lodash-es';
|
import { isEmpty, map } from 'lodash-es';
|
||||||
|
|
||||||
import { TMagicCard } from '@tmagic/design';
|
import { FormItem, TableConfig } from '@tmagic/form';
|
||||||
import { FormState, TableConfig } from '@tmagic/form';
|
import { HookType } from '@tmagic/schema';
|
||||||
|
|
||||||
import type { Services } from '../type';
|
import { Services } from '../type';
|
||||||
import { CodeSelectOp } from '../type';
|
|
||||||
const services = inject<Services>('services');
|
const services = inject<Services>('services');
|
||||||
const form = inject<FormState>('mForm');
|
|
||||||
const emit = defineEmits(['change']);
|
const emit = defineEmits(['change']);
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
@ -37,7 +33,7 @@ const props = defineProps<{
|
|||||||
size: 'mini' | 'small' | 'medium';
|
size: 'mini' | 'small' | 'medium';
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const tableConfig = computed(() => {
|
const tableConfig = computed<FormItem>(() => {
|
||||||
const defaultConfig = {
|
const defaultConfig = {
|
||||||
dropSort: true,
|
dropSort: true,
|
||||||
items: [
|
items: [
|
||||||
@ -57,110 +53,41 @@ const tableConfig = computed(() => {
|
|||||||
return [];
|
return [];
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// {
|
|
||||||
// label: '参数',
|
|
||||||
// name: 'params',
|
|
||||||
// filter: v=>JSON.stringify(v)
|
|
||||||
// },
|
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
return {
|
return {
|
||||||
name: 'data',
|
|
||||||
...defaultConfig,
|
...defaultConfig,
|
||||||
...props.config.tableConfig,
|
...props.config.tableConfig,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
// const selectModel = computed(() => {
|
watch(
|
||||||
// console.log("props.model[props.name].data",props.model[props.name].data)
|
() => props.model[props.name],
|
||||||
// return {
|
(value) => {
|
||||||
// [props.name]: props.model[props.name]?.data?.map((item: { codeId: Id }) => item.codeId) || []
|
// 兼容旧的数据结构
|
||||||
// }
|
if (isEmpty(value)) {
|
||||||
// });
|
// 空值或者空数组
|
||||||
|
props.model[props.name] = {
|
||||||
// watch(
|
hookType: HookType.CODE,
|
||||||
// () => selectModel.value,
|
hookData: [],
|
||||||
// () => {
|
|
||||||
// const selectData
|
|
||||||
// if (isEmpty(selectModel)) return;
|
|
||||||
// const hookData = selectModel.value.map((selectedCodeId: Id) => ({
|
|
||||||
// codeId: selectedCodeId,
|
|
||||||
// }));
|
|
||||||
// console.log('hookData', hookData);
|
|
||||||
// if (isEmpty(hookData)) return;
|
|
||||||
// if (!props.model[props.name]?.data || isEmpty(props.model[props.name]?.data)) {
|
|
||||||
// // 新增hook
|
|
||||||
// props.model[props.name] = {
|
|
||||||
// hookType: HookType.CODE,
|
|
||||||
// data: hookData,
|
|
||||||
// };
|
|
||||||
// } else {
|
|
||||||
// // 新增hook data
|
|
||||||
// props.model[props.name].data = {
|
|
||||||
// ...props.model[props.name].data,
|
|
||||||
// ...hookData,
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
// console.log('-0-props.model[props.name]--', props.model[props.name]);
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// deep: true,
|
|
||||||
// immediate: true,
|
|
||||||
// },
|
|
||||||
// );
|
|
||||||
|
|
||||||
const fieldKey = ref('');
|
|
||||||
const multiple = ref(true);
|
|
||||||
const lastTagSnapshot = ref<string[]>([]);
|
|
||||||
|
|
||||||
// watchEffect(async () => {
|
|
||||||
// if (isEmpty(selectModel)) return;
|
|
||||||
// const combineNames = await Promise.all(
|
|
||||||
// selectModel.value[props.name].map(async (id: string) => {
|
|
||||||
// const { name = '' } = (await services?.codeBlockService.getCodeContentById(id)) || {};
|
|
||||||
// return name;
|
|
||||||
// }),
|
|
||||||
// );
|
|
||||||
// fieldKey.value = combineNames.join('-');
|
|
||||||
// });
|
|
||||||
|
|
||||||
const changeHandler = async (value: any) => {
|
|
||||||
console.log('---value--', value);
|
|
||||||
let codeIds = value;
|
|
||||||
if (typeof value === 'string') {
|
|
||||||
multiple.value = false;
|
|
||||||
codeIds = value ? [value] : [];
|
|
||||||
}
|
|
||||||
await setCombineRelation(codeIds);
|
|
||||||
emit('change', value);
|
|
||||||
};
|
};
|
||||||
|
} else if (Array.isArray(value) && value.length > 0) {
|
||||||
// 同步绑定关系
|
// 兼容旧的数据结构 ['code1','code2']
|
||||||
const setCombineRelation = async (codeIds: string[]) => {
|
const hookData = value.map((codeId) => ({
|
||||||
// 组件id
|
codeId,
|
||||||
const { id = '' } = services?.editorService.get('node') || {};
|
}));
|
||||||
|
props.model[props.name] = {
|
||||||
// 兼容单选
|
hookType: HookType.CODE,
|
||||||
let opFlag = CodeSelectOp.CHANGE;
|
hookData,
|
||||||
let diffValues = codeIds;
|
|
||||||
if (multiple.value) {
|
|
||||||
// initValues为表单初始值,当表单内容发生变化时,initValues也会更新,可以理解为上一次表单内容的快照
|
|
||||||
lastTagSnapshot.value = form?.initValues[props.name] || [];
|
|
||||||
opFlag = codeIds.length < lastTagSnapshot.value.length ? CodeSelectOp.DELETE : CodeSelectOp.ADD;
|
|
||||||
diffValues = xor(codeIds, lastTagSnapshot.value) as string[];
|
|
||||||
}
|
|
||||||
// 记录绑定关系
|
|
||||||
await services?.codeBlockService.setCombineRelation(id, diffValues, opFlag, props.prop);
|
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
// const viewHandler = async () => {
|
const changeHandler = async () => {
|
||||||
// if (props.model[props.name].length === 0) {
|
emit('change', props.model[props.name]);
|
||||||
// tMagicMessage.error('请先绑定代码块');
|
};
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// // 记录当前已被绑定的代码块,为查看弹窗的展示内容
|
|
||||||
// await services?.codeBlockService.setCombineIds(props.model[props.name]);
|
|
||||||
// await services?.codeBlockService.setMode(CodeEditorMode.LIST);
|
|
||||||
// services?.codeBlockService.setCodeEditorContent(true, props.model[props.name][0]);
|
|
||||||
// };
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -65,7 +65,7 @@ import { CodeBlockContent } from '@tmagic/schema';
|
|||||||
|
|
||||||
import FunctionEditor from '../../../components/FunctionEditor.vue';
|
import FunctionEditor from '../../../components/FunctionEditor.vue';
|
||||||
import Layout from '../../../components/Layout.vue';
|
import Layout from '../../../components/Layout.vue';
|
||||||
import type { CodeDslList, ListState, Services } from '../../../type';
|
import type { CodeDslItem, ListState, Services } from '../../../type';
|
||||||
import { CodeEditorMode } from '../../../type';
|
import { CodeEditorMode } from '../../../type';
|
||||||
import { serializeConfig } from '../../../utils/editor';
|
import { serializeConfig } from '../../../utils/editor';
|
||||||
|
|
||||||
@ -87,8 +87,6 @@ const editable = computed(() => services?.codeBlockService.getEditStatus());
|
|||||||
// 当前选中组件绑定的代码块id数组
|
// 当前选中组件绑定的代码块id数组
|
||||||
const selectedIds = computed(() => services?.codeBlockService.getCombineIds() || []);
|
const selectedIds = computed(() => services?.codeBlockService.getCombineIds() || []);
|
||||||
|
|
||||||
services?.codeBlockService.getCombineInfo();
|
|
||||||
|
|
||||||
watchEffect(async () => {
|
watchEffect(async () => {
|
||||||
codeConfig.value = cloneDeep(await services?.codeBlockService.getCodeContentById(id.value)) || null;
|
codeConfig.value = cloneDeep(await services?.codeBlockService.getCodeContentById(id.value)) || null;
|
||||||
if (!codeConfig.value) return;
|
if (!codeConfig.value) return;
|
||||||
@ -108,7 +106,7 @@ watchEffect(async () => {
|
|||||||
currentTitle.value = state.codeList[0]?.name || '';
|
currentTitle.value = state.codeList[0]?.name || '';
|
||||||
});
|
});
|
||||||
|
|
||||||
const selectHandler = (data: CodeDslList) => {
|
const selectHandler = (data: CodeDslItem) => {
|
||||||
services?.codeBlockService.setId(data.id);
|
services?.codeBlockService.setId(data.id);
|
||||||
currentTitle.value = data.name;
|
currentTitle.value = data.name;
|
||||||
};
|
};
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
effect="dark"
|
effect="dark"
|
||||||
content="查看绑定关系"
|
content="查看绑定关系"
|
||||||
placement="bottom"
|
placement="bottom"
|
||||||
v-if="state.bindComps[data.id] && state.bindComps[data.id].length > 0"
|
v-if="data.combineInfo && data.combineInfo.length > 0"
|
||||||
>
|
>
|
||||||
<Icon :icon="Link" class="edit-icon" @click.stop="toggleCombineRelation(data)"></Icon>
|
<Icon :icon="Link" class="edit-icon" @click.stop="toggleCombineRelation(data)"></Icon>
|
||||||
</TMagicTooltip>
|
</TMagicTooltip>
|
||||||
@ -53,7 +53,7 @@
|
|||||||
<!-- 展示代码块下绑定的组件 -->
|
<!-- 展示代码块下绑定的组件 -->
|
||||||
<div
|
<div
|
||||||
class="code-comp-map-wrapper"
|
class="code-comp-map-wrapper"
|
||||||
v-if="data.showRelation && state.bindComps[data.id] && state.bindComps[data.id].length > 0"
|
v-if="data.showRelation && data.combineInfo && data.combineInfo.length > 0"
|
||||||
>
|
>
|
||||||
<svg class="arrow-left" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" data-v-029747aa="">
|
<svg class="arrow-left" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" data-v-029747aa="">
|
||||||
<path
|
<path
|
||||||
@ -61,23 +61,14 @@
|
|||||||
d="M609.408 149.376 277.76 489.6a32 32 0 0 0 0 44.672l331.648 340.352a29.12 29.12 0 0 0 41.728 0 30.592 30.592 0 0 0 0-42.752L339.264 511.936l311.872-319.872a30.592 30.592 0 0 0 0-42.688 29.12 29.12 0 0 0-41.728 0z"
|
d="M609.408 149.376 277.76 489.6a32 32 0 0 0 0 44.672l331.648 340.352a29.12 29.12 0 0 0 41.728 0 30.592 30.592 0 0 0 0-42.752L339.264 511.936l311.872-319.872a30.592 30.592 0 0 0 0-42.688 29.12 29.12 0 0 0-41.728 0z"
|
||||||
></path>
|
></path>
|
||||||
</svg>
|
</svg>
|
||||||
<!-- todo 功能暂时隐藏 -->
|
|
||||||
<!-- <TMagicButton
|
|
||||||
v-for="(comp, index) in state.bindComps[data.id]"
|
|
||||||
:key="index"
|
|
||||||
class="code-comp"
|
|
||||||
size="small"
|
|
||||||
:plain="true"
|
|
||||||
>{{ comp.name }}<Icon :icon="Close" class="comp-delete-icon" @click.stop="unbind(comp.id, data.id)"></Icon
|
|
||||||
></TMagicButton> -->
|
|
||||||
<TMagicButton
|
<TMagicButton
|
||||||
v-for="(comp, index) in state.bindComps[data.id]"
|
v-for="(comp, index) in data.combineInfo"
|
||||||
:key="index"
|
:key="index"
|
||||||
class="code-comp"
|
class="code-comp"
|
||||||
size="small"
|
size="small"
|
||||||
:plain="true"
|
:plain="true"
|
||||||
@click.stop="selectComp(comp.id)"
|
@click.stop="selectComp(comp.compId)"
|
||||||
>{{ comp.name }}</TMagicButton
|
>{{ comp.compName }}</TMagicButton
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -96,65 +87,65 @@
|
|||||||
<script lang="ts" setup name="MEditorCodeBlockList">
|
<script lang="ts" setup name="MEditorCodeBlockList">
|
||||||
import { computed, inject, reactive, ref, watch } from 'vue';
|
import { computed, inject, reactive, ref, watch } from 'vue';
|
||||||
import { Close, Edit, Link, View } from '@element-plus/icons-vue';
|
import { Close, Edit, Link, View } from '@element-plus/icons-vue';
|
||||||
import { forIn, isEmpty } from 'lodash-es';
|
import { cloneDeep, forIn, isEmpty } from 'lodash-es';
|
||||||
|
|
||||||
import { TMagicButton, TMagicInput, tMagicMessage, TMagicTooltip, TMagicTree } from '@tmagic/design';
|
import { TMagicButton, TMagicInput, tMagicMessage, TMagicTooltip, TMagicTree } from '@tmagic/design';
|
||||||
import { CodeBlockContent, Id } from '@tmagic/schema';
|
import { CodeBlockContent, Id } from '@tmagic/schema';
|
||||||
import StageCore from '@tmagic/stage';
|
import StageCore from '@tmagic/stage';
|
||||||
|
|
||||||
import Icon from '../../../components/Icon.vue';
|
import Icon from '../../../components/Icon.vue';
|
||||||
import type { Services } from '../../../type';
|
import type { CodeRelation, Services } from '../../../type';
|
||||||
import { CodeDeleteErrorType, CodeDslList, CodeEditorMode, ListRelationState } from '../../../type';
|
import { CodeDeleteErrorType, CodeDslItem, CodeEditorMode, ListState } from '../../../type';
|
||||||
|
|
||||||
import codeBlockEditor from './CodeBlockEditor.vue';
|
import codeBlockEditor from './CodeBlockEditor.vue';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
customError?: (id: string, errorType: CodeDeleteErrorType) => any;
|
customError?: (id: Id, errorType: CodeDeleteErrorType) => any;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const services = inject<Services>('services');
|
const services = inject<Services>('services');
|
||||||
|
|
||||||
// 代码块列表
|
// 代码块列表
|
||||||
const state = reactive<ListRelationState>({
|
const state = reactive<ListState>({
|
||||||
codeList: [],
|
codeList: [],
|
||||||
bindComps: {},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const editable = computed(() => services?.codeBlockService.getEditStatus());
|
const editable = computed(() => services?.codeBlockService.getEditStatus());
|
||||||
|
|
||||||
// 是否展示代码编辑区
|
// 是否展示代码编辑区
|
||||||
const isShowCodeBlockEditor = computed(() => services?.codeBlockService.getCodeEditorShowStatus() || false);
|
const isShowCodeBlockEditor = computed(() => services?.codeBlockService.getCodeEditorShowStatus() || false);
|
||||||
|
// 获取绑定关系
|
||||||
|
const codeCombineInfo = ref<CodeRelation | null>(null);
|
||||||
|
|
||||||
// 根据代码块ID获取其绑定的组件信息
|
// 根据代码块ID获取其绑定的组件信息
|
||||||
const getBindCompsByCodeId = (codeId: string) => {
|
const getBindCompsByCodeId = (codeId: Id) => {
|
||||||
const codeCombineInfo = services?.codeBlockService.getCombineInfo();
|
if (!codeCombineInfo.value || !codeCombineInfo.value[codeId]) return [];
|
||||||
if (!codeCombineInfo) return null;
|
const bindCompsId = Object.keys(codeCombineInfo.value[codeId]);
|
||||||
const bindCompsId = Object.keys(codeCombineInfo[codeId]);
|
return bindCompsId.map((compId) => ({
|
||||||
const compsInfo = bindCompsId.map((compId) => ({
|
compId,
|
||||||
id: compId,
|
compName: getCompName(compId),
|
||||||
name: getCompName(compId),
|
|
||||||
}));
|
}));
|
||||||
state.bindComps[codeId] = compsInfo;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 初始化代码块列表
|
// 初始化代码块列表
|
||||||
const initList = async () => {
|
const initList = async () => {
|
||||||
const codeDsl = (await services?.codeBlockService.getCodeDsl()) || null;
|
const codeDsl = cloneDeep(await services?.codeBlockService.getCodeDsl()) || null;
|
||||||
if (!codeDsl) return;
|
codeCombineInfo.value = cloneDeep(services?.codeBlockService.getCombineInfo()) || null;
|
||||||
|
if (!codeDsl || !codeCombineInfo.value) return;
|
||||||
state.codeList = [];
|
state.codeList = [];
|
||||||
forIn(codeDsl, (value: CodeBlockContent, codeId: string) => {
|
forIn(codeDsl, (value: CodeBlockContent, codeId: Id) => {
|
||||||
getBindCompsByCodeId(codeId);
|
|
||||||
state.codeList.push({
|
state.codeList.push({
|
||||||
id: codeId,
|
id: codeId,
|
||||||
name: value.name,
|
name: value.name,
|
||||||
codeBlockContent: value,
|
codeBlockContent: value,
|
||||||
showRelation: true,
|
showRelation: true,
|
||||||
|
combineInfo: getBindCompsByCodeId(codeId),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => services?.codeBlockService.getCodeDsl(),
|
[() => services?.codeBlockService.getCodeDsl(), () => services?.codeBlockService.refreshCombineInfo()],
|
||||||
() => {
|
() => {
|
||||||
initList();
|
initList();
|
||||||
},
|
},
|
||||||
@ -164,21 +155,6 @@ watch(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// 监听组件名称修改,更新到代码块列表
|
|
||||||
watch(
|
|
||||||
() => services?.editorService.get('node'),
|
|
||||||
(curNode) => {
|
|
||||||
if (!curNode?.id) return;
|
|
||||||
forIn(state.bindComps, (bindCompInfo) => {
|
|
||||||
bindCompInfo.forEach((comp) => {
|
|
||||||
if (comp.id === curNode.id) {
|
|
||||||
comp.name = curNode.name;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
// 新增代码块
|
// 新增代码块
|
||||||
const createCodeBlock = async () => {
|
const createCodeBlock = async () => {
|
||||||
const { codeBlockService } = services || {};
|
const { codeBlockService } = services || {};
|
||||||
@ -197,14 +173,15 @@ const createCodeBlock = async () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 编辑代码块
|
// 编辑代码块
|
||||||
const editCode = async (key: string) => {
|
const editCode = async (key: Id) => {
|
||||||
await services?.codeBlockService.setMode(CodeEditorMode.EDITOR);
|
await services?.codeBlockService.setMode(CodeEditorMode.EDITOR);
|
||||||
services?.codeBlockService.setCodeEditorContent(true, key);
|
services?.codeBlockService.setCodeEditorContent(true, key);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 删除代码块
|
// 删除代码块
|
||||||
const deleteCode = (key: string) => {
|
const deleteCode = (key: Id) => {
|
||||||
const existBinds = !!(state.bindComps[key]?.length > 0);
|
const currentCode = state.codeList.find((codeItem: CodeDslItem) => codeItem.id === key);
|
||||||
|
const existBinds = !isEmpty(currentCode?.combineInfo);
|
||||||
const undeleteableList = services?.codeBlockService.getUndeletableList() || [];
|
const undeleteableList = services?.codeBlockService.getUndeletableList() || [];
|
||||||
if (!existBinds && !undeleteableList.includes(key)) {
|
if (!existBinds && !undeleteableList.includes(key)) {
|
||||||
// 无绑定关系,且不在不可删除列表中
|
// 无绑定关系,且不在不可删除列表中
|
||||||
@ -221,7 +198,7 @@ const deleteCode = (key: string) => {
|
|||||||
const filterText = ref('');
|
const filterText = ref('');
|
||||||
const tree = ref();
|
const tree = ref();
|
||||||
|
|
||||||
const filterNode = (value: string, data: CodeDslList): boolean => {
|
const filterNode = (value: string, data: CodeDslItem): boolean => {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -233,7 +210,7 @@ const filterTextChangeHandler = (val: string) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 展示/隐藏组件绑定关系
|
// 展示/隐藏组件绑定关系
|
||||||
const toggleCombineRelation = (data: CodeDslList) => {
|
const toggleCombineRelation = (data: CodeDslItem) => {
|
||||||
const { id } = data;
|
const { id } = data;
|
||||||
const currentCode = state.codeList.find((item) => item.id === id);
|
const currentCode = state.codeList.find((item) => item.id === id);
|
||||||
if (!currentCode) return;
|
if (!currentCode) return;
|
||||||
@ -246,17 +223,6 @@ const getCompName = (compId: Id): string => {
|
|||||||
return node?.name || String(compId);
|
return node?.name || String(compId);
|
||||||
};
|
};
|
||||||
|
|
||||||
// todo 功能暂时隐藏
|
|
||||||
// 解除绑定
|
|
||||||
// const unbind = async (compId: Id, codeId: string) => {
|
|
||||||
// const res = await services?.codeBlockService.unbind(compId, codeId, codeHooks);
|
|
||||||
// if (res) {
|
|
||||||
// ElMessage.success('绑定关系解除成功');
|
|
||||||
// } else {
|
|
||||||
// ElMessage.error('绑定关系解除失败');
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
// 选中组件
|
// 选中组件
|
||||||
const selectComp = (compId: Id) => {
|
const selectComp = (compId: Id) => {
|
||||||
const stage = services?.editorService.get<StageCore | null>('stage');
|
const stage = services?.editorService.get<StageCore | null>('stage');
|
||||||
|
@ -23,8 +23,8 @@ import { CodeBlockContent, CodeBlockDSL, HookType, Id, MApp, MNode } from '@tmag
|
|||||||
|
|
||||||
import editorService from '../services/editor';
|
import editorService from '../services/editor';
|
||||||
import type { CodeRelation, CodeState, HookData } from '../type';
|
import type { CodeRelation, CodeState, HookData } from '../type';
|
||||||
import { CODE_DRAFT_STORAGE_KEY, CodeEditorMode, CodeSelectOp } from '../type';
|
import { CODE_DRAFT_STORAGE_KEY, CodeEditorMode } from '../type';
|
||||||
import { error, info } from '../utils/logger';
|
import { info } from '../utils/logger';
|
||||||
|
|
||||||
import BaseService from './BaseService';
|
import BaseService from './BaseService';
|
||||||
|
|
||||||
@ -242,84 +242,23 @@ class CodeBlock extends BaseService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置绑定关系
|
* 刷新绑定关系
|
||||||
* @param {Id} 组件id
|
|
||||||
* @param {string[]} diffCodeIds 代码块id数组
|
|
||||||
* @param {CodeSelectOp} opFlag 操作类型
|
|
||||||
* @param {string} hook 代码块挂载hook名称
|
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
public async setCombineRelation(compId: Id, diffCodeIds: string[], opFlag: CodeSelectOp, hook: string) {
|
public refreshCombineInfo(): CodeRelation | null {
|
||||||
const combineInfo = this.getCombineInfo();
|
const root = editorService.get<MApp | null>('root');
|
||||||
if (!combineInfo) return;
|
if (!root) return null;
|
||||||
if (opFlag === CodeSelectOp.DELETE) {
|
const relations = {};
|
||||||
try {
|
this.recurseMNode(root, relations);
|
||||||
diffCodeIds.forEach((codeId) => {
|
this.state.relations = relations;
|
||||||
const compsContent = combineInfo[codeId];
|
return this.state.relations;
|
||||||
const index = compsContent?.[compId].findIndex((item) => item === hook);
|
|
||||||
if (typeof index !== 'undefined' && index !== -1) {
|
|
||||||
compsContent?.[compId].splice(index, 1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
error(e);
|
|
||||||
throw new Error('解绑代码块失败');
|
|
||||||
}
|
|
||||||
} else if (opFlag === CodeSelectOp.ADD) {
|
|
||||||
try {
|
|
||||||
diffCodeIds.forEach((codeId) => {
|
|
||||||
const compsContent = combineInfo[codeId];
|
|
||||||
const existHooks = compsContent?.[compId];
|
|
||||||
if (isEmpty(existHooks)) {
|
|
||||||
// comps属性不存在,或者comps为空:新增
|
|
||||||
combineInfo[codeId] = {
|
|
||||||
...(combineInfo[codeId] || {}),
|
|
||||||
[compId]: [hook],
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
// 往已有的关系中添加hook
|
|
||||||
existHooks?.push(hook);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
error(e);
|
|
||||||
throw new Error('绑定代码块失败');
|
|
||||||
}
|
|
||||||
} else if (opFlag === CodeSelectOp.CHANGE) {
|
|
||||||
// 单选修改
|
|
||||||
forIn(combineInfo, (combineItem, codeId) => {
|
|
||||||
if (codeId === diffCodeIds[0]) {
|
|
||||||
// 增加
|
|
||||||
combineItem = {
|
|
||||||
...(combineItem || {}),
|
|
||||||
[compId]: [hook],
|
|
||||||
};
|
|
||||||
} else if (isEmpty(diffCodeIds) || codeId !== diffCodeIds[0]) {
|
|
||||||
// 清空或者移除之前的选项
|
|
||||||
const compHooks = combineItem?.[compId];
|
|
||||||
// continue
|
|
||||||
if (!compHooks) return true;
|
|
||||||
const index = compHooks.findIndex((hookName) => hookName === hook);
|
|
||||||
if (index !== -1) {
|
|
||||||
compHooks.splice(index, 1);
|
|
||||||
// break
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
console.log('---combineInfo--', combineInfo);
|
|
||||||
console.log('---this.state.relations--', this.state.relations);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取绑定关系
|
* 获取绑定关系
|
||||||
* @returns {CodeRelation | null}
|
* @returns {CodeRelation}
|
||||||
*/
|
*/
|
||||||
public getCombineInfo(): CodeRelation | null {
|
public getCombineInfo(): CodeRelation {
|
||||||
const root = editorService.get<MApp | null>('root');
|
|
||||||
if (!root) return null;
|
|
||||||
this.recurseMNode(root);
|
|
||||||
return this.state.relations;
|
return this.state.relations;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -429,17 +368,19 @@ class CodeBlock extends BaseService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 递归遍历dsl中挂载了代码块的节点,并更新绑定关系数据
|
* 递归遍历dsl中挂载了代码块的节点,并更新绑定关系数据
|
||||||
* @param {MNode} node 节点信息
|
* @param {MContainer} node 节点信息
|
||||||
* @returns void
|
* @returns void
|
||||||
*/
|
*/
|
||||||
private recurseMNode(node: MNode) {
|
private recurseMNode(node: MNode, relations: CodeRelation) {
|
||||||
forIn(node, (value, key) => {
|
forIn(node, (value, key) => {
|
||||||
if (value?.hookType === HookType.CODE && !isEmpty(value?.data)) {
|
if (value?.hookType === HookType.CODE && !isEmpty(value.hookData)) {
|
||||||
value.data.forEach((relationItem: HookData) => {
|
value.hookData.forEach((relationItem: HookData) => {
|
||||||
if (!this.state.relations[relationItem.codeId]) {
|
// continue
|
||||||
this.state.relations[relationItem.codeId] = {};
|
if (!relationItem.codeId) return;
|
||||||
|
if (!relations[relationItem.codeId]) {
|
||||||
|
relations[relationItem.codeId] = {};
|
||||||
}
|
}
|
||||||
const codeItem = this.state.relations[relationItem.codeId];
|
const codeItem = relations[relationItem.codeId];
|
||||||
if (isEmpty(codeItem[node.id])) {
|
if (isEmpty(codeItem[node.id])) {
|
||||||
codeItem[node.id] = [];
|
codeItem[node.id] = [];
|
||||||
}
|
}
|
||||||
@ -449,7 +390,7 @@ class CodeBlock extends BaseService {
|
|||||||
});
|
});
|
||||||
if (!isEmpty(node.items)) {
|
if (!isEmpty(node.items)) {
|
||||||
node.items.forEach((item: MNode) => {
|
node.items.forEach((item: MNode) => {
|
||||||
this.recurseMNode(item);
|
this.recurseMNode(item, relations);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { reactive, toRaw } from 'vue';
|
import { reactive, toRaw } from 'vue';
|
||||||
import { cloneDeep, mergeWith, uniq } from 'lodash-es';
|
import { cloneDeep, isObject, mergeWith, uniq } from 'lodash-es';
|
||||||
|
|
||||||
import type { CodeBlockDSL, Id, MApp, MComponent, MContainer, MNode, MPage } from '@tmagic/schema';
|
import type { CodeBlockDSL, Id, MApp, MComponent, MContainer, MNode, MPage } from '@tmagic/schema';
|
||||||
import { NodeType } from '@tmagic/schema';
|
import { NodeType } from '@tmagic/schema';
|
||||||
@ -459,6 +459,11 @@ class Editor extends BaseService {
|
|||||||
let newConfig = await this.toggleFixedPosition(toRaw(config), node, this.get<MApp>('root'));
|
let newConfig = await this.toggleFixedPosition(toRaw(config), node, this.get<MApp>('root'));
|
||||||
|
|
||||||
newConfig = mergeWith(cloneDeep(node), newConfig, (objValue, srcValue) => {
|
newConfig = mergeWith(cloneDeep(node), newConfig, (objValue, srcValue) => {
|
||||||
|
if (isObject(srcValue) && Array.isArray(objValue)) {
|
||||||
|
// 原来的配置是数组,新的配置是对象,则直接使用新的值
|
||||||
|
console.log('--srcValue-', srcValue);
|
||||||
|
return srcValue;
|
||||||
|
}
|
||||||
if (Array.isArray(srcValue)) {
|
if (Array.isArray(srcValue)) {
|
||||||
return srcValue;
|
return srcValue;
|
||||||
}
|
}
|
||||||
@ -521,7 +526,7 @@ class Editor extends BaseService {
|
|||||||
this.pushHistoryState();
|
this.pushHistoryState();
|
||||||
|
|
||||||
this.emit('update', newNodes);
|
this.emit('update', newNodes);
|
||||||
|
codeBlockService.refreshCombineInfo();
|
||||||
return Array.isArray(config) ? newNodes : newNodes[0];
|
return Array.isArray(config) ? newNodes : newNodes[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -349,7 +349,7 @@ export enum CodeEditorMode {
|
|||||||
EDITOR = 'editor',
|
EDITOR = 'editor',
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CodeDslList {
|
export interface CodeDslItem {
|
||||||
/** 代码块id */
|
/** 代码块id */
|
||||||
id: Id;
|
id: Id;
|
||||||
/** 代码块名称 */
|
/** 代码块名称 */
|
||||||
@ -358,19 +358,20 @@ export interface CodeDslList {
|
|||||||
codeBlockContent?: CodeBlockContent;
|
codeBlockContent?: CodeBlockContent;
|
||||||
/** 是否展示代码绑定关系 */
|
/** 是否展示代码绑定关系 */
|
||||||
showRelation?: boolean;
|
showRelation?: boolean;
|
||||||
|
/** 代码块对应绑定的组件信息 */
|
||||||
|
combineInfo?: CombineInfo[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CombineInfo {
|
||||||
|
/** 组件id */
|
||||||
|
compId: Id;
|
||||||
|
/** 组件名称 */
|
||||||
|
compName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ListState {
|
export interface ListState {
|
||||||
/** 代码块列表 */
|
/** 代码块列表 */
|
||||||
codeList: CodeDslList[];
|
codeList: CodeDslItem[];
|
||||||
}
|
|
||||||
|
|
||||||
export interface ListRelationState extends ListState {
|
|
||||||
/** 与代码块绑定的组件信息 */
|
|
||||||
bindComps: {
|
|
||||||
/** 代码块id : 组件信息 */
|
|
||||||
[id: Id]: MNode[];
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum CodeDeleteErrorType {
|
export enum CodeDeleteErrorType {
|
||||||
@ -380,14 +381,5 @@ export enum CodeDeleteErrorType {
|
|||||||
BIND = 'bind',
|
BIND = 'bind',
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum CodeSelectOp {
|
|
||||||
/** 增加 */
|
|
||||||
ADD = 'add',
|
|
||||||
/** 删除 */
|
|
||||||
DELETE = 'delete',
|
|
||||||
/** 单选修改 */
|
|
||||||
CHANGE = 'change',
|
|
||||||
}
|
|
||||||
|
|
||||||
// 代码块草稿localStorage key
|
// 代码块草稿localStorage key
|
||||||
export const CODE_DRAFT_STORAGE_KEY = 'magicCodeDraft';
|
export const CODE_DRAFT_STORAGE_KEY = 'magicCodeDraft';
|
||||||
|
@ -226,14 +226,14 @@ export const fillConfig = (config: FormConfig = []) => [
|
|||||||
{
|
{
|
||||||
name: 'created',
|
name: 'created',
|
||||||
text: 'created',
|
text: 'created',
|
||||||
type: 'code-select',
|
|
||||||
labelWidth: '100px',
|
labelWidth: '100px',
|
||||||
|
type: 'code-select',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'mounted',
|
name: 'mounted',
|
||||||
text: 'mounted',
|
text: 'mounted',
|
||||||
type: 'code-select',
|
|
||||||
labelWidth: '100px',
|
labelWidth: '100px',
|
||||||
|
type: 'code-select',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -59,7 +59,7 @@ export default {
|
|||||||
events: [],
|
events: [],
|
||||||
created: {
|
created: {
|
||||||
hookType: 'code',
|
hookType: 'code',
|
||||||
data: [
|
hookData: [
|
||||||
{
|
{
|
||||||
codeId: 'code_5336',
|
codeId: 'code_5336',
|
||||||
params: {
|
params: {
|
||||||
@ -74,7 +74,7 @@ export default {
|
|||||||
},
|
},
|
||||||
mounted: {
|
mounted: {
|
||||||
hookType: 'code',
|
hookType: 'code',
|
||||||
data: [
|
hookData: [
|
||||||
{
|
{
|
||||||
codeId: 'code_5316',
|
codeId: 'code_5316',
|
||||||
},
|
},
|
||||||
@ -106,7 +106,7 @@ export default {
|
|||||||
events: [],
|
events: [],
|
||||||
created: {
|
created: {
|
||||||
hookType: 'code',
|
hookType: 'code',
|
||||||
data: [
|
hookData: [
|
||||||
{
|
{
|
||||||
codeId: 'code_5316',
|
codeId: 'code_5316',
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user