|
|
@@ -21,6 +21,7 @@
|
|
|
<template v-else-if="item.type === 'text'">文本</template>
|
|
|
<template v-else-if="item.type === 'scrollingText'">滚动文本</template>
|
|
|
<template v-else-if="item.type === 'mediaAsset'">媒资</template>
|
|
|
+ <template v-else-if="item.type === 'live'">直播</template>
|
|
|
<!-- 未来可扩展图片等类型 -->
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -33,6 +34,7 @@
|
|
|
<div class="toolbar-item" draggable="true" @dragstart="onToolbarDragStart('text')">文本</div>
|
|
|
<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>
|
|
|
<div class="editor-canvas" ref="editorCanvasRef" @dragover.prevent @drop="onCanvasDrop">
|
|
|
@@ -73,6 +75,13 @@
|
|
|
item.height = height;
|
|
|
}
|
|
|
" @click.stop="selectComponent(item)" :class="{ selected: selectedComponent === item }" />
|
|
|
+ <LiveBoard v-if="item.type === 'live'" :width="item.width" :height="item.height" :live-url="item.liveUrl"
|
|
|
+ :play-audio="item.playAudio" :selected="selectedComponent === item" @resize="
|
|
|
+ ({ width, height }) => {
|
|
|
+ item.width = width;
|
|
|
+ item.height = height;
|
|
|
+ }
|
|
|
+ " @click.stop="selectComponent(item)" :class="{ selected: selectedComponent === item }" />
|
|
|
<!-- 未来可扩展更多类型 -->
|
|
|
</div>
|
|
|
</template>
|
|
|
@@ -93,7 +102,12 @@
|
|
|
<div style="margin-bottom: 8px; font-weight: bold">组件属性</div>
|
|
|
<template v-for="[key, value] in Object.entries(selectedComponent || {})" :key="key">
|
|
|
<el-form-item v-if="showEditableProp(key)" :label="getPropLabel(key)">
|
|
|
- <el-input v-model="selectedComponent[key]" />
|
|
|
+ <template v-if="selectedComponent.type === 'live' && key === 'playAudio'">
|
|
|
+ <el-switch v-model="selectedComponent[key]" active-text="开" inactive-text="关" />
|
|
|
+ </template>
|
|
|
+ <template v-else>
|
|
|
+ <el-input v-model="selectedComponent[key]" />
|
|
|
+ </template>
|
|
|
</el-form-item>
|
|
|
</template>
|
|
|
</template>
|
|
|
@@ -149,7 +163,8 @@ import CanvasBoard from './component/CanvasBoard.vue';
|
|
|
import TextBoard from './component/TextBoard.vue';
|
|
|
import ScrollingTextBoard from './component/ScrollingTextBoard.vue';
|
|
|
import MediaAssetBoard from './component/MediaAssetBoard.vue';
|
|
|
-import { canvasPropNameMap } from './component/propNameMaps';
|
|
|
+import LiveBoard from './component/LiveBoard.vue';
|
|
|
+import { canvasPropNameMap, textPropNameMap, scrollingTextPropNameMap, mediaAssetPropNameMap, livePropNameMap } from './component/propNameMaps';
|
|
|
// 拖拽类型
|
|
|
const dragType = ref<string | null>(null);
|
|
|
// 获取最大 depth
|
|
|
@@ -187,19 +202,17 @@ function showEditableProp(key: string) {
|
|
|
}
|
|
|
|
|
|
// 获取属性中文名
|
|
|
-import { textPropNameMap, scrollingTextPropNameMap, mediaAssetPropNameMap } from './component/propNameMaps';
|
|
|
function getPropLabel(key: string) {
|
|
|
if (selectedComponent.value?.type === 'canvas') {
|
|
|
return canvasPropNameMap[key] || key;
|
|
|
- }
|
|
|
- if (selectedComponent.value?.type === 'text') {
|
|
|
+ } else if (selectedComponent.value?.type === 'text') {
|
|
|
return textPropNameMap[key] || key;
|
|
|
- }
|
|
|
- if (selectedComponent.value?.type === 'scrollingText') {
|
|
|
+ } else if (selectedComponent.value?.type === 'scrollingText') {
|
|
|
return scrollingTextPropNameMap[key] || key;
|
|
|
- }
|
|
|
- if (selectedComponent.value?.type === 'mediaAsset') {
|
|
|
+ } else if (selectedComponent.value?.type === 'mediaAsset') {
|
|
|
return mediaAssetPropNameMap[key] || key;
|
|
|
+ } else if (selectedComponent.value?.type === 'live') {
|
|
|
+ return livePropNameMap[key] || key;
|
|
|
}
|
|
|
return key;
|
|
|
}
|
|
|
@@ -307,9 +320,8 @@ function onElementMouseMove(e: MouseEvent) {
|
|
|
if (draggingId.value === null) return;
|
|
|
const item = editorContent.value.elements.find((el) => el.depth === draggingId.value);
|
|
|
if (!item) return;
|
|
|
- const scale = canvasScale.value || 1;
|
|
|
- item.x = dragStart.offsetX + (e.clientX - dragStart.x) / scale;
|
|
|
- item.y = dragStart.offsetY + (e.clientY - dragStart.y) / scale;
|
|
|
+ item.x = dragStart.offsetX + (e.clientX - dragStart.x);
|
|
|
+ item.y = dragStart.offsetY + (e.clientY - dragStart.y);
|
|
|
}
|
|
|
|
|
|
function onElementMouseUp() {
|
|
|
@@ -372,6 +384,19 @@ function onCanvasDrop(e: DragEvent) {
|
|
|
};
|
|
|
editorContent.value.elements.push(newMediaAsset);
|
|
|
nextTick(() => selectComponent(newMediaAsset));
|
|
|
+ } else if (dragType.value === 'live') {
|
|
|
+ const newLive = {
|
|
|
+ type: 'live',
|
|
|
+ liveUrl: '',
|
|
|
+ playAudio: true,
|
|
|
+ x: x,
|
|
|
+ y: y,
|
|
|
+ width: 200,
|
|
|
+ height: 120,
|
|
|
+ depth: getMaxDepth() + 1
|
|
|
+ };
|
|
|
+ editorContent.value.elements.push(newLive);
|
|
|
+ nextTick(() => selectComponent(newLive));
|
|
|
}
|
|
|
dragType.value = null;
|
|
|
}
|
|
|
@@ -508,7 +533,7 @@ const goBack = () => {
|
|
|
align-self: flex-start;
|
|
|
align-items: center;
|
|
|
height: 50px;
|
|
|
- width: 450px;
|
|
|
+ width: 700px;
|
|
|
margin-left: 5%;
|
|
|
margin-top: -5%;
|
|
|
margin-bottom: 1%;
|