| <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> |