Эх сурвалжийг харах

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

ryanemax 9 сар өмнө
parent
commit
d606c58ef4
100 өөрчлөгдсөн 3721 нэмэгдсэн , 1158 устгасан
  1. 44 0
      README.md
  2. 18 0
      docs/Schema.md
  3. 17 1
      package-lock.json
  4. 2 1
      package.json
  5. 1 0
      projects/textbook/public/img/404-empty.svg
  6. BIN
      projects/textbook/public/img/approval-no-permissions.png
  7. BIN
      projects/textbook/public/img/group-empty.png
  8. BIN
      projects/textbook/public/img/pipeline-empty.png
  9. BIN
      projects/textbook/public/img/role-new-default.png
  10. BIN
      projects/textbook/public/img/sourceEmpty.png
  11. BIN
      projects/textbook/public/img/sso-empty.png
  12. BIN
      projects/textbook/public/img/webhook-empty.png
  13. BIN
      projects/textbook/public/img/whitelist-default.png
  14. 3 0
      projects/textbook/src/app/app.component.scss
  15. 1 0
      projects/textbook/src/app/app.component.ts
  16. 13 7
      projects/textbook/src/app/app.routes.ts
  17. 21 0
      projects/textbook/src/app/captcha/captcha.component.html
  18. 25 0
      projects/textbook/src/app/captcha/captcha.component.scss
  19. 28 0
      projects/textbook/src/app/captcha/captcha.component.spec.ts
  20. 140 0
      projects/textbook/src/app/captcha/captcha.component.ts
  21. 4 2
      projects/textbook/src/app/comp-comfirm-dialog/comp-comfirm-dialog.component.html
  22. 4 2
      projects/textbook/src/app/comp-comfirm-dialog/comp-comfirm-dialog.component.ts
  23. 49 0
      projects/textbook/src/app/comp-manage/comp-manage.component.html
  24. 27 2
      projects/textbook/src/app/comp-manage/comp-manage.component.scss
  25. 6 6
      projects/textbook/src/app/comp-manage/comp-manage.component.spec.ts
  26. 192 0
      projects/textbook/src/app/comp-manage/comp-manage.component.ts
  27. 35 6
      projects/textbook/src/app/comp-nav/comp-nav.component.html
  28. 29 13
      projects/textbook/src/app/comp-nav/comp-nav.component.scss
  29. 11 3
      projects/textbook/src/app/comp-nav/comp-nav.component.ts
  30. 63 8
      projects/textbook/src/app/comp-table/comp-table-list/comp-table-list.component.html
  31. 65 0
      projects/textbook/src/app/comp-table/comp-table-list/comp-table-list.component.scss
  32. 81 4
      projects/textbook/src/app/comp-table/comp-table-list/comp-table-list.component.ts
  33. 2 2
      projects/textbook/src/app/comp-table/parse-data.service.ts
  34. 0 3
      projects/textbook/src/app/comp-user/comp-user.component.html
  35. 7 3
      projects/textbook/src/app/comp-user/comp-user.component.scss
  36. 8 0
      projects/textbook/src/index.html
  37. 277 0
      projects/textbook/src/modules/login/account-info/account-info.component.html
  38. 88 0
      projects/textbook/src/modules/login/account-info/account-info.component.scss
  39. 6 6
      projects/textbook/src/modules/login/account-info/account-info.component.spec.ts
  40. 251 0
      projects/textbook/src/modules/login/account-info/account-info.component.ts
  41. 11 3
      projects/textbook/src/modules/login/common.modules.ts
  42. 40 72
      projects/textbook/src/modules/login/login/login.component.html
  43. 84 30
      projects/textbook/src/modules/login/login/login.component.scss
  44. 191 56
      projects/textbook/src/modules/login/login/login.component.ts
  45. 69 0
      projects/textbook/src/modules/login/login/parse-authing.ts
  46. 5 0
      projects/textbook/src/modules/login/modules.routes.ts
  47. 2 2
      projects/textbook/src/modules/login/register/register.component.html
  48. 2 2
      projects/textbook/src/modules/login/reset-password/reset-password.component.html
  49. 15 17
      projects/textbook/src/modules/nav-admin/modules.routes.ts
  50. 32 0
      projects/textbook/src/modules/nav-admin/page-collection/page-collection.component.html
  51. 10 0
      projects/textbook/src/modules/nav-admin/page-collection/page-collection.component.scss
  52. 22 0
      projects/textbook/src/modules/nav-admin/page-collection/page-collection.component.spec.ts
  53. 61 0
      projects/textbook/src/modules/nav-admin/page-collection/page-collection.component.ts
  54. 0 35
      projects/textbook/src/modules/nav-admin/page-home/page-home.component.html
  55. 0 15
      projects/textbook/src/modules/nav-admin/page-home/page-home.component.scss
  56. 0 86
      projects/textbook/src/modules/nav-admin/page-home/page-home.component.ts
  57. 31 20
      projects/textbook/src/modules/nav-author/apply/apply.component.html
  58. 10 1
      projects/textbook/src/modules/nav-author/apply/apply.component.scss
  59. 35 9
      projects/textbook/src/modules/nav-author/apply/apply.component.ts
  60. 108 120
      projects/textbook/src/modules/nav-author/components/attachment/attachment.component.html
  61. 80 31
      projects/textbook/src/modules/nav-author/components/attachment/attachment.component.ts
  62. 39 32
      projects/textbook/src/modules/nav-author/components/basic-in/basic-in.component.html
  63. 167 40
      projects/textbook/src/modules/nav-author/components/basic-in/basic-in.component.ts
  64. 0 0
      projects/textbook/src/modules/nav-author/components/page-textbook/page-textbook.component.html
  65. 0 0
      projects/textbook/src/modules/nav-author/components/page-textbook/page-textbook.component.scss
  66. 0 0
      projects/textbook/src/modules/nav-author/components/page-textbook/page-textbook.component.spec.ts
  67. 5 6
      projects/textbook/src/modules/nav-author/components/page-textbook/page-textbook.component.ts
  68. 2 2
      projects/textbook/src/modules/nav-author/components/textbook-content/textbook-content.component.html
  69. 15 3
      projects/textbook/src/modules/nav-author/components/textbook-content/textbook-content.component.ts
  70. 10 11
      projects/textbook/src/modules/nav-author/components/textbook-pertain/textbook-pertain.component.html
  71. 95 21
      projects/textbook/src/modules/nav-author/components/textbook-pertain/textbook-pertain.component.ts
  72. 17 12
      projects/textbook/src/modules/nav-author/modules.routes.ts
  73. 0 35
      projects/textbook/src/modules/nav-author/page-home/page-home.component.html
  74. 0 71
      projects/textbook/src/modules/nav-author/page-home/page-home.component.ts
  75. 17 0
      projects/textbook/src/modules/nav-author/recycle/recycle.component.html
  76. 41 0
      projects/textbook/src/modules/nav-author/recycle/recycle.component.scss
  77. 6 6
      projects/textbook/src/modules/nav-author/recycle/recycle.component.spec.ts
  78. 30 0
      projects/textbook/src/modules/nav-author/recycle/recycle.component.ts
  79. 32 0
      projects/textbook/src/modules/nav-author/space/space.component.html
  80. 41 0
      projects/textbook/src/modules/nav-author/space/space.component.scss
  81. 6 6
      projects/textbook/src/modules/nav-author/space/space.component.spec.ts
  82. 29 0
      projects/textbook/src/modules/nav-author/space/space.component.ts
  83. 497 0
      projects/textbook/src/modules/nav-author/textbook-details/textbook-details.component.html
  84. 86 0
      projects/textbook/src/modules/nav-author/textbook-details/textbook-details.component.scss
  85. 24 0
      projects/textbook/src/modules/nav-author/textbook-details/textbook-details.component.spec.ts
  86. 216 0
      projects/textbook/src/modules/nav-author/textbook-details/textbook-details.component.ts
  87. 6 8
      projects/textbook/src/modules/nav-province-contact/modules.routes.ts
  88. 0 35
      projects/textbook/src/modules/nav-province-contact/page-home/page-home.component.html
  89. 0 15
      projects/textbook/src/modules/nav-province-contact/page-home/page-home.component.scss
  90. 0 50
      projects/textbook/src/modules/nav-province-contact/page-home/page-home.component.ts
  91. 6 8
      projects/textbook/src/modules/nav-province-school-contact/modules.routes.ts
  92. 0 35
      projects/textbook/src/modules/nav-province-school-contact/page-home/page-home.component.html
  93. 0 15
      projects/textbook/src/modules/nav-province-school-contact/page-home/page-home.component.scss
  94. 0 50
      projects/textbook/src/modules/nav-province-school-contact/page-home/page-home.component.ts
  95. 6 8
      projects/textbook/src/modules/nav-province-submit/modules.routes.ts
  96. 0 35
      projects/textbook/src/modules/nav-province-submit/page-home/page-home.component.html
  97. 0 15
      projects/textbook/src/modules/nav-province-submit/page-home/page-home.component.scss
  98. 0 24
      projects/textbook/src/modules/nav-province-submit/page-home/page-home.component.spec.ts
  99. 0 38
      projects/textbook/src/modules/nav-province-submit/page-home/page-home.component.ts
  100. 2 9
      projects/textbook/src/modules/nav-review/modules.routes.ts

+ 44 - 0
README.md

@@ -14,6 +14,50 @@ npm i -f
 npm run start
 ```
 
+## Authing 用户服务
+### 管理员
+https://lljydpt8egql.u2-dev.hep.com.cn/
+- 用户名 hanlei
+- 密码 13581837652
+
+### 单页面应用
+AppID 6682ab96b7bd5db59d6785a0
+
+AppSecret b800ac6533c640c3d1ea2b20ebe2e990
+
+Token 端点
+https://textbook.u2-dev.hep.com.cn/oidc/token
+
+用户信息端点
+https://textbook.u2-dev.hep.com.cn/oidc/me
+
+登出端点
+https://textbook.u2-dev.hep.com.cn/oidc/session/end
+
+JWKS 公钥端点
+https://textbook.u2-dev.hep.com.cn/oidc/.well-known/jwks.json
+
+认证端点
+https://textbook.u2-dev.hep.com.cn/oidc/auth
+
+Issuer
+https://textbook.u2-dev.hep.com.cn/oidc
+
+服务发现地址
+https://textbook.u2-dev.hep.com.cn/oidc/.well-known/openid-configuration
+
+认真地址
+https://textbook.u2-dev.hep.com.cn
+
+### 开发者AKSK
+对接 Authing SDK 的接口文档:https://api-explorer.authing.cn/?source=Authing%20%E7%AE%A1%E7%90%86%20API
+
+https://api-explorer.authing.cn/?source=Authing%20%E7%94%A8%E6%88%B7%E8%AE%A4%E8%AF%81%20API
+
+用户池 id:6672540d8756a503c6f6f03e
+
+测试用户池密钥:491670e7ef2fd553ce6d0668a1bb87f3
+
 # 国家级教材遴选系统——前端项目 edu-textbook
 
 This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 18.0.4.

+ 18 - 0
docs/Schema.md

@@ -0,0 +1,18 @@
+# 数据范式说明
+
+
+
+# 系统范式
+- _User 注册账号
+- _Role 用户组/角色
+- Profile 角色认证审核档案
+
+
+# 教材范式
+- EduTextbook
+    - 教材详情内容
+
+
+# 合集范式
+- EduCollection
+    - 配置身份、报送人、配额数量

+ 17 - 1
package-lock.json

@@ -18,6 +18,7 @@
         "@angular/platform-browser": "^18.0.0",
         "@angular/platform-browser-dynamic": "^18.0.0",
         "@angular/router": "^18.0.0",
+        "@authing/browser": "^0.0.1-alpha3",
         "@ionic/angular": "^8.2.2",
         "@ngx-translate/core": "^15.0.0",
         "@types/parse": "^3.0.9",
@@ -767,6 +768,14 @@
         "rxjs": "^6.4.0 || ^7.4.0"
       }
     },
+    "node_modules/@authing/browser": {
+      "version": "0.0.1-alpha3",
+      "resolved": "https://registry.npmmirror.com/@authing/browser/-/browser-0.0.1-alpha3.tgz",
+      "integrity": "sha512-m1KsQPZFa1BOElNPp7w4RWNY0VnpvgSx8R2a59h/DshJzVimIfpUnA1dVkcbcV9ZJWygJ2NaeWo+Sx6I0gmf5w==",
+      "dependencies": {
+        "axios": "^0.26.1"
+      }
+    },
     "node_modules/@babel/code-frame": {
       "version": "7.24.7",
       "resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.24.7.tgz",
@@ -5772,6 +5781,14 @@
         "postcss": "^8.1.0"
       }
     },
+    "node_modules/axios": {
+      "version": "0.26.1",
+      "resolved": "https://registry.npmmirror.com/axios/-/axios-0.26.1.tgz",
+      "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==",
+      "dependencies": {
+        "follow-redirects": "^1.14.8"
+      }
+    },
     "node_modules/babel-loader": {
       "version": "9.1.3",
       "resolved": "https://registry.npmmirror.com/babel-loader/-/babel-loader-9.1.3.tgz",
@@ -7830,7 +7847,6 @@
       "version": "1.15.6",
       "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.6.tgz",
       "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
-      "dev": true,
       "funding": [
         {
           "type": "individual",

+ 2 - 1
package.json

@@ -20,6 +20,7 @@
     "@angular/platform-browser": "^18.0.0",
     "@angular/platform-browser-dynamic": "^18.0.0",
     "@angular/router": "^18.0.0",
+    "@authing/browser": "^0.0.1-alpha3",
     "@ionic/angular": "^8.2.2",
     "@ngx-translate/core": "^15.0.0",
     "@types/parse": "^3.0.9",
@@ -43,4 +44,4 @@
     "karma-jasmine-html-reporter": "~2.1.0",
     "typescript": "~5.4.2"
   }
-}
+}

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 1 - 0
projects/textbook/public/img/404-empty.svg


BIN
projects/textbook/public/img/approval-no-permissions.png


BIN
projects/textbook/public/img/group-empty.png


BIN
projects/textbook/public/img/pipeline-empty.png


BIN
projects/textbook/public/img/role-new-default.png


BIN
projects/textbook/public/img/sourceEmpty.png


BIN
projects/textbook/public/img/sso-empty.png


BIN
projects/textbook/public/img/webhook-empty.png


BIN
projects/textbook/public/img/whitelist-default.png


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

@@ -0,0 +1,3 @@
+body{
+  background-color: #F9EAEA;
+}

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

@@ -19,4 +19,5 @@ export class AppComponent {
     (Parse as any).serverURL = ("http://localhost:61337/parse");
     localStorage.setItem('company','RbIKpmuaMC')
   }
+
 }

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

@@ -2,7 +2,7 @@ import { Routes,mapToCanActivate } from '@angular/router';
 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'
 export const routes: Routes = [
   { path: '',loadComponent:()=>import('../modules/textbook/page-home/page-home.component').then(m=>m.PageHomeComponent) }, // 默认跳转到 ''
   {
@@ -16,32 +16,38 @@ export const routes: Routes = [
   },
   {
     path: 'nav-admin', //国家级管理员管理平台
-    //canActivate: mapToCanActivate([AuthGuard]),
+    component: CompManageComponent,
+    canActivate: mapToCanActivate([AuthGuard]),
     loadChildren: () =>import('../modules/nav-admin/modules.routes').then((mod) => mod.NavAdminRoutingModule),
   },
   {
     path: 'nav-province-submit',//省级教育行政部门
-    //canActivate: mapToCanActivate([AuthGuard]),
+    component: CompManageComponent,
+    canActivate: mapToCanActivate([AuthGuard]),
     loadChildren: () =>import('../modules/nav-province-submit/modules.routes').then((mod) => mod.NavProRoutingModule),
   },
   {
     path: 'nav-province-contact',//中央部门所属高校联系人、部省合建高校联系人、出版单位联系人、省属高校流程管理员
-    //canActivate: mapToCanActivate([AuthGuard]),
+    component: CompManageComponent,
+    canActivate: mapToCanActivate([AuthGuard]),
     loadChildren: () =>import('../modules/nav-province-contact/modules.routes').then((mod) => mod.NavProContactRoutingModule),
   },
   {
     path: 'nav-province-school-contact', //省属高校联系人
-    //canActivate: mapToCanActivate([AuthGuard]),
+    component: CompManageComponent,
+    canActivate: mapToCanActivate([AuthGuard]),
     loadChildren: () =>import('../modules/nav-province-school-contact/modules.routes').then((mod) => mod.NavProSchoolRoutingModule),
   },
   {
     path: 'nav-review', //教材评审组成员
-    //canActivate: mapToCanActivate([AuthGuard]),
+    component: CompManageComponent,
+    canActivate: mapToCanActivate([AuthGuard]),
     loadChildren: () =>import('../modules/nav-review/modules.routes').then((mod) => mod.NavReviewRoutingModule),
   },
   {
     path: 'nav-author', //作者 / 教师 / 主编
-    //canActivate: mapToCanActivate([AuthGuard]),
+    component: CompManageComponent,
+    canActivate: mapToCanActivate([AuthGuard]),
     loadChildren: () =>import('../modules/nav-author/modules.routes').then((mod) => mod.NavAuthorRoutingModule),
   },
 ];

+ 21 - 0
projects/textbook/src/app/captcha/captcha.component.html

@@ -0,0 +1,21 @@
+<ng-container *ngIf="type == 'input'; else elseTemplate">
+  <div class="captcha">
+    <input
+      nz-input
+      class="code-input"
+      type="text"
+      [(ngModel)]="vCode"
+      maxlength="4"
+      placeholder="验证码"
+      [nzStatus]="vCode.length == 4 ? '' : 'error'"
+      (keydown)="enter($event)"
+      (change)="onChange()"
+    />
+    <div class="code-card" #canvasDom></div>
+  </div>
+</ng-container>
+<ng-template #elseTemplate>
+  <div class="captcha">
+    <div class="code-card" #canvasDom></div>
+  </div>
+</ng-template>

+ 25 - 0
projects/textbook/src/app/captcha/captcha.component.scss

@@ -0,0 +1,25 @@
+.code-card{
+  display: flex;
+  align-items: center;
+  .canvas{
+    border: 1px solid #c2def5;
+    border-radius: 5px;
+    width: 100px;
+    height: 38px;
+  }
+}
+.code-input {
+  width: 90px;
+  padding: 4px;
+  height: 38px;
+  border: 1px solid #cdcdcd;
+}
+.code-input:focus{
+  outline:1px solid #40a9ff;
+}
+  
+
+.captcha{
+  display: flex;
+  align-items: center;
+}

+ 28 - 0
projects/textbook/src/app/captcha/captcha.component.spec.ts

@@ -0,0 +1,28 @@
+/* tslint:disable:no-unused-variable */
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { By } from '@angular/platform-browser';
+import { DebugElement } from '@angular/core';
+
+import { CaptchaComponent } from './captcha.component';
+
+describe('CaptchaComponent', () => {
+  let component: CaptchaComponent;
+  let fixture: ComponentFixture<CaptchaComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ CaptchaComponent ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(CaptchaComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 140 - 0
projects/textbook/src/app/captcha/captcha.component.ts

@@ -0,0 +1,140 @@
+import {
+  Component,
+  OnInit,
+  Input,
+  Output,
+  EventEmitter,
+  ViewChild,
+  ElementRef,
+} from "@angular/core";
+import { CommonModule } from "@angular/common";
+import { FormsModule } from "@angular/forms";
+import { NzInputModule } from 'ng-zorro-antd/input';
+
+@Component({
+  imports:[CommonModule,FormsModule,NzInputModule],
+  standalone:true,
+  selector: 'fm-captcha',
+  templateUrl: './captcha.component.html',
+  styleUrls: ['./captcha.component.scss']
+})
+export class CaptchaComponent implements OnInit {
+    @ViewChild("canvasDom") canvasDom: ElementRef | any; //本地校验码绘画
+
+    @Input() type: string = 'input';  //default & input 默认input方式
+    @Input() canvas_id: string = 'canvasCode'; //元素id
+    @Input() drawCode: Array<string> = []; //验证码数组
+    @Input() vCode: string = ''; //用户输入code
+    @Output() changeVal: EventEmitter<any> = new EventEmitter(); //改变时触发
+    @Output() onEnter: EventEmitter<any> = new EventEmitter(); //enter按下触发
+    code:string = ''
+    constructor() {}
+  
+    ngOnInit() {}
+    ngAfterViewInit(): void {
+      //Called after ngAfterContentInit when the component's view has been initialized. Applies to components only.
+      //Add 'implements AfterViewInit' to the class.
+      this.updateDrawCode();
+    }
+    updateDrawCode() {
+      let canvas_width = 100;
+      let canvas_height = 38;
+      let canv = document.getElementById(this.canvas_id);
+      canv && this.canvasDom.nativeElement.removeChild(canv);
+      let _a = document.getElementById(this.canvas_id + '_a');
+      _a && this.canvasDom.nativeElement.removeChild(_a);
+      this.canvasDom.nativeElement;
+      let canvas = document.createElement("canvas");
+      canvas.className = "canvas";
+      canvas.setAttribute("id", this.canvas_id);
+      canvas.addEventListener("click", () => {
+        this.updateDrawCode();
+      });
+      let context:any = canvas.getContext("2d"); //获取到canvas画图的环境,演员表演的舞台
+      canvas.width = canvas_width;
+      canvas.height = canvas_height;
+      let sCode =
+        "A,B,C,E,F,G,H,J,K,L,M,N,P,Q,R,S,T,W,X,Y,Z,1,2,3,4,5,6,7,8,9,0,q,w,e,r,t,y,u,i,o,p,a,s,d,f,g,h,j,k,l,z,x,c,v,b,n,m";
+      let aCode = sCode.split(",");
+      let aLength = aCode.length; //获取到数组的长度
+      for (let i = 0; i <= 3; i++) {
+        let j = Math.floor(Math.random() * aLength); //获取到随机的索引值
+        let deg = (Math.random() * 30 * Math.PI) / 180; //产生0~30之间的随机弧度
+        let txt = aCode[j]; //得到随机的一个内容
+        this.drawCode[i] = txt;
+        let x = 10 + i * 20; //文字在canvas上的x坐标
+        let y = 20 + Math.random() * 8; //文字在canvas上的y坐标
+        context.font = "bold 23px 微软雅黑";
+  
+        context.translate(x, y);
+        context.rotate(deg);
+  
+        context.fillStyle = this.randomColor();
+        context.fillText(txt, 0, 0);
+  
+        context.rotate(-deg);
+        context.translate(-x, -y);
+      }
+      for (let i = 0; i <= 5; i++) {
+        //验证码上显示线条
+        context.strokeStyle = this.randomColor();
+        context.beginPath();
+        context.moveTo(
+          Math.random() * canvas_width,
+          Math.random() * canvas_height
+        );
+        context.lineTo(
+          Math.random() * canvas_width,
+          Math.random() * canvas_height
+        );
+        context.stroke();
+      }
+      for (let i = 0; i <= 30; i++) {
+        //验证码上显示小点
+        context.strokeStyle = this.randomColor();
+        context.beginPath();
+        let x = Math.random() * canvas_width;
+        let y = Math.random() * canvas_height;
+        context.moveTo(x, y);
+        context.lineTo(x + 1, y + 1);
+        context.stroke();
+      }
+      this.code = this.drawCode.join("")
+      this.changeVal.emit({
+       code:this.code,
+       vCode:this.vCode
+      });
+      this.canvasDom.nativeElement.appendChild(canvas);
+      let a = document.createElement("a");
+      a.setAttribute("id", this.canvas_id + '_a');
+      a.innerText = "看不清,换一张";
+      a.addEventListener("click", () => {
+        this.updateDrawCode();
+      });
+      this.canvasDom.nativeElement.appendChild(a);
+    }
+    /* 得到随机的颜色值 */
+    randomColor() {
+      let r = Math.floor(Math.random() * 256);
+      let g = Math.floor(Math.random() * 256);
+      let b = Math.floor(Math.random() * 256);
+      return "rgb(" + r + "," + g + "," + b + ")";
+    }
+    //按下确认键触发
+    enter(e:any) {
+      if (e.keyCode == 13) {
+        this.changeVal.emit({
+          code:this.code,
+          vCode:this.vCode
+        });
+        this.onEnter.emit()
+      }
+    }
+    onChange(){
+      this.changeVal.emit({
+        code:this.code,
+        vCode:this.vCode
+      });
+    }
+  }
+  

+ 4 - 2
projects/textbook/src/app/comp-comfirm-dialog/comp-comfirm-dialog.component.html

@@ -3,6 +3,8 @@
   <p>{{data?.message}}</p>
 </div>
 <div mat-dialog-actions>
-  <button mat-button (click)="confirm(false)" >{{'取消'|translate}}</button>
-  <button mat-button (click)="confirm(true)" >{{'确认'|translate}}</button>
+  <!-- <button mat-button (click)="confirm(false)" >{{'取消'}}</button>
+  <button mat-button (click)="confirm(true)">{{'确认'}}</button> -->
+  <button nz-button nzType="text" nzShape="round" (click)="confirm(false)" >取消</button>
+  <button nz-button nzType="text" [nzDanger]="data?.danger" nzShape="round" (click)="confirm(true)">确认</button>
 </div>

+ 4 - 2
projects/textbook/src/app/comp-comfirm-dialog/comp-comfirm-dialog.component.ts

@@ -2,7 +2,7 @@ import { CommonModule } from '@angular/common';
 import { Component, Inject } from '@angular/core';
 import { MatButtonModule } from '@angular/material/button';
 import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
-import { TranslateModule } from '@ngx-translate/core';
+import { NzButtonModule } from 'ng-zorro-antd/button';
 
 @Component({
   selector: 'app-comp-comfirm-dialog',
@@ -11,7 +11,7 @@ import { TranslateModule } from '@ngx-translate/core';
     CommonModule,
     MatButtonModule,
     MatDialogModule,
-    TranslateModule,
+    NzButtonModule,
   ],
   templateUrl: './comp-comfirm-dialog.component.html',
   styleUrls: ['./comp-comfirm-dialog.component.scss']
@@ -22,6 +22,8 @@ export class CompComfirmDialogComponent {
     @Inject(MAT_DIALOG_DATA) public data: {
       title:string|null,
       message:string|null,
+      mode?:string|null,
+      danger?:boolean|null,
     },
   ){
   }

+ 49 - 0
projects/textbook/src/app/comp-manage/comp-manage.component.html

@@ -0,0 +1,49 @@
+<div class="page">
+  <div class="content-left" [style.width]="isCollapsed ? '' : '248px'">
+    <div class="btn-menu">
+      <button mat-icon-button (click)="toggleCollapsed()" aria-label="LogOut" style="margin-right: 4px;">
+        <mat-icon
+        svgIcon="menu"
+        ></mat-icon>
+      </button>
+      {{ isCollapsed ? "" : "教材遴选系统" }}
+    </div>
+
+    <ul
+      [nzInlineCollapsed]="isCollapsed"
+      nz-menu
+      nzMode="inline"
+      style="width: 100%; background: #f9eaea"
+    >
+      @for (item of optionsMap[textbook.profile?.identity]; track item.id;let index = $index) { @if(item.child)
+      {
+      <li nz-submenu [nzTitle]="item.name" nzIcon="api" [nzOpen]="true">
+        <ul>
+          @for (child of item.child; track child.id;let idx = $index) {
+          <li
+            nz-menu-item
+            [nzSelected]="active == child.id"
+            (click)="toUrl(child)"
+          >
+            {{ child.name }}
+          </li>
+          }
+        </ul>
+      </li>
+      } @else {
+      <li nz-menu-item (click)="toUrl(item)" [nzSelected]="active == item.id">
+        <span nz-icon nzType="home" nzTheme="outline"></span>
+        <span>{{ item.name }}</span>
+      </li>
+      } }
+    </ul>
+    <app-comp-nav
+      [viewCollapsed]="isCollapsed"
+      class="left-fonter"
+      [style.width]="isCollapsed ? '248px' : ''"
+    ></app-comp-nav>
+  </div>
+  <div class="preview">
+    <router-outlet></router-outlet>
+  </div>
+</div>

+ 27 - 2
projects/textbook/src/modules/nav-author/page-home/page-home.component.scss → projects/textbook/src/app/comp-manage/comp-manage.component.scss

@@ -1,20 +1,39 @@
 .page{
   font-family: PingFang SC;
   display: flex;
-  height: calc(100% - 60px);
+  // height: calc(100% - 60px);
   // overflow-y: scroll;
   overflow-y: hidden;
+  height: 100vh;
+  background-color: #F9EAEA;
+  padding: 10px;
   .content-left{
+    position: relative;
     background-color:#f9eaea;
+    // width: 248px;
+    overflow: hidden;
+    .btn-menu{
+      padding: 10px;
+      display: flex;
+      align-items: center;
+    }
+    .left-fonter{
+      width: 248px;
+      position: absolute;
+      bottom: 0;
+      left: 0;
+    }
   }
   .preview{
     height: 100%;
     overflow-y: scroll;
     padding: 0 0 40px 0;
     flex: 1;
+    background-color: white;
+    border-radius: 10px;
   }
-
 }
+
 ::ng-deep .ant-menu-sub.ant-menu-inline{
   background: #f9eaea;
 }
@@ -24,6 +43,9 @@
 ::ng-deep .ant-menu-light .ant-menu-submenu-title:hover{
   color: #c6233f !important;
 }
+::ng-deep .ant-menu-submenu:hover > .ant-menu-submenu-title > .ant-menu-submenu-arrow{
+  color: #c6233f !important;
+}
 ::ng-deep .ant-menu-inline .ant-menu-item::after{
   border-right: 3px solid #c6233f;
 }
@@ -34,4 +56,7 @@
 ::ng-deep .ant-menu-submenu-selected{
   background-color: #f4cbcd;
   color: #c6233f !important;
+}
+::ng-deep  .ant-menu-light .ant-menu-submenu-active{
+  color:black;
 }

+ 6 - 6
projects/textbook/src/modules/nav-admin/page-home/page-home.component.spec.ts → projects/textbook/src/app/comp-manage/comp-manage.component.spec.ts

@@ -1,19 +1,19 @@
 import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
 import { IonicModule } from '@ionic/angular';
 
-import { PageHomeComponent } from './page-home.component';
+import { CompManageComponent } from './comp-manage.component';
 
-describe('PageHomeComponent', () => {
-  let component: PageHomeComponent;
-  let fixture: ComponentFixture<PageHomeComponent>;
+describe('CompManageComponent', () => {
+  let component: CompManageComponent;
+  let fixture: ComponentFixture<CompManageComponent>;
 
   beforeEach(waitForAsync(() => {
     TestBed.configureTestingModule({
-      declarations: [ PageHomeComponent ],
+      declarations: [ CompManageComponent ],
       imports: [IonicModule.forRoot()]
     }).compileComponents();
 
-    fixture = TestBed.createComponent(PageHomeComponent);
+    fixture = TestBed.createComponent(CompManageComponent);
     component = fixture.componentInstance;
     fixture.detectChanges();
   }));

+ 192 - 0
projects/textbook/src/app/comp-manage/comp-manage.component.ts

@@ -0,0 +1,192 @@
+import { Component, OnInit} from '@angular/core';
+import { CompNavComponent } from '../comp-nav/comp-nav.component';
+import {DomSanitizer} from '@angular/platform-browser';
+import { RouterOutlet, Router } from '@angular/router';
+import { CommonCompModule } from '../../services/common.modules';
+import { MatIconRegistry, MatIconModule } from '@angular/material/icon';
+import { textbookServer } from '../../services/textbook';
+@Component({
+  selector: 'app-comp-manage',
+  standalone: true,
+  imports: [CompNavComponent, RouterOutlet, CommonCompModule,MatIconModule],
+  templateUrl: './comp-manage.component.html',
+  styleUrls: ['./comp-manage.component.scss'],
+})
+export class CompManageComponent implements OnInit {
+  MENU_ICON:string = `<svg width="18" height="20" viewBox="0 0 18 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+  <path d="M18 2H4C3.46957 2 2.96086 2.21071 2.58579 2.58579C2.21071 2.96086 2 3.46957 2 4C2 4.53043 2.21071 5.03914 2.58579 5.41421C2.96086 5.78929 3.46957 6 4 6H18V19C18 19.2652 17.8946 19.5196 17.7071 19.7071C17.5196 19.8946 17.2652 20 17 20H4C2.93913 20 1.92172 19.5786 1.17157 18.8284C0.421427 18.0783 0 17.0609 0 16V4C0 2.93913 0.421427 1.92172 1.17157 1.17157C1.92172 0.421427 2.93913 0 4 0H17C17.2652 0 17.5196 0.105357 17.7071 0.292893C17.8946 0.48043 18 0.734783 18 1V2Z" fill="url(#paint0_linear_5_11023)"/>
+  <defs>
+  <linearGradient id="paint0_linear_5_11023" x1="9" y1="-2.21282e-07" x2="25.5" y2="40" gradientUnits="userSpaceOnUse">
+  <stop stop-color="#E04860"/>
+  <stop offset="1" stop-color="#E99306"/>
+  </linearGradient>
+  </defs>
+  </svg>
+  `
+  optionsMap: any = {
+    "国家级管理员":[
+      {
+        name:'教材管理',
+        id:'1',
+        child:[
+          {
+            name:'报送合集',
+            path:"/nav-admin/manage/collection",
+            id:'1-1',
+          },
+          {
+            name:'全部材料',
+            id:'1-2',
+          },
+        ]
+      },
+      {
+        name:'用户管理',
+        id:'2',
+        child:[
+          {
+            name:'用户审核',
+            id:'2-1',
+          },
+          {
+            name:'注册账户',
+            path:"/nav-admin/manage/user",
+            id:'2-2',
+          },
+          {
+            name:'用户组管理',
+            path:"/nav-admin/manage/role",
+            id:'2-3',
+          },
+        ]
+      },
+      {
+        name:'品牌化',
+        id:'3',
+        child:[
+          {
+            name:'登录框',
+            id:'3-1',
+          },
+          {
+            name:'消息设置',
+            id:'3-2',
+          },
+        ]
+      },
+      {
+        name:'字段管理',
+        id:'4',
+      },
+    ],
+    "省级教育行政部门":[
+      {
+        name:'省内合集',
+        id:'1',
+      },
+    ],
+    "流程管理员登录":[
+      {
+        name:'报送流程',
+        id:'1',
+      },
+      {
+        name:'用户管理',
+        id:'2',
+        child:[
+          {
+            name:'用户列表',
+            id:'2-1',
+          },
+          {
+            name:'用户组管理',
+            id:'2-2',
+          },
+          {
+            name:'邀请注册',
+            id:'2-3',
+          },
+        ]
+      }
+    ],
+    "省属高校联系人":[
+      {
+        name:'校内空间',
+        id:'1',
+      },
+      {
+        name:'用户管理',
+        id:'2',
+        child:[
+          {
+            name:'邀请注册',
+            id:'2-1',
+          },
+          {
+            name:'用户列表',
+            id:'2-2',
+          },
+        ]
+      },
+      {
+        name:'个人信息',
+        id:'3',
+      },
+    ],
+    "教材评审组成员":[
+      {
+        name:'报送流程',
+        id:'1',
+        path: '/nav-review/home/apply',
+      },
+      {
+        name:'个人信息',
+        id:'2',
+        path: '/nav-review/profile',
+      },
+    ],
+    "作者/教师/主编":[
+      {
+        name: '个人空间',
+        id: '1',
+        path: '/nav-author/manage/space',
+      },
+      {
+        name: '回收站',
+        id: '2',
+        path: '/nav-author/manage/recycle',
+        params: {
+          isDeleted: true,
+        },
+      },
+    ],
+  } 
+  active: string = localStorage.getItem('active') || '1';
+  isCollapsed:boolean = false;
+
+  constructor(
+    public router: Router,
+    public textbook:textbookServer,
+    iconRegistry: MatIconRegistry, 
+    sanitizer: DomSanitizer
+  ) {
+    iconRegistry.addSvgIconLiteral('menu', sanitizer.bypassSecurityTrustHtml(this.MENU_ICON));
+   }
+
+  ngOnInit() {
+  }
+  toggleCollapsed(): void {
+    this.isCollapsed = !this.isCollapsed;
+  }
+  toUrl(child: any) {
+    let cateid = child.id;
+    this.active = cateid;
+    localStorage.setItem('active', cateid);
+    console.log(child);
+    if (child.params) {
+      this.router.navigate([child.path, child?.params]);
+    } else {
+      this.router.navigate([child.path]);
+    }
+  }
+}

+ 35 - 6
projects/textbook/src/app/comp-nav/comp-nav.component.html

@@ -1,10 +1,39 @@
 <div class="bar">
-  <nz-avatar (click)="goUrl('/profile')" nzIcon="user" style="background-color:#87d068;"></nz-avatar>
-  <div class="title">{{tbookSer.profile?.name}}</div>
-  <div class="space"></div>
+  <nz-avatar
+    (click)="goUrl('/profile')"
+    nzIcon="user"
+    style="background-color: #87d068;cursor: pointer;"
+  ></nz-avatar>
+  @if(!viewCollapsed){
   <div class="user">
-    <button mat-icon-button (click)="authServr.logout()" aria-label="LogOut" style="margin-top: -10px;">
-      <mat-icon>logout</mat-icon>
+    <div class="name">{{ tbookSer.profile?.name || "未认证用户" }}</div>
+    <div class="email">{{ tbookSer.profile?.email || "test@edu.com" }}</div>
+  </div>
+  <div class="more">
+    <button
+      mat-icon-button
+      nzType="primary"
+      nz-popover
+      nzPopoverTitle="操作"
+      [(nzPopoverVisible)]="visible"
+      (nzPopoverVisibleChange)="change($event)"
+      nzPopoverTrigger="click"
+      [nzPopoverContent]="contentTemplate"
+    >
+      <mat-icon fontIcon="more"></mat-icon>
     </button>
+    <ng-template #contentTemplate>
+      <div style="display: flex; flex-direction: column">
+        <a
+          nz-button
+          nzType="link"
+          (click)="clickMe()"
+          style="margin-bottom: 6px;color:#3e49b3;"
+          >我的</a
+        >
+        <a nz-button nzType="link" style="color:#3e49b3" (click)="authServr.logout()">退出登录</a>
+      </div>
+    </ng-template>
   </div>
-</div>
+  }
+</div>

+ 29 - 13
projects/textbook/src/app/comp-nav/comp-nav.component.scss

@@ -1,18 +1,34 @@
-.bar{
-  width: 100%;
+.bar {
+  // width: 100%;
   padding: 10px;
-  border-bottom: 1px solid #d3d3d3;
+  // border-bottom: 1px solid #d3d3d3;
   display: flex;
-  div{
-    margin-top:5px;
+  align-items: center;
+  border-top:  1px solid #d3d3d3;
+  .user {
+    display: flex;
+    flex-direction: column;
+    margin: 0 10px;
+    flex: 1;
+    .name {
+      font-family: PingFang SC;
+      font-size: 14px;
+      font-weight: 400;
+      line-height: 20px;
+      text-align: left;
+    }
+    .email {
+      font-family: Helvetica;
+      font-size: 14px;
+      font-weight: 400;
+      line-height: 20px;
+      text-align: left;
+    }
   }
-  .title{
-    margin-left: 10px;
-  }
-  .space{
-    flex:1;
-  }
-  .user{
-    width:100px;
+  .more{
+    flex-shrink: 0;
   }
+}
+::ng-deep .ant-popover-title{
+  min-width: 100px;
 }

+ 11 - 3
projects/textbook/src/app/comp-nav/comp-nav.component.ts

@@ -1,22 +1,25 @@
-import { Component, OnInit } from '@angular/core';
+import { Component, OnInit, Input } from '@angular/core';
 import { NzAvatarModule } from 'ng-zorro-antd/avatar';
 import { textbookServer } from "../../services/textbook";
 import { MatButtonModule } from '@angular/material/button';
 import { MatIconModule } from '@angular/material/icon';
 import { RouterModule,Router } from '@angular/router';
 import { AuthServr } from '../../services/auth.service'
+import { NzPopoverModule } from 'ng-zorro-antd/popover';
 @Component({
   selector: 'app-comp-nav',
   standalone: true,
   imports: [
     RouterModule,
     NzAvatarModule,
-    MatButtonModule,MatIconModule
+    MatButtonModule,MatIconModule,NzPopoverModule
   ],
   templateUrl: './comp-nav.component.html',
   styleUrls: ['./comp-nav.component.scss'],
 })
 export class CompNavComponent implements OnInit {
+  visible: boolean = false;
+  @Input('viewCollapsed') viewCollapsed:boolean = false;
 
   constructor(
     public router: Router,
@@ -25,7 +28,12 @@ export class CompNavComponent implements OnInit {
   ) {}
 
   ngOnInit() {}
-    
+  change(value: boolean): void {
+    console.log(value);
+  }
+  clickMe(): void {
+    this.visible = false;
+  }
   goUrl(path: string) {
     this.router.navigate([
       path,

+ 63 - 8
projects/textbook/src/app/comp-table/comp-table-list/comp-table-list.component.html

@@ -1,5 +1,6 @@
-<div style="width:100%;display: flex;justify-content: end;">
 
+
+<div style="width:100%;display: flex;justify-content: end;">
   <div style="width:30%;display: flex;justify-content: end;align-items: flex-end;">
     <ng-container *ngFor="let button of schema?.buttons">
       <button *ngIf="button?.place=='top'&&button?.show({queryParams:queryParams})" mat-raised-button color="primary" (click)="batchHandle(button)" >{{button?.name }}</button>
@@ -7,12 +8,19 @@
   </div>
 </div>
 
-<nz-table #editRowTable nzBordered [nzData]="list" *ngIf="showMode=='list'"
-  [nzNoResult]="currentLang=='cn'?'暂无数据':'No Data'"
-  [nzLoading]="isLoading" nzFrontPagination="false"
->
+<!-- 数据表格:渲染当前页 -->
+<nz-table #editRowTable [nzData]="list" *ngIf="showMode=='list'&&list?.length"
+  [nzLoading]="isLoading" nzFrontPagination="false">
     <thead>
       <tr>
+        <!-- 全部选择 -->
+        <th
+            [nzChecked]="checked"
+            [nzIndeterminate]="indeterminate"
+            nzLabel="Select all"
+            (nzCheckedChange)="onAllChecked($event)"
+            (nzCurrentPageDataChange)="onCurrentPageDataChange($event)"
+          ></th>
         <ng-container *ngFor="let field of headerArray">
             <th >{{field?.name}}</th>
         </ng-container>
@@ -23,6 +31,13 @@
     <tbody>
       <ng-container *ngFor="let object of editRowTable.data">
         <tr class="editable-row" *ngIf="object?.get('isDeleted')!=true">
+          <!-- 单行选择 -->
+          <!-- [nzDisabled]="object.disabled" -->
+          <td
+          [nzChecked]="setOfCheckedId.has(object.id)"
+          [nzLabel]="object.className"
+          (nzCheckedChange)="onItemChecked(object.id, $event)"
+        ></td>
           <ng-container *ngFor="let field of headerArray">
             <!-- 单行数据每个字段渲染 -->
             <td > 
@@ -70,12 +85,52 @@
         <!-- <comp-monitor-card [monitor]="object"></comp-monitor-card> -->
       </div>
     </ng-container>
-    <nz-empty *ngIf="!list?.length" nzNotFoundImage="simple" [nzNotFoundContent]="currentLang=='cn'?'暂无数据':'No Data'"></nz-empty>
   </div>
 
-  <div style="width:100%;display: flex;justify-content: center;align-items: center;">
+  <!-- 暂无数据:提示模板 -->
+  <ng-template #noResultTpl>
+    <nz-result [nzIcon]="emptyImgTpl" [nzTitle]="schema?.title+'管理'" [nzSubTitle]="schema?.emptyDesc || '当前还没有'+schema?.title+'数据哦,请您点击创建。'">
+      <div nz-result-extra>
+        <button mat-raised-button color="secondary" (click)="createObject()">创建{{schema?.title}}</button>
+      </div>
+    </nz-result>
+  </ng-template>
+  <ng-template #emptyImgTpl>
+    <img style="width:50%;max-width:300px;" [src]="schema?.emptyImg || '/img/404-empty.svg' " alt="">
+  </ng-template>
+
+  <ng-container *ngIf="!list?.length">
+    <ng-container *ngTemplateOutlet="noResultTpl"></ng-container>
+  </ng-container>
+
+  <!-- 分页区域:分页组件 -->
+  <div style="width:100%;display: flex;justify-content: end;align-items: center;padding-right: 20px;margin-top:-20px;">
     <nz-pagination 
     [nzPageIndex]="pageIndex"
+    [nzSize]="'small'"
     [nzPageSize]="pageSize" [nzTotal]="pageTotal" (nzPageIndexChange)="onPageIndexChange($event)"
     ></nz-pagination>
-  </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)="deleteSelected()">
+            <span nz-icon nzType="delete"></span>
+            删除
+          </button>
+        </div>
+      </div>
+    </div>
+    <div class="styles_cancel__AARoT">
+      <button nz-button nzType="text">取消选中</button>
+    </div>
+  </div>
+</div>

+ 65 - 0
projects/textbook/src/app/comp-table/comp-table-list/comp-table-list.component.scss

@@ -2,4 +2,69 @@
 nz-table{
     width:100%;
     padding:20px;
+    th{
+        color:var(--color-text-desc);
+    }
+}
+
+
+// 选中,批量操作区域
+.batch-toolbar-modal{
+    position: absolute;
+    display: flex;
+    justify-content: center;
+    bottom: 80px;
+    left: calc(50% - 210px);
+    -webkit-transform: translate(0);
+    transform: translate(0);
+}
+.batch-toolbar {
+    display: flex;
+    align-items: center;
+    height: 56px;
+    // min-width: 600px;
+    background: #fff;
+    border: 1px solid #e5e6eb;
+    box-sizing: border-box;
+    box-shadow: 0 16px 32px -10px rgba(4, 24, 115, .1);
+    border-radius: 4px;
+    button{
+        color:#545968;
+    }
+}
+.batch-toolbar .styles_counter__18S08 {
+    color: #fff;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    height: 100%;
+    background: #215ae5;
+    width: 100px;
+    font-size: 12px;
+    border-top-left-radius: 4px;
+    border-bottom-left-radius: 4px;
+}
+.batch-toolbar .batch-toolbar-actions {
+    display: flex;
+    margin: auto;
+    padding: 0 20px;
+}
+.batch-toolbar .styles_cancel__AARoT {
+    font-size: 16px;
+    border-left: 1px solid #a9aeb8;
+    // padding-left: 20px;
+    display: flex;
+    justify-content: center;
+    width: 128px;
+}
+.batch-toolbar .styles_counter__18S08 .styles_num__178Wa {
+    font-size: 24px;
+    margin-left: 8px;
+}
+.ant-space-align-center {
+    align-items: center;
+}
+
+.ant-space {
+    display: inline-flex;
 }

+ 81 - 4
projects/textbook/src/app/comp-table/comp-table-list/comp-table-list.component.ts

@@ -8,12 +8,20 @@ import { CommonModule } from '@angular/common';
 
 import { NzPaginationModule } from 'ng-zorro-antd/pagination';
 import { NzEmptyModule } from 'ng-zorro-antd/empty';
+import { NzResultModule } from 'ng-zorro-antd/result';
 
 import { MatCheckboxModule } from '@angular/material/checkbox';
 import { MatButtonModule } from '@angular/material/button';
 import { MatSlideToggleModule } from '@angular/material/slide-toggle';
 import { UtilnowPipe } from '../../../pipes/utilnow.pipe';
 import { NzTableModule } from 'ng-zorro-antd/table';
+import { confirmDialog, openObjectEditDialog } from '../../../schemas/func-parse';
+import { MatIconModule } from '@angular/material/icon';
+import { NzIconModule } from 'ng-zorro-antd/icon';
+import { NzPageHeaderModule } from 'ng-zorro-antd/page-header';
+import { NzBreadCrumbModule } from 'ng-zorro-antd/breadcrumb';
+import { NzTagModule } from 'ng-zorro-antd/tag';
+import { Router } from '@angular/router';
 
 interface SchemaFiled{
   key:string,
@@ -30,8 +38,8 @@ interface SchemaFiled{
   imports:[CommonModule,
     UtilnowPipe,
     // TranslateModule,
-    NzPaginationModule,NzEmptyModule,NzTableModule,
-    MatButtonModule,MatCheckboxModule,MatSlideToggleModule,
+    NzPaginationModule,NzEmptyModule,NzTableModule,NzResultModule,NzIconModule,
+    MatButtonModule,MatCheckboxModule,MatSlideToggleModule,MatIconModule,
   ],
   providers:[]
 })
@@ -60,6 +68,7 @@ export class CompTableListComponent {
     private parseData:ParseDataService,
     // private clusterServ:ClusterService,
     private dialog:MatDialog,
+    private router:Router,
     // public translate:TranslateService
   ){
     this.currentLang = "cn"// this.translate.getDefaultLang();
@@ -69,6 +78,12 @@ export class CompTableListComponent {
     this.refresh();
   }
 
+  createObject(){
+    openObjectEditDialog(this.dialog,this.schema,undefined,()=>{
+      this.refresh();
+    })
+  }
+
   batchHandle(button:any){
     // console.log(this.currentLang,'888888888888888888')
     button?.handle({
@@ -84,7 +99,7 @@ export class CompTableListComponent {
   buttonHandle(button:any,object:any){
     let that = this
     if(button?.handle){
-      button?.handle({object:object,dialog:this.dialog,callback:this.onButtonHandleCallBack},that.currentLang)
+      button?.handle({object:object,dialog:this.dialog,router:this.router,callback:this.onButtonHandleCallBack},that.currentLang)
     }
   }
   refresh(page?:number){
@@ -140,7 +155,7 @@ export class CompTableListComponent {
     await this.parseData.cachePointerList(Object.values(this.pointerMap))
     Object.keys(this.pointerMap).forEach(async id=>{
       let obj = this.parseData.ParseObjectCacheMap[id]
-      let field = this.fieldsArray?.find(item=>item?.className==obj?.className)
+      let field = this.fieldsArray?.find(item=>item?.targetClass==obj?.className)
       this.pointerShowMap[id] = await this.parseData.showNameByObj(obj,field?.showName)
     })
   }
@@ -154,4 +169,66 @@ export class CompTableListComponent {
     object.set(key,!object.get(key))
     object.save();
    }
+
+
+  /**
+   * 行选择处理逻辑
+   */
+  checked = false;
+  indeterminate = false;
+  setOfCheckedId = new Set<string>();
+
+  updateCheckedSet(id: string, checked: boolean): void {
+    if (checked) {
+      this.setOfCheckedId.add(id);
+    } else {
+      this.setOfCheckedId.delete(id);
+    }
+  }
+
+  onCurrentPageDataChange(event:any): void {
+    this.refreshCheckedStatus();
+  }
+
+  refreshCheckedStatus(): void {
+    const listOfEnabledData = this.list // .filter(({ disabled }) => !disabled);
+    this.checked = listOfEnabledData.every(({ id }) => this.setOfCheckedId.has(id));
+    this.indeterminate = listOfEnabledData.some(({ id }) => this.setOfCheckedId.has(id)) && !this.checked;
+  }
+
+  onItemChecked(id: string, checked: boolean): void {
+    this.updateCheckedSet(id, checked);
+    this.refreshCheckedStatus();
+  }
+
+  onAllChecked(checked: boolean): void {
+    this.list
+      // .filter(({ disabled }) => !disabled)
+      .forEach(({ id }) => this.updateCheckedSet(id, checked));
+    this.refreshCheckedStatus();
+  }
+  /**
+   * 选择快捷功能:批量处理
+   */
+  // 批量删除
+   deleteSelected(){
+    confirmDialog(this.dialog,{
+      title:"批量删除",
+      message:"删除后数据不可恢复,请谨慎操作",
+      danger:true,
+      handleOK:async ()=>{
+        let selectedList = this.list.filter(item=>this.setOfCheckedId.has(item?.id))
+        let deletePromiseList = selectedList.map(item=>{
+          return new Promise((resolve=>{
+            item.set("isDeleted",true);
+            item.save();
+          }))
+        })
+        try{
+          await Promise.all(deletePromiseList)
+        }catch(err){}
+        this.refresh();
+      }
+    })
+   }
 }

+ 2 - 2
projects/textbook/src/app/comp-table/parse-data.service.ts

@@ -40,11 +40,11 @@ export class ParseDataService {
     }
 
     // 获取模板标记数组
-    console.log(matches);
+    // console.log(matches);
     matches.forEach(keyword=>{
       text = text.replaceAll("${"+keyword+"}",obj?.get(keyword)||"")
     })
-    console.log(text)
+    // console.log(text)
 
     // 特殊数据名称设定
     // if(obj.className=="MinerCluster"){

+ 0 - 3
projects/textbook/src/app/comp-user/comp-user.component.html

@@ -1,8 +1,5 @@
 <div class="page">
   <div class="login-content">
-    <div class="title">本科国家级规划教材遴选报送系统</div>
     <router-outlet></router-outlet>
   </div>
 </div>
-
-

+ 7 - 3
projects/textbook/src/app/comp-user/comp-user.component.scss

@@ -12,15 +12,19 @@
 }
 .title{
   font-size: 1.5rem !important;
+  text-align: left;
 }
 .login-content{
   position: absolute;
   transform:translateY(-50%);
   top: 50%;
   right: 100px;
-  padding: 10px;
+  padding:10px 50px;
   text-align: center;
-  max-width: 500px;
+  width:448px;
+  min-height: 536px;
   margin: 0 auto;
-  background: #f5f5f5;
+  background: #fff;
+  border-radius: 8px;
+  overflow: hidden;
 }

+ 8 - 0
projects/textbook/src/index.html

@@ -8,7 +8,15 @@
   <link rel="icon" type="image/x-icon" href="favicon.ico">
   <link href="https://fonts.loli.net/css2?family=Roboto:wght@300;400;500&display=swap" rel="stylesheet">
   <link href="https://fonts.loli.net/icon?family=Material+Icons" rel="stylesheet">
+  <!-- Authing -->
+  <script type="text/javascript" src="https://cdn.authing.co/packages/guard/latest/guard.min.js"></script>
+  <link rel="stylesheet" href="https://cdn.authing.co/packages/guard/latest/guard.min.css" />
 </head>
+<style>
+  *{
+    font-family: PingFang SC;
+  }
+</style>
 <body class="mat-typography">
   <app-root></app-root>
 </body>

+ 277 - 0
projects/textbook/src/modules/login/account-info/account-info.component.html

@@ -0,0 +1,277 @@
+<div class="region">
+  <div class="nav">
+    <div>
+      <svg
+        width="24"
+        height="27"
+        viewBox="0 0 18 20"
+        fill="none"
+        xmlns="http://www.w3.org/2000/svg"
+      >
+        <path
+          d="M18 2H4C3.46957 2 2.96086 2.21071 2.58579 2.58579C2.21071 2.96086 2 3.46957 2 4C2 4.53043 2.21071 5.03914 2.58579 5.41421C2.96086 5.78929 3.46957 6 4 6H18V19C18 19.2652 17.8946 19.5196 17.7071 19.7071C17.5196 19.8946 17.2652 20 17 20H4C2.93913 20 1.92172 19.5786 1.17157 18.8284C0.421427 18.0783 0 17.0609 0 16V4C0 2.93913 0.421427 1.92172 1.17157 1.17157C1.92172 0.421427 2.93913 0 4 0H17C17.2652 0 17.5196 0.105357 17.7071 0.292893C17.8946 0.48043 18 0.734783 18 1V2Z"
+          fill="url(#paint0_linear_5_11023)"
+        />
+        <defs>
+          <linearGradient
+            id="paint0_linear_5_11023"
+            x1="9"
+            y1="-2.21282e-07"
+            x2="25.5"
+            y2="40"
+            gradientUnits="userSpaceOnUse"
+          >
+            <stop stop-color="#E04860" />
+            <stop offset="1" stop-color="#E99306" />
+          </linearGradient>
+        </defs>
+      </svg>
+    </div>
+    完善账号信息
+    <div class="tips">
+      欢迎使用教材遴选系统 ,为了激活账号使用权限,请先完善您的资料信息。
+    </div>
+  </div>
+  <div class="form">
+    <form
+      nz-form
+      [formGroup]="validateForm"
+      class="account-form"
+      (ngSubmit)="submitForm()"
+    >
+      <nz-form-item>
+        <nz-form-label class="label" [nzNoColon]="true" nzRequired
+          >姓名</nz-form-label
+        >
+        <nz-input-group>
+          <input
+            nz-input
+            type="text"
+            formControlName="name"
+            placeholder="请填写姓名"
+          />
+        </nz-input-group>
+      </nz-form-item>
+      <nz-form-item>
+        <nz-form-label class="label" [nzNoColon]="true" nzRequired
+          >手机号</nz-form-label
+        >
+        <nz-input-group>
+          <input
+            nz-input
+            type="text"
+            [disabled]="true"
+            [ngModel]="mobile"
+            [ngModelOptions]="{standalone: true}"
+            placeholder="请填写手机号"
+          />
+        </nz-input-group> </nz-form-item
+      ><nz-form-item>
+        <nz-form-label class="label" [nzNoColon]="true" nzRequired
+          >电子邮箱</nz-form-label
+        >
+        <nz-input-group>
+          <input
+            nz-input
+            type="email"
+            formControlName="email"
+            placeholder="请填写电子邮箱"
+          />
+        </nz-input-group> </nz-form-item
+      ><nz-form-item>
+        <nz-form-label class="label" [nzNoColon]="true">办公电话</nz-form-label>
+        <nz-input-group>
+          <input
+            nz-input
+            type="text"
+            [(ngModel)]="nonRequired.workPhone"
+            [ngModelOptions]="{standalone: true}"
+            placeholder="请填写办公电话"
+          />
+        </nz-input-group>
+      </nz-form-item>
+      <nz-form-item>
+        <nz-form-label class="label" [nzNoColon]="true" nzRequired
+          >省份</nz-form-label
+        >
+        <nz-input-group>
+          <!-- <input
+            nz-input
+            type="text"
+            formControlName="province"
+            placeholder="请填写用户名"
+          /> -->
+          <nz-select
+            style="width: 100%"
+            nzShowSearch
+            nzAllowClear
+            nzPlaceHolder="请选择省份"
+            formControlName="province"
+          >
+            @for(item of provinces; track item;let index = $index){
+            <nz-option nzCustomContent [nzValue]="item" [nzLabel]="item">{{
+              item
+            }}</nz-option>
+            }
+          </nz-select>
+        </nz-input-group>
+      </nz-form-item>
+      <nz-form-item>
+        <nz-form-label class="label" [nzNoColon]="true" nzRequired
+          >单位类型</nz-form-label
+        >
+        <nz-input-group>
+          <!-- <input
+            nz-input
+            type="text"
+            formControlName="unitType"
+            placeholder="请填写用户名"
+          /> -->
+          <nz-select
+            style="width: 100%"
+            nzShowSearch
+            nzAllowClear
+            nzPlaceHolder="请选择单位类型"
+            formControlName="unitType"
+          >
+            @for(item of unitTypes; track item;let index = $index){
+            <nz-option nzCustomContent [nzValue]="item" [nzLabel]="item">{{
+              item
+            }}</nz-option>
+            }
+          </nz-select>
+        </nz-input-group>
+      </nz-form-item>
+      <nz-form-item>
+        <nz-form-label class="label" [nzNoColon]="true" nzRequired
+          >单位名称</nz-form-label
+        >
+        <nz-input-group>
+          <input
+            nz-input
+            type="text"
+            formControlName="unit"
+            placeholder="请填写单位名称"
+          />
+        </nz-input-group>
+      </nz-form-item>
+      <nz-form-item>
+        <nz-form-label class="label" [nzNoColon]="true">所在部门</nz-form-label>
+        <nz-input-group>
+          <input
+            nz-input
+            type="text"
+            [(ngModel)]="nonRequired.branch"
+            [ngModelOptions]="{standalone: true}"
+            placeholder="请填写所在部门"
+          />
+        </nz-input-group>
+      </nz-form-item>
+      <nz-form-item>
+        <nz-form-label class="label" [nzNoColon]="true">职务</nz-form-label>
+        <nz-input-group>
+          <input
+            nz-input
+            type="text"
+            [(ngModel)]="nonRequired.job"
+            [ngModelOptions]="{standalone: true}"
+            placeholder="请填写职务"
+          />
+        </nz-input-group>
+      </nz-form-item>
+      <nz-form-item>
+        <nz-form-label class="label" [nzNoColon]="true" nzRequired
+          >身份证号</nz-form-label
+        >
+        <nz-input-group>
+          <input
+            nz-input
+            type="text"
+            formControlName="idcard"
+            placeholder="请填写身份证号"
+          />
+        </nz-input-group>
+      </nz-form-item>
+      <nz-form-item>
+        <nz-form-label class="label" [nzNoColon]="true" nzRequired
+          >用户类型</nz-form-label
+        >
+        <nz-input-group>
+          <!-- <input
+            nz-input
+            type="text"
+            formControlName="identity"
+            placeholder="请选择用户类型"
+          /> -->
+          <nz-select
+            style="width: 100%"
+            nzShowSearch
+            nzAllowClear
+            nzPlaceHolder="请选择单位类型"
+            formControlName="identity"
+          >
+            @for(item of identitys; track item;let index = $index){
+            <nz-option nzCustomContent [nzValue]="item" [nzLabel]="item">{{
+              item
+            }}</nz-option>
+            }
+          </nz-select>
+        </nz-input-group>
+      </nz-form-item>
+      <nz-form-item>
+        <nz-form-label class="label" [nzNoColon]="true" nzRequired
+          >单位联系人认证文件</nz-form-label
+        >
+        <nz-input-group>
+          <!-- <input
+            nz-input
+            type="text"
+            formControlName="file"
+            placeholder="请填写用户名"
+          /> -->
+          <nz-upload
+            formControlName="file"
+            nzAction="https://www.mocky.io/v2/5cc8019d300000980a055e76"
+            [nzHeaders]="{ authorization: 'authorization-text' }"
+            (nzChange)="handleChange($event)"
+          >
+            <div style="color: #3e49b3">
+              <span nz-icon nzType="upload"></span>上传认证文件
+            </div>
+          </nz-upload>
+          <div class="text" style="margin: 10px 0; color: #231c1f99">
+            请下载单位联系人认证<a href="">文件模板</a
+            >,填写盖章后上传。支持上传 PDF、JPG、JPEG、PNG
+            格式,单个文件大小不超过 2M
+          </div>
+        </nz-input-group>
+      </nz-form-item>
+    </form>
+
+    <button
+      id="basic"
+      class="form-button"
+      type="button"
+      mat-button
+      (click)="submitForm()"
+    >
+      保存
+    </button>
+    <div class="menu">
+      <a nz-dropdown [nzDropdownMenu]="menu">
+        <span style="color: #231c1f99">English</span>
+        <span
+          nz-icon
+          nzType="down"
+          style="color: #756b6d; margin-left: 4px"
+        ></span>
+      </a>
+      <nz-dropdown-menu #menu="nzDropdownMenu">
+        <ul nz-menu nzSelectable>
+          <li nz-menu-item>English</li>
+          <li nz-menu-item>中文简体</li>
+        </ul>
+      </nz-dropdown-menu>
+    </div>
+  </div>
+</div>

+ 88 - 0
projects/textbook/src/modules/login/account-info/account-info.component.scss

@@ -0,0 +1,88 @@
+.region {
+  width: 348px;
+  margin: 20px auto 10px;
+  .nav {
+    text-align: left;
+    margin: 10px 0 20px;
+    font-family: PingFang SC;
+    font-size: 24px;
+    font-weight: 600;
+    line-height: 33.6px;
+    .tips {
+      font-family: PingFang SC;
+      font-size: 14px;
+      font-weight: 400;
+      line-height: 19.6px;
+      text-align: left;
+      color: #545968;
+    }
+  }
+  .account-form {
+    height: 300px;
+    overflow-y: scroll;
+    scrollbar-width: none; /* firefox */
+    -ms-overflow-style: none; /* IE 10+ */
+    overflow-x: hidden;
+    overflow-y: auto;
+  }
+  .account-form::-webkit-scrollbar {
+    display: none; /* Chrome Safari */
+  }
+
+  nz-form-item {
+    display: flex;
+    flex-direction: column;
+    justify-content: start;
+    align-items: self-start;
+    margin-bottom: 10px;
+  }
+}
+.ant-input-group{
+  text-align: left;
+
+}
+// input {
+//   text-align: left;
+//   border: none;
+//   width: 100%;
+//   padding: 4px 6px;
+//   background: #f9f9f9;
+//   border-radius: 4px;
+//   font-family: PingFang SC;
+//   font-size: 14px;
+//   font-weight: 400;
+//   line-height: 22px;
+// }
+// input {
+//   outline: none;
+// }
+.form-button {
+  width: 100%;
+  height: 46px;
+  margin: 10px 0;
+  background-color: #c6233f;
+  color: white !important;
+  border-radius: 4px;
+}
+::ng-deep .ant-tabs-tab.ant-tabs-tab-active .ant-tabs-tab-btn {
+  color: #c6233f;
+}
+::ng-deep .ant-tabs-ink-bar {
+  background: #c6233f;
+}
+::ng-deep .ant-tabs-tab:hover {
+  color: #e97488;
+}
+::ng-deep .ant-tabs-tab-btn:active {
+  color: #e97488;
+}
+// ::ng-deep .ant-input-affix-wrapper:not(.ant-input-affix-wrapper-disabled):hover{
+//   border-color: #c6233f;
+// }
+::ng-deep .ant-checkbox-checked .ant-checkbox-inner {
+  background-color: #c6233f;
+  border-color: #c6233f;
+}
+::ng-deep .ant-checkbox-wrapper:hover .ant-checkbox-inner {
+  border-color: #c6233f;
+}

+ 6 - 6
projects/textbook/src/modules/nav-province-school-contact/page-home/page-home.component.spec.ts → projects/textbook/src/modules/login/account-info/account-info.component.spec.ts

@@ -1,19 +1,19 @@
 import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
 import { IonicModule } from '@ionic/angular';
 
-import { PageHomeComponent } from './page-home.component';
+import { AccountInfoComponent } from './account-info.component';
 
-describe('PageHomeComponent', () => {
-  let component: PageHomeComponent;
-  let fixture: ComponentFixture<PageHomeComponent>;
+describe('AccountInfoComponent', () => {
+  let component: AccountInfoComponent;
+  let fixture: ComponentFixture<AccountInfoComponent>;
 
   beforeEach(waitForAsync(() => {
     TestBed.configureTestingModule({
-      declarations: [ PageHomeComponent ],
+      declarations: [ AccountInfoComponent ],
       imports: [IonicModule.forRoot()]
     }).compileComponents();
 
-    fixture = TestBed.createComponent(PageHomeComponent);
+    fixture = TestBed.createComponent(AccountInfoComponent);
     component = fixture.componentInstance;
     fixture.detectChanges();
   }));

+ 251 - 0
projects/textbook/src/modules/login/account-info/account-info.component.ts

@@ -0,0 +1,251 @@
+import { Component, OnInit, ViewChild } from '@angular/core';
+import { ReactiveFormsModule } from '@angular/forms';
+import { HttpClient } from '@angular/common/http';
+import { Router } from '@angular/router';
+import { catchError } from 'rxjs/operators';
+import { NzUploadChangeParam } from 'ng-zorro-antd/upload';
+import { NzUploadModule } from 'ng-zorro-antd/upload';
+import {
+  FormControl,
+  FormGroup,
+  NonNullableFormBuilder,
+  Validators,
+} from '@angular/forms';
+import { CommonCompModule } from '../common.modules';
+import { textbookServer } from '../../../services/textbook';
+import { AuthServr } from '../../../services/auth.service';
+import { CaptchaComponent } from '../../../app/captcha/captcha.component';
+import { NzMessageService } from 'ng-zorro-antd/message';
+import Parse from 'parse';
+@Component({
+  selector: 'app-account-info',
+  standalone: true,
+  imports: [
+    ReactiveFormsModule,
+    CommonCompModule,
+    CaptchaComponent,
+    NzUploadModule,
+  ],
+  templateUrl: './account-info.component.html',
+  styleUrls: ['./account-info.component.scss'],
+})
+export class AccountInfoComponent implements OnInit {
+  user: Parse.Object = Parse.User.current()!;
+  validateForm: FormGroup<{
+    name: FormControl<string>; //姓名
+    // mobile: FormControl<string>; //手机号
+    email: FormControl<string>; //电子邮箱
+    province: FormControl<string>; //省份
+    unitType: FormControl<string>; //单位类型
+    unit: FormControl<string>; //单位名称
+    idcard: FormControl<string>; //身份证号
+    identity: FormControl<string>; //用户类型
+    file: FormControl<string>; //单位联系人认证文件
+  }> = this.fb.group({
+    name: ['', [Validators.required]],
+    // mobile: ['', [Validators.required]],
+    email: ['', [Validators.required]],
+    province: ['', [Validators.required]],
+    unitType: ['', [Validators.required]],
+    unit: ['', [Validators.required]],
+    idcard: ['', [Validators.required]],
+    identity: ['', [Validators.required]],
+    file: ['暂无', [Validators.required]],
+  });
+  nonRequired: any = {
+    workPhone: '',
+    branch: '',
+    job: '',
+  };
+  mobile: string = '';
+
+  //省份
+  provinces: Array<string> = [
+    '北京市',
+    '天津市',
+    '河北省',
+    '山西省',
+    '内蒙古自治区',
+    '辽宁省',
+    '吉林省',
+    '黑龙江省',
+    '上海市',
+    '江苏省',
+    '浙江省',
+    '安徽省',
+    '福建省',
+    '江西省',
+    '山东省',
+    '河南省',
+    '湖北省',
+    '湖南省',
+    '广东省',
+    '广西壮族自治区',
+    '海南省',
+    '重庆市',
+    '四川省',
+    '贵州省',
+    '云南省',
+    '西藏自治区',
+    '陕西省',
+    '甘肃省',
+    '青海省',
+    '宁夏回族自治区',
+    '新疆维吾尔自治区',
+    '台湾省',
+    '香港特别行政区',
+    '澳门特别行政区',
+  ];
+  unitTypes: Array<string> = [
+    '个体工商户',
+    '企业公司',
+    '国有机构或事业单位',
+    '非营利组织或公益机构',
+    '教育机构',
+    '自由职业者或个人',
+    '其他特定单位类型',
+  ];
+  identitys: Array<string> = [
+    '国家级管理员',
+    '省级教育行政部门',
+    '合集管理员',
+    '省属高校联系人',
+    '教材评审组成员',
+    '作者/教师/主编',
+  ];
+  constructor(
+    public tbookSer: textbookServer,
+    private fb: NonNullableFormBuilder,
+    public router: Router,
+    private authServr: AuthServr,
+    private message: NzMessageService,
+    private http: HttpClient
+  ) {}
+
+  ngOnInit() {
+    if (Parse.User.current()?.id) {
+      // this.validateForm.value.mobile = Parse.User.current()?.get('mobile');
+      this.mobile = this.user.get('mobile');
+      this.authProfile();
+    } else {
+      this.router.navigate(['user/login']);
+    }
+  }
+  async authProfile() {
+    let query = new Parse.Query('Profile');
+    query.equalTo('user', Parse.User.current()?.id);
+    query.notEqualTo('isDeleted', true);
+    let r = await query.first();
+    if (r?.id) {
+      if (!r.get('verify')) {
+        this.message.info('您已完成身份认证,即将跳转到管理后台');
+        return;
+      }
+      this.validateForm = this.fb.group({
+        name: [r.get('name'), [Validators.required]],
+        // mobile: [Parse.User.current()?.get('mobile') || r.get('mobile'), [Validators.required]],
+        email: [r.get('email'), [Validators.required]],
+        province: [r.get('province'), [Validators.required]],
+        unitType: [r.get('unitType'), [Validators.required]],
+        unit: [r.get('unit'), [Validators.required]],
+        idcard: [r.get('idcard'), [Validators.required]],
+        identity: [r.get('identity'), [Validators.required]],
+        file: [r.get('file'), [Validators.required]],
+      });
+      this.nonRequired = {
+        workPhone: r.get('workPhone'),
+        branch: r.get('branch'),
+        job: r.get('job'),
+      };
+    }
+  }
+  submitForm(): void {
+    console.log(this.validateForm.value);
+    if (this.validateForm.valid) {
+      let {
+        name,
+        // mobile,
+        email,
+        province,
+        unitType,
+        unit,
+        idcard,
+        identity,
+        file,
+      } = this.validateForm.value;
+  
+      let a =
+        /^\d{6}((((((19|20)\d{2})(0[13-9]|1[012])(0[1-9]|[12]\d|30))|(((19|20)\d{2})(0[13578]|1[02])31)|((19|20)\d{2})02(0[1-9]|1\d|2[0-8])|((((19|20)([13579][26]|[2468][048]|0[48]))|(2000))0229))\d{3})|((((\d{2})(0[13-9]|1[012])(0[1-9]|[12]\d|30))|((\d{2})(0[13578]|1[02])31)|((\d{2})02(0[1-9]|1\d|2[0-8]))|(([13579][26]|[2468][048]|0[048])0229))\d{2}))(\d|X|x)$/;
+      if (!String(idcard).match(a)) {
+        this.message.error('身份证格式错误');
+        return;
+      }
+      let params = {
+        name,
+        mobile: this.mobile,
+        email,
+        province,
+        unitType,
+        unit,
+        idcard,
+        identity,
+        file,
+        workPhone: this.nonRequired.workPhone,
+        branch: this.nonRequired.branch,
+        job: this.nonRequired.job,
+      };
+      this.profileSave(params);
+    } else {
+      this.message.warning('请填写完整的信息');
+      Object.values(this.validateForm.controls).forEach((control) => {
+        if (control.invalid) {
+          control.markAsDirty();
+          control.updateValueAndValidity({ onlySelf: true });
+        }
+      });
+    }
+  }
+
+  async profileSave(params: any) {
+    console.log(params);
+    let query = new Parse.Query('Profile');
+    query.equalTo('user', Parse.User.current()?.id);
+    query.notEqualTo('isDeleted', true);
+    let profile = await query.first();
+    if (!profile?.id) {
+      let obj = Parse.Object.extend('Profile');
+      profile = new obj();
+    }
+    profile?.set('user', Parse.User.current()?.toPointer());
+    profile?.set('company', {
+      __type: 'Pointer',
+      className: 'Company',
+      objectId: this.tbookSer.company,
+    });
+    profile?.set('name', params.name);
+    profile?.set('email', params.email);
+    profile?.set('mobile', params.email);
+    profile?.set('province', params.province);
+    profile?.set('unitType', params.unitType);
+    profile?.set('unit', params.unit);
+    profile?.set('idcard', params.idcard);
+    profile?.set('identity', params.identity);
+    profile?.set('file', params.file);
+    profile?.set('workPhone', params.workPhone);
+    profile?.set('branch', params.branch);
+    profile?.set('job', params.job);
+    profile?.set('verify', true);
+    let res = await profile?.save();
+    this.authServr.profileVerify()
+  }
+  handleChange(info: NzUploadChangeParam): void {
+    if (info.file.status !== 'uploading') {
+      console.log(info.file, info.fileList);
+    }
+    if (info.file.status === 'done') {
+      this.message.success(`${info.file.name} file uploaded successfully`);
+    } else if (info.file.status === 'error') {
+      this.message.error(`${info.file.name} file upload failed.`);
+    }
+  }
+}

+ 11 - 3
projects/textbook/src/modules/login/common.modules.ts

@@ -2,21 +2,29 @@ import { NgModule } from '@angular/core';
 import { FormsModule } from '@angular/forms';
 import { NzFormModule } from 'ng-zorro-antd/form';
 import { NzIconModule } from 'ng-zorro-antd/icon';
-import { NzButtonModule } from 'ng-zorro-antd/button';
+// import { NzButtonModule } from 'ng-zorro-antd/button';
 import { NzModalModule } from 'ng-zorro-antd/modal';
 import { NzTabsModule } from 'ng-zorro-antd/tabs';
 import { NzInputModule } from 'ng-zorro-antd/input';
 import { NzSelectModule } from 'ng-zorro-antd/select';
+import { NzCheckboxModule } from 'ng-zorro-antd/checkbox';
+import { NzDropDownModule } from 'ng-zorro-antd/dropdown';
+import {MatButtonModule} from '@angular/material/button';
+import { NzMessageModule } from 'ng-zorro-antd/message';
 @NgModule({
   exports: [
     FormsModule,
     NzFormModule,
     NzIconModule,
-    NzButtonModule,
+    // NzButtonModule,
     NzModalModule,
     NzTabsModule,
     NzInputModule,
-    NzSelectModule
+    NzSelectModule,
+    NzCheckboxModule,
+    NzDropDownModule,
+    MatButtonModule,
+    NzMessageModule
   ]
 })
 export class CommonCompModule { }

+ 40 - 72
projects/textbook/src/modules/login/login/login.component.html

@@ -1,78 +1,46 @@
 <div class="region">
-  <div class="selector">
-    @for (item of selector; track $index) {
-    <div
-      class="option"
-      [class.last]="$index == selector.length - 1"
-      [class.active]="item.type == currentProfile.type"
-      (click)="onChange(item)"
-    >
-      {{ item.name }}
+  <div class="nav">
+    <div>
+      <svg
+        width="24"
+        height="27"
+        viewBox="0 0 18 20"
+        fill="none"
+        xmlns="http://www.w3.org/2000/svg"
+      >
+        <path
+          d="M18 2H4C3.46957 2 2.96086 2.21071 2.58579 2.58579C2.21071 2.96086 2 3.46957 2 4C2 4.53043 2.21071 5.03914 2.58579 5.41421C2.96086 5.78929 3.46957 6 4 6H18V19C18 19.2652 17.8946 19.5196 17.7071 19.7071C17.5196 19.8946 17.2652 20 17 20H4C2.93913 20 1.92172 19.5786 1.17157 18.8284C0.421427 18.0783 0 17.0609 0 16V4C0 2.93913 0.421427 1.92172 1.17157 1.17157C1.92172 0.421427 2.93913 0 4 0H17C17.2652 0 17.5196 0.105357 17.7071 0.292893C17.8946 0.48043 18 0.734783 18 1V2Z"
+          fill="url(#paint0_linear_5_11023)"
+        />
+        <defs>
+          <linearGradient
+            id="paint0_linear_5_11023"
+            x1="9"
+            y1="-2.21282e-07"
+            x2="25.5"
+            y2="40"
+            gradientUnits="userSpaceOnUse"
+          >
+            <stop stop-color="#E04860" />
+            <stop offset="1" stop-color="#E99306" />
+          </linearGradient>
+        </defs>
+      </svg>
     </div>
-    }
+    登录教材遴选管理系统
   </div>
   <div class="form">
-    <div class="title">{{ currentProfile.name }}</div>
-    <form
-      nz-form
-      [formGroup]="validateForm"
-      class="login-form"
-      (ngSubmit)="submitForm()"
-    >
-      <nz-form-item style="margin-bottom: 16px;">
-        <nz-form-label [nzSm]="6" [nzXs]="24" nzRequired nzFor="user">用户名</nz-form-label>
-        <nz-form-control>
-          <nz-input-group>
-            <input
-              type="text"
-              nz-input
-              formControlName="userName"
-              placeholder="请输入用户名"
-            />
-          </nz-input-group>
-        </nz-form-control>
-      </nz-form-item>
-      <nz-form-item style="margin-bottom: 16px;">
-        <nz-form-label [nzSm]="6" [nzXs]="24" nzRequired nzFor="password">密码</nz-form-label>
-        <nz-form-control>
-          <nz-input-group>
-            <input
-              type="password"
-              nz-input
-              formControlName="password"
-              placeholder="请输入密码"
-            />
-          </nz-input-group>
-        </nz-form-control>
-      </nz-form-item>
-      <nz-form-item style="margin-bottom: 16px;">
-        <nz-form-label [nzSm]="6" [nzXs]="24" nzRequired nzFor="code">验证码</nz-form-label>
-        <nz-form-control>
-          <nz-input-group>
-            <input
-              type="text"
-              nz-input
-              formControlName="code"
-              placeholder="请输入验证码"
-            />
-          </nz-input-group>
-        </nz-form-control>
-      </nz-form-item>
-      <div nz-row class="login-form-margin">
-        <div nz-col [nzSpan]="12">
-          <a class="login-form-left" (click)="goUrl('/user/register')">立即注册</a>
-        </div>
-        <div nz-col [nzSpan]="12">
-          <a class="login-form-forgot" (click)="goUrl('/user/reset_password')">忘记密码</a>
-        </div>
-      </div>
-      <button
-        nz-button
-        class="login-form-button"
-        [nzType]="'primary'"
-      >
-        登录
-      </button>
-    </form>
+    <nz-tabset [nzSelectedIndex]="active" (nzSelectChange)="onChange($event)">
+      <nz-tab nzTitle="密码登录">
+        <form
+          nz-form
+          [formGroup]="validateForm"
+          class="login-form"
+          (ngSubmit)="submitForm('account')"
+        >
+          <div id="authing-guard-container"></div>
+        </form>
+      </nz-tab>
+    </nz-tabset>
   </div>
 </div>

+ 84 - 30
projects/textbook/src/modules/login/login/login.component.scss

@@ -1,52 +1,106 @@
 .region {
-  width: 450px;
-  margin: 20px auto 50px;
-  display: flex;
-  justify-content: center;
-  background-color: white;
-  .selector {
-    font-size: 14px;
-    width: 150px;
-    display: flex;
-    flex-direction: column;
-    .option {
-      padding:16px 10px;
-      border-bottom: 1px solid #d9d9d9;
-      text-align: left;
-    }
-    .active {
-      background-color: #215ae5;
-      color: white;
-    }
-    .last{
-      border-bottom: none;
-    }
+  width: 348px;
+  margin: 20px auto 10px;
+  .nav {
+    text-align: left;
+    margin: 10px 0 20px;
+    font-family: PingFang SC;
+    font-size: 24px;
+    font-weight: 600;
+    line-height: 33.6px;
   }
   .form {
-    width: 300px;
-    padding: 10px;
-    box-shadow: rgba(100, 100, 111, 0.2) 0px 7px 29px 0px;
-    .title{
+    width: 100%;
+    // padding: 10px;
+    // box-shadow: rgba(100, 100, 111, 0.2) 0px 7px 29px 0px;
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    .title {
       text-align: left;
       margin-bottom: 6px;
       font-size: 14px;
       font-weight: 600;
     }
     .login-form {
-      max-width: 300px;
+      max-width: 100%;
+      nz-form-item {
+        margin-bottom: 16px;
+      }
     }
-    .login-form-left{
+    .login-form-left {
       float: left;
     }
     .login-form-forgot {
       float: right;
     }
-    .login-form-margin{
+    .login-form-margin {
       margin-bottom: 8px;
       margin-top: 80px;
     }
     .login-form-button {
-      width: 90%;
+      width: 100%;
+      height: 46px;
+      margin: 10px 0;
+      background-color: #c6233f;
+      color: white;
+      border-radius: 4px;
+    }
+    .ipt {
+      padding: 8px;
+    }
+    .vrifly-btn {
+      height: 48px;
+      color: white;
+      border-radius: 4px;
+      margin-left: 10px;
+    }
+    .row-code {
+      width: 100%;
+      display: flex;
+      align-items: center;
+    }
+    .checked {
+      font-size: 14px;
+      display: flex;
+      align-items: center;
+      a {
+        color: #c6233f;
+      }
+    }
+    .menu {
+      width: 100%;
+      margin: 18px 0 0;
     }
   }
 }
+input:-webkit-autofill,
+input:-webkit-autofill:hover,
+input:-webkit-autofill:focus,
+input:-webkit-autofill:active {
+  -webkit-transition-delay: 99999s;
+  -webkit-transition: color 99999s ease-out, background-color 99999s ease-out;
+}
+
+::ng-deep .ant-tabs-tab.ant-tabs-tab-active .ant-tabs-tab-btn {
+  color: #c6233f;
+}
+::ng-deep .ant-tabs-ink-bar {
+  background: #c6233f;
+}
+::ng-deep .ant-tabs-tab:hover {
+  color: #e97488;
+}
+::ng-deep .ant-tabs-tab-btn:active {
+  color: #e97488;
+}
+// ::ng-deep .ant-input-affix-wrapper:not(.ant-input-affix-wrapper-disabled):hover{
+//   border-color: #c6233f;
+// }
+::ng-deep .ant-checkbox-checked .ant-checkbox-inner {
+  background-color: #c6233f;
+  border-color: #c6233f;
+}
+::ng-deep .ant-checkbox-wrapper:hover .ant-checkbox-inner {
+  border-color: #c6233f;
+}

+ 191 - 56
projects/textbook/src/modules/login/login/login.component.ts

@@ -1,95 +1,159 @@
-import { Component } from '@angular/core';
+import { Component, ViewChild,OnInit } from '@angular/core';
 import { ReactiveFormsModule } from '@angular/forms';
+import { HttpClient } from "@angular/common/http";
 import { Router } from '@angular/router';
+import { catchError } from "rxjs/operators";
 import {
   FormControl,
   FormGroup,
   NonNullableFormBuilder,
   Validators,
+  ValidatorFn,
+  AbstractControl,
 } from '@angular/forms';
 import { CommonCompModule } from '../common.modules';
 import { textbookServer } from '../../../services/textbook';
 import { AuthServr } from '../../../services/auth.service';
+import { CaptchaComponent } from '../../../app/captcha/captcha.component';
+import Parse from "parse";
+import { NzMessageService } from 'ng-zorro-antd/message';
+import { ParseAuthing } from './parse-authing';
+
 @Component({
   selector: 'app-login',
   standalone: true,
-  imports: [ReactiveFormsModule, CommonCompModule],
+  imports: [ReactiveFormsModule, CommonCompModule,CaptchaComponent],
   templateUrl: './login.component.html',
   styleUrl: './login.component.scss',
 })
-export class LoginComponent {
+export class LoginComponent implements OnInit{
+  @ViewChild("codelogin") codelogin: any; 
+  @ViewChild("codeloginSign") codeloginSign: any; 
+
+  ngOnInit(){
+    let parseAuthing = new ParseAuthing({
+      // 监听事件:登陆成功后,返回用户信息
+      login:(user,authClient)=>{
+        console.log(user,authClient)
+      }
+    });
+    parseAuthing.initLoginModal();
+  }
+  code:string = '' //本地生成验证码
+
+  active:number = 0
   validateForm: FormGroup<{
     userName: FormControl<string>;
     password: FormControl<string>;
     code: FormControl<string>;
-    remember: FormControl<boolean>;
+    checked: FormControl<boolean>;
   }> = this.fb.group({
     userName: ['', [Validators.required]],
     password: ['', [Validators.required]],
     code: ['', [Validators.required]],
-    remember: [true],
+    checked: [false]
   });
-  selector: Array<any> = [
-    {
-      name: '国家级管理员',
-      type: 1,
-      route: '/nav-admin/home',
-    },
-    {
-      name: '省级教育行政部门',
-      type: 2,
-      route: '/nav-province-submit/home',
-    },
-    {
-      name: '流程管理员登录',
-      type: 3,
-      route: '/nav-province-contact/home',
-    },
-    {
-      name: '省属高校联系人',
-      type: 4,
-      route: '/nav-province-school-contact/home',
-    },
-    {
-      name: '教材评审组成员',
-      type: 5,
-      route: '/nav-review/home',
-    },
-    {
-      name: '作者/教师/主编',
-      type: 6,
-      route:'/nav-author/manage/textbook'
-    },
-  ];
-  currentProfile: any = this.selector[0];
+  //校验手机号
+  confirmationValidator: ValidatorFn = (control: AbstractControl): { [s: string]: boolean } => {
+    let a = /^1[3456789]\d{9}$/;
+    if (!control.value || !String(control.value).match(a)) {
+      return { required: true };
+    }
+    return {};
+  };
+
+  validateFormPhone: FormGroup<{
+    phoneNumber: FormControl<string>;
+    code: FormControl<string>;
+    checkCode:FormControl<string>;
+    checked: FormControl<boolean>;
+  }> = this.fb.group({
+    phoneNumber: ['', [Validators.required, this.confirmationValidator]],
+    code: ['', [Validators.required]],
+    checkCode: ['', [Validators.required]],
+    checked: [false]
+  });
+
   constructor(
     public tbookSer: textbookServer,
     private fb: NonNullableFormBuilder,
     public router: Router,
-    private authServr: AuthServr
+    private authServr: AuthServr,
+    private message: NzMessageService,
+    private http: HttpClient,
   ) {
+    Parse?.User?.logOut()
   }
-  submitForm(): void {
-    if (this.validateForm.valid) {
-      let {userName, password, code } = this.validateForm.value
-      console.log(userName, password,);
-      localStorage.setItem('profile', JSON.stringify(this.currentProfile));
-      this.tbookSer.profile = this.currentProfile;
-      this.authServr.login(userName, password, this.tbookSer.company).then(() => {
-        this.router.navigate([this.currentProfile.route]);
-      });
-    } else {
-      Object.values(this.validateForm.controls).forEach((control) => {
-        if (control.invalid) {
-          control.markAsDirty();
-          control.updateValueAndValidity({ onlySelf: true });
+
+
+  onChangeCode(e:any){
+    let { code } = e
+    this.code = code
+  }
+
+  submitForm(type:string): void {
+    console.log(this.code);
+    if(type == 'account'){//登录
+      if (this.validateForm.valid) {
+        let {userName, password, code, checked } = this.validateForm.value
+        console.log(userName, password, code);
+        if(this.code.toLowerCase() != code?.toLowerCase()){
+          this.message.warning('验证码错误')
+          return
+        }else if(!checked){
+          this.message.warning('请勾选隐私协议与服务条款')
+          return
         }
-      });
+        this.authServr.login(userName, password, this.tbookSer.company).then(()=>{
+          this.codelogin.updateDrawCode();
+        }) .catch(err=>{
+          console.warn(err);
+          this.message.error(err?.message || '登录失败')
+        })
+      } else {
+        this.message.warning('填写信息不正确')
+        Object.values(this.validateForm.controls).forEach((control) => {
+          if (control.invalid) {
+            control.markAsDirty();
+            control.updateValueAndValidity({ onlySelf: true });
+          }
+        });
+      }
+    }else{//手机号登录/注册
+      console.log(this.validateFormPhone.value);
+      if (this.validateFormPhone.valid) {
+        let {phoneNumber, code } = this.validateFormPhone.value
+        console.log(phoneNumber, code);
+        if(this.code.toLowerCase() != code?.toLowerCase()){
+          this.message.warning('验证码错误')
+          return
+        }
+        this.authServr.register(phoneNumber, code, this.tbookSer.company).then(()=>{
+          this.codeloginSign.updateDrawCode();
+        }).catch((err) => {
+          console.warn(err);
+          this.message.error(err?.message || '登录失败')
+        });
+      } else {
+        this.message.warning('填写信息不正确')
+        Object.values(this.validateFormPhone.controls).forEach((control) => {
+          if (control.invalid) {
+            control.markAsDirty();
+            control.updateValueAndValidity({ onlySelf: true });
+          }
+        });
+      }
     }
+
   }
 
-  onChange(e: string) {
-    this.currentProfile = e;
+  onChange(e: any) {
+    console.log(e);
+    this.active = e.index
+    this.validateForm.reset()
+    this.validateFormPhone.reset()
+    this.codelogin.updateDrawCode();
+    this.codeloginSign.updateDrawCode();
   }
 
   goUrl(path: string) {
@@ -100,4 +164,75 @@ export class LoginComponent {
       },
     ]);
   }
+
+  buttonText = "获取验证码";
+  //添加倒计时开始和结束的判断
+  isCountingdown = false;
+  /* 获取验证码 */
+  codeDown: boolean = false;
+  startCountdown() {
+    let a = /^1[3456789]\d{9}$/;
+    let { phoneNumber, code } = this.validateFormPhone.value
+    console.log(phoneNumber);
+    if (!String(phoneNumber).match(a)) {
+      this.message.error("请填写正确手机号");
+      return;
+    }
+    if (code?.toLowerCase() != this.code.toLowerCase()) {
+      this.message.error("验证码不正确");
+      return;
+    }
+    if (this.codeDown || this.isCountingdown) return;
+    this.codeDown = true;
+    let host =
+      (Parse as any).serverURL?.split("parse")?.[0] ||
+      "https://server.fmode.cn/";
+
+    this.http
+      .post(host + "api/apig/message", {
+        company: this.tbookSer.company,
+        mobile: phoneNumber,
+      })
+      .pipe(
+        catchError(async (e) => {
+          // 显示报错
+          console.log(e);
+          this.message.create("error", e.error.mess || "验证码获取失败");
+          this.codeDown = false;
+          this.isCountingdown = false;
+          return;
+        })
+      )
+      .subscribe((res: any) => {
+        console.log(res);
+        if(res){
+          this.message.success("发送成功");
+          this.isCountingdown = true;
+          this.time();
+        }
+        this.codeloginSign.updateDrawCode();
+        this.codeDown = false;
+      });
+  }
+  /* 倒计时 */
+  time() {
+    this.isCountingdown = true;
+    this.buttonText = `${this.authServr.countdown}秒`;
+    const timer = setInterval(() => {
+      this.authServr.countdown--;
+      this.buttonText = `${this.authServr.countdown}秒`;
+      if (this.authServr.countdown === 0) {
+        clearInterval(timer);
+        this.buttonText = "重新发送";
+        this.isCountingdown = false;
+      }
+    }, 1000);
+  }
+
+  loginAuthing(){
+    this.authServr.loginAuthing();
+  }
+  stateAuthing(){
+    this.authServr.getLoginState();
+  }
 }

+ 69 - 0
projects/textbook/src/modules/login/login/parse-authing.ts

@@ -0,0 +1,69 @@
+declare var GuardFactory:any;
+
+/**
+ * ParseAuthing 通过Authing实现登录逻辑,再同步至Parse.User.become身份
+ */
+export class ParseAuthing{
+    authingGurad:any
+
+    /**
+     * Event
+     * @desc
+     * https://cdn.authing.co/packages/guard/doc/v5/guide/essentials/events.html
+     *  */
+    event:{[key:string]:Function|undefined} = {
+        onLoad:undefined, // Guard初始化完成,开始渲染页面
+        login:undefined, // 登陆成功回调
+        loginError:undefined, // 登陆失败
+        beforeLogin:undefined, // 用户触发登录前(返回<boolean | Promise<boolean>>用于控制本次登录是否继续)。
+        register:undefined, // 用户注册成功
+        beforeRegister:undefined, // 用户触发注册前(返回<boolean | Promise<boolean>>用于控制本次注册是否继续)。
+    }
+    constructor(options?:{
+        login?:{(user:any,authenticationClient:any):void}
+        loginError?:Function
+        beforeLogin?:Function
+        register?:Function
+        beforeRegister?:Function
+    }){
+        this.event['login'] = options?.login
+        this.event['login-error'] = options?.loginError
+        this.event['beforeLogin'] = options?.beforeLogin
+        this.event['register'] = options?.register
+        this.event['beforeRegister'] = options?.beforeRegister
+    }
+    initLoginModal(){
+        this.authingGurad = new GuardFactory.Guard({
+            host: 'https://textbook.u2-dev.hep.com.cn', // 应用的认证地址
+            appId: '6682ab96b7bd5db59d6785a0',
+            redirectUri:location.origin
+        })
+        // 使用 start 方法挂载 Guard 组件到你指定的 DOM 节点,登录成功后返回 userInfo
+        this.authingGurad.start('#authing-guard-container').then((userInfo:any) => {
+            console.log('userInfo in start: ', userInfo)
+        })
+        // 生命周期事件绑定
+        Object.keys(this.event).forEach(key=>{
+            if(this.event[key]){
+                this.authingGurad.on(key,this.event[key])
+            }
+        })
+        // 定制特殊生命周期
+        this.authingGurad.on("login",(user:any,authClient:any)=>{
+            // 获取Authing
+            let token = user?.token;
+            // 执行回调
+            if(typeof this.event["login"] == 'function'){
+                this.event["login"](user,authClient)
+            }
+        })
+    }
+    logout(){
+        this.authingGurad.logout();
+    }
+    async current(){
+        // 获取当前用户信息
+        const userInfo = await this.authingGurad.trackSession();
+        console.log(userInfo);
+    }
+}

+ 5 - 0
projects/textbook/src/modules/login/modules.routes.ts

@@ -3,11 +3,16 @@ import { RouterModule, Routes } from "@angular/router";
 import { LoginComponent } from './login/login.component';
 import { ResetPasswordComponent } from './reset-password/reset-password.component';
 import { RegisterComponent } from './register/register.component';
+import { AccountInfoComponent } from './account-info/account-info.component'
 const routes: Routes = [
   {
     path: 'login',
     component: LoginComponent,
   },
+  {
+    path:'account_info',
+    component:AccountInfoComponent
+  },
   {
     path: 'reset_password',
     component: ResetPasswordComponent,

+ 2 - 2
projects/textbook/src/modules/login/register/register.component.html

@@ -80,7 +80,7 @@
       </nz-input-group>
     </div>
     <div class="login-submit-btn">
-      <button
+      <!-- <button
         nz-button
         nzType="primary"
         nzBlock
@@ -88,7 +88,7 @@
         (click)="onRegister()"
       >
         注册
-      </button>
+      </button> -->
     </div>
   </div>
   <div class="card-fonter">

+ 2 - 2
projects/textbook/src/modules/login/reset-password/reset-password.component.html

@@ -69,7 +69,7 @@
       </nz-input-group>
     </div>
     <div class="login-submit-btn">
-      <button
+      <!-- <button
         nz-button
         nzType="primary"
         nzBlock
@@ -77,7 +77,7 @@
         (click)="onRegister()"
       >
         确认修改
-      </button>
+      </button> -->
     </div>
   </div>
   <div class="card-fonter">

+ 15 - 17
projects/textbook/src/modules/nav-admin/modules.routes.ts

@@ -1,34 +1,32 @@
-import { NgModule } from "@angular/core";
-import { RouterModule, Routes } from "@angular/router";
-import { PageHomeComponent } from './page-home/page-home.component';
-import { PageRoleComponent } from "./page-role/page-role.component";
-import { PageUserComponent } from "./page-user/page-user.component";
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+import { PageCollectionComponent } from './page-collection/page-collection.component';
+import { PageRoleComponent } from './page-role/page-role.component';
+import { PageUserComponent } from './page-user/page-user.component';
 const routes: Routes = [
   {
-    path: 'home',
-    component: PageHomeComponent,
-    children:[
-      // {
-      //   path: "",
-      //   redirectTo: "pay",
-      //   pathMatch: "full",
-      // },
-    ]
+    path: '',
+    redirectTo:'manage/collection',
+    pathMatch: "full",
   },
   {
     path: 'manage',
-    component: PageHomeComponent,
     children:[
       {
-        path: 'user',//列表
+        path: 'user', //列表
         component: PageUserComponent,
       },
       {
-        path: 'role',//列表
+        path: 'role', //列表
         component: PageRoleComponent,
       },
+      {
+        path: 'collection', //列表
+        component: PageCollectionComponent,
+      },
     ]
   }
+  
 ];
 @NgModule({
   imports: [RouterModule.forChild(routes)],

+ 32 - 0
projects/textbook/src/modules/nav-admin/page-collection/page-collection.component.html

@@ -0,0 +1,32 @@
+
+<!-- 表格头部 -->
+<nz-page-header *ngIf="list?.schema?.title">
+  <!--breadcrumb-->
+  <nz-breadcrumb nz-page-header-breadcrumb>
+    <nz-breadcrumb-item>国家级管理</nz-breadcrumb-item>
+    <nz-breadcrumb-item><a>报送合集</a></nz-breadcrumb-item>
+  </nz-breadcrumb>
+
+  <!--title-->
+  <nz-page-header-title>{{list?.schema?.title}}
+    <br>
+    <div class="subtitle">{{list?.schema?.subTitle}}</div>
+  </nz-page-header-title>
+
+  <!--extra-->
+  <nz-page-header-extra>
+    <nz-space>
+      <button *nzSpaceItem nz-button nzType="primary" (click)="list?.createObject()">创建合集</button>
+    </nz-space>
+  </nz-page-header-extra>
+</nz-page-header>
+
+
+<comp-table-list
+  #list
+  [schema]="EduCollection"
+  *ngIf="className && fieldsArray"
+  [className]="className"
+  [fieldsArray]="fieldsArray"
+  [queryParams]="queryParams"
+></comp-table-list>

+ 10 - 0
projects/textbook/src/modules/nav-admin/page-collection/page-collection.component.scss

@@ -0,0 +1,10 @@
+.subtitle{
+        margin-right: 12px;
+        color: #00000073;
+        font-size: 14px;
+        font-weight: normal;
+        line-height: 1.5715;
+        overflow: hidden;
+        white-space: nowrap;
+        text-overflow: ellipsis;
+}

+ 22 - 0
projects/textbook/src/modules/nav-admin/page-collection/page-collection.component.spec.ts

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

+ 61 - 0
projects/textbook/src/modules/nav-admin/page-collection/page-collection.component.ts

@@ -0,0 +1,61 @@
+import { Component, OnInit, ViewChild } from '@angular/core';
+import { ActivatedRoute, RouterOutlet } from '@angular/router';
+import { CompTableListComponent } from '../../../app/comp-table/comp-table-list/comp-table-list.component';
+import EduCollection from '../../../schemas/EduCollection';
+// import { TranslateService } from '@ngx-translate/core';
+import * as Parse from "parse";
+import { CommonModule } from '@angular/common';
+import { NzTagModule } from 'ng-zorro-antd/tag';
+import { NzButtonModule } from 'ng-zorro-antd/button';
+import { NzIconModule } from 'ng-zorro-antd/icon';
+import { NzPageHeaderModule } from 'ng-zorro-antd/page-header';
+import { NzBreadCrumbModule } from 'ng-zorro-antd/breadcrumb';
+import { NzSpaceModule } from 'ng-zorro-antd/space';
+import { NzDropDownModule } from 'ng-zorro-antd/dropdown';
+
+
+@Component({
+  selector: 'app-page-collection',
+  templateUrl: './page-collection.component.html',
+  styleUrls: ['./page-collection.component.scss'],
+  imports: [
+    CommonModule,RouterOutlet,CompTableListComponent,
+    NzPageHeaderModule,NzBreadCrumbModule,NzTagModule,NzButtonModule,NzIconModule,NzSpaceModule,
+    NzDropDownModule,
+  ],
+  standalone: true,
+})
+export class PageCollectionComponent  implements OnInit {
+  @ViewChild(CompTableListComponent) list:CompTableListComponent|undefined
+
+  EduCollection = EduCollection
+  className:string|undefined
+  queryParams:any|undefined
+  fieldsArray:Array<any>|undefined
+
+  constructor(
+    private route: ActivatedRoute,
+    private activeRoute: ActivatedRoute,
+    // private translate:TranslateService,
+  ) {
+    this.className = this.EduCollection.className
+    this.fieldsArray = this.EduCollection.fieldsArray
+    this.queryParams = {where:{
+      // Collection:this.Collection?.toPointer(),
+      isDeleted:{$ne:true},
+    }}
+  }
+
+  ngOnInit(): void {
+    this.activeRoute.paramMap.subscribe(async (params) => {
+      let isDeleted = params.get('isDeleted')
+      if(isDeleted){
+        this.queryParams.where['isDeleted'] = {$eq:true}
+      }else{
+        this.queryParams.where['isDeleted'] = {$ne:true}
+      }
+      this.list?.ngOnInit()
+    });
+  }
+
+}

+ 0 - 35
projects/textbook/src/modules/nav-admin/page-home/page-home.component.html

@@ -1,35 +0,0 @@
-<app-comp-nav></app-comp-nav>
-<div class="page">
-  <div class="content-left">
-    <ul nz-menu nzMode="inline" style="width: 240px">
-      @for (item of options; track item.id;let index = $index) { @if(item.child)
-      {
-      <li nz-submenu [nzTitle]="item.name" nzIcon="api" [nzOpen]="true">
-        <ul>
-          @for (child of item.child; track child.id;let idx = $index) {
-          <li
-            nz-menu-item
-            [nzSelected]="active == child.id"
-            (click)="toUrl(child)"
-          >
-            {{ child.name }}
-          </li>
-          }
-        </ul>
-      </li>
-      } @else {
-      <li
-        nz-menu-item
-        (click)="toUrl(item)"
-        [nzSelected]="active == item.id"
-      >
-        <span nz-icon nzType="home" nzTheme="outline"></span>
-        <span>{{ item.name }}</span>
-      </li>
-      } }
-    </ul>
-  </div>
-  <div class="preview">
-    <router-outlet></router-outlet>
-  </div>
-</div>

+ 0 - 15
projects/textbook/src/modules/nav-admin/page-home/page-home.component.scss

@@ -1,15 +0,0 @@
-.page{
-  display: flex;
-  height: calc(100% - 60px);
-  // overflow-y: scroll;
-  overflow-y: hidden;
-  .content-left{
-    background-color:#fff;
-  }
-  .preview{
-    height: 100%;
-    overflow-y: scroll;
-    padding: 20px 0 40px 0;
-    flex: 1;
-  }
-}

+ 0 - 86
projects/textbook/src/modules/nav-admin/page-home/page-home.component.ts

@@ -1,86 +0,0 @@
-import { Component, OnInit } from '@angular/core';
-import { CompNavComponent } from '../../../app/comp-nav/comp-nav.component'
-import { RouterOutlet, Router } from '@angular/router';
-import { CommonCompModule } from '../../../services/common.modules'
-
-@Component({
-  selector: 'app-page-home',
-  standalone: true,
-  imports: [CompNavComponent,RouterOutlet,CommonCompModule],
-  templateUrl: './page-home.component.html',
-  styleUrls: ['./page-home.component.scss'],
-})
-export class PageHomeComponent  implements OnInit {
-
-  options:Array<any> = [
-    {
-      name:'教材管理',
-      id:'1',
-      child:[
-        {
-          name:'报送合集',
-          id:'1-1',
-        },
-        {
-          name:'全部材料',
-          id:'1-2',
-        },
-      ]
-    },
-    {
-      name:'用户管理',
-      id:'2',
-      child:[
-        {
-          name:'用户审核',
-          id:'2-1',
-        },
-        {
-          name:'注册账户',
-          path:"/nav-admin/manage/user",
-          id:'2-2',
-        },
-        {
-          name:'用户组管理',
-          path:"/nav-admin/manage/role",
-          id:'2-3',
-        },
-      ]
-    },
-    {
-      name:'品牌化',
-      id:'3',
-      child:[
-        {
-          name:'登录框',
-          id:'3-1',
-        },
-        {
-          name:'消息设置',
-          id:'3-2',
-        },
-      ]
-    },
-    {
-      name:'字段管理',
-      id:'4',
-    },
-  ]
-  active:string = localStorage.getItem('active') || this.options[0].id
-  constructor(
-    public router: Router,
-  ) { }
-
-  ngOnInit() {}
-  toUrl(child: any) {
-    let cateid = child.id;
-    this.active = cateid;
-    localStorage.setItem('active', cateid);
-    console.log(child);
-    if (child.params) {
-      this.router.navigate([child.path, child?.params]);
-    } else {
-      this.router.navigate([child.path]);
-    }
-  }
-}

+ 31 - 20
projects/textbook/src/modules/nav-author/apply/apply.component.html

@@ -1,42 +1,53 @@
-<nz-page-header class="site-page-header" nzTitle="" nzSubtitle="">
-  <nz-breadcrumb nz-page-header-breadcrumb>
-    <nz-breadcrumb-item>个人空间</nz-breadcrumb-item>
-    <nz-breadcrumb-item>
-      <a>创建材料</a>
-    </nz-breadcrumb-item>
-    <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-step nzTitle="上传附件及承诺" nzDescription=""></nz-step>
-      </nz-steps>
-    </div>
-  </nz-breadcrumb>
-</nz-page-header>
+<div class="site-page-header">
+  <nz-page-header nzTitle="创建/编辑空间" nzSubtitle="" style="padding: 0">
+    <nz-breadcrumb nz-page-header-breadcrumb>
+      <div class="back" (click)="back()">
+        <span nz-icon nzType="left" nzTheme="outline"></span>返回
+      </div>
+    </nz-breadcrumb>
+  </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-step nzTitle="上传附件及承诺" nzDescription=""></nz-step>
+    </nz-steps>
+  </div>
+</div>
+
 <div class="content">
   <div class="state-title">{{ stateMap }}</div>
+  @if (showFrom) {
   <div class="submit-block" #submitComp>
     @switch (state) { @case (0) {
-    <app-basic (next)="next()" (save)="save()"></app-basic>
+    <app-basic
+      [eduTextbook]="textBook"
+      (state)="changeState($event)"
+      (save)="save()"
+    ></app-basic>
     } @case (1) {
     <app-textbook-pertain
-      (next)="next()"
+      [eduTextbook]="textBook"
+      (state)="changeState($event)"
       (save)="save()"
       (maxWidth)="(submitComp.style.width)"
     ></app-textbook-pertain>
     } @case (2) {
     <app-textbook-content
-      (next)="next()"
+      [eduTextbook]="textBook"
+      (state)="changeState($event)"
       (save)="save()"
       (maxWidth)="(submitComp.style.width)"
     ></app-textbook-content>
     } @case (3) {
     <app-attachment
-      (next)="next()"
+      [eduTextbook]="textBook"
+      (state)="changeState($event)"
       (save)="save()"
       (maxWidth)="(submitComp.style.width)"
     ></app-attachment>
     } }
   </div>
+  }
 </div>

+ 10 - 1
projects/textbook/src/modules/nav-author/apply/apply.component.scss

@@ -4,15 +4,24 @@
   z-index: 9;
   padding:24px 24px 10px;
   background-color: white;
+  font-family: PingFang SC;
   .steps{
     max-width: 1000px;
     margin: 10px 0;
   }
+  .back{
+    font-family: PingFang SC;
+    font-size: 14px;
+    font-weight: 400;
+    line-height: 22px;
+    text-align: left;
+    cursor: pointer;
+  }
 }
 
 .content {
   font-family: PingFang SC;
-  padding: 10px 20px;
+  padding: 10px 24px;
   .state-title {
     margin:0 0 20px;
     font-family: PingFang SC;

+ 35 - 9
projects/textbook/src/modules/nav-author/apply/apply.component.ts

@@ -1,12 +1,14 @@
 import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
 import { CommonCompModule } from '../../../services/common.modules';
-import { Router } from '@angular/router';
+import { Router, ActivatedRoute } from '@angular/router';
 import { ReactiveFormsModule } from '@angular/forms';
 import { BasicInComponent } from '../components/basic-in/basic-in.component';
 import { TextbookPertainComponent } from '../components/textbook-pertain/textbook-pertain.component';
-import { TextbookContentComponent }  from '../components/textbook-content/textbook-content.component'
-import { AttachmentComponent } from '../components/attachment/attachment.component'
+import { TextbookContentComponent } from '../components/textbook-content/textbook-content.component';
+import { AttachmentComponent } from '../components/attachment/attachment.component';
 // import { NzLayoutModule } from 'ng-zorro-antd/layout';
+import Parse from 'parse';
+
 @Component({
   selector: 'app-apply',
   imports: [
@@ -15,13 +17,14 @@ import { AttachmentComponent } from '../components/attachment/attachment.compone
     BasicInComponent,
     TextbookPertainComponent,
     TextbookContentComponent,
-    AttachmentComponent
+    AttachmentComponent,
   ],
   standalone: true,
   templateUrl: './apply.component.html',
   styleUrls: ['./apply.component.scss'],
 })
 export class ApplyComponent implements OnInit {
+  textBook: Parse.Object | any;
   state: number = 0;
   get stateMap() {
     let map: any = {
@@ -32,13 +35,36 @@ export class ApplyComponent implements OnInit {
     };
     return map[this.state];
   }
-  editForm: any;
+  showFrom: boolean = false;
 
-  constructor(private router: Router) {}
+  constructor(private router: Router, private activeRoute: ActivatedRoute) {}
 
-  ngOnInit() {}
-  next() {
-    this.state++;
+  async ngOnInit() {
+    this.activeRoute.paramMap.subscribe(async (params) => {
+      let id = params.get('id');
+      if (id) {
+        let query = new Parse.Query('EduTextbook');
+        query.equalTo('objectId', id);
+        this.textBook = await query.first();
+        console.log(this.textBook);
+      }
+      this.showFrom = true;
+    });
+  }
+  changeState(event: string | any) {
+    console.log(event);
+    if(event?.textBook){
+      this.textBook = event?.textBook
+    }
+    if (event?.type == 'pre') {
+      this.state--;
+    } else {
+      this.state++;
+    }
   }
   save() {}
+
+  back() {
+    history.back();
+  }
 }

+ 108 - 120
projects/textbook/src/modules/nav-author/components/attachment/attachment.component.html

@@ -86,88 +86,79 @@
 
       <nz-table
         #basicTable
-        [nzData]="courses"
+        [nzData]="opinions"
         [nzScroll]="{ x: (maxWidth || '1200') + 'px' }"
       >
         <thead>
           <tr>
             <th nzWidth="80px" nzLeft nzAlign="right">序号</th>
-            <th nzWidth="120px">出版时间</th>
-            <th nzWidth="100px">字数</th>
-            <th nzWidth="100px">重印次数</th>
-            <th nzWidth="100px">本版总印数</th>
-            <th nzWidth="200px">获奖励情况</th>
+            <th nzWidth="120px">姓名</th>
+            <th nzWidth="120px">单位</th>
+            <th nzWidth="120px">出生年月</th>
+            <th nzWidth="120px">国籍</th>
+            <th nzWidth="120px" nzRight>
+              <nz-form-label [nzNoColon]="true" nzRequired
+                >作者政治审查表</nz-form-label
+              >
+            </th>
             <th nzWidth="80px" nzRight>操作</th>
           </tr>
         </thead>
         <tbody>
-          @for (data of courses; track $index) {
+          @for (data of opinions; track $index) {
           <tr>
             <td nzLeft nzAlign="right">{{ $index + 1 }}</td>
             <td>
-              <nz-date-picker
-                nzMode="month"
+              <input
+                nz-input
+                type="number"
+                placeholder="请填写作者姓名"
                 [ngModelOptions]="{ standalone: true }"
-                [(ngModel)]="data.date"
-              ></nz-date-picker>
-            </td>
-            <td>
-              <nz-input-group
-                style="width: 100%"
-                [nzSuffix]="suffixTemplateInfo"
-              >
-                <input
-                  type="number"
-                  [(ngModel)]="data.wordage"
-                  nz-input
-                  placeholder="请输入字数"
-                  [ngModelOptions]="{ standalone: true }"
-                />
-              </nz-input-group>
-              <ng-template #suffixTemplateInfo>万</ng-template>
+                [(ngModel)]="data.name"
+                nzStatus=""
+              />
             </td>
             <td>
-              <nz-input-group
-                style="width: 100%"
-                [nzSuffix]="suffixTemplateInfo2"
-              >
-                <input
-                  type="number"
-                  [(ngModel)]="data.num"
-                  nz-input
-                  placeholder="请输入重印次数"
-                  [ngModelOptions]="{ standalone: true }"
-                />
-              </nz-input-group>
-              <ng-template #suffixTemplateInfo2>次</ng-template>
+              <input
+                nz-input
+                type="number"
+                placeholder="请填写作者单位"
+                [ngModelOptions]="{ standalone: true }"
+                [(ngModel)]="data.unit"
+                nzStatus=""
+              />
             </td>
             <td>
-              <nz-input-group
-                style="width: 100%"
-                [nzSuffix]="suffixTemplateInfo"
-              >
-                <input
-                  type="number"
-                  [(ngModel)]="data.sumNum"
-                  nz-input
-                  placeholder="请输入本版总印数"
-                  [ngModelOptions]="{ standalone: true }"
-                />
-              </nz-input-group>
-              <ng-template #suffixTemplateInfo>万</ng-template>
+              <nz-date-picker
+                nzMode="month"
+                [ngModelOptions]="{ standalone: true }"
+                [(ngModel)]="data.birth"
+              ></nz-date-picker>
             </td>
             <td>
               <input
                 nz-input
                 type="number"
-                placeholder="请输入所获奖项"
+                placeholder="请填写作者国籍"
                 [ngModelOptions]="{ standalone: true }"
-                [(ngModel)]="data.accolade"
+                [(ngModel)]="data.nationality"
                 nzStatus=""
               />
             </td>
             <td nzRight>
-              <a class="edit-icon" (click)="onPush($index)"
+              <nz-upload
+                formControlName="textbookFiles"
+                nzAction="https://www.mocky.io/v2/5cc8019d300000980a055e76"
+                [nzHeaders]="{ authorization: 'authorization-text' }"
+                (nzChange)="handleChange($event)"
+              >
+                <div style="color: #3e49b3">
+                  <span nz-icon nzType="upload"></span>上传文件
+                </div>
+              </nz-upload>
+            </td>
+            <td nzRight>
+              <a class="edit-icon" (click)="onPush('opinions', $index)"
                 ><span
                   nz-icon
                   style="font-size: 20px; margin-right: 10px"
@@ -175,7 +166,7 @@
                   nzTheme="outline"
                 ></span
               ></a>
-              <a class="edit-icon" (click)="onDel($index)"
+              <a class="edit-icon" (click)="onDel('opinions', $index)"
                 ><span
                   nz-icon
                   style="font-size: 20px"
@@ -211,7 +202,7 @@
           style="width: 100%"
         >
           <nz-upload
-            formControlName="textbookFiles"
+            formControlName="selfResults"
             nzAction="https://www.mocky.io/v2/5cc8019d300000980a055e76"
             [nzHeaders]="{ authorization: 'authorization-text' }"
             (nzChange)="handleChange($event)"
@@ -322,7 +313,7 @@
     </div>
     <div class="author-content">
       <div class="nav">教材作者诚信承诺</div>
-      <div class="text">请输入作者诚信承诺文字内容,并上传所有作者签名</div>
+      <div class="text">请填写作者诚信承诺文字内容,并上传所有作者签名</div>
       <nz-form-item class="row" style="margin-bottom: 16px">
         <nz-form-label
           class="label"
@@ -330,16 +321,16 @@
           [nzSm]="16"
           [nzXs]="16"
           nzRequired
-          >输入诚信承诺:本人自愿参加此次申报,已认真填写并检查以上材料,保证内容真实</nz-form-label
+          >填写诚信承诺:本人自愿参加此次申报,已认真填写并检查以上材料,保证内容真实</nz-form-label
         >
         <nz-form-control
           class="val"
-          nzErrorTip="请输入承诺内容"
+          nzErrorTip="请填写承诺内容"
           style="width: 450px"
         >
           <input
             formControlName="links"
-            placeholder="请输入承诺内容"
+            placeholder="请填写承诺内容"
             nz-input
           />
         </nz-form-control>
@@ -356,88 +347,79 @@
       >
       <nz-table
         #basicTable
-        [nzData]="courses"
+        [nzData]="authorSign"
         [nzScroll]="{ x: (maxWidth || '1200') + 'px' }"
       >
         <thead>
           <tr>
             <th nzWidth="80px" nzLeft nzAlign="right">序号</th>
-            <th nzWidth="120px">出版时间</th>
-            <th nzWidth="100px">字数</th>
-            <th nzWidth="100px">重印次数</th>
-            <th nzWidth="100px">本版总印数</th>
-            <th nzWidth="200px">获奖励情况</th>
+            <th nzWidth="120px">姓名</th>
+            <th nzWidth="120px">单位</th>
+            <th nzWidth="120px">出生年月</th>
+            <th nzWidth="120px">国籍</th>
+            <th nzWidth="120px" nzRight>
+              <nz-form-label [nzNoColon]="true" nzRequired
+                >作者政治审查表</nz-form-label
+              >
+            </th>
             <th nzWidth="80px" nzRight>操作</th>
           </tr>
         </thead>
         <tbody>
-          @for (data of courses; track $index) {
+          @for (data of authorSign; track $index) {
           <tr>
             <td nzLeft nzAlign="right">{{ $index + 1 }}</td>
             <td>
-              <nz-date-picker
-                nzMode="month"
+              <input
+                nz-input
+                type="number"
+                placeholder="请填写作者姓名"
                 [ngModelOptions]="{ standalone: true }"
-                [(ngModel)]="data.date"
-              ></nz-date-picker>
-            </td>
-            <td>
-              <nz-input-group
-                style="width: 100%"
-                [nzSuffix]="suffixTemplateInfo"
-              >
-                <input
-                  type="number"
-                  [(ngModel)]="data.wordage"
-                  nz-input
-                  placeholder="请输入字数"
-                  [ngModelOptions]="{ standalone: true }"
-                />
-              </nz-input-group>
-              <ng-template #suffixTemplateInfo>万</ng-template>
+                [(ngModel)]="data.name"
+                nzStatus=""
+              />
             </td>
             <td>
-              <nz-input-group
-                style="width: 100%"
-                [nzSuffix]="suffixTemplateInfo2"
-              >
-                <input
-                  type="number"
-                  [(ngModel)]="data.num"
-                  nz-input
-                  placeholder="请输入重印次数"
-                  [ngModelOptions]="{ standalone: true }"
-                />
-              </nz-input-group>
-              <ng-template #suffixTemplateInfo2>次</ng-template>
+              <input
+                nz-input
+                type="number"
+                placeholder="请填写作者单位"
+                [ngModelOptions]="{ standalone: true }"
+                [(ngModel)]="data.unit"
+                nzStatus=""
+              />
             </td>
             <td>
-              <nz-input-group
-                style="width: 100%"
-                [nzSuffix]="suffixTemplateInfo"
-              >
-                <input
-                  type="number"
-                  [(ngModel)]="data.sumNum"
-                  nz-input
-                  placeholder="请输入本版总印数"
-                  [ngModelOptions]="{ standalone: true }"
-                />
-              </nz-input-group>
-              <ng-template #suffixTemplateInfo>万</ng-template>
+              <nz-date-picker
+                nzMode="month"
+                [ngModelOptions]="{ standalone: true }"
+                [(ngModel)]="data.birth"
+              ></nz-date-picker>
             </td>
             <td>
               <input
                 nz-input
                 type="number"
-                placeholder="请输入所获奖项"
+                placeholder="请填写作者国籍"
                 [ngModelOptions]="{ standalone: true }"
-                [(ngModel)]="data.accolade"
+                [(ngModel)]="data.nationality"
                 nzStatus=""
               />
             </td>
             <td nzRight>
-              <a class="edit-icon" (click)="onPush($index)"
+              <nz-upload
+                formControlName="textbookFiles"
+                nzAction="https://www.mocky.io/v2/5cc8019d300000980a055e76"
+                [nzHeaders]="{ authorization: 'authorization-text' }"
+                (nzChange)="handleChange($event)"
+              >
+                <div style="color: #3e49b3">
+                  <span nz-icon nzType="upload"></span>上传文件
+                </div>
+              </nz-upload>
+            </td>
+            <td nzRight>
+              <a class="edit-icon" (click)="onPush('authorSign', $index)"
                 ><span
                   nz-icon
                   style="font-size: 20px; margin-right: 10px"
@@ -445,7 +427,7 @@
                   nzTheme="outline"
                 ></span
               ></a>
-              <a class="edit-icon" (click)="onDel($index)"
+              <a class="edit-icon" (click)="onDel('authorSign', $index)"
                 ><span
                   nz-icon
                   style="font-size: 20px"
@@ -481,7 +463,7 @@
           style="width: 450px"
         >
           <nz-upload
-            formControlName="textbookFiles"
+            formControlName="unitMaterial"
             nzAction="https://www.mocky.io/v2/5cc8019d300000980a055e76"
             [nzHeaders]="{ authorization: 'authorization-text' }"
             (nzChange)="handleChange($event)"
@@ -507,7 +489,13 @@
   >
     保存本页
   </button>
-  <button nz-button nzType="primary" (click)="submitForm('next')">
-    下一页
+  <button
+    nz-button
+    nzType="default"
+    style="margin-right: 20px"
+    (click)="submitForm('pre')"
+  >
+    上一步
   </button>
+  <button nz-button nzType="primary" style="background: #3e49b3; border: 1px #3e49b3" (click)="submitForm('complete')">完成</button>
 </div>

+ 80 - 31
projects/textbook/src/modules/nav-author/components/attachment/attachment.component.ts

@@ -9,18 +9,19 @@ import { NzCheckboxModule } from 'ng-zorro-antd/checkbox';
 import { NzTableModule } from 'ng-zorro-antd/table';
 import { NzUploadChangeParam } from 'ng-zorro-antd/upload';
 import { NzUploadModule } from 'ng-zorro-antd/upload';
+import { NzModalService } from 'ng-zorro-antd/modal';
 import {
   FormControl,
   FormGroup,
   NonNullableFormBuilder,
   Validators,
 } from '@angular/forms';
-interface course {
-  date: Date | any;
-  wordage: number | any;
-  num: number | any;
-  sumNum: number | any;
-  accolade: string;
+interface opinionType {
+  name: string;
+  unit: string;
+  birth: Date | any;
+  nationality: string;
+  reviewFile: string;
 }
 @Component({
   selector: 'app-attachment',
@@ -32,43 +33,58 @@ interface course {
     NzGridModule,
     NzCheckboxModule,
     NzTableModule,
-    NzUploadModule
+    NzUploadModule,
   ],
   standalone: true,
   templateUrl: './attachment.component.html',
   styleUrls: ['./attachment.component.scss'],
 })
 export class AttachmentComponent implements OnInit {
-  @Input('editFrom') editFrom: any;
+  @Input('eduTextbook') editFrom: any;
   @Input('maxWidth') maxWidth: number = 0;
-  @Output() next: EventEmitter<any> = new EventEmitter<any>();
+  @Output() state: EventEmitter<any> = new EventEmitter<any>();
   @Output() save: EventEmitter<any> = new EventEmitter<any>();
   validateForm: FormGroup<{
     textbookTypes: FormControl<Array<string> | any>; //教材电子版
-    textbookFiles: FormControl<Array<string> | any>;//上传教材文件
-    links: FormControl<string> //教材数字内容链接地址、账号
+    textbookFiles: FormControl<Array<string> | any>; //上传教材文件
+    links: FormControl<string>; //教材数字内容链接地址、账号
+    selfResults:FormControl<object|any>, //图书编校质量自查结果记录表
+    unitMaterial:FormControl<object|any>, //申报单位承诺意见材料
   }> = this.fb.group({
     textbookTypes: ['', [Validators.required]],
     textbookFiles: ['', [Validators.required]],
     links: ['', [Validators.required]],
+    selfResults: ['', [Validators.required]],
+    unitMaterial: ['', [Validators.required]],
   });
   checkOptionsOne = [
     { label: '纸质教材', value: '纸质教材' },
     { label: '电子教材 / 资源', value: '电子教材 / 资源' },
   ];
-  //申报教材建设历程
-  courses: Array<course> = [
+  //所有作者政治审查意见
+  opinions: Array<opinionType> = [
     {
-      date: '', //出版时间
-      wordage: '', //字数
-      num: '', //重印次数
-      sumNum: '', //本版总印数
-      accolade: '', //获奖励情况
+      name: '', //作者
+      unit: '', //单位
+      birth: '', //出生年月
+      nationality: '', //国籍
+      reviewFile: '', //作者政治审查表/作者签名
+    },
+  ];
+  //所有作者签名
+  authorSign: Array<opinionType> = [
+    {
+      name: '', //作者
+      unit: '', //单位
+      birth: '', //出生年月
+      nationality: '', //国籍
+      reviewFile: '', //作者政治审查表/作者签名
     },
   ];
   constructor(
     private fb: NonNullableFormBuilder,
-    private msg: NzMessageService
+    private msg: NzMessageService,
+    private modal: NzModalService
   ) {}
   ngOnInit() {}
   submitForm(event?: string): void {
@@ -84,25 +100,58 @@ export class AttachmentComponent implements OnInit {
       });
       this.msg.warning('请填写完整信息');
     }
-    if (event == 'next') {
-      this.next.emit();
+    if (event == 'pre') {
+      this.state.emit('pre');
+    }
+    if (event == 'save') {
+      this.modal.success({
+        nzTitle: '您已填写完成',
+        nzContent: '<p>已保存并且至空间</p>',
+        nzOnOk: () => console.log('Info OK')
+      });
     }
+    if(event == 'complete')
+    this.modal.success({
+      nzTitle: '您已填写完成',
+      nzContent: '<p>已保存并且至空间</p>',
+      nzOnOk: () => console.log('Info OK')
+    });
   }
   changeCode() {}
   getCode(e: any) {}
   //添加作者信息
-  onPush(idx: number) {
-    this.courses.splice(idx + 1, 0, {
-      date: '',
-      wordage: '',
-      num: '',
-      sumNum: '',
-      accolade: '',
-    });
+  onPush(type: string, idx: number) {
+    switch (type) {
+      case 'opinions':
+        this.opinions.splice(idx + 1, 0, {
+          name: '', //作者
+          unit: '', //单位
+          birth: '', //出生年月
+          nationality: '', //国籍
+          reviewFile: '', //作者政治审查表/作者签名
+        });
+        break;
+      case 'authorSign':
+        this.authorSign.splice(idx + 1, 0, {
+          name: '', //作者
+          unit: '', //单位
+          birth: '', //出生年月
+          nationality: '', //国籍
+          reviewFile: '', //作者政治审查表/作者签名
+        });
+        break;
+    }
   }
   //删除作者信息
-  onDel(idx: number) {
-    this.courses.splice(idx, 1);
+  onDel(type: string, idx: number) {
+    switch (type) {
+      case 'opinions':
+        this.opinions.splice(idx, 1);
+        break;
+      case 'authorSign':
+        this.authorSign.splice(idx, 1);
+        break;
+    }
   }
   handleChange(info: NzUploadChangeParam): void {
     if (info.file.status !== 'uploading') {

+ 39 - 32
projects/textbook/src/modules/nav-author/components/basic-in/basic-in.component.html

@@ -6,7 +6,12 @@
     (ngSubmit)="submitForm()"
   >
     <nz-form-item style="margin-bottom: 16px">
-      <nz-form-label [nzSm]="8" [nzNoColon]="true" [nzXs]="8" nzRequired nzFor="user"
+      <nz-form-label
+        [nzSm]="8"
+        [nzNoColon]="true"
+        [nzXs]="8"
+        nzRequired
+        nzFor="user"
         >申报教材名称</nz-form-label
       >
       <nz-form-control nzErrorTip="请输入申报教材名称" [nzSm]="12" [nzXs]="12">
@@ -14,7 +19,7 @@
           <input
             type="text"
             nz-input
-            formControlName="name"
+            formControlName="title"
             placeholder="请输入申报教材名称"
           />
         </nz-input-group>
@@ -74,7 +79,9 @@
       </nz-form-control>
     </nz-form-item>
     <nz-form-item style="margin-bottom: 16px">
-      <nz-form-label [nzSm]="8" [nzNoColon]="true" [nzXs]="8" nzRequired>申报类型</nz-form-label>
+      <nz-form-label [nzSm]="8" [nzNoColon]="true" [nzXs]="8" nzRequired
+        >申报类型</nz-form-label
+      >
       <nz-form-control nzErrorTip="请输入申报类型" [nzSm]="12" [nzXs]="12">
         <nz-input-group>
           <!-- <input
@@ -88,12 +95,12 @@
             style="display: flex; flex-direction: column"
             formControlName="type"
           >
-            <label nz-radio nzValue="单册">单册</label>
+            <label nz-radio nzValue="单册" (click)="requiredTypeNumber(false)">单册</label>
             <div class="basic-row">
-              <label nz-radio nzValue="全册">全册</label>
+              <label nz-radio nzValue="全册" (click)="requiredTypeNumber(true)">全册</label>
               @if (validateForm.value.type =='全册') {
               <nz-input-group
-                style="flex:1; margin-left: 20px"
+                style="flex: 1; margin-left: 20px"
                 [nzSuffix]="suffixTemplateInfo"
               >
                 <input
@@ -125,8 +132,6 @@
             nzAllowClear
             nzPlaceHolder="请输入搜索内容"
             formControlName="majorPoniter"
-            (ngModelChange)="changeMajor()"
-            (nzOnSearch)="getMajor($event)"
           >
             @for(major of selectList; track major.code;let index = $index){
             <nz-option
@@ -155,8 +160,6 @@
             nzAllowClear
             nzPlaceHolder="请输入搜索内容"
             formControlName="lang"
-            (ngModelChange)="changeMajor()"
-            (nzOnSearch)="getMajor($event)"
           >
             @for(lang of selectLang; track lang.lang;let index = $index){
             <nz-option
@@ -211,57 +214,56 @@
             nzAllowClear
             nzPlaceHolder="请输入是否重点立项教材"
             formControlName="approval"
-            (ngModelChange)="changeMajor()"
-            (nzOnSearch)="getMajor($event)"
           >
-            @for(item of directorys; track item.code;let index = $index){
-            <nz-option
-              nzCustomContent
-              [nzValue]="item.code"
-              [nzLabel]="item.name"
-              >{{ item.name }}</nz-option
+            <nz-option nzCustomContent [nzValue]="true" [nzLabel]="'是'"
+              >是</nz-option
+            >
+            <nz-option nzCustomContent [nzValue]="false" [nzLabel]="'否'"
+              >否</nz-option
             >
-            }
           </nz-select>
         </nz-input-group>
       </nz-form-control>
     </nz-form-item>
     <nz-form-item style="margin-bottom: 16px">
-      <nz-form-label [nzSm]="8" [nzNoColon]="true" [nzXs]="8" nzRequired>出版单位</nz-form-label>
+      <nz-form-label [nzSm]="8" [nzNoColon]="true" [nzXs]="8" nzRequired
+        >出版单位</nz-form-label
+      >
       <nz-form-control nzErrorTip="请输入出版单位" [nzSm]="12" [nzXs]="12">
         <nz-input-group>
           <input
             type="text"
             nz-input
-            formControlName="edition"
+            formControlName="editionUnit"
             placeholder="请输入出版单位"
           />
         </nz-input-group>
       </nz-form-control>
     </nz-form-item>
     <nz-form-item style="margin-bottom: 16px">
-      <nz-form-label [nzSm]="8" [nzNoColon]="true" [nzXs]="8" nzRequired>初版时间</nz-form-label>
+      <nz-form-label [nzSm]="8" [nzNoColon]="true" [nzXs]="8" nzRequired
+        >初版时间</nz-form-label
+      >
       <nz-form-control nzErrorTip="请输入初版时间" [nzSm]="12" [nzXs]="12">
         <nz-input-group>
           <nz-date-picker
             style="width: 100%"
             formControlName="editionFirst"
-            (ngModelChange)="onChange($event)"
           ></nz-date-picker>
         </nz-input-group>
       </nz-form-control>
     </nz-form-item>
     <nz-form-item style="margin-bottom: 16px">
-      <nz-form-label [nzSm]="8" [nzNoColon]="true" [nzXs]="8" nzRequired>载体形式</nz-form-label>
+      <nz-form-label [nzSm]="8" [nzNoColon]="true" [nzXs]="8" nzRequired
+        >载体形式</nz-form-label
+      >
       <nz-form-control nzErrorTip="请输入载体形式" [nzSm]="12" [nzXs]="12">
         <nz-input-group>
           <nz-select
             nzShowSearch
             nzAllowClear
             nzPlaceHolder="请输入是否重点立项教材"
-            formControlName="approval"
-            (ngModelChange)="changeMajor()"
-            (nzOnSearch)="getMajor($event)"
+            formControlName="carrierShape"
           >
             @for(item of carrierOptions; track item.code;let index = $index){
             <nz-option
@@ -285,7 +287,6 @@
             <nz-date-picker
               style="flex: 1"
               formControlName="editionDate"
-              (ngModelChange)="onChange($event)"
             ></nz-date-picker>
             <nz-input-group
               style="width: 100px; margin-left: 20px"
@@ -313,7 +314,6 @@
             <nz-date-picker
               style="flex: 1"
               formControlName="printDate"
-              (ngModelChange)="onChange($event)"
             ></nz-date-picker>
             <nz-input-group
               style="width: 100px; margin-left: 20px"
@@ -365,7 +365,7 @@
             formControlName="importantProject"
           >
             @for (item of importantProjectList; track item.value) {
-            <label nz-radio [nzValue]="item.value">{{ item.title }}</label>
+            <label (click)="onChangeRadio()" nz-radio [nzValue]="item.value">{{ item.title }}</label>
             } @if (validateForm.value.importantProject ==
             '其他省部级及以上项目') {
             <input
@@ -380,7 +380,9 @@
       </nz-form-control>
     </nz-form-item>
     <nz-form-item style="margin-bottom: 16px">
-      <nz-form-label [nzSm]="8" [nzNoColon]="true" [nzXs]="8" nzRequired>版权页截图</nz-form-label>
+      <nz-form-label [nzSm]="8" [nzNoColon]="true" [nzXs]="8" nzRequired
+        >版权页截图</nz-form-label
+      >
       <nz-form-control nzErrorTip="请输入版权页截图" [nzSm]="12" [nzXs]="12">
         <nz-input-group>
           <nz-upload
@@ -440,7 +442,12 @@
   >
     保存本页
   </button>
-  <button nz-button nzType="primary" (click)="submitForm('next')">
+  <button
+    nz-button
+    nzType="primary"
+    style="background: #3e49b3; border: 1px #3e49b3"
+    (click)="submitForm('next')"
+  >
     下一页
   </button>
 </div>

+ 167 - 40
projects/textbook/src/modules/nav-author/components/basic-in/basic-in.component.ts

@@ -7,6 +7,9 @@ import { NzRadioModule } from 'ng-zorro-antd/radio';
 import { NzUploadModule } from 'ng-zorro-antd/upload';
 import { NzMessageService } from 'ng-zorro-antd/message';
 import { NzUploadChangeParam } from 'ng-zorro-antd/upload';
+import { NzModalService } from 'ng-zorro-antd/modal';
+import { textbookServer } from '../../../../services/textbook'
+import Parse from 'parse';
 import {
   FormControl,
   FormGroup,
@@ -27,12 +30,13 @@ import {
   styleUrls: ['./basic-in.component.scss'],
 })
 export class BasicInComponent implements OnInit {
+  @Input('eduTextbook') eduTextbook: Parse.Object|any;
   @Input('editFrom') editFrom: any;
-  @Output() next: EventEmitter<any> = new EventEmitter<any>();
+  @Output() state: EventEmitter<any> = new EventEmitter<any>();
   @Output() save: EventEmitter<any> = new EventEmitter<any>();
 
   validateForm: FormGroup<{
-    name: FormControl<string>; //申报教材名称
+    title: FormControl<string>; //申报教材名称
     ISBN: FormControl<string>; //国际标准书号
     author: FormControl<string>; //第一主编(作者)
     unit: FormControl<string>; //第一主编(作者)单位
@@ -44,8 +48,8 @@ export class BasicInComponent implements OnInit {
     authors: FormControl<string>; //其他主编姓名
     editor: FormControl<string>; //其他编者姓名
 
-    approval: FormControl<string>; //是否重点立项教材
-    edition: FormControl<string>; //出版单位
+    approval: FormControl<boolean>; //是否为重点立项教材
+    editionUnit: FormControl<string>; //出版单位
     editionFirst: FormControl<Date>; //初版时间
     carrierShape: FormControl<string>; //载体形式
 
@@ -64,19 +68,18 @@ export class BasicInComponent implements OnInit {
 
     // remember: FormControl<boolean>;
   }> = this.fb.group({
-    name: ['', [Validators.required]],
+    title: ['', [Validators.required]],
     ISBN: ['', [Validators.required]],
     author: ['', [Validators.required]],
     unit: ['', [Validators.required]],
     type: ['', [Validators.required]],
-    typeNumber: ['', [Validators.required]],
-
+    typeNumber: [''],
     majorPoniter: ['', [Validators.required]],
     lang: ['', [Validators.required]],
     authors: ['', [Validators.required]],
     editor: ['', [Validators.required]],
-    approval: ['', [Validators.required]],
-    edition: ['', [Validators.required]],
+    approval: [false],
+    editionUnit: ['', [Validators.required]],
     editionFirst: [new Date(), [Validators.required]],
     carrierShape: ['', [Validators.required]],
     editionDate: [new Date(), [Validators.required]],
@@ -85,9 +88,9 @@ export class BasicInComponent implements OnInit {
     printNumber: [0, [Validators.required]],
     printSum: [0, [Validators.required]],
     importantProject: ['', [Validators.required]],
-    importantProjectOther: ['', [Validators.required]],
-    copyrightImgUrl: ['', [Validators.required]],
-    CIPImgUrl: ['', [Validators.required]],
+    importantProjectOther: [''],
+    copyrightImgUrl: ['https://www.jyvtc.edu.cn/yssj/resource/cms/2022/01/2022010610314324023.pdf'],
+    CIPImgUrl: ['https://www.jyvtc.edu.cn/yssj/resource/cms/2022/01/2022010610314324023.pdf'],
     // remember: [true],
   });
   //教材应用对象及所诉学科专业类
@@ -107,21 +110,6 @@ export class BasicInComponent implements OnInit {
   ];
   //语言选择
   selectLang: Array<any> = languages.options;
-  //重点项目选择
-  directorys: Array<any> = [
-    {
-      name: '电气设计原理',
-      code: 'T001',
-    },
-    {
-      name: '微生物学',
-      code: 'T002',
-    },
-    {
-      name: '细胞学',
-      code: 'T003',
-    },
-  ];
   //载体形式
   carrierOptions: Array<any> = [
     {
@@ -159,20 +147,66 @@ export class BasicInComponent implements OnInit {
   //   return this.importantProjectList.some((item:any)=> item.value == this.validateForm.value.importantProject)
   // }
   constructor(
+    public tbookSer: textbookServer,
     private fb: NonNullableFormBuilder,
+    private modal: NzModalService,
     private msg: NzMessageService
-  ) {}
-
-  ngOnInit() {}
+  ) {
+  }
 
-  changeMajor() {}
-  getMajor(e: any) {
-    console.log(e);
+  ngOnInit() {
+    console.log(this.eduTextbook);
+    this.validateForm = this.fb.group({
+      title: [this.eduTextbook?.get('title') || '', [Validators.required]],
+      ISBN: [this.eduTextbook?.get('ISBN') || '', [Validators.required]],
+      author: [this.eduTextbook?.get('author') || '', [Validators.required]],
+      unit: [this.eduTextbook?.get('unit') || '', [Validators.required]],
+      type: [this.eduTextbook?.get('type') || '', [Validators.required]],
+      typeNumber: [this.eduTextbook?.get('typeNumber') || '', [Validators.required]],
+  
+      majorPoniter: [this.eduTextbook?.get('majorPoniter') || '', [Validators.required]],
+      lang: [this.eduTextbook?.get('lang') || '', [Validators.required]],
+      authors: [this.eduTextbook?.get('authors') || '', [Validators.required]],
+      editor: [this.eduTextbook?.get('editor') || '', [Validators.required]],
+      approval: [this.eduTextbook?.get('approval') || false, [Validators.required]],
+      editionUnit: [this.eduTextbook?.get('editionUnit') || '', [Validators.required]],
+      editionFirst: [this.eduTextbook?.get('editionFirst') || new Date(), [Validators.required]],
+      carrierShape: [this.eduTextbook?.get('carrierShape') || '', [Validators.required]],
+      editionDate: [this.eduTextbook?.get('editionDate') || new Date(), [Validators.required]],
+      editionNumber: [this.eduTextbook?.get('editionNumber') || 0, [Validators.required]],
+      printDate: [this.eduTextbook?.get('printDate') || new Date(), [Validators.required]],
+      printNumber: [this.eduTextbook?.get('printNumber') || 0, [Validators.required]],
+      printSum: [this.eduTextbook?.get('printSum') || 0, [Validators.required]],
+      importantProject: [this.eduTextbook?.get('importantProject') || '', [Validators.required]],
+      importantProjectOther: [this.eduTextbook?.get('importantProjectOther') || '', [Validators.required]],
+      copyrightImgUrl: [this.eduTextbook?.get('copyrightImgUrl') || 'https://www.jyvtc.edu.cn/yssj/resource/cms/2022/01/2022010610314324023.pdf', [Validators.required]],
+      CIPImgUrl: [this.eduTextbook?.get('CIPImgUrl') || 'https://www.jyvtc.edu.cn/yssj/resource/cms/2022/01/2022010610314324023.pdf', [Validators.required]],
+      // remember: [true],
+    });
   }
-  onChange(e: any) {
-    console.log(e);
-    console.log(this.validateForm);
+  //校验其他省部级及以上项目是否需填
+  onChangeRadio(){
+    if (this.validateForm.value.importantProject != '其他省部级及以上项目') {
+      this.validateForm.controls.importantProjectOther.clearValidators();
+      this.validateForm.controls.importantProjectOther.markAsPristine();
+    } else {
+      this.validateForm.controls.importantProjectOther.setValidators(Validators.required);
+      this.validateForm.controls.importantProjectOther.markAsDirty();
+    }
+    this.validateForm.controls.importantProjectOther.updateValueAndValidity();
   }
+  //校验全册册数是否需填
+  requiredTypeNumber(e:boolean){
+    if (e) {
+      this.validateForm.controls.typeNumber.clearValidators();
+      this.validateForm.controls.typeNumber.markAsPristine();
+    } else {
+      this.validateForm.controls.typeNumber.setValidators(Validators.required);
+      this.validateForm.controls.typeNumber.markAsDirty();
+    }
+    this.validateForm.controls.typeNumber.updateValueAndValidity();
+  }
+
   handleChange(info: NzUploadChangeParam): void {
     if (info.file.status !== 'uploading') {
       console.log(info.file, info.fileList);
@@ -184,20 +218,113 @@ export class BasicInComponent implements OnInit {
     }
   }
 
-  submitForm(event?: string): void {
+  async submitForm(event?: string): Promise<void> {
     console.log(this.validateForm.value);
     if (this.validateForm.valid) {
-      console.log(this.validateForm.value);
+      // console.log(this.validateForm.value);
+      // let {
+      //   title,
+      //   ISBN,
+      //   author,
+      //   unit,
+      //   type,
+      //   typeNumber,
+      //   majorPoniter,
+      //   lang,
+      //   authors,
+      //   editor,
+      //   approval,
+      //   editionUnit,
+      //   editionFirst,
+      //   carrierShape,
+      //   editionDate,
+      //   editionNumber,
+      //   printDate,
+      //   printNumber,
+      //   printSum,
+      //   importantProject,
+      //   importantProjectOther,
+      //   copyrightImgUrl,
+      //   CIPImgUrl,
+      // } = this.validateForm.value
+      let params = this.validateForm.value
+      if(event == 'next'){
+        await this.saveEduTextbook(params, this.validateForm.valid)
+        this.state.emit({type:'next',textBook:this.eduTextbook});
+      }
     } else {
+      if(event == 'save'){
+        let params = this.validateForm.value
+        await this.saveEduTextbook(params, this.validateForm.valid)
+        this.modal.success({
+          nzTitle: '保存成功',
+          nzContent: '<p>已保存并且至空间</p>',
+          nzOnOk: () => console.log('Info OK')
+        });
+        return
+      }
       Object.values(this.validateForm.controls).forEach((control) => {
         if (control.invalid) {
           control.markAsDirty();
           control.updateValueAndValidity({ onlySelf: true });
         }
       });
+      this.msg.warning('请填写完整的内容')
+      return
+    }
+    if(event == 'save'){
+      let params = this.validateForm.value
+      await this.saveEduTextbook(params, this.validateForm.valid)
+      this.modal.success({
+        nzTitle: '保存成功',
+        nzContent: '<p>已保存并且至空间</p>',
+        nzOnOk: () => console.log('Info OK')
+      });
+    }
+  }
+
+  async saveEduTextbook(params: any, isComplete:boolean){
+    console.log(params);
+    if(!this.eduTextbook){
+      let obj = Parse.Object.extend('EduTextbook');
+      this.eduTextbook = new obj();
     }
-    if (event == 'next') {
-      this.next.emit();
+    //如果填写未完整,仅保存,状态修改待完善101
+    if(this.eduTextbook.get('status') == '102' && !isComplete){
+      this.eduTextbook?.set('status', '101');
+    }else if(!this.eduTextbook.get('status')){
+      this.eduTextbook?.set('status', '101');
     }
+    this.eduTextbook?.set('user', Parse.User.current()?.toPointer());
+    this.eduTextbook?.set('company', {
+      __type: 'Pointer',
+      className: 'Company',
+      objectId: this.tbookSer.company,
+    });
+    this.eduTextbook?.set('title', params.title);
+    this.eduTextbook?.set('ISBN', params.ISBN);
+    this.eduTextbook?.set('author', params.author);
+    this.eduTextbook?.set('unit', params.unit);
+    this.eduTextbook?.set('type', params.type);
+    this.eduTextbook?.set('typeNumber', params.typeNumber);
+    this.eduTextbook?.set('majorPoniter', params.majorPoniter);
+    this.eduTextbook?.set('lang', params.lang);
+    this.eduTextbook?.set('authors', params.authors);
+    this.eduTextbook?.set('editor', params.editor);
+    this.eduTextbook?.set('approval', params.approval);
+    this.eduTextbook?.set('editionUnit', params.editionUnit);
+    this.eduTextbook?.set('editionFirst', params.editionFirst);
+    this.eduTextbook?.set('carrierShape', params.carrierShape);
+    this.eduTextbook?.set('editionDate', params.editionDate);
+    this.eduTextbook?.set('editionNumber', params.editionNumber);
+    this.eduTextbook?.set('printDate', params.printDate);
+    this.eduTextbook?.set('printNumber', params.printNumber);
+    this.eduTextbook?.set('printSum', params.printSum);
+    this.eduTextbook?.set('importantProject', params.importantProject);
+    this.eduTextbook?.set('importantProjectOther', params.importantProjectOther);
+    this.eduTextbook?.set('copyrightImgUrl', params.copyrightImgUrl);
+    this.eduTextbook?.set('CIPImgUrl', params.CIPImgUrl);
+    await this.eduTextbook?.save();
+    return
   }
 }

+ 0 - 0
projects/textbook/src/modules/nav-author/page-textbook/page-textbook.component.html → projects/textbook/src/modules/nav-author/components/page-textbook/page-textbook.component.html


+ 0 - 0
projects/textbook/src/modules/nav-author/page-textbook/page-textbook.component.scss → projects/textbook/src/modules/nav-author/components/page-textbook/page-textbook.component.scss


+ 0 - 0
projects/textbook/src/modules/nav-author/page-textbook/page-textbook.component.spec.ts → projects/textbook/src/modules/nav-author/components/page-textbook/page-textbook.component.spec.ts


+ 5 - 6
projects/textbook/src/modules/nav-author/page-textbook/page-textbook.component.ts → projects/textbook/src/modules/nav-author/components/page-textbook/page-textbook.component.ts

@@ -1,11 +1,10 @@
 import { Component, OnInit, ViewChild } from '@angular/core';
-import { ActivatedRoute, RouterOutlet } from '@angular/router';
-import { CompTableListComponent } from '../../../app/comp-table/comp-table-list/comp-table-list.component';
-import { EduTextbook } from '../../../schemas/EduTextbook';
+import { ActivatedRoute, RouterOutlet, Router } from '@angular/router';
+import { CompTableListComponent } from '../../../../app/comp-table/comp-table-list/comp-table-list.component';
+import { EduTextbook } from '../../../../schemas/EduTextbook';
 // import { TranslateService } from '@ngx-translate/core';
 import * as Parse from "parse";
 import { CommonModule } from '@angular/common';
-
 @Component({
   selector: 'app-page-textbook',
   templateUrl: './page-textbook.component.html',
@@ -13,7 +12,7 @@ import { CommonModule } from '@angular/common';
   imports: [CommonModule,RouterOutlet,CompTableListComponent],
   standalone: true,
 })
-export class PageTextbookComponent  implements OnInit {
+export class PageTextbookComponent implements OnInit {
   @ViewChild(CompTableListComponent) list:CompTableListComponent|undefined
 
   EduTextbook = EduTextbook
@@ -23,7 +22,7 @@ export class PageTextbookComponent  implements OnInit {
   fieldsArray:Array<any>|undefined
 
   constructor(
-    private route: ActivatedRoute,
+    private router: Router,
     private activeRoute: ActivatedRoute,
     // private translate:TranslateService,
   ) {

+ 2 - 2
projects/textbook/src/modules/nav-author/components/textbook-content/textbook-content.component.html

@@ -13,7 +13,7 @@
       >
         <thead>
           <tr>
-            <th nzWidth="80px" nzLeft nzAlign="right">序号</th>
+            <th nzWidth="80px" nzLeft nzAlign="right">版次</th>
             <th nzWidth="120px">出版时间</th>
             <th nzWidth="100px">字数</th>
             <th nzWidth="100px">重印次数</th>
@@ -170,7 +170,7 @@
   >
     上一页
   </button>
-  <button nz-button nzType="primary" (click)="submitForm('next')">
+  <button nz-button style="background: #3e49b3; border: 1px #3e49b3" nzType="primary" (click)="submitForm('next')">
     下一页
   </button>
 </div>

+ 15 - 3
projects/textbook/src/modules/nav-author/components/textbook-content/textbook-content.component.ts

@@ -7,6 +7,8 @@ import { NzMessageService } from 'ng-zorro-antd/message';
 import { NzGridModule } from 'ng-zorro-antd/grid';
 import { NzCheckboxModule } from 'ng-zorro-antd/checkbox';
 import { NzTableModule } from 'ng-zorro-antd/table';
+import { NzModalService } from 'ng-zorro-antd/modal';
+import Parse from 'parse';
 import {
   FormControl,
   FormGroup,
@@ -37,9 +39,9 @@ interface course {
   styleUrls: ['./textbook-content.component.scss'],
 })
 export class TextbookContentComponent  implements OnInit {
-  @Input('editFrom') editFrom: any;
+  @Input('eduTextbook') editFrom: any;
   @Input('maxWidth') maxWidth: number = 0;
-  @Output() next: EventEmitter<any> = new EventEmitter<any>();
+  @Output() state: EventEmitter<any> = new EventEmitter<any>();
   @Output() save: EventEmitter<any> = new EventEmitter<any>();
   validateForm: FormGroup<{
     innovateExplain: FormControl<string>; //申报教材特色及创新
@@ -60,6 +62,7 @@ export class TextbookContentComponent  implements OnInit {
   ];
   constructor(
     private fb: NonNullableFormBuilder,
+    private modal: NzModalService,
     private msg: NzMessageService
   ) { }
 
@@ -77,9 +80,18 @@ export class TextbookContentComponent  implements OnInit {
       });
       this.msg.warning('请填写完整信息');
     }
+    if (event == 'pre') {
+      this.state.emit('pre');
+    }
     if (event == 'next') {
-      this.next.emit();
+      this.state.emit('next');
     }
+    if(event == 'complete')
+    this.modal.success({
+      nzTitle: '您已填写完成',
+      nzContent: '<p>已保存并且至空间</p>',
+      nzOnOk: () => console.log('Info OK')
+    });
   }
   changeCode() {}
   getCode(e: any) {}

+ 10 - 11
projects/textbook/src/modules/nav-author/components/textbook-pertain/textbook-pertain.component.html

@@ -10,11 +10,11 @@
         <div nz-col nzSpan="12">
           <nz-form-item class="row" style="margin-bottom: 16px">
             <nz-form-label class="label" [nzNoColon]="true" [nzSm]="10" [nzXs]="10" nzRequired
-              >适用专业代码(六位)及名称</nz-form-label
+              >适用专业代码(六位)及名称</nz-form-label
             >
             <nz-form-control
               class="val"
-              nzErrorTip="填写适用专业代码(六位)及名称"
+              nzErrorTip="适用专业代码(六位)及名称"
               style="width: 100%"
             >
               <nz-select
@@ -22,7 +22,7 @@
                 nzShowSearch
                 nzAllowClear
                 nzPlaceHolder="填写 6 位专业代码选择"
-                formControlName="code"
+                formControlName="major"
                 (ngModelChange)="changeCode()"
                 (nzOnSearch)="getCode($event)"
               >
@@ -102,7 +102,7 @@
       <div class="title">作者(含主编,不超过 6 人,教材中明确出现姓名)</div>
       <nz-table
         #basicTable
-        [nzData]="dataArr"
+        [nzData]="authorList"
         [nzScroll]="{ x: (maxWidth || '1200') + 'px' }"
       >
         <thead>
@@ -121,7 +121,7 @@
           </tr>
         </thead>
         <tbody>
-          @for (data of dataArr; track data.mobile;let index = $index) {
+          @for (data of authorList; track data.mobile;let index = $index) {
           <tr>
             <td nzLeft nzAlign="right">{{ index + 1 }}</td>
             <td nzLeft>
@@ -212,7 +212,7 @@
               </nz-select>
             </td>
             <td nzRight>
-              <a (click)="onPush('dataArr', index)"
+              <a (click)="onPush('authorList', index)"
                 ><span
                   nz-icon
                   style="font-size: 20px; margin-right: 10px"
@@ -220,7 +220,7 @@
                   nzTheme="outline"
                 ></span
               ></a>
-              <a (click)="onDel('dataArr',index)"
+              <a (click)="onDel('authorList',index)"
                 ><span
                   nz-icon
                   style="font-size: 20px"
@@ -235,10 +235,9 @@
       </nz-table>
     </div>
     <div class="author-content">
-      <div class="nav">作者信息</div>
+      <div class="nav">第一主编(作者)情况</div>
       <nz-form-item class="row" style="margin-bottom: 16px">
-        <div class="title">作者信息</div>
-
+        <div class="title">相关教学经历</div>
         <nz-form-control
           class="val"
           nzErrorTip="请输入第一主编(作者)承担学校教学任务、开展教学研究情况、教材编写情况以及取得的教学成果"
@@ -340,7 +339,7 @@
   >
     上一页
   </button>
-  <button nz-button nzType="primary" (click)="submitForm('next')">
+  <button nz-button nzType="primary" style="background: #3e49b3; border: 1px #3e49b3" (click)="submitForm('next')">
     下一页
   </button>
 </div>

+ 95 - 21
projects/textbook/src/modules/nav-author/components/textbook-pertain/textbook-pertain.component.ts

@@ -7,12 +7,15 @@ import { NzMessageService } from 'ng-zorro-antd/message';
 import { NzGridModule } from 'ng-zorro-antd/grid';
 import { NzCheckboxModule } from 'ng-zorro-antd/checkbox';
 import { NzTableModule } from 'ng-zorro-antd/table';
+import { NzModalService } from 'ng-zorro-antd/modal';
+import Parse from 'parse';
 import {
   FormControl,
   FormGroup,
   NonNullableFormBuilder,
   Validators,
 } from '@angular/forms';
+import { textbookServer } from '../../../../services/textbook';
 interface author {
   name: string;
   unit: string;
@@ -45,27 +48,26 @@ interface achievementType {
   styleUrls: ['./textbook-pertain.component.scss'],
 })
 export class TextbookPertainComponent implements OnInit {
-  @Input('editFrom') editFrom: any;
+  @Input('eduTextbook') eduTextbook: Parse.Object|any;
+
   @Input('maxWidth') maxWidth: number = 0;
-  @Output() next: EventEmitter<any> = new EventEmitter<any>();
+  @Output() state: EventEmitter<any> = new EventEmitter<any>();
   @Output() save: EventEmitter<any> = new EventEmitter<any>();
   validateForm: FormGroup<{
-    code: FormControl<string>; //适用专业代码及名称
+    major: FormControl<string>; //适用专业代码及名称
     period: FormControl<number | any>; //课程学时
     lessons: FormControl<string>; //适用课程
     characteristic: FormControl<Array<any> | any>; //适用课程性质
-    // authors: FormControl<Array<any> | any>; //作者信息
-    authorDetails: FormControl<string>; //第一主编(作者)情况
-    type: FormControl<string>; //申报类型
+    // authorList: FormControl<Array<any> | any>; //作者信息
+    authorDetails: FormControl<string>; //第一主编(作者)相关教学经历
     // achievement: FormControl<Array<any> | any>; //相关科学研究项目、成果或论文专著(限5项)
   }> = this.fb.group({
-    code: ['', [Validators.required]],
+    major: ['', [Validators.required]],
     period: ['', [Validators.required]],
     lessons: ['', [Validators.required]],
     characteristic: ['', [Validators.required]],
-    // authors: ['', [Validators.required]],
+    // authorList: ['', [Validators.required]],
     authorDetails: ['', [Validators.required]],
-    type: ['', [Validators.required]],
     // achievement: ['', [Validators.required]],
   });
   //适用专业代码及名称
@@ -103,7 +105,7 @@ export class TextbookPertainComponent implements OnInit {
   //   { label: '实验课', value: '实验课' },
   // ];
   //作者信息
-  dataArr: Array<author> = [
+  authorList: Array<author> = [
     {
       name: '',
       unit: '',
@@ -126,16 +128,50 @@ export class TextbookPertainComponent implements OnInit {
   ];
   workOptions = ['主编', '作者', '副主编', '写者'];
   constructor(
+    public tbookSer: textbookServer,
     private fb: NonNullableFormBuilder,
+    private modal: NzModalService,
     private msg: NzMessageService
   ) {}
 
-  ngOnInit() {}
-  submitForm(event?: string): void {
+  ngOnInit() {
+    console.log(this.eduTextbook);
+    if(this.eduTextbook.id){
+      this.checkOptionsOne = this.eduTextbook.get('characteristic') || this.checkOptionsOne
+      let major = this.selectList.find(item=> item.code == this.eduTextbook.get('major')?.code)
+      let lessons = this.eduTextbook.get('lessons')?.join(';')
+      this.validateForm = this.fb.group({
+        major: [major?.code || '', [Validators.required]],
+        period: [this.eduTextbook.get('period') || '', [Validators.required]],
+        lessons: [lessons || '', [Validators.required]],
+        characteristic: [this.eduTextbook.get('characteristic') || '', [Validators.required]],
+        authorDetails: [this.eduTextbook.get('authorDetails') || '', [Validators.required]],
+      });
+    }
+
+  }
+  async submitForm(event?: string):Promise<void>{
     console.log(this.validateForm.value);
     if (this.validateForm.valid) {
-      console.log(this.validateForm.value);
+      let params = this.validateForm.value
+      if (event == 'next') {
+        await this.saveEduTextbook(params, this.validateForm.valid)
+        this.state.emit({type:'next',textBook:this.eduTextbook});
+      }
     } else {
+      if(event == 'pre'){
+        this.state.emit({type:'pre'});
+      }
+      else if(event == 'save'){
+        let params = this.validateForm.value
+        await this.saveEduTextbook(params, this.validateForm.valid)
+        this.modal.success({
+          nzTitle: '保存成功',
+          nzContent: '<p>已保存并且至空间</p>',
+          nzOnOk: () => console.log('Info OK')
+        });
+        return
+      }
       Object.values(this.validateForm.controls).forEach((control) => {
         if (control.invalid) {
           control.markAsDirty();
@@ -144,8 +180,14 @@ export class TextbookPertainComponent implements OnInit {
       });
       this.msg.warning('请填写完整信息');
     }
-    if (event == 'next') {
-      this.next.emit();
+    if(event == 'save'){
+      let params = this.validateForm.value
+      await this.saveEduTextbook(params, this.validateForm.valid)
+      this.modal.success({
+        nzTitle: '保存成功',
+        nzContent: '<p>已保存并且至空间</p>',
+        nzOnOk: () => console.log('Info OK')
+      });
     }
   }
   changeCode() {}
@@ -154,8 +196,8 @@ export class TextbookPertainComponent implements OnInit {
   //添加作者信息
   onPush(type: string, idx: number) {
     switch (type) {
-      case 'dataArr':
-        this.dataArr.splice(idx+1, 0, {
+      case 'authorList':
+        this.authorList.splice(idx+1, 0, {
           name: '',
           unit: '',
           birth: '',
@@ -183,9 +225,9 @@ export class TextbookPertainComponent implements OnInit {
   //删除作者信息
   onDel(type: string, idx: number) {
     switch (type) {
-      case 'dataArr':
-        if (this.dataArr.length == 1) {
-          this.dataArr = [
+      case 'authorList':
+        if (this.authorList.length == 1) {
+          this.authorList = [
             {
               name: '',
               unit: '',
@@ -200,7 +242,7 @@ export class TextbookPertainComponent implements OnInit {
           ];
           return;
         }
-        this.dataArr.splice(idx, 1);
+        this.authorList.splice(idx, 1);
         break;
       case 'achievementOptions':
         if (this.achievementOptions.length == 1) {
@@ -217,4 +259,36 @@ export class TextbookPertainComponent implements OnInit {
         break;
     }
   }
+
+  async saveEduTextbook(params: any, isComplete:boolean){
+    console.log(params);
+    if(!this.eduTextbook){
+      this.msg.error('请先创建教材')
+      return
+      // let obj = Parse.Object.extend('EduTextbook');
+      // this.eduTextbook = new obj();
+    }
+    //如果填写未完整,仅保存,状态修改待完善101
+    if(this.eduTextbook.get('status') == '102' && !isComplete){
+      this.eduTextbook?.set('status', '101');
+    }else if(!this.eduTextbook.get('status')){
+      this.eduTextbook?.set('status', '101');
+    }
+    this.eduTextbook?.set('user', Parse.User.current()?.toPointer());
+    this.eduTextbook?.set('company', {
+      __type: 'Pointer',
+      className: 'Company',
+      objectId: this.tbookSer.company,
+    });
+    let major = this.selectList.find(item=> item.code == params.major)
+    let lessons = params.lessons.split(';')
+    this.eduTextbook?.set('major', major);
+    params.period && this.eduTextbook?.set('period', params.period);
+    params.period && this.eduTextbook?.set('lessons', lessons);
+    this.eduTextbook?.set('characteristic', params.characteristic);
+    this.eduTextbook?.set('authorDetails', params.authorDetails);
+
+    await this.eduTextbook?.save();
+    return
+  }
 }

+ 17 - 12
projects/textbook/src/modules/nav-author/modules.routes.ts

@@ -1,37 +1,42 @@
 import { NgModule } from '@angular/core';
 import { RouterModule, Routes } from '@angular/router';
-import { PageHomeComponent } from './page-home/page-home.component';
-import { PageTextbookComponent } from './page-textbook/page-textbook.component';
+import { PageTextbookComponent } from './components/page-textbook/page-textbook.component';
 import { ApplyComponent } from './apply/apply.component';
-import { ProfileComponent } from '../user/profile/profile.component';
+// import { ProfileComponent } from '../user/profile/profile.component';
+import { SpaceComponent } from './space/space.component'
+import { TextbookDetailsComponent } from './textbook-details/textbook-details.component'
+import { RecycleComponent } from './recycle/recycle.component'
 const routes: Routes = [
   {
     path: '',
-    redirectTo:'manage/apply',
+    redirectTo:'manage/space',
     pathMatch: "full",
   },
   {
     path: 'manage',
-    component: PageHomeComponent,
     children: [
+      {
+        path: 'space',//创建教材
+        component: SpaceComponent,
+      },
       {
         path: 'apply',//创建教材
         component: ApplyComponent,
       },
       {
-        path: 'textbook',//列表
-        component: PageTextbookComponent,
+        path: 'dateils',//创建教材
+        component: TextbookDetailsComponent,
       },
+      // {
+      //   path: 'textbook',//列表
+      //   component: PageTextbookComponent,
+      // },
       {
         path: 'recycle',//回收站
-        component: PageTextbookComponent,
+        component: RecycleComponent,
       },
     ],
   },
-  {
-    path: 'profile',
-    component: ProfileComponent,
-  },
 ];
 @NgModule({
   imports: [RouterModule.forChild(routes)],

+ 0 - 35
projects/textbook/src/modules/nav-author/page-home/page-home.component.html

@@ -1,35 +0,0 @@
-<app-comp-nav></app-comp-nav>
-<div class="page">
-  <div class="content-left">
-    <ul nz-menu nzMode="inline" style="width: 240px;background: #f9eaea;">
-      @for (item of options; track item.id;let index = $index) { @if(item.child)
-      {
-      <li nz-submenu [nzTitle]="item.name" nzIcon="api" [nzOpen]="true">
-        <ul>
-          @for (child of item.child; track child.id;let idx = $index) {
-          <li
-            nz-menu-item
-            [nzSelected]="active == child.id"
-            (click)="toUrl(child)"
-          >
-            {{ child.name }}
-          </li>
-          }
-        </ul>
-      </li>
-      } @else {
-      <li
-        nz-menu-item
-        (click)="toUrl(item)"
-        [nzSelected]="active == item.id"
-      >
-        <span nz-icon nzType="home" nzTheme="outline"></span>
-        <span>{{ item.name }}</span>
-      </li>
-      } }
-    </ul>
-  </div>
-  <div class="preview">
-    <router-outlet></router-outlet>
-  </div>
-</div>

+ 0 - 71
projects/textbook/src/modules/nav-author/page-home/page-home.component.ts

@@ -1,71 +0,0 @@
-import { Component, OnInit } from '@angular/core';
-import { CompNavComponent } from '../../../app/comp-nav/comp-nav.component';
-import { RouterOutlet, Router } from '@angular/router';
-import { CommonCompModule } from '../../../services/common.modules';
-
-@Component({
-  selector: 'app-page-home',
-  standalone: true,
-  imports: [CompNavComponent, RouterOutlet, CommonCompModule],
-  templateUrl: './page-home.component.html',
-  styleUrls: ['./page-home.component.scss'],
-})
-export class PageHomeComponent implements OnInit {
-  options: Array<any> = [
-    // {
-    //   name:'教材管理',
-    //   id:'5',
-    //   child:[
-    //     {
-    //       name:'教材列表',
-    //       id:'1-1',
-    //       path:"/nav-author/textbook/list"
-    //     }
-    //   ]
-    // },
-    {
-      name: '个人空间',
-      id: '1',
-      child: [
-        {
-          name: '创建教材',
-          id: '1-1',
-          path: '/nav-author/manage/apply',
-        },
-        {
-          name: '教材列表',
-          id: '1-2',
-          path: '/nav-author/manage/textbook',
-        },
-      ],
-    },
-    {
-      name: '回收站',
-      id: '2',
-      path: '/nav-author/manage/textbook',
-      params: {
-        isDeleted: true,
-      },
-    },
-    {
-      name: '个人信息',
-      id: '3',
-      path: '/nav-author/profile',
-    },
-  ];
-  active: string = localStorage.getItem('active') || this.options[0].id;
-  constructor(public router: Router) {}
-
-  ngOnInit() {}
-  toUrl(child: any) {
-    let cateid = child.id;
-    this.active = cateid;
-    localStorage.setItem('active', cateid);
-    console.log(child);
-    if (child.params) {
-      this.router.navigate([child.path, child?.params]);
-    } else {
-      this.router.navigate([child.path]);
-    }
-  }
-}

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

@@ -0,0 +1,17 @@
+<div class="space-page">
+  <div class="space-head">
+    <div class="content">
+      <div class="title">
+        回收站
+      </div>
+      <div class="text">
+        在此查看已删除教材,将需要重新编辑的教材恢复至个人空间
+      </div>
+    </div>
+    <div class="btn">
+    </div>
+  </div>
+  <div class="space-content">
+    <app-page-textbook></app-page-textbook>
+  </div>
+</div>

+ 41 - 0
projects/textbook/src/modules/nav-author/recycle/recycle.component.scss

@@ -0,0 +1,41 @@
+.space-page {
+  padding: 20px;
+  font-family: PingFang SC;
+  .space-head {
+    display: flex;
+    justify-content: space-between;
+    .content {
+      .title {
+        //styleName: 字体/标题-大-Medium;
+        font-family: PingFang SC;
+        font-size: 24px;
+        font-weight: 500;
+        line-height: 38px;
+        text-align: left;
+      }
+      .text {
+        font-family: PingFang SC;
+        font-size: 14px;
+        font-weight: 400;
+        line-height: 22px;
+        text-align: left;
+        color: #231C1F99;
+      }
+    }
+  }
+  .space-content{
+    margin: 20px 0;
+  }
+}
+::ng-deep .ant-tabs-tab.ant-tabs-tab-active .ant-tabs-tab-btn{
+  color: #c6233f;
+}
+::ng-deep .ant-tabs-ink-bar{
+  background: #c6233f;
+}
+::ng-deep .ant-tabs-tab:hover{
+  color: #e97488;
+}
+::ng-deep .ant-tabs-tab-btn:active{
+  color: #e97488;
+}

+ 6 - 6
projects/textbook/src/modules/nav-province-contact/page-home/page-home.component.spec.ts → projects/textbook/src/modules/nav-author/recycle/recycle.component.spec.ts

@@ -1,19 +1,19 @@
 import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
 import { IonicModule } from '@ionic/angular';
 
-import { PageHomeComponent } from './page-home.component';
+import { RecycleComponent } from './recycle.component';
 
-describe('PageHomeComponent', () => {
-  let component: PageHomeComponent;
-  let fixture: ComponentFixture<PageHomeComponent>;
+describe('RecycleComponent', () => {
+  let component: RecycleComponent;
+  let fixture: ComponentFixture<RecycleComponent>;
 
   beforeEach(waitForAsync(() => {
     TestBed.configureTestingModule({
-      declarations: [ PageHomeComponent ],
+      declarations: [ RecycleComponent ],
       imports: [IonicModule.forRoot()]
     }).compileComponents();
 
-    fixture = TestBed.createComponent(PageHomeComponent);
+    fixture = TestBed.createComponent(RecycleComponent);
     component = fixture.componentInstance;
     fixture.detectChanges();
   }));

+ 30 - 0
projects/textbook/src/modules/nav-author/recycle/recycle.component.ts

@@ -0,0 +1,30 @@
+import { Component, OnInit } from '@angular/core';
+import { CommonCompModule } from '../../../services/common.modules';
+import { Router } from '@angular/router';
+import * as Parse from 'parse';
+import { PageTextbookComponent } from '../components/page-textbook/page-textbook.component';
+
+@Component({
+  selector: 'app-recycle',
+  standalone: true,
+  imports: [CommonCompModule,PageTextbookComponent],
+  templateUrl: './recycle.component.html',
+  styleUrls: ['./recycle.component.scss'],
+})
+export class RecycleComponent  implements OnInit {
+
+  user: Parse.Object = Parse.User.current()!;
+
+  constructor(private router: Router) {}
+
+  ngOnInit() {}
+
+  goUrl(url:string,params?:object|any){
+    console.log(url);
+    if(params){
+      this.router.navigate([url,params])
+    }else{
+      this.router.navigate([url])
+    }
+  }
+}

+ 32 - 0
projects/textbook/src/modules/nav-author/space/space.component.html

@@ -0,0 +1,32 @@
+<div class="space-page">
+  <div class="space-head">
+    <div class="content">
+      <div class="title">
+        {{ user?.get("name") || "彭秀龙" }},欢迎使用教材遴选提交系统
+      </div>
+      <div class="text">
+        创建教材、使用教材网信息加快填写速度,下载附件材料、上传教材所需文件,将你创建的教材提交至流程上级评审
+      </div>
+    </div>
+    <div class="btn">
+      <button
+        nz-button
+        nzType="primary"
+        style="background: #3e49b3; border: 1px #3e49b3"
+        (click)="goUrl('/nav-author/manage/apply')"
+      >
+        创建教材
+      </button>
+    </div>
+  </div>
+  <div class="space-content">
+    <nz-tabset>
+      <nz-tab nzTitle="我的教材">
+        <app-page-textbook></app-page-textbook>
+      </nz-tab>
+      <nz-tab nzTitle="已提交评审教材">
+        <app-page-textbook></app-page-textbook>
+      </nz-tab>
+    </nz-tabset>
+  </div>
+</div>

+ 41 - 0
projects/textbook/src/modules/nav-author/space/space.component.scss

@@ -0,0 +1,41 @@
+.space-page {
+  padding: 20px;
+  font-family: PingFang SC;
+  .space-head {
+    display: flex;
+    justify-content: space-between;
+    .content {
+      .title {
+        //styleName: 字体/标题-大-Medium;
+        font-family: PingFang SC;
+        font-size: 24px;
+        font-weight: 500;
+        line-height: 38px;
+        text-align: left;
+      }
+      .text {
+        font-family: PingFang SC;
+        font-size: 14px;
+        font-weight: 400;
+        line-height: 22px;
+        text-align: left;
+        color: #231C1F99;
+      }
+    }
+  }
+  .space-content{
+    margin: 20px 0;
+  }
+}
+::ng-deep .ant-tabs-tab.ant-tabs-tab-active .ant-tabs-tab-btn{
+  color: #c6233f;
+}
+::ng-deep .ant-tabs-ink-bar{
+  background: #c6233f;
+}
+::ng-deep .ant-tabs-tab:hover{
+  color: #e97488;
+}
+::ng-deep .ant-tabs-tab-btn:active{
+  color: #e97488;
+}

+ 6 - 6
projects/textbook/src/modules/nav-author/page-home/page-home.component.spec.ts → projects/textbook/src/modules/nav-author/space/space.component.spec.ts

@@ -1,19 +1,19 @@
 import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
 import { IonicModule } from '@ionic/angular';
 
-import { PageHomeComponent } from './page-home.component';
+import { SpaceComponent } from './space.component';
 
-describe('PageHomeComponent', () => {
-  let component: PageHomeComponent;
-  let fixture: ComponentFixture<PageHomeComponent>;
+describe('SpaceComponent', () => {
+  let component: SpaceComponent;
+  let fixture: ComponentFixture<SpaceComponent>;
 
   beforeEach(waitForAsync(() => {
     TestBed.configureTestingModule({
-      declarations: [ PageHomeComponent ],
+      declarations: [ SpaceComponent ],
       imports: [IonicModule.forRoot()]
     }).compileComponents();
 
-    fixture = TestBed.createComponent(PageHomeComponent);
+    fixture = TestBed.createComponent(SpaceComponent);
     component = fixture.componentInstance;
     fixture.detectChanges();
   }));

+ 29 - 0
projects/textbook/src/modules/nav-author/space/space.component.ts

@@ -0,0 +1,29 @@
+import { Component, OnInit } from '@angular/core';
+import { CommonCompModule } from '../../../services/common.modules';
+import { Router } from '@angular/router';
+import * as Parse from 'parse';
+import { NzTabsModule } from 'ng-zorro-antd/tabs';
+import { PageTextbookComponent } from '../components/page-textbook/page-textbook.component';
+@Component({
+  selector: 'app-space',
+  standalone: true,
+  imports: [CommonCompModule, NzTabsModule, PageTextbookComponent],
+  templateUrl: './space.component.html',
+  styleUrls: ['./space.component.scss'],
+})
+export class SpaceComponent implements OnInit {
+  user: Parse.Object = Parse.User.current()!;
+
+  constructor(private router: Router) {}
+
+  ngOnInit() {}
+
+  goUrl(url:string,params?:object|any){
+    console.log(url);
+    if(params){
+      this.router.navigate([url,params])
+    }else{
+      this.router.navigate([url])
+    }
+  }
+}

+ 497 - 0
projects/textbook/src/modules/nav-author/textbook-details/textbook-details.component.html

@@ -0,0 +1,497 @@
+<div class="site-page-header">
+  <nz-page-header
+    nzTitle="教材详情 - {{textBook.type}}"
+    nzSubtitle=""
+    style="padding: 0"
+  >
+    <nz-breadcrumb nz-page-header-breadcrumb>
+      <div class="back" (click)="back()">
+        <span nz-icon nzType="left" nzTheme="outline"></span>返回
+      </div>
+    </nz-breadcrumb>
+  </nz-page-header>
+</div>
+<div class="content">
+  <div nz-row>
+    <div nz-col nzSpan="18" #scroll>
+      <div class="templ1" #templ1 style="width: 500px; height: 700px">
+        <div class="title">教材基本信息</div>
+        <div class="base-content">
+          <div class="row">
+            <div class="label">申报教材名称</div>
+            <div class="value">{{textBook.title}}</div>
+          </div>
+          <div class="row">
+            <div class="label">第一主编(作者)</div>
+            <div class="value">{{textBook.author}}</div>
+          </div>
+          <div class="row">
+            <div class="label">第一主编(作者)单位</div>
+            <div class="value">{{textBook.unit}}</div>
+          </div>
+          <div class="row">
+            <div class="label">申报类型</div>
+            <div class="value">{{textBook.type}}</div>
+          </div>
+          <div class="row">
+            <div class="label">教材应用对象及所属学科专业类</div>
+            <div class="value">{{textBook.majorPoniter}}</div>
+          </div>
+          <div class="row">
+            <div class="label">教材主要语种类型</div>
+            <div class="value">{{textBook.lang}}</div>
+          </div>
+          <div class="row">
+            <div class="label">国际标准书号</div>
+            <div class="value">{{textBook.ISBN}}</div>
+          </div>
+          <div class="row">
+            <div class="label">其他主编姓名</div>
+            <div class="value">{{textBook.authors}}</div>
+          </div>
+          <div class="row">
+            <div class="label">其他编者姓名</div>
+            <div class="value">{{textBook.editor}}</div>
+          </div>
+          <div class="row">
+            <div class="label">是否为重点立项教材</div>
+            <div class="value">{{textBook.approval}}</div>
+          </div>
+          <div class="row">
+            <div class="label">出版单位</div>
+            <div class="value">{{textBook.editionUnit}}</div>
+          </div>
+          <div class="row">
+            <div class="label">初版时间</div>
+            <div class="value">{{textBook.editionFirst | date :'yyyy-MM'}}</div>
+          </div>
+          <div class="row">
+            <div class="label">载体形式</div>
+            <div class="value">{{textBook.carrierShape}}</div>
+          </div>
+          <div class="row">
+            <div class="label">本版出版时间及版次</div>
+            <div class="value">{{textBook.editionDate | date :'yyyy-MM'}}/{{textBook.editionNumber}}</div>
+          </div>
+          <div class="row">
+            <div class="label">最新印次时间及印次</div>
+            <div class="value">{{textBook.printDate | date :'yyyy-MM'}}/{{textBook.printNumber}}</div>
+          </div>
+          <div class="row">
+            <div class="label">初版以来合计印数</div>
+            <div class="value">{{textBook.printSum}}</div>
+          </div>
+          <div class="row">
+            <div class="label">初版以来是否曾列为重点项目</div>
+            <div class="value">{{textBook.importantProject}}</div>
+          </div>
+          <div class="row">
+            <div class="label">版权页截图</div>
+            <div class="value">{{textBook.copyrightImgUrl}}</div>
+          </div>
+          <div class="row">
+            <div class="label">中国版本图书馆 CIP 查询截图</div>
+            <div class="value">{{textBook.CIPImgUrl}}</div>
+          </div>
+        </div>
+      </div>
+      <div class="templ">
+        <div class="title">教材适用情况</div>
+        <div class="base-content">
+          <div class="row">
+            <div class="label">适用专业代码(六位)及名称</div>
+            <div class="value">{{textBook.major.code}}/{{textBook.major.name}}</div>
+          </div>
+          <div class="row">
+            <div class="label">适用课程</div>
+            <div class="value">{{textBook.lessons}}</div>
+          </div>
+          <div class="row">
+            <div class="label">课程学时</div>
+            <div class="value">{{textBook.period}}</div>
+          </div>
+          <div class="row">
+            <div class="label">适用课程性质</div>
+            <div class="value">{{textBook.characteristic}}</div>
+          </div>
+        </div>
+      </div>
+      <div class="templ">
+        <div class="title">教材适用情况</div>
+        <div class="text mar10">
+          作者(含主编,不超过 6 人,教材中明确出现姓名)
+        </div>
+        <div class="base-content">
+          <nz-table
+            #basicTable
+            [nzShowPagination]="false"
+            [nzData]="textBook.authorList"
+            [nzScroll]="{
+              x: (templ1.style.width || '1000') + 'px',
+              y: '240px'
+            }"
+          >
+            <thead>
+              <tr>
+                <th nzWidth="160px" nzLeft>姓名</th>
+                <th nzWidth="160px">单位</th>
+                <th nzWidth="160px">出生年月</th>
+                <th nzWidth="160px">国籍</th>
+                <th nzWidth="160px">职务</th>
+                <th nzWidth="160px">职称</th>
+                <th nzWidth="160px">手机号码</th>
+                <th nzWidth="160px">电子邮箱</th>
+                <th nzWidth="160px" nzRight>分工</th>
+              </tr>
+            </thead>
+            <tbody>
+              @for (data of textBook.authorList; track data.mobile;let index =
+              $index) {
+              <tr>
+                <td nzLeft>
+                  {{ data.name }}
+                </td>
+                <td>
+                  {{ data.unit }}
+                </td>
+                <td>
+                  {{ data.birth | date : "yyyy-MM" }}
+                </td>
+                <td>
+                  {{ data.nationality }}
+                </td>
+                <td>
+                  {{ data.job }}
+                </td>
+                <td>
+                  {{ data.title }}
+                </td>
+                <td>
+                  {{ data.mobile }}
+                </td>
+                <td>
+                  {{ data.email }}
+                </td>
+                <td nzRight>
+                  {{ data.work }}
+                </td>
+              </tr>
+              }
+            </tbody>
+          </nz-table>
+        </div>
+
+        <div class="text mar10">第一主编(作者)情况</div>
+        <div class="base-content">
+          <div class="text-tips">相关教学经历</div>
+          <div class="note">
+            {{ textBook.authorDetails }}
+          </div>
+          <div class="text-tips">相关科学研究项目、成果或论文专著(限5项)</div>
+          <nz-table
+            #basicTable
+            [nzShowPagination]="false"
+            [nzData]="textBook.achievementOptions"
+            [nzScroll]="{
+              x: (templ1.style.width || '1000') + 'px',
+              y: '240px'
+            }"
+          >
+            <thead>
+              <tr>
+                <th nzWidth="80px" nzLeft nzAlign="right">序号</th>
+                <th nzWidth="160px" nzLeft>名称</th>
+                <th nzWidth="160px">来源/出版单位</th>
+                <th nzWidth="80px">时间</th>
+              </tr>
+            </thead>
+            <tbody>
+              @for (data of textBook.achievementOptions; track data.name;let
+              index = $index) {
+              <tr>
+                <td nzLeft nzAlign="right">{{ index + 1 }}</td>
+                <td nzLeft>
+                  {{ data.name }}
+                </td>
+                <td>
+                  {{ data.unit }}
+                </td>
+                <td>
+                  {{ data.date | date : "yyyy-MM" }}
+                </td>
+              </tr>
+              }
+            </tbody>
+          </nz-table>
+        </div>
+      </div>
+      <div class="templ">
+        <div class="title">申报教材建设历程</div>
+        <div class="base-content">
+          <nz-table
+            #basicTable
+            [nzShowPagination]="false"
+            [nzData]="textBook.courses"
+            [nzScroll]="{
+              x: (templ1.style.width || '1000') + 'px',
+              y: '240px'
+            }"
+          >
+            <thead>
+              <tr>
+                <th nzWidth="80px" nzLeft nzAlign="right">版次</th>
+                <th nzWidth="120px">出版时间</th>
+                <th nzWidth="100px">字数</th>
+                <th nzWidth="100px">重印次数</th>
+                <th nzWidth="100px">本版总印数</th>
+                <th nzWidth="200px">获奖励情况</th>
+              </tr>
+            </thead>
+            <tbody>
+              @for (data of textBook.courses; track data;let index = $index) {
+              <tr>
+                <td nzLeft nzAlign="right">{{ index + 1 }}</td>
+                <td>
+                  {{ data.date | date : "yyyy-MM" }}
+                </td>
+                <td>
+                  {{ data.wordage }}
+                </td>
+                <td>
+                  {{ data.num }}
+                </td>
+                <td>
+                  {{ data.sumNum }}
+                </td>
+                <td>
+                  {{ data.accolade }}
+                </td>
+              </tr>
+              }
+            </tbody>
+          </nz-table>
+        </div>
+      </div>
+      <div class="templ">
+        <div class="title">申报教材特色及创新</div>
+        <div class="base-content">
+          <div class="note">
+            {{ textBook.innovateExplain }}
+          </div>
+        </div>
+      </div>
+      <div class="templ">
+        <div class="title">申报教材应用情况及社会影响力</div>
+        <div class="base-content">
+          <div class="note">
+            {{ textBook.influence }}
+          </div>
+        </div>
+      </div>
+      <div class="templ">
+        <div class="title">附件材料</div>
+        <div class="base-content">
+          <div class="row">
+            <div class="label">教材电子版</div>
+            <div class="value">
+              @for (item of textBook.textbookFiles; track item.name) {
+              <a style="margin-right: 10px" [href]="item.url">{{
+                item.name
+              }}</a>
+              }
+            </div>
+          </div>
+          <div class="row">
+            <div class="label">教材数字内容链接地址、账号</div>
+            <div class="value">
+              @for (item of textBook.links; track item) {
+              <li>{{ item }}</li>
+              }
+            </div>
+          </div>
+          <div class="text-tips">所有作者政治审查意见</div>
+          <nz-table
+            #basicTable
+            [nzShowPagination]="false"
+            [nzData]="textBook.opinions"
+            [nzScroll]="{
+              x: (templ1.style.width || '1000') + 'px',
+              y: '240px'
+            }"
+          >
+            <thead>
+              <tr>
+                <th nzWidth="80px" nzLeft nzAlign="right">序号</th>
+                <th nzWidth="100px">作者</th>
+                <th nzWidth="100px">单位</th>
+                <th nzWidth="100px">出生年月</th>
+                <th nzWidth="100px">国籍</th>
+                <th nzWidth="100px" nzRight>作者政治审查表</th>
+              </tr>
+            </thead>
+            <tbody>
+              @for (data of textBook.opinions; track data.name;let index =
+              $index) {
+              <tr>
+                <td nzLeft nzAlign="right">{{ index + 1 }}</td>
+                <td>
+                  {{ data.name }}
+                </td>
+                <td>
+                  {{ data.unit }}
+                </td>
+                <td>
+                  {{ data.birth | date : "yyyy-MM" }}
+                </td>
+                <td>
+                  {{ data.nationality }}
+                </td>
+                <td nzRight>
+                  <a [href]="data.reviewFile.url">{{ data.reviewFile.name }}</a>
+                </td>
+              </tr>
+              }
+            </tbody>
+          </nz-table>
+          <div class="row" style="margin-top: 10px">
+            <div class="label">图书编校质量自查结果记录表</div>
+            <div class="value">
+              <a [href]="textBook.selfResults.url">{{
+                textBook.selfResults.name
+              }}</a>
+            </div>
+          </div>
+          <div class="row">
+            <div class="label">专家审核意见表</div>
+            <div class="value">
+              <a [href]="textBook.expertOpinion.url">{{
+                textBook.expertOpinion.name
+              }}</a>
+            </div>
+          </div>
+          <div class="row">
+            <div class="label">教材使用情况证明材料</div>
+            <div class="value">
+              <a [href]="textBook.evidence.url">{{ textBook.evidence.name }}</a>
+            </div>
+          </div>
+          <div class="row">
+            <div class="label">其他材料</div>
+            <div class="value">
+              @for (item of textBook.moreMaterial; track item.name) {
+              <a style="margin-right: 10px" [href]="item.url">{{
+                item.name
+              }}</a>
+              }
+            </div>
+          </div>
+        </div>
+      </div>
+      <div class="templ">
+        <div class="title">教材作者诚信承诺</div>
+        <div class="base-content">
+          <nz-table
+            #basicTable
+            [nzShowPagination]="false"
+            [nzData]="textBook.authorSign"
+            [nzScroll]="{
+              x: (templ1.style.width || '1000') + 'px',
+              y: '240px'
+            }"
+          >
+            <thead>
+              <tr>
+                <th nzWidth="80px" nzLeft nzAlign="right">序号</th>
+                <th nzWidth="100px">作者</th>
+                <th nzWidth="100px">单位</th>
+                <th nzWidth="100px">出生年月</th>
+                <th nzWidth="100px">国籍</th>
+                <th nzWidth="100px" nzRight>作者签名</th>
+              </tr>
+            </thead>
+            <tbody>
+              @for (data of textBook.authorSign; track data.name;let index =
+              $index) {
+              <tr>
+                <td nzLeft nzAlign="right">{{ index + 1 }}</td>
+                <td>
+                  {{ data.name }}
+                </td>
+                <td>
+                  {{ data.unit }}
+                </td>
+                <td>
+                  {{ data.birth | date : "yyyy-MM" }}
+                </td>
+                <td>
+                  {{ data.nationality }}
+                </td>
+                <td nzRight>
+                  <a [href]="data.reviewFile.url">{{ data.reviewFile.name }}</a>
+                </td>
+              </tr>
+              }
+            </tbody>
+          </nz-table>
+        </div>
+      </div>
+      <div class="templ">
+        <div class="title">申报单位承诺意见</div>
+        <div class="base-content">
+          <div class="row">
+            <div class="label">申报单位承诺意见材料</div>
+            <div class="value">
+              <a style="margin-right: 10px" [href]="textBook.unitMaterial.url">{{textBook.unitMaterial.name}}</a>
+            </div>
+          </div>
+        </div>
+      </div>
+      <div class="templ">
+        <div class="title">初评推荐意见</div>
+        <div class="base-content">
+          <div class="row">
+            <div class="label">省级教育行政部门初评专家组意见</div>
+            <div class="value">
+              <span style="color:#231C1F99">暂未填写</span>
+            </div>
+          </div>
+          <div class="row">
+            <div class="label">省级教育行政部门意见</div>
+            <div class="value">
+              <span style="color:#231C1F99">暂无</span>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <div nz-col nzSpan="6">
+      <nz-anchor
+        style="position: fixed"
+        (nzClick)="handleClick($event)"
+        [nzShowInkInFixed]="true"
+        [nzShowInkInFixed]="true"
+      >
+        <nz-link nzHref="#templ1" nzTitle="教材基本信息"></nz-link>
+        <nz-link
+          nzHref="#components-anchor-demo-static"
+          nzTitle="教材适用情况"
+        ></nz-link>
+        <nz-link nzHref="#api" nzTitle="作者信息">
+          <nz-link nzHref="#nz-anchor" nzTitle="作者"></nz-link>
+          <nz-link nzHref="#nz-link" nzTitle="第一主编(作者)情况"></nz-link>
+        </nz-link>
+        <nz-link nzHref="#base" nzTitle="申报教材建设历程"></nz-link>
+        <nz-link nzHref="#base" nzTitle="申报教材特色及创新"></nz-link>
+        <nz-link
+          nzHref="#base"
+          nzTitle="申报教材应用情况及社会影响力"
+        ></nz-link>
+        <nz-link nzHref="#base" nzTitle="附件材料清单"></nz-link>
+        <nz-link nzHref="#base" nzTitle="教材作者诚信承诺"></nz-link>
+        <nz-link nzHref="#base" nzTitle="申报单位承诺意见"></nz-link>
+        <nz-link nzHref="#base" nzTitle="初评推荐意见"></nz-link>
+      </nz-anchor>
+    </div>
+  </div>
+</div>

+ 86 - 0
projects/textbook/src/modules/nav-author/textbook-details/textbook-details.component.scss

@@ -0,0 +1,86 @@
+.site-page-header {
+  position: sticky;
+  top: 0;
+  z-index: 9;
+  padding: 24px 24px 10px;
+  background-color: white;
+  font-family: PingFang SC;
+  .steps {
+    max-width: 1000px;
+    margin: 10px 0;
+  }
+  .back {
+    font-family: PingFang SC;
+    font-size: 14px;
+    font-weight: 400;
+    line-height: 22px;
+    text-align: left;
+    cursor: pointer;
+  }
+}
+.content {
+  font-family: PingFang SC;
+  padding: 10px 24px;
+  .title {
+    font-family: PingFang SC;
+    font-size: 20px;
+    font-weight: 500;
+    line-height: 28px;
+    text-align: left;
+    margin-bottom: 20px;
+  }
+  .templ {
+    margin-top: 40px;
+    .text {
+      font-family: PingFang SC;
+      font-size: 16px;
+      font-weight: 500;
+      line-height: 22px;
+      text-align: left;
+    }
+  }
+  .base-content {
+    .row {
+      display: flex;
+      margin-bottom: 14px;
+      .label {
+        width: 220px;
+        font-family: PingFang SC;
+        font-size: 14px;
+        font-weight: 400;
+        line-height: 20px;
+        text-align: left;
+        color: #231c1f99;
+      }
+      .value {
+        margin-left: 20px;
+        flex: 1;
+        font-family: PingFang SC;
+        font-size: 14px;
+        font-weight: 400;
+        line-height: 20px;
+        text-align: left;
+      }
+    }
+    .text-tips {
+      font-family: PingFang SC;
+      font-size: 14px;
+      font-weight: 400;
+      line-height: 20px;
+      text-align: left;
+      color: #231c1f99;
+      margin: 10px 0;
+    }
+    .note{
+      font-family: PingFang SC;
+      font-size: 14px;
+      font-weight: 400;
+      line-height: 20px;
+      text-align: left;
+      color: #231C1F;
+    }
+  }
+}
+.mar10{
+  margin: 20px 0;
+}

+ 24 - 0
projects/textbook/src/modules/nav-author/textbook-details/textbook-details.component.spec.ts

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

+ 216 - 0
projects/textbook/src/modules/nav-author/textbook-details/textbook-details.component.ts

@@ -0,0 +1,216 @@
+import {
+  Component,
+  OnInit,
+  Input,
+  Output,
+  EventEmitter,
+  ViewChild,
+  ElementRef,
+} from '@angular/core';
+import { CommonCompModule } from '../../../services/common.modules';
+import { Router } from '@angular/router';
+import { ReactiveFormsModule } from '@angular/forms';
+import { BasicInComponent } from '../components/basic-in/basic-in.component';
+import { TextbookPertainComponent } from '../components/textbook-pertain/textbook-pertain.component';
+import { TextbookContentComponent } from '../components/textbook-content/textbook-content.component';
+import { AttachmentComponent } from '../components/attachment/attachment.component';
+import { NzAnchorModule } from 'ng-zorro-antd/anchor';
+import { DatePipe } from '@angular/common';
+
+interface author {
+  name: string;
+  unit: string;
+  birth: Date | any;
+  nationality: string;
+  job: string;
+  title: string;
+  mobile: string;
+  email: string;
+  work: string;
+}
+@Component({
+  selector: 'app-textbook-details',
+  imports: [
+    CommonCompModule,
+    ReactiveFormsModule,
+    BasicInComponent,
+    TextbookPertainComponent,
+    TextbookContentComponent,
+    AttachmentComponent,
+    NzAnchorModule,
+    DatePipe,
+  ],
+  standalone: true,
+  templateUrl: './textbook-details.component.html',
+  styleUrls: ['./textbook-details.component.scss'],
+  providers: [DatePipe],
+})
+export class TextbookDetailsComponent implements OnInit {
+  @ViewChild('templ1') templ1: any;
+
+  textBook: object | any = {
+    title: '', //申报教材名称
+    ISBN: '', //国际标准书号
+    author: '', //第一主编(作者)
+    unit: '', //第一主编(作者)单位
+    type: '', //申报类型
+    typeNumber: '', //全册次数
+
+    majorPoniter: '', //教材应用对象及所诉学科专业类
+    lang: '', //教材主要语种类型
+    authors: '', //其他主编姓名
+    editor: '', //其他编者姓名
+
+    approval: '', //是否为重点立项教材
+    editionUnit: '', //出版单位
+    editionFirst: '', //初版时间
+    carrierShape: '', //载体形式
+
+    editionDate: '', //出版时间
+    editionNumber: '', //出版版次
+    printDate: '', //最新印次时间
+    printNumber: '', //最新印次
+
+    printSum: '', //初版以来合计印次
+
+    importantProject: '', //初版以来是否列为重点项目
+    importantProjectOther: '', //其他省部级及以上项目
+
+    copyrightImgUrl: '', //版权页截图
+    CIPImgUrl: '', //中国版本图书馆CIP查询截图
+    major:{ //适用专业代码(六位)及名称
+      code:'000416',
+      name:'通信工程'
+    },
+    lessons:[],
+    characteristic:[],
+    period:1,
+
+    authorDetails:
+      '从事英语教学和外事管理二十年,教学经验丰富,系“双师型”教师,主持和参与多项省部级科研课题,连续多年担任全国导游资格面试中英文考官,2015 年和 2016 年担任全国职业院校技能大赛英文导游裁判长;2020 年入选“中国东盟双百职校强强合作旗舰计划”专家和来华留学生高等教育质量认证(高职院校类)技术专家库;2021 年湖北省教育厅推荐入选教育部鲁班工坊建设联盟专家库首批专家。组织申报学校荣获世界职教院校联盟卓越奖(2016 年铜奖、2018 年银奖、2020 年金奖)。',
+    authorList: [
+      {
+        name: '曹春海',
+        unit: '外语教育出版社',
+        birth: new Date('2000-1-1'),
+        nationality: '中国',
+        job: '博士生导师',
+        title: '教授',
+        mobile: '1881881888',
+        email: '123@123.com',
+        work: '主编',
+      },
+    ],
+    achievementOptions: [
+      //相关科学研究项目、成果或论文专著(限5项)
+      {
+        name: '双语教育对人脑杏仁核发育影响研究',
+        unit: '二十一世纪出版社',
+        date: new Date('2000-1-1'),
+      },
+    ],
+    courses: [
+      //申报教材建设历程
+      {
+        date: new Date('2000-1-1'), //出版时间
+        wordage: 569, //字数
+        num: 2, //重印次数
+        sumNum: 3, //本版总印数
+        accolade: '国家高等教材特等奖', //获奖励情况
+      },
+    ],
+    //申报教材特色及创新
+    innovateExplain:
+      '本教材最大的特色是教材内容编写延用情景启发模式,表现形式上融情景、体验、拓展、互动于一体,打造生动、立体课堂,提高学生学习兴趣及主动性。',
+    //申报教材应用情况及社会影响力
+    influence:
+      '指导教学更有章法、更可复制。本教材系“十四五”职业教育江苏省规划教材、“十三五”江苏省高等学校重点教材、高等院校人文素质教育重点教材、精品工程项目教材,内容丰富、取材合适、系统性强,在促进学生成长成才、科学指导就业创业等方面有着成熟而广泛的应用前景,目前已推广到南通中等专业学校、聊城苏通技工学校等省内外多所职业院校,均得到师生的一致好评',
+    textbookFiles: [
+      //附件教材
+      {
+        name: '汉语版.pdf',
+        url: 'https://www.jyvtc.edu.cn/yssj/resource/cms/2022/01/2022010610314324023.pdf',
+      },
+      {
+        name: '维语版.pdf',
+        url: 'https://www.jyvtc.edu.cn/yssj/resource/cms/2022/01/2022010610314324023.pdf',
+      },
+    ],
+    links: [
+      //数字内容链接地址、账号
+      'https://www.hep.com.cn/book/show/0519241c-ed3a-4bdf-9c79-2eedc51fbe21 账号:xxxxxx 密码:xxxxxx',
+      'https://www.hepmall.com/index.php/gallery-index-.html?scontent=%E7%B3%BB%E7%BB%9F%E5%88%86%E6%9E%90%E4%B8%8E%E8%AE%BE%E8%AE%A',
+    ],
+    opinions: [
+      //所有作者政治审查意见
+      {
+        name: '曹春海', //作者
+        unit: '外语教育出版社', //单位
+        birth: new Date(), //出生年月
+        nationality: '中华人民共和国', //国籍
+        reviewFile: {
+          //作者政治审查表
+          name: '维语版.pdf',
+          url: 'https://www.jyvtc.edu.cn/yssj/resource/cms/2022/01/2022010610314324023.pdf',
+        },
+      },
+    ],
+    selfResults: {
+      //图书编校质量自查结果记录表
+      name: '自查表.pdf',
+      url: 'https://www.jyvtc.edu.cn/yssj/resource/cms/2022/01/2022010610314324023.pdf',
+    },
+    //专家审核意见表
+    expertOpinion:{
+      name: '意见表.pdf',
+      url: 'https://www.jyvtc.edu.cn/yssj/resource/cms/2022/01/2022010610314324023.pdf',
+    },
+    //教材使用情况证明材料
+    evidence:{
+      name: '材料.pdf',
+      url: 'https://www.jyvtc.edu.cn/yssj/resource/cms/2022/01/2022010610314324023.pdf',
+    },
+    //其他材料
+    moreMaterial:[
+      {
+        name: '材料1.pdf',
+        url: 'https://www.jyvtc.edu.cn/yssj/resource/cms/2022/01/2022010610314324023.pdf',
+      },
+      {
+        name: '材料2.pdf',
+        url: 'https://www.jyvtc.edu.cn/yssj/resource/cms/2022/01/2022010610314324023.pdf',
+      },
+    ],
+    //所有作者签名&教材作者诚信承诺
+    authorSign:[
+      {
+        name: '曹春海', //作者
+        unit: '外语教育出版社', //单位
+        birth: new Date(), //出生年月
+        nationality: '中华人民共和国', //国籍
+        reviewFile: {
+          //作者政治审查表/作者签名
+          name: '曹春海签名.pdf',
+          url: 'https://www.jyvtc.edu.cn/yssj/resource/cms/2022/01/2022010610314324023.pdf',
+        },
+      },
+    ],
+    //申报单位承诺意见材料
+    unitMaterial:{
+      name: '承诺意见表.pdf',
+      url: 'https://www.jyvtc.edu.cn/yssj/resource/cms/2022/01/2022010610314324023.pdf',
+    },
+  };
+  constructor() {}
+
+  ngOnInit() {}
+
+  handleClick(e: string): void {
+    console.log(e);
+    // let dom:any = [e]
+    // dom.nativeElement.scrollIntoView({ behavior: 'smooth', block: 'start', inline: 'start' });
+  }
+  back() {
+    history.back();
+  }
+}

+ 6 - 8
projects/textbook/src/modules/nav-province-contact/modules.routes.ts

@@ -1,16 +1,14 @@
 import { NgModule } from "@angular/core";
 import { RouterModule, Routes } from "@angular/router";
-import { PageHomeComponent } from './page-home/page-home.component';
 const routes: Routes = [
   {
-    path: 'home',
-    component: PageHomeComponent,
+    path: '',
+    redirectTo:'manage',
+    pathMatch: "full",
+  },
+  {
+    path: 'manage',
     children:[
-      // {
-      //   path: "",
-      //   redirectTo: "pay",
-      //   pathMatch: "full",
-      // },
     ]
   }
 ];

+ 0 - 35
projects/textbook/src/modules/nav-province-contact/page-home/page-home.component.html

@@ -1,35 +0,0 @@
-<app-comp-nav></app-comp-nav>
-<div class="page">
-  <div class="content-left">
-    <ul nz-menu nzMode="inline" style="width: 240px">
-      @for (item of options; track item.id;let index = $index) { @if(item.child)
-      {
-      <li nz-submenu [nzTitle]="item.name" nzIcon="api" [nzOpen]="true">
-        <ul>
-          @for (child of item.child; track child.id;let idx = $index) {
-          <li
-            nz-menu-item
-            [nzSelected]="active == child.id"
-            (click)="toUrl('/nav-admin', child.id, { category: child.id })"
-          >
-            {{ child.name }}
-          </li>
-          }
-        </ul>
-      </li>
-      } @else {
-      <li
-        nz-menu-item
-        (click)="toUrl('/nav-admin', 'list')"
-        [nzSelected]="active == item.id"
-      >
-        <span nz-icon nzType="home" nzTheme="outline"></span>
-        <span>{{ item.name }}</span>
-      </li>
-      } }
-    </ul>
-  </div>
-  <div class="proview">
-    <router-outlet></router-outlet>
-  </div>
-</div>

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

@@ -1,15 +0,0 @@
-.page{
-  display: flex;
-  height: calc(100% - 60px);
-  // overflow-y: scroll;
-  overflow-y: hidden;
-  .content-left{
-    background-color:#fff;
-  }
-  .content-rifht{
-    height: 100%;
-    overflow-y: scroll;
-    padding: 20px 0 40px 0;
-    flex: 1;
-  }
-}

+ 0 - 50
projects/textbook/src/modules/nav-province-contact/page-home/page-home.component.ts

@@ -1,50 +0,0 @@
-import { Component, OnInit } from '@angular/core';
-import { CompNavComponent } from '../../../app/comp-nav/comp-nav.component'
-import { RouterOutlet, Router } from '@angular/router';
-import { CommonCompModule } from '../../../services/common.modules'
-
-@Component({
-  selector: 'app-page-home',
-  standalone: true,
-  imports: [CompNavComponent,RouterOutlet,CommonCompModule],
-  templateUrl: './page-home.component.html',
-  styleUrls: ['./page-home.component.scss'],
-})
-export class PageHomeComponent  implements OnInit {
-
-  options:Array<any> = [
-    {
-      name:'报送流程',
-      id:'1',
-    },
-    {
-      name:'用户管理',
-      id:'2',
-      child:[
-        {
-          name:'用户列表',
-          id:'2-1',
-        },
-        {
-          name:'用户组管理',
-          id:'2-2',
-        },
-        {
-          name:'邀请注册',
-          id:'2-3',
-        },
-      ]
-    }
-  ]
-  active:string = localStorage.getItem('active') || this.options[0].id
-  constructor(
-    public router: Router,
-  ) { }
-
-  ngOnInit() {}
-  toUrl(url:string, cateid:string, params?:any){
-    this.active = cateid
-    localStorage.setItem('active', cateid)
-    // this.router.navigate([url, params ? params : {}])
-  }
-}

+ 6 - 8
projects/textbook/src/modules/nav-province-school-contact/modules.routes.ts

@@ -1,16 +1,14 @@
 import { NgModule } from "@angular/core";
 import { RouterModule, Routes } from "@angular/router";
-import { PageHomeComponent } from './page-home/page-home.component';
 const routes: Routes = [
   {
-    path: 'home',
-    component: PageHomeComponent,
+    path: '',
+    redirectTo:'manage',
+    pathMatch: "full",
+  },
+  {
+    path: 'manage',
     children:[
-      // {
-      //   path: "",
-      //   redirectTo: "pay",
-      //   pathMatch: "full",
-      // },
     ]
   }
 ];

+ 0 - 35
projects/textbook/src/modules/nav-province-school-contact/page-home/page-home.component.html

@@ -1,35 +0,0 @@
-<app-comp-nav></app-comp-nav>
-<div class="page">
-  <div class="content-left">
-    <ul nz-menu nzMode="inline" style="width: 240px">
-      @for (item of options; track item.id;let index = $index) { @if(item.child)
-      {
-      <li nz-submenu [nzTitle]="item.name" nzIcon="api" [nzOpen]="true">
-        <ul>
-          @for (child of item.child; track child.id;let idx = $index) {
-          <li
-            nz-menu-item
-            [nzSelected]="active == child.id"
-            (click)="toUrl('/nav-admin', child.id, { category: child.id })"
-          >
-            {{ child.name }}
-          </li>
-          }
-        </ul>
-      </li>
-      } @else {
-      <li
-        nz-menu-item
-        (click)="toUrl('/nav-admin', 'list')"
-        [nzSelected]="active == item.id"
-      >
-        <span nz-icon nzType="home" nzTheme="outline"></span>
-        <span>{{ item.name }}</span>
-      </li>
-      } }
-    </ul>
-  </div>
-  <div class="proview">
-    <router-outlet></router-outlet>
-  </div>
-</div>

+ 0 - 15
projects/textbook/src/modules/nav-province-school-contact/page-home/page-home.component.scss

@@ -1,15 +0,0 @@
-.page{
-  display: flex;
-  height: calc(100% - 60px);
-  // overflow-y: scroll;
-  overflow-y: hidden;
-  .content-left{
-    background-color:#fff;
-  }
-  .content-rifht{
-    height: 100%;
-    overflow-y: scroll;
-    padding: 20px 0 40px 0;
-    flex: 1;
-  }
-}

+ 0 - 50
projects/textbook/src/modules/nav-province-school-contact/page-home/page-home.component.ts

@@ -1,50 +0,0 @@
-import { Component, OnInit } from '@angular/core';
-import { CompNavComponent } from '../../../app/comp-nav/comp-nav.component'
-import { RouterOutlet, Router } from '@angular/router';
-import { CommonCompModule } from '../../../services/common.modules'
-
-@Component({
-  selector: 'app-page-home',
-  standalone: true,
-  imports: [CompNavComponent,RouterOutlet,CommonCompModule],
-  templateUrl: './page-home.component.html',
-  styleUrls: ['./page-home.component.scss'],
-})
-export class PageHomeComponent  implements OnInit {
-
-  options:Array<any> = [
-    {
-      name:'校内空间',
-      id:'1',
-    },
-    {
-      name:'用户管理',
-      id:'2',
-      child:[
-        {
-          name:'邀请注册',
-          id:'2-1',
-        },
-        {
-          name:'用户列表',
-          id:'2-2',
-        },
-      ]
-    },
-    {
-      name:'个人信息',
-      id:'3',
-    },
-  ]
-  active:string = localStorage.getItem('active') || this.options[0].id
-  constructor(
-    public router: Router,
-  ) { }
-
-  ngOnInit() {}
-  toUrl(url:string, cateid:string, params?:any){
-    this.active = cateid
-    localStorage.setItem('active', cateid)
-    // this.router.navigate([url, params ? params : {}])
-  }
-}

+ 6 - 8
projects/textbook/src/modules/nav-province-submit/modules.routes.ts

@@ -1,16 +1,14 @@
 import { NgModule } from "@angular/core";
 import { RouterModule, Routes } from "@angular/router";
-import { PageHomeComponent } from './page-home/page-home.component';
 const routes: Routes = [
   {
-    path: 'home',
-    component: PageHomeComponent,
+    path: '',
+    redirectTo:'manage',
+    pathMatch: "full",
+  },
+  {
+    path: 'manage',
     children:[
-      // {
-      //   path: "",
-      //   redirectTo: "pay",
-      //   pathMatch: "full",
-      // },
     ]
   }
 ];

+ 0 - 35
projects/textbook/src/modules/nav-province-submit/page-home/page-home.component.html

@@ -1,35 +0,0 @@
-<app-comp-nav></app-comp-nav>
-<div class="page">
-  <div class="content-left">
-    <ul nz-menu nzMode="inline" style="width: 240px">
-      @for (item of options; track item.id;let index = $index) { @if(item.child)
-      {
-      <li nz-submenu [nzTitle]="item.name" nzIcon="api" [nzOpen]="true">
-        <ul>
-          @for (child of item.child; track child.id;let idx = $index) {
-          <li
-            nz-menu-item
-            [nzSelected]="active == child.id"
-            (click)="toUrl('/nav-admin', child.id, { category: child.id })"
-          >
-            {{ child.name }}
-          </li>
-          }
-        </ul>
-      </li>
-      } @else {
-      <li
-        nz-menu-item
-        (click)="toUrl('/nav-admin', 'list')"
-        [nzSelected]="active == item.id"
-      >
-        <span nz-icon nzType="home" nzTheme="outline"></span>
-        <span>{{ item.name }}</span>
-      </li>
-      } }
-    </ul>
-  </div>
-  <div class="proview">
-    <router-outlet></router-outlet>
-  </div>
-</div>

+ 0 - 15
projects/textbook/src/modules/nav-province-submit/page-home/page-home.component.scss

@@ -1,15 +0,0 @@
-.page{
-  display: flex;
-  height: calc(100% - 60px);
-  // overflow-y: scroll;
-  overflow-y: hidden;
-  .content-left{
-    background-color:#fff;
-  }
-  .content-rifht{
-    height: 100%;
-    overflow-y: scroll;
-    padding: 20px 0 40px 0;
-    flex: 1;
-  }
-}

+ 0 - 24
projects/textbook/src/modules/nav-province-submit/page-home/page-home.component.spec.ts

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

+ 0 - 38
projects/textbook/src/modules/nav-province-submit/page-home/page-home.component.ts

@@ -1,38 +0,0 @@
-import { Component, OnInit } from '@angular/core';
-import { CompNavComponent } from '../../../app/comp-nav/comp-nav.component'
-import { RouterOutlet, Router } from '@angular/router';
-import { CommonCompModule } from '../../../services/common.modules'
-
-@Component({
-  selector: 'app-page-home',
-  standalone: true,
-  imports: [CompNavComponent,RouterOutlet,CommonCompModule],
-  templateUrl: './page-home.component.html',
-  styleUrls: ['./page-home.component.scss'],
-})
-export class PageHomeComponent  implements OnInit {
-
-  options:Array<any> = [
-    {
-      name:'省内合集',
-      id:'1',
-      // child:[
-      //   {
-      //     name:'确认报送',
-      //     id:'1-1',
-      //   },
-      // ]
-    },
-  ]
-  active:string = localStorage.getItem('active') || this.options[0].id
-  constructor(
-    public router: Router,
-  ) { }
-
-  ngOnInit() {}
-  toUrl(url:string, cateid:string, params?:any){
-    this.active = cateid
-    localStorage.setItem('active', cateid)
-    // this.router.navigate([url, params ? params : {}])
-  }
-}

+ 2 - 9
projects/textbook/src/modules/nav-review/modules.routes.ts

@@ -1,27 +1,20 @@
 import { NgModule } from '@angular/core';
 import { RouterModule, Routes } from '@angular/router';
-import { PageHomeComponent } from './page-home/page-home.component';
 import { ApproveComponent } from './approve/approve.component';
-import { ProfileComponent } from '../user/profile/profile.component';
 const routes: Routes = [
   {
     path: '',
-    redirectTo:'home/apply',
+    redirectTo:'manage/apply',
     pathMatch: "full",
   },
   {
-    path: 'home',
-    component: PageHomeComponent,
+    path: 'manage',
     children: [
       {
         path: 'apply', //创建教材
         component: ApproveComponent,
       },
     ],
-  },
-  {
-    path: 'profile',
-    component: ProfileComponent,
   }
 ];
 @NgModule({

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно