<template>
  <div style="width: 98%;margin-left: 1%;">
    <el-tabs
      v-model="activeName"
      type="card"
      class="demo-tabs"
      
      @tab-click="handleClick"
    >
      <el-tab-pane label="模型事件" name="first">
        <el-form ref="formRef" :inline="true" :model="queryParams1">
          <el-form-item label="运行事件">
            <el-select
               v-model="queryParams1.event"
               placeholder=""
               clearable
               style="width: 150px"
            >
               <el-option
                  v-for="dict in model_run_log_event"
                  :key="dict.value"
                  :label="dict.label"
                  :value="dict.value"
               />
            </el-select>
          </el-form-item>
          <el-form-item label="模型名称">
            <el-input v-model="queryParams1.mdName" style="width: 150px"></el-input>
          </el-form-item>
          <el-form-item label="时间">
            <el-date-picker v-model="queryParams1.time" type="daterange" range-separator="至"
                            start-placeholder="开始时间" end-placeholder="结束时间" 
                            value-format="YYYY-MM-DD">
            </el-date-picker>
          </el-form-item>
          <el-form-item>
            <el-button type="primary" @click="getList1" icon="Search">搜索</el-button>
          </el-form-item>
        </el-form>
        <div style="display: flex;width: 100%;">
          <div style="width: 60%;">
            <el-table
              stripe
              style="height: 68vh;margin-top: 1%;width: 100%;"
              :data="tableDataJian"
              :cell-style="{ padding: '5px' }"
              :row-style="{ fontSize: '1rem', textAlign:'center' }"
              border>
              <el-table-column type="index" align="center" label="序号" width="60">
                <template #default="{ $index }">
                  <div style="text-align: center;">{{ $index + 1 }}</div>
                </template>
              </el-table-column>
              <el-table-column show-overflow-tooltip header-align="center" align="left"  prop="createBy" label="人员名称"/>
              <el-table-column show-overflow-tooltip header-align="center" align="left"  prop="createTime" label="创建时间"/>
              <el-table-column show-overflow-tooltip header-align="center" align="left"  prop="mdName" label="模型名称"/>
              <el-table-column show-overflow-tooltip header-align="center" align="left"  prop="event" label="运行事件"/>
            </el-table>
            <div style="display: flex;">
              <el-pagination
                small
                background
                style="margin-top: 1%;margin-left: auto;display: flex;margin-right: 1%;"
                layout="prev, pager, next"
                :total="totalJian"
                v-model="pageNumJian"
                @change="fanJian"
                class="mt-4"
            />
            </div>
          </div>
          <div style="width: 49%;margin-left: 1%;margin-top: 1%;">
            <div>
              过去7天模型吞吐量
            </div>
            <div style="height: 40vh;width: 100%;background-color: ;margin-top: 1%;" id="right1">

            </div>
            <div style="margin-top: 3%;">
              过去7天模型错误率
            </div>
            <div style="height: 30vh;width: 100%;background-color: ;margin-top: 1%;" id="right2">

            </div>
          </div>
        </div>
        
        
      </el-tab-pane>
      <el-tab-pane label="模型服务监控" name="second" style="height: 100vh;">
        <el-row>
      <!-- 筛选条件 -->
      <el-form ref="formRef" :inline="true" :model="queryParams">
        <el-form-item label="服务名称">
          <el-input v-model="queryParams.name"></el-input>
        </el-form-item>
        <el-form-item label="请求用户">
          <el-input v-model="queryParams.userName"></el-input>
        </el-form-item>
        <el-form-item label="时间">
          <el-date-picker v-model="queryParams.time" type="daterange" unlink-panels range-separator="至"
                          start-placeholder="开始时间" end-placeholder="结束时间" :shortcuts="shortcuts"
                          format="yyyy-MM-dd">
          </el-date-picker>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="getList" icon="Search">搜索</el-button>
        </el-form-item>
      </el-form>
    </el-row>
    <el-row class="table_box">
      <el-table
          stripe
          style="height: 68vh;"
          :data="tableData"
          :cell-style="{ padding: '5px' }"
          :row-style="{ fontSize: '1rem', textAlign:'center' }"
          border>
        <el-table-column type="index" align="center" label="序号" width="60">
          <template #default="{ $index }">
            <div style="text-align: center;">{{ $index + 1 }}</div>
          </template>
        </el-table-column>
        <el-table-column show-overflow-tooltip header-align="center" align="left" width="240" prop="modelName"
                         label="调用模型"/>
        <el-table-column show-overflow-tooltip header-align="center" align="left" width="200" prop="serviceName"
                         label="服务名称"/>
        <el-table-column prop="url" show-overflow-tooltip header-align="center" align="left" label="服务地址"/>
        <el-table-column show-overflow-tooltip header-align="center" align="left" width="220" prop="senText"
                         label="请求参数" :tooltip-formatter="({ row }) =>  {
          if( row.senText.length >= 30){
            return row.senText.substring(0, 30) + '...';
          }
          return row.senText;
        }">
          <template #default="scope">
            <span style="cursor: copy;" @click="copyParams(scope.row.senText)">{{ scope.row.senText }}</span>
          </template>
        </el-table-column>
        <el-table-column show-overflow-tooltip align="center" width="180" prop="tm" label="请求时间"></el-table-column>
        <el-table-column show-overflow-tooltip align="center" width="120" prop="execTm" label="请求耗时(ms)"/>
        <el-table-column show-overflow-tooltip align="center" width="100" prop="userName" label="请求用户"/>
        <el-table-column show-overflow-tooltip header-align="center" align="left" width="220" prop="appName"
                         label="请求应用"/>
        <el-table-column show-overflow-tooltip align="center" width="100" prop="statusCode" label="请求状态">
          <template #default="scope">
            <el-tag v-if="scope.row.statusCode==200">成功</el-tag>
            <el-tag v-else type="danger">失败</el-tag>
          </template>
        </el-table-column>
      </el-table>
    </el-row>
    <pagination
        v-show="total>0"
        :total="total"
        v-model:page="queryParams.pageNum"
        v-model:limit="queryParams.pageSize"
        style="margin-top: 1%;"
        @pagination="getList"
    />

    <el-dialog v-model="open" title="服务日志详情" width="60%" append-to-body>

    </el-dialog>
      </el-tab-pane>
    </el-tabs>
    
  </div>
</template>
<script setup>
import * as echarts from 'echarts';
import {onMounted, reactive, ref} from "vue";
import {getServiceLogList,getMdLogList,getMdStatusSum,getMdAllList } from "@/api/service/log.js";
import useClipboard from 'vue-clipboard3'

const {toClipboard} = useClipboard()
const {proxy} = getCurrentInstance();
const { model_run_log_event } = proxy.useDict("model_run_log_event");
const tableHeight = ref(window.innerHeight - 400)
const queryParams1 = ref({
  time:[]
})
const queryParams = reactive({
  pageNum: 1,
  pageSize: 20,
  orderBy: "",
  name: "",
  userName: "",
  time: [],
  sttm: "",
  entm: "",
})
const totalJian = ref(0)
const tableDataJian = ref([])
const pageNumJian = ref(1)
const activeName = ref('first')
const tableData = ref([])
const total = ref(0)
const shortcuts = ref([
  {
    text: "近一周",
    value: () => {
      const end = new Date();
      const start = new Date();
      start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
      return [start, end];
    },
  },
  {
    text: "近一个月",
    value: () => {
      const end = new Date();
      const start = new Date();
      start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
      return [start, end];
    },
  },
  {
    text: "近三个月",
    value: () => {
      const end = new Date();
      const start = new Date();
      start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
      return [start, end];
    },
  },
  {
    text: "近一年",
    value: () => {
      const end = new Date();
      const start = new Date();
      start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
      return [start, end];
    },
  },
])

async function copyParams(message) {
  toClipboard(message).then(() => {
    proxy.$modal.msgSuccess("复制成功!");
  })
}
function fanJian(val){
  pageNumJian.value = val
  getList1()
}
function getList1(){
  queryParams1.value.pageSize = 20
  queryParams1.value.pageNum = pageNumJian.value
  var par = {
    pageNum:pageNumJian.value,
    pageSize:20,
    event:queryParams1.value.event,
    mdName:queryParams1.value.mdName,
    params:{
      beginTime:queryParams1.value.time==[]?'':queryParams1.value.time[0],
      endTime:queryParams1.value.time==[]?'':queryParams1.value.time[1],
    }
  }
  getMdLogList(par).then(r=>{
    tableDataJian.value = r.rows;
    totalJian.value = r.total;
    for(var i = 0;i<tableDataJian.value.length;i++){
      for(var i1 = 0;i1<model_run_log_event.value.length;i1++){
        if(tableDataJian.value[i].event===model_run_log_event.value[i1].value){
          tableDataJian.value[i].event = model_run_log_event.value[i1].label
        }
      }
    }
  })
  
}
function getLast7DaysRange() {
  const end = new Date(); 
  const start = new Date();
  end.setDate(start.getDate() - 1);
  start.setDate(end.getDate() - 7);
  function formatDate(date) {
    const year = date.getFullYear();
    const month = String(date.getMonth() + 1).padStart(2, '0');
    const day = String(date.getDate()).padStart(2, '0');
    return `${year}-${month}-${day}`;
  }

  return {
    start: formatDate(start),
    end: formatDate(end)
  };
}
function mergeModelData(data) {
  const mergeMap = {};
  
  data.forEach(item => {
    const mdName = item.mdName?.trim(); // 处理可能的空格
    if (!mdName) return;
    
    if (!mergeMap[mdName]) {
      mergeMap[mdName] = {
        mdName: mdName,
        mdId: item.mdId,
        statisNum: 0,
        statisNumErr: 0
      };
    }
    
    const current = mergeMap[mdName];
    const statisNumValue = Number(item.statisNum) || 0;
    
    if (item.statusCode === '200') {
      // statusCode为200，保留statisNum
      current.statisNum = statisNumValue;
    } else if (item.statusCode) {
      // 其他statusCode，累加到statisNumErr
      current.statisNumErr += statisNumValue;
    }
    
    // 保留第一个非空的mdId
    if (!current.mdId && item.mdId) {
      current.mdId = item.mdId;
    }
  });
  
  return Object.values(mergeMap);
}
async function drawRight2(){
  var chartDom = document.getElementById('right2');
  var myChart = echarts.init(chartDom);
  var option;
  const last7Days = getLast7DaysRange();
  var par1 = {
    params:{
      beginTime:last7Days.start,
      endTime:last7Days.end,
    }
  }
  var uniqueMdNames
  var mergedData
  var success = []
  var error = []
  await getMdStatusSum(par1).then(res=>{
    uniqueMdNames = [...new Map(res.data.map(item => [item.mdName, item.mdName])).values()].filter(Boolean);
    mergedData = mergeModelData(res.data)
    mergedData.forEach(item=>{
      success.push(item.statisNum)
      error.push(item.statisNumErr)
    })
  })
  option = {
     grid: {
      top: '15%',     // 图表距离容器顶部的距离
      right: '5%',    // 图表距离容器右侧的距离
      bottom: '15%',  // 图表距离容器底部的距离
      left: '10%',    // 图表距离容器左侧的距离
      containLabel: true  // 确保坐标轴标签在 grid 区域内
    },
    tooltip: {
      trigger: 'axis',
      axisPointer: {
        type: 'shadow'
      }
    },
    legend: {},
    color: ['#67C23A','#F56C6C',],
    xAxis: [
      {
        type: 'category',
        data: uniqueMdNames,
        axisLabel: {
          interval: 0,  // 强制显示所有标签
          rotate: -25,   // 旋转角度，正值表示顺时针旋转，负值表示逆时针旋转
          // 可以设置文字样式，如字体大小、颜色等
          textStyle: {
            fontSize: 9,
            color: '#333'
          }
        }
      }
    ],
    yAxis: [
      {
        type: 'value'
      }
    ],
    series: [
      {
        name: '成功',
        type: 'bar',
        stack: 'Ad',
        emphasis: {
          focus: 'series'
        },
        data: success,
        
      },
      {
        name: '失败',
        type: 'bar',
        stack: 'Ad',
        emphasis: {
          focus: 'series'
        },
        data: error,
        label: {
          show: true, // 显示标签
          position: 'top', // 标签位置在柱子上方
          // 自定义标签内容，formatter可以是字符串模板，也可以是回调函数
          formatter: function(params) {
          // 计算每个柱子占当天的总比例
            const total = params.data + option.series[0].data[params.dataIndex];
            const percent = ((params.data / total) * 100).toFixed(1);
            if(params.data){
              return params.data + `\n(${percent}%)`;
            }
          },
          // 标签文本样式
          textStyle: {
            color: '#000', // 颜色
            fontSize: 12
          }
        }
      },
    ]
  };

  option && myChart.setOption(option);

}
function getList() {
  getServiceLogList(queryParams)
      .then((r) => {
        tableData.value = r.rows;
        total.value = r.total;
      });
}
function processModelData(data) {
  const resultMap = {};
  
  data.forEach(item => {
    const mdName = item.mdName?.trim();
    if (!mdName) return;
    
    const statisNum = Number(item.statisNum) || 0;
    
    if (!resultMap[mdName]) {
      // 初始化该模型的数据
      resultMap[mdName] = {
        mdName: mdName,
        mdId: item.mdId || null,
        totalStatisNum: statisNum,
        recordCount: 1,
        firstRecordDate: item.statisTm,
        lastRecordDate: item.statisTm,
        records: [item] // 可选：保留详细记录
      };
    } else {
      // 更新现有模型数据
      resultMap[mdName].totalStatisNum += statisNum;
      resultMap[mdName].recordCount += 1;
      
      // 更新最新记录日期
      if (item.statisTm && (!resultMap[mdName].lastRecordDate || item.statisTm > resultMap[mdName].lastRecordDate)) {
        resultMap[mdName].lastRecordDate = item.statisTm;
      }
      
      resultMap[mdName].records.push(item);
    }
  });
  
  // 转换为数组并排序（按统计数字降序）
  return Object.values(resultMap)
    .sort((a, b) => b.totalStatisNum - a.totalStatisNum);
}
function getDateRange(startStr, endStr) {
    const startDate = new Date(startStr);
    const endDate = new Date(endStr);
    const dates = [];
    
    // 验证日期有效性
    if (isNaN(startDate.getTime()) || isNaN(endDate.getTime())) {
        throw new Error('无效的日期格式');
    }
    
    if (startDate > endDate) {
        throw new Error('开始日期不能晚于结束日期');
    }
    
    // 复制开始日期对象，避免修改原日期
    const currentDate = new Date(startDate);
    
    // 循环直到当前日期超过结束日期
    while (currentDate <= endDate) {
        // 格式化为 YYYY-MM-DD
        const year = currentDate.getFullYear();
        const month = String(currentDate.getMonth() + 1).padStart(2, '0');
        const day = String(currentDate.getDate()).padStart(2, '0');
        
        dates.push(`${year}-${month}-${day}`);
        
        // 日期加一天
        currentDate.setDate(currentDate.getDate() + 1);
    }
    
    return dates;
}
async function drawRight1(){
  var chartDom = document.getElementById('right1');
  var myChart = echarts.init(chartDom);
  var option;
  const last7Days = getLast7DaysRange();
  var par = {
    params:{
      beginTime:last7Days.start,
      endTime:last7Days.end,
    }
  }
  var x = getDateRange(last7Days.start,last7Days.end)
  var y = []
  await getMdAllList(par).then(res=>{
    res.data.forEach(item=>{
      item.value = []
      item.lineCharts.forEach(item1=>{
        item.value.push(item1.num)
      })
    })
    res.data.forEach(item=>{
      var par = {
        name: item.mdName,
        type: 'line',
        data: item.value,
        smooth: true
      }
      y.push(par)
    })
    console.log(res.data)
  })
  option = {
     grid: {
      top: '10%',     // 图表距离容器顶部的距离
      right: '5%',    // 图表距离容器右侧的距离
      bottom: '15%',  // 图表距离容器底部的距离
      left: '10%',    // 图表距离容器左侧的距离
      containLabel: true  // 确保坐标轴标签在 grid 区域内
    },
    tooltip: {
        trigger: 'axis',
        show:'false'
    },
    legend: {
      top:'88%'
    },
    xAxis: {
      splitLine: { show: false },
      // type: 'category',
      data: x,
      axisLabel: {
          top:'10%',
          interval: 0,  // 强制显示所有标签
          rotate: -25,   // 旋转角度，正值表示顺时针旋转，负值表示逆时针旋转
          // 可以设置文字样式，如字体大小、颜色等
          textStyle: {
            fontSize: 9,
            color: '#333'
          }
        }
    },
    yAxis: {
      type: 'value',
      show: true,
      splitLine: { show: false },
      name: '单位：次', 
      minInterval: 1, 
      axisTick: {
        show: true // 确保显示刻度线
      },
       axisLine: {
        show: true, // 确保显示轴线
        lineStyle: {
          color: '#333', // 可以设置轴线的颜色，例如与文字颜色一致
          // width: 1 // 可以设置轴线宽度，可选
        }
      },
    },
    series:y
  };
  
  option && myChart.setOption(option);

}
onMounted(() => {
  getList()
  getList1()
  drawRight2()
  drawRight1()
});

watch(() => queryParams.time, value => {
  queryParams.sttm = value[0];
  queryParams.entm = value[1];
}, {immediate: true})

</script>
<style scoped>
.el-row {
  margin-bottom: 10px;
}

.table_box ::v-deep .el-table {
  border: 1px solid #e6e6e6;
  border-right: 1px solid #e6e6e6;
  border-bottom: none;
  border-radius: 5px;
}

::v-deep .el-form-item {
  margin-bottom: 0;
}
</style>
