zhangjie 2 жил өмнө
parent
commit
768ef8ad36

+ 57 - 31
src/components/base/OrgSelect.vue

@@ -1,5 +1,8 @@
 <template>
-  <div class="org-select el-select major-select el-select--small">
+  <div
+    class="org-select el-select major-select el-select--small"
+    @click="handleOpen"
+  >
     <div v-if="multiple" class="el-select__tags">
       <el-tag v-for="item in selectedList" :key="item.id">{{
         item.name
@@ -19,8 +22,6 @@
         class="el-input__inner"
         :value="selectedOrg.name"
         readonly
-        @focus="handleFocus"
-        @blur="handleBlur"
       />
       <span class="el-input__suffix">
         <span class="el-input__suffix-inner">
@@ -43,32 +44,35 @@
       v-model="visible"
     >
       <div ref="popoverRef" slot="reference"></div>
-      <el-tree
-        ref="OrgTree"
-        :data="orgs"
-        default-expand-all
-        node-key="id"
-        :props="defaultProps"
-        check-on-click-node
-        :expand-on-click-node="false"
-        @node-click="nodeClick"
-      >
-        <span
-          :class="['custom-tree-node', { 'is-select': checkSelected(data) }]"
-          slot-scope="{ node, data }"
+      <div class="org-popover-tree" v-clickoutside="handleClose">
+        <el-tree
+          ref="OrgTree"
+          :data="orgs"
+          default-expand-all
+          node-key="id"
+          :props="defaultProps"
+          check-on-click-node
+          :expand-on-click-node="false"
+          @node-click="nodeClick"
         >
-          <span>{{ node.label }}</span>
-          <span>
-            <i class="el-icon-check"></i>
+          <span
+            :class="['custom-tree-node', { 'is-select': checkSelected(data) }]"
+            slot-scope="{ node, data }"
+          >
+            <span>{{ node.label }}</span>
+            <span>
+              <i class="el-icon-check"></i>
+            </span>
           </span>
-        </span>
-      </el-tree>
+        </el-tree>
+      </div>
     </el-popover>
   </div>
 </template>
 
 <script>
 import { organizationList } from "../../modules/base/api";
+import Clickoutside from "element-ui/src/utils/clickoutside";
 
 export default {
   name: "org-select",
@@ -86,6 +90,7 @@ export default {
       default: false
     }
   },
+  directives: { Clickoutside },
   data() {
     return {
       selectedOrg: {},
@@ -116,29 +121,41 @@ export default {
         });
       }
     },
-    handleFocus() {
-      this.visible = true;
+    switchOpen() {
+      if (this.visible) {
+        this.handleClose();
+      } else {
+        this.handleOpen();
+      }
+    },
+    handleOpen() {
       this.isFocus = true;
+      setTimeout(() => {
+        this.visible = true;
+      }, 200);
     },
-    handleBlur() {
+    handleClose() {
       this.visible = false;
       this.isFocus = false;
     },
     nodeClick(data) {
+      if (!this.multiple) {
+        this.selectedOrg = { ...data };
+        this.selectedOrgList = [{ ...data }];
+        this.updateSelectOrgIds();
+        this.visible = false;
+        this.emitChange();
+        return;
+      }
+
       if (this.selectedOrgIds.includes(data.id)) {
         this.selectedOrgList = this.selectedOrgList.filter(
           item => item.id !== data.id
         );
-        if (!this.multiple) this.selectedOrg = {};
       } else {
-        if (!this.multiple) {
-          this.selectedOrgList = [];
-          this.selectedOrg = { ...data };
-        }
         this.selectedOrgList.push({ ...data });
       }
       this.updateSelectOrgIds();
-      if (!this.multiple) this.visible = false;
       this.emitChange();
     },
     updateSelectOrgIds() {
@@ -166,7 +183,16 @@ export default {
   width: 220px;
 }
 .org-popover {
-  width: 300px;
+  &.el-popover {
+    width: 300px;
+    padding: 0;
+  }
+
+  &-tree {
+    max-height: 300px;
+    overflow: auto;
+    padding: 5px 0;
+  }
 
   .custom-tree-node {
     .el-icon-check {

+ 102 - 102
src/modules/stmms/components/UploadPaperAnswerDialog.vue

@@ -1,102 +1,102 @@
-<template>
-  <el-dialog
-    class="upload-paper-answer-dialog"
-    :visible.sync="modalIsShow"
-    title="上传试卷标答PDF文档"
-    top="10vh"
-    width="600px"
-    :close-on-click-modal="false"
-    :close-on-press-escape="false"
-    append-to-body
-    destroy-on-close
-    @open="visibleChange"
-  >
-    <el-form ref="modalFormComp" :model="infos" label-width="50px">
-      <div class="part-box">
-        <h3 class="mb-2">卷型{{ instance.paperType }}</h3>
-        <el-form-item prop="file" label="标答:">
-          <select-file
-            :format="fileFormat"
-            :disabled="isSubmit"
-            @file-change="fileChange"
-          ></select-file>
-        </el-form-item>
-      </div>
-    </el-form>
-    <div slot="footer">
-      <el-button type="primary" :disabled="isSubmit" @click="submit"
-        >确认</el-button
-      >
-      <el-button @click="cancel">取消</el-button>
-    </div>
-  </el-dialog>
-</template>
-
-<script>
-import { examStructureUploadAnswer } from "../api";
-import SelectFile from "./SelectFile.vue";
-
-export default {
-  name: "upload-paper-answer-dialog",
-  components: { SelectFile },
-  props: {
-    instance: {
-      type: Object,
-      default() {
-        return {};
-      }
-    }
-  },
-  data() {
-    return {
-      modalIsShow: false,
-      isSubmit: false,
-      infos: { file: null, md5: null, errorMsg: null },
-      fileFormat: ["pdf"]
-    };
-  },
-  methods: {
-    visibleChange() {
-      this.infos = { file: null, md5: null, errorMsg: null };
-    },
-    cancel() {
-      this.modalIsShow = false;
-    },
-    open() {
-      this.modalIsShow = true;
-    },
-    fileChange(data) {
-      if (data.errorMsg) {
-        this.infos.file = null;
-        this.infos.md5 = null;
-        this.infos.errorMsg = data.errorMsg;
-      } else {
-        this.infos.file = data.file;
-        this.infos.md5 = data.md5;
-        this.infos.errorMsg = null;
-      }
-    },
-    async submit() {
-      if (!this.infos.file) {
-        this.$message.error("请选择标答文件");
-        return;
-      }
-
-      if (this.isSubmit) return;
-      this.isSubmit = true;
-
-      let formData = new FormData();
-      formData.append("id", this.instance.id);
-      formData.append(`file`, this.infos.file);
-      formData.append(`md5`, this.infos.md5);
-      const data = await examStructureUploadAnswer(formData).catch(() => {});
-      this.isSubmit = false;
-      if (!data) return;
-
-      this.$message.success("上传成功!");
-      this.$emit("modified");
-      this.cancel();
-    }
-  }
-};
-</script>
+<template>
+  <el-dialog
+    class="upload-paper-answer-dialog"
+    :visible.sync="modalIsShow"
+    title="上传试卷标答PDF文档"
+    top="10vh"
+    width="600px"
+    :close-on-click-modal="false"
+    :close-on-press-escape="false"
+    append-to-body
+    destroy-on-close
+    @open="visibleChange"
+  >
+    <el-form ref="modalFormComp" :model="infos" label-width="50px">
+      <div class="part-box">
+        <h3 class="mb-2">卷型{{ instance.paperType }}</h3>
+        <el-form-item prop="file" label="标答:">
+          <select-file
+            :format="fileFormat"
+            :disabled="isSubmit"
+            @file-change="fileChange"
+          ></select-file>
+        </el-form-item>
+      </div>
+    </el-form>
+    <div slot="footer">
+      <el-button type="primary" :disabled="isSubmit" @click="submit"
+        >确认</el-button
+      >
+      <el-button @click="cancel">取消</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import { examStructureUploadAnswer } from "../api";
+import SelectFile from "./SelectFile.vue";
+
+export default {
+  name: "upload-paper-answer-dialog",
+  components: { SelectFile },
+  props: {
+    instance: {
+      type: Object,
+      default() {
+        return {};
+      }
+    }
+  },
+  data() {
+    return {
+      modalIsShow: false,
+      isSubmit: false,
+      infos: { file: null, md5: null, errorMsg: null },
+      fileFormat: ["pdf"]
+    };
+  },
+  methods: {
+    visibleChange() {
+      this.infos = { file: null, md5: null, errorMsg: null };
+    },
+    cancel() {
+      this.modalIsShow = false;
+    },
+    open() {
+      this.modalIsShow = true;
+    },
+    fileChange(data) {
+      if (data.errorMsg) {
+        this.infos.file = null;
+        this.infos.md5 = null;
+        this.infos.errorMsg = data.errorMsg;
+      } else {
+        this.infos.file = data.file;
+        this.infos.md5 = data.md5;
+        this.infos.errorMsg = null;
+      }
+    },
+    async submit() {
+      if (!this.infos.file) {
+        this.$message.error("请选择标答文件");
+        return;
+      }
+
+      if (this.isSubmit) return;
+      this.isSubmit = true;
+
+      let formData = new FormData();
+      formData.append("id", this.instance.id);
+      formData.append(`file`, this.infos.file);
+      formData.append(`md5`, this.infos.md5);
+      const data = await examStructureUploadAnswer(formData).catch(() => {});
+      this.isSubmit = false;
+      if (!data) return;
+
+      this.$message.success("上传成功!");
+      this.$emit("modified");
+      this.cancel();
+    }
+  }
+};
+</script>

+ 204 - 207
src/modules/stmms/components/markParam/ModifyObjectiveAnswer.vue

@@ -1,207 +1,204 @@
-<template>
-  <el-dialog
-    class="modify-objective-answer modify-mark-params"
-    :visible.sync="modalIsShow"
-    top="0"
-    :close-on-click-modal="false"
-    :close-on-press-escape="false"
-    :show-close="false"
-    append-to-body
-    fullscreen
-    destroy-on-close
-    @open="visibleChange"
-  >
-    <div class="box-justify" slot="title">
-      <h2 class="el-dialog__title">设置客观题标答</h2>
-      <div>
-        <el-button type="success" :disabled="isSubmit" @click="submit"
-          >确定</el-button
-        >
-        <el-button @click="cancel">取消</el-button>
-      </div>
-    </div>
-
-    <p class="structure-desc">
-      <span>课程名称:</span>
-      <span class="mr-4">{{ instance.courseName }}</span>
-      <span>课程代码:</span>
-      <span>{{ instance.courseCode }}</span>
-    </p>
-    <el-table
-      ref="TableList"
-      :data="tableData"
-      border
-      :row-class-name="getRowClassName"
-    >
-      <el-table-column width="50" align="center">
-        <template slot-scope="scope" v-if="scope.row.isMainFirstSub">
-          <div
-            :class="[
-              'expand-btn',
-              { 'expand-btn-unexpand': !scope.row.expandSub }
-            ]"
-            @click="switchExpandSub(scope.row)"
-          >
-            <i
-              :class="scope.row.expandSub ? 'el-icon-minus' : 'el-icon-plus'"
-            ></i>
-          </div>
-        </template>
-      </el-table-column>
-      <el-table-column prop="mainTitle" label="大题名称">
-        <span slot-scope="scope" v-if="scope.row.isMainFirstSub">
-          {{ scope.row.mainTitle }}
-        </span>
-      </el-table-column>
-      <el-table-column prop="mainNumber" label="大题号" width="80">
-        <template slot-scope="scope" v-if="scope.row.isMainFirstSub">
-          <span>{{ scope.row.mainNumber }}</span>
-        </template>
-      </el-table-column>
-      <el-table-column
-        prop="subNumber"
-        label="小题号"
-        width="80"
-      ></el-table-column>
-      <el-table-column prop="totalScore" label="小题满分" width="105">
-      </el-table-column>
-      <el-table-column label="答案" width="200px">
-        <template slot-scope="scope">
-          <el-input
-            v-model.trim="scope.row.answer"
-            placeholder="请输入答案"
-            maxlength="16"
-            clearable
-          ></el-input>
-        </template>
-      </el-table-column>
-    </el-table>
-
-    <div slot="footer"></div>
-  </el-dialog>
-</template>
-
-<script>
-import { updateObjectiveAnswer } from "../../api";
-
-export default {
-  name: "modify-objective-answer",
-  props: {
-    instance: {
-      type: Object,
-      default() {
-        return {};
-      }
-    }
-  },
-  data() {
-    return {
-      modalIsShow: false,
-      isSubmit: false,
-      tableData: []
-    };
-  },
-  methods: {
-    initData() {
-      let objectiveStructure = JSON.parse(
-        this.instance.objectiveStructure || "[]"
-      );
-      objectiveStructure.sort((a, b) => {
-        if (a.mainNumber === b.mainNumber) {
-          return a.subNumber - b.subNumber;
-        } else {
-          return a.mainNumber - b.mainNumber;
-        }
-      });
-
-      let curMainNumber = null,
-        curMainId = null;
-      this.tableData = objectiveStructure.map(item => {
-        let nitem = { ...item };
-        if (nitem.mainNumber !== curMainNumber) {
-          curMainId = this.$randomCode();
-          curMainNumber = nitem.mainNumber;
-          nitem.isMainFirstSub = true;
-        }
-        nitem.id = this.$randomCode();
-        nitem.mainId = curMainId;
-        nitem.expandSub = true;
-        nitem.answer = item.answer || "";
-        return nitem;
-      });
-    },
-    visibleChange() {
-      this.initData();
-    },
-    cancel() {
-      this.modalIsShow = false;
-    },
-    open() {
-      this.modalIsShow = true;
-    },
-    getRowClassName({ row }) {
-      let classNames = [];
-      if (row.isMainFirstSub) {
-        classNames.push("row-main-first-sub");
-      }
-      if (!row.isMainFirstSub && !row.expandSub) {
-        classNames.push("row-unexpand-sub");
-      }
-      return classNames.join(" ");
-    },
-    switchExpandSub(row) {
-      row.expandSub = !row.expandSub;
-      this.tableData
-        .filter(item => item.mainId === row.mainId && !item.isMainFirstSub)
-        .forEach(item => (item.expandSub = row.expandSub));
-    },
-    checkData() {
-      let errorMessages = [];
-      this.tableData.forEach(item => {
-        let errorMsg = "";
-        if (item.answer) {
-          if (!/^[A-Z]{1,26}$/.test(item.answer)) {
-            errorMsg += `答案只能输入英文大写字母`;
-          } else {
-            const ansSet = new Set(item.answer.split(""));
-            if (ansSet.size !== item.answer.length) {
-              errorMsg += `答案不能重复`;
-            }
-          }
-        } else {
-          errorMsg += `答案不能为空`;
-        }
-
-        if (errorMsg) {
-          errorMessages.push(
-            `第${item.mainNumber}大题,第${item.subNumber}小题,${errorMsg}`
-          );
-        }
-      });
-      if (errorMessages.length) {
-        this.$message.error(errorMessages.join("。"));
-        return;
-      }
-
-      return true;
-    },
-    async submit() {
-      if (!this.checkData()) return;
-
-      if (this.isSubmit) return;
-      this.isSubmit = true;
-      const datas = {
-        id: this.instance.id,
-        objectiveStructure: this.tableData
-      };
-      const data = await updateObjectiveAnswer(datas).catch(() => {});
-      this.isSubmit = false;
-      if (!data) return;
-
-      this.$message.success("编辑成功!");
-      this.$emit("modified");
-      this.cancel();
-    }
-  }
-};
-</script>
+<template>
+  <el-dialog
+    class="modify-objective-answer modify-mark-params"
+    :visible.sync="modalIsShow"
+    top="0"
+    :close-on-click-modal="false"
+    :close-on-press-escape="false"
+    :show-close="false"
+    append-to-body
+    fullscreen
+    destroy-on-close
+    @open="visibleChange"
+  >
+    <div class="box-justify" slot="title">
+      <h2 class="el-dialog__title">
+        设置客观题标答
+        <span>-{{ instance.courseName }}({{ instance.courseCode }})</span>
+      </h2>
+      <div>
+        <el-button type="success" :disabled="isSubmit" @click="submit"
+          >确定</el-button
+        >
+        <el-button @click="cancel">取消</el-button>
+      </div>
+    </div>
+
+    <el-table
+      ref="TableList"
+      :data="tableData"
+      border
+      :row-class-name="getRowClassName"
+    >
+      <el-table-column width="50" align="center">
+        <template slot-scope="scope" v-if="scope.row.isMainFirstSub">
+          <div
+            :class="[
+              'expand-btn',
+              { 'expand-btn-unexpand': !scope.row.expandSub }
+            ]"
+            @click="switchExpandSub(scope.row)"
+          >
+            <i
+              :class="scope.row.expandSub ? 'el-icon-minus' : 'el-icon-plus'"
+            ></i>
+          </div>
+        </template>
+      </el-table-column>
+      <el-table-column prop="mainTitle" label="大题名称">
+        <span slot-scope="scope" v-if="scope.row.isMainFirstSub">
+          {{ scope.row.mainTitle }}
+        </span>
+      </el-table-column>
+      <el-table-column prop="mainNumber" label="大题号" width="80">
+        <template slot-scope="scope" v-if="scope.row.isMainFirstSub">
+          <span>{{ scope.row.mainNumber }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column
+        prop="subNumber"
+        label="小题号"
+        width="80"
+      ></el-table-column>
+      <el-table-column prop="totalScore" label="小题满分" width="105">
+      </el-table-column>
+      <el-table-column label="答案" width="200px">
+        <template slot-scope="scope">
+          <el-input
+            v-model.trim="scope.row.answer"
+            placeholder="请输入答案"
+            maxlength="16"
+            clearable
+          ></el-input>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <div slot="footer"></div>
+  </el-dialog>
+</template>
+
+<script>
+import { updateObjectiveAnswer } from "../../api";
+
+export default {
+  name: "modify-objective-answer",
+  props: {
+    instance: {
+      type: Object,
+      default() {
+        return {};
+      }
+    }
+  },
+  data() {
+    return {
+      modalIsShow: false,
+      isSubmit: false,
+      tableData: []
+    };
+  },
+  methods: {
+    initData() {
+      let objectiveStructure = JSON.parse(
+        this.instance.objectiveStructure || "[]"
+      );
+      objectiveStructure.sort((a, b) => {
+        if (a.mainNumber === b.mainNumber) {
+          return a.subNumber - b.subNumber;
+        } else {
+          return a.mainNumber - b.mainNumber;
+        }
+      });
+
+      let curMainNumber = null,
+        curMainId = null;
+      this.tableData = objectiveStructure.map(item => {
+        let nitem = { ...item };
+        if (nitem.mainNumber !== curMainNumber) {
+          curMainId = this.$randomCode();
+          curMainNumber = nitem.mainNumber;
+          nitem.isMainFirstSub = true;
+        }
+        nitem.id = this.$randomCode();
+        nitem.mainId = curMainId;
+        nitem.expandSub = true;
+        nitem.answer = item.answer || "";
+        return nitem;
+      });
+    },
+    visibleChange() {
+      this.initData();
+    },
+    cancel() {
+      this.modalIsShow = false;
+    },
+    open() {
+      this.modalIsShow = true;
+    },
+    getRowClassName({ row }) {
+      let classNames = [];
+      if (row.isMainFirstSub) {
+        classNames.push("row-main-first-sub");
+      }
+      if (!row.isMainFirstSub && !row.expandSub) {
+        classNames.push("row-unexpand-sub");
+      }
+      return classNames.join(" ");
+    },
+    switchExpandSub(row) {
+      row.expandSub = !row.expandSub;
+      this.tableData
+        .filter(item => item.mainId === row.mainId && !item.isMainFirstSub)
+        .forEach(item => (item.expandSub = row.expandSub));
+    },
+    checkData() {
+      let errorMessages = [];
+      this.tableData.forEach(item => {
+        let errorMsg = "";
+        if (item.answer) {
+          if (!/^[A-Z]{1,26}$/.test(item.answer)) {
+            errorMsg += `答案只能输入英文大写字母`;
+          } else {
+            const ansSet = new Set(item.answer.split(""));
+            if (ansSet.size !== item.answer.length) {
+              errorMsg += `答案不能重复`;
+            }
+          }
+        } else {
+          errorMsg += `答案不能为空`;
+        }
+
+        if (errorMsg) {
+          errorMessages.push(
+            `第${item.mainNumber}大题,第${item.subNumber}小题,${errorMsg}`
+          );
+        }
+      });
+      if (errorMessages.length) {
+        this.$message.error(errorMessages.join("。"));
+        return;
+      }
+
+      return true;
+    },
+    async submit() {
+      if (!this.checkData()) return;
+
+      if (this.isSubmit) return;
+      this.isSubmit = true;
+      const datas = {
+        id: this.instance.id,
+        objectiveStructure: this.tableData
+      };
+      const data = await updateObjectiveAnswer(datas).catch(() => {});
+      this.isSubmit = false;
+      if (!data) return;
+
+      this.$message.success("编辑成功!");
+      this.$emit("modified");
+      this.cancel();
+    }
+  }
+};
+</script>