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 1 <template>
2   - <div class="box-model">
  2 + <div v-if="editingElement" class="box-model">
3 3 <div v-if="lastSelect" class="prompt">设置 {{ lastSelect }} 大小</div>
4 4 <div v-else>选择 margin/border/padding 设置大小</div>
5   - <PositionCheckbox label="上" />
  5 + <PositionCheckbox label="上" label-key="top" />
6 6 <div class="middle">
7   - <PositionCheckbox label="左" />
  7 + <PositionCheckbox label="左" label-key="left" />
8 8 <div ref="margin" class="margin" data-type="margin" @click="onBoxModelClick">
9 9 margin
10 10 <div ref="border" class="border" data-type="border">
... ... @@ -14,13 +14,14 @@
14 14 </div>
15 15 </div>
16 16 </div>
17   - <PositionCheckbox label="右" />
  17 + <PositionCheckbox label="右" label-key="right" />
18 18 </div>
19   - <PositionCheckbox label="下" />
  19 + <PositionCheckbox label="下" label-key="bottom" />
20 20 </div>
21 21 </template>
22 22  
23 23 <script>
  24 + import { mapState, mapActions } from 'vuex'
24 25 import PositionCheckbox from './position-checkbox'
25 26 export default {
26 27 name: 'BoxModel',
... ... @@ -32,14 +33,24 @@
32 33 lastSelect: ''
33 34 }
34 35 },
35   -
  36 + computed: {
  37 + ...mapState('editor', {
  38 + editingElement: state => state.editingElement
  39 + })
  40 + },
36 41 methods: {
  42 + ...mapActions('editor', [
  43 + 'setElementPosition'
  44 + ]),
37 45 onBoxModelClick (e) {
38 46 const target = e.target
39 47 const classList = target.classList
40 48 const type = target.dataset.type
41 49 const selectClass = type + '-select'
42   -
  50 + // 更新选中的 boxModelPart,用于判断当前设置的是 margin / border / padding
  51 + this.setElementPosition({
  52 + boxModelPart: type
  53 + })
43 54 if (this.lastSelect && type !== this.lastSelect) {
44 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 1 <template>
2 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 17 </div>
21 18 </template>
22 19  
23 20 <script>
  21 + import { mapState, mapActions } from 'vuex'
24 22 export default {
25 23 name: 'PositionCheckbox',
26 24 props: {
27 25 label: {
28 26 type: String,
29 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 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 65 </script>
... ...
front-end/h5/src/components/core/models/element.js
... ... @@ -13,7 +13,69 @@ const defaultStyle = {
13 13 textAlign: 'center',
14 14 color: '#000000',
15 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 81 class Element {
... ... @@ -75,7 +137,25 @@ class Element {
75 137  
76 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 159 getStyle ({ position = 'static', isRem = false } = {}) {
80 160 if (this.name === 'lbp-background') {
81 161 return {
... ... @@ -85,12 +165,17 @@ class Element {
85 165 }
86 166 const pluginProps = this.pluginProps
87 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 171 let style = {
89 172 top: parsePx(pluginProps.top || commonStyle.top, isRem),
90 173 left: parsePx(pluginProps.left || commonStyle.left, isRem),
91 174 width: parsePx(pluginProps.width || commonStyle.width, isRem),
92 175 height: parsePx(pluginProps.height || commonStyle.height, isRem),
93 176 fontSize: parsePx(pluginProps.fontSize || commonStyle.fontSize, isRem),
  177 + ...boxModel,
  178 + // 'border-style': commonStyle['border-style'],
94 179 color: pluginProps.color || commonStyle.color,
95 180 // backgroundColor: pluginProps.backgroundColor || commonStyle.backgroundColor,
96 181 textAlign: pluginProps.textAlign || commonStyle.textAlign,
... ...