<template>
  <div v-loading="loading">
    <div class="flex-row" style="gap: 16px; align-items: stretch;margin-bottom: 16px">
      <el-card shadow="nover" class="flex1">
        <div class="flex-row">
          <el-descriptions :column="1" border class="flex1">
            <el-descriptions-item label="CPU数">{{ sysInfo.cpuNum }}</el-descriptions-item>
            <el-descriptions-item label="核心数">{{ sysInfo.cpuCores }}</el-descriptions-item>
            <el-descriptions-item label="使用率">{{ sysInfo.cpuUsed }}%</el-descriptions-item>
            <el-descriptions-item label="LA5">{{ sysInfo.cpuAvg5 }}%</el-descriptions-item>
            <el-descriptions-item label="LA15">{{ sysInfo.cpuAvg15 }}%</el-descriptions-item>
          </el-descriptions>
          <div class="flex1">
            <VueUiGauge :dataset="dataset" :config="config" />
          </div>
        </div>
      </el-card>
      <el-card shadow="nover" class="flex1">
        <div class="flex-row">
          <el-descriptions :column="1" border class="flex1">
            <el-descriptions-item label="内存总数">{{ memorySizeFormat(sysInfo.memTotal) }}</el-descriptions-item>
            <el-descriptions-item label="已使用">{{ memorySizeFormat(sysInfo.memUsed) }}</el-descriptions-item>
            <el-descriptions-item label="剩余">{{ memorySizeFormat(sysInfo.available) }}</el-descriptions-item>
            <el-descriptions-item label="系统使用">{{ memorySizeFormat(sysInfo.goUsed) }}</el-descriptions-item>
            <el-descriptions-item label="使用率">{{ memorySizeFormat(sysInfo.memUsage) }}%</el-descriptions-item>
          </el-descriptions>
          <div class="flex1">
            <VueUiGauge :dataset="dataset2" :config="config2" />
          </div>
        </div>
      </el-card>
      <el-card shadow="nover" class="flex1">
        <div class="flex-row">
          <el-descriptions :column="1" border class="flex1">
            <el-descriptions-item label="磁盘容量">{{ memorySizeFormat(sysInfo.diskTotal) }}</el-descriptions-item>
            <el-descriptions-item label="已使用">{{ memorySizeFormat(sysInfo.diskUsed) }}</el-descriptions-item>
            <el-descriptions-item label="使用率">{{ memorySizeFormat(sysInfo.diskUsedPercent) }}%</el-descriptions-item>
          </el-descriptions>
          <div class="flex1">
            <VueUiGauge :dataset="dataset3" :config="config3" />
          </div>
        </div>
      </el-card>
    </div>
    <el-row :gutter="15">
      <el-col :xs="24" :sm="12" :md="8" class="mb-4">
        <el-card shadow="nover" class="box-card-height" style="height:auto">
          <template #header>
            <div class="card-header">
              <span>CPU运行情况</span>
            </div>
          </template>
          <div style="height: 250px" ref="chartsWarningRef4"></div>
        </el-card>
      </el-col>
      <el-col :xs="24" :sm="12" :md="8" class="mb-4">
        <el-card shadow="nover" class="box-card-height" style="height:auto">
          <template #header>
            <div class="card-header">
              <span>内存运行情况</span>
            </div>
          </template>
          <div style="height: 250px" ref="chartsWarningRef5"></div>
        </el-card>
      </el-col>
      <el-col :xs="24" :sm="12" :md="8" class="mb-4">
        <el-card shadow="nover" class="box-card-height" style="height:auto">
          <template #header>
            <div class="card-header">
              <span>磁盘使用情况</span>
            </div>
          </template>
          <div style="height: 250px" ref="chartsWarningRef6"></div>
        </el-card>
      </el-col>
    </el-row>
    <div class="flex-row gap-2">
      <el-col :xs="24" :sm="24" :md="24">
        <el-card shadow="nover" class="box-card-height" style="height:auto">
          <template #header>
            <div class="card-header">
              <span>运行环境信息</span>
            </div>
          </template>
          <el-descriptions :column="3" border class="flex1">
            <el-descriptions-item label="操作系统">{{ hostData.os }}</el-descriptions-item>
            <el-descriptions-item label="系统架构">{{ goInfoData.arch }}</el-descriptions-item>
            <el-descriptions-item label="架构版本">{{ hostData.kernelArch }}</el-descriptions-item>
            <el-descriptions-item label="启动时间">{{ goInfoData.startTime }}</el-descriptions-item>
            <el-descriptions-item label="语言环境">{{ goInfoData.goName }}</el-descriptions-item>
            <el-descriptions-item label="GO 版本">{{ goInfoData.goVersion }}</el-descriptions-item>
            <el-descriptions-item label="运行时长">{{ timeFormat(goInfoData.runTime) }}</el-descriptions-item>
            <el-descriptions-item label="磁盘占用">{{ goInfoData.goSize }}</el-descriptions-item>
            <el-descriptions-item label="协程数量">{{ goInfoData.goroutine }}</el-descriptions-item>
            <el-descriptions-item label="运行内存">{{ goInfoData.goMem }}</el-descriptions-item>
            <el-descriptions-item label="项目地址">{{ goInfoData.pwd }}</el-descriptions-item>
            <el-descriptions-item label="服务器IP">{{ hostData.intranet_ip }} (内) &nbsp;&nbsp;&nbsp; {{ hostData.public_ip }} (公) </el-descriptions-item>
          </el-descriptions>
        </el-card>
      </el-col>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { ref, toRefs, reactive, onMounted, getCurrentInstance, defineComponent, onUnmounted } from 'vue';
import * as echarts from 'echarts';
import 'echarts-wordcloud';
import dayjs from 'dayjs';
import { getSSEOrigin } from '/@/utils/origin'
import { VueUiGauge } from "vue-data-ui";
import "vue-data-ui/style.css";
import { getGaugeData } from "/@/utils/dataUiOptions";

let interval: any = null;
let es: any = null;
const { proxy } = getCurrentInstance() as any;
const sysInfo: any = reactive<any>({
});

const loading = ref(true)

//#region 线图

// 获取默认图形配置数据
const chartData = getGaugeData({
  value: 0
})

const config = ref<any>(chartData.config);
const config2 = ref<any>(chartData.config);
const config3 = ref<any>(chartData.config);
const dataset = ref<any>(chartData.dataset);
const dataset2 = ref<any>(chartData.dataset);
const dataset3 = ref<any>(chartData.dataset);

//#endregion

let myChart4: any;
let myChart5: any;
let myChart6: any;
const hostData = reactive({
  "bootTime": "2022-11-24T11:12:13+08:00",
  "hostId": "8be74718-1a53-4208-be22-9c126d891ddd",
  "hostname": "iZ2zee04uvnkmhvglw9oghZ",
  "intranet_ip": "172.17.47.62",
  "kernelArch": "x86_64",
  "kernelVersion": "3.10.0-1127.19.1.el7.x86_64",
  "os": "linux",
  "platform": "centos",
  "platformFamily": "rhel",
  "platformVersion": "7.7.1908",
  "procs": 138,
  "public_ip": "101.200.198.249",
  "uptime": 6393278,
  "virtualizationRole": "guest",
  "virtualizationSystem": ""
});
const goInfoData = reactive({
  "goOs": "-", "arch": "-", "goVersion": "-", "goMem": "-", "goName": "-", "goSize": "-", "goroutine": '-', "pwd": "-", "rootPath": "-",
  "runTime": '', "startTime": "-", "intranet_ip": "-"
});

function goInfo(event: { data: any; }) {
  const data = JSON.parse(event.data);
  Object.assign(goInfoData, data);
  loading.value = false
}

function hostInfo(event: { data: any; }) {
  const data = JSON.parse(event.data);
  Object.assign(hostData, data);
  loading.value = false
}

const myChart4Data: any = {
  name: [],
  value: [],
}
const myChart5Data: any = {
  name: [],
  value: [],
}
const myChart6Data: any = {
  name: [],
  value: [],
}

const moveOption = {
  tooltip: {
    trigger: 'axis',
  },
  grid: {
    top: 5,
    bottom: 5,
    left: 5,
    right: 30,
    containLabel: true
  },
  xAxis: {
    type: 'category',
    boundaryGap: false,
    splitLine: {
      show: false
    }
  },
  yAxis: {
    type: 'value',
    boundaryGap: [0, '100%'],
    axisLabel: {
      formatter: '{value}%'
    },
    splitLine: {
      show: false
    }
  },
  series: [
    {
      name: '使用率',
      type: 'line',
      showSymbol: false,
      data: [],
      smooth: true,
      lineStyle: {
        width: 0
      },
      areaStyle: {}
    }
  ]
};

function setOptChart1(value: number) {
  const chartData = getGaugeData({ value })
  config.value = chartData.config
  dataset.value = chartData.dataset
}
function setOptChart2(value: number) {
  const chartData = getGaugeData({ value })
  config2.value = chartData.config
  dataset2.value = chartData.dataset
}
function setOptChart3(value: number) {
  const chartData = getGaugeData({ value })
  config3.value = chartData.config
  dataset3.value = chartData.dataset
}
function setOptChart(myChart: any, myChartData: any, value: number) {
  myChartData.name.push(dayjs().format('HH:mm:ss'));
  myChartData.value.push(value);
  if (myChartData.name.length > 20) {
    myChartData.name.shift()
    myChartData.value.shift()
  }
  myChart.setOption({
    xAxis: {
      data: myChartData.name
    },
    series: [
      {
        data: myChartData.value
      },
    ],
  });
}


//cpu运行状态
const initChartCPURun = () => {
  myChart4 = echarts.init(proxy.$refs.chartsWarningRef4);
  moveOption.series[0].areaStyle = {
    opacity: 0.8,
    color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
      {
        offset: 0,
        color: 'rgb(128, 255, 165)'
      },
      {
        offset: 1,
        color: 'rgb(1, 191, 236)'
      }
    ])
  }
  myChart4.setOption(moveOption);
};

//内存运行状态
const initChartRAMRun = () => {
  myChart5 = echarts.init(proxy.$refs.chartsWarningRef5);
  moveOption.series[0].areaStyle = {
    opacity: 0.8,
    color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
      {
        offset: 0,
        color: 'rgb(0, 221, 255)'
      },
      {
        offset: 1,
        color: 'rgb(77, 119, 255)'
      }
    ])
  }
  myChart5.setOption(moveOption);
};

//磁盘运行状态
const initChartDISKRun = () => {
  myChart6 = echarts.init(proxy.$refs.chartsWarningRef6);
  moveOption.series[0].areaStyle = {
    opacity: 0.8,
    color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
      {
        offset: 0,
        color: 'rgb(55, 162, 255)'
      },
      {
        offset: 1,
        color: 'rgb(116, 21, 219)'
      }
    ])
  }
  myChart6.setOption(moveOption);
};

// 页面加载时
onMounted(() => {
  initChartCPURun();
  initChartRAMRun();
  initChartDISKRun();
});

function startWs() {
  es = new EventSource(getSSEOrigin("/subscribe/sysenv"));

  es.addEventListener("host", displayHost);
  es.addEventListener("mem", displayMem);
  es.addEventListener("cpu", displayCpu);
  es.addEventListener("sysLoad", displaySysLoad);
  es.addEventListener("disk", displayDisk);
  es.addEventListener("go", goInfo);
  es.addEventListener("host", hostInfo);
}

startWs();

function displayHost(event: { data: any; }) {
  const data = JSON.parse(event.data);
  sysInfo.os = data.os
  sysInfo.kernelArch = data.kernelArch
  sysInfo.sysComputerName = data.hostname
  sysInfo.goStartTime = data.bootTime
  sysInfo.goRunTime = data.uptime
  loading.value = false
}

function displayMem(event: { data: any; }) {
  const data = JSON.parse(event.data);
  setOptChart2(data.usedPercent.toFixed(2));
  sysInfo.memTotal = data.total
  sysInfo.memUsed = data.used
  sysInfo.available = data.available
  sysInfo.goUsed = data.goUsed
  sysInfo.memUsage = data.usedPercent.toFixed(2)
  setOptChart(myChart5, myChart5Data, sysInfo.memUsage);
  loading.value = false
}

function displayCpu(event: { data: any; }) {
  const data = JSON.parse(event.data);
  // console.log(dayjs().format('HH:mm:ss'))
  // console.log(data)

  sysInfo.cpuNum = data.Number
  sysInfo.cpuCores = data.Cores
  sysInfo.cpuUsed = data.UsedPercent[0].toFixed(2)
  setOptChart1(data.UsedPercent[0].toFixed(2));
  setOptChart(myChart4, myChart4Data, sysInfo.cpuUsed);
  loading.value = false
}

function displaySysLoad(event: { data: any; }) {
  const data = JSON.parse(event.data)
  sysInfo.cpuAvg5 = data.load5.toFixed(2)
  sysInfo.cpuAvg15 = data.load15.toFixed(2)
  loading.value = false
}

function displayDisk(event: { data: any; }) {
  const data = JSON.parse(event.data)
  sysInfo.diskTotal = data.total
  sysInfo.diskUsed = data.used
  sysInfo.diskUsedPercent = data.usedPercent.toFixed(2)
  setOptChart3(data.usedPercent.toFixed(2));
  setOptChart(myChart6, myChart6Data, sysInfo.diskUsedPercent);
  loading.value = false
}

const memorySizeFormat = (size: any) => {
  if (size === null || size === undefined) return ''
  size = parseFloat(size);
  let rank = 0;
  let rankchar = 'Bytes';
  while (size > 1024 && rankchar != 'TB') {
    size = size / 1024;
    rank++;
    if (rank == 1) {
      rankchar = 'KB';
    } else if (rank == 2) {
      rankchar = 'MB';
    } else if (rank == 3) {
      rankchar = 'GB';
    } else if (rank == 4) {
      rankchar = 'TB';
    }
  }
  return size.toFixed(2) + ' ' + rankchar;
}

const timeFormat = (second: any) => {
  if (!second) return '-'
  second = parseFloat(second);
  let rank = 0;
  let rankchar = '秒';
  while ((second > 60 && rankchar != '小时' && rankchar != '天') || (second > 24 && rankchar == '小时')) {
    if (rankchar == '小时') {
      second = second / 24;
    } else {
      second = second / 60;
    }
    rank++;
    if (rank == 1) {
      rankchar = '分';
    } else if (rank == 2) {
      rankchar = '小时';
    } else if (rank == 3) {
      rankchar = '天';
    }
  }
  return second.toFixed(2) + ' ' + rankchar;
}

onUnmounted(() => {
  if (interval) {
    clearInterval(interval);
    interval = null;
  }
  if (es) {
    es.close()
  }
});

</script>

<style scoped lang="scss">
.el-card {
  ::v-deep .el-card__body {
    height: 100%;

    .flex-row {
      height: 100%;
    }
  }
}

.mb-4 {
  margin-bottom: 15px;
}

.cell {
  box-sizing: border-box;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: normal;
  word-break: break-all;
  line-height: 36px;
  padding-left: 10px;
  padding-right: 10px;
}

.cell-card {
  box-sizing: border-box;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: normal;
  word-break: break-all;
  line-height: 36px;
}

.box-card {
  min-height: 380px;
}

.box-card-meter {
  height: auto;
  min-height: 180px;
}
</style>
