feat: tab的调整
This commit is contained in:
1 parent
9475a3cc3a
commit
f93b9f034f
8 files changed
+439
-300
No files matched your search
+89
-23
@@ -1,9 +1,65 @@
|
||||
/**
|
||||
* 导航工具:登录回跳、Tab 切换、返回兜底
|
||||
* 本项目未使用原生 tabBar(Tab 栏为自绘组件),因此 Tab 之间用 redirectTo 切换。
|
||||
* ---------------------------------------------------------------------------
|
||||
* 三个 Tab 不是三个页面,而是主包壳页 pages/home/index.vue 里的三块面板(views/*):
|
||||
* 同屏常驻、切 Tab 只切面板可见性 —— Tab 栏因此只渲染一次,切 Tab 不会闪烁、不重建、不重复请求。
|
||||
* 壳在 onMounted 时用 registerTabController({ go, getActive }) 把切换器交给本模块,
|
||||
* 页面内部(如「我的页 → 我的权益」)调的 switchTabTo 即转为调它,不再走路由。
|
||||
*
|
||||
* ⚠️ 面板不是页面,没有 query 可用 → Tab 间参数用内存透传(setTabQuery / consumeTabQuery)。
|
||||
* ⚠️ 壳未挂载时切 Tab(子页 / 登录页 / 冷启)→ 记 pendingTab 并 reLaunch 回壳,由壳 onMounted 消费。
|
||||
*/
|
||||
import { ROUTES, STORAGE_KEYS } from "@/constant";
|
||||
|
||||
/** 壳内面板 key */
|
||||
const TAB_KEYS = ["home", "benefit", "mine"];
|
||||
|
||||
/** 壳注册进来的 Tab 切换器 */
|
||||
let tabCtl = { go: null, getActive: () => "home" };
|
||||
|
||||
export const registerTabController = (ctl) => {
|
||||
tabCtl = {
|
||||
go: (ctl && ctl.go) || null,
|
||||
getActive: (ctl && ctl.getActive) || (() => "home"),
|
||||
};
|
||||
};
|
||||
|
||||
/** Tab 间透传的参数 */
|
||||
let tabQuery = "";
|
||||
/** 壳尚未就绪时的待切 Tab */
|
||||
let pendingTab = null;
|
||||
|
||||
export const setTabQuery = (query) => {
|
||||
tabQuery = query || "";
|
||||
};
|
||||
|
||||
/** 取出并清空透传参数(仅在目标面板 onPanelShow 调用一次) */
|
||||
export const consumeTabQuery = () => {
|
||||
const query = tabQuery;
|
||||
tabQuery = "";
|
||||
return query;
|
||||
};
|
||||
|
||||
/** 取出并清空待切 Tab(仅在壳 onMounted 调用一次) */
|
||||
export const consumePendingTab = () => {
|
||||
const pending = pendingTab;
|
||||
pendingTab = null;
|
||||
return pending;
|
||||
};
|
||||
|
||||
/** query 串取参数 */
|
||||
const pickParam = (query, key) => {
|
||||
const matched = (query || "").match(new RegExp(`(?:^|&)${key}=([^&]*)`));
|
||||
return matched ? matched[1] : "";
|
||||
};
|
||||
|
||||
/** query 串去掉某个参数 */
|
||||
const dropParam = (query, key) =>
|
||||
(query || "")
|
||||
.split("&")
|
||||
.filter((kv) => kv && !new RegExp(`^${key}=`).test(kv))
|
||||
.join("&");
|
||||
|
||||
/** 当前页面路径(含参数) */
|
||||
export const currentRoute = () => {
|
||||
const pages = getCurrentPages();
|
||||
@@ -18,6 +74,13 @@ export const currentRoute = () => {
|
||||
return `/${page.route}${query ? `?${query}` : ""}`;
|
||||
};
|
||||
|
||||
/** 壳页地址补上当前 Tab(否则登录后只能落回主页) */
|
||||
const withTab = (url) => {
|
||||
const [path, query = ""] = (url || "").split("?");
|
||||
if (path !== ROUTES.HOME || /(?:^|&)tab=/.test(query)) return url;
|
||||
return `${path}?tab=${tabCtl.getActive()}${query ? `&${query}` : ""}`;
|
||||
};
|
||||
|
||||
/** 是否已登录,未登录则跳登录页并带上 redirect */
|
||||
export const requireLogin = (silent = false) => {
|
||||
const token = uni.getStorageSync(STORAGE_KEYS.ACCESS_TOKEN) || "";
|
||||
@@ -31,28 +94,28 @@ export const requireLogin = (silent = false) => {
|
||||
|
||||
/** 跳登录页,redirect 为登录后的回跳地址 */
|
||||
export const goLogin = (redirect) => {
|
||||
const target = redirect || currentRoute();
|
||||
const target = withTab(redirect || currentRoute());
|
||||
const url = `${ROUTES.LOGIN}${target ? `?redirect=${encodeURIComponent(target)}` : ""}`;
|
||||
uni.navigateTo({ url });
|
||||
};
|
||||
|
||||
/** 登录成功后的回跳 */
|
||||
/** 登录成功后的回跳:目标是壳页 → 切回原 Tab(含原分段);其余页面走 redirectTo */
|
||||
export const goAfterLogin = (redirect) => {
|
||||
if (redirect) {
|
||||
const url = decodeURIComponent(redirect);
|
||||
const pages = getCurrentPages();
|
||||
const top = pages.length ? `/${pages[pages.length - 1].route}` : "";
|
||||
if (top && url.startsWith(top)) {
|
||||
uni.navigateBack();
|
||||
return;
|
||||
}
|
||||
uni.redirectTo({
|
||||
url,
|
||||
if (!redirect) {
|
||||
uni.navigateBack({
|
||||
fail: () => uni.reLaunch({ url: ROUTES.HOME }),
|
||||
});
|
||||
return;
|
||||
}
|
||||
uni.navigateBack({
|
||||
const url = decodeURIComponent(redirect);
|
||||
const [path, query = ""] = url.split("?");
|
||||
if (path === ROUTES.HOME) {
|
||||
const rest = dropParam(query, "tab");
|
||||
switchTabTo(pickParam(query, "tab") || tabCtl.getActive(), rest ? `?${rest}` : "");
|
||||
return;
|
||||
}
|
||||
uni.redirectTo({
|
||||
url,
|
||||
fail: () => uni.reLaunch({ url: ROUTES.HOME }),
|
||||
});
|
||||
};
|
||||
@@ -67,18 +130,21 @@ export const goBack = () => {
|
||||
}
|
||||
};
|
||||
|
||||
/** Tab 切换 */
|
||||
/**
|
||||
* 切 Tab:已在壳页 → 交由壳切面板(不重建、不重复请求);
|
||||
* 不在壳页(子页 / 登录页 / 冷启)→ 记待办并 reLaunch 回壳,由壳 onMounted 消费。
|
||||
* extraQuery 形如 "?seg=mine",由目标面板 onPanelShow 取用。
|
||||
*/
|
||||
export const switchTabTo = (key, extraQuery = "") => {
|
||||
const map = {
|
||||
home: ROUTES.HOME,
|
||||
benefit: ROUTES.BENEFIT,
|
||||
mine: ROUTES.MINE,
|
||||
};
|
||||
const url = `${map[key] || ROUTES.HOME}${extraQuery}`;
|
||||
if (!TAB_KEYS.includes(key)) return;
|
||||
const pages = getCurrentPages();
|
||||
const top = pages.length ? `/${pages[pages.length - 1].route}` : "";
|
||||
if (top === url.split("?")[0]) return;
|
||||
uni.redirectTo({ url });
|
||||
if (top === ROUTES.HOME && tabCtl.go) {
|
||||
tabCtl.go(key, extraQuery);
|
||||
return;
|
||||
}
|
||||
pendingTab = { key, query: extraQuery };
|
||||
uni.reLaunch({ url: ROUTES.HOME });
|
||||
};
|
||||
|
||||
/** 跳板块列表页 */
|
||||
|
||||
Reference in new issue
Block a user