瀏覽代碼

功能修改

zhangjie 2 年之前
父節點
當前提交
4d7a6ec450

二進制
public/temps/courseTemplate.xlsx


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

@@ -223,6 +223,15 @@ export const deleteCard = (id) => {
 export const convertCardImage = (id) => {
   return $postParam("/api/admin/exam/card/convert_image", { id });
 };
+export const downloadCardFile = (id) => {
+  return $postParam(
+    "/api/admin/exam/card/download_card",
+    { id },
+    {
+      responseType: "blob",
+    }
+  );
+};
 // course-manage
 export const courseListPage = (datas) => {
   return $postParam("/api/admin/basic/course/list", datas);

+ 74 - 0
src/modules/base/components/ExamBackupEdit.vue

@@ -0,0 +1,74 @@
+<template>
+  <div class="exam-backup-edit inline-block">
+    <el-input-number
+      class="mr-1"
+      v-model="backupCount"
+      size="small"
+      :min="0"
+      :max="type === 'count' ? 200 : 99"
+      :step="1"
+      step-strictly
+      :controls="false"
+      style="width: 60px"
+      :disabled="disabled"
+      @change="emitChange"
+    ></el-input-number>
+    <el-radio-group v-model="type" :disabled="disabled" @change="typeChange">
+      <el-radio-button label="count">份</el-radio-button>
+      <el-radio-button label="percent">%</el-radio-button>
+    </el-radio-group>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "exam-backup-edit",
+  props: {
+    value: {
+      type: Number,
+      default: 1,
+    },
+    disabled: {
+      type: Boolean,
+      default: false,
+    },
+  },
+  watch: {
+    value: {
+      immediate: true,
+      handler(val) {
+        if (!val) {
+          this.backupCount = 0;
+        } else {
+          this.backupCount = val;
+          if (this.type === "percent") {
+            this.backupCount = val * 100;
+          }
+        }
+      },
+    },
+  },
+  data() {
+    return {
+      type: "count",
+      backupCount: 0,
+    };
+  },
+  methods: {
+    typeChange() {
+      if (this.type === "percent") {
+        this.backupCount = Math.min(this.backupCount, 99);
+      }
+      this.emitChange();
+    },
+    emitChange() {
+      let val = this.backupCount;
+      if (this.type === "percent") {
+        val = val / 100;
+      }
+      this.$emit("input", val);
+      this.$emit("change", val);
+    },
+  },
+};
+</script>

+ 5 - 36
src/modules/base/components/ModifyExamConfigDetail.vue

@@ -90,18 +90,7 @@
               :label="val"
             ></el-option>
           </el-select>
-          <el-input-number
-            class="mr-1"
-            v-model="modalForm.backupCount"
-            size="small"
-            :min="0"
-            :max="200"
-            :step="1"
-            step-strictly
-            :controls="false"
-            style="width: 60px"
-          ></el-input-number>
-          <span>份</span>
+          <exam-backup-edit v-model="modalForm.backupCount"></exam-backup-edit>
         </el-form-item>
         <el-form-item
           v-show="infoShow"
@@ -170,18 +159,7 @@
                 :label="val"
               ></el-option>
             </el-select>
-            <el-input-number
-              v-model="item.backupCount"
-              class="mr-1"
-              size="small"
-              :min="1"
-              :max="200"
-              :step="1"
-              step-strictly
-              :controls="false"
-              style="width: 60px"
-            ></el-input-number>
-            <span>份</span>
+            <exam-backup-edit v-model="item.backupCount"></exam-backup-edit>
           </div>
         </el-form-item>
         <!-- <h4 class="part-box-tips">普通印品:</h4> -->
@@ -222,18 +200,7 @@
                 :label="val"
               ></el-option>
             </el-select>
-            <el-input-number
-              v-model="item.backupCount"
-              class="mr-1"
-              size="small"
-              :min="1"
-              :max="200"
-              :step="1"
-              step-strictly
-              :controls="false"
-              style="width: 60px"
-            ></el-input-number>
-            <span>份</span>
+            <exam-backup-edit v-model="item.backupCount"></exam-backup-edit>
           </div>
         </el-form-item>
       </div>
@@ -283,6 +250,7 @@ import {
 import { deepCopy } from "@/plugins/utils";
 import { updateExamConfig, listOrgsByExamId, organizationList } from "../api";
 import { printPlanTemplateList } from "../../print/api";
+import ExamBackupEdit from "./ExamBackupEdit.vue";
 
 const initModalForm = {
   id: null,
@@ -324,6 +292,7 @@ const initModalForm = {
 
 export default {
   name: "modify-exam-config-detail",
+  components: { ExamBackupEdit },
   props: {
     instance: {
       type: Object,

+ 24 - 1
src/modules/base/views/CardManage.vue

@@ -162,6 +162,13 @@
               @click="toEditInfo(scope.row)"
               >编辑信息</el-button
             >
+            <el-button
+              v-if="checkPrivilege('link', 'Download')"
+              class="btn-primary"
+              type="text"
+              @click="toDownload(scope.row)"
+              >下载</el-button
+            >
           </template>
         </el-table-column>
       </el-table>
@@ -201,11 +208,17 @@
 
 <script>
 import { CARD_CREATE_METHOD_TYPE } from "../../../constants/enumerate";
-import { cardListPage, deleteCard, convertCardImage } from "../api";
+import {
+  cardListPage,
+  deleteCard,
+  convertCardImage,
+  downloadCardFile,
+} from "../api";
 import ModifyCardInfo from "../components/ModifyCardInfo";
 import pickerOptions from "@/constants/datePickerOptions";
 import ModifyCard from "../../card/components/ModifyCard";
 import SimpleImagePreview from "@/components/SimpleImagePreview";
+import { downloadByApi } from "@/plugins/download";
 
 export default {
   name: "card-manage",
@@ -308,6 +321,16 @@ export default {
       await convertCardImage(row.id);
       this.$message.success("操作成功!");
     },
+    async toDownload(row) {
+      const res = await downloadByApi(() => {
+        return downloadCardFile(row.id);
+      }, "").catch((e) => {
+        this.$message.error(e || "下载失败,请重新尝试!");
+      });
+
+      if (!res) return;
+      this.$message.success("下载成功!");
+    },
     // image-preview
     toPreviewImage(row) {
       this.imageList = row.imageUrls;

+ 4 - 0
src/modules/exam/api.js

@@ -284,3 +284,7 @@ export const dataBatchDownload = (datas) => {
 export const actionLogList = (datas) => {
   return $postParam("/api/admin/basic/operation_log/query", datas);
 };
+export const savePreviewLog = (datas) => {
+  // examTaskId,paperType,type
+  return $postParam("/api/admin/basic/operation_log/save_preview_log", datas);
+};

+ 44 - 2
src/modules/exam/components/ApplyContent.vue

@@ -52,7 +52,12 @@
                 class="icon icon-download mr-1"
                 v-if="attachment.attachmentId"
               ></i>
-              <i>{{ attachment.filename }}</i>
+              <i
+                :class="{
+                  'color-primary': auditLogCache.paper[attachment.attachmentId],
+                }"
+                >{{ attachment.filename }}</i
+              >
             </el-button>
           </td>
           <td>
@@ -139,7 +144,12 @@
               type="text"
               class="btn-primary"
               @click="toViewCard(attachment)"
-              >{{ attachment.cardTitle || "预览" }}</el-button
+              ><i
+                :class="{
+                  'color-primary': auditLogCache.card[attachment.cardId],
+                }"
+                >{{ attachment.cardTitle || "预览" }}</i
+              ></el-button
             >
           </td>
           <td v-if="IS_APPLY">
@@ -514,6 +524,7 @@ import {
   updateTaskApply,
   taskAuditApply,
   cardForSelectList,
+  savePreviewLog,
 } from "../api";
 import { attachmentPreview } from "../../login/api";
 import SimpleImagePreview from "@/components/SimpleImagePreview";
@@ -648,6 +659,7 @@ export default {
       exchangeUsers: [],
       selectUserType: "exchange", // exchange:转审,approve:下一节点审核
       curSelectedUsers: [],
+      auditLogCache: { paper: {}, card: {} },
       // 选择下一节点审批人
       IS_NEED_SELECT_APPROVE_USER: false,
       nextFlowTaskResult: {}, //下一节点信息
@@ -728,12 +740,16 @@ export default {
       let exposedPaperTypes = exposedPaperType.split(",");
       exposedPaperTypes.sort((a, b) => (a > b ? -1 : 1));
       const maxExposedPaperType = exposedPaperTypes[0];
+      let auditLogCache = { paper: {}, card: {} };
       this.paperAttachments.forEach((paper) => {
         paper.canDelete = maxExposedPaperType
           ? paper.name > maxExposedPaperType
           : true;
         paper.isExposed = exposedPaperTypes.includes(paper.name);
+        auditLogCache.paper[paper.attachmentId] = false;
+        auditLogCache.card[paper.cardId] = false;
       });
+      this.auditLogCache = auditLogCache;
 
       this.paperConfirmAttachments = this.curTaskApply.paperConfirmAttachmentIds
         ? JSON.parse(this.curTaskApply.paperConfirmAttachmentIds)
@@ -918,6 +934,7 @@ export default {
       this.paperConfirmAttachments.splice(index, 1);
     },
     toViewCard(attachment) {
+      this.addPreviewLog(attachment, "card");
       window.open(
         this.getRouterPath({
           name: "CardPreview",
@@ -1012,6 +1029,7 @@ export default {
     },
     async downloadPaper(attachment) {
       if (!attachment.attachmentId) return;
+      this.addPreviewLog(attachment, "paper");
       const data = await attachmentPreview(attachment.attachmentId);
       window.open(data.url);
     },
@@ -1144,6 +1162,13 @@ export default {
       this.$emit("modified");
     },
     async toAuditSubmit() {
+      if (this.IS_AUDIT && !this.checkAllFilePreview()) {
+        this.$message.error(
+          "还有未被查看过的题卡或试卷,请点击试卷及题卡进行查看审核"
+        );
+        return;
+      }
+
       const valid = await this.$refs.auditModalComp.validate().catch(() => {});
       if (!valid) return;
 
@@ -1207,6 +1232,23 @@ export default {
       this.$message.success("审批成功!");
       this.$emit("modified");
     },
+    // audit preview log
+    async addPreviewLog(attachment, type) {
+      if (!this.IS_AUDIT) return;
+      const id = type === "paper" ? attachment.attachmentId : attachment.cardId;
+      this.auditLogCache[type][id] = true;
+      await savePreviewLog({
+        examTaskId: this.curTaskApply.examTaskId,
+        paperType: attachment.name,
+        type,
+      });
+    },
+    checkAllFilePreview() {
+      return (
+        !Object.values(this.auditLogCache.paper).some((item) => !item) &&
+        !Object.values(this.auditLogCache.card).some((item) => !item)
+      );
+    },
     // image-preview
     toPreview(index) {
       this.curImageIndex = index;

+ 7 - 4
src/modules/exam/components/createExamAndPrintTask/InfoPrintTask.vue

@@ -129,18 +129,18 @@
         <el-table-column prop="studentCount" label="人数" width="60">
         </el-table-column>
         <el-table-column prop="backupCount" label="备份数量" width="90">
-          <!-- <template slot-scope="scope">
+          <template slot-scope="scope">
             <el-input-number
               v-model="scope.row.backupCount"
-              style="width:60px"
-              :min="1"
+              style="width: 60px"
+              :min="infoExamPrintPlan.backupCount"
               :max="99999"
               :step="1"
               step-strictly
               :controls="false"
               @change="backupCountChange"
             ></el-input-number>
-          </template> -->
+          </template>
         </el-table-column>
         <el-table-column prop="examPlace" label="考点名称">
           <template slot-scope="scope">
@@ -375,6 +375,9 @@ export default {
           }
         });
 
+        if (!row.backupCount) {
+          errorFields.push("备份数量");
+        }
         if (!row.printHouseId) {
           errorFields.push("印刷室");
         }

+ 3 - 0
src/modules/print/api.js

@@ -24,6 +24,9 @@ export const updatePrintPlan = (datas) => {
 export const removePrintPlan = (id) => {
   return $post("/api/admin/exam/print/remove", { id });
 };
+export const finishPrintPlan = (id) => {
+  return $postParam("/api/admin/exam/print/plan_finish", { id });
+};
 export const printPlanTemplateList = (datas) => {
   return $postParam("/api/admin/exam/print/get_template", datas);
 };

+ 9 - 36
src/modules/print/components/ModifyPrintPlan.vue

@@ -12,10 +12,9 @@
   >
     <el-form
       ref="modalFormComp"
-      label-width="120px"
+      label-width="130px"
       :rules="rules"
       :model="modalForm"
-      label-position="left"
     >
       <div class="part-box">
         <h4 class="part-box-tips">基本信息:</h4>
@@ -102,19 +101,10 @@
               :label="val"
             ></el-option>
           </el-select>
-          <el-input-number
-            class="mr-1"
+          <exam-backup-edit
             v-model="modalForm.backupCount"
-            size="small"
-            :min="1"
-            :max="200"
-            :step="1"
-            step-strictly
-            :controls="false"
             disabled
-            style="width: 60px"
-          ></el-input-number>
-          <span>份</span>
+          ></exam-backup-edit>
         </el-form-item>
         <el-form-item
           v-if="contentIncludesPaper"
@@ -179,19 +169,10 @@
                 :label="val"
               ></el-option>
             </el-select>
-            <el-input-number
+            <exam-backup-edit
               v-model="item.backupCount"
-              class="mr-1"
-              size="small"
-              :min="1"
-              :max="200"
-              :step="1"
-              step-strictly
-              :controls="false"
               disabled
-              style="width: 60px"
-            ></el-input-number>
-            <span>份</span>
+            ></exam-backup-edit>
           </div>
         </el-form-item>
       </div>
@@ -202,7 +183,6 @@
           v-for="(item, index) in modalForm.ordinaryContent"
           :key="item.type"
           :label="`${TEMPLATE_CLASSIFY[item.type]}:`"
-          label-width="130px"
           :prop="`ordinaryContent.${index}.templateId`"
           :rules="{
             required: false,
@@ -238,19 +218,10 @@
                 :label="val"
               ></el-option>
             </el-select>
-            <el-input-number
+            <exam-backup-edit
               v-model="item.backupCount"
-              class="mr-1"
-              size="small"
-              :min="1"
-              :max="200"
-              :step="1"
-              step-strictly
-              :controls="false"
               disabled
-              style="width: 60px"
-            ></el-input-number>
-            <span>份</span>
+            ></exam-backup-edit>
           </div>
         </el-form-item>
       </div>
@@ -282,6 +253,7 @@ import {
 import { deepCopy } from "@/plugins/utils";
 import { updatePrintPlan, printPlanTemplateList } from "../api";
 import { examConfigQuery } from "../../base/api";
+import ExamBackupEdit from "../../base/components/ExamBackupEdit.vue";
 
 const initModalForm = {
   id: null,
@@ -323,6 +295,7 @@ const initModalForm = {
 
 export default {
   name: "modify-print-plan",
+  components: { ExamBackupEdit },
   props: {
     instance: {
       type: Object,

+ 23 - 1
src/modules/print/views/PrintPlanManage.vue

@@ -162,6 +162,17 @@
               "
               >删除</el-button
             >
+            <el-button
+              class="btn-danger"
+              type="text"
+              @click="toFinish(scope.row)"
+              v-if="
+                scope.row.createId === curUserId &&
+                scope.row.status !== 'END' &&
+                checkPrivilege('link', 'Finish')
+              "
+              >删除</el-button
+            >
           </template>
         </el-table-column>
       </el-table>
@@ -198,7 +209,7 @@
 </template>
 
 <script>
-import { printPlanListPage, removePrintPlan } from "../api";
+import { printPlanListPage, removePrintPlan, finishPrintPlan } from "../api";
 import { PRINT_PLAN_STATUS } from "@/constants/enumerate";
 import pickerOptions from "@/constants/datePickerOptions";
 import ModifyPrintPlan from "../components/ModifyPrintPlan";
@@ -282,6 +293,17 @@ export default {
         })
         .catch(() => {});
     },
+    toFinish(row) {
+      this.$confirm(`结束后状态无法回退,是否继续操作?`, "提示", {
+        type: "warning",
+      })
+        .then(async () => {
+          await finishPrintPlan(row.id);
+          this.$message.success("操作成功!");
+          this.getList();
+        })
+        .catch(() => {});
+    },
   },
 };
 </script>