File size: 5,949 Bytes
89ce340 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
<template>
<div
class="editable-element"
ref="elementRef"
:id="`editable-element-${elementInfo.id}`"
:style="{
zIndex: elementIndex,
}"
>
<component
:is="currentElementComponent"
:elementInfo="elementInfo"
:selectElement="selectElement"
:contextmenus="contextmenus"
></component>
</div>
</template>
<script lang="ts" setup>
import { computed } from 'vue'
import { ElementTypes, type PPTElement } from '@/types/slides'
import type { ContextmenuItem } from '@/components/Contextmenu/types'
import useLockElement from '@/hooks/useLockElement'
import useDeleteElement from '@/hooks/useDeleteElement'
import useCombineElement from '@/hooks/useCombineElement'
import useOrderElement from '@/hooks/useOrderElement'
import useAlignElementToCanvas from '@/hooks/useAlignElementToCanvas'
import useCopyAndPasteElement from '@/hooks/useCopyAndPasteElement'
import useSelectElement from '@/hooks/useSelectElement'
import { ElementOrderCommands, ElementAlignCommands } from '@/types/edit'
import ImageElement from '@/views/components/element/ImageElement/index.vue'
import TextElement from '@/views/components/element/TextElement/index.vue'
import ShapeElement from '@/views/components/element/ShapeElement/index.vue'
import LineElement from '@/views/components/element/LineElement/index.vue'
import ChartElement from '@/views/components/element/ChartElement/index.vue'
import TableElement from '@/views/components/element/TableElement/index.vue'
import LatexElement from '@/views/components/element/LatexElement/index.vue'
import VideoElement from '@/views/components/element/VideoElement/index.vue'
import AudioElement from '@/views/components/element/AudioElement/index.vue'
const props = defineProps<{
elementInfo: PPTElement
elementIndex: number
isMultiSelect: boolean
selectElement: (e: MouseEvent | TouchEvent, element: PPTElement, canMove?: boolean) => void
openLinkDialog: () => void
}>()
const currentElementComponent = computed<unknown>(() => {
const elementTypeMap = {
[ElementTypes.IMAGE]: ImageElement,
[ElementTypes.TEXT]: TextElement,
[ElementTypes.SHAPE]: ShapeElement,
[ElementTypes.LINE]: LineElement,
[ElementTypes.CHART]: ChartElement,
[ElementTypes.TABLE]: TableElement,
[ElementTypes.LATEX]: LatexElement,
[ElementTypes.VIDEO]: VideoElement,
[ElementTypes.AUDIO]: AudioElement,
}
return elementTypeMap[props.elementInfo.type] || null
})
const { orderElement } = useOrderElement()
const { alignElementToCanvas } = useAlignElementToCanvas()
const { combineElements, uncombineElements } = useCombineElement()
const { deleteElement } = useDeleteElement()
const { lockElement, unlockElement } = useLockElement()
const { copyElement, pasteElement, cutElement } = useCopyAndPasteElement()
const { selectAllElements } = useSelectElement()
const contextmenus = (): ContextmenuItem[] => {
if (props.elementInfo.lock) {
return [{
text: '解锁',
handler: () => unlockElement(props.elementInfo),
}]
}
return [
{
text: '剪切',
subText: 'Ctrl + X',
handler: cutElement,
},
{
text: '复制',
subText: 'Ctrl + C',
handler: copyElement,
},
{
text: '粘贴',
subText: 'Ctrl + V',
handler: pasteElement,
},
{ divider: true },
{
text: '水平居中',
handler: () => alignElementToCanvas(ElementAlignCommands.HORIZONTAL),
children: [
{ text: '水平垂直居中', handler: () => alignElementToCanvas(ElementAlignCommands.CENTER), },
{ text: '水平居中', handler: () => alignElementToCanvas(ElementAlignCommands.HORIZONTAL) },
{ text: '左对齐', handler: () => alignElementToCanvas(ElementAlignCommands.LEFT) },
{ text: '右对齐', handler: () => alignElementToCanvas(ElementAlignCommands.RIGHT) },
],
},
{
text: '垂直居中',
handler: () => alignElementToCanvas(ElementAlignCommands.VERTICAL),
children: [
{ text: '水平垂直居中', handler: () => alignElementToCanvas(ElementAlignCommands.CENTER) },
{ text: '垂直居中', handler: () => alignElementToCanvas(ElementAlignCommands.VERTICAL) },
{ text: '顶部对齐', handler: () => alignElementToCanvas(ElementAlignCommands.TOP) },
{ text: '底部对齐', handler: () => alignElementToCanvas(ElementAlignCommands.BOTTOM) },
],
},
{ divider: true },
{
text: '置于顶层',
disable: props.isMultiSelect && !props.elementInfo.groupId,
handler: () => orderElement(props.elementInfo, ElementOrderCommands.TOP),
children: [
{ text: '置于顶层', handler: () => orderElement(props.elementInfo, ElementOrderCommands.TOP) },
{ text: '上移一层', handler: () => orderElement(props.elementInfo, ElementOrderCommands.UP) },
],
},
{
text: '置于底层',
disable: props.isMultiSelect && !props.elementInfo.groupId,
handler: () => orderElement(props.elementInfo, ElementOrderCommands.BOTTOM),
children: [
{ text: '置于底层', handler: () => orderElement(props.elementInfo, ElementOrderCommands.BOTTOM) },
{ text: '下移一层', handler: () => orderElement(props.elementInfo, ElementOrderCommands.DOWN) },
],
},
{ divider: true },
{
text: '设置链接',
handler: props.openLinkDialog,
},
{
text: props.elementInfo.groupId ? '取消组合' : '组合',
subText: 'Ctrl + G',
handler: props.elementInfo.groupId ? uncombineElements : combineElements,
hide: !props.isMultiSelect,
},
{
text: '全选',
subText: 'Ctrl + A',
handler: selectAllElements,
},
{
text: '锁定',
subText: 'Ctrl + L',
handler: lockElement,
},
{
text: '删除',
subText: 'Delete',
handler: deleteElement,
},
]
}
</script> |