| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399 |
- <template>
- <view class="main-container">
- <!-- 主内容区域 - 使用 swiper 实现滑动切换 -->
- <swiper class="main-swiper" :current="currentIndex" @change="onSwiperChange" :circular="false" :duration="300">
- <!-- 动态渲染页面 -->
- <swiper-item v-for="(page, index) in pages" :key="index">
- <view class="page-container">
- <BjdmStatisticsPage v-if="page.key === 'mp_njdmHomep' && page.activated"
- v-show="currentIndex === index" :ref="(el) => setPageRef(el, index)" />
- <XcdmPage v-else-if="page.key === 'xcDm' && page.activated" v-show="currentIndex === index"
- :ref="(el) => setPageRef(el, index)" />
- <BzrdmPage v-else-if="page.key === 'bzrDm' && page.activated" v-show="currentIndex === index"
- :ref="(el) => setPageRef(el, index)" />
- <TodoPage v-else-if="page.key === 'todo' && page.activated" v-show="currentIndex === index"
- :ref="(el) => setPageRef(el, index)" />
- <MyPage v-else-if="page.key === 'my' && page.activated" v-show="currentIndex === index"
- :ref="(el) => setPageRef(el, index)" />
- </view>
- </swiper-item>
- </swiper>
- </view>
- </template>
- <script setup>
- import { ref, nextTick } from "vue";
- import { onShow, onHide, onLoad, onUnload } from "@dcloudio/uni-app";
- import Icon from "@/components/icon/index.vue";
- // 引入各个页面组件
- import MyPage from "@/pages/my/index.vue";
- import TodoPage from "@/pages/todo/todo_list.vue";
- import BjdmStatisticsPage from "@/pages/statistics/bjdm_statistics.vue";
- import BzrdmPage from "@/pages/bjdm/bjdm_bzrDmHomep.vue";
- import XcdmPage from "@/pages/xcdm/index.vue";
- // 当前选中的页面索引
- const currentIndex = ref(0);
- // 上一个页面索引
- const prevIndex = ref(0);
- // 页面组件引用数组
- const pageRefs = ref([]);
- // 页面配置(根据登录态与 syList 动态构建)
- const pages = ref([]);
- /**
- * 设置页面组件引用
- */
- const setPageRef = (el, index) => {
- if (el) {
- pageRefs.value[index] = el;
- }
- };
- /**
- * 触发子组件的生命周期
- */
- const triggerPageLifecycle = (pageIndex, lifecycle) => {
- const pageRef = pageRefs.value[pageIndex];
- if (pageRef && typeof pageRef[lifecycle] === "function") {
- // console.log(`[Main] 触发页面 ${pages.value[pageIndex]?.title} 的 ${lifecycle}`)
- pageRef[lifecycle]();
- } else {
- try {
- console.warn("[Main] 生命周期调用失败: 未找到方法", {
- pageIndex,
- lifecycle,
- hasRef: !!pageRef,
- refKeys: pageRef ? Object.keys(pageRef) : [],
- });
- } catch (e) { }
- }
- };
- // 在小程序环境中,组件渲染与 ref 赋值可能比 nextTick 更晚
- // 增加一个轻量重试机制,确保拿到子组件并调用其暴露的生命周期
- function ensureRefReady(pageIndex, lifecycle, tries = 0) {
- const pageRef = pageRefs.value[pageIndex];
- if (pageRef && typeof pageRef[lifecycle] === "function") {
- // console.log(`[Main] ensureRefReady 命中 -> 调用 ${pages.value[pageIndex]?.title}.${lifecycle}`)
- pageRef[lifecycle]();
- return;
- }
- if (tries >= 8) {
- console.warn("[Main] ensureRefReady 超过重试次数,放弃调用", {
- pageIndex,
- lifecycle,
- hasRef: !!pageRef,
- refKeys: pageRef ? Object.keys(pageRef) : [],
- });
- return;
- }
- setTimeout(() => ensureRefReady(pageIndex, lifecycle, tries + 1), 30);
- }
- /**
- * swiper 切换事件
- */
- const onSwiperChange = (e) => {
- const newIndex = e.detail.current;
- const oldIndex = currentIndex.value;
- // 触发前一个页面的 onHide
- if (oldIndex !== newIndex) {
- console.log(`[Main] 触发页面 ${oldIndex} 的 onHide`);
- triggerPageLifecycle(oldIndex, "onHide");
- }
- // 更新当前页面索引
- prevIndex.value = oldIndex;
- currentIndex.value = newIndex;
- // 懒加载激活
- activateByIndex(currentIndex.value);
- // 触发新页面的 onShow(可能需要等待 ref 就绪)
- nextTick(() => {
- console.log(`[Main] 触发页面 ${newIndex} 的 onShow`);
- ensureRefReady(currentIndex.value, "onShow");
- });
- console.log("切换到页面:", pages.value[currentIndex.value].title);
- };
- /**
- * 点击指示器切换页面
- */
- function switchToPage(index) {
- if (currentIndex.value !== index) {
- const oldIndex = currentIndex.value;
- // 触发前一个页面的 onHide
- // console.log(`[Main] switchToPage 触发页面 ${oldIndex} 的 onHide`)
- triggerPageLifecycle(oldIndex, "onHide");
- // 更新页面索引
- prevIndex.value = oldIndex;
- currentIndex.value = index;
- // 懒加载激活
- activateByIndex(currentIndex.value);
- // 触发新页面的 onShow(可能需要等待 ref 就绪)
- nextTick(() => {
- // console.log(`[Main] switchToPage 触发页面 ${index} 的 onShow`)
- ensureRefReady(currentIndex.value, "onShow");
- });
- }
- }
- /**
- * 激活页面
- */
- function activateByIndex(pageIndex) {
- const page = pages.value[pageIndex];
- if (!page) return;
- if (!page.activated) {
- // 标记为已激活,触发首次挂载
- page.activated = true;
- // 首次激活后,等组件挂载完成再触发子组件 onLoad(自定义)
- nextTick(() => {
- ensureRefReady(pageIndex, "onLoad");
- });
- }
- }
- /**
- * 是否已登录
- */
- function isLoggedIn() {
- try {
- const u = uni.getStorageSync("userInfo");
- if (!u) return false;
- const info = typeof u === "string" ? JSON.parse(u) : u;
- return !!info?.yhsbToken;
- } catch (e) {
- return false;
- }
- }
- /**
- * 获取 syList(数组)
- */
- function getSyList() {
- try {
- const u = uni.getStorageSync("userInfo");
- const info = typeof u === "string" ? JSON.parse(u) : u;
- const raw = info?.syList || info?.sylist || "[]";
- // return ['statistics','bzrDmHomep']
- if (Array.isArray(raw)) return raw;
- return JSON.parse(raw);
- } catch (e) {
- return [];
- }
- }
- /**
- * 按登录态构建一级页
- * - 未登录:仅“我的”
- * - 已登录:按 syList 渲染可见首页
- */
- function buildPagesFromAuth() {
- const list = [];
- const loggedIn = isLoggedIn();
- const sy = loggedIn ? getSyList() : [];
- // 能力 → 页面配置映射(按需扩展)
- const capabilityMap = {
- mp_xcdmHomep: {
- key: "xcDm",
- title: "校车点名",
- icon: "icon-dianming",
- path: "pages/xcdm/index",
- component: XcdmPage,
- },
- mp_njdmHomep: {
- key: "mp_njdmHomep",
- title: "点名统计",
- icon: "icon-tongji",
- path: "pages/statistics/bjdm_statistics",
- component: BjdmStatisticsPage,
- },
- mp_bzrdmHomep: {
- key: "bzrDm",
- title: "班主任点名",
- icon: "icon-dianming",
- path: "pages/bjdm/bjdm_bzrDm",
- component: BzrdmPage,
- },
- todo: {
- key: "todo",
- title: "待办",
- icon: "icon-daiban",
- path: "pages/todo/todo_list",
- component: TodoPage,
- },
- };
- if (loggedIn) {
- const added = new Set();
- // 仅当 syList 含 mp_xcdmHomep 时才展示“校车点名”
- if (sy.includes("mp_xcdmHomep")) {
- list.push({ ...capabilityMap.mp_xcdmHomep, activated: false });
- added.add(capabilityMap.mp_xcdmHomep.key);
- }
- sy.forEach((cap) => {
- const conf = capabilityMap[cap];
- if (conf && !added.has(conf.key)) {
- list.push({ ...conf, activated: false });
- added.add(conf.key);
- }
- });
- }
- // 末尾永远追加“我的”
- list.push({
- key: "my",
- title: "我的",
- icon: "icon-wode",
- path: "pages/my/index",
- component: MyPage,
- activated: false,
- });
- pages.value = list;
- console.log("✅ 获取权限列表成功:", list);
- }
- // 主容器的生命周期
- onLoad((options) => {
- // options.sn = "ssDevId_a";
- // options.cardNo = "E004015327BD68C5";
- // if (true) {
- if (typeof wmpf !== "undefined") {
- console.log("WMPF环境");
- const sn = options.sn || "";
- const cardNo = options.cardNo || "";
- if (sn && cardNo) {
- uni.reLaunch({
- url: `/pages/parent/message?role=device&sn=${sn}&cardNo=${cardNo}`,
- });
- return;
- }
- if (sn && !cardNo) {
- uni.reLaunch({
- url: `/pages/device/notice?sn=${sn}`,
- });
- return;
- }
- } else {
- console.log("非WMPF环境");
- // 先按登录态构建一级页
- buildPagesFromAuth();
- // 临时:主首页写死默认打开“校车点名”
- const xcdmIndex = pages.value.findIndex((p) => p.key === "xcDm");
- currentIndex.value = xcdmIndex >= 0 ? xcdmIndex : 0;
- // 激活当前页(首次时会触发 onLoad)
- activateByIndex(currentIndex.value);
- // 监听登录事件,登录后重建一级页
- uni.$on("login", () => {
- const currentKey = pages.value[currentIndex.value]?.key;
- buildPagesFromAuth();
- // 临时:登录后默认打开“校车点名”
- const idx = pages.value.findIndex((p) => p.key === "xcDm");
- currentIndex.value = idx >= 0 ? idx : 0;
- activateByIndex(currentIndex.value);
- nextTick(() => {
- ensureRefReady(currentIndex.value, "onShow");
- });
- });
- }
- });
- onShow(() => {
- // console.log('主容器页面显示')
- // 触发当前页面的 onShow(可能需要等待 ref 就绪)
- nextTick(() => {
- ensureRefReady(currentIndex.value, "onShow");
- });
- });
- onHide(() => {
- // console.log('主容器页面隐藏')
- // 触发当前页面的 onHide
- triggerPageLifecycle(currentIndex.value, "onHide");
- });
- onUnload(() => {
- // console.log('主容器页面卸载')
- // 触发所有页面的 onUnload
- pages.value.forEach((_, index) => {
- triggerPageLifecycle(index, "onUnload");
- });
- });
- </script>
- <style lang="scss" scoped>
- .main-container {
- width: 100%;
- height: 100vh;
- display: flex;
- flex-direction: column;
- }
- .top-indicator {
- height: 100rpx;
- background: #ffffff;
- border-bottom: 1rpx solid #e6e6e6;
- display: flex;
- align-items: center;
- justify-content: space-around;
- padding: 0 20rpx;
- box-sizing: border-box;
- flex-shrink: 0;
- }
- .indicator-item {
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- flex: 1;
- height: 100%;
- gap: 8rpx;
- text {
- font-size: 24rpx;
- transition: color 0.3s;
- }
- &.active {
- text {
- font-weight: bold;
- }
- }
- &:active {
- background-color: rgba(83, 156, 248, 0.1);
- }
- }
- .main-swiper {
- flex: 1;
- width: 100%;
- height: calc(100vh - 100rpx);
- }
- .page-container {
- width: 100%;
- height: 100%;
- overflow: hidden;
- }
- </style>
|