10 Commits 8a1f4f506d ... 76f5abf541

Auteur SHA1 Bericht Datum
  dedsudiyu 76f5abf541 Merge branch 'master' into SCHOOL-XiBeiNongLin 10 uur geleden
  dedsudiyu d99388a057 zc 10 uur geleden
  dedsudiyu f22b8266a9 zc 3 dagen geleden
  dedsudiyu 9bb3015603 zc 3 dagen geleden
  dedsudiyu b782fea042 zc 3 dagen geleden
  dedsudiyu b5c7847df6 zc 3 dagen geleden
  dedsudiyu fed169f931 zc 4 dagen geleden
  dedsudiyu 54bea08ee7 zc 4 dagen geleden
  dedsudiyu 07fdb4110e zc 4 dagen geleden
  dedsudiyu 8dcb25a257 zc 4 dagen geleden
43 gewijzigde bestanden met toevoegingen van 2003 en 817 verwijderingen
  1. 32 0
      src/api/safetyEducationExaminationNew/index.js
  2. BIN
      src/assets/ZDimages/basicsModules/image_420782143223404.png
  3. BIN
      src/assets/ZDimages/basicsModules/image_986222064626770.png
  4. 2 2
      src/assets/styles/index.scss
  5. 2 1
      src/views/safetyEducationExaminationNew/components/answerKey.vue
  6. 3 2
      src/views/safetyEducationExaminationNew/components/historyOfIncorrectQuestions.vue
  7. 213 0
      src/views/safetyEducationExaminationNew/components/richTextPdf.vue
  8. 6 6
      src/views/safetyEducationExaminationNew/courseManagement/courseManagement/basicSettings.vue
  9. 1 1
      src/views/safetyEducationExaminationNew/courseManagement/courseManagement/drawerItem.vue
  10. 2 2
      src/views/safetyEducationExaminationNew/courseManagement/courseManagement/index.vue
  11. 14 14
      src/views/safetyEducationExaminationNew/courseManagement/coursewareManagement/addPage.vue
  12. 21 2
      src/views/safetyEducationExaminationNew/courseManagement/coursewareManagement/index.vue
  13. 6 2
      src/views/safetyEducationExaminationNew/workbench/ExamSituation.vue
  14. 6 2
      src/views/safetyEducationExaminationNew/workbench/LabPersonMatch.vue
  15. 24 3
      src/views/safetyEducationExaminationNew/workbench/StudyHourStats.vue
  16. 55 0
      src/views/safetyEducationExaminationNew/dataStatistics/index.vue
  17. 54 6
      src/views/safetyEducationExaminationNew/examManagement/examinationArrange/addPage.vue
  18. 3 1
      src/views/safetyEducationExaminationNew/examManagement/examinationArrange/index.vue
  19. 5 0
      src/views/safetyEducationExaminationNew/examManagement/examinationResult/academicPerformance.vue
  20. 3 3
      src/views/safetyEducationExaminationNew/examManagement/testPaperManagement/addPage.vue
  21. 5 5
      src/views/safetyEducationExaminationNew/examManagement/testPaperManagement/index.vue
  22. 3 3
      src/views/safetyEducationExaminationNew/featurePage/learningCourse/index.vue
  23. 2 2
      src/views/safetyEducationExaminationNew/featurePage/learningMaterials/index.vue
  24. 2 2
      src/views/safetyEducationExaminationNew/featurePage/mockExam/index.vue
  25. 2 2
      src/views/safetyEducationExaminationNew/featurePage/startPracticing/index.vue
  26. 2 2
      src/views/safetyEducationExaminationNew/featurePage/startTheExam/index.vue
  27. 2 2
      src/views/safetyEducationExaminationNew/featurePage/startTraining/index.vue
  28. 5 7
      src/views/safetyEducationExaminationNew/workbench/LabBindingApply.vue
  29. 314 0
      src/views/safetyEducationExaminationNew/personnelApproval/index.vue
  30. 17 4
      src/views/safetyEducationExaminationNew/publicConfiguration/basicConfiguration/index.vue
  31. 1 1
      src/views/safetyEducationExaminationNew/questionBankManagement/practiceSolvingProblems/index.vue
  32. 32 9
      src/views/safetyEducationExaminationNew/questionBankManagement/questionBankManagement/addPage.vue
  33. 22 4
      src/views/safetyEducationExaminationNew/questionBankManagement/questionBankManagement/index.vue
  34. 62 22
      src/views/safetyEducationExaminationNew/safetyEducation/knowledgeLearning/index.vue
  35. 45 9
      src/views/safetyEducationExaminationNew/safetyEducation/learningTasks/index.vue
  36. 32 10
      src/views/safetyEducationExaminationNew/safetyTest/mockExam/index.vue
  37. 34 2
      src/views/safetyEducationExaminationNew/safetyTest/myGrades/index.vue
  38. 141 38
      src/views/safetyEducationExaminationNew/safetyTest/onlineExam/index.vue
  39. 63 11
      src/views/safetyEducationExaminationNew/safetyTest/practiceQuestions/index.vue
  40. 355 358
      src/views/safetyEducationExaminationNew/workbench/ResourceCard.vue
  41. 281 167
      src/views/safetyEducationExaminationNew/workbench/TaskCard.vue
  42. 126 90
      src/views/safetyEducationExaminationNew/workbench/UserInfoCard.vue
  43. 3 20
      src/views/safetyEducationExaminationNew/workbench/index.vue

+ 32 - 0
src/api/safetyEducationExaminationNew/index.js

@@ -860,3 +860,35 @@ export function examElStatisticsCreditHourList(data) {
     data: data
   })
 }
+//工作台查询考试列表
+export function examUserExamStudyTaskList(data) {
+  return request({
+    url: '/exam/user/exam/studyTaskList',
+    method: 'post',
+    data: data
+  })
+}
+//工作台按知识点分组查询试题数量
+export function examElQuestionBankGroupByKnowledgePoint(data) {
+  return request({
+    url: '/exam/elQuestionBank/groupByKnowledgePoint',
+    method: 'post',
+    data: data
+  })
+}
+//确认考试承诺书
+export function examUserExamCommitmentConfirm(data) {
+  return request({
+    url: '/exam/user/exam/commitment/confirm',
+    method: 'post',
+    data: data
+  })
+}
+//工作台按知识点分组查询试题数量
+export function examUserPracticeSummary(query) {
+  return request({
+    url: '/exam/user/practice/summary',
+    method: 'get',
+    params: query
+  })
+}

BIN
src/assets/ZDimages/basicsModules/image_420782143223404.png


BIN
src/assets/ZDimages/basicsModules/image_986222064626770.png


+ 2 - 2
src/assets/styles/index.scss

@@ -438,9 +438,9 @@ aside {
   background: $acquiesceThemeScrollbarB;
 }
 .scrollbar-box::-webkit-scrollbar-track{
-  -webkit-box-shadow: inset 0 0 5px $acquiesceThemeScrollbarA;
+  -webkit-box-shadow: inset 0 0 5px rgba(255,255,255,0);
   border-radius: 0;
-  background: $acquiesceThemeScrollbarA;
+  background:  rgba(255,255,255,0);
 }
 //横向
 .scrollbar-x-box{

+ 2 - 1
src/views/safetyEducationExaminationNew/components/answerKey.vue

@@ -32,7 +32,8 @@
           <!-- 答案解析 -->
           <div class="analysis-box">
             <div class="analysis-title">答案解析</div>
-            <div class="analysis-content" v-html="questionData.analysis"></div>
+            <div class="analysis-content" v-if="questionData.analysis" v-html="questionData.analysis"></div>
+            <div class="analysis-content" style="color:#999;" v-else>未配置</div>
           </div>
         </div>
       </div>

+ 3 - 2
src/views/safetyEducationExaminationNew/components/historyOfIncorrectQuestions.vue

@@ -56,6 +56,7 @@
         <p class="page-inquire-common-style-button" @click="handleQuery">查询</p>
         <p class="page-reset-common-style-button" @click="resetQuery">重置</p>
         <p class="page-submit-common-style-button"
+           v-if="dataList[0]"
            style="float: right;"
            @click="tableButton(1)"
         >开始训练</p>
@@ -185,8 +186,8 @@
             obj.knowledgePointId = this.historyOfIncorrectQuestionsPropsData.knowledgePointId;
           }
           this.$router.push({
-            name: 'startTraining',
-            params: obj
+            path: '/startTraining',
+            query: obj
           })
         }else if(type == 2){
           //查看答案

+ 213 - 0
src/views/safetyEducationExaminationNew/components/richTextPdf.vue

@@ -0,0 +1,213 @@
+<template>
+  <div class="rich-text-pdf-wrapper">
+    <div ref="a4Paper" class="a4-paper">
+      <div class="rich-content" v-html="content"></div>
+    </div>
+  </div>
+</template>
+
+<script>
+  import html2canvas from 'html2canvas';
+
+  export default {
+    name: 'RichTextPdf',
+    props: {
+      content: {
+        type: String,
+        default: ''
+      }
+    },
+    data() {
+      return {
+        loading: false
+      };
+    },
+    methods: {
+      async downloadPDF() {
+        if (!this.content) {
+          alert('没有可下载的内容');
+          return;
+        }
+
+        this.loading = true;
+        try {
+          const el = this.$refs.a4Paper;
+          // 将 DOM 转换为 Canvas,scale: 2 保证高清输出
+          const canvas = await html2canvas(el, {
+            scale: 2,
+            useCORS: true, // 允许跨域图片
+            backgroundColor: '#ffffff',
+            logging: false
+          });
+
+          const imgW = canvas.width;
+          const imgH = canvas.height;
+
+          // A4 纸的宽度点数 (595 pt = 210mm)
+          const a4WidthPt = 595;
+          // 根据原图比例计算 A4 纸应有的高度点数
+          const a4HeightPt = Math.round((imgH / imgW) * a4WidthPt);
+
+          // A4 纸标准高度点数 (842 pt = 297mm)
+          const pageHeightPt = 842;
+
+          // 计算需要多少页
+          const totalPages = Math.ceil(a4HeightPt / pageHeightPt);
+
+          // 将 canvas 转为 JPEG base64 并解码为二进制字节数组
+          const jpegB64 = canvas.toDataURL('image/jpeg', 0.92).split(',')[1];
+          const jpegBytes = Uint8Array.from(atob(jpegB64), c => c.charCodeAt(0));
+
+          // 调用你的底层 PDF 构建方法(已改造为支持多页)
+          const pdfBytes = this._buildMultiPagePdf(jpegBytes, imgW, imgH, a4WidthPt, a4HeightPt, pageHeightPt, totalPages);
+
+          // 触发浏览器下载
+          const blob = new Blob([pdfBytes], { type: 'application/pdf' });
+          const url = URL.createObjectURL(blob);
+          const a = document.createElement('a');
+          a.href = url;
+          a.download = '富文本内容.pdf';
+          document.body.appendChild(a);
+          a.click();
+          URL.revokeObjectURL(url);
+          document.body.removeChild(a);
+
+        } catch (error) {
+          console.error('PDF 生成失败:', error);
+          alert('PDF 下载失败,请重试!');
+        } finally {
+          this.loading = false;
+        }
+      },
+
+      // 核心:构造内嵌 JPEG 图片的多页最小 PDF
+      _buildMultiPagePdf(jpegBytes, imgW, imgH, pageW, totalImgH, pageH, pageCount) {
+        const enc = s => new TextEncoder().encode(s);
+        const concat = (...parts) => {
+          const total = parts.reduce((n, p) => n + p.length, 0);
+          const out = new Uint8Array(total);
+          let off = 0;
+          for (const p of parts) { out.set(p, off); off += p.length; }
+          return out;
+        };
+
+        // 动态生成每一页的 Page 对象和 Contents 对象
+        const pageObjects = [];
+        const contentObjects = [];
+
+        for (let i = 0; i < pageCount; i++) {
+          const contentId = 3 + i * 2;      // Contents 对象 ID (从 3 开始)
+          const pageId = 4 + i * 2;         // Page 对象 ID (从 4 开始)
+
+          // 计算当前页的裁剪偏移量 (Y轴向下移动)
+          const yOffset = -(i * pageH);
+          // 注意:这里使用 /Do 绘制整图,但通过 cm 变换来实现视觉上的“分页裁剪”效果
+          const stream = `q ${pageW} 0 0 ${totalImgH} 0 ${yOffset} cm /Im0 Do Q\n`;
+
+          const streamEnc = enc(stream);
+          contentObjects.push({
+            id: contentId,
+            bytes: concat(
+              enc(`${contentId} 0 obj\n<< /Length ${streamEnc.length} >>\nstream\n`),
+              streamEnc,
+              enc('\nendstream\nendobj\n')
+            )
+          });
+
+          pageObjects.push({
+            id: pageId,
+            bytes: concat(
+              enc(`${pageId} 0 obj\n<< /Type /Page /Parent 2 0 R /MediaBox [0 0 ${pageW} ${pageH}] /Contents ${contentId} 0 R /Resources << /XObject << /Im0 5 0 R >> >> >>\nendobj\n`)
+            )
+          });
+        }
+
+        // 构建 Kids 数组字符串
+        const kidsStr = pageObjects.map(p => `${p.id} 0 R`).join(' ');
+
+        // 基础对象
+        const o1 = { id: 1, bytes: concat(enc('1 0 obj\n<< /Type /Catalog /Pages 2 0 R >>\nendobj\n')) };
+        const o2 = { id: 2, bytes: concat(enc(`2 0 obj\n<< /Type /Pages /Kids [${kidsStr}] /Count ${pageCount} >>\nendobj\n`)) };
+
+        // 图片对象 (所有页共享同一张长图)
+        const o5 = {
+          id: 5,
+          bytes: concat(
+            enc(`5 0 obj\n<< /Type /XObject /Subtype /Image /Width ${imgW} /Height ${imgH} /ColorSpace /DeviceRGB /BitsPerComponent 8 /Filter /DCTDecode /Length ${jpegBytes.length} >>\nstream\n`),
+            jpegBytes,
+            enc('\nendstream\nendobj\n')
+          )
+        };
+
+        // 组装所有对象
+        const header = enc('%PDF-1.4\n');
+        const allObjs = [o1, o2, ...contentObjects, ...pageObjects, o5];
+
+        const offsets = [];
+        let pos = header.length;
+        const bodyParts = [];
+
+        for (const o of allObjs) {
+          offsets.push(pos);
+          pos += o.bytes.length;
+          bodyParts.push(o.bytes);
+        }
+
+        // 构建交叉引用表 (xref)
+        const totalObjsCount = allObjs.length + 1; // 包含 0 号对象
+        let xrefStr = `xref\n0 ${totalObjsCount}\n0000000000 65535 f \n`;
+        for (const offset of offsets) {
+          xrefStr += `${String(offset).padStart(10, '0')} 00000 n \n`;
+        }
+        xrefStr += `trailer\n<< /Size ${totalObjsCount} /Root 1 0 R >>\nstartxref\n${pos}\n%%EOF\n`;
+
+        const xref = enc(xrefStr);
+        return concat(header, ...bodyParts, xref);
+      }
+    }
+  };
+</script>
+
+<style scoped>
+  .rich-text-pdf-wrapper {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+  }
+
+  /* 核心:严格限制容器为 A4 纸比例 (210mm x 297mm ≈ 794px x 1123px) */
+  .a4-paper {
+    width: 794px;
+    min-height: 1123px;
+    padding: 40px;
+    box-sizing: border-box;
+    background: #fff;
+    box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
+    overflow: hidden;
+    position: relative;
+  }
+
+  /* 重置并规范富文本内部样式 */
+  .rich-content {
+    font-family: "SimSun", "宋体", serif;
+    font-size: 16px;
+    line-height: 1.8;
+    color: #333;
+    word-wrap: break-word;
+  }
+
+  .rich-content p { margin: 8px 0; }
+
+  .action-bar { margin-top: 20px; }
+
+  .download-btn {
+    padding: 10px 24px;
+    background: #409eff;
+    color: #fff;
+    border: none;
+    border-radius: 4px;
+    font-size: 16px;
+    cursor: pointer;
+  }
+  .download-btn:disabled { background: #a0cfff; cursor: not-allowed; }
+</style>

+ 6 - 6
src/views/safetyEducationExaminationNew/courseManagement/courseManagement/basicSettings.vue

@@ -5,8 +5,8 @@
         <div class="form-big-box">
           <div class="form-box">
             <div class="form-flex-box">
-              <el-form-item label="专业类别" prop="disciplineTypeId">
-                <el-select v-model="newData.disciplineTypeId" :disabled="showType" placeholder="请选择专业类别" style="width: 160px">
+              <el-form-item label="课程分类" prop="disciplineTypeId">
+                <el-select v-model="newData.disciplineTypeId" :disabled="showType" placeholder="请选择课程分类" style="width: 160px">
                   <el-option
                     v-for="dict in optionListA"
                     :key="dict.id"
@@ -133,10 +133,10 @@
           popupIntervalMinutes: 0,
         },
         rules:{
-          disciplineTypeId: [
-            { required: true, message: "请选择专业类别", trigger: "blur" },
-            { required: true, message: "请选择专业类别", validator: this.spaceJudgment, trigger: "blur" }
-          ],
+          // disciplineTypeId: [
+          //   { required: true, message: "请选择课程分类", trigger: "blur" },
+          //   { required: true, message: "请选择课程分类", validator: this.spaceJudgment, trigger: "blur" }
+          // ],
           courseName: [
             { required: true, message: "请输入课程名称", trigger: "blur" },
             { required: true, message: "请输入课程名称", validator: this.spaceJudgment, trigger: "blur" }

+ 1 - 1
src/views/safetyEducationExaminationNew/courseManagement/courseManagement/drawerItem.vue

@@ -301,7 +301,7 @@
       //知识点
       examElKnowledgePointTreeList(){
         if(!this.newData.knowledgePointId){
-          examElKnowledgePointTreeList({searchValue:this.leftData.searchValue}).then(response => {
+          examElKnowledgePointTreeList({dataScope:1,searchValue:this.leftData.searchValue}).then(response => {
             let list = [];
             for(let i=0;i<response.data.length;i++){
               list.push({

+ 2 - 2
src/views/safetyEducationExaminationNew/courseManagement/courseManagement/index.vue

@@ -40,7 +40,7 @@
             ></el-cascader>
           </el-form-item>
           <el-form-item label="" prop="disciplineId">
-            <el-select v-model="queryParams.disciplineId" placeholder="专业类别" style="width: 200px">
+            <el-select v-model="queryParams.disciplineId" placeholder="课程分类" style="width: 200px">
               <el-option
                 v-for="dict in optionListC"
                 :key="dict.id"
@@ -97,7 +97,7 @@
               <span style="padding:2px 10px;border:1px solid rgb(245, 154, 35);border-radius:4px;color: rgb(245, 154, 35);background-color:rgba(245, 154, 35,0.2)" v-if="scope.row.shareStatus==0">不共享</span>
             </template>
           </el-table-column>
-          <el-table-column label="专业类别" prop="disciplineTypeName" width="120" show-overflow-tooltip/>
+          <el-table-column label="课程分类" prop="disciplineTypeName" width="120" show-overflow-tooltip/>
           <el-table-column label="课件总数" prop="coursewareTotalCount" width="100" show-overflow-tooltip/>
           <el-table-column label="总时长" prop="totalLearningDuration" width="100" show-overflow-tooltip/>
           <el-table-column label="可得学时" prop="totalCreditHours" width="100" show-overflow-tooltip/>

+ 14 - 14
src/views/safetyEducationExaminationNew/courseManagement/coursewareManagement/addPage.vue

@@ -53,16 +53,16 @@
                 </el-switch>
                 <span style="margin-left:15px;">{{newData.shareStatus==1?'共享开启,全校所有学院单位都可见':'不共享,仅本学院单位及上级都可见'}}</span>
               </el-form-item>
-              <!--<el-form-item label="专业类别" prop="disciplineTypeId">-->
-                <!--<el-select v-model="newData.disciplineTypeId" placeholder="请选择专业类别" style="width: 400px">-->
-                  <!--<el-option-->
-                    <!--v-for="dict in optionListC"-->
-                    <!--:key="dict.id"-->
-                    <!--:label="dict.disciplineName"-->
-                    <!--:value="dict.id"-->
-                  <!--/>-->
-                <!--</el-select>-->
-              <!--</el-form-item>-->
+              <el-form-item label="课件分类" prop="disciplineTypeId">
+                <el-select v-model="newData.disciplineTypeId" placeholder="请选择课件分类" style="width: 400px">
+                  <el-option
+                    v-for="dict in optionListC"
+                    :key="dict.id"
+                    :label="dict.disciplineName"
+                    :value="dict.id"
+                  />
+                </el-select>
+              </el-form-item>
             </div>
           </div>
           <div class="form-box" v-if="newData.materialType == 1">
@@ -293,8 +293,8 @@
             { required: true, message: "请选择知识点", validator: this.spaceJudgment, trigger: "blur" }
           ],
           disciplineTypeId: [
-            { required: true, message: "请选择专业类别", trigger: "blur" },
-            { required: true, message: "请选择专业类别", validator: this.spaceJudgment, trigger: "blur" }
+            { required: true, message: "请选择课件分类", trigger: "blur" },
+            { required: true, message: "请选择课件分类", validator: this.spaceJudgment, trigger: "blur" }
           ],
           attachments: [
             { required: true, message: "请上传课件", trigger: "blur" },
@@ -365,7 +365,7 @@
     },
     mounted(){
       this.examElKnowledgePointTreeList();
-      // this.examElDisciplineTypeList();
+      this.examElDisciplineTypeList();
     },
     methods:{
       getData(){
@@ -375,7 +375,7 @@
               id:response.data.id,
               materialType:response.data.materialType,
               knowledgePointId:response.data.knowledgePointId,
-              disciplineTypeId:'',
+              disciplineTypeId:response.data.disciplineTypeId,
               watermark:response.data.watermark?response.data.watermark:'',
               coursewareName:response.data.coursewareName,
               minLearningDuration:response.data.minLearningDuration,

+ 21 - 2
src/views/safetyEducationExaminationNew/courseManagement/coursewareManagement/index.vue

@@ -55,6 +55,16 @@
               placeholder="来源"
             ></el-cascader>
           </el-form-item>
+          <el-form-item label="" prop="disciplineTypeId">
+            <el-select v-model="queryParams.disciplineTypeId" placeholder="课件分类" style="width: 200px">
+              <el-option
+                v-for="dict in disciplineOptionList"
+                :key="dict.id"
+                :label="dict.disciplineName"
+                :value="dict.id"
+              />
+            </el-select>
+          </el-form-item>
           <el-form-item label="" prop="searchValue">
             <el-input
               maxLength="30"
@@ -80,6 +90,7 @@
             </template>
           </el-table-column>
           <el-table-column label="知识点" prop="knowledgePointName" width="120" show-overflow-tooltip/>
+          <el-table-column label="课件分类" prop="disciplineTypeName" width="120" show-overflow-tooltip/>
           <!--<el-table-column label="专业类别" prop="content" width="100" show-overflow-tooltip/>-->
           <el-table-column label="是否共享" prop="shareStatus" width="100" show-overflow-tooltip>
             <template slot-scope="scope">
@@ -111,7 +122,7 @@
               <span>{{ parseTime(scope.row.createTime,"{y}-{m}-{d} {h}:{i}") }}</span>
             </template>
           </el-table-column>
-          <el-table-column label="操作" width="200" show-overflow-tooltip v-if="tableButtonType">
+          <el-table-column label="操作" width="140" show-overflow-tooltip v-if="tableButtonType">
             <template slot-scope="scope">
               <div class="table-button-box">
                 <p class="table-button-null"></p>
@@ -147,7 +158,7 @@
   import fullScreenFileLook from "@/components/fullScreenFileLook/fullScreenFileLook.vue";
   import {
     examElCoursewarePage,examElCoursewareDel,examElKnowledgePointTreeList,
-    systemDeptCurrentDept,examElCoursewareDetail
+    systemDeptCurrentDept,examElCoursewareDetail,examElDisciplineTypeList
   } from "@/api/safetyEducationExaminationNew/index";
   import addPage from "./addPage.vue";
   export default {
@@ -165,6 +176,7 @@
         optionListA:[{value:1,label:'视频'},{value:3,label:'文档'},{value:4,label:'文章'}],
         optionListB:[],
         optionListC:[],
+        disciplineOptionList:[],
         queryParams:{
           page:1,
           pageSize:20,
@@ -188,6 +200,7 @@
     mounted () {
       this.systemDeptCurrentDept();
       this.examElKnowledgePointTreeList();
+      this.examElDisciplineTypeList();
       this.getList();
     },
     methods: {
@@ -302,6 +315,12 @@
           this.$set(this,'optionListC',list);
         });
       },
+      //查询全部专业类别
+      examElDisciplineTypeList(){
+        examElDisciplineTypeList({}).then(response => {
+          this.$set(this,'disciplineOptionList',response.data);
+        });
+      },
     },
   }
 </script>

+ 6 - 2
src/views/safetyEducationExaminationNew/workbench/ExamSituation.vue

@@ -384,10 +384,14 @@ export default {
 <style scoped lang="scss">
 .exam-situation-card {
   background: #fff;
-  border-radius: 6px;
+  /*border-radius: 6px;*/
   padding: 20px;
   margin-bottom: 12px;
-  box-shadow: 0 1px 4px rgba(0,0,0,0.06);
+  /*box-shadow: 0 1px 4px rgba(0,0,0,0.06);*/
+  background: rgba(255, 255, 255, 0.95);
+  border: 1px solid #e8edf5;
+  border-radius: 16px;
+  box-shadow: 0 4px 20px rgba(37, 50, 74, 0.06);
 
   .card-header {
     display: flex;

+ 6 - 2
src/views/safetyEducationExaminationNew/workbench/LabPersonMatch.vue

@@ -213,10 +213,14 @@ export default {
 <style scoped lang="scss">
 .lab-person-card {
   background: #fff;
-  border-radius: 6px;
+  /*border-radius: 6px;*/
   padding: 20px;
   margin-bottom: 12px;
-  box-shadow: 0 1px 4px rgba(0,0,0,0.06);
+  /*box-shadow: 0 1px 4px rgba(0,0,0,0.06);*/
+  background: rgba(255, 255, 255, 0.95);
+  border: 1px solid #e8edf5;
+  border-radius: 16px;
+  box-shadow: 0 4px 20px rgba(37, 50, 74, 0.06);
 
   .card-header {
     display: flex;

+ 24 - 3
src/views/safetyEducationExaminationNew/workbench/StudyHourStats.vue

@@ -3,7 +3,7 @@
   <div class="study-hour-card">
     <div class="card-header">
       <span class="card-title">学时统计</span>
-      <p class="export-btn" @click="() => {}">
+      <p class="export-btn" @click="exportButton()">
         <i class="el-icon-download"></i> 导出数据
       </p>
     </div>
@@ -124,6 +124,23 @@ export default {
     if (this._barChart) this._barChart.dispose()
   },
   methods: {
+    //导出
+    exportButton(){
+      let self = this;
+      self.$confirm(`确认导出数据?`, "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(async () => {
+        let obj = {
+          academicYear:this.valueYear,
+          deptId:this.queryParams.deptId,
+          gradeNumber:this.queryParams.gradeNumber,
+          searchValue:this.queryParams.searchValue,
+        };
+        self.download('/exam/elStatistics/creditHour/export', {...obj}, '学时统计.xlsx')
+      }).catch(() => {})
+    },
     initBarChart() {
       const chart = echarts.init(this.$refs.barChart)
       this._barChart = chart
@@ -263,10 +280,14 @@ export default {
 <style scoped lang="scss">
 .study-hour-card {
   background: #fff;
-  border-radius: 6px;
+  /*border-radius: 6px;*/
   padding: 16px 20px;
   margin-bottom: 12px;
-  box-shadow: 0 1px 4px rgba(0,0,0,0.06);
+  /*box-shadow: 0 1px 4px rgba(0,0,0,0.06);*/
+  background: rgba(255, 255, 255, 0.95);
+  border: 1px solid #e8edf5;
+  border-radius: 16px;
+  box-shadow: 0 4px 20px rgba(37, 50, 74, 0.06);
 
   .card-header {
     display: flex;

+ 55 - 0
src/views/safetyEducationExaminationNew/dataStatistics/index.vue

@@ -0,0 +1,55 @@
+<!-- 数据统计 -->
+<template>
+  <div class="app-container dataStatistics">
+    <div class="page-container dataStatisticsPage scrollbar-box">
+      <!-- 考试情况统计 -->
+      <exam-situation/>
+      <!-- 实验室与人员匹配 -->
+      <lab-person-match/>
+      <!-- 学时统计 -->
+      <study-hour-stats/>
+    </div>
+  </div>
+</template>
+<script>
+  import ExamSituation from './ExamSituation.vue'
+  import LabPersonMatch from './LabPersonMatch.vue'
+  import StudyHourStats from './StudyHourStats.vue'
+  export default {
+    name: 'index',
+    components: {
+      ExamSituation,
+      LabPersonMatch,
+      StudyHourStats,
+    },
+    data() {
+      return {
+
+      }
+    },
+    created() {
+
+    },
+    mounted() {
+
+    },
+    methods: {
+
+    }
+  }
+</script>
+<style scoped lang="scss">
+  .dataStatistics {
+    flex: 1;
+    display: flex;
+    flex-direction: column;
+    overflow: hidden;
+    .dataStatisticsPage {
+      padding: 16px;
+      background: #f5f7fa;
+      overflow-y: scroll !important;
+      display: flex;
+      flex-direction: column;
+    }
+  }
+</style>

+ 54 - 6
src/views/safetyEducationExaminationNew/examManagement/examinationArrange/addPage.vue

@@ -30,15 +30,27 @@
                   <el-form-item label="考试类型" prop="examTypeId">
                     <el-select :disabled="showType" v-model="newData.examTypeId" placeholder="考试类型" @change="examChange" style="width:200px;">
                       <el-option v-for="item in optionExamType" :key="item.id" :label="item.examTypeName"
-                                 :value="item.id"
-                      />
+                                 :value="item.id"/>
+                    </el-select>
+                  </el-form-item>
+                  <el-form-item label="安全分类" v-if="!placementTest" :prop="placementTest?'disciplineTypeId':''">
+                    <el-select :disabled="showType" v-model="newData.disciplineTypeId" placeholder="安全分类" style="width:200px;">
+                      <el-option v-for="item in tableList" :key="item.id"
+                                 :label="item.disciplineName"
+                                 :value="item.id"/>
+                    </el-select>
+                  </el-form-item>
+                  <el-form-item label="安全分类" v-if="placementTest" :prop="placementTest?'disciplineTypeId':''">
+                    <el-select :disabled="showType" v-model="newData.disciplineTypeId" placeholder="安全分类" style="width:200px;">
+                      <el-option v-for="item in tableList2" :key="item.id"
+                                 :label="item.disciplineName"
+                                 :value="item.id"/>
                     </el-select>
                   </el-form-item>
                   <el-form-item label="风险等级" prop="riskLevelId" v-if="placementTest">
                     <el-select :disabled="showType" v-model="newData.riskLevelId" placeholder="请选择" style="width:200px;">
                       <el-option v-for="item in optionRiskLevel" :key="item.levelId" :label="item.titleName"
-                                 :value="item.levelId"
-                      />
+                                 :value="item.levelId"/>
                     </el-select>
                   </el-form-item>
                 </div>
@@ -581,7 +593,7 @@
   import selectScope from './selectScope.vue'
   import selectCertificate from './selectCertificate.vue'
   import {
-    examElExamAdd,examElExamEdit,examElExamDetail,examElKnowledgePointTreeList,
+    examElExamAdd,examElExamEdit,examElExamDetail,examElKnowledgePointTreeList,examElDisciplineTypeList,
     examElExamTypeList, laboratoryLevelConfigGetLevelTitleList,examElConfigMasterInitMinHour
   } from '@/api/safetyEducationExaminationNew/index'
 
@@ -713,6 +725,8 @@
         ],
         optionListC:[],
         optionExamType: [],
+        tableList: [],
+        tableList2: [],
         optionRiskLevel: [],
         scopeList: [],
         userList: [],
@@ -731,6 +745,7 @@
         },
         newData: {
           examTypeId: null,
+          disciplineTypeId: null,
           riskLevelId: null,
           examName: '',
           attemptLimit: 1,
@@ -779,6 +794,9 @@
           examTypeId: [
             { required: true, message: '请选择考试类型', trigger: 'change' }
           ],
+          disciplineTypeId: [
+            { required: true, message: '请选择安全分类', trigger: 'change' }
+          ],
           riskLevelId: [
             { required: true, message: '请选择风险等级', trigger: 'change' }
           ],
@@ -867,6 +885,7 @@
       this.laboratoryLevelConfigGetLevelTitleList();
       this.examElConfigMasterInitMinHour();
       this.examElKnowledgePointTreeList();
+      this.examElDisciplineTypeList();
     },
     methods: {
       initialize() {
@@ -881,6 +900,7 @@
             let obj = {
               id:this.propsData.id,
               examTypeId: response.data.examTypeId,
+              disciplineTypeId: response.data.disciplineTypeId,
               riskLevelId: response.data.riskLevelId,
               examName: response.data.examName,
               attemptLimit: response.data.attemptLimit,
@@ -939,7 +959,7 @@
           if (!valid) {
             const firstErrorField = Object.keys(fields)[0]
             const tabFieldMap = [
-              { tab: 'basic', list: ['examTypeId','riskLevelId','examName','attemptLimit','paperId','enableStatus','answerDuration','scopeType','examTimeRange'] },
+              { tab: 'basic', list: ['examTypeId','disciplineTypeId','riskLevelId','examName','attemptLimit','paperId','enableStatus','answerDuration','scopeType','examTimeRange'] },
               { tab: 'preExam', list: ['studyHoursRequirementEnabled','preCourseEnabled','mockEnabled','commitmentEnabled'] },
               // { tab: 'antiCheat', list: ['popupVerifyEnabled'] },
               { tab: 'certificate', list: ['certificateEnabled','certificateValidMonths','certificateReviewMonths'] }
@@ -963,6 +983,7 @@
         let self = this;
         let obj = {
           examTypeId:this.newData.examTypeId,
+          disciplineTypeId:this.newData.disciplineTypeId,
           riskLevelId:this.placementTest?this.newData.riskLevelId:'',
           examName:this.newData.examName,
           attemptLimit:this.answerUnlimited?0:this.newData.attemptLimit,
@@ -1121,8 +1142,26 @@
           if (self.optionExamType[i].id == self.newData.examTypeId) {
             if (self.optionExamType[i].examTypeCode == 'CLASSIFIED') {
               self.$set(this, 'placementTest', true)
+              let num = 0;
+              for(let o=0;o<self.tableList2.length;o++){
+                if(self.newData.disciplineTypeId == self.tableList2[o].id){
+                  num++
+                }
+              }
+              if(num == 0){
+                self.$set(self.newData,'disciplineTypeId',null);
+              }
             } else {
               self.$set(this, 'placementTest', false)
+              let num = 0;
+              for(let o=0;o<self.tableList.length;o++){
+                if(self.newData.disciplineTypeId == self.tableList[o].id){
+                  num++
+                }
+              }
+              if(num == 0){
+                self.$set(self.newData,'disciplineTypeId',null);
+              }
             }
             if (self.optionExamType[i].examTypeCode == 'yzyh') {
               self.$set(this, 'yzyhTest', true)
@@ -1170,6 +1209,15 @@
           this.$set(this, 'optionListC', list);
         });
       },
+      //类型选项卡数据
+      examElDisciplineTypeList(){
+        examElDisciplineTypeList({}).then(response => {
+          const validCodes = ['CHEMISTRY', 'BIOLOGY', 'RADIATION', 'MECHANICAL_ELECTRICAL', 'OTHER'];
+          let list = response.data.filter(item => validCodes.includes(item.disciplineTypeCode));
+          this.$set(this, 'tableList', response.data)
+          this.$set(this, 'tableList2', list)
+        })
+      },
     }
   }
 </script>

+ 3 - 1
src/views/safetyEducationExaminationNew/examManagement/examinationArrange/index.vue

@@ -100,7 +100,7 @@
             </template>
           </el-table-column>
           <el-table-column label="考试类型" prop="examTypeName" width="140" show-overflow-tooltip/>
-          <el-table-column label="专业类别" prop="disciplineTypeName" width="140" show-overflow-tooltip/>
+          <el-table-column label="安全分类" prop="disciplineTypeName" width="140" show-overflow-tooltip/>
           <el-table-column label="是否共享" prop="shareStatus" width="120" show-overflow-tooltip>
             <template slot-scope="scope">
               <span style="padding:2px 10px;border:1px solid rgb(1, 131, 251);border-radius:4px;color: rgb(1, 131, 251);background-color:rgba(1, 131, 251,0.2)" v-if="scope.row.shareStatus==1">共享</span>
@@ -137,6 +137,7 @@
                    @click="tableButton(2,scope.row)"
                 >补考</p>
                 <p class="table-button-p"
+                   v-if="scope.row.canEditDelete"
                    v-hasPermiRouter="['exam:elExam:edit']"
                    @click="tableButton(3,scope.row)"
                 >编辑</p>
@@ -145,6 +146,7 @@
                    @click="tableButton(4,scope.row)"
                 >复制</p>
                 <p class="table-button-p"
+                   v-if="scope.row.canEditDelete"
                    v-hasPermiRouter="['exam:elExam:del']"
                    @click="tableButton(5,scope.row)"
                 >删除</p>

+ 5 - 0
src/views/safetyEducationExaminationNew/examManagement/examinationResult/academicPerformance.vue

@@ -52,6 +52,11 @@
         </el-table-column>
         <el-table-column label="学时" prop="rewardCreditHours" width="200" show-overflow-tooltip/>
         <el-table-column label="积分" prop="rewardPoints" width="200" show-overflow-tooltip/>
+        <el-table-column label="是否完成" prop="passStatus" width="200" show-overflow-tooltip>
+          <template slot-scope="scope">
+            <span>{{ scope.row.passStatus == 1?'已完成':'未完成' }}</span>
+          </template>
+        </el-table-column>
       </el-table>
       <pagination :page-sizes="[20, 30, 40, 50]"
                   v-show="total>0"

+ 3 - 3
src/views/safetyEducationExaminationNew/examManagement/testPaperManagement/addPage.vue

@@ -69,8 +69,8 @@
 
           <!-- 专业类别 / 是否共享 -->
           <div class="flex-row-box">
-            <el-form-item label="专业类别" prop="disciplineTypeId">
-              <el-select :disabled="showType" v-model="newData.disciplineTypeId" placeholder="专业类别" style="width:200px;">
+            <el-form-item label="试卷分类" prop="disciplineTypeId">
+              <el-select :disabled="showType" v-model="newData.disciplineTypeId" placeholder="试卷分类" style="width:200px;">
                 <el-option
                   v-for="item in optionListA"
                   :key="item.id"
@@ -761,7 +761,7 @@
       },
       //知识点
       examElKnowledgePointTreeList() {
-        examElKnowledgePointTreeList({}).then(response => {
+        examElKnowledgePointTreeList({dataScope:2}).then(response => {
           const list = response.data || []
           this.formatTreeData(list)
           this.$set(this, 'optionListKnowledge', list)

+ 5 - 5
src/views/safetyEducationExaminationNew/examManagement/testPaperManagement/index.vue

@@ -46,9 +46,9 @@
             ></el-cascader>
           </el-form-item>
           <el-form-item label="" prop="disciplineTypeId">
-            <el-select v-model="queryParams.disciplineTypeId" placeholder="专业类别" style="width: 140px">
+            <el-select v-model="queryParams.disciplineTypeId" placeholder="试卷分类" style="width: 200px">
               <el-option
-                v-for="dict in optionListD"
+                v-for="dict in disciplineOptionList"
                 :key="dict.id"
                 :label="dict.disciplineName"
                 :value="dict.id"
@@ -91,7 +91,7 @@
             </template>
           </el-table-column>
           <el-table-column label="知识点" prop="knowledgePointNames" width="160" show-overflow-tooltip/>
-          <el-table-column label="专业类别" prop="disciplineTypeName" width="120" show-overflow-tooltip/>
+          <el-table-column label="试卷分类" prop="disciplineTypeName" width="120" show-overflow-tooltip/>
           <el-table-column label="是否共享" prop="shareStatus" width="120" show-overflow-tooltip>
             <template slot-scope="scope">
               <span style="padding:2px 10px;border:1px solid rgb(1, 131, 251);border-radius:4px;color: rgb(1, 131, 251);background-color:rgba(1, 131, 251,0.2)" v-if="scope.row.shareStatus==1">共享</span>
@@ -163,7 +163,7 @@
         //下拉列表数据
         optionListB:[],
         optionListC:[],
-        optionListD:[],
+        disciplineOptionList:[],
         //查询条件
         queryParams:{
           page:1,
@@ -291,7 +291,7 @@
       //查询全部专业类别
       examElDisciplineTypeList(){
         examElDisciplineTypeList({}).then(response => {
-          this.$set(this,'optionListD',response.data);
+          this.$set(this,'disciplineOptionList',response.data);
         });
       },
     },

+ 3 - 3
src/views/safetyEducationExaminationNew/featurePage/learningCourse/index.vue

@@ -106,8 +106,8 @@
     methods: {
       //初始化
       initialization(){
-        this.$set(this,'courseId',this.$route.params.courseId)
-        this.$set(this,'examId',this.$route.params.examId)
+        this.$set(this,'courseId',this.$route.query.courseId)
+        this.$set(this,'examId',this.$route.query.examId)
         this.$nextTick(()=>{
           this.examUserCourseLearningCoursewareList();
         })
@@ -390,7 +390,7 @@
         margin:20px 20px;
         border-radius:10px;
         overflow: hidden;
-        box-shadow: 0 0 15px rgba(0, 0, 0, 0.4);
+        box-shadow: 0 2px 8px rgba(37, 50, 74, 0.12);
         border:1px solid #dedede;
       }
       .right-max-big-box{

+ 2 - 2
src/views/safetyEducationExaminationNew/featurePage/learningMaterials/index.vue

@@ -87,7 +87,7 @@
     methods: {
       //初始化
       initialization(){
-        this.$set(this,'coursewareId',this.$route.params.coursewareId)
+        this.$set(this,'coursewareId',this.$route.query.coursewareId)
         this.$nextTick(()=>{
           this.examUserCoursewareLearningDetail();
         })
@@ -290,7 +290,7 @@
         margin:20px 20px;
         border-radius:10px;
         overflow: hidden;
-        box-shadow: 0 0 15px rgba(0, 0, 0, 0.4);
+        box-shadow: 0 2px 8px rgba(37, 50, 74, 0.12);
         border:1px solid #dedede;
       }
       .right-max-big-box{

+ 2 - 2
src/views/safetyEducationExaminationNew/featurePage/mockExam/index.vue

@@ -226,8 +226,8 @@
     },
     methods: {
       initialize() {
-        if (this.$route.params) {
-          this.$set(this, 'newData', this.$route.params)
+        if (this.$route.query) {
+          this.$set(this, 'newData', this.$route.query)
         } else {
           this.$router.back()
           return

+ 2 - 2
src/views/safetyEducationExaminationNew/featurePage/startPracticing/index.vue

@@ -208,8 +208,8 @@
     },
     methods: {
       initialize() {
-        if (this.$route.params) {
-          this.$set(this, 'newData', this.$route.params)
+        if (this.$route.query) {
+          this.$set(this, 'newData', this.$route.query)
         } else {
           this.$router.back()
           return

+ 2 - 2
src/views/safetyEducationExaminationNew/featurePage/startTheExam/index.vue

@@ -176,8 +176,8 @@
     },
     methods: {
       initialize() {
-        if (this.$route.params) {
-          this.$set(this, 'newData', this.$route.params)
+        if (this.$route.query) {
+          this.$set(this, 'newData', this.$route.query)
         } else {
           this.$router.back()
           return

+ 2 - 2
src/views/safetyEducationExaminationNew/featurePage/startTraining/index.vue

@@ -193,8 +193,8 @@
     },
     methods: {
       initialize() {
-        if (this.$route.params) {
-          this.$set(this, 'newData', this.$route.params)
+        if (this.$route.query) {
+          this.$set(this, 'newData', this.$route.query)
         } else {
           this.$router.back()
           return

+ 5 - 7
src/views/safetyEducationExaminationNew/workbench/LabBindingApply.vue

@@ -1,6 +1,6 @@
 <!-- 实验室绑定申请 -->
 <template>
-  <div class="lab-binding-card" v-show="dataList[0]||showType">
+  <div class="app-container lab-binding-card">
     <div class="card-header">
       <span class="card-title">实验室绑定申请</span>
       <div class="header-right">
@@ -121,7 +121,6 @@ export default {
       dataList: [],
       //数据数量
       total: 0,
-      showType:false,
       dialogType:false,
       dialogData:{
         reason:'',
@@ -198,9 +197,6 @@ export default {
       let obj = JSON.parse(JSON.stringify(this.queryParams))
       obj.statusCode = this.filterData.activeStatus;
       examElLabEduRelationAuditList(obj).then(response => {
-        if(response.data.records[0]){
-          this.$set(this,'showType',true);
-        }
         this.$set(this, 'dataList', response.data.records)
         this.$set(this, 'total', response.data.total)
       })
@@ -212,10 +208,12 @@ export default {
 <style scoped lang="scss">
 .lab-binding-card {
   background: #fff;
-  border-radius: 6px;
+  /*border-radius: 6px;*/
   padding: 20px;
   margin-bottom: 12px;
-  box-shadow: 0 1px 4px rgba(0,0,0,0.06);
+  /*box-shadow: 0 1px 4px rgba(0,0,0,0.06);*/
+  background: rgba(255, 255, 255, 0.95);
+  box-shadow: 0 4px 20px rgba(37, 50, 74, 0.06);
 
   .card-header {
     display: flex;

+ 314 - 0
src/views/safetyEducationExaminationNew/personnelApproval/index.vue

@@ -0,0 +1,314 @@
+<!-- 实验室绑定申请 -->
+<template>
+  <div class="app-container lab-binding-card">
+    <div class="page-container">
+      <div class="card-header">
+        <span class="card-title">实验室绑定申请</span>
+        <div class="header-right">
+          <!-- 分组筛选按钮 -->
+          <div class="table-top-button-box">
+            <div>
+              <p
+                v-for="(btn, i) in filterData.statusBtns" :key="btn.value"
+                :class="filterData.activeStatus === btn.value ? 'check-table-button' : ''"
+                @click="checkButton(btn.value)"
+              >{{ btn.label }}</p>
+            </div>
+          </div>
+        </div>
+      </div>
+      <div class="page-content-box">
+        <el-table class="table-box" :data="dataList" border>
+          <el-table-column prop="userName" label="申请人" width="80" show-overflow-tooltip/>
+          <el-table-column prop="userAccount" label="学号" width="110" show-overflow-tooltip/>
+          <el-table-column prop="educationName" label="用户类型" width="100" show-overflow-tooltip/>
+          <el-table-column prop="deptName" label="所属学院" min-width="120" show-overflow-tooltip />
+          <el-table-column prop="subName" label="申请实验室" min-width="160" show-overflow-tooltip />
+          <el-table-column prop="levelName" label="分级" width="70" align="center" show-overflow-tooltip>
+            <template slot-scope="scope">
+              <span :style="'color:'+scope.row.levelColor+';'">{{ scope.row.levelName }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="typeName" label="分类" width="120" />
+          <el-table-column prop="reason" label="进入原因" min-width="120" show-overflow-tooltip />
+          <el-table-column prop="submitTime" label="提交时间" width="150" show-overflow-tooltip>
+            <template slot-scope="scope">
+              <span>{{ parseTime(scope.row.submitTime,"{y}-{m}-{d} {h}:{i}") }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="approveTime" label="通过时间" width="150" show-overflow-tooltip>
+            <template slot-scope="scope">
+              <span>{{ parseTime(scope.row.approveTime,"{y}-{m}-{d} {h}:{i}") }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="statusCode" label="状态" width="80" align="center" show-overflow-tooltip>
+            <template slot-scope="scope">
+            <span :class="scope.row.statusCode==0?'status-txt-a':(scope.row.statusCode==1?'status-txt-b':(scope.row.statusCode==2?'status-txt-c':''))">
+              {{ scope.row.statusCode==0?'待审批':(scope.row.statusCode==1?'已通过':(scope.row.statusCode==2?'已驳回':'')) }}
+            </span>
+            </template>
+          </el-table-column>
+          <el-table-column label="操作" min-width="130" align="left">
+            <template slot-scope="scope">
+              <p class="button-color-a" v-if="scope.row.statusCode==0" @click="tableButton(1,scope.row)">通过</p>
+              <p class="button-color-b" v-if="scope.row.statusCode==0" @click="tableButton(2,scope.row)">驳回</p>
+            </template>
+          </el-table-column>
+        </el-table>
+        <pagination :page-sizes="[20, 30, 40, 50]"
+                    v-show="total>0"
+                    :total="total"
+                    :page.sync="queryParams.page"
+                    :limit.sync="queryParams.pageSize"
+                    @pagination="getList"
+        />
+      </div>
+      <el-dialog class="slab-binding-card-dialog"
+                 :modal-append-to-body="false"
+                 :close-on-click-modal="false" :close-on-press-escape="false"
+                 title="驳回申请"
+                 :visible.sync="dialogType"
+                 v-if="dialogType"
+                 width="560px"
+                 append-to-body>
+        <div style="min-height:60px;overflow: hidden">
+          <div>
+            <el-form :model="dialogData" ref="dialogForm" :rules="dialogRules">
+              <el-form-item label="" prop="reason" label-width="0">
+                <el-input
+                  type="textarea"
+                  :autosize="{ minRows: 4, maxRows: 4}"
+                  placeholder="请输入原因"
+                  maxLength="100"
+                  resize="none"
+                  style="width: 520px"
+                  v-model="dialogData.reason">
+                </el-input>
+              </el-form-item>
+            </el-form>
+          </div>
+        </div>
+        <div slot="footer" class="dialog-footer dialog-footer-box">
+          <p class="dialog-footer-button-null"></p>
+          <p class="dialog-footer-button-info" @click="dialogCancel">取消</p>
+          <p class="dialog-footer-button-primary" @click="dialogSubmit">提交</p>
+          <p class="dialog-footer-button-null"></p>
+        </div>
+      </el-dialog>
+    </div>
+  </div>
+</template>
+
+<script>
+  import {
+    examElLabEduRelationAuditList,examElLabEduRelationAudit,
+  } from "@/api/safetyEducationExaminationNew/index";
+  export default {
+    name: 'LabBindingApply',
+    data() {
+      return {
+        filterData: {
+          activeStatus: '',
+          statusBtns: [
+            { label: '全部',   value: '' },
+            { label: '待审批', value: '0' },
+            { label: '已通过', value: '1' },
+            { label: '已驳回', value: '2' },
+          ]
+        },
+        queryParams: {
+          page: 1,
+          pageSize: 20,
+        },
+        dataList: [],
+        //数据数量
+        total: 0,
+        dialogType:false,
+        dialogData:{
+          reason:'',
+        },
+        dialogRules:{
+          reason: [
+            { required: true, message: "请输入驳回原因", trigger: "blur" }
+          ],
+        },
+        checkId:null,
+      }
+    },
+    mounted(){
+      this.getList();
+    },
+    methods: {
+      checkButton(val){
+        if(this.filterData.activeStatus != val){
+          this.$set(this.filterData,'activeStatus',val);
+          this.handleQuery();
+        }
+      },
+      tableButton(val,row){
+        let self = this;
+        this.$set(this,'checkId',row.id);
+        this.$set(this.dialogData,'reason','');
+        if (val == 1){
+          //通过
+          this.$confirm('确认审核通过?', "提示", {
+            confirmButtonText: "确认",
+            cancelButtonText: "取消",
+            type: "warning"
+          }).then(function() {
+          }).then(() => {
+            self.examElLabEduRelationAudit(1)
+          }).catch(() => {});
+        } else {
+          //驳回
+          this.$set(this,'dialogType',true);
+        }
+      },
+      //提交按钮
+      dialogSubmit(){
+        let self = this;
+        this.$refs["dialogForm"].validate(valid => {
+          if (valid) {
+            self.examElLabEduRelationAudit(2)
+          }
+        })
+      },
+      examElLabEduRelationAudit(statusCode){
+        let obj = {
+          id:this.checkId,
+          statusCode:statusCode,
+          reason:this.dialogData.reason,
+        }
+        examElLabEduRelationAudit(obj).then(response => {
+          this.msgSuccess(response.message)
+          this.$set(this,'dialogType',false);
+          this.getList();
+        })
+      },
+      //关闭按钮
+      dialogCancel(){
+        this.$set(this,'dialogType',false);
+      },
+      //查询按钮
+      handleQuery() {
+        this.$set(this.queryParams, 'page', 1)
+        this.getList()
+      },
+      //获取数据列表
+      getList() {
+        let obj = JSON.parse(JSON.stringify(this.queryParams))
+        obj.statusCode = this.filterData.activeStatus;
+        examElLabEduRelationAuditList(obj).then(response => {
+          this.$set(this, 'dataList', response.data.records)
+          this.$set(this, 'total', response.data.total)
+        })
+      },
+    },
+  }
+</script>
+
+<style scoped lang="scss">
+  .lab-binding-card {
+    padding:20px;
+
+    .card-header {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      margin-bottom: 16px;
+
+      .card-title {
+        font-size: 16px;
+        font-weight: 700;
+        color: #222;
+      }
+
+      .header-right {
+        display: flex;
+        align-items: center;
+        gap: 20px;
+      }
+    }
+    .page-content-box{
+      height:500px;
+      padding:0;
+    }
+
+    /* 分组筛选按钮 — 与其他页面保持一致 */
+    .table-top-button-box {
+      display: inline-block;
+      vertical-align: top;
+
+      div {
+        display: flex;
+
+        p {
+          border: 1px solid #DCDFE6;
+          width: 80px;
+          text-align: center;
+          height: 40px;
+          line-height: 40px;
+          cursor: pointer;
+          font-size: 14px;
+
+          &:nth-child(1) {
+            border-top-left-radius: 4px;
+            border-bottom-left-radius: 4px;
+          }
+          &:nth-child(2) { border-left: none; }
+          &:nth-child(3) { border-left: none; border-right: none; }
+          &:nth-child(4) {
+            border-top-right-radius: 4px;
+            border-bottom-right-radius: 4px;
+          }
+
+          &.check-table-button {
+            border: 1px solid #0183fa;
+            background-color: #0183fa;
+            color: #fff;
+          }
+        }
+      }
+    }
+    .button-color-a{
+      width:60px;
+      cursor: pointer;
+      margin-right:10px;
+      display: inline-block;
+      text-align: center;
+      line-height:24px;
+      border-radius:4px;
+      border: 1px solid #00B176;
+      color: #fff;
+      background-color: #00B176;
+    }
+    .button-color-b{
+      width:60px;
+      cursor: pointer;
+      display: inline-block;
+      text-align: center;
+      line-height:24px;
+      border-radius:4px;
+      border: 1px solid #E86452;
+      color: #fff;
+      background-color: #E86452;
+    }
+    .status-txt-a{
+      color: #F59A48;
+    }
+    .status-txt-b{
+      color: #00B176;
+    }
+    .status-txt-c{
+      color: #E86452;
+    }
+
+    ::v-deep .row-reject td {
+      background: #fffafa !important;
+    }
+
+    ::v-deep .el-table td {
+      padding: 10px 0;
+    }
+  }
+</style>

+ 17 - 4
src/views/safetyEducationExaminationNew/publicConfiguration/basicConfiguration/index.vue

@@ -10,6 +10,7 @@
     <div class="bottom-max-big-box">
       <div class="left-max-big-box">
         <p class="left-for-p" :class="item.value == buttonType?'check-button-p':''"
+           v-show="shouldShowItem(item)"
            @click="tableButton(item.value)"
            v-for="(item,index) in buttonList" :key="index">{{item.name}}</p>
       </div>
@@ -22,9 +23,7 @@
   </div>
 </template>
 <script>
-  //import { getDicts } from "@/api/commonality/noPermission";
-  //import { systemUserSelect } from "@/api/commonality/permission";
-  //import { getInfo } from "@/api/basicsModules/index";
+  import store from '@/store'
   import examinationConfiguration from "./examinationConfiguration.vue";
   import specialtyConfiguration from "./specialtyConfiguration.vue";
   import gradingConfiguration from "./gradingConfiguration.vue";
@@ -52,13 +51,20 @@
           {name:'学时积分配置',value:'4'},
           {name:'其他配置',value:'5'},
         ],
+        //管理权限
+        sustainType:false,
       }
     },
     created () {
 
     },
     mounted () {
-
+      let permissions = store.getters.permissions;
+      if(permissions[0] == "*:*:*"){
+        this.$set(this,'sustainType',true);
+      }else{
+        this.$set(this,'sustainType',false);
+      }
     },
     methods: {
       tableButton(val){
@@ -93,6 +99,13 @@
           this.$refs.otherConfiguration.submitButton();
         }
       },
+      shouldShowItem(item){
+        if(this.sustainType){
+          return true
+        }else{
+          return item.value != 2;
+        }
+      },
     },
   }
 </script>

+ 1 - 1
src/views/safetyEducationExaminationNew/questionBankManagement/practiceSolvingProblems/index.vue

@@ -192,7 +192,7 @@
       },
       //知识点
       examElKnowledgePointTreeList(){
-        examElKnowledgePointTreeList({}).then(response => {
+        examElKnowledgePointTreeList({ dataScope:2 }).then(response => {
           const list = response.data || [];
           this.formatTreeData(list);
           this.$set(this, 'optionListC', list);

+ 32 - 9
src/views/safetyEducationExaminationNew/questionBankManagement/questionBankManagement/addPage.vue

@@ -22,7 +22,7 @@
               <span style="margin-left:15px;line-height:40px;color:#999;">{{newData.shareStatus==1?'共享开启,全校所有学院单位都可见':'不共享,仅本学院单位及上级都可见'}}</span>
             </el-form-item>
             <el-form-item label="试题类型" prop="questionType" label-width="100px">
-              <el-select v-model="newData.questionType" @change="answersScreening()" placeholder="试题类型" style="width: 180px">
+              <el-select v-model="newData.questionType" @change="answersScreening()" placeholder="试题类型" style="width: 160px">
                 <el-option
                   v-for="dict in optionListA"
                   :key="dict.value"
@@ -32,7 +32,7 @@
               </el-select>
             </el-form-item>
             <el-form-item label="难度" prop="difficulty" label-width="70px">
-              <el-select v-model="newData.difficulty" placeholder="难度" style="width: 180px">
+              <el-select v-model="newData.difficulty" placeholder="难度" style="width: 160px">
                 <el-option
                   v-for="dict in optionListC"
                   :key="dict.value"
@@ -41,9 +41,9 @@
                 />
               </el-select>
             </el-form-item>
-            <el-form-item label="知识点" prop="knowledgePointIds" label-width="90px">
+            <el-form-item label="知识点" prop="knowledgePointIds" label-width="85px">
               <el-cascader
-                style="width: 490px"
+                style="width: 220px"
                 v-model="newData.knowledgePointIds"
                 :options="optionListB"
                 :props="{
@@ -59,6 +59,16 @@
                 placeholder="知识点"
               ></el-cascader>
             </el-form-item>
+            <el-form-item label="试题分类" prop="disciplineTypeId" label-width="95px">
+              <el-select :disabled="showType" v-model="newData.disciplineTypeId" placeholder="试题分类" style="width:220px;">
+                <el-option
+                  v-for="item in optionListD"
+                  :key="item.id"
+                  :label="item.disciplineName"
+                  :value="item.id"
+                />
+              </el-select>
+            </el-form-item>
           </div>
         </div>
         <div class="title-content-box">
@@ -152,7 +162,7 @@
   //import { systemUserSelect } from "@/api/commonality/permission";
   import {
     examElKnowledgePointTreeList,examElQuestionBankDetail,
-    examElQuestionBankAdd,examElQuestionBankEdit,
+    examElQuestionBankAdd,examElQuestionBankEdit,examElDisciplineTypeList,
   } from "@/api/safetyEducationExaminationNew/index";
   import TinymceContainer from "@/components/tinymceContainer/index.vue";
   import { getToken } from "@/utils/auth";
@@ -167,9 +177,11 @@
         optionListA:[{value:1,label:'单选'},{value:2,label:'多选'},{value:3,label:'判断'}],
         optionListB:[],
         optionListC:[{value:1,label:'简单'},{value:2,label:'一般'},{value:3,label:'较难'},{value:4,label:'极难'}],
+        optionListD:[],
         newData: {
           questionType:null,
           knowledgePointIds:[],
+          disciplineTypeId:null,
           shareStatus:1,
           difficulty:null,
           questionContent:"",
@@ -192,6 +204,10 @@
             { required: true, message: "请选择知识点", trigger: "blur" },
             { required: true, message: "请选择知识点", validator: this.spaceJudgment, trigger: "blur" }
           ],
+          disciplineTypeId: [
+            { required: true, message: "请选择试题分类", trigger: "blur" },
+            { required: true, message: "请选择试题分类", validator: this.spaceJudgment, trigger: "blur" }
+          ],
           difficulty: [
             { required: true, message: "请选择难度", trigger: "blur" },
             { required: true, message: "请选择难度", validator: this.spaceJudgment, trigger: "blur" }
@@ -207,10 +223,8 @@
           // 假设最多只能选 2 个
           if (newVal && newVal.length > 10) {
             this.msgError('最多选择10个知识点')
-            this.$nextTick(() => {
-              // 将值回退到上一次的状态
-              this.newData.knowledgePointIds = oldVal;
-            });
+            // 将值回退到上一次的状态
+            this.newData.knowledgePointIds = oldVal;
           }
         },
         deep: true, // 关键:必须开启深度监听
@@ -225,6 +239,7 @@
         this.examElQuestionBankDetail();
       }
       this.examElKnowledgePointTreeList();
+      this.examElDisciplineTypeList();
     },
     methods: {
       examElQuestionBankDetail(){
@@ -233,6 +248,7 @@
             id:this.propsData.id,
             questionType:response.data.questionType,
             knowledgePointIds:response.data.knowledgePointIds,
+            disciplineTypeId:response.data.disciplineTypeId,
             shareStatus:response.data.shareStatus,
             difficulty:response.data.difficulty,
             questionContent:response.data.questionContent,
@@ -335,6 +351,7 @@
           questionContent:this.newData.questionContent,
           questionType:this.newData.questionType,
           knowledgePointIds:this.newData.knowledgePointIds,
+          disciplineTypeId:this.newData.disciplineTypeId,
           difficulty:this.newData.difficulty,
           correctAnswer:'',
           analysis:this.newData.analysis,
@@ -508,6 +525,12 @@
           this.$set(this, 'optionListB', list);
         });
       },
+      //查询全部专业类别
+      examElDisciplineTypeList() {
+        examElDisciplineTypeList({}).then(response => {
+          this.$set(this, 'optionListD', response.data)
+        })
+      },
       /** 将下标转换为字母*/
       getLetter(index) {
         if (typeof index !== 'number' || index < 0 || index >= 26) {

+ 22 - 4
src/views/safetyEducationExaminationNew/questionBankManagement/questionBankManagement/index.vue

@@ -52,6 +52,16 @@
               />
             </el-select>
           </el-form-item>
+          <el-form-item label="" prop="disciplineTypeId">
+            <el-select v-model="queryParams.disciplineTypeId" placeholder="试题分类" style="width: 200px">
+              <el-option
+                v-for="dict in disciplineOptionList"
+                :key="dict.id"
+                :label="dict.disciplineName"
+                :value="dict.id"
+              />
+            </el-select>
+          </el-form-item>
           <el-form-item label="" prop="questionContent">
             <el-input
               maxLength="30"
@@ -141,7 +151,7 @@
 <script>
   //import { getDicts } from "@/api/commonality/noPermission";
   //import { systemUserSelect } from "@/api/commonality/permission";
-  import { examElKnowledgePointTreeList,examElQuestionBankList,examElQuestionBankDel } from "@/api/safetyEducationExaminationNew/index";
+  import { examElKnowledgePointTreeList,examElQuestionBankList,examElQuestionBankDel,examElDisciplineTypeList } from "@/api/safetyEducationExaminationNew/index";
   import importComponent from "@/components/importComponent/importComponent.vue";
   import answerKey from "@/views/safetyEducationExaminationNew/components/answerKey.vue";
   import addPage from "./addPage.vue";
@@ -172,12 +182,14 @@
         optionListB:[],
         optionListC:[{value:1,label:'单选'},{value:2,label:'多选'},{value:3,label:'判断'}],
         optionListD:[{value:1,label:'简单'},{value:2,label:'一般'},{value:3,label:'较难'},{value:4,label:'极难'}],
+        disciplineOptionList:[],
         //查询条件
         queryParams:{
           page:1,
           pageSize:20,
           shareStatus:null,
           knowledgePointId :null,
+          disciplineTypeId: '',
           questionType :null,
           difficulty :null,
           questionContent :'',
@@ -200,6 +212,7 @@
     },
     mounted () {
       this.examElKnowledgePointTreeList();
+      this.examElDisciplineTypeList();
       this.getList();
     },
     methods: {
@@ -227,6 +240,7 @@
           pageSize:20,
           shareStatus:null,
           knowledgePointId :null,
+          disciplineTypeId: '',
           questionType :null,
           difficulty :null,
           questionContent :'',
@@ -235,10 +249,8 @@
       },
       //获取数据列表
       getList(){
-
         let obj = JSON.parse(JSON.stringify(this.queryParams))
         examElQuestionBankList(obj).then(response => {
-
           this.$set(this,'dataList',response.data.records);
           this.$set(this,'total',response.data.total);
         });
@@ -283,12 +295,18 @@
         }
       },
       examElKnowledgePointTreeList(){
-        examElKnowledgePointTreeList({}).then(response => {
+        examElKnowledgePointTreeList({ dataScope:2 }).then(response => {
           const list = response.data || [];
           this.formatTreeData(list);
           this.$set(this, 'optionListB', list);
         });
       },
+      //查询全部专业类别
+      examElDisciplineTypeList(){
+        examElDisciplineTypeList({}).then(response => {
+          this.$set(this,'disciplineOptionList',response.data);
+        });
+      },
     },
   }
 </script>

+ 62 - 22
src/views/safetyEducationExaminationNew/safetyEducation/knowledgeLearning/index.vue

@@ -18,8 +18,8 @@
                      :inline="true" style="width:100%;">
               <div class="table-top-button-box-2">
                 <div>
-                  <p :class="topButtonIndex === 1?'check-table-button':''" @click="topCheckButton(1)">视频资源</p>
-                  <p :class="topButtonIndex === 2?'check-table-button':''" @click="topCheckButton(2)">文档文章</p>
+                  <p :class="topButtonIndex == 1?'check-table-button':''" @click="topCheckButton(1)">视频资源</p>
+                  <p :class="topButtonIndex == 2?'check-table-button':''" @click="topCheckButton(2)">文档文章</p>
                 </div>
               </div>
               <div class="table-top-button-box">
@@ -47,6 +47,16 @@
                   placeholder="知识点"
                 ></el-cascader>
               </el-form-item>
+              <el-form-item label="" prop="disciplineTypeId">
+                <el-select v-model="queryParams.disciplineTypeId" placeholder="知识分类" style="width: 200px">
+                  <el-option
+                    v-for="dict in disciplineOptionList"
+                    :key="dict.id"
+                    :label="dict.disciplineName"
+                    :value="dict.id"
+                  />
+                </el-select>
+              </el-form-item>
               <el-form-item label="" prop="coursewareName">
                 <el-input
                   maxLength="30"
@@ -63,7 +73,7 @@
             <div class="for-max-big-box scrollbar-box">
               <p class="null-text-p" v-if="!dataList[0]">暂无数据</p>
               <div class="for-big-box" v-for="(item,index) in dataList" :key="index" @click="tableButton(item)">
-                <img v-if="item.materialType == 1" :src="item.exampleImg">
+                <img v-if="item.materialType == 1&&item.exampleImg" :src="item.exampleImg">
                 <img v-else src="@/assets/ZDimages/basicsModules/image_986222064626770.png">
                 <div class="bottom-big-box">
                   <p class="name-p">{{item.coursewareName}}</p>
@@ -91,7 +101,10 @@
   //import { systemUserSelect } from "@/api/commonality/permission";
   //import { getInfo } from "@/api/basicsModules/index";
   //import addPage from "./addPage.vue";
-  import { examUserCoursewareLearningList,examElKnowledgePointTreeList,examUserCoursewareLearningRestart, } from "@/api/safetyEducationExaminationNew/index";
+  import {
+    examUserCoursewareLearningList,examElKnowledgePointTreeList,
+    examUserCoursewareLearningRestart,examElDisciplineTypeList,
+  } from "@/api/safetyEducationExaminationNew/index";
   export default {
     name: 'index',
     //components: {
@@ -99,19 +112,19 @@
     //},
     data() {
       return {
-        //页面状态
-        pageType: 1,
         letDataList:[],
         leftDataIndex:0,
         topButtonIndex:1,
         //下拉列表数据
         optionListB: [],
+        disciplineOptionList:[],
         //查询条件
         learnStatus:'',
         queryParams: {
           page: 1,
           pageSize: 20,
           knowledgePointId: '',
+          disciplineTypeId: '',
           coursewareName: null
         },
         //列表数据
@@ -129,8 +142,9 @@
 
     },
     mounted() {
-      if(this.$route.params.skip){
-        this.$set(this,'topButtonIndex',2);
+      if(this.$route.query.skipType){
+        this.$set(this,'topButtonIndex',this.$route.query.skipType);
+        this.$set(this.queryParams,'disciplineTypeId',this.$route.query.disciplineId);
       }
       if(this.$route.query.text){
         let obj = JSON.parse(Decrypt(this.$route.query.text));
@@ -139,12 +153,16 @@
         this.$set(this,'completedStudyHours',obj.completedStudyHours);
         this.$set(this,'studyHoursRequirement',obj.studyHoursRequirement);
       }
-
-      // this.$set(this,'examName',this.$route.query.examName?this.$route.query.examName:'');
-      // this.$set(this,'knowledgePointIds',this.$route.query.knowledgePointIds?this.$route.query.knowledgePointIds:[]);
-      // this.$set(this,'completedStudyHours',this.$route.query.completedStudyHours?this.$route.query.completedStudyHours:0);
-      // this.$set(this,'studyHoursRequirement',this.$route.query.studyHoursRequirement?this.$route.query.studyHoursRequirement:0);
+      if(sessionStorage.getItem('skipQueryParamsData')){
+        let skipQueryParamsData = JSON.parse(sessionStorage.getItem('skipQueryParamsData'))
+        this.$set(this,'queryParams',skipQueryParamsData.queryParams);
+        this.$set(this,'leftDataIndex',skipQueryParamsData.leftDataIndex);
+        this.$set(this,'topButtonIndex',skipQueryParamsData.topButtonIndex);
+        this.$set(this,'learnStatus',skipQueryParamsData.learnStatus);
+        sessionStorage.removeItem('skipQueryParamsData');
+      }
       this.examElKnowledgePointTreeList();
+      this.examElDisciplineTypeList();
     },
     methods: {
       //左侧列表切换
@@ -183,6 +201,7 @@
           page: 1,
           pageSize: 20,
           knowledgePointId: '',
+          disciplineTypeId: '',
           coursewareName: null
         })
         this.getList()
@@ -212,8 +231,8 @@
           }).then(() => {
             examUserCoursewareLearningRestart({coursewareId:item.coursewareId}).then(response => {
               self.$router.push({
-                name: 'learningMaterials',
-                params: {
+                path: '/learningMaterials',
+                query: {
                   coursewareId: item.coursewareId,
                 }
               })
@@ -221,8 +240,8 @@
           }).catch(() => {});
         }else{
           this.$router.push({
-            name: 'learningMaterials',
-            params: {
+            path: '/learningMaterials',
+            query: {
               coursewareId: item.coursewareId,
             }
           })
@@ -230,7 +249,8 @@
       },
       examElKnowledgePointTreeList(){
         let obj = {
-          knowledgePointIds : this.knowledgePointIds
+          knowledgePointIds : this.knowledgePointIds,
+          dataScope:1,
         };
         examElKnowledgePointTreeList(obj).then(response => {
           const list = response.data || [];
@@ -244,6 +264,12 @@
           this.getList();
         });
       },
+      //查询全部专业类别
+      examElDisciplineTypeList(){
+        examElDisciplineTypeList({}).then(response => {
+          this.$set(this,'disciplineOptionList',response.data);
+        });
+      },
       //换算分钟
       secondsToMinutes(totalSeconds) {
         if (typeof totalSeconds !== 'number' || totalSeconds <= 0) {
@@ -251,7 +277,21 @@
         }
         return Math.ceil(totalSeconds / 60);
       },
-    }
+    },
+    beforeRouteLeave(to, from, next) {
+      if (to.name === 'learningMaterials') {
+        const skipQueryParamsData = {
+          queryParams: this.queryParams,
+          leftDataIndex: this.leftDataIndex,
+          topButtonIndex: this.topButtonIndex,
+          learnStatus: this.learnStatus,
+        };
+        sessionStorage.setItem('skipQueryParamsData', JSON.stringify(skipQueryParamsData));
+      } else {
+        sessionStorage.removeItem('skipQueryParamsData');
+      }
+      next(); // 必须调用 next() 放行路由
+    },
   }
 </script>
 <style scoped lang="scss">
@@ -275,7 +315,7 @@
             margin:5px 0;
             padding:0 20px;
             text-align: center;
-            /*border-right:4px solid #ffffff;*/
+            border-left:6px solid #ffffff;
             cursor: pointer;
             font-weight:700;
             font-size:16px;
@@ -390,7 +430,7 @@
             }
           }
           .page-content-box{
-            padding: 0;
+            padding: 0 0 10px 0;
           }
           .for-max-big-box{
             flex:1;
@@ -407,7 +447,7 @@
               margin:20px 0 0 20px;
               border-radius:6px;
               overflow: hidden;
-              box-shadow: 0 0 8px 1px rgba(0, 0, 0, 0.1);
+              box-shadow: 0 2px 8px rgba(37, 50, 74, 0.12);
               position: relative;
               img{
                 display: inline-block;

+ 45 - 9
src/views/safetyEducationExaminationNew/safetyEducation/learningTasks/index.vue

@@ -31,6 +31,16 @@
               placeholder="知识点"
             ></el-cascader>
           </el-form-item>
+          <el-form-item label="" prop="disciplineTypeId">
+            <el-select v-model="queryParams.disciplineTypeId" placeholder="课程分类" style="width: 200px">
+              <el-option
+                v-for="dict in disciplineOptionList"
+                :key="dict.id"
+                :label="dict.disciplineName"
+                :value="dict.id"
+              />
+            </el-select>
+          </el-form-item>
           <el-form-item label="" prop="courseName">
             <el-input
               maxLength="30"
@@ -78,21 +88,21 @@
 <script>
   //import { getDicts } from "@/api/commonality/noPermission";
   //import { systemUserSelect } from "@/api/commonality/permission";
-  import { examUserCourseLearningList,examElKnowledgePointTreeList, } from "@/api/safetyEducationExaminationNew/index";
+  import { examUserCourseLearningList,examElKnowledgePointTreeList,examElDisciplineTypeList, } from "@/api/safetyEducationExaminationNew/index";
   export default {
     name: 'index',
     data() {
       return {
-        //页面状态
-        pageType: 1,
         //下拉列表数据
         optionListB: [],
+        disciplineOptionList:[],
         //查询条件
         learnStatus:'',
         queryParams: {
           page: 1,
           pageSize: 20,
           knowledgePointId: '',
+          disciplineTypeId: '',
           courseName: null
         },
         //列表数据
@@ -105,8 +115,15 @@
 
     },
     mounted() {
+      if(sessionStorage.getItem('skipQueryParamsData')){
+        let skipQueryParamsData = JSON.parse(sessionStorage.getItem('skipQueryParamsData'))
+        this.$set(this,'queryParams',skipQueryParamsData.queryParams);
+        this.$set(this,'learnStatus',skipQueryParamsData.learnStatus);
+        sessionStorage.removeItem('skipQueryParamsData');
+      }
       this.getList();
       this.examElKnowledgePointTreeList();
+      this.examElDisciplineTypeList();
     },
     methods: {
       //切换按钮
@@ -128,6 +145,7 @@
           page: 1,
           pageSize: 20,
           knowledgePointId: '',
+          disciplineTypeId: '',
           courseName: null
         })
         this.getList()
@@ -153,15 +171,15 @@
           }).then(() => {
             //学时要求
             self.$router.push({
-              name: 'knowledgeLearning',
-              params: {}
+              path: '/safetyEducationExaminationNew/safetyEducation/knowledgeLearning',
+              query: {}
             })
           }).catch(() => {});
         }else{
           //学习课程
           this.$router.push({
-            name: 'learningCourse',
-            params: {
+            path: '/learningCourse',
+            query: {
               courseId: item.courseId,
               examId: item.examId,
             }
@@ -175,6 +193,12 @@
           this.$set(this, 'optionListB', list);
         });
       },
+      //查询全部专业类别
+      examElDisciplineTypeList(){
+        examElDisciplineTypeList({}).then(response => {
+          this.$set(this,'disciplineOptionList',response.data);
+        });
+      },
       //换算分钟
       secondsToMinutes(totalSeconds) {
         if (typeof totalSeconds !== 'number' || totalSeconds <= 0) {
@@ -182,7 +206,19 @@
         }
         return Math.ceil(totalSeconds / 60);
       },
-    }
+    },
+    beforeRouteLeave(to, from, next) {
+      if (to.name === 'learningCourse') {
+        const skipQueryParamsData = {
+          queryParams: this.queryParams,
+          learnStatus: this.learnStatus,
+        };
+        sessionStorage.setItem('skipQueryParamsData', JSON.stringify(skipQueryParamsData));
+      } else {
+        sessionStorage.removeItem('skipQueryParamsData');
+      }
+      next(); // 必须调用 next() 放行路由
+    },
   }
 </script>
 <style scoped lang="scss">
@@ -249,7 +285,7 @@
           margin:0 0 20px 20px;
           border-radius:6px;
           overflow: hidden;
-          box-shadow: 0 0 8px 1px rgba(0, 0, 0, 0.1);
+          box-shadow: 0 2px 8px rgba(37, 50, 74, 0.12);
           position: relative;
           img{
             display: inline-block;

+ 32 - 10
src/views/safetyEducationExaminationNew/safetyTest/mockExam/index.vue

@@ -112,6 +112,14 @@
 
     },
     mounted() {
+      if(sessionStorage.getItem('skipQueryParamsData')){
+        let skipQueryParamsData = JSON.parse(sessionStorage.getItem('skipQueryParamsData'))
+        this.$set(this,'queryParams',skipQueryParamsData.queryParams);
+        this.$set(this,'dateRange',skipQueryParamsData.dateRange);
+        this.$set(this,'examTypeId',skipQueryParamsData.examTypeId);
+        this.$set(this,'examStatus',skipQueryParamsData.examStatus);
+        sessionStorage.removeItem('skipQueryParamsData');
+      }
       this.examUserExamTypeSelectExamType();
     },
     methods: {
@@ -166,14 +174,14 @@
         if (type == 1) {
           //学时要求
           self.$router.push({
-            name: 'knowledgeLearning',
-            params: {}
+            path: '/safetyEducationExaminationNew/safetyEducation/knowledgeLearning',
+            query: {}
           })
         }else if(type == 2){
           //学习课程
           this.$router.push({
-            name: 'learningCourse',
-            params: {
+            path: '/learningCourse',
+            query: {
               courseId: item.courseId,
               examId: item.examId,
             }
@@ -182,8 +190,8 @@
           //模拟考试
           if(item.attemptId){
             this.$router.push({
-              name: 'mockExam',
-              params: {
+              path: '/mockExam',
+              query: {
                 examId: item.examId,
                 attemptId: item.attemptId,
               }
@@ -192,8 +200,8 @@
             examUserExamStart({examId:item.examId,examScene:2,}).then(response => {
               if(response.data.attemptId){
                 this.$router.push({
-                  name: 'mockExam',
-                  params: {
+                  path: '/mockExam',
+                  query: {
                     examId: item.examId,
                     attemptId: response.data.attemptId,
                   }
@@ -233,7 +241,21 @@
         m=Math.pow(10,Math.max(r1,r2))
         return ((arg1*m+arg2*m)/m).toFixed(0);
       },
-    }
+    },
+    beforeRouteLeave(to, from, next) {
+      if (to.name === 'learningCourse'||to.name === 'mockExam') {
+        const skipQueryParamsData = {
+          queryParams: this.queryParams,
+          dateRange: this.dateRange,
+          examTypeId: this.examTypeId,
+          examStatus: this.examStatus,
+        };
+        sessionStorage.setItem('skipQueryParamsData', JSON.stringify(skipQueryParamsData));
+      } else {
+        sessionStorage.removeItem('skipQueryParamsData');
+      }
+      next(); // 必须调用 next() 放行路由
+    },
   }
 </script>
 <style scoped lang="scss">
@@ -318,7 +340,7 @@
           margin:10px 0 10px 20px;
           border-radius:10px;
           overflow: hidden;
-          box-shadow: 0 0 15px rgba(0, 0, 0, 0.2);
+          box-shadow: 0 2px 8px rgba(37, 50, 74, 0.12);
           position: relative;
           padding:20px;
           .top-box{

+ 34 - 2
src/views/safetyEducationExaminationNew/safetyTest/myGrades/index.vue

@@ -142,6 +142,19 @@
 
     },
     mounted() {
+      if(sessionStorage.getItem('skipQueryParamsData')){
+        let skipQueryParamsData = JSON.parse(sessionStorage.getItem('skipQueryParamsData'))
+        this.$set(this,'queryParams',skipQueryParamsData.queryParams);
+        this.$set(this,'dateRange',skipQueryParamsData.dateRange);
+        this.$set(this,'pageType',skipQueryParamsData.pageType);
+        this.$set(this,'examTypeId',skipQueryParamsData.examTypeId);
+        this.$set(this,'resultStatus',skipQueryParamsData.resultStatus);
+        this.$set(this,'propsData',skipQueryParamsData.propsData);
+        this.$set(this,'historyOfIncorrectQuestionsPropsData',skipQueryParamsData.historyOfIncorrectQuestionsPropsData);
+        this.$set(this,'dialogType',skipQueryParamsData.dialogType);
+        this.$set(this,'dataStatisticsReportPropsData',skipQueryParamsData.dataStatisticsReportPropsData);
+        sessionStorage.removeItem('skipQueryParamsData');
+      }
       this.examUserExamTypeSelectExamType();
     },
     methods: {
@@ -254,7 +267,26 @@
         m=Math.pow(10,Math.max(r1,r2))
         return ((arg1*m+arg2*m)/m).toFixed(0);
       },
-    }
+    },
+    beforeRouteLeave(to, from, next) {
+      if (to.name === 'startTraining') {
+        const skipQueryParamsData = {
+          queryParams: this.queryParams,
+          dateRange: this.dateRange,
+          pageType: this.pageType,
+          examTypeId: this.examTypeId,
+          resultStatus: this.resultStatus,
+          propsData: this.propsData,
+          historyOfIncorrectQuestionsPropsData: this.historyOfIncorrectQuestionsPropsData,
+          dialogType: this.dialogType,
+          dataStatisticsReportPropsData: this.dataStatisticsReportPropsData,
+        };
+        sessionStorage.setItem('skipQueryParamsData', JSON.stringify(skipQueryParamsData));
+      } else {
+        sessionStorage.removeItem('skipQueryParamsData');
+      }
+      next(); // 必须调用 next() 放行路由
+    },
   }
 </script>
 <style scoped lang="scss">
@@ -336,7 +368,7 @@
           margin:10px 0 10px 20px;
           border-radius:10px;
           overflow: hidden;
-          box-shadow: 0 0 15px rgba(0, 0, 0, 0.2);
+          box-shadow: 0 2px 8px rgba(37, 50, 74, 0.12);
           position: relative;
           padding:20px;
           .title-p{

+ 141 - 38
src/views/safetyEducationExaminationNew/safetyTest/onlineExam/index.vue

@@ -73,6 +73,24 @@
         />
       </div>
     </div>
+    <el-dialog class="preExam-dialog"
+               :modal-append-to-body="false"
+               :close-on-click-modal="false" :close-on-press-escape="false"
+               title="考试承诺书"
+               :visible.sync="preExamDialogType"
+               v-if="preExamDialogType"
+               width="840px"
+               append-to-body>
+      <div style="height:600px;" class="scrollbar-box">
+        <richTextPdf ref="richTextPdf" :content="richTextHtml" />
+      </div>
+      <div slot="footer" class="dialog-footer dialog-footer-box">
+        <p class="dialog-footer-button-null"></p>
+        <p class="dialog-footer-button-border" v-if="preButtonType" @click="preExamDialogCancel">下载</p>
+        <p class="dialog-footer-button-primary" @click="examUserExamStart">确认</p>
+        <p class="dialog-footer-button-null"></p>
+      </div>
+    </el-dialog>
   </div>
 </template>
 <script>
@@ -80,9 +98,11 @@
   //import { systemUserSelect } from "@/api/commonality/permission";
   //import { getInfo } from "@/api/basicsModules/index";
   //import addPage from "./addPage.vue";
-  import { examUserExamList,examUserExamTypeSelectExamType,examUserExamStart, } from "@/api/safetyEducationExaminationNew/index";
+  import { examUserExamList,examUserExamTypeSelectExamType,examUserExamStart,examUserExamCommitmentConfirm, } from "@/api/safetyEducationExaminationNew/index";
+  import richTextPdf from '@/views/safetyEducationExaminationNew/components/richTextPdf.vue';
   export default {
     name: 'index',
+    components: { richTextPdf },
     data() {
       return {
         tableButtonType: this.hasPermiDom(['demo:demo:detail', 'demo:demo:edit', 'demo:demo:del']),
@@ -105,13 +125,26 @@
         //数据数量
         total: 0,
         //组件传参
-        propsData: {}
+        propsData: {},
+        //考前承诺相关
+        preExamDialogType:false,
+        preButtonType:false,
+        richTextHtml: '',
+        preData:null,
       }
     },
     created() {
 
     },
     mounted() {
+      if(sessionStorage.getItem('skipQueryParamsData')){
+        let skipQueryParamsData = JSON.parse(sessionStorage.getItem('skipQueryParamsData'))
+        this.$set(this,'queryParams',skipQueryParamsData.queryParams);
+        this.$set(this,'dateRange',skipQueryParamsData.dateRange);
+        this.$set(this,'examTypeId',skipQueryParamsData.examTypeId);
+        this.$set(this,'examStatus',skipQueryParamsData.examStatus);
+        sessionStorage.removeItem('skipQueryParamsData');
+      }
       this.examUserExamTypeSelectExamType();
     },
     methods: {
@@ -160,20 +193,99 @@
           this.$set(this, 'total', response.data.total)
         })
       },
+      //下载承诺书
+      preExamDialogCancel(){
+        this.msgSuccess('正在下载,请耐心等候')
+        this.$refs['richTextPdf'].downloadPDF();
+      },
+      //确认承诺-并考试
+      examUserExamStart(){
+        if(this.preData.attemptId){
+          this.examUserExamCommitmentConfirm(1,this.preData.attemptId);
+        }else{
+          examUserExamStart({examId:this.preData.examId,examScene:1,}).then(response => {
+            if(response.data.attemptId){
+              this.examUserExamCommitmentConfirm(2,response.data.attemptId);
+            }else{
+              this.msgError(response.message)
+            }
+          })
+        }
+      },
+      examUserExamCommitmentConfirm(type,attemptId){
+        examUserExamCommitmentConfirm({attemptId:attemptId}).then(response => {
+          if(type == 1){
+            this.$router.push({
+              path: '/startTheExam',
+              query: {
+                attemptId: attemptId,
+                type: '1',
+                examKind:this.preData.examKind,
+              }
+            })
+          }else if(type == 2){
+            this.$router.push({
+              path: '/startTheExam',
+              query: {
+                examId: this.preData.examId,
+                attemptId: attemptId,
+                type: '1',
+                examKind:this.preData.examKind,
+              }
+            })
+          }
+        })
+      },
+      //开始考试判断是否有承诺书
+      setRichExamData(item){
+        if(item.commitmentEnabled == 1 && !item.commitmentConfirmed){
+          this.$set(this,'preButtonType',item.commitmentPrintEnabled == 1?true:false);
+          this.$set(this,'richTextHtml',item.commitmentContent);
+          this.$set(this,'preData',item);
+          this.$set(this,'preExamDialogType',true);
+        }else{
+          if(item.attemptId){
+            this.$router.push({
+              path: '/startTheExam',
+              query: {
+                attemptId: item.attemptId,
+                type: '1',
+                examKind:item.examKind,
+              }
+            })
+          }else{
+            examUserExamStart({examId:item.examId,examScene:1,}).then(response => {
+              if(response.data.attemptId){
+                this.$router.push({
+                  path: '/startTheExam',
+                  query: {
+                    examId: item.examId,
+                    attemptId: response.data.attemptId,
+                    type: '1',
+                    examKind:item.examKind,
+                  }
+                })
+              }else{
+                this.msgError(response.message)
+              }
+            })
+          }
+        }
+      },
       //操作按钮
       tableButton(type, item) {
         let self = this
         if (type == 1) {
           //学时要求
           self.$router.push({
-            name: 'knowledgeLearning',
-            params: {}
+            path: '/safetyEducationExaminationNew/safetyEducation/knowledgeLearning',
+            query: {}
           })
         }else if(type == 2){
           //学习课程
           this.$router.push({
-            name: 'learningCourse',
-            params: {
+            path: '/learningCourse',
+            query: {
               courseId: item.courseId,
               examId: item.examId,
             }
@@ -182,8 +294,8 @@
           //模拟考试
           if(item.mockExamId){
             this.$router.push({
-              name: 'mockExam',
-              params: {
+              path: '/mockExam',
+              query: {
                 examId: item.examId,
                 attemptId: item.mockExamId,
               }
@@ -192,8 +304,8 @@
             examUserExamStart({examId:item.examId,examScene:2,}).then(response => {
               if(response.data.attemptId){
                 this.$router.push({
-                  name: 'mockExam',
-                  params: {
+                  path: '/mockExam',
+                  query: {
                     examId: item.examId,
                     attemptId: response.data.attemptId,
                   }
@@ -204,32 +316,8 @@
             })
           }
         }else if(type == 4){
-          //开始考试
-          if(item.attemptId){
-            this.$router.push({
-              name: 'startTheExam',
-              params: {
-                examId: item.examId,
-                attemptId: item.attemptId,
-                examKind:item.examKind,
-              }
-            })
-          }else{
-            examUserExamStart({examId:item.examId,examScene:1,}).then(response => {
-              if(response.data.attemptId){
-                this.$router.push({
-                  name: 'startTheExam',
-                  params: {
-                    examId: item.examId,
-                    attemptId: response.data.attemptId,
-                    examKind:item.examKind,
-                  }
-                })
-              }else{
-                this.msgError(response.message)
-              }
-            })
-          }
+          //在线考试//补考
+          this.setRichExamData(item);
         }else if (type == 6) {
           //返回并刷新
           this.$set(this, 'pageType', 1)
@@ -260,7 +348,21 @@
         m=Math.pow(10,Math.max(r1,r2))
         return ((arg1*m+arg2*m)/m).toFixed(0);
       },
-    }
+    },
+    beforeRouteLeave(to, from, next) {
+      if (to.name === 'learningCourse'||to.name === 'mockExam'||to.name === 'startTheExam') {
+        const skipQueryParamsData = {
+          queryParams: this.queryParams,
+          dateRange: this.dateRange,
+          examTypeId: this.examTypeId,
+          examStatus: this.examStatus,
+        };
+        sessionStorage.setItem('skipQueryParamsData', JSON.stringify(skipQueryParamsData));
+      } else {
+        sessionStorage.removeItem('skipQueryParamsData');
+      }
+      next(); // 必须调用 next() 放行路由
+    },
   }
 </script>
 <style scoped lang="scss">
@@ -318,6 +420,7 @@
           }
           p:nth-child(2){
             border-left:none;
+            border-right:none;
           }
           p:nth-child(3){
             border-top-right-radius:4px;
@@ -345,7 +448,7 @@
           margin:10px 0 10px 20px;
           border-radius:10px;
           overflow: hidden;
-          box-shadow: 0 0 15px rgba(0, 0, 0, 0.2);
+          box-shadow: 0 2px 8px rgba(37, 50, 74, 0.12);
           position: relative;
           padding:20px;
           .top-box{

+ 63 - 11
src/views/safetyEducationExaminationNew/safetyTest/practiceQuestions/index.vue

@@ -40,6 +40,16 @@
                   placeholder="知识点"
                 ></el-cascader>
               </el-form-item>
+              <el-form-item label="" prop="disciplineTypeId">
+                <el-select v-model="queryParams.disciplineTypeId" placeholder="题目分类" style="width: 200px">
+                  <el-option
+                    v-for="dict in disciplineOptionList"
+                    :key="dict.id"
+                    :label="dict.disciplineName"
+                    :value="dict.id"
+                  />
+                </el-select>
+              </el-form-item>
               <el-form-item label="" prop="searchName">
                 <el-input
                   maxLength="30"
@@ -92,7 +102,7 @@
   //import { systemUserSelect } from "@/api/commonality/permission";
   //import { getInfo } from "@/api/basicsModules/index";
   //import addPage from "./addPage.vue";
-  import { examUserPracticeList,examElKnowledgePointTreeList, } from "@/api/safetyEducationExaminationNew/index";
+  import { examUserPracticeList,examElKnowledgePointTreeList,examElDisciplineTypeList, } from "@/api/safetyEducationExaminationNew/index";
   import historyOfIncorrectQuestions from "@/views/safetyEducationExaminationNew/components/historyOfIncorrectQuestions.vue";
   export default {
     name: 'index',
@@ -107,12 +117,14 @@
         leftDataIndex:0,
         //下拉列表数据
         optionListB: [],
+        disciplineOptionList:[],
         //查询条件
         practiceStatus:'',
         queryParams: {
           page: 1,
           pageSize: 20,
           knowledgePointId: null,
+          disciplineTypeId: null,
           searchName: ''
         },
         //列表数据
@@ -126,7 +138,18 @@
 
     },
     mounted() {
+      if(this.$route.query.disciplineId){
+        this.$set(this.queryParams,'disciplineTypeId',this.$route.query.disciplineId);
+      }
+      if(sessionStorage.getItem('skipQueryParamsData')){
+        let skipQueryParamsData = JSON.parse(sessionStorage.getItem('skipQueryParamsData'))
+        this.$set(this,'queryParams',skipQueryParamsData.queryParams);
+        this.$set(this,'leftDataIndex',skipQueryParamsData.leftDataIndex);
+        this.$set(this,'practiceStatus',skipQueryParamsData.practiceStatus);
+        sessionStorage.removeItem('skipQueryParamsData');
+      }
       this.examElKnowledgePointTreeList();
+      this.examElDisciplineTypeList();
     },
     methods: {
       //左侧列表切换
@@ -156,6 +179,7 @@
           page: 1,
           pageSize: 20,
           knowledgePointId: null,
+          disciplineTypeId: null,
           searchName: ''
         })
         this.getList()
@@ -178,8 +202,8 @@
         if (type == 1) {
           //刷题练习
           this.$router.push({
-            name: 'startPracticing',
-            params: {
+            path: '/startPracticing',
+            query: {
               knowledgePointId: item.knowledgePointId,
               type: '1'
             }
@@ -198,15 +222,42 @@
         }
       },
       examElKnowledgePointTreeList(){
-        examElKnowledgePointTreeList({}).then(response => {
+        let self = this;
+        examElKnowledgePointTreeList({ dataScope:2 }).then(response => {
           const list = response.data || [];
           this.formatTreeData(list);
-          this.$set(this, 'letDataList', list);
-          this.$set(this, 'optionListB', list[0].children?list[0].children:[]);
+          this.$set(this, 'letDataList', [{knowledgePointName:'全部',id:''},...list]);
+          if(this.$route.query.knowledgePointId){
+            for(let i=0;i<self.letDataList.length;i++){
+              if(self.letDataList[i].id == this.$route.query.knowledgePointId){
+                self.$set(self,'leftDataIndex',i);
+              }
+            }
+          }
+          // this.$set(this, 'optionListB', list[0].children?list[0].children:[]);
           this.getList();
         });
       },
-    }
+      //查询全部专业类别
+      examElDisciplineTypeList(){
+        examElDisciplineTypeList({}).then(response => {
+          this.$set(this,'disciplineOptionList',response.data);
+        });
+      },
+    },
+    beforeRouteLeave(to, from, next) {
+      if (to.name === 'startPracticing'||to.name === 'startTraining') {
+        const skipQueryParamsData = {
+          queryParams: this.queryParams,
+          leftDataIndex: this.leftDataIndex,
+          practiceStatus: this.practiceStatus,
+        };
+        sessionStorage.setItem('skipQueryParamsData', JSON.stringify(skipQueryParamsData));
+      } else {
+        sessionStorage.removeItem('skipQueryParamsData');
+      }
+      next(); // 必须调用 next() 放行路由
+    },
   }
 </script>
 <style scoped lang="scss">
@@ -230,7 +281,7 @@
             margin:5px 0;
             padding:0 20px;
             text-align: center;
-            border-right:4px solid #ffffff;
+            border-left:6px solid #ffffff;
             cursor: pointer;
             font-weight:700;
             font-size:16px;
@@ -246,8 +297,9 @@
             color: #ffffff;
           }
           .leftCheck{
-            color: #0183fa;
-            border-right:4px solid #0183fa;
+            color: #fff;
+            background-color: #0183fa;
+            /*border-right:4px solid #0183fa;*/
           }
         }
         .right-box{
@@ -323,7 +375,7 @@
               margin:0 0 20px 20px;
               border-radius:10px;
               overflow: hidden;
-              box-shadow: 4px 4px 4px 4px rgba(0,0,0,0.1);
+              box-shadow: 0 2px 8px rgba(37, 50, 74, 0.12);
               position: relative;
               border:1px solid rgba(222,222,222,0.4);
               background-color: rgba(222,222,222,0.2);

+ 355 - 358
src/views/safetyEducationExaminationNew/workbench/ResourceCard.vue

@@ -1,71 +1,72 @@
 <!-- 实验室安全素养资源卡 -->
 <template>
   <div class="resource-card">
-    <div class="card-title">实验室安全素养资源卡</div>
-    <!-- 分类 Tab 横向滚动 -->
-    <div class="tab-scroll-wrap">
-      <div class="tab-bar">
-        <p v-for="(item,index) in topList" :key="index"
-           :class="item.knowledgePointId == knowledgePointId?'check-p':''"
-          @click="topButton(item.knowledgePointId)">{{ item.knowledgePointName }}</p>
+    <div class="resource-card-page">
+      <div class="card-title">实验室安全素养资源</div>
+      <div class="table-max-big-box">
+        <p class="table-for-p" :class="topCheckIndex == index ? 'check-table-p':''"
+           @click="topTableButton(index)"
+           v-for="(item,index) in tableList" :key="index">{{item.disciplineName}}</p>
+        <p class="table-null-p"></p>
       </div>
-    </div>
-    <div class="resource-body">
-      <div class="left-max-big-box">
-        <!--知识学习-->
-        <div class="left-top-big-box">
-          <div class="big-title-box">
-            <p>知识学习</p>
+      <div class="resource-body-top">
+        <div class="left-resource-box">
+          <div class="resource-title-box">
+            <p class="el-icon-folder-opened"></p>
+            <p>学习资料</p>
             <p @click="goPage(1)">查看更多</p>
           </div>
-          <div class="big-content-box scrollbar-box">
-            <p class="null-p" v-if="!leftTopList[0]">暂无数据</p>
-            <div class="for-big-box" v-for="(item,index) in leftTopList" :key="index" @click="tableButton(2,item)">
-              <p>{{item.coursewareName}}</p>
-              <p>{{secondsToMinutes(item.minLearningDuration)}}分钟丨{{item.creditHours}}学时丨{{item.points}}积分</p>
-              <p :class="item.learnStatus==1?'colorA':(item.learnStatus==2?'colorB':'')">{{item.learnStatus==1?'学习中':(item.learnStatus==2?'已完成':'未学习')}}</p>
+          <p class="text-null-p" v-if="!topLeftList[0]">暂无数据</p>
+          <div class="for-max-big-box" @click="tableButton(item)"
+               v-for="(item,index) in topLeftList" :key="index">
+            <div class="left-box">
+              <p v-if="item.materialType == 1" class="el-icon-video-play"></p>
+              <p v-if="item.materialType == 3" class="el-icon-document"></p>
+              <p v-if="item.materialType == 4" class="el-icon-reading"></p>
+            </div>
+            <div class="center-box">
+              <p>{{ item.coursewareName }}</p>
+              <p>{{ item.materialType == 4?'文章':item.attachmentType.substring(1) }}</p>
+            </div>
+            <div class="right-box">
+              <p class="el-icon-time"></p>
+              <p>{{secondsToMinutes(item.minLearningDuration)}}分钟</p>
             </div>
           </div>
         </div>
-        <!--刷题练习-->
-        <div class="left-bottom-big-box">
-          <div class="big-title-box">
-            <p>刷题练习</p>
+        <div class="right-resource-box">
+          <div class="resource-title-box">
+            <p class="el-icon-edit-outline"></p>
+            <p>题库</p>
             <p @click="goPage(2)">查看更多</p>
           </div>
-          <div class="big-content-box scrollbar-box">
-            <p class="null-p" v-if="!leftBottomList[0]">暂无数据</p>
-            <div class="for-big-box" v-for="(item,index) in leftBottomList" :key="index" @click="tableButton(1,item)">
-              <div class="for-flex-box">
-                <p class="el-icon-time"></p>
-                <p :style="!item.lastAnswerTime?'font-size:14px;':''">{{item.lastAnswerTime?parseTime(item.lastAnswerTime,"{y}-{m}-{d} {h}:{i}"):'未练习'}}</p>
-              </div>
-              <p class="text-p">练习进度:{{item.answeredCount}}/{{item.totalCount}}</p>
-              <p class="text-p">正确数:{{item.correctCount}}丨错题数:{{item.wrongCount}}丨正确率:{{item.correctRate}}%</p>
-              <el-progress
-                class="num-p" type="circle"
-                :stroke-width="4"
-                :width="60" :percentage="item.progress">
-              </el-progress>
-            </div>
+          <p class="text-null-p" v-if="!topRightList[0]">暂无数据</p>
+          <div class="for-max-big-box" v-for="(item,index) in topRightList" :key="index" @click="goPage(4,item)">
+            <p class="el-icon-notebook-2"></p>
+            <p>{{item.knowledgePointName}}</p>
+            <p>{{item.questionCount}} 题</p>
           </div>
         </div>
       </div>
-      <!--视频资源学习-->
-      <div class="right-max-big-box">
-        <div class="big-title-box">
-          <p>视频资源学习</p>
-          <p @click="goPage(3)">查看更多</p>
-        </div>
-        <div class="big-content-box-1 scrollbar-box">
-          <p class="null-p" v-if="!rightList[0]">暂无数据</p>
-          <div class="for-big-box" v-for="(item,index) in rightList" :key="index" @click="tableButton(2,item)">
-            <img :src="item.exampleImg">
-            <div class="text-box">
-              <p>{{item.coursewareName}}</p>
-              <p>{{secondsToMinutes(item.minLearningDuration)}}分钟丨{{item.creditHours}}学时丨{{item.points}}积分</p>
-              <p :class="item.learnStatus==1?'colorA':(item.learnStatus==2?'colorB':'')">{{item.learnStatus==1?'学习中':(item.learnStatus==2?'已完成':'未学习')}}</p>
-            </div>
+    </div>
+    <div class="resource-card-page">
+      <div class="card-title">视频学习资源</div>
+      <p class="skip-button" @click="goPage(3)">查看更多</p>
+      <div class="table-max-big-box">
+        <p class="table-for-p"  :class="bottomCheckIndex == index ? 'check-table-p':''"
+           @click="bottomTableButton(index)"
+           v-for="(item,index) in tableList" :key="index">{{item.disciplineName}}</p>
+        <p class="table-null-p"></p>
+      </div>
+      <div class="resource-body-bottom">
+        <p class="text-null-p" v-if="!bottomList[0]">暂无数据</p>
+        <div class="for-max-big-box"  @click="tableButton(item)"
+             v-for="(item,index) in bottomList" :key="index">
+          <img v-if="item.exampleImg" :src="item.exampleImg">
+          <img v-else src="@/assets/ZDimages/basicsModules/image_420782143223404.png">
+          <div>
+            <p>{{item.coursewareName}}</p>
+            <p>{{secondsToMinutes(item.minLearningDuration)}}分钟 丨 {{item.creditHours}}学时 丨 {{item.points}}积分</p>
           </div>
         </div>
       </div>
@@ -75,129 +76,144 @@
 
 <script>
   import {
-    examUserCoursewareLearningKnowledgePoints,examUserCoursewareLearningRestart,
-    examUserPracticeList,examUserCoursewareLearningList,
+    examElDisciplineTypeList,examUserCoursewareLearningRestart,
+    examUserCoursewareLearningList,examElQuestionBankGroupByKnowledgePoint,
   } from "@/api/safetyEducationExaminationNew/index";
 export default {
   name: 'ResourceCard',
   data() {
     return {
-      topList:[],
-      knowledgePointId:'',
-      leftTopList:[],
-      leftBottomList:[],
-      rightList:[],
+      topCheckIndex:0,
+      bottomCheckIndex:0,
+      tableList:[],
+      tableListBottom:[],
+      topLeftList:[],
+      topRightList:[],
+      bottomList:[],
     }
   },
   mounted(){
-    this.examUserCoursewareLearningKnowledgePoints();
+    this.examElDisciplineTypeList();
   },
   methods:{
-    tableButton(type,item){
-      if(type == 1){
-        //刷题练习
-        this.$router.push({
-          name: 'startPracticing',
-          params: {
-            knowledgePointId: item.knowledgePointId,
-            type: '1'
-          }
-        })
-      }else if(type == 2){
-        let self = this;
-        if(item.learnStatus == 2){
-          this.$confirm('该课件已学完,是否重置进度重新学习?', "提示", {
-            confirmButtonText: "确认",
-            cancelButtonText: "取消",
-            type: "warning"
-          }).then(function() {
-          }).then(() => {
-            examUserCoursewareLearningRestart({coursewareId:item.coursewareId}).then(response => {
-              self.$router.push({
-                name: 'learningMaterials',
-                params: {
-                  coursewareId: item.coursewareId,
-                }
-              })
-            });
-          }).catch(() => {});
-        }else{
-          this.$router.push({
-            name: 'learningMaterials',
-            params: {
-              coursewareId: item.coursewareId,
-            }
-          })
-        }
+    //顶部选项切换
+    topTableButton(index){
+      if(this.topCheckIndex != index){
+        this.$set(this,'topCheckIndex',index);
+        this.leftExamUserCoursewareLearningList();
+        this.examElQuestionBankGroupByKnowledgePoint();
       }
     },
-    topButton(val){
-      if(this.knowledgePointId != val){
-        this.$set(this,'knowledgePointId',val);
-        this.leftExamUserCoursewareLearningList();
+    bottomTableButton(index){
+      if(this.bottomCheckIndex != index){
+        this.$set(this,'bottomCheckIndex',index);
         this.rightExamUserCoursewareLearningList();
-        this.examUserPracticeList();
       }
     },
-    goPage(type){
-      //1.文章文档 2.刷题 3.视频
+    tableButton(item){
+      let self = this;
+      if(item.learnStatus == 2){
+        this.$confirm('该课件已学完,是否重置进度重新学习?', "提示", {
+          confirmButtonText: "确认",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+        }).then(() => {
+          examUserCoursewareLearningRestart({coursewareId:item.coursewareId}).then(response => {
+            self.$router.push({
+              path: '/learningMaterials',
+              query: {
+                coursewareId: item.coursewareId,
+              }
+            })
+          });
+        }).catch(() => {});
+      }else{
+        this.$router.push({
+          path: '/learningMaterials',
+          query: {
+            coursewareId: item.coursewareId,
+          }
+        })
+      }
+    },
+    goPage(type,item){
+      //1.文章文档 2.刷题 3.视频 4.知识点指向刷题
       if(type == 1){
         this.$router.push({
-          name: 'knowledgeLearning',
-          params: {
-            skip: true,
+          path: '/safetyEducationExaminationNew/safetyEducation/knowledgeLearning',
+          query: {
+            skipType: 2,
+            disciplineId:this.tableList[this.topCheckIndex].id,
           }
         })
       }else if(type == 2){
         this.$router.push({
-          name: 'practiceQuestions',
-          params: {}
+          path: '/safetyEducationExaminationNew/safetyTest/practiceQuestions',
+          query: {
+            disciplineId:this.tableList[this.bottomCheckIndex].id,
+          }
         })
       }else if(type == 3){
         this.$router.push({
-          name: 'knowledgeLearning',
-          params: {}
+          path: '/safetyEducationExaminationNew/safetyEducation/knowledgeLearning',
+          query: {
+            skipType: 1,
+            disciplineId:this.tableList[this.bottomCheckIndex].id,
+          }
+        })
+      }else if(type == 4){
+        this.$router.push({
+          path: '/safetyEducationExaminationNew/safetyTest/practiceQuestions',
+          query: {
+            knowledgePointId:item.knowledgePointId,
+            disciplineId:this.tableList[this.bottomCheckIndex].id,
+          }
         })
       }
     },
+    //文章
     leftExamUserCoursewareLearningList(){
       let obj = {
         page:1,
         pageSize:5,
         materialType:2,
-        knowledgePointId:this.knowledgePointId,
+        disciplineTypeId:this.tableList[this.topCheckIndex].id,
       }
       examUserCoursewareLearningList(obj).then(response => {
-        this.$set(this, 'leftTopList', response.data.records)
+        this.$set(this, 'topLeftList', response.data.records)
       })
     },
+    //视频
     rightExamUserCoursewareLearningList(){
       let obj = {
         page:1,
         pageSize:6,
         materialType:1,
-        knowledgePointId:this.knowledgePointId,
+        disciplineTypeId:this.tableList[this.bottomCheckIndex].id,
       }
       examUserCoursewareLearningList(obj).then(response => {
-        this.$set(this, 'rightList', response.data.records)
+        this.$set(this, 'bottomList', response.data.records)
       })
     },
-    examUserPracticeList(){
+    //知识点题库
+    examElQuestionBankGroupByKnowledgePoint(){
       let obj = {
         page:1,
-        pageSize:1,
-        knowledgePointId:this.knowledgePointId,
+        pageSize:6,
+        disciplineTypeId:this.tableList[this.topCheckIndex].id,
       }
-      examUserPracticeList(obj).then(response => {
-        this.$set(this, 'leftBottomList', response.data.records)
+      examElQuestionBankGroupByKnowledgePoint(obj).then(response => {
+        this.$set(this, 'topRightList', response.data.records)
       })
     },
-    examUserCoursewareLearningKnowledgePoints(){
-      examUserCoursewareLearningKnowledgePoints({}).then(response => {
-        this.$set(this, 'topList', [{knowledgePointName:'总览',knowledgePointId:''},...response.data])
+    //类型选项卡数据
+    examElDisciplineTypeList(){
+      examElDisciplineTypeList({}).then(response => {
+        this.$set(this, 'tableList', response.data)
         this.leftExamUserCoursewareLearningList();
         this.rightExamUserCoursewareLearningList();
-        this.examUserPracticeList();
+        this.examElQuestionBankGroupByKnowledgePoint();
       })
     },
     //换算分钟
@@ -213,273 +229,254 @@ export default {
 
 <style scoped lang="scss">
 .resource-card {
-  background: #fff;
-  border-radius: 6px;
-  margin-bottom: 12px;
-  box-shadow: 0 1px 4px rgba(0,0,0,0.06);
-
-  .card-title {
-    font-size: 16px;
-    font-weight: 700;
-    line-height:20px;
-    color: #333;
-    margin:20px 0 20px 20px;
-  }
-
-  .tab-scroll-wrap {
-    height:60px;
-    overflow-x: auto;
-    padding-bottom: 4px;
-    margin:20px 20px 0 20px;
-
-    &::-webkit-scrollbar { height: 4px; }
-    &::-webkit-scrollbar-thumb { background: #ddd; border-radius: 2px; }
-
-    .tab-bar {
+  .resource-card-page{
+    background: #fff;
+    margin-bottom: 12px;
+    background: rgba(255, 255, 255, 0.95);
+    border: 1px solid #e8edf5;
+    border-radius: 16px;
+    box-shadow: 0 4px 20px rgba(37, 50, 74, 0.06);
+    padding:20px;
+    position: relative;
+    .skip-button{
+      position: absolute;
+      top:50px;
+      right:25px;
+      color:#409EFF;
+      cursor: pointer;
+      font-size: 14px;
+      line-height:50px;
+    }
+    .card-title {
+      font-size: 16px;
+      font-weight: 700;
+      line-height:20px;
+      color: #333;
+      margin-bottom:20px;
+    }
+    .table-max-big-box{
       display: flex;
-      gap: 6px;
-      white-space: nowrap;
-      width: max-content;
       p{
         height:40px;
-        line-height:40px;
-        border-radius:6px;
-        border:1px solid #666;
-        color:#666;
         padding:0 20px;
-        min-width: 100px;
+        line-height:40px;
+        font-size: 14px;
+        font-weight: 500;
+        color: #303133;
         text-align: center;
+      }
+      .table-for-p:nth-child(1){
+        border-left:1px solid #E4E7ED;
+        border-top-left-radius:4px;
+      }
+      :nth-last-child(2){
+        border-top-right-radius:4px;
+      }
+      .table-for-p{
+        border-top:1px solid #E4E7ED;
+        border-right:1px solid #E4E7ED;
+        border-bottom:1px solid #E4E7ED;
         cursor: pointer;
       }
-      .check-p{
-        color:#fff;
-        background-color: #0183fa;
-        border: 1px solid #0183fa;
+      .table-null-p{
+        flex:1;
+        border-bottom:1px solid #E4E7ED;
+      }
+      .check-table-p{
+        color:#0183fa!important;
+        border-bottom:none!important;
       }
     }
-  }
-
-  .resource-body {
-    height:910px;
-    display: flex;
-    .left-max-big-box{
-      flex:1;
+    .text-null-p{
+      text-align: center;
+      font-size:14px;
+      line-height:400px;
+      color:#999;
+    }
+    .resource-body-top{
+      height:500px;
+      border-left:1px solid #E4E7ED;
+      border-right:1px solid #E4E7ED;
+      border-bottom:1px solid #E4E7ED;
       display: flex;
-      flex-direction: column;
-      overflow: hidden;
-      padding:15px 0 20px 20px;
-      .left-top-big-box{
-        height:620px;
-        display: flex;
-        flex-direction: column;
+      .left-resource-box{
+        flex:1;
+        padding:10px 15px 20px 20px;
         overflow: hidden;
-        border-radius:10px;
-        box-shadow: 0 0 15px rgba(0, 0, 0, 0.2);
-        margin-bottom:20px;
-        margin-right:20px;
-        padding-bottom:20px;
-        .null-p{
-          text-align: center;
-          line-height:400px;
-          color:#999;
-          font-size:14px;
-        }
-        .for-big-box{
-          margin:12px 14px 0 20px;
-          background-color: rgba(1, 131, 250, 0.1);
-          border-radius:6px;
-          padding:24px 20px;
-          position: relative;
+        .for-max-big-box{
+          margin-top:15px;
+          border: 1px solid #e8edf3;
+          border-radius: 10px;
+          padding: 14px;
+          display: flex;
+          align-items: flex-start;
+          gap: 12px;
           cursor: pointer;
-          p:nth-child(1){
-            font-size:16px;
-            font-weight:700;
-            color:#0183fa;
-            line-height: 24px;
-          }
-          p:nth-child(2){
-            font-size:14px;
-            color:#333;
-            line-height: 24px;
-          }
-          p:nth-child(3){
-            position: absolute;
-            bottom:20px;
-            right:20px;
-            font-size:14px;
-            border-radius:4px;
-            line-height: 24px;
-            width: 60px;
+          transition: all 0.2s;
+          background: #fafbfd;
+          .left-box{
+            width:40px;
+            height:40px;
+            border-radius: 8px;
+            background: #eef3ff;
             text-align: center;
-            background-color: #999;
-            color:#fff;
-          }
-          .colorA{
-            border:1px solid #0183fa;
-            background-color: #fff!important;
-            color:#0183fa!important;
-          }
-          .colorB{
-            background-color: #0183fa!important;
-            color:#fff!important;
-          }
-        }
-      }
-      .left-bottom-big-box{
-        height:235px;
-        display: flex;
-        flex-direction: column;
-        overflow: hidden;
-        border-radius:10px;
-        margin-right:20px;
-        box-shadow: 0 0 15px rgba(0, 0, 0, 0.2);
-        padding-bottom:20px;
-        .null-p{
-          text-align: center;
-          line-height:140px;
-          color:#999;
-          font-size:14px;
-        }
-        .for-big-box{
-          margin:12px 14px 0 20px;
-          background-color: rgba(1, 131, 250, 0.1);
-          border-radius:6px;
-          padding:16px 20px;
-          position: relative;
-          cursor: pointer;
-          .for-flex-box{
-            display: flex;
-            color:#0183fa;
             p{
-              font-weight:700;
+              font-size: 20px;
+              color: #5b95f7;
+              line-height:40px;
+              text-align: center;
             }
+          }
+          .center-box{
+            flex: 1;
             p:nth-child(1){
-              font-size:18px;
-              line-height:40px;
-              margin-right:5px;
+              font-size: 14px;
+              color: #25324a;
+              font-weight: 500;
+              display: block;
+              margin-bottom: 5px;
+              /*单行省略号*/
+              overflow:hidden;
+              text-overflow:ellipsis;
+              white-space:nowrap;
             }
             p:nth-child(2){
-              font-size:14px;
-              line-height:40px;
+              font-size: 12px;
+              color: #93a0b5;
             }
           }
-          .text-p{
-            line-height:30px;
-            font-size:14px;
-            color:#666;
-            font-weight:700;
-          }
-          .num-p{
-            position: absolute;
-            right:40px;
-            top:35px;
-          }
-          .num-p ::v-deep .el-progress__text {
-            margin-left:0!important;
-            font-size:12px!important;
-          }
-          .num-p ::v-deep svg path:first-child {
-            stroke: #cccccc !important; /* 修改为红色 */
+          .right-box{
+            display: flex;
+            margin-top:20px;
+            p{
+              font-size: 12px;
+              line-height:20px;
+              color: #60708a;
+            }
+            p:nth-child(1){
+              margin-right:4px;
+            }
           }
         }
+        .for-max-big-box:hover{
+          border-color:#5b95f7;
+          background-color: #f0f6ff;
+          box-shadow: 0 2px 8px rgba(91,149,247,0.1);
+        }
       }
-    }
-    .right-max-big-box{
-      flex:1;
-      display: flex;
-      flex-direction: column;
-      overflow: hidden;
-      width:740px;
-      border-radius:10px;
-      box-shadow: 0 0 15px rgba(0, 0, 0, 0.2);
-      margin:15px 20px 20px 0;
-      .big-content-box-1{
+      .right-resource-box{
         flex:1;
-        .null-p{
-          text-align: center;
-          line-height:400px;
-          color:#999;
-          font-size:14px;
+        padding:10px 20px 20px 15px;
+        overflow: hidden;
+        .for-max-big-box:nth-child(even){
+          margin:15px 15px 0 0!important;
         }
-        .for-big-box{
-          margin:12px 0 0 20px;
+        .for-max-big-box{
+          margin-top:15px;
+          border: 1px solid #e8edf3;
+          border-radius: 10px;
+          padding: 16px 14px;
           display: inline-block;
-          width:346px;
-          border-radius:6px;
-          overflow: hidden;
-          position: relative;
+          flex-direction: column;
+          align-items: center;
+          gap: 8px;
           cursor: pointer;
-          img{
-            width:346px;
-            height:180px;
-            display: block;
-            overflow: hidden;
-            margin: 0;
-            padding: 0;
+          transition: all 0.2s;
+          background: #fafbfd;
+          text-align: center;
+          width:348px;
+          height:127px;
+          p:nth-child(1){
+            width:36px;
+            height:36px;
+            font-size:18px;
+            border-radius: 50%;
+            background-color: #eef3ff;
+            color:#5b95f7;
+            text-align: center;
+            line-height:36px;
+            margin-top:5px;
           }
-          .text-box{
-            background-color: rgba(1, 131, 250, 0.1);
-            p:nth-child(1){
-              margin:0 20px;
-              line-height:40px;
-              color:#0183fa;
-              font-size:16px;
-              font-weight:700;
-            }
-            p:nth-child(2){
-              margin:0 20px;
-              line-height:20px;
-              color:#333;
-              font-size:14px;
-              padding-bottom:10px;
-            }
-            p:nth-child(3){
-              position: absolute;
-              bottom:10px;
-              right:10px;
-              background-color: #999;
-              color:#fff;
-              font-size:14px;
-              border-radius:4px;
-              line-height: 24px;
-              width: 60px;
-              text-align: center;
-            }
-            .colorA{
-              border:1px solid #0183fa;
-              background-color: #fff!important;
-              color:#0183fa!important;
-            }
-            .colorB{
-              background-color: #0183fa!important;
-              color:#fff!important;
-            }
+          p:nth-child(2){
+            font-size: 13px;
+            color: #25324a;
+            font-weight: 500;
+            margin-top:10px;
+          }
+          p:nth-child(3){
+            font-size: 12px;
+            color: #93a0b5;
+            margin-top:5px;
           }
         }
+        .for-max-big-box:hover{
+          border-color:#5b95f7;
+          background-color: #f0f6ff;
+          box-shadow: 0 2px 8px rgba(91,149,247,0.1);
+        }
       }
-    }
-    .big-title-box{
-      display: flex;
-      height:60px;
-      padding:0 20px;
-      p{
-        line-height:60px;
-        font-size:16px;
-      }
-      p:nth-child(1){
-        flex:1;
-        font-weight: 700;
+      .resource-title-box{
+        display: flex;
+        border-bottom:1px solid #E4E7ED;
+        p{
+          font-size: 14px;
+          line-height:50px;
+        }
+        p:nth-child(1){
+          color: #5b95f7;
+          margin-right:10px;
+        }
+        p:nth-child(2){
+          flex:1;
+          color: #25324a;
+          font-weight: 600;
+        }
+        p:nth-child(3){
+          color:#409EFF;
+          cursor: pointer;
+        }
       }
-      p:nth-child(2){
+    }
+    .resource-body-bottom{
+      height:500px;
+      border-left:1px solid #E4E7ED;
+      border-right:1px solid #E4E7ED;
+      border-bottom:1px solid #E4E7ED;
+      .for-max-big-box{
+        display: inline-block;
+        border-radius: 10px;
+        overflow: hidden;
         cursor: pointer;
-        color:#0183fa;
-        font-size:15px;
+        box-shadow: 0 2px 8px rgba(37, 50, 74, 0.08);
+        transition: transform 0.2s;
+        margin:15px 0 0 15px;
+        img{
+          display: block;
+          height: 164px;
+          width: 356px;
+        }
+        div{
+          padding: 12px;
+          p:nth-child(1){
+            font-size: 13px;
+            color: #25324a;
+            font-weight: 500;
+            margin-bottom: 4px;
+            /*单行省略号*/
+            display:block;
+            overflow:hidden;
+            text-overflow:ellipsis;
+            white-space:nowrap;
+          }
+          p:nth-child(2){
+            font-size: 11px;
+            color: #93a0b5;
+          }
+        }
+      }
+      .for-max-big-box:hover{
+        transform:translateY(-2px),
       }
-    }
-    .big-content-box{
-      flex:1;
-      display: flex;
-      flex-direction: column;
     }
   }
 }

+ 281 - 167
src/views/safetyEducationExaminationNew/workbench/TaskCard.vue

@@ -2,14 +2,13 @@
 <template>
   <div class="task-card">
     <div class="top-title-box">
-      <p>工作台任务</p>
+      <p>工作台任务</p>
     </div>
     <div class="card-max-big-box">
       <div class="year-card-box for-max-big-box">
         <div class="year-card-top-title-box">
           <p>学年数据统计</p>
           <p>按学年统计历年考试通过情况与成绩</p>
-          <!--<p v-if="yearType">成绩报告</p>-->
         </div>
         <div class="bottom-content-box scrollbar-box">
           <p class="null-p" v-if="!yearMinList[0]">暂无数据</p>
@@ -19,49 +18,78 @@
           </div>
         </div>
       </div>
-      <!--学习任务卡-->
-      <!--<div class="study-card-box for-max-big-box">-->
-        <!--<div class="year-card-top-title-box">-->
-          <!--<p>学习任务</p>-->
-          <!--<p>待完成的学习任务</p>-->
-        <!--</div>-->
-        <!--<div class="bottom-content-box scrollbar-box">-->
-          <!--<p class="null-p" v-if="!studyMinList[0]">暂无数据</p>-->
-          <!--<div class="bottom-big-box-2" v-for="(item,index) in studyMinList" @click="studyTableButton(item)">-->
-            <!--<p>{{item.courseName}}</p>-->
-            <!--<p >{{item.deptName}}丨{{item.learnStatus==0?'待完成':(item.learnStatus==1?'进行中':(item.learnStatus==2?'已完成':''))}}</p>-->
-          <!--</div>-->
-        <!--</div>-->
-      <!--</div>-->
-      <!--模拟任务卡-->
-      <!--<div class="examination-card-box for-max-big-box">-->
-        <!--<div class="year-card-top-title-box">-->
-          <!--<p>模拟考试</p>-->
-          <!--<p>待完成的考前模拟练习</p>-->
-        <!--</div>-->
-        <!--<div class="bottom-content-box scrollbar-box">-->
-          <!--<p class="null-p" v-if="!examinationMinList[0]">暂无数据</p>-->
-          <!--<div class="bottom-big-box-3" v-for="(item,index) in examinationMinList" @click="mockTableButton(item)">-->
-            <!--<p>{{item.examName}}</p>-->
-            <!--<p >最高成绩 {{item.maxScore?item.maxScore:0}}</p>-->
-          <!--</div>-->
-        <!--</div>-->
-      <!--</div>-->
+      <!--任务卡列表-->
+      <div class="year-card-box for-max-big-box">
+        <div class="year-card-top-title-box">
+          <p>学习考试任务</p>
+          <p>待完成的学习任务</p>
+        </div>
+        <div class="bottom-content-box scrollbar-box">
+          <p class="null-p" v-if="!dataList2[0]">暂无数据</p>
+          <div class="bottom-big-box-5" v-for="(item,index) in dataList2" @click="tableButton(item.conditionType,item)">
+            <p class="text-name-p">{{item.examName}}</p>
+            <div class="text-flex-box" v-if="item.conditionType == 1">
+              <p>考前学习</p>
+              <p>{{item.completedStudyHours}} / {{item.studyHoursRequirement}} 学时</p>
+            </div>
+            <div class="text-flex-box" v-if="item.conditionType == 2">
+              <p>考前学习</p>
+              <p>未完成</p>
+            </div>
+            <div class="text-flex-box" v-if="item.conditionType == 3">
+              <p>模拟考试</p>
+              <p>未完成</p>
+            </div>
+            <div class="text-flex-box" v-if="item.examKind==1&&item.conditionType == 4">
+              <p>在线考试</p>
+              <p>
+                <span :class="!item.isPassed&&item.attemptCount==0?'color-A':(!item.isPassed&&item.attemptCount>0?'color-B':(item.isPassed?'color-C':''))">{{!item.isPassed&&item.attemptCount==0?'未开始':(!item.isPassed&&item.attemptCount>0?'未通过':(item.isPassed?'已通过':''))}}</span>
+                <span style="margin-left:20px;">{{item.attemptCount>0?'成绩:'+item.maxScore+'分':''}}</span>
+              </p>
+            </div>
+            <div class="text-flex-box" v-if="item.examKind==2&&item.conditionType == 4">
+              <p>补考</p>
+              <p>未完成</p>
+            </div>
+            <p class="time-p">{{parseTime(item.startTime,"{y}-{m}-{d} {h}:{i}")}} 至 {{parseTime(item.endTime,"{y}-{m}-{d} {h}:{i}")}}</p>
+          </div>
+        </div>
+      </div>
+      <!--模拟练习卡-->
+      <div class="examination-card-box for-max-big-box">
+        <div class="year-card-top-title-box">
+          <p>模拟练习</p>
+          <p>刷题进度和正确率</p>
+        </div>
+        <div class="bottom-content-box scrollbar-box" style="cursor: pointer;" @click="goPracticeQuestions()">
+          <div class="bottom-big-box-6">
+            <p>{{summaryData.completedCount}} / {{summaryData.totalCount}}</p>
+            <p >已完成题目数 / 题库总数</p>
+          </div>
+          <div class="bottom-big-box-6">
+            <p>{{summaryData.correctRate}}%</p>
+            <p >当前模拟练习正确率</p>
+          </div>
+        </div>
+      </div>
       <!--在线任务卡-->
       <div class="for-max-big-box" v-for="(item,index) in dataList" :key="index">
         <div class="year-card-top-title-box">
-          <p>{{item.examTypeName}}</p>
+          <p>{{item.examName}}</p>
           <p v-if="item.examKind==1&&item.conditionType != 4">满足前置条件后可参加考试</p>
           <p v-if="item.examKind==1&&item.conditionType == 4">
-            <span :class="!item.isPassed&&item.maxScore==0?'color-A':(!item.isPassed&&item.maxScore>0?'color-B':(item.isPassed?'color-C':''))">{{!item.isPassed&&item.maxScore==0?'未开始':(!item.isPassed&&item.maxScore>0?'未通过':(item.isPassed?'已通过':''))}}</span>
-            <span style="margin-left:20px;">{{item.maxScore>0?'成绩:'+item.maxScore+'分':''}}</span>
+            <span>{{parseTime(item.startTime,"{y}-{m}-{d} {h}:{i}")}} 至 {{parseTime(item.endTime,"{y}-{m}-{d} {h}:{i}")}}</span>
+          </p>
+          <p v-if="item.examKind==1&&item.conditionType == 4">
+            <span :class="!item.isPassed&&item.attemptCount==0?'color-A':(!item.isPassed&&item.attemptCount>0?'color-B':(item.isPassed?'color-C':''))">{{!item.isPassed&&item.attemptCount==0?'未考试':(!item.isPassed&&item.attemptCount>0?'未通过':(item.isPassed?'已通过':''))}}</span>
+            <span v-if="item.maxScore>0" style="margin-left:15px;">{{item.attemptCount>0?'成绩:'+item.maxScore+'分':''}}</span>
           </p>
         </div>
         <div class="bottom-content-box scrollbar-box">
           <div class="bottom-big-box-4">
             <p :class="item.completedStudyHours<item.studyHoursRequirement?'text-name':''">学时要求</p>
             <p class="colorA" v-if="item.needStudy" @click="tableButton(1,item)">开始学习</p>
-            <p class="position-p-1" v-if="item.completedStudyHours<item.studyHoursRequirement">{{item.completedStudyHours}} / {{item.studyHoursRequirement}}</p>
+            <p class="position-p-1" v-if="item.completedStudyHours<item.studyHoursRequirement">{{item.completedStudyHours}} / {{item.studyHoursRequirement}} 学时</p>
             <p class="text-type" v-if="item.completedStudyHours>=item.studyHoursRequirement">已达标</p>
           </div>
           <div class="bottom-big-box-4" v-if="item.examStudy">
@@ -75,7 +103,7 @@
             <p class="colorC" v-if="item.examStudy">待完成学习任务后解锁</p>
           </div>
           <div class="bottom-big-box-4">
-            <p>考试状态</p>
+            <p>在线考试</p>
             <p class="colorA" v-if="item.examKind==1&&item.conditionType == 4" @click="tableButton(4,item)">开始考试</p>
             <p class="colorC" v-if="item.examKind==1&&item.conditionType != 4">待通过模拟考试后解锁</p>
             <p class="colorB" v-if="item.examKind==2">考试未通过</p>
@@ -87,6 +115,24 @@
         </div>
       </div>
     </div>
+    <el-dialog class="preExam-dialog"
+               :modal-append-to-body="false"
+               :close-on-click-modal="false" :close-on-press-escape="false"
+               title="考试承诺书"
+               :visible.sync="preExamDialogType"
+               v-if="preExamDialogType"
+               width="840px"
+               append-to-body>
+      <div style="height:600px;" class="scrollbar-box">
+        <richTextPdf ref="richTextPdf" :content="richTextHtml" />
+      </div>
+      <div slot="footer" class="dialog-footer dialog-footer-box">
+        <p class="dialog-footer-button-null"></p>
+        <p class="dialog-footer-button-border" v-if="preButtonType" @click="preExamDialogCancel">下载</p>
+        <p class="dialog-footer-button-primary" @click="examUserExamStart">确认</p>
+        <p class="dialog-footer-button-null"></p>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
@@ -94,10 +140,13 @@
   import { Encrypt,Decrypt} from '@/utils/secret'
   import {
     examUserCoursewareLearningRestart,examElLabEduRelationAcademicYearProgress,
-    examUserCourseLearningList,examUserExamMockList,examUserExamList,examUserExamStart,
+    examUserExamStudyTaskList,examUserExamStart,examUserPracticeSummary,
+    examUserExamCommitmentConfirm,
   } from "@/api/safetyEducationExaminationNew/index";
+  import richTextPdf from '@/views/safetyEducationExaminationNew/components/richTextPdf.vue';
 export default {
   name: 'TaskCard',
+  components: { richTextPdf },
   data() {
     return {
       //学年数据
@@ -106,6 +155,17 @@ export default {
       studyMinList:[],
       examinationMinList:[],
       dataList:[],
+      dataList2:[],
+      summaryData:{
+        totalCount:0,
+        completedCount:0,
+        correctRate:0,
+      },
+      //考前承诺相关
+      preExamDialogType:false,
+      preButtonType:false,
+      richTextHtml: '',
+      preData:null,
     }
   },
   created() {
@@ -116,88 +176,81 @@ export default {
   },
   methods: {
     initialization(){
+      this.examUserPracticeSummary();
       this.examElLabEduRelationAcademicYearProgress();
-      // this.examUserCourseLearningList();
-      // this.examUserExamMockList();
-      this.examUserExamList();
+      this.examUserExamStudyTaskList();
+      this.examUserExamStudyTaskList2();
     },
-    //学习任务
-    studyTableButton(item){
-      let self = this;
-      if(item.conditionType == 1){
-        this.$confirm('还未达到学时要求,是否现在去学习?', "提示", {
-          confirmButtonText: "确认",
-          cancelButtonText: "取消",
-          type: "warning"
-        }).then(function() {
-        }).then(() => {
-          //学时要求
-          self.$router.push({
-            name: 'knowledgeLearning',
-            params: {}
-          })
-        }).catch(() => {});
+    //下载承诺书
+    preExamDialogCancel(){
+      this.msgSuccess('正在下载,请耐心等候')
+      this.$refs['richTextPdf'].downloadPDF();
+    },
+    //确认承诺-并考试
+    examUserExamStart(){
+      if(this.preData.attemptId){
+        this.examUserExamCommitmentConfirm(1,this.preData.attemptId);
       }else{
-        //学习课程
-        this.$router.push({
-          name: 'learningCourse',
-          params: {
-            courseId: item.courseId,
-            examId: item.examId,
+        examUserExamStart({examId:this.preData.examId,examScene:1,}).then(response => {
+          if(response.data.attemptId){
+            this.examUserExamCommitmentConfirm(2,response.data.attemptId);
+          }else{
+            this.msgError(response.message)
           }
         })
       }
     },
-    //模拟考试
-    mockTableButton(item){
-      let self = this;
-      if(item.conditionType == 1){
-        this.$confirm('完成学时要求后解锁,是否现在去学习?', "提示", {
-          confirmButtonText: "确认",
-          cancelButtonText: "取消",
-          type: "warning"
-        }).then(function() {
-        }).then(() => {
-          //学时要求
-          self.$router.push({
-            name: 'knowledgeLearning',
-            params: {}
+    examUserExamCommitmentConfirm(type,attemptId){
+      examUserExamCommitmentConfirm({attemptId:attemptId}).then(response => {
+        if(type == 1){
+          this.$router.push({
+            path: '/startTheExam',
+            query: {
+              attemptId: attemptId,
+              type: '1',
+              examKind:this.preData.examKind,
+            }
           })
-        }).catch(() => {});
-      }else if(item.conditionType == 2){
-        this.$confirm('完成考前课程学习后解锁,是否现在去学习?', "提示", {
-          confirmButtonText: "确认",
-          cancelButtonText: "取消",
-          type: "warning"
-        }).then(function() {
-        }).then(() => {
-          //学习课程
-          self.$router.push({
-            name: 'learningCourse',
-            params: {
-              courseId: item.courseId,
-              examId: item.examId,
+        }else if(type == 2){
+          this.$router.push({
+            path: '/startTheExam',
+            query: {
+              examId: this.preData.examId,
+              attemptId: attemptId,
+              type: '1',
+              examKind:this.preData.examKind,
             }
           })
-        }).catch(() => {});
+        }
+      })
+    },
+    //开始考试判断是否有承诺书
+    setRichExamData(item){
+      if(item.commitmentEnabled == 1 && !item.commitmentConfirmed){
+        this.$set(this,'preButtonType',item.commitmentPrintEnabled == 1?true:false);
+        this.$set(this,'richTextHtml',item.commitmentContent);
+        this.$set(this,'preData',item);
+        this.$set(this,'preExamDialogType',true);
       }else{
-        //模拟考试
         if(item.attemptId){
           this.$router.push({
-            name: 'mockExam',
-            params: {
-              examId: item.examId,
+            path: '/startTheExam',
+            query: {
               attemptId: item.attemptId,
+              type: '1',
+              examKind:item.examKind,
             }
           })
         }else{
-          examUserExamStart({examId:item.examId,examScene:2,}).then(response => {
+          examUserExamStart({examId:item.examId,examScene:1,}).then(response => {
             if(response.data.attemptId){
               this.$router.push({
-                name: 'mockExam',
-                params: {
+                path: '/startTheExam',
+                query: {
                   examId: item.examId,
                   attemptId: response.data.attemptId,
+                  type: '1',
+                  examKind:item.examKind,
                 }
               })
             }else{
@@ -207,6 +260,13 @@ export default {
         }
       }
     },
+    //跳转刷题练习
+    goPracticeQuestions(){
+      this.$router.push({
+        path: '/safetyEducationExaminationNew/safetyTest/practiceQuestions',
+        query: {}
+      })
+    },
     //考试跳转
     tableButton(type,item){
       let self = this;
@@ -228,8 +288,8 @@ export default {
       }else if(type == 2){
         //学习课程
         this.$router.push({
-          name: 'learningCourse',
-          params: {
+          path: '/learningCourse',
+          query: {
             courseId: item.courseId,
             examId: item.examId,
           }
@@ -238,8 +298,8 @@ export default {
         //模拟考试
         if(item.mockExamId){
           this.$router.push({
-            name: 'mockExam',
-            params: {
+            path: '/mockExam',
+            query: {
               examId: item.examId,
               attemptId: item.mockExamId,
             }
@@ -248,8 +308,8 @@ export default {
           examUserExamStart({examId:item.examId,examScene:2,}).then(response => {
             if(response.data.attemptId){
               this.$router.push({
-                name: 'mockExam',
-                params: {
+                path: '/mockExam',
+                query: {
                   examId: item.examId,
                   attemptId: response.data.attemptId,
                 }
@@ -261,32 +321,7 @@ export default {
         }
       }else if(type == 4){
         //在线考试//补考
-        if(item.attemptId){
-          this.$router.push({
-            name: 'startTheExam',
-            params: {
-              attemptId: item.attemptId,
-              type: '1',
-              examKind:item.examKind,
-            }
-          })
-        }else{
-          examUserExamStart({examId:item.examId,examScene:1,}).then(response => {
-            if(response.data.attemptId){
-              this.$router.push({
-                name: 'startTheExam',
-                params: {
-                  examId: item.examId,
-                  attemptId: response.data.attemptId,
-                  type: '1',
-                  examKind:item.examKind,
-                }
-              })
-            }else{
-              this.msgError(response.message)
-            }
-          })
-        }
+        this.setRichExamData(item);
       }
     },
     //查询学年进度列表
@@ -295,36 +330,34 @@ export default {
         this.$set(this, 'yearMinList', response.data)
       })
     },
-    //学习任务
-    examUserCourseLearningList(){
-      let obj = {
-        page:1,
-        pageSize:20,
-      }
-      examUserCourseLearningList(obj).then(response => {
-        this.$set(this, 'studyMinList', response.data.records)
-      })
-    },
-    //模拟考试
-    examUserExamMockList(){
+    //特殊考试
+    examUserExamStudyTaskList(){
       let obj = {
         page:1,
-        pageSize:20,
+        pageSize:5,
         examStatus:2,
+        isSpecialExam:true,
       }
-      examUserExamMockList(obj).then(response => {
-        this.$set(this, 'examinationMinList', response.data.records)
+      examUserExamStudyTaskList(obj).then(response => {
+        this.$set(this, 'dataList', response.data.records)
       })
     },
     //在线考试
-    examUserExamList(){
+    examUserExamStudyTaskList2(){
       let obj = {
         page:1,
         pageSize:5,
         examStatus:2,
+        isSpecialExam:false,
       }
-      examUserExamList(obj).then(response => {
-        this.$set(this, 'dataList', response.data.records)
+      examUserExamStudyTaskList(obj).then(response => {
+        this.$set(this, 'dataList2', response.data.records)
+      })
+    },
+    //在线考试
+    examUserPracticeSummary(){
+      examUserPracticeSummary({}).then(response => {
+        this.$set(this, 'summaryData', response.data)
       })
     },
   },
@@ -334,10 +367,14 @@ export default {
 <style scoped lang="scss">
 .task-card {
   background: #fff;
-  border-radius: 6px;
+  /*border-radius: 6px;*/
   padding: 16px 0 0 0;
   margin-bottom: 12px;
-  box-shadow: 0 1px 4px rgba(0,0,0,0.06);
+  /*box-shadow: 0 1px 4px rgba(0,0,0,0.06);*/
+  background: rgba(255, 255, 255, 0.95);
+  border: 1px solid #e8edf5;
+  border-radius: 16px;
+  box-shadow: 0 4px 20px rgba(37, 50, 74, 0.06);
   .top-title-box{
     display: flex;
     flex-direction: column;
@@ -371,12 +408,15 @@ export default {
     .for-max-big-box{
       display: inline-block;
       width:360px;
-      height:240px;
+      height:300px;
       margin: 0 0 20px 20px;
-      border-radius:6px;
-      border:1px solid #dedede;
-      box-shadow: 0 0 15px rgba(0, 0, 0, 0.2);
+      /*border-radius:6px;*/
+      /*border:1px solid #dedede;*/
+      /*box-shadow: 0 0 15px rgba(0, 0, 0, 0.2);*/
       overflow: hidden;
+      background: linear-gradient(180deg, #fff, #f7faff);
+      border: 1px solid #eaf0f8;
+      border-radius: 14px;
       .year-card-top-title-box{
         padding:20px 20px 0 20px;
         position: relative;
@@ -390,19 +430,18 @@ export default {
           font-size:14px;
           line-height:20px;
           margin-top:6px;
+          color:#60708a;
 
         }
         p:nth-child(3){
           cursor: pointer;
           font-size:14px;
           line-height:30px;
-          background-color: #0183fa;
-          color:#fff;
-          border-radius:6px;
+          color:#60708a;
+          text-align: right;
           position: absolute;
           top:10px;
-          right:10px;
-          padding:0 10px;
+          right:20px;
         }
         .color-A{
           color:#999;
@@ -415,7 +454,7 @@ export default {
         }
       }
       .bottom-content-box{
-        height:168px;
+        height:208px;
         margin-top:6px;
         padding:8px 14px 0 20px;
         .null-p{
@@ -426,11 +465,13 @@ export default {
         }
         .bottom-big-box-1{
           display: flex;
-          background-color: rgba(1, 131, 250, 0.1);
+          /*background-color: rgba(1, 131, 250, 0.1);*/
           border-radius:6px;
           padding:12px 14px;
           margin-bottom:12px;
           height:68px;
+          border: 1px solid #e5edf8;
+          background-color: #fff;
           p{
             font-size:14px;
             line-height:44px;
@@ -446,12 +487,14 @@ export default {
           }
         }
         .bottom-big-box-2{
-          background-color: rgba(1, 131, 250, 0.1);
+          /*background-color: rgba(1, 131, 250, 0.1);*/
           border-radius:6px;
           padding:12px 14px;
           margin-bottom:12px;
           height:68px;
           cursor: pointer;
+          border: 1px solid #e5edf8;
+          background-color: #fff;
           p{
             font-size:14px;
             line-height:22px;
@@ -462,12 +505,14 @@ export default {
           }
         }
         .bottom-big-box-3{
-          background-color: rgba(1, 131, 250, 0.1);
+          /*background-color: rgba(1, 131, 250, 0.1);*/
           border-radius:6px;
           padding:12px 14px;
           margin-bottom:12px;
           height:68px;
           cursor: pointer;
+          border: 1px solid #e5edf8;
+          background-color: #fff;
           p{
             font-size:14px;
             line-height:22px;
@@ -478,13 +523,15 @@ export default {
           }
         }
         .bottom-big-box-4{
-          background-color: rgba(1, 131, 250, 0.1);
+          /*background-color: rgba(1, 131, 250, 0.1);*/
           border-radius:6px;
           padding:12px 14px;
           margin-bottom:12px;
           height:68px;
           display: flex;
           position: relative;
+          border: 1px solid #e5edf8;
+          background-color: #fff;
           p{
             font-size:14px;
             line-height:44px;
@@ -504,14 +551,15 @@ export default {
             color:#D9001B;
           }
           .colorC{
-            color:#999;
+            color:#60708a;
           }
           .position-p-1{
             position: absolute;
             bottom:0;
-            left:10px;
-            width: 60px;
-            text-align: center!important;
+            left:15px;
+            width: 120px;
+            font-size:12px;
+            color:#60708a;
           }
           .text-name{
             margin-top:-10px;
@@ -520,6 +568,72 @@ export default {
             color: #4fbe7e;
           }
         }
+        .bottom-big-box-5{
+          /*background-color: rgba(1, 131, 250, 0.1);*/
+          border-radius:6px;
+          padding:8px 14px;
+          margin-bottom:12px;
+          height:76px;
+          position: relative;
+          border: 1px solid #e5edf8;
+          background-color: #fff;
+          cursor: pointer;
+          .text-name-p{
+            font-size:14px;
+            font-weight:700;
+            line-height:20px;
+          }
+          .text-flex-box{
+            display: flex;
+            color:#60708a;
+            p{
+              font-size:14px;
+              line-height:20px;
+            }
+            p:nth-child(1){
+              margin-right:20px;
+            }
+            p:nth-child(2){
+              color:#60708a;
+              .color-A{
+                color:#999;
+              }
+              .color-B{
+                color:#f56c6c;
+              }
+              .color-C{
+                color:#4fbe7e;
+              }
+            }
+          }
+          .time-p{
+            color:#60708a;
+            font-size:14px;
+            line-height:20px;
+          }
+        }
+        .bottom-big-box-6{
+          /*background-color: rgba(1, 131, 250, 0.1);*/
+          border-radius:6px;
+          padding:13px 14px;
+          margin-bottom:12px;
+          height:78px;
+          position: relative;
+          border: 1px solid #e5edf8;
+          background-color: #fff;
+          p:nth-child(1){
+            display: block;
+            font-size: 22px;
+            color: #25324a;
+            font-weight:700;
+            line-height:26px;
+          }
+          p:nth-child(2){
+            font-size:14px;
+            line-height:26px;
+            color:#60708a;
+          }
+        }
       }
     }
   }

+ 126 - 90
src/views/safetyEducationExaminationNew/workbench/UserInfoCard.vue

@@ -2,12 +2,12 @@
 <template>
   <div class="user-info-card">
     <div class="top-title-box">
-      <p>用户信息</p>
+      <p>用户信息</p>
       <p><span class="el-icon-coin"></span><span> {{userInfo.totalPoints?userInfo.totalPoints:0}} </span>积分</p>
     </div>
     <div class="user-info-max-box">
       <!--用户信息-->
-      <div class="left-max-box">
+      <div :class="userInfo.userType == 1?'min-height-box':''" class="left-max-box">
         <div class="left-min-box">
           <p>姓名</p>
           <p>{{userInfo.userName}}</p>
@@ -34,7 +34,7 @@
         </div>
       </div>
       <!--进度-->
-      <div class="center-max-box">
+      <div :class="userInfo.userType == 1?'min-height-box':''" class="center-max-box">
         <div class="center-title-box scrollbar-x-box">
           <p>{{userInfo.gradeRange}}</p>
           <p :style="'color:'+userInfo.levelColor+';'" v-if="userInfo.levelName">{{userInfo.levelName}}</p>
@@ -64,7 +64,7 @@
         </div>
       </div>
       <!--任务-->
-      <div class="right-max-box">
+      <div :class="userInfo.userType == 1?'min-height-box':''" class="right-max-box">
         <p class="right-title-p">当前学年任务状态</p>
         <div class="right-big-box">
           <p>考试状态</p>
@@ -91,12 +91,12 @@
       <div class="shade-big-box" v-if="shadeType == 1">
         <div class="shade-title-box">
           <p>绑定实验室</p>
-          <p class="el-icon-close" @click="shadeButton(5)"></p>
+          <p class="el-icon-close" v-if="shadeFormData.offType" @click="shadeButton(6)"></p>
         </div>
         <div class="shade-content-box">
           <el-form :model="shadeFormData" class="form-box" ref="shadeForm"
                    :inline="true" :rules="rules" style="width:100%;">
-            <div>
+            <div v-if="!shadeFormData.isEnter">
               <el-form-item label="" prop="subId" label-width="0">
                 <el-select
                   style="width:760px;"
@@ -116,9 +116,9 @@
                 </el-select>
               </el-form-item>
             </div>
-            <p class="shade-text-p">此处请选择需要后续进入的科研实验室的名称,输入实验室名称、房间号或楼栋关键词,再从检索结果中选择目标实验室。</p>
+            <p v-if="!shadeFormData.isEnter" class="shade-text-p">此处请选择需要后续进入的科研实验室的名称,输入实验室名称、房间号或楼栋关键词,再从检索结果中选择目标实验室。</p>
             <!--实验室信息-->
-            <div class="shade-sub-max-box" v-if="shadeFormData.subId&&subData.subName">
+            <div class="shade-sub-max-box" v-if="shadeFormData.subId&&subData.subName&&!shadeFormData.isEnter">
               <div class="shade-sub-big-box">
                 <div class="shade-sub-box">
                   <p>实验室名称</p>
@@ -172,7 +172,7 @@
               <p class="shade-text-p">毕业论文或毕业设计,科创等相关需要在具体的实验室开展业务的情况可申请绑定实验室,绑定完毕后需要完成对应的分级考试。</p>
             </div>
             <!--研究生选项-->
-            <div class="checkbox-box" v-if="userInfo.educationType == 1&&userInfo.isNew">
+            <div class="checkbox-box">
               <el-form-item label="" label-width="0">
                 <el-checkbox v-model="shadeFormData.isEnter">无需进入实验室</el-checkbox>
                 <p class="checkbox-text-p">人文、体育等相关学院无需进入实验室的新研究生可选择此项,选择后学时要求为4小时,需通过应知应会考试。</p>
@@ -180,7 +180,9 @@
             </div>
             <div class="shade-check-box">
               <el-form-item label="" prop="checkType" label-width="0">
-                <el-checkbox v-model="shadeFormData.checkType">我已阅读并同意</el-checkbox>
+                <el-checkbox
+                  @click.native.prevent="shadeButton(2)"
+                  v-model="shadeFormData.checkType">我已阅读并同意</el-checkbox>
                 <span style="color:#0183fa;font-size:14px;cursor: pointer"  @click="shadeButton(2)">《新生绑定实验室须知及责任说明》</span>
               </el-form-item>
             </div>
@@ -188,8 +190,8 @@
         </div>
         <div class="shade-button-box">
           <p></p>
-          <p @click="shadeButton(5)">取消</p>
-          <p @click="shadeButton(1)">确认绑定</p>
+          <p class="out-button" v-if="shadeFormData.offType" @click="shadeButton(6)">取消</p>
+          <p class="submit-button" @click="shadeButton(1)">确认绑定</p>
         </div>
       </div>
       <div class="shade-big-box" v-if="shadeType == 2">
@@ -197,11 +199,13 @@
           <p>新生绑定实验室须知及责任说明</p>
         </div>
         <div class="shade-content-box-2 scrollbar-box">
-          <p v-html="textDetail"></p>
+          <p>1. 保证进入的实验室为导师实际使用实验室或属于当前实验室所属课题组。</p>
+          <p>2. 研究生期间涉及到操作实验室内重要危险源,必须绑定实验室。</p>
+          <p></p>
         </div>
         <div class="shade-button-box-2">
           <p></p>
-          <p></p>
+          <p @click="shadeButton(33)">取消</p>
           <p @click="shadeButton(3)">我已知晓</p>
         </div>
       </div>
@@ -212,7 +216,7 @@
 <script>
   import {
     examElLabEduRelationBindStatus,examElLabEduRelationLabLists,examElLabEduRelationBind,
-    examElLabEduRelationLabDetail,laboratoryLabSafeManagerRegulationsDetail,
+    examElLabEduRelationLabDetail,
   } from "@/api/safetyEducationExaminationNew/index";
 export default {
   name: 'UserInfoCard',
@@ -277,7 +281,6 @@ export default {
   },
   mounted() {
     this.examElLabEduRelationBindStatus();
-    this.laboratoryLabSafeManagerRegulationsDetail();
   },
   methods: {
     //进度条去除描述
@@ -288,17 +291,11 @@ export default {
     examElLabEduRelationBindStatus(){
       examElLabEduRelationBindStatus({}).then(response => {
         this.$set(this, 'userInfo', response.data)
-        if((!response.data.bound&&response.data.educationType == 1)||(!response.data.bound&&response.data.educationType == 2&&response.data.isFinishExam)){
-          this.shadeButton(4);
+        if(!response.data.bound&&response.data.educationType == 1){
+          this.shadeButton(5);
         }
       })
     },
-    //实验室管理规定查询
-    laboratoryLabSafeManagerRegulationsDetail(){
-      laboratoryLabSafeManagerRegulationsDetail({}).then(response => {
-        this.$set(this, 'textDetail', unescape(response.data))
-      })
-    },
     //实验室懒加载
     subSelectList(query) {
       if (query !== '' && query.length>1) {
@@ -329,20 +326,27 @@ export default {
       }else if(type == 2){
         //查看通知
         this.$set(this,'shadeType',2);
-      }else if(type == 3){
-        //关闭通知
-        this.$set(this.shadeFormData,'checkType',true);
-        this.$set(this,'shadeType',1);
-      }else if(type == 4){
+      }else if(type == 3 || type == 33){
+        if(type == 3){
+          //关闭通知
+          this.$set(this.shadeFormData,'checkType',true);
+          this.$set(this,'shadeType',1);
+        }else if(type == 33){
+          //关闭通知
+          this.$set(this.shadeFormData,'checkType',false);
+          this.$set(this,'shadeType',1);
+        }
+      }else if(type == 4||type == 5){
         //开启
         this.$set(this,'shadeFormData',{
           subId:null,
           reason:'',
           isEnter:false,
           checkType:false,
+          offType:type == 4?true:false,
         });
         this.$set(this,'shadeType',1);
-      }else if(type == 5){
+      }else if(type == 6){
         //关闭
         this.$set(this,'shadeType',null);
       }
@@ -354,19 +358,10 @@ export default {
     },
     examElLabEduRelationBind(){
       let obj = {
-        subId:this.shadeFormData.subId,
+        subId:this.shadeFormData.subId?this.shadeFormData.subId:'',
+        reason:this.shadeFormData.reason?this.shadeFormData.reason:'',
+        isEnter:this.shadeFormData.isEnter?'0':'1'
       };
-      if(this.userInfo.educationType == 1&&this.userInfo.isNew){
-        obj.reason = '';
-        obj.isEnter = this.shadeFormData.isEnter?'0':'1';
-      }else if(this.userInfo.educationType == 1&&!this.userInfo.isNew){
-        obj.reason = '';
-        obj.isEnter = '0';
-      }else if(this.userInfo.educationType == 2){
-        obj.reason = this.shadeFormData.reason;
-        obj.isEnter = '1';
-      }
-
       examElLabEduRelationBind(obj).then(response => {
         this.msgSuccess(response.message);
         this.$set(this,'shadeType',null);
@@ -380,10 +375,14 @@ export default {
 <style scoped lang="scss">
 .user-info-card {
   background: #fff;
-  border-radius: 6px;
+  /*border-radius: 6px;*/
   padding: 16px 20px;
   margin-bottom: 12px;
-  box-shadow: 0 1px 4px rgba(0,0,0,0.06);
+  /*box-shadow: 0 1px 4px rgba(0,0,0,0.06);*/
+  background: rgba(255, 255, 255, 0.95);
+  border: 1px solid #e8edf5;
+  border-radius: 16px;
+  box-shadow: 0 4px 20px rgba(37, 50, 74, 0.06);
   .top-title-box{
     display: flex;
     p{
@@ -409,29 +408,32 @@ export default {
     display: flex;
     margin-top:20px;
     .left-max-box{
-      width:460px;
-      height:290px;
-      border-radius:6px;
-      border:1px solid #dedede;
-      box-shadow: 0 0 15px rgba(0, 0, 0, 0.2);
+      width:560px;
+      height:260px;
+      /*border-radius:6px;*/
+      /*border:1px solid #dedede;*/
+      /*box-shadow: 0 0 15px rgba(0, 0, 0, 0.2);*/
       padding:20px 20px 0 20px;
+      background: linear-gradient(180deg, #fff, #f7faff);
+      border: 1px solid #eaf0f8;
+      border-radius: 14px;
       .left-min-box:nth-child(odd){
         margin-right:20px;
       }
       .left-min-box{
         display: inline-block;
         overflow:hidden;
-        width:198px;
-        margin-bottom:15px;
+        width:248px;
+        margin-bottom:10px;
         p{
-          line-height:30px;
+          line-height:25px;
         }
         p:nth-child(1){
-          font-size:14px;
+          font-size:12px;
           color:#666;
         }
         p:nth-child(2){
-          font-size:16px;
+          font-size:14px;
           font-weight:700;
           display:block;
           overflow:hidden;
@@ -448,7 +450,7 @@ export default {
       .left-sub-min-box{
         display: inline-block;
         overflow:hidden;
-        width:198px;
+        width:248px;
         margin-bottom:15px;
         p{
           line-height:30px;
@@ -458,7 +460,7 @@ export default {
           color:#666;
         }
         .text-p{
-          font-size:16px;
+          font-size:14px;
           font-weight:700;
           display:block;
           overflow:hidden;
@@ -480,24 +482,31 @@ export default {
     }
     .center-max-box{
       width:430px;
-      height:290px;
-      border-radius:6px;
-      border:1px solid #dedede;
-      box-shadow: 0 0 15px rgba(0, 0, 0, 0.2);
+      height:260px;
+      /*border-radius:6px;*/
+      /*border:1px solid #dedede;*/
+      /*box-shadow: 0 0 15px rgba(0, 0, 0, 0.2);*/
       padding:20px;
       margin:0 20px;
+      background: linear-gradient(180deg, #fff, #f7faff);
+      border: 1px solid #eaf0f8;
+      border-radius: 14px;
       .center-title-box{
         height:50px;
         p{
+          color: #3978e6;
+          background: #eef4ff;
           display: inline-block;
-          border:1px solid #999;
-          color:#0183fa;
-          border-radius:6px;
+          /*border:1px solid #999;*/
+          /*color:#0183fa;*/
+          /*border-radius:6px;*/
+          border-radius:99px;
           padding: 0 15px;
           height:32px;
-          line-height:30px;
+          line-height:32px;
           margin-right:10px;
-          cursor: pointer;
+          font-size:14px;
+          font-weight:700;
         }
         .check-title-p{
           /*color:#fff;*/
@@ -510,14 +519,13 @@ export default {
           padding:0;
         }
         .progress-max-box{
-          height:90px;
-          margin-top:20px;
+          height:70px;
           .progress-min-box{
             display: flex;
             p{
-              font-size:16px;
+              font-size:14px;
               font-weight:700;
-              line-height:60px;
+              line-height:50px;
             }
             p:nth-child(1){
               flex:1;
@@ -530,7 +538,9 @@ export default {
             margin-right:10px;
           }
           .center-bottom-min-box{
-            background-color: rgba(1,131,250,0.1);
+            /*background-color: rgba(1,131,250,0.1);*/
+            border: 1px solid #e5edf8;
+            background-color: #f7faff;;
             padding:10px 20px;
             border-radius:6px;
             width:188px;
@@ -541,7 +551,9 @@ export default {
               font-size:14px;
             }
             p:nth-child(2){
-              font-size:16px;
+              font-size:14px;
+              line-height:20px;
+              color:#60708a;
             }
           }
         }
@@ -549,21 +561,26 @@ export default {
     }
     .right-max-box{
       flex:1;
-      height:290px;
-      border-radius:6px;
-      border:1px solid #dedede;
-      box-shadow: 0 0 15px rgba(0, 0, 0, 0.2);
+      height:260px;
+      /*border-radius:6px;*/
+      /*border:1px solid #dedede;*/
+      /*box-shadow: 0 0 15px rgba(0, 0, 0, 0.2);*/
       padding:20px;
+      background: linear-gradient(180deg, #fff, #f7faff);
+      border: 1px solid #eaf0f8;
+      border-radius: 14px;
       .right-title-p{
-        font-size:16px;
+        font-size:14px;
         font-weight:700;
         line-height:30px;
-        padding-left:20px;
-        margin-bottom:30px;
+        margin-bottom:10px;
       }
       .right-big-box{
-        background-color: #E9E9E9;
-        border-radius:6px;
+        border-radius: 10px;
+        background: #f7f9fd;
+        border: 1px solid #e8eef9;
+        /*background-color: #E9E9E9;*/
+        /*border-radius:6px;*/
         margin-bottom:10px;
         display: flex;
         height: 40px;
@@ -571,12 +588,13 @@ export default {
         p:nth-child(1){
           flex:1;
           line-height:40px;
+          font-size:14px;
         }
         p:nth-child(2){
-          width:80px;
-          height:30px;
-          line-height:30px;
-          margin:5px 20px 0 0;
+          width:70px;
+          height:24px;
+          line-height:24px;
+          margin:7px 0 0 0;
           text-align: center;
           font-size:14px;
           border-radius:15px;
@@ -592,6 +610,9 @@ export default {
         }
       }
     }
+    .min-height-box{
+      height:170px !important;
+    }
   }
   .shade-max-big-box{
     z-index:100;
@@ -713,7 +734,11 @@ export default {
       .shade-content-box-2{
         padding: 0 40px;
         margin: 20px 0;
-        height: 400px;
+        height: 200px;
+        p{
+          line-height:40px;
+          font-size:15px;
+        }
       }
       .shade-button-box{
         display: flex;
@@ -721,7 +746,7 @@ export default {
         p:nth-child(1){
           flex:1;
         }
-        p:nth-child(2){
+        .out-button{
           width:70px;
           line-height:40px;
           border-radius:4px;
@@ -730,12 +755,12 @@ export default {
           margin-right:20px;
           cursor: pointer;
         }
-        p:nth-child(2):hover{
+        .out-button:hover{
           border:1px solid #999;
           background-color: #999;
           color:#fff;
         }
-        p:nth-child(3){
+        .submit-button{
           background-color: #A0CFFE;
           color:#fff;
           width:100px;
@@ -745,7 +770,7 @@ export default {
           border:1px solid #A0CFFE;
           cursor: pointer;
         }
-        p:nth-child(3):hover{
+        .submit-button:hover{
           border:1px solid #0183fa;
           background-color: #0183fa;
         }
@@ -757,7 +782,18 @@ export default {
           flex:1;
         }
         p:nth-child(2){
-
+          width:70px;
+          line-height:40px;
+          border-radius:4px;
+          text-align: center;
+          border:1px solid #dedede;
+          margin-right:20px;
+          cursor: pointer;
+        }
+        p:nth-child(2):hover{
+          border:1px solid #999;
+          background-color: #999;
+          color:#fff;
         }
         p:nth-child(3){
           background-color: #A0CFFE;

+ 3 - 20
src/views/safetyEducationExaminationNew/workbench/index.vue

@@ -1,21 +1,13 @@
 <!-- 工作台 -->
 <template>
   <div class="app-container workbench">
-    <div class="page-container workbenchPage scrollbar-box" v-if="pageType === 1">
+    <div class="page-container workbenchPage scrollbar-box">
       <!-- 用户信息卡片 -->
       <user-info-card/>
       <!-- 工作台任务卡片 -->
       <task-card/>
       <!-- 实验室安全素养资源卡 -->
       <resource-card/>
-      <!-- 实验室绑定申请 -->
-      <lab-binding-apply/>
-      <!-- 考试情况统计 -->
-      <exam-situation v-if="adminType"/>
-      <!-- 实验室与人员匹配 -->
-      <lab-person-match v-if="adminType"/>
-      <!-- 学时统计 -->
-      <study-hour-stats v-if="adminType"/>
     </div>
   </div>
 </template>
@@ -25,10 +17,6 @@
   import UserInfoCard from './UserInfoCard.vue'
   import TaskCard from './TaskCard.vue'
   import ResourceCard from './ResourceCard.vue'
-  import LabBindingApply from './LabBindingApply.vue'
-  import ExamSituation from './ExamSituation.vue'
-  import LabPersonMatch from './LabPersonMatch.vue'
-  import StudyHourStats from './StudyHourStats.vue'
 
   export default {
     name: 'index',
@@ -36,22 +24,17 @@
       UserInfoCard,
       TaskCard,
       ResourceCard,
-      LabBindingApply,
-      ExamSituation,
-      LabPersonMatch,
-      StudyHourStats,
     },
     data() {
       return {
-        pageType: 1,
-        adminType:false,
+
       }
     },
     created() {
 
     },
     mounted() {
-      this.$set(this,'adminType',itoOrVideoLimits());
+
     },
     methods: {