From 67a2484722faa35bf1dad104ae8cbec294ea14b0 Mon Sep 17 00:00:00 2001
From: hejianhao <15708179461@qq.com>
Date: 星期三, 04 三月 2026 16:12:26 +0800
Subject: [PATCH] feat(robotaxi): 添加登录检查与搜索界面优化

---
 src/robotaxi/pages/site-search/index.tsx     |   85 +++++++++++++--------
 src/robotaxi/pages/site-search/index.less    |   18 ++++
 src/robotaxi/pages/select-map-site/index.tsx |   55 ++++++++++---
 src/pages/robotaxi/home/index.tsx            |   39 ++++++++-
 src/robotaxi/pages/begin-route/index.tsx     |    8 +
 5 files changed, 152 insertions(+), 53 deletions(-)

diff --git a/src/pages/robotaxi/home/index.tsx b/src/pages/robotaxi/home/index.tsx
index 3c54e75..95de197 100644
--- a/src/pages/robotaxi/home/index.tsx
+++ b/src/pages/robotaxi/home/index.tsx
@@ -803,6 +803,10 @@
   }
 
   const toCoupon = () => {
+    if (isLogin) {
+      jumpTo({ url: '/pages/user/login?hideBack=1' });
+      return
+    }
     if (Taro.getStorageSync('has_show_privicy_Robotaxi') !== 'true') {
       setShowPrivacy(true);
       return;
@@ -813,6 +817,10 @@
   }
 
   const toOrder = () => {
+    if (isLogin) {
+      jumpTo({ url: '/pages/user/login?hideBack=1' });
+      return
+    }
     if (Taro.getStorageSync('has_show_privicy_Robotaxi') !== 'true') {
       setShowPrivacy(true);
       return;
@@ -827,8 +835,30 @@
   }
 
   // 查看运营区域
-  const handleViewOperatingArea = () => {
-    if (!polygons || polygons.length === 0) {
+  const handleViewOperatingArea = async () => {
+    if (!selectedCity?.code) {
+      Taro.showToast({
+        title: '此城市暂未开通运营区域',
+        icon: 'none'
+      });
+      return;
+    }
+    let nextPolygons = polygons;
+    try {
+      const res: any = await getGeofence({ cityCode: selectedCity.code });
+      if (res && Array.isArray(res)) {
+        nextPolygons = formatGeofencePolygons(res);
+        setPolygons(nextPolygons);
+      } else {
+        nextPolygons = [];
+        setPolygons([]);
+      }
+    } catch (err) {
+      nextPolygons = [];
+      setPolygons([]);
+    }
+
+    if (!nextPolygons || nextPolygons.length === 0) {
       Taro.showToast({
         title: '此城市暂未开通运营区域',
         icon: 'none'
@@ -836,8 +866,7 @@
       return;
     }
 
-    const points = extractPointsFromPolygons(polygons);
-
+    const points = extractPointsFromPolygons(nextPolygons);
     if (points.length > 0) {
       const mapCtx = Taro.createMapContext('map');
       mapCtx.includePoints({
@@ -916,7 +945,7 @@
         <View className="position-box">
           {/* 游客模式展示同意协议 */}
           {
-            Taro.getStorageSync('has_show_privicy_Robotaxi') != 'true' && <View className="visitor-stste">
+            (Taro.getStorageSync('has_show_privicy_Robotaxi') != 'true' && !isLogin) && <View className="visitor-stste">
               <View className="visitor-stste-tip">同意隐私协议体验更多约车体验</View>
               <View onClick={() => setShowPrivacy(true)} className="visitor-stste-go">去同意</View>
             </View>
diff --git a/src/robotaxi/pages/begin-route/index.tsx b/src/robotaxi/pages/begin-route/index.tsx
index 77a7b63..be0b31b 100644
--- a/src/robotaxi/pages/begin-route/index.tsx
+++ b/src/robotaxi/pages/begin-route/index.tsx
@@ -20,7 +20,6 @@
 import originIcon from '../../../robotaxi/assets/origin-icon.png'
 import wsManager from '../../../utils/websocket';
 import { getWalkingRoute, formatDurationToClock, formatDateTime, getStoredRoutePoints, clearOrderTripStorage } from '../../../utils/Robotaxi-public-method';
-import lineRight from '../../../robotaxi/assets/line-right.png';
 import {
   saveOrder,
   queryRouteAndFare,
@@ -30,6 +29,8 @@
   queryOrderRoute,
 } from '../../../robotaxi/api/begin-route';
 import { getOrderDetail } from '../../../robotaxi/api/order';
+import { checkOtp } from '../../../utils/tools';
+import { jumpTo } from '../../../utils/jump';
 
 export default function SelectMapSite() {
   const WAITING_TIMER_START_KEY = 'waitingTimerStartAt';
@@ -877,6 +878,11 @@
 
   // 立即呼叫
   const callImmediately = async () => {
+    const otp = await checkOtp(false);
+    if (!otp) {
+      jumpTo({ url: '/pages/user/login?hideBack=1' });
+      return
+    }
     if (!endSite.name) {
       Taro.showToast({
         title: '请选择站点',
diff --git a/src/robotaxi/pages/select-map-site/index.tsx b/src/robotaxi/pages/select-map-site/index.tsx
index 99c7a0e..1204238 100644
--- a/src/robotaxi/pages/select-map-site/index.tsx
+++ b/src/robotaxi/pages/select-map-site/index.tsx
@@ -22,6 +22,8 @@
 } from '../../../utils/Robotaxi-public-method';
 import { getGeofence } from '../../api/home';
 import { getOrderDistance } from '../../api/select-map-site';
+import { checkOtp } from '../../../utils/tools';
+import { jumpTo } from '../../../utils/jump';
 
 export default function SelectMapSite() {
 
@@ -73,7 +75,8 @@
       cachedSite = Taro.getStorageSync('endSite');
     }
 
-    // 有缓存,优先使用缓存回显;否则使用当前定位
+    const hasCachedSite = !!(cachedSite && cachedSite.latitude && cachedSite.longitude);
+    // 有缓存,优先使用缓存回显
     if (cachedSite && cachedSite.latitude && cachedSite.longitude) {
       setLatitude(cachedSite.latitude);
       setLongitude(cachedSite.longitude);
@@ -81,8 +84,6 @@
       updateMapData(cachedSite.latitude, cachedSite.longitude).then(({ isInside }) => {
         setOutOfServiceRange(getOutOfServiceRange(isInside, cachedSite));
       });
-    } else {
-      getLocationInfo();
     }
     fetchUserLocation();
 
@@ -106,13 +107,38 @@
         if (res && Array.isArray(res)) {
           const newPolygons = formatGeofencePolygons(res);
           setPolygons(newPolygons);
+          if (!hasCachedSite && res.length > 0 && res[0]?.points?.length > 0) {
+            const firstPoint = res[0].points[0];
+            const lat = Number(firstPoint.lat);
+            const lng = Number(firstPoint.lng);
+            setLatitude(lat);
+            setLongitude(lng);
+            updateMapData(lat, lng).then(({ isInside }) => {
+              setOutOfServiceRange(getOutOfServiceRange(isInside, {}));
+            });
+            const mapCtx = Taro.createMapContext('map');
+            mapCtx.moveToLocation({
+              latitude: lat,
+              longitude: lng,
+            });
+          } else if (!hasCachedSite) {
+            getLocationInfo();
+          }
         } else {
           setPolygons([]);
+          if (!hasCachedSite) {
+            getLocationInfo();
+          }
         }
       }).catch(err => {
         console.error('获取电子围栏失败', err);
         setPolygons([]);
+        if (!hasCachedSite) {
+          getLocationInfo();
+        }
       });
+    } else if (!hasCachedSite) {
+      getLocationInfo();
     }
   }, []);
 
@@ -336,22 +362,23 @@
     });
   }, [pageType, userLatitude, userLongitude, latitude, longitude, selectedSite?.latitude, selectedSite?.longitude]);
 
-  // useEffect(() => {
-  //   if (!polyline.length || !polyline[0]?.points?.length) return;
-  //   const mapCtx = Taro.createMapContext('map');
-  //   mapCtx.includePoints({
-  //     points: polyline[0].points,
-  //     padding: [80, 80, 200, 80]
-  //   });
-  // }, [polyline]);
-
-  const toCoupon = () => {
+  const toCoupon = async () => {
+    const otp = await checkOtp(false);
+    if (!otp) {
+      jumpTo({ url: '/pages/user/login?hideBack=1' });
+      return
+    }
     Taro.navigateTo({
       url: '/robotaxi/pages/coupon/index',
     })
   }
 
-  const toOrder = () => {
+  const toOrder = async () => {
+    const otp = await checkOtp(false);
+    if (!otp) {
+      jumpTo({ url: '/pages/user/login?hideBack=1' });
+      return
+    }
     Taro.navigateTo({
       url: '/robotaxi/pages/order/index',
     })
diff --git a/src/robotaxi/pages/site-search/index.less b/src/robotaxi/pages/site-search/index.less
index d48fb46..b061a84 100644
--- a/src/robotaxi/pages/site-search/index.less
+++ b/src/robotaxi/pages/site-search/index.less
@@ -26,6 +26,24 @@
       margin-right: 16px;
     }
 
+    .search-input-box {
+      flex: 1;
+      display: flex;
+      align-items: center;
+
+      .cancel-icon-box {
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        padding: 10px;
+
+        .cancel-icon {
+          width: 32px;
+          height: 32px;
+        }
+      }
+    }
+
     .end-icon {
       background: #8BB654;
     }
diff --git a/src/robotaxi/pages/site-search/index.tsx b/src/robotaxi/pages/site-search/index.tsx
index 1c981dc..f0abacf 100644
--- a/src/robotaxi/pages/site-search/index.tsx
+++ b/src/robotaxi/pages/site-search/index.tsx
@@ -9,6 +9,7 @@
 import { formatDistance, debounce } from '../../../utils/Robotaxi-public-method';
 import { AMAP_KEY } from '../../../constants/api';
 import amapFile from '../../../libs/amap-wx.130.js';
+import { checkOtp } from '../../../utils/tools';
 
 
 
@@ -41,7 +42,7 @@
       if (Array.isArray(availablePoints)) {
         const list = availablePoints.map(item => ({
           ...item,
-          distance: formatDistance(item.distance)
+          distance: item.distance
         }));
         setNearbySiteList(list);
       } else {
@@ -56,36 +57,41 @@
   useEffect(() => {
     const { pageType: type, latitude: lat, longitude: lon, electronicAreaId } = router.params;
 
+    checkOtp(false).then(otp => {
+      if (otp) {
+        if (lat && lon) {
+          fetchNearbySites(Number(lat), Number(lon), electronicAreaId);
+          const payload = {
+            lat: Number(lat),
+            lon: Number(lon)
+          };
+
+          const handleSuccess = (res) => {
+            if (Array.isArray(res)) {
+              const list = res.map(item => ({
+                ...item,
+                distance: item.distance
+              }));
+              setHistorySite(list);
+            }
+          };
+
+          if (type === 'start') {
+            getStartPoints(payload).then(handleSuccess);
+          } else if (type === 'end') {
+            getEndPoints(payload).then(handleSuccess);
+          }
+        }
+      }
+    });
+
     if (type) {
       setPageType(type);
-    }
-
-    if (lat && lon) {
-      fetchNearbySites(Number(lat), Number(lon), electronicAreaId);
-      const payload = {
-        lat: Number(lat),
-        lon: Number(lon)
-      };
-
-      const handleSuccess = (res) => {
-        if (Array.isArray(res)) {
-          const list = res.map(item => ({
-            ...item,
-            distance: formatDistance(item.distance)
-          }));
-          setHistorySite(list);
-        }
-      };
-
-      if (type === 'start') {
-        getStartPoints(payload).then(handleSuccess);
-      } else if (type === 'end') {
-        getEndPoints(payload).then(handleSuccess);
-      }
     }
   }, [])
 
   const searchSite = async (val?: string) => {
+    setNonOperationalSite([]);
     const queryVal = val !== undefined ? val : searchValue;
     if (!queryVal) return;
 
@@ -107,7 +113,7 @@
       if (Array.isArray(availablePoints)) {
         const list = availablePoints.map(item => ({
           ...item,
-          distance: formatDistance(item.distance)
+          distance: item.distance
         }));
         setSiteList(list);
       } else {
@@ -209,6 +215,11 @@
     }
   }
 
+  const clearSearchValue = () => {
+    setSearchValue('');
+    searchSite('');
+  }
+
 
   const recommendList = siteList.length > 0 ? siteList : nearbySiteList;
 
@@ -217,12 +228,20 @@
       {/* 搜索区域 */}
       <View className='search-card'>
         <View className={`search-icon ${pageType == 'end' ? 'end-icon' : ''}`}></View>
-        <Input className='search-input' placeholder={pageType == 'start' ? '请输入上车点' : '请输入目的地'} value={searchValue}
-          onInput={(e) => changeSearchValue(e)}
-          onBlur={() => searchSite()}
-          onConfirm={() => searchSite()}
-          autoFocus
-        ></Input>
+        <View className='search-input-box'>
+          <Input className='search-input' placeholder={pageType == 'start' ? '请输入上车点' : '请输入目的地'} value={searchValue}
+            onInput={(e) => changeSearchValue(e)}
+            onBlur={() => searchSite()}
+            onConfirm={() => searchSite()}
+            autoFocus
+          />
+          {
+            searchValue &&
+            <View onClick={clearSearchValue} className='cancel-icon-box'>
+              <Image className='cancel-icon' src={require('../../assets/close-icon.png')} />
+            </View>
+          }
+        </View>
         <Image onClick={toSelectSite} className='clear-icon' src={map}></Image>
       </View>
       {/* 历史记录 */}
@@ -239,7 +258,7 @@
                     <View className='history-name'>{item.name || '_'}</View>
                     <View className='history-address-box'>
                       <View className='history-address'>{item.address || '-'}</View>
-                      <View className='history-distance'>{item.distance}</View>
+                      <View className='history-distance'>{item.distance}km</View>
                     </View>
                   </View>
                 </View>

--
Gitblit v1.7.1