Browse Source

refactor(components):控制页面组件更新

HMY 8 months ago
parent
commit
3aa616b709

+ 234 - 120
ui/src/components/GeneralComponents/control/PumpControl2Component.vue

@@ -2,35 +2,43 @@
     <div class="flow_single flow_others">
         <div class="flow_single_title">{{ title }}</div>
         <div class="flow_single_show">
-            <!-- 状态 -->
+            <!-- 状态区域(方形指示灯) -->
             <div class="show_body">
                 <div class="show_body_left">状态</div>
                 <div class="show_body_right">
-                    <div class="show_detail">
-                        <div class="status_buttons">
-                            <el-button size="small" :type="pumpStatus === 'start' ? 'success' : 'default'"
-                                :disabled="!pumpSetArr.length" @click="setPump(pumpSetArr[0], true)">
-                                启动
-                            </el-button>
-
-                            <el-button size="small" :type="pumpStatus === 'stop' ? 'danger' : 'default'"
-                                :disabled="!pumpSetArr.length" @click="setPump(pumpSetArr[0], false)">
-                                停止
-                            </el-button>
-
-                            <el-button size="small" :type="pumpStatus === 'fault' ? 'warning' : 'default'" disabled>
-                                故障
-                            </el-button>
-                        </div>
+                    <div class="show_detail status_indicator_container">
+                        <!-- 绿色方形灯(启动) -->
+                        <div class="indicator square green" :class="{ active: pumpStatus === 'start' }"></div>
+                        <!-- 红色方形灯(停止) -->
+                        <div class="indicator square red" :class="{ active: pumpStatus === 'stop' }"></div>
+                        <!-- 黄色方形灯(故障) -->
+                        <div class="indicator square yellow" :class="{ active: pumpStatus === 'fault' }"></div>
                     </div>
                 </div>
             </div>
 
-            <!-- 转速 -->
-            <div class="show_body" v-if="pumpDataArr.length > 1">
-                <div class="show_body_left">转速</div>
+            <!-- 独立操作行 -->
+            <div class="show_body operation_row">
+                <div class="show_body_left">操作</div>
                 <div class="show_body_right">
-                    <div class="show_detail">
+                    <div class="show_detail operation_buttons">
+                        <el-button size="small" type="success" :disabled="!pumpSetArr.length || pumpStatus === 'start'"
+                            @click="setPump(pumpSetArr[0], true)">
+                            启动
+                        </el-button>
+                        <el-button size="small" type="danger" :disabled="!pumpSetArr.length || pumpStatus === 'stop'"
+                            @click="setPump(pumpSetArr[0], false)">
+                            停止
+                        </el-button>
+                    </div>
+                </div>
+            </div>
+
+            <!-- 转速(优化布局) -->
+            <div class="show_body speed_section" v-if="pumpDataArr.length > 1">
+                <div class="show_body_left">转速</div>
+                <div class="show_body_right speed_container">
+                    <div class="speed_item">
                         <div class="text">实时值</div>
                         <div class="body_show">
                             <div class="body_show_value">
@@ -39,29 +47,30 @@
                             <div class="body_show_unit">{{ pumpSetArr[1]?.unitType || '%' }}</div>
                         </div>
                     </div>
-                    <div class="show_detail">
+                    <div class="speed_item">
                         <div class="text">设定值</div>
-                        <div class="body_show_value">
-                            <el-input v-model="speedValue" style="width: 75px" size="small" type="number" :min="0"
-                                :max="100" placeholder="" @blur="onSpeedInputBlur" />
+                        <div class="body_show">
+                            <!-- 使用原生input并自定义样式 -->
+                            <input v-model="speedValue" type="number" :min="0" :max="100" class="custom-input"
+                                @blur="onSpeedInputBlur" placeholder="输入值">
+                            <div class="body_show_unit">{{ pumpSetArr[1]?.unitType || '%' }}</div>
                         </div>
-                        <div class="body_show_unit">{{ pumpSetArr[1]?.unitType || '%' }}</div>
                     </div>
                 </div>
             </div>
 
-            <!-- 进料量 -->
-            <div class="show_body" v-if="pumpDataArr.length > 2">
+            <!-- 进料量(与实时值样式统一) -->
+            <div class="show_body speed_section" v-if="pumpDataArr.length > 2">
                 <div class="show_body_left">进料</div>
-                <div class="show_body_right">
-                    <div class="show_detail">
+                <div class="show_body_right speed_container">
+                    <div class="speed_item">
                         <div class="text">进料量</div>
                         <div class="body_show">
                             <div class="body_show_value">
                                 {{ (pumpDataArr[2]) || 0 }}
                             </div>
+                            <div class="body_show_unit">kg</div>
                         </div>
-                        <div class="body_show_unit">kg</div>
                     </div>
                 </div>
             </div>
@@ -114,9 +123,9 @@ const statusWord = ref(['', '正转', '反转', '停机', '故障'])
 
 const pumpStatus = computed(() => {
     const code = pumpDataArr.value[0];
-    if (code === 1 || code === 2) return 'start';
-    if (code === 3) return 'stop';
-    if (code === 4) return 'fault';
+    if (code === 1 || code === 2) return 'start';  // 启动状态
+    if (code === 3) return 'stop';                 // 停止状态
+    if (code === 4) return 'fault';                // 故障状态
     return 'stop';
 });
 
@@ -161,30 +170,28 @@ function onSpeedInputBlur() {
         openElWarnMessage('未获取到设定地址');
         return;
     }
-    setPumpVaule(pumpSetArr.value[1], speedValue.value * 50);
+    // 验证输入值范围
+    if (speedValue.value < 0) speedValue.value = 0;
+    if (speedValue.value > 100) speedValue.value = 100;
+    if (speedValue.value !== undefined && speedValue.value !== null) {
+        setPumpVaule(pumpSetArr.value[1], speedValue.value * 50);
+    }
 }
 </script>
 
 <style scoped lang="scss">
 .flow_single {
-    width: 100px;
     display: flex;
     padding: 6px;
     flex-direction: column;
-    align-items: center;
-    gap: 3px;
     border-radius: 5px;
     border: 1px solid #72E0FF;
     background: linear-gradient(to bottom, #0e1a2d, #11243e);
 
 
     .flow_single_title {
-        display: flex;
         padding: 4px 8px;
-        justify-content: center;
-        align-items: center;
-        gap: 10px;
-        align-self: stretch;
+        text-align: center;
         color: #76E1FF;
         font-size: 20px;
         font-weight: bold;
@@ -195,84 +202,10 @@ function onSpeedInputBlur() {
     .flow_single_show {
         display: flex;
         flex-direction: column;
-        align-items: center;
-        justify-content: center;
         color: #FFF;
-        // height: 100px;
-        gap: 3px;
-
-        .show_body {
-            display: flex;
-            align-items: center;
-            justify-content: space-between;
-
-            .show_body_left {
-                width: 50px;
-                text-align: center;
-                padding: 7px 0;
-                font-size: large;
-                background: #0e2b60;
-                border-radius: 5px;
-                color: #63c8c7;
-            }
-
-            .show_body_right {
-                gap: 5px;
-                width: 220px;
-                display: flex;
-                flex-direction: column;
-                align-items: center;
-                justify-content: center;
-                align-items: self-start;
-                margin-left: 20px;
-
-                .show_detail {
-                    display: flex;
-                    align-items: center;
-                    justify-content: center;
-                    gap: 8px;
-
-                    .text {
-                        text-align: center;
-                        font-size: small;
-                        width: 47px;
-                    }
-
-                    .body_show,
-                    .body_set {
-                        display: flex;
-                        align-items: center;
-                        gap: 5px;
-
-                        .body_show_value {
-                            text-align: center;
-                            width: 75px;
-                            font-size: small;
-                            border: solid 1px #B8CEE5;
-                            border-radius: 5px;
-
-
-                        }
-                    }
-
-                    :deep(.el-input__inner) {
-                        height: 18px;
-                        text-align: center;
-                    }
-
-                    .status_buttons {
-                        display: flex;
-                        align-items: center;
-                    }
-
-                    .status_buttons :deep(.el-button--small) {
-                        height: 24px !important;
-                        padding: 0 8px;
-                        min-width: 56px;
-                    }
-                }
-            }
-        }
+        gap: 8px;
+        padding-top: 5px;
+        width: 100%;
     }
 }
 
@@ -280,4 +213,185 @@ function onSpeedInputBlur() {
     width: 300px;
     margin: 10px;
 }
+
+.show_body {
+    display: flex;
+    align-items: center;
+    gap: 10px;
+    width: 100%;
+
+    .show_body_left {
+        margin: auto;
+        width: 50px;
+        text-align: center;
+        padding: 7px 0;
+        font-size: 14px;
+        background: #0e2b60;
+        border-radius: 5px;
+        color: #63c8c7;
+        flex-shrink: 0;
+        /* 固定宽度不收缩 */
+    }
+
+    .show_body_right {
+        flex-grow: 1;
+        /* 占满剩余宽度 */
+        display: flex;
+        align-items: center;
+        margin: 0;
+    }
+
+    .show_detail {
+        display: flex;
+        align-items: center;
+        width: 100%;
+    }
+}
+
+/* 状态指示灯样式 */
+.status_indicator_container {
+    justify-content: space-around;
+    padding: 5px 0;
+    width: 100%;
+}
+
+.indicator {
+    width: 24px;
+    height: 24px;
+    opacity: 0.3;
+    transition: all 0.3s ease;
+    border: 2px solid rgba(255, 255, 255, 0.3);
+    flex: 1;
+    max-width: 30px;
+}
+
+.indicator.square {
+    border-radius: 3px;
+}
+
+.indicator.active {
+    opacity: 1;
+    box-shadow: 0 0 8px 1px currentColor;
+}
+
+.green {
+    background-color: #4cd964;
+    color: #4cd964;
+}
+
+.yellow {
+    background-color: #ffcc00;
+    color: #ffcc00;
+}
+
+.red {
+    background-color: #ff3b30;
+    color: #ff3b30;
+}
+
+/* 操作按钮区域样式 */
+.operation_buttons {
+    justify-content: space-around;
+    width: 100%;
+    gap: 10px;
+    padding: 5px 0;
+}
+
+.operation_buttons :deep(.el-button) {
+    flex: 1;
+    max-width: 100px;
+}
+
+.operation_row {
+    margin-top: 5px;
+}
+
+/* 转速和进料量共用样式 */
+.speed_section {
+    align-items: flex-start;
+    padding: 5px 0;
+}
+
+.speed_container {
+    flex-direction: column;
+    align-items: stretch;
+    gap: 6px;
+    width: 100%;
+}
+
+.speed_item {
+    display: flex;
+    align-items: center;
+    width: 100%;
+    gap: 12px;
+}
+
+.speed_item .text {
+    text-align: right;
+    font-size: 13px;
+    min-width: 55px;
+    color: #b8cee5;
+}
+
+.speed_item .body_show {
+    display: flex;
+    align-items: center;
+    gap: 8px;
+    flex-grow: 1;
+}
+
+.speed_item .body_show_value {
+    text-align: center;
+    flex-grow: 1;
+    font-size: 14px;
+    border: solid 1px #B8CEE5;
+    border-radius: 5px;
+    padding: 2px 8px;
+    min-height: 24px;
+    line-height: 24px;
+}
+
+/* 自定义输入框样式 */
+.custom-input {
+    flex-grow: 1;
+    height: 24px;
+    padding: 0 8px;
+    font-size: 14px;
+    color: #fff;
+    background-color: rgba(15, 36, 62, 0.5);
+    border: 1px solid #B8CEE5;
+    border-radius: 5px;
+    text-align: center;
+    outline: none;
+    box-sizing: border-box;
+    transition: all 0.2s ease;
+}
+
+.custom-input:focus {
+    border-color: #72E0FF;
+    box-shadow: 0 0 0 2px rgba(114, 224, 255, 0.2);
+}
+
+.custom-input::placeholder {
+    color: #88a0b8;
+    font-size: 12px;
+}
+
+/* 移除数字输入框的默认箭头 */
+.custom-input::-webkit-outer-spin-button,
+.custom-input::-webkit-inner-spin-button {
+    -webkit-appearance: none;
+    margin: 0;
+}
+
+.custom-input[type=number] {
+    -moz-appearance: textfield;
+}
+
+.body_show_unit {
+    font-size: 13px;
+    color: #b8cee5;
+    white-space: nowrap;
+}
 </style>
+    

+ 83 - 33
ui/src/components/GeneralComponents/control/ValveControl2Component.vue

@@ -4,23 +4,30 @@
         <div class="flow_single_title">
             {{ formatTitle(title) }}
         </div>
-        <div class="flow_status_row">
+
+        <!-- 状态指示灯区域 -->
+        <div class="status_indicator_area">
             <div class="status_label">状态</div>
-            <div class="status_buttons">
-                <!-- 绿色按钮(打开) -->
-                <el-button :type="valveStatus === 'open' ? 'success' : 'default'" size="small" @click="setValve(true)">
+            <div class="status_indicators">
+                <!-- 绿色灯(打开) -->
+                <div class="indicator green" :class="{ active: valveStatus === 'open' }"></div>
+                <!-- 红色灯(关闭) -->
+                <div class="indicator red" :class="{ active: valveStatus === 'close' }"></div>
+                <!-- 黄色灯(过渡/异常) -->
+                <div class="indicator yellow" :class="{ active: valveStatus === 'transition' }"></div>
+            </div>
+        </div>
+
+        <!-- 操作按钮区域 -->
+        <div class="operation_area">
+            <div class="operation_label">操作</div>
+            <div class="operation_buttons">
+                <el-button type="success" size="small" @click="setValve(true)" :disabled="valveStatus === 'open'">
                 </el-button>
-
-                <!-- 红色按钮(关闭) -->
-                <el-button :type="valveStatus === 'close' ? 'danger' : 'default'" size="small" @click="setValve(false)">
+                <el-button type="danger" size="small" @click="setValve(false)" :disabled="valveStatus === 'close'">
                 </el-button>
-
-                <!-- 黄色按钮(过渡/异常) -->
-                <el-button :type="valveStatus === 'transition' ? 'warning' : 'default'" size="small" disabled>
-                    渡
-                </el-button>
             </div>
         </div>
     </div>
@@ -40,20 +47,20 @@ const props = defineProps({
 // 处理标题显示逻辑的方法
 const formatTitle = (title) => {
     if (!title) return '';
-    
+
     // 分割标题为前缀和后缀
     const [prefix, suffix] = title.split('-');
-    
+
     // 如果没有分隔符,直接添加"阀门"前缀
     if (suffix === undefined) {
         return `阀门${title}`;
     }
-    
+
     // 如果前缀是null或空,使用"阀门-后缀"
     if (prefix === 'null' || !prefix.trim()) {
         return `阀门-${suffix}`;
     }
-    
+
     // 其他情况保持原标题
     return title;
 }
@@ -114,25 +121,68 @@ function setValve(open) {
         background: #192846;
     }
 
-    .flow_status_row {
+    .status_indicator_area,
+    .operation_area {
         display: flex;
         align-items: center;
-        margin-top: 8px;
-
-        .status_label {
-            font-size: 14px;
-            margin-right: 8px;
-            width: 50px;
-            text-align: center;
-            padding: 5px 0;
-            background: #0e2b60;
-            border-radius: 5px;
-            color: #63c8c7;
-        }
-
-        .status_buttons {
-            display: flex;
-        }
+        margin-top: 12px;
+        padding: 0 4px;
+    }
+
+    .status_label,
+    .operation_label {
+        font-size: 14px;
+        margin-right: 8px;
+        width: 50px;
+        text-align: center;
+        padding: 5px 0;
+        background: #0e2b60;
+        border-radius: 5px;
+        color: #63c8c7;
+    }
+
+    .status_indicators {
+        display: flex;
+        gap: 12px;
+        padding: 8px 0;
+        flex: 1;
+        justify-content: center;
+    }
+
+    .indicator {
+        width: 24px;
+        height: 24px;
+        border-radius: 50%;
+        opacity: 0.3;
+        transition: all 0.3s ease;
+        border: 2px solid rgba(255, 255, 255, 0.3);
+    }
+
+    .indicator.active {
+        opacity: 1;
+        box-shadow: 0 0 10px 2px currentColor;
+    }
+
+    .green {
+        background-color: #4cd964;
+        color: #4cd964;
+    }
+
+    .yellow {
+        background-color: #ffcc00;
+        color: #ffcc00;
+    }
+
+    .red {
+        background-color: #ff3b30;
+        color: #ff3b30;
+    }
+
+    .operation_buttons {
+        display: flex;
+        gap: 8px;
+        flex: 1;
+        justify-content: center;
     }
 }
 </style>