mirror of
https://github.com/Tencent/tmagic-editor.git
synced 2025-06-29 13:59:17 +08:00
feat(editor): 修改service get set 方法的ts定义,不再需要传入泛型参数
This commit is contained in:
parent
23708e4644
commit
0491487385
@ -228,7 +228,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
const rootChangeHandler = (value: MApp, preValue?: MApp | null) => {
|
const rootChangeHandler = (value: MApp, preValue?: MApp | null) => {
|
||||||
const nodeId = editorService.get<MNode | null>('node')?.id || props.defaultSelected;
|
const nodeId = editorService.get('node')?.id || props.defaultSelected;
|
||||||
let node;
|
let node;
|
||||||
if (nodeId) {
|
if (nodeId) {
|
||||||
node = editorService.getNodeById(nodeId);
|
node = editorService.getNodeById(nodeId);
|
||||||
|
@ -37,7 +37,7 @@ const uiSelectMode = ref(false);
|
|||||||
|
|
||||||
const cancelHandler = () => {
|
const cancelHandler = () => {
|
||||||
if (!services?.uiService) return;
|
if (!services?.uiService) return;
|
||||||
services.uiService.set<boolean>('uiSelectMode', false);
|
services.uiService.set('uiSelectMode', false);
|
||||||
uiSelectMode.value = false;
|
uiSelectMode.value = false;
|
||||||
globalThis.document.removeEventListener('ui-select', clickHandler as EventListener);
|
globalThis.document.removeEventListener('ui-select', clickHandler as EventListener);
|
||||||
};
|
};
|
||||||
@ -61,7 +61,7 @@ const toName = computed(() => {
|
|||||||
|
|
||||||
const startSelect = () => {
|
const startSelect = () => {
|
||||||
if (!services?.uiService) return;
|
if (!services?.uiService) return;
|
||||||
services.uiService.set<boolean>('uiSelectMode', true);
|
services.uiService.set('uiSelectMode', true);
|
||||||
uiSelectMode.value = true;
|
uiSelectMode.value = true;
|
||||||
globalThis.document.addEventListener('ui-select', clickHandler as EventListener);
|
globalThis.document.addEventListener('ui-select', clickHandler as EventListener);
|
||||||
};
|
};
|
||||||
|
@ -28,9 +28,12 @@ const clickHandler = () => {
|
|||||||
|
|
||||||
if (!editorService) return;
|
if (!editorService) return;
|
||||||
|
|
||||||
|
const root = toRaw(editorService.get('root'));
|
||||||
|
if (!root) throw new Error('root 不能为空');
|
||||||
|
|
||||||
editorService.add({
|
editorService.add({
|
||||||
type: NodeType.PAGE,
|
type: NodeType.PAGE,
|
||||||
name: generatePageNameByApp(toRaw(editorService.get('root'))),
|
name: generatePageNameByApp(root),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@ -46,7 +46,6 @@
|
|||||||
import { computed, inject, ref, watch } from 'vue';
|
import { computed, inject, ref, watch } from 'vue';
|
||||||
|
|
||||||
import { TMagicScrollbar } from '@tmagic/design';
|
import { TMagicScrollbar } from '@tmagic/design';
|
||||||
import type { MApp } from '@tmagic/schema';
|
|
||||||
|
|
||||||
import Layout from '../components/Layout.vue';
|
import Layout from '../components/Layout.vue';
|
||||||
import { GetColumnWidth, Services } from '../type';
|
import { GetColumnWidth, Services } from '../type';
|
||||||
@ -67,11 +66,11 @@ withDefaults(
|
|||||||
|
|
||||||
const { editorService, uiService } = inject<Services>('services') || {};
|
const { editorService, uiService } = inject<Services>('services') || {};
|
||||||
|
|
||||||
const root = computed(() => editorService?.get<MApp>('root'));
|
const root = computed(() => editorService?.get('root'));
|
||||||
const nodes = computed(() => editorService?.get<Node[]>('nodes') || []);
|
const nodes = computed(() => editorService?.get('nodes') || []);
|
||||||
|
|
||||||
const pageLength = computed(() => editorService?.get<number>('pageLength') || 0);
|
const pageLength = computed(() => editorService?.get('pageLength') || 0);
|
||||||
const showSrc = computed(() => uiService?.get<boolean>('showSrc'));
|
const showSrc = computed(() => uiService?.get('showSrc'));
|
||||||
|
|
||||||
const LEFT_COLUMN_WIDTH_STORAGE_KEY = '$MagicEditorLeftColumnWidthData';
|
const LEFT_COLUMN_WIDTH_STORAGE_KEY = '$MagicEditorLeftColumnWidthData';
|
||||||
const RIGHT_COLUMN_WIDTH_STORAGE_KEY = '$MagicEditorRightColumnWidthData';
|
const RIGHT_COLUMN_WIDTH_STORAGE_KEY = '$MagicEditorRightColumnWidthData';
|
||||||
@ -101,7 +100,7 @@ watch(
|
|||||||
columnWidth.value.center = globalThis.document.body.clientWidth - left - right;
|
columnWidth.value.center = globalThis.document.body.clientWidth - left - right;
|
||||||
}
|
}
|
||||||
|
|
||||||
uiService?.set('columnWidth', columnWidth);
|
uiService?.set('columnWidth', columnWidth.value as GetColumnWidth);
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
immediate: true,
|
immediate: true,
|
||||||
|
@ -13,7 +13,7 @@ import { Back, Delete, FullScreen, Grid, Memo, Right, ScaleToOriginal, ZoomIn, Z
|
|||||||
import { NodeType } from '@tmagic/schema';
|
import { NodeType } from '@tmagic/schema';
|
||||||
|
|
||||||
import ToolButton from '../components/ToolButton.vue';
|
import ToolButton from '../components/ToolButton.vue';
|
||||||
import { ColumnLayout, GetColumnWidth, MenuBarData, MenuButton, MenuComponent, MenuItem, Services } from '../type';
|
import { ColumnLayout, MenuBarData, MenuButton, MenuComponent, MenuItem, Services } from '../type';
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
@ -29,12 +29,12 @@ const props = withDefaults(
|
|||||||
const services = inject<Services>('services');
|
const services = inject<Services>('services');
|
||||||
const uiService = services?.uiService;
|
const uiService = services?.uiService;
|
||||||
|
|
||||||
const columnWidth = computed(() => services?.uiService.get<GetColumnWidth>('columnWidth'));
|
const columnWidth = computed(() => services?.uiService.get('columnWidth'));
|
||||||
const keys = Object.values(ColumnLayout);
|
const keys = Object.values(ColumnLayout);
|
||||||
|
|
||||||
const showGuides = computed((): boolean => uiService?.get<boolean>('showGuides') ?? true);
|
const showGuides = computed((): boolean => uiService?.get('showGuides') ?? true);
|
||||||
const showRule = computed((): boolean => uiService?.get<boolean>('showRule') ?? true);
|
const showRule = computed((): boolean => uiService?.get('showRule') ?? true);
|
||||||
const zoom = computed((): number => uiService?.get<number>('zoom') ?? 1);
|
const zoom = computed((): number => uiService?.get('zoom') ?? 1);
|
||||||
|
|
||||||
const isMac = /mac os x/.test(navigator.userAgent.toLowerCase());
|
const isMac = /mac os x/.test(navigator.userAgent.toLowerCase());
|
||||||
const ctrl = isMac ? 'Command' : 'Ctrl';
|
const ctrl = isMac ? 'Command' : 'Ctrl';
|
||||||
@ -67,7 +67,10 @@ const getConfig = (item: MenuItem): (MenuButton | MenuComponent)[] => {
|
|||||||
icon: markRaw(Delete),
|
icon: markRaw(Delete),
|
||||||
tooltip: `刪除(Delete)`,
|
tooltip: `刪除(Delete)`,
|
||||||
disabled: () => services?.editorService.get('node')?.type === NodeType.PAGE,
|
disabled: () => services?.editorService.get('node')?.type === NodeType.PAGE,
|
||||||
handler: () => services?.editorService.remove(services?.editorService.get('node')),
|
handler: () => {
|
||||||
|
const node = services?.editorService.get('node');
|
||||||
|
node && services?.editorService.remove(node);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 'undo':
|
case 'undo':
|
||||||
|
@ -19,8 +19,6 @@ import { computed, getCurrentInstance, inject, onMounted, onUnmounted, ref, watc
|
|||||||
import { tMagicMessage } from '@tmagic/design';
|
import { tMagicMessage } from '@tmagic/design';
|
||||||
import type { FormValue } from '@tmagic/form';
|
import type { FormValue } from '@tmagic/form';
|
||||||
import { MForm } from '@tmagic/form';
|
import { MForm } from '@tmagic/form';
|
||||||
import type { MNode } from '@tmagic/schema';
|
|
||||||
import type StageCore from '@tmagic/stage';
|
|
||||||
|
|
||||||
import type { Services } from '../type';
|
import type { Services } from '../type';
|
||||||
|
|
||||||
@ -32,11 +30,9 @@ const configForm = ref<InstanceType<typeof MForm>>();
|
|||||||
// ts类型应该是FormConfig, 但是打包时会出错,所以暂时用any
|
// ts类型应该是FormConfig, 但是打包时会出错,所以暂时用any
|
||||||
const curFormConfig = ref<any>([]);
|
const curFormConfig = ref<any>([]);
|
||||||
const services = inject<Services>('services');
|
const services = inject<Services>('services');
|
||||||
const node = computed(() => services?.editorService.get<MNode | null>('node'));
|
const node = computed(() => services?.editorService.get('node'));
|
||||||
const propsPanelSize = computed(
|
const propsPanelSize = computed(() => services?.uiService.get('propsPanelSize') || 'small');
|
||||||
() => services?.uiService.get<'large' | 'default' | 'small'>('propsPanelSize') || 'small',
|
const stage = computed(() => services?.editorService.get('stage'));
|
||||||
);
|
|
||||||
const stage = computed(() => services?.editorService.get<StageCore>('stage'));
|
|
||||||
|
|
||||||
const init = async () => {
|
const init = async () => {
|
||||||
if (!node.value) {
|
if (!node.value) {
|
||||||
|
@ -44,7 +44,6 @@ import { Grid, Search } from '@element-plus/icons-vue';
|
|||||||
import serialize from 'serialize-javascript';
|
import serialize from 'serialize-javascript';
|
||||||
|
|
||||||
import { TMagicCollapse, TMagicCollapseItem, TMagicInput, TMagicScrollbar, TMagicTooltip } from '@tmagic/design';
|
import { TMagicCollapse, TMagicCollapseItem, TMagicInput, TMagicScrollbar, TMagicTooltip } from '@tmagic/design';
|
||||||
import type StageCore from '@tmagic/stage';
|
|
||||||
import { removeClassNameByClassName } from '@tmagic/utils';
|
import { removeClassNameByClassName } from '@tmagic/utils';
|
||||||
|
|
||||||
import MIcon from '../../components/Icon.vue';
|
import MIcon from '../../components/Icon.vue';
|
||||||
@ -54,7 +53,7 @@ const searchText = ref('');
|
|||||||
const services = inject<Services>('services');
|
const services = inject<Services>('services');
|
||||||
const stageOptions = inject<StageOptions>('stageOptions');
|
const stageOptions = inject<StageOptions>('stageOptions');
|
||||||
|
|
||||||
const stage = computed(() => services?.editorService.get<StageCore>('stage'));
|
const stage = computed(() => services?.editorService.get('stage'));
|
||||||
const list = computed(() =>
|
const list = computed(() =>
|
||||||
services?.componentListService.getList().map((group: ComponentGroup) => ({
|
services?.componentListService.getList().map((group: ComponentGroup) => ({
|
||||||
...group,
|
...group,
|
||||||
|
@ -65,7 +65,6 @@ import { difference, throttle, union } from 'lodash-es';
|
|||||||
import { TMagicInput, TMagicScrollbar, TMagicTree } from '@tmagic/design';
|
import { TMagicInput, TMagicScrollbar, TMagicTree } from '@tmagic/design';
|
||||||
import type { Id, MNode, MPage } from '@tmagic/schema';
|
import type { Id, MNode, MPage } from '@tmagic/schema';
|
||||||
import { MContainer, NodeType } from '@tmagic/schema';
|
import { MContainer, NodeType } from '@tmagic/schema';
|
||||||
import StageCore from '@tmagic/stage';
|
|
||||||
import { getNodePath, isPage } from '@tmagic/utils';
|
import { getNodePath, isPage } from '@tmagic/utils';
|
||||||
|
|
||||||
import type { MenuButton, MenuComponent, Services } from '../../type';
|
import type { MenuButton, MenuComponent, Services } from '../../type';
|
||||||
@ -108,8 +107,8 @@ const treeProps = {
|
|||||||
|
|
||||||
const isMultiSelect = computed(() => isCtrlKeyDown.value || checkedKeys.value.length > 1);
|
const isMultiSelect = computed(() => isCtrlKeyDown.value || checkedKeys.value.length > 1);
|
||||||
|
|
||||||
const nodes = computed(() => editorService?.get<MNode[]>('nodes') || []);
|
const nodes = computed(() => editorService?.get('nodes') || []);
|
||||||
const page = computed(() => editorService?.get<MPage>('page'));
|
const page = computed(() => editorService?.get('page'));
|
||||||
const values = computed(() => (page.value ? [page.value] : []));
|
const values = computed(() => (page.value ? [page.value] : []));
|
||||||
// 高亮的节点
|
// 高亮的节点
|
||||||
const highlightNode = computed(() => editorService?.get('highlightNode'));
|
const highlightNode = computed(() => editorService?.get('highlightNode'));
|
||||||
@ -121,13 +120,13 @@ const select = async (data: MNode) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await editorService?.select(data);
|
await editorService?.select(data);
|
||||||
editorService?.get<StageCore>('stage')?.select(data.id);
|
editorService?.get('stage')?.select(data.id);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 触发画布多选
|
// 触发画布多选
|
||||||
const multiSelect = async (data: Id[]) => {
|
const multiSelect = async (data: Id[]) => {
|
||||||
await editorService?.multiSelect(data);
|
await editorService?.multiSelect(data);
|
||||||
editorService?.get<StageCore>('stage')?.multiSelect(data);
|
editorService?.get('stage')?.multiSelect(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 触发画布高亮
|
// 触发画布高亮
|
||||||
@ -136,7 +135,7 @@ const highlight = (data: MNode) => {
|
|||||||
throw new Error('没有id');
|
throw new Error('没有id');
|
||||||
}
|
}
|
||||||
editorService?.highlight(data);
|
editorService?.highlight(data);
|
||||||
editorService?.get<StageCore>('stage')?.highlight(data.id);
|
editorService?.get('stage')?.highlight(data.id);
|
||||||
};
|
};
|
||||||
|
|
||||||
// tree方法:拖拽时判定目标节点能否成为拖动目标位置
|
// tree方法:拖拽时判定目标节点能否成为拖动目标位置
|
||||||
@ -230,14 +229,14 @@ watch(nodes, (nodes) => {
|
|||||||
|
|
||||||
watch(isMultiSelect, (isMultiSelect) => {
|
watch(isMultiSelect, (isMultiSelect) => {
|
||||||
if (!isMultiSelect) {
|
if (!isMultiSelect) {
|
||||||
currentNodeKey.value = editorService?.get<MNode>('node').id;
|
currentNodeKey.value = editorService?.get('node')?.id;
|
||||||
tree.value?.setCurrentKey(currentNodeKey.value);
|
tree.value?.setCurrentKey(currentNodeKey.value);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const editorServiceRemoveHandler = () => {
|
const editorServiceRemoveHandler = () => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
tree.value?.getNode(editorService?.get('node').id)?.updateChildren();
|
tree.value?.getNode(editorService?.get('node')?.id)?.updateChildren();
|
||||||
}, 0);
|
}, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -300,7 +299,7 @@ const clickHandler = (data: MNode): void => {
|
|||||||
if (isCtrlKeyDown.value) {
|
if (isCtrlKeyDown.value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (services?.uiService.get<boolean>('uiSelectMode')) {
|
if (services?.uiService.get('uiSelectMode')) {
|
||||||
document.dispatchEvent(new CustomEvent('ui-select', { detail: data }));
|
document.dispatchEvent(new CustomEvent('ui-select', { detail: data }));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,6 @@ import { cloneDeep, forIn, isEmpty } from 'lodash-es';
|
|||||||
|
|
||||||
import { TMagicButton, TMagicInput, tMagicMessage, TMagicScrollbar, TMagicTooltip, TMagicTree } from '@tmagic/design';
|
import { TMagicButton, TMagicInput, tMagicMessage, TMagicScrollbar, TMagicTooltip, TMagicTree } from '@tmagic/design';
|
||||||
import { CodeBlockContent, Id } from '@tmagic/schema';
|
import { CodeBlockContent, Id } from '@tmagic/schema';
|
||||||
import StageCore from '@tmagic/stage';
|
|
||||||
|
|
||||||
import Icon from '../../../components/Icon.vue';
|
import Icon from '../../../components/Icon.vue';
|
||||||
import type { CodeRelation, Services } from '../../../type';
|
import type { CodeRelation, Services } from '../../../type';
|
||||||
@ -228,7 +227,7 @@ const getCompName = (compId: Id): string => {
|
|||||||
|
|
||||||
// 选中组件
|
// 选中组件
|
||||||
const selectComp = (compId: Id) => {
|
const selectComp = (compId: Id) => {
|
||||||
const stage = services?.editorService.get<StageCore | null>('stage');
|
const stage = services?.editorService.get('stage');
|
||||||
services?.editorService.select(compId);
|
services?.editorService.select(compId);
|
||||||
stage?.select(compId);
|
stage?.select(compId);
|
||||||
};
|
};
|
||||||
|
@ -11,8 +11,7 @@
|
|||||||
import { computed, inject } from 'vue';
|
import { computed, inject } from 'vue';
|
||||||
|
|
||||||
import { TMagicButton } from '@tmagic/design';
|
import { TMagicButton } from '@tmagic/design';
|
||||||
import type { MApp, MNode } from '@tmagic/schema';
|
import type { MNode } from '@tmagic/schema';
|
||||||
import type StageCore from '@tmagic/stage';
|
|
||||||
import { getNodePath } from '@tmagic/utils';
|
import { getNodePath } from '@tmagic/utils';
|
||||||
|
|
||||||
import type { Services } from '../../type';
|
import type { Services } from '../../type';
|
||||||
@ -20,13 +19,13 @@ import type { Services } from '../../type';
|
|||||||
const services = inject<Services>('services');
|
const services = inject<Services>('services');
|
||||||
const editorService = services?.editorService;
|
const editorService = services?.editorService;
|
||||||
|
|
||||||
const node = computed(() => editorService?.get<MNode>('node'));
|
const node = computed(() => editorService?.get('node'));
|
||||||
const nodes = computed(() => editorService?.get<MNode[]>('nodes') || []);
|
const nodes = computed(() => editorService?.get('nodes') || []);
|
||||||
const root = computed(() => editorService?.get<MApp>('root'));
|
const root = computed(() => editorService?.get('root'));
|
||||||
const path = computed(() => getNodePath(node.value?.id || '', root.value?.items || []));
|
const path = computed(() => getNodePath(node.value?.id || '', root.value?.items || []));
|
||||||
|
|
||||||
const select = async (node: MNode) => {
|
const select = async (node: MNode) => {
|
||||||
await editorService?.select(node);
|
await editorService?.select(node);
|
||||||
editorService?.get<StageCore>('stage')?.select(node.id);
|
editorService?.get('stage')?.select(node.id);
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@ -51,7 +51,7 @@ import { computed, inject } from 'vue';
|
|||||||
import { CaretBottom, Delete, DocumentCopy } from '@element-plus/icons-vue';
|
import { CaretBottom, Delete, DocumentCopy } from '@element-plus/icons-vue';
|
||||||
|
|
||||||
import { TMagicIcon, TMagicPopover, TMagicTooltip } from '@tmagic/design';
|
import { TMagicIcon, TMagicPopover, TMagicTooltip } from '@tmagic/design';
|
||||||
import type { MApp, MPage } from '@tmagic/schema';
|
import type { MPage } from '@tmagic/schema';
|
||||||
|
|
||||||
import ToolButton from '../../components/ToolButton.vue';
|
import ToolButton from '../../components/ToolButton.vue';
|
||||||
import type { Services } from '../../type';
|
import type { Services } from '../../type';
|
||||||
@ -61,7 +61,7 @@ import PageBarScrollContainer from './PageBarScrollContainer.vue';
|
|||||||
const services = inject<Services>('services');
|
const services = inject<Services>('services');
|
||||||
const editorService = services?.editorService;
|
const editorService = services?.editorService;
|
||||||
|
|
||||||
const root = computed(() => editorService?.get<MApp>('root'));
|
const root = computed(() => editorService?.get('root'));
|
||||||
|
|
||||||
const page = computed(() => editorService?.get('page'));
|
const page = computed(() => editorService?.get('page'));
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ const scroll = (type: 'left' | 'right' | 'start' | 'end') => {
|
|||||||
itemsContainer.value.style.transform = `translate(${translateLeft}px, 0px)`;
|
itemsContainer.value.style.transform = `translate(${translateLeft}px, 0px)`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const pageLength = computed(() => editorService?.get<number>('pageLength'));
|
const pageLength = computed(() => editorService?.get('pageLength'));
|
||||||
|
|
||||||
watch(pageLength, (length = 0, preLength = 0) => {
|
watch(pageLength, (length = 0, preLength = 0) => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@ -115,9 +115,11 @@ watch(pageLength, (length = 0, preLength = 0) => {
|
|||||||
|
|
||||||
const addPage = () => {
|
const addPage = () => {
|
||||||
if (!editorService) return;
|
if (!editorService) return;
|
||||||
|
const root = toRaw(editorService.get('root'));
|
||||||
|
if (!root) throw new Error('root 不能为空');
|
||||||
const pageConfig = {
|
const pageConfig = {
|
||||||
type: NodeType.PAGE,
|
type: NodeType.PAGE,
|
||||||
name: generatePageNameByApp(toRaw(editorService.get('root'))),
|
name: generatePageNameByApp(root),
|
||||||
};
|
};
|
||||||
editorService.add(pageConfig);
|
editorService.add(pageConfig);
|
||||||
};
|
};
|
||||||
|
@ -30,11 +30,11 @@
|
|||||||
import { computed, inject, markRaw, nextTick, onMounted, onUnmounted, ref, toRaw, watch, watchEffect } from 'vue';
|
import { computed, inject, markRaw, nextTick, onMounted, onUnmounted, ref, toRaw, watch, watchEffect } from 'vue';
|
||||||
import { cloneDeep } from 'lodash-es';
|
import { cloneDeep } from 'lodash-es';
|
||||||
|
|
||||||
import type { MApp, MContainer, MNode, MPage } from '@tmagic/schema';
|
import type { MContainer } from '@tmagic/schema';
|
||||||
import StageCore, { calcValueByFontsize, getOffset, Runtime } from '@tmagic/stage';
|
import StageCore, { calcValueByFontsize, getOffset, Runtime } from '@tmagic/stage';
|
||||||
|
|
||||||
import ScrollViewer from '../../components/ScrollViewer.vue';
|
import ScrollViewer from '../../components/ScrollViewer.vue';
|
||||||
import { Layout, MenuButton, MenuComponent, Services, StageOptions, StageRect } from '../../type';
|
import { Layout, MenuButton, MenuComponent, Services, StageOptions } from '../../type';
|
||||||
import { useStage } from '../../utils/stage';
|
import { useStage } from '../../utils/stage';
|
||||||
|
|
||||||
import ViewerMenu from './ViewerMenu.vue';
|
import ViewerMenu from './ViewerMenu.vue';
|
||||||
@ -53,13 +53,14 @@ const stageWrap = ref<InstanceType<typeof ScrollViewer>>();
|
|||||||
const stageContainer = ref<HTMLDivElement>();
|
const stageContainer = ref<HTMLDivElement>();
|
||||||
const menu = ref<InstanceType<typeof ViewerMenu>>();
|
const menu = ref<InstanceType<typeof ViewerMenu>>();
|
||||||
|
|
||||||
const isMultiSelect = computed(() => services?.editorService.get('nodes')?.length > 1);
|
const nodes = computed(() => services?.editorService.get('nodes') || []);
|
||||||
const stageRect = computed(() => services?.uiService.get<StageRect>('stageRect'));
|
const isMultiSelect = computed(() => nodes.value.length > 1);
|
||||||
const stageContainerRect = computed(() => services?.uiService.get<StageRect>('stageContainerRect'));
|
const stageRect = computed(() => services?.uiService.get('stageRect'));
|
||||||
const root = computed(() => services?.editorService.get<MApp>('root'));
|
const stageContainerRect = computed(() => services?.uiService.get('stageContainerRect'));
|
||||||
const page = computed(() => services?.editorService.get<MPage>('page'));
|
const root = computed(() => services?.editorService.get('root'));
|
||||||
const zoom = computed(() => services?.uiService.get<number>('zoom') || 1);
|
const page = computed(() => services?.editorService.get('page'));
|
||||||
const node = computed(() => services?.editorService.get<MNode>('node'));
|
const zoom = computed(() => services?.uiService.get('zoom') || 1);
|
||||||
|
const node = computed(() => services?.editorService.get('node'));
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
if (stage || !page.value) return;
|
if (stage || !page.value) return;
|
||||||
@ -142,7 +143,7 @@ const dropHandler = async (e: DragEvent) => {
|
|||||||
const doc = stage?.renderer.contentWindow?.document;
|
const doc = stage?.renderer.contentWindow?.document;
|
||||||
const parentEl: HTMLElement | null | undefined = doc?.querySelector(`.${stageOptions?.containerHighlightClassName}`);
|
const parentEl: HTMLElement | null | undefined = doc?.querySelector(`.${stageOptions?.containerHighlightClassName}`);
|
||||||
|
|
||||||
let parent: MContainer | undefined = page.value;
|
let parent: MContainer | undefined | null = page.value;
|
||||||
if (parentEl) {
|
if (parentEl) {
|
||||||
parent = services?.editorService.getNodeById(parentEl.id, false) as MContainer;
|
parent = services?.editorService.getNodeById(parentEl.id, false) as MContainer;
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,7 @@
|
|||||||
import { computed, inject, markRaw, ref, watch } from 'vue';
|
import { computed, inject, markRaw, ref, watch } from 'vue';
|
||||||
import { Bottom, CopyDocument, Delete, DocumentCopy, Top } from '@element-plus/icons-vue';
|
import { Bottom, CopyDocument, Delete, DocumentCopy, Top } from '@element-plus/icons-vue';
|
||||||
|
|
||||||
import { MNode, NodeType } from '@tmagic/schema';
|
import { NodeType } from '@tmagic/schema';
|
||||||
import StageCore from '@tmagic/stage';
|
|
||||||
import { isPage } from '@tmagic/utils';
|
import { isPage } from '@tmagic/utils';
|
||||||
|
|
||||||
import ContentMenu from '../../components/ContentMenu.vue';
|
import ContentMenu from '../../components/ContentMenu.vue';
|
||||||
@ -26,10 +25,10 @@ const menu = ref<InstanceType<typeof ContentMenu>>();
|
|||||||
const canPaste = ref(false);
|
const canPaste = ref(false);
|
||||||
const canCenter = ref(false);
|
const canCenter = ref(false);
|
||||||
|
|
||||||
const node = computed(() => editorService?.get<MNode>('node'));
|
const node = computed(() => editorService?.get('node'));
|
||||||
const nodes = computed(() => editorService?.get<MNode[]>('nodes'));
|
const nodes = computed(() => editorService?.get('nodes'));
|
||||||
const parent = computed(() => editorService?.get('parent'));
|
const parent = computed(() => editorService?.get('parent'));
|
||||||
const stage = computed(() => editorService?.get<StageCore>('stage'));
|
const stage = computed(() => editorService?.get('stage'));
|
||||||
|
|
||||||
const menuData = computed<(MenuButton | MenuComponent)[]>(() => [
|
const menuData = computed<(MenuButton | MenuComponent)[]>(() => [
|
||||||
{
|
{
|
||||||
@ -129,7 +128,7 @@ const menuData = computed<(MenuButton | MenuComponent)[]>(() => [
|
|||||||
type: 'button',
|
type: 'button',
|
||||||
text: '清空参考线',
|
text: '清空参考线',
|
||||||
handler: () => {
|
handler: () => {
|
||||||
editorService?.get<StageCore>('stage').clearGuides();
|
editorService?.get('stage')?.clearGuides();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
...props.stageContentMenu,
|
...props.stageContentMenu,
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
import { computed, inject, onMounted, onUnmounted, ref } from 'vue';
|
import { computed, inject, onMounted, onUnmounted, ref } from 'vue';
|
||||||
import KeyController from 'keycon';
|
import KeyController from 'keycon';
|
||||||
|
|
||||||
import type { MNode, MPage } from '@tmagic/schema';
|
|
||||||
import { isPage } from '@tmagic/utils';
|
import { isPage } from '@tmagic/utils';
|
||||||
|
|
||||||
import type { MenuButton, MenuComponent, Services } from '../../type';
|
import type { MenuButton, MenuComponent, Services } from '../../type';
|
||||||
@ -34,8 +33,8 @@ defineProps<{
|
|||||||
|
|
||||||
const services = inject<Services>('services');
|
const services = inject<Services>('services');
|
||||||
const workspace = ref<HTMLDivElement>();
|
const workspace = ref<HTMLDivElement>();
|
||||||
const nodes = computed(() => services?.editorService.get<MNode[]>('nodes'));
|
const nodes = computed(() => services?.editorService.get('nodes'));
|
||||||
const page = computed(() => services?.editorService.get<MPage>('page'));
|
const page = computed(() => services?.editorService.get('page'));
|
||||||
|
|
||||||
const mouseenterHandler = () => {
|
const mouseenterHandler = () => {
|
||||||
workspace.value?.focus();
|
workspace.value?.focus();
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
import { reactive } from 'vue';
|
import { reactive } from 'vue';
|
||||||
import { cloneDeep, forIn, isEmpty, keys, omit, pick } from 'lodash-es';
|
import { cloneDeep, forIn, isEmpty, keys, omit, pick } from 'lodash-es';
|
||||||
|
|
||||||
import { CodeBlockContent, CodeBlockDSL, HookType, Id, MApp, MNode } from '@tmagic/schema';
|
import { CodeBlockContent, CodeBlockDSL, HookType, Id, MNode } from '@tmagic/schema';
|
||||||
|
|
||||||
import editorService from '../services/editor';
|
import editorService from '../services/editor';
|
||||||
import type { CodeRelation, CodeState, HookData } from '../type';
|
import type { CodeRelation, CodeState, HookData } from '../type';
|
||||||
@ -253,7 +253,7 @@ class CodeBlock extends BaseService {
|
|||||||
* @returns {CodeRelation | null}
|
* @returns {CodeRelation | null}
|
||||||
*/
|
*/
|
||||||
public refreshCombineInfo(): CodeRelation | null {
|
public refreshCombineInfo(): CodeRelation | null {
|
||||||
const root = editorService.get<MApp | null>('root');
|
const root = editorService.get('root');
|
||||||
if (!root) return null;
|
if (!root) return null;
|
||||||
const relations = {};
|
const relations = {};
|
||||||
this.recurseMNode(root, relations);
|
this.recurseMNode(root, relations);
|
||||||
|
@ -27,7 +27,7 @@ import { getNodePath, isNumber, isPage, isPop } from '@tmagic/utils';
|
|||||||
import codeBlockService from '../services/codeBlock';
|
import codeBlockService from '../services/codeBlock';
|
||||||
import historyService from '../services/history';
|
import historyService from '../services/history';
|
||||||
import storageService, { Protocol } from '../services/storage';
|
import storageService, { Protocol } from '../services/storage';
|
||||||
import type { AddMNode, EditorNodeInfo, PastePosition, StepValue, StoreState } from '../type';
|
import type { AddMNode, EditorNodeInfo, PastePosition, StepValue, StoreState, StoreStateKey } from '../type';
|
||||||
import { LayerOffset, Layout } from '../type';
|
import { LayerOffset, Layout } from '../type';
|
||||||
import {
|
import {
|
||||||
change2Fixed,
|
change2Fixed,
|
||||||
@ -94,15 +94,26 @@ class Editor extends BaseService {
|
|||||||
* @param name 'root' | 'page' | 'parent' | 'node' | 'highlightNode' | 'nodes' | 'stage' | 'modifiedNodeIds' | 'pageLength'
|
* @param name 'root' | 'page' | 'parent' | 'node' | 'highlightNode' | 'nodes' | 'stage' | 'modifiedNodeIds' | 'pageLength'
|
||||||
* @param value MNode
|
* @param value MNode
|
||||||
*/
|
*/
|
||||||
public set<T = MNode>(name: keyof StoreState, value: T) {
|
public set<K extends StoreStateKey, T extends StoreState[K]>(name: K, value: T) {
|
||||||
const preValue = this.state[name];
|
const preValue = this.state[name];
|
||||||
this.state[name] = value as any;
|
this.state[name] = value;
|
||||||
|
|
||||||
// set nodes时将node设置为nodes第一个元素
|
// set nodes时将node设置为nodes第一个元素
|
||||||
if (name === 'nodes') {
|
if (name === 'nodes' && Array.isArray(value)) {
|
||||||
this.set('node', (value as unknown as MNode[])[0]);
|
this.set('node', value[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name === 'root') {
|
if (name === 'root') {
|
||||||
this.state.pageLength = (value as unknown as MApp)?.items?.length || 0;
|
if (Array.isArray(value)) {
|
||||||
|
throw new Error('root 不能为数组');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isObject(value) && !(value instanceof StageCore) && !(value instanceof Map)) {
|
||||||
|
this.state.pageLength = value.items.length;
|
||||||
|
} else {
|
||||||
|
this.state.pageLength = 0;
|
||||||
|
}
|
||||||
|
|
||||||
this.emit('root-change', value, preValue);
|
this.emit('root-change', value, preValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -112,8 +123,8 @@ class Editor extends BaseService {
|
|||||||
* @param name 'root' | 'page' | 'parent' | 'node' | 'highlightNode' | 'nodes' | 'stage' | 'modifiedNodeIds' | 'pageLength'
|
* @param name 'root' | 'page' | 'parent' | 'node' | 'highlightNode' | 'nodes' | 'stage' | 'modifiedNodeIds' | 'pageLength'
|
||||||
* @returns MNode
|
* @returns MNode
|
||||||
*/
|
*/
|
||||||
public get<T = MNode>(name: keyof StoreState): T {
|
public get<K extends StoreStateKey>(name: K): StoreState[K] {
|
||||||
return (this.state as any)[name];
|
return this.state[name];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -123,22 +134,29 @@ class Editor extends BaseService {
|
|||||||
* @returns {EditorNodeInfo}
|
* @returns {EditorNodeInfo}
|
||||||
*/
|
*/
|
||||||
public getNodeInfo(id: Id, raw = true): EditorNodeInfo {
|
public getNodeInfo(id: Id, raw = true): EditorNodeInfo {
|
||||||
let root = this.get<MApp | null>('root');
|
let root = this.get('root');
|
||||||
if (raw) {
|
if (raw) {
|
||||||
root = toRaw(root);
|
root = toRaw(root);
|
||||||
}
|
}
|
||||||
if (!root) return {};
|
|
||||||
|
const info: EditorNodeInfo = {
|
||||||
|
node: null,
|
||||||
|
parent: null,
|
||||||
|
page: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!root) return info;
|
||||||
|
|
||||||
if (id === root.id) {
|
if (id === root.id) {
|
||||||
return { node: root };
|
info.node = root;
|
||||||
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
const path = getNodePath(id, root.items);
|
const path = getNodePath(id, root.items);
|
||||||
|
|
||||||
if (!path.length) return {};
|
if (!path.length) return info;
|
||||||
|
|
||||||
path.unshift(root);
|
path.unshift(root);
|
||||||
const info: EditorNodeInfo = {};
|
|
||||||
|
|
||||||
info.node = path[path.length - 1] as MComponent;
|
info.node = path[path.length - 1] as MComponent;
|
||||||
info.parent = path[path.length - 2] as MContainer;
|
info.parent = path[path.length - 2] as MContainer;
|
||||||
@ -159,7 +177,7 @@ class Editor extends BaseService {
|
|||||||
* @param {boolean} raw 是否使用toRaw
|
* @param {boolean} raw 是否使用toRaw
|
||||||
* @returns 组件节点配置
|
* @returns 组件节点配置
|
||||||
*/
|
*/
|
||||||
public getNodeById(id: Id, raw = true): MNode | undefined {
|
public getNodeById(id: Id, raw = true): MNode | null {
|
||||||
const { node } = this.getNodeInfo(id, raw);
|
const { node } = this.getNodeInfo(id, raw);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
@ -170,8 +188,7 @@ class Editor extends BaseService {
|
|||||||
* @param {boolean} raw 是否使用toRaw
|
* @param {boolean} raw 是否使用toRaw
|
||||||
* @returns 指点组件的父节点配置
|
* @returns 指点组件的父节点配置
|
||||||
*/
|
*/
|
||||||
public getParentById(id: Id, raw = true): MContainer | undefined {
|
public getParentById(id: Id, raw = true): MContainer | null {
|
||||||
if (!this.get<MApp | null>('root')) return;
|
|
||||||
const { parent } = this.getNodeInfo(id, raw);
|
const { parent } = this.getNodeInfo(id, raw);
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
@ -201,9 +218,9 @@ class Editor extends BaseService {
|
|||||||
*/
|
*/
|
||||||
public async select(config: MNode | Id): Promise<MNode> | never {
|
public async select(config: MNode | Id): Promise<MNode> | never {
|
||||||
const { node, page, parent } = this.selectedConfigExceptionHandler(config);
|
const { node, page, parent } = this.selectedConfigExceptionHandler(config);
|
||||||
this.set('nodes', [node]);
|
this.set('nodes', node ? [node] : []);
|
||||||
this.set('page', page || null);
|
this.set('page', page);
|
||||||
this.set('parent', parent || null);
|
this.set('parent', parent);
|
||||||
|
|
||||||
if (page) {
|
if (page) {
|
||||||
historyService.changePage(toRaw(page));
|
historyService.changePage(toRaw(page));
|
||||||
@ -212,7 +229,7 @@ class Editor extends BaseService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (node?.id) {
|
if (node?.id) {
|
||||||
this.get<StageCore>('stage')
|
this.get('stage')
|
||||||
?.renderer.runtime?.getApp?.()
|
?.renderer.runtime?.getApp?.()
|
||||||
?.emit(
|
?.emit(
|
||||||
'editor:select',
|
'editor:select',
|
||||||
@ -221,7 +238,7 @@ class Editor extends BaseService {
|
|||||||
page,
|
page,
|
||||||
parent,
|
parent,
|
||||||
},
|
},
|
||||||
getNodePath(node.id, this.get<MApp>('root').items),
|
getNodePath(node.id, this.get('root')?.items),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,7 +247,7 @@ class Editor extends BaseService {
|
|||||||
return node!;
|
return node!;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async selectNextNode(): Promise<MNode> | never {
|
public async selectNextNode(): Promise<MNode | null> | never {
|
||||||
const node = toRaw(this.get('node'));
|
const node = toRaw(this.get('node'));
|
||||||
|
|
||||||
if (!node || isPage(node) || node.type === NodeType.ROOT) return node;
|
if (!node || isPage(node) || node.type === NodeType.ROOT) return node;
|
||||||
@ -244,21 +261,24 @@ class Editor extends BaseService {
|
|||||||
const nextNode = parent.items[index + 1] || parent.items[0];
|
const nextNode = parent.items[index + 1] || parent.items[0];
|
||||||
|
|
||||||
await this.select(nextNode);
|
await this.select(nextNode);
|
||||||
this.get<StageCore>('stage')?.select(nextNode.id);
|
this.get('stage')?.select(nextNode.id);
|
||||||
|
|
||||||
return nextNode;
|
return nextNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async selectNextPage(): Promise<MNode> | never {
|
public async selectNextPage(): Promise<MNode> | never {
|
||||||
const root = toRaw(this.get<MApp>('root'));
|
const root = toRaw(this.get('root'));
|
||||||
const page = toRaw(this.get('page'));
|
const page = toRaw(this.get('page'));
|
||||||
|
|
||||||
|
if (!page) throw new Error('page不能为空');
|
||||||
|
if (!root) throw new Error('root不能为空');
|
||||||
|
|
||||||
const index = getNodeIndex(page, root);
|
const index = getNodeIndex(page, root);
|
||||||
|
|
||||||
const nextPage = root.items[index + 1] || root.items[0];
|
const nextPage = root.items[index + 1] || root.items[0];
|
||||||
|
|
||||||
await this.select(nextPage);
|
await this.select(nextPage);
|
||||||
this.get<StageCore>('stage')?.select(nextPage.id);
|
this.get('stage')?.select(nextPage.id);
|
||||||
|
|
||||||
return nextPage;
|
return nextPage;
|
||||||
}
|
}
|
||||||
@ -292,20 +312,25 @@ class Editor extends BaseService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async doAdd(node: MNode, parent: MContainer): Promise<MNode> {
|
public async doAdd(node: MNode, parent: MContainer): Promise<MNode> {
|
||||||
const root = this.get<MApp>('root');
|
const root = this.get('root');
|
||||||
const curNode = this.get<MNode>('node');
|
|
||||||
const stage = this.get<StageCore | null>('stage');
|
|
||||||
|
|
||||||
if ((parent?.type === NodeType.ROOT || curNode.type === NodeType.ROOT) && node.type !== NodeType.PAGE) {
|
if (!root) throw new Error('root为空');
|
||||||
|
|
||||||
|
const curNode = this.get('node');
|
||||||
|
const stage = this.get('stage');
|
||||||
|
|
||||||
|
if (!curNode) throw new Error('当前选中节点为空');
|
||||||
|
|
||||||
|
if ((parent.type === NodeType.ROOT || curNode?.type === NodeType.ROOT) && node.type !== NodeType.PAGE) {
|
||||||
throw new Error('app下不能添加组件');
|
throw new Error('app下不能添加组件');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parent.id !== curNode.id && node.type !== NodeType.PAGE) {
|
if (parent.id !== curNode.id && node.type !== NodeType.PAGE) {
|
||||||
const index = parent.items.indexOf(curNode);
|
const index = parent.items.indexOf(curNode);
|
||||||
parent?.items?.splice(index + 1, 0, node);
|
parent.items?.splice(index + 1, 0, node);
|
||||||
} else {
|
} else {
|
||||||
// 新增节点添加到配置中
|
// 新增节点添加到配置中
|
||||||
parent?.items?.push(node);
|
parent.items?.push(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
const layout = await this.getLayout(toRaw(parent), node as MNode);
|
const layout = await this.getLayout(toRaw(parent), node as MNode);
|
||||||
@ -337,7 +362,7 @@ class Editor extends BaseService {
|
|||||||
* @returns 添加后的节点
|
* @returns 添加后的节点
|
||||||
*/
|
*/
|
||||||
public async add(addNode: AddMNode | MNode[], parent?: MContainer | null): Promise<MNode | MNode[]> {
|
public async add(addNode: AddMNode | MNode[], parent?: MContainer | null): Promise<MNode | MNode[]> {
|
||||||
const stage = this.get<StageCore | null>('stage');
|
const stage = this.get('stage');
|
||||||
|
|
||||||
// 新增多个组件只存在于粘贴多个组件,粘贴的是一个完整的config,所以不再需要getPropsValue
|
// 新增多个组件只存在于粘贴多个组件,粘贴的是一个完整的config,所以不再需要getPropsValue
|
||||||
const addNodes = [];
|
const addNodes = [];
|
||||||
@ -353,8 +378,9 @@ class Editor extends BaseService {
|
|||||||
|
|
||||||
const newNodes = await Promise.all(
|
const newNodes = await Promise.all(
|
||||||
addNodes.map((node) => {
|
addNodes.map((node) => {
|
||||||
if (isPage(node)) {
|
const root = this.get('root');
|
||||||
return this.doAdd(node, this.get('root'));
|
if (isPage(node) && root) {
|
||||||
|
return this.doAdd(node, root);
|
||||||
}
|
}
|
||||||
const parentNode = parent && typeof parent !== 'function' ? parent : getAddParent(node);
|
const parentNode = parent && typeof parent !== 'function' ? parent : getAddParent(node);
|
||||||
if (!parentNode) throw new Error('未找到父元素');
|
if (!parentNode) throw new Error('未找到父元素');
|
||||||
@ -388,9 +414,8 @@ class Editor extends BaseService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async doRemove(node: MNode): Promise<void> {
|
public async doRemove(node: MNode): Promise<void> {
|
||||||
const root = this.get<MApp | null>('root');
|
const root = this.get('root');
|
||||||
|
if (!root) throw new Error('root不能为空');
|
||||||
if (!root) throw new Error('没有root');
|
|
||||||
|
|
||||||
const { parent, node: curNode } = this.getNodeInfo(node.id);
|
const { parent, node: curNode } = this.getNodeInfo(node.id);
|
||||||
|
|
||||||
@ -401,7 +426,7 @@ class Editor extends BaseService {
|
|||||||
if (typeof index !== 'number' || index === -1) throw new Error('找不要删除的节点');
|
if (typeof index !== 'number' || index === -1) throw new Error('找不要删除的节点');
|
||||||
|
|
||||||
parent.items?.splice(index, 1);
|
parent.items?.splice(index, 1);
|
||||||
const stage = this.get<StageCore | null>('stage');
|
const stage = this.get('stage');
|
||||||
stage?.remove({ id: node.id, parentId: parent.id, root: cloneDeep(root) });
|
stage?.remove({ id: node.id, parentId: parent.id, root: cloneDeep(root) });
|
||||||
|
|
||||||
if (node.type === NodeType.PAGE) {
|
if (node.type === NodeType.PAGE) {
|
||||||
@ -450,6 +475,9 @@ class Editor extends BaseService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async doUpdate(config: MNode) {
|
public async doUpdate(config: MNode) {
|
||||||
|
const root = this.get('root');
|
||||||
|
if (!root) throw new Error('root为空');
|
||||||
|
|
||||||
if (!config?.id) throw new Error('没有配置或者配置缺少id值');
|
if (!config?.id) throw new Error('没有配置或者配置缺少id值');
|
||||||
|
|
||||||
const info = this.getNodeInfo(config.id, false);
|
const info = this.getNodeInfo(config.id, false);
|
||||||
@ -458,7 +486,7 @@ class Editor extends BaseService {
|
|||||||
|
|
||||||
const node = cloneDeep(toRaw(info.node));
|
const node = cloneDeep(toRaw(info.node));
|
||||||
|
|
||||||
let newConfig = await this.toggleFixedPosition(toRaw(config), node, this.get<MApp>('root'));
|
let newConfig = await this.toggleFixedPosition(toRaw(config), node, root);
|
||||||
|
|
||||||
newConfig = mergeWith(cloneDeep(node), newConfig, (objValue, srcValue) => {
|
newConfig = mergeWith(cloneDeep(node), newConfig, (objValue, srcValue) => {
|
||||||
if (isObject(srcValue) && Array.isArray(objValue)) {
|
if (isObject(srcValue) && Array.isArray(objValue)) {
|
||||||
@ -473,7 +501,7 @@ class Editor extends BaseService {
|
|||||||
if (!newConfig.type) throw new Error('配置缺少type值');
|
if (!newConfig.type) throw new Error('配置缺少type值');
|
||||||
|
|
||||||
if (newConfig.type === NodeType.ROOT) {
|
if (newConfig.type === NodeType.ROOT) {
|
||||||
this.set('root', newConfig);
|
this.set('root', newConfig as MApp);
|
||||||
return newConfig;
|
return newConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -494,19 +522,19 @@ class Editor extends BaseService {
|
|||||||
parentNodeItems[index] = newConfig;
|
parentNodeItems[index] = newConfig;
|
||||||
|
|
||||||
// 将update后的配置更新到nodes中
|
// 将update后的配置更新到nodes中
|
||||||
const nodes = this.get<MNode[]>('nodes') || [];
|
const nodes = this.get('nodes');
|
||||||
const targetIndex = nodes.findIndex((nodeItem: MNode) => `${nodeItem.id}` === `${newConfig.id}`);
|
const targetIndex = nodes.findIndex((nodeItem: MNode) => `${nodeItem.id}` === `${newConfig.id}`);
|
||||||
nodes.splice(targetIndex, 1, newConfig);
|
nodes.splice(targetIndex, 1, newConfig);
|
||||||
this.set('nodes', [...nodes]);
|
this.set('nodes', [...nodes]);
|
||||||
|
|
||||||
this.get<StageCore | null>('stage')?.update({
|
this.get('stage')?.update({
|
||||||
config: cloneDeep(newConfig),
|
config: cloneDeep(newConfig),
|
||||||
parentId: parent.id,
|
parentId: parent.id,
|
||||||
root: cloneDeep(this.get('root')),
|
root: cloneDeep(root),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (newConfig.type === NodeType.PAGE) {
|
if (newConfig.type === NodeType.PAGE) {
|
||||||
this.set('page', newConfig);
|
this.set('page', newConfig as MPage);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.addModifiedNodeId(newConfig.id);
|
this.addModifiedNodeId(newConfig.id);
|
||||||
@ -538,8 +566,15 @@ class Editor extends BaseService {
|
|||||||
* @returns void
|
* @returns void
|
||||||
*/
|
*/
|
||||||
public async sort(id1: Id, id2: Id): Promise<void> {
|
public async sort(id1: Id, id2: Id): Promise<void> {
|
||||||
const node = this.get<MNode>('node');
|
const root = this.get('root');
|
||||||
const parent = cloneDeep(toRaw(this.get<MContainer>('parent')));
|
if (!root) throw new Error('root为空');
|
||||||
|
|
||||||
|
const node = this.get('node');
|
||||||
|
if (!node) throw new Error('当前节点为空');
|
||||||
|
|
||||||
|
const parent = cloneDeep(toRaw(this.get('parent')));
|
||||||
|
if (!parent) throw new Error('父节点为空');
|
||||||
|
|
||||||
const index2 = parent.items.findIndex((node: MNode) => `${node.id}` === `${id2}`);
|
const index2 = parent.items.findIndex((node: MNode) => `${node.id}` === `${id2}`);
|
||||||
// 在 id1 的兄弟组件中若无 id2 则直接 return
|
// 在 id1 的兄弟组件中若无 id2 则直接 return
|
||||||
if (index2 < 0) return;
|
if (index2 < 0) return;
|
||||||
@ -550,10 +585,10 @@ class Editor extends BaseService {
|
|||||||
await this.update(parent);
|
await this.update(parent);
|
||||||
await this.select(node);
|
await this.select(node);
|
||||||
|
|
||||||
this.get<StageCore | null>('stage')?.update({
|
this.get('stage')?.update({
|
||||||
config: cloneDeep(node),
|
config: cloneDeep(node),
|
||||||
parentId: parent.id,
|
parentId: parent.id,
|
||||||
root: cloneDeep(this.get('root')),
|
root: cloneDeep(root),
|
||||||
});
|
});
|
||||||
|
|
||||||
this.addModifiedNodeId(parent.id);
|
this.addModifiedNodeId(parent.id);
|
||||||
@ -581,14 +616,14 @@ class Editor extends BaseService {
|
|||||||
|
|
||||||
if (!Array.isArray(config)) return;
|
if (!Array.isArray(config)) return;
|
||||||
|
|
||||||
const node = this.get<MNode>('node');
|
const node = this.get('node');
|
||||||
|
|
||||||
let parent: MContainer | undefined = undefined;
|
let parent: MContainer | null = null;
|
||||||
// 粘贴的组件为当前选中组件的副本时,则添加到当前选中组件的父组件中
|
// 粘贴的组件为当前选中组件的副本时,则添加到当前选中组件的父组件中
|
||||||
if (config.length === 1 && config[0].id === node.id) {
|
if (config.length === 1 && config[0].id === node?.id) {
|
||||||
parent = this.get<MContainer>('parent');
|
parent = this.get('parent');
|
||||||
if (parent.type === NodeType.ROOT) {
|
if (parent?.type === NodeType.ROOT) {
|
||||||
parent = this.get<MPage>('page');
|
parent = this.get('page');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -615,7 +650,7 @@ class Editor extends BaseService {
|
|||||||
|
|
||||||
if (!node.style) return config;
|
if (!node.style) return config;
|
||||||
|
|
||||||
const stage = this.get<StageCore>('stage');
|
const stage = this.get('stage');
|
||||||
const doc = stage?.renderer.contentWindow?.document;
|
const doc = stage?.renderer.contentWindow?.document;
|
||||||
|
|
||||||
if (doc) {
|
if (doc) {
|
||||||
@ -638,7 +673,7 @@ class Editor extends BaseService {
|
|||||||
*/
|
*/
|
||||||
public async alignCenter(config: MNode | MNode[]): Promise<MNode | MNode[]> {
|
public async alignCenter(config: MNode | MNode[]): Promise<MNode | MNode[]> {
|
||||||
const nodes = Array.isArray(config) ? config : [config];
|
const nodes = Array.isArray(config) ? config : [config];
|
||||||
const stage = this.get<StageCore | null>('stage');
|
const stage = this.get('stage');
|
||||||
|
|
||||||
const newNodes = await Promise.all(nodes.map((node) => this.doAlignCenter(node)));
|
const newNodes = await Promise.all(nodes.map((node) => this.doAlignCenter(node)));
|
||||||
|
|
||||||
@ -658,9 +693,16 @@ class Editor extends BaseService {
|
|||||||
* @param offset 偏移量
|
* @param offset 偏移量
|
||||||
*/
|
*/
|
||||||
public async moveLayer(offset: number | LayerOffset): Promise<void> {
|
public async moveLayer(offset: number | LayerOffset): Promise<void> {
|
||||||
const parent = this.get<MContainer>('parent');
|
const root = this.get('root');
|
||||||
const node = this.get<MNode>('node');
|
if (!root) throw new Error('root为空');
|
||||||
const brothers: MNode[] = parent?.items || [];
|
|
||||||
|
const parent = this.get('parent');
|
||||||
|
if (!parent) throw new Error('父节点为空');
|
||||||
|
|
||||||
|
const node = this.get('node');
|
||||||
|
if (!node) throw new Error('当前节点为空');
|
||||||
|
|
||||||
|
const brothers: MNode[] = parent.items || [];
|
||||||
const index = brothers.findIndex((item) => `${item.id}` === `${node?.id}`);
|
const index = brothers.findIndex((item) => `${item.id}` === `${node?.id}`);
|
||||||
|
|
||||||
// 流式布局与绝对定位布局操作的相反的
|
// 流式布局与绝对定位布局操作的相反的
|
||||||
@ -678,10 +720,10 @@ class Editor extends BaseService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const grandparent = this.getParentById(parent.id);
|
const grandparent = this.getParentById(parent.id);
|
||||||
this.get<StageCore | null>('stage')?.update({
|
this.get('stage')?.update({
|
||||||
config: cloneDeep(toRaw(parent)),
|
config: cloneDeep(toRaw(parent)),
|
||||||
parentId: grandparent?.id,
|
parentId: grandparent?.id,
|
||||||
root: cloneDeep(this.get<MApp>('root')),
|
root: cloneDeep(root),
|
||||||
});
|
});
|
||||||
|
|
||||||
this.addModifiedNodeId(parent.id);
|
this.addModifiedNodeId(parent.id);
|
||||||
@ -694,13 +736,12 @@ class Editor extends BaseService {
|
|||||||
* @param targetId 容器ID
|
* @param targetId 容器ID
|
||||||
*/
|
*/
|
||||||
public async moveToContainer(config: MNode, targetId: Id): Promise<MNode | undefined> {
|
public async moveToContainer(config: MNode, targetId: Id): Promise<MNode | undefined> {
|
||||||
|
const root = cloneDeep(this.get('root'));
|
||||||
const { node, parent } = this.getNodeInfo(config.id, false);
|
const { node, parent } = this.getNodeInfo(config.id, false);
|
||||||
const target = this.getNodeById(targetId, false) as MContainer;
|
const target = this.getNodeById(targetId, false) as MContainer;
|
||||||
|
|
||||||
const stage = this.get<StageCore | null>('stage');
|
const stage = this.get('stage');
|
||||||
|
if (root && node && parent && stage) {
|
||||||
if (node && parent && stage) {
|
|
||||||
const root = cloneDeep(this.get<MApp>('root'));
|
|
||||||
const index = getNodeIndex(node, parent);
|
const index = getNodeIndex(node, parent);
|
||||||
parent.items?.splice(index, 1);
|
parent.items?.splice(index, 1);
|
||||||
|
|
||||||
@ -783,7 +824,7 @@ class Editor extends BaseService {
|
|||||||
this.set('stage', null);
|
this.set('stage', null);
|
||||||
this.set('highlightNode', null);
|
this.set('highlightNode', null);
|
||||||
this.set('modifiedNodeIds', new Map());
|
this.set('modifiedNodeIds', new Map());
|
||||||
this.set('pageLength', new Map());
|
this.set('pageLength', 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public destroy() {
|
public destroy() {
|
||||||
@ -793,7 +834,7 @@ class Editor extends BaseService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public resetModifiedNodeId() {
|
public resetModifiedNodeId() {
|
||||||
this.get<Map<Id, Id>>('modifiedNodeIds').clear();
|
this.get('modifiedNodeIds').clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -801,15 +842,13 @@ class Editor extends BaseService {
|
|||||||
* @returns {CodeBlockDSL | null}
|
* @returns {CodeBlockDSL | null}
|
||||||
*/
|
*/
|
||||||
public async getCodeDsl(): Promise<CodeBlockDSL | null> {
|
public async getCodeDsl(): Promise<CodeBlockDSL | null> {
|
||||||
const root = this.get<MApp | null>('root');
|
const root = this.get('root');
|
||||||
if (!root) return null;
|
return root?.codeBlocks || null;
|
||||||
return root.codeBlocks || null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public getCodeDslSync(): CodeBlockDSL | null {
|
public getCodeDslSync(): CodeBlockDSL | null {
|
||||||
const root = this.get<MApp | null>('root');
|
const root = this.get('root');
|
||||||
if (!root) return null;
|
return root?.codeBlocks || null;
|
||||||
return root.codeBlocks || null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -824,16 +863,17 @@ class Editor extends BaseService {
|
|||||||
|
|
||||||
private addModifiedNodeId(id: Id) {
|
private addModifiedNodeId(id: Id) {
|
||||||
if (!this.isHistoryStateChange) {
|
if (!this.isHistoryStateChange) {
|
||||||
this.get<Map<Id, Id>>('modifiedNodeIds').set(id, id);
|
this.get('modifiedNodeIds').set(id, id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private pushHistoryState() {
|
private pushHistoryState() {
|
||||||
const curNode = cloneDeep(toRaw(this.get('node')));
|
const curNode = cloneDeep(toRaw(this.get('node')));
|
||||||
if (!this.isHistoryStateChange) {
|
const page = this.get('page');
|
||||||
|
if (!this.isHistoryStateChange && curNode && page) {
|
||||||
historyService.push({
|
historyService.push({
|
||||||
data: cloneDeep(toRaw(this.get('page'))),
|
data: cloneDeep(toRaw(page)),
|
||||||
modifiedNodeIds: this.get<Map<Id, Id>>('modifiedNodeIds'),
|
modifiedNodeIds: this.get('modifiedNodeIds'),
|
||||||
nodeId: curNode.id,
|
nodeId: curNode.id,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -849,7 +889,7 @@ class Editor extends BaseService {
|
|||||||
setTimeout(async () => {
|
setTimeout(async () => {
|
||||||
if (!value.nodeId) return;
|
if (!value.nodeId) return;
|
||||||
await this.select(value.nodeId);
|
await this.select(value.nodeId);
|
||||||
this.get<StageCore | null>('stage')?.select(value.nodeId);
|
this.get('stage')?.select(value.nodeId);
|
||||||
}, 0);
|
}, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,8 +18,6 @@
|
|||||||
|
|
||||||
import { reactive } from 'vue';
|
import { reactive } from 'vue';
|
||||||
|
|
||||||
import type StageCore from '@tmagic/stage';
|
|
||||||
|
|
||||||
import editorService from '../services/editor';
|
import editorService from '../services/editor';
|
||||||
import type { StageRect, UiState } from '../type';
|
import type { StageRect, UiState } from '../type';
|
||||||
|
|
||||||
@ -53,8 +51,8 @@ class Ui extends BaseService {
|
|||||||
super(['zoom', 'calcZoom']);
|
super(['zoom', 'calcZoom']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public set<T = any>(name: keyof UiState, value: T) {
|
public set<K extends keyof UiState, T extends UiState[K]>(name: K, value: T) {
|
||||||
const mask = editorService.get<StageCore>('stage')?.mask;
|
const mask = editorService.get('stage')?.mask;
|
||||||
|
|
||||||
if (name === 'stageRect') {
|
if (name === 'stageRect') {
|
||||||
this.setStageRect(value as unknown as StageRect);
|
this.setStageRect(value as unknown as StageRect);
|
||||||
@ -69,16 +67,16 @@ class Ui extends BaseService {
|
|||||||
mask?.showRule(value as unknown as boolean);
|
mask?.showRule(value as unknown as boolean);
|
||||||
}
|
}
|
||||||
|
|
||||||
(state as any)[name] = value;
|
state[name] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get<T>(name: keyof typeof state): T {
|
public get<K extends keyof UiState>(name: K) {
|
||||||
return (state as any)[name];
|
return state[name];
|
||||||
}
|
}
|
||||||
|
|
||||||
public async zoom(zoom: number) {
|
public async zoom(zoom: number) {
|
||||||
this.set('zoom', (this.get<number>('zoom') * 100 + zoom * 100) / 100);
|
this.set('zoom', (this.get('zoom') * 100 + zoom * 100) / 100);
|
||||||
if (this.get<number>('zoom') < 0.1) this.set('zoom', 0.1);
|
if (this.get('zoom') < 0.1) this.set('zoom', 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async calcZoom() {
|
public async calcZoom() {
|
||||||
|
@ -82,6 +82,8 @@ export interface StoreState {
|
|||||||
pageLength: number;
|
pageLength: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type StoreStateKey = keyof StoreState;
|
||||||
|
|
||||||
export interface PropsState {
|
export interface PropsState {
|
||||||
propsConfigMap: Record<string, FormConfig>;
|
propsConfigMap: Record<string, FormConfig>;
|
||||||
propsValueMap: Record<string, MNode>;
|
propsValueMap: Record<string, MNode>;
|
||||||
@ -138,9 +140,9 @@ export interface UiState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface EditorNodeInfo {
|
export interface EditorNodeInfo {
|
||||||
node?: MNode;
|
node: MNode | null;
|
||||||
parent?: MContainer;
|
parent: MContainer | null;
|
||||||
page?: MPage;
|
page: MPage | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AddMNode {
|
export interface AddMNode {
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import { toRaw } from 'vue';
|
import { toRaw } from 'vue';
|
||||||
import { isEmpty } from 'lodash-es';
|
import { isEmpty } from 'lodash-es';
|
||||||
|
|
||||||
import { Id, MApp, MContainer, MNode } from '@tmagic/schema';
|
import { Id, MContainer, MNode } from '@tmagic/schema';
|
||||||
import StageCore from '@tmagic/stage';
|
|
||||||
import { isPage } from '@tmagic/utils';
|
import { isPage } from '@tmagic/utils';
|
||||||
|
|
||||||
import editorService from '../services/editor';
|
import editorService from '../services/editor';
|
||||||
@ -18,7 +17,7 @@ import { generatePageNameByApp, getInitPositionStyle } from '../utils/editor';
|
|||||||
*/
|
*/
|
||||||
export const beforePaste = async (position: PastePosition, config: MNode[]): Promise<MNode[]> => {
|
export const beforePaste = async (position: PastePosition, config: MNode[]): Promise<MNode[]> => {
|
||||||
if (!config[0]?.style) return config;
|
if (!config[0]?.style) return config;
|
||||||
const curNode = editorService.get<MContainer>('node');
|
const curNode = editorService.get('node');
|
||||||
// 将数组中第一个元素的坐标作为参照点
|
// 将数组中第一个元素的坐标作为参照点
|
||||||
const { left: referenceLeft, top: referenceTop } = config[0].style;
|
const { left: referenceLeft, top: referenceTop } = config[0].style;
|
||||||
// 坐标校准后的粘贴数据
|
// 坐标校准后的粘贴数据
|
||||||
@ -28,7 +27,7 @@ export const beforePaste = async (position: PastePosition, config: MNode[]): Pro
|
|||||||
const { offsetX = 0, offsetY = 0, ...positionClone } = position;
|
const { offsetX = 0, offsetY = 0, ...positionClone } = position;
|
||||||
let pastePosition = positionClone;
|
let pastePosition = positionClone;
|
||||||
|
|
||||||
if (!isEmpty(pastePosition) && curNode.items) {
|
if (!isEmpty(pastePosition) && curNode?.items) {
|
||||||
// 如果没有传入粘贴坐标则可能为键盘操作,不再转换
|
// 如果没有传入粘贴坐标则可能为键盘操作,不再转换
|
||||||
// 如果粘贴时选中了容器,则将元素粘贴到容器内,坐标需要转换为相对于容器的坐标
|
// 如果粘贴时选中了容器,则将元素粘贴到容器内,坐标需要转换为相对于容器的坐标
|
||||||
pastePosition = getPositionInContainer(pastePosition, curNode.id);
|
pastePosition = getPositionInContainer(pastePosition, curNode.id);
|
||||||
@ -59,8 +58,9 @@ export const beforePaste = async (position: PastePosition, config: MNode[]): Pro
|
|||||||
...pastePosition,
|
...pastePosition,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (isPage(pasteConfig)) {
|
const root = editorService.get('root');
|
||||||
pasteConfig.name = generatePageNameByApp(editorService.get('root'));
|
if (isPage(pasteConfig) && root) {
|
||||||
|
pasteConfig.name = generatePageNameByApp(root);
|
||||||
}
|
}
|
||||||
return pasteConfig as MNode;
|
return pasteConfig as MNode;
|
||||||
}),
|
}),
|
||||||
@ -76,7 +76,7 @@ export const beforePaste = async (position: PastePosition, config: MNode[]): Pro
|
|||||||
*/
|
*/
|
||||||
export const getPositionInContainer = (position: PastePosition = {}, id: Id) => {
|
export const getPositionInContainer = (position: PastePosition = {}, id: Id) => {
|
||||||
let { left = 0, top = 0 } = position;
|
let { left = 0, top = 0 } = position;
|
||||||
const parentEl = editorService.get<StageCore>('stage')?.renderer?.contentWindow?.document.getElementById(`${id}`);
|
const parentEl = editorService.get('stage')?.renderer?.contentWindow?.document.getElementById(`${id}`);
|
||||||
const parentElRect = parentEl?.getBoundingClientRect();
|
const parentElRect = parentEl?.getBoundingClientRect();
|
||||||
left = left - (parentElRect?.left || 0);
|
left = left - (parentElRect?.left || 0);
|
||||||
top = top - (parentElRect?.top || 0);
|
top = top - (parentElRect?.top || 0);
|
||||||
@ -87,14 +87,14 @@ export const getPositionInContainer = (position: PastePosition = {}, id: Id) =>
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const getAddParent = (node: MNode) => {
|
export const getAddParent = (node: MNode) => {
|
||||||
const curNode = editorService.get<MContainer>('node');
|
const curNode = editorService.get('node');
|
||||||
|
|
||||||
let parentNode;
|
let parentNode;
|
||||||
if (isPage(node)) {
|
if (isPage(node)) {
|
||||||
parentNode = editorService.get<MApp>('root');
|
parentNode = editorService.get('root');
|
||||||
} else if (curNode.items) {
|
} else if (curNode?.items) {
|
||||||
parentNode = curNode;
|
parentNode = curNode as MContainer;
|
||||||
} else {
|
} else if (curNode?.id) {
|
||||||
parentNode = editorService.getParentById(curNode.id, false);
|
parentNode = editorService.getParentById(curNode.id, false);
|
||||||
}
|
}
|
||||||
return parentNode;
|
return parentNode;
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
|
|
||||||
import { MApp, MPage } from '@tmagic/schema';
|
|
||||||
import StageCore, { GuidesType, SortEventData, UpdateEventData } from '@tmagic/stage';
|
import StageCore, { GuidesType, SortEventData, UpdateEventData } from '@tmagic/stage';
|
||||||
|
|
||||||
import editorService from '../services/editor';
|
import editorService from '../services/editor';
|
||||||
@ -9,10 +8,10 @@ import { H_GUIDE_LINE_STORAGE_KEY, StageOptions, V_GUIDE_LINE_STORAGE_KEY } from
|
|||||||
|
|
||||||
import { getGuideLineFromCache } from './editor';
|
import { getGuideLineFromCache } from './editor';
|
||||||
|
|
||||||
const root = computed(() => editorService.get<MApp>('root'));
|
const root = computed(() => editorService.get('root'));
|
||||||
const page = computed(() => editorService.get<MPage>('page'));
|
const page = computed(() => editorService.get('page'));
|
||||||
const zoom = computed(() => uiService.get<number>('zoom') || 1);
|
const zoom = computed(() => uiService.get('zoom') || 1);
|
||||||
const uiSelectMode = computed(() => uiService.get<boolean>('uiSelectMode'));
|
const uiSelectMode = computed(() => uiService.get('uiSelectMode'));
|
||||||
|
|
||||||
const getGuideLineKey = (key: string) => `${key}_${root.value?.id}_${page.value?.id}`;
|
const getGuideLineKey = (key: string) => `${key}_${root.value?.id}_${page.value?.id}`;
|
||||||
|
|
||||||
@ -76,8 +75,9 @@ export const useStage = (stageOptions: StageOptions) => {
|
|||||||
|
|
||||||
stage.on('select-parent', () => {
|
stage.on('select-parent', () => {
|
||||||
const parent = editorService.get('parent');
|
const parent = editorService.get('parent');
|
||||||
|
if (!parent) throw new Error('父节点为空');
|
||||||
editorService.select(parent);
|
editorService.select(parent);
|
||||||
editorService.get<StageCore>('stage').select(parent.id);
|
editorService.get('stage')?.select(parent.id);
|
||||||
});
|
});
|
||||||
|
|
||||||
stage.on('change-guides', (e) => {
|
stage.on('change-guides', (e) => {
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
import { beforeAll, describe, expect, test } from 'vitest';
|
import { beforeAll, describe, expect, test } from 'vitest';
|
||||||
import { cloneDeep } from 'lodash-es';
|
import { cloneDeep } from 'lodash-es';
|
||||||
|
|
||||||
import type { MApp, MContainer, MNode } from '@tmagic/schema';
|
import type { MApp } from '@tmagic/schema';
|
||||||
import { NodeType } from '@tmagic/schema';
|
import { NodeType } from '@tmagic/schema';
|
||||||
|
|
||||||
import editorService from '@editor/services/editor';
|
import editorService from '@editor/services/editor';
|
||||||
@ -74,7 +74,7 @@ enum NodeId {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// mock 页面数据,包含一个页面,两个组件
|
// mock 页面数据,包含一个页面,两个组件
|
||||||
const root: MNode = {
|
const root: MApp = {
|
||||||
id: NodeId.ROOT_ID,
|
id: NodeId.ROOT_ID,
|
||||||
type: NodeType.ROOT,
|
type: NodeType.ROOT,
|
||||||
items: [
|
items: [
|
||||||
@ -109,7 +109,7 @@ describe('get', () => {
|
|||||||
|
|
||||||
test('get', () => {
|
test('get', () => {
|
||||||
const root = editorService.get('root');
|
const root = editorService.get('root');
|
||||||
expect(root.id).toBe(NodeId.ROOT_ID);
|
expect(root?.id).toBe(NodeId.ROOT_ID);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('get undefined', () => {
|
test('get undefined', () => {
|
||||||
@ -131,9 +131,9 @@ describe('getNodeInfo', () => {
|
|||||||
|
|
||||||
test('异常', () => {
|
test('异常', () => {
|
||||||
const info = editorService.getNodeInfo(NodeId.ERROR_NODE_ID);
|
const info = editorService.getNodeInfo(NodeId.ERROR_NODE_ID);
|
||||||
expect(info?.node).toBeUndefined();
|
expect(info?.node).toBeNull();
|
||||||
expect(info?.parent?.id).toBeUndefined();
|
expect(info?.parent?.id).toBeUndefined();
|
||||||
expect(info?.page).toBeUndefined();
|
expect(info?.page).toBeNull();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -147,7 +147,7 @@ describe('getNodeById', () => {
|
|||||||
|
|
||||||
test('异常', () => {
|
test('异常', () => {
|
||||||
const node = editorService.getNodeById(NodeId.ERROR_NODE_ID);
|
const node = editorService.getNodeById(NodeId.ERROR_NODE_ID);
|
||||||
expect(node).toBeUndefined();
|
expect(node).toBeNull();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -210,9 +210,9 @@ describe('add', () => {
|
|||||||
const node = editorService.get('node');
|
const node = editorService.get('node');
|
||||||
const parent = editorService.get('parent');
|
const parent = editorService.get('parent');
|
||||||
if (!Array.isArray(newNode)) {
|
if (!Array.isArray(newNode)) {
|
||||||
expect(node.id).toBe(newNode.id);
|
expect(node?.id).toBe(newNode.id);
|
||||||
}
|
}
|
||||||
expect(parent.items).toHaveLength(3);
|
expect(parent?.items).toHaveLength(3);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('正常, 当前不是容器', async () => {
|
test('正常, 当前不是容器', async () => {
|
||||||
@ -226,15 +226,15 @@ describe('add', () => {
|
|||||||
const node = editorService.get('node');
|
const node = editorService.get('node');
|
||||||
const parent = editorService.get('parent');
|
const parent = editorService.get('parent');
|
||||||
if (!Array.isArray(newNode)) {
|
if (!Array.isArray(newNode)) {
|
||||||
expect(node.id).toBe(newNode.id);
|
expect(node?.id).toBe(newNode.id);
|
||||||
}
|
}
|
||||||
expect(parent.items).toHaveLength(3);
|
expect(parent?.items).toHaveLength(3);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('往root下添加page', async () => {
|
test('往root下添加page', async () => {
|
||||||
editorService.set('root', cloneDeep(root));
|
editorService.set('root', cloneDeep(root));
|
||||||
await editorService.select(NodeId.PAGE_ID);
|
await editorService.select(NodeId.PAGE_ID);
|
||||||
const rootNode = editorService.get<MApp>('root');
|
const rootNode = editorService.get('root');
|
||||||
const newNode = await editorService.add(
|
const newNode = await editorService.add(
|
||||||
{
|
{
|
||||||
type: NodeType.PAGE,
|
type: NodeType.PAGE,
|
||||||
@ -243,15 +243,15 @@ describe('add', () => {
|
|||||||
);
|
);
|
||||||
const node = editorService.get('node');
|
const node = editorService.get('node');
|
||||||
if (!Array.isArray(newNode)) {
|
if (!Array.isArray(newNode)) {
|
||||||
expect(node.id).toBe(newNode.id);
|
expect(node?.id).toBe(newNode.id);
|
||||||
}
|
}
|
||||||
expect(rootNode.items.length).toBe(2);
|
expect(rootNode?.items.length).toBe(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
test.skip('往root下添加普通节点', () => {
|
test.skip('往root下添加普通节点', () => {
|
||||||
editorService.set('root', cloneDeep(root));
|
editorService.set('root', cloneDeep(root));
|
||||||
// 根节点下只能加页面
|
// 根节点下只能加页面
|
||||||
const rootNode = editorService.get<MApp>('root');
|
const rootNode = editorService.get('root');
|
||||||
expect(() =>
|
expect(() =>
|
||||||
editorService.add(
|
editorService.add(
|
||||||
{
|
{
|
||||||
@ -269,13 +269,13 @@ describe('remove', () => {
|
|||||||
test('正常', async () => {
|
test('正常', async () => {
|
||||||
editorService.remove({ id: NodeId.NODE_ID, type: 'text' });
|
editorService.remove({ id: NodeId.NODE_ID, type: 'text' });
|
||||||
const node = editorService.getNodeById(NodeId.NODE_ID);
|
const node = editorService.getNodeById(NodeId.NODE_ID);
|
||||||
expect(node).toBeUndefined();
|
expect(node).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('remove page', async () => {
|
test('remove page', async () => {
|
||||||
editorService.set('root', cloneDeep(root));
|
editorService.set('root', cloneDeep(root));
|
||||||
editorService.select(NodeId.PAGE_ID);
|
editorService.select(NodeId.PAGE_ID);
|
||||||
const rootNode = editorService.get<MApp>('root');
|
const rootNode = editorService.get('root');
|
||||||
// 先加一个页面
|
// 先加一个页面
|
||||||
const newPage = await editorService.add(
|
const newPage = await editorService.add(
|
||||||
{
|
{
|
||||||
@ -283,9 +283,9 @@ describe('remove', () => {
|
|||||||
},
|
},
|
||||||
rootNode,
|
rootNode,
|
||||||
);
|
);
|
||||||
expect(rootNode.items.length).toBe(2);
|
expect(rootNode?.items.length).toBe(2);
|
||||||
await editorService.remove(newPage);
|
await editorService.remove(newPage);
|
||||||
expect(rootNode.items.length).toBe(1);
|
expect(rootNode?.items.length).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test.skip('undefine', async () => {
|
test.skip('undefine', async () => {
|
||||||
@ -347,11 +347,11 @@ describe('sort', () => {
|
|||||||
|
|
||||||
test('正常', async () => {
|
test('正常', async () => {
|
||||||
await editorService.select(NodeId.NODE_ID2);
|
await editorService.select(NodeId.NODE_ID2);
|
||||||
let parent = editorService.get<MContainer>('parent');
|
let parent = editorService.get('parent');
|
||||||
expect(parent.items[0].id).toBe(NodeId.NODE_ID);
|
expect(parent?.items[0].id).toBe(NodeId.NODE_ID);
|
||||||
await editorService.sort(NodeId.NODE_ID2, NodeId.NODE_ID);
|
await editorService.sort(NodeId.NODE_ID2, NodeId.NODE_ID);
|
||||||
parent = editorService.get<MContainer>('parent');
|
parent = editorService.get('parent');
|
||||||
expect(parent.items[0].id).toBe(NodeId.NODE_ID2);
|
expect(parent?.items[0].id).toBe(NodeId.NODE_ID2);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -371,9 +371,9 @@ describe('moveLayer', () => {
|
|||||||
test('正常', async () => {
|
test('正常', async () => {
|
||||||
// 设置当前编辑的组件
|
// 设置当前编辑的组件
|
||||||
await editorService.select(NodeId.NODE_ID);
|
await editorService.select(NodeId.NODE_ID);
|
||||||
const parent = editorService.get<MContainer>('parent');
|
const parent = editorService.get('parent');
|
||||||
await editorService.moveLayer(1);
|
await editorService.moveLayer(1);
|
||||||
expect(parent.items[0].id).toBe(NodeId.NODE_ID2);
|
expect(parent?.items[0].id).toBe(NodeId.NODE_ID2);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -385,9 +385,10 @@ describe('undo redo', () => {
|
|||||||
// 设置当前编辑的组件
|
// 设置当前编辑的组件
|
||||||
await editorService.select(NodeId.NODE_ID);
|
await editorService.select(NodeId.NODE_ID);
|
||||||
const node = editorService.get('node');
|
const node = editorService.get('node');
|
||||||
|
if (!node) throw new Error('未选中节点');
|
||||||
await editorService.remove(node);
|
await editorService.remove(node);
|
||||||
const removedNode = editorService.getNodeById(NodeId.NODE_ID);
|
const removedNode = editorService.getNodeById(NodeId.NODE_ID);
|
||||||
expect(removedNode).toBeUndefined();
|
expect(removedNode).toBeNull();
|
||||||
await editorService.undo();
|
await editorService.undo();
|
||||||
const undoNode = editorService.getNodeById(NodeId.NODE_ID);
|
const undoNode = editorService.getNodeById(NodeId.NODE_ID);
|
||||||
expect(undoNode?.id).toBe(NodeId.NODE_ID);
|
expect(undoNode?.id).toBe(NodeId.NODE_ID);
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<router-view></router-view>
|
<router-view></router-view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script lang="ts">
|
||||||
export default {
|
export default {
|
||||||
name: 'App',
|
name: 'App',
|
||||||
};
|
};
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
import { defineComponent, ref } from 'vue';
|
import { defineComponent, ref } from 'vue';
|
||||||
|
|
||||||
import { editorService } from '@tmagic/editor';
|
import { editorService } from '@tmagic/editor';
|
||||||
import type StageCore from '@tmagic/stage';
|
|
||||||
|
|
||||||
enum DeviceType {
|
enum DeviceType {
|
||||||
Phone = 'phone',
|
Phone = 'phone',
|
||||||
@ -49,7 +48,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
const calcFontsize = (width: number) => {
|
const calcFontsize = (width: number) => {
|
||||||
const { iframe } = editorService.get<StageCore>('stage').renderer;
|
const iframe = editorService.get('stage')?.renderer.iframe;
|
||||||
if (!iframe?.contentWindow) return;
|
if (!iframe?.contentWindow) return;
|
||||||
iframe.contentWindow.appInstance.designWidth = width;
|
iframe.contentWindow.appInstance.designWidth = width;
|
||||||
};
|
};
|
||||||
|
@ -39,7 +39,7 @@ import { ElMessage, ElMessageBox } from 'element-plus';
|
|||||||
import serialize from 'serialize-javascript';
|
import serialize from 'serialize-javascript';
|
||||||
|
|
||||||
import { editorService, MenuBarData, MoveableOptions, TMagicEditor } from '@tmagic/editor';
|
import { editorService, MenuBarData, MoveableOptions, TMagicEditor } from '@tmagic/editor';
|
||||||
import type { Id, MContainer, MNode } from '@tmagic/schema';
|
import type { MContainer, MNode } from '@tmagic/schema';
|
||||||
import { NodeType } from '@tmagic/schema';
|
import { NodeType } from '@tmagic/schema';
|
||||||
import { CustomizeMoveableOptionsCallbackConfig } from '@tmagic/stage';
|
import { CustomizeMoveableOptionsCallbackConfig } from '@tmagic/stage';
|
||||||
import { asyncLoadJs } from '@tmagic/utils';
|
import { asyncLoadJs } from '@tmagic/utils';
|
||||||
@ -65,7 +65,7 @@ const stageRect = ref({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const previewUrl = computed(
|
const previewUrl = computed(
|
||||||
() => `${VITE_RUNTIME_PATH}/page/index.html?localPreview=1&page=${editor.value?.editorService.get('page').id}`,
|
() => `${VITE_RUNTIME_PATH}/page/index.html?localPreview=1&page=${editor.value?.editorService.get('page')?.id}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
const menu: MenuBarData = {
|
const menu: MenuBarData = {
|
||||||
@ -93,7 +93,7 @@ const menu: MenuBarData = {
|
|||||||
text: '预览',
|
text: '预览',
|
||||||
icon: Connection,
|
icon: Connection,
|
||||||
handler: async (services) => {
|
handler: async (services) => {
|
||||||
if (services?.editorService.get<Map<Id, Id>>('modifiedNodeIds').size > 0) {
|
if (services?.editorService.get('modifiedNodeIds').size > 0) {
|
||||||
try {
|
try {
|
||||||
await ElMessageBox.confirm('有修改未保存,是否先保存再预览', '提示', {
|
await ElMessageBox.confirm('有修改未保存,是否先保存再预览', '提示', {
|
||||||
confirmButtonText: '保存并预览',
|
confirmButtonText: '保存并预览',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user