From 6c2dcecf8dbbb4f78f4e37f5df57de003cd008ba Mon Sep 17 00:00:00 2001
From: hejianhao <15708179461@qq.com>
Date: 星期五, 22 五月 2026 17:16:31 +0800
Subject: [PATCH] feat(whitelist): 新增全局白名单校验及拦截页面
---
src/app.config.ts | 1
src/pages/not-on-whitelist/index.config.ts | 4 +
src/pages/not-on-whitelist/index.tsx | 29 +++++++
src/pages/not-on-whitelist/index.less | 12 +++
src/app.tsx | 19 ++++
src/utils/whitelist.ts | 134 +++++++++++++++++++++++++++++++++
6 files changed, 198 insertions(+), 1 deletions(-)
diff --git a/src/app.config.ts b/src/app.config.ts
index a8dd114..40e9dd6 100644
--- a/src/app.config.ts
+++ b/src/app.config.ts
@@ -7,6 +7,7 @@
if (process.env.TARO_ENV === 'weapp') {
pages = [
+ 'pages/not-on-whitelist/index',
// 'pages/home/index',
'pages/robotaxi/home/index',
'pages/xpeng/index',
diff --git a/src/app.tsx b/src/app.tsx
index 6105237..0c3b1bd 100644
--- a/src/app.tsx
+++ b/src/app.tsx
@@ -23,6 +23,7 @@
import { privicyShowManager } from './components/privacy-popup/utils';
import { initPrivacyPopupState } from './reducers/privacyPopup';
import { preloadLoginBgImageOnWx } from './utils/login-bg-utils';
+import { checkWhitelistAccess, redirectToWhitelistBlockPage } from './utils/whitelist';
const store = configStore();
const ENV = process.env.TARO_ENV;
@@ -93,7 +94,7 @@
this.xpReportSend({ pageId: 'P10107', buttonId: 'B001' });
}
- componentDidShow() {
+ async componentDidShow() {
wsManager.onAppShow();
if (ENV === 'weapp' && Taro.canIUse('onBeforePageUnload') && Taro.canIUse('offBeforePageUnload')) {
// @ts-ignore
@@ -106,6 +107,11 @@
this.scene = router.scene;
}
if (router.scene === 1154) {
+ return;
+ }
+
+ const whitelistAccessResult = await this.handleWhitelistGuard();
+ if (whitelistAccessResult === 'deny') {
return;
}
@@ -127,6 +133,17 @@
}
+ /**
+ * 执行全局白名单守卫。
+ */
+ handleWhitelistGuard = async () => {
+ const whitelistAccessResult = await checkWhitelistAccess();
+ if (whitelistAccessResult === 'deny') {
+ await redirectToWhitelistBlockPage();
+ }
+ return whitelistAccessResult;
+ }
+
componentDidHide() {
wsManager.onAppHide();
if (ENV === 'weapp' && Taro.canIUse('offBeforePageUnload')) {
diff --git a/src/pages/not-on-whitelist/index.config.ts b/src/pages/not-on-whitelist/index.config.ts
new file mode 100644
index 0000000..73327bb
--- /dev/null
+++ b/src/pages/not-on-whitelist/index.config.ts
@@ -0,0 +1,4 @@
+export default {
+ navigationStyle: 'custom',
+ disableScroll: true,
+};
diff --git a/src/pages/not-on-whitelist/index.less b/src/pages/not-on-whitelist/index.less
new file mode 100644
index 0000000..d798164
--- /dev/null
+++ b/src/pages/not-on-whitelist/index.less
@@ -0,0 +1,12 @@
+.not-on-whitelist-page {
+ width: 100vw;
+ height: 100vh;
+ overflow: hidden;
+ background: #ffffff;
+}
+
+.not-on-whitelist-image {
+ width: 100%;
+ height: 100%;
+ display: block;
+}
diff --git a/src/pages/not-on-whitelist/index.tsx b/src/pages/not-on-whitelist/index.tsx
new file mode 100644
index 0000000..5a10592
--- /dev/null
+++ b/src/pages/not-on-whitelist/index.tsx
@@ -0,0 +1,29 @@
+import Taro, { useDidShow } from '@tarojs/taro';
+import { Image, View } from '@tarojs/components';
+import { syncWhitelistBlockPageAccess } from '../../utils/whitelist';
+import './index.less';
+
+/** 白名单拦截图 CDN 地址。 */
+const NOT_ON_WHITELIST_IMAGE_URL = 'https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/not-on-whitelist.png';
+
+/**
+ * 非白名单拦截页。
+ */
+export default function NotOnWhitelist() {
+ useDidShow(() => {
+ if (typeof Taro.hideHomeButton === 'function') {
+ Taro.hideHomeButton();
+ }
+ void syncWhitelistBlockPageAccess();
+ });
+
+ return (
+ <View className="not-on-whitelist-page">
+ <Image
+ className="not-on-whitelist-image"
+ src={NOT_ON_WHITELIST_IMAGE_URL}
+ mode="aspectFill"
+ />
+ </View>
+ );
+}
diff --git a/src/utils/whitelist.ts b/src/utils/whitelist.ts
new file mode 100644
index 0000000..a337fef
--- /dev/null
+++ b/src/utils/whitelist.ts
@@ -0,0 +1,134 @@
+import Taro from '@tarojs/taro';
+import { isWhiteList } from '../robotaxi/api/home';
+import { checkOtp } from './tools';
+
+/** 白名单拦截页路由。 */
+export const WHITELIST_BLOCK_PAGE_URL = '/pages/not-on-whitelist/index';
+
+/** Robotaxi 首页路由。 */
+export const ROBOTAXI_HOME_PAGE_URL = '/pages/robotaxi/home/index';
+
+/** 白名单守卫结果。 */
+export type WhitelistAccessResult = 'pass' | 'guest' | 'deny' | 'skip';
+
+/** 白名单守卫豁免路由。 */
+const WHITELIST_EXEMPT_ROUTES = [
+ 'pages/not-on-whitelist/index',
+ 'pages/user/login',
+];
+
+/** 白名单请求并发锁。 */
+let whitelistCheckTask: Promise<WhitelistAccessResult> | null = null;
+
+/** 白名单拦截跳转锁。 */
+let isRedirectingToWhitelistBlockPage = false;
+
+/**
+ * 判断当前页面是否跳过白名单守卫。
+ */
+export function isWhitelistExemptPage(route: string) {
+ return WHITELIST_EXEMPT_ROUTES.includes(route);
+}
+
+/**
+ * 获取白名单拦截页地址。
+ */
+export function getWhitelistBlockPageUrl() {
+ return WHITELIST_BLOCK_PAGE_URL;
+}
+
+/**
+ * 获取 Robotaxi 首页地址。
+ */
+export function getRobotaxiHomePageUrl() {
+ return ROBOTAXI_HOME_PAGE_URL;
+}
+
+/**
+ * 获取当前页面路由。
+ */
+export function getCurrentRoute() {
+ const pages = Taro.getCurrentPages();
+ const currentPage = pages[pages.length - 1];
+ return currentPage?.route || '';
+}
+
+/**
+ * 校验当前访问是否允许进入 Robotaxi 业务页。
+ */
+export async function checkWhitelistAccess(options?: { ignoreRouteExempt?: boolean }): Promise<WhitelistAccessResult> {
+ const currentRoute = getCurrentRoute();
+ if (!options?.ignoreRouteExempt && isWhitelistExemptPage(currentRoute)) {
+ return 'skip';
+ }
+
+ if (whitelistCheckTask) {
+ return whitelistCheckTask;
+ }
+
+ whitelistCheckTask = (async () => {
+ const otp = await checkOtp(false);
+ if (!otp) {
+ return 'guest';
+ }
+
+ try {
+ const whitelistResult = await isWhiteList();
+ return whitelistResult ? 'pass' : 'deny';
+ } catch (error) {
+ console.error('白名单校验失败', error);
+ return 'pass';
+ }
+ })();
+
+ return whitelistCheckTask.finally(() => {
+ whitelistCheckTask = null;
+ });
+}
+
+/**
+ * 跳转到白名单拦截页。
+ */
+export async function redirectToWhitelistBlockPage() {
+ const currentRoute = getCurrentRoute();
+ if (isRedirectingToWhitelistBlockPage || currentRoute === WHITELIST_BLOCK_PAGE_URL.replace(/^\//, '')) {
+ return;
+ }
+
+ isRedirectingToWhitelistBlockPage = true;
+ try {
+ await Taro.reLaunch({
+ url: WHITELIST_BLOCK_PAGE_URL,
+ });
+ } finally {
+ setTimeout(() => {
+ isRedirectingToWhitelistBlockPage = false;
+ }, 300);
+ }
+}
+
+/**
+ * 跳回 Robotaxi 首页。
+ */
+export async function redirectToRobotaxiHomePage() {
+ const currentRoute = getCurrentRoute();
+ if (currentRoute === ROBOTAXI_HOME_PAGE_URL.replace(/^\//, '')) {
+ return;
+ }
+
+ await Taro.reLaunch({
+ url: ROBOTAXI_HOME_PAGE_URL,
+ });
+}
+
+/**
+ * 白名单拦截页自恢复:白名单命中后自动返回首页。
+ */
+export async function syncWhitelistBlockPageAccess() {
+ const whitelistAccessResult = await checkWhitelistAccess({ ignoreRouteExempt: true });
+ // 白名单页不允许未登录用户停留,游客态或白名单恢复后都回首页。
+ if (whitelistAccessResult === 'guest' || whitelistAccessResult === 'pass') {
+ await redirectToRobotaxiHomePage();
+ }
+ return whitelistAccessResult;
+}
--
Gitblit v1.7.1