2 次代碼提交 0969c0db51 ... 7b5512f262

作者 SHA1 備註 提交日期
  dsy 7b5512f262 Merge branch 'master' of http://60.205.254.193:3000/GCLS/eep_page 3 周之前
  dsy 2a0819bbb0 先等组件保存完毕,再保存课节框架 3 周之前

+ 1 - 1
src/styles/variables.scss

@@ -22,4 +22,4 @@ $setting-active-color: #4176ff;
 
 // px
 $header-h: 64px;
-$courseware-width: 1000px;
+$courseware-width: 1100px;

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

@@ -362,10 +362,10 @@ export default {
      * 保存课件内容
      * @param {string} type 类型
      */
-    saveCoursewareContent(type) {
+    async saveCoursewareContent(type) {
       let isAllLoader = false;
       if (this.isEdit) {
-        isAllLoader = this.$refs?.component.every((item) => item.property.isGetContent);
+        isAllLoader = this.$refs?.component?.every((item) => item.property.isGetContent);
       } else {
         isAllLoader = this.$refs?.previewEdit?.$refs?.preview?.every((item) => item.loader);
       }
@@ -375,14 +375,6 @@ export default {
         return false;
       }
 
-      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();
-      });
-
       const loading = this.$loading({
         lock: true,
         text: '保存中...',
@@ -390,80 +382,96 @@ export default {
         background: 'rgba(0, 0, 0, 0.7)',
       });
 
-      let groupIdList = _.cloneDeep(this.content_group_row_list);
-      let groupList = [];
-      // 通过判断 is_pre_same_group 将组合并
-      for (let i = 0; i < groupIdList.length; i++) {
-        if (groupIdList[i].is_pre_same_group) {
-          groupList[groupList.length - 1].row_id_list.push(groupIdList[i].row_id);
-        } else {
-          groupList.push({
-            name: '',
-            row_id_list: [groupIdList[i].row_id],
-            component_id_list: [],
-          });
+      try {
+        // 先等待所有子组件内容落库完成
+        if (this.isEdit) {
+          const comps = Array.isArray(this.$refs?.component)
+            ? this.$refs.component
+            : [this.$refs?.component].filter(Boolean);
+          await Promise.all(comps.map((item) => item.saveCoursewareComponentContent()));
         }
-      }
 
-      // 通过合并后的分组,获取对应的组件 id 和分组名称
-      groupList.forEach(({ row_id_list, component_id_list }, i) => {
-        row_id_list.forEach((row_id, j) => {
-          let row = this.data.row_list.find((row) => {
-            return row.row_id === row_id;
-          });
-          // 当前行所有组件id列表
-          let gridIdList = row.col_list.map((col) => col.grid_list.map((grid) => grid.id)).flat();
-          component_id_list.push(...gridIdList);
-          // 查找每组第一行中第一个包含 describe、label 或 stem 的组件
-          if (j === 0) {
-            let findKey = '';
-            let findType = '';
-            row.col_list.some((col) => {
-              const findItem = col.grid_list.find(({ type }) => {
-                return ['describe', 'label', 'stem'].includes(type);
-              });
-              if (findItem) {
-                findKey = findItem.id;
-                findType = findItem.type;
-                return true;
-              }
+        // 再收集并保存页面结构
+        let component_id_list = this.data.row_list.flatMap((row) =>
+          row.col_list.flatMap((col) => col.grid_list.map((grid) => grid.id)),
+        );
+
+        let groupIdList = _.cloneDeep(this.content_group_row_list);
+        let groupList = [];
+        // 通过判断 is_pre_same_group 将组合并
+        for (let i = 0; i < groupIdList.length; i++) {
+          if (groupIdList[i].is_pre_same_group) {
+            groupList[groupList.length - 1].row_id_list.push(groupIdList[i].row_id);
+          } else {
+            groupList.push({
+              name: '',
+              row_id_list: [groupIdList[i].row_id],
+              component_id_list: [],
             });
-            let groupName = `组${i + 1}`;
-
-            // 如果有标签类组件,获取对应名称
-            if (findKey) {
-              let item = this.isEdit
-                ? this.findChildComponentByKey(`grid-${findKey}`)
-                : this.$refs.previewEdit.findChildComponentByKey(`preview-${findKey}`);
-              if (['describe', 'stem'].includes(findType)) {
-                groupName = item.data.content.replace(/<[^>]+>/g, ''); // 去掉html标签
-              } else if (findType === 'label') {
-                groupName = item.data.dynamicTags.map((tag) => tag.text).join(', ');
+          }
+        }
+
+        // 通过合并后的分组,获取对应的组件 id 和分组名称
+        groupList.forEach(({ row_id_list, component_id_list }, i) => {
+          row_id_list.forEach((row_id, j) => {
+            let row = this.data.row_list.find((row) => {
+              return row.row_id === row_id;
+            });
+            // 当前行所有组件id列表
+            let gridIdList = row.col_list.map((col) => col.grid_list.map((grid) => grid.id)).flat();
+            component_id_list.push(...gridIdList);
+            // 查找每组第一行中第一个包含 describe、label 或 stem 的组件
+            if (j === 0) {
+              let findKey = '';
+              let findType = '';
+              row.col_list.some((col) => {
+                const findItem = col.grid_list.find(({ type }) => {
+                  return ['describe', 'label', 'stem'].includes(type);
+                });
+                if (findItem) {
+                  findKey = findItem.id;
+                  findType = findItem.type;
+                  return true;
+                }
+              });
+              let groupName = `组${i + 1}`;
+
+              // 如果有标签类组件,获取对应名称
+              if (findKey) {
+                let item = this.isEdit
+                  ? this.findChildComponentByKey(`grid-${findKey}`)
+                  : this.$refs.previewEdit.findChildComponentByKey(`preview-${findKey}`);
+                if (['describe', 'stem'].includes(findType)) {
+                  groupName = item.data.content.replace(/<[^>]+>/g, '');
+                } else if (findType === 'label') {
+                  groupName = item.data.dynamicTags.map((tag) => tag.text).join(', ');
+                }
               }
+
+              groupList[i].name = groupName;
             }
+          });
+        });
 
-            groupList[i].name = groupName;
-          }
+        await ContentSaveCoursewareContent({
+          id: this.courseware_id,
+          category: 'NEW',
+          content: JSON.stringify(this.data),
+          component_id_list,
+          content_group_component_list: groupList,
+          content_group_row_list: this.content_group_row_list,
         });
-      });
 
-      ContentSaveCoursewareContent({
-        id: this.courseware_id,
-        category: 'NEW',
-        content: JSON.stringify(this.data),
-        component_id_list,
-        content_group_component_list: groupList,
-        content_group_row_list: this.content_group_row_list,
-      }).then(() => {
         this.$message.success('保存成功');
-        loading.close();
         if (type === 'quit') {
           this.$emit('back');
         }
         if (type === 'edit') {
           this.$emit('changeEditStatus');
         }
-      });
+      } finally {
+        loading.close();
+      }
     },
     setBackgroundImage(url, position) {
       this.data.background_image_url = url;

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

@@ -125,8 +125,12 @@ const mixin = {
     handleComponentMove(data) {
       this.componentMove({ ...data, id: this.id });
     },
+    /**
+     * 保护课节组件内容
+     * @returns {Promise} 返回 Promise,便于父组件 await
+     */
     saveCoursewareComponentContent() {
-      ContentSaveCoursewareComponentContent({
+      return ContentSaveCoursewareComponentContent({
         courseware_id: this.courseware_id,
         component_id: this.id,
         component_type: this.data.type,