浏览代码

管理员新增教材列表管理

warrior 5 月之前
父节点
当前提交
eddb0eeca9

+ 4 - 1
projects/textbook/src/app/app.routes.ts

@@ -4,6 +4,8 @@ import { CompUserComponent } from './comp-user/comp-user.component';
 import { ProfileComponent } from '../modules/user/profile/profile.component'
 import { CompManageComponent } from './comp-manage/comp-manage.component'
 import {PageHomeComponent} from '../modules/textbook/page-home/page-home.component'
+import { AuthGuard as superAuthGuard } from "../modules/nav-admin/auth.guard";
+
 export const routes: Routes = [
   { path: '', redirectTo:'user/login', pathMatch: "full",}, // 默认跳转到 ''
   // { path: '',loadComponent:()=>import('../modules/textbook/page-home/page-home.component').then(m=>m.PageHomeComponent) }, // 默认跳转到 ''
@@ -65,7 +67,8 @@ export const routes: Routes = [
     loadChildren: () =>import('../modules/nav-author/modules.routes').then((mod) => mod.NavAuthorRoutingModule),
   },
   {
-    path: 'test/upload', // 用户登录/注册
+    path: 'test/upload', // 私有上传测试
+    canActivate: mapToCanActivate([superAuthGuard]),
     loadComponent:()=> import('../app/comp-upload/example-upload/example-upload.component').then((mod) => mod.ExampleUploadComponent),
   }
 ];

+ 29 - 1
projects/textbook/src/app/textbook/textbook.component.html

@@ -471,6 +471,7 @@
         <th nzEllipsis nzWidth="120px">教材名称</th>
         }
         <th nzEllipsis nzWidth="50px">册数</th>
+        <th nzEllipsis nzWidth="70px">状态</th>
         <th nzEllipsis nzWidth="120px">第一主编/作者</th>
         <th nzEllipsis nzWidth="80px">所属单位</th>
         <th nzEllipsis nzWidth="120px">教材所属学科专业类</th>
@@ -582,6 +583,11 @@
             </div>
           </ng-template>
         </td>
+        <td
+          nzEllipsis
+        >
+          <nz-tag [nzColor]="getStatusColor(data?.get('status')).color">{{getStatusColor(data?.get("status")).text}}</nz-tag>
+        </td>
         <td
           nzEllipsis
           nz-popover
@@ -808,6 +814,18 @@
                 </button>
               </li>
               }
+              @if(filterObj.btns.changStatus && this.tbookSer.profile.identity === '国家级管理员'){
+                <li nz-menu-item>
+                  <button
+                    (click)="openStateModal(data)"
+                    nz-button
+                    nzType="link"
+                    style="color: #231c1f"
+                  >
+                    <span nz-icon nzType="retweet" nzTheme="outline"></span>变更状态
+                  </button>
+                </li>
+              }
             </ul>
           </nz-dropdown-menu>
           } @else { - }
@@ -918,7 +936,17 @@
   </div>
 </div>
 }
-
+<nz-modal nzOkDanger [(nzVisible)]="isVisible" nzTitle="你将变更教材状态(危险操作)" (nzOnCancel)="isVisible = false" (nzOnOk)="onChangeStatus()">
+  <ng-container *nzModalContent>
+    <div class="">当前状态 {{getStatusColor(currentStatuesParse?.get('status')).text}}</div>
+    <nz-radio-group [(ngModel)]="upStatus">
+      <label nz-radio nzValue="102">未提交</label>
+      <label nz-radio nzValue="200">已提交</label>
+      <label nz-radio nzValue="300">已退回</label>
+      <label nz-radio nzValue="400">已报送</label>
+    </nz-radio-group>
+  </ng-container>
+</nz-modal>
 <div class="loading" [hidden]="!showLoading">
   <nz-spin nzSimple [nzSize]="'large'"></nz-spin>
 </div>

+ 144 - 7
projects/textbook/src/app/textbook/textbook.component.ts

@@ -80,6 +80,7 @@ export class TextbookComponent implements OnInit {
       mark: false, //打分
       exportExcel:false, //导出表格
       uploadPDF:false, //教材作者诚信承诺上传
+      changStatus:false //变更状态(高危操作)
     },
   };
   @Input('scoreMap') scoreMap:any = {} //评分状态
@@ -242,7 +243,42 @@ export class TextbookComponent implements OnInit {
     }
     return j || '-';
   }
-
+  getStatusColor(status:string): any{
+    return {
+      '101':{
+        color:'red',
+        text:'填写中'
+      },
+      '102':{
+        color:'red',
+        text:'未提交'
+      },
+      '103':{
+        color:'orange',
+        text:'提交高校'
+      },
+      '200':{
+        color:'lime',
+        text:'已提交'
+      },
+      '201':{
+        color:'green',
+        text:'公示中'
+      },
+      '300':{
+        color:'gold',
+        text:'已退回'
+      },
+      '400':{
+        color:'geekblue',
+        text:'已报送'
+      },
+      "":{
+        color:'red',
+        text:'填写中'
+      }
+    }[status]
+  }
   constructor(
     public tbookSer: textbookServer,
     private route: Router,
@@ -255,7 +291,7 @@ export class TextbookComponent implements OnInit {
   ngOnInit() {
     this.activeRoute.paramMap.subscribe(async (params) => {
       // this.eduProcessId = params.get('id');
-      let arr = ['review', 'verify', 'eduReivew', 'mark', 'exportExcel', 'uploadPDF'];
+      let arr = ['review', 'verify', 'eduReivew', 'mark', 'exportExcel', 'uploadPDF','changStatus'];
       Object.keys(this.filterObj?.btns).forEach((key) => {
         if (this.filterObj[key] && !arr.includes(key)) this.calc += 70;
       });
@@ -389,7 +425,7 @@ export class TextbookComponent implements OnInit {
     this.filterObj?.contained && query.containedIn('objectId', this.filterObj.contained);
     query.descending('createdAt');
     query.notEqualTo('isDeleted', true);
-    if (!this.uid && !this.filterObj.team) {
+    if (!this.uid && !this.filterObj.team && !this.filterObj.btns?.changStatus) {
       query.equalTo('render', true);
     }
     if (this.filterObj?.status?.length > 0) {
@@ -884,14 +920,16 @@ export class TextbookComponent implements OnInit {
       nzOnCancel: () => console.log('Cancel'),
     });
   }
-  async getEduProcess(id: string): Promise<string | undefined> {
+  async getEduProcess(id: string, admin?:boolean): Promise<string | undefined> {
     if (!id) return;
     let query = new Parse.Query('EduProcess');
     query.equalTo('department', id);
-    query.lessThanOrEqualTo('startDate', new Date());
-    query.greaterThan('deadline', new Date());
+    if(!admin){
+      query.lessThanOrEqualTo('startDate', new Date());
+      query.greaterThan('deadline', new Date());
+      query.containedIn('status',['200', '300']);
+    }
     query.notEqualTo('isDeleted', true);
-    query.containedIn('status', ['200', '300']);
     query.select('objectId');
     let res = await query.first();
     return res?.id;
@@ -1161,4 +1199,103 @@ export class TextbookComponent implements OnInit {
     link.click();
     document.body.removeChild(link);
   }
+  
+  isVisible:boolean = false
+  upStatus:string = ''
+  currentStatuesParse?:Parse.Object
+  /* 打开变更状态 */
+  openStateModal(data:Parse.Object){
+    console.log(data);
+    this.currentStatuesParse = data
+    this.upStatus = data?.get('status')
+    this.isVisible = true
+  }
+  onChangeStatus(){
+    console.log(this.upStatus);
+    this.modal.confirm({
+      nzTitle: '修改教材状态',
+      nzContent: '你将修改该教材的状态,该操作将改变教材所处流程,请谨慎操作',
+      nzOkText: '确定',
+      nzOkType: 'primary',
+      nzOkDanger: true,
+      nzOnOk:async () => {
+        this.currentStatuesParse?.set('status',this.upStatus)
+        switch (this.upStatus) {
+          case '102':
+            this.currentStatuesParse?.set('render',null)
+            this.currentStatuesParse?.set('recommend',null)
+            break;
+          case '200':
+            this.currentStatuesParse?.set('render',true)
+            if(!this.currentStatuesParse?.get('eduProcess')){
+              let parentMap = await this.tbookSer.formatNode(
+                this.currentStatuesParse?.get('user')?.get('department')?.id
+              );
+              console.log(parentMap);
+              let processId = await this.getEduProcess(parentMap[1]?.key,true);
+              if (!processId) {
+                this.message.warning('申报单位暂无流程');
+                return;
+              }
+              let inviteUnit = parentMap[1]?.title; //推荐单位
+              this.currentStatuesParse?.set('eduProcess', {
+                __type: 'Pointer',
+                className: 'EduProcess',
+                objectId: processId,
+              });
+              if (parentMap[1]?.key) {
+                this.currentStatuesParse?.set('department', {
+                  __type: 'Pointer',
+                  className: 'Department',
+                  objectId: parentMap[1]?.key,
+                });
+              }
+              this.currentStatuesParse?.set('inviteUnit', inviteUnit);
+            }
+          break;
+          case '300':
+            this.currentStatuesParse?.set('render',null)
+            this.currentStatuesParse?.set('recommend',null)
+          break;
+          case '400':
+            this.currentStatuesParse?.set('render',true)
+            this.currentStatuesParse?.set('recommend',true)
+            if(!this.currentStatuesParse?.get('eduProcess')){
+              let parentMap = await this.tbookSer.formatNode(
+                this.currentStatuesParse?.get('user')?.get('department')?.objectId
+              );
+              console.log(parentMap);
+              let processId = await this.getEduProcess(parentMap[1]?.key,true);
+              if (!processId) {
+                this.message.warning('申报单位暂无流程');
+                return;
+              }
+              let inviteUnit = parentMap[1]?.title; //推荐单位
+              this.currentStatuesParse?.set('eduProcess', {
+                __type: 'Pointer',
+                className: 'EduProcess',
+                objectId: processId,
+              });
+              if (parentMap[1]?.key) {
+                this.currentStatuesParse?.set('department', {
+                  __type: 'Pointer',
+                  className: 'Department',
+                  objectId: parentMap[1]?.key,
+                });
+              }
+              this.currentStatuesParse?.set('inviteUnit', inviteUnit);
+            }
+          break;
+          default:
+            break;
+        }
+        await this.currentStatuesParse?.save()
+        this.message.success('变更状态成功')
+        await this.getTextbook(this.searchValue);
+        this.isVisible = false
+      },
+      nzCancelText: '取消',
+      nzOnCancel: () => console.log('Cancel')
+    });
+  }
 }

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

@@ -15,5 +15,8 @@
       <app-collect-textbook
     ></app-collect-textbook>
     </nz-tab>
+    <nz-tab nzTitle="所有教材(含未提交)">
+      <app-textbook [filterObj]="allFilterObj"></app-textbook>
+    </nz-tab>
   </nz-tabset>
 </div>

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

@@ -43,6 +43,12 @@ export class PageTextbookComponent implements OnInit {
     status: ['400'],
     btns: {eduReivew:true},
   };
+  allFilterObj: any = {
+    // showMore: true, //显示更多字段
+    isCheck: false,
+    status: ['102','103','200','201','300','400'],
+    btns: {review:true,changStatus:true},
+  };
   active: number = 0;
 
   constructor(

+ 169 - 50
projects/textbook/src/services/textbook.ts

@@ -3,6 +3,7 @@ import Parse from 'parse';
 import { HttpClient } from '@angular/common/http';
 import { updateDept } from './importDept';
 import { NzMessageService } from 'ng-zorro-antd/message';
+import { ProvierOssAli } from '../app/comp-upload/provider-oss-aliyun';
 
 @Injectable({
   providedIn: 'root',
@@ -11,7 +12,11 @@ export class textbookServer {
   company: string = localStorage.getItem('company')!;
   theme: boolean = false; //深色主题模式
   profile: any = JSON.parse(localStorage.getItem('profile')!);
-  constructor(private http: HttpClient) {}
+
+  ossProvider: any|{ upload: any, signatureUrl: any, download:any } | undefined;
+  constructor(private http: HttpClient) {
+    this.ossProvider = new ProvierOssAli();
+  }
   authMobile(mobile: string): boolean {
     let a = /^1[3456789]\d{9}$/;
     if (!String(mobile).match(a)) {
@@ -236,16 +241,94 @@ export class textbookServer {
 
   /* 获取已有联系人出版单位、未注册联系人出版单位 */
   async getUnitList() {
+    let title = '未注册出版社';
+    let arr = [
+      "甘肃人民出版社",
+      "河南人民出版社",
+      "湖南人民出版社",
+      "江苏人民出版社",
+      "企业管理出版社",
+      "海洋出版社",
+      "线装书局",
+      "中国工人出版社",
+      "中国海关出版社",
+      "中国青年出版总社",
+      "中国原子能出版社",
+      "中国标准出版社",
+      "国家图书馆出版社",
+      "中国戏剧出版社",
+      "北京人民出版社",
+      "中国社会科学出版社",
+      "新星出版社",
+      "河北大学出版社",
+      "测试流程开始",
+      "北京科学技术出版社",
+      "吉林人民出版社",
+      "南京东南大学出版社",
+      "陕西师范大学出版总社",
+      "上海教育出版社",
+      "成都西南交大出版社",
+      "重庆西南师范大学电子音像出版社"
+  ]
     let unitMap:any = {}
     let unitList = new Set<string>(); //单位出版社
-    let query = new Parse.Query('EduTextbook');
+    let queryParamsbook: any = {
+      where: {
+        $or: [
+          {
+            childrens: {
+              $inQuery: {
+                where: {
+                  editionUnit: { $in: arr },
+                },
+                className: 'EduTextbookVolume',
+              }
+            },
+          },
+        ],
+      },
+    };
+    let query = Parse.Query.fromJSON('EduTextbook', queryParamsbook);
     query.equalTo('status', '400');
     query.notEqualTo('isDeleted', true);
     query.notEqualTo('discard', true);
-    query.include('user.phone', 'childrens.editionUnit');
-    query.select('user.phone', 'childrens.editionUnit')
+    query.include('user.phone', 'user.name','childrens.editionUnit');
+    query.select('user.phone', 'user.name','childrens.editionUnit')
     query.limit(10000);
     let r = await query.find();
+    let tb = `<table border="1px" cellspacing="0" cellpadding="0">
+        <thead>
+          <tr>
+            <th>手机号</th>
+            <th>姓名</th>
+            <th>关联出版社</th>
+          </tr>
+        </thead>
+        <tbody>
+        `;
+
+    let _body = '';
+    for (var row = 0; row < r.length; row++) {
+      _body += '<tr>';
+      _body += '<td>';
+      _body += `&nbsp;${r[row]?.get('user')?.get('phone') || ''}`;
+      _body += '</td>';
+
+      _body += '<td>';
+      _body += `${r[row]?.get('user')?.get('name') || ''}`;
+      _body += '</td>';
+
+      _body += '<td>';
+      _body += ` &nbsp;${this.fromatFiled(r[row]?.get('childrens'), 'editionUnit') || ''}`;
+      _body += '</td>';
+
+      _body += '</tr>';
+    }
+    tb += _body;
+    tb += '</tbody>';
+    tb += '</table>';
+    this.excel(tb, `${title}.xls`);
+    return
     r.forEach((item) => {
       item
         .get('childrens')
@@ -280,6 +363,7 @@ export class textbookServer {
     let queryEduProcess = Parse.Query.fromJSON('EduProcess', queryParams);
     queryEduProcess.include('profileSubmitted.user');
     queryEduProcess.select('profileSubmitted.user.phone','name')
+    queryEduProcess.notEqualTo('isDeleted',true)
     queryEduProcess.limit(1000)
     let list = await queryEduProcess.find();
     // console.log(list);
@@ -296,45 +380,45 @@ export class textbookServer {
     let a = Array.from(unitPhoneList), b = Array.from(notUnitPhoneList)
     console.log('已注册联系:', Array.from(unitPhoneList));
     console.log('未注册联系:',Array.from(notUnitPhoneList));
-    let len = a.length > b.length ? a.length : b.length
-     let table = `<table border="1px" cellspacing="0" cellpadding="0">
-          <thead>
-            <tr>
-              <th>已注册</th>
-              <th>教材数量</th>
-              <th>未注册</th>
-              <th>教材数量</th>
-            </tr>
-          </thead>
-          <tbody>
-          `;
-
-      let _body = '';
-      for (var row = 0; row < len; row++) {
-        _body += '<tr>';
-        _body += '<td>';
-        _body += `${a[row] || ''}`;
-        _body += '</td>';
-
-        _body += '<td>';
-        _body += `${unitMap[a[row]] || ''}`;
-        _body += '</td>';
-
-        _body += '<td>';
-        _body += ` &nbsp;${b[row] || ''}`;
-        _body += '</td>';
-
-        _body += '<td>';
-        _body += `${unitMap[b[row]] || ''}`;
-        _body += '</td>';
-
-        _body += '</tr>';
-      }
-      table += _body;
-      table += '</tbody>';
-      table += '</table>';
-      let title = '出版社';
-      this.excel(table, `${title}.xls`);
+    return
+    // let len = a.length > b.length ? a.length : b.length
+    //  let table = `<table border="1px" cellspacing="0" cellpadding="0">
+    //       <thead>
+    //         <tr>
+    //           <th>已注册</th>
+    //           <th>教材数量</th>
+    //           <th>未注册</th>
+    //           <th>教材数量</th>
+    //         </tr>
+    //       </thead>
+    //       <tbody>
+    //       `;
+
+    //   let _body = '';
+    //   for (var row = 0; row < len; row++) {
+    //     _body += '<tr>';
+    //     _body += '<td>';
+    //     _body += `${a[row] || ''}`;
+    //     _body += '</td>';
+
+    //     _body += '<td>';
+    //     _body += `${unitMap[a[row]] || ''}`;
+    //     _body += '</td>';
+
+    //     _body += '<td>';
+    //     _body += ` &nbsp;${b[row] || ''}`;
+    //     _body += '</td>';
+
+    //     _body += '<td>';
+    //     _body += `${unitMap[b[row]] || ''}`;
+    //     _body += '</td>';
+
+    //     _body += '</tr>';
+    //   }
+    //   table += _body;
+    //   table += '</tbody>';
+    //   table += '</table>';
+    //   this.excel(table, `${title}.xls`);
   }
 
   /* 获取高等教育出版社教材 */
@@ -700,13 +784,48 @@ export class textbookServer {
     let unitPhoneArr = Array.from(unitPhoneList)
     unitPhoneArr.push(...['13581837652','13407973043','18510409671'])
     
-    Parse.Cloud.run('aliSmsSend', {
-      mobileList: [unitPhoneArr],
-      templateCode: 'SMS_474290139',
-      params: {end_date:'2024-10-20 16:00'},
-      signName: '普通高等教育教材网',
-    });
+    // Parse.Cloud.run('aliSmsSend', {
+    //   mobileList: [unitPhoneArr],
+    //   templateCode: 'SMS_474290139',
+    //   params: {end_date:'2024-10-20 16:00'},
+    //   signName: '普通高等教育教材网',
+    // });
     console.log('出版社电话:',unitPhoneArr);
-    
+  }
+
+  /* 获取10月9号之前上传的教材文件转私有 */
+  async getEtxVolCollect(){
+    let queryParams: any = {
+      where: {
+        $or: [
+          {
+            collectFiles: {$exists: true},
+            collectDigitFiles: {$exists: true},
+            
+          },
+        ],
+      },
+    };
+    let query = Parse.Query.fromJSON('EduTextbookVolume', queryParams);
+    query.lessThan('updatedAt',new Date('2024-10-10 18:00'))
+    query.select('collectFiles','collectDigitFiles')
+    query.limit(2000)
+    let r = await query.find()
+    let urlList:Array<string> = []
+    r.forEach(item=>{
+      item?.get('collectFiles')?.forEach((f:any)=>{
+        urlList.push(f?.url)
+      })
+      item?.get('collectDigitFiles')?.forEach((d:any)=>{
+        urlList.push(d?.url)
+      })
+    })
+
+    console.log(urlList);
+    for (let index = 0; index < urlList.length; index++) {
+      const u = urlList[index];
+      console.log(u);
+      // await this.ossProvider?.setACLPrivate(u)
+    }
   }
 }