update
This commit is contained in:
parent
f37c7d7a62
commit
5b333c4dab
16
src/App.vue
16
src/App.vue
|
@ -2,6 +2,22 @@
|
|||
<router-view/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent, onMounted } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { MutationTypes } from '@/store/constants'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'app',
|
||||
setup() {
|
||||
const store = useStore()
|
||||
onMounted(() => {
|
||||
store.commit(MutationTypes.SET_AVAILABLE_FONTS)
|
||||
})
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
#app {
|
||||
height: 100%;
|
||||
|
|
|
@ -19,24 +19,24 @@ export const ELEMENT_TYPE_TABS = {
|
|||
table: { key: 'element-table', label: '表格属性' },
|
||||
}
|
||||
|
||||
export const ELEMENTS = {
|
||||
text: '文本',
|
||||
image: '图片',
|
||||
shape: '形状',
|
||||
icon: '图标',
|
||||
line: '线条',
|
||||
chart: '图表',
|
||||
iframe: 'Iframe',
|
||||
table: '表格',
|
||||
export enum ELEMENTS {
|
||||
text = '文本',
|
||||
image = '图片',
|
||||
shape = '形状',
|
||||
icon = '图标',
|
||||
line = '线条',
|
||||
chart = '图表',
|
||||
iframe = 'Iframe',
|
||||
table = '表格',
|
||||
}
|
||||
|
||||
export const OPERATE_KEYS = {
|
||||
LEFT_TOP: 1,
|
||||
TOP: 2,
|
||||
RIGHT_TOP: 3,
|
||||
LEFT: 4,
|
||||
RIGHT: 5,
|
||||
LEFT_BOTTOM: 6,
|
||||
BOTTOM: 7,
|
||||
RIGHT_BOTTOM: 8,
|
||||
export enum OPERATE_KEYS {
|
||||
LEFT_TOP = 1,
|
||||
TOP = 2,
|
||||
RIGHT_TOP = 3,
|
||||
LEFT = 4,
|
||||
RIGHT = 5,
|
||||
LEFT_BOTTOM = 6,
|
||||
BOTTOM = 7,
|
||||
RIGHT_BOTTOM = 8,
|
||||
}
|
|
@ -1,4 +1,10 @@
|
|||
export const FONT_FAMILYS = [
|
||||
export interface FontName {
|
||||
source: string;
|
||||
zh: string;
|
||||
en: string;
|
||||
}
|
||||
|
||||
export const FONT_NAMES = [
|
||||
{ source: 'windows', zh: '微软雅黑', en: 'Microsoft Yahei' },
|
||||
{ source: 'windows', zh: '宋体', en: 'SimSun' },
|
||||
{ source: 'windows', zh: '黑体', en: 'SimHei' },
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
export const KEYCODE = {
|
||||
S: 83,
|
||||
C: 67,
|
||||
X: 88,
|
||||
Z: 90,
|
||||
Y: 89,
|
||||
A: 65,
|
||||
G: 71,
|
||||
L: 76,
|
||||
DELETE: 46,
|
||||
UP: 38,
|
||||
DOWN: 40,
|
||||
LEFT: 37,
|
||||
RIGHT: 39,
|
||||
ENTER: 13,
|
||||
SPACE: 32,
|
||||
TAB: 9,
|
||||
export enum KEYCODE {
|
||||
S = 83,
|
||||
C = 67,
|
||||
X = 88,
|
||||
Z = 90,
|
||||
Y = 89,
|
||||
A = 65,
|
||||
G = 71,
|
||||
L = 76,
|
||||
DELETE = 46,
|
||||
UP = 38,
|
||||
DOWN = 40,
|
||||
LEFT = 37,
|
||||
RIGHT = 39,
|
||||
ENTER = 13,
|
||||
SPACE = 32,
|
||||
TAB = 9,
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
import { MutationTypes } from './constants'
|
||||
import { State, SaveState } from './state'
|
||||
import { Slide, PPTElement } from '@/types/slides'
|
||||
import { FONT_NAMES } from '@/configs/fontName'
|
||||
import { isSupportFontFamily } from '@/utils/index'
|
||||
|
||||
interface AddSlidesData {
|
||||
index?: number;
|
||||
|
@ -33,7 +35,7 @@ export type Mutations = {
|
|||
[MutationTypes.TOGGLE_SHOW_GRID_LINES](state: State): void;
|
||||
[MutationTypes.SET_THUMBNAILS_FOCUS](state: State, isFocus: boolean): void;
|
||||
[MutationTypes.SET_EDITORAREA_FOCUS](state: State, isFocus: boolean): void;
|
||||
[MutationTypes.SET_AVAILABLE_FONTS](state: State, fonts: string[]): void;
|
||||
[MutationTypes.SET_AVAILABLE_FONTS](state: State): void;
|
||||
[MutationTypes.SET_SAVE_STATE](state: State, saveState: SaveState ): void;
|
||||
[MutationTypes.SET_SLIDES](state: State, slides: Slide[]): void;
|
||||
[MutationTypes.ADD_SLIDES](state: State, data: AddSlidesData): void;
|
||||
|
@ -44,6 +46,10 @@ export type Mutations = {
|
|||
[MutationTypes.UPDATE_SLIDE_INDEX](state: State, index: number): void;
|
||||
[MutationTypes.ADD_ELEMENTS](state: State, elements: PPTElement[]): void;
|
||||
[MutationTypes.UPDATE_ELEMENT](state: State, data: UpdateElementData): void;
|
||||
[MutationTypes.SET_CURSOR](state: State, cursor: number): void;
|
||||
[MutationTypes.UNDO](state: State): void;
|
||||
[MutationTypes.REDO](state: State): void;
|
||||
[MutationTypes.SET_HISTORY_RECORD_LENGTH](state: State, length: number): void;
|
||||
}
|
||||
|
||||
export const mutations: Mutations = {
|
||||
|
@ -81,8 +87,8 @@ export const mutations: Mutations = {
|
|||
state.editorAreaFocus = isFocus
|
||||
},
|
||||
|
||||
[MutationTypes.SET_AVAILABLE_FONTS](state, fonts) {
|
||||
state.availableFonts = fonts
|
||||
[MutationTypes.SET_AVAILABLE_FONTS](state) {
|
||||
state.availableFonts = FONT_NAMES.filter(font => isSupportFontFamily(font.en))
|
||||
},
|
||||
|
||||
[MutationTypes.SET_SAVE_STATE](state, saveState) {
|
||||
|
@ -146,4 +152,22 @@ export const mutations: Mutations = {
|
|||
})
|
||||
state.slides[slideIndex].elements = (elements as PPTElement[])
|
||||
},
|
||||
|
||||
// history
|
||||
|
||||
[MutationTypes.SET_CURSOR](state, cursor) {
|
||||
state.cursor = cursor
|
||||
},
|
||||
|
||||
[MutationTypes.UNDO](state) {
|
||||
state.cursor -= 1
|
||||
},
|
||||
|
||||
[MutationTypes.REDO](state) {
|
||||
state.cursor += 1
|
||||
},
|
||||
|
||||
[MutationTypes.SET_HISTORY_RECORD_LENGTH](state, length) {
|
||||
state.historyRecordLength = length
|
||||
},
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
import { Slide } from '@/types/slides'
|
||||
import { slides } from '@/mocks/index'
|
||||
import { FontName } from '@/configs/fontName'
|
||||
|
||||
export type SaveState = 'complete' | 'pending'
|
||||
|
||||
|
@ -11,7 +12,7 @@ export type State = {
|
|||
canvasScale: number;
|
||||
thumbnailsFocus: boolean;
|
||||
editorAreaFocus: boolean;
|
||||
availableFonts: string[];
|
||||
availableFonts: FontName[];
|
||||
saveState: SaveState;
|
||||
slides: Slide[];
|
||||
slideIndex: number;
|
||||
|
|
|
@ -10,7 +10,7 @@ export const createRandomNumber = (min: number, max: number) => {
|
|||
}
|
||||
|
||||
// 生成随机码
|
||||
export const createRandomCode = (len: number = 6) => {
|
||||
export const createRandomCode = (len = 6) => {
|
||||
const charset = `_0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz`
|
||||
const maxLen = charset.length
|
||||
let ret = ''
|
||||
|
@ -30,7 +30,7 @@ export const createUUID = () => {
|
|||
}
|
||||
|
||||
// 获取当前日期字符串
|
||||
export const getDateTime = (format: string = 'yyyy-MM-dd hh:mm:ss') => {
|
||||
export const getDateTime = (format = 'yyyy-MM-dd hh:mm:ss') => {
|
||||
const date = new Date()
|
||||
|
||||
const formatMap = {
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
ref="canvasRef"
|
||||
@mousedown="$event => handleClickBlankArea($event)"
|
||||
v-contextmenu="contextmenus"
|
||||
v-click-outside="removeEditorAreaFocus"
|
||||
>
|
||||
<div
|
||||
class="viewport"
|
||||
|
@ -32,6 +33,7 @@
|
|||
import { computed, defineComponent, onMounted, onUnmounted, reactive, ref } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { State } from '@/store/state'
|
||||
import { MutationTypes } from '@/store/constants'
|
||||
import { ContextmenuItem } from '@/components/Contextmenu/types'
|
||||
import { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'
|
||||
|
||||
|
@ -149,8 +151,16 @@ export default defineComponent({
|
|||
mouseSelectionState.isShow = false
|
||||
}
|
||||
}
|
||||
|
||||
const editorAreaFocus = computed(() => store.state.editorAreaFocus)
|
||||
|
||||
const handleClickBlankArea = (e: MouseEvent) => {
|
||||
updateMouseSelection(e)
|
||||
if(!editorAreaFocus.value) store.commit(MutationTypes.SET_EDITORAREA_FOCUS, true)
|
||||
}
|
||||
|
||||
const removeEditorAreaFocus = () => {
|
||||
if(editorAreaFocus.value) store.commit(MutationTypes.SET_EDITORAREA_FOCUS, false)
|
||||
}
|
||||
|
||||
const contextmenus = (): ContextmenuItem[] => {
|
||||
|
@ -191,6 +201,7 @@ export default defineComponent({
|
|||
viewportStyles,
|
||||
mouseSelectionState,
|
||||
handleClickBlankArea,
|
||||
removeEditorAreaFocus,
|
||||
contextmenus,
|
||||
}
|
||||
},
|
||||
|
|
|
@ -13,7 +13,12 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue'
|
||||
import { computed, defineComponent, onMounted, onUnmounted, ref } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { State } from '@/store/state'
|
||||
import { KEYCODE } from '@/configs/keyCode'
|
||||
|
||||
import { message } from 'ant-design-vue'
|
||||
|
||||
import EditorHeader from './EditorHeader/index.vue'
|
||||
import Canvas from './Canvas/index.vue'
|
||||
|
@ -30,6 +35,94 @@ export default defineComponent({
|
|||
Thumbnails,
|
||||
Toolbar,
|
||||
},
|
||||
setup() {
|
||||
const ctrlKeyDown = ref(false)
|
||||
const shiftKeyDown = ref(false)
|
||||
|
||||
const store = useStore<State>()
|
||||
const editorAreaFocus = computed(() => store.state.editorAreaFocus)
|
||||
const thumbnailsFocus = computed(() => store.state.thumbnailsFocus)
|
||||
|
||||
const save = () => {
|
||||
message.success('save')
|
||||
}
|
||||
const copy = () => {
|
||||
message.success('copy')
|
||||
}
|
||||
const cut = () => {
|
||||
message.success('cut')
|
||||
}
|
||||
const undo = () => {
|
||||
message.success('undo')
|
||||
}
|
||||
const redo = () => {
|
||||
message.success('redo')
|
||||
}
|
||||
const selectAll = () => {
|
||||
message.success('selectAll')
|
||||
}
|
||||
const lock = () => {
|
||||
message.success('lock')
|
||||
}
|
||||
const combine = () => {
|
||||
message.success('combine')
|
||||
}
|
||||
const uncombine = () => {
|
||||
message.success('uncombine')
|
||||
}
|
||||
const remove = () => {
|
||||
message.success('remove')
|
||||
}
|
||||
const move = (key: number) => {
|
||||
message.success(`move: ${key}`)
|
||||
}
|
||||
const create = () => {
|
||||
message.success('create')
|
||||
}
|
||||
|
||||
const keydownListener = (e: KeyboardEvent) => {
|
||||
const { keyCode, ctrlKey, shiftKey } = e
|
||||
|
||||
if(ctrlKey && !ctrlKeyDown.value) ctrlKeyDown.value = true
|
||||
if(shiftKey && !shiftKeyDown.value) shiftKeyDown.value = true
|
||||
|
||||
if(!editorAreaFocus.value && !thumbnailsFocus.value) return
|
||||
|
||||
e.preventDefault()
|
||||
|
||||
if(ctrlKey && keyCode === KEYCODE.S) save()
|
||||
if(ctrlKey && keyCode === KEYCODE.C) copy()
|
||||
if(ctrlKey && keyCode === KEYCODE.X) cut()
|
||||
if(ctrlKey && keyCode === KEYCODE.Z) undo()
|
||||
if(ctrlKey && keyCode === KEYCODE.Y) redo()
|
||||
if(ctrlKey && keyCode === KEYCODE.A) selectAll()
|
||||
if(ctrlKey && keyCode === KEYCODE.L) lock()
|
||||
if(!shiftKey && ctrlKey && keyCode === KEYCODE.G) combine()
|
||||
if(shiftKey && ctrlKey && keyCode === KEYCODE.G) uncombine()
|
||||
if(keyCode === KEYCODE.DELETE) remove()
|
||||
if(keyCode === KEYCODE.UP) move(KEYCODE.UP)
|
||||
if(keyCode === KEYCODE.DOWN) move(KEYCODE.DOWN)
|
||||
if(keyCode === KEYCODE.LEFT) move(KEYCODE.LEFT)
|
||||
if(keyCode === KEYCODE.RIGHT) move(KEYCODE.RIGHT)
|
||||
if(keyCode === KEYCODE.ENTER) create()
|
||||
}
|
||||
|
||||
const keyupListener = () => {
|
||||
if(ctrlKeyDown.value) ctrlKeyDown.value = false
|
||||
if(shiftKeyDown.value) shiftKeyDown.value = false
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
document.addEventListener('keydown', keydownListener)
|
||||
document.addEventListener('keyup', keyupListener)
|
||||
window.addEventListener('blur', keyupListener)
|
||||
})
|
||||
onUnmounted(() => {
|
||||
document.removeEventListener('keydown', keydownListener)
|
||||
document.removeEventListener('keyup', keyupListener)
|
||||
window.removeEventListener('blur', keyupListener)
|
||||
})
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
|
|
Loading…
Reference in New Issue