Sfoglia il codice sorgente

优化构建背景样式方法,支持动态更新

dsy 2 settimane fa
parent
commit
02f38c29f4

+ 18 - 17
src/components/CommonPreview.vue

@@ -111,11 +111,11 @@
           <SvgIcon icon-class="catalogue" size="54" />
         </div>
 
-        <main :class="['preview-main', { 'no-audit': !isShowAudit }]" :style="computedCommonPreviewStyle()">
+        <main :class="['preview-main', { 'no-audit': !isShowAudit }]" :style="computedCommonPreviewStyle">
           <div class="preview-left" :style="{ backgroundColor: background.background?.is_global ? '' : '#fff' }"></div>
           <CoursewarePreview
             v-if="courseware_info.book_name"
-            ref="courserware"
+            ref="courseware"
             :is-show-group="isShowGroup"
             :group-show-all="groupShowAll"
             :group-row-list="content_group_row_list"
@@ -516,6 +516,7 @@ import {
 import { toggleFullScreen } from '@/utils/common';
 import * as OpenCC from 'opencc-js';
 import { isTrue } from '@/utils/validate';
+import { buildCoursewareStyle } from '@/views/book/courseware/preview/common/utils/coursewareStyle';
 import { CreateCoursewarePreviewURL } from '@/api/app';
 
 export default {
@@ -742,6 +743,9 @@ export default {
       if (this.dialogType === 2) return '反馈';
       return '笔记';
     },
+    computedCommonPreviewStyle() {
+      return buildCoursewareStyle(this.background, 'commonPreview');
+    },
   },
   watch: {
     isJudgeCorrect(newVal) {
@@ -1020,7 +1024,7 @@ export default {
           this.submit_loading = false;
           this.visibleRemark = false;
           this.getCoursewareAuditRemarkList(id || this.id);
-          this.$refs.courserware.resetRemark();
+          this.$refs.courseware.resetRemark();
         })
         .catch(() => {
           this.submit_loading = false;
@@ -1029,7 +1033,7 @@ export default {
     // 关闭审核批注弹窗
     closeVisibleRemark() {
       this.visibleRemark = false;
-      this.$refs.courserware.resetRemark();
+      this.$refs.courseware.resetRemark();
     },
     // 删除批注
     deleteRemarks(id) {
@@ -1049,7 +1053,7 @@ export default {
     // 定位批注
     async handleLocationRemarks(offsetTop) {
       // if (componentId) {
-      //   let node = await this.$refs.courserware.findChildComponentByKey(componentId);
+      //   let node = await this.$refs.courseware.findChildComponentByKey(componentId);
       //   if (node) {
       await this.$nextTick();
       this.$refs.previewMain.scrollTo({
@@ -1062,7 +1066,7 @@ export default {
     },
     // 计算previewMain滑动距离
     computeScroll() {
-      this.$refs.courserware.handleResult(
+      this.$refs.courseware.handleResult(
         this.$refs.previewMain.scrollTop,
         this.$refs.previewMain.scrollLeft,
         this.select_node,
@@ -1105,7 +1109,7 @@ export default {
       let [nodeId, componentId] = data.split('#');
       if (nodeId) this.selectNode(nodeId);
       if (componentId) {
-        let node = await this.$refs.courserware.findChildComponentByKey(componentId);
+        let node = await this.$refs.courseware.findChildComponentByKey(componentId);
         if (node) {
           await this.$nextTick();
           this.$refs.previewMain.scrollTo({
@@ -1243,7 +1247,7 @@ export default {
     async handleFileClick(courseware_id, component_id) {
       if (courseware_id) this.selectNode(courseware_id);
       if (component_id) {
-        let node = await this.$refs.courserware.findChildComponentByKey(component_id);
+        let node = await this.$refs.courseware.findChildComponentByKey(component_id);
         if (node) {
           await this.$nextTick();
           this.$refs.previewMain.scrollTo({
@@ -1310,7 +1314,7 @@ export default {
     },
 
     simulateAnswer(disabled = true) {
-      this.$refs.courserware.simulateAnswer(this.isJudgeCorrect, this.isShowAnswer, disabled);
+      this.$refs.courseware.simulateAnswer(this.isJudgeCorrect, this.isShowAnswer, disabled);
     },
 
     /**
@@ -1325,7 +1329,7 @@ export default {
       this.selectNode(nodeId);
       this.isShowGroup = false;
       this.groupShowAll = true;
-      this.$refs.courserware.clearRowCheckList();
+      this.$refs.courseware.clearRowCheckList();
     },
     /**
      * 计算章节名称样式
@@ -1403,9 +1407,9 @@ export default {
         return;
       }
 
-      if (this.$refs.courserware && this.$refs.courserware.handleLocation) {
+      if (this.$refs.courseware && this.$refs.courseware.handleLocation) {
         item.type = type;
-        this.$refs.courserware.handleLocation(item);
+        this.$refs.courseware.handleLocation(item);
       }
     },
 
@@ -1754,10 +1758,10 @@ export default {
      * @returns {object} 选中分组行的课件信息
      */
     computedSelectedGroupCoursewareInfo() {
-      return this.$refs.courserware.computedSelectedGroupCoursewareInfo();
+      return this.$refs.courseware.computedSelectedGroupCoursewareInfo();
     },
     saveCoursewareStyleTemplate(data) {
-      return this.$refs.courserware.saveCoursewareStyleTemplate(data);
+      return this.$refs.courseware.saveCoursewareStyleTemplate(data);
     },
 
     async submitChapterAllCoursewareToAuditFlow(chapter_id) {
@@ -1792,9 +1796,6 @@ export default {
         this.$set(component, 'background', background);
       }
     },
-    computedCommonPreviewStyle() {
-      return this.$refs.courserware?.computedCourserwareStyle('commonPreview');
-    },
     /**
      * 获取 main-container 视口内第一个可见的组件 id
      * @returns {string} 第一个可见组件 id;不存在时返回空字符串

+ 1 - 1
src/views/book/courseware/create/components/PreviewEdit.vue

@@ -128,7 +128,7 @@ export default {
   },
   mounted() {
     const element = this.$refs.previewRoot;
-    // 监听 courserware 高度变化,获取其高度
+    // 监听 courseware 高度变化,获取其高度
     this.resizeObserver = new ResizeObserver(() => {
       const rect = element.getBoundingClientRect();
       this.heightPrompt = rect.height > 1620;

+ 2 - 2
src/views/book/courseware/create/components/SetBackground.vue

@@ -278,7 +278,7 @@ export default {
         const isGlobal = this.backgroundData.is_global;
         const courseware = isGlobal
           ? document.querySelector('main.preview-main')
-          : document.querySelector('div.courserware');
+          : document.querySelector('div.courseware');
         if (courseware) {
           const rect = courseware.getBoundingClientRect();
           const coursewareRatio = rect.width / rect.height;
@@ -316,7 +316,7 @@ export default {
     'background.is_global'(newVal) {
       const courseware = newVal
         ? document.querySelector('main.preview-main')
-        : document.querySelector('div.courserware');
+        : document.querySelector('div.courseware');
       if (courseware) {
         const rect = courseware.getBoundingClientRect();
         const coursewareRatio = rect.width / rect.height;

+ 13 - 86
src/views/book/courseware/preview/CoursewarePreview.vue

@@ -1,9 +1,9 @@
 <template>
   <div
     id="selectable-area-preview"
-    ref="courserware"
-    class="courserware"
-    :style="computedCourserwareStyle('courseware')"
+    ref="courseware"
+    class="courseware"
+    :style="computedCoursewareStyle"
     @mouseup="handleTextSelection"
     @mousedown="startSelection"
     @mousemove="updateSelection"
@@ -174,6 +174,7 @@
 <script>
 import { previewComponentList } from '@/views/book/courseware/data/bookType';
 import { getToken, getConfig } from '@/utils/auth';
+import { buildCoursewareStyle } from '@/views/book/courseware/preview/common/utils/coursewareStyle';
 import _ from 'lodash';
 const Base64 = require('js-base64').Base64;
 
@@ -267,6 +268,12 @@ export default {
       visible_id: this.$route.query?.visible_id || '', // 可见组件 id
     };
   },
+  computed: {
+    // 计算课件背景样式
+    computedCoursewareStyle() {
+      return buildCoursewareStyle(this.background, 'courseware');
+    },
+  },
   watch: {
     groupRowList: {
       handler(val) {
@@ -286,7 +293,7 @@ export default {
     },
   },
   mounted() {
-    const element = this.$refs.courserware;
+    const element = this.$refs.courseware;
     const rect = element.getBoundingClientRect();
     this.divPosition = {
       left: rect.left,
@@ -656,86 +663,6 @@ export default {
         gridTemplateRows,
       };
     },
-
-    /**
-     * 计算课件背景样式
-     * @param {'courseware' | 'commonPreview'} type 从哪个组件调用 'courseware' 或 'commonPreview'
-     * @returns {object} 课件背景样式对象
-     */
-    computedCourserwareStyle(type) {
-      const {
-        background_image_url: bcImgUrl = '',
-        background_position: pos = {},
-        background: back,
-      } = this.background || {};
-
-      // 如果是 commonPreview 但背景不是全域的,或者是 courseware 但背景是全域的,都不应用背景样式
-      if (type === 'commonPreview' && !back?.is_global) {
-        return {};
-      }
-      if (type === 'courseware' && back?.is_global) {
-        return {};
-      }
-
-      let canvasStyle = {
-        backgroundSize: bcImgUrl ? `${pos.width}% ${pos.height}%` : '',
-        backgroundPosition: bcImgUrl ? `${pos.left}% ${pos.top}%` : '',
-        backgroundImage: bcImgUrl ? `url(${bcImgUrl})` : '',
-      };
-
-      if (back) {
-        if (!back.has_image) {
-          canvasStyle['backgroundBlendMode'] = '';
-          canvasStyle['backgroundImage'] = '';
-          canvasStyle['backgroundRepeat'] = '';
-          canvasStyle['backgroundPosition'] = '';
-          canvasStyle['backgroundSize'] = '';
-        }
-
-        if (back.imageMode === 'fill') {
-          canvasStyle['backgroundRepeat'] = 'repeat';
-          canvasStyle['backgroundSize'] = '';
-          canvasStyle['backgroundPosition'] = '';
-        } else {
-          canvasStyle['backgroundRepeat'] = 'no-repeat';
-        }
-
-        if (back.imageMode === 'stretch') {
-          canvasStyle['backgroundSize'] = '100% 100%';
-        }
-
-        if (back.imageMode === 'adapt') {
-          canvasStyle['backgroundSize'] = 'contain';
-        }
-
-        if (back.imageMode === 'auto') {
-          canvasStyle['backgroundPosition'] = `${pos.imgX}% ${pos.imgY}%`;
-        }
-
-        if (back.has_color) {
-          canvasStyle['backgroundColor'] = back.color;
-        } else {
-          canvasStyle['backgroundColor'] = '#fff';
-        }
-
-        if (back.enable_border) {
-          canvasStyle['border'] = `${back.border_width}px ${back.border_style} ${back.border_color}`;
-        } else {
-          canvasStyle['border'] = 'none';
-        }
-
-        if (back.enable_radius) {
-          canvasStyle['border-top-left-radius'] = `${back.top_left_radius}px`;
-          canvasStyle['border-top-right-radius'] = `${back.top_right_radius}px`;
-          canvasStyle['border-bottom-left-radius'] = `${back.bottom_left_radius}px`;
-          canvasStyle['border-bottom-right-radius'] = `${back.bottom_right_radius}px`;
-        } else {
-          canvasStyle['border-radius'] = '0';
-        }
-      }
-
-      return canvasStyle;
-    },
     handleContextMenu(event, id) {
       if (this.canRemark) {
         event.preventDefault(); // 阻止默认的上下文菜单显示
@@ -862,7 +789,7 @@ export default {
         this.selectHandleInfo = selectHandleInfo;
 
         if (!this.canRemark) this.showToolbar = true;
-        const container = document.querySelector('.courserware');
+        const container = document.querySelector('.courseware');
         const boxRect = container.getBoundingClientRect();
         const selectRect = range.getBoundingClientRect();
         this.contentmenu = {
@@ -1228,7 +1155,7 @@ export default {
 </script>
 
 <style lang="scss" scoped>
-.courserware {
+.courseware {
   position: relative;
   display: flex;
   flex-direction: column;

+ 77 - 0
src/views/book/courseware/preview/common/utils/coursewareStyle.js

@@ -0,0 +1,77 @@
+/**
+ * 构建课件背景样式
+ * @param {object} background 背景信息
+ * @param {string} type 预览类型,commonPreview: 公共预览,courseware: 课件预览
+ * @returns {object} 样式对象
+ */
+export function buildCoursewareStyle(background, type) {
+  const { background_image_url: bcImgUrl = '', background_position: pos = {}, background: back } = background || {};
+
+  if (type === 'commonPreview' && !back?.is_global) {
+    return {};
+  }
+  if (type === 'courseware' && back?.is_global) {
+    return {};
+  }
+
+  const canvasStyle = {
+    backgroundSize: bcImgUrl ? `${pos.width}% ${pos.height}%` : '',
+    backgroundPosition: bcImgUrl ? `${pos.left}% ${pos.top}%` : '',
+    backgroundImage: bcImgUrl ? `url(${bcImgUrl})` : '',
+  };
+
+  if (!back) {
+    return canvasStyle;
+  }
+
+  if (!back.has_image) {
+    canvasStyle.backgroundBlendMode = '';
+    canvasStyle.backgroundImage = '';
+    canvasStyle.backgroundRepeat = '';
+    canvasStyle.backgroundPosition = '';
+    canvasStyle.backgroundSize = '';
+  }
+
+  if (back.imageMode === 'fill') {
+    canvasStyle.backgroundRepeat = 'repeat';
+    canvasStyle.backgroundSize = '';
+    canvasStyle.backgroundPosition = '';
+  } else {
+    canvasStyle.backgroundRepeat = 'no-repeat';
+  }
+
+  if (back.imageMode === 'stretch') {
+    canvasStyle.backgroundSize = '100% 100%';
+  }
+
+  if (back.imageMode === 'adapt') {
+    canvasStyle.backgroundSize = 'contain';
+  }
+
+  if (back.imageMode === 'auto') {
+    canvasStyle.backgroundPosition = `${pos.imgX}% ${pos.imgY}%`;
+  }
+
+  if (back.has_color) {
+    canvasStyle.backgroundColor = back.color;
+  } else {
+    canvasStyle.backgroundColor = '#fff';
+  }
+
+  if (back.enable_border) {
+    canvasStyle.border = `${back.border_width}px ${back.border_style} ${back.border_color}`;
+  } else {
+    canvasStyle.border = 'none';
+  }
+
+  if (back.enable_radius) {
+    canvasStyle['border-top-left-radius'] = `${back.top_left_radius}px`;
+    canvasStyle['border-top-right-radius'] = `${back.top_right_radius}px`;
+    canvasStyle['border-bottom-left-radius'] = `${back.bottom_left_radius}px`;
+    canvasStyle['border-bottom-right-radius'] = `${back.bottom_right_radius}px`;
+  } else {
+    canvasStyle.borderRadius = '0';
+  }
+
+  return canvasStyle;
+}

+ 1 - 1
src/views/personal_workbench/edit_task/edit/UseTemplate.vue

@@ -65,7 +65,7 @@
         </div>
         <CoursewarePreview
           v-if="coursewareData.row_list?.length > 0"
-          ref="courserware"
+          ref="courseware"
           :is-show-group="false"
           :group-show-all="true"
           :group-row-list="content_group_row_list"

+ 1 - 1
src/views/personal_workbench/template_list/preview/CommonPreview.vue

@@ -39,7 +39,7 @@
           <div class="preview-left"></div>
           <CoursewarePreview
             v-if="courseware_info.book_name || courseware_info.name"
-            ref="courserware"
+            ref="courseware"
             :is-show-group="false"
             :group-show-all="true"
             :group-row-list="content_group_row_list"