From a1d7e81859f554f3a53680cc35f0f49bf1f77098 Mon Sep 17 00:00:00 2001
From: wwf <1971391498@qq.com>
Date: 星期四, 14 五月 2026 14:37:02 +0800
Subject: [PATCH] 导入项目
---
src/views/iot/home/components/MessageTrendCard.vue | 227 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 227 insertions(+), 0 deletions(-)
diff --git a/src/views/iot/home/components/MessageTrendCard.vue b/src/views/iot/home/components/MessageTrendCard.vue
new file mode 100644
index 0000000..1d2d4c5
--- /dev/null
+++ b/src/views/iot/home/components/MessageTrendCard.vue
@@ -0,0 +1,227 @@
+<template>
+ <el-card class="chart-card" shadow="never" :loading="loading">
+ <template #header>
+ <div class="flex items-center justify-between">
+ <span class="text-base font-medium text-gray-600">娑堟伅閲忕粺璁�</span>
+ <div class="flex flex-wrap items-center gap-4">
+ <el-form-item label="鏃堕棿鑼冨洿" class="!mb-0">
+ <el-date-picker
+ v-model="queryParams.times"
+ :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
+ :shortcuts="defaultShortcuts"
+ class="!w-240px"
+ end-placeholder="缁撴潫鏃ユ湡"
+ start-placeholder="寮�濮嬫棩鏈�"
+ type="daterange"
+ value-format="YYYY-MM-DD HH:mm:ss"
+ @change="handleQuery"
+ />
+ </el-form-item>
+ <el-form-item label="鏃堕棿闂撮殧" class="!mb-0">
+ <el-select
+ v-model="queryParams.interval"
+ class="!w-120px"
+ placeholder="闂撮殧绫诲瀷"
+ @change="handleQuery"
+ >
+ <el-option
+ v-for="dict in getIntDictOptions(DICT_TYPE.DATE_INTERVAL)"
+ :key="dict.value"
+ :label="dict.label"
+ :value="dict.value"
+ />
+ </el-select>
+ </el-form-item>
+ </div>
+ </div>
+ </template>
+ <div v-if="loading && !hasData" class="h-[300px] flex justify-center items-center">
+ <el-empty description="鍔犺浇涓�..." />
+ </div>
+ <div v-else-if="!hasData" class="h-[300px] flex justify-center items-center">
+ <el-empty description="鏆傛棤鏁版嵁" />
+ </div>
+ <div v-else ref="messageChartRef" class="h-[300px]"></div>
+ </el-card>
+</template>
+
+<script lang="ts" setup>
+import * as echarts from 'echarts/core'
+import { LineChart } from 'echarts/charts'
+import { CanvasRenderer } from 'echarts/renderers'
+import { GridComponent, LegendComponent, TooltipComponent } from 'echarts/components'
+import { UniversalTransition } from 'echarts/features'
+import {
+ StatisticsApi,
+ IotStatisticsDeviceMessageSummaryByDateRespVO,
+ IotStatisticsDeviceMessageReqVO
+} from '@/api/iot/statistics'
+import { formatDate, beginOfDay, endOfDay, defaultShortcuts } from '@/utils/formatTime'
+import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
+
+/** 娑堟伅瓒嬪娍缁熻鍗$墖 */
+defineOptions({ name: 'MessageTrendCard' })
+
+const messageChartRef = ref()
+const loading = ref(false)
+const messageData = ref<IotStatisticsDeviceMessageSummaryByDateRespVO[]>([])
+
+const queryParams = reactive<IotStatisticsDeviceMessageReqVO>({
+ interval: 1, // DAY, 鏃�
+ times: [
+ // 榛樿鏄剧ず鏈�杩戜竴鍛ㄧ殑鏁版嵁
+ formatDate(beginOfDay(new Date(new Date().getTime() - 3600 * 1000 * 24 * 7))),
+ formatDate(endOfDay(new Date(new Date().getTime() - 3600 * 1000 * 24)))
+ ]
+}) // 鏌ヨ鍙傛暟
+
+// 鏄惁鏈夋暟鎹�
+const hasData = computed(() => {
+ return messageData.value && messageData.value.length > 0
+})
+
+// 澶勭悊鏌ヨ鎿嶄綔
+const handleQuery = () => {
+ fetchMessageData()
+}
+
+// 鑾峰彇娑堟伅缁熻鏁版嵁
+const fetchMessageData = async () => {
+ loading.value = true
+ try {
+ messageData.value = await StatisticsApi.getDeviceMessageSummaryByDate(queryParams)
+
+ // 浣跨敤 nextTick 纭繚鏁版嵁鏇存柊鍚庨噸鏂版覆鏌撳浘琛�
+ await nextTick()
+ initChart()
+ } catch (error) {
+ console.error('鑾峰彇娑堟伅缁熻鏁版嵁澶辫触:', error)
+ messageData.value = []
+ } finally {
+ loading.value = false
+ }
+}
+
+// 鍒濆鍖栧浘琛�
+const initChart = () => {
+ // 妫�鏌ユ槸鍚︽湁鏁版嵁鍙互缁樺埗
+ if (!hasData.value) return
+ // 纭繚 DOM 鍏冪礌瀛樺湪涓斿凡娓叉煋
+ if (!messageChartRef.value) {
+ console.warn('鍥捐〃 DOM 鍏冪礌涓嶅瓨鍦�')
+ return
+ }
+
+ // 閰嶇疆鍥捐〃
+ echarts.use([
+ LineChart,
+ CanvasRenderer,
+ GridComponent,
+ LegendComponent,
+ TooltipComponent,
+ UniversalTransition
+ ])
+ try {
+ const chart = echarts.init(messageChartRef.value)
+ chart.setOption({
+ tooltip: {
+ trigger: 'axis',
+ backgroundColor: 'rgba(255, 255, 255, 0.9)',
+ borderColor: '#E5E7EB',
+ textStyle: {
+ color: '#374151'
+ }
+ },
+ legend: {
+ data: ['涓婅娑堟伅閲�', '涓嬭娑堟伅閲�'],
+ textStyle: {
+ color: '#374151',
+ fontWeight: 500
+ }
+ },
+ grid: {
+ left: '3%',
+ right: '4%',
+ bottom: '3%',
+ containLabel: true
+ },
+ xAxis: {
+ type: 'category',
+ boundaryGap: false,
+ data: messageData.value.map((item) => item.time),
+ axisLine: {
+ lineStyle: {
+ color: '#E5E7EB'
+ }
+ },
+ axisLabel: {
+ color: '#6B7280'
+ }
+ },
+ yAxis: {
+ type: 'value',
+ axisLine: {
+ lineStyle: {
+ color: '#E5E7EB'
+ }
+ },
+ axisLabel: {
+ color: '#6B7280'
+ },
+ splitLine: {
+ lineStyle: {
+ color: '#F3F4F6'
+ }
+ }
+ },
+ series: [
+ {
+ name: '涓婅娑堟伅閲�',
+ type: 'line',
+ smooth: true,
+ data: messageData.value.map((item) => item.upstreamCount),
+ itemStyle: {
+ color: '#3B82F6'
+ },
+ lineStyle: {
+ width: 2
+ },
+ areaStyle: {
+ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+ { offset: 0, color: 'rgba(59, 130, 246, 0.2)' },
+ { offset: 1, color: 'rgba(59, 130, 246, 0)' }
+ ])
+ }
+ },
+ {
+ name: '涓嬭娑堟伅閲�',
+ type: 'line',
+ smooth: true,
+ data: messageData.value.map((item) => item.downstreamCount),
+ itemStyle: {
+ color: '#10B981'
+ },
+ lineStyle: {
+ width: 2
+ },
+ areaStyle: {
+ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+ { offset: 0, color: 'rgba(16, 185, 129, 0.2)' },
+ { offset: 1, color: 'rgba(16, 185, 129, 0)' }
+ ])
+ }
+ }
+ ]
+ })
+ return chart
+ } catch (error) {
+ console.error('鍒濆鍖栧浘琛ㄥけ璐�:', error)
+ return null
+ }
+}
+
+/** 缁勪欢鎸傝浇鏃跺垵濮嬪寲 */
+onMounted(() => {
+ fetchMessageData()
+})
+</script>
--
Gitblit v1.8.0