hejianhao
2026-06-25 cbba37d087c73bd351ad6f1110464decbdb3ddc3
fix(robotaxi home): 修复拖拽手势异常及状态残留问题

- 新增触摸取消事件处理,完善拖拽手势监听
- 添加应用前后台切换时的状态重置逻辑,避免拖拽状态卡住
- 优化拖拽钩子的依赖项与透明度计算逻辑
3个文件已修改
81 ■■■■■ 已修改文件
src/pages/robotaxi/home/components/home-content-panel.tsx 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/robotaxi/home/hooks/use-drag-gesture.ts 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/robotaxi/home/index.tsx 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/robotaxi/home/components/home-content-panel.tsx
@@ -46,6 +46,8 @@
  onTouchMove: (event: any) => void;
  /** 触摸结束。 */
  onTouchEnd: () => void;
  /** 触摸取消。 */
  onTouchCancel: () => void;
};
/**
@@ -99,6 +101,10 @@
        event.stopPropagation();
        props.onTouchEnd();
      }}
      onTouchCancel={(event) => {
        event.stopPropagation();
        props.onTouchCancel();
      }}
    >
      <View className="content-body">
        <View className="select-site">
src/pages/robotaxi/home/hooks/use-drag-gesture.ts
@@ -9,6 +9,8 @@
  bannerList: any[];
  /** 行程状态 */
  tripStatus: HomeTripStatus;
  /** 是否展示订单状态卡片 */
  shouldShowOrderStatusCard: boolean;
};
/**
@@ -35,6 +37,37 @@
  const pendingHeight = useRef<number | null>(null);
  /**
   * 根据当前面板高度计算回中按钮透明度。
   */
  const resolveOriginOpacity = (height: number, min: number, full: number) => {
    const range = full - min;
    if (range <= 0 || !Number.isFinite(height)) {
      return 1;
    }
    const fadeDistance = 100;
    const moveDistance = height - min;
    const factor = moveDistance / fadeDistance;
    return 1 - Math.min(1, Math.max(0, factor));
  };
  /**
   * 统一重置拖拽态,避免触摸中断或前后台切换后停留在中间高度。
   */
  const resetDragState = (shouldRecalculateHeight = false) => {
    isDragging.current = false;
    if (dragFrame.current) {
      clearTimeout(dragFrame.current);
      dragFrame.current = null;
    }
    pendingHeight.current = null;
    setBoxHeight(minHeight.current || 280);
    setOriginOpacity(1);
    if (shouldRecalculateHeight) {
      calculateBoxHeight();
    }
  };
  /**
   * 计算拖拽容器高度边界。
   */
  const calculateBoxHeight = () => {
@@ -50,6 +83,10 @@
          // 仅在初始化或当前高度为旧的最大高度时更新高度,避免拖拽过程中被意外重置
          setBoxHeight(prev => {
            const nextHeight = (prev === 280 || prev === oldFullHeight || oldFullHeight === 0)
              ? baseHeight
              : prev;
            setOriginOpacity(resolveOriginOpacity(nextHeight, minHeight.current, fullHeight.current));
            if (prev === 280 || prev === oldFullHeight || oldFullHeight === 0) {
              return baseHeight;
            }
@@ -59,6 +96,7 @@
          minHeight.current = 280;
          fullHeight.current = 280;
          setBoxHeight(280);
          setOriginOpacity(1);
        }
      }).exec();
    }, 500);
@@ -121,19 +159,28 @@
  useEffect(() => {
    calculateBoxHeight();
  }, [deps.bannerList, deps.tripStatus]);
  }, [deps.bannerList, deps.tripStatus, deps.shouldShowOrderStatusCard]);
  useEffect(() => {
    const range = fullHeight.current - minHeight.current;
    if (range > 0 && typeof boxHeight === 'number') {
      // 更加积极的淡出策略:向上滑动 100px 即可完全淡出
      const fadeDistance = 100;
      const moveDistance = boxHeight - minHeight.current;
      const factor = moveDistance / fadeDistance;
      const next = 1 - Math.min(1, Math.max(0, factor));
      setOriginOpacity(next);
    if (typeof boxHeight === 'number') {
      setOriginOpacity(resolveOriginOpacity(boxHeight, minHeight.current, fullHeight.current));
    }
  }, [boxHeight]);
  useEffect(() => {
    const handleAppHide = () => {
      resetDragState(false);
    };
    const handleAppShow = () => {
      resetDragState(true);
    };
    Taro.onAppHide(handleAppHide);
    Taro.onAppShow(handleAppShow);
    return () => {
      Taro.offAppHide(handleAppHide);
      Taro.offAppShow(handleAppShow);
    };
  }, []);
  return {
    boxHeight,
@@ -142,6 +189,7 @@
    handleTouchStart,
    handleTouchMove,
    handleTouchEnd,
    calculateBoxHeight
    calculateBoxHeight,
    resetDragState
  };
}
src/pages/robotaxi/home/index.tsx
@@ -182,7 +182,11 @@
    handleTouchStart,
    handleTouchMove,
    handleTouchEnd
  } = useDragGesture({ bannerList, tripStatus });
  } = useDragGesture({
    bannerList,
    tripStatus,
    shouldShowOrderStatusCard
  });
  const {
    skipNextLocationCenterRef,
    lastSelectedCityCodeRef,
@@ -584,6 +588,7 @@
        onTouchStart={handleTouchStart}
        onTouchMove={handleTouchMove}
        onTouchEnd={handleTouchEnd}
        onTouchCancel={handleTouchEnd}
      />
      <HomeOverlayLayer
        isMaintain={isMaintain}