refactor: 使用pinia代替vuex

This commit is contained in:
pipipi-pikachu 2021-11-26 17:11:54 +08:00
parent 16f5646023
commit 54dfccd643
98 changed files with 1243 additions and 1259 deletions

View File

@ -1,6 +0,0 @@
module.exports = {
preset: '@vue/cli-plugin-unit-jest/presets/typescript-and-babel',
transform: {
'^.+\\.vue$': 'vue-jest',
},
}

View File

@ -21,6 +21,7 @@
"hfmath": "0.0.2",
"lodash": "^4.17.20",
"mitt": "^3.0.0",
"pinia": "^2.0.4",
"pptxgenjs": "^3.7.1",
"prosemirror-commands": "^1.1.7",
"prosemirror-dropcursor": "^1.3.2",
@ -36,8 +37,7 @@
"svg-pathdata": "^6.0.0",
"tinycolor2": "^1.4.2",
"vue": "^3.2.22",
"vuedraggable": "^4.0.1",
"vuex": "^4.0.2"
"vuedraggable": "^4.0.1"
},
"devDependencies": {
"@commitlint/cli": "^12.0.0",

View File

@ -4,8 +4,9 @@
</template>
<script lang="ts">
import { computed, defineComponent, onMounted } from 'vue'
import { MutationTypes, ActionTypes, useStore } from '@/store'
import { defineComponent, onMounted } from 'vue'
import { storeToRefs } from 'pinia'
import { useScreenStore, useMainStore, useSnapshotStore } from '@/store'
import Editor from './views/Editor/index.vue'
import Screen from './views/Screen/index.vue'
@ -17,16 +18,17 @@ export default defineComponent({
Screen,
},
setup() {
const store = useStore()
const screening = computed(() => store.state.screening)
const mainStore = useMainStore()
const snapshotStore = useSnapshotStore()
const { screening } = storeToRefs(useScreenStore())
if (process.env.NODE_ENV === 'production') {
window.onbeforeunload = () => false
}
onMounted(() => {
store.commit(MutationTypes.SET_AVAILABLE_FONTS)
store.dispatch(ActionTypes.INIT_SNAPSHOT_DATABASE)
snapshotStore.initSnapshotDatabase()
mainStore.setAvailableFonts()
})
return {

View File

@ -1,16 +1,14 @@
import { computed } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { PPTElement, Slide } from '@/types/slides'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store'
import { PPTElement } from '@/types/slides'
import { ElementAlignCommand, ElementAlignCommands } from '@/types/edit'
import { getElementListRange, getRectRotatedOffset } from '@/utils/element'
import useHistorySnapshot from './useHistorySnapshot'
export default () => {
const store = useStore()
const activeElementIdList = computed(() => store.state.activeElementIdList)
const activeElementList = computed<PPTElement[]>(() => store.getters.activeElementList)
const currentSlide = computed<Slide>(() => store.getters.currentSlide)
const slidesStore = useSlidesStore()
const { activeElementIdList, activeElementList } = storeToRefs(useMainStore())
const { currentSlide } = storeToRefs(slidesStore)
const { addHistorySnapshot } = useHistorySnapshot()
@ -164,8 +162,8 @@ export default () => {
}
})
}
store.commit(MutationTypes.UPDATE_SLIDE, { elements: elementList })
slidesStore.updateSlide({ elements: elementList })
addHistorySnapshot()
}

View File

@ -1,18 +1,15 @@
import { computed } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { PPTElement, Slide } from '@/types/slides'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store'
import { PPTElement } from '@/types/slides'
import { ElementAlignCommand, ElementAlignCommands } from '@/types/edit'
import { getElementListRange } from '@/utils/element'
import { VIEWPORT_SIZE } from '@/configs/canvas'
import useHistorySnapshot from './useHistorySnapshot'
export default () => {
const store = useStore()
const activeElementIdList = computed(() => store.state.activeElementIdList)
const viewportRatio = computed(() => store.state.viewportRatio)
const activeElementList = computed<PPTElement[]>(() => store.getters.activeElementList)
const currentSlide = computed<Slide>(() => store.getters.currentSlide)
const slidesStore = useSlidesStore()
const { activeElementIdList, activeElementList } = storeToRefs(useMainStore())
const { currentSlide, viewportRatio } = storeToRefs(slidesStore)
const { addHistorySnapshot } = useHistorySnapshot()
@ -73,8 +70,8 @@ export default () => {
element.left = element.left - offsetX
}
}
store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })
slidesStore.updateSlide({ elements: newElementList })
addHistorySnapshot()
}

View File

@ -1,15 +1,15 @@
import { computed } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { PPTElement, Slide } from '@/types/slides'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store'
import { PPTElement } from '@/types/slides'
import { createRandomCode } from '@/utils/common'
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
export default () => {
const store = useStore()
const activeElementIdList = computed(() => store.state.activeElementIdList)
const activeElementList = computed<PPTElement[]>(() => store.getters.activeElementList)
const currentSlide = computed<Slide>(() => store.getters.currentSlide)
const handleElementId = computed(() => store.state.handleElementId)
const mainStore = useMainStore()
const slidesStore = useSlidesStore()
const { activeElementIdList, activeElementList, handleElementId } = storeToRefs(mainStore)
const { currentSlide } = storeToRefs(slidesStore)
const { addHistorySnapshot } = useHistorySnapshot()
@ -57,7 +57,7 @@ export default () => {
const insertLevel = combineElementMaxLevel - combineElementList.length + 1
newElementList.splice(insertLevel, 0, ...combineElementList)
store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })
slidesStore.updateSlide({ elements: newElementList })
addHistorySnapshot()
}
@ -73,12 +73,13 @@ export default () => {
for (const element of newElementList) {
if (activeElementIdList.value.includes(element.id) && element.groupId) delete element.groupId
}
store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })
slidesStore.updateSlide({ elements: newElementList })
// 取消组合后,需要重置激活元素状态
// 默认重置为当前正在操作的元素,如果不存在则重置为空
const handleElementIdList = handleElementId.value ? [handleElementId.value] : []
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, handleElementIdList)
mainStore.setActiveElementIdList(handleElementIdList)
addHistorySnapshot()
}

View File

@ -1,6 +1,5 @@
import { computed } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { PPTElement } from '@/types/slides'
import { storeToRefs } from 'pinia'
import { useMainStore } from '@/store'
import { copyText, readClipboard } from '@/utils/clipboard'
import { encrypt } from '@/utils/crypto'
import { message } from 'ant-design-vue'
@ -8,9 +7,8 @@ import usePasteTextClipboardData from '@/hooks/usePasteTextClipboardData'
import useDeleteElement from './useDeleteElement'
export default () => {
const store = useStore()
const activeElementIdList = computed(() => store.state.activeElementIdList)
const activeElementList = computed<PPTElement[]>(() => store.getters.activeElementList)
const mainStore = useMainStore()
const { activeElementIdList, activeElementList } = storeToRefs(mainStore)
const { pasteTextClipboardData } = usePasteTextClipboardData()
const { deleteElement } = useDeleteElement()
@ -25,7 +23,7 @@ export default () => {
}))
copyText(text).then(() => {
store.commit(MutationTypes.SET_EDITORAREA_FOCUS, true)
mainStore.setEditorareaFocus(true)
})
}

View File

@ -1,5 +1,5 @@
import { computed } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store'
import { createRandomCode } from '@/utils/common'
import { getImageSize } from '@/utils/image'
import { VIEWPORT_SIZE } from '@/configs/canvas'
@ -23,24 +23,23 @@ interface LineElementPosition {
}
export default () => {
const store = useStore()
const themeColor = computed(() => store.state.theme.themeColor)
const fontColor = computed(() => store.state.theme.fontColor)
const fontName = computed(() => store.state.theme.fontName)
const viewportRatio = computed(() => store.state.viewportRatio)
const creatingElement = computed(() => store.state.creatingElement)
const mainStore = useMainStore()
const slidesStore = useSlidesStore()
const { creatingElement } = storeToRefs(mainStore)
const { theme, viewportRatio } = storeToRefs(slidesStore)
const { themeColor, fontColor, fontName } = theme.value
const { addHistorySnapshot } = useHistorySnapshot()
// 创建(插入)一个元素并将其设置为被选中元素
const createElement = (element: PPTElement) => {
store.commit(MutationTypes.ADD_ELEMENT, element)
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [element.id])
slidesStore.addElement(element)
mainStore.setActiveElementIdList([element.id])
if (creatingElement.value) store.commit(MutationTypes.SET_CREATING_ELEMENT, null)
if (creatingElement.value) mainStore.setCreatingElement(null)
setTimeout(() => {
store.commit(MutationTypes.SET_EDITORAREA_FOCUS, true)
mainStore.setEditorareaFocus(true)
}, 0)
addHistorySnapshot()
@ -91,8 +90,8 @@ export default () => {
width: 400,
height: 400,
rotate: 0,
themeColor: [themeColor.value],
gridColor: fontColor.value,
themeColor: [themeColor],
gridColor: fontColor,
data: {
labels: ['类别1', '类别2', '类别3', '类别4', '类别5'],
legends: ['系列1'],
@ -110,8 +109,8 @@ export default () => {
*/
const createTableElement = (row: number, col: number) => {
const style: TableCellStyle = {
fontname: fontName.value,
color: fontColor.value,
fontname: fontName,
color: fontColor,
}
const data: TableCell[][] = []
for (let i = 0; i < row; i++) {
@ -146,7 +145,7 @@ export default () => {
color: '#eeece1',
},
theme: {
color: themeColor.value,
color: themeColor,
rowHeader: true,
rowFooter: false,
colHeader: false,
@ -171,8 +170,8 @@ export default () => {
height,
content,
rotate: 0,
defaultFontName: fontName.value,
defaultColor: fontColor.value,
defaultFontName: fontName,
defaultColor: fontColor,
})
}
@ -192,7 +191,7 @@ export default () => {
height,
viewBox: data.viewBox,
path: data.path,
fill: themeColor.value,
fill: themeColor,
fixedRatio: false,
rotate: 0,
}
@ -216,7 +215,7 @@ export default () => {
start,
end,
points: data.points,
color: themeColor.value,
color: themeColor,
style: data.style,
width: 2,
}
@ -240,7 +239,7 @@ export default () => {
top: (VIEWPORT_SIZE * viewportRatio.value - data.h) / 2,
path: data.path,
latex: data.latex,
color: fontColor.value,
color: fontColor,
strokeWidth: 2,
viewBox: [data.w, data.h],
fixedRatio: true,

View File

@ -1,13 +1,13 @@
import { computed } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { PPTElement, Slide } from '@/types/slides'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store'
import { PPTElement } from '@/types/slides'
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
export default () => {
const store = useStore()
const activeElementIdList = computed(() => store.state.activeElementIdList)
const activeGroupElementId = computed(() => store.state.activeGroupElementId)
const currentSlide = computed<Slide>(() => store.getters.currentSlide)
const mainStore = useMainStore()
const slidesStore = useSlidesStore()
const { activeElementIdList, activeGroupElementId } = storeToRefs(mainStore)
const { currentSlide } = storeToRefs(slidesStore)
const { addHistorySnapshot } = useHistorySnapshot()
@ -24,16 +24,16 @@ export default () => {
newElementList = currentSlide.value.elements.filter(el => !activeElementIdList.value.includes(el.id))
}
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])
store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })
mainStore.setActiveElementIdList([])
slidesStore.updateSlide({ elements: newElementList })
addHistorySnapshot()
}
// 删除内面内全部元素(无论是否选中)
const deleteAllElements = () => {
if (!currentSlide.value.elements.length) return
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])
store.commit(MutationTypes.UPDATE_SLIDE, { elements: [] })
mainStore.setActiveElementIdList([])
slidesStore.updateSlide({ elements: [] })
addHistorySnapshot()
}

View File

@ -1,18 +1,18 @@
import { computed, ref } from 'vue'
import { ref } from 'vue'
import { storeToRefs } from 'pinia'
import { trim } from 'lodash'
import { saveAs } from 'file-saver'
import pptxgen from 'pptxgenjs'
import tinycolor from 'tinycolor2'
import { useSlidesStore } from '@/store'
import { getElementRange, getLineElementPath, getTableSubThemeColor } from '@/utils/element'
import { AST, toAST } from '@/utils/htmlParser'
import { SvgPoints, toPoints } from '@/utils/svgPathParser'
import { svg2Base64 } from '@/utils/svg2Base64'
import { useStore } from '@/store'
import { message } from 'ant-design-vue'
export default () => {
const store = useStore()
const slides = computed(() => store.state.slides)
const { slides } = storeToRefs(useSlidesStore())
const exporting = ref(false)

View File

@ -1,7 +1,7 @@
import { computed, onMounted, onUnmounted } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { onMounted, onUnmounted } from 'vue'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore, useKeyboardStore } from '@/store'
import { ElementOrderCommand, ElementOrderCommands } from '@/types/edit'
import { PPTElement, Slide } from '@/types/slides'
import { KEYS } from '@/configs/hotkey'
import useSlideHandler from './useSlideHandler'
@ -17,17 +17,18 @@ import useScreening from './useScreening'
import useScaleCanvas from './useScaleCanvas'
export default () => {
const store = useStore()
const ctrlKeyActive = computed(() => store.state.ctrlKeyState)
const shiftKeyActive = computed(() => store.state.shiftKeyState)
const disableHotkeys = computed(() => store.state.disableHotkeys)
const activeElementIdList = computed(() => store.state.activeElementIdList)
const handleElement = computed<PPTElement>(() => store.getters.handleElement)
const currentSlide = computed<Slide>(() => store.getters.currentSlide)
const editorAreaFocus = computed(() => store.state.editorAreaFocus)
const thumbnailsFocus = computed(() => store.state.thumbnailsFocus)
const mainStore = useMainStore()
const keyboardStore = useKeyboardStore()
const {
activeElementIdList,
disableHotkeys,
handleElement,
handleElementId,
editorAreaFocus,
thumbnailsFocus,
} = storeToRefs(mainStore)
const { currentSlide } = storeToRefs(useSlidesStore())
const { ctrlKeyState, shiftKeyState } = storeToRefs(keyboardStore)
const {
updateSlideIndex,
@ -106,17 +107,16 @@ export default () => {
const tabActiveElement = () => {
if (!currentSlide.value.elements.length) return
if (!handleElement.value) {
if (!handleElementId.value) {
const firstElement = currentSlide.value.elements[0]
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [firstElement.id])
mainStore.setActiveElementIdList([firstElement.id])
return
}
const currentIndex = currentSlide.value.elements.findIndex(el => el.id === handleElement.value.id)
const currentIndex = currentSlide.value.elements.findIndex(el => el.id === handleElementId.value)
const nextIndex = currentIndex >= currentSlide.value.elements.length - 1 ? 0 : currentIndex + 1
const nextElementId = currentSlide.value.elements[nextIndex].id
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [nextElementId])
mainStore.setActiveElementIdList([nextElementId])
}
const keydownListener = (e: KeyboardEvent) => {
@ -125,13 +125,13 @@ export default () => {
const key = e.key.toUpperCase()
if (ctrlOrMetaKeyActive && !ctrlKeyActive.value) store.commit(MutationTypes.SET_CTRL_KEY_STATE, true)
if (shiftKey && !shiftKeyActive.value) store.commit(MutationTypes.SET_SHIFT_KEY_STATE, true)
if (ctrlOrMetaKeyActive && !ctrlKeyState.value) keyboardStore.setCtrlKeyState(true)
if (shiftKey && !shiftKeyState.value) keyboardStore.setShiftKeyState(true)
if (ctrlOrMetaKeyActive && key === KEYS.F) {
e.preventDefault()
enterScreening()
store.commit(MutationTypes.SET_CTRL_KEY_STATE, false)
keyboardStore.setCtrlKeyState(false)
}
if (!editorAreaFocus.value && !thumbnailsFocus.value) return
@ -244,8 +244,8 @@ export default () => {
}
const keyupListener = () => {
if (ctrlKeyActive.value) store.commit(MutationTypes.SET_CTRL_KEY_STATE, false)
if (shiftKeyActive.value) store.commit(MutationTypes.SET_SHIFT_KEY_STATE, false)
if (ctrlKeyState.value) keyboardStore.setCtrlKeyState(false)
if (shiftKeyState.value) keyboardStore.setShiftKeyState(false)
}
onMounted(() => {

View File

@ -1,22 +1,22 @@
import { debounce, throttle} from 'lodash'
import { ActionTypes, useStore } from '@/store'
import { useSnapshotStore } from '@/store'
export default () => {
const store = useStore()
const snapshotStore = useSnapshotStore()
// 添加历史快照(历史记录)
const addHistorySnapshot = debounce(function() {
store.dispatch(ActionTypes.ADD_SNAPSHOT)
snapshotStore.addSnapshot()
}, 300, { trailing: true })
// 重做
const redo = throttle(function() {
store.dispatch(ActionTypes.RE_DO)
snapshotStore.reDo()
}, 100, { leading: true, trailing: false })
// 撤销
const undo = throttle(function() {
store.dispatch(ActionTypes.UN_DO)
snapshotStore.unDo()
}, 100, { leading: true, trailing: false })
return {

View File

@ -1,10 +1,10 @@
import { MutationTypes, useStore } from '@/store'
import { useSlidesStore } from '@/store'
import { PPTElement } from '@/types/slides'
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
import { message } from 'ant-design-vue'
export default () => {
const store = useStore()
const slidesStore = useSlidesStore()
const { addHistorySnapshot } = useHistorySnapshot()
@ -15,14 +15,14 @@ export default () => {
return false
}
const props = { link }
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.id, props })
slidesStore.updateElement({ id: handleElement.id, props })
addHistorySnapshot()
return true
}
const removeLink = (handleElement: PPTElement) => {
store.commit(MutationTypes.REMOVE_ELEMENT_PROPS, { id: handleElement.id, propName: 'link' })
slidesStore.removeElementProps({ id: handleElement.id, propName: 'link' })
addHistorySnapshot()
}

View File

@ -1,12 +1,13 @@
import { computed } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { PPTElement, Slide } from '@/types/slides'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store'
import { PPTElement } from '@/types/slides'
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
export default () => {
const store = useStore()
const activeElementIdList = computed(() => store.state.activeElementIdList)
const currentSlide = computed<Slide>(() => store.getters.currentSlide)
const mainStore = useMainStore()
const slidesStore = useSlidesStore()
const { activeElementIdList } = storeToRefs(mainStore)
const { currentSlide } = storeToRefs(slidesStore)
const { addHistorySnapshot } = useHistorySnapshot()
@ -17,8 +18,8 @@ export default () => {
for (const element of newElementList) {
if (activeElementIdList.value.includes(element.id)) element.lock = true
}
store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])
slidesStore.updateSlide({ elements: newElementList })
mainStore.setActiveElementIdList([])
addHistorySnapshot()
}
@ -42,8 +43,8 @@ export default () => {
break
}
}
store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [handleElement.id])
slidesStore.updateSlide({ elements: newElementList })
mainStore.setActiveElementIdList([handleElement.id])
addHistorySnapshot()
}

View File

@ -1,14 +1,13 @@
import { computed } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { PPTElement, Slide } from '@/types/slides'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store'
import { PPTElement } from '@/types/slides'
import { KEYS } from '@/configs/hotkey'
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
export default () => {
const store = useStore()
const activeElementIdList = computed(() => store.state.activeElementIdList)
const activeGroupElementId = computed(() => store.state.activeGroupElementId)
const currentSlide = computed<Slide>(() => store.getters.currentSlide)
const slidesStore = useSlidesStore()
const { activeElementIdList, activeGroupElementId } = storeToRefs(useMainStore())
const { currentSlide } = storeToRefs(slidesStore)
const { addHistorySnapshot } = useHistorySnapshot()
@ -52,7 +51,7 @@ export default () => {
})
}
store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })
slidesStore.updateSlide({ elements: newElementList })
addHistorySnapshot()
}

View File

@ -1,12 +1,12 @@
import { computed } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { PPTElement, Slide } from '@/types/slides'
import { storeToRefs } from 'pinia'
import { useSlidesStore } from '@/store'
import { PPTElement } from '@/types/slides'
import { ElementOrderCommand, ElementOrderCommands } from '@/types/edit'
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
export default () => {
const store = useStore()
const currentSlide = computed<Slide>(() => store.getters.currentSlide)
const slidesStore = useSlidesStore()
const { currentSlide } = storeToRefs(slidesStore)
const { addHistorySnapshot } = useHistorySnapshot()
@ -202,7 +202,7 @@ export default () => {
if (!newElementList) return
store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })
slidesStore.updateSlide({ elements: newElementList })
addHistorySnapshot()
}

View File

@ -1,14 +1,12 @@
import { computed, onMounted, onUnmounted } from 'vue'
import { useStore } from '@/store'
import { onMounted, onUnmounted } from 'vue'
import { storeToRefs } from 'pinia'
import { useMainStore } from '@/store'
import { getImageDataURL } from '@/utils/image'
import usePasteTextClipboardData from './usePasteTextClipboardData'
import useCreateElement from './useCreateElement'
export default () => {
const store = useStore()
const editorAreaFocus = computed(() => store.state.editorAreaFocus)
const thumbnailsFocus = computed(() => store.state.thumbnailsFocus)
const disableHotkeys = computed(() => store.state.disableHotkeys)
const { editorAreaFocus, thumbnailsFocus, disableHotkeys } = storeToRefs(useMainStore())
const { pasteTextClipboardData } = usePasteTextClipboardData()
const { createImageElement } = useCreateElement()

View File

@ -1,5 +1,5 @@
import { computed } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { storeToRefs } from 'pinia'
import { useSlidesStore, useMainStore } from '@/store'
import { pasteCustomClipboardString } from '@/utils/clipboard'
import { PPTElement, Slide } from '@/types/slides'
import { createRandomCode } from '@/utils/common'
@ -14,8 +14,9 @@ interface PasteTextClipboardDataOptions {
}
export default () => {
const store = useStore()
const currentSlide = computed<Slide>(() => store.getters.currentSlide)
const mainStore = useMainStore()
const slidesStore = useSlidesStore()
const { currentSlide } = storeToRefs(slidesStore)
const { addHistorySnapshot } = useHistorySnapshot()
const { createTextElement } = useCreateElement()
@ -40,8 +41,8 @@ export default () => {
if (element.groupId) element.groupId = groupIdMap[element.groupId]
}
store.commit(MutationTypes.ADD_ELEMENT, elements)
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, Object.values(elIdMap))
slidesStore.addElement(elements)
mainStore.setActiveElementIdList(Object.values(elIdMap))
addHistorySnapshot()
}
@ -67,7 +68,7 @@ export default () => {
id: createRandomCode(8),
}
})
store.commit(MutationTypes.ADD_SLIDE, newSlides)
slidesStore.addSlide(newSlides)
addHistorySnapshot()
}

View File

@ -1,9 +1,9 @@
import { computed } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { storeToRefs } from 'pinia'
import { useMainStore } from '@/store'
export default () => {
const store = useStore()
const canvasPercentage = computed(() => store.state.canvasPercentage)
const mainStore = useMainStore()
const { canvasPercentage } = storeToRefs(mainStore)
/**
*
@ -16,8 +16,8 @@ export default () => {
const min = 60
if (command === '+' && percentage <= max) percentage += step
if (command === '-' && percentage >= min) percentage -= step
store.commit(MutationTypes.SET_CANVAS_PERCENTAGE, percentage)
mainStore.setCanvasPercentage(percentage)
}
/**
@ -25,7 +25,7 @@ export default () => {
* @param percentage 0.8
*/
const setCanvasPercentage = (percentage: number) => {
store.commit(MutationTypes.SET_CANVAS_PERCENTAGE, percentage)
mainStore.setCanvasPercentage(percentage)
}
return {

View File

@ -1,24 +1,25 @@
import { MutationTypes, useStore } from '@/store'
import { useScreenStore, useSlidesStore } from '@/store'
import { enterFullscreen, exitFullscreen, isFullscreen } from '@/utils/fullscreen'
export default () => {
const store = useStore()
const screenStore = useScreenStore()
const slidesStore = useSlidesStore()
// 进入放映状态(从当前页开始)
const enterScreening = () => {
enterFullscreen()
store.commit(MutationTypes.SET_SCREENING, true)
screenStore.setScreening(true)
}
// 进入放映状态(从第一页开始)
const enterScreeningFromStart = () => {
store.commit(MutationTypes.UPDATE_SLIDE_INDEX, 0)
slidesStore.updateSlideIndex(0)
enterScreening()
}
// 退出放映状态
const exitScreening = () => {
store.commit(MutationTypes.SET_SCREENING, false)
screenStore.setScreening(false)
if (isFullscreen()) exitFullscreen()
}

View File

@ -1,16 +1,15 @@
import { computed } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { Slide } from '@/types/slides'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store'
export default () => {
const store = useStore()
const currentSlide = computed<Slide>(() => store.getters.currentSlide)
const mainStore = useMainStore()
const { currentSlide } = storeToRefs(useSlidesStore())
// 将当前页面全部元素设置为被选择状态
const selectAllElement = () => {
const unlockedElements = currentSlide.value.elements.filter(el => !el.lock)
const newActiveElementIdList = unlockedElements.map(el => el.id)
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, newActiveElementIdList)
mainStore.setActiveElementIdList(newActiveElementIdList)
}
return {

View File

@ -1,5 +1,6 @@
import { computed } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store'
import { Slide } from '@/types/slides'
import { createRandomCode } from '@/utils/common'
import { copyText, readClipboard } from '@/utils/clipboard'
@ -11,13 +12,12 @@ import usePasteTextClipboardData from '@/hooks/usePasteTextClipboardData'
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
export default () => {
const store = useStore()
const slideIndex = computed(() => store.state.slideIndex)
const theme = computed(() => store.state.theme)
const slides = computed(() => store.state.slides)
const currentSlide = computed<Slide>(() => store.getters.currentSlide)
const mainStore = useMainStore()
const slidesStore = useSlidesStore()
const { selectedSlidesIndex: _selectedSlidesIndex } = storeToRefs(mainStore)
const { currentSlide, slides, theme, slideIndex } = storeToRefs(slidesStore)
const selectedSlidesIndex = computed(() => [...store.state.selectedSlidesIndex, slideIndex.value])
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))
@ -26,7 +26,7 @@ export default () => {
// 重置幻灯片
const resetSlides = () => {
const emptySlide = {
const emptySlide: Slide = {
id: createRandomCode(8),
elements: [],
background: {
@ -34,9 +34,9 @@ export default () => {
color: theme.value.backgroundColor,
},
}
store.commit(MutationTypes.UPDATE_SLIDE_INDEX, 0)
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])
store.commit(MutationTypes.SET_SLIDES, [emptySlide])
slidesStore.updateSlideIndex(0)
mainStore.setActiveElementIdList([])
slidesStore.setSlides([emptySlide])
}
/**
@ -45,10 +45,10 @@ export default () => {
*/
const updateSlideIndex = (command: string) => {
if (command === KEYS.UP && slideIndex.value > 0) {
store.commit(MutationTypes.UPDATE_SLIDE_INDEX, slideIndex.value - 1)
slidesStore.updateSlideIndex(slideIndex.value - 1)
}
else if (command === KEYS.DOWN && slideIndex.value < slides.value.length - 1) {
store.commit(MutationTypes.UPDATE_SLIDE_INDEX, slideIndex.value + 1)
slidesStore.updateSlideIndex(slideIndex.value + 1)
}
}
@ -60,7 +60,7 @@ export default () => {
}))
copyText(text).then(() => {
store.commit(MutationTypes.SET_THUMBNAILS_FOCUS, true)
mainStore.setThumbnailsFocus(true)
})
}
@ -73,7 +73,7 @@ export default () => {
// 创建一页空白页并添加到下一页
const createSlide = () => {
const emptySlide = {
const emptySlide: Slide = {
id: createRandomCode(8),
elements: [],
background: {
@ -81,8 +81,8 @@ export default () => {
color: theme.value.backgroundColor,
},
}
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])
store.commit(MutationTypes.ADD_SLIDE, emptySlide)
mainStore.setActiveElementIdList([])
slidesStore.addSlide(emptySlide)
addHistorySnapshot()
}
@ -98,8 +98,8 @@ export default () => {
...slide,
id: createRandomCode(8),
}
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])
store.commit(MutationTypes.ADD_SLIDE, newSlide)
mainStore.setActiveElementIdList([])
slidesStore.addSlide(newSlide)
addHistorySnapshot()
}
@ -112,9 +112,9 @@ export default () => {
// 删除当前页,若将删除全部页面,则执行重置幻灯片操作
const deleteSlide = (targetSlidesId = selectedSlidesId.value) => {
if (slides.value.length === targetSlidesId.length) resetSlides()
else store.commit(MutationTypes.DELETE_SLIDE, targetSlidesId)
else slidesStore.deleteSlide(targetSlidesId)
store.commit(MutationTypes.UPDATE_SELECTED_SLIDES_INDEX, [])
mainStore.updateSelectedSlidesIndex([])
addHistorySnapshot()
}
@ -130,8 +130,8 @@ export default () => {
// 选中全部幻灯片
const selectAllSlide = () => {
const newSelectedSlidesIndex = Array.from(Array(slides.value.length), (item, index) => index)
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])
store.commit(MutationTypes.UPDATE_SELECTED_SLIDES_INDEX, newSelectedSlidesIndex)
mainStore.setActiveElementIdList([])
mainStore.updateSelectedSlidesIndex(newSelectedSlidesIndex)
}
return {

View File

@ -1,6 +1,7 @@
import { computed } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { PPTElement, Slide } from '@/types/slides'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store'
import { PPTElement } from '@/types/slides'
import { getElementRange, getElementListRange, getRectRotatedOffset } from '@/utils/element'
import useHistorySnapshot from './useHistorySnapshot'
@ -34,10 +35,9 @@ interface LastPos {
}
export default () => {
const store = useStore()
const activeElementIdList = computed(() => store.state.activeElementIdList)
const activeElementList = computed<PPTElement[]>(() => store.getters.activeElementList)
const currentSlide = computed<Slide>(() => store.getters.currentSlide)
const slidesStore = useSlidesStore()
const { activeElementIdList, activeElementList } = storeToRefs(useMainStore())
const { currentSlide } = storeToRefs(slidesStore)
const { addHistorySnapshot } = useHistorySnapshot()
@ -154,7 +154,7 @@ export default () => {
}
}
store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })
slidesStore.updateSlide({ elements: newElementList })
addHistorySnapshot()
}
@ -249,7 +249,7 @@ export default () => {
}
}
store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList })
slidesStore.updateSlide({ elements: newElementList })
addHistorySnapshot()
}

View File

@ -1,6 +1,6 @@
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import { store, key } from './store'
import '@icon-park/vue-next/styles/index.css'
import 'prosemirror-view/style/prosemirror.css'
@ -65,5 +65,5 @@ app.use(Icon)
app.use(Component)
app.use(Directive)
app.use(store, key)
app.use(createPinia())
app.mount('#app')

View File

@ -1,99 +0,0 @@
import { ActionTree } from 'vuex'
import { IndexableTypeArray } from 'dexie'
import { State } from './state'
import { ActionTypes, MutationTypes } from './constants'
import { snapshotDB, Snapshot } from '@/utils/database'
export const actions: ActionTree<State, State> = {
async [ActionTypes.INIT_SNAPSHOT_DATABASE]({ commit, state }) {
const snapshots: Snapshot[] = await snapshotDB.snapshots.orderBy('id').toArray()
const lastSnapshot = snapshots.slice(-1)[0]
if (lastSnapshot) {
snapshotDB.snapshots.clear()
}
const newFirstSnapshot = {
index: state.slideIndex,
slides: state.slides,
}
await snapshotDB.snapshots.add(newFirstSnapshot)
commit(MutationTypes.SET_SNAPSHOT_CURSOR, 0)
commit(MutationTypes.SET_SNAPSHOT_LENGTH, 1)
},
async [ActionTypes.ADD_SNAPSHOT]({ state, commit }) {
// 获取当前indexeddb中全部快照的ID
const allKeys = await snapshotDB.snapshots.orderBy('id').keys()
let needDeleteKeys: IndexableTypeArray = []
// 记录需要删除的快照ID
// 若当前快照指针不处在最后一位,那么再添加快照时,应该将当前指针位置后面的快照全部删除,对应的实际情况是:
// 用户撤回多次后,再进行操作(添加快照),此时原先被撤销的快照都应该被删除
if (state.snapshotCursor >= 0 && state.snapshotCursor < allKeys.length - 1) {
needDeleteKeys = allKeys.slice(state.snapshotCursor + 1)
}
// 添加新快照
const snapshot = {
index: state.slideIndex,
slides: state.slides,
}
await snapshotDB.snapshots.add(snapshot)
// 计算当前快照长度,用于设置快照指针的位置(此时指针应该处在最后一位,即:快照长度 - 1
let snapshotLength = allKeys.length - needDeleteKeys.length + 1
// 快照数量超过长度限制时,应该将头部多余的快照删除
const snapshotLengthLimit = 20
if (snapshotLength > snapshotLengthLimit) {
needDeleteKeys.push(allKeys[0])
snapshotLength--
}
// 快照数大于1时需要保证撤回操作后维持页面焦点不变也就是将倒数第二个快照对应的索引设置为当前页的索引
// https://github.com/pipipi-pikachu/PPTist/issues/27
if (snapshotLength >= 2) {
snapshotDB.snapshots.update(allKeys[snapshotLength - 2] as number, { index: state.slideIndex })
}
await snapshotDB.snapshots.bulkDelete(needDeleteKeys)
commit(MutationTypes.SET_SNAPSHOT_CURSOR, snapshotLength - 1)
commit(MutationTypes.SET_SNAPSHOT_LENGTH, snapshotLength)
},
async [ActionTypes.UN_DO]({ state, commit }) {
if (state.snapshotCursor <= 0) return
const snapshotCursor = state.snapshotCursor - 1
const snapshots: Snapshot[] = await snapshotDB.snapshots.orderBy('id').toArray()
const snapshot = snapshots[snapshotCursor]
const { index, slides } = snapshot
const slideIndex = index > slides.length - 1 ? slides.length - 1 : index
commit(MutationTypes.SET_SLIDES, slides)
commit(MutationTypes.UPDATE_SLIDE_INDEX, slideIndex)
commit(MutationTypes.SET_SNAPSHOT_CURSOR, snapshotCursor)
commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])
},
async [ActionTypes.RE_DO]({ state, commit }) {
if (state.snapshotCursor >= state.snapshotLength - 1) return
const snapshotCursor = state.snapshotCursor + 1
const snapshots: Snapshot[] = await snapshotDB.snapshots.orderBy('id').toArray()
const snapshot = snapshots[snapshotCursor]
const { index, slides } = snapshot
const slideIndex = index > slides.length - 1 ? slides.length - 1 : index
commit(MutationTypes.SET_SLIDES, slides)
commit(MutationTypes.UPDATE_SLIDE_INDEX, slideIndex)
commit(MutationTypes.SET_SNAPSHOT_CURSOR, snapshotCursor)
commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])
},
}

View File

@ -1,52 +0,0 @@
export const enum MutationTypes {
// editor
SET_ACTIVE_ELEMENT_ID_LIST = 'setActiveElementIdList',
SET_HANDLE_ELEMENT_ID = 'setHandleElementId',
SET_ACTIVE_GROUP_ELEMENT_ID = 'setActiveGroupElementId',
SET_CANVAS_PERCENTAGE = 'setCanvasPercentage',
SET_CANVAS_SCALE = 'setCanvasScale',
SET_THUMBNAILS_FOCUS = 'setThumbnailsFocus',
SET_EDITORAREA_FOCUS = 'setEditorAreaFocus',
SET_DISABLE_HOTKEYS_STATE = 'setDisableHotkeysState',
SET_GRID_LINES_STATE = 'setGridLinesState',
SET_CREATING_ELEMENT = 'setCreatingElement',
SET_AVAILABLE_FONTS = 'setAvailableFonts',
SET_TOOLBAR_STATE = 'setToolbarState',
SET_CLIPING_IMAGE_ELEMENT_ID = 'setClipingImageElementId',
SET_RICHTEXT_ATTRS = 'setRichTextAttrs',
SET_SELECTED_TABLE_CELLS = 'setSelectedTableCells',
SET_SCALING_STATE = 'setScalingState',
SET_EDITING_SHAPE_ELEMENT_ID = 'setEditingShapeElementId',
// slides
SET_THEME = 'setTheme',
SET_VIEWPORT_RATIO = 'setViewportRatio',
SET_SLIDES = 'setSlides',
ADD_SLIDE = 'addSlide',
UPDATE_SLIDE = 'updateSlide',
DELETE_SLIDE = 'deleteSlide',
UPDATE_SLIDE_INDEX = 'updateSlideIndex',
UPDATE_SELECTED_SLIDES_INDEX = 'updateSelectedSlidesIndex',
ADD_ELEMENT = 'addElement',
UPDATE_ELEMENT = 'updateElement',
REMOVE_ELEMENT_PROPS = 'removeElementProps',
// snapshot
SET_SNAPSHOT_CURSOR = 'setSnapshotCursor',
SET_SNAPSHOT_LENGTH = 'setSnapshotLength',
// keyboard
SET_CTRL_KEY_STATE = 'setCtrlKeyState',
SET_SHIFT_KEY_STATE = 'setShiftKeyState',
// screen
SET_SCREENING = 'setScreening',
}
export const enum ActionTypes {
INIT_SNAPSHOT_DATABASE = 'initSnapshotDatabase',
ADD_SNAPSHOT = 'addSnapshot',
UN_DO = 'undo',
RE_DO = 'redo',
}

View File

@ -1,65 +0,0 @@
import { GetterTree } from 'vuex'
import tinycolor from 'tinycolor2'
import { State } from './state'
import { layouts } from '@/mocks/layout'
export const getters: GetterTree<State, State> = {
currentSlide(state) {
return state.slides[state.slideIndex] || null
},
currentSlideAnimations(state) {
const currentSlide = state.slides[state.slideIndex]
if (!currentSlide) return null
const animations = currentSlide.animations
if (!animations) return null
const els = currentSlide.elements
const elIds = els.map(el => el.id)
return animations.filter(animation => elIds.includes(animation.elId))
},
layouts(state) {
const {
themeColor,
fontColor,
fontName,
backgroundColor,
} = state.theme
const subColor = tinycolor(fontColor).isDark() ? 'rgba(230, 230, 230, 0.5)' : 'rgba(180, 180, 180, 0.5)'
const layoutsString = JSON.stringify(layouts)
.replaceAll('{{themeColor}}', themeColor)
.replaceAll('{{fontColor}}', fontColor)
.replaceAll('{{fontName}}', fontName)
.replaceAll('{{backgroundColor}}', backgroundColor)
.replaceAll('{{subColor}}', subColor)
return JSON.parse(layoutsString)
},
activeElementList(state) {
const currentSlide = state.slides[state.slideIndex]
if (!currentSlide || !currentSlide.elements) return []
return currentSlide.elements.filter(element => state.activeElementIdList.includes(element.id))
},
handleElement(state) {
const currentSlide = state.slides[state.slideIndex]
if (!currentSlide || !currentSlide.elements) return null
return currentSlide.elements.find(element => state.handleElementId === element.id) || null
},
canUndo(state) {
return state.snapshotCursor > 0
},
canRedo(state) {
return state.snapshotCursor < state.snapshotLength - 1
},
ctrlOrShiftKeyActive(state) {
return state.ctrlKeyState || state.shiftKeyState
},
}

View File

@ -1,20 +1,13 @@
import { InjectionKey } from 'vue'
import { createStore, Store, useStore as baseUseStore } from 'vuex'
import { state, State } from './state'
import { getters } from './getters'
import { actions } from './actions'
import { mutations } from './mutations'
import { MutationTypes, ActionTypes } from './constants'
import { useMainStore } from './main'
import { useSlidesStore } from './slides'
import { useSnapshotStore } from './snapshot'
import { useKeyboardStore } from './keyboard'
import { useScreenStore } from './screen'
export { MutationTypes, ActionTypes }
export const key: InjectionKey<Store<State>> = Symbol()
export const store = createStore<State>({
state,
getters,
mutations,
actions,
})
export const useStore = () => baseUseStore(key)
export {
useMainStore,
useSlidesStore,
useSnapshotStore,
useKeyboardStore,
useScreenStore,
}

28
src/store/keyboard.ts Normal file
View File

@ -0,0 +1,28 @@
import { defineStore } from 'pinia'
export interface KeyboardState {
ctrlKeyState: boolean;
shiftKeyState: boolean;
}
export const useKeyboardStore = defineStore('keyboard', {
state: (): KeyboardState => ({
ctrlKeyState: false, // ctrl键按下状态
shiftKeyState: false, // shift键按下状态
}),
getters: {
ctrlOrShiftKeyActive(state) {
return state.ctrlKeyState || state.shiftKeyState
},
},
actions: {
setCtrlKeyState(active: boolean) {
this.ctrlKeyState = active
},
setShiftKeyState(active: boolean) {
this.shiftKeyState = active
},
},
})

145
src/store/main.ts Normal file
View File

@ -0,0 +1,145 @@
import { defineStore } from 'pinia'
import { CreatingElement } from '@/types/edit'
import { ToolbarState } from '@/types/toolbar'
import { SYS_FONTS } from '@/configs/font'
import { TextAttrs, defaultRichTextAttrs } from '@/utils/prosemirror/utils'
import { isSupportFont } from '@/utils/font'
import { useSlidesStore } from './slides'
export interface MainState {
activeElementIdList: string[];
handleElementId: string;
activeGroupElementId: string;
canvasPercentage: number;
canvasScale: number;
thumbnailsFocus: boolean;
editorAreaFocus: boolean;
disableHotkeys: boolean;
showGridLines: boolean;
creatingElement: CreatingElement | null;
availableFonts: typeof SYS_FONTS;
toolbarState: ToolbarState;
clipingImageElementId: string;
isScaling: boolean;
richTextAttrs: TextAttrs;
selectedTableCells: string[];
editingShapeElementId: string;
selectedSlidesIndex: number[];
}
export const useMainStore = defineStore('main', {
state: (): MainState => ({
activeElementIdList: [], // 被选中的元素ID集合包含 handleElementId
handleElementId: '', // 正在操作的元素ID
activeGroupElementId: '', // 组合元素成员中被选中可独立操作的元素ID
canvasPercentage: 90, // 画布可视区域百分比
canvasScale: 1, // 画布缩放比例基于宽度1000px
thumbnailsFocus: false, // 左侧导航缩略图区域聚焦
editorAreaFocus: false, // 编辑区域聚焦
disableHotkeys: false, // 禁用快捷键
showGridLines: false, // 显示网格线
creatingElement: null, // 正在插入的元素信息,需要绘制插入的元素需要(文字、形状、线条)
availableFonts: [], // 当前环境可用字体
toolbarState: 'slideDesign', // 右侧工具栏状态
clipingImageElementId: '', // 当前正在裁剪的图片ID
richTextAttrs: defaultRichTextAttrs, // 富文本状态
selectedTableCells: [], // 选中的表格单元格
isScaling: false, // 正在进行元素缩放
editingShapeElementId: '', // 当前正处在编辑文字状态的形状ID
selectedSlidesIndex: [], // 当前被选中的页面索引集合
}),
getters: {
activeElementList(state) {
const slidesStore = useSlidesStore()
const currentSlide = slidesStore.currentSlide
if (!currentSlide || !currentSlide.elements) return []
return currentSlide.elements.filter(element => state.activeElementIdList.includes(element.id))
},
handleElement(state) {
const slidesStore = useSlidesStore()
const currentSlide = slidesStore.currentSlide
if (!currentSlide || !currentSlide.elements) return null
return currentSlide.elements.find(element => state.handleElementId === element.id) || null
},
},
actions: {
setActiveElementIdList(activeElementIdList: string[]) {
if (activeElementIdList.length === 1) this.handleElementId = activeElementIdList[0]
else this.handleElementId = ''
this.activeElementIdList = activeElementIdList
},
setHandleElementId(handleElementId: string) {
this.handleElementId = handleElementId
},
setActiveGroupElementId(activeGroupElementId: string) {
this.activeGroupElementId = activeGroupElementId
},
setCanvasPercentage(percentage: number) {
this.canvasPercentage = percentage
},
setCanvasScale(scale: number) {
this.canvasScale = scale
},
setThumbnailsFocus(isFocus: boolean) {
this.thumbnailsFocus = isFocus
},
setEditorareaFocus(isFocus: boolean) {
this.editorAreaFocus = isFocus
},
setDisableHotkeysState(disable: boolean) {
this.disableHotkeys = disable
},
setGridLinesState(show: boolean) {
this.showGridLines = show
},
setCreatingElement(element: CreatingElement | null) {
this.creatingElement = element
},
setAvailableFonts() {
this.availableFonts = SYS_FONTS.filter(font => isSupportFont(font.value))
},
setToolbarState(toolbarState: ToolbarState) {
this.toolbarState = toolbarState
},
setClipingImageElementId(elId: string) {
this.clipingImageElementId = elId
},
setRichtextAttrs(attrs: TextAttrs) {
this.richTextAttrs = attrs
},
setSelectedTableCells(cells: string[]) {
this.selectedTableCells = cells
},
setScalingState(isScaling: boolean) {
this.isScaling = isScaling
},
setEditingShapeElementId(ellId: string) {
this.editingShapeElementId = ellId
},
updateSelectedSlidesIndex(selectedSlidesIndex: number[]) {
this.selectedSlidesIndex = selectedSlidesIndex
},
},
})

View File

@ -1,203 +0,0 @@
import { MutationTree } from 'vuex'
import { omit } from 'lodash'
import { MutationTypes } from './constants'
import { State } from './state'
import { Slide, PPTElement, SlideTheme } from '@/types/slides'
import { CreatingElement } from '@/types/edit'
import { SYS_FONTS } from '@/configs/font'
import { isSupportFont } from '@/utils/font'
import { ToolbarState } from '@/types/toolbar'
import { TextAttrs } from '@/utils/prosemirror/utils'
interface RemoveElementPropData {
id: string;
propName: string | string[];
}
interface UpdateElementData {
id: string | string[];
props: Partial<PPTElement>;
}
export const mutations: MutationTree<State> = {
// editor
[MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST](state, activeElementIdList: string[]) {
if (activeElementIdList.length === 1) state.handleElementId = activeElementIdList[0]
else state.handleElementId = ''
state.activeElementIdList = activeElementIdList
},
[MutationTypes.SET_HANDLE_ELEMENT_ID](state, handleElementId: string) {
state.handleElementId = handleElementId
},
[MutationTypes.SET_ACTIVE_GROUP_ELEMENT_ID](state, activeGroupElementId: string) {
state.activeGroupElementId = activeGroupElementId
},
[MutationTypes.SET_CANVAS_PERCENTAGE](state, percentage: number) {
state.canvasPercentage = percentage
},
[MutationTypes.SET_CANVAS_SCALE](state, scale: number) {
state.canvasScale = scale
},
[MutationTypes.SET_THUMBNAILS_FOCUS](state, isFocus: boolean) {
state.thumbnailsFocus = isFocus
},
[MutationTypes.SET_EDITORAREA_FOCUS](state, isFocus: boolean) {
state.editorAreaFocus = isFocus
},
[MutationTypes.SET_DISABLE_HOTKEYS_STATE](state, disable: boolean) {
state.disableHotkeys = disable
},
[MutationTypes.SET_GRID_LINES_STATE](state, show: boolean) {
state.showGridLines = show
},
[MutationTypes.SET_CREATING_ELEMENT](state, element: CreatingElement | null) {
state.creatingElement = element
},
[MutationTypes.SET_AVAILABLE_FONTS](state) {
state.availableFonts = SYS_FONTS.filter(font => isSupportFont(font.value))
},
[MutationTypes.SET_TOOLBAR_STATE](state, toolbarState: ToolbarState) {
state.toolbarState = toolbarState
},
[MutationTypes.SET_CLIPING_IMAGE_ELEMENT_ID](state, elId: string) {
state.clipingImageElementId = elId
},
[MutationTypes.SET_RICHTEXT_ATTRS](state, attrs: TextAttrs) {
state.richTextAttrs = attrs
},
[MutationTypes.SET_SELECTED_TABLE_CELLS](state, cells: string[]) {
state.selectedTableCells = cells
},
[MutationTypes.SET_SCALING_STATE](state, isScaling: boolean) {
state.isScaling = isScaling
},
[MutationTypes.SET_EDITING_SHAPE_ELEMENT_ID](state, ellId: string) {
state.editingShapeElementId = ellId
},
// slides
[MutationTypes.SET_THEME](state, themeProps: Partial<SlideTheme>) {
state.theme = { ...state.theme, ...themeProps }
},
[MutationTypes.SET_VIEWPORT_RATIO](state, viewportRatio: number) {
state.viewportRatio = viewportRatio
},
[MutationTypes.SET_SLIDES](state, slides: Slide[]) {
state.slides = slides
},
[MutationTypes.ADD_SLIDE](state, slide: Slide | Slide[]) {
const slides = Array.isArray(slide) ? slide : [slide]
const addIndex = state.slideIndex + 1
state.slides.splice(addIndex, 0, ...slides)
state.slideIndex = addIndex
},
[MutationTypes.UPDATE_SLIDE](state, props: Partial<Slide>) {
const slideIndex = state.slideIndex
state.slides[slideIndex] = { ...state.slides[slideIndex], ...props }
},
[MutationTypes.DELETE_SLIDE](state, slideId: string | string[]) {
const slidesId = Array.isArray(slideId) ? slideId : [slideId]
const deleteSlidesIndex = []
for (let i = 0; i < slidesId.length; i++) {
const index = state.slides.findIndex(item => item.id === slidesId[i])
deleteSlidesIndex.push(index)
}
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) {
state.slideIndex = index
},
[MutationTypes.UPDATE_SELECTED_SLIDES_INDEX](state, selectedSlidesIndex: number[]) {
state.selectedSlidesIndex = selectedSlidesIndex
},
[MutationTypes.ADD_ELEMENT](state, element: PPTElement | PPTElement[]) {
const elements = Array.isArray(element) ? element : [element]
const currentSlideEls = state.slides[state.slideIndex].elements
const newEls = [...currentSlideEls, ...elements]
state.slides[state.slideIndex].elements = newEls
},
[MutationTypes.UPDATE_ELEMENT](state, data: UpdateElementData) {
const { id, props } = data
const elIdList = typeof id === 'string' ? [id] : id
const slideIndex = state.slideIndex
const slide = state.slides[slideIndex]
const elements = slide.elements.map(el => {
return elIdList.includes(el.id) ? { ...el, ...props } : el
})
state.slides[slideIndex].elements = (elements as PPTElement[])
},
[MutationTypes.REMOVE_ELEMENT_PROPS](state, data: RemoveElementPropData) {
const { id, propName } = data
const propsNames = typeof propName === 'string' ? [propName] : propName
const slideIndex = state.slideIndex
const slide = state.slides[slideIndex]
const elements = slide.elements.map(el => {
return el.id === id ? omit(el, propsNames) : el
})
state.slides[slideIndex].elements = (elements as PPTElement[])
},
// snapshot
[MutationTypes.SET_SNAPSHOT_CURSOR](state, cursor: number) {
state.snapshotCursor = cursor
},
[MutationTypes.SET_SNAPSHOT_LENGTH](state, length: number) {
state.snapshotLength = length
},
// keyboard
[MutationTypes.SET_CTRL_KEY_STATE](state, isActive: boolean) {
state.ctrlKeyState = isActive
},
[MutationTypes.SET_SHIFT_KEY_STATE](state, isActive: boolean) {
state.shiftKeyState = isActive
},
// screen
[MutationTypes.SET_SCREENING](state, screening) {
state.screening = screening
},
}

17
src/store/screen.ts Normal file
View File

@ -0,0 +1,17 @@
import { defineStore } from 'pinia'
export interface ScreenState {
screening: boolean;
}
export const useScreenStore = defineStore('screen', {
state: (): ScreenState => ({
screening: false, // 是否进入放映状态
}),
actions: {
setScreening(screening: boolean) {
this.screening = screening
},
},
})

148
src/store/slides.ts Normal file
View File

@ -0,0 +1,148 @@
import { defineStore } from 'pinia'
import tinycolor from 'tinycolor2'
import { omit } from 'lodash'
import { Slide, SlideTheme, PPTElement } from '@/types/slides'
import { slides } from '@/mocks/slides'
import { theme } from '@/mocks/theme'
import { layouts } from '@/mocks/layout'
interface RemoveElementPropData {
id: string;
propName: string | string[];
}
interface UpdateElementData {
id: string | string[];
props: Partial<PPTElement>;
}
export interface SlidesState {
theme: SlideTheme;
slides: Slide[];
slideIndex: number;
viewportRatio: number;
}
export const useSlidesStore = defineStore('slides', {
state: (): SlidesState => ({
theme: theme, // 主题样式
slides: slides, // 幻灯片页面数据
slideIndex: 0, // 当前页面索引
viewportRatio: 0.5625, // 可是区域比例默认16:9
}),
getters: {
currentSlide(state) {
return state.slides[state.slideIndex]
},
currentSlideAnimations(state) {
const currentSlide = state.slides[state.slideIndex]
if (!currentSlide) return null
const animations = currentSlide.animations
if (!animations) return null
const els = currentSlide.elements
const elIds = els.map(el => el.id)
return animations.filter(animation => elIds.includes(animation.elId))
},
layouts(state) {
const {
themeColor,
fontColor,
fontName,
backgroundColor,
} = state.theme
const subColor = tinycolor(fontColor).isDark() ? 'rgba(230, 230, 230, 0.5)' : 'rgba(180, 180, 180, 0.5)'
const layoutsString = JSON.stringify(layouts)
.replaceAll('{{themeColor}}', themeColor)
.replaceAll('{{fontColor}}', fontColor)
.replaceAll('{{fontName}}', fontName)
.replaceAll('{{backgroundColor}}', backgroundColor)
.replaceAll('{{subColor}}', subColor)
return JSON.parse(layoutsString)
},
},
actions: {
setTheme(themeProps: Partial<SlideTheme>) {
this.theme = { ...this.theme, ...themeProps }
},
setViewportRatio(viewportRatio: number) {
this.viewportRatio = viewportRatio
},
setSlides(slides: Slide[]) {
this.slides = slides
},
addSlide(slide: Slide | Slide[]) {
const slides = Array.isArray(slide) ? slide : [slide]
const addIndex = this.slideIndex + 1
this.slides.splice(addIndex, 0, ...slides)
this.slideIndex = addIndex
},
updateSlide(props: Partial<Slide>) {
const slideIndex = this.slideIndex
this.slides[slideIndex] = { ...this.slides[slideIndex], ...props }
},
deleteSlide(slideId: string | string[]) {
const slidesId = Array.isArray(slideId) ? slideId : [slideId]
const deleteSlidesIndex = []
for (let i = 0; i < slidesId.length; i++) {
const index = this.slides.findIndex(item => item.id === slidesId[i])
deleteSlidesIndex.push(index)
}
let newIndex = Math.min(...deleteSlidesIndex)
const maxIndex = this.slides.length - slidesId.length - 1
if (newIndex > maxIndex) newIndex = maxIndex
this.slideIndex = newIndex
this.slides = this.slides.filter(item => !slidesId.includes(item.id))
},
updateSlideIndex(index: number) {
this.slideIndex = index
},
addElement(element: PPTElement | PPTElement[]) {
const elements = Array.isArray(element) ? element : [element]
const currentSlideEls = this.slides[this.slideIndex].elements
const newEls = [...currentSlideEls, ...elements]
this.slides[this.slideIndex].elements = newEls
},
updateElement(data: UpdateElementData) {
const { id, props } = data
const elIdList = typeof id === 'string' ? [id] : id
const slideIndex = this.slideIndex
const slide = this.slides[slideIndex]
const elements = slide.elements.map(el => {
return elIdList.includes(el.id) ? { ...el, ...props } : el
})
this.slides[slideIndex].elements = (elements as PPTElement[])
},
removeElementProps(data: RemoveElementPropData) {
const { id, propName } = data
const propsNames = typeof propName === 'string' ? [propName] : propName
const slideIndex = this.slideIndex
const slide = this.slides[slideIndex]
const elements = slide.elements.map(el => {
return el.id === id ? omit(el, propsNames) : el
})
this.slides[slideIndex].elements = (elements as PPTElement[])
},
},
})

137
src/store/snapshot.ts Normal file
View File

@ -0,0 +1,137 @@
import { defineStore } from 'pinia'
import { IndexableTypeArray } from 'dexie'
import { snapshotDB, Snapshot } from '@/utils/database'
import { useSlidesStore } from './slides'
import { useMainStore } from './main'
export interface ScreenState {
snapshotCursor: number;
snapshotLength: number;
}
export const useSnapshotStore = defineStore('snapshot', {
state: (): ScreenState => ({
snapshotCursor: -1, // 历史快照指针
snapshotLength: 0, // 历史快照长度
}),
getters: {
canUndo(state) {
return state.snapshotCursor > 0
},
canRedo(state) {
return state.snapshotCursor < state.snapshotLength - 1
},
},
actions: {
setSnapshotCursor(cursor: number) {
this.snapshotCursor = cursor
},
setSnapshotLength(length: number) {
this.snapshotLength = length
},
async initSnapshotDatabase() {
const slidesStore = useSlidesStore()
const snapshots: Snapshot[] = await snapshotDB.snapshots.orderBy('id').toArray()
const lastSnapshot = snapshots.slice(-1)[0]
if (lastSnapshot) {
snapshotDB.snapshots.clear()
}
const newFirstSnapshot = {
index: slidesStore.slideIndex,
slides: slidesStore.slides,
}
await snapshotDB.snapshots.add(newFirstSnapshot)
this.setSnapshotCursor(0)
this.setSnapshotLength(1)
},
async addSnapshot() {
const slidesStore = useSlidesStore()
// 获取当前indexeddb中全部快照的ID
const allKeys = await snapshotDB.snapshots.orderBy('id').keys()
let needDeleteKeys: IndexableTypeArray = []
// 记录需要删除的快照ID
// 若当前快照指针不处在最后一位,那么再添加快照时,应该将当前指针位置后面的快照全部删除,对应的实际情况是:
// 用户撤回多次后,再进行操作(添加快照),此时原先被撤销的快照都应该被删除
if (this.snapshotCursor >= 0 && this.snapshotCursor < allKeys.length - 1) {
needDeleteKeys = allKeys.slice(this.snapshotCursor + 1)
}
// 添加新快照
const snapshot = {
index: slidesStore.slideIndex,
slides: slidesStore.slides,
}
await snapshotDB.snapshots.add(snapshot)
// 计算当前快照长度,用于设置快照指针的位置(此时指针应该处在最后一位,即:快照长度 - 1
let snapshotLength = allKeys.length - needDeleteKeys.length + 1
// 快照数量超过长度限制时,应该将头部多余的快照删除
const snapshotLengthLimit = 20
if (snapshotLength > snapshotLengthLimit) {
needDeleteKeys.push(allKeys[0])
snapshotLength--
}
// 快照数大于1时需要保证撤回操作后维持页面焦点不变也就是将倒数第二个快照对应的索引设置为当前页的索引
// https://github.com/pipipi-pikachu/PPTist/issues/27
if (snapshotLength >= 2) {
snapshotDB.snapshots.update(allKeys[snapshotLength - 2] as number, { index: slidesStore.slideIndex })
}
await snapshotDB.snapshots.bulkDelete(needDeleteKeys)
this.setSnapshotCursor(snapshotLength - 1)
this.setSnapshotLength(snapshotLength)
},
async unDo() {
if (this.snapshotCursor <= 0) return
const slidesStore = useSlidesStore()
const mainStore = useMainStore()
const snapshotCursor = this.snapshotCursor - 1
const snapshots: Snapshot[] = await snapshotDB.snapshots.orderBy('id').toArray()
const snapshot = snapshots[snapshotCursor]
const { index, slides } = snapshot
const slideIndex = index > slides.length - 1 ? slides.length - 1 : index
slidesStore.setSlides(slides)
slidesStore.updateSlideIndex(slideIndex)
this.setSnapshotCursor(snapshotCursor)
mainStore.setActiveElementIdList([])
},
async reDo() {
if (this.snapshotCursor >= this.snapshotLength - 1) return
const slidesStore = useSlidesStore()
const mainStore = useMainStore()
const snapshotCursor = this.snapshotCursor + 1
const snapshots: Snapshot[] = await snapshotDB.snapshots.orderBy('id').toArray()
const snapshot = snapshots[snapshotCursor]
const { index, slides } = snapshot
const slideIndex = index > slides.length - 1 ? slides.length - 1 : index
slidesStore.setSlides(slides)
slidesStore.updateSlideIndex(slideIndex)
this.setSnapshotCursor(snapshotCursor)
mainStore.setActiveElementIdList([])
},
},
})

View File

@ -1,67 +0,0 @@
import { Slide, SlideTheme } from '@/types/slides'
import { CreatingElement } from '@/types/edit'
import { ToolbarState } from '@/types/toolbar'
import { slides } from '@/mocks/slides'
import { theme } from '@/mocks/theme'
import { SYS_FONTS } from '@/configs/font'
import { TextAttrs, defaultRichTextAttrs } from '@/utils/prosemirror/utils'
export interface State {
activeElementIdList: string[];
handleElementId: string;
activeGroupElementId: string;
canvasPercentage: number;
canvasScale: number;
thumbnailsFocus: boolean;
editorAreaFocus: boolean;
disableHotkeys: boolean;
showGridLines: boolean;
creatingElement: CreatingElement | null;
availableFonts: typeof SYS_FONTS;
toolbarState: ToolbarState;
theme: SlideTheme;
viewportRatio: number;
slides: Slide[];
slideIndex: number;
selectedSlidesIndex: number[];
snapshotCursor: number;
snapshotLength: number;
ctrlKeyState: boolean;
shiftKeyState: boolean;
screening: boolean;
clipingImageElementId: string;
richTextAttrs: TextAttrs;
selectedTableCells: string[];
isScaling: boolean;
editingShapeElementId: string;
}
export const state: State = {
activeElementIdList: [], // 被选中的元素ID集合包含 handleElementId
handleElementId: '', // 正在操作的元素ID
activeGroupElementId: '', // 组合元素成员中被选中可独立操作的元素ID
canvasPercentage: 90, // 画布可视区域百分比
canvasScale: 1, // 画布缩放比例基于宽度1000px
thumbnailsFocus: false, // 左侧导航缩略图区域聚焦
editorAreaFocus: false, // 编辑区域聚焦
disableHotkeys: false, // 禁用快捷键
showGridLines: false, // 显示网格线
creatingElement: null, // 正在插入的元素信息,需要绘制插入的元素需要(文字、形状、线条)
availableFonts: [], // 当前环境可用字体
toolbarState: 'slideDesign', // 右侧工具栏状态
viewportRatio: 0.5625, // 可是区域比例默认16:9
theme: theme, // 主题样式
slides: slides, // 幻灯片页面数据
slideIndex: 0, // 当前页面索引
selectedSlidesIndex: [], // 当前被选中的页面索引集合
snapshotCursor: -1, // 历史快照指针
snapshotLength: 0, // 历史快照长度
ctrlKeyState: false, // ctrl键按下状态
shiftKeyState: false, // shift键按下状态
screening: false, // 是否进入放映状态
clipingImageElementId: '', // 当前正在裁剪的图片ID
richTextAttrs: defaultRichTextAttrs, // 富文本状态
selectedTableCells: [], // 选中的表格单元格
isScaling: false, // 正在进行元素缩放
editingShapeElementId: '', // 当前正处在编辑文字状态的形状ID
}

View File

@ -545,6 +545,9 @@ export interface SlideBackground {
gradientRotate?: number;
}
export type TurningMode = 'no' | 'fade' | 'slideX' | 'slideY'
/**
*
*
@ -566,7 +569,7 @@ export interface Slide {
remark?: string;
background?: SlideBackground;
animations?: PPTAnimation[];
turningMode?: 'no' | 'fade' | 'slideX' | 'slideY';
turningMode?: TurningMode;
}
/**

View File

@ -1,11 +1,11 @@
export type ToolbarState = 'symbol' | 'elAnimation' | 'elStyle' | 'elPosition' | 'slideDesign' | 'slideAnimation' | 'multiPosition'
export const ToolbarStates = {
SYMBOL: 'symbol',
EL_ANIMATION: 'elAnimation',
EL_STYLE: 'elStyle',
EL_POSITION: 'elPosition',
SLIDE_DESIGN: 'slideDesign',
SLIDE_ANIMATION: 'slideAnimation',
MULTI_POSITION: 'multiPosition',
export const enum ToolbarStates {
SYMBOL = 'symbol',
EL_ANIMATION = 'elAnimation',
EL_STYLE = 'elStyle',
EL_POSITION = 'elPosition',
SLIDE_DESIGN = 'slideDesign',
SLIDE_ANIMATION = 'slideAnimation',
MULTI_POSITION = 'multiPosition',
}

View File

@ -6,7 +6,8 @@
<script lang="ts">
import { computed, PropType, defineComponent } from 'vue'
import { useStore } from '@/store'
import { storeToRefs } from 'pinia'
import { useMainStore } from '@/store'
import { AlignmentLineAxis } from '@/types/edit'
export default defineComponent({
@ -26,8 +27,7 @@ export default defineComponent({
},
},
setup(props) {
const store = useStore()
const canvasScale = computed(() => store.state.canvasScale)
const { canvasScale } = storeToRefs(useMainStore())
// 线
const left = computed(() => props.axis.x * canvasScale.value + 'px')

View File

@ -30,15 +30,16 @@
<script lang="ts">
import { computed, defineComponent, onMounted, reactive, ref } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { storeToRefs } from 'pinia'
import { useMainStore, useKeyboardStore } from '@/store'
export default defineComponent({
name: 'element-create-selection',
emits: ['created'],
setup(props, { emit }) {
const store = useStore()
const ctrlOrShiftKeyActive = computed<boolean>(() => store.getters.ctrlOrShiftKeyActive)
const creatingElement = computed(() => store.state.creatingElement)
const mainStore = useMainStore()
const { creatingElement } = storeToRefs(mainStore)
const { ctrlOrShiftKeyActive } = storeToRefs(useKeyboardStore())
const start = ref<[number, number]>()
const end = ref<[number, number]>()
@ -107,7 +108,7 @@ export default defineComponent({
document.onmouseup = null
if (e.button === 2) {
setTimeout(() => store.commit(MutationTypes.SET_CREATING_ELEMENT, null), 0)
setTimeout(() => mainStore.setCreatingElement(null), 0)
return
}

View File

@ -16,17 +16,18 @@
<script lang="ts">
import { defineComponent, computed } from 'vue'
import tinycolor from 'tinycolor2'
import { useStore } from '@/store'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store'
import { VIEWPORT_SIZE } from '@/configs/canvas'
import { SlideBackground } from '@/types/slides'
export default defineComponent({
name: 'grid-lines',
setup() {
const store = useStore()
const canvasScale = computed(() => store.state.canvasScale)
const viewportRatio = computed(() => store.state.viewportRatio)
const background = computed<SlideBackground | undefined>(() => store.getters.currentSlide?.background)
const { canvasScale } = storeToRefs(useMainStore())
const { currentSlide, viewportRatio } = storeToRefs(useSlidesStore())
const background = computed<SlideBackground | undefined>(() => currentSlide.value?.background)
// 线
const gridColor = computed(() => {

View File

@ -10,17 +10,16 @@
</template>
<script lang="ts">
import { computed, defineComponent, onMounted, ref } from 'vue'
import { useStore } from '@/store'
import { PPTElement } from '@/types/slides'
import { defineComponent, onMounted, ref } from 'vue'
import { storeToRefs } from 'pinia'
import { useMainStore } from '@/store'
import useLink from '@/hooks/useLink'
export default defineComponent({
name: 'link-dialog',
emits: ['close'],
setup(props, { emit }) {
const store = useStore()
const handleElement = computed<PPTElement | null>(() => store.getters.handleElement)
const { handleElement } = storeToRefs(useMainStore())
const link = ref('')

View File

@ -28,8 +28,8 @@
<script lang="ts">
import { computed, defineComponent, PropType } from 'vue'
import { useStore } from '@/store'
import { storeToRefs } from 'pinia'
import { useMainStore } from '@/store'
import { PPTShapeElement, PPTVideoElement, PPTLatexElement } from '@/types/slides'
import { OperateResizeHandler } from '@/types/edit'
import useCommonOperate from '../hooks/useCommonOperate'
@ -67,8 +67,7 @@ export default defineComponent({
},
},
setup(props) {
const store = useStore()
const canvasScale = computed(() => store.state.canvasScale)
const { canvasScale } = storeToRefs(useMainStore())
const scaleWidth = computed(() => props.elementInfo.width * canvasScale.value)
const scaleHeight = computed(() => props.elementInfo.height * canvasScale.value)

View File

@ -28,7 +28,8 @@
<script lang="ts">
import { computed, defineComponent, PropType } from 'vue'
import { useStore } from '@/store'
import { storeToRefs } from 'pinia'
import { useMainStore } from '@/store'
import { PPTImageElement } from '@/types/slides'
import { OperateResizeHandler } from '@/types/edit'
import useCommonOperate from '../hooks/useCommonOperate'
@ -64,9 +65,8 @@ export default defineComponent({
},
},
setup(props) {
const store = useStore()
const canvasScale = computed(() => store.state.canvasScale)
const clipingImageElementId = computed(() => store.state.clipingImageElementId)
const { canvasScale, clipingImageElementId } = storeToRefs(useMainStore())
const isCliping = computed(() => clipingImageElementId.value === props.elementInfo.id)
const scaleWidth = computed(() => props.elementInfo.width * canvasScale.value)

View File

@ -15,8 +15,8 @@
<script lang="ts">
import { computed, defineComponent, PropType } from 'vue'
import { useStore } from '@/store'
import { storeToRefs } from 'pinia'
import { useMainStore } from '@/store'
import { PPTLineElement } from '@/types/slides'
import { OperateLineHandler, OperateLineHandlers } from '@/types/edit'
@ -43,8 +43,7 @@ export default defineComponent({
},
},
setup(props) {
const store = useStore()
const canvasScale = computed(() => store.state.canvasScale)
const { canvasScale } = storeToRefs(useMainStore())
const resizeHandlers = computed(() => {
const handlers = [

View File

@ -10,8 +10,9 @@
</template>
<script lang="ts">
import { computed, defineComponent, PropType } from 'vue'
import { useStore } from '@/store'
import { defineComponent, PropType } from 'vue'
import { storeToRefs } from 'pinia'
import { useMainStore } from '@/store'
import { PPTElement } from '@/types/slides'
import useLink from '@/hooks/useLink'
@ -28,8 +29,7 @@ export default defineComponent({
},
},
setup() {
const store = useStore()
const canvasScale = computed(() => store.state.canvasScale)
const { canvasScale } = storeToRefs(useMainStore())
const { removeLink } = useLink()

View File

@ -22,7 +22,8 @@
<script lang="ts">
import { computed, defineComponent, reactive, PropType, watchEffect, toRefs } from 'vue'
import { useStore } from '@/store'
import { storeToRefs } from 'pinia'
import { useMainStore } from '@/store'
import { PPTElement } from '@/types/slides'
import { getElementListRange } from '@/utils/element'
import { OperateResizeHandler, MultiSelectRange } from '@/types/edit'
@ -48,9 +49,8 @@ export default defineComponent({
},
},
setup(props) {
const store = useStore()
const activeElementIdList = computed(() => store.state.activeElementIdList)
const canvasScale = computed(() => store.state.canvasScale)
const { activeElementIdList, canvasScale } = storeToRefs(useMainStore())
const localActiveElementList = computed(() => props.elementList.filter(el => activeElementIdList.value.includes(el.id)))
const range = reactive({

View File

@ -28,8 +28,8 @@
<script lang="ts">
import { computed, defineComponent, PropType } from 'vue'
import { useStore } from '@/store'
import { storeToRefs } from 'pinia'
import { useMainStore } from '@/store'
import { PPTShapeElement } from '@/types/slides'
import { OperateResizeHandler } from '@/types/edit'
import useCommonOperate from '../hooks/useCommonOperate'
@ -65,8 +65,7 @@ export default defineComponent({
},
},
setup(props) {
const store = useStore()
const canvasScale = computed(() => store.state.canvasScale)
const { canvasScale } = storeToRefs(useMainStore())
const scaleWidth = computed(() => props.elementInfo.width * canvasScale.value)
const scaleHeight = computed(() => props.elementInfo.height * canvasScale.value)

View File

@ -28,8 +28,8 @@
<script lang="ts">
import { computed, defineComponent, PropType } from 'vue'
import { useStore } from '@/store'
import { storeToRefs } from 'pinia'
import { useMainStore } from '@/store'
import { PPTTableElement } from '@/types/slides'
import { OperateResizeHandler } from '@/types/edit'
import useCommonOperate from '../hooks/useCommonOperate'
@ -65,8 +65,7 @@ export default defineComponent({
},
},
setup(props) {
const store = useStore()
const canvasScale = computed(() => store.state.canvasScale)
const { canvasScale } = storeToRefs(useMainStore())
const outlineWidth = computed(() => props.elementInfo.outline.width || 1)

View File

@ -28,8 +28,8 @@
<script lang="ts">
import { computed, defineComponent, PropType } from 'vue'
import { useStore } from '@/store'
import { storeToRefs } from 'pinia'
import { useMainStore } from '@/store'
import { PPTTextElement } from '@/types/slides'
import { OperateResizeHandler } from '@/types/edit'
import useCommonOperate from '../hooks/useCommonOperate'
@ -65,8 +65,7 @@ export default defineComponent({
},
},
setup(props) {
const store = useStore()
const canvasScale = computed(() => store.state.canvasScale)
const { canvasScale } = storeToRefs(useMainStore())
const scaleWidth = computed(() => props.elementInfo.width * canvasScale.value)
const scaleHeight = computed(() => props.elementInfo.height * canvasScale.value)

View File

@ -37,8 +37,9 @@
<script lang="ts">
import { defineComponent, PropType, computed } from 'vue'
import { useStore } from '@/store'
import { ElementTypes, PPTElement, Slide } from '@/types/slides'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store'
import { ElementTypes, PPTElement } from '@/types/slides'
import { OperateLineHandler, OperateResizeHandler } from '@/types/edit'
import ImageElementOperate from './ImageElementOperate.vue'
@ -93,10 +94,8 @@ export default defineComponent({
},
},
setup(props) {
const store = useStore()
const canvasScale = computed(() => store.state.canvasScale)
const toolbarState = computed(() => store.state.toolbarState)
const currentSlide = computed<Slide>(() => store.getters.currentSlide)
const { canvasScale, toolbarState } = storeToRefs(useMainStore())
const { currentSlide } = storeToRefs(useSlidesStore())
const currentOperateComponent = computed(() => {
const elementTypeMap = {

View File

@ -9,7 +9,8 @@
<script lang="ts">
import { computed, defineComponent } from 'vue'
import { useStore } from '@/store'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store'
import { SlideBackground } from '@/types/slides'
import GridLines from './GridLines.vue'
import useSlideBackgroundStyle from '@/hooks/useSlideBackgroundStyle'
@ -20,9 +21,9 @@ export default defineComponent({
GridLines,
},
setup() {
const store = useStore()
const showGridLines = computed(() => store.state.showGridLines)
const background = computed<SlideBackground | undefined>(() => store.getters.currentSlide?.background)
const { showGridLines } = storeToRefs(useMainStore())
const { currentSlide } = storeToRefs(useSlidesStore())
const background = computed<SlideBackground | undefined>(() => currentSlide.value?.background)
const { backgroundStyle } = useSlideBackgroundStyle(background)

View File

@ -1,5 +1,6 @@
import { Ref, computed } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { Ref } from 'vue'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store'
import { PPTElement } from '@/types/slides'
import { AlignmentLineProps } from '@/types/edit'
import { VIEWPORT_SIZE } from '@/configs/canvas'
@ -10,11 +11,9 @@ export default (
elementList: Ref<PPTElement[]>,
alignmentLines: Ref<AlignmentLineProps[]>,
) => {
const store = useStore()
const activeElementIdList = computed(() => store.state.activeElementIdList)
const activeGroupElementId = computed(() => store.state.activeGroupElementId)
const canvasScale = computed(() => store.state.canvasScale)
const viewportRatio = computed(() => store.state.viewportRatio)
const slidesStore = useSlidesStore()
const { activeElementIdList, activeGroupElementId, canvasScale } = storeToRefs(useMainStore())
const { viewportRatio } = storeToRefs(slidesStore)
const { addHistorySnapshot } = useHistorySnapshot()
@ -296,7 +295,7 @@ export default (
if (startPageX === currentPageX && startPageY === currentPageY) return
store.commit(MutationTypes.UPDATE_SLIDE, { elements: elementList.value })
slidesStore.updateSlide({ elements: elementList.value })
addHistorySnapshot()
}
}

View File

@ -1,5 +1,6 @@
import { Ref, computed } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { Ref } from 'vue'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store'
import { PPTElement, PPTLineElement } from '@/types/slides'
import { OperateLineHandler, OperateLineHandlers } from '@/types/edit'
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
@ -10,8 +11,8 @@ interface AdsorptionPoint {
}
export default (elementList: Ref<PPTElement[]>) => {
const store = useStore()
const canvasScale = computed(() => store.state.canvasScale)
const slidesStore = useSlidesStore()
const { canvasScale } = storeToRefs(useMainStore())
const { addHistorySnapshot } = useHistorySnapshot()
@ -180,7 +181,7 @@ export default (elementList: Ref<PPTElement[]>) => {
if (startPageX === currentPageX && startPageY === currentPageY) return
store.commit(MutationTypes.UPDATE_SLIDE, { elements: elementList.value })
slidesStore.updateSlide({ elements: elementList.value })
addHistorySnapshot()
}
}

View File

@ -1,12 +1,12 @@
import { computed, onMounted, onUnmounted, Ref } from 'vue'
import { useStore } from '@/store'
import { onMounted, onUnmounted, Ref } from 'vue'
import { storeToRefs } from 'pinia'
import { useMainStore } from '@/store'
import { getImageDataURL } from '@/utils/image'
import { parseText2Paragraphs } from '@/utils/textParser'
import useCreateElement from '@/hooks/useCreateElement'
export default (elementRef: Ref<HTMLElement | undefined>) => {
const store = useStore()
const disableHotkeys = computed(() => store.state.disableHotkeys)
const { disableHotkeys } = storeToRefs(useMainStore())
const { createImageElement, createTextElement } = useCreateElement()

View File

@ -1,12 +1,12 @@
import { computed, Ref } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { Ref } from 'vue'
import { storeToRefs } from 'pinia'
import { useMainStore } from '@/store'
import { CreateElementSelectionData, CreatingLineElement, CreatingShapeElement } from '@/types/edit'
import useCreateElement from '@/hooks/useCreateElement'
export default (viewportRef: Ref<HTMLElement | undefined>) => {
const store = useStore()
const canvasScale = computed(() => store.state.canvasScale)
const creatingElement = computed(() => store.state.creatingElement)
const mainStore = useMainStore()
const { canvasScale, creatingElement } = storeToRefs(mainStore)
// 通过鼠标框选时的起点和终点,计算选区的位置大小
const formatCreateSelection = (selectionData: CreateElementSelectionData) => {
@ -85,7 +85,7 @@ export default (viewportRef: Ref<HTMLElement | undefined>) => {
const position = formatCreateSelectionForLine(selectionData)
position && createLineElement(position, (creatingElement.value as CreatingLineElement).data)
}
store.commit(MutationTypes.SET_CREATING_ELEMENT, null)
mainStore.setCreatingElement(null)
}
return {

View File

@ -1,11 +1,12 @@
import { Ref, reactive, computed } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { Ref, reactive } from 'vue'
import { storeToRefs } from 'pinia'
import { useMainStore } from '@/store'
import { PPTElement } from '@/types/slides'
import { getElementRange } from '@/utils/element'
export default (elementList: Ref<PPTElement[]>, viewportRef: Ref<HTMLElement | undefined>) => {
const store = useStore()
const canvasScale = computed(() => store.state.canvasScale)
const mainStore = useMainStore()
const { canvasScale } = storeToRefs(mainStore)
const mouseSelectionState = reactive({
isShow: false,
@ -127,7 +128,7 @@ export default (elementList: Ref<PPTElement[]>, viewportRef: Ref<HTMLElement | u
return true
})
const inRangeElementIdList = inRangeElementList.map(inRangeElement => inRangeElement.id)
if (inRangeElementIdList.length) store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, inRangeElementIdList)
mainStore.setActiveElementIdList(inRangeElementIdList)
mouseSelectionState.isShow = false
}

View File

@ -1,5 +1,6 @@
import { Ref, computed } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { Ref } from 'vue'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store'
import { PPTElement, PPTTextElement, PPTImageElement, PPTShapeElement } from '@/types/slides'
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
@ -15,8 +16,8 @@ const getAngleFromCoordinate = (x: number, y: number) => {
}
export default (elementList: Ref<PPTElement[]>, viewportRef: Ref<HTMLElement | undefined>) => {
const store = useStore()
const canvasScale = computed(() => store.state.canvasScale)
const slidesStore = useSlidesStore()
const { canvasScale } = storeToRefs(useMainStore())
const { addHistorySnapshot } = useHistorySnapshot()
@ -71,7 +72,7 @@ export default (elementList: Ref<PPTElement[]>, viewportRef: Ref<HTMLElement | u
if (elOriginRotate === angle) return
store.commit(MutationTypes.UPDATE_SLIDE, { elements: elementList.value })
slidesStore.updateSlide({ elements: elementList.value })
addHistorySnapshot()
}
}

View File

@ -1,5 +1,6 @@
import { computed, Ref } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { Ref } from 'vue'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore, useKeyboardStore } from '@/store'
import { PPTElement, PPTImageElement, PPTLineElement, PPTShapeElement } from '@/types/slides'
import { OperateResizeHandlers, AlignmentLineProps, MultiSelectRange } from '@/types/edit'
import { VIEWPORT_SIZE } from '@/configs/canvas'
@ -95,19 +96,18 @@ export default (
elementList: Ref<PPTElement[]>,
alignmentLines: Ref<AlignmentLineProps[]>,
) => {
const store = useStore()
const activeElementIdList = computed(() => store.state.activeElementIdList)
const activeGroupElementId = computed(() => store.state.activeGroupElementId)
const canvasScale = computed(() => store.state.canvasScale)
const viewportRatio = computed(() => store.state.viewportRatio)
const ctrlOrShiftKeyActive = computed<boolean>(() => store.getters.ctrlOrShiftKeyActive)
const mainStore = useMainStore()
const slidesStore = useSlidesStore()
const { activeElementIdList, activeGroupElementId, canvasScale } = storeToRefs(mainStore)
const { viewportRatio } = storeToRefs(slidesStore)
const { ctrlOrShiftKeyActive } = storeToRefs(useKeyboardStore())
const { addHistorySnapshot } = useHistorySnapshot()
// 缩放元素
const scaleElement = (e: MouseEvent, element: Exclude<PPTElement, PPTLineElement>, command: OperateResizeHandlers) => {
let isMouseDown = true
store.commit(MutationTypes.SET_SCALING_STATE, true)
mainStore.setScalingState(true)
const elOriginLeft = element.left
const elOriginTop = element.top
@ -404,8 +404,8 @@ export default (
if (startPageX === e.pageX && startPageY === e.pageY) return
store.commit(MutationTypes.UPDATE_SLIDE, { elements: elementList.value })
store.commit(MutationTypes.SET_SCALING_STATE, false)
slidesStore.updateSlide({ elements: elementList.value })
mainStore.setScalingState(false)
addHistorySnapshot()
}
@ -509,7 +509,7 @@ export default (
if (startPageX === e.pageX && startPageY === e.pageY) return
store.commit(MutationTypes.UPDATE_SLIDE, { elements: elementList.value })
slidesStore.updateSlide({ elements: elementList.value })
addHistorySnapshot()
}
}

View File

@ -1,23 +1,21 @@
import { Ref, computed } from 'vue'
import { Ref } from 'vue'
import { uniq } from 'lodash'
import { MutationTypes, useStore } from '@/store'
import { storeToRefs } from 'pinia'
import { useMainStore, useKeyboardStore } from '@/store'
import { PPTElement } from '@/types/slides'
export default (
elementList: Ref<PPTElement[]>,
moveElement: (e: MouseEvent, element: PPTElement) => void,
) => {
const store = useStore()
const activeElementIdList = computed(() => store.state.activeElementIdList)
const handleElementId = computed(() => store.state.handleElementId)
const activeGroupElementId = computed(() => store.state.activeGroupElementId)
const editorAreaFocus = computed(() => store.state.editorAreaFocus)
const ctrlOrShiftKeyActive = computed<boolean>(() => store.getters.ctrlOrShiftKeyActive)
const mainStore = useMainStore()
const { activeElementIdList, activeGroupElementId, handleElementId, editorAreaFocus } = storeToRefs(mainStore)
const { ctrlOrShiftKeyActive } = storeToRefs(useKeyboardStore())
// 选中元素
// startMove 表示是否需要再选中操作后进入到开始移动的状态
const selectElement = (e: MouseEvent, element: PPTElement, startMove = true) => {
if (!editorAreaFocus.value) store.commit(MutationTypes.SET_EDITORAREA_FOCUS, true)
if (!editorAreaFocus.value) mainStore.setEditorareaFocus(true)
// 如果目标元素当前未被选中,则将他设为选中状态
// 此时如果按下Ctrl键或Shift键则进入多选状态将当前已选中的元素和目标元素一起设置为选中状态否则仅将目标元素设置为选中状态
@ -38,8 +36,8 @@ export default (
newActiveIdList = [...newActiveIdList, ...groupMembersId]
}
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, uniq(newActiveIdList))
store.commit(MutationTypes.SET_HANDLE_ELEMENT_ID, element.id)
mainStore.setActiveElementIdList(uniq(newActiveIdList))
mainStore.setHandleElementId(element.id)
}
// 如果目标元素已被选中且按下了Ctrl键或Shift键则取消其被选中状态
@ -60,13 +58,13 @@ export default (
}
if (newActiveIdList.length > 0) {
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, newActiveIdList)
mainStore.setActiveElementIdList(newActiveIdList)
}
}
// 如果目标元素已被选中,同时目标元素不是当前操作元素,则将其设置为当前操作元素
else if (handleElementId.value !== element.id) {
store.commit(MutationTypes.SET_HANDLE_ELEMENT_ID, element.id)
mainStore.setHandleElementId(element.id)
}
// 如果目标元素已被选中,同时也是当前操作元素,那么当目标元素在该状态下再次被点击时,将被设置为多选元素中的激活成员
@ -79,7 +77,7 @@ export default (
const currentPageY = e.pageY
if (startPageX === currentPageX && startPageY === currentPageY) {
store.commit(MutationTypes.SET_ACTIVE_GROUP_ELEMENT_ID, element.id)
mainStore.setActiveGroupElementId(element.id)
;(e.target as HTMLElement).onmouseup = null
}
}
@ -92,7 +90,7 @@ export default (
const selectAllElement = () => {
const unlockedElements = elementList.value.filter(el => !el.lock)
const newActiveElementIdList = unlockedElements.map(el => el.id)
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, newActiveElementIdList)
mainStore.setActiveElementIdList(newActiveElementIdList)
}
return {

View File

@ -1,14 +1,15 @@
import { ref, computed, onMounted, onUnmounted, Ref, watch } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store'
import { VIEWPORT_SIZE } from '@/configs/canvas'
export default (canvasRef: Ref<HTMLElement | undefined>) => {
const viewportLeft = ref(0)
const viewportTop = ref(0)
const store = useStore()
const canvasPercentage = computed(() => store.state.canvasPercentage)
const viewportRatio = computed(() => store.state.viewportRatio)
const mainStore = useMainStore()
const { canvasPercentage } = storeToRefs(mainStore)
const { viewportRatio } = storeToRefs(useSlidesStore())
// 计算画布可视区域的位置
const setViewportPosition = () => {
@ -18,13 +19,13 @@ export default (canvasRef: Ref<HTMLElement | undefined>) => {
if (canvasHeight / canvasWidth > viewportRatio.value) {
const viewportActualWidth = canvasWidth * (canvasPercentage.value / 100)
store.commit(MutationTypes.SET_CANVAS_SCALE, viewportActualWidth / VIEWPORT_SIZE)
mainStore.setCanvasScale(viewportActualWidth / VIEWPORT_SIZE)
viewportLeft.value = (canvasWidth - viewportActualWidth) / 2
viewportTop.value = (canvasHeight - viewportActualWidth * viewportRatio.value) / 2
}
else {
const viewportActualHeight = canvasHeight * (canvasPercentage.value / 100)
store.commit(MutationTypes.SET_CANVAS_SCALE, viewportActualHeight / (VIEWPORT_SIZE * viewportRatio.value))
mainStore.setCanvasScale(viewportActualHeight / (VIEWPORT_SIZE * viewportRatio.value))
viewportLeft.value = (canvasWidth - viewportActualHeight / viewportRatio.value) / 2
viewportTop.value = (canvasHeight - viewportActualHeight) / 2
}

View File

@ -87,11 +87,12 @@
</template>
<script lang="ts">
import { computed, defineComponent, provide, ref, watch, watchEffect } from 'vue'
import { defineComponent, provide, ref, watch, watchEffect } from 'vue'
import { throttle } from 'lodash'
import { MutationTypes, useStore } from '@/store'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore, useKeyboardStore } from '@/store'
import { ContextmenuItem } from '@/components/Contextmenu/types'
import { PPTElement, Slide } from '@/types/slides'
import { PPTElement } from '@/types/slides'
import { AlignmentLineProps } from '@/types/edit'
import { removeAllRanges } from '@/utils/selection'
import { KEYS } from '@/configs/hotkey'
@ -135,14 +136,18 @@ export default defineComponent({
LinkDialog,
},
setup() {
const store = useStore()
const activeElementIdList = computed(() => store.state.activeElementIdList)
const handleElementId = computed(() => store.state.handleElementId)
const activeGroupElementId = computed(() => store.state.activeGroupElementId)
const editorAreaFocus = computed(() => store.state.editorAreaFocus)
const ctrlKeyState = computed(() => store.state.ctrlKeyState)
const ctrlOrShiftKeyActive = computed<boolean>(() => store.getters.ctrlOrShiftKeyActive)
const mainStore = useMainStore()
const {
activeElementIdList,
activeGroupElementId,
handleElementId,
editorAreaFocus,
showGridLines,
creatingElement,
canvasScale,
} = storeToRefs(mainStore)
const { currentSlide } = storeToRefs(useSlidesStore())
const { ctrlKeyState, ctrlOrShiftKeyActive } = storeToRefs(useKeyboardStore())
const viewportRef = ref<HTMLElement>()
const alignmentLines = ref<AlignmentLineProps[]>([])
@ -151,10 +156,9 @@ export default defineComponent({
const openLinkDialog = () => linkDialogVisible.value = true
watch(handleElementId, () => {
store.commit(MutationTypes.SET_ACTIVE_GROUP_ELEMENT_ID, '')
mainStore.setActiveGroupElementId('')
})
const currentSlide = computed<Slide>(() => store.getters.currentSlide)
const elementList = ref<PPTElement[]>([])
const setLocalElementList = () => {
elementList.value = currentSlide.value ? JSON.parse(JSON.stringify(currentSlide.value.elements)) : []
@ -162,7 +166,6 @@ export default defineComponent({
watchEffect(setLocalElementList)
const canvasRef = ref<HTMLElement>()
const canvasScale = computed(() => store.state.canvasScale)
const { viewportStyles } = useViewportSize(canvasRef)
useDropImageOrText(canvasRef)
@ -183,15 +186,15 @@ export default defineComponent({
//
const handleClickBlankArea = (e: MouseEvent) => {
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])
mainStore.setActiveElementIdList([])
if (!ctrlOrShiftKeyActive.value) updateMouseSelection(e)
if (!editorAreaFocus.value) store.commit(MutationTypes.SET_EDITORAREA_FOCUS, true)
if (!editorAreaFocus.value) mainStore.setEditorareaFocus(true)
removeAllRanges()
}
//
const removeEditorAreaFocus = () => {
if (editorAreaFocus.value) store.commit(MutationTypes.SET_EDITORAREA_FOCUS, false)
if (editorAreaFocus.value) mainStore.setEditorareaFocus(false)
}
//
@ -215,13 +218,11 @@ export default defineComponent({
}
// 线
const showGridLines = computed(() => store.state.showGridLines)
const toggleGridLines = () => {
store.commit(MutationTypes.SET_GRID_LINES_STATE, !showGridLines.value)
mainStore.setGridLinesState(!showGridLines.value)
}
//
const creatingElement = computed(() => store.state.creatingElement)
const { insertElementFromCreateSelection } = useInsertFromCreateSelection(viewportRef)
const contextmenus = (): ContextmenuItem[] => {

View File

@ -95,7 +95,8 @@
<script lang="ts">
import { defineComponent, computed, ref } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { storeToRefs } from 'pinia'
import { useMainStore, useSnapshotStore } from '@/store'
import { getImageDataURL } from '@/utils/image'
import { ShapePoolItem } from '@/configs/shapes'
import { LinePoolItem } from '@/configs/lines'
@ -121,10 +122,9 @@ export default defineComponent({
LaTeXEditor,
},
setup() {
const store = useStore()
const canvasScale = computed(() => store.state.canvasScale)
const canUndo = computed(() => store.getters.canUndo)
const canRedo = computed(() => store.getters.canRedo)
const mainStore = useMainStore()
const { canvasScale } = storeToRefs(mainStore)
const { canUndo, canRedo } = storeToRefs(useSnapshotStore())
const canvasScalePercentage = computed(() => parseInt(canvasScale.value * 100 + '') + '%')
@ -148,15 +148,14 @@ export default defineComponent({
//
const drawText = () => {
store.commit(MutationTypes.SET_CREATING_ELEMENT, {
mainStore.setCreatingElement({
type: 'text',
data: null,
})
}
//
const drawShape = (shape: ShapePoolItem) => {
store.commit(MutationTypes.SET_CREATING_ELEMENT, {
mainStore.setCreatingElement({
type: 'shape',
data: shape,
})
@ -165,7 +164,7 @@ export default defineComponent({
// 线
const drawLine = (line: LinePoolItem) => {
store.commit(MutationTypes.SET_CREATING_ELEMENT, {
mainStore.setCreatingElement({
type: 'line',
data: line,
})

View File

@ -68,8 +68,9 @@
</template>
<script lang="ts">
import { computed, defineComponent, ref } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { defineComponent, ref } from 'vue'
import { storeToRefs } from 'pinia'
import { useMainStore } from '@/store'
import useScreening from '@/hooks/useScreening'
import useSlideHandler from '@/hooks/useSlideHandler'
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
@ -83,16 +84,16 @@ export default defineComponent({
HotkeyDoc,
},
setup() {
const store = useStore()
const mainStore = useMainStore()
const { showGridLines } = storeToRefs(mainStore)
const { enterScreening, enterScreeningFromStart } = useScreening()
const { createSlide, deleteSlide, resetSlides } = useSlideHandler()
const { redo, undo } = useHistorySnapshot()
const { exporting, exportJSON, exportPPTX } = useExport()
const showGridLines = computed(() => store.state.showGridLines)
const toggleGridLines = () => {
store.commit(MutationTypes.SET_GRID_LINES_STATE, !showGridLines.value)
mainStore.setGridLinesState(!showGridLines.value)
}
const hotkeyDrawerVisible = ref(false)

View File

@ -14,8 +14,8 @@
<script lang="ts">
import { computed, defineComponent } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { Slide } from '@/types/slides'
import { storeToRefs } from 'pinia'
import { useSlidesStore } from '@/store'
export default defineComponent({
name: 'remark',
@ -27,13 +27,14 @@ export default defineComponent({
},
},
setup(props, { emit }) {
const store = useStore()
const currentSlide = computed<Slide>(() => store.getters.currentSlide)
const slidesStore = useSlidesStore()
const { currentSlide } = storeToRefs(slidesStore)
const remark = computed(() => currentSlide.value?.remark || '')
const handleInput = (e: InputEvent) => {
const value = (e.target as HTMLTextAreaElement).value
store.commit(MutationTypes.UPDATE_SLIDE, { remark: value })
slidesStore.updateSlide({ remark: value })
}
const resize = (e: MouseEvent) => {

View File

@ -12,8 +12,9 @@
</template>
<script lang="ts">
import { computed, defineComponent } from 'vue'
import { useStore } from '@/store'
import { defineComponent } from 'vue'
import { storeToRefs } from 'pinia'
import { useSlidesStore } from '@/store'
import { Slide } from '@/types/slides'
import ThumbnailSlide from '@/views/components/ThumbnailSlide/index.vue'
@ -25,8 +26,7 @@ export default defineComponent({
ThumbnailSlide,
},
setup(props, { emit }) {
const store = useStore()
const layouts = computed<Slide[]>(() => store.getters.layouts)
const { layouts } = storeToRefs(useSlidesStore())
const selectSlideTemplate = (slide: Slide) => {
emit('select', slide)

View File

@ -45,7 +45,8 @@
<script lang="ts">
import { computed, defineComponent, provide, ref } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore, useKeyboardStore } from '@/store'
import { fillDigit } from '@/utils/common'
import { ContextmenuItem } from '@/components/Contextmenu/types'
import { VIEWPORT_SIZE } from '@/configs/canvas'
@ -64,12 +65,14 @@ export default defineComponent({
LayoutPool,
},
setup() {
const store = useStore()
const slides = computed(() => store.state.slides)
const slideIndex = computed(() => store.state.slideIndex)
const ctrlKeyState = computed(() => store.state.ctrlKeyState)
const shiftKeyState = computed(() => store.state.shiftKeyState)
const selectedSlidesIndex = computed(() => [...store.state.selectedSlidesIndex, slideIndex.value])
const mainStore = useMainStore()
const slidesStore = useSlidesStore()
const keyboardStore = useKeyboardStore()
const { selectedSlidesIndex: _selectedSlidesIndex, thumbnailsFocus } = storeToRefs(mainStore)
const { slides, slideIndex } = storeToRefs(slidesStore)
const { ctrlKeyState, shiftKeyState } = storeToRefs(keyboardStore)
const selectedSlidesIndex = computed(() => [..._selectedSlidesIndex.value, slideIndex.value])
const presetLayoutPopoverVisible = ref(false)
@ -89,10 +92,10 @@ export default defineComponent({
//
const changSlideIndex = (index: number) => {
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, [])
mainStore.setActiveElementIdList([])
if (slideIndex.value === index) return
store.commit(MutationTypes.UPDATE_SLIDE_INDEX, index)
slidesStore.updateSlideIndex(index)
}
//
@ -107,17 +110,17 @@ export default defineComponent({
if (!isMultiSelected) return
const newSelectedSlidesIndex = selectedSlidesIndex.value.filter(item => item !== index)
store.commit(MutationTypes.UPDATE_SELECTED_SLIDES_INDEX, newSelectedSlidesIndex)
mainStore.updateSelectedSlidesIndex(newSelectedSlidesIndex)
changSlideIndex(selectedSlidesIndex.value[0])
}
else {
if (selectedSlidesIndex.value.includes(index)) {
const newSelectedSlidesIndex = selectedSlidesIndex.value.filter(item => item !== index)
store.commit(MutationTypes.UPDATE_SELECTED_SLIDES_INDEX, newSelectedSlidesIndex)
mainStore.updateSelectedSlidesIndex(newSelectedSlidesIndex)
}
else {
const newSelectedSlidesIndex = [...selectedSlidesIndex.value, index]
store.commit(MutationTypes.UPDATE_SELECTED_SLIDES_INDEX, newSelectedSlidesIndex)
mainStore.updateSelectedSlidesIndex(newSelectedSlidesIndex)
changSlideIndex(index)
}
}
@ -136,24 +139,22 @@ export default defineComponent({
const newSelectedSlidesIndex = []
for (let i = minIndex; i <= maxIndex; i++) newSelectedSlidesIndex.push(i)
store.commit(MutationTypes.UPDATE_SELECTED_SLIDES_INDEX, newSelectedSlidesIndex)
mainStore.updateSelectedSlidesIndex(newSelectedSlidesIndex)
changSlideIndex(index)
}
//
else {
store.commit(MutationTypes.UPDATE_SELECTED_SLIDES_INDEX, [])
mainStore.updateSelectedSlidesIndex([])
changSlideIndex(index)
}
}
const thumbnailsFocus = computed(() => store.state.thumbnailsFocus)
//
const setThumbnailsFocus = (focus: boolean) => {
if (thumbnailsFocus.value === focus) return
store.commit(MutationTypes.SET_THUMBNAILS_FOCUS, focus)
mainStore.setThumbnailsFocus(focus)
if (!focus) store.commit(MutationTypes.UPDATE_SELECTED_SLIDES_INDEX, [])
if (!focus) mainStore.updateSelectedSlidesIndex([])
}
//
@ -165,8 +166,8 @@ export default defineComponent({
const _slide = _slides[oldIndex]
_slides.splice(oldIndex, 1)
_slides.splice(newIndex, 0, _slide)
store.commit(MutationTypes.SET_SLIDES, _slides)
store.commit(MutationTypes.UPDATE_SLIDE_INDEX, newIndex)
slidesStore.setSlides(_slides)
slidesStore.updateSlideIndex(newIndex)
}
const { enterScreening } = useScreening()

View File

@ -89,8 +89,9 @@
<script lang="ts">
import { computed, defineComponent, ref } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { PPTAnimation, PPTElement, Slide } from '@/types/slides'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store'
import { PPTAnimation } from '@/types/slides'
import { ANIMATIONS } from '@/configs/animation'
import { ELEMENT_TYPE_ZH } from '@/configs/element'
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
@ -112,10 +113,9 @@ export default defineComponent({
Draggable,
},
setup() {
const store = useStore()
const handleElement = computed<PPTElement>(() => store.getters.handleElement)
const currentSlideAnimations = computed<PPTAnimation[] | null>(() => store.getters.currentSlideAnimations)
const currentSlide = computed<Slide>(() => store.getters.currentSlide)
const slidesStore = useSlidesStore()
const { handleElement, handleElementId } = storeToRefs(useMainStore())
const { currentSlide, currentSlideAnimations } = storeToRefs(slidesStore)
const hoverPreviewAnimation = ref('')
const animationPoolVisible = ref(false)
@ -145,9 +145,8 @@ export default defineComponent({
//
const handleElementAnimation = computed(() => {
if (!handleElement.value) return null
const animations = currentSlideAnimations.value || []
const animation = animations.find(item => item.elId === handleElement.value.id)
const animation = animations.find(item => item.elId === handleElementId.value)
return animation || null
})
@ -160,7 +159,7 @@ export default defineComponent({
//
const deleteAnimation = (elId: string) => {
const animations = (currentSlideAnimations.value as PPTAnimation[]).filter(item => item.elId !== elId)
store.commit(MutationTypes.UPDATE_SLIDE, { animations })
slidesStore.updateSlide({ animations })
addHistorySnapshot()
}
@ -174,7 +173,7 @@ export default defineComponent({
animations.splice(oldIndex, 1)
animations.splice(newIndex, 0, animation)
store.commit(MutationTypes.UPDATE_SLIDE, { animations })
slidesStore.updateSlide({ animations })
addHistorySnapshot()
}
@ -200,17 +199,17 @@ export default defineComponent({
if (!currentSlideAnimations.value) return
const animations = currentSlideAnimations.value.map(item => {
if (item.elId === handleElement.value.id) return { ...item, type }
if (item.elId === handleElementId.value) return { ...item, type }
return item
})
store.commit(MutationTypes.UPDATE_SLIDE, { animations })
slidesStore.updateSlide({ animations })
animationPoolVisible.value = false
addHistorySnapshot()
const animationItem = currentSlideAnimations.value.find(item => item.elId === handleElement.value.id)
const animationItem = currentSlideAnimations.value.find(item => item.elId === handleElementId.value)
const duration = animationItem?.duration || defaultDuration
runAnimation(handleElement.value.id, type, duration)
runAnimation(handleElementId.value, type, duration)
}
//
@ -219,10 +218,10 @@ export default defineComponent({
if (duration < 100 || duration > 5000) return
const animations = currentSlideAnimations.value.map(item => {
if (item.elId === handleElement.value.id) return { ...item, duration }
if (item.elId === handleElementId.value) return { ...item, duration }
return item
})
store.commit(MutationTypes.UPDATE_SLIDE, { animations })
slidesStore.updateSlide({ animations })
addHistorySnapshot()
}
@ -234,15 +233,15 @@ export default defineComponent({
}
const animations: PPTAnimation[] = currentSlideAnimations.value ? JSON.parse(JSON.stringify(currentSlideAnimations.value)) : []
animations.push({
elId: handleElement.value.id,
elId: handleElementId.value,
type,
duration: defaultDuration,
})
store.commit(MutationTypes.UPDATE_SLIDE, { animations })
slidesStore.updateSlide({ animations })
animationPoolVisible.value = false
addHistorySnapshot()
runAnimation(handleElement.value.id, type, defaultDuration)
runAnimation(handleElementId.value, type, defaultDuration)
}
// 500ms

View File

@ -134,8 +134,8 @@
<script lang="ts">
import { computed, defineComponent, ref, watch } from 'vue'
import { round } from 'lodash'
import { MutationTypes, useStore } from '@/store'
import { PPTElement } from '@/types/slides'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store'
import { MIN_SIZE } from '@/configs/element'
import useOrderElement from '@/hooks/useOrderElement'
import useAlignElementToCanvas from '@/hooks/useAlignElementToCanvas'
@ -144,8 +144,8 @@ import useHistorySnapshot from '@/hooks/useHistorySnapshot'
export default defineComponent({
name: 'element-positopn-panel',
setup() {
const store = useStore()
const handleElement = computed<PPTElement>(() => store.getters.handleElement)
const slidesStore = useSlidesStore()
const { handleElement, handleElementId } = storeToRefs(useMainStore())
const left = ref(0)
const top = ref(0)
@ -182,36 +182,36 @@ export default defineComponent({
//
const updateLeft = (value: number) => {
const props = { left: value }
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })
slidesStore.updateElement({ id: handleElementId.value, props })
addHistorySnapshot()
}
const updateTop = (value: number) => {
const props = { top: value }
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })
slidesStore.updateElement({ id: handleElementId.value, props })
addHistorySnapshot()
}
//
const updateWidth = (value: number) => {
const props = { width: value }
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })
slidesStore.updateElement({ id: handleElementId.value, props })
addHistorySnapshot()
}
const updateHeight = (value: number) => {
const props = { height: value }
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })
slidesStore.updateElement({ id: handleElementId.value, props })
addHistorySnapshot()
}
const updateRotate = (value: number) => {
const props = { rotate: value }
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })
slidesStore.updateElement({ id: handleElementId.value, props })
addHistorySnapshot()
}
//
const updateFixedRatio = (value: boolean) => {
const props = { fixedRatio: value }
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })
slidesStore.updateElement({ id: handleElementId.value, props })
addHistorySnapshot()
}
@ -225,7 +225,7 @@ export default defineComponent({
if (_rotate > 180) _rotate = 180
const props = { rotate: _rotate }
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })
slidesStore.updateElement({ id: handleElementId.value, props })
addHistorySnapshot()
}

View File

@ -125,9 +125,10 @@
</template>
<script lang="ts">
import { computed, defineComponent, onUnmounted, ref, watch } from 'vue'
import { defineComponent, onUnmounted, ref, watch } from 'vue'
import { IBarChartOptions, ILineChartOptions, IPieChartOptions } from 'chartist'
import { MutationTypes, useStore } from '@/store'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store'
import { ChartData, PPTChartElement } from '@/types/slides'
import emitter, { EmitterEvents } from '@/utils/emitter'
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
@ -144,9 +145,10 @@ export default defineComponent({
ColorButton,
},
setup() {
const store = useStore()
const handleElement = computed<PPTChartElement>(() => store.getters.handleElement)
const theme = computed(() => store.state.theme)
const mainStore = useMainStore()
const slidesStore = useSlidesStore()
const { handleElement, handleElementId } = storeToRefs(mainStore)
const { theme } = storeToRefs(slidesStore)
const chartDataEditorVisible = ref(false)
@ -189,28 +191,28 @@ export default defineComponent({
legend.value = handleElement.value.legend || ''
}, { deep: true, immediate: true })
const updateElement = (props: Partial<PPTChartElement>) => {
slidesStore.updateElement({ id: handleElementId.value, props })
addHistorySnapshot()
}
//
const updateData = (data: ChartData) => {
chartDataEditorVisible.value = false
const props = { data }
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })
addHistorySnapshot()
updateElement({ data })
}
//
const updateFill = (value: string) => {
const props = { fill: value }
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })
addHistorySnapshot()
updateElement({ fill: value })
}
// 线线线线
const updateOptions = (optionProps: ILineChartOptions & IBarChartOptions & IPieChartOptions) => {
const options = handleElement.value.options || {}
const newOptions = { ...options, ...optionProps }
const props = { options: newOptions }
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })
addHistorySnapshot()
const _handleElement = handleElement.value as PPTChartElement
const newOptions = { ..._handleElement.options, ...optionProps }
updateElement({ options: newOptions })
}
//
@ -218,8 +220,7 @@ export default defineComponent({
const props = {
themeColor: themeColor.value.map((c, i) => i === index ? color : c),
}
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })
addHistorySnapshot()
updateElement(props)
}
//
@ -227,8 +228,7 @@ export default defineComponent({
const props = {
themeColor: [...themeColor.value, theme.value.themeColor],
}
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })
addHistorySnapshot()
updateElement(props)
}
//
@ -236,22 +236,17 @@ export default defineComponent({
const props = {
themeColor: themeColor.value.filter((c, i) => i !== index),
}
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })
addHistorySnapshot()
updateElement(props)
}
//
const updateGridColor = (gridColor: string) => {
const props = { gridColor }
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })
addHistorySnapshot()
updateElement({ gridColor })
}
// /
const updateLegend = (legend: '' | 'top' | 'bottom') => {
const props = { legend }
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })
addHistorySnapshot()
updateElement({ legend })
}
const openDataEditor = () => chartDataEditorVisible.value = true

View File

@ -75,9 +75,10 @@
</template>
<script lang="ts">
import { computed, defineComponent, ref, watch } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { PPTImageElement, Slide } from '@/types/slides'
import { defineComponent, ref, watch } from 'vue'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store'
import { PPTImageElement, SlideBackground } from '@/types/slides'
import { CLIPPATHS } from '@/configs/imageClip'
import { getImageDataURL } from '@/utils/image'
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
@ -148,9 +149,10 @@ export default defineComponent({
ElementFlip,
},
setup() {
const store = useStore()
const handleElement = computed<PPTImageElement>(() => store.getters.handleElement)
const currentSlide = computed<Slide>(() => store.getters.currentSlide)
const mainStore = useMainStore()
const slidesStore = useSlidesStore()
const { handleElement, handleElementId } = storeToRefs(mainStore)
const { currentSlide } = storeToRefs(slidesStore)
const clipPanelVisible = ref(false)
@ -173,28 +175,30 @@ export default defineComponent({
//
const updateFilter = (filter: FilterOption, value: number) => {
const originFilters = handleElement.value.filters || {}
const _handleElement = handleElement.value as PPTImageElement
const originFilters = _handleElement.filters || {}
const filters = { ...originFilters, [filter.key]: `${value}${filter.unit}` }
const props = { filters }
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })
slidesStore.updateElement({ id: handleElementId.value, props: { filters } })
addHistorySnapshot()
}
//
const clipImage = () => {
store.commit(MutationTypes.SET_CLIPING_IMAGE_ELEMENT_ID, handleElement.value.id)
mainStore.setClipingImageElementId(handleElementId.value)
clipPanelVisible.value = false
}
//
const getImageElementDataBeforeClip = () => {
const _handleElement = handleElement.value as PPTImageElement
//
const imgWidth = handleElement.value.width
const imgHeight = handleElement.value.height
const imgLeft = handleElement.value.left
const imgTop = handleElement.value.top
const originClipRange = handleElement.value.clip ? handleElement.value.clip.range : [[0, 0], [100, 100]]
const imgWidth = _handleElement.width
const imgHeight = _handleElement.height
const imgLeft = _handleElement.left
const imgTop = _handleElement.top
const originClipRange: [[number, number], [number, number]] = _handleElement.clip ? _handleElement.clip.range : [[0, 0], [100, 100]]
const originWidth = imgWidth / ((originClipRange[1][0] - originClipRange[0][0]) / 100)
const originHeight = imgHeight / ((originClipRange[1][1] - originClipRange[0][1]) / 100)
@ -212,6 +216,8 @@ export default defineComponent({
//
const presetImageClip = (shape: string, ratio = 0) => {
const _handleElement = handleElement.value as PPTImageElement
const {
originClipRange,
originWidth,
@ -226,7 +232,7 @@ export default defineComponent({
const min = 0
const max = 100
let range
let range: [[number, number], [number, number]]
if (imageRatio > ratio) {
const distance = ((1 - ratio / imageRatio) / 2) * 100
@ -236,10 +242,10 @@ export default defineComponent({
const distance = ((1 - imageRatio / ratio) / 2) * 100
range = [[distance, min], [max - distance, max]]
}
store.commit(MutationTypes.UPDATE_ELEMENT, {
id: handleElement.value.id,
slidesStore.updateElement({
id: handleElementId.value,
props: {
clip: { ...handleElement.value.clip, shape, range },
clip: { ..._handleElement.clip, shape, range },
left: originLeft + originWidth * (range[0][0] / 100),
top: originTop + originHeight * (range[0][1] / 100),
width: originWidth * (range[1][0] - range[0][0]) / 100,
@ -249,10 +255,10 @@ export default defineComponent({
}
//
else {
store.commit(MutationTypes.UPDATE_ELEMENT, {
id: handleElement.value.id,
slidesStore.updateElement({
id: handleElementId.value,
props: {
clip: { ...handleElement.value.clip, shape, range: originClipRange }
clip: { ..._handleElement.clip, shape, range: originClipRange }
},
})
}
@ -266,14 +272,16 @@ export default defineComponent({
if (!imageFile) return
getImageDataURL(imageFile).then(dataURL => {
const props = { src: dataURL }
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })
slidesStore.updateElement({ id: handleElementId.value, props })
})
addHistorySnapshot()
}
//
const resetImage = () => {
if (handleElement.value.clip) {
const _handleElement = handleElement.value as PPTImageElement
if (_handleElement.clip) {
const {
originWidth,
originHeight,
@ -281,8 +289,8 @@ export default defineComponent({
originTop,
} = getImageElementDataBeforeClip()
store.commit(MutationTypes.UPDATE_ELEMENT, {
id: handleElement.value.id,
slidesStore.updateElement({
id: handleElementId.value,
props: {
left: originLeft,
top: originTop,
@ -292,8 +300,8 @@ export default defineComponent({
})
}
store.commit(MutationTypes.REMOVE_ELEMENT_PROPS, {
id: handleElement.value.id,
slidesStore.removeElementProps({
id: handleElementId.value,
propName: ['clip', 'outline', 'flip', 'shadow', 'filters'],
})
addHistorySnapshot()
@ -301,13 +309,15 @@ export default defineComponent({
//
const setBackgroundImage = () => {
const background = {
const _handleElement = handleElement.value as PPTImageElement
const background: SlideBackground = {
...currentSlide.value.background,
type: 'image',
image: handleElement.value.src,
image: _handleElement.src,
imageSize: 'cover',
}
store.commit(MutationTypes.UPDATE_SLIDE, { background })
slidesStore.updateSlide({ background })
addHistorySnapshot()
}

View File

@ -44,8 +44,9 @@
</template>
<script lang="ts">
import { computed, defineComponent, onUnmounted, ref } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { defineComponent, onUnmounted, ref } from 'vue'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store'
import { PPTLatexElement } from '@/types/slides'
import emitter, { EmitterEvents } from '@/utils/emitter'
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
@ -60,15 +61,16 @@ export default defineComponent({
LaTeXEditor,
},
setup() {
const store = useStore()
const handleElement = computed<PPTLatexElement>(() => store.getters.handleElement)
const slidesStore = useSlidesStore()
const { handleElement } = storeToRefs(useMainStore())
const latexEditorVisible = ref(false)
const { addHistorySnapshot } = useHistorySnapshot()
const updateLatex = (props: Partial<PPTLatexElement>) => {
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })
if (!handleElement.value) return
slidesStore.updateElement({ id: handleElement.value.id, props })
addHistorySnapshot()
}

View File

@ -63,8 +63,9 @@
</template>
<script lang="ts">
import { computed, defineComponent } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { defineComponent } from 'vue'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store'
import { PPTLineElement } from '@/types/slides'
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
@ -78,13 +79,14 @@ export default defineComponent({
ColorButton,
},
setup() {
const store = useStore()
const handleElement = computed<PPTLineElement>(() => store.getters.handleElement)
const slidesStore = useSlidesStore()
const { handleElement } = storeToRefs(useMainStore())
const { addHistorySnapshot } = useHistorySnapshot()
const updateLine = (props: Partial<PPTLineElement>) => {
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })
if (!handleElement.value) return
slidesStore.updateElement({ id: handleElement.value.id, props })
addHistorySnapshot()
}

View File

@ -196,7 +196,8 @@
<script lang="ts">
import { computed, defineComponent, ref, watch } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store'
import { PPTShapeElement, ShapeGradient, ShapeText } from '@/types/slides'
import { WEB_FONTS } from '@/configs/font'
import emitter, { EmitterEvents } from '@/utils/emitter'
@ -220,13 +221,11 @@ export default defineComponent({
ColorButton,
},
setup() {
const store = useStore()
const handleElement = computed<PPTShapeElement>(() => store.getters.handleElement)
const editingShapeElementId = computed(() => store.state.editingShapeElementId)
const mainStore = useMainStore()
const slidesStore = useSlidesStore()
const { handleElement, handleElementId, editingShapeElementId, richTextAttrs, availableFonts } = storeToRefs(mainStore)
const showTextTools = computed(() => {
return editingShapeElementId.value === handleElement.value.id
})
const showTextTools = computed(() => editingShapeElementId.value === handleElementId.value)
const fill = ref<string>()
const gradient = ref<ShapeGradient>()
@ -235,61 +234,54 @@ export default defineComponent({
watch(handleElement, () => {
if (!handleElement.value || handleElement.value.type !== 'shape') return
fill.value = handleElement.value.fill || '#000'
gradient.value = handleElement.value.gradient || { type: 'linear', rotate: 0, color: [fill.value, '#fff'] }
fillType.value = handleElement.value.gradient ? 'gradient' : 'fill'
textAlign.value = handleElement.value?.text?.align || 'middle'
}, { deep: true, immediate: true })
const { addHistorySnapshot } = useHistorySnapshot()
const updateElement = (props: Partial<PPTShapeElement>) => {
slidesStore.updateElement({ id: handleElementId.value, props })
addHistorySnapshot()
}
//
const updateFillType = (type: 'gradient' | 'fill') => {
if (type === 'fill') {
store.commit(MutationTypes.REMOVE_ELEMENT_PROPS, {
id: handleElement.value.id,
propName: 'gradient',
})
slidesStore.removeElementProps({ id: handleElementId.value, propName: 'gradient' })
addHistorySnapshot()
}
else {
const props = { gradient: gradient.value }
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })
}
addHistorySnapshot()
else updateElement({ gradient: gradient.value })
}
//
const updateGradient = (gradientProps: Partial<ShapeGradient>) => {
const props = { gradient: { ...gradient.value, ...gradientProps } }
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })
addHistorySnapshot()
if (!gradient.value) return
const _gradient: ShapeGradient = { ...gradient.value, ...gradientProps }
updateElement({ gradient: _gradient })
}
//
const updateFill = (value: string) => {
const props = { fill: value }
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })
addHistorySnapshot()
updateElement({ fill: value })
}
const updateTextAlign = (align: 'top' | 'middle' | 'bottom') => {
const _handleElement = handleElement.value as PPTShapeElement
const defaultText: ShapeText = {
content: '',
defaultFontName: '微软雅黑',
defaultColor: '#000',
align: 'middle',
}
const _text = handleElement.value.text || defaultText
const props = { text: { ..._text, align } }
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })
addHistorySnapshot()
const _text = _handleElement.text || defaultText
updateElement({ text: { ..._text, align } })
}
const richTextAttrs = computed(() => store.state.richTextAttrs)
const availableFonts = computed(() => store.state.availableFonts)
const fontSizeOptions = [
'12px', '14px', '16px', '18px', '20px', '22px', '24px', '28px', '32px',
'36px', '40px', '44px', '48px', '54px', '60px', '66px', '72px', '76px',

View File

@ -122,7 +122,6 @@
:max="20"
v-model:value="rowCount"
@pressEnter="e => setTableRow(e)"
@blur="e => setTableRow(e)"
style="flex: 3;"
/>
</div>
@ -133,7 +132,6 @@
:max="20"
v-model:value="colCount"
@pressEnter="e => setTableCol(e)"
@blur="e => setTableCol(e)"
style="flex: 3;"
/>
</div>
@ -193,7 +191,8 @@
<script lang="ts">
import { computed, defineComponent, onMounted, ref, watch } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store'
import { PPTTableElement, TableCell, TableCellStyle, TableTheme } from '@/types/slides'
import { createRandomCode } from '@/utils/common'
import { WEB_FONTS } from '@/configs/font'
@ -213,12 +212,10 @@ export default defineComponent({
ColorButton,
},
setup() {
const store = useStore()
const handleElement = computed<PPTTableElement>(() => store.getters.handleElement)
const selectedCells = computed(() => store.state.selectedTableCells)
const themeColor = computed(() => store.state.theme.themeColor)
const slidesStore = useSlidesStore()
const { handleElement, handleElementId, selectedTableCells: selectedCells, availableFonts } = storeToRefs(useMainStore())
const themeColor = computed(() => slidesStore.theme.themeColor)
const availableFonts = computed(() => store.state.availableFonts)
const fontSizeOptions = [
'12px', '14px', '16px', '18px', '20px', '22px', '24px', '28px', '32px',
]
@ -304,9 +301,16 @@ export default defineComponent({
watch(selectedCells, updateTextAttrState)
const updateElement = (props: Partial<PPTTableElement>) => {
slidesStore.updateElement({ id: handleElementId.value, props })
addHistorySnapshot()
}
//
const updateTextAttrs = (textAttrProp: Partial<TableCellStyle>) => {
const data: TableCell[][] = JSON.parse(JSON.stringify(handleElement.value.data))
const _handleElement = handleElement.value as PPTTableElement
const data: TableCell[][] = JSON.parse(JSON.stringify(_handleElement.data))
for (let i = 0; i < data.length; i++) {
for (let j = 0; j < data[i].length; j++) {
@ -316,19 +320,15 @@ export default defineComponent({
}
}
}
const props = { data }
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })
addHistorySnapshot()
updateElement({ data })
updateTextAttrState()
}
//
const updateTheme = (themeProp: Partial<TableTheme>) => {
const currentTheme = theme.value || {}
const props = { theme: { ...currentTheme, ...themeProp } }
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })
addHistorySnapshot()
if (!theme.value) return
const _theme = { ...theme.value, ...themeProp }
updateElement({ theme: _theme })
}
// /
@ -343,18 +343,20 @@ export default defineComponent({
colFooter: false,
}
}
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })
updateElement(props)
}
else {
store.commit(MutationTypes.REMOVE_ELEMENT_PROPS, { id: handleElement.value.id, propName: 'theme' })
slidesStore.removeElementProps({ id: handleElementId.value, propName: 'theme' })
addHistorySnapshot()
}
addHistorySnapshot()
}
//
const setTableRow = (e: KeyboardEvent) => {
const _handleElement = handleElement.value as PPTTableElement
const value = +(e.target as HTMLInputElement).value
const rowCount = handleElement.value.data.length
const rowCount = _handleElement.data.length
if (value === rowCount) return
if (value < rowCount) return message.warning('设置行数不能少于当前值')
@ -362,34 +364,34 @@ export default defineComponent({
const rowCells: TableCell[] = new Array(colCount.value).fill({ id: createRandomCode(), colspan: 1, rowspan: 1, text: '' })
const newTableCells: TableCell[][] = new Array(value - rowCount).fill(rowCells)
const tableCells: TableCell[][] = JSON.parse(JSON.stringify(handleElement.value.data))
const tableCells: TableCell[][] = JSON.parse(JSON.stringify(_handleElement.data))
tableCells.push(...newTableCells)
const props = { data: tableCells }
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })
addHistorySnapshot()
updateElement({ data: tableCells })
}
//
const setTableCol = (e: KeyboardEvent) => {
const _handleElement = handleElement.value as PPTTableElement
const value = +(e.target as HTMLInputElement).value
const colCount = handleElement.value.data[0].length
const colCount = _handleElement.data[0].length
if (value === colCount) return
if (value < colCount) return message.warning('设置列数不能少于当前值')
const tableCells = handleElement.value.data.map(item => {
const tableCells = _handleElement.data.map(item => {
const cells: TableCell[] = new Array(value - colCount).fill({ id: createRandomCode(), colspan: 1, rowspan: 1, text: '' })
item.push(...cells)
return item
})
const colSizeList = handleElement.value.colWidths.map(item => item * handleElement.value.width)
const colSizeList = _handleElement.colWidths.map(item => item * _handleElement.width)
const newColSizeList = new Array(value - colCount).fill(100)
colSizeList.push(...newColSizeList)
const width = handleElement.value.width + 100 * (value - colCount)
const width = _handleElement.width + 100 * (value - colCount)
const colWidths = colSizeList.map(item => item / width)
const props = {
@ -397,9 +399,7 @@ export default defineComponent({
data: tableCells,
colWidths,
}
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })
addHistorySnapshot()
updateElement(props)
}
return {

View File

@ -218,9 +218,9 @@
</template>
<script lang="ts">
import { computed, defineComponent, ref, watch } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { PPTTextElement } from '@/types/slides'
import { defineComponent, ref, watch } from 'vue'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store'
import emitter, { EmitterEvents, RichTextCommand } from '@/utils/emitter'
import { WEB_FONTS } from '@/configs/font'
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
@ -228,6 +228,7 @@ import useHistorySnapshot from '@/hooks/useHistorySnapshot'
import ElementOpacity from '../common/ElementOpacity.vue'
import ElementOutline from '../common/ElementOutline.vue'
import ElementShadow from '../common/ElementShadow.vue'
import { PPTTextElement } from '@/types/slides'
const presetStyles = [
{
@ -312,9 +313,8 @@ export default defineComponent({
ElementShadow,
},
setup() {
const store = useStore()
const handleElement = computed<PPTTextElement>(() => store.getters.handleElement)
const richTextAttrs = computed(() => store.state.richTextAttrs)
const slidesStore = useSlidesStore()
const { handleElement, handleElementId, richTextAttrs, availableFonts } = storeToRefs(useMainStore())
const fill = ref<string>()
const lineHeight = ref<number>()
@ -328,7 +328,6 @@ export default defineComponent({
wordSpace.value = handleElement.value.wordSpace || 0
}, { deep: true, immediate: true })
const availableFonts = computed(() => store.state.availableFonts)
const fontSizeOptions = [
'12px', '14px', '16px', '18px', '20px', '22px', '24px', '28px', '32px',
'36px', '40px', '44px', '48px', '54px', '60px', '66px', '72px', '76px',
@ -349,25 +348,24 @@ export default defineComponent({
const { addHistorySnapshot } = useHistorySnapshot()
const updateElement = (props: Partial<PPTTextElement>) => {
slidesStore.updateElement({ id: handleElementId.value, props })
addHistorySnapshot()
}
//
const updateLineHeight = (value: number) => {
const props = { lineHeight: value }
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })
addHistorySnapshot()
updateElement({ lineHeight: value })
}
//
const updateWordSpace = (value: number) => {
const props = { wordSpace: value }
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })
addHistorySnapshot()
updateElement({ wordSpace: value })
}
//
const updateFill = (value: string) => {
const props = { fill: value }
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })
addHistorySnapshot()
updateElement({ fill: value })
}
return {

View File

@ -15,8 +15,9 @@
</template>
<script lang="ts">
import { computed, defineComponent } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { defineComponent } from 'vue'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store'
import { PPTVideoElement } from '@/types/slides'
import { getImageDataURL } from '@/utils/image'
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
@ -24,13 +25,14 @@ import useHistorySnapshot from '@/hooks/useHistorySnapshot'
export default defineComponent({
name: 'video-style-panel',
setup() {
const store = useStore()
const handleElement = computed<PPTVideoElement>(() => store.getters.handleElement)
const slidesStore = useSlidesStore()
const { handleElement } = storeToRefs(useMainStore())
const { addHistorySnapshot } = useHistorySnapshot()
const updateVideo = (props: Partial<PPTVideoElement>) => {
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })
if (!handleElement.value) return
slidesStore.updateElement({ id: handleElement.value.id, props })
addHistorySnapshot()
}

View File

@ -9,8 +9,9 @@
<script lang="ts">
import { computed, defineComponent } from 'vue'
import { useStore } from '@/store'
import { ElementTypes, PPTElement } from '@/types/slides'
import { storeToRefs } from 'pinia'
import { useMainStore } from '@/store'
import { ElementTypes } from '@/types/slides'
import TextStylePanel from './TextStylePanel.vue'
import ImageStylePanel from './ImageStylePanel.vue'
@ -24,8 +25,7 @@ import VideoStylePanel from './VideoStylePanel.vue'
export default defineComponent({
name: 'element-style-panel',
setup() {
const store = useStore()
const handleElement = computed<PPTElement>(() => store.getters.handleElement)
const { handleElement } = storeToRefs(useMainStore())
const currentPanelComponent = computed(() => {
if (!handleElement.value) return null

View File

@ -18,20 +18,25 @@
<script lang="ts">
import { computed, defineComponent } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { Slide } from '@/types/slides'
import { storeToRefs } from 'pinia'
import { useSlidesStore } from '@/store'
import { TurningMode } from '@/types/slides'
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
interface Animations {
label: string;
value: TurningMode;
}
export default defineComponent({
name: 'slide-animation-panel',
setup() {
const store = useStore()
const slides = computed(() => store.state.slides)
const currentSlide = computed<Slide>(() => store.getters.currentSlide)
const slidesStore = useSlidesStore()
const { slides, currentSlide } = storeToRefs(slidesStore)
const currentTurningMode = computed(() => currentSlide.value.turningMode || 'slideY')
const animations = [
const animations: Animations[] = [
{ label: '无', value: 'no' },
{ label: '淡入淡出', value: 'fade' },
{ label: '左右推移', value: 'slideX' },
@ -41,9 +46,9 @@ export default defineComponent({
const { addHistorySnapshot } = useHistorySnapshot()
//
const updateTurningMode = (mode: string) => {
const updateTurningMode = (mode: TurningMode) => {
if (mode === currentTurningMode.value) return
store.commit(MutationTypes.UPDATE_SLIDE, { turningMode: mode })
slidesStore.updateSlide({ turningMode: mode })
addHistorySnapshot()
}
@ -55,7 +60,7 @@ export default defineComponent({
turningMode: currentSlide.value.turningMode,
}
})
store.commit(MutationTypes.SET_SLIDES, newSlides)
slidesStore.setSlides(newSlides)
addHistorySnapshot()
}

View File

@ -193,7 +193,8 @@
<script lang="ts">
import { computed, defineComponent, ref } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store'
import { Slide, SlideBackground, SlideTheme } from '@/types/slides'
import { PRESET_THEMES } from '@/configs/theme'
import { WEB_FONTS } from '@/configs/font'
@ -211,12 +212,9 @@ export default defineComponent({
ColorButton,
},
setup() {
const store = useStore()
const slides = computed(() => store.state.slides)
const theme = computed(() => store.state.theme)
const availableFonts = computed(() => store.state.availableFonts)
const viewportRatio = computed(() => store.state.viewportRatio)
const currentSlide = computed<Slide>(() => store.getters.currentSlide)
const slidesStore = useSlidesStore()
const { availableFonts } = storeToRefs(useMainStore())
const { slides, currentSlide, viewportRatio, theme } = storeToRefs(slidesStore)
const background = computed(() => {
if (!currentSlide.value.background) {
@ -238,7 +236,7 @@ export default defineComponent({
type: 'solid',
color: background.value.color || '#fff',
}
store.commit(MutationTypes.UPDATE_SLIDE, { background: newBackground })
slidesStore.updateSlide({ background: newBackground })
}
else if (type === 'image') {
const newBackground: SlideBackground = {
@ -247,7 +245,7 @@ export default defineComponent({
image: background.value.image || '',
imageSize: background.value.imageSize || 'cover',
}
store.commit(MutationTypes.UPDATE_SLIDE, { background: newBackground })
slidesStore.updateSlide({ background: newBackground })
}
else {
const newBackground: SlideBackground = {
@ -257,14 +255,14 @@ export default defineComponent({
gradientColor: background.value.gradientColor || ['#fff', '#fff'],
gradientRotate: background.value.gradientRotate || 0,
}
store.commit(MutationTypes.UPDATE_SLIDE, { background: newBackground })
slidesStore.updateSlide({ background: newBackground })
}
addHistorySnapshot()
}
//
const updateBackground = (props: Partial<SlideBackground>) => {
store.commit(MutationTypes.UPDATE_SLIDE, { background: { ...background.value, ...props } })
slidesStore.updateSlide({ background: { ...background.value, ...props } })
addHistorySnapshot()
}
@ -283,13 +281,13 @@ export default defineComponent({
background: currentSlide.value.background,
}
})
store.commit(MutationTypes.SET_SLIDES, newSlides)
slidesStore.setSlides(newSlides)
addHistorySnapshot()
}
//
const updateTheme = (themeProps: Partial<SlideTheme>) => {
store.commit(MutationTypes.SET_THEME, themeProps)
slidesStore.setTheme(themeProps)
}
//
@ -333,7 +331,7 @@ export default defineComponent({
else if (el.type === 'latex') el.color = fontColor
}
}
store.commit(MutationTypes.SET_SLIDES, newSlides)
slidesStore.setSlides(newSlides)
addHistorySnapshot()
}
@ -345,7 +343,7 @@ export default defineComponent({
//
const updateViewportRatio = (value: number) => {
store.commit(MutationTypes.SET_VIEWPORT_RATIO, value)
slidesStore.setViewportRatio(value)
}
return {

View File

@ -16,31 +16,33 @@
</template>
<script lang="ts">
import { computed, defineComponent, ref, watch } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { PPTImageElement, PPTShapeElement, ImageOrShapeFlip } from '@/types/slides'
import { defineComponent, ref, watch } from 'vue'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store'
import { ImageOrShapeFlip } from '@/types/slides'
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
export default defineComponent({
name: 'element-flip',
setup() {
const store = useStore()
const handleElement = computed<PPTImageElement | PPTShapeElement>(() => store.getters.handleElement)
const slidesStore = useSlidesStore()
const { handleElement } = storeToRefs(useMainStore())
const flipH = ref(false)
const flipV = ref(false)
watch(handleElement, () => {
if (!handleElement.value || !['image', 'shape'].includes(handleElement.value.type)) return
flipH.value = !!handleElement.value.flipH
flipV.value = !!handleElement.value.flipV
if (handleElement.value && (handleElement.value.type === 'image' || handleElement.value.type === 'shape')) {
flipH.value = !!handleElement.value.flipH
flipV.value = !!handleElement.value.flipV
}
}, { deep: true, immediate: true })
const { addHistorySnapshot } = useHistorySnapshot()
const updateFlip = (flipProps: ImageOrShapeFlip) => {
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props: flipProps })
if (!handleElement.value) return
slidesStore.updateElement({ id: handleElement.value.id, props: flipProps })
addHistorySnapshot()
}

View File

@ -3,11 +3,11 @@
<div class="row">
<div style="flex: 2;">不透明度</div>
<Slider
class="slider"
:min="0"
:max="1"
:step="0.1"
:value="opacity"
style="flex: 3;"
@change="value => updateOpacity(value)"
/>
</div>
@ -15,18 +15,18 @@
</template>
<script lang="ts">
import { computed, defineComponent, ref, watch } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { PPTElement } from '@/types/slides'
import { defineComponent, ref, watch } from 'vue'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store'
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
export default defineComponent({
name: 'element-opacity',
setup() {
const store = useStore()
const handleElement = computed<PPTElement>(() => store.getters.handleElement)
const slidesStore = useSlidesStore()
const { handleElement } = storeToRefs(useMainStore())
const opacity = ref<number>()
const opacity = ref<number>(1)
watch(handleElement, () => {
if (!handleElement.value) return
@ -36,8 +36,9 @@ export default defineComponent({
const { addHistorySnapshot } = useHistorySnapshot()
const updateOpacity = (value: number) => {
if (!handleElement.value) return
const props = { opacity: value }
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })
slidesStore.updateElement({ id: handleElement.value.id, props })
addHistorySnapshot()
}
@ -56,4 +57,7 @@ export default defineComponent({
align-items: center;
margin-bottom: 10px;
}
.slider {
flex: 3;
}
</style>

View File

@ -46,9 +46,10 @@
</template>
<script lang="ts">
import { computed, defineComponent, ref, watch } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { PPTElement, PPTElementOutline } from '@/types/slides'
import { defineComponent, ref, watch } from 'vue'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store'
import { PPTElementOutline } from '@/types/slides'
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
import ColorButton from './ColorButton.vue'
@ -65,8 +66,8 @@ export default defineComponent({
},
},
setup() {
const store = useStore()
const handleElement = computed<PPTElement>(() => store.getters.handleElement)
const slidesStore = useSlidesStore()
const { handleElement } = storeToRefs(useMainStore())
const outline = ref<PPTElementOutline>()
const hasOutline = ref(false)
@ -80,18 +81,20 @@ export default defineComponent({
const { addHistorySnapshot } = useHistorySnapshot()
const updateOutline = (outlineProps: Partial<PPTElementOutline>) => {
if (!handleElement.value) return
const props = { outline: { ...outline.value, ...outlineProps } }
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })
slidesStore.updateElement({ id: handleElement.value.id, props })
addHistorySnapshot()
}
const toggleOutline = (checked: boolean) => {
if (!handleElement.value) return
if (checked) {
const props = { outline: { width: 2, color: '#000', style: 'solid' } }
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })
const _outline: PPTElementOutline = { width: 2, color: '#000', style: 'solid' }
slidesStore.updateElement({ id: handleElement.value.id, props: { outline: _outline } })
}
else {
store.commit(MutationTypes.REMOVE_ELEMENT_PROPS, { id: handleElement.value.id, propName: 'outline' })
slidesStore.removeElementProps({ id: handleElement.value.id, propName: 'outline' })
}
addHistorySnapshot()
}

View File

@ -57,9 +57,10 @@
</template>
<script lang="ts">
import { computed, defineComponent, ref, watch } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { PPTElement, PPTElementShadow } from '@/types/slides'
import { defineComponent, ref, watch } from 'vue'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store'
import { PPTElementShadow } from '@/types/slides'
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
import ColorButton from './ColorButton.vue'
@ -70,8 +71,8 @@ export default defineComponent({
ColorButton,
},
setup() {
const store = useStore()
const handleElement = computed<PPTElement>(() => store.getters.handleElement)
const slidesStore = useSlidesStore()
const { handleElement } = storeToRefs(useMainStore())
const shadow = ref<PPTElementShadow>()
const hasShadow = ref(false)
@ -85,18 +86,20 @@ export default defineComponent({
const { addHistorySnapshot } = useHistorySnapshot()
const updateShadow = (shadowProps: Partial<PPTElementShadow>) => {
const props = { shadow: { ...shadow.value, ...shadowProps } }
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })
if (!handleElement.value || !shadow.value) return
const _shadow = { ...shadow.value, ...shadowProps }
slidesStore.updateElement({ id: handleElement.value.id, props: { shadow: _shadow } })
addHistorySnapshot()
}
const toggleShadow = (checked: boolean) => {
if (!handleElement.value) return
if (checked) {
const props = { shadow: { h: 1, v: 1, blur: 2, color: '#000' } }
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })
const _shadow: PPTElementShadow = { h: 1, v: 1, blur: 2, color: '#000' }
slidesStore.updateElement({ id: handleElement.value.id, props: { shadow: _shadow } })
}
else {
store.commit(MutationTypes.REMOVE_ELEMENT_PROPS, { id: handleElement.value.id, propName: 'shadow' })
slidesStore.removeElementProps({ id: handleElement.value.id, propName: 'shadow' })
}
addHistorySnapshot()
}

View File

@ -17,8 +17,8 @@
<script lang="ts">
import { computed, defineComponent, watch } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { PPTElement } from '@/types/slides'
import { storeToRefs } from 'pinia'
import { useMainStore } from '@/store'
import { ToolbarState, ToolbarStates } from '@/types/toolbar'
import ElementStylePanel from './ElementStylePanel/index.vue'
@ -29,14 +29,18 @@ import SlideAnimationPanel from './SlideAnimationPanel.vue'
import MultiPositionPanel from './MultiPositionPanel.vue'
import SymbolPanel from './SymbolPanel.vue'
interface ElementTabs {
label: string;
value: ToolbarState;
}
export default defineComponent({
name: 'toolbar',
setup() {
const store = useStore()
const toolbarState = computed(() => store.state.toolbarState)
const handleElement = computed<PPTElement>(() => store.getters.handleElement)
const mainStore = useMainStore()
const { activeElementIdList, handleElement, toolbarState } = storeToRefs(mainStore)
const elementTabs = computed(() => {
const elementTabs = computed<ElementTabs[]>(() => {
if (handleElement.value?.type === 'text') {
return [
{ label: '样式', value: ToolbarStates.EL_STYLE },
@ -62,10 +66,9 @@ export default defineComponent({
]
const setToolbarState = (value: ToolbarState) => {
store.commit(MutationTypes.SET_TOOLBAR_STATE, value)
mainStore.setToolbarState(value)
}
const activeElementIdList = computed(() => store.state.activeElementIdList)
const currentTabs = computed(() => {
if (!activeElementIdList.value.length) return slideTabs
else if (activeElementIdList.value.length > 1) return multiSelectTabs
@ -73,9 +76,9 @@ export default defineComponent({
})
watch(currentTabs, () => {
const currentTabsValue = currentTabs.value.map(tab => tab.value)
const currentTabsValue: ToolbarState[] = currentTabs.value.map(tab => tab.value)
if (!currentTabsValue.includes(toolbarState.value)) {
store.commit(MutationTypes.SET_TOOLBAR_STATE, currentTabsValue[0])
mainStore.setToolbarState(currentTabsValue[0])
}
})

View File

@ -21,8 +21,9 @@
<script lang="ts">
import { computed, defineComponent, PropType } from 'vue'
import { useStore } from '@/store'
import { ElementTypes, PPTElement, Slide } from '@/types/slides'
import { storeToRefs } from 'pinia'
import { useSlidesStore } from '@/store'
import { ElementTypes, PPTElement } from '@/types/slides'
import BaseImageElement from '@/views/components/element/ImageElement/BaseImageElement.vue'
import BaseTextElement from '@/views/components/element/TextElement/BaseTextElement.vue'
@ -64,9 +65,7 @@ export default defineComponent({
return elementTypeMap[props.elementInfo.type] || null
})
const store = useStore()
const theme = computed(() => store.state.theme)
const currentSlide = computed<Slide>(() => store.getters.currentSlide)
const { currentSlide, theme } = storeToRefs(useSlidesStore())
//
const needWaitAnimation = computed(() => {

View File

@ -20,7 +20,8 @@
<script lang="ts">
import { computed, PropType, defineComponent } from 'vue'
import { useStore } from '@/store'
import { storeToRefs } from 'pinia'
import { useSlidesStore } from '@/store'
import { Slide } from '@/types/slides'
import { VIEWPORT_SIZE } from '@/configs/canvas'
import useSlideBackgroundStyle from '@/hooks/useSlideBackgroundStyle'
@ -47,8 +48,7 @@ export default defineComponent({
},
},
setup(props) {
const store = useStore()
const viewportRatio = computed(() => store.state.viewportRatio)
const { viewportRatio } = storeToRefs(useSlidesStore())
const background = computed(() => props.slide.background)
const { backgroundStyle } = useSlideBackgroundStyle(background)

View File

@ -18,8 +18,9 @@
</template>
<script lang="ts">
import { computed, defineComponent, PropType } from 'vue'
import { useStore } from '@/store'
import { defineComponent, PropType } from 'vue'
import { storeToRefs } from 'pinia'
import { useSlidesStore } from '@/store'
import ThumbnailSlide from '@/views/components/ThumbnailSlide/index.vue'
@ -35,9 +36,7 @@ export default defineComponent({
},
},
setup(props, { emit }) {
const store = useStore()
const slides = computed(() => store.state.slides)
const slideIndex = computed(() => store.state.slideIndex)
const { slides, slideIndex } = storeToRefs(useSlidesStore())
const close = () => emit('close')

View File

@ -60,8 +60,8 @@
<script lang="ts">
import { computed, defineComponent, onMounted, onUnmounted, provide, ref } from 'vue'
import { throttle } from 'lodash'
import { MutationTypes, useStore } from '@/store'
import { Slide } from '@/types/slides'
import { storeToRefs } from 'pinia'
import { useSlidesStore } from '@/store'
import { VIEWPORT_SIZE } from '@/configs/canvas'
import { KEYS } from '@/configs/hotkey'
import { ContextmenuItem } from '@/components/Contextmenu/types'
@ -82,11 +82,8 @@ export default defineComponent({
WritingBoardTool,
},
setup() {
const store = useStore()
const slides = computed(() => store.state.slides)
const slideIndex = computed(() => store.state.slideIndex)
const viewportRatio = computed(() => store.state.viewportRatio)
const currentSlide = computed<Slide>(() => store.getters.currentSlide)
const slidesStore = useSlidesStore()
const { slides, slideIndex, currentSlide, viewportRatio } = storeToRefs(slidesStore)
const slideWidth = ref(0)
const slideHeight = ref(0)
@ -184,7 +181,7 @@ export default defineComponent({
animationIndex.value -= 1
}
else if (slideIndex.value > 0) {
store.commit(MutationTypes.UPDATE_SLIDE_INDEX, slideIndex.value - 1)
slidesStore.updateSlideIndex(slideIndex.value - 1)
const lastIndex = animations.value ? animations.value.length : 0
animationIndex.value = lastIndex
}
@ -197,7 +194,7 @@ export default defineComponent({
runAnimation()
}
else if (slideIndex.value < slides.value.length - 1) {
store.commit(MutationTypes.UPDATE_SLIDE_INDEX, slideIndex.value + 1)
slidesStore.updateSlideIndex(slideIndex.value + 1)
animationIndex.value = 0
}
else {
@ -263,18 +260,18 @@ export default defineComponent({
// /
const turnPrevSlide = () => {
store.commit(MutationTypes.UPDATE_SLIDE_INDEX, slideIndex.value - 1)
slidesStore.updateSlideIndex(slideIndex.value - 1)
animationIndex.value = 0
}
const turnNextSlide = () => {
store.commit(MutationTypes.UPDATE_SLIDE_INDEX, slideIndex.value + 1)
slidesStore.updateSlideIndex(slideIndex.value + 1)
animationIndex.value = 0
}
//
const turnSlideToIndex = (index: number) => {
slideThumbnailModelVisible.value = false
store.commit(MutationTypes.UPDATE_SLIDE_INDEX, index)
slidesStore.updateSlideIndex(index)
animationIndex.value = 0
}

View File

@ -26,7 +26,8 @@
<script lang="ts">
import { computed, PropType, defineComponent } from 'vue'
import { useStore } from '@/store'
import { storeToRefs } from 'pinia'
import { useSlidesStore } from '@/store'
import { Slide } from '@/types/slides'
import { VIEWPORT_SIZE } from '@/configs/canvas'
import useSlideBackgroundStyle from '@/hooks/useSlideBackgroundStyle'
@ -49,8 +50,7 @@ export default defineComponent({
},
},
setup(props) {
const store = useStore()
const viewportRatio = computed(() => store.state.viewportRatio)
const { viewportRatio } = storeToRefs(useSlidesStore())
const background = computed(() => props.slide.background)
const { backgroundStyle } = useSlideBackgroundStyle(background)

View File

@ -67,7 +67,8 @@
<script lang="ts">
import { computed, defineComponent, onMounted, onUnmounted, PropType, reactive, ref } from 'vue'
import { useStore } from '@/store'
import { storeToRefs } from 'pinia'
import { useMainStore, useKeyboardStore } from '@/store'
import { KEYS } from '@/configs/hotkey'
import { ImageClipData, ImageClipDataRange, ImageClipedEmitData } from '@/types/edit'
@ -106,9 +107,8 @@ export default defineComponent({
},
},
setup(props, { emit }) {
const store = useStore()
const canvasScale = computed(() => store.state.canvasScale)
const ctrlOrShiftKeyActive = computed<boolean>(() => store.getters.ctrlOrShiftKeyActive)
const { canvasScale } = storeToRefs(useMainStore())
const { ctrlOrShiftKeyActive } = storeToRefs(useKeyboardStore())
const clipWrapperPositionStyle = reactive({
top: '0',

View File

@ -58,7 +58,8 @@
<script lang="ts">
import { computed, defineComponent, PropType } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store'
import { ImageElementClip, PPTImageElement } from '@/types/slides'
import { ImageClipedEmitData } from '@/types/edit'
import { ContextmenuItem } from '@/components/Contextmenu/types'
@ -91,8 +92,10 @@ export default defineComponent({
},
},
setup(props) {
const store = useStore()
const clipingImageElementId = computed(() => store.state.clipingImageElementId)
const mainStore = useMainStore()
const slidesStore = useSlidesStore()
const { clipingImageElementId } = storeToRefs(mainStore)
const isCliping = computed(() => clipingImageElementId.value === props.elementInfo.id)
const { addHistorySnapshot } = useHistorySnapshot()
@ -117,7 +120,7 @@ export default defineComponent({
}
const handleClip = (data: ImageClipedEmitData) => {
store.commit(MutationTypes.SET_CLIPING_IMAGE_ELEMENT_ID, '')
mainStore.setClipingImageElementId('')
if (!data) return
@ -131,7 +134,7 @@ export default defineComponent({
width: props.elementInfo.width + position.width,
height: props.elementInfo.height + position.height,
}
store.commit(MutationTypes.UPDATE_ELEMENT, { id: props.elementInfo.id, props: _props })
slidesStore.updateElement({ id: props.elementInfo.id, props: _props })
addHistorySnapshot()
}

View File

@ -8,7 +8,8 @@
<script lang="ts">
import { computed, defineComponent, onMounted, onUnmounted, ref, watch } from 'vue'
import { debounce } from 'lodash'
import { MutationTypes, useStore } from '@/store'
import { storeToRefs } from 'pinia'
import { useMainStore } from '@/store'
import { EditorView } from 'prosemirror-view'
import { toggleMark, wrapIn, selectAll } from 'prosemirror-commands'
import { initProsemirrorEditor, createDocument } from '@/utils/prosemirror'
@ -47,8 +48,8 @@ export default defineComponent({
},
},
setup(props, { emit }) {
const store = useStore()
const handleElementId = computed(() => store.state.handleElementId)
const mainStore = useMainStore()
const { handleElementId } = storeToRefs(mainStore)
const editorViewRef = ref<HTMLElement>()
let editorView: EditorView
@ -67,12 +68,12 @@ export default defineComponent({
selectAll(editorView.state, editorView.dispatch)
}, 0)
}
store.commit(MutationTypes.SET_DISABLE_HOTKEYS_STATE, true)
mainStore.setDisableHotkeysState(true)
emit('focus')
}
const handleBlur = () => {
store.commit(MutationTypes.SET_DISABLE_HOTKEYS_STATE, false)
mainStore.setDisableHotkeysState(false)
emit('blur')
}
@ -81,7 +82,7 @@ export default defineComponent({
color: props.defaultColor,
fontname: props.defaultFontName,
})
store.commit(MutationTypes.SET_RICHTEXT_ATTRS, attrs)
mainStore.setRichtextAttrs(attrs)
}, 30, { trailing: true })
const handleKeydown = () => {

View File

@ -82,7 +82,8 @@
<script lang="ts">
import { computed, defineComponent, PropType, ref, watch } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store'
import { PPTShapeElement, ShapeText } from '@/types/slides'
import { ContextmenuItem } from '@/components/Contextmenu/types'
import useElementOutline from '@/views/components/element/hooks/useElementOutline'
@ -113,7 +114,9 @@ export default defineComponent({
},
},
setup(props) {
const store = useStore()
const mainStore = useMainStore()
const slidesStore = useSlidesStore()
const { handleElementId } = storeToRefs(mainStore)
const { addHistorySnapshot } = useHistorySnapshot()
@ -138,15 +141,14 @@ export default defineComponent({
const enterEditing = () => {
editable.value = true
store.commit(MutationTypes.SET_EDITING_SHAPE_ELEMENT_ID, props.elementInfo.id)
mainStore.setEditingShapeElementId(props.elementInfo.id)
}
const exitEditing = () => {
editable.value = false
store.commit(MutationTypes.SET_EDITING_SHAPE_ELEMENT_ID, '')
mainStore.setEditingShapeElementId('')
}
const handleElementId = computed(() => store.state.handleElementId)
watch(handleElementId, () => {
if (handleElementId.value !== props.elementInfo.id) {
if (editable.value) exitEditing()
@ -167,7 +169,7 @@ export default defineComponent({
const updateText = (content: string) => {
const _text = { ...text.value, content }
store.commit(MutationTypes.UPDATE_ELEMENT, {
slidesStore.updateElement({
id: props.elementInfo.id,
props: { text: _text },
})

View File

@ -69,7 +69,8 @@
<script lang="ts">
import { computed, defineComponent, nextTick, onMounted, onUnmounted, PropType, ref, watch } from 'vue'
import { debounce, isEqual } from 'lodash'
import { useStore } from '@/store'
import { storeToRefs } from 'pinia'
import { useMainStore } from '@/store'
import { PPTElementOutline, TableCell, TableTheme } from '@/types/slides'
import { ContextmenuItem } from '@/components/Contextmenu/types'
import { KEYS } from '@/configs/hotkey'
@ -112,8 +113,7 @@ export default defineComponent({
},
},
setup(props, { emit }) {
const store = useStore()
const canvasScale = computed(() => store.state.canvasScale)
const { canvasScale } = storeToRefs(useMainStore())
const isStartSelect = ref(false)
const startCell = ref<number[]>([])

View File

@ -44,8 +44,9 @@
</template>
<script lang="ts">
import { computed, defineComponent, nextTick, onMounted, onUnmounted, PropType, ref, watch } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { defineComponent, nextTick, onMounted, onUnmounted, PropType, ref, watch } from 'vue'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store'
import { PPTTableElement, TableCell } from '@/types/slides'
import { ContextmenuItem } from '@/components/Contextmenu/types'
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
@ -71,9 +72,9 @@ export default defineComponent({
},
},
setup(props) {
const store = useStore()
const canvasScale = computed(() => store.state.canvasScale)
const handleElementId = computed(() => store.state.handleElementId)
const mainStore = useMainStore()
const slidesStore = useSlidesStore()
const { canvasScale, handleElementId, isScaling } = storeToRefs(mainStore)
const elementRef = ref<HTMLElement>()
@ -94,7 +95,7 @@ export default defineComponent({
})
watch(editable, () => {
store.commit(MutationTypes.SET_DISABLE_HOTKEYS_STATE, editable.value)
mainStore.setDisableHotkeysState(editable.value)
})
const startEdit = () => {
@ -105,15 +106,13 @@ export default defineComponent({
//
const realHeightCache = ref(-1)
const isScaling = computed(() => store.state.isScaling)
watch(isScaling, () => {
if (handleElementId.value !== props.elementInfo.id) return
if (isScaling.value) editable.value = false
if (!isScaling.value && realHeightCache.value !== -1) {
store.commit(MutationTypes.UPDATE_ELEMENT, {
slidesStore.updateElement({
id: props.elementInfo.id,
props: { height: realHeightCache.value },
})
@ -129,7 +128,7 @@ export default defineComponent({
if (props.elementInfo.height !== realHeight) {
if (!isScaling.value) {
store.commit(MutationTypes.UPDATE_ELEMENT, {
slidesStore.updateElement({
id: props.elementInfo.id,
props: { height: realHeight },
})
@ -149,7 +148,7 @@ export default defineComponent({
//
const updateTableCells = (data: TableCell[][]) => {
store.commit(MutationTypes.UPDATE_ELEMENT, {
slidesStore.updateElement({
id: props.elementInfo.id,
props: { data },
})
@ -161,7 +160,7 @@ export default defineComponent({
const width = widths.reduce((a, b) => a + b)
const colWidths = widths.map(item => item / width)
store.commit(MutationTypes.UPDATE_ELEMENT, {
slidesStore.updateElement({
id: props.elementInfo.id,
props: { width, colWidths },
})
@ -170,7 +169,7 @@ export default defineComponent({
//
const updateSelectedCells = (cells: string[]) => {
nextTick(() => store.commit(MutationTypes.SET_SELECTED_TABLE_CELLS, cells))
nextTick(() => mainStore.setSelectedTableCells(cells))
}
return {

View File

@ -49,7 +49,8 @@
<script lang="ts">
import { computed, defineComponent, onMounted, onUnmounted, PropType, ref, watch } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store'
import { PPTTextElement } from '@/types/slides'
import { ContextmenuItem } from '@/components/Contextmenu/types'
import useElementShadow from '@/views/components/element/hooks/useElementShadow'
@ -78,7 +79,10 @@ export default defineComponent({
},
},
setup(props) {
const store = useStore()
const mainStore = useMainStore()
const slidesStore = useSlidesStore()
const { handleElementId, isScaling } = storeToRefs(mainStore)
const { addHistorySnapshot } = useHistorySnapshot()
const elementRef = ref<HTMLElement>()
@ -86,8 +90,6 @@ export default defineComponent({
const shadow = computed(() => props.elementInfo.shadow)
const { shadowStyle } = useElementShadow(shadow)
const handleElementId = computed(() => store.state.handleElementId)
const handleSelectElement = (e: MouseEvent, canMove = true) => {
if (props.elementInfo.lock) return
e.stopPropagation()
@ -99,13 +101,11 @@ export default defineComponent({
//
const realHeightCache = ref(-1)
const isScaling = computed(() => store.state.isScaling)
watch(isScaling, () => {
if (handleElementId.value !== props.elementInfo.id) return
if (!isScaling.value && realHeightCache.value !== -1) {
store.commit(MutationTypes.UPDATE_ELEMENT, {
slidesStore.updateElement({
id: props.elementInfo.id,
props: { height: realHeightCache.value },
})
@ -121,7 +121,7 @@ export default defineComponent({
if (props.elementInfo.height !== realHeight) {
if (!isScaling.value) {
store.commit(MutationTypes.UPDATE_ELEMENT, {
slidesStore.updateElement({
id: props.elementInfo.id,
props: { height: realHeight },
})
@ -139,8 +139,8 @@ export default defineComponent({
})
const updateContent = (content: string) => {
store.commit(MutationTypes.UPDATE_ELEMENT, {
id: props.elementInfo.id,
slidesStore.updateElement({
id: props.elementInfo.id,
props: { content },
})

View File

@ -22,7 +22,7 @@
:height="elementInfo.height"
:src="elementInfo.src"
:poster="elementInfo.poster"
:scale="scale"
:scale="canvasScale"
/>
<div
:class="['handler-border', item]"
@ -36,8 +36,9 @@
</template>
<script lang="ts">
import { computed, defineComponent, PropType } from 'vue'
import { useStore } from '@/store'
import { defineComponent, PropType } from 'vue'
import { storeToRefs } from 'pinia'
import { useMainStore } from '@/store'
import { PPTVideoElement } from '@/types/slides'
import { ContextmenuItem } from '@/components/Contextmenu/types'
@ -62,8 +63,7 @@ export default defineComponent({
},
},
setup(props) {
const store = useStore()
const scale = computed(() => store.state.canvasScale)
const { canvasScale } = storeToRefs(useMainStore())
const handleSelectElement = (e: MouseEvent, canMove = true) => {
if (props.elementInfo.lock) return
@ -73,7 +73,7 @@ export default defineComponent({
}
return {
scale,
canvasScale,
handleSelectElement,
}
},

View File

@ -23,13 +23,6 @@ module.exports = {
},
},
},
chainWebpack: config => {
config.module
.rule('images')
.use('url-loader')
.loader('url-loader')
.tap(options => Object.assign(options, { limit: 5120 }))
},
configureWebpack: {
plugins: [
new StyleLintPlugin({