Browse Source

update admin

warrior 7 months ago
parent
commit
b52303e192
33 changed files with 970 additions and 101 deletions
  1. 175 24
      projects/textbook/src/app/textbook/textbook.component.html
  2. 16 0
      projects/textbook/src/app/textbook/textbook.component.scss
  3. 162 28
      projects/textbook/src/app/textbook/textbook.component.ts
  4. 1 2
      projects/textbook/src/modules/nav-admin/page-process/process-create/process-create.component.html
  5. 3 2
      projects/textbook/src/modules/nav-admin/page-process/process-create/process-create.component.ts
  6. 23 18
      projects/textbook/src/modules/nav-admin/user-edit/user-edit.component.html
  7. 4 0
      projects/textbook/src/modules/nav-admin/user-edit/user-edit.component.ts
  8. 1 1
      projects/textbook/src/modules/nav-author/recycle/recycle.component.html
  9. 9 3
      projects/textbook/src/modules/nav-author/space/space.component.html
  10. 15 1
      projects/textbook/src/modules/nav-author/space/space.component.ts
  11. 5 0
      projects/textbook/src/modules/nav-province-contact/modules.routes.ts
  12. 18 7
      projects/textbook/src/modules/nav-province-contact/page-process/page-process.component.html
  13. 19 0
      projects/textbook/src/modules/nav-province-contact/page-process/page-process.component.ts
  14. 12 12
      projects/textbook/src/modules/nav-province-contact/page-role/page-role.component.html
  15. 1 1
      projects/textbook/src/modules/nav-province-contact/page-textbook/page-textbook.component.html
  16. 3 1
      projects/textbook/src/modules/nav-province-contact/page-textbook/page-textbook.component.ts
  17. 15 0
      projects/textbook/src/modules/nav-province-contact/submitted/complete/complete.component.html
  18. 21 0
      projects/textbook/src/modules/nav-province-contact/submitted/complete/complete.component.scss
  19. 24 0
      projects/textbook/src/modules/nav-province-contact/submitted/complete/complete.component.spec.ts
  20. 42 0
      projects/textbook/src/modules/nav-province-contact/submitted/complete/complete.component.ts
  21. 30 0
      projects/textbook/src/modules/nav-province-contact/submitted/export-file/export-file.component.html
  22. 35 0
      projects/textbook/src/modules/nav-province-contact/submitted/export-file/export-file.component.scss
  23. 24 0
      projects/textbook/src/modules/nav-province-contact/submitted/export-file/export-file.component.spec.ts
  24. 49 0
      projects/textbook/src/modules/nav-province-contact/submitted/export-file/export-file.component.ts
  25. 11 0
      projects/textbook/src/modules/nav-province-contact/submitted/export-list/export-list.component.html
  26. 21 0
      projects/textbook/src/modules/nav-province-contact/submitted/export-list/export-list.component.scss
  27. 24 0
      projects/textbook/src/modules/nav-province-contact/submitted/export-list/export-list.component.spec.ts
  28. 30 0
      projects/textbook/src/modules/nav-province-contact/submitted/export-list/export-list.component.ts
  29. 34 0
      projects/textbook/src/modules/nav-province-contact/submitted/submitted.component.html
  30. 65 0
      projects/textbook/src/modules/nav-province-contact/submitted/submitted.component.scss
  31. 24 0
      projects/textbook/src/modules/nav-province-contact/submitted/submitted.component.spec.ts
  32. 48 0
      projects/textbook/src/modules/nav-province-contact/submitted/submitted.component.ts
  33. 6 1
      server/db/schemas/EduTextbook.js

+ 175 - 24
projects/textbook/src/app/textbook/textbook.component.html

@@ -14,20 +14,28 @@
         ><span nz-icon nzType="search"></span
       ></ng-template>
     </div>
+    @if (filterObj?.btns?.verify && count != 0) {
+      <div class="sbt" (click)="toUrl('/nav-province-contact/manage/submitted/'+eduProcessId)">
+        提交推荐教材列表
+      </div>
+    }
   </div>
   <nz-table
     #tableData
     [nzData]="textbookList"
-    [nzTotal]="textbookList.length"
-    [nzPageSize]="10"
+    [nzTotal]="count"
+    [nzPageSize]="limit"
+    [nzPageIndex]="pageSize"
     style="margin: 10px 0"
     [nzLoading]="loading"
     nzSize="middle"
-    [nzNoResult]="emptyResult"
+    [nzFrontPagination]="false"
+    [nzScroll]="{ x: (maxWidth || '1200') + 'px' }"
     nzTableLayout="fixed"
   >
     <thead>
       <tr>
+        @if (filterObj.isCheck) {
         <th
           nzWidth="50px"
           nzLeft
@@ -36,34 +44,46 @@
           nzLabel="Select all"
           (nzCheckedChange)="onAllChecked($event)"
         ></th>
-        <th nzEllipsis nzWidth="50px" nzLeft>申报编号</th>
+        <th nzEllipsis nzWidth="80px">申报编号</th>
+        }@else {
+        <th nzEllipsis nzWidth="80px" nzLeft>申报编号</th>
+        }
         <th nzEllipsis nzWidth="120px">教材名称</th>
         <th nzEllipsis nzWidth="50px">册数</th>
-        <th nzEllipsis nzWidth="80px">第一主编/作者</th>
+        <th nzEllipsis nzWidth="120px">第一主编/作者</th>
+        <th nzEllipsis nzWidth="80px">所属单位</th>
         <th nzEllipsis nzWidth="120px">所属本科专业</th>
         <th nzEllipsis nzWidth="80px">主要语种类型</th>
+        <th nzEllipsis nzWidth="80px">ISBN</th>
+        <th nzEllipsis nzWidth="120px">出版单位</th>
         <th nzEllipsis nzWidth="50px" nzRight>操作</th>
       </tr>
     </thead>
+    @if (textbookList.length > 0) {
     <tbody>
       @for (data of textbookList; track data.id) {
       <tr>
+        @if (filterObj.isCheck) {
         <td
           nzEllipsis
           nzLeft
           [nzChecked]="setOfCheckedId.has(data.id)"
           (nzCheckedChange)="onItemChecked(data.id, $event)"
         ></td>
+        <td nzEllipsis class="activeTd" (click)="toUrl(path + '/' + data.id)">
+          {{ $index + 1 }}
+        </td>
+        }@else {
         <td
           nzEllipsis
           nzLeft
-          nzEllipsis
-          class="activeTd"
-          (click)="toUrl(path + '/' + data.id)"
         >
-          {{ data?.get("ISBN") || "-" }}
+          {{ $index + 1 }}
         </td>
-        <td nzEllipsis>
+        }
+        <td nzEllipsis 
+        class="activeTd"
+        (click)="toUrl(path + '/' + data.id)">
           {{ data?.get("title") || "-" }}
         </td>
         <td nzEllipsis>
@@ -76,15 +96,24 @@
         <td nzEllipsis>
           {{ data?.get("author") || "-" }}
         </td>
+        <td nzEllipsis>
+          {{ data?.get("unit") || "-" }}
+        </td>
         <td nzEllipsis>
           {{ data?.get("major").name || "-" }}
         </td>
         <td nzEllipsis>
           {{ data?.get("lang") || "-" }}
         </td>
-        <td nzEllipsis nzRight>
-          @if(data?.get('status') == '200'){
 
+        <td nzEllipsis>
+          {{ data?.get("ISBN") || "-" }}
+        </td>
+        <td nzEllipsis>
+          {{ data?.get("editionUnit") || "-" }}
+        </td>
+        <td nzEllipsis nzRight>
+          @if(manage){
           <button
             nz-button
             nz-dropdown
@@ -95,47 +124,169 @@
           </button>
           <nz-dropdown-menu #menu="nzDropdownMenu">
             <ul nz-menu>
+              @if(filterObj.btns.edit){
               <li nz-menu-item>
-                <button nz-button nzType="link" style="color: #231c1f">
+                <button
+                  (click)="toUrl('/nav-author/manage/apply', { id: data.id })"
+                  nz-button
+                  nzType="link"
+                  style="color: #231c1f"
+                >
+                  <span nz-icon nzType="edit" nzTheme="outline"></span>编辑教材
+                </button>
+              </li>
+              }@if(filterObj.btns.review){
+              <li nz-menu-item>
+                <button
+                  nz-button
+                  (click)="toUrl('/nav-admin/manage/textbook/details/' + data.id)"
+                  nzType="link"
+                  style="color: #231c1f"
+                >
+                  <span nz-icon nzType="read" nzTheme="outline"></span>预览教材
+                </button>
+              </li>
+              } @if(filterObj.btns.reject){
+              <li nz-menu-item>
+                <button
+                  (click)="reject(data)"
+                  nz-button
+                  nzType="link"
+                  style="color: #231c1f"
+                >
+                  <span nz-icon nzType="rollback" nzTheme="outline"></span
+                  >退回教材
+                </button>
+              </li>
+              } @if(filterObj.btns.star){
+              <li nz-menu-item>
+                <button
+                  (click)="updateStatus(data, true)"
+                  nz-button
+                  nzType="link"
+                  style="color: #231c1f"
+                >
+                  <span nz-icon nzType="star" nzTheme="outline"></span>加入推荐
+                </button>
+              </li>
+              } @if(filterObj.btns.remove){
+              <li nz-menu-item>
+                <button
+                  (click)="updateStatus(data, false)"
+                  nz-button
+                  nzType="link"
+                  style="color: #231c1f"
+                >
                   <span
                     nz-icon
-                    nzType="caret-right"
+                    nzType="vertical-align-bottom"
                     nzTheme="outline"
-                    (click)="reject(data)"
                   ></span
-                  >退回教材
+                  >移除推荐
                 </button>
               </li>
+              } @if(filterObj.btns.submit){
+              <li nz-menu-item>
+                <button
+                  nz-button
+                  (click)="submit(data)"
+                  nzType="link"
+                  style="color: #231c1f"
+                >
+                  <span nz-icon nzType="upload" nzTheme="outline"></span
+                  >提交教材
+                </button>
+              </li>
+              } @if(filterObj.btns.isDelete){
+              <li nz-menu-item>
+                <button
+                  (click)="del(data)"
+                  nz-button
+                  nzType="link"
+                  style="color: #231c1f"
+                >
+                  <span nz-icon nzType="delete" nzTheme="outline"></span
+                  >删除教材
+                </button>
+              </li>
+              }
             </ul>
           </nz-dropdown-menu>
-          }@else { - }
+          } @else { - }
         </td>
       </tr>
       }
     </tbody>
+    }
   </nz-table>
-  <ng-template #emptyResult>
-    <nz-empty nzNotFoundImage="/img/group-empty.png"></nz-empty>
-  </ng-template>
+  @if (textbookList.length == 0) {
+  <nz-empty nzNotFoundImage="/img/group-empty.png"></nz-empty>
+  }
 </div>
 <!-- 全选操作:批量操作 -->
-@if (setOfCheckedId.size) {
+@if (filterObj.isCheck && setOfCheckedId.size) {
 <div class="batch-toolbar-modal">
   <div class="batch-toolbar">
     <div class="styles_counter__18S08">
       <span>已选</span>
       <span class="styles_num__178Wa">{{ setOfCheckedId.size }}</span>
     </div>
+    @if(filterObj.btns.reject){
+    <div class="batch-toolbar-actions">
+      <div class="ant-space ant-space-horizontal ant-space-align-center">
+        <div class="ant-space-item" style="margin-right: 16px">
+          <button nz-button nzType="text" (click)="reject()">
+            <span nz-icon nzTheme="outline" nzType="rollback"></span>
+            批量退回
+          </button>
+        </div>
+      </div>
+    </div>
+    } @if(filterObj.btns.star){
+    <div class="styles_cancel__AARoT">
+      <button nz-button nzType="text" (click)="updateStatus(undefined, true)">
+        <span nz-icon nzType="star" nzTheme="outline"></span>
+        批量推荐
+      </button>
+    </div>
+    } @if(filterObj.btns.remove){
+    <div class="batch-toolbar-actions">
+      <div class="ant-space ant-space-horizontal ant-space-align-center">
+        <div class="ant-space-item" style="margin-right: 16px">
+          <button
+            nz-button
+            nzType="text"
+            (click)="updateStatus(undefined, false)"
+          >
+            <span
+              nz-icon
+              nzType="vertical-align-bottom"
+              nzTheme="outline"
+            ></span>
+            移除推荐
+          </button>
+        </div>
+      </div>
+    </div>
+    } @if(filterObj.btns.isDelete){
     <div class="batch-toolbar-actions">
       <div class="ant-space ant-space-horizontal ant-space-align-center">
         <div class="ant-space-item" style="margin-right: 16px">
-          <button nz-button nzType="text" (click)="rejectSelected()">
-            <span nz-icon nzType="delete"></span>
-            退回
+          <button nz-button nzType="text" (click)="del()">
+            <span nz-icon nzType="delete" nzType="outline"></span>
+            删除
           </button>
         </div>
       </div>
     </div>
+    } @if(filterObj.btns.submit){
+    <div class="styles_cancel__AARoT">
+      <button nz-button nzType="text" (click)="submit()">
+        <span nz-icon nzType="upload" nzTheme="outline"></span>
+        批量提交
+      </button>
+    </div>
+    }
     <div class="styles_cancel__AARoT">
       <button nz-button nzType="text" (click)="onAllChecked(false)">
         取消选中

+ 16 - 0
projects/textbook/src/app/textbook/textbook.component.scss

@@ -1,6 +1,22 @@
 .activeTd{
   cursor: pointer;
 }
+.tool{
+  display: flex;
+  justify-content: space-between;
+  .sbt{
+    padding: 6px 10px;
+    background: #E8F5FC;
+    font-family: PingFang SC;
+    font-size: 14px;
+    font-weight: 400;
+    /* line-height: 20px; */
+    text-align: center;
+    color: #0054C3;
+    border-radius: 4px;
+    cursor: pointer;
+  }
+}
 .activeTd:hover{
   color: #c6233f;
 }

+ 162 - 28
projects/textbook/src/app/textbook/textbook.component.ts

@@ -10,7 +10,6 @@ import { MatButtonModule } from '@angular/material/button';
 import { NzRadioModule } from 'ng-zorro-antd/radio';
 import { DatePipe } from '@angular/common';
 import { NzEmptyModule } from 'ng-zorro-antd/empty';
-
 @Component({
   selector: 'app-textbook',
   templateUrl: './textbook.component.html',
@@ -28,19 +27,39 @@ import { NzEmptyModule } from 'ng-zorro-antd/empty';
 })
 export class TextbookComponent implements OnInit {
   textbookList: Array<Parse.Object> = [];
+  count: number = 0;
+  limit: number = 10;
+  pageSize: number = 1;
+
   @Input('maxWidth') maxWidth: any; //最大宽度
   @Input('depart') depart: any; //指定申报单位
   @Input('recommend') recommend: any; //是否推荐
   @Input('uid') uid: string = ''; //个人空间
   @Input('path') path: string = '/nav-admin/manage/textbook/details';
-  @Input('power') power: Boolean = false; //权限
   @Input('discard') discard: Boolean = false; //是否删除
+  //相关权限配置
+  @Input('filterObj') filterObj: any = {
+    isCheck: true,
+    noStared: false, //非推荐
+    status: [],
+    btns: {
+      edit: false, //编辑
+      isDelete: false, //删除权限
+      review: false, //预览
+      reject: false, //退回教材
+      star: false, //加入推荐
+      remove: false, //移除推荐
+      submit: false, //提交
+      verify: false, //提交推荐权限
+    },
+  };
 
   loading: boolean = false;
   checkedAll: boolean = false; //全选
   setOfCheckedId = new Set<string>();
   searchValue: string = '';
-
+  manage: boolean = false;
+  eduProcessId:any = '' //流程id,verify存在时需要
   constructor(
     public tbookSer: textbookServer,
     private route: Router,
@@ -50,7 +69,13 @@ export class TextbookComponent implements OnInit {
   ) {}
 
   ngOnInit() {
-    this.getTextbook();
+    this.activeRoute.paramMap.subscribe(async (params) => {
+      this.eduProcessId = params.get('id');
+      this.getTextbook();
+      if (Object.values(this.filterObj.btns).some((item) => item)) {
+        this.manage = true;
+      }
+    });
   }
   async getTextbook(val?: string) {
     this.loading = true;
@@ -84,15 +109,25 @@ export class TextbookComponent implements OnInit {
     }
     this.depart && query.equalTo('department', this.depart);
     this.recommend && query.equalTo('recommend', true);
+    this.filterObj?.noStared && query.notEqualTo('recommend', true);
     this.uid && query.equalTo('user', this.uid);
     query.notEqualTo('isDeleted', true);
-    if(!this.uid){
-      query.equalTo('render',true)
-      query.containedIn('status',['200','400'])
+    if (!this.uid) {
+      query.equalTo('render', true);
+      // query.containedIn('status', ['200', '400']);
     }
-    if(this.discard){
-      query.equalTo('discard',true)
+    if (this.filterObj?.status?.length > 0) {
+      query.containedIn('status', this.filterObj?.status);
     }
+    if (this.discard) {
+      query.equalTo('discard', true);
+    } else {
+      query.notEqualTo('discard', true);
+    }
+    // query.include('department');
+    this.count = await query.count();
+    query.limit(this.limit);
+    query.skip(this.limit * (this.pageSize - 1));
     this.textbookList = await query.find();
     console.log(this.textbookList);
     this.loading = false;
@@ -111,6 +146,9 @@ export class TextbookComponent implements OnInit {
         this.setOfCheckedId.delete(item.id);
       }
     });
+    if (!checked) {
+      this.setOfCheckedId = new Set<string>();
+    }
     this.checkedAll = checked;
   }
   //单选
@@ -124,7 +162,7 @@ export class TextbookComponent implements OnInit {
       this.setOfCheckedId.has(item.id)
     );
   }
-  rejectSelected() {
+  reject(data?: Parse.Object) {
     this.modal.confirm({
       nzTitle: '批量退回',
       nzContent: `确定退回吗?`,
@@ -132,41 +170,137 @@ export class TextbookComponent implements OnInit {
       nzOkType: 'primary',
       nzOkDanger: true,
       nzOnOk: async () => {
-        let selectedList = this.textbookList.filter((item: any) =>
-          this.setOfCheckedId.has(item?.id)
-        );
-        let deletePromiseList = selectedList.map((item: any) => {
-          return new Promise((resolve) => {
-            item.set('status', '300');
-            item.save().then(() => resolve(true));
+        if (data?.id) {
+          data.set('status', '300');
+          await data.save();
+        } else {
+          let selectedList = this.textbookList.filter((item: any) =>
+            this.setOfCheckedId.has(item?.id)
+          );
+          let deletePromiseList = selectedList.map((item: any) => {
+            return new Promise((resolve) => {
+              item.set('status', '300');
+              item.save().then(() => resolve(true));
+            });
           });
-        });
-        try {
-          await Promise.all(deletePromiseList);
-          this.getTextbook();
-        } catch (err) {}
+          try {
+            await Promise.all(deletePromiseList);
+          } catch (err) {}
+        }
+        this.getTextbook();
       },
       nzCancelText: '取消',
       nzOnCancel: () => console.log('Cancel'),
     });
   }
-  reject(data: Parse.Object) {
+  //删除
+  del(data?: Parse.Object) {
+    console.log(data);
     this.modal.confirm({
-      nzTitle: '退回',
-      nzContent: `确定退回吗?`,
+      nzTitle: '删除教材',
+      nzContent: `删除后数据不可恢复,请谨慎操作`,
       nzOkText: '确认',
       nzOkType: 'primary',
       nzOkDanger: true,
       nzOnOk: async () => {
-        data.set('status', '300');
-        await data.save();
+        if (data?.id) {
+          data.set('isdeleted', true);
+          await data.save();
+        } else {
+          let selectedList = this.textbookList.filter((item: any) =>
+            this.setOfCheckedId.has(item?.id)
+          );
+          let deletePromiseList = selectedList.map((item: any) => {
+            return new Promise((resolve) => {
+              item.set('isdeleted', true);
+              item.save().then(() => resolve(true));
+            });
+          });
+          try {
+            await Promise.all(deletePromiseList);
+          } catch (err) {}
+        }
         this.getTextbook();
       },
       nzCancelText: '取消',
       nzOnCancel: () => console.log('Cancel'),
     });
   }
-  toUrl(url: string) {
+  //加入/移除推荐
+  updateStatus(data?: Parse.Object, recommend?: boolean) {
+    this.modal.confirm({
+      nzTitle: `${recommend ? '加入' : '移除'}推荐`,
+      nzContent: `确定${recommend ? '加入' : '移除'}推荐吗?`,
+      nzOkText: '确认',
+      nzOkType: 'primary',
+      nzOkDanger: !recommend,
+      nzOnOk: async () => {
+        if (data?.id) {
+          data.set('recommend', recommend);
+          await data.save();
+          this.getTextbook();
+        } else {
+          let selectedList = this.textbookList.filter((item: any) =>
+            this.setOfCheckedId.has(item?.id)
+          );
+          let deletePromiseList = selectedList.map((item: any) => {
+            return new Promise((resolve) => {
+              item.set('recommend', recommend);
+              item.save().then(() => resolve(true));
+            });
+          });
+          try {
+            await Promise.all(deletePromiseList);
+            this.getTextbook();
+            history.go();
+          } catch (err) {}
+        }
+      },
+      nzCancelText: '取消',
+      nzOnCancel: () => console.log('Cancel'),
+    });
+  }
+  //提交教材
+  submit(data?: Parse.Object) {
+    console.log(data);
+    this.modal.confirm({
+      nzTitle: '提交教材',
+      nzContent: `提交后在已提交评审教材中查看`,
+      nzOkText: '确认',
+      nzOkType: 'primary',
+      nzOkDanger: false,
+      nzOnOk: async () => {
+        if (data?.id) {
+          data.set('render', true);
+          data.set('status', '200');
+          await data.save();
+        } else {
+          let selectedList = this.textbookList.filter((item: any) =>
+            this.setOfCheckedId.has(item?.id)
+          );
+          let deletePromiseList = selectedList.map((item: any) => {
+            return new Promise((resolve) => {
+              item.set('render', true);
+              item.set('status', '200');
+              item.save().then(() => resolve(true));
+            });
+          });
+          try {
+            await Promise.all(deletePromiseList);
+          } catch (err) {}
+        }
+        this.getTextbook();
+      },
+      nzCancelText: '取消',
+      nzOnCancel: () => console.log('Cancel'),
+    });
+  }
+  toUrl(url: string, param?: Object) {
+    console.log(url);
+    if (param) {
+      this.route.navigate([url, param]);
+      return;
+    }
     this.route.navigate([url]);
   }
 }

+ 1 - 2
projects/textbook/src/modules/nav-admin/page-process/process-create/process-create.component.html

@@ -189,7 +189,6 @@
               [nzNoColon]="true"
               [nzSm]="18"
               [nzXs]="18"
-              [nzRequired]="eduProcess?.id"
               >推荐限额</nz-form-label
             >
             <nz-form-control
@@ -303,7 +302,7 @@
       <div class="title-row">
         <div class="bar">
           工作联系人
-          <a class="btn" [style.color]="profileId ? '#86b9f5' : ''" (click)="onShowCheck()">选择联系人</a>
+          <a class="btn" [style.color]="eduProcess?.get('profileSubmitted')?.get('user')?.id ? '#86b9f5' : ''" (click)="onShowCheck()">选择联系人</a>
         </div>
       </div>
       <div class="table" #maxWidth>

+ 3 - 2
projects/textbook/src/modules/nav-admin/page-process/process-create/process-create.component.ts

@@ -86,14 +86,14 @@ export class ProcessCreateComponent implements OnInit {
       if (id) {
         this.isEdit = true;
         let query = new Parse.Query('EduProcess');
-        query.include('branch', 'department');
+        query.include('branch', 'department','profileSubmitted');
         query.equalTo('objectId', id);
         this.eduProcess = await query.first();
         this.validateForm = this.fb.group({
           name: [this.eduProcess?.get('name') || '', [Validators.required]],
           desc: [this.eduProcess?.get('desc') || '',],
           code: [this.eduProcess?.get('code') || '', [Validators.required]],
-          num: [this.eduProcess?.get('num') || '', [Validators.required]],
+          num: [this.eduProcess?.get('num') || ''],
           branch: [
             this.eduProcess?.get('branch')?.id || '',
             [Validators.required],
@@ -306,6 +306,7 @@ export class ProcessCreateComponent implements OnInit {
     }else{
       this.msg.success('已删除联系人,请重新选择')
     }
+    this.ngOnInit();
     this.showProfileFrom = false
   }
   onCheck(e: any) {

+ 23 - 18
projects/textbook/src/modules/nav-admin/user-edit/user-edit.component.html

@@ -33,6 +33,7 @@
         </div>
       </div>
       <div class="header-right">
+        @if (edit) {
         <div style="margin-right: 10px">
           <button
             nz-button
@@ -61,7 +62,7 @@
                   >通过认证
                 </button>
               </li>
-              } 
+              }
               <!-- @if (user?.get('accountState') != '已禁用') {
               <li nz-menu-item>
                 <button
@@ -97,6 +98,7 @@
         >
           修改密码
         </button>
+        }
       </div>
     </div>
   </nz-page-header-content>
@@ -110,24 +112,28 @@
           <div nz-col nzSpan="8">
             <div class="lable">创建时间</div>
             <div class="value">
-              {{ user?.createdAt | date : "yyyy-MM-dd HH:MM:ss" || '-'}}
+              {{ user?.createdAt | date : "yyyy-MM-dd HH:MM:ss" || "-" }}
             </div>
           </div>
           <div nz-col nzSpan="8">
             <div class="lable">最后登录时间</div>
             <div class="value">
-              {{ user?.get("lastLogin") ? (user?.get("lastLogin") | date : "yyyy-MM-dd HH:MM:ss") : '-'}}
+              {{
+                user?.get("lastLogin")
+                  ? (user?.get("lastLogin") | date : "yyyy-MM-dd HH:MM:ss")
+                  : "-"
+              }}
             </div>
           </div>
           <div nz-col nzSpan="8">
             <div class="lable">最后登录IP</div>
-            <div class="value">{{ user?.get("lastIP") || '-'}}</div>
+            <div class="value">{{ user?.get("lastIP") || "-" }}</div>
           </div>
         </div>
         <div nz-row>
           <div nz-col nzSpan="8">
             <div class="lable">登录次数</div>
-            <div class="value">{{ user?.get("loginsCount") || '-'}}</div>
+            <div class="value">{{ user?.get("loginsCount") || "-" }}</div>
           </div>
           <div nz-col nzSpan="8">
             <div class="lable">用户类型</div>
@@ -217,22 +223,22 @@
           </div>
           <div nz-col nzSpan="8">
             <div class="lable">主要学科</div>
-            <div class="value">{{ profile?.get("majorSubject") || "未填写" }}</div>
+            <div class="value">
+              {{ profile?.get("majorSubject") || "未填写" }}
+            </div>
           </div>
         </div>
       </div>
       <div class="title-row">
         <div class="bar">
-          所属组织部门
+          所属组织部门 @if (edit) {
           <a class="btn" (click)="showModalDepart()">选择部门</a>
+          }
         </div>
       </div>
       <div class="fill-setp">
         @if (userDataJson.department?.id) {
-        <nz-tag
-          [nzBordered]="false"
-          style="color: black"
-          [nzColor]="'#efefef'"
+        <nz-tag [nzBordered]="false" style="color: black" [nzColor]="'#efefef'"
           >“十四五”高等教育国家规划教材申报系统</nz-tag
         >
         /
@@ -244,7 +250,7 @@
         >
         /
         <nz-tag [nzBordered]="false" [nzColor]="'geekblue'">{{
-          userDataJson.department?.get('name')
+          userDataJson.department?.get("name")
         }}</nz-tag>
         }@else { 待选择 }
       </div>
@@ -328,13 +334,12 @@
             <a style="color: #86909c">教材遴选</a>
             @for (data of parentMap; track data.title) {
             <span style="margin: 0 10px">/</span>
-            @if($index == 0){
-              @if (tbookSer.profile.identity != '国家级管理员') {
-                <a style="color: #86909c">{{ data.title }}</a>
-              }@else {
-                <a (click)="onCheck(data)">{{ data.title }}</a>
-              }
+            @if($index == 0){ @if (tbookSer.profile.identity != '国家级管理员')
+            {
+            <a style="color: #86909c">{{ data.title }}</a>
             }@else {
+            <a (click)="onCheck(data)">{{ data.title }}</a>
+            } }@else {
             <a style="color: #86909c">{{ data.title }}</a>
             } }
           </div>

+ 4 - 0
projects/textbook/src/modules/nav-admin/user-edit/user-edit.component.ts

@@ -133,6 +133,10 @@ export class UserEditComponent implements OnInit {
   }
   //选择部门
   async showModalDepart() {
+    if (!this.edit) {
+      this.message.warning('同级身份暂无权限操作');
+      return;
+    }
     if(this.unitTypes.length == 0){
      await this.getUnitTypes()
     }

+ 1 - 1
projects/textbook/src/modules/nav-author/recycle/recycle.component.html

@@ -13,6 +13,6 @@
   </div>
   <div class="space-content">
     <!-- <app-page-textbook [discard]="true"></app-page-textbook> -->
-    <app-textbook [uid]="user?.id"></app-textbook>
+    <app-textbook [uid]="user?.id" [discard]="true"></app-textbook>
   </div>
 </div>

+ 9 - 3
projects/textbook/src/modules/nav-author/space/space.component.html

@@ -2,7 +2,13 @@
   <div class="space-head">
     <div class="content">
       <div class="title">
-        {{ tbookSer.profile.name || "未认证用户" }},欢迎使用教材遴选提交系统
+        {{
+          tbookSer.profile.user?.name ||
+            tbookSer.profile.user?.phone ||
+            tbookSer.profile.user?.email ||
+            tbookSer.profile.user?.usernmae ||
+            "未认证用户"
+        }},欢迎使用教材遴选提交系统
       </div>
       <div class="text">
         创建教材、使用教材网信息加快填写速度,下载附件材料、上传教材所需文件,将你创建的教材提交至流程上级评审
@@ -24,13 +30,13 @@
       <nz-tab nzTitle="我的教材">
         @if (active == 0) {
         <!-- <app-page-textbook></app-page-textbook> -->
-        <app-textbook [uid]="user?.id"></app-textbook>
+        <app-textbook [filterObj]="myTextBook"  [uid]="user?.id"></app-textbook>
         }
       </nz-tab>
       <nz-tab nzTitle="已提交评审教材">
         @if (active == 1) {
         <!-- <app-page-textbook [render]="true"></app-page-textbook> -->
-        <app-textbook [uid]="user?.id"></app-textbook>
+        <app-textbook [filterObj]="submitTextBook"  [uid]="user?.id"></app-textbook>
         }
       </nz-tab>
     </nz-tabset>

+ 15 - 1
projects/textbook/src/modules/nav-author/space/space.component.ts

@@ -21,7 +21,21 @@ import { TextbookComponent } from '../../../app/textbook/textbook.component';
 export class SpaceComponent implements OnInit {
   user: Parse.Object | any = Parse.User.current();
   active: number = 0;
-
+  myTextBook:any = {
+    isCheck:true,
+    status:['101','102'],
+    btns:{
+      edit:true,//编辑
+      isDelete:true, //删除权限
+      submit:true //提交
+    }
+  }
+  submitTextBook = {
+    status:['200','300','400'],
+    btns:{
+      review:true,//编辑
+    }
+  }
   constructor(private router: Router, public tbookSer: textbookServer) {}
 
   ngOnInit() {}

+ 5 - 0
projects/textbook/src/modules/nav-province-contact/modules.routes.ts

@@ -6,6 +6,7 @@ import { PageProcessComponent } from "./page-process/page-process.component";
 import { ProcessListComponent } from "./page-process/process-list/process-list.component";
 import { PageRoleComponent } from "./page-role/page-role.component";
 import { PageTextbookComponent } from "./page-textbook/page-textbook.component";
+import { SubmittedComponent } from "./submitted/submitted.component";
 // import { PageTextbookComponent } from "./page-textbook/page-textbook.component";
 const routes: Routes = [
   {
@@ -40,6 +41,10 @@ const routes: Routes = [
         path: 'role', //组织列表
         component: PageRoleComponent,
       },
+      {
+        path: 'submitted/:id', //组织列表
+        component: SubmittedComponent,
+      },
     ]
   }
 ];

+ 18 - 7
projects/textbook/src/modules/nav-province-contact/page-process/page-process.component.html

@@ -2,10 +2,14 @@
   <nz-breadcrumb nz-page-header-breadcrumb>
     <nz-breadcrumb-item>教材申报</nz-breadcrumb-item>
     <nz-breadcrumb-item>申报流程</nz-breadcrumb-item>
-    <nz-breadcrumb-item><a>{{eduProcess?.get('department')?.get('name') || '未选择申报单位'}}</a></nz-breadcrumb-item>
+    <nz-breadcrumb-item
+      ><a>{{
+        eduProcess?.get("department")?.get("name") || "未选择申报单位"
+      }}</a></nz-breadcrumb-item
+    >
   </nz-breadcrumb>
   <nz-page-header-title
-    >{{eduProcess?.get('department')?.get('name') || '未选择申报单位'}}
+    >{{ eduProcess?.get("department")?.get("name") || "未选择申报单位" }}
     <br />
     <div class="subtitle">
       在流程中邀请作者、高校联系人、评审员登录系统,创建并提交教材,由工作联系人评审、提交推荐教材完成流程工作
@@ -21,11 +25,18 @@
     </nz-tab>
     <nz-tab nzTitle="教材列表">
       @if (active == 1) {
-        <div class="title">待评审教材列表</div>
-        <app-textbook></app-textbook>
-        <br>
-        <div class="title">推荐教材列表</div>
-        <app-textbook [recommend]="true"></app-textbook>
+      <div class="title">待评审教材列表</div>
+      <app-textbook
+        [depart]="eduProcess?.id"
+        [filterObj]="beforeFilterObj"
+      ></app-textbook>
+      <br />
+      <div class="title">推荐教材列表</div>
+      <app-textbook
+        [filterObj]="afterFilterObj"
+        [recommend]="true"
+        [depart]="eduProcess?.id"
+      ></app-textbook>
       }
     </nz-tab>
   </nz-tabset>

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

@@ -28,6 +28,25 @@ export class PageProcessComponent  implements OnInit {
   eduProcess: Parse.Object | undefined;
 
   user: Parse.User | undefined;
+  //待审核
+  beforeFilterObj: any = {
+    isCheck: true,
+    noStared:true,
+    status: ['200'],
+    btns: {
+      reject: true, //退回教材
+      star: true, //移除推荐
+    },
+  };
+  //已加入推荐
+  afterFilterObj: any = {
+    isCheck: true,
+    status: ['200'],
+    btns: {
+      verify:true,
+      remove: true, //移除推荐
+    },
+  };
 
   constructor(
     private activeRoute:ActivatedRoute,

+ 12 - 12
projects/textbook/src/modules/nav-province-contact/page-role/page-role.component.html

@@ -129,51 +129,51 @@
       >
         <thead>
           <tr>
-            <th
+            <!-- <th
               nzWidth="50px"
               nzLeft
               [nzChecked]="checkedAll"
               [nzIndeterminate]="indeterminate"
               nzLabel="Select all"
               (nzCheckedChange)="onAllChecked($event)"
-            ></th>
+            ></th> -->
             <th nzWidth="120px">用户</th>
             <th nzWidth="120px">手机号</th>
             <th nzWidth="120px">邮箱</th>
             <th nzWidth="120px">人员类型</th>
             <th nzWidth="120px">所属部门</th>
-            <th nzWidth="50px" nzRight>操作</th>
+            <!-- <th nzWidth="50px" nzRight>操作</th> -->
           </tr>
         </thead>
         <tbody>
           @for (data of profiles; track data.objectId) {
           <tr>
-            <td
+            <!-- <td
               nzLeft
               [nzChecked]="data.checked"
               (nzCheckedChange)="onItemChecked(data.objectId, $event)"
-            ></td>
+            ></td> -->
             <td
               nzEllipsis
               (click)="goDateil(data.user?.objectId)"
               class="activeTd"
             >
               <nz-avatar nzIcon="user"></nz-avatar>
-              {{ data?.user.name }}
+              {{ data?.user.name || '-'}}
             </td>
             <td>
-              {{ data?.user.phone }}
+              {{ data?.user.phone || '-'}}
             </td>
             <td>
-              {{ data?.user.email || data?.email }}
+              {{ data?.user.email || data?.email || '-'}}
             </td>
             <td>
-              {{ data?.identity }}
+              {{ data?.identity || '-'}}
             </td>
             <td>
-              {{ data?.user.departmentName }}
+              {{ data?.user.departmentName || '-' }}
             </td>
-            <td nzRight>
+            <!-- <td nzRight>
               @if(data?.user?.objectId == user?.id || data?.identity ==
               '工作联系人' || data?.identity == '高校联系人'){ - } @else {
               <button
@@ -195,7 +195,7 @@
                 </ul>
               </nz-dropdown-menu>
               }
-            </td>
+            </td> -->
           </tr>
           }
         </tbody>

+ 1 - 1
projects/textbook/src/modules/nav-province-contact/page-textbook/page-textbook.component.html

@@ -13,5 +13,5 @@
   [queryParams]="queryParams"
 ></comp-table-list> -->
 <div class="conetent">
-  <app-textbook></app-textbook>
+  <app-textbook [filterObj]="filterObj"></app-textbook>
 </div>

+ 3 - 1
projects/textbook/src/modules/nav-province-contact/page-textbook/page-textbook.component.ts

@@ -32,7 +32,9 @@ export class PageTextbookComponent implements OnInit {
   className: string | undefined;
   queryParams: any | undefined;
   fieldsArray: Array<any> | undefined;
-
+  filterObj: any = {
+    isCheck: false,
+  };
   constructor(
     public tbookSer: textbookServer,
     private router: Router,

+ 15 - 0
projects/textbook/src/modules/nav-province-contact/submitted/complete/complete.component.html

@@ -0,0 +1,15 @@
+<div class="manage">
+  <nz-empty [nzNotFoundContent]="deadline+ '后可完成报送'"></nz-empty>
+</div>
+
+<div class="footer">
+  <button nz-button disabled="true" nzType="default" style="margin-right: 20px">
+  </button>
+  <button
+    nz-button
+    nzType="primary"
+    disabled="true"
+  >
+    完成报送
+  </button>
+</div>

+ 21 - 0
projects/textbook/src/modules/nav-province-contact/submitted/complete/complete.component.scss

@@ -0,0 +1,21 @@
+.manage{
+  padding: 20px 50px;
+  width: 100%;
+  // background: #F9F9F9;
+  // border-radius: 10px;
+  // display: flex;
+  // align-items: center;
+  // justify-content: center;
+}
+.footer{
+  position: fixed;
+  bottom: 50px;
+  right: 10px;
+  display: flex;
+  margin: 10px auto;
+  align-items: center;
+  justify-content: space-evenly;
+  // width: 200px;
+  justify-content: end;
+  padding-right: 100px;
+}

+ 24 - 0
projects/textbook/src/modules/nav-province-contact/submitted/complete/complete.component.spec.ts

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

+ 42 - 0
projects/textbook/src/modules/nav-province-contact/submitted/complete/complete.component.ts

@@ -0,0 +1,42 @@
+import { Component, EventEmitter, OnInit, Output } from '@angular/core';
+import { Router, ActivatedRoute } from '@angular/router';
+import { CommonCompModule } from '../../../../services/common.modules';
+import { NzEmptyModule } from 'ng-zorro-antd/empty';
+@Component({
+  selector: 'app-complete',
+  templateUrl: './complete.component.html',
+  styleUrls: ['./complete.component.scss'],
+  imports: [CommonCompModule, NzEmptyModule],
+  standalone: true,
+})
+export class CompleteComponent implements OnInit {
+  date: Date = new Date('2024/7/21');
+  t: any;
+  deadline: string = '';
+  time() {
+    if (new Date().getTime() > this.date.getTime()) {
+      clearTimeout(this.t);
+    }
+    this.t = setTimeout(() => {
+      let hs = this.date.getTime() - new Date().getTime();
+      let a = 60 * 60 * 1000
+      let day: number = Math.floor(hs / (24 * a));
+      let h = Math.floor((hs - day * (24 * a)) / a);
+      let m = Math.floor((hs - day * (24 * a) - h * a) / (60 * 1000));
+      let s = Math.floor((hs - day * (24 * a) - h * a - (m * 60 * 1000))  / 1000);
+      this.deadline = day + '天' + h + '小时' + m + '分' + s + '秒';
+      this.time()
+    }, 1000);
+  }
+  constructor(private router: Router, private activeRoute: ActivatedRoute) {}
+
+  ngOnInit() {
+    this.time();
+  }
+
+  ngOnDestroy(): void {
+    //Called once, before the instance is destroyed.
+    //Add 'implements OnDestroy' to the class.
+    clearTimeout(this.t);
+  }
+}

+ 30 - 0
projects/textbook/src/modules/nav-province-contact/submitted/export-file/export-file.component.html

@@ -0,0 +1,30 @@
+<div class="manage">
+  <div class="left">
+    <div class="row">
+      <div class="lable">推荐教材</div>
+      <div class="val">{{allCount - otherCount}}</div>
+    </div>
+    <div class="row">
+      <div class="lable">申报限额外推荐教材</div>
+      <div class="val">{{otherCount}}</div>
+    </div>
+    <div class="row">
+      <div class="lable">推荐表总份数</div>
+      <div class="val">{{allCount}}</div>
+    </div>
+  </div>
+  <div class="right">
+    <button
+        style="background: #3e49b3; border: 1px #3e49b3"
+        nz-button
+        nzType="primary"
+      >
+        生成 PDF 并下载
+      </button>
+  </div>
+</div>
+
+<div class="footer">
+  <button nz-button nzType="default" (click)="close()" style="margin-right: 20px">取消</button>
+  <button nz-button nzType="primary" (click)="next()" style="background: #3e49b3; border: 1px #3e49b3">下一步</button>
+</div>

+ 35 - 0
projects/textbook/src/modules/nav-province-contact/submitted/export-file/export-file.component.scss

@@ -0,0 +1,35 @@
+.manage{
+  padding: 20px 50px;
+  width: 100%;
+  background: #F9F9F9;
+  border-radius: 10px;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  .left{
+    .row{
+      display: flex;
+      color: #231C1F99;
+      font-family: PingFang SC;
+      font-size: 16px;
+      font-weight: 400;
+      line-height: 24px;
+      text-align: right;
+      margin-bottom: 10px;
+      width: 250px;
+      justify-content: space-between;
+    }
+  }
+}
+.footer{
+  position: fixed;
+  bottom: 50px;
+  right: 10px;
+  display: flex;
+  margin: 10px auto;
+  align-items: center;
+  justify-content: space-evenly;
+  // width: 200px;
+  justify-content: end;
+  padding-right: 100px;
+}

+ 24 - 0
projects/textbook/src/modules/nav-province-contact/submitted/export-file/export-file.component.spec.ts

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

+ 49 - 0
projects/textbook/src/modules/nav-province-contact/submitted/export-file/export-file.component.ts

@@ -0,0 +1,49 @@
+import { Component, EventEmitter, OnInit, Output } from '@angular/core';
+import { Router, ActivatedRoute } from '@angular/router';
+import { CommonCompModule } from '../../../../services/common.modules';
+
+import Parse from 'parse';
+@Component({
+  selector: 'app-export-file',
+  templateUrl: './export-file.component.html',
+  styleUrls: ['./export-file.component.scss'],
+  imports: [CommonCompModule],
+  standalone: true,
+})
+export class ExportFileComponent implements OnInit {
+  @Output() change: EventEmitter<any> = new EventEmitter<any>();
+
+  starCount: number = 0;
+  otherCount: number = 0;
+  allCount: number = 0;
+
+  constructor(private router: Router, private activeRoute: ActivatedRoute) {}
+
+  ngOnInit() {
+    this.activeRoute.paramMap.subscribe(async (params) => {
+      let id = params.get('id');
+      // let query = new Parse.Query('EduProcess');
+      // query.include('branch', 'department');
+      // query.equalTo('objectId', id);
+      // this.eduProcess = await query.first();
+      console.log(id);
+      let query = new Parse.Query('EduTextbook');
+      query.notEqualTo('isDeleted', true);
+      query.equalTo('recommend', true);
+      query.equalTo('eduProcess', id);
+      this.allCount = await query.count();
+      query.containedIn('approval', [
+        '101计划”核心教材',
+        '“四新”重点建设教材',
+        '战略性新兴领域教材',
+      ]);
+      this.otherCount = await query.count();
+    });
+  }
+  close(){
+    history.back()
+  }
+  next(){
+    this.change.emit('next')
+  }
+}

+ 11 - 0
projects/textbook/src/modules/nav-province-contact/submitted/export-list/export-list.component.html

@@ -0,0 +1,11 @@
+<div class="manage">
+  <div class="title">北京市“十四五”普通高等教育本科国家级规划教材第一次遴选推荐名单</div>
+  <app-textbook [filterObj]="filterObj"></app-textbook>
+</div>
+
+
+<div class="footer">
+  <button nz-button nzType="default"  style="margin-right: 20px">下载公示列表</button>
+  <button nz-button nzType="default" (click)="onChange('pre')" style="margin-right: 20px">上一页</button>
+  <button nz-button nzType="primary" (click)="onChange('next')" style="background: #3e49b3; border: 1px #3e49b3">下一步</button>
+</div>

+ 21 - 0
projects/textbook/src/modules/nav-province-contact/submitted/export-list/export-list.component.scss

@@ -0,0 +1,21 @@
+.title {
+  //styleName: Header/header-5/CN-Semi Bold;
+  font-family: PingFang SC;
+  font-size: 18px;
+  font-weight: 600;
+  line-height: 24px;
+  text-align: left;
+  margin-bottom: 18px;
+}
+.footer{
+  position: fixed;
+  bottom: 50px;
+  right: 10px;
+  display: flex;
+  margin: 10px auto;
+  align-items: center;
+  justify-content: space-evenly;
+  // width: 200px;
+  justify-content: end;
+  padding-right: 100px;
+}

+ 24 - 0
projects/textbook/src/modules/nav-province-contact/submitted/export-list/export-list.component.spec.ts

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

+ 30 - 0
projects/textbook/src/modules/nav-province-contact/submitted/export-list/export-list.component.ts

@@ -0,0 +1,30 @@
+import { Component, EventEmitter, OnInit, Output } from '@angular/core';
+import { Router, ActivatedRoute } from '@angular/router';
+import { TextbookComponent } from '../../../../app/textbook/textbook.component';
+import { CommonCompModule } from '../../../../services/common.modules';
+
+@Component({
+  selector: 'app-export-list',
+  templateUrl: './export-list.component.html',
+  styleUrls: ['./export-list.component.scss'],
+  imports: [CommonCompModule, TextbookComponent],
+  standalone: true,
+})
+export class ExportListComponent implements OnInit {
+  @Output() change: EventEmitter<any> = new EventEmitter<any>();
+  textBookList: Parse.Object | any;
+
+  filterObj: any = {
+    isCheck: false,
+  };
+  constructor(private router: Router, private activeRoute: ActivatedRoute) {}
+
+  ngOnInit() {}
+  onChange(type: string) {
+    if (type == 'next') {
+      this.change.emit('next');
+    } else {
+      this.change.emit('pre');
+    }
+  }
+}

+ 34 - 0
projects/textbook/src/modules/nav-province-contact/submitted/submitted.component.html

@@ -0,0 +1,34 @@
+<div class="site-page-header">
+  <nz-page-header>
+    <nz-breadcrumb nz-page-header-breadcrumb>
+      <nz-breadcrumb-item>
+        <div class="back" (click)="back()">
+          <span nz-icon nzType="left" nzTheme="outline"></span>返回
+        </div>
+      </nz-breadcrumb-item>
+    </nz-breadcrumb>
+    <nz-page-header-title
+      >确认报送
+      <br />
+      <div class="subtitle">
+        在流程中邀请作者、高校联系人、评审员登录系统,创建并提交教材,由工作联系人评审、提交推荐教材完成流程工作
+      </div>
+    </nz-page-header-title>
+  </nz-page-header>
+  <div class="steps">
+    <nz-steps [nzCurrent]="state">
+      <nz-step nzTitle="导出函报文件" nzDescription=""></nz-step>
+      <nz-step nzTitle="导出公示教材列表" nzDescription=""></nz-step>
+      <nz-step nzTitle="完成报送" nzDescription=""></nz-step>
+    </nz-steps>
+  </div>
+</div>
+
+<div class="content">
+  @switch (state) { @case (0) {
+  <app-export-file (change)="onChange($event)"></app-export-file>
+  } @case (1) {
+  <app-export-list (change)="onChange($event)"></app-export-list>
+
+  } @case (2) { <app-complete></app-complete>} }
+</div>

+ 65 - 0
projects/textbook/src/modules/nav-province-contact/submitted/submitted.component.scss

@@ -0,0 +1,65 @@
+.site-page-header{
+  position: sticky;
+  top: 0;
+  z-index: 9;
+  padding:24px 24px 10px;
+  background-color: white;
+  font-family: PingFang SC;
+  .steps{
+    max-width: 600px;
+    margin: 10px 0;
+  }
+  .back{
+    font-family: PingFang SC;
+    font-size: 14px;
+    font-weight: 400;
+    line-height: 22px;
+    text-align: left;
+    cursor: pointer;
+  }
+  .subtitle {
+    margin-right: 12px;
+    color: #00000073;
+    font-size: 14px;
+    font-weight: normal;
+    line-height: 1.5715;
+    // overflow: hidden;
+    // white-space: nowrap;
+    // text-overflow: ellipsis;
+  }
+}
+
+.content {
+  font-family: PingFang SC;
+  padding: 10px 24px;
+  .state-title {
+    margin:0 0 20px;
+    font-family: PingFang SC;
+    font-size: 20px;
+    font-weight: 500;
+    line-height: 28px;
+    text-align: left;
+  }
+  .submit-block {
+    min-width: 800px;
+    // max-width: 1200px;
+    min-height: 600px;
+    margin: 10px auto;
+    .entry {
+      min-height: 500px;
+      // border: 1px solid;
+    }
+    .footer {
+      display: flex;
+      margin: 10px auto;
+      align-items: center;
+      justify-content: space-evenly;
+      // width: 200px;
+      justify-content: end;
+      padding-right: 100px;
+    }
+  }
+}
+::ng-deep .ant-page-header{
+  padding: 0;
+}

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

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

+ 48 - 0
projects/textbook/src/modules/nav-province-contact/submitted/submitted.component.ts

@@ -0,0 +1,48 @@
+import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
+import { CommonCompModule } from '../../../services/common.modules';
+import { Router, ActivatedRoute } from '@angular/router';
+import { ReactiveFormsModule } from '@angular/forms';
+import Parse from 'parse';
+import { ExportFileComponent } from './export-file/export-file.component';
+import { ExportListComponent } from './export-list/export-list.component';
+import { CompleteComponent } from './complete/complete.component';
+@Component({
+  selector: 'app-submitted',
+  templateUrl: './submitted.component.html',
+  styleUrls: ['./submitted.component.scss'],
+  imports: [
+    CommonCompModule,
+    ReactiveFormsModule,
+    ExportFileComponent,
+    ExportListComponent,
+    CompleteComponent
+  ],
+  standalone: true,
+})
+export class SubmittedComponent implements OnInit {
+  eduProcess?: Parse.Object;
+
+  state: number = 0;
+  get stateMap() {
+    let map: any = {
+      '0': '导出函报文件',
+      '1': '导出公示教材列表',
+      '2': '完成报送',
+    };
+    return map[this.state];
+  }
+  constructor() {}
+
+  ngOnInit() {}
+  back() {
+    history.back();
+  }
+  onChange(e: any) {
+    console.log(e);
+    if (e == 'next') {
+      this.state++;
+    } else {
+      this.state--;
+    }
+  }
+}

+ 6 - 1
server/db/schemas/EduTextbook.js

@@ -207,7 +207,12 @@ export const EduTextbook = {
         "accept": {//填写承诺书
             "type": "String",
             "required": false
-        }
+        },
+        "eduProcess": {//所属流程
+            "type": "Pointer",
+            "targetClass":"EduProcess",
+            "required": false
+        },
     },
     "classLevelPermissions": {
         "find": {