## 甘特图基本用例

  1. HTML文件
  ~~~
  <div class="flex-grow-1 flex flex-v unselectable">
    <!--加载中-->
    <ck-load [loadState]="ganttLoadState" heading="系统正在计算中..."></ck-load>
  
    <!--甘特图-->
    <ck-gantt title="甘特图" idField="equipmentLedgerId"
              [(selection)]="selection"
              [data]="data"
              [ganttItem]="ganttItem"
              [loadTableHeading]="loadTableHeading"
              [ganttStartRange]="ganttStartRange"
              [ganttEndRange]="ganttEndRange"
              [ganttHoliday]="ganttHoliday"
              ganttScaleSize="60"
              ganttMode="days"
              [cdController]="cdController"
              cdGroup="list"
              (mouseOverLineChange)="mouseOverLine($event)"
              (clickLineChange)="clickLineChange($event)">
      <!--甘特图任务线浮动层-->
      <div ganttLinePopoverContent>
        <p *ngIf="ganttLineData?.ganttCustom?.batchNumber">投产批号：<span>{{ganttLineData?.ganttCustom?.batchNumber}}</span>
        </p>
        <p *ngIf="ganttLineData?.ganttCustom?.structureName">
          结构名称：<span>{{ganttLineData?.ganttCustom?.structureName}}</span></p>
        <p *ngIf="ganttLineData?.ganttCustom?.processCode">工序编码：<span>{{ganttLineData?.ganttCustom?.processCode}}</span>
        </p>
        <p *ngIf="ganttLineData?.ganttCustom?.processName">工序名称：<span>{{ganttLineData?.ganttCustom?.processName}}</span>
        </p>
        <p *ngIf="ganttLineData?.ganttStartDate">开始时间：<span>{{ganttLineData?.ganttStartDate | date : "yyyy-MM-dd HH:mm:ss"}}</span>
        </p>
        <p *ngIf="ganttLineData?.ganttEndDate">
          结束时间：<span>{{ganttLineData?.ganttEndDate | date : "yyyy-MM-dd HH:mm:ss"}}</span></p>
      </div>
      <ck-table-column heading="所属部门" key="departmentName" width="130" sortable></ck-table-column>
      <ck-table-column heading="资产编码" key="code" width="85" sortable></ck-table-column>
      <ck-table-column heading="设备名称" key="equipmentName" width="170" sortable>
        <ng-template let-value let-row="row">
          <div style="position: relative" [title]="value">
            <div *ngIf="row.unlimitedCapacity == 1" class="ck-green-triangle-topRight" title="无限产能"></div>
            <div class="singleTextBeyondHide">
              {{value}}
            </div>
          </div>
        </ng-template>
      </ck-table-column>
      <ck-table-column heading="设备型号" key="equipmentModel" width="140" sortable></ck-table-column>
      <ck-table-column heading="工序数量" key="processCount" width="90" align="right" sortable></ck-table-column>
      <ck-table-column heading="开始时间" key="equipmentStartDate" width="160" sortable>
        <ng-template let-value>
          {{value | date : "yyyy-MM-dd HH:mm:ss"}}
        </ng-template>
      </ck-table-column>
      <ck-table-column heading="结束时间" key="equipmentEndDate" width="160" sortable>
        <ng-template let-value>
          {{value | date : "yyyy-MM-dd HH:mm:ss"}}
        </ng-template>
      </ck-table-column>
    </ck-gantt>
  </div>

  ~~~
  
  2. TS文件
  ~~~
  import { AfterContentInit, Component, HostBinding, OnInit } from "@angular/core";
  import { ChangeDetectorHandler } from "../../../casekey/utils/change-detector-handler";
  import { TestGanttService } from "./test-gantt.service";
  import { Utils } from "../../../casekey/utils/utils";
  import { GanttData } from "../../../casekey/gantt/gantt-data";
  import { GanttHoliday } from "../../../casekey/gantt/gantt-holiday";
  import { GanttItem } from "../../../casekey/gantt/gantt-item";
  
  @Component({
      selector: "ck-test-gantt",
      templateUrl: "test-gantt.component.html"
  })
  export class TestGanttComponent implements OnInit, AfterContentInit {
  
      @HostBinding("class.flex-component-v") flex: boolean = true;
  
      // 变更检测控制器
      cdController: ChangeDetectorHandler;
  
      // 加载中
      ganttLoadState: boolean = false;
  
      selection: any;
  
      data: any[];
  
      supplierProcessData: any[];
  
      schedulingData: any[];
  
      ganttHoliday: GanttHoliday[];
  
      // 表格提示
      loadTableHeading = "暂无数据";
  
      ganttLineData: any = {};
  
      ganttStartRange: number;
  
      ganttEndRange: number;
  
      ganttHolidayMap: any = {};
  
      ganttItem: GanttItem[];
  
      constructor(private testGanttService: TestGanttService) {
      }
  
      ngOnInit() {
          this.listEquipment();
      }
  
      ngAfterContentInit() {
          this.cdController = new ChangeDetectorHandler();
          this.cdController.reattachChangeDetector("list");
      }
  
      listEquipment() {
          // 开启加载中
          this.ganttLoadState = true;
          this.loadTableHeading = "";
          let departmentId: any = 53;
          let startDate: any = "2018-01-01";
          let endDate: any = "2018-01-15";
          this.testGanttService.listEquipment(departmentId, startDate, endDate).subscribe((response: any) => {
              if (response.success) {
                  // 分钟转毫秒，并且仅保留毫秒字段（millisecond）
                  this.ganttHoliday = Utils.numberToMillisecond(response.data.holiday, "minute", "minute", "millisecond", true);
                  // startDate 分钟转毫秒
                  this.schedulingData = Utils.numberToMillisecond(response.data.scheduling, "minute", "startDate", "_startDate");
                  // endDate 分钟转毫秒
                  this.schedulingData = Utils.numberToMillisecond(response.data.scheduling, "minute", "endDate", "_endDate");
                  // 甘特图的开始范围
                  this.ganttStartRange = Utils.findValueMin(this.schedulingData, "_startDate");
                  // 甘特图的结束范围
                  this.ganttEndRange = Utils.findValueMax(this.schedulingData, "_endDate");
                  // 制作 ganttData 数据
                  this.makeEquipmentGanttData();
              } else {
                  this.loadTableHeading = "暂无数据";
              }
              this.ganttLoadState = false;
          });
      }
  
      makeEquipmentGanttData() {
          let mapLedger: any = {};
          let mapProduction: any = {};
          let ledgerData: any[] = [];
          if (this.schedulingData != null && this.schedulingData.length > 0) {
              this.ganttItem = [];
              this.schedulingData.forEach((row) => {
                  if (!mapLedger[row.equipmentLedgerId]) {
                      ledgerData.push({
                          equipmentLedgerId: row.equipmentLedgerId,
                          code: row.code,
                          productionId: row.productionId,
                          batchNumber: row.batchNumber,
                          departmentName: row.departmentName,
                          equipmentName: row.equipmentName,
                          equipmentModel: row.equipmentModel,
                          unlimitedCapacity: row.unlimitedCapacity
                      });
                      mapLedger[row.equipmentLedgerId] = true;
                  }
  
                  // 批次数组
                  if (!mapProduction[row.productionId]) {
                      this.ganttItem.push({
                          id: row.productionId,
                          name: "投产批号【" + row.batchNumber + "】"
                      });
                      mapProduction[row.productionId] = true;
                  }
              });
  
              ledgerData.forEach((data) => {
                  data.ganttData = [];
                  this.schedulingData.forEach((rowSource) => {
                      if (data.equipmentLedgerId === rowSource.equipmentLedgerId) {
                          let ganttData: GanttData = {
                              ganttItemId: rowSource.productionId,
                              ganttId: Utils.newId("supplier"),
                              ganttName: rowSource.processName,
                              ganttStartDate: rowSource._startDate,
                              ganttEndDate: rowSource._endDate,
                              ganttCustom: {
                                  batchNumber: rowSource.batchNumber,
                                  structureName: rowSource.structureName,
                                  processCode: rowSource.processCode,
                                  processName: rowSource.processName
                              }
                          };
                          data.ganttData.push(ganttData);
                      }
                  });
                  data.equipmentStartDate = Utils.findValueMin(this.schedulingData, "_startDate", "equipmentLedgerId", data.equipmentLedgerId);
                  data.equipmentEndDate = Utils.findValueMax(this.schedulingData, "_endDate", "equipmentLedgerId", data.equipmentLedgerId);
                  data.processCount = data.ganttData.length;
              });
          }
          this.data = ledgerData;
          this.ganttLoadState = false;
          this.loadTableHeading = "暂无数据";
      }
  
      /**
       * 鼠标经过甘特图线条时回调事件
       * @param lineEvent
       */
      mouseOverLine(lineEvent: any) {
          if (!!lineEvent) {
              this.ganttLineData = lineEvent.ganttLineData;
          }
  
      }
  
      /**
       * 鼠标点击甘特图线条后回调事件
       * @param lineEvent
       */
      clickLineChange(lineEvent: any) {
          console.log("lineEvent:" + lineEvent);
      }
  
  }
  ~~~
  
  
  ## 树结构甘特图基本用例
  
  1. HTML 文件
  ~~~
  <div class="flex-grow-1 flex flex-v unselectable">
    <!--加载中-->
    <ck-load [loadState]="ganttLoadState" heading="系统正在计算中..."></ck-load>
  
    <!--结构模式-->
    <ck-tree-gantt
        title="已投计划"
        [(selection)]="selection"
        [data]="data"
        [loadTableHeading]="loadTableHeading"
        [ganttStartRange]="ganttStartRange"
        [ganttEndRange]="ganttEndRange"
        [ganttHoliday]="ganttHoliday"
        ganttScaleSize="60"
        ganttMode="days"
        [cdController]="cdController"
        cdGroup="list"
        (mouseOverLineChange)="mouseOverLine($event)"
        (clickLineChange)="clickLineChange($event)">
      <!--甘特图任务线浮动层-->
      <div ganttLinePopoverContent>
        <p *ngIf="ganttLineData?.ganttCustom?.structureName">结构名称：<span>{{ganttLineData?.ganttCustom?.structureName}}</span></p>
        <p *ngIf="ganttLineData?.ganttStartDate">开始时间：<span>{{ganttLineData?.ganttStartDate | date : "yyyy-MM-dd HH:mm:ss"}}</span></p>
        <p *ngIf="ganttLineData?.ganttEndDate">结束时间：<span>{{ganttLineData?.ganttEndDate | date : "yyyy-MM-dd HH:mm:ss"}}</span></p>
      </div>
      <ck-table-column heading="结构编码" key="structureCode" width="150" sortable></ck-table-column>
      <ck-table-column heading="结构名称" key="structureName" width="150" sortable></ck-table-column>
      <ck-table-column heading="加工总量" key="planQty" width="90" align="right" sortable></ck-table-column>
      <ck-table-column heading="工序数量" key="processCount" width="90" align="right" sortable></ck-table-column>
      <ck-table-column heading="开始时间" key="structureStartDate" width="160" sortable>
        <ng-template let-value>
          {{value | date : "yyyy-MM-dd HH:mm:ss"}}
        </ng-template>
      </ck-table-column>
      <ck-table-column heading="结束时间" key="structureEndDate" width="160" sortable>
        <ng-template let-value>
          {{value | date : "yyyy-MM-dd HH:mm:ss"}}
        </ng-template>
      </ck-table-column>
    </ck-tree-gantt>
  </div>

  ~~~
  2. TS 文件
  ~~~
  import { AfterContentInit, Component, HostBinding, OnInit } from "@angular/core";
  import { ChangeDetectorHandler } from "../../../casekey/utils/change-detector-handler";
  import { Utils } from "../../../casekey/utils/utils";
  import { GanttData } from "../../../casekey/gantt/gantt-data";
  import { GanttHoliday } from "../../../casekey/gantt/gantt-holiday";
  import { CkTreeNode } from "../../../casekey/tree/tree-node";
  import { TestGanttService } from "./test-gantt.service";
  
  @Component({
      selector: "ck-test-tree-gantt",
      templateUrl: "test-tree-gantt.component.html"
  })
  export class TestTreeGanttComponent implements OnInit, AfterContentInit {
  
      @HostBinding("class.flex-component-v") flex: boolean = true;
  
      // 变更检测控制器
      cdController: ChangeDetectorHandler;
  
      // 加载中
      ganttLoadState: boolean = false;
  
      selection: any;
  
      data: CkTreeNode[];
  
      schedulingData: any[];
  
      ganttHoliday: GanttHoliday[];
  
      // 表格提示
      loadTableHeading = "暂无数据";
  
      ganttLineData: any = {};
  
      ganttStartRange: number;
  
      ganttEndRange: number;
  
      ganttHolidayMap: any = {};
  
      constructor(private testGanttService: TestGanttService) {
      }
  
      ngOnInit() {
          this.list();
      }
  
      ngAfterContentInit() {
          this.cdController = new ChangeDetectorHandler();
          this.cdController.reattachChangeDetector("list");
      }
  
      list() {
          // 开启加载中
          this.ganttLoadState = true;
          this.loadTableHeading = "";
          let productionId = "2096";
          this.testGanttService.list(productionId).subscribe((response: any) => {
              if (response.success) {
                  // 分钟转毫秒，并且仅保留毫秒字段（millisecond）
                  this.ganttHoliday = Utils.numberToMillisecond(response.data.holiday, "minute", "minute", "millisecond", true);
                  // startDate 分钟转毫秒
                  this.schedulingData = Utils.numberToMillisecond(response.data.scheduling, "minute", "startDate", "_startDate");
                  // endDate 分钟转毫秒
                  this.schedulingData = Utils.numberToMillisecond(response.data.scheduling, "minute", "endDate", "_endDate");
                  // 甘特图的开始范围
                  this.ganttStartRange = Utils.findValueMin(this.schedulingData, "_startDate");
                  // 甘特图的结束范围
                  this.ganttEndRange = Utils.findValueMax(this.schedulingData, "_endDate");
                  // 制作 ganttData 数据
                  this.makeGanttData();
              } else {
                  this.loadTableHeading = "暂无数据";
              }
              this.ganttLoadState = false;
          });
      }
  
      makeGanttData() {
          let structureData: any[] = [];
          let structureDataMap: any = {};
          if (this.schedulingData != null && this.schedulingData.length > 0) {
              this.schedulingData.forEach((row) => {
                  if (!structureDataMap[row.structureId]) {
                      structureData.push({
                          id: row.structureId,
                          structureId: row.structureId,
                          structurePid: row.structurePid,
                          structureCode: row.structureCode,
                          structureName: row.structureName,
                          planQty: row.planQty,
                      });
                      structureDataMap[row.structureId] = true;
                  }
              });
  
              structureData.forEach((data) => {
                  data.ganttData = [];
  
                  // 加工总量（为空或者0时，不计算开始时间与结束时间，不显示甘特图线条）
                  if (data.planQty != null && data.planQty > 0) {
                      data.structureStartDate = Utils.findValueMin(this.schedulingData, "_startDate", "structureId", data.structureId);
                      data.structureEndDate = Utils.findValueMax(this.schedulingData, "_endDate", "structureId", data.structureId);
                      // 甘特图数据源
                      let ganttData: GanttData = {
                          ganttItemId: "2096",
                          ganttId: Utils.newId("structure"),
                          ganttName: data.structureName,
                          ganttStartDate: data.structureStartDate,
                          ganttEndDate: data.structureEndDate,
                          ganttCustom: {
                              structureId: data.structureId,
                              structureName: data.structureName,
                          }
                      };
                      data.ganttData.push(ganttData);
                  }
              });
          }
  
          this.data = Utils.listToTreeData({data: structureData, idField: "structureId", pidField: "structurePid"});
  
          this.loadTableHeading = "暂无数据";
      }
  
      /**
       * 鼠标经过甘特图线条时回调事件
       * @param lineEvent
       */
      mouseOverLine(lineEvent: any) {
          if (!!lineEvent) {
              this.ganttLineData = lineEvent.ganttLineData;
          }
  
      }
  
      /**
       * 鼠标点击甘特图线条后回调事件
       * @param lineEvent
       */
      clickLineChange(lineEvent: any) {
          console.log("lineEvent:" + lineEvent);
      }
  
  }
  
  ~~~