From ccc970e575ef3f3e5c67af8da210263f4ac549f9 Mon Sep 17 00:00:00 2001
From: feiyu02 <risaku@163.com>
Date: 星期五, 10 四月 2026 16:44:55 +0800
Subject: [PATCH] 2026.4.10

---
 src/views/inspection/MonitorControl.vue |  551 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 550 insertions(+), 1 deletions(-)

diff --git a/src/views/inspection/MonitorControl.vue b/src/views/inspection/MonitorControl.vue
index 50ede86..be00dde 100644
--- a/src/views/inspection/MonitorControl.vue
+++ b/src/views/inspection/MonitorControl.vue
@@ -1 +1,550 @@
-<template>s</template>
+<template>
+  <!-- 鎬昏鐜板満宸℃煡鍗$墖 -->
+  <el-card class="mb-4">
+    <!-- <template #header>
+      <div class="card-header">
+        <span>鐜板満宸℃煡鎬昏</span>
+        <el-form :model="params" label-position="left" label-width="70px">
+          <FYOptionTime
+            :initValue="false"
+            type="daterange"
+            v-model:value="params.timeRange"
+            style="width: 300px"
+            :shortcuts="shortcuts"
+          ></FYOptionTime>
+          <FYOptionLocation
+            :allOption="false"
+            :level="3"
+            :checkStrictly="false"
+            :initValue="false"
+            v-model:value="params.locations"
+            style="width: 300px; margin-bottom: 0px"
+          ></FYOptionLocation>
+        </el-form>
+      </div>
+    </template> -->
+
+    <el-scrollbar>
+      <!-- 缁熻鏁版嵁鍖哄煙 -->
+      <div class="stats-sections">
+        <!-- 宸︿晶锛氬凡宸℃煡搴楅摵鐜囥�佸贰鏌ョ偣娆°�佸鏌ョ偣娆� -->
+        <div class="stats-section left-section">
+          <h3>宸℃煡姒傚喌</h3>
+          <el-row justify="space-between">
+            <div class="chart-item">
+              <div class="progress-container">
+                <el-progress
+                  type="dashboard"
+                  :percentage="parseFloat(inspectionStats.inspectedRate)"
+                  :color="['#409EFF', '#67C23A']"
+                  :width="120"
+                />
+                <div class="progress-label">宸插贰鏌ュ簵閾虹巼</div>
+                <div class="progress-value">
+                  {{ `${inspectionStats.inspectedShops}/${inspectionStats.totalShops}` }}
+                </div>
+              </div>
+            </div>
+            <div class="stats-grid m-l-16">
+              <el-statistic
+                class="stat-item"
+                :value="inspectionStats.inspectionPoints"
+                title="宸℃煡鐐规"
+              />
+              <el-statistic
+                class="stat-item"
+                :value="inspectionStats.reviewPoints"
+                title="澶嶆煡鐐规"
+              />
+            </div>
+          </el-row>
+        </div>
+
+        <!-- 鍙充晶锛氶棶棰樻暟銆侀棶棰樻暣鏀规暟銆侀棶棰樻暣鏀圭巼缁熻鍥� -->
+        <div class="stats-section right-section">
+          <h3>闂鏁存敼姒傚喌</h3>
+          <div class="stats-grid">
+            <el-row justify="space-around">
+              <el-text>闂鏁帮細{{ inspectionStats.problemCount }}</el-text>
+              <el-text>鏁存敼鏁帮細{{ inspectionStats.rectifiedProblems }}</el-text>
+            </el-row>
+            <!-- <el-statistic class="stat-item" :value="inspectionStats.problemCount" title="闂鏁�" />
+            <el-statistic
+              class="stat-item"
+              :value="inspectionStats.rectifiedProblems"
+              title="闂鏁存敼鏁�"
+            /> -->
+          </div>
+          <!-- <div class="chart-item"> -->
+          <div ref="rectificationRateChart" class="chart"></div>
+          <!-- </div> -->
+        </div>
+      </div>
+
+      <!-- 鍏朵粬鍥捐〃灞曠ず -->
+      <div class="chart-container">
+        <div class="chart-item">
+          <h3>宸℃煡瀹屾垚鎯呭喌瓒嬪娍</h3>
+          <div ref="inspectionTrendChart" class="chart"></div>
+        </div>
+        <div class="chart-item">
+          <h3>闂绫诲瀷鍒嗗竷</h3>
+          <div ref="problemTypeChart" class="chart"></div>
+        </div>
+      </div>
+    </el-scrollbar>
+  </el-card>
+</template>
+
+<script setup>
+import { ref, onMounted, onUnmounted, watch, computed } from 'vue'
+import * as echarts from 'echarts'
+import { Icon } from '@iconify/vue'
+import dayjs from 'dayjs'
+import { ElMessage } from 'element-plus'
+
+// 鎬昏鐜板満宸℃煡鏁版嵁
+const dayStart = dayjs('2025-08-01').startOf('date')
+const dayEnd = dayStart.endOf('date')
+const shortcuts = [
+  {
+    text: '浠婂ぉ',
+    value: [dayStart.toDate(), dayEnd.toDate()],
+  },
+  {
+    text: '鏈懆',
+    value: [dayStart.startOf('week').toDate(), dayEnd.endOf('week').toDate()],
+  },
+  {
+    text: '涓婂懆',
+    value: [dayStart.day(-7).toDate(), dayEnd.day(-1).toDate()],
+  },
+  {
+    text: '鏈湀',
+    value: [dayStart.startOf('month').toDate(), dayEnd.endOf('month').toDate()],
+  },
+  {
+    text: '涓婃湀',
+    value: [
+      dayStart.subtract(1, 'month').startOf('month').toDate(),
+      dayEnd.subtract(1, 'month').endOf('month').toDate(),
+    ],
+  },
+  {
+    text: '鏈搴�',
+    value: [dayStart.startOf('quarter').toDate(), dayEnd.endOf('quarter').toDate()],
+  },
+  {
+    text: '涓婂搴�',
+    value: [
+      dayStart.subtract(1, 'quarter').startOf('quarter').toDate(),
+      dayEnd.subtract(1, 'quarter').endOf('quarter').toDate(),
+    ],
+  },
+  {
+    text: '鍘诲勾',
+    value: [
+      dayStart.subtract(1, 'year').startOf('year').toDate(),
+      dayEnd.subtract(1, 'year').endOf('year').toDate(),
+    ],
+  },
+  {
+    text: '浠婂勾',
+    value: [dayStart.startOf('year').toDate(), dayEnd.endOf('year').toDate()],
+  },
+]
+const params = ref({
+  prodBaseTypes: [],
+  prodCheck: '',
+  scenetype: '',
+  topTask: '',
+  locations: {
+    aCode: null,
+    aName: null,
+    cCode: '3100',
+    cName: '涓婃捣甯�',
+    dCode: '310104',
+    dName: '寰愭眹鍖�',
+    mCode: null,
+    mName: null,
+    pCode: '31',
+    pName: '涓婃捣甯�',
+    tCode: null,
+    tName: null,
+  },
+  timeRange: [dayStart.startOf('month').toDate(), dayEnd.endOf('month').toDate()],
+})
+const inspectionStats = ref({
+  // totalShops: 1250,
+  // inspectedShops: 980,
+  // inspectedRate: '78.4%',
+  // inspectionPoints: 2350,
+  // reviewPoints: 450,
+  // problemCount: 320,
+  // rectifiedProblems: 280,
+  // sameDayRectificationRate: '65.2%',
+  // effectiveRectificationRate: '78.5%',
+  // comprehensiveRectificationRate: '82.3%',
+  // auditPassRate: '87.5%',
+})
+
+// 鍥捐〃寮曠敤
+const inspectionTrendChart = ref(null)
+const problemTypeChart = ref(null)
+const rectificationRateChart = ref(null)
+
+const refreshInspectionData = () => {
+  // 妯℃嫙鍒锋柊鏁版嵁
+  console.log('鍒锋柊宸℃煡鏁版嵁', params.value)
+  // 鐢熸垚鏂扮殑妯℃嫙鏁版嵁
+  const totalShops = 90 + Math.floor(Math.random() * 10)
+  const inspectedShops = 70 + Math.floor(Math.random() * 10)
+  const inspectedRate = ((inspectedShops / totalShops) * 100).toFixed(1) + '%'
+
+  // 璁$畻鏃堕棿鑼冨洿
+  const startTime = params.value.timeRange[0]
+  const endTime = params.value.timeRange[1]
+  const startDate = dayjs(startTime)
+  const endDate = dayjs(endTime)
+  const daysDiff = endDate.diff(startDate, 'day')
+  const months = daysDiff / 30
+
+  // 鏍规嵁鏃堕棿鑼冨洿璋冩暣鏁版嵁閲忕骇
+  const inspectionPoints = Math.floor(100 * months) + Math.floor(Math.random() * 20)
+  const problemCount = Math.floor(200 * months) + Math.floor(Math.random() * 30)
+  const reviewPoints = Math.floor(inspectionPoints * 0.2) + Math.floor(Math.random() * 10)
+  const rectifiedProblems = Math.floor(problemCount * 0.8) + Math.floor(Math.random() * 20)
+
+  inspectionStats.value = {
+    totalShops,
+    inspectedShops,
+    inspectedRate,
+    inspectionPoints,
+    reviewPoints,
+    problemCount,
+    rectifiedProblems,
+    sameDayRectificationRate: (60 + Math.random() * 20).toFixed(1) + '%',
+    effectiveRectificationRate: (70 + Math.random() * 20).toFixed(1) + '%',
+    comprehensiveRectificationRate: (75 + Math.random() * 15).toFixed(1) + '%',
+    auditPassRate: (80 + Math.random() * 15).toFixed(1) + '%',
+  }
+  // 閲嶆柊鍒濆鍖栧浘琛ㄤ互鏇存柊鏁版嵁
+  initCharts()
+}
+
+const handleExceed = (files, fileList) => {
+  ElMessage.warning('鍙兘涓婁紶涓�涓枃浠�')
+}
+
+// 鍒濆鍖栧浘琛�
+const initCharts = () => {
+  // 宸℃煡瀹屾垚鎯呭喌瓒嬪娍鍥�
+  if (inspectionTrendChart.value) {
+    const chart = echarts.init(inspectionTrendChart.value)
+
+    // 璁$畻鏃堕棿鑼冨洿骞剁敓鎴恱杞存暟鎹�
+    const startTime = params.value.timeRange[0]
+    const endTime = params.value.timeRange[1]
+    const startDate = dayjs(startTime)
+    const endDate = dayjs(endTime)
+    const daysDiff = endDate.diff(startDate, 'day')
+
+    let xAxisData = []
+    let seriesData = []
+
+    if (daysDiff <= 30) {
+      // 鍚屼竴涓湀鍐咃紝鎸夋棩鏄剧ず
+      for (let i = 0; i <= daysDiff; i++) {
+        const date = startDate.add(i, 'day')
+        xAxisData.push(date.format('MM/DD'))
+        seriesData.push(60 + Math.floor(Math.random() * 30)) // 鐢熸垚闅忔満鏁版嵁
+      }
+    } else {
+      // 瓒呰繃涓�涓湀锛屾寜鏈堟樉绀�
+      const startMonth = startDate.startOf('month')
+      const endMonth = endDate.endOf('month')
+      const monthsDiff = endMonth.diff(startMonth, 'month')
+
+      for (let i = 0; i <= monthsDiff; i++) {
+        const date = startMonth.add(i, 'month')
+        xAxisData.push(date.format('YYYY/MM'))
+        seriesData.push(60 + Math.floor(Math.random() * 30)) // 鐢熸垚闅忔満鏁版嵁
+      }
+    }
+
+    chart.setOption({
+      xAxis: {
+        type: 'category',
+        data: xAxisData,
+      },
+      yAxis: {
+        type: 'value',
+        axisLabel: {
+          formatter: '{value}%',
+        },
+      },
+      series: [
+        {
+          data: seriesData,
+          type: 'bar',
+        },
+      ],
+    })
+  }
+
+  // 闂绫诲瀷鍒嗗竷鍥�
+  if (problemTypeChart.value) {
+    const chart = echarts.init(problemTypeChart.value)
+    chart.setOption({
+      series: [
+        {
+          type: 'pie',
+          radius: ['20%', '45%'],
+          center: ['50%', '45%'],
+          data: [
+            { value: 30, name: '娌圭儫鍦ㄧ嚎鐩戞祴璁惧' },
+            { value: 25, name: '娌圭儫鍑�鍖栬鏂借澶�' },
+            { value: 20, name: '娌圭儫鍦ㄧ嚎鐩戞祴璁惧缁存姢' },
+            { value: 15, name: '娌圭儫鍑�鍖栬鏂借澶囩淮鎶�' },
+            { value: 10, name: '娌圭儫鍦ㄧ嚎鐩戞祴鏁版嵁閲忕骇' },
+            { value: 20, name: '绌鸿皟鍜岄鏈哄櫔澹�' },
+            { value: 18, name: '鍙拌处绠$悊' },
+            { value: 22, name: '淇$敤鎵胯鑷瘎' },
+          ],
+          label: {
+            show: true,
+            formatter: '{b}: {d}%',
+          },
+        },
+      ],
+    })
+  }
+
+  // 闂鏁存敼鐜囩粺璁″浘
+  if (rectificationRateChart.value) {
+    const chart = echarts.init(rectificationRateChart.value)
+    chart.setOption({
+      xAxis: {
+        type: 'category',
+        data: [
+          '褰撴棩鏁存敼鐜�',
+          // '48灏忔椂鍐呮暣鏀圭巼',
+          '缁煎悎鏁存敼鐜�',
+          '瀹℃牳閫氳繃鐜�',
+        ],
+      },
+      yAxis: {
+        type: 'value',
+        axisLabel: {
+          formatter: '{value}%',
+        },
+      },
+      series: [
+        {
+          data: [
+            parseFloat(inspectionStats.value.sameDayRectificationRate),
+            // parseFloat(inspectionStats.value.effectiveRectificationRate),
+            parseFloat(inspectionStats.value.comprehensiveRectificationRate),
+            parseFloat(inspectionStats.value.auditPassRate),
+          ],
+          type: 'bar',
+          itemStyle: {
+            color: function (params) {
+              const colors = ['#409EFF', '#67C23A', '#E6A23C', '#F56C6C']
+              return colors[params.dataIndex]
+            },
+          },
+        },
+      ],
+    })
+  }
+}
+
+// 鐩戝惉绐楀彛澶у皬鍙樺寲
+const handleResize = () => {
+  // 閲嶆柊璋冩暣鍥捐〃澶у皬
+  if (inspectionTrendChart.value) {
+    echarts.init(inspectionTrendChart.value).resize()
+  }
+  if (problemTypeChart.value) {
+    echarts.init(problemTypeChart.value).resize()
+  }
+  if (rectificationRateChart.value) {
+    echarts.init(rectificationRateChart.value).resize()
+  }
+}
+
+// 鐩戝惉params鍙樺寲
+watch(
+  () => params.value,
+  () => {
+    refreshInspectionData()
+  },
+  { deep: true },
+)
+
+// 鐢熷懡鍛ㄦ湡
+onMounted(() => {
+  refreshInspectionData()
+  initCharts()
+  window.addEventListener('resize', handleResize)
+})
+
+// 缁勪欢鍗歌浇鏃舵竻鐞嗕簨浠剁洃鍚�
+onUnmounted(() => {
+  cleanup()
+})
+
+// 娓呯悊
+const cleanup = () => {
+  window.removeEventListener('resize', handleResize)
+}
+</script>
+
+<style scoped>
+:deep() .el-card__body {
+  padding: 8px;
+}
+.mb-4 {
+  /* width: 600px; */
+}
+
+.card-header {
+  display: flex;
+  flex-direction: column;
+  align-items: flex-start;
+  gap: 10px;
+}
+
+.filter-group {
+  display: flex;
+  flex-direction: column;
+  align-items: flex-start;
+  width: 100%;
+  gap: 10px;
+}
+
+.mr-2 {
+  margin-right: 10px;
+}
+
+.stats-sections {
+  display: flex;
+  flex-direction: column;
+  gap: 20px;
+}
+
+.stats-section {
+  flex: 1;
+  background-color: #fff;
+  border-radius: 8px;
+  /* border: 1px solid #e4e7ed; */
+}
+
+.stats-section h3 {
+  margin-bottom: 15px;
+  font-size: 16px;
+  font-weight: 600;
+  color: #303133;
+}
+
+.stats-grid {
+  display: flex;
+  flex-direction: column;
+  gap: 10px;
+}
+
+.stat-item {
+  flex: 1;
+  background-color: #fff;
+  padding: 20px;
+  border-radius: 8px;
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+
+.progress-container {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  height: 100%;
+}
+
+.progress-label {
+  margin-top: 10px;
+  font-size: 14px;
+  font-weight: 500;
+  color: #606266;
+}
+
+.progress-value {
+  margin-top: 5px;
+  font-size: 18px;
+  font-weight: 600;
+  color: #409eff;
+}
+
+.chart-container {
+  display: flex;
+  flex-direction: column;
+  gap: 20px;
+  margin-bottom: 30px;
+}
+
+.chart-item {
+  flex: 1;
+  background-color: #fff;
+  padding: 20px;
+  border-radius: 8px;
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+
+.chart-item h3 {
+  margin-bottom: 15px;
+  font-size: 16px;
+  font-weight: 600;
+}
+
+.chart-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 15px;
+}
+
+.chart-summary {
+  font-size: 14px;
+  color: #606266;
+  font-weight: 500;
+}
+
+.chart {
+  width: 100%;
+  height: 250px;
+}
+
+.pagination-container {
+  margin-top: 20px;
+  display: flex;
+  justify-content: flex-end;
+}
+
+.dialog-footer {
+  display: flex;
+  justify-content: flex-end;
+}
+
+.import-container {
+  padding: 20px 0;
+}
+
+.import-tip {
+  margin-bottom: 20px;
+  font-size: 14px;
+  color: #606266;
+}
+
+.upload-demo {
+  margin-bottom: 20px;
+}
+</style>

--
Gitblit v1.9.3