From 26cd65ace0c8787b5ff6feff3e6270fb371e1a9c Mon Sep 17 00:00:00 2001 From: zhuguifei <zhuguifei@zhuguifeideiMac.local> Date: 星期四, 11 九月 2025 13:41:23 +0800 Subject: [PATCH] 添加质量预测性维护两个页面 --- src/views/index.vue | 1031 +++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 files changed, 885 insertions(+), 146 deletions(-) diff --git a/src/views/index.vue b/src/views/index.vue index 8dce3f0..714f6a7 100644 --- a/src/views/index.vue +++ b/src/views/index.vue @@ -1,166 +1,905 @@ <template> <div class="app-container home"> - <el-row :gutter="20"> - <el-col :sm="24" :lg="12" style="padding-left: 20px"> - <h2>RuoYi-Vue-Plus澶氱鎴风鐞嗙郴缁�</h2> - <p> - RuoYi-Vue-Plus 鏄熀浜� RuoYi-Vue 閽堝 鍒嗗竷寮忛泦缇� 鍦烘櫙鍗囩骇(涓嶅吋瀹瑰師妗嗘灦) - <br /> - * 鍓嶇寮�鍙戞鏋� Vue3銆乀S銆丒lement Plus<br /> - * 鍚庣寮�鍙戞鏋� Spring Boot<br /> - * 瀹瑰櫒妗嗘灦 Undertow 鍩轰簬 Netty 鐨勯珮鎬ц兘瀹瑰櫒<br /> - * 鏉冮檺璁よ瘉妗嗘灦 Sa-Token 鏀寔澶氱粓绔璇佺郴缁�<br /> - * 鍏崇郴鏁版嵁搴� MySQL 閫傞厤 8.X 鏈�浣� 5.7<br /> - * 缂撳瓨鏁版嵁搴� Redis 閫傞厤 6.X 鏈�浣� 4.X<br /> - * 鏁版嵁搴撴鏋� Mybatis-Plus 蹇�� CRUD 澧炲姞寮�鍙戞晥鐜�<br /> - * 鏁版嵁搴撴鏋� p6spy 鏇村己鍔茬殑 SQL 鍒嗘瀽<br /> - * 澶氭暟鎹簮妗嗘灦 dynamic-datasource 鏀寔涓讳粠涓庡绉嶇被鏁版嵁搴撳紓鏋�<br /> - * 搴忓垪鍖栨鏋� Jackson 缁熶竴浣跨敤 jackson 楂樻晥鍙潬<br /> - * Redis瀹㈡埛绔� Redisson 鎬ц兘寮哄姴銆丄PI涓板瘜<br /> - * 鍒嗗竷寮忛檺娴� Redisson 鍏ㄥ眬銆佽姹侷P銆侀泦缇D 澶氱闄愭祦<br /> - * 鍒嗗竷寮忛攣 Lock4j 娉ㄨВ閿併�佸伐鍏烽攣 澶氱澶氭牱<br /> - * 鍒嗗竷寮忓箓绛� Lock4j 鍩轰簬鍒嗗竷寮忛攣瀹炵幇<br /> - * 鍒嗗竷寮忛摼璺拷韪� SkyWalking 鏀寔閾捐矾杩借釜銆佺綉鏍煎垎鏋愩�佸害閲忚仛鍚堛�佸彲瑙嗗寲<br /> - * 鍒嗗竷寮忎换鍔¤皟搴� SnailJob 楂樻�ц兘 楂樺彲闈� 鏄撴墿灞�<br /> - * 鏂囦欢瀛樺偍 Minio 鏈湴瀛樺偍<br /> - * 鏂囦欢瀛樺偍 涓冪墰銆侀樋閲屻�佽吘璁� 浜戝瓨鍌�<br /> - * 鐩戞帶妗嗘灦 SpringBoot-Admin 鍏ㄦ柟浣嶆湇鍔$洃鎺�<br /> - * 鏍¢獙妗嗘灦 Validation 澧炲己鎺ュ彛瀹夊叏鎬� 涓ヨ皑鎬�<br /> - * Excel妗嗘灦 Alibaba EasyExcel 鎬ц兘浼樺紓 鎵╁睍鎬у己<br /> - * 鏂囨。妗嗘灦 SpringDoc銆乯avadoc 鏃犳敞瑙i浂鍏ヤ镜鍩轰簬java娉ㄩ噴<br /> - * 宸ュ叿绫绘鏋� Hutool銆丩ombok 鍑忓皯浠g爜鍐椾綑 澧炲姞瀹夊叏鎬�<br /> - * 浠g爜鐢熸垚鍣� 閫傞厤MP銆丼pringDoc瑙勮寖鍖栦唬鐮� 涓�閿敓鎴愬墠鍚庣浠g爜<br /> - * 閮ㄧ讲鏂瑰紡 Docker 瀹瑰櫒缂栨帓 涓�閿儴缃蹭笟鍔¢泦缇�<br /> - * 鍥介檯鍖� SpringMessage Spring鏍囧噯鍥介檯鍖栨柟妗�<br /> - </p> - <p><b>褰撳墠鐗堟湰:</b> <span>v5.1.2</span></p> - <p> - <el-tag type="danger">¥鍏嶈垂寮�婧�</el-tag> - </p> - <p> - <el-button type="primary" icon="Cloudy" plain @click="goTarget('https://gitee.com/dromara/RuoYi-Vue-Plus')">璁块棶鐮佷簯</el-button> - <el-button type="primary" icon="Cloudy" plain @click="goTarget('https://github.com/dromara/RuoYi-Vue-Plus')">璁块棶GitHub</el-button> - <el-button type="primary" icon="Cloudy" plain @click="goTarget('https://plus-doc.dromara.org/#/ruoyi-vue-plus/changlog')" - >鏇存柊鏃ュ織</el-button - > - </p> - </el-col> + <div class="p-5"> + <div style="display: flex" class="gap-4"> - <el-col :sm="24" :lg="12" style="padding-left: 20px"> - <h2>RuoYi-Cloud-Plus澶氱鎴峰井鏈嶅姟绠$悊绯荤粺</h2> - <p> - RuoYi-Cloud-Plus 寰湇鍔¢�氱敤鏉冮檺绠$悊绯荤粺 閲嶅啓 RuoYi-Cloud 鍏ㄦ柟浣嶅崌绾�(涓嶅吋瀹瑰師妗嗘灦) - <br /> - * 鍓嶇寮�鍙戞鏋� Vue3銆乀S銆丒lement UI<br /> - * 鍚庣寮�鍙戞鏋� Spring Boot<br /> - * 寰湇鍔″紑鍙戞鏋� Spring Cloud銆丼pring Cloud Alibaba<br /> - * 瀹瑰櫒妗嗘灦 Undertow 鍩轰簬 XNIO 鐨勯珮鎬ц兘瀹瑰櫒<br /> - * 鏉冮檺璁よ瘉妗嗘灦 Sa-Token銆丣wt 鏀寔澶氱粓绔璇佺郴缁�<br /> - * 鍏崇郴鏁版嵁搴� MySQL 閫傞厤 8.X 鏈�浣� 5.7<br /> - * 鍏崇郴鏁版嵁搴� Oracle 閫傞厤 11g 12c<br /> - * 鍏崇郴鏁版嵁搴� PostgreSQL 閫傞厤 13 14<br /> - * 鍏崇郴鏁版嵁搴� SQLServer 閫傞厤 2017 2019<br /> - * 缂撳瓨鏁版嵁搴� Redis 閫傞厤 6.X 鏈�浣� 5.X<br /> - * 鍒嗗竷寮忔敞鍐屼腑蹇� Alibaba Nacos 閲囩敤2.X 鍩轰簬GRPC閫氫俊楂樻�ц兘<br /> - * 鍒嗗竷寮忛厤缃腑蹇� Alibaba Nacos 閲囩敤2.X 鍩轰簬GRPC閫氫俊楂樻�ц兘<br /> - * 鏈嶅姟缃戝叧 Spring Cloud Gateway 鍝嶅簲寮忛珮鎬ц兘缃戝叧<br /> - * 璐熻浇鍧囪 Spring Cloud Loadbalancer 璐熻浇鍧囪 澶勭悊<br /> - * RPC杩滅▼璋冪敤 Apache Dubbo 鍘熺敓鎬佷娇鐢ㄤ綋楠屻�侀珮鎬ц兘<br /> - * 鍒嗗竷寮忛檺娴佺啍鏂� Alibaba Sentinel 鏃犱镜鍏ャ�侀珮鎵╁睍<br /> - * 鍒嗗竷寮忎簨鍔� Alibaba Seata 鏃犱镜鍏ャ�侀珮鎵╁睍 鏀寔 鍥涚妯″紡<br /> - * 鍒嗗竷寮忔秷鎭槦鍒� Spring Cloud Stream 闂ㄩ潰妗嗘灦鍏煎鍚勭MQ闆嗘垚<br /> - * 鍒嗗竷寮忔秷鎭槦鍒� Apache Kafka 楂樻�ц兘楂橀�熷害<br /> - * 鍒嗗竷寮忔秷鎭槦鍒� Apache RocketMQ 楂樺彲鐢ㄥ姛鑳藉鏍�<br /> - * 鍒嗗竷寮忔秷鎭槦鍒� RabbitMQ 鏀寔鍚勭鎵╁睍鎻掍欢鍔熻兘澶氭牱鎬�<br /> - * 鍒嗗竷寮忔悳绱㈠紩鎿� ElasticSearch 涓氱晫鐭ュ悕<br /> - * 鍒嗗竷寮忛摼璺拷韪� Apache SkyWalking 閾捐矾杩借釜銆佺綉鏍煎垎鏋愩�佸害閲忚仛鍚堛�佸彲瑙嗗寲<br /> - * 鍒嗗竷寮忔棩蹇椾腑蹇� ELK 涓氱晫鎴愮啛瑙e喅鏂规<br /> - * 鍒嗗竷寮忕洃鎺� Prometheus銆丟rafana 鍏ㄦ柟浣嶆�ц兘鐩戞帶<br /> - * 鍏朵綑涓� Vue 鐗堟湰涓�鑷�<br /> - </p> - <p><b>褰撳墠鐗堟湰:</b> <span>v2.1.2</span></p> - <p> - <el-tag type="danger">¥鍏嶈垂寮�婧�</el-tag> - </p> - <p> - <el-button type="primary" icon="Cloudy" plain @click="goTarget('https://gitee.com/dromara/RuoYi-Cloud-Plus')">璁块棶鐮佷簯</el-button> - <el-button type="primary" icon="Cloudy" plain @click="goTarget('https://github.com/dromara/RuoYi-Cloud-Plus')">璁块棶GitHub</el-button> - <el-button type="primary" icon="Cloudy" plain @click="goTarget('https://plus-doc.dromara.org/#/ruoyi-cloud-plus/changlog')" - >鏇存柊鏃ュ織</el-button - > - </p> - </el-col> - </el-row> - <el-divider /> + <el-card style="width: 100%;flex: 1;" class="mb-4"> + + <div style="display: flex"> + <div> + <el-statistic :value="batchScore" :suffix="'鍒�'" :precision="1" :value-style="{fontSize: '30px',fontWeight: 'bold'}"> + <template #title> + <div style="display: inline-flex; align-items: center;font-size: 18px"> + 缁煎悎璐ㄩ噺璇勫垎 + <el-tooltip effect="dark" content="" placement="top"> + <el-icon style="margin-left: 4px" :size="12"> + <Warning /> + </el-icon> + </el-tooltip> + </div> + </template> + </el-statistic> + <div class="statistic-footer"> + <div class="footer-item"> + <span>杈冩槰澶�</span> + <span :class="{ 'green': batchScore > 9.4, 'red': batchScore <= 9.4 }"> + <el-icon v-if="batchScore > 9.4"> + <CaretTop /> + </el-icon> + <el-icon v-else> + <CaretBottom /> + </el-icon> + </span> + </div> + </div> + </div> + <div style="flex: 1;display: flex;justify-content: center;align-items: center"> + <el-image style="width: 60px; height: 60px" :src="q1" fit="contain" /> + </div> + </div> + + + </el-card> + <el-card style="flex: 1" class="mb-4"> + + + <div style="display: flex"> + <div> + <el-statistic :value="qualityRate" :suffix="'%'" :value-style="{fontSize: '30px',fontWeight: 'bold'}"> + <template #title> + <div style="display: inline-flex; align-items: center;font-size: 18px"> + 鑹搧鐜� + <el-tooltip effect="dark" content="" placement="top"> + <el-icon style="margin-left: 4px" :size="12"> + <Warning /> + </el-icon> + </el-tooltip> + </div> + </template> + </el-statistic> + <div class="statistic-footer"> + <div class="footer-item"> + <span>杈冩槰澶�</span> + <span :class="{ 'green': qualityRate >= 95, 'red': qualityRate < 95 }"> + <el-icon v-if="qualityRate >= 95"> + <CaretTop /> + </el-icon> + <el-icon v-else> + <CaretBottom /> + </el-icon> + </span> + </div> + </div> + </div> + <div style="flex: 1;display: flex;justify-content: center;align-items: center"> + <el-image style="width: 60px; height: 60px" :src="q2" fit="contain" /> + </div> + </div> + + + </el-card> + <el-card style="flex: 1" class="mb-4"> + + + <div style="display: flex"> + <div> + <el-statistic :value="checkNum" :suffix="'pcs'" :value-style="{fontSize: '30px',fontWeight: 'bold'}"> + <template #title> + <div style="display: inline-flex; align-items: center;font-size: 18px"> + 妫�娴嬫暟閲� + <el-tooltip effect="dark" content="" placement="top"> + <el-icon style="margin-left: 4px" :size="12"> + <Warning /> + </el-icon> + </el-tooltip> + </div> + </template> + </el-statistic> + <div class="statistic-footer"> + <div class="footer-item"> + <span>杈冩槰澶�</span> + <span :class="{ 'green': batchScore > 1, 'red': batchScore <= 1 }"> + <el-icon v-if="batchScore > 1"> + <CaretTop /> + </el-icon> + <el-icon v-else> + <CaretBottom /> + </el-icon> + </span> + </div> + </div> + </div> + <div style="flex: 1;display: flex;justify-content: center;align-items: center"> + <el-image style="width: 60px; height: 60px" :src="q3" fit="contain" /> + </div> + </div> + + + </el-card> + <el-card style="flex: 1" class="mb-4"> + + + <div style="display: flex"> + <div> + <el-statistic :value="ngCountNum" :suffix="'pcs'" :value-style="{fontSize: '30px',fontWeight: 'bold'}"> + <template #title> + <div style="display: inline-flex; align-items: center;font-size: 18px"> + 寮傚父鏁伴噺 + <el-tooltip effect="dark" content="" placement="top"> + <el-icon style="margin-left: 4px" :size="12"> + <Warning /> + </el-icon> + </el-tooltip> + </div> + </template> + </el-statistic> + <div class="statistic-footer"> + <div class="footer-item"> + <span>杈冩槰澶�</span> + <span :class="{ 'green': ngCountNum < 50, 'red': ngCountNum >= 50 }"> + <el-icon v-if="ngCountNum >= 50"> + <CaretTop /> + </el-icon> + <el-icon v-else> + <CaretBottom /> + </el-icon> + </span> + + <span style="margin-left: 10px">棰勬祴寮傚父鐜�:</span> + <span class="red" v-if="qualityRate > 80"> {{(((100-qualityRate)/ 3)+0.1).toFixed(1) }}% </span> + <span v-else > 3.7%</span> + </div> + </div> + </div> + <div style="flex: 1;display: flex;justify-content: center;align-items: center"> + <el-image style="width: 60px; height: 60px" :src="q4" fit="contain" /> + </div> + </div> + </el-card> + </div> + <!-- 璁惧鍋ュ悍鐘舵�佸彲瑙嗗寲 --> + <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> + <el-card shadow="hover" class="h-420" > + <template #header> + <div class="card-header"> + <span>鍋ュ悍搴﹁瘎鍒�</span> + </div> + </template> + <div ref="healthChartRef" class="h-400 w-full"></div> + </el-card> + + <el-card shadow="hover" class="h-420"> + <template #header> + <div class="card-header"> + <span>璐ㄩ噺棰勮淇℃伅</span> + </div> + </template> +<!-- <div class="grid grid-cols-2 gap-2">--> +<!-- <div class="p-2 bg-blue-50 rounded">--> +<!-- <p class="text-sm text-gray-600">榻愮撼淇濇姢鐢靛帇(榛�)</p>--> +<!-- <p class="text-xl">39.00 V 鈮� result 鈮� 49.00 V</p>--> +<!-- </div>--> +<!-- <div class="p-2 bg-yellow-50 rounded">--> +<!-- <p class="text-sm text-gray-600">璺濈</p>--> +<!-- <p class="text-xl">4.75 mm 鈮� result 鈮� 5.15 mm</p>--> +<!-- </div>--> +<!-- <div class="p-2 bg-red-50 rounded">--> +<!-- <p class="text-sm text-gray-600">鍘嬮檷(榛�)1</p>--> +<!-- <p class="text-xl">0.30 V 鈮� result 鈮� 3.00 V</p>--> +<!-- </div>--> +<!-- <div class="p-2 bg-green-50 rounded">--> +<!-- <p class="text-sm text-gray-600">鍥炲樊</p>--> +<!-- <p class="text-xl">0.05 mm 鈮� result 鈮� 1.00 mm</p>--> +<!-- </div>--> +<!-- <div class="p-2 bg-blue-50 rounded">--> +<!-- <p class="text-sm text-gray-600">婕忕數娴�(榛�)1</p>--> +<!-- <p class="text-xl">result 鈮� 800.00 uA</p>--> +<!-- </div>--> +<!-- <div class="p-2 bg-yellow-50 rounded">--> +<!-- <p class="text-sm text-gray-600"></p>--> +<!-- <p class="text-xl font-bold"></p>--> +<!-- </div>--> +<!-- </div>--> + + <el-table size="large" :data="warnBatchList" style="width: 100%" :border="true" stripe> + <el-table-column prop="batchTime" label="棰勮鏃堕棿" /> + <el-table-column prop="batchCode" label="鎵规鍙�" width="140" /> + <el-table-column prop="gw" label="璁惧/宸ヤ綅" /> + <el-table-column prop="yc" label="寮傚父绫诲瀷" /> + <el-table-column prop="cd" label="涓ラ噸绋嬪害"> + <template #default="{ row }"> + <el-tag :type="getStatusTagType(row.cd)">{{ row.cd }}</el-tag> + </template> + </el-table-column> + + + </el-table> + </el-card> + </div> + + + <el-card shadow="hover" class="mb-6"> + <template #header> + <div class="card-header"> + <span>妫�娴嬫壒娆�</span> + <el-date-picker + v-model="batchDate" + type="date" + placeholder="閫夋嫨鏃ユ湡" + :disabled-date="disabledDate" + :shortcuts="shortcuts" + @change="changeBatchDate" + /> + </div> + </template> + <div class="grid grid-cols-1 gap-4"> + <!-- 杩欓噷灏嗘斁缃璀﹁〃鏍� --> + <el-table v-loading="loading" :data="batchList" style="width: 100%" :border="true" stripe> + <el-table-column prop="batchCode" label="鎵规鍙�" width="180" /> + <el-table-column prop="prodModel" label="浜у搧鍨嬪彿" width="180" /> + <el-table-column prop="num" label="妫�娴嬫暟閲�" width="120" /> + <el-table-column prop="okNum" label="鑹搧鏁伴噺" width="120" /> + <el-table-column prop="ngNum" label="涓嶈壇鏁伴噺" width="120" /> + <el-table-column prop="lpv" label="鑹搧鐜�" width="120"> + <template #default="{ row }"> + <el-tag :type="goodProductsRate(row) >= 95 ? 'success' : 'warning'"> {{ goodProductsRate(row) }} % </el-tag> + </template> + </el-table-column> + <el-table-column prop="whjy" label="缁存姢寤鸿"> + <template #default="{ row }"> + <el-tag :type="goodProductsRate(row) >= 95 ? 'success' : 'warning'"> + {{ goodProductsRate(row) >= 95 ? '鑹搧鐜囨寚鏍囧凡浼樺紓锛岃鍏虫敞璁惧缁煎悎鏁堢巼' : '棰勮锛屾鏌ュ伐鑹哄弬鏁版槸鍚︾鍚堟爣鍑嗭紝浼樺寲鍏抽敭鍙傛暟' }} + </el-tag> + </template> + </el-table-column> + <el-table-column label="鎿嶄綔" width="180"> + <template #default="{ row }"> + <el-button link type="primary" @click="handleDetail(row)">璇︽儏</el-button> + </template> + </el-table-column> + </el-table> + </div> + </el-card> + + + + + + <!-- 澶囦欢淇℃伅 --> + <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> + <!-- 鎵规鍚堟牸鐜囪秼鍔� --> + <el-card shadow="hover" class="h-420"> + <template #header> + <div class="card-header"> + <span>鎵规鍚堟牸鐜囪秼鍔�</span> + </div> + </template> + <div ref="batchRateTrendRef" class="h-400 w-full"></div> + </el-card> + + + <el-card shadow="hover" class="h-420"> + <template #header> + <div class="card-header"> + <span>杩戜竴鍛∟G椤筎OP5</span> + </div> + </template> + <div ref="ngChartRef" class="h-400 w-full"></div> + </el-card> + </div> + </div> </div> </template> <script setup name="Index" lang="ts"> -const goTarget = (url: string) => { - window.open(url, '__blank'); +import { onMounted, ref } from 'vue'; +import { useRouter } from 'vue-router'; +import { ElMessage } from 'element-plus'; +import * as echarts from 'echarts'; + +import q1 from '@/assets/images/quailty/q1.png'; +import q2 from '@/assets/images/quailty/q2.png'; +import q3 from '@/assets/images/quailty/q3.png'; +import q4 from '@/assets/images/quailty/q4.png'; + +import { queryQualityHealth, queryBatchList,queryPwbatchList ,queryNgrank} from '@/api/qms/index'; +import { BatchVO } from '@/api/qms/batch/types'; +import { listBatch } from '@/api/qms/batch'; + +const batchScore = ref(0); +const qualityRate = ref(0); +const checkNum = ref(0); +const ngCountNum = ref(0); + +const batchDate = ref(''); + +const healthChartRef = ref<HTMLElement | null>(null); +const batchRateTrendRef = ref<HTMLElement | null>(null); +const ngChartRef = ref<HTMLElement | null>(null); +const healthChart = ref(); +const batchRateChart = ref(); +const ngChart = ref(); +const router = useRouter(); + +const loading = ref(false); +const batchList = ref<BatchVO[]>([]); +const warnBatchList = ref<any>([]); + + +const gwList = [ + "寰満鐢电郴缁熻殌鍒绘満", + "鏅跺渾閿悎鏈�", + "浼犳劅鍣ㄦ牎鍑嗙珯", + "钖勮啘娌夌Н璁惧", + "鍏夊埢鏈�", + "绂诲瓙娉ㄥ叆鏈�", + "鍖栧鏈烘鎶涘厜璁惧", + "鐑鐞嗙倝", + "灏佽娴嬭瘯绔�", + "婵�鍏変慨璋冭澶�", + "鐢垫�ц兘娴嬭瘯鍙�", + "鍏夊妫�娴嬩华", + "鐪熺┖闀�鑶滄満", + "瓒呭0娉㈡竻娲楁満", + "X灏勭嚎妫�娴嬩华" +] +const ycList = [ + "铓�鍒绘繁搴﹀亸宸�", + "閿悎鍘嬪姏寮傚父", + "鏍″噯鏁版嵁鍋忕Щ", + "娌夌Н閫熺巼娉㈠姩", + "鍏夊埢瀵瑰噯鍋忓樊", + "绂诲瓙娉ㄥ叆鍓傞噺寮傚父", + "鎶涘厜鍘氬害涓嶅潎", + "娓╁害绋冲畾鎬у紓甯�", + "灏佽瀵嗗皝鎬т笉鑹�", + "鐢甸樆鍊煎亸宸�", + "鐏垫晱搴﹀紓甯�", + "鍝嶅簲鏃堕棿瓒呴檺", + "淇″彿婕傜Щ寮傚父", + "绾挎�у害鍋忓樊", + "闆剁偣婕傜Щ寮傚父", + "杩囪浇鎭㈠寮傚父", + "缁濈紭鐢甸樆涓嶈冻", + "浠嬭川鑰愬帇涓嶅悎鏍�", + "棰戠巼鍝嶅簲寮傚父", + "淇″櫔姣斾笉杈炬爣" +]; + +const cdList = [ + "楂�", "楂�", "涓�", "涓�", "楂�", + "涓�", "涓�", "楂�", "楂�", "涓�", + "楂�", "涓�", "涓�", "涓�", "浣�", + "涓�", "楂�", "楂�", "涓�", "浣�" +]; +const getStatusTagType = (status: string) => { + switch (status) { + case '楂�': return 'danger'; + case '涓�': return 'warning'; + case '浣�': return 'info'; + } }; + +function changeBatchDate(date: Date){ + getBatch(date ? date : new Date()) + +} +async function queryWarnBatchList(){ + const queryParams = { + pageNum: 1, + pageSize: 6 + }; + const res:any = await listBatch(queryParams); + + if(res && res.rows){ + warnBatchList.value = []; + res.rows.forEach((item,index) => { + item.gw = gwList[index]; + item.yc = ycList[index]; + item.cd = cdList[index]; + item.batchTime = item.batchTime.substring(0,10); + warnBatchList.value.push(item); + }) + } + +} + +const shortcuts = [ + { + text: '浠婂ぉ', + value: new Date(), + }, + { + text: '鏄ㄥぉ', + value: () => { + const date = new Date() + date.setTime(date.getTime() - 3600 * 1000 * 24) + return date + }, + }, + { + text: '涓�鍛ㄥ墠', + value: () => { + const date = new Date() + date.setTime(date.getTime() - 3600 * 1000 * 24 * 7) + return date + }, + }, +] + +const disabledDate = (time: Date) => { + return time.getTime() > Date.now() +} + + + + + + +const goodProductsRate = (row) => { + if (row.num > 0 && row.okNum > 0) { + return Math.round((row.okNum / row.num) * 100); + } +}; + + + + + + + + + + +const generateWorkOrder = (record) => { + // 宸ュ崟鐢熸垚閫昏緫 + ElMessage.success(`宸蹭负 ${record.name} 鐢熸垚宸ュ崟`); +}; + +const handleDetail = (record) => { + router.push({ path: '/quality/detail', query: { id: record.id } }); +}; + +const initHealthChart = () => { + if (healthChartRef.value) { + healthChart.value = echarts.init(healthChartRef.value); + const option = { + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'shadow' + } + }, + xAxis: { + type: 'category', + data: ['1鏈�', '2鏈�', '3鏈�', '4鏈�', '5鏈�', '6鏈�', '7鏈�', '8鏈�', '9鏈�', '10鏈�', '11鏈�', '12鏈�'] + }, + yAxis: { + type: 'value', + name: '寰楀垎', + minInterval: 1 + }, + series: [ + { + name: '璐ㄩ噺鏁版嵁', + type: 'bar', + barWidth: '50%', + data: [ + { value: 9.8, itemStyle: { color: '#52c41a' } }, + { value: 9.9, itemStyle: { color: '#52c41a' } }, + { value: 9.7, itemStyle: { color: '#52c41a' } }, + { value: 9.8, itemStyle: { color: '#52c41a' } }, + { value: 9.9, itemStyle: { color: '#52c41a' } }, + { value: 9.8, itemStyle: { color: '#52c41a' } }, + { value: 9.9, itemStyle: { color: '#52c41a' } }, + { value: 9.8, itemStyle: { color: '#52c41a' } }, + { value: 9.8, itemStyle: { color: '#52c41a' } } + ], + label: { + show: true, + position: 'top', + formatter: '{c}鍒�' + } + } + ] + }; + healthChart.value.setOption(option); + + window.addEventListener('resize', () => { + healthChart.value.resize(); + }); + } +}; + +const initBatchRateChart = () => { + if (batchRateTrendRef.value) { + batchRateChart.value = echarts.init(batchRateTrendRef.value); + const option = { + color: ['#FFBF00'], + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'cross', + label: { + backgroundColor: '#6a7985' + } + } + }, + + xAxis: [ + { + splitLine: { show: false }, + type: 'category', + boundaryGap: false, + data: ['08-01', '08-02', '08-03', '08-04', '08-05', '08-06', '08-07'] + } + ], + yAxis: [ + { + splitLine: { show: false }, + type: 'value', + name: '妫�娴嬪悎鏍肩巼', + min: 80, // 璁剧疆鏈�灏忓�间负90 + max: 100, // 璁剧疆鏈�澶у�间负100 + interval: 5, // 璁剧疆鍒诲害闂撮殧涓�1 + axisLabel: { + formatter: '{value}%' // 娣诲姞鐧惧垎姣旂鍙� + } + } + ], + series: [ + { + name: '', + type: 'line', + stack: 'Total', + smooth: true, + lineStyle: { + width: 0 + }, + showSymbol: false, + areaStyle: { + opacity: 0.8, + color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ + { + offset: 0, + color: 'rgb(128, 255, 165)' + }, + { + offset: 1, + color: 'rgb(1, 191, 236)' + } + ]) + }, + emphasis: { + focus: 'series' + }, + data: [99, 98, 95, 99, 92, 98, 96], + + } + ] + }; + + option && batchRateChart.value.setOption(option); + + + window.addEventListener('resize', () => { + batchRateChart.value.resize(); + }); + } +}; + +const initNgChart = () => { + if (ngChartRef.value) { + ngChart.value = echarts.init(ngChartRef.value); + const option = { + + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'shadow' + } + }, + grid: { + left: '120px', // 澧炲姞宸︿晶杈硅窛锛屼负鏍囩鐣欏嚭鏇村绌洪棿 + top: '0px', + }, + xAxis: { + type: 'value', + boundaryGap: [0, 0.01], + splitLine: { show: false } + }, + yAxis: { + splitLine: { show: false }, + type: 'category', + data: [ + '闈欐�佹秷鑰楃數娴�2', + '鍥炲樊', + '鐭矾淇濇姢娑堣�楃數娴�(榛�)2', + '鍔ㄦ�佹秷鑰楃數娴�2', + '璺濈', + '鍘嬮檷(榛�)2' + ] + }, + series: [ + { + name: '', + type: 'bar', + barWidth: '60%', + data: [100, 90, 80, 70, 60, 10], + itemStyle: { + color: '#faad14' // 淇敼鏌辩姸鍥鹃鑹� + }, + label: { + show: true, + position: 'right', + formatter: '{c}娆�' + } + } + ] + }; + + option && ngChart.value.setOption(option); + + + + window.addEventListener('resize', () => { + ngChart.value.resize(); + }); + } +}; + +const getHealth = async () => { + const res: any = await queryQualityHealth(); + if (res && res.yAxis) { + const xAxisData = []; + const minValue = res.yAxis.reduce((min, item) => { + return min === null ? item.value : Math.min(min, item.value); + }, null); + res.yAxis.forEach((item, index) => { + if (item.value >= 9.5) { + item.itemStyle = { color: '#52c41a' }; + } else if (item.value < 9.5 && item.value >= 9.0) { + item.itemStyle = { color: '#faad14' }; + } else { + item.itemStyle = { color: '#f5222d' }; + } + if (item.value == minValue) { + item.itemStyle = { color: '#faad14' }; + } + xAxisData.push(item); + }); + updateHealthData(res.xAxis, xAxisData); + } +}; + +const getBatch = async (date = new Date()) => { + loading.value = true; + + const res: any = await queryBatchList({ + pageNum: 1, + pageSize: 10, + params: { + startTime: formatDate(date) + ' 00:00:00', + endTime: formatDate(date) + ' 23:59:59' + } + }); + if (!res || !res.rows) { + return; + } + batchList.value = res.rows; + + checkNum.value = res.rows.reduce((sum, item) => sum + (item.num || 0), 0); + + ngCountNum.value = res.rows.reduce((sum, item) => sum + (item.ngNum || 0), 0); + // 璁$畻oknum鎬诲拰 + const totalOkNum = res.rows.reduce((sum, item) => sum + (item.okNum || 0), 0); + // 璁$畻鑹搧鐜� (閬垮厤闄や互0鐨勬儏鍐�) + const yieldRate = checkNum.value > 0 ? (totalOkNum / checkNum.value) * 100 : 0; + qualityRate.value = Number(yieldRate.toFixed(2)); + batchScore.value = Number(((yieldRate/10 )-0.1).toFixed(1)); + if(batchScore.value == -0.1){ + batchScore.value = 0; + } + loading.value = false; +}; + +const getPwbatch = async () => { + const res: any = await queryPwbatchList(); + if (res && res.yAxis) { + updatePwbatchData(res.xAxis, res.yAxis); + } +}; + + +const getNgrank = async () => { + const res: any = await queryNgrank(); + if (res && res.yAxis) { + updateNgrankData(res.xAxis, res.yAxis); + } +}; + +const formatDate = (date) => { + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, '0'); + const day = String(date.getDate()).padStart(2, '0'); + return `${year}-${month}-${day}`; +}; + +function updateHealthData(xAxis, yAxis) { + healthChart.value.setOption({ + xAxis: { + type: 'category', + data: xAxis + }, + series: [ + { + data: yAxis + } + ] + }); +} + + +function updatePwbatchData(xAxis, yAxis) { + batchRateChart.value.setOption({ + xAxis: { + type: 'category', + data: xAxis + }, + series: [ + { + data: yAxis + } + ] + }); +} + + +function updateNgrankData(xAxis, yAxis) { + ngChart.value.setOption({ + yAxis: { + type: 'category', + data: xAxis, + inverse: true, + }, + series: [ + { + data: yAxis + } + ] + }); +} + +onMounted(() => { + queryWarnBatchList(); + initHealthChart(); + initBatchRateChart(); + initNgChart(); + getHealth(); + getBatch(); + getPwbatch(); + getNgrank(); +}); </script> <style scoped lang="scss"> -.home { - blockquote { - padding: 10px 20px; - margin: 0 0 20px; - font-size: 17.5px; - border-left: 5px solid #eee; - } - hr { - margin-top: 20px; - margin-bottom: 20px; - border: 0; - border-top: 1px solid #eee; - } - .col-item { - margin-bottom: 20px; - } +.h-500 { + height: 500px; +} - ul { - padding: 0; - margin: 0; +.card-header { + display: flex; + justify-content: space-between; + align-items: center; + font-weight: bold; +} + +.grid { + display: grid; +} + +.grid-cols-1 { + grid-template-columns: repeat(1, minmax(0, 1fr)); +} + +.grid-cols-2 { + grid-template-columns: repeat(2, minmax(0, 1fr)); +} + +.gap-4 { + gap: 1rem; +} + +.mb-6 { + margin-bottom: 1.5rem; +} + +.p-5 { + padding: 1.25rem; +} + +.w-full { + width: 100%; +} + +.h-400 { + height: 400px; +} + +.h-420 { + height: 420px; +} + +.bg-blue-50 { + background-color: #eff6ff; +} + +.bg-yellow-50 { + background-color: #fffbeb; +} + +.bg-red-50 { + background-color: #fef2f2; +} + +.bg-green-50 { + background-color: #f0fdf4; +} + +.rounded { + border-radius: 0.25rem; +} + +.text-sm { + font-size:14px; +} + +.text-xl { + font-size: 14px; +} + +.font-bold { + font-weight: 700; +} + +.text-gray-600 { + color: #4b5563; +} + +@media (min-width: 768px) { + .md\:grid-cols-2 { + grid-template-columns: repeat(2, minmax(0, 1fr)); } +} - font-family: 'open sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; - font-size: 13px; - color: #676a6c; - overflow-x: hidden; +.statistic-footer { + display: flex; + justify-content: space-between; + align-items: center; + flex-wrap: wrap; + font-size: 12px; + color: var(--el-text-color-regular); + margin-top: 16px; +} - ul { - list-style-type: none; - } +.statistic-footer .footer-item { + font-size: 14px; + display: flex; + justify-content: space-between; + align-items: center; +} - h4 { - margin-top: 0px; - } +.statistic-footer .footer-item span:last-child { + display: inline-flex; + align-items: center; + margin-left: 4px; +} - h2 { - margin-top: 10px; - font-size: 26px; - font-weight: 100; - } +.green { + color: var(--el-color-success); +} - p { - margin-top: 10px; - - b { - font-weight: 700; - } - } - - .update-log { - ol { - display: block; - list-style-type: decimal; - margin-block-start: 1em; - margin-block-end: 1em; - margin-inline-start: 0; - margin-inline-end: 0; - padding-inline-start: 40px; - } - } +.red { + color: var(--el-color-error); } </style> -- Gitblit v1.9.3