zhangjie hai 1 ano
pai
achega
fe5c1b0acc

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

@@ -132,3 +132,14 @@ export const markIssueReset = (datas) => {
 export const markArbitrationListPage = (datas) => {
   return $postParam("/api/admin/mark/arbitrate/list", datas);
 };
+
+// score check --------->
+export const scoreCheckListPage = (datas) => {
+  return $postParam("/api/admin/mark/setting/scoreList", datas);
+};
+export const scoreDetailListPage = (datas) => {
+  return $postParam("/api/admin/mark/student/score", datas);
+};
+export const packageListPage = (datas) => {
+  return $postParam("/api/admin/mark/paper/package/list", datas);
+};

+ 383 - 0
src/modules/mark/components/ScoreDetail.vue

@@ -0,0 +1,383 @@
+<template>
+  <el-dialog
+    :visible.sync="modalIsShow"
+    top="0"
+    :close-on-click-modal="false"
+    :close-on-press-escape="false"
+    :show-close="false"
+    append-to-body
+    fullscreen
+    @open="initData"
+  >
+    <div slot="title">
+      <h2 class="el-dialog__title">成绩详情</h2>
+      <span
+        >课程名称:{{ instance.courseName }}({{ instance.courseCode }})</span
+      >
+      <span>试卷编号:{{ instance.paperNumber }}</span>
+      <button class="el-dialog__headerbtn" @click="cancel"></button>
+    </div>
+
+    <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="学院">
+          <college-select
+            v-model="filter.college"
+            placeholder="学院"
+          ></college-select>
+        </el-form-item>
+        <el-form-item label="班级">
+          <major-class-select
+            v-model="filter.className"
+            :major-id="filter.majorId"
+            cascader
+            placeholder="班级"
+          ></major-class-select>
+        </el-form-item>
+        <el-form-item label="任课老师">
+          <el-select v-model="filter.teacher" placeholder="任课老师" clearable>
+            <!-- TODO: -->
+            <el-option :value="1">班级1</el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="检查条件">
+          <el-select v-model="filter.filter" placeholder="检查条件">
+            <el-option :value="0">无</el-option>
+            <el-option :value="1">客观题0分</el-option>
+            <el-option :value="2">客观题0分,主观题有分</el-option>
+            <el-option :value="3">主观题有分,客观题0分</el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="是否缺考">
+          <el-select v-model="filter.absent" placeholder="是否缺考" clearable>
+            <el-option :value="1">缺考</el-option>
+            <el-option :value="0">正常</el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="是否违纪">
+          <el-select v-model="filter.breach" placeholder="是否违纪" clearable>
+            <el-option :value="1">违纪</el-option>
+            <el-option :value="0">正常</el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="试卷总分">
+          <el-input-number
+            v-model="filter.startScore"
+            placeholder="试卷总分"
+            :min="0"
+            :max="9999"
+            :step="0.01"
+            step-strictly
+            :controls="false"
+            clearable
+          >
+          </el-input-number>
+          <span>-</span>
+          <el-input-number
+            v-model="filter.endScore"
+            placeholder="试卷总分"
+            :min="0"
+            :max="9999"
+            :step="0.01"
+            step-strictly
+            :controls="false"
+            clearable
+          >
+          </el-input-number>
+        </el-form-item>
+        <el-form-item label="小题得分">
+          <el-input-number
+            v-model="filter.subScore"
+            placeholder="小题得分"
+            :min="0"
+            :max="9999"
+            :step="0.01"
+            step-strictly
+            :controls="false"
+            clearable
+          >
+          </el-input-number>
+        </el-form-item>
+        <el-form-item label="客观分">
+          <el-input-number
+            v-model="filter.objectiveScoreRateLt"
+            placeholder="客观分小于X%"
+            :min="1"
+            :max="100"
+            :step="1"
+            step-strictly
+            :controls="false"
+            clearable
+          >
+          </el-input-number>
+        </el-form-item>
+        <el-form-item label="姓名">
+          <el-input
+            v-model.trim="filter.studentName"
+            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-width="0px">
+          <el-button type="primary" @click="search">查询</el-button>
+        </el-form-item>
+      </el-form>
+      <div class="part-box-action">
+        <el-button
+          type="primary"
+          :disabled="!multipleSelection.length"
+          @click="toBatchCheck(multipleSelection)"
+        >
+          批量检查
+        </el-button>
+      </div>
+    </div>
+
+    <div class="part-box part-box-pad">
+      <el-table
+        ref="TableList"
+        :data="dataList"
+        @selection-change="handleSelectionChange"
+      >
+        <el-table-column
+          type="selection"
+          width="55"
+          align="center"
+        ></el-table-column>
+        <el-table-column prop="studentName" label="姓名" min-width="100">
+        </el-table-column>
+        <el-table-column
+          prop="studentCode"
+          label="学号"
+          width="180"
+        ></el-table-column>
+        <el-table-column
+          prop="secretNumber"
+          label="密号"
+          width="180"
+        ></el-table-column>
+        <el-table-column
+          prop="className"
+          label="班级"
+          min-width="100"
+        ></el-table-column>
+        <el-table-column
+          prop="objectiveScoreString"
+          label="客观分"
+          width="80"
+        ></el-table-column>
+        <el-table-column
+          prop="subjectiveScoreString"
+          label="主观分"
+          width="80"
+        ></el-table-column>
+        <el-table-column
+          prop="totalScoreString"
+          label="总分"
+          width="80"
+        ></el-table-column>
+        <el-table-column
+          prop="subjectiveScoreList"
+          label="主观题明细"
+          min-width="240"
+        ></el-table-column>
+        <el-table-column
+          prop="checkUserName"
+          label="检查人"
+          width="140"
+        ></el-table-column>
+        <el-table-column prop="checkTime" label="检查时间" width="170">
+          <span slot-scope="scope">{{
+            scope.row.checkTime | timestampFilter
+          }}</span>
+        </el-table-column>
+        <el-table-column
+          class-name="action-column"
+          label="操作"
+          width="300"
+          fixed="right"
+        >
+          <template slot-scope="scope">
+            <el-button
+              class="btn-primary"
+              type="text"
+              @click="toViewSheetPaper(scope.row)"
+              >原图</el-button
+            >
+            <el-button
+              class="btn-primary"
+              type="text"
+              @click="toViewPaper(scope.row)"
+              >轨迹图</el-button
+            >
+            <el-button
+              class="btn-primary"
+              type="text"
+              :disabled="!scope.row.subjectiveScoreString"
+              @click="toCheckQuestion(scope.row, 'subjective')"
+              >主观题检查</el-button
+            >
+            <el-button
+              class="btn-primary"
+              type="text"
+              @click="toCheckQuestion(scope.row, 'objective')"
+              >客观题检查</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>
+
+    <!-- image-preview -->
+    <simple-image-preview
+      :cur-image="curImage"
+      @on-prev="toPrevImage"
+      @on-next="toNextImage"
+      ref="SimpleImagePreview"
+    ></simple-image-preview>
+
+    <div slot="footer"></div>
+  </el-dialog>
+</template>
+
+<script>
+import { scoreDetailListPage } from "../api";
+import SimpleImagePreview from "@/components/SimpleImagePreview";
+
+export default {
+  name: "score-detail",
+  components: { SimpleImagePreview },
+  props: {
+    instance: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+  },
+  data() {
+    return {
+      modalIsShow: false,
+      filter: {
+        college: "",
+        className: "",
+        teacher: "",
+        filter: 0,
+        absent: null,
+        breach: null,
+        startScore: null,
+        endScore: null,
+        subScore: null,
+        objectiveScoreRateLt: null,
+        studentName: "",
+        studentCode: "",
+      },
+      current: 1,
+      size: this.GLOBAL.pageSize,
+      total: 0,
+      dataList: [],
+      multipleSelection: [],
+      // img view
+      curImage: {},
+      curImageIndex: 0,
+      imageList: [],
+    };
+  },
+  methods: {
+    cancel() {
+      this.modalIsShow = false;
+    },
+    open() {
+      this.modalIsShow = true;
+    },
+    async getList() {
+      const datas = {
+        ...this.filter,
+        examId: this.instance.examId,
+        paperNumber: this.instance.pageNumber,
+        pageNumber: this.current,
+        pageSize: this.size,
+      };
+      if (datas.absent !== null && datas.absent !== "")
+        datas.absent = !!datas.absent;
+      if (datas.breach !== null && datas.breach !== "")
+        datas.breach = !!datas.breach;
+
+      const data = await scoreDetailListPage(datas);
+      this.dataList = data.records;
+      this.total = data.total;
+    },
+    toPage(page) {
+      this.current = page;
+      this.getList();
+    },
+    search() {
+      this.toPage(1);
+    },
+    handleSelectionChange(val) {
+      this.multipleSelection = val;
+    },
+    toBatchCheck() {
+      if (!this.multipleSelection.length) return;
+      // TODO:
+    },
+    toCheckQuestion(row, type) {
+      console.log(row, type);
+      // TODO:
+    },
+    // img view
+    toViewSheetPaper(row) {
+      this.curImageIndex = 0;
+      this.imageList = row.sheetUrls || [];
+      this.selectImage(this.curImageIndex);
+      this.$refs.SimpleImagePreview.open();
+    },
+    async toViewPaper() {
+      // TODO:
+    },
+    selectImage(index) {
+      this.curImage = this.imageList[index];
+    },
+    toPrevImage() {
+      if (this.curImageIndex === 0) {
+        this.curImageIndex = this.imageList.length - 1;
+      } else {
+        this.curImageIndex--;
+      }
+
+      this.selectImage(this.curImageIndex);
+    },
+    toNextImage() {
+      if (this.curImageIndex === this.imageList.length - 1) {
+        this.curImageIndex = 0;
+      } else {
+        this.curImageIndex++;
+      }
+
+      this.selectImage(this.curImageIndex);
+    },
+  },
+};
+</script>

+ 186 - 0
src/modules/mark/components/SignTablePreview.vue

@@ -0,0 +1,186 @@
+<template>
+  <el-dialog
+    :visible.sync="modalIsShow"
+    top="0"
+    :close-on-click-modal="false"
+    :close-on-press-escape="false"
+    :show-close="false"
+    append-to-body
+    fullscreen
+    @open="initData"
+  >
+    <div slot="title">
+      <h2 class="el-dialog__title">成绩详情</h2>
+      <span
+        >课程名称:{{ instance.courseName }}({{ instance.courseCode }})</span
+      >
+      <span>试卷编号:{{ instance.paperNumber }}</span>
+      <button class="el-dialog__headerbtn" @click="cancel"></button>
+    </div>
+
+    <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.packageCode"
+            placeholder="签到表编号"
+            clearable
+          >
+            <el-option :value="1">班级1</el-option>
+          </el-select>
+        </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="packageCode" label="签到表编号" min-width="200">
+        </el-table-column>
+        <el-table-column prop="count" label="图片数量" width="100">
+        </el-table-column>
+        <el-table-column
+          class-name="action-column"
+          label="查看图片"
+          width="100"
+          fixed="right"
+        >
+          <template slot-scope="scope">
+            <el-button
+              class="btn-primary"
+              type="text"
+              @click="toViewSheetPaper(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>
+
+    <!-- image-preview -->
+    <simple-image-preview
+      :cur-image="curImage"
+      @on-prev="toPrevImage"
+      @on-next="toNextImage"
+      ref="SimpleImagePreview"
+    ></simple-image-preview>
+
+    <div slot="footer"></div>
+  </el-dialog>
+</template>
+
+<script>
+import { packageListPage } from "../api";
+import SimpleImagePreview from "@/components/SimpleImagePreview";
+
+export default {
+  name: "score-detail",
+  components: { SimpleImagePreview },
+  props: {
+    instance: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+  },
+  data() {
+    return {
+      modalIsShow: false,
+      filter: {
+        packageCode: "",
+      },
+      current: 1,
+      size: this.GLOBAL.pageSize,
+      total: 0,
+      dataList: [],
+      multipleSelection: [],
+      // img view
+      curImage: {},
+      curImageIndex: 0,
+      imageList: [],
+    };
+  },
+  methods: {
+    cancel() {
+      this.modalIsShow = false;
+    },
+    open() {
+      this.modalIsShow = true;
+    },
+    async getList() {
+      const datas = {
+        ...this.filter,
+        examId: this.instance.examId,
+        paperNumber: this.instance.pageNumber,
+        pageNumber: this.current,
+        pageSize: this.size,
+      };
+      const data = await packageListPage(datas);
+      this.dataList = data.records;
+      this.total = data.total;
+    },
+    toPage(page) {
+      this.current = page;
+      this.getList();
+    },
+    search() {
+      this.toPage(1);
+    },
+    handleSelectionChange(val) {
+      this.multipleSelection = val;
+    },
+    // img view
+    toViewSheetPaper(row) {
+      this.curImageIndex = 0;
+      this.imageList = (row.urls || []).map((url, index) => {
+        return { url, index: index + 1 };
+      });
+      this.selectImage(this.curImageIndex);
+      this.$refs.SimpleImagePreview.open();
+    },
+    selectImage(index) {
+      this.curImage = this.imageList[index];
+    },
+    toPrevImage() {
+      if (this.curImageIndex === 0) {
+        this.curImageIndex = this.imageList.length - 1;
+      } else {
+        this.curImageIndex--;
+      }
+
+      this.selectImage(this.curImageIndex);
+    },
+    toNextImage() {
+      if (this.curImageIndex === this.imageList.length - 1) {
+        this.curImageIndex = 0;
+      } else {
+        this.curImageIndex++;
+      }
+
+      this.selectImage(this.curImageIndex);
+    },
+  },
+};
+</script>

+ 143 - 4
src/modules/mark/views/ScoreCheck.vue

@@ -1,13 +1,152 @@
 <template>
-  <div class="mark-check">mark-check</div>
+  <div class="score-check">
+    <div class="part-box part-box-filter part-box-flex">
+      <el-form ref="FilterForm" label-position="left" label-width="85px" inline>
+        <template v-if="checkPrivilege('condition', 'condition')">
+          <secp-select
+            v-model="filter"
+            defaultSelectExam
+            @exam-default="search"
+          ></secp-select>
+        </template>
+        <el-form-item label-width="0px">
+          <el-button
+            v-if="checkPrivilege('button', 'select')"
+            type="primary"
+            @click="search"
+            >查询</el-button
+          >
+        </el-form-item>
+      </el-form>
+      <div class="part-box-action"></div>
+    </div>
+
+    <div class="part-box part-box-pad">
+      <el-table
+        ref="TableList"
+        :data="dataList"
+        @selection-change="handleSelectionChange"
+      >
+        <el-table-column
+          type="selection"
+          width="55"
+          align="center"
+        ></el-table-column>
+        <el-table-column prop="courseName" label="课程(代码)" min-width="200">
+          <template slot-scope="scope">
+            {{ scope.row.courseName }}({{ scope.row.courseCode }})
+          </template>
+        </el-table-column>
+        <el-table-column
+          prop="paperNumber"
+          label="试卷编号"
+          min-width="140"
+        ></el-table-column>
+        <el-table-column prop="percent" label="参考人数" width="100">
+        </el-table-column>
+        <el-table-column
+          class-name="action-column"
+          label="操作"
+          width="200"
+          fixed="right"
+        >
+          <template slot-scope="scope">
+            <el-button
+              v-if="checkPrivilege('link', 'Submit')"
+              class="btn-primary"
+              type="text"
+              @click="toDetail(scope.row)"
+              >查看详情</el-button
+            >
+            <el-button
+              v-if="checkPrivilege('link', 'Submit')"
+              class="btn-primary"
+              type="text"
+              @click="toViewSign(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>
+
+    <!-- ScoreDetail -->
+    <score-detail ref="ScoreDetail" :instance="curRow"></score-detail>
+  </div>
 </template>
 
 <script>
+import { scoreCheckListPage } from "../api";
+import ScoreDetail from "../components/ScoreDetail.vue";
+
 export default {
-  name: "mark-check",
+  name: "score-check",
+  components: { ScoreDetail },
   data() {
-    return {};
+    return {
+      filter: {
+        semesterId: "",
+        examId: "",
+        courseCode: "",
+        paperNumber: "",
+        progressStatus: null,
+      },
+      current: 1,
+      size: this.GLOBAL.pageSize,
+      total: 0,
+      dataList: [],
+      curRow: {},
+      multipleSelection: [],
+      downloading: false,
+    };
+  },
+  methods: {
+    async getList() {
+      if (!this.checkPrivilege("list", "list")) return;
+
+      const datas = {
+        ...this.filter,
+        pageNumber: this.current,
+        pageSize: this.size,
+      };
+      if (datas.progressStatus !== null && datas.progressStatus !== "")
+        datas.progressStatus = !!datas.progressStatus;
+
+      const data = await scoreCheckListPage(datas);
+      this.dataList = data.records;
+      this.total = data.total;
+    },
+    toPage(page) {
+      this.current = page;
+      this.getList();
+    },
+    search() {
+      this.toPage(1);
+    },
+    handleSelectionChange(val) {
+      this.multipleSelection = val;
+    },
+    toDetail(row) {
+      this.curRow = row;
+      this.$refs.ScoreDetail.open();
+    },
+    toViewSign(row) {
+      // TODO:
+      console.log(row);
+    },
   },
-  methods: {},
 };
 </script>