소스 검색

merge from release_v3.0

deason 5 년 전
부모
커밋
37475d7665
40개의 변경된 파일4872개의 추가작업 그리고 957개의 파일을 삭제
  1. 9 1
      jenkins-dev.sh
  2. 1 1
      jenkins-prod.sh
  3. 9 1
      jenkins-test.sh
  4. 3 1
      package.json
  5. 30 0
      postbuild.js
  6. 1 0
      src/constants/constants.js
  7. 734 160
      src/modules/basic/view/clientConfig.vue
  8. 16 5
      src/modules/basic/view/school_config.vue
  9. 10 0
      src/modules/examwork/routes/routes.js
  10. 50 37
      src/modules/examwork/view/examInfo.vue
  11. 243 68
      src/modules/examwork/view/examStudent.vue
  12. 8 26
      src/modules/examwork/view/offlineExam.vue
  13. 87 50
      src/modules/examwork/view/onlineExam.vue
  14. 950 0
      src/modules/examwork/view/onlineHomework.vue
  15. 842 0
      src/modules/examwork/view/onlineHomeworkOrgSettings.vue
  16. 36 38
      src/modules/examwork/view/practiceExam.vue
  17. 200 56
      src/modules/examwork/view/student.vue
  18. 2 1
      src/modules/marking/filters/filters.js
  19. 69 65
      src/modules/marking/views/MarkWork.vue
  20. 30 0
      src/modules/marking/views/MarkWorkOverview.vue
  21. 6 0
      src/modules/oe/routes/routes.js
  22. 1 1
      src/modules/oe/views/absent.vue
  23. 33 8
      src/modules/oe/views/alreadyAudited.vue
  24. 62 14
      src/modules/oe/views/awaitingAudit.vue
  25. 72 14
      src/modules/oe/views/captureDetail.vue
  26. 60 15
      src/modules/oe/views/examDetail.vue
  27. 114 28
      src/modules/oe/views/examScheduling.vue
  28. 82 71
      src/modules/oe/views/examSummary.vue
  29. 63 10
      src/modules/oe/views/illegalityNameList.vue
  30. 630 0
      src/modules/oe/views/illegalityType.vue
  31. 6 2
      src/modules/oe/views/reexamine.vue
  32. 1 3
      src/modules/oe/views/scoreStatistics.vue
  33. 2 1
      src/modules/questions/constants/constants.js
  34. 115 112
      src/modules/questions/views/EditPaper.vue
  35. 148 0
      src/modules/questions/views/ExportTemplate.vue
  36. 2 2
      src/modules/questions/views/ExtractPaperRule.vue
  37. 50 50
      src/modules/questions/views/GenPaper.vue
  38. 47 47
      src/modules/questions/views/ImportPaper.vue
  39. 18 11
      src/modules/questions/views/InsertPaperStructureInfo.vue
  40. 30 58
      yarn.lock

+ 9 - 1
jenkins-dev.sh

@@ -6,4 +6,12 @@ npm run build
 
 rm -rf ~/project/examcloud/static/examcloud-admin-web/dist/*
 mkdir -p ~/project/examcloud/static/examcloud-admin-web
-cp -r  dist ~/project/examcloud/static/examcloud-admin-web/
+cp -r  dist ~/project/examcloud/static/examcloud-admin-web/
+
+rm -rf ~/packages/static/examcloud-admin-web/*
+mkdir -p ~/packages/static/examcloud-admin-web
+cp -r dist ~/packages/static/examcloud-admin-web/
+
+cd ~/packages/static/
+rm -rf examcloud-admin-web.tar.gz
+tar -zcvf examcloud-admin-web.tar.gz examcloud-admin-web

+ 1 - 1
jenkins-prod.sh

@@ -2,7 +2,7 @@
 pwd
 
 yarn
-npm run build
+npm run build:prod
 
 rm -rf ~/project/examcloud/static/examcloud-admin-web/dist/*
 mkdir -p ~/project/examcloud/static/examcloud-admin-web

+ 9 - 1
jenkins-test.sh

@@ -6,4 +6,12 @@ npm run build
 
 rm -rf ~/project/examcloud/static/examcloud-admin-web/dist/*
 mkdir -p ~/project/examcloud/static/examcloud-admin-web
-cp -r  dist ~/project/examcloud/static/examcloud-admin-web/
+cp -r  dist ~/project/examcloud/static/examcloud-admin-web
+
+rm -rf ~/packages/static/examcloud-admin-web/*
+mkdir -p ~/packages/static/examcloud-admin-web
+cp -r dist ~/packages/static/examcloud-admin-web/
+
+cd ~/packages/static/
+rm -rf examcloud-admin-web.tar.gz
+tar -zcvf examcloud-admin-web.tar.gz examcloud-admin-web//

+ 3 - 1
package.json

@@ -6,6 +6,8 @@
     "start": "vue-cli-service serve --port 3000",
     "serve": "vue-cli-service serve",
     "build": "vue-cli-service build",
+    "build:prod": "vue-cli-service build",
+    "postbuild:prod": "IS_PROD=true node postbuild",
     "lint": "vue-cli-service lint",
     "test:unit": "vue-cli-service test:unit"
   },
@@ -42,7 +44,7 @@
     "eslint": "^5.16.0",
     "eslint-plugin-vue": "^5.2.3",
     "lint-staged": "^9.2.5",
-    "node-sass": "^4.12.0",
+    "node-sass": "^4.14.1",
     "sass-loader": "^8.0.0",
     "vue-cli-plugin-axios": "0.0.4",
     "vue-cli-plugin-element": "^1.0.0",

+ 30 - 0
postbuild.js

@@ -0,0 +1,30 @@
+console.log("> postbuild");
+const fs = require("fs");
+
+console.log("process.env.IS_PROD", process.env.IS_PROD);
+
+if (process.env.IS_PROD === "true") {
+  console.log("> postbuild 将sourcemap文件改名,防止源码泄露");
+
+  const revision = require("child_process")
+    .execSync("git rev-parse HEAD")
+    .toString()
+    .trim()
+    .slice(10, 17);
+  const DIR = "./dist/js/";
+  const sourcemaps = fs
+    .readdirSync(DIR)
+    .filter(v => v.endsWith(".map"))
+    .map(v => DIR + v);
+  for (const s of sourcemaps) {
+    fs.renameSync(s, s.replace(".js.map", "-" + revision + ".js.map"));
+    console.log(
+      "  rename ",
+      s,
+      " => ",
+      s.replace(".js.map", "-" + revision + ".js.map")
+    );
+  }
+
+  console.log();
+}

+ 1 - 0
src/constants/constants.js

@@ -15,6 +15,7 @@ export const EXAM_TYPE = [
   { label: "网考", value: "ONLINE" },
   { label: "练习", value: "PRACTICE" },
   { label: "离线", value: "OFFLINE" },
+  { label: "在线作业", value: "ONLINE_HOMEWORK" },
   { label: "印刷", value: "PRINT_EXAM" }
 ];
 

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 734 - 160
src/modules/basic/view/clientConfig.vue


+ 16 - 5
src/modules/basic/view/school_config.vue

@@ -52,10 +52,21 @@
           ></el-switch>
         </el-form-item>
         <el-form-item label="证件号隐私模式" prop="ID_NUMBER_PRIVATE_MODE">
-          <el-switch v-model="ruleForm.ID_NUMBER_PRIVATE_MODE" on-text="是" off-text="否"></el-switch>
+          <el-switch
+            v-model="ruleForm.ID_NUMBER_PRIVATE_MODE"
+            on-text="是"
+            off-text="否"
+          ></el-switch>
         </el-form-item>
-        <el-form-item label="展示APP下载二维码" prop="SHOW_STUDENT_CLIENT_APP_QRCODE">
-          <el-switch v-model="ruleForm.SHOW_STUDENT_CLIENT_APP_QRCODE" on-text="是" off-text="否"></el-switch>
+        <el-form-item
+          label="展示APP下载二维码"
+          prop="SHOW_STUDENT_CLIENT_APP_QRCODE"
+        >
+          <el-switch
+            v-model="ruleForm.SHOW_STUDENT_CLIENT_APP_QRCODE"
+            on-text="是"
+            off-text="否"
+          ></el-switch>
         </el-form-item>
         <el-form-item label="开放APP" prop="APP_ENABLED">
           <el-switch
@@ -88,8 +99,8 @@
             :disabled="btnSaveDiabled"
             type="primary"
             @click="submitForm('ruleForm')"
-            >保 存
-          </el-button>
+            >保 存</el-button
+          >
         </el-form-item>
       </el-form>
     </el-main>

+ 10 - 0
src/modules/examwork/routes/routes.js

@@ -5,11 +5,13 @@ import examStudent from "../view/examStudent.vue";
 import examInfo from "../view/examInfo.vue";
 import traditionExam from "../view/traditionExam.vue";
 import onlineExam from "../view/onlineExam.vue";
+import onlineHomework from "../view/onlineHomework.vue";
 import practiceExam from "../view/practiceExam.vue";
 import offlineExam from "../view/offlineExam.vue";
 import printExam from "../view/printExam.vue";
 import offlineExamOrgSettings from "../view/offlineExamOrgSettings.vue";
 import onlineExamOrgSettings from "../view/onlineExamOrgSettings.vue";
+import onlineHomeworkOrgSettings from "../view/onlineHomeworkOrgSettings.vue";
 import Tips from "../../portal/views/tips/Tips.vue";
 import notice from "../view/notice.vue";
 import studentSpecialSettings from "../view/studentSpecialSettings.vue";
@@ -52,6 +54,10 @@ export default [
         path: "onlineExam/:id",
         component: onlineExam
       },
+      {
+        path: "onlineHomework/:id",
+        component: onlineHomework
+      },
       {
         path: "practiceExam/:id",
         component: practiceExam
@@ -72,6 +78,10 @@ export default [
         path: "onlineExamOrgSettings/:id",
         component: onlineExamOrgSettings
       },
+      {
+        path: "onlineHomeworkOrgSettings/:id",
+        component: onlineHomeworkOrgSettings
+      },
       {
         path: "studentSpecialSettings/:id",
         component: studentSpecialSettings

+ 50 - 37
src/modules/examwork/view/examInfo.vue

@@ -28,8 +28,7 @@
                 :label="item.label"
                 :value="item.value"
                 :key="item.value"
-              >
-              </el-option>
+              ></el-option>
             </el-select>
           </el-form-item>
           <el-form-item class="d-block">
@@ -39,16 +38,16 @@
               type="primary"
               icon="el-icon-search"
               @click="resetPageAndSearchForm"
-              >查询
-            </el-button>
+              >查询</el-button
+            >
             <el-button
               v-if="rolePrivileges.add_exam"
               size="small"
               type="primary"
               icon="el-icon-plus"
               @click="addExamInfoDialog"
-              >新增
-            </el-button>
+              >新增</el-button
+            >
             <el-button
               size="small"
               type="primary"
@@ -62,7 +61,7 @@
         <!-- 弹出窗口 -->
         <el-dialog
           title="请选择考试类型"
-          width="650px"
+          width="750px"
           :visible.sync="examInfoDialog"
         >
           <div>
@@ -70,7 +69,8 @@
             <el-button @click="toOnline">网络考试</el-button>
             <el-button @click="toPractice">练习考试</el-button>
             <el-button @click="toOffline">离线考试</el-button>
-            <el-button @click="toPrint"> 分布式印刷考试</el-button>
+            <el-button @click="toOnlineHomework">在线作业</el-button>
+            <el-button @click="toPrint">分布式印刷考试</el-button>
           </div>
           <div style="margin-top: 10px;text-align: center;">
             <el-button type="primary" @click="examInfoDialog = false"
@@ -89,10 +89,14 @@
           @selection-change="selectChange"
         >
           <el-table-column type="selection" width="40"></el-table-column>
-          <el-table-column prop="id" width="60" label="ID" sortable>
-          </el-table-column>
-          <el-table-column prop="code" label="考试编码"> </el-table-column>
-          <el-table-column prop="name" label="考试名称"> </el-table-column>
+          <el-table-column
+            prop="id"
+            width="60"
+            label="ID"
+            sortable
+          ></el-table-column>
+          <el-table-column prop="code" label="考试编码"></el-table-column>
+          <el-table-column prop="name" label="考试名称"></el-table-column>
           <el-table-column width="130" label="考试类型" sortable>
             <template slot-scope="scope">
               <div>
@@ -105,17 +109,19 @@
             width="155"
             label="开始时间"
             sortable
-          >
-          </el-table-column>
-          <el-table-column prop="endTime" width="155" label="结束时间" sortable>
-          </el-table-column>
+          ></el-table-column>
+          <el-table-column
+            prop="endTime"
+            width="155"
+            label="结束时间"
+            sortable
+          ></el-table-column>
           <el-table-column
             prop="updateTime"
             width="155"
             label="更新时间"
             sortable
-          >
-          </el-table-column>
+          ></el-table-column>
           <el-table-column width="50" label="状态">
             <span slot-scope="scope">
               <span v-if="scope.row.enable">
@@ -150,9 +156,8 @@
                   type="primary"
                   icon="el-icon-edit"
                   @click="editExamInfoDialog(scope.row)"
+                  >编辑</el-button
                 >
-                  编辑
-                </el-button>
 
                 <el-dropdown
                   style="margin-left: 10px;"
@@ -162,7 +167,8 @@
                   "
                 >
                   <el-button type="primary" plain size="mini">
-                    更多<i class="el-icon-arrow-down el-icon--right"></i>
+                    更多
+                    <i class="el-icon-arrow-down el-icon--right"></i>
                   </el-button>
                   <el-dropdown-menu slot="dropdown">
                     <el-dropdown-item>
@@ -187,15 +193,16 @@
                         @click="disableById(scope.row)"
                       >
                         <i class="fa fa-close" aria-hidden="true"></i>禁用
-                      </el-button></el-dropdown-item
-                    >
+                      </el-button>
+                    </el-dropdown-item>
                     <el-dropdown-item>
                       <el-button
                         :disabled="
                           !(
                             rolePrivileges.update_exam &&
                             (scope.row.examType == 'OFFLINE' ||
-                              scope.row.examType == 'ONLINE') &&
+                              scope.row.examType == 'ONLINE' ||
+                              scope.row.examType == 'ONLINE_HOMEWORK') &&
                             scope.row.specialSettingsEnabled &&
                             scope.row.specialSettingsType == 'ORG_BASED'
                           )
@@ -204,31 +211,28 @@
                         type="primary"
                         icon="el-icon-edit"
                         @click="editOrgSettings(scope.row)"
+                        >学习中心设置</el-button
                       >
-                        学习中心设置
-                      </el-button>
                     </el-dropdown-item>
                     <el-dropdown-item>
                       <el-button
                         v-show="
-                          (
-                            rolePrivileges.update_exam &&
+                          rolePrivileges.update_exam &&
                             (scope.row.examType == 'OFFLINE' ||
-                              scope.row.examType == 'ONLINE') &&
+                              scope.row.examType == 'ONLINE' ||
+                              scope.row.examType == 'ONLINE_HOMEWORK') &&
                             scope.row.specialSettingsEnabled &&
                             scope.row.specialSettingsType == 'STUDENT_BASED'
-                          )
                         "
                         size="mini"
                         type="primary"
                         icon="el-icon-edit"
                         @click="editStudentSettings(scope.row)"
+                        >学生特殊设置</el-button
                       >
-                        学生特殊设置
-                      </el-button>
                     </el-dropdown-item>
-                  </el-dropdown-menu></el-dropdown
-                >
+                  </el-dropdown-menu>
+                </el-dropdown>
               </div>
             </template>
           </el-table-column>
@@ -243,8 +247,7 @@
             @size-change="handleSizeChange"
             layout="total, sizes, prev, pager, next, jumper"
             :total="total"
-          >
-          </el-pagination>
+          ></el-pagination>
         </div>
 
         <!-- 考试复制弹窗 -->
@@ -263,7 +266,7 @@
             label-width="120px"
           >
             <el-row>
-              <el-form-item label="考试编码" placeholder="">
+              <el-form-item label="考试编码" placeholder>
                 <el-input
                   v-model="examCopyForm.destExamName"
                   class="input"
@@ -500,6 +503,8 @@ export default {
       this.setSearchParams();
       if (row.examType == "ONLINE") {
         this.$router.push({ path: "/examwork/onlineExam/" + row.id });
+      } else if (row.examType == "ONLINE_HOMEWORK") {
+        this.$router.push({ path: "/examwork/onlineHomework/" + row.id });
       } else if (row.examType == "TRADITION") {
         this.$router.push({ path: "/examwork/traditionExam/" + row.id });
       } else if (row.examType == "PRACTICE") {
@@ -520,6 +525,10 @@ export default {
         this.$router.push({
           path: "/examwork/onlineExamOrgSettings/" + row.id
         });
+      } else if (row.examType == "ONLINE_HOMEWORK") {
+        this.$router.push({
+          path: "/examwork/onlineHomeworkOrgSettings/" + row.id
+        });
       }
     },
     editStudentSettings(row) {
@@ -552,6 +561,10 @@ export default {
       this.setSearchParams();
       this.$router.push({ path: "/examwork/offlineExam/add" });
     },
+    toOnlineHomework() {
+      this.setSearchParams();
+      this.$router.push({ path: "/examwork/onlineHomework/add" });
+    },
     toPrint() {
       this.setSearchParams();
       this.$router.push({ path: "/examwork/printExam/add" });

+ 243 - 68
src/modules/examwork/view/examStudent.vue

@@ -20,17 +20,30 @@
                 :label="item.name"
                 :value="item.id"
                 :key="item.id"
-              ></el-option>
+              >
+              </el-option>
             </el-select>
           </el-form-item>
           <el-form-item label="姓名">
-            <el-input class="input" placeholder="请输入姓名" v-model="formSearch.studentName"></el-input>
+            <el-input
+              class="input"
+              placeholder="请输入姓名"
+              v-model="formSearch.studentName"
+            ></el-input>
           </el-form-item>
           <el-form-item label="学号">
-            <el-input class="input" placeholder="请输入学号" v-model="formSearch.studentCode"></el-input>
+            <el-input
+              class="input"
+              placeholder="请输入学号"
+              v-model="formSearch.studentCode"
+            ></el-input>
           </el-form-item>
           <el-form-item label="专业">
-            <el-input class="input" placeholder="请输入专业" v-model="formSearch.specialtyName"></el-input>
+            <el-input
+              class="input"
+              placeholder="请输入专业"
+              v-model="formSearch.specialtyName"
+            ></el-input>
           </el-form-item>
           <el-form-item label="课程">
             <el-select
@@ -48,7 +61,8 @@
                 :label="item.name + ' - ' + item.code"
                 :value="item.id"
                 :key="item.id"
-              ></el-option>
+              >
+              </el-option>
             </el-select>
           </el-form-item>
           <el-form-item label="学习中心">
@@ -68,17 +82,30 @@
                 :label="item.name + ' - ' + item.code"
                 :value="item.id"
                 :key="item.id"
-              ></el-option>
+              >
+              </el-option>
             </el-select>
           </el-form-item>
           <el-form-item label="采集人">
-            <el-input class="input" placeholder="请输入采集人" v-model="formSearch.infoCollector"></el-input>
+            <el-input
+              class="input"
+              placeholder="请输入采集人"
+              v-model="formSearch.infoCollector"
+            ></el-input>
           </el-form-item>
           <el-form-item label="身份证">
-            <el-input class="input" placeholder="请输入身份证" v-model="formSearch.identityNumber"></el-input>
+            <el-input
+              class="input"
+              placeholder="请输入身份证"
+              v-model="formSearch.identityNumber"
+            ></el-input>
           </el-form-item>
           <el-form-item label="考点">
-            <el-input class="input" placeholder="请输入考点" v-model="formSearch.examSite"></el-input>
+            <el-input
+              class="input"
+              placeholder="请输入考点"
+              v-model="formSearch.examSite"
+            ></el-input>
           </el-form-item>
           <el-form-item class="d-block">
             <el-button
@@ -87,29 +114,39 @@
               type="primary"
               icon="el-icon-search"
               @click="resetPageAndSearchForm"
-            >查询</el-button>
-            <el-button size="small" icon="el-icon-refresh" @click="resetSearchForm">重置</el-button>
+              >查询
+            </el-button>
+            <el-button
+              size="small"
+              icon="el-icon-refresh"
+              @click="resetSearchForm"
+            >
+              重置
+            </el-button>
             <el-button
               v-if="rolePrivileges.add_examStudent"
               size="small"
               type="primary"
               icon="el-icon-plus"
               @click="openAddingDialog"
-            >新增</el-button>
+              >新增
+            </el-button>
             <el-button
               v-if="rolePrivileges.del_examStudent"
               size="small"
               type="danger"
               icon="el-icon-delete"
               @click="deleteStuByExam"
-            >批次删除</el-button>
+              >批次删除
+            </el-button>
             <el-button
               v-if="rolePrivileges.copy_examStudent"
               size="small"
               type="primary"
               icon="el-icon-document"
               @click="copy"
-            >复制</el-button>
+              >复制
+            </el-button>
           </el-form-item>
         </el-form>
 
@@ -123,7 +160,8 @@
             icon="el-icon-delete"
             @click="deleteStuBatch"
             :disabled="noBatchSelected"
-          >删除</el-button>
+            >删除
+          </el-button>
         </div>
 
         <div style="width: 100%;margin-bottom: 10px;"></div>
@@ -160,7 +198,8 @@
                   :value="item.id"
                   :key="item.id"
                   :disabled="!item.enable"
-                ></el-option>
+                >
+                </el-option>
               </el-select>
             </el-form-item>
             <el-form-item label="姓名" prop="studentName">
@@ -205,7 +244,8 @@
                   :value="item.id"
                   :key="item.id"
                   :disabled="!item.enable"
-                ></el-option>
+                >
+                </el-option>
               </el-select>
             </el-form-item>
             <el-form-item label="课程" prop="courseId">
@@ -225,12 +265,23 @@
                   :value="item.id"
                   :key="item.id"
                   :disabled="!item.enable"
-                ></el-option>
+                >
+                </el-option>
               </el-select>
             </el-form-item>
             <el-form-item label="试卷类型" prop="paperType">
-              <el-select class="input" v-model="examStudentForm.paperType" placeholder="请选择">
-                <el-option v-for="item in paperTypeList" :label="item" :value="item" :key="item"></el-option>
+              <el-select
+                class="input"
+                v-model="examStudentForm.paperType"
+                placeholder="请选择"
+              >
+                <el-option
+                  v-for="item in paperTypeList"
+                  :label="item"
+                  :value="item"
+                  :key="item"
+                >
+                </el-option>
               </el-select>
             </el-form-item>
             <el-form-item label="专业">
@@ -250,10 +301,18 @@
               ></el-input>
             </el-form-item>
             <el-form-item label="年级">
-              <el-input class="input" v-model="examStudentForm.grade" auto-complete="off"></el-input>
+              <el-input
+                class="input"
+                v-model="examStudentForm.grade"
+                auto-complete="off"
+              ></el-input>
             </el-form-item>
             <el-form-item label="采集人">
-              <el-input class="input" v-model="examStudentForm.infoCollector" maxlength="20"></el-input>
+              <el-input
+                class="input"
+                v-model="examStudentForm.infoCollector"
+                maxlength="20"
+              ></el-input>
             </el-form-item>
             <el-form-item label="电话">
               <el-input
@@ -264,7 +323,11 @@
               ></el-input>
             </el-form-item>
             <el-form-item label="试卷袋编码">
-              <el-input class="input" v-model="examStudentForm.ext1" maxlength="20"></el-input>
+              <el-input
+                class="input"
+                v-model="examStudentForm.ext1"
+                maxlength="20"
+              ></el-input>
             </el-form-item>
           </el-form>
           <div style="text-align: center;">
@@ -307,7 +370,8 @@
                   :value="item.id"
                   :key="item.id"
                   :disabled="!item.enable"
-                ></el-option>
+                >
+                </el-option>
               </el-select>
             </el-form-item>
             <el-form-item label="姓名" prop="studentName">
@@ -319,7 +383,12 @@
               ></el-input>
             </el-form-item>
             <el-form-item label="学号" prop="studentCode">
-              <el-input class="input" v-model="examStudentForm.studentCode" maxlength="20" readonly></el-input>
+              <el-input
+                class="input"
+                v-model="examStudentForm.studentCode"
+                maxlength="20"
+                readonly
+              ></el-input>
             </el-form-item>
             <el-form-item label="身份证号" prop="identityNumber">
               <el-input
@@ -348,7 +417,8 @@
                   :value="item.id"
                   :key="item.id"
                   :disabled="!item.enable"
-                ></el-option>
+                >
+                </el-option>
               </el-select>
             </el-form-item>
             <el-form-item label="课程" prop="courseId">
@@ -369,12 +439,23 @@
                   :value="item.id"
                   :key="item.id"
                   :disabled="!item.enable"
-                ></el-option>
+                >
+                </el-option>
               </el-select>
             </el-form-item>
             <el-form-item label="试卷类型" prop="paperType">
-              <el-select class="input" v-model="examStudentForm.paperType" placeholder="请选择">
-                <el-option v-for="item in paperTypeList" :label="item" :value="item" :key="item"></el-option>
+              <el-select
+                class="input"
+                v-model="examStudentForm.paperType"
+                placeholder="请选择"
+              >
+                <el-option
+                  v-for="item in paperTypeList"
+                  :label="item"
+                  :value="item"
+                  :key="item"
+                >
+                </el-option>
               </el-select>
             </el-form-item>
             <el-form-item label="专业">
@@ -402,7 +483,11 @@
               ></el-input>
             </el-form-item>
             <el-form-item label="采集人">
-              <el-input class="input" v-model="examStudentForm.infoCollector" maxlength="20"></el-input>
+              <el-input
+                class="input"
+                v-model="examStudentForm.infoCollector"
+                maxlength="20"
+              ></el-input>
             </el-form-item>
             <el-form-item label="电话">
               <el-input
@@ -413,7 +498,11 @@
               ></el-input>
             </el-form-item>
             <el-form-item label="试卷袋编码">
-              <el-input class="input" v-model="examStudentForm.ext1" maxlength="20"></el-input>
+              <el-input
+                class="input"
+                v-model="examStudentForm.ext1"
+                maxlength="20"
+              ></el-input>
             </el-form-item>
           </el-form>
           <div style="text-align: center;">
@@ -423,7 +512,11 @@
         </el-dialog>
 
         <!-- 复制弹窗 -->
-        <el-dialog title="考生信息复制" width="500px" :visible.sync="studentCopyDialog">
+        <el-dialog
+          title="考生信息复制"
+          width="500px"
+          :visible.sync="studentCopyDialog"
+        >
           <el-form
             :model="studentCopyForm"
             :rules="rules"
@@ -448,7 +541,8 @@
                   :label="item.name"
                   :value="item.id"
                   :key="item.id"
-                ></el-option>
+                >
+                </el-option>
               </el-select>
             </el-form-item>
             <el-form-item label="目标考试批次" prop="targetExamId">
@@ -468,7 +562,8 @@
                   :value="item.id"
                   :key="item.id"
                   :disabled="!item.enable"
-                ></el-option>
+                >
+                </el-option>
               </el-select>
             </el-form-item>
             <div style="text-align: center;">
@@ -487,63 +582,98 @@
           style="width: 100%;text-align:center;"
           @selection-change="selectChange"
         >
-          <el-table-column type="selection" width="40" fixed="left"></el-table-column>
-          <el-table-column prop="id" label="ID" sortable fixed="left"></el-table-column>
+          <el-table-column
+            type="selection"
+            width="40"
+            fixed="left"
+          ></el-table-column>
+          <el-table-column
+            prop="id"
+            label="ID"
+            sortable
+            fixed="left"
+          ></el-table-column>
           <el-table-column label="考生" fixed="left">
             <template slot-scope="scope">
               <el-popover trigger="hover" placement="left">
                 <div style="font-size: 18px;font-family: 新宋体">
                   <tr>
                     <td style="color: green">姓名</td>
-                    <td style="color:purple;padding-left: 20px;">{{ scope.row.studentName }}</td>
+                    <td style="color:purple;padding-left: 20px;">
+                      {{ scope.row.studentName }}
+                    </td>
                   </tr>
                   <tr>
                     <td style="color: green">身份证号</td>
-                    <td style="color:purple;padding-left: 20px;">{{ scope.row.identityNumber }}</td>
+                    <td style="color:purple;padding-left: 20px;">
+                      {{ scope.row.identityNumber }}
+                    </td>
                   </tr>
                   <tr>
                     <td style="color: green">学号</td>
-                    <td style="color:purple;padding-left: 20px;">{{ scope.row.studentCode }}</td>
+                    <td style="color:purple;padding-left: 20px;">
+                      {{ scope.row.studentCode }}
+                    </td>
                   </tr>
                   <tr>
                     <td style="color: green">学习中心名称</td>
-                    <td style="color:purple;padding-left: 20px;">{{ scope.row.orgName }}</td>
+                    <td style="color:purple;padding-left: 20px;">
+                      {{ scope.row.orgName }}
+                    </td>
                   </tr>
                   <tr>
                     <td style="color: green">学习中心编码</td>
-                    <td style="color:purple;padding-left: 20px;">{{ scope.row.orgCode }}</td>
+                    <td style="color:purple;padding-left: 20px;">
+                      {{ scope.row.orgCode }}
+                    </td>
                   </tr>
                   <tr>
                     <td style="color: green">课程名称</td>
-                    <td style="color:purple;padding-left: 20px;">{{ scope.row.courseName }}</td>
+                    <td style="color:purple;padding-left: 20px;">
+                      {{ scope.row.courseName }}
+                    </td>
                   </tr>
                   <tr>
                     <td style="color: green">课程编码</td>
-                    <td style="color:purple;padding-left: 20px;">{{ scope.row.courseCode }}</td>
+                    <td style="color:purple;padding-left: 20px;">
+                      {{ scope.row.courseCode }}
+                    </td>
                   </tr>
                   <tr>
                     <td style="color: green">年级</td>
-                    <td style="color:purple;padding-left: 20px;">{{ scope.row.grade }}</td>
+                    <td style="color:purple;padding-left: 20px;">
+                      {{ scope.row.grade }}
+                    </td>
                   </tr>
                   <tr>
                     <td style="color: green">电话</td>
-                    <td style="color:purple;padding-left: 20px;">{{ scope.row.phone }}</td>
+                    <td style="color:purple;padding-left: 20px;">
+                      {{ scope.row.phone }}
+                    </td>
                   </tr>
                   <tr>
                     <td style="color: green">专业</td>
-                    <td style="color:purple;padding-left: 20px;">{{ scope.row.specialtyName }}</td>
+                    <td style="color:purple;padding-left: 20px;">
+                      {{ scope.row.specialtyName }}
+                    </td>
                   </tr>
                   <tr>
                     <td style="color: green">采集人</td>
-                    <td style="color:purple;padding-left: 20px;">{{ scope.row.infoCollector }}</td>
+                    <td style="color:purple;padding-left: 20px;">
+                      {{ scope.row.infoCollector }}
+                    </td>
                   </tr>
                   <tr>
                     <td style="color: green">考点</td>
-                    <td style="color:purple;padding-left: 20px;">{{ scope.row.examSite }}</td>
+                    <td style="color:purple;padding-left: 20px;">
+                      {{ scope.row.examSite }}
+                    </td>
                   </tr>
                   <tr>
                     <td style="color: green">试卷袋编码</td>
-                    <td style="color:purple;padding-left: 20px;">{{ scope.row.ext1 }}</td>
+                    <td style="color:purple;padding-left: 20px;">
+                      {{ scope.row.ext1 }}
+                    </td>
                   </tr>
                 </div>
 
@@ -553,21 +683,52 @@
               </el-popover>
             </template>
           </el-table-column>
-          <el-table-column prop="studentCode" label="学号" sortable></el-table-column>
-          <el-table-column prop="ext2" label="身份证号" width="120" sortable></el-table-column>
-          <el-table-column prop="orgName" label="学习中心" width="120" sortable></el-table-column>
-          <el-table-column prop="examName" label="考试名称" width="120" sortable></el-table-column>
-          <el-table-column prop="courseName" label="课程名称" width="120" sortable></el-table-column>
-          <el-table-column prop="updateTime" width="155" label="更新时间" sortable></el-table-column>
+          <el-table-column prop="studentCode" label="学号" sortable>
+          </el-table-column>
+          <el-table-column prop="ext2" label="身份证号" width="120" sortable>
+          </el-table-column>
+          <el-table-column prop="orgName" label="学习中心" width="120" sortable>
+          </el-table-column>
+          <el-table-column
+            prop="examName"
+            label="考试名称"
+            width="120"
+            sortable
+          >
+          </el-table-column>
+          <el-table-column
+            prop="courseName"
+            label="课程名称"
+            width="120"
+            sortable
+          >
+          </el-table-column>
+          <el-table-column
+            prop="updateTime"
+            width="155"
+            label="更新时间"
+            sortable
+          >
+          </el-table-column>
           <el-table-column width="50" label="状态">
             <span slot-scope="scope">
               <span v-if="scope.row.enable">
-                <el-tooltip class="item" effect="dark" content="启用" placement="left">
+                <el-tooltip
+                  class="item"
+                  effect="dark"
+                  content="启用"
+                  placement="left"
+                >
                   <i class="el-icon-success" style="color:green;"></i>
                 </el-tooltip>
               </span>
               <span v-else>
-                <el-tooltip class="item" effect="dark" content="禁用" placement="left">
+                <el-tooltip
+                  class="item"
+                  effect="dark"
+                  content="禁用"
+                  placement="left"
+                >
                   <i class="el-icon-error" style="color:red;"></i>
                 </el-tooltip>
               </span>
@@ -584,7 +745,9 @@
                   :disabled="!scope.row.photoPath"
                   icon="el-icon-picture"
                   @click="showPhoto(scope.row)"
-                >查看照片</el-button>
+                >
+                  查看照片
+                </el-button>
                 <el-button
                   v-if="rolePrivileges.update_examStudent"
                   size="mini"
@@ -592,7 +755,9 @@
                   plain
                   icon="el-icon-edit"
                   @click="openUpdateDialog(scope.row)"
-                >编辑</el-button>
+                >
+                  编辑
+                </el-button>
 
                 <el-dropdown
                   style="margin-left: 10px;"
@@ -602,8 +767,7 @@
                   "
                 >
                   <el-button type="primary" plain size="mini">
-                    更多
-                    <i class="el-icon-arrow-down el-icon--right"></i>
+                    更多<i class="el-icon-arrow-down el-icon--right"></i>
                   </el-button>
                   <el-dropdown-menu slot="dropdown">
                     <el-dropdown-item>
@@ -613,8 +777,9 @@
                         type="danger"
                         icon="el-icon-delete"
                         @click="deleteExamStudent(scope.row)"
-                      >删除</el-button>
-                    </el-dropdown-item>
+                        >删除
+                      </el-button></el-dropdown-item
+                    >
                     <el-dropdown-item>
                       <el-button
                         v-if="
@@ -627,7 +792,8 @@
                         plain
                         icon="el-icon-check"
                         @click="enableExamStudent(scope.row)"
-                      >启用</el-button>
+                        >启用
+                      </el-button>
                       <el-button
                         v-else-if="
                           rolePrivileges.change_exam_student_availability
@@ -636,7 +802,8 @@
                         type="danger"
                         icon="el-icon-close"
                         @click="disableExamStudent(scope.row)"
-                      >禁用</el-button>
+                        >禁用
+                      </el-button>
                     </el-dropdown-item>
                   </el-dropdown-menu>
                 </el-dropdown>
@@ -653,7 +820,8 @@
             @size-change="handleSizeChange"
             layout="total, sizes, prev, pager, next, jumper"
             :total="total"
-          ></el-pagination>
+          >
+          </el-pagination>
         </div>
 
         <el-dialog title="错误提示" v-model="errDialog">
@@ -661,13 +829,20 @@
             class="text-danger"
             v-for="errMessage in errMessages"
             :key="errMessage.lineNum"
-          >第{{ errMessage.lineNum }}行:{{ errMessage.msg }}</div>
+          >
+            第{{ errMessage.lineNum }}行:{{ errMessage.msg }}
+          </div>
           <span slot="footer" class="dialog-footer">
             <el-button @click="errDialog = false">确定</el-button>
           </span>
         </el-dialog>
 
-        <el-dialog @close="closePhotoDialog" title="照片" :visible.sync="photoDialog" width="300px">
+        <el-dialog
+          @close="closePhotoDialog"
+          title="照片"
+          :visible.sync="photoDialog"
+          width="300px"
+        >
           <img :src="photo.url" height="100%" width="100%" />
         </el-dialog>
       </div>

+ 8 - 26
src/modules/examwork/view/offlineExam.vue

@@ -104,8 +104,7 @@
                         :key="item.value"
                         :label="item.label"
                         :value="item.value"
-                      >
-                      </el-option>
+                      ></el-option>
                     </el-select>
                   </el-form-item>
                 </el-row>
@@ -135,8 +134,7 @@
                       end-placeholder="结束日期"
                       value-format="yyyy-MM-dd HH:mm:ss"
                       :clearable="false"
-                    >
-                    </el-date-picker>
+                    ></el-date-picker>
                   </el-form-item>
                 </el-row>
                 <el-row>
@@ -162,7 +160,7 @@
                       class="input"
                     >
                       <el-radio label="ORG_BASED">机构特殊设置</el-radio>
-                      <!-- <el-radio label="STUDENT_BASED">学生特殊设置</el-radio> -->
+                      <el-radio label="STUDENT_BASED">学生特殊设置</el-radio>
                     </el-radio-group>
                   </el-form-item>
                 </el-row>
@@ -181,7 +179,7 @@
                 </el-row>
                 <el-row>
                   <el-form-item
-                    label="上传附件"
+                    label="管理端上传附件"
                     :label-width="style.label_width_tab1"
                   >
                     <el-radio-group
@@ -200,11 +198,7 @@
                     label="附件类型"
                     :label-width="style.label_width_tab1"
                   >
-                    <el-checkbox-group
-                      v-model="uploadFileType"
-                      :disabled="this.uploadFileTypeDis()"
-                      class="input"
-                    >
+                    <el-checkbox-group v-model="uploadFileType" class="input">
                       <el-checkbox label="ZIP" key="ZIP"></el-checkbox>
                       <el-checkbox label="PDF" key="PDF"></el-checkbox>
                     </el-checkbox-group>
@@ -262,10 +256,7 @@ let validateExamDatetimeRange = (rule, value, callback) => {
   }
 };
 let validateUploadFileType = (rule, value, callback) => {
-  if (
-    _this.form.properties.CAN_UPLOAD_ATTACHMENT == "true" &&
-    _this.uploadFileType.length == 0
-  ) {
+  if (_this.uploadFileType.length == 0) {
     callback(new Error("请至少勾选一个附件类型"));
   } else {
     callback();
@@ -313,6 +304,7 @@ export default {
         ],
         uploadFileType: [
           {
+            required: true,
             validator: validateUploadFileType,
             trigger: "change"
           }
@@ -420,17 +412,7 @@ export default {
     this.examId = this.$route.params.id;
     this.init();
   },
-  watch: {
-    "form.properties.CAN_UPLOAD_ATTACHMENT": {
-      immediate: false,
-      handler(val) {
-        if (val != "true") {
-          this.uploadFileType = [];
-          this.$refs["uploadFileType"].resetField();
-        }
-      }
-    }
-  }
+  watch: {}
 };
 </script>
 <style scoped>

+ 87 - 50
src/modules/examwork/view/onlineExam.vue

@@ -196,7 +196,7 @@
                       class="input"
                     >
                       <el-radio label="ORG_BASED">机构特殊设置</el-radio>
-                      <!-- <el-radio label="STUDENT_BASED">学生特殊设置</el-radio> -->
+                      <el-radio label="STUDENT_BASED">学生特殊设置</el-radio>
                     </el-radio-group>
                   </el-form-item>
                 </el-row>
@@ -213,6 +213,23 @@
                     ></el-switch>
                   </el-form-item>
                 </el-row>
+                <el-row v-if="this.APP_ENABLED">
+                  <el-form-item
+                    label="开启手机app考试"
+                    :label-width="style.label_width_tab1"
+                  >
+                    <el-switch
+                      v-model="form.properties.APP_EXAM_ENABLED"
+                      @change="appExamEnabledChanged"
+                      on-text="是"
+                      off-text="否"
+                    ></el-switch>
+                  </el-form-item>
+                  <span
+                    style="color: #f56c6c; font-size: 12px; line-height: 44px;"
+                    >开启手机app考试,将不能开启人脸身份检测</span
+                  >
+                </el-row>
               </el-tab-pane>
               <!-- 控制设置 -->
               <el-tab-pane label="控制设置" name="tab2">
@@ -228,9 +245,7 @@
                       auto-complete="off"
                       class="input"
                     >
-                      <template slot="append"
-                        >分钟</template
-                      >
+                      <template slot="append">分钟</template>
                     </el-input>
                   </el-form-item>
                 </el-row>
@@ -246,9 +261,7 @@
                       auto-complete="off"
                       class="input"
                     >
-                      <template slot="append"
-                        >次</template
-                      >
+                      <template slot="append">次</template>
                     </el-input>
                   </el-form-item>
                 </el-row>
@@ -264,9 +277,7 @@
                       auto-complete="off"
                       class="input"
                     >
-                      <template slot="append"
-                        >分钟</template
-                      >
+                      <template slot="append">分钟</template>
                     </el-input>
                   </el-form-item>
                 </el-row>
@@ -282,9 +293,7 @@
                       auto-complete="off"
                       class="input"
                     >
-                      <template slot="append"
-                        >分钟</template
-                      >
+                      <template slot="append">分钟</template>
                     </el-input>
                   </el-form-item>
                 </el-row>
@@ -300,9 +309,7 @@
                       auto-complete="off"
                       class="input"
                     >
-                      <template slot="append"
-                        >次</template
-                      >
+                      <template slot="append">次</template>
                     </el-input>
                   </el-form-item>
                 </el-row>
@@ -460,7 +467,10 @@
                     <el-radio-group
                       @change="faceEnableChange"
                       v-model="form.properties.IS_FACE_ENABLE"
-                      :disabled="this.is_face_enable_diabled"
+                      :disabled="
+                        is_face_enable_disabled ||
+                          form.properties.APP_EXAM_ENABLED == true
+                      "
                       class="input"
                     >
                       <el-radio label="true">是</el-radio>
@@ -510,9 +520,7 @@
                       auto-complete="off"
                       class="input"
                     >
-                      <template slot="append"
-                        >分钟</template
-                      >
+                      <template slot="append">分钟</template>
                     </el-input>
                   </el-form-item>
                 </el-row>
@@ -528,9 +536,7 @@
                       auto-complete="off"
                       class="input"
                     >
-                      <template slot="append"
-                        >%</template
-                      >
+                      <template slot="append">%</template>
                     </el-input>
                   </el-form-item>
                 </el-row>
@@ -546,13 +552,16 @@
                       auto-complete="off"
                       class="input"
                     >
-                      <template slot="append"
-                        >%</template
-                      >
+                      <template slot="append">%</template>
                     </el-input>
                   </el-form-item>
                 </el-row>
-                <el-row v-show="form.properties.IS_FACE_ENABLE == 'true'">
+                <el-row
+                  v-if="
+                    form.properties.APP_EXAM_ENABLED == false &&
+                      form.properties.IS_FACE_ENABLE == 'true'
+                  "
+                >
                   <el-form-item
                     label="开启人脸活体检测"
                     :label-width="style.label_width_tab4"
@@ -567,7 +576,12 @@
                     </el-radio-group>
                   </el-form-item>
                 </el-row>
-                <el-row v-show="form.properties.IS_FACE_VERIFY == 'true'">
+                <el-row
+                  v-if="
+                    form.properties.APP_EXAM_ENABLED == false &&
+                      form.properties.IS_FACE_VERIFY == 'true'
+                  "
+                >
                   <el-form-item
                     label="人脸活体检测开始时间"
                     prop="FACE_VERIFY_START_MINUTE"
@@ -581,13 +595,16 @@
                       auto-complete="off"
                       class="input"
                     >
-                      <template slot="append"
-                        >分钟</template
-                      >
+                      <template slot="append">分钟</template>
                     </el-input>
                   </el-form-item>
                 </el-row>
-                <el-row v-show="form.properties.IS_FACE_VERIFY == 'true'">
+                <el-row
+                  v-if="
+                    form.properties.APP_EXAM_ENABLED == false &&
+                      form.properties.IS_FACE_VERIFY == 'true'
+                  "
+                >
                   <el-form-item
                     label="人脸活体检测结束时间"
                     prop="FACE_VERIFY_END_MINUTE"
@@ -601,15 +618,14 @@
                       auto-complete="off"
                       class="input"
                     >
-                      <template slot="append"
-                        >分钟</template
-                      >
+                      <template slot="append">分钟</template>
                     </el-input>
                   </el-form-item>
                 </el-row>
                 <el-row
-                  v-show="
-                    form.properties.IS_FACE_ENABLE == 'true' &&
+                  v-if="
+                    form.properties.APP_EXAM_ENABLED == false &&
+                      form.properties.IS_FACE_ENABLE == 'true' &&
                       form.IDENTIFICATION_OF_LIVING_BODY_SCHEME == 'S2'
                   "
                 >
@@ -628,8 +644,9 @@
                   </el-form-item>
                 </el-row>
                 <el-row
-                  v-show="
-                    form.IDENTIFICATION_OF_LIVING_BODY_SCHEME == 'S2' &&
+                  v-if="
+                    form.properties.APP_EXAM_ENABLED == false &&
+                      form.IDENTIFICATION_OF_LIVING_BODY_SCHEME == 'S2' &&
                       form.properties.ADD_FACE_VERIFY_OUT_FREEZE_TIME == 'true'
                   "
                 >
@@ -646,15 +663,14 @@
                       auto-complete="off"
                       class="input"
                     >
-                      <template slot="append"
-                        >分钟</template
-                      >
+                      <template slot="append">分钟</template>
                     </el-input>
                   </el-form-item>
                 </el-row>
                 <el-row
-                  v-show="
-                    form.IDENTIFICATION_OF_LIVING_BODY_SCHEME == 'S2' &&
+                  v-if="
+                    form.properties.APP_EXAM_ENABLED == false &&
+                      form.IDENTIFICATION_OF_LIVING_BODY_SCHEME == 'S2' &&
                       form.properties.ADD_FACE_VERIFY_OUT_FREEZE_TIME == 'true'
                   "
                 >
@@ -671,9 +687,7 @@
                       auto-complete="off"
                       class="input"
                     >
-                      <template slot="append"
-                        >分钟</template
-                      >
+                      <template slot="append">分钟</template>
                     </el-input>
                   </el-form-item>
                 </el-row>
@@ -872,6 +886,12 @@ let validateExamReconnectTime = (rule, value, callback) => {
       _this.toActiveName = "tab2";
       _this.activeName = "tab2";
     }
+  } else if (examReconnectTime < 3) {
+    callback(new Error("最小设置值为3"));
+    if (!_this.toActiveName) {
+      _this.toActiveName = "tab2";
+      _this.activeName = "tab2";
+    }
   } else {
     callback();
   }
@@ -1159,9 +1179,10 @@ export default {
       examDatetimeRange: [],
       show_ckeditor: false,
       is_face_verify_diabled: true,
-      is_face_enable_diabled: true,
+      is_face_enable_disabled: true,
       rootOrgWenXinAnswerEnabled: false,
       IDENTIFICATION_OF_LIVING_BODY_SCHEME: "S1",
+      APP_ENABLED: false,
       form: {
         started: false,
         name: "",
@@ -1207,6 +1228,7 @@ export default {
           PUSH_SCORE: "false",
           CHECK_ENVIRONMENT: "false",
           WEIXIN_ANSWER_ENABLED: "false",
+          APP_EXAM_ENABLED: "false",
           ADD_FACE_VERIFY_OUT_FREEZE_TIME: "false",
           OUT_FREEZE_TIME_FACE_VERIFY_START_MINUTE: 10,
           OUT_FREEZE_TIME_FACE_VERIFY_END_MINUTE: 30,
@@ -1343,9 +1365,13 @@ export default {
               this.form.properties.CHECK_ENVIRONMENT === "true";
             this.form.properties.WEIXIN_ANSWER_ENABLED =
               this.form.properties.WEIXIN_ANSWER_ENABLED === "true";
+
             this.form.properties.LIMITED_IF_NO_SPECIAL_SETTINGS =
               this.form.properties.LIMITED_IF_NO_SPECIAL_SETTINGS === "true";
 
+            this.form.properties.APP_EXAM_ENABLED =
+              this.form.properties.APP_EXAM_ENABLED === "true";
+
             this.show_ckeditor = true;
 
             this.checkRootOrgPrivileges();
@@ -1370,9 +1396,9 @@ export default {
           this.form.properties.IS_FACE_CHECK = "false";
           this.form.properties.IS_FACE_VERIFY = "false";
           this.form.properties.ADD_FACE_VERIFY_OUT_FREEZE_TIME = "false";
-          this.is_face_enable_diabled = true;
+          this.is_face_enable_disabled = true;
         } else {
-          this.is_face_enable_diabled = false;
+          this.is_face_enable_disabled = false;
         }
         if (!res.IDENTIFICATION_OF_LIVING_BODY) {
           this.is_face_verify_diabled = true;
@@ -1401,6 +1427,10 @@ export default {
       ) {
         that.form.IDENTIFICATION_OF_LIVING_BODY_SCHEME = res;
       });
+
+      this.getOrgProperty("APP_ENABLED", function(res) {
+        that.APP_ENABLED = res;
+      });
     },
     getOrgProperty: function(propkey, callback) {
       let url =
@@ -1454,6 +1484,13 @@ export default {
     },
     back() {
       this.$router.push({ path: "/examwork/examInfo" });
+    },
+    appExamEnabledChanged(val) {
+      debugger;
+      if (val == true) {
+        this.form.properties.IS_FACE_ENABLE = "false";
+        this.faceEnableChange();
+      }
     }
   },
   created() {

+ 950 - 0
src/modules/examwork/view/onlineHomework.vue

@@ -0,0 +1,950 @@
+<template>
+  <div>
+    <LinkTitlesCustom
+      :currentPaths="['考试管理', '考试信息', '在线作业设置']"
+    />
+    <section class="content">
+      <div class="box box-info">
+        <!-- 正文信息 -->
+        <div class="box-body">
+          <el-form
+            :inline="true"
+            :rules="rules"
+            ref="form"
+            :model="form"
+            inline-message
+            label-position="right"
+          >
+            <div style="margin-bottom: 10px;">
+              <el-button type="primary" size="small" @click="saveExam"
+                >保 存</el-button
+              >
+              <el-button
+                type="primary"
+                size="small"
+                @click="back"
+                icon="el-icon-arrow-left"
+                >返 回</el-button
+              >
+            </div>
+            <el-tabs ref="tabs" type="border-card" v-model="activeName">
+              <!-- 基础信息 -->
+              <el-tab-pane label="基础信息" name="tab1">
+                <el-row v-if="examId != 'add'">
+                  <el-form-item
+                    label="ID"
+                    prop="id"
+                    :label-width="style.label_width_tab1"
+                  >
+                    <el-input
+                      v-model="form.id"
+                      class="input"
+                      :disabled="true"
+                      maxlength="20"
+                    ></el-input>
+                  </el-form-item>
+                </el-row>
+                <el-row v-if="examId != 'add'">
+                  <el-form-item
+                    label="考试编码"
+                    placeholder="请输入考试编码"
+                    prop="code"
+                    :label-width="style.label_width_tab1"
+                  >
+                    <el-input
+                      v-model="form.code"
+                      class="input"
+                      :disabled="true"
+                      maxlength="20"
+                    ></el-input>
+                  </el-form-item>
+                </el-row>
+                <el-row v-else>
+                  <el-form-item
+                    label="考试编码"
+                    placeholder="请输入考试编码"
+                    prop="code"
+                    :label-width="style.label_width_tab1"
+                  >
+                    <el-input
+                      v-model="form.name"
+                      class="input"
+                      :disabled="true"
+                      maxlength="20"
+                    ></el-input>
+                  </el-form-item>
+                </el-row>
+                <el-row>
+                  <el-form-item
+                    label="考试名称"
+                    placeholder="请输入考试名称"
+                    prop="name"
+                    :label-width="style.label_width_tab1"
+                  >
+                    <el-input
+                      v-model="form.name"
+                      class="input"
+                      maxlength="20"
+                    ></el-input>
+                  </el-form-item>
+                </el-row>
+                <el-row>
+                  <el-form-item
+                    label="考试类型"
+                    :label-width="style.label_width_tab1"
+                  >
+                    <el-select
+                      class="input"
+                      :disabled="true"
+                      v-model="form.examType"
+                      placeholder="请选择"
+                    >
+                      <el-option
+                        v-for="item in examTypeList"
+                        :key="item.value"
+                        :label="item.label"
+                        :value="item.value"
+                      ></el-option>
+                    </el-select>
+                  </el-form-item>
+                </el-row>
+                <el-row>
+                  <el-form-item
+                    label="状态"
+                    :label-width="style.label_width_tab1"
+                  >
+                    <el-radio-group v-model="form.enable" class="input">
+                      <el-radio label="true">启用</el-radio>
+                      <el-radio label="false">禁用</el-radio>
+                    </el-radio-group>
+                  </el-form-item>
+                </el-row>
+                <el-row v-if="1 == 2">
+                  <el-form-item
+                    label="是否可以考试"
+                    :label-width="style.label_width_tab1"
+                  >
+                    <el-radio-group v-model="form.examLimit" class="input">
+                      <el-radio label="true">否</el-radio>
+                      <el-radio label="false">是</el-radio>
+                    </el-radio-group>
+                  </el-form-item>
+                </el-row>
+                <el-row>
+                  <el-form-item
+                    label="考试时间"
+                    prop="examDatetimeRange"
+                    :label-width="style.label_width_tab1"
+                  >
+                    <el-date-picker
+                      class="input"
+                      v-model="examDatetimeRange"
+                      type="datetimerange"
+                      range-separator="至"
+                      start-placeholder="开始日期"
+                      end-placeholder="结束日期"
+                      value-format="yyyy-MM-dd HH:mm:ss"
+                      :clearable="false"
+                    ></el-date-picker>
+                  </el-form-item>
+                </el-row>
+                <el-row>
+                  <el-form-item
+                    label="开启环境检测"
+                    :label-width="style.label_width_tab1"
+                  >
+                    <el-switch
+                      v-model="form.properties.CHECK_ENVIRONMENT"
+                      on-text="是"
+                      off-text="否"
+                    ></el-switch>
+                  </el-form-item>
+                </el-row>
+                <el-row>
+                  <el-form-item
+                    label="开放微信小程序作答"
+                    :label-width="style.label_width_tab1"
+                  >
+                    <el-switch
+                      :disabled="!this.rootOrgWenXinAnswerEnabled"
+                      v-model="form.properties.WEIXIN_ANSWER_ENABLED"
+                      on-text="是"
+                      off-text="否"
+                    ></el-switch>
+                  </el-form-item>
+                </el-row>
+                <el-row v-show="false">
+                  <el-form-item
+                    label="开启特殊设置"
+                    :label-width="style.label_width_tab1"
+                  >
+                    <el-switch
+                      v-model="form.specialSettingsEnabled"
+                      on-text="是"
+                      off-text="否"
+                    ></el-switch>
+                  </el-form-item>
+                </el-row>
+                <el-row>
+                  <el-form-item
+                    label="特殊设置方式"
+                    :label-width="style.label_width_tab1"
+                    v-show="form.specialSettingsEnabled"
+                  >
+                    <el-radio-group
+                      v-model="form.specialSettingsType"
+                      class="input"
+                    >
+                      <el-radio label="ORG_BASED">机构特殊设置</el-radio>
+                      <el-radio label="STUDENT_BASED">学生特殊设置</el-radio>
+                    </el-radio-group>
+                  </el-form-item>
+                </el-row>
+                <el-row>
+                  <el-form-item
+                    label="无特殊设置时禁止考试"
+                    :label-width="style.label_width_tab1"
+                    v-show="form.specialSettingsEnabled"
+                  >
+                    <el-switch
+                      v-model="form.properties.LIMITED_IF_NO_SPECIAL_SETTINGS"
+                      on-text="是"
+                      off-text="否"
+                    ></el-switch>
+                  </el-form-item>
+                </el-row>
+              </el-tab-pane>
+              <!-- 控制设置 -->
+              <el-tab-pane label="控制设置" name="tab2">
+                <el-row>
+                  <el-form-item
+                    label="考试时长"
+                    prop="duration"
+                    :label-width="style.label_width_tab2"
+                  >
+                    <el-input
+                      maxlength="5"
+                      v-model.trim.number="form.duration"
+                      auto-complete="off"
+                      class="input"
+                    >
+                      <template slot="append">分钟</template>
+                    </el-input>
+                  </el-form-item>
+                </el-row>
+                <el-row>
+                  <el-form-item
+                    label="考试次数"
+                    prop="examTimes"
+                    :label-width="style.label_width_tab2"
+                  >
+                    <el-input
+                      maxlength="5"
+                      v-model.trim.number="form.examTimes"
+                      auto-complete="off"
+                      class="input"
+                    >
+                      <template slot="append">次</template>
+                    </el-input>
+                  </el-form-item>
+                </el-row>
+                <el-row>
+                  <el-form-item
+                    label="交卷冻结时间"
+                    prop="FREEZE_TIME"
+                    :label-width="style.label_width_tab2"
+                  >
+                    <el-input
+                      maxlength="5"
+                      v-model.trim.number="form.properties.FREEZE_TIME"
+                      auto-complete="off"
+                      class="input"
+                    >
+                      <template slot="append">分钟</template>
+                    </el-input>
+                  </el-form-item>
+                </el-row>
+                <el-row>
+                  <el-form-item
+                    label="断点续考时间"
+                    prop="EXAM_RECONNECT_TIME"
+                    :label-width="style.label_width_tab2"
+                  >
+                    <el-input
+                      maxlength="5"
+                      v-model.trim.number="form.properties.EXAM_RECONNECT_TIME"
+                      auto-complete="off"
+                      class="input"
+                    >
+                      <template slot="append">分钟</template>
+                    </el-input>
+                  </el-form-item>
+                </el-row>
+                <el-row>
+                  <el-form-item
+                    label="断点续考次数"
+                    prop="MAX_INTERRUPT_NUM"
+                    :label-width="style.label_width_tab2"
+                  >
+                    <el-input
+                      maxlength="5"
+                      v-model.trim.number="form.properties.MAX_INTERRUPT_NUM"
+                      auto-complete="off"
+                      class="input"
+                    >
+                      <template slot="append">次</template>
+                    </el-input>
+                  </el-form-item>
+                </el-row>
+              </el-tab-pane>
+              <el-tab-pane label="显示设置" name="tab3">
+                <el-row v-if="show_ckeditor">
+                  <el-form-item
+                    label="考前说明"
+                    :label-width="style.label_width_tab3"
+                  >
+                    <ckeditor
+                      v-model="form.properties.BEFORE_EXAM_REMARK"
+                    ></ckeditor>
+                  </el-form-item>
+                </el-row>
+                <el-row v-if="show_ckeditor">
+                  <el-form-item
+                    label="考后说明"
+                    :label-width="style.label_width_tab3"
+                  >
+                    <ckeditor
+                      v-model="form.properties.AFTER_EXAM_REMARK"
+                    ></ckeditor>
+                  </el-form-item>
+                </el-row>
+                <el-row>
+                  <el-form-item
+                    label="展示作弊说明"
+                    :label-width="style.label_width_tab3"
+                  >
+                    <el-radio-group
+                      v-model="form.properties.SHOW_CHEATING_REMARK"
+                      class="input"
+                    >
+                      <el-radio label="true">开启</el-radio>
+                      <el-radio label="false">关闭</el-radio>
+                    </el-radio-group>
+                  </el-form-item>
+                </el-row>
+                <el-row v-if="show_ckeditor">
+                  <el-form-item
+                    label="作弊说明"
+                    :label-width="style.label_width_tab3"
+                  >
+                    <ckeditor
+                      v-model="form.properties.CHEATING_REMARK"
+                    ></ckeditor>
+                  </el-form-item>
+                </el-row>
+                <el-row>
+                  <el-form-item
+                    label="单选题补充说明"
+                    :label-width="style.label_width_tab3"
+                  >
+                    <el-input
+                      maxlength="20"
+                      :disabled="!form.properties.SINGLE_EDIT"
+                      v-model="form.properties.SINGLE_ANSWER_REMARK"
+                      auto-complete="off"
+                      class="input"
+                    ></el-input>
+                  </el-form-item>
+                  <el-form-item label>
+                    <el-switch
+                      v-model="form.properties.SINGLE_EDIT"
+                      on-text="启用"
+                      off-text="禁用"
+                    ></el-switch>
+                  </el-form-item>
+                </el-row>
+                <el-row>
+                  <el-form-item
+                    label="多选题补充说明"
+                    :label-width="style.label_width_tab3"
+                  >
+                    <el-input
+                      maxlength="20"
+                      :disabled="!form.properties.MUTIPLE_EDIT"
+                      v-model="form.properties.MUTIPLE_ANSWER_REMARK"
+                      auto-complete="off"
+                      class="input"
+                    ></el-input>
+                  </el-form-item>
+                  <el-form-item label>
+                    <el-switch
+                      v-model="form.properties.MUTIPLE_EDIT"
+                      on-text="启用"
+                      off-text="禁用"
+                    ></el-switch>
+                  </el-form-item>
+                </el-row>
+                <el-row>
+                  <el-form-item
+                    label="判断题补充说明"
+                    :label-width="style.label_width_tab3"
+                  >
+                    <el-input
+                      maxlength="20"
+                      :disabled="!form.properties.BOOL_EDIT"
+                      v-model="form.properties.BOOL_ANSWER_REMARK"
+                      class="input"
+                      auto-complete="off"
+                    ></el-input>
+                  </el-form-item>
+                  <el-form-item label>
+                    <el-switch
+                      v-model="form.properties.BOOL_EDIT"
+                      on-text="启用"
+                      off-text="禁用"
+                    ></el-switch>
+                  </el-form-item>
+                </el-row>
+                <el-row>
+                  <el-form-item
+                    label="填空题补充说明"
+                    :label-width="style.label_width_tab3"
+                  >
+                    <el-input
+                      maxlength="20"
+                      :disabled="!form.properties.FILL_BLANK_EDIT"
+                      v-model="form.properties.FILL_BLANK_REMARK"
+                      class="input"
+                      auto-complete="off"
+                    ></el-input>
+                  </el-form-item>
+                  <el-form-item label>
+                    <el-switch
+                      v-model="form.properties.FILL_BLANK_EDIT"
+                      on-text="启用"
+                      off-text="禁用"
+                    ></el-switch>
+                  </el-form-item>
+                </el-row>
+                <el-row>
+                  <el-form-item
+                    label="客观题成绩显示"
+                    :label-width="style.label_width_tab3"
+                  >
+                    <el-radio-group
+                      v-model="form.properties.IS_OBJ_SCORE_VIEW"
+                      class="input"
+                    >
+                      <el-radio label="true">开启</el-radio>
+                      <el-radio label="false">关闭</el-radio>
+                    </el-radio-group>
+                  </el-form-item>
+                </el-row>
+              </el-tab-pane>
+              <el-tab-pane label="阅卷设置" name="tab5">
+                <el-row>
+                  <el-form-item
+                    label="阅卷方式"
+                    :label-width="style.label_width_tab5"
+                  >
+                    <el-radio-group
+                      :disabled="form.started"
+                      v-model="form.properties.MARKING_TYPE"
+                      class="input"
+                    >
+                      <el-radio label="ALL">全部评阅</el-radio>
+                      <el-radio label="OBJECT_SCORE_MAX">客观分最高</el-radio>
+                      <el-radio label="LAST_SUBMIT">最后一次提交</el-radio>
+                    </el-radio-group>
+                  </el-form-item>
+                </el-row>
+              </el-tab-pane>
+              <el-tab-pane label="网络设置" name="tab6">
+                <el-row>
+                  <el-form-item
+                    label="IP限制"
+                    :label-width="style.label_width_tab6"
+                  >
+                    <el-radio-group v-model="form.properties.IP_LIMIT">
+                      <el-radio label="true">开启</el-radio>
+                      <el-radio label="false">关闭</el-radio>
+                    </el-radio-group>
+                  </el-form-item>
+                </el-row>
+                <el-row>
+                  <el-form-item
+                    label="IP段( *表示任意 )"
+                    :label-width="style.label_width_tab6"
+                  >
+                    <el-input
+                      maxlength="2000"
+                      v-model="form.properties.IP_ADDRESSES"
+                      class="input"
+                      type="textarea"
+                      rows="6"
+                    ></el-input>
+                  </el-form-item>
+                </el-row>
+              </el-tab-pane>
+              <el-tab-pane label="其它" name="tab7">
+                <el-row>
+                  <el-form-item
+                    label="是否推送成绩"
+                    :label-width="style.label_width_tab7"
+                  >
+                    <el-radio-group v-model="form.properties.PUSH_SCORE">
+                      <el-radio label="true">是</el-radio>
+                      <el-radio label="false">否</el-radio>
+                    </el-radio-group>
+                  </el-form-item>
+                </el-row>
+              </el-tab-pane>
+            </el-tabs>
+          </el-form>
+        </div>
+      </div>
+    </section>
+  </div>
+</template>
+
+<script>
+import { mapState } from "vuex";
+import { EXAM_TYPE, EXAM_WORK_API, CORE_API } from "@/constants/constants.js";
+import moment from "moment";
+import ckeditor from "@/components/ckeditor.vue";
+import LinkTitlesCustom from "@/components/LinkTitlesCustom.vue";
+let _this = null;
+
+let validateCode = (rule, value, callback) => {
+  if (_this.examId == "add") {
+    _this.form.code = _this.form.name;
+  }
+  let code = _this.form.code;
+  if (code == "") {
+    callback(new Error("请输入考试编码"));
+    if (!_this.toActiveName) {
+      _this.toActiveName = "tab1";
+      _this.activeName = "tab1";
+    }
+  } else {
+    callback();
+  }
+};
+
+let validateName = (rule, value, callback) => {
+  let name = _this.form.name;
+  if (name == "") {
+    callback(new Error("请输入考试名称"));
+    if (!_this.toActiveName) {
+      _this.toActiveName = "tab1";
+      _this.activeName = "tab1";
+    }
+  } else {
+    callback();
+  }
+};
+
+let validateExamDatetimeRange = (rule, value, callback) => {
+  let examDatetimeRange = _this.examDatetimeRange;
+  if (!examDatetimeRange) {
+    callback(new Error("请输入考试时间"));
+    if (!_this.toActiveName) {
+      _this.toActiveName = "tab1";
+      _this.activeName = "tab1";
+    }
+  } else {
+    callback();
+  }
+};
+
+let validateDuration = (rule, value, callback) => {
+  let duration = _this.form.duration;
+  if (duration === "") {
+    callback(new Error("请输入考试时长"));
+    if (!_this.toActiveName) {
+      _this.toActiveName = "tab2";
+      _this.activeName = "tab2";
+    }
+  } else if (!duration.toString().match(/^[1-9]\d*|0$/)) {
+    callback(new Error("只能是非负整数"));
+    if (!_this.toActiveName) {
+      _this.toActiveName = "tab2";
+      _this.activeName = "tab2";
+    }
+  } else {
+    callback();
+  }
+};
+
+let validateExamTimes = (rule, value, callback) => {
+  let examTimes = _this.form.examTimes;
+  if (examTimes === "") {
+    callback(new Error("请输入考试次数"));
+    if (!_this.toActiveName) {
+      _this.toActiveName = "tab2";
+      _this.activeName = "tab2";
+    }
+  } else if (!examTimes.toString().match(/^[1-9]\d*$/)) {
+    callback(new Error("只能是正整数"));
+    if (!_this.toActiveName) {
+      _this.toActiveName = "tab2";
+      _this.activeName = "tab2";
+    }
+  } else {
+    callback();
+  }
+};
+
+let validateFreezeTime = (rule, value, callback) => {
+  let freezeTime = _this.form.properties.FREEZE_TIME;
+  let duration = _this.form.duration;
+  if (freezeTime === "") {
+    callback(new Error("请输入交卷冻结时长"));
+    if (!_this.toActiveName) {
+      _this.toActiveName = "tab2";
+      _this.activeName = "tab2";
+    }
+  } else if (!freezeTime.toString().match(/^[1-9]\d*|0$/)) {
+    callback(new Error("只能是非负整数"));
+    if (!_this.toActiveName) {
+      _this.toActiveName = "tab2";
+      _this.activeName = "tab2";
+    }
+  } else if (duration != "" && parseInt(freezeTime) > parseInt(duration)) {
+    callback(new Error("交卷冻结时长不能大于考试时长"));
+    if (!_this.toActiveName) {
+      _this.toActiveName = "tab2";
+      _this.activeName = "tab2";
+    }
+  } else {
+    callback();
+  }
+};
+
+let validateExamReconnectTime = (rule, value, callback) => {
+  let examReconnectTime = _this.form.properties.EXAM_RECONNECT_TIME;
+  if (examReconnectTime === "") {
+    callback(new Error("请输入断点续考时间"));
+    if (!_this.toActiveName) {
+      _this.toActiveName = "tab2";
+      _this.activeName = "tab2";
+    }
+  } else if (!examReconnectTime.toString().match(/^[1-9]\d*$/)) {
+    callback(new Error("只能是正整数"));
+    if (!_this.toActiveName) {
+      _this.toActiveName = "tab2";
+      _this.activeName = "tab2";
+    }
+  } else if (examReconnectTime < 3) {
+    callback(new Error("最小设置值为3"));
+    if (!_this.toActiveName) {
+      _this.toActiveName = "tab2";
+      _this.activeName = "tab2";
+    }
+  } else {
+    callback();
+  }
+};
+
+let validateMaxInterruptNum = (rule, value, callback) => {
+  let examReconnectTime = _this.form.properties.MAX_INTERRUPT_NUM;
+  if (examReconnectTime === "") {
+    callback();
+  } else if (!examReconnectTime.toString().match(/^[0-9]\d*$/)) {
+    callback(new Error("只能是非负整数"));
+    if (!_this.toActiveName) {
+      _this.toActiveName = "tab2";
+      _this.activeName = "tab2";
+    }
+  } else {
+    callback();
+  }
+};
+
+export default {
+  components: {
+    ckeditor,
+    LinkTitlesCustom
+  },
+  data() {
+    return {
+      style: {
+        label_width_tab1: "160px",
+        label_width_tab2: "110px",
+        label_width_tab3: "120px",
+        label_width_tab4: "170px",
+        label_width_tab5: "80px",
+        label_width_tab6: "120px",
+        label_width_tab7: "150px"
+      },
+      activeName: "tab1",
+      toActiveName: null,
+      examDatetimeRange: [],
+      show_ckeditor: false,
+      is_face_verify_diabled: true,
+      is_face_enable_diabled: true,
+      rootOrgWenXinAnswerEnabled: false,
+      IDENTIFICATION_OF_LIVING_BODY_SCHEME: "S1",
+      form: {
+        started: false,
+        name: "",
+        code: "",
+        examType: "ONLINE_HOMEWORK",
+        examTimes: 1,
+        beginTime: null,
+        endTime: null,
+        duration: 120,
+        enable: "true",
+        examLimit: "false",
+        specialSettingsEnabled: false,
+        specialSettingsType: "ORG_BASED",
+        properties: {
+          IS_OBJ_SCORE_VIEW: "true",
+          IS_STRANGER_ENABLE: "false",
+          MAX_INTERRUPT_NUM: "",
+          EXAM_RECONNECT_TIME: 30,
+          FREEZE_TIME: 0,
+          BEFORE_EXAM_REMARK: "",
+          AFTER_EXAM_REMARK: "",
+          SHOW_CHEATING_REMARK: "true",
+          CHEATING_REMARK: "",
+          SINGLE_EDIT: "false",
+          MUTIPLE_EDIT: "false",
+          BOOL_EDIT: "false",
+          FILL_BLANK_EDIT: "false",
+          SINGLE_ANSWER_REMARK: "",
+          MUTIPLE_ANSWER_REMARK: "",
+          FILL_BLANK_REMARK: "",
+          BOOL_ANSWER_REMARK: "",
+          IS_FACE_ENABLE: "false",
+          IS_FACE_CHECK: "false",
+          SNAPSHOT_INTERVAL: 30,
+          WARN_THRESHOLD: 50,
+          MARKING_TYPE: "ALL",
+          IP_LIMIT: "false",
+          IP_ADDRESSES: null,
+          LIVING_WARN_THRESHOLD: 50,
+          IS_FACE_VERIFY: "false",
+          FACE_VERIFY_START_MINUTE: 5,
+          FACE_VERIFY_END_MINUTE: 10,
+          PUSH_SCORE: "false",
+          CHECK_ENVIRONMENT: "false",
+          WEIXIN_ANSWER_ENABLED: "false",
+          ADD_FACE_VERIFY_OUT_FREEZE_TIME: "false",
+          OUT_FREEZE_TIME_FACE_VERIFY_START_MINUTE: 10,
+          OUT_FREEZE_TIME_FACE_VERIFY_END_MINUTE: 30,
+          LIMITED_IF_NO_SPECIAL_SETTINGS: "false"
+        }
+      },
+      examTypeList: EXAM_TYPE,
+      examId: "",
+      rootOrgId: null,
+      rules: {
+        code: [{ required: true, validator: validateCode, trigger: "blur" }],
+        name: [{ required: true, validator: validateName, trigger: "blur" }],
+        examDatetimeRange: [
+          {
+            required: true,
+            validator: validateExamDatetimeRange,
+            trigger: "blur"
+          }
+        ],
+        duration: [
+          { required: true, validator: validateDuration, trigger: "blur" }
+        ],
+        examTimes: [
+          { required: true, validator: validateExamTimes, trigger: "blur" }
+        ],
+        FREEZE_TIME: [
+          { required: true, validator: validateFreezeTime, trigger: "blur" }
+        ],
+        EXAM_RECONNECT_TIME: [
+          {
+            required: true,
+            validator: validateExamReconnectTime,
+            trigger: "blur"
+          }
+        ],
+        MAX_INTERRUPT_NUM: [
+          {
+            required: false,
+            validator: validateMaxInterruptNum,
+            trigger: "blur"
+          }
+        ]
+      }
+    };
+  },
+
+  methods: {
+    faceEnableChange() {
+      if (this.form.properties.IS_FACE_ENABLE == "false") {
+        this.form.properties.IS_STRANGER_ENABLE = "false";
+        this.form.properties.IS_FACE_CHECK = "false";
+        this.form.properties.IS_FACE_VERIFY = "false";
+        this.form.properties.ADD_FACE_VERIFY_OUT_FREEZE_TIME = "false";
+      }
+    },
+    init() {
+      if (this.examId != "add") {
+        let url = EXAM_WORK_API + "/exam/" + this.examId;
+        this.$httpWithMsg.get(url).then(response => {
+          let body = response.data;
+          this.rootOrgId = body.rootOrgId;
+          body.properties = this.form.properties;
+          this.form = Object.assign(this.form, response.data);
+          this.form.enable = this.form.enable ? "true" : "false";
+          this.form.examLimit = this.form.examLimit ? "true" : "false";
+          this.examDatetimeRange = [this.form.beginTime, this.form.endTime];
+          console.log("getOnlineHomework(); form: ", this.form);
+
+          let url = EXAM_WORK_API + "/exam/allProperties/" + this.examId;
+          this.$httpWithMsg.get(url).then(response => {
+            this.form.properties = Object.assign(
+              this.form.properties,
+              response.data
+            );
+
+            this.form.properties.SINGLE_EDIT =
+              this.form.properties.SINGLE_EDIT === "true";
+            this.form.properties.MUTIPLE_EDIT =
+              this.form.properties.MUTIPLE_EDIT === "true";
+            this.form.properties.BOOL_EDIT =
+              this.form.properties.BOOL_EDIT === "true";
+            this.form.properties.FILL_BLANK_EDIT =
+              this.form.properties.FILL_BLANK_EDIT === "true";
+            this.form.properties.CHECK_ENVIRONMENT =
+              this.form.properties.CHECK_ENVIRONMENT === "true";
+            this.form.properties.WEIXIN_ANSWER_ENABLED =
+              this.form.properties.WEIXIN_ANSWER_ENABLED === "true";
+            this.form.properties.LIMITED_IF_NO_SPECIAL_SETTINGS =
+              this.form.properties.LIMITED_IF_NO_SPECIAL_SETTINGS === "true";
+
+            this.show_ckeditor = true;
+
+            this.checkRootOrgPrivileges();
+          });
+        });
+      } else {
+        let now = moment().format("YYYY-MM-DD HH:mm:ss");
+        this.examDatetimeRange = [now, now];
+        this.show_ckeditor = true;
+        this.checkRootOrgPrivileges();
+      }
+    },
+    checkRootOrgPrivileges: function() {
+      let url =
+        CORE_API +
+        "/rolePrivilege/checkRootOrgPrivileges?privilegeCodes=FACE_CHECK,IDENTIFICATION_OF_LIVING_BODY";
+      this.$httpWithMsg.post(url).then(response => {
+        let res = response.data;
+        if (!res.FACE_CHECK) {
+          this.form.properties.IS_FACE_ENABLE = "false";
+          this.form.properties.IS_STRANGER_ENABLE = "false";
+          this.form.properties.IS_FACE_CHECK = "false";
+          this.form.properties.IS_FACE_VERIFY = "false";
+          this.form.properties.ADD_FACE_VERIFY_OUT_FREEZE_TIME = "false";
+          this.is_face_enable_diabled = true;
+        } else {
+          this.is_face_enable_diabled = false;
+        }
+        if (!res.IDENTIFICATION_OF_LIVING_BODY) {
+          this.is_face_verify_diabled = true;
+          this.form.properties.IS_FACE_VERIFY = "false";
+          this.form.properties.ADD_FACE_VERIFY_OUT_FREEZE_TIME = "false";
+        } else {
+          this.is_face_verify_diabled = false;
+        }
+      });
+
+      let url2 =
+        CORE_API +
+        "/org/property/" +
+        this.user.rootOrgId +
+        "/WEIXIN_ANSWER_ENABLED";
+      this.$httpWithMsg.get(url2).then(response => {
+        let res = response.data;
+        this.rootOrgWenXinAnswerEnabled = res == true;
+        if (!this.rootOrgWenXinAnswerEnabled) {
+          this.form.properties.WEIXIN_ANSWER_ENABLED = false;
+        }
+      });
+      let that = this;
+      this.getOrgProperty("IDENTIFICATION_OF_LIVING_BODY_SCHEME", function(
+        res
+      ) {
+        that.form.IDENTIFICATION_OF_LIVING_BODY_SCHEME = res;
+      });
+    },
+    getOrgProperty: function(propkey, callback) {
+      let url =
+        CORE_API + "/org/property/" + this.user.rootOrgId + "/" + propkey;
+      this.$httpWithMsg.get(url).then(response => {
+        let res = response.data;
+        callback(res);
+      });
+    },
+    saveExam: function() {
+      this.toActiveName = null;
+      this.form.beginTime = this.examDatetimeRange[0];
+      this.form.endTime = this.examDatetimeRange[1];
+      console.log(this.form);
+      let url = EXAM_WORK_API + "/exam";
+      this.$refs.form.validate(valid => {
+        if (valid) {
+          if (this.examId != "add") {
+            this.$httpWithMsg.put(url, this.form).then(response => {
+              if (200 != response.status) {
+                this.$notify({
+                  type: "error",
+                  message: response.body.desc
+                });
+                return;
+              }
+              this.$notify({
+                type: "success",
+                message: "保存成功"
+              });
+            });
+          } else {
+            this.form.code = this.form.name;
+            this.$httpWithMsg.post(url, this.form).then(response => {
+              console.log(response);
+              this.$notify({
+                type: "success",
+                message: "新增成功"
+              });
+              this.examId = response.data.id;
+              this.form.id = this.examId;
+              this.$router.push({
+                path: "/examwork/onlineHomework/" + response.data.id
+              });
+            });
+          }
+        } else {
+          return false;
+        }
+      });
+    },
+    back() {
+      this.$router.push({ path: "/examwork/examInfo" });
+    }
+  },
+  created() {
+    _this = this;
+    this.examId = this.$route.params.id;
+    this.init();
+  },
+  computed: {
+    ...mapState({ user: state => state.user })
+  }
+};
+</script>
+<style scoped>
+.input {
+  width: 440px;
+}
+.input >>> .el-input__inner {
+  -webkit-appearance: button;
+}
+</style>

+ 842 - 0
src/modules/examwork/view/onlineHomeworkOrgSettings.vue

@@ -0,0 +1,842 @@
+<template>
+  <div>
+    <LinkTitlesCustom
+      :currentPaths="['考试管理', '考试信息', '学习中心设置']"
+    />
+    <section class="content">
+      <div class="box-body">
+        <el-form
+          :model="formSearch"
+          :inline="true"
+          label-position="right"
+          label-width="80px"
+        >
+          <el-form-item label="学习中心">
+            <el-select
+              class="select"
+              :remote-method="getOrgList4Search"
+              :loading="loadingOrg4Search"
+              remote
+              filterable
+              clearable
+              v-model="formSearch.orgId"
+              placeholder="请选择"
+            >
+              <el-option
+                v-for="item in orgList4Search"
+                :label="item.name"
+                :value="item.id"
+                :key="item.id"
+              >
+              </el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item>
+            <el-button
+              size="small"
+              type="primary"
+              icon="el-icon-search"
+              @click="resetPageAndSearch"
+              >查询
+            </el-button>
+            <el-button
+              size="small"
+              type="primary"
+              icon="el-icon-plus"
+              @click="showAddOrgSetting"
+              >新增
+            </el-button>
+            <el-button
+              size="small"
+              type="primary"
+              icon="el-icon-download"
+              @click="exportOrgSettings"
+            >
+              导出
+            </el-button>
+            <el-button
+              size="small"
+              type="primary"
+              icon="el-icon-upload2"
+              @click="importOrgSettings"
+            >
+              导入
+            </el-button>
+            <el-button size="small" type="primary" @click="back"
+              >返 回
+            </el-button>
+          </el-form-item>
+        </el-form>
+
+        <div class="block-seperator"></div>
+        <span>批量操作:</span>
+
+        <el-button
+          size="small"
+          type="success"
+          icon="el-icon-check"
+          :disabled="noBatchSelected"
+          @click="batchNotLimit"
+          >开考
+        </el-button>
+        <el-button
+          size="small"
+          type="danger"
+          icon="el-icon-close"
+          :disabled="noBatchSelected"
+          @click="batchLimit"
+          >禁考
+        </el-button>
+        <el-button
+          size="small"
+          type="danger"
+          icon="el-icon-delete"
+          :disabled="noBatchSelected"
+          @click="batchDelete"
+          >删除
+        </el-button>
+        <el-button
+          size="small"
+          type="danger"
+          icon="el-icon-delete"
+          :disabled="total == 0"
+          @click="deleteAll"
+          >删除所有
+        </el-button>
+
+        <div style="width: 100%;margin-bottom: 10px;"></div>
+
+        <!-- 页面列表 -->
+        <el-table
+          :data="tableData"
+          border
+          style="width: 100%;text-align:center;"
+          @selection-change="selectChange"
+          v-loading="loading4FormSearch"
+        >
+          <el-table-column type="selection" width="40"></el-table-column>
+          <el-table-column prop="id" width="80" label="ID"></el-table-column>
+          <el-table-column
+            prop="orgCode"
+            label="学习中心代码"
+            sortable
+          ></el-table-column>
+          <el-table-column
+            prop="orgName"
+            label="学习中心名称"
+            sortable
+          ></el-table-column>
+          <el-table-column
+            prop="beginTime"
+            width="155"
+            label="开始时间"
+            sortable
+          >
+          </el-table-column>
+          <el-table-column prop="endTime" width="155" label="结束时间" sortable>
+          </el-table-column>
+          <el-table-column width="80" label="开考状态">
+            <span slot-scope="scope">
+              <span v-if="!scope.row.examLimit">
+                <el-tooltip
+                  class="item"
+                  effect="dark"
+                  content="开考"
+                  placement="left"
+                >
+                  <i class="el-icon-success" style="color:green;"></i>
+                </el-tooltip>
+              </span>
+              <span v-else>
+                <el-tooltip
+                  class="item"
+                  effect="dark"
+                  content="禁考"
+                  placement="left"
+                >
+                  <i class="el-icon-error" style="color:red;"></i>
+                </el-tooltip>
+              </span>
+            </span>
+          </el-table-column>
+          <el-table-column prop="updateTime" width="155" label="更新时间">
+          </el-table-column>
+          <el-table-column label="操作" width="200">
+            <template slot-scope="scope">
+              <div>
+                <el-button
+                  v-if="scope.row.examLimit"
+                  size="mini"
+                  type="primary"
+                  plain
+                  icon="el-icon-edit"
+                  @click="updateExamLimit(scope.row)"
+                >
+                  开考
+                </el-button>
+                <el-button
+                  v-else
+                  size="mini"
+                  type="danger"
+                  icon="el-icon-edit"
+                  @click="updateExamLimit(scope.row)"
+                >
+                  禁考
+                </el-button>
+                <el-button
+                  size="mini"
+                  type="primary"
+                  plain
+                  icon="el-icon-edit"
+                  @click="showUpdateOrgSetting(scope.row)"
+                >
+                  编辑
+                </el-button>
+              </div>
+            </template>
+          </el-table-column>
+        </el-table>
+        <div class="page pull-right">
+          <el-pagination
+            @current-change="handleCurrentChange"
+            :current-page="currentPage"
+            :page-size="pageSize"
+            :page-sizes="[10, 20, 50, 100, 200, 300]"
+            @size-change="handleSizeChange"
+            layout="total, sizes, prev, pager, next, jumper"
+            :total="total"
+          >
+          </el-pagination>
+        </div>
+
+        <!-- 新增 -->
+        <el-dialog
+          title="新增学习中心考试设置"
+          size="tiny"
+          :visible.sync="addOrgSettingDialog"
+        >
+          <el-form
+            :model="orgSetting"
+            :rules="orgSettingRules"
+            ref="addOrgSettingForm"
+            label-position="right"
+            :inline="true"
+            inline-message
+          >
+            <el-row>
+              <el-form-item label="学习中心" prop="orgId" label-width="120px">
+                <el-select
+                  class="select"
+                  :remote-method="getOrgList4InsertOrUpdate"
+                  :loading="loadingOrg4InsertOrUpdate"
+                  remote
+                  filterable
+                  clearable
+                  v-model="orgSetting.orgId"
+                  placeholder="请选择"
+                >
+                  <el-option
+                    v-for="item in orgList4InsertOrUpdate"
+                    :label="item.name"
+                    :value="item.id"
+                    :key="item.id"
+                  >
+                  </el-option>
+                </el-select>
+              </el-form-item>
+            </el-row>
+            <el-row>
+              <el-form-item
+                label="考试时间"
+                prop="orgSettingDatetimeRange"
+                label-width="120px"
+              >
+                <el-date-picker
+                  v-model="orgSettingDatetimeRange"
+                  type="datetimerange"
+                  range-separator="至"
+                  start-placeholder="开始日期"
+                  end-placeholder="结束日期"
+                  value-format="yyyy-MM-dd HH:mm:ss"
+                >
+                </el-date-picker>
+              </el-form-item>
+            </el-row>
+            <el-row>
+              <el-form-item label="开考状态" label-width="120px">
+                <el-radio-group v-model="orgSetting.examLimit" class="input">
+                  <el-radio label="true">禁考</el-radio>
+                  <el-radio label="false">开考</el-radio>
+                </el-radio-group>
+              </el-form-item>
+            </el-row>
+            <el-row>
+              <div style="text-align:center;">
+                <el-button type="primary" @click="addOrgSetting"
+                  >确 定
+                </el-button>
+                <el-button @click="addOrgSettingDialog = false"
+                  >取 消
+                </el-button>
+              </div>
+            </el-row>
+          </el-form>
+        </el-dialog>
+
+        <!-- 修改 -->
+        <el-dialog
+          title="修改学习中心考试设置"
+          size="tiny"
+          :visible.sync="updateOrgSettingDialog"
+        >
+          <el-form
+            :model="orgSetting"
+            :rules="orgSettingRules"
+            ref="updateOrgSettingForm"
+            label-position="right"
+            :inline="true"
+            inline-message
+          >
+            <el-row>
+              <el-form-item label="学习中心" prop="orgId" label-width="120px">
+                <el-select
+                  class="select"
+                  :remote-method="getOrgList4InsertOrUpdate"
+                  :loading="loadingOrg4InsertOrUpdate"
+                  remote
+                  filterable
+                  clearable
+                  :disabled="true"
+                  v-model="orgSetting.orgId"
+                  placeholder="请选择"
+                >
+                  <el-option
+                    v-for="item in orgList4InsertOrUpdate"
+                    :label="item.name"
+                    :value="item.id"
+                    :key="item.id"
+                  >
+                  </el-option>
+                </el-select>
+              </el-form-item>
+            </el-row>
+            <el-row>
+              <el-form-item
+                label="考试时间"
+                prop="orgSettingDatetimeRange"
+                label-width="120px"
+              >
+                <el-date-picker
+                  v-model="orgSettingDatetimeRange"
+                  type="datetimerange"
+                  range-separator="至"
+                  start-placeholder="开始日期"
+                  end-placeholder="结束日期"
+                  value-format="yyyy-MM-dd HH:mm:ss"
+                >
+                </el-date-picker>
+              </el-form-item>
+            </el-row>
+            <el-row>
+              <el-form-item label="开考状态" label-width="120px">
+                <el-radio-group v-model="orgSetting.examLimit" class="input">
+                  <el-radio label="true">禁考</el-radio>
+                  <el-radio label="false">开考</el-radio>
+                </el-radio-group>
+              </el-form-item>
+            </el-row>
+            <el-row>
+              <div style="margin-left:30%">
+                <el-button type="primary" @click="updateOrgSetting"
+                  >确 定
+                </el-button>
+                <el-button @click="updateOrgSettingDialog = false"
+                  >取 消
+                </el-button>
+              </div>
+            </el-row>
+          </el-form>
+        </el-dialog>
+
+        <!-- 导入弹窗 -->
+        <el-dialog
+          title="学习中心设置导入"
+          size="tiny"
+          width="500px"
+          :visible.sync="orgSettingsImportDialog"
+        >
+          <el-form :model="orgSettingsImportForm" ref="orgSettingsImportForm">
+            <el-row>
+              <el-form-item style="margin-left:30px">
+                <el-upload
+                  ref="upload"
+                  accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
+                  :action="uploadAction"
+                  :headers="uploadHeaders"
+                  :data="uploadData"
+                  :on-success="uploadSuccess"
+                  :on-error="uploadError"
+                  :file-list="fileList"
+                  :auto-upload="false"
+                  :multiple="false"
+                >
+                  <el-button
+                    size="small"
+                    slot="trigger"
+                    type="primary"
+                    icon="el-icon-search"
+                    >选择文件
+                  </el-button>
+                  <el-button
+                    size="small"
+                    style="margin-left:10px;"
+                    type="primary"
+                    @click="submitUpload"
+                    icon="el-icon-check"
+                    >确认上传
+                  </el-button>
+                  <el-button
+                    size="small"
+                    style="margin-left: 10px;"
+                    type="primary"
+                    @click="removeFile"
+                    icon="el-icon-refresh"
+                    >清空文件
+                  </el-button>
+                  <div slot="tip" class="el-upload__tip">只能上传xlsx文件</div>
+                </el-upload>
+              </el-form-item>
+            </el-row>
+          </el-form>
+        </el-dialog>
+
+        <!-- 导入错误信息列表 -->
+        <el-dialog title="错误提示" :visible.sync="errDialog">
+          <div
+            class="text-danger"
+            v-for="errMessage in errMessages"
+            :key="errMessage.lineNum"
+          >
+            第{{ errMessage.lineNum }}行:{{ errMessage.msg }}
+          </div>
+          <span slot="footer" class="dialog-footer">
+            <el-button @click="errDialog = false">确定</el-button>
+          </span>
+        </el-dialog>
+        <!--END-->
+      </div>
+    </section>
+  </div>
+</template>
+
+<script>
+import { CORE_API, EXAM_WORK_API } from "@/constants/constants.js";
+import LinkTitlesCustom from "@/components/LinkTitlesCustom.vue";
+import { mapState } from "vuex";
+
+export default {
+  components: { LinkTitlesCustom },
+  data() {
+    return {
+      examId: null,
+      loading4FormSearch: false,
+      formSearch: {
+        examId: null,
+        orgId: ""
+      },
+      loadingOrg4Search: false,
+      orgList4Search: [],
+
+      tableData: [],
+      currentPage: 1,
+      pageSize: 10,
+      total: 0,
+      selectedOrgSettings: [],
+
+      orgSetting: {
+        examId: null,
+        orgId: null,
+        beginTime: null,
+        endTime: null,
+        examLimit: "false",
+        properties: {
+          CAN_UPLOAD_ATTACHMENT: "true"
+        }
+      },
+      orgSettingDatetimeRange: [],
+      addOrgSettingDialog: false,
+      updateOrgSettingDialog: false,
+      orgList4InsertOrUpdate: [],
+      loadingOrg4InsertOrUpdate: false,
+      orgSettingRules: {
+        orgId: [
+          { required: true, message: "请选择学习中心", trigger: "blur,change" }
+        ]
+      },
+
+      orgSettingsImportDialog: false,
+      orgSettingsImportForm: {},
+      uploadAction: null,
+      uploadHeaders: {},
+      uploadData: {},
+      fileList: [],
+      errDialog: false,
+      errMessages: []
+    };
+  },
+  computed: {
+    ...mapState({ user: state => state.user }),
+    noBatchSelected() {
+      return this.selectedOrgSettings.length === 0;
+    }
+  },
+  methods: {
+    batchNotLimit() {
+      this.$confirm("是否开考?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        let url =
+          EXAM_WORK_API +
+          "/exam/setOrgExamNotLimited/" +
+          this.selectedOrgSettings;
+        this.$httpWithMsg.put(url).then(response => {
+          console.log(response);
+          this.$notify({
+            type: "success",
+            message: "开考成功"
+          });
+          this.search();
+        });
+      });
+    },
+    batchLimit() {
+      this.$confirm("是否禁考?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        let url =
+          EXAM_WORK_API + "/exam/setOrgExamLimited/" + this.selectedOrgSettings;
+        this.$httpWithMsg.put(url).then(response => {
+          console.log(response);
+          this.$notify({
+            type: "success",
+            message: "禁考成功"
+          });
+          this.search();
+        });
+      });
+    },
+    batchDelete() {
+      this.$confirm("删除所选学习中心特殊设置?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        let url =
+          EXAM_WORK_API +
+          "/exam/deleteExamOrgSettings/" +
+          this.selectedOrgSettings;
+        this.$httpWithMsg.put(url).then(response => {
+          console.log(response);
+          this.$notify({
+            type: "success",
+            message: "删除成功"
+          });
+          this.search();
+        });
+      });
+    },
+    deleteAll() {
+      this.$confirm("删除所有学习中心特殊设置?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        let url =
+          EXAM_WORK_API + "/exam/deleteAllExamOrgSettings/" + this.examId;
+        this.$httpWithMsg.put(url).then(response => {
+          console.log(response);
+          this.$notify({
+            type: "success",
+            message: "删除成功"
+          });
+          this.search();
+        });
+      });
+    },
+    selectChange(row) {
+      this.selectedOrgSettings = [];
+      row.forEach((element, index) => {
+        console.log(index);
+        this.selectedOrgSettings.push(element.id);
+      });
+      console.log(this.selectedOrgSettings);
+    },
+    getOrgList4Search(name) {
+      this.loadingOrg4Search = true;
+      var url = CORE_API + "/org/query?" + new URLSearchParams({ name: name });
+      this.$httpWithMsg
+        .get(url)
+        .then(response => {
+          this.orgList4Search = response.data;
+          this.loadingOrg4Search = false;
+        })
+        .catch(response => {
+          console.log(response);
+          this.loadingOrg4Search = false;
+        });
+    },
+    getOrgList4InsertOrUpdate(name) {
+      this.loadingOrg4InsertOrUpdate = true;
+      var url = CORE_API + "/org/query?" + new URLSearchParams({ name: name });
+      this.$httpWithMsg
+        .get(url)
+        .then(response => {
+          this.orgList4InsertOrUpdate = response.data;
+          this.loadingOrg4InsertOrUpdate = false;
+        })
+        .catch(response => {
+          console.log(response);
+          this.loadingOrg4InsertOrUpdate = false;
+        });
+    },
+    updateExamLimit(row) {
+      row.examLimit = !row.examLimit;
+      let url = EXAM_WORK_API + "/exam/examOrgSettings";
+      this.$httpWithMsg.post(url, row).then(response => {
+        row.updateTime = response.data.updateTime;
+      });
+    },
+    updateOrgSetting() {
+      if (!this.orgSettingDatetimeRange) {
+        this.orgSetting.beginTime = null;
+        this.orgSetting.endTime = null;
+      } else {
+        this.orgSetting.beginTime = this.orgSettingDatetimeRange[0];
+        this.orgSetting.endTime = this.orgSettingDatetimeRange[1];
+      }
+
+      this.$refs.updateOrgSettingForm.validate(valid => {
+        if (valid) {
+          let url = EXAM_WORK_API + "/exam/examOrgSettings";
+          this.$httpWithMsg.post(url, this.orgSetting).then(response => {
+            console.log(response);
+            this.$notify({
+              type: "success",
+              message: "保存成功"
+            });
+            this.search();
+            this.updateOrgSettingDialog = false;
+          });
+        } else {
+          return false;
+        }
+      });
+    },
+    addOrgSetting() {
+      if (!this.orgSettingDatetimeRange) {
+        this.orgSetting.beginTime = null;
+        this.orgSetting.endTime = null;
+      } else {
+        this.orgSetting.beginTime = this.orgSettingDatetimeRange[0];
+        this.orgSetting.endTime = this.orgSettingDatetimeRange[1];
+      }
+      this.$refs.addOrgSettingForm.validate(valid => {
+        if (valid) {
+          let url = EXAM_WORK_API + "/exam/examOrgSettings";
+          this.$httpWithMsg.put(url, this.orgSetting).then(response => {
+            console.log(response);
+            this.$notify({
+              type: "success",
+              message: "保存成功"
+            });
+            this.search();
+            this.addOrgSettingDialog = false;
+          });
+        } else {
+          return false;
+        }
+      });
+    },
+    back() {
+      this.$router.push({ path: "/examwork/examInfo" });
+    },
+    getCanUpload(row) {
+      if (row.properties.CAN_UPLOAD_ATTACHMENT === null) {
+        if (Date.now() > row.endTime) {
+          return "不允许";
+        } else {
+          return "允许";
+        }
+      } else {
+        return row.properties.CAN_UPLOAD_ATTACHMENT == "true"
+          ? "允许"
+          : "不允许";
+      }
+    },
+    handleCurrentChange(val) {
+      this.currentPage = val;
+      this.search();
+    },
+    handleSizeChange(val) {
+      this.pageSize = val;
+      this.search();
+    },
+    showUpdateOrgSetting(row) {
+      this.orgSetting.examId = row.examId;
+      this.orgSetting.beginTime = row.beginTime;
+      this.orgList4InsertOrUpdate = [{ id: row.orgId, name: row.orgName }];
+      this.orgSetting.orgId = row.orgId;
+      this.orgSetting.endTime = row.endTime;
+      this.orgSetting.examLimit = row.examLimit ? "true" : "false";
+      this.orgSetting.properties.CAN_UPLOAD_ATTACHMENT =
+        row.properties.CAN_UPLOAD_ATTACHMENT;
+      if (row.beginTime && row.endTime) {
+        this.orgSettingDatetimeRange = [row.beginTime, row.endTime];
+      } else {
+        this.orgSettingDatetimeRange = [];
+      }
+      this.updateOrgSettingDialog = true;
+    },
+    showAddOrgSetting() {
+      this.orgSetting.examId = this.examId;
+      this.orgSetting.beginTime = null;
+      this.orgList4InsertOrUpdate = [];
+      this.orgSetting.orgId = null;
+      this.orgSetting.endTime = null;
+      this.orgSetting.properties.CAN_UPLOAD_ATTACHMENT = "true";
+      this.orgSettingDatetimeRange = [];
+      this.addOrgSettingDialog = true;
+    },
+    exportOrgSettings() {
+      window.open(
+        EXAM_WORK_API +
+          "/exam/exportExamOrgSettings/" +
+          this.examId +
+          "?$key=" +
+          this.user.key +
+          "&$token=" +
+          this.user.token
+      );
+    },
+    importOrgSettings() {
+      this.removeFile();
+      this.orgSettingsImportDialog = true;
+    },
+
+    uploadSuccess(response, file, fileList) {
+      console.log("uploadSuccess");
+      console.log(response);
+      console.log(file);
+      console.log(fileList);
+      this.$notify({
+        message: "上传成功",
+        type: "success"
+      });
+      this.orgSettingsImportDialog = false;
+      this.resetPageAndSearch();
+    },
+    uploadError(response, file, fileList) {
+      console.log("uploadError");
+      console.log(response);
+      console.log(file);
+      console.log(fileList);
+      var json = JSON.parse(response.message);
+      if (response.status == 500) {
+        this.$notify({
+          message: json.desc,
+          type: "error"
+        });
+      }
+    },
+    //清空文件
+    removeFile() {
+      this.fileList = [];
+      if (this.$refs.upload) {
+        this.$refs.upload.clearFiles();
+      }
+    },
+    //确定上传
+    submitUpload() {
+      if (!this.checkUpload()) {
+        return false;
+      }
+      this.$refs.upload.submit();
+      this.fileLoading = true;
+    },
+    checkUpload() {
+      var fileList = this.$refs.upload.uploadFiles;
+      if (fileList.length == 0) {
+        this.$notify({
+          message: "上传文件不能为空",
+          type: "error"
+        });
+        return false;
+      }
+      if (fileList.length > 1) {
+        this.$notify({
+          message: "每次只能上传一个文件",
+          type: "error"
+        });
+        return false;
+      }
+      for (let file of fileList) {
+        if (!file.name.endsWith(".xlsx")) {
+          this.$notify({
+            message: "上传文件必须为xlsx格式",
+            type: "error"
+          });
+          return false;
+        }
+      }
+      return true;
+    },
+    resetPageAndSearch() {
+      this.currentPage = 1;
+      this.search();
+    },
+    search() {
+      let param = new URLSearchParams(this.formSearch);
+      let url =
+        EXAM_WORK_API +
+        "/exam/getExamOrgSettingsList/" +
+        (this.currentPage - 1) +
+        "/" +
+        this.pageSize +
+        "?" +
+        param;
+      this.loading4FormSearch = true;
+      this.$httpWithMsg
+        .get(url)
+        .then(response => {
+          console.log(response);
+          this.tableData = response.data.list;
+          this.total = response.data.total;
+          this.loading4FormSearch = false;
+        })
+        .catch(response => {
+          console.log(response);
+          this.loading4FormSearch = false;
+        });
+    },
+    init() {
+      this.search();
+    }
+  },
+  created() {
+    this.examId = this.$route.params.id;
+    this.formSearch.examId = this.examId;
+    this.init();
+    this.uploadHeaders = {
+      key: this.user.key,
+      token: this.user.token
+    };
+    this.uploadAction =
+      EXAM_WORK_API + "/exam/importExamOrgSettings/" + this.examId;
+  }
+};
+</script>
+<style scoped></style>

+ 36 - 38
src/modules/examwork/view/practiceExam.vue

@@ -15,7 +15,7 @@
             label-position="right"
             inline-message
           >
-            <div style="margin-bottom: 10px">
+            <div style="margin-bottom: 10px;">
               <el-button type="primary" size="small" @click="saveExam"
                 >保 存</el-button
               >
@@ -153,9 +153,7 @@
                       class="input"
                       v-model.trim.number="form.duration"
                       auto-complete="off"
-                      ><template slot="append"
-                        >分钟</template
-                      ></el-input
+                      ><template slot="append">分钟</template></el-input
                     >
                   </el-form-item>
                 </el-row>
@@ -170,9 +168,7 @@
                       class="input"
                       v-model.trim.number="form.examTimes"
                       auto-complete="off"
-                      ><template slot="append"
-                        >次</template
-                      ></el-input
+                      ><template slot="append">次</template></el-input
                     >
                   </el-form-item>
                 </el-row>
@@ -187,9 +183,7 @@
                       class="input"
                       v-model.trim.number="form.properties.FREEZE_TIME"
                       auto-complete="off"
-                      ><template slot="append"
-                        >分钟</template
-                      ></el-input
+                      ><template slot="append">分钟</template></el-input
                     >
                   </el-form-item>
                 </el-row>
@@ -204,9 +198,7 @@
                       class="input"
                       v-model.trim.number="form.properties.EXAM_RECONNECT_TIME"
                       auto-complete="off"
-                      ><template slot="append"
-                        >分钟</template
-                      ></el-input
+                      ><template slot="append">分钟</template></el-input
                     >
                   </el-form-item>
                 </el-row>
@@ -393,6 +385,12 @@ let validateExamReconnectTime = (rule, value, callback) => {
       _this.toActiveName = "tab2";
       _this.activeName = "tab2";
     }
+  } else if (examReconnectTime < 3) {
+    callback(new Error("最小设置值为3"));
+    if (!_this.toActiveName) {
+      _this.toActiveName = "tab2";
+      _this.activeName = "tab2";
+    }
   } else {
     callback();
   }
@@ -401,14 +399,14 @@ let validateExamReconnectTime = (rule, value, callback) => {
 export default {
   components: {
     ckeditor,
-    LinkTitlesCustom
+    LinkTitlesCustom,
   },
   data() {
     return {
       style: {
         label_width_tab1: "80px",
         label_width_tab2: "110px",
-        label_width_tab3: "120px"
+        label_width_tab3: "120px",
       },
       activeName: "tab1",
       toActiveName: null,
@@ -429,8 +427,8 @@ export default {
           BEFORE_EXAM_REMARK: "",
           AFTER_EXAM_REMARK: "",
           IS_OBJ_SCORE_VIEW: "true",
-          PRACTICE_TYPE: "IN_PRACTICE"
-        }
+          PRACTICE_TYPE: "IN_PRACTICE",
+        },
       },
       examTypeList: EXAM_TYPE,
       examId: "",
@@ -441,26 +439,26 @@ export default {
           {
             required: true,
             validator: validateExamDatetimeRange,
-            trigger: "blur"
-          }
+            trigger: "blur",
+          },
         ],
         duration: [
-          { required: true, validator: validateDuration, trigger: "blur" }
+          { required: true, validator: validateDuration, trigger: "blur" },
         ],
         examTimes: [
-          { required: true, validator: validateExamTimes, trigger: "blur" }
+          { required: true, validator: validateExamTimes, trigger: "blur" },
         ],
         FREEZE_TIME: [
-          { required: true, validator: validateFreezeTime, trigger: "blur" }
+          { required: true, validator: validateFreezeTime, trigger: "blur" },
         ],
         EXAM_RECONNECT_TIME: [
           {
             required: true,
             validator: validateExamReconnectTime,
-            trigger: "blur"
-          }
-        ]
-      }
+            trigger: "blur",
+          },
+        ],
+      },
     };
   },
 
@@ -468,7 +466,7 @@ export default {
     init() {
       if (this.examId != "add") {
         let url = EXAM_WORK_API + "/exam/" + this.examId;
-        this.$httpWithMsg.get(url).then(response => {
+        this.$httpWithMsg.get(url).then((response) => {
           let body = response.data;
           body.properties = this.form.properties;
           this.form = Object.assign(this.form, response.data);
@@ -477,7 +475,7 @@ export default {
           console.log("getOnlineExam(); form: ", this.form);
 
           let url = EXAM_WORK_API + "/exam/allProperties/" + this.examId;
-          this.$httpWithMsg.get(url).then(response => {
+          this.$httpWithMsg.get(url).then((response) => {
             this.form.properties = Object.assign(
               this.form.properties,
               response.data
@@ -491,40 +489,40 @@ export default {
         this.show_ckeditor = true;
       }
     },
-    saveExam: function() {
+    saveExam: function () {
       this.toActiveName = null;
       this.form.beginTime = this.examDatetimeRange[0];
       this.form.endTime = this.examDatetimeRange[1];
       console.log(this.form);
       let url = EXAM_WORK_API + "/exam";
-      this.$refs.form.validate(valid => {
+      this.$refs.form.validate((valid) => {
         if (valid) {
           if (this.examId != "add") {
-            this.$httpWithMsg.put(url, this.form).then(response => {
+            this.$httpWithMsg.put(url, this.form).then((response) => {
               if (200 != response.status) {
                 this.$notify({
                   type: "error",
-                  message: response.body.desc
+                  message: response.body.desc,
                 });
                 return;
               }
               this.$notify({
                 type: "success",
-                message: "保存成功"
+                message: "保存成功",
               });
             });
           } else {
             this.form.code = this.form.name;
-            this.$httpWithMsg.post(url, this.form).then(response => {
+            this.$httpWithMsg.post(url, this.form).then((response) => {
               console.log(response);
               this.$notify({
                 type: "success",
-                message: "新增成功"
+                message: "新增成功",
               });
               this.examId = response.data.id;
               this.form.id = this.examId;
               this.$router.push({
-                path: "/examwork/practiceExam/" + response.data.id
+                path: "/examwork/practiceExam/" + response.data.id,
               });
             });
           }
@@ -535,13 +533,13 @@ export default {
     },
     back() {
       this.$router.push({ path: "/examwork/examInfo" });
-    }
+    },
   },
   created() {
     _this = this;
     this.examId = this.$route.params.id;
     this.init();
-  }
+  },
 };
 </script>
 <style scoped>

+ 200 - 56
src/modules/examwork/view/student.vue

@@ -3,7 +3,12 @@
     <div class="box box-info">
       <!-- 正文信息 -->
       <div class="box-body">
-        <el-form :model="formSearch" :inline="true" ref="formSearch" label-width="70px">
+        <el-form
+          :model="formSearch"
+          :inline="true"
+          ref="formSearch"
+          label-width="70px"
+        >
           <el-form-item v-if="isSuperAdmin" label="学校">
             <el-select
               v-model="formSearch.rootOrgId"
@@ -20,13 +25,25 @@
             </el-select>
           </el-form-item>
           <el-form-item label="姓名">
-            <el-input placeholder="请输入姓名" v-model="formSearch.name" class="input"></el-input>
+            <el-input
+              placeholder="请输入姓名"
+              v-model="formSearch.name"
+              class="input"
+            ></el-input>
           </el-form-item>
           <el-form-item label="学号">
-            <el-input placeholder="请输入学号" v-model="formSearch.studentCode" class="input"></el-input>
+            <el-input
+              placeholder="请输入学号"
+              v-model="formSearch.studentCode"
+              class="input"
+            ></el-input>
           </el-form-item>
           <el-form-item label="身份证">
-            <el-input placeholder="请输入身份证" v-model="formSearch.identityNumber" class="input"></el-input>
+            <el-input
+              placeholder="请输入身份证"
+              v-model="formSearch.identityNumber"
+              class="input"
+            ></el-input>
           </el-form-item>
           <el-form-item label="学习中心">
             <el-select
@@ -62,16 +79,29 @@
               type="primary"
               icon="el-icon-search"
               @click="resetPageAndSearchForm"
-            >查询</el-button>
-            <el-button size="small" icon="el-icon-refresh" @click="resetSearchForm">重置</el-button>
+              >查询</el-button
+            >
+            <el-button
+              size="small"
+              icon="el-icon-refresh"
+              @click="resetSearchForm"
+              >重置</el-button
+            >
             <el-button
               v-if="rolePrivileges.upload_student_photo"
               size="small"
               type="primary"
               icon="el-icon-upload2"
               @click="uploadPhoto"
-            >上传照片</el-button>
-            <el-button size="small" type="primary" icon="el-icon-download" @click="exportStudent">导出</el-button>
+              >上传照片</el-button
+            >
+            <el-button
+              size="small"
+              type="primary"
+              icon="el-icon-download"
+              @click="exportStudent"
+              >导出</el-button
+            >
           </el-form-item>
         </el-form>
 
@@ -85,7 +115,8 @@
           icon="el-icon-refresh"
           :disabled="noBatchSelected"
           @click="resetPassword('')"
-        >重置密码</el-button>
+          >重置密码</el-button
+        >
         <el-button
           v-if="rolePrivileges.change_student_availability"
           size="small"
@@ -93,7 +124,8 @@
           icon="el-icon-check"
           :disabled="noBatchSelected"
           @click="enableStudent('')"
-        >启用</el-button>
+          >启用</el-button
+        >
         <el-button
           v-if="rolePrivileges.change_student_availability"
           size="small"
@@ -101,19 +133,25 @@
           icon="el-icon-close"
           :disabled="noBatchSelected"
           @click="disableStudent('')"
-        >禁用</el-button>
+          >禁用</el-button
+        >
         <el-button
           v-if="rolePrivileges.reset_student_password"
           size="small"
           type="danger"
           icon="el-icon-refresh"
           @click="resetPasswordByOrgId()"
-        >重置学习中心所有学生密码</el-button>
+          >重置学习中心所有学生密码</el-button
+        >
 
         <div style="width: 100%;margin-bottom: 10px;"></div>
 
         <!-- 重置学习中心所有学生密码-->
-        <el-dialog title="重置学习中心所有学生密码" width="500px" :visible.sync="resetPasswordByOrgIdDialog">
+        <el-dialog
+          title="重置学习中心所有学生密码"
+          width="500px"
+          :visible.sync="resetPasswordByOrgIdDialog"
+        >
           <el-form
             :model="resetPasswordByOrgIdForm"
             :inline="true"
@@ -143,8 +181,12 @@
             </el-form-item>
           </el-form>
           <div style="text-align: center;margin-top: 20px;">
-            <el-button type="primary" @click="submitResetPasswordByOrgId">确 定</el-button>
-            <el-button @click="resetPasswordByOrgIdDialog = false">取 消</el-button>
+            <el-button type="primary" @click="submitResetPasswordByOrgId"
+              >确 定</el-button
+            >
+            <el-button @click="resetPasswordByOrgIdDialog = false"
+              >取 消</el-button
+            >
           </div>
         </el-dialog>
 
@@ -156,44 +198,63 @@
           @selection-change="selectChange"
         >
           <el-table-column type="selection" width="50"></el-table-column>
-          <el-table-column prop="id" width="100" label="ID" sortable></el-table-column>
+          <el-table-column
+            prop="id"
+            width="100"
+            label="ID"
+            sortable
+          ></el-table-column>
           <el-table-column label="考生" width="100">
             <template slot-scope="scope">
               <el-popover trigger="hover" placement="left">
                 <div style="font-size: 18px;font-family: 新宋体">
                   <tr>
                     <td style="color: green">姓名</td>
-                    <td style="color:purple;padding-left: 20px;">{{ scope.row.name }}</td>
+                    <td style="color:purple;padding-left: 20px;">
+                      {{ scope.row.name }}
+                    </td>
                   </tr>
                   <tr>
                     <td style="color: green">身份证号</td>
-                    <td
-                      style="color:purple;padding-left: 20px;"
-                    >{{ scope.row.privateIdentityNumber }}</td>
+                    <td style="color:purple;padding-left: 20px;">
+                      {{ scope.row.privateIdentityNumber }}
+                    </td>
                   </tr>
                   <tr>
                     <td style="color: green">学号</td>
-                    <td style="color:purple;padding-left: 20px;">{{ scope.row.studentCodeList }}</td>
+                    <td style="color:purple;padding-left: 20px;">
+                      {{ scope.row.studentCodeList }}
+                    </td>
                   </tr>
                   <tr>
                     <td style="color: green">学习中心名称</td>
-                    <td style="color:purple;padding-left: 20px;">{{ scope.row.orgName }}</td>
+                    <td style="color:purple;padding-left: 20px;">
+                      {{ scope.row.orgName }}
+                    </td>
                   </tr>
                   <tr>
                     <td style="color: green">学习中心编码</td>
-                    <td style="color:purple;padding-left: 20px;">{{ scope.row.orgCode }}</td>
+                    <td style="color:purple;padding-left: 20px;">
+                      {{ scope.row.orgCode }}
+                    </td>
                   </tr>
                   <tr>
                     <td style="color: green">手机号</td>
-                    <td style="color:purple;padding-left: 20px;">{{ scope.row.phoneNumber }}</td>
+                    <td style="color:purple;padding-left: 20px;">
+                      {{ scope.row.phoneNumber }}
+                    </td>
                   </tr>
                   <tr>
                     <td style="color: green">安全手机号</td>
-                    <td style="color:purple;padding-left: 20px;">{{ scope.row.securityPhone }}</td>
+                    <td style="color:purple;padding-left: 20px;">
+                      {{ scope.row.securityPhone }}
+                    </td>
                   </tr>
                   <tr>
                     <td style="color: green">创建时间</td>
-                    <td style="color:purple;padding-left: 20px;">{{ scope.row.creationTime }}</td>
+                    <td style="color:purple;padding-left: 20px;">
+                      {{ scope.row.creationTime }}
+                    </td>
                   </tr>
                 </div>
 
@@ -206,18 +267,43 @@
           <el-table-column label="学号">
             <span slot-scope="scope" v-html="scope.row.studentCodesStr"></span>
           </el-table-column>
-          <el-table-column prop="privateIdentityNumber" width label="身份证" sortable></el-table-column>
-          <el-table-column prop="orgName" width label="学习中心" sortable></el-table-column>
-          <el-table-column prop="updateTime" width="168" label="更新时间" sortable></el-table-column>
+          <el-table-column
+            prop="privateIdentityNumber"
+            width
+            label="身份证"
+            sortable
+          ></el-table-column>
+          <el-table-column
+            prop="orgName"
+            width
+            label="学习中心"
+            sortable
+          ></el-table-column>
+          <el-table-column
+            prop="updateTime"
+            width="168"
+            label="更新时间"
+            sortable
+          ></el-table-column>
           <el-table-column width="50" label="状态">
             <span slot-scope="scope">
               <span v-if="scope.row.enable">
-                <el-tooltip class="item" effect="dark" content="启用" placement="left">
+                <el-tooltip
+                  class="item"
+                  effect="dark"
+                  content="启用"
+                  placement="left"
+                >
                   <i class="el-icon-success" style="color:green;"></i>
                 </el-tooltip>
               </span>
               <span v-else>
-                <el-tooltip class="item" effect="dark" content="禁用" placement="left">
+                <el-tooltip
+                  class="item"
+                  effect="dark"
+                  content="禁用"
+                  placement="left"
+                >
                   <i class="el-icon-error" style="color:red;"></i>
                 </el-tooltip>
               </span>
@@ -232,7 +318,8 @@
                 plain
                 icon="el-icon-picture"
                 @click="showPhoto(scope.row)"
-              >查看照片</el-button>
+                >查看照片</el-button
+              >
               <el-button
                 v-if="
                   null != scope.row.enable &&
@@ -244,14 +331,16 @@
                 plain
                 icon="el-icon-check"
                 @click="enableStudent(scope.row)"
-              >启用</el-button>
+                >启用</el-button
+              >
               <el-button
                 v-else-if="rolePrivileges.change_student_availability"
                 size="mini"
                 type="danger"
                 icon="el-icon-close"
                 @click="disableStudent(scope.row)"
-              >禁用</el-button>
+                >禁用</el-button
+              >
 
               <el-dropdown style="margin-left: 10px;">
                 <el-button type="primary" plain size="mini">
@@ -259,13 +348,16 @@
                   <i class="el-icon-arrow-down el-icon--right"></i>
                 </el-button>
                 <el-dropdown-menu slot="dropdown">
-                  <el-dropdown-item v-if="rolePrivileges.reset_student_password">
+                  <el-dropdown-item
+                    v-if="rolePrivileges.reset_student_password"
+                  >
                     <el-button
                       size="mini"
                       type="danger"
                       icon="el-icon-refresh"
                       @click="resetPassword(scope.row)"
-                    >重置密码</el-button>
+                      >重置密码</el-button
+                    >
                   </el-dropdown-item>
                   <el-dropdown-item>
                     <el-button
@@ -273,7 +365,8 @@
                       type="primary"
                       icon="el-icon-document"
                       @click="showStuExamDialog(scope.row)"
-                    >考试记录</el-button>
+                      >考试记录</el-button
+                    >
                   </el-dropdown-item>
                   <el-dropdown-item v-if="rolePrivileges.unbind_student_code">
                     <el-button
@@ -281,7 +374,8 @@
                       type="danger"
                       icon="el-icon-refresh"
                       @click="showUnbindStudentCode(scope.row)"
-                    >解绑学号</el-button>
+                      >解绑学号</el-button
+                    >
                   </el-dropdown-item>
                   <el-dropdown-item v-if="rolePrivileges.unbind_security_phone">
                     <el-button
@@ -289,7 +383,8 @@
                       type="danger"
                       icon="el-icon-refresh"
                       @click="unbindSecurityPhone(scope.row)"
-                    >解绑安全手机</el-button>
+                      >解绑安全手机</el-button
+                    >
                   </el-dropdown-item>
                 </el-dropdown-menu>
               </el-dropdown>
@@ -309,7 +404,11 @@
         </div>
 
         <!-- 解绑学号-->
-        <el-dialog title="解绑学号" width="50%" :visible.sync="unbindStudentCodeDialog">
+        <el-dialog
+          title="解绑学号"
+          width="50%"
+          :visible.sync="unbindStudentCodeDialog"
+        >
           <el-table
             :data="unbindStudentCodeData.tableData"
             border
@@ -325,7 +424,8 @@
                   type="danger"
                   @click="unbindStudentCode(scope.row)"
                   icon="el-icon-delete"
-                >解绑</el-button>
+                  >解绑</el-button
+                >
               </div>
             </el-table-column>
           </el-table>
@@ -339,7 +439,12 @@
           v-loading="stuExamLoading"
           element-loading-text="拼命加载中"
         >
-          <el-form :inline="true" :model="stuExamSearch" label-position="right" label-width="50px">
+          <el-form
+            :inline="true"
+            :model="stuExamSearch"
+            label-position="right"
+            label-width="50px"
+          >
             <el-form-item label="考试" class="pull-left">
               <el-select
                 class="input"
@@ -360,16 +465,37 @@
               </el-select>
             </el-form-item>
             <el-form-item class="pull-left">
-              <el-button size="small" type="primary" icon="el-icon-search" @click="searchStuExam">查询</el-button>
+              <el-button
+                size="small"
+                type="primary"
+                icon="el-icon-search"
+                @click="searchExamRecord"
+                >查询</el-button
+              >
             </el-form-item>
           </el-form>
 
-          <el-table :data="stuExamList" border style="width: 100%;text-align:center;">
-            <el-table-column prop="studentName" label="学生姓名"></el-table-column>
+          <el-table
+            :data="stuExamList"
+            border
+            style="width: 100%;text-align:center;"
+          >
+            <el-table-column
+              prop="studentName"
+              label="学生姓名"
+            ></el-table-column>
             <el-table-column prop="studentCode" label="学号"></el-table-column>
             <el-table-column prop="ext2" label="身份证"></el-table-column>
-            <el-table-column prop="examName" label="考试" sortable></el-table-column>
-            <el-table-column prop="courseName" label="课程" sortable></el-table-column>
+            <el-table-column
+              prop="examName"
+              label="考试"
+              sortable
+            ></el-table-column>
+            <el-table-column
+              prop="courseName"
+              label="课程"
+              sortable
+            ></el-table-column>
             <el-table-column width="130" label="考试状态">
               <div slot-scope="scope">
                 <span v-if="null == scope.row.started"></span>
@@ -393,7 +519,11 @@
         </el-dialog>
 
         <!-- 导入照片弹窗 -->
-        <el-dialog title="学生照片导入" width="350px" :visible.sync="photoUploadDialog">
+        <el-dialog
+          title="学生照片导入"
+          width="350px"
+          :visible.sync="photoUploadDialog"
+        >
           <el-form>
             <el-row>
               <el-form-item style="margin-left:30px">
@@ -412,15 +542,24 @@
                   :auto-upload="false"
                   :multiple="false"
                 >
-                  <el-button size="small" slot="trigger" type="primary" icon="el-icon-search">选择文件</el-button>
+                  <el-button
+                    size="small"
+                    slot="trigger"
+                    type="primary"
+                    icon="el-icon-search"
+                    >选择文件</el-button
+                  >
                   <el-button
                     size="small"
                     style="margin-left:10px;"
                     type="primary"
                     icon="el-icon-check"
                     @click="submitUpload"
-                  >确认上传</el-button>
-                  <div slot="tip" class="el-upload__tip">只能上传jpg,png文件</div>
+                    >确认上传</el-button
+                  >
+                  <div slot="tip" class="el-upload__tip">
+                    只能上传jpg,png文件
+                  </div>
                 </el-upload>
               </el-form-item>
             </el-row>
@@ -673,16 +812,21 @@ export default {
       this.stuExamList = [];
       this.stuExamTotal = 0;
       this.queryExams4Search("");
-      this.searchStuExam();
+      this.stuExamCurPage = 1;
+      this.searchStuExam(this.stuExamCurPage);
       this.stuExamDialog = true;
     },
-    searchStuExam() {
+    searchExamRecord() {
+      this.stuExamCurPage = 1;
+      this.searchStuExam(this.stuExamCurPage);
+    },
+    searchStuExam(curPage) {
       var param = new URLSearchParams(this.stuExamSearch);
       this.stuExamLoading = true;
       var url =
         EXAM_WORK_API +
         "/exam_student/examStudentPage/" +
-        (this.stuExamCurPage - 1) +
+        (curPage - 1) +
         "/" +
         this.stuExamPageSize +
         "?" +
@@ -701,11 +845,11 @@ export default {
     },
     stuExamCurChange(val) {
       this.stuExamCurPage = val;
-      this.searchStuExam();
+      this.searchStuExam(val);
     },
     handleStuExamSizeChange(val) {
       this.stuExamPageSize = val;
-      this.searchStuExam();
+      this.searchStuExam(val);
     },
     closePhotoDialog() {
       this.photo.url = "/img/blank.png";

+ 2 - 1
src/modules/marking/filters/filters.js

@@ -20,7 +20,8 @@ export const EXAMTYPES = [
   { label: "在线考试", value: "ONLINE" },
   { label: "离线考试", value: "OFFLINE" },
   { label: "传统考试", value: "TRADITION" },
-  { label: "练习", value: "PRACTICE" }
+  { label: "练习", value: "PRACTICE" },
+  { label: "在线作业", value: "ONLINE_HOMEWORK" }
 ];
 //考试类型过滤器
 Vue.filter("examTypeFilter", function(val) {

+ 69 - 65
src/modules/marking/views/MarkWork.vue

@@ -36,7 +36,7 @@
             element-loading-text="拼命加载中"
             :data="tableData"
             border
-            style="width: 100%"
+            style="width: 100%;"
           >
             <el-table-column label="评卷工作名称" width="150">
               <template slot-scope="scope">
@@ -96,7 +96,7 @@
                     >评卷设置</el-button
                   >
                   <el-dropdown
-                    style="margin-left:10px;"
+                    style="margin-left: 10px;"
                     placement="bottom-start"
                   >
                     <el-button size="mini" type="primary" plain>
@@ -202,7 +202,7 @@
                 <el-input
                   placeholder="评卷工作名称"
                   v-model="formMarkWork.name"
-                  style="width: 200px"
+                  style="width: 200px;"
                 ></el-input>
               </el-form-item>
               <el-form-item
@@ -212,11 +212,13 @@
               >
                 <el-select
                   v-model="formMarkWork.examType"
-                  style="width: 200px"
+                  style="width: 200px;"
                   @change="examTypeChange()"
                 >
                   <el-option label="在线考试" value="ONLINE"> </el-option>
                   <el-option label="离线考试" value="OFFLINE"> </el-option>
+                  <el-option label="在线作业" value="ONLINE_HOMEWORK">
+                  </el-option>
                 </el-select>
               </el-form-item>
               <el-form-item label="考试批次" prop="examIds">
@@ -226,7 +228,7 @@
                   filterable
                   multiple
                   placeholder="考试批次"
-                  style="width: 200px"
+                  style="width: 200px;"
                 >
                   <el-option
                     v-for="item in examSelect"
@@ -238,14 +240,14 @@
               </el-form-item>
               <el-form-item label="备注" prop="remark">
                 <el-input
-                  style="width: 200px"
+                  style="width: 200px;"
                   type="textarea"
                   :rows="3"
                   placeholder="备注"
                   v-model="formMarkWork.remark"
                 ></el-input>
               </el-form-item>
-              <el-form-item style="margin-top:10px;margin-left: 100px">
+              <el-form-item style="margin-top: 10px; margin-left: 100px;">
                 <el-button
                   :loading="saveLoading"
                   type="primary"
@@ -270,13 +272,13 @@ export default {
   data() {
     return {
       formSearch: {
-        name: ""
+        name: "",
       },
       formMarkWork: {
         examType: "",
         name: "",
         examIds: [],
-        remark: ""
+        remark: "",
       },
       rules: {
         name: [{ required: true, message: "请输入名称", trigger: "blur" }],
@@ -285,23 +287,23 @@ export default {
             required: true,
             message: "请选择考试批次",
             trigger: "change",
-            type: "array"
-          }
+            type: "array",
+          },
         ],
         examType: [
           {
             required: true,
             message: "请选择考试类型",
             trigger: "change",
-            type: "string"
-          }
-        ]
+            type: "string",
+          },
+        ],
       },
       statusList: [
         { code: 0, name: "创建中" },
         { code: 1, name: "创建成功" },
         { code: 2, name: "创建失败" },
-        { code: 3, name: "追加中" }
+        { code: 3, name: "追加中" },
       ],
       examSelect: [],
       tableData: [],
@@ -316,18 +318,18 @@ export default {
       loading: false,
       closeClickModal: false,
       saveLoading: false,
-      oldWorkName: ""
+      oldWorkName: "",
     };
   },
   computed: {
-    ...mapState({ user: state => state.user })
+    ...mapState({ user: (state) => state.user }),
   },
   methods: {
     settingMarkWork(row) {
       if (Number.parseInt(row.status) != 1) {
         this.$notify({
           message: "该评卷工作未完成,不能进行设置.",
-          type: "warning"
+          type: "warning",
         });
         return;
       }
@@ -337,7 +339,7 @@ export default {
         "/" +
         encodeURIComponent(row.name);
       this.$router.push({
-        path: url
+        path: url,
       });
     },
     getStatus(code) {
@@ -362,7 +364,7 @@ export default {
         .then(() => {
           this.$notify({
             message: "操作成功",
-            type: "success"
+            type: "success",
           });
           this.initMarkWorkData();
           this.loading = false;
@@ -373,7 +375,7 @@ export default {
       this.$http.put(DATA_PROCESS_API + "/markWorks/" + row.id).then(() => {
         this.$notify({
           message: "操作成功",
-          type: "success"
+          type: "success",
         });
         this.initMarkWorkData();
         this.loading = false;
@@ -398,23 +400,25 @@ export default {
       if (this.formMarkWork.examType) {
         params = params + "&examType=" + this.formMarkWork.examType;
       }
-      this.$http.get(DATA_PROCESS_API + "/exam/all" + params).then(response => {
-        response.data.forEach((element, index) => {
-          tempSelect[index] = {
-            value: element.id,
-            label: element.name
-          };
+      this.$http
+        .get(DATA_PROCESS_API + "/exam/all" + params)
+        .then((response) => {
+          response.data.forEach((element, index) => {
+            tempSelect[index] = {
+              value: element.id,
+              label: element.name,
+            };
+          });
+          this.examSelect = tempSelect;
+          //this.loading = false;
         });
-        this.examSelect = tempSelect;
-        //this.loading = false;
-      });
     },
     initMarkWorkData() {
       var orgId = this.user.rootOrgId;
       this.loading = true;
       this.$http
         .get(DATA_PROCESS_API + "/markWorks?orgId=" + orgId)
-        .then(response => {
+        .then((response) => {
           console.log(response);
           this.totalTableData = response.data;
           this.total = response.data.length;
@@ -431,10 +435,10 @@ export default {
           .get(
             MARKING_API + "/markWorks/getWorkList?workIds=" + creatingWorkIds
           )
-          .then(response => {
-            response.data.forEach(element => {
+          .then((response) => {
+            response.data.forEach((element) => {
               if (element.status != 0) {
-                this.tableData.forEach(e => {
+                this.tableData.forEach((e) => {
                   if (e.id == element.id) {
                     e.status = element.status;
                   }
@@ -449,7 +453,7 @@ export default {
     },
     getCreatingWorkId() {
       var tempData = [];
-      this.tableData.forEach(element => {
+      this.tableData.forEach((element) => {
         if (element.status == 0) {
           tempData.push(element.id);
         }
@@ -461,7 +465,7 @@ export default {
       this.paging();
     },
     filterMarkWork() {
-      var tempData = this.totalTableData.filter(element => {
+      var tempData = this.totalTableData.filter((element) => {
         if (this.formSearch.name) {
           return element.name.includes(this.formSearch.name);
         } else {
@@ -516,14 +520,14 @@ export default {
       if (Number.parseInt(row.status) == 0) {
         this.$notify({
           message: "创建中的评卷工作不能删除!",
-          type: "error"
+          type: "error",
         });
         return;
       }
       this.$confirm("确认删除评卷工作?", "提示", {
         confirmButtonText: "确定",
         cancelButtonText: "取消",
-        type: "warning"
+        type: "warning",
       }).then(() => {
         this.loading = true;
         this.$http
@@ -531,14 +535,14 @@ export default {
           .then(() => {
             this.$notify({
               message: "删除成功",
-              type: "success"
+              type: "success",
             });
             this.initMarkWorkData();
           })
-          .catch(e => {
+          .catch((e) => {
             this.$notify({
               message: e.response.data.desc,
-              type: "error"
+              type: "error",
             });
           });
         this.loading = false;
@@ -548,7 +552,7 @@ export default {
       this.$confirm("确认结束评卷工作?", "提示", {
         confirmButtonText: "确定",
         cancelButtonText: "取消",
-        type: "warning"
+        type: "warning",
       }).then(() => {
         this.loading = true;
         this.$http
@@ -556,14 +560,14 @@ export default {
           .then(() => {
             this.$notify({
               message: "操作成功",
-              type: "success"
+              type: "success",
             });
             this.initMarkWorkData();
           })
-          .catch(e => {
+          .catch((e) => {
             this.$notify({
               message: e.response.data.desc,
-              type: "error"
+              type: "error",
             });
           });
         this.loading = false;
@@ -573,7 +577,7 @@ export default {
       this.$confirm("确认开启评卷工作?", "提示", {
         confirmButtonText: "确定",
         cancelButtonText: "取消",
-        type: "warning"
+        type: "warning",
       }).then(() => {
         this.loading = true;
         this.$http
@@ -581,14 +585,14 @@ export default {
           .then(() => {
             this.$notify({
               message: "操作成功",
-              type: "success"
+              type: "success",
             });
             this.initMarkWorkData();
           })
-          .catch(e => {
+          .catch((e) => {
             this.$notify({
               message: e.response.data.desc,
-              type: "error"
+              type: "error",
             });
           });
         this.loading = false;
@@ -598,27 +602,27 @@ export default {
       if (!(Number.parseInt(row.progress) == 100)) {
         this.$notify({
           message: "进度未达到100%,不能进行成绩发布",
-          type: "error"
+          type: "error",
         });
         return;
       }
       this.$confirm("确认成绩发布?", "提示", {
         confirmButtonText: "确定",
         cancelButtonText: "取消",
-        type: "warning"
+        type: "warning",
       }).then(() => {
         this.loading = true;
         this.$http.post(MARKING_API + "/markWorks/" + row.id + "/publish").then(
           () => {
             this.$notify({
               message: "成绩发布成功",
-              type: "success"
+              type: "success",
             });
           },
           () => {
             this.$notify({
               message: "成绩发布失败",
-              type: "error"
+              type: "error",
             });
           }
         );
@@ -631,7 +635,7 @@ export default {
         if (workList.name == workName) {
           this.$notify({
             message: "评卷工作名称已存在,请重新输入!",
-            type: "warning"
+            type: "warning",
           });
           return true;
         }
@@ -639,7 +643,7 @@ export default {
       return false;
     },
     saveMarkWork() {
-      this.$refs.formMarkWork.validate(valid => {
+      this.$refs.formMarkWork.validate((valid) => {
         if (valid) {
           var newWorkName = this.formMarkWork.name;
           if (newWorkName != this.oldWorkName) {
@@ -660,17 +664,17 @@ export default {
                 () => {
                   this.$notify({
                     message: "评卷工作保存成功",
-                    type: "success"
+                    type: "success",
                   });
                   this.closeMarkWork();
                   this.initMarkWorkData();
                   this.loading = false;
                   this.saveLoading = false;
                 },
-                error => {
+                (error) => {
                   this.$notify({
                     message: error.response.data,
-                    type: "error"
+                    type: "error",
                   });
                   this.loading = false;
                   this.saveLoading = false;
@@ -683,17 +687,17 @@ export default {
                 () => {
                   this.$notify({
                     message: "评卷工作新增成功",
-                    type: "success"
+                    type: "success",
                   });
                   this.closeMarkWork();
                   this.initMarkWorkData();
                   this.loading = false;
                   this.saveLoading = false;
                 },
-                error => {
+                (error) => {
                   this.$notify({
                     message: error.response.data,
-                    type: "error"
+                    type: "error",
                   });
                   this.loading = false;
                   this.saveLoading = false;
@@ -713,7 +717,7 @@ export default {
         //编辑
         this.formMarkWork = Object.assign(this.formMarkWork, {
           remark: "",
-          name: ""
+          name: "",
         });
         this.$refs["formMarkWork"].clearValidate();
       } else {
@@ -721,7 +725,7 @@ export default {
         this.formMarkWork = Object.assign(this.formMarkWork, {
           remark: "",
           examName: "",
-          name: ""
+          name: "",
         });
         this.$refs["formMarkWork"].clearValidate();
       }
@@ -736,11 +740,11 @@ export default {
       this.pageSize = val;
       this.filterMarkWork();
       this.paging();
-    }
+    },
   },
   created() {
     this.initMarkWorkData();
-  }
+  },
 };
 </script>
 <style scoped>

+ 30 - 0
src/modules/marking/views/MarkWorkOverview.vue

@@ -71,6 +71,15 @@
                 >查询</el-button
               >
             </el-form-item>
+            <el-form-item>
+              <el-button
+                size="small"
+                type="primary"
+                icon="el-icon-download"
+                @click="exportBtnFn"
+                >导出</el-button
+              >
+            </el-form-item>
           </el-form>
         </el-col>
       </el-row>
@@ -392,6 +401,27 @@ export default {
       this.currentPage = 1;
       this.searchSetting();
     },
+    exportBtnFn() {
+      if (!this.markWorkSearchForm.markId) {
+        this.$notify({
+          title: "警告",
+          message: "请选择评卷名称",
+          type: "warning"
+        });
+        return false;
+      }
+      window.open(
+        MARKING_API +
+          "/markCourses/all/export?workId=" +
+          this.workId +
+          "&courseCode=" +
+          this.formSearch.courseCode +
+          "&$key=" +
+          this.user.key +
+          "&$token=" +
+          this.user.token
+      );
+    },
     searchSetting() {
       if (!this.markWorkSearchForm.markId) {
         this.$notify({

+ 6 - 0
src/modules/oe/routes/routes.js

@@ -4,6 +4,7 @@ import awaitingAudit from "../views/awaitingAudit.vue";
 import alreadyAudited from "../views/alreadyAudited.vue";
 import reexamine from "../views/reexamine.vue";
 import illegalityNameList from "../views/illegalityNameList.vue";
+import illegalityType from "../views/illegalityType.vue";
 import scoreStatistics from "../views/scoreStatistics.vue";
 import examDetail from "../views/examDetail.vue";
 import examScheduling from "../views/examScheduling.vue";
@@ -52,6 +53,11 @@ export default [
         name: "illegalityNameList",
         component: illegalityNameList //违纪名单
       },
+      {
+        path: "illegalityType",
+        name: "illegalityType",
+        component: illegalityType //违纪类型管理
+      },
       {
         path: "scoreStatistics",
         name: "scoreStatistics",

+ 1 - 1
src/modules/oe/views/absent.vue

@@ -112,7 +112,7 @@ export default {
         ORG_FIND_ALL: false //查询所有机构l
       },
       getExamCondition: {
-        params: { name: "", examTypes: "ONLINE#OFFLINE" },
+        params: { name: "", examTypes: "ONLINE#OFFLINE#ONLINE_HOMEWORK" },
         filterCondition: "OVERDUE"
       },
       tableData: [],

+ 33 - 8
src/modules/oe/views/alreadyAudited.vue

@@ -38,17 +38,21 @@
           <el-col :span="6">
             <el-form-item label="审核说明">
               <el-select
-                class="form_search_width"
-                size="small"
                 v-model="form.disciplineType"
+                filterable
+                remote
+                :remote-method="getDisciplineTypeList"
                 clearable
+                class="form_search_width"
+                @clear="getDisciplineTypeList"
                 placeholder="全部"
+                size="small"
               >
                 <el-option
-                  v-for="item in auditExplainList"
-                  :key="item.name"
-                  :label="item.desc"
-                  :value="item.name"
+                  v-for="item in disciplineTypeList"
+                  :key="item.code"
+                  :label="item.name"
+                  :value="item.code"
                 ></el-option>
               </el-select>
             </el-form-item>
@@ -252,7 +256,7 @@ export default {
       getExamCondition: {
         params: {
           name: "",
-          examTypes: "ONLINE",
+          examTypes: "ONLINE#ONLINE_HOMEWORK",
           propertyKeys: "IS_FACE_ENABLE"
         },
         filterCondition: "IS_FACE_ENABLE"
@@ -377,6 +381,25 @@ export default {
         }
         this.search();
       }
+    },
+    getDisciplineTypeList(name) {
+      if (!name) {
+        name = "";
+      }
+      this.$http
+        .get("/api/ecs_oe_admin/illegallyType/queryByNameLike", {
+          params: { name }
+        })
+        .then(response => {
+          if (response.data) {
+            //排除断电和机器故障
+            this.disciplineTypeList = response.data.filter(
+              v =>
+                !(v.rootOrgId == -1 && v.code == "POWER_FAILURE") &&
+                !(v.rootOrgId == -1 && v.code == "MACHINE_STOPPAGE")
+            );
+          }
+        });
     }
   },
   watch: {
@@ -390,7 +413,9 @@ export default {
       }
     }
   },
-  created() {}
+  created() {
+    this.getDisciplineTypeList("");
+  }
 };
 </script>
 <style scoped src="../style/common.css"></style>

+ 62 - 14
src/modules/oe/views/awaitingAudit.vue

@@ -77,6 +77,20 @@
               </el-row>
             </el-form-item>
           </el-col>
+          <el-col :span="6">
+            <el-form-item label="虚拟设备">
+              <el-select
+                class="form_search_width"
+                size="small"
+                v-model="form.hasVirtual"
+                clearable
+                placeholder="全部"
+              >
+                <el-option value="true" label="有"></el-option>
+                <el-option value="false" label="无"></el-option>
+              </el-select>
+            </el-form-item>
+          </el-col>
         </el-row>
       </commonFormVue>
       <el-col :span="24">
@@ -169,9 +183,9 @@
                   type="text"
                   >{{ scope.row.dataId }}</el-button
                 >
-                <span v-show="!currentPagePrivileges.SNAPSHOT_DETAILS">{{
-                  scope.row.dataId
-                }}</span>
+                <span v-show="!currentPagePrivileges.SNAPSHOT_DETAILS">
+                  {{ scope.row.dataId }}
+                </span>
               </template>
             </el-table-column>
             <el-table-column
@@ -202,12 +216,24 @@
               prop="courseName"
               width="150"
             ></el-table-column>
+            <el-table-column
+              sortable
+              label="客观题总分"
+              prop="objectiveTotalScore"
+              width="120"
+            ></el-table-column>
             <el-table-column
               sortable
               label="课程层次"
               prop="courseLevel"
               width="120"
             ></el-table-column>
+            <el-table-column
+              sortable
+              label="虚拟设备"
+              prop="virtualCameraNames"
+              width="120"
+            ></el-table-column>
             <el-table-column
               sortable
               label="校验次数"
@@ -294,17 +320,26 @@
         <el-form :model="auditForm" ref="auditForm">
           <el-form-item
             label="违纪类型"
-            prop="disciplineType"
+            prop="illegallyTypeId"
             :rules="[
               { required: true, message: '请选择违纪类型', trigger: 'change' }
             ]"
           >
-            <el-select v-model="auditForm.disciplineType" placeholder="请选择">
+            <el-select
+              v-model="auditForm.illegallyTypeId"
+              filterable
+              remote
+              :remote-method="getDisciplineTypeList"
+              clearable
+              @clear="getDisciplineTypeList"
+              placeholder="请选择"
+              size="small"
+            >
               <el-option
                 v-for="item in disciplineTypeList"
-                :key="item.name"
-                :label="item.desc"
-                :value="item.name"
+                :key="item.id"
+                :label="item.name"
+                :value="item.id"
               ></el-option>
             </el-select>
           </el-form-item>
@@ -329,7 +364,6 @@
 import { mapState } from "vuex";
 import pagePrivilege from "../mixin/pagePrivilege.js";
 import commonFormVue from "../component/commonForm.vue";
-import { DISCIPLINE_TYPE_LIST } from "../constants/constants";
 import _ from "lodash";
 export default {
   mixins: [pagePrivilege],
@@ -358,18 +392,19 @@ export default {
         isWarn: null,
         pageNo: 1,
         pageSize: 10,
-        ORG_FIND_ALL: false //查询所有机构
+        ORG_FIND_ALL: false, //查询所有机构
+        hasVirtual: null
       },
       auditForm: {
         examRecordDataId: null,
-        disciplineType: "",
+        illegallyTypeId: null,
         disciplineDetail: "",
         isPass: null
       },
       getExamCondition: {
         params: {
           name: "",
-          examTypes: "ONLINE",
+          examTypes: "ONLINE#ONLINE_HOMEWORK",
           propertyKeys: "IS_FACE_ENABLE"
         },
         filterCondition: "IS_FACE_ENABLE"
@@ -382,13 +417,25 @@ export default {
         PENDING_OPERATE: false,
         SNAPSHOT_DETAILS: false
       },
-      disciplineTypeList: DISCIPLINE_TYPE_LIST
+      disciplineTypeList: []
     };
   },
   computed: {
     ...mapState({ user: state => state.user })
   },
   methods: {
+    getDisciplineTypeList(name) {
+      if (!name) {
+        name = "";
+      }
+      this.$http
+        .get("/api/ecs_oe_admin/illegallyType/queryByNameLike", {
+          params: { name, queryScope: "audit" }
+        })
+        .then(response => {
+          this.disciplineTypeList = response.data;
+        });
+    },
     resetForm() {
       this.form = {
         examRecordDataId: null,
@@ -508,7 +555,7 @@ export default {
       this.dialogFormVisible = true;
       this.auditForm = {
         examRecordDataId: examRecordDataId,
-        disciplineType: "",
+        illegallyTypeId: null,
         disciplineDetail: "",
         isPass: false
       };
@@ -590,6 +637,7 @@ export default {
   },
   created() {
     this.backFill();
+    this.getDisciplineTypeList("");
   }
 };
 </script>

+ 72 - 14
src/modules/oe/views/captureDetail.vue

@@ -5,11 +5,11 @@
     </el-header>
     <el-main style="overflow: unset;margin-left: 20px;" class="el-main-padding">
       <el-row>
-        <el-col :span="6">
+        <el-col :span="5">
           <img :src="studentBasePhotoPath" alt width="180" />
-          <img :src="syncCapturePhotoPath" alt width="180" class="syncPhto" />
+          <img :src="syncCapturePhotoPath" alt class="syncPhto" />
         </el-col>
-        <el-col :span="18">
+        <el-col :span="19">
           <el-row>
             <el-col :span="8" class="capture-title">
               <span>监考数据ID:{{ examRecordDataId }}</span>
@@ -46,15 +46,28 @@
           <el-row class="margin-top-10">
             <el-col :span="24">
               <el-table :data="examAuditData" border>
+                <el-table-column
+                  sortable
+                  label="学习中心"
+                  prop="orgName"
+                  min-width="110px"
+                ></el-table-column>
+                <el-table-column
+                  sortable
+                  label="年级"
+                  prop="grade"
+                ></el-table-column>
                 <el-table-column
                   sortable
                   label="学号"
                   prop="studentCode"
+                  min-width="110px"
                 ></el-table-column>
                 <el-table-column
                   sortable
                   label="身份证号"
                   prop="identityNumber"
+                  min-width="120px"
                 ></el-table-column>
                 <el-table-column
                   sortable
@@ -65,11 +78,24 @@
                   sortable
                   label="课程代码"
                   prop="courseCode"
+                  min-width="110px"
                 ></el-table-column>
                 <el-table-column
                   sortable
                   label="课程名称"
                   prop="courseName"
+                  min-width="110px"
+                ></el-table-column>
+                <el-table-column sortable label="课程层次" min-width="110px">
+                  <template slot-scope="scope">
+                    <span v-html="getLevel(scope.row.courseLevel)"></span>
+                  </template>
+                </el-table-column>
+                <el-table-column
+                  sortable
+                  label="客观题总分"
+                  prop="objectiveTotalScore"
+                  min-width="150px"
                 ></el-table-column>
               </el-table>
             </el-col>
@@ -166,17 +192,26 @@
         <el-form :model="auditForm" ref="auditForm">
           <el-form-item
             label="违纪类型"
-            prop="disciplineType"
+            prop="illegallyTypeId"
             :rules="[
               { required: true, message: '请选择违纪类型', trigger: 'change' }
             ]"
           >
-            <el-select v-model="auditForm.disciplineType" placeholder="请选择">
+            <el-select
+              v-model="auditForm.illegallyTypeId"
+              filterable
+              remote
+              :remote-method="getDisciplineTypeList"
+              clearable
+              @clear="getDisciplineTypeList"
+              placeholder="请选择"
+              size="small"
+            >
               <el-option
                 v-for="item in disciplineTypeList"
-                :key="item.name"
-                :label="item.desc"
-                :value="item.name"
+                :key="item.id"
+                :label="item.name"
+                :value="item.id"
               ></el-option>
             </el-select>
           </el-form-item>
@@ -200,7 +235,6 @@
 <script>
 import { mapState } from "vuex";
 import LinkTitlesCustom from "@/components/LinkTitlesCustom.vue";
-import { DISCIPLINE_TYPE_LIST } from "../constants/constants";
 export default {
   components: { LinkTitlesCustom },
   data() {
@@ -215,12 +249,12 @@ export default {
       dialogFormVisible: false,
       auditForm: {
         examRecordDataId: null,
-        disciplineType: "",
+        illegallyTypeId: null,
         disciplineDetail: "",
         isPass: null
       },
       currentPaths: ["抓拍详情"],
-      disciplineTypeList: DISCIPLINE_TYPE_LIST,
+      disciplineTypeList: [],
       pendingOperate: false
     };
   },
@@ -228,6 +262,18 @@ export default {
     ...mapState({ user: state => state.user })
   },
   methods: {
+    getDisciplineTypeList(name) {
+      if (!name) {
+        name = "";
+      }
+      this.$http
+        .get("/api/ecs_oe_admin/illegallyType/queryByNameLike", {
+          params: { name, queryScope: "audit" }
+        })
+        .then(response => {
+          this.disciplineTypeList = response.data;
+        });
+    },
     getExamAuditData() {
       var param = new URLSearchParams({
         examRecordDataId: this.examRecordDataId
@@ -289,7 +335,7 @@ export default {
       this.dialogFormVisible = true;
       this.auditForm = {
         examRecordDataId: this.examRecordDataId,
-        disciplineType: "",
+        illegallyTypeId: null,
         disciplineDetail: "",
         isPass: false
       };
@@ -327,6 +373,17 @@ export default {
       } else {
         return value;
       }
+    },
+    getLevel(level) {
+      if (level == "ZSB") {
+        return "专升本";
+      } else if (level == "GQZ") {
+        return "高起专";
+      } else if (level == "GQB") {
+        return "高起本";
+      } else {
+        return "不限";
+      }
     }
   },
   created() {
@@ -342,6 +399,7 @@ export default {
     this.currentPaths = currentPathJson[fromPage];
     this.getExamAuditData();
     this.listExamCapture();
+    this.getDisciplineTypeList("");
   }
 };
 </script>
@@ -404,8 +462,8 @@ export default {
 .syncPhto {
   margin-top: 30px;
   display: block;
-  width: 180px;
-  height: 159px;
+  /* width: 180px;
+  height: 159px; */
 }
 </style>
 <style scoped src="../style/common.css"></style>

+ 60 - 15
src/modules/oe/views/examDetail.vue

@@ -13,6 +13,20 @@
               ></el-input>
             </el-form-item>
           </el-col>
+          <el-col :span="6">
+            <el-form-item label="虚拟设备">
+              <el-select
+                class="form_search_width"
+                size="small"
+                v-model="form.hasVirtual"
+                clearable
+                placeholder="全部"
+              >
+                <el-option value="true" label="有"></el-option>
+                <el-option value="false" label="无"></el-option>
+              </el-select>
+            </el-form-item>
+          </el-col>
           <el-col :span="12">
             <el-form-item label="开考时间">
               <el-date-picker
@@ -87,7 +101,8 @@
               <template slot-scope="scope">
                 <el-button
                   v-show="
-                    scope.row.examType == 'ONLINE' &&
+                    (scope.row.examType == 'ONLINE' ||
+                      scope.row.examType == 'ONLINE_HOMEWORK') &&
                       currentPagePrivileges.SNAPSHOT_DETAILS
                   "
                   @click="gotoCaptureDetail(scope.row.dataId)"
@@ -96,7 +111,8 @@
                 >
                 <span
                   v-show="
-                    scope.row.examType != 'ONLINE' ||
+                    (scope.row.examType != 'ONLINE' &&
+                      scope.row.examType != 'ONLINE_HOMEWORK') ||
                       !currentPagePrivileges.SNAPSHOT_DETAILS
                   "
                   >{{ scope.row.dataId }}</span
@@ -194,6 +210,12 @@
               prop="continuedCount"
               width="120"
             ></el-table-column>
+            <el-table-column
+              sortable
+              label="虚拟设备"
+              prop="virtualCameraNames"
+              width="120"
+            ></el-table-column>
             <el-table-column
               sortable
               :sort-method="sortByPaperTotalScore"
@@ -218,7 +240,8 @@
                 <el-row
                   class="operateRow"
                   v-if="
-                    scope.row.examType == 'ONLINE' &&
+                    (scope.row.examType == 'ONLINE' ||
+                      scope.row.examType == 'ONLINE_HOMEWORK') &&
                       currentPagePrivileges.EXAM_QUERY_GETPAPER
                   "
                 >
@@ -317,17 +340,26 @@
         <el-form :model="auditForm" ref="redoAuditForm">
           <el-form-item
             label="违纪类型"
-            prop="disciplineType"
+            prop="illegallyTypeId"
             :rules="[
               { required: true, message: '请选择违纪类型', trigger: 'change' }
             ]"
           >
-            <el-select v-model="auditForm.disciplineType" placeholder="请选择">
+            <el-select
+              v-model="auditForm.illegallyTypeId"
+              filterable
+              remote
+              :remote-method="getDisciplineTypeList"
+              clearable
+              @clear="getDisciplineTypeList"
+              placeholder="请选择"
+              size="small"
+            >
               <el-option
                 v-for="item in disciplineTypeList"
-                :key="item.name"
-                :label="item.desc"
-                :value="item.name"
+                :key="item.id"
+                :label="item.name"
+                :value="item.id"
               ></el-option>
             </el-select>
           </el-form-item>
@@ -354,7 +386,6 @@
 import { mapState } from "vuex";
 import commonFormVue from "../component/commonForm.vue";
 import commonExportVue from "../component/commonExport.vue";
-import { DISCIPLINE_TYPE_LIST } from "../constants/constants";
 import pagePrivilege from "../mixin/pagePrivilege.js";
 import _ from "lodash";
 export default {
@@ -362,7 +393,7 @@ export default {
   mixins: [pagePrivilege],
   data() {
     return {
-      disciplineTypeList: DISCIPLINE_TYPE_LIST,
+      disciplineTypeList: [],
       total: 0,
       tableLoading: false,
       showAllCondition: false,
@@ -386,13 +417,14 @@ export default {
         startTime: null,
         endTime: null,
         infoCollector: null,
+        hasVirtual: null,
         ORG_FIND_ALL: false //查询所有机构
       },
 
       getExamCondition: {
         params: {
           name: "",
-          examTypes: "ONLINE#OFFLINE"
+          examTypes: "ONLINE#OFFLINE#ONLINE_HOMEWORK"
         },
         filterCondition: ""
       },
@@ -408,7 +440,7 @@ export default {
       dialogAuditFormVisible: false,
       auditForm: {
         examRecordDataId: null,
-        disciplineType: "",
+        illegallyTypeId: null,
         disciplineDetail: "",
         isPass: null
       }
@@ -418,6 +450,18 @@ export default {
     ...mapState({ user: state => state.user })
   },
   methods: {
+    getDisciplineTypeList(name) {
+      if (!name) {
+        name = "";
+      }
+      this.$http
+        .get("/api/ecs_oe_admin/illegallyType/queryByNameLike", {
+          params: { name, queryScope: "audit" }
+        })
+        .then(response => {
+          this.disciplineTypeList = response.data;
+        });
+    },
     resetForm() {
       this.form = {
         examRecordDataId: null,
@@ -533,7 +577,7 @@ export default {
         var redoAuditInfo = {
           examRecordDataIds: [examRecordDataId],
           isPass: true,
-          disciplineType: "",
+          illegallyTypeId: null,
           disciplineDetail: ""
         };
         this.$http
@@ -565,7 +609,7 @@ export default {
           var redoAuditInfo = {
             examRecordDataIds: [this.auditForm.examRecordDataId],
             isPass: false,
-            disciplineType: this.auditForm.disciplineType,
+            illegallyTypeId: this.auditForm.illegallyTypeId,
             disciplineDetail: this.auditForm.disciplineDetail
           };
           this.$http
@@ -599,7 +643,7 @@ export default {
     doRedoAuditNoPassPostProcess() {
       this.auditForm = {
         examRecordDataId: null,
-        disciplineType: "",
+        illegallyTypeId: null,
         disciplineDetail: "",
         isPass: null
       };
@@ -645,6 +689,7 @@ export default {
   created() {
     this.form.rootOrgId = this.user.rootOrgId;
     this.backFill();
+    this.getDisciplineTypeList("");
   }
 };
 </script>

+ 114 - 28
src/modules/oe/views/examScheduling.vue

@@ -6,7 +6,11 @@
           <el-col :span="6">
             <el-form-item label="完成状态">
               <el-select
-                v-if="form.examType == '' || form.examType == 'ONLINE'"
+                v-if="
+                  form.examType == '' ||
+                    form.examType == 'ONLINE' ||
+                    form.examType == 'ONLINE_HOMEWORK'
+                "
                 class="form_search_width"
                 size="small"
                 v-model="form.finished"
@@ -48,32 +52,43 @@
           size="small"
           type="primary"
           icon="el-icon-search"
-        >查询</el-button>
+          >查询</el-button
+        >
         <el-button
           size="small"
           type="primary"
           icon="el-icon-more"
           v-if="!showAllCondition"
           @click="showMoreCondition"
-        >高级查询</el-button>
+          >高级查询</el-button
+        >
         <el-button
           size="small"
           type="primary"
           v-if="showAllCondition"
           @click="showSimpleCondition"
-        >简单查询</el-button>
+          >简单查询</el-button
+        >
         <el-button
           size="small"
           icon="el-icon-refresh"
           @click="resetForm"
           class="margin-bottom-10"
-        >重置</el-button>
+          >重置</el-button
+        >
       </el-col>
       <el-row>
-        <el-col :span="24" v-show="currentPagePrivileges.EXAM_PARTICULARS_EXPORT">
+        <el-col
+          :span="24"
+          v-show="currentPagePrivileges.EXAM_PARTICULARS_EXPORT"
+        >
           <div class="block-seperator"></div>
           <span>操作:</span>
-          <commonExportVue :form="form" :exportUrl="exportUrl" :exportFileName="exportFileName"></commonExportVue>
+          <commonExportVue
+            :form="form"
+            :exportUrl="exportUrl"
+            :exportFileName="exportFileName"
+          ></commonExportVue>
         </el-col>
       </el-row>
       <el-row class="margin-top-10">
@@ -86,18 +101,78 @@
             :data="tableData"
             border
           >
-            <el-table-column sortable label="学习中心" prop="orgName" width="120"></el-table-column>
-            <el-table-column sortable label="姓名" prop="studentName" width="120"></el-table-column>
-            <el-table-column sortable label="身份证号" prop="identityNumber" width="120"></el-table-column>
-            <el-table-column sortable label="学号" prop="studentCode" width="120"></el-table-column>
-            <el-table-column sortable label="课程" prop="courseName" width="120"></el-table-column>
-            <el-table-column sortable label="课程层次" prop="courseLevel" width="120"></el-table-column>
-            <el-table-column sortable label="专业" prop="specialtyName" width="120"></el-table-column>
-            <el-table-column sortable label="已考次数" prop="usedNum" width="120"></el-table-column>
-            <el-table-column sortable label="学生电话" prop="phone" width="120"></el-table-column>
-            <el-table-column sortable label="年级" prop="grade" width="120"></el-table-column>
-            <el-table-column sortable label="采集人" prop="infoCollector" width="120"></el-table-column>
-            <el-table-column sortable label="完成状态" prop="finishedStatus" width="120"></el-table-column>
+            <el-table-column
+              sortable
+              label="学习中心"
+              prop="orgName"
+              width="120"
+            ></el-table-column>
+            <el-table-column
+              sortable
+              label="姓名"
+              prop="studentName"
+              width="120"
+            ></el-table-column>
+            <el-table-column
+              sortable
+              label="身份证号"
+              prop="identityNumber"
+              width="120"
+            ></el-table-column>
+            <el-table-column
+              sortable
+              label="学号"
+              prop="studentCode"
+              width="120"
+            ></el-table-column>
+            <el-table-column
+              sortable
+              label="课程"
+              prop="courseName"
+              width="120"
+            ></el-table-column>
+            <el-table-column
+              sortable
+              label="课程层次"
+              prop="courseLevel"
+              width="120"
+            ></el-table-column>
+            <el-table-column
+              sortable
+              label="专业"
+              prop="specialtyName"
+              width="120"
+            ></el-table-column>
+            <el-table-column
+              sortable
+              label="已考次数"
+              prop="usedNum"
+              width="120"
+            ></el-table-column>
+            <el-table-column
+              sortable
+              label="学生电话"
+              prop="phone"
+              width="120"
+            ></el-table-column>
+            <el-table-column
+              sortable
+              label="年级"
+              prop="grade"
+              width="120"
+            ></el-table-column>
+            <el-table-column
+              sortable
+              label="采集人"
+              prop="infoCollector"
+              width="120"
+            ></el-table-column>
+            <el-table-column
+              sortable
+              label="完成状态"
+              prop="finishedStatus"
+              width="120"
+            ></el-table-column>
             <!-- <el-table-column sortable label="完成状态" width="120">
               <template slot-scope="scope">
                 <span> {{ scope.row.finishedStatus }} </span>
@@ -114,7 +189,8 @@
                       icon="el-icon-view"
                       @click="previewPaper(scope.row.examStudentId)"
                       v-if="scope.row.examType == 'OFFLINE'"
-                    >查看考题</el-button>
+                      >查看考题</el-button
+                    >
                   </el-col>
                 </el-row>
                 <el-row class="operateRow">
@@ -126,7 +202,8 @@
                       icon="el-icon-download"
                       @click="exportPaper(scope.row.examStudentId)"
                       v-if="scope.row.examType == 'OFFLINE'"
-                    >下载考题</el-button>
+                      >下载考题</el-button
+                    >
                   </el-col>
                 </el-row>
                 <el-row class="operateRow">
@@ -141,7 +218,8 @@
                         scope.row.examType == 'OFFLINE' &&
                           scope.row.canUploadAttachment
                       "
-                    >上传作答</el-button>
+                      >上传作答</el-button
+                    >
                   </el-col>
                 </el-row>
                 <el-row class="operateRow">
@@ -156,7 +234,8 @@
                         scope.row.examType == 'OFFLINE' &&
                           scope.row.offlineFileUrl
                       "
-                    >下载作答</el-button>
+                      >下载作答</el-button
+                    >
                   </el-col>
                 </el-row>
               </template>
@@ -195,8 +274,15 @@
               <div>温馨提示:仅支持pdf和zip文件,文件大小请不要超过30M!</div>
             </el-form-item>
             <div class="dialog-footer">
-              <el-button @click="uploadAnswerDialogVisible = false">取 消</el-button>
-              <el-button :disabled="!offlineAnswerFile" type="primary" @click="doUploadAnswer">确 定</el-button>
+              <el-button @click="uploadAnswerDialogVisible = false"
+                >取 消</el-button
+              >
+              <el-button
+                :disabled="!offlineAnswerFile"
+                type="primary"
+                @click="doUploadAnswer"
+                >确 定</el-button
+              >
             </div>
           </el-form>
         </el-dialog>
@@ -243,7 +329,7 @@ export default {
       getExamCondition: {
         params: {
           name: "",
-          examTypes: "ONLINE#OFFLINE"
+          examTypes: "ONLINE#OFFLINE#ONLINE_HOMEWORK"
         },
         filterCondition: ""
       },
@@ -377,13 +463,13 @@ export default {
             var examRecordList = response.data;
             if (examRecordList && examRecordList.length > 0) {
               var basePaperId = examRecordList[0].basePaperId;
-              var rootOrgName = currentUser.rootOrgName;
+              var rootOrgId = currentUser.rootOrgId;
               this.$http
                 .get(
                   "/api/ecs_ques/paper/export/" +
                     basePaperId +
                     "/PAPER/" +
-                    rootOrgName +
+                    rootOrgId +
                     "/" +
                     basePaperId +
                     "/offLine",

+ 82 - 71
src/modules/oe/views/examSummary.vue

@@ -34,13 +34,13 @@
                 :stroke-width="22"
                 :percentage="examSyncPercentage"
                 status="success"
-                style="width:200px;float:left;line-height:38px;"
+                style="width: 200px; float: left; line-height: 38px;"
               ></el-progress>
               <el-button
                 size="small"
                 type="primary"
                 icon="el-icon-refresh"
-                style="float:left;margin-left:20px;margin-top:4px;"
+                style="float: left; margin-left: 20px; margin-top: 4px;"
                 @click="refreshExamSyncPercentage"
                 >刷新</el-button
               >
@@ -62,11 +62,11 @@
           </div>
         </el-col>
       </el-row>
-      <el-row style="margin-top:10px;">
+      <el-row style="margin-top: 10px;">
         <el-col :span="24">
           <el-tabs type="card" v-model="activeName" @tab-click="handleClick">
             <el-tab-pane label="学习中心完成进度" name="first">
-              <el-row style="margin-top:20px;">
+              <el-row style="margin-top: 20px;">
                 <el-col :span="24">
                   <el-form>
                     <el-form-item label="学习中心">
@@ -145,7 +145,7 @@
               </el-row>
             </el-tab-pane>
             <el-tab-pane label="课程完成进度" name="two">
-              <el-row style="margin-top:20px;">
+              <el-row style="margin-top: 20px;">
                 <el-col :span="24">
                   <el-form>
                     <el-form-item label="课程">
@@ -256,11 +256,11 @@ export default {
       pieOptions: {},
       exportOrgLoading: false,
       exportCourseLoading: false,
-      examSyncPercentage: 0
+      examSyncPercentage: 0,
     };
   },
   computed: {
-    ...mapState({ user: state => state.user })
+    ...mapState({ user: (state) => state.user }),
   },
   methods: {
     getExams(examName) {
@@ -269,9 +269,12 @@ export default {
       }
       this.$http
         .get("/api/ecs_exam_work/exam/queryByNameLike", {
-          params: { name: examName, examTypes: "ONLINE#OFFLINE" }
+          params: {
+            name: examName,
+            examTypes: "ONLINE#OFFLINE#ONLINE_HOMEWORK",
+          },
         })
-        .then(response => {
+        .then((response) => {
           this.examList = response.data;
         });
     },
@@ -285,10 +288,10 @@ export default {
           params: {
             name: orgName,
             rootOrgId: rootOrgId,
-            enable: true
-          }
+            enable: true,
+          },
         })
-        .then(response => {
+        .then((response) => {
           this.orgList = response.data;
         });
     },
@@ -303,7 +306,7 @@ export default {
             "&orgId=" +
             this.orgId
         )
-        .then(response => {
+        .then((response) => {
           if (response.data && response.data.length > 0) {
             this.orgExamInfos = response.data;
           } else {
@@ -316,10 +319,10 @@ export default {
         .get("/api/ecs_oe_admin/exam/student/courseProgress/list", {
           params: {
             examId: this.examId,
-            courseId: this.courseId
-          }
+            courseId: this.courseId,
+          },
         })
-        .then(response => {
+        .then((response) => {
           if (response.data && response.data.length > 0) {
             this.courseProgressList = response.data;
             this.buildLine(response.data);
@@ -337,10 +340,10 @@ export default {
         .get("/api/ecs_oe_admin/exam/student/findCoursesByExamIdAndOrgId", {
           params: {
             examId: this.examId,
-            orgId: this.orgId
-          }
+            orgId: this.orgId,
+          },
         })
-        .then(response => {
+        .then((response) => {
           if (response.data && response.data.length > 0) {
             this.courseList = response.data;
           } else {
@@ -349,7 +352,7 @@ export default {
         });
     },
     changeExam(examId) {
-      var exam = this.examList.filter(item => {
+      var exam = this.examList.filter((item) => {
         return item.id == examId;
       })[0];
       this.getPieData(exam.examType);
@@ -358,8 +361,14 @@ export default {
       this.getCourseProgress();
     },
     getPieData(examType) {
-      var completedWord = examType == "ONLINE" ? "已完成:" : "已抽题:";
-      var noCompletedWord = examType == "ONLINE" ? "未完成:" : "未抽题:";
+      var completedWord =
+        examType == "ONLINE" || examType == "ONLINE_HOMEWORK"
+          ? "已完成:"
+          : "已抽题:";
+      var noCompletedWord =
+        examType == "ONLINE" || examType == "ONLINE_HOMEWORK"
+          ? "未完成:"
+          : "未抽题:";
       if (!this.examId) {
         return;
       }
@@ -368,24 +377,24 @@ export default {
           "/api/ecs_oe_admin/exam/student/statistic/by/finished?examId=" +
             this.examId
         )
-        .then(response => {
+        .then((response) => {
           var resp = response.data;
           var optionData = {
             title: "考试人次:" + (resp.finished + resp.unFinished),
             legendData: [
               noCompletedWord + resp.unFinished,
-              completedWord + resp.finished
+              completedWord + resp.finished,
             ],
             seriesData: [
               {
                 name: noCompletedWord + resp.unFinished,
-                value: resp.unFinished
+                value: resp.unFinished,
               },
               {
                 name: completedWord + resp.finished,
-                value: resp.finished
-              }
-            ]
+                value: resp.finished,
+              },
+            ],
           };
           this.buildPieOptions(optionData);
         });
@@ -397,18 +406,18 @@ export default {
         title: {
           text: data.title,
           subtext: "",
-          x: "left"
+          x: "left",
         },
         tooltip: {
           trigger: "item",
-          formatter: "{b}人次<br/>占比:{d}%"
+          formatter: "{b}人次<br/>占比:{d}%",
         },
         legend: {
           type: "scroll",
           orient: "vertical",
           right: 200,
           top: 30,
-          data: data.legendData
+          data: data.legendData,
         },
         series: [
           {
@@ -421,15 +430,15 @@ export default {
               emphasis: {
                 shadowBlur: 10,
                 shadowOffsetX: 0,
-                shadowColor: "rgba(0, 0, 0, 0.5)"
-              }
-            }
-          }
-        ]
+                shadowColor: "rgba(0, 0, 0, 0.5)",
+              },
+            },
+          },
+        ],
       };
     },
     buildLine(courseProgressList) {
-      courseProgressList.sort(function(a, b) {
+      courseProgressList.sort(function (a, b) {
         if (b["completedProportion"] != a["completedProportion"]) {
           return b["completedProportion"] - a["completedProportion"];
         } else if (b["allNum"] != a["allNum"]) {
@@ -451,17 +460,18 @@ export default {
       var seriesBar = {
         name: "计划数",
         type: "bar",
-        data: []
+        data: [],
       };
       var seriesLine1 = {
         name: "完成数",
         type: "line",
-        data: []
+        data: [],
       };
       var seriesLine2 = {
         name: "完成比(%)",
         type: "line",
-        data: []
+        yAxisIndex: 1,
+        data: [],
       };
       var yAxis_maxScale1 = 0;
       for (var i = 0; i < courseProgressDataList.length; i++) {
@@ -477,7 +487,7 @@ export default {
         legendData: ["计划数", "完成数", "完成比(%)"],
         xAxis: { data: xAxisData },
         series: [seriesBar, seriesLine1, seriesLine2],
-        yAxis_maxScale1
+        yAxis_maxScale1,
       };
       this.buildLineOptions(optionData);
     },
@@ -490,29 +500,29 @@ export default {
           axisPointer: {
             type: "cross",
             crossStyle: {
-              color: "#999"
-            }
-          }
+              color: "#999",
+            },
+          },
         },
         toolbox: {
           feature: {
             dataView: { show: true, readOnly: false },
             magicType: { show: true, type: ["line", "bar"] },
             restore: { show: true },
-            saveAsImage: { show: true }
-          }
+            saveAsImage: { show: true },
+          },
         },
         legend: {
-          data: optionData.legendData
+          data: optionData.legendData,
         },
         xAxis: [
           {
             type: "category",
             data: optionData.xAxis.data,
             axisPointer: {
-              type: "shadow"
-            }
-          }
+              type: "shadow",
+            },
+          },
         ],
         yAxis: [
           {
@@ -522,8 +532,8 @@ export default {
             max: optionData.yAxis_maxScale1,
             interval: 10000,
             axisLabel: {
-              formatter: "{value} "
-            }
+              formatter: "{value} ",
+            },
           },
           {
             type: "value",
@@ -532,11 +542,11 @@ export default {
             max: 100,
             interval: 20,
             axisLabel: {
-              formatter: "{value} %"
-            }
-          }
+              formatter: "{value} %",
+            },
+          },
         ],
-        series: optionData.series
+        series: optionData.series,
       };
     },
     sortByFinishedPercent(obj1, obj2) {
@@ -550,16 +560,16 @@ export default {
         .get("/api/ecs_oe_admin/exam/student/statistic/by/org/export", {
           params: {
             examId: this.examId,
-            orgId: this.orgId
+            orgId: this.orgId,
           },
           responseType: "arraybuffer",
-          timeout: 20 * 60 * 1000 //限时20分钟
+          timeout: 20 * 60 * 1000, //限时20分钟
         })
-        .then(response => {
+        .then((response) => {
           if (response.data) {
             var blob = new Blob([response.data], {
               type:
-                "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
+                "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
             });
             var url = URL.createObjectURL(blob);
             var a = document.createElement("a");
@@ -578,16 +588,16 @@ export default {
         .get("/api/ecs_oe_admin/exam/student/courseProgress/list/export", {
           params: {
             examId: this.examId,
-            courseId: this.courseId
+            courseId: this.courseId,
           },
           responseType: "arraybuffer",
-          timeout: 20 * 60 * 1000 //限时20分钟
+          timeout: 20 * 60 * 1000, //限时20分钟
         })
-        .then(response => {
+        .then((response) => {
           if (response.data) {
             var blob = new Blob([response.data], {
               type:
-                "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
+                "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
             });
             var url = URL.createObjectURL(blob);
             var a = document.createElement("a");
@@ -606,18 +616,18 @@ export default {
           title: "警告",
           message: "请选择考试批次",
           type: "warning",
-          duration: 2000
+          duration: 2000,
         });
         return false;
       }
       this.$http
         .get("/api/ecs_oe_admin/examControl/getExamSyncPercentage", {
-          params: { examId: this.examId }
+          params: { examId: this.examId },
         })
-        .then(response => {
+        .then((response) => {
           this.examSyncPercentage = response.data;
         })
-        .catch(res => {
+        .catch((res) => {
           var errorMsg = "操作失败";
           if (res.response && res.response.data) {
             errorMsg = res.response.data.desc;
@@ -625,15 +635,16 @@ export default {
           this.$notify({
             title: "提示",
             message: errorMsg,
-            type: "error"
+            type: "error",
           });
         });
-    }
+    },
   },
   created() {
     this.getExams();
     this.getOrgs();
-  }
+    this.refreshExamSyncPercentage();
+  },
 };
 </script>
 <style>

+ 63 - 10
src/modules/oe/views/illegalityNameList.vue

@@ -5,17 +5,21 @@
         <el-col :span="6">
           <el-form-item label="违纪类型">
             <el-select
-              class="form_search_width"
-              size="small"
               v-model="form.disciplineType"
+              filterable
+              remote
+              :remote-method="getDisciplineTypeList"
               clearable
+              class="form_search_width"
+              @clear="getDisciplineTypeList"
               placeholder="全部"
+              size="small"
             >
               <el-option
                 v-for="item in disciplineTypeList"
-                :key="item.name"
-                :label="item.desc"
-                :value="item.name"
+                :key="item.code"
+                :label="item.name"
+                :value="item.code"
               ></el-option>
             </el-select>
           </el-form-item>
@@ -68,9 +72,9 @@
                   type="text"
                   >{{ scope.row.examRecordDataId }}</el-button
                 >
-                <span v-show="!currentPagePrivileges.SNAPSHOT_DETAILS">{{
-                  scope.row.examRecordDataId
-                }}</span>
+                <span v-show="!currentPagePrivileges.SNAPSHOT_DETAILS">
+                  {{ scope.row.examRecordDataId }}
+                </span>
               </template>
             </el-table-column>
             <el-table-column
@@ -103,6 +107,12 @@
               prop="courseName"
               width="120"
             ></el-table-column>
+            <el-table-column
+              sortable
+              label="客观题总分"
+              prop="objectiveScore"
+              width="120"
+            ></el-table-column>
             <el-table-column
               sortable
               label="课程层次"
@@ -139,6 +149,18 @@
               prop="disciplineType"
               width="120"
             ></el-table-column>
+            <el-table-column
+              sortable
+              label="违纪描述"
+              prop="disciplineDetail"
+              width="120"
+            >
+              <template slot-scope="scope">
+                <span
+                  v-html="disciplineTypeFilter(scope.row.disciplineDetail)"
+                ></span>
+              </template>
+            </el-table-column>
           </el-table>
           <div class="block pull-right">
             <el-pagination
@@ -160,7 +182,6 @@
 import { mapState } from "vuex";
 import commonFormVue from "../component/commonForm.vue";
 import commonExportVue from "../component/commonExport.vue";
-import { DISCIPLINE_TYPE_LIST } from "../constants/constants";
 import pagePrivilege from "../mixin/pagePrivilege.js";
 import _ from "lodash";
 export default {
@@ -168,7 +189,7 @@ export default {
   mixins: [pagePrivilege],
   data() {
     return {
-      disciplineTypeList: DISCIPLINE_TYPE_LIST,
+      disciplineTypeList: [],
       total: 0,
       tableLoading: false,
       exportLoading: false,
@@ -214,6 +235,25 @@ export default {
     ...mapState({ user: state => state.user })
   },
   methods: {
+    getDisciplineTypeList(name) {
+      if (!name) {
+        name = "";
+      }
+      this.$http
+        .get("/api/ecs_oe_admin/illegallyType/queryByNameLike", {
+          params: { name }
+        })
+        .then(response => {
+          if (response.data) {
+            //排除断电和机器故障
+            this.disciplineTypeList = response.data.filter(
+              v =>
+                !(v.rootOrgId == -1 && v.code == "POWER_FAILURE") &&
+                !(v.rootOrgId == -1 && v.code == "MACHINE_STOPPAGE")
+            );
+          }
+        });
+    },
     resetForm() {
       this.form = {
         examRecordDataId: null,
@@ -306,11 +346,24 @@ export default {
         }
         this.search();
       }
+    },
+    disciplineTypeFilter: function(value) {
+      if (value && value.indexOf("&&") > -1) {
+        var arr = value.split("&&");
+        var detail = "";
+        for (var i = 0; i < arr.length; i++) {
+          detail += arr[i] + "<br>";
+        }
+        return detail;
+      } else {
+        return value;
+      }
     }
   },
   created() {
     this.form.rootOrgId = this.user.rootOrgId;
     this.backFill();
+    this.getDisciplineTypeList("");
   }
 };
 </script>

+ 630 - 0
src/modules/oe/views/illegalityType.vue

@@ -0,0 +1,630 @@
+<template>
+  <section class="content">
+    <div
+      class="box-body"
+      v-loading.body="fileLoading"
+      v-loading.fullscreen="loading"
+      element-loading-text="请稍后..."
+    >
+      <el-form :inline="true" :model="formSearch" ref="primaryForm">
+        <el-row>
+          <el-form-item label="违纪类型名称">
+            <el-input
+              class="input_width_lg"
+              placeholder="请输入违纪类型名称"
+              v-model="formSearch.name"
+            />
+          </el-form-item>
+          <el-form-item label="违纪类型代码">
+            <el-input
+              class="input_width_lg"
+              placeholder="请输入违纪类型代码"
+              v-model="formSearch.code"
+            />
+          </el-form-item>
+
+          <el-form-item>
+            <el-button
+              size="small"
+              type="primary"
+              icon="el-icon-search"
+              @click="handleSearchBtn"
+              >查询</el-button
+            >
+            <el-button
+              size="small"
+              @click="resetPrimaryForm"
+              icon="el-icon-refresh"
+              >重置</el-button
+            >
+            <el-button
+              size="small"
+              type="primary"
+              icon="el-icon-plus"
+              @click="insert"
+              >新增</el-button
+            >
+          </el-form-item>
+        </el-row>
+      </el-form>
+
+      <div class="block-seperator"></div>
+
+      <span>操作:</span>
+      <el-button
+        size="small"
+        type="danger"
+        @click="deleteIds"
+        :disabled="noBatchSelected"
+        icon="el-icon-delete"
+        >删除</el-button
+      >
+      <el-button
+        size="small"
+        type="primary"
+        @click="impIllegallyType"
+        icon="el-icon-upload2"
+        >导入</el-button
+      >
+      <el-button
+        size="small"
+        type="primary"
+        @click="exportIllegallyType"
+        icon="el-icon-download"
+        >导出</el-button
+      >
+
+      <div style="width: 100%;margin-bottom: 10px;"></div>
+
+      <!-- 新增或修改弹出框 -->
+      <el-dialog
+        title="违纪类型"
+        width="450px"
+        :visible.sync="illegallyTypeDialog"
+        @close="dialogBeforeClose"
+      >
+        <el-form
+          :inline="true"
+          inline-message
+          :model="illegallyTypeForm"
+          ref="illegallyTypeForm"
+          :rules="rules"
+          label-position="right"
+          label-width="90px"
+        >
+          <el-form-item label="代码" prop="code">
+            <el-input
+              :disabled="null != illegallyTypeForm.id"
+              class="pull_length"
+              v-model="illegallyTypeForm.code"
+              auto-complete="off"
+              placeholder="违纪类型代码"
+              maxlength="100"
+            />
+          </el-form-item>
+          <el-form-item label="名称" prop="name">
+            <el-input
+              class="pull_length"
+              v-model="illegallyTypeForm.name"
+              auto-complete="off"
+              placeholder="违纪类型名称"
+              maxlength="100"
+            />
+          </el-form-item>
+          <el-row class="pull_center">
+            <el-button type="primary" @click="submitForm('illegallyTypeForm')"
+              >保 存</el-button
+            >
+            <el-button @click="close">取 消</el-button>
+          </el-row>
+        </el-form>
+      </el-dialog>
+
+      <!-- 页面列表 -->
+      <el-table
+        :data="tableData"
+        border
+        @selection-change="handleSelectionChange"
+      >
+        <el-table-column
+          type="selection"
+          :selectable="showCheckBox"
+          width="40"
+        ></el-table-column>
+        <el-table-column prop="id" label="ID" width="60"></el-table-column>
+        <el-table-column prop="code" label="违纪类型代码"></el-table-column>
+        <el-table-column prop="name" label="违纪类型名称"></el-table-column>
+        <el-table-column prop="dataCategory" label="数据分类"></el-table-column>
+        <el-table-column label="数据分类">
+          <span slot-scope="scope">
+            <span v-if="scope.row.dataCategory == 'SYSTEM'">
+              <el-tooltip
+                class="item"
+                effect="dark"
+                content="系统数据不可编辑"
+                placement="right"
+              >
+                <el-button>系统</el-button>
+              </el-tooltip>
+            </span>
+            <span v-else>
+              <el-tooltip
+                class="item"
+                effect="dark"
+                content="自定义数据可编辑"
+                placement="right"
+              >
+                <el-button>自定义</el-button>
+              </el-tooltip>
+            </span>
+          </span>
+        </el-table-column>
+        <el-table-column
+          sortable
+          prop="updateTime"
+          label="更新时间"
+          width="170"
+        ></el-table-column>
+        <el-table-column label="操作" width="200">
+          <template slot-scope="scope">
+            <div>
+              <el-button
+                v-show="scope.row.dataCategory != 'SYSTEM'"
+                size="mini"
+                type="primary"
+                icon="el-icon-edit"
+                @click="edit(scope.row)"
+                plain
+                >编辑</el-button
+              >
+              <el-button
+                v-show="scope.row.dataCategory != 'SYSTEM'"
+                size="mini"
+                type="danger"
+                icon="el-icon-delete"
+                @click="deleteId(scope.row)"
+                >删除</el-button
+              >
+            </div>
+          </template>
+        </el-table-column>
+      </el-table>
+      <div class="page pull-right">
+        <el-pagination
+          @current-change="handleCurrentChange"
+          :current-page="currentPage"
+          :page-size="pageSize"
+          :page-sizes="[10, 20, 50, 100, 200, 300]"
+          @size-change="handleSizeChange"
+          layout="total, sizes, prev, pager, next, jumper"
+          :total="total"
+        />
+      </div>
+
+      <!-- 导入弹窗 -->
+      <el-dialog title="导入窗口" width="520px" :visible.sync="impDialog">
+        <el-form>
+          <el-row>
+            <el-form-item style="margin-left:20px">
+              <el-upload
+                class="form_left"
+                ref="upload"
+                accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
+                :action="uploadAction"
+                :headers="uploadHeaders"
+                :data="uploadData"
+                :before-upload="beforeUpload"
+                :on-progress="uploadProgress"
+                :on-success="uploadSuccess"
+                :on-error="uploadError"
+                :file-list="fileList"
+                :auto-upload="false"
+                :multiple="false"
+              >
+                <el-button
+                  size="small"
+                  slot="trigger"
+                  type="primary"
+                  icon="el-icon-search"
+                  >选择文件</el-button
+                >&nbsp;
+                <el-button
+                  size="small"
+                  type="primary"
+                  @click="submitUpload"
+                  icon="el-icon-check"
+                  >确认上传</el-button
+                >
+                <el-button
+                  size="small"
+                  type="primary"
+                  @click="removeFile"
+                  icon="el-icon-refresh"
+                  >清空文件</el-button
+                >
+                <el-button
+                  size="small"
+                  type="primary"
+                  @click="exportFile"
+                  icon="el-icon-download"
+                  >下载模板</el-button
+                >
+                <div slot="tip" class="el-upload__tip">只能上传xlsx文件</div>
+              </el-upload>
+            </el-form-item>
+          </el-row>
+        </el-form>
+      </el-dialog>
+
+      <!-- 导入错误信息列表 -->
+      <el-dialog title="错误提示" :visible.sync="errDialog">
+        <div
+          class="text-danger"
+          v-for="errMessage in errMessages"
+          :key="errMessage.lineNum"
+        >
+          第{{ errMessage.lineNum }}行:{{ errMessage.msg }}
+        </div>
+        <span slot="footer" class="dialog-footer">
+          <el-button @click="errDialog = false">确定</el-button>
+        </span>
+      </el-dialog>
+    </div>
+  </section>
+</template>
+
+<script>
+import { mapState } from "vuex";
+
+export default {
+  name: "illegallyType",
+  data() {
+    return {
+      formSearch: {
+        name: "",
+        code: ""
+      },
+      illegallyTypeForm: {
+        id: null,
+        name: "",
+        code: "",
+        sortNo: 0
+      },
+      illegallyTypeId: "",
+      illegallyTypeDialog: false,
+      loading: false,
+      multipleSelection: [],
+      tableData: [],
+      currentPage: 1,
+      pageSize: 10,
+      total: 10,
+      impDialog: false,
+      uploadAction: "/api/ecs_oe_admin/illegallyType/import",
+      uploadHeaders: {},
+      uploadData: {},
+      errMessages: [],
+      errDialog: false,
+      fileLoading: false,
+      fileList: [],
+      rules: {
+        name: [{ required: true, message: "名称不允许为空", trigger: "blur" }],
+        code: [
+          {
+            required: true,
+            message: "代码不允许为空",
+            trigger: "blur"
+          }
+        ]
+      }
+    };
+  },
+  computed: {
+    ...mapState({
+      user: state => state.user
+    }),
+    noBatchSelected() {
+      return this.multipleSelection.length === 0;
+    }
+  },
+  methods: {
+    dialogBeforeClose() {
+      this.$refs.illegallyTypeForm.clearValidate();
+    },
+    handleSizeChange(val) {
+      this.pageSize = val;
+      this.searchForm();
+    },
+    resetPrimaryForm() {
+      this.formSearch = {
+        name: "",
+        code: ""
+      };
+      this.$refs.primaryForm.resetFields();
+    },
+    handleSearchBtn() {
+      this.currentPage = 1;
+      this.searchForm();
+    },
+    //查询
+    searchForm() {
+      let searchLock = true;
+      setTimeout(() => {
+        if (searchLock) {
+          this.loading = true;
+        }
+      }, 500);
+      var param = new URLSearchParams(this.formSearch);
+      var url =
+        "/api/ecs_oe_admin/illegallyType/illegallyTypePage/" +
+        (this.currentPage - 1) +
+        "/" +
+        this.pageSize +
+        "?" +
+        param;
+      this.$httpWithMsg
+        .get(url)
+        .then(response => {
+          console.log("response :", response);
+          this.tableData = response.data.list;
+          this.total = response.data.total;
+        })
+        .finally(() => {
+          searchLock = false;
+          this.loading = false;
+        });
+    },
+    handleCurrentChange(val) {
+      this.currentPage = val;
+      this.searchForm();
+    },
+    //全选
+    handleSelectionChange(val) {
+      this.multipleSelection = val;
+    },
+    //保存
+    submitForm(formData) {
+      this.$refs[formData].validate(valid => {
+        if (valid) {
+          var url = "/api/ecs_oe_admin/illegallyType";
+          //修改
+          if (null != this.illegallyTypeForm.id) {
+            this.$httpWithMsg.put(url, this.illegallyTypeForm).then(
+              () => {
+                this.$notify({
+                  type: "success",
+                  message: "修改成功!"
+                });
+                this.searchForm();
+                this.illegallyTypeDialog = false;
+              },
+              () => {
+                this.searchForm();
+                this.illegallyTypeDialog = false;
+              }
+            );
+          }
+          //新增
+          else {
+            this.$httpWithMsg.post(url, this.illegallyTypeForm).then(
+              () => {
+                this.$notify({
+                  type: "success",
+                  message: "新增成功!"
+                });
+                this.illegallyTypeDialog = false;
+                this.searchForm();
+              },
+              () => {
+                this.illegallyTypeDialog = false;
+                return this.searchForm();
+              }
+            );
+          }
+        } else {
+          console.log("error submit!");
+          return false;
+        }
+      });
+    },
+
+    //重置
+    resetForm(formData) {
+      this.$refs[formData].resetFields();
+    },
+    close() {
+      this.illegallyTypeDialog = false;
+    },
+    //新增
+    insert() {
+      this.illegallyTypeForm.id = null;
+      this.illegallyTypeForm.name = "";
+      this.illegallyTypeForm.code = "";
+      this.illegallyTypeForm.sortNo = 0;
+
+      this.illegallyTypeDialog = true;
+    },
+    //修改
+    edit(row) {
+      this.illegallyTypeForm = Object.assign({}, row);
+
+      this.illegallyTypeDialog = true;
+    },
+    //删除
+    deleteId(row) {
+      this.$confirm("是否删除该条违纪类型信息?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "error"
+      }).then(() => {
+        var url = "/api/ecs_oe_admin/illegallyType/" + row.id;
+        this.$httpWithMsg.delete(url).then(() => {
+          this.$notify({
+            type: "success",
+            message: "删除成功!"
+          });
+          this.searchForm();
+        });
+      });
+    },
+    //删除多条信息
+    deleteIds() {
+      if (this.multipleSelection.length === 0) {
+        this.$notify({
+          type: "warning",
+          message: "请选择要删除的违纪类型"
+        });
+      } else {
+        this.$confirm("是否删除这些违纪类型信息?", "提示", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "error"
+        }).then(() => {
+          var ids = [];
+          for (var i = 0; i < this.multipleSelection.length; i++) {
+            ids.push(this.multipleSelection[i].id);
+          }
+          var url = "/api/ecs_oe_admin/illegallyType/" + ids;
+          this.$httpWithMsg.delete(url).then(() => {
+            this.$notify({
+              type: "success",
+              message: "删除成功!"
+            });
+            this.searchForm();
+          });
+        });
+      }
+    },
+
+    exportIllegallyType() {
+      let param = new URLSearchParams(this.formSearch);
+      window.open(
+        "/api/ecs_oe_admin/illegallyType/export?$key=" +
+          this.user.key +
+          "&$token=" +
+          this.user.token +
+          "&" +
+          param
+      );
+    },
+    //导入
+    impIllegallyType() {
+      this.impDialog = true;
+      this.initUpload();
+    },
+    initUpload() {
+      this.fileList = [];
+    },
+    beforeUpload(file) {
+      console.log(file);
+    },
+    uploadProgress() {
+      console.log("uploadProgress");
+    },
+    uploadSuccess(response) {
+      if (!response.hasError) {
+        this.$notify({
+          message: "上传成功",
+          type: "success"
+        });
+        this.fileLoading = false;
+        this.impDialog = false;
+        this.searchForm();
+      } else {
+        this.fileLoading = false;
+        this.impDialog = false;
+        this.errMessages = response.failRecords;
+        this.errDialog = true;
+      }
+    },
+    uploadError(response) {
+      var json = JSON.parse(response.message);
+      if (response.status == 500) {
+        this.$notify({
+          message: json.desc,
+          type: "error"
+        });
+      }
+      this.fileLoading = false;
+    },
+    //确定上传
+    submitUpload() {
+      if (!this.checkUpload()) {
+        return false;
+      }
+      this.$refs.upload.submit();
+      this.fileLoading = true;
+    },
+    checkUpload() {
+      var fileList = this.$refs.upload.uploadFiles;
+      if (fileList.length == 0) {
+        this.$notify({
+          message: "上传文件不能为空",
+          type: "error"
+        });
+        return false;
+      }
+      if (fileList.length > 1) {
+        this.$notify({
+          message: "每次只能上传一个文件",
+          type: "error"
+        });
+        return false;
+      }
+      for (let file of fileList) {
+        if (!file.name.endsWith(".xlsx")) {
+          this.$notify({
+            message: "上传文件必须为xlsx格式",
+            type: "error"
+          });
+          this.initUpload();
+          return false;
+        }
+      }
+      return true;
+    },
+    //清空文件
+    removeFile() {
+      // this.fileList = [];
+      this.$refs.upload.clearFiles();
+    },
+    //下载模板
+    exportFile() {
+      window.location.href =
+        "/api/ecs_oe_admin/illegallyType/importTemplate?$key=" +
+        this.user.key +
+        "&$token=" +
+        this.user.token;
+    },
+    showCheckBox(row) {
+      if (row.dataCategory == "SYSTEM") {
+        return false;
+      }
+      return true;
+    }
+  },
+  //初始化查询
+  created() {
+    this.searchForm();
+    this.uploadHeaders = {
+      key: this.user.key,
+      token: this.user.token
+    };
+  }
+};
+</script>
+
+<style scoped>
+.page {
+  margin-top: 10px;
+}
+
+.input_width_lg {
+  width: 180px;
+}
+.pull_center {
+  margin-left: 120px;
+}
+.pull_length {
+  width: 200px;
+}
+</style>

+ 6 - 2
src/modules/oe/views/reexamine.vue

@@ -113,6 +113,8 @@
               type="textarea"
               :autosize="{ minRows: 6, maxRows: 10 }"
               placeholder="请输入内容"
+              maxlength="200"
+              show-word-limit
             ></el-input>
           </el-form-item>
           <div class="dialog-footer margin-top-10 text-center">
@@ -161,7 +163,7 @@ export default {
       getExamCondition: {
         params: {
           name: "",
-          examTypes: "ONLINE"
+          examTypes: "ONLINE#ONLINE_HOMEWORK"
         },
         filterCondition: ""
       },
@@ -255,7 +257,9 @@ export default {
       this.$refs["reexamineForm"].validate(valid => {
         if (valid) {
           var param = new URLSearchParams({
-            examStudentId: this.reexamineForm.examStudentId
+            examStudentId: this.reexamineForm.examStudentId,
+            reexamineType: this.reexamineForm.reexamineType,
+            reexamineDetail: this.reexamineForm.reexamineDetail
           });
           this.$http
             .post("/api/ecs_oe_admin/exam/student/reexamine", param)

+ 1 - 3
src/modules/oe/views/scoreStatistics.vue

@@ -223,14 +223,12 @@
 import { mapState } from "vuex";
 import commonFormVue from "../component/commonForm.vue";
 //import commonExportVue from "../component/commonExport.vue";
-import { DISCIPLINE_TYPE_LIST } from "../constants/constants";
 import pagePrivilege from "../mixin/pagePrivilege.js";
 export default {
   components: { commonFormVue },
   mixins: [pagePrivilege],
   data() {
     return {
-      disciplineTypeList: DISCIPLINE_TYPE_LIST,
       total: 0,
       tableLoading: false,
       dialogExportTypeVisible: false,
@@ -261,7 +259,7 @@ export default {
       getExamCondition: {
         params: {
           name: "",
-          examTypes: "ONLINE#OFFLINE"
+          examTypes: "ONLINE#OFFLINE#ONLINE_HOMEWORK"
         },
         filterCondition: ""
       },

+ 2 - 1
src/modules/questions/constants/constants.js

@@ -19,7 +19,8 @@ export const PUBLICITY_LIST = [
 export const EXAM_TYPES = [
   { value: "TRADITION", label: "传统考试" },
   { value: "ONLINE", label: "网络考试" },
-  { value: "PRACTICE", label: "在线练习" }
+  { value: "PRACTICE", label: "在线练习" },
+  { value: "ONLINE_HOMEWORK", label: "在线作业" }
 ];
 export const EXPORT_TYPES = [
   { value: "ONLINE", label: "机考" },

+ 115 - 112
src/modules/questions/views/EditPaper.vue

@@ -98,7 +98,7 @@
           </el-table-column>
         </el-table>
 
-        <div class="mainQues" style="margin-top:20px;margin-left:0px;">
+        <div class="mainQues" style="margin-top: 20px; margin-left: 0px;">
           <div class="mainQuesTitle">
             <span>考试说明:</span>
             <span>
@@ -106,7 +106,7 @@
                 >编辑</el-button
               >
             </span>
-            <div style="width:550px;margin-left:20px;margin-top:20px;">
+            <div style="width: 550px; margin-left: 20px; margin-top: 20px;">
               <span v-html="paper.examRemark"></span>
             </div>
           </div>
@@ -467,7 +467,7 @@
                   </div>
                   <span>
                     <el-tag
-                      style="margin-right:5px;"
+                      style="margin-right: 5px;"
                       :key="content.id"
                       :closable="!updatePorperty"
                       type="primary"
@@ -546,7 +546,7 @@
                 <el-button
                   type="primary"
                   @click="insertProperty"
-                  style="margin-left:-50px;"
+                  style="margin-left: -50px;"
                   :disabled="updatePorperty"
                   ><i class="el-icon-plus"></i>新增属性
                 </el-button>
@@ -594,9 +594,9 @@
             <div
               v-if="
                 quesModel.questionType != 'NESTED_ANSWER_QUESTION' &&
-                  quesModel.questionType != 'SINGLE_ANSWER_QUESTION' &&
-                  quesModel.questionType != 'MULTIPLE_ANSWER_QUESTION' &&
-                  quesModel.questionType != 'BOOL_ANSWER_QUESTION'
+                quesModel.questionType != 'SINGLE_ANSWER_QUESTION' &&
+                quesModel.questionType != 'MULTIPLE_ANSWER_QUESTION' &&
+                quesModel.questionType != 'BOOL_ANSWER_QUESTION'
               "
             >
               <el-form-item label="答案">
@@ -607,7 +607,7 @@
             <div
               v-if="
                 quesModel.questionType == 'SINGLE_ANSWER_QUESTION' ||
-                  quesModel.questionType == 'MULTIPLE_ANSWER_QUESTION'
+                quesModel.questionType == 'MULTIPLE_ANSWER_QUESTION'
               "
             >
               <el-form-item label="答案">
@@ -645,7 +645,7 @@
                 paper.paperType == 'IMPORT' &&
                 (quesModel.questionType == 'SINGLE_ANSWER_QUESTION' ||
                   quesModel.questionType == 'MULTIPLE_ANSWER_QUESTION')
-              )
+              ),
             }"
           >
             <el-button
@@ -653,8 +653,8 @@
               @click="addQuesOption"
               v-if="
                 paper.paperType == 'IMPORT' &&
-                  (quesModel.questionType == 'SINGLE_ANSWER_QUESTION' ||
-                    quesModel.questionType == 'MULTIPLE_ANSWER_QUESTION')
+                (quesModel.questionType == 'SINGLE_ANSWER_QUESTION' ||
+                  quesModel.questionType == 'MULTIPLE_ANSWER_QUESTION')
               "
               ><i class="el-icon-plus"></i> 新增选项
             </el-button>
@@ -671,7 +671,7 @@
           <el-row :gutter="10">
             <el-col :xs="10" :sm="10" :md="10" :lg="10">
               <el-form-item label="考试说明">
-                <div style="width:550px;">
+                <div style="width: 550px;">
                   <ckeditor
                     :display="display"
                     :width="wValue"
@@ -682,7 +682,7 @@
               </el-form-item>
             </el-col>
           </el-row>
-          <div style="margin-top:20px;margin-left:40%">
+          <div style="margin-top: 20px; margin-left: 40%;">
             <el-button type="primary" @click="savePaperRemark">保存</el-button>
             <el-button @click="closPaperRemark">取消</el-button>
           </div>
@@ -720,8 +720,8 @@
         </form>
         <div style="margin-top: 20px;" v-if="checkResult">
           <span>检查结果:</span><br /><br />
-          <span style="color: #13CE66;" v-show="message == 'OK!'">OK!</span>
-          <span style="color: #FF4949;" v-show="message != 'OK!'">{{
+          <span style="color: #13ce66;" v-show="message == 'OK!'">OK!</span>
+          <span style="color: #ff4949;" v-show="message != 'OK!'">{{
             message
           }}</span>
         </div>
@@ -742,7 +742,7 @@ export default {
   name: "editPaperApp",
   components: {
     reduplicate_mark,
-    ckeditor
+    ckeditor,
   },
   data() {
     return {
@@ -761,9 +761,9 @@ export default {
       paper: {
         course: {
           code: "",
-          name: ""
+          name: "",
         },
-        examRemark: ""
+        examRemark: "",
       },
       loading: false,
       dialogLoading: false,
@@ -805,7 +805,7 @@ export default {
         "SlateBlue",
         "SlateGray",
         "Tomato",
-        "VioletRed"
+        "VioletRed",
       ],
       difficultyDegreeList: [
         { label: 0.1, value: 0.1 },
@@ -817,15 +817,15 @@ export default {
         { label: 0.7, value: 0.7 },
         { label: 0.8, value: 0.8 },
         { label: 0.9, value: 0.9 },
-        { label: 1.0, value: 1.0 }
+        { label: 1.0, value: 1.0 },
       ],
       publicityList: [
         { label: "公开", value: true },
-        { label: "非公开", value: false }
+        { label: "非公开", value: false },
       ],
       answerTypes: [
         { label: "文本", value: "DIVERSIFIED_TEXT" },
-        { label: "音频", value: "SINGLE_AUDIO" }
+        { label: "音频", value: "SINGLE_AUDIO" },
       ],
       coursePropertyList: [],
       coursePropertyName: "", //课程属性名
@@ -835,7 +835,7 @@ export default {
       secondPropertyId: "", //二级属性id
       examRemark: "",
       showQuestions: [],
-      showButtons: []
+      showButtons: [],
     };
   },
   methods: {
@@ -872,7 +872,7 @@ export default {
           "/" +
           this.paperDetailId +
           "/" +
-          this.parentView
+          this.parentView,
       });
     },
     //打开编辑大题题目弹窗
@@ -894,7 +894,7 @@ export default {
         .then(() => {
           this.$notify({
             message: "保存成功",
-            type: "success"
+            type: "success",
           });
           this.detailLoading = false;
           this.closePaperDatailDialog();
@@ -909,60 +909,63 @@ export default {
       this.paper = {
         course: {
           code: "",
-          name: ""
-        }
+          name: "",
+        },
       };
-      this.$http.get(QUESTION_API + "/paper/" + this.paperId).then(response => {
-        this.paper = response.data;
-        //查询所有课程属性名
-        this.initCourseProperty(this.paper.course.code);
-        //将所有小题分为公开和非公开
-        if (this.paper.paperDetails && this.paper.paperDetails.length > 0) {
-          for (let paperDetil of this.paper.paperDetails) {
-            this.showQuestions.push({ is_show: true });
-            this.showButtons.push({ up: true });
-            paperDetil.pubCount = 0;
-            paperDetil.noPubCount = 0;
-            if (
-              paperDetil.paperDetailUnits &&
-              paperDetil.paperDetailUnits.length > 0
-            ) {
-              for (let paperDetilUt of paperDetil.paperDetailUnits) {
-                if (
-                  paperDetilUt.question.questionType != "NESTED_ANSWER_QUESTION"
-                ) {
-                  //非套题
-                  if (paperDetilUt.question.publicity) {
-                    paperDetil.pubCount = paperDetil.pubCount + 1;
-                  } else {
-                    paperDetil.noPubCount = paperDetil.noPubCount + 1;
-                  }
-                } else {
-                  //循环所有子题
-                  for (let ques of paperDetilUt.question.subQuestions) {
-                    if (ques.publicity) {
+      this.$http
+        .get(QUESTION_API + "/paper/" + this.paperId)
+        .then((response) => {
+          this.paper = response.data;
+          //查询所有课程属性名
+          this.initCourseProperty(this.paper.course.code);
+          //将所有小题分为公开和非公开
+          if (this.paper.paperDetails && this.paper.paperDetails.length > 0) {
+            for (let paperDetil of this.paper.paperDetails) {
+              this.showQuestions.push({ is_show: true });
+              this.showButtons.push({ up: true });
+              paperDetil.pubCount = 0;
+              paperDetil.noPubCount = 0;
+              if (
+                paperDetil.paperDetailUnits &&
+                paperDetil.paperDetailUnits.length > 0
+              ) {
+                for (let paperDetilUt of paperDetil.paperDetailUnits) {
+                  if (
+                    paperDetilUt.question.questionType !=
+                    "NESTED_ANSWER_QUESTION"
+                  ) {
+                    //非套题
+                    if (paperDetilUt.question.publicity) {
                       paperDetil.pubCount = paperDetil.pubCount + 1;
                     } else {
                       paperDetil.noPubCount = paperDetil.noPubCount + 1;
                     }
+                  } else {
+                    //循环所有子题
+                    for (let ques of paperDetilUt.question.subQuestions) {
+                      if (ques.publicity) {
+                        paperDetil.pubCount = paperDetil.pubCount + 1;
+                      } else {
+                        paperDetil.noPubCount = paperDetil.noPubCount + 1;
+                      }
+                    }
                   }
                 }
               }
             }
           }
-        }
-        setTimeout(() => {
-          document.documentElement.scrollTop = document.body.scrollTop = scrollPosition;
-          console.log(scrollPosition);
-        }, 1000);
-        this.loading = false;
-      });
+          setTimeout(() => {
+            document.documentElement.scrollTop = document.body.scrollTop = scrollPosition;
+            console.log(scrollPosition);
+          }, 1000);
+          this.loading = false;
+        });
     },
     //查询所有课程属性名
     initCourseProperty(courseCode) {
       this.$http
         .get(QUESTION_API + "/courseProperty/enable/" + courseCode)
-        .then(response => {
+        .then((response) => {
           this.coursePropertyList = response.data;
         });
     },
@@ -981,7 +984,7 @@ export default {
       if (count == 0) {
         this.$alert("您确定删除吗?", "提示", {
           confirmButtonText: "确定",
-          callback: action => {
+          callback: (action) => {
             if (action == "confirm") {
               this.loading = true;
               this.$http
@@ -991,17 +994,17 @@ export default {
                   this.loading = true;
                   this.$notify({
                     message: "删除成功",
-                    type: "success"
+                    type: "success",
                   });
                   this.loading = false;
                 });
             }
-          }
+          },
         });
       } else {
         this.$alert("大题下还有小题,不可删除!", "提示", {
           confirmButtonText: "确定",
-          callback: () => {}
+          callback: () => {},
         });
       }
     },
@@ -1167,7 +1170,7 @@ export default {
           if (courseProperty.name == this.coursePropertyName) {
             this.$http
               .get(QUESTION_API + "/property/first/" + courseProperty.id)
-              .then(response => {
+              .then((response) => {
                 this.firstPropertyList = response.data;
               });
           }
@@ -1180,7 +1183,7 @@ export default {
       if (this.firstPropertyId) {
         this.$http
           .get(QUESTION_API + "/property/second/" + this.firstPropertyId)
-          .then(response => {
+          .then((response) => {
             this.secondPropertyList = response.data;
           });
       }
@@ -1194,7 +1197,7 @@ export default {
         id: "",
         coursePropertyName: "",
         firstProperty: {},
-        secondProperty: {}
+        secondProperty: {},
       };
       if (
         this.quesModel.quesProperties == null ||
@@ -1216,7 +1219,7 @@ export default {
         if (quesPro.id == quesProperty.id) {
           this.$notify({
             message: "该属性已存在,请重新选择",
-            type: "error"
+            type: "error",
           });
           return false;
         }
@@ -1236,7 +1239,7 @@ export default {
         if (!this.secondPropertyId) {
           this.$notify({
             message: "请选择二级属性",
-            type: "error"
+            type: "error",
           });
           return false;
         }
@@ -1261,14 +1264,14 @@ export default {
       if (!this.coursePropertyName) {
         this.$notify({
           message: "请选择属性",
-          type: "error"
+          type: "error",
         });
         return false;
       }
       if (!this.firstPropertyId) {
         this.$notify({
           message: "请选择一级属性",
-          type: "error"
+          type: "error",
         });
         return false;
       }
@@ -1303,7 +1306,7 @@ export default {
       this.quesModel.quesOptions.push({
         number: "",
         optionBody: "",
-        isCorrect: ""
+        isCorrect: "",
       });
       for (var i = 0; i < this.quesModel.quesOptions.length; i++) {
         this.quesModel.quesOptions[i]["number"] = i + 1;
@@ -1327,14 +1330,14 @@ export default {
       } else {
         this.$notify({
           message: "分数只能为正数",
-          type: "error"
+          type: "error",
         });
         return;
       }
       let paperDetailUnitExp = {
         id: this.editPaperDetailUnit.id,
         question: this.quesModel,
-        score: this.quesModel.score
+        score: this.quesModel.score,
       };
       if (
         this.quesModel.quesOptions &&
@@ -1343,12 +1346,12 @@ export default {
         this.$confirm("无选项将删除该试题, 是否继续?", "提示", {
           confirmButtonText: "确定",
           cancelButtonText: "取消",
-          type: "warning"
+          type: "warning",
         }).then(() => {
           this.dialogLoading = true;
           this.$http
             .delete(QUESTION_API + "/paper/deleteQuestion/" + this.quesModel.id)
-            .then(response => {
+            .then((response) => {
               if (response.data.length > 0) {
                 var deleteInfo =
                   "该试题被试卷:" +
@@ -1356,12 +1359,12 @@ export default {
                   "使用,不能删除";
                 this.$notify({
                   message: deleteInfo,
-                  type: "error"
+                  type: "error",
                 });
               } else {
                 this.$notify({
                   message: "保存成功",
-                  type: "success"
+                  type: "success",
                 });
               }
               this.dialogLoading = false;
@@ -1374,7 +1377,7 @@ export default {
           .then(() => {
             this.$notify({
               message: "保存成功",
-              type: "success"
+              type: "success",
             });
             this.dialogLoading = false;
             this.closeQuesDialog();
@@ -1416,7 +1419,7 @@ export default {
     deleteQues01(paperDetailUnitId) {
       this.$alert("您确定删除吗?", "提示", {
         confirmButtonText: "确定",
-        callback: action => {
+        callback: (action) => {
           if (action == "confirm") {
             this.loading = true;
             this.$http
@@ -1428,23 +1431,23 @@ export default {
                 this.loading = true;
                 this.$notify({
                   message: "删除成功",
-                  type: "success"
+                  type: "success",
                 });
                 this.loading = false;
               });
           }
-        }
+        },
       });
     },
     deleteQues02(questionId) {
       this.$alert("您确定删除吗?", "提示", {
         confirmButtonText: "确定",
-        callback: action => {
+        callback: (action) => {
           if (action == "confirm") {
             this.loading = true;
             this.$http
               .delete(QUESTION_API + "/paper/deleteQuestion/" + questionId)
-              .then(response => {
+              .then((response) => {
                 if (response.data.length > 0) {
                   var deleteInfo =
                     "该试题被试卷:" +
@@ -1452,7 +1455,7 @@ export default {
                     "使用,不能删除";
                   this.$notify({
                     message: deleteInfo,
-                    type: "error"
+                    type: "error",
                   });
                 } else {
                   this.initPaper();
@@ -1461,13 +1464,13 @@ export default {
                   this.loading = true;
                   this.$notify({
                     message: "保存成功",
-                    type: "success"
+                    type: "success",
                   });
                 }
                 this.loading = false;
               });
           }
-        }
+        },
       });
     },
     //获取重复试题
@@ -1475,7 +1478,7 @@ export default {
       this.duplicateLoading = true;
       this.$http
         .get(QUESTION_API + "/paper/" + this.paperId + "/reduplicate-questions")
-        .then(response => {
+        .then((response) => {
           this.reduplicateQuestions = response.data;
           this.duplicateLoading = false;
           this.initReduplicateQuesColor();
@@ -1488,7 +1491,7 @@ export default {
       if (colorCount > 20) {
         this.reduplicateQuesColor = randomColor({
           luminosity: "bright",
-          count: colorCount
+          count: colorCount,
         });
       } else {
         this.reduplicateQuesColor = this.defaultColor;
@@ -1525,38 +1528,38 @@ export default {
         .then(() => {
           this.$notify({
             message: "保存成功",
-            type: "success"
+            type: "success",
           });
           this.loading = false;
           this.initPaper();
         })
-        .catch(error => {
+        .catch((error) => {
           this.loading = false;
           this.$notify({
             type: "error",
-            message: error.body.msg
+            message: error.response.data.desc,
           });
         });
     },
     //删除试卷
     deletePaper(id) {
       this.$confirm("确认删除试卷吗?", "提示", {
-        type: "warning"
+        type: "warning",
       }).then(() => {
         this.loading = true;
         this.$http.delete(QUESTION_API + "/paper/" + id).then(
           () => {
             this.$notify({
               message: "删除成功",
-              type: "success"
+              type: "success",
             });
             this.back();
           },
-          error => {
+          (error) => {
             this.$notify({
-              message: error.response.data.msg,
+              message: error.response.data.desc,
               type: "error",
-              title: "错误"
+              title: "错误",
             });
             this.loading = false;
           }
@@ -1581,11 +1584,11 @@ export default {
     back() {
       if (sessionStorage.getItem("question_back") == "true") {
         this.$router.push({
-          path: "/questions/" + this.parentView + "/0"
+          path: "/questions/" + this.parentView + "/0",
         });
       } else {
         this.$router.push({
-          path: "/questions/" + this.parentView + "/1"
+          path: "/questions/" + this.parentView + "/1",
         });
       }
     },
@@ -1638,7 +1641,7 @@ export default {
           QUESTION_API + "/checkRadioFile/" + this.paperId,
           this.fileNameList
         )
-        .then(response => {
+        .then((response) => {
           console.log("response:", response);
           this.message = response.data.errorMsg;
           if (this.message == "OK") {
@@ -1648,7 +1651,7 @@ export default {
             this.isUpload = true;
           }
         })
-        .catch(error => {
+        .catch((error) => {
           console.log(error);
         });
     },
@@ -1662,7 +1665,7 @@ export default {
         param.append("files", file, file.name);
       }
       let config = {
-        headers: { "Content-Type": "multipart/form-data" }
+        headers: { "Content-Type": "multipart/form-data" },
       };
       this.$http
         .post(QUESTION_API + "/uploadRadio/" + this.paperId, param, config)
@@ -1674,15 +1677,15 @@ export default {
           document.getElementById("radioFile").value = "";
           this.initPaper();
         })
-        .catch(error => {
+        .catch((error) => {
           this.message = error.response.data.desc;
           this.uploadAudioLoading = false;
         });
-    }
+    },
   },
   computed: {
     ...mapState({
-      user: state => state.user
+      user: (state) => state.user,
     }),
     updatePorperty() {
       if (this.parentView === "gen_paper") {
@@ -1698,7 +1701,7 @@ export default {
         return obj.sort().toString();
       }
       return this.quesModel.quesAnswer;
-    }
+    },
   },
   watch: {},
   created() {
@@ -1711,10 +1714,10 @@ export default {
     this.uploadAction = QUESTION_API + "/uploadRadio/" + this.paperId;
     this.uploadHeaders = {
       key: this.user.key,
-      token: this.user.token
+      token: this.user.token,
     };
   },
-  mounted() {}
+  mounted() {},
 };
 </script>
 <style scoped src="../styles/EditPaper.css">

+ 148 - 0
src/modules/questions/views/ExportTemplate.vue

@@ -13,6 +13,8 @@
             <el-form-item v-if="isSuperAdmin" label="学校">
               <el-select
                 v-model="formSearch.rootOrgId"
+                clearable
+                filterable
                 placeholder="请选择"
                 class="search_width"
                 size="small"
@@ -71,6 +73,14 @@
               >
                 新增
               </el-button>
+              <el-button
+                size="small"
+                type="primary"
+                icon="el-icon-edit"
+                @click="operConfig"
+              >
+                配置
+              </el-button>
             </div>
           </el-col>
         </el-row>
@@ -236,6 +246,50 @@
         </el-row>
       </el-form>
     </el-dialog>
+    <el-dialog
+      title="配置信息"
+      width="550px"
+      :visible.sync="configModel"
+      :close-on-click-modal="false"
+      @close="closeConfigModel"
+    >
+      <el-form
+        :inline="true"
+        :model="configForm"
+        ref="configForm"
+        :rules="configRules"
+        label-width="90px"
+        :key="configModelKey"
+      >
+        <el-row class="form-row" v-if="isSuperAdmin">
+          <el-form-item label="学校名称">
+            <el-input
+              disabled="true"
+              class="pull-length"
+              v-model="configForm.orgName"
+            ></el-input>
+          </el-form-item>
+        </el-row>
+        <el-row class="form-row">
+          <el-form-item label="配置名称" prop="serviceName">
+            <el-input
+              class="pull-length"
+              placeholder="请输入serviceName"
+              v-model="configForm.serviceName"
+            ></el-input>
+          </el-form-item>
+        </el-row>
+        <el-row class="pull-center">
+          <el-button
+            type="primary"
+            @click="subConfig"
+            :loading="this.configForm.loading"
+            >确定</el-button
+          >
+          <el-button @click="closeConfigModel">取消</el-button>
+        </el-row>
+      </el-form>
+    </el-dialog>
   </section>
 </template>
 <script>
@@ -265,6 +319,8 @@ export default {
       loading: false,
       fileModel: false,
       fileModelKey: Math.random(),
+      configModel: false,
+      configModelKey: Math.random(),
       paginationShow: false,
       formSearch: {
         rootOrgId: null,
@@ -278,6 +334,11 @@ export default {
         dataFile: null,
         loading: false
       },
+      configForm: {
+        serviceName: null,
+        orgName: null,
+        loading: false
+      },
       tableData: [],
       currentPage: 1,
       pageSize: 10,
@@ -317,6 +378,21 @@ export default {
             trigger: "change"
           }
         ]
+      },
+      configRules: {
+        serviceName: [
+          {
+            required: true,
+            type: "string",
+            message: "请输入配置名称",
+            trigger: "change"
+          },
+          {
+            pattern: /^[^\\/\\?%#&=\\+]*$/,
+            message: "名称不能包含特殊字符 / ? % # & = +",
+            trigger: "change"
+          }
+        ]
       }
     };
   },
@@ -396,6 +472,33 @@ export default {
       }
       this.fileModel = true;
     },
+    operConfig() {
+      if (this.formSearch.rootOrgId == null) {
+        this.$notify({
+          type: "warning",
+          message: "请选择学校"
+        });
+        return;
+      }
+      this.loading = true;
+      var url =
+        QUESTION_API + "/exportTemplate/config/" + this.formSearch.rootOrgId;
+      this.$httpWithMsg
+        .get(url)
+        .then(response => {
+          this.configForm.serviceName = response.data.exportServiceName;
+          if (this.isSuperAdmin) {
+            for (const org of this.rootOrgList) {
+              if (this.formSearch.rootOrgId == org.id) {
+                this.configForm.orgName = org.name;
+                break;
+              }
+            }
+          }
+          this.configModel = true;
+        })
+        .finally(() => (this.loading = false));
+    },
     async subFile() {
       const res = await this.$refs.fileForm.validate();
 
@@ -427,6 +530,30 @@ export default {
         })
         .finally(() => (this.fileForm.loading = false));
     },
+    async subConfig() {
+      const res = await this.$refs.configForm.validate();
+
+      if (res === false) {
+        return;
+      }
+      this.configForm.loading = true;
+      var params = "?serviceName=" + this.configForm.serviceName;
+      var url =
+        QUESTION_API +
+        "/exportTemplate/config/" +
+        this.formSearch.rootOrgId +
+        params;
+      this.$httpWithMsg
+        .put(url)
+        .then(() => {
+          this.$notify({
+            type: "success",
+            message: "配置成功!"
+          });
+          this.closeConfigModel();
+        })
+        .finally(() => (this.configForm.loading = false));
+    },
     closeFileModel() {
       this.fileModel = false;
       this.$refs.fileForm.resetFields();
@@ -436,6 +563,13 @@ export default {
       this.fileForm.dataFile = null;
       this.fileForm.templateName = null;
     },
+    closeConfigModel() {
+      this.configModel = false;
+      this.$refs.configForm.resetFields();
+      this.configModelKey = Math.random();
+      this.configForm.orgName = null;
+      this.configForm.serviceName = null;
+    },
     handleSearchBtn() {
       this.currentPage = 1;
       this.searchForm();
@@ -491,6 +625,20 @@ export default {
       }
     }
   },
+  watch: {
+    "formSearch.rootOrgId": {
+      immediate: false,
+      handler(val) {
+        if (val == null) {
+          this.curDir = "";
+        } else {
+          this.curDir = "/";
+          this.formSearch.parentId = -1;
+          this.handleSearchBtn();
+        }
+      }
+    }
+  },
   //初始化查询
   created() {
     this.init();

+ 2 - 2
src/modules/questions/views/ExtractPaperRule.vue

@@ -561,7 +561,7 @@ export default {
                 window.location.href =
                   QUESTION_API +
                   "/exportSingleExamPaperInfo/" +
-                  this.user.rootOrgName +
+                  this.user.rootOrgId +
                   "/" +
                   exportWay +
                   "/" +
@@ -582,7 +582,7 @@ export default {
                 window.location.href =
                   QUESTION_API +
                   "/exportBatchExamPaperInfo/" +
-                  this.user.rootOrgName +
+                  this.user.rootOrgId +
                   "/" +
                   exportWay +
                   "/" +

+ 50 - 50
src/modules/questions/views/GenPaper.vue

@@ -22,7 +22,7 @@
                 clearable
                 placeholder="全部"
                 size="small"
-                @focus="e => getCourses(e.target.value)"
+                @focus="(e) => getCourses(e.target.value)"
               >
                 <el-option
                   v-for="item in courseInfoSelect"
@@ -83,14 +83,14 @@
         <el-row>
           <el-form-item>
             <span>批量操作:</span>
-            <!-- <el-button
+            <el-button
               size="small"
               type="danger"
               @click="batchDeleteGenPaper"
               :disabled="noBatchSelected"
             >
               <i class="el-icon-delete"></i> 删除成卷
-            </el-button> -->
+            </el-button>
             <el-button
               size="small"
               type="primary"
@@ -115,13 +115,13 @@
           </el-form-item>
         </el-row>
       </el-form>
-      <div style="width: 100%;margin-bottom: 10px;"></div>
+      <div style="width: 100%; margin-bottom: 10px;"></div>
       <el-table
         v-loading="loading"
         element-loading-text="拼命加载中"
         :data="tableData"
         border
-        style="width: 100%"
+        style="width: 100%;"
         @selection-change="selectChange"
       >
         <el-table-column type="selection" width="40"></el-table-column>
@@ -282,7 +282,7 @@
                   v-model="printExamPackagePassword"
                   placeholder="加密密码 (可选)"
                   type="password"
-                  style="width: 150px"
+                  style="width: 150px;"
                 ></el-input>
               </el-checkbox-group>
             </el-form-item>
@@ -442,7 +442,7 @@ export default {
         { label: 0.7, value: 0.7 },
         { label: 0.8, value: 0.8 },
         { label: 0.9, value: 0.9 },
-        { label: 1.0, value: 1.0 }
+        { label: 1.0, value: 1.0 },
       ],
       publicityList: PUBLICITY_LIST,
       isClear: 0,
@@ -451,7 +451,7 @@ export default {
         courseNo: "",
         courseName: "",
         level: "",
-        name: ""
+        name: "",
       },
       tableData: [],
       currentPage: 1,
@@ -465,7 +465,7 @@ export default {
       fileList: [],
       uploadAction: "",
       formUpload: {
-        paperName: ""
+        paperName: "",
       },
       uploadData: {},
       fileLoading: false,
@@ -474,7 +474,7 @@ export default {
         id: "",
         courseCode: "",
         courseName: "",
-        exportContentList: []
+        exportContentList: [],
       },
       isShow: true,
       examList: [],
@@ -485,11 +485,11 @@ export default {
       isShowPrintExamPackagePassword: false,
       printExamPackagePassword: "",
       printFrom: {
-        examId: ""
+        examId: "",
       },
       rules: {
-        examId: [{ required: true, message: "请输入名称", trigger: "change" }]
-      }
+        examId: [{ required: true, message: "请输入名称", trigger: "change" }],
+      },
     };
   },
   methods: {
@@ -498,7 +498,7 @@ export default {
         this.$notify({
           title: "警告",
           message: "请勾选难度或公开度",
-          type: "warning"
+          type: "warning",
         });
         return;
       }
@@ -515,7 +515,7 @@ export default {
         .then(() => {
           this.$notify({
             message: "更新成功",
-            type: "success"
+            type: "success",
           });
           this.searchGenPaper();
           this.quesLoading = false;
@@ -530,7 +530,7 @@ export default {
         this.$notify({
           title: "警告",
           message: "请选择试卷",
-          type: "warning"
+          type: "warning",
         });
         return;
       }
@@ -550,7 +550,7 @@ export default {
         courseNo: "",
         courseName: "",
         level: "",
-        name: ""
+        name: "",
       };
     },
     //查询
@@ -563,7 +563,7 @@ export default {
       this.currentPage = 1;
       this.loading = true;
       var url = QUESTION_API + "/genPaper/" + pageNo + "/" + this.pageSize;
-      this.$http.get(url, { params: this.formSearch }).then(response => {
+      this.$http.get(url, { params: this.formSearch }).then((response) => {
         this.tableData = response.data.content;
         this.total = response.data.totalElements;
         this.currentPage = Number(pageNo);
@@ -576,7 +576,7 @@ export default {
         this.$notify({
           title: "警告",
           message: "请选择课程",
-          type: "warning"
+          type: "warning",
         });
       } else {
         var course = this.getCourseObj(courseNo);
@@ -585,7 +585,7 @@ export default {
         sessionStorage.setItem("gen_paper", JSON.stringify(this.formSearch));
         sessionStorage.setItem("gen_paper_currentPage", this.currentPage);
         this.$router.push({
-          path: "/questions/gen_paper_detail/" + courseNo + "/" + level
+          path: "/questions/gen_paper_detail/" + courseNo + "/" + level,
         });
       }
     },
@@ -620,26 +620,26 @@ export default {
       sessionStorage.setItem("gen_paper_currentPage", this.currentPage);
       sessionStorage.setItem("question_back", "false");
       this.$router.push({
-        path: "/edit_paper/" + row.id + "/gen_paper"
+        path: "/edit_paper/" + row.id + "/gen_paper",
       });
     },
     deleteGenPaper(row) {
       this.$confirm("确认删除试卷吗?", "提示", {
-        type: "warning"
+        type: "warning",
       }).then(() => {
         this.loading = true;
         this.$http.delete(QUESTION_API + "/paper/" + row.id).then(
           () => {
             this.$notify({
               message: "删除成功",
-              type: "success"
+              type: "success",
             });
             this.searchGenPaper();
           },
-          response => {
+          (response) => {
             this.$notify({
-              message: response.response.data.msg,
-              type: "error"
+              message: response.response.data.desc,
+              type: "error",
             });
             this.loading = false;
           }
@@ -648,7 +648,7 @@ export default {
     },
     selectChange(row) {
       this.selectedPaperIds = [];
-      row.forEach(element => {
+      row.forEach((element) => {
         this.selectedPaperIds.push(element.id);
       });
     },
@@ -656,22 +656,22 @@ export default {
       var paperIds = this.paperIds;
       if (this.selectedPaperIds.length != 0) {
         this.$confirm("确认删除试卷吗?", "提示", {
-          type: "warning"
+          type: "warning",
         }).then(() => {
           this.loading = true;
           this.$http.delete(QUESTION_API + "/paper/" + paperIds).then(
             () => {
               this.$notify({
                 message: "删除成功",
-                type: "success"
+                type: "success",
               });
               this.searchGenPaper();
               this.selectedPaperIds = [];
             },
-            response => {
+            (response) => {
               this.$notify({
-                message: response.data.msg,
-                type: "error"
+                message: response.response.data.desc,
+                type: "error",
               });
               this.loading = false;
             }
@@ -680,7 +680,7 @@ export default {
       } else {
         this.$notify({
           message: "请勾选删除的数据",
-          type: "warning"
+          type: "warning",
         });
       }
     },
@@ -690,7 +690,7 @@ export default {
       this.courseLoading = true;
       this.$http
         .get(CORE_API + "/course/query?name=" + query + "&enable=true")
-        .then(response => {
+        .then((response) => {
           this.courseList = response.data;
           this.courseLoading = false;
         });
@@ -719,7 +719,7 @@ export default {
       } else {
         this.$notify({
           message: "请勾选导出的数据",
-          type: "warning"
+          type: "warning",
         });
       }
       /* 分布式印刷数据包设置 */
@@ -732,7 +732,7 @@ export default {
       if (this.exportModel.exportContentList.length == 0) {
         this.$notify({
           message: "请选择导出内容",
-          type: "error"
+          type: "error",
         });
         return false;
       }
@@ -741,7 +741,7 @@ export default {
         if (!reg.test(this.printExamPackagePassword)) {
           this.$notify({
             message: "加密密码请输入6至12位的数字或字母!",
-            type: "error"
+            type: "error",
           });
           return false;
         }
@@ -756,7 +756,7 @@ export default {
           "/" +
           this.exportModel.exportContentList +
           "/" +
-          this.user.rootOrgName +
+          this.user.rootOrgId +
           "/" +
           this.user.displayName +
           "/onLine" +
@@ -776,7 +776,7 @@ export default {
           "/" +
           this.exportModel.exportContentList +
           "/" +
-          this.user.rootOrgName +
+          this.user.rootOrgId +
           "/" +
           this.user.displayName +
           "/onLine" +
@@ -812,7 +812,7 @@ export default {
     },
     //传至印刷模块
     sendPrint(formData) {
-      this.$refs[formData].validate(valid => {
+      this.$refs[formData].validate((valid) => {
         if (valid) {
           var orgId = "";
           for (let exam of this.examList) {
@@ -834,7 +834,7 @@ export default {
             }
             this.$notify({
               message: "已推送",
-              type: "success"
+              type: "success",
             });
             this.resetForm2(formData);
             this.dialogModel = false;
@@ -852,7 +852,7 @@ export default {
         .get(
           EXAM_WORK_API + "/exam/queryByNameLike?name=" + query + "&enable=true"
         )
-        .then(response => {
+        .then((response) => {
           this.examList = response.data;
         });
     },
@@ -860,7 +860,7 @@ export default {
       //查询所有考试
       this.$http
         .get(EXAM_WORK_API + "/exam/queryByNameLike?name=&enable=true")
-        .then(response => {
+        .then((response) => {
           var list = response.data;
           for (var i = 0; i < list.length; i++) {
             if (list[i].examType == "TRADITION") {
@@ -873,7 +873,7 @@ export default {
     searchOrgName() {
       this.$http
         .get(CORE_API + "/org/rootOrg/" + this.user.rootOrgId)
-        .then(response => {
+        .then((response) => {
           this.Org = response.data;
         });
     },
@@ -885,7 +885,7 @@ export default {
           courseNo: "",
           courseName: "",
           level: "",
-          name: ""
+          name: "",
         };
         this.currentPage = 1;
       } else {
@@ -897,7 +897,7 @@ export default {
       }
       this.getCourses(this.formSearch.courseName);
       this.searchGenPaper();
-    }
+    },
   },
   computed: {
     paperIds() {
@@ -920,7 +920,7 @@ export default {
         courseList.push({
           courseNo: courseNo,
           courseInfo: courseInfo,
-          courseName: courseName
+          courseName: courseName,
         });
       }
       return courseList;
@@ -928,16 +928,16 @@ export default {
     noBatchSelected() {
       return this.selectedPaperIds.length === 0;
     },
-    ...mapState({ user: state => state.user })
+    ...mapState({ user: (state) => state.user }),
   },
   watch: {
-    $route: "initVue"
+    $route: "initVue",
   },
   created() {
     this.initVue();
     this.searchExamList();
     this.searchOrgName();
-  }
+  },
 };
 </script>
 <style scoped src="../styles/Common.css"></style>

+ 47 - 47
src/modules/questions/views/ImportPaper.vue

@@ -23,7 +23,7 @@
                 clearable
                 placeholder="请输入"
                 size="small"
-                @focus="e => getCourses(e.target.value)"
+                @focus="(e) => getCourses(e.target.value)"
               >
                 <el-option
                   v-for="item in courseInfoSelect"
@@ -120,13 +120,13 @@
           </el-form-item>
         </el-row>
       </el-form>
-      <div style="width: 100%;margin-bottom: 10px;"></div>
+      <div style="width: 100%; margin-bottom: 10px;"></div>
       <el-table
         v-loading="loading"
         element-loading-text="拼命加载中"
         :data="tableData"
         border
-        style="width: 100%"
+        style="width: 100%;"
         @selection-change="selectChange"
       >
         <el-table-column type="selection" width="40"></el-table-column>
@@ -276,7 +276,7 @@
               filterable
               clearable
               placeholder="全部"
-              @focus="e => getCourses(e.target.value)"
+              @focus="(e) => getCourses(e.target.value)"
             >
               <el-option
                 v-for="item in courseInfoSelect"
@@ -369,7 +369,7 @@ export default {
         courseNo: "",
         courseName: "",
         level: "",
-        name: ""
+        name: "",
       },
       tableData: [],
       levelList: LEVEL_TYPE,
@@ -385,7 +385,7 @@ export default {
       copyPaperDialog: false,
       copyPaperForm: {
         paperName: "",
-        courseNo: null
+        courseNo: null,
       },
       copyPaperId: "",
       quesPropertyDialog: false,
@@ -402,17 +402,17 @@ export default {
         { label: 0.7, value: 0.7 },
         { label: 0.8, value: 0.8 },
         { label: 0.9, value: 0.9 },
-        { label: 1.0, value: 1.0 }
+        { label: 1.0, value: 1.0 },
       ],
       publicityList: PUBLICITY_LIST,
       rules: {
         paperName: [
-          { required: true, message: "请输试卷名称", trigger: "blur" }
+          { required: true, message: "请输试卷名称", trigger: "blur" },
         ],
         courseNo: [
-          { required: true, message: "请选择课程名称", trigger: "change" }
-        ]
-      }
+          { required: true, message: "请选择课程名称", trigger: "change" },
+        ],
+      },
     };
   },
   methods: {
@@ -425,7 +425,7 @@ export default {
       this.currentPage = 1;
       this.loading = true;
       var url = QUESTION_API + "/importPaper/" + pageNo + "/" + this.pageSize;
-      this.$http.get(url, { params: this.formSearch }).then(response => {
+      this.$http.get(url, { params: this.formSearch }).then((response) => {
         this.tableData = response.data.content;
         this.total = response.data.totalElements;
         this.currentPage = pageNo;
@@ -455,26 +455,26 @@ export default {
       sessionStorage.setItem("import_paper_currentPage", this.currentPage);
       sessionStorage.setItem("question_back", "false");
       this.$router.push({
-        path: "/edit_paper/" + row.id + "/import_paper"
+        path: "/edit_paper/" + row.id + "/import_paper",
       });
     },
     deleteImportPaper(row) {
       this.$confirm("确认删除试卷吗?", "提示", {
-        type: "warning"
+        type: "warning",
       }).then(() => {
         this.loading = true;
         this.$http.delete(QUESTION_API + "/paper/" + row.id).then(
           () => {
             this.$notify({
               message: "删除成功",
-              type: "success"
+              type: "success",
             });
             this.searchImportPaper();
           },
-          error => {
+          (error) => {
             this.$notify({
-              message: error.response.data.msg,
-              type: "error"
+              message: error.response.data.desc,
+              type: "error",
             });
             this.loading = false;
           }
@@ -483,29 +483,29 @@ export default {
     },
     selectChange(row) {
       this.selectedPaperIds = [];
-      row.forEach(element => {
+      row.forEach((element) => {
         this.selectedPaperIds.push(element.id);
       });
     },
     batchDeletePaper() {
       var paperIds = this.paperIds;
       this.$confirm("确认删除试卷吗?", "提示", {
-        type: "warning"
+        type: "warning",
       }).then(() => {
         this.loading = true;
         this.$http.delete(QUESTION_API + "/paper/" + paperIds).then(
           () => {
             this.$notify({
               message: "删除成功",
-              type: "success"
+              type: "success",
             });
             this.searchImportPaper();
             this.selectedPaperIds = [];
           },
-          error => {
+          (error) => {
             this.$notify({
-              message: error.response.data.msg,
-              type: "error"
+              message: error.response.data.desc,
+              type: "error",
             });
             this.loading = false;
           }
@@ -515,7 +515,7 @@ export default {
     //导入试卷
     impPaper() {
       this.$router.push({
-        path: "/questions/import_paper_info"
+        path: "/questions/import_paper_info",
       });
     },
     //查询所有课程
@@ -523,7 +523,7 @@ export default {
       this.courseLoading = true;
       this.$http
         .get(CORE_API + "/course/query?name=" + query + "&enable=true")
-        .then(response => {
+        .then((response) => {
           this.courseList = response.data;
           this.courseLoading = false;
         });
@@ -533,22 +533,22 @@ export default {
       this.$http
         .put(QUESTION_API + "/useBasePaper/" + this.selectedPaperIds)
         .then(
-          response => {
+          (response) => {
             console.log("come in response:", response);
             if (!response.data.desc) {
               this.$notify({
                 message: "操作成功",
-                type: "success"
+                type: "success",
               });
             } else {
               this.$notify({
                 message: response.data.desc,
-                type: "error"
+                type: "error",
               });
             }
             this.loading = false;
           },
-          error => {
+          (error) => {
             var message = error.response.data.desc;
             var err = message
               .replace("[", "")
@@ -556,7 +556,7 @@ export default {
               .substring(message.indexOf("desc") + 4);
             this.$notify({
               message: err,
-              type: "error"
+              type: "error",
             });
             this.loading = false;
           }
@@ -571,7 +571,7 @@ export default {
     },
     //保存
     submitCopy(formData) {
-      this.$refs[formData].validate(valid => {
+      this.$refs[formData].validate((valid) => {
         if (valid) {
           this.cloneLoading = true;
           this.$http
@@ -587,16 +587,16 @@ export default {
             .then(() => {
               this.$notify({
                 message: "复制成功",
-                type: "success"
+                type: "success",
               });
               this.cloneLoading = false;
               this.copyPaperDialog = false;
               this.searchImportPaper();
             })
-            .catch(error => {
+            .catch((error) => {
               this.$notify({
                 type: "error",
-                message: error.response.data.msg
+                message: error.response.data.msg,
               });
               this.cloneLoading = false;
             });
@@ -614,7 +614,7 @@ export default {
         this.$notify({
           title: "警告",
           message: "请输入课程",
-          type: "warning"
+          type: "warning",
         });
         return;
       }
@@ -670,7 +670,7 @@ export default {
         this.$notify({
           title: "警告",
           message: "请选择试卷",
-          type: "warning"
+          type: "warning",
         });
         return;
       }
@@ -683,7 +683,7 @@ export default {
         this.$notify({
           title: "警告",
           message: "请输入课程",
-          type: "warning"
+          type: "warning",
         });
         return;
       }
@@ -714,7 +714,7 @@ export default {
         .then(() => {
           this.$notify({
             message: "更新成功",
-            type: "success"
+            type: "success",
           });
           this.searchImportPaper();
           this.quesLoading = false;
@@ -723,7 +723,7 @@ export default {
         .catch(() => {
           this.$notify({
             type: "error",
-            message: "更新失败"
+            message: "更新失败",
           });
           this.quesLoading = false;
           this.closePropertyDialog();
@@ -747,7 +747,7 @@ export default {
         .then(() => {
           this.$notify({
             message: "更新成功",
-            type: "success"
+            type: "success",
           });
           this.quesLoading = false;
           this.closePropertyDialog();
@@ -755,7 +755,7 @@ export default {
         .catch(() => {
           this.$notify({
             type: "error",
-            message: "更新失败"
+            message: "更新失败",
           });
           this.quesLoading = false;
           this.closePropertyDialog();
@@ -768,7 +768,7 @@ export default {
         this.formSearch = {
           courseNo: "",
           level: "",
-          name: ""
+          name: "",
         };
         this.currentPage = 1;
       } else {
@@ -782,7 +782,7 @@ export default {
         this.getCourses(this.formSearch.courseName);
       }
       this.handleCurrentChange(this.currentPage);
-    }
+    },
   },
   computed: {
     paperIds() {
@@ -808,14 +808,14 @@ export default {
     noBatchSelected() {
       return this.selectedPaperIds.length === 0;
     },
-    ...mapState({ user: state => state.user })
+    ...mapState({ user: (state) => state.user }),
   },
   watch: {
-    $route: "initVue"
+    $route: "initVue",
   },
   created() {
     this.initVue();
-  }
+  },
 };
 </script>
 <style scoped src="../styles/Common.css"></style>

+ 18 - 11
src/modules/questions/views/InsertPaperStructureInfo.vue

@@ -847,6 +847,13 @@ export default {
         this.$http.get(url, { params: quesTypeObj }).then(response => {
           console.log(response);
           this.quesNameList = response.data;
+          if (this.quesNameList != null) {
+            for (let quesName of this.quesNameList) {
+              if (quesName.name.length > 50) {
+                quesName.name = quesName.name.substring(0, 50) + "...";
+              }
+            }
+          }
           this.initQuesNames();
         });
       }
@@ -906,17 +913,17 @@ export default {
           unitStruct.id = maxId + 1;
           this.unitStructs.push(unitStruct);
           this.resetForm(formData);
-          this.paperUnitForm.publicSimple=0;
-          this.paperUnitForm.publicMedium=0;
-          this.paperUnitForm.publicDifficulty=0;
-          this.paperUnitForm.noPublicSimple=0;
-          this.paperUnitForm.noPublicMedium=0;
-          this.paperUnitForm.noPublicDifficulty=0;
-          this.paperUnitForm.publicSum=0;
-          this.paperUnitForm.noPublicSum=0;
-          this.paperUnitForm.simpleSum=0;
-          this.paperUnitForm.mediumSum=0;
-          this.paperUnitForm.difficultySum=0;
+          this.paperUnitForm.publicSimple = 0;
+          this.paperUnitForm.publicMedium = 0;
+          this.paperUnitForm.publicDifficulty = 0;
+          this.paperUnitForm.noPublicSimple = 0;
+          this.paperUnitForm.noPublicMedium = 0;
+          this.paperUnitForm.noPublicDifficulty = 0;
+          this.paperUnitForm.publicSum = 0;
+          this.paperUnitForm.noPublicSum = 0;
+          this.paperUnitForm.simpleSum = 0;
+          this.paperUnitForm.mediumSum = 0;
+          this.paperUnitForm.difficultySum = 0;
           this.setUnits();
           sessionStorage.setItem(
             "paperStruct",

+ 30 - 58
yarn.lock

@@ -2696,11 +2696,6 @@ camelcase@^2.0.0:
   resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f"
   integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=
 
-camelcase@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a"
-  integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo=
-
 camelcase@^4.1.0:
   version "4.1.0"
   resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
@@ -2930,15 +2925,6 @@ clipboardy@^2.0.0:
     arch "^2.1.1"
     execa "^1.0.0"
 
-cliui@^3.2.0:
-  version "3.2.0"
-  resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d"
-  integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=
-  dependencies:
-    string-width "^1.0.1"
-    strip-ansi "^3.0.1"
-    wrap-ansi "^2.0.0"
-
 cliui@^4.0.0:
   version "4.1.0"
   resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49"
@@ -8087,10 +8073,10 @@ node-releases@^1.1.3:
   dependencies:
     semver "^5.3.0"
 
-node-sass@^4.12.0:
-  version "4.12.0"
-  resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.12.0.tgz#0914f531932380114a30cc5fa4fa63233a25f017"
-  integrity sha512-A1Iv4oN+Iel6EPv77/HddXErL2a+gZ4uBeZUy+a8O35CFYTXhgA8MgLCWBtwpGZdCvTvQ9d+bQxX/QC36GDPpQ==
+node-sass@^4.14.1:
+  version "4.14.1"
+  resolved "https://registry.npm.taobao.org/node-sass/download/node-sass-4.14.1.tgz#99c87ec2efb7047ed638fb4c9db7f3a42e2217b5"
+  integrity sha1-mch+wu+3BH7WOPtMnbfzpC4iF7U=
   dependencies:
     async-foreach "^0.1.3"
     chalk "^1.1.1"
@@ -8099,14 +8085,14 @@ node-sass@^4.12.0:
     get-stdin "^4.0.1"
     glob "^7.0.3"
     in-publish "^2.0.0"
-    lodash "^4.17.11"
+    lodash "^4.17.15"
     meow "^3.7.0"
     mkdirp "^0.5.1"
     nan "^2.13.2"
     node-gyp "^3.8.0"
     npmlog "^4.0.0"
     request "^2.88.0"
-    sass-graph "^2.2.4"
+    sass-graph "2.2.5"
     stdout-stream "^1.4.0"
     "true-case-path" "^1.0.2"
 
@@ -8430,13 +8416,6 @@ os-homedir@^1.0.0:
   resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
   integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M=
 
-os-locale@^1.4.0:
-  version "1.4.0"
-  resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9"
-  integrity sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=
-  dependencies:
-    lcid "^1.0.0"
-
 os-locale@^2.0.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2"
@@ -10236,15 +10215,15 @@ sane@^4.0.3:
     minimist "^1.1.1"
     walker "~1.0.5"
 
-sass-graph@^2.2.4:
-  version "2.2.4"
-  resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.4.tgz#13fbd63cd1caf0908b9fd93476ad43a51d1e0b49"
-  integrity sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k=
+sass-graph@2.2.5:
+  version "2.2.5"
+  resolved "https://registry.npm.taobao.org/sass-graph/download/sass-graph-2.2.5.tgz?cache=0&sync_timestamp=1588596670185&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsass-graph%2Fdownload%2Fsass-graph-2.2.5.tgz#a981c87446b8319d96dce0671e487879bd24c2e8"
+  integrity sha1-qYHIdEa4MZ2W3OBnHkh4eb0kwug=
   dependencies:
     glob "^7.0.0"
     lodash "^4.0.0"
     scss-tokenizer "^0.2.3"
-    yargs "^7.0.0"
+    yargs "^13.3.2"
 
 sass-loader@^8.0.0:
   version "8.0.0"
@@ -10843,7 +10822,7 @@ string-length@^2.0.0:
     astral-regex "^1.0.0"
     strip-ansi "^4.0.0"
 
-string-width@^1.0.1, string-width@^1.0.2:
+string-width@^1.0.1:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
   integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=
@@ -11996,11 +11975,6 @@ whatwg-url@^7.0.0:
     tr46 "^1.0.1"
     webidl-conversions "^4.0.2"
 
-which-module@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f"
-  integrity sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=
-
 which-module@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
@@ -12298,12 +12272,13 @@ yargs-parser@^13.1.1:
     camelcase "^5.0.0"
     decamelize "^1.2.0"
 
-yargs-parser@^5.0.0:
-  version "5.0.0"
-  resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a"
-  integrity sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=
+yargs-parser@^13.1.2:
+  version "13.1.2"
+  resolved "https://registry.npm.taobao.org/yargs-parser/download/yargs-parser-13.1.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fyargs-parser%2Fdownload%2Fyargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38"
+  integrity sha1-Ew8JcC667vJlDVTObj5XBvek+zg=
   dependencies:
-    camelcase "^3.0.0"
+    camelcase "^5.0.0"
+    decamelize "^1.2.0"
 
 yargs-parser@^9.0.2:
   version "9.0.2"
@@ -12364,24 +12339,21 @@ yargs@^13.0.0:
     y18n "^4.0.0"
     yargs-parser "^13.1.1"
 
-yargs@^7.0.0:
-  version "7.1.0"
-  resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8"
-  integrity sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=
+yargs@^13.3.2:
+  version "13.3.2"
+  resolved "https://registry.npm.taobao.org/yargs/download/yargs-13.3.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fyargs%2Fdownload%2Fyargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd"
+  integrity sha1-rX/+/sGqWVZayRX4Lcyzipwxot0=
   dependencies:
-    camelcase "^3.0.0"
-    cliui "^3.2.0"
-    decamelize "^1.1.1"
-    get-caller-file "^1.0.1"
-    os-locale "^1.4.0"
-    read-pkg-up "^1.0.1"
+    cliui "^5.0.0"
+    find-up "^3.0.0"
+    get-caller-file "^2.0.1"
     require-directory "^2.1.1"
-    require-main-filename "^1.0.1"
+    require-main-filename "^2.0.0"
     set-blocking "^2.0.0"
-    string-width "^1.0.2"
-    which-module "^1.0.0"
-    y18n "^3.2.1"
-    yargs-parser "^5.0.0"
+    string-width "^3.0.0"
+    which-module "^2.0.0"
+    y18n "^4.0.0"
+    yargs-parser "^13.1.2"
 
 yorkie@^2.0.0:
   version "2.0.0"

이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.