mirror of
https://github.com/pipipi-pikachu/PPTist.git
synced 2025-04-15 02:20:00 +08:00
update
This commit is contained in:
parent
2b49692319
commit
f575fa56b3
@ -1,160 +0,0 @@
|
|||||||
export const ANIMATIONS_TYPES = ['弹跳', '淡入', '翻转', '旋转', '滑入', '缩放']
|
|
||||||
|
|
||||||
export const ANIMATIONS = [
|
|
||||||
{
|
|
||||||
key: 'bounceIn',
|
|
||||||
type: '弹跳',
|
|
||||||
name: '弹跳',
|
|
||||||
icon: 'icon-anime-bounce'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'bounceInDown',
|
|
||||||
type: '弹跳',
|
|
||||||
name: '向下弹跳',
|
|
||||||
icon: 'icon-anime-bounce-down',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'bounceInLeft',
|
|
||||||
type: '弹跳',
|
|
||||||
name: '从左弹跳',
|
|
||||||
icon: 'icon-anime-bounce-left',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'bounceInRight',
|
|
||||||
type: '弹跳',
|
|
||||||
name: '从右弹跳',
|
|
||||||
icon: 'icon-anime-bounce-right',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'bounceInUp',
|
|
||||||
type: '弹跳',
|
|
||||||
name: '向上弹跳',
|
|
||||||
icon: 'icon-anime-bounce-up',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'fadeIn',
|
|
||||||
type: '淡入',
|
|
||||||
name: '淡入',
|
|
||||||
icon: 'icon-anime-fade',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'fadeInDown',
|
|
||||||
type: '淡入',
|
|
||||||
name: '向下淡入',
|
|
||||||
icon: 'icon-anime-fade-down',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'fadeInLeft',
|
|
||||||
type: '淡入',
|
|
||||||
name: '从左淡入',
|
|
||||||
icon: 'icon-anime-fade-left',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'fadeInRight',
|
|
||||||
type: '淡入',
|
|
||||||
name: '从右淡入',
|
|
||||||
icon: 'icon-anime-fade-right',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'fadeInUp',
|
|
||||||
type: '淡入',
|
|
||||||
name: '向上淡入',
|
|
||||||
icon: 'icon-anime-fade-up',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'flipInX',
|
|
||||||
type: '翻转',
|
|
||||||
name: '水平翻转',
|
|
||||||
icon: 'icon-anime-flip-x',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'flipInY',
|
|
||||||
type: '翻转',
|
|
||||||
name: '垂直翻转',
|
|
||||||
icon: 'icon-anime-flip-y',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'rotateIn',
|
|
||||||
type: '旋转',
|
|
||||||
name: '旋转',
|
|
||||||
icon: 'icon-anime-rotate',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'rotateInDownLeft',
|
|
||||||
type: '旋转',
|
|
||||||
name: '从左下旋转',
|
|
||||||
icon: 'icon-anime-rotate-up-right',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'rotateInDownRight',
|
|
||||||
type: '旋转',
|
|
||||||
name: '从右下旋转',
|
|
||||||
icon: 'icon-anime-rotate-up-left',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'rotateInUpLeft',
|
|
||||||
type: '旋转',
|
|
||||||
name: '从左上旋转',
|
|
||||||
icon: 'icon-anime-rotate-down-right',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'rotateInUpRight',
|
|
||||||
type: '旋转',
|
|
||||||
name: '从右上旋转',
|
|
||||||
icon: 'icon-anime-rotate-down-left',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'slideInDown',
|
|
||||||
type: '滑入',
|
|
||||||
name: '向下滑入',
|
|
||||||
icon: 'icon-anime-slide-down',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'slideInLeft',
|
|
||||||
type: '滑入',
|
|
||||||
name: '从左滑入',
|
|
||||||
icon: 'icon-anime-slide-left',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'slideInRight',
|
|
||||||
type: '滑入',
|
|
||||||
name: '从右滑入',
|
|
||||||
icon: 'icon-anime-slide-right',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'slideInUp',
|
|
||||||
type: '滑入',
|
|
||||||
name: '向上滑入',
|
|
||||||
icon: 'icon-anime-slide-up',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'zoomIn',
|
|
||||||
type: '缩放',
|
|
||||||
name: '放大',
|
|
||||||
icon: 'icon-anime-zoom',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'zoomInDown',
|
|
||||||
type: '缩放',
|
|
||||||
name: '向下放大',
|
|
||||||
icon: 'icon-anime-zoom-down',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'zoomInLeft',
|
|
||||||
type: '缩放',
|
|
||||||
name: '从左放大',
|
|
||||||
icon: 'icon-anime-zoom-left',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'zoomInRight',
|
|
||||||
type: '缩放',
|
|
||||||
name: '从右放大',
|
|
||||||
icon: 'icon-anime-zoom-right',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'zoomInUp',
|
|
||||||
type: '缩放',
|
|
||||||
name: '向上放大',
|
|
||||||
icon: 'icon-anime-zoom-up',
|
|
||||||
},
|
|
||||||
]
|
|
@ -1,15 +0,0 @@
|
|||||||
import { useStore } from 'vuex'
|
|
||||||
import debounce from 'lodash/debounce'
|
|
||||||
import { State, ActionTypes } from '@/store'
|
|
||||||
|
|
||||||
export default () => {
|
|
||||||
const store = useStore<State>()
|
|
||||||
|
|
||||||
const addHistorySnapshot = debounce(function() {
|
|
||||||
store.dispatch(ActionTypes.ADD_SNAPSHOT)
|
|
||||||
}, 300, { trailing: true })
|
|
||||||
|
|
||||||
return {
|
|
||||||
addHistorySnapshot,
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,6 +3,7 @@ import { useStore } from 'vuex'
|
|||||||
import { State, MutationTypes } from '@/store'
|
import { State, MutationTypes } from '@/store'
|
||||||
import { PPTElement, Slide } from '@/types/slides'
|
import { PPTElement, Slide } from '@/types/slides'
|
||||||
import { createRandomCode } from '@/utils/common'
|
import { createRandomCode } from '@/utils/common'
|
||||||
|
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
const store = useStore<State>()
|
const store = useStore<State>()
|
||||||
@ -10,6 +11,8 @@ export default () => {
|
|||||||
const activeElementList: Ref<PPTElement[]> = computed(() => store.getters.activeElementList)
|
const activeElementList: Ref<PPTElement[]> = computed(() => store.getters.activeElementList)
|
||||||
const currentSlide: Ref<Slide> = computed(() => store.getters.currentSlide)
|
const currentSlide: Ref<Slide> = computed(() => store.getters.currentSlide)
|
||||||
|
|
||||||
|
const { addHistorySnapshot } = useHistorySnapshot()
|
||||||
|
|
||||||
// 组合元素(为当前所有激活元素添加一个相同的groupId)
|
// 组合元素(为当前所有激活元素添加一个相同的groupId)
|
||||||
const combineElements = () => {
|
const combineElements = () => {
|
||||||
if(!activeElementList.value.length) return
|
if(!activeElementList.value.length) return
|
||||||
@ -34,6 +37,7 @@ export default () => {
|
|||||||
newElementList.splice(insertIndex, 0, ...combineElementList)
|
newElementList.splice(insertIndex, 0, ...combineElementList)
|
||||||
|
|
||||||
store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })
|
store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })
|
||||||
|
addHistorySnapshot()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 取消组合元素(移除所有被激活元素的groupId)
|
// 取消组合元素(移除所有被激活元素的groupId)
|
||||||
@ -47,6 +51,7 @@ export default () => {
|
|||||||
if(activeElementIdList.value.includes(element.elId) && element.groupId) delete element.groupId
|
if(activeElementIdList.value.includes(element.elId) && element.groupId) delete element.groupId
|
||||||
}
|
}
|
||||||
store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })
|
store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })
|
||||||
|
addHistorySnapshot()
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -12,6 +12,7 @@ import {
|
|||||||
DEFAULT_CHART,
|
DEFAULT_CHART,
|
||||||
DEFAULT_TABLE,
|
DEFAULT_TABLE,
|
||||||
} from '@/configs/element'
|
} from '@/configs/element'
|
||||||
|
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
|
||||||
|
|
||||||
interface CommonElementPosition {
|
interface CommonElementPosition {
|
||||||
top: number;
|
top: number;
|
||||||
@ -30,9 +31,12 @@ interface LineElementPosition {
|
|||||||
export default () => {
|
export default () => {
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
|
|
||||||
|
const { addHistorySnapshot } = useHistorySnapshot()
|
||||||
|
|
||||||
const createElement = (element: PPTElement) => {
|
const createElement = (element: PPTElement) => {
|
||||||
store.commit(MutationTypes.ADD_ELEMENT, element)
|
store.commit(MutationTypes.ADD_ELEMENT, element)
|
||||||
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [element.elId])
|
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [element.elId])
|
||||||
|
addHistorySnapshot()
|
||||||
}
|
}
|
||||||
|
|
||||||
const createImageElement = (imgUrl: string) => {
|
const createImageElement = (imgUrl: string) => {
|
||||||
|
@ -2,23 +2,28 @@ import { Ref, computed } from 'vue'
|
|||||||
import { useStore } from 'vuex'
|
import { useStore } from 'vuex'
|
||||||
import { State, MutationTypes } from '@/store'
|
import { State, MutationTypes } from '@/store'
|
||||||
import { Slide } from '@/types/slides'
|
import { Slide } from '@/types/slides'
|
||||||
|
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
const store = useStore<State>()
|
const store = useStore<State>()
|
||||||
const activeElementIdList = computed(() => store.state.activeElementIdList)
|
const activeElementIdList = computed(() => store.state.activeElementIdList)
|
||||||
const currentSlide: Ref<Slide> = computed(() => store.getters.currentSlide)
|
const currentSlide: Ref<Slide> = computed(() => store.getters.currentSlide)
|
||||||
|
|
||||||
|
const { addHistorySnapshot } = useHistorySnapshot()
|
||||||
|
|
||||||
const deleteElement = () => {
|
const deleteElement = () => {
|
||||||
if(!activeElementIdList.value.length) return
|
if(!activeElementIdList.value.length) return
|
||||||
const newElementList = currentSlide.value.elements.filter(el => !activeElementIdList.value.includes(el.elId))
|
const newElementList = currentSlide.value.elements.filter(el => !activeElementIdList.value.includes(el.elId))
|
||||||
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])
|
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])
|
||||||
store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })
|
store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })
|
||||||
|
addHistorySnapshot()
|
||||||
}
|
}
|
||||||
|
|
||||||
const deleteAllElements = () => {
|
const deleteAllElements = () => {
|
||||||
if(!currentSlide.value.elements.length) return
|
if(!currentSlide.value.elements.length) return
|
||||||
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])
|
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])
|
||||||
store.commit(MutationTypes.UPDATE_SLIDE, { elements: [] })
|
store.commit(MutationTypes.UPDATE_SLIDE, { elements: [] })
|
||||||
|
addHistorySnapshot()
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -1,10 +1,15 @@
|
|||||||
import { useStore } from 'vuex'
|
import { useStore } from 'vuex'
|
||||||
|
import debounce from 'lodash/debounce'
|
||||||
import throttle from 'lodash/throttle'
|
import throttle from 'lodash/throttle'
|
||||||
import { State, ActionTypes } from '@/store'
|
import { State, ActionTypes } from '@/store'
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
const store = useStore<State>()
|
const store = useStore<State>()
|
||||||
|
|
||||||
|
const addHistorySnapshot = debounce(function() {
|
||||||
|
store.dispatch(ActionTypes.ADD_SNAPSHOT)
|
||||||
|
}, 300, { trailing: true })
|
||||||
|
|
||||||
const redo = throttle(function() {
|
const redo = throttle(function() {
|
||||||
store.dispatch(ActionTypes.RE_DO)
|
store.dispatch(ActionTypes.RE_DO)
|
||||||
}, 100, { leading: true, trailing: false })
|
}, 100, { leading: true, trailing: false })
|
||||||
@ -14,6 +19,7 @@ export default () => {
|
|||||||
}, 100, { leading: true, trailing: false })
|
}, 100, { leading: true, trailing: false })
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
addHistorySnapshot,
|
||||||
redo,
|
redo,
|
||||||
undo,
|
undo,
|
||||||
}
|
}
|
@ -2,12 +2,15 @@ import { useStore } from 'vuex'
|
|||||||
import { Ref, computed } from 'vue'
|
import { Ref, computed } from 'vue'
|
||||||
import { State, MutationTypes } from '@/store'
|
import { State, MutationTypes } from '@/store'
|
||||||
import { PPTElement, Slide } from '@/types/slides'
|
import { PPTElement, Slide } from '@/types/slides'
|
||||||
|
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
const store = useStore<State>()
|
const store = useStore<State>()
|
||||||
const activeElementIdList = computed(() => store.state.activeElementIdList)
|
const activeElementIdList = computed(() => store.state.activeElementIdList)
|
||||||
const currentSlide: Ref<Slide> = computed(() => store.getters.currentSlide)
|
const currentSlide: Ref<Slide> = computed(() => store.getters.currentSlide)
|
||||||
|
|
||||||
|
const { addHistorySnapshot } = useHistorySnapshot()
|
||||||
|
|
||||||
const lockElement = () => {
|
const lockElement = () => {
|
||||||
const newElementList: PPTElement[] = JSON.parse(JSON.stringify(currentSlide.value.elements))
|
const newElementList: PPTElement[] = JSON.parse(JSON.stringify(currentSlide.value.elements))
|
||||||
|
|
||||||
@ -15,6 +18,7 @@ export default () => {
|
|||||||
if(activeElementIdList.value.includes(element.elId)) element.isLock = true
|
if(activeElementIdList.value.includes(element.elId)) element.isLock = true
|
||||||
}
|
}
|
||||||
store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })
|
store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })
|
||||||
|
addHistorySnapshot()
|
||||||
}
|
}
|
||||||
|
|
||||||
const unlockElement = (handleElement: PPTElement) => {
|
const unlockElement = (handleElement: PPTElement) => {
|
||||||
@ -34,6 +38,7 @@ export default () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })
|
store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })
|
||||||
|
addHistorySnapshot()
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -3,12 +3,15 @@ import { useStore } from 'vuex'
|
|||||||
import { State, MutationTypes } from '@/store'
|
import { State, MutationTypes } from '@/store'
|
||||||
import { Slide } from '@/types/slides'
|
import { Slide } from '@/types/slides'
|
||||||
import { KEYS } from '@/configs/hotkey'
|
import { KEYS } from '@/configs/hotkey'
|
||||||
|
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
const store = useStore<State>()
|
const store = useStore<State>()
|
||||||
const activeElementIdList = computed(() => store.state.activeElementIdList)
|
const activeElementIdList = computed(() => store.state.activeElementIdList)
|
||||||
const currentSlide: Ref<Slide> = computed(() => store.getters.currentSlide)
|
const currentSlide: Ref<Slide> = computed(() => store.getters.currentSlide)
|
||||||
|
|
||||||
|
const { addHistorySnapshot } = useHistorySnapshot()
|
||||||
|
|
||||||
const moveElement = (command: string) => {
|
const moveElement = (command: string) => {
|
||||||
const newElementList = currentSlide.value.elements.map(el => {
|
const newElementList = currentSlide.value.elements.map(el => {
|
||||||
if(activeElementIdList.value.includes(el.elId)) {
|
if(activeElementIdList.value.includes(el.elId)) {
|
||||||
@ -33,6 +36,7 @@ export default () => {
|
|||||||
return el
|
return el
|
||||||
})
|
})
|
||||||
store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })
|
store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })
|
||||||
|
addHistorySnapshot()
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -3,11 +3,14 @@ import { useStore } from 'vuex'
|
|||||||
import { State, MutationTypes } from '@/store'
|
import { State, MutationTypes } from '@/store'
|
||||||
import { PPTElement, Slide } from '@/types/slides'
|
import { PPTElement, Slide } from '@/types/slides'
|
||||||
import { ElementOrderCommand, ElementOrderCommands } from '@/types/edit'
|
import { ElementOrderCommand, ElementOrderCommands } from '@/types/edit'
|
||||||
|
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
const store = useStore<State>()
|
const store = useStore<State>()
|
||||||
const currentSlide: Ref<Slide> = computed(() => store.getters.currentSlide)
|
const currentSlide: Ref<Slide> = computed(() => store.getters.currentSlide)
|
||||||
|
|
||||||
|
const { addHistorySnapshot } = useHistorySnapshot()
|
||||||
|
|
||||||
// 获取组合元素层级范围(组合成员中的最大层级和最小层级)
|
// 获取组合元素层级范围(组合成员中的最大层级和最小层级)
|
||||||
const getCombineElementIndexRange = (elementList: PPTElement[], combineElementList: PPTElement[]) => {
|
const getCombineElementIndexRange = (elementList: PPTElement[], combineElementList: PPTElement[]) => {
|
||||||
const minIndex = elementList.findIndex(_element => _element.elId === combineElementList[0].elId)
|
const minIndex = elementList.findIndex(_element => _element.elId === combineElementList[0].elId)
|
||||||
@ -174,6 +177,7 @@ export default () => {
|
|||||||
else if(command === ElementOrderCommands.BOTTOM) newElementList = moveBottomElement(currentSlide.value.elements, element)
|
else if(command === ElementOrderCommands.BOTTOM) newElementList = moveBottomElement(currentSlide.value.elements, element)
|
||||||
|
|
||||||
store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })
|
store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })
|
||||||
|
addHistorySnapshot()
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -4,6 +4,7 @@ import { MutationTypes, State } from '@/store'
|
|||||||
import { decrypt } from '@/utils/crypto'
|
import { decrypt } from '@/utils/crypto'
|
||||||
import { PPTElement, Slide } from '@/types/slides'
|
import { PPTElement, Slide } from '@/types/slides'
|
||||||
import { createRandomCode } from '@/utils/common'
|
import { createRandomCode } from '@/utils/common'
|
||||||
|
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
|
||||||
|
|
||||||
interface PasteTextClipboardDataOptions {
|
interface PasteTextClipboardDataOptions {
|
||||||
onlySlide?: boolean;
|
onlySlide?: boolean;
|
||||||
@ -14,6 +15,8 @@ export default () => {
|
|||||||
const store = useStore<State>()
|
const store = useStore<State>()
|
||||||
const currentSlide: Ref<Slide> = computed(() => store.getters.currentSlide)
|
const currentSlide: Ref<Slide> = computed(() => store.getters.currentSlide)
|
||||||
|
|
||||||
|
const { addHistorySnapshot } = useHistorySnapshot()
|
||||||
|
|
||||||
const pasteElement = (elements: PPTElement[]) => {
|
const pasteElement = (elements: PPTElement[]) => {
|
||||||
const groupIdMap = {}
|
const groupIdMap = {}
|
||||||
const elIdMap = {}
|
const elIdMap = {}
|
||||||
@ -40,10 +43,12 @@ export default () => {
|
|||||||
}
|
}
|
||||||
store.commit(MutationTypes.ADD_ELEMENT, elements)
|
store.commit(MutationTypes.ADD_ELEMENT, elements)
|
||||||
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, Object.values(elIdMap))
|
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, Object.values(elIdMap))
|
||||||
|
addHistorySnapshot()
|
||||||
}
|
}
|
||||||
|
|
||||||
const pasteSlide = (slide: Slide) => {
|
const pasteSlide = (slide: Slide) => {
|
||||||
store.commit(MutationTypes.ADD_SLIDE, slide)
|
store.commit(MutationTypes.ADD_SLIDE, slide)
|
||||||
|
addHistorySnapshot()
|
||||||
}
|
}
|
||||||
|
|
||||||
const pasteText = (text: string) => {
|
const pasteText = (text: string) => {
|
||||||
|
@ -8,6 +8,7 @@ import { encrypt } from '@/utils/crypto'
|
|||||||
import { KEYS } from '@/configs/hotkey'
|
import { KEYS } from '@/configs/hotkey'
|
||||||
import { message } from 'ant-design-vue'
|
import { message } from 'ant-design-vue'
|
||||||
import usePasteTextClipboardData from '@/hooks/usePasteTextClipboardData'
|
import usePasteTextClipboardData from '@/hooks/usePasteTextClipboardData'
|
||||||
|
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
const store = useStore<State>()
|
const store = useStore<State>()
|
||||||
@ -16,6 +17,7 @@ export default () => {
|
|||||||
const currentSlide: Ref<Slide> = computed(() => store.getters.currentSlide)
|
const currentSlide: Ref<Slide> = computed(() => store.getters.currentSlide)
|
||||||
|
|
||||||
const { pasteTextClipboardData } = usePasteTextClipboardData()
|
const { pasteTextClipboardData } = usePasteTextClipboardData()
|
||||||
|
const { addHistorySnapshot } = useHistorySnapshot()
|
||||||
|
|
||||||
const updateSlideIndex = (command: string) => {
|
const updateSlideIndex = (command: string) => {
|
||||||
let targetIndex = 0
|
let targetIndex = 0
|
||||||
@ -51,14 +53,17 @@ export default () => {
|
|||||||
elements: [],
|
elements: [],
|
||||||
}
|
}
|
||||||
store.commit(MutationTypes.ADD_SLIDE, emptySlide)
|
store.commit(MutationTypes.ADD_SLIDE, emptySlide)
|
||||||
|
addHistorySnapshot()
|
||||||
}
|
}
|
||||||
|
|
||||||
const copyAndPasteSlide = () => {
|
const copyAndPasteSlide = () => {
|
||||||
store.commit(MutationTypes.ADD_SLIDE, currentSlide.value)
|
store.commit(MutationTypes.ADD_SLIDE, currentSlide.value)
|
||||||
|
addHistorySnapshot()
|
||||||
}
|
}
|
||||||
|
|
||||||
const deleteSlide = () => {
|
const deleteSlide = () => {
|
||||||
store.commit(MutationTypes.DELETE_SLIDE, currentSlide.value.id)
|
store.commit(MutationTypes.DELETE_SLIDE, currentSlide.value.id)
|
||||||
|
addHistorySnapshot()
|
||||||
}
|
}
|
||||||
|
|
||||||
const cutSlide = () => {
|
const cutSlide = () => {
|
||||||
|
@ -5,14 +5,22 @@ import { ActionTypes, MutationTypes } from './constants'
|
|||||||
import db, { Snapshot } from '@/utils/database'
|
import db, { Snapshot } from '@/utils/database'
|
||||||
|
|
||||||
export const actions: ActionTree<State, State> = {
|
export const actions: ActionTree<State, State> = {
|
||||||
async [ActionTypes.INIT_SNAPSHOT_DATABASE]({ commit }) {
|
async [ActionTypes.INIT_SNAPSHOT_DATABASE]({ commit, state }) {
|
||||||
const snapshots: Snapshot[] = await db.snapshots.orderBy('id').toArray()
|
const snapshots: Snapshot[] = await db.snapshots.orderBy('id').toArray()
|
||||||
const snapshot = snapshots.slice(-1)[0]
|
const lastSnapshot = snapshots.slice(-1)[0]
|
||||||
|
|
||||||
if(snapshot) {
|
if(lastSnapshot) {
|
||||||
db.snapshots.clear()
|
db.snapshots.clear()
|
||||||
commit(MutationTypes.SET_SLIDES, snapshot.slides)
|
// commit(MutationTypes.SET_SLIDES, lastSnapshot.slides)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const newFirstSnapshot = {
|
||||||
|
index: state.slideIndex,
|
||||||
|
slides: state.slides,
|
||||||
|
}
|
||||||
|
await db.snapshots.add(newFirstSnapshot)
|
||||||
|
commit(MutationTypes.SET_SNAPSHOT_CURSOR, 0)
|
||||||
|
commit(MutationTypes.SET_SNAPSHOT_LENGTH, 1)
|
||||||
},
|
},
|
||||||
|
|
||||||
async [ActionTypes.ADD_SNAPSHOT]({ state, commit }) {
|
async [ActionTypes.ADD_SNAPSHOT]({ state, commit }) {
|
||||||
@ -44,7 +52,7 @@ export const actions: ActionTree<State, State> = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
async [ActionTypes.UN_DO]({ state, commit }) {
|
async [ActionTypes.UN_DO]({ state, commit }) {
|
||||||
if(state.snapshotCursor > 0) return
|
if(state.snapshotCursor <= 0) return
|
||||||
|
|
||||||
const snapshotCursor = state.snapshotCursor - 1
|
const snapshotCursor = state.snapshotCursor - 1
|
||||||
const snapshots: Snapshot[] = await db.snapshots.orderBy('id').toArray()
|
const snapshots: Snapshot[] = await db.snapshots.orderBy('id').toArray()
|
||||||
@ -58,7 +66,7 @@ export const actions: ActionTree<State, State> = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
async [ActionTypes.RE_DO]({ state, commit }) {
|
async [ActionTypes.RE_DO]({ state, commit }) {
|
||||||
if(state.snapshotCursor < state.snapshotLength - 1) return
|
if(state.snapshotCursor >= state.snapshotLength - 1) return
|
||||||
|
|
||||||
const snapshotCursor = state.snapshotCursor + 1
|
const snapshotCursor = state.snapshotCursor + 1
|
||||||
const snapshots: Snapshot[] = await db.snapshots.orderBy('id').toArray()
|
const snapshots: Snapshot[] = await db.snapshots.orderBy('id').toArray()
|
||||||
|
@ -5,6 +5,7 @@ import { ElementTypes, PPTElement } from '@/types/slides'
|
|||||||
import { AlignmentLineProps } from '@/types/edit'
|
import { AlignmentLineProps } from '@/types/edit'
|
||||||
import { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'
|
import { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'
|
||||||
import { getRectRotatedRange, AlignLine, uniqAlignLines } from '@/utils/element'
|
import { getRectRotatedRange, AlignLine, uniqAlignLines } from '@/utils/element'
|
||||||
|
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
|
||||||
|
|
||||||
export default (
|
export default (
|
||||||
elementList: Ref<PPTElement[]>,
|
elementList: Ref<PPTElement[]>,
|
||||||
@ -15,6 +16,8 @@ export default (
|
|||||||
const activeElementIdList = computed(() => store.state.activeElementIdList)
|
const activeElementIdList = computed(() => store.state.activeElementIdList)
|
||||||
const canvasScale = computed(() => store.state.canvasScale)
|
const canvasScale = computed(() => store.state.canvasScale)
|
||||||
|
|
||||||
|
const { addHistorySnapshot } = useHistorySnapshot()
|
||||||
|
|
||||||
const dragElement = (e: MouseEvent, element: PPTElement) => {
|
const dragElement = (e: MouseEvent, element: PPTElement) => {
|
||||||
if(!activeElementIdList.value.includes(element.elId)) return
|
if(!activeElementIdList.value.includes(element.elId)) return
|
||||||
let isMouseDown = true
|
let isMouseDown = true
|
||||||
@ -305,6 +308,7 @@ export default (
|
|||||||
if(startPageX === currentPageX && startPageY === currentPageY) return
|
if(startPageX === currentPageX && startPageY === currentPageY) return
|
||||||
|
|
||||||
store.commit(MutationTypes.UPDATE_SLIDE, { elements: elementList.value })
|
store.commit(MutationTypes.UPDATE_SLIDE, { elements: elementList.value })
|
||||||
|
addHistorySnapshot()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,11 +2,12 @@ import { Ref, computed } from 'vue'
|
|||||||
import { useStore } from 'vuex'
|
import { useStore } from 'vuex'
|
||||||
import { State, MutationTypes } from '@/store'
|
import { State, MutationTypes } from '@/store'
|
||||||
import { PPTElement, PPTTextElement, PPTImageElement, PPTShapeElement } from '@/types/slides'
|
import { PPTElement, PPTTextElement, PPTImageElement, PPTShapeElement } from '@/types/slides'
|
||||||
|
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
|
||||||
|
|
||||||
// 给定一个坐标,计算该坐标到(0, 0)点连线的弧度值
|
// 给定一个坐标,计算该坐标到(0, 0)点连线的弧度值
|
||||||
// 注意,Math.atan2的一般用法是Math.atan2(y, x)返回的是原点(0,0)到(x,y)点的线段与X轴正方向之间的弧度值
|
// 注意,Math.atan2的一般用法是Math.atan2(y, x)返回的是原点(0,0)到(x,y)点的线段与X轴正方向之间的弧度值
|
||||||
// 这里将使用时将x与y的传入顺序交换了,为的是获取原点(0,0)到(x,y)点的线段与Y轴正方向之间的弧度值
|
// 这里将使用时将x与y的传入顺序交换了,为的是获取原点(0,0)到(x,y)点的线段与Y轴正方向之间的弧度值
|
||||||
export const getAngleFromCoordinate = (x: number, y: number) => {
|
const getAngleFromCoordinate = (x: number, y: number) => {
|
||||||
const radian = Math.atan2(x, y)
|
const radian = Math.atan2(x, y)
|
||||||
const angle = 180 / Math.PI * radian
|
const angle = 180 / Math.PI * radian
|
||||||
return angle
|
return angle
|
||||||
@ -16,6 +17,8 @@ export default (elementList: Ref<PPTElement[]>, viewportRef: Ref<HTMLElement | n
|
|||||||
const store = useStore<State>()
|
const store = useStore<State>()
|
||||||
const canvasScale = computed(() => store.state.canvasScale)
|
const canvasScale = computed(() => store.state.canvasScale)
|
||||||
|
|
||||||
|
const { addHistorySnapshot } = useHistorySnapshot()
|
||||||
|
|
||||||
const rotateElement = (element: PPTTextElement | PPTImageElement | PPTShapeElement) => {
|
const rotateElement = (element: PPTTextElement | PPTImageElement | PPTShapeElement) => {
|
||||||
let isMouseDown = true
|
let isMouseDown = true
|
||||||
let angle = 0
|
let angle = 0
|
||||||
@ -67,6 +70,7 @@ export default (elementList: Ref<PPTElement[]>, viewportRef: Ref<HTMLElement | n
|
|||||||
if(elOriginRotate === angle) return
|
if(elOriginRotate === angle) return
|
||||||
|
|
||||||
store.commit(MutationTypes.UPDATE_SLIDE, { elements: elementList.value })
|
store.commit(MutationTypes.UPDATE_SLIDE, { elements: elementList.value })
|
||||||
|
addHistorySnapshot()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import { ElementTypes, PPTElement, PPTImageElement, PPTLineElement, PPTShapeElem
|
|||||||
import { OperatePoints, ElementScaleHandler, AlignmentLineProps, MultiSelectRange } from '@/types/edit'
|
import { OperatePoints, ElementScaleHandler, AlignmentLineProps, MultiSelectRange } from '@/types/edit'
|
||||||
import { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'
|
import { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'
|
||||||
import { AlignLine, uniqAlignLines } from '@/utils/element'
|
import { AlignLine, uniqAlignLines } from '@/utils/element'
|
||||||
|
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
|
||||||
|
|
||||||
// 计算元素被旋转一定角度后,八个操作点的新坐标
|
// 计算元素被旋转一定角度后,八个操作点的新坐标
|
||||||
interface RotateElementData {
|
interface RotateElementData {
|
||||||
@ -13,7 +14,7 @@ interface RotateElementData {
|
|||||||
width: number;
|
width: number;
|
||||||
height: number;
|
height: number;
|
||||||
}
|
}
|
||||||
export const getRotateElementPoints = (element: RotateElementData, angle: number) => {
|
const getRotateElementPoints = (element: RotateElementData, angle: number) => {
|
||||||
const { left, top, width, height } = element
|
const { left, top, width, height } = element
|
||||||
|
|
||||||
const radius = Math.sqrt( Math.pow(width, 2) + Math.pow(height, 2) ) / 2
|
const radius = Math.sqrt( Math.pow(width, 2) + Math.pow(height, 2) ) / 2
|
||||||
@ -67,7 +68,7 @@ export const getRotateElementPoints = (element: RotateElementData, angle: number
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 获取元素某个操作点对角线上另一端的操作点坐标(例如:左上 <-> 右下)
|
// 获取元素某个操作点对角线上另一端的操作点坐标(例如:左上 <-> 右下)
|
||||||
export const getOppositePoint = (direction: number, points: ReturnType<typeof getRotateElementPoints>): { left: number; top: number } => {
|
const getOppositePoint = (direction: number, points: ReturnType<typeof getRotateElementPoints>): { left: number; top: number } => {
|
||||||
const oppositeMap = {
|
const oppositeMap = {
|
||||||
[OperatePoints.RIGHT_BOTTOM]: points.leftTopPoint,
|
[OperatePoints.RIGHT_BOTTOM]: points.leftTopPoint,
|
||||||
[OperatePoints.LEFT_BOTTOM]: points.rightTopPoint,
|
[OperatePoints.LEFT_BOTTOM]: points.rightTopPoint,
|
||||||
@ -91,6 +92,8 @@ export default (
|
|||||||
const ctrlOrShiftKeyActive: Ref<boolean> = computed(() => store.getters.ctrlOrShiftKeyActive)
|
const ctrlOrShiftKeyActive: Ref<boolean> = computed(() => store.getters.ctrlOrShiftKeyActive)
|
||||||
const canvasScale = computed(() => store.state.canvasScale)
|
const canvasScale = computed(() => store.state.canvasScale)
|
||||||
|
|
||||||
|
const { addHistorySnapshot } = useHistorySnapshot()
|
||||||
|
|
||||||
const scaleElement = (e: MouseEvent, element: Exclude<PPTElement, PPTLineElement>, command: ElementScaleHandler) => {
|
const scaleElement = (e: MouseEvent, element: Exclude<PPTElement, PPTLineElement>, command: ElementScaleHandler) => {
|
||||||
let isMouseDown = true
|
let isMouseDown = true
|
||||||
|
|
||||||
@ -383,6 +386,7 @@ export default (
|
|||||||
if(startPageX === e.pageX && startPageY === e.pageY) return
|
if(startPageX === e.pageX && startPageY === e.pageY) return
|
||||||
|
|
||||||
store.commit(MutationTypes.UPDATE_SLIDE, { elements: elementList.value })
|
store.commit(MutationTypes.UPDATE_SLIDE, { elements: elementList.value })
|
||||||
|
addHistorySnapshot()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -486,6 +490,7 @@ export default (
|
|||||||
if(startPageX === e.pageX && startPageY === e.pageY) return
|
if(startPageX === e.pageX && startPageY === e.pageY) return
|
||||||
|
|
||||||
store.commit(MutationTypes.UPDATE_SLIDE, { elements: elementList.value })
|
store.commit(MutationTypes.UPDATE_SLIDE, { elements: elementList.value })
|
||||||
|
addHistorySnapshot()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="canvas-tool">
|
<div class="canvas-tool">
|
||||||
<div class="left-handler">
|
<div class="left-handler">
|
||||||
<IconFont class="handler-item" type="icon-undo" />
|
<IconFont class="handler-item" :class="{ 'disable': !canUndo }" type="icon-undo" @click="undo()" />
|
||||||
<IconFont class="handler-item" type="icon-redo" />
|
<IconFont class="handler-item" :class="{ 'disable': !canRedo }" type="icon-redo" @click="redo()" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="add-element-handler">
|
<div class="add-element-handler">
|
||||||
@ -28,6 +28,7 @@ import { defineComponent, computed } from 'vue'
|
|||||||
import { useStore } from 'vuex'
|
import { useStore } from 'vuex'
|
||||||
import { MutationTypes, State } from '@/store'
|
import { MutationTypes, State } from '@/store'
|
||||||
import useScaleCanvas from '@/hooks/useScaleCanvas'
|
import useScaleCanvas from '@/hooks/useScaleCanvas'
|
||||||
|
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'canvas-tool',
|
name: 'canvas-tool',
|
||||||
@ -35,10 +36,13 @@ export default defineComponent({
|
|||||||
const store = useStore<State>()
|
const store = useStore<State>()
|
||||||
const canvasScale = computed(() => store.state.canvasScale)
|
const canvasScale = computed(() => store.state.canvasScale)
|
||||||
const showGridLines = computed(() => store.state.showGridLines)
|
const showGridLines = computed(() => store.state.showGridLines)
|
||||||
|
const canUndo = computed(() => store.getters.canUndo)
|
||||||
|
const canRedo = computed(() => store.getters.canRedo)
|
||||||
|
|
||||||
const canvasScalePercentage = computed(() => parseInt(canvasScale.value * 100 + '') + '%')
|
const canvasScalePercentage = computed(() => parseInt(canvasScale.value * 100 + '') + '%')
|
||||||
|
|
||||||
const { scaleCanvas } = useScaleCanvas()
|
const { scaleCanvas } = useScaleCanvas()
|
||||||
|
const { redo, undo } = useHistorySnapshot()
|
||||||
|
|
||||||
const toggleGridLines = () => {
|
const toggleGridLines = () => {
|
||||||
store.commit(MutationTypes.SET_GRID_LINES_STATE, !showGridLines.value)
|
store.commit(MutationTypes.SET_GRID_LINES_STATE, !showGridLines.value)
|
||||||
@ -48,6 +52,10 @@ export default defineComponent({
|
|||||||
scaleCanvas,
|
scaleCanvas,
|
||||||
canvasScalePercentage,
|
canvasScalePercentage,
|
||||||
toggleGridLines,
|
toggleGridLines,
|
||||||
|
canUndo,
|
||||||
|
canRedo,
|
||||||
|
redo,
|
||||||
|
undo,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -77,6 +85,10 @@ export default defineComponent({
|
|||||||
.handler-item {
|
.handler-item {
|
||||||
margin: 0 10px;
|
margin: 0 10px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
|
&.disable {
|
||||||
|
opacity: .5;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.right-handler {
|
.right-handler {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -2,7 +2,6 @@ import { computed, onMounted, onUnmounted } from 'vue'
|
|||||||
import { useStore } from 'vuex'
|
import { useStore } from 'vuex'
|
||||||
import { State, MutationTypes } from '@/store'
|
import { State, MutationTypes } from '@/store'
|
||||||
import { KEYS } from '@/configs/hotkey'
|
import { KEYS } from '@/configs/hotkey'
|
||||||
import { message } from 'ant-design-vue'
|
|
||||||
|
|
||||||
import useSlideHandler from '@/hooks/useSlideHandler'
|
import useSlideHandler from '@/hooks/useSlideHandler'
|
||||||
import useLockElement from '@/hooks/useLockElement'
|
import useLockElement from '@/hooks/useLockElement'
|
||||||
@ -11,6 +10,7 @@ import useCombineElement from '@/hooks/useCombineElement'
|
|||||||
import useCopyAndPasteElement from '@/hooks/useCopyAndPasteElement'
|
import useCopyAndPasteElement from '@/hooks/useCopyAndPasteElement'
|
||||||
import useSelectAllElement from '@/hooks/useSelectAllElement'
|
import useSelectAllElement from '@/hooks/useSelectAllElement'
|
||||||
import useMoveElement from '@/hooks/useMoveElement'
|
import useMoveElement from '@/hooks/useMoveElement'
|
||||||
|
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
const store = useStore<State>()
|
const store = useStore<State>()
|
||||||
@ -37,6 +37,7 @@ export default () => {
|
|||||||
const { copyElement, cutElement } = useCopyAndPasteElement()
|
const { copyElement, cutElement } = useCopyAndPasteElement()
|
||||||
const { selectAllElement } = useSelectAllElement()
|
const { selectAllElement } = useSelectAllElement()
|
||||||
const { moveElement } = useMoveElement()
|
const { moveElement } = useMoveElement()
|
||||||
|
const { redo, undo } = useHistorySnapshot()
|
||||||
|
|
||||||
const copy = () => {
|
const copy = () => {
|
||||||
if(disableHotkeys.value) return
|
if(disableHotkeys.value) return
|
||||||
@ -50,14 +51,6 @@ export default () => {
|
|||||||
else if(activeElementIdList.value.length) cutElement()
|
else if(activeElementIdList.value.length) cutElement()
|
||||||
}
|
}
|
||||||
|
|
||||||
const undo = () => {
|
|
||||||
message.success('undo')
|
|
||||||
}
|
|
||||||
|
|
||||||
const redo = () => {
|
|
||||||
message.success('redo')
|
|
||||||
}
|
|
||||||
|
|
||||||
const selectAll = () => {
|
const selectAll = () => {
|
||||||
if(!editorAreaFocus.value && disableHotkeys.value) return
|
if(!editorAreaFocus.value && disableHotkeys.value) return
|
||||||
selectAllElement()
|
selectAllElement()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user