<template>
  <a-drawer
    width="100%"
    :visible="show"
    @close="close"
    :after-visible-change="openDrawer"
    :destroy-on-close="true"
    class="jobmonitoring_container"
  >
    <template slot="title">
      <a-button @click="close" icon="caret-left" class="a_back"></a-button>
      <span class="detail_title">
        实时任务监控
        <template v-if="data.jobType=='datadev'">(数据开发)</template>
      </span>
      <div class="refresh">
        <a-button type="link" @click="toJobTask">查看调度任务</a-button>
        <span @click="refresh">刷新&nbsp;<a-icon type="reload" /></span>
      </div>
    </template>
    <div class="jobmonitoring_content">
      <a-card size="small" title="任务信息概览" class="no_border">
        <a-row class="card-list" :gutter="20">
          <a-col :span="6">任务名称：{{data.jobName}}</a-col>
          <a-col :span="6">状态：
            <a-tag class="tag_or" v-if="data.taskState == 'SUCCESS'">运行成功</a-tag>
            <a-tag class="tag_value" v-else-if="data.taskState == 'RUNNING'">运行中</a-tag>
            <a-tag class="tag_and" v-else-if="data.taskState == 'WALKING'">异常运行中</a-tag>
            <a-tag class="tag_entry" v-else>{{ returnTaskState(data.taskState) }}</a-tag>
          </a-col>
          <a-col :span="6">创建时间：{{data.createTime}}</a-col>
          <a-col :span="6">负责人：{{data.createBy || '--'}}</a-col>
        </a-row>
        <a-row class="card-list" :gutter="20">
          <a-col :span="6">所属集群：{{data.clusterName || '--'}}</a-col>
          <a-col :span="6">开始时间：{{data.startTime}}</a-col>
          <a-col :span="6">结束时间：{{data.endTime || '--'}}</a-col>
          <!-- <a-col :span="6">总吞吐量：{{mainNodeInf.length > 0 ? mainNodeInf[0].ioCount : '--'}}</a-col> -->
          <a-col :span="6">总吞吐量：{{taskList.length > 0 ? taskList[0].insertCount : '--'}}</a-col>
        </a-row>
        <a-row class="card-list last" :gutter="20">
          <a-col :span="6">任务ID：{{data.id}}</a-col>
          <a-col :span="6">作业ID：{{data.jobId}}</a-col>
        </a-row>
      </a-card>
      <div class="card_top">
        <a-tabs default-active-key="task">
          <a-tab-pane key="task" tab="任务展示">
            <div class="designer_process">
              <vxe-table
                ref="taskTree"
                show-overflow
                show-header-overflow
                border
                resizable
                :loading="taskLoading"
                :row-config="{ isHover: true }"
                :data="taskList"
                :row-class-name="getRowClass"
                @cell-click="cellClickEvent"
                :tree-config="{
                  expandAll: true,
                  reserve: true,
                  trigger: 'cell'
                }"
                height="auto"
              >
                <vxe-column type="seq" title="序号" width="80" align="center"></vxe-column>
                <vxe-column field="name" title="名称" tree-node></vxe-column>
                <vxe-column field="type" title="类别">
                  <template #default="{ row }">
                    {{ row.type | filterType }}
                  </template>
                </vxe-column>
                <vxe-column field="status" title="状态">
                  <template #default="{ row }">
                    <a-tag class="tag_or" v-if="row.status == 'SUCCESS'">运行成功</a-tag>
                    <a-tag class="tag_value" v-else-if="row.status == 'RUNNING'">运行中</a-tag>
                    <a-tag class="tag_and" v-else-if="row.status == 'WALKING'">异常运行中</a-tag>
                    <a-tag class="tag_entry" v-else>{{ returnTaskState(row.status) }}</a-tag>
                  </template>
                </vxe-column>
                <vxe-column field="runningCount" title="运行中/成功/失败">
                  <template #header="{}">
                    <span>运行中/成功/失败</span>
                    <a-tooltip placement="rightTop">
                      <template slot="title">flink任务数量，即"转换"的数量</template>
                      <a-icon type="info-circle" style="margin-left:5px;"/>
                    </a-tooltip>
                  </template>
                  <template #default="{ row }">
                    <span class="running">{{ row.runningCount || 0 }}</span>/
                    <span class="success">{{ row.successCount || 0 }}</span>/
                    <span class="fail">{{ row.failedCount || 0 }}</span>
                  </template>
                </vxe-column>
                <vxe-column field="title" title="操作" align="center" v-if="data.jobType=='datadev'">
                  <template #default="{ row }">
                    <a-button
                      v-if="row.type == 'model' || row.type == 'indicator'"
                      type="link"
                      @click="toDebug(row)"
                    >
                      调试
                    </a-button>
                    <span v-else>--</span>
                  </template>
                </vxe-column>

                <template #empty>
                  <a-empty
                    :image-style="{
                      height: '80px',
                    }"
                  >
                    <span slot="description"> 暂无数据 </span>
                  </a-empty>
                </template>
              </vxe-table>
            </div>
          </a-tab-pane>
          <a-tab-pane key="process" tab="流程预览" force-render>
            <a-spin :spinning="jobLoading">
              <div class="designer_process">
                <devLinkProcess v-if="data.jobType == 'datadev'" :jobId="data.jobId" :nodeList="linkNodeList"></devLinkProcess>
                <jobProcess
                  v-else
                  :jobId="data.jobId"
                  :dataDetail="jobProcessDetail"
                  :taskList="taskList"
                  @blankClickCallback="blankClickCallback"
                  @nodeClickCallback="nodeClickCallback"
                ></jobProcess>
              </div>
            </a-spin>
          </a-tab-pane>
        </a-tabs>
      </div>
      <a-card size="small" title="监控详情" class="no_border card_top date">
        <span slot="extra">
          <span class="search_label">时间范围：</span>
          <a-range-picker
            style="width:370px;"
            :allowClear="false"
            :locale="locale"
            :ranges="rangesDate"
            :disabled-date="disabledDate"
            :placeholder="['请选择','请选择']"
            :show-time="{ format: 'HH:mm:ss' }"
            :value="timeVal"
            format="YYYY-MM-DD HH:mm:ss"
            separator="至"
            @change="onTimeChange">
            <a-icon slot="suffixIcon" type="calendar" />
          </a-range-picker>
          <span style="margin-left: 12px;">
            自动刷新&nbsp;<a-switch v-model="isRefresh" @change="onRefreshChange" />
          </span>
        </span>
        <a-spin :spinning="recordLoading">
          <a-row :gutter="12">
            <a-col :span="14">
              <div class="record_list">
                <div id="record_monitoring" ref="record_monitoring" class="echarts"></div>
              </div>
            </a-col>
            <a-col :span="10">
              <div class="record_data">
                <div style="height: calc(100% - 38px)">
                  <vxe-table
                    show-overflow
                    show-header-overflow
                    border
                    resizable
                    :row-config="{ isHover: true }"
                    :data="recordLists"
                    height="auto"
                    show-footer
                    :footer-span-method="footerColspanMethod"
                    :footer-method="footerMethod"
                  >
                    <!-- <vxe-colgroup field="time" align="center" :title="`${paramsTime.startTime} ～ ${paramsTime.endTime}`"> -->
                      <vxe-column type="seq" title="序号" width="50" align="center"></vxe-column>
                      <vxe-column field="stepName" title="节点名称"> </vxe-column>
                      <vxe-column field="ioCount" title="吞吐量"></vxe-column>
                      <vxe-column field="period" title="区间时长"> </vxe-column>
                      <vxe-column field="cps" title="每秒吞吐量(个/秒)"> </vxe-column>
                    <!-- </vxe-colgroup> -->
                    <template #empty>
                      <a-empty
                        :image-style="{
                          height: '80px',
                        }"
                      >
                        <span slot="description"> 暂无数据 </span>
                      </a-empty>
                    </template>
                  </vxe-table>
                </div>
              </div>
            </a-col>
          </a-row>
        </a-spin>
      </a-card>
      <a-card size="small" title="运行日志" class="no_border card_top">
        <a-spin :spinning="logLoading">
          <div class="log_container">
            <logCollapse :data="logData"></logCollapse>
          </div>
        </a-spin>
      </a-card>
    </div>
    <debugDesign v-model="debugInfo.show" :type="debugInfo.type" :showEdit="false" :info="debugInfo.info"></debugDesign>
  </a-drawer>
</template>
<script>
import moment from 'moment';
/**
 * @Author: y_zp
 * @description: 实时监控
 */
const $dataIntegration = require("@/api/dataIntegration");
const $standardModel = require("@/api/datadevelopment/standardModel");
const logCollapse = require("@/components/logCollapse").default;
const devLinkProcess = require("../../components/devlinkprocess.vue").default;
const jobProcess = require("../../components/jobprocess.vue").default;
const debugDesign = require("@/components/debugDesign").default;

export default {
  components: {
    logCollapse,
    devLinkProcess,
    jobProcess,
    debugDesign
  },
  props: {
    visible: [Boolean],
    data: [Object]
  },
  computed:{
    show: {
      get() {
        return this.visible
      },
      set(val) {
        this.$emit('update:visible', val)
      }
    },
    returnTaskState() {
      return (val) => {
        let item = this.statueList.find(item => { return item.value ==  val})
          if (item) {
            return item.label;
          } else {
            return "未知"
          }
      }
    }
  },
  filters: {
    filterType(val) {
      switch(val) {
        case "job":
          return "作业"
        case "transform":
          return "转换"
        case "model":
          return "事实模型"
        case "sql":
          return "SQL"
        case "indicator":
          return "指标"
        default: 
          return "未知分类"
      }
    }
  },
  data() {
    let rangesDate = {
      近1小时: [moment().subtract(1, 'hours'), moment()],
      近2小时: [moment().subtract(2, 'hours'), moment()],
      近3小时: [moment().subtract(3, 'hours'), moment()]
    }
    return {
      timeVal: [moment().subtract(1, 'days'), moment()],
      rangesDate: rangesDate,
      recordParams: {
        startTime: moment().subtract(1, "days").format("YYYY-MM-DD HH:mm:ss"),
        endTime: moment().format("YYYY-MM-DD HH:mm:ss"),
      },
      paramsTime: {
        startTime: undefined,
        endTime: undefined,
      },
      recordDates: [],
      recordLoading: false,
      recordLists: [],
      curStepId: undefined,
      timer: undefined,
      taskLoading: false,
      taskList: [],
      jobLoading: false,
      job: {},
      logLoading: false,
      logData: [],
      isRefresh: true,
      statueList: [],
      linkNodeList: [],
      jobProcessDetail: {},
      debugInfo: {
        show: false,
        type: undefined,
        info: {}
      }
    }
  },
  created() {},
  methods: {
    /**
     * @Author: y_zp
     * @description: 设置不可选日期
     */
    disabledDate(cur) {
      return cur && cur > moment().endOf('day')
    },

    openDrawer(val) {
      if (val) {
        this.isRefresh = true;
        this.statueList = $dataIntegration.monitorStatueList;
        this.getTaskList();
        this.initData();
        this.getLog();
        this.getRecordChart();
        this.refreshFun();
      }
    },

    /**
     * @Author: y_zp
     * @description: 定时刷新数据
     */
    refreshFun() {
      this.timer = setInterval(() => {
        this.getTaskList();
        this.getRecordChart();
      }, 1000 * 15)
    },

    /**
     * @Author: y_zp
     * @description: 任务展示
     */
    getTaskList() {
      //定时刷新时，不需要加载loading
      this.taskList.length == 0 && (this.taskLoading = true);
      $dataIntegration
        .getTaskTree(this.data.id)
        .then((req) => {
          let info = req.data;
          if(!this.curStepId) {
            this.curStepId = info.stepId;
          }
          this.taskList = [];
          this.taskList.push(info);
        })
        .finally(() => {
          this.$refs.taskTree && this.$refs.taskTree.setAllTreeExpand(true);
          this.taskLoading = false;
          // 定时刷新时，需要更新节点状态
          // if (this.job.data && this.job.data.jsonDetail) {
          //   try {
          //     let cells = JSON.parse(this.job.data.jsonDetail);
          //     this.setCanvas(cells, this.job);
          //   } catch (e) {}
          // }

        })
    },
    /**
     * @Author: y_zp
     * @description: 自动刷新
     */
    onRefreshChange(val) {
      this.isRefresh = val;
      if (val) {
        this.refreshFun();
      } else {
        clearInterval(this.timer);
      }
    },

    /**
     * @Author: y_zp
     * @description: 整体刷新页面
     */
    refresh() {
      this.taskLoading = true;
      this.getTaskList();
      this.initData();
      this.getLog();
      this.getRecordChart();
    },
    /**
     * @Author: y_zp
     * @description: 任务展示点击列
     */
    cellClickEvent({ row }) {
      this.curStepId = row.stepId;
      this.getRecordChart()
    },

    getRowClass({ row }) {
      console.log()
      return row.stepId == this.curStepId ? "row--current" : "";
    },

    /**
     * @Author: y_zp
     * @description: 运行日志
     */
    getLog() {
      this.logLoading = true;
      if (this.data.jobType == "datadev") {
        $standardModel
          .getMonitorTaskLog(this.data.id)
          .then((req) => {
            this.logData = req.data;
          })
          .finally(() => {
            this.logLoading = false;
          })
      } else {
        $dataIntegration
          .getTaskLog(this.data.id)
          .then((req) => {
            this.logData = req.data;
          })
          .finally(() => {
            this.logLoading = false;
          })
      }
    },

    /**
     * @Author: y_zp
     * @description: 监控详情
     */
    getRecordChart() {
      if(this.$refs.record_monitoring){
        this.recordLoading = true;
        let myChart = this.$echarts.init(
          document.getElementById("record_monitoring")
        );
        let option = {
          tooltip: {
            trigger: "axis",
          },
          grid: {
            top: '10%',
            left: "3%",
            right: "4%",
            bottom: "7%",
            containLabel: true
          },
          color: ['#2D5AFA'],
          xAxis: {
            type: "category",
            data: []
          },
          yAxis: {
            name: "单位：个",
            type: "value",
            splitLine: {
              lineStyle: {
                type: 'dashed'
              }
            }
          },
          series: [{
            type: "line",
            lineStyle: {
              width: 2,
            },
            data: [],
            smooth: true
          }],
        }
        if (this.isRefresh) {
          //开启刷新，就会一直更新时间
          let curTime = moment();
          let diff = curTime.diff(this.recordParams.endTime);
          this.recordParams = {
            startTime: moment(this.recordParams.startTime).add(diff, "milliseconds").format("YYYY-MM-DD HH:mm:ss"),
            endTime: moment().format("YYYY-MM-DD HH:mm:ss"),
          }
          this.timeVal = [moment(this.recordParams.startTime), moment(this.recordParams.endTime)];
        }
        $dataIntegration
        .getRuntimeData({
          taskId: this.data.id,
          stepId: this.curStepId,
          ...this.recordParams
        })
        .then((req) => {
          let info = req.data[this.curStepId];
          if (info) {
            this.recordDates = info.dates || [];
            option.xAxis.data = info.xs;
            option.series[0].data = info.values;
          } else {
            this.recordDates = [];
            option.xAxis.data = [];
            option.series[0].data = [];
          }
          // 获取实时监控数据
          this.getRecordLists();
        })
        .finally(() => {
          myChart.setOption(option);
        });
      }else{
        this.$nextTick(()=>{
          setTimeout(() => {
            this.getRecordChart();
          }, 300);
        })
      }
    },

    /**
     * @Author: y_zp
     * @description: 获取实时监控-list
     */
    getRecordLists() {
      $dataIntegration
        .getRuntimeIoCount({
          taskId: this.data.id,
          stepId: this.curStepId,
          ...this.recordParams
        })
        .then((req) => {
          let info = req.data;
          this.recordLists = [];
          if (info[this.curStepId]) {
            this.recordLists.push(info[this.curStepId]);
          }
        })
        .finally(() => {
          this.recordLoading = false
        });
    },

    /**
     * @Author: y_zp
     * @description: 时间选择
     */
    onTimeChange(date, dateString) {
      this.recordParams.startTime = dateString[0];
      this.recordParams.endTime = dateString[1];
      let curTime = moment();
      let diff = curTime.diff(this.recordParams.endTime);
      // 超过一分钟，关掉定时刷新
      if (Number(diff) > 1000*60) {
        this.isRefresh = false;
        clearInterval(this.timer);
      } else {
        this.isRefresh = true;
      }
      this.timeVal = [moment(dateString[0]), moment(dateString[1])];
      this.querySearch()
    },

    /**
     * @Author: y_zp
     * @description: 查询
     */
    querySearch(id) {
      if(id) {
        this.curStepId = id;
      }
      this.getRecordChart()
    },

    /**
     * @Author: 
     * @description: 流程预览
     */
    initData() {
      this.jobLoading = true;
      if(this.data.jobType == "datadev") {
        $standardModel
          .getMonitorNodeList({ linkId: this.data.jobId })
          .then((req) => {
            this.linkNodeList = req.data;
        }).finally(() => {
          this.jobLoading = false;
        })
      } else {
        $dataIntegration
          .getJobDetail({ id: this.data.jobId })
          .then((req) => {
            let job = req.data;
            if (job) {
              this.jobProcessDetail = job
            } else {
              this.jobLoading = false;
            }
          }).finally(() => {
            this.jobLoading = false;
          })
      }
    },

    blankClickCallback() {
      this.querySearch(this.taskList[0].stepId)
    },

    nodeClickCallback(val) {
      this.curStepId = val;
      this.getRecordChart()
    },

    /**
     * @Author: y_zp
     * @description: 获取实时监控-list 求和
     */
    sumNum (list, field) {
      let count = 0
      list.forEach(item => {
        count += Number(item[field])
      })
      return count
    },
    footerMethod ({ columns, data }) {
      const footerData = [
        columns.map((column, _columnIndex) => {
           if (_columnIndex === 0) {
            return '合计'
          }
          if (['jobId'].includes(column.property)) {
            return '合计'
          }
          if (['ioCount', 'period', 'cps', 'delay'].includes(column.property)) {
            return column.property == "period" ? "--" : this.sumNum(data, column.property);
          }
          return null
        })
      ]
      return footerData
    },

    /**
     * @Author: y_zp
     * @description: 获取实时监控-list 合并
     */
    footerColspanMethod ({ _columnIndex }) {
      if (_columnIndex === 0) {
        return {
          rowspan: 1,
          colspan: 2
        }
      } else if (_columnIndex === 1) {
        return {
          rowspan: 0,
          colspan: 0
        }
      }
    },
    /**
     * @Author: y_zp
     * @description: 查看调度任务
     */
    toJobTask() {
      this.$router.push({
        path: "/realtimeTasks",
        query: {
          type: "REALTIME",
          scheduleJobId: this.data.jobInfoId,
        }
      });
      this.close();
    },

    /**
     * @Author: y_zp
     * @description: 调试
     */
    toDebug(row) {
      console.log(row)
      this.debugInfo = {
        show: true,
        type: row.type == "indicator" ? 2 : 1,
        info: {
          id: row.stepId
        }
      }
    },

    close() {
      this.show = false;
      this.curStepId = undefined;
      this.taskList = [];
      this.recordParams = {
        startTime: moment().subtract(1, "days").format("YYYY-MM-DD HH:mm:ss"),
        endTime: moment().format("YYYY-MM-DD HH:mm:ss"),
      };
      this.timer && clearInterval(this.timer);
      this.job.graph && this.job.graph.dispose(); //销毁画布
    }

  }
}
</script>
<style lang="less" scoped>
.jobmonitoring_container {
  .a_back {
    position: absolute;
    top:0;
    left: 0;
    width: 54px;
    height: 54px;
    border: 0;
    font-size: 20px;
    color: rgba(0, 0, 0, 0.7);
    border-radius: 0;
    border-right: 1px solid #e9e9e9;
    &:hover {
      background: rgba(0, 0, 0, 0.1);
    }
  }
  .detail_title {
    margin-left: 40px;
  }
  .refresh {
    cursor: pointer;
    float: right;
    margin-right: 30px;
    .ant-btn {
      font-size: 16px;
      margin-top: -4px;
    }
  }
  .jobmonitoring_content {
    height: calc(100vh - 85px);
    overflow: hidden;
    overflow-y: scroll;
  }
  .ant-drawer-content {
    background: #eff2fd;
  }
  .search-icon {
    cursor: pointer;
    margin-left: 6px;
    color: #999;
    vertical-align: middle;
    font-size: 20px;
  }
  .card-list {
    padding: 8px 4px 0;
    &.last {
      padding-bottom: 12px;
    }
  }
  .card_top {
    margin-top: 12px;
  }
  .designer_process {
    width: 100%;
    height: 260px;
    .running {
      color: #2d5afa;
      margin: 0 5px;
    }
    .success {
      color: #29DF7E;
      margin: 0 5px;
    }
    .fail {
      color: #EA4B4B;
      margin: 0 5px;
    }
  }
  .echarts {
    width: 100%;
    height: 100%;
  }
  .record_list, .record_data {
    height: 310px;
  }
  .time {
    margin-bottom: 12px;
  }
  .log_container {
    padding-bottom: 12px;
    max-height: calc(100vh - 150px);
    overflow: hidden;
    overflow-y: scroll;
  }
}
</style>