Ver código fonte

组件背景修改

dsy 1 mês atrás
pai
commit
706d73108d

+ 0 - 1
src/styles/mixin.scss

@@ -41,7 +41,6 @@
 @mixin preview-base {
   display: grid;
   gap: 6px;
-  background-repeat: no-repeat;
 
   :deep .rich-text {
     @include rich-text;

+ 13 - 0
src/views/book/courseware/create/components/SelectBackground.vue

@@ -10,6 +10,9 @@
       <div class="select-background-top">
         <span class="tab">{{ title }}</span>
         <SelectUpload :is-show-resource="isResource" type="image" @uploadSuccess="uploadSuccess" />
+        <el-select v-model="imageMode" style="width: 100px; margin-left: 4px">
+          <el-option v-for="item in imageModeList" :key="item.value" :label="item.label" :value="item.value" />
+        </el-select>
       </div>
       <div class="background-img">
         <div v-if="file_url" class="img-set" :style="{ top: `${imgData.top - 9}px`, left: `${imgData.left}px` }">
@@ -42,6 +45,8 @@
 <script>
 import SelectUpload from './common/SelectUpload.vue';
 
+import { imageModeList } from '@/views/book/courseware/data/common';
+
 export default {
   name: 'SelectBackground',
   components: {
@@ -74,6 +79,10 @@ export default {
       type: String,
       default: 'normal', // normal:正常,cover:覆盖
     },
+    type: {
+      type: String,
+      default: 'page', // component:组件背景图,page:页面背景图
+    },
   },
   data() {
     return {
@@ -87,6 +96,8 @@ export default {
         type: '',
       },
       imgData: this.position,
+      imageModeList,
+      imageMode: 'free',
     };
   },
   watch: {
@@ -111,6 +122,7 @@ export default {
             top: (val.top * this.maxHeight) / 100,
             left: (val.left * this.maxWidth) / 100,
           };
+          this.imageMode = val.image_mode || 'free';
         }
       },
       deep: true,
@@ -135,6 +147,7 @@ export default {
         height: (height / this.maxHeight) * 100,
         top: (top / this.maxHeight) * 100,
         left: (left / this.maxWidth) * 100,
+        image_mode: this.imageMode,
       });
     },
     /**

+ 52 - 3
src/views/book/courseware/create/components/common/BackgroundSet.vue

@@ -1,7 +1,9 @@
 <template>
   <div>
-    <el-form-item label="背景图" label-width="60px">
+    <el-form-item label="背景图" label-width="60px" style="position: relative">
       <el-button type="primary" size="mini" @click="openSetBackgroundImage">设置背景图</el-button>
+
+      <div class="background-image" :style="computedBackgroundImage()"></div>
     </el-form-item>
     <el-form-item label="背景色" label-width="60px">
       <el-color-picker v-model="propertyObj.background_color" :show-alpha="true" @change="changeBackgroundColor" />
@@ -13,9 +15,13 @@
         :disabled="!isEnable(propertyObj.is_border)"
         placeholder="请选择边框样式"
         style="width: 120px; margin-left: 10px"
+        popper-class="border-style"
         @change="changeBorderStyle"
       >
-        <el-option v-for="item in borderStyleList" :key="item.value" :label="item.label" :value="item.value" />
+        <el-option v-for="item in borderStyleList" :key="item.value" :label="item.label" :value="item.value">
+          {{ item.label }}
+          <span :style="{ borderStyle: item.value, borderWidth: item.value === 'double' ? '3px' : '1px' }"></span>
+        </el-option>
       </el-select>
       <el-color-picker
         v-model="propertyObj.border_color"
@@ -29,8 +35,9 @@
       :visible.sync="visible"
       image-fill-mode="cover"
       :is-resource="false"
-      :position="propertyObj.background_image_position"
+      :position="propertyObj.background_position"
       title="组件背景图"
+      type="component"
       :url="propertyObj.background_image_url"
       @setBackgroundImage="setBackgroundImage"
     />
@@ -119,11 +126,38 @@ export default {
 
       this.$message.success('设置背景图成功');
     },
+    computedBackgroundImage() {
+      const backgroundData = {};
+
+      if (Object.hasOwn(this.propertyObj, 'background_image_url')) {
+        // 保护性读取位置/大小值,避免 undefined 导致字符串 "undefined%"
+        const { background_position: pos } = this.propertyObj;
+        const widthPct = typeof pos.width === 'undefined' ? '' : pos.width;
+        const heightPct = typeof pos.height === 'undefined' ? '' : pos.height;
+        const leftPct = typeof pos.left === 'undefined' ? '' : pos.left;
+        const topPct = typeof pos.top === 'undefined' ? '' : pos.top;
+
+        backgroundData.backgroundImage = `url(${this.propertyObj.background_image_url})`;
+        backgroundData.backgroundSize = pos.image_mode === 'fill' ? '100% 100%' : `${widthPct}% ${heightPct}%`;
+        backgroundData.backgroundPosition = pos.image_mode === 'fill' ? '0% 0%' : `${leftPct}% ${topPct}%`;
+        backgroundData.backgroundRepeat = pos.image_mode === 'repeat' ? 'repeat' : 'no-repeat';
+      }
+      return backgroundData;
+    },
   },
 };
 </script>
 
 <style lang="scss" scoped>
+.background-image {
+  position: absolute;
+  left: 96px;
+  display: inline-block;
+  width: 100px;
+  height: 100px;
+  border: $border;
+}
+
 .border-setting {
   :deep .el-form-item__content {
     display: flex;
@@ -131,4 +165,19 @@ export default {
     align-items: center;
   }
 }
+
+.border-style {
+  .el-select-dropdown__item {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+
+    span {
+      display: inline-block;
+      width: 12px;
+      height: 12px;
+      border-color: #000;
+    }
+  }
+}
 </style>

+ 7 - 0
src/views/book/courseware/data/common.js

@@ -66,6 +66,13 @@ export const borderStyleList = [
   { value: 'double', label: '双线' },
 ];
 
+// 图片显示模式
+export const imageModeList = [
+  { value: 'free', label: '自由' },
+  { value: 'fill', label: '填充' },
+  { value: 'repeat', label: '平铺' },
+];
+
 // 序号样式
 export const serialNumberStyleList = [
   { value: 'solidBlockStyle' }, // 实心方块

+ 25 - 16
src/views/book/courseware/preview/components/common/PreviewMixin.js

@@ -149,25 +149,34 @@ const mixin = {
      * 得到背景图、背景色及边框样式
      */
     getComponentStyle() {
-      if (!Object.hasOwn(this.data.property, 'background_image_url')) return {};
+      let backgroundData = {};
+      if (Object.hasOwn(this.data.property, 'background_image_url')) {
+        // 保护性读取位置/大小值,避免 undefined 导致字符串 "undefined%"
+        const { background_position: pos } = this.data.property;
+        const widthPct = typeof pos.width === 'undefined' ? '' : pos.width;
+        const heightPct = typeof pos.height === 'undefined' ? '' : pos.height;
+        const leftPct = typeof pos.left === 'undefined' ? '' : pos.left;
+        const topPct = typeof pos.top === 'undefined' ? '' : pos.top;
 
-      // 保护性读取位置/大小值,避免 undefined 导致字符串 "undefined%"
-      const { background_position: pos } = this.data.property;
-      const widthPct = typeof pos.width === 'undefined' ? '' : pos.width;
-      const heightPct = typeof pos.height === 'undefined' ? '' : pos.height;
-      const leftPct = typeof pos.left === 'undefined' ? '' : pos.left;
-      const topPct = typeof pos.top === 'undefined' ? '' : pos.top;
+        backgroundData.backgroundImage = `url(${this.data.property.background_image_url})`;
+        backgroundData.backgroundSize = pos.image_mode === 'fill' ? '100% 100%' : `${widthPct}% ${heightPct}%`;
+        backgroundData.backgroundPosition = pos.image_mode === 'fill' ? '0% 0%' : `${leftPct}% ${topPct}%`;
+        backgroundData.backgroundRepeat = pos.image_mode === 'repeat' ? 'repeat' : 'no-repeat';
+      }
+
+      let borderData = {};
+      if (Object.hasOwn(this.data.property, 'is_border')) {
+        const isBorder = isEnable(this.data.property.is_border);
+        borderData.borderWidth = isBorder ? (this.data.property.border_style === 'double' ? '3px' : '1px') : '0px';
+        borderData.borderStyle = isBorder ? this.data.property.border_style : 'none';
+        borderData.borderColor = isBorder ? this.data.property.border_color : 'transparent';
+      }
 
-      let style = {
-        backgroundColor: this.data.property.background_color,
-        backgroundImage: `url(${this.data.property.background_image_url})`,
-        backgroundSize: `${widthPct}% ${heightPct}%`,
-        backgroundPosition: `${leftPct}% ${topPct}%`,
-        borderWidth: isEnable(this.data.property.is_border) ? '1px' : '0px',
-        borderStyle: isEnable(this.data.property.is_border) ? this.data.property.border_style : 'none',
-        borderColor: isEnable(this.data.property.is_border) ? this.data.property.border_color : 'transparent',
+      return {
+        backgroundColor: this.data.property?.background_color,
+        ...backgroundData,
+        ...borderData,
       };
-      return style;
     },
   },
 };