hejianhao
2026-06-26 00193c3f54f9d38c85a4498f195632499ac27ad3
feat(robotaxi): 新增独立收藏站点页面并调整相关文案与导航
3个文件已添加
6个文件已修改
208 ■■■■■ 已修改文件
src/app.config.ts 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/api/site-search.ts 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/components/coupon-select-popup/index.tsx 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/favorite-sites/index.config.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/favorite-sites/index.less 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/favorite-sites/index.tsx 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/personal-center/index.tsx 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/site-search/components/favorite-popup/index.tsx 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/site-search/index.tsx 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/app.config.ts
@@ -40,6 +40,7 @@
        'pages/operating-area/index',
        'pages/share-trip/index',
        'pages/personal-center/index',
        'pages/favorite-sites/index',
        'pages/payment-setting/index',
        'pages/payment-setting-detail/index',
      ],
src/robotaxi/api/site-search.ts
@@ -37,7 +37,7 @@
    }, true);
}
// 获取用户收藏夹收藏地址列表
// 获取用户收藏站点收藏地址列表
export const getCollectPoints = async (payload) => {
    return request({
        url: _ROBOTAXI_HOST + '/account/api/v1/mini-program/collect/addrlist',
src/robotaxi/components/coupon-select-popup/index.tsx
@@ -219,10 +219,10 @@
            <View className="coupon-list-head-item">
              平台优惠券({couponCount}张)
            </View>
            <View className="my-coupon-item" onClick={gotoMyCoupon}>
            {/* <View className="my-coupon-item" onClick={gotoMyCoupon}>
              <Text>我的优惠券</Text>
              <Image className="arrow-icon" src="https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/coupon-arrow-right.png" />
            </View>
            </View> */}
          </View>
          <ScrollView
            scrollY={canScroll}
src/robotaxi/pages/favorite-sites/index.config.ts
New file
@@ -0,0 +1,3 @@
export default {
  navigationBarTitleText: '收藏站点',
};
src/robotaxi/pages/favorite-sites/index.less
New file
@@ -0,0 +1,74 @@
page {
  background-color: #F4F5F7;
}
.favorite-sites-page {
  width: 100vw;
  height: 100vh;
  display: flex;
  flex-direction: column;
  background-color: #F4F5F7;
  overflow: hidden;
  .favorite-list {
    flex: 1;
    height: 100%;
    .favorite-list-inner {
      padding: 36px 24px;
      padding-bottom: constant(safe-area-inset-bottom);
      padding-bottom: env(safe-area-inset-bottom);
    }
  }
  .favorite-item {
    background: #FFFFFF;
    border-radius: 24px;
    padding: 28px 32px;
    margin-bottom: 24px;
    display: flex;
    flex-direction: row;
    justify-content: space-between;
    .favorite-info {
      flex: 1;
      overflow: hidden;
      margin-right: 32px;
      .favorite-name {
        font-weight: 500;
        font-size: 28px;
        color: #3D3D3D;
        display: -webkit-box;
        -webkit-box-orient: vertical;
        -webkit-line-clamp: 2;
        overflow: hidden;
        text-overflow: ellipsis;
        word-break: break-all;
        margin-bottom: 8px;
      }
      .favorite-address {
        font-size: 24px;
        color: rgba(0, 0, 0, 0.4);
        line-height: 36px;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
      }
    }
    .delete-icon {
      width: 40px;
      height: 40px;
      flex-shrink: 0;
    }
  }
  .empty-tip {
    text-align: center;
    font-size: 28px;
    color: #999999;
    margin-top: 200px;
  }
}
src/robotaxi/pages/favorite-sites/index.tsx
New file
@@ -0,0 +1,102 @@
import Taro from '@tarojs/taro';
import { View, Image, ScrollView } from '@tarojs/components';
import { useEffect, useState } from 'react';
import './index.less';
import { getCollectPoints, collectPoint } from '../../api/site-search';
export default function FavoriteSitesPage() {
  const [list, setList] = useState<any[]>([]);
  const [current, setCurrent] = useState(1);
  const [hasNextPage, setHasNextPage] = useState(false);
  const [loading, setLoading] = useState(false);
  const fetchData = async (page = 1) => {
    if (loading) return;
    setLoading(true);
    try {
      const res = await getCollectPoints({
        pageNum: page,
        pageSize: 20,
      });
      if (res && res.records) {
        setList(prev => page === 1 ? res.records : [...prev, ...res.records]);
        setHasNextPage(res.hasNextPage);
        setCurrent(res.current);
      }
    } catch (e) {
      console.log('获取收藏站点失败', e);
    } finally {
      setLoading(false);
    }
  };
  const handleScrollToLower = () => {
    if (hasNextPage && !loading) {
      fetchData(current + 1);
    }
  };
  const handleDelete = async (item: any) => {
    try {
      const currentItemType = Number(item?.itemType); // 删除项类型
      const payload: any = {
        type: 2, // 2=取消收藏
        itemType: currentItemType,
      };
      if (currentItemType === 2) {
        payload.stationId = item?.stationId;
      } else {
        payload.pointId = item?.pointId || item?.id;
        payload.latitude = item?.latitude;
        payload.longitude = item?.longitude;
      }
      await collectPoint(payload);
      setList(prev => prev.filter(f => (f.id || f.pointId || f.stationId) !== (item.id || item.pointId || item.stationId)));
      Taro.showToast({ title: '已取消收藏', icon: 'none' });
    } catch (e) {
      console.log('取消收藏失败', e);
      Taro.showToast({ title: '取消收藏失败', icon: 'none' });
    }
  };
  useEffect(() => {
    fetchData(1);
  }, []);
  return (
    <View className='favorite-sites-page'>
      <ScrollView
        scrollY
        className='favorite-list'
        enhanced
        lowerThreshold={50}
        onScrollToLower={handleScrollToLower}
      >
        <View className='favorite-list-inner'>
          {list.map((item, index) => (
            <View key={item.id || index} className='favorite-item'>
              <View className='favorite-info'>
                <View className='favorite-name'>{item.pointName}</View>
                <View className='favorite-address'>{item.pointAddress}</View>
              </View>
              <Image
                onClick={(e) => {
                  e.stopPropagation();
                  handleDelete(item);
                }}
                className='delete-icon'
                src="https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/delete-icon.png"
              />
            </View>
          ))}
          {list.length === 0 && !loading && (
            <View className='empty-tip'>暂无收藏站点</View>
          )}
        </View>
      </ScrollView>
    </View>
  );
}
src/robotaxi/pages/personal-center/index.tsx
@@ -3,7 +3,6 @@
import { View, Text, Image } from "@tarojs/components";
import { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import FavoritePopup from "../site-search/components/favorite-popup";
import { getOrderHistoryList } from "../../api/order";
import { getUserouponNum } from "../../api/coupon";
import { _INVOICE_URL } from "../../../constants/api";
@@ -45,7 +44,6 @@
  const nickname = useSelector((state: any) => state.user?.userInfo?.nickName) || "小鹏艺术家";
  const reduxDispatch = useDispatch();
  const [showFavoritePopup, setShowFavoritePopup] = useState(false);
  const [hasPendingPayOrder, setHasPendingPayOrder] = useState(false);
  const [couponCount, setCouponCount] = useState(0);
@@ -122,7 +120,7 @@
    }
    if (key === "favorite") {
      setShowFavoritePopup(true);
      Taro.navigateTo({ url: "/robotaxi/pages/favorite-sites/index" });
      return;
    }
@@ -206,14 +204,6 @@
          </View>
        </View>
      </View>
      <FavoritePopup
        show={showFavoritePopup}
        onClose={() => setShowFavoritePopup(false)}
        onSelect={(item) => {
          console.log('Selected favorite item:', item);
        }}
      />
    </View>
  );
}
src/robotaxi/pages/site-search/components/favorite-popup/index.tsx
@@ -50,7 +50,7 @@
        setCurrent(res.current);
      }
    } catch (e) {
      console.log('获取收藏夹失败', e);
      console.log('获取收藏站点失败', e);
    } finally {
      setLoading(false);
    }
@@ -178,7 +178,7 @@
      <View className='favorite-mask' onClick={onClose}></View>
      <View className='favorite-content' animation={animationData}>
        <View className='favorite-header'>
          <Text className='favorite-title'>收藏夹</Text>
          <Text className='favorite-title'>收藏站点</Text>
          <Image className='close-icon' src="https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/close-icon.png" onClick={onClose} />
        </View>
        <View className='favorite-list-wrap'>
src/robotaxi/pages/site-search/index.tsx
@@ -431,7 +431,7 @@
  };
  /**
   * 收藏夹返回的是“收藏记录对象”,这里统一转换成下单链路使用的站点对象。
   * 收藏站点返回的是“收藏记录对象”,这里统一转换成下单链路使用的站点对象。
   */
  const normalizeFavoriteSelectedSite = (item: any) => {
    const resolvedPointId = item?.pointId || '';
@@ -554,11 +554,11 @@
          }
        </View>
      </View>
      {/* 收藏夹与地图选点 */}
      {/* 收藏站点与地图选点 */}
      <View className='fast-box'>
        <View className='fast-item' onClick={() => setShowFavoritePopup(true)}>
          <Image className='fast-item-icon' src="https://s.xiaopeng.com/xp-fe/robot-taxi/imgs/favorite.png"></Image>
          <Text className='fast-item-text'>收藏夹</Text>
          <Text className='fast-item-text'>收藏站点</Text>
        </View>
        <View className='fast-split'></View>
        <View onClick={toSelectSite} className='fast-item'>