Browse Source

项目档案

chenc 4 years ago
parent
commit
202420a61d
17 changed files with 1349 additions and 252 deletions
  1. 14 0
      src/app/entity/project-manage-archives/project-manage-archives.ts
  2. 1 1
      src/app/routes/message-notification/message-notification.component.ts
  3. 6 1
      src/app/routes/project-manage-archives/add/add.component.html
  4. 211 27
      src/app/routes/project-manage-archives/add/add.component.ts
  5. 23 23
      src/app/routes/project-manage-archives/add/business-affairs/business-affairs.component.html
  6. 128 60
      src/app/routes/project-manage-archives/add/business-affairs/business-affairs.component.ts
  7. 142 14
      src/app/routes/project-manage-archives/add/development/development.component.html
  8. 213 8
      src/app/routes/project-manage-archives/add/development/development.component.ts
  9. 57 29
      src/app/routes/project-manage-archives/add/essential-information/essential-information.component.html
  10. 159 15
      src/app/routes/project-manage-archives/add/essential-information/essential-information.component.ts
  11. 23 12
      src/app/routes/project-manage-archives/add/implementation/implementation.component.html
  12. 18 35
      src/app/routes/project-manage-archives/add/implementation/implementation.component.ts
  13. 142 14
      src/app/routes/project-manage-archives/add/serviceta/serviceta.component.html
  14. 201 11
      src/app/routes/project-manage-archives/add/serviceta/serviceta.component.ts
  15. 3 1
      src/app/routes/project-manage-archives/project-node-tree.ts
  16. 1 1
      src/app/routes/system/user/user.component.ts
  17. 7 0
      src/app/services/basedata/base-archives-milestone.service.ts

+ 14 - 0
src/app/entity/project-manage-archives/project-manage-archives.ts

@@ -18,6 +18,8 @@ export class ProjectManageArchives extends Page{
     cusName?:string;
     //项目总金额
     totalPrice?:number;
+    //已回款金额
+    received?:number;
     //销售经理id
     saleManagerId?:string;
     //销售经理
@@ -52,4 +54,16 @@ export class ProjectManageArchives extends Page{
     seEngineer?:string;
     //组织
     pkOrg?:string;
+    //里程碑类型id
+    milestoneId?:string;
+    //里程碑类型名称
+    milestoneType?:string;
+    //商务
+    bsInfo?:{}
+    //实施
+    ipInfo?:{}
+    //开发
+    deInfo?:{}
+    //服务
+    seInfo?:{}
 }

+ 1 - 1
src/app/routes/message-notification/message-notification.component.ts

@@ -48,7 +48,7 @@ export class RoutesMessageNotificationComponent implements OnInit {
   getCustomerCodeData() {
     const page = new Page();
     page.pageSize = 500;
-    this.personnelService.queryApprover().then((response) => {
+    this.personnelService.queryApprover(null).then((response) => {
       this.personnelData = response.result;
     })
   }

+ 6 - 1
src/app/routes/project-manage-archives/add/add.component.html

@@ -2,7 +2,8 @@
   <nz-tabset nzTabPosition="left">
     <!-- 基本信息 -->
     <nz-tab nzTitle="{{'essential.information'|translate}}">
-      <app-project-manage-archives-add-essential-information #essentialInformation (projectManageArchivesaEntiy)="projectManageArchivesaEntiy($event)">
+      <app-project-manage-archives-add-essential-information #essentialInformation (projectManageArchivesaEntiy)="projectManageArchivesaEntiy($event)"
+      (milestone)="milestone($event)">
 
       </app-project-manage-archives-add-essential-information>
     </nz-tab>
@@ -20,11 +21,15 @@
     </nz-tab>
     <!-- 开发 -->
     <nz-tab nzTitle="{{'development'|translate}}">
+      <app-project-manage-archives-add-development #development>
 
+      </app-project-manage-archives-add-development>
     </nz-tab>
     <!-- 服务 -->
     <nz-tab nzTitle="{{'service'|translate}}">
+      <app-project-manage-archives-add-serviceta #serviceta>
 
+      </app-project-manage-archives-add-serviceta>
     </nz-tab>
   </nz-tabset>
 </nz-spin>

+ 211 - 27
src/app/routes/project-manage-archives/add/add.component.ts

@@ -1,17 +1,25 @@
 import { Component, OnInit, ViewChild } from '@angular/core';
-import { NzModalRef, NzMessageService, NzDrawerRef } from 'ng-zorro-antd';
+import { NzModalRef, NzMessageService, NzDrawerRef, NzNotificationService } from 'ng-zorro-antd';
 import { _HttpClient } from '@delon/theme';
 import { ProjectManageArchivesAddEssentialInformationComponent } from './essential-information/essential-information.component';
 import { ProjectManageArchivesAddBusinessAffairsComponent } from './business-affairs/business-affairs.component';
 import { ProjectManageArchivesAddImplementationComponent } from './implementation/implementation.component';
 import { DictService } from 'app/services/dict.service';
+import { PersonnelService } from 'app/services/basedata/personnel.service';
+import { recursiveQuery } from '@shared/utils/yuan copy';
+import { ProjectManageArchivesAddDevelopmentComponent } from './development/development.component';
+import { ProjectManageArchivesAddServicetaComponent } from './serviceta/serviceta.component';
+import { BaseArchivesMilestone } from 'app/entity/basedata/base-archives-milestone';
+import { BaseArchivesMilestoneService } from 'app/services/basedata/base-archives-milestone.service';
+import { ProjectManageArchives } from 'app/entity/project-manage-archives/project-manage-archives';
+import { I18NService } from '@core';
 
 @Component({
   selector: 'app-project-manage-archives-add',
   templateUrl: './add.component.html',
-  styles:[
+  styles: [
     `
-    .base {
+      .base {
         position: absolute;
         bottom: 0px;
         width: 100%;
@@ -22,72 +30,248 @@ import { DictService } from 'app/services/dict.service';
         background: #fff;
         z-index: 99;
       }
-    `
-  ]
+    `,
+  ],
 })
 export class ProjectManageArchivesAddComponent implements OnInit {
-  
-
   constructor(
-    private drawerRef:NzDrawerRef,
-    private dictService:DictService
-  ) { }
+    private drawerRef: NzDrawerRef,
+    private dictService: DictService,
+    private personnelService: PersonnelService,
+    private baseArchivesMilestoneService: BaseArchivesMilestoneService,
+    private nzNotificationService: NzNotificationService,
+    private i18NService: I18NService,
+  ) {}
 
   ngOnInit(): void {
     this.getPlanType();
+    //人员下拉
+    this.getPersonnelList();
+    //里程碑类型
+    this.getTypeList();
   }
 
-  isLoadingSave=false;//保存加载
+  isLoadingSave = false; //保存加载
   //基本信息
   @ViewChild('essentialInformation') essentialInformation: ProjectManageArchivesAddEssentialInformationComponent;
   //商务
   @ViewChild('businessAffairs') businessAffairs: ProjectManageArchivesAddBusinessAffairsComponent;
   //实施
   @ViewChild('implementation') implementation: ProjectManageArchivesAddImplementationComponent;
+  //开发
+  @ViewChild('development') development: ProjectManageArchivesAddDevelopmentComponent;
+  //服务
+  @ViewChild('serviceta') serviceta: ProjectManageArchivesAddServicetaComponent;
 
   /**
    * 计划类型查询
    */
-  getPlanType(){
-    return new Promise((resolve)=>{
+  getPlanType() {
+    return new Promise(resolve => {
       this.dictService.getByDictCode('plan_type').then(response => {
         //商务计划类型
         this.businessAffairs.planList = response.result;
         resolve();
       });
-    })
+    });
   }
 
   /**
    * 根据类型id回写数据到实施、开发、服务页签的汇款信息
    * @param data 计划对象
    */
-  remittanceInformationChange(data){
+  remittanceInformationChange(data) {
     //实施页签
-    if(data.planId==="2"){
-      this.implementation.remittanceInformation=data;
-    }else if(data.planId==="3"){
-
-    }else if(data.planId==="4"){
-
+    if (data.planId === '2') {
+      this.implementation.remittanceInformation = data;
+    } else if (data.planId === '3') {
+      //开发
+      this.development.remittanceInformation = data;
+    } else if (data.planId === '4') {
+      //服务
+      this.serviceta.remittanceInformation = data;
     }
   }
 
   /**
    * 基本信息的信息回写到其他页签
    */
-  projectManageArchivesaEntiy(event){
+  projectManageArchivesaEntiy(event) {
     //商务
-    this.businessAffairs.projectManageArchives=event;
+    this.businessAffairs.projectManageArchives = event;
     //实施
-    this.implementation.projectManageArchives=event;
+    this.implementation.projectManageArchives = event;
     //开发
-
+    this.development.projectManageArchives = event;
     //服务
+    this.serviceta.projectManageArchives = event;
+  }
+
+  /**
+   * 获取人员下拉数据到各个页签中
+   */
+  getPersonnelList() {
+    return new Promise(resolve => {
+      this.personnelService.queryApprover(sessionStorage.getItem('pkOrg')).then(response => {
+        //基本信息页签人员
+        this.essentialInformation.personnelList = JSON.parse(JSON.stringify(response.result));
+        this.essentialInformation.saleManagerList = JSON.parse(JSON.stringify(response.result));
+        this.essentialInformation.impManagerList = JSON.parse(JSON.stringify(response.result));
+        this.essentialInformation.deManagerList = JSON.parse(JSON.stringify(response.result));
+        this.essentialInformation.seManagerList = JSON.parse(JSON.stringify(response.result));
+        //实施页签
+        this.implementation.personnelList = JSON.parse(JSON.stringify(response.result));
+        //开发页签
+        this.development.personnelList = JSON.parse(JSON.stringify(response.result));
+        //服务页签
+        this.serviceta.personnelList = JSON.parse(JSON.stringify(response.result));
+        recursiveQuery(this.essentialInformation.personnelList);
+        recursiveQuery(this.essentialInformation.saleManagerList);
+        recursiveQuery(this.essentialInformation.impManagerList);
+        recursiveQuery(this.essentialInformation.deManagerList);
+        recursiveQuery(this.essentialInformation.seManagerList);
+        //禁用公司、部分不可选
+        //实施
+        recursiveQuery(this.implementation.personnelList);
+        //开发
+        recursiveQuery(this.development.personnelList);
+        //服务
+        recursiveQuery(this.serviceta.personnelList);
+        resolve();
+      });
+    });
   }
 
-  save(){
-    this.essentialInformation.submitForm();
+  /**
+   * 获取里程碑类型到基本信息中
+   */
+  getTypeList() {
+    this.dictService.getByDictCode('base_archives_milestone_type').then(response => {
+      this.essentialInformation.milestoneList = response.result;
+    });
+  }
+
+  /**
+   * 根据里程碑类型查询商务的里程碑下拉数据以及实施、开发、服务的里程碑明细
+   */
+  milestone(event: ProjectManageArchives) {
+    //商务里程碑下拉数据
+    //查询条件
+    let baseArchivesMilestone = new BaseArchivesMilestone();
+    baseArchivesMilestone.parentId = '0';
+    baseArchivesMilestone.typeId = event.milestoneId; //里程碑档案类型
+    //查询数据
+    this.baseArchivesMilestoneService.getAllParent(baseArchivesMilestone).then(response => {
+      if (response.result) {
+        this.businessAffairs.milestoneList = response.result;
+      }
+    });
+    //计划里程碑
+    //查询条件
+    let baseArchivesMilestone2 = new BaseArchivesMilestone();
+    baseArchivesMilestone2.pkOrg = sessionStorage.getItem('pkOrg'); //组织
+    baseArchivesMilestone2.typeId = event.milestoneId;
+    //查询数据
+    this.baseArchivesMilestoneService.getTreeList(baseArchivesMilestone2).then(response => {
+      if (response.result) {
+        //实施
+        this.implementation.listOfMapData = JSON.parse(JSON.stringify(response.result));
+        this.implementation.getLoding();
+        //开发
+        this.development.listOfMapData = JSON.parse(JSON.stringify(response.result));
+        this.development.getLoding();
+        //服务
+        this.serviceta.listOfMapData = JSON.parse(JSON.stringify(response.result));
+        this.serviceta.getLoding();
+      }
+    });
+  }
+
+  save() {
+    return new Promise(resolve => {
+      //基本信息中的
+      this.essentialInformation.submitForm();
+      //基本信息
+      let projectManageArchives = this.essentialInformation.projectManageArchivesa;
+      //已回款金额
+      projectManageArchives.received;
+      //组织
+      projectManageArchives.pkOrg = sessionStorage.getItem('pkOrg');
+      ////////////商务页签的计划表格数据
+      let bsInfo: any = {};
+      bsInfo.coPlanList = this.businessAffairs.collectionPlanList; //收款计划
+      bsInfo.coSituationList = this.businessAffairs.paymentCollectionList; //收款情况
+      bsInfo.payPlanList = this.businessAffairs.paymentPlanList; //付款计划
+      bsInfo.paySituationList = this.businessAffairs.paymentStatusList; //付款情况
+      projectManageArchives.bsInfo = bsInfo;
+      ////////////实施页签的计划树形表格数据
+      let ipInfo: any = {};
+      let implementation = [];
+      //获取计划里程碑明细
+      this.getMileItem(this.implementation, implementation);
+      ipInfo.planList = implementation;
+      projectManageArchives.ipInfo = ipInfo;
+      ////////////实施页签的计划树形表格数据
+      let deInfo: any = {};
+      let development = [];
+      //获取计划里程碑明细
+      this.getMileItem(this.development, development);
+      deInfo.planList = development;
+      projectManageArchives.deInfo = deInfo;
+      ////////////实施页签的计划树形表格数据
+      let seInfo: any = {};
+      let serviceta = [];
+      //获取计划里程碑明细
+      this.getMileItem(this.serviceta, serviceta);
+      seInfo.planList = serviceta;
+      projectManageArchives.seInfo = seInfo;
+      this.baseArchivesMilestoneService.add(projectManageArchives).then(response => {
+        if (response.success) {
+          //保存成功
+          this.nzNotificationService.success(this.i18NService.fanyi('save.ok'), '');
+          this.drawerRef.close();
+          resolve();
+        } else {
+          //保存失败
+          this.nzNotificationService.error(this.i18NService.fanyi('save.not'), '');
+        }
+      });
+    });
+  }
+
+  /**
+   * 获取计划里程碑明细数据
+   * @param component 页签组件对象
+   * @param list 需要的保存集合
+   */
+  getMileItem(component, list) {
+    component.listOfMapData.forEach(item => {
+      component.mapOfExpandedData[item.key].forEach(element => {
+        let names = ''; //人员名称
+        let ids = ''; //人员id
+        //获取执行人的名称和id
+        element.executors.forEach(element => {
+          component.personnelList.forEach(pkOrg => {
+            pkOrg.children.forEach(depart => {
+              depart.children.forEach(personnel => {
+                if (personnel.key === element) {
+                  if (names === '') {
+                    names = personnel.name;
+                    ids = personnel.key;
+                  } else {
+                    names = names + '、' + personnel.name;
+                    ids = ids + '、' + personnel.key;
+                  }
+                }
+              });
+            });
+          });
+        });
+        element.executor = names;
+        element.executorId = ids;
+        list.push(element);
+      });
+    });
   }
 
   close() {

+ 23 - 23
src/app/routes/project-manage-archives/add/business-affairs/business-affairs.component.html

@@ -1,42 +1,42 @@
-<!-- 商务 -->
+<!-- 开发 -->
 <form nz-form>
   <div nz-row [nzGutter]="24">
     <div nz-col [nzSpan]="6">
       <nz-form-item>
-        <nz-form-label [nzSpan]="6">客户编码</nz-form-label>
-        <nz-form-control [nzSm]="18" [nzXs]="24">{{projectManageArchives.cusCode}}</nz-form-control>
+        <nz-form-label [nzSpan]="8">客户编码</nz-form-label>
+        <nz-form-control [nzSm]="16" [nzXs]="24">{{projectManageArchives.cusCode}}</nz-form-control>
       </nz-form-item>
     </div>
     <div nz-col [nzSpan]="6">
       <nz-form-item>
-        <nz-form-label [nzSpan]="6">客户名称</nz-form-label>
-        <nz-form-control [nzSm]="18" [nzXs]="24">{{projectManageArchives.cusName}}</nz-form-control>
+        <nz-form-label [nzSpan]="8">客户名称</nz-form-label>
+        <nz-form-control [nzSm]="16" [nzXs]="24">{{projectManageArchives.cusName}}</nz-form-control>
       </nz-form-item>
     </div>
     <div nz-col [nzSpan]="6">
       <nz-form-item>
-        <nz-form-label [nzSpan]="6">销售经理</nz-form-label>
-        <nz-form-control [nzSm]="18" [nzXs]="24">{{projectManageArchives.saleManager}}</nz-form-control>
+        <nz-form-label [nzSpan]="8">销售经理</nz-form-label>
+        <nz-form-control [nzSm]="16" [nzXs]="24">{{projectManageArchives.saleManager}}</nz-form-control>
       </nz-form-item>
     </div>
     <div nz-col [nzSpan]="6">
       <nz-form-item>
-        <nz-form-label [nzSpan]="6">业务员</nz-form-label>
-        <nz-form-control [nzSm]="18" [nzXs]="24">{{projectManageArchives.saleMan}}</nz-form-control>
+        <nz-form-label [nzSpan]="8">业务员</nz-form-label>
+        <nz-form-control [nzSm]="16" [nzXs]="24">{{projectManageArchives.saleMan}}</nz-form-control>
       </nz-form-item>
     </div>
   </div>
   <div nz-row [nzGutter]="24">
     <div nz-col [nzSpan]="6">
       <nz-form-item>
-        <nz-form-label [nzSpan]="6">项目总金额</nz-form-label>
-        <nz-form-control [nzSm]="18" [nzXs]="24">{{projectManageArchives.totalPrice}}</nz-form-control>
+        <nz-form-label [nzSpan]="8">项目总金额</nz-form-label>
+        <nz-form-control [nzSm]="16" [nzXs]="24">{{projectManageArchives.totalPrice}}</nz-form-control>
       </nz-form-item>
     </div>
     <div nz-col [nzSpan]="6">
       <nz-form-item>
-        <nz-form-label [nzSpan]="6">已汇款金额</nz-form-label>
-        <nz-form-control [nzSm]="18" [nzXs]="24">{{projectManageArchives.proCode}}</nz-form-control>
+        <nz-form-label [nzSpan]="8">已回款金额</nz-form-label>
+        <nz-form-control [nzSm]="16" [nzXs]="24">{{projectManageArchives.received}}</nz-form-control>
       </nz-form-item>
     </div>
   </div>
@@ -67,7 +67,7 @@
           <tr *ngFor="let data of basicTable.data">
             <td style="width: 7%;">
               <nz-select style="width: 100%;" nzShowSearch nzAllowClear [(ngModel)]="data.planId" nzPlaceHolder="请选择"
-                [nzDropdownMatchSelectWidth]="false">
+                [nzDropdownMatchSelectWidth]="false" (ngModelChange)="planIdChange(data,'1')">
                 <nz-option *ngFor="let i of planList" [nzValue]="i.value" [nzLabel]="i.text"></nz-option>
               </nz-select>
             </td>
@@ -79,7 +79,7 @@
             <td style="width: 5%;">
               <nz-select style="width: 100%;" nzShowSearch nzAllowClear [(ngModel)]="data.mileId1" nzPlaceHolder="请选择"
                 [nzDropdownMatchSelectWidth]="false">
-                <nz-option *ngFor="let i of milestoneList" [nzValue]="i.value" [nzLabel]="i.text"></nz-option>
+                <nz-option *ngFor="let i of milestoneList" [nzValue]="i.id" [nzLabel]="i.name"></nz-option>
               </nz-select>
             </td>
             <td style="width: 5%;">
@@ -178,7 +178,7 @@
           <tr *ngFor="let data of basicTable2.data">
             <td style="width: 7%;">
               <nz-select style="width: 100%;" nzShowSearch nzAllowClear [(ngModel)]="data.planId" nzPlaceHolder="请选择"
-                [nzDropdownMatchSelectWidth]="false" (ngModelChange)="planIdChange(data)">
+                [nzDropdownMatchSelectWidth]="false" (ngModelChange)="planIdChange(data,'2')">
                 <nz-option *ngFor="let i of planList" [nzValue]="i.value" [nzLabel]="i.text"></nz-option>
               </nz-select>
             </td>
@@ -189,7 +189,7 @@
             </td>
             <td style="width: 5%;">
               <nz-select style="width: 100%;" nzShowSearch nzAllowClear [(ngModel)]="data.mileId1" nzPlaceHolder="请选择"
-                [nzDropdownMatchSelectWidth]="false" (ngModelChange)="getRemittanceInformationChange(data)">
+                [nzDropdownMatchSelectWidth]="false" (ngModelChange)="mileChange(data)">
                 <nz-option *ngFor="let i of milestoneList" [nzValue]="i.value" [nzLabel]="i.text"></nz-option>
               </nz-select>
             </td>
@@ -203,7 +203,7 @@
             </td>
             <td style="width: 5%;">
               <nz-select style="width: 100%;" nzShowSearch nzAllowClear [(ngModel)]="data.mileId2" nzPlaceHolder="请选择"
-                [nzDropdownMatchSelectWidth]="false" (ngModelChange)="getRemittanceInformationChange(data)">
+                [nzDropdownMatchSelectWidth]="false" (ngModelChange)="mileChange(data)">
                 <nz-option *ngFor="let i of milestoneList" [nzValue]="i.value" [nzLabel]="i.text"></nz-option>
               </nz-select>
             </td>
@@ -217,7 +217,7 @@
             </td>
             <td style="width: 5%;">
               <nz-select style="width: 100%;" nzShowSearch nzAllowClear [(ngModel)]="data.mileId3" nzPlaceHolder="请选择"
-                [nzDropdownMatchSelectWidth]="false" (ngModelChange)="getRemittanceInformationChange(data)">
+                [nzDropdownMatchSelectWidth]="false" (ngModelChange)="mileChange(data)">
                 <nz-option *ngFor="let i of milestoneList" [nzValue]="i.value" [nzLabel]="i.text"></nz-option>
               </nz-select>
             </td>
@@ -231,7 +231,7 @@
             </td>
             <td style="width: 5%;">
               <nz-select style="width: 100%;" nzShowSearch nzAllowClear [(ngModel)]="data.mileId4" nzPlaceHolder="请选择"
-                [nzDropdownMatchSelectWidth]="false" (ngModelChange)="getRemittanceInformationChange(data)">
+                [nzDropdownMatchSelectWidth]="false" (ngModelChange)="mileChange(data)">
                 <nz-option *ngFor="let i of milestoneList" [nzValue]="i.value" [nzLabel]="i.text"></nz-option>
               </nz-select>
             </td>
@@ -245,7 +245,7 @@
             </td>
             <td style="width: 5%;">
               <nz-select style="width: 100%;" nzShowSearch nzAllowClear [(ngModel)]="data.mileId5" nzPlaceHolder="请选择"
-                [nzDropdownMatchSelectWidth]="false" (ngModelChange)="getRemittanceInformationChange(data)">
+                [nzDropdownMatchSelectWidth]="false" (ngModelChange)="mileChange(data)">
                 <nz-option *ngFor="let i of milestoneList" [nzValue]="i.value" [nzLabel]="i.text"></nz-option>
               </nz-select>
             </td>
@@ -289,7 +289,7 @@
           <tr *ngFor="let data of basicTable3.data">
             <td style="width: 7%;">
               <nz-select style="width: 100%;" nzShowSearch nzAllowClear [(ngModel)]="data.planId" nzPlaceHolder="请选择"
-                [nzDropdownMatchSelectWidth]="false">
+                [nzDropdownMatchSelectWidth]="false" (ngModelChange)="planIdChange(data,'3')">
                 <nz-option *ngFor="let i of planList" [nzValue]="i.value" [nzLabel]="i.text"></nz-option>
               </nz-select>
             </td>
@@ -400,7 +400,7 @@
           <tr *ngFor="let data of basicTable4.data">
             <td style="width: 7%;">
               <nz-select style="width: 100%;" nzShowSearch nzAllowClear [(ngModel)]="data.planId" nzPlaceHolder="请选择"
-                [nzDropdownMatchSelectWidth]="false">
+                [nzDropdownMatchSelectWidth]="false" (ngModelChange)="planIdChange(data,'4')">
                 <nz-option *ngFor="let i of planList" [nzValue]="i.value" [nzLabel]="i.text"></nz-option>
               </nz-select>
             </td>

+ 128 - 60
src/app/routes/project-manage-archives/add/business-affairs/business-affairs.component.ts

@@ -2,48 +2,47 @@ import { Component, OnInit, Output, EventEmitter } from '@angular/core';
 import { NzModalRef, NzMessageService } from 'ng-zorro-antd';
 import { _HttpClient } from '@delon/theme';
 import { ProjectManageArchives } from 'app/entity/project-manage-archives/project-manage-archives';
+import { BaseArchivesMilestoneService } from 'app/services/basedata/base-archives-milestone.service';
+import { BaseArchivesMilestone } from 'app/entity/basedata/base-archives-milestone';
 
 @Component({
   selector: 'app-project-manage-archives-add-business-affairs',
   templateUrl: './business-affairs.component.html',
 })
 export class ProjectManageArchivesAddBusinessAffairsComponent implements OnInit {
-  
-
   constructor(
-    
-  ) { }
+    private baseArchivesMilestoneService:BaseArchivesMilestoneService
+  ) {}
 
   ngOnInit(): void {
-    
   }
 
-  projectManageArchives:ProjectManageArchives={}//项目档案实体对象
-  collectionPlanList=[];//收款计划数据
-  paymentCollectionList=[];//回款情况数据
-  paymentPlanList=[];//付款计划
-  paymentStatusList=[];//付款情况
-  planList=[];//计划下来集合数据
+  projectManageArchives: ProjectManageArchives = {}; //项目档案实体对象
+  collectionPlanList = []; //收款计划数据
+  paymentCollectionList = []; //回款情况数据
+  paymentPlanList = []; //付款计划
+  paymentStatusList = []; //付款情况
+  planList = []; //计划下来集合数据
   formatterDollar = (value: number) => `$ ${value}`;
   parserDollar = (value: string) => value.replace('$ ', '');
-  milestoneList=[];//里程碑集合数据
+  milestoneList :any= []; //里程碑集合数据
 
   /**
    * 
    收款计划新增
    */
-  collectionPlanSort=0;//收款计划排序
-  collectionPlanAdd(){
+  collectionPlanSort = 0; //收款计划排序
+  collectionPlanAdd() {
     this.collectionPlanList = [
       ...this.collectionPlanList,
       {
-        price1:0,
-        price2:0,
-        price3:0,
-        price4:0,
-        price5:0,
-        sort:this.collectionPlanSort,
-        planType:"1"
+        price1: 0,
+        price2: 0,
+        price3: 0,
+        price4: 0,
+        price5: 0,
+        sort: this.collectionPlanSort,
+        planType: '1',
       },
     ];
     this.collectionPlanSort++;
@@ -52,25 +51,25 @@ export class ProjectManageArchivesAddBusinessAffairsComponent implements OnInit
   /**
    * 收款删除按钮
    */
-  collectionPlanDelete(sort){
+  collectionPlanDelete(sort) {
     this.collectionPlanList = this.collectionPlanList.filter(d => d.sort !== sort);
   }
 
   /**
    * 回款计划新增
    */
-  paymentCollectionSort=0;//回款情况排序
-  paymentCollectionAdd(){
+  paymentCollectionSort = 0; //回款情况排序
+  paymentCollectionAdd() {
     this.paymentCollectionList = [
       ...this.paymentCollectionList,
       {
-        price1:0,
-        price2:0,
-        price3:0,
-        price4:0,
-        price5:0,
-        sort:this.paymentCollectionSort,
-        planType:"2"
+        price1: 0,
+        price2: 0,
+        price3: 0,
+        price4: 0,
+        price5: 0,
+        sort: this.paymentCollectionSort,
+        planType: '2',
       },
     ];
     this.paymentCollectionSort++;
@@ -79,25 +78,25 @@ export class ProjectManageArchivesAddBusinessAffairsComponent implements OnInit
   /**
    * 回款删除按钮
    */
-  paymentCollectionDelete(sort){
+  paymentCollectionDelete(sort) {
     this.paymentCollectionList = this.paymentCollectionList.filter(d => d.sort !== sort);
   }
 
   /**
    * 付款计划新增
    */
-  paymentPlanSort=0;
-  paymentPlanAdd(){
+  paymentPlanSort = 0;
+  paymentPlanAdd() {
     this.paymentPlanList = [
       ...this.paymentPlanList,
       {
-        price1:0,
-        price2:0,
-        price3:0,
-        price4:0,
-        price5:0,
-        sort:this.paymentPlanSort,
-        planType:"3"
+        price1: 0,
+        price2: 0,
+        price3: 0,
+        price4: 0,
+        price5: 0,
+        sort: this.paymentPlanSort,
+        planType: '3',
       },
     ];
     this.paymentPlanSort++;
@@ -106,26 +105,25 @@ export class ProjectManageArchivesAddBusinessAffairsComponent implements OnInit
   /**
    * 付款计划删除按钮
    */
-  paymentPlanDelete(sort){
+  paymentPlanDelete(sort) {
     this.paymentPlanList = this.paymentPlanList.filter(d => d.sort !== sort);
   }
 
-
   /**
    * 付款情况
    */
-  paymentStatusSort=0;
-  paymentStatusAdd(){
+  paymentStatusSort = 0;
+  paymentStatusAdd() {
     this.paymentStatusList = [
       ...this.paymentStatusList,
       {
-        price1:0,
-        price2:0,
-        price3:0,
-        price4:0,
-        price5:0,
-        sort:this.paymentPlanSort,
-        planType:"3"
+        price1: 0,
+        price2: 0,
+        price3: 0,
+        price4: 0,
+        price5: 0,
+        sort: this.paymentPlanSort,
+        planType: '3',
       },
     ];
     this.paymentPlanSort++;
@@ -134,31 +132,101 @@ export class ProjectManageArchivesAddBusinessAffairsComponent implements OnInit
   /**
    * 付款情况删除按钮
    */
-  paymentStatusDelete(sort){
+  paymentStatusDelete(sort) {
     this.paymentStatusList = this.paymentStatusList.filter(d => d.sort !== sort);
   }
 
-  
   /**
    * 类型触发事件
    */
-  planIdChange(data){
+  planIdChange(data, type) {
     //获取类型名称
+    this.getPlanName(data);
+    //如果是回款情况表格中下拉触发
+    if (type === '2') {
+      //获取收款计划的金额
+      this.getCollectionPlanPrice(this.collectionPlanList,data);
+      //回写数据到实施、开发、服务页签的回款信息
+      this.getRemittanceInformationChange(data);
+    }
+    //如果是付款情况表格中下来触发
+    if (type === '4') {
+      //获取付款计划中的金额
+      this.getCollectionPlanPrice(this.paymentPlanList,data);
+    }
+  }
+
+  /**
+   * 获取类型名称
+   * @param data 计划对象
+   */
+  getPlanName(data) {
     this.planList.forEach(element => {
-      if(element.value===data.planId){
-        data.planName=element.text;
+      if (element.value === data.planId) {
+        data.planName = element.text;
       }
     });
+  }
+
+  /**
+   * 根据回款情况类型获取对应的收款计划金额
+   * @param list 表格数据
+   * @param data 表格中的对象
+   */
+  getCollectionPlanPrice(list,data) {
+    list.forEach(element => {
+      if (data.planId === element.planId) {
+        data.price1 = element.price1;
+        data.price2 = element.price2;
+        data.price3 = element.price3;
+        data.price4 = element.price4;
+        data.price5 = element.price5;
+      }
+    });
+  }
+
+  /**
+   * 里程碑选择事件
+   * @param data
+   */
+  mileChange(data) {
+    //已汇款金额
+    this.getReceived();
     //回写数据到实施、开发、服务页签的回款信息
     this.getRemittanceInformationChange(data);
   }
 
+  /**
+   * 获取回款情况中的回款金额累加(已汇款金额)
+   */
+  getReceived() {
+    let received = 0;
+    this.paymentCollectionList.forEach(element => {
+      if (element.desc1 && !isNaN(Number(element.desc1))) {
+        received += Number(element.desc1);
+      }
+      if (element.desc2 && !isNaN(Number(element.desc2))) {
+        received += Number(element.desc2);
+      }
+      if (element.desc3 && !isNaN(Number(element.desc3))) {
+        received += Number(element.desc3);
+      }
+      if (element.desc4 && !isNaN(Number(element.desc4))) {
+        received += Number(element.desc4);
+      }
+      if (element.desc5 && !isNaN(Number(element.desc5))) {
+        received += Number(element.desc5);
+      }
+    });
+    this.projectManageArchives.received = received;
+  }
+
   /**
    * 回写数据到实施、开发、服务页签的回款信息
    * @param 对象
    */
-  @Output() remittanceInformationChange= new EventEmitter<{}>();
-  getRemittanceInformationChange(data){
-    this.remittanceInformationChange.emit(data)
+  @Output() remittanceInformationChange = new EventEmitter<{}>();
+  getRemittanceInformationChange(data) {
+    this.remittanceInformationChange.emit(data);
   }
 }

+ 142 - 14
src/app/routes/project-manage-archives/add/development/development.component.html

@@ -1,14 +1,142 @@
-<div class="modal-header">
-  <div class="modal-title">查看 {{ record.id }} 信息</div>
-</div>
-<nz-spin *ngIf="!i" class="modal-spin"></nz-spin>
-<div sv-container *ngIf="i">
-  <sv label="姓名">{{ i.owner }}</sv>
-  <sv label="会员卡号">32943898021309809423</sv>
-  <sv label="身份证">3321944288191034921</sv>
-  <sv label="联系方式">18112345678</sv>
-  <sv label="联系地址">曲丽丽 18100000000 浙江省杭州市西湖区黄姑山路工专路交叉路口</sv>
-</div>
-<div class="modal-footer">
-  <button nz-button type="button" (click)="close()">关闭</button>
-</div>
+<!-- 商务 -->
+<form nz-form>
+  <div nz-row [nzGutter]="24">
+    <div nz-col [nzSpan]="6">
+      <nz-form-item>
+        <nz-form-label [nzSpan]="8">客户编码</nz-form-label>
+        <nz-form-control [nzSm]="16" [nzXs]="24">{{projectManageArchives.cusCode}}</nz-form-control>
+      </nz-form-item>
+    </div>
+    <div nz-col [nzSpan]="6">
+      <nz-form-item>
+        <nz-form-label [nzSpan]="8">客户名称</nz-form-label>
+        <nz-form-control [nzSm]="16" [nzXs]="24">{{projectManageArchives.cusName}}</nz-form-control>
+      </nz-form-item>
+    </div>
+    <div nz-col [nzSpan]="6">
+      <nz-form-item>
+        <nz-form-label [nzSpan]="8">开发项目经理</nz-form-label>
+        <nz-form-control [nzSm]="16" [nzXs]="24">{{projectManageArchives.deManager}}</nz-form-control>
+      </nz-form-item>
+    </div>
+    <div nz-col [nzSpan]="6">
+      <nz-form-item>
+        <nz-form-label [nzSpan]="8">开发工程师</nz-form-label>
+        <nz-form-control [nzSm]="16" [nzXs]="24">{{projectManageArchives.deEngineer}}</nz-form-control>
+      </nz-form-item>
+    </div>
+  </div>
+</form>
+
+<!-- 汇款信息 -->
+<nz-card nzTitle="回款信息" nzSize="small">
+  <nz-table nzBordered nzSize="small" [nzNoResult]="' '" [nzShowPagination]="false">
+    <tbody>
+      <tr>
+        <td><strong>开发金额</strong></td>
+        <td>第一笔</td>
+        <td>{{remittanceInformation.price1}}</td>
+        <td>第二笔</td>
+        <td>{{remittanceInformation.price2}}</td>
+        <td>第三笔</td>
+        <td>{{remittanceInformation.price3}}</td>
+        <td>第四笔</td>
+        <td>{{remittanceInformation.price4}}</td>
+        <td>第五笔</td>
+        <td>{{remittanceInformation.price5}}</td>
+      </tr>
+      <tr>
+        <td><strong>实际回款</strong></td>
+        <td>{{remittanceInformation.milestone1}}</td>
+        <td>{{remittanceInformation.desc1}}</td>
+        <td>{{remittanceInformation.milestone2}}</td>
+        <td>{{remittanceInformation.desc2}}</td>
+        <td>{{remittanceInformation.milestone3}}</td>
+        <td>{{remittanceInformation.desc3}}</td>
+        <td>{{remittanceInformation.milestone4}}</td>
+        <td>{{remittanceInformation.desc4}}</td>
+        <td>{{remittanceInformation.milestone5}}</td>
+        <td>{{remittanceInformation.desc5}}</td>
+      </tr>
+    </tbody>
+  </nz-table>
+</nz-card>
+
+<!-- 实施计划 -->
+<nz-card nzTitle="开发计划" nzSize="small">
+  <div nz-row [nzGutter]="24">
+    <div nz-col [nzSpan]="24">
+      <!-- 新增按钮 -->
+      <button (click)="addParent()" nz-button nzType="primary">{{ 'button.add' | translate }}</button>
+    </div>
+  </div>
+  <div nz-row [nzGutter]="24">
+    <div nz-col [nzSpan]="24">
+      <nz-table style="padding-top: 5px;" nzSize="small" class="tableTdPadding" #expandTable [nzData]="listOfMapData"
+        nzTableLayout="fixed" [nzShowPagination]="false" [nzFrontPagination]="false">
+        <thead>
+          <tr>
+            <th></th>
+            <th style="width: 10%;">里程碑</th>
+            <th style="width: 20%;">开始时间</th>
+            <th style="width: 20%;">结束时间</th>
+            <th style="width: 10%;">计划人天</th>
+            <th style="width: 20%;">执行人</th>
+            <th style="width: 10%;">实际人天</th>
+            <th style="width: 10%;">操作</th>
+          </tr>
+        </thead>
+        <tbody>
+          <ng-container *ngFor="let data of expandTable.data">
+            <ng-container *ngFor="let item of mapOfExpandedData[data.key]">
+
+
+              <tr *ngIf="(item.parent && item.parent.expand) || !item.parent">
+                <td [nzIndentSize]="item.level! * 20" [nzShowExpand]="!!item.children" [(nzExpand)]="item.expand"
+                  (nzExpandChange)="collapse(mapOfExpandedData[data.key], item, $event)">
+                </td>
+                <td>
+                  <ng-container *ngIf="item.id">
+                    {{ item.name }}
+                  </ng-container>
+                  <ng-container *ngIf="!item.id">
+                    <input nz-input [(ngModel)]="item.name" />
+                  </ng-container>
+                </td>
+                <td>
+                  <nz-date-picker [(ngModel)]="item.startDate"></nz-date-picker>
+                </td>
+                <td>
+                  <nz-date-picker [(ngModel)]="item.endDate"></nz-date-picker>
+                </td>
+                <td>
+                  <nz-input-number [(ngModel)]="item.planTime" [nzMin]="0" [nzStep]="1"></nz-input-number>
+                </td>
+                <td>
+                  <!-- <nz-select style="width: 100%;" [nzMaxTagCount]="3" nzMode="multiple" nzPlaceHolder="请选择"
+                    [(ngModel)]="item.executor">
+                    <nz-option *ngFor="let item of personnelList" [nzLabel]="item.id" [nzValue]="item.name"></nz-option>
+                  </nz-select> -->
+                  <nz-tree-select style="width: 100%" [nzNodes]="personnelList" nzShowSearch [nzMultiple]="true"
+                  nzPlaceHolder="请选择"
+                  [(ngModel)]="item.executors" [nzMaxTagCount]="3" [nzAllowClear]="true">
+                </nz-tree-select>
+                </td>
+                <td>
+                  <nz-input-number [(ngModel)]="item.realTime" [nzMin]="0" [nzStep]="1"></nz-input-number>
+                </td>
+                <td>
+                  <a (click)="addChild(item.key)">{{ 'button.leve.lower' | translate }}</a>
+                  <nz-divider nzType="vertical"></nz-divider>
+                  <a nz-popconfirm nzTitle="{{'isdelete'|translate}}" nzOkText="{{ 'yes' | translate }}"
+                    nzCancelText="{{ 'no' | translate }}"
+                    (nzOnConfirm)="deleteRow(mapOfExpandedData[data.key],item,item.key)">{{ 'milestone.delete' | translate }}</a>
+                </td>
+              </tr>
+            </ng-container>
+          </ng-container>
+        </tbody>
+      </nz-table>
+    </div>
+  </div>
+</nz-card>

+ 213 - 8
src/app/routes/project-manage-archives/add/development/development.component.ts

@@ -1,26 +1,231 @@
 import { Component, OnInit } from '@angular/core';
 import { NzModalRef, NzMessageService } from 'ng-zorro-antd';
 import { _HttpClient } from '@delon/theme';
+import { BaseArchivesMilestoneService } from 'app/services/basedata/base-archives-milestone.service';
+import { ProjectManageArchives } from 'app/entity/project-manage-archives/project-manage-archives';
+import { BaseArchivesMilestone } from 'app/entity/basedata/base-archives-milestone';
+import { ProjectNodeTree } from '../../project-node-tree';
 
 @Component({
   selector: 'app-project-manage-archives-add-development',
   templateUrl: './development.component.html',
 })
 export class ProjectManageArchivesAddDevelopmentComponent implements OnInit {
-  record: any = {};
-  i: any;
+  
 
   constructor(
-    private modal: NzModalRef,
-    public msgSrv: NzMessageService,
-    public http: _HttpClient
+    private baseArchivesMilestoneService:BaseArchivesMilestoneService
   ) { }
 
   ngOnInit(): void {
-    this.http.get(`/user/${this.record.id}`).subscribe(res => this.i = res);
+    this.getTreeList();
   }
+  
 
-  close() {
-    this.modal.destroy();
+  projectManageArchives:ProjectManageArchives={};//项目档案主表实体
+  listOfMapData:any=[];//树形集合
+  personnelList=[];//人员下拉列表
+  remittanceInformation:any={};//回款信息实体
+
+
+  /**
+   * 获取树形集合
+   */
+  getTreeList() {
+    // let baseArchivesMilestone=new BaseArchivesMilestone();
+    // baseArchivesMilestone.pkOrg=sessionStorage.getItem("pkOrg");//组织
+    // baseArchivesMilestone.typeId="3";
+    // this.baseArchivesMilestoneService.getTreeList(baseArchivesMilestone).then((response)=>{
+    //   if(response.result){
+    //     this.listOfMapData=response.result
+    //     this.getLoding();
+    //   }
+    // })
+  }
+
+  /**
+   * 初始化树形
+   */
+  getLoding(){
+    this.listOfMapData.forEach(item => {
+      this.mapOfExpandedData[item.key] = this.convertTreeToList(item);
+    });
+  }
+
+  /**
+   * 新增父级
+   */
+  //uuid
+  S4() {
+    return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
+  };
+  guid() {
+    return (this.S4() + this.S4() + this.S4() + this.S4() + this.S4() + this.S4() + this.S4() + this.S4());
+  };
+  // 随机数
+  add() {
+    return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
+  };
+  adding() {
+    return (this.add() + this.add() + this.add() + this.add() + this.add() + this.add() + this.add() + this.add());
+  };
+  addParent(){
+    this.listOfMapData.forEach(item => {
+      console.log(this.mapOfExpandedData[item.key]);
+    });
+    this.listOfMapData=[
+      ...this.listOfMapData,
+      {key:this.adding()}
+    ]
+    // this.getLoding();
+    this.initialValue();
+  }
+
+  /**
+   * 新增子集
+   * @param parentId 父级id
+   * @param data 操作对象
+   */
+  addChild(parentId){
+    this.getChild(this.listOfMapData, parentId);
+    this.initialValue();
+  }
+
+  /**
+   * 递归查询子集增加
+   */
+  getChild(children, parentId) {
+    var keyId = this.adding();
+    children.forEach(element => {
+      // 是否和点击的数据相等
+      // 相等则在此条数据加子数据
+      if (element.key == parentId) {
+        // 是否存在自数据不存在则创建child
+        if (element.children == null) {
+          element.children = []
+        }
+        // 添加一条空的子数据到child
+        element.children = [
+          ...element.children,
+          { key: keyId, parentId: parentId}
+        ]
+        // this.mapOfExpandedData[element.key] = this.convertTreeToList(null);
+        // this.initialValue();
+      } else {
+        if (element.children != null) {
+          this.getChild(element.children, parentId);
+        }
+      }
+    });
+  }
+
+ /**
+   * 删除行
+   */
+  deleteRow(array: ProjectNodeTree[], data: ProjectNodeTree, key){
+    this.getdeleteRow(key, this.listOfMapData);
+    this.initialValue()
+  }
+
+  /**
+   * 递归删除
+   * @param itemsId 对象id
+   * @param list 需要删除对象的集合
+   * @param parent 父级对象
+   */
+  getdeleteRow(itemsId: string, list?: any,parent?:any) {
+    list.forEach((element, i) => {
+      //判断选中得数据是否有找到
+      if (element.key == itemsId) {
+        //找到则先判断对象是否有子集,有则删除
+        if (element.children != null && element.children.length > 0) {
+          element.children.splice(0, element.children.length);
+        }
+        //然后删除父极对象
+        list.splice(i, 1);
+        //判断父极是否存在子集
+        if (list.length == 0&&parent) {
+          parent.children = null;
+        }
+        this.listOfMapData=[
+          ...this.listOfMapData
+        ]
+        // this.getDataInitialization2();
+        // this.initialValue();
+      } else {
+        //没有则判断是否有子集 有则递归同样判断
+        if (element.children != null && element.children.length > 0) {
+          this.getdeleteRow(itemsId, element.children,element);
+        }
+      }
+    });
+  }
+
+
+
+  initialValue(){
+    this.listOfMapData.forEach(item => {
+      const data = this.mapOfExpandedData[item.key];
+      this.mapOfExpandedData[item.key] = this.convertTreeToList(item);
+      const mapData = this.mapOfExpandedData[item.key];
+      if (data && mapData) {
+        mapData.forEach(el => {
+          data.forEach(element => {
+            if (element.key === el.key) {
+              el.muilesId = element.muilesId;
+              el.muilesName = element.muilesName;
+              el.startDate = element.startDate;
+              el.endDate = element.endDate;
+              el.planTime = element.planTime;
+              el.executors = element.executors;
+              el.realTime = element.realTime;
+            }
+          })
+        })
+      }
+    });
+  }
+
+  ///////////////////////////树形配置
+  mapOfExpandedData: { [key: string]: ProjectNodeTree[] } = {};
+
+  collapse(array: ProjectNodeTree[], data: ProjectNodeTree, $event: boolean): void {
+    if (!$event) {
+      if (data.children) {
+        data.children.forEach(d => {
+          const target = array.find(a => a.key === d.key)!;
+          target.expand = false;
+          this.collapse(array, target, false);
+        });
+      } else {
+        return;
+      }
+    }
+  }
+
+  convertTreeToList(root: ProjectNodeTree): ProjectNodeTree[] {
+    const stack: ProjectNodeTree[] = [];
+    const array: ProjectNodeTree[] = [];
+    const hashMap = {};
+    stack.push({ ...root, level: 0, expand: true });
+
+    while (stack.length !== 0) {
+      const node = stack.pop()!;
+      this.visitNode(node, hashMap, array);
+      if (node.children) {
+        for (let i = node.children.length - 1; i >= 0; i--) {
+          stack.push({ ...node.children[i], level: node.level! + 1, expand: true, parent: node });
+        }
+      }
+    }
+
+    return array;
+  }
+
+  visitNode(node: ProjectNodeTree, hashMap: { [key: string]: boolean }, array: ProjectNodeTree[]): void {
+    if (!hashMap[node.key]) {
+      hashMap[node.key] = true;
+      array.push(node);
+    }
   }
 }

+ 57 - 29
src/app/routes/project-manage-archives/add/essential-information/essential-information.component.html

@@ -58,10 +58,26 @@
           <nz-input-number [(ngModel)]="projectManageArchivesa.totalPrice" formControlName="totalPrice" id="totalPrice"
             [nzMin]="0" [nzStep]="1" [nzFormatter]="formatterDollar" [nzParser]="parserDollar"
             (keyup)="getProjectManageArchivesa()"></nz-input-number>
+          <nz-form-explain *ngIf="validateForm.get('totalPrice')?.dirty && validateForm.get('totalPrice')?.errors">
+            请输入项目总金额
+          </nz-form-explain>
+        </nz-form-control>
+
+      </nz-form-item>
+    </div>
+    <div nz-col [nzSpan]="6">
+      <nz-form-item>
+        <nz-form-label [nzSpan]="'vertical' ? 24 : null" [nzXs]="24" nzRequired>里程碑类型</nz-form-label>
+        <nz-form-control [nzSm]="24" [nzXs]="24">
+          <nz-select style="widows: 100%;" nzShowSearch nzAllowClear formControlName="milestoneId" id="milestoneId"
+            [(ngModel)]="projectManageArchivesa.milestoneId" nzPlaceHolder="请选择"
+            (ngModelChange)="milestoneChange($event)">
+            <nz-option *ngFor="let i of milestoneList" [nzValue]="i.value" [nzLabel]="i.text"></nz-option>
+          </nz-select>
+          <nz-form-explain *ngIf="validateForm.get('milestoneId')?.dirty && validateForm.get('milestoneId')?.errors">
+            请选择里程碑
+          </nz-form-explain>
         </nz-form-control>
-        <nz-form-explain *ngIf="validateForm.get('totalPrice')?.dirty && validateForm.get('totalPrice')?.errors">
-          请输入项目总金额
-        </nz-form-explain>
       </nz-form-item>
     </div>
   </div>
@@ -70,9 +86,10 @@
       <nz-form-item>
         <nz-form-label [nzSpan]="'vertical' ? 24 : null" [nzXs]="24">销售经理</nz-form-label>
         <nz-form-control [nzSm]="24" [nzXs]="24">
-          <nz-tree-select style="width: 100%" [nzNodes]="personnelList" nzShowSearch [nzMultiple]="false"
+          <nz-tree-select style="width: 100%" [nzNodes]="saleManagerList" nzShowSearch [nzMultiple]="false"
             formControlName="saleManagerId" id="saleManagerId" nzPlaceHolder="请选择"
-            [(ngModel)]="projectManageArchivesa.saleManagerId" [nzMaxTagCount]="3" [nzAllowClear]="true">
+            [(ngModel)]="projectManageArchivesa.saleManagerId" [nzMaxTagCount]="3" [nzAllowClear]="true"
+            (ngModelChange)="managerChange($event,'1')">
           </nz-tree-select>
         </nz-form-control>
       </nz-form-item>
@@ -81,10 +98,14 @@
       <nz-form-item>
         <nz-form-label [nzSpan]="'vertical' ? 24 : null" [nzXs]="24">业务员</nz-form-label>
         <nz-form-control [nzSm]="24" [nzXs]="24">
-          <nz-select [nzMaxTagCount]="3" nzMode="multiple" nzPlaceHolder="请选择" formControlName="saleManIds"
+          <!-- <nz-select [nzMaxTagCount]="3" nzMode="multiple" nzPlaceHolder="请选择" formControlName="saleManIds"
             id="saleManIds" [(ngModel)]="saleManIds">
             <nz-option *ngFor="let item of personnelList" [nzLabel]="item.id" [nzValue]="item.name"></nz-option>
-          </nz-select>
+          </nz-select> -->
+          <nz-tree-select style="width: 100%" [nzNodes]="personnelList" nzShowSearch [nzMultiple]="true"
+            formControlName="saleManIds" id="saleManIds" nzPlaceHolder="请选择" [(ngModel)]="saleManIds"
+            [nzMaxTagCount]="3" [nzAllowClear]="true" (ngModelChange)="personnelChange($event,'1')">
+          </nz-tree-select>
         </nz-form-control>
       </nz-form-item>
     </div>
@@ -94,10 +115,11 @@
       <nz-form-item>
         <nz-form-label [nzSpan]="'vertical' ? 24 : null" [nzXs]="24">实施项目经理</nz-form-label>
         <nz-form-control [nzSm]="24" [nzXs]="24">
-          <nz-select style="widows: 100%;" nzShowSearch nzAllowClear formControlName="impManagerId" id="impManagerId"
-            [(ngModel)]="projectManageArchivesa.impManagerId" nzPlaceHolder="请选择">
-            <nz-option *ngFor="let i of personnelList" [nzValue]="i.id" [nzLabel]="i.code"></nz-option>
-          </nz-select>
+          <nz-tree-select style="width: 100%" [nzNodes]="impManagerList" nzShowSearch [nzMultiple]="false"
+            formControlName="impManagerId" id="impManagerId" nzPlaceHolder="请选择"
+            [(ngModel)]="projectManageArchivesa.impManagerId" [nzMaxTagCount]="3" [nzAllowClear]="true"
+            (ngModelChange)="managerChange($event,'2')">
+          </nz-tree-select>
         </nz-form-control>
       </nz-form-item>
     </div>
@@ -105,10 +127,14 @@
       <nz-form-item>
         <nz-form-label [nzSpan]="'vertical' ? 24 : null" [nzXs]="24">实施顾问</nz-form-label>
         <nz-form-control [nzSm]="24" [nzXs]="24">
-          <nz-select [nzMaxTagCount]="3" nzMode="multiple" nzPlaceHolder="请选择" formControlName="impConsultantIds"
+          <!-- <nz-select [nzMaxTagCount]="3" nzMode="multiple" nzPlaceHolder="请选择" formControlName="impConsultantIds"
             id="impConsultantIds" [(ngModel)]="impConsultantIds">
             <nz-option *ngFor="let item of personnelList" [nzLabel]="item.id" [nzValue]="item.name"></nz-option>
-          </nz-select>
+          </nz-select> -->
+          <nz-tree-select style="width: 100%" [nzNodes]="personnelList" nzShowSearch [nzMultiple]="true"
+            formControlName="impConsultantIds" id="impConsultantIds" nzPlaceHolder="请选择" [(ngModel)]="impConsultantIds"
+            [nzMaxTagCount]="3" [nzAllowClear]="true" (ngModelChange)="personnelChange($event,'2')">
+          </nz-tree-select>
         </nz-form-control>
       </nz-form-item>
     </div>
@@ -118,10 +144,11 @@
       <nz-form-item>
         <nz-form-label [nzSpan]="'vertical' ? 24 : null" [nzXs]="24">开发项目经理</nz-form-label>
         <nz-form-control [nzSm]="24" [nzXs]="24">
-          <nz-select style="widows: 100%;" nzShowSearch nzAllowClear formControlName="deManagerId" id="deManagerId"
-            [(ngModel)]="projectManageArchivesa.deManagerId" nzPlaceHolder="请选择">
-            <nz-option *ngFor="let i of personnelList" [nzValue]="i.id" [nzLabel]="i.code"></nz-option>
-          </nz-select>
+          <nz-tree-select style="width: 100%" [nzNodes]="deManagerList" nzShowSearch [nzMultiple]="false"
+            formControlName="deManagerId" id="deManagerId" nzPlaceHolder="请选择"
+            [(ngModel)]="projectManageArchivesa.deManagerId" [nzMaxTagCount]="3" [nzAllowClear]="true"
+            (ngModelChange)="managerChange($event,'3')">
+          </nz-tree-select>
         </nz-form-control>
       </nz-form-item>
     </div>
@@ -129,10 +156,10 @@
       <nz-form-item>
         <nz-form-label [nzSpan]="'vertical' ? 24 : null" [nzXs]="24">开发工程师</nz-form-label>
         <nz-form-control [nzSm]="24" [nzXs]="24">
-          <nz-select [nzMaxTagCount]="3" nzMode="multiple" nzPlaceHolder="请选择" formControlName="deEngineerIds"
-            id="deEngineerIds" [(ngModel)]="deEngineerIds">
-            <nz-option *ngFor="let item of personnelList" [nzLabel]="item.id" [nzValue]="item.name"></nz-option>
-          </nz-select>
+          <nz-tree-select style="width: 100%" [nzNodes]="personnelList" nzShowSearch [nzMultiple]="true"
+            formControlName="deEngineerIds" id="deEngineerIds" nzPlaceHolder="请选择" [(ngModel)]="deEngineerIds"
+            [nzMaxTagCount]="3" [nzAllowClear]="true" (ngModelChange)="personnelChange($event,'3')">
+          </nz-tree-select>
         </nz-form-control>
       </nz-form-item>
     </div>
@@ -142,10 +169,11 @@
       <nz-form-item>
         <nz-form-label [nzSpan]="'vertical' ? 24 : null" [nzXs]="24">服务经理</nz-form-label>
         <nz-form-control [nzSm]="24" [nzXs]="24">
-          <nz-select style="widows: 100%;" nzShowSearch nzAllowClear formControlName="seManagerId" id="seManagerId"
-            [(ngModel)]="projectManageArchivesa.seManagerId" nzPlaceHolder="请选择">
-            <nz-option *ngFor="let i of personnelList" [nzValue]="i.id" [nzLabel]="i.code"></nz-option>
-          </nz-select>
+          <nz-tree-select style="width: 100%" [nzNodes]="seManagerList" nzShowSearch [nzMultiple]="false"
+            formControlName="seManagerId" id="seManagerId" nzPlaceHolder="请选择"
+            [(ngModel)]="projectManageArchivesa.seManagerId" [nzMaxTagCount]="3" [nzAllowClear]="true"
+            (ngModelChange)="managerChange($event,'4')">
+          </nz-tree-select>
         </nz-form-control>
       </nz-form-item>
     </div>
@@ -153,10 +181,10 @@
       <nz-form-item>
         <nz-form-label [nzSpan]="'vertical' ? 24 : null" [nzXs]="24">服务工程师</nz-form-label>
         <nz-form-control [nzSm]="24" [nzXs]="24">
-          <nz-select [nzMaxTagCount]="3" nzMode="multiple" nzPlaceHolder="请选择" formControlName="seEngineerIds"
-            id="seEngineerIds" [(ngModel)]="seEngineerIds">
-            <nz-option *ngFor="let item of personnelList" [nzLabel]="item.id" [nzValue]="item.name"></nz-option>
-          </nz-select>
+          <nz-tree-select style="width: 100%" [nzNodes]="personnelList" nzShowSearch [nzMultiple]="true"
+            formControlName="seEngineerIds" id="seEngineerIds" nzPlaceHolder="请选择" [(ngModel)]="seEngineerIds"
+            [nzMaxTagCount]="3" [nzAllowClear]="true" (ngModelChange)="personnelChange($event,'4')">
+          </nz-tree-select>
         </nz-form-control>
       </nz-form-item>
     </div>

+ 159 - 15
src/app/routes/project-manage-archives/add/essential-information/essential-information.component.ts

@@ -19,7 +19,7 @@ export class ProjectManageArchivesAddEssentialInformationComponent implements On
     private fb: FormBuilder,
     private baseArchivesProjectApprovalService: BaseArchivesProjectApprovalService,
     private customerService: CustomerService,
-    private personnelService:PersonnelService
+    private personnelService: PersonnelService,
   ) {}
 
   ngOnInit(): void {
@@ -36,6 +36,7 @@ export class ProjectManageArchivesAddEssentialInformationComponent implements On
       deEngineerIds: [null],
       seManagerId: [null],
       seEngineerIds: [null],
+      milestoneId: [null, [Validators.required]]
     });
     this.getProList();
     this.getCusList();
@@ -56,6 +57,7 @@ export class ProjectManageArchivesAddEssentialInformationComponent implements On
   impConsultantIds = []; //实施顾问下拉选择绑定
   deEngineerIds = []; //开发工程师下拉选择绑定
   seEngineerIds = []; //服务工程师下拉选择绑定
+  milestoneList = []; //里程碑类型下拉数据
 
   /**
    * 查询项目立项
@@ -71,15 +73,41 @@ export class ProjectManageArchivesAddEssentialInformationComponent implements On
     });
   }
 
+  /**
+   * 里程碑类型选择事件
+   */
+  //回写里程碑类型到其他页签查询明细
+  @Output() milestone = new EventEmitter<{}>();
+  milestoneChange(event) {
+    if (event) {
+      this.milestoneList.forEach(element => {
+        if (element.value === event) {
+          this.projectManageArchivesa.milestoneType = element.text;
+        }
+      });
+      this.milestone.emit(this.projectManageArchivesa);
+    }
+  }
+
   /**
    * 项目立项选择事件
    * @param event 立项id
    */
   proChange(event) {
-    this.proList.forEach(element => {
+    this.getChild(this.proList, event);
+  }
+
+  //递归查找项目名称
+  getChild(list, event) {
+    list.forEach(element => {
       if (event === element.id) {
         this.projectManageArchivesa.proCode = element.code;
         this.projectManageArchivesa.proName = element.title;
+      } else {
+        //如果没找到则进入子集查找
+        if (element.children && element.children.length > 0) {
+          this.getChild(element.children, event);
+        }
       }
     });
   }
@@ -102,11 +130,11 @@ export class ProjectManageArchivesAddEssentialInformationComponent implements On
   /**
    * 客户档案选择事件
    */
-  cusChange(event){
+  cusChange(event) {
     this.cusList.forEach(element => {
-      if(event===element.id){
-        this.projectManageArchivesa.cusCode=element.code;
-        this.projectManageArchivesa.cusName=element.name;
+      if (event === element.id) {
+        this.projectManageArchivesa.cusCode = element.code;
+        this.projectManageArchivesa.cusName = element.name;
       }
     });
     this.getProjectManageArchivesa();
@@ -115,19 +143,135 @@ export class ProjectManageArchivesAddEssentialInformationComponent implements On
   /**
    * 人员下拉查询
    */
-  getPersonnelList(){
-    return new Promise(resolve => {
-      this.personnelService.queryApprover(sessionStorage.getItem("pkOrg")).then(response => {
-        this.personnelList = JSON.parse(JSON.stringify(response.result));
-        recursiveQuery(this.personnelList);
-        resolve();
+  saleManagerList = []; //销售经理下拉数据
+  impManagerList = []; //实施经理下拉数据
+  deManagerList = []; //开发项目经理数据
+  seManagerList = []; //服务项目经理数据
+  getPersonnelList() {
+    // return new Promise(resolve => {
+    //   this.personnelService.queryApprover(sessionStorage.getItem('pkOrg')).then(response => {
+    //     this.personnelList = JSON.parse(JSON.stringify(response.result));
+    //     this.saleManagerList = JSON.parse(JSON.stringify(response.result));
+    //     this.impManagerList = JSON.parse(JSON.stringify(response.result));
+    //     this.deManagerList = JSON.parse(JSON.stringify(response.result));
+    //     this.seManagerList = JSON.parse(JSON.stringify(response.result));
+    //     recursiveQuery(this.personnelList);
+    //     recursiveQuery(this.saleManagerList);
+    //     recursiveQuery(this.impManagerList);
+    //     recursiveQuery(this.deManagerList);
+    //     recursiveQuery(this.seManagerList);
+    //     resolve();
+    //   });
+    // });
+  }
+
+  /**
+   *  经理选择触发事件
+   * @param event 经理id
+   * @param type 经理类型
+   */
+  managerChange(event, type) {
+    if (event) {
+      this.saleManagerList.forEach(pkOrg => {
+        pkOrg.children.forEach(depart => {
+          depart.children.forEach(personnel => {
+            if (personnel.key === event) {
+              if (type === '1') {
+                //销售经理名称
+                this.projectManageArchivesa.saleManager = personnel.name;
+              } else if (type === '2') {
+                //实施项目经理名称
+                this.projectManageArchivesa.impManager = personnel.name;
+              } else if (type === '3') {
+                //开发项目经理名称
+                this.projectManageArchivesa.deManager = personnel.name;
+              } else if (type === '4') {
+                //服务经理名称
+                this.projectManageArchivesa.seManager = personnel.name;
+              }
+            }
+          });
+        });
       });
-    });
+      this.getProjectManageArchivesa();
+    }
+  }
+
+  /**
+   * 人员多选触发事件
+   * @param event 人员id
+   * @param type 经理类型
+   */
+  personnelChange(event, type) {
+    if (event) {
+      let names = '';
+      let ids = '';
+      let sort = 0;
+      //根据下拉数据获取名称
+      event.forEach(element => {
+        this.saleManagerList.forEach(pkOrg => {
+          pkOrg.children.forEach(depart => {
+            depart.children.forEach(personnel => {
+              if (personnel.key === element) {
+                if (names === '') {
+                  names = personnel.name;
+                  ids = personnel.key;
+                } else {
+                  names = names + '、' + personnel.name;
+                  ids = ids + '、' + personnel.key;
+                }
+                sort++;
+              }
+            });
+          });
+        });
+      });
+      //有数据则正常赋值
+      if (sort > 0) {
+        if (type === '1') {
+          //业务员
+          this.projectManageArchivesa.saleManId = ids;
+          this.projectManageArchivesa.saleMan = names;
+        } else if (type === '2') {
+          //实施顾问
+          this.projectManageArchivesa.impConsultantId = ids;
+          this.projectManageArchivesa.impConsultant = names;
+        } else if (type === '3') {
+          //开发工程师
+          this.projectManageArchivesa.deEngineerId = ids;
+          this.projectManageArchivesa.deEngineer = names;
+        } else if (type === '4') {
+          //服务工程师
+          this.projectManageArchivesa.seEngineerId = ids;
+          this.projectManageArchivesa.seEngineer = names;
+        }
+      } else {
+        //没数据则清空
+        if (type === '1') {
+          //业务员
+          this.projectManageArchivesa.saleManId = '';
+          this.projectManageArchivesa.saleMan = '';
+        } else if (type === '2') {
+          //实施顾问
+          this.projectManageArchivesa.impConsultantId = '';
+          this.projectManageArchivesa.impConsultant = '';
+        } else if (type === '3') {
+          //开发工程师
+          this.projectManageArchivesa.deEngineerId = '';
+          this.projectManageArchivesa.deEngineer = '';
+        } else if (type === '4') {
+          //服务工程师
+          this.projectManageArchivesa.seEngineerId = '';
+          this.projectManageArchivesa.seEngineer = '';
+        }
+      }
+      this.getProjectManageArchivesa();
+    }
   }
 
   //基本信息回写到其他页签
-  @Output() projectManageArchivesaEntiy= new EventEmitter<{}>();
-  getProjectManageArchivesa(){
+  @Output() projectManageArchivesaEntiy = new EventEmitter<{}>();
+  getProjectManageArchivesa() {
     this.projectManageArchivesaEntiy.emit(this.projectManageArchivesa);
   }
 

+ 23 - 12
src/app/routes/project-manage-archives/add/implementation/implementation.component.html

@@ -3,33 +3,33 @@
   <div nz-row [nzGutter]="24">
     <div nz-col [nzSpan]="6">
       <nz-form-item>
-        <nz-form-label [nzSpan]="6">客户编码</nz-form-label>
-        <nz-form-control [nzSm]="18" [nzXs]="24">{{projectManageArchives.proCode}}</nz-form-control>
+        <nz-form-label [nzSpan]="8">客户编码</nz-form-label>
+        <nz-form-control [nzSm]="16" [nzXs]="24">{{projectManageArchives.cusCode}}</nz-form-control>
       </nz-form-item>
     </div>
     <div nz-col [nzSpan]="6">
       <nz-form-item>
-        <nz-form-label [nzSpan]="6">客户名称</nz-form-label>
-        <nz-form-control [nzSm]="18" [nzXs]="24">{{projectManageArchives.cusName}}</nz-form-control>
+        <nz-form-label [nzSpan]="8">客户名称</nz-form-label>
+        <nz-form-control [nzSm]="16" [nzXs]="24">{{projectManageArchives.cusName}}</nz-form-control>
       </nz-form-item>
     </div>
     <div nz-col [nzSpan]="6">
       <nz-form-item>
-        <nz-form-label [nzSpan]="6">实施经理</nz-form-label>
-        <nz-form-control [nzSm]="18" [nzXs]="24">{{projectManageArchives.impManager}}</nz-form-control>
+        <nz-form-label [nzSpan]="8">实施项目经理</nz-form-label>
+        <nz-form-control [nzSm]="16" [nzXs]="24">{{projectManageArchives.impManager}}</nz-form-control>
       </nz-form-item>
     </div>
     <div nz-col [nzSpan]="6">
       <nz-form-item>
-        <nz-form-label [nzSpan]="6">实施顾问</nz-form-label>
-        <nz-form-control [nzSm]="18" [nzXs]="24">{{projectManageArchives.impConsultant}}</nz-form-control>
+        <nz-form-label [nzSpan]="8">实施顾问</nz-form-label>
+        <nz-form-control [nzSm]="16" [nzXs]="24">{{projectManageArchives.impConsultant}}</nz-form-control>
       </nz-form-item>
     </div>
   </div>
 </form>
 
 <!-- 汇款信息 -->
-<nz-card nzTitle="款信息" nzSize="small">
+<nz-card nzTitle="款信息" nzSize="small">
   <nz-table nzBordered nzSize="small" [nzNoResult]="' '" [nzShowPagination]="false">
     <tbody>
       <tr>
@@ -76,6 +76,7 @@
         nzTableLayout="fixed" [nzShowPagination]="false" [nzFrontPagination]="false">
         <thead>
           <tr>
+            <th nzAlign="center"></th>
             <th style="width: 10%;">里程碑</th>
             <th style="width: 20%;">开始时间</th>
             <th style="width: 20%;">结束时间</th>
@@ -93,7 +94,14 @@
               <tr *ngIf="(item.parent && item.parent.expand) || !item.parent">
                 <td [nzIndentSize]="item.level! * 20" [nzShowExpand]="!!item.children" [(nzExpand)]="item.expand"
                   (nzExpandChange)="collapse(mapOfExpandedData[data.key], item, $event)">
-                  {{ item.muilesId }}
+                </td>
+                <td>
+                  <ng-container *ngIf="item.id">
+                    {{ item.name }}
+                  </ng-container>
+                  <ng-container *ngIf="!item.id">
+                    <input nz-input [(ngModel)]="item.name" />
+                  </ng-container>
                 </td>
                 <td>
                   <nz-date-picker [(ngModel)]="item.startDate"></nz-date-picker>
@@ -105,10 +113,13 @@
                   <nz-input-number [(ngModel)]="item.planTime" [nzMin]="0" [nzStep]="1"></nz-input-number>
                 </td>
                 <td>
-                  <nz-select style="width: 100%;" [nzMaxTagCount]="3" nzMode="multiple" nzPlaceHolder="请选择"
+                  <!-- <nz-select style="width: 100%;" [nzMaxTagCount]="3" nzMode="multiple" nzPlaceHolder="请选择"
                     [(ngModel)]="item.executor">
                     <nz-option *ngFor="let item of personnelList" [nzLabel]="item.id" [nzValue]="item.name"></nz-option>
-                  </nz-select>
+                  </nz-select> -->
+                  <nz-tree-select style="width: 100%" [nzNodes]="personnelList" nzShowSearch [nzMultiple]="true"
+                    nzPlaceHolder="请选择" [(ngModel)]="item.executors" [nzMaxTagCount]="3" [nzAllowClear]="true">
+                  </nz-tree-select>
                 </td>
                 <td>
                   <nz-input-number [(ngModel)]="item.realTime" [nzMin]="0" [nzStep]="1"></nz-input-number>

+ 18 - 35
src/app/routes/project-manage-archives/add/implementation/implementation.component.ts

@@ -3,6 +3,8 @@ import { NzModalRef, NzMessageService } from 'ng-zorro-antd';
 import { _HttpClient } from '@delon/theme';
 import { ProjectManageArchives } from 'app/entity/project-manage-archives/project-manage-archives';
 import { ProjectNodeTree } from '../../project-node-tree';
+import { BaseArchivesMilestone } from 'app/entity/basedata/base-archives-milestone';
+import { BaseArchivesMilestoneService } from 'app/services/basedata/base-archives-milestone.service';
 
 @Component({
   selector: 'app-project-manage-archives-add-implementation',
@@ -12,7 +14,7 @@ export class ProjectManageArchivesAddImplementationComponent implements OnInit {
   
 
   constructor(
-    
+    private baseArchivesMilestoneService:BaseArchivesMilestoneService
   ) { }
 
   ngOnInit(): void {
@@ -21,7 +23,7 @@ export class ProjectManageArchivesAddImplementationComponent implements OnInit {
   
 
   projectManageArchives:ProjectManageArchives={};//项目档案主表实体
-  listOfMapData=[];//树形集合
+  listOfMapData:any=[];//树形集合
   personnelList=[];//人员下拉列表
   remittanceInformation:any={};//回款信息实体
 
@@ -30,37 +32,15 @@ export class ProjectManageArchivesAddImplementationComponent implements OnInit {
    * 获取树形集合
    */
   getTreeList() {
-    // this.baseArchivesMilestone.pkOrg=sessionStorage.getItem("pkOrg");//组织
-    // this.baseArchivesMilestoneService.getTreeList(this.baseArchivesMilestone).then((response)=>{
-    //   this.listOfMapData=response.result
-    //   this.getLoding();
+    // let baseArchivesMilestone=new BaseArchivesMilestone();
+    // baseArchivesMilestone.pkOrg=sessionStorage.getItem("pkOrg");//组织
+    // baseArchivesMilestone.typeId="2";
+    // this.baseArchivesMilestoneService.getTreeList(baseArchivesMilestone).then((response)=>{
+    //   if(response.result){
+    //     this.listOfMapData=response.result
+    //     this.getLoding();
+    //   }
     // })
-
-    this.listOfMapData = [
-      {
-        key: `1`,
-        id:"1",
-        muilesId: '001',
-        parentId:"0",
-        children: [
-          {
-            key: `1-1`,
-            id:"1-1",
-            muilesId: '001',
-            parentId:"1",
-            children:null
-          },
-        ],
-      },
-      {
-        key: `2`,
-        id:"2",
-        parentId:"0",
-        muilesId: '002',
-        children:null
-      }
-    ];
-    this.getLoding();
   }
 
   /**
@@ -90,6 +70,9 @@ export class ProjectManageArchivesAddImplementationComponent implements OnInit {
     return (this.add() + this.add() + this.add() + this.add() + this.add() + this.add() + this.add() + this.add());
   };
   addParent(){
+    this.listOfMapData.forEach(item => {
+      console.log(this.mapOfExpandedData[item.key]);
+    });
     this.listOfMapData=[
       ...this.listOfMapData,
       {key:this.adding()}
@@ -116,7 +99,7 @@ export class ProjectManageArchivesAddImplementationComponent implements OnInit {
     children.forEach(element => {
       // 是否和点击的数据相等
       // 相等则在此条数据加子数据
-      if (element.id == parentId) {
+      if (element.key == parentId) {
         // 是否存在自数据不存在则创建child
         if (element.children == null) {
           element.children = []
@@ -124,7 +107,7 @@ export class ProjectManageArchivesAddImplementationComponent implements OnInit {
         // 添加一条空的子数据到child
         element.children = [
           ...element.children,
-          { key: keyId, parentId: parentId}
+          { key: keyId, parentId: parentId,children:null}
         ]
         // this.mapOfExpandedData[element.key] = this.convertTreeToList(null);
         // this.initialValue();
@@ -194,7 +177,7 @@ export class ProjectManageArchivesAddImplementationComponent implements OnInit {
               el.startDate = element.startDate;
               el.endDate = element.endDate;
               el.planTime = element.planTime;
-              el.executor = element.executor;
+              el.executors = element.executors;
               el.realTime = element.realTime;
             }
           })

+ 142 - 14
src/app/routes/project-manage-archives/add/serviceta/serviceta.component.html

@@ -1,14 +1,142 @@
-<div class="modal-header">
-  <div class="modal-title">查看 {{ record.id }} 信息</div>
-</div>
-<nz-spin *ngIf="!i" class="modal-spin"></nz-spin>
-<div sv-container *ngIf="i">
-  <sv label="姓名">{{ i.owner }}</sv>
-  <sv label="会员卡号">32943898021309809423</sv>
-  <sv label="身份证">3321944288191034921</sv>
-  <sv label="联系方式">18112345678</sv>
-  <sv label="联系地址">曲丽丽 18100000000 浙江省杭州市西湖区黄姑山路工专路交叉路口</sv>
-</div>
-<div class="modal-footer">
-  <button nz-button type="button" (click)="close()">关闭</button>
-</div>
+<!-- 服务 -->
+<form nz-form>
+  <div nz-row [nzGutter]="24">
+    <div nz-col [nzSpan]="6">
+      <nz-form-item>
+        <nz-form-label [nzSpan]="8">客户编码</nz-form-label>
+        <nz-form-control [nzSm]="16" [nzXs]="24">{{projectManageArchives.cusCode}}</nz-form-control>
+      </nz-form-item>
+    </div>
+    <div nz-col [nzSpan]="6">
+      <nz-form-item>
+        <nz-form-label [nzSpan]="8">客户名称</nz-form-label>
+        <nz-form-control [nzSm]="16" [nzXs]="24">{{projectManageArchives.cusName}}</nz-form-control>
+      </nz-form-item>
+    </div>
+    <div nz-col [nzSpan]="6">
+      <nz-form-item>
+        <nz-form-label [nzSpan]="8">服务项目经理</nz-form-label>
+        <nz-form-control [nzSm]="16" [nzXs]="24">{{projectManageArchives.seManager}}</nz-form-control>
+      </nz-form-item>
+    </div>
+    <div nz-col [nzSpan]="6">
+      <nz-form-item>
+        <nz-form-label [nzSpan]="8">服务工程师</nz-form-label>
+        <nz-form-control [nzSm]="16" [nzXs]="24">{{projectManageArchives.seEngineer}}</nz-form-control>
+      </nz-form-item>
+    </div>
+  </div>
+</form>
+
+<!-- 汇款信息 -->
+<nz-card nzTitle="回款信息" nzSize="small">
+  <nz-table nzBordered nzSize="small" [nzNoResult]="' '" [nzShowPagination]="false">
+    <tbody>
+      <tr>
+        <td><strong>服务金额</strong></td>
+        <td>第一笔</td>
+        <td>{{remittanceInformation.price1}}</td>
+        <td>第二笔</td>
+        <td>{{remittanceInformation.price2}}</td>
+        <td>第三笔</td>
+        <td>{{remittanceInformation.price3}}</td>
+        <td>第四笔</td>
+        <td>{{remittanceInformation.price4}}</td>
+        <td>第五笔</td>
+        <td>{{remittanceInformation.price5}}</td>
+      </tr>
+      <tr>
+        <td><strong>实际回款</strong></td>
+        <td>{{remittanceInformation.milestone1}}</td>
+        <td>{{remittanceInformation.desc1}}</td>
+        <td>{{remittanceInformation.milestone2}}</td>
+        <td>{{remittanceInformation.desc2}}</td>
+        <td>{{remittanceInformation.milestone3}}</td>
+        <td>{{remittanceInformation.desc3}}</td>
+        <td>{{remittanceInformation.milestone4}}</td>
+        <td>{{remittanceInformation.desc4}}</td>
+        <td>{{remittanceInformation.milestone5}}</td>
+        <td>{{remittanceInformation.desc5}}</td>
+      </tr>
+    </tbody>
+  </nz-table>
+</nz-card>
+
+<!-- 实施计划 -->
+<nz-card nzTitle="服务计划" nzSize="small">
+  <div nz-row [nzGutter]="24">
+    <div nz-col [nzSpan]="24">
+      <!-- 新增按钮 -->
+      <button (click)="addParent()" nz-button nzType="primary">{{ 'button.add' | translate }}</button>
+    </div>
+  </div>
+  <div nz-row [nzGutter]="24">
+    <div nz-col [nzSpan]="24">
+      <nz-table style="padding-top: 5px;" nzSize="small" class="tableTdPadding" #expandTable [nzData]="listOfMapData"
+        nzTableLayout="fixed" [nzShowPagination]="false" [nzFrontPagination]="false">
+        <thead>
+          <tr>
+            <th></th>
+            <th style="width: 10%;">里程碑</th>
+            <th style="width: 20%;">开始时间</th>
+            <th style="width: 20%;">结束时间</th>
+            <th style="width: 10%;">计划人天</th>
+            <th style="width: 20%;">执行人</th>
+            <th style="width: 10%;">实际人天</th>
+            <th style="width: 10%;">操作</th>
+          </tr>
+        </thead>
+        <tbody>
+          <ng-container *ngFor="let data of expandTable.data">
+            <ng-container *ngFor="let item of mapOfExpandedData[data.key]">
+
+
+              <tr *ngIf="(item.parent && item.parent.expand) || !item.parent">
+                <td [nzIndentSize]="item.level! * 20" [nzShowExpand]="!!item.children" [(nzExpand)]="item.expand"
+                  (nzExpandChange)="collapse(mapOfExpandedData[data.key], item, $event)">
+                </td>
+                <td>
+                  <ng-container *ngIf="item.id">
+                    {{ item.name }}
+                  </ng-container>
+                  <ng-container *ngIf="!item.id">
+                    <input nz-input [(ngModel)]="item.name" />
+                  </ng-container>
+                </td>
+                <td>
+                  <nz-date-picker [(ngModel)]="item.startDate"></nz-date-picker>
+                </td>
+                <td>
+                  <nz-date-picker [(ngModel)]="item.endDate"></nz-date-picker>
+                </td>
+                <td>
+                  <nz-input-number [(ngModel)]="item.planTime" [nzMin]="0" [nzStep]="1"></nz-input-number>
+                </td>
+                <td>
+                  <!-- <nz-select style="width: 100%;" [nzMaxTagCount]="3" nzMode="multiple" nzPlaceHolder="请选择"
+                    [(ngModel)]="item.executor">
+                    <nz-option *ngFor="let item of personnelList" [nzLabel]="item.id" [nzValue]="item.name"></nz-option>
+                  </nz-select> -->
+                  <nz-tree-select style="width: 100%" [nzNodes]="personnelList" nzShowSearch [nzMultiple]="true"
+                  nzPlaceHolder="请选择"
+                  [(ngModel)]="item.executors" [nzMaxTagCount]="3" [nzAllowClear]="true">
+                </nz-tree-select>
+                </td>
+                <td>
+                  <nz-input-number [(ngModel)]="item.realTime" [nzMin]="0" [nzStep]="1"></nz-input-number>
+                </td>
+                <td>
+                  <a (click)="addChild(item.key)">{{ 'button.leve.lower' | translate }}</a>
+                  <nz-divider nzType="vertical"></nz-divider>
+                  <a nz-popconfirm nzTitle="{{'isdelete'|translate}}" nzOkText="{{ 'yes' | translate }}"
+                    nzCancelText="{{ 'no' | translate }}"
+                    (nzOnConfirm)="deleteRow(mapOfExpandedData[data.key],item,item.key)">{{ 'milestone.delete' | translate }}</a>
+                </td>
+              </tr>
+            </ng-container>
+          </ng-container>
+        </tbody>
+      </nz-table>
+    </div>
+  </div>
+</nz-card>

+ 201 - 11
src/app/routes/project-manage-archives/add/serviceta/serviceta.component.ts

@@ -1,26 +1,216 @@
 import { Component, OnInit } from '@angular/core';
 import { NzModalRef, NzMessageService } from 'ng-zorro-antd';
 import { _HttpClient } from '@delon/theme';
+import { BaseArchivesMilestoneService } from 'app/services/basedata/base-archives-milestone.service';
+import { ProjectManageArchives } from 'app/entity/project-manage-archives/project-manage-archives';
+import { BaseArchivesMilestone } from 'app/entity/basedata/base-archives-milestone';
+import { ProjectNodeTree } from '../../project-node-tree';
 
 @Component({
   selector: 'app-project-manage-archives-add-serviceta',
   templateUrl: './serviceta.component.html',
 })
 export class ProjectManageArchivesAddServicetaComponent implements OnInit {
-  record: any = {};
-  i: any;
-
-  constructor(
-    private modal: NzModalRef,
-    public msgSrv: NzMessageService,
-    public http: _HttpClient
-  ) { }
+  constructor(private baseArchivesMilestoneService: BaseArchivesMilestoneService) {}
 
   ngOnInit(): void {
-    this.http.get(`/user/${this.record.id}`).subscribe(res => this.i = res);
+    this.getTreeList();
+  }
+
+  projectManageArchives: ProjectManageArchives = {}; //项目档案主表实体
+  listOfMapData: any = []; //树形集合
+  personnelList = []; //人员下拉列表
+  remittanceInformation: any = {}; //回款信息实体
+
+  /**
+   * 获取树形集合
+   */
+  getTreeList() {
+    
+    // let baseArchivesMilestone = new BaseArchivesMilestone();
+    // baseArchivesMilestone.pkOrg = sessionStorage.getItem('pkOrg'); //组织
+    // baseArchivesMilestone.typeId = '4';
+    // this.baseArchivesMilestoneService.getTreeList(baseArchivesMilestone).then(response => {
+    //   if (response.result) {
+    //     this.listOfMapData = response.result;
+    //     this.getLoding();
+    //   }
+    // });
+  }
+
+  /**
+   * 初始化树形
+   */
+  getLoding() {
+    this.listOfMapData.forEach(item => {
+      this.mapOfExpandedData[item.key] = this.convertTreeToList(item);
+    });
+  }
+
+  /**
+   * 新增父级
+   */
+  //uuid
+  S4() {
+    return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
+  }
+  guid() {
+    return this.S4() + this.S4() + this.S4() + this.S4() + this.S4() + this.S4() + this.S4() + this.S4();
+  }
+  // 随机数
+  add() {
+    return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
+  }
+  adding() {
+    return this.add() + this.add() + this.add() + this.add() + this.add() + this.add() + this.add() + this.add();
+  }
+  addParent() {
+    this.listOfMapData.forEach(item => {
+      console.log(this.mapOfExpandedData[item.key]);
+    });
+    this.listOfMapData = [...this.listOfMapData, { key: this.adding() }];
+    // this.getLoding();
+    this.initialValue();
+  }
+
+  /**
+   * 新增子集
+   * @param parentId 父级id
+   * @param data 操作对象
+   */
+  addChild(parentId) {
+    this.getChild(this.listOfMapData, parentId);
+    this.initialValue();
+  }
+
+  /**
+   * 递归查询子集增加
+   */
+  getChild(children, parentId) {
+    var keyId = this.adding();
+    children.forEach(element => {
+      // 是否和点击的数据相等
+      // 相等则在此条数据加子数据
+      if (element.key == parentId) {
+        // 是否存在自数据不存在则创建child
+        if (element.children == null) {
+          element.children = [];
+        }
+        // 添加一条空的子数据到child
+        element.children = [...element.children, { key: keyId, parentId: parentId }];
+        // this.mapOfExpandedData[element.key] = this.convertTreeToList(null);
+        // this.initialValue();
+      } else {
+        if (element.children != null) {
+          this.getChild(element.children, parentId);
+        }
+      }
+    });
+  }
+
+  /**
+   * 删除行
+   */
+  deleteRow(array: ProjectNodeTree[], data: ProjectNodeTree, key) {
+    this.getdeleteRow(key, this.listOfMapData);
+    this.initialValue();
+  }
+
+  /**
+   * 递归删除
+   * @param itemsId 对象id
+   * @param list 需要删除对象的集合
+   * @param parent 父级对象
+   */
+  getdeleteRow(itemsId: string, list?: any, parent?: any) {
+    list.forEach((element, i) => {
+      //判断选中得数据是否有找到
+      if (element.key == itemsId) {
+        //找到则先判断对象是否有子集,有则删除
+        if (element.children != null && element.children.length > 0) {
+          element.children.splice(0, element.children.length);
+        }
+        //然后删除父极对象
+        list.splice(i, 1);
+        //判断父极是否存在子集
+        if (list.length == 0 && parent) {
+          parent.children = null;
+        }
+        this.listOfMapData = [...this.listOfMapData];
+        // this.getDataInitialization2();
+        // this.initialValue();
+      } else {
+        //没有则判断是否有子集 有则递归同样判断
+        if (element.children != null && element.children.length > 0) {
+          this.getdeleteRow(itemsId, element.children, element);
+        }
+      }
+    });
+  }
+
+  initialValue() {
+    this.listOfMapData.forEach(item => {
+      const data = this.mapOfExpandedData[item.key];
+      this.mapOfExpandedData[item.key] = this.convertTreeToList(item);
+      const mapData = this.mapOfExpandedData[item.key];
+      if (data && mapData) {
+        mapData.forEach(el => {
+          data.forEach(element => {
+            if (element.key === el.key) {
+              el.muilesId = element.muilesId;
+              el.muilesName = element.muilesName;
+              el.startDate = element.startDate;
+              el.endDate = element.endDate;
+              el.planTime = element.planTime;
+              el.executors = element.executors;
+              el.realTime = element.realTime;
+            }
+          });
+        });
+      }
+    });
+  }
+
+  ///////////////////////////树形配置
+  mapOfExpandedData: { [key: string]: ProjectNodeTree[] } = {};
+
+  collapse(array: ProjectNodeTree[], data: ProjectNodeTree, $event: boolean): void {
+    if (!$event) {
+      if (data.children) {
+        data.children.forEach(d => {
+          const target = array.find(a => a.key === d.key)!;
+          target.expand = false;
+          this.collapse(array, target, false);
+        });
+      } else {
+        return;
+      }
+    }
+  }
+
+  convertTreeToList(root: ProjectNodeTree): ProjectNodeTree[] {
+    const stack: ProjectNodeTree[] = [];
+    const array: ProjectNodeTree[] = [];
+    const hashMap = {};
+    stack.push({ ...root, level: 0, expand: true });
+
+    while (stack.length !== 0) {
+      const node = stack.pop()!;
+      this.visitNode(node, hashMap, array);
+      if (node.children) {
+        for (let i = node.children.length - 1; i >= 0; i--) {
+          stack.push({ ...node.children[i], level: node.level! + 1, expand: true, parent: node });
+        }
+      }
+    }
+
+    return array;
   }
 
-  close() {
-    this.modal.destroy();
+  visitNode(node: ProjectNodeTree, hashMap: { [key: string]: boolean }, array: ProjectNodeTree[]): void {
+    if (!hashMap[node.key]) {
+      hashMap[node.key] = true;
+      array.push(node);
+    }
   }
 }

+ 3 - 1
src/app/routes/project-manage-archives/project-node-tree.ts

@@ -12,7 +12,9 @@ export interface ProjectNodeTree {
     startDate?:string;
     endDate?:string;
     planTime?:string;
-    executor?:[];
+    executors?:[];
     realTime?:string;
     parentId?:string;
+    executor?:string;
+    executorId?:string;
   }

+ 1 - 1
src/app/routes/system/user/user.component.ts

@@ -122,7 +122,7 @@ export class SystemUserComponent implements OnInit {
     this.isVisible = true;
     this.id = id;
     this.title = this.i18NService.fanyi("agent") + ":[" + username + "]"
-    this.personnelService.queryApprover().then((response) => {
+    this.personnelService.queryApprover(null).then((response) => {
       this.nzOptions = response.result;
       this.nzOptions.forEach(e => {
         e.children.forEach(element => {

+ 7 - 0
src/app/services/basedata/base-archives-milestone.service.ts

@@ -41,4 +41,11 @@ export class BaseArchivesMilestoneService {
   async delete(body: any): Promise<BaseResponse<any>> {
     return await this.http.post<BaseResponse<any>>('basedata/baseArchivesMilestone/delete', body).toPromise();
   }
+
+  //查詢父级里程碑
+  async getAllParent(body: any): Promise<BaseResponse<Result<any>>> {
+    return await this.http
+      .get<BaseResponse<Result<any>>>('/basedata/baseArchivesMilestone/getAll', { params: body })
+      .toPromise();
+  }
 }