| <template> | |
| <div class="element-outline"> | |
| <div class="row" v-if="!fixed"> | |
| <div style="width: 40%;">启用边框:</div> | |
| <div class="switch-wrapper" style="width: 60%;"> | |
| <Switch | |
| :value="hasOutline" | |
| @update:value="value => toggleOutline(value)" | |
| /> | |
| </div> | |
| </div> | |
| <template v-if="hasOutline && outline"> | |
| <div class="row"> | |
| <div style="width: 40%;">边框样式:</div> | |
| <SelectCustom style="width: 60%;"> | |
| <template #options> | |
| <div class="option" v-for="item in lineStyleOptions" :key="item" @click="updateOutline({ style: item })"> | |
| <SVGLine :type="item" /> | |
| </div> | |
| </template> | |
| <template #label> | |
| <SVGLine :type="outline.style" /> | |
| </template> | |
| </SelectCustom> | |
| </div> | |
| <div class="row"> | |
| <div style="width: 40%;">边框颜色:</div> | |
| <Popover trigger="click" style="width: 60%;"> | |
| <template #content> | |
| <ColorPicker | |
| :modelValue="outline.color" | |
| @update:modelValue="value => updateOutline({ color: value })" | |
| /> | |
| </template> | |
| <ColorButton :color="outline.color || '#000'" /> | |
| </Popover> | |
| </div> | |
| <div class="row"> | |
| <div style="width: 40%;">边框粗细:</div> | |
| <NumberInput | |
| :value="outline.width || 0" | |
| @update:value="value => updateOutline({ width: value })" | |
| style="width: 60%;" | |
| /> | |
| </div> | |
| </template> | |
| </div> | |
| </template> | |
| <script lang="ts" setup> | |
| import { ref, watch } from 'vue' | |
| import { storeToRefs } from 'pinia' | |
| import { useMainStore, useSlidesStore } from '@/store' | |
| import type { LineStyleType, PPTElementOutline } from '@/types/slides' | |
| import useHistorySnapshot from '@/hooks/useHistorySnapshot' | |
| import SVGLine from '../common/SVGLine.vue' | |
| import ColorButton from '@/components/ColorButton.vue' | |
| import ColorPicker from '@/components/ColorPicker/index.vue' | |
| import Switch from '@/components/Switch.vue' | |
| import NumberInput from '@/components/NumberInput.vue' | |
| import SelectCustom from '@/components/SelectCustom.vue' | |
| import Popover from '@/components/Popover.vue' | |
| withDefaults(defineProps<{ | |
| fixed?: boolean | |
| }>(), { | |
| fixed: false, | |
| }) | |
| const slidesStore = useSlidesStore() | |
| const { theme } = storeToRefs(slidesStore) | |
| const { handleElement } = storeToRefs(useMainStore()) | |
| const outline = ref<PPTElementOutline>() | |
| const hasOutline = ref(false) | |
| const lineStyleOptions = ref<LineStyleType[]>(['solid', 'dashed', 'dotted']) | |
| watch(handleElement, () => { | |
| if (!handleElement.value) return | |
| outline.value = 'outline' in handleElement.value ? handleElement.value.outline : undefined | |
| hasOutline.value = !!outline.value | |
| }, { deep: true, immediate: true }) | |
| const { addHistorySnapshot } = useHistorySnapshot() | |
| const updateOutline = (outlineProps: Partial<PPTElementOutline>) => { | |
| if (!handleElement.value) return | |
| const props = { outline: { ...outline.value, ...outlineProps } } | |
| slidesStore.updateElement({ id: handleElement.value.id, props }) | |
| addHistorySnapshot() | |
| } | |
| const toggleOutline = (checked: boolean) => { | |
| if (!handleElement.value) return | |
| if (checked) { | |
| const _outline: PPTElementOutline = theme.value.outline | |
| slidesStore.updateElement({ id: handleElement.value.id, props: { outline: _outline } }) | |
| } | |
| else { | |
| slidesStore.removeElementProps({ id: handleElement.value.id, propName: 'outline' }) | |
| } | |
| addHistorySnapshot() | |
| } | |
| </script> | |
| <style lang="scss" scoped> | |
| .row { | |
| width: 100%; | |
| height: 30px; | |
| display: flex; | |
| align-items: center; | |
| margin-bottom: 10px; | |
| } | |
| .switch-wrapper { | |
| text-align: right; | |
| } | |
| .option { | |
| height: 32px; | |
| padding: 0 5px; | |
| border-radius: $borderRadius; | |
| &:not(.selected):hover { | |
| background-color: rgba($color: $themeColor, $alpha: .05); | |
| cursor: pointer; | |
| } | |
| &.selected { | |
| color: $themeColor; | |
| font-weight: 700; | |
| } | |
| } | |
| </style> |