hookehuyr

feat(导航): 添加全局底部导航组件并替换各页面原有导航

将原有的分散在各页面的底部导航代码重构为可复用的indexNav组件
支持不同位置、选中状态和中心按钮样式配置
通过props控制导航行为和样式,统一管理导航逻辑
......@@ -7,6 +7,7 @@ export {}
declare module 'vue' {
export interface GlobalComponents {
IndexNav: typeof import('./src/components/indexNav.vue')['default']
NutButton: typeof import('@nutui/nutui-taro')['Button']
NutCheckbox: typeof import('@nutui/nutui-taro')['Checkbox']
NutCheckboxGroup: typeof import('@nutui/nutui-taro')['CheckboxGroup']
......
<template>
<view class="index-nav" :class="[`is-${position}`]">
<view class="nav-logo" :class="{ 'is-active': active === 'home' }" @tap="() => on_select('home')">
<image class="nav-icon" :src="icons?.home" mode="aspectFit" />
<text class="nav-text">首页</text>
</view>
<view
class="nav-logo"
:class="[{ 'is-active': active === 'code' }, { 'is-center-raised': center_variant === 'raised' }]"
@tap="() => on_select('code')"
>
<image
class="nav-icon"
:class="{ 'nav-icon--raised': center_variant === 'raised' }"
:src="icons?.code"
mode="aspectFit"
/>
<view v-if="center_variant === 'raised'" class="nav-icon-placeholder"></view>
<text class="nav-text">预约码</text>
</view>
<view class="nav-logo" :class="{ 'is-active': active === 'me' }" @tap="() => on_select('me')">
<image class="nav-icon" :src="icons?.me" mode="aspectFit" />
<text class="nav-text">我的</text>
</view>
</view>
</template>
<script setup>
const props = defineProps({
icons: {
type: Object,
default: () => ({})
},
active: {
type: String,
default: ''
},
position: {
type: String,
default: 'fixed'
},
center_variant: {
type: String,
default: 'normal'
},
allow_active_tap: {
type: Boolean,
default: false
}
})
const emit = defineEmits(['select'])
const on_select = (key) => {
if (!props.allow_active_tap && props.active && key === props.active) return
emit('select', key)
}
</script>
<style lang="less">
.index-nav {
left: 0;
bottom: 0;
width: 750rpx;
height: 134rpx;
background: #FFFFFF;
box-shadow: 0 -10rpx 8rpx 0 rgba(0, 0, 0, 0.12);
display: flex;
align-items: center;
justify-content: space-around;
color: #A67939;
z-index: 99;
&.is-fixed {
position: fixed;
}
&.is-absolute {
position: absolute;
}
.nav-logo {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
}
.nav-icon {
width: 48rpx;
height: 48rpx;
display: block;
&.nav-icon--raised {
width: 130rpx;
height: 130rpx;
position: absolute;
top: -100rpx;
left: 50%;
transform: translateX(-50%);
}
}
.nav-icon-placeholder {
width: 48rpx;
height: 48rpx;
}
.nav-text {
font-size: 24rpx;
margin-top: 12rpx;
line-height: 1;
}
.nav-logo.is-center-raised {
.nav-text {
margin-top: -10rpx;
}
}
}
</style>
<!--
* @Date: 2024-01-16 10:06:47
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2026-01-13 21:33:58
* @LastEditTime: 2026-01-21 17:14:47
* @FilePath: /xyxBooking-weapp/src/pages/bookingCode/index.vue
* @Description: 预约码页面
-->
......@@ -15,20 +15,13 @@
<view style="height: 256rpx;"></view>
</view>
</view>
<view class="index-nav">
<view class="nav-logo" @tap="toHome">
<image :src="icon_3" style="width: 48rpx; height: 48rpx;" />
首页
</view>
<view class="nav-logo">
<image :src="icon_4" style="width: 48rpx; height: 48rpx; margin-bottom: 3rpx;" />
预约码
</view>
<view class="nav-logo" @tap="toMy">
<image :src="icon_5" style="width: 48rpx; height: 48rpx;" />
我的
</view>
</view>
<indexNav
:icons="nav_icons"
active="code"
position="fixed"
center_variant="normal"
@select="on_nav_select"
/>
</view>
</template>
......@@ -37,6 +30,7 @@ import { ref } from 'vue'
import Taro, { useDidShow } from '@tarojs/taro'
import qrCode from '@/components/qrCode';
import { IconFont } from '@nutui/icons-vue-taro'
import indexNav from '@/components/indexNav.vue'
import icon_3 from '@/assets/images/首页01@2x.png'
import icon_4 from '@/assets/images/二维码icon.png'
import icon_5 from '@/assets/images/我的01@2x.png'
......@@ -89,6 +83,13 @@ const toHome = () => { // 跳转到首页
})
}
const nav_icons = { home: icon_3, code: icon_4, me: icon_5 }
const on_nav_select = (key) => {
if (key === 'home') return toHome()
if (key === 'me') return toMy()
}
</script>
<style lang="less">
......@@ -102,25 +103,5 @@ const toHome = () => { // 跳转到首页
color: #A67939;
margin-top: 32rpx;
}
.index-nav {
position: fixed;
bottom: 0;
left: 0;
width: 750rpx;
height: 134rpx;
background: #FFFFFF;
box-shadow: 0 -10rpx 8rpx 0 rgba(0,0,0,0.12);
display: flex;
align-items: center;
justify-content: space-around;
color: #A67939;
.nav-logo {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
}
}
}
</style>
......
......@@ -33,21 +33,13 @@
</view>
<view class="logo" :style="logo_style"></view>
</view>
<view class="index-nav">
<view class="nav-logo">
<image :src="icon_3" style="width: 48rpx; height: 48rpx;" />
首页
</view>
<view class="nav-logo" @tap="toCode">
<image :src="icon_4" style="width: 140rpx; height: 140rpx; position: absolute; top: -100rpx;" />
<view style="width: 48rpx; height: 48rpx;"></view>
预约码
</view>
<view class="nav-logo" @tap="toMy">
<image :src="icon_5" style="width: 48rpx; height: 48rpx;" />
我的
</view>
</view>
<indexNav
:icons="nav_icons"
active="home"
position="absolute"
center_variant="raised"
@select="on_nav_select"
/>
</view>
</template>
......@@ -58,6 +50,7 @@ import { ref, onMounted, onUnmounted, computed } from 'vue'
import { useGo } from '@/hooks/useGo'
import { get_network_type, is_usable_network } from '@/utils/network'
import { weak_network_text } from '@/utils/uiText'
import indexNav from '@/components/indexNav.vue'
import icon_1 from '@/assets/images/立即预约@2x.png'
import icon_3 from '@/assets/images/首页02@2x.png'
......@@ -230,6 +223,13 @@ const toMy = () => { // 跳转到我的
})
}
const nav_icons = { home: icon_3, code: icon_4, me: icon_5 }
const on_nav_select = (key) => {
if (key === 'code') return toCode()
if (key === 'me') return toMy()
}
useShareAppMessage(() => {
return {
title: '西园寺预约',
......@@ -355,24 +355,5 @@ useShareAppMessage(() => {
background-position: center;
}
}
.index-nav {
position: absolute;
bottom: 0;
left: 0;
width: 750rpx;
height: 134rpx;
background: #FFFFFF;
box-shadow: 0 -10rpx 8rpx 0 rgba(0,0,0,0.12);
display: flex;
align-items: center;
justify-content: space-around;
color: #A67939;
.nav-logo {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
}
}
}
</style>
......
......@@ -9,21 +9,13 @@
<IconFont name="rect-right" size="38rpx" />
</view>
</view>
<view class="index-nav">
<view class="nav-logo" @tap="toHome">
<image :src="icon_3" style="width: 48rpx; height: 48rpx;" />
首页
</view>
<view class="nav-logo" @tap="toCode">
<image :src="icon_4" style="width: 140rpx; height: 140rpx; position: absolute; top: -100rpx;" />
<view style="width: 48rpx; height: 48rpx;"></view>
预约码
</view>
<view class="nav-logo">
<image :src="icon_5" style="width: 48rpx; height: 48rpx;" />
我的
</view>
</view>
<indexNav
:icons="nav_icons"
active="me"
position="fixed"
center_variant="raised"
@select="on_nav_select"
/>
</view>
</template>
......@@ -32,6 +24,7 @@ import { ref } from 'vue'
import Taro from '@tarojs/taro'
import { useGo } from '@/hooks/useGo'
import { IconFont } from '@nutui/icons-vue-taro'
import indexNav from '@/components/indexNav.vue'
import icon_3 from '@/assets/images/首页01@2x.png'
import icon_4 from '@/assets/images/二维码icon.png'
import icon_5 from '@/assets/images/我的02@2x.png'
......@@ -78,6 +71,13 @@ const toHome = () => { // 跳转到首页
})
}
const nav_icons = { home: icon_3, code: icon_4, me: icon_5 }
const on_nav_select = (key) => {
if (key === 'home') return toHome()
if (key === 'code') return toCode()
}
const menu_list = [{
icon: icon_booking,
name: '预约记录',
......@@ -114,24 +114,5 @@ const menu_list = [{
align-items: center;
}
}
.index-nav {
position: fixed;
bottom: 0;
left: 0;
width: 750rpx;
height: 134rpx;
background: #FFFFFF;
box-shadow: 0 -10rpx 8rpx 0 rgba(0,0,0,0.12);
display: flex;
align-items: center;
justify-content: space-around;
color: #A67939;
.nav-logo {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
}
}
}
</style>
......
......@@ -26,20 +26,14 @@
</view>
</view>
<view style="height: 256rpx;"></view>
<view class="index-nav">
<view class="nav-logo" @tap="toHome">
<image :src="icon_3" style="width: 48rpx; height: 48rpx;" />
首页
</view>
<view class="nav-logo" @tap="toCode">
<image :src="icon_4" style="width: 48rpx; height: 48rpx; margin-bottom: 3rpx;" />
预约码
</view>
<view class="nav-logo" @tap="toMy">
<image :src="icon_5" style="width: 48rpx; height: 48rpx;" />
我的
</view>
</view>
<indexNav
:icons="nav_icons"
active="me"
:allow_active_tap="true"
position="fixed"
center_variant="normal"
@select="on_nav_select"
/>
</view>
</template>
......@@ -49,6 +43,7 @@ import Taro, { useDidShow } from '@tarojs/taro'
import { IconFont } from '@nutui/icons-vue-taro'
import { useGo } from '@/hooks/useGo'
import { personListAPI, delPersonAPI } from '@/api/index'
import indexNav from '@/components/indexNav.vue'
import icon_3 from '@/assets/images/首页01@2x.png'
import icon_4 from '@/assets/images/二维码icon.png'
import icon_5 from '@/assets/images/我的02@2x.png'
......@@ -65,6 +60,14 @@ const toMy = () => { // 跳转到我的
go('/pages/me/index');
}
const nav_icons = { home: icon_3, code: icon_4, me: icon_5 }
const on_nav_select = (key) => {
if (key === 'home') return toHome()
if (key === 'code') return toCode()
if (key === 'me') return toMy()
}
const visitorList = ref([]);
function replaceMiddleCharacters(inputString) {
......@@ -169,26 +172,5 @@ useDidShow(() => {
}
}
}
.index-nav {
position: fixed;
bottom: 0;
left: 0;
width: 750rpx;
height: 134rpx;
background: #FFFFFF;
box-shadow: 0 -10rpx 8rpx 0 rgba(0,0,0,0.12);
display: flex;
align-items: center;
justify-content: space-around;
color: #A67939;
.nav-logo {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
font-size: 26rpx;
}
}
}
</style>
......