| New file |
| | |
| | | import Taro from '@tarojs/taro'; |
| | | import { useEffect, useMemo, useRef, useState } from 'react'; |
| | | import { getUserQuickCapsule } from '../../../../robotaxi/api/home'; |
| | | |
| | | type CapsuleSite = { |
| | | id: string | number; |
| | | name: string; |
| | | latitude: number; |
| | | longitude: number; |
| | | electronicAreaId?: string | number; |
| | | time?: number; |
| | | [key: string]: any; |
| | | }; |
| | | |
| | | type Deps = { |
| | | /** 是否游客态(未登录) */ |
| | | isGuest: boolean; |
| | | /** 登录校验 */ |
| | | checkOtp: (silent?: boolean) => Promise<any>; |
| | | /** 当前上车点 */ |
| | | currentSite: any; |
| | | }; |
| | | |
| | | /** |
| | | * 首页快捷胶囊编排:负责登录态校验、数据请求、点击跳转。 |
| | | */ |
| | | export default function useQuickCapsule(deps: Deps) { |
| | | const [capsuleSites, setCapsuleSites] = useState<CapsuleSite[]>([]); // 快捷胶囊站点列表 |
| | | const requestSeqRef = useRef(0); // 快捷胶囊请求序号,避免旧请求覆盖 |
| | | |
| | | /** |
| | | * 获取用于请求的上车点 ID(仅使用当前选中站点,避免滑动过程误用旧缓存)。 |
| | | */ |
| | | const resolveRequestStartPointId = () => { |
| | | const currentPointId = deps.currentSite?.id; |
| | | if (!currentPointId) { |
| | | return ''; |
| | | } |
| | | return String(currentPointId); |
| | | }; |
| | | |
| | | /** |
| | | * 获取用于跳转的有效上车点。 |
| | | */ |
| | | const resolveValidStartSite = () => { |
| | | const storageStartSite = Taro.getStorageSync('startSite'); // 缓存上车点 |
| | | const candidate = deps.currentSite?.id ? deps.currentSite : storageStartSite; |
| | | if (!candidate?.id) { |
| | | return null; |
| | | } |
| | | return candidate; |
| | | }; |
| | | const effectiveStartPointId = useMemo(() => resolveRequestStartPointId(), [deps.currentSite?.id]); // 当前可用于请求的上车点ID |
| | | |
| | | /** |
| | | * 清空快捷胶囊数据。 |
| | | */ |
| | | const clearQuickCapsule = () => { |
| | | setCapsuleSites([]); |
| | | }; |
| | | |
| | | /** |
| | | * 归一化快捷胶囊站点结构,兼容不同后端字段。 |
| | | */ |
| | | const normalizeCapsuleSite = (item: any): CapsuleSite | null => { |
| | | const latitude = Number(item?.latitude ?? item?.lat); |
| | | const longitude = Number(item?.longitude ?? item?.lon); |
| | | const id = item?.id ?? item?.pointId ?? ''; |
| | | const name = String(item?.name ?? item?.pointName ?? '').trim(); |
| | | if (!id || !name || !Number.isFinite(latitude) || !Number.isFinite(longitude)) { |
| | | return null; |
| | | } |
| | | return { |
| | | ...item, |
| | | id, |
| | | name, |
| | | latitude, |
| | | longitude, |
| | | electronicAreaId: item?.electronicAreaId ?? item?.xpElectronicFenceAreaId ?? '', |
| | | time: Number(item?.time ?? item?.parkingTimeLimit ?? 0) |
| | | }; |
| | | }; |
| | | |
| | | /** |
| | | * 拉取快捷胶囊数据(仅登录态)。 |
| | | */ |
| | | const refreshQuickCapsule = async (startPointId?: string) => { |
| | | const otp = await deps.checkOtp(false); |
| | | if (!otp) { |
| | | clearQuickCapsule(); |
| | | return; |
| | | } |
| | | const targetStartPointId = String(startPointId || effectiveStartPointId || ''); |
| | | if (!targetStartPointId) { |
| | | clearQuickCapsule(); |
| | | return; |
| | | } |
| | | const nextSeq = requestSeqRef.current + 1; |
| | | requestSeqRef.current = nextSeq; |
| | | try { |
| | | const res: any = await getUserQuickCapsule({ startPointId: targetStartPointId }); |
| | | if (nextSeq !== requestSeqRef.current) { |
| | | return; |
| | | } |
| | | const rawList = Array.isArray(res?.points) ? res.points : Array.isArray(res) ? res : []; |
| | | const normalizedList = rawList |
| | | .map(normalizeCapsuleSite) |
| | | .filter((item: CapsuleSite | null): item is CapsuleSite => !!item); |
| | | setCapsuleSites(normalizedList); |
| | | } catch (error) { |
| | | if (nextSeq !== requestSeqRef.current) { |
| | | return; |
| | | } |
| | | clearQuickCapsule(); |
| | | } |
| | | }; |
| | | |
| | | /** |
| | | * 点击快捷胶囊:写入缓存并跳转到冒泡发单页。 |
| | | */ |
| | | const handleQuickCapsuleClick = async () => { |
| | | const targetStartSite = resolveValidStartSite(); |
| | | if (!targetStartSite) { |
| | | Taro.showToast({ title: '请先选择起点站点', icon: 'none' }); |
| | | return; |
| | | } |
| | | if (capsuleSites.length === 0) { |
| | | Taro.showToast({ title: '暂无快捷目的地', icon: 'none' }); |
| | | return; |
| | | } |
| | | const targetSite = capsuleSites[0]; |
| | | Taro.setStorageSync('endSite', targetSite); |
| | | Taro.setStorageSync('startSite', targetStartSite); |
| | | await Taro.reLaunch({ url: '/robotaxi/pages/begin-route/index' }); |
| | | }; |
| | | |
| | | /** |
| | | * 胶囊展示文案。 |
| | | */ |
| | | const quickCapsuleText = useMemo(() => { |
| | | if (capsuleSites.length === 0) return ''; |
| | | return `去:${capsuleSites[0].name}`; |
| | | }, [capsuleSites]); |
| | | |
| | | // 游客态清空,非游客态拉取 |
| | | useEffect(() => { |
| | | if (deps.isGuest) { |
| | | clearQuickCapsule(); |
| | | return; |
| | | } |
| | | if (!effectiveStartPointId) { |
| | | clearQuickCapsule(); |
| | | return; |
| | | } |
| | | refreshQuickCapsule(effectiveStartPointId); |
| | | }, [deps.isGuest, effectiveStartPointId]); |
| | | |
| | | return { |
| | | capsuleSites, |
| | | quickCapsuleText, |
| | | showQuickCapsule: !!quickCapsuleText, |
| | | refreshQuickCapsule, |
| | | handleQuickCapsuleClick |
| | | }; |
| | | } |