Browse Source

上传客观题标答

zhangjie 3 years ago
parent
commit
b134989a5a

+ 19 - 0
src/assets/styles/pages.scss

@@ -1023,3 +1023,22 @@
     }
   }
 }
+// answer-popover
+.answer-popover {
+  line-height: 24px;
+  padding: 15px;
+
+  .answer-divider {
+    margin: 10px 0;
+    height: 1px;
+    border-bottom: 1px dashed $--color-text-gray-5;
+  }
+  .el-checkbox__label,
+  .el-radio__label {
+    width: 24px;
+    text-align: center;
+  }
+  .el-radio__label {
+    display: inline-block;
+  }
+}

+ 6 - 0
src/modules/base/api.js

@@ -10,6 +10,12 @@ export const unitQueryByType = (datas, dictionaryEnum) => {
     dictionaryEnum
   });
 };
+export const enumsByType = type => {
+  // type: PUSH_TYPE_ENUM("同步类型"),
+  return $postParam("/api/admin/common/get_enums", {
+    type
+  });
+};
 // user --------------------------------->
 // user-manage
 export const userListPage = datas => {

+ 6 - 0
src/modules/base/views/PrintPlanPushManage.vue

@@ -16,6 +16,12 @@
             ></el-option>
           </el-select>
         </el-form-item>
+        <el-form-item label="考试:">
+          <exam-select
+            v-model="filter.examId"
+            :semester-id="filter.semesterId"
+          ></exam-select>
+        </el-form-item>
         <el-form-item label="印刷计划:">
           <print-plan-select
             v-model.trim="filter.printPlanId"

+ 7 - 0
src/modules/stmms/api.js

@@ -15,6 +15,9 @@ export const examStructureFindJpg = datas => {
 export const examStructureSubmit = datas => {
   return $post("/api/admin/exam/structure/submit", datas);
 };
+export const updateObjectiveAnswer = datas => {
+  return $post("/api/admin/exam/answer/submit", datas);
+};
 
 // score-archive
 export const scoreListPage = datas => {
@@ -56,3 +59,7 @@ export const yptAuth = roleType => {
 export const syncResultListPage = datas => {
   return $postParam("/api/admin/data/sync/query", datas);
 };
+export const syncResync = id => {
+  // objectId
+  return $postParam("/api/admin/data/sync/resync", { id });
+};

+ 83 - 0
src/modules/stmms/components/markParam/AnswerPopover.vue

@@ -0,0 +1,83 @@
+<template>
+  <el-popover
+    placement="left-start"
+    popper-class="answer-popover"
+    width="310"
+    trigger="hover"
+  >
+    <el-radio-group v-model="bAnswer" @change="bAnswerChange">
+      <el-radio v-for="item in radioList" :key="item" :label="item">{{
+        item
+      }}</el-radio>
+    </el-radio-group>
+    <div class="answer-divider"></div>
+    <el-checkbox-group v-model="oAnswer" @change="oAnswerChange">
+      <el-checkbox v-for="item in choiceList" :key="item" :label="item">{{
+        item
+      }}</el-checkbox>
+    </el-checkbox-group>
+    <el-button
+      slot="reference"
+      :type="answerStr ? 'primary' : 'default'"
+      plain
+      >{{ answerStr || "请设置答案" }}</el-button
+    >
+  </el-popover>
+</template>
+
+<script>
+export default {
+  name: "answer-popover",
+  props: {
+    value: {
+      type: String
+    }
+  },
+  data() {
+    return {
+      answerStr: "",
+      oAnswer: [],
+      bAnswer: null,
+      choiceList: "abcdefghijklmnopqrstuvwxyz".toUpperCase().split(""),
+      radioList: "√×".split("")
+    };
+  },
+  watch: {
+    value(val) {
+      if (val === this.answerStr) return;
+
+      if (this.radioList.includes(val)) {
+        this.bAnswer = val;
+      } else {
+        this.oAnswer = val.split("");
+      }
+      this.updateAnswerStr();
+    }
+  },
+  computed: {},
+  methods: {
+    oAnswerChange(val) {
+      if (val) this.bAnswer = null;
+      this.updateAnswerStr();
+      this.emitChange();
+    },
+    bAnswerChange(val) {
+      if (val) this.oAnswer = [];
+      this.updateAnswerStr();
+      this.emitChange();
+    },
+    updateAnswerStr() {
+      if (this.bAnswer) {
+        this.answerStr = this.bAnswer;
+        return;
+      }
+      this.oAnswer.sort((a, b) => (a < b ? -1 : 1));
+      this.answerStr = this.oAnswer.join("");
+    },
+    emitChange() {
+      this.$emit("input", this.answerStr);
+      this.$emit("change", this.answerStr);
+    }
+  }
+};
+</script>

+ 0 - 1
src/modules/stmms/components/markParam/MarkPaperStructure.vue

@@ -146,7 +146,6 @@ export default {
 
       this.$emit("on-ready");
     },
-
     createMain() {
       this.tableData.push({
         id: this.$randomCode(),

+ 10 - 7
src/modules/stmms/components/markParam/ModifyMarkParams.vue

@@ -127,14 +127,16 @@ export default {
       this.loading = false;
 
       if (this.instance.paperInfoJson) {
-        const paperInfoJson = JSON.parse(this.instance.paperInfoJson);
+        const { basicPaperInfo, paperStructureInfo, groupInfo } = JSON.parse(
+          this.instance.paperInfoJson
+        );
         this.infos = {
           paperStructureInfo: [
-            ...paperInfoJson.objectiveQuestionList,
-            ...paperInfoJson.subjectiveQuestionList
+            ...paperStructureInfo.objectiveQuestionList,
+            ...paperStructureInfo.subjectiveQuestionList
           ],
-          groupInfo: paperInfoJson.groupInfo,
-          basicPaperInfo: { ...this.instance }
+          groupInfo,
+          basicPaperInfo
         };
       } else {
         this.infos = {
@@ -143,8 +145,6 @@ export default {
           basicPaperInfo: { ...this.instance }
         };
       }
-      // this.current = 1;
-      // this.infos = paramData;
 
       this.dataReady = true;
     },
@@ -155,6 +155,7 @@ export default {
       if (res !== "confirm") return;
 
       this.modalIsShow = false;
+      this.dataReady = false;
     },
     open() {
       this.modalIsShow = true;
@@ -164,6 +165,8 @@ export default {
         type: "warning"
       }).catch(() => {});
       if (res !== "confirm") return;
+
+      this.dataReady = false;
       done();
     },
     prevStep() {

+ 169 - 0
src/modules/stmms/components/markParam/ModifyObjectiveAnswer.vue

@@ -0,0 +1,169 @@
+<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
+    @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">
+          <answer-popover v-model="scope.row.answer"></answer-popover>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <div slot="footer"></div>
+  </el-dialog>
+</template>
+
+<script>
+import AnswerPopover from "./AnswerPopover.vue";
+import { updateObjectiveAnswer } from "../../api";
+
+export default {
+  name: "modify-objective-answer",
+  components: { AnswerPopover },
+  props: {
+    instance: {
+      type: Object,
+      default() {
+        return {};
+      }
+    }
+  },
+  data() {
+    return {
+      modalIsShow: false,
+      isSubmit: false,
+      tableData: []
+    };
+  },
+  methods: {
+    initData() {
+      const objectiveStructure = JSON.parse(
+        this.instance.objectiveStructure || "[]"
+      );
+      this.tableData = objectiveStructure.map(item => {
+        return { ...item, answer: item.answer || "" };
+      });
+    },
+    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) {
+          errorMsg += `第${item.mainNumber}大题,第${item.subNumber}小题,答案不能为空,`;
+        }
+        if (errorMsg) {
+          errorMessages.push(errorMsg);
+        }
+      });
+      if (errorMessages.length) {
+        this.$message.error(errorMessages.join("。"));
+        return;
+      }
+
+      return true;
+    },
+    async submit() {
+      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>

+ 32 - 4
src/modules/stmms/views/SyncManage.vue

@@ -50,7 +50,7 @@
         ></el-table-column>
         <el-table-column prop="type" label="类别"></el-table-column>
         <el-table-column prop="status" label="状态"> </el-table-column>
-        <el-table-column prop="result" label="结果" width="100">
+        <el-table-column prop="resultStr" label="结果" width="100">
         </el-table-column>
         <el-table-column prop="createTime" label="创建时间" width="180">
           <span slot-scope="scope">{{
@@ -68,6 +68,14 @@
               @click="toDonwloadLog(scope.row)"
               >导出日志</el-button
             >
+            <el-button
+              v-if="scope.row.result === 'ERROR'"
+              type="text"
+              class="btn-primary"
+              :disabled="loading"
+              @click="toResync(scope.row)"
+              >重新同步</el-button
+            >
           </template>
         </el-table-column>
       </el-table>
@@ -87,16 +95,17 @@
 </template>
 
 <script>
-import { STMMS_SYNC_TYPE, DATA_TASK_RESULT } from "@/constants/enumerate";
-import { syncResultListPage } from "../api";
+import { DATA_TASK_RESULT } from "@/constants/enumerate";
+import { syncResultListPage, syncResync } from "../api";
 import { attachmentDownload } from "../../login/api";
+import { enumsByType } from "../../base/api";
 import { downloadByUrl } from "@/plugins/download";
 
 export default {
   name: "sync-manage",
   data() {
     return {
-      STMMS_SYNC_TYPE,
+      STMMS_SYNC_TYPE: {},
       DATA_TASK_RESULT,
       filter: {
         result: "",
@@ -110,9 +119,18 @@ export default {
     };
   },
   created() {
+    this.getSyncTypes();
     this.getList();
   },
   methods: {
+    async getSyncTypes() {
+      const res = await enumsByType("PUSH_TYPE_ENUM");
+      const data = res || [];
+      this.STMMS_SYNC_TYPE = {};
+      data.forEach(item => {
+        this.STMMS_SYNC_TYPE[item.name] = item.desc;
+      });
+    },
     async getList() {
       if (!this.checkPrivilege("list", "list")) return;
 
@@ -153,6 +171,16 @@ export default {
 
       downloadByUrl(url);
       this.$message.success("文件下载成功!");
+    },
+    async toResync(row) {
+      if (this.loading) return;
+
+      this.loading = true;
+      const res = await syncResync(row.objectId).catch(() => false);
+      this.loading = false;
+
+      if (!res) return;
+      this.$message.success("操作成功!");
     }
   }
 };

+ 17 - 52
src/modules/stmms/views/UploadStructure.vue

@@ -51,54 +51,18 @@
               >评卷参数设置</el-button
             >
             <el-button
-              v-if="checkPrivilege('link', 'Upload')"
               class="btn-primary"
               type="text"
-              @click="toUpload(scope.row)"
-              >上传试卷结构/标答</el-button
+              @click="toSetAnswer(scope.row)"
+              >设置客观题标答</el-button
             >
             <el-button
-              v-if="
-                checkPrivilege('link', 'Preview') &&
-                  scope.row.status === 'FINISH'
-              "
+              v-if="checkPrivilege('link', 'Upload')"
               class="btn-primary"
               type="text"
-              @click="toViewPaper(scope.row)"
-              >查看试卷结构</el-button
-            >
-            <template
-              v-if="
-                checkPrivilege('link', 'Preview') &&
-                  scope.row.status === 'FINISH'
-              "
+              @click="toUpload(scope.row)"
+              >上传标答</el-button
             >
-              <el-popover
-                v-if="scope.row.paperTypes.length > 1"
-                popper-class="popper-list"
-                placement="bottom-start"
-                width="80"
-                trigger="hover"
-              >
-                <el-button
-                  v-for="paperType in scope.row.paperTypes"
-                  :key="paperType"
-                  class="btn-primary"
-                  @click="toViewAnswer(scope.row, paperType)"
-                  >{{ paperType }}卷</el-button
-                >
-                <el-button class="btn-primary" type="text" slot="reference"
-                  >查看标答</el-button
-                >
-              </el-popover>
-              <el-button
-                v-else
-                class="btn-primary"
-                type="text"
-                @click="toViewAnswer(scope.row, scope.row.paperType)"
-                >查看标答</el-button
-              >
-            </template>
           </template>
         </el-table-column>
       </el-table>
@@ -120,30 +84,31 @@
       :instance="curTask"
       @modified="getList"
     />
-    <PreviewPaperStructureDialog
-      ref="PreviewPaperStructureDialog"
-      :instance="curTask"
-    />
     <ModifyMarkParams
       ref="ModifyMarkParams"
       :instance="curTask"
       @modified="getList"
     />
+    <ModifyObjectiveAnswer
+      ref="ModifyObjectiveAnswer"
+      :datas="curTask"
+      @modified="getList"
+    />
   </div>
 </template>
 
 <script>
 import { examStructureListPage } from "../api";
 import UploadPaperAnswerDialog from "../components/UploadPaperAnswerDialog";
-import PreviewPaperStructureDialog from "../components/PreviewPaperStructureDialog";
 import ModifyMarkParams from "../components/markParam/ModifyMarkParams";
+import ModifyObjectiveAnswer from "../components/markParam/ModifyObjectiveAnswer.vue";
 
 export default {
   name: "upload-structure",
   components: {
     UploadPaperAnswerDialog,
-    PreviewPaperStructureDialog,
-    ModifyMarkParams
+    ModifyMarkParams,
+    ModifyObjectiveAnswer
   },
   data() {
     return {
@@ -191,13 +156,13 @@ export default {
       this.curTask = row;
       this.$refs.ModifyMarkParams.open();
     },
-    toUpload(row) {
+    toSetAnswer(row) {
       this.curTask = row;
-      this.$refs.UploadPaperAnswerDialog.open();
+      this.$refs.ModifyObjectiveAnswer.open();
     },
-    toViewPaper(row) {
+    toUpload(row) {
       this.curTask = row;
-      this.$refs.PreviewPaperStructureDialog.open();
+      this.$refs.UploadPaperAnswerDialog.open();
     },
     toViewAnswer(row, paperType) {
       if (!row.paperAnswer || !row.paperAnswer.length) {