hejianhao
2026-04-21 b03f6ffa5c8ec670ea06a142de7ae4f0f6e5205b
feat(robotaxi): 增加路线过期校验并优化蓝牙解锁提示

- 新增 `routeStaleCheck` API 用于下单前校验路线是否过期,若过期则刷新路线并提示用户
- 优化蓝牙车门解锁流程,统一鉴权失败和解锁失败的提示文案,并增加解锁成功提示
- 调整取消叫车弹窗的等待时间文案表述
4个文件已修改
74 ■■■■■ 已修改文件
src/robotaxi/api/begin-route.ts 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/components/cancel-popup.tsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/hooks/use-bluetooth-car-control.ts 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/hooks/use-order-actions.ts 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/api/begin-route.ts
@@ -28,6 +28,14 @@
    }, true);
}
// 导航-下单前校验路况是否过期
export const routeStaleCheck = async () => {
    return request({
        url: _ROBOTAXI_HOST + '/itinerary/base/v1/mini-program/navigation/route-stale-check',
        method: 'POST'
    }, true);
}
// 保存订单
export const saveOrder = async (payload) => {
    return request({
src/robotaxi/pages/begin-route/components/cancel-popup.tsx
@@ -36,7 +36,7 @@
    // 不同取消阶段对应的文案配置
    const STATUS_MAP = {
        1: {
            title: `预计${waitMinutesValue}分钟内有车,确定取消吗?`,
            title: `${waitMinutesValue}分钟内预计有车,确定取消吗?`,
            tip: discountAmountValue > 0 ? `本单限时优惠${discountAmountValue}元,重新叫车可能等待更久` : '',
        },
        2: {
src/robotaxi/pages/begin-route/hooks/use-bluetooth-car-control.ts
@@ -11,6 +11,8 @@
};
type ConnectStatus = 0 | 1 | 2 | 3;
const RETRY_UNLOCK_MESSAGE = '请点击解锁按钮解锁车门'; // 鉴权失败/解锁失败统一提示文案
const UNLOCK_SUCCESS_MESSAGE = '车门已解锁,请上车'; // 解锁成功提示文案
/**
 * 解析车辆信息中的蓝牙 MAC。
@@ -42,6 +44,12 @@
  const [authSuccess, setAuthSuccess] = useState(false); // RtAuth 鉴权是否成功
  const [isAuthorizing, setIsAuthorizing] = useState(false); // 鉴权流程进行中
  const [authError, setAuthError] = useState<string>(''); // 鉴权流程错误信息
  const showUnlockToast = useCallback((title: string) => {
    Taro.showToast({
      title,
      icon: 'none'
    });
  }, []); // 统一展示蓝牙解锁结果提示
  const bluetoothMac = useMemo(() => resolveBluetoothMac(vehicleInfo), [vehicleInfo]); // 车辆蓝牙 MAC
@@ -74,15 +82,32 @@
          setAuthError('');
          setConnectStatus(3);
        } else {
          const message = result?.data?.errorDesc || result?.error || '蓝牙鉴权失败';
          setAuthSuccess(false);
          setAuthError(String(message));
          setAuthError(RETRY_UNLOCK_MESSAGE);
          showUnlockToast(RETRY_UNLOCK_MESSAGE);
        }
        setIsAuthorizing(false);
      },
      onRtNotification: (result: any) => {
        console.log('[蓝牙] 解锁通知:', result);
        if (result?.type === 'pollingUnlock') {
          if (result?.success) {
            setAuthError('');
            showUnlockToast(UNLOCK_SUCCESS_MESSAGE);
          } else {
            setAuthError(RETRY_UNLOCK_MESSAGE);
            showUnlockToast(RETRY_UNLOCK_MESSAGE);
          }
          return;
        }
        if (result?.type === 'error') {
          setAuthError(RETRY_UNLOCK_MESSAGE);
          showUnlockToast(RETRY_UNLOCK_MESSAGE);
        }
      }
    });
    return managerRef.current;
  }, []);
  }, [showUnlockToast]);
  /**
   * 主动断开蓝牙连接并重置状态。
src/robotaxi/pages/begin-route/hooks/use-order-actions.ts
@@ -1,6 +1,6 @@
import Taro from '@tarojs/taro';
import { formatDateTime, clearOrderTripStorage, debounce, reportEvent } from '../../../../utils/Robotaxi-public-method';
import { saveOrder, getOrderPayment, cancelOrder, endOrder } from '../../../api/begin-route';
import { saveOrder, getOrderPayment, cancelOrder, endOrder, routeStaleCheck } from '../../../api/begin-route';
import { checkOtp } from '../../../../utils/tools';
import { jumpTo } from '../../../../utils/jump';
import { TripStatus } from '../constants/trip-status';
@@ -60,6 +60,8 @@
 * 订单动作编排:下单、取消、结束、支付。
 */
export default function useOrderActions(deps: Deps) {
  const ROUTE_STALE_NOTICE_TEXT = '路况已变,价格已更新'; // 路况变化提示文案
  /**
   * 结束下单中状态。
   */
@@ -156,6 +158,33 @@
  };
  /**
   * 下单前校验路线是否过期,命中过期时刷新路线并终止本次下单。
   */
  const checkRouteStaleBeforeOrder = async (startSite: any) => {
    try {
      const staleCheckRes: any = await routeStaleCheck();
      const needRefreshNotice = staleCheckRes?.needRefreshNotice === true; // 服务端是否要求刷新路线
      if (!needRefreshNotice) {
        return true;
      }
      Taro.showToast({ title: ROUTE_STALE_NOTICE_TEXT, icon: 'none' });
      deps.routeRequestRouteAndFare(
        Number(startSite?.latitude),
        Number(startSite?.longitude),
        Number(deps.endSite?.latitude),
        Number(deps.endSite?.longitude),
        true
      );
      stopCallSubmitting();
      return false;
    } catch (error) {
      Taro.showToast({ title: '路线校验失败,请重试', icon: 'none' });
      stopCallSubmitting();
      return false;
    }
  };
  /**
   * 呼叫车辆。
   */
  const callImmediately = debounce(async () => {
@@ -169,6 +198,8 @@
    if (!s) return;
    const openCityId = await deps.checkDistanceAndCityReady(s);
    if (!openCityId) return;
    const routeStalePassed = await checkRouteStaleBeforeOrder(s);
    if (!routeStalePassed) return;
    try {
      const nextOrderId = await submitOrder(s, openCityId);
      if (!nextOrderId) {