Преглед на файлове

Merge branch 'master' of http://git.fmode.cn:3000/bin/edu-textbook

xll преди 7 месеца
родител
ревизия
c8a12b05a3
променени са 23 файла, в които са добавени 549 реда и са изтрити 281 реда
  1. 7 0
      projects/textbook/src/app/app.routes.ts
  2. 1 1
      projects/textbook/src/app/textbook/textbook.component.ts
  3. 15 0
      projects/textbook/src/modules/common/modules.routes.ts
  4. 36 0
      projects/textbook/src/modules/nav-admin/auth.guard.ts
  5. 3 1
      projects/textbook/src/modules/nav-admin/modules.routes.ts
  6. 3 3
      projects/textbook/src/modules/nav-admin/page-process/process-create/process-create.component.ts
  7. 10 10
      projects/textbook/src/modules/nav-admin/page-process/process-list/process-list.component.ts
  8. 109 63
      projects/textbook/src/modules/nav-admin/page-user/page-user.component.ts
  9. 1 1
      projects/textbook/src/modules/nav-admin/user-edit/user-edit.component.ts
  10. 36 0
      projects/textbook/src/modules/nav-province-contact/auth.guard.ts
  11. 3 1
      projects/textbook/src/modules/nav-province-contact/modules.routes.ts
  12. 136 132
      projects/textbook/src/modules/nav-province-contact/page-process/process-list/process-list.component.html
  13. 12 0
      projects/textbook/src/modules/nav-province-contact/page-process/process-list/process-list.component.scss
  14. 14 10
      projects/textbook/src/modules/nav-province-contact/page-process/process-list/process-list.component.ts
  15. 10 0
      projects/textbook/src/modules/nav-province-contact/page-role/page-role.component.html
  16. 12 1
      projects/textbook/src/modules/nav-province-contact/page-role/page-role.component.scss
  17. 27 2
      projects/textbook/src/modules/nav-province-contact/page-role/page-role.component.ts
  18. 52 53
      projects/textbook/src/modules/nav-province-contact/page-textbook/page-textbook.component.html
  19. 12 0
      projects/textbook/src/modules/nav-province-contact/page-textbook/page-textbook.component.scss
  20. 8 1
      projects/textbook/src/modules/nav-province-contact/page-textbook/page-textbook.component.ts
  21. 36 0
      projects/textbook/src/modules/nav-province-school-contact/auth.guard.ts
  22. 3 1
      projects/textbook/src/modules/nav-province-school-contact/modules.routes.ts
  23. 3 1
      projects/textbook/src/services/common.modules.ts

+ 7 - 0
projects/textbook/src/app/app.routes.ts

@@ -3,6 +3,7 @@ import { AuthGuard } from '../services/auth.guard';
 import { CompUserComponent } from './comp-user/comp-user.component';
 import { ProfileComponent } from '../modules/user/profile/profile.component'
 import { CompManageComponent } from './comp-manage/comp-manage.component'
+import { TextbookDetailsComponent } from '../modules/common/textbook-details/textbook-details.component';
 export const routes: Routes = [
   { path: '', redirectTo:'user/login', pathMatch: "full",}, // 默认跳转到 ''
   // { path: '',loadComponent:()=>import('../modules/textbook/page-home/page-home.component').then(m=>m.PageHomeComponent) }, // 默认跳转到 ''
@@ -15,6 +16,12 @@ export const routes: Routes = [
     path: 'profile', // 用户登录/注册
     component: ProfileComponent,
   },
+  {
+    path: 'common', //教材详情
+    component: CompManageComponent,
+    canActivate: mapToCanActivate([AuthGuard]),
+    loadChildren: () =>import('../modules/common/modules.routes').then((mod) => mod.CommonRoutingModule),
+  },
   {
     path: 'nav-admin', //国家级管理员管理平台
     component: CompManageComponent,

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

@@ -45,7 +45,7 @@ export class TextbookComponent implements OnInit {
   @Input('depart') depart: any; //指定申报单位
   @Input('recommend') recommend: any; //是否推荐
   @Input('uid') uid: string = ''; //个人空间
-  @Input('path') path: string = '/nav-admin/manage/textbook/details';
+  @Input('path') path: string = '/common/textbook/details';
   @Input('discard') discard: Boolean = false; //是否删除
   @Input('eduProcess') eduProcess?: Parse.Object; //流程id,verify存在时需要
 

+ 15 - 0
projects/textbook/src/modules/common/modules.routes.ts

@@ -0,0 +1,15 @@
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes,RouteReuseStrategy, mapToCanActivate } from '@angular/router';
+import { TextbookDetailsComponent } from './textbook-details/textbook-details.component';
+const routes: Routes = [
+  {
+    path: 'textbook/details/:id', //流程申报
+    component: TextbookDetailsComponent,
+  },
+]
+
+@NgModule({
+  imports: [RouterModule.forChild(routes)],
+  exports: [RouterModule],
+})
+export class CommonRoutingModule {}

+ 36 - 0
projects/textbook/src/modules/nav-admin/auth.guard.ts

@@ -0,0 +1,36 @@
+import { Injectable } from '@angular/core';
+import {
+  CanActivate,
+  ActivatedRouteSnapshot,
+  RouterStateSnapshot,
+} from '@angular/router';
+import { Observable } from 'rxjs';
+import { Router } from '@angular/router';
+import { textbookServer } from '../../services/textbook';
+@Injectable({
+  providedIn: 'root',
+})
+export class AuthGuard implements CanActivate {
+  LoginPage = '/user/login';
+
+  constructor(private tbookSer: textbookServer, private router: Router) {}
+
+  canActivate(
+    next: ActivatedRouteSnapshot,
+    state: RouterStateSnapshot
+  ): Observable<boolean> | Promise<boolean> | boolean {
+    // 当前路由url
+    // let url: string = state.url;
+    // console.log(url);
+    return this.checkLogin();
+  }
+  checkLogin(): boolean {
+    if (this.tbookSer.profile.identity == '国家级管理员') {
+      return true;
+    }
+    // 否则重定向到login页面
+    this.router.navigate([this.LoginPage]);
+    return false;
+  }
+}
+export { CanActivate };

+ 3 - 1
projects/textbook/src/modules/nav-admin/modules.routes.ts

@@ -1,5 +1,5 @@
 import { NgModule } from '@angular/core';
-import { RouterModule, Routes,RouteReuseStrategy } from '@angular/router';
+import { RouterModule, Routes,RouteReuseStrategy, mapToCanActivate } from '@angular/router';
 // import { CollectionEditComponent } from './collection/collection-edit/collection-edit.component';
 // import { CreateCollectionComponent } from './collection/create-collection/create-collection.component';
 // import { PageCollectionComponent } from './collection/page-collection/page-collection.component';
@@ -14,6 +14,7 @@ import { TextbookDetailsComponent } from '../common/textbook-details/textbook-de
 import { UserCreateComponent } from './page-user/user-create/user-create.component';
 import { ReuseService } from "../../services/route-reuse.service";
 import { LeaveGuard } from './user-edit/auth.guard';
+import { AuthGuard } from './auth.guard';
 const routes: Routes = [
   {
     path: '',
@@ -22,6 +23,7 @@ const routes: Routes = [
   },
   {
     path: 'manage',
+    canActivate: mapToCanActivate([AuthGuard]),
     children:[
       {
         path: 'process', //流程申报

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

@@ -57,7 +57,7 @@ export class ProcessCreateComponent implements OnInit {
     name: ['', [Validators.required]],
     desc: ['',[Validators.maxLength(500)]],
     code: ['', [Validators.required]],
-    num: ['',],
+    num: [0,],
     branch: ['', [Validators.required]],
     startDate: [new Date('2024/07/20'), [Validators.required]],
     deadline: [new Date('2024/09/20'), [Validators.required]],
@@ -93,7 +93,7 @@ export class ProcessCreateComponent implements OnInit {
         this.validateForm.get('name')?.setValue(this.eduProcess?.get('name') || '')
         this.validateForm.get('desc')?.setValue(this.eduProcess?.get('desc') || '')
         this.validateForm.get('code')?.setValue(this.eduProcess?.get('code') || '')
-        this.validateForm.get('num')?.setValue(this.eduProcess?.get('num') || this.eduProcess?.get('num') == 0 ? this.eduProcess?.get('num') : '')
+        this.validateForm.get('num')?.setValue(this.eduProcess?.get('num') || this.eduProcess?.get('num') == 0 ? this.eduProcess?.get('num') : 0)
         this.validateForm.get('branch')?.setValue(this.eduProcess?.get('branch')?.id || '')
         this.validateForm.get('startDate')?.setValue(this.eduProcess?.get('startDate')
               ? this.eduProcess?.get('startDate')
@@ -203,7 +203,7 @@ export class ProcessCreateComponent implements OnInit {
     this.eduProcess?.set('name', params.name);
     this.eduProcess?.set('desc', params.desc);
     this.eduProcess?.set('code', params.code);
-    params.num && this.eduProcess?.set('num', params.num);
+    typeof(params.num) == 'number' && this.eduProcess?.set('num', params.num);
     this.eduProcess?.set('startDate', params.startDate);
     this.eduProcess?.set('deadline', params.deadline);
     if (!this.eduProcess?.get('profileSubmitted')) {

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

@@ -148,6 +148,16 @@ export class ProcessListComponent implements OnInit {
         del: true,
       };
     }
+    if (e?.get('deadline') && new Date() > new Date(e?.get('deadline'))) {
+      return {
+        title: '已逾期',
+        color: 'red',
+        strat: true,
+        stop: false,
+        end: false,
+        del: true,
+      };
+    }
     if (
       e.get('status') == '200' &&
       e?.get('startDate') &&
@@ -162,16 +172,6 @@ export class ProcessListComponent implements OnInit {
         del: false,
       };
     }
-    if (e?.get('deadline') && new Date() > new Date(e?.get('deadline'))) {
-      return {
-        title: '已逾期',
-        color: 'red',
-        strat: true,
-        stop: false,
-        end: false,
-        del: true,
-      };
-    }
     if (e.get('status') == '300') {
       return {
         title: '已公示',

+ 109 - 63
projects/textbook/src/modules/nav-admin/page-user/page-user.component.ts

@@ -48,12 +48,15 @@ export class PageUserComponent implements OnInit {
     companyType: {
       listOfFilter: [
         { value: '教育部直属高校', text: '教育部直属高校' },
-        { value: '中央有关部门(单位)教育司(局)', text: '中央有关部门(单位)教育司(局)' },
+        {
+          value: '中央有关部门(单位)教育司(局)',
+          text: '中央有关部门(单位)教育司(局)',
+        },
         { value: '省级教育行政部门', text: '省级教育行政部门' },
         { value: '出版单位', text: '出版单位' },
       ],
     },
-  }
+  };
   // _User = _User;
   // ProfileList = Profile;
   // className: string | undefined;
@@ -107,9 +110,9 @@ export class PageUserComponent implements OnInit {
 
   ngOnInit(): void {
     this.activeRoute.queryParamMap.subscribe(async (queryParams) => {
-      console.log(queryParams)
-      let page = queryParams.get("page");
-      if(page){
+      console.log(queryParams);
+      let page = queryParams.get('page');
+      if (page) {
         this.pageIndex = Number(page);
         this.updateUrlPageIndex(Number(page));
       }
@@ -150,7 +153,9 @@ export class PageUserComponent implements OnInit {
       },
     };
     if (this.tbookSer.profile.identity != '国家级管理员') {
-      let childrens = await this.tbookSer.getChild(this.tbookSer.profile.user.department?.objectId)
+      let childrens = await this.tbookSer.getChild(
+        this.tbookSer.profile.user.department?.objectId
+      );
       this.tbookSer.profile.user.department;
       queryParams['where']['$or'][0]['user']['$inQuery']['where'][
         'department'
@@ -188,28 +193,31 @@ export class PageUserComponent implements OnInit {
     this.getProfile();
   }
   /** 更新页码queryParams */
-  updateUrlPageIndex(page:number){
+  updateUrlPageIndex(page: number) {
     let search = window.location.search;
-    if(!search){
-      search = `?page=${page}`
-    }else{
-      let pagestr = window.location.search?.replaceAll("?","").split("&").find(item=>item.indexOf("page=")>-1);
-      if(pagestr){
-        search = search.replaceAll(pagestr,`page=${page}`)
-      }else{
-        search = search + `?page=${page}`
+    if (!search) {
+      search = `?page=${page}`;
+    } else {
+      let pagestr = window.location.search
+        ?.replaceAll('?', '')
+        .split('&')
+        .find((item) => item.indexOf('page=') > -1);
+      if (pagestr) {
+        search = search.replaceAll(pagestr, `page=${page}`);
+      } else {
+        search = search + `?page=${page}`;
       }
     }
     let newHref = window.location.origin + window.location.pathname + search;
-    window.history.replaceState(null, "", newHref);
+    window.history.replaceState(null, '', newHref);
   }
   //筛选条件
-  onChangeFilter(data: any, type:string){
+  onChangeFilter(data: any, type: string) {
     console.log(data);
-    this.filters[type].value = data
-    this.profiles = []
-    this.pageIndex = 1
-    this.getProfile()
+    this.filters[type].value = data;
+    this.profiles = [];
+    this.pageIndex = 1;
+    this.getProfile();
   }
   createUser() {
     this.route.navigate(['/nav-admin/manage/user/create']);
@@ -261,18 +269,26 @@ export class PageUserComponent implements OnInit {
         if (r?.id) {
           switch (type) {
             case '通过认证':
-              if(!r?.get('department')?.id){
-                this.message.warning('该用户暂未绑定所属单位')
-                return
+              if (!r?.get('department')?.id) {
+                this.message.warning('该用户暂未绑定所属单位');
+                return;
               }
-              if(data?.get('identity') == '工作联系人'){
-                let auth = await this.tbookSer.updateProfileSubmitted(data?.id,'save',r?.get('department')?.id,this.message)
-                if(!auth) return
+              if (data?.get('identity') == '工作联系人') {
+                let auth = await this.tbookSer.updateProfileSubmitted(
+                  data?.id,
+                  'save',
+                  r?.get('department')?.id,
+                  this.message
+                );
+                if (!auth) return;
               }
               r?.set('accountState', '已认证');
-              Parse.Cloud.run('aliSmsSend',{
-                "mobileList": [data?.get('user')?.get('phone')],"templateCode":"SMS_468870790","params":{},"signName":"普通高等教育教材网"
-              })
+              Parse.Cloud.run('aliSmsSend', {
+                mobileList: [data?.get('user')?.get('phone')],
+                templateCode: 'SMS_468870790',
+                params: {},
+                signName: '普通高等教育教材网',
+              });
               await r?.save();
               break;
             case '禁用':
@@ -307,15 +323,15 @@ export class PageUserComponent implements OnInit {
         );
         let deletePromiseList = selectedList.map((item: any) => {
           return new Promise(async (resolve) => {
-            await item.get('user')?.destroy()
-            await item.destroy()
-            resolve(true)
+            await item.get('user')?.destroy();
+            await item.destroy();
+            resolve(true);
           });
         });
         try {
           await Promise.all(deletePromiseList);
           this.setOfCheckedId = new Set<string>();
-          this.checkedAll = false
+          this.checkedAll = false;
           this.getProfile();
         } catch (err) {}
       },
@@ -324,7 +340,21 @@ export class PageUserComponent implements OnInit {
     });
   }
   goDateil(id: string) {
-    this.route.navigate(['/nav-admin/manage/user/edit', { id: id }],{queryParams:{page:this.pageIndex}});
+    let url = '';
+    switch (this.tbookSer.profile.identity) {
+      case '国家级管理员':
+        url = '/nav-admin/manage/user/edit';
+        break;
+      case '工作联系人':
+        url = '/nav-province-contact/manage/user/edit';
+        break;
+      case '高校联系人':
+        url = '/nav-province-school-contact/manage/user/edit';
+        break;
+    }
+    this.route.navigate([url, { id: id }], {
+      queryParams: { page: this.pageIndex },
+    });
   }
 
   /* 添加用户 */
@@ -356,8 +386,12 @@ export class PageUserComponent implements OnInit {
       //     type: res.get('type'),
       //   },
       // ];
-      this.parentList = await this.getDepart(this.tbookSer.profile.user.department?.objectId);
-      this.parentMap = await this.formatNode(this.tbookSer.profile.user.department?.objectId);
+      this.parentList = await this.getDepart(
+        this.tbookSer.profile.user.department?.objectId
+      );
+      this.parentMap = await this.formatNode(
+        this.tbookSer.profile.user.department?.objectId
+      );
     } else {
       this.parentList = await this.getDepart();
     }
@@ -406,10 +440,11 @@ export class PageUserComponent implements OnInit {
       this.parentMap = [];
       return;
     }
-    if (index == this.parentMap.length - 1){
-      if(this.parentList.length == 0 ) this.parentList = await this.getDepart(data?.key);
+    if (index == this.parentMap.length - 1) {
+      if (this.parentList.length == 0)
+        this.parentList = await this.getDepart(data?.key);
       return;
-    } 
+    }
     this.parentMap.splice((index || 0) + 1);
     this.parentList = await this.getDepart(data?.key);
   }
@@ -434,7 +469,9 @@ export class PageUserComponent implements OnInit {
       this.account.department = { title: e.title, id: e.key };
       this.account.companyType = e.branch || e.title;
       this.userType = this.parents.some((item) => e.parent == item.key)
-        ? !e.type ? ['工作联系人'] : ['评审专家', '工作联系人', '教师']
+        ? !e.type
+          ? ['工作联系人']
+          : ['评审专家', '工作联系人', '教师']
         : e.type == '单位'
         ? ['评审专家', '高校联系人', '教师']
         : ['评审专家', '教师'];
@@ -471,18 +508,18 @@ export class PageUserComponent implements OnInit {
     console.log(this.account.password);
   }
   /* 添加账号 */
-  isLoadingOne:boolean = false
+  isLoadingOne: boolean = false;
   async accountComplete() {
-    if(this.isLoadingOne) return
-    this.isLoadingOne = true
+    if (this.isLoadingOne) return;
+    this.isLoadingOne = true;
     this.account.username = this.account?.username.trim();
     this.account.email = this.account?.email.trim();
     this.account.phone = this.account?.phone.trim();
     this.account.name = this.account?.name.trim();
     this.account.password = this.account?.password.trim();
-    if(!await this.authVrifly()){
-      this.isLoadingOne = false
-      return
+    if (!(await this.authVrifly())) {
+      this.isLoadingOne = false;
+      return;
     }
     try {
       let obj = Parse.Object.extend('_User');
@@ -509,12 +546,15 @@ export class PageUserComponent implements OnInit {
       profile?.set('email', this.account.email);
       profile?.set('identity', this.account.identity);
       let res = await profile?.save();
-      this.isLoadingOne = false
+      this.isLoadingOne = false;
       this.accountIsVisible = false;
       this.account = null;
-      Parse.Cloud.run('aliSmsSend',{
-        "mobileList": [this.account?.phone],"templateCode":"SMS_469060724","params":{},"signName":"普通高等教育教材网"
-      })
+      Parse.Cloud.run('aliSmsSend', {
+        mobileList: [this.account?.phone],
+        templateCode: 'SMS_469060724',
+        params: {},
+        signName: '普通高等教育教材网',
+      });
       this.modal.success({
         nzTitle: '添加成功',
         nzContent: '',
@@ -525,14 +565,14 @@ export class PageUserComponent implements OnInit {
       });
     } catch (err: any) {
       console.warn('添加用户错误', err);
-      this.isLoadingOne = false
+      this.isLoadingOne = false;
       this.message.error(
         err?.Error || '错误:请检查用户或邮箱及手机号是否已存在'
       );
       return;
     }
   }
-  async authVrifly():Promise< boolean | undefined>{
+  async authVrifly(): Promise<boolean | undefined> {
     this.account.password = this.account?.password.trim();
     this.account.email = this.account?.email.trim();
     this.account.phone = this.account?.phone.trim();
@@ -540,8 +580,9 @@ export class PageUserComponent implements OnInit {
     if (
       !this.account?.name ||
       !this.account.department?.id ||
-      !this.account.password||
-      !this.account.phone || !this.account?.email
+      !this.account.password ||
+      !this.account.phone ||
+      !this.account?.email
     ) {
       this.message.warning('请填写必填项');
       return;
@@ -555,23 +596,28 @@ export class PageUserComponent implements OnInit {
       this.message.error('请填写正确手机号');
       return;
     }
-    let m = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
-    if(!String(this.account.email).match(m)){
-      this.message.error("邮箱格式有误");
+    let m =
+      /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
+    if (!String(this.account.email).match(m)) {
+      this.message.error('邮箱格式有误');
       return;
     }
     // if (!this.account?.email&& !this.account?.phone) {
     //   this.message.error('邮箱或手机号必须填写一项');
     //   return;
     // }
-    if(!(this.account.password.length >= 6 && this.account.password.length <= 18)){
-      this.message.error('密码格式错误,请填写6-18位非空字符串(数字、大小写字母或英文符号)');
+    if (
+      !(this.account.password.length >= 6 && this.account.password.length <= 18)
+    ) {
+      this.message.error(
+        '密码格式错误,请填写6-18位非空字符串(数字、大小写字母或英文符号)'
+      );
       return;
     }
-    if(!await this.tbookSer.userFind(this.account.phone)){
+    if (!(await this.tbookSer.userFind(this.account.phone))) {
       this.message.error('手机号已存在');
-      return
+      return;
     }
-    return true
+    return true;
   }
 }

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

@@ -130,7 +130,7 @@ export class UserEditComponent implements OnInit {
         this.tbookSer.profile.identity == '工作联系人' &&
         arr.includes(this.profile.get('identity'))
       ) {
-        this.userType = ['教师', '评审专家', '工作联系人'];
+        this.userType = ['教师', '评审专家', '高校联系人'];
         this.edit = true;
       } else if (
         this.tbookSer.profile.identity == '高校联系人' &&

+ 36 - 0
projects/textbook/src/modules/nav-province-contact/auth.guard.ts

@@ -0,0 +1,36 @@
+import { Injectable } from '@angular/core';
+import {
+  CanActivate,
+  ActivatedRouteSnapshot,
+  RouterStateSnapshot,
+} from '@angular/router';
+import { Observable } from 'rxjs';
+import { Router } from '@angular/router';
+import { textbookServer } from '../../services/textbook';
+@Injectable({
+  providedIn: 'root',
+})
+export class AuthGuard implements CanActivate {
+  LoginPage = '/user/login';
+
+  constructor(private tbookSer: textbookServer, private router: Router) {}
+
+  canActivate(
+    next: ActivatedRouteSnapshot,
+    state: RouterStateSnapshot
+  ): Observable<boolean> | Promise<boolean> | boolean {
+    // 当前路由url
+    // let url: string = state.url;
+    // console.log(url);
+    return this.checkLogin();
+  }
+  checkLogin(): boolean {
+    if (this.tbookSer.profile.identity == '工作联系人') {
+      return true;
+    }
+    // 否则重定向到login页面
+    this.router.navigate([this.LoginPage]);
+    return false;
+  }
+}
+export { CanActivate };

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

@@ -1,5 +1,5 @@
 import { NgModule } from "@angular/core";
-import { RouterModule, Routes } from "@angular/router";
+import { mapToCanActivate, RouterModule, Routes } from "@angular/router";
 import { PageUserComponent } from "../nav-admin/page-user/page-user.component";
 import { UserEditComponent } from "../nav-admin/user-edit/user-edit.component";
 import { PageProcessComponent } from "./page-process/page-process.component";
@@ -7,6 +7,7 @@ import { ProcessListComponent } from "./page-process/process-list/process-list.c
 import { PageRoleComponent } from "./page-role/page-role.component";
 import { PageTextbookComponent } from "./page-textbook/page-textbook.component";
 import { SubmittedComponent } from "./submitted/submitted.component";
+import { AuthGuard } from "./auth.guard";
 // import { PageTextbookComponent } from "./page-textbook/page-textbook.component";
 const routes: Routes = [
   {
@@ -16,6 +17,7 @@ const routes: Routes = [
   },
   {
     path: 'manage',
+    canActivate: mapToCanActivate([AuthGuard]),
     children:[
       {
         path: 'process', //流程申报

+ 136 - 132
projects/textbook/src/modules/nav-province-contact/page-process/process-list/process-list.component.html

@@ -1,3 +1,4 @@
+@if (!editLoading && eduProcessList.length > 0) {
 <nz-page-header>
   <!--title-->
   <nz-page-header-title
@@ -15,19 +16,19 @@
   <div class="tool">
     <div class="tool-left">
       <!-- <div class="search">
-        <nz-input-group style="width: 210px" [nzPrefix]="prefixTemplateUser">
-          <input
-            type="text"
-            nz-input
-            placeholder="搜索"
-            [(ngModel)]="searchValue"
-            (ngModelChange)="onSearch($event)"
-          />
-        </nz-input-group>
-        <ng-template #prefixTemplateUser
-          ><span nz-icon nzType="search"></span
-        ></ng-template>
-      </div> -->
+          <nz-input-group style="width: 210px" [nzPrefix]="prefixTemplateUser">
+            <input
+              type="text"
+              nz-input
+              placeholder="搜索"
+              [(ngModel)]="searchValue"
+              (ngModelChange)="onSearch($event)"
+            />
+          </nz-input-group>
+          <ng-template #prefixTemplateUser
+            ><span nz-icon nzType="search"></span
+          ></ng-template>
+        </div> -->
       <div class="">
         <nz-input-group style="width: 210px" [nzPrefix]="prefixTemplateUser">
           <input
@@ -47,12 +48,12 @@
   </div>
   <div class="layout" #maxWidth>
     <!-- <div class="sider" #sider>
-      <ul nz-menu>
-        @for (item of nodes; track $index) {
-        <li nz-menu-item (click)="changeDepart(item)">{{ item.title }}</li>
-        }
-      </ul>
-    </div> -->
+        <ul nz-menu>
+          @for (item of nodes; track $index) {
+          <li nz-menu-item (click)="changeDepart(item)">{{ item.title }}</li>
+          }
+        </ul>
+      </div> -->
     <div class="breadcrumb">
       <nz-table
         #tableData
@@ -71,14 +72,14 @@
         <thead>
           <tr>
             <!-- <th
-              nzEllipsis
-              nzWidth="50px"
-              nzLeft
-              [nzChecked]="checkedAll"
-              [nzIndeterminate]="indeterminate"
-              nzLabel="Select all"
-              (nzCheckedChange)="onAllChecked($event)"
-            ></th> -->
+                nzEllipsis
+                nzWidth="50px"
+                nzLeft
+                [nzChecked]="checkedAll"
+                [nzIndeterminate]="indeterminate"
+                nzLabel="Select all"
+                (nzCheckedChange)="onAllChecked($event)"
+              ></th> -->
             <th nzEllipsis nzWidth="120px" nzLeft>流程名称</th>
             <!-- <th nzEllipsis nzWidth="120px">流程code</th> -->
             <th nzEllipsis nzWidth="120px">流程描述</th>
@@ -92,11 +93,11 @@
           @for (data of tableData.data; track data.id) {
           <tr>
             <!-- <td
-              nzEllipsis
-              nzLeft
-              [nzChecked]="setOfCheckedId.has(data.id)"
-              (nzCheckedChange)="onItemChecked(data.id, $event)"
-            ></td> -->
+                nzEllipsis
+                nzLeft
+                [nzChecked]="setOfCheckedId.has(data.id)"
+                (nzCheckedChange)="onItemChecked(data.id, $event)"
+              ></td> -->
             <td
               nzEllipsis
               (click)="
@@ -109,13 +110,17 @@
               {{ data?.get("name") || "-" }}
             </td>
             <!-- <td nzEllipsis>
-              {{ data?.get("code") || "-" }}
-            </td> -->
+                {{ data?.get("code") || "-" }}
+              </td> -->
             <td nzEllipsis>
               {{ data?.get("desc") || "-" }}
             </td>
             <td nzEllipsis>
-              {{ data?.get("num") || data?.get("num") == 0 ? data?.get("num") : "-" }}
+              {{
+                data?.get("num") || data?.get("num") == 0
+                  ? data?.get("num")
+                  : "-"
+              }}
             </td>
             <td nzEllipsis>
               {{
@@ -128,65 +133,65 @@
               >
             </td>
             <!-- <td nzEllipsis nzRight>
-              <button
-                nz-button
-                nz-dropdown
-                [nzDropdownMenu]="menu"
-                [nzPlacement]="'bottomLeft'"
-              >
-                <span nz-icon nzType="ellipsis" nzTheme="outline"></span>
-              </button>
-              <nz-dropdown-menu #menu="nzDropdownMenu">
-                <ul nz-menu>
-                  @if (statusMap[data.id].strat){
-                  <li nz-menu-item>
-                    <button
-                      nz-button
-                      nzType="link"
-                      style="color: #231c1f"
-                      (click)="onStatusChange(data, 'strat', true)"
-                    >
-                      <span
-                        nz-icon
-                        nzType="caret-right"
-                        nzTheme="outline"
-                      ></span
-                      >开始流程
-                    </button>
-                  </li>
-                  } @if (statusMap[data.id].stop){
-                  <li nz-menu-item>
-                    <button
-                      nz-button
-                      nzType="link"
-                      style="color: #231c1f"
-                      (click)="onStatusChange(data, 'stop', true)"
-                    >
-                      <span
-                        nz-icon
-                        nzType="pause-circle"
-                        nzTheme="outline"
-                      ></span
-                      >暂停流程
-                    </button>
-                  </li>
-                  } @if (statusMap[data.id].end){
-                  <li nz-menu-item>
-                    <button
-                      nz-button
-                      nzType="link"
-                      style="color: #231c1f"
-                      (click)="onStatusChange(data, 'end', true)"
-                    >
-                      <span nz-icon nzType="stop" nzTheme="outline"></span
-                      >结束流程
-                    </button>
-                  </li>
-                  } @if (statusMap[data.id].del){
-                  }
-                </ul>
-              </nz-dropdown-menu>
-            </td> -->
+                <button
+                  nz-button
+                  nz-dropdown
+                  [nzDropdownMenu]="menu"
+                  [nzPlacement]="'bottomLeft'"
+                >
+                  <span nz-icon nzType="ellipsis" nzTheme="outline"></span>
+                </button>
+                <nz-dropdown-menu #menu="nzDropdownMenu">
+                  <ul nz-menu>
+                    @if (statusMap[data.id].strat){
+                    <li nz-menu-item>
+                      <button
+                        nz-button
+                        nzType="link"
+                        style="color: #231c1f"
+                        (click)="onStatusChange(data, 'strat', true)"
+                      >
+                        <span
+                          nz-icon
+                          nzType="caret-right"
+                          nzTheme="outline"
+                        ></span
+                        >开始流程
+                      </button>
+                    </li>
+                    } @if (statusMap[data.id].stop){
+                    <li nz-menu-item>
+                      <button
+                        nz-button
+                        nzType="link"
+                        style="color: #231c1f"
+                        (click)="onStatusChange(data, 'stop', true)"
+                      >
+                        <span
+                          nz-icon
+                          nzType="pause-circle"
+                          nzTheme="outline"
+                        ></span
+                        >暂停流程
+                      </button>
+                    </li>
+                    } @if (statusMap[data.id].end){
+                    <li nz-menu-item>
+                      <button
+                        nz-button
+                        nzType="link"
+                        style="color: #231c1f"
+                        (click)="onStatusChange(data, 'end', true)"
+                      >
+                        <span nz-icon nzType="stop" nzTheme="outline"></span
+                        >结束流程
+                      </button>
+                    </li>
+                    } @if (statusMap[data.id].del){
+                    }
+                  </ul>
+                </nz-dropdown-menu>
+              </td> -->
           </tr>
           }
         </tbody>
@@ -198,44 +203,43 @@
   </div>
 </div>
 <!-- 全选操作:批量操作 -->
-<div class="batch-toolbar-modal" *ngIf="setOfCheckedId?.size">
-  <div class="batch-toolbar">
-    <div class="styles_counter__18S08">
-      <span>已选</span>
-      <span class="styles_num__178Wa">{{ setOfCheckedId.size }}</span>
-    </div>
-    <!-- <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)="statusSelected('del')">
-            <span nz-icon nzType="delete"></span>
-            删除
-          </button>
-        </div>
+<!-- <div class="batch-toolbar-modal" *ngIf="setOfCheckedId?.size">
+    <div class="batch-toolbar">
+      <div class="styles_counter__18S08">
+        <span>已选</span>
+        <span class="styles_num__178Wa">{{ setOfCheckedId.size }}</span>
+      </div>
+      <div class="styles_cancel__AARoT">
+        <button nz-button nzType="text" (click)="statusSelected('strat')">
+          <span nz-icon nzType="caret-right" nzTheme="outline"></span>
+          批量开始
+        </button>
+      </div>
+      <div class="styles_cancel__AARoT">
+        <button nz-button nzType="text" (click)="statusSelected('stop')">
+          <span nz-icon nzType="pause-circle" nzTheme="outline"></span>
+          批量暂停
+        </button>
+      </div>
+      <div class="styles_cancel__AARoT">
+        <button nz-button nzType="text" (click)="statusSelected('end')">
+          <span nz-icon nzType="stop" nzTheme="outline"></span>
+          批量结束
+        </button>
+      </div>
+      <div class="styles_cancel__AARoT">
+        <button nz-button nzType="text" (click)="onAllChecked(false)">
+          取消选中
+        </button>
       </div>
-    </div> -->
-    <div class="styles_cancel__AARoT">
-      <button nz-button nzType="text" (click)="statusSelected('strat')">
-        <span nz-icon nzType="caret-right" nzTheme="outline"></span>
-        批量开始
-      </button>
-    </div>
-    <div class="styles_cancel__AARoT">
-      <button nz-button nzType="text" (click)="statusSelected('stop')">
-        <span nz-icon nzType="pause-circle" nzTheme="outline"></span>
-        批量暂停
-      </button>
-    </div>
-    <div class="styles_cancel__AARoT">
-      <button nz-button nzType="text" (click)="statusSelected('end')">
-        <span nz-icon nzType="stop" nzTheme="outline"></span>
-        批量结束
-      </button>
-    </div>
-    <div class="styles_cancel__AARoT">
-      <button nz-button nzType="text" (click)="onAllChecked(false)">
-        取消选中
-      </button>
     </div>
+  </div> -->
+}
+@else if (editLoading) {
+  <div class="loading">
+    <nz-spin nzSimple [nzSize]="'large'"></nz-spin>
   </div>
-</div>
+}
+@else {
+  <nz-empty style="margin: 100px auto;" nzNotFoundContent="暂未绑定对应单位管理员,请联系工作人员"></nz-empty> 
+}

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

@@ -94,6 +94,18 @@
     }
   }
 }
+.loading{
+  position: fixed;
+  top: 0;
+  left: 0;
+  width: 100vw;
+  text-align: center;
+  height: 100vh;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  background: rgb(0 0 0 / 30%);
+}
 // 选中,批量操作区域
 .batch-toolbar-modal{
   position: fixed;

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

@@ -141,6 +141,16 @@ export class ProcessListComponent implements OnInit {
         del: true,
       };
     }
+    if (e?.get('deadline') && new Date() > new Date(e?.get('deadline'))) {
+      return {
+        title: '已逾期',
+        color: 'red',
+        strat: true,
+        stop: false,
+        end: false,
+        del: true,
+      };
+    }
     if (
       e.get('status') == '200' &&
       e?.get('startDate') &&
@@ -155,16 +165,6 @@ export class ProcessListComponent implements OnInit {
         del: false,
       };
     }
-    if (e?.get('deadline') && new Date() > new Date(e?.get('deadline'))) {
-      return {
-        title: '已逾期',
-        color: 'red',
-        strat: true,
-        stop: false,
-        end: false,
-        del: true,
-      };
-    }
     if (e.get('status') == '300') {
       return {
         title: '已公示',
@@ -177,6 +177,8 @@ export class ProcessListComponent implements OnInit {
     }
     return;
   };
+  editLoading:boolean = true
+
   constructor(
     public tbookSer: textbookServer,
     private route: Router,
@@ -260,6 +262,7 @@ export class ProcessListComponent implements OnInit {
     query.notEqualTo('isDeleted', true);
     query.equalTo('department',this.tbookSer.profile.user.department?.objectId)
     query.descending('createdAt');
+    query.equalTo('profileSubmitted',this.tbookSer?.profile?.objectId)
     let r = await query.find();
     // let list: any[] = [];
     r.forEach((item) => {
@@ -269,6 +272,7 @@ export class ProcessListComponent implements OnInit {
       this.statusMap[item.id] = this.formatStatus(item);
     });
     this.eduProcessList = r;
+    this.editLoading = false
     this.loading = false;
   }
   //分页切换

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

@@ -1,3 +1,4 @@
+@if (!editLoading && eduProcess?.id) {
 <nz-page-header>
   <nz-page-header-title
     >申报单位管理
@@ -688,3 +689,12 @@
     </div>
   </div>
 </div>
+}
+@else if (editLoading) {
+  <div class="page-loading">
+    <nz-spin nzSimple [nzSize]="'large'"></nz-spin>
+  </div>
+}
+@else {
+  <nz-empty style="margin: 100px auto;" nzNotFoundContent="暂未绑定对应单位管理员,请联系工作人员"></nz-empty> 
+}

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

@@ -162,7 +162,18 @@
   font-size: 24px;
   margin-left: 8px;
 }
-
+.page-loading{
+  position: fixed;
+  top: 0;
+  left: 0;
+  width: 100vw;
+  text-align: center;
+  height: 100vh;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  background: rgb(0 0 0 / 30%);
+}
 input:-webkit-autofill,
 input:-webkit-autofill:hover,
 input:-webkit-autofill:focus,

+ 27 - 2
projects/textbook/src/modules/nav-province-contact/page-role/page-role.component.ts

@@ -125,6 +125,9 @@ export class PageRoleComponent implements OnInit {
     companyType: '',
     identity: '',
   };
+  eduProcess?: Parse.Object;
+  editLoading:boolean = true
+
   constructor(
     public tbookSer: textbookServer,
     private route: Router,
@@ -152,9 +155,19 @@ export class PageRoleComponent implements OnInit {
   async refresh() {
     if (!this.tbookSer.profile.user.department?.objectId) {
       this.message.warning('权限不足');
-      history.back();
+      // history.back();
       return;
     }
+    let queryEduProcess = new Parse.Query('EduProcess');
+    queryEduProcess.notEqualTo('isDeleted', true);
+    queryEduProcess.equalTo('department', this.tbookSer.profile.user.department?.objectId)
+    if(this.tbookSer.profile.identity == '工作联系人'){
+      queryEduProcess.equalTo('profileSubmitted',this.tbookSer?.profile?.objectId)
+    }
+    queryEduProcess.select('objectId')
+    this.eduProcess = await queryEduProcess.first();
+    this.editLoading = false
+
     let query = new Parse.Query('Department');
     query.equalTo('objectId', this.tbookSer.profile.user.department?.objectId);
     query.select('code', 'name', 'branch', 'parent', 'type', 'hasChildren');
@@ -681,7 +694,19 @@ export class PageRoleComponent implements OnInit {
     this.message.warning('权限灰度中');
   }
   goDateil(id: string) {
-    this.route.navigate(['/nav-admin/manage/user/edit', { id: id }]);
+    let url = '';
+    switch (this.tbookSer.profile.identity) {
+      case '国家级管理员':
+        url = '/nav-admin/manage/user/edit';
+        break;
+      case '工作联系人':
+        url = '/nav-province-contact/manage/user/edit';
+        break;
+      case '高校联系人':
+        url = '/nav-province-school-contact/manage/user/edit';
+        break;
+    }
+    this.route.navigate([url, { id: id }]);
   }
   randomPassword() {
     this.account.password = this.tbookSer.randomPassword();

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

@@ -1,54 +1,53 @@
-<nz-page-header>
-  <nz-page-header-title
-    >全部教材
-    <br />
-    <div class="subtitle">
-      查看全部申报流程所提交的教材推荐表
-    </div>
-  </nz-page-header-title>
-  <nz-page-header-extra>
-    <nz-space>
-      <button
-        style="background: #3e49b3; border: 1px #3e49b3"
-        *nzSpaceItem
-        nz-button
-        nzType="primary"
-        (click)="submitted()"
-      >
-      提交推荐教材列表
-      </button>
-    </nz-space>
-  </nz-page-header-extra>
-</nz-page-header>
-<!-- <comp-table-list
-  #list
-  [schema]="EduTextbook"
-  *ngIf="className && fieldsArray"
-  [className]="className"
-  [fieldsArray]="fieldsArray"
-  [queryParams]="queryParams"
-></comp-table-list> -->
-<!-- <div class="conetent">
-  <app-textbook [depart]="this.tbookSer.profile.user.department?.objectId" [limit]="15" [filterObj]="filterObj"></app-textbook>
-</div> -->
-<div class="conetent">
-  <nz-tabset [(nzSelectedIndex)]="active">
-    <nz-tab nzTitle="待评审教材">
-      @if (!active && eduProcess) {
-        <app-textbook
-        [eduProcess]="eduProcess"
-        [filterObj]="beforeFilterObj"
-      ></app-textbook>
-      }
-    </nz-tab>
-    <nz-tab nzTitle="推荐教材">
-      @if (active && eduProcess) {
-        <app-textbook
-        [filterObj]="afterFilterObj"
-        [recommend]="true"
-        [eduProcess]="eduProcess"
+@if (!editLoading && eduProcess?.id) {
+  <nz-page-header>
+    <nz-page-header-title
+      >全部教材
+      <br />
+      <div class="subtitle">
+        查看全部申报流程所提交的教材推荐表
+      </div>
+    </nz-page-header-title>
+    <nz-page-header-extra>
+      <nz-space>
+        <button
+          style="background: #3e49b3; border: 1px #3e49b3"
+          *nzSpaceItem
+          nz-button
+          nzType="primary"
+          (click)="submitted()"
+        >
+        提交推荐教材列表
+        </button>
+      </nz-space>
+    </nz-page-header-extra>
+  </nz-page-header>
+  <div class="conetent">
+    <nz-tabset [(nzSelectedIndex)]="active">
+      <nz-tab nzTitle="待评审教材">
+        @if (!active) {
+          <app-textbook
+          [eduProcess]="eduProcess"
+          [filterObj]="beforeFilterObj"
         ></app-textbook>
-      }
-    </nz-tab>
-  </nz-tabset>
-</div>
+        }
+      </nz-tab>
+      <nz-tab nzTitle="推荐教材">
+        @if (active) {
+          <app-textbook
+          [filterObj]="afterFilterObj"
+          [recommend]="true"
+          [eduProcess]="eduProcess"
+          ></app-textbook>
+        }
+      </nz-tab>
+    </nz-tabset>
+  </div>
+}
+@else if (editLoading) {
+  <div class="loading">
+    <nz-spin nzSimple [nzSize]="'large'"></nz-spin>
+  </div>
+}
+@else {
+  <nz-empty style="margin: 100px auto;" nzNotFoundContent="暂未绑定对应单位管理员,请联系工作人员"></nz-empty> 
+}

+ 12 - 0
projects/textbook/src/modules/nav-province-contact/page-textbook/page-textbook.component.scss

@@ -27,3 +27,15 @@
 ::ng-deep .ant-tabs-tab-btn:active {
   color: #e97488;
 }
+.loading{
+  position: fixed;
+  top: 0;
+  left: 0;
+  width: 100vw;
+  text-align: center;
+  height: 100vh;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  background: rgb(0 0 0 / 30%);
+}

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

@@ -65,6 +65,7 @@ export class PageTextbookComponent implements OnInit {
     },
   };
   eduProcess?: Parse.Object;
+  editLoading:boolean = true
 
   constructor(
     public tbookSer: textbookServer,
@@ -94,11 +95,12 @@ export class PageTextbookComponent implements OnInit {
     );
     if (!parentMap[1]?.key) return;
     let query = new Parse.Query('EduProcess');
-    query.equalTo('department', parentMap[1]?.key);
+    // query.equalTo('department', parentMap[1]?.key);
     // query.lessThanOrEqualTo('startDate', new Date());
     // query.greaterThan('deadline', new Date());
     query.notEqualTo('isDeleted', true);
     // query.notEqualTo('status', '100');
+    query.equalTo('profileSubmitted',this.tbookSer?.profile?.objectId)
     let res = await query.first();
     let vrifly = await this.tbookSer.getEduProcess(parentMap[1]?.key);
     if (vrifly) {
@@ -112,6 +114,7 @@ export class PageTextbookComponent implements OnInit {
         export: true,
       };
     }
+    this.editLoading = false
     this.eduProcess = res;
   }
   toUrl(url: string, params?: object) {
@@ -130,6 +133,10 @@ export class PageTextbookComponent implements OnInit {
       );
       return;
     }
+    if(this.eduProcess?.get('deadline') && new Date() > new Date(this.eduProcess?.get('deadline'))){
+      this.message.warning('流程已逾期');
+      return
+    }
     // this.eduProcess?.set('status', '400');
     // this.eduProcess?.set('releaseDate', new Date());
     let query = new Parse.Query('EduTextbook');

+ 36 - 0
projects/textbook/src/modules/nav-province-school-contact/auth.guard.ts

@@ -0,0 +1,36 @@
+import { Injectable } from '@angular/core';
+import {
+  CanActivate,
+  ActivatedRouteSnapshot,
+  RouterStateSnapshot,
+} from '@angular/router';
+import { Observable } from 'rxjs';
+import { Router } from '@angular/router';
+import { textbookServer } from '../../services/textbook';
+@Injectable({
+  providedIn: 'root',
+})
+export class AuthGuard implements CanActivate {
+  LoginPage = '/user/login';
+
+  constructor(private tbookSer: textbookServer, private router: Router) {}
+
+  canActivate(
+    next: ActivatedRouteSnapshot,
+    state: RouterStateSnapshot
+  ): Observable<boolean> | Promise<boolean> | boolean {
+    // 当前路由url
+    // let url: string = state.url;
+    // console.log(url);
+    return this.checkLogin();
+  }
+  checkLogin(): boolean {
+    if (this.tbookSer.profile.identity == '高校联系人') {
+      return true;
+    }
+    // 否则重定向到login页面
+    this.router.navigate([this.LoginPage]);
+    return false;
+  }
+}
+export { CanActivate };

+ 3 - 1
projects/textbook/src/modules/nav-province-school-contact/modules.routes.ts

@@ -1,11 +1,12 @@
 import { NgModule } from "@angular/core";
-import { RouterModule, Routes } from "@angular/router";
+import { mapToCanActivate, RouterModule, Routes } from "@angular/router";
 import { PageUserComponent } from "../nav-admin/page-user/page-user.component";
 import { UserEditComponent } from "../nav-admin/user-edit/user-edit.component";
 import { RecycleComponent } from "../nav-author/recycle/recycle.component";
 import { SpaceComponent } from "../nav-author/space/space.component";
 import { PageRoleComponent } from "../nav-province-contact/page-role/page-role.component";
 import { PageTextbookComponent } from "./page-textbook/page-textbook.component";
+import { AuthGuard } from "./auth.guard";
 const routes: Routes = [
   {
     path: '',
@@ -14,6 +15,7 @@ const routes: Routes = [
   },
   {
     path: 'manage',
+    canActivate: mapToCanActivate([AuthGuard]),
     children:[
       {
         path: 'textbook', //全部教材

+ 3 - 1
projects/textbook/src/services/common.modules.ts

@@ -16,6 +16,7 @@ import { NzModalModule } from 'ng-zorro-antd/modal';
 import { NzSwitchModule } from 'ng-zorro-antd/switch';
 import { NzAvatarModule } from 'ng-zorro-antd/avatar';
 import { NzSpinModule } from 'ng-zorro-antd/spin';
+import { NzEmptyModule } from 'ng-zorro-antd/empty';
 @NgModule({
   exports: [
     FormsModule,
@@ -34,7 +35,8 @@ import { NzSpinModule } from 'ng-zorro-antd/spin';
     NzModalModule,
     NzSwitchModule,
     NzAvatarModule,
-    NzSpinModule
+    NzSpinModule,
+    NzEmptyModule
   ]
 })
 export class CommonCompModule { }