Jelajahi Sumber

瑞鹰统计看板

lipenghui 3 minggu lalu
induk
melakukan
8dbc260cf8
4 mengubah file dengan 2106 tambahan dan 50 penghapusan
  1. 45 45
      src/views/pms/stat/rdkb.vue
  2. 114 5
      src/views/pms/stat/rhkb.vue
  3. 1026 0
      src/views/pms/stat/rykb.vue
  4. 921 0
      src/views/pms/stat/test.vue

+ 45 - 45
src/views/pms/stat/rdkb.vue

@@ -78,7 +78,7 @@
     </el-row>
     <el-row :gutter="16" class="mb-4">
       <!-- 设备状态统计和工单数量情况图表部分保持不变 -->
-      <el-col :span="7">
+      <el-col :span="8">
         <el-card class="chart-card" shadow="never">
           <template #header>
             <div class="flex items-center">
@@ -88,7 +88,7 @@
           <div ref="statusChartRef" class="h-[290px]"></div>
         </el-card>
       </el-col>
-      <el-col :span="17">
+      <el-col :span="16">
         <el-card class="chart-card" shadow="never">
           <template #header>
             <div class="flex items-center justify-between">
@@ -101,7 +101,7 @@
     </el-row>
     <el-row :gutter="16" class="mb-4">
       <!-- 备件更换情况部分保持不变 -->
-      <el-col :span="7">
+      <el-col :span="8">
         <el-card class="chart-card" shadow="never">
           <template #header>
             <div class="flex items-center justify-between">
@@ -110,10 +110,10 @@
           </template>
           <!-- 添加两个卡片 -->
           <div class="flex justify-between mb-2">
-            <el-card class="stat-card " >
+            <el-card class="stat-card">
               <div class="flex flex-row justify-evenly">
                 <div>
-                  <Icon icon="fa-solid:award" size="30" color="blue"/>
+                  <Icon icon="fa-solid:award" size="30" color="blue" />
                 </div>
                 <div class="flex flex-col items-center">
                   <span class="text-sm text-gray-600">物料消耗数量</span>
@@ -124,7 +124,7 @@
             <el-card class="stat-card">
               <div class="flex flex-row justify-evenly">
                 <div>
-                  <Icon icon="fa-solid:yen-sign" size="30" color="orange"/>
+                  <Icon icon="fa-solid:yen-sign" size="30" color="orange" />
                 </div>
                 <div class="flex flex-col items-center">
                   <span class="text-sm text-gray-600">物料消耗费用</span>
@@ -136,11 +136,11 @@
           <div ref="sparePartRef" class="h-[330px]"></div>
         </el-card>
       </el-col>
-      <el-col :span="17">
+      <el-col :span="16">
         <div class="flex flex-col justify-between">
           <el-card class="chart-card" shadow="never">
             <template #header>
-              <div class="flex items-center justify-between" >
+              <div class="flex items-center justify-between">
                 <span class="text-base font-medium text-gray-600">保养情况</span>
               </div>
             </template>
@@ -149,18 +149,18 @@
               <div class="w-3/5 p-4 flex flex-col mt-5">
                 <div class="flex justify-between">
                   <div class="flex flex-col items-center">
-                    <Icon icon="fa-solid:list" size="30" color="blue"/>
-                    <p style="font-size: 20px;margin-top: 5px">总工单数</p>
-                    <span style="font-size: 20px">{{ by.finished+by.todo }}</span>
+                    <Icon icon="fa-solid:list" size="30" color="blue" />
+                    <p style="font-size: 20px; margin-top: 5px">总工单数</p>
+                    <span style="font-size: 20px">{{ by.finished + by.todo }}</span>
                   </div>
                   <div class="flex flex-col items-center">
-                    <Icon icon="fa-solid:check-circle" size="30" color="green"/>
-                    <p style="font-size: 20px;margin-top: 5px">已执行工单数</p>
+                    <Icon icon="fa-solid:check-circle" size="30" color="green" />
+                    <p style="font-size: 20px; margin-top: 5px">已执行工单数</p>
                     <span style="font-size: 20px">{{ by.finished }}</span>
                   </div>
                   <div class="flex flex-col items-center">
-                    <Icon icon="fa-solid:hourglass-half" size="30" color="orange"/>
-                    <p style="font-size: 20px;margin-top: 5px">待执行工单数 </p>
+                    <Icon icon="fa-solid:hourglass-half" size="30" color="orange" />
+                    <p style="font-size: 20px; margin-top: 5px">待执行工单数 </p>
                     <span style="font-size: 20px">{{ by.todo }}</span>
                   </div>
                 </div>
@@ -178,18 +178,18 @@
               <div class="w-3/5 p-4 flex flex-col mt-5">
                 <div class="flex justify-between">
                   <div class="flex flex-col items-center">
-                    <Icon icon="fa-solid:list" size="30" color="blue"/>
-                    <p style="font-size: 20px;margin-top: 5px">总工单数</p>
-                    <span style="font-size: 20px">{{ inspect.todo+inspect.finished }}</span>
+                    <Icon icon="fa-solid:list" size="30" color="blue" />
+                    <p style="font-size: 20px; margin-top: 5px">总工单数</p>
+                    <span style="font-size: 20px">{{ inspect.todo + inspect.finished }}</span>
                   </div>
                   <div class="flex flex-col items-center">
-                    <Icon icon="fa-solid:check-circle" size="30" color="green"/>
-                    <p style="font-size: 20px;margin-top: 5px">已执行工单数</p>
+                    <Icon icon="fa-solid:check-circle" size="30" color="green" />
+                    <p style="font-size: 20px; margin-top: 5px">已执行工单数</p>
                     <span style="font-size: 20px">{{ inspect.finished }}</span>
                   </div>
                   <div class="flex flex-col items-center">
-                    <Icon icon="fa-solid:hourglass-half" size="30" color="orange"/>
-                    <p style="font-size: 20px;margin-top: 5px">待执行工单数</p>
+                    <Icon icon="fa-solid:hourglass-half" size="30" color="orange" />
+                    <p style="font-size: 20px; margin-top: 5px">待执行工单数</p>
                     <span style="font-size: 20px">{{ inspect.todo }}</span>
                   </div>
                 </div>
@@ -217,8 +217,8 @@ import {
 import { LabelLayout, UniversalTransition } from 'echarts/features'
 import { CanvasRenderer } from 'echarts/renderers'
 import { IotStatApi } from '@/api/pms/stat'
-import {ref, onMounted, computed, watch, nextTick, reactive} from 'vue';
-import {useUserStore} from "@/store/modules/user";
+import { ref, onMounted, computed, watch, nextTick, reactive } from 'vue'
+import { useUserStore } from '@/store/modules/user'
 
 /** 会员统计 */
 defineOptions({ name: 'IotRdStat' })
@@ -265,7 +265,7 @@ const maintain = ref({
 })
 const by = ref({
   todo: undefined,
-  finished: undefined,
+  finished: undefined
 })
 const fill = ref({
   filledCount: undefined,
@@ -304,14 +304,14 @@ const completedInspectionOrders = ref(60)
 
 // 计算物料消耗数量及费用
 const totalMaterialCount = computed(() => {
-  const quantitySeries = sparePartData.value.series.find(item => item.name === '数量');
-  return quantitySeries ? quantitySeries.data.reduce((sum, val) => sum + val, 0) : 0;
-});
+  const quantitySeries = sparePartData.value.series.find((item) => item.name === '数量')
+  return quantitySeries ? quantitySeries.data.reduce((sum, val) => sum + val, 0) : 0
+})
 
 const totalMaterialCost = computed(() => {
-  const costSeries = sparePartData.value.series.find(item => item.name === '金额');
-  return costSeries ? costSeries.data.reduce((sum, val) => sum + val, 0) : 0;
-});
+  const costSeries = sparePartData.value.series.find((item) => item.name === '金额')
+  return costSeries ? costSeries.data.reduce((sum, val) => sum + val, 0) : 0
+})
 
 const getStats = () => {
   IotStatApi.getDeviceStatusCount().then((res) => {
@@ -343,9 +343,9 @@ const getStats = () => {
     inspect.value = res
     initInspectChart()
   })
-  fillQueryParams.deptId = useUserStore().getUser.deptId;
+  fillQueryParams.deptId = useUserStore().getUser.deptId
   IotStatApi.getDeptStatistics(fillQueryParams).then((res) => {
-    fill.value = res.totalList[0] || [];
+    fill.value = res.totalList[0] || []
   })
   initSparePartChart()
   initInspectionChart()
@@ -481,7 +481,7 @@ const initSparePartChart = () => {
       yAxisIndex: item.yAxisIndex,
       itemStyle: {
         color: ['#6084fb', '#5aef13'][index]
-      },
+      }
     }))
   }
 
@@ -491,7 +491,8 @@ const initSparePartChart = () => {
 const initInspectChart = () => {
   if (!inspectChartRef.value) return
   inspectChartInstance = echarts.init(inspectChartRef.value)
-  const completionRate = (inspect.value.finished / (inspect.value.finished+inspect.value.todo)) * 100
+  const completionRate =
+    (inspect.value.finished / (inspect.value.finished + inspect.value.todo)) * 100
   debugger
   const option = {
     tooltip: {
@@ -501,8 +502,8 @@ const initInspectChart = () => {
       // top: '5%',
       // right: '10%',
       // align: 'center',
-      orient: 'horizontal',  // 水平排列图例项
-      bottom: '0%',         // 放置在底部
+      orient: 'horizontal', // 水平排列图例项
+      bottom: '0%', // 放置在底部
       icon: 'circle'
     },
     series: [
@@ -527,8 +528,8 @@ const initInspectChart = () => {
         //   color: ['#e4a317', '#5aef13']
         // },
         data: [
-          { name:'完成率',value: completionRate.toFixed(2)  },
-          { name:'未完成率',value: 100 - completionRate.toFixed(2)  }
+          { name: '完成率', value: completionRate.toFixed(2) },
+          { name: '未完成率', value: 100 - completionRate.toFixed(2) }
         ]
       }
     ]
@@ -539,7 +540,7 @@ const initInspectChart = () => {
 const initMaintenanceChart = () => {
   if (!maintenanceChartRef.value) return
   maintenanceChartInstance = echarts.init(maintenanceChartRef.value)
-  const completionRate = (by.value.finished / (by.value.finished+by.value.todo)) * 100
+  const completionRate = (by.value.finished / (by.value.finished + by.value.todo)) * 100
   debugger
   const option = {
     tooltip: {
@@ -549,8 +550,8 @@ const initMaintenanceChart = () => {
       // top: '5%',
       // right: '10%',
       // align: 'center',
-      orient: 'horizontal',  // 水平排列图例项
-      bottom: '0%',         // 放置在底部
+      orient: 'horizontal', // 水平排列图例项
+      bottom: '0%', // 放置在底部
       icon: 'circle'
     },
     series: [
@@ -572,8 +573,8 @@ const initMaintenanceChart = () => {
           show: true
         },
         data: [
-          { name:'完成率',value: completionRate.toFixed(2)  },
-          { name:'未完成率',value: 100 - completionRate.toFixed(2)  }
+          { name: '完成率', value: completionRate.toFixed(2) },
+          { name: '未完成率', value: 100 - completionRate.toFixed(2) }
         ]
       }
     ]
@@ -639,7 +640,6 @@ const initDeviceStatusCharts = () => {
   })
 }
 
-
 /** 初始化 **/
 onMounted(async () => {
   loading.value = true

+ 114 - 5
src/views/pms/stat/rhkb.vue

@@ -1,7 +1,83 @@
 <template>
+  <el-row :gutter="16" class="summary">
+    <!-- 原有的统计卡片部分保持不变 -->
+    <el-col v-loading="loading" :sm="3" :xs="12">
+      <SummaryCard
+        :value="device.total || 0"
+        icon="fa-solid:project-diagram"
+        icon-bg-color="text-blue-500"
+        icon-color="bg-blue-100"
+        title="设备数"
+      />
+    </el-col>
+    <el-col v-loading="loading" :sm="3" :xs="12">
+      <SummaryCard
+        :value="maintain.total || 0"
+        icon="fa-solid:list"
+        icon-bg-color="text-pink-500"
+        icon-color="bg-blue-100"
+        title="维修工单"
+      />
+    </el-col>
+    <el-col v-loading="loading" :sm="3" :xs="12">
+      <SummaryCard
+        :value="fill.unfilledCount || 0"
+        icon="fa-solid:times-circle"
+        icon-bg-color="text-purple-500"
+        icon-color="bg-purple-100"
+        title="运行未填写"
+      />
+    </el-col>
+    <el-col v-loading="loading" :sm="3" :xs="12">
+      <SummaryCard
+        :value="fill.filledCount || 0"
+        icon="fa-solid:award"
+        icon-bg-color="text-purple-500"
+        icon-color="bg-purple-100"
+        title="运行已填写"
+      />
+    </el-col>
+    <el-col v-loading="loading" :sm="3" :xs="12">
+      <SummaryCard
+        :value="by.todo || 0"
+        icon="fa-solid:times-circle"
+        icon-bg-color="text-green-500"
+        icon-color="bg-green-100"
+        title="未执行保养"
+      />
+    </el-col>
+    <el-col v-loading="loading" :sm="3" :xs="12">
+      <SummaryCard
+        :value="by.finished || 0"
+        icon="fa-solid:award"
+        icon-bg-color="text-green-500"
+        icon-color="bg-green-100"
+        title="已执行保养"
+      />
+    </el-col>
+    <el-col v-loading="loading" :sm="3" :xs="12">
+      <SummaryCard
+        :value="inspectt.todo || 0"
+        icon="fa-solid:times-circle"
+        icon-bg-color="text-yellow-500"
+        icon-color="bg-yellow-100"
+        title="待填写巡检"
+      />
+    </el-col>
+    <el-col v-loading="loading" :sm="3" :xs="12">
+      <SummaryCard
+        :value="inspectt.finished || 0"
+        icon="fa-solid:award"
+        icon-bg-color="text-yellow-500"
+        icon-color="bg-yellow-100"
+        title="已填写巡检"
+      />
+    </el-col>
+    <!-- 其他统计卡片... -->
+  </el-row>
   <!-- 第二行:图表行 -->
-  <el-row :gutter="16" class="mb-4">
-    <el-col :span="6">
+  <el-row :gutter="16" class="mb-4 mt-3">
+    <el-col :span="7">
       <el-card class="chart-card" shadow="never">
         <template #header>
           <div class="flex items-center">
@@ -11,7 +87,7 @@
         <div ref="statusChartRef" class="h-[290px]"></div>
       </el-card>
     </el-col>
-    <el-col :span="8">
+    <el-col :span="7">
       <el-card class="chart-card" shadow="never">
         <template #header>
           <div class="flex items-center">
@@ -35,7 +111,7 @@
 
   <!-- 第三行:消息统计行 -->
   <el-row :gutter="16" class="mb-1">
-    <el-col :span="6">
+    <el-col :span="7">
       <el-card class="chart-card" shadow="never">
         <template #header>
           <div class="flex items-center">
@@ -45,7 +121,7 @@
         <div ref="materialChartRef" class="h-[320px]"></div>
       </el-card>
     </el-col>
-    <el-col :span="18">
+    <el-col :span="17">
       <el-card class="chart-card" shadow="never">
         <template #header>
           <div class="flex items-center justify-between">
@@ -79,6 +155,9 @@ import {
 } from '@/api/iot/statistics'
 import { formatDate } from '@/utils/formatTime'
 import { IotStatApi } from '@/api/pms/stat'
+import SummaryCard from "@/components/SummaryCard/index.vue";
+import {reactive, ref} from "vue";
+import {useUserStore} from "@/store/modules/user";
 
 // TODO @super:参考下 /Users/yunai/Java/yudao-ui-admin-vue3/src/views/mall/home/index.vue,拆一拆组件
 
@@ -103,6 +182,18 @@ echarts.use([
 
 const dateRange = ref<[Date, Date] | null>(null)
 
+const by = ref({
+  todo: undefined,
+  finished: undefined
+})
+const fill = ref({
+  filledCount: undefined,
+  unfilledCount: undefined
+})
+const inspectt = ref({
+  finished: 0,
+  todo: 0
+})
 const queryParams = reactive({
   startTime: Date.now() - 7 * 24 * 60 * 60 * 1000, // 设置默认开始时间为 7 天前
   endTime: Date.now() // 设置默认结束时间为当前时间
@@ -197,6 +288,24 @@ const getStats =  () => {
     orderSevenData.value = res
     initQxChart();
   })
+  IotStatApi.getMaintenanceStatus().then((res) => {
+    by.value = res
+    initMaintenanceChart()
+  })
+  const fillQueryParams = reactive({
+    startTime: Date.now() - 7 * 24 * 60 * 60 * 1000, // 设置默认开始时间为 7 天前
+    endTime: Date.now(), // 设置默认结束时间为当前时间
+    createTime: [],
+    deptId: null, // 选中的部门ID
+    status: null // 填写状态
+  })
+  IotStatApi.getInspectStatus(fillQueryParams).then((res) => {
+    inspectt.value = res
+  })
+  fillQueryParams.deptId = useUserStore().getUser.deptId
+  IotStatApi.getDeptStatistics(fillQueryParams).then((res) => {
+    fill.value = res.totalList[0] || []
+  })
 }
 
 const initMaterials = () => {

+ 1026 - 0
src/views/pms/stat/rykb.vue

@@ -0,0 +1,1026 @@
+<template>
+  <el-row :gutter="16" class="summary">
+    <!-- 原有的统计卡片部分保持不变 -->
+    <el-col v-loading="loading" :sm="3" :xs="12">
+      <SummaryCard
+        :value="device.total || 0"
+        icon="fa-solid:project-diagram"
+        icon-bg-color="text-blue-500"
+        icon-color="bg-blue-100"
+        title="设备数"
+      />
+    </el-col>
+    <el-col v-loading="loading" :sm="3" :xs="12">
+      <SummaryCard
+        :value="maintain.total || 0"
+        icon="fa-solid:list"
+        icon-bg-color="text-pink-500"
+        icon-color="bg-blue-100"
+        title="维修工单"
+      />
+    </el-col>
+    <el-col v-loading="loading" :sm="3" :xs="12">
+      <SummaryCard
+        :value="fill.unfilledCount || 0"
+        icon="fa-solid:times-circle"
+        icon-bg-color="text-purple-500"
+        icon-color="bg-purple-100"
+        title="运行未填写"
+      />
+    </el-col>
+    <el-col v-loading="loading" :sm="3" :xs="12">
+      <SummaryCard
+        :value="fill.filledCount || 0"
+        icon="fa-solid:award"
+        icon-bg-color="text-purple-500"
+        icon-color="bg-purple-100"
+        title="运行已填写"
+      />
+    </el-col>
+    <el-col v-loading="loading" :sm="3" :xs="12">
+      <SummaryCard
+        :value="by.todo || 0"
+        icon="fa-solid:times-circle"
+        icon-bg-color="text-green-500"
+        icon-color="bg-green-100"
+        title="未执行保养"
+      />
+    </el-col>
+    <el-col v-loading="loading" :sm="3" :xs="12">
+      <SummaryCard
+        :value="by.finished || 0"
+        icon="fa-solid:award"
+        icon-bg-color="text-green-500"
+        icon-color="bg-green-100"
+        title="已执行保养"
+      />
+    </el-col>
+    <el-col v-loading="loading" :sm="3" :xs="12">
+      <SummaryCard
+        :value="inspectt.todo || 0"
+        icon="fa-solid:times-circle"
+        icon-bg-color="text-yellow-500"
+        icon-color="bg-yellow-100"
+        title="待填写巡检"
+      />
+    </el-col>
+    <el-col v-loading="loading" :sm="3" :xs="12">
+      <SummaryCard
+        :value="inspectt.finished || 0"
+        icon="fa-solid:award"
+        icon-bg-color="text-yellow-500"
+        icon-color="bg-yellow-100"
+        title="已填写巡检"
+      />
+    </el-col>
+    <!-- 其他统计卡片... -->
+  </el-row>
+  <!-- 第二行:图表行 -->
+  <el-row :gutter="16" class="mb-4 mt-3">
+    <el-col :span="6">
+      <el-card class="chart-card" shadow="never">
+        <template #header>
+          <div class="flex items-center">
+            <span class="text-base font-medium text-gray-600">设备状态统计</span>
+          </div>
+        </template>
+        <div ref="statusChartRef" class="h-[320px]"></div>
+      </el-card>
+    </el-col>
+    <el-col :span="7">
+      <el-card class="chart-card" shadow="never">
+        <template #header>
+          <div class="flex items-center">
+            <span class="text-base font-medium text-gray-600">设备类别TOP5数量</span>
+          </div>
+        </template>
+        <div ref="topContainer" class="h-[320px]"></div>
+      </el-card>
+    </el-col>
+    <el-col :span="11">
+      <el-card class="chart-card" shadow="never">
+        <template #header>
+          <div class="flex items-center justify-between">
+            <span class="text-base font-medium text-gray-600">工单数量情况</span>
+          </div>
+        </template>
+        <div ref="qxRef" class="h-[320px]"></div>
+      </el-card>
+    </el-col>
+  </el-row>
+
+  <!-- 新增:修井完成情况图表 -->
+  <el-row :gutter="16" class="mb-4">
+    <el-col :span="8">
+    <div class="flex flex-col justify-between">
+      <el-card class="chart-card" shadow="never">
+        <template #header>
+          <div class="flex items-center">
+            <span class="text-base font-medium text-gray-600">修井完成情况</span>
+          </div>
+        </template>
+        <div ref="repairWellChartRef" class="h-[150px]"></div>
+      </el-card>
+      <el-card class="chart-card mt-1" shadow="never">
+        <template #header>
+          <div class="flex items-center">
+            <span class="text-base font-medium text-gray-600">钻井完成情况</span>
+          </div>
+        </template>
+        <div ref="drillingWellChartRef" class="h-[150px]"></div>
+      </el-card>
+    </div>
+    </el-col>
+    <el-col :span="8">
+        <el-card class="chart-card" shadow="never">
+          <template #header>
+            <div class="flex items-center">
+              <span class="text-base font-medium text-gray-600">钻井工作量情况</span>
+            </div>
+          </template>
+          <div ref="drillingWorkloadChartRef" class="h-[400px]"></div>
+        </el-card>
+    </el-col>
+    <el-col :span="8">
+      <el-card class="chart-card mt-1" shadow="never">
+        <template #header>
+          <div class="flex items-center">
+            <span class="text-base font-medium text-gray-600">修井工作量情况</span>
+          </div>
+        </template>
+        <div ref="repairWorkloadChartRef" class="h-[400px]"></div>
+      </el-card>
+    </el-col>
+  </el-row>
+
+
+</template>
+
+<script setup lang="ts" name="Index">
+import * as echarts from 'echarts/core'
+import { BarChart, GaugeChart, LineChart, PieChart } from 'echarts/charts' // 显式导入柱状图模块
+import {
+  GridComponent,
+  LegendComponent,
+  TitleComponent,
+  ToolboxComponent,
+  TooltipComponent
+} from 'echarts/components'
+import { LabelLayout, UniversalTransition } from 'echarts/features'
+import { CanvasRenderer } from 'echarts/renderers'
+import { useElementSize } from '@vueuse/core'
+import {
+  IotStatisticsDeviceMessageSummaryRespVO,
+  IotStatisticsSummaryRespVO
+} from '@/api/iot/statistics'
+import { formatDate } from '@/utils/formatTime'
+import { IotStatApi } from '@/api/pms/stat'
+import SummaryCard from "@/components/SummaryCard/index.vue";
+import {reactive, ref, onMounted, onBeforeUnmount, watch} from "vue";
+import {useUserStore} from "@/store/modules/user";
+
+// TODO @super:参考下 /Users/yunai/Java/yudao-ui-admin-vue3/src/views/mall/home/index.vue,拆一拆组件
+
+/** IoT 首页 */
+defineOptions({ name: 'IotRyStat' })
+
+// TODO @super:使用下 Echart 组件,参考 yudao-ui-admin-vue3/src/views/mall/home/components/TradeTrendCard.vue 等
+echarts.use([
+  TooltipComponent,
+  LegendComponent,
+  PieChart,
+  CanvasRenderer,
+  LabelLayout,
+  TitleComponent,
+  ToolboxComponent,
+  GridComponent,
+  LineChart,
+  UniversalTransition,
+  GaugeChart,
+  BarChart
+])
+
+const dateRange = ref<[Date, Date] | null>(null)
+const by = ref({
+  todo: undefined,
+  finished: undefined
+})
+const fill = ref({
+  filledCount: undefined,
+  unfilledCount: undefined
+})
+const inspectt = ref({
+  finished: 0,
+  todo: 0
+})
+const queryParams = reactive({
+  startTime: Date.now() - 7 * 24 * 60 * 60 * 1000, // 设置默认开始时间为 7 天前
+  endTime: Date.now() // 设置默认结束时间为当前时间
+})
+const backendData = ref([])
+const statusChartRef = ref() // 设备数量统计的图表
+const materialChartRef = ref() // 设备数量统计的图表
+const drillingWorkloadChartRef = ref()
+const repairWorkloadChartRef = ref()
+// 基础统计数据
+// TODO @super:初始为 -1,然后界面展示先是加载中?试试用 cursor 改哈
+const statsData = ref<IotStatisticsSummaryRespVO>({
+  productCategoryCount: 0,
+  productCount: 0,
+  deviceCount: 0,
+  deviceMessageCount: 0,
+  productCategoryTodayCount: 0,
+  productTodayCount: 0,
+  deviceTodayCount: 0,
+  deviceMessageTodayCount: 0,
+  deviceOnlineCount: 0,
+  deviceOfflineCount: 0,
+  deviceInactiveCount: 0,
+  productCategoryDeviceCounts: {}
+})
+
+const device = ref({
+  total: undefined,
+  today: undefined
+})
+const maintain = ref({
+  total: undefined,
+  today: undefined
+})
+const work = ref({
+  total: undefined,
+  today: undefined
+})
+const inspect = ref({
+  total: undefined,
+  today: undefined
+})
+
+const status = ref({
+  finished: 0,
+  todo: 0
+})
+const todayStatus = ref({
+  finished: 0,
+  todo: 0
+})
+const typeData = ref({})
+const materialData = ref({})
+const orderSevenData = ref({})
+const safe = ref()
+
+// 新增:修井完成情况数据
+const repairWellData = ref({
+  xAxis: ['小修10队', '小修8队', '小修9队'],
+  series: [
+    { name: '日累完成井数', data: [10, 15, 20] },
+    { name: '月累完成井数', data: [50, 60, 70] },
+    { name: '年累完成井数', data: [200, 220, 250] }
+  ]
+})
+
+// 新增:钻井完成情况数据
+const drillingWellData = ref({
+  xAxis: ['50010队', '四川宝石带压作业队'],
+  series: [
+    { name: '日累完成井数', data: [5, 8] },
+    { name: '月累完成井数', data: [40, 30] },
+    { name: '年累完成井数', data: [180,150 ] }
+  ]
+})
+const drillingWorkloadData = ref({
+  xAxis: ['SCP项目部', '伊拉克项目部', '陕西项目部'],
+  series: [
+    { name: '日累进尺', data: [150,100, 200] },
+    { name: '月累进尺', data: [1000, 1200, 1500] },
+    { name: '年累进尺', data: [2000,5000, 10000] }
+  ]
+})
+
+// 新增:修井工作量情况数据
+const repairWorkloadData = ref({
+  xAxis: ['SCP项目部', '伊拉克项目部', '陕西项目部'],
+  series: [
+    { name: '日累进尺', data: [120,80, 160] },
+    { name: '月累进尺', data: [1300,800, 1000] },
+    { name: '年累进尺', data: [4000, 5000, 7000] }
+  ]
+})
+const repairWellChartRef = ref()
+const drillingWellChartRef = ref()
+
+/** 获取统计数据 */
+const getStats =  () => {
+  initYwcbChart()
+  // 获取基础统计数据
+  IotStatApi.getDeviceCount().then((res) => {
+    device.value = res
+  })
+  IotStatApi.getMaintainCount().then((res) => {
+    maintain.value = res
+  })
+  IotStatApi.getMainWorkCount().then((res) => {
+    work.value = res
+  })
+  IotStatApi.getInspectCount().then((res) => {
+    inspect.value = res
+  })
+  IotStatApi.getMaintenanceStatus().then((res) => {
+    status.value = res
+    // initCharts()
+  })
+  IotStatApi.getMaintenanceTodayStatus().then((res) => {
+    todayStatus.value = res
+    initTopChart()
+  })
+
+  IotStatApi.getDeviceStatusCount().then((res) => {
+    typeData.value = res
+    initDeviceStatusCharts()
+  })
+  IotStatApi.getSafeCount().then((res) => {
+    safe.value = res
+  })
+  IotStatApi.getMaterial().then((res) => {
+    materialData.value = res
+    initMaterials()
+  })
+
+  IotStatApi.getOrderSeven().then((res) => {
+    orderSevenData.value = res
+    initQxChart();
+  })
+
+  IotStatApi.getMaintenanceStatus().then((res) => {
+    by.value = res
+    initMaintenanceChart()
+  })
+  const fillQueryParams = reactive({
+    startTime: Date.now() - 7 * 24 * 60 * 60 * 1000, // 设置默认开始时间为 7 天前
+    endTime: Date.now(), // 设置默认结束时间为当前时间
+    createTime: [],
+    deptId: null, // 选中的部门ID
+    status: null // 填写状态
+  })
+  IotStatApi.getInspectStatus(fillQueryParams).then((res) => {
+    inspectt.value = res
+  })
+  fillQueryParams.deptId = useUserStore().getUser.deptId
+  IotStatApi.getDeptStatistics(fillQueryParams).then((res) => {
+    fill.value = res.totalList[0] || []
+  })
+}
+
+
+const initDrillingWorkloadChart = () => {
+  if (!drillingWorkloadChartRef.value) return
+  const chart = echarts.init(drillingWorkloadChartRef.value)
+  const option = {
+    tooltip: {
+      trigger: 'axis',
+      axisPointer: {
+        type: 'shadow'
+      }
+    },
+    legend: {
+      data: drillingWorkloadData.value.series.map(item => item.name)
+    },
+    grid: {
+      left: '3%',
+      right: '4%',
+      bottom: '3%',
+      containLabel: true
+    },
+    xAxis: {
+      type: 'category',
+      data: drillingWorkloadData.value.xAxis
+    },
+    yAxis: {
+      type: 'value',
+      name: '进尺(米)'
+    },
+    series: drillingWorkloadData.value.series.map(item => ({
+      name: item.name,
+      type: 'bar',
+      data: item.data
+    }))
+  }
+  chart.setOption(option)
+}
+
+// 新增:初始化修井工作量情况图表
+const initRepairWorkloadChart = () => {
+  if (!repairWorkloadChartRef.value) return
+  const chart = echarts.init(repairWorkloadChartRef.value)
+  const option = {
+    tooltip: {
+      trigger: 'axis',
+      axisPointer: {
+        type: 'shadow'
+      }
+    },
+    legend: {
+      data: repairWorkloadData.value.series.map(item => item.name)
+    },
+    grid: {
+      left: '3%',
+      right: '4%',
+      bottom: '3%',
+      containLabel: true
+    },
+    xAxis: {
+      type: 'category',
+      data: repairWorkloadData.value.xAxis
+    },
+    yAxis: {
+      type: 'value',
+      name: '进尺(米)'
+    },
+    series: repairWorkloadData.value.series.map(item => ({
+      name: item.name,
+      type: 'bar',
+      data: item.data
+    }))
+  }
+  chart.setOption(option)
+}
+
+const initMaterials = () => {
+
+  echarts.init(materialChartRef.value).setOption({
+    tooltip: {
+      trigger: 'item'
+    },
+    legend: {
+      // top: '5%',
+      // right: '10%',
+      // align: 'left',
+      // orient: 'vertical',
+      // icon: 'circle'
+      orient: 'horizontal',  // 水平排列图例项
+      bottom: '0%',         // 放置在底部
+      icon: 'circle'
+    },
+    series: [
+      {
+        name: '',
+        type: 'pie',
+        radius: ['50%', '80%'],
+        avoidLabelOverlap: false,
+        center: ['50%', '44%'],
+        label: {
+          show: false,
+          position: 'outside'
+        },
+        emphasis: {
+          label: {
+            show: true,
+            fontSize: 15,
+            fontWeight: 'bold'
+          }
+        },
+        labelLine: {
+          show: false
+        },
+        data: materialData.value
+      }
+    ]
+  })
+}
+
+/** 初始化图表 */
+const initDeviceStatusCharts = () => {
+  // 设备数量统计
+  echarts.init(statusChartRef.value).setOption({
+    tooltip: {
+      trigger: 'item'
+    },
+    legend: {
+      orient: 'horizontal',  // 水平排列图例项
+      bottom: '0%',         // 放置在底部
+      icon: 'circle'
+    },
+    series: [
+      {
+        name: '',
+        type: 'pie',
+        radius: ['50%', '80%'],
+        avoidLabelOverlap: false,
+        center: ['50%', '46%'],
+        label: {
+          show: false,
+          position: 'outside'
+        },
+        emphasis: {
+          label: {
+            show: true,
+            fontSize: 15,
+            fontWeight: 'bold'
+          }
+        },
+        labelLine: {
+          show: false
+        },
+        data: typeData.value
+      }
+    ]
+  })
+}
+
+/** 初始化消息统计图表 */
+const chartContainer = ref(null)
+let chartInstance = null
+
+// 生成过去12个月份的标签 (格式: YYYY-MM)
+const generateMonthLabels = () => {
+  const months = []
+  const date = new Date()
+  for (let i = 11; i >= 0; i--) {
+    const tempDate = new Date(date.getFullYear(), date.getMonth() - i, 1)
+    const year = tempDate.getFullYear()
+    const month = String(tempDate.getMonth() + 1).padStart(2, '0')
+    months.push(`${year}-${month}`)
+  }
+  return months
+}
+
+// 模拟数据获取
+const fetchChartData = async () => {
+  // 模拟异步请求
+  return new Promise((resolve) => {
+    setTimeout(() => {
+      resolve({
+        months: ['空压机','增压机','提纯撬'],
+        repairs: [10, 30, 90 ]
+      })
+    }, 300)
+  })
+}
+
+// 初始化图表配置
+const initYwcbChart = async () => {
+  if (!chartContainer.value) return
+
+  // 获取数据
+  const { months, faults, repairs } = await fetchChartData()
+  // const months = ['空压机','增压机','提纯撬']
+  // ECharts配置
+  const option = {
+    tooltip: {
+      trigger: 'axis',
+      axisPointer: {
+        type: 'shadow'
+      },
+      formatter: (params) => {
+        return `${params[0].axisValue}<br/>
+                ${params[0].marker} ${params[0].seriesName}: ${params[0].value}`
+      }
+    },
+    legend: {
+      data: ['当日运维成本'],
+      top: 1
+    },
+    grid: {
+      left: '3%',
+      right: '4%',
+      bottom: '1%',
+      containLabel: true
+    },
+    xAxis: {
+      type: 'category',
+      data: months,
+      axisLabel: {
+        rotate: 45,
+        margin: 15
+      }
+    },
+    yAxis: {
+      type: 'value',
+      axisLabel: {
+        formatter: (value) => Math.floor(value).toString()
+      }
+    },
+    series: [
+      {
+        name: '当日运维成本',
+        type: 'bar',
+        itemStyle: {
+          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+            { offset: 0, color: '#f69606' },
+          ])
+        },
+        emphasis: {
+          focus: 'series'
+        },
+        data: repairs
+      }
+    ]
+  }
+
+  // 初始化图表
+  chartInstance = echarts.init(chartContainer.value)
+  chartInstance.setOption(option)
+
+  // 窗口缩放监听
+  window.addEventListener('resize', handleResize)
+  handleResize()
+}
+
+// 自适应调整
+const handleResize = () => {
+  chartInstance?.resize()
+}
+
+const topContainer = ref(null)
+let topInstance = null
+// 响应式容器尺寸
+const { width, height } = useElementSize(topContainer)
+// 处理数据(排序+限制5条)
+const processedData = () => {
+  const data = IotStatApi.getDeviceTypeCount()
+  backendData.value = data
+  return [...backendData.value].sort((a, b) => a.value - b.value)
+}
+
+const fetchTop = () => {
+  IotStatApi.getDeviceTypeCount().then((res) => {
+    backendData.value = res
+  })
+}
+// 初始化图表配置
+const getTopOption = () => {
+  // backendData.value = data
+  const data = backendData.value.sort((a, b) => a.value - b.value)
+  return {
+    tooltip: {
+      trigger: 'axis',
+      axisPointer: { type: 'shadow' },
+      formatter: (params) => {
+        const item = params[0]
+        return `${item.name}<br/>${item.marker} ${item.value.toLocaleString()}`
+      }
+    },
+    grid: {
+      height: '200px',
+      left: '6%',
+      right: '6%',
+      bottom: '18%',
+      containLabel: true
+    },
+    xAxis: {
+      type: 'value',
+      axisLabel: {
+        formatter: (value) => {
+          if (value >= 10000) return `${(value / 10000).toFixed(1)}万`
+          return value.toLocaleString()
+        }
+      }
+    },
+    yAxis: {
+      type: 'category',
+      data: data.map((item) => item.category),
+      axisTick: { show: false },
+      axisLabel: {}
+    },
+    series: [
+      {
+        type: 'bar',
+        data: data.map((item) => item.value),
+        itemStyle: {
+          color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
+            { offset: 0, color: '#83bff6' },
+            { offset: 0.7, color: '#188df0' },
+            { offset: 1, color: '#188df0' }
+          ]),
+          borderRadius: [0, 8, 8, 0]
+        },
+        label: {
+          show: true,
+          position: 'right',
+          formatter: '{@value}',
+          color: '#333',
+          fontWeight: 'bold'
+        },
+        emphasis: {
+          itemStyle: {
+            shadowBlur: 10,
+            shadowColor: 'rgba(0, 0, 0, 0.5)'
+          }
+        }
+      }
+    ]
+  }
+}
+
+// 初始化图表
+const initTopChart = async () => {
+  await IotStatApi.getDeviceTypeCount().then((res) => {
+    backendData.value = res
+  })
+  if (!topContainer.value) return
+  topInstance = echarts.init(topContainer.value)
+  updateTopChart()
+}
+
+// 更新图表
+const updateTopChart = () => {
+  if (!topInstance) return
+  topInstance.setOption(getTopOption())
+}
+
+// 自适应调整
+watch([width, height], () => {
+  topInstance?.resize()
+})
+
+// 监听数据变化
+watch(
+  backendData,
+  () => {
+    updateTopChart()
+  },
+  { deep: true }
+)
+
+const activeDom = ref(null)
+let activeInstance = null
+
+const activeData = ref([])
+const initActiveChart = async () => {
+  if (!activeDom.value) return
+  activeData.value = await IotStatApi.getDeptCount()
+  activeInstance = echarts.init(activeDom.value)
+
+  const option = {
+    tooltip: {
+      trigger: 'axis',
+      axisPointer: { type: 'shadow' },
+      formatter: (params) => `
+        ${params[0].name}<br/>
+        ${params[0].marker} 总人数: ${params[0].value}<br/>
+        ${params[1].marker} 活跃人数: ${params[1].value}
+      `
+    },
+    legend: {
+      data: ['总人数', '活跃人数'],
+      top: 30
+    },
+    grid: {
+      left: '3%',
+      right: '4%',
+      bottom: '3%',
+      containLabel: true
+    },
+    xAxis: {
+      type: 'category',
+      data: activeData.value.map((item) => item.department),
+      axisLabel: {
+        interval: 0,
+        rotate: 0
+      }
+    },
+    yAxis: {
+      type: 'value',
+      name: '人数',
+      splitLine: {
+        show: true,
+        lineStyle: { type: 'dashed' }
+      }
+    },
+    series: [
+      {
+        name: '总人数',
+        type: 'bar',
+        data: activeData.value.map((item) => item.total),
+        itemStyle: {
+          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+            { offset: 0, color: '#5470c6' },
+            { offset: 1, color: '#83bff6' }
+          ])
+        },
+        barWidth: 30
+      },
+      {
+        name: '活跃人数',
+        type: 'bar',
+        data: activeData.value.map((item) => item.active),
+        itemStyle: {
+          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+            { offset: 0, color: '#91cc75' },
+            { offset: 1, color: '#e6f4d2' }
+          ])
+        },
+        barWidth: 30
+      }
+    ]
+  }
+
+  activeInstance.setOption(option)
+}
+
+const qxRef = ref(null)
+let qxInstance = null
+
+// 生成近12个月份 (包含当年和去年)
+const generateMonths = () => {
+  const months = []
+  const date = new Date()
+  date.setMonth(date.getMonth() + 1, 1) // 从下个月开始倒推
+
+  for (let i = 0; i < 12; i++) {
+    date.setMonth(date.getMonth() - 1)
+    months.push(`${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}`)
+  }
+  return months.reverse()
+}
+
+const initQxChart = () => {
+  if (!qxRef.value) return
+  qxInstance = echarts.init(qxRef.value)
+  debugger
+  const option = {
+    tooltip: {
+      trigger: 'axis',
+      axisPointer: {
+        type: 'cross',
+        label: {
+          backgroundColor: '#6a7985'
+        }
+      }
+    },
+    legend: {
+      data: orderSevenData.value.series.map((item) => item.name),
+      top: 30
+    },
+    grid: {
+      left: '3%',
+      right: '4%',
+      bottom: '3%',
+      containLabel: true
+    },
+    xAxis: {
+      type: 'category',
+      boundaryGap: false,
+      data: orderSevenData.value.xAxis,
+      axisLabel: {
+        formatter: (value) => value.split('-').join('/') // 显示为 2023/01
+      }
+    },
+    yAxis: [
+      {
+        type: 'value',
+        axisLabel: {
+          formatter: '{value}'
+        },
+        position: 'left' // 左侧 Y 轴
+      },
+      {
+        type: 'value',
+        axisLabel: {
+          formatter: '{value}'
+        },
+        position: 'right', // 右侧 Y 轴
+        splitLine: {
+          show: false // 隐藏右侧 Y 轴的分割线
+        }
+      }
+    ],
+    series: orderSevenData.value.series.map((item, index) => {
+      // 假设前两条曲线使用左侧 Y 轴,后两条曲线使用右侧 Y 轴
+      const yAxisIndex = index < 2 ? 0 : 1;
+      return {
+        name: item.name,
+        type: 'line',
+        smooth: true,
+        symbol: 'circle',
+        symbolSize: 8,
+        itemStyle: {
+          color: ['#5470c6', '#f1d209', '#e14f0f', '#91cc75'][index]
+        },
+        areaStyle: {
+          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+            { offset: 0, color: 'rgba(84,112,198,0.4)' },
+            { offset: 1, color: 'rgba(84,112,198,0.1)' }
+          ])
+        },
+        data: item.data,
+        yAxisIndex: yAxisIndex // 指定使用的 Y 轴
+      }
+    })
+  }
+
+  qxInstance.setOption(option)
+}
+
+// 响应式调整
+const resizeQxChart = () => qxInstance?.resize()
+
+// 新增:初始化修井完成情况图表
+const initRepairWellChart = () => {
+  if (!repairWellChartRef.value) return
+  const option = {
+    tooltip: {
+      trigger: 'axis',
+      axisPointer: {
+        type: 'shadow'
+      }
+    },
+    legend: {
+      data: repairWellData.value.series.map(item => item.name),
+      top: 10
+    },
+    grid: {
+      left: '3%',
+      right: '4%',
+      bottom: '3%',
+      containLabel: true
+    },
+    xAxis: {
+      type: 'category',
+      data: repairWellData.value.xAxis
+    },
+    yAxis: {
+      type: 'value',
+      name: '完成井数(口)'
+    },
+    series: repairWellData.value.series.map(item => ({
+      name: item.name,
+      type: 'bar',
+      data: item.data
+    }))
+  }
+  const chart = echarts.init(repairWellChartRef.value)
+  chart.setOption(option)
+  window.addEventListener('resize', () => chart.resize())
+}
+
+// 新增:初始化钻井完成情况图表
+const initDrillingWellChart = () => {
+  if (!drillingWellChartRef.value) return
+  const option = {
+    tooltip: {
+      trigger: 'axis',
+      axisPointer: {
+        type: 'shadow'
+      }
+    },
+    legend: {
+      data: drillingWellData.value.series.map(item => item.name),
+      top: 10
+    },
+    grid: {
+      left: '3%',
+      right: '4%',
+      bottom: '3%',
+      containLabel: true
+    },
+    xAxis: {
+      type: 'category',
+      data: drillingWellData.value.xAxis
+    },
+    yAxis: {
+      type: 'value',
+      name: '完成井数(口)'
+    },
+    series: drillingWellData.value.series.map(item => ({
+      name: item.name,
+      type: 'bar',
+      data: item.data
+    }))
+  }
+  const chart = echarts.init(drillingWellChartRef.value)
+  chart.setOption(option)
+  window.addEventListener('resize', () => chart.resize())
+}
+
+/** 初始化 */
+onMounted(() => {
+  getStats()
+  // initChart()
+  // initTopChart()
+  // initActiveChart()
+  // initQxChart()
+  window.addEventListener('resize', resizeQxChart)
+  // fetchTop()
+  window.addEventListener('resize', () => topInstance?.resize())
+  initRepairWellChart()
+  initDrillingWellChart()
+  initDrillingWorkloadChart()
+  initRepairWorkloadChart()
+})
+
+onBeforeUnmount(() => {
+  chartInstance?.dispose()
+  window.removeEventListener('resize', () => chartInstance?.resize())
+  topInstance?.dispose()
+  window.removeEventListener('resize', handleResize)
+  qxInstance?.dispose()
+  window.removeEventListener('resize', resizeQxChart)
+  echarts.getInstanceByDom(repairWellChartRef.value)?.dispose()
+  window.removeEventListener('resize', () => echarts.getInstanceByDom(repairWellChartRef.value)?.resize())
+  echarts.getInstanceByDom(drillingWellChartRef.value)?.dispose()
+  window.removeEventListener('resize', () => echarts.getInstanceByDom(drillingWellChartRef.value)?.resize())
+})
+</script>
+
+<style lang="scss" scoped></style>

+ 921 - 0
src/views/pms/stat/test.vue

@@ -0,0 +1,921 @@
+<template>
+  <el-row :gutter="16" class="summary">
+    <!-- 原有的统计卡片部分保持不变 -->
+    <el-col v-loading="loading" :sm="3" :xs="12">
+      <SummaryCard
+        :value="device.total || 0"
+        icon="fa-solid:project-diagram"
+        icon-bg-color="text-blue-500"
+        icon-color="bg-blue-100"
+        title="设备数"
+      />
+    </el-col>
+    <el-col v-loading="loading" :sm="3" :xs="12">
+      <SummaryCard
+        :value="maintain.total || 0"
+        icon="fa-solid:list"
+        icon-bg-color="text-pink-500"
+        icon-color="bg-blue-100"
+        title="维修工单"
+      />
+    </el-col>
+    <el-col v-loading="loading" :sm="3" :xs="12">
+      <SummaryCard
+        :value="fill.unfilledCount || 0"
+        icon="fa-solid:times-circle"
+        icon-bg-color="text-purple-500"
+        icon-color="bg-purple-100"
+        title="运行未填写"
+      />
+    </el-col>
+    <el-col v-loading="loading" :sm="3" :xs="12">
+      <SummaryCard
+        :value="fill.filledCount || 0"
+        icon="fa-solid:award"
+        icon-bg-color="text-purple-500"
+        icon-color="bg-purple-100"
+        title="运行已填写"
+      />
+    </el-col>
+    <el-col v-loading="loading" :sm="3" :xs="12">
+      <SummaryCard
+        :value="by.todo || 0"
+        icon="fa-solid:times-circle"
+        icon-bg-color="text-green-500"
+        icon-color="bg-green-100"
+        title="未执行保养"
+      />
+    </el-col>
+    <el-col v-loading="loading" :sm="3" :xs="12">
+      <SummaryCard
+        :value="by.finished || 0"
+        icon="fa-solid:award"
+        icon-bg-color="text-green-500"
+        icon-color="bg-green-100"
+        title="已执行保养"
+      />
+    </el-col>
+    <el-col v-loading="loading" :sm="3" :xs="12">
+      <SummaryCard
+        :value="inspectt.todo || 0"
+        icon="fa-solid:times-circle"
+        icon-bg-color="text-yellow-500"
+        icon-color="bg-yellow-100"
+        title="待填写巡检"
+      />
+    </el-col>
+    <el-col v-loading="loading" :sm="3" :xs="12">
+      <SummaryCard
+        :value="inspectt.finished || 0"
+        icon="fa-solid:award"
+        icon-bg-color="text-yellow-500"
+        icon-color="bg-yellow-100"
+        title="已填写巡检"
+      />
+    </el-col>
+    <!-- 其他统计卡片... -->
+  </el-row>
+  <!-- 第二行:图表行 -->
+  <el-row :gutter="16" class="mb-4 mt-3">
+    <el-col :span="6">
+      <el-card class="chart-card" shadow="never">
+        <template #header>
+          <div class="flex items-center">
+            <span class="text-base font-medium text-gray-600">设备状态统计</span>
+          </div>
+        </template>
+        <div ref="statusChartRef" class="h-[320px]"></div>
+      </el-card>
+    </el-col>
+    <el-col :span="7">
+      <el-card class="chart-card" shadow="never">
+        <template #header>
+          <div class="flex items-center">
+            <span class="text-base font-medium text-gray-600">设备类别TOP5数量</span>
+          </div>
+        </template>
+        <div ref="topContainer" class="h-[320px]"></div>
+      </el-card>
+    </el-col>
+    <el-col :span="11">
+      <el-card class="chart-card" shadow="never">
+        <template #header>
+          <div class="flex items-center justify-between">
+            <span class="text-base font-medium text-gray-600">工单数量情况</span>
+          </div>
+        </template>
+        <div ref="qxRef" class="h-[320px]"></div>
+      </el-card>
+    </el-col>
+  </el-row>
+
+  <!-- 新增:修井完成情况和钻井完成情况以及新的柱状图 -->
+  <el-row :gutter="16" class="mb-4">
+    <el-col :span="8">
+      <div class="flex flex-col justify-between">
+        <el-card class="chart-card" shadow="never">
+          <template #header>
+            <div class="flex items-center">
+              <span class="text-base font-medium text-gray-600">修井完成情况</span>
+            </div>
+          </template>
+          <div ref="repairWellChartRef" class="h-[160px]"></div>
+        </el-card>
+        <el-card class="chart-card mt-1" shadow="never">
+          <template #header>
+            <div class="flex items-center">
+              <span class="text-base font-medium text-gray-600">钻井完成情况</span>
+            </div>
+          </template>
+          <div ref="drillingWellChartRef" class="h-[160px]"></div>
+        </el-card>
+      </div>
+    </el-col>
+    <el-col :span="8">
+      <div class="flex flex-col justify-between">
+        <el-card class="chart-card" shadow="never">
+          <template #header>
+            <div class="flex items-center">
+              <span class="text-base font-medium text-gray-600">钻井工作量情况(进尺(米))</span>
+            </div>
+          </template>
+          <div ref="drillingWorkloadChartRef" class="h-[360px]"></div>
+        </el-card>
+        <el-card class="chart-card mt-1" shadow="never">
+          <template #header>
+            <div class="flex items-center">
+              <span class="text-base font-medium text-gray-600">修井工作量情况(进尺(米))</span>
+            </div>
+          </template>
+          <div ref="repairWorkloadChartRef" class="h-[360px]"></div>
+        </el-card>
+      </div>
+    </el-col>
+  </el-row>
+</template>
+
+<script setup lang="ts" name="Index">
+import * as echarts from 'echarts/core'
+import { BarChart, GaugeChart, LineChart, PieChart } from 'echarts/charts' // 显式导入柱状图模块
+import {
+  GridComponent,
+  LegendComponent,
+  TitleComponent,
+  ToolboxComponent,
+  TooltipComponent
+} from 'echarts/components'
+import { LabelLayout, UniversalTransition } from 'echarts/features'
+import { CanvasRenderer } from 'echarts/renderers'
+import { useElementSize } from '@vueuse/core'
+import {
+  IotStatisticsDeviceMessageSummaryRespVO,
+  IotStatisticsSummaryRespVO
+} from '@/api/iot/statistics'
+import { formatDate } from '@/utils/formatTime'
+import { IotStatApi } from '@/api/pms/stat'
+import SummaryCard from "@/components/SummaryCard/index.vue";
+import {reactive, ref, onMounted, onBeforeUnmount, watch} from "vue";
+import {useUserStore} from "@/store/modules/user";
+
+// TODO @super:参考下 /Users/yunai/Java/yudao-ui-admin-vue3/src/views/mall/home/index.vue,拆一拆组件
+
+/** IoT 首页 */
+defineOptions({ name: 'IotRyStat' })
+
+// TODO @super:使用下 Echart 组件,参考 yudao-ui-admin-vue3/src/views/mall/home/components/TradeTrendCard.vue 等
+echarts.use([
+  TooltipComponent,
+  LegendComponent,
+  PieChart,
+  CanvasRenderer,
+  LabelLayout,
+  TitleComponent,
+  ToolboxComponent,
+  GridComponent,
+  LineChart,
+  UniversalTransition,
+  GaugeChart,
+  BarChart
+])
+
+const dateRange = ref<[Date, Date] | null>(null)
+const by = ref({
+  todo: undefined,
+  finished: undefined
+})
+const fill = ref({
+  filledCount: undefined,
+  unfilledCount: undefined
+})
+const inspectt = ref({
+  finished: 0,
+  todo: 0
+})
+const queryParams = reactive({
+  startTime: Date.now() - 7 * 24 * 60 * 60 * 1000, // 设置默认开始时间为 7 天前
+  endTime: Date.now() // 设置默认结束时间为当前时间
+})
+const backendData = ref([])
+const statusChartRef = ref() // 设备数量统计的图表
+const materialChartRef = ref() // 设备数量统计的图表
+// 基础统计数据
+// TODO @super:初始为 -1,然后界面展示先是加载中?试试用 cursor 改哈
+const statsData = ref<IotStatisticsSummaryRespVO>({
+  productCategoryCount: 0,
+  productCount: 0,
+  deviceCount: 0,
+  deviceMessageCount: 0,
+  productCategoryTodayCount: 0,
+  productTodayCount: 0,
+  deviceTodayCount: 0,
+  deviceMessageTodayCount: 0,
+  deviceOnlineCount: 0,
+  deviceOfflineCount: 0,
+  deviceInactiveCount: 0,
+  productCategoryDeviceCounts: {}
+})
+
+const device = ref({
+  total: undefined,
+  today: undefined
+})
+const maintain = ref({
+  total: undefined,
+  today: undefined
+})
+const work = ref({
+  total: undefined,
+  today: undefined
+})
+const inspect = ref({
+  total: undefined,
+  today: undefined
+})
+
+const status = ref({
+  finished: 0,
+  todo: 0
+})
+const todayStatus = ref({
+  finished: 0,
+  todo: 0
+})
+const typeData = ref({})
+const materialData = ref({})
+const orderSevenData = ref({})
+const safe = ref()
+
+// 新增:修井完成情况数据
+const repairWellData = ref({
+  xAxis: ['小修10队', '小修8队', '小修9队'],
+  series: [
+    { name: '日累完成井数', data: [10, 15, 20] },
+    { name: '月累完成井数', data: [50, 60, 70] },
+    { name: '年累完成井数', data: [200, 220, 250] }
+  ]
+})
+
+// 新增:钻井完成情况数据
+const drillingWellData = ref({
+  xAxis: ['50010队', '四川宝石带压作业队'],
+  series: [
+    { name: '日累完成井数', data: [5, 8] },
+    { name: '月累完成井数', data: [30, 40] },
+    { name: '年累完成井数', data: [150, 180] }
+  ]
+})
+
+// 新增:钻井工作量情况数据
+const drillingWorkloadData = ref({
+  xAxis: ['SCP项目部', '伊拉克项目部', '陕西项目部'],
+  series: [
+    { name: '日累进尺', data: [100, 150, 200] },
+    { name: '月累进尺', data: [1000, 1200, 1500] },
+    { name: '年累进尺', data: [5000, 6000, 8000] }
+  ]
+})
+
+// 新增:修井工作量情况数据
+const repairWorkloadData = ref({
+  xAxis: ['SCP项目部', '伊拉克项目部', '陕西项目部'],
+  series: [
+    { name: '日累进尺', data: [80, 120, 160] },
+    { name: '月累进尺', data: [800, 1000, 1300] },
+    { name: '年累进尺', data: [4000, 5000, 7000] }
+  ]
+})
+
+const repairWellChartRef = ref()
+const drillingWellChartRef = ref()
+const drillingWorkloadChartRef = ref()
+const repairWorkloadChartRef = ref()
+
+/** 获取统计数据 */
+const getStats =  () => {
+  initYwcbChart()
+  // 获取基础统计数据
+  IotStatApi.getDeviceCount().then((res) => {
+    device.value = res
+  })
+  IotStatApi.getMaintainCount().then((res) => {
+    maintain.value = res
+  })
+  IotStatApi.getMainWorkCount().then((res) => {
+    work.value = res
+  })
+  IotStatApi.getInspectCount().then((res) => {
+    inspect.value = res
+  })
+  IotStatApi.getMaintenanceStatus().then((res) => {
+    status.value = res
+    // initCharts()
+  })
+  IotStatApi.getMaintenanceTodayStatus().then((res) => {
+    todayStatus.value = res
+    initTopChart()
+  })
+
+  IotStatApi.getDeviceStatusCount().then((res) => {
+    typeData.value = res
+    initDeviceStatusCharts()
+  })
+  IotStatApi.getSafeCount().then((res) => {
+    safe.value = res
+  })
+  IotStatApi.getMaterial().then((res) => {
+    materialData.value = res
+    initMaterials()
+  })
+
+  IotStatApi.getOrderSeven().then((res) => {
+    orderSevenData.value = res
+    initQxChart();
+  })
+
+  IotStatApi.getMaintenanceStatus().then((res) => {
+    by.value = res
+    initMaintenanceChart()
+  })
+  const fillQueryParams = reactive({
+    startTime: Date.now() - 7 * 24 * 60 * 60 * 1000, // 设置默认开始时间为 7 天前
+    endTime: Date.now(), // 设置默认结束时间为当前时间
+    createTime: [],
+    deptId: null, // 选中的部门ID
+    status: null // 填写状态
+  })
+  IotStatApi.getInspectStatus(fillQueryParams).then((res) => {
+    inspectt.value = res
+  })
+  fillQueryParams.deptId = useUserStore().getUser.deptId
+  IotStatApi.getDeptStatistics(fillQueryParams).then((res) => {
+    fill.value = res.totalList[0] || []
+  })
+}
+
+const initMaterials = () => {
+
+  echarts.init(materialChartRef.value).setOption({
+    tooltip: {
+      trigger: 'item'
+    },
+    legend: {
+      // top: '5%',
+      // right: '10%',
+      // align: 'left',
+      // orient: 'vertical',
+      // icon: 'circle'
+      orient: 'horizontal',  // 水平排列图例项
+      bottom: '0%',         // 放置在底部
+      icon: 'circle'
+    },
+    series: [
+      {
+        name: '',
+        type: 'pie',
+        radius: ['50%', '80%'],
+        avoidLabelOverlap: false,
+        center: ['50%', '44%'],
+        label: {
+          show: false,
+          position: 'outside'
+        },
+        emphasis: {
+          label: {
+            show: true,
+            fontSize: 15,
+            fontWeight: 'bold'
+          }
+        },
+        labelLine: {
+          show: false
+        },
+        data: materialData.value
+      }
+    ]
+  })
+}
+
+/** 初始化图表 */
+const initDeviceStatusCharts = () => {
+  // 设备数量统计
+  echarts.init(statusChartRef.value).setOption({
+    tooltip: {
+      trigger: 'item'
+    },
+    legend: {
+      orient: 'horizontal',  // 水平排列图例项
+      bottom: '0%',         // 放置在底部
+      icon: 'circle'
+    },
+    series: [
+      {
+        name: '',
+        type: 'pie',
+        radius: ['50%', '80%'],
+        avoidLabelOverlap: false,
+        center: ['50%', '46%'],
+        label: {
+          show: false,
+          position: 'outside'
+        },
+        emphasis: {
+          label: {
+            show: true,
+            fontSize: 15,
+            fontWeight: 'bold'
+          }
+        },
+        labelLine: {
+          show: false
+        },
+        data: typeData.value
+      }
+    ]
+  })
+}
+
+/** 初始化消息统计图表 */
+const chartContainer = ref(null)
+let chartInstance = null
+
+// 生成过去12个月份的标签 (格式: YYYY-MM)
+const generateMonthLabels = () => {
+  const months = []
+  const date = new Date()
+  for (let i = 11; i >= 0; i--) {
+    const tempDate = new Date(date.getFullYear(), date.getMonth() - i, 1)
+    const year = tempDate.getFullYear()
+    const month = String(tempDate.getMonth() + 1).padStart(2, '0')
+    months.push(`${year}-${month}`)
+  }
+  return months
+}
+
+// 模拟数据获取
+const fetchChartData = async () => {
+  // 模拟异步请求
+  return new Promise((resolve) => {
+    setTimeout(() => {
+      resolve({
+        months: ['空压机','增压机','提纯撬'],
+        repairs: [10, 30, 90 ]
+      })
+    }, 300)
+  })
+}
+
+// 初始化图表配置
+const initYwcbChart = async () => {
+  if (!chartContainer.value) return
+
+  // 获取数据
+  const { months, faults, repairs } = await fetchChartData()
+  // const months = ['空压机','增压机','提纯撬']
+  // ECharts配置
+  const option = {
+    tooltip: {
+      trigger: 'axis',
+      axisPointer: {
+        type: 'shadow'
+      },
+      formatter: (params) => {
+        return `${params[0].axisValue}<br/>
+                ${params[0].marker} ${params[0].seriesName}: ${params[0].value}`
+      }
+    },
+    legend: {
+      data: ['当日运维成本'],
+      top: 1
+    },
+    grid: {
+      left: '3%',
+      right: '4%',
+      bottom: '1%',
+      containLabel: true
+    },
+    xAxis: {
+      type: 'category',
+      data: months,
+      axisLabel: {
+        rotate: 45,
+        margin: 15
+      }
+    },
+    yAxis: {
+      type: 'value',
+      axisLabel: {
+        formatter: (value) => Math.floor(value).toString()
+      }
+    },
+    series: [
+      {
+        name: '当日运维成本',
+        type: 'bar',
+        itemStyle: {
+          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+            { offset: 0, color: '#f69606' },
+          ])
+        },
+        emphasis: {
+          focus: 'series'
+        },
+        data: repairs
+      }
+    ]
+  }
+
+  // 初始化图表
+  chartInstance = echarts.init(chartContainer.value)
+  chartInstance.setOption(option)
+
+  // 窗口缩放监听
+  window.addEventListener('resize', handleResize)
+  handleResize()
+}
+
+// 自适应调整
+const handleResize = () => {
+  chartInstance?.resize()
+}
+
+const topContainer = ref(null)
+let topInstance = null
+// 响应式容器尺寸
+const { width, height } = useElementSize(topContainer)
+// 处理数据(排序+限制5条)
+const processedData = () => {
+  const data = IotStatApi.getDeviceTypeCount()
+  backendData.value = data
+  return [...backendData.value].sort((a, b) => a.value - b.value)
+}
+
+const fetchTop = () => {
+  IotStatApi.getDeviceTypeCount().then((res) => {
+    backendData.value = res
+  })
+}
+// 初始化图表配置
+const getTopOption = () => {
+  // backendData.value = data
+  const data = backendData.value.sort((a, b) => a.value - b.value)
+  return {
+    tooltip: {
+      trigger: 'axis',
+      axisPointer: { type: 'shadow' },
+      formatter: (params) => {
+        const item = params[0]
+        return `${item.name}<br/>${item.marker} ${item.value.toLocaleString()}`
+      }
+    },
+    grid: {
+      height: '200px',
+      left: '6%',
+      right: '6%',
+      bottom: '18%',
+      containLabel: true
+    },
+    xAxis: {
+      type: 'value',
+      axisLabel: {
+        formatter: (value) => {
+          if (value >= 10000) return `${(value / 10000).toFixed(1)}万`
+          return value.toLocaleString()
+        }
+      }
+    },
+    yAxis: {
+      type: 'category',
+      data: data.map((item) => item.category),
+      axisTick: { show: false },
+      axisLabel: {}
+    },
+    series: [
+      {
+        type: 'bar',
+        data: data.map((item) => item.value),
+        itemStyle: {
+          color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
+            { offset: 0, color: '#83bff6' },
+            { offset: 0.7, color: '#188df0' },
+            { offset: 1, color: '#188df0' }
+          ]),
+          borderRadius: [0, 8, 8, 0]
+        },
+        label: {
+          show: true,
+          position: 'right',
+          formatter: '{@value}',
+          color: '#333',
+          fontWeight: 'bold'
+        },
+        emphasis: {
+          itemStyle: {
+            shadowBlur: 10,
+            shadowColor: 'rgba(0, 0, 0, 0.5)'
+          }
+        }
+      }
+    ]
+  }
+}
+
+// 初始化图表
+const initTopChart = async () => {
+  await IotStatApi.getDeviceTypeCount().then((res) => {
+    backendData.value = res
+  })
+  if (!topContainer.value) return
+  topInstance = echarts.init(topContainer.value)
+  updateTopChart()
+}
+
+// 更新图表
+const updateTopChart = () => {
+  if (!topInstance) return
+  topInstance.setOption(getTopOption())
+}
+
+// 自适应调整
+watch([width, height], () => {
+  topInstance?.resize()
+})
+
+// 监听数据变化
+watch(
+  backendData,
+  () => {
+    updateTopChart()
+  },
+  { deep: true }
+)
+
+const activeDom = ref(null)
+let activeInstance = null
+
+const activeData = ref([])
+const initActiveChart = async () => {
+  if (!activeDom.value) return
+  activeData.value = await IotStatApi.getDeptCount()
+  activeInstance = echarts.init(activeDom.value)
+
+  const option = {
+    tooltip: {
+      trigger: 'axis',
+      axisPointer: { type: 'shadow' },
+      formatter: (params) => `
+        ${params[0].name}<br/>
+        ${params[0].marker} 总人数: ${params[0].value}<br/>
+        ${params[1].marker} 活跃人数: ${params[1].value}
+      `
+    },
+    legend: {
+      data: ['总人数', '活跃人数'],
+      top: 30
+    },
+    grid: {
+      left: '3%',
+      right: '4%',
+      bottom: '3%',
+      containLabel: true
+    },
+    xAxis: {
+      type: 'category',
+      data: activeData.value.map((item) => item.department),
+      axisLabel: {
+        interval: 0,
+        rotate: 0
+      }
+    },
+    yAxis: {
+      type: 'value',
+      name: '人数',
+      splitLine: {
+        show: true,
+        lineStyle: { type: 'dashed' }
+      }
+    },
+    series: [
+      {
+        name: '总人数',
+        type: 'bar',
+        data: activeData.value.map((item) => item.total),
+        itemStyle: {
+          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+            { offset: 0, color: '#5470c6' },
+            { offset: 1, color: '#83bff6' }
+          ])
+        },
+        barWidth: 30
+      },
+      {
+        name: '活跃人数',
+        type: 'bar',
+        data: activeData.value.map((item) => item.active),
+        itemStyle: {
+          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+            { offset: 0, color: '#91cc75' },
+            { offset: 1, color: '#e6f4d2' }
+          ])
+        },
+        barWidth: 30
+      }
+    ]
+  }
+
+  activeInstance.setOption(option)
+}
+
+const qxRef = ref(null)
+let qxInstance = null
+
+// 生成近12个月份 (包含当年和去年)
+const generateMonths = () => {
+  const months = []
+  const date = new Date()
+  date.setMonth(date.getMonth() + 1, 1) // 从下个月开始倒推
+
+  for (let i = 0; i < 12; i++) {
+    date.setMonth(date.getMonth() - 1)
+    months.push(`${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}`)
+  }
+  return months.reverse()
+}
+
+const initQxChart = () => {
+  if (!qxRef.value) return
+  qxInstance = echarts.init(qxRef.value)
+  debugger
+  const option = {
+    tooltip: {
+      trigger: 'axis',
+      axisPointer: {
+        type: 'cross',
+        label: {
+          backgroundColor: '#6a7985'
+        }
+      }
+    },
+    legend: {
+      data: orderSevenData.value.series.map((item) => item.name),
+      top: 30
+    },
+    grid: {
+      left: '3%',
+      right: '4%',
+      bottom: '3%',
+      containLabel: true
+    },
+    xAxis: {
+      type: 'category',
+      boundaryGap: false,
+      data: orderSevenData.value.xAxis,
+      axisLabel: {
+        formatter: (value) => value.split('-').join('/') // 显示为 2023/01
+      }
+    },
+    yAxis: [
+      {
+        type: 'value',
+        axisLabel: {
+          formatter: '{value}'
+        },
+        position: 'left' // 左侧 Y 轴
+      },
+      {
+        type: 'value',
+        axisLabel: {
+          formatter: '{value}'
+        },
+        position: 'right', // 右侧 Y 轴
+        splitLine: {
+          show: false // 隐藏右侧 Y 轴的分割线
+        }
+      }
+    ],
+    series: orderSevenData.value.series.map((item, index) => {
+      // 假设前两条曲线使用左侧 Y 轴,后两条曲线使用右侧 Y 轴
+      const yAxisIndex = index < 2 ? 0 : 1;
+      return {
+        name: item.name,
+        type: 'line',
+        smooth: true,
+        symbol: 'circle',
+        symbolSize: 8,
+        itemStyle: {
+          color: ['#5470c6', '#f1d209', '#e14f0f', '#91cc75'][index]
+        },
+        areaStyle: {
+          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+            { offset: 0, color: 'rgba(84,112,198,0.4)' },
+            { offset: 1, color: 'rgba(84,112,198,0.1)' }
+          ])
+        },
+        yAxisIndex: yAxisIndex
+      }
+    })
+  }
+
+  qxInstance.setOption(option)
+}
+
+// 新增:初始化钻井工作量情况图表
+const initDrillingWorkloadChart = () => {
+  if (!drillingWorkloadChartRef.value) return
+  const chart = echarts.init(drillingWorkloadChartRef.value)
+  const option = {
+    tooltip: {
+      trigger: 'axis',
+      axisPointer: {
+        type: 'shadow'
+      }
+    },
+    legend: {
+      data: drillingWorkloadData.value.series.map(item => item.name)
+    },
+    grid: {
+      left: '3%',
+      right: '4%',
+      bottom: '3%',
+      containLabel: true
+    },
+    xAxis: {
+      type: 'category',
+      data: drillingWorkloadData.value.xAxis
+    },
+    yAxis: {
+      type: 'value',
+      name: '进尺(米)'
+    },
+    series: drillingWorkloadData.value.series.map(item => ({
+      name: item.name,
+      type: 'bar',
+      data: item.data
+    }))
+  }
+  chart.setOption(option)
+}
+
+// 新增:初始化修井工作量情况图表
+const initRepairWorkloadChart = () => {
+  if (!repairWorkloadChartRef.value) return
+  const chart = echarts.init(repairWorkloadChartRef.value)
+  const option = {
+    tooltip: {
+      trigger: 'axis',
+      axisPointer: {
+        type: 'shadow'
+      }
+    },
+    legend: {
+      data: repairWorkloadData.value.series.map(item => item.name)
+    },
+    grid: {
+      left: '3%',
+      right: '4%',
+      bottom: '3%',
+      containLabel: true
+    },
+    xAxis: {
+      type: 'category',
+      data: repairWorkloadData.value.xAxis
+    },
+    yAxis: {
+      type: 'value',
+      name: '进尺(米)'
+    },
+    series: repairWorkloadData.value.series.map(item => ({
+      name: item.name,
+      type: 'bar',
+      data: item.data
+    }))
+  }
+  chart.setOption(option)
+}
+
+onMounted(() => {
+  getStats()
+  initDrillingWorkloadChart()
+  initRepairWorkloadChart()
+})
+
+</script>