| <template> | |
| <div class="toolbar"> | |
| <Tabs | |
| :tabs="currentTabs" | |
| :value="toolbarState" | |
| card | |
| @update:value="key => setToolbarState(key as ToolbarStates)" | |
| /> | |
| <div class="content"> | |
| <component :is="currentPanelComponent"></component> | |
| </div> | |
| </div> | |
| </template> | |
| <script lang="ts" setup> | |
| import { computed, watch } from 'vue' | |
| import { storeToRefs } from 'pinia' | |
| import { useMainStore } from '@/store' | |
| import { ToolbarStates } from '@/types/toolbar' | |
| import ElementStylePanel from './ElementStylePanel/index.vue' | |
| import ElementPositionPanel from './ElementPositionPanel.vue' | |
| import ElementAnimationPanel from './ElementAnimationPanel.vue' | |
| import SlideDesignPanel from './SlideDesignPanel/index.vue' | |
| import SlideAnimationPanel from './SlideAnimationPanel.vue' | |
| import MultiPositionPanel from './MultiPositionPanel.vue' | |
| import MultiStylePanel from './MultiStylePanel.vue' | |
| import SymbolPanel from './SymbolPanel.vue' | |
| import Tabs from '@/components/Tabs.vue' | |
| interface ElementTabs { | |
| label: string | |
| key: ToolbarStates | |
| } | |
| const mainStore = useMainStore() | |
| const { activeElementIdList, activeElementList, activeGroupElementId, handleElement, toolbarState } = storeToRefs(mainStore) | |
| const elementTabs = computed<ElementTabs[]>(() => { | |
| if (handleElement.value?.type === 'text') { | |
| return [ | |
| { label: '样式', key: ToolbarStates.EL_STYLE }, | |
| { label: '符号', key: ToolbarStates.SYMBOL }, | |
| { label: '位置', key: ToolbarStates.EL_POSITION }, | |
| { label: '动画', key: ToolbarStates.EL_ANIMATION }, | |
| ] | |
| } | |
| return [ | |
| { label: '样式', key: ToolbarStates.EL_STYLE }, | |
| { label: '位置', key: ToolbarStates.EL_POSITION }, | |
| { label: '动画', key: ToolbarStates.EL_ANIMATION }, | |
| ] | |
| }) | |
| const slideTabs = [ | |
| { label: '设计', key: ToolbarStates.SLIDE_DESIGN }, | |
| { label: '切换', key: ToolbarStates.SLIDE_ANIMATION }, | |
| { label: '动画', key: ToolbarStates.EL_ANIMATION }, | |
| ] | |
| const multiSelectTabs = [ | |
| { label: '样式(多选)', key: ToolbarStates.MULTI_STYLE }, | |
| { label: '位置(多选)', key: ToolbarStates.MULTI_POSITION }, | |
| ] | |
| const setToolbarState = (value: ToolbarStates) => { | |
| mainStore.setToolbarState(value) | |
| } | |
| const currentTabs = computed(() => { | |
| if (!activeElementIdList.value.length) return slideTabs | |
| else if (activeElementIdList.value.length > 1) { | |
| if (!activeGroupElementId.value) return multiSelectTabs | |
| const activeGroupElement = activeElementList.value.find(item => item.id === activeGroupElementId.value) | |
| if (activeGroupElement) return elementTabs.value | |
| return multiSelectTabs | |
| } | |
| return elementTabs.value | |
| }) | |
| watch(currentTabs, () => { | |
| const currentTabsValue: ToolbarStates[] = currentTabs.value.map(tab => tab.key) | |
| if (!currentTabsValue.includes(toolbarState.value)) { | |
| mainStore.setToolbarState(currentTabsValue[0]) | |
| } | |
| }) | |
| const currentPanelComponent = computed(() => { | |
| const panelMap = { | |
| [ToolbarStates.EL_STYLE]: ElementStylePanel, | |
| [ToolbarStates.EL_POSITION]: ElementPositionPanel, | |
| [ToolbarStates.EL_ANIMATION]: ElementAnimationPanel, | |
| [ToolbarStates.SLIDE_DESIGN]: SlideDesignPanel, | |
| [ToolbarStates.SLIDE_ANIMATION]: SlideAnimationPanel, | |
| [ToolbarStates.MULTI_STYLE]: MultiStylePanel, | |
| [ToolbarStates.MULTI_POSITION]: MultiPositionPanel, | |
| [ToolbarStates.SYMBOL]: SymbolPanel, | |
| } | |
| return panelMap[toolbarState.value] || null | |
| }) | |
| </script> | |
| <style lang="scss" scoped> | |
| .toolbar { | |
| border-left: solid 1px $borderColor; | |
| background-color: #fff; | |
| display: flex; | |
| flex-direction: column; | |
| } | |
| .content { | |
| padding: 12px; | |
| font-size: 13px; | |
| @include overflow-overlay(); | |
| } | |
| </style> |