refactor(merchcategory): add bottom tabbar and optimize page layout

1. add diy bottom navigation component to the merch category page
2. replace hardcoded height style with dynamic computed style based on tabbar status
3. add unified page path mapping and url resolution utilities
4. update page jump logic to use new page_key based routing
This commit is contained in:
2026-06-16 08:40:59 +08:00
parent 7b83636c99
commit b86e8e7fa6
2 changed files with 167 additions and 4 deletions

View File

@@ -42,6 +42,140 @@ export const MEMBER_PAGE_URL = '/pages_tool/member/index';
export const LOGIN_PAGE_URL = '/pages_tool/login/login';
export const AI_CHAT_PAGE_URL = '/pages_tool/ai-chat/index';
// page_key 到实际路径的映射表(统一管理所有页面的语义常量 → 实际路径)
// 前端组织页面(重命名路径、分包调整)时只需要修改此映射表
export const PAGE_KEY_MAP = {
// === 主页 & 商品 ===
PAGE_INDEX: '/pages/index/index',
PAGE_GOODS_LIST: '/pages_goods/list',
PAGE_GOODS_CATEGORY: '/pages_goods/category',
PAGE_GOODS_DETAIL: '/pages_goods/detail',
PAGE_GOODS_CART: '/pages_goods/cart',
PAGE_GOODS_COUPON: '/pages_tool/goods/coupon',
PAGE_GOODS_BRAND: '/pages_tool/goods/brand',
// === 订单 ===
PAGE_ORDER_LIST: '/pages/order/list',
PAGE_ORDER_DETAIL: '/pages/order/detail',
PAGE_ORDER_CREATE: '/pages/order/create',
PAGE_ORDER_REFUND: '/pages/order/refund',
PAGE_ORDER_ACTIVIST: '/pages/order/activist',
// === 会员中心 ===
PAGE_MEMBER_INDEX: '/pages_tool/member/index',
PAGE_MEMBER_INFO: '/pages_tool/member/info',
PAGE_MEMBER_ACCOUNT: '/pages_tool/member/account',
PAGE_MEMBER_COLLECTION: '/pages_tool/member/collection',
PAGE_MEMBER_FOOTPRINT: '/pages_tool/member/footprint',
PAGE_MEMBER_COUPON: '/pages_tool/member/coupon',
PAGE_MEMBER_BALANCE: '/pages_tool/member/balance_detail',
PAGE_MEMBER_ADDRESS: '/pages_tool/member/address',
PAGE_MEMBER_LEVEL: '/pages_tool/member/level',
PAGE_MEMBER_SIGNIN: '/pages_tool/member/signin',
PAGE_MEMBER_CARD: '/pages_tool/member/card',
PAGE_MEMBER_CONTACT: '/pages_tool/member/contact',
// === 公告/文章/帮助 ===
PAGE_NOTICE_LIST: '/pages_tool/notice/list',
PAGE_ARTICLE_LIST: '/pages_tool/article/list',
PAGE_ARTICLE_DETAIL: '/pages_tool/article/detail',
PAGE_HELP_LIST: '/pages_tool/help/list',
// === 积分商城 ===
PAGE_POINT_LIST: '/pages_promotion/point/list',
PAGE_POINT_ORDER_LIST: '/pages_promotion/point/order_list',
// === 分销 ===
PAGE_FENXIAO_INDEX: '/pages_promotion/fenxiao/index',
PAGE_FENXIAO_WITHDRAW: '/pages_promotion/fenxiao/withdraw_list',
PAGE_FENXIAO_ORDER: '/pages_promotion/fenxiao/order',
PAGE_FENXIAO_TEAM: '/pages_promotion/fenxiao/team',
PAGE_FENXIAO_PROMOTE: '/pages_promotion/fenxiao/promote_code',
// === 商户 ===
PAGE_MERCH_CATEGORY: '/pages_promotion/merch/merchcategory',
// === 案例展示 ===
PAGE_CASES_INDEX: '/pages_tool/cases/index',
// === 电子名片 ===
PAGE_CONTACT_CARD: '/pages/contact/contact',
// === VR ===
PAGE_VR_INDEX: '/pages_tool/vr/index',
// === 介质材料/结构选型 ===
PAGE_SEAL_MEDIUM: '/pages_tool/seal/medium/search',
PAGE_SEAL_STRUCTURE: '/pages_tool/seal/structure',
// === 充值/核销 ===
PAGE_RECHARGE_LIST: '/pages_tool/recharge/list',
PAGE_VERIFICATION_INDEX: '/pages_tool/verification/index',
// === 登录/联系 ===
PAGE_LOGIN: '/pages_tool/login/login',
PAGE_REGISTER: '/pages_tool/login/register',
PAGE_CONTACT: '/pages_tool/contact/contact',
// === 文件/微页面 ===
PAGE_FILES_LIST: '/pages_tool/files/list',
PAGE_FILES_DETAIL: '/pages_tool/files/detail',
PAGE_DIY_VIEW: '/pages_tool/index/diy',
// === 其他 ===
PAGE_AI_CHAT: '/pages_tool/ai-chat/index',
PAGE_WEBVIEW: '/pages_tool/webview/webview'
};
/**
* 根据 page_key + params 解析得到实际跳转URL
* @param {string} page_key 页面语义常量,如 PAGE_GOODS_LIST
* @param {Object} params 页面参数(JSON对象)
* @returns {string|null} 实际URL(已拼接参数)或 null(未匹配)
*/
export const resolvePageUrl = (page_key, params = {}) => {
if (!page_key || !PAGE_KEY_MAP[page_key]) {
return null;
}
let url = PAGE_KEY_MAP[page_key];
if (params && typeof params === 'object' && Object.keys(params).length > 0) {
const parts = [];
Object.keys(params).forEach(function (key) {
const value = params[key];
if (value === null || value === undefined || value === '') return;
parts.push(key + '=' + encodeURIComponent(value));
});
if (parts.length > 0) {
url = url + (url.indexOf('?') !== -1 ? '&' : '?') + parts.join('&');
}
}
return url;
};
/**
* 解析 link 对象得到最终可跳转的 URL
* 优先级: page_key → wap_url → null
* @param {Object} link
* @returns {string|null}
*/
export const resolveLinkUrl = (link) => {
if (!link) return null;
// 优先使用 page_key(新机制)
if (link.page_key) {
let params = link.page_params;
if (typeof params === 'string' && params) {
try { params = JSON.parse(params); } catch (e) { params = {}; }
}
const url = resolvePageUrl(link.page_key, params || {});
if (url) return url;
}
// 回退:旧的 wap_url
if (link.wap_url) {
return decodeEntity(link.wap_url);
}
return null;
};
// 当前最新的tabBar.list (参见pages.json 中的tabBar.list 配置)
export const systemTabBarList = [
INDEX_PAGE_URL,
@@ -203,6 +337,15 @@ export default {
LOGIN_PAGE_URL,
AI_CHAT_PAGE_URL,
/** page_key 到路径的映射表(统一管理所有页面) */
PAGE_KEY_MAP,
/** 根据 page_key + params 解析实际URL */
resolvePageUrl,
/** 解析 link 对象得到最终可跳转的 URL(优先级: page_key → wap_url) */
resolveLinkUrl,
/**
* 页面跳转
* @param {string} to 跳转链接 /pages/idnex/index
@@ -686,6 +829,12 @@ export default {
link.wap_url = decodeEntity(link.wap_url);
}
// 优先用 page_key 解析实际URL(新机制,向后兼容)
const resolvedUrl = resolveLinkUrl(link);
if (link.page_key && resolvedUrl) {
link.wap_url = resolvedUrl;
}
// 外部链接
if (link.wap_url && link.wap_url.indexOf('http') != -1) {
// 公共参数

View File

@@ -1,6 +1,6 @@
<template>
<view :style="themeColor">
<view class="category-page-wrap category-template-1" style="height: calc(-56px + 100vh);">
<view class="category-page-wrap category-template-1" :style="categoryPageStyle">
<!-- <view class="search-box" @click="$util.redirectTo('/pages_tool/goods/search')">
<view class="search-content">
@@ -56,6 +56,11 @@
<ns-login ref="login"></ns-login>
<!-- <loading-cover ref="loadingCover"></loading-cover> -->
<!-- 底部tabBar -->
<view class="page-bottom">
<diy-bottom-nav></diy-bottom-nav>
</view>
</view>
</template>
@@ -85,9 +90,18 @@
]
},*/
],
user_type:uni.getStorageSync('user_type')
};
],
user_type:uni.getStorageSync('user_type')
};
},
computed: {
categoryPageStyle() {
const hasTabBar = this.tabBarList && this.tabBarList.list;
return this.$util.objToStyle({
height: 'calc(100vh - 56px)',
paddingBottom: hasTabBar ? '112rpx' : '0'
});
}
},
onLoad() {
uni.hideTabBar()