<script setup lang="ts">
import { nextTick, onMounted, onUnmounted, ref } from 'vue'
import { ArrowDown, Minus, RefreshRight, Setting } from '@element-plus/icons-vue'
import * as echarts from 'echarts'
import type { ECharts, EChartsOption } from 'echarts'

const reliableChart = ref<HTMLElement>()
const pressureChart = ref<HTMLElement>()
const trendChart = ref<HTMLElement>()
const pressureTrendChart = ref<HTMLElement>()
const charts: ECharts[] = []

function createChart(el: HTMLElement | undefined, option: EChartsOption) {
  if (!el) return
  const chart = echarts.init(el)
  chart.setOption(option)
  charts.push(chart)
}

function resizeCharts() {
  charts.forEach((chart) => chart.resize())
}

function ringOption(
  centerText: string,
  data: Array<{ value: number; name: string; itemStyle?: object }>,
): EChartsOption {
  return {
    color: ['#1267f2', '#e7f0ff'],
    animationDuration: 900,
    title: {
      text: centerText,
      left: 'center',
      top: '42%',
      textStyle: { color: '#05070b', fontSize: 30, fontWeight: 800 },
    },
    series: [
      {
        type: 'pie',
        radius: ['57%', '77%'],
        center: ['50%', '51%'],
        startAngle: 90,
        avoidLabelOverlap: false,
        label: { show: false },
        labelLine: { show: false },
        itemStyle: { borderColor: '#fff', borderWidth: 4 },
        data,
      },
    ],
  }
}

function sparkOption(values: number[]): EChartsOption {
  return {
    animationDuration: 700,
    grid: { left: 2, right: 2, top: 8, bottom: 7 },
    xAxis: { type: 'category', show: false, data: values.map((_, index) => index) },
    yAxis: { type: 'value', show: false },
    series: [
      {
        type: 'line',
        data: values,
        symbol: 'none',
        smooth: false,
        lineStyle: { color: '#1267f2', width: 2 },
      },
    ],
  }
}

onMounted(async () => {
  await nextTick()
  createChart(
    reliableChart.value,
    ringOption('低靠', [
      { value: 65, name: '巨靠系数', itemStyle: { color: '#1267f2' } },
      { value: 35, name: '其他', itemStyle: { color: '#e7f0ff' } },
    ]),
  )

  createChart(
    pressureChart.value,
    ringOption('逾期概率', [
      { value: 34, name: '高压力', itemStyle: { color: '#18c7c0' } },
      { value: 66, name: '低压力', itemStyle: { color: '#1267f2' } },
    ]),
  )

  createChart(trendChart.value, sparkOption([15, 34, 18, 8, 27, 55, 36, 48]))
  createChart(pressureTrendChart.value, sparkOption([12, 24, 18, 49, 62, 30, 52, 72]))

  window.addEventListener('resize', resizeCharts)
})

onUnmounted(() => {
  window.removeEventListener('resize', resizeCharts)
  charts.forEach((chart) => chart.dispose())
})
</script>

<template>
  <article class="board reliable-board">
    <div class="board-head">
      <h2><span></span>头寸巨靠情况</h2>
      <div class="actions">
        <button class="active">本月数据<el-icon><ArrowDown /></el-icon></button>
        <el-icon><RefreshRight /></el-icon>
        <el-icon><Setting /></el-icon>
        <el-icon><Minus /></el-icon>
      </div>
    </div>
    <div class="reliable-layout">
      <div class="metric-box">
        <h3>巨靠结果</h3>
        <div ref="reliableChart" class="ring"></div>
        <ul class="legend-list">
          <li><b class="blue"></b>极高靠(≥2.0)</li>
          <li><b class="deep"></b>高靠(1.5-2.0)</li>
          <li><b class="sky"></b>中靠(1.0-1.5)</li>
          <li><b class="orange"></b>低靠(&lt;1.0)</li>
        </ul>
      </div>
      <div class="metric-box">
        <h3>流动性压力点</h3>
        <div ref="pressureChart" class="ring"></div>
        <ul class="legend-list pressure">
          <li><b class="green"></b>高压力(≥70%)</li>
          <li><b class="pale"></b>中压力(30%-70%)</li>
          <li><b class="blue"></b>低压力(&lt;30%)</li>
        </ul>
      </div>
      <div class="mini-strip">
        <div><p>巨靠客户数(个)</p><strong>3566</strong></div>
        <div><p>较上月</p><strong class="blue-text">0.1 <em>↓</em></strong></div>
        <div><p>巨靠趋势(近7日)</p><div ref="trendChart" class="spark"></div></div>
        <div><p>流动性缺口(万元)</p><strong>1025596</strong></div>
        <div><p>较上月</p><strong class="blue-text">↑ 1.2%</strong></div>
        <div><p>压力趋势(近7日)</p><div ref="pressureTrendChart" class="spark"></div></div>
      </div>
    </div>
  </article>
</template>

<style scoped>
.reliable-board {
  --blue: #1267f2;
  --line: #dce4ef;
  min-width: 0;
  height: clamp(520px, 58vh, 640px);
  min-height: 520px;
  padding: 14px;
  display: flex;
  flex-direction: column;
  background: rgba(255, 255, 255, .96);
  border-radius: 10px;
  box-shadow: 0 10px 22px rgba(34, 67, 123, .16);
}

.board-head {
  height: 38px;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
}

.board-head h2 {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 20px;
  line-height: 1.1;
  font-weight: 900;
}

.board-head h2 span {
  width: 13px;
  height: 14px;
  border-radius: 4px;
  background: var(--blue);
  box-shadow: inset 0 0 4px rgba(255, 255, 255, .35);
}

.actions {
  display: flex;
  align-items: center;
  gap: 16px;
  color: #6c7480;
  font-size: 15px;
}

.actions button {
  height: 26px;
  display: flex;
  align-items: center;
  gap: 3px;
  border: 0;
  background: transparent;
  color: #6c7480;
  font-size: 13px;
  font-weight: 600;
}

.actions button.active {
  padding: 0 13px;
  border-radius: 14px;
  background: var(--blue);
  color: #fff;
}

.reliable-layout {
  display: grid;
  flex: 1;
  margin-top: 8px;
  gap: 12px;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: minmax(0, 1fr) auto;
}

.metric-box {
  min-width: 0;
  position: relative;
  height: 100%;
  min-height: 0;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: #fff;
}

.metric-box h3 {
  position: absolute;
  left: 18px;
  top: 18px;
  z-index: 1;
  font-size: 18px;
  font-weight: 900;
}

.ring {
  position: absolute;
  left: 35%;
  top: 53%;
  width: min(56%, 330px);
  height: min(72%, 330px);
  transform: translate(-50%, -50%);
}

.legend-list {
  position: absolute;
  top: 50%;
  right: 9%;
  transform: translateY(-55%);
  display: grid;
  gap: 18px;
  list-style: none;
}

.legend-list li {
  display: flex;
  align-items: center;
  gap: 10px;
  color: #56606d;
  font-size: 15px;
  white-space: nowrap;
}

.legend-list b {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--blue);
}

.deep {
  background: #1667e8 !important;
}

.sky {
  background: #58aef7 !important;
}

.green {
  background: #18c7c0 !important;
}

.pale {
  background: #aeeeff !important;
}

.orange {
  background: #ff9f13 !important;
}

.pressure {
  right: 60px;
}

.mini-strip {
  grid-column: 1 / -1;
  height: 100%;
  min-height: 130px;
  display: grid;
  grid-template-columns: 1.1fr .65fr 1.35fr 1.45fr .7fr 1.35fr;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: #fff;
}

.mini-strip > div {
  padding: 18px;
  border-right: 1px solid #e4e9f0;
}

.mini-strip > div:last-child {
  border-right: 0;
}

.mini-strip p {
  color: #4d5868;
  font-size: 14px;
}

.mini-strip strong {
  display: block;
  margin-top: 18px;
  font-size: 25px;
  font-weight: 900;
}

.blue-text {
  color: var(--blue) !important;
}

.mini-strip em {
  color: #14a77c;
  font-style: normal;
}

.spark {
  width: min(92%, 260px);
  height: 84px;
  margin-top: 13px;
}

@media (max-width: 1200px) {
  .reliable-board {
    height: auto;
    min-height: 0;
  }

  .reliable-layout {
    grid-template-columns: 1fr;
    grid-template-rows: auto;
  }

  .metric-box {
    height: auto;
    min-height: 230px;
  }

  .mini-strip {
    grid-template-columns: repeat(3, 1fr);
    height: auto;
  }

  .mini-strip > div {
    min-height: 72px;
  }
}

@media (max-width: 720px) {
  .actions {
    gap: 10px;
  }

  .board-head {
    height: auto;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 12px;
  }

  .reliable-layout {
    gap: 10px;
  }

  .legend-list {
    right: 16px;
  }

  .mini-strip {
    grid-template-columns: repeat(2, 1fr);
  }

  .mini-strip > div:nth-child(2n) {
    border-right: 0;
  }
}
</style>
