From be89bb996f63b74df9e3ef010a92d4a7dc34b60e Mon Sep 17 00:00:00 2001
From: 卢春龙 <lucl@xiaopeng.com>
Date: 星期三, 22 四月 2026 10:17:09 +0800
Subject: [PATCH] Merge branch 'feature_search_fix' into 'develop'
---
src/robotaxi/pages/site-search/hooks/use-site-search.ts | 121 ++++++++++++++++++++++++++++++++--------
1 files changed, 96 insertions(+), 25 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 8f8b302..a02364e 100644
--- a/src/robotaxi/pages/site-search/hooks/use-site-search.ts
+++ b/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
};
}
--
Gitblit v1.7.1