10 小时以前 1c829f9177eab675b22be4d20ef2761ed1bbb423
src/views/reportAnalysis/dataDashboard/components/basic/right-top.vue
@@ -13,7 +13,7 @@
        :tooltip="tooltip"
        :xAxis="xAxis"
        :yAxis="yAxis"
        :options="{ backgroundColor: 'transparent', textStyle: { color: '#B8C8E0' } }"
        :options="{ backgroundColor: 'transparent', textStyle: { color: BI.text } }"
        style="height: 360px"
      />
    </div>
@@ -26,30 +26,19 @@
import PanelHeader from '../PanelHeader.vue'
import DateTypeSwitch from '../DateTypeSwitch.vue'
import { supplierPurchaseRanking } from '@/api/viewIndex.js'
import { BI, withTooltip } from '../../theme.js'
const chartStyle = {
  width: '100%',
  height: '100%',
}
const radio1 = ref(1)
// 飞机图标 SVG path
const aircraft =
  'path://M107.000,71.000 C104.936,71.000 102.665,70.806 100.273,70.467 C94.592,76.922 86.275,81.000 77.000,81.000 C70.794,81.000 65.020,79.170 60.172,76.029 C66.952,74.165 72.647,69.714 76.173,63.817 C69.821,61.362 64.063,58.593 60.000,56.039 L60.000,52.813 C70.456,53.950 80.723,55.000 83.000,55.000 C88.972,55.000 93.000,53.723 93.000,50.000 C93.000,47.071 89.222,45.000 83.000,45.000 C80.723,45.000 70.456,46.050 60.000,47.187 L60.000,43.989 C64.057,41.431 69.807,38.644 76.168,36.173 C72.641,30.281 66.948,25.834 60.172,23.971 C65.020,20.830 70.794,19.000 77.000,19.000 C86.270,19.000 94.584,23.074 100.265,29.524 C102.647,29.191 104.918,29.000 107.000,29.000 C129.644,29.000 148.000,50.000 148.000,50.000 C148.000,50.000 129.644,71.000 107.000,71.000 ZM113.000,38.000 C106.373,38.000 101.000,43.373 101.000,50.000 C101.000,56.627 106.373,62.000 113.000,62.000 C119.627,62.000 125.000,56.627 125.000,50.000 C125.000,43.373 119.627,38.000 113.000,38.000 ZM113.000,56.000 C109.686,56.000 107.000,53.314 107.000,50.000 C107.000,46.686 109.686,44.000 113.000,44.000 C116.314,44.000 119.000,46.686 119.000,50.000 C119.000,53.314 116.314,56.000 113.000,56.000 ZM110.500,19.000 C109.567,19.000 108.763,18.483 108.334,17.726 C100.231,9.857 89.187,5.000 77.000,5.000 C64.813,5.000 53.769,9.857 45.666,17.726 C45.237,18.483 44.433,19.000 43.500,19.000 C42.119,19.000 41.000,17.881 41.000,16.500 C41.000,15.847 41.256,15.259 41.665,14.813 L41.575,14.718 C50.629,5.628 63.156,-0.000 77.000,-0.000 C90.844,-0.000 103.371,5.628 112.425,14.718 L112.335,14.813 C112.744,15.259 113.000,15.847 113.000,16.500 C113.000,17.881 111.881,19.000 110.500,19.000 ZM53.000,49.484 C61.406,48.626 77.810,47.000 81.345,47.000 C87.353,47.000 91.000,48.243 91.000,50.000 C91.000,52.234 87.111,53.000 81.345,53.000 C77.810,53.000 61.406,51.374 53.000,50.516 L53.000,49.484 ZM53.000,47.000 L9.000,50.000 L53.000,53.000 L53.000,56.000 L-0.000,50.000 L53.000,44.000 L53.000,47.000 ZM43.500,81.000 C44.433,81.000 45.237,81.517 45.666,82.274 C53.769,90.143 64.813,95.000 77.000,95.000 C89.187,95.000 100.231,90.143 108.334,82.274 C108.763,81.517 109.567,81.000 110.500,81.000 C111.881,81.000 113.000,82.119 113.000,83.500 C113.000,84.153 112.744,84.741 112.335,85.187 L112.425,85.282 C103.371,94.372 90.844,100.000 77.000,100.000 C63.156,100.000 50.629,94.372 41.575,85.282 L41.665,85.187 C41.256,84.741 41.000,84.153 41.000,83.500 C41.000,82.119 42.119,81.000 43.500,81.000 Z'
// 颜色配置
const color = {
  0: '#ff5676',
  1: '#ffd83e',
  2: '#fbff94',
  3: '#7daeff',
}
const radio1 = ref(3) // 1=周 2=月 3=季度,默认季度
// 原始数据
const dataArr = ref([])
// 排序后的数据
// 排序后的数据(升序:值越大越靠上)
const dataArray = computed(() => {
  return [...dataArr.value].sort((a, b) => a.NUM - b.NUM)
})
@@ -64,66 +53,43 @@
  return dataArray.value.map((v) => v.NAME)
})
// 排名配色:Top1 金色,Top2-3 亮蓝,其余暗蓝
const rankColor = (rank) => {
  if (rank === 1) return '#F0B14A'
  if (rank <= 3) return BI.accentBright
  return '#2C4A9E'
}
const getRank = (i) => dataArray.value.length - i
// y轴数据(数值,带样式)
const dataNum = computed(() => {
  return dataArray.value.map((v, i) => {
    const index = dataArray.value.length - i - 1
    const isTop3 = index < 3
    const rank = getRank(i)
    return {
      value: Number(v.NUM),
      itemStyle: {
        color: {
          type: 'linear',
          x: 1,
          y: 0,
          x2: 0,
          y2: 0,
          colorStops: [
            {
              offset: 0,
              color: isTop3 ? '#ffdae1' : '#ecf3ff',
            },
            {
              offset: 0.07,
              color: isTop3 ? color[index] : color[3],
            },
            {
              offset: 1,
              color: isTop3
                ? 'rgba(255, 86, 118, .1)'
                : 'rgba(125,174,255, .1)',
            },
          ],
          global: false,
        },
        barBorderRadius: [0, 20, 20, 0],
        color: rankColor(rank),
        barBorderRadius: [0, 10, 10, 0],
      },
      symbol: isTop3 ? aircraft : 'none',
      symbolPosition: 'end',
      symbolSize: [30, 25],
      symbolOffset: [35, 0],
    }
  })
})
// 背景数据
// 背景轨道数据
const bgData = computed(() => {
  const maxValue = Math.max(...dataNum.value.map((v) => v.value))
  return dataNum.value.map(() => maxValue + 200)
  const maxValue = dataNum.value.length ? Math.max(...dataNum.value.map((v) => v.value)) : 0
  return dataNum.value.map(() => maxValue * 1.08 || 1)
})
// tooltip
const tooltip = computed(() => {
  return {
    trigger: 'axis',
    textStyle: { fontSize: '100%' },
    formatter: function (params) {
      let result = params[0].axisValueLabel + '<br/>'
      result += `<div>${params[0].marker}${params[0].value}元</div>`
      return result
    },
  }
const tooltip = withTooltip({
  trigger: 'axis',
  formatter: function (params) {
    let result = params[0].axisValueLabel + '<br/>'
    result += `<div>${params[0].marker}${Number(params[0].value || 0).toLocaleString('zh-CN')}元</div>`
    return result
  },
})
// grid
@@ -167,7 +133,7 @@
          a: {
            width: 120,
            fontSize: 14,
            color: '#fff',
            color: BI.textStrong,
            padding: [5, 4, 5, 0],
            align: 'right',
          },
@@ -183,54 +149,17 @@
      axisLabel: {
        formatter: (params, index) => {
          const value = typeof params === 'object' ? params.value : params
          const percent = ((value / total.value) * 100).toFixed(0)
          const rank = dataArray.value.length - index
          const isTop3 = rank < 4
          return `{a${isTop3 ? rank : ''}|${percent} }{b${isTop3 ? rank : ''}|%}`
          const percent = total.value ? ((value / total.value) * 100).toFixed(0) : 0
          const rank = getRank(index)
          return `{a${rank}|${percent} }{b${rank}|%}`
        },
        rich: {
          a: {
            fontSize: 18,
            color: '#98bfff',
            verticalAlign: 'bottom',
          },
          a1: {
            fontSize: 18,
            color: '#ff7f97',
            verticalAlign: 'bottom',
          },
          a2: {
            fontSize: 18,
            color: '#ffce64',
            verticalAlign: 'bottom',
          },
          a3: {
            fontSize: 18,
            color: '#e8ed66',
            verticalAlign: 'bottom',
          },
          b: {
            fontSize: 12,
            color: '#98bfff',
            verticalAlign: 'bottom',
          },
          b1: {
            fontSize: 12,
            color: '#ff7f97',
            verticalAlign: 'bottom',
          },
          b2: {
            fontSize: 12,
            color: '#ffce64',
            verticalAlign: 'bottom',
          },
          b3: {
            fontSize: 12,
            color: '#e8ed66',
            verticalAlign: 'bottom',
          },
        },
        rich: dataNum.value.reduce((rich, _, i) => {
          const rank = getRank(i)
          const color = rank === 1 ? '#F0B14A' : rank <= 3 ? BI.accentBright : BI.text
          rich[`a${rank}`] = { fontSize: 16, color, verticalAlign: 'bottom' }
          rich[`b${rank}`] = { fontSize: 12, color, verticalAlign: 'bottom' }
          return rich
        }, {}),
      },
      axisLine: { show: false },
      axisTick: { show: false },
@@ -239,71 +168,41 @@
  ]
})
// series
const series = computed(() => {
  return [
    {
      z: 6,
      type: 'pictorialBar',
      data: dataNum.value,
// series:背景轨道 + 实色条
const series = computed(() => [
  {
    name: '背景',
    z: 5,
    type: 'bar',
    barWidth: 18,
    tooltip: { show: false },
    itemStyle: {
      color: 'rgba(143, 163, 200, 0.12)',
      barBorderRadius: [0, 10, 10, 0],
    },
    {
      z: 6,
      type: 'bar',
      barWidth: 25,
      tooltip: { show: false },
      itemStyle: {
        color: 'rgba(255,255,255,.1)',
        barBorderRadius: [0, 20, 20, 0],
      },
      data: bgData.value,
    },
    {
      type: 'bar',
      barWidth: 25,
      barGap: '-100%',
      tooltip: { show: false },
      itemStyle: {
        color: {
          type: 'linear',
          x: 1,
          y: 0,
          x2: 0,
          y2: 0,
          colorStops: [
            {
              offset: 0,
              color: 'rgba(255, 218, 220)',
            },
            {
              offset: 0.07,
              color: 'rgba(255, 86, 118)',
            },
            {
              offset: 1,
              color: 'rgba(255, 86, 118, 0)',
            },
          ],
          global: false,
        },
        barBorderRadius: [0, 20, 20, 0],
      },
      data: dataNum.value,
    },
  ]
})
    data: bgData.value,
  },
  {
    name: '金额',
    z: 6,
    type: 'bar',
    barWidth: 18,
    barGap: '-100%',
    data: dataNum.value,
  },
])
// 供应商采购排名
const fetchSupplierRanking = () => {
  supplierPurchaseRanking({ type: radio1.value })
    .then((res) => {
      if (res.code === 200 && Array.isArray(res.data)) {
        dataArr.value = res.data.map(item => ({
      if (res.code === 200 && Array.isArray(res.data) && res.data.length > 0) {
        dataArr.value = res.data.map((item) => ({
          NAME: item.supplierName,
          NUM: item.totalAmount
          NUM: Number(item.totalAmount) || 0,
        }))
      } else {
        // 如果没有数据,使用模拟数据
        // 接口无数据时给一组模拟供应商,保证UI可用
        dataArr.value = [
          { NAME: '供应商A', NUM: 102 },
          { NAME: '供应商B', NUM: 122 },
@@ -315,7 +214,6 @@
    })
    .catch((error) => {
      console.error('获取供应商采购排名失败:', error)
      // 使用模拟数据
      dataArr.value = [
        { NAME: '供应商A', NUM: 102 },
        { NAME: '供应商B', NUM: 122 },
@@ -327,7 +225,7 @@
}
// 处理日期类型切换
const handleDateTypeChange = (value) => {
const handleDateTypeChange = () => {
  fetchSupplierRanking()
}
@@ -338,7 +236,9 @@
<style scoped>
.panel-item-customers {
  border: 1px solid #1a58b0;
  border: 1px solid var(--bi-panel-border);
  background: var(--bi-panel-bg);
  border-radius: 8px;
  padding: 18px;
  width: 100%;
  height: 449px;
@@ -348,11 +248,5 @@
  display: flex;
  justify-content: flex-end;
  margin-bottom: 16px;
}
.section-title {
  font-weight: 500;
  font-size: 16px;
  color: #d9ecff;
}
</style>