فهرست منبع

Merge remote-tracking branch 'origin/master'

wangpx 1 سال پیش
والد
کامیت
f0b22034f1

+ 23 - 3
ui/src/assets/dcs/iconfont_colour/iconfont.css

@@ -2,9 +2,9 @@
   font-family: "iconfont-colour"; /* Project id 4898001 */
   /* Color fonts */
   src: 
-       url('iconfont.woff2?t=1745716703096') format('woff2'),
-       url('iconfont.woff?t=1745716703096') format('woff'),
-       url('iconfont.ttf?t=1745716703096') format('truetype');
+       url('iconfont.woff2?t=1747099540104') format('woff2'),
+       url('iconfont.woff?t=1747099540104') format('woff'),
+       url('iconfont.ttf?t=1747099540104') format('truetype');
 }
 
 .iconfont-colour {
@@ -15,6 +15,26 @@
   -moz-osx-font-smoothing: grayscale;
 }
 
+.icon-zhengqifashengqi:before {
+  content: "\e65a";
+}
+
+.icon-chuqiguan:before {
+  content: "\e66f";
+}
+
+.icon-kongyaji:before {
+  content: "\e620";
+}
+
+.icon-penlinta:before {
+  content: "\e61b";
+}
+
+.icon-tank5:before {
+  content: "\e603";
+}
+
 .icon-tank3:before {
   content: "\e604";
 }

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
ui/src/assets/dcs/iconfont_colour/iconfont.js


+ 36 - 1
ui/src/assets/dcs/iconfont_colour/iconfont.json

@@ -5,6 +5,41 @@
   "css_prefix_text": "icon-",
   "description": "彩色图标,颜色不可变换",
   "glyphs": [
+    {
+      "icon_id": "8427499",
+      "name": "蒸汽发生器",
+      "font_class": "zhengqifashengqi",
+      "unicode": "e65a",
+      "unicode_decimal": 58970
+    },
+    {
+      "icon_id": "8427590",
+      "name": "储气罐",
+      "font_class": "chuqiguan",
+      "unicode": "e66f",
+      "unicode_decimal": 58991
+    },
+    {
+      "icon_id": "17122953",
+      "name": "空压机",
+      "font_class": "kongyaji",
+      "unicode": "e620",
+      "unicode_decimal": 58912
+    },
+    {
+      "icon_id": "36185100",
+      "name": "喷淋塔",
+      "font_class": "penlinta",
+      "unicode": "e61b",
+      "unicode_decimal": 58907
+    },
+    {
+      "icon_id": "44288232",
+      "name": "J1",
+      "font_class": "tank5",
+      "unicode": "e603",
+      "unicode_decimal": 58883
+    },
     {
       "icon_id": "44161150",
       "name": "tank3",
@@ -49,7 +84,7 @@
     },
     {
       "icon_id": "18678347",
-      "name": "初始罐体",
+      "name": "下锥形罐体",
       "font_class": "initialTank1",
       "unicode": "e60b",
       "unicode_decimal": 58891

BIN
ui/src/assets/dcs/iconfont_colour/iconfont.ttf


BIN
ui/src/assets/dcs/iconfont_colour/iconfont.woff


BIN
ui/src/assets/dcs/iconfont_colour/iconfont.woff2


+ 158 - 0
ui/src/assets/styles/dcs/equipment.scss

@@ -0,0 +1,158 @@
+//管道通用样式
+.progress_red {
+    .el-progress-bar__inner--striped {
+        background-size: 20px 20px;
+        background-image: linear-gradient(45deg,
+                rgba(200, 200, 200, 1) 25%,
+                /* 白色条纹 */
+                transparent 25%,
+                transparent 50%,
+                rgba(200, 200, 200, 1) 50%,
+                rgba(200, 200, 200, 1) 75%,
+                transparent 75%,
+                transparent);
+    }
+
+    .el-progress-bar__inner {
+        background-color: #ff1900;
+    }
+
+}
+
+
+
+//压缩空气管道样式
+.progress_compressed_air {
+
+    //蓝色进度条
+    .el-progress-bar__inner--striped {
+        background-size: 20px 20px;
+        background-image: linear-gradient(45deg,
+                rgba(200, 200, 200, 1) 25%,
+                /* 白色 */
+                transparent 25%,
+                transparent 50%,
+                rgba(200, 200, 200, 1) 50%,
+                rgba(200, 200, 200, 1) 75%,
+                transparent 75%,
+                transparent);
+    }
+
+    .el-progress-bar__inner {
+        background-color: #0586ef;
+    }
+}
+
+
+//换热液管道样式
+.progress_heat_exchange_fluid {
+
+    //黄色进度条
+    .el-progress-bar__inner--striped {
+        background-size: 20px 20px;
+        background-image: linear-gradient(45deg,
+                rgba(200, 200, 200, 1) 25%,
+                /* 白色条纹 */
+                transparent 25%,
+                transparent 50%,
+                rgba(200, 200, 200, 1) 50%,
+                rgba(200, 200, 200, 1) 75%,
+                transparent 75%,
+                transparent);
+    }
+
+    .el-progress-bar__inner {
+        background-color: #FFCC00;
+    }
+}
+
+//臭气管道效果
+.progress_stench {
+
+    /* 紫色条纹背景 */
+    .el-progress-bar__inner--striped {
+        background-size: 20px 20px;
+        background-image: linear-gradient(45deg,
+                rgba(200, 200, 200, 1) 25%,
+                /* 白色条纹 */
+                transparent 25%,
+                transparent 50%,
+                rgba(200, 200, 200, 1) 50%,
+                rgba(200, 200, 200, 1) 75%,
+                transparent 75%,
+                transparent);
+    }
+
+    .el-progress-bar__inner {
+        background-color: purple;
+    }
+
+}
+
+//物料管道效果
+.progress_materials {
+
+    /* 灰色条纹背景 */
+    .el-progress-bar__inner--striped {
+        background-size: 20px 20px;
+        background-image: linear-gradient(45deg,
+                rgba(200, 200, 200, 1) 25%,
+                /* 浅灰 */
+                transparent 25%,
+                transparent 50%,
+                rgba(200, 200, 200, 1) 50%,
+                rgba(200, 200, 200, 1) 75%,
+                transparent 75%,
+                transparent);
+    }
+
+    /* 灰色填充背景 */
+    .el-progress-bar__inner {
+        background-color: #808080;
+        /* 深灰 */
+    }
+}
+
+// 蒸汽管道效果
+.progress_steam {
+
+    /* 橙色条纹管道效果:深色增强对比 */
+    .el-progress-bar__inner--striped {
+        background-size: 20px 20px;
+        background-image: linear-gradient(45deg,
+                rgba(200, 200, 200, 1) 25%,
+                /* 白色条纹 */
+                transparent 25%,
+                transparent 50%,
+                rgba(200, 200, 200, 1) 50%,
+                rgba(200, 200, 200, 1) 75%,
+                transparent 75%,
+                transparent);
+    }
+
+    .el-progress-bar__inner {
+        background-color: #ff6200;
+    }
+
+
+}
+
+//顺时针旋转90度
+.rotate_90 {
+    transform: rotate(90deg);
+}
+
+//逆时针旋转45度
+.rotate_315 {
+    transform: rotate(-45deg);
+}
+
+//旋转180度
+.rotate_180 {
+    transform: rotate(180deg);
+}
+
+//顺时针旋转270度
+.rotate_270 {
+    transform: rotate(270deg);
+}

+ 5 - 0
ui/src/components/DCS/DeviceStatusComponent.vue

@@ -116,6 +116,11 @@ const frequencyOptions = props.title.includes('S') ?
     ]
 // 设置泵
 function setPump(address, value) {
+    //地址未定义
+    if (!address) {
+        openElWarnMessage('地址未定义')
+        return;
+    }
     const open = 0;
     const close = 2;
     const setValue = value ? frequencyOptions[open].value : frequencyOptions[close].value;

+ 130 - 0
ui/src/components/DCS/J1TankComponent.vue

@@ -0,0 +1,130 @@
+<template>
+    <div class="tank" :style="{ width: `${iconSize}px`, height: `${iconSize}px` }">
+        <!-- j1罐体 -->
+        <div class="tank_j1">
+            <i class="icon iconfont-colour icon-tank5" :style="{ fontSize: iconSize + 'px' }"></i>
+            <div class="tank_title" v-if="title">{{ title }}</div>
+        </div>
+        <!-- d1/d3阀门 -->
+        <div :style="valveProgressStyle" class="valve_progress1 rotate_270" v-if="hasValve(valveNames[0])">
+            <ValveProgress :iconSize="valveIconSize" :title="valveNames[0]" :rotateAngle="270"
+                :valveStatusArr="getValveStatusArr(valveNames[0])" :pipeStatus="getValveAndStatus(valveNames[0])"
+                :pipeReverse="true" />
+        </div>
+        <!-- d2 -->
+        <div :style="valveProgressStyle" class="valve_progress2" v-if="hasValve(valveNames[1])">
+            <ValveProgress :iconSize="valveIconSize" :title="valveNames[1]"
+                :valveStatusArr="getValveStatusArr(valveNames[1])" :pipeStatus="getValveAndStatus(valveNames[1])"
+                :pipeReverse="true" />
+        </div>
+        <!-- d4 -->
+        <div :style="valveProgressStyle" class="valve_progress4" v-if="hasValve(valveNames[2])">
+            <ValveProgress :iconSize="valveIconSize" :title="valveNames[2]"
+                :valveStatusArr="getValveStatusArr(valveNames[2])" :pipeStatus="getValveAndStatus(valveNames[2])"
+                :pipeReverse="true" />
+        </div>
+
+    </div>
+</template>
+<script setup>
+import ValveProgress from '@/components/DCS/ValveProgressComponent.vue';
+import { defineProps, computed } from 'vue'
+import { useValveHelper } from '@/hooks/useValveHelper'
+const props = defineProps({
+    title: {
+        type: String,
+        required: true
+    },
+    valveArr: {//阀门数组
+        type: Array,
+    },
+    iconSize: {//罐体图标大小
+        type: Number,
+        default: 300,
+    },
+})
+
+// 将 props.valveArr 引用传入
+const { hasValve, getValveStatusArr, getValveAndStatus } = useValveHelper(props.valveArr)
+
+const valveNames1 = ['D1', 'D2']
+const valveNames2 = ['D3', '', 'D4']
+// 根据title进行判断
+const valveNames = computed(() => {
+    switch (props.title) {
+        case 'J1':
+            return valveNames1;
+        case 'J2':
+            return valveNames2;
+        default:
+            return valveNames1;
+    }
+});
+
+//阀门icon大小(罐子300-阀门50)
+const valveIconSize = computed(() => {
+    return props.iconSize / 6;
+});
+
+//阀门进度样式
+const valveProgressStyle = computed(() => {
+    return {
+        width: `${valveIconSize.value}px`,
+        height: `${valveIconSize.value}px`,
+    }
+});
+
+
+
+</script>
+
+<style lang="scss" scoped>
+.page {
+    width: 100%;
+    height: 100%;
+    background-color: #0b172c;
+
+    .tank {
+        margin: 200px;
+        position: relative;
+        z-index: 10;
+
+        .tank_j1 {
+            position: absolute;
+            z-index: 10;
+
+            .tank_title {
+                position: absolute;
+                top: 50%;
+                left: 50%;
+                transform: translate(-50%, -50%);
+                font-size: 28px;
+                color: #FFA500;
+                font-weight: bold;
+            }
+
+        }
+
+
+        .valve_progress1 {
+            position: absolute;
+            top: 105%;
+            left: 39%;
+        }
+
+        .valve_progress2 {
+            position: absolute;
+            top: 15%;
+            left: 72%;
+        }
+
+        .valve_progress4 {
+            position: absolute;
+            top: 63%;
+            left: 72%;
+        }
+
+
+    }
+}
+</style>

+ 296 - 0
ui/src/components/DCS/M1TankComponent.vue

@@ -0,0 +1,296 @@
+<template>
+
+    <div class="tank" :style="{ width: `${iconSize}px`, height: `${iconSize}px` }">
+        <!-- m1罐体 -->
+        <WaterTank :temperatureValue="temperatureValue" tankType="1" :title="title" :waterLevelValue="waterLevelValue"
+            :iconSize="iconSize" class="m1_tank" :pressureValue="pressureValue" :weightValue="weightValue">
+        </WaterTank>
+        <!-- n4/n14 -->
+        <div :style="valveProgressStyle" class="valve_progress_4" v-if="hasValve(valveNames[0])">
+            <ValveProgress :iconSize="valveIconSize" :title="valveNames[0]" progressType="compressed_air"
+                :valveStatusArr="getValveStatusArr(valveNames[0])" :pipeStatus="getValveAndStatus(valveNames[0])"
+                :pipeReverse="true" />
+        </div>
+
+        <!-- N6 /n16-->
+        <div :style="valveProgressStyle" class="valve_progress_6" v-if="hasValve(valveNames[1])">
+            <ValveProgress :iconSize="valveIconSize" :title="valveNames[1]" :pipeLength="267" :pipeLeftOffset="-132"
+                :valveStatusArr="getValveStatusArr(valveNames[1])" :progressType="getProgressType"
+                :pipeStatus="getValveAndStatus(valveNames[1], valveNames[3]) || getValveAndStatus(valveNames[1], valveNames[4])"
+                :pipeReverse="getValveAndStatus(valveNames[1], valveNames[4])" />
+            <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                :striped="getValveAndStatus(valveNames[1], valveNames[3]) || getValveAndStatus(valveNames[1], valveNames[4])"
+                :striped-flow="getValveAndStatus(valveNames[1], valveNames[3]) || getValveAndStatus(valveNames[1], valveNames[4])"
+                :duration="6" class="progress rotate_90 progress6_2"
+                :class="[getProgressClass, { 'rotate_270': getValveAndStatus(valveNames[1], valveNames[4]) }]" />
+        </div>
+
+        <!-- N7 /n17-->
+        <div :style="valveProgressStyle" class="valve_progress_7" v-if="hasValve(valveNames[2])">
+            <ValveProgress :iconSize="valveIconSize" :title="valveNames[2]" :pipeLength="352" :pipeLeftOffset="-216"
+                :valveStatusArr="getValveStatusArr(valveNames[2])" :progressType="getProgressType"
+                :pipeStatus="getValveAndStatus(valveNames[2], valveNames[3]) || getValveAndStatus(valveNames[2], valveNames[4])"
+                :pipeReverse="getValveAndStatus(valveNames[2], valveNames[4])" />
+            <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                :striped="getValveAndStatus(valveNames[2], valveNames[3]) || getValveAndStatus(valveNames[2], valveNames[4])"
+                :striped-flow="getValveAndStatus(valveNames[2], valveNames[3]) || getValveAndStatus(valveNames[2], valveNames[4])"
+                :duration="progressConfig.duration" class="progress rotate_90 progress7_2"
+                :class="[getProgressClass, { 'rotate_270': getValveAndStatus(valveNames[2], valveNames[4]) }]" />
+        </div>
+
+        <!-- N8 /n18-->
+        <div :style="valveProgressStyle" class="valve_progress_8 rotate_315" v-if="hasValve(valveNames[3])">
+            <ValveProgress :iconSize="valveIconSize" :title="valveNames[3]" :rotateAngle="315" :pipeLength="226"
+                :valveStatusArr="getValveStatusArr(valveNames[3])" progressType="compressed_air"
+                :pipeStatus="getValveAndStatus(valveNames[3], valveNames[2]) || getValveAndStatus(valveNames[3], valveNames[1])" />
+            <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                :striped="getValveAndStatus(valveNames[2], valveNames[3]) || getValveAndStatus(valveNames[1], valveNames[4])"
+                :striped-flow="getValveAndStatus(valveNames[2], valveNames[3]) || getValveAndStatus(valveNames[1], valveNames[4])"
+                class="progress progress8_1" :class="getProgressClass"/>
+        </div>
+
+        <!-- N9 /n15-->
+        <div :style="valveProgressStyle" class="valve_progress_9 rotate_315" v-if="hasValve(valveNames[4])">
+            <ValveProgress :iconSize="iconSize * 0.125" :title="valveNames[4]" :rotateAngle="315" :pipeLength="287"
+                :pipeLeftOffset="-49" :valveStatusArr="getValveStatusArr(valveNames[4])" :progressType="title === 'M1' ? 'heat_exchange_fluid' : 'materials'"
+                :pipeStatus="getValveAndStatus(valveNames[4], valveNames[1]) || getValveAndStatus(valveNames[4], valveNames[2])" />
+        </div>
+
+        <!-- N11 /n20-->
+        <div :style="valveProgressStyle" class="valve_progress_11 rotate_270" v-if="hasValve(valveNames[5])">
+            <ValveProgress :iconSize="iconSize * 0.125" :title="valveNames[5]" :rotateAngle="270" progressType="stench"
+                :valveStatusArr="getValveStatusArr(valveNames[5])" :pipeLength="600"
+                :pipeStatus="getValveAndStatus(valveNames[5])" />
+        </div>
+
+        <!-- N1/n12 -->
+        <div :style="valveProgressStyle" class="valve_progress_1" v-if="hasValve(valveNames[6])">
+            <ValveProgress :iconSize="valveIconSize" :title="valveNames[6]" progressType="materials"
+                :valveStatusArr="getValveStatusArr(valveNames[6])" :pipeStatus="getValveAndStatus(valveNames[6])" />
+        </div>
+
+        <!-- N2 /n13-->
+        <div :style="valveProgressStyle" class="valve_progress_2" v-if="hasValve(valveNames[7])">
+            <ValveProgress :iconSize="valveIconSize" :title="valveNames[7]"
+                :progressType="title === 'M1' ? 'heat_exchange_fluid' : 'red'"
+                :valveStatusArr="getValveStatusArr(valveNames[7])" :pipeStatus="getValveAndStatus(valveNames[7])" />
+        </div>
+
+        <!-- N10 /n19-->
+        <div :style="valveProgressStyle" class="valve_progress_10 rotate_270" v-if="hasValve(valveNames[8])">
+            <ValveProgress :iconSize="valveIconSize" :title="valveNames[8]" :rotateAngle="270"
+                :valveStatusArr="getValveStatusArr(valveNames[8])" :pipeLength="218"
+                :pipeStatus="getValveAndStatus(valveNames[8])" :pipeReverse="true" />
+        </div>
+
+
+        <!-- N3-->
+        <div :style="valveProgressStyle" class="valve_progress_3" v-if="hasValve(valveNames[9])">
+            <ValveProgress :iconSize="valveIconSize" :title="valveNames[9]"
+                :valveStatusArr="getValveStatusArr(valveNames[9])" :pipeStatus="getValveAndStatus(valveNames[9])"
+                :pipeReverse="true" />
+        </div>
+
+        <!-- n5 暂时隐藏-->
+        <div :style="valveProgressStyle" class="valve_progress_5 rotate_90" v-if="false">
+            <ValveProgress :iconSize="iconSize * 0.125" :title="valveNames[10]" :rotateAngle="90"
+                :valveStatusArr="getValveStatusArr(valveNames[10])" :pipeStatus="getValveAndStatus(valveNames[10])" />
+        </div>
+    </div>
+</template>
+
+<script setup>
+import WaterTank from '@/components/DCS/WaterTankComponent';
+import ValveProgress from '@/components/DCS/ValveProgressComponent.vue';
+import { defineProps, computed } from 'vue'
+import { useValveHelper } from '@/hooks/useValveHelper'
+
+const props = defineProps({
+    title: {
+        type: String,
+        required: true
+    },
+    iconSize: {
+        type: Number,
+        default: 400
+    },
+    temperatureValue: {//温度
+        type: Number,
+    },
+    waterLevelValue: {//液位
+        type: Number,
+    },
+    pressureValue: {//压力
+        type: Number,
+    },
+    weightValue: {//重量
+        type: Number,
+    },
+    // fanStatus: {//风扇状态
+    //     type: Boolean,
+    // },
+    valveArr: {//阀门数组
+        type: Array,
+    },
+})
+
+const { hasValve, getValveStatusArr, getValveAndStatus } = useValveHelper(props.valveArr)
+
+//进度条配置
+const progressConfig = {
+    strokeWidth: 8,//进度条宽度
+    percentage: 100,//进度条百分比
+    duration: 10,//进度条流速
+    showText: false,//是否显示文字
+}
+// M1,M2罐对应阀门名称
+const valveNames1 = ['N4', 'N6', 'N7', 'N8', 'N9', 'N11', 'N1', 'N2', 'N10', 'N13', 'N5'];
+const valveNames2 = ['N14', 'N16', 'N17', 'N18', 'N15', 'N20', 'N12', 'N13', 'N19', '', '']
+// 根据title进行判断
+const valveNames = computed(() => {
+    switch (props.title) {
+        case 'M1':
+            return valveNames1;
+        case 'M2':
+            return valveNames2;
+        default:
+            return valveNames1;
+    }
+});
+
+//阀门图标大小(罐子400-阀门50)
+const valveIconSize = computed(() => {
+    return props.iconSize * 0.125;
+});
+//阀门进度样式
+const valveProgressStyle = computed(() => {
+    return {
+        width: `${valveIconSize.value}px`,
+        height: `${valveIconSize.value}px`,
+    }
+});
+
+//根据阀门状态获取n6/n7和n16/n17进度条颜色
+const getProgressType = computed(() => {
+    //如果下面的阀门开启,说明流进的是压缩空气
+    if (getValveAndStatus(valveNames.value[3]))//computed运算出来的结果是对象,要解构
+        return 'compressed_air';
+    //如果上面的阀门开启,说明流进的是蒸汽
+    if (getValveAndStatus(valveNames.value[4]))
+        return props.title === 'M1' ? 'heat_exchange_fluid' : 'materials';
+    return 'red'
+})
+
+const getProgressClass = computed(() => `progress_${getProgressType.value}`);
+
+</script>
+
+<style lang="scss" scoped>
+.tank {
+    margin: 200px;
+    position: relative;
+    z-index: 10;
+
+    .valve_progress_4 {
+        position: absolute;
+        top: 5%;
+        left: 85%;
+    }
+
+    .valve_progress_5 {
+        position: absolute;
+        top: -25%;
+        left: -11%;
+    }
+
+    .valve_progress_6 {
+        position: absolute;
+        top: -13%;
+        left: 9%;
+
+
+        .progress6_2 {
+            position: absolute;
+            width: 66%;
+            top: 86%;
+            left: 101%;
+        }
+    }
+
+    .valve_progress_7 {
+        position: absolute;
+        top: -25%;
+        left: 33%;
+
+
+
+        .progress7_2 {
+            position: absolute;
+            width: 154%;
+            top: 129%;
+            left: 56%;
+
+        }
+    }
+
+    .valve_progress_8 {
+        position: absolute;
+        top: 0%;
+        left: -27%;
+
+
+        .progress8_1 {
+            width: 152%;
+            top: 57%;
+            left: 177%;
+        }
+    }
+
+    .valve_progress_9 {
+        position: absolute;
+        top: -33%;
+        left: 6%;
+
+
+    }
+
+    .valve_progress_10 {
+        position: absolute;
+        left: 42%;
+        top: 103%;
+
+
+    }
+
+    .valve_progress_11 {
+        position: absolute;
+        top: -15%;
+        left: 60%;
+    }
+
+    .valve_progress_1 {
+        position: absolute;
+        top: 64%;
+        left: 9%;
+    }
+
+    .valve_progress_2 {
+        position: absolute;
+        top: 45%;
+        left: 85%;
+    }
+
+    .valve_progress_3 {
+        position: absolute;
+        top: 45%;
+        left: 2%;
+    }
+
+    .m1_tank {
+        position: absolute;
+        z-index: 10;
+    }
+
+
+}
+</style>

+ 70 - 0
ui/src/components/DCS/PumpComponent.vue

@@ -0,0 +1,70 @@
+<template>
+    <!-- 泵组件 -->
+    <div class="pump" :style="{ width: `${props.iconSize}px`, height: `${props.iconSize}px` }">
+        <i class="icon iconfont-colour icon-beng icon_pump" :style="{ fontSize: `${props.iconSize}px` }"></i>
+        <div class="pump_title"> {{ props.title }} </div>
+        <div class="pump_status" :style="{ fontSize: `${props.iconSize/6}px` }"> {{ props.pumpStatus }} </div>
+        <div class="pump_hz" :style="{ fontSize: `${props.iconSize/5}px` }"> {{ hzValue }} Hz</div>
+    </div>
+</template>
+
+<script setup>
+import { defineProps, computed } from 'vue'
+const props = defineProps({
+    title: {
+        type: String,
+        required: true
+    },
+    iconSize: {
+        type: Number,
+        default: 100
+    },
+    pumpStatus: {
+        type: String,
+        default: '正转'
+    },
+    hz: {
+        type: Number,
+        default: 0
+    },
+})
+
+const hzValue = computed(() => `${props.hz}` *0.01);
+
+
+</script>
+
+
+<style scoped lang="scss">
+.pump {
+    position: relative;
+    z-index: 15;
+    .pump_title {
+        position: absolute;
+        width: max-content;
+        top: -7%;
+        left: 56%;
+        font-size: 20px;
+        color: aliceblue;
+    }
+
+    .pump_status {
+        position: absolute;
+        text-align: center;
+        top: 40%;
+        left: 26%;
+        color: #d7e908;
+    }
+
+    .pump_hz {
+        position: absolute;
+        width: max-content;
+        text-align: center;
+        top: 41%;
+        left: 82%;
+        font-weight: bold;
+        color: #d7e908;
+    }
+
+}
+</style>

+ 193 - 0
ui/src/components/DCS/S1TankComponent.vue

@@ -0,0 +1,193 @@
+<template>
+    <div class="tank" :style="{ width: `${iconSize}px`, height: `${iconSize}px` }">
+        <!-- s1罐体 拓展s2,s3罐体 -->
+        <WaterTank :temperatureValue="temperatureValue" tankType="3" :waterLevelValue="waterLevelValue"
+            :iconSize="iconSize" :pressureValue="pressureValue" :weightValue="weightValue" :title="title"
+            class="s1_tank" />
+        <!-- d11阀门/d12/d13 -->
+        <div :style="valveProgressStyle" class="valve_progress11 rotate_270" v-if="hasValve(valveNames[0])">
+            <ValveProgress :iconSize="valveIconSize" :title="valveNames[0]" :rotateAngle="270" :pipeLength="400"
+                :pipeLeftOffset="-93" :valveStatusArr="getValveStatusArr(valveNames[0])" progressType="steam"
+                :pipeStatus="getValveAndStatus(valveNames[0])" :pipeReverse="true" />
+        </div>
+        <!-- d5阀门/d6/d7 -->
+        <div :style="valveProgressStyle" class="valve_progress5 rotate_270" v-if="hasValve(valveNames[1])">
+            <ValveProgress :iconSize="valveIconSize" :title="valveNames[1]" :rotateAngle="270" :pipeLength="300"
+                :pipeLeftOffset="-154" :valveStatusArr="getValveStatusArr(valveNames[1])" progressType="materials"
+                :pipeStatus="getValveAndStatus('N10', valveNames[1])" :pipeReverse="true" />
+        </div>
+        <!-- d16阀门/d17/d18 -->
+        <div :style="valveProgressStyle" class="valve_progress16 rotate_270" v-if="hasValve(valveNames[2])">
+            <ValveProgress :iconSize="valveIconSize" :title="valveNames[2]" :rotateAngle="270" :pipeLength="710"
+            progressType="stench"
+                :valveStatusArr="getValveStatusArr(valveNames[2])" :pipeStatus="getValveAndStatus(valveNames[2])" />
+        </div>
+        <!-- d8阀门/d9/d10 -->
+        <div :style="valveProgressStyle" class="valve_progress8" v-if="hasValve(valveNames[3])">
+            <ValveProgress :iconSize="valveIconSize" :title="valveNames[3]" :rotateAngle="0" :pipeLength="200"
+                progressType="compressed_air" :pipeLeftOffset="-63" :valveStatusArr="getValveStatusArr(valveNames[3])"
+                :pipeStatus="getValveAndStatus(valveNames[3])" />
+        </div>
+        <!-- n22阀门 /n23/n24 -->
+        <div :style="valveProgressStyle" class="valve_progress22 rotate_270" v-if="hasValve(valveNames[4])">
+            <ValveProgress :iconSize="valveIconSize" :title="valveNames[4]" :rotateAngle="270" :pipeLength="250"
+                :pipeLeftOffset="-47" :valveStatusArr="getValveStatusArr(valveNames[4])" progressType="materials"
+                :pipeStatus="getValveAndStatus(valveNames[4])" :pipeReverse="true" />
+        </div>
+        <!-- 搅拌电机 -->
+        <div class="beng">
+            <i class="icon iconfont icon-fengshan fan_pos" :class="{ 'fan_run': fanStatus }"></i>
+        </div>
+    </div>
+</template>
+<script setup>
+import WaterTank from '@/components/DCS/WaterTankComponent';
+import ValveProgress from '@/components/DCS/ValveProgressComponent.vue';
+import { defineProps, computed } from 'vue'
+import { useValveHelper } from '@/hooks/useValveHelper'
+
+const props = defineProps({
+    title: {
+        type: String,
+        required: true
+    },
+    temperatureValue: {//温度
+        type: Number,
+    },
+    waterLevelValue: {//液位
+        type: Number,
+    },
+    pressureValue: {//压力
+        type: Number,
+    },
+    weightValue: {//重量
+        type: Number,
+    },
+    fanStatus: {//风扇状态
+        type: Boolean,
+    },
+    valveArr: {//阀门数组
+        type: Array,
+    },
+    iconSize: {//罐体图标大小
+        type: Number,
+        default: 300,
+    },
+})
+// 将 props.valveArr 转换为响应式引用传入
+const { hasValve, getValveStatusArr, getValveAndStatus } = useValveHelper(props.valveArr)
+// s1,s2,s3罐对应阀门数组
+const valveNames1 = ['D11', 'D5', 'D16', 'D8', 'N22']
+const valveNames2 = ['D12', 'D6', 'D17', 'D9', 'N23']
+const valveNames3 = ['D13', 'D7', 'D18', 'D10', 'N24']
+// 根据title进行判断
+const valveNames = computed(() => {
+    switch (props.title) {
+        case 'S1':
+            return valveNames1;
+        case 'S2':
+            return valveNames2;
+        case 'S3':
+            return valveNames3;
+        default:
+            return valveNames1;
+    }
+});
+//阀门icon大小(罐子300-阀门50)
+const valveIconSize = computed(() => {
+    return props.iconSize / 6;
+});
+
+//阀门进度样式
+const valveProgressStyle = computed(() => {
+    return {
+        width: `${valveIconSize.value}px`,
+        height: `${valveIconSize.value}px`,
+    }
+});
+
+
+</script>
+
+<style lang="scss" scoped>
+.page {
+    width: 100%;
+    height: 100%;
+    background-color: #0b172c;
+
+    .tank {
+        margin: 200px;
+        position: relative;
+        z-index: 10;
+
+        .valve_progress11 {
+            position: absolute;
+            top: -30%;
+            left: 45%;
+
+        }
+
+        .valve_progress5 {
+            position: absolute;
+            top: -40%;
+            left: 28%;
+
+        }
+
+        .valve_progress16 {
+            position: absolute;
+            top: -18%;
+            left: 60%;
+
+        }
+
+        .valve_progress8 {
+            position: absolute;
+            top: 71%;
+            left: 4%;
+        }
+
+        .valve_progress22 {
+            position: absolute;
+            top: 98%;
+            left: 40%;
+
+        }
+
+        //罐体
+        .s1_tank {
+            position: absolute;
+            z-index: 10;
+        }
+
+        .beng {
+            .fan_pos {
+                color: red;
+                position: absolute;
+                top: 30%;
+                left: 38%;
+                font-size: 80px;
+            }
+        }
+
+
+
+        //旋转动画
+        @keyframes rotate-clockwise {
+            from {
+                transform: rotate(0deg);
+            }
+
+            to {
+                transform: rotate(360deg);
+            }
+        }
+
+        .fan_run {
+            animation: rotate-clockwise 1s linear infinite;
+        }
+
+
+    }
+}
+</style>

+ 1 - 1
ui/src/components/DCS/ValveComponent.vue

@@ -51,7 +51,7 @@ const props = defineProps({
 const pointerClass = computed(() => {
     // 未传入阀门信号状态时,该阀门为N阀门
     if(null === props.valveOpenSignalStatus || null === props.valveCloseSignalStatus){
-        console.log('未传入阀门信号状态')
+        // console.log('未传入阀门信号状态')
         return props.valveOpenObj?.value ? 'pointer_open' : 'pointer_close'
     }
     // 传入阀门信号状态时,该阀门为D阀门,根据信号状态判断指针样式

+ 114 - 0
ui/src/components/DCS/ValveProgressComponent.vue

@@ -0,0 +1,114 @@
+<template>
+    <!-- 阀门以及对应管道组件 -->
+    <div class="valve_progress_component">
+        <singleValve :title="title" :rotateAngle="rotateAngle" v-bind="getValveStatus1" :iconSize="iconSize"
+            class="valve" />
+        <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+            :striped="pipeStatus" :striped-flow="pipeStatus"
+            :duration="progressConfig.duration" class="progress"  :class="[getProgressClass, { 'rotate_180': pipeReverse }]"
+            :style="getProgressStyle" />
+    </div>
+</template>
+
+<script setup>
+import singleValve from '@/components/DCS/singleValveComponent';
+import { defineProps, computed } from 'vue'
+const props = defineProps({
+    title: {// 阀门名称
+        type: String,
+        required: true
+    },
+    //阀门title逆旋转角度
+    rotateAngle: {
+        type: Number,
+        default: 0
+    },
+    // 阀门状态数组[TRUE,FALSE,TRUE]/[TRUE]
+    valveStatusArr: {
+        type: Array,
+        default: null
+    },
+    //管道长度(默认200%)
+    pipeLength: {
+        type: Number,
+        default: 200
+    },
+    //管道左偏移量
+    pipeLeftOffset: {
+        type: Number,
+        default: -44
+    },
+    //管道是否反转
+    pipeReverse: {
+        type: Boolean,
+        default: false
+    },
+    //管道流通状态
+    pipeStatus: {
+        type: Boolean,
+        default: false
+    },
+    //阀门图标大小
+    iconSize: {
+        type: Number,
+        default: 50
+    },
+    //进度条颜色
+    progressType: {
+        type: String,
+        default: 'red'
+    }
+})
+
+//进度条配置
+const progressConfig = {
+    strokeWidth: 8,//进度条宽度
+    duration: 10,//进度条流速
+}
+
+// 计算 pointer 的 class
+const getProgressStyle = computed(() => {
+    return {
+        position: 'absolute',
+        top: '57%',
+        left: `${props.pipeLeftOffset}%`,
+        width: `${props.pipeLength}%`,
+        zIndex: 1,
+    }
+})
+
+// 计算 progress 的 class
+const getProgressClass = computed(() => {
+    return `progress_${props.progressType}`
+})
+
+
+//计算阀门状态
+const getValveStatus1 = computed(() => {
+    const val = props.valveStatusArr;
+    if (!val) return {};
+    if (val.length === 1) {
+        return { valveOpenObj: val[0] };
+    } else if (val.length === 3) {
+        return {
+            valveOpenSignalStatus: val[0],
+            valveCloseSignalStatus: val[1],
+            valveOpenObj: val[2],
+        };
+    } else {
+        return {};
+    }
+});
+
+
+</script>
+
+
+<style scoped lang="scss">
+.valve_progress_component {
+    .valve {
+        position: absolute;
+        z-index: 100;
+    }
+}
+</style>

+ 267 - 20
ui/src/components/DCS/WaterTankComponent.vue

@@ -1,24 +1,58 @@
 <template>
     <!-- 水解罐:水位、温度 -->
-    <div class="water_level_tank">
+    <div class="water_level_tank" :style="{ width: iconSize + 'px', height: iconSize + 'px' }">
         <!-- 罐体 -->
-        <i class="icon iconfont-colour tank" :class="tankIconClass">
+        <!-- font-size大小可调节 ,根据传进来的值来控制图标的大小 -->
+        <i class="icon iconfont-colour tank" :class="tankIconClass" :style="{ fontSize: iconSize + 'px' }">
+            <!-- 标题 -->
+            <div class="tank_title" v-if="title">{{ title }}</div>
             <!-- 水位 -->
             <div v-if="waterLevelValue >= 0">
                 <dv-water-level-pond :config="waterLevelConfig" class="water_level" :class="waterLevelPosClass" />
             </div>
             <!-- 温度计 -->
             <div class="slider-demo-block" v-if="temperatureValue >= 0" :class="tempPosClass">
-                <el-slider v-model="temperatureValue" vertical disabled max="150" min="0" :marks="marks"
-                    class="temperature_slider" :class="{ 'high_temp': temperatureValue > 70 }" />
+                <el-slider v-model="temperatureValue" vertical disabled max="140" min="-10" :marks="marks"
+                    class="temperature_slider" :class="getTempClass" />
             </div>
         </i>
+        <!-- 压力  -->
+        <div class="pressure_block" v-if="pressureValue >= 0"
+            :style="{ width: iconSize * 0.375 + 'px', height: iconSize * 0.375 + 'px' }">
+            <div ref="chartRef" :style="{ width: iconSize * 0.5 + 'px', height: iconSize * 0.5 + 'px' }"
+                class="pressure_chart"></div>
+        </div>
+        <!-- 重量 -->
+        <div class="weight_block" v-if="weightValue >= 0" :style="{ width: iconSize * 0.3 + 'px' }">
+            <div class="weight_value">{{ weightValue }}kg</div>
+        </div>
     </div>
 </template>
 
 <script setup>
 import { computed } from 'vue'
+import { ref, onMounted, onBeforeUnmount, watch } from 'vue'
+import * as echarts from 'echarts'
+//图表
 
+const chartRef = ref(null)
+let myChart = null
+onBeforeUnmount(() => {
+    if (myChart) {
+        window.removeEventListener('resize', myChart.resize)
+        myChart.dispose()
+    }
+})
+onMounted(() => {
+    if (chartRef.value) {
+        myChart = echarts.init(chartRef.value, null, {
+            renderer: 'svg'
+        })
+        myChart.setOption(option.value)
+        // 响应式自适应大小
+        window.addEventListener('resize', myChart.resize)
+    }
+})
 const props = defineProps({
     temperatureValue: {//温度
         type: Number,
@@ -29,20 +63,138 @@ const props = defineProps({
         default: -1,// -1表示未传水位值
         // required: true
     },
-    tankType: {// 罐型
+    pressureValue: {// 压力值
+        type: Number,
+        default: -1,// -1表示未传压力值
+    },
+    weightValue: {// 重量值
+        type: Number,
+        default: -1,// -1表示未传重量值
+    },
+    tankType: {// 罐型1下锥2上锥3平4上圆
         type: Number,
         default: 1,// 1表示默认罐型水解罐
-    }
+    },
+    iconSize: {
+        type: Number,
+        default: 200,
+    },
+    title: {//罐名
+        type: String,
+    },
+})
+//图表配置项
+const option = ref({
+    series: [
+        {
+            max: 1,// 最大值
+            type: 'gauge',
+            startAngle: 200,
+            endAngle: -20,
+            axisLine: {//仪表盘刻度
+                lineStyle: {
+                    width: props.iconSize * 0.05,
+                    color: [
+                        [0.4, '#4CAF50'],//绿色:正常
+                        [0.7, '#fb8a1c'],//橙色:警告
+                        [1, '#F44336']//红色:危险
+                    ],
+                }
+            },
+            pointer: {
+                itemStyle: {
+                    color: 'auto'
+                }
+            },
+            axisTick: {//细刻度
+                distance: -(props.iconSize * 0.05),
+                length: 8,
+                lineStyle: {
+                    color: '#fff',
+                    width: 2
+                }
+            },
+            splitLine: {//粗刻度
+                distance: -(props.iconSize * 0.05),
+                length: (props.iconSize * 0.05) + 5,
+                lineStyle: {
+                    color: '#fff',
+                    width: 4
+                }
+            },
+            axisLabel: {
+                color: 'inherit',
+                distance: (props.iconSize * 0.05) + 5,
+                fontSize: 8,// 刻度字体大小
+            },
+            detail: {// 数值显示
+                valueAnimation: true,// 数值变化动画
+                // formatter: '{value} Mpa',
+                formatter: function (value) {
+                    return '{value|' + value.toFixed(3) + '}{unit|MPa}';
+                },
+                rich: {
+                    value: {
+                        fontSize: props.iconSize * 0.06,
+                        fontWeight: 'bolder',
+                        color: 'inherit',
+                        padding: [0, 0, -10, 0]
+                    },
+                    unit: {
+                        fontSize: props.iconSize * 0.04,
+                        color: 'inherit',
+                        padding: [0, 0, -10, 4]
+                    }
+                },
+                // color: 'inherit',
+                // fontSize: props.iconSize * 0.05,// 数值字体大小
+                offsetCenter: [0, '45%'],
+                // backgroundColor: '#999',
+                // width: '100%',
+            },
+            data: [
+                {
+                    value: props.pressureValue.toFixed(3),
+                }
+            ],
+        }
+    ]
 })
+
+
+
 //温度值
 const temperatureValue = computed({
     get() {
         return props.temperatureValue
     },
 })
+
+const getTempClass = computed(() => {
+    if (temperatureValue.value > 120) {
+        return 'temp_red'
+    } else if (temperatureValue.value > 75) {
+        return 'temp_orange'
+    } else {
+        return 'temp_green'
+    }
+})
+// 监听压力变化
+watch(props?.pressureValue, (newVal) => {
+    if (myChart) {
+        myChart.setOption({
+            series: [
+                {
+                    type: 'gauge',
+                    data: [{ name: '压力数据', value: newVal.toFixed(2) }]
+                }
+            ]
+        })
+    }
+})
 // 罐型图标
 const tankIconClass = computed(() => {
-    return props.waterLevelValue >= 0 ? 'icon-tank'+ props.tankType : 'icon-initialTank'+ props.tankType;
+    return props.waterLevelValue >= 0 ? 'icon-tank' + props.tankType : 'icon-initialTank' + props.tankType;
 });
 
 // 水位图标位置
@@ -53,6 +205,30 @@ const waterLevelPosClass = computed(() =>
 const tempPosClass = computed(() =>
     'temp_pos' + props.tankType
 )
+//温度计数值显示
+const marks = computed(() => ({
+    // 80: '80°C',
+    // 75: {
+    //     style: {
+    //         color: '#fb8a1c',
+    //     },
+    //     label: '75°C',
+    // },
+    // 120: {
+    //     style: {
+    //         color: '#ff0000',
+    //         // fontWeight: 'bold',
+    //     },
+    //     label: '120°C',
+    // },
+    [temperatureValue.value]: {
+        style: {
+            color: temperatureValue.value < 75 ? '#4CAF50' : (temperatureValue.value < 120 ? '#FFC107' : '#ff0000'),
+            fontWeight: 'bold',
+        },
+        label: `${temperatureValue.value}°C`
+    }
+}))
 
 
 // 仅传 waterLevelValue,内部组装 config
@@ -61,9 +237,8 @@ const waterLevelConfig = computed(() => ({
     waveHeight: 5,// 波浪高度
 }))
 
-const marks = computed(() => ({
-    [temperatureValue.value]: `${temperatureValue.value}°C`
-}))
+
+
 </script>
 
 <style scoped lang="scss">
@@ -71,7 +246,17 @@ const marks = computed(() => ({
 .water_level_tank {
     .tank {
         position: relative;
-        font-size: 200px; //罐子大小可调节
+        z-index: 10;
+
+        //罐子名称
+        .tank_title {
+            position: absolute;
+            top: -7%;
+            left: 44%;
+            font-size: 30px;
+            color: #FFA500;
+            font-weight: bold;
+        }
 
         // 水位
         .water_level {
@@ -121,25 +306,54 @@ const marks = computed(() => ({
             display: flex;
             align-items: center;
 
-            .temperature_slider {
+            :deep(.temperature_slider) {
                 height: 0.5em;
                 margin-left: 8% !important;
 
-                :deep(.el-slider__runway .el-slider__button-wrapper .el-slider__button) {
+                .el-slider__runway .el-slider__button-wrapper .el-slider__button {
                     position: absolute;
                     left: 22%;
                     bottom: 22%;
-                    display: none;//隐藏进度条上的圆形按键
+                    display: none; //隐藏进度条上的圆形按键
                 }
 
-                :deep(.el-slider__runway .el-slider__bar) {
+                .el-slider__runway .el-slider__bar {
                     background-color: lightgreen; //绿色
                 }
+
+                .el-slider__marks-text {
+                    color: #fff; //字体颜色 
+                    font-size: large;
+                }
+
+                .el-slider__runway {
+                    width: 10px; //进度条宽度
+                }
+
+                .el-slider__runway .el-slider__bar {
+                    width: 100%;
+                }
+
+                .el-slider__marks-stop {
+                    width: 100%;
+                }
+            }
+
+            .temp_green {
+                :deep(.el-slider__runway .el-slider__bar) {
+                    background-color: #4CAF50; //绿色
+                }
+            }
+
+            .temp_red {
+                :deep(.el-slider__runway .el-slider__bar) {
+                    background-color: #F44336; //红色
+                }
             }
 
-            .high_temp {
+            .temp_orange {
                 :deep(.el-slider__runway .el-slider__bar) {
-                    background-color: crimson; //红色
+                    background-color: #fb8a1c; //橙
                 }
             }
         }
@@ -148,7 +362,7 @@ const marks = computed(() => ({
         .temp_pos1 {
             position: absolute;
             top: 10%;
-            left: 63%;
+            left: 64%;
         }
 
         .temp_pos2 {
@@ -159,8 +373,8 @@ const marks = computed(() => ({
 
         .temp_pos3 {
             position: absolute;
-            top: 20%;
-            left: 63%;
+            top: 15%;
+            left: 64%;
         }
 
         .temp_pos4 {
@@ -174,6 +388,39 @@ const marks = computed(() => ({
             margin-left: 12px;
         }
 
+
+
+    }
+
+    // 压力
+    .pressure_block {
+        background-color: #e4e4e4;
+        position: absolute;
+        top: 52%;
+        left: 31%;
+        z-index: 10;
+        border-radius: 50%;
+
+        .pressure_chart {
+            position: absolute;
+            top: -16%;
+            left: -16%;
+        }
+    }
+
+    .weight_block {
+        position: absolute;
+        z-index: 11;
+        top: 6%;
+        left: 35%;
+        text-align: center;
+
+        .weight_value {
+            font-size: 16px;
+            // color: #333;
+            background-color: #e4e4e4;
+            border: #333 1px solid;
+        }
     }
 }
 </style>

+ 92 - 0
ui/src/components/DCS/Z1TankComponent.vue

@@ -0,0 +1,92 @@
+<template>
+    <div class="tank" :style="{ width: `${iconSize}px`, height: `${iconSize}px` }">
+        <!-- Z1罐体 -->
+        <WaterTank :temperatureValue="temperatureValue" tankType="3" :waterLevelValue="waterLevelValue"
+            :iconSize="iconSize" :weightValue="weightValue" :title="title" class="z1_tank" />
+        <!-- n21 -->
+        <div :style="valveProgressStyle" class="valve_progress21 rotate_270" v-if="hasValve(valveNames[0])">
+            <ValveProgress :iconSize="valveIconSize" :title="valveNames[0]" :rotateAngle="270" :pipeLength="250"
+                :pipeLeftOffset="-47" :valveStatusArr="getValveStatusArr(valveNames[0])"
+                :pipeStatus="getValveAndStatus(valveNames[0])" :pipeReverse="true" />
+        </div>
+    </div>
+</template>
+<script setup>
+import WaterTank from '@/components/DCS/WaterTankComponent';
+import ValveProgress from '@/components/DCS/ValveProgressComponent.vue';
+import { defineProps, computed } from 'vue'
+import { useValveHelper } from '@/hooks/useValveHelper'
+
+const props = defineProps({
+    title: {
+        type: String,
+        required: true
+    },
+    temperatureValue: {//温度
+        type: Number,
+    },
+    waterLevelValue: {//液位
+        type: Number,
+    },
+    pressureValue: {//压力
+        type: Number,
+    },
+    weightValue: {//重量
+        type: Number,
+    },
+    valveArr: {//阀门数组
+        type: Array,
+    },
+    iconSize: {//罐体图标大小
+        type: Number,
+        default: 300,
+    },
+})
+// 将 props.valveArr 转换为响应式引用传入
+const { hasValve, getValveStatusArr, getValveAndStatus } = useValveHelper(props.valveArr)
+
+const valveNames = ['N21']
+
+//阀门icon大小(罐子300-阀门50)
+const valveIconSize = computed(() => {
+    return props.iconSize / 6;
+});
+
+//阀门进度样式
+const valveProgressStyle = computed(() => {
+    return {
+        width: `${valveIconSize.value}px`,
+        height: `${valveIconSize.value}px`,
+    }
+});
+
+
+</script>
+
+<style lang="scss" scoped>
+.page {
+    width: 100%;
+    height: 100%;
+    background-color: #0b172c;
+
+    .tank {
+        margin: 200px;
+        position: relative;
+        z-index: 10;
+
+        //罐体
+        .z1_tank {
+            position: absolute;
+            z-index: 10;
+        }
+
+        //阀门进度样式
+        .valve_progress21 {
+            position: absolute;
+            top: 98%;
+            left: 40%;
+        }
+
+    }
+}
+</style>

+ 168 - 0
ui/src/components/DCS/singleValveComponent.vue

@@ -0,0 +1,168 @@
+<template>
+    <!-- 阀门组件 -->
+    <div class="body_show">
+        <i class="icon iconfont icon-waterValve valve" :style="{ fontSize: `${props.iconSize}px` }">
+            <div :class="pointerClass" :style="pointerStyle"></div>
+        </i>
+        <div class="title" :style="titleStyle">{{ title }}</div>
+        <slot></slot>
+    </div>
+</template>
+
+<script setup>
+import { defineProps, computed } from 'vue'
+const props = defineProps({
+    title: {
+        type: String,
+        required: true
+    },
+    // 阀门开信号状态(非必填,默认 null)
+    valveOpenSignalStatus: {
+        type: Boolean,
+        default: null
+    },
+    // 阀门关闭信号状态(非必填,默认 null)
+    valveCloseSignalStatus: {
+        type: Boolean,
+        default: null
+    },
+    // 开阀门对应的对象的状态
+    valveOpenObj: {
+        type: Boolean,
+        required: true
+    },
+    //旋转角度
+    rotateAngle: {
+        type: Number,
+        default: 0
+    },
+    //阀门图标大小
+    iconSize: {
+        type: Number,
+        default: 50
+    }
+})
+
+
+
+// 计算 pointer 的 class
+const pointerClass = computed(() => {
+    // 未传入阀门信号状态时,该阀门为N阀门
+    if (null === props.valveOpenSignalStatus || null === props.valveCloseSignalStatus) {
+        // console.log('未传入阀门信号状态')
+        return props.valveOpenObj ? 'pointer_open' : 'pointer_close'
+    }
+    // 传入阀门信号状态时,该阀门为D阀门,根据信号状态判断指针样式
+    if (props.valveOpenSignalStatus) {
+        return 'pointer_open'
+    } else {
+        if (props.valveCloseSignalStatus) {
+            return 'pointer_close'
+        } else {
+            return props.valveOpenObj?.value ? 'pointer_to_open' : 'pointer_to_close'
+        }
+    }
+})
+
+// 计算 titleStyle 
+const titleStyle = computed(() => {
+    return {
+        transform: `rotate(${-props.rotateAngle}deg)`,
+    }
+})
+
+const pointerStyle = computed(() => {
+  return {
+    borderRadius: '4px',
+    width: `${props.iconSize * 0.16}px`,
+    height: `${props.iconSize * 0.506}px`,
+    position: 'absolute',
+    left: '43%',
+    top: '41.4%',
+  }
+})
+
+
+</script>
+
+
+<style scoped lang="scss">
+.body_show {
+    display: flex;
+    align-items: center;
+    // margin-right: 45px;
+    gap: 5px;
+
+    .title {
+        color: #C7D2E0;
+        position: absolute;
+        top: 100%;
+        left: 29%;
+    }
+
+    .valve {
+        //银色
+        color: #C7D2E0;
+        position: relative;
+        // margin-left: 18px;
+
+        //顺时针旋转动画
+        @keyframes rotate-clockwise {
+            from {
+                transform: rotate(0deg);
+            }
+
+            to {
+                transform: rotate(90deg);
+            }
+        }
+
+        //逆时针旋转动画
+        @keyframes rotate-counterclockwise {
+            from {
+                transform: rotate(90deg);
+            }
+
+            to {
+                transform: rotate(0deg);
+            }
+        }
+
+        .pointer_close {
+            background-color: #f10909;
+        }
+
+
+        .pointer_to_open {
+            animation: rotate-clockwise 15s linear infinite;
+            background-color: yellow;
+        }
+
+        .pointer_to_close {
+            animation: rotate-counterclockwise 15s linear infinite;
+            background-color: yellow;
+        }
+
+        .pointer_open {
+            //旋转90度
+            transform: rotate(90deg);
+            background-color: #2fb31e;
+        }
+    }
+
+    :deep(.el-switch) {
+        .el-switch__label {
+            color: #FFF;
+        }
+
+        .el-switch__label.is-active {
+            color: var(--el-color-primary);
+        }
+
+        .el-switch__core {
+            height: 25px;
+            min-width: 50px;
+        }
+    }
+}
+</style>

+ 50 - 0
ui/src/hooks/useValveHelper.js

@@ -0,0 +1,50 @@
+// src/hooks/useValveHelper.js
+import { unref } from 'vue'
+
+export function useValveHelper(valveArrRef) {
+  // 兼容 ref/reactive/普通数组
+  const getArr = () => unref(valveArrRef)
+
+  const hasValve = (code) => {
+    return getArr().some(v => v.code.toUpperCase() === code.toUpperCase())
+  }
+
+  const getValveStatusArr = (code) => {
+    const valve = getArr().find(v => v.code.toUpperCase() === code.toUpperCase())
+    return valve?.value || []
+  }
+
+
+  const getValveAndStatus = (...codes) => {
+    const arr = getArr();
+    let matched = [];
+
+    if (codes.length === 1) {
+      matched = arr.filter(item => item.code === codes[0]);
+    } else {
+      const codeSet = new Set(codes); // 更快匹配
+      matched = arr.filter(item => codeSet.has(item.code));
+    }
+
+    if (matched.length === 0) return false;
+    return matched.every(item => item.value?.[0] === true);
+  };
+
+  const getValveOrStatus = (...codes) => {
+    const arr = getArr();
+    if (codes.length === 1) {
+      return arr.some(item => item.code === codes[0] && item.value?.[0] === true);
+    } else {
+      const codeSet = new Set(codes);
+      return arr.some(item => codeSet.has(item.code) && item.value?.[0] === true);
+    }
+  };
+
+
+  return {
+    hasValve,
+    getValveStatusArr,
+    getValveAndStatus,
+    getValveOrStatus
+  }
+}

+ 1 - 2
ui/src/main.js

@@ -6,14 +6,13 @@ import '@/assets/dcs/iconfont/iconfont.css'// iconfont字体图标
 import '@/assets/dcs/iconfont_colour/iconfont.css'// iconfont彩色字体图标
 import DataVVue3 from '@kjgl77/datav-vue3'//dataV组件库
 import HeaderComponent from '@/components/DCS/HeaderComponent.vue'
-
 import ElementPlus from 'element-plus'
 import 'element-plus/dist/index.css'
 import 'element-plus/theme-chalk/dark/css-vars.css'
 import locale from 'element-plus/es/locale/lang/zh-cn'
 
 import '@/assets/styles/index.scss' // global css
-
+import '@/assets/styles/dcs/equipment.scss' // 引入自定义样式
 import App from './App'
 import store from './store'
 import router from './router'

+ 586 - 0
ui/src/views/configuratePage/m1Hydrolyze/index.vue

@@ -0,0 +1,586 @@
+<template>
+    <div class="page">
+        <HeaderComponent title="M1水解"></HeaderComponent>
+        <div class="content_page">
+            <M1Tank title="M1" :valveArr="valveArr_M1" :waterLevelValue="30" :pressureValue="0.444"
+                :temperatureValue="110" :iconSize="400" :weightValue="100" class="m1Flow_m1Tank"></M1Tank>
+            <S1Tank title="S1" :fanStatus="fanStatus" :valveArr="valveArr_S1" :pressureValue="0.444"
+                :waterLevelValue="30" :temperatureValue="20" :iconSize="300" :weightValue="100" class="m1Flow_s1Tank">
+            </S1Tank>
+            <S1Tank title="S2" :fanStatus="fanStatus" :valveArr="valveArr_S2" :pressureValue="0.444"
+                :waterLevelValue="30" :temperatureValue="20" :iconSize="300" :weightValue="100" class="m1Flow_s2Tank">
+            </S1Tank>
+            <S1Tank title="S3" :fanStatus="fanStatus" :valveArr="valveArr_S3" :pressureValue="0.444"
+                :waterLevelValue="30" :temperatureValue="20" :iconSize="300" :weightValue="100" class="m1Flow_s3Tank">
+            </S1Tank>
+            <div class="pumps">
+                <!-- lb9 -->
+                <div class="lb9_pos">
+                    <Pump title="进料泵" :hz="5000" :pumpStatus="正转" :iconSize="100"></Pump>
+                </div>
+            </div>
+            <div class="icon_others">
+                <div class="other1">
+                    <div class="other_title"> 储气罐</div>
+                    <i class="icon iconfont-colour icon-chuqiguan icon_cqg"></i>
+                </div>
+                <div class="other2">
+                    <div class="other_title"> 喷淋塔</div>
+                    <i class="icon iconfont-colour icon-penlinta"></i>
+                </div>
+                <div class="other3">
+                    <div class="other_title"> 蒸汽发生器</div>
+                    <i class="icon iconfont-colour icon-zhengqifashengqi"></i>
+                </div>
+            </div>
+            <!-- 外部管道排布 -->
+            <div class="outer_progress">
+                <!-- n10-进料泵-s1,s2,s3 -->
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveAndStatus('N10') && getValveOrStatus('D5', 'D6', 'D7')"
+                    :striped-flow="getValveAndStatus('N10') && getValveOrStatus('D5', 'D6', 'D7')"
+                    :duration="progressConfig.duration" class="progress_materials progress_pos1" />
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveAndStatus('N10') && getValveOrStatus('D5', 'D6', 'D7')"
+                    :striped-flow="getValveAndStatus('N10') && getValveOrStatus('D5', 'D6', 'D7')" :duration="20"
+                    class="progress_materials progress_pos2 rotate_270" />
+
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveAndStatus('N10') && getValveOrStatus('D5', 'D6', 'D7')"
+                    :striped-flow="getValveAndStatus('N10') && getValveOrStatus('D5', 'D6', 'D7')" :duration="30"
+                    class="progress_materials progress_pos3" />
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveAndStatus('N10') && getValveOrStatus('D6', 'D7')"
+                    :striped-flow="getValveAndStatus('N10') && getValveOrStatus('D6', 'D7')" :duration="20"
+                    class="progress_materials progress_pos3_2" />
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveAndStatus('N10', 'D7')" :striped-flow="getValveAndStatus('N10', 'D7')"
+                    :duration="20" class="progress_materials progress_pos3_3" />
+
+                <!-- 储气罐相关管道 -->
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveAndStatus('N8')" :striped-flow="getValveAndStatus('N8')"
+                    :duration="progressConfig.duration" class="progress_compressed_air progress_pos4 rotate_90" />
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveAndStatus('N4')" :striped-flow="getValveAndStatus('N4')"
+                    :duration="progressConfig.duration" class="progress_compressed_air progress_pos5 rotate_90" />
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveAndStatus('D8')" :striped-flow="getValveAndStatus('D8')" :duration="30"
+                    class="progress_compressed_air progress_pos6 rotate_90" />
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveAndStatus('D9')" :striped-flow="getValveAndStatus('D9')" :duration="30"
+                    class="progress_compressed_air progress_pos7 rotate_90" />
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveAndStatus('D10')" :striped-flow="getValveAndStatus('D10')" :duration="30"
+                    class="progress_compressed_air progress_pos8 rotate_90" />
+
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveOrStatus('N4','D8','D9','D10')" :striped-flow="getValveOrStatus('N4','D8','D9','D10')" :duration="30"
+                    class="progress_compressed_air progress_pos9_1" />
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveOrStatus('D8','D9','D10')" :striped-flow="getValveOrStatus('D8','D9','D10')" :duration="3"
+                    class="progress_compressed_air progress_pos9_2" />
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveOrStatus('D9','D10')" :striped-flow="getValveOrStatus('D9','D10')" :duration="30"
+                    class="progress_compressed_air progress_pos9_3" />
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveOrStatus('D10')" :striped-flow="getValveOrStatus('D10')" :duration="30"
+                    class="progress_compressed_air progress_pos9_4" />
+
+                <!-- 喷淋塔相关管道 -->
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveAndStatus('N11')" :striped-flow="getValveAndStatus('N11')" :duration="20"
+                    class="progress_stench progress_pos10_1" />
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveOrStatus('N11', 'D16')" :striped-flow="getValveOrStatus('N11', 'D16')"
+                    :duration="20" class="progress_stench progress_pos10_2" />
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveOrStatus('N11', 'D16', 'D17')"
+                    :striped-flow="getValveOrStatus('N11', 'D16', 'D17')" :duration="20"
+                    class="progress_stench progress_pos10_3" />
+
+                <!-- 蒸汽发生器相关管道 -->
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveOrStatus('D11')" :striped-flow="getValveOrStatus('D11')" :duration="20"
+                    class="progress_steam progress_pos11_1 rotate_180" />
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveOrStatus('D11', 'D12')" :striped-flow="getValveOrStatus('D11', 'D12')"
+                    :duration="20" class="progress_steam progress_pos11_2 rotate_180" />
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveOrStatus('D11', 'D12', 'D13')"
+                    :striped-flow="getValveOrStatus('D11', 'D12', 'D13')" :duration="10"
+                    class="progress_steam progress_pos11_3 rotate_180" />
+
+                <!-- n22,n23,n24通向下一流程相关管道 -->
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveOrStatus('N22')" :striped-flow="getValveOrStatus('N22')" :duration="20"
+                    class="progress_materials progress_pos12_1" />
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveOrStatus('N22', 'N23')" :striped-flow="getValveOrStatus('N22', 'N23')"
+                    :duration="20" class="progress_materials progress_pos12_2" />
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveOrStatus('N22', 'N23', 'N24')"
+                    :striped-flow="getValveOrStatus('N22', 'N23', 'N24')" :duration="10"
+                    class="progress_materials progress_pos12_3" />
+            </div>
+
+            <!-- 大箭头指向 -->
+            <div class="arrows">
+                <div class="arrow_pos1">
+                    <i class="icon iconfont icon-rightArrow arrow_icon" @click="router.push('/m2cl')"> </i>
+                    <div class="arrow_text">M2流程</div>
+                </div>
+                <div class="arrow_pos2">
+                    <i class="icon iconfont icon-rightArrow arrow_icon"> </i>
+                    <div class="arrow_text">物料进入</div>
+                </div>
+            </div>
+        </div>
+
+    </div>
+</template>
+
+<script setup>
+import M1Tank from '@/components/DCS/M1TankComponent.vue';
+import S1Tank from '@/components/DCS/S1TankComponent.vue';
+import Pump from '@/components/DCS/PumpComponent.vue';
+import { useValveHelper } from '@/hooks/useValveHelper'
+import { useRouter } from 'vue-router'
+
+const router = useRouter()
+//M1罐阀门状态
+const valveArr_M1 = [
+    {
+        code: 'N1',
+        value: [true],
+    },
+    // {
+    //     code: 'N2',
+    //     value: [true],
+    // },
+    // {
+    //     code: 'N3',
+    //     value: [true],
+    // },
+    {
+        code: 'N4',
+        value: [true],
+    },
+    {
+        code: 'N5',
+        value: [true],
+    },
+    {
+        code: 'N6',
+        value: [true],
+    },
+    {
+        code: 'N7',
+        value: [true],
+    },
+    {
+        code: 'N8',
+        value: [false],
+    },
+    {
+        code: 'N9',
+        value: [true],
+    },
+    {
+        code: 'N10',
+        value: [true],
+    },
+    {
+        code: 'N11',
+        value: [true],
+    },
+]
+
+//S1罐阀门状态
+const valveArr_S1 = [
+    {
+        code: 'N10',
+        value: [true],
+    },
+    {
+        code: 'D5',
+        value: [true, false, false],
+    },
+    {
+        code: 'D11',
+        value: [true, false, false],
+    },
+    {
+        code: 'N22',
+        value: [true]
+    },
+    {
+        code: 'D16',
+        value: [true, false, true],
+    },
+    {
+        code: 'D8',
+        value: [true, false, false],
+    },
+
+]
+//S2罐阀门状态
+const valveArr_S2 = [
+    {
+        code: 'D6',
+        value: [true, false, false],
+    },
+    {
+        code: 'D9',
+        value: [true, false, false],
+    },
+    {
+        code: 'D17',
+        value: [true, false, false],
+    },
+    {
+        code: 'D12',
+        value: [true, false, false],
+    },
+    {
+        code: 'N23',
+        value: [true],
+    },
+
+]
+//S3罐阀门状态
+const valveArr_S3 = [
+    {
+        code: 'D7',
+        value: [false, true, false],
+    },
+    {
+        code: 'D10',
+        value: [true, false, false],
+    },
+    {
+        code: 'D13',
+        value: [true, false, false],
+    },
+    {
+        code: 'N24',
+        value: [true],
+    },
+
+]
+//所有阀门状态
+const valveArr = [...new Set([
+    ...valveArr_M1,
+    ...valveArr_S1,
+    ...valveArr_S2,
+    ...valveArr_S3
+])];
+
+const { getValveAndStatus, getValveOrStatus } = useValveHelper(valveArr)
+
+//搅拌电机运行状态
+const fanStatus = true;
+
+//进度条配置
+const progressConfig = {
+    strokeWidth: 8,//进度条宽度
+    percentage: 100,//进度条百分比
+    duration: 10,//进度条流速
+    showText: false,//是否显示文字
+}
+
+</script>
+
+<style lang="scss" scoped>
+.page {
+    // width: 100%;
+    // height: 100%;
+    width: 1920px;
+    height: 1080px;
+    background-color: #0b172c;
+
+    .content_page {
+        position: relative;
+        width: 100%;
+        height: 1000px;
+
+        .m1Flow_m1Tank {
+            position: absolute;
+            top: 40%;
+            left: 9%;
+            transform: translate(-50%, -50%);
+        }
+
+        .m1Flow_s1Tank {
+            position: absolute;
+            top: 40%;
+            left: 31%;
+            transform: translate(-50%, -50%);
+        }
+
+        .m1Flow_s2Tank {
+            position: absolute;
+            top: 40%;
+            left: 53%;
+            transform: translate(-50%, -50%);
+        }
+
+        .m1Flow_s3Tank {
+            position: absolute;
+            top: 40%;
+            left: 75%;
+            transform: translate(-50%, -50%);
+        }
+
+        .pumps {
+            .lb9_pos {
+                position: absolute;
+                z-index: 5;
+                top: 88%;
+                left: 30.4%;
+                transform: translate(-50%, -50%);
+            }
+
+        }
+
+        //其他图标
+        .icon_others {
+            i {
+                font-size: 150px;
+            }
+
+            .other_title {
+                text-align: center;
+                color: aliceblue;
+            }
+
+            //储气罐
+            .other1 {
+                position: absolute;
+                left: -7.7%;
+                top: 10%;
+
+                .icon_cqg {
+                    font-size: 200px;
+                }
+            }
+
+            //喷淋塔
+            .other2 {
+                position: absolute;
+                right: 0%;
+            }
+
+            //蒸汽发生器
+            .other3 {
+                position: absolute;
+                top: 18%;
+                right: 0%;
+            }
+
+            .other1,
+            .other2,
+            .other3 {
+                z-index: 10;
+            }
+        }
+
+        .outer_progress {
+            .progress_pos1 {
+                position: absolute;
+                top: 88%;
+                left: 19.3%;
+                width: 168px;
+            }
+
+            .progress_pos2 {
+                position: absolute;
+                top: 56.2%;
+                left: 16.1%;
+                width: 530px;
+            }
+
+
+            .progress_pos3 {
+                position: absolute;
+                top: 30%;
+                left: 29.7%;
+                width: 196px;
+            }
+
+            .progress_pos3_2 {
+                position: absolute;
+                top: 30%;
+                left: 39.5%;
+                width: 430px;
+            }
+
+            .progress_pos3_3 {
+                position: absolute;
+                top: 30%;
+                left: 61.7%;
+                width: 425px;
+            }
+
+            .progress_pos4 {
+                position: absolute;
+                top: 37.2%;
+                left: -1%;
+                width: 168px;
+            }
+
+            .progress_pos5 {
+                position: absolute;
+                top: 31.6%;
+                left: 23.7%;
+                width: 265px;
+            }
+
+            .progress_pos6 {
+                position: absolute;
+                top: 44%;
+                left: 19.3%;
+                width: 510px;
+            }
+
+            .progress_pos7 {
+                position: absolute;
+                top: 44%;
+                left: 41.3%;
+                width: 510px;
+            }
+
+            .progress_pos8 {
+                position: absolute;
+                top: 44%;
+                left: 63.3%;
+                width: 510px;
+            }
+
+            .progress_pos9_1 {
+                position: absolute;
+                top: 18.5%;
+                left: 4.5%;
+                width: 505px;
+            }
+
+            .progress_pos9_2 {
+                position: absolute;
+                top: 18.5%;
+                left: 30.5%;
+                width: 42px;
+            }
+
+            .progress_pos9_3 {
+                position: absolute;
+                top: 18.5%;
+                left: 32.5%;
+                width: 426px;
+            }
+
+            .progress_pos9_4 {
+                position: absolute;
+                top: 18.5%;
+                left: 54.5%;
+                width: 426px;
+            }
+
+            .progress_pos10_1 {
+                position: absolute;
+                top: 11%;
+                left: 23%;
+                width: 419px;
+            }
+
+            .progress_pos10_2 {
+                position: absolute;
+                top: 11%;
+                left: 44.5%;
+                width: 431px;
+            }
+
+            .progress_pos10_3 {
+                position: absolute;
+                top: 11%;
+                left: 66.5%;
+                width: 518px;
+            }
+
+            .progress_pos11_1 {
+                position: absolute;
+                top: 25.3%;
+                left: 42.2%;
+                width: 428px;
+            }
+
+            .progress_pos11_2 {
+                position: absolute;
+                top: 25.3%;
+                left: 64.2%;
+                width: 428px;
+            }
+
+            .progress_pos11_3 {
+                position: absolute;
+                top: 25.3%;
+                left: 86.2%;
+                width: 200px;
+            }
+
+            .progress_pos12_1 {
+                position: absolute;
+                top: 81%;
+                left: 41.4%;
+                width: 430px;
+            }
+
+            .progress_pos12_2 {
+                position: absolute;
+                top: 81%;
+                left: 63.4%;
+                width: 430px;
+            }
+
+            .progress_pos12_3 {
+                position: absolute;
+                top: 81%;
+                left: 85.4%;
+                width: 195px;
+            }
+        }
+
+        .arrows {
+
+            .arrow_pos1,
+            .arrow_pos2 {
+                position: absolute;
+                top: 82.6%;
+                left: 95%;
+                transform: translate(-50%, -50%);
+
+                .arrow_icon {
+                    font-size: 100px;
+                    color: aliceblue;
+                }
+
+                .arrow_text {
+                    text-align: center;
+                    font-size: 20px;
+                    color: aliceblue;
+
+                }
+            }
+
+            .arrow_pos2 {
+                left: 7%;
+                top: 70%;
+                .arrow_icon{
+                    color: darkgray;
+                }
+                
+            }
+        }
+
+    }
+}
+</style>

+ 699 - 0
ui/src/views/configuratePage/m2OutMaterial/index.vue

@@ -0,0 +1,699 @@
+<template>
+    <div class="page">
+        <HeaderComponent title="M2出料"></HeaderComponent>
+        <div class="content_page">
+            <M1Tank title="M2" :valveArr="valveArr_M2" :waterLevelValue="30" :pressureValue="0.444"
+                :temperatureValue="110" :iconSize="400" :weightValue="100" class="m2Flow_m1Tank"></M1Tank>
+            <S1Tank title="S1" :fanStatus="fanStatus" :valveArr="valveArr_S1" :pressureValue="0.444"
+                :waterLevelValue="30" :temperatureValue="20" :iconSize="300" :weightValue="100" class="m2Flow_s1Tank">
+            </S1Tank>
+            <S1Tank title="S2" :fanStatus="fanStatus" :valveArr="valveArr_S2" :pressureValue="0.444"
+                :waterLevelValue="30" :temperatureValue="20" :iconSize="300" :weightValue="100" class="m2Flow_s2Tank">
+            </S1Tank>
+            <S1Tank title="S3" :fanStatus="fanStatus" :valveArr="valveArr_S3" :pressureValue="0.444"
+                :waterLevelValue="30" :temperatureValue="20" :iconSize="300" :weightValue="100" class="m2Flow_s3Tank">
+            </S1Tank>
+            <WaterTank title="P1" :tankType="3" class="m2Flow_p1Tank" :iconSize="300"></WaterTank>
+
+            <!-- <J1Tank title="J2" :valveArr="valveArr_J2" :iconSize="300" class="m2Flow_j1Tank"></J1Tank> -->
+            <div class="pumps">
+                <!-- lb9 -->
+                <div class="lb6_pos">
+                    <Pump title="出料泵" :hz="5000" :pumpStatus="正转" :iconSize="100"></Pump>
+                </div>
+                <!-- <div class="lb7_pos">
+                    <Pump title="换热进液泵" :hz="5000" :pumpStatus="正转" :iconSize="100"></Pump>
+                </div> -->
+            </div>
+            <div class="icon_others">
+                <div class="other1">
+                    <div class="other_title"> 储气罐</div>
+                    <i class="icon iconfont-colour icon-chuqiguan icon_cqg"></i>
+                </div>
+                <div class="other2">
+                    <div class="other_title"> 喷淋塔</div>
+                    <i class="icon iconfont-colour icon-penlinta"></i>
+                </div>
+                <div class="other3">
+                    <div class="other_title"> 蒸汽发生器</div>
+                    <i class="icon iconfont-colour icon-zhengqifashengqi"></i>
+                </div>
+            </div>
+            <!-- 外部管道排布 -->
+            <div class="outer_progress">
+                <!-- m2进料 -->
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveAndStatus('N12', 'N22')" :striped-flow="getValveAndStatus('N12', 'N22')"
+                    :duration="progressConfig.duration" class="progress_materials progress_pos1_1" />
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveAndStatus('N12') && getValveOrStatus('N22', 'N23')"
+                    :striped-flow="getValveAndStatus('N12') && getValveOrStatus('N22', 'N23')"
+                    :duration="progressConfig.duration" class="progress_materials progress_pos1_2" />
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveAndStatus('N12') && getValveOrStatus('N22', 'N23', 'N24')"
+                    :striped-flow="getValveAndStatus('N12') && getValveOrStatus('N22', 'N23', 'N24')"
+                    :duration="progressConfig.duration" class="progress_materials progress_pos1_3" />
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveAndStatus('N12') && getValveOrStatus('N22', 'N23', 'N24')"
+                    :striped-flow="getValveAndStatus('N12') && getValveOrStatus('N22', 'N23', 'N24')"
+                    :duration="progressConfig.duration" class="progress_materials progress_pos2 rotate_270" />
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveAndStatus('N12') && getValveOrStatus('N22', 'N23', 'N24')"
+                    :striped-flow="getValveAndStatus('N12') && getValveOrStatus('N22', 'N23', 'N24')"
+                    :duration="progressConfig.duration" class="progress_materials progress_pos2_2" />
+
+                <!-- m2-换热进液泵-j2 -->
+                <!-- <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                     :striped="getValveAndStatus('N15') && getValveOrStatus('N16', 'N17')"
+                    :striped-flow="getValveAndStatus('N15') && getValveOrStatus('N16', 'N17')"
+                    :duration="progressConfig.duration" class="progress_red progress_pos3" />
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                     :striped="getValveAndStatus('N15', 'D4') && getValveOrStatus('N16', 'N17')"
+                    :striped-flow="getValveAndStatus('N15', 'D4') && getValveOrStatus('N16', 'N17')"
+                    :duration="progressConfig.duration" class="progress_red progress_pos4 rotate_270" />
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                     :striped="getValveAndStatus('N15', 'D4') && getValveOrStatus('N16', 'N17')"
+                    :striped-flow="getValveAndStatus('N15', 'D4') && getValveOrStatus('N16', 'N17')" :duration="20"
+                    class="progress_red progress_pos5" />
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                     :striped="getValveAndStatus('N15', 'D4') && getValveOrStatus('N16', 'N17')"
+                    :striped-flow="getValveAndStatus('N15', 'D4') && getValveOrStatus('N16', 'N17')" :duration="30"
+                    class="progress_red progress_pos6 rotate_90" /> -->
+
+                <!-- 喷淋塔相关管道 -->
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveOrStatus('D16')" :striped-flow="getValveOrStatus('D16')" :duration="20"
+                    class="progress_stench progress_pos7_1" />
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveOrStatus('D16', 'D17')" :striped-flow="getValveOrStatus('D16', 'D17')"
+                    :duration="50" class="progress_stench progress_pos7_2" />
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveOrStatus('D16', 'D17', 'N20')" :striped-flow="getValveOrStatus('D16', 'D17', 'N20')"
+                    :duration="40" class="progress_stench progress_pos7_3" />
+
+                <!-- 蒸汽发生器相关管道 -->
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveOrStatus('D11')"
+                    :striped-flow="getValveOrStatus('D11')" :duration="20"
+                    class="progress_steam progress_pos8_1" />
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveOrStatus('D11', 'D12')"
+                    :striped-flow="getValveOrStatus('D11', 'D12')" :duration="20"
+                    class="progress_steam progress_pos8_2" />
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveOrStatus('D11', 'D12','D13')"
+                    :striped-flow="getValveOrStatus('D11', 'D12','D13')" :duration="50"
+                    class="progress_steam progress_pos8_3" />
+
+                <!-- 储气罐相关管道 -->
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveAndStatus('D8')" :striped-flow="getValveAndStatus('D8')" :duration="20"
+                    class="progress_compressed_air progress_pos9 rotate_90" />
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveAndStatus('D9')" :striped-flow="getValveAndStatus('D9')" :duration="20"
+                    class="progress_compressed_air progress_pos10 rotate_90" />
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveAndStatus('D10')" :striped-flow="getValveAndStatus('D10')" :duration="20"
+                    class="progress_compressed_air progress_pos11 rotate_90" />
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="pumpStatus_N18" :striped-flow="pumpStatus_N18" :duration="20"
+                    class="progress_compressed_air progress_pos12 rotate_90" />
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveAndStatus('N14')" :striped-flow="getValveAndStatus('N14')" :duration="20"
+                    class="progress_compressed_air progress_pos13 rotate_90" />
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveOrStatus('D9', 'D10', 'N14') || pumpStatus_N18"
+                    :striped-flow="getValveOrStatus('D9', 'D10', 'N14') || pumpStatus_N18" :duration="20"
+                    class="progress_compressed_air progress_pos14_1" />
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveOrStatus('D10', 'N14') || pumpStatus_N18"
+                    :striped-flow="getValveOrStatus('D10', 'N14') || pumpStatus_N18" :duration="20"
+                    class="progress_compressed_air progress_pos14_2" />
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveOrStatus('N14') || pumpStatus_N18"
+                    :striped-flow="getValveOrStatus('N14') || pumpStatus_N18" :duration="20"
+                    class="progress_compressed_air progress_pos14_3" />
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveOrStatus('N14')" :striped-flow="getValveOrStatus('N14')" :duration="20"
+                    class="progress_compressed_air progress_pos14_4" />
+
+                <!-- 通向m1流程页面的管道 -->
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveOrStatus('D6', 'D7')" :striped-flow="getValveOrStatus('D6', 'D7')"
+                    :duration="progressConfig.duration" class="progress_materials progress_pos15_1" />
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveAndStatus('D7')" :striped-flow="getValveAndStatus('D7')"
+                    :duration="progressConfig.duration" class="progress_materials progress_pos15_2" />
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveOrStatus('D5', 'D6', 'D7')" :striped-flow="getValveOrStatus('D5', 'D6', 'D7')"
+                    :duration="progressConfig.duration" class="progress_materials progress_pos16 rotate_90" />
+
+                <!-- 通向换热流程的管道 -->
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveOrStatus('D16', 'D17') && getValveAndStatus('N15')"
+                    :striped-flow="getValveOrStatus('D16', 'D17') && getValveAndStatus('N15')"
+                    :duration="progressConfig.duration" class="progress_materials progress_pos17 rotate_270" />
+                <!-- 通向p1的管道 -->
+                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
+                    :striped="getValveOrStatus('N13')" :striped-flow="getValveOrStatus('N13')"
+                    :duration="progressConfig.duration" class="progress_red progress_pos18" />
+            </div>
+            <!-- 大箭头指向 -->
+            <div class="arrows">
+                <div class="arrow_pos1">
+                    <i class="icon iconfont icon-rightArrow arrow_icon rotate_270" @click="router.push('/m1sj')"> </i>
+                    <div class="arrow_text">M1流程</div>
+                </div>
+
+                <div class="arrow_pos2">
+                    <i class="icon iconfont icon-rightArrow arrow_icon rotate_270" @click="router.push('/hr')"> </i>
+                    <div class="arrow_text">换热流程</div>
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script setup>
+import M1Tank from '@/components/DCS/M1TankComponent.vue';
+import S1Tank from '@/components/DCS/S1TankComponent.vue';
+import WaterTank from '@/components/DCS/WaterTankComponent.vue';
+import J1Tank from '@/components/DCS/J1TankComponent.vue';
+import Pump from '@/components/DCS/PumpComponent.vue';
+import { useValveHelper } from '@/hooks/useValveHelper'
+import { useRouter } from 'vue-router'
+import { computed } from 'vue';
+
+const router = useRouter()
+//M1罐阀门状态
+const valveArr_M2 = [
+    {
+        code: 'N12',
+        value: [true],
+    },
+    {
+        code: 'N14',
+        value: [false],
+    },
+    {
+        code: 'N15',
+        value: [false],
+    },
+    {
+        code: 'N16',
+        value: [true],
+    },
+    {
+        code: 'N17',
+        value: [true],
+    },
+    {
+        code: 'N20',
+        value: [true],
+    },
+    {
+        code: 'N13',
+        value: [true],
+    },
+    {
+        code: 'N18',
+        value: [true],
+    },
+    // {
+    //     code: 'N19',
+    //     value: [true],
+    // },
+]
+
+//S1罐阀门状态
+const valveArr_S1 = [
+    {
+        code: 'N10',
+        value: [true],
+    },
+    {
+        code: 'D5',
+        value: [true, false, false],
+    },
+    {
+        code: 'D11',
+        value: [true, false, false],
+    },
+    {
+        code: 'N22',
+        value: [true]
+    },
+    {
+        code: 'D16',
+        value: [true, false, true],
+    },
+    {
+        code: 'D8',
+        value: [true, false, false],
+    },
+
+]
+//S2罐阀门状态
+const valveArr_S2 = [
+    {
+        code: 'D6',
+        value: [true, false, false],
+    },
+    {
+        code: 'D9',
+        value: [true, false, false],
+    },
+    {
+        code: 'D17',
+        value: [true, false, false],
+    },
+    {
+        code: 'D12',
+        value: [true, false, false],
+    },
+    {
+        code: 'N23',
+        value: [true],
+    },
+
+]
+//S3罐阀门状态
+const valveArr_S3 = [
+    {
+        code: 'D7',
+        value: [false, true, false],
+    },
+    {
+        code: 'D10',
+        value: [true, false, false],
+    },
+    {
+        code: 'D13',
+        value: [true, false, false],
+    },
+    {
+        code: 'N24',
+        value: [true],
+    },
+
+]
+
+const valveArr_J2 = [
+    // {
+    //     code: 'D3',
+    //     value: [true, false, true],
+    // },
+    {
+        code: 'D4',
+        value: [true, false, true],
+    }
+]
+//所有阀门状态
+const valveArr = [...new Set([
+    ...valveArr_M2,
+    ...valveArr_S1,
+    ...valveArr_S2,
+    ...valveArr_S3,
+    ...valveArr_J2
+])];
+
+const { getValveAndStatus, getValveOrStatus } = useValveHelper(valveArr)
+
+//搅拌电机运行状态
+const fanStatus = true;
+
+//进度条配置
+const progressConfig = {
+    strokeWidth: 8,//进度条宽度
+    percentage: 100,//进度条百分比
+    duration: 10,//进度条流速
+    showText: false,//是否显示文字
+}
+
+//N18处管道流通状态(多次用到,所以单独抽出来)
+const pumpStatus_N18 = computed(() => {
+    return getValveAndStatus('N18') && getValveOrStatus('N16', 'N17')
+})
+
+</script>
+
+<style lang="scss" scoped>
+.page {
+    // width: 100%;
+    // height: 100%;
+    width: 1920px;
+    height: 1080px;
+    background-color: #0b172c;
+
+    .content_page {
+        position: relative;
+        width: 100%;
+        height: 1000px;
+
+        .m2Flow_m1Tank {
+            position: absolute;
+            top: 40%;
+            left: 59%;
+            transform: translate(-50%, -50%);
+        }
+
+        .m2Flow_s1Tank {
+            position: absolute;
+            top: 40%;
+            left: 3%;
+            transform: translate(-50%, -50%);
+        }
+
+        .m2Flow_s2Tank {
+            position: absolute;
+            top: 40%;
+            left: 18%;
+            transform: translate(-50%, -50%);
+        }
+
+        .m2Flow_s3Tank {
+            position: absolute;
+            top: 40%;
+            left: 33%;
+            transform: translate(-50%, -50%);
+        }
+
+        .m2Flow_p1Tank {
+            z-index: 10;
+            position: absolute;
+            top: 62%;
+            left: 90%;
+            transform: translate(-50%, -50%);
+        }
+
+        .pumps {
+
+            .lb6_pos,
+            .lb7_pos {
+                z-index: 15;
+            }
+
+            .lb6_pos {
+                position: absolute;
+                top: 81%;
+                left: 53.2%;
+                transform: translate(-50%, -50%);
+            }
+
+            .lb7_pos {
+                position: absolute;
+                top: 23%;
+                left: 69.6%;
+                transform: translate(-50%, -50%);
+            }
+
+        }
+
+        //其他图标
+        .icon_others {
+            i {
+                font-size: 150px;
+            }
+
+            .other_title {
+                text-align: center;
+                color: aliceblue;
+            }
+
+            //储气罐
+            .other1 {
+                position: absolute;
+                left: -6.7%;
+                top: 10%;
+
+
+                .icon_cqg {
+                    font-size: 200px;
+                }
+            }
+
+            //喷淋塔
+            .other2 {
+                position: absolute;
+                right: 0%;
+            }
+
+            //蒸汽发生器
+            .other3 {
+                position: absolute;
+                top: 18%;
+                right: 0%;
+            }
+
+            .other1,
+            .other2,
+            .other3 {
+                z-index: 10;
+            }
+        }
+
+        //箭头指向
+        .arrows {
+
+            .arrow_pos1,
+            .arrow_pos2 {
+                position: absolute;
+                z-index: 15;
+                top: 6%;
+                left: 14.3%;
+                transform: translate(-50%, -50%);
+                display: flex;
+                //竖直居中
+                align-items: center;
+
+                .arrow_icon {
+                    font-size: 100px;
+                    color: #fff;
+                }
+
+                .arrow_text {
+                    font-size: 30px;
+                    color: #fff;
+                }
+            }
+
+            .arrow_pos2 {
+                left: 68.3%;
+                top: 9%;
+            }
+        }
+
+        //外部管道排布
+        .outer_progress {
+            .progress_pos1_1 {
+                position: absolute;
+                top: 81.1%;
+                left: 13.4%;
+                width: 15.3%;
+            }
+
+            .progress_pos1_2 {
+                position: absolute;
+                top: 81.1%;
+                left: 28.4%;
+                width: 15.3%;
+            }
+
+            .progress_pos1_3 {
+                position: absolute;
+                top: 81.1%;
+                left: 43.4%;
+                width: 15.3%;
+            }
+
+            .progress_pos2 {
+                position: absolute;
+                top: 76.1%;
+                left: 48.6%;
+                width: 8.3%;
+            }
+
+            .progress_pos2_2 {
+                position: absolute;
+                top: 68.4%;
+                left: 52.6%;
+                width: 7.3%;
+            }
+
+            .progress_pos3 {
+                position: absolute;
+                top: 23.1%;
+                left: 58%;
+                width: 11.3%;
+            }
+
+            .progress_pos4 {
+                position: absolute;
+                top: 18.1%;
+                left: 66.5%;
+                width: 5.3%;
+            }
+
+            .progress_pos5 {
+                position: absolute;
+                top: 13.1%;
+                left: 69%;
+                width: 18.9%;
+            }
+
+            .progress_pos6 {
+                position: absolute;
+                top: 40%;
+                left: 73.6%;
+                width: 28.3%;
+            }
+
+            //喷淋塔相关管道
+            .progress_pos7_1 {
+                position: absolute;
+                top: 11%;
+                left: 16.5%;
+                width: 15.3%;
+            }
+
+            .progress_pos7_2 {
+                position: absolute;
+                top: 11%;
+                left: 31.5%;
+                width: 41.8%;
+            }
+
+            .progress_pos7_3 {
+                position: absolute;
+                top: 11%;
+                left: 73%;
+                width: 20.8%;
+            }
+
+            //蒸汽发生器相关管道
+            .progress_pos8_1 {
+                position: absolute;
+                top: 25.3%;
+                left: 14.2%;
+                width: 15.3%;
+            }
+
+            .progress_pos8_2 {
+                position: absolute;
+                top: 25.3%;
+                left: 29.2%;
+                width: 15.3%;
+            }
+
+            .progress_pos8_3 {
+                position: absolute;
+                top: 25.3%;
+                left: 44.2%;
+                width: 52.3%;
+            }
+
+            //储气罐相关管道
+            .progress_pos9 {
+                position: absolute;
+                top: 50%;
+                left: -5.4%;
+                width: 20.3%;
+            }
+
+            .progress_pos10 {
+                position: absolute;
+                top: 42%;
+                left: 5.6%;
+                width: 28.3%;
+            }
+
+            .progress_pos11 {
+                position: absolute;
+                top: 42%;
+                left: 20.6%;
+                width: 28.3%;
+            }
+
+            .progress_pos12 {
+                position: absolute;
+                top: 30%;
+                left: 45.2%;
+                width: 16.3%;
+            }
+
+            .progress_pos13 {
+                position: absolute;
+                top: 29.8%;
+                left: 72.7%;
+                width: 16%;
+            }
+
+            .progress_pos14_1 {
+                position: absolute;
+                top: 14.6%;
+                left: 6.6%;
+                width: 13.3%;
+            }
+
+            .progress_pos14_2 {
+                position: absolute;
+                top: 14.6%;
+                left: 19.6%;
+                width: 15.3%;
+            }
+
+            .progress_pos14_3 {
+                position: absolute;
+                top: 14.6%;
+                left: 34.6%;
+                width: 18.8%;
+            }
+
+            .progress_pos14_4 {
+                position: absolute;
+                top: 14.6%;
+                left: 53.2%;
+                width: 27.7%;
+            }
+
+            // 通向m1流程页面的管道
+            .progress_pos15_1 {
+                position: absolute;
+                top: 30.6%;
+                left: 11.6%;
+                width: 15.3%;
+            }
+
+            .progress_pos15_2 {
+                position: absolute;
+                top: 30.6%;
+                left: 26.6%;
+                width: 15.3%;
+            }
+
+            .progress_pos16 {
+                position: absolute;
+                top: 20%;
+                left: 6.2%;
+                width: 11%;
+            }
+
+            .progress_pos17 {
+                position: absolute;
+                top: 17.3%;
+                left: 62.2%;
+                width: 6%;
+            }
+
+            .progress_pos18 {
+                position: absolute;
+                top: 60.8%;
+                left: 80.6%;
+                width: 9%;
+            }
+
+        }
+
+    }
+}
+</style>

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است