cehn 7 months ago
parent
commit
d2deeba92c
17 changed files with 450 additions and 69 deletions
  1. 35 28
      projects/textbook/src/app/textbook/textbook.component.html
  2. 41 1
      projects/textbook/src/app/textbook/textbook.component.ts
  3. 10 0
      projects/textbook/src/modules/nav-admin/page-process/process-list/process-list.component.ts
  4. 5 4
      projects/textbook/src/modules/nav-province-contact/activity/activity.component.ts
  5. 3 0
      projects/textbook/src/modules/nav-province-contact/components/review-details/review-details.component.html
  6. 0 0
      projects/textbook/src/modules/nav-province-contact/components/review-details/review-details.component.scss
  7. 24 0
      projects/textbook/src/modules/nav-province-contact/components/review-details/review-details.component.spec.ts
  8. 14 0
      projects/textbook/src/modules/nav-province-contact/components/review-details/review-details.component.ts
  9. 21 8
      projects/textbook/src/modules/nav-province-contact/page-process/page-process.component.html
  10. 145 17
      projects/textbook/src/modules/nav-province-contact/page-process/page-process.component.ts
  11. 10 0
      projects/textbook/src/modules/nav-province-contact/page-process/process-list/process-list.component.ts
  12. 7 3
      projects/textbook/src/modules/nav-review/approve/approve.component.html
  13. 9 0
      projects/textbook/src/modules/nav-review/approve/approve.component.scss
  14. 13 7
      projects/textbook/src/modules/nav-review/approve/approve.component.ts
  15. 101 0
      projects/textbook/src/services/compute.ts
  16. 8 1
      server/db/schemas/EduProcess.js
  17. 4 0
      server/db/schemas/EduTextbook.js

+ 35 - 28
projects/textbook/src/app/textbook/textbook.component.html

@@ -108,9 +108,17 @@
         >
           申报部门
         </th>
-        @if (filterObj.btns.eduReivew) {
-        @if (filterObj.btns?.mark) {
-          <th nzEllipsis nzWidth="80px" nzRight>评审状态</th>
+        @if (filterObj.btns.eduReivew) { @if (filterObj.btns?.mark) {
+        <th
+          nzEllipsis
+          nzWidth="100px"
+          [nzShowFilter]="true"
+          [nzFilters]="listOfColumns.status.listOfFilter"
+          (nzFilterChange)="listOfColumns.status.onChange($event)"
+          nzRight
+        >
+          评审状态
+        </th>
         }
         <th nzEllipsis nzWidth="80px" nzRight>评审分值</th>
         }
@@ -262,17 +270,16 @@
             </div>
           </ng-template>
         </td>
-        @if (filterObj.btns.eduReivew) {
-        @if (filterObj.btns?.mark) {
-          <td nzEllipsis [nzAlign]="'center'" nzRight>
-            @if (scoreMap[data.id]?.status == 'complete') {
-            <nz-tag nzColor="success">已评审</nz-tag>
-            } @else if (scoreMap[data.id]?.status == 'save') {
-            <nz-tag nzColor="warning">已保存</nz-tag>
-            }@else {
-            <nz-tag nzColor="processing">未评审</nz-tag>
-            }
-          </td>
+        @if (filterObj.btns.eduReivew) { @if (filterObj.btns?.mark) {
+        <td nzEllipsis [nzAlign]="'center'" nzRight>
+          @if (scoreMap[data.id]?.status == '已评审') {
+          <nz-tag nzColor="success">已评审</nz-tag>
+          } @else if (scoreMap[data.id]?.status == '已保存') {
+          <nz-tag nzColor="warning">已保存</nz-tag>
+          }@else {
+          <nz-tag nzColor="processing">未评审</nz-tag>
+          }
+        </td>
         }
         <td nzEllipsis [nzAlign]="'right'" nzRight>
           {{ scoreMap[data.id]?.score ?? "-" }}
@@ -298,21 +305,10 @@
                   nzType="link"
                   style="color: #231c1f"
                 >
-                  <span nz-icon nzType="eye" nzTheme="outline"></span>教材详情
+                  <span nz-icon nzType="eye" nzTheme="outline"></span>在线预览
                 </button>
               </li>
-              } @if(filterObj.btns.mark){
-              <li nz-menu-item>
-                <button
-                  (click)="onMarking(data.id)"
-                  nz-button
-                  nzType="link"
-                  style="color: #231c1f"
-                >
-                  <span nz-icon nzType="form" nzTheme="outline"></span>打分
-                </button>
-              </li>
-              } @if(filterObj.btns.edit){
+              }@if(filterObj.btns.edit){
               <li nz-menu-item>
                 <button
                   (click)="toUrl('/nav-author/manage/apply', { id: data.id })"
@@ -409,7 +405,18 @@
                   >提交教材
                 </button>
               </li>
-              }@if(filterObj.btns.isDelete){
+              } @if(filterObj.btns.mark){
+              <li nz-menu-item>
+                <button
+                  (click)="onMarking(data.id, scoreMap[data.id]?.status)"
+                  nz-button
+                  nzType="link"
+                  style="color: #231c1f"
+                >
+                  <span nz-icon nzType="form" nzTheme="outline"></span>打分
+                </button>
+              </li>
+              } @if(filterObj.btns.isDelete){
               <li nz-menu-item>
                 <button
                   (click)="del(data)"

+ 41 - 1
projects/textbook/src/app/textbook/textbook.component.ts

@@ -154,7 +154,42 @@ export class TextbookComponent implements OnInit {
         this.onFilter();
       },
     },
+    status: {
+      listOfFilter: [
+        { value: '已保存', text: '已保存' },
+        { value: '未评审', text: '未评审' },
+        { value: '已评审', text: '已评审' },
+      ],
+      onChange: (data: [any]) => {
+        // console.log(data);
+        // console.log(this.filterObj.contained);
+        // console.log(this.scoreMap);
+        this.statusFilter = data
+        this.updateStatusChange()
+      },
+    },
   };
+  updateStatusChange(){
+    this.filterObj.contained = this.initContained?.map(item=> item)
+    this.filterObj.contained = this.filterObj.contained?.filter((item:string)=>{
+      if(this.statusFilter?.length < 1){
+        return item
+      }else{
+        if(this.statusFilter.includes(this.scoreMap[item]?.status)){
+          return item
+        }else if(!this.scoreMap[item]?.status && this.statusFilter.includes('未评审')){
+          return item
+        }
+      }
+      return
+    })
+    // console.log(this.filterObj.contained);
+    this.pageIndex = 1
+    this.getTextbook()
+  }
+  statusFilter:Array<string> = []
+  initContained:Array<string> = []
+
   //筛选条件
   filters: filter | any = {
     lang: { type: 'EduTextbookVolume', value: [] },
@@ -227,6 +262,7 @@ export class TextbookComponent implements OnInit {
           true
         );
       }
+      this.filterObj?.contained && this.initContained.push(...this.filterObj.contained) //需包含的数组再次赋值给原始查询,防止筛选重置问题
     });
   }
   async getTextbook(
@@ -835,8 +871,12 @@ export class TextbookComponent implements OnInit {
     this.loading = false
   }
   //打分
-  onMarking(id:string){
+  onMarking(id:string, status:string){
     let pid = this.tbookSer.profile?.objectId
+    if(status == '已评审'){
+      this.message.warning('当前教材已提交评审打分')
+      return
+    }
     if(!pid){
       this.message.error('当前登录身份已过期,请重新登录')
       return

+ 10 - 0
projects/textbook/src/modules/nav-admin/page-process/process-list/process-list.component.ts

@@ -182,6 +182,16 @@ export class ProcessListComponent implements OnInit {
         del: false,
       };
     }
+    if (e.get('status') == '201') {
+      return {
+        title: '评审中',
+        color: 'cyan',
+        strat: false,
+        stop: true,
+        end: true,
+        del: false,
+      };
+    }
     return;
   };
   /* 新建组织 */

+ 5 - 4
projects/textbook/src/modules/nav-province-contact/activity/activity.component.ts

@@ -92,8 +92,9 @@ export class ActivityComponent implements OnInit {
 
 
   async refersh() {
-    this.getActivity()
-    this.getExpertGroup()
+    await this.getActivity()
+    await this.getExpertGroup()
+    this.saveLoading = false
   }
   company: string = localStorage.getItem('company')!
   /**评审活动 */
@@ -104,7 +105,7 @@ export class ActivityComponent implements OnInit {
     let query = new Parse.Query('Activity')
     query.notEqualTo('isDeleted', true)
     query.equalTo('eduProcess', this.eduProcess?.id)
-    query.equalTo('company', this.company)
+    // query.equalTo('company', this.company)
     this.activity = await query.first()
     console.log(this.activity)
     if (this.activity?.id) {
@@ -113,7 +114,6 @@ export class ActivityComponent implements OnInit {
       this.deadline = this.activity?.get('deadline') || null
       this.calculation = this.activity?.get('calculation') || 'mean'
       this.reviewDetails = this.activity?.get('reviewDetails') || {}
-      this.saveLoading = false
     } else {
       let Activity = Parse.Object.extend('Activity')
       this.activity = new Activity()
@@ -151,6 +151,7 @@ export class ActivityComponent implements OnInit {
   calculation: 'truncatedMean' | 'mean' = 'mean'
   async changeCalculation() {
     console.log(this.calculation)
+    this.msg.warning('计算方式已调整,请返回评审活动重新计算平均分')
     this.save()
   }
   /**评审细则 */

+ 3 - 0
projects/textbook/src/modules/nav-province-contact/components/review-details/review-details.component.html

@@ -0,0 +1,3 @@
+<p>
+  review-details works!
+</p>

+ 0 - 0
projects/textbook/src/modules/nav-province-contact/components/review-details/review-details.component.scss


+ 24 - 0
projects/textbook/src/modules/nav-province-contact/components/review-details/review-details.component.spec.ts

@@ -0,0 +1,24 @@
+import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
+import { IonicModule } from '@ionic/angular';
+
+import { ReviewDetailsComponent } from './review-details.component';
+
+describe('ReviewDetailsComponent', () => {
+  let component: ReviewDetailsComponent;
+  let fixture: ComponentFixture<ReviewDetailsComponent>;
+
+  beforeEach(waitForAsync(() => {
+    TestBed.configureTestingModule({
+      declarations: [ ReviewDetailsComponent ],
+      imports: [IonicModule.forRoot()]
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(ReviewDetailsComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  }));
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 14 - 0
projects/textbook/src/modules/nav-province-contact/components/review-details/review-details.component.ts

@@ -0,0 +1,14 @@
+import { Component, OnInit } from '@angular/core';
+
+@Component({
+  selector: 'app-review-details',
+  templateUrl: './review-details.component.html',
+  styleUrls: ['./review-details.component.scss'],
+})
+export class ReviewDetailsComponent  implements OnInit {
+
+  constructor() { }
+
+  ngOnInit() {}
+
+}

+ 21 - 8
projects/textbook/src/modules/nav-province-contact/page-process/page-process.component.html

@@ -30,25 +30,42 @@
         <div class="title">{{ activity?.get("name") || "暂未设置" }}</div>
         <div class="row">
           <div class="lable">开始时间:</div>
-          <div class="val">{{ this.activity?.get("startDate") | date : "yyyy-MM-dd HH:mm" }}</div>
+          <div class="val">
+            {{ this.activity?.get("startDate") | date : "yyyy-MM-dd HH:mm" }}
+          </div>
         </div>
         <div class="row">
           <div class="lable">结束时间:</div>
-          <div class="val">{{ this.activity?.get("deadline") | date : "yyyy-MM-dd HH:mm" }}</div>
+          <div class="val">
+            {{ this.activity?.get("deadline") | date : "yyyy-MM-dd HH:mm" }}
+          </div>
         </div>
         <div class="row">
           <div class="lable">评审数量:</div>
           <div class="val">{{ expertGroupLength || 0 }}</div>
         </div>
         <div class="examine-fonter">
+          @if (activity?.id && eduProcess?.get('status') == '201') {
           <button
             style="background: #3e49b3; border: 1px #3e49b3; margin-right: 50px"
             nz-button
             nzType="primary"
             [disabled]="!activity?.id"
+            (click)="onCease()"
+          >
+            结束评审
+          </button>
+          }@else {
+          <button
+            style="background: #3e49b3; border: 1px #3e49b3; margin-right: 50px"
+            nz-button
+            nzType="primary"
+            [disabled]="!activity?.id"
+            (click)="startActivity()"
           >
             启动
           </button>
+          }
           <button
             style="background: #a2a2a2; border: 1px #a2a2a2; margin-right: 50px"
             nz-button
@@ -59,12 +76,8 @@
           >
             编辑
           </button>
-          @if (authCompute) {
-            <button
-            nzDanger
-            nz-button
-            nzType="primary"
-          >
+          @if (activity?.id && authCompute) {
+          <button [nzLoading]="isLoading" nzDanger nz-button nzType="primary" (click)="onCompute()">
             计算平均分
           </button>
           }

+ 145 - 17
projects/textbook/src/modules/nav-province-contact/page-process/page-process.component.ts

@@ -10,7 +10,9 @@ import { ProcessCreateComponent } from './process-create/process-create.componen
 import { TextbookComponent } from '../../../app/textbook/textbook.component';
 import { textbookServer } from '../../../services/textbook';
 import { DatePipe } from '@angular/common';
-
+import { NzMessageService } from 'ng-zorro-antd/message';
+import * as compute from '../../../services/compute';
+import { NzModalService } from 'ng-zorro-antd/modal';
 @Component({
   selector: 'app-page-process',
   templateUrl: './page-process.component.html',
@@ -56,14 +58,20 @@ export class PageProcessComponent implements OnInit {
       export: true,
     },
   };
-  activity?: Parse.Object
-  get authCompute():boolean{
-    return this.activity?.get("startDate") < new Date()
+  activity?: Parse.Object;
+  get authCompute(): boolean {
+    return (
+      this.activity?.get('startDate') < new Date() &&
+      (!this.activity?.get('deadline') ||
+        this.activity?.get('deadline') > new Date())
+    );
   }
   constructor(
     private activeRoute: ActivatedRoute,
     public tbookSer: textbookServer,
-    private router: Router
+    private router: Router,
+    private msg: NzMessageService,
+    private modal: NzModalService
   ) {
     this.user = Parse.User.current();
   }
@@ -95,25 +103,33 @@ export class PageProcessComponent implements OnInit {
           }
         }
         this.eduProcess = res;
-        this.getActivity()
-        this.getExpertGroup()
+        this.getActivity();
+        this.getExpertGroup();
       }
     });
   }
   async getActivity() {
-    let query = new Parse.Query('Activity')
-    query.notEqualTo('isDeleted', true)
-    query.equalTo('eduProcess', this.eduProcess?.id)
-    this.activity = await query.first()
+    let query = new Parse.Query('Activity');
+    query.notEqualTo('isDeleted', true);
+    query.equalTo('eduProcess', this.eduProcess?.id);
+    this.activity = await query.first();
+    //如果已到期,退回遴选中状态
+    if (
+      this.activity?.get('deadline') < new Date() &&
+      this.eduProcess?.get('status') == '201'
+    ) {
+      this.eduProcess?.set('status', '200');
+      await this.eduProcess.save();
+    }
   }
   /**评审组 */
-  expertGroupLength: Number = 0
+  expertGroupLength: Number = 0;
   async getExpertGroup() {
-    let query = new Parse.Query('ExpertGroup')
-    query.equalTo('eduProcess', this.eduProcess?.id)
-    query.notEqualTo('isDeleted', true)
-    query.descending('updatedAt')//大到小
-    this.expertGroupLength = await query.count()
+    let query = new Parse.Query('ExpertGroup');
+    query.equalTo('eduProcess', this.eduProcess?.id);
+    query.notEqualTo('isDeleted', true);
+    query.descending('updatedAt'); //大到小
+    this.expertGroupLength = await query.count();
   }
   onCreateProcess() {
     this.router.navigate([
@@ -128,6 +144,118 @@ export class PageProcessComponent implements OnInit {
       this.router.navigate([url]);
     }
   }
+  /* 开始活动 */
+  async startActivity() {
+    console.log(this.activity);
+    if (!this.activity?.id || !this.activity?.get('startDate')) {
+      this.msg.error('请先创建活动或设置活动开始时间');
+      return;
+    }
+    if (this.activity?.get('deadline') < new Date()) {
+      this.msg.error('评审活动时间已结束');
+      return;
+    }
+    this?.eduProcess?.set('status', '201');
+    await this.eduProcess?.save();
+    this.msg.success('活动已启动');
+    this.ngOnInit();
+  }
+  /* 计算平均分 */
+  isLoading: boolean = false;
+  async onCompute() {
+    if (this.isLoading) return;
+    this.isLoading = true;
+    try {
+      let queryExpertGroup = new Parse.Query('ExpertGroup');
+      queryExpertGroup.notEqualTo('isDeleted', true);
+      queryExpertGroup.equalTo('eduProcess', this.eduProcess?.id);
+      // queryExpertGroup.select('textbookList')
+      queryExpertGroup.include('textbookList');
+      let expertGroupList = await queryExpertGroup.find();
+      for (let index = 0; index < expertGroupList.length; index++) {
+        const item = expertGroupList[index];
+        if (!item?.get('textbookList')?.length) continue;
+        for (let j = 0; j < item?.get('textbookList').length; j++) {
+          const book: Parse.Object = item?.get('textbookList')[j];
+          let obj = await this.getEduReview(book.id);
+          console.log(obj);
+          // console.log(book?.get('title') + '平均分' + num);
+          if (obj.count) {
+            if (
+              item?.get('calculation') == 'truncatedMean' &&
+              obj.sort.length > 3
+            ) {
+              let cut = compute.addNum(
+                obj.sort[0],
+                obj.sort[obj.sort.length - 1]
+              );
+              obj.total = compute.subtraction(obj.total, cut);
+              book.set('score', compute.accDiv(obj.total, obj.count - 2));
+            } else {
+              book.set('score', compute.accDiv(obj.total, obj.count));
+            }
+            await book.save();
+          }
+        }
+      }
+      this.msg.success('计算完成');
+    } catch (err) {
+      this.msg.error('计算错误');
+    }
+    this.isLoading = false;
+  }
+  async getEduReview(
+    bookid: string
+  ): Promise<{ total: number; count: number; sort: Array<any> }> {
+    let score = 0,
+      count = 0,
+      arrScore: Array<any> = [];
+    let queryExpertGroup = new Parse.Query('EduReview');
+    queryExpertGroup.notEqualTo('isDeleted', true);
+    queryExpertGroup.equalTo('verify', true);
+    queryExpertGroup.equalTo('eduTextbook', bookid);
+    queryExpertGroup.exists('score');
+    count = await queryExpertGroup.count();
+    let r = await queryExpertGroup.find();
+    r?.forEach((item) => {
+      // console.log(item.get('score'));
+      score = compute.addNum(score, item.get('score'));
+      arrScore.push(item?.get('score'));
+    });
+    return {
+      total: score,
+      count: count,
+      sort: arrScore.sort(),
+    };
+  }
+  //结束
+  onCease() {
+    if (this.eduProcess?.get('status') != '201') {
+      this.msg.warning('当前流程非评审中');
+      return;
+    }
+    if (this.activity?.get('deadline') > new Date()) {
+      this.modal.confirm({
+        nzTitle: '结束评审活动',
+        nzContent: '当前评审活动结束时间暂未到期,是否结束评审活动?',
+        nzOkText: '确认',
+        nzOkType: 'primary',
+        nzOnOk: async () => {
+          this.activity?.set('deadline', new Date());
+          this.activity?.save();
+          this.eduProcess?.set('status', '200');
+          this.eduProcess?.save();
+          this.msg.success('已结束');
+        },
+        nzCancelText: '取消',
+        nzOnCancel: () => console.log('Cancel'),
+      });
+    } else {
+      this.eduProcess?.set('status', '200');
+      this.eduProcess?.save();
+      this.msg.success('已结束');
+    }
+  }
   back() {
     history.back();
   }

+ 10 - 0
projects/textbook/src/modules/nav-province-contact/page-process/process-list/process-list.component.ts

@@ -177,6 +177,16 @@ export class ProcessListComponent implements OnInit {
         del: false,
       };
     }
+    if (e.get('status') == '201') {
+      return {
+        title: '评审中',
+        color: 'cyan',
+        strat: false,
+        stop: true,
+        end: true,
+        del: false,
+      };
+    }
     return;
   };
   editLoading:boolean = true

+ 7 - 3
projects/textbook/src/modules/nav-review/approve/approve.component.html

@@ -4,7 +4,7 @@
     >{{activity?.get('name') || '暂无评审活动'}} @if(eduProcess?.get('status') == '200'){
     <nz-tag style="margin-left: 10px" [nzColor]="'blue'"> 评审中</nz-tag>
     } @else if (eduProcess?.get('status') != '200') {
-    <nz-tag style="margin-left: 10px" [nzColor]="'blue'"> 已结束</nz-tag>
+    <nz-tag style="margin-left: 10px" nzColor="default"> 已结束</nz-tag>
     }
 
     <br />
@@ -43,12 +43,16 @@
   [(nzVisible)]="mrakVisible"
   nzTitle="填写评审打分"
   (nzOnCancel)="handleCancel()"
-  nzWidth="400px"
+  nzWidth="460px"
   nzCentered
 >
   <ng-container *nzModalContent>
     <div nz-row class="modal">
-      <div class="proview-pdf"></div>
+      @if (srcUrl) {
+        <div class="proview-pdf">
+          <iframe [src]="srcUrl" frameborder="0"></iframe>
+        </div>
+      }
       <div class="modal-title">分值</div>
       <nz-input-group style="width: 100%" nzSuffix="/100">
         <nz-input-number

+ 9 - 0
projects/textbook/src/modules/nav-review/approve/approve.component.scss

@@ -38,4 +38,13 @@
   align-items: center;
   justify-content: center;
   background: rgb(0 0 0 / 30%);
+}
+.proview-pdf{
+  width: 100%;
+  margin: 10px auto;
+  height: 300px;
+  iframe{
+    height: 100%;
+    width: 100%;
+  }
 }

+ 13 - 7
projects/textbook/src/modules/nav-review/approve/approve.component.ts

@@ -14,6 +14,7 @@ import { NzTabsModule } from 'ng-zorro-antd/tabs';
 import { NzMessageService } from 'ng-zorro-antd/message';
 import { NzInputNumberModule } from 'ng-zorro-antd/input-number';
 import { NzModalService } from 'ng-zorro-antd/modal';
+import { DomSanitizer} from '@angular/platform-browser';
 @Component({
   selector: 'app-approve',
   imports: [
@@ -60,7 +61,7 @@ export class ApproveComponent implements OnInit {
     contained: [],
     btns: {
       eduReivew: true,
-      export: true,
+      // export: true,
     },
   };
   showText: boolean = false;
@@ -74,7 +75,8 @@ export class ApproveComponent implements OnInit {
   constructor(
     private message: NzMessageService,
     public tbookSer: textbookServer,
-    private modal: NzModalService
+    private modal: NzModalService,
+    private sanitizer: DomSanitizer
   ) {
     this.user = Parse.User.current();
   }
@@ -95,10 +97,10 @@ export class ApproveComponent implements OnInit {
     r.forEach((item) => {
       this.scoreMap[item?.get('eduTextbook').id] = {
         status: item?.get('verify')
-          ? 'complete'
+          ? '已评审'
           : item?.get('num')
-          ? 'save'
-          : '',
+          ? '已保存'
+          : '未评审',
         score: item?.get('score') ?? item?.get('num') ?? '-',
       };
     });
@@ -127,11 +129,13 @@ export class ApproveComponent implements OnInit {
     this.showText = true;
     this.eduProcess = r[0]?.get('eduProcess')
   }
+  srcUrl:any
   async getActivity(){
     let query = new Parse.Query('Activity')
     query.notEqualTo('isDeleted', true)
     query.equalTo('eduProcess', this.eduProcess?.id)
     this.activity = await query.first()
+    this.srcUrl = this.sanitizer.bypassSecurityTrustResourceUrl(this.activity?.get('reviewDetails')?.url+'#toolbar=0')
   }
   //切换tab
   async onSelectChange(e: number) {
@@ -211,10 +215,11 @@ export class ApproveComponent implements OnInit {
           await this.eduReview?.save();
           this.message.success('提交成功');
           this.textbook.scoreMap[this.editTextbook] = {
-            status: 'complete',
+            status: '已评审',
             score: this.eduReview?.get('score'),
           };
           this.scoreMap = this.textbook.scoreMap;
+          this.textbook.updateStatusChange()
           this.handleCancel();
         },
         nzCancelText: '取消',
@@ -235,10 +240,11 @@ export class ApproveComponent implements OnInit {
       await this.eduReview?.save();
       this.message.success('保存成功');
       this.textbook.scoreMap[this.editTextbook] = {
-        status: 'save',
+        status: '已保存',
         score: this.eduReview?.get('num'),
       };
       this.scoreMap = this.textbook.scoreMap;
+      this.textbook.updateStatusChange()
       this.handleCancel();
     }
   }

+ 101 - 0
projects/textbook/src/services/compute.ts

@@ -0,0 +1,101 @@
+/* 加减乘除精度计算 */
+export const addNum = function addNum(arg1: number, arg2: number): number {
+  arg1 = arg1 ? arg1 : 0;
+  arg2 = arg2 ? arg2 : 0;
+  let r1, r2, m, c;
+  try {
+    r1 = arg1.toString().split('.')[1].length;
+  } catch (e) {
+    r1 = 0;
+  }
+  try {
+    r2 = arg2.toString().split('.')[1].length;
+  } catch (e) {
+    r2 = 0;
+  }
+  c = Math.abs(r1 - r2);
+  m = Math.pow(10, Math.max(r1, r2));
+  if (c > 0) {
+    let cm = Math.pow(10, c);
+    if (r1 > r2) {
+      arg1 = Number(arg1.toString().replace('.', ''));
+      arg2 = Number(arg2.toString().replace('.', '')) * cm;
+    } else {
+      arg1 = Number(arg1.toString().replace('.', '')) * cm;
+      arg2 = Number(arg2.toString().replace('.', ''));
+    }
+  } else {
+    arg1 = Number(arg1.toString().replace('.', ''));
+    arg2 = Number(arg2.toString().replace('.', ''));
+  }
+  return (arg1 + arg2) / m;
+};
+//减法
+export const subtraction = function subtraction(
+  num1: number,
+  num2: number
+): number {
+  var r1, r2, m, floatNum;
+  try {
+    r1 = num1.toString().split('.')[1].length;
+  } catch (e) {
+    r1 = 0;
+  }
+  try {
+    r2 = num2.toString().split('.')[1].length;
+  } catch (e) {
+    r2 = 0;
+  }
+  m = Math.pow(10, Math.max(r1, r2));
+  return (num1 * m - num2 * m) / m;
+};
+
+//相乘
+export const multiply = function multiply(arg1: number, arg2: number): number {
+  arg1 = arg1 ? arg1 : 0;
+  arg2 = arg2 ? arg2 : 0;
+  let r1, r2, m, c;
+  try {
+    r1 = arg1.toString().split('.')[1].length;
+  } catch (e) {
+    r1 = 0;
+  }
+  try {
+    r2 = arg2.toString().split('.')[1].length;
+  } catch (e) {
+    r2 = 0;
+  }
+  c = Math.abs(r1 - r2);
+  m = Math.pow(10, Math.max(r1, r2) * 2);
+  if (c > 0) {
+    let cm = Math.pow(10, c);
+    if (r1 > r2) {
+      arg1 = Number(arg1.toString().replace('.', ''));
+      arg2 = Number(arg2.toString().replace('.', '')) * cm;
+    } else {
+      arg1 = Number(arg1.toString().replace('.', '')) * cm;
+      arg2 = Number(arg2.toString().replace('.', ''));
+    }
+  } else {
+    arg1 = Number(arg1.toString().replace('.', ''));
+    arg2 = Number(arg2.toString().replace('.', ''));
+  }
+  return (arg1 * arg2) / m;
+};
+
+//相除
+export const accDiv = function accDiv(arg1: number, arg2: number): number {
+  var t1 = 0,
+    t2 = 0,
+    r1,
+    r2;
+  try {
+    t1 = arg1.toString().split('.')[1].length;
+  } catch (e) {}
+  try {
+    t2 = arg2.toString().split('.')[1].length;
+  } catch (e) {}
+  r1 = Number(arg1.toString().replace('.', ''));
+  r2 = Number(arg2.toString().replace('.', ''));
+  return (r1 / r2) * Math.pow(10, t2 - t1);
+}

+ 8 - 1
server/db/schemas/EduProcess.js

@@ -45,7 +45,14 @@ export const EduProcess = {
       "type": "Date",
       "required": false
     },
-    "status": {//状态 100:暂停 200:已开始 300:已公示 400:已提交(完成)
+    /**@状态
+     * 100:暂停
+     * 200:已开始
+     * 201:评审中
+     * 300:已公示
+     * 400:已提交(完成)
+    */
+    "status": {
       "type": "String",
       "required": false
     },

+ 4 - 0
server/db/schemas/EduTextbook.js

@@ -265,6 +265,10 @@ export const EduTextbook = {
             "type":'Array',
             "required": false  
         },
+        'score':{//平均分
+            "type":'Number',
+            "required": false  
+        },
     },
     "classLevelPermissions": {
         "find": {