Explorar el Código

feat(components):硫酸钙流程相关组件封装

HMY hace 10 meses
padre
commit
1fe4707a92
Se han modificado 30 ficheros con 4222 adiciones y 0 borrados
  1. 101 0
      ui/src/components/HnyzDcs/ArrowComponent.vue
  2. 288 0
      ui/src/components/HnyzDcs/BK200SeparatorComponent.vue
  3. 236 0
      ui/src/components/HnyzDcs/BK30SeparatorComponent.vue
  4. 95 0
      ui/src/components/HnyzDcs/ConveyorComponent.vue
  5. 167 0
      ui/src/components/HnyzDcs/D40SeparatorComponent.vue
  6. 139 0
      ui/src/components/HnyzDcs/ETypeTankComponent.vue
  7. 161 0
      ui/src/components/HnyzDcs/ETypeTankValves1Component.vue
  8. 149 0
      ui/src/components/HnyzDcs/ETypeTankValves2Component.vue
  9. 150 0
      ui/src/components/HnyzDcs/FTypeTankComponent.vue
  10. 158 0
      ui/src/components/HnyzDcs/FTypeTankValvesComponent.vue
  11. 78 0
      ui/src/components/HnyzDcs/FlowMeterComponent.vue
  12. 57 0
      ui/src/components/HnyzDcs/IonDetectionMachineComponent.vue
  13. 50 0
      ui/src/components/HnyzDcs/PageIconComponent.vue
  14. 105 0
      ui/src/components/HnyzDcs/PhSliderComponent.vue
  15. 50 0
      ui/src/components/HnyzDcs/PipeComponent.vue
  16. 105 0
      ui/src/components/HnyzDcs/PumpProgressComponent.vue
  17. 146 0
      ui/src/components/HnyzDcs/RTypeTankComponent.vue
  18. 219 0
      ui/src/components/HnyzDcs/RTypeTankValvesComponent.vue
  19. 125 0
      ui/src/components/HnyzDcs/STypeTankComponent.vue
  20. 136 0
      ui/src/components/HnyzDcs/STypeTankValvesComponent.vue
  21. 81 0
      ui/src/components/HnyzDcs/SeparatorComponent.vue
  22. 201 0
      ui/src/components/HnyzDcs/SeparatorTowerValvesComponent.vue
  23. 114 0
      ui/src/components/HnyzDcs/TempSliderComponent.vue
  24. 85 0
      ui/src/components/HnyzDcs/TransportProgressComponent.vue
  25. 127 0
      ui/src/components/HnyzDcs/VTypeTank2Component.vue
  26. 189 0
      ui/src/components/HnyzDcs/VTypeTankComponent.vue
  27. 209 0
      ui/src/components/HnyzDcs/VTypeTankValves2Component.vue
  28. 200 0
      ui/src/components/HnyzDcs/VTypeTankValvesComponent.vue
  29. 143 0
      ui/src/components/HnyzDcs/WaterSinkComponent.vue
  30. 158 0
      ui/src/components/HnyzDcs/WaterSinkValvesComponent.vue

+ 101 - 0
ui/src/components/HnyzDcs/ArrowComponent.vue

@@ -0,0 +1,101 @@
+<template>
+    <div class="arrow_default" :style="arrowStyle" @click="handleClick">
+        <div class="arrow_text" :style="getFontSize" v-if="!props.iconFirst">{{ props.arrowText }}</div>
+        <i class="icon iconfont icon-rightArrow arrow_icon" :style="{ transform: getArrowRotation }"
+            :class="{ can_click: !!props.linkUrl }"></i>
+        <div class="arrow_text" :style="getFontSize" v-if="props.iconFirst">{{ props.arrowText }}</div>
+    </div>
+</template>
+
+<script setup>
+import { useRouter } from 'vue-router'
+import { computed } from 'vue'
+
+const router = useRouter()
+
+const props = defineProps({
+    arrowText: {
+        type: String,
+        default: '默认',
+    },
+    flexDir: {// 主轴方向 row | column
+        type: String,
+        default: 'row',
+    },
+    arrowDir: {// 箭头方向 up | down | left | right
+        type: String,
+        default: 'right',
+    },
+    linkUrl: {// 跳转链接
+        type: String,
+        default: '',
+    },
+    iconFirst: {// 是否图标在前
+        type: Boolean,
+        default: true,
+    },
+    //字体大小
+    fontSize: {
+        type: Number,
+        default: 30,
+    },
+})
+
+// 箭头容器样式(flex布局)
+const arrowStyle = computed(() => ({
+    display: 'flex',
+    flexDirection: props.flexDir,
+    justifyContent: 'center',
+    alignItems: 'center',
+}))
+
+// 箭头方向转换
+const getArrowRotation = computed(() => {
+    const map = {
+        up: 'rotate(-90deg)',
+        down: 'rotate(90deg)',
+        left: 'rotate(180deg)',
+        right: 'rotate(0deg)',
+    }
+    return map[props.arrowDir] || 'rotate(0deg)'
+})
+
+// 字体大小
+const getFontSize = computed(() => ({
+    fontSize: `${props.fontSize}px`,
+}))
+
+// 点击跳转
+const handleClick = () => {
+    if (props.linkUrl) {
+        router.push(props.linkUrl)
+    }
+}
+</script>
+
+
+<style lang="scss" scoped>
+.arrow_default {
+    position: absolute;
+    z-index: 15;
+
+    .arrow_icon {
+        font-size: 100px;
+        color: rgb(164, 161, 161);
+    }
+
+    //可点击
+    .can_click {
+        color: #fff;
+
+        &:hover {
+            cursor: pointer;
+            opacity: 0.8;
+        }
+    }
+
+    .arrow_text {
+        color: #fff;
+    }
+}
+</style>

+ 288 - 0
ui/src/components/HnyzDcs/BK200SeparatorComponent.vue

@@ -0,0 +1,288 @@
+<template>
+    <div class="tank_valves" :style="getTankBodyStyle">
+        <Separator :title="title" :iconWidth="iconWidth" :iconHeight="iconHeight" :iconSize="iconSize"></Separator>
+
+        <!-- 阀门进度 -->
+        <div class="valve_progress">
+            <div :style="valveProgressStyle" class="valve_progress1" v-if="valveNames[0]">
+                <ValveProgress :iconSize="valveIconSize" :title="valveNames[0]" :pipeLength="210" :pipeLeftOffset="-60"
+                    :valveStatusArr="initValveStatusArr" progressType="steam" :pipeStatus="initPipeStatus" />
+            </div>
+            <div :style="valveProgressStyle" class="valve_progress2" v-if="valveNames[1]">
+                <ValveProgress :iconSize="valveIconSize" :title="valveNames[1]" :pipeLength="324" :pipeLeftOffset="-54"
+                    :valveStatusArr="initValveStatusArr" progressType="steam" :pipeStatus="initPipeStatus" />
+            </div>
+            <div :style="valveProgressStyle" class="valve_progress3" v-if="valveNames[2]">
+                <ValveProgress :iconSize="valveIconSize" :title="valveNames[2]" :pipeLength="430" :pipeLeftOffset="-267"
+                    :valveStatusArr="initValveStatusArr" progressType="steam" :pipeStatus="initPipeStatus" />
+            </div>
+            <div :style="valveProgressStyle" class="valve_progress4" v-if="valveNames[3]">
+                <ValveProgress :iconSize="valveIconSize" :title="valveNames[3]" :pipeLength="324" :pipeLeftOffset="-162"
+                    :valveStatusArr="initValveStatusArr" progressType="steam" :pipeStatus="initPipeStatus" />
+            </div>
+            <div :style="valveProgressStyle" class="valve_progress5" v-if="valveNames[4]">
+                <ValveProgress :iconSize="valveIconSize" :title="valveNames[4]" :pipeLength="324" :pipeLeftOffset="-136"
+                    :valveStatusArr="initValveStatusArr" progressType="steam" :pipeStatus="initPipeStatus" />
+            </div>
+            <div :style="valveProgressStyle" class="valve_progress6 rotate_90" v-if="valveNames[5]">
+                <ValveProgress :iconSize="valveIconSize" :title="valveNames[5]" :rotateAngle="90" :pipeLength="211"
+                    :pipeLeftOffset="-55" :valveStatusArr="initValveStatusArr" progressType="steam"
+                    :pipeStatus="initPipeStatus" />
+            </div>
+            <div :style="valveProgressStyle" class="valve_progress7 rotate_270" v-if="valveNames[6]">
+                <ValveProgress :iconSize="valveIconSize" :title="valveNames[6]" :rotateAngle="270" :pipeLength="350"
+                    :pipeLeftOffset="-197" :valveStatusArr="initValveStatusArr" progressType="steam"
+                    :pipeStatus="initPipeStatus" :pipeReverse="true" />
+            </div>
+        </div>
+
+        <!-- 运输器及管道 -->
+        <div class="transport_progress">
+            <div :style="transportProgressStyle" class="transport_progress1" v-if="transportName">
+                <TransportProgress :title="transportName" :iconSize="transportIconSize" :pipeStatus="initPipeStatus"
+                    progressType="steam"></TransportProgress>
+            </div>
+        </div>
+
+        <!-- 拓展管道排布 -->
+        <div class="expand_pipe" v-if="showExpandPipe">
+            <!-- 左上ACV2045向上延伸管道 -->
+            <Pipe :pipeStatus="initPipeStatus" class="progress_steam progress_pos1 rotate_90"></Pipe>
+            <!-- 右上ACV2049,ACV2050向上延伸管道 -->
+            <Pipe :pipeStatus="initPipeStatus" class="progress_steam progress_pos2_1 rotate_270"></Pipe>
+            <Pipe :pipeStatus="initPipeStatus" class="progress_steam progress_pos2_2 rotate_270"></Pipe>
+            <!-- 左下ACV2046向下延伸管道 -->
+            <Pipe :pipeStatus="initPipeStatus" class="progress_steam progress_pos3 rotate_270"></Pipe>
+            <!-- 右上ACV2048,ACV2047向上延伸管道 -->
+            <Pipe :pipeStatus="initPipeStatus" class="progress_steam progress_pos4"></Pipe>
+            <Pipe :pipeStatus="initPipeStatus" class="progress_steam progress_pos5 rotate_90"></Pipe>
+            <!-- 右下ACV2051向下延伸管道 -->
+            <Pipe :pipeStatus="initPipeStatus" class="progress_steam progress_pos6 rotate_90"></Pipe>
+            <!-- 下方PD2003向下延伸管道 -->
+            <Pipe :pipeStatus="initPipeStatus" class="progress_steam progress_pos7 rotate_90"></Pipe>
+        </div>
+    </div>
+</template>
+
+<script setup>
+import Separator from '@/components/HnyzDcs/SeparatorComponent.vue';
+import ValveProgress from '@/components/DCS/ValveProgressComponent.vue';
+import TransportProgress from '@/components/HnyzDcs/TransportProgressComponent.vue';
+import Pipe from '@/components/HnyzDcs/PipeComponent.vue';
+import { computed } from 'vue'
+const initValveStatusArr = [true]
+const initPipeStatus = true
+const props = defineProps({
+    tempValue: {//temp
+        type: Number,
+        default: null
+    },
+    waterLevelValue: {// 水位值
+        type: Number,
+        default: -1,// -1表示未传水位值
+    },
+    fanStatus: {//风扇状态
+        type: Boolean,
+        default: false,
+    },
+    iconSize: {//图标大小
+        type: Number,
+        default: 200,
+    },
+    title: {//罐名
+        type: String,
+    },
+    iconWidth: {//图标宽度
+        type: Number,
+    },
+    iconHeight: {//图标高度
+        type: Number,
+    },
+    //是否显示拓展管道
+    showExpandPipe: {
+        type: Boolean,
+        default: false,
+    },
+})
+
+
+//默认阀门名称数组
+const defaultValveNames = new Array(7).fill('ACV_default')
+// 阀门名称映射表
+const valveNameArr = {
+    'S2003A': ['ACV2045A', 'ACV2046A', 'ACV2049A', 'ACV2050A', 'ACV2051A', 'ACV2047A', 'ACV2048A'],
+    'S2003B': ['ACV2045B', 'ACV2046B', 'ACV2049B', 'ACV2050B', 'ACV2051B', 'ACV2047B', 'ACV2048B'],
+    'S2003C': ['ACV2045C', 'ACV2046C', 'ACV2049C', 'ACV2050C', 'ACV2051C', 'ACV2047C', 'ACV2048C'],
+}
+//阀门名称数组,根据罐名来匹配
+const valveNames = computed(() => {
+    return valveNameArr[props.title] || defaultValveNames
+})
+
+//默认pd名称
+const defaultTransportName = 'PD_default'
+//pd名称映射表
+const transportNameArr = {
+    'S2003A': 'PD2003A',
+    'S2003B': 'PD2003B',
+    'S2003C': 'PD2003C',
+}
+//pd名称
+const transportName = computed(() => {
+    return transportNameArr[props.title] || defaultTransportName
+})
+
+//罐体样式
+const getTankBodyStyle = computed(() => ({
+    width: `${props.iconWidth ?? props.iconSize}px`,
+    height: `${props.iconHeight ?? props.iconSize}px`,
+}))
+
+//阀门icon大小(罐子200-阀门50)
+const valveIconSize = computed(() => {
+    return props.iconSize * 0.25;
+});
+
+//阀门进度样式
+const valveProgressStyle = computed(() => {
+    return {
+        width: `${valveIconSize.value}px`,
+        height: `${valveIconSize.value}px`,
+    }
+});
+
+//泵icon大小(罐子200-泵80)
+const transportIconSize = computed(() => {
+    return props.iconSize * 0.3;
+});
+
+//泵进度样式
+const transportProgressStyle = computed(() => {
+    return {
+        width: `${transportIconSize.value}px`,
+        height: `${transportIconSize.value}px`,
+    }
+});
+
+</script>
+
+<style scoped lang="scss">
+.tank_valves {
+    position: relative;
+    z-index: 10;
+
+    .valve_progress {
+        .valve_progress1 {
+            position: absolute;
+            top: 10%;
+            left: -33%;
+        }
+
+        .valve_progress2 {
+            position: absolute;
+            top: 48%;
+            left: -64%;
+        }
+
+        .valve_progress3 {
+            position: absolute;
+            top: 2%;
+            left: 120%;
+        }
+
+        .valve_progress4 {
+            position: absolute;
+            top: 37%;
+            left: 120%;
+        }
+
+        .valve_progress5 {
+            position: absolute;
+            top: 72%;
+            left: 94%;
+        }
+
+        .valve_progress6 {
+            position: absolute;
+            top: -8%;
+            left: 78%;
+        }
+
+        .valve_progress7 {
+            position: absolute;
+            top: -8%;
+            left: 106%;
+        }
+    }
+
+    .transport_progress {
+        .transport_progress1 {
+            position: absolute;
+            top: 116%;
+            left: 43%;
+            transform: translate(-50%, -50%);
+        }
+    }
+
+    //拓展管道排布
+    .expand_pipe {
+        .progress_pos1 {
+            position: absolute;
+            top: -46%;
+            left: -46%;
+            width: 144%;
+        }
+
+        .progress_pos2_1 {
+            position: absolute;
+            top: 36%;
+            left: 159%;
+            width: 38%;
+        }
+
+        .progress_pos2_2 {
+            position: absolute;
+            top: -34%;
+            left: 159%;
+            width: 105%;
+        }
+
+        .progress_pos3 {
+            position: absolute;
+            top: 109.5%;
+            left: -76%;
+            width: 93%;
+        }
+
+        .progress_pos4 {
+            position: absolute;
+            top: -34%;
+            left: 71.7%;
+            width: 40.6%;
+        }
+
+        .progress_pos5 {
+            position: absolute;
+            top: -37.5%;
+            left: 73.65%;
+            width: 14%;
+        }
+
+        .progress_pos6 {
+            position: absolute;
+            top: 138%;
+            left: 139%;
+            width: 100%;
+        }
+
+        .progress_pos7 {
+            position: absolute;
+            top: 174%;
+            left: 122%;
+            width: 100%;
+        }
+
+    }
+
+}
+</style>

+ 236 - 0
ui/src/components/HnyzDcs/BK30SeparatorComponent.vue

@@ -0,0 +1,236 @@
+<template>
+    <div class="tank_valves" :style="getTankBodyStyle">
+        <Separator :title="title" :iconWidth="iconWidth" :iconHeight="iconHeight" :iconSize="iconSize"></Separator>
+
+        <!-- 阀门进度 -->
+        <div class="valve_progress">
+            <div :style="valveProgressStyle" class="valve_progress1" v-if="valveNames[0]">
+                <ValveProgress :iconSize="valveIconSize" :title="valveNames[0]" :pipeLength="474" :pipeLeftOffset="-229"
+                    :valveStatusArr="initValveStatusArr" progressType="steam" :pipeStatus="initPipeStatus" />
+            </div>
+            <div :style="valveProgressStyle" class="valve_progress2" v-if="valveNames[1]">
+                <ValveProgress :iconSize="valveIconSize" :title="valveNames[1]" :pipeLength="324" :pipeLeftOffset="-54"
+                    :valveStatusArr="initValveStatusArr" progressType="steam" :pipeStatus="initPipeStatus" />
+            </div>
+            <div :style="valveProgressStyle" class="valve_progress3" v-if="valveNames[2]">
+                <ValveProgress :iconSize="valveIconSize" :title="valveNames[2]" :pipeLength="430" :pipeLeftOffset="-267"
+                    :valveStatusArr="initValveStatusArr" progressType="steam" :pipeStatus="initPipeStatus" />
+            </div>
+            <div :style="valveProgressStyle" class="valve_progress4" v-if="valveNames[3]">
+                <ValveProgress :iconSize="valveIconSize" :title="valveNames[3]" :pipeLength="324" :pipeLeftOffset="-162"
+                    :valveStatusArr="initValveStatusArr" progressType="steam" :pipeStatus="initPipeStatus" />
+            </div>
+            <div :style="valveProgressStyle" class="valve_progress5" v-if="valveNames[4]">
+                <ValveProgress :iconSize="valveIconSize" :title="valveNames[4]" :pipeLength="324" :pipeLeftOffset="-136"
+                    :valveStatusArr="initValveStatusArr" progressType="steam" :pipeStatus="initPipeStatus" />
+            </div>
+            <div :style="valveProgressStyle" class="valve_progress6 rotate_90" v-if="valveNames[5]">
+                <ValveProgress :iconSize="valveIconSize" :title="valveNames[5]" :rotateAngle="90" :pipeLength="380"
+                    :pipeLeftOffset="-55" :valveStatusArr="initValveStatusArr" progressType="steam"
+                    :pipeStatus="initPipeStatus" />
+            </div>
+            <div :style="valveProgressStyle" class="valve_progress7 rotate_270" v-if="valveNames[6]">
+                <ValveProgress :iconSize="valveIconSize" :title="valveNames[6]" :rotateAngle="270" :pipeLength="517"
+                    :pipeLeftOffset="-363" :valveStatusArr="initValveStatusArr" progressType="steam"
+                    :pipeStatus="initPipeStatus" :pipeReverse="true" />
+            </div>
+            <div :style="valveProgressStyle" class="valve_progress8" v-if="valveNames[7]">
+                <ValveProgress :iconSize="valveIconSize" :title="valveNames[7]" :pipeLength="352" :pipeLeftOffset="-153"
+                    :valveStatusArr="initValveStatusArr" progressType="steam" :pipeStatus="initPipeStatus" />
+            </div>
+            <div :style="valveProgressStyle" class="valve_progress9" v-if="valveNames[8]">
+                <ValveProgress :iconSize="valveIconSize" :title="valveNames[8]" :pipeLength="502" :pipeLeftOffset="-182"
+                    :valveStatusArr="initValveStatusArr" progressType="steam" :pipeStatus="initPipeStatus" />
+            </div>
+        </div>
+
+        <!-- 运输器及管道 -->
+        <div class="transport_progress">
+            <div :style="transportProgressStyle" class="transport_progress1" v-if="initHasValve">
+                <TransportProgress title="PD2003A" :iconSize="transportIconSize" :pipeStatus="initPipeStatus"
+                    progressType="steam" pipeLength="412" pipeTopOffset="-181"></TransportProgress>
+            </div>
+        </div>
+        <!-- 料仓 -->
+        <div class="stock_bins">
+            <div class="stock_bin_pos1">
+                <i class="icon iconfont-hnyz-colour icon-hnyz-colourstockBin"></i>
+                <div class="stock_bin_text">料仓LC2002</div>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script setup>
+import Separator from '@/components/HnyzDcs/SeparatorComponent.vue';
+import ValveProgress from '@/components/DCS/ValveProgressComponent.vue';
+import TransportProgress from '@/components/HnyzDcs/TransportProgressComponent.vue';
+import { computed } from 'vue'
+const initHasValve = true
+const initValveStatusArr = [true]
+const initPipeStatus = true
+const props = defineProps({
+    tempValue: {//temp
+        type: Number,
+        default: null
+    },
+    waterLevelValue: {// 水位值
+        type: Number,
+        default: -1,// -1表示未传水位值
+    },
+    fanStatus: {//风扇状态
+        type: Boolean,
+        default: false,
+    },
+    iconSize: {//图标大小
+        type: Number,
+        default: 200,
+    },
+    title: {//罐名
+        type: String,
+    },
+    iconWidth: {//图标宽度
+        type: Number,
+    },
+    iconHeight: {//图标高度
+        type: Number,
+    },
+})
+
+
+//默认阀门名称数组
+const defaultValveNames = new Array(9).fill('ACV_default')
+// 阀门名称映射表
+const valveNameArr= {
+    'S2001': ['ACV2013', 'ACV2014', 'ACV2016','ACV2017','ACV2015','ACV2018','ACV2019','ACV2029','ACV2030'],
+}
+//阀门名称数组,根据罐名来匹配
+const valveNames = computed(() => {
+    return valveNameArr[props.title] || defaultValveNames
+})
+
+//罐体样式
+const getTankBodyStyle = computed(() => ({
+    width: `${props.iconWidth ?? props.iconSize}px`,
+    height: `${props.iconHeight ?? props.iconSize}px`,
+}))
+
+//阀门icon大小(罐子200-阀门50)
+const valveIconSize = computed(() => {
+    return props.iconSize * 0.25;
+});
+
+//阀门进度样式
+const valveProgressStyle = computed(() => {
+    return {
+        width: `${valveIconSize.value}px`,
+        height: `${valveIconSize.value}px`,
+    }
+});
+
+//泵icon大小(罐子200-泵60)
+const transportIconSize = computed(() => {
+    return props.iconSize * 0.3;
+});
+
+//泵进度样式
+const transportProgressStyle = computed(() => {
+    return {
+        width: `${transportIconSize.value}px`,
+        height: `${transportIconSize.value}px`,
+    }
+});
+
+</script>
+
+<style scoped lang="scss">
+.tank_valves {
+    position: relative;
+    z-index: 10;
+
+    .valve_progress {
+        .valve_progress1 {
+            position: absolute;
+            top: 10%;
+            left: -33%;
+        }
+
+        .valve_progress2 {
+            position: absolute;
+            top: 48%;
+            left: -33%;
+        }
+
+        .valve_progress3 {
+            position: absolute;
+            top: 2%;
+            left: 120%;
+        }
+
+        .valve_progress4 {
+            position: absolute;
+            top: 37%;
+            left: 120%;
+        }
+
+        .valve_progress5 {
+            position: absolute;
+            top: 72%;
+            left: 94%;
+        }
+
+        .valve_progress6 {
+            position: absolute;
+            top: -50%;
+            left: 78%;
+        }
+
+        .valve_progress7 {
+            position: absolute;
+            top: -50%;
+            left: 106%;
+        }
+
+        .valve_progress8 {
+            position: absolute;
+            top: -20%;
+            left: 150%;
+        }
+
+        .valve_progress9 {
+            position: absolute;
+            top: -44%;
+            left: 120%;
+        }
+    }
+
+    .transport_progress {
+        .transport_progress1 {
+            position: absolute;
+            top: 158%;
+            left: 43%;
+            transform: translate(-50%, -50%);
+        }
+    }
+
+    .stock_bins {
+        .stock_bin_pos1 {
+            position: absolute;
+            top: 98%;
+            left: 23%;
+            display: flex;
+            align-items: center;
+
+            i {
+                font-size: 75px;
+            }
+
+            .stock_bin_text {
+                font-size: 16px;
+                color: aliceblue;
+            }
+        }
+    }
+
+}
+</style>

+ 95 - 0
ui/src/components/HnyzDcs/ConveyorComponent.vue

@@ -0,0 +1,95 @@
+<template>
+    <div class="conveyor_component" :style="gePumptProgressStyle">
+        <!-- 传送带图标 -->
+        <i class="icon iconfont-hnyz-colour icon-hnyz-colourconveyor pump_icon"
+            :style="{ fontSize: `${iconSize}px` }"></i>
+        <div class="pump_title">{{ title }}</div>
+        <div class="conveyor_bar">
+            <div class="conveyor_flow" :style="getConveyorFlowStyle"></div>
+        </div>
+    </div>
+</template>
+
+<script setup>
+import { defineProps, computed } from 'vue'
+const props = defineProps({
+    title: {// 传送带名称
+        type: String,
+        required: true
+    },
+    //图标大小
+    iconSize: {
+        type: Number,
+        default: 80
+    },
+})
+
+// 计算 组件 的 style
+const gePumptProgressStyle = computed(() => {
+    return {
+        fontSize: `${props.iconSize}px`,
+        width: `${props.iconSize}px`,
+        height: `${props.iconSize}px`,
+    }
+})
+
+// 计算 进度条 style
+const getConveyorFlowStyle = computed(() => {
+    return {
+        backgroundImage: `repeating-linear-gradient(90deg,
+                    rgba(133, 134, 135, 0.3) 0px,
+                    rgba(133, 134, 135, 0.3) ${props.iconSize * 0.15}px,
+                    rgba(133, 134, 135, 0.5) ${props.iconSize * 0.15}px,
+                    rgba(133, 134, 135, 0.9) ${props.iconSize * 0.3}px)`
+    }
+})
+
+</script>
+
+<style scoped lang="scss">
+.conveyor_component {
+    position: relative;
+
+    .pump_icon {
+        position: absolute;
+    }
+
+    .pump_title {
+        color: #C7D2E0;
+        position: absolute;
+        top: 125%;
+        left: 128%;
+        transform: translate(-50%, -50%);
+        font-size: 18px;
+    }
+
+    .conveyor_bar {
+        top: 20%;
+        left: 32%;
+        width: 194%;
+        height: 70%;
+        background-color: #eee;
+        overflow: hidden;
+        position: relative;
+
+        /* 动画流动条 */
+        .conveyor_flow {
+            width: 200%;
+            height: 100%;
+            animation: conveyor-move 5s linear infinite;
+        }
+
+        @keyframes conveyor-move {
+            0% {
+                transform: translateX(-50%);
+            }
+
+            100% {
+                transform: translateX(0%);
+            }
+        }
+    }
+
+
+}
+</style>

+ 167 - 0
ui/src/components/HnyzDcs/D40SeparatorComponent.vue

@@ -0,0 +1,167 @@
+<template>
+    <div class="tank_valves" :style="getTankBodyStyle">
+        <Separator :title="title" :iconWidth="iconWidth" :iconHeight="iconHeight" :iconSize="iconSize"></Separator>
+
+        <!-- 阀门进度 -->
+        <div class="valve_progress">
+            <!-- 左 -->
+            <div :style="valveProgressStyle" class="valve_progress1" v-if="valveNames[0]">
+                <ValveProgress :iconSize="valveIconSize" :title="valveNames[0]" :pipeLength="200" :pipeLeftOffset="-50"
+                    :valveStatusArr="initValveStatusArr" progressType="steam" :pipeStatus="initPipeStatus" />
+            </div>
+            <!-- 右  -->
+            <div :style="valveProgressStyle" class="valve_progress4" v-if="valveNames[1]">
+                <ValveProgress :iconSize="valveIconSize" :title="valveNames[1]" :pipeLength="324" :pipeLeftOffset="-162"
+                    :valveStatusArr="initValveStatusArr" progressType="steam" :pipeStatus="initPipeStatus" />
+            </div>
+            <!-- 上  -->
+            <div :style="valveProgressStyle" class="valve_progress6 rotate_90" v-if="valveNames[2]">
+                <ValveProgress :iconSize="valveIconSize" :title="valveNames[2]" :rotateAngle="90" :pipeLength="211"
+                    :pipeLeftOffset="-55" :valveStatusArr="initValveStatusArr" progressType="steam"
+                    :pipeStatus="initPipeStatus" />
+            </div>
+
+        </div>
+
+        <!-- 泵进度 -->
+        <div class="pump_progress">
+            <!-- 左 -->
+            <PumpProgress :title="pumpNames[0]" :pumpDataArr="[1, 10]" :iconSize="iconSize * 0.4" :showPipe="true"
+                :pipeType="steam" class="pump_progress1" v-if="pumpNames[0]" />
+        </div>
+        <!-- 管道 -->
+        <div class="pipes">
+            <Pipe :pipeStatus="initPipeStatus" :strokeWidth="props.iconSize * 0.04"
+                class="pipe_pos1 progress_steam zIndex10" v-if="pumpNames[0]" />
+        </div>
+
+    </div>
+</template>
+
+<script setup>
+import Separator from '@/components/HnyzDcs/SeparatorComponent.vue';
+import ValveProgress from '@/components/DCS/ValveProgressComponent.vue';
+import PumpProgress from '@/components/DCS/PumpComponent.vue';
+import Pipe from '@/components/HnyzDcs/PipeComponent.vue';
+import { computed } from 'vue'
+const initValveStatusArr = [true]
+const initPipeStatus = true
+const props = defineProps({
+    tempValue: {//temp
+        type: Number,
+        default: null
+    },
+    waterLevelValue: {// 水位值
+        type: Number,
+        default: -1,// -1表示未传水位值
+    },
+    fanStatus: {//风扇状态
+        type: Boolean,
+        default: false,
+    },
+    iconSize: {//图标大小
+        type: Number,
+        default: 200,
+    },
+    title: {//罐名
+        type: String,
+    },
+    iconWidth: {//图标宽度
+        type: Number,
+    },
+    iconHeight: {//图标高度
+        type: Number,
+    },
+})
+
+//默认阀门名称数组
+const defaultValveNames = new Array(3).fill('ACV_default')
+//泵默认名称
+const defaultPumpNames = new Array(1).fill('P_default')
+
+// 阀门名称映射表
+const valveNameArr = {
+    'S2006': ['ACV2067', 'ACV2063', ''],
+    'S2007': ['ACV2075', '', 'ACV2087'],
+}
+//泵名称映射表
+const pumpNameArr = {
+    'S2006': ['P2015'],
+    'S2007': [''],
+}
+
+//阀门名称数组,根据罐名来匹配
+const valveNames = computed(() => {
+    return valveNameArr[props.title] || defaultValveNames
+})
+//泵名称
+const pumpNames = computed(() => {
+    return pumpNameArr[props.title] || defaultPumpNames
+})
+
+//罐体样式
+const getTankBodyStyle = computed(() => ({
+    width: `${props.iconWidth ?? props.iconSize}px`,
+    height: `${props.iconHeight ?? props.iconSize}px`,
+}))
+
+//阀门icon大小(罐子200-阀门50)
+const valveIconSize = computed(() => {
+    return props.iconSize * 0.25;
+});
+
+//阀门进度样式
+const valveProgressStyle = computed(() => {
+    return {
+        width: `${valveIconSize.value}px`,
+        height: `${valveIconSize.value}px`,
+    }
+});
+
+</script>
+
+<style scoped lang="scss">
+.tank_valves {
+    position: relative;
+    z-index: 10;
+
+    .valve_progress {
+        .valve_progress1 {
+            position: absolute;
+            top: 33%;
+            left: -33%;
+        }
+
+        .valve_progress4 {
+            position: absolute;
+            top: 37%;
+            left: 106%;
+        }
+
+        .valve_progress6 {
+            position: absolute;
+            top: -8%;
+            left: 50%;
+        }
+
+    }
+
+    .pump_progress {
+        .pump_progress1 {
+            position: absolute;
+            top: 85.1%;
+            left: -97.5%;
+            transform: translate(-50%, -50%);
+        }
+    }
+
+    .pipes {
+        .pipe_pos1 {
+            position: absolute;
+            top: 47.5%;
+            left: -103%;
+            width: 105%;
+        }
+    }
+}
+</style>

+ 139 - 0
ui/src/components/HnyzDcs/ETypeTankComponent.vue

@@ -0,0 +1,139 @@
+<template>
+    <!-- 换热器:温度、搅拌 -->
+    <div class="tank_body" :style="getTankBodyStyle">
+        <!-- 罐体 -->
+        <i class="icon iconfont-hnyz-colour tank" :class="getTankClass" :style="getTankStyle">
+            <!-- 标题 -->
+            <div class="tank_title" :style="{ fontSize: `${iconSize * 0.15}px` }" v-if="title">{{ title }}</div>
+        </i>
+        <!-- 搅拌电机 -->
+        <div class="mixer_machine" v-if="typeof fanStatus === 'boolean'">
+            <i class="icon iconfont icon-fengshan" :class="{ 'fan_run': fanStatus }"></i>
+        </div>
+        <!-- temp值组件 -->
+        <TempSlider :tempValue="tempValue" :sliderWidth="iconSize * 0.05" class="temp_pos" />
+    </div>
+</template>
+
+<script setup>
+import TempSlider from '@/components/HnyzDcs/TempSliderComponent.vue'
+import { computed } from 'vue'
+
+const props = defineProps({
+    tempValue: {//temp
+        type: Number,
+        default: null
+    },
+    fanStatus: {//风扇状态
+        type: Boolean,
+    },
+    iconSize: {//图标大小
+        type: Number,
+        default: 200,
+    },
+    title: {//罐名
+        type: String,
+    },
+    iconWidth: {//图标宽度
+        type: Number,
+    },
+    iconHeight: {//图标高度
+        type: Number,
+    },
+})
+//解构
+const { iconSize, title, iconWidth, iconHeight } = props
+
+//罐体样式
+const getTankBodyStyle = computed(() => ({
+    width: `${iconWidth ?? iconSize}px`,
+    height: `${iconHeight ?? iconSize}px`,
+    fontSize: `${iconSize}px`,
+}))
+
+
+// 罐子样式
+const getTankStyle = computed(() => {
+    const style = {
+        fontSize: iconSize + 'px',
+        display: 'inline-block'
+    }
+    //根据传进来的iconWidth和iconHeight来控制图标的大小
+    const scaleX = iconWidth ? iconWidth / iconSize : 1
+    const scaleY = iconHeight ? iconHeight / iconSize : 1
+
+    if (scaleX !== 1 || scaleY !== 1) {
+        style.transform = `scale(${scaleX}, ${scaleY})`
+    }
+
+    return style
+})
+
+// 罐子类名 
+const getTankClass = computed(() => {
+    return props.fanStatus
+        ? 'icon-hnyz-colourheatExchanger_hollowedOut'
+        : 'icon-hnyz-colourheatExchanger';
+});
+
+</script>
+
+<style scoped lang="scss">
+//水位罐
+.tank_body {
+    text-align: center;
+    position: relative;
+
+    .tank {
+        position: relative;
+        z-index: 10;
+
+        //罐子名称
+        .tank_title {
+            position: absolute;
+            top: 80%;
+            left: 50%;
+            transform: translate(-50%, -50%);
+            color: #e65100;
+            font-weight: bold;
+        }
+    }
+
+    .temp_pos {
+        position: absolute;
+        top: 23%;
+        left: 59%;
+        z-index: 100;
+    }
+
+    //搅拌电机
+    .mixer_machine {
+        position: absolute;
+        top: 26%;
+        left: 50%;
+        transform: translate(-50%, -50%);
+
+        .icon-fengshan {
+            color: aliceblue;
+            font-size: 50px;
+            display: inline-block;
+        }
+
+        //旋转动画
+        @keyframes rotate-clockwise {
+            from {
+                transform: rotate(0deg);
+            }
+
+            to {
+                transform: rotate(360deg);
+            }
+        }
+
+        .fan_run {
+            animation: rotate-clockwise 1s linear infinite;
+        }
+    }
+
+}
+</style>

+ 161 - 0
ui/src/components/HnyzDcs/ETypeTankValves1Component.vue

@@ -0,0 +1,161 @@
+<template>
+    <div class="tank_valves" :style="getTankBodyStyle">
+        <!-- 换热器:温度、搅拌 -->
+        <ETypeTank :title="title" :waterLevelValue="waterLevelValue" :iconWidth="iconWidth" :iconHeight="iconHeight"
+            :iconSize="iconSize" :tempValue="tempValue" :fanStatus="fanStatus"></ETypeTank>
+        <!-- 阀门进度 -->
+        <div class="valve_progress">
+            <!-- 左1 -->
+            <ValveProgress :iconSize="valveIconSize" :title="valveNames[0]" :rotateAngle="0" :pipeLength="258"
+                :pipeLeftOffset="-108" :valveStatusArr="initValveStatusArr" progressType="steam"
+                :pipeStatus="initPipeStatus" class="valve_progress1"/>
+            <!-- 左2 -->
+            <ValveProgress :iconSize="valveIconSize" :title="valveNames[1]" :rotateAngle="0" :pipeLength="200"
+                :pipeLeftOffset="-50" :valveStatusArr="initValveStatusArr" progressType="steam"
+                :pipeStatus="initPipeStatus" class="valve_progress2"/>
+            <!-- 右1 -->
+            <ValveProgress :iconSize="valveIconSize" :title="valveNames[3]" :pipeLength="498" :pipeLeftOffset="-114"
+                :valveStatusArr="initValveStatusArr" progressType="steam" :pipeStatus="initPipeStatus"
+                :pipeReverse="true" class="valve_progress4"/>
+            <!-- 右2 -->
+            <ValveProgress :iconSize="valveIconSize" :title="valveNames[4]" :pipeLength="285" :pipeLeftOffset="-114"
+                :valveStatusArr="initValveStatusArr" progressType="steam" :pipeStatus="initPipeStatus"
+                class="valve_progress5"/>
+            <!-- 右3 -->
+            <ValveProgress :iconSize="valveIconSize" :title="valveNames[2]" :pipeLength="364" :pipeLeftOffset="-114"
+                :valveStatusArr="initValveStatusArr" progressType="steam" :pipeStatus="initPipeStatus"
+                class="valve_progress3"/>
+        </div>
+        <!-- 泵进度 -->
+        <div class="pump_progress">
+        </div>
+        <!-- 流量计 -->
+        <div class="flow_meters">
+        </div>
+    </div>
+</template>
+
+<script setup>
+import ETypeTank from '@/components/HnyzDcs/ETypeTankComponent.vue';
+import ValveProgress from '@/components/DCS/ValveProgressComponent.vue';
+import PumpProgress from '@/components/HnyzDcs/PumpProgressComponent.vue';
+import FlowMeter from '@/components/HnyzDcs/FlowMeterComponent.vue';
+import { computed } from 'vue'
+const initValveStatusArr = [true]
+const initPipeStatus = true
+const props = defineProps({
+    tempValue: {//temp
+        type: Number,
+        default: null
+    },
+    waterLevelValue: {// 水位值
+        type: Number,
+        default: -1,// -1表示未传水位值
+    },
+    fanStatus: {//风扇状态
+        type: Boolean,
+        default: false,
+    },
+    iconSize: {//图标大小
+        type: Number,
+        default: 200,
+    },
+    title: {//罐名
+        type: String,
+    },
+    iconWidth: {//图标宽度
+        type: Number,
+    },
+    iconHeight: {//图标高度
+        type: Number,
+    },
+})
+
+//默认阀门名称数组
+const defaultValveNames = new Array(5).fill('ACV_default')
+
+// 阀门名称映射表
+const valveNameArr = {
+    'E2001A': ['ACV2056A', 'ACV2057A', 'ACV2058A', 'ACV2059A', 'ACV2060A'],
+    'E2001B': ['ACV2056B', 'ACV2057B', 'ACV2058B', 'ACV2059B', 'ACV2060B'],
+}
+
+//阀门名称数组,根据罐名来匹配
+const valveNames = computed(() => {
+    return valveNameArr[props.title] || defaultValveNames
+})
+
+//罐体样式
+const getTankBodyStyle = computed(() => ({
+    width: `${props.iconWidth ?? props.iconSize}px`,
+    height: `${props.iconHeight ?? props.iconSize}px`,
+}))
+
+
+//阀门icon大小(罐子200-阀门50)
+const valveIconSize = computed(() => {
+    return props.iconSize * 0.25;
+});
+
+//阀门进度样式
+const valveProgressStyle = computed(() => {
+    return {
+        width: `${valveIconSize.value}px`,
+        height: `${valveIconSize.value}px`,
+    }
+});
+
+//泵icon大小(罐子200-泵80)
+const pumpIconSize = computed(() => {
+    return props.iconSize * 0.4;
+});
+
+//泵进度样式
+const pumpProgressStyle = computed(() => {
+    return {
+        width: `${pumpIconSize.value}px`,
+        height: `${pumpIconSize.value}px`,
+    }
+});
+
+</script>
+
+<style scoped lang="scss">
+.tank_valves {
+    position: relative;
+    z-index: 10;
+
+    .valve_progress {
+        .valve_progress1 {
+            position: absolute;
+            top: 2%;
+            left: -11%;
+        }
+
+        .valve_progress2 {
+            position: absolute;
+            top: 41%;
+            left: -11%;
+        }
+
+        .valve_progress3 {
+            position: absolute;
+            top: 78%;
+            left: 99%;
+        }
+
+
+        .valve_progress4 {
+            position: absolute;
+            top: 2%;
+            left: 99%;
+        }
+
+        .valve_progress5 {
+            position: absolute;
+            top: 41%;
+            left: 99%;
+        }
+    }
+}
+</style>

+ 149 - 0
ui/src/components/HnyzDcs/ETypeTankValves2Component.vue

@@ -0,0 +1,149 @@
+<template>
+    <div class="tank_valves" :style="getTankBodyStyle">
+        <!-- 换热器 泵-->
+        <ETypeTank :title="title" :iconWidth="iconWidth" :iconHeight="iconHeight" :iconSize="iconSize"></ETypeTank>
+        <!-- 阀门进度 -->
+        <div class="valve_progress">
+            <!-- 上  -->
+            <div :style="valveProgressStyle" class="valve_progress1 rotate_90" v-if="valveNames[0]">
+                <ValveProgress :iconSize="valveIconSize" :title="valveNames[0]" :rotateAngle="90" :pipeLength="200"
+                    :pipeLeftOffset="-50" :valveStatusArr="initValveStatusArr" progressType="steam"
+                    :pipeStatus="initPipeStatus" />
+            </div>
+            <!-- 下  -->
+            <div :style="valveProgressStyle" class="valve_progress2 rotate_90" v-if="valveNames[1]">
+                <ValveProgress :iconSize="valveIconSize" :title="valveNames[1]" :rotateAngle="90" :pipeLength="200"
+                    :pipeLeftOffset="-50" :valveStatusArr="initValveStatusArr" progressType="steam"
+                    :pipeStatus="initPipeStatus" :pipeReverse="true" />
+            </div>
+            <!-- 左  -->
+            <div :style="valveProgressStyle" class="valve_progress3" v-if="valveNames[2]">
+                <ValveProgress :iconSize="valveIconSize" :title="valveNames[2]" :pipeLength="264" :pipeLeftOffset="-114"
+                    :valveStatusArr="initValveStatusArr" progressType="steam" :pipeStatus="initPipeStatus"
+                    :pipeReverse="true" />
+            </div>
+            <!-- 右  -->
+            <div :style="valveProgressStyle" class="valve_progress4" v-if="valveNames[3]">
+                <ValveProgress :iconSize="valveIconSize" :title="valveNames[3]" :pipeLength="593" :pipeLeftOffset="-60"
+                    :valveStatusArr="initValveStatusArr" progressType="steam" :pipeStatus="initPipeStatus"
+                    :pipeReverse="true" />
+            </div>
+        </div>
+        <!-- 泵进度 -->
+        <div class="pump_progress">
+            <PumpProgress :title="pumpNames[0]" :pumpDataArr="[1, 10]" :iconSize="iconSize * 0.4" :showPipe="true"
+                :pipeType="steam" pumpDirection="R" class="pump_progress1" />
+        </div>
+    </div>
+</template>
+
+<script setup>
+import ETypeTank from '@/components/HnyzDcs/ETypeTankComponent.vue';
+import ValveProgress from '@/components/DCS/ValveProgressComponent.vue';
+import PumpProgress from '@/components/DCS/PumpComponent.vue';
+import { computed } from 'vue'
+const initValveStatusArr = [true]
+const initPipeStatus = true
+const props = defineProps({
+    iconSize: {//图标大小
+        type: Number,
+        default: 200,
+    },
+    title: {//罐名
+        type: String,
+    },
+    iconWidth: {//图标宽度
+        type: Number,
+    },
+    iconHeight: {//图标高度
+        type: Number,
+    },
+})
+
+//默认阀门名称数组
+const defaultValveNames = new Array(4).fill('ACV_default')
+//泵默认名称
+const defaultPumpNames = new Array(1).fill('P_default')
+
+// 阀门名称映射表
+const valveNameArr = {
+    'E2003': ['ACV2068', 'ACV2062', 'ACV2069', 'ACV2080'],
+}
+//泵名称映射表
+const pumpNameArr = {
+    'E2003': ['P2016'],
+}
+
+//阀门名称数组,根据罐名来匹配
+const valveNames = computed(() => {
+    return valveNameArr[props.title] || defaultValveNames
+})
+//泵名称
+const pumpNames = computed(() => {
+    return pumpNameArr[props.title] || defaultPumpNames
+})
+
+//罐体样式
+const getTankBodyStyle = computed(() => ({
+    width: `${props.iconWidth ?? props.iconSize}px`,
+    height: `${props.iconHeight ?? props.iconSize}px`,
+}))
+
+//阀门icon大小(罐子200-阀门50)
+const valveIconSize = computed(() => {
+    return props.iconSize * 0.25;
+});
+
+//阀门进度样式
+const valveProgressStyle = computed(() => {
+    return {
+        width: `${valveIconSize.value}px`,
+        height: `${valveIconSize.value}px`,
+    }
+});
+
+</script>
+
+<style scoped lang="scss">
+.tank_valves {
+    position: relative;
+    z-index: 10;
+
+    .valve_progress {
+        .valve_progress1 {
+            position: absolute;
+            top: -15%;
+            left: 53%;
+        }
+
+        .valve_progress2 {
+            position: absolute;
+            top: 124%;
+            left: 53%;
+        }
+
+        .valve_progress3 {
+            position: absolute;
+            top: 35%;
+            left: -11%;
+        }
+
+
+        .valve_progress4 {
+            position: absolute;
+            top: 35%;
+            left: 88%;
+        }
+    }
+
+    .pump_progress {
+        .pump_progress1 {
+            position: absolute;
+            top: 50.2%;
+            left: -66%;
+            transform: translate(-50%, -50%);
+        }
+    }
+
+}
+</style>

+ 150 - 0
ui/src/components/HnyzDcs/FTypeTankComponent.vue

@@ -0,0 +1,150 @@
+<template>
+    <!-- 落地罐:水位、温度 -->
+    <div class="tank_body" :style="getTankBodyStyle">
+        <!-- 罐体 -->
+        <i class="icon iconfont-hnyz-colour tank" :class="tankIconClass" :style="getTankStyle">
+            <!-- 标题 200-30px-->
+            <div class="tank_title" v-if="title" :style="{ fontSize: `${iconSize * 0.15}px` }">{{ title }}</div>
+            <!-- 水位 -->
+            <div v-if="waterLevelValue >= 0">
+                <dv-water-level-pond :config="waterLevelConfig" class="water_level water_level_pos3" />
+            </div>
+        </i>
+        <!-- temp值组件 -->
+        <TempSlider :tempValue="tempValue" :sliderWidth="iconSize*0.05" class="temp_pos" />
+    </div>
+</template>
+
+<script setup>
+import TempSlider from '@/components/HnyzDcs/TempSliderComponent.vue'
+
+import { computed } from 'vue'
+
+const props = defineProps({
+    tempValue: {//temp
+        type: Number,
+        default: null
+    },
+    waterLevelValue: {// 水位值
+        type: Number,
+        default: -1,// -1表示未传水位值
+    },
+    iconSize: {//图标大小
+        type: Number,
+        default: 200,
+    },
+    title: {//罐名
+        type: String,
+    },
+    iconWidth: {//图标宽度
+        type: Number,
+    },
+    iconHeight: {//图标高度
+        type: Number,
+    },
+})
+
+
+//罐体样式
+const getTankBodyStyle = computed(() => ({
+    width: `${props.iconWidth ?? props.iconSize}px`,
+    height: `${props.iconHeight ?? props.iconSize}px`,
+    fontSize: `${props.iconSize}px`,
+}))
+
+
+// 罐子样式
+const getTankStyle = computed(() => {
+    const style = {
+        fontSize: props.iconSize + 'px',
+        display: 'inline-block'
+    }
+    //根据传进来的iconWidth和iconHeight来控制图标的大小
+    const scaleX = props.iconWidth ? props.iconWidth / props.iconSize : 1
+    const scaleY = props.iconHeight ? props.iconHeight / props.iconSize : 1
+
+    if (scaleX !== 1 || scaleY !== 1) {
+        style.transform = `scale(${scaleX}, ${scaleY})`
+    }
+
+    return style
+})
+
+// 罐型图标
+const tankIconClass = computed(() => {
+    return props.waterLevelValue >= 0 || props.fanStatus ? 'icon-hnyz-colourfloorTank_hollowedOut' : 'icon-hnyz-colourfloorTank'
+});
+
+// 仅传 waterLevelValue,内部组装 config
+const waterLevelConfig = computed(() => ({
+    data: [props.waterLevelValue],
+    waveHeight: 5,// 波浪高度
+}))
+
+//temp值
+const tempValue = computed({
+    get() {
+        return props.tempValue
+    },
+})
+
+</script>
+
+<style scoped lang="scss">
+//水位罐
+.tank_body {
+    text-align: center;
+    position: relative;
+
+    .tank {
+        position: relative;
+        z-index: 10;
+
+        //罐子名称
+        .tank_title {
+            position: absolute;
+            top: 75%;
+            left: 49%;
+            transform: translate(-50%, -50%);
+            color: #e65100;
+            font-weight: bold;
+        }
+
+        // 水位
+        .water_level {
+            width: 0.4em;
+            height: 0.5em;
+        }
+
+        //水位图位置
+        .water_level_pos3 {
+            position: absolute;
+            top: 18%;
+            left: 30%;
+        }
+
+        .dv-water-pond-level :deep(canvas) {
+            position: absolute;
+            left: 0%;
+        }
+
+        .dv-water-pond-level :deep(rect) {
+            // fill:unset;//去掉默认的颜色
+            width: 99%;
+            height: 99%;
+            stroke-width: 0 !important;
+        }
+
+
+    }
+
+    .temp_pos {
+        position: absolute;
+        top: 22%;
+        left: 60%;
+        z-index: 100;
+    }
+
+
+}
+</style>

+ 158 - 0
ui/src/components/HnyzDcs/FTypeTankValvesComponent.vue

@@ -0,0 +1,158 @@
+<template>
+    <div class="tank_valves" :style="getTankBodyStyle">
+        <!-- 换热器:温度、搅拌 -->
+        <FTypeTank :title="title" :waterLevelValue="waterLevelValue" :iconWidth="iconWidth" :iconHeight="iconHeight"
+            :iconSize="iconSize" :tempValue="tempValue"></FTypeTank>
+        <!-- 阀门进度 -->
+        <div class="valve_progress">
+            <!-- 上 -->
+            <!-- <ValveProgress :iconSize="valveIconSize" :title="valveNames[0]" :rotateAngle="270" :pipeLength="258"
+                :pipeLeftOffset="-108" :valveStatusArr="initValveStatusArr" progressType="red" :pipeReverse="true"
+                :pipeStatus="initPipeStatus" class="valve_progress1 rotate_270" /> -->
+            <!-- 下1 -->
+            <!-- <ValveProgress :iconSize="valveIconSize" :title="valveNames[1]" :rotateAngle="270" :pipeLength="0"
+                :pipeLeftOffset="-200" :valveStatusArr="initValveStatusArr" progressType="steam"
+                :pipeStatus="initPipeStatus" class="valve_progress2 rotate_270 zIndex10" /> -->
+            <ValveProgress :iconSize="valveIconSize" :title="valveNames[1]" :rotateAngle="270" :pipeLength="0"
+                :pipeLeftOffset="-200" :valveStatusArr="initValveStatusArr" progressType="steam"
+                :pipeStatus="initPipeStatus" class="valve_progress3 rotate_270 zIndex10" />
+        </div>
+        <!-- 泵进度 -->
+        <div class="pipes">
+            <!-- 上左管道 -->
+            <Pipe :pipeStatus="initPipeStatus" :strokeWidth="6" class="progress_red progress_pos3 rotate_90" />
+            <!-- 上右管道 -->
+            <Pipe :pipeStatus="initPipeStatus" :strokeWidth="6" class="progress_green progress_pos1 rotate_90" />
+            <!-- 下管道 -->
+            <Pipe :pipeStatus="initPipeStatus" :strokeWidth="6" class="progress_blue progress_pos2 rotate_90" />
+        </div>
+        <!-- 流量计 -->
+        <div class="flow_meters">
+            <div class="flow_meter1">
+                <FlowMeter title="K离子检测仪" ionValue="3" :rotateAngle="270" :meterType="2" :iconSize="iconSize * 0.275" />
+            </div>
+        </div>
+    </div>
+</template>
+
+<script setup>
+import FTypeTank from '@/components/HnyzDcs/FTypeTankComponent.vue';
+import ValveProgress from '@/components/DCS/ValveProgressComponent.vue';
+import Pipe from '@/components/HnyzDcs/PipeComponent.vue';
+import FlowMeter from '@/components/HnyzDcs/FlowMeterComponent.vue';
+import { computed } from 'vue'
+const initValveStatusArr = [true]
+const initPipeStatus = true
+const props = defineProps({
+    tempValue: {//temp
+        type: Number,
+        default: null
+    },
+    waterLevelValue: {// 水位值
+        type: Number,
+        default: -1,// -1表示未传水位值
+    },
+    fanStatus: {//风扇状态
+        type: Boolean,
+        default: false,
+    },
+    iconSize: {//图标大小
+        type: Number,
+        default: 200,
+    },
+    title: {//罐名
+        type: String,
+    },
+    iconWidth: {//图标宽度
+        type: Number,
+    },
+    iconHeight: {//图标高度
+        type: Number,
+    },
+})
+
+//默认阀门名称数组
+const defaultValveNames = new Array(3).fill('SQF')
+
+// 阀门名称映射表
+const valveNameArr = {
+}
+
+//阀门名称数组,根据罐名来匹配
+const valveNames = computed(() => {
+    return valveNameArr[props.title] || defaultValveNames
+})
+
+//罐体样式
+const getTankBodyStyle = computed(() => ({
+    width: `${props.iconWidth ?? props.iconSize}px`,
+    height: `${props.iconHeight ?? props.iconSize}px`,
+}))
+
+
+//阀门icon大小(罐子200-阀门50)
+const valveIconSize = computed(() => {
+    return props.iconSize * 0.25;
+});
+
+
+</script>
+
+<style scoped lang="scss">
+.tank_valves {
+    position: relative;
+    z-index: 10;
+
+    .valve_progress {
+        .valve_progress1 {
+            position: absolute;
+            top: -33%;
+            left: 40%;
+        }
+
+        .valve_progress2 {
+            position: absolute;
+            top: 140%;
+            left: 45.6%;
+        }
+
+        .valve_progress3 {
+            position: absolute;
+            top: 160%;
+            left: 45.6%;
+        }
+    }
+
+    .flow_meters {
+        .flow_meter1 {
+            position: absolute;
+            top: 115%;
+            left: 56.5%;
+            transform: translate(-50%, -50%);
+        }
+    }
+
+    .pipes {
+        .progress_pos1 {
+            position: absolute;
+            top: -3%;
+            left: 63%;
+            width: 25%;
+        }
+
+        .progress_pos2 {
+            position: absolute;
+            top: 142%;
+            left: 50%;
+            width: 115%;
+        }
+
+        .progress_pos3 {
+            position: absolute;
+            top: -23%;
+            left: 43%;
+            width: 70%;
+        }
+    }
+}
+</style>

+ 78 - 0
ui/src/components/HnyzDcs/FlowMeterComponent.vue

@@ -0,0 +1,78 @@
+<template>
+    <el-popover placement="right" trigger="hover" popper-class="flow_meter_popover">
+        <!-- 弹出内容 -->
+        <template #default>
+            <div class="flow_title">{{ title }}</div>
+            <div class="flow_value" v-if="meterType === 1">瞬时流量: {{ flowValueArr[0] }} m³/h</div>
+            <div class="flow_value" v-if="meterType === 1">累计流量: {{ flowValueArr[1] }} m³</div>
+            <div class="flow_value" v-if="meterType === 2">K离子浓度: {{ ionValue }} %</div>
+        </template>
+        <!-- 悬浮触发区域 -->
+        <template #reference>
+            <div class="flow_meter_icon" :style="getRotateStyle">
+                <i class="icon iconfont-hnyz-colour icon-hnyz-colourflowmeter"
+                    :style="{ fontSize: `${props.iconSize}px` }"></i>
+            </div>
+        </template>
+    </el-popover>
+</template>
+
+<script setup>
+import { computed } from 'vue';
+const props = defineProps({
+    title: {
+        type: String,
+    },
+    flowValueArr: {// 瞬时流量和累计流量
+        type: Array,
+        default: () => [10, 10],
+    },
+    ionValue: {// K离子浓度
+        type: Number,
+        default: 3,
+    },
+    rotateAngle: {// 旋转角度
+        type: Number,
+        default: 0,
+    },
+    iconSize: {// 流量图标大小
+        type: Number,
+        default: 55
+    },
+    //仪表类型1:流量计,2:离子浓度测量仪
+    meterType: {
+        type: Number,
+        default: 1
+    }
+
+});
+
+// 计算旋转角度样式
+const getRotateStyle = computed(() => ({
+    transform: `rotate(${props.rotateAngle}deg) translate(-50%, -50%)`,
+}))
+</script>
+
+<style scoped lang="scss">
+.flow_meter_icon {
+    position: relative;
+    z-index: 100;
+}
+
+.flow_title {
+    font-weight: bold;
+    font-size: 14px;
+    margin-bottom: 4px;
+}
+
+.flow_value {
+    font-size: 12px;
+    color: #333;
+}
+</style>
+<style lang="scss">//写到非 scoped <style> 里,因为 popover 是挂在 body 外部的 DOM 节点
+.flow_meter_popover {
+    min-width: unset !important;// 取消弹出层的最小宽度限制
+    width: auto !important;
+}
+</style>

+ 57 - 0
ui/src/components/HnyzDcs/IonDetectionMachineComponent.vue

@@ -0,0 +1,57 @@
+<template>
+    <el-popover placement="right" trigger="hover" popper-class="machine_popover">
+        <!-- 弹出内容 -->
+        <template #default>
+            <div class="flow_title">{{ title }}</div>
+            <div class="flow_value">K离子含量: {{ machineValue }} %</div>
+        </template>
+
+        <!-- 悬浮触发区域 -->
+        <template #reference>
+            <div class="flow_meter_icon">
+                <!-- 离子检测仪图标 -->
+                <i class="icon iconfont-hnyz-colour icon-hnyz-colourIonDetectionMachine"
+                    :style="{ fontSize: props.iconSize + 'px' }"></i>
+            </div>
+        </template>
+    </el-popover>
+</template>
+
+<script setup>
+
+const props = defineProps({
+    title: String,
+    machineValue: {// 离子含量
+        type: Number,
+        default: 5,
+    },
+    iconSize: {// 图标大小
+        type: Number,
+        default: 50
+    },
+});
+
+</script>
+
+<style scoped lang="scss">
+.flow_meter_icon {
+    position: relative;
+    z-index: 100;
+
+    i {
+        cursor: pointer;
+    }
+}
+
+.flow_title {
+    font-weight: bold;
+    font-size: 14px;
+    margin-bottom: 4px;
+}
+
+.flow_value,
+.flow_total {
+    font-size: 12px;
+    color: #333;
+}
+</style>

+ 50 - 0
ui/src/components/HnyzDcs/PageIconComponent.vue

@@ -0,0 +1,50 @@
+<template>
+    <div class="icon_other" :style="{ 'flex-direction': flexDirection }">
+        <i class="icon iconfont-hnyz-colour" :class="'icon-hnyz-' + iconClass"
+            :style="{ 'font-size': props.iconSize + 'px' }"></i>
+        <div class="icon_title">{{ props.title }}</div>
+    </div>
+</template>
+
+<script setup>
+import { defineProps } from 'vue'
+const props = defineProps({
+    title: {
+        type: String,
+        required: true
+    },
+    //图标class
+    iconClass: {
+        type: String,
+    },
+    //图标大小
+    iconSize: {
+        type: Number,
+        default: 100
+    },
+    //排布方向 row/column
+    flexDirection: {
+        type: String,
+        default: 'column'
+    },
+})
+
+</script>
+
+<style scoped lang="scss">
+.icon_others {
+    .icon_other {
+        display: flex;
+        align-items: center;
+
+        .iconfont-hnyz-colour {
+            font-size: 75px;
+        }
+
+        .icon_title {
+            font-size: 12px;
+            color: aliceblue;
+        }
+    }
+}
+</style>

+ 105 - 0
ui/src/components/HnyzDcs/PhSliderComponent.vue

@@ -0,0 +1,105 @@
+<template>
+    <div class="slider-demo-block ph_pos" v-if="props.phValue !== null && props.phValue !== undefined">
+        <el-slider :model-value="props.phValue" vertical disabled :max="14" :min="0" :marks="marks" class="ph_slider"
+            :class="getPhClass" />
+    </div>
+</template>
+
+<script setup>
+import { computed } from 'vue'
+
+const props = defineProps({
+    phValue: Number
+})
+
+function getPhColor(val) {//color与class对应
+    if (val >= 9) return { class: 'ph_purple', color: '#9C27B0' }//强碱 紫色
+    if (val >= 7) return { class: 'ph_blue', color: '#2196F3' }//弱碱 蓝色
+    if (val >= 6) return { class: 'ph_green', color: '#4CAF50' }// 中性 绿色
+    if (val >= 4) return { class: 'ph_orange', color: '#FF9800' }// 弱酸 橙色
+    return { class: 'ph_red', color: '#F44336' } // 强酸 红色
+}
+//ph管道
+const getPhClass = computed(() => getPhColor(props.phValue).class)
+//ph显示值
+const marks = computed(() => {
+    if (props.phValue == null || isNaN(props.phValue)) return {}
+
+    const { color } = getPhColor(props.phValue)
+    const valueNum = Number(props.phValue)
+    const valueLabel = valueNum.toFixed(1)  //  保留一位小数
+
+    return {
+        [valueNum]: {
+            style: {
+                color,
+                fontWeight: 'bold',
+            },
+            label: `pH: ${valueLabel}`,
+        },
+    }
+})
+
+</script>
+
+
+<style scoped lang="scss">
+.slider-demo-block {
+    max-width: 600px;
+    display: flex;
+    align-items: center;
+}
+
+:deep(.ph_slider) {
+    height: 0.5em;
+    margin-left: 8% !important;
+
+    .el-slider__runway .el-slider__button-wrapper .el-slider__button {
+        position: absolute;
+        left: 22%;
+        bottom: 22%;
+        display: none; // 隐藏进度条上的圆形按键
+    }
+
+    .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%;
+    }
+}
+
+:deep(.ph_green .el-slider__runway .el-slider__bar) {
+    background-color: #4CAF50;
+}
+
+:deep(.ph_orange .el-slider__runway .el-slider__bar) {
+    background-color: #FF9800;
+}
+
+:deep(.ph_red .el-slider__runway .el-slider__bar) {
+    background-color: #F44336;
+}
+
+:deep(.ph_blue .el-slider__runway .el-slider__bar) {
+    background-color: #2196F3;
+}
+
+:deep(.ph_purple .el-slider__runway .el-slider__bar) {
+    background-color: #9C27B0;
+}
+</style>

+ 50 - 0
ui/src/components/HnyzDcs/PipeComponent.vue

@@ -0,0 +1,50 @@
+<template>
+    <div ref="wrapperRef" class="progress-wrapper">
+        <el-progress :percentage="100" :stroke-width="strokeWidth" :show-text="false" :striped="pipeStatus"
+            :striped-flow="pipeStatus" :duration="duration" />
+    </div>
+</template>
+
+<script setup>
+import { ref, onMounted, computed ,nextTick} from 'vue'
+
+const props = defineProps({
+    strokeWidth: {// 进度条宽度,单位为像素
+        type: Number,
+        default: 8,
+    },
+    pipeStatus: {
+        type: Boolean,
+        default: false,
+    },
+    durationValue: {// 进度条动画时长,单位为毫秒
+        type: Number,
+    },
+})
+
+const wrapperRef = ref(null)
+const width = ref(0)
+// 获取 DOM 宽度
+// onMounted(() => {
+//     if (wrapperRef.value) {
+//         width.value = wrapperRef.value.offsetWidth || 0
+//     }
+// })
+onMounted(() => {
+  nextTick(() => {
+    if (wrapperRef.value) {
+      width.value = wrapperRef.value.offsetWidth || 0
+    }
+  })
+})
+
+
+// 根据宽度计算 duration,宽度越大,速度越慢(duration 越大)
+const duration = computed(() => {
+    if (props.durationValue !== null && !isNaN(props.durationValue)) {
+        return props.durationValue
+    }
+    const w = width.value == 0 ? 100 : width.value
+    return Math.round(w / 10)
+})
+</script>

+ 105 - 0
ui/src/components/HnyzDcs/PumpProgressComponent.vue

@@ -0,0 +1,105 @@
+<template>
+    <div class="pump_progress_component" :style="gePumptProgressStyle">
+        <i class="icon iconfont-hnyz-colour pump_icon" :class="getPumpIconClass"
+            :style="{ fontSize: `${pumpIconSize}px` }"></i>
+        <div class="pump_title">{{ title }}</div>
+        <Pipe :pipeStatus="pipeStatus" :strokeWidth="pumpIconSize * 0.1" :class="[getProgressClass]" :style="getProgressStyle"></Pipe>
+    </div>
+</template>
+
+<script setup>
+import Pipe from '@/components/HnyzDcs/PipeComponent.vue'
+import { defineProps, computed } from 'vue'
+const props = defineProps({
+    title: {// 泵名称
+        type: String,
+        required: true
+    },
+    //管道长度(默认70%)
+    pipeLength: {
+        type: Number,
+        default: 70
+    },
+    //管道偏移量
+    pipeLeftOffset: {
+        type: Number,
+        default: 74
+    },
+    //是否反转(默认不反转,泵口朝右)
+    isReverse: {
+        type: Boolean,
+        default: false
+    },
+    //管道流通状态
+    pipeStatus: {
+        type: Boolean,
+        default: false
+    },
+    //泵图标大小
+    pumpIconSize: {
+        type: Number,
+        default: 80
+    },
+    //进度条类型
+    progressType: {
+        type: String,
+        default: 'steam'
+    }
+})
+
+//泵icon大小
+const pumpIconSize = computed(() => {
+    return props.pumpIconSize;
+});
+// 计算 pump组件 的 style
+const gePumptProgressStyle = computed(() => {
+    return {
+        fontSize: `${props.pumpIconSize}px`,
+        width: `${props.pumpIconSize}px`,
+        height: `${props.pumpIconSize}px`,
+    }
+})
+
+// 计算 pumpIcon 的 class
+const getPumpIconClass = computed(() => {
+    return `icon-hnyz-colourbeng2_${props.isReverse ? 'L' : 'R'}`
+})
+
+// 计算 progress管道 的 style
+const getProgressStyle = computed(() => {
+    const leftOrRight = props.isReverse ? 'right' : 'left'
+    return {
+        position: 'absolute',
+        top: '19%',
+        width: `${props.pipeLength}%`,
+        zIndex: 1,
+        [leftOrRight]: `${props.pipeLeftOffset}%`,
+    }
+})
+
+// 计算 progress 的 class
+const getProgressClass = computed(() => {
+    return `progress_${props.progressType}`
+})
+
+
+</script>
+
+
+<style scoped lang="scss">
+.pump_progress_component {
+    .pump_icon {
+        position: absolute;
+        z-index: 50;
+    }
+
+    .pump_title {
+        color: #C7D2E0;;
+        position: absolute;
+        top: 110%;
+        left: 43%;
+        transform: translate(-50%, -50%);
+        font-size: 18px;
+    }
+}
+</style>

+ 146 - 0
ui/src/components/HnyzDcs/RTypeTankComponent.vue

@@ -0,0 +1,146 @@
+<template>
+    <!-- 反应釜:温度、搅拌 -->
+    <div class="tank_body" :style="getTankBodyStyle">
+        <!-- 罐体 -->
+        <!-- font-size大小可调节 ,根据传进来的值来控制图标的大小 -->
+        <i class="icon iconfont-hnyz-colour icon-hnyz-colourreactor_hollowedOut tank " :style="getTankStyle">
+            <!-- 标题 -->
+            <div class="tank_title" v-if="title">{{ title }}</div>
+        </i>
+        <!-- 搅拌电机 -->
+        <div class="mixer_machine">
+            <i class="icon iconfont icon-fengshan" :class="{ 'fan_run': getFanStatus }"></i>
+        </div>
+        <!-- temp值组件 -->
+        <TempSlider :tempValue="tempValue" class="temp_pos" />
+    </div>
+</template>
+
+<script setup>
+import TempSlider from '@/components/HnyzDcs/TempSliderComponent.vue'
+import { computed } from 'vue'
+
+const props = defineProps({
+    tempValue: {//temp
+        type: Number,
+        default: null
+    },
+    fanStatus: {//风扇状态
+        type: Boolean,
+        default: false,
+    },
+    iconSize: {//图标大小
+        type: Number,
+        default: 200,
+    },
+    title: {//罐名
+        type: String,
+    },
+    iconWidth: {//图标宽度
+        type: Number,
+    },
+    iconHeight: {//图标高度
+        type: Number,
+    },
+})
+
+
+//罐体样式
+const getTankBodyStyle = computed(() => ({
+    width: `${props.iconWidth ?? props.iconSize}px`,
+    height: `${props.iconHeight ?? props.iconSize}px`,
+    fontSize: `${props.iconSize}px`,
+}))
+
+
+// 罐子样式
+const getTankStyle = computed(() => {
+    const style = {
+        fontSize: props.iconSize + 'px',
+        display: 'inline-block'
+    }
+    //根据传进来的iconWidth和iconHeight来控制图标的大小
+    const scaleX = props.iconWidth ? props.iconWidth / props.iconSize : 1
+    const scaleY = props.iconHeight ? props.iconHeight / props.iconSize : 1
+
+    if (scaleX !== 1 || scaleY !== 1) {
+        style.transform = `scale(${scaleX}, ${scaleY})`
+    }
+
+    return style
+})
+
+
+//temp值
+const tempValue = computed({
+    get() {
+        return props.tempValue
+    },
+})
+
+//风扇状态
+const getFanStatus = computed(() => {
+    return props.fanStatus
+})
+
+</script>
+
+<style scoped lang="scss">
+.tank_body {
+    text-align: center;
+    position: relative;
+
+    .tank {
+        position: relative;
+        z-index: 10;
+
+        //罐子名称
+        .tank_title {
+            position: absolute;
+            top: 75%;
+            left: 49%;
+            transform: translate(-50%, -50%);
+            font-size: 30px;
+            color: #e65100;
+            font-weight: bold;
+        }
+    }
+
+    .temp_pos {
+        position: absolute;
+        top: 40%;
+        left: 64%;
+        z-index: 100;
+    }
+
+    //搅拌电机
+    .mixer_machine {
+        position: absolute;
+        top: 37%;
+        left: 50%;
+        transform: translate(-50%, -50%);
+
+        .icon-fengshan {
+            color: aliceblue;
+            font-size: 50px;
+            display: inline-block; 
+        }
+
+        //旋转动画
+        @keyframes rotate-clockwise {
+            from {
+                transform: rotate(0deg);
+            }
+
+            to {
+                transform: rotate(360deg);
+            }
+        }
+
+        .fan_run {
+            animation: rotate-clockwise 1s linear infinite;
+        }
+    }
+
+}
+</style>

+ 219 - 0
ui/src/components/HnyzDcs/RTypeTankValvesComponent.vue

@@ -0,0 +1,219 @@
+<template>
+    <div class="tank_valves" :style="getTankBodyStyle">
+        <RTypeTank :title="title" :waterLevelValue="waterLevelValue" :iconWidth="iconWidth" :iconHeight="iconHeight"
+            :iconSize="iconSize" :tempValue="tempValue" :fanStatus="fanStatus"></RTypeTank>
+        <!-- 阀门进度 -->
+        <div class="valve_progress">
+            <div :style="valveProgressStyle" class="valve_progress1 rotate_270" v-if="valveNames[0]">
+                <ValveProgress :iconSize="valveIconSize" :title="valveNames[0]" :rotateAngle="270" :pipeLength="419"
+                    :pipeLeftOffset="-271" :valveStatusArr="initValveStatusArr" progressType="steam"
+                    :pipeStatus="initPipeStatus" :pipeReverse="true" />
+            </div>
+            <div :style="valveProgressStyle" class="valve_progress2" v-if="valveNames[1]">
+                <ValveProgress :iconSize="valveIconSize" :title="valveNames[1]" :pipeLength="290"
+                    :pipeLeftOffset="-60" :valveStatusArr="initValveStatusArr" progressType="steam"
+                    :pipeStatus="initPipeStatus" />
+            </div>
+            <div :style="valveProgressStyle" class="valve_progress3" v-if="valveNames[2]">
+                <ValveProgress :iconSize="valveIconSize" :title="valveNames[2]" :pipeLength="200" :pipeLeftOffset="-60"
+                    :valveStatusArr="initValveStatusArr" progressType="steam" :pipeStatus="initPipeStatus" />
+            </div>
+            <div :style="valveProgressStyle" class="valve_progress4" v-if="valveNames[3]">
+                <ValveProgress :iconSize="valveIconSize" :title="valveNames[3]" :pipeLength="575" :pipeLeftOffset="-232"
+                    :valveStatusArr="initValveStatusArr" progressType="steam" :pipeStatus="initPipeStatus" />
+            </div>
+        </div>
+        <!-- 泵进度 -->
+        <div class="pump_progress">
+            <div :style="pumpProgressStyle" class="pump_progress1" v-if="pumpName">
+                <Pump :title="pumpName" :pumpDataArr="[1, 10]" :iconSize="80" :showPipe="true" :pipeType="steam" />
+            </div>
+        </div>
+        <!-- 流量计 -->
+        <div class="flow_meters">
+            <div class="flow_meter1">
+                <FlowMeter title="PIT2001" :flowValueArr="[100, 100]" :rotateAngle="270" :iconSize="flowMeterIconSize" />
+            </div>
+
+            <div class="flow_meter2">
+                <FlowMeter title="PIT2002" :flowValueArr="[100, 100]" :iconSize="flowMeterIconSize" />
+            </div>
+        </div>
+    </div>
+</template>
+
+<script setup>
+import RTypeTank from '@/components/HnyzDcs/RTypeTankComponent.vue';
+import ValveProgress from '@/components/DCS/ValveProgressComponent.vue';
+import PumpProgress from '@/components/HnyzDcs/PumpProgressComponent.vue';
+import Pump from '@/components/DCS/PumpComponent.vue';
+import FlowMeter from '@/components/HnyzDcs/FlowMeterComponent.vue';
+import { computed } from 'vue'
+
+const initValveStatusArr = [true]
+const initPipeStatus = true
+const props = defineProps({
+    tempValue: {//temp
+        type: Number,
+        default: null
+    },
+    waterLevelValue: {// 水位值
+        type: Number,
+        default: -1,// -1表示未传水位值
+    },
+    fanStatus: {//风扇状态
+        type: Boolean,
+        default: false,
+    },
+    iconSize: {//图标大小
+        type: Number,
+        default: 200,
+    },
+    title: {//罐名
+        type: String,
+    },
+    iconWidth: {//图标宽度
+        type: Number,
+    },
+    iconHeight: {//图标高度
+        type: Number,
+    },
+})
+
+//默认阀门名称数组
+const defaultValveNames = new Array(4).fill('ACV_default')
+//泵默认名称
+const defaultPumpName = 'P_default'
+//流量计默认名称
+const defaultFlowMeterName = new Array(4).fill('PIT_default')
+// 阀门名称映射表
+const valveNameArr= {
+    'R2001': ['ACV2003', 'ACV2001', 'ACV2007','ACV2005'],
+    'R2002': ['ACV2004', 'ACV2002', 'ACV2008','ACV2006'],
+}
+//泵名称映射表
+const pumpNameArr = {
+    'R2001': 'P2001',
+    'R2002': 'P2002',
+}
+//流量计名称映射表
+const flowMeterNameArr = {
+    'R2001': ['PIT2001', 'PIT2002'],
+    'R2002': ['PIT2004', 'PIT2003'],
+}
+//阀门名称数组,根据罐名来匹配
+const valveNames = computed(() => {
+    return valveNameArr[props.title] || defaultValveNames
+})
+
+//泵名称
+const pumpName = computed(() => {
+    return pumpNameArr[props.title] || defaultPumpName
+})
+
+//流量计名称数组
+const flowMeterNames = computed(() => {
+    return flowMeterNameArr[props.title] || defaultFlowMeterName
+})
+
+//罐体样式
+const getTankBodyStyle = computed(() => ({
+    width: `${props.iconWidth ?? props.iconSize}px`,
+    height: `${props.iconHeight ?? props.iconSize}px`,
+}))
+
+//阀门icon大小(罐子200-阀门50)
+const valveIconSize = computed(() => {
+    return props.iconSize * 0.25;
+});
+
+//阀门进度样式
+const valveProgressStyle = computed(() => {
+    return {
+        width: `${valveIconSize.value}px`,
+        height: `${valveIconSize.value}px`,
+    }
+});
+
+//泵icon大小(罐子200-泵80)
+const pumpIconSize = computed(() => {
+    return props.iconSize * 0.4;
+});
+
+//泵进度样式
+const pumpProgressStyle = computed(() => {
+    return {
+        width: `${pumpIconSize.value}px`,
+        height: `${pumpIconSize.value}px`,
+    }
+});
+//流量计icon大小(罐子200-流量计55)
+const flowMeterIconSize = computed(() => {
+    return props.iconSize * 0.275;
+});
+
+//temp值
+const tempValue = computed({
+    get() {
+        return props.tempValue
+    },
+})
+
+</script>
+
+<style scoped lang="scss">
+.tank_valves {
+    position: relative;
+    z-index: 10;
+
+    .valve_progress {
+        .valve_progress1 {
+            position: absolute;
+            top: -38%;
+            left: 61%;
+        }
+
+        .valve_progress2 {
+            position: absolute;
+            top: 17%;
+            left: -11%;
+        }
+
+        .valve_progress3 {
+            position: absolute;
+            top: 78%;
+            left: 96%;
+        }
+
+        .valve_progress4 {
+            position: absolute;
+            top: 18%;
+            left: 126%;
+        }
+    }
+
+    .pump_progress {
+        .pump_progress1 {
+            position: absolute;
+            top: 93%;
+            left: 150%;
+            transform: translate(-50%, -50%);
+            z-index: 50;
+        }
+    }
+
+    .flow_meters {
+        .flow_meter1 {
+            position: absolute;
+            top: -30%;
+            left: 58.2%;
+        }
+
+        .flow_meter2 {
+            position: absolute;
+            top: 27%;
+            left: 100%;
+        }
+    }
+}
+</style>

+ 125 - 0
ui/src/components/HnyzDcs/STypeTankComponent.vue

@@ -0,0 +1,125 @@
+<template>
+    <!-- 分离塔:搅拌 -->
+    <div class="tank_body" :style="getTankBodyStyle">
+        <!-- 罐体 -->
+        <!-- font-size大小可调节 ,根据传进来的值来控制图标的大小 -->
+        <i class="icon iconfont-hnyz-colour icon-hnyz-colourknockoutTower_hollowedOut tank " :style="getTankStyle">
+            <!-- 标题 -->
+            <div class="tank_title" v-if="title">{{ title }}</div>
+        </i>
+        <!-- 搅拌电机 -->
+        <div class="mixer_machine">
+            <i class="icon iconfont icon-fengshan" :class="{ 'fan_run': getFanStatus }"></i>
+        </div>
+    </div>
+</template>
+
+<script setup>
+import { computed } from 'vue'
+
+const props = defineProps({
+    fanStatus: {//风扇状态
+        type: Boolean,
+        default: false,
+    },
+    iconSize: {//图标大小
+        type: Number,
+        default: 200,
+    },
+    title: {//罐名
+        type: String,
+    },
+    iconWidth: {//图标宽度
+        type: Number,
+    },
+    iconHeight: {//图标高度
+        type: Number,
+    },
+})
+
+
+//罐体样式
+const getTankBodyStyle = computed(() => ({
+    width: `${props.iconWidth ?? props.iconSize}px`,
+    height: `${props.iconHeight ?? props.iconSize}px`,
+    fontSize: `${props.iconSize}px`,
+}))
+
+
+// 罐子样式
+const getTankStyle = computed(() => {
+    const style = {
+        fontSize: props.iconSize + 'px',
+        display: 'inline-block'
+    }
+    //根据传进来的iconWidth和iconHeight来控制图标的大小
+    const scaleX = props.iconWidth ? props.iconWidth / props.iconSize : 1
+    const scaleY = props.iconHeight ? props.iconHeight / props.iconSize : 1
+
+    if (scaleX !== 1 || scaleY !== 1) {
+        style.transform = `scale(${scaleX}, ${scaleY})`
+    }
+
+    return style
+})
+
+//风扇状态
+const getFanStatus = computed(() => {
+    return props.fanStatus
+})
+
+</script>
+
+<style scoped lang="scss">
+//水位罐
+.tank_body {
+    text-align: center;
+    position: relative;
+
+    .tank {
+        position: relative;
+        z-index: 10;
+
+        //罐子名称
+        .tank_title {
+            position: absolute;
+            top: 66%;
+            left: 49%;
+            transform: translate(-50%, -50%);
+            font-size: 30px;
+            color: #e65100;
+            font-weight: bold;
+        }
+    }
+
+    //搅拌电机
+    .mixer_machine {
+        position: absolute;
+        top: 26%;
+        left: 50%;
+        transform: translate(-50%, -50%);
+
+        .icon-fengshan {
+            color: aliceblue;
+            font-size: 50px;
+            display: inline-block; 
+        }
+
+        //旋转动画
+        @keyframes rotate-clockwise {
+            from {
+                transform: rotate(0deg);
+            }
+
+            to {
+                transform: rotate(360deg);
+            }
+        }
+
+        .fan_run {
+            animation: rotate-clockwise 1s linear infinite;
+        }
+    }
+
+}
+</style>

+ 136 - 0
ui/src/components/HnyzDcs/STypeTankValvesComponent.vue

@@ -0,0 +1,136 @@
+<template>
+    <div class="tank_valves" :style="getTankBodyStyle">
+        <STypeTank :title="title" :waterLevelValue="waterLevelValue" :iconWidth="iconWidth" :iconHeight="iconHeight"
+            :iconSize="iconSize" :tempValue="tempValue" :fanStatus="fanStatus"></STypeTank>
+        <!-- 阀门进度 -->
+        <div class="valve_progress">
+            <div :style="valveProgressStyle" class="valve_progress1" v-if="valveNames[0]">
+                <ValveProgress :iconSize="valveIconSize" :title="valveNames[0]" :pipeLength="200" :pipeLeftOffset="-38"
+                    :valveStatusArr="initValveStatusArr" progressType="steam" :pipeStatus="initPipeStatus" />
+            </div>
+            <div :style="valveProgressStyle" class="valve_progress2" v-if="valveNames[1]">
+                <ValveProgress :iconSize="valveIconSize" :title="valveNames[1]" :pipeLength="200" :pipeLeftOffset="-60"
+                    :valveStatusArr="initValveStatusArr" progressType="steam" :pipeStatus="initPipeStatus" />
+            </div>
+            <div :style="valveProgressStyle" class="valve_progress3" v-if="valveNames[2]">
+                <ValveProgress :iconSize="valveIconSize" :title="valveNames[2]" :pipeLength="250" :pipeLeftOffset="-60"
+                    :valveStatusArr="initValveStatusArr" progressType="steam" :pipeStatus="initPipeStatus" />
+            </div>
+            <div :style="valveProgressStyle" class="valve_progress4 rotate_90" v-if="valveNames[3]">
+                <ValveProgress :iconSize="valveIconSize" :title="valveNames[3]" :rotateAngle="90" :pipeLength="400"
+                    :pipeLeftOffset="-121" :valveStatusArr="initValveStatusArr" progressType="steam"
+                    :pipeStatus="initPipeStatus" />
+            </div>
+        </div>
+    </div>
+</template>
+
+<script setup>
+import STypeTank from '@/components/HnyzDcs/STypeTankComponent.vue';
+import ValveProgress from '@/components/DCS/ValveProgressComponent.vue';
+import { computed } from 'vue'
+const initValveStatusArr = [true]
+const initPipeStatus = true
+const props = defineProps({
+    tempValue: {//temp
+        type: Number,
+        default: null
+    },
+    waterLevelValue: {// 水位值
+        type: Number,
+        default: -1,// -1表示未传水位值
+    },
+    fanStatus: {//风扇状态
+        type: Boolean,
+        default: false,
+    },
+    iconSize: {//图标大小
+        type: Number,
+        default: 200,
+    },
+    title: {//罐名
+        type: String,
+    },
+    iconWidth: {//图标宽度
+        type: Number,
+    },
+    iconHeight: {//图标高度
+        type: Number,
+    },
+})
+
+
+//默认阀门名称数组
+const defaultValveNames = new Array(4).fill('ACV_default')
+
+// 阀门名称映射表
+const valveNameArr = {
+    'S2002': ['ACV2032', 'ACV2033', 'ACV2034', 'ACV2044'],
+    'S2004': ['ACV2039', '', 'ACV2040', ''],
+}
+
+//阀门名称数组,根据罐名来匹配
+const valveNames = computed(() => {
+    return valveNameArr[props.title] || defaultValveNames
+})
+
+//罐体样式
+const getTankBodyStyle = computed(() => ({
+    width: `${props.iconWidth ?? props.iconSize}px`,
+    height: `${props.iconHeight ?? props.iconSize}px`,
+}))
+
+//temp值
+const tempValue = computed({
+    get() {
+        return props.tempValue
+    },
+})
+
+//阀门icon大小(罐子200-阀门50)
+const valveIconSize = computed(() => {
+    return props.iconSize * 0.25;
+});
+
+//阀门进度样式
+const valveProgressStyle = computed(() => {
+    return {
+        width: `${valveIconSize.value}px`,
+        height: `${valveIconSize.value}px`,
+    }
+});
+
+</script>
+
+<style scoped lang="scss">
+.tank_valves {
+    position: relative;
+    z-index: 10;
+
+    .valve_progress {
+        .valve_progress1 {
+            position: absolute;
+            top: 16%;
+            left: -12%;
+        }
+
+        .valve_progress2 {
+            position: absolute;
+            top: 76%;
+            left: -7%;
+        }
+
+        .valve_progress3 {
+            position: absolute;
+            top: 16%;
+            left: 91%;
+        }
+
+        .valve_progress4 {
+            position: absolute;
+            top: 170%;
+            left: 54%;
+        }
+    }
+}
+</style>

+ 81 - 0
ui/src/components/HnyzDcs/SeparatorComponent.vue

@@ -0,0 +1,81 @@
+<template>
+    <!-- 分离器 -->
+    <div class="tank_body" :style="getTankBodyStyle">
+        <i class="icon iconfont-hnyz-colour icon-hnyz-colourseparator tank " :style="getTankStyle">
+            <!-- 标题 -->
+            <div class="tank_title" v-if="title">{{ title }}</div>
+        </i>
+    </div>
+</template>
+
+<script setup>
+import { computed } from 'vue'
+
+const props = defineProps({
+    iconSize: {//图标大小
+        type: Number,
+        default: 200,
+    },
+    title: {//罐名
+        type: String,
+    },
+    iconWidth: {//图标宽度
+        type: Number,
+    },
+    iconHeight: {//图标高度
+        type: Number,
+    },
+})
+
+
+//罐体样式
+const getTankBodyStyle = computed(() => ({
+    width: `${props.iconWidth ?? props.iconSize}px`,
+    height: `${props.iconHeight ?? props.iconSize}px`,
+    fontSize: `${props.iconSize}px`,
+}))
+
+
+// 罐子样式
+const getTankStyle = computed(() => {
+    const style = {
+        fontSize: props.iconSize + 'px',
+        display: 'inline-block'
+    }
+    //根据传进来的iconWidth和iconHeight来控制图标的大小
+    const scaleX = props.iconWidth ? props.iconWidth / props.iconSize : 1
+    const scaleY = props.iconHeight ? props.iconHeight / props.iconSize : 1
+
+    if (scaleX !== 1 || scaleY !== 1) {
+        style.transform = `scale(${scaleX}, ${scaleY})`
+    }
+
+    return style
+})
+
+</script>
+
+<style scoped lang="scss">
+//水位罐
+.tank_body {
+    text-align: center;
+    position: relative;
+
+    .tank {
+        position: relative;
+        z-index: 10;
+
+        //罐子名称
+        .tank_title {
+            position: absolute;
+            top: 39%;
+            left: 50%;
+            transform: translate(-50%, -50%);
+            font-size: 30px;
+            color: #d3e600;
+            font-weight: bold;
+        }
+    }
+
+}
+</style>

+ 201 - 0
ui/src/components/HnyzDcs/SeparatorTowerValvesComponent.vue

@@ -0,0 +1,201 @@
+<template>
+    <div class="tank_valves" :style="getTankBodyStyle">
+        <!-- 分离塔·  -->
+        <!-- <VTypeTank2 :title="title" :width="width" :height="height" :waterLevelValue="80" :tempValue="50" /> -->
+        <VTypeTank2 title="V7002" :iconSize="iconSize" />
+        <div class="valve_progress">
+            <ValveProgress :iconSize="valveIconSize" :title="valveNames[0]" :rotateAngle="270" :pipeLength="1250"
+                :pipeLeftOffset="-1090" :valveStatusArr="initValveStatusArr" progressType="steam" :pipeReverse="true"
+                :pipeStatus="initPipeStatus" class="valve_progress1 rotate_270" />
+            <ValveProgress :iconSize="valveIconSize" :title="valveNames[1]" :rotateAngle="90" :pipeLength="140"
+                :pipeLeftOffset="-20" :valveStatusArr="initValveStatusArr" progressType="steam"
+                :pipeStatus="initPipeStatus" class="valve_progress2 rotate_90" />
+            <ValveProgress :iconSize="valveIconSize" :title="valveNames[2]" :rotateAngle="90" :pipeLength="140"
+                :pipeLeftOffset="-20" :valveStatusArr="initValveStatusArr" progressType="steam"
+                :pipeStatus="initPipeStatus" class="valve_progress3 rotate_90" />
+            <ValveProgress :iconSize="valveIconSize" :title="valveNames[3]" :rotateAngle="90" :pipeLength="140"
+                :pipeLeftOffset="-20" :valveStatusArr="initValveStatusArr" progressType="steam"
+                :pipeStatus="initPipeStatus" class="valve_progress4 rotate_90" />
+            <ValveProgress :iconSize="valveIconSize" :title="valveNames[4]" :rotateAngle="90" :pipeLength="140"
+                :pipeLeftOffset="-20" :valveStatusArr="initValveStatusArr" progressType="steam"
+                :pipeStatus="initPipeStatus" class="valve_progress5 rotate_90" />
+            <ValveProgress :iconSize="valveIconSize" :title="valveNames[5]" :rotateAngle="90" :pipeLength="140"
+                :pipeLeftOffset="-20" :valveStatusArr="initValveStatusArr" progressType="steam"
+                :pipeStatus="initPipeStatus" class="valve_progress6 rotate_90" />
+        </div>
+        <div class="pump_progress">
+           
+        </div>
+        <div class="pipes">
+            <Pipe :pipeStatus="initPipeStatus" :strokeWidth="strokeWidth" class="progress_steam progress_pos1"></Pipe>
+            <Pipe :pipeStatus="initPipeStatus" :strokeWidth="strokeWidth" class="progress_steam progress_pos2"></Pipe>
+            <Pipe :pipeStatus="initPipeStatus" :strokeWidth="strokeWidth" class="progress_steam progress_pos3"></Pipe>
+            <Pipe :pipeStatus="initPipeStatus" :strokeWidth="strokeWidth" class="progress_steam progress_pos4"></Pipe>
+            <Pipe :pipeStatus="initPipeStatus" :strokeWidth="strokeWidth" class="progress_steam progress_pos5"></Pipe>
+        </div>
+    </div>
+</template>
+
+<script setup>
+import VTypeTank2 from '@/components/HnyzDcs/VTypeTank2Component.vue';
+import ValveProgress from '@/components/DCS/ValveProgressComponent.vue';
+import Pipe from '@/components/HnyzDcs/PipeComponent.vue';
+import Pump from '@/components/DCS/PumpComponent.vue';
+import { computed } from 'vue'
+const initValveStatusArr = [true]
+const initPipeStatus = true
+const props = defineProps({
+    iconSize: {
+        type: Number,
+    },
+    iconWidth: {//图标宽度
+        type: Number,
+    },
+    iconHeight: {//图标高度
+        type: Number,
+    },
+    tempValue: {
+        type: Number,
+    },
+    waterLevelValue: {// 水位值
+        type: Number,
+        default: -1,// -1表示未传水位值
+    },
+    title: {//罐名
+        type: String,
+    },
+})
+
+//默认阀门名称数组
+const defaultValveNames = new Array(6).fill('ACV_default')
+
+// 阀门名称映射表
+const valveNameArr = {
+    '分离塔1': ['ACV6301A', 'ACV6011B', 'ACV6003A', 'ACV6015A', 'ACV6020A', 'ACV6502A'],
+}
+
+
+//阀门名称数组,根据罐名来匹配
+const valveNames = computed(() => {
+    return valveNameArr[props.title] || defaultValveNames
+})
+
+
+
+const width = computed(() => {
+    return props.iconWidth ?? props.iconSize
+})
+const height = computed(() => {
+    return props.iconHeight ?? props.iconSize
+})
+
+//罐体样式
+const getTankBodyStyle = computed(() => ({
+    width: `${width.value}px`,
+    height: `${height.value}px`,
+}))
+
+//阀门icon大小(水槽100*80-阀门30)
+const valveIconSize = computed(() => {
+    return width.value * 0.3;
+});
+
+//管道宽度
+const strokeWidth = computed(() => {
+    return width.value * 0.048;
+});
+
+</script>
+
+<style scoped lang="scss">
+.tank_valves {
+    position: relative;
+    z-index: 10;
+
+    .valve_progress {
+        .valve_progress1 {
+            position: absolute;
+            top: -300%;
+            left: 60%;
+        }
+
+        .valve_progress2 {
+            position: absolute;
+            top: -20%;
+            left: 40%;
+        }
+
+        .valve_progress3 {
+            position: absolute;
+            top: -70%;
+            left: 40%;
+        }
+
+        .valve_progress4 {
+            position: absolute;
+            top: -120%;
+            left: 40%;
+        }
+
+        .valve_progress5 {
+            position: absolute;
+            top: -170%;
+            left: 40%;
+        }
+
+        .valve_progress6 {
+            position: absolute;
+            top: -240%;
+            left: 40%;
+        }
+    }
+
+    .pump_progress {
+
+        .pump_progress1 {
+            position: absolute;
+            top: 93%;
+            left: 146%;
+            transform: translate(-50%, -50%);
+        }
+    }
+
+    .pipes {
+        .progress_pos1 {
+            width: 34%;
+            position: absolute;
+            top: -3%;
+            left: 33%;
+        }
+
+        .progress_pos2 {
+            width: 34%;
+            position: absolute;
+            top: -53%;
+            left: 33%;
+        }
+
+        .progress_pos3 {
+            width: 34%;
+            position: absolute;
+            top: -103%;
+            left: 33%;
+        }
+
+
+        .progress_pos4 {
+            width: 34%;
+            position: absolute;
+            top: -153%;
+            left: 33%;
+        }
+
+        .progress_pos5 {
+            width: 34%;
+            position: absolute;
+            top: -223%;
+            left: 33%;
+        }
+    }
+}
+</style>

+ 114 - 0
ui/src/components/HnyzDcs/TempSliderComponent.vue

@@ -0,0 +1,114 @@
+<template>
+    <div class="slider_demo_block" v-if="props.tempValue !== null && props.tempValue !== undefined">
+        <el-slider :model-value="props.tempValue" vertical disabled :max="140" :min="-10" :marks="marks"
+            class="temp_slider" :class="getTempClass" :style="sliderStyle" />
+    </div>
+</template>
+
+<script setup>
+import { computed } from 'vue'
+
+const props = defineProps({
+    tempValue: {
+        type: Number, // 传入的温度
+    },
+    sliderWidth: {// 进度条宽度
+        type: Number,
+        default: 10,
+    },
+    sliderHeighth: {// 进度条高度
+        type: Number,
+    },
+})
+
+/** 颜色 & 进度条 class */
+function getTempColor(val) {
+    if (val >= 120) return { class: 'temp_red', color: '#F44336' } // 红
+    if (val >= 75) return { class: 'temp_orange', color: '#FF9800' } // 橙
+    return { class: 'temp_green', color: '#4CAF50' }      // 绿
+}
+
+/** 进度条主体颜色 class */
+const getTempClass = computed(() => getTempColor(props.tempValue).class)
+
+/** slider 上的刻度 marks */
+const marks = computed(() => {
+    if (props.tempValue == null || isNaN(props.tempValue)) return {}
+
+    const { color } = getTempColor(props.tempValue)
+    const valueNum = Number(props.tempValue)    // 数值型 key
+    const valueLabel = Math.round(valueNum)
+
+    return {
+        [valueNum]: {
+            style: { color, fontWeight: 'bold' },
+            label: `${valueLabel}°C`,
+        },
+    }
+})
+// slider 动态样式
+const sliderStyle = computed(() => ({
+    '--marks-font-size': `${props.sliderWidth * 1.8}px`,// 刻度字体大小
+    '--runway-width': `${props.sliderWidth}px`, // 进度条宽度
+    '--slider-height': props.sliderHeighth
+        ? `${props.sliderHeighth}px`
+        : '0.5em',                   // 进度条高度
+}))
+
+</script>
+
+
+
+<style scoped lang="scss">
+.slider_demo_block {
+    max-width: 600px;
+    display: flex;
+    align-items: center;
+}
+
+:deep(.temp_slider) {
+    height: var(--slider-height, 0.5em);
+
+    .el-slider__runway .el-slider__button-wrapper .el-slider__button {
+        position: absolute;
+        left: 22%;
+        bottom: 22%;
+        display: none; // 隐藏进度条上的圆形按键
+    }
+
+    .el-slider__runway .el-slider__bar {
+        background-color: lightgreen; //绿色
+    }
+
+    --marks-font-size: 18px;
+    --runway-width: 10px;
+
+    .el-slider__marks-text {
+        font-size: var(--marks-font-size);
+    }
+
+    .el-slider__runway {
+        width: var(--runway-width);
+    }
+
+    .el-slider__runway .el-slider__bar {
+        width: 100%;
+    }
+
+    .el-slider__marks-stop {
+        width: 100%;
+    }
+}
+
+:deep(.temp_green .el-slider__runway .el-slider__bar) {
+    background-color: #4CAF50;
+}
+
+:deep(.temp_orange .el-slider__runway .el-slider__bar) {
+    background-color: #FF9800;
+}
+
+:deep(.temp_red .el-slider__runway .el-slider__bar) {
+    background-color: #F44336;
+}
+</style>

+ 85 - 0
ui/src/components/HnyzDcs/TransportProgressComponent.vue

@@ -0,0 +1,85 @@
+<template>
+    <div class="transport_progress_component" :style="{ fontSize: `${iconSize}px` }">
+        <!-- 运输器 -->
+        <i class="icon iconfont-hnyz-colour icon-hnyz-colourkaomianjin-1 transport_icon"
+            :style="{ fontSize: `${iconSize}px` }"></i>
+        <div class="transport_title">{{ title }}</div>
+        <Pipe :pipeStatus="pipeStatus" :class="[getProgressClass]" :style="getProgressStyle" class="rotate_90"></Pipe>
+    </div>
+</template>
+
+<script setup>
+import Pipe from '@/components/HnyzDcs/PipeComponent.vue'
+import { defineProps, computed } from 'vue'
+const props = defineProps({
+    title: {// 泵名称
+        type: String,
+        required: true
+    },
+    //管道流通状态
+    pipeStatus: {
+        type: Boolean,
+        default: false
+    },
+    //泵图标大小
+    iconSize: {
+        type: Number,
+        default: 60
+    },
+    //进度条类型
+    progressType: {
+        type: String,
+        default: 'steam'
+    },
+    //进度条宽度
+    pipeLength: {
+        type: Number,
+        default: 130
+    },
+    //进度条位移
+    pipeTopOffset: {
+        type: Number,
+        default: -40
+    },
+})
+
+//泵icon大小
+const iconSize = computed(() => {
+    return props.iconSize;
+});
+
+// 计算 progress 颜色的 class
+const getProgressClass = computed(() => {
+    return `progress_${props.progressType}`
+})
+
+// 计算 progress 的 style(单独使用时方便引入)
+const getProgressStyle = computed(() => {
+    return {
+        'position': 'absolute',
+        'top': `${props.pipeTopOffset}%`,
+        'left': '42%',
+        'width': `${props.pipeLength}%`,
+    }
+})
+
+</script>
+
+
+<style scoped lang="scss">
+.transport_progress_component {
+    .transport_icon {
+        position: absolute;
+        z-index: 50;
+    }
+
+    .transport_title {
+        color: white;
+        position: absolute;
+        top: 118%;
+        left: 145%;
+        transform: translate(-50%, -50%);
+        font-size: 16px;
+    }
+}
+</style>

+ 127 - 0
ui/src/components/HnyzDcs/VTypeTank2Component.vue

@@ -0,0 +1,127 @@
+<template>
+    <!-- 储罐:水位 -->
+    <div class="tank_body" :style="getTankBodyStyle">
+        <!-- 罐体 -->
+        <i class="icon iconfont-hnyz-colour tank" :class="tankIconClass" :style="getTankStyle">
+            <!-- 标题 -->
+            <div class="tank_title" v-if="title" :style="{ fontSize: `${iconSize * 0.15}px` }">{{ title }}</div>
+            <!-- 水位 -->
+            <div v-if="waterLevelValue >= 0">
+                <dv-water-level-pond :config="waterLevelConfig" class="water_level water_level_pos3" />
+            </div>
+        </i>
+    </div>
+</template>
+
+<script setup>
+import { computed } from 'vue'
+
+const props = defineProps({
+    waterLevelValue: {// 水位值
+        type: Number,
+        default: -1,// -1表示未传水位值
+    },
+    iconSize: {//图标大小
+        type: Number,
+        default: 200,
+    },
+    title: {//罐名
+        type: String,
+    },
+    iconWidth: {//图标宽度
+        type: Number,
+    },
+    iconHeight: {//图标高度
+        type: Number,
+    },
+})
+
+
+//罐体样式
+const getTankBodyStyle = computed(() => ({
+    width: `${props.iconWidth ?? props.iconSize}px`,
+    height: `${props.iconHeight ?? props.iconSize}px`,
+    fontSize: `${props.iconSize}px`,
+}))
+
+// 罐子样式
+const getTankStyle = computed(() => {
+    const style = {
+        fontSize: props.iconSize + 'px',
+        display: 'inline-block'
+    }
+    //根据传进来的iconWidth和iconHeight来控制图标的大小
+    const scaleX = props.iconWidth ? props.iconWidth / props.iconSize : 1
+    const scaleY = props.iconHeight ? props.iconHeight / props.iconSize : 1
+
+    if (scaleX !== 1 || scaleY !== 1) {
+        style.transform = `scale(${scaleX}, ${scaleY})`
+    }
+    return style
+})
+
+// 罐型图标
+const tankIconClass = computed(() => {
+    return props.waterLevelValue >= 0 ? 'icon-hnyz-colourstorageTank_hollowedOut' : 'icon-hnyz-colourstorageTank'
+});
+
+// 仅传 waterLevelValue,内部组装 config
+const waterLevelConfig = computed(() => ({
+    data: [props.waterLevelValue],
+    waveHeight: 5,// 波浪高度
+}))
+
+
+
+</script>
+
+<style scoped lang="scss">
+//水位罐
+.tank_body {
+    text-align: center;
+    position: relative;
+
+    .tank {
+        position: relative;
+        z-index: 10;
+
+        //罐子名称
+        .tank_title {
+            position: absolute;
+            top: 82%;
+            left: 49%;
+            transform: translate(-50%, -50%);
+            font-size: 30px;
+            color: #e65100;
+            font-weight: bold;
+        }
+
+        // 水位
+        .water_level {
+            width: 0.4em;
+            height: 0.5em;
+        }
+
+        //水位图位置
+        .water_level_pos3 {
+            position: absolute;
+            top: 21%;
+            left: 30%;
+        }
+
+        .dv-water-pond-level :deep(canvas) {
+            position: absolute;
+            left: 0%;
+        }
+
+        .dv-water-pond-level :deep(rect) {
+            // fill:unset;//去掉默认的颜色
+            width: 99%;
+            height: 99%;
+            stroke-width: 0 !important;
+        }
+
+    }
+
+}
+</style>

+ 189 - 0
ui/src/components/HnyzDcs/VTypeTankComponent.vue

@@ -0,0 +1,189 @@
+<template>
+    <!-- 落地罐:水位、ph、搅拌 -->
+    <div class="tank_body" :style="getTankBodyStyle">
+        <!-- 罐体 -->
+        <i class="icon iconfont-hnyz-colour tank" :class="tankIconClass" :style="getTankStyle">
+            <!-- 标题 200-30px-->
+            <div class="tank_title" v-if="title" :style="{ fontSize: `${iconSize * 0.15}px` }">{{ title }}</div>
+            <!-- 水位 -->
+            <div v-if="waterLevelValue >= 0">
+                <dv-water-level-pond :config="waterLevelConfig" class="water_level water_level_pos3" />
+            </div>
+        </i>
+        <!-- 搅拌电机 -->
+        <div class="mixer_machine" v-if="typeof fanStatus === 'boolean'">
+            <i class="icon iconfont icon-fengshan" :class="{ 'fan_run': fanStatus }"></i>
+        </div>
+        <!-- ph值组件 -->
+        <PhSlider :phValue="phValue" class="ph_pos" />
+    </div>
+</template>
+
+<script setup>
+import PhSlider from '@/components/HnyzDcs/PhSliderComponent.vue'
+import { computed } from 'vue'
+
+const props = defineProps({
+    phValue: {//ph
+        type: Number,
+        default: null
+    },
+    waterLevelValue: {// 水位值
+        type: Number,
+        default: -1,// -1表示未传水位值
+    },
+    fanStatus: {//风扇状态
+        type: Boolean,
+    },
+    iconSize: {//图标大小
+        type: Number,
+        default: 200,
+    },
+    title: {//罐名
+        type: String,
+    },
+    iconWidth: {//图标宽度
+        type: Number,
+    },
+    iconHeight: {//图标高度
+        type: Number,
+    },
+})
+
+
+//罐体样式
+const getTankBodyStyle = computed(() => ({
+    width: `${props.iconWidth ?? props.iconSize}px`,
+    height: `${props.iconHeight ?? props.iconSize}px`,
+    fontSize: `${props.iconSize}px`,
+}))
+
+
+// 罐子样式
+const getTankStyle = computed(() => {
+    const style = {
+        fontSize: props.iconSize + 'px',
+        display: 'inline-block'
+    }
+    //根据传进来的iconWidth和iconHeight来控制图标的大小
+    const scaleX = props.iconWidth ? props.iconWidth / props.iconSize : 1
+    const scaleY = props.iconHeight ? props.iconHeight / props.iconSize : 1
+
+    if (scaleX !== 1 || scaleY !== 1) {
+        style.transform = `scale(${scaleX}, ${scaleY})`
+    }
+
+    return style
+})
+
+// 罐型图标
+const tankIconClass = computed(() => {
+    console.log('3getFanStatus', props.fanStatus, typeof props.fanStatus)
+    return props.waterLevelValue >= 0 || props.fanStatus ? 'icon-hnyz-colourfloorTank_hollowedOut' : 'icon-hnyz-colourfloorTank'
+});
+
+// 仅传 waterLevelValue,内部组装 config
+const waterLevelConfig = computed(() => ({
+    data: [props.waterLevelValue],
+    waveHeight: 5,// 波浪高度
+}))
+
+//ph值
+const phValue = computed({
+    get() {
+        return props.phValue
+    },
+})
+//风扇状态
+const getFanStatus = computed(() => {
+    console.log('getFanStatus', props.fanStatus, typeof props.fanStatus)
+    return props.fanStatus
+})
+
+</script>
+
+<style scoped lang="scss">
+//水位罐
+.tank_body {
+    text-align: center;
+    position: relative;
+
+    .tank {
+        position: relative;
+        z-index: 10;
+
+        //罐子名称
+        .tank_title {
+            position: absolute;
+            top: 75%;
+            left: 49%;
+            transform: translate(-50%, -50%);
+            color: #e65100;
+            font-weight: bold;
+        }
+
+        // 水位
+        .water_level {
+            width: 0.4em;
+            height: 0.5em;
+        }
+
+        //水位图位置
+        .water_level_pos3 {
+            position: absolute;
+            top: 18%;
+            left: 30%;
+        }
+
+        .dv-water-pond-level :deep(canvas) {
+            position: absolute;
+            left: 0%;
+        }
+
+        .dv-water-pond-level :deep(rect) {
+            // fill:unset;//去掉默认的颜色
+            width: 99%;
+            height: 99%;
+            stroke-width: 0 !important;
+        }
+
+
+    }
+
+    .ph_pos {
+        position: absolute;
+        top: 22%;
+        left: 60%;
+        z-index: 100;
+    }
+
+    .mixer_machine {
+        position: absolute;
+        top: 37%;
+        left: 50%;
+        transform: translate(-50%, -50%);
+
+        .icon-fengshan {
+            color: aliceblue;
+            font-size: 50px;
+            display: inline-block;
+        }
+
+        //旋转动画
+        @keyframes rotate-clockwise {
+            from {
+                transform: rotate(0deg);
+            }
+
+            to {
+                transform: rotate(360deg);
+            }
+        }
+
+        .fan_run {
+            animation: rotate-clockwise 1s linear infinite;
+        }
+    }
+
+}
+</style>

+ 209 - 0
ui/src/components/HnyzDcs/VTypeTankValves2Component.vue

@@ -0,0 +1,209 @@
+<template>
+    <div class="tank_valves" :style="getTankBodyStyle">
+        <VTypeTank :title="title" :waterLevelValue="waterLevelValue" :iconWidth="iconWidth" :iconHeight="iconHeight"
+            :iconSize="iconSize" :phValue="phValue" :fanStatus="fanStatus"></VTypeTank>
+        <div class="valve_progress">
+
+            <div :style="valveProgressStyle" class="valve_progress1 rotate_270" v-if="valveNames[0]">
+                <ValveProgress :iconSize="valveIconSize" :title="valveNames[0]" :rotateAngle="270" :pipeLength="247"
+                    :pipeLeftOffset="-60" :valveStatusArr="initValveStatusArr" progressType="steam" :pipeReverse="true"
+                    :pipeStatus="initPipeStatus" />
+            </div>
+            <div :style="valveProgressStyle" class="valve_progress2" v-if="valveNames[1]">
+                <ValveProgress :iconSize="valveIconSize" :title="valveNames[1]" :pipeLength="200" :pipeLeftOffset="-60"
+                    :valveStatusArr="initValveStatusArr" progressType="steam" :pipeStatus="initPipeStatus" />
+            </div>
+        </div>
+        <div class="pump_progress">
+            <div :style="[pumpProgressStyle, { left: props.iconWidth === 300 ? '124%' : '144%' }]"
+                class="pump_progress1" v-if="pumpNames[0]">
+                <Pump :title="pumpNames[0]" :pumpDataArr="[1, 10]" :iconSize="80" :showPipe="true" />
+            </div>
+            <div :style="[pumpProgressStyle, { left: props.topPumpDir === 'L' ? '9%' : '108%' }]" class="pump_progress2"
+                v-if="pumpNames[1]">
+                <Pump :title="pumpNames[0]" :pumpDataArr="[1, 10]" :iconSize="80" :pumpDirection="topPumpDir"
+                    :showPipe="true" />
+            </div>
+        </div>
+        <div class="pipes" v-if="pumpNames[1]">
+            <Pipe :pipeStatus="initPipeStatus" class="progress_steam" :class="getPipeClass"></Pipe>
+        </div>
+    </div>
+</template>
+
+<script setup>
+import VTypeTank from '@/components/HnyzDcs/VTypeTank2Component.vue';
+import ValveProgress from '@/components/DCS/ValveProgressComponent.vue';
+import PumpProgress from '@/components/HnyzDcs/PumpProgressComponent.vue';
+import Pipe from '@/components/HnyzDcs/PipeComponent.vue';
+import Pump from '@/components/DCS/PumpComponent.vue';
+import { computed } from 'vue'
+import { get } from '@vueuse/core';
+const initValveStatusArr = [true]
+const initPipeStatus = true
+const props = defineProps({
+    phValue: {//ph
+        type: Number,
+        default: null
+    },
+    waterLevelValue: {// 水位值
+        type: Number,
+        default: -1,// -1表示未传水位值
+    },
+    fanStatus: {//风扇状态
+        type: Boolean,
+        default: false,
+    },
+    iconSize: {//图标大小
+        type: Number,
+        default: 200,
+    },
+    title: {//罐名
+        type: String,
+    },
+    iconWidth: {//图标宽度
+        type: Number,
+    },
+    iconHeight: {//图标高度
+        type: Number,
+    },
+    //上方泵的位置
+    topPumpDir: {
+        type: String,
+        default: 'L',
+    },
+})
+
+//默认阀门名称数组
+const defaultValveNames = new Array(2).fill('ACV_default')
+//泵默认名称
+const defaultPumpNames = new Array(1).fill('P_default')
+
+// 阀门名称映射表
+const valveNameArr = {
+    'V7002': ['', 'ACV2031'],
+    'V7004': ['ACV2024', 'ACV2025'],
+    'V7003': ['ACV2041', 'ACV2042'],
+}
+//泵名称映射表
+const pumpNameArr = {
+    'V7002': ['P2007', ''],
+    'V7004': ['P2006', 'P2024'],
+    'V7003': ['P2011', 'P2010'],
+}
+
+//阀门名称数组,根据罐名来匹配
+const valveNames = computed(() => {
+    return valveNameArr[props.title] || defaultValveNames
+})
+//泵名称
+const pumpNames = computed(() => {
+    return pumpNameArr[props.title] || defaultPumpNames
+})
+
+
+
+//罐体样式
+const getTankBodyStyle = computed(() => ({
+    width: `${props.iconWidth ?? props.iconSize}px`,
+    height: `${props.iconHeight ?? props.iconSize}px`,
+}))
+
+//ph值
+const phValue = computed({
+    get() {
+        return props.phValue
+    },
+})
+
+//阀门icon大小(罐子200-阀门50)
+const valveIconSize = computed(() => {
+    return props.iconSize * 0.25;
+});
+
+//阀门进度样式
+const valveProgressStyle = computed(() => {
+    return {
+        width: `${valveIconSize.value}px`,
+        height: `${valveIconSize.value}px`,
+    }
+});
+
+//泵icon大小(罐子200-泵80)
+const pumpIconSize = computed(() => {
+    return props.iconSize * 0.4;
+});
+
+//泵进度样式
+const pumpProgressStyle = computed(() => {
+    return {
+        width: `${pumpIconSize.value}px`,
+        height: `${pumpIconSize.value}px`,
+    }
+});
+
+//管道class
+const getPipeClass = computed(() => {
+    const baseClass = 'progress_pos1_' + props.topPumpDir;
+    const rotateClass = props.topPumpDir === 'R' ? 'rotate_180' : '';
+    return [baseClass, rotateClass];
+});
+
+</script>
+
+<style scoped lang="scss">
+.tank_valves {
+    position: relative;
+    z-index: 10;
+
+    .valve_progress {
+
+
+        .valve_progress1 {
+            position: absolute;
+            top: -18%;
+            left: 48%;
+        }
+
+        .valve_progress2 {
+            position: absolute;
+            top: 62%;
+            left: 90%;
+        }
+    }
+
+    .pump_progress {
+        .pump_progress1 {
+            position: absolute;
+            top: 77%;
+            left: 116%;
+            transform: translate(-50%, -50%);
+            z-index: 100;
+        }
+
+        .pump_progress2 {
+            position: absolute;
+            top: -15%;
+            left: 12%;
+            transform: translate(-50%, -50%);
+            z-index: 100;
+        }
+    }
+
+    .pipes {
+        .progress_pos1_L {
+            width: 46%;
+            position: absolute;
+            top: -53%;
+            left: 6%;
+        }
+
+        .progress_pos1_R {
+            width: 88%;
+            position: absolute;
+            top: -52.5%;
+            left: 50.3%;
+        }
+    }
+}
+</style>

+ 200 - 0
ui/src/components/HnyzDcs/VTypeTankValvesComponent.vue

@@ -0,0 +1,200 @@
+<template>
+    <div class="tank_valves" :style="getTankBodyStyle">
+        <!-- 落地罐 -->
+        <VTypeTank :title="title" :waterLevelValue="waterLevelValue" :iconWidth="iconWidth" :iconHeight="iconHeight"
+            :iconSize="iconSize" :phValue="phValue" :fanStatus="fanStatus"></VTypeTank>
+        <div class="valve_progress">
+            <!-- 上右 -->
+            <div :style="valveProgressStyle" class="valve_progress1 rotate_270" v-if="valveNames[0]">
+                <ValveProgress :iconSize="valveIconSize" :title="valveNames[0]" :rotateAngle="270" :pipeLength="205"
+                    :pipeLeftOffset="-47" :valveStatusArr="initValveStatusArr" progressType="steam"
+                    :pipeStatus="initPipeStatus" :pipeReverse="true" />
+            </div>
+            <!-- 左 -->
+            <div :style="valveProgressStyle" class="valve_progress2" v-if="valveNames[1]">
+                <ValveProgress :iconSize="valveIconSize" :title="valveNames[1]" :pipeLength="200" :pipeLeftOffset="-60"
+                    :valveStatusArr="initValveStatusArr" progressType="steam" :pipeStatus="initPipeStatus" />
+            </div>
+            <!-- 右 -->
+            <div :style="valveProgressStyle" class="valve_progress3" v-if="valveNames[2]">
+                <ValveProgress :iconSize="valveIconSize" :title="valveNames[2]" :pipeLength="185" :pipeLeftOffset="-45"
+                    :valveStatusArr="initValveStatusArr" progressType="steam" :pipeStatus="initPipeStatus" />
+            </div>
+            <!-- 下 -->
+            <div :style="valveProgressStyle" class="valve_progress4 rotate_270" v-if="valveNames[3]">
+                <ValveProgress :iconSize="valveIconSize" :title="valveNames[3]" :pipeLength="200" :pipeLeftOffset="-40"
+                    :valveStatusArr="initValveStatusArr" progressType="steam" :pipeStatus="initPipeStatus"
+                    :rotateAngle="270" :pipeReverse="true" />
+            </div>
+        </div>
+        <div class="pump_progress">
+            <!-- 右  -->
+            <PumpProgress :title="pumpNames[0]" :pumpDataArr="[1, 10]" :iconSize="iconSize * 0.4" :showPipe="true"
+                :pipeType="steam" class="pump_progress1" v-if="pumpNames[0]" />
+        </div>
+    </div>
+</template>
+
+<script setup>
+import VTypeTank from '@/components/HnyzDcs/VTypeTankComponent.vue';
+import ValveProgress from '@/components/DCS/ValveProgressComponent.vue';
+import PumpProgress from '@/components/DCS/PumpComponent.vue';
+import { computed } from 'vue'
+const initValveStatusArr = [true]
+const initPipeStatus = true
+const props = defineProps({
+    phValue: {//ph
+        type: Number,
+        default: null
+    },
+    waterLevelValue: {// 水位值
+        type: Number,
+        default: -1,// -1表示未传水位值
+    },
+    fanStatus: {//风扇状态
+        type: Boolean,
+        default: undefined,// undefined表示未传风扇状态,如果不写它会默认false
+    },
+    iconSize: {//图标大小
+        type: Number,
+        default: 200,
+    },
+    title: {//罐名
+        type: String,
+    },
+    iconWidth: {//图标宽度
+        type: Number,
+    },
+    iconHeight: {//图标高度
+        type: Number,
+    },
+})
+//默认阀门名称数组
+const defaultValveNames = new Array(4).fill('ACV_default')
+//泵默认名称
+const defaultPumpNames = new Array(1).fill('P_default')
+
+// 阀门名称映射表
+const valveNameArr = {
+    'V5001': ['', '', 'ACV5001', ''],
+    'V2002': ['ACV2011', 'ACV2009', 'ACV2012', ''],
+    'V2001': ['ACV2023', '', '', 'ACV2010'],
+    'V2003': ['ACV2020', '', 'ACV2022', ''],
+    'V2004': ['', 'ACV2054', 'ACV2038', ''],
+    'V2007': ['ACV2028', 'ACV2021', '', 'ACV2036'],
+    'V2009': ['', '', 'ACV2035', ''],
+    'V2014': ['', '', 'ACV2055', ''],
+    'V2006': ['', '', 'ACV2061', ''],
+    'V2008': ['ACV2072', '', 'ACV2070', ''],
+    'V2010': ['ACV2073', 'ACV2071', 'ACV2074', ''],
+    'V2011':['ACV2078','','',''],
+    'V2012':['','','ACV2082',''],
+    'V2013':['ACV2079','','ACV2077',''],
+    'S2008':['ACV2076','','',''],
+    'V2017':['','','ACV2086',''],
+    'V2015':['','','ACV2084',''],
+}
+//泵名称映射表
+const pumpNameArr = {
+    'V5001': ['P5001'],
+    'V2002': ['P2003'],
+    'V2001': [''],
+    'V2003': ['P2004'],
+    'V2004': ['P2009'],
+    'V2007': [''],
+    'V2009': ['P2008'],
+    'V2014': ['P2014'],
+    'V2006': ['P2022'],
+    'V2008': ['P2017'],
+    'V2010': ['P2018'],
+    'V2011': [''],
+    'V2012': ['P2019'],
+    'V2013': ['P2020'],
+    'S2008': [''],
+    'V2017': ['P2023'],
+    'V2015': ['P2021'],
+}
+
+//阀门名称数组,根据罐名来匹配
+const valveNames = computed(() => {
+    return valveNameArr[props.title] || defaultValveNames
+})
+//泵名称
+const pumpNames = computed(() => {
+    return pumpNameArr[props.title] || defaultPumpNames
+})
+
+
+//罐体样式
+const getTankBodyStyle = computed(() => ({
+    width: `${props.iconWidth ?? props.iconSize}px`,
+    height: `${props.iconHeight ?? props.iconSize}px`,
+    // fontSize: `${props.iconSize}px`,
+}))
+
+//ph值
+const phValue = computed({
+    get() {
+        return props.phValue
+    },
+})
+
+//阀门icon大小(罐子200-阀门50)
+const valveIconSize = computed(() => {
+    console.log('getFanStatus', props.fanStatus, typeof props.fanStatus)
+
+    return props.iconSize * 0.25;
+});
+
+//阀门进度样式
+const valveProgressStyle = computed(() => {
+    return {
+        width: `${valveIconSize.value}px`,
+        height: `${valveIconSize.value}px`,
+    }
+});
+
+</script>
+
+<style scoped lang="scss">
+.tank_valves {
+    position: relative;
+    z-index: 10;
+
+    .valve_progress {
+        .valve_progress1 {
+            position: absolute;
+            top: -15%;
+            left: 65%;
+        }
+
+        .valve_progress2 {
+            position: absolute;
+            top: 10%;
+            left: -6%;
+        }
+
+        .valve_progress3 {
+            position: absolute;
+            top: 62%;
+            left: 82%;
+        }
+
+        .valve_progress4 {
+            position: absolute;
+            top: 115%;
+            left: 45%;
+        }
+    }
+
+    .pump_progress {
+        .pump_progress1 {
+            position: absolute;
+            top: 77%;
+            left: 134%;
+            transform: translate(-50%, -50%);
+            z-index: 100;
+        }
+    }
+}
+</style>

+ 143 - 0
ui/src/components/HnyzDcs/WaterSinkComponent.vue

@@ -0,0 +1,143 @@
+<template>
+    <div class="water_sink" :style="{
+        width: `${slotWidth}px`,
+        height: `${slotHeight}px`,
+    }">
+        <!-- 水槽  -->
+        <div class="u_slot">
+            <div class="u_slot_side u_slot_left" :style="sideStyle"></div>
+            <div class="u_slot_bottom" :style="bottomStyle"></div>
+            <div class="u_slot_side u_slot_right" :style="sideStyle"></div>
+        </div>
+
+        <!-- 水位 -->
+        <dv-water-level-pond :config="waterLevelConfig" class="water_level water_level_pos3"
+            v-if="waterLevelValue > 0" :style="getWaterLevelStyle"/>
+        <!-- temp值组件 -->
+        <TempSlider :tempValue="tempValue" :sliderHeighth="slotHeight * 0.8" :sliderWidth="slotWidth * 0.08"
+            class="temp_pos" v-if="tempValue" />
+        <div class="title_pos" :style="{ fontSize: `${bottomHeight}px` }">
+            {{ props.title }}
+        </div>
+    </div>
+</template>
+
+<script setup>
+import TempSlider from '@/components/HnyzDcs/TempSliderComponent.vue'
+
+import { computed } from 'vue'
+
+const props = defineProps({
+    title: {
+        type: String,
+    },
+    iconSize: {
+        type: Number,
+    },
+    width: {
+        type: Number,
+    },
+    height: {
+        type: Number,
+    },
+    waterLevelValue: {
+        type: Number,
+    },
+    tempValue: {
+        type: Number,
+    },
+})
+
+// 尺寸逻辑
+const slotWidth = computed(() => props.width ?? props.iconSize ?? 100)
+const slotHeight = computed(() => props.height ?? props.iconSize ?? 60)
+
+// 水槽边的宽度(按比例)
+const sideThickness = computed(() => Math.max(4, Math.round(slotWidth.value * 0.15)))
+const bottomHeight = computed(() => Math.max(4, Math.round(slotHeight.value * 0.2)))
+
+// 左右竖边的样式
+const sideStyle = computed(() => ({
+    width: `${sideThickness.value}px`,
+    height: `${slotHeight.value}px`,
+    backgroundColor: '#666',
+}))
+// 底部横边的样式
+const bottomStyle = computed(() => ({
+    height: `${bottomHeight.value}px`,
+    width: `${slotWidth.value - sideThickness.value * 2}px`,
+    backgroundColor: '#666',
+}))
+
+// 仅传 waterLevelValue,内部组装 config
+const waterLevelConfig = computed(() => ({
+    data: [props.waterLevelValue],
+    waveHeight: 3,// 波浪高度
+}))
+
+//水位表样式
+const getWaterLevelStyle = computed(() => ({
+    '--water_level_text_size': `${slotWidth.value * 0.2}px`,
+}))
+
+</script>
+
+<style scoped lang="scss">
+.water_sink {
+    position: relative;
+
+    .u_slot {
+        display: flex;
+        justify-content: space-between;
+        align-items: flex-end;
+        position: relative;
+
+        /* 左右竖边 */
+        .u_slot_side {
+            z-index: 10;
+            background-color: #666;
+        }
+
+        /* 底部横边 */
+        .u_slot_bottom {
+            z-index: 10;
+            position: absolute;
+            bottom: 0;
+            left: 50%;
+            transform: translateX(-50%);
+        }
+    }
+
+    .water_level {
+        width: 100%;
+        height: 90%;
+    }
+
+    :deep(.dv-water-pond-level text){
+        font-size: var(--water_level_text_size, 20px)
+    }
+
+    .water_level_pos3 {
+        position: absolute;
+        top: 0%;
+        left: 0%;
+    }
+
+    .temp_pos {
+        position: absolute;
+        top: 4%;
+        right: -14%;
+        z-index: 100;
+    }
+
+    .title_pos {
+        position: absolute;
+        top: 90%;
+        left: 50%;
+        z-index: 100;
+        font-size: 14px;
+        transform: translate(-50%, -50%);
+        color: #fff;
+    }
+}
+</style>

+ 158 - 0
ui/src/components/HnyzDcs/WaterSinkValvesComponent.vue

@@ -0,0 +1,158 @@
+<template>
+    <div class="tank_valves" :style="getTankBodyStyle">
+        <!-- 水槽  -->
+        <WaterSinkComponent :title="title" :width="width" :height="height" :waterLevelValue="80" :tempValue="50" />
+        <div class="valve_progress">
+            <ValveProgress :iconSize="valveIconSize" :title="valveNames[0]" :rotateAngle="90" :pipeLength="440"
+                :pipeLeftOffset="-300" :valveStatusArr="initValveStatusArr" progressType="steam"
+                :pipeStatus="initPipeStatus" class="valve_progress1 rotate_90" />
+            <ValveProgress :iconSize="valveIconSize" :title="valveNames[1]" :rotateAngle="90" :pipeLength="440"
+                :pipeLeftOffset="-220" :valveStatusArr="initValveStatusArr" progressType="steam"
+                :pipeStatus="initPipeStatus" class="valve_progress2 rotate_90" />
+            <ValveProgress :iconSize="valveIconSize" :title="valveNames[2]" :rotateAngle="90" :pipeLength="440"
+                :pipeLeftOffset="-140" :valveStatusArr="initValveStatusArr" progressType="steam"
+                :pipeStatus="initPipeStatus" class="valve_progress3 rotate_90" />
+            <ValveProgress :iconSize="valveIconSize" :title="valveNames[3]" :rotateAngle="90" :pipeLength="440"
+                :pipeLeftOffset="-60" :valveStatusArr="initValveStatusArr" progressType="steam"
+                :pipeStatus="initPipeStatus" class="valve_progress4 rotate_90" />
+        </div>
+        <div class="pump_progress">
+            <Pump :title="pumpNames[0]" :pumpDataArr="[1, 10]" :iconSize="pumpIconSize" :showPipe="true"
+                :pipeType="steam" class="pump_progress1" />
+        </div>
+        <div class="pipes" v-if="pumpNames[0]">
+            <!-- 右下泵管道 -->
+            <Pipe :pipeStatus="initPipeStatus" :strokeWidth="width * 0.048" class="progress_steam progress_pos1"></Pipe>
+        </div>
+    </div>
+</template>
+
+<script setup>
+import WaterSinkComponent from '@/components/HnyzDcs/WaterSinkComponent.vue';
+import ValveProgress from '@/components/DCS/ValveProgressComponent.vue';
+import Pipe from '@/components/HnyzDcs/PipeComponent.vue';
+import Pump from '@/components/DCS/PumpComponent.vue';
+import { computed } from 'vue'
+const initValveStatusArr = [true]
+const initPipeStatus = true
+const props = defineProps({
+    iconSize: {
+        type: Number,
+    },
+    iconWidth: {//图标宽度
+        type: Number,
+    },
+    iconHeight: {//图标高度
+        type: Number,
+    },
+    tempValue: {
+        type: Number,
+    },
+    waterLevelValue: {// 水位值
+        type: Number,
+        default: -1,// -1表示未传水位值
+    },
+    title: {//罐名
+        type: String,
+    },
+})
+
+//默认阀门名称数组
+const defaultValveNames = new Array(2).fill('ACV_default')
+//泵默认名称
+const defaultPumpNames = new Array(1).fill('P_default')
+
+// 阀门名称映射表
+const valveNameArr = {
+    'V6101': ['ACV6007A', 'ACV6007B', 'ACV6008A', 'ACV6008B'],
+}
+//泵名称映射表
+const pumpNameArr = {
+    'V6101': ['P6004'],
+}
+
+//阀门名称数组,根据罐名来匹配
+const valveNames = computed(() => {
+    return valveNameArr[props.title] || defaultValveNames
+})
+//泵名称
+const pumpNames = computed(() => {
+    return pumpNameArr[props.title] || defaultPumpNames
+})
+
+const width = computed(() => {
+    return props.iconWidth ?? props.iconSize
+})
+const height = computed(() => {
+    return props.iconHeight ?? props.iconSize
+})
+
+//罐体样式
+const getTankBodyStyle = computed(() => ({
+    width: `${width.value}px`,
+    height: `${height.value}px`,
+}))
+
+//阀门icon大小(水槽100*80-阀门30)
+const valveIconSize = computed(() => {
+    return width.value * 0.3;
+});
+
+//泵icon大小(水槽100*80-泵48)
+const pumpIconSize = computed(() => {
+    return width.value * 0.48;
+});
+
+</script>
+
+<style scoped lang="scss">
+.tank_valves {
+    position: relative;
+    z-index: 10;
+
+    .valve_progress {
+        .valve_progress1 {
+            position: absolute;
+            top: -30%;
+            left: 13%;
+        }
+
+        .valve_progress2 {
+            position: absolute;
+            top: -60%;
+            left: 41%;
+        }
+
+        .valve_progress3 {
+            position: absolute;
+            top: -90%;
+            left: 69%;
+        }
+
+        .valve_progress4 {
+            position: absolute;
+            top: -120%;
+            left: 97%;
+        }
+    }
+
+    .pump_progress {
+
+        .pump_progress1 {
+            position: absolute;
+            top: 93%;
+            left: 146%;
+            transform: translate(-50%, -50%);
+        }
+    }
+
+    .pipes {
+        .progress_pos1 {
+            width: 46%;
+            position: absolute;
+            top: 92%;
+            left: 90%;
+        }
+    }
+}
+</style>