Explorar el Código

Merge branch 'dev' into test

hans hace 1 mes
padre
commit
3c0209d9e5
Se han modificado 3 ficheros con 1507 adiciones y 118 borrados
  1. 62 0
      src/views/home/data.js
  2. 66 118
      src/views/home/index.vue
  3. 1379 0
      src/views/home/indexDynamic.vue

+ 62 - 0
src/views/home/data.js

@@ -451,3 +451,65 @@ export const pieOptions = (data) => {
     ]
   };
 };
+
+// ==================== 首页大屏静态数据 ====================
+// 数据来源:五品四数.xlsx(各分厂生产指标 + 1-12月工单入库数量)
+// metrics 顺序:计划数、投入数、产出数、在制品数、合格品数
+// defective 顺序:返工品、返修品、废品
+// inWarehouse 顺序:1月 ~ 12月
+
+export const monthLabels = [
+  '一月',
+  '二月',
+  '三月',
+  '四月',
+  '五月',
+  '六月',
+  '七月',
+  '八月',
+  '九月',
+  '十月',
+  '十一月',
+  '十二月'
+];
+
+// 工厂(分厂)切换选项
+export const factoryOptions = [
+  { id: '1', name: '机加一分厂' },
+  { id: '2', name: '机加二分厂' },
+  { id: '3', name: '特种作业分厂' },
+  { id: '4', name: '总装分厂' }
+];
+
+export const mesStaticData = {
+  // 机加一分厂
+  1: {
+    metrics: [24386, 20500, 9412, 10730, 8630],
+    defective: [314, 113, 355],
+    inWarehouse: [1030, 1058, 1098, 1073, 1104, 1093, 1055, 1046, 500, 0, 0, 0]
+  },
+  // 机加二分厂
+  2: {
+    metrics: [19828, 17700, 8461, 8616, 7840],
+    defective: [230, 102, 289],
+    inWarehouse: [960, 983, 971, 969, 978, 975, 982, 950, 400, 0, 0, 0]
+  },
+  // 特种作业分厂
+  3: {
+    metrics: [10256, 9000, 4840, 4080, 4535],
+    defective: [35, 0, 270],
+    inWarehouse: [550, 538, 544, 552, 546, 540, 551, 547, 202, 0, 0, 0]
+  },
+  // 总装分厂(返修数、1月入库数原表为空,按 0 处理)
+  4: {
+    metrics: [3600, 2600, 1530, 980, 1452],
+    defective: [18, 0, 60],
+    inWarehouse: [0, 33, 230, 220, 225, 212, 240, 223, 87, 0, 0, 0]
+  },
+  // 企业合计
+  ALL: {
+    metrics: [58070, 49800, 24243, 24406, 22457],
+    defective: [597, 215, 974],
+    inWarehouse: [2540, 2612, 2843, 2814, 2853, 2820, 2828, 2766, 1189, 0, 0, 0]
+  }
+};

+ 66 - 118
src/views/home/index.vue

@@ -84,7 +84,7 @@
         <el-col :xs="24" :sm="24" :md="8" :lg="8" :xl="7" class="side-col">
           <el-card class="box-card screen-panel pie-panel">
             <div slot="header" class="clearfix panel-header">
-              <span>不良品分布图</span>
+              <span>不合格品分布图: {{ defectiveTotal }}</span>
             </div>
             <v-chart ref="pieRef" class="screen-chart" :option="pieOptions" />
           </el-card>
@@ -111,10 +111,18 @@
 </template>
 <script>
   import dictMixins from '@/mixins/dictMixins';
-  import { pieOption, barOption, columns, pieOptions } from './data';
+  import {
+    pieOption,
+    barOption,
+    columns,
+    pieOptions,
+    factoryOptions,
+    monthLabels,
+    mesStaticData
+  } from './data';
   import { use } from 'echarts/core';
   import { CanvasRenderer } from 'echarts/renderers';
-  import { BarChart, PieChart, LineChart } from 'echarts/charts';
+  import { BarChart, PieChart } from 'echarts/charts';
   import {
     GridComponent,
     TooltipComponent,
@@ -122,14 +130,7 @@
   } from 'echarts/components';
   import VChart from 'vue-echarts';
   import { echartsMixin } from '@/utils/echarts-mixin';
-  import {
-    getCount,
-    getCompletionCount,
-    getOrderList,
-    queryProportionDefectiveTypes
-  } from '@/api/mes/index';
-
-  import { getAllFactory } from '@/api/aps/index.js';
+  import { getOrderList } from '@/api/mes/index';
 
   // 按需加载 echarts
   use([
@@ -138,8 +139,7 @@
     PieChart,
     GridComponent,
     TooltipComponent,
-    LegendComponent,
-    LineChart
+    LegendComponent
   ]);
   export default {
     mixins: [dictMixins, echartsMixin(['pieRef', 'barRef'])],
@@ -149,32 +149,32 @@
         columns,
         arr: [
           {
-            name: '生产总数',
+            name: '计划数',
             num: '',
             imgUrl: require('../../assets/Group1.png'),
             unit: ''
           },
           {
-            name: '待生产数量',
+            name: '投入数',
             num: '',
             imgUrl: require('../../assets/Group2.png'),
             unit: ''
           },
           {
-            name: '已完成数量',
+            name: '产出数',
             num: '',
             imgUrl: require('../../assets/Group3.png'),
             unit: ''
           },
           {
-            name: '生产中数量',
+            name: '在制品数',
             num: '',
             imgUrl: require('../../assets/Group4.png'),
             unit: '',
             color: '#f97876'
           },
           {
-            name: '已延期',
+            name: '合格品数',
             num: '',
             imgUrl: require('../../assets/Group2.png'),
             unit: ''
@@ -196,8 +196,8 @@
           createTimeStart: '',
           createTimeEnd: ''
         },
-        // 工厂列表
-        factoryList: [],
+        // 工厂列表(静态)
+        factoryList: [...factoryOptions],
         pickerOptions: {
           shortcuts: [
             {
@@ -227,6 +227,19 @@
         }
       };
     },
+    computed: {
+      // 当前静态数据的 key:企业模式取合计,工厂模式取选中分厂
+      currentDataKey() {
+        return this.form.timeType === '2' && this.params.factoryId
+          ? this.params.factoryId
+          : 'ALL';
+      },
+      // 不合格品总数(当前模式/分厂口径)
+      defectiveTotal() {
+        const data = mesStaticData[this.currentDataKey] || mesStaticData.ALL;
+        return data.defective.reduce((sum, num) => sum + num, 0);
+      }
+    },
     watch: {
       params: {
         deep: true,
@@ -246,9 +259,7 @@
             this.params.createTimeEnd = '';
           }
 
-          this.getCount();
-          this.getCompletionCount();
-          this.proportion();
+          this.applyStaticData();
           this.$nextTick(() => {
             this.$refs.table.reload();
           });
@@ -275,128 +286,65 @@
       );
       this.params.createTimeEnd = this.$util.toDateString(endOfYear, 'yyyy-MM');
 
-      this.getCount();
-      this.getCompletionCount();
-      this.proportion();
+      this.applyStaticData();
     },
     mounted() {
-      this.getFactoryList();
       setTimeout(() => {
         this.$refs.barRef.resize();
         this.$refs.pieRef.resize();
       }, 300);
     },
     methods: {
-      async getFactoryList() {
-        const res = await getAllFactory();
-        this.factoryList = res;
-      },
-      async proportion() {
-        const res = await queryProportionDefectiveTypes(
-          `?factoryId=${this.params.factoryId || ''}&createTimeStart=${
-            this.params.createTimeStart
-          }&createTimeEnd=${this.params.createTimeEnd}`
-        );
-        let list = res.map((el) => {
-          return {
-            value: el.unQualifiedNumber,
-            name: el.categoryLevelClassName
-          };
-        });
-        this.pieOptions = pieOptions(list);
-      },
-      datasource({ page, where, limit }) {
-        return getOrderList({
-          ...where,
-          pageNum: page,
-          size: limit,
-          createTimeStart: this.params.createTimeStart,
-          createTimeEnd: this.params.createTimeEnd,
-          factoryId: this.params.factoryId || null
-        });
-      },
-      timeTypeChange() {
-        // 重置工厂选择
-        this.params.factoryId = '';
-      },
-      //首页统计
-      async getCount() {
-        let rest = await getCount({
-          factoryId: this.params.factoryId || null,
-          createTimeStart: this.params.createTimeStart,
-          createTimeEnd: this.params.createTimeEnd
-        });
+      // 应用静态数据:顶部指标 + 不合格品分布 + 工单完成统计
+      applyStaticData() {
+        const data = mesStaticData[this.currentDataKey] || mesStaticData.ALL;
+
+        // 顶部五个指标(顺序:计划数、投入数、产出数、在制品数、合格品数)
         this.arr.forEach((item, index) => {
-          if (item.name === '生产总数') {
-            item.num = rest.formingNum ? Number(rest.formingNum).toFixed(2) : 0;
-          } else if (item.name === '待生产数量') {
-            item.num = rest.pendingProductionCount
-              ? Number(rest.pendingProductionCount).toFixed(2)
-              : 0;
-          } else if (item.name === '已完成数量') {
-            item.num = rest.formedNum ? Number(rest.formedNum).toFixed(2) : 0;
-          } else if (item.name === '生产中数量') {
-            item.num = rest.inProgressWorkOrderCount
-              ? Number(rest.inProgressWorkOrderCount).toFixed(2)
-              : 0;
-          } else if (item.name === '已延期') {
-            item.num = rest.postponeCount
-              ? Number(rest.postponeCount).toFixed(2)
-              : 0;
-          }
+          item.num = data.metrics[index];
         });
-        // console.log(rest, 'rest');
-      },
 
-      //工单完成统计
-      async getCompletionCount() {
-        let params = {
-          createTimeStart: this.params.createTimeStart,
-          createTimeEnd: this.params.createTimeEnd,
-          factoryId: this.params.factoryId || null
-        };
-        let rest = await getCompletionCount(params);
-        let inWarehouseCountList = []; //入库数量
-        let inProductCountList = []; //在制工单数
-        let xAxisData = []; //X轴数据
-
-        rest.forEach((item) => {
-          inWarehouseCountList.push(item.inWarehouseCount);
-          inProductCountList.push(item.inProductCountList);
-          xAxisData.push(item.inProductDate);
-        });
+        // 不合格品分布图(返工品、返修品、废品)
+        const [rework, repair, scrap] = data.defective;
+        this.pieOptions = pieOptions([
+          { value: rework, name: '返工品' },
+          { value: repair, name: '返修品' },
+          { value: scrap, name: '废品' }
+        ]);
 
+        // 工单完成统计:仅展示工单入库数量
         this.barOption = barOption(
           [
             {
               name: '工单入库数量',
               barWidth: '25%',
-              data: inWarehouseCountList,
+              data: data.inWarehouse,
               type: 'bar',
               yAxisIndex: 0 // 使用第一个Y轴
-            },
-            {
-              name: '工单数',
-              symbolSize: 10,
-              data: inProductCountList,
-              type: 'line',
-              smooth: true,
-              itemStyle: {
-                color: '#ffab08'
-              }
             }
           ],
           {
             xAxis: {
               type: 'category',
-              data: xAxisData,
-              axisLabel: {
-                fontSize: window.innerHeight * 0.012
-              }
+              data: monthLabels
             }
           }
         );
-        console.log('this.barOption', inWarehouseCountList, inProductCountList);
+      },
+      datasource({ page, where, limit }) {
+        return getOrderList({
+          ...where,
+          pageNum: page,
+          size: limit,
+          createTimeStart: this.params.createTimeStart,
+          createTimeEnd: this.params.createTimeEnd,
+          factoryId: this.params.factoryId || null
+        });
+      },
+      timeTypeChange() {
+        // 工厂模式默认选中第一个分厂,企业模式展示合计
+        this.params.factoryId =
+          this.form.timeType === '2' ? factoryOptions[0].id : '';
       }
     }
   };

+ 1379 - 0
src/views/home/indexDynamic.vue

@@ -0,0 +1,1379 @@
+<template>
+  <div class="ele-body mes-screen">
+    <div class="screen-shell">
+      <div class="screen-toolbar">
+        <div class="screen-title">
+          <span>首页</span>
+          <!-- <em>Manufacturing Execution Dashboard</em> -->
+        </div>
+        <div class="screen-filters">
+          <el-radio-group
+            v-model="form.timeType"
+            class="mode-tabs"
+            @change="timeTypeChange"
+          >
+            <el-radio-button label="1">企业</el-radio-button>
+            <el-radio-button label="2">工厂</el-radio-button>
+            <!-- <el-radio-button label="3">班组</el-radio-button>
+          <el-radio-button label="4">产线</el-radio-button> -->
+          </el-radio-group>
+          <el-select
+            v-if="form.timeType === '2'"
+            v-model="params.factoryId"
+            class="factory-select"
+            filterable
+            placeholder="请选择工厂"
+            size="mini"
+          >
+            <el-option
+              v-for="item in factoryList"
+              :key="item.id"
+              :label="item.name"
+              :value="item.id"
+            >
+            </el-option>
+          </el-select>
+          <el-date-picker
+            v-model="params.date"
+            class="date-range"
+            type="monthrange"
+            range-separator="至"
+            start-placeholder="开始月份"
+            end-placeholder="结束月份"
+            size="mini"
+            :clearable="false"
+            :picker-options="pickerOptions"
+          >
+          </el-date-picker>
+        </div>
+      </div>
+
+      <el-row :gutter="16" class="screen-grid">
+        <el-col :xs="24" :sm="24" :md="16" :lg="16" :xl="17" class="main-col">
+          <div class="item metrics-grid">
+            <div
+              v-for="(item, index) in arr"
+              :key="index"
+              class="metric-card"
+              :class="'metric-card-' + index"
+              :style="{ color: item.color }"
+            >
+              <div class="metric-content">
+                <span class="metric-label">
+                  {{ item.name }}
+                </span>
+                <div class="metric-main">
+                  <div class="metric-icon">
+                    <img :src="item.imgUrl" />
+                  </div>
+                  <span class="metric-value">
+                    {{ item.num }}
+                    <span>{{ item.unit }}</span>
+                  </span>
+                </div>
+              </div>
+            </div>
+          </div>
+          <el-card class="box-card screen-panel chart-panel">
+            <div slot="header" class="clearfix panel-header">
+              <span>工单完成统计</span>
+            </div>
+            <v-chart ref="barRef" class="screen-chart" :option="barOption" />
+          </el-card>
+        </el-col>
+        <el-col :xs="24" :sm="24" :md="8" :lg="8" :xl="7" class="side-col">
+          <el-card class="box-card screen-panel pie-panel">
+            <div slot="header" class="clearfix panel-header">
+              <span>不合格品分布图: 571</span>
+            </div>
+            <v-chart ref="pieRef" class="screen-chart" :option="pieOptions" />
+          </el-card>
+        </el-col>
+        <el-col :span="24" class="table-col">
+          <el-card class="box-card screen-panel table-panel">
+            <div slot="header" class="clearfix panel-header">
+              <span>工单进度执行跟踪</span>
+            </div>
+            <ele-pro-table
+              ref="table"
+              height="calc(100%)"
+              :columns="columns"
+              :datasource="datasource"
+              :toolbar="false"
+              :needPage="false"
+            >
+            </ele-pro-table>
+          </el-card>
+        </el-col>
+      </el-row>
+    </div>
+  </div>
+</template>
+<script>
+  import dictMixins from '@/mixins/dictMixins';
+  import { pieOption, barOption, columns, pieOptions } from './data';
+  import { use } from 'echarts/core';
+  import { CanvasRenderer } from 'echarts/renderers';
+  import { BarChart, PieChart, LineChart } from 'echarts/charts';
+  import {
+    GridComponent,
+    TooltipComponent,
+    LegendComponent
+  } from 'echarts/components';
+  import VChart from 'vue-echarts';
+  import { echartsMixin } from '@/utils/echarts-mixin';
+  import {
+    getCount,
+    getCompletionCount,
+    getOrderList,
+    queryProportionDefectiveTypes
+  } from '@/api/mes/index';
+
+  import { getAllFactory } from '@/api/aps/index.js';
+
+  // 按需加载 echarts
+  use([
+    CanvasRenderer,
+    BarChart,
+    PieChart,
+    GridComponent,
+    TooltipComponent,
+    LegendComponent,
+    LineChart
+  ]);
+  export default {
+    mixins: [dictMixins, echartsMixin(['pieRef', 'barRef'])],
+    components: { VChart },
+    data() {
+      return {
+        columns,
+        arr: [
+          {
+            name: '计划数',
+            num: '',
+            imgUrl: require('../../assets/Group1.png'),
+            unit: ''
+          },
+          {
+            name: '投入数',
+            num: '',
+            imgUrl: require('../../assets/Group2.png'),
+            unit: ''
+          },
+          {
+            name: '产出数',
+            num: '',
+            imgUrl: require('../../assets/Group3.png'),
+            unit: ''
+          },
+          {
+            name: '在制品数',
+            num: '',
+            imgUrl: require('../../assets/Group4.png'),
+            unit: '',
+            color: '#f97876'
+          },
+          {
+            name: '合格品数',
+            num: '',
+            imgUrl: require('../../assets/Group2.png'),
+            unit: ''
+          }
+        ],
+
+        pieOption: {},
+        barOption: {},
+        pieOptions: {},
+        form: {
+          finishTime: '',
+          timeType: '1'
+        },
+        params: {
+          // 工厂id
+          factoryId: '',
+          // 时间
+          date: '',
+          createTimeStart: '',
+          createTimeEnd: ''
+        },
+        // 工厂列表
+        factoryList: [],
+        pickerOptions: {
+          shortcuts: [
+            {
+              text: '本月',
+              onClick(picker) {
+                picker.$emit('pick', [new Date(), new Date()]);
+              }
+            },
+            {
+              text: '今年至今',
+              onClick(picker) {
+                const end = new Date();
+                const start = new Date(new Date().getFullYear(), 0);
+                picker.$emit('pick', [start, end]);
+              }
+            },
+            {
+              text: '最近六个月',
+              onClick(picker) {
+                const end = new Date();
+                const start = new Date();
+                start.setMonth(start.getMonth() - 6);
+                picker.$emit('pick', [start, end]);
+              }
+            }
+          ]
+        }
+      };
+    },
+    watch: {
+      params: {
+        deep: true,
+        handler(newVal) {
+          // 处理参数变化 根据date同步createTimeStart和createTimeEnd
+          if (newVal.date && newVal.date.length === 2) {
+            this.params.createTimeStart = this.$util.toDateString(
+              newVal.date[0],
+              'yyyy-MM'
+            );
+            this.params.createTimeEnd = this.$util.toDateString(
+              newVal.date[1],
+              'yyyy-MM'
+            );
+          } else {
+            this.params.createTimeStart = '';
+            this.params.createTimeEnd = '';
+          }
+
+          this.getCount();
+          this.getCompletionCount();
+          this.proportion();
+          this.$nextTick(() => {
+            this.$refs.table.reload();
+          });
+        }
+      }
+    },
+    created() {
+      // this.pieOption = pieOption([
+      //   { value: 40, name: '  外观检测' },
+      //   { value: 30, name: '  尺寸检测' },
+      //   { value: 15, name: '  性能检测' },
+      //   { value: 10, name: '  密度检测' },
+      //   { value: 5, name: '  重量检测' }
+      // ]);
+
+      // 设置params.date 为今年的开始和结束月份
+      const currentYear = new Date().getFullYear();
+      const startOfYear = new Date(currentYear, 0, 1); // 一月一日
+      const endOfYear = new Date(currentYear, 11, 31); // 十二月三十一日
+      this.params.date = [startOfYear, endOfYear];
+      this.params.createTimeStart = this.$util.toDateString(
+        startOfYear,
+        'yyyy-MM'
+      );
+      this.params.createTimeEnd = this.$util.toDateString(endOfYear, 'yyyy-MM');
+
+      this.getCount();
+      this.getCompletionCount();
+      this.proportion();
+    },
+    mounted() {
+      this.getFactoryList();
+      setTimeout(() => {
+        this.$refs.barRef.resize();
+        this.$refs.pieRef.resize();
+      }, 300);
+    },
+    methods: {
+      async getFactoryList() {
+        const res = await getAllFactory();
+        this.factoryList = res;
+      },
+      async proportion() {
+        const res = await queryProportionDefectiveTypes(
+          `?factoryId=${this.params.factoryId || ''}&createTimeStart=${
+            this.params.createTimeStart
+          }&createTimeEnd=${this.params.createTimeEnd}`
+        );
+        let list = res.map((el) => {
+          return {
+            value: el.unQualifiedNumber,
+            name: el.categoryLevelClassName
+          };
+        });
+        this.pieOptions = pieOptions(list);
+      },
+      datasource({ page, where, limit }) {
+        return getOrderList({
+          ...where,
+          pageNum: page,
+          size: limit,
+          createTimeStart: this.params.createTimeStart,
+          createTimeEnd: this.params.createTimeEnd,
+          factoryId: this.params.factoryId || null
+        });
+      },
+      timeTypeChange() {
+        // 重置工厂选择
+        this.params.factoryId = '';
+      },
+      //首页统计
+      async getCount() {
+        let rest = await getCount({
+          factoryId: this.params.factoryId || null,
+          createTimeStart: this.params.createTimeStart,
+          createTimeEnd: this.params.createTimeEnd
+        });
+        this.arr.forEach((item, index) => {
+          if (item.name === '计划数') {
+            item.num = rest.formingNum ? Number(rest.formingNum).toFixed(2) : 0;
+          } else if (item.name === '投入数') {
+            item.num = rest.pendingProductionCount
+              ? Number(rest.pendingProductionCount).toFixed(2)
+              : 0;
+          } else if (item.name === '产出数') {
+            item.num = rest.formedNum ? Number(rest.formedNum).toFixed(2) : 0;
+          } else if (item.name === '在制品数') {
+            item.num = rest.inProgressWorkOrderCount
+              ? Number(rest.inProgressWorkOrderCount).toFixed(2)
+              : 0;
+          } else if (item.name === '合格品') {
+            item.num = rest.postponeCount
+              ? Number(rest.postponeCount).toFixed(2)
+              : 0;
+          }
+        });
+        console.log(rest, 'rest');
+      },
+
+      //工单完成统计
+      async getCompletionCount() {
+        let params = {
+          createTimeStart: this.params.createTimeStart,
+          createTimeEnd: this.params.createTimeEnd,
+          factoryId: this.params.factoryId || null
+        };
+        let rest = await getCompletionCount(params);
+        let inWarehouseCountList = []; //入库数量
+        let inProductCountList = []; //在制工单数
+        let xAxisData = []; //X轴数据
+
+        rest.forEach((item) => {
+          inWarehouseCountList.push(item.inWarehouseCount);
+          inProductCountList.push(item.inProductCountList);
+          xAxisData.push(item.inProductDate);
+        });
+
+        this.barOption = barOption(
+          [
+            {
+              name: '工单入库数量',
+              barWidth: '25%',
+              data: inWarehouseCountList,
+              type: 'bar',
+              yAxisIndex: 0 // 使用第一个Y轴
+            },
+            {
+              name: '工单数',
+              symbolSize: 10,
+              data: inProductCountList,
+              type: 'line',
+              smooth: true,
+              itemStyle: {
+                color: '#ffab08'
+              }
+            }
+          ],
+          {
+            xAxis: {
+              type: 'category',
+              data: xAxisData,
+              axisLabel: {
+                fontSize: window.innerHeight * 0.012
+              }
+            }
+          }
+        );
+        console.log('this.barOption', inWarehouseCountList, inProductCountList);
+      }
+    }
+  };
+</script>
+<style lang="scss" scoped>
+  .mes-screen {
+    height: calc(100vh - 111px);
+    min-height: 680px;
+    box-sizing: border-box;
+    overflow: hidden;
+    color: #d9f7ff;
+    background: linear-gradient(
+        90deg,
+        rgba(56, 189, 248, 0.11) 0 1px,
+        transparent 1px 100%
+      ),
+      linear-gradient(
+        180deg,
+        rgba(56, 189, 248, 0.08) 0 1px,
+        transparent 1px 100%
+      ),
+      linear-gradient(118deg, rgba(13, 148, 136, 0.1) 0%, transparent 34%),
+      linear-gradient(242deg, rgba(14, 165, 233, 0.08) 0%, transparent 36%),
+      linear-gradient(180deg, #061422 0%, #06101d 46%, #030914 100%);
+    background-size: 86px 86px, 86px 86px, auto, auto, auto;
+    position: relative;
+    box-shadow: 0 0 0 100vmax #050c17;
+    clip-path: inset(0 -100vmax -100vmax -100vmax);
+
+    &::before {
+      content: '';
+      position: absolute;
+      inset: 0;
+      pointer-events: none;
+      background-image: linear-gradient(
+          115deg,
+          transparent 0 42%,
+          rgba(103, 232, 249, 0.08) 42% 42.4%,
+          transparent 42.4% 100%
+        ),
+        linear-gradient(
+          245deg,
+          transparent 0 58%,
+          rgba(16, 185, 129, 0.06) 58% 58.4%,
+          transparent 58.4% 100%
+        );
+      background-size: 420px 220px, 460px 240px;
+      mask-image: linear-gradient(
+        to bottom,
+        rgba(0, 0, 0, 0.9),
+        transparent 94%
+      );
+    }
+
+    &::after {
+      content: '';
+      position: absolute;
+      inset: 0;
+      pointer-events: none;
+      background: repeating-linear-gradient(
+        180deg,
+        rgba(255, 255, 255, 0.018) 0,
+        rgba(255, 255, 255, 0.018) 1px,
+        transparent 1px,
+        transparent 6px
+      );
+      opacity: 0.22;
+    }
+  }
+
+  .screen-shell {
+    position: relative;
+    z-index: 1;
+    height: 100%;
+    min-height: 0;
+    padding: 18px 22px 20px;
+    display: flex;
+    flex-direction: column;
+    gap: 16px;
+
+    &::before,
+    &::after {
+      content: '';
+      position: absolute;
+      left: 20px;
+      right: 20px;
+      height: 1px;
+      pointer-events: none;
+      background: linear-gradient(
+        90deg,
+        transparent,
+        rgba(103, 232, 249, 0.42),
+        transparent
+      );
+    }
+
+    &::before {
+      top: 8px;
+    }
+
+    &::after {
+      bottom: 8px;
+    }
+  }
+
+  .screen-toolbar {
+    position: relative;
+    overflow: hidden;
+    min-height: 64px;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    gap: 18px;
+    padding: 14px 22px;
+    border: 1px solid rgba(103, 232, 249, 0.3);
+    border-radius: 7px;
+    background: linear-gradient(
+        90deg,
+        rgba(8, 47, 73, 0.84),
+        rgba(5, 15, 28, 0.7) 58%,
+        rgba(7, 30, 48, 0.82)
+      ),
+      linear-gradient(180deg, rgba(103, 232, 249, 0.13), transparent 62%);
+    box-shadow: inset 0 1px 0 rgba(236, 254, 255, 0.16),
+      inset 0 -1px 0 rgba(56, 189, 248, 0.22),
+      inset 0 0 34px rgba(14, 165, 233, 0.13), 0 16px 32px rgba(0, 0, 0, 0.26);
+
+    &::before {
+      content: '';
+      position: absolute;
+      left: 18px;
+      right: 18px;
+      bottom: 0;
+      height: 2px;
+      background: linear-gradient(
+        90deg,
+        transparent,
+        rgba(103, 232, 249, 0.72),
+        rgba(16, 185, 129, 0.42),
+        transparent
+      );
+      opacity: 0.78;
+    }
+
+    &::after {
+      content: '';
+      position: absolute;
+      left: 0;
+      top: 0;
+      width: 36%;
+      height: 100%;
+      background: linear-gradient(
+          100deg,
+          rgba(103, 232, 249, 0.16),
+          transparent 58%
+        ),
+        repeating-linear-gradient(
+          90deg,
+          rgba(125, 211, 252, 0.08) 0 1px,
+          transparent 1px 22px
+        );
+      pointer-events: none;
+    }
+  }
+
+  .screen-title {
+    position: relative;
+    z-index: 1;
+    display: flex;
+    flex-direction: column;
+    min-width: 260px;
+
+    span {
+      display: flex;
+      align-items: center;
+      gap: 10px;
+      font-size: clamp(22px, 1.6vw, 30px);
+      line-height: 1.2;
+      font-weight: 700;
+      letter-spacing: 0;
+      color: #f5fdff;
+      text-shadow: 0 0 14px rgba(34, 211, 238, 0.54),
+        0 0 28px rgba(14, 165, 233, 0.22);
+
+      &::before {
+        content: '';
+        width: 8px;
+        height: 32px;
+        border-radius: 1px;
+        background: linear-gradient(
+          180deg,
+          #67e8f9 0%,
+          #22d3ee 48%,
+          #0ea5e9 100%
+        );
+        box-shadow: 0 0 12px rgba(34, 211, 238, 0.9),
+          10px 0 24px rgba(14, 165, 233, 0.22);
+      }
+    }
+
+    em {
+      margin-top: 4px;
+      font-style: normal;
+      font-size: 12px;
+      color: rgba(165, 243, 252, 0.68);
+      text-transform: uppercase;
+    }
+  }
+
+  .screen-filters {
+    position: relative;
+    z-index: 1;
+    display: flex;
+    align-items: center;
+    justify-content: flex-end;
+    flex-wrap: wrap;
+    gap: 10px;
+    padding: 5px;
+    border: 1px solid rgba(56, 189, 248, 0.26);
+    border-radius: 7px;
+    background: linear-gradient(
+        180deg,
+        rgba(6, 18, 32, 0.82),
+        rgba(2, 8, 17, 0.8)
+      ),
+      repeating-linear-gradient(
+        90deg,
+        rgba(56, 189, 248, 0.035) 0 1px,
+        transparent 1px 26px
+      );
+    box-shadow: inset 0 1px 0 rgba(165, 243, 252, 0.1),
+      inset 0 0 18px rgba(14, 165, 233, 0.12), 0 0 20px rgba(14, 165, 233, 0.1);
+  }
+
+  .mode-tabs {
+    :deep(.el-radio-button__inner) {
+      min-width: 72px;
+      height: 32px;
+      line-height: 30px;
+      padding: 0 18px;
+      border-color: rgba(56, 189, 248, 0.28);
+      color: rgba(224, 242, 254, 0.82);
+      background: rgba(5, 14, 26, 0.78);
+      box-shadow: none;
+    }
+
+    :deep(.el-radio-button__orig-radio:checked + .el-radio-button__inner) {
+      color: #06131f;
+      border-color: #22d3ee;
+      background: linear-gradient(135deg, #67e8f9, #38bdf8);
+      box-shadow: inset 0 1px 0 rgba(236, 254, 255, 0.36),
+        0 0 18px rgba(56, 189, 248, 0.42);
+    }
+  }
+
+  .factory-select {
+    width: 180px;
+  }
+
+  .date-range {
+    width: 310px;
+
+    :deep(.el-range__close-icon) {
+      display: none !important;
+      visibility: hidden;
+      pointer-events: none;
+    }
+  }
+
+  :deep(.el-date-editor .el-range__close-icon),
+  :deep(.date-range .el-range__close-icon) {
+    display: none !important;
+    visibility: hidden !important;
+    width: 0 !important;
+    pointer-events: none;
+  }
+
+  :deep(.el-input__inner) {
+    height: 32px;
+    color: #e0f7ff;
+    border-color: rgba(56, 189, 248, 0.32);
+    background: rgba(3, 12, 24, 0.86);
+    box-shadow: inset 0 1px 0 rgba(125, 211, 252, 0.08),
+      inset 0 0 12px rgba(14, 165, 233, 0.08);
+  }
+
+  :deep(.el-input__inner::placeholder) {
+    color: rgba(191, 219, 254, 0.55);
+  }
+
+  :deep(.el-range-input) {
+    color: #e0f7ff;
+    background: transparent;
+  }
+
+  :deep(.el-range-separator),
+  :deep(.el-input__icon) {
+    color: rgba(125, 211, 252, 0.8);
+  }
+
+  .screen-grid {
+    flex: 1;
+    min-height: 0;
+  }
+
+  .main-col,
+  .side-col {
+    height: 58%;
+  }
+
+  .main-col {
+    display: flex;
+    flex-direction: column;
+    gap: 16px;
+  }
+
+  .table-col {
+    height: calc(42% - 16px);
+    margin-top: 16px;
+  }
+
+  .metrics-grid {
+    width: 100%;
+    min-height: 116px;
+    display: grid;
+    grid-template-columns: repeat(5, minmax(0, 1fr));
+    gap: 18px;
+  }
+
+  .metric-card {
+    position: relative;
+    overflow: hidden;
+    min-width: 0;
+    min-height: 116px;
+    padding: 17px 14px 15px;
+    display: flex;
+    flex-direction: column;
+    justify-content: space-between;
+    gap: 0;
+    border: 1px solid rgba(103, 232, 249, 0.34);
+    border-radius: 7px;
+    color: #7dd3fc;
+    background: linear-gradient(
+        150deg,
+        rgba(14, 116, 144, 0.34),
+        rgba(5, 13, 25, 0.94) 62%
+      ),
+      linear-gradient(90deg, rgba(34, 211, 238, 0.14), transparent 55%),
+      repeating-linear-gradient(
+        135deg,
+        rgba(125, 211, 252, 0.035) 0,
+        rgba(125, 211, 252, 0.035) 1px,
+        transparent 1px,
+        transparent 26px
+      );
+    box-shadow: inset 0 1px 0 rgba(236, 254, 255, 0.12),
+      inset 0 -1px 0 rgba(34, 211, 238, 0.12),
+      inset 0 0 28px rgba(34, 211, 238, 0.08), 0 14px 26px rgba(0, 0, 0, 0.24);
+    transition: border-color 0.2s ease, box-shadow 0.2s ease,
+      transform 0.2s ease;
+
+    &::before,
+    &::after {
+      content: '';
+      position: absolute;
+      pointer-events: none;
+    }
+
+    &::before {
+      inset: 0;
+      background: linear-gradient(
+            90deg,
+            rgba(103, 232, 249, 0.9),
+            transparent 44%
+          )
+          left top / 100% 3px no-repeat,
+        linear-gradient(180deg, rgba(103, 232, 249, 0.52), transparent 50%) left
+          top / 1px 100% no-repeat,
+        linear-gradient(90deg, rgba(103, 232, 249, 0.16), transparent 50%) left
+          bottom / 100% 1px no-repeat;
+      opacity: 0.82;
+    }
+
+    &::after {
+      width: 78px;
+      height: 78px;
+      right: -34px;
+      bottom: -36px;
+      border: 1px solid rgba(125, 211, 252, 0.22);
+      transform: rotate(45deg);
+      background: linear-gradient(
+        135deg,
+        rgba(14, 165, 233, 0.18),
+        rgba(13, 148, 136, 0.04)
+      );
+    }
+  }
+
+  .metric-card:hover {
+    border-color: rgba(103, 232, 249, 0.62);
+    box-shadow: inset 0 1px 0 rgba(165, 243, 252, 0.16),
+      inset 0 0 34px rgba(34, 211, 238, 0.13), 0 16px 32px rgba(0, 0, 0, 0.3),
+      0 0 22px rgba(14, 165, 233, 0.18);
+    transform: translateY(-1px);
+  }
+
+  .metric-card-3 {
+    color: #fb7185 !important;
+    border-color: rgba(251, 113, 133, 0.42);
+    background: linear-gradient(
+        150deg,
+        rgba(190, 18, 60, 0.28),
+        rgba(5, 13, 25, 0.94) 62%
+      ),
+      linear-gradient(90deg, rgba(251, 113, 133, 0.15), transparent 55%);
+
+    &::before {
+      border-top-color: rgba(251, 113, 133, 0.72);
+    }
+  }
+
+  .metric-card-3 .metric-value {
+    color: #ff7890;
+    text-shadow: 0 0 10px rgba(251, 113, 133, 0.85),
+      0 0 22px rgba(251, 113, 133, 0.38);
+  }
+
+  .metric-icon {
+    flex: 0 0 40px;
+    width: 40px;
+    height: 40px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    border: 1px solid rgba(125, 211, 252, 0.12);
+    border-radius: 7px;
+    background: linear-gradient(
+        135deg,
+        rgba(10, 28, 46, 0.92),
+        rgba(14, 116, 144, 0.2)
+      ),
+      linear-gradient(180deg, rgba(103, 232, 249, 0.08), transparent);
+    box-shadow: inset 0 0 18px rgba(103, 232, 249, 0.14),
+      0 0 18px rgba(14, 165, 233, 0.14);
+
+    img {
+      width: 30px;
+      max-height: 30px;
+      object-fit: contain;
+      filter: drop-shadow(0 0 10px rgba(56, 189, 248, 0.55));
+    }
+  }
+
+  .metric-content {
+    position: relative;
+    z-index: 1;
+    min-width: 0;
+    flex: 1;
+    display: flex;
+    flex-direction: column;
+    justify-content: space-between;
+    gap: 16px;
+  }
+
+  .metric-label {
+    position: relative;
+    padding-left: 12px;
+    font-size: clamp(12px, 0.72vw, 14px);
+    line-height: 1.25;
+    color: rgba(224, 242, 254, 0.76);
+    white-space: nowrap;
+    overflow: hidden;
+    text-overflow: ellipsis;
+
+    &::before {
+      content: '';
+      position: absolute;
+      left: 0;
+      top: 50%;
+      width: 5px;
+      height: 5px;
+      border-radius: 50%;
+      background: #67e8f9;
+      box-shadow: 0 0 9px rgba(103, 232, 249, 0.9);
+      transform: translateY(-50%);
+    }
+  }
+
+  .metric-main {
+    min-width: 0;
+    display: grid;
+    grid-template-columns: 42px minmax(0, 1fr);
+    align-items: center;
+    gap: 10px;
+  }
+
+  .metric-value {
+    display: block;
+    width: 100%;
+    min-width: 0;
+    font-size: clamp(18px, 1.08vw, 24px);
+    line-height: 1;
+    font-weight: 700;
+    color: #8fe3ff;
+    white-space: nowrap;
+    overflow: visible;
+    text-overflow: clip;
+    font-variant-numeric: tabular-nums;
+    text-shadow: 0 0 10px rgba(56, 189, 248, 0.85),
+      0 0 22px rgba(56, 189, 248, 0.35);
+
+    span {
+      font-size: 10px;
+      color: rgba(224, 242, 254, 0.78);
+      text-shadow: none;
+    }
+  }
+
+  .screen-panel {
+    position: relative;
+    overflow: hidden;
+    height: 100%;
+    border: 1px solid rgba(56, 189, 248, 0.28);
+    border-radius: 7px;
+    color: #d9f7ff;
+    background: linear-gradient(
+        180deg,
+        rgba(10, 34, 56, 0.9),
+        rgba(4, 13, 25, 0.94)
+      ),
+      linear-gradient(135deg, rgba(34, 211, 238, 0.1), transparent 42%),
+      repeating-linear-gradient(
+        90deg,
+        rgba(125, 211, 252, 0.02) 0 1px,
+        transparent 1px 52px
+      );
+    box-shadow: inset 0 1px 0 rgba(236, 254, 255, 0.1),
+      inset 0 -1px 0 rgba(56, 189, 248, 0.12),
+      inset 0 0 28px rgba(14, 165, 233, 0.09), 0 16px 34px rgba(0, 0, 0, 0.26);
+
+    &::before {
+      content: '';
+      position: absolute;
+      inset: 0;
+      pointer-events: none;
+      border-radius: inherit;
+      background: linear-gradient(
+            90deg,
+            rgba(103, 232, 249, 0.72),
+            transparent 88px
+          )
+          left top / 148px 1px no-repeat,
+        linear-gradient(180deg, rgba(103, 232, 249, 0.52), transparent 64px)
+          left top / 1px 100px no-repeat,
+        linear-gradient(270deg, rgba(103, 232, 249, 0.46), transparent 88px)
+          right bottom / 148px 1px no-repeat,
+        linear-gradient(0deg, rgba(103, 232, 249, 0.34), transparent 64px) right
+          bottom / 1px 100px no-repeat;
+      opacity: 0.85;
+    }
+
+    &::after {
+      content: '';
+      position: absolute;
+      left: 16px;
+      right: 16px;
+      bottom: 0;
+      height: 1px;
+      pointer-events: none;
+      background: linear-gradient(
+        90deg,
+        transparent,
+        rgba(34, 211, 238, 0.62),
+        transparent
+      );
+      opacity: 0.6;
+    }
+
+    :deep(.el-card__header) {
+      position: relative;
+      z-index: 1;
+      padding: 12px 18px;
+      border-bottom: 1px solid rgba(56, 189, 248, 0.18);
+      background: linear-gradient(90deg, rgba(8, 47, 73, 0.58), transparent 68%),
+        linear-gradient(180deg, rgba(125, 211, 252, 0.06), transparent);
+    }
+
+    :deep(.el-card__body) {
+      position: relative;
+      z-index: 1;
+      height: calc(100% - 48px);
+      padding: 12px 14px 14px;
+      background: linear-gradient(
+          rgba(125, 211, 252, 0.022) 1px,
+          transparent 1px
+        ),
+        linear-gradient(90deg, rgba(125, 211, 252, 0.022) 1px, transparent 1px);
+      background-size: 30px 30px;
+    }
+  }
+
+  .panel-header {
+    display: flex;
+    align-items: center;
+    min-height: 24px;
+    justify-content: space-between;
+
+    > span {
+      position: relative;
+      padding-left: 12px;
+      font-size: 16px;
+      line-height: 1.3;
+      font-weight: 700;
+      color: #f0fdff;
+      text-shadow: 0 0 12px rgba(34, 211, 238, 0.45);
+
+      &::before {
+        content: '';
+        position: absolute;
+        left: 0;
+        top: 50%;
+        width: 4px;
+        height: 18px;
+        border-radius: 1px;
+        background: linear-gradient(180deg, #67e8f9, #38bdf8);
+        transform: translateY(-50%);
+        box-shadow: 0 0 12px rgba(34, 211, 238, 0.8);
+      }
+    }
+
+    &::after {
+      content: '';
+      width: 96px;
+      height: 1px;
+      background: linear-gradient(
+        90deg,
+        rgba(103, 232, 249, 0.86),
+        rgba(16, 185, 129, 0.3),
+        transparent
+      );
+      opacity: 0.7;
+    }
+  }
+
+  .chart-panel {
+    flex: 1;
+    min-height: 0;
+  }
+
+  .screen-chart {
+    width: 100%;
+    height: 100%;
+  }
+
+  .chart-panel {
+    :deep(.el-card__body) {
+      background: linear-gradient(
+          180deg,
+          rgba(6, 21, 38, 0.18),
+          rgba(3, 11, 22, 0.34)
+        ),
+        repeating-linear-gradient(
+          90deg,
+          rgba(56, 189, 248, 0.026) 0 1px,
+          transparent 1px 78px
+        ),
+        linear-gradient(rgba(125, 211, 252, 0.022) 1px, transparent 1px),
+        linear-gradient(90deg, rgba(125, 211, 252, 0.022) 1px, transparent 1px);
+      background-size: auto, auto, 30px 30px, 30px 30px;
+    }
+  }
+
+  .pie-panel {
+    :deep(.el-card__body) {
+      background: linear-gradient(
+          180deg,
+          rgba(6, 21, 38, 0.2),
+          rgba(3, 11, 22, 0.36)
+        ),
+        repeating-linear-gradient(
+          135deg,
+          rgba(56, 189, 248, 0.028) 0 1px,
+          transparent 1px 34px
+        ),
+        linear-gradient(rgba(125, 211, 252, 0.022) 1px, transparent 1px),
+        linear-gradient(90deg, rgba(125, 211, 252, 0.022) 1px, transparent 1px);
+      background-size: auto, auto, 30px 30px, 30px 30px;
+    }
+  }
+
+  .table-panel {
+    :deep(.el-card__body) {
+      padding: 12px 14px 14px;
+      background: linear-gradient(
+          180deg,
+          rgba(5, 16, 30, 0.12),
+          rgba(5, 16, 30, 0.34)
+        ),
+        repeating-linear-gradient(
+          90deg,
+          rgba(56, 189, 248, 0.02) 0,
+          rgba(56, 189, 248, 0.02) 1px,
+          transparent 1px,
+          transparent 72px
+        );
+    }
+
+    :deep(.ele-pro-table) {
+      height: 100%;
+      color: #dbeafe;
+      background: linear-gradient(
+          180deg,
+          rgba(6, 20, 36, 0.86),
+          rgba(3, 11, 22, 0.92)
+        ),
+        linear-gradient(90deg, rgba(56, 189, 248, 0.04), transparent);
+    }
+
+    :deep(.ele-pro-table-body),
+    :deep(.ele-pro-table-main),
+    :deep(.ele-table-tool-default),
+    :deep(.el-table__body-wrapper),
+    :deep(.el-table__fixed),
+    :deep(.el-table__fixed-right) {
+      background: rgba(3, 12, 24, 0.92) !important;
+    }
+
+    :deep(.el-table) {
+      overflow: hidden;
+      font-size: 12px;
+      color: #dbeafe;
+      background: linear-gradient(
+          180deg,
+          rgba(6, 20, 36, 0.88),
+          rgba(3, 11, 22, 0.94)
+        ),
+        repeating-linear-gradient(
+          90deg,
+          rgba(56, 189, 248, 0.022) 0,
+          rgba(56, 189, 248, 0.022) 1px,
+          transparent 1px,
+          transparent 72px
+        );
+      border: 1px solid rgba(125, 211, 252, 0.24);
+      box-shadow: inset 0 0 18px rgba(14, 165, 233, 0.08),
+        0 0 18px rgba(14, 165, 233, 0.1);
+    }
+
+    :deep(.el-table .cell) {
+      line-height: 19px;
+      font-weight: 500;
+      letter-spacing: 0;
+    }
+
+    :deep(.el-table__header-wrapper) {
+      background: linear-gradient(
+        180deg,
+        rgba(13, 95, 117, 0.78),
+        rgba(8, 47, 73, 0.72)
+      );
+    }
+
+    :deep(.el-table__empty-block) {
+      min-height: 214px;
+      background: radial-gradient(
+          circle at 50% 42%,
+          rgba(34, 211, 238, 0.12),
+          transparent 30%
+        ),
+        linear-gradient(180deg, rgba(6, 20, 36, 0.88), rgba(3, 11, 22, 0.96)) !important;
+    }
+
+    :deep(.el-table__empty-text) {
+      color: rgba(224, 242, 254, 0.72);
+      text-shadow: 0 0 12px rgba(56, 189, 248, 0.38);
+    }
+
+    :deep(.el-table__empty-text .el-empty__image) {
+      opacity: 0.74;
+      filter: drop-shadow(0 0 14px rgba(56, 189, 248, 0.3));
+    }
+
+    :deep(.el-loading-mask) {
+      background: radial-gradient(
+          circle at 50% 42%,
+          rgba(34, 211, 238, 0.16),
+          transparent 28%
+        ),
+        linear-gradient(180deg, rgba(5, 17, 31, 0.94), rgba(2, 8, 17, 0.96)) !important;
+      backdrop-filter: blur(1px);
+    }
+
+    :deep(.el-loading-spinner .path) {
+      stroke: #67e8f9;
+    }
+
+    :deep(.el-loading-spinner .el-loading-text) {
+      color: #c7fbff;
+    }
+
+    :deep(.el-table::before),
+    :deep(.el-table--border::after),
+    :deep(.el-table--group::after) {
+      background-color: rgba(56, 189, 248, 0.12);
+    }
+
+    :deep(.el-table th),
+    :deep(.el-table tr),
+    :deep(.el-table td) {
+      background: transparent !important;
+    }
+
+    :deep(.el-table th) {
+      height: 36px;
+      color: #c7fbff;
+      background: linear-gradient(
+        180deg,
+        rgba(14, 116, 144, 0.62),
+        rgba(8, 47, 73, 0.78)
+      ) !important;
+      border-color: rgba(56, 189, 248, 0.22);
+      text-shadow: 0 0 10px rgba(103, 232, 249, 0.34);
+    }
+
+    :deep(.el-table td) {
+      height: 34px;
+      color: rgba(226, 232, 240, 0.8);
+      border-color: rgba(56, 189, 248, 0.1);
+    }
+
+    :deep(.el-table__body tr:nth-child(odd) > td) {
+      background: rgba(8, 30, 52, 0.26) !important;
+    }
+
+    :deep(.el-table__body tr:nth-child(even) > td) {
+      background: rgba(3, 14, 27, 0.16) !important;
+    }
+
+    :deep(.el-table__body tr:hover),
+    :deep(.el-table__body tr.hover-row),
+    :deep(.el-table__body tr.current-row) {
+      background: transparent !important;
+    }
+
+    :deep(.el-table--enable-row-hover .el-table__body tr:hover > td),
+    :deep(
+        .el-table--enable-row-hover .el-table__body tr:hover > td.el-table__cell
+      ),
+    :deep(.el-table__body tr.hover-row > td),
+    :deep(.el-table__body tr.hover-row > td.el-table__cell),
+    :deep(.el-table__body tr.current-row > td),
+    :deep(.el-table__body tr.current-row > td.el-table__cell) {
+      color: #f8fafc !important;
+      background: linear-gradient(
+        90deg,
+        rgba(34, 211, 238, 0.2),
+        rgba(14, 165, 233, 0.14)
+      ) !important;
+      box-shadow: inset 0 1px 0 rgba(125, 211, 252, 0.2),
+        inset 0 -1px 0 rgba(125, 211, 252, 0.16);
+    }
+
+    :deep(.el-table__body tr:hover > td .cell),
+    :deep(.el-table__body tr.hover-row > td .cell),
+    :deep(.el-table__body tr.current-row > td .cell) {
+      color: #f8fafc !important;
+    }
+
+    :deep(.el-table__body-wrapper::-webkit-scrollbar) {
+      width: 8px;
+      height: 8px;
+    }
+
+    :deep(.el-table__body-wrapper::-webkit-scrollbar-thumb) {
+      border-radius: 8px;
+      background: rgba(56, 189, 248, 0.48);
+    }
+
+    :deep(.el-table__body-wrapper::-webkit-scrollbar-track) {
+      background: rgba(8, 20, 35, 0.72);
+    }
+  }
+
+  @media (max-width: 1400px) {
+    .metrics-grid {
+      grid-template-columns: repeat(3, minmax(0, 1fr));
+    }
+
+    .metric-card {
+      min-height: 108px;
+    }
+
+    .metric-value {
+      font-size: 22px;
+    }
+  }
+
+  @media (max-width: 992px) {
+    .mes-screen {
+      height: auto;
+      min-height: calc(100vh - 111px);
+      overflow: auto;
+    }
+
+    .screen-shell {
+      min-height: 0;
+    }
+
+    .screen-toolbar {
+      align-items: flex-start;
+      flex-direction: column;
+    }
+
+    .screen-filters {
+      width: 100%;
+      justify-content: flex-start;
+    }
+
+    .main-col,
+    .side-col,
+    .table-col {
+      height: auto;
+    }
+
+    .side-col,
+    .table-col {
+      margin-top: 14px;
+    }
+
+    .chart-panel,
+    .pie-panel {
+      height: 360px;
+    }
+
+    .table-panel {
+      height: 420px;
+    }
+  }
+
+  @media (max-width: 768px) {
+    .screen-shell {
+      padding: 10px;
+    }
+
+    .screen-title span {
+      font-size: 20px;
+    }
+
+    .metrics-grid {
+      grid-template-columns: repeat(2, minmax(0, 1fr));
+    }
+
+    .factory-select,
+    .date-range {
+      width: 100%;
+    }
+
+    .metric-value {
+      font-size: 24px;
+    }
+  }
+
+  @media (max-width: 520px) {
+    .metrics-grid {
+      grid-template-columns: 1fr;
+    }
+
+    .mode-tabs {
+      width: 100%;
+
+      :deep(.el-radio-button) {
+        width: 50%;
+      }
+
+      :deep(.el-radio-button__inner) {
+        width: 100%;
+      }
+    }
+  }
+</style>