Commit 74accbcfc538c91a083d7a34a0b492e4c3953b8b

Authored by 宋远桥
Committed by 小小鲁班
1 parent a81a9fb6

[feature] 解决更改组件border渲染问题

front-end/h5/src/components/core/editor/right-panel/box-model/index.vue
1 <template> 1 <template>
2 - <div class="box-model"> 2 + <div v-if="editingElement" class="box-model">
3 <div v-if="lastSelect" class="prompt">设置 {{ lastSelect }} 大小</div> 3 <div v-if="lastSelect" class="prompt">设置 {{ lastSelect }} 大小</div>
4 <div v-else>选择 margin/border/padding 设置大小</div> 4 <div v-else>选择 margin/border/padding 设置大小</div>
5 - <PositionCheckbox label="上" /> 5 + <PositionCheckbox label="上" label-key="top" />
6 <div class="middle"> 6 <div class="middle">
7 - <PositionCheckbox label="左" /> 7 + <PositionCheckbox label="左" label-key="left" />
8 <div ref="margin" class="margin" data-type="margin" @click="onBoxModelClick"> 8 <div ref="margin" class="margin" data-type="margin" @click="onBoxModelClick">
9 margin 9 margin
10 <div ref="border" class="border" data-type="border"> 10 <div ref="border" class="border" data-type="border">
@@ -14,13 +14,14 @@ @@ -14,13 +14,14 @@
14 </div> 14 </div>
15 </div> 15 </div>
16 </div> 16 </div>
17 - <PositionCheckbox label="右" /> 17 + <PositionCheckbox label="右" label-key="right" />
18 </div> 18 </div>
19 - <PositionCheckbox label="下" /> 19 + <PositionCheckbox label="下" label-key="bottom" />
20 </div> 20 </div>
21 </template> 21 </template>
22 22
23 <script> 23 <script>
  24 + import { mapState, mapActions } from 'vuex'
24 import PositionCheckbox from './position-checkbox' 25 import PositionCheckbox from './position-checkbox'
25 export default { 26 export default {
26 name: 'BoxModel', 27 name: 'BoxModel',
@@ -32,14 +33,24 @@ @@ -32,14 +33,24 @@
32 lastSelect: '' 33 lastSelect: ''
33 } 34 }
34 }, 35 },
35 - 36 + computed: {
  37 + ...mapState('editor', {
  38 + editingElement: state => state.editingElement
  39 + })
  40 + },
36 methods: { 41 methods: {
  42 + ...mapActions('editor', [
  43 + 'setElementPosition'
  44 + ]),
37 onBoxModelClick (e) { 45 onBoxModelClick (e) {
38 const target = e.target 46 const target = e.target
39 const classList = target.classList 47 const classList = target.classList
40 const type = target.dataset.type 48 const type = target.dataset.type
41 const selectClass = type + '-select' 49 const selectClass = type + '-select'
42 - 50 + // 更新选中的 boxModelPart,用于判断当前设置的是 margin / border / padding
  51 + this.setElementPosition({
  52 + boxModelPart: type
  53 + })
43 if (this.lastSelect && type !== this.lastSelect) { 54 if (this.lastSelect && type !== this.lastSelect) {
44 this.$refs[this.lastSelect].classList.remove(this.lastSelect + '-select') 55 this.$refs[this.lastSelect].classList.remove(this.lastSelect + '-select')
45 } 56 }
front-end/h5/src/components/core/editor/right-panel/box-model/position-checkbox.vue
1 <template> 1 <template>
2 <div class="position-checkbox"> 2 <div class="position-checkbox">
3 - <div class="flex">  
4 - <a-checkbox @change="onCheckboxChange">  
5 - </a-checkbox>  
6 - <div class="label">{{label}}</div>  
7 - </div>  
8 - <a-input-number style="width:70px" v-model="value" :min="0" @change="onInputNumberChange" />  
9 - <a-select default-value="px" style="width:70px">  
10 - <a-select-option value="px">  
11 - px  
12 - </a-select-option>  
13 - <a-select-option value="%">  
14 - %  
15 - </a-select-option>  
16 - <a-select-option value="em">  
17 - em  
18 - </a-select-option>  
19 - </a-select> 3 + <!-- 只有选中 padding border margin 之后才会显示 -->
  4 + <template v-if="boxModelPart">
  5 + <div class="flex">
  6 + <a-checkbox @change="onCheckboxChange">
  7 + </a-checkbox>
  8 + <div class="label">{{label}}</div>
  9 + </div>
  10 + <a-input-number style="width:70px" :value="value" :min="0" @change="onInputNumberChange" />
  11 + <a-select :default-value="unitList[0]" style="width:70px">
  12 + <a-select-option v-for="(item,index) in unitList" :key="index" :value="item">
  13 + {{ item }}
  14 + </a-select-option>
  15 + </a-select>
  16 + </template>
20 </div> 17 </div>
21 </template> 18 </template>
22 19
23 <script> 20 <script>
  21 + import { mapState, mapActions } from 'vuex'
24 export default { 22 export default {
25 name: 'PositionCheckbox', 23 name: 'PositionCheckbox',
26 props: { 24 props: {
27 label: { 25 label: {
28 type: String, 26 type: String,
29 default: '' 27 default: ''
  28 + },
  29 + labelKey: {
  30 + type: String,
  31 + default: ''
30 } 32 }
31 }, 33 },
32 - data () {  
33 - return {  
34 - value: 1 34 + computed: {
  35 + ...mapState('editor', {
  36 + editingElement: state => state.editingElement
  37 + }),
  38 + boxModelPart () {
  39 + return this.editingElement && this.editingElement.commonStyle.boxModelPart
  40 + },
  41 + value () {
  42 + const { editingElement, labelKey, boxModelPart } = this
  43 + return this.boxModelPart ? editingElement.commonStyle[boxModelPart][labelKey].value : ''
  44 + },
  45 + unitList () {
  46 + return this.boxModelPart === 'border' ? ['px', 'em'] : ['px', '%', 'em']
35 } 47 }
36 }, 48 },
37 -  
38 methods: { 49 methods: {
39 - onCheckboxChange () {},  
40 - onInputNumberChange () {} 50 + ...mapActions('editor', [
  51 + 'setElementPosition'
  52 + ]),
  53 + onCheckboxChange (e) {
  54 + },
  55 + onInputNumberChange (value) {
  56 + const boxModelPart = this.boxModelPart
  57 + // 例如 boxModelPart 为 margin 时候
  58 + const boxModelPartStyle = this.editingElement.commonStyle[boxModelPart]
  59 + // 更新值例如: padding-top
  60 + Object.assign(boxModelPartStyle[this.labelKey], { value })
  61 + this.setElementPosition({ [boxModelPart]: boxModelPartStyle })
  62 + }
41 } 63 }
42 } 64 }
43 </script> 65 </script>
front-end/h5/src/components/core/models/element.js
@@ -13,7 +13,69 @@ const defaultStyle = { @@ -13,7 +13,69 @@ const defaultStyle = {
13 textAlign: 'center', 13 textAlign: 'center',
14 color: '#000000', 14 color: '#000000',
15 backgroundColor: 'rgba(255, 255, 255, 0)', 15 backgroundColor: 'rgba(255, 255, 255, 0)',
16 - fontSize: 14 16 + fontSize: 14,
  17 + margin: {
  18 + top: {
  19 + value: 10,
  20 + unit: 'px'
  21 + },
  22 + right: {
  23 + value: 0,
  24 + unit: 'px'
  25 + },
  26 + bottom: {
  27 + value: 30,
  28 + unit: 'px'
  29 + },
  30 + left: {
  31 + value: 0,
  32 + unit: 'px'
  33 + }
  34 + },
  35 + padding: {
  36 + top: {
  37 + value: 0,
  38 + unit: 'px'
  39 + },
  40 + right: {
  41 + value: 0,
  42 + unit: 'px'
  43 + },
  44 + bottom: {
  45 + value: 0,
  46 + unit: 'px'
  47 + },
  48 + left: {
  49 + value: 0,
  50 + unit: 'px'
  51 + }
  52 + },
  53 + border: {
  54 + top: {
  55 + value: 0,
  56 + unit: 'px'
  57 + },
  58 + right: {
  59 + value: 0,
  60 + unit: 'px'
  61 + },
  62 + bottom: {
  63 + value: 0,
  64 + unit: 'px'
  65 + },
  66 + left: {
  67 + value: 0,
  68 + unit: 'px'
  69 + },
  70 + color: {
  71 + value: '#000'
  72 + },
  73 + style: {
  74 + value: 'solid'
  75 + }
  76 + },
  77 + 'border-style': 'solid',
  78 + boxModelPart: '' // 可选值 margin、padding、border
17 } 79 }
18 80
19 class Element { 81 class Element {
@@ -75,7 +137,25 @@ class Element { @@ -75,7 +137,25 @@ class Element {
75 137
76 return pluginProps 138 return pluginProps
77 } 139 }
78 - 140 + packPosData (obj, prefix) {
  141 + let init = {}
  142 + Object.keys(obj).forEach(key => {
  143 + init[prefix + '-' + key] = obj[key].value + (obj[key].unit || '')
  144 + })
  145 + return init
  146 + }
  147 + packBorderData () {
  148 + const { top, right, bottom, left, color, style } = this.commonStyle.border
  149 + return {
  150 + /**
  151 + * 使用 border-left border-right 等方式,在 chrome 浏览器中会导致渲染问题
  152 + * 这里就将他拼接成完整的 border-width解决bug,不知道是什么原因
  153 + */
  154 + 'border-width': `${top.value}px ${right.value}px ${bottom.value}px ${left.value}px `,
  155 + 'border-style': style.value,
  156 + 'border-color': color.value
  157 + }
  158 + }
79 getStyle ({ position = 'static', isRem = false } = {}) { 159 getStyle ({ position = 'static', isRem = false } = {}) {
80 if (this.name === 'lbp-background') { 160 if (this.name === 'lbp-background') {
81 return { 161 return {
@@ -85,12 +165,17 @@ class Element { @@ -85,12 +165,17 @@ class Element {
85 } 165 }
86 const pluginProps = this.pluginProps 166 const pluginProps = this.pluginProps
87 const commonStyle = this.commonStyle 167 const commonStyle = this.commonStyle
  168 + const { margin, padding } = commonStyle
  169 + // 由于在 defaultStyle 定义的时候是对象,这里需要将数据重新组装成 margin-top 这种形式
  170 + const boxModel = { ...this.packPosData(margin, 'margin'), ...this.packPosData(padding, 'padding'), ...this.packBorderData() }
88 let style = { 171 let style = {
89 top: parsePx(pluginProps.top || commonStyle.top, isRem), 172 top: parsePx(pluginProps.top || commonStyle.top, isRem),
90 left: parsePx(pluginProps.left || commonStyle.left, isRem), 173 left: parsePx(pluginProps.left || commonStyle.left, isRem),
91 width: parsePx(pluginProps.width || commonStyle.width, isRem), 174 width: parsePx(pluginProps.width || commonStyle.width, isRem),
92 height: parsePx(pluginProps.height || commonStyle.height, isRem), 175 height: parsePx(pluginProps.height || commonStyle.height, isRem),
93 fontSize: parsePx(pluginProps.fontSize || commonStyle.fontSize, isRem), 176 fontSize: parsePx(pluginProps.fontSize || commonStyle.fontSize, isRem),
  177 + ...boxModel,
  178 + // 'border-style': commonStyle['border-style'],
94 color: pluginProps.color || commonStyle.color, 179 color: pluginProps.color || commonStyle.color,
95 // backgroundColor: pluginProps.backgroundColor || commonStyle.backgroundColor, 180 // backgroundColor: pluginProps.backgroundColor || commonStyle.backgroundColor,
96 textAlign: pluginProps.textAlign || commonStyle.textAlign, 181 textAlign: pluginProps.textAlign || commonStyle.textAlign,