Skip to content

Commit 8c099bb

Browse files
committed
feat(editor): support undo-redo && first version
1 parent ffebb06 commit 8c099bb

File tree

7 files changed

+94
-2
lines changed

7 files changed

+94
-2
lines changed

front-end/h5/src/components/core/editor/canvas/edit.js

+7
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ export default {
4545
'setEditingElement', // -> this.foo()
4646
'setElementPosition', // -> this.foo()
4747
'setElementShape', // -> this.foo()
48+
'recordElementRect', // -> this.foo()
4849
'elementManager'
4950
]),
5051
// TODO #!zh: 优化代码
@@ -196,6 +197,12 @@ export default {
196197
this.setElementPosition(pos)
197198
}}
198199
handleElementMoveProp={this.handleElementMove}
200+
handleElementMouseUpProp={() => {
201+
this.recordElementRect()
202+
}}
203+
handlePointMouseUpProp={() => {
204+
this.recordElementRect()
205+
}}
199206
>
200207
{h(element.name, data)}
201208
</Shape>

front-end/h5/src/components/core/editor/index.js

+7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import Vue from 'vue'
22
import { mapState, mapActions } from 'vuex'
33
// import Element from '../models/element'
4+
import undoRedoHistory from '../../../store/plugins/undo-redo/History'
45

56
import '../styles/index.scss'
67

@@ -79,6 +80,12 @@ export default {
7980
defaultSelectedKeys={['2']}
8081
style={{ lineHeight: '64px', float: 'right', background: 'transparent' }}
8182
>
83+
<a-menu-item key="4" class="transparent-bg">
84+
<a-button-group>
85+
<a-button class="transparent-bg" style={{ color: 'white' }} type="dashed" size="small" onClick={() => undoRedoHistory.undo()}><i class={['shortcut-icon', 'fa', `fa-mail-reply`]} aria-hidden='true'/> 撤销</a-button>
86+
<a-button class="transparent-bg" style={{ color: 'white' }} type="dashed" size="small" onClick={() => undoRedoHistory.redo()}><i class={['shortcut-icon', 'fa', `fa-mail-forward`]} aria-hidden='true'/> 重做</a-button>
87+
</a-button-group>
88+
</a-menu-item>
8289
<a-menu-item key="1" class="transparent-bg"><a-button type="primary" size="small">预览</a-button></a-menu-item>
8390
<a-menu-item key="2" class="transparent-bg"><a-button size="small">保存</a-button></a-menu-item>
8491
<a-menu-item key="3" class="transparent-bg"><a-button size="small">发布</a-button></a-menu-item>

front-end/h5/src/components/core/support/shape.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const directionKey = {
1313
const points = ['lt', 'rt', 'lb', 'rb', 'l', 'r', 't', 'b']
1414

1515
export default {
16-
props: ['defaultPosition', 'active', 'handleMousedownProp', 'handleElementMoveProp', 'handlePointMoveProp'],
16+
props: ['defaultPosition', 'active', 'handleMousedownProp', 'handleElementMoveProp', 'handlePointMoveProp', 'handleElementMouseUpProp', 'handlePointMouseUpProp'],
1717
computed: {
1818
position () {
1919
return { ...this.defaultPosition }

front-end/h5/src/store/index.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import Vue from 'vue'
22
import Vuex from 'vuex'
3+
import undoRedoPlugin from './plugins/undo-redo/index'
34
import editor from './modules/editor'
45
import user from './modules/user'
56
import visible from './modules/visible'
@@ -24,5 +25,6 @@ export default new Vuex.Store({
2425
visible,
2526
loading,
2627
element
27-
}
28+
},
29+
plugins: [undoRedoPlugin]
2830
})

front-end/h5/src/store/modules/element.js

+6
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ const actions = {
2222
setElementShape ({ commit }, payload) {
2323
commit('setElementCommonStyle', payload)
2424
},
25+
recordElementRect ({ commit }, payload = {}) {
26+
commit('recordRect', payload)
27+
},
2528
elementManager ({ commit }, payload) {
2629
commit('elementManager', payload)
2730
}
@@ -58,6 +61,9 @@ const mutations = {
5861
break
5962
default:
6063
}
64+
},
65+
recordRect (state, { type, value }) {
66+
6167
}
6268
}
6369

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { cloneDeep } from 'lodash'
2+
3+
class UndoRedoHistory {
4+
store;
5+
history = [];
6+
currentIndex = -1;
7+
8+
get canUndo () {
9+
return this.currentIndex > 0
10+
}
11+
12+
get canRedo () {
13+
return this.history.length > this.currentIndex + 1
14+
}
15+
16+
init (store) {
17+
this.store = store
18+
}
19+
20+
addState (state) {
21+
// may be we have to remove redo steps
22+
if (this.currentIndex + 1 < this.history.length) {
23+
this.history.splice(this.currentIndex + 1)
24+
}
25+
this.history.push(state)
26+
this.currentIndex++
27+
}
28+
29+
undo () {
30+
if (!this.canUndo) return
31+
const prevState = this.history[this.currentIndex - 1]
32+
// take a copy of the history state
33+
// because it would be changed during store mutations
34+
// what would corrupt the undo-redo-history
35+
// (same on redo)
36+
this.store.replaceState(cloneDeep(prevState))
37+
this.currentIndex--
38+
}
39+
40+
redo () {
41+
if (!this.canRedo) return
42+
const nextState = this.history[this.currentIndex + 1]
43+
this.store.replaceState(cloneDeep(nextState))
44+
this.currentIndex++
45+
}
46+
}
47+
48+
const undoRedoHistory = new UndoRedoHistory()
49+
50+
export default undoRedoHistory
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
2+
import { cloneDeep } from 'lodash'
3+
import undoRedoHistory from './History'
4+
const unRecordHistoryMutationTypes = ['element/setElementCommonStyle']
5+
6+
const undoRedoPlugin = (store) => {
7+
// initialize and save the starting stage
8+
undoRedoHistory.init(store)
9+
let firstState = cloneDeep(store.state)
10+
undoRedoHistory.addState(firstState)
11+
12+
store.subscribe((mutation, state) => {
13+
const { type } = mutation
14+
if (unRecordHistoryMutationTypes.includes(type)) return
15+
// is called AFTER every mutation
16+
undoRedoHistory.addState(cloneDeep(state))
17+
})
18+
}
19+
20+
export default undoRedoPlugin

0 commit comments

Comments
 (0)