mrr.sj.front/components/tabbar/tabbar.vue

209 lines
7.1 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<uv-tabbar
v-if="tabbarReady"
:key="refreshKey"
fixed
:value="currentTabIndex"
@change="onTabChange"
activeColor="#FF4767"
:placeholder="false"
:safeAreaInsetBottom="false"
:customStyle="{height:'110rpx'}"
>
<uv-tabbar-item
v-for="(item, idx) in tabbarList"
:key="idx"
:name="idx"
:text="item.text"
:badge="getNum(idx)"
:customStyle="{height:'110rpx'}"
@click="onItemClick(idx)"
>
<template v-slot:active-icon>
<image class="icon" :src="item.selectedIconPath"></image>
</template>
<template v-slot:inactive-icon>
<image class="icon" :src="item.iconPath"></image>
</template>
</uv-tabbar-item>
</uv-tabbar>
</template>
<script>
import { mapState, mapMutations } from 'vuex';
import request from "@/utils/request";
export default {
name: "tab-bar",
// 不再需要 props.selected完全由 Vuex 控制高亮
data() {
return {
refreshKey: 0, // 强制重建标识
tabbarReady: false, // 组件就绪标识
tabbarList: [ // tab 配置
{
iconPath: "/static/images/tabbar/new_home_gray.png",
text: "首页",
selectedIconPath: "/static/images/tabbar/new_home.png",
pagePath: "/pages/home/home"
},
{
iconPath: "/static/images/tabbar/new_order_gray.png",
text: "订单",
selectedIconPath: "/static/images/tabbar/new_order.png",
pagePath: "/pages/order/userorder-list"
},
{
iconPath: "/static/images/tabbar/new_message_gray.png",
text: "消息",
selectedIconPath: "/static/images/tabbar/new_message.png",
pagePath: "/pages/message/message"
},
{
iconPath: "/static/images/tabbar/new_my_gray.png",
text: "我的",
selectedIconPath: "/static/images/tabbar/new_my.png",
pagePath: "/pages/my/my"
}
]
};
},
computed: {
// 保留对消息数量的映射
...mapState(['messageNum']),
// ========= 动态计算当前高亮索引 =========
// 替代原先直接获取 Vuex 的方式,改为根据当前真实路由计算,解决刷新状态丢失问题
currentTabIndex() {
try {
// 获取当前页面栈
const pages = getCurrentPages();
if (pages && pages.length > 0) {
// 获取当前页面实例
const currentPage = pages[pages.length - 1];
// 拼接当前页面路径(兼容不同平台获取路由的方式)
const currentPath = '/' + (currentPage.route || currentPage.__route__);
// 在 tabbarList 中查找匹配当前路径的索引
const index = this.tabbarList.findIndex(item => item.pagePath === currentPath);
if (index !== -1) {
return index;
}
}
// 如果由于某些原因匹配不到,降级去取 Vuex 中的值(防止其他极端情况报错)
return this.$store.state.currentTabIndex || 0;
} catch (e) {
return this.$store.state.currentTabIndex || 0;
}
}
// =================================================
},
watch: {
// 当 tabbarList 内容变化(如异步更新图标)时,强制重建组件
tabbarList: {
deep: true,
handler() {
this.rebuildTabbar();
}
}
},
created() {
// 初始化时延迟显示,避免闪烁
this.tabbarReady = false;
this.$nextTick(() => {
this.tabbarReady = true;
// 如果需要异步加载图标,取消下面注释
// this.getButtonImg();
});
},
methods: {
...mapMutations(['SET_CURRENT_TAB_INDEX']),
// 设置全局选中索引(简化调用)
setCurrentTabIndex(index) {
this.SET_CURRENT_TAB_INDEX(index);
},
// 强制重建 uv-tabbar用于异步更新图标后
rebuildTabbar() {
this.tabbarReady = false;
this.$nextTick(() => {
this.refreshKey++;
this.tabbarReady = true;
});
},
// 获取角标数字(只有消息 tab 且数量 > 0 才显示)
getNum(index) {
if (index === 2 && this.messageNum > 0) {
return this.messageNum;
}
return null;
},
// 异步更新图标(保留你的业务逻辑)
async getButtonImg() {
try {
let res = await request.post("/sj/poster/getButtonImg", {});
if (res.code === 200) {
this.tabbarList.forEach((item, index) => {
if (res.data[index]?.iconPath) {
item.iconPath = res.data[index].iconPath;
}
if (res.data[index]?.selectedIconPath) {
item.selectedIconPath = res.data[index].selectedIconPath;
}
});
this.$store.commit("setTabbarList", this.tabbarList);
// 图标更新后,强制重建组件
this.rebuildTabbar();
}
} catch (err) {
console.error('getButtonImg 请求失败', err);
}
},
// uv-tabbar 的 change 事件(组件内部触发)
onTabChange(val) {
const idx = parseInt(val, 10);
this.doJump(idx);
},
// 手动点击 item 时触发
onItemClick(idx) {
this.doJump(idx);
},
// 实际跳转逻辑 + 更新全局高亮
doJump(index) {
const idx = parseInt(index, 10);
if (isNaN(idx) || !this.tabbarList[idx]) return;
// 依然更新全局高亮,确保其他可能依赖 Vuex 状态的逻辑正常运行
this.setCurrentTabIndex(idx);
// 跳转页面
const targetPage = this.tabbarList[idx].pagePath;
uni.switchTab({
url: targetPage,
fail: (err) => console.error('switchTab 失败', err)
});
// 保留你原有的消息更新方法
if (typeof this.messageUpudateNum === 'function') {
this.messageUpudateNum();
}
}
}
};
</script>
<style lang="scss">
.icon {
height: 54rpx;
width: 54rpx;
}
::v-deep .uv-tabbar__content {
z-index: 999 !important;
}
</style>