dedsudiyu hai 12 horas
pai
achega
97dbca0b26

+ 13 - 3
src/api/index.js

@@ -103,8 +103,13 @@ export async function getRiskWarningList() {
     const d = res.data
     return wrapResult({
       totalMonth: d.monthAlarmCount,
+      emergencyCount: d.emergencyCount || 0,
+      violationCount: d.violationCount || 0,
       list: (d.eventList || []).map(e => ({
-        id: e.id, lab: e.subName, dept: '', type: e.eventName, value: '',
+        id: e.id,
+        lab: e.labInfo || e.subName,
+        type: e.eventName,
+        category: e.category || '',
         time: e.eventStartTime ? e.eventStartTime.replace('T', ' ') : ''
       }))
     })
@@ -145,7 +150,12 @@ export async function getEquipmentStats() {
         totalHours: d.totalUsageHours ? d.totalUsageHours.toLocaleString() : '0',
         usageRate: String(d.usageRate || 0)
       },
-      status: { using: d.inUseCount, idle: d.idleCount, normal: d.normalCount, repair: d.repairCount }
+      status: {
+        using:  (d.usageStatusList  || []).find(s => s.name === '使用')?.count  || 0,
+        idle:   (d.usageStatusList  || []).find(s => s.name === '空闲')?.count  || 0,
+        normal: (d.deviceStatusList || []).find(s => s.name === '正常')?.count  || 0,
+        repair: (d.deviceStatusList || []).find(s => s.name === '维修')?.count  || 0
+      }
     })
   }
   throw new Error(res.message || '接口异常')
@@ -222,7 +232,7 @@ export async function getMqttConfig() {
 
 // ======================== 化学品库动态统计 ========================
 export async function getChemicalStats() {
-  const res = await request.get('/laboratory/labScreen/chemicalStatistics')
+  const res = await request.get('/chemical/stock/stockSummary')
   if (res.code === 200 && res.data) return res.data
   throw new Error(res.message || '接口异常')
 }

+ 17 - 18
src/components/LabStats/ChemicalsStats.vue

@@ -19,7 +19,7 @@
             </svg>
           </div>
           <div class="chem-stat-info">
-            <div class="chem-stat-value" style="color:#48d7ff">{{ formatNum(stats.totalAmount) }}<span class="unit"> L</span></div>
+            <div class="chem-stat-value" style="color:#48d7ff">{{ formatNum(stats.totalAmount) }}<span class="unit"> {{ stats.unit }}</span></div>
             <div class="chem-stat-label">存量化学品总量</div>
           </div>
         </div>
@@ -62,7 +62,7 @@
 
         <!-- 右下:类目统计 -->
         <div class="chem-stat-item item-center">
-          <div class="chem-stat-value" style="color:#ffb020;font-size:28px;">{{ stats.totalCategories }}</div>
+          <div class="chem-stat-value" style="color:#ffb020;font-size:22px;">{{ stats.totalCategories }}</div>
           <div class="chem-stat-label">存量化学品总类目</div>
           <div class="chem-stat-sub">管控{{ stats.controlledCategories }}类 / 非管控{{ stats.uncontrolledCategories }}类</div>
         </div>
@@ -80,7 +80,7 @@ export default {
   data() {
     return {
       stats: {
-        totalAmount: 0, controlledAmount: 0, uncontrolledAmount: 0,
+        totalAmount: 0, unit: 'L', controlledAmount: 0, uncontrolledAmount: 0,
         totalCategories: 0, controlledCategories: 0, uncontrolledCategories: 0
       },
       controlledPct: 0,
@@ -105,16 +105,16 @@ export default {
       try {
         const d = await getChemicalStats()
         this.stats = {
-          totalAmount: d.totalAmount || 0,
-          controlledAmount: d.controlledAmount || 0,
-          uncontrolledAmount: d.uncontrolledAmount || 0,
-          totalCategories: d.totalCategories || 0,
-          controlledCategories: d.controlledCategories || 0,
-          uncontrolledCategories: d.uncontrolledCategories || 0
+          totalAmount: d.totalSurplus || 0,
+          unit: d.totalUnit || 'L',
+          controlledAmount: d.controlledSurplus || 0,
+          uncontrolledAmount: d.uncontrolledSurplus || 0,
+          totalCategories: d.totalCategoryCount || 0,
+          controlledCategories: d.controlledCategoryCount || 0,
+          uncontrolledCategories: d.uncontrolledCategoryCount || 0
         }
-        const total = this.stats.totalAmount || 1
-        this.controlledPct = Math.round(this.stats.controlledAmount / total * 1000) / 10
-        this.uncontrolledPct = Math.round(this.stats.uncontrolledAmount / total * 1000) / 10
+        this.controlledPct = d.controlledPercent || 0
+        this.uncontrolledPct = d.uncontrolledPercent || 0
       } catch (e) {
         console.error('ChemicalsStats:', e)
       }
@@ -151,7 +151,6 @@ export default {
   border-radius: 6px;
   display: flex;
   align-items: center;
-  padding: 0 14px;
   gap: 12px;
   overflow: hidden;
 
@@ -168,7 +167,7 @@ export default {
   flex-shrink: 0;
   width: 52px;
   height: 52px;
-
+  margin-left:14px;
   svg { width: 100%; height: 100%; }
 }
 
@@ -199,25 +198,25 @@ export default {
 }
 
 .chem-stat-value {
-  font-size: 22px;
+  font-size: 16px;
   font-weight: 700;
   line-height: 1;
   letter-spacing: 1px;
 
   .unit {
-    font-size: 11px;
+    font-size: 12px;
     font-weight: 400;
     color: #7eacc8;
   }
 }
 
 .chem-stat-label {
-  font-size: 11px;
+  font-size: 12px;
   color: #7eacc8;
 }
 
 .chem-stat-sub {
-  font-size: 10px;
+  font-size: 14px;
   color: rgba(126, 172, 200, 0.65);
 }
 </style>

+ 63 - 2
src/components/LabStats/RiskWarning.vue

@@ -7,12 +7,16 @@
       <div class="warning-header">
         <div class="warning-count">{{ totalMonth }}</div>
         <div class="warning-count-label">本月预警响应总数</div>
+        <div class="warning-sub-counts">
+          <span class="sub-count emergency">应急 {{ emergencyCount }}</span>
+          <span class="sub-count violation">违规带离 {{ violationCount }}</span>
+        </div>
       </div>
       <div class="warning-scroll-wrap" ref="scrollWrap" @mouseenter="paused=true" @mouseleave="paused=false">
         <div ref="scrollInner" class="warning-scroll-inner">
           <div class="warning-item" v-for="(item, idx) in displayList" :key="idx">
-            <div class="w-lab">{{ item.lab }} - {{ item.dept }}</div>
-            <div class="w-sensor">异常: {{ item.type }} {{ item.value }}</div>
+            <div class="w-lab">{{ item.lab }}</div>
+            <div class="w-sensor" :style="{ color: categoryColor(item.category) }">异常: {{ item.type }}</div>
             <div class="w-time">{{ item.time }}</div>
           </div>
         </div>
@@ -29,6 +33,8 @@ export default {
   data() {
     return {
       totalMonth: 0,
+      emergencyCount: 0,
+      violationCount: 0,
       list: [],
       paused: false,
       scrollTimer: null,
@@ -58,6 +64,8 @@ export default {
       try {
         const res = await getRiskWarningList()
         this.totalMonth = res.data.totalMonth
+        this.emergencyCount = res.data.emergencyCount
+        this.violationCount = res.data.violationCount
         this.list = res.data.list
         if (!this.scrollTimer) {
           this.$nextTick(() => setTimeout(() => this.startScroll(), 500))
@@ -66,6 +74,11 @@ export default {
         console.error('RiskWarning:', e)
       }
     },
+    categoryColor(category) {
+      if (category === '应急预警') return '#FFB020'
+      if (category === '违规带离') return '#A78BFA'
+      return '#FFB020'
+    },
     startScroll() {
       const wrap = this.$refs.scrollWrap
       const inner = this.$refs.scrollInner
@@ -123,6 +136,54 @@ export default {
   color: $text-secondary;
 }
 
+.warning-sub-counts {
+  margin-left: auto;
+  display: flex;
+  gap: 8px;
+}
+
+.sub-count {
+  font-size: 11px;
+  padding: 2px 8px;
+  border-radius: 10px;
+
+  &.emergency {
+    color: #FFB020;
+    background: rgba(255, 176, 32, 0.1);
+    border: 1px solid rgba(255, 176, 32, 0.3);
+  }
+
+  &.violation {
+    color: #A78BFA;
+    background: rgba(167, 139, 250, 0.1);
+    border: 1px solid rgba(167, 139, 250, 0.3);
+  }
+}
+
+.warning-sub-counts {
+  margin-left: auto;
+  display: flex;
+  gap: 8px;
+}
+
+.sub-count {
+  font-size: 11px;
+  padding: 2px 8px;
+  border-radius: 10px;
+
+  &.emergency {
+    color: #FFB020;
+    background: rgba(255, 176, 32, 0.12);
+    border: 1px solid rgba(255, 176, 32, 0.3);
+  }
+
+  &.violation {
+    color: #A78BFA;
+    background: rgba(167, 139, 250, 0.12);
+    border: 1px solid rgba(167, 139, 250, 0.3);
+  }
+}
+
 .warning-scroll-wrap {
   flex: 1;
   overflow: hidden;

+ 5 - 1
src/router/index.js

@@ -36,7 +36,11 @@ const router = new VueRouter({
 router.beforeEach((to, from, next) => {
   const token = localStorage.getItem('token')
   if (to.meta.requiresAuth && !token) {
-    next('/login')
+    if (to.path !== '/login') {
+      next('/login')
+    } else {
+      next()
+    }
   } else if (to.path === '/login' && token) {
     next('/lab-status')
   } else {