| | |
| | | 'pages/user/index', |
| | | 'pages/user/login', |
| | | 'pages/map/index', |
| | | 'pages/robotaxi/home/index', |
| | | ]; |
| | | |
| | | subPackages = [ |
| | |
| | | // iconPath: './assets/tabbar/tab_icon_home.png', |
| | | // selectedIconPath: './assets/tabbar/tab_icon_home_act.png', |
| | | // }, |
| | | // { |
| | | // pagePath: 'pages/driveNew/index', |
| | | // text: '试驾', |
| | | // iconPath: './assets/tabbar/tab_icon_drive.png', |
| | | // selectedIconPath: './assets/tabbar/tab_icon_drive_act.png', |
| | | // }, |
| | | { |
| | | pagePath: 'pages/robotaxi/home/index', |
| | | text: 'Robotaxi', |
| | | iconPath: './assets/tabbar/tab_icon_drive.png', |
| | | selectedIconPath: './assets/tabbar/tab_icon_drive_act.png', |
| | | }, |
| | | { |
| | | pagePath: 'pages/xpeng/index', |
| | | text: '购车', |
| | |
| | | }, |
| | | debug: false, |
| | | resizable: false, |
| | | requiredBackgroundModes: [ 'audio' ], |
| | | requiredBackgroundModes: ['audio'], |
| | | permission: { |
| | | 'scope.userLocation': { |
| | | desc: '您的位置信息将用于定位就近的门店' |
| New file |
| | |
| | | .privacy-popup { |
| | | position: fixed; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | z-index: 99999; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | |
| | | .privacy-mask { |
| | | position: absolute; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | background: rgba(0, 0, 0, 0.5); |
| | | } |
| | | |
| | | .privacy-content { |
| | | position: relative; |
| | | background: #ffffff; |
| | | padding: 56px 40px 40px 40px; |
| | | border-radius: 32px; |
| | | margin: 0 75px; |
| | | |
| | | .title { |
| | | margin-bottom: 34px; |
| | | text-align: center; |
| | | font-size: 36px; |
| | | font-weight: bold; |
| | | line-height: 52px; |
| | | letter-spacing: normal; |
| | | color: rgba(0, 0, 0, 0.9); |
| | | } |
| | | |
| | | .privacy-text { |
| | | font-size: 28px; |
| | | font-weight: normal; |
| | | line-height: 48px; |
| | | letter-spacing: normal; |
| | | color: rgba(0, 0, 0, 0.9); |
| | | margin-bottom: 0; |
| | | |
| | | .txt-tip { |
| | | margin-top: 24px; |
| | | } |
| | | } |
| | | |
| | | .privacy-link { |
| | | margin-top: 16px; |
| | | |
| | | .link-item { |
| | | display: flex; |
| | | align-items: center; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .item-radio { |
| | | flex-shrink: 0; |
| | | width: 36px; |
| | | height: 36px; |
| | | margin-right: 14px; |
| | | } |
| | | |
| | | .item-name { |
| | | flex-shrink: 0; |
| | | font-size: 24px; |
| | | font-weight: normal; |
| | | line-height: 40px; |
| | | letter-spacing: normal; |
| | | color: rgba(0, 0, 0, 0.6); |
| | | } |
| | | } |
| | | |
| | | .agree-btn { |
| | | margin: 0 auto; |
| | | margin-top: 30px; |
| | | width: 472px; |
| | | text-align: center; |
| | | line-height: 96px; |
| | | border-radius: 16px; |
| | | background: linear-gradient(98deg, #8475FF 0%, #7DD6FF 103%); |
| | | font-size: 30px; |
| | | font-weight: normal; |
| | | letter-spacing: normal; |
| | | color: #FFFFFF; |
| | | } |
| | | |
| | | .close-txt { |
| | | text-align: center; |
| | | margin-top: 40px; |
| | | font-size: 28px; |
| | | font-weight: normal; |
| | | line-height: 48px; |
| | | letter-spacing: normal; |
| | | color: rgba(0, 0, 0, 0.6); |
| | | } |
| | | |
| | | } |
| | | } |
| New file |
| | |
| | | import Taro from '@tarojs/taro'; |
| | | import { View, Text, Image } from '@tarojs/components'; |
| | | import { useEffect, useState } from 'react'; |
| | | import './index.less'; |
| | | |
| | | type Props = { |
| | | show?: boolean; |
| | | onClose?: () => void; |
| | | onAgree?: () => void; |
| | | } |
| | | |
| | | export default function PrivacyPopup({ show = false, onClose, onAgree }: Props) { |
| | | const [visible, setVisible] = useState(false); |
| | | const [animationData, setAnimationData] = useState<any>(); |
| | | |
| | | useEffect(() => { |
| | | if (show && !visible) { |
| | | setVisible(true); |
| | | const animation = Taro.createAnimation({ |
| | | duration: 300, |
| | | timingFunction: 'ease-out' |
| | | }); |
| | | animation.translateY(0).step(); |
| | | setAnimationData(animation.export()); |
| | | } else if (!show && visible) { |
| | | const animation = Taro.createAnimation({ |
| | | duration: 300, |
| | | timingFunction: 'ease-in' |
| | | }); |
| | | animation.translateY(500).step(); |
| | | setAnimationData(animation.export()); |
| | | |
| | | setTimeout(() => { |
| | | setVisible(false); |
| | | }, 300); |
| | | } |
| | | }, [show]); |
| | | |
| | | const handleClose = () => { |
| | | onClose?.(); |
| | | }; |
| | | |
| | | const handleAgree = () => { |
| | | onAgree?.(); |
| | | }; |
| | | |
| | | const handleLinkClick = (url: string) => { |
| | | }; |
| | | |
| | | if (!visible) return null; |
| | | |
| | | return ( |
| | | <View className='privacy-popup' catchMove> |
| | | <View className='privacy-mask'></View> |
| | | <View className='privacy-content' animation={animationData}> |
| | | <View className='title'>用户协议与隐私政策</View> |
| | | |
| | | <View className='privacy-text'> |
| | | <Text className='text-content'> |
| | | 欢迎使用小鹏Robotaxi App!为了更好地保障您的个人权益,我们将通过 《用户服务协议》、《隐私政策》、以及《关于路Robotaxi平台向第三方提供个人信息情况的说明》、《关于关于路Robotaxi平台向第三方提供个人信息情况的说明》等文档来保护您的个人信息。 |
| | | </Text> |
| | | <View className='txt-tip'>我已满十四周岁,阅读并同意:</View> |
| | | </View> |
| | | |
| | | <View className='privacy-link'> |
| | | <View className='link-item'> |
| | | <Image className='item-radio' src={`https://s.xiaopeng.com/xp-fe/mini/common/xp-logo-circle-20250728.svg`} |
| | | mode='aspectFill' /> |
| | | <Text className='item-name'>《 用户服务协议 》</Text> |
| | | </View> |
| | | <View className='link-item'> |
| | | <Image className='item-radio' src={`https://s.xiaopeng.com/xp-fe/mini/common/xp-logo-circle-20250728.svg`} |
| | | mode='aspectFill' /> |
| | | <Text className='item-name'>《 小鹏Robotaxi 平台隐私政策 》</Text> |
| | | </View> |
| | | <View className='link-item'> |
| | | <Image className='item-radio' src={`https://s.xiaopeng.com/xp-fe/mini/common/xp-logo-circle-20250728.svg`} |
| | | mode='aspectFill' /> |
| | | <Text className='item-name'>《 小鹏Robotaxi 平台隐私政策 》</Text> |
| | | </View> |
| | | <View className='link-item'> |
| | | <Image className='item-radio' src={`https://s.xiaopeng.com/xp-fe/mini/common/xp-logo-circle-20250728.svg`} |
| | | mode='aspectFill' /> |
| | | <Text className='item-name'>《 小鹏Robotaxi 平台隐私政策 》</Text> |
| | | </View> |
| | | <View className='link-item'> |
| | | <Image className='item-radio' src={`https://s.xiaopeng.com/xp-fe/mini/common/xp-logo-circle-20250728.svg`} |
| | | mode='aspectFill' /> |
| | | <Text className='item-name'>全部勾选</Text> |
| | | </View> |
| | | </View> |
| | | <View className='agree-btn' onClick={handleAgree}> |
| | | 同意并进入 |
| | | </View> |
| | | <View className='close-txt'>暂不同意,留在游客模式</View> |
| | | </View> |
| | | </View> |
| | | ) |
| | | } |
| New file |
| | |
| | | import Taro from "@tarojs/taro" |
| | | |
| | | export const privacyUrls = { |
| | | userPrivacy: 'https://events.xiaopeng.com/3b1695.html?ch=00977&ps=event', |
| | | userAgreement: 'https://events.xiaopeng.com/nx9w4x.html?ch=00977&ps=event', |
| | | } |
| | | |
| | | export const checkIsPrivicyPage = (url: string) => { |
| | | return Object.values(privacyUrls).includes(url) |
| | | } |
| | | |
| | | const STORAGE_KEY = 'has_show_privicy_v1' |
| | | export const privicyShowManager = { |
| | | getHasShow: () => { |
| | | try { |
| | | return Taro.getStorageSync(STORAGE_KEY) === 'true' |
| | | } catch (e) { |
| | | console.error('获取隐私弹窗显示状态失败', e) |
| | | return false |
| | | } |
| | | }, |
| | | |
| | | setHasShow: (_hasShow) => { |
| | | try { |
| | | Taro.setStorageSync(STORAGE_KEY, _hasShow ? 'true' : 'false') |
| | | } catch (e) { |
| | | console.error('设置隐私弹窗显示状态失败', e) |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | export default { |
| | | navigationStyle: "custom" |
| | | }; |
| New file |
| | |
| | | .demo { |
| | | text-align: center; |
| | | } |
| New file |
| | |
| | | import { useEffect, useState } from 'react'; |
| | | import { View } from '@tarojs/components'; |
| | | import './index.less'; |
| | | import PrivacyPopup from '../components/privacy-popup'; |
| | | |
| | | export default function Home() { |
| | | |
| | | const [showPrivacy, setShowPrivacy] = useState(true); |
| | | |
| | | const handleClosePrivacy = () => { |
| | | setShowPrivacy(false); |
| | | }; |
| | | |
| | | const handleAgreePrivacy = () => { |
| | | // 处理用户同意逻辑 |
| | | console.log('用户同意了隐私政策'); |
| | | setShowPrivacy(false); |
| | | }; |
| | | |
| | | return ( |
| | | <View> |
| | | 11 |
| | | <PrivacyPopup |
| | | show={showPrivacy} |
| | | onClose={handleClosePrivacy} |
| | | onAgree={handleAgreePrivacy} |
| | | /> |
| | | </View> |
| | | ) |
| | | } |