| src/robotaxi/pages/begin-route/hooks/use-order-actions.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/robotaxi/pages/begin-route/hooks/use-web-socket-events.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/robotaxi/pages/begin-route/index.tsx | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/robotaxi/pages/site-search/hooks/use-site-search.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/robotaxi/pages/site-search/index.tsx | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
src/robotaxi/pages/begin-route/hooks/use-order-actions.ts
@@ -25,6 +25,8 @@ setTripStatus: (value: number) => void; /** 订单设置 */ setOrderId: (value: string) => void; /** 车辆信息设置 */ setVehicleInfo: (value: any) => void; /** 下单提交设置 */ setCallSubmitting: (value: boolean) => void; /** 取消类型设置 */ @@ -173,6 +175,7 @@ */ const clearActiveOrderRuntime = () => { deps.setOrderId(''); deps.setVehicleInfo({}); clearOrderTripStorage(); Taro.removeStorageSync('pickupEndTime'); Taro.removeStorageSync('waitingTimerStartAt'); src/robotaxi/pages/begin-route/hooks/use-web-socket-events.ts
@@ -42,7 +42,8 @@ payload?.content?.orderId || payload?.orderId || fallbackOrderId || Taro.getStorageSync('orderId'); const isSameOrder = (incomingOrderId: string, currentOrderId: string) => { if (!incomingOrderId || !currentOrderId) return true; if (!incomingOrderId && !currentOrderId) return true; if (!incomingOrderId || !currentOrderId) return false; return String(incomingOrderId) === String(currentOrderId); }; @@ -86,20 +87,21 @@ lastFetchedVehicleOrderIdRef: any ) => { if (!effectiveOrderId) return; const vehicleInfoEmpty = !deps.vehicleInfo || (!deps.vehicleInfo.plateNumber && !deps.vehicleInfo.vehicleCode && !deps.vehicleInfo.vehicleColor && !deps.vehicleInfo.vehiclePictures); const shouldFetchVehicle = lastFetchedVehicleOrderIdRef.current !== effectiveOrderId && (vehicleInfoEmpty || deps.orderId !== effectiveOrderId); const shouldFetchVehicle = lastFetchedVehicleOrderIdRef.current !== effectiveOrderId; if (deps.orderId !== effectiveOrderId) { deps.setOrderId(effectiveOrderId); Taro.setStorageSync('orderId', effectiveOrderId); } if (!shouldFetchVehicle) return; lastFetchedVehicleOrderIdRef.current = effectiveOrderId; const requestedOrderId = String(effectiveOrderId); queryVehicleByOrderId({ orderId: effectiveOrderId }) .then((res: any) => { const latestOrderId = String(Taro.getStorageSync('orderId') || ''); if (latestOrderId !== requestedOrderId) { return; } deps.setVehicleInfo(res); }) .catch(() => { }); @@ -109,6 +111,7 @@ if (!payload?.showCancelPopup) return; if (changeStatusOld === 4 || changeStatusOld === 5) { deps.setOrderId(''); deps.setVehicleInfo({}); clearOrderTripStorage(); Taro.removeStorageSync('pickupEndTime'); Taro.removeStorageSync('waitingTimerStartAt'); @@ -346,8 +349,13 @@ return; } lastFetchedVehicleOrderIdRef.current = null; const requestedOrderId = String(currentOrderId || ''); queryVehicleByOrderId({ orderId: currentOrderId }) .then((res: any) => { const latestOrderId = String((depsRef.current.orderId || Taro.getStorageSync('orderId') || '')); if (!requestedOrderId || latestOrderId !== requestedOrderId) { return; } currentDeps.setVehicleInfo(res); }) .catch(() => { }); src/robotaxi/pages/begin-route/index.tsx
@@ -393,6 +393,7 @@ cancelType, setTripStatus, setOrderId, setVehicleInfo, setCallSubmitting, setCancelType, setShowCancelPopup, src/robotaxi/pages/site-search/hooks/use-site-search.ts
@@ -33,11 +33,19 @@ const [isSearching, setIsSearching] = useState(false); // 最近一次完成搜索的关键词 const [lastCompletedKeyword, setLastCompletedKeyword] = useState(''); // 初始化数据是否已完成加载 const [isInitLoaded, setIsInitLoaded] = useState(false); const searchSeqRef = useRef(0); const debounceTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null); const pendingSearchValueRef = useRef(''); // 拉取附近站点 const fetchNearbySites = async (lat: number, lon: number, electronicAreaId?: string) => { const fetchNearbySites = async ( lat: number, lon: number, electronicAreaId?: string, canUpdate?: () => boolean ) => { const selectedCity = Taro.getStorageSync('selectedCity'); try { const res = await getNearestSite({ @@ -46,9 +54,15 @@ longitude: Number(lon), electronicAreaId }); if (canUpdate && !canUpdate()) { return; } const points = Array.isArray(res?.points) ? res.points : []; setNearbySiteList(points.map(normalizeSiteItem)); } catch { if (canUpdate && !canUpdate()) { return; } setNearbySiteList([]); } }; @@ -139,21 +153,55 @@ // 搜索输入防抖 const debouncedSearch = useMemo(() => { return (val: string) => { pendingSearchValueRef.current = val; if (debounceTimerRef.current) { clearTimeout(debounceTimerRef.current); } debounceTimerRef.current = setTimeout(() => { debounceTimerRef.current = null; searchSiteRef.current(val); }, 300); }; }, []); // 清空搜索结果列表 const clearSearchResults = () => { // 取消搜索输入防抖定时器 const cancelDebouncedSearch = () => { if (debounceTimerRef.current) { clearTimeout(debounceTimerRef.current); debounceTimerRef.current = null; } pendingSearchValueRef.current = ''; }; // 立即执行待触发的防抖搜索 const flushDebouncedSearch = () => { if (!debounceTimerRef.current) { return; } const pendingValue = pendingSearchValueRef.current; clearTimeout(debounceTimerRef.current); debounceTimerRef.current = null; pendingSearchValueRef.current = ''; searchSiteRef.current(pendingValue); }; // 确认搜索:优先使用显式关键字,其次使用防抖待执行关键字,最后回退到当前输入值 const confirmSearch = (val?: string) => { const explicitValue = typeof val === 'string' ? val : ''; const pendingValue = pendingSearchValueRef.current; const fallbackValue = deps.searchValue; const targetValue = explicitValue || pendingValue || fallbackValue || ''; if (debounceTimerRef.current) { clearTimeout(debounceTimerRef.current); debounceTimerRef.current = null; } pendingSearchValueRef.current = ''; searchSiteRef.current(targetValue); }; // 清空搜索结果列表 const clearSearchResults = () => { cancelDebouncedSearch(); // 推进请求序号,使清空前已发出的请求结果失效 searchSeqRef.current += 1; setSiteList([]); @@ -164,36 +212,55 @@ useEffect(() => { return () => { if (debounceTimerRef.current) { clearTimeout(debounceTimerRef.current); } cancelDebouncedSearch(); }; }, []); // 初始化:拉取附近站点、历史记录、页面类型 useEffect(() => { const { pageType: type, latitude: lat, longitude: lon, electronicAreaId } = deps.router.params; if (lat && lon) { fetchNearbySites(Number(lat), Number(lon), electronicAreaId); } checkOtp(false).then(otp => { if (otp && lat && lon) { const payload = { lat: Number(lat), lon: Number(lon), electronicAreaId }; const handleSuccess = (res: any) => { if (Array.isArray(res)) { let isUnmounted = false; const initPageData = async () => { const { pageType: type, latitude: lat, longitude: lon, electronicAreaId } = deps.router.params; const initTasks: Promise<unknown>[] = []; if (lat && lon) { initTasks.push( fetchNearbySites( Number(lat), Number(lon), electronicAreaId, () => !isUnmounted ) ); } initTasks.push((async () => { try { const otp = await checkOtp(false); if (!otp || !lat || !lon) { return; } const payload = { lat: Number(lat), lon: Number(lon), electronicAreaId }; const res = type === 'start' ? await getStartPoints(payload) : type === 'end' ? await getEndPoints(payload) : []; if (Array.isArray(res) && !isUnmounted) { setHistorySite(res.map(normalizeSiteItem)); } }; if (type === 'start') { getStartPoints(payload).then(handleSuccess); } else if (type === 'end') { getEndPoints(payload).then(handleSuccess); } } catch { } })()); if (type) { setPageType(type); } }); if (type) { setPageType(type); } await Promise.allSettled(initTasks); if (!isUnmounted) { setIsInitLoaded(true); } }; initPageData(); return () => { isUnmounted = true; }; }, []); return { @@ -204,8 +271,12 @@ nearbySiteList, isSearching, lastCompletedKeyword, isInitLoaded, searchSite, debouncedSearch, cancelDebouncedSearch, flushDebouncedSearch, confirmSearch, clearSearchResults }; } src/robotaxi/pages/site-search/index.tsx
@@ -39,8 +39,12 @@ nearbySiteList, isSearching, lastCompletedKeyword, isInitLoaded, searchSite, debouncedSearch, cancelDebouncedSearch, flushDebouncedSearch, confirmSearch, clearSearchResults } = useSiteSearch({ router, @@ -61,7 +65,7 @@ }).catch(() => { }); }, []); const changeSearchValue = (e) => { const changeSearchValue = (e: any) => { const val = e.detail.value; setSearchValue(val); debouncedSearch(val); @@ -238,8 +242,12 @@ <View className='search-input-box'> <Input className='search-input' placeholder={pageType == 'start' ? '请输入上车点' : '请输入目的地'} value={searchValue} onInput={(e) => changeSearchValue(e)} onBlur={() => searchSite()} onConfirm={() => searchSite()} onBlur={flushDebouncedSearch} onConfirm={(e) => { const keyword = e?.detail?.value || searchValue; // 确认搜索关键字,优先取输入框事件值 confirmSearch(keyword); }} confirmType='search' autoFocus /> { @@ -300,7 +308,7 @@ </View> } { canShowSearchFallback && (!siteList.length && (!searchValue ? !nearbySiteList.length : true) && !nonOperationalSite.length && (!searchValue ? !historySite.length : true)) && isInitLoaded && canShowSearchFallback && (!siteList.length && (!searchValue ? !nearbySiteList.length : true) && !nonOperationalSite.length && (!searchValue ? !historySite.length : true)) && <View className='history-card'> <View className='card-header'>暂无搜索结果,为您推荐附近站点</View> <View className='card-content list-content'>