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