mirror of
https://github.com/pipipi-pikachu/PPTist.git
synced 2025-04-15 02:20:00 +08:00
feat: 添加幻灯片页面批量操作
This commit is contained in:
parent
5421f82801
commit
8c705ca09c
@ -35,6 +35,7 @@ export const HOTKEY_DOC = [
|
|||||||
{ label: '撤销', value: 'Ctrl + Z' },
|
{ label: '撤销', value: 'Ctrl + Z' },
|
||||||
{ label: '恢复', value: 'Ctrl + Y' },
|
{ label: '恢复', value: 'Ctrl + Y' },
|
||||||
{ label: '删除', value: 'Delete / Backspace' },
|
{ label: '删除', value: 'Delete / Backspace' },
|
||||||
|
{ label: '多选', value: '按住 Ctrl 或 Shift' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -67,7 +68,6 @@ export const HOTKEY_DOC = [
|
|||||||
{ label: '取消组合', value: 'Ctrl + Shift + G' },
|
{ label: '取消组合', value: 'Ctrl + Shift + G' },
|
||||||
{ label: '置顶层', value: 'Alt + F' },
|
{ label: '置顶层', value: 'Alt + F' },
|
||||||
{ label: '置底层', value: 'Alt + B' },
|
{ label: '置底层', value: 'Alt + B' },
|
||||||
{ label: '多选', value: '按住 Ctrl 或 Shift' },
|
|
||||||
{ label: '锁定宽高比例', value: '按住 Ctrl 或 Shift' },
|
{ label: '锁定宽高比例', value: '按住 Ctrl 或 Shift' },
|
||||||
{ label: '创建水平 / 垂直线条', value: '按住 Ctrl 或 Shift' },
|
{ label: '创建水平 / 垂直线条', value: '按住 Ctrl 或 Shift' },
|
||||||
{ label: '确认图片裁剪', value: 'Enter' },
|
{ label: '确认图片裁剪', value: 'Enter' },
|
||||||
|
@ -55,11 +55,12 @@ export default () => {
|
|||||||
* 粘贴页面
|
* 粘贴页面
|
||||||
* @param slide 页面数据
|
* @param slide 页面数据
|
||||||
*/
|
*/
|
||||||
const pasteSlide = (slide: Slide) => {
|
const pasteSlides = (slides: Slide[]) => {
|
||||||
store.commit(MutationTypes.ADD_SLIDE, {
|
const newSlides = slides.map(slide => ({
|
||||||
...slide,
|
...slide,
|
||||||
id: createRandomCode(8),
|
id: createRandomCode(8),
|
||||||
})
|
}))
|
||||||
|
store.commit(MutationTypes.ADD_SLIDE, newSlides)
|
||||||
addHistorySnapshot()
|
addHistorySnapshot()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,7 +99,7 @@ export default () => {
|
|||||||
const { type, data } = clipboardData
|
const { type, data } = clipboardData
|
||||||
|
|
||||||
if (type === 'elements' && !onlySlide) pasteElement(data)
|
if (type === 'elements' && !onlySlide) pasteElement(data)
|
||||||
else if (type === 'slide' && !onlyElements) pasteSlide(data)
|
else if (type === 'slides' && !onlyElements) pasteSlides(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 普通文本
|
// 普通文本
|
||||||
|
@ -13,12 +13,26 @@ export default () => {
|
|||||||
const store = useStore()
|
const store = useStore()
|
||||||
const slideIndex = computed(() => store.state.slideIndex)
|
const slideIndex = computed(() => store.state.slideIndex)
|
||||||
const theme = computed(() => store.state.theme)
|
const theme = computed(() => store.state.theme)
|
||||||
const slidesLength = computed(() => store.state.slides.length)
|
const slides = computed(() => store.state.slides)
|
||||||
const currentSlide = computed<Slide>(() => store.getters.currentSlide)
|
const currentSlide = computed<Slide>(() => store.getters.currentSlide)
|
||||||
|
|
||||||
|
const selectedSlidesIndex = computed(() => [...store.state.selectedSlidesIndex, 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 { pasteTextClipboardData } = usePasteTextClipboardData()
|
||||||
const { addHistorySnapshot } = useHistorySnapshot()
|
const { addHistorySnapshot } = useHistorySnapshot()
|
||||||
|
|
||||||
|
// 重置幻灯片
|
||||||
|
const resetSlides = () => {
|
||||||
|
store.commit(MutationTypes.UPDATE_SLIDE_INDEX, 0)
|
||||||
|
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])
|
||||||
|
store.commit(MutationTypes.SET_SLIDES, [{
|
||||||
|
id: createRandomCode(),
|
||||||
|
elements: [],
|
||||||
|
}])
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 移动页面焦点
|
* 移动页面焦点
|
||||||
* @param command 移动页面焦点命令:上移、下移
|
* @param command 移动页面焦点命令:上移、下移
|
||||||
@ -28,7 +42,7 @@ export default () => {
|
|||||||
if (command === KEYS.UP && slideIndex.value > 0) {
|
if (command === KEYS.UP && slideIndex.value > 0) {
|
||||||
targetIndex = slideIndex.value - 1
|
targetIndex = slideIndex.value - 1
|
||||||
}
|
}
|
||||||
else if (command === KEYS.DOWN && slideIndex.value < slidesLength.value - 1) {
|
else if (command === KEYS.DOWN && slideIndex.value < slides.value.length - 1) {
|
||||||
targetIndex = slideIndex.value + 1
|
targetIndex = slideIndex.value + 1
|
||||||
}
|
}
|
||||||
store.commit(MutationTypes.UPDATE_SLIDE_INDEX, targetIndex)
|
store.commit(MutationTypes.UPDATE_SLIDE_INDEX, targetIndex)
|
||||||
@ -37,8 +51,8 @@ export default () => {
|
|||||||
// 将当前页面数据加密后复制到剪贴板
|
// 将当前页面数据加密后复制到剪贴板
|
||||||
const copySlide = () => {
|
const copySlide = () => {
|
||||||
const text = encrypt(JSON.stringify({
|
const text = encrypt(JSON.stringify({
|
||||||
type: 'slide',
|
type: 'slides',
|
||||||
data: currentSlide.value,
|
data: selectedSlides.value,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
copyText(text).then(() => {
|
copyText(text).then(() => {
|
||||||
@ -76,21 +90,26 @@ export default () => {
|
|||||||
addHistorySnapshot()
|
addHistorySnapshot()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除当前页
|
// 删除当前页,若将删除全部页面,则执行重置幻灯片操作
|
||||||
const deleteSlide = () => {
|
const deleteSlide = (targetSlidesId = selectedSlidesId.value) => {
|
||||||
if (slidesLength.value === 1) return message.warning('无法继续删除')
|
if (slides.value.length === targetSlidesId.length) resetSlides()
|
||||||
|
else store.commit(MutationTypes.DELETE_SLIDE, targetSlidesId)
|
||||||
store.commit(MutationTypes.DELETE_SLIDE, currentSlide.value.id)
|
|
||||||
|
store.commit(MutationTypes.UPDATE_SELECTED_SLIDES_INDEX, [])
|
||||||
|
|
||||||
addHistorySnapshot()
|
addHistorySnapshot()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 将当前页复制后删除(剪切)
|
// 将当前页复制后删除(剪切)
|
||||||
|
// 由于复制操作会导致多选状态消失,所以需要提前将需要删除的页面ID进行缓存
|
||||||
const cutSlide = () => {
|
const cutSlide = () => {
|
||||||
|
const targetSlidesId = [...selectedSlidesId.value]
|
||||||
copySlide()
|
copySlide()
|
||||||
deleteSlide()
|
deleteSlide(targetSlidesId)
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
resetSlides,
|
||||||
updateSlideIndex,
|
updateSlideIndex,
|
||||||
copySlide,
|
copySlide,
|
||||||
pasteSlide,
|
pasteSlide,
|
||||||
|
@ -82,9 +82,10 @@ export const mutations: MutationTree<State> = {
|
|||||||
state.slides = slides
|
state.slides = slides
|
||||||
},
|
},
|
||||||
|
|
||||||
[MutationTypes.ADD_SLIDE](state, slide: Slide) {
|
[MutationTypes.ADD_SLIDE](state, slide: Slide | Slide[]) {
|
||||||
|
const slides = Array.isArray(slide) ? slide : [slide]
|
||||||
const addIndex = state.slideIndex + 1
|
const addIndex = state.slideIndex + 1
|
||||||
state.slides.splice(addIndex, 0, slide)
|
state.slides.splice(addIndex, 0, ...slides)
|
||||||
state.slideIndex = addIndex
|
state.slideIndex = addIndex
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -93,13 +94,21 @@ export const mutations: MutationTree<State> = {
|
|||||||
state.slides[slideIndex] = { ...state.slides[slideIndex], ...props }
|
state.slides[slideIndex] = { ...state.slides[slideIndex], ...props }
|
||||||
},
|
},
|
||||||
|
|
||||||
[MutationTypes.DELETE_SLIDE](state, slideId: string) {
|
[MutationTypes.DELETE_SLIDE](state, slideId: string | string[]) {
|
||||||
const deleteIndex = state.slides.findIndex(item => item.id === slideId)
|
const slidesId = Array.isArray(slideId) ? slideId : [slideId]
|
||||||
|
|
||||||
if (deleteIndex === state.slides.length - 1) {
|
const deleteSlidesIndex = []
|
||||||
state.slideIndex = deleteIndex - 1
|
for (let i = 0; i < slidesId.length; i++) {
|
||||||
|
const index = state.slides.findIndex(item => item.id === slidesId[i])
|
||||||
|
deleteSlidesIndex.push(index)
|
||||||
}
|
}
|
||||||
state.slides.splice(deleteIndex, 1)
|
let newIndex = Math.min(...deleteSlidesIndex)
|
||||||
|
|
||||||
|
const maxIndex = state.slides.length - slidesId.length - 1
|
||||||
|
if (newIndex > maxIndex) newIndex = maxIndex
|
||||||
|
|
||||||
|
state.slideIndex = newIndex
|
||||||
|
state.slides = state.slides.filter(item => !slidesId.includes(item.id))
|
||||||
},
|
},
|
||||||
|
|
||||||
[MutationTypes.UPDATE_SLIDE_INDEX](state, index: number) {
|
[MutationTypes.UPDATE_SLIDE_INDEX](state, index: number) {
|
||||||
|
@ -65,7 +65,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { computed, defineComponent, ref } from 'vue'
|
import { computed, defineComponent, ref } from 'vue'
|
||||||
import { MutationTypes, useStore } from '@/store'
|
import { MutationTypes, useStore } from '@/store'
|
||||||
import { createRandomCode } from '@/utils/common'
|
|
||||||
import useScreening from '@/hooks/useScreening'
|
import useScreening from '@/hooks/useScreening'
|
||||||
import useSlideHandler from '@/hooks/useSlideHandler'
|
import useSlideHandler from '@/hooks/useSlideHandler'
|
||||||
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
|
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
|
||||||
@ -82,7 +81,7 @@ export default defineComponent({
|
|||||||
const store = useStore()
|
const store = useStore()
|
||||||
|
|
||||||
const { enterScreening, enterScreeningFromStart } = useScreening()
|
const { enterScreening, enterScreeningFromStart } = useScreening()
|
||||||
const { createSlide, deleteSlide } = useSlideHandler()
|
const { createSlide, deleteSlide, resetSlides } = useSlideHandler()
|
||||||
const { redo, undo } = useHistorySnapshot()
|
const { redo, undo } = useHistorySnapshot()
|
||||||
|
|
||||||
const editDropdownVisible = ref(false)
|
const editDropdownVisible = ref(false)
|
||||||
@ -94,14 +93,6 @@ export default defineComponent({
|
|||||||
store.commit(MutationTypes.SET_GRID_LINES_STATE, !showGridLines.value)
|
store.commit(MutationTypes.SET_GRID_LINES_STATE, !showGridLines.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
const resetSlides = () => {
|
|
||||||
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])
|
|
||||||
store.commit(MutationTypes.SET_SLIDES, [{
|
|
||||||
id: createRandomCode(),
|
|
||||||
elements: [],
|
|
||||||
}])
|
|
||||||
}
|
|
||||||
|
|
||||||
const openDoc = () => {
|
const openDoc = () => {
|
||||||
message.warning('作者努力编写中...')
|
message.warning('作者努力编写中...')
|
||||||
}
|
}
|
||||||
|
@ -200,7 +200,7 @@ export default defineComponent({
|
|||||||
{
|
{
|
||||||
text: '删除页面',
|
text: '删除页面',
|
||||||
subText: 'Delete',
|
subText: 'Delete',
|
||||||
handler: deleteSlide,
|
handler: () => deleteSlide(),
|
||||||
},
|
},
|
||||||
{ divider: true },
|
{ divider: true },
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user