hejianhao
2026-06-25 df6975470eb6395025ae56609d73eb05ed2e6566
feat(robotaxi): 更新车辆标记图标,优化行程页面交互与样式
10个文件已修改
355 ■■■■■ 已修改文件
src/pages/robotaxi/home/hooks/use-nearby-vehicles.ts 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/components/css-folder/modify-destination-review.less 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/components/modify-destination-review.tsx 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/components/pickup-exception-popup.tsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/hooks/use-map-markers.ts 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/index.tsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/share-trip/components/share-trip-view.tsx 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/share-trip/hooks/use-map-markers.ts 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/share-trip/index.less 294 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/share-trip/index.tsx 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/robotaxi/home/hooks/use-nearby-vehicles.ts
@@ -45,7 +45,7 @@
const MOVE_THRESHOLD_METERS = 500; // 触发新搜索的位移阈值(米)
const ANIMATION_DURATION_MS = 2000; // 车辆位移动画时长(毫秒)
const VEHICLE_LOCATION_EPSILON = 0.000001; // 车辆经纬度可见变化阈值
const VEHICLE_MARKER_ICON = 'https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/marker-car.png'; // 车辆 icon 地址
const VEHICLE_MARKER_ICON = 'https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/marker-car-v2.png'; // 车辆 icon 地址
/**
 * 归一化角度到 [0, 360) 区间。
src/robotaxi/pages/begin-route/components/css-folder/modify-destination-review.less
@@ -153,6 +153,15 @@
    color: rgba(0, 0, 0, 0.9);
  }
  &-fare-original {
    margin-left: 26px;
    font-size: 20px;
    font-weight: normal;
    line-height: 20px;
    letter-spacing: normal;
    color: rgba(0, 0, 0, 0.4);
  }
  &-tip-icon {
    width: 22px;
    height: 22px;
src/robotaxi/pages/begin-route/components/modify-destination-review.tsx
@@ -45,6 +45,11 @@
  return '修改次数获取失败';
};
/**
 * 置灰确认按钮提示文案。
 */
const MODIFY_DESTINATION_DISABLED_TOAST = '车辆临近终点,不支持修改目的地';
export default function ModifyDestinationReview({
  orderId = '',
  startSite,
@@ -73,6 +78,17 @@
  const isModifyCountDisabled = remainingModifyCount === MODIFY_DESTINATION_DISABLED_COUNT; // 后端明确返回无修改机会
  const isConfirmDisabled = isConfirmingModifyDestination || isLoadingModifyCount || !isModifyCountReady || isRouteDataIncomplete || isModifyCountDisabled; // 提交中、次数未就绪、路线未就绪或无次数时禁用确认
  const modifyDestinationTipText = getModifyDestinationTipText(remainingModifyCount, isLoadingModifyCount); // 修改次数展示文案
  const previousEstimatedFareText = previousFareEstimate?.finalFareStr || '-'; // 改终点前上一版预估价
  /**
   * 置灰态点击确认按钮时给出明确提示。
   */
  const handleDisabledConfirmToast = () => {
    Taro.showToast({
      title: MODIFY_DESTINATION_DISABLED_TOAST,
      icon: 'none'
    });
  };
  const isDragging = useRef(false);
  const startY = useRef(0);
@@ -296,11 +312,14 @@
                {isOperateFree ? (
                  <View className='modify-destination-review-operate-free'>载客测试免费</View>
                ) : (
                  <View className='modify-destination-review-fare-main' onClick={toPriceDescription}>
                    <Image className='modify-destination-review-tip-icon' src="https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/tip-default-icon.png" />
                    预估
                    <Text className='modify-destination-review-fare-num'>{fareEstimate?.finalFareStr || '-'}</Text>
                    元
                  <View>
                    <View className='modify-destination-review-fare-main' onClick={toPriceDescription}>
                      <Image className='modify-destination-review-tip-icon' src="https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/tip-default-icon.png" />
                      预估
                      <Text className='modify-destination-review-fare-num'>{fareEstimate?.finalFareStr || '-'}</Text>
                      元
                    </View>
                    <View className='modify-destination-review-fare-original'>原价格:{previousEstimatedFareText}元</View>
                  </View>
                )}
                {isOperateFree ? null : fareEstimate.discountAmount > 0 &&
@@ -313,7 +332,10 @@
                <View
                  className={`modify-destination-review-confirm${isConfirmDisabled ? ' modify-destination-review-confirm-disabled' : ''}`}
                  onClick={() => {
                    if (isConfirmDisabled) return;
                    if (isConfirmDisabled) {
                      handleDisabledConfirmToast();
                      return;
                    }
                    onConfirm();
                  }}
                >
@@ -327,7 +349,7 @@
                          ? '路线加载中...'
                          : '确认修改'}
                </View>
                {isConfirmDisabled && <View className='modify-destination-review-confirm-mask' />}
                {isConfirmDisabled && <View className='modify-destination-review-confirm-mask' onClick={handleDisabledConfirmToast} />}
              </View>
            </View>
          </View>
src/robotaxi/pages/begin-route/components/pickup-exception-popup.tsx
@@ -17,7 +17,7 @@
const LOCATION_REFRESH_INTERVAL_MS = 5000;
const MAP_INCLUDE_POINTS_PADDING = [32, 32, 120, 32];
const USER_MARKER_ICON_URL = 'https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/site-poi.png';
const VEHICLE_MARKER_ICON_URL = 'https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/marker-car.png';
const VEHICLE_MARKER_ICON_URL = 'https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/marker-car-v2.png';
type LocationPoint = {
  latitude: number;
src/robotaxi/pages/begin-route/hooks/use-map-markers.ts
@@ -197,7 +197,7 @@
      id: deps.vehicleMarkerId,
      latitude: deps.vehicleLocation.latitude,
      longitude: deps.vehicleLocation.longitude,
      iconPath: 'https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/marker-car.png',
      iconPath: 'https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/marker-car-v2.png',
      width: 20,
      height: 40,
      anchor: { x: 0.5, y: 0.5 },
src/robotaxi/pages/begin-route/index.tsx
@@ -946,7 +946,7 @@
      id: ROUTE_SUMMARY_MARKER_ID,
      latitude: summaryLocation.latitude,
      longitude: summaryLocation.longitude,
      iconPath: 'https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/marker-car.png',
      iconPath: 'https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/marker-car-v2.png',
      width: 1,
      height: 1,
      alpha: 0,
src/robotaxi/pages/share-trip/components/share-trip-view.tsx
@@ -82,10 +82,10 @@
      </Map>
      <View className='container'>
        <View
          className={`share-contact ${showReminder ? 'has-tip' : ''}`}
          className={`map-entry ${showReminder ? 'has-tip' : ''}`}
          onClick={handleContactService}
        >
          <Image className='share-contact-icon' src='https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/contact-service.png' />
          <Image className='map-entry-icon' src='https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/contact-service.png' />
        </View>
        <View className='container-inner'>
          <View catchMove onClick={(event) => event.stopPropagation()}>
src/robotaxi/pages/share-trip/hooks/use-map-markers.ts
@@ -174,7 +174,7 @@
            id: deps.vehicleMarkerId,
            latitude: deps.vehicleLocation.latitude,
            longitude: deps.vehicleLocation.longitude,
            iconPath: 'https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/marker-car.png',
            iconPath: 'https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/marker-car-v2.png',
            width: 20,
            height: 40,
            anchor: { x: 0.5, y: 0.5 },
src/robotaxi/pages/share-trip/index.less
@@ -87,30 +87,27 @@
  }
}
.share-contact {
  position: absolute;
  bottom: calc(100% + 16px);
.map-entry {
  position: fixed;
  top: 204px;
  right: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 72px;
  height: 72px;
  border-radius: 16px;
  background: #ffffff;
  box-shadow: 0px 4px 16px 0px rgba(84, 92, 143, 0.1);
  z-index: 11;
  transition: bottom 0.3s ease; /* 可选,平滑过渡效果 */
  background: rgba(255, 255, 255, 1);
  overflow: hidden;
  padding: 4px 4px;
  z-index: 300;
  &.has-tip {
    bottom: calc(100% + 16px);
    top: 204px;
  }
  .share-contact-icon {
    /* 自动布局子元素 */
  .map-entry-icon {
    width: 64px;
    height: 64px;
    z-index: 12;
  }
}
@@ -141,10 +138,12 @@
  font-size: 32px;
  font-weight: 500;
  color: rgba(0, 0, 0, 0.9);
  .calling-car-head-title {
    display: flex;
    align-items: center;
  }
  .calling-car-head-title-eta {
    font-size: 40px;
    font-weight: 500;
@@ -163,25 +162,26 @@
  border-radius: 40px 40px 0 0;
  padding: 14px 32px;
  box-sizing: border-box;
  background: linear-gradient(
    96deg,
    #71c5ff -10%,
    #87ceff -10%,
    #898afa 103%,
    #8283ff 103%
  );
  background: linear-gradient(96deg,
      #71c5ff -10%,
      #87ceff -10%,
      #898afa 103%,
      #8283ff 103%);
  z-index: 8;
  .tip-box-content {
    display: flex;
    align-items: center;
    justify-content: space-between;
  }
  .tip-box-text {
    font-size: 24px;
    line-height: 40px;
    height: 40px;
    color: #ffffff;
  }
  .tip-box-btn {
    width: 120px;
    height: 48px;
@@ -366,6 +366,7 @@
            &.start {
              background: #768aff;
            }
            &.end {
              background: #8bb654;
            }
@@ -388,6 +389,7 @@
        font-size: 24px;
        line-height: 40px;
        color: rgba(0, 0, 0, 0.9);
        &.disabled-text {
          color: rgba(0, 0, 0, 0.4);
        }
@@ -397,187 +399,187 @@
}
.custom-callout {
    position: relative;
    z-index: 999;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-direction: column;
    overflow: visible;
  position: relative;
  z-index: 999;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  overflow: visible;
}
.pd-6-10 {
    padding: 8px 20px !important;
  padding: 8px 20px !important;
}
.waiting-callout-content {
    z-index: 2;
    position: absolute;
    top: 240px;
    left: 50%;
    transform: translateX(-50%);
  z-index: 2;
  position: absolute;
  top: 240px;
  left: 50%;
  transform: translateX(-50%);
}
.custom-callout-content {
    display: flex;
    align-items: center;
    white-space: nowrap;
    border-radius: 16px;
    background: rgba(255, 255, 255, 1);
    font-size: 24px;
    font-weight: 400;
    color: rgba(0, 0, 0, 0.9);
    line-height: 38px;
    box-shadow: 0px 4px 16px 0px rgba(45, 48, 64, 0.2);
    padding: 8px 20px;
  display: flex;
  align-items: center;
  white-space: nowrap;
  border-radius: 16px;
  background: rgba(255, 255, 255, 1);
  font-size: 24px;
  font-weight: 400;
  color: rgba(0, 0, 0, 0.9);
  line-height: 38px;
  box-shadow: 0px 4px 16px 0px rgba(45, 48, 64, 0.2);
  padding: 8px 20px;
}
.route-summary-callout {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 188px;
    height: 54px;
    padding-left: 20px;
    padding-right: 20px;
    box-sizing: border-box;
    border-radius: 27px;
    background: #ffffff;
    border: 2px solid rgba(109, 127, 217, 0.18);
    box-shadow: 0px 6px 18px 0px rgba(45, 48, 64, 0.12);
    overflow: visible;
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 188px;
  height: 54px;
  padding-left: 20px;
  padding-right: 20px;
  box-sizing: border-box;
  border-radius: 27px;
  background: #ffffff;
  border: 2px solid rgba(109, 127, 217, 0.18);
  box-shadow: 0px 6px 18px 0px rgba(45, 48, 64, 0.12);
  overflow: visible;
}
.route-summary-callout-text {
    position: relative;
    z-index: 2;
    font-size: 24px;
    font-weight: 500;
    line-height: 38px;
    color: rgba(0, 0, 0, 0.9);
    white-space: nowrap;
    text-align: center;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
  position: relative;
  z-index: 2;
  font-size: 24px;
  font-weight: 500;
  line-height: 38px;
  color: rgba(0, 0, 0, 0.9);
  white-space: nowrap;
  text-align: center;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
}
.txt-center {
    text-align: center;
  text-align: center;
}
.car-time {
    font-size: 24px;
    letter-spacing: normal;
    display: flex;
    align-items: center;
    justify-content: center;
  font-size: 24px;
  letter-spacing: normal;
  display: flex;
  align-items: center;
  justify-content: center;
}
.car-time-num {
    font-size: 36px;
    letter-spacing: normal;
    color: #6D7FD9;
    margin-bottom: 4px;
  font-size: 36px;
  letter-spacing: normal;
  color: #6D7FD9;
  margin-bottom: 4px;
}
.custom-callout-icon {
    width: 32px;
    height: 32px;
    flex-shrink: 0;
    display: block;
  width: 32px;
  height: 32px;
  flex-shrink: 0;
  display: block;
}
.car-callout-android {
    z-index: 9;
    pointer-events: none;
    will-change: transform;
    backface-visibility: hidden;
    transition: transform 0.18s linear;
  z-index: 9;
  pointer-events: none;
  will-change: transform;
  backface-visibility: hidden;
  transition: transform 0.18s linear;
}
.waiting-callout {
    position: relative;
    z-index: 999;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    justify-content: flex-start;
    overflow: visible; // 确保辐射动画不被裁剪
    min-width: 700px;
    height: 600px;
  position: relative;
  z-index: 999;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: flex-start;
  overflow: visible; // 确保辐射动画不被裁剪
  min-width: 700px;
  height: 600px;
}
.waiting-radar {
    position: absolute;
    bottom: 50px;
    left: 0;
    width: 100%;
    height: 350px;
    pointer-events: none;
    z-index: 1;
  position: absolute;
  bottom: 50px;
  left: 0;
  width: 100%;
  height: 350px;
  pointer-events: none;
  z-index: 1;
}
.waiting-radar-img {
    position: fixed;
    width: 700px;
    height: 350px;
    top: 48%;
    left: 50%;
    transform: translate(-50%, -48%);
  position: fixed;
  width: 700px;
  height: 350px;
  top: 48%;
  left: 50%;
  transform: translate(-50%, -48%);
}
.waiting-callout-bg {
    position: relative;
    height: 70px;
    min-width: 155px;
    text-align: center;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    width: fit-content;
  position: relative;
  height: 70px;
  min-width: 155px;
  text-align: center;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  width: fit-content;
}
.waiting-callout-bg-img {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: 1;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 1;
}
.waiting-callout-bg-text {
    position: relative;
    z-index: 100;
    font-size: 22px;
    font-weight: 400;
    letter-spacing: normal;
    color: #FFFFFF;
    line-height: 48px;
    padding: 0 20px;
    box-sizing: border-box;
    white-space: nowrap;
  position: relative;
  z-index: 100;
  font-size: 22px;
  font-weight: 400;
  letter-spacing: normal;
  color: #FFFFFF;
  line-height: 48px;
  padding: 0 20px;
  box-sizing: border-box;
  white-space: nowrap;
}
.waiting-callout-txt {
    z-index: 200;
    border-radius: 16px;
    color: rgba(0, 0, 0, 0.9);
    font-size: 24px;
    font-weight: 400;
    background: rgba(255, 255, 255, 1);
    padding: 8px 20px;
    line-height: 48px;
    display: flex;
  z-index: 200;
  border-radius: 16px;
  color: rgba(0, 0, 0, 0.9);
  font-size: 24px;
  font-weight: 400;
  background: rgba(255, 255, 255, 1);
  padding: 8px 20px;
  line-height: 48px;
  display: flex;
}
.pr-6 {
    padding-right: 6px;
  padding-right: 6px;
}
.pr-0 {
    padding-right: 0;
}
  padding-right: 0;
}
src/robotaxi/pages/share-trip/index.tsx
@@ -238,7 +238,7 @@
      id: ROUTE_SUMMARY_MARKER_ID,
      latitude: midpoint.latitude,
      longitude: midpoint.longitude,
      iconPath: 'https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/marker-car.png',
      iconPath: 'https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/marker-car-v2.png',
      width: 1,
      height: 1,
      alpha: 0,