<template>
  <div class="app-container">
    <div class="head-container">
      <!--工具栏-->
      <el-form :inline="true" class="demo-form-inline" label-suffix=":" label-width="80px">
        <el-form-item label="日志标签">
          <el-cascader
            v-model="labelAndValue"
            :options="labelsOptions"
            placeholder="请选择标签"
            @change="queryData"
          />
        </el-form-item>
        <el-form-item label="关键字">
          <label slot="label">关&nbsp;&nbsp;键&nbsp;字:</label>

          <el-input
            v-model="text"
            size="mini"
            placeholder="请输入内容"
            clearable
          />
        </el-form-item>
        <el-form-item v-show="!showOptions" label="时间范围">
          <el-date-picker
            v-model="timeRange"
            size="mini"
            clearable
            type="datetimerange"
            range-separator="至"
            start-placeholder="开始日期"
            end-placeholder="结束日期"
            align="right"
            @change="queryData"
            @blur="queryData"
          />
        </el-form-item>
        <el-form-item v-show="showOptions" label="时间段">
          <el-select v-model="timeZoneValue" filterable placeholder="请选择标签" size="mini" @change="queryData">
            <el-option
              v-for="item in timeZoneOptions"
              :key="item.index"
              :label="item.label"
              :value="item.value"
            />
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-tooltip class="item" effect="dark" content="切换查询条件" placement="top">
            <span class="el-icon-sort" @click="changeShow" />
          </el-tooltip>
        </el-form-item>
        <el-form-item label="方向">
          <label slot="label">方&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;向:</label>
          <el-radio-group v-model="direction" size="mini" @change="queryData">
            <el-radio label="backward">backward</el-radio>
            <el-radio label="forward">forward</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="显示条数">
          <el-input-number
            v-model="limits"
            size="mini"
            controls-position="right"
            :min="100"
            :max="5000"
            :step="100"
          />
        </el-form-item>
        <el-form-item label="滚动步数">
          <el-input-number
            v-model="scrollStep"
            size="mini"
            controls-position="right"
            :min="10"
            :max="2000"
            :step="10"
          />
        </el-form-item>
        <el-form-item>
          <el-dropdown split-button type="primary" size="mini" @click="queryData">
            查询{{ runStatu }}
            <el-dropdown-menu slot="dropdown">
              <el-dropdown-item v-for="(item, index) in runStatuOptions" :key="index" @click.native="startInterval(item)">{{ item.label }}</el-dropdown-item>
            </el-dropdown-menu>
          </el-dropdown>
        </el-form-item>
      </el-form>
    </div>
    <div style="margin: 3px; min-height: 80vh;">
      <!--数据判空-->
      <el-empty v-if="showEmpty" :description="emptyText" />
      <!--数据加载-->
      <el-card v-else shadow="hover" style="width: 100%" class="log-warpper">
        <div style="width: 100%">
          <div v-for="(log, index) in logs" :key="index">
            <div style="margin-bottom: 5px; font-size: 12px;" v-html="log[1]" />
          </div>
        </div>
      </el-card>
    </div>
  </div>
</template>

<script>

import logOperation from '@/views/loki/api/loki'
import { default as AnsiUp } from 'ansi_up'

let queryParam = {
  logLabel: null,
  logLabelValue: null,
  start: null,
  end: null,
  text: null,
  limits: 100,
  direction: 'backward'
}
export default {
  name: 'Loki',
  data() {
    return {
      labelAndValue: [], // 搜索的值
      labelsOptions: [], // 所有标签和对应所有值数据
      timeRange: [],
      text: '',
      limits: 100,
      direction: 'backward',
      logData: [],
      logs: [], // 所有日志
      showEmpty: true,
      emptyText: '请选择标签',
      displayDirection: [{
        value: 'backward',
        label: '新的在前'
      }, {
        value: 'forward',
        label: '旧的在前'
      }],
      scrollStep: 10,
      runStatu: 'off',
      runStatuOptions: [{
        label: 'off',
        value: 0
      }, {
        label: '5s',
        value: 5000
      }, {
        label: '10s',
        value: 10000
      }, {
        label: '1m',
        value: 60000
      }, {
        label: '5m',
        value: 300000
      }, {
        label: '30m',
        value: 1800000
      }],
      timeZoneOptions: [{
        label: '最近5分钟',
        value: 300 * 1000
      }, {
        label: '最近15分钟',
        value: 900 * 1000
      }, {
        label: '最近30分钟',
        value: 1800 * 1000
      }, {
        label: '最近1小时',
        value: 3600 * 1000
      }, {
        label: '最近3小时',
        value: 3600 * 1000 * 3
      }, {
        label: '最近6小时',
        value: 3600 * 1000 * 6
      }, {
        label: '最近12小时',
        value: 3600 * 1000 * 12
      }, {
        label: '最近24小时',
        value: 3600 * 1000 * 24
      }, {
        label: '最近2天',
        value: 3600 * 1000 * 24 * 2
      }, {
        label: '最近7天',
        value: 3600 * 1000 * 24 * 7
      }, {
        label: '最近15天',
        value: 3600 * 1000 * 24 * 15
      }],
      timeZoneValue: '',
      showOptions: true
    }
  },
  mounted() {
    window.addEventListener('scroll', this.handleScroll)
  },
  created() {
    this.initLabelsValues()
  },
  // 关闭定时器 - 加了缓存就必须使用deactivated
  deactivated() {
    // js提供的clearInterval方法用来清除定时器
    console.log('定时任务销毁')
    clearInterval(this.timer)
    window.removeEventListener('scroll', this.handleScroll)
  },
  beforeDestroy() {
    // js提供的clearInterval方法用来清除定时器
    console.log('定时任务销毁')
    clearInterval(this.timer)
    window.removeEventListener('scroll', this.handleScroll)
  },
  methods: {
    initLabelsValues() {
      logOperation.labelsValues().then(res => {
        this.labelsOptions = res
      })
    },
    queryData() {
      console.log(this.labelAndValue)
      // 清空查询数据
      this.clearParam()
      if (this.labelAndValue.length > 0) {
        queryParam.logLabel = this.labelAndValue[0]
        queryParam.logLabelValue = this.labelAndValue[1]
      }
      if (queryParam.logLabelValue === null) { // 判空
        this.$message({
          showClose: true,
          message: '请选择标签',
          type: 'warning'
        })
        this.showEmpty = true
        this.emptyText = '请选择标签'
        return
      }
      if (this.timeRange.length !== 0) { // 如果是输入时间范围
        queryParam.start = (new Date(this.timeRange[0]).getTime() * 1000000).toString()
        queryParam.end = (new Date(this.timeRange[1]).getTime() * 1000000).toString()
      }
      if (this.timeZoneValue) {
        const time = new Date()
        queryParam.start = ((time.getTime() - this.timeZoneValue) * 1000000).toString()
        queryParam.end = (time.getTime() * 1000000).toString()
      }
      if (this.text) {
        queryParam.text = this.text.replace(/^\s*|\s*$/g, '')
      }
      if (this.limits) {
        queryParam.limits = this.limits
      }
      queryParam.direction = this.direction
      var ansi_up = new AnsiUp()
      logOperation.getLogData(queryParam).then(res => {
        this.showEmpty = false
        if (res.data.result.length === 1) {
          this.logs = res.data.result[0].values
          for (const i in res.data.result[0].values) {
            this.logs[i][1] = ansi_up.ansi_to_html(res.data.result[0].values[i][1])
          }
        } else if (res.data.result.length > 1) {
          // 清空
          this.logs = []
          for (const j in res.data.result) { // 用push的方式将所有日志数组添加进去
            for (const values_index in res.data.result[j].values) {
              this.logs.push(res.data.result[j].values[values_index])
            }
          }
          for (const k in this.logs) {
            this.logs[k][1] = ansi_up.ansi_to_html(this.logs[k][1])
          }
          if (this.direction === 'backward') { // 由于使用公共标签会导致时间顺序错乱，因此对二维数组进行排序
            this.logs.sort((a, b) => b[0] - a[0])
          } else {
            this.logs.sort((a, b) => a[0] - b[0])
          }
        } else {
          this.showEmpty = true
          this.emptyText = '暂无日志信息，请选择时间段试试'
        }
      })
    },
    clearParam() {
      queryParam = {
        logLabel: null,
        logLabelValue: null,
        start: null,
        end: null,
        text: null,
        limits: 100,
        direction: 'backward'
      }
    },
    handleScroll() { // 滚动事件
      const scrollTop = document.documentElement.scrollTop// 滚动高度
      const clientHeight = document.documentElement.clientHeight// 可视高度
      const scrollHeight = document.documentElement.scrollHeight// 内容高度
      const bottomest = Math.ceil(scrollTop + clientHeight)
      if (bottomest >= scrollHeight) {
        // 加载新数据
        queryParam.limits = this.scrollStep
        queryParam.direction = this.direction
        // 获取时间差
        let zone = queryParam.end - queryParam.start
        if (this.timeRange.length) { // 如果是输入时间范围
          zone = ((new Date(this.timeRange[1]).getTime() - new Date(this.timeRange[0]).getTime()) * 1000000).toString()
        }
        if (this.timeZoneValue) {
          zone = this.timeZoneValue * 1000000
        }
        if (zone === 0) {
          zone = 3600 * 1000 * 6
        }
        if (this.direction === 'backward') { // 设置时间区间
          queryParam.start = (this.logs[this.logs.length - 1][0] - zone).toString()
          queryParam.end = this.logs[this.logs.length - 1][0]
        } else {
          queryParam.start = this.logs[this.logs.length - 1][0]
          queryParam.end = (parseFloat(this.logs[this.logs.length - 1][0]) + parseFloat(zone.toString())).toString()
        }
        var ansi_up = new AnsiUp()
        logOperation.getLogData(queryParam).then(res => {
          console.log(res)
          this.showEmpty = false
          if (res.data.result.length === 1) {
            // 如果返回的日志是一样的就不显示
            if (res.data.result[0].values.length === 1 && ansi_up.ansi_to_html(res.data.result[0].values[0][1]) === this.logs[this.logs.length - 1][1]) {
              this.$notify({
                title: '警告',
                duration: 1000,
                message: '当前时间段日志已最新！',
                type: 'warning'
              })
              return
            }
            const log = res.data.result[0].values
            for (const i in res.data.result[0].values) {
              log[i][1] = ansi_up.ansi_to_html(res.data.result[0].values[i][1])
              this.logs.push(log[i])
            }
          } else if (res.data.result.length > 1) {
            const tempArray = [] // 数据需要处理，由于是追加数组，所以需要用额外变量来存放
            // 刷新就是添加，不清空原数组
            for (const j in res.data.result) { // 用push的方式将所有日志数组添加进去
              for (const values_index in res.data.result[j].values) {
                tempArray.push(res.data.result[j].values[values_index])
              }
            }
            if (this.direction === 'backward') { // 由于使用公共标签会导致时间顺序错乱，因此对二维数组进行排序
              tempArray.sort((a, b) => b[0] - a[0])
            } else {
              tempArray.sort((a, b) => a[0] - b[0])
            }
            for (const k in tempArray) {
              tempArray[k][1] = ansi_up.ansi_to_html(tempArray[k][1]) // 数据转换
              this.logs.push(tempArray[k]) // 追加数据
            }
          } else {
            this.$notify({
              title: '警告',
              duration: 1000,
              message: '暂无以往日志数据！',
              type: 'warning'
            })
          }
        })
      }
    },
    startInterval(item) {
      this.runStatu = item.label
      console.log(item.value)
      if (item.value !== 0) {
        this.timer = setInterval(() => { // 定时刷新
          this.intervalLogs()
        }, item.value)
      } else {
        console.log('销毁了')
        clearInterval(this.timer)
      }
    },
    intervalLogs() { // 定时器的方法
      // 组织参数
      // 设置开始时间和结束时间
      // 开始为现在时间
      const start = new Date()
      const end = new Date()
      // 时差判断
      let zone = queryParam.end - queryParam.start
      if (this.timeRange.length) { // 如果是输入时间范围
        zone = ((new Date(this.timeRange[1]).getTime() - new Date(this.timeRange[0]).getTime()) * 1000000).toString()
      }
      if (this.timeZoneValue) {
        zone = this.timeZoneValue * 1000000
      }
      if (zone === 0) { // 防止空指针
        start.setTime(start.getTime() - 3600 * 1000 * 6)
        queryParam.start = (start.getTime() * 1000000).toString()
      } else {
        queryParam.start = (start.getTime() * 1000000 - zone).toString()
      }
      queryParam.end = (end.getTime() * 1000000).toString()
      queryParam.limits = this.limits
      console.log('定时器最后参数：', queryParam)
      var ansi_up = new AnsiUp() // 后端日志格式转化
      logOperation.getLogData(queryParam).then(res => {
        console.log('res', res)
        this.showEmpty = false
        debugger
        if (res.data.result.length === 1) {
          this.logs = res.data.result[0].values
          for (const i in res.data.result[0].values) { // 格式转换
            this.logs[i][1] = ansi_up.ansi_to_html(res.data.result[0].values[i][1])
          }
        } else if (res.data.result.length > 1) {
          // 清空
          this.logs = []
          for (const j in res.data.result) { // 用push的方式将所有日志数组添加进去
            for (const values_index in res.data.result[j].values) {
              this.logs.push(res.data.result[j].values[values_index])
            }
          }
          for (const k in this.logs) {
            this.logs[k][1] = ansi_up.ansi_to_html(this.logs[k][1])
          }
          if (this.direction === 'backward') { // 由于使用公共标签会导致时间顺序错乱，因此对二维数组进行排序
            this.logs.sort((a, b) => b[0] - a[0])
          } else {
            this.logs.sort((a, b) => a[0] - b[0])
          }
        } else {
          this.showEmpty = true
          this.emptyText = '暂无日志信息，请选择时间段试试'
        }
      })
    },
    changeShow() {
      // 清空数据
      this.timeZoneValue = ''
      this.timeRange = []
      this.showOptions = !this.showOptions
    }
  }
}
</script>

<style scoped>
.log-warpper {
  word-break: break-word;
  word-wrap: break-word
}
</style>
