Commit 9e44e40af1a7005c68b3de8e10b06ca597454e5c

Authored by ly525
1 parent 42c972ba

feat: support copy plugin on canvas

front-end/h5/src/components/core/editor/canvas/edit.js
1 import { mapState, mapActions } from 'vuex' 1 import { mapState, mapActions } from 'vuex'
2 import Shape from '../../support/shape' 2 import Shape from '../../support/shape'
3 3
  4 +const contextmenuOptions = [
  5 + {
  6 + label: '复制',
  7 + value: 'copy'
  8 + },
  9 + {
  10 + label: '删除',
  11 + value: 'delete'
  12 + },
  13 + {
  14 + label: '置顶',
  15 + value: 'bring2Top'
  16 + },
  17 + {
  18 + label: '置底',
  19 + value: 'bring2Bottom'
  20 + },
  21 + {
  22 + label: '上移',
  23 + value: 'addZindex'
  24 + },
  25 + {
  26 + label: '下移',
  27 + value: 'minusZindex'
  28 + }
  29 +]
  30 +
4 export default { 31 export default {
5 props: ['elements', 'handleClickElementProp', 'handleClickCanvasProp'], 32 props: ['elements', 'handleClickElementProp', 'handleClickCanvasProp'],
6 data: () => ({ 33 data: () => ({
@@ -17,7 +44,8 @@ export default { @@ -17,7 +44,8 @@ export default {
17 ...mapActions('element', [ 44 ...mapActions('element', [
18 'setEditingElement', // -> this.foo() 45 'setEditingElement', // -> this.foo()
19 'setElementPosition', // -> this.foo() 46 'setElementPosition', // -> this.foo()
20 - 'setElementShape' // -> this.foo() 47 + 'setElementShape', // -> this.foo()
  48 + 'elementManager'
21 ]), 49 ]),
22 // TODO #!zh: 优化代码 50 // TODO #!zh: 优化代码
23 // generate vertical line 51 // generate vertical line
@@ -187,6 +215,9 @@ export default { @@ -187,6 +215,9 @@ export default {
187 { 215 {
188 this.contextmenuPos.length 216 this.contextmenuPos.length
189 ? <a-menu 217 ? <a-menu
  218 + onSelect={({ item, key, selectedKeys }) => {
  219 + this.elementManager({ type: key })
  220 + }}
190 style={{ 221 style={{
191 left: this.contextmenuPos[0] + 'px', 222 left: this.contextmenuPos[0] + 'px',
192 top: this.contextmenuPos[1] + 'px', 223 top: this.contextmenuPos[1] + 'px',
@@ -195,12 +226,7 @@ export default { @@ -195,12 +226,7 @@ export default {
195 zIndex: 999 226 zIndex: 999
196 }} 227 }}
197 > 228 >
198 - <a-menu-item data-command='copyEditingElement'>复制</a-menu-item>  
199 - <a-menu-item data-command="deleteEditingElement">删除</a-menu-item>  
200 - <a-menu-item data-command="bringLayer2Front">置顶</a-menu-item>  
201 - <a-menu-item data-command="bringLayer2End">置底</a-menu-item>  
202 - <a-menu-item data-command="addLayerZindex">上移</a-menu-item>  
203 - <a-menu-item data-command="subtractLayerZindex">下移</a-menu-item> 229 + { contextmenuOptions.map(option => <a-menu-item key={option.value} data-command={option.value}>{option.label}</a-menu-item>) }
204 </a-menu> 230 </a-menu>
205 : null 231 : null
206 } 232 }
front-end/h5/src/components/core/editor/index.js
1 import Vue from 'vue' 1 import Vue from 'vue'
2 -import Element from '../models/element' 2 +import { mapState, mapActions } from 'vuex'
  3 +// import Element from '../models/element'
  4 +
3 import '../styles/index.scss' 5 import '../styles/index.scss'
4 6
5 import RenderEditCanvas from './canvas/edit' 7 import RenderEditCanvas from './canvas/edit'
@@ -30,10 +32,19 @@ export default { @@ -30,10 +32,19 @@ export default {
30 data: () => ({ 32 data: () => ({
31 activeMenuKey: 'pluginList', 33 activeMenuKey: 'pluginList',
32 pages: [], 34 pages: [],
33 - elements: [], 35 + // elements: [],
34 isPreviewMode: false 36 isPreviewMode: false
35 }), 37 }),
  38 + computed: {
  39 + ...mapState('element', {
  40 + editingElement: state => state.editingElement,
  41 + elements: state => state.elementsOfCurrentPage
  42 + })
  43 + },
36 methods: { 44 methods: {
  45 + ...mapActions('element', [
  46 + 'elementManager'
  47 + ]),
37 getEditorConfig (pluginName) { 48 getEditorConfig (pluginName) {
38 // const pluginCtor = Vue.options[pluginName] 49 // const pluginCtor = Vue.options[pluginName]
39 // const pluginCtor = this.$options.components[pluginName] 50 // const pluginCtor = this.$options.components[pluginName]
@@ -49,7 +60,11 @@ export default { @@ -49,7 +60,11 @@ export default {
49 const zindex = this.elements.length + 1 60 const zindex = this.elements.length + 1
50 // const defaultPropsValue = this.getPropsDefaultValue(name) 61 // const defaultPropsValue = this.getPropsDefaultValue(name)
51 const editorConfig = this.getEditorConfig(name) 62 const editorConfig = this.getEditorConfig(name)
52 - this.elements.push(new Element({ name, zindex, editorConfig })) 63 + // this.elements.push(new Element({ name, zindex, editorConfig }))
  64 + this.elementManager({
  65 + type: 'add',
  66 + value: { name, zindex, editorConfig }
  67 + })
53 } 68 }
54 }, 69 },
55 render (h) { 70 render (h) {
front-end/h5/src/components/core/models/element.js
@@ -16,28 +16,34 @@ class Element { @@ -16,28 +16,34 @@ class Element {
16 this.name = ele.name 16 this.name = ele.name
17 this.uuid = +new Date() 17 this.uuid = +new Date()
18 this.editorConfig = ele.editorConfig || {} 18 this.editorConfig = ele.editorConfig || {}
19 - this.pluginProps = {}  
20 - this.commonStyle = {}  
21 - this.init() 19 + /**
  20 + * 之前版本代码:https://github.com/ly525/luban-h5/blob/a7875cbc73c0d18bc2459985ca3ce1d4dc44f141/front-end/h5/src/components/core/models/element.js#L21
  21 + * 1.之前的版本为:this.pluginProps = {}, 改为下面的版本
  22 + * 是因为要支持[复制画布上的元素],所以需要先使用 ele.pluginProps 进行初始化(也就是拷贝之前的元素的值)
  23 + *
  24 + * 2. 移除 this.init() 原因是:如果是 复制元素,则 init 会把 copy 的值重新覆盖为初始值,copy 无效
  25 + */
  26 + this.pluginProps = ele.pluginProps || this.getDefaultPluginProps()
  27 + this.commonStyle = ele.commonStyle || this.getDefaultCommonStyle()
22 } 28 }
23 29
24 - init () {  
25 - const commonStyle = this.commonStyle  
26 - // init common props  
27 - Object.keys(defaultProps).forEach(key => {  
28 - commonStyle[key] = defaultProps[key]  
29 - }) 30 + getDefaultCommonStyle () {
  31 + return { ...defaultProps }
  32 + }
30 33
  34 + getDefaultPluginProps () {
31 // init prop of plugin 35 // init prop of plugin
32 const propConf = this.editorConfig.propsConfig 36 const propConf = this.editorConfig.propsConfig
  37 + const pluginProps = {}
33 Object.keys(propConf).forEach(key => { 38 Object.keys(propConf).forEach(key => {
34 // #6 39 // #6
35 if (key === 'name') { 40 if (key === 'name') {
36 console.warn('Please do not use {name} as plugin prop') 41 console.warn('Please do not use {name} as plugin prop')
37 return 42 return
38 } 43 }
39 - this.pluginProps[key] = propConf[key].defaultPropValue 44 + pluginProps[key] = propConf[key].defaultPropValue
40 }) 45 })
  46 + return pluginProps
41 } 47 }
42 48
43 getStyle (position = 'static') { 49 getStyle (position = 'static') {
@@ -64,6 +70,19 @@ class Element { @@ -64,6 +70,19 @@ class Element {
64 getData () { 70 getData () {
65 71
66 } 72 }
  73 +
  74 + clone () {
  75 + return new Element({
  76 + name: this.name,
  77 + editorConfig: this.editorConfig,
  78 + pluginProps: JSON.parse(JSON.stringify(this.pluginProps)),
  79 + commonStyle: {
  80 + ...this.commonStyle,
  81 + top: this.commonStyle.top + 20,
  82 + left: this.commonStyle.left + 20
  83 + }
  84 + })
  85 + }
67 } 86 }
68 87
69 export default Element 88 export default Element
front-end/h5/src/store/modules/element.js
1 // initial state 1 // initial state
  2 +import Element from '../../components/core/models/element'
  3 +
2 const state = { 4 const state = {
3 - editingElement: null 5 + editingElement: null,
  6 + elementsOfCurrentPage: []
4 } 7 }
5 8
6 // getters 9 // getters
@@ -18,6 +21,9 @@ const actions = { @@ -18,6 +21,9 @@ const actions = {
18 }, 21 },
19 setElementShape ({ commit }, payload) { 22 setElementShape ({ commit }, payload) {
20 commit('setElementCommonStyle', payload) 23 commit('setElementCommonStyle', payload)
  24 + },
  25 + elementManager ({ commit }, payload) {
  26 + commit('elementManager', payload)
21 } 27 }
22 } 28 }
23 29
@@ -31,6 +37,18 @@ const mutations = { @@ -31,6 +37,18 @@ const mutations = {
31 ...state.editingElement.commonStyle, 37 ...state.editingElement.commonStyle,
32 ...payload 38 ...payload
33 } 39 }
  40 + },
  41 + elementManager (state, { type, value }) {
  42 + switch (type) {
  43 + case 'add':
  44 + const element = new Element(value)
  45 + state.elementsOfCurrentPage.push(element)
  46 + break
  47 + case 'copy':
  48 + state.elementsOfCurrentPage.push(state.editingElement.clone())
  49 + break
  50 + default:
  51 + }
34 } 52 }
35 } 53 }
36 54