From 59af55dc3e72f8f2655ae06af9d1b6f766bac423 Mon Sep 17 00:00:00 2001
From: riku <risaku@163.com>
Date: 星期五, 20 三月 2026 16:02:19 +0800
Subject: [PATCH] 2026.3.20
---
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..bc15ba7 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('2023-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