zjk
2026-07-29 429208957f30ab9eedc5533a81aaa284048d09f5
src/robotaxi/pages/select-map-site/components/select-map-site-view.tsx
@@ -2,6 +2,7 @@
import CustomerServicePopup from '../../../components/customer-service';
import TipPopup from '../../../components/tip-popup';
import { formatTripDistance, formatTripDurationFromSeconds } from '../../../../utils/Robotaxi-public-method';
import { SELECT_SITE_RANGE_STATUS, type SelectSiteRangeStatus } from '../hooks/use-select-map-site-state';
type Deps = {
  longitude: number | null;
@@ -27,7 +28,7 @@
  selectionMode: 'point' | 'station';
  selectedStation: any;
  stationSiteList: any[];
  outOfServiceRange: boolean;
  rangeStatus: SelectSiteRangeStatus;
  tooltipBgSrc: string;
  pageType: string;
  bounce: boolean;
@@ -42,22 +43,36 @@
  activeStar: string;
  noStar: string;
  confirmSite: () => void;
  confirmButtonText: string;
  confirmButtonDisabled: boolean;
  crossOperatingAreaHintText: string;
  showViewOperatingAreaButton: boolean;
  handleViewOperatingArea: () => void;
  showCustomerService: boolean;
  handleCloseCustomerService: () => void;
  showTipPopup: boolean;
  handleCloseTipPopup: () => void;
  tipType: string;
  toPersonalCenter: () => void;
  toSiteSearch: () => void;
  hideSearchBox?: boolean;
};
/**
 * 选点页视图组件:仅负责渲染地图与页面 UI,不包含业务状态编排。
 */
export default function SelectMapSiteView(deps: Deps) {
  const isOutOfOperatingArea = deps.rangeStatus === SELECT_SITE_RANGE_STATUS.outOfOperatingArea;
  const isCrossOperatingArea = deps.rangeStatus === SELECT_SITE_RANGE_STATUS.crossOperatingArea;
  const showRangeWarning = isOutOfOperatingArea || isCrossOperatingArea;
  const shouldShowSelectedSiteEcho = !showRangeWarning && Boolean(deps.selectedSite.name);
  const shouldShowStationSelection = deps.selectionMode === 'station' && !showRangeWarning;
  const garyToolTipBg = 'https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/v2/tooltip-bg-gray-20260714.png';
  return (
    <View className="home-container">
      <Map
        id="map"
        id="select-site-map"
        longitude={deps.longitude}
        latitude={deps.latitude}
        scale={deps.mapScale}
@@ -73,14 +88,16 @@
        <View onClick={deps.toBack} className="select-city">
          <Image className="select-city-icon" src={deps.backIcon} />
        </View>
        {/* 地图浮层入口 */}
        <View className="map-entry">
          <Image onClick={deps.toPersonalCenter} className="map-entry-icon" src={deps.personalCenter} />
          <View className="split-line"></View>
          <Image onClick={deps.openService} className="map-entry-icon" src={deps.contactService} />
          <View className="split-line"></View>
          <Image onClick={deps.toCoupon} className="map-entry-icon" src={deps.coupon} />
        </View>
        {/* 搜索框 */}
        {!deps.hideSearchBox && (
          <View onClick={deps.toSiteSearch} className="search-card">
            <View className={`search-icon ${deps.pageType == 'end' ? 'end-icon' : ''}`}></View>
            <View className="search-input-box">
              <View className="search-input-placeholder">{deps.pageType == 'start' ? '请输入上车点' : '请输入目的地'}</View>
            </View>
          </View>
        )}
        {/* 地图浮层入口 - 选点页不展示 */}
        {deps.nearbyLoading && deps.isAndroid && (
          <Image className="waiting-radar-img" src={deps.waitingRadarSrc} />
        )}
@@ -89,27 +106,33 @@
          {deps.nearbyLoading && !deps.isAndroid && (
            <Image className="waiting-radar" src={deps.waitingRadarSrc} />
          )}
          {((deps.showToolTip && deps.selectedSite.name) || deps.outOfServiceRange) && (
          {((deps.showToolTip && shouldShowSelectedSiteEcho) || showRangeWarning) && (
            <View className="toolTip">
              {(deps.outOfServiceRange || deps.selectedSite.time) && (
              {(showRangeWarning || deps.selectedSite.time) && (
                <View className="toolTip-bg">
                  <Image className="toolTip-bg-img" src={deps.tooltipBgSrc} />
                  <Image className="toolTip-bg-img" src={(isOutOfOperatingArea || isCrossOperatingArea) ? garyToolTipBg : deps.tooltipBgSrc } />
                  {!showRangeWarning && (
                    <Image className="toolTip-bg-icon" src="https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/v2/map-time-icon-20260708.png" />
                  )}
                  <Text className="toolTip-bg-text">
                    {deps.outOfServiceRange ? '不在运营区' : `限停${deps.selectedSite.time}分钟`}
                    {isOutOfOperatingArea ? '不在运营区' : isCrossOperatingArea ? '不在同一运营区' : `限停${deps.selectedSite.time}分钟`}
                  </Text>
                </View>
              )}
              <View className="toolTip-txt">
                <View className="toolTip-txt-content">
                  {deps.outOfServiceRange ? `请拖动至${deps.pageType == 'end' ? '目的地' : '上车点'}` : deps.selectedSite.name}
                  {isOutOfOperatingArea
                    ? `请拖动至${deps.pageType == 'end' ? '目的地' : '上车点'}`
                    : isCrossOperatingArea
                      ? '请在同一运营区内选择'
                      : deps.selectedSite.name}
                </View>
                <Image className="toolTip-diamond-icon" src="https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/v2/diamond-icon-20260708.png" />
              </View>
            </View>
          )}
          <Image
            className={`pointer-icon ${deps.bounce ? 'bounce' : ''}`}
            src={deps.pointer}
          />
          {/* 黑色站点名浮窗(toolTip)显示时隐藏中心大头针 */}
          <Image className={`pointer-icon ${deps.bounce ? 'bounce' : ''} ${(deps.showToolTip && shouldShowSelectedSiteEcho) || showRangeWarning ? 'hidden-pointer' : ''}`}  src={deps.pointer} />
        </View>
        <View className="container">
          <View className="container-inner">
@@ -117,62 +140,71 @@
            <View className="origin-box">
              <Image onClick={deps.toOrigin} className="origin-icon" src={deps.originIcon} />
            </View>
            <View catchMove onClick={(e) => e.stopPropagation()}>
            <View className="content-box-wrap" catchMove onClick={(e) => e.stopPropagation()}>
              {deps.showViewOperatingAreaButton && (
                <View onClick={deps.handleViewOperatingArea} className="select-operating-area-entry">
                  查看运营区域
                </View>
              )}
              {/* 确认站点 */}
              <View className="content-box">
                <View className="content-box-item">
                  <View className='content-box-item-title'>
                    <View className="content-title">{deps.selectionMode === 'station' ? deps.selectedStation?.name : (deps.pageType === 'start' ? '确认上车站点' : '确认目的地')}</View>
                    {deps.pageType === 'start' && deps.walkingDuration !== null && deps.walkingDistance !== null && (
                      <View className="limit-tip">
                        从当前位置出发步行{formatTripDurationFromSeconds(deps.walkingDuration)}({formatTripDistance(deps.walkingDistance)})上车
                      </View>
                    )}
                    {(deps.nearbySites.length > 0 && deps.pageType === 'end') && (
                      <View className="limit-tip">点击紫色原点或拖动大头针,可修改{deps.pageType === 'start' ? '上车点' : '目的地'}</View>
                    )}
                  </View>
                  {deps.selectionMode === 'station' && (
                    <Image
                      onClick={deps.handleCollect}
                      className='collect-icon'
                      src={deps.selectedStation?.isCollect ? deps.activeStar : deps.noStar}
                    />
                  )}
                </View>
                <View className='site-list-wrap'>
                  <ScrollView
                    className="site-list"
                    scrollY
                    enhanced
                    showScrollbar={true}
                  >
                    <View className='site-list-inner'>
                      {deps.selectionMode === 'station' ? (
                        deps.stationSiteList.length > 0 ? deps.stationSiteList.map((item) => (
                          <View
                            key={item.id || item.pointId || `${item.latitude}_${item.longitude}`}
                            className={`site-item ${String(item.id || item.pointId || '') === String(deps.selectedSite?.id || deps.selectedSite?.pointId || '') ? 'site-active' : ''}`}
                            onClick={() => deps.changeStationSite(item)}
                          >
                            <View>{item.name}</View>
                          </View>
                        )) : <View className="no-service">当前场站暂无可选站点</View>
                      ) : deps.selectedSite.name ? (
                        <View className='site-item site-active'>
                          <View>{deps.selectedSite.name}</View>
                          {deps.selectionMode === 'point' && (
                            <Image onClick={deps.handleCollect} className='collect-icon' src={deps.selectedSite.isCollect === 1 ? deps.activeStar : deps.noStar} />
                          )}
                <Image className="content-box-top-bg" src='https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/v2/top-card-bg-20260722.png' />
                <View className="content-box-coantainer">
                  <View className="content-box-item">
                    <View className='content-box-item-title'>
                      <View className="content-title">{shouldShowStationSelection ? deps.selectedStation?.name : (deps.pageType === 'start' ? '确认上车点' : '确认目的地')}</View>
                      {deps.pageType === 'start' && deps.walkingDuration !== null && deps.walkingDistance !== null && (
                        <View className="limit-tip">
                          从当前位置出发步行{formatTripDurationFromSeconds(deps.walkingDuration)}({formatTripDistance(deps.walkingDistance)})上车
                        </View>
                      ) : (
                        <View className="no-service">超出服务范围,请在运营区内选择</View>
                      )}
                      {(deps.nearbySites.length > 0 && deps.pageType === 'end') && (
                        <View className="limit-tip">点击金色圆点或拖动大头针,可修改目的地</View>
                      )}
                    </View>
                  </ScrollView>
                </View>
                <View onClick={deps.confirmSite} className={`site-confirm ${deps.selectedSite.name ? '' : 'no-confirm'}`}>
                  {deps.pageType === 'start' ? '确认上车站点' : '确认目的地站点'}
                    {shouldShowStationSelection && (
                      <Image
                        onClick={deps.handleCollect}
                        className='collect-icon'
                        src={deps.selectedStation?.isCollect ? deps.activeStar : deps.noStar}
                      />
                    )}
                  </View>
                  <View className='site-list-wrap'>
                    <ScrollView
                      className="site-list"
                      scrollY
                      enhanced
                      showScrollbar={true}
                    >
                      <View className='site-list-inner'>
                        {shouldShowStationSelection ? (
                          deps.stationSiteList.length > 0 ? deps.stationSiteList.map((item) => (
                            <View
                              key={item.id || item.pointId || `${item.latitude}_${item.longitude}`}
                              className={`site-item ${String(item.id || item.pointId || '') === String(deps.selectedSite?.id || deps.selectedSite?.pointId || '') ? 'site-active' : ''}`}
                              onClick={() => deps.changeStationSite(item)}
                            >
                              <View>{item.name}</View>
                            </View>
                          )) : <View className="no-service">当前场站暂无可选站点</View>
                        ) : shouldShowSelectedSiteEcho ? (
                          <View className='site-item site-active'>
                            <View>{deps.selectedSite.name}</View>
                            {deps.selectionMode === 'point' && (
                              <Image onClick={deps.handleCollect} className='collect-icon' src={deps.selectedSite.isCollect === 1 ? deps.activeStar : deps.noStar} />
                            )}
                          </View>
                        ) : showRangeWarning ? (
                          <View className="no-service">{isCrossOperatingArea ? deps.crossOperatingAreaHintText : '超出服务范围,请在运营区内选择'}</View>
                        ) : <View className="no-service">附近无可选站点</View>
                        }
                      </View>
                    </ScrollView>
                  </View>
                  <View onClick={deps.confirmButtonDisabled ? undefined : deps.confirmSite} className={`site-confirm ${deps.confirmButtonDisabled ? 'no-confirm' : ''}`}>
                    {deps.confirmButtonText}
                  </View>
                </View>
              </View>
            </View>