From cc0c86385cdef27783ca4f71f050ccddc30eb4e2 Mon Sep 17 00:00:00 2001
From: zjk <852185829@qq.com>
Date: 星期五, 04 九月 2026 17:28:28 +0800
Subject: [PATCH] fix(appointment-scan): 修复步骤进度条在横屏下宽度没有占满的问题

---
 pages/appointment-scan/n-index.nvue |  162 +++++++++++++++++++++++++++++++++++++++-
 components/StepProgress.vue         |   66 +++++++++++++++
 2 files changed, 220 insertions(+), 8 deletions(-)

diff --git a/components/StepProgress.vue b/components/StepProgress.vue
index 5434e73..2589f71 100644
--- a/components/StepProgress.vue
+++ b/components/StepProgress.vue
@@ -1,5 +1,5 @@
 <template>
-  <view class="steps-card">
+  <view class="steps-card" :class="{ landscape: isLandscapeLayout }">
     <view class="steps-row">
       <template v-for="(step, index) in stepsList" :key="index">
         <view class="step-item">
@@ -17,7 +17,7 @@
 </template>
 
 <script setup>
-import { computed } from 'vue';
+import { computed, ref, onMounted, onUnmounted } from 'vue';
 import qrActiveIcon from '../static/appointment-scan/qr-active.png';
 import qrCompletedIcon from '../static/appointment-scan/qr-completed.png';
 import idcardInactiveIcon from '../static/appointment-scan/idcard-inactive.png';
@@ -36,6 +36,47 @@
 import printActiveIcon from '../static/appointment-scan/print-active.png';
 import stepArrowActiveImage from '../static/appointment-scan/step-arrow-active.png';
 import stepArrowInactiveImage from '../static/appointment-scan/step-arrow-inactive.png';
+
+const isLandscapeLayout = ref(false);
+const updateLayoutMode = () => {
+    try {
+        const windowInfo = uni.getWindowInfo ? uni.getWindowInfo() : uni.getSystemInfoSync();
+        const viewportWidth = Number(windowInfo?.windowWidth || windowInfo?.screenWidth || 0);
+        const viewportHeight = Number(windowInfo?.windowHeight || windowInfo?.screenHeight || 0);
+        isLandscapeLayout.value = Boolean(viewportWidth && viewportHeight && viewportWidth > viewportHeight);
+    } catch (error) {
+        console.error('StepProgress 读取窗口尺寸失败:', error);
+        isLandscapeLayout.value = false;
+    }
+};
+
+let flowWindowResizeHandler = null;
+const registerFlowWindowResize = () => {
+    if (flowWindowResizeHandler || !uni.onWindowResize) {
+        return;
+    }
+    flowWindowResizeHandler = () => {
+        updateLayoutMode();
+    };
+    uni.onWindowResize(flowWindowResizeHandler);
+};
+const unregisterFlowWindowResize = () => {
+    if (!flowWindowResizeHandler || !uni.offWindowResize) {
+        flowWindowResizeHandler = null;
+        return;
+    }
+    uni.offWindowResize(flowWindowResizeHandler);
+    flowWindowResizeHandler = null;
+};
+
+onMounted(() => {
+    updateLayoutMode();
+    registerFlowWindowResize();
+});
+
+onUnmounted(() => {
+    unregisterFlowWindowResize();
+});
 
 const props = defineProps({
   currentStep: {
@@ -164,7 +205,7 @@
   height: 138px;
   display: flex;
   flex-direction: row;
-  align-items: flex-start;
+  align-items: center;
   justify-content: space-between;
 }
 
@@ -235,10 +276,29 @@
   display: flex;
   align-items: center;
   justify-content: center;
+  margin-bottom: 56px;
 }
 
 .arrow-img {
   width: 92px;
   height: 82px;
 }
+
+/* 横屏模式 */
+.steps-card.landscape {
+  width: 1824px;
+}
+.steps-card.landscape .steps-row {
+  width: 1824px;
+}
+.steps-card.landscape .step-line {
+  flex: 1; /* 让连接线自动撑开 */
+  align-items: center;
+  justify-content: center;
+  display: flex;
+}
+.steps-card.landscape .step-item {
+  flex: none;
+  width: 150px;
+}
 </style>
diff --git a/pages/appointment-scan/n-index.nvue b/pages/appointment-scan/n-index.nvue
index 56c0011..18af453 100644
--- a/pages/appointment-scan/n-index.nvue
+++ b/pages/appointment-scan/n-index.nvue
@@ -1,5 +1,5 @@
 <template>
-  <view class="page-container" @touchstart="resetInactivityTimer" @click="resetInactivityTimer">
+  <view class="page-container" :class="{ landscape: isLandscapeLayout }" @touchstart="resetInactivityTimer" @click="resetInactivityTimer">
     <!-- 左侧柔光氛围 -->
     <view class="bg-glow"></view>
 
@@ -106,7 +106,8 @@
 
       <!-- 手动录入信息 UI -->
       <template v-else>
-        <view class="main-card manual-card" @click="dismissNameInput">
+        <view class="manual-layout-wrapper" :class="{ landscape: isLandscapeLayout }">
+          <view class="main-card manual-card" @click="dismissNameInput">
           <text class="main-title">手动录入身份证号</text>
           <text class="error-hint" v-if="mode === 'signout' && showMissingEntryHint">未检测到您的进场信息,请检查身份证号码是否正确</text>
 
@@ -165,6 +166,7 @@
           </view>
         </view>
 
+
         <!-- 自定义键盘 -->
         <view class="custom-keyboard" v-if="showCustomKeyboard">
           <view class="keyboard-grid">
@@ -190,6 +192,7 @@
             </view>
           </view>
         </view>
+		</view>
       </template>
     </template>
 
@@ -646,7 +649,7 @@
 
 <script setup>
 import { ref, computed, onMounted, onUnmounted, watch, nextTick, getCurrentInstance } from 'vue';
-import { onLoad } from '@dcloudio/uni-app';
+import { onLoad, onShow, onHide } from '@dcloudio/uni-app';
 import StepProgress from '../../components/StepProgress.vue';
 import { HardwareAPI } from '../../utils/visitorDevice';
 import { saveImageToLocal, deleteLocalImage } from '../../utils/fs';
@@ -682,6 +685,7 @@
 
 const appointmentQrcodePayload = ref(null);
 const appointmentIdCardPayload = ref(null);
+const isLandscapeLayout = ref(false);
 const faceScanLineRef = ref(null);
 const hostScanLineRef = ref(null);
 const facePreviewReady = ref(false);
@@ -2510,7 +2514,7 @@
 };
 // ----------------------------------------------------
 onMounted(async () => {
-  resetInactivityTimer();
+resetInactivityTimer();
 
   // 必须在页面挂载的第一时间注册扫码和读卡的事件监听,
   // 绝对不能放在 await 数据加载之后,否则会导致进入页面前几十秒内刷卡/扫码无反应!
@@ -2557,7 +2561,7 @@
 });
 
 onUnmounted(() => {
-  clearInactivityTimer();
+clearInactivityTimer();
   unregisterAppointmentScanHandler();
   uni.$off('Hardware-PrintOutOfPaper', handlePrinterOutOfPaper);
   dismissNameInput();
@@ -2572,6 +2576,11 @@
 });
 
 onLoad((options) => {
+  const windowInfo = uni.getWindowInfo();
+  isLandscapeLayout.value = windowInfo.windowWidth > windowInfo.windowHeight;
+  uni.onWindowResize((res) => {
+    isLandscapeLayout.value = res.size.windowWidth > res.size.windowHeight;
+  });
   if (options.step) {
     currentStep.value = parseInt(options.step, 10);
   }
@@ -4652,4 +4661,147 @@
 
 .plate-confirm-btn { flex: 1; }
 
+
+/* ==================== 横屏兼容 ==================== */
+.page-container.landscape {
+  width: 1920px;
+  height: 1080px;
+  padding-top: 30px;
+  padding-right: 48px;
+  padding-bottom: 40px;
+  padding-left: 48px;
+  align-items: center;
+}
+
+.page-container.landscape .header-area {
+  width: 1824px;
+}
+.page-container.landscape .left-action {
+  width: 1824px;
+}
+.page-container.landscape .steps-card {
+  width: 1824px;
+}
+.page-container.landscape .steps-row {
+  width: 1824px;
+}
+
+/* 主内容区 & 辅助区缩放 */
+.page-container.landscape .main-card {
+  width: 1824px;
+  height: 540px;
+  padding-top: 20px;
+  padding-right: 80px;
+  padding-bottom: 20px;
+  padding-left: 80px;
+}
+
+.page-container.landscape .bottom-area {
+  width: 1824px;
+  height: 140px;
+  flex-direction: row;
+  justify-content: space-between;
+}
+.page-container.landscape .help-card,
+.page-container.landscape .action-card {
+  width: 880px;
+  height: 140px;
+}
+.page-container.landscape .device-img {
+  width: 420px;
+  height: 320px;
+}
+.page-container.landscape .device-area {
+  height: 320px;
+}
+
+/* 手动录入 */
+.manual-layout-wrapper {
+  display: flex;
+  flex-direction: column;
+}
+.manual-layout-wrapper.landscape {
+  flex-direction: row;
+  justify-content: space-between;
+  width: 1824px;
+}
+.manual-layout-wrapper.landscape .manual-card {
+  width: 900px;
+  height: 704px;
+}
+.manual-layout-wrapper.landscape .custom-keyboard {
+  width: 900px;
+  height: 704px;
+}
+.manual-layout-wrapper.landscape .input-form-card {
+  width: 800px;
+}
+.manual-layout-wrapper.landscape .manual-input-box {
+  width: 800px;
+}
+.manual-layout-wrapper.landscape .real-input {
+  width: 800px;
+}
+
+/* 人脸验证 */
+.page-container.landscape .face-capture-card {
+  height: 360px;
+}
+.page-container.landscape .viewfinder-area {
+  height: 240px;
+}
+.page-container.landscape .viewfinder-box {
+  width: 240px;
+  height: 240px;
+}
+.page-container.landscape .face-camera {
+  width: 240px;
+  height: 240px;
+}
+.page-container.landscape .scan-line {
+  width: 240px;
+}
+.page-container.landscape .viewfinder-border-mask {
+  width: 240px;
+  height: 240px;
+}
+.page-container.landscape .corner-donut {
+  width: 240px;
+  height: 240px;
+}
+
+/* 完善信息 */
+.page-container.landscape .form-card {
+  width: 1824px;
+  height: 704px;
+  flex-direction: row;
+  flex-wrap: wrap;
+  align-content: flex-start;
+  padding-top: 40px;
+  padding-right: 40px;
+  padding-bottom: 40px;
+  padding-left: 40px;
+}
+.page-container.landscape .form-row {
+  width: 800px;
+  margin-right: 40px;
+}
+.page-container.landscape .form-action-row {
+  width: 1744px;
+  margin-top: auto;
+  justify-content: center;
+}
+.page-container.landscape .form-save-btn {
+  width: 600px;
+}
+
+/* 打印凭条 */
+.page-container.landscape .print-ticket-demo {
+  width: 240px;
+  height: 320px;
+}
+.page-container.landscape .print-display-card {
+  height: 360px;
+}
+
 </style>

--
Gitblit v1.7.1