Browse Source

feat: 评卷管理

zhangjie 10 months ago
parent
commit
70be0b83fc

+ 3 - 0
.vscode/settings.json

@@ -0,0 +1,3 @@
+{
+  "editor.hover.delay": 1000
+}

+ 8 - 0
src/constants/enumerate.js

@@ -433,3 +433,11 @@ export const TASK_STATUS = {
   FINISH: "已完成",
   UN_FINISH: "未完成",
 };
+export const MARK_TASK_STATUS = {
+  WAITING: "未处理",
+  MARKED: "已评",
+  REJECTED: "已打回",
+  WAIT_ARBITRATE: "等待仲裁",
+  ARBITRATED: "已仲裁",
+  PROBLEM: "问题卷",
+};

+ 8 - 0
src/modules/mark/api.js

@@ -133,6 +133,14 @@ export const markMarkerRecycle = (datas) => {
 export const markMarkerSetTaskCount = (datas) => {
   return $postParam("/api/admin/mark/marker/setTaskCount", datas);
 };
+// mark-detail-task
+export const markDetailTaskListPage = (datas) => {
+  return $postParam("/api/admin/mark/quality/list", datas);
+};
+// mark-detail-reject
+export const markRejectHistoryListPage = (datas) => {
+  return $postParam("/api/admin/mark/quality/list", datas);
+};
 // mark-detail-quality
 export const markQualityListPage = (datas) => {
   return $postParam("/api/admin/mark/quality/list", datas);

+ 12 - 0
src/modules/mark/components/markDetail/MarkDetail.vue

@@ -47,6 +47,8 @@ import MarkDetailMarker from "./MarkDetailMarker.vue";
 import MarkDetailQuality from "./MarkDetailQuality.vue";
 import MarkDetailIssue from "./MarkDetailIssue.vue";
 import MarkDetailArbitration from "./MarkDetailArbitration.vue";
+import MarkDetailTask from "./MarkDetailTask.vue";
+import MarkDetailReject from "./MarkDetailReject.vue";
 
 export default {
   name: "mark-detail",
@@ -56,6 +58,8 @@ export default {
     MarkDetailQuality,
     MarkDetailIssue,
     MarkDetailArbitration,
+    MarkDetailTask,
+    MarkDetailReject,
   },
   props: {
     instance: {
@@ -79,6 +83,10 @@ export default {
           name: "评卷员管理",
           val: "marker",
         },
+        {
+          name: "任务管理",
+          val: "task",
+        },
         {
           name: "评卷质量",
           val: "quality",
@@ -91,6 +99,10 @@ export default {
           name: "仲裁管理",
           val: "arbitration",
         },
+        {
+          name: "打回记录",
+          val: "reject",
+        },
       ],
       current: 0,
     };

+ 205 - 0
src/modules/mark/components/markDetail/MarkDetailReject.vue

@@ -0,0 +1,205 @@
+<template>
+  <div class="mark-detail-reject">
+    <div class="part-box part-box-filter part-box-flex">
+      <el-form ref="FilterForm" label-position="left" label-width="85px" inline>
+        <el-form-item label="评阅题目">
+          <el-select
+            v-model="filter.groupNumber"
+            placeholder="评阅题目"
+            clearable
+          >
+            <el-option
+              v-for="group in questions"
+              :key="group.groupNumber"
+              :value="group.groupNumber"
+              :label="group.groupQuestions"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="评卷员">
+          <el-input
+            v-model.trim="filter.loginName"
+            placeholder="评卷员姓名"
+            clearable
+          >
+          </el-input>
+        </el-form-item>
+        <el-form-item label="学号">
+          <el-input
+            v-model.trim="filter.studentCode"
+            placeholder="学号"
+            clearable
+          >
+          </el-input>
+        </el-form-item>
+        <el-form-item label="密号">
+          <el-input
+            v-model.trim="filter.secretNumber"
+            placeholder="密号"
+            clearable
+          >
+          </el-input>
+        </el-form-item>
+        <el-form-item label-width="0px">
+          <el-button type="primary" @click="search">查询</el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+
+    <div class="part-box part-box-pad">
+      <el-table ref="TableList" :data="dataList">
+        <el-table-column
+          type="index"
+          label="序号"
+          width="70"
+          :index="indexMethod"
+        ></el-table-column>
+        <el-table-column
+          prop="groupQuestions"
+          label="评阅题目"
+          min-width="200"
+        ></el-table-column>
+        <el-table-column
+          prop="studentCode"
+          label="学号"
+          width="180"
+        ></el-table-column>
+        <el-table-column
+          prop="studentName"
+          label="姓名"
+          width="120"
+        ></el-table-column>
+        <el-table-column
+          prop="secretNumber"
+          label="密号"
+          width="100"
+        ></el-table-column>
+        <el-table-column
+          prop="teachClassName"
+          label="教学班"
+          min-width="200"
+        ></el-table-column>
+        <el-table-column prop="userName" label="评卷员" min-width="100">
+          <template slot-scope="scope">
+            <el-tag size="medium" type="primary">
+              {{ scope.row.userName }}({{ scope.row.loginName }})
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column
+          prop="markerScore"
+          label="评卷总分"
+          width="90"
+        ></el-table-column>
+        <el-table-column
+          prop="markerScoreList"
+          label="给分明细"
+          width="90"
+        ></el-table-column>
+        <el-table-column prop="markerTime" label="评卷时间" width="170">
+          <span slot-scope="scope">{{
+            scope.row.markerTime | timestampFilter
+          }}</span>
+        </el-table-column>
+        <el-table-column prop="rejectUserName" label="打回人" min-width="100">
+          <template slot-scope="scope">
+            <el-tag
+              v-if="scope.row.rejectUserName"
+              size="medium"
+              type="primary"
+            >
+              {{ scope.row.rejectUserName }}({{ scope.row.rejectLoginName }})
+            </el-tag>
+            <span v-else>--</span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="rejectTime" label="打回时间" width="170">
+          <span slot-scope="scope">{{
+            scope.row.rejectTime | timestampFilter
+          }}</span>
+        </el-table-column>
+        <el-table-column
+          prop="rejectReason"
+          label="打回原因"
+          width="120"
+        ></el-table-column>
+      </el-table>
+      <div class="part-page">
+        <el-pagination
+          background
+          layout="total, sizes, prev, pager, next, jumper"
+          :pager-count="5"
+          :current-page="current"
+          :total="total"
+          :page-size="size"
+          @current-change="toPage"
+          @size-change="pageSizeChange"
+        >
+        </el-pagination>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { markRejectHistoryListPage, markGroupQuestions } from "../../api";
+
+export default {
+  name: "mark-detail-reject",
+  props: {
+    baseInfo: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+  },
+  data() {
+    return {
+      filter: {
+        groupNumber: "",
+        loginName: "",
+        studentCode: "",
+        secretNumber: "",
+      },
+      current: 1,
+      size: this.GLOBAL.pageSize,
+      total: 0,
+      dataList: [],
+      questions: [],
+    };
+  },
+  mounted() {
+    this.getQuestions();
+    this.search();
+  },
+  methods: {
+    async getQuestions() {
+      const res = await markGroupQuestions({
+        examId: this.baseInfo.examId,
+        paperNumber: this.baseInfo.paperNumber,
+      });
+      this.questions = res || [];
+    },
+    async getList() {
+      const datas = {
+        ...this.filter,
+        examId: this.baseInfo.examId,
+        paperNumber: this.baseInfo.paperNumber,
+        pageNumber: this.current,
+        pageSize: this.size,
+      };
+      const data = await markRejectHistoryListPage(datas);
+      this.dataList = data.records;
+      this.total = data.total;
+    },
+    toPage(page) {
+      this.current = page;
+      this.getList();
+    },
+    search() {
+      this.toPage(1);
+    },
+  },
+};
+</script>

+ 262 - 0
src/modules/mark/components/markDetail/MarkDetailTask.vue

@@ -0,0 +1,262 @@
+<template>
+  <div class="mark-detail-task">
+    <div class="part-box part-box-filter part-box-flex">
+      <el-form ref="FilterForm" label-position="left" label-width="85px" inline>
+        <el-form-item label="评阅题目">
+          <el-select
+            v-model="filter.groupNumber"
+            placeholder="评阅题目"
+            clearable
+          >
+            <el-option
+              v-for="group in questions"
+              :key="group.groupNumber"
+              :value="group.groupNumber"
+              :label="group.groupQuestions"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="评卷员">
+          <el-input
+            v-model.trim="filter.loginName"
+            placeholder="评卷员姓名"
+            clearable
+          >
+          </el-input>
+        </el-form-item>
+        <el-form-item label="状态">
+          <el-select v-model="filter.status" placeholder="状态" clearable>
+            <el-option
+              v-for="(val, key) in MARK_TASK_STATUS"
+              :key="key"
+              :value="key"
+              :label="val"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="学号">
+          <el-input
+            v-model.trim="filter.studentCode"
+            placeholder="学号"
+            clearable
+          >
+          </el-input>
+        </el-form-item>
+        <el-form-item label="密号">
+          <el-input
+            v-model.trim="filter.secretNumber"
+            placeholder="密号"
+            clearable
+          >
+          </el-input>
+        </el-form-item>
+        <el-form-item label="小题得分">
+          <el-input-number
+            v-model="filter.subScore"
+            placeholder="小题得分"
+            clearable
+            :min="0"
+            :max="999"
+            :step="0.01"
+            step-strictly
+            :controls="false"
+          >
+          </el-input-number>
+        </el-form-item>
+        <el-form-item label-width="0px">
+          <el-button type="primary" @click="search">查询</el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+
+    <div class="part-box part-box-pad">
+      <el-table ref="TableList" :data="dataList">
+        <el-table-column
+          type="index"
+          label="序号"
+          width="70"
+          :index="indexMethod"
+        ></el-table-column>
+        <el-table-column
+          prop="groupQuestions"
+          label="评阅题目"
+          min-width="200"
+        ></el-table-column>
+        <el-table-column
+          prop="studentCode"
+          label="学号"
+          width="180"
+        ></el-table-column>
+        <el-table-column
+          prop="studentName"
+          label="姓名"
+          width="120"
+        ></el-table-column>
+        <el-table-column
+          prop="secretNumber"
+          label="密号"
+          width="100"
+        ></el-table-column>
+        <el-table-column
+          prop="teachClassName"
+          label="教学班"
+          min-width="200"
+        ></el-table-column>
+        <el-table-column
+          prop="statusDisplay"
+          label="状态"
+          width="80"
+        ></el-table-column>
+        <el-table-column prop="userName" label="评卷员" min-width="200">
+          <template slot-scope="scope">
+            <el-tag size="medium" type="primary">
+              {{ scope.row.userName }}({{ scope.row.loginName }})
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column
+          prop="markerScore"
+          label="评卷总分"
+          width="90"
+        ></el-table-column>
+        <el-table-column
+          prop="markerScoreList"
+          label="给分明细"
+          width="90"
+        ></el-table-column>
+        <el-table-column prop="markerTime" label="评卷时间" width="170">
+          <span slot-scope="scope">{{
+            scope.row.markerTime | timestampFilter
+          }}</span>
+        </el-table-column>
+        <el-table-column prop="rejectUserName" label="打回人" min-width="100">
+          <template slot-scope="scope">
+            <el-tag
+              v-if="scope.row.rejectUserName"
+              size="medium"
+              type="primary"
+            >
+              {{ scope.row.rejectUserName }}({{ scope.row.rejectLoginName }})
+            </el-tag>
+            <span v-else>--</span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="headerTime" label="打回时间" width="170">
+          <span slot-scope="scope">{{
+            scope.row.headerTime | timestampFilter
+          }}</span>
+        </el-table-column>
+        <el-table-column
+          prop="rejectReason"
+          label="打回原因"
+          width="120"
+        ></el-table-column>
+        <el-table-column
+          class-name="action-column"
+          label="操作"
+          width="120"
+          fixed="right"
+        >
+          <template slot-scope="scope">
+            <el-button
+              v-if="checkPrivilege('link', 'MarkTaskReject')"
+              class="btn-primary"
+              :disabled="scope.row.status !== 'MARKED'"
+              type="text"
+              @click="toReject(scope.row)"
+              >打回</el-button
+            >
+          </template>
+        </el-table-column>
+      </el-table>
+      <div class="part-page">
+        <el-pagination
+          background
+          layout="total, sizes, prev, pager, next, jumper"
+          :pager-count="5"
+          :current-page="current"
+          :total="total"
+          :page-size="size"
+          @current-change="toPage"
+          @size-change="pageSizeChange"
+        >
+        </el-pagination>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { markDetailTaskListPage, markGroupQuestions } from "../../api";
+import { MARK_TASK_STATUS } from "@/constants/enumerate";
+
+export default {
+  name: "mark-detail-task",
+  props: {
+    baseInfo: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+  },
+  data() {
+    return {
+      filter: {
+        groupNumber: "",
+        loginName: "",
+        status: "",
+        studentCode: "",
+        secretNumber: "",
+        subScore: undefined,
+      },
+      current: 1,
+      size: this.GLOBAL.pageSize,
+      total: 0,
+      dataList: [],
+      questions: [],
+      MARK_TASK_STATUS,
+    };
+  },
+  mounted() {
+    this.getQuestions();
+    this.search();
+  },
+  methods: {
+    async getQuestions() {
+      const res = await markGroupQuestions({
+        examId: this.baseInfo.examId,
+        paperNumber: this.baseInfo.paperNumber,
+      });
+      this.questions = res || [];
+    },
+    async getList() {
+      const datas = {
+        ...this.filter,
+        examId: this.baseInfo.examId,
+        paperNumber: this.baseInfo.paperNumber,
+        pageNumber: this.current,
+        pageSize: this.size,
+      };
+      const data = await markDetailTaskListPage(datas);
+      this.dataList = data.records;
+      this.total = data.total;
+    },
+    toPage(page) {
+      this.current = page;
+      this.getList();
+    },
+    search() {
+      this.toPage(1);
+    },
+    toReject(row) {
+      this.toMarkReject({
+        examId: row.examId,
+        paperNumber: row.paperNumber,
+        groupNumber: row.groupNumber,
+        studentId: row.studentId,
+      });
+    },
+  },
+};
+</script>

+ 4 - 0
src/modules/mark/markMinxin.js

@@ -25,6 +25,10 @@ export default {
       this.$ls.set("check-students", { examId, paperNumber, studentIds });
       this.openPage("/mark/check/subjective-answer");
     },
+    toMarkReject({ examId, paperNumber, groupNumber, studentId }) {
+      this.$ls.set("reject", { examId, paperNumber, groupNumber, studentId });
+      this.openPage("/mark/check/subjective-answer");
+    },
     openPage(url) {
       // window.location.href = url;
       window.open(url);