瀏覽代碼

Merge branch 'master' into lhd

natasha 1 年之前
父節點
當前提交
3eb7da6422

+ 3 - 3
package-lock.json

@@ -7234,9 +7234,9 @@
       }
     },
     "node_modules/electron": {
-      "version": "29.3.2",
-      "resolved": "https://registry.npmmirror.com/electron/-/electron-29.3.2.tgz",
-      "integrity": "sha512-pRWsaFtbd78kEHR0lg5aMhZDY6b5JykIEhZRtyTCaJpGFObB2NFIJDzR7mTia0cZp3pPq60n/SS4gRxvSM5WFQ==",
+      "version": "29.4.2",
+      "resolved": "https://registry.npmmirror.com/electron/-/electron-29.4.2.tgz",
+      "integrity": "sha512-XyIkuWQguwY8hGtLg0j5Q4Fqphdbh0ctBsKCSVzJ/R7Z2+2WN/oQ1M+zYwchmfiDgiuL3EKkrBrfPdxXYdMr+A==",
       "dev": true,
       "hasInstallScript": true,
       "dependencies": {

+ 2 - 1
src/styles/variables.scss

@@ -18,7 +18,8 @@ $error-color: #f2555a;
 $right-color: #30a47d;
 $right-bc-color: #e8f7f2;
 $label-color: #076aff;
-$setting-active-color: #4176FF;
+$setting-active-color: #4176ff;
 
 // px
 $header-h: 64px;
+$courseware-width: 1000px;

+ 5 - 1
src/views/book/chapter.vue

@@ -171,7 +171,11 @@ export default {
       this.visibleStatus = false;
     },
     addCoursewareToBook() {
-      AddCoursewareToBook({ book_id: this.book_id, chapter_id: this.curChapterId, name: '教材内容' }).then(() => {
+      AddCoursewareToBook({
+        book_id: this.book_id,
+        chapter_id: this.curChapterId,
+        name: `教材内容${this.coursewareDataList.length + 1}`,
+      }).then(() => {
         this.getCoursewareList_Chapter(this.curChapterId);
         this.$message.success('添加成功');
       });

+ 2 - 1
src/views/book/components/catalogueTree.vue

@@ -2,7 +2,8 @@
   <div class="node-wrapper">
     <div v-for="node in nodes" :key="node.id" :class="['node', { active: getCurChapterId() === node.id }]">
       <div
-        :class="['node-name', { content: node.is_leaf_chapter === 'true' }]"
+        :class="['node-name', 'nowrap-ellipsis', { content: node.is_leaf_chapter === 'true' }]"
+        :title="node.name"
         @click="handleSelectNode(node.is_leaf_chapter, node.id)"
       >
         <span>{{ node.name }}</span>

+ 3 - 3
src/views/book/courseware/create/components/CreateCanvas.vue

@@ -845,7 +845,7 @@ export default {
   display: flex;
   flex-direction: column;
   row-gap: 6px;
-  width: 1100px;
+  width: $courseware-width;
   min-height: calc(100% - 56px);
   padding: 24px;
   margin: 0 auto;
@@ -887,7 +887,7 @@ export default {
   }
 
   .drag-line {
-    z-index: 9;
+    z-index: 2;
     width: calc(100% - 16px);
     height: 4px;
     margin: 0 8px;
@@ -907,7 +907,7 @@ export default {
 
   .drag-vertical-line {
     position: relative;
-    z-index: 9;
+    z-index: 2;
     width: 4px;
     height: 100%;
     background-color: #379fff;

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

@@ -337,7 +337,7 @@ export default {
       }
 
       .drag-line {
-        z-index: 9;
+        z-index: 2;
         width: 100%;
         height: 6px;
         cursor: ns-resize;
@@ -356,7 +356,7 @@ export default {
       }
 
       .drag-vertical-line {
-        z-index: 9;
+        z-index: 2;
         width: 6px;
         height: 100%;
         cursor: ew-resize;

+ 1 - 1
src/views/book/courseware/data/audio.js

@@ -24,7 +24,7 @@ export function getAudioData() {
     single_size: 100, // 单位MB
     total_size: 1024, // 单位MB
     min_width: '280',
-    min_height: '152',
+    min_height: '110',
     property: getAudioProperty(),
     file_info_list: [],
     file_id_list: [], // 文件 id['20032-121212', '20032-121216']

+ 1 - 1
src/views/book/courseware/data/picture.js

@@ -19,7 +19,7 @@ export function getPictureData() {
   return {
     type: 'picture',
     title: '图片',
-    single_size: 2, // 单位MB
+    single_size: 1, // 单位MB
     total_size: 100, // 单位MB
     min_width: '144', // 大于等于最小缩略图宽度
     min_height: '306', // 大于等于2倍缩略图宽度加间隙高度

+ 1 - 1
src/views/book/courseware/preview/CoursewarePreview.vue

@@ -188,7 +188,7 @@ export default {
   display: flex;
   flex-direction: column;
   row-gap: 6px;
-  width: 1100px;
+  width: $courseware-width;
   min-height: 500px;
   padding: 24px;
   background-color: #fff;

+ 2 - 0
src/views/book/courseware/preview/common/SoundRecord.vue

@@ -313,8 +313,10 @@ export default {
 <style lang="scss" scoped>
 .record {
   display: flex;
+  grid-area: record;
   align-items: center;
   justify-content: center;
+  max-width: 160px;
   height: 32px;
 
   .playBack {

+ 27 - 9
src/views/book/courseware/preview/components/audio/AudioPreview.vue

@@ -76,7 +76,7 @@ export default {
       fileLen: 0,
       viewScroll: 'hidden',
       elementID: '',
-      observersMap: {},
+      audioObserversMap: {},
     };
   },
   watch: {
@@ -85,8 +85,19 @@ export default {
         this.fileLen = val.file_list.length;
         if (this.fileLen > 0 && this.data.property.view_method === 'list') {
           const ele = this.$refs.audioAreaBox;
-          this.elementWidth = ele.clientWidth;
-          this.elementHeight = ele.clientHeight;
+          // this.elementWidth = ele.clientWidth;
+          // this.elementHeight = ele.clientHeight;
+
+          const sn_position = this.data.property.sn_position;
+          // 序号在左和右补齐序号高度,去掉padding(8*2)
+          if (sn_position.includes('left') || sn_position.includes('right')) {
+            this.elementWidth = ele.clientWidth - 16;
+            this.elementHeight = ele.clientHeight + 30;
+          } else {
+            this.elementWidth = ele.clientWidth;
+            this.elementHeight = ele.clientHeight;
+          }
+
           const mainEle = this.$refs.audioArea;
           // 检查元素是否包含已知的类名
           mainEle.classList.forEach((className) => {
@@ -115,20 +126,27 @@ export default {
       const canvasElement = document.querySelector('.canvas');
       if (!canvasElement) return;
       const instanceName = `observer_${this.elementID}`;
-      this.observersMap[instanceName] = new ResizeObserver((entries) => {
+      this.audioObserversMap[instanceName] = new ResizeObserver((entries) => {
         if (!this.getDragStatus()) return;
         for (let entry of entries) {
           window.requestAnimationFrame(() => {
-            this.elementWidth = entry.contentRect.width;
-            this.elementHeight = entry.contentRect.height;
+            const sn_position = this.data.property.sn_position;
+            // 序号在上方和下方减去序号高度,在左右去掉padding(8*2)
+            if (sn_position.includes('top') || sn_position.includes('bottom')) {
+              this.elementWidth = entry.contentRect.width;
+              this.elementHeight = entry.contentRect.height - 30;
+            } else {
+              this.elementWidth = entry.contentRect.width - 16;
+              this.elementHeight = entry.contentRect.height;
+            }
           });
         }
       });
-      this.observersMap[instanceName].observe(this.$el);
+      this.audioObserversMap[instanceName].observe(this.$el);
     });
   },
   beforeDestroy() {
-    Object.values(this.observersMap).forEach((observer) => {
+    Object.values(this.audioObserversMap).forEach((observer) => {
       observer.disconnect();
     });
   },
@@ -177,7 +195,7 @@ export default {
   padding: 8px;
 
   > .main {
-    margin: 4px auto;
+    margin: 0 auto;
 
     > span {
       display: flex;

+ 5 - 2
src/views/book/courseware/preview/components/common/PreviewMixin.js

@@ -40,8 +40,11 @@ const mixin = {
      * 得到序号外部样式
      */
     getAreaStyle() {
-      if (!isEnable(this.data.property.sn_display_mode)) return {};
-
+      if (!isEnable(this.data.property.sn_display_mode)) {
+        return {
+          grid: `"main" / 1fr`,
+        };
+      }
       const position = this.data.property.sn_position;
       let grid = '';
 

+ 40 - 12
src/views/book/courseware/preview/components/fill/FillPreview.vue

@@ -13,19 +13,25 @@
               <el-input
                 :key="j"
                 v-model="li.content"
-                :style="[{ width: Math.max(80, li.content.length * 21.3) + 'px' }, { 'font-family': fontFamily }]"
+                :class="[data.property.fill_font]"
+                :style="[{ width: Math.max(80, li.content.length * 21.3) + 'px' }]"
               />
             </template>
           </template>
         </p>
       </div>
-      <SoundRecord ref="record" type="normal" class="record-box" />
+      <SoundRecord
+        v-if="isEnable(data.property.is_enable_voice_answer)"
+        ref="record"
+        type="normal"
+        class="record-box"
+      />
     </div>
   </div>
 </template>
 
 <script>
-import { getFillData, fillFontList, arrangeTypeList } from '@/views/book/courseware/data/fill';
+import { getFillData, fillFontList, arrangeTypeList, audioPositionList } from '@/views/book/courseware/data/fill';
 
 import PreviewMixin from '../common/PreviewMixin';
 import AudioFill from './components/AudioFillPlay.vue';
@@ -67,14 +73,24 @@ export default {
   methods: {
     getMainStyle() {
       const isRow = this.data.property.arrange_type === arrangeTypeList[0].value;
+      const isFront = this.data.property.audio_position === audioPositionList[0].value;
+      const isEnableVoice = this.data.property.is_enable_voice_answer === 'true';
+      let _list = [
+        { name: 'audio', value: '24px' },
+        { name: 'fill', value: '1fr' },
+      ];
+      if (!isFront) {
+        _list = _list.reverse();
+      }
+      let grid = isRow
+        ? `"${_list[0].name} ${_list[1].name}${isEnableVoice ? ' record' : ''}" auto / ${_list[0].value} ${_list[1].value}${isEnableVoice ? ' 160px' : ''}`
+        : `"${_list[0].name}" ${_list[0].value} "${_list[1].name}" ${_list[1].value}${isEnableVoice ? `" record" 32px ` : ''} / 1fr`;
       let style = {
-        'flex-direction': isRow ? 'row' : 'column',
+        'grid-auto-flow': isRow ? 'column' : 'row',
+        'column-gap': isRow ? '16px' : undefined,
+        'row-gap': isRow ? undefined : '8px',
+        grid,
       };
-      if (isRow) {
-        style['column-gap'] = '16px';
-      } else {
-        style['row-gap'] = '8px';
-      }
       return style;
     },
   },
@@ -88,12 +104,12 @@ export default {
   @include preview-base;
 
   .main {
-    display: flex;
-    align-items: flex-start;
+    display: grid;
+    align-items: center;
   }
 
   .fill-wrapper {
-    flex: 1;
+    grid-area: fill;
     font-size: 16pt;
 
     p {
@@ -106,6 +122,18 @@ export default {
       width: 120px;
       margin: 0 2px;
 
+      &.pinyin :deep input.el-input__inner {
+        font-family: 'PINYIN-B', sans-serif;
+      }
+
+      &.chinese :deep input.el-input__inner {
+        font-family: 'arial', sans-serif;
+      }
+
+      &.english :deep input.el-input__inner {
+        font-family: 'arial', sans-serif;
+      }
+
       :deep input.el-input__inner {
         padding: 0;
         font-size: 16pt;

+ 2 - 0
src/views/book/courseware/preview/components/fill/components/AudioFillPlay.vue

@@ -125,6 +125,8 @@ export default {
 
 <style lang="scss" scoped>
 .audio-fill {
+  grid-area: audio;
+
   .audio-play {
     width: 24px;
     height: 24px;

+ 26 - 8
src/views/book/courseware/preview/components/picture/PicturePreview.vue

@@ -57,7 +57,7 @@ export default {
       viewLeftRightBtn: false,
       fileLen: 0,
       elementID: '',
-      observersMap: {},
+      pictureObserversMap: {},
     };
   },
   watch: {
@@ -66,8 +66,19 @@ export default {
         this.fileLen = val.file_list.length;
         if (this.fileLen > 0 && this.data.property.view_method === 'list') {
           const ele = this.$refs.pictureAreaBox;
-          this.elementWidth = ele.clientWidth;
-          this.elementHeight = ele.clientHeight;
+          // this.elementWidth = ele.clientWidth;
+          // this.elementHeight = ele.clientHeight;
+
+          const sn_position = this.data.property.sn_position;
+          // 序号在左和右补齐序号高度,去掉padding(8*2)
+          if (sn_position.includes('left') || sn_position.includes('right')) {
+            this.elementWidth = ele.clientWidth - 16;
+            this.elementHeight = ele.clientHeight + 30;
+          } else {
+            this.elementWidth = ele.clientWidth;
+            this.elementHeight = ele.clientHeight;
+          }
+
           const mainEle = this.$refs.pictureArea;
           // 检查元素是否包含已知的类名
           mainEle.classList.forEach((className) => {
@@ -94,20 +105,27 @@ export default {
       const canvasElement = document.querySelector('.canvas');
       if (!canvasElement) return;
       const instanceName = `observer_${this.elementID}`;
-      this.observersMap[instanceName] = new ResizeObserver((entries) => {
+      this.pictureObserversMap[instanceName] = new ResizeObserver((entries) => {
         if (!this.getDragStatus()) return;
         for (let entry of entries) {
           window.requestAnimationFrame(() => {
-            this.elementWidth = entry.contentRect.width;
-            this.elementHeight = entry.contentRect.height;
+            const sn_position = this.data.property.sn_position;
+            // 序号在上方和下方减去序号高度,在左右去掉padding(8*2)
+            if (sn_position.includes('top') || sn_position.includes('bottom')) {
+              this.elementWidth = entry.contentRect.width;
+              this.elementHeight = entry.contentRect.height - 30;
+            } else {
+              this.elementWidth = entry.contentRect.width - 16;
+              this.elementHeight = entry.contentRect.height;
+            }
           });
         }
       });
-      this.observersMap[instanceName].observe(this.$el);
+      this.pictureObserversMap[instanceName].observe(this.$el);
     });
   },
   beforeDestroy() {
-    Object.values(this.observersMap).forEach((observer) => {
+    Object.values(this.pictureObserversMap).forEach((observer) => {
       observer.disconnect();
     });
   },

+ 29 - 9
src/views/book/courseware/preview/components/video/VideoPreview.vue

@@ -31,7 +31,7 @@
             />
           </el-carousel-item>
         </el-carousel>
-        <div class="container-box">
+        <div class="container-box" :style="{ height: elementHeight + 'px' }">
           <ul
             ref="container"
             class="view-list-bottom"
@@ -73,7 +73,7 @@ export default {
       fileLen: 0,
       translateY: 0,
       elementID: '',
-      observersMap: {},
+      videoObserversMap: {},
     };
   },
   watch: {
@@ -82,8 +82,20 @@ export default {
         this.fileLen = val.file_list.length;
         if (this.fileLen > 0 && this.data.property.view_method === 'list') {
           const ele = this.$refs.videoAreaBox;
-          this.elementWidth = ele.clientWidth;
-          this.elementHeight = ele.clientHeight;
+          const sn_position = this.data.property.sn_position;
+          // 序号在左和右补齐序号高度,去掉padding(8*2)
+          if (sn_position.includes('left') || sn_position.includes('right')) {
+            this.elementWidth = ele.clientWidth - 16;
+            this.elementHeight = ele.clientHeight + 30;
+          } else {
+            this.elementWidth = ele.clientWidth;
+            this.elementHeight = ele.clientHeight;
+          }
+
+          if (ele.clientHeight <= 0) {
+            this.elementHeight = this.data.minHeight;
+          }
+
           const mainEle = this.$refs.videoArea;
           // 检查元素是否包含已知的类名
           mainEle.classList.forEach((className) => {
@@ -110,20 +122,27 @@ export default {
       const canvasElement = document.querySelector('.canvas');
       if (!canvasElement) return;
       const instanceName = `observer_${this.elementID}`;
-      this.observersMap[instanceName] = new ResizeObserver((entries) => {
+      this.videoObserversMap[instanceName] = new ResizeObserver((entries) => {
         if (!this.getDragStatus()) return;
         for (let entry of entries) {
           window.requestAnimationFrame(() => {
-            this.elementWidth = entry.contentRect.width;
-            this.elementHeight = entry.contentRect.height;
+            const sn_position = this.data.property.sn_position;
+            // 序号在上方和下方减去序号高度,在左右去掉padding(8*2)
+            if (sn_position.includes('top') || sn_position.includes('bottom')) {
+              this.elementWidth = entry.contentRect.width;
+              this.elementHeight = entry.contentRect.height - 30;
+            } else {
+              this.elementWidth = entry.contentRect.width - 16;
+              this.elementHeight = entry.contentRect.height;
+            }
           });
         }
       });
-      this.observersMap[instanceName].observe(this.$el);
+      this.videoObserversMap[instanceName].observe(this.$el);
     });
   },
   beforeDestroy() {
-    Object.values(this.observersMap).forEach((observer) => {
+    Object.values(this.videoObserversMap).forEach((observer) => {
       observer.disconnect();
     });
   },
@@ -167,6 +186,7 @@ export default {
         this.viewTopBottomBtn = true;
       } else {
         this.viewTopBottomBtn = false;
+        this.translateY = 0;
       }
     },
     // 滚动图片列表

+ 2 - 26
src/views/book/courseware/preview/index.vue

@@ -15,7 +15,7 @@
             <SvgIcon icon-class="menu-2" size="24" />
             <template v-for="(item, m) in menuList">
               <span :key="m">{{ item }}</span>
-              <span v-if="index < menuList.length - 1" :key="`separator-${m}`" class="separator">/</span>
+              <span v-if="m < menuList.length - 1" :key="`separator-${m}`" class="separator">/</span>
             </template>
           </span>
           <CoursewarePreview :data="data" />
@@ -306,7 +306,7 @@ export default {
     }
 
     .content {
-      width: 1106px;
+      width: calc($courseware-width + 6px);
       margin: 24px auto 0;
       background-color: #fff;
       border: 3px solid #f44444;
@@ -325,30 +325,6 @@ export default {
         border-top-left-radius: 12px;
         border-bottom-right-radius: 16px;
       }
-
-      .courserware {
-        display: flex;
-        flex-direction: column;
-        row-gap: 6px;
-        width: 100%;
-        min-height: 500px;
-        padding: 24px;
-        background-color: #fff;
-        background-repeat: no-repeat;
-        border-bottom-right-radius: 12px;
-        border-bottom-left-radius: 12px;
-
-        .row {
-          display: grid;
-          gap: 16px;
-
-          .col {
-            display: grid;
-            gap: 16px;
-            overflow: auto;
-          }
-        }
-      }
     }
   }
 }

+ 2 - 19
src/views/home/components/ListingDialog.vue

@@ -1,12 +1,6 @@
 <template>
   <el-dialog :visible="visible" title="上架" width="450px" @close="dialogClose">
     <div class="listing">
-      <div class="visible-range">
-        <div class="visible-range-title">可见范围</div>
-        <el-radio-group v-model="publish_scope">
-          <el-radio v-for="{ label, value } in publishList" :key="value" :label="value">{{ label }}</el-radio>
-        </el-radio-group>
-      </div>
       <div class="authorized-agency">
         <div class="authorized-agency-title">选择授权机构(可多选)</div>
         <el-select
@@ -49,7 +43,7 @@ export default {
   },
   data() {
     return {
-      publish_scope: 1, // 可见范围
+      publish_scope: 0, // 可见范围
       publishList: [
         { label: '全部机构可见', value: 1 },
         { label: '仅授权机构可见', value: 0 },
@@ -99,17 +93,6 @@ export default {
     .listing {
       padding: 0 16px;
 
-      .visible-range {
-        display: flex;
-        flex-direction: column;
-        row-gap: 12px;
-
-        &-title {
-          font-size: 14px;
-          color: $font-light-color;
-        }
-      }
-
       .authorized-agency {
         display: flex;
         flex-direction: column;
@@ -119,7 +102,7 @@ export default {
     }
 
     &__body {
-      padding: 16px 20px;
+      padding: 0 20px 16px;
     }
 
     &__header {

+ 3 - 1
src/views/home/index.vue

@@ -25,7 +25,7 @@
         @keyup.enter.native="pageQueryBookList"
       />
       <span class="search-name">创建者</span>
-      <el-select v-model="creator_id" placeholder="全部">
+      <el-select v-model="creator_id" placeholder="全部" @change="pageQueryBookList">
         <el-option label="-全部- " value="" />
         <el-option
           v-for="{ user_id, user_real_name } in user_list"
@@ -134,9 +134,11 @@ export default {
     },
     changePage(number) {
       this.cur_page = number;
+      this.pageQueryBookList();
     },
     changePageSize(size) {
       this.page_capacity = size;
+      this.pageQueryBookList();
     },
     // 分页查询教材列表
     pageQueryBookList() {