Bladeren bron

fix: 接入瑞都看板设备分类接口
- 移除设备分类假数据,改为调用分类统计接口
- 按 top 优先排序并限制展示前 10 条
- 区分 top 与普通分类柱体颜色
- 增加图表加载状态

Zimo 5 dagen geleden
bovenliggende
commit
207280f0b9
2 gewijzigde bestanden met toevoegingen van 84 en 25 verwijderingen
  1. 3 0
      src/api/pms/stat/index.ts
  2. 81 25
      src/views/pms/stat/rdkb/rd-device-category.vue

+ 3 - 0
src/api/pms/stat/index.ts

@@ -260,6 +260,9 @@ export const IotStatApi = {
   getRdRecentWbcs: async () => {
     return await request.get({ url: `/rq/stat/recent/wbcs/rd` })
   },
+  getRdNewClassify: async () => {
+    return await request.get({ url: `/rq/stat/new/classify` })
+  },
 
   // 瑞都看板(新)
   // 获取ssoToken

+ 81 - 25
src/views/pms/stat/rdkb/rd-device-category.vue

@@ -1,27 +1,45 @@
 <script lang="ts" setup>
 import * as echarts from 'echarts'
+import { IotStatApi } from '@/api/pms/stat'
 import { ANIMATION, CHART_RENDERER, createTooltip, FONT_FAMILY, THEME } from '@/utils/kb'
 
 interface DeviceCategoryItem {
   name: string
   count: number
+  type: string
+}
+
+interface DeviceCategoryResponseItem {
+  className?: string
+  count?: number | string
+  type?: string
 }
 
 const chartRef = ref<HTMLDivElement>()
+const loading = ref(false)
+const categoryData = ref<DeviceCategoryItem[]>([])
 let chart: echarts.ECharts | null = null
 
-const categoryData: DeviceCategoryItem[] = [
-  { name: '压裂泵车', count: 75 },
-  { name: '连油主车', count: 36 },
-  { name: '其他', count: 35 },
-  { name: '小车', count: 32 },
-  { name: '井控装备', count: 22 },
-  { name: '连油辅助设备', count: 19 },
-  { name: '货车', count: 17 },
-  { name: '四川瑞都设备', count: 16 },
-  { name: '卡车', count: 16 },
-  { name: '供液橇', count: 12 }
-]
+const TOP_BAR_COLOR = new echarts.graphic.LinearGradient(0, 0, 1, 0, [
+  { offset: 0, color: '#ffd166' },
+  { offset: 0.58, color: '#ff9f43' },
+  { offset: 1, color: '#f76707' }
+])
+const DEFAULT_BAR_COLOR = new echarts.graphic.LinearGradient(0, 0, 1, 0, [
+  { offset: 0, color: THEME.color.blue.light },
+  { offset: 0.58, color: THEME.color.blue.mid },
+  { offset: 1, color: THEME.color.blue.line }
+])
+
+function sortCategoryData(data: DeviceCategoryItem[]) {
+  const typeOrder = (type: string) => {
+    if (type === 'top') return 0
+    if (type === '') return 1
+    return 2
+  }
+
+  return data.sort((a, b) => typeOrder(a.type) - typeOrder(b.type))
+}
 
 function getChartLayout() {
   const { clientWidth = 0, clientHeight = 0 } = chartRef.value ?? {}
@@ -44,7 +62,7 @@ function formatValue(value: number) {
 
 function getChartOption(): echarts.EChartsOption {
   const layout = getChartLayout()
-  const values = categoryData.map((item) => item.count)
+  const values = categoryData.value.map((item) => item.count)
   const maxValue = Math.max(...values, 1)
   const xAxisMax = Math.ceil((maxValue * 1.12) / 10) * 10
 
@@ -67,7 +85,7 @@ function getChartOption(): echarts.EChartsOption {
       },
       formatter(params: any[]) {
         const first = params[0]
-        const row = categoryData[first?.dataIndex ?? 0]
+        const row = categoryData.value[first?.dataIndex ?? 0]
         if (!row) return ''
 
         return [
@@ -109,7 +127,7 @@ function getChartOption(): echarts.EChartsOption {
     },
     yAxis: {
       type: 'category',
-      data: categoryData.map((item) => item.name),
+      data: categoryData.value.map((item) => item.name),
       inverse: true,
       axisLine: {
         show: false
@@ -130,7 +148,12 @@ function getChartOption(): echarts.EChartsOption {
       {
         name: '设备数量',
         type: 'bar',
-        data: values,
+        data: categoryData.value.map((item) => ({
+          value: item.count,
+          itemStyle: {
+            color: item.type === 'top' ? TOP_BAR_COLOR : DEFAULT_BAR_COLOR
+          }
+        })),
         barWidth: layout.barWidth,
         showBackground: true,
         backgroundStyle: {
@@ -138,12 +161,7 @@ function getChartOption(): echarts.EChartsOption {
           borderRadius: 999
         },
         itemStyle: {
-          borderRadius: 999,
-          color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
-            { offset: 0, color: THEME.color.blue.light },
-            { offset: 0.58, color: THEME.color.blue.mid },
-            { offset: 1, color: THEME.color.blue.line }
-          ])
+          borderRadius: 999
         },
         label: {
           show: true,
@@ -159,8 +177,8 @@ function getChartOption(): echarts.EChartsOption {
         },
         emphasis: {
           itemStyle: {
-            shadowBlur: 16,
-            shadowColor: THEME.color.blue.shadow
+            shadowBlur: 2
+            // shadowColor: THEME.color.blue.shadow
           }
         }
       }
@@ -192,8 +210,33 @@ function destroyChart() {
   chart = null
 }
 
+async function getDeviceCategory() {
+  loading.value = true
+
+  try {
+    const res = await IotStatApi.getRdNewClassify()
+    categoryData.value = Array.isArray(res)
+      ? sortCategoryData(
+          res.map((item: DeviceCategoryResponseItem) => ({
+            name: item.className || '未知',
+            count: Number(item.count ?? 0),
+            type: item.type || ''
+          }))
+        ).slice(0, 10)
+      : []
+    renderChart()
+  } catch (error) {
+    console.error('获取瑞都设备分类失败:', error)
+    categoryData.value = []
+    renderChart()
+  } finally {
+    loading.value = false
+  }
+}
+
 onMounted(() => {
   initChart()
+  getDeviceCategory()
   window.addEventListener('resize', resizeChart)
   window.addEventListener('rdkb:resize', resizeChart)
 })
@@ -214,13 +257,26 @@ onUnmounted(() => {
       </div>
       设备分类
     </div>
-    <div ref="chartRef" class="device-category-chart"></div>
+    <div
+      v-loading="loading"
+      element-loading-text="加载中..."
+      element-loading-background="rgb(222 236 252 / 72%)"
+      class="device-category-body">
+      <div ref="chartRef" class="device-category-chart"></div>
+    </div>
   </div>
 </template>
 
 <style lang="scss" scoped>
 @import url('@/styles/kb.scss');
 
+.device-category-body {
+  display: flex;
+  width: 100%;
+  min-height: 0;
+  flex: 1;
+}
+
 .device-category-chart {
   width: 100%;
   min-height: 0;