Преглед на файлове

feat(tabbar): 添加中间凸起按钮功能并更新配置

添加中间凸起按钮功能,支持自定义图标和点击事件处理
更新tabbar配置,增加isBulge字段标识凸起按钮项
修改默认策略为CUSTOM_TABBAR_WITH_CACHE
添加扫描图标资源文件
feige996 преди 8 месеца
родител
ревизия
1980595ba8
променени са 3 файла, в които са добавени 54 реда и са изтрити 5 реда
  1. BIN
      src/static/tabbar/scan.png
  2. 5 3
      src/tabbar/config.ts
  3. 49 2
      src/tabbar/index.vue

BIN
src/static/tabbar/scan.png


+ 5 - 3
src/tabbar/config.ts

@@ -2,12 +2,13 @@ import type { TabBar } from '@uni-helper/vite-plugin-uni-pages'
 
 type NativeTabBarItem = TabBar['list'][0]
 
-type CustomTabBarItem = Pick<NativeTabBarItem, 'text' | 'pagePath'> & {
+type CustomTabBarItem = (Pick<NativeTabBarItem, 'text' | 'pagePath'> & {
   iconType: 'uniUi' | 'uiLib' | 'unocss' | 'iconfont' | 'image' // 不建议用 image 模式,需要配置2张图
   icon: any // 其实是 string 类型,这里是为了避免 ts 报错 (tabbar/index.vue 里面 uni-icons 那行)
   activeIcon?: string // 只有在 image 模式下才需要,传递的是高亮的图片(PS: 不建议用 image 模式)
   badge?: number | 'dot' // badge 显示一个数字或 小红点(样式可以直接在 tabbar/index.vue 里面修改)
-}
+  isBulge?: boolean // 是否是中间的鼓包tabbarItem
+})
 
 /**
  * tabbar 选择的策略,更详细的介绍见 tabbar.md 文件
@@ -26,7 +27,7 @@ export const TABBAR_MAP = {
 }
 
 // TODO: 1/3. 通过这里切换使用tabbar的策略
-export const selectedTabbarStrategy = TABBAR_MAP.NATIVE_TABBAR
+export const selectedTabbarStrategy = TABBAR_MAP.CUSTOM_TABBAR_WITH_CACHE
 
 // TODO: 2/3. 更新下面的 tabbar 配置
 // 如果是使用 NO_TABBAR(0),nativeTabbarList 和 customTabbarList 都不生效(里面的配置不用管)
@@ -73,6 +74,7 @@ export const customTabbarList: CustomTabBarItem[] = [
     icon: 'i-carbon-code',
     // badge: 10,
   },
+
   // {
   //   pagePath: 'pages/mine/index',
   //   text: '我的',

+ 49 - 2
src/tabbar/index.vue

@@ -10,13 +10,31 @@ defineOptions({
 })
 // #endif
 
+// TODO 1/2: 中间的鼓包tabbarItem的开关
+const BULGE_ENABLE = true
+function handleClickBulge() {
+  console.log('点击了中间的鼓包tabbarItem')
+}
+
 /** tabbarList 里面的 path 从 pages.config.ts 得到 */
 const tabbarList = _tabBarList.map(item => ({ ...item, path: `/${item.pagePath}` }))
+if (BULGE_ENABLE) {
+  if (tabbarList.length % 2 === 1) {
+    console.error('tabbar 数量必须是偶数,否则样式很奇怪!!')
+  }
+  tabbarList.splice(tabbarList.length / 2, 0, {
+    isBulge: true,
+  } as any)
+}
 function handleClick(index: number) {
   // 点击原来的不做操作
   if (index === tabbarStore.curIdx) {
     return
   }
+  if (tabbarList[index].isBulge) {
+    handleClickBulge()
+    return
+  }
   const url = tabbarList[index].path
   tabbarStore.setCurIdx(index)
   if (tabbarCacheEnable) {
@@ -34,7 +52,7 @@ onLoad(() => {
       console.log('hideTabBar fail: ', err)
     },
     success(res) {
-      console.log('hideTabBar success: ', res)
+      // console.log('hideTabBar success: ', res)
     },
   })
 })
@@ -63,7 +81,15 @@ function getImageByIndex(index: number, item: { iconActive?: string, icon: strin
           :style="{ color: getColorByIndex(index) }"
           @click="handleClick(index)"
         >
-          <view class="relative px-3">
+          <view v-if="item.isBulge" class="relative">
+            <!-- 中间一个鼓包tabbarItem的处理 -->
+            <view class="bulge">
+              <!-- TODO 2/2: 通常是一个图片,或者icon,点击触发业务逻辑 -->
+              <!-- 常见的是:扫描按钮、发布按钮、更多按钮等 -->
+              <image class="mt-6rpx h-200rpx w-200rpx" src="/static/tabbar/scan.png" />
+            </view>
+          </view>
+          <view v-else class="relative px-3">
             <template v-if="item.iconType === 'uniUi'">
               <uni-icons :type="item.icon" size="20" :color="getColorByIndex(index)" />
             </template>
@@ -97,6 +123,7 @@ function getImageByIndex(index: number, item: { iconActive?: string, icon: strin
           </view>
         </view>
       </view>
+
       <view class="pb-safe" />
     </view>
   </view>
@@ -112,4 +139,24 @@ function getImageByIndex(index: number, item: { iconActive?: string, icon: strin
   border-top: 1px solid #eee;
   box-sizing: border-box;
 }
+// 中间鼓包的样式
+.bulge {
+  position: absolute;
+  top: -20px;
+  left: 50%;
+  transform-origin: top center;
+  transform: translateX(-50%) scale(0.5) translateY(-33%);
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  width: 250rpx;
+  height: 250rpx;
+  border-radius: 50%;
+  background-color: #fff;
+  box-shadow: inset 0 0 0 1px #fefefe;
+
+  &:active {
+    opacity: 0.8;
+  }
+}
 </style>