Commit d04cf043b7558729a15123456fbc2a0025f08c3e
1 parent
714b898c
chore(editor): #2 edit plugin props in the props editor panel
Showing
1 changed file
with
104 additions
and
82 deletions
front-end/h5/src/views/Editor.vue
| @@ -84,14 +84,12 @@ const LbpButton = { | @@ -84,14 +84,12 @@ const LbpButton = { | ||
| 84 | } | 84 | } |
| 85 | }, | 85 | }, |
| 86 | editorConfig: { | 86 | editorConfig: { |
| 87 | - propConfig: { | ||
| 88 | - name: { | 87 | + propsConfig: { |
| 88 | + text: { | ||
| 89 | type: 'el-input', | 89 | type: 'el-input', |
| 90 | label: '按钮文字', | 90 | label: '按钮文字', |
| 91 | require: true, | 91 | require: true, |
| 92 | - widgetProps: { | ||
| 93 | - value: '按钮' | ||
| 94 | - } | 92 | + defaultPropValue: '按钮' |
| 95 | }, | 93 | }, |
| 96 | fontSize: { | 94 | fontSize: { |
| 97 | type: 'el-input-number', | 95 | type: 'el-input-number', |
| @@ -102,10 +100,7 @@ const LbpButton = { | @@ -102,10 +100,7 @@ const LbpButton = { | ||
| 102 | min: 12, | 100 | min: 12, |
| 103 | max: 144 | 101 | max: 144 |
| 104 | }, | 102 | }, |
| 105 | - widgetProps: { | ||
| 106 | - value: 14 | ||
| 107 | - | ||
| 108 | - } | 103 | + defaultPropValue: 14 |
| 109 | }, | 104 | }, |
| 110 | color: { | 105 | color: { |
| 111 | type: 'el-input', | 106 | type: 'el-input', |
| @@ -115,9 +110,7 @@ const LbpButton = { | @@ -115,9 +110,7 @@ const LbpButton = { | ||
| 115 | type: 'color' | 110 | type: 'color' |
| 116 | }, | 111 | }, |
| 117 | require: true, | 112 | require: true, |
| 118 | - widgetProps: { | ||
| 119 | - value: '' | ||
| 120 | - } | 113 | + defaultPropValue: 'black' |
| 121 | }, | 114 | }, |
| 122 | backgroundColor: { | 115 | backgroundColor: { |
| 123 | type: 'el-input', // lbs-color-picker | 116 | type: 'el-input', // lbs-color-picker |
| @@ -126,9 +119,7 @@ const LbpButton = { | @@ -126,9 +119,7 @@ const LbpButton = { | ||
| 126 | type: 'color' | 119 | type: 'color' |
| 127 | }, | 120 | }, |
| 128 | require: true, | 121 | require: true, |
| 129 | - widgetProps: { | ||
| 130 | - value: '' | ||
| 131 | - } | 122 | + defaultPropValue: '#ffffff' // TODO why logogram for color does't work? |
| 132 | }, | 123 | }, |
| 133 | borderColor: { | 124 | borderColor: { |
| 134 | type: 'el-input', // lbs-color-picker | 125 | type: 'el-input', // lbs-color-picker |
| @@ -137,9 +128,7 @@ const LbpButton = { | @@ -137,9 +128,7 @@ const LbpButton = { | ||
| 137 | type: 'color' | 128 | type: 'color' |
| 138 | }, | 129 | }, |
| 139 | require: true, | 130 | require: true, |
| 140 | - widgetProps: { | ||
| 141 | - value: '#ced4da' | ||
| 142 | - } | 131 | + defaultPropValue: '#eeeeee' |
| 143 | }, | 132 | }, |
| 144 | borderWidth: { | 133 | borderWidth: { |
| 145 | type: 'el-input-number', | 134 | type: 'el-input-number', |
| @@ -150,9 +139,7 @@ const LbpButton = { | @@ -150,9 +139,7 @@ const LbpButton = { | ||
| 150 | min: 1, | 139 | min: 1, |
| 151 | max: 10 | 140 | max: 10 |
| 152 | }, | 141 | }, |
| 153 | - widgetProps: { | ||
| 154 | - value: 1 | ||
| 155 | - } | 142 | + defaultPropValue: 1 |
| 156 | }, | 143 | }, |
| 157 | borderRadius: { | 144 | borderRadius: { |
| 158 | type: 'el-input-number', | 145 | type: 'el-input-number', |
| @@ -163,10 +150,7 @@ const LbpButton = { | @@ -163,10 +150,7 @@ const LbpButton = { | ||
| 163 | min: 0, | 150 | min: 0, |
| 164 | max: 10 | 151 | max: 10 |
| 165 | }, | 152 | }, |
| 166 | - widgetProps: { | ||
| 167 | - value: 0 | ||
| 168 | - | ||
| 169 | - } | 153 | + defaultPropValue: 0 |
| 170 | }, | 154 | }, |
| 171 | lineHeight: { | 155 | lineHeight: { |
| 172 | type: 'el-input-number', | 156 | type: 'el-input-number', |
| @@ -177,19 +161,13 @@ const LbpButton = { | @@ -177,19 +161,13 @@ const LbpButton = { | ||
| 177 | min: 0.1, | 161 | min: 0.1, |
| 178 | max: 10 | 162 | max: 10 |
| 179 | }, | 163 | }, |
| 180 | - widgetProps: { | ||
| 181 | - value: 1 | ||
| 182 | - | ||
| 183 | - } | 164 | + defaultPropValue: 1 |
| 184 | }, | 165 | }, |
| 185 | textAlign: { | 166 | textAlign: { |
| 186 | type: 'lbs-text-align', | 167 | type: 'lbs-text-align', |
| 187 | label: '文字对齐', | 168 | label: '文字对齐', |
| 188 | require: true, | 169 | require: true, |
| 189 | - widgetProps: { | ||
| 190 | - value: 'center' | ||
| 191 | - | ||
| 192 | - } | 170 | + defaultPropValue: 'center' |
| 193 | } | 171 | } |
| 194 | }, | 172 | }, |
| 195 | components: { | 173 | components: { |
| @@ -293,21 +271,51 @@ const PluginList = [ | @@ -293,21 +271,51 @@ const PluginList = [ | ||
| 293 | } | 271 | } |
| 294 | ] | 272 | ] |
| 295 | 273 | ||
| 274 | +const defaultProps = { | ||
| 275 | + top: 100, | ||
| 276 | + left: 100, | ||
| 277 | + width: 100, | ||
| 278 | + height: 40, | ||
| 279 | + zindex: 1, | ||
| 280 | + textAlign: 'center', | ||
| 281 | + color: '#000000', | ||
| 282 | + backgroundColor: '#ffffff', | ||
| 283 | + fontSize: 14 | ||
| 284 | +} | ||
| 285 | + | ||
| 296 | class Element { | 286 | class Element { |
| 297 | constructor (ele) { | 287 | constructor (ele) { |
| 298 | - const { defaultPropsValue = {} } = ele | ||
| 299 | - this.type = ele.name | 288 | + // TODO 需要处理plugin的prop中是 name 的,会覆盖 this.name, |
| 289 | + // 或者将plugin的props赋值给this.pluginProps,这样可以避免冲突,也可以知道哪些是plugin 的props | ||
| 300 | this.name = ele.name | 290 | this.name = ele.name |
| 301 | - this.zindex = ele.zindex || defaultPropsValue.zindex || 1 | ||
| 302 | - this.style = { | ||
| 303 | - top: ele.top || defaultPropsValue.top || 100, | ||
| 304 | - left: ele.left || defaultPropsValue.left || 100, | ||
| 305 | - ...defaultPropsValue | ||
| 306 | - } | 291 | + this.editorConfig = ele.editorConfig || {} |
| 292 | + this.init() | ||
| 307 | } | 293 | } |
| 308 | 294 | ||
| 309 | - getStyle () { | 295 | + init () { |
| 296 | + // init common props | ||
| 297 | + Object.keys(defaultProps).forEach(key => { | ||
| 298 | + this[key] = defaultProps[key] | ||
| 299 | + }) | ||
| 300 | + | ||
| 301 | + // init prop of plugin | ||
| 302 | + const propConf = this.editorConfig.propsConfig | ||
| 303 | + Object.keys(propConf).forEach(key => { | ||
| 304 | + this[key] = propConf[key].defaultPropValue | ||
| 305 | + }) | ||
| 306 | + } | ||
| 310 | 307 | ||
| 308 | + getStyle () { | ||
| 309 | + return { | ||
| 310 | + top: `${this.top}px`, | ||
| 311 | + left: `${this.left}px`, | ||
| 312 | + width: `${this.width}px`, | ||
| 313 | + height: `${this.height}px`, | ||
| 314 | + fontSize: `${this.fontSize}px`, | ||
| 315 | + color: this.color, | ||
| 316 | + backgroundColor: this.backgroundColor, | ||
| 317 | + textAlign: this.textAlign | ||
| 318 | + } | ||
| 311 | } | 319 | } |
| 312 | 320 | ||
| 313 | getClass () { | 321 | getClass () { |
| @@ -322,27 +330,29 @@ class Element { | @@ -322,27 +330,29 @@ class Element { | ||
| 322 | const Editor = { | 330 | const Editor = { |
| 323 | name: 'Editor', | 331 | name: 'Editor', |
| 324 | components: { | 332 | components: { |
| 325 | - EditorPanel: { | ||
| 326 | - template: '<div>Editor Panel</div>' | ||
| 327 | - } | ||
| 328 | }, | 333 | }, |
| 329 | data: () => ({ | 334 | data: () => ({ |
| 330 | pages: [], | 335 | pages: [], |
| 331 | - elements: [] | 336 | + elements: [], |
| 337 | + editingElement: null | ||
| 332 | }), | 338 | }), |
| 333 | methods: { | 339 | methods: { |
| 340 | + getEditorConfig (pluginName) { | ||
| 341 | + return this.$options.components[pluginName].editorConfig | ||
| 342 | + }, | ||
| 334 | /** | 343 | /** |
| 335 | * !#zh 点击插件,copy 其基础数据到组件树(中间画布) | 344 | * !#zh 点击插件,copy 其基础数据到组件树(中间画布) |
| 336 | * pluginInfo {Object}: 插件列表中的基础数据, {name}=pluginInfo | 345 | * pluginInfo {Object}: 插件列表中的基础数据, {name}=pluginInfo |
| 337 | */ | 346 | */ |
| 338 | clone ({ name }) { | 347 | clone ({ name }) { |
| 348 | + debugger | ||
| 339 | const zindex = this.elements.length + 1 | 349 | const zindex = this.elements.length + 1 |
| 340 | - const defaultPropsValue = this.getPropsDefaultValue(name) | ||
| 341 | - this.elements.push(new Element({ name, zindex, defaultPropsValue })) | ||
| 342 | - // return new Element({ name, zindex }) | 350 | + // const defaultPropsValue = this.getPropsDefaultValue(name) |
| 351 | + const editorConfig = this.getEditorConfig(name) | ||
| 352 | + this.elements.push(new Element({ name, zindex, editorConfig })) | ||
| 343 | }, | 353 | }, |
| 344 | setCurrentEditingElement (element) { | 354 | setCurrentEditingElement (element) { |
| 345 | - | 355 | + this.editingElement = element |
| 346 | }, | 356 | }, |
| 347 | /** | 357 | /** |
| 348 | * #!zh: renderCanvas 将拖拽过来的组件渲染到中间画布 上 | 358 | * #!zh: renderCanvas 将拖拽过来的组件渲染到中间画布 上 |
| @@ -357,16 +367,8 @@ const Editor = { | @@ -357,16 +367,8 @@ const Editor = { | ||
| 357 | {elements.map((element, index) => { | 367 | {elements.map((element, index) => { |
| 358 | return (() => { | 368 | return (() => { |
| 359 | const data = { | 369 | const data = { |
| 360 | - style: { | ||
| 361 | - top: '100px', | ||
| 362 | - fontSize: '16px', | ||
| 363 | - textAlign: 'center', | ||
| 364 | - color: 'orange', | ||
| 365 | - width: '100px', | ||
| 366 | - height: '30px', | ||
| 367 | - position: 'absolute' | ||
| 368 | - }, | ||
| 369 | - on: { | 370 | + style: element.getStyle(), |
| 371 | + nativeOn: { | ||
| 370 | click: this.setCurrentEditingElement.bind(this, element) | 372 | click: this.setCurrentEditingElement.bind(this, element) |
| 371 | } | 373 | } |
| 372 | } | 374 | } |
| @@ -404,27 +406,54 @@ const Editor = { | @@ -404,27 +406,54 @@ const Editor = { | ||
| 404 | </el-tabs> | 406 | </el-tabs> |
| 405 | ) | 407 | ) |
| 406 | }, | 408 | }, |
| 407 | - renderPropsEditorPanel () { | ||
| 408 | - return (<EditorPanel />) | 409 | + renderPropsEditorPanel (h) { |
| 410 | + if (!this.editingElement) return (<span>请先选择一个元素</span>) | ||
| 411 | + const editingElement = this.editingElement | ||
| 412 | + const propsConfig = editingElement.editorConfig.propsConfig | ||
| 413 | + return ( | ||
| 414 | + <el-form ref="form" label-width="80px"> | ||
| 415 | + { | ||
| 416 | + Object.keys(propsConfig).map(propKey => { | ||
| 417 | + const item = propsConfig[propKey] | ||
| 418 | + // https://vuejs.org/v2/guide/render-function.html | ||
| 419 | + const data = { | ||
| 420 | + props: { | ||
| 421 | + ...item.prop, | ||
| 422 | + // https://vuejs.org/v2/guide/render-function.html#v-model | ||
| 423 | + ...{ value: editingElement[propKey] || item.defaultPropValue } | ||
| 424 | + }, | ||
| 425 | + on: { | ||
| 426 | + // https://vuejs.org/v2/guide/render-function.html#v-model | ||
| 427 | + input (value) { | ||
| 428 | + editingElement[propKey] = value | ||
| 429 | + } | ||
| 430 | + } | ||
| 431 | + } | ||
| 432 | + return ( | ||
| 433 | + <el-form-item label={item.label}> | ||
| 434 | + { h(item.type, data) } | ||
| 435 | + </el-form-item> | ||
| 436 | + ) | ||
| 437 | + }) | ||
| 438 | + } | ||
| 439 | + </el-form> | ||
| 440 | + ) | ||
| 409 | } | 441 | } |
| 410 | }, | 442 | }, |
| 411 | render (h) { | 443 | render (h) { |
| 412 | return ( | 444 | return ( |
| 413 | - <div style='height: 100vh;'> | ||
| 414 | - <div id='designer-page'> | ||
| 415 | - <div class='el-col-5'> | ||
| 416 | - { this.renderPluginListPanel() } | ||
| 417 | - </div> | ||
| 418 | - <div class='el-col-13'> | ||
| 419 | - <div class='canvas-wrapper'> | ||
| 420 | - { this.renderCanvas(h, this.elements) } | ||
| 421 | - { this.hasEleEditing && <Shape elementStyle={this.editingElement.style || {}} /> } | ||
| 422 | - </div> | ||
| 423 | - </div> | ||
| 424 | - <div class='el-col-6'> | ||
| 425 | - { this.renderPropsEditorPanel() } | 445 | + <div id='designer-page'> |
| 446 | + <div class='el-col-5'> | ||
| 447 | + { this.renderPluginListPanel() } | ||
| 448 | + </div> | ||
| 449 | + <div class='el-col-13'> | ||
| 450 | + <div class='canvas-wrapper'> | ||
| 451 | + { this.renderCanvas(h, this.elements) } | ||
| 426 | </div> | 452 | </div> |
| 427 | </div> | 453 | </div> |
| 454 | + <div class='el-col-6' style="border-left: 1px solid #eee;"> | ||
| 455 | + { this.renderPropsEditorPanel(h) } | ||
| 456 | + </div> | ||
| 428 | </div> | 457 | </div> |
| 429 | ) | 458 | ) |
| 430 | } | 459 | } |
| @@ -439,13 +468,6 @@ export default { | @@ -439,13 +468,6 @@ export default { | ||
| 439 | } | 468 | } |
| 440 | }, | 469 | }, |
| 441 | methods: { | 470 | methods: { |
| 442 | - getPropsDefaultValue (pluginName) { | ||
| 443 | - const defaultPropsValue = {} | ||
| 444 | - const component = this.$options.components[pluginName] | ||
| 445 | - const propConfig = component.editorConfig.propConfig | ||
| 446 | - Object.keys(propConfig).forEach(key => { defaultPropsValue[key] = propConfig[key].widgetProps.value }) | ||
| 447 | - return defaultPropsValue | ||
| 448 | - }, | ||
| 449 | mixinPlugins2Editor () { | 471 | mixinPlugins2Editor () { |
| 450 | PluginList.forEach(plugin => { | 472 | PluginList.forEach(plugin => { |
| 451 | this.$options.components[plugin.name] = plugin.component | 473 | this.$options.components[plugin.name] = plugin.component |