Browse Source

Merge remote-tracking branch 'origin/master'

lizeyu 4 months ago
parent
commit
cb8797374b
27 changed files with 1899 additions and 251 deletions
  1. 6 0
      lib/数据更新脚本.txt
  2. 5 0
      lib/考试模块菜单.txt
  3. 1002 236
      parth5/parth5/package-lock.json
  4. 1 1
      parth5/parth5/package.json
  5. 7 0
      parth5/parth5/src/app/app.scss
  6. 4 1
      parth5/parth5/src/app/routes/exam.ts
  7. 10 7
      parth5/parth5/src/app/views/login/login.module.ts
  8. 51 0
      parth5/parth5/src/app/views/pages/examonline/examonline.component.html
  9. 0 0
      parth5/parth5/src/app/views/pages/examonline/examonline.component.scss
  10. 69 0
      parth5/parth5/src/app/views/pages/examonline/examonline.component.ts
  11. 32 0
      parth5/parth5/src/app/views/pages/examonline/showpaper/card/card.component.html
  12. 46 0
      parth5/parth5/src/app/views/pages/examonline/showpaper/card/card.component.scss
  13. 31 0
      parth5/parth5/src/app/views/pages/examonline/showpaper/card/card.component.ts
  14. 20 0
      parth5/parth5/src/app/views/pages/examonline/showpaper/result/result.component.html
  15. 15 0
      parth5/parth5/src/app/views/pages/examonline/showpaper/result/result.component.scss
  16. 24 0
      parth5/parth5/src/app/views/pages/examonline/showpaper/result/result.component.ts
  17. 125 0
      parth5/parth5/src/app/views/pages/examonline/showpaper/showpaper.component.html
  18. 96 0
      parth5/parth5/src/app/views/pages/examonline/showpaper/showpaper.component.scss
  19. 331 0
      parth5/parth5/src/app/views/pages/examonline/showpaper/showpaper.component.ts
  20. 1 1
      parth5/parth5/src/app/views/pages/examtest/show/card/card.component.html
  21. 3 0
      parth5/parth5/src/app/views/pages/examtest/show/card/card.component.scss
  22. 2 2
      parth5/parth5/src/app/views/pages/examtest/show/show.component.html
  23. 5 2
      parth5/parth5/src/app/views/pages/examtest/show/show.component.scss
  24. 6 0
      parth5/parth5/src/app/views/tapp/tab-main/tab-main.page.html
  25. 7 1
      parth5/parth5/src/app/views/tapp/tabs/tabs.module.ts
  26. BIN
      parth5/parth5/src/assets/icon/test-question.png
  27. BIN
      parth5/parth5/src/assets/icon/test-wait.png

+ 6 - 0
lib/数据更新脚本.txt

@@ -188,6 +188,12 @@ INSERT INTO `cf_menu` (`MENUID`, `APPLICATIONID`, `PARENTMENUID`, `MNUSYSTEM`, `
 INSERT INTO `cf_dictionary` (`DICTIONARYID`, `DICKEY`, `DICVALUE`, `DICTYPEKEY`, `DICTYPE`, `APPLICATIONID`, `DICNOTE`, `OPERATETIME`, `OPERATESTATE`, `SYNCSTATE`) VALUES ('058a7fc0-0000-0001-9999-bdb74a278a72', 1, '媒体报道', 'fcType', 2, 'f0c4fa7f9f3c4fb6bd56aac608b7ad3f', '风采类型', '2019-09-26 15:13:15', 'M', 'N');
 INSERT INTO `cf_dictionary` (`DICTIONARYID`, `DICKEY`, `DICVALUE`, `DICTYPEKEY`, `DICTYPE`, `APPLICATIONID`, `DICNOTE`, `OPERATETIME`, `OPERATESTATE`, `SYNCSTATE`) VALUES ('058a7fc0-0000-0002-9999-bdb74a278a72', 2, '其他', 'fcType', 2, 'f0c4fa7f9f3c4fb6bd56aac608b7ad3f', '风采类型', '2019-09-26 15:13:15', 'M', 'N');
 
+---7.18
+INSERT INTO CF_DICTIONARY (DICTIONARYID, DICKEY, DICVALUE, DICTYPEKEY, DICTYPE, APPLICATIONID, DICNOTE, OPERATETIME, OPERATESTATE, SYNCSTATE) VALUES ('3e8addee-6666-4c46-94d8-111138164863', 1, '待考试', 'testmanRecordStauts', 1, 'f0c4fa7f9f3c4fb6bd56aac608b7ad3f', null, TIMESTAMP '2022-04-20 16:51:33', 'A', 'N');
+INSERT INTO CF_DICTIONARY (DICTIONARYID, DICKEY, DICVALUE, DICTYPEKEY, DICTYPE, APPLICATIONID, DICNOTE, OPERATETIME, OPERATESTATE, SYNCSTATE) VALUES ('855867d0-7777-4710-90fd-222e6bb77993', 2, '考试中', 'testmanRecordStauts', 1, 'f0c4fa7f9f3c4fb6bd56aac608b7ad3f', null, TIMESTAMP '2022-04-20 16:51:33', 'A', 'N');
+INSERT INTO CF_DICTIONARY (DICTIONARYID, DICKEY, DICVALUE, DICTYPEKEY, DICTYPE, APPLICATIONID, DICNOTE, OPERATETIME, OPERATESTATE, SYNCSTATE) VALUES ('855867d0-8888-4710-90fd-222e6bb77993', 3, '已交卷', 'testmanRecordStauts', 1, 'f0c4fa7f9f3c4fb6bd56aac608b7ad3f', null, TIMESTAMP '2022-04-20 16:51:33', 'A', 'N');
+INSERT INTO CF_DICTIONARY (DICTIONARYID, DICKEY, DICVALUE, DICTYPEKEY, DICTYPE, APPLICATIONID, DICNOTE, OPERATETIME, OPERATESTATE, SYNCSTATE) VALUES ('855867d0-9999-4710-90fd-333e6bb77993', 4, '缺考', 'testmanRecordStauts', 1, 'f0c4fa7f9f3c4fb6bd56aac608b7ad3f', null, TIMESTAMP '2022-04-20 16:51:33', 'A', 'N');
+INSERT INTO CF_DICTIONARY (DICTIONARYID, DICKEY, DICVALUE, DICTYPEKEY, DICTYPE, APPLICATIONID, DICNOTE, OPERATETIME, OPERATESTATE, SYNCSTATE) VALUES ('855867d0-0000-4710-90fd-333e6bb77993', 5, '已公布成绩', 'testmanRecordStauts', 1, 'f0c4fa7f9f3c4fb6bd56aac608b7ad3f', null, TIMESTAMP '2022-04-20 16:51:33', 'A', 'N');
 
 -- 2024.7.19
 alter table cf_users add wxUserId varchar(50);

+ 5 - 0
lib/考试模块菜单.txt

@@ -76,3 +76,8 @@ INSERT INTO CF_DICTIONARY (DICTIONARYID, DICKEY, DICVALUE, DICTYPEKEY, DICTYPE,
 INSERT INTO CF_DICTIONARY (DICTIONARYID, DICKEY, DICVALUE, DICTYPEKEY, DICTYPE, APPLICATIONID, DICNOTE, OPERATETIME, OPERATESTATE, SYNCSTATE) VALUES ('627DF6C0D5634617845214C926CE81C8', 3, '新任组织助理员', 'PaperBasetype', 2, 'f0c4fa7f9f3c4fb6bd56aac608b7ad3f', null, date('2023-01-06 16:13:09'), 'A', 'Y');
 INSERT INTO CF_DICTIONARY (DICTIONARYID, DICKEY, DICVALUE, DICTYPEKEY, DICTYPE, APPLICATIONID, DICNOTE, OPERATETIME, OPERATESTATE, SYNCSTATE) VALUES ('A20C95A703B846E5B23563BDA9651229', 4, '新任宣传助理员', 'PaperBasetype', 2, 'f0c4fa7f9f3c4fb6bd56aac608b7ad3f', null, date('2023-01-06 16:13:09'), 'A', 'Y');
 
+INSERT INTO CF_DICTIONARY (DICTIONARYID, DICKEY, DICVALUE, DICTYPEKEY, DICTYPE, APPLICATIONID, DICNOTE, OPERATETIME, OPERATESTATE, SYNCSTATE) VALUES ('3e8addee-6666-4c46-94d8-111138164863', 1, '待考试', 'testmanRecordStauts', 1, 'f0c4fa7f9f3c4fb6bd56aac608b7ad3f', null, TIMESTAMP '2022-04-20 16:51:33', 'A', 'N');
+INSERT INTO CF_DICTIONARY (DICTIONARYID, DICKEY, DICVALUE, DICTYPEKEY, DICTYPE, APPLICATIONID, DICNOTE, OPERATETIME, OPERATESTATE, SYNCSTATE) VALUES ('855867d0-7777-4710-90fd-222e6bb77993', 2, '考试中', 'testmanRecordStauts', 1, 'f0c4fa7f9f3c4fb6bd56aac608b7ad3f', null, TIMESTAMP '2022-04-20 16:51:33', 'A', 'N');
+INSERT INTO CF_DICTIONARY (DICTIONARYID, DICKEY, DICVALUE, DICTYPEKEY, DICTYPE, APPLICATIONID, DICNOTE, OPERATETIME, OPERATESTATE, SYNCSTATE) VALUES ('855867d0-8888-4710-90fd-222e6bb77993', 3, '已交卷', 'testmanRecordStauts', 1, 'f0c4fa7f9f3c4fb6bd56aac608b7ad3f', null, TIMESTAMP '2022-04-20 16:51:33', 'A', 'N');
+INSERT INTO CF_DICTIONARY (DICTIONARYID, DICKEY, DICVALUE, DICTYPEKEY, DICTYPE, APPLICATIONID, DICNOTE, OPERATETIME, OPERATESTATE, SYNCSTATE) VALUES ('855867d0-9999-4710-90fd-333e6bb77993', 4, '缺考', 'testmanRecordStauts', 1, 'f0c4fa7f9f3c4fb6bd56aac608b7ad3f', null, TIMESTAMP '2022-04-20 16:51:33', 'A', 'N');
+INSERT INTO CF_DICTIONARY (DICTIONARYID, DICKEY, DICVALUE, DICTYPEKEY, DICTYPE, APPLICATIONID, DICNOTE, OPERATETIME, OPERATESTATE, SYNCSTATE) VALUES ('855867d0-0000-4710-90fd-333e6bb77993', 5, '已公布成绩', 'testmanRecordStauts', 1, 'f0c4fa7f9f3c4fb6bd56aac608b7ad3f', null, TIMESTAMP '2022-04-20 16:51:33', 'A', 'N');

File diff suppressed because it is too large
+ 1002 - 236
parth5/parth5/package-lock.json


+ 1 - 1
parth5/parth5/package.json

@@ -31,7 +31,7 @@
     "crypto-js": "^4.0.0",
     "echarts": "^5.1.2",
     "eventemitter3": "^4.0.7",
-    "moment": "^2.29.1",
+    "moment": "^2.30.1",
     "ng2-pdf-viewer": "^5.1.3",
     "ngx-order-pipe": "^2.1.1",
     "ngx-pinch-zoom": "^2.5.5",

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

@@ -531,3 +531,10 @@ ion-list {
     border-radius: 8px;
   }
 }
+.onlineresult-modal {
+  .modal-wrapper {
+    height: 38% !important;
+    width: 80% !important;
+    border-radius: 8px;
+  }
+}

+ 4 - 1
parth5/parth5/src/app/routes/exam.ts

@@ -1,10 +1,13 @@
 import {Routes} from "@angular/router";
 import {ExamtestComponent} from "../views/pages/examtest/examtest.component";
 import {ShowComponent} from "../views/pages/examtest/show/show.component";
-
+import {ExamonlineComponent} from "../views/pages/examonline/examonline.component";
+import {ShowpaperComponent} from "../views/pages/examonline/showpaper/showpaper.component";
 const routes: Routes = [
   {path: 'exam/examtest', component: ExamtestComponent},
   {path: 'exam/examtest/show', component: ShowComponent},
+  {path: 'exam/examonline', component: ExamonlineComponent},
+  {path: 'exam/examonline/showpaper', component: ShowpaperComponent},
 ];
 
 export default routes;

+ 10 - 7
parth5/parth5/src/app/views/login/login.module.ts

@@ -16,12 +16,15 @@ const routes: Routes = [
 ];
 
 @NgModule({
-  imports: [
-    CommonModule,
-    FormsModule,
-    IonicModule,
-    RouterModule.forChild(routes)
-  ],
-  declarations: [LoginPage,ClickLogDirective]
+    imports: [
+        CommonModule,
+        FormsModule,
+        IonicModule,
+        RouterModule.forChild(routes)
+    ],
+    exports: [
+        ClickLogDirective
+    ],
+    declarations: [LoginPage, ClickLogDirective]
 })
 export class LoginPageModule {}

+ 51 - 0
parth5/parth5/src/app/views/pages/examonline/examonline.component.html

@@ -0,0 +1,51 @@
+<ion-header class="header-theme2" id="main-content">
+  <ion-toolbar>
+    <ion-label class="title-center">我的考试</ion-label>
+    <ion-buttons slot="start">
+      <ion-back-button icon="ios-back2" text="" mode="md"></ion-back-button>
+    </ion-buttons>
+  </ion-toolbar>
+</ion-header>
+<ion-content>
+  <ion-list>
+    <ng-container *ngFor="let item of dataList">
+      <ion-item class="border-item">
+        <ion-label text-wrap>
+          <ion-row>
+            <ion-col>
+             <h2> {{ item.testName }}</h2>
+            </ion-col>
+          </ion-row>
+          <ion-row>
+            <ion-col>
+              开始时间:{{ item.testBeginDate | date:'yyyy-MM-dd HH:mm' }}
+            </ion-col>
+          </ion-row>
+          <ion-row>
+            <ion-col>
+              结束时间:{{ item.testEndDate | date:'yyyy-MM-dd HH:mm' }}
+            </ion-col>
+          </ion-row>
+          <ion-row>
+            <ion-col>
+              考试时长:{{ item.limitedMinutes }}分钟
+            </ion-col>
+          </ion-row>
+          <ion-row>
+            <ion-col size="8">
+              100分
+            </ion-col>
+            <ion-col>
+              {{ item.manStatusName }}
+            </ion-col>
+          </ion-row>
+          <ion-row *ngIf="item.manStatus<3">
+            <ion-col style="text-align: center">
+              <ion-button size="small" (click)="toExamTest(item.onlinetestId)">进入考试</ion-button>
+            </ion-col>
+          </ion-row>
+        </ion-label>
+      </ion-item>
+    </ng-container>
+  </ion-list>
+</ion-content>

+ 0 - 0
parth5/parth5/src/app/views/pages/examonline/examonline.component.scss


+ 69 - 0
parth5/parth5/src/app/views/pages/examonline/examonline.component.ts

@@ -0,0 +1,69 @@
+import {Component, OnInit} from '@angular/core';
+import {ConfigService, RequsetData} from "../../../service/config.service";
+import {AlertController, MenuController} from "@ionic/angular";
+import {ActivatedRoute, Router} from "@angular/router";
+import * as moment from 'moment';
+
+@Component({
+  selector: 'app-examonline',
+  templateUrl: './examonline.component.html',
+  styleUrls: ['./examonline.component.scss'],
+})
+export class ExamonlineComponent implements OnInit {
+
+  dataList = [];
+
+  constructor(public alertController: AlertController, private menu: MenuController, private router: Router, private configService: ConfigService, private routeInfo: ActivatedRoute) {
+  }
+
+  ngOnInit() {
+    this.loadData();
+  }
+
+  loadData() {
+    this.configService.HttpGetRomote('/api/exammanage/plan/getMyExamPlanList', {
+      pageindex: 1,
+      pagesize: 100
+    }).subscribe((data: RequsetData) => {
+      if (data.success) {
+        this.dataList = data.item.list;
+      }
+    });
+  }
+  toExamTest(id){
+    this.configService.HttpGetRomote('/api/exammanage/plan/getMyExamPlan', {
+      testId: id
+    }).subscribe((data: RequsetData) => {
+      var myexam = data.item;
+      if (myexam != null) {
+        if (myexam.manStatus > 2) {
+          this.presentAlert('开始时间必须小于结束时间');
+          return;
+        }
+        if (moment().isAfter(myexam.testEndDate)) {
+          this.presentAlert('考试时间已过,不允许进入');
+          return;
+        }
+        //只能进入当天考试
+        if(moment().isBefore(myexam.testBeginDate)&&Math.abs(moment().diff(myexam.testBeginDate,'days'))!=0){
+          this.presentAlert('考试时间未到,不允许进入');
+          return;
+        }
+        this.router.navigate(['showpaper'], {
+          relativeTo: this.routeInfo,
+          queryParams: {id: id, random: Math.random()}
+        });
+      }
+    });
+  }
+  async presentAlert(msg: string) {
+    const alert = await this.alertController.create({
+      header: '提示',
+      subHeader: '',
+      message: msg,
+      buttons: ['确定']
+    });
+
+    await alert.present();
+  }
+}

+ 32 - 0
parth5/parth5/src/app/views/pages/examonline/showpaper/card/card.component.html

@@ -0,0 +1,32 @@
+<ion-header class="header-theme2" id="main-content">
+  <ion-toolbar>
+    <ion-title>
+      共{{ answerNumber + unNumber }}道题
+    </ion-title>
+  </ion-toolbar>
+</ion-header>
+<ion-content>
+  <ion-list>
+    <div class="card-body">
+      <div class="card-total">
+        <div>
+          <ion-icon name="ellipse-outline" style="color: #00ff00;vertical-align: middle;"></ion-icon>
+          已答{{ answerNumber }}道
+        </div>
+        <div>
+          <ion-icon name="ellipse-outline" style="color: lightgrey;vertical-align: middle;"></ion-icon>
+          未做{{ unNumber }}道
+        </div>
+      </div>
+      <div *ngFor="let it of previewList">
+        <div class="question-type"> {{ it.name }}_共{{ it.questionNum }}题({{ it.score }}分)</div>
+        <div class="question-num">
+          <div *ngFor="let ques of it.question"
+               (click)="selectQuestion(ques)"
+               [ngClass]="{'unColor':ques.isAnswer==null,'answerColor':ques.isAnswer}">
+            {{ ques.order }}</div>
+        </div>
+      </div>
+    </div>
+  </ion-list>
+</ion-content>

+ 46 - 0
parth5/parth5/src/app/views/pages/examonline/showpaper/card/card.component.scss

@@ -0,0 +1,46 @@
+.card-body{
+  margin: 10px;
+}
+.card-total{
+  display: flex;
+  flex-wrap: nowrap;
+  border-bottom: 1px solid #5e5c5c52;
+  padding-bottom: 10px;
+
+  div{
+    margin-right: 10px;
+  }
+  span{
+    width: 10px;
+    height: 10px;
+    border: 1px solid #1f91f3;
+  }
+}
+.question-type{
+  margin: 5px 0px;
+}
+.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;
+  }
+}
+
+.unColor{
+  border: 2px solid lightgrey !important;
+}
+
+.answerColor{
+  border: 2px solid #00ff00 !important;
+}

+ 31 - 0
parth5/parth5/src/app/views/pages/examonline/showpaper/card/card.component.ts

@@ -0,0 +1,31 @@
+import {Component, Input, OnInit} from '@angular/core';
+import {ModalController} from "@ionic/angular";
+
+@Component({
+  selector: 'app-card',
+  templateUrl: './card.component.html',
+  styleUrls: ['./card.component.scss'],
+})
+export class CardComponent implements OnInit {
+
+  @Input()
+  previewList = [];
+  @Input()
+  testQuestionList= [];
+  unNumber=0;
+  answerNumber=0;
+
+  constructor(public modalController: ModalController) { }
+
+  ngOnInit() {
+    this.answerNumber =this.testQuestionList.filter(x => x.isAnswer).length;
+    this.unNumber =this.testQuestionList.length-this.answerNumber;
+  }
+
+  selectQuestion(ques){
+    this.modalController.dismiss({
+      'dismissed': true,
+      'order': ques.order
+    });
+  }
+}

+ 20 - 0
parth5/parth5/src/app/views/pages/examonline/showpaper/result/result.component.html

@@ -0,0 +1,20 @@
+<ion-header class="header-theme2" id="main-content">
+  <ion-toolbar>
+    <ion-title>
+      考试结果提示
+    </ion-title>
+  </ion-toolbar>
+</ion-header>
+<ion-content>
+  <div class="card" style="margin-top: 10px;padding-bottom: 20px;">
+    <div class="result-body">
+      <div class="result-title">你已成功交卷 </div>
+      <div class="result-correctrate">阅卷完成后可查看本次考试成绩 </div>
+      <div class="result-questionnum">本次考试主观题数:{{subjectiveCount}}题 </div>
+      <div class="result-questionnum">客观题总题数:{{objectiveCount}}题 </div>
+      <div>
+        <ion-button size="small" slot="end" color="warning" (click)="dismiss(2)">确定</ion-button>
+      </div>
+    </div>
+  </div>
+</ion-content>

+ 15 - 0
parth5/parth5/src/app/views/pages/examonline/showpaper/result/result.component.scss

@@ -0,0 +1,15 @@
+.result-body{
+  display: flex;
+  flex-flow: column;
+  align-content: center;
+  justify-items: center;
+  font-size: 15px;
+  text-align: center;
+}
+.result-body >div{
+  padding: 10px 0px;
+}
+.result-body >.result-title{
+  font-size: 18px;
+  font-weight: bold;
+}

+ 24 - 0
parth5/parth5/src/app/views/pages/examonline/showpaper/result/result.component.ts

@@ -0,0 +1,24 @@
+import { Component, OnInit } from '@angular/core';
+import {ModalController} from "@ionic/angular";
+
+@Component({
+  selector: 'app-result',
+  templateUrl: './result.component.html',
+  styleUrls: ['./result.component.scss'],
+})
+export class ResultComponent implements OnInit {
+
+  subjectiveCount=0;
+  objectiveCount=0;
+
+  constructor(public modalController: ModalController) { }
+
+  ngOnInit() {}
+
+  dismiss(action) {
+    this.modalController.dismiss({
+      'dismissed': true,
+      'action': action,
+    });
+  }
+}

+ 125 - 0
parth5/parth5/src/app/views/pages/examonline/showpaper/showpaper.component.html

@@ -0,0 +1,125 @@
+<ion-header class="header-theme2" id="main-content">
+  <ion-toolbar>
+    <ion-label class="title-center">考试答题</ion-label>
+    <ion-buttons slot="start">
+      <ion-back-button icon="ios-back2" text="" mode="md"></ion-back-button>
+    </ion-buttons>
+  </ion-toolbar>
+</ion-header>
+<ion-content>
+  <div *ngIf="examing==false" class="showpaper-header">
+    <div style="text-align: center;">
+      <img src="/assets/icon/test-wait.png" />
+    </div>
+    <div style="font-weight: bold;text-align: center;color: red">
+      考试未开始
+    </div>
+    <div>
+      {{myexam.testName}}_卷面总分:{{myexam.paperScore}}分
+    </div>
+    <div>
+      考生姓名:{{userInfo.username }}
+    </div>
+    <div>
+      所属组织:{{userInfo.DZZMC}}
+    </div>
+    <div>
+      考试时间:{{myexam.testBeginDate}}至{{myexam.testEndDate|date:'MM-dd HH:mm'}}
+    </div>
+    <div>
+      距离考试开始还有: <span style="color: #0e1773;font-weight: bold;">{{examtip}}</span>
+    </div>
+  </div>
+  <div *ngIf="examing" class="test-paper">
+    <div class="paper-quesetion-body">
+      <div *ngFor="let ques of curQuestionList;let i = index">
+        <div [ngSwitch]="ques.NAME">
+          <div class="paper-quesetion-question" *ngSwitchCase="'单选题'">
+            <div class="paper-quesetion-content">
+              <span class="paper-quesetion-num">{{ ques.order }}/{{ questionIndex }}</span>
+              <span class="paper-quesetion-num"> {{ ques.NAME }}</span>
+              {{ ques.CONTENT }}<span
+              class="paper-quesetion-score">({{ ques.SCORE }}分)</span></div>
+            <div
+              *ngFor="let ans of sort(ques.ANSWERS,'ORDER');let $index=index;">
+              <input name="rd_{{ques.order}}" type="radio" [(ngModel)]="ques.useranswer" (ngModelChange)="answer(ques)"
+                     value="{{ans.PROVID_ANSWER_ID}}"
+                     class="with-gap" id="rd_{{ques.order}}_{{$index}}"/>
+              <label for="rd_{{ques.order}}_{{$index}}">{{ options($index) }}、{{ ans.ANSWER_NAME }}</label>
+            </div>
+          </div>
+          <div class="paper-quesetion-question" *ngSwitchCase="'填空题'">
+            <span class="paper-quesetion-num">{{ ques.order }}/{{ questionIndex }}</span>
+            <span class="paper-quesetion-num"> 填空题</span>
+            <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="请输入"
+                           (ngModelChange)="answer(ques)"></ion-input>
+              </ng-container>
+            </ng-container>
+            <span class="paper-quesetion-score">({{ ques.SCORE }}分)</span>
+          </div>
+          <div class="paper-quesetion-question" *ngSwitchCase="'判断题'">
+            <div class="paper-quesetion-content">
+              <span class="paper-quesetion-num">{{ ques.order }}/{{ questionIndex }}</span>
+              <span class="paper-quesetion-num"> 判断题</span>
+              {{ ques.CONTENT }}<span
+              class="paper-quesetion-score">({{ ques.SCORE }}分)</span></div>
+            <div
+              *ngFor="let ans of sort(ques.ANSWERS,'ORDER');let $index=index;">
+              <input name="rd2_{{ques.order}}" type="radio" [(ngModel)]="ques.useranswer" (ngModelChange)="answer(ques)"
+                     value="{{ans.PROVID_ANSWER_ID}}"
+                     class="with-gap" id="rd2_{{ques.order}}_{{$index}}"/>
+              <label for="rd2_{{ques.order}}_{{$index}}">{{ ans.ANSWER_NAME }}</label>
+            </div>
+          </div>
+          <div class="paper-quesetion-question" *ngSwitchCase="'简答题'">
+            <div>
+              <span class="paper-quesetion-num">{{ ques.order }}/{{ questionIndex }}</span>
+              <span class="paper-quesetion-num"> 简答题</span>
+              {{ ques.CONTENT }}<span class="paper-quesetion-score">({{ ques.SCORE }}分)</span>
+            </div>
+            <div *ngFor="let ans of sort(ques.ANSWERS,'ORDER')">
+              <ion-textarea readonly="false" placeholder="请填写" name="txa_{{ques.order}}"
+                            (ngModelChange)="answer(ques)" rows="5"
+                            [(ngModel)]="ques.useranswer"></ion-textarea>
+            </div>
+          </div>
+          <div class="paper-quesetion-question" *ngSwitchCase="'多选题'">
+            <div class="paper-quesetion-content">
+              <span class="paper-quesetion-num">{{ ques.order }}/{{ questionIndex }}</span>
+              <span class="paper-quesetion-num"> 多选题</span>
+              {{ ques.CONTENT }}<span
+              class="paper-quesetion-score">({{ ques.SCORE }}分)</span></div>
+            <div *ngFor="let ans of sort(ques.ANSWERS,'ORDER');let $index=index;">
+              <input type="checkbox" [(ngModel)]="ans.useranswer" (ngModelChange)="answer(ques)"
+                     value="{{ans.PROVID_ANSWER_ID}}"
+                     id="ts_ckb_{{ques.order}}_{{$index}}"/>
+              <label for="ts_ckb_{{ques.order}}_{{$index}}">{{ options($index) }}、{{ ans.ANSWER_NAME }}</label>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</ion-content>
+<ion-footer *ngIf="examing">
+  <div class="examendtip">
+    距考试结束剩<span style="font-weight: bold;color: red">{{examendtip}}</span>
+  </div>
+  <ion-toolbar style="display: flex;align-items: center">
+    <ion-icon (click)="presentModal()" name="reorder-four-outline" style="color: red;vertical-align: middle;"
+              size="large"
+              aria-label="Favorite"></ion-icon>
+    <span>已答{{ answerCount }}/{{ questionCount }}</span>
+    <ion-button size="small" slot="end" [disabled]="order==1" (click)="order=order-1;changeView();">
+      上一题
+    </ion-button>
+    <ion-button size="small" slot="end" [disabled]="questionCount==order" (click)="order=order+1;changeView();">
+      下一题
+    </ion-button>
+    <ion-button size="small" slot="end" color="warning" (click)="submitExamTest()">交卷</ion-button>
+  </ion-toolbar>
+</ion-footer>

+ 96 - 0
parth5/parth5/src/app/views/pages/examonline/showpaper/showpaper.component.scss

@@ -0,0 +1,96 @@
+.showpaper-header {
+  width: 100%;
+  margin: 10px;
+  display: flex;
+  flex-flow: column;
+
+  div{
+    margin-top: 10px;
+  }
+}
+
+.showpaper-header > table {
+  margin: auto;
+  font-size: 16px;
+}
+
+.showpaper-header td {
+  padding: 10px 0px 10px 10px;
+}
+.paper-type-view > .paper-quesetion-type {
+  height: 30px;
+  margin-top: 5px;
+  margin-left: 10px;
+}
+
+.paper-quesetion-type img {
+  width: 30px;
+  height: 30px;
+  vertical-align: middle;
+}
+
+.paper-type-view .paper-quesetion-body {
+  background-color: white;
+  padding: 10px;
+  border-radius: 15px;
+}
+
+.paper-quesetion-question {
+  margin: 5px;
+
+  ion-input {
+    width: 100px;
+    display: inline-block;
+    border-bottom: 1px solid rgb(118, 118, 118);
+  }
+
+  ion-textarea {
+    border: 1px solid rgb(118, 118, 118);
+  }
+}
+
+.paper-quesetion-body {
+  margin: 0px 10px;
+}
+
+.paper-quesetion-body input {
+  border: none;
+  border-bottom: 1px solid rgb(118, 118, 118);
+}
+
+.paper-quesetion-question > div {
+  margin-bottom: 5px;
+}
+
+ .paper-quesetion-num {
+  color: rgb(172, 39, 32);
+  border: 1px solid rgb(172, 39, 32);
+  padding: 1px 5px;
+}
+
+.paper-quesetion-question .isright-answer {
+  color: #00A8FF;
+}
+
+.paper-quesetion-score {
+  color: rgb(172, 39, 32);
+}
+
+.paper-quesetion-content {
+
+}
+
+.paper-viewanswer {
+  border: 1px solid #ee2020;
+  width: 65px;
+  text-align: center;
+  color: #ee2020;
+  cursor: pointer;
+}
+
+.examendtip {
+  text-align: right;
+  width: 100%;
+  padding: 5px;
+  border-bottom: 1px solid #76767652;
+}

+ 331 - 0
parth5/parth5/src/app/views/pages/examonline/showpaper/showpaper.component.ts

@@ -0,0 +1,331 @@
+import {Component, OnInit} from '@angular/core';
+import {AlertController, MenuController, ModalController} from "@ionic/angular";
+import {ActivatedRoute, Router} from "@angular/router";
+import {ConfigService, RequsetData} from "../../../../service/config.service";
+import * as moment from 'moment';
+import {CardComponent} from "./card/card.component";
+import {ResultComponent} from "./result/result.component";
+import {UserService} from "../../../../service/user.service";
+
+@Component({
+  selector: 'app-showpaper',
+  templateUrl: './showpaper.component.html',
+  styleUrls: ['./showpaper.component.scss'],
+})
+export class ShowpaperComponent implements OnInit {
+
+  lstorage = localStorage;
+  myexam: any = {};
+  userInfo: any = {};
+  examing = null;
+  examtip = "";
+  examendtip = "";
+  testQuestionList = [];
+  timer;
+  datatimer;
+  testId = "";
+  exambegintimer;
+  previewList = [];
+  questionIndex = 0;
+  paperScore = 0;
+  questiontypeList = [];
+  curQuestionList = [];
+  order = 1;
+  questionCount = 0;
+  answerCount = 0;
+
+  constructor(private userService: UserService, private modalController: ModalController, public alertController: AlertController, private menu: MenuController, private router: Router, private configService: ConfigService, private routeInfo: ActivatedRoute) {
+  }
+
+  ngOnInit() {
+    this.routeInfo.queryParams.subscribe(params => {
+      this.testId = params['id'];
+      this.getQuestiontypeList();
+      this.getExamTest();
+      this.userInfo = this.userService.GetUser();
+      this.exambegintimer = setInterval(() => {
+        this.getExamTest();
+      }, 1000);
+    });
+  }
+
+  getExamTest() {
+    this.configService.HttpGetRomote
+    ('/api/exammanage/plan/getMyExamPlan', {testId: this.testId}).subscribe((data) => {
+      this.myexam = data.item;
+      this.configService.HttpGetRomote('/api/exammanage/plan/getServerDate', {}).subscribe((date) => {
+        var sysdate = date + "";
+        if (this.myexam != null) {
+          if (this.myexam.manStatus > 2) {
+            this.showMsg('提示', '不在待考试,不允许进入');
+            clearInterval(this.exambegintimer);
+            return;
+          }
+          if (moment(sysdate).isAfter(this.myexam.testEndDate)) {
+            this.showMsg('提示', '考试时间已过,不允许进入');
+            clearInterval(this.exambegintimer);
+            return;
+          }
+          if (moment(sysdate).isBetween(this.myexam.testBeginDate, this.myexam.testEndDate)) {
+            clearInterval(this.exambegintimer);
+            this.timer = setInterval(() => {
+              this.checkTestExamTime();
+            }, 1000);
+            this.datatimer = setInterval(() => {
+              this.getTestExamTime();
+              this.cacheQuestion();
+            }, 60000);
+            this.examing = true;
+            this.showPaper();
+            this.updateTestManStatu(this.myexam.testmanId, 2);
+          } else {
+            this.examing = false;
+            var duration = moment.duration(
+              moment(sysdate).diff(moment(this.myexam.testBeginDate))
+            );
+            var hours = Math.abs(duration.get("hours"));
+            var mins = Math.abs(duration.get("minutes"));
+            var ss = Math.abs(duration.get("seconds"));
+            this.examtip = hours + "小时" + mins + "分" + ss + "秒";
+          }
+        }
+      })
+    });
+  }
+
+  cacheQuestion = () => {
+    if (this.testQuestionList != undefined && this.testQuestionList.length > 0) {
+      this.lstorage.setItem("paperQuestion_" + this.testId, JSON.stringify(this.testQuestionList));
+    }
+  }
+  getTestExamTime = () => {
+    this.configService.HttpGetRomote('/api/exammanage/plan/getTestEndDate', {testId: this.testId}).subscribe((result) => {
+      this.myexam.testEndDate = result.item;
+    });
+  }
+  checkTestExamTime = () => {
+    var myexam = this.myexam;
+    this.configService.HttpGetRomote('/api/exammanage/plan/getServerDate').subscribe((p) => {
+      var sysdate = p + "";
+      if (moment(sysdate).isAfter(this.myexam.testEndDate)) {
+        clearInterval(this.timer);
+        clearInterval(this.datatimer);
+        this.showMsg('提示', '考试时间已到,已自动为您交卷');
+        this.examendtip = "0小时0分";
+        this.submitExamTestSync();
+      } else {
+        var duration = moment.duration(
+          moment(sysdate).diff(moment(myexam.testEndDate))
+        );
+        var hours = Math.abs(duration.get("hours"));
+        var mins = Math.abs(duration.get("minutes"));
+        //因为不显示秒,避免秒倒计时的时候分为0
+        mins = mins == 0 && hours == 0 ? 1 : mins + 1;
+        this.examendtip = hours + "小时" + mins + "分";
+      }
+    })
+  }
+  submitExamTestSync = () => {
+    let pm = new Promise((resolve, reject) => {
+      this.configService.HttpPostRomote('/api/examtest/submitExamTest', {
+        onlinetestId: this.myexam.onlinetestId,
+        testmanId: this.myexam.testmanId,
+        userQuestionList: this.testQuestionList,
+      }).subscribe((data) => {
+        if (data.success) {
+          var subjectiveCount = this.testQuestionList.filter(function (type) {
+            return type.OBJECTIVE_TYPE == 1
+          }).length;
+          var objectiveCount = this.testQuestionList.filter(function (type) {
+            return type.OBJECTIVE_TYPE == 2
+          }).length;
+          this.resultModal(subjectiveCount, objectiveCount);
+        } else {
+          this.showMsg('错误', data.msg);
+        }
+        resolve();
+      })
+    });
+    return pm;
+  }
+  submitExamTest = () => {
+    this.presentAlertConfirm("是否确认交卷?", () => {
+      this.submitExamTestSync().then(() => {
+
+      });
+    })
+  };
+
+  showPaper() {
+    this.getUserTestPaperQuestions().then(() => {
+      this.changeView();
+      this.questionCount = this.testQuestionList.length;
+      this.answerCount = this.testQuestionList.filter(x => x.isAnswer).length;
+
+      this.previewList = [];
+      this.questionIndex = 0;
+      var selectQuestionTypeList = this.questiontypeList.filter((type) => {
+        return this.testQuestionList.filter((pquestion) => {
+          return pquestion.BASE_QUESTION_TYPE_ID == type.baseQuestionTypeId;
+        }).length > 0;
+      });
+      selectQuestionTypeList.forEach((type) => {
+        var typequestion = this.testQuestionList.filter((pquestion) => {
+          return pquestion.BASE_QUESTION_TYPE_ID == type.baseQuestionTypeId;
+        })
+        if (typequestion.length > 0) {
+          var previewItem = Object.assign({}, type);
+          var typescore = 0;
+          typequestion.forEach((tquestion) => {
+            typescore += tquestion.SCORE;
+            this.questionIndex++;
+            tquestion.order = this.questionIndex;
+          })
+          this.paperScore += typescore;
+          previewItem.score = typescore;//题型总分
+          previewItem.questionNum = typequestion.length;
+          previewItem.question = typequestion;
+          this.previewList.push(previewItem);
+        }
+      })
+    });
+  }
+
+  //加载试题类型数据
+  getQuestiontypeList = () => {
+    this.configService.HttpGetRomote('/api/exammanage/questiontypeSetting/getList', {}).subscribe((data: RequsetData) => {
+      if (data.success) {
+        this.questiontypeList = data.item;
+      }
+    });
+  };
+
+  getUserTestPaperQuestions() {
+    let pm = new Promise((resolve, reject) => {
+      //先取缓存数据
+      var lstkey = "paperQuestion_" + this.testId;
+      if (this.lstorage.getItem(lstkey)) {
+        this.testQuestionList = JSON.parse(this.lstorage.getItem(lstkey));
+        resolve();
+      } else {
+        this.configService.HttpGetRomote('/api/examtest/getUserTestPaperQuestions', {
+          paperid: this.myexam.testPaperId,
+          testid: this.myexam.onlinetestId,
+        }).subscribe((data: RequsetData) => {
+          if (data.success) {
+            this.testQuestionList = data.item;
+            this.testQuestionList.forEach((x, index) => {
+              x.ANSWERS = this.sort(x.ANSWERS, 'ORDER');
+              x.order = index + 1;
+            })
+            this.lstorage.setItem(lstkey, JSON.stringify(this.testQuestionList));
+            resolve();
+          }
+        });
+      }
+    });
+    return pm;
+  }
+
+  updateTestManStatu(testmanId, manStatu) {
+    this.configService.HttpGetRomote('/api/examtest/updateTestManStatu', {
+      testmanId: testmanId, manStatu: manStatu
+    }).subscribe((data: RequsetData) => {
+      if (data.success) {
+      }
+    });
+  }
+
+  sort(list: any[], field: string) {
+    return list.sort((a, b) => a[field] - b[field]);
+  }
+
+  options(index) {
+    return String.fromCharCode(65 + index);
+  }
+
+  answer(ques) {
+    ques.isAnswer = true;
+    this.answerCount = this.testQuestionList.filter(x => x.isAnswer).length;
+  }
+
+  changeView() {
+    this.curQuestionList = this.testQuestionList.filter(x => x.order == this.order);
+  }
+
+  close() {
+    this.router.navigate(['../'], {
+      relativeTo: this.routeInfo,
+      queryParams: {id: 'id', random: Math.random()}
+    });
+  }
+
+  async presentModal() {
+    const modal = await this.modalController.create({
+      component: CardComponent,
+      cssClass: 'examtest-modal',
+      componentProps: {
+        'previewList': this.previewList,
+        'testQuestionList': this.testQuestionList
+      }
+    });
+    await modal.present();
+
+    const {data} = await modal.onWillDismiss();
+
+    if (data != undefined && data.dismissed) {
+      this.order = data.order;
+      this.changeView();
+    }
+  }
+
+  async showMsg(title: string, msg: string) {
+    const alert = await this.alertController.create({
+      header: title,
+      subHeader: '',
+      message: msg,
+      buttons: ['确定']
+    });
+
+    await alert.present();
+  }
+
+  async presentAlertConfirm(msg: string, handler) {
+    const alert = await this.alertController.create({
+      header: '提示',
+      message: '<strong>' + msg + '</strong>',
+      buttons: [
+        {
+          text: '关闭',
+          role: 'cancel',
+          cssClass: 'secondary',
+          handler: () => {
+
+          }
+        }, {
+          text: '确定',
+          handler: handler
+        }
+      ]
+    });
+    await alert.present();
+  }
+
+  async resultModal(subjectiveCount: number, objectiveCount: number) {
+    const modal = await this.modalController.create({
+      component: ResultComponent,
+      cssClass: 'onlineresult-modal',
+      componentProps: {
+        'subjectiveCount': subjectiveCount,
+        'objectiveCount': objectiveCount
+      }
+    });
+    await modal.present();
+
+    const {data} = await modal.onWillDismiss();
+
+    if (data != undefined && data.dismissed) {
+      this.close();
+    }
+  }
+}

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

@@ -24,7 +24,7 @@
         </div>
       </div>
       <div *ngFor="let it of previewList">
-        <h5> {{ it.name }}_共{{ it.questionNum }}题({{ it.score }}分)</h5>
+        <div class="question-type"> {{ it.name }}_共{{ it.questionNum }}题({{ it.score }}分)</div>
         <div class="question-num">
           <div *ngFor="let ques of it.question"
                (click)="selectQuestion(ques)"

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

@@ -16,6 +16,9 @@
     border: 1px solid #1f91f3;
   }
 }
+.question-type{
+  margin: 5px 0px;
+}
 .question-num {
   display: flex;
 

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

@@ -81,10 +81,10 @@
                 aria-label="Favorite"></ion-icon>
       <span>已答{{ answerCount }}/{{ questionCount }}</span>
       <ion-icon slot="end" name="checkbox-outline" size="large" (click)="showAnswer()"></ion-icon>
-      <ion-button size="small" slot="end" *ngIf="order>1" (click)="order=order-1;changeView();">
+      <ion-button size="small" slot="end" [disabled]="order==1" (click)="order=order-1;changeView();">
         上一题
       </ion-button>
-      <ion-button size="small" slot="end" *ngIf="questionCount>order" (click)="order=order+1;changeView();">
+      <ion-button size="small" slot="end" [disabled]="questionCount==order" (click)="order=order+1;changeView();">
         下一题
       </ion-button>
       <ion-button size="small" slot="end" color="warning" (click)="resultModal()">结束练习</ion-button>

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

@@ -4,7 +4,8 @@
 
 .question-body {
   margin: 10px;
-  div{
+
+  div {
     margin-top: 10px;
   }
 }
@@ -15,5 +16,7 @@
   border-bottom: 1px solid rgb(118, 118, 118);
 }
 
-.input-container {
+.question-body ion-textarea {
+  border-bottom: 1px solid rgb(118, 118, 118);
 }
+

+ 6 - 0
parth5/parth5/src/app/views/tapp/tab-main/tab-main.page.html

@@ -13,6 +13,12 @@
       </div>
       <div class="tool-title">自测练习</div>
     </a>
+    <a class="tool-item"   routerLink="./exam/examonline">
+      <div class="tool-img">
+        <img src="assets/icon/tool_more.svg" style="width: 32px;height: 32px">
+      </div>
+      <div class="tool-title">我的考试</div>
+    </a>
     <a class="tool-item" (click)="more()">
       <div class="tool-img">
         <img src="assets/icon/tool_more.svg" style="width: 32px;height: 32px">

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

@@ -65,7 +65,9 @@ import {DzzfcListComponent} from "../../pages/propagandawork/dzzfc/list.componen
 import {DzzfcEditComponent} from "../../pages/propagandawork/dzzfc/edit/edit.component";
 import {DzzfcDetailComponent} from "../../pages/propagandawork/dzzfc/detail/detail.component";
 import {ShowComponent as ExamtestShowComponent} from "../../pages/examtest/show/show.component";
-
+import {ExamonlineComponent} from "../../pages/examonline/examonline.component";
+import {ShowpaperComponent} from "../../pages/examonline/showpaper/showpaper.component";
+import {CardComponent as ShowpaperCardComponent} from "../../pages/examonline/showpaper/card/card.component";
 const pageComponents = [
   PositionComponent,
   PositionEditComponent,
@@ -96,6 +98,10 @@ const pageComponents = [
   ExamtestShowComponent,
   CardComponent,
   ResultComponent,
+  ExamonlineComponent,
+  ShowpaperComponent,
+  ShowpaperCardComponent,
+  ResultComponent,
   DzzfcListComponent,
   DzzfcEditComponent,
   DzzfcDetailComponent

BIN
parth5/parth5/src/assets/icon/test-question.png


BIN
parth5/parth5/src/assets/icon/test-wait.png