|
|
@@ -22,6 +22,7 @@
|
|
|
<template v-else-if="item.type === 'scrollingText'">滚动文本</template>
|
|
|
<template v-else-if="item.type === 'mediaAsset'">媒资</template>
|
|
|
<template v-else-if="item.type === 'live'">直播</template>
|
|
|
+ <template v-else-if="item.type === 'webPage'">网页</template>
|
|
|
<!-- 未来可扩展图片等类型 -->
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -35,6 +36,7 @@
|
|
|
<div class="toolbar-item" draggable="true" @dragstart="onToolbarDragStart('scrollingText')">滚动文本</div>
|
|
|
<div class="toolbar-item" draggable="true" @dragstart="onToolbarDragStart('mediaAsset')">媒资</div>
|
|
|
<div class="toolbar-item" draggable="true" @dragstart="onToolbarDragStart('live')">直播</div>
|
|
|
+ <div class="toolbar-item" draggable="true" @dragstart="onToolbarDragStart('webPage')">网页</div>
|
|
|
<!-- 可扩展更多组件 -->
|
|
|
</div>
|
|
|
<div class="editor-canvas" ref="editorCanvasRef" @dragover.prevent @drop="onCanvasDrop">
|
|
|
@@ -82,6 +84,13 @@
|
|
|
item.height = height;
|
|
|
}
|
|
|
" @click.stop="selectComponent(item)" :class="{ selected: selectedComponent === item }" />
|
|
|
+ <WebPageBoard v-if="item.type === 'webPage'" :width="item.width" :height="item.height" :url="item.url"
|
|
|
+ :selected="selectedComponent === item" @resize="
|
|
|
+ ({ width, height }) => {
|
|
|
+ item.width = width;
|
|
|
+ item.height = height;
|
|
|
+ }
|
|
|
+ " @click.stop="selectComponent(item)" :class="{ selected: selectedComponent === item }" />
|
|
|
<!-- 未来可扩展更多类型 -->
|
|
|
</div>
|
|
|
</template>
|
|
|
@@ -164,7 +173,15 @@ import TextBoard from './component/TextBoard.vue';
|
|
|
import ScrollingTextBoard from './component/ScrollingTextBoard.vue';
|
|
|
import MediaAssetBoard from './component/MediaAssetBoard.vue';
|
|
|
import LiveBoard from './component/LiveBoard.vue';
|
|
|
-import { canvasPropNameMap, textPropNameMap, scrollingTextPropNameMap, mediaAssetPropNameMap, livePropNameMap } from './component/propNameMaps';
|
|
|
+import WebPageBoard from './component/WebPageBoard.vue';
|
|
|
+import {
|
|
|
+ canvasPropNameMap,
|
|
|
+ textPropNameMap,
|
|
|
+ scrollingTextPropNameMap,
|
|
|
+ mediaAssetPropNameMap,
|
|
|
+ livePropNameMap,
|
|
|
+ webPagePropNameMap
|
|
|
+} from './component/propNameMaps';
|
|
|
// 拖拽类型
|
|
|
const dragType = ref<string | null>(null);
|
|
|
// 获取最大 depth
|
|
|
@@ -213,6 +230,8 @@ function getPropLabel(key: string) {
|
|
|
return mediaAssetPropNameMap[key] || key;
|
|
|
} else if (selectedComponent.value?.type === 'live') {
|
|
|
return livePropNameMap[key] || key;
|
|
|
+ } else if (selectedComponent.value?.type === 'webPage') {
|
|
|
+ return webPagePropNameMap[key] || key;
|
|
|
}
|
|
|
return key;
|
|
|
}
|
|
|
@@ -298,6 +317,7 @@ const editorContent = ref({ elements: [] });
|
|
|
|
|
|
// editor-canvas 缩放逻辑
|
|
|
const editorCanvasRef = ref<HTMLElement | null>(null);
|
|
|
+const containerSize = ref({ width: 0, height: 0 });
|
|
|
const dragComponentType = ref<string | null>(null);
|
|
|
|
|
|
const draggingId = ref<number | null>(null);
|
|
|
@@ -397,12 +417,22 @@ function onCanvasDrop(e: DragEvent) {
|
|
|
};
|
|
|
editorContent.value.elements.push(newLive);
|
|
|
nextTick(() => selectComponent(newLive));
|
|
|
+ } else if (dragType.value === 'webPage') {
|
|
|
+ const newWebPage = {
|
|
|
+ type: 'webPage',
|
|
|
+ url: '',
|
|
|
+ x: x,
|
|
|
+ y: y,
|
|
|
+ width: 120,
|
|
|
+ height: 120,
|
|
|
+ depth: getMaxDepth() + 1
|
|
|
+ };
|
|
|
+ editorContent.value.elements.push(newWebPage);
|
|
|
+ nextTick(() => selectComponent(newWebPage));
|
|
|
}
|
|
|
dragType.value = null;
|
|
|
}
|
|
|
|
|
|
-const containerSize = ref({ width: 0, height: 0 });
|
|
|
-
|
|
|
function updateContainerSize() {
|
|
|
if (editorCanvasRef.value) {
|
|
|
containerSize.value.width = editorCanvasRef.value.clientWidth;
|
|
|
@@ -427,13 +457,7 @@ const canvasScale = computed(() => {
|
|
|
return Math.min(boxW / cW, boxH / cH, 1);
|
|
|
});
|
|
|
|
|
|
-try {
|
|
|
- let parsed = json_str ? JSON.parse(json_str) : { elements: [] };
|
|
|
- editorContent.value.elements = ensureCanvasAndDepth(parsed.elements || []);
|
|
|
-} catch (e) {
|
|
|
- // fallback
|
|
|
- editorContent.value.elements = ensureCanvasAndDepth([]);
|
|
|
-}
|
|
|
+// 已移除多余的 return 和重复代码,仅保留 canvasScale 的 computed 实现
|
|
|
|
|
|
const handleSave = () => {
|
|
|
program.value.content = JSON.stringify(editorContent.value);
|