import { computed } from 'vue' import { storeToRefs } from 'pinia' import { nanoid } from 'nanoid' import { useMainStore, useSlidesStore } from '@/store' import type { Slide } from '@/types/slides' import { copyText, readClipboard } from '@/utils/clipboard' import { encrypt } from '@/utils/crypto' import { createElementIdMap } from '@/utils/element' import { KEYS } from '@/configs/hotkey' import message from '@/utils/message' import usePasteTextClipboardData from '@/hooks/usePasteTextClipboardData' import useHistorySnapshot from '@/hooks/useHistorySnapshot' import useAddSlidesOrElements from '@/hooks/useAddSlidesOrElements' export default () => { const mainStore = useMainStore() const slidesStore = useSlidesStore() const { selectedSlidesIndex: _selectedSlidesIndex, activeElementIdList } = storeToRefs(mainStore) const { currentSlide, slides, theme, slideIndex } = storeToRefs(slidesStore) const selectedSlidesIndex = computed(() => [..._selectedSlidesIndex.value, slideIndex.value]) const selectedSlides = computed(() => slides.value.filter((item, index) => selectedSlidesIndex.value.includes(index))) const selectedSlidesId = computed(() => selectedSlides.value.map(item => item.id)) const { pasteTextClipboardData } = usePasteTextClipboardData() const { addSlidesFromData } = useAddSlidesOrElements() const { addHistorySnapshot } = useHistorySnapshot() // 重置幻灯片 const resetSlides = () => { const emptySlide: Slide = { id: nanoid(10), elements: [], background: { type: 'solid', color: theme.value.backgroundColor, }, } slidesStore.updateSlideIndex(0) mainStore.setActiveElementIdList([]) slidesStore.setSlides([emptySlide]) } /** * 移动页面焦点 * @param command 移动页面焦点命令:上移、下移 */ const updateSlideIndex = (command: string) => { if (command === KEYS.UP && slideIndex.value > 0) { if (activeElementIdList.value.length) mainStore.setActiveElementIdList([]) slidesStore.updateSlideIndex(slideIndex.value - 1) } else if (command === KEYS.DOWN && slideIndex.value < slides.value.length - 1) { if (activeElementIdList.value.length) mainStore.setActiveElementIdList([]) slidesStore.updateSlideIndex(slideIndex.value + 1) } } // 将当前页面数据加密后复制到剪贴板 const copySlide = () => { const text = encrypt(JSON.stringify({ type: 'slides', data: selectedSlides.value, })) copyText(text).then(() => { mainStore.setThumbnailsFocus(true) }) } // 尝试将剪贴板页面数据解密后添加到下一页(粘贴) const pasteSlide = () => { readClipboard().then(text => { pasteTextClipboardData(text, { onlySlide: true }) }).catch(err => message.warning(err)) } // 创建一页空白页并添加到下一页 const createSlide = () => { const emptySlide: Slide = { id: nanoid(10), elements: [], background: { type: 'solid', color: theme.value.backgroundColor, }, } mainStore.setActiveElementIdList([]) slidesStore.addSlide(emptySlide) addHistorySnapshot() } // 根据模板创建新页面 const createSlideByTemplate = (slide: Slide) => { const { groupIdMap, elIdMap } = createElementIdMap(slide.elements) for (const element of slide.elements) { element.id = elIdMap[element.id] if (element.groupId) element.groupId = groupIdMap[element.groupId] } const newSlide = { ...slide, id: nanoid(10), } mainStore.setActiveElementIdList([]) slidesStore.addSlide(newSlide) addHistorySnapshot() } // 将当前页复制一份到下一页 const copyAndPasteSlide = () => { const slide = JSON.parse(JSON.stringify(currentSlide.value)) addSlidesFromData([slide]) } // 删除当前页,若将删除全部页面,则执行重置幻灯片操作 const deleteSlide = (targetSlidesId = selectedSlidesId.value) => { if (slides.value.length === targetSlidesId.length) resetSlides() else slidesStore.deleteSlide(targetSlidesId) mainStore.updateSelectedSlidesIndex([]) addHistorySnapshot() } // 将当前页复制后删除(剪切) // 由于复制操作会导致多选状态消失,所以需要提前将需要删除的页面ID进行缓存 const cutSlide = () => { const targetSlidesId = [...selectedSlidesId.value] copySlide() deleteSlide(targetSlidesId) } // 选中全部幻灯片 const selectAllSlide = () => { const newSelectedSlidesIndex = Array.from(Array(slides.value.length), (item, index) => index) mainStore.setActiveElementIdList([]) mainStore.updateSelectedSlidesIndex(newSelectedSlidesIndex) } // 拖拽调整幻灯片顺序同步数据 const sortSlides = (newIndex: number, oldIndex: number) => { if (oldIndex === newIndex) return const _slides: Slide[] = JSON.parse(JSON.stringify(slides.value)) const movingSlide = _slides[oldIndex] const movingSlideSection = movingSlide.sectionTag if (movingSlideSection) { const movingSlideSectionNext = _slides[oldIndex + 1] delete movingSlide.sectionTag if (movingSlideSectionNext && !movingSlideSectionNext.sectionTag) { movingSlideSectionNext.sectionTag = movingSlideSection } } if (newIndex === 0) { const firstSection = _slides[0].sectionTag if (firstSection) { delete _slides[0].sectionTag movingSlide.sectionTag = firstSection } } const _slide = _slides[oldIndex] _slides.splice(oldIndex, 1) _slides.splice(newIndex, 0, _slide) slidesStore.setSlides(_slides) slidesStore.updateSlideIndex(newIndex) } const isEmptySlide = computed(() => { if (slides.value.length > 1) return false if (slides.value[0].elements.length > 0) return false return true }) return { resetSlides, updateSlideIndex, copySlide, pasteSlide, createSlide, createSlideByTemplate, copyAndPasteSlide, deleteSlide, cutSlide, selectAllSlide, sortSlides, isEmptySlide, } }