Browse Source

评审端

cehn 8 months ago
parent
commit
d10cd3119a

+ 73 - 8
projects/textbook/src/app/textbook/textbook.component.html

@@ -28,9 +28,9 @@
     [nzLoading]="loading"
     nzSize="middle"
     [nzFrontPagination]="false"
-    [nzScroll]="{ x: (maxWidth || '1200') + 'px',y: '580px' }"
+    [nzScroll]="{ x: (maxWidth || '1200') + 'px', y: '580px' }"
     nzTableLayout="fixed"
-    [nzPageSizeOptions]="[ 10, 20, 30, 40, 50 ]"
+    [nzPageSizeOptions]="[10, 20, 30, 40, 50]"
     nzShowSizeChanger
     (nzPageIndexChange)="pageIndexChange($event)"
     (nzPageSizeChange)="onPageSizeChange($event)"
@@ -108,6 +108,12 @@
         >
           申报部门
         </th>
+        @if (filterObj.btns.eduReivew) {
+        @if (filterObj.btns?.mark) {
+          <th nzEllipsis nzWidth="80px" nzRight>评审状态</th>
+        }
+        <th nzEllipsis nzWidth="80px" nzRight>评审分值</th>
+        }
         <th nzEllipsis nzWidth="50px" nzRight>操作</th>
       </tr>
     </thead>
@@ -256,6 +262,22 @@
             </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>
+        }
+        <td nzEllipsis [nzAlign]="'right'" nzRight>
+          {{ scoreMap[data.id]?.score ?? "-" }}
+        </td>
+        }
         <td nzEllipsis nzRight>
           @if(manage){
           <button
@@ -268,7 +290,29 @@
           </button>
           <nz-dropdown-menu #menu="nzDropdownMenu">
             <ul nz-menu>
-              @if(filterObj.btns.edit){
+              @if(filterObj.btns.eduReivew){
+              <li nz-menu-item>
+                <button
+                  (click)="onlinePreview(data.id)"
+                  nz-button
+                  nzType="link"
+                  style="color: #231c1f"
+                >
+                  <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){
               <li nz-menu-item>
                 <button
                   (click)="toUrl('/nav-author/manage/apply', { id: data.id })"
@@ -519,7 +563,12 @@
             </div>
           </ng-template>
         </td>
-        <td nzEllipsis nz-popover [nzPopoverContent]="contentTemplateauthor" #author>
+        <td
+          nzEllipsis
+          nz-popover
+          [nzPopoverContent]="contentTemplateauthor"
+          #author
+        >
           {{ fromatFiled(data?.get("childrens"), "author") }}
           <ng-template #contentTemplateauthor>
             <div style="max-width: 400px">
@@ -527,7 +576,12 @@
             </div>
           </ng-template>
         </td>
-        <td nzEllipsis nz-popover [nzPopoverContent]="contentTemplateunit" #unit>
+        <td
+          nzEllipsis
+          nz-popover
+          [nzPopoverContent]="contentTemplateunit"
+          #unit
+        >
           {{ fromatFiled(data?.get("childrens"), "unit") }}
           <ng-template #contentTemplateunit>
             <div style="max-width: 400px">
@@ -543,7 +597,12 @@
             </div>
           </ng-template>
         </td>
-        <td nzEllipsis nz-popover [nzPopoverContent]="contentTemplatelang" #lang>
+        <td
+          nzEllipsis
+          nz-popover
+          [nzPopoverContent]="contentTemplatelang"
+          #lang
+        >
           {{ fromatFiled(data?.get("childrens"), "lang") }}
           <ng-template #contentTemplatelang>
             <div style="max-width: 400px">
@@ -551,7 +610,12 @@
             </div>
           </ng-template>
         </td>
-        <td nzEllipsis nz-popover [nzPopoverContent]="contentTemplateISBN" #ISBN>
+        <td
+          nzEllipsis
+          nz-popover
+          [nzPopoverContent]="contentTemplateISBN"
+          #ISBN
+        >
           {{ fromatFiled(data?.get("childrens"), "ISBN") }}
           <ng-template #contentTemplateISBN>
             <div style="max-width: 400px">
@@ -559,7 +623,8 @@
             </div>
           </ng-template>
         </td>
-        <td nzEllipsis
+        <td
+          nzEllipsis
           nz-popover
           [nzPopoverContent]="contentTemplateeditionUnit"
           #editionUnit

+ 130 - 79
projects/textbook/src/app/textbook/textbook.component.ts

@@ -31,7 +31,8 @@ interface filter {
     MatButtonModule,
     NzRadioModule,
     DatePipe,
-    NzEmptyModule,NzPopoverModule
+    NzEmptyModule,
+    NzPopoverModule,
   ],
   standalone: true,
   providers: [DatePipe],
@@ -50,6 +51,7 @@ export class TextbookComponent implements OnInit {
   @Input('discard') discard: Boolean = false; //是否删除
   @Input('eduProcess') eduProcess?: Parse.Object; //流程id,verify存在时需要
   @Output() updateCheck: EventEmitter<any> = new EventEmitter<any>();
+  @Output() markScore: EventEmitter<any> = new EventEmitter<any>();
 
   //相关权限配置
   @Input('filterObj') filterObj: any = {
@@ -58,11 +60,9 @@ export class TextbookComponent implements OnInit {
     isCheck: true,
     noStared: false, //非推荐
     team: false, //只获取当前部门或下级部门所属用户的教材,且不限制是否提交
-    showText:false, //选择后不展示定位btns,只展示相关教材名称列表
-    notContained:[],//不包含教材(查询时自动排除)
-    eduReivew:{ //评审相关
-
-    },
+    showText: false, //选择后不展示定位btns,只展示相关教材名称列表
+    notContained: [], //不包含教材(查询时自动排除)
+    contained:[], //包含查询(查询只获取在数组内的id)
     btns: {
       edit: false, //编辑
       isDelete: false, //删除权限
@@ -72,11 +72,15 @@ export class TextbookComponent implements OnInit {
       remove: false, //移除推荐
       submit: false, //提交
       beforSubmit: false, //高校联系人提交至工作联系人
-      export: false,//导出附件
+      export: false, //导出附件
       verify: false, //提交推荐权限
       restore: false, //恢复教材
+      eduReivew: false, //在线预览
+      mark: false, //打分
     },
   };
+  @Input('scoreMap') scoreMap:any = {} //评分状态
+
   listOfColumns: any = {
     lang: {
       listOfFilter: [
@@ -169,23 +173,26 @@ export class TextbookComponent implements OnInit {
 
   showLoading: boolean = false; //全局
   /* 格式化拓展表字段 */
-  fromatFiled(list:Array<Parse.Object>, filed:string):string{
-    let arr:Array<string|null> = []
-    let isDate = false
-    list.forEach((item:Parse.Object)=>{
+  fromatFiled(list: Array<Parse.Object>, filed: string): string {
+    let arr: Array<string | null> = [];
+    let isDate = false;
+    list.forEach((item: Parse.Object) => {
       // arr.add(item.get(filed))
-     if(isDate || Object.prototype.toString.call(item.get(filed)).indexOf('Date') != -1){
-        arr.push(this.datePipe.transform(item.get(filed), 'yyyy-MM'))
-        isDate = true
-      }else{
-        arr.push(item.get(filed))
+      if (
+        isDate ||
+        Object.prototype.toString.call(item.get(filed)).indexOf('Date') != -1
+      ) {
+        arr.push(this.datePipe.transform(item.get(filed), 'yyyy-MM'));
+        isDate = true;
+      } else {
+        arr.push(item.get(filed));
       }
-    })
-    let j = Array.from(arr).join(',')
-    if(!isDate){
-      j = Array.from(new Set(arr)).join(' ')
+    });
+    let j = Array.from(arr).join(',');
+    if (!isDate) {
+      j = Array.from(new Set(arr)).join(' ');
     }
-    return j || '-'
+    return j || '-';
   }
 
   constructor(
@@ -200,9 +207,10 @@ export class TextbookComponent implements OnInit {
   ngOnInit() {
     this.activeRoute.paramMap.subscribe(async (params) => {
       // this.eduProcessId = params.get('id');
-       Object.keys(this.filterObj?.btns).forEach((key)=> {
-        if(this.filterObj[key] && key != 'review' && key != 'verify') this.calc += 70;
-      })
+      let arr = ['review', 'verify', 'eduReivew', 'mark'];
+      Object.keys(this.filterObj?.btns).forEach((key) => {
+        if (this.filterObj[key] && !arr.includes(key)) this.calc += 70;
+      });
       this.getTextbook();
       if (Object.values(this.filterObj?.btns).some((item) => item)) {
         this.manage = true;
@@ -221,9 +229,12 @@ export class TextbookComponent implements OnInit {
       }
     });
   }
-  async getTextbook(val?: string, exported?:{excel:boolean, id:boolean}): Promise<any[] | void> {
+  async getTextbook(
+    val?: string,
+    exported?: { excel: boolean; id: boolean }
+  ): Promise<any[] | void> {
     this.loading = true;
-    let queryParams:any = {
+    let queryParams: any = {
       where: {
         $or: [
           {
@@ -233,49 +244,56 @@ export class TextbookComponent implements OnInit {
             childrens: {
               $inQuery: {
                 where: {
-                  "$or": [
+                  $or: [
                     {
                       ISBN: { $regex: `.*${val || ''}.*` },
                     },
                     {
                       author: { $regex: `.*${val || ''}.*` },
                     },
-                  ]
+                  ],
                 },
                 className: 'EduTextbookVolume',
               },
             },
-          }
+          },
         ],
       },
-    }
+    };
     let query1 = Parse.Query.fromJSON('EduTextbook', queryParams);
     let query = Parse.Query.or(query1);
-    let queryParams2:any = {
-      where: {}
-    }
+    let queryParams2: any = {
+      where: {},
+    };
     for (const key in this.filters) {
       const element = this.filters[key];
       if (element.value?.length > 0 && element.type == 'EduTextbookVolume') {
-        if(!queryParams2['where']['childrens']){
-          queryParams2['where']['childrens']= {
-            '$inQuery':{
-              'where': {
-                  [key]: { $in: element.value }
+        if (!queryParams2['where']['childrens']) {
+          queryParams2['where']['childrens'] = {
+            $inQuery: {
+              where: {
+                [key]: { $in: element.value },
               },
               className: 'EduTextbookVolume',
-            }
-          }
-        }else{
-          queryParams2['where']['childrens']['$inQuery']['where'][key] = { $in: element.value }
+            },
+          };
+        } else {
+          queryParams2['where']['childrens']['$inQuery']['where'][key] = {
+            $in: element.value,
+          };
         }
-      }else if(element.value?.length > 0 && element.type == 'EduTextbook'){
-          queryParams2['where'][key] = { $in: element.value }
+      } else if (element.value?.length > 0 && element.type == 'EduTextbook') {
+        queryParams2['where'][key] = { $in: element.value };
       }
     }
-    let vrifly = Object.keys(queryParams2['where']).some(item=> Object.values(item).length > 0)
-    if(vrifly){
-      query = Parse.Query.and(Parse.Query.fromJSON('EduTextbook', queryParams2), query);
+    let vrifly = Object.keys(queryParams2['where']).some(
+      (item) => Object.values(item).length > 0
+    );
+    if (vrifly) {
+      query = Parse.Query.and(
+        Parse.Query.fromJSON('EduTextbook', queryParams2),
+        query
+      );
     }
     if (this.filterObj.team) {
       let childrens = await this.tbookSer.getChild(
@@ -297,9 +315,13 @@ export class TextbookComponent implements OnInit {
           ],
         },
       });
-      if(vrifly){
-        query = Parse.Query.and(query3, Parse.Query.fromJSON('EduTextbook', queryParams2), query);
-      }else{
+      if (vrifly) {
+        query = Parse.Query.and(
+          query3,
+          Parse.Query.fromJSON('EduTextbook', queryParams2),
+          query
+        );
+      } else {
         query = Parse.Query.and(query3, query);
       }
     }
@@ -308,7 +330,9 @@ export class TextbookComponent implements OnInit {
     this.recommend && query.equalTo('recommend', true);
     this.filterObj?.noStared && query.notEqualTo('recommend', true);
     this.uid && query.equalTo('user', this.uid);
-    this.filterObj?.notContained && query.notContainedIn('objectId', this.filterObj.notContained);
+    this.filterObj?.notContained &&
+      query.notContainedIn('objectId', this.filterObj.notContained);
+    this.filterObj?.contained && query.containedIn('objectId', this.filterObj.contained);
     query.descending('createdAt');
     query.notEqualTo('isDeleted', true);
     if (!this.uid && !this.filterObj.team) {
@@ -324,21 +348,23 @@ export class TextbookComponent implements OnInit {
     }
     if (exported?.excel) {
       query.limit(1000);
-      if(exported?.id){
-        query.select('objectId')
+      if (exported?.id) {
+        query.select('objectId');
       }
       let r = await query.find();
       this.loading = false;
       return r;
     }
-    query.include('department','childrens');
+    query.include('department', 'childrens');
     this.count = await query.count();
     query.limit(this.limit);
     query.skip(this.limit * (this.pageIndex - 1));
     // query.include('user')
     this.textbookList = await query.find();
     console.log(this.textbookList);
-    this.checkedAll = this.textbookList.every(item=> this.setOfCheckedId.has(item.id))
+    this.checkedAll = this.textbookList.every((item) =>
+      this.setOfCheckedId.has(item.id)
+    );
     this.loading = false;
   }
   async getDepartment(all?: boolean): Promise<any> {
@@ -388,11 +414,11 @@ export class TextbookComponent implements OnInit {
     this.getTextbook(this.searchValue);
   }
   //切换分页条数
-  onPageSizeChange($event:any): void {
+  onPageSizeChange($event: any): void {
     console.log(this.limit);
     // this.onAllChecked(false)
-    this.pageIndex = 1
-    this.getTextbook()
+    this.pageIndex = 1;
+    this.getTextbook();
   }
   //全选
   onAllChecked(checked: boolean) {
@@ -408,7 +434,7 @@ export class TextbookComponent implements OnInit {
       this.setOfCheckedId = new Set<string>();
     }
     this.checkedAll = checked;
-    this.updateCheck.emit() //选项变更触发传递事件父组建
+    this.updateCheck.emit(); //选项变更触发传递事件父组建
   }
   //单选
   onItemChecked(id: string, e: boolean) {
@@ -420,7 +446,7 @@ export class TextbookComponent implements OnInit {
     this.checkedAll = this.textbookList.every((item) =>
       this.setOfCheckedId.has(item.id)
     );
-    this.updateCheck.emit() //选项变更触发传递事件父组建
+    this.updateCheck.emit(); //选项变更触发传递事件父组建
   }
   //退回
   reject(data?: Parse.Object) {
@@ -575,10 +601,10 @@ export class TextbookComponent implements OnInit {
             this.message.warning('教材信息填写不完整');
             return;
           }
-          if(!data?.get('code')){
+          if (!data?.get('code')) {
             let t =
-            this.tbookSer.formatTime('YYYYmmdd', new Date()) +
-            Math.random().toString().slice(-4);
+              this.tbookSer.formatTime('YYYYmmdd', new Date()) +
+              Math.random().toString().slice(-4);
             data.set('code', t);
           }
           data.set('render', true);
@@ -610,10 +636,10 @@ export class TextbookComponent implements OnInit {
                 item?.get('status') == '300'
               ) {
                 count++;
-                if(!item?.get('code')){
+                if (!item?.get('code')) {
                   let t =
-                  this.tbookSer.formatTime('YYYYmmdd', new Date()) +
-                  Math.random().toString().slice(-4);
+                    this.tbookSer.formatTime('YYYYmmdd', new Date()) +
+                    Math.random().toString().slice(-4);
                   item.set('code', t);
                 }
                 item.set('render', true);
@@ -677,7 +703,7 @@ export class TextbookComponent implements OnInit {
         if (data?.id) {
           data.set('status', '200');
           await data.save();
-          this.message.success('提交成功')
+          this.message.success('提交成功');
         } else {
           let count = 0,
             failCount = 0;
@@ -801,6 +827,22 @@ export class TextbookComponent implements OnInit {
       this.showLoading = false;
     }
   }
+  //在线预览
+  async onlinePreview(id: string) {
+    if(this.loading) return
+    this.loading = true
+    await this.tbookSer.preview({ bookid: id });
+    this.loading = false
+  }
+  //打分
+  onMarking(id:string){
+    let pid = this.tbookSer.profile?.objectId
+    if(!pid){
+      this.message.error('当前登录身份已过期,请重新登录')
+      return
+    }
+    this.markScore.emit(id)
+  }
   toUrl(url: string, param?: Object) {
     console.log(url);
     if (param) {
@@ -850,14 +892,14 @@ export class TextbookComponent implements OnInit {
   async export() {
     if (this.showLoading) return;
     this.showLoading = true;
-    try{
+    try {
       console.log(this.eduProcess);
       let query = new Parse.Query('EduProcess');
       query.equalTo('objectId', this.eduProcess?.id);
       query.include('profileSubmitted', 'profileSubmitted.user');
       query.select('name', 'profileSubmitted');
       let r = await query.first();
-      let data: any = await this.getTextbook('',{excel:true, id:false});
+      let data: any = await this.getTextbook('', { excel: true, id: false });
       let table = `<table border="1px" cellspacing="0" cellpadding="0">
           <thead>
           <tr>
@@ -874,7 +916,9 @@ export class TextbookComponent implements OnInit {
               <tr>
                   <th></th><th></th>
                   <th style="font-size: 12px;font-family: '黑体';text-align: left;">单位名称(公章):</th>
-                  <th colspan="3" style="font-size: 12px;font-family: '黑体';text-align: left;">${r?.get('name')}</th>
+                  <th colspan="3" style="font-size: 12px;font-family: '黑体';text-align: left;">${r?.get(
+                    'name'
+                  )}</th>
                   <th></th><th></th><th></th>
               </tr>
               <tr>
@@ -940,7 +984,7 @@ export class TextbookComponent implements OnInit {
         _body += `${
           data[row]?.get('type') == '单本'
             ? '单本'
-            :'全册 - ' + data[row]?.get('typeNumber') || '-'
+            : '全册 - ' + data[row]?.get('typeNumber') || '-'
         }`;
         _body += '</td>';
 
@@ -949,17 +993,24 @@ export class TextbookComponent implements OnInit {
         _body += '</td>';
 
         _body += '<td>';
-        _body += `${this.fromatFiled(data[row]?.get('childrens'), 'editionUnit')}`;
+        _body += `${this.fromatFiled(
+          data[row]?.get('childrens'),
+          'editionUnit'
+        )}`;
         _body += '</td>';
 
         _body += '<td>';
-        _body += `&nbsp;${
-          this.fromatFiled(data[row]?.get('childrens'), 'editionFirst')
-        }`;
+        _body += `&nbsp;${this.fromatFiled(
+          data[row]?.get('childrens'),
+          'editionFirst'
+        )}`;
         _body += '</td>';
 
         _body += '<td>';
-        _body += `${this.fromatFiled(data[row]?.get('childrens'), 'carrierShape')}`;
+        _body += `${this.fromatFiled(
+          data[row]?.get('childrens'),
+          'carrierShape'
+        )}`;
         _body += '</td>';
 
         _body += '</tr>';
@@ -970,9 +1021,9 @@ export class TextbookComponent implements OnInit {
       let title = '推荐汇总表';
       this.excel(table, `${title}.xls`);
       this.showLoading = false;
-    }catch(err){
-      this.showLoading = false
-      this.message.error('导出超时')
+    } catch (err) {
+      this.showLoading = false;
+      this.message.error('导出超时');
     }
   }
   excel(data: any, filename: string) {

+ 63 - 14
projects/textbook/src/modules/nav-review/approve/approve.component.html

@@ -1,32 +1,81 @@
 <nz-page-header>
   <!--title-->
   <nz-page-header-title
-    >全部教材<nz-tag style="margin-left: 10px;" [nzColor]="'blue'">
-      评审中</nz-tag
-    >
+    >{{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>
+    }
+
     <br />
-    <div class="subtitle">
-      查看全部申报流程所提交的教材推荐表
-    </div>
+    <div class="subtitle">查看全部申报流程所提交的教材推荐表</div>
   </nz-page-header-title>
 </nz-page-header>
 
 <div class="conetent">
-  <nz-tabset [(nzSelectedIndex)]="active">
-    <nz-tab nzTitle="待评审教材">
-      @if (!active) {
-        <app-textbook
+  <nz-tabset
+    [nzSelectedIndex]="active"
+    (nzSelectedIndexChange)="onSelectChange($event)"
+  >
+    <nz-tab nzTitle="教材列表">
+      @if (!active && showText) {
+      <app-textbook
+        (markScore)="onMarkScore($event)"
         [filterObj]="beforeFilterObj"
+        [scoreMap]="scoreMap"
+        #textbook
       ></app-textbook>
       }
     </nz-tab>
-    <nz-tab nzTitle="推荐教材">
+    <nz-tab nzTitle="评审明细">
       @if (active) {
-        <!-- <app-textbook
+      <app-textbook
         [filterObj]="afterFilterObj"
-        [recommend]="true"
-        ></app-textbook> -->
+        [scoreMap]="scoreMap"
+      ></app-textbook>
       }
     </nz-tab>
   </nz-tabset>
 </div>
+
+<!-- 评分 -->
+<nz-modal
+  [(nzVisible)]="mrakVisible"
+  nzTitle="填写评审打分"
+  (nzOnCancel)="handleCancel()"
+  nzWidth="400px"
+  nzCentered
+>
+  <ng-container *nzModalContent>
+    <div nz-row class="modal">
+      <div class="proview-pdf"></div>
+      <div class="modal-title">分值</div>
+      <nz-input-group style="width: 100%" nzSuffix="/100">
+        <nz-input-number
+          style="width: 100%"
+          [nzPrecision]="2"
+          [nzStep]="0.01"
+          [nzMin]="0"
+          [nzMax]="100"
+          nzBorderless
+          [(ngModel)]="score"
+          nzPlaceHolder="请输入整数分值"
+        ></nz-input-number>
+      </nz-input-group>
+    </div>
+  </ng-container>
+  <div *nzModalFooter>
+    <button nz-button nzType="default" (click)="handleCancel()">取消</button>
+    <button nz-button nzType="default" (click)="saveScore('submit')">
+      提交
+    </button>
+    <button
+      nz-button
+      nzType="primary"
+      style="background: #3e49b3; border: 1px #3e49b3"
+      (click)="saveScore('save')"
+    >
+      保存
+    </button>
+  </div>
+</nz-modal>

+ 190 - 9
projects/textbook/src/modules/nav-review/approve/approve.component.ts

@@ -12,6 +12,8 @@ import { NzSpaceModule } from 'ng-zorro-antd/space';
 import { CommonCompModule } from '../../../services/common.modules';
 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';
 @Component({
   selector: 'app-approve',
   imports: [
@@ -24,6 +26,7 @@ import { NzMessageService } from 'ng-zorro-antd/message';
     NzBreadCrumbModule,
     NzSpaceModule,
     NzTabsModule,
+    NzInputNumberModule,
   ],
   standalone: true,
   templateUrl: './approve.component.html',
@@ -31,34 +34,212 @@ import { NzMessageService } from 'ng-zorro-antd/message';
 })
 export class ApproveComponent implements OnInit {
   // @ViewChild(CompTableListComponent) list: CompTableListComponent | undefined;
+  @ViewChild('textbook') textbook: TextbookComponent | any;
+  eduProcess?:Parse.Object
+
   active: number = 0;
   user: Parse.User | undefined;
 
-  //待审核
+  //待评分
   beforeFilterObj: any = {
     showMore: true, //显示更多字段
     isCheck: true,
-    noStared: true,
     status: ['200'],
+    contained: [],
     btns: {
-      review:true,
       export: true,
+      eduReivew: true,
+      mark: true,
     },
   };
-  //已加入推荐
+  //已评审
   afterFilterObj: any = {
     showMore: true, //显示更多字段
-    isCheck: true,
-    status: ['200', '201', '400'],
+    isCheck: false,
+    status: ['200'],
+    contained: [],
     btns: {
-      review:true,
+      eduReivew: true,
       export: true,
     },
   };
+  showText: boolean = false;
+  mrakVisible: boolean = false;
+  editTextbook: string | any; //评分教材
+  eduReview?: Parse.Object; //评审记录
+  score?: number; //填写评分
+  scoreMap: any = {};
+  activity?: Parse.Object
 
-  constructor() {
+  constructor(
+    private message: NzMessageService,
+    public tbookSer: textbookServer,
+    private modal: NzModalService
+  ) {
     this.user = Parse.User.current();
   }
 
-  ngOnInit() {}
+  async ngOnInit() {
+    await this.getEduReview();
+    await this.getExpertGroup();
+    this.getActivity()
+  }
+  //获取评审记录
+  async getEduReview() {
+    let query = new Parse.Query('EduReview');
+    query.notEqualTo('isDeleted', true);
+    query.equalTo('profile', this.tbookSer.profile?.objectId);
+    query.select('score', 'num', 'verify', 'eduTextbook');
+    query.limit(1000);
+    let r = await query.find();
+    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') ?? '-',
+      };
+    });
+    console.log(this.scoreMap);
+  }
+  async getExpertGroup() {
+    let query = new Parse.Query('ExpertGroup');
+    query.notEqualTo('isDeleted', true);
+    query.containedIn('reviewList', [
+      {
+        __type: 'Pointer',
+        className: 'Profile',
+        objectId: this.tbookSer.profile?.objectId,
+      },
+    ]);
+    query.include('eduProcess')
+    query.select('textbookList', 'reviewDetails','eduProcess');
+    let r = await query.find();
+    console.log(r);
+    r.forEach((item) => {
+      item.get('textbookList')?.forEach((obj: any) => {
+        this.beforeFilterObj.contained.push(obj.id || obj.objectId);
+      });
+    });
+    this.beforeFilterObj.contained;
+    this.showText = true;
+    this.eduProcess = r[0]?.get('eduProcess')
+  }
+  async getActivity(){
+    let query = new Parse.Query('Activity')
+    query.notEqualTo('isDeleted', true)
+    query.equalTo('eduProcess', this.eduProcess?.id)
+    this.activity = await query.first()
+  }
+  //切换tab
+  async onSelectChange(e: number) {
+    console.log(e);
+    switch (e) {
+      case 1:
+        this.afterFilterObj.contained = [];
+        let query = new Parse.Query('EduReview');
+        query.notEqualTo('isDeleted', true);
+        query.equalTo('profile', this.tbookSer.profile?.objectId);
+        query.equalTo('verify', true);
+        query.select('eduTextbook');
+        let r = await query.find();
+        console.log(r);
+        r.forEach((item) => {
+          console.log(item?.get('eduTextbook')?.id);
+          this.afterFilterObj.contained.push(
+            item?.get('eduTextbook')?.id || item?.get('eduTextbook')?.objectId
+          );
+        });
+        console.log(this.afterFilterObj.contained);
+
+        break;
+
+      default:
+        await this.getEduReview();
+        break;
+    }
+    this.active = e;
+  }
+  async onMarkScore(e: any) {
+    console.log(e);
+    let query = new Parse.Query('EduReview');
+    query.notEqualTo('isDeleted', true);
+    query.equalTo('eduTextbook', e);
+    this.eduReview = await query.first();
+    if (!this.eduReview?.id) {
+      let obj = Parse.Object.extend('EduReview');
+      this.eduReview = new obj();
+    }
+    this.editTextbook = e;
+    this.score = this.eduReview?.get('score') ?? this.eduReview?.get('num');
+    this.mrakVisible = true;
+  }
+  handleCancel() {
+    this.mrakVisible = false;
+    this.eduReview = undefined;
+    this.editTextbook = undefined;
+    this.score = undefined;
+  }
+  /* 保存/提交评分 */
+  async saveScore(type: string) {
+    if (!this.score && this.score != 0) {
+      this.message.warning('请填写分数');
+      return;
+    }
+    if (type == 'submit') {
+      this.modal.confirm({
+        nzTitle: '确认提交打分?',
+        nzContent: `提交后将不能再修改`,
+        nzOkText: '确认',
+        nzOkType: 'primary',
+        nzOkDanger: true,
+        nzOnOk: async () => {
+          this.eduReview?.set('score', this.score);
+          this.eduReview?.set('eduTextbook', {
+            __type: 'Pointer',
+            className: 'EduTextbook',
+            objectId: this.editTextbook,
+          });
+          this.eduReview?.set('profile', {
+            __type: 'Pointer',
+            className: 'Profile',
+            objectId: this.tbookSer.profile?.objectId,
+          });
+          this.eduReview?.set('verify', true);
+          await this.eduReview?.save();
+          this.message.success('提交成功');
+          this.textbook.scoreMap[this.editTextbook] = {
+            status: 'complete',
+            score: this.eduReview?.get('score'),
+          };
+          this.scoreMap = this.textbook.scoreMap;
+          this.handleCancel();
+        },
+        nzCancelText: '取消',
+        nzOnCancel: () => console.log('Cancel'),
+      });
+    } else {
+      this.eduReview?.set('num', this.score);
+      this.eduReview?.set('eduTextbook', {
+        __type: 'Pointer',
+        className: 'EduTextbook',
+        objectId: this.editTextbook,
+      });
+      this.eduReview?.set('profile', {
+        __type: 'Pointer',
+        className: 'Profile',
+        objectId: this.tbookSer.profile?.objectId,
+      });
+      await this.eduReview?.save();
+      this.message.success('保存成功');
+      this.textbook.scoreMap[this.editTextbook] = {
+        status: 'save',
+        score: this.eduReview?.get('num'),
+      };
+      this.scoreMap = this.textbook.scoreMap;
+      this.handleCancel();
+    }
+  }
 }

+ 15 - 0
projects/textbook/src/services/textbook.ts

@@ -147,6 +147,21 @@ export class textbookServer {
       document.body.removeChild(a); // 下载后移除&lt;a&gt;元素
     });
   }
+  async preview(options:{bookid:string}){
+    let url = Parse.serverURL + '/api/tbook/preview';
+    let response = await fetch(url, {
+      method: 'POST',
+      headers: {
+        'Content-Type': 'application/json',
+        'X-Parse-Application-Id': 'edu-textbook',
+      },
+      body: JSON.stringify(options),
+    });
+    let result = await response.json();
+    let { urlPdf } = result?.data
+    console.log(urlPdf);
+    window.open(urlPdf)
+  }
 
   async getEduProcess(id: string): Promise<string | undefined> {
     if (!id) return;