fix:移除取消动效占位图,修复安卓地图气泡闪烁问题,修复安卓等待接单时候需触摸地图才更新的问题,修改地图气泡距离站点太远的问题
| | |
| | | } |
| | | |
| | | // 占位动画图片地址:优先加载 webp,加载失败回退 png |
| | | const CANCEL_ANIMATION_WEBP = 'https://xps01.xiaopeng.com/content/commomother/2026/07-09/14-45-520155-955631373.png?x-oss-process=image/format,webp'; |
| | | const CANCEL_ANIMATION_PNG = 'https://xps01.xiaopeng.com/content/commomother/2026/07-09/14-45-520155-955631373.png'; |
| | | // const CANCEL_ANIMATION_WEBP = 'https://xps01.xiaopeng.com/content/commomother/2026/07-09/14-45-520155-955631373.png?x-oss-process=image/format,webp'; |
| | | // const CANCEL_ANIMATION_PNG = 'https://xps01.xiaopeng.com/content/commomother/2026/07-09/14-45-520155-955631373.png'; |
| | | |
| | | export default function CancelPopup({ show = false, cancelType = 1, startSite, endSite, waitMinutes, tripStatus, routeDurationSeconds, discountAmount, onClose, onConfirm }: Props) { |
| | | const { visible, animationData } = useBottomPopupAnimation(show); |
| | | // 占位动画当前使用的图片地址,默认 webp,加载失败时回退到 png |
| | | const [animationSrc, setAnimationSrc] = useState(CANCEL_ANIMATION_WEBP); |
| | | // const [animationSrc, setAnimationSrc] = useState(CANCEL_ANIMATION_WEBP); |
| | | |
| | | // webp 加载失败时回退到 png |
| | | const handleAnimationError = () => { |
| | | if (animationSrc !== CANCEL_ANIMATION_PNG) { |
| | | setAnimationSrc(CANCEL_ANIMATION_PNG); |
| | | } |
| | | }; |
| | | // // webp 加载失败时回退到 png |
| | | // const handleAnimationError = () => { |
| | | // if (animationSrc !== CANCEL_ANIMATION_PNG) { |
| | | // setAnimationSrc(CANCEL_ANIMATION_PNG); |
| | | // } |
| | | // }; |
| | | const cachedStartSite = startSite || Taro.getStorageSync('startSite') || {}; |
| | | const cachedEndSite = endSite || Taro.getStorageSync('endSite') || {}; |
| | | const startSiteName = cachedStartSite?.name || cachedStartSite?.address || '-'; |
| | |
| | | : |
| | | <> |
| | | {/* 占位动画:优先 webp,加载失败回退 png */} |
| | | <Image className='cancel-animation' src={animationSrc} onError={handleAnimationError} /> |
| | | {/* <Image className='cancel-animation' src={animationSrc} onError={handleAnimationError} /> */} |
| | | <View className='default-empty' /> |
| | | <View className='cancel-btn-box'> |
| | | <View className=' cancel-btn-cancel' onClick={onConfirm}>确认取消</View> |
| | | <View className='cancel-btn-again wait-btn' onClick={onClose}>再等等</View> |
| | |
| | | border-radius: 60px 60px 0 0; |
| | | overflow: hidden; |
| | | &.calling-status-car { |
| | | padding-top: 84px; |
| | | padding-top: 94px; |
| | | } |
| | | .calling-car-content-box { |
| | | position: relative; |
| | |
| | | right: 0; |
| | | border-radius: 60px 60px 0px 0px; |
| | | background: #F1F5FA; |
| | | padding: 48px 48px 80px 48px; |
| | | padding: 66px 48px 80px 48px; |
| | | |
| | | .cancel-box { |
| | | position: absolute; |
| | |
| | | height: 262px; |
| | | margin-top: 48px; |
| | | } |
| | | |
| | | .default-empty { |
| | | height: 142px; |
| | | } |
| | | .cancel-btn-box { |
| | | display: flex; |
| | | margin-top: 48px; |
| | |
| | | // 三角态浮窗为富内容(图片/限停),必须走 cover-view customCallout,不能用原生 callout(原生仅支持纯文本)。 |
| | | const usePickupRichCallout = isPickupTriangle && !shouldHidePickupName; |
| | | const usePickupNativeCallout = useAndroidNativeTrip1Callout && !usePickupRichCallout; |
| | | |
| | | const getCustomCalloutAnchorY = () => { |
| | | if ([TripStatus.Publishing, TripStatus.CallingCar].includes(deps.tripStatus)) { |
| | | if (deps.isAndroid) { |
| | | return 125; |
| | | } |
| | | return 140; |
| | | } |
| | | if (isPickupArrived) { |
| | | return 2; |
| | | } |
| | | if (isPickupApproaching) { |
| | | return 12; |
| | | } |
| | | if (isPickupSettled && !deps.isAndroid) { |
| | | return 6; |
| | | } |
| | | return 6; |
| | | } |
| | | |
| | | return { |
| | | id: 1, |
| | | latitude: pickupSite.latitude, |
| | |
| | | : !shouldHidePickupName |
| | | ? { |
| | | customCallout: { |
| | | anchorY: [TripStatus.Publishing, TripStatus.CallingCar].includes( |
| | | deps.tripStatus |
| | | ) |
| | | ? 150 |
| | | : isPickupArrived |
| | | ? -10 |
| | | : -2, |
| | | anchorY: getCustomCalloutAnchorY(), |
| | | anchorX: 0, |
| | | display: "ALWAYS" |
| | | } |
| | |
| | | ].includes(deps.tripStatus); |
| | | const isDropoffTriangle = isDropoffInService || isDropoffSettled; |
| | | const useDropoffRichCallout = isDropoffTriangle; // cover-view 富浮窗 |
| | | const getCustomCalloutAnchorY = () => { |
| | | if (!deps.isAndroid && isDropoffSettled) { |
| | | return 6; |
| | | } |
| | | return 8; |
| | | } |
| | | |
| | | return { |
| | | id: 2, |
| | | latitude: dropoffSite.latitude, |
| | |
| | | } |
| | | } |
| | | : { |
| | | customCallout: { anchorY: -2, anchorX: 0, display: "ALWAYS" } |
| | | customCallout: { anchorY: getCustomCalloutAnchorY(), anchorX: 0, display: "ALWAYS" } |
| | | }) |
| | | }; |
| | | }; |
| | |
| | | }; |
| | | }, [markersRepaintSignature, deps.tripStatus, deps.isAndroid, toggleCalloutRepaint]); |
| | | |
| | | |
| | | /** |
| | | * Android 呼叫等待态(Publishing/CallingCar)等待气泡(customCallout)同样存在偶现不绘制、 |
| | | * 倒计时文案不刷新的问题,需拖动/缩放地图才会重绘。呼叫等待期间 elapsedSeconds 每秒自增, |
| | | * 借助其变化按秒触发一次 borderRadius 回流重绘,兜底原生地图对该 cover-view 的绘制与刷新。 |
| | | */ |
| | | useEffect(() => { |
| | | if (!deps.isAndroid) { |
| | | return undefined; |
| | | } |
| | | const isWaitingCalloutActive = [ |
| | | TripStatus.Publishing, |
| | | TripStatus.CallingCar |
| | | ].includes(deps.tripStatus); |
| | | if (!isWaitingCalloutActive) { |
| | | return undefined; |
| | | } |
| | | toggleCalloutRepaint(); |
| | | return undefined; |
| | | }, [deps.elapsedSeconds, deps.tripStatus, deps.isAndroid, toggleCalloutRepaint]); |
| | | |
| | | |
| | | |
| | | /** |
| | | * 渲染等待态气泡。 |
| | | */ |
| | |
| | | slot="callout" |
| | | marker-id={item.id} |
| | | key={calloutKey} |
| | | className='waiting-callout' |
| | | className="waiting-callout" |
| | | style={calloutRepaintStyle} |
| | | > |
| | | <CoverView className="waiting-callout-content"> |
| | | {deps.tripStatus === TripStatus.CallingCar && ( |
| | | {/* {deps.tripStatus === TripStatus.CallingCar && ( */} |
| | | <CoverView className="waiting-callout-bg waiting-timedown-bg"> |
| | | <CoverImage |
| | | className="waiting-callout-bg-img" |
| | |
| | | {formatCountdownDisplay(deps.elapsedSeconds)} |
| | | </CoverView> |
| | | </CoverView> |
| | | )} |
| | | <CoverView |
| | | {/* )} */} |
| | | {/* <CoverView |
| | | className={`waiting-callout-txt ${!deps.isAndroid && "pr-6"}${ |
| | | deps.tripStatus === TripStatus.CallingCar |
| | | ? " waiting-callout-txt--overlap" |
| | | : "" |
| | | }`} |
| | | > */} |
| | | <CoverView |
| | | className={`waiting-callout-txt ${!deps.isAndroid && "pr-6"} waiting-callout-txt--overlap`} |
| | | > |
| | | {item.name} |
| | | {!deps.isAndroid && ( |
| | |
| | | src="https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/v2/diamond-icon-20260708.png" |
| | | /> |
| | | </CoverView> |
| | | <CoverImage className="waiting-radar" src={deps.waitingRadarSrc} /> |
| | | { |
| | | !deps.isAndroid && <CoverImage className="waiting-radar" src={deps.waitingRadarSrc} /> |
| | | } |
| | | </CoverView> |
| | | ), |
| | | [deps.isAndroid, deps.waitingRadarSrc, deps.tripStatus, deps.elapsedSeconds] |
| | | [ |
| | | deps.isAndroid, |
| | | deps.waitingRadarSrc, |
| | | deps.elapsedSeconds, |
| | | calloutRepaintStyle |
| | | ] |
| | | ); |
| | | |
| | | /** |
| | |
| | | * 渲染单个 marker 气泡。 |
| | | */ |
| | | const renderMarkerCallout = useCallback((item: any, index: number) => { |
| | | // iOS 上 CoverView 内多个文本节点(里程/时长数字)原地更新会偶发数字错乱, |
| | | // 故将会变化的里程/时长/限停时长纳入 key,数值变化时强制整体重新挂载而非原地 patch。 |
| | | const calloutKey = `callout-${item.id}-${item.name || ''}-${deps.routeDistance?.value ?? ''}-${deps.routeDistance?.unit ?? ''}-${deps.routeDuration ?? ''}-${deps.startSite?.time ?? ''}`; |
| | | // 故将会变化的限停时长纳入 key,数值变化时强制整体重新挂载而非原地 patch。 |
| | | const calloutKey = `callout-${item.id}-${item.name || ''}-${deps.startSite?.time ?? ''}-${deps.isAndroid}`; |
| | | // 待支付/完成态的上/下车点浮窗为富内容(end-site 图片),需走 cover-view,不能被 Android 常规隐藏规则误伤 |
| | | const isSettledSiteMarker = |
| | | (item.id === 1 || item.id === 2) && |
| | |
| | | // 均规避被 translateMarker 丢弃(customCallout 在 iOS translate 下接驾/送驾都会偶发丢失)。 |
| | | if (item.name === '车辆位置' && [TripStatus.VehicleApproaching, TripStatus.InService].includes(deps.tripStatus)) return null; |
| | | return renderDefaultCallout(item, calloutKey); |
| | | }, [deps.isAndroid, deps.tripStatus, renderDefaultCallout, renderWaitingCallout, shouldHideAndroidMarkerCallout]); |
| | | }, [deps.isAndroid, deps.tripStatus, renderDefaultCallout, renderWaitingCallout, shouldHideAndroidMarkerCallout, deps.startSite?.time]); |
| | | |
| | | /** |
| | | * 渲染地图覆盖层。 |
| | |
| | | justify-content: center; |
| | | flex-direction: column; |
| | | transform: translateY(6px); |
| | | &.site-status-callout-box { |
| | | transform: translateY(22px); |
| | | } |
| | | &.arrived-pickup-callout-box { |
| | | transform: translateY(24px); |
| | | } |
| | | &.end-callout-box { |
| | | transform: translateY(10px); |
| | | } |
| | | // &.site-status-callout-box { |
| | | // transform: translateY(22px); |
| | | // } |
| | | // &.arrived-pickup-callout-box { |
| | | // transform: translateY(24px); |
| | | // } |
| | | // &.end-callout-box { |
| | | // transform: translateY(10px); |
| | | // } |
| | | } |
| | | |
| | | .pd-6-10 { |
| | |
| | | overflow: visible; // 确保辐射动画不被裁剪 |
| | | min-width: 700px; |
| | | height: 600px; |
| | | transform: translateY(-40px); |
| | | transform: translateY(-20px); |
| | | } |
| | | |
| | | .waiting-radar { |
| | |
| | | top: 48%; |
| | | left: 50%; |
| | | transform: translate(-50%, -48%); |
| | | z-index: 1; |
| | | } |
| | | |
| | | .waiting-callout-bg { |