| <template> | |
| <MoveablePanel | |
| class="notes-panel" | |
| :width="300" | |
| :height="130" | |
| title="幻灯片类型标注" | |
| :left="-270" | |
| :top="90" | |
| @close="close()" | |
| > | |
| <div class="container"> | |
| <div class="row"> | |
| <div style="width: 40%;">当前页面类型:</div> | |
| <Select | |
| style="width: 60%;" | |
| :value="slideType" | |
| @update:value="value => updateSlide(value as SlideType | '')" | |
| :options="slideTypeOptions" | |
| /> | |
| </div> | |
| <div class="row" v-if="handleElement && (handleElement.type === 'text' || (handleElement.type === 'shape' && handleElement.text))"> | |
| <div style="width: 40%;">当前文本类型:</div> | |
| <Select | |
| style="width: 60%;" | |
| :value="textType" | |
| @update:value="value => updateElement(value as TextType | '')" | |
| :options="textTypeOptions" | |
| /> | |
| </div> | |
| <div class="row" v-else-if="handleElement && handleElement.type === 'image'"> | |
| <div style="width: 40%;">当前图片类型:</div> | |
| <Select | |
| style="width: 60%;" | |
| :value="imageType" | |
| @update:value="value => updateElement(value as ImageType | '')" | |
| :options="imageTypeOptions" | |
| /> | |
| </div> | |
| <div class="placeholder" v-else>选中图片、文字、带文字的形状,标记类型</div> | |
| </div> | |
| </MoveablePanel> | |
| </template> | |
| <script lang="ts" setup> | |
| import { computed, ref } from 'vue' | |
| import { storeToRefs } from 'pinia' | |
| import { useMainStore, useSlidesStore } from '@/store' | |
| import type { ImageType, SlideType, TextType } from '@/types/slides' | |
| import MoveablePanel from '@/components/MoveablePanel.vue' | |
| import Select from '@/components/Select.vue' | |
| const slidesStore = useSlidesStore() | |
| const mainStore = useMainStore() | |
| const { currentSlide } = storeToRefs(slidesStore) | |
| const { handleElement, handleElementId } = storeToRefs(mainStore) | |
| const slideTypeOptions = ref<{ label: string; value: SlideType | '' }[]>([ | |
| { label: '未标记类型', value: '' }, | |
| { label: '封面页', value: 'cover' }, | |
| { label: '目录页', value: 'contents' }, | |
| { label: '过渡页', value: 'transition' }, | |
| { label: '内容页', value: 'content' }, | |
| { label: '结束页', value: 'end' }, | |
| ]) | |
| const textTypeOptions = ref<{ label: string; value: TextType | '' }[]>([ | |
| { label: '未标记类型', value: '' }, | |
| { label: '标题', value: 'title' }, | |
| { label: '副标题', value: 'subtitle' }, | |
| { label: '正文', value: 'content' }, | |
| { label: '列表项目', value: 'item' }, | |
| { label: '列表项标题', value: 'itemTitle' }, | |
| { label: '注释', value: 'notes' }, | |
| { label: '页眉', value: 'header' }, | |
| { label: '页脚', value: 'footer' }, | |
| { label: '节编号', value: 'partNumber' }, | |
| { label: '项目编号', value: 'itemNumber' }, | |
| ]) | |
| const imageTypeOptions = ref<{ label: string; value: ImageType | '' }[]>([ | |
| { label: '未标记类型', value: '' }, | |
| { label: '页面插图', value: 'pageFigure' }, | |
| { label: '项目插图', value: 'itemFigure' }, | |
| { label: '背景图', value: 'background' }, | |
| ]) | |
| const slideType = computed(() => currentSlide.value?.type || '') | |
| const textType = computed(() => { | |
| if (!handleElement.value) return '' | |
| if (handleElement.value.type === 'text') return handleElement.value.textType || '' | |
| if (handleElement.value.type === 'shape' && handleElement.value.text) return handleElement.value.text.type || '' | |
| return '' | |
| }) | |
| const imageType = computed(() => { | |
| if (!handleElement.value) return '' | |
| if (handleElement.value.type === 'image') return handleElement.value.imageType || '' | |
| return '' | |
| }) | |
| const updateSlide = (type: SlideType | '') => { | |
| if (type) slidesStore.updateSlide({ type }) | |
| else { | |
| slidesStore.removeSlideProps({ | |
| id: currentSlide.value.id, | |
| propName: 'type', | |
| }) | |
| } | |
| } | |
| const updateElement = (type: TextType | ImageType | '') => { | |
| if (!handleElement.value) return | |
| if (handleElement.value.type === 'image') { | |
| if (type) { | |
| slidesStore.updateElement({ id: handleElementId.value, props: { imageType: type as ImageType } }) | |
| } | |
| else { | |
| slidesStore.removeElementProps({ | |
| id: handleElementId.value, | |
| propName: 'imageType', | |
| }) | |
| } | |
| } | |
| if (handleElement.value.type === 'text') { | |
| if (type) { | |
| slidesStore.updateElement({ id: handleElementId.value, props: { textType: type as TextType } }) | |
| } | |
| else { | |
| slidesStore.removeElementProps({ | |
| id: handleElementId.value, | |
| propName: 'textType', | |
| }) | |
| } | |
| } | |
| if (handleElement.value.type === 'shape') { | |
| const text = handleElement.value.text | |
| if (!text) return | |
| if (type) { | |
| slidesStore.updateElement({ | |
| id: handleElementId.value, | |
| props: { text: { ...text, type: type as TextType } }, | |
| }) | |
| } | |
| else { | |
| delete text.type | |
| slidesStore.updateElement({ | |
| id: handleElementId.value, | |
| props: { text }, | |
| }) | |
| } | |
| } | |
| } | |
| const close = () => { | |
| mainStore.setMarkupPanelState(false) | |
| } | |
| </script> | |
| <style lang="scss" scoped> | |
| .notes-panel { | |
| height: 100%; | |
| font-size: 12px; | |
| user-select: none; | |
| } | |
| .container { | |
| height: 100%; | |
| display: flex; | |
| flex-direction: column; | |
| } | |
| .row { | |
| width: 100%; | |
| display: flex; | |
| align-items: center; | |
| & + .row { | |
| margin-top: 5px; | |
| } | |
| } | |
| .placeholder { | |
| height: 30px; | |
| line-height: 30px; | |
| text-align: center; | |
| color: #999; | |
| font-style: italic; | |
| border: 1px dashed #ccc; | |
| border-radius: $borderRadius; | |
| margin-top: 5px; | |
| } | |
| </style> |