Commit 84e312efa23eb6f2f4e63610abc33f00510a336b

Authored by ly525
1 parent f809cdf8

refactor: detach the plugin props editor from the plugin; zh: 将组件和组件属性编辑器进行分离

front-end/h5/src/components/core/editor/edit-panel/props.js
  1 +import Vue from 'vue'
1 import { mapState, mapActions } from 'vuex' 2 import { mapState, mapActions } from 'vuex'
2 import { getVM } from '../../../../utils/element' 3 import { getVM } from '../../../../utils/element'
3 4
4 export default { 5 export default {
  6 + data: () => ({
  7 + loadCustomEditorFlag: false
  8 + }),
5 props: { 9 props: {
6 layout: { 10 layout: {
7 type: String, 11 type: String,
@@ -9,12 +13,31 @@ export default { @@ -9,12 +13,31 @@ export default {
9 } 13 }
10 }, 14 },
11 computed: { 15 computed: {
12 - ...mapState('editor', ['editingElement', 'editingElementEditorConfig']) 16 + ...mapState('editor', ['editingElement', 'editingElementEditorConfig']),
  17 + customEditorName () {
  18 + return `${this.editingElement.name}-custom-editor`
  19 + }
13 }, 20 },
14 methods: { 21 methods: {
15 ...mapActions('editor', [ 22 ...mapActions('editor', [
16 'setEditingElement' 23 'setEditingElement'
17 ]), 24 ]),
  25 + loadCustomEditorForPlugin () {
  26 + this.loadCustomEditorFlag = false
  27 + if (!this.editingElement) return
  28 +
  29 + if (Vue.component(this.customEditorName)) {
  30 + this.loadCustomEditorFlag = true
  31 + } else {
  32 + import(`../../../plugins/${this.editingElement.name}__editor`).then(component => {
  33 + this.loadCustomEditorFlag = true
  34 + Vue.component(this.customEditorName, component.default)
  35 + }).catch(err => {
  36 + console.log(err)
  37 + console.warn('没有发现组件对应的编辑器')
  38 + })
  39 + }
  40 + },
18 /** 41 /**
19 * 将插件属性的 自定义增强编辑器注入 属性编辑面板中 42 * 将插件属性的 自定义增强编辑器注入 属性编辑面板中
20 */ 43 */
@@ -37,9 +60,18 @@ export default { @@ -37,9 +60,18 @@ export default {
37 layout={this.layout} 60 layout={this.layout}
38 > 61 >
39 { 62 {
  63 + // plugin-custom-editor
  64 + this.loadCustomEditorFlag &&
  65 + h(this.customEditorName, {
  66 + props: {
  67 + elementProps: editingElement.pluginProps
  68 + }
  69 + })
  70 + }
  71 + {
40 Object 72 Object
41 .entries(props) 73 .entries(props)
42 - .filter(([propKey, obj]) => obj.editor) 74 + .filter(([propKey, obj]) => obj.editor && !obj.editor.custom)
43 .map(([propKey, obj]) => { 75 .map(([propKey, obj]) => {
44 const item = obj.editor 76 const item = obj.editor
45 // https://vuejs.org/v2/guide/render-function.html 77 // https://vuejs.org/v2/guide/render-function.html
@@ -92,5 +124,8 @@ export default { @@ -92,5 +124,8 @@ export default {
92 if (!ele) return (<span>{this.$t('editor.editPanel.common.empty')}</span>) 124 if (!ele) return (<span>{this.$t('editor.editPanel.common.empty')}</span>)
93 this.mixinEnhancedPropsEditor(ele) 125 this.mixinEnhancedPropsEditor(ele)
94 return this.renderPropsEditorPanel(h, ele) 126 return this.renderPropsEditorPanel(h, ele)
  127 + },
  128 + created () {
  129 + window.getEditorApp.$on('setEditingElement', this.loadCustomEditorForPlugin)
95 } 130 }
96 } 131 }
front-end/h5/src/components/plugins/lbp-slide.js
1 import { Swipe, SwipeItem } from 'vant' 1 import { Swipe, SwipeItem } from 'vant'
2 import 'vant/lib/swipe/style' 2 import 'vant/lib/swipe/style'
3 import 'vant/lib/swipe-item/style' 3 import 'vant/lib/swipe-item/style'
4 -import ImageGallery from '@/components/core/support/image-gallery/gallery.js'  
5 4
6 const defaultItems = [ 5 const defaultItems = [
7 { 6 {
@@ -12,13 +11,6 @@ const defaultItems = [ @@ -12,13 +11,6 @@ const defaultItems = [
12 } 11 }
13 ] 12 ]
14 13
15 -function getDefaultDataSource () {  
16 - return {  
17 - activeIndex: 0,  
18 - items: defaultItems.slice(0)  
19 - }  
20 -}  
21 -  
22 export default { 14 export default {
23 name: 'lbp-slide', 15 name: 'lbp-slide',
24 props: { 16 props: {
@@ -28,18 +20,7 @@ export default { @@ -28,18 +20,7 @@ export default {
28 editor: { 20 editor: {
29 type: 'a-input-number', 21 type: 'a-input-number',
30 label: '间隔时间', 22 label: '间隔时间',
31 - require: true,  
32 - defaultPropValue: 4000  
33 - }  
34 - },  
35 - dataSource: {  
36 - type: Object,  
37 - default: () => getDefaultDataSource(),  
38 - editor: {  
39 - type: 'lbs-slide-items-editor',  
40 - label: '图片列表',  
41 - require: true,  
42 - defaultPropValue: getDefaultDataSource() 23 + require: true
43 } 24 }
44 }, 25 },
45 editorMode: { 26 editorMode: {
@@ -48,87 +29,21 @@ export default { @@ -48,87 +29,21 @@ export default {
48 }, 29 },
49 activeIndex: { 30 activeIndex: {
50 type: Number, 31 type: Number,
51 - default: 0 32 + default: 0,
  33 + editor: {
  34 + custom: true
  35 + }
  36 + },
  37 + items: {
  38 + type: Array,
  39 + default: () => defaultItems.slice(0),
  40 + editor: {
  41 + custom: true
  42 + }
52 } 43 }
53 }, 44 },
54 editorConfig: { 45 editorConfig: {
55 components: { 46 components: {
56 - 'lbs-slide-items-editor': {  
57 - render () {  
58 - const currentItem = this.innerItems[this.current - 1] || {}  
59 - return <div>  
60 - {  
61 - <a-pagination  
62 - current={this.current}  
63 - onChange={(page) => {  
64 - this.current = page  
65 - this.$emit('change', {  
66 - items: this.innerItems,  
67 - activeIndex: page - 1  
68 - })  
69 - }}  
70 - size="small"  
71 - total={this.innerItems.length}  
72 - defaultPageSize={1}  
73 - itemRender={this.itemRender}  
74 - />  
75 - }  
76 - <ImageGallery  
77 - style={{ margin: '16px 0' }}  
78 - value={currentItem.image}  
79 - onChange={url => {  
80 - currentItem.image = url  
81 - }}  
82 - />  
83 - </div>  
84 - },  
85 - props: {  
86 - value: {  
87 - type: Object,  
88 - default: () => getDefaultDataSource()  
89 - }  
90 - },  
91 - computed: {  
92 - innerItems () {  
93 - return this.value.items  
94 - }  
95 - },  
96 - data: () => ({  
97 - current: 1  
98 - }),  
99 - methods: {  
100 - itemRender (current, type, originalElement) {  
101 - if (type === 'prev') {  
102 - return <a-button style={{ marginRight: '8px' }} size="small" icon="minus" onClick={() => this.minus(current)} disabled={this.innerItems.length === 1}></a-button>  
103 - } else if (type === 'next') {  
104 - return <a-button style={{ marginLeft: '8px' }} size="small" icon="plus" onClick={this.add}></a-button>  
105 - }  
106 - return originalElement  
107 - },  
108 - add () {  
109 - this.$emit('change', {  
110 - activeIndex: this.innerItems.length,  
111 - items: [  
112 - ...this.innerItems,  
113 - {  
114 - image: '',  
115 - value: `选项${this.innerItems.length + 1}-value`,  
116 - label: `选项${this.innerItems.length + 1}-label`  
117 - }  
118 - ]  
119 - })  
120 - },  
121 - minus (index) {  
122 - if (this.innerItems.length === 1) return  
123 - const items = this.innerItems.slice(0)  
124 - items.splice(index, 1)  
125 - this.$emit('change', {  
126 - items,  
127 - activeIndex: index > 0 ? index - 1 : 0  
128 - })  
129 - }  
130 - }  
131 - }  
132 } 47 }
133 }, 48 },
134 mounted () { 49 mounted () {
@@ -137,7 +52,7 @@ export default { @@ -137,7 +52,7 @@ export default {
137 52
138 }, 53 },
139 render () { 54 render () {
140 - const { items, activeIndex } = this.dataSource 55 + const { items, activeIndex } = this
141 return ( 56 return (
142 this.editorMode === 'edit' 57 this.editorMode === 'edit'
143 ? items.length && <img src={items[activeIndex].image} /> 58 ? items.length && <img src={items[activeIndex].image} />
front-end/h5/src/components/plugins/lbp-slide__editor.js 0 → 100644
  1 +import ImageGallery from '@/components/core/support/image-gallery/gallery.js'
  2 +
  3 +export default {
  4 + props: {
  5 + elementProps: {
  6 + type: Object,
  7 + default: () => ({
  8 + items: [],
  9 + activeIndex: 0
  10 + })
  11 + }
  12 + },
  13 + computed: {
  14 + innerItems () {
  15 + return this.elementProps.items
  16 + }
  17 + },
  18 + data: () => ({
  19 + current: 1
  20 + }),
  21 + methods: {
  22 + itemRender (current, type, originalElement) {
  23 + if (type === 'prev') {
  24 + return <a-button style={{ marginRight: '8px' }} size="small" icon="minus" onClick={() => this.minus(current)} disabled={this.innerItems.length === 1}></a-button>
  25 + } else if (type === 'next') {
  26 + return <a-button style={{ marginLeft: '8px' }} size="small" icon="plus" onClick={this.add}></a-button>
  27 + }
  28 + return originalElement
  29 + },
  30 + add () {
  31 + // this.$emit('change', {
  32 + // activeIndex: this.innerItems.length,
  33 + // items: [
  34 + // ...this.innerItems,
  35 + // {
  36 + // image: '',
  37 + // value: `选项${this.innerItems.length + 1}-value`,
  38 + // label: `选项${this.innerItems.length + 1}-label`
  39 + // }
  40 + // ]
  41 + // })
  42 + this.elementProps.items.push({
  43 + image: '',
  44 + value: `选项${this.innerItems.length + 1}-value`,
  45 + label: `选项${this.innerItems.length + 1}-label`
  46 + })
  47 + },
  48 + minus (index) {
  49 + if (this.innerItems.length === 1) return
  50 + this.elementProps.items.splice(index, 1)
  51 + this.elementProps.activeIndex = index > 0 ? index - 1 : 0
  52 + // const items = this.innerItems.slice(0)
  53 + // items.splice(index, 1)
  54 + // this.$emit('change', {
  55 + // items,
  56 + // activeIndex: index > 0 ? index - 1 : 0
  57 + // })
  58 + }
  59 + },
  60 + render () {
  61 + const currentItem = this.innerItems[this.current - 1] || {}
  62 + return <div>
  63 + {
  64 + <a-pagination
  65 + current={this.current}
  66 + onChange={(page) => {
  67 + this.current = page
  68 +
  69 + this.activeIndex = page - 1
  70 + // this.$emit('change', {
  71 + // items: this.innerItems,
  72 + // activeIndex: page - 1
  73 + // })
  74 + }}
  75 + size="small"
  76 + total={this.innerItems.length}
  77 + defaultPageSize={1}
  78 + itemRender={this.itemRender}
  79 + />
  80 + }
  81 + <ImageGallery
  82 + style={{ margin: '16px 0' }}
  83 + value={currentItem.image}
  84 + onChange={url => {
  85 + currentItem.image = url
  86 + }}
  87 + />
  88 + </div>
  89 + }
  90 +
  91 +}
front-end/h5/src/store/modules/element.js
@@ -8,6 +8,8 @@ export const actions = { @@ -8,6 +8,8 @@ export const actions = {
8 8
9 const vm = (payload && payload.name) ? getEditorConfigForEditingElement(payload.name) : null 9 const vm = (payload && payload.name) ? getEditorConfigForEditingElement(payload.name) : null
10 commit('setEditingElementEditorConfig', vm) 10 commit('setEditingElementEditorConfig', vm)
  11 +
  12 + window.getEditorApp.$emit('setEditingElement')
11 }, 13 },
12 setElementPosition ({ commit }, payload) { 14 setElementPosition ({ commit }, payload) {
13 commit('setElementCommonStyle', payload) 15 commit('setElementCommonStyle', payload)