Explorar o código

修改:
- 主题样式修改
- 异常提示修改
- 一直停留首页
- 增加还料离开

liuyanpeng hai 2 meses
pai
achega
f5c9f4bb5e
Modificáronse 42 ficheiros con 5541 adicións e 415 borrados
  1. 5 4
      src/App.vue
  2. 4 4
      src/Fingerprint/FingerprintEnroll.vue
  3. 9 8
      src/agv-process/AbnormalManagement.vue
  4. 7 6
      src/agv-process/DeliveryManagement.vue
  5. 13 11
      src/agv-process/ReturnManagement.vue
  6. 199 0
      src/assets/css/light-theme-components.css
  7. 3214 0
      src/assets/css/light-theme.css
  8. BIN=BIN
      src/assets/images/J20.png
  9. BIN=BIN
      src/assets/images/menu/J20.jpg
  10. BIN=BIN
      src/assets/images/menu/chuku.jpg
  11. BIN=BIN
      src/assets/images/menu/guihuan.jpg
  12. BIN=BIN
      src/assets/images/menu/huanliao.jpg
  13. BIN=BIN
      src/assets/images/menu/jieyong.jpg
  14. BIN=BIN
      src/assets/images/menu/lingliao.jpg
  15. BIN=BIN
      src/assets/images/menu/ruku.jpg
  16. BIN=BIN
      src/assets/images/menu/yunshu.jpg
  17. 16 15
      src/box/FeedingArea.vue
  18. 88 0
      src/common/ErrorDialog.vue
  19. 3 1
      src/composables/useIdleTimeout.js
  20. 12 11
      src/finishProduct/FinishProductIn.vue
  21. 11 10
      src/finishProduct/FinishProductOut.vue
  22. 6 5
      src/gate/ControlGate.vue
  23. 9 8
      src/login/FingerprintLogin.vue
  24. 510 160
      src/login/UserHome.vue
  25. 9 8
      src/login/UserLogin.vue
  26. 8 0
      src/main.js
  27. 5 1
      src/router/routes.js
  28. 10 9
      src/stock-in/InConfirm.vue
  29. 10 9
      src/stock-in/ReturnedLeave.vue
  30. 16 13
      src/stock-out/AgvRfidRecognition.vue
  31. 17 16
      src/stock-out/MaterialInOutConfirm.vue
  32. 16 14
      src/stock-out/OrderPicking.vue
  33. 17 16
      src/stock-out/OutboundConfirm.vue
  34. 828 0
      src/stock-out/OutboundLeave.vue
  35. 20 19
      src/stock/ApplyMaterial.vue
  36. 17 16
      src/stock/RegularRequisition.vue
  37. 21 20
      src/stock/StockPickingCar.vue
  38. 12 11
      src/stock/StockRequisition.vue
  39. 322 0
      src/util/errorDialog.js
  40. 14 17
      src/util/request.js
  41. 90 0
      src/util/theme.js
  42. 3 3
      webpack.dev.js

+ 5 - 4
src/App.vue

@@ -8,12 +8,13 @@
 import { useIdleTimeout } from './composables/useIdleTimeout.js';
 
 // 启用全局3分钟无操作自动跳转功能
-// 排除登录相关页面:首页(/)、指纹登录(/fingerprint-login)
+// 排除登录相关页面:首页(/)
 useIdleTimeout(
-    3 * 60 * 1000, // 3分钟
+    // 3 * 60 * 1000, // 3分钟
+    1000 * 30,
     // 20000, // 20s
-    '/fingerprint-login', // 跳转到指纹登录
-    ['/', '/fingerprint-login'], // 排除的页面
+    '/home', // 跳转到首
+    ['/','/home'], // 排除的页面
 );
 </script>
 

+ 4 - 4
src/Fingerprint/FingerprintEnroll.vue

@@ -120,12 +120,12 @@
 
 <script setup>
 import { useRouter } from 'vue-router';
-import { showToast, showFailToast, showNotify } from 'vant';
 import { ref, onMounted, onUnmounted } from 'vue';
 import { checkEmployeeByJobNo } from '../api/fingerprint.js';
 
 // 图片资源
 import bgImg from '../assets/images/bj.png';
+import { showErrorDialog } from '../util/errorDialog.js';
 
 const router = useRouter();
 
@@ -144,7 +144,7 @@ const handleBack = () => {
 // 录入指纹
 const handleEnroll = () => {
     if (!isConnected.value) {
-        showToast('设备未连接或插件异常,请检查指纹设备');
+        showErrorDialog('设备未连接或插件异常,请检查指纹设备');
         return;
     }
     isScanning.value = true;
@@ -171,7 +171,7 @@ const handleReEnroll = async () => {
             }, 1000);
         }
     } catch (error) {
-        showFailToast('重新连接设备失败');
+        if(error.status !== 401) showErrorDialog('重新连接设备失败');
         statusText.value = '设备连接失败,请检查设备';
     }
 };
@@ -742,7 +742,7 @@ onUnmounted(() => {
   }
 
   .main-content {
-    padding: 10px 20px;
+    padding: 20px;
   }
 
   .step-card {

+ 9 - 8
src/agv-process/AbnormalManagement.vue

@@ -111,7 +111,7 @@
         
         <div class="modal-footer">
           <button class="modal-btn cancel-btn" @click="cancelTask">取消</button>
-          <button class="modal-btn confirm-btn" @click="showErrorDialog">核对异常</button>
+          <button class="modal-btn confirm-btn" @click="showErrorDialogs">核对异常</button>
           <button class="modal-btn take-away-btn" @click="showConfirmDialog">确认无误</button>
         </div>
       </div>
@@ -155,6 +155,7 @@
 import { ref, onMounted } from 'vue';
 import { showNotify } from 'vant';
 import { getLocatorAbnormalAreaStatus, takeAwayAbnormalCar } from '../api/agv.js';
+import { showErrorDialog } from '../util/errorDialog.js';
 
 // 图片资源
 import bgImg from '../assets/images/bj.png';
@@ -198,7 +199,7 @@ const getStatusClass = status => {
 // 打开弹窗
 const openStation = station => {
     if (station.positionStatus === '空闲中' || station.positionStatus === '待入库') {
-        showNotify({ type: 'danger', message: '请选择占用中的异常停泊区' });
+        showErrorDialog('请选择占用中的异常停泊区');
     } else {
         visible.value = true;
         positionName.value = station.positionName;
@@ -225,11 +226,11 @@ const takeAway = async isError => {
             selectedStation.value = null;
             await getStations();
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage || '料车取走失败' });
+            showErrorDialog(res.errorMessage || '料车取走失败');
         }
     } catch (error) {
         console.error('料车取走失败:', error);
-        showNotify({ type: 'danger', message: '料车取走失败' });
+        if(error.status !== 401) showErrorDialog('料车取走失败');
     } finally {
         loading.value = false;
     }
@@ -253,7 +254,7 @@ const showConfirmDialog = () => {
 };
 
 // 显示核对异常对话框
-const showErrorDialog = () => {
+const showErrorDialogs = () => {
     confirmDialog.value = {
         visible: true,
         title: '核对异常',
@@ -291,12 +292,12 @@ const getStations = async () => {
                 stations.value = [];
             }
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage });
+            showErrorDialog(res.errorMessage);
         }
 
     } catch (error) {
         console.error('获取异常停泊区货位数据失败:', error);
-        showNotify({ type: 'danger', message: '获取异常停泊区货位数据失败' });
+        if(error.status !== 401) showErrorDialog('获取异常停泊区货位数据失败');
     } finally {
         loading.value = false;
     }
@@ -789,7 +790,7 @@ onMounted(() => {
   }
 
   .main-content {
-    padding: 10px 20px;
+    padding: 20px;
   }
 
   .station-card {

+ 7 - 6
src/agv-process/DeliveryManagement.vue

@@ -83,6 +83,7 @@
 import { ref, onMounted } from 'vue';
 import { showNotify } from 'vant';
 import { getLocatorFeedAreaStatus, takeAwaySkip } from '../api/agv.js';
+import { showErrorDialog } from '../util/errorDialog.js';
 
 // 图片资源
 import bgImg from '../assets/images/bj.png';
@@ -117,7 +118,7 @@ const getStatusClass = status => {
 // 打开弹窗
 const openStation = station => {
     if (station.positionStatus === '空闲中' || station.positionStatus === '待入库') {
-        showNotify({ type: 'danger', message: '请选择占用中的还料区' });
+        showErrorDialog('请选择占用中的还料区');
     } else {
         visible.value = true;
         positionName.value = station.positionName;
@@ -136,11 +137,11 @@ const takeAway = async () => {
             visible.value = false;
             await getStations();
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage || '料车取走失败' });
+            showErrorDialog(res.errorMessage || '料车取走失败');
         }
     } catch (error) {
         console.error('料车取走失败:', error);
-        showNotify({ type: 'danger', message: '料车取走失败' });
+        if(error.status !== 401) showErrorDialog('料车取走失败');
     } finally {
         loading.value = false;
     }
@@ -162,12 +163,12 @@ const getStations = async () => {
                 stations.value = [];
             }
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage });
+            showErrorDialog(res.errorMessage);
         }
 
     } catch (error) {
         console.error('获取还料位数据失败:', error);
-        showNotify({ type: 'danger', message: '获取还料位数据失败' });
+        if(error.status !== 401) showErrorDialog('获取还料位数据失败');
     } finally {
         loading.value = false;
     }
@@ -462,7 +463,7 @@ onMounted(() => {
   }
 
   .main-content {
-    padding: 10px 20px;
+    padding: 20px;
   }
 
   .station-card {

+ 13 - 11
src/agv-process/ReturnManagement.vue

@@ -174,6 +174,7 @@ import { showNotify } from 'vant';
 import { getLocatorStatus, getNoInStorageTruck, generateTaskByBlankNo, findDeviceByCondition } from '../api/agv.js';
 import vSelect from 'vue-select';
 import 'vue-select/dist/vue-select.css';
+import { showErrorDialog } from '../util/errorDialog.js';
 
 // 图片资源
 import bgImg from '../assets/images/bj.png';
@@ -265,7 +266,7 @@ const handleSearch = value => {
                     truckData.value = [];
                 }
             } else {
-                showNotify({ type: 'danger', message: res.errorMessage || '搜索料车失败' });
+                showErrorDialog(res.errorMessage || '搜索料车失败');
                 truckNos.value = [];
                 truckData.value = [];
             }
@@ -280,7 +281,7 @@ const handleSearch = value => {
 // 打开弹窗
 const openStation = station => {
     if (station.positionStatus === '已占用') {
-        showNotify({ type: 'danger', message: '请选择空闲的还料区' });
+        showErrorDialog('请选择空闲的还料区');
     } else {
         visible.value = true;
         positionName.value = station.positionName;
@@ -380,15 +381,16 @@ const searchToolingDevices = async () => {
                 }));
             } else {
                 toolingDevices.value = [];
-                showNotify({ type: 'danger', message: '未找到相关工装设备' });
+                showErrorDialog('未找到相关工装设备');
             }
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage || '搜索工装设备失败' });
+            showErrorDialog(res.errorMessage || '搜索工装设备失败');
             toolingDevices.value = [];
         }
     } catch (error) {
         console.error('搜索工装设备失败:', error);
-        showNotify({ type: 'danger', message: '搜索工装设备失败' });
+        if(error.status !== 401) showErrorDialog('搜索工装设备失败');
+
         toolingDevices.value = [];
     } finally {
         loading.value = false;
@@ -469,13 +471,13 @@ const handleDialogClose = async action => {
 // 根据还料货位和料车编号生成归还单和调度任务
 const generateTask = async () => {
     if (!truckNo.value) {
-        showNotify({ type: 'danger', message: '请输入料车编号' });
+        showErrorDialog('请输入料车编号');
         return false; // 返回 false 阻止关闭
     }
 
     // 如果是接驳车,检查是否选择了工装设备
     if (isTransferTruck.value && selectedToolings.value.length === 0) {
-        showNotify({ type: 'danger', message: '接驳车需要至少选择一个工装设备' });
+        showErrorDialog('接驳车需要至少选择一个工装设备');
         return false; // 返回 false 阻止关闭
     }
 
@@ -510,12 +512,12 @@ const generateTask = async () => {
             await getStations();
             return true; // 成功后关闭弹窗
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage || '绑定失败' });
+            showErrorDialog(res.errorMessage || '绑定失败');
             return false; // 失败不关闭
         }
     } catch (error) {
         console.error('绑定失败:', error);
-        showNotify({ type: 'danger', message: '绑定失败' });
+        if(error.status !== 401) showErrorDialog('绑定失败');
         return false; // 异常不关闭
     } finally {
         loading.value = false;
@@ -549,12 +551,12 @@ const getStations = async () => {
                 stations.value = [];
             }
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage });
+            showErrorDialog(res.errorMessage);
         }
 
     } catch (error) {
         console.error('获取还料位数据失败:', error);
-        showNotify({ type: 'danger', message: '获取还料位数据失败' });
+        if(error.status !== 401) showErrorDialog('获取还料位数据失败');
     } finally {
         loading.value = false;
     }

+ 199 - 0
src/assets/css/light-theme-components.css

@@ -0,0 +1,199 @@
+/**
+ * 明亮主题 - 其他组件样式
+ * 包括:表格、筛选面板、通用组件等
+ */
+
+/* ========== 明亮主题 - 表格样式 ========== */
+[data-theme="light"] .table-container {
+  background: #FFFFFF;
+  border: 1px solid #E0E0E0;
+}
+
+[data-theme="light"] .table-header {
+  background: linear-gradient(90deg, #E6F7FF 0%, #BAE7FF 100%);
+  color: #1890FF;
+  border-bottom: 2px solid #1890FF;
+}
+
+[data-theme="light"] .table-row {
+  border-bottom: 1px solid #F0F0F0;
+}
+
+[data-theme="light"] .table-row:hover {
+  background: #FAFAFA;
+}
+
+[data-theme="light"] .table-cell {
+  color: #1a1a1a;
+}
+
+/* ========== 明亮主题 - 筛选面板 ========== */
+[data-theme="light"] .filter-panel {
+  background: #FFFFFF;
+  border: 1px solid #E0E0E0;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+}
+
+[data-theme="light"] .filter-title {
+  color: #1a1a1a;
+  border-bottom: 1px solid #E0E0E0;
+}
+
+[data-theme="light"] .filter-item label {
+  color: #666666;
+}
+
+/* ========== 明亮主题 - 卡片样式 ========== */
+[data-theme="light"] .card {
+  background: #FFFFFF;
+  border: 1px solid #E0E0E0;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+}
+
+[data-theme="light"] .card-header {
+  background: linear-gradient(90deg, #E6F7FF 0%, #BAE7FF 100%);
+  color: #1890FF;
+  border-bottom: 1px solid #E0E0E0;
+}
+
+[data-theme="light"] .card-title {
+  color: #1a1a1a;
+}
+
+[data-theme="light"] .card-body {
+  color: #666666;
+}
+
+/* ========== 明亮主题 - 列表项 ========== */
+[data-theme="light"] .list-item {
+  background: #FFFFFF;
+  border: 1px solid #E0E0E0;
+}
+
+[data-theme="light"] .list-item:hover {
+  background: #FAFAFA;
+  border-color: #1890FF;
+}
+
+[data-theme="light"] .list-item-title {
+  color: #1a1a1a;
+}
+
+[data-theme="light"] .list-item-desc {
+  color: #666666;
+}
+
+/* ========== 明亮主题 - 标签 ========== */
+[data-theme="light"] .tag {
+  background: #E6F7FF;
+  color: #1890FF;
+  border: 1px solid #91D5FF;
+}
+
+[data-theme="light"] .tag.success {
+  background: #F6FFED;
+  color: #52C41A;
+  border: 1px solid #B7EB8F;
+}
+
+[data-theme="light"] .tag.warning {
+  background: #FFFBE6;
+  color: #FA8C16;
+  border: 1px solid #FFE58F;
+}
+
+[data-theme="light"] .tag.danger {
+  background: #FFF1F0;
+  color: #FF4D4F;
+  border: 1px solid #FFCCC7;
+}
+
+/* ========== 明亮主题 - 分页器 ========== */
+[data-theme="light"] .pagination {
+  background: #FFFFFF;
+}
+
+[data-theme="light"] .pagination-item {
+  background: #FFFFFF;
+  border: 1px solid #D9D9D9;
+  color: #1a1a1a;
+}
+
+[data-theme="light"] .pagination-item:hover {
+  border-color: #1890FF;
+  color: #1890FF;
+}
+
+[data-theme="light"] .pagination-item.active {
+  background: #1890FF;
+  border-color: #1890FF;
+  color: #FFFFFF;
+}
+
+/* ========== 明亮主题 - 步骤条 ========== */
+[data-theme="light"] .steps-item {
+  color: #666666;
+}
+
+[data-theme="light"] .steps-item.active {
+  color: #1890FF;
+}
+
+[data-theme="light"] .steps-item.completed {
+  color: #52C41A;
+}
+
+[data-theme="light"] .steps-icon {
+  background: #F5F5F5;
+  border: 2px solid #D9D9D9;
+  color: #666666;
+}
+
+[data-theme="light"] .steps-item.active .steps-icon {
+  background: #1890FF;
+  border-color: #1890FF;
+  color: #FFFFFF;
+}
+
+[data-theme="light"] .steps-item.completed .steps-icon {
+  background: #52C41A;
+  border-color: #52C41A;
+  color: #FFFFFF;
+}
+
+/* ========== 明亮主题 - 错误提示弹窗 ========== */
+.error-dialog-light .van-dialog {
+  background-color: #ffffff;
+  border-radius: 8px;
+  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
+}
+
+.error-dialog-light .van-dialog__header {
+  color: #323233;
+  font-weight: 600;
+  font-size: 16px;
+  padding-top: 26px;
+}
+
+.error-dialog-light .van-dialog__message {
+  color: #646566;
+  font-size: 14px;
+  line-height: 20px;
+  padding: 26px 24px;
+  text-align: left;
+}
+
+.error-dialog-light .van-dialog__footer {
+  border-top: 1px solid #ebedf0;
+}
+
+.error-dialog-light .van-dialog__confirm {
+  color: #1989fa;
+  font-weight: 500;
+  font-size: 16px;
+}
+
+.error-dialog-light .van-dialog__confirm:active {
+  background-color: #f2f3f5;
+}
+

+ 3214 - 0
src/assets/css/light-theme.css

@@ -0,0 +1,3214 @@
+/**
+ * 明亮柔和主题样式
+ * 参考客户提供的设计图:简洁、明亮、现代
+ * 主色调:浅蓝白色渐变背景 + 鲜艳蓝色按钮
+ *
+ * 重要:明亮主题需要完全重新设计,包括:
+ * 1. 背景图片/渐变
+ * 2. 卡片背景图
+ * 3. 图标样式
+ * 4. 所有组件的视觉风格
+ */
+
+/* ========== 明亮主题 - 全局背景 ========== */
+/* 使用柔和的渐变背景替代深色背景图 */
+[data-theme="light"] .bg-layer {
+  background: linear-gradient(180deg,
+    #E8F4FF 0%,
+    #F0F8FF 30%,
+    #FAFCFF 60%,
+    #FFFFFF 100%) !important;
+  background-image: none !important;
+}
+
+/* 首页背景 */
+[data-theme="light"] .home-page {
+  background: linear-gradient(180deg,
+    #E8F4FF 0%,
+    #F0F8FF 30%,
+    #FAFCFF 60%,
+    #FFFFFF 100%);
+}
+
+/* 登录页背景 */
+[data-theme="light"] .fingerprint-login-page,
+[data-theme="light"] .login-page {
+  background: linear-gradient(135deg,
+    #E8F4FF 0%,
+    #F0F8FF 50%,
+    #FFFFFF 100%) !important;
+}
+
+[data-theme="light"] .fingerprint-login-page .bg-layer,
+[data-theme="light"] .login-page .bg-layer {
+  background: linear-gradient(135deg,
+    #E8F4FF 0%,
+    #F0F8FF 50%,
+    #FFFFFF 100%) !important;
+  background-image: none !important;
+}
+
+/* 业务页面背景 */
+[data-theme="light"] .stock-requisition-page,
+[data-theme="light"] .stock-out-page,
+[data-theme="light"] .stock-in-page,
+[data-theme="light"] .order-picking-page,
+[data-theme="light"] .finish-product-page {
+  background: linear-gradient(180deg,
+    #E8F4FF 0%,
+    #F5F9FF 50%,
+    #FFFFFF 100%);
+}
+
+[data-theme="light"] .stock-requisition-page .bg-layer,
+[data-theme="light"] .stock-out-page .bg-layer,
+[data-theme="light"] .stock-in-page .bg-layer,
+[data-theme="light"] .order-picking-page .bg-layer,
+[data-theme="light"] .finish-product-page .bg-layer {
+  background: linear-gradient(180deg,
+    #E8F4FF 0%,
+    #F5F9FF 50%,
+    #FFFFFF 100%) !important;
+  background-image: none !important;
+}
+
+/* 飞机图片 - 明亮主题下隐藏背景层,使用 Banner 区域 */
+[data-theme="light"] .airplane-layer {
+  display: none !important;
+}
+
+/* 明亮主题 - 歼-20 Banner 区域样式 */
+[data-theme="light"] .aircraft-banner {
+  display: flex !important;
+}
+
+[data-theme="light"] .banner-title {
+  color: #1a1a1a !important;
+}
+
+[data-theme="light"] .banner-subtitle {
+  color: #1890FF !important;
+}
+
+[data-theme="light"] .banner-desc {
+  color: #666666 !important;
+}
+
+/* ========== 明亮主题 - 顶部区域 ========== */
+/* 通用顶部区域样式 - 适用于所有使用 header-section 的页面 */
+[data-theme="light"] .header-section {
+  background: linear-gradient(90deg,
+    rgba(24, 144, 255, 0.08) 0%,
+    rgba(24, 144, 255, 0.15) 50%,
+    rgba(24, 144, 255, 0.08) 100%) !important;
+  border-bottom: 2px solid rgba(24, 144, 255, 0.2) !important;
+}
+
+/* 通用标题样式 */
+[data-theme="light"] .header-section .page-title,
+[data-theme="light"] .page-title {
+  color: #1890FF !important;
+  text-shadow: 0 2px 4px rgba(24, 144, 255, 0.2) !important;
+  font-weight: 700 !important;
+}
+
+/* 首页顶部区域 - 特殊布局 */
+[data-theme="light"] .home-page .header-section {
+  position: relative !important;
+  width: 100% !important;
+  height: 100px !important;
+  min-height: 100px !important;
+  padding: 0 !important;
+  z-index: 10 !important;
+}
+
+/* 隐藏深色主题的背景图 */
+[data-theme="light"] .home-page .header-section .header-bg {
+  display: none !important;
+}
+
+/* 首页标题 - 保持绝对定位居中 */
+[data-theme="light"] .home-page .header-section .title {
+  position: absolute !important;
+  top: 50% !important;
+  left: 50% !important;
+  transform: translate(-50%, -50%) !important;
+  color: #1890FF !important;
+  text-shadow: 0 2px 4px rgba(24, 144, 255, 0.2) !important;
+  font-weight: 700 !important;
+  font-size: 32px !important;
+  z-index: 12 !important;
+  margin: 0 !important;
+  padding: 0 !important;
+  white-space: nowrap !important;
+}
+
+/* 用户徽章 - 确保不遮挡标题 */
+[data-theme="light"] .home-page .user-badge {
+  z-index: 11 !important;
+}
+
+/* 操作按钮区 - 确保不遮挡标题 */
+[data-theme="light"] .home-page .header-actions {
+  z-index: 11 !important;
+}
+
+/* 其他页面的顶部区域(使用PageHeader组件) */
+[data-theme="light"] .page-header {
+  background: linear-gradient(90deg,
+    rgba(24, 144, 255, 0.08) 0%,
+    rgba(24, 144, 255, 0.15) 50%,
+    rgba(24, 144, 255, 0.08) 100%) !important;
+  border-bottom: 2px solid rgba(24, 144, 255, 0.2) !important;
+}
+
+[data-theme="light"] .page-header-title {
+  color: #1890FF !important;
+  text-shadow: 0 2px 4px rgba(24, 144, 255, 0.2) !important;
+  font-weight: 700 !important;
+}
+
+/* ========== 明亮主题 - 顶部按钮 ========== */
+[data-theme="light"] .logout-btn,
+[data-theme="light"] .back-btn {
+  background: linear-gradient(90deg, #1890FF 0%, #0066FF 100%) !important;
+  border: 1px solid #0066FF !important;
+  color: #fff !important;
+  box-shadow: 0 2px 8px rgba(24, 144, 255, 0.3) !important;
+}
+
+/* 返回按钮图标 */
+[data-theme="light"] .back-btn i,
+[data-theme="light"] .back-btn .fas,
+[data-theme="light"] .back-btn .fa {
+  color: #ffffff !important;
+}
+
+[data-theme="light"] .logout-btn:hover,
+[data-theme="light"] .back-btn:hover {
+  box-shadow: 0 4px 12px rgba(24, 144, 255, 0.4) !important;
+  /* transform: translateY(-1px) !important; */
+}
+
+[data-theme="light"] .logout-btn:hover,
+[data-theme="light"] .back-btn:hover {
+  background: linear-gradient(90deg, #0066FF 0%, #0050DD 100%) !important;
+  box-shadow: 0 4px 12px rgba(24, 144, 255, 0.4) !important;
+}
+
+[data-theme="light"] .logout-btn i,
+[data-theme="light"] .back-btn i {
+  color: #ffffff !important;
+}
+
+/* ========== 明亮主题 - 统计卡片区域 ========== */
+/* 使用明亮的渐变背景,但保持与深色主题相似的视觉效果 */
+[data-theme="light"] .home-page .stat-card {
+  background: rgba(255, 255, 255, 0.95) !important;
+  border: 2px solid rgba(24, 144, 255, 0.2) !important;
+  box-shadow: 0 4px 16px rgba(24, 144, 255, 0.15) !important;
+  backdrop-filter: blur(10px);
+  position: relative;
+  overflow: visible !important;
+  background-image: none !important;
+  justify-content: center !important;
+  padding: 25px !important;
+}
+
+/* 统计卡片内容包装器 - 明亮主题下左对齐 */
+[data-theme="light"] .home-page .stat-card {
+  display: flex !important;
+  align-items: center !important;
+  justify-content: flex-start !important;
+}
+
+/* 统计图标 - 明亮主题样式 */
+[data-theme="light"] .home-page .stat-icon {
+  width: 65px !important;
+  height: 65px !important;
+  border-radius: 12px !important;
+  display: flex !important;
+  align-items: center !important;
+  justify-content: center !important;
+  font-size: 32px !important;
+  flex-shrink: 0 !important;
+  margin-right: 20px !important;
+  background: rgba(30, 144, 255, 0.1) !important;
+}
+
+[data-theme="light"] .home-page .stat-icon i {
+  font-size: 32px !important;
+}
+
+/* 第一个卡片 - 蓝色 */
+[data-theme="light"] .home-page .stat-card:nth-child(1) {
+  background: linear-gradient(135deg, rgba(255, 255, 255, 0.98) 0%, rgba(230, 247, 255, 0.95) 100%) !important;
+  border-color: rgba(24, 144, 255, 0.3) !important;
+}
+
+[data-theme="light"] .home-page .stat-card:nth-child(1) .stat-icon {
+  background: #dbeafe !important;
+  color: #2563eb !important;
+}
+
+/* 第二个卡片 - 紫色 */
+[data-theme="light"] .home-page .stat-card:nth-child(2) {
+  background: linear-gradient(135deg, rgba(255, 255, 255, 0.98) 0%, rgba(243, 229, 245, 0.95) 100%) !important;
+  border-color: rgba(156, 39, 176, 0.3) !important;
+}
+
+[data-theme="light"] .home-page .stat-card:nth-child(2) .stat-icon {
+  background: #f3e8ff !important;
+  color: #9333ea !important;
+}
+
+/* 第三个卡片 - 青色 */
+[data-theme="light"] .home-page .stat-card:nth-child(3) {
+  background: linear-gradient(135deg, rgba(255, 255, 255, 0.98) 0%, rgba(224, 247, 250, 0.95) 100%) !important;
+  border-color: rgba(0, 188, 212, 0.3) !important;
+}
+
+[data-theme="light"] .home-page .stat-card:nth-child(3) .stat-icon {
+  background: #dcfce7 !important;
+  color: #16a34a !important;
+}
+
+[data-theme="light"] .home-page .stat-label {
+  color: #1a1a1a !important;
+  font-weight: 700 !important;
+  font-size: 18px !important;
+}
+
+[data-theme="light"] .home-page .stat-value {
+  color: #1890FF !important;
+  font-weight: 700 !important;
+  font-size: 36px !important;
+  text-shadow: 0 2px 4px rgba(24, 144, 255, 0.2) !important;
+}
+
+[data-theme="light"] .home-page .stat-card:nth-child(2) .stat-value {
+  color: #9C27B0 !important;
+  text-shadow: 0 2px 4px rgba(156, 39, 176, 0.2) !important;
+}
+
+[data-theme="light"] .home-page .stat-card:nth-child(3) .stat-value {
+  color: #00BCD4 !important;
+  text-shadow: 0 2px 4px rgba(0, 188, 212, 0.2) !important;
+}
+
+/* ========== 明亮主题 - 操作按钮区域 ========== */
+[data-theme="light"] .home-page .buttons-section {
+  background: transparent !important;
+  border: none !important;
+  /* padding: 0 !important; */
+  display: flex !important;
+  flex-wrap: wrap !important;
+  justify-content: center !important;
+  gap: 20px !important;
+}
+
+[data-theme="light"] .home-page .action-btn {
+  width: clamp(140px, 22vw, 220px) !important;
+  height: clamp(120px, 15vw, 160px) !important;
+  border-radius: 16px !important;
+  background-color: #ffffff !important;
+  display: flex !important;
+  flex-direction: column !important;
+  justify-content: space-between !important;
+  padding: 24px !important;
+  border: none !important;
+  max-width: none !important;
+  flex: none !important;
+}
+
+/* 隐藏深色主题元素 */
+[data-theme="light"] .home-page .btn-bg,
+[data-theme="light"] .home-page .btn-text {
+  display: none !important;
+}
+
+/* 确保背景图在卡片内部正确显示 */
+[data-theme="light"] .home-page .card-bg-image {
+  display: block !important;
+  position: absolute !important;
+  inset: 0 !important;
+  width: 100% !important;
+  height: 100% !important;
+  object-fit: cover !important;
+  z-index: 1 !important;
+}
+
+[data-theme="light"] .home-page .card-color-overlay {
+  display: block !important;
+  position: absolute !important;
+  inset: 0 !important;
+  z-index: 2 !important;
+  opacity: 0.85 !important;
+}
+
+[data-theme="light"] .home-page .card-content {
+  display: block !important;
+  position: relative !important;
+  z-index: 3 !important;
+  text-align: left !important;
+}
+
+[data-theme="light"] .home-page .card-arrow {
+  display: flex !important;
+  position: relative !important;
+  z-index: 3 !important;
+  justify-content: flex-end !important;
+}
+
+/* Removed conflicting action-btn hover and nth-child rules for light theme to let UserHome.vue styles apply */
+
+/* Removed conflicting action-btn rules - let UserHome.vue styles apply for menu cards */
+
+/* 常用领料按钮 - 紫色主题 */
+[data-theme="light"] .regular-btn {
+  background: linear-gradient(90deg, #9C27B0 0%, #7B1FA2 100%) !important;
+  border-color: #9C27B0 !important;
+}
+
+[data-theme="light"] .regular-btn:hover {
+  background: linear-gradient(90deg, #7B1FA2 0%, #6A1B9A 100%) !important;
+  box-shadow: 0 4px 12px rgba(156, 39, 176, 0.4) !important;
+}
+
+[data-theme="light"] .regular-btn i {
+  color: #ffffff !important;
+}
+
+/* 领料车按钮 - 青色主题 */
+[data-theme="light"] .cart-btn {
+  background: linear-gradient(90deg, #00BCD4 0%, #0097A7 100%) !important;
+  border-color: #00BCD4 !important;
+}
+
+[data-theme="light"] .cart-btn:hover {
+  background: linear-gradient(90deg, #0097A7 0%, #00838F 100%) !important;
+  box-shadow: 0 4px 12px rgba(0, 188, 212, 0.4) !important;
+}
+
+[data-theme="light"] .cart-btn i {
+  color: #ffffff !important;
+}
+
+/* ========== 明亮主题 - 用户徽章 ========== */
+[data-theme="light"] .home-page .user-badge {
+  background: linear-gradient(90deg, #1890FF 0%, #0066FF 100%) !important;
+  border: 1px solid #0066FF !important;
+  box-shadow: 0 2px 8px rgba(24, 144, 255, 0.3) !important;
+}
+
+[data-theme="light"] .home-page .user-icon {
+  color: #ffffff !important;
+}
+
+[data-theme="light"] .home-page .username {
+  color: #ffffff !important;
+}
+
+/* 退出按钮 */
+[data-theme="light"] .home-page .exit-btn {
+  background: linear-gradient(90deg, #1890FF 0%, #0066FF 100%) !important;
+  box-shadow: 0 2px 8px rgba(24, 144, 255, 0.3) !important;
+  color: #ffffff !important;
+}
+
+[data-theme="light"] .home-page .exit-btn:hover {
+  box-shadow: 0 4px 12px rgba(24, 144, 255, 0.4) !important;
+}
+
+/* 设置图标按钮 */
+[data-theme="light"] .home-page .icon-btn {
+  background: rgba(24, 144, 255, 0.1) !important;
+  border: 1px solid rgba(24, 144, 255, 0.3) !important;
+}
+
+[data-theme="light"] .home-page .icon-btn:hover {
+  background: rgba(24, 144, 255, 0.2) !important;
+}
+
+[data-theme="light"] .home-page .settings-icon {
+  filter: brightness(0.3) sepia(1) hue-rotate(180deg) saturate(5);
+}
+
+/* 下拉菜单 */
+[data-theme="light"] .home-page .dropdown-menu {
+  background: #FFFFFF !important;
+  border: 1px solid #E0E0E0 !important;
+  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15) !important;
+}
+
+[data-theme="light"] .home-page .dropdown-item {
+  color: #1a1a1a !important;
+}
+
+[data-theme="light"] .home-page .dropdown-item:hover {
+  background: #E6F7FF !important;
+}
+
+[data-theme="light"] .home-page .dropdown-item i {
+  color: #1890FF !important;
+}
+
+/* ========== 明亮主题 - Loading 遮罩层 ========== */
+[data-theme="light"] .loading-overlay {
+  background: rgba(255, 255, 255, 0.95) !important;
+}
+
+[data-theme="light"] .loading-dots .dot {
+  background: #1890FF !important;
+}
+
+[data-theme="light"] .loading-text {
+  color: #1890FF !important;
+}
+
+/* ========== 明亮主题 - 表格区域 ========== */
+[data-theme="light"] .home-page .table-section {
+  background: rgba(255, 255, 255, 0.95) !important;
+  border: 1px solid #E0E0E0 !important;
+  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08) !important;
+}
+
+[data-theme="light"] .home-page :deep(.dv-scroll-board .header) {
+  color: #1890FF !important;
+  background: linear-gradient(90deg, rgba(24, 144, 255, 0.05) 0%, rgba(24, 144, 255, 0.15) 50%, rgba(24, 144, 255, 0.05) 100%) !important;
+  font-weight: 600 !important;
+}
+
+[data-theme="light"] .home-page :deep(.dv-scroll-board .rows .row-item) {
+  color: #1a1a1a !important;
+}
+
+[data-theme="light"] .home-page :deep(.dv-scroll-board .rows .ceil) {
+  background: rgba(248, 248, 248, 0.5) !important;
+}
+
+[data-theme="light"] .home-page :deep(.dv-scroll-board .rows .ceil:nth-child(even)) {
+  background: rgba(255, 255, 255, 0.8) !important;
+}
+
+/* ========== 明亮主题 - 底部装饰 ========== */
+[data-theme="light"] .divider-section {
+  display: none !important;
+}
+
+[data-theme="light"] .divider-img {
+  display: none !important;
+}
+
+/* ========== 明亮主题 - 异常停泊区提示卡片 ========== */
+[data-theme="light"] .home-page .abnormal-card {
+  background: #FFFFFF !important;
+  border: 2px solid #FFD666 !important;
+  box-shadow: 0 4px 12px rgba(255, 193, 7, 0.2) !important;
+}
+
+[data-theme="light"] .home-page .abnormal-card-header h3 {
+  color: #FA8C16 !important;
+  text-shadow: none !important;
+}
+
+[data-theme="light"] .home-page .abnormal-card-content p {
+  color: #666666 !important;
+}
+
+[data-theme="light"] .home-page .know-btn {
+  background: #F5F5F5 !important;
+  color: #666666 !important;
+  border: 1px solid #D9D9D9 !important;
+}
+
+[data-theme="light"] .home-page .know-btn:hover {
+  background: #E8E8E8 !important;
+  color: #1a1a1a !important;
+}
+
+[data-theme="light"] .home-page .go-btn {
+  background: linear-gradient(90deg, #FA8C16 0%, #FFA940 100%) !important;
+  color: #fff !important;
+}
+
+[data-theme="light"] .home-page .go-btn:hover {
+  box-shadow: 0 4px 12px rgba(250, 140, 22, 0.4) !important;
+}
+
+/* ========== 明亮主题 - 科技感弹窗样式 ========== */
+[data-theme="light"] .tech-modal-overlay {
+  background: rgba(0, 0, 0, 0.5) !important;
+}
+
+[data-theme="light"] .tech-modal {
+  background: #FFFFFF !important;
+  border: 1px solid #E0E0E0 !important;
+  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15) !important;
+}
+
+[data-theme="light"] .tech-modal.danger-modal {
+  border-color: #FF4D4F !important;
+  box-shadow: 0 8px 24px rgba(255, 77, 79, 0.2) !important;
+}
+
+[data-theme="light"] .modal-text h3 {
+  color: #1a1a1a !important;
+  text-shadow: none !important;
+}
+
+[data-theme="light"] .modal-text p {
+  color: #666666 !important;
+}
+
+[data-theme="light"] .icon-box {
+  background: linear-gradient(135deg, #1890FF 0%, #0066FF 100%) !important;
+  box-shadow: 0 4px 12px rgba(24, 144, 255, 0.3) !important;
+}
+
+[data-theme="light"] .icon-box.danger-box {
+  background: linear-gradient(135deg, #FF4D4F 0%, #F5222D 100%) !important;
+  box-shadow: 0 4px 12px rgba(255, 77, 79, 0.3) !important;
+}
+
+[data-theme="light"] .modal-btn.cancel-btn,
+[data-theme="light"] .modal-btn.cancel {
+  background: #F5F5F5 !important;
+  border: 1px solid #D9D9D9 !important;
+  color: #666666 !important;
+}
+
+[data-theme="light"] .modal-btn.cancel-btn:hover,
+[data-theme="light"] .modal-btn.cancel:hover {
+  background: #E8E8E8 !important;
+  border-color: #BFBFBF !important;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1) !important;
+}
+
+[data-theme="light"] .modal-btn.confirm-btn,
+[data-theme="light"] .modal-btn.confirm {
+  background: linear-gradient(90deg, #52C41A 0%, #73D13D 100%) !important;
+  color: #fff !important;
+}
+
+[data-theme="light"] .modal-btn.confirm-btn:hover,
+[data-theme="light"] .modal-btn.confirm:hover {
+  box-shadow: 0 4px 12px rgba(82, 196, 26, 0.4) !important;
+  transform: translateY(-2px) !important;
+}
+
+[data-theme="light"] .modal-btn.danger-confirm-btn,
+[data-theme="light"] .modal-btn.confirm.danger {
+  background: linear-gradient(90deg, #FF4D4F 0%, #F5222D 100%) !important;
+  color: #fff !important;
+}
+
+[data-theme="light"] .modal-btn.danger-confirm-btn:hover,
+[data-theme="light"] .modal-btn.confirm.danger:hover {
+  box-shadow: 0 4px 12px rgba(255, 77, 79, 0.4) !important;
+  transform: translateY(-2px) !important;
+}
+
+/* ========== 明亮主题 - 输入框样式 ========== */
+[data-theme="light"] .dark-input {
+  background: #FFFFFF !important;
+  border: 1px solid #D9D9D9 !important;
+  color: #1a1a1a !important;
+}
+
+[data-theme="light"] .dark-input::placeholder {
+  color: #BFBFBF !important;
+  opacity: 1 !important;
+}
+
+[data-theme="light"] .dark-input:focus {
+  border-color: #1890FF !important;
+  box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2) !important;
+}
+
+/* 弹窗内的表单输入框 - 仅匹配直接子元素以避免影响vue-select */
+[data-theme="light"] .form-item > input {
+  background: #FFFFFF !important;
+  border: 2px solid #D9D9D9 !important;
+  color: #1a1a1a !important;
+  font-weight: 600 !important;
+}
+
+[data-theme="light"] .form-item > input::placeholder {
+  color: #BFBFBF !important;
+  opacity: 1 !important;
+}
+
+[data-theme="light"] .form-item > input:focus {
+  border-color: #1890FF !important;
+  box-shadow: 0 0 8px rgba(24, 144, 255, 0.25) !important;
+}
+
+/* 弹窗内的表单标签 */
+[data-theme="light"] .form-item label {
+  color: #666666 !important;
+  font-weight: 700 !important;
+}
+
+/* ========== 明亮主题 - 弹窗样式 ========== */
+/* 弹窗遮罩层 */
+[data-theme="light"] .tech-modal-overlay {
+  background: rgba(0, 0, 0, 0.45) !important;
+}
+
+/* 弹窗主体 */
+[data-theme="light"] .tech-modal {
+  background: linear-gradient(135deg, #FFFFFF 0%, #F5F9FF 100%) !important;
+  border: 3px solid rgba(24, 144, 255, 0.3) !important;
+  box-shadow: 0 8px 32px rgba(24, 144, 255, 0.2) !important;
+}
+
+/* 弹窗头部 */
+[data-theme="light"] .modal-header h3 {
+  color: #1890FF !important;
+  font-weight: 800 !important;
+  text-shadow: none !important;
+}
+
+[data-theme="light"] .modal-header p {
+  color: #666666 !important;
+  font-weight: 600 !important;
+}
+
+/* 弹窗按钮 */
+[data-theme="light"] .modal-btn.cancel {
+  background: #F5F5F5 !important;
+  border: 2px solid #D9D9D9 !important;
+  color: #666666 !important;
+  font-weight: 700 !important;
+}
+
+[data-theme="light"] .modal-btn.cancel:hover {
+  background: #E8E8E8 !important;
+  border-color: #BFBFBF !important;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1) !important;
+}
+
+[data-theme="light"] .modal-btn.confirm {
+  background: linear-gradient(90deg, #1890FF 0%, #0066FF 100%) !important;
+  border: none !important;
+  color: #ffffff !important;
+  box-shadow: 0 4px 12px rgba(24, 144, 255, 0.4) !important;
+  font-weight: 700 !important;
+}
+
+[data-theme="light"] .modal-btn.confirm:hover:not(:disabled) {
+  box-shadow: 0 6px 16px rgba(24, 144, 255, 0.5) !important;
+  transform: translateY(-1px) !important;
+}
+
+[data-theme="light"] .modal-btn.confirm:disabled {
+  background: #F5F5F5 !important;
+  color: #BFBFBF !important;
+  box-shadow: none !important;
+  cursor: not-allowed !important;
+}
+
+/* 弹窗关闭按钮 */
+[data-theme="light"] .modal-close-btn {
+  background: rgba(24, 144, 255, 0.1) !important;
+  color: #1890FF !important;
+}
+
+[data-theme="light"] .modal-close-btn:hover {
+  background: rgba(24, 144, 255, 0.2) !important;
+  color: #0066FF !important;
+}
+
+/* ========== 明亮主题 - vue-select 下拉框样式 ========== */
+/* 下拉框主体 */
+[data-theme="light"] .dark-select .vs__dropdown-toggle,
+[data-theme="light"] .filter-select .vs__dropdown-toggle,
+[data-theme="light"] .dialog-select .vs__dropdown-toggle,
+[data-theme="light"] .location-select .vs__dropdown-toggle,
+[data-theme="light"] :deep(.v-select .vs__dropdown-toggle),
+[data-theme="light"] :deep(.dark-select .vs__dropdown-toggle) {
+  background: #FFFFFF !important;
+  border: 2px solid #D9D9D9 !important;
+  border-radius: 8px !important;
+  padding: 8px 12px !important;
+  min-height: 44px !important;
+}
+
+/* 移除内部边框 */
+[data-theme="light"] .dark-select .vs__selected-options,
+[data-theme="light"] .filter-select .vs__selected-options,
+[data-theme="light"] .dialog-select .vs__selected-options,
+[data-theme="light"] .location-select .vs__selected-options,
+[data-theme="light"] :deep(.v-select .vs__selected-options),
+[data-theme="light"] :deep(.dark-select .vs__selected-options) {
+  border: none !important;
+  background: transparent !important;
+}
+
+/* 移除所有内部元素的边框和背景 */
+[data-theme="light"] .dark-select .vs__actions,
+[data-theme="light"] .filter-select .vs__actions,
+[data-theme="light"] .dialog-select .vs__actions,
+[data-theme="light"] .location-select .vs__actions,
+[data-theme="light"] :deep(.v-select .vs__actions),
+[data-theme="light"] :deep(.dark-select .vs__actions) {
+  border: none !important;
+  background: transparent !important;
+}
+
+/* 确保搜索框没有边框 */
+[data-theme="light"] .dark-select .vs__search,
+[data-theme="light"] .filter-select .vs__search,
+[data-theme="light"] .dialog-select .vs__search,
+[data-theme="light"] .location-select .vs__search,
+[data-theme="light"] :deep(.v-select .vs__search),
+[data-theme="light"] :deep(.dark-select .vs__search) {
+  border: none !important;
+  background: transparent !important;
+  margin: 0 !important;
+}
+
+/* 下拉框选中的值 */
+[data-theme="light"] .dark-select .vs__selected,
+[data-theme="light"] .filter-select .vs__selected,
+[data-theme="light"] .dialog-select .vs__selected,
+[data-theme="light"] .location-select .vs__selected,
+[data-theme="light"] :deep(.v-select .vs__selected),
+[data-theme="light"] :deep(.dark-select .vs__selected) {
+  color: #1a1a1a !important;
+  font-weight: 600 !important;
+}
+
+/* 下拉框占位符 */
+[data-theme="light"] .dark-select .vs__search::placeholder,
+[data-theme="light"] .filter-select .vs__search::placeholder,
+[data-theme="light"] .dialog-select .vs__search::placeholder,
+[data-theme="light"] .location-select .vs__search::placeholder,
+[data-theme="light"] :deep(.v-select .vs__search::placeholder),
+[data-theme="light"] :deep(.dark-select .vs__search::placeholder) {
+  color: #BFBFBF !important;
+}
+
+/* 下拉框搜索输入 */
+[data-theme="light"] .dark-select .vs__search,
+[data-theme="light"] .filter-select .vs__search,
+[data-theme="light"] .dialog-select .vs__search,
+[data-theme="light"] .location-select .vs__search,
+[data-theme="light"] :deep(.v-select .vs__search),
+[data-theme="light"] :deep(.dark-select .vs__search) {
+  color: #1a1a1a !important;
+  border: none !important;
+  background: transparent !important;
+}
+
+/* 下拉框箭头图标 */
+[data-theme="light"] .dark-select .vs__open-indicator,
+[data-theme="light"] .filter-select .vs__open-indicator,
+[data-theme="light"] .dialog-select .vs__open-indicator,
+[data-theme="light"] .location-select .vs__open-indicator,
+[data-theme="light"] :deep(.v-select .vs__open-indicator),
+[data-theme="light"] :deep(.dark-select .vs__open-indicator) {
+  fill: #666666 !important;
+}
+
+/* 下拉框清除按钮 */
+[data-theme="light"] .dark-select .vs__clear,
+[data-theme="light"] .filter-select .vs__clear,
+[data-theme="light"] .dialog-select .vs__clear,
+[data-theme="light"] .location-select .vs__clear,
+[data-theme="light"] :deep(.v-select .vs__clear),
+[data-theme="light"] :deep(.dark-select .vs__clear) {
+  fill: #999999 !important;
+}
+
+/* 下拉菜单 */
+[data-theme="light"] .dark-select .vs__dropdown-menu,
+[data-theme="light"] .filter-select .vs__dropdown-menu,
+[data-theme="light"] .dialog-select .vs__dropdown-menu,
+[data-theme="light"] .location-select .vs__dropdown-menu,
+[data-theme="light"] :deep(.v-select .vs__dropdown-menu),
+[data-theme="light"] :deep(.dark-select .vs__dropdown-menu) {
+  background: #FFFFFF !important;
+  border: 2px solid #D9D9D9 !important;
+  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1) !important;
+}
+
+/* 下拉菜单选项 */
+[data-theme="light"] .dark-select .vs__dropdown-option,
+[data-theme="light"] .filter-select .vs__dropdown-option,
+[data-theme="light"] .dialog-select .vs__dropdown-option,
+[data-theme="light"] .location-select .vs__dropdown-option,
+[data-theme="light"] :deep(.v-select .vs__dropdown-option),
+[data-theme="light"] :deep(.dark-select .vs__dropdown-option) {
+  color: #1a1a1a !important;
+  font-weight: 600 !important;
+}
+
+/* 下拉菜单选项悬停 */
+[data-theme="light"] .dark-select .vs__dropdown-option--highlight,
+[data-theme="light"] .filter-select .vs__dropdown-option--highlight,
+[data-theme="light"] .dialog-select .vs__dropdown-option--highlight,
+[data-theme="light"] .location-select .vs__dropdown-option--highlight,
+[data-theme="light"] :deep(.v-select .vs__dropdown-option--highlight),
+[data-theme="light"] :deep(.dark-select .vs__dropdown-option--highlight) {
+  background: rgba(24, 144, 255, 0.1) !important;
+  color: #1890FF !important;
+}
+
+/* 下拉菜单选项选中 */
+[data-theme="light"] .dark-select .vs__dropdown-option--selected,
+[data-theme="light"] .filter-select .vs__dropdown-option--selected,
+[data-theme="light"] .dialog-select .vs__dropdown-option--selected,
+[data-theme="light"] .location-select .vs__dropdown-option--selected,
+[data-theme="light"] :deep(.v-select .vs__dropdown-option--selected),
+[data-theme="light"] :deep(.dark-select .vs__dropdown-option--selected) {
+  background: rgba(24, 144, 255, 0.15) !important;
+  color: #1890FF !important;
+  font-weight: 700 !important;
+}
+
+/* 无选项提示 */
+[data-theme="light"] .dark-select .vs__no-options,
+[data-theme="light"] .filter-select .vs__no-options,
+[data-theme="light"] .dialog-select .vs__no-options,
+[data-theme="light"] .location-select .vs__no-options,
+[data-theme="light"] :deep(.v-select .vs__no-options),
+[data-theme="light"] :deep(.dark-select .vs__no-options) {
+  color: #999999 !important;
+}
+
+/* 聚焦状态 */
+[data-theme="light"] .dark-select.vs--open .vs__dropdown-toggle,
+[data-theme="light"] .filter-select.vs--open .vs__dropdown-toggle,
+[data-theme="light"] .dialog-select.vs--open .vs__dropdown-toggle,
+[data-theme="light"] .location-select.vs--open .vs__dropdown-toggle,
+[data-theme="light"] :deep(.v-select.vs--open .vs__dropdown-toggle),
+[data-theme="light"] :deep(.dark-select.vs--open .vs__dropdown-toggle) {
+  border-color: #1890FF !important;
+  box-shadow: 0 0 8px rgba(24, 144, 255, 0.25) !important;
+}
+
+/* ========== 明亮主题 - 密码修改弹窗 ========== */
+[data-theme="light"] .home-page .modal-header {
+  border-bottom: 1px solid #E0E0E0 !important;
+  background: linear-gradient(90deg, rgba(24, 144, 255, 0.05) 0%, rgba(24, 144, 255, 0.1) 50%, rgba(24, 144, 255, 0.05) 100%) !important;
+}
+
+[data-theme="light"] .home-page .modal-header h3 {
+  color: #1a1a1a !important;
+}
+
+[data-theme="light"] .home-page .close-btn {
+  color: #666666 !important;
+  background: transparent !important;
+}
+
+[data-theme="light"] .home-page .close-btn:hover {
+  background: rgba(0, 0, 0, 0.05) !important;
+  color: #1a1a1a !important;
+}
+
+[data-theme="light"] .home-page .form-group label {
+  color: #666666 !important;
+  font-weight: 600 !important;
+}
+
+[data-theme="light"] .home-page .form-input {
+  background: #FFFFFF !important;
+  border: 1px solid #D9D9D9 !important;
+  color: #1a1a1a !important;
+}
+
+[data-theme="light"] .home-page .form-input:focus {
+  border-color: #1890FF !important;
+  box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2) !important;
+}
+
+[data-theme="light"] .home-page .form-input::placeholder {
+  color: #BFBFBF !important;
+}
+
+[data-theme="light"] .home-page .password-toggle {
+  color: #666666 !important;
+}
+
+[data-theme="light"] .home-page .password-toggle:hover {
+  color: #1890FF !important;
+}
+
+[data-theme="light"] .home-page .dialog-footer {
+  border-top: 1px solid #E0E0E0 !important;
+  background: rgba(248, 250, 255, 0.5) !important;
+}
+
+[data-theme="light"] .home-page .close-action-btn {
+  background: #F5F5F5 !important;
+  color: #666666 !important;
+  border: 1px solid #D9D9D9 !important;
+}
+
+[data-theme="light"] .home-page .close-action-btn:hover {
+  background: #E8E8E8 !important;
+}
+
+[data-theme="light"] .home-page .primary-btn {
+  background: linear-gradient(90deg, #1890FF 0%, #0066FF 100%) !important;
+  color: #ffffff !important;
+}
+
+[data-theme="light"] .home-page .primary-btn:hover {
+  box-shadow: 0 4px 12px rgba(24, 144, 255, 0.4) !important;
+}
+
+/* ========== 明亮主题 - Vue-Select 下拉框样式 ========== */
+[data-theme="light"] .v-select .vs__dropdown-toggle,
+[data-theme="light"] .dark-select .vs__dropdown-toggle,
+[data-theme="light"] .filter-select .vs__dropdown-toggle,
+[data-theme="light"] .dialog-select .vs__dropdown-toggle {
+  background: #FFFFFF !important;
+  border: 1px solid #D9D9D9 !important;
+}
+
+[data-theme="light"] .v-select .vs__selected,
+[data-theme="light"] .dark-select .vs__selected,
+[data-theme="light"] .filter-select .vs__selected,
+[data-theme="light"] .dialog-select .vs__selected {
+  color: #1a1a1a !important;
+}
+
+[data-theme="light"] .v-select .vs__search,
+[data-theme="light"] .dark-select .vs__search,
+[data-theme="light"] .filter-select .vs__search,
+[data-theme="light"] .dialog-select .vs__search {
+  color: #1a1a1a !important;
+}
+
+[data-theme="light"] .v-select .vs__search::placeholder,
+[data-theme="light"] .dark-select .vs__search::placeholder,
+[data-theme="light"] .filter-select .vs__search::placeholder,
+[data-theme="light"] .dialog-select .vs__search::placeholder {
+  color: #BFBFBF !important;
+}
+
+[data-theme="light"] .v-select .vs__actions svg,
+[data-theme="light"] .dark-select .vs__actions svg,
+[data-theme="light"] .filter-select .vs__actions svg,
+[data-theme="light"] .dialog-select .vs__actions svg {
+  fill: #666666 !important;
+}
+
+[data-theme="light"] .v-select .vs__clear svg,
+[data-theme="light"] .dark-select .vs__clear svg,
+[data-theme="light"] .filter-select .vs__clear svg,
+[data-theme="light"] .dialog-select .vs__clear svg {
+  fill: #666666 !important;
+}
+
+/* 下拉菜单样式 */
+[data-theme="light"] .v-select .vs__dropdown-menu,
+[data-theme="light"] .dark-select .vs__dropdown-menu,
+[data-theme="light"] .filter-select .vs__dropdown-menu,
+[data-theme="light"] .dialog-select .vs__dropdown-menu,
+[data-theme="light"] .vs__dropdown-menu {
+  background: #FFFFFF !important;
+  border: 1px solid #D9D9D9 !important;
+  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15) !important;
+}
+
+[data-theme="light"] .vs__dropdown-menu .vs__dropdown-option,
+[data-theme="light"] .v-select .vs__dropdown-option,
+[data-theme="light"] .dark-select .vs__dropdown-option,
+[data-theme="light"] .filter-select .vs__dropdown-option,
+[data-theme="light"] .dialog-select .vs__dropdown-option {
+  color: #1a1a1a !important;
+}
+
+[data-theme="light"] .vs__dropdown-menu .vs__dropdown-option:hover,
+[data-theme="light"] .vs__dropdown-menu .vs__dropdown-option--highlight,
+[data-theme="light"] .v-select .vs__dropdown-option--highlight,
+[data-theme="light"] .dark-select .vs__dropdown-option--highlight,
+[data-theme="light"] .filter-select .vs__dropdown-option--highlight,
+[data-theme="light"] .dialog-select .vs__dropdown-option--highlight {
+  background: #E6F7FF !important;
+  color: #1890FF !important;
+}
+
+[data-theme="light"] .vs__dropdown-menu .vs__no-options,
+[data-theme="light"] .v-select .vs__no-options,
+[data-theme="light"] .dark-select .vs__no-options,
+[data-theme="light"] .filter-select .vs__no-options,
+[data-theme="light"] .dialog-select .vs__no-options {
+  color: #BFBFBF !important;
+}
+
+/* ========== 明亮主题 - 通用按钮样式 ========== */
+[data-theme="light"] .btn-primary {
+  background: linear-gradient(90deg, #1890FF 0%, #0066FF 100%);
+  box-shadow: 0 2px 8px rgba(24, 144, 255, 0.3);
+}
+
+[data-theme="light"] .btn-primary:hover {
+  box-shadow: 0 4px 12px rgba(24, 144, 255, 0.4);
+  transform: translateY(-2px);
+}
+
+[data-theme="light"] .btn-secondary {
+  background: #F5F5F5;
+  border: 1px solid #D9D9D9;
+  color: #666666;
+}
+
+[data-theme="light"] .btn-secondary:hover {
+  background: #E8E8E8;
+  border-color: #BFBFBF;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+}
+
+[data-theme="light"] .btn-danger {
+  background: linear-gradient(90deg, #FF4D4F 0%, #F5222D 100%);
+  box-shadow: 0 2px 8px rgba(255, 77, 79, 0.3);
+}
+
+[data-theme="light"] .btn-danger:hover {
+  box-shadow: 0 4px 12px rgba(255, 77, 79, 0.4);
+  transform: translateY(-2px);
+}
+
+/* ========== 明亮主题 - 首页特定样式 ========== */
+/* 首页标题 */
+[data-theme="light"] .home-page .title {
+  color: #1a1a1a;
+  text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+
+/* 用户徽章 */
+[data-theme="light"] .home-page .user-badge {
+  background: linear-gradient(90deg, #1890FF 0%, #0066FF 100%);
+  border: 1px solid #0066FF;
+  box-shadow: 0 2px 8px rgba(24, 144, 255, 0.3);
+}
+
+[data-theme="light"] .home-page .user-icon {
+  color: #ffffff;
+}
+
+[data-theme="light"] .home-page .username {
+  color: #ffffff;
+}
+
+/* 退出按钮 */
+[data-theme="light"] .home-page .exit-btn {
+  background: linear-gradient(90deg, #1890FF 0%, #0066FF 100%);
+  box-shadow: 0 2px 8px rgba(24, 144, 255, 0.3);
+}
+
+[data-theme="light"] .home-page .exit-btn:hover {
+  box-shadow: 0 4px 12px rgba(24, 144, 255, 0.4);
+}
+
+/* 下拉菜单 */
+[data-theme="light"] .home-page .dropdown-menu {
+  background: #FFFFFF;
+  border: 1px solid #E0E0E0;
+  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
+}
+
+[data-theme="light"] .home-page .dropdown-item {
+  color: #1a1a1a;
+}
+
+[data-theme="light"] .home-page .dropdown-item:hover {
+  background: #E6F7FF;
+}
+
+[data-theme="light"] .home-page .dropdown-item i {
+  color: #1890FF;
+}
+
+/* 统计卡片 */
+[data-theme="light"] .home-page .stat-label {
+  color: #1a1a1a;
+  font-weight: 500;
+}
+
+[data-theme="light"] .home-page .stat-value {
+  color: #1890FF;
+  font-weight: 600;
+}
+
+/* 操作按钮区域 */
+[data-theme="light"] .home-page .buttons-section {
+  background: rgba(255, 255, 255, 0.9);
+  border: 1px solid #E0E0E0;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+}
+
+[data-theme="light"] .home-page .btn-text {
+  color: #1a1a1a;
+  font-weight: 600;
+}
+
+/* 表格区域 */
+[data-theme="light"] .home-page .table-section {
+  background: rgba(255, 255, 255, 0.95);
+  border: 1px solid #E0E0E0;
+}
+
+[data-theme="light"] .home-page :deep(.dv-scroll-board .header) {
+  color: #1890FF !important;
+  background: linear-gradient(90deg, rgba(24, 144, 255, 0.05) 0%, rgba(24, 144, 255, 0.15) 50%, rgba(24, 144, 255, 0.05) 100%) !important;
+}
+
+[data-theme="light"] .home-page :deep(.dv-scroll-board .rows .row-item) {
+  color: #1a1a1a !important;
+}
+
+[data-theme="light"] .home-page :deep(.dv-scroll-board .rows .ceil) {
+  background: rgba(248, 248, 248, 0.5) !important;
+}
+
+[data-theme="light"] .home-page :deep(.dv-scroll-board .rows .ceil:nth-child(even)) {
+  background: rgba(255, 255, 255, 0.8) !important;
+}
+
+/* 异常停泊区提示卡片 */
+[data-theme="light"] .home-page .abnormal-card {
+  background: #FFFFFF;
+  border: 1px solid #FFD666;
+  box-shadow: 0 4px 12px rgba(255, 193, 7, 0.2);
+}
+
+[data-theme="light"] .home-page .abnormal-card-header h3 {
+  color: #FA8C16;
+  text-shadow: none;
+}
+
+[data-theme="light"] .home-page .abnormal-card-content p {
+  color: #666666;
+}
+
+[data-theme="light"] .home-page .know-btn {
+  background: #F5F5F5;
+  color: #666666;
+  border: 1px solid #D9D9D9;
+}
+
+[data-theme="light"] .home-page .know-btn:hover {
+  background: #E8E8E8;
+  color: #1a1a1a;
+}
+
+[data-theme="light"] .home-page .go-btn {
+  background: linear-gradient(90deg, #FA8C16 0%, #FFA940 100%);
+  color: #fff;
+}
+
+[data-theme="light"] .home-page .go-btn:hover {
+  box-shadow: 0 4px 12px rgba(250, 140, 22, 0.4);
+}
+
+/* 密码修改弹窗 */
+[data-theme="light"] .home-page .modal-header {
+  border-bottom: 1px solid #E0E0E0;
+}
+
+[data-theme="light"] .home-page .modal-header h3 {
+  color: #1a1a1a;
+}
+
+[data-theme="light"] .home-page .close-btn {
+  color: #666666;
+}
+
+[data-theme="light"] .home-page .close-btn:hover {
+  background: rgba(0, 0, 0, 0.05);
+  color: #1a1a1a;
+}
+
+[data-theme="light"] .home-page .form-group label {
+  color: #666666;
+}
+
+[data-theme="light"] .home-page .form-input {
+  background: #FFFFFF;
+  border: 1px solid #D9D9D9;
+  color: #1a1a1a;
+}
+
+[data-theme="light"] .home-page .form-input:focus {
+  border-color: #1890FF;
+  box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
+}
+
+[data-theme="light"] .home-page .form-input::placeholder {
+  color: #BFBFBF;
+}
+
+[data-theme="light"] .home-page .password-toggle {
+  color: #666666;
+}
+
+[data-theme="light"] .home-page .password-toggle:hover {
+  color: #1890FF;
+}
+
+[data-theme="light"] .home-page .dialog-footer {
+  border-top: 1px solid #E0E0E0;
+}
+
+[data-theme="light"] .home-page .close-action-btn {
+  background: #F5F5F5;
+  color: #666666;
+  border: 1px solid #D9D9D9;
+}
+
+[data-theme="light"] .home-page .close-action-btn:hover {
+  background: #E8E8E8;
+}
+
+[data-theme="light"] .home-page .primary-btn {
+  background: linear-gradient(90deg, #1890FF 0%, #0066FF 100%);
+  color: #ffffff;
+}
+
+[data-theme="light"] .home-page .primary-btn:hover {
+  box-shadow: 0 4px 12px rgba(24, 144, 255, 0.4);
+}
+
+/* ========== 明亮主题 - 指纹登录页面 ========== */
+[data-theme="light"] .fingerprint-login-page .action-btn {
+  background: linear-gradient(90deg, #1890FF 0%, #0066FF 100%);
+  border: 1px solid #0066FF;
+  color: #fff;
+  box-shadow: 0 2px 8px rgba(24, 144, 255, 0.3);
+}
+
+[data-theme="light"] .fingerprint-login-page .action-btn:hover {
+  background: linear-gradient(90deg, #0066FF 0%, #0050DD 100%);
+  box-shadow: 0 4px 12px rgba(24, 144, 255, 0.4);
+}
+
+[data-theme="light"] .fingerprint-login-page .action-btn i {
+  color: #ffffff;
+}
+
+[data-theme="light"] .fingerprint-login-page .status-circle {
+  background: rgba(255, 255, 255, 0.95);
+  border: 3px solid #E0E0E0;
+  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
+}
+
+[data-theme="light"] .fingerprint-login-page .status-circle.recognizing {
+  border-color: #1890FF;
+  box-shadow: 0 8px 24px rgba(24, 144, 255, 0.3);
+}
+
+[data-theme="light"] .fingerprint-login-page .status-circle.success {
+  border-color: #52C41A;
+  box-shadow: 0 8px 24px rgba(82, 196, 26, 0.3);
+}
+
+[data-theme="light"] .fingerprint-login-page .status-circle.failed {
+  border-color: #FF4D4F;
+  box-shadow: 0 8px 24px rgba(255, 77, 79, 0.3);
+}
+
+[data-theme="light"] .fingerprint-login-page .fingerprint-svg {
+  color: #1890FF;
+}
+
+[data-theme="light"] .fingerprint-login-page .status-circle.success .fingerprint-svg {
+  color: #52C41A;
+}
+
+[data-theme="light"] .fingerprint-login-page .status-circle.failed .fingerprint-svg {
+  color: #FF4D4F;
+}
+
+[data-theme="light"] .fingerprint-login-page .scan-line {
+  background: linear-gradient(180deg, transparent 0%, #1890FF 50%, transparent 100%);
+}
+
+[data-theme="light"] .fingerprint-login-page .status-text {
+  color: #1a1a1a;
+}
+
+[data-theme="light"] .fingerprint-login-page .status-circle.recognizing .status-text {
+  color: #1890FF;
+}
+
+[data-theme="light"] .fingerprint-login-page .status-circle.success .status-text {
+  color: #52C41A;
+}
+
+[data-theme="light"] .fingerprint-login-page .status-circle.failed .status-text {
+  color: #FF4D4F;
+}
+
+[data-theme="light"] .fingerprint-login-page .user-info-card {
+  background: rgba(255, 255, 255, 0.95);
+  border: 1px solid #E0E0E0;
+  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+}
+
+[data-theme="light"] .fingerprint-login-page .user-name {
+  color: #1a1a1a;
+}
+
+[data-theme="light"] .fingerprint-login-page .user-role {
+  color: #666666;
+}
+
+/* ========== 明亮主题 - 密码登录页面 ========== */
+[data-theme="light"] .login-page .login-card {
+  background: #FFFFFF;
+  border: 1px solid #E0E0E0;
+  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
+}
+
+[data-theme="light"] .login-page .login-title {
+  color: #1a1a1a;
+}
+
+[data-theme="light"] .login-page .login-subtitle {
+  color: #666666;
+}
+
+[data-theme="light"] .login-page .form-label {
+  color: #666666;
+}
+
+[data-theme="light"] .login-page .form-input {
+  background: #FFFFFF;
+  border: 1px solid #D9D9D9;
+  color: #1a1a1a;
+}
+
+[data-theme="light"] .login-page .form-input:focus {
+  border-color: #1890FF;
+  box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
+}
+
+[data-theme="light"] .login-page .form-input::placeholder {
+  color: #BFBFBF;
+}
+
+[data-theme="light"] .login-page .login-btn {
+  background: linear-gradient(90deg, #1890FF 0%, #0066FF 100%);
+  box-shadow: 0 2px 8px rgba(24, 144, 255, 0.3);
+}
+
+[data-theme="light"] .login-page .login-btn:hover {
+  box-shadow: 0 4px 12px rgba(24, 144, 255, 0.4);
+}
+
+[data-theme="light"] .login-page .fingerprint-login-link {
+  color: #1890FF;
+}
+
+[data-theme="light"] .login-page .fingerprint-login-link:hover {
+  color: #0066FF;
+}
+
+/* ========== 明亮主题 - Vant 组件覆盖 ========== */
+[data-theme="light"] .van-notify--success {
+  background: #52C41A;
+}
+
+[data-theme="light"] .van-notify--danger {
+  background: #FF4D4F;
+}
+
+[data-theme="light"] .van-notify--warning {
+  background: #FA8C16;
+}
+
+[data-theme="light"] .van-notify--primary {
+  background: #1890FF;
+}
+
+/* ========== 明亮主题 - 业务页面通用样式 ========== */
+/* 领料、出库、入库等页面 */
+[data-theme="light"] .stock-requisition-page,
+[data-theme="light"] .stock-out-page,
+[data-theme="light"] .stock-in-page,
+[data-theme="light"] .order-picking-page {
+  background: linear-gradient(180deg, #E8F4FF 0%, #F0F8FF 50%, #FFFFFF 100%);
+}
+
+/* 筛选区域 */
+[data-theme="light"] .filter-section {
+  background: rgba(255, 255, 255, 0.98) !important;
+  border: 2px solid rgba(24, 144, 255, 0.2) !important;
+  box-shadow: 0 4px 12px rgba(24, 144, 255, 0.1) !important;
+}
+
+[data-theme="light"] .filter-label {
+  color: #1a1a1a !important;
+  font-weight: 700 !important;
+}
+
+[data-theme="light"] .filter-input,
+[data-theme="light"] .filter-input.dark-input {
+  background: #FFFFFF !important;
+  border: 2px solid #D9D9D9 !important;
+  color: #1a1a1a !important;
+  font-weight: 500 !important;
+}
+
+[data-theme="light"] .filter-input:focus,
+[data-theme="light"] .filter-input.dark-input:focus {
+  border-color: #1890FF !important;
+  box-shadow: 0 0 0 3px rgba(24, 144, 255, 0.15) !important;
+}
+
+[data-theme="light"] .filter-input::placeholder,
+[data-theme="light"] .filter-input.dark-input::placeholder {
+  color: #BFBFBF !important;
+}
+
+[data-theme="light"] .search-btn {
+  background: linear-gradient(90deg, #1890FF 0%, #0066FF 100%) !important;
+  box-shadow: 0 4px 12px rgba(24, 144, 255, 0.4) !important;
+  color: #ffffff !important;
+  font-weight: 700 !important;
+}
+
+[data-theme="light"] .search-btn:hover {
+  box-shadow: 0 6px 16px rgba(24, 144, 255, 0.5) !important;
+}
+
+[data-theme="light"] .reset-btn {
+  background: rgba(255, 255, 255, 0.9) !important;
+  border: 2px solid #1890FF !important;
+  color: #1890FF !important;
+  font-weight: 700 !important;
+}
+
+[data-theme="light"] .reset-btn:hover {
+  background: rgba(24, 144, 255, 0.1) !important;
+  box-shadow: 0 4px 12px rgba(24, 144, 255, 0.3) !important;
+}
+
+/* 全选控制栏 */
+[data-theme="light"] .select-all-bar {
+  background: rgba(230, 247, 255, 0.9) !important;
+  border: 2px solid rgba(24, 144, 255, 0.3) !important;
+  box-shadow: 0 2px 8px rgba(24, 144, 255, 0.1) !important;
+}
+
+[data-theme="light"] .select-all-text {
+  color: #1a1a1a !important;
+  font-weight: 700 !important;
+}
+
+[data-theme="light"] .select-all-bar .van-checkbox__label {
+  color: #1a1a1a !important;
+  font-weight: 600 !important;
+}
+
+/* Vue Select 明亮主题 */
+[data-theme="light"] .dark-select .vs__dropdown-toggle,
+[data-theme="light"] :deep(.dark-select .vs__dropdown-toggle) {
+  background: #FFFFFF !important;
+  border: 2px solid #D9D9D9 !important;
+}
+
+[data-theme="light"] .dark-select .vs__selected,
+[data-theme="light"] :deep(.dark-select .vs__selected) {
+  color: #1a1a1a !important;
+}
+
+[data-theme="light"] .dark-select .vs__search,
+[data-theme="light"] :deep(.dark-select .vs__search) {
+  color: #1a1a1a !important;
+}
+
+[data-theme="light"] .dark-select .vs__search::placeholder,
+[data-theme="light"] :deep(.dark-select .vs__search::placeholder) {
+  color: #BFBFBF !important;
+}
+
+[data-theme="light"] .dark-select .vs__dropdown-menu,
+[data-theme="light"] :deep(.dark-select .vs__dropdown-menu) {
+  background: #FFFFFF !important;
+  border: 2px solid #D9D9D9 !important;
+}
+
+[data-theme="light"] .dark-select .vs__dropdown-option,
+[data-theme="light"] :deep(.dark-select .vs__dropdown-option) {
+  color: #1a1a1a !important;
+}
+
+[data-theme="light"] .dark-select .vs__dropdown-option--highlight,
+[data-theme="light"] :deep(.dark-select .vs__dropdown-option--highlight) {
+  background: rgba(24, 144, 255, 0.1) !important;
+  color: #1890FF !important;
+}
+
+/* 物料卡片 */
+
+[data-theme="light"] .stats-text {
+  color: black !important;
+}
+[data-theme="light"] .inventory-card {
+  background: rgba(255, 255, 255, 0.98) !important;
+  border: 2px solid rgba(24, 144, 255, 0.2) !important;
+  box-shadow: 0 4px 12px rgba(24, 144, 255, 0.1) !important;
+}
+
+[data-theme="light"] .inventory-card:hover {
+  border-color: rgba(24, 144, 255, 0.5) !important;
+  box-shadow: 0 6px 20px rgba(24, 144, 255, 0.25) !important;
+}
+
+[data-theme="light"] .inventory-card.selected {
+  border-color: #1890FF !important;
+  box-shadow: 0 8px 24px rgba(24, 144, 255, 0.35) !important;
+  background: rgba(230, 247, 255, 0.98) !important;
+}
+
+[data-theme="light"] .inventory-card.completed {
+  border-color: #52C41A !important;
+  box-shadow: 0 6px 20px rgba(82, 196, 26, 0.25) !important;
+  background: rgba(246, 255, 237, 0.98) !important;
+}
+
+[data-theme="light"] .card-index {
+  background: linear-gradient(135deg, #1890FF 0%, #0066FF 100%) !important;
+  color: #ffffff !important;
+  box-shadow: 0 2px 8px rgba(24, 144, 255, 0.4) !important;
+}
+
+[data-theme="light"] .card-index.completed {
+  background: linear-gradient(135deg, #52C41A 0%, #73D13D 100%) !important;
+}
+
+[data-theme="light"] .card-info {
+  background: rgba(248, 250, 255, 0.9) !important;
+}
+
+[data-theme="light"] .info-label {
+  color: #666666 !important;
+  font-weight: 600 !important;
+}
+
+[data-theme="light"] .info-value {
+  color: #1a1a1a !important;
+  font-weight: 700 !important;
+}
+
+[data-theme="light"] .selected-indicator {
+  background: linear-gradient(135deg, #52C41A 0%, #389E0D 100%) !important;
+  color: #ffffff !important;
+  box-shadow: 0 2px 8px rgba(82, 196, 26, 0.5) !important;
+}
+
+/* 选中指示器内的图标 - 强制白色 */
+[data-theme="light"] .selected-indicator i,
+[data-theme="light"] .selected-indicator .fa,
+[data-theme="light"] .selected-indicator .fas,
+[data-theme="light"] .selected-indicator .fa-check {
+  color: #ffffff !important;
+  opacity: 1 !important;
+}
+
+/* 确保图标在所有状态下都是白色 */
+[data-theme="light"] .inventory-card.selected .selected-indicator i,
+[data-theme="light"] .material-card.selected .selected-indicator i {
+  color: #ffffff !important;
+}
+
+/* ========== 明亮主题 - 配送方式按钮 ========== */
+/* 配送区域背景 */
+[data-theme="light"] .card-delivery-section {
+  background: rgba(230, 247, 255, 0.6) !important;
+  border-top: 1px solid rgba(24, 144, 255, 0.2) !important;
+}
+
+/* 配送方式按钮 */
+[data-theme="light"] .delivery-btn {
+  background: #FFFFFF !important;
+  border: 2px solid #D9D9D9 !important;
+  color: #666666 !important;
+  font-weight: 600 !important;
+}
+
+[data-theme="light"] .delivery-btn i,
+[data-theme="light"] .delivery-btn .fas,
+[data-theme="light"] .delivery-btn .fa {
+  color: #666666 !important;
+}
+
+/* 配送方式按钮 - 激活状态 */
+[data-theme="light"] .delivery-btn.active {
+  background: linear-gradient(90deg, #1890FF 0%, #0066FF 100%) !important;
+  border: 2px solid #1890FF !important;
+  color: #ffffff !important;
+  box-shadow: 0 2px 8px rgba(24, 144, 255, 0.3) !important;
+}
+
+[data-theme="light"] .delivery-btn.active i,
+[data-theme="light"] .delivery-btn.active .fas,
+[data-theme="light"] .delivery-btn.active .fa {
+  color: #ffffff !important;
+  opacity: 1 !important;
+}
+
+/* 配送方式按钮 - 悬停状态 */
+[data-theme="light"] .delivery-btn:hover:not(.disabled):not(.active) {
+  background: rgba(24, 144, 255, 0.1) !important;
+  border-color: #1890FF !important;
+  color: #1890FF !important;
+}
+
+[data-theme="light"] .delivery-btn:hover:not(.disabled):not(.active) i,
+[data-theme="light"] .delivery-btn:hover:not(.disabled):not(.active) .fas,
+[data-theme="light"] .delivery-btn:hover:not(.disabled):not(.active) .fa {
+  color: #1890FF !important;
+}
+
+/* 配送方式按钮 - 禁用状态 */
+[data-theme="light"] .delivery-btn.disabled {
+  background: #F5F5F5 !important;
+  border-color: #E8E8E8 !important;
+  color: #BFBFBF !important;
+  opacity: 0.6 !important;
+}
+
+[data-theme="light"] .delivery-btn.disabled i,
+[data-theme="light"] .delivery-btn.disabled .fas,
+[data-theme="light"] .delivery-btn.disabled .fa {
+  color: #BFBFBF !important;
+}
+
+/* 配送标签 */
+[data-theme="light"] .delivery-label {
+  color: #666666 !important;
+  font-weight: 700 !important;
+}
+
+/* 配送类型徽章 */
+[data-theme="light"] .delivery-type-badge.badge-manual {
+  background: rgba(107, 114, 128, 0.15) !important;
+  border: 1px solid #9CA3AF !important;
+  color: #374151 !important;
+  font-weight: 700 !important;
+}
+
+[data-theme="light"] .delivery-type-badge.badge-agv-force {
+  background: rgba(234, 88, 12, 0.15) !important;
+  border: 1px solid #F97316 !important;
+  color: #c2410c !important;
+  font-weight: 700 !important;
+}
+
+[data-theme="light"] .delivery-type-badge.badge-agv-optional {
+  background: rgba(16, 185, 129, 0.15) !important;
+  border: 1px solid #10B981 !important;
+  color: #059669 !important;
+  font-weight: 700 !important;
+}
+
+/* 人工配送文本 */
+[data-theme="light"] .delivery-location-row span {
+  color: #1890FF !important;
+  font-weight: 700 !important;
+}
+
+[data-theme="light"] .reset-btn {
+  background: #F5F5F5;
+  border: 1px solid #D9D9D9;
+  color: #666666;
+}
+
+[data-theme="light"] .reset-btn:hover {
+  background: #E8E8E8;
+  border-color: #BFBFBF;
+}
+
+/* 物料卡片 */
+[data-theme="light"] .material-card,
+[data-theme="light"] .inventory-card {
+  background: rgba(255, 255, 255, 0.98) !important;
+  border: 2px solid rgba(24, 144, 255, 0.2) !important;
+  box-shadow: 0 4px 12px rgba(24, 144, 255, 0.1) !important;
+}
+
+[data-theme="light"] .material-card:hover,
+[data-theme="light"] .inventory-card:hover {
+  border-color: rgba(24, 144, 255, 0.5) !important;
+  box-shadow: 0 6px 20px rgba(24, 144, 255, 0.25) !important;
+}
+
+[data-theme="light"] .material-card.selected,
+[data-theme="light"] .inventory-card.selected {
+  border-color: #1890FF !important;
+  box-shadow: 0 8px 24px rgba(24, 144, 255, 0.35) !important;
+  background: rgba(230, 247, 255, 0.98) !important;
+}
+
+[data-theme="light"] .material-card.completed,
+[data-theme="light"] .inventory-card.completed {
+  border-color: #52C41A !important;
+  box-shadow: 0 6px 20px rgba(82, 196, 26, 0.25) !important;
+  background: rgba(246, 255, 237, 0.98) !important;
+}
+
+[data-theme="light"] .card-info {
+  background: rgba(248, 250, 255, 0.9) !important;
+}
+
+[data-theme="light"] .info-label {
+  color: #666666 !important;
+  font-weight: 600 !important;
+}
+
+[data-theme="light"] .info-value {
+  color: #1a1a1a !important;
+  font-weight: 700 !important;
+}
+
+/* 物料图片区域 */
+[data-theme="light"] .material-image,
+[data-theme="light"] .card-image {
+  background: rgba(248, 250, 255, 0.9) !important;
+  border: 2px solid rgba(24, 144, 255, 0.15) !important;
+}
+
+[data-theme="light"] .material-image img,
+[data-theme="light"] .card-image img {
+  filter: brightness(1) contrast(1.1) !important;
+}
+
+[data-theme="light"] .image-placeholder {
+  background: rgba(230, 247, 255, 0.5) !important;
+}
+
+/* 卡片图标 */
+[data-theme="light"] .inventory-card .card-icon,
+[data-theme="light"] .inventory-card i.fa,
+[data-theme="light"] .inventory-card i.fas {
+  color: #1890FF !important;
+}
+
+[data-theme="light"] .inventory-card.completed .card-icon,
+[data-theme="light"] .inventory-card.completed i.fa,
+[data-theme="light"] .inventory-card.completed i.fas {
+  color: #52C41A !important;
+}
+
+/* 卡片底部配送区域 - 改为浅色背景 */
+[data-theme="light"] .card-delivery-section {
+  background: rgba(230, 247, 255, 0.6) !important;
+  border-top: 2px solid rgba(24, 144, 255, 0.2) !important;
+}
+
+[data-theme="light"] .delivery-label {
+  color: #1a1a1a !important;
+  font-weight: 700 !important;
+}
+
+[data-theme="light"] .delivery-placeholder {
+  color: #1890FF !important;
+  opacity: 0.6 !important;
+}
+
+/* 配送方式按钮 */
+[data-theme="light"] .delivery-btn {
+  background: rgba(255, 255, 255, 0.9) !important;
+  border: 2px solid #D9D9D9 !important;
+  color: #666666 !important;
+  font-weight: 600 !important;
+}
+
+[data-theme="light"] .delivery-btn.active {
+  background: linear-gradient(90deg, #1890FF 0%, #0066FF 100%) !important;
+  border-color: #1890FF !important;
+  color: #ffffff !important;
+  font-weight: 700 !important;
+}
+
+[data-theme="light"] .delivery-btn.active i,
+[data-theme="light"] .delivery-btn.active .fas,
+[data-theme="light"] .delivery-btn.active .fa {
+  color: #ffffff !important;
+  opacity: 1 !important;
+}
+
+[data-theme="light"] .delivery-btn:hover:not(.disabled) {
+  border-color: #1890FF !important;
+  box-shadow: 0 2px 8px rgba(24, 144, 255, 0.3) !important;
+}
+
+[data-theme="light"] .delivery-btn.disabled {
+  opacity: 0.4 !important;
+  cursor: not-allowed !important;
+}
+
+/* 配送类型徽章 - 提高对比度 */
+[data-theme="light"] .delivery-type-badge.badge-manual {
+  background: rgba(107, 114, 128, 0.15) !important;
+  border: 2px solid #6b7280 !important;
+  color: #374151 !important;
+  font-weight: 700 !important;
+}
+
+[data-theme="light"] .delivery-type-badge.badge-agv-force {
+  background: rgba(234, 88, 12, 0.15) !important;
+  border: 2px solid #ea580c !important;
+  color: #c2410c !important;
+  font-weight: 700 !important;
+}
+
+[data-theme="light"] .delivery-type-badge.badge-agv-optional {
+  background: rgba(16, 185, 129, 0.15) !important;
+  border: 2px solid #10b981 !important;
+  color: #059669 !important;
+  font-weight: 700 !important;
+}
+
+/* 位置选择器 */
+[data-theme="light"] .location-select .vs__dropdown-toggle {
+  background: #FFFFFF !important;
+  border: 2px solid #D9D9D9 !important;
+}
+
+[data-theme="light"] .location-select .vs__selected {
+  color: #1a1a1a !important;
+  font-weight: 600 !important;
+}
+
+/* 状态标签 */
+[data-theme="light"] .status-badge {
+  font-weight: 700 !important;
+}
+
+[data-theme="light"] .status-success {
+  background: rgba(82, 196, 26, 0.15) !important;
+  color: #52C41A !important;
+  border: 1px solid rgba(82, 196, 26, 0.3) !important;
+}
+
+[data-theme="light"] .status-danger {
+  background: rgba(255, 77, 79, 0.15) !important;
+  color: #FF4D4F !important;
+  border: 1px solid rgba(255, 77, 79, 0.3) !important;
+}
+
+[data-theme="light"] .status-warning {
+  background: rgba(250, 173, 20, 0.15) !important;
+  color: #FAAD14 !important;
+  border: 1px solid rgba(250, 173, 20, 0.3) !important;
+}
+
+/* 底部操作区 */
+[data-theme="light"] .bottom-actions,
+[data-theme="light"] .footer-actions,
+[data-theme="light"] .action-footer {
+  background: rgba(255, 255, 255, 0.98) !important;
+  border-top: 2px solid rgba(24, 144, 255, 0.2) !important;
+  box-shadow: 0 -4px 12px rgba(24, 144, 255, 0.1) !important;
+  backdrop-filter: blur(10px);
+}
+
+[data-theme="light"] .submit-btn,
+[data-theme="light"] .confirm-btn {
+  background: linear-gradient(90deg, #52C41A 0%, #73D13D 100%) !important;
+  color: #ffffff !important;
+  box-shadow: 0 4px 12px rgba(82, 196, 26, 0.4) !important;
+  font-weight: 700 !important;
+}
+
+[data-theme="light"] .submit-btn:hover,
+[data-theme="light"] .confirm-btn:hover {
+  box-shadow: 0 6px 16px rgba(82, 196, 26, 0.5) !important;
+}
+
+[data-theme="light"] .material-card.selected,
+[data-theme="light"] .inventory-card.selected {
+  border-color: #1890FF;
+  background: #E6F7FF;
+}
+
+[data-theme="light"] .material-name,
+[data-theme="light"] .inventory-name {
+  color: #1a1a1a;
+}
+
+[data-theme="light"] .material-info,
+[data-theme="light"] .inventory-info {
+  color: #666666;
+}
+
+[data-theme="light"] .material-stock,
+[data-theme="light"] .inventory-stock {
+  color: #1890FF;
+  font-weight: 600;
+}
+
+[data-theme="light"] .material-stock.low-stock,
+[data-theme="light"] .inventory-stock.low-stock {
+  color: #FA8C16;
+}
+
+[data-theme="light"] .material-stock.out-of-stock,
+[data-theme="light"] .inventory-stock.out-of-stock {
+  color: #FF4D4F;
+}
+
+/* 操作按钮 */
+[data-theme="light"] .add-btn,
+[data-theme="light"] .pick-btn {
+  background: linear-gradient(90deg, #1890FF 0%, #0066FF 100%);
+  box-shadow: 0 2px 8px rgba(24, 144, 255, 0.3);
+}
+
+[data-theme="light"] .add-btn:hover,
+[data-theme="light"] .pick-btn:hover {
+  box-shadow: 0 4px 12px rgba(24, 144, 255, 0.4);
+}
+
+[data-theme="light"] .remove-btn,
+[data-theme="light"] .cancel-pick-btn {
+  background: #F5F5F5;
+  border: 1px solid #D9D9D9;
+  color: #666666;
+}
+
+[data-theme="light"] .remove-btn:hover,
+[data-theme="light"] .cancel-pick-btn:hover {
+  background: #E8E8E8;
+  border-color: #BFBFBF;
+}
+
+[data-theme="light"] .confirm-btn,
+[data-theme="light"] .submit-btn {
+  background: linear-gradient(90deg, #52C41A 0%, #73D13D 100%);
+}
+
+[data-theme="light"] .confirm-btn:hover,
+[data-theme="light"] .submit-btn:hover {
+  box-shadow: 0 4px 12px rgba(82, 196, 26, 0.4);
+}
+
+/* 数量输入框 */
+[data-theme="light"] .quantity-input {
+  background: #FFFFFF;
+  border: 1px solid #D9D9D9;
+  color: #1a1a1a;
+}
+
+[data-theme="light"] .quantity-input:focus {
+  border-color: #1890FF;
+  box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
+}
+
+/* 空状态 */
+[data-theme="light"] .empty-state {
+  color: #BFBFBF;
+}
+
+[data-theme="light"] .empty-state i {
+  color: #D9D9D9;
+}
+
+/* 加载状态 */
+[data-theme="light"] .loading-state {
+  color: #1890FF;
+}
+
+[data-theme="light"] .loading-spinner {
+  border-color: #E0E0E0;
+  border-top-color: #1890FF;
+}
+
+/* ========== 明亮主题 - 密码登录页 ========== */
+[data-theme="light"] .login-page {
+  background: linear-gradient(135deg,
+    #E8F4FF 0%,
+    #F0F8FF 50%,
+    #FFFFFF 100%) !important;
+}
+
+/* 隐藏所有深色主题的背景动画元素 */
+[data-theme="light"] .login-page .bg-layer,
+[data-theme="light"] .login-page .circuit-bg,
+[data-theme="light"] .login-page .matrix-rain,
+[data-theme="light"] .login-page .hexagon-bg,
+[data-theme="light"] .login-page .scan-lines,
+[data-theme="light"] .login-page .gradient-bg,
+[data-theme="light"] .login-page .particles-bg,
+[data-theme="light"] .login-page .geometric-bg {
+  display: none !important;
+}
+
+/* 左侧信息区 - 提高对比度 */
+[data-theme="light"] .login-page .login-left {
+  color: #1a1a1a !important;
+}
+
+[data-theme="light"] .login-page .system-title {
+  color: #1890FF !important;
+  text-shadow: 0 4px 8px rgba(24, 144, 255, 0.3) !important;
+  font-weight: 800 !important;
+  font-size: 48px !important;
+}
+
+[data-theme="light"] .login-page .system-subtitle {
+  color: #1a1a1a !important;
+  font-weight: 600 !important;
+  font-size: 20px !important;
+}
+
+[data-theme="light"] .login-page .feature-item {
+  color: #1a1a1a !important;
+  font-weight: 600 !important;
+  font-size: 18px !important;
+}
+
+[data-theme="light"] .login-page .feature-item i {
+  color: #1890FF !important;
+  font-size: 20px !important;
+}
+
+[data-theme="light"] .login-page .feature-item span {
+  color: #1a1a1a !important;
+  font-weight: 600 !important;
+}
+
+/* 右侧登录表单 - 改为白色卡片 */
+[data-theme="light"] .login-page .login-form-wrapper {
+  background: rgba(255, 255, 255, 0.98) !important;
+  border: 3px solid rgba(24, 144, 255, 0.4) !important;
+  box-shadow: 0 20px 60px rgba(24, 144, 255, 0.25),
+              0 0 40px rgba(24, 144, 255, 0.15) !important;
+  backdrop-filter: blur(10px);
+}
+
+[data-theme="light"] .login-page .form-icon {
+  background: linear-gradient(135deg, #1890FF 0%, #0066FF 100%) !important;
+  box-shadow: 0 6px 16px rgba(24, 144, 255, 0.5) !important;
+}
+
+[data-theme="light"] .login-page .form-icon i {
+  color: #ffffff !important;
+}
+
+[data-theme="light"] .login-page .form-title {
+  color: #1890FF !important;
+  font-weight: 800 !important;
+  font-size: 32px !important;
+}
+
+[data-theme="light"] .login-page .form-subtitle {
+  color: #1a1a1a !important;
+  font-weight: 600 !important;
+  font-size: 16px !important;
+}
+
+[data-theme="light"] .login-page .input-label {
+  color: #1a1a1a !important;
+  font-weight: 700 !important;
+  font-size: 16px !important;
+}
+
+[data-theme="light"] .login-page .input-wrapper {
+  background: #FFFFFF !important;
+  border: 2px solid #D9D9D9 !important;
+  border-radius: 8px !important;
+}
+
+[data-theme="light"] .login-page .dark-input {
+  background: #FFFFFF !important;
+  border: none !important;
+  color: #1a1a1a !important;
+  font-weight: 600 !important;
+  font-size: 16px !important;
+}
+
+[data-theme="light"] .login-page .input-wrapper:focus-within {
+  border-color: #1890FF !important;
+  box-shadow: 0 0 0 3px rgba(24, 144, 255, 0.2) !important;
+}
+
+[data-theme="light"] .login-page .dark-input::placeholder {
+  color: #BFBFBF !important;
+}
+
+[data-theme="light"] .login-page .input-icon {
+  color: #1890FF !important;
+  font-size: 18px !important;
+}
+
+[data-theme="light"] .login-page .password-toggle {
+  color: #1890FF !important;
+  font-size: 18px !important;
+}
+
+[data-theme="light"] .login-page .login-btn {
+  background: linear-gradient(90deg, #1890FF 0%, #0066FF 100%) !important;
+  color: #ffffff !important;
+  border: none !important;
+  box-shadow: 0 6px 16px rgba(24, 144, 255, 0.5) !important;
+  font-weight: 800 !important;
+  font-size: 18px !important;
+  letter-spacing: 4px !important;
+}
+
+[data-theme="light"] .login-page .login-btn:hover {
+  box-shadow: 0 8px 20px rgba(24, 144, 255, 0.6) !important;
+  transform: translateY(-2px) !important;
+}
+
+[data-theme="light"] .login-page .fingerprint-btn {
+  background: rgba(255, 255, 255, 0.9) !important;
+  border: 2px solid #1890FF !important;
+  color: #1890FF !important;
+  font-weight: 700 !important;
+  font-size: 16px !important;
+}
+
+[data-theme="light"] .login-page .fingerprint-btn:hover {
+  background: rgba(24, 144, 255, 0.1) !important;
+  box-shadow: 0 4px 12px rgba(24, 144, 255, 0.4) !important;
+  transform: translateY(-2px) !important;
+}
+
+/* ========== 明亮主题 - 指纹录入页 ========== */
+[data-theme="light"] .fingerprint-enroll-page {
+  background: linear-gradient(135deg,
+    #E8F4FF 0%,
+    #F0F8FF 50%,
+    #FFFFFF 100%) !important;
+}
+
+[data-theme="light"] .fingerprint-enroll-page .bg-layer {
+  background: linear-gradient(135deg,
+    #E8F4FF 0%,
+    #F0F8FF 50%,
+    #FFFFFF 100%) !important;
+  background-image: none !important;
+}
+
+/* 步骤卡片 */
+[data-theme="light"] .step-card,
+[data-theme="light"] .step-card.step-two {
+  background: rgba(255, 255, 255, 0.98) !important;
+  border: 3px solid rgba(24, 144, 255, 0.3) !important;
+  box-shadow: 0 8px 32px rgba(24, 144, 255, 0.2) !important;
+}
+
+/* 卡片头部 - 修复布局和样式 */
+[data-theme="light"] .step-card .card-header {
+  background: linear-gradient(90deg,
+    rgba(24, 144, 255, 0.08) 0%,
+    rgba(24, 144, 255, 0.15) 50%,
+    rgba(24, 144, 255, 0.08) 100%) !important;
+  border-bottom: 2px solid rgba(24, 144, 255, 0.2) !important;
+  padding: 20px !important;
+  margin: -50px -40px 30px -40px !important;
+  border-radius: 16px 16px 0 0 !important;
+  position: relative !important;
+  z-index: 1 !important;
+}
+
+/* 横屏时的 card-header 样式修复 */
+@media screen and (orientation: landscape) {
+  [data-theme="light"] .step-card .card-header {
+    margin: -20px -30px 15px -30px !important;
+    padding: 15px !important;
+  }
+
+   [data-theme="light"] .page-container {
+    margin-top: 40px !important;
+   }
+
+   /* 飞机图片 - 明亮主题只调整透明度和颜色,不改变位置 */
+[data-theme="light"] .airplane-layer {
+  height: 514px !important;
+  top: 270px !important;
+  opacity: 1 !important;
+}
+[data-theme="light"] .airplane-layer>img {
+width: 100%;
+}
+}
+
+@media screen and (orientation: portrait) {
+[data-theme="light"] .airplane-layer {
+  height: 510px !important;
+  top: 290px !important;
+  opacity: 1 !important;
+  width: 100% !important;
+}
+[data-theme="light"] .airplane-layer>img {
+width: 100%;
+/* height: 100%; */
+}
+[data-theme="light"] .page-container {
+margin-top: 36px !important;
+}
+[data-theme="light"] .header-actions-home,.user-badge-home {
+margin-top: -20px !important;
+}
+}
+
+[data-theme="light"] .step-card .step-icon {
+  background: linear-gradient(135deg, #1890FF 0%, #0066FF 100%) !important;
+  box-shadow: 0 4px 16px rgba(24, 144, 255, 0.5) !important;
+}
+
+[data-theme="light"] .step-card .step-icon.fingerprint-step {
+  background: linear-gradient(135deg, #52C41A 0%, #73D13D 100%) !important;
+  box-shadow: 0 4px 16px rgba(82, 196, 26, 0.5) !important;
+}
+
+[data-theme="light"] .step-card .step-title {
+  color: #1890FF !important;
+  font-weight: 800 !important;
+}
+
+[data-theme="light"] .step-card .step-desc {
+  color: #1a1a1a !important;
+  font-weight: 600 !important;
+}
+
+[data-theme="light"] .step-card .job-highlight {
+  color: #1890FF !important;
+  font-weight: 700 !important;
+}
+
+/* 设备状态 - 调整位置避免重叠 */
+[data-theme="light"] .device-status-top {
+  position: absolute !important;
+  top: 20px !important;
+  right: 20px !important;
+  z-index: 10 !important;
+}
+
+[data-theme="light"] .status-indicator {
+  background: rgba(255, 255, 255, 0.95) !important;
+  border: 2px solid #D9D9D9 !important;
+  padding: 8px 16px !important;
+  border-radius: 20px !important;
+}
+
+[data-theme="light"] .status-indicator.connected {
+  border-color: #52C41A !important;
+  background: rgba(246, 255, 237, 0.95) !important;
+}
+
+[data-theme="light"] .status-dot {
+  background: #FF4D4F !important;
+}
+
+[data-theme="light"] .status-indicator.connected .status-dot {
+  background: #52C41A !important;
+}
+
+[data-theme="light"] .status-text {
+  color: #1a1a1a !important;
+  font-weight: 700 !important;
+}
+
+/* 指纹扫描区域 */
+[data-theme="light"] .fingerprint-scanner {
+  background: linear-gradient(135deg,
+    rgba(230, 247, 255, 0.8) 0%,
+    rgba(248, 250, 255, 0.8) 100%) !important;
+  border: 3px solid rgba(24, 144, 255, 0.3) !important;
+  box-shadow: 0 8px 24px rgba(24, 144, 255, 0.2) !important;
+}
+
+[data-theme="light"] .fingerprint-icon {
+  color: #1890FF !important;
+}
+
+[data-theme="light"] .scan-progress {
+  color: #1890FF !important;
+  font-weight: 700 !important;
+}
+
+/* 输入框 */
+[data-theme="light"] .step-card .dark-input {
+  background: #FFFFFF !important;
+  border: 2px solid #D9D9D9 !important;
+  color: #1a1a1a !important;
+  font-weight: 600 !important;
+}
+
+[data-theme="light"] .step-card .dark-input:focus {
+  border-color: #1890FF !important;
+  box-shadow: 0 0 0 3px rgba(24, 144, 255, 0.15) !important;
+}
+
+[data-theme="light"] .step-card .input-label {
+  color: #1a1a1a !important;
+  font-weight: 700 !important;
+}
+
+/* ========== 明亮主题 - 指纹登录页(识别页) ========== */
+[data-theme="light"] .fingerprint-login-page {
+  background: linear-gradient(135deg,
+    #E8F4FF 0%,
+    #F0F8FF 50%,
+    #FFFFFF 100%) !important;
+}
+
+[data-theme="light"] .fingerprint-login-page .bg-layer {
+  background: linear-gradient(135deg,
+    #E8F4FF 0%,
+    #F0F8FF 50%,
+    #FFFFFF 100%) !important;
+  background-image: none !important;
+}
+
+/* 隐藏深色主题的背景装饰 */
+[data-theme="light"] .fingerprint-login-page .circuit-bg,
+[data-theme="light"] .fingerprint-login-page .matrix-rain,
+[data-theme="light"] .fingerprint-login-page .hexagon-bg,
+[data-theme="light"] .fingerprint-login-page .scan-lines,
+[data-theme="light"] .fingerprint-login-page .gradient-bg,
+[data-theme="light"] .fingerprint-login-page .particles-bg,
+[data-theme="light"] .fingerprint-login-page .geometric-bg {
+  display: none !important;
+}
+
+/* 状态圆形 */
+[data-theme="light"] .fingerprint-login-page .status-circle {
+  background: rgba(255, 255, 255, 0.98) !important;
+  border: 3px solid rgba(24, 144, 255, 0.3) !important;
+  box-shadow: 0 20px 60px rgba(24, 144, 255, 0.25),
+              0 0 40px rgba(24, 144, 255, 0.15) !important;
+}
+
+[data-theme="light"] .fingerprint-login-page .status-circle.status-waiting {
+  border-color: rgba(24, 144, 255, 0.4) !important;
+}
+
+[data-theme="light"] .fingerprint-login-page .status-circle.status-recognizing {
+  border-color: #1890FF !important;
+  box-shadow: 0 20px 60px rgba(24, 144, 255, 0.35),
+              0 0 50px rgba(24, 144, 255, 0.25) !important;
+}
+
+[data-theme="light"] .fingerprint-login-page .status-circle.status-success {
+  border-color: #52C41A !important;
+  background: rgba(246, 255, 237, 0.98) !important;
+}
+
+[data-theme="light"] .fingerprint-login-page .status-circle.status-failed {
+  border-color: #FF4D4F !important;
+  background: rgba(255, 245, 245, 0.98) !important;
+}
+
+/* 指纹图标 */
+[data-theme="light"] .fingerprint-login-page .fingerprint-svg {
+  color: #1890FF !important;
+}
+
+[data-theme="light"] .fingerprint-login-page .status-waiting .fingerprint-svg {
+  color: rgba(24, 144, 255, 0.6) !important;
+}
+
+[data-theme="light"] .fingerprint-login-page .status-recognizing .fingerprint-svg {
+  color: #1890FF !important;
+}
+
+[data-theme="light"] .fingerprint-login-page .status-success .fingerprint-svg {
+  color: #52C41A !important;
+}
+
+[data-theme="light"] .fingerprint-login-page .status-failed .fingerprint-svg {
+  color: #FF4D4F !important;
+}
+
+/* 状态文本 */
+[data-theme="light"] .fingerprint-login-page .status-text {
+  color: #1a1a1a !important;
+  font-weight: 800 !important;
+}
+
+/* 操作按钮 */
+[data-theme="light"] .fingerprint-login-page .action-btn {
+  background: rgba(255, 255, 255, 0.95) !important;
+  border: 2px solid #1890FF !important;
+  color: #1890FF !important;
+  font-weight: 700 !important;
+}
+
+[data-theme="light"] .fingerprint-login-page .action-btn:hover {
+  background: rgba(24, 144, 255, 0.1) !important;
+  box-shadow: 0 4px 12px rgba(24, 144, 255, 0.4) !important;
+}
+
+[data-theme="light"] .fingerprint-login-page .instruction-text {
+  color: #1a1a1a !important;
+  font-weight: 700 !important;
+  font-size: 18px !important;
+}
+
+[data-theme="light"] .fingerprint-login-page .status-text {
+  color: #1a1a1a !important;
+  font-weight: 600 !important;
+  font-size: 16px !important;
+}
+
+[data-theme="light"] .fingerprint-login-page .switch-login-btn,
+[data-theme="light"] .fingerprint-login-page .password-login-btn {
+  background: linear-gradient(90deg, #1890FF 0%, #0066FF 100%) !important;
+  color: #ffffff !important;
+  border: none !important;
+  box-shadow: 0 6px 16px rgba(24, 144, 255, 0.5) !important;
+  font-weight: 800 !important;
+  font-size: 18px !important;
+  padding: 14px 36px !important;
+}
+
+[data-theme="light"] .fingerprint-login-page .switch-login-btn:hover,
+[data-theme="light"] .fingerprint-login-page .password-login-btn:hover {
+  box-shadow: 0 8px 20px rgba(24, 144, 255, 0.6) !important;
+  transform: translateY(-2px) !important;
+}
+
+/* ========== 明亮主题 - AGV RFID识别页和闸机控制页 ========== */
+/* 优化配色:更接近指纹录入页的美观效果 */
+[data-theme="light"] .agv-page,
+[data-theme="light"] .gate-control-page,
+[data-theme="light"] .delivery-management,
+[data-theme="light"] .return-management {
+  background: linear-gradient(135deg,
+    #E8F4FF 0%,
+    #F0F8FF 50%,
+    #FFFFFF 100%) !important;
+}
+
+/* 隐藏深色主题的背景装饰 */
+[data-theme="light"] .agv-page .bg-layer,
+[data-theme="light"] .gate-control-page .bg-layer,
+[data-theme="light"] .delivery-management .bg-layer,
+[data-theme="light"] .return-management .bg-layer {
+  background: linear-gradient(135deg,
+    #E8F4FF 0%,
+    #F0F8FF 50%,
+    #FFFFFF 100%) !important;
+  background-image: none !important;
+}
+
+/* 站点卡片 - 优化配色,更柔和美观 */
+[data-theme="light"] .station-card,
+[data-theme="light"] .gate-card,
+[data-theme="light"] .agv-card,
+[data-theme="light"] .control-card {
+  background: linear-gradient(135deg,
+    rgba(255, 255, 255, 0.95) 0%,
+    rgba(248, 250, 255, 0.95) 100%) !important;
+  border: 3px solid rgba(24, 144, 255, 0.25) !important;
+  box-shadow: 0 8px 32px rgba(24, 144, 255, 0.15),
+              0 2px 8px rgba(24, 144, 255, 0.1) !important;
+  backdrop-filter: blur(10px);
+  transition: all 0.3s ease !important;
+  position: relative !important;
+  overflow: hidden !important;
+}
+
+/* 卡片装饰 - 右上角光晕效果 */
+[data-theme="light"] .station-card::after,
+[data-theme="light"] .gate-card::after,
+[data-theme="light"] .agv-card::after,
+[data-theme="light"] .control-card::after {
+  content: '';
+  position: absolute;
+  top: -50px;
+  right: -50px;
+  width: 150px;
+  height: 150px;
+  background: radial-gradient(circle,
+    rgba(24, 144, 255, 0.15) 0%,
+    rgba(24, 144, 255, 0.05) 40%,
+    transparent 70%);
+  border-radius: 50%;
+  pointer-events: none;
+  transition: all 0.3s ease;
+}
+
+[data-theme="light"] .station-card:hover::after,
+[data-theme="light"] .gate-card:hover::after,
+[data-theme="light"] .agv-card:hover::after,
+[data-theme="light"] .control-card:hover::after {
+  top: -60px;
+  right: -60px;
+  width: 180px;
+  height: 180px;
+  background: radial-gradient(circle,
+    rgba(24, 144, 255, 0.2) 0%,
+    rgba(24, 144, 255, 0.08) 40%,
+    transparent 70%);
+}
+
+[data-theme="light"] .station-card:hover,
+[data-theme="light"] .gate-card:hover,
+[data-theme="light"] .agv-card:hover,
+[data-theme="light"] .control-card:hover {
+  border-color: rgba(24, 144, 255, 0.4) !important;
+  box-shadow: 0 12px 48px rgba(24, 144, 255, 0.25),
+              0 4px 16px rgba(24, 144, 255, 0.15) !important;
+  transform: translateY(-4px) scale(1.01) !important;
+}
+
+/* 占用状态 - 优化红色配色 */
+[data-theme="light"] .station-card.station-occupied,
+[data-theme="light"] .gate-card.occupied {
+  border-color: rgba(255, 77, 79, 0.4) !important;
+  background: linear-gradient(135deg,
+    rgba(255, 245, 245, 0.95) 0%,
+    rgba(255, 250, 250, 0.95) 100%) !important;
+  box-shadow: 0 8px 32px rgba(255, 77, 79, 0.15),
+              0 2px 8px rgba(255, 77, 79, 0.1) !important;
+}
+
+/* 占用状态装饰 - 红色光晕 */
+[data-theme="light"] .station-card.station-occupied::after,
+[data-theme="light"] .gate-card.occupied::after {
+  background: radial-gradient(circle,
+    rgba(255, 77, 79, 0.15) 0%,
+    rgba(255, 77, 79, 0.05) 40%,
+    transparent 70%) !important;
+}
+
+[data-theme="light"] .station-card.station-occupied:hover,
+[data-theme="light"] .gate-card.occupied:hover {
+  border-color: rgba(255, 77, 79, 0.6) !important;
+  box-shadow: 0 12px 48px rgba(255, 77, 79, 0.25),
+              0 4px 16px rgba(255, 77, 79, 0.15) !important;
+}
+
+[data-theme="light"] .station-card.station-occupied:hover::after,
+[data-theme="light"] .gate-card.occupied:hover::after {
+  background: radial-gradient(circle,
+    rgba(255, 77, 79, 0.2) 0%,
+    rgba(255, 77, 79, 0.08) 40%,
+    transparent 70%) !important;
+}
+
+/* 空闲状态 - 优化绿色配色 */
+[data-theme="light"] .station-card.station-idle,
+[data-theme="light"] .gate-card.idle {
+  border-color: rgba(82, 196, 26, 0.4) !important;
+  background: linear-gradient(135deg,
+    rgba(246, 255, 237, 0.95) 0%,
+    rgba(250, 255, 245, 0.95) 100%) !important;
+  box-shadow: 0 8px 32px rgba(82, 196, 26, 0.15),
+              0 2px 8px rgba(82, 196, 26, 0.1) !important;
+}
+
+/* 空闲状态装饰 - 绿色光晕 */
+[data-theme="light"] .station-card.station-idle::after,
+[data-theme="light"] .gate-card.idle::after {
+  background: radial-gradient(circle,
+    rgba(82, 196, 26, 0.15) 0%,
+    rgba(82, 196, 26, 0.05) 40%,
+    transparent 70%) !important;
+}
+
+[data-theme="light"] .station-card.station-idle:hover,
+[data-theme="light"] .gate-card.idle:hover {
+  border-color: rgba(82, 196, 26, 0.6) !important;
+  box-shadow: 0 12px 48px rgba(82, 196, 26, 0.25),
+              0 4px 16px rgba(82, 196, 26, 0.15) !important;
+}
+
+[data-theme="light"] .station-card.station-idle:hover::after,
+[data-theme="light"] .gate-card.idle:hover::after {
+  background: radial-gradient(circle,
+    rgba(82, 196, 26, 0.2) 0%,
+    rgba(82, 196, 26, 0.08) 40%,
+    transparent 70%) !important;
+}
+
+/* 待入库状态 - 优化橙色配色 */
+[data-theme="light"] .station-card.station-pending {
+  border-color: rgba(250, 173, 20, 0.4) !important;
+  background: linear-gradient(135deg,
+    rgba(255, 251, 230, 0.95) 0%,
+    rgba(255, 253, 240, 0.95) 100%) !important;
+  box-shadow: 0 8px 32px rgba(250, 173, 20, 0.15),
+              0 2px 8px rgba(250, 173, 20, 0.1) !important;
+}
+
+/* 待入库状态装饰 - 橙色光晕 */
+[data-theme="light"] .station-card.station-pending::after {
+  background: radial-gradient(circle,
+    rgba(250, 173, 20, 0.15) 0%,
+    rgba(250, 173, 20, 0.05) 40%,
+    transparent 70%) !important;
+}
+
+[data-theme="light"] .station-card.station-pending:hover {
+  border-color: rgba(250, 173, 20, 0.6) !important;
+  box-shadow: 0 12px 48px rgba(250, 173, 20, 0.25),
+              0 4px 16px rgba(250, 173, 20, 0.15) !important;
+}
+
+[data-theme="light"] .station-card.station-pending:hover::after {
+  background: radial-gradient(circle,
+    rgba(250, 173, 20, 0.2) 0%,
+    rgba(250, 173, 20, 0.08) 40%,
+    transparent 70%) !important;
+}
+
+/* 卡片头部 - 优化渐变效果 */
+[data-theme="light"] .station-card .card-header,
+[data-theme="light"] .gate-card .card-header,
+[data-theme="light"] .agv-card .card-header,
+[data-theme="light"] .control-card .card-header {
+  background: linear-gradient(90deg,
+    rgba(24, 144, 255, 0.06) 0%,
+    rgba(24, 144, 255, 0.12) 50%,
+    rgba(24, 144, 255, 0.06) 100%) !important;
+  border-bottom: 2px solid rgba(24, 144, 255, 0.15) !important;
+  padding: 18px 20px !important;
+  margin: -20px -20px 20px -20px !important;
+  border-radius: 12px 12px 0 0 !important;
+  position: relative !important;
+}
+
+/* 卡片头部添加装饰线 */
+[data-theme="light"] .station-card .card-header::before,
+[data-theme="light"] .gate-card .card-header::before,
+[data-theme="light"] .agv-card .card-header::before,
+[data-theme="light"] .control-card .card-header::before {
+  content: '';
+  position: absolute;
+  top: 0;
+  left: 0;
+  right: 0;
+  height: 3px;
+  background: linear-gradient(90deg,
+    transparent 0%,
+    rgba(24, 144, 255, 0.5) 50%,
+    transparent 100%);
+  border-radius: 12px 12px 0 0;
+}
+
+/* 卡片标题 - 优化字体和颜色 */
+[data-theme="light"] .station-card .card-title,
+[data-theme="light"] .gate-card .card-title,
+[data-theme="light"] .agv-card .card-title,
+[data-theme="light"] .control-card .card-title {
+  color: #1890FF !important;
+  font-weight: 800 !important;
+  font-size: 22px !important;
+  text-shadow: 0 1px 2px rgba(24, 144, 255, 0.1) !important;
+  letter-spacing: 0.5px !important;
+}
+
+/* 卡片内容 - 优化文字样式和间距 */
+[data-theme="light"] .station-card .card-content,
+[data-theme="light"] .gate-card .card-content,
+[data-theme="light"] .agv-card .card-content,
+[data-theme="light"] .control-card .card-content {
+  color: #1a1a1a !important;
+  font-weight: 600 !important;
+  line-height: 1.8 !important;
+  padding: 8px 0 !important;
+}
+
+/* 卡片文本 */
+[data-theme="light"] .station-card .card-text,
+[data-theme="light"] .gate-card .card-text,
+[data-theme="light"] .agv-card .card-text,
+[data-theme="light"] .control-card .card-text {
+  color: #1a1a1a !important;
+  font-weight: 600 !important;
+  font-size: 16px !important;
+  line-height: 1.8 !important;
+}
+
+/* 卡片标签 - 优化颜色和样式 */
+[data-theme="light"] .station-card .card-label,
+[data-theme="light"] .gate-card .card-label,
+[data-theme="light"] .agv-card .card-label {
+  color: #595959 !important;
+  font-weight: 700 !important;
+  font-size: 15px !important;
+  letter-spacing: 0.3px !important;
+  text-transform: uppercase !important;
+  opacity: 0.85 !important;
+}
+
+[data-theme="light"] .station-card .card-value,
+[data-theme="light"] .gate-card .card-value,
+[data-theme="light"] .agv-card .card-value {
+  color: #1a1a1a !important;
+  font-weight: 800 !important;
+  font-size: 18px !important;
+  letter-spacing: 0.5px !important;
+}
+
+/* 状态徽章 - 优化样式,更加美观 */
+[data-theme="light"] .status-badge.status-success {
+  background: linear-gradient(135deg,
+    rgba(82, 196, 26, 0.15) 0%,
+    rgba(82, 196, 26, 0.25) 100%) !important;
+  color: #389E0D !important;
+  border: 2px solid rgba(82, 196, 26, 0.4) !important;
+  font-weight: 800 !important;
+  padding: 8px 16px !important;
+  border-radius: 8px !important;
+  box-shadow: 0 2px 8px rgba(82, 196, 26, 0.15) !important;
+  transition: all 0.3s ease !important;
+}
+
+[data-theme="light"] .status-badge.status-success:hover {
+  border-color: rgba(82, 196, 26, 0.6) !important;
+  box-shadow: 0 4px 12px rgba(82, 196, 26, 0.25) !important;
+  transform: translateY(-1px) !important;
+}
+
+[data-theme="light"] .status-badge.status-danger {
+  background: linear-gradient(135deg,
+    rgba(255, 77, 79, 0.15) 0%,
+    rgba(255, 77, 79, 0.25) 100%) !important;
+  color: #CF1322 !important;
+  border: 2px solid rgba(255, 77, 79, 0.4) !important;
+  font-weight: 800 !important;
+  padding: 8px 16px !important;
+  border-radius: 8px !important;
+  box-shadow: 0 2px 8px rgba(255, 77, 79, 0.15) !important;
+  transition: all 0.3s ease !important;
+}
+
+[data-theme="light"] .status-badge.status-danger:hover {
+  border-color: rgba(255, 77, 79, 0.6) !important;
+  box-shadow: 0 4px 12px rgba(255, 77, 79, 0.25) !important;
+  transform: translateY(-1px) !important;
+}
+
+[data-theme="light"] .status-badge.status-warning {
+  background: linear-gradient(135deg,
+    rgba(250, 173, 20, 0.15) 0%,
+    rgba(250, 173, 20, 0.25) 100%) !important;
+  color: #D48806 !important;
+  border: 2px solid rgba(250, 173, 20, 0.4) !important;
+  font-weight: 800 !important;
+  padding: 8px 16px !important;
+  border-radius: 8px !important;
+  box-shadow: 0 2px 8px rgba(250, 173, 20, 0.15) !important;
+  transition: all 0.3s ease !important;
+}
+
+[data-theme="light"] .status-badge.status-warning:hover {
+  border-color: rgba(250, 173, 20, 0.6) !important;
+  box-shadow: 0 4px 12px rgba(250, 173, 20, 0.25) !important;
+  transform: translateY(-1px) !important;
+}
+
+/* 物料显示区域 - 优化背景和边框 */
+[data-theme="light"] .material-display {
+  background: linear-gradient(135deg,
+    rgba(248, 250, 255, 0.95) 0%,
+    rgba(240, 245, 255, 0.95) 100%) !important;
+  border: 2px solid rgba(24, 144, 255, 0.25) !important;
+  border-radius: 12px !important;
+  padding: 18px !important;
+  box-shadow: 0 4px 16px rgba(24, 144, 255, 0.08) !important;
+  transition: all 0.3s ease !important;
+}
+
+[data-theme="light"] .material-display:hover {
+  border-color: rgba(24, 144, 255, 0.35) !important;
+  box-shadow: 0 6px 20px rgba(24, 144, 255, 0.12) !important;
+}
+
+[data-theme="light"] .material-image {
+  background: rgba(255, 255, 255, 0.95) !important;
+  border: 2px solid rgba(24, 144, 255, 0.2) !important;
+  border-radius: 8px !important;
+  box-shadow: 0 2px 8px rgba(24, 144, 255, 0.08) !important;
+}
+
+[data-theme="light"] .material-name {
+  color: #1890FF !important;
+  font-weight: 800 !important;
+  font-size: 18px !important;
+  letter-spacing: 0.5px !important;
+  text-shadow: 0 1px 2px rgba(24, 144, 255, 0.1) !important;
+}
+
+[data-theme="light"] .material-info {
+  color: #1a1a1a !important;
+  font-weight: 600 !important;
+  font-size: 15px !important;
+  line-height: 1.8 !important;
+}
+
+/* 密码登录页 */
+[data-theme="light"] .password-login-page {
+  background: linear-gradient(135deg, #E8F4FF 0%, #F0F8FF 50%, #FFFFFF 100%) !important;
+}
+
+[data-theme="light"] .password-login-page .bg-layer {
+  background: linear-gradient(135deg, #E8F4FF 0%, #F0F8FF 50%, #FFFFFF 100%) !important;
+  background-image: none !important;
+}
+
+[data-theme="light"] .password-login-page .login-box {
+  background: rgba(255, 255, 255, 0.98) !important;
+  border: 2px solid rgba(24, 144, 255, 0.3) !important;
+  box-shadow: 0 8px 32px rgba(24, 144, 255, 0.2) !important;
+  backdrop-filter: blur(10px);
+}
+
+[data-theme="light"] .password-login-page .login-header {
+  border-bottom: 2px solid rgba(24, 144, 255, 0.2) !important;
+  background: linear-gradient(90deg, rgba(24, 144, 255, 0.08) 0%, rgba(24, 144, 255, 0.15) 50%, rgba(24, 144, 255, 0.08) 100%) !important;
+  padding: 20px !important;
+}
+
+[data-theme="light"] .password-login-page .login-header h2 {
+  color: #1890FF !important;
+  text-shadow: none !important;
+  font-weight: 700 !important;
+  font-size: 28px !important;
+}
+
+[data-theme="light"] .password-login-page .form-label {
+  color: #1a1a1a !important;
+  font-weight: 700 !important;
+  font-size: 16px !important;
+  margin-bottom: 8px !important;
+}
+
+[data-theme="light"] .password-login-page .login-input {
+  background: #FFFFFF !important;
+  border: 2px solid #D9D9D9 !important;
+  color: #1a1a1a !important;
+  font-size: 16px !important;
+  padding: 12px 16px !important;
+  font-weight: 500 !important;
+}
+
+[data-theme="light"] .password-login-page .login-input:focus {
+  border-color: #1890FF !important;
+  box-shadow: 0 0 0 3px rgba(24, 144, 255, 0.15) !important;
+}
+
+[data-theme="light"] .password-login-page .login-input::placeholder {
+  color: #BFBFBF !important;
+  font-weight: 400 !important;
+}
+
+[data-theme="light"] .password-login-page .login-submit-btn {
+  background: linear-gradient(90deg, #1890FF 0%, #0066FF 100%) !important;
+  color: #ffffff !important;
+  border: none !important;
+  box-shadow: 0 4px 12px rgba(24, 144, 255, 0.4) !important;
+  font-weight: 700 !important;
+  font-size: 18px !important;
+  padding: 14px !important;
+}
+
+[data-theme="light"] .password-login-page .login-submit-btn:hover {
+  box-shadow: 0 6px 16px rgba(24, 144, 255, 0.5) !important;
+  transform: translateY(-2px);
+}
+
+[data-theme="light"] .password-login-page .back-to-fingerprint {
+  color: #1890FF !important;
+  font-weight: 600 !important;
+}
+
+[data-theme="light"] .password-login-page .back-to-fingerprint:hover {
+  color: #0066FF !important;
+  text-decoration: underline;
+}
+
+/* 登录页通用元素 */
+[data-theme="light"] .login-page .header-img,
+[data-theme="light"] .fingerprint-login-page .header-img,
+[data-theme="light"] .password-login-page .header-img {
+  display: none !important;
+}
+
+[data-theme="light"] .login-page .bottom-img,
+[data-theme="light"] .fingerprint-login-page .bottom-img,
+[data-theme="light"] .password-login-page .bottom-img {
+  display: none !important;
+}
+
+/* ========== 明亮主题 - 业务页面样式 ========== */
+/* 底部操作区 */
+[data-theme="light"] .bottom-actions,
+[data-theme="light"] .footer-actions,
+[data-theme="light"] .action-footer {
+  background: rgba(255, 255, 255, 0.98) !important;
+  border-top: 2px solid rgba(24, 144, 255, 0.2) !important;
+  box-shadow: 0 -4px 12px rgba(24, 144, 255, 0.1) !important;
+  backdrop-filter: blur(10px);
+}
+
+/* 详情卡片 */
+[data-theme="light"] .detail-card,
+[data-theme="light"] .info-card,
+[data-theme="light"] .material-card {
+  background: rgba(255, 255, 255, 0.95) !important;
+  border: 2px solid rgba(24, 144, 255, 0.2) !important;
+  box-shadow: 0 4px 12px rgba(24, 144, 255, 0.1) !important;
+  backdrop-filter: blur(10px);
+}
+
+[data-theme="light"] .detail-card .card-header,
+[data-theme="light"] .info-card .card-header,
+[data-theme="light"] .material-card .card-header {
+  background: linear-gradient(90deg, rgba(24, 144, 255, 0.08) 0%, rgba(24, 144, 255, 0.15) 50%, rgba(24, 144, 255, 0.08) 100%) !important;
+  border-bottom: 2px solid rgba(24, 144, 255, 0.2) !important;
+  color: #1890FF !important;
+  font-weight: 700 !important;
+}
+
+[data-theme="light"] .detail-card .card-body,
+[data-theme="light"] .info-card .card-body,
+[data-theme="light"] .material-card .card-body {
+  background: rgba(255, 255, 255, 0.9) !important;
+}
+
+[data-theme="light"] .detail-card .label,
+[data-theme="light"] .info-card .label,
+[data-theme="light"] .material-card .label {
+  color: #1a1a1a !important;
+  font-weight: 600 !important;
+}
+
+[data-theme="light"] .detail-card .value,
+[data-theme="light"] .info-card .value,
+[data-theme="light"] .material-card .value {
+  color: #1890FF !important;
+  font-weight: 600 !important;
+}
+
+/* 业务页面筛选面板 */
+[data-theme="light"] .filter-panel,
+[data-theme="light"] .search-panel {
+  background: rgba(255, 255, 255, 0.95) !important;
+  border: 2px solid rgba(24, 144, 255, 0.2) !important;
+  box-shadow: 0 4px 12px rgba(24, 144, 255, 0.1) !important;
+}
+
+/* 业务页面列表项 */
+[data-theme="light"] .list-item,
+[data-theme="light"] .material-item {
+  background: rgba(255, 255, 255, 0.9) !important;
+  border: 1px solid rgba(24, 144, 255, 0.15) !important;
+  box-shadow: 0 2px 8px rgba(24, 144, 255, 0.08) !important;
+}
+
+[data-theme="light"] .list-item:hover,
+[data-theme="light"] .material-item:hover {
+  background: rgba(230, 247, 255, 0.9) !important;
+  border-color: rgba(24, 144, 255, 0.3) !important;
+  box-shadow: 0 4px 12px rgba(24, 144, 255, 0.15) !important;
+}
+
+[data-theme="light"] .list-item .item-title,
+[data-theme="light"] .material-item .item-title {
+  color: #1a1a1a !important;
+  font-weight: 700 !important;
+}
+
+[data-theme="light"] .list-item .item-desc,
+[data-theme="light"] .material-item .item-desc {
+  color: #666666 !important;
+}
+
+[data-theme="light"] .list-item .item-value,
+[data-theme="light"] .material-item .item-value {
+  color: #1890FF !important;
+  font-weight: 700 !important;
+}
+
+/* ========== 明亮主题 - AGV RFID识别页 ========== */
+[data-theme="light"] .agv-rfid-page {
+  background: linear-gradient(135deg, #F0F8FF 0%, #FAFCFF 50%, #FFFFFF 100%) !important;
+}
+
+[data-theme="light"] .agv-rfid-page .bg-layer {
+  background: linear-gradient(135deg, #F0F8FF 0%, #FAFCFF 50%, #FFFFFF 100%) !important;
+  background-image: none !important;
+}
+
+[data-theme="light"] .agv-rfid-page .rfid-container {
+  background: rgba(255, 255, 255, 0.98) !important;
+  border: 2px solid rgba(24, 144, 255, 0.3) !important;
+  box-shadow: 0 8px 32px rgba(24, 144, 255, 0.2) !important;
+  backdrop-filter: blur(10px);
+}
+
+[data-theme="light"] .agv-rfid-page .page-title {
+  color: #1890FF !important;
+  font-weight: 700 !important;
+  text-shadow: none !important;
+}
+
+[data-theme="light"] .agv-rfid-page .rfid-status {
+  background: rgba(255, 255, 255, 0.95) !important;
+  border: 2px solid rgba(24, 144, 255, 0.2) !important;
+  box-shadow: 0 4px 12px rgba(24, 144, 255, 0.1) !important;
+}
+
+[data-theme="light"] .agv-rfid-page .status-text {
+  color: #1a1a1a !important;
+  font-weight: 600 !important;
+}
+
+[data-theme="light"] .agv-rfid-page .rfid-icon {
+  filter: brightness(0.4) sepia(1) hue-rotate(180deg) saturate(6) !important;
+}
+
+/* ========== 明亮主题 - 闸机控制页 ========== */
+[data-theme="light"] .gate-control-page {
+  background: linear-gradient(135deg, #F0F8FF 0%, #FAFCFF 50%, #FFFFFF 100%) !important;
+}
+
+[data-theme="light"] .gate-control-page .bg-layer {
+  background: linear-gradient(135deg, #F0F8FF 0%, #FAFCFF 50%, #FFFFFF 100%) !important;
+  background-image: none !important;
+}
+
+[data-theme="light"] .gate-control-page .control-container {
+  background: rgba(255, 255, 255, 0.98) !important;
+  border: 2px solid rgba(24, 144, 255, 0.3) !important;
+  box-shadow: 0 8px 32px rgba(24, 144, 255, 0.2) !important;
+  backdrop-filter: blur(10px);
+}
+
+[data-theme="light"] .gate-control-page .page-title {
+  color: #1890FF !important;
+  font-weight: 700 !important;
+  text-shadow: none !important;
+}
+
+[data-theme="light"] .gate-control-page .gate-status {
+  background: rgba(255, 255, 255, 0.95) !important;
+  border: 2px solid rgba(24, 144, 255, 0.2) !important;
+  box-shadow: 0 4px 12px rgba(24, 144, 255, 0.1) !important;
+}
+
+[data-theme="light"] .gate-control-page .control-btn {
+  background: linear-gradient(135deg,
+    rgba(24, 144, 255, 0.95) 0%,
+    rgba(0, 102, 255, 0.95) 100%) !important;
+  color: #ffffff !important;
+  border: 2px solid rgba(255, 255, 255, 0.3) !important;
+  box-shadow: 0 4px 16px rgba(24, 144, 255, 0.35),
+              0 2px 8px rgba(24, 144, 255, 0.2) !important;
+  font-weight: 800 !important;
+  padding: 12px 24px !important;
+  border-radius: 10px !important;
+  transition: all 0.3s ease !important;
+  position: relative !important;
+  overflow: hidden !important;
+}
+
+/* 按钮光泽效果 */
+[data-theme="light"] .gate-control-page .control-btn::before {
+  content: '';
+  position: absolute;
+  top: 0;
+  left: -100%;
+  width: 100%;
+  height: 100%;
+  background: linear-gradient(90deg,
+    transparent 0%,
+    rgba(255, 255, 255, 0.3) 50%,
+    transparent 100%);
+  transition: left 0.5s ease;
+}
+
+[data-theme="light"] .gate-control-page .control-btn:hover::before {
+  left: 100%;
+}
+
+[data-theme="light"] .gate-control-page .control-btn:hover {
+  box-shadow: 0 6px 24px rgba(24, 144, 255, 0.45),
+              0 3px 12px rgba(24, 144, 255, 0.3) !important;
+  transform: translateY(-2px) scale(1.02) !important;
+  border-color: rgba(255, 255, 255, 0.5) !important;
+}
+
+[data-theme="light"] .gate-control-page .control-btn.danger {
+  background: linear-gradient(135deg,
+    rgba(255, 77, 79, 0.95) 0%,
+    rgba(245, 34, 45, 0.95) 100%) !important;
+  box-shadow: 0 4px 16px rgba(255, 77, 79, 0.35),
+              0 2px 8px rgba(255, 77, 79, 0.2) !important;
+}
+
+[data-theme="light"] .gate-control-page .control-btn.danger:hover {
+  box-shadow: 0 6px 24px rgba(255, 77, 79, 0.45),
+              0 3px 12px rgba(255, 77, 79, 0.3) !important;
+}
+
+/* AGV页面的按钮样式 */
+[data-theme="light"] .agv-page .control-btn,
+[data-theme="light"] .agv-page .action-btn {
+  background: linear-gradient(135deg,
+    rgba(24, 144, 255, 0.95) 0%,
+    rgba(0, 102, 255, 0.95) 100%) !important;
+  color: #ffffff !important;
+  border: 2px solid rgba(255, 255, 255, 0.3) !important;
+  box-shadow: 0 4px 16px rgba(24, 144, 255, 0.35),
+              0 2px 8px rgba(24, 144, 255, 0.2) !important;
+  font-weight: 800 !important;
+  padding: 12px 24px !important;
+  border-radius: 10px !important;
+  transition: all 0.3s ease !important;
+}
+
+[data-theme="light"] .agv-page .control-btn:hover,
+[data-theme="light"] .agv-page .action-btn:hover {
+  box-shadow: 0 6px 24px rgba(24, 144, 255, 0.45),
+              0 3px 12px rgba(24, 144, 255, 0.3) !important;
+  transform: translateY(-2px) scale(1.02) !important;
+  border-color: rgba(255, 255, 255, 0.5) !important;
+}
+
+/* 信息行样式优化 */
+[data-theme="light"] .station-card .info-row,
+[data-theme="light"] .gate-card .info-row,
+[data-theme="light"] .agv-card .info-row {
+  padding: 12px 0 !important;
+  border-bottom: 1px solid rgba(24, 144, 255, 0.1) !important;
+  transition: all 0.3s ease !important;
+}
+
+[data-theme="light"] .station-card .info-row:last-child,
+[data-theme="light"] .gate-card .info-row:last-child,
+[data-theme="light"] .agv-card .info-row:last-child {
+  border-bottom: none !important;
+}
+
+[data-theme="light"] .station-card .info-row:hover,
+[data-theme="light"] .gate-card .info-row:hover,
+[data-theme="light"] .agv-card .info-row:hover {
+  background: rgba(24, 144, 255, 0.03) !important;
+  padding-left: 8px !important;
+  margin-left: -8px !important;
+  margin-right: -8px !important;
+  padding-right: 8px !important;
+  border-radius: 6px !important;
+}
+[data-theme="light"] .task-status-card, .device-card, .control-panel {
+   background: linear-gradient(90deg, rgba(24, 144, 255, 0.08) 0%, rgba(24, 144, 255, 0.15) 50%, rgba(24, 144, 255, 0.08) 100%) !important;
+}
+[data-theme="light"] .agv-title, .gate-title {
+  color: #1890FF !important;
+}
+[data-theme="light"] .status-info-item {
+  background: #c3dafc !important;
+}
+[data-theme="light"] .status-info-item > .info-label {
+  color: #ffffff !important;
+}

BIN=BIN
src/assets/images/J20.png


BIN=BIN
src/assets/images/menu/J20.jpg


BIN=BIN
src/assets/images/menu/chuku.jpg


BIN=BIN
src/assets/images/menu/guihuan.jpg


BIN=BIN
src/assets/images/menu/huanliao.jpg


BIN=BIN
src/assets/images/menu/jieyong.jpg


BIN=BIN
src/assets/images/menu/lingliao.jpg


BIN=BIN
src/assets/images/menu/ruku.jpg


BIN=BIN
src/assets/images/menu/yunshu.jpg


+ 16 - 15
src/box/FeedingArea.vue

@@ -416,6 +416,7 @@ import {
     findProductCanRemoved, productRemoved,
 } from '../api/blankBox.js';
 import { useRouter } from 'vue-router';
+import { showErrorDialog } from '../util/errorDialog.js';
 
 const router = useRouter();
 const currentDate = ref('');
@@ -479,7 +480,7 @@ const handleDataProcessing = (res, isReverify = false) => {
     if (res.errorCode !== 0) {
         verificationSuccess.value = false;
         errorResult.value = res.errorMessage,
-        showNotify({ type: 'danger', message: res.errorMessage, duration: 6000, zIndex: 9999999 });
+        showErrorDialog(res.errorMessage);
     } else {
         errorResult.value = '';
     }
@@ -497,7 +498,7 @@ const handlePlaceEmptyBin = async isReverify => {
     } catch (error) {
         verificationSuccess.value = false;
         console.error('空料箱上架:', error);
-        showNotify({ type: 'danger', message: '空料箱上架API调用失败' });
+        if(error.status !== 401) showErrorDialog('空料箱上架API调用失败');
     } finally {
         loading.value = false;
     }
@@ -514,7 +515,7 @@ const handleRequestEmptyBin = async isReverify => {
     } catch (error) {
         console.error('校验失败:', error);
         verificationSuccess.value = false;
-        showNotify({ type: 'danger', message: '请求空料箱API调用失败' });
+        if(error.status !== 401) showErrorDialog('请求空料箱API调用失败');
     } finally {
         loading.value = false;
     }
@@ -531,7 +532,7 @@ const handleRequestVerification = async isReverify => {
     } catch (error) {
         console.error('校验失败:', error);
         verificationSuccess.value = false;
-        showNotify({ type: 'danger', message: '请求校验API调用失败' });
+        if(error.status !== 401) showErrorDialog('请求校验API调用失败');
     } finally {
         loading.value = false;
     }
@@ -590,7 +591,7 @@ const handleProductShelfDataProcessing = (res, isReverify = false) => {
     if (res.errorCode !== 0) {
         productShelfSuccess.value = false;
         productShelfError.value = res.errorMessage;
-        showNotify({ type: 'danger', message: res.errorMessage, duration: 6000, zIndex: 9999999 });
+        showErrorDialog(res.errorMessage);
     } else {
         productShelfError.value = '';
     }
@@ -606,7 +607,7 @@ const handleProductShelf = async (isReverify = false) => {
     } catch (error) {
         console.error('成品上架校验失败:', error);
         productShelfSuccess.value = false;
-        showNotify({ type: 'danger', message: '成品上架校验API调用失败' });
+        if(error.status !== 401) showErrorDialog('成品上架校验API调用失败');
     } finally {
         loading.value = false;
     }
@@ -651,13 +652,13 @@ const removeSelectedProduct = productId => {
 const submitProductShelf = async () => {
     console.log(productShelfSuccess.value);
     if (!productShelfSuccess.value) {
-        showNotify({ type: 'danger', message: '校验未通过,请重新校验', duration: 3000, zIndex: 9999999 });
+        showErrorDialog('校验未通过,请重新校验');
         return;
     }
 
     // 校验: 是否选择了成品
     if (selectedProducts.value.length === 0) {
-        showNotify({ type: 'danger', message: '请先选择要上架的成品', duration: 3000, zIndex: 9999999 });
+        showErrorDialog('请先选择要上架的成品');
         return;
     }
 
@@ -675,13 +676,13 @@ const submitProductShelf = async () => {
             showNotify({ type: 'success', message: '成品上架成功', duration: 3000, zIndex: 9999999 });
             closeProductShelfDialog();
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage, duration: 3000, zIndex: 9999999 });
+            showErrorDialog( res.errorMessage);
         }
 
     } catch (error) {
         productShelfSuccess.value = false;
         console.error('成品上架校验失败:', error);
-        showNotify({ type: 'danger', message: '成品上架校验API调用失败' });
+        if(error.status !== 401) showErrorDialog('成品上架校验API调用失败');
     } finally {
         loading.value = false;
     }
@@ -710,11 +711,11 @@ const handleProductOffShelf = async () => {
                 offShelfProductList.value = [];
             }
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage, duration: 3000, zIndex: 9999999 });
+            showErrorDialog(res.errorMessage);
         }
     } catch (error) {
         console.error('获取成品下架列表失败:', error);
-        showNotify({ type: 'danger', message: '获取成品下架列表失败' });
+        if(error.status !== 401) showErrorDialog('获取成品下架列表失败');
     } finally {
         loading.value = false;
     }
@@ -753,7 +754,7 @@ const removeOffShelfProduct = productId => {
 const submitProductOffShelf = async () => {
     // 校验是否选择了成品
     if (selectedOffShelfProducts.value.length === 0) {
-        showNotify({ type: 'danger', message: '请先选择要下架的成品', duration: 3000, zIndex: 9999999 });
+        showErrorDialog('请先选择要下架的成品');
         return;
     }
 
@@ -774,11 +775,11 @@ const submitProductOffShelf = async () => {
             showNotify({ type: 'success', message: '成品下架成功', duration: 3000, zIndex: 9999999 });
             closeProductOffShelfDialog();
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage, duration: 6000, zIndex: 9999999 });
+            showErrorDialog(res.errorMessage);
         }
     } catch (error) {
         console.error('成品下架API调用失败:', error);
-        showNotify({ type: 'danger', message: '成品下架API调用失败' });
+        if(error.status !== 401) showErrorDialog('成品下架API调用失败');
     } finally {
         loading.value = false;
     }

+ 88 - 0
src/common/ErrorDialog.vue

@@ -0,0 +1,88 @@
+<template>
+    <van-dialog
+        v-model:show="visible"
+        :title="title"
+        :message="message"
+        :show-cancel-button="false"
+        :show-confirm-button="true"
+        confirm-button-text="确认"
+        :close-on-click-overlay="false"
+        :close-on-popstate="false"
+        class-name="error-dialog-light"
+        @confirm="handleConfirm"
+    >
+    </van-dialog>
+</template>
+
+<script setup>
+import { ref } from 'vue';
+
+const visible = ref(false);
+const title = ref('提示');
+const message = ref('');
+const onConfirmCallback = ref(null);
+
+const show = (options) => {
+    if (typeof options === 'string') {
+        message.value = options;
+        title.value = '提示';
+    } else {
+        message.value = options.message || '';
+        title.value = options.title || '提示';
+        onConfirmCallback.value = options.onConfirm || null;
+    }
+    visible.value = true;
+};
+
+const hide = () => {
+    visible.value = false;
+    message.value = '';
+    title.value = '提示';
+    onConfirmCallback.value = null;
+};
+
+const handleConfirm = () => {
+    if (onConfirmCallback.value && typeof onConfirmCallback.value === 'function') {
+        onConfirmCallback.value();
+    }
+    hide();
+};
+
+defineExpose({
+    show,
+    hide
+});
+</script>
+
+<style>
+.error-dialog-light {
+    background-color: #ffffff;
+}
+
+.error-dialog-light .van-dialog__header {
+    color: #323233;
+    font-weight: 600;
+    padding-top: 26px;
+}
+
+.error-dialog-light .van-dialog__message {
+    color: #646566;
+    font-size: 14px;
+    line-height: 20px;
+    padding: 26px 24px;
+}
+
+.error-dialog-light .van-dialog__footer {
+    border-top: 1px solid #ebedf0;
+}
+
+.error-dialog-light .van-dialog__confirm {
+    color: #1989fa;
+    font-weight: 500;
+}
+
+.error-dialog-light .van-dialog__confirm:active {
+    background-color: #f2f3f5;
+}
+</style>
+

+ 3 - 1
src/composables/useIdleTimeout.js

@@ -49,10 +49,12 @@ export function useIdleTimeout(
 
     // 处理空闲超时
     const handleIdleTimeout = () => {
-        console.log('用户空闲超时,跳转到指纹登录页');
+        console.log('用户空闲超时,跳转到页');
     
         // 清理计时器
         clearIdleTimer();
+
+        localStorage.clear();
     
         // 跳转到指纹登录页
         router.push(redirectPath);

+ 12 - 11
src/finishProduct/FinishProductIn.vue

@@ -67,7 +67,7 @@
             <!-- 操作区域 -->
             <div class="card-action-section">
               <button class="delete-btn" @click.stop="openDeleteDialog(index)">
-                <i class="fas fa-trash" /> 删除
+                <i class="fas fa-trash" style="color: red !important;" /> 删除
               </button>
             </div>
           </div>
@@ -190,6 +190,7 @@ import { generateStockIn, getLocatorList } from '../api/finishProduct';
 import vSelect from 'vue-select';
 import 'vue-select/dist/vue-select.css';
 import { gateController } from '../hardware/GateOperate.js';
+import { showErrorDialog } from '../util/errorDialog';
 
 // 图片资源
 import bgImg from '../assets/images/bj.png';
@@ -253,7 +254,7 @@ const resetForm = () => {
 // 保存成品
 const saveProduct = () => {
     if (!isFormValid.value) {
-        showNotify({ type: 'danger', message: '请完整填写成品信息' });
+        showErrorDialog('请完整填写成品信息');
         return;
     }
 
@@ -277,7 +278,7 @@ const saveProduct = () => {
 // 执行入库
 const handleSubmit = () => {
     if (products.value.length === 0) {
-        showNotify({ type: 'danger', message: '暂无可提交的成品,请添加成品' });
+        showErrorDialog('暂无可提交的成品,请添加成品');
         return;
     }
     showConfirmModal.value = true;
@@ -302,15 +303,15 @@ const executeInbound = async () => {
             gateController('SHOTOPEN');
 
             showNotify({ type: 'success', message: `已提交 ${count} 条成品入库记录` });
-            router.push('/');
+            router.push('/home');
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage || '添加失败' });
+            showErrorDialog(res.errorMessage || '添加失败');
         }
         products.value = [];
         showConfirmModal.value = false;
     } catch (error) {
         console.log(error);
-        showNotify({ type: 'danger', message: '添加成品失败' });
+        if(error.status !== 401) showErrorDialog('添加成品失败');
     } finally {
         loading.value = false;
     }
@@ -338,11 +339,11 @@ const getLocators = async () => {
         if (res && res.length > 0) {
             warehouseLocationOptions.value = res;
         } else {
-            showNotify({ type: 'danger', message: '获取货位列表失败' });
+            showErrorDialog('获取货位列表失败');
         }
     } catch (error) {
         console.log(error);
-        showNotify({ type: 'danger', message: '获取货位列表失败' });
+        if(error.status !== 401) showErrorDialog('获取货位列表失败');
     }
 };
 onMounted(() => {
@@ -398,7 +399,7 @@ onMounted(() => {
   flex: 1;
   display: flex;
   flex-direction: column;
-  padding: 0 30px;
+  padding: 20px 30px;
   position: relative;
   z-index: 10;
   min-height: 0;
@@ -588,7 +589,7 @@ onMounted(() => {
   background: rgba(239, 68, 68, 0.2);
   border: 1px solid #ef4444;
   border-radius: 6px;
-  color: #fca5a5;
+  color: #ef4444;
   font-size: 13px;
   cursor: pointer;
   transition: all 0.3s;
@@ -925,7 +926,7 @@ onMounted(() => {
   }
 
   .main-content {
-    padding: 0 20px;
+    padding: 20px;
   }
 
   .card-grid {

+ 11 - 10
src/finishProduct/FinishProductOut.vue

@@ -172,6 +172,7 @@ import { queryFinishProduct, generateStockOut } from '../api/finishProduct.js';
 import vSelect from 'vue-select';
 import 'vue-select/dist/vue-select.css';
 import { gateController } from '../hardware/GateOperate.js';
+import { showErrorDialog } from '../util/errorDialog.js';
 
 // 图片资源
 import bgImg from '../assets/images/bj.png';
@@ -345,7 +346,7 @@ const toggleSelectAll = checked => {
 // 打开发起出库确认
 const confirmOutbound = () => {
     if (selectedProducts.value.length === 0) {
-        showNotify({ type: 'danger', message: '请选择要确认出库的成品' });
+        showErrorDialog('请选择要确认出库的成品');
         return;
     }
     showConfirmModal.value = true;
@@ -367,14 +368,14 @@ const executeOutbound = async () => {
             gateController('SHOTOPEN');
             showNotify({ type: 'success', message: '出库成功' });
             selectedProducts.value = [];
-            router.push('/');
+            router.push('/home');
             // await getList(); // 重新加载列表
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage });
+            showErrorDialog(res.errorMessage);
         }
     } catch (error) {
         console.log(error);
-        showNotify({ type: 'danger', message: '出库失败' });
+        if(error.status !== 401) showErrorDialog('出库失败');
     } finally {
         submitting.value = false;
     }
@@ -422,11 +423,11 @@ const getList = async () => {
         } else {
             finishProductList.value = [];
             total.value = 0;
-            showNotify({ type: 'danger', message: res.errorMessage });
+            showErrorDialog(res.errorMessage);
         }
     } catch (error) {
         console.error('获取成品列表失败:', error);
-        showNotify({ type: 'danger', message: '获取成品列表失败' });
+        if(error.status !== 401) showErrorDialog('获取成品列表失败');
     } finally {
         loading.value = false;
         isInitialLoading = false;
@@ -445,11 +446,11 @@ const getWarehouse = async () => {
                 warehouseList.value = [];
             }
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage });
+            showErrorDialog(res.errorMessage);
         }
     } catch (error) {
         console.error('获取仓库列表API调用失败:', error);
-        showNotify({ type: 'danger', message: '获取仓库数据失败' });
+        if(error.status !== 401) showErrorDialog('获取仓库数据失败');
     } finally {
         loading.value = false;
     }
@@ -493,7 +494,7 @@ onMounted(() => {
   flex: 1;
   display: flex;
   flex-direction: column;
-  padding: 0 30px;
+  padding: 20px 30px;
   position: relative;
   z-index: 10;
   min-height: 0;
@@ -1110,7 +1111,7 @@ onMounted(() => {
   }
 
   .main-content {
-    padding: 0 20px;
+    padding: 20px;
   }
 
   .filter-section {

+ 6 - 5
src/gate/ControlGate.vue

@@ -28,7 +28,7 @@
             <i class="fas fa-door-open" />
           </div>
           <div class="panel-title">
-            <h2>闸机操作</h2>
+            <h2 class="gate-title">闸机操作</h2>
             <p>选择以下操作来控制闸机</p>
           </div>
           <div class="panel-status">
@@ -146,6 +146,7 @@ import { useRouter } from 'vue-router';
 import { showNotify } from 'vant';
 import { controlGate, controlGateByBigInv, getGateStatus } from '../api/gate.js';
 import { gateController } from '../hardware/GateOperate.js';
+import { showErrorDialog } from '../util/errorDialog.js';
 // 图片资源
 import bgImg from '../assets/images/bj.png';
 // import { plugin } from 'postcss';
@@ -191,7 +192,7 @@ const handleControl = async (command, actionName, isBigInv) => {
         // }
     } catch (error) {
         console.error('闸机控制失败:', error);
-        showNotify({ type: 'danger', message: `${actionName}操作失败`, duration: 3000 });
+        if(error.status !== 401) showErrorDialog(`${actionName}操作失败`);
     } finally {
         loading.value = false;
     }
@@ -206,11 +207,11 @@ const getStatus = async () => {
             showNotify({ type: 'success', message: `闸机状态: ${res.data.gateStatus}`, duration: 3000 });
             status.value = res.data.gateStatus;
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage || '闸机状态获取失败', duration: 3000 });
+            showErrorDialog(res.errorMessage || '闸机状态获取失败');
         }
     } catch (error) {
         console.error('闸机状态获取失败:', error);
-        showNotify({ type: 'danger', message: '闸机状态获取失败', duration: 3000 });
+        if(error.status !== 401) showErrorDialog('闸机状态获取失败');
     } finally {
         loading.value = false;
     }
@@ -698,7 +699,7 @@ onMounted(() => {
   }
 
   .main-content {
-    padding: 30px;
+    padding: 20px 30px;
     justify-content: flex-start;
   }
 

+ 9 - 8
src/login/FingerprintLogin.vue

@@ -7,11 +7,11 @@
     <!-- 操作按钮 - 右上角 -->
     <div class="action-buttons-top">
       <button class="action-btn password-btn" @click="goToPasswordLogin">
-        <i class="fas fa-key" />
+        <i class="fas fa-key" style="color: #1890FF !important;" />
         密码登录
       </button>
       <button class="action-btn restart-btn" @click="handleRestart">
-        <i class="fas fa-redo-alt" />
+        <i class="fas fa-redo-alt" style="color: #1890FF !important;" />
         重启识别
       </button>
     </div>
@@ -119,6 +119,7 @@ import { useRouter, useRoute } from 'vue-router';
 import { ref, onMounted, onUnmounted } from 'vue';
 import { showNotify } from 'vant';
 import { queryRemindTime } from '../api/login.js';
+import { showErrorDialog } from '../util/errorDialog.js';
 
 // 图片资源
 import bgImg from '../assets/images/bj.png';
@@ -161,7 +162,7 @@ const handleFingerprintResponse = data => {
 
     if (!data) {
         updateStatus('failed', '识别失败,未接收到数据');
-        showNotify({ type: 'danger', message: '识别失败' });
+        showErrorDialog('识别失败');
         return;
     }
 
@@ -215,7 +216,7 @@ const handleFingerprintResponse = data => {
 const startRecognize = () => {
     if (!plugin.fingerprintConfig) {
         updateStatus('failed', '指纹设备插件未就绪');
-        showNotify({ type: 'danger', message: '设备不支持指纹识别功能' });
+        showErrorDialog('设备不支持指纹识别功能');
         return;
     }
 
@@ -224,7 +225,7 @@ const startRecognize = () => {
     } catch (error) {
         console.error('启动指纹识别失败', error);
         updateStatus('failed', '启动识别失败');
-        showNotify({ type: 'danger', message: '启动识别失败' });
+        if(error.status !== 401) showErrorDialog('启动识别失败');
     }
 };
 
@@ -271,15 +272,15 @@ const checkPasswordReminder = async () => {
         if (res.errorCode === 0) {
             if (res.data === true) {
                 setTimeout(() => {
-                    showNotify({ type: 'danger', message: res.errorMessage });
+                    showErrorDialog(res.errorMessage);
                 }, 4000);
             }
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage });
+            showErrorDialog(res.errorMessage);
         }
     } catch (error) {
         console.error('提示修改密码Api调用失败', error);
-        showNotify({ type: 'danger', message: '提示修改密码Api调用失败' });
+        if(error.status !== 401) showErrorDialog('提示修改密码Api调用失败');
     }
 };
 

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 510 - 160
src/login/UserHome.vue


+ 9 - 8
src/login/UserLogin.vue

@@ -175,6 +175,7 @@ import { useRouter, useRoute } from 'vue-router';
 import { loginApi, queryRemindTime, queryAwayAbnormalCar } from '../api/login.js';
 import { getFormattedDateTime } from '../common/Common.js';
 import { showNotify } from 'vant';
+import { showErrorDialog } from '../util/errorDialog.js';
 
 // 图片资源
 // import bgImg from '../assets/images/bj.png';
@@ -236,7 +237,7 @@ onMounted(() => {
 const handleLogin = async () => {
     if (!username.value || !password.value) {
     // message.error('请输入完整的登录信息');
-        showNotify({ type: 'danger', message: '请输入完整的登录信息' });
+        showErrorDialog('请输入完整的登录信息');
         return;
     }
 
@@ -269,15 +270,15 @@ const handleLogin = async () => {
             } else {
                 router.push('/home');
             }
-            // checkPasswordReminder();
+            checkPasswordReminder();
             checkAwayAbnormalCar();
             //登录成功播放提示音
             plugin.soundPlay.playLogin();
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage });
+            showErrorDialog(res.errorMessage);
         }
     } catch (error) {
-        showNotify({ type: 'danger', message: '登录API调用失败' });
+        showErrorDialog('登录API调用失败');
     } finally {
         loading.value = false;
     }
@@ -289,15 +290,15 @@ const checkPasswordReminder = async () => {
         if (res.errorCode === 0) {
             if (res.data === true) {
                 setTimeout(() => {
-                    showNotify({ type: 'danger', message: res.errorMessage });
+                    showErrorDialog(res.errorMessage);
                 }, 4000);
             }
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage });
+            showErrorDialog(res.errorMessage);
         }
     } catch (error) {
         console.error('提示修改密码Api调用失败', error);
-        showNotify({ type: 'danger', message: '提示修改密码Api调用失败' });
+        if(error.status !== 401) showErrorDialog('提示修改密码Api调用失败');
     }
 };
 
@@ -335,7 +336,7 @@ const handleFingerprintLogin = () => {
 
 // 忘记密码处理函数
 const handleForgotPassword = () => {
-    showNotify({ type: 'danger', message: '请联系管理员重置密码' });
+    showErrorDialog('请联系管理员重置密码');
 };
 
 // 组件卸载时清理资源

+ 8 - 0
src/main.js

@@ -10,6 +10,8 @@ import 'pc-component-v3/dist/pc-component-v3.css';
 // import 'ant-design-vue/dist/reset.css';
 import './assets/css/main.css';
 import './assets/css/common.css';
+import './assets/css/light-theme.css';
+import './assets/css/light-theme-components.css';
 import routes from './router/routes.js';
 import $ from 'jquery';
 
@@ -18,10 +20,16 @@ import 'vant/lib/index.css';
 
 import DataVVue3 from '@kjgl77/datav-vue3';
 
+// 导入主题管理器并初始化
+import { initTheme } from './util/theme.js';
+
 window.$ = $;
 window.jQuery = $;
 window.PcComponentV3 = PcComponentV3;
 
+// 初始化主题
+initTheme();
+
 
 let instance = null;
 const router = createRouter({

+ 5 - 1
src/router/routes.js

@@ -14,6 +14,9 @@ const StockPickingCar = () => import('../stock/StockPickingCar.vue');
 const OrderPicking = () => import('../stock-out/OrderPicking.vue');
 // 出库确认
 const OutboundConfirm = () => import('../stock-out/OutboundConfirm.vue');
+// 还料离开
+const OutboundLeave = () => import('../stock-out/OutboundLeave.vue');
+
 // 还料离开
 // const ReturnedLeave = () => import('../stock-in/ReturnedLeave.vue');
 // 离开
@@ -52,11 +55,12 @@ const FeedingArea = () => import('../box/FeedingArea.vue');
 const ControlGate = () => import('../gate/ControlGate.vue');
 
 const routes = [
-    { path: '/', redirect: '/fingerprint-login' },
+    { path: '/', redirect: '/home' },
     { path: '/login', component: UserLogin, meta: { title: '用户登录' } },
     { path: '/home', component: UserHome, meta: { title: '首页' } },
     { path: '/order-picking', component: OrderPicking, meta: { title: '拣货管理' } },
     { path: '/outbound-confirm', component: OutboundConfirm, meta: { title: '借用' } },
+    { path: '/outbound-leave', component: OutboundLeave, meta: { title: '还料离开' } },
     { path: '/material-in-out-leave', component: MaterialInOutConfirm, meta: { title: '离开' } },
 
     // { path: '/returned-leave', component: ReturnedLeave, meta: { title: '还料离开' } },    

+ 10 - 9
src/stock-in/InConfirm.vue

@@ -142,6 +142,7 @@ import { ref,reactive, onMounted, computed, onUnmounted } from 'vue';
 import { cfStockIn, createStockIn } from '../api/stockIn.js';
 import { areArraysEqual } from '../common/utils.js';
 import { gateController } from '../hardware/GateOperate.js';
+import { showErrorDialog } from '../util/errorDialog.js';
 
 // 图片资源
 import bgImg from '../assets/images/bj.png';
@@ -290,11 +291,11 @@ const getList = async () => {
             }
         } else {
             materialList.value = [];
-            showNotify({ type: 'danger', message: res.errorMessage });
+            showErrorDialog(res.errorMessage);
         }
     } catch (error) {
         console.error('获取物料列表API调用失败:', error);
-        showNotify({ type: 'danger', message: '获取物料列表API调用失败' });
+        if(error.status !== 401) showErrorDialog('获取物料列表API调用失败');
         // 处理查询失败的物料
         tempMaterialList.forEach(item => {
             item.queryStatus = 0;
@@ -317,14 +318,14 @@ const generateCFStockIn = async params => {
             
             showNotify({ type: 'success', message: '归还申请已完成,还料任务已创建!' });
             // 跳转回主页
-            router.push('/');
+            router.push('/home');
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage });
+            showErrorDialog(res.errorMessage);
         }
 
     } catch (error) {
         console.error('生成CF归还单API调用失败:', error);
-        showNotify({ type: 'danger', message: '生成CF归还单API调用失败' });
+        if(error.status !== 401) showErrorDialog('生成CF归还单API调用失败');
     } finally {
         loading.value = false;
     }
@@ -396,7 +397,7 @@ const unrecognizedCount = computed(() => {
 
 const handleSelect = item => {
     if(item.remarks === '在库'){
-        showNotify({ type: 'danger', message: '该物料已在库,不可选择,请选择不在库的物料!' });
+        showErrorDialog('该物料已在库,不可选择,请选择不在库的物料!');
         return;
     }
     if(item.remarks === '不在库'){
@@ -413,7 +414,7 @@ const enterConfirm = () => {
     gateController('SHOTOPEN');
             
     // 跳转回主页
-    router.push('/');
+    router.push('/home');
 };
 </script>
 
@@ -450,7 +451,7 @@ const enterConfirm = () => {
   flex: 1;
   display: flex;
   flex-direction: column;
-  padding: 0 30px;
+  padding: 20px 30px;
   position: relative;
   z-index: 10;
   min-height: 0;
@@ -787,7 +788,7 @@ const enterConfirm = () => {
   }
 
   .main-content {
-    padding: 0 20px;
+    padding: 20px;
   }
 
   .stats-section {

+ 10 - 9
src/stock-in/ReturnedLeave.vue

@@ -107,6 +107,7 @@ import { ref, onMounted, computed, onUnmounted } from 'vue';
 import { queryCFStockInByUser, backfillCFStockInTime, cfStockInLeave } from '../api/stockIn.js';
 import { areArraysEqual } from '../common/utils.js';
 import { gateController } from '../hardware/GateOperate.js';
+import { showErrorDialog } from '../util/errorDialog.js';
 
 // 图片资源
 import bgImg from '../assets/images/bj.png';
@@ -206,12 +207,12 @@ const getCFStockInByUser = async () => {
                 inList.value = [];
             }
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage,zIndex: 99999999 });
+            showErrorDialog(res.errorMessage);
             getInnerList();
         }
     } catch (error) {
         console.error('获取物料列表API调用失败:', error);
-        showNotify({ type: 'danger', message: '获取物料列表API调用失败' });
+        if(error.status !== 401) showErrorDialog('获取物料列表API调用失败');
     }
 };
 
@@ -237,14 +238,14 @@ const getInnerList = async () => {
                 });
                 materialList.value = [...userMaterialList.value, ...res.datas];
                 validateList.value = res.datas;
-                showNotify({ type: 'danger', message: '检测到您已携带工装设备,请将工装设备全部还料后,再次点击【重新校验】按钮,待校验通过后,请在闸机开门后离开', duration: 6000 });
+                showErrorDialog('检测到您已携带工装设备,请将工装设备全部还料后,再次点击【重新校验】按钮,待校验通过后,请在闸机开门后离开');
             } else {
-                showNotify({ type: 'danger', message: res.errorMessage });
+                showErrorDialog(res.errorMessage);
             }
         }
     } catch (error) {
         console.error('获取物料列表API调用失败:', error);
-        showNotify({ type: 'danger', message: '获取物料列表API调用失败' });
+        if(error.status !== 401) showErrorDialog('获取物料列表API调用失败');
     } finally {
         loading.value = false;
     }
@@ -261,12 +262,12 @@ const generateCFStockIn = async params => {
             showNotify({ type: 'success', message: '还料离开已完成!' });
             router.push('/home');
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage });
+            showErrorDialog(res.errorMessage);
         }
 
     } catch (error) {
         console.error('生成CF离开单API调用失败:', error);
-        showNotify({ type: 'danger', message: '生成CF离开单API调用失败' });
+        if(error.status !== 401) showErrorDialog('生成CF离开单API调用失败');
     } finally {
         loading.value = false;
     }
@@ -347,7 +348,7 @@ onUnmounted(() => {
   flex: 1;
   display: flex;
   flex-direction: column;
-  padding: 0 30px;
+  padding: 20px 30px;
   position: relative;
   z-index: 10;
   min-height: 0;
@@ -654,7 +655,7 @@ onUnmounted(() => {
   }
 
   .main-content {
-    padding: 0 20px;
+    padding: 20px;
   }
 
   .stats-section {

+ 16 - 13
src/stock-out/AgvRfidRecognition.vue

@@ -27,7 +27,7 @@
         <div class="status-header">
           <div class="status-title">
             <i class="fas fa-tasks" />
-            <span>任务状态</span>
+            <span class="agv-title">任务状态</span>
           </div>
           <div class="status-badge" :class="taskStatus.success ? 'success' : 'error'">
             <i :class="taskStatus.success ? 'fas fa-check-circle' : 'fas fa-exclamation-circle'" />
@@ -59,7 +59,7 @@
               <i class="fas fa-box-open" />
             </div>
             <div class="card-title">
-              <h3>目标搬运</h3>
+              <h3 class="agv-title">目标搬运</h3>
               <p>AGV 应当搬运的信息</p>
             </div>
           </div>
@@ -97,7 +97,7 @@
               <i class="fas fa-tags" />
             </div>
             <div class="card-title">
-              <h3>已识别列表</h3>
+              <h3 class="agv-title">已识别列表</h3>
               <p>RFID 实际扫描到的设备信息</p>
             </div>
           </div>
@@ -147,6 +147,7 @@ import { useRouter } from 'vue-router';
 import { ref, computed, onMounted } from 'vue';
 import { getAgvRfidLogByTaskId } from '../api/stockOut.js';
 import { showNotify } from 'vant';
+import { showErrorDialog } from '../util/errorDialog.js';
 
 // 图片资源
 import bgImg from '../assets/images/bj.png';
@@ -225,15 +226,17 @@ const getAgvRfidLog = async () => {
 
             // message.success('获取识别结果成功');
         } else {
-            showNotify({ type: 'danger',  message: '暂无识别记录',  duration: 3000 });
+            showErrorDialog('暂无识别记录');
         }
     } catch (error) {
         console.error('获取RFID识别记录失败:', error);
-        showNotify({
-            type: 'danger',
-            message: '获取识别结果失败',
-            duration: 3000,
-        });
+        if(error.status !== 401) {
+            showNotify({
+                type: 'danger',
+                message: '获取识别结果失败',
+                duration: 3000,
+            });
+        }
     } finally {
         loading.value = false;
     }
@@ -335,7 +338,7 @@ const handleCancelTask = () => {
   flex: 1;
   display: flex;
   flex-direction: column;
-  padding: 0 30px 20px;
+  padding: 20px 30px 20px;
   position: relative;
   z-index: 10;
   min-height: 0;
@@ -392,7 +395,7 @@ const handleCancelTask = () => {
 .status-badge.error {
   background: rgba(239, 68, 68, 0.3);
   border: 1px solid #ef4444;
-  color: #fca5a5;
+  color: red;
 }
 
 .status-info-grid {
@@ -633,7 +636,7 @@ const handleCancelTask = () => {
 /* ========== 响应式 - 横屏 1920*1080 ========== */
 @media screen and (orientation: landscape) {
   .main-content {
-    padding: 0 30px 20px;
+    padding: 20px 30px 20px;
     gap: 20px;
   }
 
@@ -726,7 +729,7 @@ const handleCancelTask = () => {
 /* ========== 响应式 - 竖屏 1080*1920 ========== */
 @media screen and (orientation: portrait) {
   .main-content {
-    padding: 0 30px 30px;
+    padding: 20px 30px 30px;
     gap: 25px;
   }
 

+ 17 - 16
src/stock-out/MaterialInOutConfirm.vue

@@ -185,6 +185,7 @@ import { cfStockOut, createStockOut, cfStockOutLeave,leaveCFWarehouse } from '..
 import { areArraysEqual } from '../common/utils.js';
 import { gateController } from '../hardware/GateOperate.js';
 import { queryCFStockInByUser, backfillCFStockInTime, cfStockInLeave } from '../api/stockIn.js';
+import { showErrorDialog } from '../util/errorDialog.js';
 
 // 图片资源
 import bgImg from '../assets/images/bj.png';
@@ -279,11 +280,11 @@ const handleApply = async record => {
             showNotify({ type: 'success', message: '申请领料成功' });
             getStockOutList();
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage });
+            showErrorDialog(res.errorMessage);
         }
     } catch (error) {
         console.error('申请领料API调用失败:', error);
-        showNotify({ type: 'danger', message: '申请领料API调用失败' });
+        if(error.status !== 401) showErrorDialog('申请领料API调用失败');
     } finally {
         loading.value = false;
     }
@@ -329,7 +330,7 @@ const handleLeave = async () => {
     if(params.length == 0){
         // 直接开门离开
         gateController('SHOTOPEN');
-        router.push('/');
+        router.push('/home');
         return;
     }
 
@@ -341,13 +342,13 @@ const handleLeave = async () => {
         if (res.errorCode === 0) {
             gateController('SHOTOPEN');
             showNotify({ type: 'success', message: '领料离开成功' });
-            router.push('/');
+            router.push('/home');
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage });
+            showErrorDialog(res.errorMessage);
         }
     } catch (error) {
         console.error('领料离开API调用失败:', error);
-        showNotify({ type: 'danger', message: '领料离开API调用失败' });
+        if(error.status !== 401) showErrorDialog('领料离开API调用失败');
     } finally {
         loading.value = false;
     }
@@ -399,12 +400,12 @@ const getStockOutList = async () => {
                 });
             }
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage });
+            showErrorDialog(res.errorMessage);
         }
         computerErrorData();
     } catch (error) {
         console.error('获取扫描到的领料数据API调用失败:', error);
-        showNotify({ type: 'danger', message: '获取扫描到的领料数据API调用失败' });
+        if(error.status !== 401) showErrorDialog('获取扫描到的领料数据API调用失败');
         // 处理查询失败的物料
         tempMaterialList.forEach(item => {
             item.queryStatus = 0;
@@ -429,12 +430,12 @@ const generateCFStockOut = async id => {
         if (res.errorCode === 0) {
             getStockOutList();
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage });
+            showErrorDialog(res.errorMessage);
         }
 
     } catch (error) {
         console.error('生成出库单API调用失败:', error);
-        showNotify({ type: 'danger', message: '生成出库单API调用失败' });
+        if(error.status !== 401) showErrorDialog('生成出库单API调用失败');
     } finally {
         loading.value = false;
     }
@@ -521,12 +522,12 @@ const getCFStockInByUser = async () => {
                 // userMaterialList.value = [];
             }
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage,zIndex: 99999999 });
+            showErrorDialog(res.errorMessage);
             // getInnerList();
         }
     } catch (error) {
         console.error('获取物料列表API调用失败:', error);
-        showNotify({ type: 'danger', message: '获取物料列表API调用失败' });
+        if(error.status !== 401) showErrorDialog('获取物料列表API调用失败');
     }
 };
 
@@ -546,12 +547,12 @@ const generateCFStockIn = async params => {
             //showNotify({ type: 'success', message: '还料离开已完成!' });
             //router.push('/home');
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage });
+            showErrorDialog(res.errorMessage);
         }
 
     } catch (error) {
         console.error('生成CF离开单API调用失败:', error);
-        showNotify({ type: 'danger', message: '生成CF离开单API调用失败' });
+        if(error.status !== 401) showErrorDialog('生成CF离开单API调用失败');
     } finally {
         loading.value = false;
     }
@@ -637,7 +638,7 @@ const resetView = () => {
   flex: 1;
   display: flex;
   flex-direction: column;
-  padding: 0 30px;
+  padding: 20px 30px;
   position: relative;
   z-index: 10;
   min-height: 0;
@@ -948,7 +949,7 @@ const resetView = () => {
   }
 
   .main-content {
-    padding: 0 20px;
+    padding: 20px;
   }
 
   .stats-section {

+ 16 - 14
src/stock-out/OrderPicking.vue

@@ -155,7 +155,7 @@
                     :options="locator" :clearable="false" class="location-select dark-select" :append-to-body="true"
                     :calculate-position="withPopper"
                   />
-                  <span v-else style="font-size: 16px;">人工配送</span>
+                  <span v-else style="font-size: 16px; color: #168aff;">人工配送</span>
                 </div>
               </template>
               <!-- 未选中时显示占位 -->
@@ -221,6 +221,8 @@ import { createPopper } from '@popperjs/core';
 import { list, createStockOut } from '../api/stockOut.js';
 import { getWarehouseList, queryIdleLocator } from '../api/stock.js';
 import { gateController } from '../hardware/GateOperate.js';
+import { showErrorDialog } from '../util/errorDialog.js';
+
 // 图片资源
 import bgImg from '../assets/images/bj.png';
 
@@ -431,7 +433,7 @@ const addToRequisition = record => {
 // 领料申请,直接验证并提交
 const handleComplete = async () => {
     if (selectedIds.value.length === 0) {
-        showNotify({ type: 'danger', message: '请至少选择一个物料' });
+        showErrorDialog('请至少选择一个物料');
         return;
     }
 
@@ -440,7 +442,7 @@ const handleComplete = async () => {
     const hasEmptyLocation = agvItems.some(item => !item.selectedLocation);
 
     if (hasEmptyLocation) {
-        showNotify({ type: 'danger', message: '请为所有 AGV 配送的物料选择配送位置' });
+        showErrorDialog('请为所有 AGV 配送的物料选择配送位置');
         return;
     }
 
@@ -528,12 +530,12 @@ const getList = async () => {
                 materialList.value = [];
             }
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage });
+            showErrorDialog(res.errorMessage);
         }
     } catch (error) {
         loading.value = false;
         console.error('获取物料列表API调用失败:', error);
-        showNotify({ type: 'danger', message: '获取物料列表API调用失败' });
+        if(error.status !== 401) showErrorDialog('获取物料列表API调用失败');
         return;
     }
 };
@@ -550,12 +552,12 @@ const generateCFStockOut = async params => {
             // 显示完成确认弹窗
             completeModalVisible.value = true;
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage });
+            showErrorDialog(res.errorMessage);
         }
 
     } catch (error) {
         console.error('生成CF出库单API调用失败:', error);
-        showNotify({ type: 'danger', message: '生成CF出库单API调用失败' });
+        if(error.status !== 401) showErrorDialog('生成CF出库单API调用失败');
     } finally {
         loading.value = false;
     }
@@ -566,7 +568,7 @@ const handleCompleteConfirm = () => {
     // 调用开门操作
     gateController('SHOTOPEN');
     completeModalVisible.value = false;
-    router.push('/');
+    router.push('/home');
     // showToast('领料申请已完成,配送任务已创建!');
 };
 
@@ -589,11 +591,11 @@ const getWarehouse = async () => {
                 warehouseList.value = [];
             }
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage });
+            showErrorDialog(res.errorMessage);
         }
     } catch (error) {
         console.error('获取仓库列表API调用失败:', error);
-        showNotify({ type: 'danger', message: '获取仓库列表API调用失败' });
+        if(error.status !== 401) showErrorDialog('获取仓库列表API调用失败');
     } finally {
         loading.value = false;
     }
@@ -615,11 +617,11 @@ const getIdleLocator = async () => {
                 locator.value = [];
             }
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage });
+            showErrorDialog(res.errorMessage);
         }
     } catch (error) {
         console.error('获取空闲货位API调用失败:', error);
-        showNotify({ type: 'danger', message: '获取空闲货位API调用失败' });
+        if(error.status !== 401) showErrorDialog('获取空闲货位API调用失败');
     }
 };
 
@@ -663,7 +665,7 @@ onMounted(() => {
   flex: 1;
   display: flex;
   flex-direction: column;
-  padding: 0 30px;
+  padding: 20px 30px;
   position: relative;
   z-index: 10;
   min-height: 0;
@@ -1172,7 +1174,7 @@ onMounted(() => {
   }
 
   .main-content {
-    padding: 0 20px;
+    padding: 20px;
   }
 
   .filter-section {

+ 17 - 16
src/stock-out/OutboundConfirm.vue

@@ -159,6 +159,7 @@ import { showNotify } from 'vant';
 import { cfStockOut, createStockOut, cfStockOutLeave,leaveCFWarehouse } from '../api/stockOut.js';
 import { areArraysEqual } from '../common/utils.js';
 import { gateController } from '../hardware/GateOperate.js';
+import { showErrorDialog } from '../util/errorDialog.js';
 
 // 图片资源
 import bgImg from '../assets/images/bj.png';
@@ -250,12 +251,12 @@ const validMaterialList = computed(() => {
 const handleSelect = item => {
     // 不在库和未识别epc的卡片不可选中
     if (item.positionName === '不在库' || item.inventoryName === '未识别epc') {
-        showNotify({ type: 'danger', message: '不在库或尚未借用的卡片不可选中' });
+        showErrorDialog('不在库或尚未借用的卡片不可选中');
         return;
     }
     // 只有已借用状态(status === 1)的卡片才可被勾选
     if (item.status !== 1) {
-        showNotify({ type: 'danger', message: '只有已借用状态的卡片才可被勾选' });
+        showErrorDialog('只有已借用状态的卡片才可被勾选');
         return;
     }
     item.selected = !item.selected;
@@ -267,7 +268,7 @@ const exitConfirmVisible = ref(false);
 // 处理离开按钮点击
 const handleLeaveClick = () => {
     gateController('SHOTOPEN');
-    router.push('/');
+    router.push('/home');
     // if (selectedCount.value === 0) {
     //     exitConfirmVisible.value = true;
     //     return;
@@ -280,7 +281,7 @@ const directExit = () => {
     exitConfirmVisible.value = false;
     // 直接开门离开
     gateController('SHOTOPEN');
-    router.push('/');
+    router.push('/home');
 };
 
 // 开始借用
@@ -314,11 +315,11 @@ const handleApply = async record => {
                 });
             }
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage });
+            showErrorDialog(res.errorMessage);
         }
     } catch (error) {
         console.error('申请借用API调用失败:', error);
-        showNotify({ type: 'danger', message: '申请借用API调用失败' });
+        if(error.status !== 401) showErrorDialog('申请借用API调用失败');
     } finally {
         loading.value = false;
     }
@@ -339,7 +340,7 @@ const handleLeave = async () => {
     if(params.length == 0){
         // 直接开门离开
         gateController('SHOTOPEN');
-        router.push('/');
+        router.push('/home');
         return;
     }
 
@@ -351,13 +352,13 @@ const handleLeave = async () => {
         if (res.errorCode === 0) {
             gateController('SHOTOPEN');
             showNotify({ type: 'success', message: '借用离开成功' });
-            router.push('/');
+            router.push('/home');
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage });
+            showErrorDialog(res.errorMessage);
         }
     } catch (error) {
         console.error('借用离开API调用失败:', error);
-        showNotify({ type: 'danger', message: '借用离开API调用失败' });
+        if(error.status !== 401) showErrorDialog('借用离开API调用失败');
     } finally {
         loading.value = false;
     }
@@ -413,11 +414,11 @@ const getStockOutList = async () => {
                 });
             }
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage });
+            showErrorDialog(res.errorMessage);
         }
     } catch (error) {
         console.error('获取扫描到的借用数据API调用失败:', error);
-        showNotify({ type: 'danger', message: '获取扫描到的借用数据API调用失败' });
+        if(error.status !== 401) showErrorDialog('获取扫描到的借用数据API调用失败');
         tempMaterialList.forEach(item => {
             item.queryStatus = 0;
         });
@@ -442,12 +443,12 @@ const generateCFStockOut = async id => {
             // getStockOutList();
             resetView();
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage });
+            showErrorDialog(res.errorMessage);
         }
 
     } catch (error) {
         console.error('生成出库单API调用失败:', error);
-        showNotify({ type: 'danger', message: '生成出库单API调用失败' });
+        if(error.status !== 401) showErrorDialog('生成出库单API调用失败');
     } finally {
         loading.value = false;
     }
@@ -540,7 +541,7 @@ onUnmounted(() => {
   flex: 1;
   display: flex;
   flex-direction: column;
-  padding: 0 30px;
+  padding: 20px 30px;
   position: relative;
   z-index: 10;
   min-height: 0;
@@ -932,7 +933,7 @@ onUnmounted(() => {
   }
 
   .main-content {
-    padding: 0 20px;
+    padding: 20px;
   }
 
   .stats-section {

+ 828 - 0
src/stock-out/OutboundLeave.vue

@@ -0,0 +1,828 @@
+<!-- 借用 - 智能仓储风格 -->
+<template>
+  <dv-border-box-8>
+    <div class="stock-requisition-page">
+      <!-- 背景层 -->
+      <div class="bg-layer" :style="{ backgroundImage: `url(${bgImg})` }" />
+
+      <!-- 顶部标题区域 -->
+      <div class="header-section">
+        <button class="logout-btn" @click="goHome">
+          <i class="fas fa-home" />
+          <span>主页</span>
+        </button>
+        <h1 class="page-title">还料离开</h1>
+        <!-- 右侧操作按钮 -->
+        <div class="header-actions">
+          <button class="action-btn refresh-btn" @click="resetView">
+            <i class="fas fa-sync-alt" />
+            <span>重新校验</span>
+          </button>
+        </div>
+      </div>
+
+      <!-- 主内容区域 -->
+      <main class="main-content">
+        <!-- 统计信息 -->
+        <div v-if="materialList.length > 0" class="stats-section">
+          <!-- <span class="stats-text">共 {{ materialList.length }} 条数据,已完成 {{ completedCount }} 条</span> -->
+          <span class="stats-text">共 {{ materialList.length }} 条数据,不识别 {{ unrecognizedCount }} 条</span>
+        </div>
+
+        <!-- 卡片网格区域 -->
+        <div class="card-grid-wrapper">
+          <!-- 空状态 -->
+          <div v-if="materialList.length === 0 && !loading" class="empty-state">
+            <i class="fas fa-inbox empty-icon" />
+            <p>暂无数据</p>
+          </div>
+
+          <!-- 卡片网格 -->
+          <div v-else class="card-grid">
+            <template v-for="(item, index) in validMaterialList" :key="item.inventoryId || index">
+              <div
+                class="inventory-card"
+                :class="{ 
+                  'completed': item.status === 1 || item.status === 3, 
+                  'not-selectable': item.positionName === '不在库' || item.inventoryName === '未识别epc'
+                }"
+              >
+                <!-- @click="handleSelect(item)" -->
+                <!-- 'selected': item.selected, -->
+                <!-- 'warning': item.status === 2 || item.status === 3, -->
+                <!-- 卡片序号 -->
+                <div class="card-index" :class="{ 'completed': item.status === 1 }">{{ index + 1 }}</div>
+
+                <!-- 信息区域 -->
+                <div class="card-info">
+                  <div class="info-row">
+                    <span class="info-label">名称:</span>
+                    <span class="info-value">{{ item.inventoryName || '-' }}</span>
+                  </div>
+                  <div class="info-row">
+                    <span class="info-label">编号:</span>
+                    <span class="info-value">{{ item.inventoryNo || '-' }}</span>
+                  </div>
+                  <div class="info-row">
+                    <span class="info-label">类型:</span>
+                    <span class="info-value">{{ item.inventoryType || '-' }}</span>
+                    <i :class="getInventoryIcon(item.inventoryType)" class="type-icon" />
+                  </div>
+                  <div class="info-row location-row">
+                    <i class="fas fa-map-marker-alt location-icon" />
+                    <span class="info-value">{{ item.positionName || '-' }} / {{ item.warehouseName || '-' }}</span>
+                  </div>
+                  <!-- 不在库的借用人信息显示在内容区域 -->
+                  <div v-if="item.positionName === '不在库'" class="info-row borrower-row">
+                    <span class="info-label">借用人:</span>
+                    <span class="info-value">{{ item.borrower || '-' }}</span>
+                  </div>
+                  <div v-else class="borrower-row">
+                    <span class="info-label">-</span>
+                  </div>
+                </div>
+
+                <!-- 操作区域(固定高度) -->
+                <!-- <div class="card-action-section">
+                  <template v-if="item.positionName !== '不在库' && item.inventoryName !== '未识别epc'">
+                    <button v-if="item.status === 1 || item.status === 3" class="status-btn apply-btn" @click.stop="handleApply(item)">
+                      <i class="fas fa-hand-paper" /> 借用
+                    </button>
+                  </template>
+                  <template v-else-if="item.positionName === '不在库'">
+                    <div class="status-badge borrowed-badge">
+                      <i class="fas fa-exclamation-circle" />
+                      已借用
+                    </div>
+                  </template>
+                  <template v-else>
+                    <span class="status-placeholder">无需操作</span>
+                  </template>
+                </div> -->
+
+                <!-- 选中状态指示 -->
+                <!-- <div v-if="item.selected" class="selected-indicator">
+                  <i class="fas fa-check" />
+                </div> -->
+              </div>
+            </template>
+          </div>
+        </div>
+      </main>
+
+      <!-- 底部操作按钮 -->
+      <div class="bottom-actions">
+        <button class="submit-btn" :disabled="hasValidMaterials || !canClickButton" @click="handleLeaveClick">
+          闸机开门
+        </button>
+      </div>
+
+      <!-- Loading -->
+      <div v-if="loading" class="loading-overlay">
+        <div class="loading-dots">
+          <div class="dot" />
+          <div class="dot" />
+          <div class="dot" />
+        </div>
+        <span class="loading-text">执行中...</span>
+      </div>
+    </div>
+  </dv-border-box-8>
+</template>
+
+<script setup>
+import { useRouter } from 'vue-router';
+import { ref, computed, onMounted, onUnmounted } from 'vue';
+import { cfStockOut } from '../api/stockOut.js';
+import { gateController } from '../hardware/GateOperate.js';
+import { showErrorDialog } from '../util/errorDialog.js';
+
+// 图片资源
+import bgImg from '../assets/images/bj.png';
+
+// 路由
+const router = useRouter();
+
+// 返回主页
+const goHome = () => {
+    router.push('/home');
+};
+
+// 表格加载状态
+const loading = ref(false);
+
+// 物料列表数据
+const materialList = ref([]);
+
+// 控制按钮是否可点击(页面加载2秒后才可点击)
+const canClickButton = ref(false);
+
+// 获取设备类型图标
+const getInventoryIcon = type => {
+    const iconMap = {
+        '工装': 'fas fa-cube',
+        '设备': 'fas fa-cogs',
+        '成品': 'fas fa-box',
+    };
+    return iconMap[type] || 'fas fa-cube';
+};
+
+const unrecognizedCount = computed(() => {
+    return materialList.value.filter(item => item.inventoryId == null).length;
+});
+
+// 判断是否有有效物料(含有inventoryId)
+const hasValidMaterials = computed(() => {
+    return materialList.value.length > 0 && materialList.value.some(item => item.inventoryId != null);
+});
+
+// 过滤出有效的物料项目(用于连续序号显示)
+const validMaterialList = computed(() => {
+    return materialList.value.filter(item => item.inventoryId != null);
+});
+
+// 卡片选择处理
+const handleSelect = item => {
+    // 不在库和未识别epc的卡片不可选中
+    if (item.positionName === '不在库' || item.inventoryName === '未识别epc') {
+        showErrorDialog('不在库或尚未借用的卡片不可选中');
+        return;
+    }
+    // 只有已借用状态(status === 1)的卡片才可被勾选
+    if (item.status !== 1) {
+        showErrorDialog('只有已借用状态的卡片才可被勾选');
+        return;
+    }
+    item.selected = !item.selected;
+};
+
+// 处理离开按钮点击
+const handleLeaveClick = () => {
+    gateController('SHOTOPEN');
+    router.push('/home');
+};
+
+const resetView = () => {
+    materialList.value = [];
+};
+
+// 获取扫描到的借用数据
+const getStockOutList = async () => {
+    // loading.value = true;
+    const params = {
+        epcList: [],
+    };
+
+    const tempMaterialList = [];
+
+    for(let i = 0; i < materialList.value.length; i++) {
+        if(materialList.value[i].queryStatus === 0) {
+            params.epcList.push(materialList.value[i].epc);
+            materialList.value[i].queryStatus = 1;
+            tempMaterialList.push(materialList.value[i]);
+        }
+    }
+
+    if(params.epcList.length == 0){
+        return;
+    }
+    try {
+        const res = await cfStockOut(params);
+
+        if (res.errorCode === 0) {
+            if (res.datas && res.datas.length > 0) {
+                res.datas.forEach(i => {
+                    materialList.value.forEach(j => {
+                        if (j.epc === i.epc) {
+                            j.stockOutId = i.stockOutId;
+                            j.inventoryName = i.inventoryName;
+                            j.inventoryNo = i.inventoryNo;
+                            j.inventoryType = i.inventoryType;
+                            j.borrower = i.borrower;
+                            j.warehouseName = i.warehouseName;
+                            j.positionName = i.positionName;
+                            j.stockOutPrepareNo = i.stockOutPrepareNo;
+                            j.stockOutNo = i.stockOutNo;
+                            j.inventoryId = i.inventoryId;
+                            j.stockOutPrepareLineId = i.stockOutPrepareLineId;
+                            j.queryStatus = 2;
+                            j.status = i.status;
+                        }
+                    });
+                });
+            }
+        } else {
+            showErrorDialog(res.errorMessage);
+        }
+    } catch (error) {
+        console.error('获取扫描到的借用数据API调用失败:', error);
+        if(error.status !== 401) showErrorDialog('获取扫描到的借用数据API调用失败');
+        tempMaterialList.forEach(item => {
+            item.queryStatus = 0;
+        });
+    } finally {
+        loading.value = false;
+    }
+};
+
+
+let timer = null; // 用于保存当前定时器引用
+
+const addEpc = data => {
+    const newEpcs = data.map(item => item.epc);
+    
+    // 将新的EPC数据添加到临时数组中,使用Set进行去重
+    const uniqueEpcs = new Set([...newEpcs]);
+
+    if(newEpcs != null && newEpcs.length > 0) {
+        newEpcs.forEach(item => {
+            let exist = false;
+            for(let i =0; i < materialList.value.length; i++) {
+                if(materialList.value[i].epc === item) {
+                    exist = true;
+                    break;
+                }
+            }
+            if(exist == false) {
+                materialList.value.push({
+                    epc: item,
+                    queryStatus: 0, // 0: 未查询, 1: 查询中, 2: 已查询, 3: 未查询到
+                    selected: false, // 初始化选中状态
+                });
+            }
+        });
+    }
+};
+
+onMounted(() => {
+    plugin.gateConfig.sendEpc = function(data){
+        if (typeof(GATE_CONFIG) == 'undefined') {
+            console.log('设备不支持读写器功能。');
+        } else {
+            addEpc(data);
+        }
+    };
+
+    // 2秒后启用按钮
+    setTimeout(() => {
+        canClickButton.value = true;
+    }, 2000);
+
+    // 创建全局唯一定时器,每2秒执行一次
+    timer = setInterval(() => {
+        getStockOutList();
+        // addEpc([ { 'epc': 'EEE000000640804317955613' }, { 'epc': 'FFF000000000000000000001' },{ 'epc': 'AAA000000000000000000002' }]);
+    }, 1000);
+});
+
+onUnmounted(() => {
+    plugin.gateConfig.sendEpc = null;
+    // 清除定时器
+    if (timer) {
+        clearInterval(timer);
+        timer = null;
+    }
+});
+</script>
+
+<style scoped>
+/* ========== 基础样式 ========== */
+.stock-requisition-page {
+  width: 100%;
+  height: 100vh;
+  max-height: 100vh;
+  position: relative;
+  font-family: 'Microsoft YaHei', sans-serif;
+  color: #fff;
+  overflow: hidden;
+  display: flex;
+  flex-direction: column;
+}
+
+/* 背景层 */
+.bg-layer {
+  position: fixed;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  background-color: #041c3d;
+  background-size: cover;
+  background-position: center;
+  background-repeat: no-repeat;
+  z-index: 0;
+}
+
+/* ========== 主内容区域 ========== */
+.main-content {
+  flex: 1;
+  display: flex;
+  flex-direction: column;
+  padding: 20px 30px;
+  position: relative;
+  z-index: 10;
+  min-height: 0;
+  overflow: hidden;
+}
+
+/* 统计信息 */
+.stats-section {
+  background: rgba(9, 61, 140, 0.5);
+  border: 1px solid #049FD8;
+  border-radius: 12px;
+  padding: 15px 20px;
+  margin-bottom: 15px;
+  flex-shrink: 0;
+}
+
+.stats-text {
+  color: #7ec8ff;
+  font-size: 16px;
+}
+
+/* ========== 卡片网格区域 ========== */
+.card-grid-wrapper {
+  flex: 1;
+  display: flex;
+  flex-direction: column;
+  min-height: 0;
+  overflow-y: auto;
+  overflow-x: hidden;
+  padding-bottom: 10px;
+  scrollbar-width: none;
+  -ms-overflow-style: none;
+}
+
+.card-grid-wrapper::-webkit-scrollbar {
+  display: none;
+}
+
+/* 空状态 */
+.empty-state {
+  flex: 1;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  color: #7ec8ff;
+  padding: 60px 0;
+}
+
+.empty-icon {
+  font-size: 80px;
+  margin-bottom: 20px;
+  opacity: 0.5;
+}
+
+.empty-state p {
+  font-size: 18px;
+  margin: 0;
+}
+
+/* 卡片网格 - 4列布局 */
+.card-grid {
+  display: grid;
+  grid-template-columns: repeat(4, 1fr);
+  gap: 20px;
+}
+
+/* ========== 设备卡片样式 ========== */
+.inventory-card {
+  background: rgba(5, 30, 60, 0.8);
+  border: 2px solid #ef4444 !important;
+  border-radius: 12px;
+  overflow: hidden;
+  transition: all 0.3s ease;
+  position: relative;
+}
+
+.inventory-card:hover {
+  border-color: #1e90ff;
+  box-shadow: 0 0 20px rgba(30, 144, 255, 0.3);
+  transform: translateY(-3px);
+}
+
+.inventory-card.completed {
+  border-color: #10b981;
+  box-shadow: 0 0 15px rgba(16, 185, 129, 0.3);
+}
+
+.inventory-card.warning {
+  border-color: #fbbf24 !important;
+  box-shadow: 0 0 15px rgba(251, 191, 36, 0.4) !important;
+}
+
+.inventory-card.selected {
+  border-color: #fbbf24;
+  box-shadow: 0 0 20px rgba(251, 191, 36, 0.4);
+  background: rgba(251, 191, 36, 0.1);
+}
+
+/* 选中状态指示 - 右上角 */
+.selected-indicator {
+  position: absolute;
+  top: 10px;
+  right: 10px;
+  width: 28px;
+  height: 28px;
+  background: linear-gradient(135deg, #10b981 0%, #34d399 100%);
+  border-radius: 50%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  color: white;
+  font-size: 12px;
+  font-weight: bold;
+  box-shadow: 0 2px 8px rgba(16, 185, 129, 0.4);
+  z-index: 10;
+}
+
+/* 卡片序号 - 左上角 */
+.card-index {
+  position: absolute;
+  top: 10px;
+  left: 10px;
+  width: 36px;
+  height: 36px;
+  background: linear-gradient(135deg, #1e90ff 0%, #00bfff 100%);
+  border-radius: 50%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  font-size: 16px;
+  font-weight: bold;
+  color: #fff;
+  z-index: 2;
+  box-shadow: 0 2px 8px rgba(0, 191, 255, 0.4);
+}
+
+.card-index.completed {
+  /* background: linear-gradient(135deg, #10b981 0%, #34d399 100%); */
+  box-shadow: 0 2px 8px rgba(16, 185, 129, 0.4);
+}
+
+/* 类型图标样式 */
+.type-icon {
+  color: #fbbf24;
+  margin-left: 8px;
+  font-size: 16px;
+}
+
+/* 不可选择的卡片 - 红色边框 */
+.inventory-card.not-selectable {
+  border-color: #ef4444 !important;
+  box-shadow: 0 0 15px rgba(239, 68, 68, 0.3) !important;
+  cursor: not-allowed;
+}
+
+.inventory-card.not-selectable:hover {
+  border-color: #dc2626 !important;
+  box-shadow: 0 0 20px rgba(220, 38, 38, 0.4) !important;
+  transform: none;
+}
+
+/* 借用人信息样式 */
+.borrower-info {
+  display: flex;
+  flex-direction: column;
+  gap: 8px;
+  padding: 8px 0;
+  min-height: 48px; /* 确保与按钮区域高度一致 */
+}
+
+.borrower-row {
+  display: flex;
+  align-items: center;
+  font-size: 14px;
+  border-bottom: 1px solid rgba(126, 200, 255, 0.2) !important;
+}
+
+.borrower-label {
+  color: #7ec8ff;
+  white-space: nowrap;
+  margin-right: 5px;
+}
+
+.borrower-value {
+  color: #fff;
+  flex: 1;
+}
+
+/* 信息区域 */
+.card-info {
+  padding: 50px 15px 15px;
+}
+
+.info-row {
+  display: flex;
+  align-items: center;
+  padding: 6px 0; /* 增加内容块高度 */
+  font-size: 14px;
+  min-height: 28px; /* 增加最小高度 */
+  border-bottom: 1px solid rgba(126, 200, 255, 0.2); /* 添加分割线 */
+  margin-bottom: 0;
+}
+
+.info-row:last-child {
+  border-bottom: none; /* 最后一行不显示分割线 */
+}
+
+.info-label {
+  color: #7ec8ff;
+  white-space: nowrap;
+  margin-right: 5px;
+}
+
+.info-value {
+  color: #fff;
+  flex: 1;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+/* 位置行样式 */
+.location-row {
+  display: flex;
+  align-items: center;
+  margin-top: 4px;
+  /* padding-top: 4px; */
+  /* border-top: 1px solid rgba(30, 144, 255, 0.2); */
+  border-bottom: 1px solid rgba(30, 144, 255, 0.2) !important;
+}
+
+.location-icon {
+  color: #00bfff;
+  font-size: 12px;
+  margin-right: 6px;
+}
+
+/* ========== 操作区域(固定高度) ========== */
+.card-action-section {
+  padding: 8px 15px;
+  min-height: 48px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  /* 移除边框和背景色差异,与无需操作区域保持一致 */
+}
+
+.status-placeholder {
+  color: #5a8abf;
+  font-size: 14px;
+  opacity: 0.8;
+  margin-top: -10px;
+}
+
+/* 状态按钮 */
+.status-btn {
+  width: 100%;
+  padding: 10px 15px;
+  border-radius: 6px;
+  font-size: 13px;
+  font-weight: 500;
+  cursor: pointer;
+  transition: all 0.3s;
+  border: none;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  gap: 6px;
+}
+
+.completed-btn {
+  background: linear-gradient(90deg, #10b981 0%, #34d399 100%);
+  color: #fff;
+  opacity: 0.7;
+  cursor: not-allowed;
+}
+
+.start-btn {
+  background: linear-gradient(90deg, #f59e0b 0%, #fbbf24 100%);
+  color: #fff;
+}
+
+.start-btn:hover {
+  box-shadow: 0 0 15px rgba(245, 158, 11, 0.5);
+}
+
+.apply-btn {
+  background: linear-gradient(90deg, #1e90ff 0%, #00bfff 100%);
+  color: #fff;
+}
+
+.apply-btn:hover {
+  box-shadow: 0 0 15px rgba(30, 144, 255, 0.5);
+}
+
+.in-stock-btn {
+  background: linear-gradient(90deg, #10b981 0%, #34d399 100%);
+  color: #fff;
+  opacity: 0.8;
+  cursor: default;
+}
+
+/* 状态徽章样式 */
+.status-badge {
+  padding: 8px 20px;
+  border-radius: 20px;
+  font-size: 13px;
+  font-weight: 500;
+  display: flex;
+  align-items: center;
+  gap: 6px;
+}
+
+.borrowed-badge {
+  background: rgba(239, 68, 68, 0.3);
+  border: 1px solid #ef4444;
+  color: #fca5a5;
+  margin-top: -10px;
+}
+
+/* ========== 底部操作按钮 ========== */
+.bottom-actions {
+  width: 100%;
+  padding: 15px 30px;
+  box-sizing: border-box;
+  background: rgba(4, 28, 61, 0.95);
+  z-index: 20;
+  flex-shrink: 0;
+}
+
+.submit-btn {
+  width: 100%;
+  padding: 18px 0;
+   background: #4a99e2;
+  border: none;
+  border-radius: 12px;
+  font-size: 24px;
+  font-weight: bold;
+  color: #fff;
+  cursor: pointer;
+  transition: all 0.3s;
+  letter-spacing: 8px;
+  text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
+}
+
+.submit-btn:hover:not(:disabled) {
+  box-shadow: 0 0 30px rgba(16, 185, 129, 0.6);
+  transform: translateY(-2px);
+}
+
+.submit-btn:disabled {
+  opacity: 0.5;
+  cursor: not-allowed;
+  background: linear-gradient(90deg, #6b7280 0%, #9ca3af 100%);
+}
+
+/* ========== 响应式 - 横屏 ========== */
+@media screen and (orientation: landscape) {
+  .header-section {
+    padding: 30px 20px 10px 20px;
+  }
+
+  .page-title {
+    font-size: 22px;
+  }
+
+  .logout-btn {
+    padding: 6px 14px;
+    font-size: 13px;
+    left: 20px;
+  }
+
+  .logout-btn i {
+    font-size: 14px;
+  }
+
+  .header-actions {
+    right: 20px;
+  }
+
+  .action-btn {
+    padding: 6px 14px;
+    font-size: 13px;
+  }
+
+  .action-btn i {
+    font-size: 14px;
+  }
+
+  .main-content {
+    padding: 20px;
+  }
+
+  .stats-section {
+    padding: 10px 15px;
+    margin-bottom: 10px;
+  }
+
+  .stats-text {
+    font-size: 14px;
+  }
+
+  /* 卡片网格响应式 */
+  .card-grid {
+    grid-template-columns: repeat(6, 1fr);
+    gap: 15px;
+  }
+
+  .card-index {
+    width: 24px;
+    height: 24px;
+    font-size: 11px;
+    top: 6px;
+    left: 6px;
+  }
+
+  .card-image {
+    margin: 10px;
+    margin-bottom: 8px;
+    width: calc(100% - 20px);
+  }
+
+  .image-placeholder {
+    font-size: 36px;
+  }
+
+  .card-info {
+    padding: 32px 10px 8px;
+  }
+
+  .info-row {
+    font-size: 11px;
+    margin-bottom: 3px;
+  }
+
+  .location-icon {
+    font-size: 10px;
+  }
+
+  .card-action-section {
+    padding: 8px 10px;
+    min-height: 40px;
+  }
+
+  .status-btn {
+    padding:  10px;
+    font-size: 11px;
+    gap: 4px;
+  }
+
+  .status-placeholder {
+    font-size: 14px;
+  }
+
+  .bottom-actions {
+    padding: 10px 20px;
+  }
+
+  .submit-btn {
+    padding: 12px 0;
+    font-size: 18px;
+    letter-spacing: 6px;
+    border-radius: 8px;
+  }
+}
+</style>

+ 20 - 19
src/stock/ApplyMaterial.vue

@@ -171,7 +171,7 @@
                     :options="locator" :clearable="false" class="location-select dark-select" :append-to-body="true"
                     :calculate-position="withPopper"
                   />
-                  <span v-else style="font-size: 16px;">人工配送</span>
+                  <span v-else style="font-size: 16px; color: #168aff;">人工配送</span>
                 </div>
               </template>
               <!-- 未选中时显示占位 -->
@@ -261,6 +261,7 @@ import bgImg from '../assets/images/bj.png';
 import { getWarehouseList, queryFeedAreaStatus } from '../api/stock.js';
 import { findInventory, createStockOutPrepareLine, queryPickingCarNumber, generatePickPaper } from '../api/stockOut.js';
 import { gateController } from '../hardware/GateOperate.js';
+import { showErrorDialog } from '../util/errorDialog.js';
 
 const router = useRouter();
 
@@ -490,11 +491,11 @@ const queryFeedArea = async () => {
                 locator.value = [];
             }
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage });
+            showErrorDialog(res.errorMessage);
         }
     } catch (error) {
         console.error('获取送料区货位API调用失败:', error);
-        showNotify({ type: 'danger', message: '获取送料区货位API调用失败' });
+        if(error.status !== 401) showErrorDialog('获取送料区货位API调用失败');
     }
 };
 
@@ -572,7 +573,7 @@ const getStockRequisitionList = async () => {
         }
     } catch (error) {
         console.error('获取物料数据失败:', error);
-        showNotify({ type: 'danger', message: '获取库存数据失败' });
+        if(error.status !== 401) showErrorDialog('获取库存数据失败');
     } finally {
         loading.value = false;
         isInitialLoading = false;
@@ -590,12 +591,12 @@ const getWarehouses = async () => {
                 warehouseList.value = [];
             }
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage });
+            showErrorDialog(res.errorMessage);
         }
 
     } catch (error) {
         console.error('获取仓库数据失败:', error);
-        showNotify({ type: 'danger', message: '获取仓库数据失败' });
+        if(error.status !== 401) showErrorDialog('获取仓库数据失败');
     }
 };
 
@@ -628,7 +629,7 @@ const submitting = ref(false);
 // 加入领料车
 const submitStock = async () => {
     if (selectedIds.value.length == 0) {
-        showNotify({ type: 'danger', message: '请至少选择一个物料' });
+        showErrorDialog('请至少选择一个物料');
         return;
     }
     submitting.value = true;
@@ -647,7 +648,7 @@ const submitStock = async () => {
         }
     } catch (error) {
         console.error('添加领料车失败:', error);
-        showNotify({ type: 'danger', message: '添加到领料车失败' });
+        if(error.status !== 401) showErrorDialog('添加到领料车失败');
     } finally {
         submitting.value = false;
     }
@@ -656,7 +657,7 @@ const submitStock = async () => {
 // 领料申请,直接验证并提交
 const handleComplete = async () => {
     if (selectedIds.value.length === 0) {
-        showNotify({ type: 'danger', message: '请至少选择一个物料' });
+        showErrorDialog('请至少选择一个物料');
         return;
     }
 
@@ -665,7 +666,7 @@ const handleComplete = async () => {
     const hasEmptyLocation = agvItems.some(item => !item.selectedLocation);
 
     if (hasEmptyLocation) {
-        showNotify({ type: 'danger', message: '请为所有 AGV 配送的物料选择配送位置' });
+        showErrorDialog('请为所有 AGV 配送的物料选择配送位置');
         return;
     }
 
@@ -686,9 +687,9 @@ const handleComplete = async () => {
         selectedRows.value = [];
         // 显示完成确认弹窗
         gateController('SHOTOPEN');
-        router.push('/');
+        router.push('/home');
     } else {
-        showNotify({ type: 'danger', message: res.errorMessage });
+        showErrorDialog(res.errorMessage);
     }
 };
 
@@ -697,7 +698,7 @@ const handleCompleteConfirm = () => {
     // 调用开门操作
     gateController('SHOTOPEN');
     completeModalVisible.value = false;
-    router.push('/');
+    router.push('/home');
     // showToast('领料申请已完成,配送任务已创建!');
 };
 
@@ -721,12 +722,12 @@ const queryPickingCarCount = async () => {
                 count.value = 0;
             }
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage });
+            showErrorDialog(res.errorMessage);
         }
 
     } catch (error) {
         console.error('查询领料车数量失败:', error);
-        showNotify({ type: 'danger', message: '查询领料车数量失败' });
+        if(error.status !== 401) showErrorDialog('查询领料车数量失败');
     }
 };
 onMounted(() => {
@@ -770,7 +771,7 @@ onMounted(() => {
   flex: 1;
   display: flex;
   flex-direction: column;
-  padding: 0 30px;
+  padding: 20px 30px;
   position: relative;
   z-index: 10;
   min-height: 0;
@@ -1339,7 +1340,7 @@ onMounted(() => {
   }
 
   .main-content {
-    padding: 0 20px;
+    padding: 20px;
     flex: 1;
     min-height: 0;
     overflow: hidden;
@@ -1592,7 +1593,7 @@ onMounted(() => {
   }
 
   .main-content {
-    padding: 0 15px;
+    padding: 20px;
     flex: 1;
     min-height: 0;
     overflow: hidden;
@@ -1683,7 +1684,7 @@ onMounted(() => {
   }
 
   .main-content {
-    padding: 0 40px;
+    padding: 20px 40px;
   }
 
   .filter-section {

+ 17 - 16
src/stock/RegularRequisition.vue

@@ -160,7 +160,7 @@
                     :options="locator" :clearable="false" class="location-select dark-select" :append-to-body="true"
                     :calculate-position="withPopper"
                   />
-                  <span v-else style="font-size: 16px;">人工配送</span>
+                  <span v-else style="font-size: 16px; color: #168aff;">人工配送</span>
                 </div>
               </template>
               <!-- 未选中时显示占位 -->
@@ -248,6 +248,7 @@ import bgImg from '../assets/images/bj.png';
 import { getWarehouseList, queryFeedAreaStatus } from '../api/stock.js';
 import { queryCommonUse, createStockOutPrepareLine, queryPickingCarNumber, generatePickPaper } from '../api/stockOut.js';
 import { gateController } from '../hardware/GateOperate.js';
+import { showErrorDialog } from '../util/errorDialog.js';
 
 const router = useRouter();
 
@@ -551,7 +552,7 @@ const getStockRequisitionList = async () => {
             }
         }
     } catch (error) {
-        showNotify({ type: 'danger', message: '查询常用物料API失败' });
+        if(error.status !== 401) showErrorDialog('查询常用物料API失败');
         console.error('查询常用物料API失败', error);
     } finally {
         loading.value = false;
@@ -570,11 +571,11 @@ const getWarehouses = async () => {
                 warehouseList.value = [];
             }
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage });
+            showErrorDialog(res.errorMessage);
         }
     } catch (error) {
         console.error('获取仓库数据失败:', error);
-        showNotify({ type: 'danger', message: '获取库存数据失败' });
+        if(error.status !== 401) showErrorDialog('获取库存数据失败');
     }
 };
 
@@ -608,7 +609,7 @@ const submitting = ref(false);
 // 加入领料车
 const submitStock = async () => {
     if (selectedIds.value.length == 0) {
-        showNotify({ type: 'danger', message: '请至少选择一个物料' });
+        showErrorDialog('请至少选择一个物料');
         return;
     }
     submitting.value = true;
@@ -628,7 +629,7 @@ const submitStock = async () => {
         }
     } catch (error) {
         console.error('添加领料车失败:', error);
-        showNotify({ type: 'danger', message: '添加到领料车失败' });
+        if(error.status !== 401) showErrorDialog('添加到领料车失败');
     } finally {
         submitting.value = false;
     }
@@ -637,7 +638,7 @@ const submitStock = async () => {
 // 领料申请,直接验证并提交
 const handleComplete = async () => {
     if (selectedIds.value.length === 0) {
-        showNotify({ type: 'danger', message: '请至少选择一个物料' });
+        showErrorDialog('请至少选择一个物料');
         return;
     }
 
@@ -646,7 +647,7 @@ const handleComplete = async () => {
     const hasEmptyLocation = agvItems.some(item => !item.selectedLocation);
 
     if (hasEmptyLocation) {
-        showNotify({ type: 'danger', message: '请为所有 AGV 配送的物料选择配送位置' });
+        showErrorDialog('请为所有 AGV 配送的物料选择配送位置');
         return;
     }
 
@@ -667,9 +668,9 @@ const handleComplete = async () => {
         selectedRows.value = [];
         // 显示完成确认弹窗
         gateController('SHOTOPEN');
-        router.push('/');
+        router.push('/home');
     } else {
-        showNotify({ type: 'danger', message: res.errorMessage });
+        showErrorDialog(res.errorMessage);
     }
 };
 
@@ -703,11 +704,11 @@ const queryPickingCarCount = async () => {
                 count.value = 0;
             }
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage });
+            showErrorDialog(res.errorMessage);
         }
     } catch (error) {
         console.error('查询领料车数量失败:', error);
-        showNotify({ type: 'danger', message: '查询领料车数量失败' });
+        if(error.status !== 401) showErrorDialog('查询领料车数量失败');
     }
 };
 
@@ -728,11 +729,11 @@ const getFeedAreaLocator = async () => {
                 locator.value = [];
             }
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage });
+            showErrorDialog(res.errorMessage);
         }
     } catch (error) {
         console.error('获取送料区货位API调用失败:', error);
-        showNotify({ type: 'danger', message: '获取送料区货位API调用失败' });
+        if(error.status !== 401) showErrorDialog('获取送料区货位API调用失败');
     }
 };
 
@@ -778,7 +779,7 @@ onMounted(() => {
   flex: 1;
   display: flex;
   flex-direction: column;
-  padding: 0 30px;
+  padding: 20px 30px;
   position: relative;
   z-index: 10;
   min-height: 0;
@@ -1485,7 +1486,7 @@ onMounted(() => {
   }
 
   .main-content {
-    padding: 0 20px;
+    padding: 20px;
     flex: 1;
     min-height: 0;
     overflow: hidden;

+ 21 - 20
src/stock/StockPickingCar.vue

@@ -144,7 +144,7 @@
                     :options="locator" :clearable="false" class="location-select dark-select" :append-to-body="true"
                     :calculate-position="withPopper"
                   />
-                  <span v-else style="font-size: 16px;">人工配送</span>
+                  <span v-else style="font-size: 16px; color: #168aff;">人工配送</span>
                 </div>
               </template>
               <!-- 未选中时显示占位 -->
@@ -282,6 +282,7 @@ import bgImg from '../assets/images/bj.png';
 import { getWarehouseList,queryFeedAreaStatus } from '../api/stock.js';
 import { queryCFPickCar, deleteCFPickCar, saveCFStockOutPrepare, generatePickPaper } from '../api/stockOut.js';
 import { gateController } from '../hardware/GateOperate.js';
+import { showErrorDialog } from '../util/errorDialog.js';
 
 const router = useRouter();
 
@@ -509,11 +510,11 @@ const queryFeedArea = async () => {
                 locator.value = [];
             }
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage });
+            showErrorDialog(res.errorMessage);
         }
     } catch (error) {
         console.error('获取送料区货位API调用失败:', error);
-        showNotify({ type: 'danger', message: '获取送料区货位API调用失败' });
+        if(error.status !== 401) showErrorDialog('获取送料区货位API调用失败');
     }
 };
 
@@ -595,11 +596,11 @@ const getPickerCarList = async () => {
                 noMoreData.value = true;
             }
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage });
+            showErrorDialog(res.errorMessage);
         }
     } catch (error) {
         console.log('获取领料车列表API调用失败', error);
-        showNotify({ type: 'danger', message: '获取领料车列表API调用失败' });
+        if(error.status !== 401) showErrorDialog('获取领料车列表API调用失败');
     } finally {
         loading.value = false;
         isInitialLoading = false;
@@ -609,7 +610,7 @@ const getPickerCarList = async () => {
 // 领料申请,直接验证并提交
 const handleComplete = async () => {
     if (selectedIds.value.length === 0) {
-        showNotify({ type: 'danger', message: '请至少选择一个物料' });
+        showErrorDialog('请至少选择一个物料');
         return;
     }
 
@@ -618,7 +619,7 @@ const handleComplete = async () => {
     const hasEmptyLocation = agvItems.some(item => !item.selectedLocation);
 
     if (hasEmptyLocation) {
-        showNotify({ type: 'danger', message: '请为所有 AGV 配送的物料选择配送位置' });
+        showErrorDialog('请为所有 AGV 配送的物料选择配送位置');
         return;
     }
 
@@ -639,9 +640,9 @@ const handleComplete = async () => {
         selectedRows.value = [];
         // 显示完成确认弹窗
         gateController('SHOTOPEN');
-        router.push('/');
+        router.push('/home');
     } else {
-        showNotify({ type: 'danger', message: res.errorMessage });
+        showErrorDialog(res.errorMessage);
     }
 };
 
@@ -650,7 +651,7 @@ const handleCompleteConfirm = () => {
     // 调用开门操作
     gateController('SHOTOPEN');
     completeModalVisible.value = false;
-    router.push('/');
+    router.push('/home');
     // showToast('领料申请已完成,配送任务已创建!');
 };
 
@@ -682,7 +683,7 @@ const handleReset = () => {
 // 从领料车里删除工装设备
 const deleteStock = () => {
     if (selectedIds.value.length == 0) {
-        showNotify({ type: 'danger', message: '请至少选择一个工装设备' });
+        showErrorDialog('请至少选择一个工装设备');
         return;
     }
     // 显示删除确认弹窗
@@ -705,11 +706,11 @@ const deleteStockCarApi = async () => {
             selectedIds.value = [];
             await getDatas();
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage });
+            showErrorDialog(res.errorMessage);
         }
     } catch (error) {
         console.log('删除领料车API调用失败', error);
-        showNotify({ type: 'danger', message: '删除领料车API调用失败' });
+        if(error.status !== 401) showErrorDialog('删除领料车API调用失败');
     } finally {
         submitting.value = false;
     }
@@ -725,11 +726,11 @@ const getWarehouses = async () => {
                 warehouseList.value = [];
             }
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage });
+            showErrorDialog(res.errorMessage);
         }
     } catch (error) {
         console.error('获取仓库数据失败:', error);
-        showNotify({ type: 'danger', message: '获取仓库数据失败' });
+        if(error.status !== 401) showErrorDialog('获取仓库数据失败');
     }
 };
 
@@ -766,7 +767,7 @@ const getDatas = async () => {
 // 领料
 const submitStock = async () => {
     if (selectedIds.value.length == 0) {
-        showNotify({ type: 'danger', message: '请至少选择一个工装设备' });
+        showErrorDialog('请至少选择一个工装设备');
         return;
     }
     submitting.value = true;
@@ -783,11 +784,11 @@ const submitStock = async () => {
             await getDatas();
             confirmModalVisible.value = true;
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage });
+            showErrorDialog(res.errorMessage);
         }
     } catch (error) {
         console.log('生成领料单API调用失败', error);
-        showNotify({ type: 'danger', message: '生成领料单API调用失败' });
+        if(error.status !== 401) showErrorDialog('生成领料单API调用失败');
     } finally {
         submitting.value = false;
     }
@@ -833,7 +834,7 @@ onMounted(() => {
   flex: 1;
   display: flex;
   flex-direction: column;
-  padding: 0 30px;
+  padding: 20px 30px;
   position: relative;
   z-index: 10;
   min-height: 0;
@@ -1436,7 +1437,7 @@ onMounted(() => {
   }
 
   .main-content {
-    padding: 0 20px;
+    padding: 20px;
     flex: 1;
     min-height: 0;
     overflow: hidden;

+ 12 - 11
src/stock/StockRequisition.vue

@@ -202,6 +202,7 @@ import bgImg from '../assets/images/bj.png';
 
 import { getWarehouseList } from '../api/stock.js';
 import { findInventory, createStockOutPrepareLine, queryPickingCarNumber } from '../api/stockOut.js';
+import { showErrorDialog } from '../util/errorDialog.js';
 
 const router = useRouter();
 
@@ -399,7 +400,7 @@ const getStockRequisitionList = async () => {
         }
     } catch (error) {
         console.error('获取物料数据失败:', error);
-        showNotify({ type: 'danger', message: '获取库存数据失败' });
+        if(error.status !== 401) showErrorDialog('获取库存数据失败');
     } finally {
         loading.value = false;
         isInitialLoading = false;
@@ -417,12 +418,12 @@ const getWarehouses = async () => {
                 warehouseList.value = [];
             }
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage });
+            showErrorDialog(res.errorMessage);
         }
 
     } catch (error) {
         console.error('获取仓库数据失败:', error);
-        showNotify({ type: 'danger', message: '获取仓库数据失败' });
+        if(error.status !== 401) showErrorDialog('获取仓库数据失败');
     }
 };
 
@@ -455,7 +456,7 @@ const submitting = ref(false);
 // 加入领料车
 const submitStock = async () => {
     if (selectedIds.value.length == 0) {
-        showNotify({ type: 'danger', message: '请至少选择一个物料' });
+        showErrorDialog('请至少选择一个物料');
         return;
     }
     submitting.value = true;
@@ -474,7 +475,7 @@ const submitStock = async () => {
         }
     } catch (error) {
         console.error('添加领料车失败:', error);
-        showNotify({ type: 'danger', message: '添加到领料车失败' });
+        if(error.status !== 401) showErrorDialog('添加到领料车失败');
     } finally {
         submitting.value = false;
     }
@@ -493,12 +494,12 @@ const queryPickingCarCount = async () => {
                 count.value = 0;
             }
         } else {
-            showNotify({ type: 'danger', message: res.errorMessage });
+            showErrorDialog(res.errorMessage);
         }
 
     } catch (error) {
         console.error('查询领料车数量失败:', error);
-        showNotify({ type: 'danger', message: '查询领料车数量失败' });
+        if(error.status !== 401) showErrorDialog('查询领料车数量失败');
     }
 };
 onMounted(() => {
@@ -541,7 +542,7 @@ onMounted(() => {
   flex: 1;
   display: flex;
   flex-direction: column;
-  padding: 0 30px;
+  padding: 20px 30px;
   position: relative;
   z-index: 10;
   min-height: 0;
@@ -961,7 +962,7 @@ onMounted(() => {
   }
 
   .main-content {
-    padding: 0 20px;
+    padding: 20px;
     flex: 1;
     min-height: 0;
     overflow: hidden;
@@ -1213,7 +1214,7 @@ onMounted(() => {
   }
 
   .main-content {
-    padding: 0 15px;
+    padding: 15px;
     flex: 1;
     min-height: 0;
     overflow: hidden;
@@ -1304,7 +1305,7 @@ onMounted(() => {
   }
 
   .main-content {
-    padding: 0 40px;
+    padding: 20px 40px;
   }
 
   .filter-section {

+ 322 - 0
src/util/errorDialog.js

@@ -0,0 +1,322 @@
+import { createApp, h } from 'vue';
+
+let dialogInstance = null;
+
+/**
+ * 显示错误提示弹窗
+ * @param {string} message - 错误信息
+ */
+export const showErrorDialog = message => {
+    // 如果已有弹窗实例,先移除
+    if (dialogInstance) {
+        dialogInstance.unmount();
+        const existingEl = document.getElementById('custom-error-dialog');
+        if (existingEl) {
+            existingEl.remove();
+        }
+    }
+
+    // 创建容器
+    const container = document.createElement('div');
+    container.id = 'custom-error-dialog';
+    document.body.appendChild(container);
+
+    // 创建 Vue 组件
+    const DialogComponent = {
+        data() {
+            return {
+                visible: true,
+                message: message || '操作失败',
+            };
+        },
+        methods: {
+            handleConfirm() {
+                this.visible = false;
+                setTimeout(() => {
+                    this.close();
+                }, 300);
+            },
+            close() {
+                if (dialogInstance) {
+                    dialogInstance.unmount();
+                    const el = document.getElementById('custom-error-dialog');
+                    if (el) {
+                        el.remove();
+                    }
+                    dialogInstance = null;
+                }
+            },
+        },
+        render() {
+            if (!this.visible) return null;
+
+            return h('div', {
+                class: 'light-modal-overlay',
+                onClick: e => {
+                    // 点击遮罩不关闭
+                    e.stopPropagation();
+                },
+            }, [
+                h('div', {
+                    class: 'light-modal',
+                    onClick: e => {
+                        e.stopPropagation();
+                    },
+                }, [
+                    // 标题区域
+                    h('div', { class: 'light-modal-header' }, [
+                        h('div', { class: 'error-icon' }, [
+                            h('svg', {
+                                viewBox: '0 0 24 24',
+                                fill: 'none',
+                                stroke: 'currentColor',
+                                'stroke-width': '2',
+                            }, [
+                                h('circle', { cx: '12', cy: '12', r: '10' }),
+                                h('line', { x1: '12', y1: '8', x2: '12', y2: '12' }),
+                                h('line', { x1: '12', y1: '16', x2: '12.01', y2: '16' }),
+                            ]),
+                        ]),
+                        h('h2', { class: 'light-modal-title' }, '错误提示'),
+                    ]),
+                    // 内容区域
+                    h('div', { class: 'light-modal-content' }, [
+                        h('p', { class: 'light-modal-message' }, this.message),
+                    ]),
+                    // 底部按钮
+                    h('div', { class: 'light-modal-footer' }, [
+                        h('button', {
+                            class: 'light-modal-btn confirm-btn',
+                            onClick: this.handleConfirm,
+                        }, '确认'),
+                    ]),
+                ]),
+            ]);
+        },
+    };
+
+    // 创建并挂载实例
+    dialogInstance = createApp(DialogComponent);
+    dialogInstance.mount(container);
+
+    // 添加样式
+    if (!document.getElementById('custom-error-dialog-style')) {
+        const style = document.createElement('style');
+        style.id = 'custom-error-dialog-style';
+        style.textContent = `
+            .light-modal-overlay {
+                position: fixed;
+                top: 0;
+                left: 0;
+                width: 100%;
+                height: 100%;
+                background: rgba(0, 0, 0, 0.6);
+                display: flex;
+                align-items: center;
+                justify-content: center;
+                z-index: 2000;
+                animation: fadeIn 0.3s ease;
+            }
+
+            @keyframes fadeIn {
+                from {
+                    opacity: 0;
+                }
+                to {
+                    opacity: 1;
+                }
+            }
+
+            .light-modal {
+                background: #ffffff;
+                border-radius: 20px;
+                width: 90vw;
+                max-width: 650px;
+                box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
+                border: 3px solid #ef4444;
+                animation: slideUp 0.3s ease;
+            }
+
+            @keyframes slideUp {
+                from {
+                    transform: translateY(30px);
+                    opacity: 0;
+                }
+                to {
+                    transform: translateY(0);
+                    opacity: 1;
+                }
+            }
+
+            .light-modal-header {
+                padding: 2rem 2.5rem 1.5rem;
+                display: flex;
+                align-items: center;
+                gap: 1.5rem;
+                border-bottom: 2px solid #fee2e2;
+                background: linear-gradient(135deg, #fef2f2 0%, #ffffff 100%);
+                border-radius: 20px 20px 0 0;
+            }
+
+            .error-icon {
+                width: 60px;
+                height: 60px;
+                background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
+                border-radius: 50%;
+                display: flex;
+                align-items: center;
+                justify-content: center;
+                color: white;
+                flex-shrink: 0;
+                box-shadow: 0 4px 15px rgba(239, 68, 68, 0.4);
+            }
+
+            .error-icon svg {
+                width: 36px;
+                height: 36px;
+            }
+
+            .light-modal-title {
+                margin: 0;
+                font-size: 2rem;
+                font-weight: 700;
+                color: #dc2626;
+                letter-spacing: 0.5px;
+            }
+
+            .light-modal-content {
+                padding: 3rem 2.5rem;
+                min-height: 150px;
+                display: flex;
+                align-items: center;
+                justify-content: center;
+            }
+
+            .light-modal-message {
+                margin: 0;
+                font-size: 1.5rem;
+                line-height: 1.8;
+                color: #1f2937;
+                text-align: center;
+                font-weight: 600;
+            }
+
+            .light-modal-footer {
+                padding: 0 2.5rem 2.5rem;
+                display: flex;
+                justify-content: center;
+            }
+
+            .light-modal-btn {
+                flex: 1;
+                max-width: 300px;
+                height: 64px;
+                font-size: 1.375rem;
+                font-weight: 700;
+                border-radius: 12px;
+                border: none;
+                cursor: pointer;
+                transition: all 0.3s;
+                letter-spacing: 2px;
+            }
+
+            .light-modal-btn.confirm-btn {
+                background: linear-gradient(90deg, #ef4444 0%, #dc2626 100%);
+                color: white;
+                box-shadow: 0 4px 15px rgba(239, 68, 68, 0.3);
+            }
+
+            .light-modal-btn.confirm-btn:hover {
+                background: linear-gradient(90deg, #dc2626 0%, #b91c1c 100%);
+                box-shadow: 0 6px 20px rgba(239, 68, 68, 0.5);
+                transform: translateY(-2px);
+            }
+
+            .light-modal-btn.confirm-btn:active {
+                transform: translateY(0) scale(0.98);
+            }
+
+            /* 响应式 - 横屏 */
+            @media screen and (orientation: landscape) {
+                .light-modal {
+                    max-width: 600px;
+                }
+
+                .light-modal-header {
+                    padding: 1.5rem 2rem 1.25rem;
+                }
+
+                .error-icon {
+                    width: 50px;
+                    height: 50px;
+                }
+
+                .error-icon svg {
+                    width: 30px;
+                    height: 30px;
+                }
+
+                .light-modal-title {
+                    font-size: 1.75rem;
+                }
+
+                .light-modal-content {
+                    padding: 2.5rem 2rem;
+                    min-height: 130px;
+                }
+
+                .light-modal-message {
+                    font-size: 1.375rem;
+                }
+
+                .light-modal-btn {
+                    height: 56px;
+                    font-size: 1.25rem;
+                }
+            }
+
+            /* 响应式 - 竖屏 */
+            @media screen and (orientation: portrait) {
+                .light-modal {
+                    max-width: 650px;
+                }
+
+                .light-modal-header {
+                    padding: 2rem 2.5rem 1.5rem;
+                }
+
+                .error-icon {
+                    width: 60px;
+                    height: 60px;
+                }
+
+                .error-icon svg {
+                    width: 36px;
+                    height: 36px;
+                }
+
+                .light-modal-title {
+                    font-size: 2rem;
+                }
+
+                .light-modal-content {
+                    padding: 3rem 2.5rem;
+                    min-height: 150px;
+                }
+
+                .light-modal-message {
+                    font-size: 1.5rem;
+                }
+
+                .light-modal-btn {
+                    height: 64px;
+                    font-size: 1.375rem;
+                }
+            }
+        `;
+        document.head.appendChild(style);
+    }
+};
+
+export default showErrorDialog;
+

+ 14 - 17
src/util/request.js

@@ -25,11 +25,11 @@ const errorHandler = error => {
         }
         if (error.response.status === 401 && !(data.result && data.result.isLogin)) {
             console.log('401');
-            showNotify({
-                type: 'danger',
-                message: 'Unauthorized: Authorization verification failed',
-                duration: 3000,
-            });
+            // showNotify({
+            //     type: 'danger',
+            //     message: 'Unauthorized: Authorization verification failed',
+            //     duration: 3000,
+            // });
             if (token) {
                 // store.dispatch('Logout').then(() => {
                 //   setTimeout(() => {
@@ -59,22 +59,19 @@ const responseErrorHandler = error => {
     console.log(error);
     if (error.response.status === 401) {
         const currentUrl = window.location.href;
-        if (currentUrl.indexOf('login') < 0 && currentUrl.indexOf('redirectUrl=') < 0) {
-
-            // window.location = Common.getRedirectUrl('#/login?redirectUrl=' + encodeURIComponent(currentUrl));
+        // 检查当前是否已经在登录页面,避免重复跳转
+        if (currentUrl.indexOf('fingerprint-login') < 0 && currentUrl.indexOf('login') < 0 && currentUrl.indexOf('redirectUrl=') < 0) {
+            // 清除本地存储的认证信息
+            localStorage.removeItem('#token');
+            localStorage.removeItem('#LoginInfo');
+            localStorage.removeItem('#accountId');
 
-            const isOut = localStorage.getItem('isOut');
             // 根据环境判断使用不同的 URL
             const isProduction = process.env.APP_ENV === 'production';
-            const loginPath = isProduction ? 'board.html#/login' : '#/login';
-            
-            // if (isOut == 'true') {
-            //     window.location = Common.getRedirectUrl(loginPath + '?isOut=true&redirectUrl=' + encodeURIComponent(currentUrl));
-            // } else {
-            //     window.location = Common.getRedirectUrl(loginPath + '?isOut=false&redirectUrl=' + encodeURIComponent(currentUrl));
-            // }
+            const loginPath = isProduction ? 'board.html#/fingerprint-login' : '#/fingerprint-login';
 
-            window.location = Common.getRedirectUrl(loginPath + '?redirectUrl=' + encodeURIComponent(currentUrl));
+            // 跳转到指纹登录页
+            window.location = Common.getRedirectUrl(loginPath);
         }
     }
     if (error.response.status === 504) {

+ 90 - 0
src/util/theme.js

@@ -0,0 +1,90 @@
+/**
+ * 主题管理器
+ * 支持深色主题和明亮主题的切换
+ */
+
+// 主题类型常量
+export const THEME_DARK = 'dark';
+export const THEME_LIGHT = 'light';
+
+// 默认主题
+const DEFAULT_THEME = THEME_LIGHT;
+
+// 主题存储键
+const THEME_STORAGE_KEY = '#theme';
+
+/**
+ * 获取当前主题
+ * @returns {string} 当前主题类型
+ */
+export function getCurrentTheme() {
+    const savedTheme = localStorage.getItem(THEME_STORAGE_KEY);
+    return savedTheme || DEFAULT_THEME;
+}
+
+/**
+ * 设置主题
+ * @param {string} theme - 主题类型 (dark/light)
+ */
+export function setTheme(theme) {
+    if (theme !== THEME_DARK && theme !== THEME_LIGHT) {
+        console.error('Invalid theme:', theme);
+        return;
+    }
+
+    // 保存到 localStorage
+    localStorage.setItem(THEME_STORAGE_KEY, theme);
+
+    // 设置 HTML 根元素的 data-theme 属性
+    document.documentElement.setAttribute('data-theme', theme);
+
+    // 触发自定义事件,通知其他组件主题已更改
+    window.dispatchEvent(new CustomEvent('theme-changed', { detail: { theme } }));
+}
+
+/**
+ * 切换主题
+ * @returns {string} 切换后的主题类型
+ */
+export function toggleTheme() {
+    const currentTheme = getCurrentTheme();
+    const newTheme = currentTheme === THEME_DARK ? THEME_LIGHT : THEME_DARK;
+    setTheme(newTheme);
+    return newTheme;
+}
+
+/**
+ * 初始化主题
+ * 在应用启动时调用,应用保存的主题设置
+ */
+export function initTheme() {
+    const theme = getCurrentTheme();
+    document.documentElement.setAttribute('data-theme', theme);
+}
+
+/**
+ * 监听主题变化
+ * @param {Function} callback - 主题变化时的回调函数
+ * @returns {Function} 取消监听的函数
+ */
+export function onThemeChange(callback) {
+    const handler = event => {
+        callback(event.detail.theme);
+    };
+    window.addEventListener('theme-changed', handler);
+    
+    // 返回取消监听的函数
+    return () => {
+        window.removeEventListener('theme-changed', handler);
+    };
+}
+
+/**
+ * 获取主题显示名称
+ * @param {string} theme - 主题类型
+ * @returns {string} 主题显示名称
+ */
+export function getThemeDisplayName(theme) {
+    return theme === THEME_DARK ? '深色主题' : '明亮主题';
+}
+

+ 3 - 3
webpack.dev.js

@@ -43,17 +43,17 @@ module.exports = WebpackMerge.merge(baseConfig, {
         // },
         proxy: {
             '/api': {
-                target: 'http://192.168.50.11:10026/',
+                target: 'http://jb55c494.natappfree.cc/',
                 ws: false,
                 changeOrigin: true,
             },
             '/authApi': {
-                target: 'http://192.168.50.11:10026/',
+                target: 'http://jb55c494.natappfree.cc/',
                 ws: false,
                 changeOrigin: true,
             },
             '/android-device-sdk': {
-                target: 'http://192.168.50.11:10026/',
+                target: 'http://jb55c494.natappfree.cc/',
                 ws: false,
                 changeOrigin: true,
             },

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio