hejianhao
2026-05-22 6c2dcecf8dbbb4f78f4e37f5df57de003cd008ba
feat(whitelist): 新增全局白名单校验及拦截页面

创建非白名单拦截页面及其配置与样式,注册拦截页路由至小程序配置,新增全局白名单校验工具函数,在App启动时执行白名单校验,未通过权限校验时自动跳转至拦截页;拦截页会自动重新校验权限,权限恢复后自动返回首页
4个文件已添加
2个文件已修改
199 ■■■■■ 已修改文件
src/app.config.ts 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/app.tsx 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/not-on-whitelist/index.config.ts 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/not-on-whitelist/index.less 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/not-on-whitelist/index.tsx 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/whitelist.ts 134 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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',
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')) {
src/pages/not-on-whitelist/index.config.ts
New file
@@ -0,0 +1,4 @@
export default {
  navigationStyle: 'custom',
  disableScroll: true,
};
src/pages/not-on-whitelist/index.less
New file
@@ -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;
}
src/pages/not-on-whitelist/index.tsx
New file
@@ -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>
  );
}
src/utils/whitelist.ts
New file
@@ -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;
}