Procházet zdrojové kódy

feat: 添加 REM 适配大屏功能

yusheng před 2 měsíci
rodič
revize
e8b034c930
4 změnil soubory, kde provedl 296 přidání a 413 odebrání
  1. 1 0
      package.json
  2. 28 0
      src/main.js
  3. 251 413
      src/views/home/index.vue
  4. 16 0
      vue.config.js

+ 1 - 0
package.json

@@ -74,6 +74,7 @@
     "eslint-config-prettier": "^8.10.0",
     "eslint-plugin-prettier": "^4.2.1",
     "eslint-plugin-vue": "^9.4.0",
+    "postcss-pxtorem": "^6.1.0",
     "prettier": "^2.7.1",
     "sass": "^1.54.8",
     "sass-loader": "^13.0.2",

+ 28 - 0
src/main.js

@@ -24,6 +24,34 @@ Vue.component('virtual-scroller', VirtualScroller);
 import dataV from '@jiaminghi/data-view'
 
 import { all, create } from 'mathjs'; // 引入mathjs工具并初始化
+
+// REM 适配大屏 - 基于设计稿 1920px
+(function() {
+  function setRem() {
+    const baseSize = 192; // 基础值,设计稿宽度 / 10
+    const scale = document.documentElement.clientWidth / 1920;
+    // 限制最大缩放比例为 2 倍
+    const rem = baseSize * Math.min(scale, 2);
+    document.documentElement.style.fontSize = rem + 'px';
+    // 同时设置 data 属性,方便 CSS 中使用
+    document.documentElement.setAttribute('data-scale', Math.min(scale, 2).toFixed(4));
+  }
+
+  // 初始化
+  setRem();
+
+  // 防抖处理
+  let timer = null;
+  window.addEventListener('resize', function() {
+    if (timer) clearTimeout(timer);
+    timer = setTimeout(setRem, 100);
+  });
+
+  // 确保 DOM 加载完成后执行
+  if (document.readyState !== 'complete') {
+    window.addEventListener('load', setRem);
+  }
+})();
 // 注册全局自定义指令
 Vue.directive('click-once', clickOnce);
 Vue.directive('no-chinese', noChinese);

+ 251 - 413
src/views/home/index.vue

@@ -6,171 +6,169 @@
     fullscreenClass="box-container"
     :exit-on-click-wrapper="false"
   >
-    <div class="box-container" v-cloak>
-      <!-- 中间内容区域 - 可左右滚动,头部跟随 -->
-      <div class="box-content">
-        <div class="scroll-wrapper">
-          <!-- 头部区域 - 跟随滚动 -->
-          <div class="header-section">
-            <div class="box-header-scroll">
-              <div class="logo">
-                <el-select
-                  v-model="stationId"
-                  placeholder="请选择"
-                  class="custom-select"
-                  popper-class="custom-select-dropdown"
-                  @change="init"
-                >
-                  <el-option
-                    v-for="item in selectOptions"
-                    :key="item.value"
-                    :label="item.label"
-                    :value="item.value"
-                  />
-                </el-select>
-              </div>
-              <div class="header-center">
-                <div class="title">生产管控</div>
-              </div>
-              <div class="time">
-                <div class="time-display">
-                  <span class="date-text">{{ date }}</span>
-                  <span class="time-text">{{ time }}</span>
-                </div>
-                <span class="fullscreen-toggle" @click.passive="onFullscreen">
-                  <i
-                    v-if="isFullscreen"
-                    title="取消全屏"
-                    class="el-icon-_screen-restore"
-                  />
-                  <i v-else title="全屏" class="el-icon-_screen-full" />
-                </span>
+    <!-- 中间内容区域 - 可左右滚动,头部跟随 -->
+    <div class="box-content">
+      <div class="scroll-wrapper">
+        <!-- 头部区域 - 跟随滚动 -->
+        <div class="header-section">
+          <div class="box-header-scroll">
+            <div class="logo">
+              <el-select
+                v-model="stationId"
+                placeholder="请选择"
+                class="custom-select"
+                popper-class="custom-select-dropdown"
+                @change="init"
+              >
+                <el-option
+                  v-for="item in selectOptions"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.value"
+                />
+              </el-select>
+            </div>
+            <div class="header-center">
+              <div class="title">生产管控</div>
+            </div>
+            <div class="time">
+              <div class="time-display">
+                <span class="date-text">{{ date }}</span>
+                <span class="time-text">{{ time }}</span>
               </div>
+              <span class="fullscreen-toggle" @click.passive="onFullscreen">
+                <i
+                  v-if="isFullscreen"
+                  title="取消全屏"
+                  class="el-icon-_screen-restore"
+                />
+                <i v-else title="全屏" class="el-icon-_screen-full" />
+              </span>
             </div>
           </div>
+        </div>
 
-          <!-- 双栏布局区域 -->
-          <div class="two-column-layout">
-            <!-- 左侧区域 -->
-            <div class="left-section">
-              <!-- 综合数据 -->
-              <div class="panel data-panel">
-                <div class="panel-title">
-                  <div class="panel-icon"></div>
-                  综合数据
-                </div>
-                <div
-                  style="
-                    display: flex;
-                    flex: 1;
-                    align-items: center;
-                    justify-content: center;
-                  "
-                >
-                  <div class="data-grid">
-                    <div
-                      class="data-item"
-                      v-for="(item, index) in comprehensiveList"
-                      :key="index"
+        <!-- 双栏布局区域 -->
+        <div class="two-column-layout">
+          <!-- 左侧区域 -->
+          <div class="left-section">
+            <!-- 综合数据 -->
+            <div class="panel data-panel">
+              <div class="panel-title">
+                <div class="panel-icon"></div>
+                综合数据
+              </div>
+              <div
+                style="
+                  display: flex;
+                  flex: 1;
+                  align-items: center;
+                  justify-content: center;
+                "
+              >
+                <div class="data-grid">
+                  <div
+                    class="data-item"
+                    v-for="(item, index) in comprehensiveList"
+                    :key="index"
+                  >
+                    <div class="img"></div>
+                    <div class="data-item_value">
+                      <span class="data-label">{{ item.label }}</span>
+                      <span class="data-value">{{ item.value }}</span></div
                     >
-                      <div class="img"></div>
-                      <div class="data-item_value">
-                        <span class="data-label">{{ item.label }}</span>
-                        <span class="data-value">{{ item.value }}</span></div
-                      >
-                    </div>
                   </div>
                 </div>
               </div>
+            </div>
 
-              <!-- 区域用能对比 -->
-              <div class="panel chart-panel" style="position: relative">
-                <div class="panel-title energy-title">
-                  <div class="title-left">
-                    <div class="panel-icon"></div>
-                    用水用煤趋势图
-                  </div>
-                </div>
-                <div class="energy-tabs">
-                  <span
-                    v-for="tab in energyTabs"
-                    :key="tab.value"
-                    :class="[
-                      'tab-item',
-                      { active: activeEnergyTab === tab.value }
-                    ]"
-                    @click="energyTabsCahnge(tab.value)"
-                  >
-                    {{ tab.label }}
-                  </span>
+            <!-- 区域用能对比 -->
+            <div class="panel chart-panel" style="position: relative">
+              <div class="panel-title energy-title">
+                <div class="title-left">
+                  <div class="panel-icon"></div>
+                  用水用煤趋势图
                 </div>
-                <div class="chart-container" ref="waterChart"></div>
               </div>
-
-              <!-- 区域能耗对比 -->
-              <div class="panel chart-panel">
-                <div class="panel-title energy-title">
-                  <div class="title-left">
-                    <div class="panel-icon"></div>
-                    固废量趋势图
-                  </div>
-                </div>
-                <div class="chart-container" ref="returnChart"></div>
+              <div class="energy-tabs">
+                <span
+                  v-for="tab in energyTabs"
+                  :key="tab.value"
+                  :class="[
+                    'tab-item',
+                    { active: activeEnergyTab === tab.value }
+                  ]"
+                  @click="energyTabsCahnge(tab.value)"
+                >
+                  {{ tab.label }}
+                </span>
               </div>
+              <div class="chart-container" ref="waterChart"></div>
             </div>
 
-            <!-- 右侧区域 -->
-            <div class="right-section">
-              <!-- 告警数据统计 -->
-              <div class="panel alert-panel">
-                <div class="panel-title">
+            <!-- 区域能耗对比 -->
+            <div class="panel chart-panel">
+              <div class="panel-title energy-title">
+                <div class="title-left">
                   <div class="panel-icon"></div>
-                  告警数据概览
+                  固废量趋势图
                 </div>
-                <div class="alert-stats">
-                  <!-- 左侧数据卡片 -->
-                  <div class="alert-cards">
-                    <div
-                      class="alert-card-item"
-                      v-for="(item, index) in alertStatsData"
-                      :key="index"
+              </div>
+              <div class="chart-container" ref="returnChart"></div>
+            </div>
+          </div>
+
+          <!-- 右侧区域 -->
+          <div class="right-section">
+            <!-- 告警数据统计 -->
+            <div class="panel alert-panel">
+              <div class="panel-title">
+                <div class="panel-icon"></div>
+                告警数据概览
+              </div>
+              <div class="alert-stats">
+                <!-- 左侧数据卡片 -->
+                <div class="alert-cards">
+                  <div
+                    class="alert-card-item"
+                    v-for="(item, index) in alertStatsData"
+                    :key="index"
+                  >
+                    <div class="img"></div>
+                    <div class="data-item_value">
+                      <span class="data-label">{{ item.label }}</span>
+                      <span class="data-value">{{ item.value }}</span></div
                     >
-                      <div class="img"></div>
-                      <div class="data-item_value">
-                        <span class="data-label">{{ item.label }}</span>
-                        <span class="data-value">{{ item.value }}</span></div
-                      >
-                    </div>
-                  </div>
-                  <!-- 右侧环形图 -->
-                  <div class="alert-pie-chart">
-                    <div class="alert-pie" ref="alertPieChart"></div>
                   </div>
                 </div>
+                <!-- 右侧环形图 -->
+                <div class="alert-pie-chart">
+                  <div class="alert-pie" ref="alertPieChart"></div>
+                </div>
               </div>
+            </div>
 
-              <!-- 告警列表 -->
-              <div class="panel alert-list-panel">
-                <div class="panel-title">
-                  <div class="panel-icon"></div>
-                  告警列表
-                </div>
-                <div class="alert-table">
-                  <dv-scroll-board
-                    :config="alertConfig"
-                    style="width: 100%; height: calc(100% - 40px)"
-                  />
-                </div>
+            <!-- 告警列表 -->
+            <div class="panel alert-list-panel">
+              <div class="panel-title">
+                <div class="panel-icon"></div>
+                告警列表
+              </div>
+              <div class="alert-table">
+                <dv-scroll-board
+                  :config="alertConfig"
+                  style="width: 100%; height: calc(100% - 40px)"
+                />
               </div>
+            </div>
 
-              <!-- 设备告警趋势图 -->
-              <div class="panel chart-panel">
-                <div class="panel-title">
-                  <div class="panel-icon"></div>
-                  设备告警趋势图
-                </div>
-                <div class="chart-container" ref="alertTrendChart"></div>
+            <!-- 设备告警趋势图 -->
+            <div class="panel chart-panel">
+              <div class="panel-title">
+                <div class="panel-icon"></div>
+                设备告警趋势图
               </div>
+              <div class="chart-container" ref="alertTrendChart"></div>
             </div>
           </div>
         </div>
@@ -247,9 +245,9 @@
     },
     watch: {
       isFullscreen: {
-        handler() {
-          this.handleResize();
-        },
+        // handler() {
+        //   this.handleResize();
+        // },
         immediate: true
       }
     },
@@ -272,15 +270,15 @@
     mounted() {
       this.updateTimer = setInterval(this.updateTime, 1000);
 
-      window.addEventListener('resize', this.handleResize);
+      // window.addEventListener('resize', this.handleResize);
       // 初始化时同步头部宽度
-      this.$nextTick(() => {
-        this.syncHeaderWidth();
-      });
+      // this.$nextTick(() => {
+      //   this.syncHeaderWidth();
+      // });
     },
     beforeDestroy() {
       clearInterval(this.updateTimer);
-      window.removeEventListener('resize', this.handleResize);
+      // window.removeEventListener('resize', this.handleResize);
       Object.values(this.charts).forEach((chart) => chart && chart.dispose());
     },
     methods: {
@@ -481,38 +479,38 @@
         const day = now.getDate().toString().padStart(2, '0');
         this.date = `${year}-${month}-${day}`;
       },
-      syncHeaderWidth() {
-        this.$nextTick(() => {
-          const threeColumnLayout =
-            document.querySelector('.two-column-layout');
-          const headerSection = document.querySelector('.header-section');
-          if (threeColumnLayout && headerSection) {
-            const layoutWidth = threeColumnLayout.scrollWidth;
-            headerSection.style.width = layoutWidth + 'px';
-          }
-        });
-      },
-      handleResize() {
-        this.$nextTick(() => {
-          // 同步头部宽度
-          this.syncHeaderWidth();
-
-          const { clientWidth, clientHeight } = document.documentElement;
-          const containers = document.getElementsByClassName('box-container');
-          Array.from(containers).forEach((item) => {
-            if (this.isFullscreen) {
-              item.style.height = clientHeight + 'px';
-              item.style.width = clientWidth + 'px';
-            } else {
-              item.style.height = clientHeight - 100 + 'px';
-              item.style.width = clientWidth - 240 + 'px';
-            }
-          });
-          Object.values(this.charts).forEach(
-            (chart) => chart && chart.resize()
-          );
-        });
-      },
+      // syncHeaderWidth() {
+      //   this.$nextTick(() => {
+      //     const threeColumnLayout =
+      //       document.querySelector('.two-column-layout');
+      //     const headerSection = document.querySelector('.header-section');
+      //     if (threeColumnLayout && headerSection) {
+      //       const layoutWidth = threeColumnLayout.scrollWidth;
+      //       headerSection.style.width = layoutWidth + 'px';
+      //     }
+      //   });
+      // },
+      // handleResize() {
+      //   this.$nextTick(() => {
+      //     // 同步头部宽度
+      //     this.syncHeaderWidth();
+
+      //     const { clientWidth, clientHeight } = document.documentElement;
+      //     const containers = document.getElementsByClassName('box-container');
+      //     Array.from(containers).forEach((item) => {
+      //       if (this.isFullscreen) {
+      //         item.style.height = clientHeight + 'px';
+      //         item.style.width = clientWidth + 'px';
+      //       } else {
+      //         item.style.height = clientHeight - 100 + 'px';
+      //         item.style.width = clientWidth - 240 + 'px';
+      //       }
+      //     });
+      //     Object.values(this.charts).forEach(
+      //       (chart) => chart && chart.resize()
+      //     );
+      //   });
+      // },
 
       initWaterChart(res) {
         if (!this.$refs.waterChart) return;
@@ -832,33 +830,32 @@
 
 <style lang="scss" scoped>
   .box-container {
-    width: 100vw;
-    height: 100vh;
+    // width: 100vw;
+    height: 100%;
 
     .box-header-scroll {
-      height: 80px;
+      height: 0.417rem;
       background: url('~@/assets/pcs/header.png') no-repeat center top;
       background-size: 100% 100%;
       display: flex;
       align-items: center;
       justify-content: center;
-      padding: 0 20px;
+      padding: 0 0.104rem;
       position: relative;
       z-index: 10;
 
       .logo {
-        // width: 200px;
-        padding-top: 10px;
+        padding-top: 0.052rem;
         position: absolute;
-        left: 80px;
+        left: 0.417rem;
 
         ::v-deep .custom-select {
           .el-input__inner {
             background: #0d2960;
             border: 1px solid #1a4a8a;
             color: #fff;
-            height: 36px;
-            line-height: 36px;
+            height: 0.188rem;
+            line-height: 0.188rem;
 
             &::placeholder {
               color: #8ba3c7;
@@ -876,21 +873,22 @@
       .title {
         flex: 1;
         text-align: center;
-        font-size: 28px;
+        font-size: 0.146rem;
+        margin-bottom: 0.14rem;
         font-weight: bold;
         color: #fff;
-        text-shadow: 0 0 10px rgba(59, 130, 246, 0.5);
-        letter-spacing: 4px;
+        text-shadow: 0 0 0.052rem rgba(59, 130, 246, 0.5);
+        letter-spacing: 0.021rem;
       }
 
       .time {
         position: absolute;
-        right: 30px;
-        width: 280px;
+        right: 0.156rem;
+        width: 1.458rem;
         display: flex;
         align-items: center;
         justify-content: flex-end;
-        gap: 15px;
+        gap: 0.078rem;
 
         .time-display {
           display: flex;
@@ -898,12 +896,12 @@
           align-items: flex-end;
 
           .date-text {
-            font-size: 14px;
+            font-size: 0.073rem;
             color: #8ba3c7;
           }
 
           .time-text {
-            font-size: 20px;
+            font-size: 0.104rem;
             font-weight: bold;
             color: #fff;
           }
@@ -911,7 +909,7 @@
 
         .fullscreen-toggle {
           cursor: pointer;
-          font-size: 20px;
+          font-size: 0.104rem;
           color: #8ba3c7;
           transition: color 0.3s;
 
@@ -938,11 +936,9 @@
       overflow: auto;
       font-family: 'Microsoft YaHei', sans-serif;
       flex: 1;
-      // overflow-x: auto;
-      // overflow-y: hidden;
 
       &::-webkit-scrollbar {
-        height: 6px;
+        height: 0.031rem;
       }
 
       &::-webkit-scrollbar-track {
@@ -951,21 +947,17 @@
 
       &::-webkit-scrollbar-thumb {
         background: linear-gradient(180deg, #1a4a8a, #0d2a5a);
-        border-radius: 3px;
+        border-radius: 0.016rem;
       }
 
       .scroll-wrapper {
-        // display: flex;
         display: inline-block;
         height: 100%;
-        // flex-direction: column;
-        // gap: 20px;
-        // padding: 0 20px 20px 20px;
         width: 100%;
         .header-section {
           width: auto;
           flex-shrink: 0;
-          padding-top: 10px;
+          padding-top: 0.052rem;
           min-width: 100%;
         }
 
@@ -973,10 +965,10 @@
           display: flex;
           justify-content: space-between;
           flex: 1;
-          min-height: 850px;
-          height: calc(100% - 130px);
+          min-height: 4.427rem;
+          height: calc(100% - 0.677rem);
           min-width: 100%;
-          margin-top: 20px;
+          margin-top: 0.104rem;
           font-size: 0;
           background: url('~@/assets/pcs/back.png') no-repeat center top;
           background-size: 100% 100%;
@@ -987,14 +979,14 @@
       .right-section {
         display: inline-flex;
         flex-direction: column;
-        gap: 15px;
+        gap: 0.078rem;
         overflow: hidden;
         height: 100%;
-        font-size: 14px;
+        font-size: 0.073rem;
         white-space: normal;
         min-width: 45%;
         flex: 1;
-        margin-right: 20px;
+        margin-right: 0.104rem;
 
         &:last-child {
           margin-right: 0;
@@ -1002,27 +994,16 @@
       }
 
       .panel {
-        // background: linear-gradient(
-        //   135deg,
-        //   rgba(16, 42, 88, 0.9) 0%,
-        //   rgba(10, 28, 65, 0.85) 100%
-        // );
-        // border: 1px solid rgba(42, 90, 170, 0.4);
-        // border-radius: 8px;
-        padding: 15px;
+        padding: 0.078rem;
         min-height: 0;
-        // box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05),
-        //   0 4px 20px rgba(0, 0, 0, 0.3);
 
         .panel-title {
-          font-size: 28px;
-          // font-weight: bold;
-          // font-style: italic;
+          font-size: 0.146rem;
           font-family: 'YouSheBiaoTiHei', 'Microsoft YaHei', sans-serif;
           color: #fff;
-          margin-bottom: 15px;
-          height: 42px;
-          padding-left: 40px;
+          margin-bottom: 0.078rem;
+          height: 0.219rem;
+          padding-left: 0.208rem;
           position: relative;
           display: flex;
           align-items: center;
@@ -1032,40 +1013,40 @@
           &.energy-title {
             display: flex;
             justify-content: space-between;
-            padding-right: 15px;
+            padding-right: 0.078rem;
 
             .title-left {
               display: flex;
               align-items: center;
-              gap: 8px;
+              gap: 0.042rem;
             }
           }
           .panel-icon {
             position: absolute;
-            left: 15px;
-            width: 20px;
-            height: 25px;
+            left: 0.078rem;
+            width: 0.104rem;
+            height: 0.13rem;
             background: url('~@/assets/pcs/titleIcon.png') no-repeat center top;
             background-size: 100% 100%;
           }
         }
         .energy-tabs {
           position: absolute;
-          top: 65px;
-          right: 40px;
+          top: 0.339rem;
+          right: 0.208rem;
           z-index: 999;
           display: flex;
           gap: 0;
           background: rgba(13, 41, 96, 0.5);
-          border-radius: 4px;
-          padding: 2px;
+          border-radius: 0.021rem;
+          padding: 0.01rem;
 
           .tab-item {
-            padding: 4px 12px;
-            font-size: 12px;
+            padding: 0.021rem 0.063rem;
+            font-size: 0.063rem;
             color: #8ba3c7;
             cursor: pointer;
-            border-radius: 3px;
+            border-radius: 0.016rem;
             transition: all 0.3s;
 
             &:hover {
@@ -1081,7 +1062,7 @@
       }
 
       .data-panel {
-        min-height: 220px;
+        min-height: 1.146rem;
         flex-shrink: 0;
         display: flex;
         flex-direction: column;
@@ -1093,9 +1074,7 @@
 
         .data-grid {
           display: flex;
-
-          gap: 12px;
-          // padding: 10px 0;
+          gap: 0.063rem;
           align-items: center;
           justify-content: space-between;
           flex-wrap: wrap;
@@ -1103,65 +1082,40 @@
           height: 100%;
 
           .data-item {
-            // background: linear-gradient(
-            //   135deg,
-            //   rgba(20, 50, 105, 0.9) 0%,
-            //   rgba(14, 38, 82, 0.85) 100%
-            // );
-            // border: 1px solid rgba(45, 95, 180, 0.5);
             .img {
-              width: 35px;
-              height: 35px;
+              width: 0.182rem;
+              height: 0.182rem;
               background: url('~@/assets/pcs/icon.png') no-repeat center top;
               background-size: 100% 100%;
             }
-            border-radius: 6px;
+            border-radius: 0.031rem;
             display: flex;
             .data-item_value {
               display: flex;
               flex-direction: column;
-              // align-items: center;
             }
-            // flex-direction: column;
             align-items: center;
-            // justify-content: center;
-            padding-left: 15px;
-            gap: 8px;
+            padding-left: 0.078rem;
+            gap: 0.042rem;
             position: relative;
             overflow: hidden;
             width: 21%;
-            height: 60px;
+            height: 0.313rem;
             background: url('~@/assets/pcs/leftItem.png') no-repeat center top;
             background-size: 100% 100%;
 
-            // &::before {
-            //   content: '';
-            //   position: absolute;
-            //   top: 0;
-            //   left: 0;
-            //   right: 0;
-            //   height: 2px;
-            //   background: linear-gradient(
-            //     90deg,
-            //     transparent,
-            //     #00d4ff,
-            //     transparent
-            //   );
-            //   box-shadow: 0 0 8px rgba(0, 212, 255, 0.6);
-            // }
-
             .data-label {
-              font-size: 12px;
+              font-size: 0.063rem;
               color: #8ba3c7;
               text-align: center;
               line-height: 1.3;
             }
 
             .data-value {
-              font-size: 18px;
+              font-size: 0.094rem;
               font-weight: bold;
               color: #b6ceff;
-              text-shadow: 0 0 10px rgba(0, 212, 255, 0.5);
+              text-shadow: 0 0 0.052rem rgba(0, 212, 255, 0.5);
             }
           }
         }
@@ -1169,7 +1123,7 @@
 
       .chart-panel {
         flex: 1;
-        min-height: 250px;
+        min-height: 1.302rem;
         display: flex;
         flex-direction: column;
 
@@ -1179,96 +1133,9 @@
           min-height: 0;
         }
       }
-      .param-card3 {
-        right: 10px;
-      }
-      .param-card2 {
-        left: 30%;
-      }
-      .param-card {
-        width: 23%;
-        top: 50px;
-
-        position: absolute;
-        background: rgba(39, 88, 233, 0.1);
-        border: 1px solid #3373d4;
-        border-radius: 8px;
-
-        &::before {
-          content: '';
-          position: absolute;
-          top: 0;
-          left: 0;
-          right: 0;
-          height: 2px;
-          background: linear-gradient(90deg, transparent, #00d4ff, transparent);
-          box-shadow: 0 0 8px rgba(0, 212, 255, 0.5);
-        }
-
-        .param-title {
-          font-size: 14px;
-          font-weight: bold;
-          color: #fff;
-          padding-bottom: 12px;
-          padding-top: 12px;
-          text-align: center;
-          text-shadow: 0 0 10px rgba(0, 212, 255, 0.3);
-          border-bottom: 1px solid rgba(0, 212, 255, 0.5);
-          background: rgba(39, 88, 233, 0.1);
-        }
-
-        .param-list {
-          padding: 15px;
-
-          display: flex;
-          flex-direction: column;
-          gap: 10px;
-
-          .param-item {
-            display: flex;
-            justify-content: space-between;
-            font-size: 12px;
-            padding: 4px 0;
-            // border-bottom: 1px dashed rgba(138, 163, 199, 0.2);
-
-            &:last-child {
-              border-bottom: none;
-            }
-
-            .param-name {
-              color: #8ba3c7;
-            }
-
-            .param-value {
-              color: #fff;
-              font-weight: 500;
-            }
-          }
-        }
-      }
-
-      .pipeline-container {
-        flex: 1;
-        min-height: 0;
-        position: absolute;
-        bottom: 15px;
-        left: 0;
-        height: 60%;
-        width: 100%;
-        // background: linear-gradient(
-        //   135deg,
-        //   rgba(14, 40, 85, 0.6) 0%,
-        //   rgba(10, 28, 60, 0.5) 100%
-        // );
-        // border: 1px solid rgba(45, 95, 180, 0.3);
-        // border-radius: 8px;
-        background: url('~@/assets/pcs/home.png') no-repeat center top;
-        background-size: 100% 100%;
-        // max-height: 680px;
-      }
 
       .alert-panel {
-        min-height: 220px;
+        min-height: 1.146rem;
         flex-shrink: 0;
         display: flex;
         flex-direction: column;
@@ -1283,10 +1150,8 @@
           min-height: 0;
           display: flex;
           align-items: center;
-          height: calc(100% - 35px);
-          // gap: 20px;
+          height: calc(100% - 0.182rem);
 
-          // 左侧数据卡片区域
           .alert-cards {
             width: 50%;
             height: 100%;
@@ -1297,70 +1162,43 @@
 
             .alert-card-item {
               width: 42%;
-              // background: linear-gradient(
-              //   135deg,
-              //   rgba(20, 50, 105, 0.9) 0%,
-              //   rgba(14, 38, 82, 0.85) 100%
-              // );
-              // border: 1px solid rgba(45, 95, 180, 0.5);
               .img {
-                width: 35px;
-                height: 35px;
+                width: 0.182rem;
+                height: 0.182rem;
                 background: url('~@/assets/pcs/icon.png') no-repeat center top;
                 background-size: 100% 100%;
-                margin-right: 15px;
+                margin-right: 0.078rem;
               }
-              border-radius: 6px;
+              border-radius: 0.031rem;
               display: flex;
               .data-item_value {
                 display: flex;
                 flex-direction: column;
-                // align-items: center;
               }
-              // flex-direction: column;
               align-items: center;
-              // justify-content: center;
-              padding-left: 15px;
-              // gap: 8px;
+              padding-left: 0.078rem;
               position: relative;
               overflow: hidden;
               height: 30%;
               background: url('~@/assets/pcs/leftItem.png') no-repeat center top;
               background-size: 100% 100%;
 
-              // &::before {
-              //   content: '';
-              //   position: absolute;
-              //   top: 0;
-              //   left: 0;
-              //   right: 0;
-              //   height: 2px;
-              //   background: linear-gradient(
-              //     90deg,
-              //     transparent,
-              //     #00d4ff,
-              //     transparent
-              //   );
-              //   box-shadow: 0 0 8px rgba(0, 212, 255, 0.6);
-              // }
-
               .data-label {
-                font-size: 12px;
+                font-size: 0.063rem;
                 color: #8ba3c7;
                 text-align: center;
                 line-height: 1.3;
               }
 
               .data-value {
-                font-size: 18px;
+                font-size: 0.094rem;
                 font-weight: bold;
                 color: #b6ceff;
-                text-shadow: 0 0 10px rgba(0, 212, 255, 0.5);
+                text-shadow: 0 0 0.052rem rgba(0, 212, 255, 0.5);
               }
             }
           }
 
-          // 右侧环形图区域
           .alert-pie-chart {
             width: 50%;
             height: 100%;
@@ -1372,7 +1210,7 @@
             .alert-pie {
               width: 100%;
               height: 100%;
-              min-height: 180px;
+              min-height: 0.938rem;
             }
           }
         }
@@ -1383,7 +1221,7 @@
         min-height: 0;
         display: flex;
         flex-direction: column;
-        min-height: 250px;
+        min-height: 1.302rem;
 
         .alert-table {
           flex: 1;
@@ -1392,15 +1230,15 @@
 
           .table-header {
             display: grid;
-            grid-template-columns: 50px 90px 100px 70px 1fr 130px 70px;
-            gap: 6px;
-            padding: 10px 6px;
+            grid-template-columns: 0.26rem 0.469rem 0.521rem 0.365rem 1fr 0.677rem 0.365rem;
+            gap: 0.031rem;
+            padding: 0.052rem 0.031rem;
             background: linear-gradient(
               90deg,
               rgba(16, 45, 95, 0.9) 0%,
               rgba(12, 35, 75, 0.85) 100%
             );
-            font-size: 12px;
+            font-size: 0.063rem;
             color: #00d4ff;
             text-align: center;
             font-weight: 500;

+ 16 - 0
vue.config.js

@@ -93,6 +93,22 @@ module.exports = {
           outputStyle: 'expanded',
           importer: transformElementScss()
         }
+      },
+      postcss: {
+        postcssOptions: {
+          plugins: [
+            require('postcss-pxtorem')({
+              rootValue: 192, // 设计稿宽度 / 10,如设计稿宽度为 1920px,则 rootValue 为 192
+              unitPrecision: 5, // 转换后的小数精度
+              propList: ['*'], // 需要转换的属性,* 表示全部
+              selectorBlackList: ['.el-', '.dv-', '.data-'], // 不需要转换的选择器(排除第三方组件)
+              replace: true, // 是否替换
+              mediaQuery: false, // 是否转换媒体查询中的像素值
+              minPixelValue: 2, // 小于或等于 2px 不转换
+              exclude: /(^@\/views\/home\/|node_modules)/i // 只转换 views/home 目录(大屏页面)
+            })
+          ]
+        }
       }
     }
   }