TabBar.vue 4.18 KB
<!--
 * @Date: 2026-01-29 20:33:23
 * @LastEditors: hookehuyr hookehuyr@gmail.com
 * @LastEditTime: 2026-02-03 22:06:37
 * @FilePath: /manulife-weapp/src/components/TabBar.vue
 * @Description: 通用底部导航栏组件,用于页面底部固定导航栏,展示页面标题。
-->
<template>
  <view
    class="fixed bottom-0 left-0 w-full bg-white shadow-[0_-4rpx_16rpx_rgba(0,0,0,0.05)] pb-[env(safe-area-inset-bottom)] z-50">
    <view class="flex items-center justify-around py-[32rpx]">
      <view class="flex-1 flex flex-col items-center justify-center" v-for="(item, index) in tabs" :key="index"
        @tap="handleTabClick(item)">
        <view class="relative">
          <IconFont :name="item.icon" :class="[current === item.key ? 'text-blue-600' : 'text-gray-400']" size="24" />
          <!-- 红点提醒标记 -->
          <view v-if="badges.includes(item.key)" class="tabbar-badge"></view>
        </view>
        <text class="text-[20rpx] mt-[8rpx]" :class="[current === item.key ? 'text-blue-600' : 'text-gray-400']">{{
          item.label }}</text>
      </view>
    </view>
  </view>
</template>

<script setup>
import { shallowRef, computed } from 'vue'
import IconFont from '@/components/IconFont.vue'
import { useGo } from '@/hooks/useGo'
import Taro from '@tarojs/taro'
import { useUserStore } from '@/stores/user'

const props = defineProps({
  current: {
    type: String,
    default: 'home'
  }
})

const go = useGo()
const userStore = useUserStore()

// 自动从 user store 读取红点状态
const badges = computed(() => userStore.tabBarBadges)

const tabs = shallowRef([
  {
    key: 'home',
    label: '首页',
    icon: 'home',
    path: '/pages/index/index'
  },
  {
    key: 'ai',
    label: 'AI答疑',
    icon: 'service',
    path: '/pages/ai/index'
  },
  {
    key: 'me',
    label: '我的',
    icon: 'my',
    path: '/pages/mine/index'
  }
])

const handleTabClick = (item) => {
  if (item.key === props.current) return

  if (item.key === 'home') {
    go(item.path)
  } else if (item.key === 'me') {
    // Check if 'me' page exists, otherwise show toast or just go
    // For now, assuming me page might not exist or we just navigate
    // go(item.path)
    // Based on existing logic in index.vue:
    // Taro.redirectTo({ url: '/pages/me/index' });
    // But wait, standard tab bar usually uses switchTab or redirectTo.
    // Since this is a custom tab bar, we use useGo (which uses navigateTo usually).
    // Ideally for tab switching we might want reLaunch or redirectTo to avoid stack buildup.
    // However, useGo defaults to navigateTo.
    // Let's use reLaunch to simulate tab switching behavior if it's a "tab bar"

    // Actually, let's look at index.vue logic:
    // if (item.key === 'me') Taro.redirectTo({ url: '/pages/me/index' });
    // if (item.key === 'ai') Taro.showToast({ title: '功能开发中', icon: 'none' });

    // I will replicate this logic for now but make it more generic if possible.
    // Since 'me' and 'ai' might not be fully implemented, I will stick to what I know.
    // But 'onboarding' and 'signing' pages use this tab bar too.

    // If we are on 'onboarding' (which is seemingly a sub-page but has a tab bar),
    // clicking 'Home' should probably go back to Home.

    Taro.reLaunch({ url: item.path })
  } else if (item.key === 'ai') {
    // 跳转到腾讯元宝AI小程序(定制版)
    Taro.navigateToMiniProgram({
      appId: 'wxd5201eb08d2fa15c', // 腾讯元宝小程序 AppID
      path: 'pages/agentChat/index?showAuthDirectly=1&agentId=sOySYp2PV9qa', // 拼接查询参数到路径中
      envVersion: 'release', // 打开正式版
      success: (res) => {
        console.log('跳转元宝小程序成功', res)
      },
      fail: (err) => {
        console.error('跳转元宝小程序失败', err)
        Taro.showToast({
          title: '跳转失败,请稍后重试',
          icon: 'none'
        })
      }
    })
  }
}
</script>

<style lang="less">
/* 红点提醒标记样式 */
.tabbar-badge {
  position: absolute;
  top: -10rpx;
  right: -10rpx;
  width: 16rpx;
  height: 16rpx;
  background-color: #ff4d4f;
  border-radius: 50%;
  border: 2rpx solid #fff;
  box-shadow: 0 2rpx 8rpx rgba(255, 77, 79, 0.3);
  z-index: 1;
}
</style>