dedsudiyu 1 day ago
parent
commit
a841c68b43

+ 41 - 7
src/views/safetyEducationExaminationNew/trainingManagement/trainingManagement/addPage.vue

@@ -33,7 +33,7 @@
               <p>*</p>
             </div>
             <el-radio-group v-model="formData.trainingMode">
-              <el-radio :label="1" border>线上培训</el-radio>
+              <!--<el-radio :label="1" border>线上培训</el-radio>-->
               <el-radio :label="2" border>线下培训</el-radio>
             </el-radio-group>
           </el-form-item>
@@ -209,8 +209,20 @@
               ></el-input-number>
             </el-form-item>
           </div>
+          <div class="form-flex-box">
+            <el-form-item label="" prop="trainingDurationMinutes" class="form-item">
+              <div class="rules-title-box">
+                <p>培训时长</p>
+                <p>*</p>
+              </div>
+              <el-input-number v-model="formData.trainingDurationMinutes" controls-position="right"
+                               style="width:645px;" :min="0" :max="9999"
+                               :step="1" :precision="0" step-strictly
+              ></el-input-number>
+            </el-form-item>
+          </div>
         </div>
-        <el-form-item label="" prop="proofRequired" class="form-item">
+        <el-form-item label="" prop="proofRequired" class="form-item" v-if="formData.trainingMode == 2">
           <div class="rules-title-box">
             <p>上传培训证明</p>
             <p></p>
@@ -344,7 +356,7 @@
         </div>
         <el-form-item label="" prop="detailContent">
           <tinymce-text
-            v-if="formData && formData.detailContent"
+            v-if="detailContentType"
             style="width:1325px;"
             v-model="formData.detailContent"
             :height="500"
@@ -480,6 +492,13 @@
           callback()
         }
       }
+      const validateData1 = (rule, value, callback) => {
+        if (this.formData.trainingMode == 2 && this.formData.trainingDurationMinutes == 0) {
+          callback(new Error('培训时长不能为0'))
+        } else {
+          callback()
+        }
+      }
       return {
         //文件上传相关
         uploadImgUrl: this.uploadUrl(), // 上传的图片服务器地址
@@ -500,7 +519,7 @@
         newData: {},
         formData:{
           trainingName:'',
-          trainingMode:'1',
+          trainingMode:2,
           categoryId:null,
           orgDeptId:null,
           orgDeptName:null,
@@ -517,8 +536,9 @@
           locationRoomRoom:'',
           creditHours:0,
           points:0,
+          trainingDurationMinutes:0,
           proofRequired:0,
-          scopeType:'1',
+          scopeType:1,
           coverImage:'',
           detailContent:'',
           attachmentPath:'',
@@ -578,6 +598,10 @@
             { required: true, message: "请输入可得积分", trigger: "blur" },
             { required: true, message: "请输入可得积分", validator: this.spaceJudgment, trigger: "blur" }
           ],
+          trainingDurationMinutes: [
+            { required: true, message: "请输入培训时长", trigger: "blur" },
+            { validator: validateData1, trigger: 'blur' }
+          ],
           scopeType: [
             { required: true, message: '请选择考试范围', trigger: 'change' },
             { validator: validateData0, trigger: 'blur' }
@@ -608,6 +632,8 @@
         userList: [],
         //详情模式
         showType:false,
+        //富文本栏展示状态
+        detailContentType:false,
       }
     },
     created() {
@@ -627,6 +653,8 @@
           this.$set(this.newData,'id',this.propsData.id);
           this.$set(this,'showType',this.propsData.showType);
           this.examElTrainingTaskDetail();
+        }else{
+          this.$set(this,'detailContentType',true);
         }
       },
       //查询培训详情
@@ -651,7 +679,8 @@
             locationRoomRoom:response.data.task.trainingMode==2?response.data.task.locationRoomRoom:'',
             creditHours:response.data.task.trainingMode==2?response.data.task.creditHours:0,
             points:response.data.task.trainingMode==2?response.data.task.points:0,
-            proofRequired:response.data.task.proofRequired,
+            trainingDurationMinutes:response.data.task.trainingMode==2?response.data.task.trainingDurationMinutes:0,
+            proofRequired:response.data.task.trainingMode==2?response.data.task.proofRequired:0,
             scopeType:response.data.task.scopeType,
             coverImage:response.data.task.coverImage,
             detailContent:response.data.task.detailContent,
@@ -670,6 +699,7 @@
                 coursewareName:response.data.coursewares[i].coursewareName,
                 creditHours:response.data.coursewares[i].creditHours,
                 points:response.data.coursewares[i].points,
+                minLearningDuration:response.data.coursewares[i].minLearningDuration,
               })
             }
           }
@@ -704,6 +734,9 @@
             this.$set(this,'userList',userList);
           }
           this.$set(this,'formData',obj);
+          this.$nextTick(()=>{
+            this.$set(this,'detailContentType',true);
+          })
         });
       },
       // 返回按钮
@@ -741,7 +774,8 @@
                 locationRoomRoom:this.formData.trainingMode==2?this.formData.locationRoomRoom:'',
                 creditHours:this.formData.trainingMode==2?this.formData.creditHours:0,
                 points:this.formData.trainingMode==2?this.formData.points:0,
-                proofRequired:this.formData.proofRequired,
+                trainingDurationMinutes:this.formData.trainingMode==2?this.formData.trainingDurationMinutes:0,
+                proofRequired:this.formData.trainingMode==2?this.formData.proofRequired:0,
                 scopeType:this.formData.scopeType,
                 scopeItems:this.formData.scopeType==2?this.scopeList:[],
                 personnel:this.formData.scopeType==3?this.userList:[],

+ 1 - 0
src/views/safetyEducationExaminationNew/trainingManagement/trainingManagement/drawerItem.vue

@@ -217,6 +217,7 @@
             coursewareName:self.multipleSelection[i].coursewareName,
             creditHours:self.multipleSelection[i].creditHours,
             points:self.multipleSelection[i].points,
+            minLearningDuration:self.multipleSelection[i].minLearningDuration,
           })
         }
         this.$parent.$parent.drawerConfirmButton(list);

+ 7 - 3
src/views/safetyEducationExaminationNew/trainingManagement/trainingManagement/trainingProgressDetails.vue

@@ -20,7 +20,7 @@
         <p>{{newData.trainingMode == 1?'签到率':'完成率'}}</p>
       </div>
     </div>
-    <el-progress stroke-width="10" :text-inside="true" style="margin:15px 0 15px;"
+    <el-progress :stroke-width="10" :text-inside="true" style="margin:15px 0 15px;"
       :percentage="percentage" :format="format"></el-progress>
     <div class="page-content-box">
       <el-table class="table-box" style="padding:0;" border :data="dataList">
@@ -76,7 +76,7 @@
           page: 1,
           pageSize: 20,
         },
-        percentage:70,
+        percentage:0,
         dataList:[],
         //数据数量
         total: 0,
@@ -93,7 +93,9 @@
         return percentage === 100 ? '' : '';
       },
       getList(){
-        examElTrainingTaskProgressDetail({ id: this.propsData.id }).then(response => {
+        let obj = JSON.parse(JSON.stringify(this.queryParams))
+        obj.id = this.propsData.id;
+        examElTrainingTaskProgressDetail(obj).then(response => {
           this.$set(this,'newData',{
             newData1:response.data.trainingMode==1?response.data.totalCount:response.data.participantCount,
             newData2:response.data.trainingMode==1?response.data.signedCount:response.data.completedCount,
@@ -102,7 +104,9 @@
             trainingMode:response.data.trainingMode,
             trainingName:response.data.trainingName,
           });
+          this.$set(this,'percentage',response.data.trainingMode==1?response.data.signRate:response.data.completionRate);
           this.$set(this,'dataList',response.data.records);
+          this.$set(this,'total',response.data.pageTotal);
         })
       },
     }

+ 4 - 1
src/views/safetyEducationExaminationNew/trainingManagement/trainingManagement/trainingRecordDetails.vue

@@ -181,7 +181,9 @@
     },
     methods: {
       getList(){
-        examElTrainingTaskProgressDetail({ id: this.propsData.id }).then(response => {
+        let obj = JSON.parse(JSON.stringify(this.queryParams))
+        obj.id = this.propsData.id;
+        examElTrainingTaskProgressDetail(obj).then(response => {
           this.$set(this,'newData',{
             newData11:response.data.trainingMode==1?response.data.totalCount:response.data.participantCount,
             newData12:response.data.trainingMode==1?response.data.signedCount:response.data.completedCount,
@@ -200,6 +202,7 @@
             speakerName:response.data.speakerName,
           });
           this.$set(this,'dataList',response.data.records);
+          this.$set(this,'total',response.data.pageTotal);
         })
       },
       tableButton(type,row){

+ 18 - 16
src/views/safetyEducationExaminationNew/trainingManagement/trainingTask/index.vue

@@ -48,14 +48,13 @@
         </el-form>
       </div>
       <div class="page-content-box">
-        <div class="for-max-big-box">
+        <div class="for-max-big-box scrollbar-box">
           <div class="for-big-box" @click="tableButton(item)" v-for="(item,index) in dataList" :key="index">
             <div class="top-img-box">
-              <!--<img v-if="item.coverImage" src="item.coverImage">-->
-              <!--<img v-else src="@/assets/ZDimages/basicsModules/image_986222064626770.png">-->
-              <img src="@/assets/ZDimages/basicsModules/image_986222064626770.png">
+              <img v-if="item.coverImage" src="item.coverImage">
+              <img v-else src="@/assets/ZDimages/basicsModules/image_986222064626770.png">
               <p class="position-type-p" :class="item.status==2?'colorA':'colorB'">{{item.status==1?'未开始':(item.status==2?'进行中':(item.status==3?'已结束':''))}}</p>
-              <p class="position-time-p">{{item.trainingMode==1?'线上':'线下'}} {{item.trainingMode==1?'课件':''}}</p>
+              <p class="position-time-p">{{item.trainingMode==1?'线上':'线下'}} · {{item.trainingMode==1?item.coursewareCount+'课件':item.trainingDurationMinutes+'学时'}}</p>
             </div>
             <div class="bottom-text-box">
               <p class="title-p">{{item.trainingName}}</p>
@@ -91,7 +90,7 @@
                v-if="dialogType"
                width="760px"
                append-to-body>
-      <div class="trainingTask-dialog-content">
+      <div class="trainingTask-dialog-content scrollbar-box">
         <info-page :propsData="propsData"></info-page>
       </div>
     </el-dialog>
@@ -173,21 +172,21 @@
       getList() {
         let obj = JSON.parse(JSON.stringify(this.queryParams))
         examUserTrainingList(obj).then(response => {
-          let list = [
-            ...response.data.records,...response.data.records,
-            ...response.data.records,...response.data.records,
-            ...response.data.records,...response.data.records,
-            ...response.data.records,...response.data.records
-          ];
-          this.$set(this,'dataList',list);
-          // this.$set(this, 'dataList', response.data.records)
+          this.$set(this, 'dataList', response.data.records)
           this.$set(this, 'total', response.data.total)
         })
       },
       //操作按钮
       tableButton(row) {
+        let obj = {
+          id:row.id,
+          status:row.status,
+          trainingMode:row.trainingMode,
+          categoryName:row.categoryName,
+
+        }
         this.$set(this,'dialogTitle',row.trainingName);
-        this.$set(this,'propsData',{id:row.id});
+        this.$set(this,'propsData',obj);
         this.$set(this,'dialogType',true);
       },
       //培训分类列表
@@ -368,7 +367,10 @@
 <style lang="scss">
   .trainingTask-dialog{
     .el-dialog__body{
-      padding:20px;
+      padding:0;
+      .trainingTask-dialog-content{
+        height:600px;
+      }
     }
   }
 </style>

+ 157 - 28
src/views/safetyEducationExaminationNew/trainingManagement/trainingTask/infoPage.vue

@@ -2,9 +2,9 @@
 <template>
   <div class="trainingTask-addPage">
     <div class="top-type-box">
-      <p>暂时没有字段</p>
-      <p>{{newData.trainingMode==1?'线上培训':'线下培训'}}</p>
-      <p>暂时没有字段</p>
+      <p>{{propsData.status==1?'未开始':(propsData.status==2?'进行中':(propsData.status==3?'已结束':''))}}</p>
+      <p>{{propsData.trainingMode==1?'线上培训':'线下培训'}}</p>
+      <p>{{propsData.categoryName}}</p>
     </div>
     <div class="title-box">
       <p></p>
@@ -28,12 +28,16 @@
         <p>{{newData.speakerName}}</p>
       </div>
       <div v-if="newData.trainingMode==2">
+        <p>培训时长</p>
+        <p>{{newData.trainingDurationMinutes}} 分钟</p>
+      </div>
+      <div v-if="newData.trainingMode==2">
         <p>可得学时</p>
-        <p>{{newData.creditHours}}</p>
+        <p style="color:#1857d4;font-weight:600;">+ {{newData.creditHours}} 学时</p>
       </div>
       <div v-if="newData.trainingMode==2">
-        <p>可得分</p>
-        <p>{{newData.points}}</p>
+        <p>可得分</p>
+        <p style="color:#e67e22;font-weight:600;">+ {{newData.points}} 积分</p>
       </div>
       <div v-if="newData.trainingMode==1">
         <p>参与人数</p>
@@ -51,45 +55,62 @@
     </div>
     <div class="max-for-box" v-if="newData.trainingMode==1">
       <p class="for-title-p">学员每完成一个课件的学习,获得对应课件的学时和积分</p>
-      <div class="for-max-box" v-for="(item,index) in coursewares" :key="index">
-        <p class="left-icon-p"></p>
-        <div class="text-box">
+      <div class="for-max-box" v-for="(item,index) in newData.coursewares" :key="index">
+        <p class="left-icon-p el-icon-video-play icon-p-a" v-if="item.materialType == 1"></p>
+        <p class="left-icon-p el-icon-document icon-p-b" v-if="item.materialType == 3"></p>
+        <p class="left-icon-p el-icon-reading icon-p-c" v-if="item.materialType == 4"></p>
+        <div class="text-center-box">
           <p>{{item.coursewareName}}</p>
           <p>{{item.materialType==1?'视频':(item.materialType==3?'文档':(item.materialType==4?'文章':''))}} · 约{{secondsToMinutes(item.minLearningDuration)}}分钟</p>
         </div>
         <div class="num-box">
-          <!--<p>+{{}}学时</p>-->
-          <!--<p>+{{}}积分</p>-->
+          <p>+{{item.creditHours}}学时</p>
+          <p>+{{item.points}}积分</p>
         </div>
-        <p class="right-p">已学习/未学习</p>
+        <p class="right-p" :class="item.learnStatus == 0?'right-color-a':(item.learnStatus == 1?'right-color-b':(item.learnStatus == 2?'right-color-c':''))"
+        >{{item.learnStatus == 0?'未学习':(item.learnStatus == 1?'学习中':(item.learnStatus == 2?'已学习':''))}}</p>
       </div>
-      <p></p>
-      <div>
+      <p class="border-p"></p>
+      <div class="progress-text-box">
         <p>学习进度</p>
-        <p>/ 课件已完成</p>
+        <p>{{count}}/{{total}} 课件已完成</p>
       </div>
+      <el-progress :stroke-width="10" :text-inside="true" style="margin:5px 0 15px;"
+                   :percentage="percentage" :format="format"></el-progress>
     </div>
-    <div class="title-box">
+    <div class="title-box" v-if="newData.attachments[0]">
       <p></p>
       <p>附件</p>
     </div>
+    <div class="attachments-box" v-if="newData.attachments[0]">
+      <p>{{newData.attachments[0].attachmentName}}</p>
+      <p @click="lookFile()">查看</p>
+    </div>
+    <fullScreenFileLook ref="fullScreenFileLook"></fullScreenFileLook>
   </div>
 </template>
 
 <script>
-import {
+  import fullScreenFileLook from "@/components/fullScreenFileLook/fullScreenFileLook.vue";
+  import {
   examUserTrainingDetail
 } from "@/api/safetyEducationExaminationNew/index";
   //import { getDicts } from "@/api/commonality/noPermission";
   //import { systemUserSelect } from "@/api/commonality/permission";
   export default {
     name: 'addPage',
+    components: {
+      fullScreenFileLook,
+    },
     props: {
       propsData: {}
     },
     data() {
       return {
-        newData: {}
+        newData: {},
+        total:0,
+        count:0,
+        percentage:0,
       }
     },
     created() {
@@ -99,9 +120,25 @@ import {
       this.examUserTrainingDetail()
     },
     methods: {
+      lookFile(){
+        let obj = {
+          name:this.newData.attachments[0].attachmentName,
+          url:this.newData.attachments[0].attachmentPath,
+          type:this.newData.attachments[0].attachmentType,
+        }
+        this.fullScreenFileLookClick(obj);
+      },
       examUserTrainingDetail(){
         examUserTrainingDetail({id:this.propsData.id}).then(response => {
           this.$set(this,'newData',response.data);
+          if(response.data.trainingMode == 1 && response.data.coursewares){
+            const total = response.data.coursewares.length;
+            const count = response.data.coursewares.reduce((acc, cur) => acc + (cur.learnStatus === 1 ? 1 : 0), 0);
+            const percentage = total > 0 ? parseFloat(((count / total) * 100).toFixed(2)) : 0;
+            this.$set(this,'total  ',total);
+            this.$set(this,'count ',count);
+            this.$set(this,'percentage',percentage);
+          }
         });
       },
       //展示时间换算
@@ -111,12 +148,19 @@ import {
         }
         return Math.ceil(totalSeconds / 60);
       },
+      format(percentage) {
+        return percentage === 100 ? '' : '';
+      },
+      fullScreenFileLookClick(item){
+        this.$refs['fullScreenFileLook'].initialize(item.name,item.url,item.type);
+      },
     }
   }
 </script>
 
 <style scoped lang="scss">
   .trainingTask-addPage {
+    padding:20px;
     .title-box{
       display: flex;
       p:nth-child(1){
@@ -186,21 +230,111 @@ import {
         margin-bottom:12px;
       }
       .for-max-box{
+        display: flex;
+        padding:14px 16px;
+        border:1px solid #dde3ed;
+        border-radius:8px;
+        margin-bottom:10px;
         .left-icon-p{
-
+          width:36px;
+          height:36px;
+          border-radius:8px;
+          text-align: center;
+          line-height:36px;
+          color:#666;
+          margin-right:20px
         }
-        .text-box{
-
+        .icon-p-a{
+          background: linear-gradient(135deg, #e6f4ff, #bae0ff);
+        }
+        .icon-p-b{
+          background: linear-gradient(135deg, #f6ffed, #d9f7be);
+        }
+        .icon-p-c{
+          background: linear-gradient(135deg, #fff7e6, #ffe7ba);
+        }
+        .text-center-box{
+          flex:1;
+          p:nth-child(1){
+            font-size:14px;
+            line-height:16px;
+            margin-bottom:4px;
+          }
+          p:nth-child(2){
+            font-size:12px;
+            line-height:16px;
+            color:#8896a7;
+          }
         }
         .num-box{
-
+          margin-right:20px;
+          p:nth-child(1){
+            font-size:13px;
+            line-height:16px;
+            color:#1857d4;
+            font-weight: 600;
+            margin-bottom:4px;
+          }
+          p:nth-child(2){
+            font-size:12px;
+            line-height:16px;
+            color:#e67e22;
+          }
         }
         .right-p{
-
+          margin-top:8px;
+          height:20px;
+          line-height:20px;
+          font-size:12px;
+          padding: 0 9px;
+          border-radius: 20px;
+        }
+        .right-color-a{
+          background-color: #f4f6fa;
+          color:#8896a7;
+        }
+        .right-color-b{
+          background-color: #fef6ec;
+          color:#e67e22;
+        }
+        .right-color-c{
+          background-color: #e6f4ff;
+          color:#1677ff;
         }
       }
 
     }
+    .attachments-box{
+      display: flex;
+      border:1px solid #91caff;
+      background-color: #e6f4ff;
+      color:#1677ff;
+      border-radius:8px;
+      padding:10px 20px;
+      p:nth-child(1){
+        flex:1;
+      }
+      p:nth-child(2){
+        cursor: pointer;
+      }
+    }
+    .border-p{
+      border-bottom:1px solid #dedede;
+      margin:15px 0;
+    }
+    .progress-text-box{
+      display: flex;
+      p:nth-child(1){
+        flex:1;
+        font-size:13px;
+        color:#4a5568;
+      }
+      p:nth-child(2){
+        font-size:13px;
+        color:#1857d4;
+        font-weight: 600;
+      }
+    }
     .rich-text-box {
       border:1px solid #dde3ed;
       padding:5px 10px;
@@ -211,7 +345,6 @@ import {
       line-height: 1.6; /* 基础行高 */
       word-break: break-word; /* 防止长单词或长链接撑破布局 */
     }
-
     /* 穿透样式,控制富文本内部的标签 */
     .rich-text-box ::v-deep img {
       max-width: 100% !important; /* 防止图片超出容器 */
@@ -224,9 +357,5 @@ import {
       width: 100%;
       border-collapse: collapse;
     }
-
-    .rich-text-box ::v-deep p {
-      margin-bottom: 10px;
-    }
   }
 </style>