|
@@ -0,0 +1,616 @@
|
|
|
+<template>
|
|
|
+ <div class="flex flex-col">
|
|
|
+ <el-row :gutter="16" class="summary">
|
|
|
+ <!-- 原有的统计卡片部分保持不变 -->
|
|
|
+ <el-col v-loading="loading" :sm="3" :xs="12">
|
|
|
+ <SummaryCard
|
|
|
+ :value="summary?.userCount || 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="summary?.userCount || 0"
|
|
|
+ icon="fa-solid:list"
|
|
|
+ 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="summary?.rechargeUserCount || 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="fenToYuan(summary?.rechargePrice || 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="fenToYuan(summary?.expensePrice || 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="fenToYuan(summary?.expensePrice || 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="fenToYuan(summary?.expensePrice || 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="fenToYuan(summary?.expensePrice || 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="7">
|
|
|
+ <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-[290px]"></div>
|
|
|
+ </el-card>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="17">
|
|
|
+ <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-[290px]"></div>
|
|
|
+ </el-card>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ <el-row :gutter="16" class="mb-4">
|
|
|
+ <!-- 备件更换情况部分保持不变 -->
|
|
|
+ <el-col :span="8">
|
|
|
+ <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 class="flex justify-between mb-2">
|
|
|
+ <el-card class="stat-card " >
|
|
|
+ <div class="flex flex-row justify-evenly">
|
|
|
+ <div>
|
|
|
+ <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>
|
|
|
+ <span class="text-lg font-bold">{{ totalMaterialCount }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-card>
|
|
|
+ <el-card class="stat-card">
|
|
|
+ <div class="flex flex-row justify-evenly">
|
|
|
+ <div>
|
|
|
+ <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>
|
|
|
+ <span class="text-lg font-bold">{{ totalMaterialCost }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-card>
|
|
|
+ </div>
|
|
|
+ <div ref="sparePartRef" class="h-[330px]"></div>
|
|
|
+ </el-card>
|
|
|
+ </el-col>
|
|
|
+ <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">
|
|
|
+ <span class="text-base font-medium text-gray-600">保养情况</span>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <div class="flex mr-3">
|
|
|
+ <div ref="maintenanceChartRef" class="h-[157px] w-2/5"></div>
|
|
|
+ <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="20" color="gray"/>
|
|
|
+ <p>总工单数</p>
|
|
|
+ <span>{{ totalMaintenanceOrders }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="flex flex-col items-center">
|
|
|
+ <Icon icon="fa-solid:check-circle" size="20" color="green"/>
|
|
|
+ <p>已执行工单数</p>
|
|
|
+ <span>{{ completedMaintenanceOrders }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="flex flex-col items-center">
|
|
|
+ <Icon icon="fa-solid:hourglass-half" size="20" color="orange"/>
|
|
|
+ <p>待执行工单数 </p>
|
|
|
+ <span>{{ pendingMaintenanceOrders }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-card>
|
|
|
+ <el-card class="chart-card mt-2" shadow="never">
|
|
|
+ <template #header>
|
|
|
+ <div class="flex items-center justify-between">
|
|
|
+ <span class="text-base font-medium text-gray-600">巡检情况</span>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <div class="flex mr-3">
|
|
|
+ <div ref="maintenanceChartRef1" class="h-[157px] w-2/5"></div>
|
|
|
+ <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="20" color="gray"/>
|
|
|
+ <p>总工单数</p>
|
|
|
+ <span>{{ totalMaintenanceOrders }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="flex flex-col items-center">
|
|
|
+ <Icon icon="fa-solid:check-circle" size="20" color="green"/>
|
|
|
+ <p>已执行工单数</p>
|
|
|
+ <span>{{ completedMaintenanceOrders }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="flex flex-col items-center">
|
|
|
+ <Icon icon="fa-solid:hourglass-half" size="20" color="orange"/>
|
|
|
+ <p>待执行工单数</p>
|
|
|
+ <span>{{ pendingMaintenanceOrders }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-card>
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="24">
|
|
|
+ <el-card class="chart-card mt-1" shadow="never">
|
|
|
+ <template #header>
|
|
|
+ <div class="flex items-center justify-between">
|
|
|
+ <span class="text-base font-medium text-gray-600">维保日历</span>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <el-calendar v-model="currentDate">
|
|
|
+ <template #dateCell="{ data }">
|
|
|
+ <div class="calendar-cell">
|
|
|
+ <span>{{ data.day.split('-').pop() }}</span>
|
|
|
+ <div :ref="el => calendarPieRefs[data.day] = el" class="calendar-pie"></div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-calendar>
|
|
|
+ </el-card>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+<script lang="ts" setup>
|
|
|
+import { MemberSummaryRespVO } from '@/api/mall/statistics/member'
|
|
|
+import SummaryCard from '@/components/SummaryCard/index.vue'
|
|
|
+import { fenToYuan } from '@/utils'
|
|
|
+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 { ref, onMounted, computed, watch, nextTick } from 'vue';
|
|
|
+import { ElCalendar } from 'element-plus';
|
|
|
+
|
|
|
+/** 会员统计 */
|
|
|
+defineOptions({ name: 'IotRdStat' })
|
|
|
+
|
|
|
+echarts.use([
|
|
|
+ TooltipComponent,
|
|
|
+ LegendComponent,
|
|
|
+ PieChart,
|
|
|
+ CanvasRenderer,
|
|
|
+ LabelLayout,
|
|
|
+ TitleComponent,
|
|
|
+ ToolboxComponent,
|
|
|
+ GridComponent,
|
|
|
+ LineChart,
|
|
|
+ UniversalTransition,
|
|
|
+ GaugeChart,
|
|
|
+ BarChart
|
|
|
+])
|
|
|
+
|
|
|
+const loading = ref(true) // 加载中
|
|
|
+const summary = ref<MemberSummaryRespVO>() // 会员统计数据
|
|
|
+const statusChartRef = ref() // 设备数量统计的图表
|
|
|
+const qxRef = ref(null)
|
|
|
+let qxInstance = null
|
|
|
+const sparePartRef = ref(null)
|
|
|
+let sparePartInstance = null
|
|
|
+const maintenanceChartRef = ref(null)
|
|
|
+let maintenanceChartInstance = null
|
|
|
+const inspectionChartRef = ref(null)
|
|
|
+let inspectionChartInstance = null
|
|
|
+const maintenanceChartRef1 = ref(null)
|
|
|
+let maintenanceChartInstance1 = null
|
|
|
+
|
|
|
+const typeData = ref({})
|
|
|
+const orderSevenData = ref({})
|
|
|
+const sparePartData = ref({
|
|
|
+ xAxis: ['扳手', '水杯', '皮带', '螺丝'],
|
|
|
+ series: [
|
|
|
+ {
|
|
|
+ name: '数量',
|
|
|
+ type: 'bar',
|
|
|
+ data: [10, 20, 15, 25],
|
|
|
+ yAxisIndex: 0
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '金额',
|
|
|
+ type: 'line',
|
|
|
+ data: [100, 200, 150, 250],
|
|
|
+ yAxisIndex: 1
|
|
|
+ }
|
|
|
+ ]
|
|
|
+})
|
|
|
+
|
|
|
+// 模拟保养工单数据
|
|
|
+const totalMaintenanceOrders = ref(100)
|
|
|
+const completedMaintenanceOrders = ref(80)
|
|
|
+const pendingMaintenanceOrders = ref(20)
|
|
|
+
|
|
|
+// 模拟巡检工单数据
|
|
|
+const totalInspectionOrders = ref(80)
|
|
|
+const completedInspectionOrders = ref(60)
|
|
|
+const pendingInspectionOrders = ref(20)
|
|
|
+
|
|
|
+// 计算物料消耗数量及费用
|
|
|
+const totalMaterialCount = computed(() => {
|
|
|
+ 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 currentDate = ref(new Date())
|
|
|
+const calendarPieRefs = ref({})
|
|
|
+const maintenanceData = ref({
|
|
|
+ // 示例数据,需要根据实际情况替换
|
|
|
+ '2024-01-01': { maintenance: 5, inspection: 3 },
|
|
|
+ '2024-01-02': { maintenance: 2, inspection: 4 },
|
|
|
+ // ... 其他日期数据
|
|
|
+})
|
|
|
+
|
|
|
+const getStats = () => {
|
|
|
+ IotStatApi.getDeviceStatusCount().then((res) => {
|
|
|
+ typeData.value = res
|
|
|
+ initDeviceStatusCharts()
|
|
|
+ })
|
|
|
+ IotStatApi.getOrderSeven().then((res) => {
|
|
|
+ orderSevenData.value = res
|
|
|
+ initQxChart()
|
|
|
+ })
|
|
|
+ initSparePartChart()
|
|
|
+ initMaintenanceChart()
|
|
|
+ initInspectionChart()
|
|
|
+ nextTick(() => {
|
|
|
+ initCalendarPieCharts()
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+const initQxChart = () => {
|
|
|
+ if (!qxRef.value) return
|
|
|
+ qxInstance = echarts.init(qxRef.value)
|
|
|
+ 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) => {
|
|
|
+ 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 initSparePartChart = () => {
|
|
|
+ if (!sparePartRef.value) return
|
|
|
+ sparePartInstance = echarts.init(sparePartRef.value)
|
|
|
+ const option = {
|
|
|
+ tooltip: {
|
|
|
+ trigger: 'axis',
|
|
|
+ axisPointer: {
|
|
|
+ type: 'cross',
|
|
|
+ crossStyle: {
|
|
|
+ color: '#999'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ legend: {
|
|
|
+ data: ['数量', '金额']
|
|
|
+ },
|
|
|
+ grid: {
|
|
|
+ left: '3%',
|
|
|
+ right: '4%',
|
|
|
+ bottom: '3%',
|
|
|
+ containLabel: true
|
|
|
+ },
|
|
|
+ xAxis: {
|
|
|
+ type: 'category',
|
|
|
+ data: sparePartData.value.xAxis
|
|
|
+ },
|
|
|
+ yAxis: [
|
|
|
+ {
|
|
|
+ type: 'value',
|
|
|
+ name: '数量',
|
|
|
+ position: 'left',
|
|
|
+ axisLabel: {
|
|
|
+ formatter: '{value}'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ type: 'value',
|
|
|
+ name: '金额',
|
|
|
+ position: 'right',
|
|
|
+ axisLabel: {
|
|
|
+ formatter: '{value}'
|
|
|
+ },
|
|
|
+ splitLine: {
|
|
|
+ show: false
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ series: sparePartData.value.series.map((item, index) => ({
|
|
|
+ name: item.name,
|
|
|
+ type: item.type,
|
|
|
+ data: item.data,
|
|
|
+ yAxisIndex: item.yAxisIndex,
|
|
|
+ itemStyle: {
|
|
|
+ color: ['#6084fb', '#5aef13'][index]
|
|
|
+ },
|
|
|
+ }))
|
|
|
+ }
|
|
|
+
|
|
|
+ sparePartInstance.setOption(option)
|
|
|
+}
|
|
|
+
|
|
|
+const initMaintenanceChart = () => {
|
|
|
+ if (!maintenanceChartRef.value) return
|
|
|
+ maintenanceChartInstance = echarts.init(maintenanceChartRef.value)
|
|
|
+ const completionRate = (completedMaintenanceOrders.value / totalMaintenanceOrders.value) * 100
|
|
|
+ const option = {
|
|
|
+ series: [
|
|
|
+ {
|
|
|
+ type: 'pie',
|
|
|
+ radius: ['40%', '70%'],
|
|
|
+ data: [
|
|
|
+ { value: completionRate, name: '完成率' },
|
|
|
+ { value: 100 - completionRate, name: '未完成率' }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ maintenanceChartInstance.setOption(option)
|
|
|
+}
|
|
|
+
|
|
|
+const initInspectionChart = () => {
|
|
|
+ if (!inspectionChartRef.value) return
|
|
|
+ inspectionChartInstance = echarts.init(inspectionChartRef.value)
|
|
|
+ const completionRate = (completedInspectionOrders.value / totalInspectionOrders.value) * 100
|
|
|
+ const option = {
|
|
|
+ series: [
|
|
|
+ {
|
|
|
+ type: 'pie',
|
|
|
+ radius: ['50%', '80%'],
|
|
|
+ data: [
|
|
|
+ { value: completionRate, name: '完成率' },
|
|
|
+ { value: 100 - completionRate, name: '未完成率' }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ inspectionChartInstance.setOption(option)
|
|
|
+}
|
|
|
+
|
|
|
+/** 初始化图表 */
|
|
|
+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%', '44%'],
|
|
|
+ label: {
|
|
|
+ show: false,
|
|
|
+ position: 'outside'
|
|
|
+ },
|
|
|
+ emphasis: {
|
|
|
+ label: {
|
|
|
+ show: true,
|
|
|
+ fontSize: 15,
|
|
|
+ fontWeight: 'bold'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ labelLine: {
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ data: typeData.value
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+const initCalendarPieCharts = () => {
|
|
|
+ Object.entries(calendarPieRefs.value).forEach(([date, el]) => {
|
|
|
+ if (el) {
|
|
|
+ const { maintenance = 0, inspection = 0 } = maintenanceData.value[date] || {}
|
|
|
+ const total = maintenance + inspection
|
|
|
+ const option = {
|
|
|
+ series: [
|
|
|
+ {
|
|
|
+ type: 'pie',
|
|
|
+ radius: ['30%', '60%'],
|
|
|
+ data: [
|
|
|
+ { value: maintenance, name: '保养' },
|
|
|
+ { value: inspection, name: '巡检' }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ echarts.init(el).setOption(option)
|
|
|
+ }
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+watch(currentDate, () => {
|
|
|
+ nextTick(() => {
|
|
|
+ initCalendarPieCharts()
|
|
|
+ })
|
|
|
+})
|
|
|
+
|
|
|
+/** 初始化 **/
|
|
|
+onMounted(async () => {
|
|
|
+ loading.value = true
|
|
|
+ await Promise.all([getStats()])
|
|
|
+ loading.value = false
|
|
|
+})
|
|
|
+</script>
|
|
|
+<style lang="scss" scoped>
|
|
|
+.summary {
|
|
|
+ .el-col {
|
|
|
+ margin-bottom: 1rem;
|
|
|
+ }
|
|
|
+}
|
|
|
+.stat-card {
|
|
|
+ width: 48%;
|
|
|
+}
|
|
|
+.calendar-cell {
|
|
|
+ position: relative;
|
|
|
+ height: 100%;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+}
|
|
|
+.calendar-pie {
|
|
|
+ width: 100%;
|
|
|
+ height: 80px;
|
|
|
+}
|
|
|
+</style>
|