Quellcode durchsuchen

feat: 补货管理设备列表页添加搜索框,支持按设备ID/名称过滤

Co-Authored-By: Claude <noreply@anthropic.com>
skyline vor 1 Tag
Ursprung
Commit
97888ee0b7
1 geänderte Dateien mit 34 neuen und 2 gelöschten Zeilen
  1. 34 2
      haha-admin-mp/src/pages/replenish/home.vue

+ 34 - 2
haha-admin-mp/src/pages/replenish/home.vue

@@ -9,6 +9,13 @@
     </view>
     <view class="header-placeholder" :style="{ height: (statusBarHeight + 44) + 'px' }"></view>
 
+    <!-- 搜索 -->
+    <view class="search-bar">
+      <view class="search-icon"></view>
+      <input class="search-input" v-model="searchKeyword" placeholder="搜索设备ID或名称" confirm-type="search" />
+      <view class="search-clear" v-if="searchKeyword" @click="searchKeyword = ''"><text>✕</text></view>
+    </view>
+
     <!-- 加载 -->
     <view class="load-tip" v-if="loading">
       <view class="dot-row"><view class="pulse-dot"></view><view class="pulse-dot"></view><view class="pulse-dot"></view></view>
@@ -22,7 +29,11 @@
         <text class="empty-hint">请联系管理员绑定设备后开始补货</text>
       </view>
 
-      <view class="device-card" v-for="(device, index) in deviceList" :key="device.deviceId || index" @click="goToOperation(device)">
+      <view class="empty-state" v-else-if="filteredDeviceList.length === 0">
+        <text class="empty-text">未找到匹配设备</text>
+      </view>
+
+      <view class="device-card" v-for="(device, index) in filteredDeviceList" :key="device.deviceId || index" @click="goToOperation(device)">
         <view class="card-left">
           <view class="card-icon"></view>
         </view>
@@ -61,7 +72,7 @@
 </template>
 
 <script setup lang="ts">
-import { ref, onMounted } from 'vue';
+import { ref, computed, onMounted } from 'vue';
 import { onShow } from '@dcloudio/uni-app';
 import { getDeviceList } from '@/api/replenish';
 import { clearAuth } from '@/utils/auth';
@@ -69,6 +80,17 @@ import { clearAuth } from '@/utils/auth';
 const statusBarHeight = ref(0);
 const deviceList = ref<any[]>([]);
 const loading = ref(true);
+const searchKeyword = ref('');
+
+const filteredDeviceList = computed(() => {
+  const kw = searchKeyword.value.trim().toLowerCase();
+  if (!kw) return deviceList.value;
+  return deviceList.value.filter(d => {
+    const id = (d.deviceId || '').toLowerCase();
+    const name = (d.name || '').toLowerCase();
+    return id.includes(kw) || name.includes(kw);
+  });
+});
 
 const loadData = async () => {
   loading.value = true;
@@ -119,6 +141,16 @@ onShow(async () => { await loadData(); });
 .header-logout { position: absolute; left: 24rpx; width: 40rpx; height: 40rpx; &:active { opacity: 0.7; } }
 .header-placeholder { width: 100%; }
 
+// ====== Search ======
+.search-bar { display: flex; align-items: center; margin: 16rpx 24rpx 8rpx; padding: 0 16rpx; height: 60rpx; background: $bg-color-card; border: 1rpx solid $border-color; border-radius: $radius-base; }
+.search-icon { width: 28rpx; height: 28rpx; border: 2.5rpx solid $text-color-muted; border-radius: 50%; position: relative; flex-shrink: 0; margin-right: 10rpx;
+  &::after { content: ''; position: absolute; bottom: -2rpx; right: -4rpx; width: 2.5rpx; height: 10rpx; background: $text-color-muted; border-radius: 1rpx; transform: rotate(-45deg); }
+}
+.search-input { flex: 1; font-size: $font-size-sm; color: $text-color-primary; height: 100%; }
+.search-clear { width: 36rpx; height: 36rpx; display: flex; align-items: center; justify-content: center; border-radius: 50%; background: $bg-color-secondary; flex-shrink: 0; margin-left: 8rpx;
+  text { font-size: 20rpx; color: $text-color-muted; line-height: 1; }
+}
+
 // ====== Loading ======
 .load-tip { display: flex; justify-content: center; padding: 200rpx 0; }
 .dot-row { display: flex; gap: $spacing-1; }