File size: 6,158 Bytes
89ce340 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
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,
}
} |