浏览代码

优化 CrossingDetailPanel 步进模式交互与多屏适配

  步进模式交互:
  - 切换到步进时不再自动弹出锁定时间面板,改为点击阶段时才显示
  - 步进模式下隐藏底部取消/确认按钮,改在锁定时间面板内提供
  - 步进模式下不显示实时方案圆饼图

  当前阶段区域多屏适配:
  - 改为 flex nowrap 单行布局,stage-item-wrapper 均分空间(flex:1 1 0)
  - phase-box 改用 width:100% + aspect-ratio:1/1 随容器自动缩放
  - stage-input 改为 width:100%,字体动态缩放(clamp 9-11px)
  - 隐藏 input[type=number] 默认的增减按钮(webkit + moz)
  - s 单位绝对定位居中,padding-right 为其预留空间
画安 1 周之前
父节点
当前提交
be6fd28bc4
共有 1 个文件被更改,包括 50 次插入25 次删除
  1. 50 25
      src/components/ui/CrossingDetailPanel.vue

+ 50 - 25
src/components/ui/CrossingDetailPanel.vue

@@ -91,7 +91,7 @@
                                     <div v-for="(item, index) in currentStageList" :key="index"
                                         class="stage-item-wrapper">
                                         <div class="phase-box" :class="{ 'is-active': item.value === currentStage }"
-                                            @click="currentStage = item.value">
+                                            @click="onStageClick(item.value)">
                                             <img :src="item.img" alt="stage" class="phase-image" />
                                         </div>
 
@@ -108,8 +108,8 @@
                                 </div>
                             </div>
 
-                            <!-- 方案圆饼图 -->
-                            <div class="donut-row" v-if="!showLockTime">
+                            <!-- 方案圆饼图:步进模式下不显示 -->
+                            <div class="donut-row" v-if="!showLockTime && currentMethod !== 'step'">
                                 <div class="donut-item">
                                     <div class="donut-title">实时方案(执行方案3)</div>
                                     <PlanDonutChart :chartData="realtimeDonutData"
@@ -144,12 +144,18 @@
                                             </label>
                                         </div>
                                     </div>
+                                    <div class="lock-time-actions" v-if="currentMethod === 'step'">
+                                        <button type="button" class="btn btn-cancel"
+                                            @click="onCancel()">取消</button>
+                                        <button type="button" class="btn btn-confirm"
+                                            @click="onConfirm()">确认</button>
+                                    </div>
                                 </div>
                             </transition>
                         </div>
                     </div>
 
-                    <div class="button-group" v-show="isManualMode">
+                    <div class="button-group" v-show="isManualMode && currentMethod !== 'step'">
                         <div>
                             <button type="button" class="btn btn-cancel" @click="onCancel()">取消</button>
                             <button type="button" class="btn btn-confirm" @click="onConfirm()">确认</button>
@@ -247,23 +253,14 @@ export default {
     watch: {
         // 监听控制方式切换
         currentMethod(newVal) {
-            // 需求4:切换步进方案策略时,出现锁定时间弹窗
+            // 切换到步进时不自动弹出锁定时间,等用户点击阶段再弹
+            this.showLockTime = false;
             if (newVal === 'step') {
-                this.showLockTime = true;
                 this.syncLocktimeByStage();
-            } else {
-                this.showLockTime = false;
             }
 
             // 模拟需求1:根据不同模式,切换对应的控制方案数据 (Mock 逻辑)
             this.updateSchemeDataByMethod(newVal);
-        },
-        // 步进模式下切换阶段时,更新锁定时间选项并重新显示面板
-        currentStage() {
-            if (this.currentMethod === 'step') {
-                this.showLockTime = true;
-                this.syncLocktimeByStage();
-            }
         }
     },
     mounted() {
@@ -278,6 +275,14 @@ export default {
         if (this._ro) this._ro.disconnect();
     },
     methods: {
+        // 点击阶段:切换选中,步进模式下同时弹出锁定时间
+        onStageClick(value) {
+            this.currentStage = value;
+            if (this.currentMethod === 'step') {
+                this.showLockTime = true;
+                this.syncLocktimeByStage();
+            }
+        },
         // 根据当前选中阶段同步锁定时间选项
         syncLocktimeByStage() {
             const stage = this.currentStageList.find(s => s.value === this.currentStage);
@@ -745,6 +750,14 @@ export default {
     color: #ffffff;
 }
 
+.lock-time-actions {
+    display: flex;
+    justify-content: flex-end;
+    gap: clamp(4px, calc(var(--s) * 8px), 8px);
+    padding: clamp(4px, calc(var(--s) * 8px), 8px) clamp(4px, calc(var(--s) * 10px), 10px);
+    border-top: 1px solid rgba(161, 190, 255, 0.15);
+}
+
 .lock-time-option {
     font-size: clamp(9px, calc(var(--s) * 14px), 14px);
 }
@@ -772,21 +785,21 @@ export default {
     width: 100%;
     display: flex;
     align-items: center;
-    justify-content: space-around;
-    flex-wrap: wrap;
-    gap: clamp(4px, calc(var(--s) * 8px), 10px);
-    padding: clamp(6px, calc(var(--s) * 12px), 32px);
+    flex-wrap: nowrap;
+    gap: clamp(8px, calc(var(--s) * 18px), 24px);
+    padding: clamp(4px, calc(var(--s) * 8px), 16px);
     color: #ffffff;
 }
 
 .current-stage-label {
     font-size: clamp(9px, calc(var(--s) * 14px), 14px);
-    width: auto;
     white-space: nowrap;
+    flex-shrink: 0;
 }
 
 .stage-input {
-    width: clamp(32px, calc(var(--s) * 65px), 65px);
+    width: 100%;
+    min-width: 0;
     border: 1px solid rgba(161, 190, 255, 0.7);
     background-color: transparent;
     padding: clamp(2px, calc(var(--s) * 5px), 5px);
@@ -796,8 +809,8 @@ export default {
 
 .phase-box {
     position: relative;
-    width: clamp(30px, calc(var(--s) * 90px), 90px);
-    height: clamp(30px, calc(var(--s) * 90px), 90px);
+    width: 100%;
+    aspect-ratio: 1 / 1;
     background: #E6F0FF;
     border-radius: 4px;
     display: flex;
@@ -910,6 +923,8 @@ export default {
 
 /* 当前阶段输入框微调 */
 .stage-item-wrapper {
+    flex: 1 1 0;
+    min-width: 0;
     display: flex;
     flex-direction: column;
     align-items: stretch;
@@ -932,7 +947,8 @@ export default {
 }
 
 .stage-input {
-    width: clamp(32px, calc(var(--s) * 65px), 65px);
+    width: 100%;
+    min-width: 0;
     border: 1px solid rgba(161, 190, 255, 0.7);
     background-color: transparent;
     padding: clamp(2px, calc(var(--s) * 5px), 5px);
@@ -962,13 +978,22 @@ export default {
 }
 
 .stage-input {
-    width: clamp(32px, calc(var(--s) * 65px), 65px);
+    width: 100%;
+    min-width: 0;
     border: 1px solid rgba(161, 190, 255, 0.7);
     background-color: transparent;
     padding: clamp(2px, calc(var(--s) * 5px), 5px);
+    font-size: clamp(9px, calc(var(--s) * 11px), 11px);
     color: #ffffff;
     text-align: center;
     border-radius: 4px;
+    -moz-appearance: textfield;
+}
+
+.stage-input::-webkit-outer-spin-button,
+.stage-input::-webkit-inner-spin-button {
+    -webkit-appearance: none;
+    margin: 0;
 }
 
 .stage-input:disabled {