<template>
  <div class="app-container">
    <div class="head-container">
      <!--工具栏-->
      <el-form :inline="true" class="demo-form-inline">
        <el-form-item label="标签">
          <el-select v-model="logLabel" filterable placeholder="请选择标签" size="mini" @change="getValues">
            <el-option
              v-for="item in labelOptions"
              :key="item.index"
              :label="item"
              :value="item"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="=">
          <el-select v-model="logLabelValue" filterable placeholder="请选择标签" size="mini" @change="queryData">
            <el-option
              v-for="item in labelValueOptions"
              :key="item.index"
              :label="item"
              :value="item"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="时间范围" style="margin-left: 10px">
          <el-date-picker
            v-model="timeRange"
            size="mini"
            clearable
            type="datetimerange"
            :picker-options="pickerOptions"
            range-separator="至"
            start-placeholder="开始日期"
            end-placeholder="结束日期"
            align="right"
          />
        </el-form-item>
        <el-form-item 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>
      <el-form :inline="true" class="demo-form-inline">
        <el-form-item label="关键字">
          <el-input
            v-model="text"
            style="width: 300px"
            size="mini"
            placeholder="请输入内容"
            clearable
          />
        </el-form-item>
        <el-form-item label="条数" style="margin-left: 10px">
          <el-input-number
            v-model="limits"
            size="mini"
            controls-position="right"
            :min="100"
            :max="5000"
            :step="100"
          />
        </el-form-item>
        <el-form-item label="滚动步数" style="margin-left: 10px">
          <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">
        <div v-for="(log, index) in logs" :key="index">
          <div style="margin-bottom: 5px; font-size: 12px; width: 100%" v-html="log[1]" />
        </div>
      </el-card>
    </div>
  </div>
</template>

<script>

import logOperation from '@/api/monitor/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: 'LogBack',
  data() {
    return {
      labelOptions: [], // 标签数据
      labelValueOptions: [], // 标签值
      logLabel: '',
      logLabelValue: '',
      timeRange: '',
      text: '',
      limits: 100,
      direction: 'backward',
      pickerOptions: {
        shortcuts: [{
          text: '最近5分钟',
          onClick(picker) {
            const end = new Date()
            const start = new Date()
            start.setTime(start.getTime() - 300 * 1000)
            picker.$emit('pick', [start, end])
          }
        }, {
          text: '最近15分钟',
          onClick(picker) {
            const end = new Date()
            const start = new Date()
            start.setTime(start.getTime() - 900 * 1000)
            picker.$emit('pick', [start, end])
          }
        }, {
          text: '最近30分钟',
          onClick(picker) {
            const end = new Date()
            const start = new Date()
            start.setTime(start.getTime() - 1800 * 1000)
            picker.$emit('pick', [start, end])
          }
        }, {
          text: '最近1小时',
          onClick(picker) {
            const end = new Date()
            const start = new Date()
            start.setTime(start.getTime() - 3600 * 1000)
            picker.$emit('pick', [start, end])
          }
        }, {
          text: '最近3小时',
          onClick(picker) {
            const end = new Date()
            const start = new Date()
            start.setTime(start.getTime() - 3600 * 1000 * 3)
            picker.$emit('pick', [start, end])
          }
        }, {
          text: '最近6小时',
          onClick(picker) {
            const end = new Date()
            const start = new Date()
            start.setTime(start.getTime() - 3600 * 1000 * 6)
            picker.$emit('pick', [start, end])
          }
        }, {
          text: '最近12小时',
          onClick(picker) {
            const end = new Date()
            const start = new Date()
            start.setTime(start.getTime() - 3600 * 1000 * 12)
            picker.$emit('pick', [start, end])
          }
        }, {
          text: '最近24小时',
          onClick(picker) {
            const end = new Date()
            const start = new Date()
            start.setTime(start.getTime() - 3600 * 1000 * 24)
            picker.$emit('pick', [start, end])
          }
        }, {
          text: '最近2天',
          onClick(picker) {
            const end = new Date()
            const start = new Date()
            start.setTime(start.getTime() - 3600 * 1000 * 24 * 2)
            picker.$emit('pick', [start, end])
          }
        }, {
          text: '最近7天',
          onClick(picker) {
            const end = new Date()
            const start = new Date()
            start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
            picker.$emit('pick', [start, end])
          }
        }, {
          text: '最近15天',
          onClick(picker) {
            const end = new Date()
            const start = new Date()
            start.setTime(start.getTime() - 3600 * 1000 * 24 * 15)
            picker.$emit('pick', [start, end])
          }
        }]
      },
      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
      }]
    }
  },
  mounted() {
    window.addEventListener('scroll', this.handleScroll)
  },
  created() {
    this.initLabelOptions()
  },
  beforeDestroy() {
    // js提供的clearInterval方法用来清除定时器
    // console.log('定时任务销毁')
    clearInterval(this.timer)
  },
  methods: {
    initLabelOptions() { // 获取lables
      logOperation.getAllLabels().then(res => {
        this.labelOptions = res.data
      })
    },
    getValues() {
      this.logLabelValue = null
      logOperation.getAllValues(this.logLabel).then(res => {
        this.labelValueOptions = res.data
      })
    },
    queryData() {
      console.log('参数：', queryParam)
      // 清空查询数据
      this.clearParam()
      if (this.logLabel !== '') {
        queryParam.logLabel = this.logLabel
      }
      if (this.logLabelValue !== '') {
        queryParam.logLabelValue = this.logLabelValue
      }
      if (queryParam.logLabelValue === null) {
        this.$message({
          showClose: true,
          message: '请选择标签',
          type: 'warning'
        })
        this.showEmpty = true
        this.emptyText = '请选择标签'
        return
      }
      if (this.timeRange !== '' && this.timeRange !== null) {
        queryParam.start = (new Date(this.timeRange[0]).getTime() * 1000000).toString()
        queryParam.end = (new Date(this.timeRange[1]).getTime() * 1000000).toString()
      }
      if (this.text !== '') {
        queryParam.text = this.text
      }
      if (this.limits !== '') {
        console.log(this.limits)
        queryParam.limits = this.limits
      }
      queryParam.direction = this.direction
      console.log(queryParam)
      var ansi_up = new AnsiUp()
      logOperation.getLogData(queryParam).then(res => {
        console.log(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])
            }
          }
          console.log(this.logs)
          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])
          }
          console.log(this.logs)
        } else {
          this.showEmpty = true
          this.emptyText = '暂无日志信息，请选择时间段试试'
        }
      })
    },
    clearParam() {
      const end = new Date()
      const start = new Date()
      start.setTime(start.getTime() - 3600 * 1000 * 6)
      queryParam = {
        logLabel: null,
        logLabelValue: null,
        start: (start.getTime() * 1000000).toString(),
        end: (end.getTime() * 1000000).toString(),
        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.round(scrollTop + clientHeight)
      if (bottomest === scrollHeight) {
        // 加载新数据
        queryParam.limits = this.scrollStep
        queryParam.direction = this.direction
        if (this.direction === 'backward') {
          queryParam.start = (this.logs[this.logs.length - 1][0] - (queryParam.end - queryParam.start)).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((queryParam.end - queryParam.start).toString())).toString()
        }
        var ansi_up = new AnsiUp()
        logOperation.getLogData(queryParam).then(res => {
          console.log(res)
          this.showEmpty = false
          if (res.data.result.length === 1) {
            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])
              }
            }
            console.log(tempArray)
            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: '警告',
              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() {
      console.log('定时的参数：', queryParam)
      // 组织参数
      // 设置开始时间和结束时间
      // 开始为现在时间
      const start = new Date()
      const end = new Date()
      // 时差判断
      const zone = queryParam.end - queryParam.start
      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
      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])
            }
          }
          console.log(this.logs)
          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 = '暂无日志信息，请选择时间段试试'
        }
      })
    }
  }
}
</script>

<style scoped>

</style>
