tanyanfei 1 vuosi sitten
vanhempi
commit
e8c67c1c61
2 muutettua tiedostoa jossa 947 lisäystä ja 213 poistoa
  1. 590 170
      src/views/tasks/Index.vue
  2. 357 43
      src/views/tasks/markPaper.vue

+ 590 - 170
src/views/tasks/Index.vue

@@ -6,109 +6,238 @@
         <el-breadcrumb-item>阅卷任务</el-breadcrumb-item>
       </el-breadcrumb>
     </div>
-    <el-form :model="params" label-width="80px" class="filter-form" :inine="true">
+    <el-form :model="queryParams" label-width="80px" class="filter-form" :inine="true">
       <el-row>
         <el-col :span="4">
           <el-form-item label="学校">
-            <el-select size="mini" v-model="params.school_id">
+            <el-select size="mini" v-model="queryParams.school_id">
               <el-option label="人大附中" value="人大附中">人大附中</el-option>
             </el-select>
           </el-form-item>
         </el-col>
         <el-col :span="4">
-          <el-form-item label="年级" v-model="params.grade_id">
-            <el-select v-model="params.school_id" size="mini">
+          <el-form-item label="年级" v-model="queryParams.grade_id">
+            <el-select v-model="queryParams.school_id" size="mini">
               <el-option label="高三一班" value="高三一班">高三一班</el-option>
             </el-select>
           </el-form-item>
         </el-col>
         <el-col :span="8">
           <el-form-item label-width="10" style="margin-left: 10px">
-            <el-button type="primary" @click="getList()" size="mini">筛选</el-button>
-            <!-- <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd">新增</el-button> -->
+            <el-button type="primary" @click="getData" size="mini">筛选</el-button>
+            <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd">新增</el-button>
           </el-form-item>
         </el-col>
       </el-row>
     </el-form>
-	<el-table :data="tableData" stripe style="width: 100%" height="65vh">
-	  <el-table-column prop="name" label="作业名称"> </el-table-column>
-	  <el-table-column prop="full_score" label="满分">
-	    <template slot-scope="scope">
-	      <div class="bold">{{ scope.row.full_score }}</div>
-	    </template>
-	  </el-table-column>
-	  <el-table-column prop="max_score" label="最高分">
-	    <template slot-scope="scope">
-	      <div class="bold">{{ scope.row.max_score }}</div>
-	    </template>
-	  </el-table-column>
-	  <el-table-column prop="avg_score" label="平均分">
-	    <template slot-scope="scope">
-	      <div class="bold">{{ scope.row.avg_score }}</div>
-	    </template>
-	  </el-table-column>
-	  <el-table-column prop="pass_rate" label="及格率">
-	    <template slot-scope="scope">
-	      <div class="bold" style="color: #0a9dff">
-	        {{ scope.row.pass_rate }}
-	      </div>
-	    </template>
-	  </el-table-column>
-	  <el-table-column prop="phone" label="批阅进度" width="180">
-	    <template slot-scope="scope">
-	     <div class="d-f prosss_box">
-	        <el-progress
-	          :percentage="scope.row.ww"
-	          :stroke-width="8"
-	          :color="
-	            scope.row.total_students == scope.row.marked_students
-	              ? '#0A9DFF'
-	              : '#FA0A2F'
-	          "
-	        ></el-progress>
-	        <div class="contrasts">
-	          <span>{{ scope.row.marked_students }}/</span>
-	          <span>{{ scope.row.total_students }}</span>
-	        </div>
-	      </div>
-	    </template>
-	  </el-table-column>
-	  <el-table-column prop="ctime" label="上传时间">
-	  </el-table-column>
-	  <el-table-column prop="phone" label="操作">
-	    <template slot-scope="scope">
-	      <el-button
-	        @click="
-	          jump(
+    <el-table v-loading="loading" :data="list" style="width: 100%; margin-top: 10px" height="50vh">
+      <el-table-column prop="name" label="作业名称"> </el-table-column>
+      	  <el-table-column prop="full_score" label="满分">
+      	    <template slot-scope="scope">
+      	      <div class="bold">{{ scope.row.full_score }}</div>
+      	    </template>
+      	  </el-table-column>
+      	  <el-table-column prop="max_score" label="最高分">
+      	    <template slot-scope="scope">
+      	      <div class="bold">{{ scope.row.max_score }}</div>
+      	    </template>
+      	  </el-table-column>
+      	  <el-table-column prop="avg_score" label="平均分">
+      	    <template slot-scope="scope">
+      	      <div class="bold">{{ scope.row.avg_score }}</div>
+      	    </template>
+      	  </el-table-column>
+      	  <el-table-column prop="pass_rate" label="及格率">
+      	    <template slot-scope="scope">
+      	      <div class="bold" style="color: #0a9dff">
+      	        {{ scope.row.pass_rate }}
+      	      </div>
+      	    </template>
+      	  </el-table-column>
+      	  <el-table-column prop="phone" label="批阅进度" width="180">
+      	    <template slot-scope="scope">
+      	     <div class="d-f prosss_box">
+      	        <el-progress
+      	          :percentage="scope.row.ww"
+      	          :stroke-width="8"
+      	          :color="
+      	            scope.row.total_students == scope.row.marked_students
+      	              ? '#0A9DFF'
+      	              : '#FA0A2F'
+      	          "
+      	        ></el-progress>
+      	        <div class="contrasts">
+      	          <span>{{ scope.row.marked_students }}/</span>
+      	          <span>{{ scope.row.total_students }}</span>
+      	        </div>
+      	      </div>
+      	    </template>
+      	  </el-table-column>
+      <el-table-column align="center" prop="ctime" label="创建时间" />
+      <el-table-column align="center" prop="date" label="操作" width="320">
+        <template slot-scope="scope">
+			
+          <el-button @click="jump(
 	            '/task/markpaper?title=' +
 	              scope.row.name +
 	              '&id=' +
 	              scope.row.id
-	          )
-	        "
-	        type="text"
-	        size="small"
-	        >批阅</el-button
-	      >
-	      <el-button
-	        type="text"
-	        size="small"
-	        @click="
-	          jump(
-	            '/Answer_analysis?title=' +
-	              scope.row.name +
-	              '&id=' +
-	              scope.row.id,2
-	          )
-	        "
-	        >查看</el-button
-	      >
-	    </template>
-	  </el-table-column>
-	</el-table>
-	
-    <Page ref="pageButton" :current="params.page" :page_size="params.page_size" :total="total" @pageChange="gopage" />
- 
+	          )" size="mini" type="warning">开始阅卷</el-button>
+		  <el-button @click="edit(scope.row.id)" size="mini" type="warning">编辑</el-button>
+          <el-button @click="openUploadPaper(scope.row.id)" size="mini" type="primary">上传试卷</el-button>
+          <el-button @click="del(scope.row.id)" size="mini" type="danger">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <Page ref="pageButton" :current="form.page" :page_size="form.page_size" :total="total" @pageChange="gopage" />
+    <!-- 新增/编辑阅卷任务 -->
+    <el-dialog title="新增/编辑阅卷任务" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="名称" prop="name">
+          <el-input clearable v-model="form.name" placeholder="请输入名称"></el-input>
+        </el-form-item>
+        <el-form-item label="试卷模板" prop="role">
+          <el-select v-model="form.paper_id" placeholder="请选择试卷模板" filterable>
+            <el-option v-for="item in papersList" :key="item.id" :label="item.name" :value="item.id">
+            </el-option>
+          </el-select>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="open = false">取 消</el-button>
+      </div>
+    </el-dialog>
+    <!-- 预览识别结果 -->
+    <el-dialog title="预览识别结果" :visible.sync="showAnsVisible" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-image :src="curStudentRecImg">
+          <div slot="error" class="image-slot">
+            <i class="el-icon-picture-outline"></i>
+          </div>
+        </el-image>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="showAnsVisible = false">关 闭</el-button>
+      </div>
+    </el-dialog>
+    <!-- 上传试卷 -->
+    <el-dialog title="试卷上传" :visible.sync="uploadDialogVisible" width="90%" @close="closeUploadDialog">
+      <el-row :gutter="20">
+        <el-col :span="16">
+          <!-- <el-row>
+            <el-col :span="6">参考人数:{{studentsList.length}}</el-col>
+            <el-col :span="6">已上传:{{studentsList.length}}</el-col>
+            <el-col :span="6">识别异常:</el-col>
+          </el-row> -->
+          <el-form :inline="true">
+            <el-form-item label="姓名">
+              <el-input size="mini" placeholder="请输入姓名/考号" v-model="queryName" clearable></el-input>
+            </el-form-item>
+            <el-form-item label="识别异常">
+              <el-select v-model="queryMarkStatus" size="mini" clearable>
+                <el-option v-for="item in $const.recErrorList" :label="item.label" :value="item.value"></el-option>
+
+              </el-select>
+            </el-form-item>
+            <el-form-item>
+              <el-button type="primary" size="mini" @click=searchMarkData>搜索</el-button>
+              <el-button size="mini" @click="reSetMarkData">重置</el-button>
+              <el-button @click="downloadObjectiveResult(curTaskId)" type="warning" size="mini" icon="el-icon-download">
+                导出</el-button>
+              <el-button @click="reTryMark" size="mini" type="success" icon="el-icon-printer">重新识别</el-button>
+            </el-form-item>
+          </el-form>
+          <el-row>
+            <el-col :span="24">
+              <el-tabs v-model="activeName" @tab-click="handleTabClick">
+                <el-tab-pane :label="'正常('+recSucTotal+')'" name="1"></el-tab-pane>
+                <el-tab-pane :label="'异常('+recErrTotal+')'" name="100"></el-tab-pane>
+              </el-tabs>
+            </el-col>
+          </el-row>
+          <el-table v-loading="loading" 
+            :data="studentsList" 
+            style="width: 100%; margin-top: 10px"
+            @selection-change="handleSelectionChange" 
+            height="60vh">
+            <el-table-column type="selection" width="45" v-if="activeName==100"></el-table-column>
+            <el-table-column align="center" prop="student_no" label="姓名" width="80" />
+            <el-table-column align="center" prop="student_no" label="考号" width="150">
+              <template slot-scope="scope">
+                <el-button type="text" @click="showStudentImgs(scope.row)" size="mini">{{scope.row.student_no}}
+                </el-button>
+              </template>
+            </el-table-column>
+            <el-table-column align="center" prop="objective_score" label="得分" />
+            <!-- <el-table-column align="center" prop="mark_status" label="试卷状态">
+              <template slot-scope="scope">
+                <span v-if="scope.row.mark_status==0" style="color:#e6a23c;">待上传</span>
+                <span v-if="scope.row.mark_status==1" style="color:#85ce61;">已上传</span>
+              </template>
+            </el-table-column> -->
+            <el-table-column align="center" prop="mark_status_name" label="识别状态">
+              <template slot-scope="scope">
+                <span v-if="scope.row.mark_status<=0" style="color:#f78989;">{{scope.row.mark_status_name}}</span>
+                <span v-if="scope.row.mark_status==1" style="color:#85ce61;">正常</span>
+              </template>
+            </el-table-column>
+            <el-table-column align="center" prop="ctime" label="时间" width="140px">
+              <template slot-scope="scope">
+                <span style="font-size:12px;">{{scope.row.ctime}}</span>
+              </template>
+            </el-table-column>
+            <el-table-column align="center" prop="date" label="操作" fixed="right" width="120px">
+              <template slot-scope="scope">
+                <el-button @click="showCurRecImg(scope.row)" size="mini" type="text">查看</el-button>
+                <el-button @click="showCurRecKhImg(scope.row)" size="mini" type="text">考号</el-button>
+                <el-button @click="delStudents(scope.row.id,scope.$index)" size="mini" type="text">删除</el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+          <Page ref="pageButton" :current="recPage" :page_size="recPageSize" :total="recTotal"
+            @pageChange="goRecPage" />
+        </el-col>
+        <el-col :span="8">
+          <div style="height:85vh;overflow-y:scroll;position: relative;">
+            <el-button style="position:absolute;top:0px;left:100px;" size="small" type="warning" icon="el-icon-printer">
+              试卷扫描</el-button>
+            <span style="position:absolute;top:0px;right:40px;color:green;">成功上传:{{fileList.length}}</span>
+            <el-upload class="upload-demo" action="http://test.scxjc.club/api/admin/papers/uploadpaper"
+              :on-success="handleUploadSuccess" :file-list="fileList" list-type="picture" :data="{taskid:taskid}"
+              multiple>
+              <el-button size="small" type="primary">点击上传</el-button>
+              <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div>
+            </el-upload>
+            <img v-if="fileList.length<1" src="../../assets/scanner.png" alt=""
+              style="position:absolute;left: 50%;transform: translate(-50%,120px)">
+          </div>
+        </el-col>
+      </el-row>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="closeUploadDialog">关 闭</el-button>
+      </div>
+    </el-dialog>
+    <!-- 重新识别 -->
+    <el-dialog title="重新识别" :visible.sync="remarkDialogVisible" width="60%" @close="closeRemarkDialog">
+      <el-form :inline="true">
+        <el-form-item label="考号噪声参数">
+          <el-input-number v-model="form.khVoiceNum" :min="1" :max="5"></el-input-number>
+        </el-form-item>
+        <el-form-item label="考号填涂比例阈值">
+          <el-input-number v-model="form.khFillRate" :min="1" :max="5"></el-input-number>
+        </el-form-item>
+        <el-form-item label="题目噪声参数">
+          <el-input-number v-model="form.tmVoiceNum" :min="1" :max="5"></el-input-number>
+        </el-form-item>
+        <el-form-item label="题目填涂比例阈值">
+          <el-input-number v-model="form.tmFillRate" :min="1" :max="5"></el-input-number>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="doReTryMark">确 定</el-button>
+      </div>
+    </el-dialog>
   </section>
 </template>
 <script>
@@ -119,106 +248,397 @@
     },
     data() {
       return {
-		  params: {
-		    page: 1,
-		    page_size: 10,
-		    mtype: "work",
-		    // ctgid: "",
-		    year: "",
-		    // status: "",
-		    name: "",
-		  },
-		  yearL: [],
-		  tableData: [],
-		  classL: [],
-		  total: 0,
-		  navKey: 2,
+        loading: false,
+        queryParams: {
+          page: 1,
+		  page_size:20
+        },
+        form: {
+          khVoiceNum:5,
+          khFillRate:3.0,
+          tmVoiceNum:3,
+          tmFillRate:1.8
+        },
+        form1: {},
+        form2: {},
+        list: [{}, {}],
+        total: 0,
+        title: "新增用户",
+        open: false,
+        doctorList: [],
+        rules: {},
+        uploadDialogVisible: false,
+        remarkDialogVisible:false,
+        fileList: [],
+        papersList: [],
+        taskid: null,
+        timer: null,
+        studentsList: [],
+        showAnsVisible: false,
+        curStudentRecImg: "",
+        activeName: "1",
+        curTaskId: null,
+        recPage: 1,
+        recPageSize: 20,
+        recTotal: 0,
+        recParams: {},
+        recSucTotal: 0,
+        recErrTotal: 0,
+        queryName: "",
+        queryMarkStatus: null,
+        selectException:[]
       };
     },
     methods: {
-		gopage(size) {
-		  if (size) {
-		    this.params.page_size = size;
-		  }
-		  this.params.page = this.$refs.pageButton.page;
-		  this.getList();
-		},
-		//重置
-		reset() {
-		  this.params.year = "";
-		  this.params.page = 1;
-		  this.params.name = "";
-		  this.params.cid = "";
-		  this.getList();
-		},
-		//搜索
-		search() {
-		  this.params.page = 1;
-		  this.getList();
-		},
-		//分页
-		handleCurrentChange(val) {
-		  this.params.page = val;
-		  this.getList();
-		},
-		//获取列表
-		getList() {
-		  var that = this;
-		  var obj = JSON.parse(JSON.stringify(this.params));
-		  for (let key in obj) {
-		    if (!obj[key] && key != "name") {
-		      obj[key] = "0";
-		    }
-		  }
-		  this.$api.getMarkTaskList(obj).then((res) => {
-			  console.log(res)
-		    if (res.data.code == 0) {
-		      res.data.data.list.forEach((item) => {
-		        if (item.marked_students) {
-		          item.ww = Math.round(
-		            (item.marked_students / item.total_students) * 100
-		          );
-		        } else {
-		          item.ww = 0;
-		        }
-		      });
-		      that.tableData = res.data.data.list;
-		      that.total = res.data.data.total;
-		    } else {
-		      that.tableData = [];
-		      that.total = 0;
-		      that.$message.warning(res.mess);
-		    }
-		  });
-		},
 		jump(url,id) {
-		  id==2?localStorage.setItem("sonNav",2):'';
-		  if (url) {
-		    this.$router.push(url);
-		  }
+				  id==2?localStorage.setItem("sonNav",2):'';
+				  if (url) {
+				    this.$router.push(url);
+				  }
 		},
+      submitUpload() {
+        this.$refs.upload.submit();
+      },
+      del(id) {
+        this.$confirm("确认删除?", "提示", {
+          type: "warning",
+        }).then(() => {
+          this.$api
+            .delMarkTask({
+              id: id,
+            })
+            .then((res) => {
+              if (!res.data.code) {
+                this.msgSuccess("删除成功");
+                this.getData();
+              } else {
+                this.$msgError(res.data.message);
+              }
+            });
+        });
+      },
+      gopage(size) {
+        if (size) {
+          this.queryParams.page_size = size;
+        }
+        this.queryParams.page = this.$refs.pageButton.page;
+        this.getData();
+      },
+      goRecPage(size) {
+        if (size) {
+          this.recPageSize = size;
+        }
+        this.recPage = this.$refs.pageButton.page;
+        this.recParams = {
+          task_id: this.curTaskId,
+          page: this.recPage,
+          page_size: this.recPageSize,
+          status: this.activeName,
+          name: this.queryName,
+          err_status: this.queryMarkStatus
+        }
+        window.clearInterval(this.timer);
+        this.openUploadPaper(this.curTaskId)
+      },
+      getData() {
+        this.loading = true;
+        this.$api
+          .getPapersSearch({})
+          .then((res) => {
+            this.papersList = res.data.data;
+            this.loading = false
+          });
+        this.$api.getMarkTaskList(this.queryParams).then(res => {
+          this.total = res.data.data.total;
+          this.list = res.data.data.list;
+        })
+      },
+      handleAdd() {
+        this.open = true;
+        this.title = "新增医生";
+        this.form = {};
+      },
+      /** 提交按钮 */
+      submitForm() {
+        this.$refs["form"].validate((valid) => {
+          if (valid) {
+            if (this.form.id != null) {
+              this.$api.editMarkTask(this.form).then((res) => {
+                if (res.data.code == 0) {
+                  this.msgSuccess("成功!");
+                  this.open = false;
+                  this.getData();
+                } else {
+                  this.msgError(res.data.message);
+                }
+              });
+            } else {
+              this.$api.addMarkTask(this.form).then((res) => {
+                if (res.data.code == 0) {
+                  this.msgSuccess("成功!");
+                  this.open = false;
+                  this.getData();
+                } else {
+                  this.msgError(res.data.message);
+                }
+              });
+            }
+          }
+        });
+      },
+      remoteMethod(query) {
+        if (query !== "") {
+          // this.loading = true;
+          this.$api
+            .getDoctorsSearchList({
+              name: query,
+            })
+            .then((res) => {
+              this.doctorList = res.data.data;
+              this.$set(this.doctorList, res.data.data);
+              // this.loading = false;
+            });
+        } else {
+          this.doctorList = [];
+        }
+      },
+      searchMarkData() {
+        this.recParams.name = this.queryName;
+        this.recParams.errStatus = this.queryMarkStatus;
+        window.clearInterval(this.timer);
+        this.openUploadPaper(this.curTaskId);
+      },
+      reSetMarkData() {
+        this.queryName = null;
+        this.queryMarkStatus = null;
+        this.queryParams.name = null;
+        this.queryParams.err_status = null;
+        window.clearInterval(this.timer);
+        this.openUploadPaper(this.curTaskId);
+      },
+      openUploadPaper(id) {
+        this.curTaskId = id
+        this.uploadDialogVisible = true
+        this.taskid = id
+        let that = this;
+        this.loading = true;
+        this.recParams = {
+          task_id: id,
+          page: this.recPage,
+          page_size: this.recPageSize,
+          status: this.activeName,
+          name: this.queryName,
+          err_status: this.queryMarkStatus
+        }
+        this.$api.getMarkTaskStudents(this.recParams).then(res => {
+          this.studentsList = res.data.data.list;
+          this.studentsList.forEach(item => {
+            let mark_status = item.mark_status;
+            if (mark_status != 1) {
+              item.mark_status_name = this.$const.recErrorList.filter((ritem) => {
+                return ritem.value == mark_status;
+              })[0].label
+            } else {
+              item.mark_status_name = "正常"
+            }
+          })
+          this.recTotal = res.data.data.total;
+          this.recSucTotal = res.data.data.suc_total;
+          this.recErrTotal = res.data.data.err_total;
+          this.loading = false;
+        })
+        window.clearInterval(this.timer);
+        this.timer = setInterval(function () {
+          that.$api.getMarkTaskStudents(that.recParams).then(res => {
+            that.studentsList = res.data.data.list;
+            that.studentsList.forEach(item => {
+              let mark_status = item.mark_status;
+              if (mark_status != 1) {
+                item.mark_status_name = that.$const.recErrorList.filter((ritem) => {
+                  return ritem.value == mark_status;
+                })[0].label
+              } else {
+                item.mark_status_name = "正常"
+              }
+            })
+            that.recTotal = res.data.data.total;
+            that.recSucTotal = res.data.data.suc_total;
+            that.recErrTotal = res.data.data.err_total;
+          })
+        }, 4000)
+      },
+      closeUploadDialog() {
+        this.uploadDialogVisible = false;
+        this.fileList = [];
+        window.clearInterval(this.timer);
+      },
+      closeRemarkDialog(){
+        this.remarkDialogVisible = false;
+      },
+      handlePreview(file) {
+        console.log(file);
+      },
+      handleUploadSuccess(res, file, fileList) {
+        if (!res.code) {
+          if (fileList.every(item => item.status == "success")) {
+            fileList.map(item => {
+              item.response && this.fileList.push({
+                "url": res.data.url,
+                "name": res.data.name
+              })
+            })
+          }
+        }
+      },
+      delStudents(id, index) {
+        this.$api.delMarkTaskStudents({
+          id: id
+        }).then(res => {
+          this.msgSuccess("删除成功!");
+          this.studentsList.splice(index, 1)
+        })
+      },
+      handleRemove(e) {
+        console.log(e)
+      },
+      showStudentImgs(row) {
+        this.curStudentRecImg = row.imgs;
+        this.showAnsVisible = true;
+      },
+      showCurRecImg(row) {
+        this.curStudentRecImg = row.ans_imgs.replace(".png", "_draw_ans.png");
+        this.showAnsVisible = true;
+      },
+      showCurRecKhImg(row) {
+        let ext = row.ans_imgs.split("/").pop()
+        if (ext) {
+          ext = "." + ext.split(".")[1]
+        }
+        this.curStudentRecImg = row.ans_imgs.replace("_ans" + ext, "_sno" + ext);
+        this.showAnsVisible = true;
+      },
+
+      handleTabClick(tab, event) {
+        this.activeName = tab.name;
+        this.recParams = {
+          task_id: this.curTaskId,
+          page: this.recPage,
+          page_size: this.recPageSize,
+          status: this.activeName,
+          name: this.queryName,
+          err_status: this.queryMarkStatus
+        }
+        window.clearInterval(this.timer);
+        this.openUploadPaper(this.curTaskId)
+      },
+      downloadObjectiveResult(task_id) {
+        this.$api
+          .downloadObjectiveResult({
+            task_id: task_id
+          })
+          .then((res) => {
+            var elink = document.createElement("a");
+            let blob = new Blob([res.data], {
+              type: "application/vnd.ms-excel,charset=UTF-8",
+            });
+            let objUrl = URL.createObjectURL(blob);
+            let file_name = decodeURIComponent(
+              res.headers["content-disposition"].split("=")[1]
+            );
+            elink.download = file_name;
+            elink.style.display = "none";
+            elink.href = objUrl;
+            document.body.appendChild(elink);
+            elink.click();
+            document.body.removeChild(elink);
+            this.download_loading = false;
+          });
+      },
+      handleSelectionChange(val) {
+        this.selectException = [];
+        if(val.length > 0){
+          val.forEach(item=>{
+            let task_img = item.task_id+";;"+item.imgs+";;"+item.id;
+            this.selectException.push(task_img);
+          })
+          window.clearInterval(this.timer);
+        }
+      },
+      reTryMark(){
+        if(this.selectException.length < 1){
+          this.msgError("请选择需要重新识别的答卷!");
+        }else{
+          this.remarkDialogVisible = true;
+        }
+      },
+      doReTryMark(){
+        let urls = []
+        this.selectException.forEach(item=>{
+          item = item + ";;" + String(this.form.khVoiceNum) + ";;" + String(this.form.khFillRate);
+          item = item + ";;" + String(this.form.tmVoiceNum) + ";;" + String(this.form.tmFillRate);
+          urls.push(item);
+        })
+        let that = this;
+        this.$api.reTryMarkPaper({urls:urls}).then(res=>{
+          this.remarkDialogVisible = false;
+          this.getData();
+          window.clearInterval(this.timer);
+          this.timer = setInterval(function () {
+          that.$api.getMarkTaskStudents(that.recParams).then(res => {
+            that.studentsList = res.data.data.list;
+            that.studentsList.forEach(item => {
+              let mark_status = item.mark_status;
+              if (mark_status != 1) {
+                item.mark_status_name = that.$const.recErrorList.filter((ritem) => {
+                  return ritem.value == mark_status;
+                })[0].label
+              } else {
+                item.mark_status_name = "正常"
+              }
+            })
+            that.recTotal = res.data.data.total;
+            that.recSucTotal = res.data.data.suc_total;
+            that.recErrTotal = res.data.data.err_total;
+          })
+        }, 4000)
+        })
+      }
     },
     created() {
-     this.getList();
+      this.getData();
 
     },
   };
 </script>
+<style lang="scss">
+  .el-upload-list--picture .el-upload-list__item {
+    width: 150px;
+    float: left;
+    margin-right: 10px;
+    position: relative;
+  }
 
+  .el-upload-list--picture .el-upload-list__item.is-success .el-upload-list__item-name {
+    position: absolute;
+    z-index: 100;
+    height: 70px;
+    line-height: 130px;
+  }
 
-
-<style>
-.prosss_box .el-progress.el-progress--line {
-  width: 88px;
-  margin: auto 5px auto 0;
-}
-.prosss_box .el-progress-bar {
-  padding-right: 0;
-}
-.prosss_box .el-progress__text {
-  display: none;
-}
-.prosss_box{
-	display:flex;
-}
+  .el-upload-list--picture .el-upload-list__item-thumbnail {
+    width: 125px;
+  }
+  .prosss_box .el-progress.el-progress--line {
+    width: 88px;
+    margin: auto 5px auto 0;
+  }
+  .prosss_box .el-progress-bar {
+    padding-right: 0;
+  }
+  .prosss_box .el-progress__text {
+    display: none;
+  }
+  .prosss_box{
+  	display:flex;
+  }
 </style>

+ 357 - 43
src/views/tasks/markPaper.vue

@@ -36,7 +36,7 @@
 	  	</div>
 		<!-- 批阅区 -->
 		<div class="mark_area">
-			<div class="canvas-wraper">
+			<div class="canvas-wraper" @click="writeScore">
 			  <canvas  id="canvas" ref="canvas"></canvas>
 			</div>
 			<div class="tool_bar">
@@ -70,7 +70,7 @@
 		</div>
 		<!-- 进度 -->
 		<div class="progress">
-				   <div class="mark_df" v-if='1'>
+				   <div class="mark_df" v-if='0'>
 								  <div class="df_title">
 									   <b>智能阅卷打分板</b><br>
 									   <span v-if="list2.length>0">
@@ -114,27 +114,82 @@
 	  </div>
 	  
 	  <!-- 打分板 -->
-	  <div class="df_pane" v-if='0'>
-		  <div class="df_title">打分板   <i class="el-icon-close"></i></div>
+	  <div class="df_pane"  
+      :style="styleObject">
+		  <div class="df_title" @mousedown="dragStart"  @touchstart="dragStart">打分板   <i class="el-icon-close"></i></div>
 		  <div class="df_content">
 			  <el-radio-group v-model="paper_type">
 			      <el-radio :label="0">无</el-radio>
 			      <el-radio :label="1">优秀试卷</el-radio>
 			      <el-radio :label="2">典型错误</el-radio>
 			   </el-radio-group>
+			   <el-tabs type="border-card" v-model="type" v-if='list2.length>0'>
+			     <el-tab-pane label="定值" name="1">
+					 <div class="tab1">
+						<span v-if='tab_index==1'>{{list1[qno_index].qno}}.</span> 
+						<span v-else>{{list2[qno_index].qno}}.</span> 
+						<ul>
+							<li :class="0===score?'act':''" @click="markScore(0)">0</li>
+							<template v-if='tab_index==1'>
+								<li v-for='i in list2[stu_index].std_score' @click="markScore(i)" :class="i==score?'act':''">{{i}}</li>
+							</template>
+							<template v-else>
+								<li v-for='i in list2[qno_index].std_score' @click="markScore(i)" :class="i==score?'act':''">{{i}}</li>
+							</template>
+							<li class="btn">
+								<el-button @click="prev" size="mini" type="success" plain>{{tab_index=='1'?'上一位':'上一题'}}</el-button>
+								<el-button @click="next" size="mini" type="success" plain>{{tab_index=='1'?'下一位':'下一题'}}</el-button>
+							</li>
+						</ul>
+					 </div>
+				 </el-tab-pane>
+			     <el-tab-pane label="累加" name="2">
+					 <div class="tab1 tab2">
+						 <ul style="width:100%;padding: 0;">
+						 	<li v-for='i in score_step' :class="i==add_score_step?'act':''" @click="accumulate(i)">+{{i}}</li>
+							<li class="ipt"><input v-model="other_score" type="text" placeholder="自定义"></li>
+						 	<li @click="pushOther">保存</li>
+							<p style="width: 100%;height: 15px;"></p>
+							<li @click="markScore('full')" style="background-color: green;border-color: green;color: #fff;">满分</li>
+							<li @click="markScore(0)" style="background-color: red;border-color: red;color: #fff;">零分</li>
+							<li @click="calcScore" style="background-color: green;border-color: green;color: #fff;margin-left: 40%;">提交</li>
+						 </ul>
+					 </div>
+				 </el-tab-pane>
+			     <el-tab-pane label="累减" name="3">
+					<div class="tab1 tab2">
+						 <ul style="width:100%;padding: 0;">
+						 	<li v-for='i in score_step' :class="i==add_score_step?'act':''" @click="accumulate(i)">-{{i}}</li>
+						 	<li class="ipt"><input v-model="other_score" type="text" placeholder="自定义"></li>
+						 	<li @click="pushOther">保存</li>
+						 	<p style="width: 100%;height: 15px;"></p>
+						 	<li @click="markScore('full')" style="background-color: green;border-color: green;color: #fff;">满分</li>
+						 	<li @click="markScore(0)" style="background-color: red;border-color: red;color: #fff;">零分</li>
+						 	<li @click="calcScore" style="background-color: green;border-color: green;color: #fff;margin-left: 40%;">提交</li>
+						 </ul>
+					 </div>					 
+				 </el-tab-pane>
+			   </el-tabs>
 		  </div>
 	  </div>
 	</section>
 </template>
 
+
+
 <script>
 	import { fabric } from 'fabric'
 	// var fabricObj=null
 	export default{
 		data(){
 			return{
-				tab_index:'1', 
-				paper_type:0,
+				add_score_step:0,  //累加分数
+				other_score:'',//自定义分数
+				type:'2',   //打分模式
+				tab_index:'1',  //批阅模式
+				paper_type:0,  //试卷类型:优秀 错误 无
+				score_step:[1,2,3],
+				full:'', //满分
 				title:'',
 				parm:{
 					 mark_type:1,    //批阅方式
@@ -215,6 +270,34 @@
 				    icon: ' icon-reset'
 				  },
 				],
+				 dragging: false,
+				  mouseX: 0,
+				  mouseY: 0,
+				  initialX: 0,
+				  initialY: 0,
+				  offsetX: 0,
+				  offsetY: 500
+			}
+		},
+		computed: {
+		    styleObject() {
+		      return {
+		        position: 'fixed',
+		        left: `${this.offsetX}px`,
+		        top: `${this.offsetY}px`
+		      };
+		    },
+		},
+		watch:{
+			type(value){
+				if(value == 2){
+					this.score=0
+				}else if(value == 3){
+					// 累减模式分数设置为满分
+					var full=this.list2[this.stu_index].std_score     //满分
+					if(this.tab_index == 2)full=this.list2[this.qno_index].std_score
+					this.score=full
+				}
 			}
 		},
 		methods:{
@@ -238,7 +321,7 @@
 				})
 			},
 			// 获取详情
-			getDataDetail(){
+			getDataDetail(next){
 				let parm=this.parm
 				if(this.tab_index == 1){
 					parm.qno=this.list1[this.qno_index].qno
@@ -248,8 +331,12 @@
 				this.$api.progressDetail(parm).then(res=>{
 					if(res.data.code == 0){
 						this.list2=res.data.data
+						if(next){
+							this.next()
+							return
+						}
 						this.score=res.data.data[0].mark_score?res.data.data[0].mark_score:''
-
+						
 						setTimeout(()=>{
 							// init(res.data.data[0].imgs)
 							this.init(res.data.data[0].imgs)
@@ -261,13 +348,14 @@
 			changeQno(index){
 				this.qno_index=index
 				this.first=1
+				this.add_score_step=0
 				if(this.tab_index == 1){
 					this.list2=[]
 					this.stu_index=0
 					this.getDataDetail()
 				}else{
 					
-					init(this.list2[index].imgs)
+					this.init(this.list2[index].imgs)
 					this.score=this.list2[index].mark_score?this.list2[index].mark_score:''
 				}
 				
@@ -276,9 +364,10 @@
 			changeStu(index){
 				this.stu_index=index
 				this.first=1
+				this.add_score_step=0
 				if(this.tab_index == 1){
 					this.score=this.list2[index].mark_score?this.list2[index].mark_score:''
-					init(this.list2[index].imgs)
+					this.init(this.list2[index].imgs)
 				}else{
 					this.list2=[]
 					this.qno_index=0
@@ -288,19 +377,28 @@
 			//下一位
 			next(){
 				if(this.parm.mark_type == 1){
-					this.submit()
+					// this.submit()
 					if(this.stu_index >= this.list2.length-1){
-						setTimeout(() => {
-						  this.$message(
-						    {
-						      message: "已经是最后一位了哦,请选择下一题",
-						      type: "warning",
-						    },1000);
-						},1000);
+						this.$message(
+						  {
+						    message: "已经是最后一位了哦,请选择下一题",
+						    type: "warning",
+						  },1000);
 					}else{
 						let index=this.stu_index+1
 						this.changeStu(index)
 					}
+				}else{
+					if(this.qno_index >= this.list2.length-1){
+						this.$message(
+						  {
+						    message: "已经是最后一题了哦,请选择下一位同学",
+						    type: "warning",
+						  },1000);
+					}else{
+						let index=this.qno_index+1
+						this.changeQno(index)
+					}
 				}
 			},
 			prev(){
@@ -314,27 +412,126 @@
 						let index=this.stu_index-1
 						this.changeStu(index)
 					}
+				}else{
+					if(this.qno_index == 0){
+						setTimeout(() => {
+						  this.$message(
+						    {
+						      message: "已经是第一题了哦",
+						      type: "warning",
+						    },1000);
+						},100);
+					}else{
+						let index=this.qno_index-1
+						this.changeQno(index)
+					}
 				}
 			},
 			//打分
-			markScore(item){
-				var score=String(this.score)
-				var full=this.list2[this.stu_index].std_score
-				if(this.tab_index == 2){
-					full=this.list2[this.qno_index].std_score
+			markScore(score){
+				if(score == 'full'){
+					score=this.list2[this.stu_index].std_score     //满分
+					if(this.tab_index == 2)score=this.list2[this.qno_index].std_score
 				}
-				if(item == '满分'){
-					item=full
-				}else if(item == 'X'){
-					item=''
+				// if(this.type == 1){
+					//定值打分
+					this.score=score
+					this.submit()
+					// setTimeout(this.next,500)
+					this.drawScore('总分'+score)
+				// }
+				
+				// var score=String(this.score)
+				// var full=this.list2[this.stu_index].std_score
+				// if(this.tab_index == 2){
+				// 	full=this.list2[this.qno_index].std_score
+				// }
+				// if(item == '满分'){
+				// 	item=full
+				// }else if(item == 'X'){
+				// 	item=''
+				// }else{
+				// 	if(this.first){
+				// 		this.first=0
+				// 	}else if(score.length<2){
+				// 		item=score+item
+				// 	}
+				// }
+				
+			},
+			//累加 减
+			accumulate(i){
+				var full=this.list2[this.stu_index].std_score     //满分
+				if(this.tab_index == 2)full=this.list2[this.qno_index].std_score
+				if(!this.add_score_step){
+					if(this.type == 2){
+						this.score=0
+					}else{
+						this.score=full
+					}
+				}
+				this.add_score_step=i
+			},
+			//保存自定义累加减分数
+			pushOther(){
+				var score=Number(this.other_score)
+				
+				if(isNaN(score)){
+					this.other_score=''
+					this.$message.warning("请输入纯数字~")
+					return
+				}
+				if(this.type == 2 && score < 0){
+					this.other_score=''
+					this.$message.warning("请输入一个正整数~")
+					return
+				}
+				score=Math.abs(score)  
+				this.add_score_step=score
+				if(this.score_step.indexOf(score)>=0){
+					this.$message.warning("该分数已存在~");
 				}else{
-					if(this.first){
-						this.first=0
-					}else if(score.length<2){
-						item=score+item
+					this.score_step.push(score)
+				}
+				this.other_score=''
+			},
+			writeScore(e){
+				var full=this.list2[this.stu_index].std_score     //满分
+				if(this.tab_index == 2)full=this.list2[this.qno_index].std_score
+				
+				var canvas = document.getElementById('canvas');
+				var x = e.clientX - canvas.getBoundingClientRect().left;
+				var y = e.clientY - canvas.getBoundingClientRect().top;
+				// console.log(x,y)
+				if(this.type == 2 && this.add_score_step){					
+					let new_score=this.score+this.add_score_step
+					if(new_score>full){
+						this.$message({
+						    message: "不能再加了,超过满分啦!",
+						    type: "warning",
+						},1000);
+						return
+					}
+					this.score=new_score
+					this.drawScore('+'+this.add_score_step,x,y)
+				}
+				else if(this.type == 3 && this.add_score_step){
+					let new_score=this.score-this.add_score_step
+					if(new_score<0){
+						this.$message({
+						    message: "不能再扣分了,分已经扣完了!",
+						    type: "warning",
+						},1000);
+						return
 					}
+					this.score=new_score
+					this.drawScore('-'+this.add_score_step,x,y)
 				}
-				this.score=item
+			},
+			//计算总分
+			calcScore(){
+				this.drawScore('总分:'+this.score)
+				this.submit()
 			},
 			submit(){
 				var score=this.score
@@ -351,7 +548,7 @@
 				  this.lock = true;
 				}, 2000);
 				var pattern = /^([1-9]\d*|0)$/;
-				if (!score) {
+				if (score === '') {
 				  this.$message.warning("还没打分哦~");
 				  return;
 				} else if (!pattern.test(score)) {
@@ -383,12 +580,46 @@
 			  }
 			  this.$api.mark(obj).then(res=>{
 			      if (res.data.code == 0) {
-			        this.score=''
+			        // this.score=''
 			        this.$message.success("批阅成功");
-			        this.getDataDetail()
-			      }
+			        this.getDataDetail(1)
+			      }else{
+					  this.$message.warning(res.data.message);
+				  }
 			  })
 			},
+			dragStart(e) {
+			  e.preventDefault();
+			  this.dragging = true;
+			  this.initialX = e.clientX || e.touches[0].clientX;
+			  this.initialY = e.clientY || e.touches[0].clientY;
+			  this.offsetX = this.styleObject.left ? parseInt(this.styleObject.left) : 0;
+			  this.offsetY = this.styleObject.top ? parseInt(this.styleObject.top) : 0;
+		 
+			  document.addEventListener('mousemove', this.dragMove);
+			  document.addEventListener('touchmove', this.dragMove);
+			  document.addEventListener('mouseup', this.dragEnd);
+			  document.addEventListener('touchend', this.dragEnd);
+			},
+			dragMove(e) {
+			  if (this.dragging) {
+				this.mouseX = e.clientX || e.touches[0].clientX;
+				this.mouseY = e.clientY || e.touches[0].clientY;
+				// console.log(e.clientX,e.clientY)
+				this.offsetX = this.mouseX>200 ? this.mouseX-200:this.mouseX;
+				this.offsetY = this.mouseY;
+			  }
+			},
+			dragEnd() {
+			  if (this.dragging) {
+				this.dragging = false;
+				document.removeEventListener('mousemove', this.dragMove);
+				document.removeEventListener('touchmove', this.dragMove);
+				document.removeEventListener('mouseup', this.dragEnd);
+				document.removeEventListener('touchend', this.dragEnd);
+			  }
+			},
+			//画布初始化
 			init(url){
 				var width=document.querySelector('.mark_area').clientWidth
 				this.fabricObj = new fabric.Canvas("canvas", {
@@ -416,17 +647,19 @@
 				}
 				this.fabricObjAddEvent()
 			},
-			downLoadImage(){
-				var width=document.querySelector('.mark_area').clientWidth
-				var text = new fabric.Textbox(this.score + "分", {
-				  left: width-100,
-				  top: 30,
+			drawScore(text,x,y){
+				var text = new fabric.Textbox(text, {
+				  left: x||20,
+				  top: y||70,
 				  width: 20,
-				  fontSize: 32,
+				  fontSize: 28,
 				  fill: this.drawColor,
 				  hasControls: true,
 				});
 				this.fabricObj.add(text);
+			},
+			downLoadImage(){
+				
 				//生成双倍像素比的图片
 				let base64URl = this.fabricObj.toDataURL({
 				  formart: "jpg",
@@ -679,6 +912,7 @@
 			this.title = this.$route.query.title;
 			this.parm.task_id = this.$route.query.id;	
 			this.getData()
+			this.offsetX=document.querySelector('body').clientWidth-330
 		}
 	}
 	
@@ -686,8 +920,9 @@
 	
 </script>
 
+
 <style>
-	.df_pane1{
+	.df_pane{
 		width: 300px;
 		position: fixed;
 		right: 10%;
@@ -700,12 +935,91 @@
 			background-color: green;
 			color: #fff;
 			font-size: 12px;
+			cursor: move;
 			i{
 				float: right;
 			}
 		}
 		.df_content{
 			padding: 5px;
+			.el-tabs{
+				margin-top: 5px;
+			}
+			.el-radio-group span{
+				font-size: 12px !important;
+			}
+			.el-tabs__item {
+				font-size: 12px;
+				padding: 5px 10px !important;
+				height: auto;
+				line-height: inherit;
+				&.is-active{
+					color: green;
+				}
+				&:hover{
+					color: green !important;
+				}
+			}
+			.el-tabs__content{
+				min-height: 120px;
+			}
+			.tab1{
+				display: flex;
+				span{
+					width: 22px;
+				}
+				ul{
+					width: 95%;
+					display: flex;
+					flex-wrap: wrap;
+					padding-left: 10px;
+					li{
+						cursor: pointer;
+						width: 25px;
+						line-height: 25px;
+						text-align: center;
+						border: 1px solid #d9d9d9;
+						list-style: none;
+						font-size: 12px;
+						margin: 2px;
+						transition: .3s;
+						height: 25px;
+						&.act{
+							background-color: green;
+							color: #fff;
+							border-color: green;
+						}
+						&.btn{
+							width: 100%;border: none;
+							text-align: left;
+							padding-top: 10px;
+						}
+						
+					}
+				}
+			}
+			.tab2{
+				li{
+					width: auto !important;
+					padding: 5px 8px;
+					height: auto !important; 
+					line-height: inherit !important;
+					border-radius: 2px;
+					&.ipt{
+						padding: 5px;
+						width: 50px !important;
+						text-align: center;
+						input{
+							width: 95%;
+							height: 93%;
+							border: none;
+							outline: none;
+							font-size: 12px;
+							text-align: center;
+						}
+					}
+				}
+			}
 		}
 	}
 	.yj_area{