Ver Fonte

card explain md

zhangjie há 4 anos atrás
pai
commit
e52282d6af

+ 11 - 0
src/assets/styles/element-ui-costom.scss

@@ -431,3 +431,14 @@
     }
   }
 }
+.alert-message {
+  .el-message-box__btns {
+    text-align: center;
+    > .el-button {
+      position: relative;
+      left: auto;
+      top: 0;
+      margin: 0;
+    }
+  }
+}

+ 38 - 3
src/modules/card/components/RightClickMenu.vue

@@ -11,6 +11,15 @@
         <ul>
           <li @click="toEdit">编辑</li>
           <li @click="toDelete">删除</li>
+          <li @click="toCopyChildren" v-if="IS_EXPLAIN_CHILDREN">
+            新增<br />答题区
+          </li>
+          <li
+            @click="toDeleteChildren"
+            v-if="IS_EXPLAIN_CHILDREN && showDeleteChildBtn"
+          >
+            删除<br />答题区
+          </li>
         </ul>
       </div>
       <el-button :style="styles" slot="reference"></el-button>
@@ -20,12 +29,15 @@
 
 <script>
 import { mapState, mapMutations, mapActions } from "vuex";
+import { fetchSameExplainNumberExplainChildernPositionInfo } from "../store";
 
 export default {
   name: "right-click-menu",
   data() {
     return {
       visible: false,
+      showDeleteChildBtn: false,
+      IS_EXPLAIN_CHILDREN: false,
       styles: {
         padding: "10px",
         position: "fixed",
@@ -35,7 +47,7 @@ export default {
     };
   },
   computed: {
-    ...mapState("card", ["curElement"])
+    ...mapState("card", ["curElement", "pages"])
   },
   mounted() {
     this.init();
@@ -46,7 +58,9 @@ export default {
       "actElementById",
       "removeElement",
       "removeElementChild",
-      "rebuildPages"
+      "rebuildPages",
+      "copyExplainChildren",
+      "deleteExplainChildren"
     ]),
     init() {
       // 注册自定义右键事件菜单
@@ -69,7 +83,13 @@ export default {
         top: e.y + "px",
         left: e.x - 50 + "px"
       });
-      // 直接用了setTimeout,完美解决弹出框跟随延迟的问题,似乎粗暴了点。
+      const positionInfos = fetchSameExplainNumberExplainChildernPositionInfo(
+        this.curElement,
+        this.pages
+      );
+      this.showDeleteChildBtn = positionInfos.length >= 2;
+      this.IS_EXPLAIN_CHILDREN = this.curElement.type === "EXPLAIN_CHILDREN";
+      // 直接用了setTimeout,解决弹出框跟随延迟的问题,似乎粗暴了点。
       setTimeout(() => {
         this.visible = true;
       }, 100);
@@ -111,6 +131,21 @@ export default {
         })
         .catch(() => {});
     },
+    toCopyChildren() {
+      this.visible = false;
+      this.copyExplainChildren(this.curElement);
+      this.$nextTick(() => {
+        this.rebuildPages();
+      });
+    },
+    toDeleteChildren() {
+      // TODO:校验当前元件是否可以删除
+      this.visible = false;
+      this.deleteExplainChildren(this.curElement);
+      this.$nextTick(() => {
+        this.rebuildPages();
+      });
+    },
     removeSelectElement() {
       if (this.curElement["container"]) {
         this.removeElementChild(this.curElement);

+ 0 - 1
src/modules/card/components/TopicElementEdit.vue

@@ -15,7 +15,6 @@
       :active="['b']"
       :move="false"
       :min-height="20"
-      :fit-parent="['w']"
       @on-click="activeCurElement"
       @resize-over="resizeOver"
       v-else

+ 2 - 8
src/modules/card/components/elementEdit/ExplainChildren.vue

@@ -1,9 +1,6 @@
 <template>
   <div class="elem-explain-children">
-    <div
-      class="elem-title"
-      v-if="data.explainNumber === data.parent.startNumber"
-    >
+    <div class="elem-title" v-if="data.showTitle">
       {{ data.parent.topicName }}
     </div>
     <div class="elem-body" :style="explainBodyStyle">
@@ -44,10 +41,7 @@ export default {
   computed: {
     ...mapState("card", ["curDragElement"]),
     explainBodyStyle() {
-      const height =
-        this.data.explainNumber === this.data.parent.startNumber
-          ? this.data.h - 24
-          : this.data.h;
+      const height = this.data.showTitle ? this.data.h - 24 : this.data.h;
       return {
         height: height + "px"
       };

+ 2 - 8
src/modules/card/components/elementPreview/ExplainChildren.vue

@@ -1,9 +1,6 @@
 <template>
   <div class="elem-explain-children">
-    <div
-      class="elem-title"
-      v-if="data.explainNumber === data.parent.startNumber"
-    >
+    <div class="elem-title" v-if="data.showTitle">
       {{ data.parent.topicName }}
     </div>
     <div class="elem-body" :style="explainBodyStyle">
@@ -36,10 +33,7 @@ export default {
   },
   computed: {
     explainBodyStyle() {
-      const height =
-        this.data.explainNumber === this.data.parent.startNumber
-          ? this.data.h - 30
-          : this.data.h;
+      const height = this.data.showTitle ? this.data.h - 30 : this.data.h;
       return {
         height: height + "px"
       };

+ 3 - 0
src/modules/card/elementModel.js

@@ -224,6 +224,8 @@ const EXPLAIN_CHILDREN_PROP = {
   sign: "subjective",
   topicNo: null,
   isCovered: false,
+  // 是否展示解答题题目内容,解答题第1小题的第1个答题区需要显示解答题题目内容
+  showTitle: false,
   // 小题序号
   explainNumber: 0,
   // 每一个解答题小题都可以包含其他基础元件,这些基础元件都用绝对定位
@@ -450,6 +452,7 @@ const getExplainChildren = explainModel => {
 
     elements[i] = child;
   }
+  elements[0].showTitle = true;
 
   return elements;
 };

+ 136 - 3
src/modules/card/store.js

@@ -97,7 +97,11 @@ const fetchAllRelateParentElementPositionInfos = (parentElement, pages) => {
     for (let j = 0, jlen = pages[i].columns.length; j < jlen; j++) {
       pages[i].columns[j].elements.forEach((item, eindex) => {
         if (item["parent"] && item.parent.id === parentElement.id) {
-          postionInfos.push({ _pageNo: i, _columnNo: j, _elementNo: eindex });
+          let pos = { _pageNo: i, _columnNo: j, _elementNo: eindex };
+          if (parentElement.type === "EXPLAIN") {
+            pos.explainNumber = item.explainNumber;
+          }
+          postionInfos.push(pos);
         }
       });
     }
@@ -116,6 +120,47 @@ const fetchFirstSubjectiveTopicPositionInfo = pages => {
   }
 };
 
+const fetchSameExplainNumberExplainChildernPositionInfo = (
+  explainChildernElement,
+  pages
+) => {
+  let postionInfos = [];
+  const explainId = explainChildernElement.parent.id;
+  const explainNumber = explainChildernElement.explainNumber;
+
+  for (let i = 0, ilen = pages.length; i < ilen; i++) {
+    for (let j = 0, jlen = pages[i].columns.length; j < jlen; j++) {
+      pages[i].columns[j].elements.forEach((item, eindex) => {
+        if (
+          item.parent &&
+          item.parent.id === explainId &&
+          item.explainNumber === explainNumber
+        ) {
+          postionInfos.push({
+            _pageNo: i,
+            _columnNo: j,
+            _elementNo: eindex,
+            _elementId: item.id
+          });
+        }
+      });
+    }
+  }
+  return postionInfos;
+};
+
+function groupByParams(datas, paramKey) {
+  let elementGroupInfos = [];
+  for (let i = 0, len = datas.length; i < len; i++) {
+    if (i === 0 || datas[i][paramKey] !== datas[i - 1][paramKey]) {
+      elementGroupInfos.push([datas[i]]);
+    } else {
+      elementGroupInfos[elementGroupInfos.length - 1].push(datas[i]);
+    }
+  }
+  return elementGroupInfos;
+}
+
 const getPageTopicNos = pages => {
   let topicNos = [];
   pages.forEach(page => {
@@ -185,6 +230,53 @@ const actions = {
       } else {
         dispatch("addElement", element);
       }
+    } else if (element.type === "EXPLAIN") {
+      const positionInfos = fetchAllRelateParentElementPositionInfos(
+        element,
+        state.pages
+      );
+      if (positionInfos.length) {
+        const elementGroupPosInfos = groupByParams(
+          positionInfos,
+          "explainNumber"
+        );
+        const orgElementCount = elementGroupPosInfos.length;
+        if (orgElementCount > element.questionsCount) {
+          // 原小题数多于新小题数,要删除原多于的小题;
+          let needDeleteInfos = elementGroupPosInfos.splice(
+            element.questionsCount,
+            orgElementCount - element.questionsCount
+          );
+          needDeleteInfos.reverse().forEach(item => {
+            item.reverse().forEach(pos => {
+              const elems =
+                state.pages[pos._pageNo].columns[pos._columnNo].elements;
+              elems.splice(pos._elementNo, 1);
+            });
+          });
+        }
+
+        const newElements = getExplainChildren(element);
+        const lastPos = elementGroupPosInfos.slice(-1)[0].slice(-1)[0];
+        for (var i = 0; i < element.questionsCount; i++) {
+          if (elementGroupPosInfos[i]) {
+            elementGroupPosInfos[i].forEach(pos => {
+              let child =
+                state.pages[pos._pageNo].columns[pos._columnNo].elements[
+                  pos._elementNo
+                ];
+              child.explainNumber = i + element.startNumber;
+              child.parent = { ...element };
+            });
+          } else {
+            state.pages[lastPos._pageNo].columns[
+              lastPos._columnNo
+            ].elements.splice(lastPos._elementNo + 1, 0, newElements[i]);
+          }
+        }
+      } else {
+        dispatch("addElement", element);
+      }
     } else {
       // 非作文题都是拆分题,即同一个题拆分成多个小题展示
       const positionInfos = fetchAllRelateParentElementPositionInfos(
@@ -198,13 +290,13 @@ const actions = {
             pos._elementNo
           ].h;
         });
-        // 删除所有解答
+        // 删除所有
         positionInfos.reverse().forEach(pos => {
           const elems =
             state.pages[pos._pageNo].columns[pos._columnNo].elements;
           elems.splice(pos._elementNo, 1);
         });
-        // 创建新的解答题元素
+        // 创建新的题元素
         const newElements = createFunc[element.type](element);
         const pos = positionInfos.pop();
         newElements.forEach((newElement, index) => {
@@ -464,9 +556,50 @@ const actions = {
     if (!curElement) return;
 
     commit("setCurElement", curElement);
+  },
+  copyExplainChildren({ state }, element) {
+    let newElement = deepCopy(element);
+    newElement.id = getElementId();
+    newElement.elements = [];
+    newElement.h = 200;
+    newElement.showTitle = false;
+
+    const positionInfos = fetchElementPositionInfos(element, state.pages);
+    if (!positionInfos.length) return;
+    const pos = positionInfos[0];
+    state.pages[pos._pageNo].columns[pos._columnNo].elements.splice(
+      pos._elementNo + 1,
+      0,
+      newElement
+    );
+  },
+  deleteExplainChildren({ state }, element) {
+    const positionInfos = fetchSameExplainNumberExplainChildernPositionInfo(
+      element,
+      state.pages
+    );
+    if (positionInfos.length < 2) return;
+    const pindex = positionInfos.findIndex(
+      item => item._elementId === element.id
+    );
+    const pos = positionInfos[pindex];
+    state.pages[pos._pageNo].columns[pos._columnNo].elements.splice(
+      pos._elementNo,
+      1
+    );
+    // 当删除的是含有标题解答题小题时,则需要将下一个答题区开启显示标题。
+    // element.explainNumber === element.parent.startNumber && pindex === 0
+    if (element.showTitle) {
+      const nextPos = positionInfos[pindex + 1];
+      state.pages[nextPos._pageNo].columns[nextPos._columnNo].elements[
+        nextPos._elementNo
+      ].showTitle = true;
+    }
   }
 };
 
+export { fetchSameExplainNumberExplainChildernPositionInfo };
+
 export default {
   namespaced: true,
   state,

+ 9 - 6
src/modules/exam-center/views/CardManage.vue

@@ -242,12 +242,15 @@ export default {
           content: JSON.stringify(cont)
         };
         await updateCardDetail(datas);
-        this.$message({
-          type: "warning",
-          message:
-            "复制成功!题卡规则有变动,将默认应用当前最新规则,请仔细核实题卡板式!",
-          duration: 4000
-        });
+
+        this.$alert(
+          "复制成功!题卡规则有变动,将默认应用当前最新规则,请仔细核实题卡板式!",
+          {
+            confirmButtonText: "确定",
+            customClass: "alert-message",
+            showClose: false
+          }
+        );
       } else {
         this.$message.success("复制成功!");
       }

+ 12 - 12
src/modules/exam-center/views/ExamManage.vue

@@ -84,19 +84,19 @@
         <el-table-column prop="endTime" label="完成时间"></el-table-column>
         <el-table-column label="操作" align="center" width="185">
           <template slot-scope="scope">
-            <el-button
+            <!-- <el-button
               class="btn-table-icon"
               type="text"
               icon="icon icon-modify"
               @click="toTaskDetail(scope.row)"
               title="任务详情"
-            ></el-button>
+            ></el-button> -->
             <el-button
               class="btn-table-icon"
               type="text"
               icon="icon icon-edit"
               @click="toEdit(scope.row)"
-              title="编辑"
+              title="任务详情"
             ></el-button>
             <el-button
               class="btn-table-icon"
@@ -225,15 +225,15 @@ export default {
         }
       });
     },
-    toTaskDetail(row) {
-      console.log(row);
-      this.$router.push({
-        name: "ExamTaskDetail",
-        params: {
-          examId: row.id
-        }
-      });
-    },
+    // toTaskDetail(row) {
+    //   console.log(row);
+    //   this.$router.push({
+    //     name: "ExamTaskDetail",
+    //     params: {
+    //       examId: row.id
+    //     }
+    //   });
+    // },
     async toExport(row) {
       console.log(row);
       let load = this.$message({

+ 3 - 6
src/modules/exam-center/views/ExamModify.vue

@@ -124,12 +124,8 @@
       </el-form-item>
       <el-form-item prop="teacher" label="指派命题老师:">
         <el-table :data="courses" style="width: 420px;" border stripe>
-          <el-table-column
-            width="154"
-            prop="courseName"
-            label="科目"
-          ></el-table-column>
-          <el-table-column label="命题老师">
+          <el-table-column prop="courseName" label="科目"></el-table-column>
+          <el-table-column label="命题老师" width="180px">
             <template slot-scope="scope">
               <el-select
                 v-model="scope.row.teacherId"
@@ -146,6 +142,7 @@
               </el-select>
             </template>
           </el-table-column>
+          <el-table-column prop="status" label="状态"></el-table-column>
         </el-table>
       </el-form-item>