hookehuyr

feat(导航): 实现小程序底部导航激活状态与跳转优化

添加 CHECKIN_ACTIVE_TAB 常量及 resolveCheckinActiveTab 函数,用于解析路由参数中的激活标签页
重构 JlsBottomNav 组件,使用新的解析函数并实现根据 activeTab 高亮对应导航项
将小程序内跳转从 navigateTo 改为 redirectTo 以避免页面栈累积
更新相关单元测试以覆盖新增功能
......@@ -6,7 +6,9 @@ describe('checkin nav mode helpers', function () {
it('resolves nav mode and map height from route query', async function () {
const {
CHECKIN_NAV_MODE,
CHECKIN_ACTIVE_TAB,
resolveCheckinNavMode,
resolveCheckinActiveTab,
getCheckinMapHeight,
} = await import('../src/views/checkin/nav-mode.js');
......@@ -17,6 +19,13 @@ describe('checkin nav mode helpers', function () {
CHECKIN_NAV_MODE.LEGACY,
);
expect(resolveCheckinActiveTab({ activeTab: 'home' })).to.equal(CHECKIN_ACTIVE_TAB.HOME);
expect(resolveCheckinActiveTab({ activeTab: 'message' })).to.equal(
CHECKIN_ACTIVE_TAB.MESSAGE,
);
expect(resolveCheckinActiveTab({ activeTab: 'mine' })).to.equal(CHECKIN_ACTIVE_TAB.MINE);
expect(resolveCheckinActiveTab({ activeTab: 'unexpected' })).to.equal('');
expect(
getCheckinMapHeight({
isMiniProgramWebView: false,
......
......@@ -23,6 +23,7 @@ import HomeIcon from '@nutui/icons-vue/dist/es/icons/Home.js';
import MessageIcon from '@nutui/icons-vue/dist/es/icons/Message.js';
import MyIcon from '@nutui/icons-vue/dist/es/icons/My.js';
import wx from 'weixin-js-sdk';
import { resolveCheckinActiveTab } from '@/views/checkin/nav-mode.js';
const ACTIVE_COLOR = '#a67939';
const INACTIVE_COLOR = '#8b95a7';
......@@ -39,16 +40,12 @@ const navItems = [
{ name: 'mine', path: '/pages/mine/index', icon: MyIcon, label: '我的' },
];
const reservedActiveTab = computed(() => {
const rawTab = Array.isArray(route.query.activeTab) ? route.query.activeTab[0] : route.query.activeTab;
return String(rawTab || '').trim().toLowerCase();
const currentActiveTab = computed(() => {
return resolveCheckinActiveTab(route.query || {});
});
const isActive = () => {
// 地图页目前不属于 JLS tab 列表中的任何一项。
// activeTab 参数先预留,待业务确认后再决定是否映射到某个 tab 并启用高亮。
void reservedActiveTab.value;
return false;
const isActive = (name) => {
return currentActiveTab.value === name;
};
const getIconColor = (name) => {
......@@ -60,8 +57,8 @@ const navigate = (path) => {
return;
}
if (wx?.miniProgram?.navigateTo) {
wx.miniProgram.navigateTo({
if (wx?.miniProgram?.redirectTo) {
wx.miniProgram.redirectTo({
url: path,
fail: () => {
wx?.miniProgram?.reLaunch?.({ url: path });
......
......@@ -4,6 +4,12 @@ export const CHECKIN_NAV_MODE = {
NONE: 'none',
};
export const CHECKIN_ACTIVE_TAB = {
HOME: 'home',
MESSAGE: 'message',
MINE: 'mine',
};
const NAV_HEIGHT = '80px';
export function resolveCheckinNavMode(query = {}) {
......@@ -32,3 +38,22 @@ export function getCheckinMapHeight({
return `calc(100vh - ${navHeight})`;
}
export function resolveCheckinActiveTab(query = {}) {
const rawTab = Array.isArray(query.activeTab) ? query.activeTab[0] : query.activeTab;
const normalizedTab = String(rawTab || '').trim().toLowerCase();
if (normalizedTab === CHECKIN_ACTIVE_TAB.HOME) {
return CHECKIN_ACTIVE_TAB.HOME;
}
if (normalizedTab === CHECKIN_ACTIVE_TAB.MESSAGE) {
return CHECKIN_ACTIVE_TAB.MESSAGE;
}
if (normalizedTab === CHECKIN_ACTIVE_TAB.MINE) {
return CHECKIN_ACTIVE_TAB.MINE;
}
return '';
}
......