From f0c8e8aaf9f41a7ab0f02a23cd7c5de1bffb9e71 Mon Sep 17 00:00:00 2001
From: gongchunyi <deslre0381@gmail.com>
Date: 星期三, 20 五月 2026 18:32:47 +0800
Subject: [PATCH] feat: 决策分析数据获取新增轮询

---
 src/views/reportAnalysis/qualityAnalysis/components/center-bottom.vue   |    8 +-
 src/views/reportAnalysis/financialAnalysis/components/left-bottom.vue   |    7 +
 src/views/reportAnalysis/financialAnalysis/components/center-top.vue    |    9 +-
 src/views/reportAnalysis/qualityAnalysis/components/right-top.vue       |    8 +-
 src/views/reportAnalysis/qualityAnalysis/components/left-top.vue        |    8 ++
 src/views/reportAnalysis/qualityAnalysis/components/center-center.vue   |    8 +-
 src/views/reportAnalysis/qualityAnalysis/components/right-bottom.vue    |    5 +
 src/hooks/usePolling.js                                                 |  121 ++++++++++++++++++++++++++++++
 src/views/reportAnalysis/financialAnalysis/components/center-center.vue |    8 +-
 src/views/reportAnalysis/financialAnalysis/components/center-bottom.vue |    8 +-
 src/views/reportAnalysis/financialAnalysis/components/left-top.vue      |    8 +-
 src/views/reportAnalysis/qualityAnalysis/components/center-top.vue      |    8 +-
 12 files changed, 170 insertions(+), 36 deletions(-)

diff --git a/src/hooks/usePolling.js b/src/hooks/usePolling.js
new file mode 100644
index 0000000..d90d341
--- /dev/null
+++ b/src/hooks/usePolling.js
@@ -0,0 +1,121 @@
+import { onMounted, onBeforeUnmount } from 'vue'
+
+/**
+ * 鏁版嵁杞 composable
+ * @param {Function} fetchFn - 鏁版嵁鑾峰彇鍑芥暟
+ * @param {Object} options - 閰嶇疆閫夐」
+ * @param {number} options.interval - 杞闂撮殧锛堟绉掞級锛岄粯璁� 60000锛�60绉掞級
+ * @param {boolean} options.immediate - 鏄惁绔嬪嵆鎵ц涓�娆★紝榛樿 true
+ * @returns {Object} { start, stop, isPolling }
+ */
+export function usePolling(fetchFn, options = {}) {
+  const {
+    interval = 60000,
+    immediate = true
+  } = options
+
+  let pollingTimer = null
+  const isPolling = { value: false }
+
+  const start = () => {
+    if (pollingTimer) return
+    
+    if (immediate) {
+      fetchFn()
+    }
+    
+    pollingTimer = setInterval(() => {
+      fetchFn()
+    }, interval)
+    
+    isPolling.value = true
+  }
+
+  const stop = () => {
+    if (pollingTimer) {
+      clearInterval(pollingTimer)
+      pollingTimer = null
+    }
+    isPolling.value = false
+  }
+
+  // 缁勪欢鎸傝浇鏃惰嚜鍔ㄥ惎鍔�
+  onMounted(() => {
+    start()
+  })
+
+  // 缁勪欢鍗歌浇鏃惰嚜鍔ㄥ仠姝�
+  onBeforeUnmount(() => {
+    stop()
+  })
+
+  return {
+    start,
+    stop,
+    isPolling
+  }
+}
+
+/**
+ * 澶氬嚱鏁拌疆璇� composable
+ * @param {Function[]} fetchFns - 鏁版嵁鑾峰彇鍑芥暟鏁扮粍
+ * @param {Object} options - 閰嶇疆閫夐」
+ * @param {number} options.interval - 杞闂撮殧锛堟绉掞級锛岄粯璁� 60000锛�60绉掞級
+ * @param {boolean} options.immediate - 鏄惁绔嬪嵆鎵ц涓�娆★紝榛樿 true
+ * @returns {Object} { start, stop, isPolling }
+ */
+export function usePollingMultiple(fetchFns, options = {}) {
+  const {
+    interval = 60000,
+    immediate = true
+  } = options
+
+  let pollingTimer = null
+  const isPolling = { value: false }
+
+  const fetchAll = () => {
+    fetchFns.forEach(fn => {
+      if (typeof fn === 'function') {
+        fn()
+      }
+    })
+  }
+
+  const start = () => {
+    if (pollingTimer) return
+    
+    if (immediate) {
+      fetchAll()
+    }
+    
+    pollingTimer = setInterval(() => {
+      fetchAll()
+    }, interval)
+    
+    isPolling.value = true
+  }
+
+  const stop = () => {
+    if (pollingTimer) {
+      clearInterval(pollingTimer)
+      pollingTimer = null
+    }
+    isPolling.value = false
+  }
+
+  // 缁勪欢鎸傝浇鏃惰嚜鍔ㄥ惎鍔�
+  onMounted(() => {
+    start()
+  })
+
+  // 缁勪欢鍗歌浇鏃惰嚜鍔ㄥ仠姝�
+  onBeforeUnmount(() => {
+    stop()
+  })
+
+  return {
+    start,
+    stop,
+    isPolling
+  }
+}
diff --git a/src/views/reportAnalysis/financialAnalysis/components/center-bottom.vue b/src/views/reportAnalysis/financialAnalysis/components/center-bottom.vue
index 20a612d..a26e712 100644
--- a/src/views/reportAnalysis/financialAnalysis/components/center-bottom.vue
+++ b/src/views/reportAnalysis/financialAnalysis/components/center-bottom.vue
@@ -19,10 +19,11 @@
 </template>
 
 <script setup>
-import { ref, onMounted } from 'vue'
+import { ref } from 'vue'
 import Echarts from '@/components/Echarts/echarts.vue'
 import PanelHeader from './PanelHeader.vue'
 import { profitTrendAnalysis } from '@/api/viewIndex.js'
+import { usePolling } from '@/hooks/usePolling.js'
 
 const chartStyle = { width: '100%', height: '150%' }
 const grid = { left: '3%', right: '4%', bottom: '3%', top: '4%', containLabel: true }
@@ -85,9 +86,8 @@
     })
 }
 
-onMounted(() => {
-  fetchData()
-})
+// 鍚姩杞锛屾瘡鍒嗛挓鍒锋柊涓�娆℃暟鎹�
+usePolling(fetchData)
 </script>
 
 <style scoped>
diff --git a/src/views/reportAnalysis/financialAnalysis/components/center-center.vue b/src/views/reportAnalysis/financialAnalysis/components/center-center.vue
index 7d32ebd..d800e86 100644
--- a/src/views/reportAnalysis/financialAnalysis/components/center-center.vue
+++ b/src/views/reportAnalysis/financialAnalysis/components/center-center.vue
@@ -27,10 +27,11 @@
 </template>
 
 <script setup>
-import { ref, onMounted } from 'vue'
+import { ref } from 'vue'
 import * as echarts from 'echarts'
 import Echarts from '@/components/Echarts/echarts.vue'
 import { incomeExpenseAnalysis } from '@/api/viewIndex.js'
+import { usePolling } from '@/hooks/usePolling.js'
 
 const chartStyle = { width: '100%', height: '100%' }
 const grid = {
@@ -144,9 +145,8 @@
     })
 }
 
-onMounted(() => {
-  fetchData()
-})
+// 鍚姩杞锛屾瘡鍒嗛挓鍒锋柊涓�娆℃暟鎹�
+usePolling(fetchData)
 </script>
 
 <style scoped>
diff --git a/src/views/reportAnalysis/financialAnalysis/components/center-top.vue b/src/views/reportAnalysis/financialAnalysis/components/center-top.vue
index 41fc941..fee5035 100644
--- a/src/views/reportAnalysis/financialAnalysis/components/center-top.vue
+++ b/src/views/reportAnalysis/financialAnalysis/components/center-top.vue
@@ -96,8 +96,9 @@
 </template>
 
 <script setup>
-import { onMounted, ref } from 'vue'
+import { ref } from 'vue'
 import { getMonthlyIncome, getMonthlyExpenditure } from '@/api/viewIndex'
+import { usePollingMultiple } from '@/hooks/usePolling.js'
 
 const income = ref({
   amount: 0,
@@ -179,10 +180,8 @@
   return Number(metric.trend) >= 0 ? '鈫�' : '鈫�'
 }
 
-onMounted(() => {
-  fetchMonthlyIncome()
-  fetchMonthlyExpenditure()
-})
+// 鍚姩杞锛屾瘡鍒嗛挓鍒锋柊涓�娆℃暟鎹�
+usePollingMultiple([fetchMonthlyIncome, fetchMonthlyExpenditure])
 </script>
 
 <style scoped>
diff --git a/src/views/reportAnalysis/financialAnalysis/components/left-bottom.vue b/src/views/reportAnalysis/financialAnalysis/components/left-bottom.vue
index 3fe95d6..4dd9a13 100644
--- a/src/views/reportAnalysis/financialAnalysis/components/left-bottom.vue
+++ b/src/views/reportAnalysis/financialAnalysis/components/left-bottom.vue
@@ -29,12 +29,13 @@
 </template>
 
 <script setup>
-import { ref, onMounted, onBeforeUnmount, computed } from 'vue'
+import { ref, onBeforeUnmount, computed } from 'vue'
 import Echarts from '@/components/Echarts/echarts.vue'
 import PanelHeader from './PanelHeader.vue'
 import ProductTypeSwitch from './ProductTypeSwitch.vue'
 import { expenseCompositionAnalysis } from '@/api/viewIndex.js'
 import { useChartBackground } from '@/hooks/useChartBackground.js'
+import { usePolling } from '@/hooks/usePolling.js'
 
 const pieWrapperRef = ref(null)
 const pieBackgroundRef = ref(null)
@@ -231,13 +232,15 @@
 }
 
 onMounted(() => {
-  fetchData()
   initBackground()
 })
 
 onBeforeUnmount(() => {
   cleanupBackground()
 })
+
+// 鍚姩杞锛屾瘡鍒嗛挓鍒锋柊涓�娆℃暟鎹�
+usePolling(fetchData)
 </script>
 
 <style scoped>
diff --git a/src/views/reportAnalysis/financialAnalysis/components/left-top.vue b/src/views/reportAnalysis/financialAnalysis/components/left-top.vue
index c735dba..1966576 100644
--- a/src/views/reportAnalysis/financialAnalysis/components/left-top.vue
+++ b/src/views/reportAnalysis/financialAnalysis/components/left-top.vue
@@ -19,10 +19,11 @@
 </template>
 
 <script setup>
-import { ref, onMounted } from 'vue'
+import { ref } from 'vue'
 import { getAmountHalfYear } from '@/api/viewIndex.js'
 import PanelHeader from './PanelHeader.vue'
 import Echarts from '@/components/Echarts/echarts.vue'
+import { usePolling } from '@/hooks/usePolling.js'
 
 const chartStyle = {
   width: '100%',
@@ -113,9 +114,8 @@
     })
 }
 
-onMounted(() => {
-  fetchData()
-})
+// 鍚姩杞锛屾瘡鍒嗛挓鍒锋柊涓�娆℃暟鎹�
+usePolling(fetchData)
 </script>
 
 <style scoped>
diff --git a/src/views/reportAnalysis/qualityAnalysis/components/center-bottom.vue b/src/views/reportAnalysis/qualityAnalysis/components/center-bottom.vue
index fe875d0..5673fa3 100644
--- a/src/views/reportAnalysis/qualityAnalysis/components/center-bottom.vue
+++ b/src/views/reportAnalysis/qualityAnalysis/components/center-bottom.vue
@@ -24,10 +24,11 @@
 </template>
 
 <script setup>
-import { ref, onMounted } from 'vue'
+import { ref } from 'vue'
 import { completedInspectionCount } from '@/api/viewIndex.js'
 import PanelHeader from './PanelHeader.vue'
 import Echarts from '@/components/Echarts/echarts.vue'
+import { usePolling } from '@/hooks/usePolling.js'
 
 const chartStyle = {
   width: '100%',
@@ -154,9 +155,8 @@
   fetchData()
 }
 
-onMounted(() => {
-  fetchData()
-})
+// 鍚姩杞锛屾瘡鍒嗛挓鍒锋柊涓�娆℃暟鎹�
+usePolling(fetchData)
 </script>
 
 <style scoped>
diff --git a/src/views/reportAnalysis/qualityAnalysis/components/center-center.vue b/src/views/reportAnalysis/qualityAnalysis/components/center-center.vue
index 8d28f7a..46506a0 100644
--- a/src/views/reportAnalysis/qualityAnalysis/components/center-center.vue
+++ b/src/views/reportAnalysis/qualityAnalysis/components/center-center.vue
@@ -25,9 +25,10 @@
 </template>
 
 <script setup>
-import { computed, getCurrentInstance, ref, onMounted } from 'vue'
+import { computed, getCurrentInstance, ref } from 'vue'
 import Echarts from '@/components/Echarts/echarts.vue'
 import { nonComplianceWarning } from '@/api/viewIndex.js'
+import { usePolling } from '@/hooks/usePolling.js'
 
 const { proxy } = getCurrentInstance() || {}
 
@@ -161,9 +162,8 @@
   // 鍏堟寜鎴浘鍋氶潤鎬佲�滆繎7澶┾�濓紝鍚庣画鏈夌湡瀹炵瓫閫夐渶姹傚啀鎺ュ叆
 }
 
-onMounted(() => {
-  fetchWarnings()
-})
+// 鍚姩杞锛屾瘡鍒嗛挓鍒锋柊涓�娆℃暟鎹�
+usePolling(fetchWarnings)
 </script>
 
 <style scoped>
diff --git a/src/views/reportAnalysis/qualityAnalysis/components/center-top.vue b/src/views/reportAnalysis/qualityAnalysis/components/center-top.vue
index 8e46770..4ae0653 100644
--- a/src/views/reportAnalysis/qualityAnalysis/components/center-top.vue
+++ b/src/views/reportAnalysis/qualityAnalysis/components/center-top.vue
@@ -20,8 +20,9 @@
 </template>
 
 <script setup>
-import { ref, onMounted } from 'vue'
+import { ref } from 'vue'
 import { qualityInspectionCount } from '@/api/viewIndex.js'
+import { usePolling } from '@/hooks/usePolling.js'
 
 const statItems = ref([])
 
@@ -62,9 +63,8 @@
     })
 }
 
-onMounted(() => {
-  fetchData()
-})
+// 鍚姩杞锛屾瘡鍒嗛挓鍒锋柊涓�娆℃暟鎹�
+usePolling(fetchData)
 </script>
 
 <style scoped>
diff --git a/src/views/reportAnalysis/qualityAnalysis/components/left-top.vue b/src/views/reportAnalysis/qualityAnalysis/components/left-top.vue
index cce4894..9e9f5f5 100644
--- a/src/views/reportAnalysis/qualityAnalysis/components/left-top.vue
+++ b/src/views/reportAnalysis/qualityAnalysis/components/left-top.vue
@@ -51,6 +51,7 @@
 import PanelHeader from './PanelHeader.vue'
 import DateTypeSwitch from './DateTypeSwitch.vue'
 import { rawMaterialDetection, processDetection, factoryDetection } from '@/api/viewIndex.js'
+import { usePolling } from '@/hooks/usePolling.js'
 
 const QUALIFIED_COLOR = '#4EE4FF'
 const UNQUALIFIED_COLOR = '#3378FF'
@@ -218,6 +219,13 @@
     fetchSectionData(section)
   })
 })
+
+// 鍚姩杞锛屾瘡鍒嗛挓鍒锋柊涓�娆℃暟鎹�
+usePolling(() => {
+  sections.forEach((section) => {
+    fetchSectionData(section)
+  })
+})
 </script>
 
 <style scoped lang="scss">
diff --git a/src/views/reportAnalysis/qualityAnalysis/components/right-bottom.vue b/src/views/reportAnalysis/qualityAnalysis/components/right-bottom.vue
index f4b0a0c..d210d13 100644
--- a/src/views/reportAnalysis/qualityAnalysis/components/right-bottom.vue
+++ b/src/views/reportAnalysis/qualityAnalysis/components/right-bottom.vue
@@ -17,6 +17,7 @@
 import PanelHeader from './PanelHeader.vue'
 import { unqualifiedProductProcessingAnalysis } from '@/api/viewIndex.js'
 import { useChartBackground } from '@/hooks/useChartBackground.js'
+import { usePolling } from '@/hooks/usePolling.js'
 
 const pieWrapperRef = ref(null)
 const pieBackgroundRef = ref(null)
@@ -149,13 +150,15 @@
 }
 
 onMounted(() => {
-  loadData()
   initBackground()
 })
 
 onBeforeUnmount(() => {
   cleanupBackground()
 })
+
+// 鍚姩杞锛屾瘡鍒嗛挓鍒锋柊涓�娆℃暟鎹�
+usePolling(loadData)
 </script>
 
 <style scoped>
diff --git a/src/views/reportAnalysis/qualityAnalysis/components/right-top.vue b/src/views/reportAnalysis/qualityAnalysis/components/right-top.vue
index 7120c3a..29686fd 100644
--- a/src/views/reportAnalysis/qualityAnalysis/components/right-top.vue
+++ b/src/views/reportAnalysis/qualityAnalysis/components/right-top.vue
@@ -24,9 +24,10 @@
 </template>
 
 <script setup>
-import { ref, onMounted } from 'vue'
+import { ref } from 'vue'
 import { unqualifiedProductRanking } from '@/api/viewIndex.js'
 import PanelHeader from './PanelHeader.vue'
+import { usePolling } from '@/hooks/usePolling.js'
 
 const panelList = ref([])
 
@@ -60,9 +61,8 @@
     })
 }
 
-onMounted(() => {
-  fetchData()
-})
+// 鍚姩杞锛屾瘡鍒嗛挓鍒锋柊涓�娆℃暟鎹�
+usePolling(fetchData)
 </script>
 
 <style scoped>

--
Gitblit v1.9.3