Ver código fonte

运营端小程序

skyline 3 meses atrás
pai
commit
bad962da82

+ 234 - 0
haha-admin-mp/src/components/CustomTabBar.vue

@@ -0,0 +1,234 @@
+<template>
+  <view class="custom-tabbar">
+    <!-- 左侧两个菜单 -->
+    <view class="tab-item" :class="{ active: currentIndex === 0 }" @click="switchTab(0)">
+      <view class="tab-icon">
+        <image :src="currentIndex === 0 ? '/static/tabbar/work-active.png' : '/static/tabbar/work.png'" mode="aspectFit" />
+      </view>
+      <text class="tab-text">工作台</text>
+    </view>
+    
+    <view class="tab-item" :class="{ active: currentIndex === 1 }" @click="switchTab(1)">
+      <view class="tab-icon">
+        <image :src="currentIndex === 1 ? '/static/tabbar/order-active.png' : '/static/tabbar/order.png'" mode="aspectFit" />
+      </view>
+      <text class="tab-text">订单</text>
+    </view>
+    
+    <!-- 中间扫码按钮 -->
+    <view class="scan-btn-wrapper">
+      <view class="scan-btn" @click="handleScan">
+        <view class="scan-icon">
+          <view class="scan-line"></view>
+          <view class="scan-line vertical"></view>
+        </view>
+        <text class="scan-text">扫码上货</text>
+      </view>
+    </view>
+    
+    <!-- 右侧两个菜单 -->
+    <view class="tab-item" :class="{ active: currentIndex === 2 }" @click="switchTab(2)">
+      <view class="tab-icon">
+        <image :src="currentIndex === 2 ? '/static/tabbar/device-active.png' : '/static/tabbar/device.png'" mode="aspectFit" />
+      </view>
+      <text class="tab-text">设备</text>
+    </view>
+    
+    <view class="tab-item" :class="{ active: currentIndex === 3 }" @click="switchTab(3)">
+      <view class="tab-icon">
+        <image :src="currentIndex === 3 ? '/static/tabbar/my-active.png' : '/static/tabbar/my.png'" mode="aspectFit" />
+      </view>
+      <text class="tab-text">我的</text>
+    </view>
+  </view>
+</template>
+
+<script setup lang="ts">
+import { ref, onMounted } from 'vue';
+
+const tabPages = [
+  '/pages/index/index',
+  '/pages/orders/list',
+  '/pages/device/list',
+  '/pages/my/my'
+];
+
+const currentIndex = ref(0);
+
+onMounted(() => {
+  // 获取当前页面路径
+  const pages = getCurrentPages();
+  const currentPage = pages[pages.length - 1];
+  const currentPath = '/' + currentPage.route;
+  
+  const index = tabPages.indexOf(currentPath);
+  if (index !== -1) {
+    currentIndex.value = index;
+  }
+});
+
+const switchTab = (index: number) => {
+  if (currentIndex.value === index) return;
+  
+  currentIndex.value = index;
+  uni.switchTab({
+    url: tabPages[index]
+  });
+};
+
+const handleScan = () => {
+  uni.scanCode({
+    scanType: ['qrCode', 'barCode'],
+    success: (res) => {
+      console.log('扫码结果:', res.result);
+      // 解析设备ID
+      let deviceId = '';
+      
+      // 尝试从URL中解析设备ID
+      const urlPattern = /\/([A-Z0-9]+)(\?|$)/;
+      const match = res.result.match(urlPattern);
+      if (match && match[1]) {
+        deviceId = match[1];
+      } else {
+        // 尝试解析JSON
+        try {
+          const qrData = JSON.parse(res.result);
+          deviceId = qrData.deviceId || res.result;
+        } catch {
+          deviceId = res.result;
+        }
+      }
+      
+      if (deviceId) {
+        // 跳转到设备详情页或上货页面
+        uni.navigateTo({
+          url: `/pages/device/detail?id=${deviceId}&mode=stock`
+        });
+      } else {
+        uni.showToast({
+          title: '无法识别设备',
+          icon: 'none'
+        });
+      }
+    },
+    fail: () => {
+      uni.showToast({
+        title: '扫码取消',
+        icon: 'none'
+      });
+    }
+  });
+};
+</script>
+
+<style lang="scss" scoped>
+.custom-tabbar {
+  position: fixed;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  height: 100rpx;
+  background: #ffffff;
+  border-top: 1rpx solid #e2e8f0;
+  display: flex;
+  align-items: center;
+  justify-content: space-around;
+  padding-bottom: constant(safe-area-inset-bottom);
+  padding-bottom: env(safe-area-inset-bottom);
+  z-index: 999;
+}
+
+.tab-item {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  flex: 1;
+  height: 100%;
+  
+  .tab-icon {
+    width: 44rpx;
+    height: 44rpx;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    
+    image {
+      width: 44rpx;
+      height: 44rpx;
+    }
+  }
+  
+  .tab-text {
+    font-size: 20rpx;
+    color: #94a3b8;
+    margin-top: 4rpx;
+  }
+  
+  &.active {
+    .tab-text {
+      color: #10b981;
+      font-weight: 500;
+    }
+  }
+}
+
+/* 扫码按钮 */
+.scan-btn-wrapper {
+  position: relative;
+  width: 100rpx;
+  height: 100%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.scan-btn {
+  position: absolute;
+  bottom: 16rpx;
+  width: 100rpx;
+  height: 100rpx;
+  background: #10b981;
+  border-radius: 50%;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  box-shadow: 0 4rpx 16rpx rgba(16, 185, 129, 0.4);
+  
+  &:active {
+    transform: scale(0.95);
+    background: #059669;
+  }
+}
+
+.scan-icon {
+  width: 36rpx;
+  height: 36rpx;
+  position: relative;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  
+  .scan-line {
+    position: absolute;
+    width: 24rpx;
+    height: 4rpx;
+    background: #ffffff;
+    border-radius: 2rpx;
+    
+    &.vertical {
+      width: 4rpx;
+      height: 24rpx;
+    }
+  }
+}
+
+.scan-text {
+  font-size: 18rpx;
+  color: #ffffff;
+  font-weight: 500;
+  margin-top: 4rpx;
+  white-space: nowrap;
+}
+</style>

+ 5 - 0
haha-admin-mp/src/pages/device/list.vue

@@ -97,12 +97,16 @@
         <text class="empty-text">暂无设备数据</text>
       </view>
     </scroll-view>
+    
+    <!-- 自定义TabBar -->
+    <CustomTabBar />
   </view>
 </template>
 
 <script setup lang="ts">
 import { ref, onMounted } from 'vue';
 import NavBar from '@/components/NavBar.vue';
+import CustomTabBar from '@/components/CustomTabBar.vue';
 import { getDeviceList, getDeviceStats } from '@/api/device';
 import { DeviceStatusText, DeviceStatusColor } from '@/mock/device';
 import { formatMoney as formatMoneyUtil, formatTime as formatTimeUtil } from '@/utils/common';
@@ -184,6 +188,7 @@ onMounted(() => {
   background: #f8fafc;
   display: flex;
   flex-direction: column;
+  padding-bottom: 200rpx;
 }
 
 /* 统计区域 */

+ 13 - 2
haha-admin-mp/src/pages/index/index.vue

@@ -137,6 +137,9 @@
         </view>
       </view>
     </view>
+    
+    <!-- 自定义TabBar -->
+    <CustomTabBar />
   </view>
 </template>
 
@@ -144,6 +147,7 @@
 import { ref, onMounted } from 'vue';
 import { getDashboardData } from '@/api/dashboard';
 import { formatMoney as formatMoneyUtil } from '@/utils/common';
+import CustomTabBar from '@/components/CustomTabBar.vue';
 
 // 获取系统信息用于计算状态栏高度
 const systemInfo = uni.getSystemInfoSync();
@@ -201,7 +205,7 @@ onMounted(() => {
 .page {
   min-height: 100vh;
   background: #f8fafc;
-  padding-bottom: 40rpx;
+  padding-bottom: 200rpx;
 }
 
 /* 顶部导航 */
@@ -336,6 +340,7 @@ onMounted(() => {
     flex: 1;
     display: flex;
     align-items: center;
+    justify-content: center;
     padding: 24rpx;
     
     &:not(:last-child) {
@@ -347,17 +352,22 @@ onMounted(() => {
       height: 12rpx;
       border-radius: 50%;
       margin-right: 16rpx;
+      flex-shrink: 0;
       
       &.green { background: #10b981; }
       &.amber { background: #f97316; }
     }
     
     .stats-info {
-      flex: 1;
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+      justify-content: center;
       
       .stats-value {
         display: flex;
         align-items: center;
+        justify-content: center;
         font-size: 32rpx;
         font-weight: 700;
         color: #1e293b;
@@ -366,6 +376,7 @@ onMounted(() => {
       .stats-label {
         display: flex;
         align-items: center;
+        justify-content: center;
         font-size: 22rpx;
         color: #64748b;
       }

+ 5 - 1
haha-admin-mp/src/pages/my/my.vue

@@ -116,12 +116,16 @@
     <view class="version-info">
       <text>版本 1.0.0</text>
     </view>
+    
+    <!-- 自定义TabBar -->
+    <CustomTabBar />
   </view>
 </template>
 
 <script setup lang="ts">
 import { ref, onMounted } from 'vue';
 import NavBar from '@/components/NavBar.vue';
+import CustomTabBar from '@/components/CustomTabBar.vue';
 import { getUserInfo, clearAuth } from '@/utils/auth';
 import { showConfirm, showToast } from '@/utils/common';
 
@@ -163,7 +167,7 @@ onMounted(() => {
 .page {
   min-height: 100vh;
   background: #f8fafc;
-  padding-bottom: 40rpx;
+  padding-bottom: 200rpx;
 }
 
 /* 用户区域 */

+ 5 - 0
haha-admin-mp/src/pages/orders/list.vue

@@ -110,12 +110,16 @@
         </view>
       </view>
     </view>
+    
+    <!-- 自定义TabBar -->
+    <CustomTabBar />
   </view>
 </template>
 
 <script setup lang="ts">
 import { ref, onMounted } from 'vue';
 import NavBar from '@/components/NavBar.vue';
+import CustomTabBar from '@/components/CustomTabBar.vue';
 import { getOrderList, handleRefund as refundOrder } from '@/api/order';
 import { OrderStatusText, OrderStatusColor, OrderStatus } from '@/mock/order';
 import { formatMoney as formatMoneyUtil, showConfirm, showToast } from '@/utils/common';
@@ -217,6 +221,7 @@ onMounted(() => {
   background: #f8fafc;
   display: flex;
   flex-direction: column;
+  padding-bottom: 200rpx;
 }
 
 /* 筛选栏 */