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

View File

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

View File

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

View File

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

View File

@ -1,15 +1,15 @@
import { computed } from 'vue' import { computed } from 'vue'
import { MutationTypes, useStore } from '@/store' import { storeToRefs } from 'pinia'
import { PPTElement, Slide } from '@/types/slides' import { useMainStore, useSlidesStore } from '@/store'
import { PPTElement } from '@/types/slides'
import { createRandomCode } from '@/utils/common' import { createRandomCode } from '@/utils/common'
import useHistorySnapshot from '@/hooks/useHistorySnapshot' import useHistorySnapshot from '@/hooks/useHistorySnapshot'
export default () => { export default () => {
const store = useStore() const mainStore = useMainStore()
const activeElementIdList = computed(() => store.state.activeElementIdList) const slidesStore = useSlidesStore()
const activeElementList = computed<PPTElement[]>(() => store.getters.activeElementList) const { activeElementIdList, activeElementList, handleElementId } = storeToRefs(mainStore)
const currentSlide = computed<Slide>(() => store.getters.currentSlide) const { currentSlide } = storeToRefs(slidesStore)
const handleElementId = computed(() => store.state.handleElementId)
const { addHistorySnapshot } = useHistorySnapshot() const { addHistorySnapshot } = useHistorySnapshot()
@ -57,7 +57,7 @@ export default () => {
const insertLevel = combineElementMaxLevel - combineElementList.length + 1 const insertLevel = combineElementMaxLevel - combineElementList.length + 1
newElementList.splice(insertLevel, 0, ...combineElementList) newElementList.splice(insertLevel, 0, ...combineElementList)
store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList }) slidesStore.updateSlide({ elements: newElementList })
addHistorySnapshot() addHistorySnapshot()
} }
@ -73,12 +73,13 @@ export default () => {
for (const element of newElementList) { for (const element of newElementList) {
if (activeElementIdList.value.includes(element.id) && element.groupId) delete element.groupId 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] : [] const handleElementIdList = handleElementId.value ? [handleElementId.value] : []
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, handleElementIdList) mainStore.setActiveElementIdList(handleElementIdList)
addHistorySnapshot() addHistorySnapshot()
} }

View File

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

View File

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

View File

@ -1,13 +1,13 @@
import { computed } from 'vue' import { storeToRefs } from 'pinia'
import { MutationTypes, useStore } from '@/store' import { useMainStore, useSlidesStore } from '@/store'
import { PPTElement, Slide } from '@/types/slides' import { PPTElement } from '@/types/slides'
import useHistorySnapshot from '@/hooks/useHistorySnapshot' import useHistorySnapshot from '@/hooks/useHistorySnapshot'
export default () => { export default () => {
const store = useStore() const mainStore = useMainStore()
const activeElementIdList = computed(() => store.state.activeElementIdList) const slidesStore = useSlidesStore()
const activeGroupElementId = computed(() => store.state.activeGroupElementId) const { activeElementIdList, activeGroupElementId } = storeToRefs(mainStore)
const currentSlide = computed<Slide>(() => store.getters.currentSlide) const { currentSlide } = storeToRefs(slidesStore)
const { addHistorySnapshot } = useHistorySnapshot() const { addHistorySnapshot } = useHistorySnapshot()
@ -24,16 +24,16 @@ export default () => {
newElementList = currentSlide.value.elements.filter(el => !activeElementIdList.value.includes(el.id)) newElementList = currentSlide.value.elements.filter(el => !activeElementIdList.value.includes(el.id))
} }
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, []) mainStore.setActiveElementIdList([])
store.commit(MutationTypes.UPDATE_SLIDE, { elements: newElementList }) slidesStore.updateSlide({ elements: newElementList })
addHistorySnapshot() addHistorySnapshot()
} }
// 删除内面内全部元素(无论是否选中) // 删除内面内全部元素(无论是否选中)
const deleteAllElements = () => { const deleteAllElements = () => {
if (!currentSlide.value.elements.length) return if (!currentSlide.value.elements.length) return
store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, []) mainStore.setActiveElementIdList([])
store.commit(MutationTypes.UPDATE_SLIDE, { elements: [] }) slidesStore.updateSlide({ elements: [] })
addHistorySnapshot() 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 { trim } from 'lodash'
import { saveAs } from 'file-saver' import { saveAs } from 'file-saver'
import pptxgen from 'pptxgenjs' import pptxgen from 'pptxgenjs'
import tinycolor from 'tinycolor2' import tinycolor from 'tinycolor2'
import { useSlidesStore } from '@/store'
import { getElementRange, getLineElementPath, getTableSubThemeColor } from '@/utils/element' import { getElementRange, getLineElementPath, getTableSubThemeColor } from '@/utils/element'
import { AST, toAST } from '@/utils/htmlParser' import { AST, toAST } from '@/utils/htmlParser'
import { SvgPoints, toPoints } from '@/utils/svgPathParser' import { SvgPoints, toPoints } from '@/utils/svgPathParser'
import { svg2Base64 } from '@/utils/svg2Base64' import { svg2Base64 } from '@/utils/svg2Base64'
import { useStore } from '@/store'
import { message } from 'ant-design-vue' import { message } from 'ant-design-vue'
export default () => { export default () => {
const store = useStore() const { slides } = storeToRefs(useSlidesStore())
const slides = computed(() => store.state.slides)
const exporting = ref(false) const exporting = ref(false)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,6 @@
import { createApp } from 'vue' import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue' import App from './App.vue'
import { store, key } from './store'
import '@icon-park/vue-next/styles/index.css' import '@icon-park/vue-next/styles/index.css'
import 'prosemirror-view/style/prosemirror.css' import 'prosemirror-view/style/prosemirror.css'
@ -65,5 +65,5 @@ app.use(Icon)
app.use(Component) app.use(Component)
app.use(Directive) app.use(Directive)
app.use(store, key) app.use(createPinia())
app.mount('#app') 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 { useMainStore } from './main'
import { createStore, Store, useStore as baseUseStore } from 'vuex' import { useSlidesStore } from './slides'
import { state, State } from './state' import { useSnapshotStore } from './snapshot'
import { getters } from './getters' import { useKeyboardStore } from './keyboard'
import { actions } from './actions' import { useScreenStore } from './screen'
import { mutations } from './mutations'
import { MutationTypes, ActionTypes } from './constants'
export { MutationTypes, ActionTypes } export {
useMainStore,
export const key: InjectionKey<Store<State>> = Symbol() useSlidesStore,
useSnapshotStore,
export const store = createStore<State>({ useKeyboardStore,
state, useScreenStore,
getters, }
mutations,
actions,
})
export const useStore = () => baseUseStore(key)

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; gradientRotate?: number;
} }
export type TurningMode = 'no' | 'fade' | 'slideX' | 'slideY'
/** /**
* *
* *
@ -566,7 +569,7 @@ export interface Slide {
remark?: string; remark?: string;
background?: SlideBackground; background?: SlideBackground;
animations?: PPTAnimation[]; 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 type ToolbarState = 'symbol' | 'elAnimation' | 'elStyle' | 'elPosition' | 'slideDesign' | 'slideAnimation' | 'multiPosition'
export const ToolbarStates = { export const enum ToolbarStates {
SYMBOL: 'symbol', SYMBOL = 'symbol',
EL_ANIMATION: 'elAnimation', EL_ANIMATION = 'elAnimation',
EL_STYLE: 'elStyle', EL_STYLE = 'elStyle',
EL_POSITION: 'elPosition', EL_POSITION = 'elPosition',
SLIDE_DESIGN: 'slideDesign', SLIDE_DESIGN = 'slideDesign',
SLIDE_ANIMATION: 'slideAnimation', SLIDE_ANIMATION = 'slideAnimation',
MULTI_POSITION: 'multiPosition', MULTI_POSITION = 'multiPosition',
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -17,8 +17,8 @@
<script lang="ts"> <script lang="ts">
import { computed, defineComponent, watch } from 'vue' import { computed, defineComponent, watch } from 'vue'
import { MutationTypes, useStore } from '@/store' import { storeToRefs } from 'pinia'
import { PPTElement } from '@/types/slides' import { useMainStore } from '@/store'
import { ToolbarState, ToolbarStates } from '@/types/toolbar' import { ToolbarState, ToolbarStates } from '@/types/toolbar'
import ElementStylePanel from './ElementStylePanel/index.vue' import ElementStylePanel from './ElementStylePanel/index.vue'
@ -29,14 +29,18 @@ import SlideAnimationPanel from './SlideAnimationPanel.vue'
import MultiPositionPanel from './MultiPositionPanel.vue' import MultiPositionPanel from './MultiPositionPanel.vue'
import SymbolPanel from './SymbolPanel.vue' import SymbolPanel from './SymbolPanel.vue'
interface ElementTabs {
label: string;
value: ToolbarState;
}
export default defineComponent({ export default defineComponent({
name: 'toolbar', name: 'toolbar',
setup() { setup() {
const store = useStore() const mainStore = useMainStore()
const toolbarState = computed(() => store.state.toolbarState) const { activeElementIdList, handleElement, toolbarState } = storeToRefs(mainStore)
const handleElement = computed<PPTElement>(() => store.getters.handleElement)
const elementTabs = computed(() => { const elementTabs = computed<ElementTabs[]>(() => {
if (handleElement.value?.type === 'text') { if (handleElement.value?.type === 'text') {
return [ return [
{ label: '样式', value: ToolbarStates.EL_STYLE }, { label: '样式', value: ToolbarStates.EL_STYLE },
@ -62,10 +66,9 @@ export default defineComponent({
] ]
const setToolbarState = (value: ToolbarState) => { const setToolbarState = (value: ToolbarState) => {
store.commit(MutationTypes.SET_TOOLBAR_STATE, value) mainStore.setToolbarState(value)
} }
const activeElementIdList = computed(() => store.state.activeElementIdList)
const currentTabs = computed(() => { const currentTabs = computed(() => {
if (!activeElementIdList.value.length) return slideTabs if (!activeElementIdList.value.length) return slideTabs
else if (activeElementIdList.value.length > 1) return multiSelectTabs else if (activeElementIdList.value.length > 1) return multiSelectTabs
@ -73,9 +76,9 @@ export default defineComponent({
}) })
watch(currentTabs, () => { watch(currentTabs, () => {
const currentTabsValue = currentTabs.value.map(tab => tab.value) const currentTabsValue: ToolbarState[] = currentTabs.value.map(tab => tab.value)
if (!currentTabsValue.includes(toolbarState.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"> <script lang="ts">
import { computed, defineComponent, PropType } from 'vue' import { computed, defineComponent, PropType } from 'vue'
import { useStore } from '@/store' import { storeToRefs } from 'pinia'
import { ElementTypes, PPTElement, Slide } from '@/types/slides' import { useSlidesStore } from '@/store'
import { ElementTypes, PPTElement } from '@/types/slides'
import BaseImageElement from '@/views/components/element/ImageElement/BaseImageElement.vue' import BaseImageElement from '@/views/components/element/ImageElement/BaseImageElement.vue'
import BaseTextElement from '@/views/components/element/TextElement/BaseTextElement.vue' import BaseTextElement from '@/views/components/element/TextElement/BaseTextElement.vue'
@ -64,9 +65,7 @@ export default defineComponent({
return elementTypeMap[props.elementInfo.type] || null return elementTypeMap[props.elementInfo.type] || null
}) })
const store = useStore() const { currentSlide, theme } = storeToRefs(useSlidesStore())
const theme = computed(() => store.state.theme)
const currentSlide = computed<Slide>(() => store.getters.currentSlide)
// //
const needWaitAnimation = computed(() => { const needWaitAnimation = computed(() => {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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