Files
longli-mp/src/pages/index/index.vue
T

97 lines
3.3 KiB
Vue
Raw 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.
<script setup>
/**
* 主包壳页面:主页 / 权益 / 我的 三块面板同屏共存,底部 Tab 栏只渲染一次
* ---------------------------------------------------------------------------
* 扫码入口:二维码指向本页并带商家 id(`merchant_id` / `scene` / `q` 三种来源都认),
* 进来自动切到权益 Tab 再打开商家详情 —— 取值见 utils/nav.js 的 pickMerchantId / handleEntry。
*/
import { nextTick, onMounted, ref } from "vue";
import { onLoad, onShow } from "@dcloudio/uni-app";
import { TABS } from "@/constant";
import {
consumePendingMerchant,
consumePendingTab,
goDetail,
pickMerchantId,
registerTabController,
setPendingMerchant,
setTabQuery,
} from "@/utils/nav";
import HomePanel from "@/views/home/index.vue";
import BenefitPanel from "@/views/benefit/index.vue";
import MinePanel from "@/views/mine/index.vue";
const active = ref("home");
const homeRef = ref(null);
const benefitRef = ref(null);
const mineRef = ref(null);
const panelRefs = { home: homeRef, benefit: benefitRef, mine: mineRef };
/** 面板按需刷新(切到它、或页面 onShow 时) */
const showPanel = (key) => panelRefs[key]?.value?.onPanelShow?.();
/**
* 切 Tab 的唯一入口:Tab 栏点击、页面内 switchTabTo(key, query)、登录回跳都汇到这里。
* query 用 nav 的内存透传(如 `?seg=mine`),由目标面板 onPanelShow 消费。
*/
const goTab = (key, query = "") => {
if (!TABS.some((t) => t.key === key)) return;
setTabQuery(query);
active.value = key;
showPanel(key);
};
/** Tab 控制器是否已就绪(onShow 可能早于 onMounted,未就绪时不消费扫码参数) */
let shellReady = false;
/**
* 扫码进店:先切权益 Tab 再打开商家详情。
* 顺序不能反 —— 先切 Tab,「详情返回」才会落在权益页而不是主页。
*/
const runEntry = () => {
if (!shellReady) return;
const id = consumePendingMerchant();
if (!id) return;
goTab("benefit");
nextTick(() => setTimeout(() => goDetail(id), 0));
};
onLoad((options) => {
setPendingMerchant(pickMerchantId(options));
});
onMounted(() => {
// 面板的 onMounted 早于本页 onMounted,此时 ref 已就绪
registerTabController({ go: goTab, getActive: () => active.value });
// 从子页 / 登录页切过来:nav 里可能压着待切 Tab(登录回跳、reLaunch 冷启)
const pending = consumePendingTab();
goTab(pending?.key || active.value, pending?.query || "");
shellReady = true;
runEntry();
});
onShow(() => {
// 从板块列表 / 详情 / 登录页等返回:让当前面板按需刷新(各家内部有幂等守卫)
showPanel(active.value);
runEntry();
});
</script>
<template>
<view class="relative h-screen w-full overflow-hidden">
<!-- 三块面板叠放同屏,靠 visibility 切换:见 script 头部的说明 -->
<view :class="['absolute inset-0', active === 'home' ? 'visible' : 'invisible']">
<HomePanel ref="homeRef" />
</view>
<view :class="['absolute inset-0', active === 'benefit' ? 'visible' : 'invisible']">
<BenefitPanel ref="benefitRef" />
</view>
<view :class="['absolute inset-0', active === 'mine' ? 'visible' : 'invisible']">
<MinePanel ref="mineRef" />
</view>
<AppTabBar :active="active" @change="goTab" />
</view>
</template>