Ver Fonte

对接接口

dusenyao há 1 ano atrás
pai
commit
45eed49d45

+ 1 - 1
src/api/app.js

@@ -72,7 +72,7 @@ export async function fileUpload(
     formData = file;
   } else {
     formData = new FormData();
-    formData.append(file.name, file.raw, file.name);
+    formData.append(file.filename, file.file, file.file.name);
   }
 
   let onUploadProgress = handleUploadProgress || null;

+ 18 - 1
src/api/book.js

@@ -114,7 +114,7 @@ export function SaveCoursewareContent(data) {
  * 得到互动课件内容
  */
 export function GetCoursewareContent(data) {
-  return http.post(`book-courseware_manager-GetCoursewareContent`, data);
+  return http.post(`${process.env.VUE_APP_BookWebSI}?MethodName=book-courseware_manager-GetCoursewareContent`, data);
 }
 
 /**
@@ -126,3 +126,20 @@ export function SaveCoursewareComponentContent(data) {
     data,
   );
 }
+
+/**
+ * 得到互动课件组件内容
+ */
+export function GetCoursewareComponentContent(data) {
+  return http.post(
+    `${process.env.VUE_APP_BookWebSI}?MethodName=book-courseware_manager-GetCoursewareComponentContent`,
+    data,
+  );
+}
+
+/**
+ * 得到互动课件组件内容(展示内容)
+ */
+export function GetCoursewareComponentContent_View(data) {
+  return http.post(`book-courseware_manager-GetCoursewareComponentContent_View`, data);
+}

+ 12 - 14
src/views/book/courseware/create/components/base/common/UploadFile.vue

@@ -44,7 +44,7 @@
 
 <script>
 import ModuleMixin from '../../common/ModuleMixin';
-import { fileUpload, GetFileStoreInfo } from '@/api/app';
+import { fileUpload } from '@/api/app';
 import { conversionSize } from '@/utils/common';
 import FillDescribe from '../../common/FillDescribe';
 
@@ -121,7 +121,7 @@ export default {
     // 文件校验
     afterSelectFile(file) {
       const fileName = file.name;
-      let singleSizeTip = '文件[' + fileName + ']大小超过 ' + conversionSize(this.moduleData.single_size) + ',被移除!';
+      let singleSizeTip = `文件[${fileName}]大小超过 ${conversionSize(this.moduleData.single_size)},被移除!`;
 
       if (file.size > this.moduleData.single_size * 1024 * 1024) {
         this.$message.error(singleSizeTip);
@@ -142,7 +142,7 @@ export default {
       }
       const isNeedType = fileType.includes(suffix);
       if (!isNeedType) {
-        typeTip += ',[' + fileName + ']被移除!';
+        typeTip += `,[${fileName}]被移除!`;
         this.$message.error(typeTip);
         this.$refs.upload.handleRemove(file);
         return false;
@@ -154,25 +154,23 @@ export default {
       const files = this.$refs.upload.uploadFiles || [];
       const totalSize = files.reduce((sum, cur) => sum + Number(cur.size || 0), 0);
       if (totalSize > this.moduleData.total_size * 1024 * 1024) {
-        this.$message.error('文件总大小不能超过' + conversionSize(this.moduleData.total_size));
+        this.$message.error(`文件总大小不能超过${conversionSize(this.moduleData.total_size)}`);
         return false;
       }
-      var that = this;
       files.forEach((file) => {
-        fileUpload('Mid', file, {
-          handleUploadProgress: function (progressEvent) {
-            var en = that.file_info_list.find((p) => p.uid == file.uid);
-            var per = Number((progressEvent.progress * 100).toFixed(2) || 0);
+        let form = new FormData();
+        form.append(file.name, file.raw, file.name);
+        fileUpload('Mid', form, {
+          handleUploadProgress: (progressEvent) => {
+            let en = this.file_info_list.find((p) => p.uid === file.uid);
+            let per = Number((progressEvent.progress * 100).toFixed(2) || 0);
             if (en) {
-              // var _i = that.file_info_list.findIndex((p) => p.uid == file.uid);
               en.progress = per;
-              // that.$set(that.file_info_list, _i, en);
-              that.$forceUpdate();
+              this.$forceUpdate();
             }
           },
         }).then(({ file_info_list }) => {
           if (file_info_list.length > 0) {
-            // console.log(file_info_list);
             this.file_info_list = file_info_list;
           }
         });
@@ -184,7 +182,7 @@ export default {
       this.visible = true;
     },
 
-    //给文件加介绍
+    // 给文件加介绍
     fillDescribeToFile() {},
   },
 };

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

@@ -1,7 +1,7 @@
 <template>
   <el-dialog title="" :visible="visible" width="260px" top="38vh" :show-close="false" @close="dialogClose">
-    <el-input v-model="form.title" autocomplete="off" placeholder="标题"></el-input>
-    <el-input type="textarea" v-model="form.describe" placeholder="介绍"></el-input>
+    <el-input v-model="form.title" autocomplete="off" placeholder="标题" />
+    <el-input v-model="form.describe" type="textarea" placeholder="介绍" />
     <template slot="footer">
       <el-button size="medium" @click="dialogClose">取消</el-button>
       <el-button type="primary" size="medium" @click="confirm">确定</el-button>

+ 15 - 1
src/views/book/courseware/create/components/common/ModuleMixin.js

@@ -1,6 +1,7 @@
 // 组件混入
 import ModuleBase from './ModuleBase.vue';
 import { snGenerationMethodList, viewMethodList, audioViewMethodList } from '@/views/book/courseware/data/common';
+import { SaveCoursewareComponentContent, GetCoursewareComponentContent } from '@/api/book';
 
 const mixin = {
   data() {
@@ -25,7 +26,12 @@ const mixin = {
       id: this.id,
     };
   },
-  created() {},
+  inject: ['courseware_id'],
+  created() {
+    GetCoursewareComponentContent({ courseware_id: this.courseware_id, component_id: this.id }).then(({ content }) => {
+      if (content) this.data = JSON.parse(content);
+    });
+  },
   methods: {
     /**
      * @description 显示设置
@@ -41,6 +47,14 @@ const mixin = {
     updateSetting(property) {
       this.data.property = property;
     },
+    saveCoursewareComponentContent() {
+      SaveCoursewareComponentContent({
+        courseware_id: this.courseware_id,
+        component_id: this.id,
+        component_type: this.data.type,
+        content: JSON.stringify(this.data),
+      });
+    },
   },
 };
 

+ 142 - 35
src/views/book/courseware/create/index.vue

@@ -24,7 +24,16 @@
       <div class="create-operation">
         <el-button><SvgIcon icon-class="background-img" />背景图</el-button>
         <el-button><SvgIcon icon-class="template" />模板</el-button>
-        <el-button><i class="el-icon-close"></i>退出编辑</el-button>
+        <el-button class="exit-edit">
+          <span><i class="el-icon-close"></i> 退出编辑</span>
+          <el-button class="save" type="primary">
+            <span @click="saveCoursewareContent"><SvgIcon icon-class="save" /> <span>保存</span></span>
+            <el-popover placement="bottom" popper-class="save-popover" trigger="click">
+              <div class="save-template">保存为模板</div>
+              <i slot="reference" class="el-icon-arrow-down"></i>
+            </el-popover>
+          </el-button>
+        </el-button>
       </div>
 
       <main ref="canvas" class="canvas">
@@ -41,16 +50,25 @@
               gridTemplateRows: col.grid_template_rows,
             }"
           >
-            <span class="drag-vertical-line start" :data-row="i" :data-col="j"></span>
-            <component
-              :is="componentList[grid.type]"
-              v-for="(grid, k) in col.grid_list"
-              :id="grid.id"
-              :key="k"
-              :style="{ gridArea: grid.grid_area }"
-              @showSetting="showSetting"
-            />
-            <span class="drag-vertical-line end" :data-row="i" :data-col="j"></span>
+            <template v-for="(grid, k) in col.grid_list">
+              <span
+                v-if="k === 0"
+                :key="`start-${k}`"
+                class="drag-vertical-line"
+                :data-row="i"
+                :data-col="j"
+                :data-grid="k"
+              ></span>
+              <component
+                :is="componentList[grid.type]"
+                :id="grid.id"
+                ref="component"
+                :key="k"
+                :style="{ gridArea: grid.grid_area }"
+                @showSetting="showSetting"
+              />
+              <span :key="`end-${k}`" class="drag-vertical-line" :data-row="i" :data-col="j" :data-grid="k + 1"></span>
+            </template>
           </div>
           <span class="drag-line" :data-row="i"></span>
         </div>
@@ -74,6 +92,7 @@ export default {
   provide() {
     return {
       getCurSettingId: () => this.curSettingId,
+      courseware_id: this.courseware_id,
     };
   },
   data() {
@@ -84,7 +103,6 @@ export default {
       book_id,
       chapter_id,
       data: {
-        id: '',
         background_image_url: '',
         background_position: {
           x: 0,
@@ -103,6 +121,7 @@ export default {
       bookTypeOption,
       curRow: -2,
       curCol: -1,
+      curGrid: -1,
       enterCanvas: false, // 是否进入画布
       // 拖拽状态
       drag: {
@@ -136,12 +155,13 @@ export default {
           item.style.opacity = 0;
         });
         this.curCol = -1;
+        this.curGrid = -1;
       },
     },
   },
   created() {
-    GetCoursewareContent({ id: this.courseware_id }).then((res) => {
-      this.data = res.data;
+    GetCoursewareContent({ id: this.courseware_id }).then(({ content }) => {
+      if (content) this.data = JSON.parse(content);
     });
   },
   mounted() {
@@ -157,7 +177,20 @@ export default {
       this.$router.push({ path: '/chapter', query: { chapter_id: this.chapter_id, book_id: this.book_id } });
     },
     saveCoursewareContent() {
-      SaveCoursewareContent({ id: this.courseware_id, category: 'NEW' }).then(() => {
+      let component_id_list = this.data.row_list.flatMap((row) =>
+        row.col_list.flatMap((col) => col.grid_list.map((grid) => grid.id)),
+      );
+
+      this.$refs.component.forEach((item) => {
+        item.saveCoursewareComponentContent();
+      });
+
+      SaveCoursewareContent({
+        id: this.courseware_id,
+        category: 'NEW',
+        content: JSON.stringify(this.data),
+        component_id_list,
+      }).then(() => {
         this.$message.success('保存成功');
       });
     },
@@ -234,10 +267,10 @@ export default {
 
       list.forEach((item, index) => {
         if (index === minIndex) {
-          const row = item.getAttribute('data-row');
-          this.curRow = Number(row);
-          const col = item.getAttribute('data-col');
-          if (col) this.curCol = Number(col);
+          this.curRow = Number(item.getAttribute('data-row'));
+          this.curCol = Number(item.getAttribute('data-col') || -1);
+          this.curGrid = Number(item.getAttribute('data-grid') || -1);
+
           item.style.opacity = 1;
         } else {
           item.style.opacity = 0;
@@ -256,15 +289,53 @@ export default {
         this.drag.dragging = false;
       }
 
-      if (this.enterCanvas && this.curRow >= -1) {
-        this.data.row_list.splice(this.curRow + 1, 0, this.calculateInsertedObject());
+      if (this.enterCanvas) {
+        if (this.curRow >= -1 && this.curCol <= -1) {
+          this.data.row_list.splice(this.curRow + 1, 0, this.calculateRowInsertedObject());
+        }
+        if (this.curRow >= -1 && this.curCol > -1 && this.curGrid > -1) {
+          this.calculateColObject();
+        }
       }
       this.enterCanvas = false;
     },
     /**
-     * 计算插入的对象
+     * 计算列插入的对象
+     */
+    calculateColObject() {
+      let num = 0; // 计算当前行之前的所有 grid_list 的数量
+      for (let i = 0; i <= this.curRow; i++) {
+        this.data.row_list[i]?.col_list.forEach((item) => {
+          num += item.grid_list.length;
+        });
+      }
+      const id = getRandomNumber(12);
+      const letter = String.fromCharCode(65 + num);
+      let col = this.data.row_list[this.curRow].col_list[this.curCol];
+
+      col.grid_list.splice(this.curGrid, 0, {
+        id,
+        grid_area: letter,
+        type: this.curType,
+      });
+
+      let grid_template_columns = '0';
+      col.grid_list.forEach((item, i) => {
+        if (i === col.grid_list.length - 1) grid_template_columns += ' auto 0';
+        else grid_template_columns += ' auto 16px';
+      });
+      col.grid_template_columns = grid_template_columns;
+
+      let grid_template_areas = '.';
+      col.grid_list.forEach(({ grid_area }) => {
+        grid_template_areas += ` ${grid_area} .`;
+      });
+      col.grid_template_areas = `"${grid_template_areas}"`;
+    },
+    /**
+     * 计算行插入的对象
      */
-    calculateInsertedObject() {
+    calculateRowInsertedObject() {
       let num = 0; // 计算当前行之前的所有 grid_list 的数量
       for (let i = 0; i <= this.curRow; i++) {
         this.data.row_list[i]?.col_list.forEach((item) => {
@@ -278,7 +349,7 @@ export default {
         col_list: [
           {
             width: '100%',
-            grid_template_areas: `'start ${letter} end'`,
+            grid_template_areas: `'. ${letter} .'`,
             grid_template_columns: '0 auto 0',
             grid_template_rows: 'auto',
             grid_list: [
@@ -391,8 +462,13 @@ export default {
       justify-content: center;
       margin-bottom: 16px;
 
-      .el-button {
+      .exit-edit {
+        padding: 4px 4px 4px 16px;
+      }
+
+      > .el-button {
         height: 40px;
+        font-size: 16px;
         font-weight: bold;
 
         :deep > span {
@@ -400,6 +476,19 @@ export default {
           column-gap: 8px;
           align-items: center;
         }
+
+        .save.el-button {
+          height: 32px;
+          margin-left: 8px;
+          font-size: 16px;
+
+          :deep > span {
+            display: flex;
+            column-gap: 4px;
+            align-items: center;
+            margin-top: -1px;
+          }
+        }
       }
     }
 
@@ -420,6 +509,18 @@ export default {
 
         .col {
           display: grid;
+
+          .drag-vertical-line:first-child {
+            left: -8px;
+          }
+
+          .drag-vertical-line:not(:first-child, :last-child) {
+            left: 6px;
+          }
+
+          .drag-vertical-line:last-child {
+            right: -4px;
+          }
         }
       }
 
@@ -439,16 +540,6 @@ export default {
         background-color: #379fff;
         border-radius: 4px;
         opacity: 0;
-
-        &.start {
-          right: 8px;
-          grid-area: start;
-        }
-
-        &.end {
-          left: 4px;
-          grid-area: end;
-        }
       }
     }
   }
@@ -478,4 +569,20 @@ export default {
   border-radius: 4px;
   transform: translate(-40%, -40%);
 }
+
+.save-popover {
+  width: 100px;
+  min-width: 100px;
+  padding: 4px;
+
+  .save-template {
+    padding: 4px 8px;
+    text-align: center;
+    cursor: pointer;
+
+    &:hover {
+      background-color: #f1f1f1;
+    }
+  }
+}
 </style>