Ver Fonte

app-自测练习

xiaoqiao há 7 meses atrás
pai
commit
e6ef17b759

+ 9 - 0
parth5/parth5/src/app/app.scss

@@ -515,3 +515,12 @@ ion-list {
     --inner-padding-bottom: 8px;
   }
 }
+.examtest-modal {
+  .modal-wrapper {
+    height: 60% !important;
+    border-radius: 8px;
+    position: absolute;
+    bottom: 0;
+    left: 0;
+  }
+}

+ 2 - 0
parth5/parth5/src/app/views/pages/examtest/examtest.component.ts

@@ -179,6 +179,8 @@ export class ExamtestComponent implements OnInit {
       typeList: quesTypeIdList,
       questionnumber: this.questionnumber
     }));
+    localStorage.setItem("questionTypeList",JSON.stringify(this.questionTypeList));
+
     this.router.navigate(['show'], {
       relativeTo: this.routeInfo,
       queryParams: {id: 'id', random: Math.random()}

+ 32 - 0
parth5/parth5/src/app/views/pages/examtest/show/card/card.component.html

@@ -0,0 +1,32 @@
+<ion-header color="danger" style="text-align: center">
+  共{{ doneQuestionNumber + unNumber }}道题
+</ion-header>
+<ion-content>
+  <ion-list>
+    <div class="card-body">
+      <div class="card-total">
+        <div>
+          <ion-icon name="ellipse-outline" style="color: deepskyblue;vertical-align: middle;"></ion-icon>
+          正确{{ rightNumber }}道
+        </div>
+        <div>
+          <ion-icon name="ellipse-outline" style="color: red;vertical-align: middle;"></ion-icon>
+          错误{{ errNumber }}道
+        </div>
+        <div>
+          <ion-icon name="ellipse-outline" style="color: lightgrey;vertical-align: middle;"></ion-icon>
+          未做{{ unNumber }}道
+        </div>
+      </div>
+      <div *ngFor="let it of previewList">
+        <h5> {{ it.name }}_共{{ it.questionNum }}题({{ it.score }}分)</h5>
+        <div class="question-num">
+          <div *ngFor="let ques of it.question"
+               (click)="selectQuestion(ques)"
+               [ngClass]="{'rightColor':ques.isRight,'unColor':ques.isRight==null,'errColor':ques.isRight==false}">
+            {{ ques.order }}</div>
+        </div>
+      </div>
+    </div>
+  </ion-list>
+</ion-content>

+ 42 - 0
parth5/parth5/src/app/views/pages/examtest/show/card/card.component.scss

@@ -0,0 +1,42 @@
+.card-body{
+  margin: 10px;
+}
+.card-total{
+  display: flex;
+  flex-wrap: nowrap;
+
+  div{
+    margin-right: 10px;
+  }
+  span{
+    width: 10px;
+    height: 10px;
+    border: 1px solid #1f91f3;
+  }
+}
+.question-num {
+  display: flex;
+
+  div{
+    width: 25px;
+    height: 25px;
+    border: 2px solid rebeccapurple;
+    border-radius: 15px;
+    text-align: center;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    margin-right: 5px;
+    font-size: 12px;
+    font-weight: bold;
+  }
+}
+.rightColor{
+  border: 2px solid deepskyblue !important;
+}
+.unColor{
+  border: 2px solid lightgrey !important;
+}
+.errColor{
+  border: 2px solid red !important;
+}

+ 106 - 0
parth5/parth5/src/app/views/pages/examtest/show/card/card.component.ts

@@ -0,0 +1,106 @@
+import {Component, Input, OnInit} from '@angular/core';
+import {ModalController} from "@ionic/angular";
+import {ConfigService, RequsetData} from "../../../../../service/config.service";
+
+@Component({
+  selector: 'app-card',
+  templateUrl: './card.component.html',
+  styleUrls: ['./card.component.scss'],
+})
+export class CardComponent implements OnInit {
+
+  @Input()
+  testQuestionList = [];
+  rightNumber = 0;
+  doneQuestionNumber = 0;
+  unNumber = 0;
+  errNumber = 0;
+  questionTypeList: any = [];
+  previewList = [];
+
+  constructor(private configService: ConfigService, public modalController: ModalController) {
+  }
+
+  ngOnInit() {
+    this.autoReaderPaper().then(() => {
+      this.getDoneNum();
+      this.unNumber = this.testQuestionList.length - this.doneQuestionNumber;
+      this.errNumber = this.testQuestionList.length - this.unNumber - this.rightNumber;
+
+      this.getQuestionTypeList().then(()=>{
+        this.questionTypeList = this.questionTypeList.sort((a, b) => a.diplayOrder - b.diplayOrder);
+        this.parseQuestion();
+      })
+    })
+  }
+
+  //按题型分类试题
+  parseQuestion() {
+    this.previewList = [];
+    this.questionTypeList.forEach((type)=> {
+      var typequestion = this.testQuestionList.filter(function (pquestion) {
+        return pquestion.BASE_QUESTION_TYPE_ID == type.baseQuestionTypeId;
+      })
+      if (typequestion.length > 0) {
+        var previewItem = type;
+        var typescore = 0;
+        typequestion.forEach(function (tquestion) {
+          typescore += tquestion.SCORE;
+        })
+        previewItem.score = typescore;//题型总分
+        previewItem.questionNum = typequestion.length;
+        previewItem.question = typequestion;
+        this.previewList.push(previewItem);
+      }
+    })
+  }
+
+  //阅卷
+  autoReaderPaper() {
+    let pm = new Promise((resolve, reject) => {
+      this.configService.HttpPostRomote('/api/examtest/autoReaderPaper', {userQuestionList: this.testQuestionList,}).subscribe((data: RequsetData) => {
+        if (data.success) {
+          this.testQuestionList = data.item;
+          this.rightNumber = data.item.filter(function (x) {
+            return x.isRight;
+          }).length;
+        }
+        resolve();
+      });
+    });
+    return pm;
+  }
+
+  getDoneNum() {
+    this.doneQuestionNumber = this.testQuestionList.filter(function (ques) {
+      return (ques.useranswer != null && ques.useranswer != "") || ques.ANSWERS.filter(function (ans) {
+        return ans.useranswer != null && ans.useranswer != ""
+      }).length > 0;
+    }).length;
+  }
+
+  getQuestionTypeList() {
+    let pm = new Promise((resolve, reject) => {
+      const lsQuestionTypeList = localStorage.getItem('questionTypeList');
+      if (lsQuestionTypeList) {
+        this.questionTypeList = JSON.parse(lsQuestionTypeList);
+        resolve();
+        return;
+      }
+      this.configService.HttpGetRomote('/api/exammanage/questiontypeSetting/getList', {}).subscribe((data: RequsetData) => {
+        if (data.success) {
+          this.questionTypeList = data.item;
+          localStorage.setItem('questionTypeList', JSON.stringify(this.questionTypeList));
+        }
+        resolve();
+      });
+    });
+    return pm;
+  }
+  selectQuestion(ques){
+    this.modalController.dismiss({
+      'dismissed': true,
+      'order': ques.order
+    });
+  }
+}

+ 16 - 64
parth5/parth5/src/app/views/pages/examtest/show/show.component.html

@@ -8,18 +8,18 @@
 </ion-header>
 <ion-content>
   <ion-list>
-    <div class="question-body" *ngFor="let ques of testQuestionList;let i = index">
+    <div class="question-body" *ngFor="let ques of curQuestionList;let i = index">
 
       <div [ngSwitch]="ques.NAME">
         <div *ngSwitchCase="'单选题'">
-          <span class="ion-text-wrap">{{ i + 1 }}.({{ ques.NAME }}){{ ques.CONTENT }}</span>
+          <span class="ion-text-wrap">{{ ques.order }}.({{ ques.NAME }}){{ ques.CONTENT }}</span>
           <div style="width: 100%;text-align: right;color:red;" (click)="ques.showAnswer=true">
             <ion-icon name="checkbox-outline" size="large"></ion-icon>
           </div>
           <div [class]="{'isright-answer':ans.ISRIGHT&&ques.showAnswer}"
                *ngFor="let ans of ques.ANSWERS;let $index = index">
             <input name="rd_p_{{ques.row_num}}_{{$index}}" type="radio" [(ngModel)]="ques.useranswer"
-                   value="{{ans.PROVID_ANSWER_ID}}"
+                   value="{{ans.PROVID_ANSWER_ID}}" (ngModelChange)="answer(ques)"
                    class="with-gap" id="rd_p_{{ques.row_num}}_{{$index}}"/>
             <label for="rd_p_{{ques.row_num}}_{{$index}}">{{ options($index) }}、{{ ans.ANSWER_NAME }}</label>
             <span class="isright-answer" *ngIf="ans.ISRIGHT&&ques.showAnswer">✔</span>
@@ -30,21 +30,21 @@
             <ion-icon name="checkbox-outline" size="large"></ion-icon>
           </div>
           <div class="input-container">
-            {{ i + 1 }}.({{ ques.NAME }})
+            {{ ques.order }}.({{ ques.NAME }})
             <ng-container *ngFor="let word of ques.CONTENT.split('___'); let j = index">
               {{ word }}
               <!-- 如果当前是句子中的最后一个词前的下划线,则不添加输入框 -->
               <ng-container *ngIf="j < ques.CONTENT.split('___').length - 1">
-                <ion-input [(ngModel)]="ques.ANSWERS[j].useranswer" placeholder="请输入"></ion-input>
+                <ion-input [(ngModel)]="ques.ANSWERS[j].useranswer" placeholder="请输入" (ngModelChange)="answer(ques)"></ion-input>
               </ng-container>
             </ng-container>
           </div>
         </div>
         <div *ngSwitchCase="'判断题'">
-          <span class="ion-text-wrap">{{ i + 1 }}.({{ ques.NAME }}){{ ques.CONTENT }}</span>
+          <span class="ion-text-wrap">{{ ques.order}}.({{ ques.NAME }}){{ ques.CONTENT }}</span>
           <div [class]="{'isright-answer':ans.ISRIGHT&&ques.showAnswer}"
                *ngFor="let ans of ques.ANSWERS;let $index = index">
-            <input name="rd_p_{{ques.row_num}}_{{$index}}" type="radio" [(ngModel)]="ques.useranswer"
+            <input name="rd_p_{{ques.row_num}}_{{$index}}" type="radio" [(ngModel)]="ques.useranswer" (ngModelChange)="answer(ques)"
                    value="{{ans.PROVID_ANSWER_ID}}"
                    class="with-gap" id="rd_p_{{ques.row_num}}_{{$index}}"/>
             <label for="rd_p_{{ques.row_num}}_{{$index}}">{{ options($index) }}、{{ ans.ANSWER_NAME }}</label>
@@ -52,21 +52,21 @@
           </div>
         </div>
         <div *ngSwitchCase="'简答题'">
-          <span class="ion-text-wrap">{{ i + 1 }}.({{ ques.NAME }}){{ ques.CONTENT }}</span>
+          <span class="ion-text-wrap">{{ ques.order }}.({{ ques.NAME }}){{ ques.CONTENT }}</span>
           <div [class]="{'isright-answer':ans.ISRIGHT&&ques.showAnswer}"
                *ngFor="let ans of ques.ANSWERS;let $index = index">
-            <ion-textarea readonly="false" placeholder="请填写" name="remark"
+            <ion-textarea readonly="false" placeholder="请填写" name="remark" (ngModelChange)="answer(ques)"
                           [(ngModel)]="ans.useranswer"></ion-textarea>
           </div>
         </div>
         <div *ngSwitchCase="'多选题'">
-          <span class="ion-text-wrap">{{ i + 1 }}.({{ ques.NAME }}){{ ques.CONTENT }}</span>
+          <span class="ion-text-wrap">{{ ques.order }}.({{ ques.NAME }}){{ ques.CONTENT }}</span>
           <div style="width: 100%;text-align: right;color:red;" (click)="ques.showAnswer=true">
             <ion-icon name="checkbox-outline" size="large"></ion-icon>
           </div>
           <div [class]="{'isright-answer':ans.ISRIGHT&&ques.showAnswer}"
                *ngFor="let ans of ques.ANSWERS;let $index = index">
-            <input name="ckb_{{ques.row_num}}_{{$index}}" type="checkbox" [(ngModel)]="ans.useranswer"
+            <input name="ckb_{{ques.row_num}}_{{$index}}" type="checkbox" [(ngModel)]="ans.useranswer" (ngModelChange)="answer(ques)"
                    value="{{ans.PROVID_ANSWER_ID}}"
                    class="with-gap" id="ckb_{{ques.row_num}}_{{$index}}"/>
             <label for="ckb_{{ques.row_num}}_{{$index}}">{{ options($index) }}、{{ ans.ANSWER_NAME }}</label>
@@ -78,66 +78,18 @@
       <div class="isright-answer" *ngIf="ques.showAnswer">题目解析<br/>{{ ques.NOTE }}</div>
     </div>
   </ion-list>
-  <ion-button id="open-modal">Open Modal</ion-button>
-
-  <ion-modal #modal trigger="open-modal" >
-    <ng-template>
-      <ion-content>
-        <ion-searchbar placeholder="Search" ></ion-searchbar>
-        <ion-list>
-          <ion-item>
-            <ion-avatar slot="start">
-              <ion-img src="https://i.pravatar.cc/300?u=b"></ion-img>
-            </ion-avatar>
-            <ion-label>
-              <h2>Connor Smith</h2>
-              <p>Sales Rep</p>
-            </ion-label>
-          </ion-item>
-          <ion-item>
-            <ion-avatar slot="start">
-              <ion-img src="https://i.pravatar.cc/300?u=a"></ion-img>
-            </ion-avatar>
-            <ion-label>
-              <h2>Daniel Smith</h2>
-              <p>Product Designer</p>
-            </ion-label>
-          </ion-item>
-          <ion-item>
-            <ion-avatar slot="start">
-              <ion-img src="https://i.pravatar.cc/300?u=d"></ion-img>
-            </ion-avatar>
-            <ion-label>
-              <h2>Greg Smith</h2>
-              <p>Director of Operations</p>
-            </ion-label>
-          </ion-item>
-          <ion-item>
-            <ion-avatar slot="start">
-              <ion-img src="https://i.pravatar.cc/300?u=e"></ion-img>
-            </ion-avatar>
-            <ion-label>
-              <h2>Zoey Smith</h2>
-              <p>CEO</p>
-            </ion-label>
-          </ion-item>
-        </ion-list>
-      </ion-content>
-    </ng-template>
-  </ion-modal>
 </ion-content>
 <ion-footer>
   <ion-toolbar style="display: flex;align-items: center">
-    <ion-icon name="reorder-four-outline" style="color: red;vertical-align: middle;" size="large"
+    <ion-icon (click)="presentModal()" name="reorder-four-outline" style="color: red;vertical-align: middle;"
+              size="large"
               aria-label="Favorite"></ion-icon>
-    <span>已答4/100</span>
-    <ion-button size="small" slot="end">
-      <ion-icon slot="start" name="star"></ion-icon>
+    <span>已答{{ answerCount }}/{{ questionCount }}</span>
+    <ion-button size="small" slot="end" *ngIf="order>1" (click)="order=order-1;changeView();">
       上一题
     </ion-button>
-    <ion-button size="small" slot="end">
+    <ion-button size="small" slot="end" *ngIf="questionCount>order" (click)="order=order+1;changeView();">
       下一题
-      <ion-icon slot="end" name="heart"></ion-icon>
     </ion-button>
   </ion-toolbar>
 </ion-footer>

+ 4 - 2
parth5/parth5/src/app/views/pages/examtest/show/show.component.scss

@@ -1,13 +1,15 @@
 .isright-answer {
   color: #00A8FF;
 }
-.question-body{
+
+.question-body {
   margin: 10px;
 }
+
 .question-body ion-input {
   width: 100px;
   display: inline-block;
-  border-bottom:1px solid rgb(118, 118, 118) ;
+  border-bottom: 1px solid rgb(118, 118, 118);
 }
 
 .input-container {

+ 48 - 24
parth5/parth5/src/app/views/pages/examtest/show/show.component.ts

@@ -1,7 +1,8 @@
-import {Component, ViewChild ,OnInit} from '@angular/core';
+import {Component, ViewChild, OnInit} from '@angular/core';
 import {ConfigService, RequsetData} from "../../../../service/config.service";
-import {AlertController,ModalController, MenuController} from "@ionic/angular";
+import {AlertController, ModalController, MenuController} from "@ionic/angular";
 import {ActivatedRoute, Router} from "@angular/router";
+import {CardComponent} from "./card/card.component";
 
 @Component({
   selector: 'app-show',
@@ -13,8 +14,13 @@ export class ShowComponent implements OnInit {
 
   testQuestionList = [];
   testSettings = {};
+  order = 1;
+  curQuestionList = [];
+  questionCount = 0;
+  answerCount = 0;
 
-  constructor(private modalController: ModalController,public alertController: AlertController, private menu: MenuController, private router: Router, private configService: ConfigService, private routeInfo: ActivatedRoute) {
+
+  constructor(private modalController: ModalController, public alertController: AlertController, private menu: MenuController, private router: Router, private configService: ConfigService, private routeInfo: ActivatedRoute) {
   }
 
   ngOnInit() {
@@ -22,48 +28,66 @@ export class ShowComponent implements OnInit {
     if (testSettings) {
       this.testSettings = JSON.parse(testSettings);
     }
-    this.getPracticeQuestions(this.testSettings );
+    this.getPracticeQuestions(this.testSettings);
   }
 
   getPracticeQuestions(data) {
     this.configService.HttpPostRomote(this.getPracticeQuestionsUrl, data).subscribe((data: RequsetData) => {
       if (data.success) {
         this.testQuestionList = data.item;
-        this.testQuestionList.forEach(x=>{
-          x.ANSWERS=this.sort(x.ANSWERS);
+        this.testQuestionList.forEach((x, index) => {
+          x.ANSWERS = this.sort(x.ANSWERS);
+          x.order = index + 1;
         })
+        this.questionCount = this.testQuestionList.length;
+        this.changeView();
       }
     });
   }
-  parseAnswer(answers:any[], questionType:string) {
+
+  parseAnswer(answers: any[], questionType: string) {
     answers = answers.filter(function (x) {
       return x.ISRIGHT
     });
-    var rightAnswers = answers.map(x=> {
-      return questionType == '判断题' ||questionType == '填空题'? x.ANSWER_NAME : this.options(x.ORDER - 1);
+    var rightAnswers = answers.map(x => {
+      return questionType == '判断题' || questionType == '填空题' ? x.ANSWER_NAME : this.options(x.ORDER - 1);
     });
     return rightAnswers.join("、");
   }
+
   options(index) {
     return String.fromCharCode(65 + index);
   }
-  sort(answers:any[]){
-    return  answers.sort((a, b) => a.ORDER - b.ORDER);
+
+  sort(answers: any[]) {
+    return answers.sort((a, b) => a.ORDER - b.ORDER);
   }
-  @ViewChild('myModal') modal: any;
-  async openModal() {
-    const modalElement = await this.modalController.create({
-      component: this.modal, // 注意:这里通常不是直接传递modal元素,而是传递一个组件
-      // 如果你的modal是一个组件,应该这样:
-      // component: SomeModalComponent,
-      // 如果是使用模板引用的modal,你可能需要另寻他法,因为通常我们不这样用
-      // 下面展示的是如果modal是一个组件的情况
-      cssClass: 'my-custom-class',
-      showBackdrop: true,
-      swipeToClose: true,
-      keyboardClose: true
+
+  changeView() {
+    this.curQuestionList = this.testQuestionList.filter(x => x.order == this.order);
+  }
+
+  answer(ques) {
+    ques.isAnswer = true;
+    this.answerCount = this.testQuestionList.filter(x => x.isAnswer).length;
+  }
+
+  async presentModal() {
+
+    const modal = await this.modalController.create({
+      component: CardComponent,
+      cssClass: 'examtest-modal',
+      componentProps: {
+        'testQuestionList': this.testQuestionList
+      }
     });
+    await modal.present();
+
+    const {data} = await modal.onWillDismiss();
 
-    return await modalElement.present();
+    if (data.dismissed) {
+      this.order = data.order;
+      this.changeView();
+    }
   }
 }

+ 3 - 1
parth5/parth5/src/app/views/tapp/tabs/tabs.module.ts

@@ -57,6 +57,7 @@ import {UserselectPage} from "../../../comm/modal/userselect/userselect.page";
 import {routes as MainRoutes} from "../tab-main/tab-main.route";
 import {routes as StudyRoutes} from "../tab-study/tab-study.route";
 import {routes as UserRoutes} from "../tab-user/tab-user.route";
+import {CardComponent} from "../../pages/examtest/show/card/card.component";
 
 import { ExamtestComponent} from "../../pages/examtest/examtest.component";
 import {ShowComponent as ExamtestShowComponent} from "../../pages/examtest/show/show.component";
@@ -88,7 +89,8 @@ const pageComponents = [
   RecordComponent,
   PartyUserRewardComponent,
   ExamtestComponent,
-  ExamtestShowComponent
+  ExamtestShowComponent,
+  CardComponent
 ];
 
 const pubComponents = [

+ 19 - 6
src/main/java/com/ghsc/partybuild/controller/exammanage/ExamTestController.java

@@ -10,8 +10,11 @@ import org.springframework.web.bind.annotation.*;
 
 import java.time.LocalDate;
 import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 @RestController
 @RequestMapping(value = "/api/examtest")
@@ -56,22 +59,32 @@ public class ExamTestController {
                 case 1://单选题
                 case 4://判断题
                     String useranswer = (String) ques.get("useranswer");
+                    if (useranswer == null) {
+                        break;
+                    }
                     isRight = answers.stream().filter(ans -> {
                         return ans.get("ISRIGHT").equals(1) && ans.get("PROVID_ANSWER_ID").equals(useranswer);
                     }).count() > 0;
+                    ques.put("isRight", isRight);
                     break;
                 case 3://多选题
-                    isRight = answers.stream().filter(ans -> {
-                        return ans.get("ISRIGHT").equals(1);
-                    }).allMatch(ans -> {
-                        return ans.get("useranswer") != null && (boolean) ans.get("useranswer");
-                    });
+                    long useranswerNum = answers.stream().filter(ans -> ans.get("useranswer") != null).count();
+                    if (useranswerNum == 0) {
+                        break;
+                    }
+                    String rightNum = answers.stream().filter(ans ->
+                            ans.get("ISRIGHT").equals(1)
+                    ).map(x -> x.get("ORDER").toString()).collect(Collectors.joining(","));
+                    String userRightNum = answers.stream().filter(ans ->
+                            ans.get("useranswer") != null && (boolean) ans.get("useranswer")
+                    ).map(x -> x.get("ORDER").toString()).collect(Collectors.joining(","));
+                    isRight = rightNum.equals(userRightNum);
+                    ques.put("isRight", isRight);
                     break;
                 case 2://填空题
                 case 5://简答题
                     break;
             }
-            ques.put("isRight", isRight);
         }
     }