Browse Source

作者/教师/主编 amdin

warrior 8 months ago
parent
commit
dba8dccecd
25 changed files with 965 additions and 376 deletions
  1. 3 3
      projects/textbook/src/app/comp-manage/comp-manage.component.ts
  2. 5 4
      projects/textbook/src/app/comp-table/comp-table-list/comp-table-list.component.ts
  3. 11 6
      projects/textbook/src/modules/login/login/login.component.ts
  4. 10 10
      projects/textbook/src/modules/login/register/register.component.ts
  5. 10 10
      projects/textbook/src/modules/login/reset-password/reset-password.component.ts
  6. 5 1
      projects/textbook/src/modules/nav-author/apply/apply.component.ts
  7. 14 14
      projects/textbook/src/modules/nav-author/components/attachment/attachment.component.html
  8. 248 23
      projects/textbook/src/modules/nav-author/components/attachment/attachment.component.ts
  9. 1 1
      projects/textbook/src/modules/nav-author/components/basic-in/basic-in.component.html
  10. 5 2
      projects/textbook/src/modules/nav-author/components/basic-in/basic-in.component.ts
  11. 30 28
      projects/textbook/src/modules/nav-author/components/page-textbook/page-textbook.component.ts
  12. 1 1
      projects/textbook/src/modules/nav-author/components/textbook-content/textbook-content.component.html
  13. 72 15
      projects/textbook/src/modules/nav-author/components/textbook-content/textbook-content.component.ts
  14. 66 12
      projects/textbook/src/modules/nav-author/components/textbook-pertain/textbook-pertain.component.html
  15. 63 39
      projects/textbook/src/modules/nav-author/components/textbook-pertain/textbook-pertain.component.ts
  16. 1 1
      projects/textbook/src/modules/nav-author/recycle/recycle.component.html
  17. 8 4
      projects/textbook/src/modules/nav-author/space/space.component.html
  18. 8 6
      projects/textbook/src/modules/nav-author/space/space.component.ts
  19. 29 12
      projects/textbook/src/modules/nav-author/textbook-details/textbook-details.component.html
  20. 9 0
      projects/textbook/src/modules/nav-author/textbook-details/textbook-details.component.scss
  21. 165 150
      projects/textbook/src/modules/nav-author/textbook-details/textbook-details.component.ts
  22. 96 1
      projects/textbook/src/schemas/EduTextbook.ts
  23. 61 27
      projects/textbook/src/services/auth.service.ts
  24. 33 2
      server/api/textbook/routes.js
  25. 11 4
      server/db/schemas/EduTextbook.js

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

@@ -155,9 +155,9 @@ export class CompManageComponent implements OnInit {
         name: '回收站',
         id: '2',
         path: '/nav-author/manage/recycle',
-        params: {
-          isDeleted: true,
-        },
+        // params: {
+        //   isDeleted: true,
+        // },
       },
     ],
   } 

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

@@ -5,11 +5,11 @@ import Parse from "parse";
 import { ParseDataService } from '../parse-data.service';
 // import { TranslateModule, TranslateService } from '@ngx-translate/core';
 import { CommonModule } from '@angular/common';
-
+import { NzModalService } from 'ng-zorro-antd/modal';
 import { NzPaginationModule } from 'ng-zorro-antd/pagination';
 import { NzEmptyModule } from 'ng-zorro-antd/empty';
 import { NzResultModule } from 'ng-zorro-antd/result';
-
+import { NzModalModule } from 'ng-zorro-antd/modal';
 import { MatCheckboxModule } from '@angular/material/checkbox';
 import { MatButtonModule } from '@angular/material/button';
 import { MatSlideToggleModule } from '@angular/material/slide-toggle';
@@ -39,7 +39,7 @@ interface SchemaFiled{
     UtilnowPipe,
     // TranslateModule,
     NzPaginationModule,NzEmptyModule,NzTableModule,NzResultModule,NzIconModule,
-    MatButtonModule,MatCheckboxModule,MatSlideToggleModule,MatIconModule,
+    MatButtonModule,MatCheckboxModule,MatSlideToggleModule,MatIconModule,NzModalModule
   ],
   providers:[]
 })
@@ -70,6 +70,7 @@ export class CompTableListComponent {
     private dialog:MatDialog,
     private router:Router,
     // public translate:TranslateService
+    private modal: NzModalService
   ){
     this.currentLang = "cn"// this.translate.getDefaultLang();
   }
@@ -99,7 +100,7 @@ export class CompTableListComponent {
   buttonHandle(button:any,object:any){
     let that = this
     if(button?.handle){
-      button?.handle({object:object,dialog:this.dialog,router:this.router,callback:this.onButtonHandleCallBack},that.currentLang)
+      button?.handle({object:object,dialog:this.dialog,router:this.router,modal:this.modal,callback:this.onButtonHandleCallBack},that.currentLang)
     }
   }
   refresh(page?:number){

+ 11 - 6
projects/textbook/src/modules/login/login/login.component.ts

@@ -35,6 +35,11 @@ export class LoginComponent implements OnInit{
       // 监听事件:登陆成功后,返回用户信息
       login:(user,authClient)=>{
         console.log(user,authClient)
+        this.authServr.profileVerify()
+        // this.authServr.login(user.id).catch(err=>{
+        //   console.warn(err);
+        //   this.message.error(err?.message || '登录失败')
+        // })
       }
     });
     parseAuthing.initLoginModal();
@@ -104,12 +109,12 @@ export class LoginComponent implements OnInit{
           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 || '登录失败')
-        })
+        // 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) => {

+ 10 - 10
projects/textbook/src/modules/login/register/register.component.ts

@@ -154,16 +154,16 @@ export class RegisterComponent implements OnInit {
             nzContent: "您已成功注册开发者账号,直接登录?",
             nzCancelText: "取消",
             nzOnOk: () => {
-              this.loginServr
-              .login(this.mobile, this.password, this.company)
-              .then((data) => {
-                console.log(data);
-                this.router.navigate(["developer/app-list"])
-              })
-              .catch((err) => {
-                console.log(err);
-                this.msg.error(err.message);
-              });
+              // this.loginServr
+              // .login(this.mobile, this.password, this.company)
+              // .then((data) => {
+              //   console.log(data);
+              //   this.router.navigate(["developer/app-list"])
+              // })
+              // .catch((err) => {
+              //   console.log(err);
+              //   this.msg.error(err.message);
+              // });
             }
           });
         }

+ 10 - 10
projects/textbook/src/modules/login/reset-password/reset-password.component.ts

@@ -149,16 +149,16 @@ export class ResetPasswordComponent {
             nzContent: "密码已重置,直接登录?",
             nzCancelText: "取消",
             nzOnOk: () => {
-              this.loginServr
-                .login(this.mobile, this.password, this.company)
-                .then((data) => {
-                  console.log(data);
-                  this.router.navigate(["developer/app-list"]);
-                })
-                .catch((err) => {
-                  console.log(err);
-                  this.msg.error(err.message);
-                });
+              // this.loginServr
+              //   .login(this.mobile, this.password, this.company)
+              //   .then((data) => {
+              //     console.log(data);
+              //     this.router.navigate(["developer/app-list"]);
+              //   })
+              //   .catch((err) => {
+              //     console.log(err);
+              //     this.msg.error(err.message);
+              //   });
             },
           });
         }

+ 5 - 1
projects/textbook/src/modules/nav-author/apply/apply.component.ts

@@ -47,6 +47,10 @@ export class ApplyComponent implements OnInit {
         query.equalTo('objectId', id);
         this.textBook = await query.first();
         console.log(this.textBook);
+        if(this.textBook?.get('render')){
+          window.alert("已提交,禁止编辑")
+          history.back()
+        }
       }
       this.showFrom = true;
     });
@@ -58,7 +62,7 @@ export class ApplyComponent implements OnInit {
     }
     if (event?.type == 'pre') {
       this.state--;
-    } else {
+    } else if(event?.type == 'next'){
       this.state++;
     }
   }

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

@@ -10,11 +10,13 @@
       <div class="text">
         教材出版单位配合按要求上传各地推荐的本单位出版的纸质教材最新印次的完整PDF电子版;数字教材上传全部教材内容电子版或填写能够查看全部教材内容的链接地址、账号;纸质教材附带数字资源的,上传纸质教材最新印次的完整PDF电子版,以及全部数字资源电子版或能够查看全部数字资源内容的链接地址、账号
       </div>
-      <nz-checkbox-group
+      <!-- <nz-checkbox-group
         style="margin: 10px 0"
         formControlName="textbookTypes"
         [(ngModel)]="checkOptionsOne"
-      ></nz-checkbox-group>
+      ></nz-checkbox-group> -->
+      <label nz-checkbox [ngModelOptions]="{ standalone: true }" [ngModel]="true">纸质教材</label>
+      <label nz-checkbox [ngModelOptions]="{ standalone: true }" [ngModel]="true">电子教材 / 资源</label>
       <div nz-row>
         <div nz-col nzSpan="12">
           <nz-form-item class="row" style="margin-bottom: 16px">
@@ -111,7 +113,7 @@
             <td>
               <input
                 nz-input
-                type="number"
+                type="text"
                 placeholder="请填写作者姓名"
                 [ngModelOptions]="{ standalone: true }"
                 [(ngModel)]="data.name"
@@ -121,7 +123,7 @@
             <td>
               <input
                 nz-input
-                type="number"
+                type="text"
                 placeholder="请填写作者单位"
                 [ngModelOptions]="{ standalone: true }"
                 [(ngModel)]="data.unit"
@@ -138,7 +140,7 @@
             <td>
               <input
                 nz-input
-                type="number"
+                type="text"
                 placeholder="请填写作者国籍"
                 [ngModelOptions]="{ standalone: true }"
                 [(ngModel)]="data.nationality"
@@ -147,7 +149,6 @@
             </td>
             <td nzRight>
               <nz-upload
-                formControlName="textbookFiles"
                 nzAction="https://www.mocky.io/v2/5cc8019d300000980a055e76"
                 [nzHeaders]="{ authorization: 'authorization-text' }"
                 (nzChange)="handleChange($event)"
@@ -241,7 +242,7 @@
           style="width: 100%"
         >
           <nz-upload
-            formControlName="textbookFiles"
+            formControlName="expertOpinion"
             nzAction="https://www.mocky.io/v2/5cc8019d300000980a055e76"
             [nzHeaders]="{ authorization: 'authorization-text' }"
             (nzChange)="handleChange($event)"
@@ -278,7 +279,7 @@
           style="width: 100%"
         >
           <nz-upload
-            formControlName="textbookFiles"
+            formControlName="evidence"
             nzAction="https://www.mocky.io/v2/5cc8019d300000980a055e76"
             [nzHeaders]="{ authorization: 'authorization-text' }"
             (nzChange)="handleChange($event)"
@@ -298,7 +299,7 @@
       <div class="text">其他佐证材料。</div>
 
       <nz-upload
-        formControlName="textbookFiles"
+        formControlName="moreMaterial"
         nzAction="https://www.mocky.io/v2/5cc8019d300000980a055e76"
         [nzHeaders]="{ authorization: 'authorization-text' }"
         (nzChange)="handleChange($event)"
@@ -329,7 +330,7 @@
           style="width: 450px"
         >
           <input
-            formControlName="links"
+            formControlName="accept"
             placeholder="请填写承诺内容"
             nz-input
           />
@@ -372,7 +373,7 @@
             <td>
               <input
                 nz-input
-                type="number"
+                type="text"
                 placeholder="请填写作者姓名"
                 [ngModelOptions]="{ standalone: true }"
                 [(ngModel)]="data.name"
@@ -382,7 +383,7 @@
             <td>
               <input
                 nz-input
-                type="number"
+                type="text"
                 placeholder="请填写作者单位"
                 [ngModelOptions]="{ standalone: true }"
                 [(ngModel)]="data.unit"
@@ -399,7 +400,7 @@
             <td>
               <input
                 nz-input
-                type="number"
+                type="text"
                 placeholder="请填写作者国籍"
                 [ngModelOptions]="{ standalone: true }"
                 [(ngModel)]="data.nationality"
@@ -408,7 +409,6 @@
             </td>
             <td nzRight>
               <nz-upload
-                formControlName="textbookFiles"
                 nzAction="https://www.mocky.io/v2/5cc8019d300000980a055e76"
                 [nzHeaders]="{ authorization: 'authorization-text' }"
                 (nzChange)="handleChange($event)"

+ 248 - 23
projects/textbook/src/modules/nav-author/components/attachment/attachment.component.ts

@@ -10,19 +10,23 @@ 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 Parse from 'parse';
 import {
   FormControl,
   FormGroup,
   NonNullableFormBuilder,
   Validators,
+  ValidatorFn,
+  AbstractControl,
 } from '@angular/forms';
 interface opinionType {
   name: string;
   unit: string;
   birth: Date | any;
   nationality: string;
-  reviewFile: string;
+  reviewFile: string | object;
 }
+import { textbookServer } from '../../../../services/textbook';
 @Component({
   selector: 'app-attachment',
   imports: [
@@ -40,26 +44,90 @@ interface opinionType {
   styleUrls: ['./attachment.component.scss'],
 })
 export class AttachmentComponent implements OnInit {
-  @Input('eduTextbook') editFrom: any;
+  @Input('eduTextbook') eduTextbook: any;
   @Input('maxWidth') maxWidth: number = 0;
   @Output() state: EventEmitter<any> = new EventEmitter<any>();
   @Output() save: EventEmitter<any> = new EventEmitter<any>();
+
+  //填写诚信承诺是否正确
+  confirmationValidator: ValidatorFn = (
+    control: AbstractControl
+  ): { [s: string]: boolean } => {
+    if (
+      control.value !=
+      '本人自愿参加此次申报,已认真填写并检查以上材料,保证内容真实'
+    ) {
+      return { required: true };
+    }
+    return {};
+  };
+
   validateForm: FormGroup<{
     textbookTypes: FormControl<Array<string> | any>; //教材电子版
     textbookFiles: FormControl<Array<string> | any>; //上传教材文件
     links: FormControl<string>; //教材数字内容链接地址、账号
-    selfResults:FormControl<object|any>, //图书编校质量自查结果记录表
-    unitMaterial:FormControl<object|any>, //申报单位承诺意见材料
+    selfResults: FormControl<object | any>; //图书编校质量自查结果记录表
+    expertOpinion: FormControl<object | any>; //专家审核意见表
+    evidence: FormControl<object | any>; //教材使用情况证明材料
+    moreMaterial: FormControl<Array<any> | any>; //其他材料
+    unitMaterial: FormControl<object | any>; //申报单位承诺意见材料
+    accept: FormControl<string>; //填写诚信承诺
   }> = this.fb.group({
     textbookTypes: ['', [Validators.required]],
-    textbookFiles: ['', [Validators.required]],
+    textbookFiles: [
+      [
+        {
+          url: 'https://www.jyvtc.edu.cn/yssj/resource/cms/2022/01/2022010610314324023.pdf',
+        },
+      ],
+      [Validators.required]
+    ],
     links: ['', [Validators.required]],
-    selfResults: ['', [Validators.required]],
-    unitMaterial: ['', [Validators.required]],
+    selfResults: [
+      {
+        name: '自查表.pdf',
+        url: 'https://www.jyvtc.edu.cn/yssj/resource/cms/2022/01/2022010610314324023.pdf',
+      },
+      [Validators.required]
+    ],
+    expertOpinion: [
+      {
+        name: '自查表.pdf',
+        url: 'https://www.jyvtc.edu.cn/yssj/resource/cms/2022/01/2022010610314324023.pdf',
+      },
+      [Validators.required]
+    ],
+    evidence: [
+      {
+        name: '材料.pdf',
+        url: 'https://www.jyvtc.edu.cn/yssj/resource/cms/2022/01/2022010610314324023.pdf',
+      },
+      [Validators.required]
+    ],
+    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',
+        },
+      ],
+    ],
+    unitMaterial: [
+      {
+        name: '承诺意见表.pdf',
+        url: 'https://www.jyvtc.edu.cn/yssj/resource/cms/2022/01/2022010610314324023.pdf',
+      },
+      [Validators.required]
+    ],
+    accept: ['', [Validators.required, this.confirmationValidator]],
   });
   checkOptionsOne = [
-    { label: '纸质教材', value: '纸质教材' },
-    { label: '电子教材 / 资源', value: '电子教材 / 资源' },
+    { label: '纸质教材', value: '纸质教材', checked: true },
+    { label: '电子教材 / 资源', value: '电子教材 / 资源', checked: true },
   ];
   //所有作者政治审查意见
   opinions: Array<opinionType> = [
@@ -68,7 +136,10 @@ export class AttachmentComponent implements OnInit {
       unit: '', //单位
       birth: '', //出生年月
       nationality: '', //国籍
-      reviewFile: '', //作者政治审查表/作者签名
+      reviewFile: {
+        name: '自查表.pdf',
+        url: 'https://www.jyvtc.edu.cn/yssj/resource/cms/2022/01/2022010610314324023.pdf',
+      }, //作者政治审查表/作者签名
     },
   ];
   //所有作者签名
@@ -78,20 +149,118 @@ export class AttachmentComponent implements OnInit {
       unit: '', //单位
       birth: '', //出生年月
       nationality: '', //国籍
-      reviewFile: '', //作者政治审查表/作者签名
+      reviewFile: {
+        name: '审查表.pdf',
+        url: 'https://www.jyvtc.edu.cn/yssj/resource/cms/2022/01/2022010610314324023.pdf',
+      }, //作者政治审查表/作者签名
     },
   ];
   constructor(
+    public tbookSer: textbookServer,
     private fb: NonNullableFormBuilder,
     private msg: NzMessageService,
     private modal: NzModalService
   ) {}
-  ngOnInit() {}
-  submitForm(event?: string): void {
+  ngOnInit() {
+    if (this.eduTextbook.id) {
+      this.validateForm = this.fb.group({
+        textbookTypes: [
+          this.eduTextbook.get('textbookTypes'),
+          [Validators.required]
+        ],
+        textbookFiles: [
+          this.eduTextbook.get('textbookFiles') ||
+            this.validateForm.value.textbookFiles,
+          [Validators.required]
+        ],
+        links: [
+          this.eduTextbook.get('links')?.join('\n') || '',
+          [Validators.required]
+        ],
+        selfResults: [
+          this.eduTextbook.get('selfResults') ||
+            this.validateForm.value.selfResults,
+          [Validators.required]
+        ],
+        expertOpinion: [
+          this.eduTextbook.get('expertOpinion') ||
+            this.validateForm.value.expertOpinion,
+          [Validators.required]
+        ],
+        evidence: [
+          this.eduTextbook.get('evidence') || this.validateForm.value.evidence,
+          [Validators.required]
+        ],
+        moreMaterial: [''],
+        unitMaterial: [
+          this.eduTextbook.get('unitMaterial') ||
+            this.validateForm.value.unitMaterial,
+          [Validators.required]
+        ],
+        accept: [
+          this.eduTextbook.get('accept') || '',
+          [Validators.required, this.confirmationValidator]
+        ],
+      });
+      this.opinions = this.eduTextbook.get('opinions') || this.opinions
+      this.authorSign = this.eduTextbook.get('authorSign') || this.authorSign
+    }
+  }
+  async submitForm(event?: string): Promise<void> {
+    if (event == 'pre') {
+      this.state.emit({ type: 'pre' });
+      return;
+    }
     console.log(this.validateForm.value);
+    let opinionsVrifly = !this.opinions.some((item) =>
+      Object.values(item).some((val) => val == '' || val == undefined)
+    );
+    let authorSignVrifly = !this.authorSign.some((item) =>
+      Object.values(item).some((val) => val == '' || val == undefined)
+    );
+    let params: any = this.validateForm.value;
     if (this.validateForm.valid) {
       console.log(this.validateForm.value);
+      if (event == 'complete') {
+        if (!opinionsVrifly) {
+          this.msg.warning('所有作者政治审查意见填写不完整');
+          return;
+        }
+        if (!authorSignVrifly) {
+          this.msg.warning('上传所有作者签名填写不完整');
+          return;
+        }
+        await this.saveEduTextbook(params, true);
+        let textBookJson = this.eduTextbook.toJSON()
+        let ignoreFiled = ['typeNumber','importantProjectOther','createdAt','updatedAt'] //非必填字段
+        console.log(textBookJson);
+        let isVrifly = Object.keys(textBookJson).some((item:string)=>{
+          if(!ignoreFiled.includes(item) && (textBookJson[item] === '' || textBookJson[item] === undefined || textBookJson[item] === null)){
+            console.warn('字段未填写:'+item);
+            return true
+          }
+          return
+        })
+        if(isVrifly){
+          this.msg.warning('存在未填项')
+          return
+        }
+        this.state.emit({ type: 'complete', textBook: this.eduTextbook });
+        this.eduTextbook.set('complete', true)
+        this.eduTextbook.set('status', '102')
+        await this.eduTextbook.save()
+        this.msg.success('已填写完成')
+      }
     } else {
+      if (event == 'save') {
+        await this.saveEduTextbook(params, this.validateForm.valid && opinionsVrifly && authorSignVrifly);
+        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();
@@ -100,22 +269,14 @@ export class AttachmentComponent implements OnInit {
       });
       this.msg.warning('请填写完整信息');
     }
-    if (event == 'pre') {
-      this.state.emit('pre');
-    }
+    await this.saveEduTextbook(params, this.validateForm.valid && opinionsVrifly && authorSignVrifly);
     if (event == 'save') {
       this.modal.success({
         nzTitle: '您已填写完成',
         nzContent: '<p>已保存并且至空间</p>',
-        nzOnOk: () => console.log('Info OK')
+        nzOnOk: () => console.log('Info OK'),
       });
     }
-    if(event == 'complete')
-    this.modal.success({
-      nzTitle: '您已填写完成',
-      nzContent: '<p>已保存并且至空间</p>',
-      nzOnOk: () => console.log('Info OK')
-    });
   }
   changeCode() {}
   getCode(e: any) {}
@@ -146,9 +307,33 @@ export class AttachmentComponent implements OnInit {
   onDel(type: string, idx: number) {
     switch (type) {
       case 'opinions':
+        if (this.opinions.length <= 1) {
+          this.opinions = [
+            {
+              name: '', //作者
+              unit: '', //单位
+              birth: '', //出生年月
+              nationality: '', //国籍
+              reviewFile: '', //作者政治审查表/作者签名
+            },
+          ];
+          return;
+        }
         this.opinions.splice(idx, 1);
         break;
       case 'authorSign':
+        if (this.authorSign.length <= 1) {
+          this.authorSign = [
+            {
+              name: '', //作者
+              unit: '', //单位
+              birth: '', //出生年月
+              nationality: '', //国籍
+              reviewFile: '', //作者政治审查表/作者签名
+            },
+          ];
+          return;
+        }
         this.authorSign.splice(idx, 1);
         break;
     }
@@ -163,4 +348,44 @@ export class AttachmentComponent implements OnInit {
       this.msg.error(`${info.file.name} file upload failed.`);
     }
   }
+
+  async saveEduTextbook(params: any, isComplete: boolean) {
+    console.log(params);
+    if (!this.eduTextbook) {
+      this.msg.error('请先创建教材');
+      return;
+    }
+    //如果填写未完整,仅保存,状态修改待完善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,
+    });
+    params.textbookTypes &&
+      this.eduTextbook?.set('textbookTypes', params.textbookTypes);
+    params.textbookFiles &&
+      this.eduTextbook?.set('textbookFiles', params.textbookFiles);
+    let links = params.links.split(/[(\r\n)\r\n]+/);
+    links && this.eduTextbook?.set('links', links);
+    params.selfResults &&
+      this.eduTextbook?.set('selfResults', params.selfResults);
+    params.unitMaterial &&
+      this.eduTextbook?.set('unitMaterial', params.unitMaterial);
+    params.expertOpinion &&
+      this.eduTextbook?.set('expertOpinion', params.expertOpinion);
+    params.evidence && this.eduTextbook?.set('evidence', params.evidence);
+    params.moreMaterial &&
+      this.eduTextbook?.set('moreMaterial', params.moreMaterial);
+    params.accept && this.eduTextbook?.set('accept', params.accept);
+    this.opinions && this.eduTextbook?.set('opinions', this.opinions);
+    this.authorSign && this.eduTextbook?.set('authorSign', this.authorSign);
+    await this.eduTextbook?.save();
+    return;
+  }
 }

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

@@ -164,7 +164,7 @@
             @for(lang of selectLang; track lang.lang;let index = $index){
             <nz-option
               nzCustomContent
-              [nzValue]="lang.lang"
+              [nzValue]="lang.name"
               [nzLabel]="lang.name"
               >{{ lang.name }}</nz-option
             >

+ 5 - 2
projects/textbook/src/modules/nav-author/components/basic-in/basic-in.component.ts

@@ -5,6 +5,7 @@ import { NzSelectModule } from 'ng-zorro-antd/select';
 import { ReactiveFormsModule } from '@angular/forms';
 import { NzRadioModule } from 'ng-zorro-antd/radio';
 import { NzUploadModule } from 'ng-zorro-antd/upload';
+import { NzTagModule } from 'ng-zorro-antd/tag';
 import { NzMessageService } from 'ng-zorro-antd/message';
 import { NzUploadChangeParam } from 'ng-zorro-antd/upload';
 import { NzModalService } from 'ng-zorro-antd/modal';
@@ -24,6 +25,7 @@ import {
     NzSelectModule,
     NzRadioModule,
     NzUploadModule,
+    NzTagModule
   ],
   standalone: true,
   templateUrl: './basic-in.component.html',
@@ -73,7 +75,7 @@ export class BasicInComponent implements OnInit {
     author: ['', [Validators.required]],
     unit: ['', [Validators.required]],
     type: ['', [Validators.required]],
-    typeNumber: [''],
+    typeNumber: [1],
     majorPoniter: ['', [Validators.required]],
     lang: ['', [Validators.required]],
     authors: ['', [Validators.required]],
@@ -162,7 +164,7 @@ export class BasicInComponent implements OnInit {
       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]],
+      typeNumber: [this.eduTextbook?.get('typeNumber') || 1, [Validators.required]],
   
       majorPoniter: [this.eduTextbook?.get('majorPoniter') || '', [Validators.required]],
       lang: [this.eduTextbook?.get('lang') || '', [Validators.required]],
@@ -292,6 +294,7 @@ export class BasicInComponent implements OnInit {
     //如果填写未完整,仅保存,状态修改待完善101
     if(this.eduTextbook.get('status') == '102' && !isComplete){
       this.eduTextbook?.set('status', '101');
+      this.eduTextbook.set('complete', false)
     }else if(!this.eduTextbook.get('status')){
       this.eduTextbook?.set('status', '101');
     }

+ 30 - 28
projects/textbook/src/modules/nav-author/components/page-textbook/page-textbook.component.ts

@@ -1,50 +1,52 @@
-import { Component, OnInit, ViewChild } from '@angular/core';
+import { Component, OnInit, ViewChild, Input } from '@angular/core';
 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 * as Parse from 'parse';
 import { CommonModule } from '@angular/common';
 @Component({
   selector: 'app-page-textbook',
   templateUrl: './page-textbook.component.html',
   styleUrls: ['./page-textbook.component.scss'],
-  imports: [CommonModule,RouterOutlet,CompTableListComponent],
+  imports: [CommonModule, RouterOutlet, CompTableListComponent],
   standalone: true,
 })
 export class PageTextbookComponent implements OnInit {
-  @ViewChild(CompTableListComponent) list:CompTableListComponent|undefined
+  @ViewChild(CompTableListComponent) list: CompTableListComponent | undefined;
+  @Input('discard') discard: boolean = false;
+  @Input('render') render: boolean = false;
 
-  EduTextbook = EduTextbook
-  user:Parse.User|undefined
-  className:string|undefined
-  queryParams:any|undefined
-  fieldsArray:Array<any>|undefined
+  EduTextbook = EduTextbook;
+  user: Parse.User | undefined;
+  className: string | undefined;
+  queryParams: any | undefined;
+  fieldsArray: Array<any> | undefined;
 
   constructor(
     private router: Router,
-    private activeRoute: ActivatedRoute,
-    // private translate:TranslateService,
-  ) {
+    private activeRoute: ActivatedRoute
+  ) // private translate:TranslateService,
+  {
     this.user = Parse.User.current();
-    this.className = this.EduTextbook.className
-    this.fieldsArray = this.EduTextbook.fieldsArray
-    this.queryParams = {where:{
-      // user:this.user?.toPointer(),
-      isDeleted:{$ne:true},
-    }}
+    this.className = this.EduTextbook.className;
+    this.fieldsArray = this.EduTextbook.fieldsArray;
+    this.queryParams = {
+      where: {
+        isDeleted: { $ne: true },
+        discard: this.discard ? { $eq: true } : { $ne: true },
+        render: this.render ? { $eq: true } : { $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()
-    });
+    console.log(this.discard);
+    console.log(this.render);
+    this.queryParams.where = {
+      isDeleted: { $ne: true },
+      discard: this.discard ? { $eq: true } : { $ne: true },
+      render: this.render ? { $eq: true } : { $ne: true },
+    };
   }
-
 }

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

@@ -81,7 +81,7 @@
             <td>
               <input
                 nz-input
-                type="number"
+                type="text"
                 placeholder="请输入所获奖项"
                 [ngModelOptions]="{ standalone: true }"
                 [(ngModel)]="data.accolade"

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

@@ -15,6 +15,7 @@ import {
   NonNullableFormBuilder,
   Validators,
 } from '@angular/forms';
+import { textbookServer } from '../../../../services/textbook';
 interface course {
   date: Date|any,
   wordage: number|any,
@@ -39,7 +40,7 @@ interface course {
   styleUrls: ['./textbook-content.component.scss'],
 })
 export class TextbookContentComponent  implements OnInit {
-  @Input('eduTextbook') editFrom: any;
+  @Input('eduTextbook') eduTextbook: any;
   @Input('maxWidth') maxWidth: number = 0;
   @Output() state: EventEmitter<any> = new EventEmitter<any>();
   @Output() save: EventEmitter<any> = new EventEmitter<any>();
@@ -61,17 +62,50 @@ export class TextbookContentComponent  implements OnInit {
     },
   ];
   constructor(
+    public tbookSer: textbookServer,
     private fb: NonNullableFormBuilder,
     private modal: NzModalService,
     private msg: NzMessageService
   ) { }
 
-  ngOnInit() {}
-  submitForm(event?: string): void {
+  ngOnInit() {
+    if (this.eduTextbook.id) {
+      this.validateForm = this.fb.group({
+        innovateExplain: [this.eduTextbook.get('innovateExplain'), [Validators.required]],
+        influence: [this.eduTextbook.get('influence'), [Validators.required]],
+      });
+      console.log(this.validateForm.value);
+      this.courses = this.eduTextbook.get('courses') || this.courses
+    }
+  }
+  async submitForm(event?: string): Promise<void> {
+    if (event == 'pre') {
+      this.state.emit({ type: 'pre' });
+      return
+    }
     console.log(this.validateForm.value);
+    let coursesVrifly = !this.courses.some(item=>Object.values(item).some(val=> val == '' || val == undefined))
     if (this.validateForm.valid) {
-      console.log(this.validateForm.value);
+      let params: any = this.validateForm.value;
+      if (event == 'next') {
+        if(!coursesVrifly){
+          this.msg.warning('申报教材建设历程填写不完整')
+          return
+        }
+        await this.saveEduTextbook(params, true);
+        this.state.emit({ type: 'next', textBook: this.eduTextbook });
+      }
     } else {
+      if (event == 'save') {
+        let params: any = this.validateForm.value;
+        await this.saveEduTextbook(params, (this.validateForm.valid && coursesVrifly));
+        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();
@@ -80,18 +114,15 @@ export class TextbookContentComponent  implements OnInit {
       });
       this.msg.warning('请填写完整信息');
     }
-    if (event == 'pre') {
-      this.state.emit('pre');
-    }
-    if (event == 'next') {
-      this.state.emit('next');
+    if (event == 'save') {
+      let params = this.validateForm.value;
+      await this.saveEduTextbook(params, (this.validateForm.valid && coursesVrifly));
+      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) {}
@@ -109,4 +140,30 @@ export class TextbookContentComponent  implements OnInit {
   onDel(idx: number) {
     this.courses.splice(idx, 1);
   }
+
+  async saveEduTextbook(params: any, isComplete: boolean) {
+    console.log(params);
+    if (!this.eduTextbook) {
+      this.msg.error('请先创建教材');
+      return;
+    }
+    //如果填写未完整,仅保存,状态修改待完善101
+    if (this.eduTextbook.get('status') == '102' && !isComplete) {
+      this.eduTextbook?.set('status', '101');
+      this.eduTextbook.set('complete', false)
+    } 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,
+    });
+    params.innovateExplain && this.eduTextbook?.set('innovateExplain', params.innovateExplain);
+    params.influence && this.eduTextbook?.set('influence', params.influence);
+    this.eduTextbook?.set('courses', this.courses);
+    await this.eduTextbook?.save();
+    return;
+  }
 }

+ 66 - 12
projects/textbook/src/modules/nav-author/components/textbook-pertain/textbook-pertain.component.html

@@ -9,7 +9,12 @@
       <div nz-row>
         <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
+              class="label"
+              [nzNoColon]="true"
+              [nzSm]="16"
+              [nzXs]="16"
+              nzRequired
               >适用专业代码(六位)及名称</nz-form-label
             >
             <nz-form-control
@@ -38,7 +43,12 @@
             </nz-form-control>
           </nz-form-item>
           <nz-form-item class="row" style="margin-bottom: 16px">
-            <nz-form-label class="label" [nzNoColon]="true" [nzSm]="8" [nzXs]="8" nzRequired
+            <nz-form-label
+              class="label"
+              [nzNoColon]="true"
+              [nzSm]="8"
+              [nzXs]="8"
+              nzRequired
               >课程学时</nz-form-label
             >
             <nz-form-control
@@ -63,7 +73,12 @@
         </div>
         <div nz-col nzSpan="12">
           <nz-form-item class="row" style="margin-bottom: 16px">
-            <nz-form-label class="label" [nzNoColon]="true" [nzSm]="6" [nzXs]="6" nzRequired
+            <nz-form-label
+              class="label"
+              [nzNoColon]="true"
+              [nzSm]="6"
+              [nzXs]="6"
+              nzRequired
               >适用课程</nz-form-label
             >
             <nz-form-control
@@ -80,7 +95,12 @@
             </nz-form-control>
           </nz-form-item>
           <nz-form-item class="row" style="margin-bottom: 16px">
-            <nz-form-label class="label" [nzNoColon]="true" [nzSm]="6" [nzXs]="6" nzRequired
+            <nz-form-label
+              class="label"
+              [nzNoColon]="true"
+              [nzSm]="6"
+              [nzXs]="6"
+              nzRequired
               >适用课程性质</nz-form-label
             >
             <nz-form-control
@@ -99,7 +119,17 @@
     </div>
     <div class="author-content">
       <div class="nav">作者信息</div>
-      <div class="title">作者(含主编,不超过 6 人,教材中明确出现姓名)</div>
+      <nz-form-label
+        class="title"
+        [nzNoColon]="true"
+        [nzSm]="24"
+        [nzXs]="24"
+        nzRequired
+      >
+        <span style="font-size: 16px">
+          作者(含主编,不超过 6 人,教材中明确出现姓名)
+        </span>
+      </nz-form-label>
       <nz-table
         #basicTable
         [nzData]="authorList"
@@ -220,7 +250,7 @@
                   nzTheme="outline"
                 ></span
               ></a>
-              <a (click)="onDel('authorList',index)"
+              <a (click)="onDel('authorList', index)"
                 ><span
                   nz-icon
                   style="font-size: 20px"
@@ -237,7 +267,15 @@
     <div class="author-content">
       <div class="nav">第一主编(作者)情况</div>
       <nz-form-item class="row" style="margin-bottom: 16px">
-        <div class="title">相关教学经历</div>
+        <nz-form-label
+          class="title"
+          [nzNoColon]="true"
+          [nzSm]="24"
+          [nzXs]="24"
+          nzRequired
+        >
+          <span style="font-size: 16px"> 相关教学经历 </span>
+        </nz-form-label>
         <nz-form-control
           class="val"
           nzErrorTip="请输入第一主编(作者)承担学校教学任务、开展教学研究情况、教材编写情况以及取得的教学成果"
@@ -253,7 +291,17 @@
       </nz-form-item>
     </div>
     <div class="author-content">
-      <div class="title">相关科学研究项目、成果或论文专著(限5项)</div>
+      <nz-form-label
+        class="title"
+        [nzNoColon]="true"
+        [nzSm]="24"
+        [nzXs]="24"
+        nzRequired
+      >
+        <span style="font-size: 16px">
+          相关科学研究项目、成果或论文专著(限5项)
+        </span>
+      </nz-form-label>
       <nz-table
         #basicTable
         [nzData]="achievementOptions"
@@ -269,7 +317,8 @@
           </tr>
         </thead>
         <tbody>
-          @for (data of achievementOptions; track data.name;let index = $index) {
+          @for (data of achievementOptions; track data.name;let index = $index)
+          {
           <tr>
             <td nzLeft nzAlign="right">{{ index + 1 }}</td>
             <td nzLeft>
@@ -298,7 +347,7 @@
               ></nz-date-picker>
             </td>
             <td nzRight>
-              <a (click)="onPush('achievementOptions',index)"
+              <a (click)="onPush('achievementOptions', index)"
                 ><span
                   nz-icon
                   style="font-size: 20px; margin-right: 10px"
@@ -306,7 +355,7 @@
                   nzTheme="outline"
                 ></span
               ></a>
-              <a (click)="onDel('achievementOptions',index)"
+              <a (click)="onDel('achievementOptions', index)"
                 ><span
                   nz-icon
                   style="font-size: 20px"
@@ -339,7 +388,12 @@
   >
     上一页
   </button>
-  <button nz-button nzType="primary" style="background: #3e49b3; border: 1px #3e49b3" (click)="submitForm('next')">
+  <button
+    nz-button
+    nzType="primary"
+    style="background: #3e49b3; border: 1px #3e49b3"
+    (click)="submitForm('next')"
+  >
     下一页
   </button>
 </div>

+ 63 - 39
projects/textbook/src/modules/nav-author/components/textbook-pertain/textbook-pertain.component.ts

@@ -48,7 +48,7 @@ interface achievementType {
   styleUrls: ['./textbook-pertain.component.scss'],
 })
 export class TextbookPertainComponent implements OnInit {
-  @Input('eduTextbook') eduTextbook: Parse.Object|any;
+  @Input('eduTextbook') eduTextbook: Parse.Object | any;
 
   @Input('maxWidth') maxWidth: number = 0;
   @Output() state: EventEmitter<any> = new EventEmitter<any>();
@@ -136,41 +136,63 @@ export class TextbookPertainComponent implements OnInit {
 
   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(';')
+    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]],
+        characteristic: [
+          this.eduTextbook.get('characteristic') || '',
+          [Validators.required],
+        ],
+        authorDetails: [
+          this.eduTextbook.get('authorDetails') || '',
+          [Validators.required],
+        ],
       });
+      this.authorList = this.eduTextbook.get('authorList') || this.authorList
+      this.achievementOptions = this.eduTextbook.get('achievementOptions') || this.authorList
     }
-
   }
-  async submitForm(event?: string):Promise<void>{
+  async submitForm(event?: string): Promise<void> {
+    if (event == 'pre') {
+      this.state.emit({ type: 'pre' });
+      return
+    }
     console.log(this.validateForm.value);
+    let authorListVrifly = !this.authorList.some(item=>Object.values(item).some(val=> val == '' || val == undefined))
+    let achievementOptionsVrifly = !this.achievementOptions.some(item=>Object.values(item).some(val=> val == '' || val == undefined))
+    console.log(authorListVrifly, achievementOptionsVrifly);
+
     if (this.validateForm.valid) {
-      let params = this.validateForm.value
+      let params: any = this.validateForm.value;
       if (event == 'next') {
-        await this.saveEduTextbook(params, this.validateForm.valid)
-        this.state.emit({type:'next',textBook:this.eduTextbook});
+        if(!authorListVrifly){
+          this.msg.warning('作者信息填写不完整')
+          return
+        }else if(!achievementOptionsVrifly){
+          this.msg.warning('相关科学研究项目、成果或论文专著填写不完整')
+          return
+        }
+        await this.saveEduTextbook(params, true);
+        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)
+      if (event == 'save') {
+        let params: any = this.validateForm.value;
+        await this.saveEduTextbook(params, (this.validateForm.valid && authorListVrifly && achievementOptionsVrifly));
         this.modal.success({
           nzTitle: '保存成功',
           nzContent: '<p>已保存并且至空间</p>',
-          nzOnOk: () => console.log('Info OK')
+          nzOnOk: () => console.log('Info OK'),
         });
-        return
+        return;
       }
       Object.values(this.validateForm.controls).forEach((control) => {
         if (control.invalid) {
@@ -180,13 +202,13 @@ export class TextbookPertainComponent implements OnInit {
       });
       this.msg.warning('请填写完整信息');
     }
-    if(event == 'save'){
-      let params = this.validateForm.value
-      await this.saveEduTextbook(params, this.validateForm.valid)
+    if (event == 'save') {
+      let params = this.validateForm.value;
+      await this.saveEduTextbook(params, (this.validateForm.valid && authorListVrifly && achievementOptionsVrifly));
       this.modal.success({
         nzTitle: '保存成功',
         nzContent: '<p>已保存并且至空间</p>',
-        nzOnOk: () => console.log('Info OK')
+        nzOnOk: () => console.log('Info OK'),
       });
     }
   }
@@ -197,7 +219,7 @@ export class TextbookPertainComponent implements OnInit {
   onPush(type: string, idx: number) {
     switch (type) {
       case 'authorList':
-        this.authorList.splice(idx+1, 0, {
+        this.authorList.splice(idx + 1, 0, {
           name: '',
           unit: '',
           birth: '',
@@ -214,7 +236,7 @@ export class TextbookPertainComponent implements OnInit {
           this.msg.warning('最多添加5条');
           return;
         }
-        this.achievementOptions.splice(idx+1, 0, {
+        this.achievementOptions.splice(idx + 1, 0, {
           name: '',
           unit: '',
           date: '',
@@ -260,18 +282,19 @@ export class TextbookPertainComponent implements OnInit {
     }
   }
 
-  async saveEduTextbook(params: any, isComplete:boolean){
+  async saveEduTextbook(params: any, isComplete: boolean) {
     console.log(params);
-    if(!this.eduTextbook){
-      this.msg.error('请先创建教材')
-      return
+    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){
+    if (this.eduTextbook.get('status') == '102' && !isComplete) {
       this.eduTextbook?.set('status', '101');
-    }else if(!this.eduTextbook.get('status')){
+      this.eduTextbook.set('complete', false)
+    } else if (!this.eduTextbook.get('status')) {
       this.eduTextbook?.set('status', '101');
     }
     this.eduTextbook?.set('user', Parse.User.current()?.toPointer());
@@ -280,15 +303,16 @@ export class TextbookPertainComponent implements OnInit {
       className: 'Company',
       objectId: this.tbookSer.company,
     });
-    let major = this.selectList.find(item=> item.code == params.major)
-    let lessons = params.lessons.split(';')
+    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);
-
+    lessons && this.eduTextbook?.set('lessons', lessons);
+    params.characteristic && this.eduTextbook?.set('characteristic', params.characteristic);
+    params.authorDetails && this.eduTextbook?.set('authorDetails', params.authorDetails);
+    this.eduTextbook?.set('authorList', this.authorList);
+    this.eduTextbook?.set('achievementOptions', this.achievementOptions);
     await this.eduTextbook?.save();
-    return
+    return;
   }
 }

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

@@ -12,6 +12,6 @@
     </div>
   </div>
   <div class="space-content">
-    <app-page-textbook></app-page-textbook>
+    <app-page-textbook [discard]="true"></app-page-textbook>
   </div>
 </div>

+ 8 - 4
projects/textbook/src/modules/nav-author/space/space.component.html

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

+ 8 - 6
projects/textbook/src/modules/nav-author/space/space.component.ts

@@ -4,6 +4,7 @@ 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';
+import { textbookServer } from '../../../services/textbook';
 @Component({
   selector: 'app-space',
   standalone: true,
@@ -13,17 +14,18 @@ import { PageTextbookComponent } from '../components/page-textbook/page-textbook
 })
 export class SpaceComponent implements OnInit {
   user: Parse.Object = Parse.User.current()!;
+  active:number = 0
 
-  constructor(private router: Router) {}
+  constructor(private router: Router, public tbookSer: textbookServer) {}
 
   ngOnInit() {}
 
-  goUrl(url:string,params?:object|any){
+  goUrl(url: string, params?: object | any) {
     console.log(url);
-    if(params){
-      this.router.navigate([url,params])
-    }else{
-      this.router.navigate([url])
+    if (params) {
+      this.router.navigate([url, params]);
+    } else {
+      this.router.navigate([url]);
     }
   }
 }

+ 29 - 12
projects/textbook/src/modules/nav-author/textbook-details/textbook-details.component.html

@@ -31,7 +31,7 @@
           </div>
           <div class="row">
             <div class="label">申报类型</div>
-            <div class="value">{{textBook.type}}</div>
+            <div class="value">{{textBook.type}} {{textBook.type == '全册' ? textBook.typeNumber + '册': ''}}</div>
           </div>
           <div class="row">
             <div class="label">教材应用对象及所属学科专业类</div>
@@ -55,7 +55,7 @@
           </div>
           <div class="row">
             <div class="label">是否为重点立项教材</div>
-            <div class="value">{{textBook.approval}}</div>
+            <div class="value">{{textBook.approval ? '是否' : '否'}}</div>
           </div>
           <div class="row">
             <div class="label">出版单位</div>
@@ -63,7 +63,7 @@
           </div>
           <div class="row">
             <div class="label">初版时间</div>
-            <div class="value">{{textBook.editionFirst | date :'yyyy-MM'}}</div>
+            <div class="value">{{textBook.editionFirst?.iso | date :'yyyy-MM'}}</div>
           </div>
           <div class="row">
             <div class="label">载体形式</div>
@@ -71,11 +71,11 @@
           </div>
           <div class="row">
             <div class="label">本版出版时间及版次</div>
-            <div class="value">{{textBook.editionDate | date :'yyyy-MM'}}/{{textBook.editionNumber}}</div>
+            <div class="value">{{textBook.editionDate?.iso | 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 class="value">{{textBook.printDate?.iso | date :'yyyy-MM'}}/{{textBook.printNumber}}</div>
           </div>
           <div class="row">
             <div class="label">初版以来合计印数</div>
@@ -87,11 +87,11 @@
           </div>
           <div class="row">
             <div class="label">版权页截图</div>
-            <div class="value">{{textBook.copyrightImgUrl}}</div>
+            <div class="value"><a href="textBook.copyrightImgUrl">截图文件</a></div>
           </div>
           <div class="row">
             <div class="label">中国版本图书馆 CIP 查询截图</div>
-            <div class="value">{{textBook.CIPImgUrl}}</div>
+            <div class="value"><a href="textBook.CIPImgUrl">查询截图</a></div>
           </div>
         </div>
       </div>
@@ -112,7 +112,12 @@
           </div>
           <div class="row">
             <div class="label">适用课程性质</div>
-            <div class="value">{{textBook.characteristic}}</div>
+            <div class="value">
+              @for (tag of textBook.characteristic; track tag) {
+                @if (tag.checked){
+                  <nz-tag>{{tag.label}}</nz-tag>
+                }
+              }</div>
           </div>
         </div>
       </div>
@@ -155,7 +160,7 @@
                   {{ data.unit }}
                 </td>
                 <td>
-                  {{ data.birth | date : "yyyy-MM" }}
+                  {{ data.birth?.iso | date : "yyyy-MM" }}
                 </td>
                 <td>
                   {{ data.nationality }}
@@ -217,7 +222,7 @@
                   {{ data.unit }}
                 </td>
                 <td>
-                  {{ data.date | date : "yyyy-MM" }}
+                  {{ data.date?.iso | date : "yyyy-MM" }}
                 </td>
               </tr>
               }
@@ -252,7 +257,7 @@
               <tr>
                 <td nzLeft nzAlign="right">{{ index + 1 }}</td>
                 <td>
-                  {{ data.date | date : "yyyy-MM" }}
+                  {{ data.date?.iso | date : "yyyy-MM" }}
                 </td>
                 <td>
                   {{ data.wordage }}
@@ -421,7 +426,7 @@
                   {{ data.unit }}
                 </td>
                 <td>
-                  {{ data.birth | date : "yyyy-MM" }}
+                  {{ data.birth?.iso | date : "yyyy-MM" }}
                 </td>
                 <td>
                   {{ data.nationality }}
@@ -495,3 +500,15 @@
     </div>
   </div>
 </div>
+@if (!textBook.discard && !textBook.render) {
+  <div class="footer">
+    <button
+      nz-button
+      nzType="primary"
+      style="background: #3e49b3; border: 1px #3e49b3"
+      (click)="edit()"
+    >
+    编辑教材
+    </button>
+  </div>
+}

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

@@ -83,4 +83,13 @@
 }
 .mar10{
   margin: 20px 0;
+}
+.footer{
+  display: flex;
+  margin: 10px auto;
+  align-items: center;
+  justify-content: space-evenly;
+  // width: 200px;
+  justify-content: end;
+  padding-right: 100px;
 }

+ 165 - 150
projects/textbook/src/modules/nav-author/textbook-details/textbook-details.component.ts

@@ -8,7 +8,7 @@ import {
   ElementRef,
 } 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';
@@ -16,6 +16,7 @@ import { TextbookContentComponent } from '../components/textbook-content/textboo
 import { AttachmentComponent } from '../components/attachment/attachment.component';
 import { NzAnchorModule } from 'ng-zorro-antd/anchor';
 import { DatePipe } from '@angular/common';
+import Parse from 'parse';
 
 interface author {
   name: string;
@@ -47,163 +48,174 @@ interface author {
 })
 export class TextbookDetailsComponent implements OnInit {
   @ViewChild('templ1') templ1: any;
+  textBook: object | any = {}
+  // {
+  //   title: '', //申报教材名称
+  //   ISBN: '', //国际标准书号
+  //   author: '', //第一主编(作者)
+  //   unit: '', //第一主编(作者)单位
+  //   type: '', //申报类型
+  //   typeNumber: '', //全册次数
 
-  textBook: object | any = {
-    title: '', //申报教材名称
-    ISBN: '', //国际标准书号
-    author: '', //第一主编(作者)
-    unit: '', //第一主编(作者)单位
-    type: '', //申报类型
-    typeNumber: '', //全册次数
+  //   majorPoniter: '', //教材应用对象及所诉学科专业类
+  //   lang: '', //教材主要语种类型
+  //   authors: '', //其他主编姓名
+  //   editor: '', //其他编者姓名
 
-    majorPoniter: '', //教材应用对象及所诉学科专业类
-    lang: '', //教材主要语种类型
-    authors: '', //其他主编姓名
-    editor: '', //其他编者姓名
+  //   approval: '', //是否为重点立项教材
+  //   editionUnit: '', //出版单位
+  //   editionFirst: '', //初版时间
+  //   carrierShape: '', //载体形式
 
-    approval: '', //是否为重点立项教材
-    editionUnit: '', //出版单位
-    editionFirst: '', //初版时间
-    carrierShape: '', //载体形式
+  //   editionDate: '', //出版时间
+  //   editionNumber: '', //出版版次
+  //   printDate: '', //最新印次时间
+  //   printNumber: '', //最新印次
 
-    editionDate: '', //出版时间
-    editionNumber: '', //出版版次
-    printDate: '', //最新印次时间
-    printNumber: '', //最新印次
+  //   printSum: '', //初版以来合计印次
 
-    printSum: '', //初版以来合计印次
+  //   importantProject: '', //初版以来是否列为重点项目
+  //   importantProjectOther: '', //其他省部级及以上项目
 
-    importantProject: '', //初版以来是否列为重点项目
-    importantProjectOther: '', //其他省部级及以上项目
+  //   copyrightImgUrl: '', //版权页截图
+  //   CIPImgUrl: '', //中国版本图书馆CIP查询截图
+  //   major:{ //适用专业代码(六位)及名称
+  //     code:'000416',
+  //     name:'通信工程'
+  //   },
+  //   lessons:[],
+  //   characteristic:[],
+  //   period:1,
 
-    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(private router: Router, private activeRoute: ActivatedRoute) {}
 
-    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() {}
+  ngOnInit() {
+    this.activeRoute.paramMap.subscribe(async (params) => {
+      let id = params.get('id');
+      if (id) {
+        let query = new Parse.Query('EduTextbook');
+        query.equalTo('objectId', id);
+        let r = await query.first();
+        this.textBook = r?.toJSON()
+        console.log(this.textBook);
+      }
+    });
+  }
 
   handleClick(e: string): void {
     console.log(e);
@@ -213,4 +225,7 @@ export class TextbookDetailsComponent implements OnInit {
   back() {
     history.back();
   }
+  edit(){
+    this.router?.navigate(['/nav-author/manage/apply',{id:this.textBook.objectId}],{ replaceUrl: true })
+  }
 }

+ 96 - 1
projects/textbook/src/schemas/EduTextbook.ts

@@ -23,10 +23,105 @@ export const EduTextbook:ParseSchema = {
                 options.router?.navigate(['/nav-author/manage/apply',{id:options.object.id}])
             }
         },
+        {
+            name:"提交材料",
+            place:"item",
+            show:(options:{object:Parse.Object})=>{
+                if(location?.pathname=='/nav-author/manage/space' && !options.object.get('render')){
+                    return true
+                }
+                return false
+            },
+            handle:(options:{dialog:MatDialog,object:Parse.Object,router?:Router,modal:any})=>{
+                options.modal?.confirm({
+                    nzTitle: '你确定提交吗?',
+                    nzContent: '<p>提交后不可撤回,你可以在已提交评审教材中查看</p>',
+                    nzOkText: '确认',
+                    nzOkType: 'primary',
+                    nzOkDanger: true,
+                    nzOnOk:async () => {
+                        options.object.set('render',true)
+                        await options.object.save()
+                        history.go(0)
+                    },
+                    nzCancelText: '取消',
+                    nzOnCancel: () => console.log('Cancel')
+                  });
+            }
+        },
+        {
+            name:"删除",
+            place:"item",
+            show:(options:{object:Parse.Object})=>{
+                if(location?.pathname=='/nav-author/manage/space'){
+                    return true
+                }
+                return false
+            },
+            handle:(options:{dialog:MatDialog,object:Parse.Object,router?:Router,modal?:any})=>{
+                options.modal?.confirm({
+                    nzTitle: '你确定删除吗?',
+                    nzContent: '<p>删除后你可以在回收站恢复</p>',
+                    nzOkText: '确认',
+                    nzOkType: 'primary',
+                    nzOkDanger: true,
+                    nzOnOk:async () => {
+                        options.object.set('discard',true)
+                        await options.object.save()
+                        history.go(0)
+                    },
+                    nzCancelText: '取消',
+                    nzOnCancel: () => console.log('Cancel')
+                  });
+            }
+        },
+        {
+            name:"恢复",
+            place:"item",
+            show:(options:{object:Parse.Object})=>{
+                if(location?.pathname=='/nav-author/manage/recycle' && options.object.get('discard')){
+                    return true
+                }
+                return false
+            },
+            handle:(options:{dialog:MatDialog,object:Parse.Object,router?:Router,modal?:any})=>{
+                options.modal?.confirm({
+                    nzTitle: '你确定恢复吗?',
+                    nzContent: '<p>恢复后你可以在个人空间中查看</p>',
+                    nzOkText: '确认',
+                    nzOkType: 'primary',
+                    nzOkDanger: true,
+                    nzOnOk:async () => {
+                        options.object.set('discard',false)
+                        await options.object.save()
+                        history.go(0)
+                    },
+                    nzCancelText: '取消',
+                    nzOnCancel: () => console.log('Cancel')
+                  });
+            }
+        },
+        {
+            name:"预览材料",
+            place:"item",
+            show:(options:{object:Parse.Object})=>{
+                if((location?.pathname=='/nav-author/manage/space' && options.object.get('render')) || location?.pathname=='/nav-author/manage/recycle'){
+                    return true
+                }
+                return false
+            },
+            handle:(options:{dialog:MatDialog,object:Parse.Object,router?:Router})=>{
+                options.router?.navigate(['/nav-author/manage/dateils',{id:options.object.id}])
+            }
+        },
     ],
     fieldsArray:[
         {key:"title",name:"教材名称",type:"String",isHeader:true},
-        {key:"desc",name:"教材描述",type:"String"},
+        {key:"typeNumber",name:"册数",type:"Number",isHeader:true},
+        {key:"author",name:"第一主编 / 作者",type:"String",isHeader:true},
+        {key:"major",name:"所属本科专业",type:"Object",isHeader:true,showName:"${name}"},
+        {key:"lang",name:"主要语种类型",type:"String",isHeader:true},
+        {key:"ISBN",name:"ISBN",type:"String",isHeader:true},
         {key:"user",name:"创建人",type:"Pointer",targetClass:"_User",isHeader:true,showName:"${mobile}"},
     ]
 }

+ 61 - 27
projects/textbook/src/services/auth.service.ts

@@ -29,37 +29,71 @@ export class AuthServr {
     private http: HttpClient,
     private message: NzMessageService,
   ) {}
-  login(username: any, password: any, company: string) {
-    return new Promise(async (resolve, reject) => {
-      let a = /^1[3456789]\d{9}$/;
-      //如果是手机号登录,获取对应的mobile
-      if (String(username).match(a)) {
-        let query = new Parse.Query('_User');
-        query.equalTo('company', company);
-        query.equalTo('mobile', username);
-        let res = await query.first();
-        if (res?.id) {
-          username = res.get('username');
-        } else {
-          reject({ message: '用户不存在' });
-          return;
-        }
-      }
-      Parse.User.logIn(username, password)
-        .then(async (data: any) => {
-          console.log(data);
-          await this.profileVerify()
-          resolve(data);
+  //登录
+  login(id:string) {
+    return new Promise((resolve, reject) => {
+      let host =
+        (Parse as any).serverURL?.split('parse')?.[0] ||
+        'https://server.fmode.cn/';
+      this.http
+        .post(host + 'api/textbook/login', {
+          id:id
         })
-        .catch((err: any) => {
-          console.log(err.message);
-          if (err.message.indexOf('Invalid username/password.') != -1) {
-            reject({ message: '用户名或密码不正确' });
-          } else {
-            reject({ message: '用户名或密码不正确' });
+        .pipe(
+          catchError(async (e) => {
+            reject(e);
+          })
+        )
+        .subscribe((res: any) => {
+          console.log(res);
+          if (res?.code == 200) {
+            let token = res.data.token;
+            Parse.User.become(token)
+              .then(async (data: any) => {
+                console.log(data);
+                await this.profileVerify()
+                resolve(data)
+              })
+              .catch((err: any) => {
+                console.log(err.message);
+                if (err.message.indexOf('Invalid username/password.') != -1) {
+                  reject({ message: '用户名或密码不正确' });
+                } else {
+                  reject({ message: '用户名或密码不正确' });
+                }
+              });
           }
         });
     });
+    // return new Promise(async (resolve, reject) => {
+    //   let a = /^1[3456789]\d{9}$/;
+    //   if (String(username).match(a)) {
+    //     let query = new Parse.Query('_User');
+    //     query.equalTo('company', company);
+    //     query.equalTo('mobile', username);
+    //     let res = await query.first();
+    //     if (res?.id) {
+    //       username = res.get('username');
+    //     } else {
+    //       reject({ message: '用户不存在' });
+    //       return;
+    //     }
+    //   }
+    //   Parse.User.logIn(username, password)
+    //     .then(async (data: any) => {
+    //       console.log(data);
+    //       await this.profileVerify()
+    //       resolve(data);
+    //     })
+    //     .catch((err: any) => {
+    //       console.log(err.message);
+    //       if (err.message.indexOf('Invalid username/password.') != -1) {
+    //         reject({ message: '用户名或密码不正确' });
+    //       } else {
+    //         reject({ message: '用户名或密码不正确' });
+    //       }
+    //     });
+    // });
   }
   //手机号注册/登录
   register(mobile: any, code: any, company: string) {

+ 33 - 2
server/api/textbook/routes.js

@@ -13,20 +13,51 @@ router.use("/test", async (req, res, next) => {
     })
 })
 
+
+router.post("/login", async (req, res, next) => {
+    goWrong(res, "接口已停止维护");
+    return
+    let id = req.body.id;
+    if (!id) {
+        goWrong(res, "参数不完整,请检查");
+        return
+    }
+    // 检查用户信息
+    let query = new global.Parse.Query("_User");
+    query.equalTo("objectId", id);
+    let user = query.first({ useMasterKey: true });
+    if (user?.id) {
+        let token = await setMobileSessionToken(user)
+        res.json({
+            code: 200,
+            msg: '登录成功',
+            data: {
+                userId: user.id,
+                username: user.get("username"),
+                mobile: user.get("mobile"),
+                token: token?.get("sessionToken")
+            }
+        })
+        return
+    }
+    goWrong(res, "用户不存在,请先注册")
+})
+
+
 router.post("/register", async (req, res, next) => {
     let company = req.body.company;
     let mobile = req.body.mobile;
     let code = req.body.code;
     let password = req.body.password
     if (!company || !mobile || !code) {
-        goWrong(req, "参数不完整,请检查");
+        goWrong(res, "参数不完整,请检查");
         return
     }
     // 检查用户信息
     let user;
     user = await getUserByMobile(mobile, company);
     if (user) {
-        // goWrong(req, "用户已存在,请登录")
+        // goWrong(res, "用户已存在,请登录")
         let token = await setMobileSessionToken(user)
         res.json({
             code: 200,

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

@@ -15,10 +15,18 @@ const EduTextbook = {
             "type": "Boolean",
             "required": false
         },
+        "complete": { //是否填写完整
+            "type": "Boolean",
+            "required": false
+        },
         "isDeleted": {
             "type": "Boolean",
             "required": false
         },
+        "discard": { //删除至回收站
+            "type": "Boolean",
+            "required": false
+        },
         "title": {
             "type": "String",
             "required": false
@@ -128,7 +136,7 @@ const EduTextbook = {
             "required": false
         },
         "authorList": {
-            "type": "Object",
+            "type": "Array",
             "required": false
         },
         "authorDetails": {
@@ -187,9 +195,8 @@ const EduTextbook = {
             "type": "Object",
             "required": false
         },
-        "user": {
-            "type": "Pointer",
-            "targetClass":"_User",
+        "accept": {//填写承诺书
+            "type": "string",
             "required": false
         }
     },