From 13c960a2b6bb54797bdbd03aa3184af507d94a9b Mon Sep 17 00:00:00 2001
From: 卢春龙 <lucl@xiaopeng.com>
Date: 星期一, 20 四月 2026 10:42:28 +0800
Subject: [PATCH] Merge branch 'feature_pr_fix' into 'develop'
---
src/robotaxi/pages/site-search/hooks/use-site-search.ts | 111 ++++++++++++++++++++++++++++++++++++++++++-------------
1 files changed, 85 insertions(+), 26 deletions(-)
diff --git a/src/robotaxi/pages/site-search/hooks/use-site-search.ts b/src/robotaxi/pages/site-search/hooks/use-site-search.ts
index df70be5..8f8b302 100644
--- a/src/robotaxi/pages/site-search/hooks/use-site-search.ts
+++ b/src/robotaxi/pages/site-search/hooks/use-site-search.ts
@@ -1,7 +1,6 @@
import Taro from '@tarojs/taro';
import { useEffect, useMemo, useRef, useState } from 'react';
import { getStartPoints, getEndPoints, queryPointByName } from '../../../api/site-search';
-import { debounce } from '../../../../utils/Robotaxi-public-method';
import { checkOtp } from '../../../../utils/tools';
import { getNearestSite } from '../../../api/home';
import { _AMAP_KEY } from '../../../../constants/api';
@@ -30,6 +29,12 @@
const [nearbySiteList, setNearbySiteList] = useState<any[]>([]);
// 页面类型(start/end)
const [pageType, setPageType] = useState('');
+ // 当前关键词是否仍在搜索中(含高德补充结果)
+ const [isSearching, setIsSearching] = useState(false);
+ // 最近一次完成搜索的关键词
+ const [lastCompletedKeyword, setLastCompletedKeyword] = useState('');
+ const searchSeqRef = useRef(0);
+ const debounceTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
// 拉取附近站点
const fetchNearbySites = async (lat: number, lon: number, electronicAreaId?: string) => {
@@ -50,9 +55,17 @@
// 站点搜索请求与结果处理
const searchSite = async (val?: string) => {
- setNonOperationalSite([]);
const queryVal = val !== undefined ? val : deps.searchValue;
- if (!queryVal) return;
+ const normalizedQuery = String(queryVal || '').trim();
+ searchSeqRef.current += 1;
+ const requestSeq = searchSeqRef.current;
+ setNonOperationalSite([]);
+ if (!normalizedQuery) {
+ setIsSearching(false);
+ setLastCompletedKeyword('');
+ return;
+ }
+ setIsSearching(true);
const { latitude, longitude, electronicAreaId } = deps.router.params;
const selectedCity = Taro.getStorageSync('selectedCity');
const payload = {
@@ -60,42 +73,63 @@
electronicAreaId: electronicAreaId ? Number(electronicAreaId) : 0,
lat: Number(latitude),
lon: Number(longitude),
- pointPoi: queryVal
+ pointPoi: normalizedQuery
};
try {
const res = await queryPointByName(payload);
+ if (requestSeq !== searchSeqRef.current) return;
const { availablePoints } = res;
if (Array.isArray(availablePoints)) {
const list = availablePoints.map(normalizeSiteItem);
- const sorted = sortSitesByNameMatchAndDistance(list, queryVal);
+ const sorted = sortSitesByNameMatchAndDistance(list, normalizedQuery);
setSiteList(sorted.slice(0, deps.maxExpandedCount));
} else {
setSiteList([]);
}
const myAmapFun = new amapFile.AMapWX({ key: _AMAP_KEY });
- myAmapFun.getPoiAround({
- querykeywords: queryVal,
- location: `${longitude},${latitude}`,
- success: (data: any) => {
- if (data && data.poisData) {
- const list = data.poisData.map((item: any) => {
- const locationArr = item.location.split(',');
- return {
- ...item,
- longitude: Number(locationArr[0]),
- latitude: Number(locationArr[1]),
- ...normalizeSiteItem(item)
- };
- });
- const sorted = sortSitesByNameMatchAndDistance(list, queryVal);
- setNonOperationalSite(sorted.slice(0, deps.maxShowCount));
+ await new Promise<void>((resolve) => {
+ myAmapFun.getPoiAround({
+ querykeywords: normalizedQuery,
+ location: `${longitude},${latitude}`,
+ success: (data: any) => {
+ if (requestSeq !== searchSeqRef.current) {
+ resolve();
+ return;
+ }
+ if (data && data.poisData) {
+ const list = data.poisData.map((item: any) => {
+ const locationArr = item.location.split(',');
+ return {
+ ...item,
+ longitude: Number(locationArr[0]),
+ latitude: Number(locationArr[1]),
+ ...normalizeSiteItem(item)
+ };
+ });
+ const sorted = sortSitesByNameMatchAndDistance(list, normalizedQuery);
+ setNonOperationalSite(sorted.slice(0, deps.maxShowCount));
+ } else {
+ setNonOperationalSite([]);
+ }
+ resolve();
+ },
+ fail: () => {
+ if (requestSeq === searchSeqRef.current) {
+ setNonOperationalSite([]);
+ }
+ resolve();
}
- },
- fail: () => { }
+ });
});
} catch {
+ if (requestSeq !== searchSeqRef.current) return;
setSiteList([]);
setNonOperationalSite([]);
+ } finally {
+ if (requestSeq === searchSeqRef.current) {
+ setIsSearching(false);
+ setLastCompletedKeyword(normalizedQuery);
+ }
}
};
@@ -103,15 +137,38 @@
searchSiteRef.current = searchSite;
// 搜索输入防抖
- const debouncedSearch = useMemo(() => debounce((val) => {
- searchSiteRef.current(val);
- }, 300), []);
+ const debouncedSearch = useMemo(() => {
+ return (val: string) => {
+ if (debounceTimerRef.current) {
+ clearTimeout(debounceTimerRef.current);
+ }
+ debounceTimerRef.current = setTimeout(() => {
+ searchSiteRef.current(val);
+ }, 300);
+ };
+ }, []);
// 清空搜索结果列表
const clearSearchResults = () => {
+ if (debounceTimerRef.current) {
+ clearTimeout(debounceTimerRef.current);
+ debounceTimerRef.current = null;
+ }
+ // 推进请求序号,使清空前已发出的请求结果失效
+ searchSeqRef.current += 1;
setSiteList([]);
setNonOperationalSite([]);
+ setIsSearching(false);
+ setLastCompletedKeyword('');
};
+
+ useEffect(() => {
+ return () => {
+ if (debounceTimerRef.current) {
+ clearTimeout(debounceTimerRef.current);
+ }
+ };
+ }, []);
// 初始化:拉取附近站点、历史记录、页面类型
useEffect(() => {
@@ -145,6 +202,8 @@
historySite,
nonOperationalSite,
nearbySiteList,
+ isSearching,
+ lastCompletedKeyword,
searchSite,
debouncedSearch,
clearSearchResults
--
Gitblit v1.7.1