2025-07-11 15:41:48 +08:00
|
|
|
|
<template>
|
|
|
|
|
<view class="limo-mobile">
|
|
|
|
|
<!-- 首页内容 -->
|
|
|
|
|
<view v-if="currentPage === 'home'">
|
|
|
|
|
<!-- Header with logo and energy button -->
|
|
|
|
|
<view class="header">
|
|
|
|
|
<view class="header-content">
|
|
|
|
|
<image :src="logoSrc" class="logo" mode="aspectFit" />
|
|
|
|
|
<!-- <view class="energy-button" @click="goToMSpace">
|
|
|
|
|
<text class="energy-icon">⚡</text>
|
|
|
|
|
</view> -->
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<!-- Navigation Tabs -->
|
|
|
|
|
<view class="nav-tabs">
|
|
|
|
|
<view class="tab-item active">
|
|
|
|
|
<text class="tab-text">发现</text>
|
|
|
|
|
<view class="tab-underline"></view>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="tab-item">
|
|
|
|
|
<text class="tab-text">关注</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<!-- Sports Categories -->
|
|
|
|
|
<view class="sports-section">
|
|
|
|
|
<view class="sports-container">
|
|
|
|
|
<view class="sport-item all-category" :class="{ active: selectedSport === 'all' }" @tap="selectSport('all')">
|
|
|
|
|
<view class="category-content">
|
|
|
|
|
<text class="category-text">全部</text>
|
|
|
|
|
<text class="category-text">项目</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="sport-item" :class="{ active: selectedSport === 'basketball' }" @tap="selectSport('basketball')">
|
|
|
|
|
<view class="sport-icon-container basketball">
|
|
|
|
|
<text class="sport-emoji">🏀</text>
|
|
|
|
|
</view>
|
|
|
|
|
<text class="sport-label">篮球</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="sport-item" :class="{ active: selectedSport === 'football' }" @tap="selectSport('football')">
|
|
|
|
|
<view class="sport-icon-container football">
|
|
|
|
|
<text class="sport-emoji">⚽</text>
|
|
|
|
|
</view>
|
|
|
|
|
<text class="sport-label">足球</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="sport-item" :class="{ active: selectedSport === 'tennis' }" @tap="selectSport('tennis')">
|
|
|
|
|
<view class="sport-icon-container tennis">
|
|
|
|
|
<text class="sport-emoji">🎾</text>
|
|
|
|
|
</view>
|
|
|
|
|
<text class="sport-label">网球</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<!-- Location Bar -->
|
|
|
|
|
<view class="location-bar">
|
|
|
|
|
<view class="location-content">
|
|
|
|
|
<text class="location-pin">📍</text>
|
2025-07-11 18:28:43 +08:00
|
|
|
|
<text class="location-text" :class="{ 'location-loading': locationLoading }">{{ currentLocation.address }}</text>
|
|
|
|
|
<text class="location-switch" @tap="switchLocation">{{ locationLoading ? '定位中' : (currentLocation.address.includes('请选择') ? '选择' : '切换') }}</text>
|
2025-07-11 15:41:48 +08:00
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
|
2025-07-11 18:28:43 +08:00
|
|
|
|
<!-- 根据定位状态显示不同内容 -->
|
|
|
|
|
<!-- 定位中状态 -->
|
|
|
|
|
<view v-if="locationLoading" class="location-status-section">
|
|
|
|
|
<view class="status-container">
|
|
|
|
|
<view class="loading-spinner"></view>
|
|
|
|
|
<text class="status-title">正在定位</text>
|
|
|
|
|
<text class="status-subtitle">获取您的位置信息,为您推荐附近场馆</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<!-- 选择位置状态 -->
|
|
|
|
|
<view v-else-if="locationError" class="location-status-section">
|
|
|
|
|
<view class="status-container">
|
|
|
|
|
<text class="status-icon">📍</text>
|
|
|
|
|
<text class="status-title">选择您的位置</text>
|
|
|
|
|
<text class="status-subtitle">在地图上选择位置,为您推荐附近的运动场馆</text>
|
|
|
|
|
<view class="retry-button" @tap="chooseLocationOnMap">
|
|
|
|
|
<text class="retry-text">在地图上选择</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<!-- 定位成功,显示场馆列表 -->
|
|
|
|
|
<view v-else-if="locationReady" class="venue-section">
|
2025-07-11 15:41:48 +08:00
|
|
|
|
<!-- Timeline -->
|
|
|
|
|
<view class="timeline-container">
|
|
|
|
|
<view class="timeline-line"></view>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<!-- First Venue -->
|
|
|
|
|
<view class="venue-card">
|
|
|
|
|
<view class="timeline-dot active"></view>
|
|
|
|
|
<view class="venue-meta">
|
|
|
|
|
<text class="distance">120km</text>
|
|
|
|
|
<text class="separator"></text>
|
|
|
|
|
<view class="update-time">
|
|
|
|
|
<text class="clock-icon">🕐</text>
|
|
|
|
|
<text class="time-text">2分钟前更新</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="venue-content">
|
|
|
|
|
<view class="venue-image">
|
|
|
|
|
<view class="image-placeholder ronin-bg">
|
|
|
|
|
<text class="placeholder-text">RONIN篮球馆</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="play-overlay" @tap="playVideo">
|
|
|
|
|
<view class="play-button">
|
|
|
|
|
<text class="play-icon">▶</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="live-badge">
|
|
|
|
|
<view class="live-dot"></view>
|
|
|
|
|
<text class="live-text">直播中</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="venue-info">
|
|
|
|
|
<view class="venue-header">
|
|
|
|
|
<view class="venue-logo ronin-logo">
|
|
|
|
|
<image :src="roninLogoSrc" class="venue-logo-image" mode="aspectFit" />
|
|
|
|
|
</view>
|
|
|
|
|
<view class="venue-details">
|
|
|
|
|
<text class="venue-name">RONIN黄金篮球馆</text>
|
|
|
|
|
<text class="venue-address">杭州拱墅区黑马路124号(肯德基对面)</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="venue-action">
|
|
|
|
|
<view class="zone-button" @tap="enterZone('ronin')">
|
|
|
|
|
<text class="button-text">进入ZONE</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<!-- Second Venue -->
|
|
|
|
|
<view class="venue-card">
|
|
|
|
|
<view class="timeline-dot"></view>
|
|
|
|
|
<view class="venue-meta">
|
|
|
|
|
<text class="distance">140km</text>
|
|
|
|
|
<text class="separator"></text>
|
|
|
|
|
<view class="update-time">
|
|
|
|
|
<text class="clock-icon">🕐</text>
|
|
|
|
|
<text class="time-text">5分钟前更新</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="venue-content">
|
|
|
|
|
<view class="venue-image">
|
|
|
|
|
<view class="image-placeholder panda-bg">
|
|
|
|
|
<text class="placeholder-text">Panda运动俱乐部</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="play-overlay" @tap="playVideo">
|
|
|
|
|
<view class="play-button">
|
|
|
|
|
<text class="play-icon">▶</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="live-badge">
|
|
|
|
|
<view class="live-dot"></view>
|
|
|
|
|
<text class="live-text">直播中</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="venue-info">
|
|
|
|
|
<view class="venue-header">
|
|
|
|
|
<view class="venue-logo panda-logo">
|
|
|
|
|
<text class="logo-text">P</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="venue-details">
|
|
|
|
|
<text class="venue-name">Panda惊怒熊猫运动俱乐部</text>
|
|
|
|
|
<text class="venue-address">杭州拱墅区黑马路124号(肯德基对面)</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="venue-action">
|
|
|
|
|
<view class="zone-button" @tap="enterZone('panda')">
|
|
|
|
|
<text class="button-text">进入ZONE</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<!-- 我的页面内容 -->
|
|
|
|
|
<view v-if="currentPage === 'profile'" class="profile-content">
|
|
|
|
|
<!-- User Profile Section -->
|
|
|
|
|
<view class="profile-section">
|
|
|
|
|
<view class="profile-card">
|
|
|
|
|
<view class="profile-header-info">
|
|
|
|
|
<view class="avatar-container">
|
|
|
|
|
<view class="avatar">
|
|
|
|
|
<text class="avatar-initial">U</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="online-status"></view>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="profile-info">
|
|
|
|
|
<view class="profile-name-row">
|
|
|
|
|
<text class="profile-name">用户昵称</text>
|
|
|
|
|
<view class="edit-icon" @tap="editProfile">
|
|
|
|
|
<text class="edit-text">✎</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
<text class="profile-id">ID: 123456789</text>
|
|
|
|
|
<view class="profile-stats">
|
|
|
|
|
<text class="stat-text">积分 2,580</text>
|
|
|
|
|
<view class="stat-divider"></view>
|
|
|
|
|
<text class="stat-text">等级 LV.8</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="member-card-button" @tap="openMemberBenefits">
|
|
|
|
|
<view class="card-background">
|
|
|
|
|
<view class="card-pattern"></view>
|
|
|
|
|
<view class="card-shine"></view>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="card-content">
|
|
|
|
|
<view class="card-left">
|
|
|
|
|
<view class="card-header">
|
|
|
|
|
<text class="card-title">LIMO</text>
|
|
|
|
|
<text class="card-subtitle">会员卡</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="card-info">
|
|
|
|
|
<text class="member-level">VIP黄金会员</text>
|
|
|
|
|
<text class="member-expiry">有效期至 2025.12.31</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="card-arrow">
|
|
|
|
|
<text class="arrow-icon">›</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<!-- Stats Cards -->
|
|
|
|
|
<view class="stats-section">
|
|
|
|
|
<view class="stats-grid">
|
2025-07-11 18:28:43 +08:00
|
|
|
|
<view class="stat-card" @tap="goToHistory">
|
2025-07-11 15:41:48 +08:00
|
|
|
|
<text class="stat-number">12</text>
|
2025-07-11 18:28:43 +08:00
|
|
|
|
<text class="stat-label">观看数量</text>
|
2025-07-11 15:41:48 +08:00
|
|
|
|
</view>
|
2025-07-11 18:28:43 +08:00
|
|
|
|
<view class="stat-card" @tap="goToFavorites">
|
2025-07-11 15:41:48 +08:00
|
|
|
|
<text class="stat-number">5</text>
|
|
|
|
|
<text class="stat-label">收藏场馆</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<!-- Menu Items -->
|
|
|
|
|
<view class="menu-section">
|
|
|
|
|
<view class="menu-card">
|
|
|
|
|
<view class="menu-item" @tap="goToFavorites">
|
|
|
|
|
<view class="menu-content">
|
2025-07-11 18:28:43 +08:00
|
|
|
|
<text class="menu-title">我的收藏</text>
|
2025-07-11 15:41:48 +08:00
|
|
|
|
</view>
|
|
|
|
|
<text class="menu-arrow">›</text>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<view class="menu-item" @tap="goToHistory">
|
|
|
|
|
<view class="menu-content">
|
|
|
|
|
<text class="menu-title">观看历史</text>
|
|
|
|
|
</view>
|
|
|
|
|
<text class="menu-arrow">›</text>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<view class="menu-item" @tap="goToNotifications">
|
|
|
|
|
<view class="menu-content">
|
|
|
|
|
<text class="menu-title">消息通知</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="menu-right">
|
|
|
|
|
<view class="notification-dot"></view>
|
|
|
|
|
<text class="menu-arrow">›</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
2025-07-11 18:28:43 +08:00
|
|
|
|
|
|
|
|
|
<view class="menu-item" @tap="goToOrders">
|
|
|
|
|
<view class="menu-content">
|
|
|
|
|
<text class="menu-title">我的订单</text>
|
|
|
|
|
</view>
|
|
|
|
|
<text class="menu-arrow">›</text>
|
|
|
|
|
</view>
|
2025-07-11 15:41:48 +08:00
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<!-- Recent Activity -->
|
|
|
|
|
<view class="activity-section">
|
|
|
|
|
<view class="activity-card">
|
|
|
|
|
<view class="activity-header">
|
|
|
|
|
<view class="activity-indicator"></view>
|
|
|
|
|
<text class="activity-title">最近活动</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="activity-list">
|
|
|
|
|
<view class="activity-item">
|
|
|
|
|
<view class="activity-content">
|
|
|
|
|
<text class="activity-title-text">观看了 RONIN黄金篮球馆</text>
|
|
|
|
|
<text class="activity-subtitle">2小时前 · 观看时长 45分钟</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="activity-item">
|
|
|
|
|
<view class="activity-content">
|
|
|
|
|
<text class="activity-title-text">收藏了 Panda惊怒熊猫运动俱乐部</text>
|
|
|
|
|
<text class="activity-subtitle">1天前</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
2025-07-11 18:28:43 +08:00
|
|
|
|
<view class="activity-more-link" @tap="goToActivityHistory">
|
|
|
|
|
<text class="more-link-text">查看历史活动</text>
|
|
|
|
|
</view>
|
2025-07-11 15:41:48 +08:00
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<!-- Bottom Spacing -->
|
|
|
|
|
<view class="bottom-spacing"></view>
|
|
|
|
|
|
|
|
|
|
<!-- Bottom Navigation -->
|
|
|
|
|
<view class="bottom-nav">
|
|
|
|
|
<view class="nav-item" :class="{ active: currentPage === 'home' }" @tap="goHome">
|
|
|
|
|
<view class="nav-icon-container" :class="{ 'home-active': currentPage === 'home' }">
|
|
|
|
|
<image :src="homeIcon" class="nav-icon-svg" mode="aspectFit" />
|
|
|
|
|
</view>
|
|
|
|
|
<text class="nav-label" :class="{ active: currentPage === 'home' }">首页</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="nav-item" :class="{ active: currentPage === 'profile' }" @tap="goProfile">
|
|
|
|
|
<view class="nav-icon-container" :class="{ 'profile-active': currentPage === 'profile' }">
|
|
|
|
|
<image :src="userIcon" class="nav-icon-svg" mode="aspectFit" />
|
|
|
|
|
</view>
|
|
|
|
|
<text class="nav-label" :class="{ active: currentPage === 'profile' }">我的</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
2025-07-11 18:28:43 +08:00
|
|
|
|
|
|
|
|
|
<!-- 授权弹窗 -->
|
|
|
|
|
<AuthModal
|
|
|
|
|
:visible="authModalVisible"
|
|
|
|
|
:auth-type="authType"
|
|
|
|
|
@close="closeAuthModal"
|
|
|
|
|
@success="onAuthSuccess"
|
|
|
|
|
@skip="onAuthSkip"
|
|
|
|
|
/>
|
2025-07-11 15:41:48 +08:00
|
|
|
|
</view>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
2025-07-11 18:28:43 +08:00
|
|
|
|
import { ref, onMounted, defineAsyncComponent } from 'vue'
|
2025-07-11 15:41:48 +08:00
|
|
|
|
import Taro from '@tarojs/taro'
|
2025-07-11 18:28:43 +08:00
|
|
|
|
// AuthModal 组件通过相对路径导入
|
|
|
|
|
const AuthModal = defineAsyncComponent(() => import('../../components/AuthModal/index.vue'))
|
2025-07-11 15:41:48 +08:00
|
|
|
|
import './index.scss'
|
|
|
|
|
|
|
|
|
|
// 静态资源
|
|
|
|
|
const logoSrc = 'https://wx-static.drip.im/img/limo/miniapp/logo.svg'
|
|
|
|
|
const homeIcon = require('@/assets/images/home.svg')
|
|
|
|
|
const userIcon = require('@/assets/images/user.svg')
|
|
|
|
|
const backIcon = require('@/assets/images/back.svg')
|
|
|
|
|
const roninLogoSrc = 'https://qiniu.drip.im/gh_09bd6126eab8/20250711/upload/4d0efe5313d38f0db01d0cfba4dac9d848bb43a2'
|
|
|
|
|
|
|
|
|
|
// 响应式状态
|
|
|
|
|
const selectedSport = ref('all')
|
|
|
|
|
const currentPage = ref('home') // 'home' | 'profile'
|
|
|
|
|
|
2025-07-11 18:28:43 +08:00
|
|
|
|
// 地理位置状态
|
|
|
|
|
const currentLocation = ref({
|
|
|
|
|
name: '定位中...',
|
|
|
|
|
address: '正在获取位置信息',
|
|
|
|
|
latitude: 0,
|
|
|
|
|
longitude: 0
|
|
|
|
|
})
|
|
|
|
|
const locationLoading = ref(false)
|
|
|
|
|
const locationReady = ref(false) // 位置信息是否已准备好
|
|
|
|
|
const locationError = ref(false) // 定位是否失败
|
|
|
|
|
|
|
|
|
|
// 授权弹窗状态
|
|
|
|
|
const authModalVisible = ref(false)
|
|
|
|
|
const authType = ref<'login' | 'video'>('login')
|
|
|
|
|
const isUserAuthorized = ref(false) // 用户是否已授权
|
|
|
|
|
|
2025-07-11 15:41:48 +08:00
|
|
|
|
// 方法
|
|
|
|
|
const selectSport = (sport: string) => {
|
|
|
|
|
selectedSport.value = sport
|
|
|
|
|
console.log('选择运动项目:', sport)
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-11 18:28:43 +08:00
|
|
|
|
// 位置存储相关方法
|
|
|
|
|
const saveLocationToStorage = (locationData: any) => {
|
|
|
|
|
try {
|
|
|
|
|
Taro.setStorageSync('userLocation', {
|
|
|
|
|
...locationData,
|
|
|
|
|
timestamp: Date.now() // 记录保存时间
|
|
|
|
|
})
|
|
|
|
|
console.log('位置信息已保存到本地存储:', locationData)
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('保存位置信息失败:', error)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const loadLocationFromStorage = () => {
|
|
|
|
|
try {
|
|
|
|
|
const savedLocation = Taro.getStorageSync('userLocation')
|
|
|
|
|
if (savedLocation && savedLocation.address) {
|
|
|
|
|
// 检查位置信息是否过期(7天有效期)
|
|
|
|
|
const sevenDaysInMs = 7 * 24 * 60 * 60 * 1000
|
|
|
|
|
const now = Date.now()
|
|
|
|
|
|
|
|
|
|
if (savedLocation.timestamp && (now - savedLocation.timestamp) < sevenDaysInMs) {
|
|
|
|
|
console.log('从本地存储加载位置信息:', savedLocation)
|
|
|
|
|
return savedLocation
|
|
|
|
|
} else {
|
|
|
|
|
console.log('位置信息已过期,清除本地存储')
|
|
|
|
|
clearLocationFromStorage()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('读取位置信息失败:', error)
|
|
|
|
|
}
|
|
|
|
|
return null
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const clearLocationFromStorage = () => {
|
|
|
|
|
try {
|
|
|
|
|
Taro.removeStorageSync('userLocation')
|
|
|
|
|
console.log('已清除本地存储的位置信息')
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('清除位置信息失败:', error)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-11 15:41:48 +08:00
|
|
|
|
const switchLocation = () => {
|
|
|
|
|
console.log('🔥 switchLocation 方法被调用!')
|
2025-07-11 18:28:43 +08:00
|
|
|
|
|
|
|
|
|
// 直接在地图上选择位置
|
|
|
|
|
chooseLocationOnMap()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 在地图上选择位置
|
|
|
|
|
const chooseLocationOnMap = () => {
|
|
|
|
|
Taro.chooseLocation({
|
2025-07-11 15:41:48 +08:00
|
|
|
|
success: (res) => {
|
2025-07-11 18:28:43 +08:00
|
|
|
|
console.log('选择位置成功:', res)
|
|
|
|
|
// 更新当前位置信息
|
|
|
|
|
const locationData = {
|
|
|
|
|
name: res.name || res.address,
|
|
|
|
|
address: res.address,
|
|
|
|
|
latitude: res.latitude,
|
|
|
|
|
longitude: res.longitude
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
currentLocation.value = locationData
|
|
|
|
|
|
|
|
|
|
// 保存位置信息到本地存储
|
|
|
|
|
saveLocationToStorage(locationData)
|
|
|
|
|
|
|
|
|
|
locationReady.value = true
|
|
|
|
|
locationError.value = false
|
|
|
|
|
|
|
|
|
|
Taro.showToast({
|
|
|
|
|
title: '位置已更新',
|
|
|
|
|
icon: 'success'
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
fail: (err) => {
|
|
|
|
|
console.error('选择位置失败:', err)
|
|
|
|
|
|
|
|
|
|
// 回到选择位置状态
|
|
|
|
|
locationReady.value = false
|
|
|
|
|
locationError.value = true
|
|
|
|
|
currentLocation.value = {
|
|
|
|
|
name: '未选择位置',
|
|
|
|
|
address: '请选择您的位置以查看附近场馆',
|
|
|
|
|
latitude: 0,
|
|
|
|
|
longitude: 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (err.errMsg.includes('auth')) {
|
|
|
|
|
Taro.showModal({
|
|
|
|
|
title: '授权提示',
|
|
|
|
|
content: '需要授权位置信息才能选择地点,是否前往设置?',
|
|
|
|
|
success: (modalRes) => {
|
|
|
|
|
if (modalRes.confirm) {
|
|
|
|
|
Taro.openSetting()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
} else if (!err.errMsg.includes('cancel')) {
|
|
|
|
|
// 只有在非取消的情况下才显示错误提示
|
|
|
|
|
Taro.showToast({
|
|
|
|
|
title: '选择位置失败',
|
|
|
|
|
icon: 'none'
|
|
|
|
|
})
|
|
|
|
|
}
|
2025-07-11 15:41:48 +08:00
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-11 18:28:43 +08:00
|
|
|
|
// 获取当前位置
|
|
|
|
|
const getCurrentLocation = (showToast = true, showLoading = false) => {
|
|
|
|
|
if (!locationLoading.value) {
|
|
|
|
|
locationLoading.value = true
|
|
|
|
|
}
|
|
|
|
|
locationReady.value = false
|
|
|
|
|
locationError.value = false
|
|
|
|
|
|
|
|
|
|
if (showLoading) {
|
|
|
|
|
Taro.showLoading({
|
|
|
|
|
title: '定位中...'
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Taro.getLocation({
|
|
|
|
|
type: 'gcj02', // 返回可以用于微信小程序的坐标
|
|
|
|
|
success: (res) => {
|
|
|
|
|
console.log('获取位置成功:', res)
|
|
|
|
|
|
|
|
|
|
// 简化处理:直接显示坐标信息,实际项目中可以调用逆地理编码API
|
|
|
|
|
const formattedAddress = `当前位置 (${res.latitude.toFixed(4)}, ${res.longitude.toFixed(4)})`
|
|
|
|
|
|
|
|
|
|
const locationData = {
|
|
|
|
|
name: '当前位置',
|
|
|
|
|
address: formattedAddress,
|
|
|
|
|
latitude: res.latitude,
|
|
|
|
|
longitude: res.longitude
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
currentLocation.value = locationData
|
|
|
|
|
|
|
|
|
|
// 保存位置信息到本地存储
|
|
|
|
|
saveLocationToStorage(locationData)
|
|
|
|
|
|
|
|
|
|
locationLoading.value = false
|
|
|
|
|
locationReady.value = true
|
|
|
|
|
locationError.value = false
|
|
|
|
|
|
|
|
|
|
if (showLoading) {
|
|
|
|
|
Taro.hideLoading()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (showToast) {
|
|
|
|
|
Taro.showToast({
|
|
|
|
|
title: '定位成功',
|
|
|
|
|
icon: 'success'
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
fail: (err) => {
|
|
|
|
|
locationLoading.value = false
|
|
|
|
|
locationReady.value = false
|
|
|
|
|
locationError.value = true
|
|
|
|
|
|
|
|
|
|
if (showLoading) {
|
|
|
|
|
Taro.hideLoading()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
console.error('获取位置失败:', err)
|
|
|
|
|
|
|
|
|
|
// 设置默认位置
|
|
|
|
|
currentLocation.value = {
|
|
|
|
|
name: '定位失败',
|
|
|
|
|
address: '无法获取位置信息,点击重试',
|
|
|
|
|
latitude: 0,
|
|
|
|
|
longitude: 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (err.errMsg.includes('auth')) {
|
|
|
|
|
Taro.showModal({
|
|
|
|
|
title: '授权提示',
|
|
|
|
|
content: '需要授权位置信息才能获取当前位置,是否前往设置?',
|
|
|
|
|
success: (modalRes) => {
|
|
|
|
|
if (modalRes.confirm) {
|
|
|
|
|
Taro.openSetting()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
} else {
|
|
|
|
|
if (showToast) {
|
|
|
|
|
Taro.showToast({
|
|
|
|
|
title: '定位失败',
|
|
|
|
|
icon: 'none'
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 选择收货地址
|
|
|
|
|
const chooseDeliveryAddress = () => {
|
|
|
|
|
Taro.chooseAddress({
|
|
|
|
|
success: (res) => {
|
|
|
|
|
console.log('选择地址成功:', res)
|
|
|
|
|
const fullAddress = `${res.provinceName}${res.cityName}${res.countyName}${res.detailInfo}`
|
|
|
|
|
const locationData = {
|
|
|
|
|
name: res.userName,
|
|
|
|
|
address: fullAddress,
|
|
|
|
|
latitude: 0, // 收货地址API不返回坐标
|
|
|
|
|
longitude: 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
currentLocation.value = locationData
|
|
|
|
|
|
|
|
|
|
// 保存位置信息到本地存储
|
|
|
|
|
saveLocationToStorage(locationData)
|
|
|
|
|
|
|
|
|
|
locationReady.value = true
|
|
|
|
|
locationError.value = false
|
|
|
|
|
|
|
|
|
|
Taro.showToast({
|
|
|
|
|
title: '地址已更新',
|
|
|
|
|
icon: 'success'
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
fail: (err) => {
|
|
|
|
|
console.error('选择地址失败:', err)
|
|
|
|
|
if (err.errMsg.includes('auth')) {
|
|
|
|
|
Taro.showModal({
|
|
|
|
|
title: '授权提示',
|
|
|
|
|
content: '需要授权地址信息才能选择收货地址,是否前往设置?',
|
|
|
|
|
success: (modalRes) => {
|
|
|
|
|
if (modalRes.confirm) {
|
|
|
|
|
Taro.openSetting()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
} else {
|
|
|
|
|
Taro.showToast({
|
|
|
|
|
title: '选择地址失败',
|
|
|
|
|
icon: 'none'
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-07-11 15:41:48 +08:00
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-11 18:28:43 +08:00
|
|
|
|
const playVideo = () => {
|
|
|
|
|
if (checkAuthRequired('video')) {
|
|
|
|
|
Taro.showToast({
|
|
|
|
|
title: '播放视频',
|
|
|
|
|
icon: 'none'
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-11 15:41:48 +08:00
|
|
|
|
const enterZone = (venueType: string) => {
|
|
|
|
|
Taro.navigateTo({
|
|
|
|
|
url: '/pages/zone/index?venue=' + venueType
|
|
|
|
|
}).then(() => {
|
|
|
|
|
console.log('✅ 成功跳转到zone页面')
|
|
|
|
|
}).catch((err) => {
|
|
|
|
|
console.error('❌ 跳转失败:', err)
|
|
|
|
|
Taro.showToast({
|
|
|
|
|
title: '跳转失败',
|
|
|
|
|
icon: 'none'
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 页面切换方法
|
|
|
|
|
const switchToHome = () => {
|
|
|
|
|
currentPage.value = 'home'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const switchToProfile = () => {
|
|
|
|
|
currentPage.value = 'profile'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 导航方法
|
|
|
|
|
const goHome = () => {
|
|
|
|
|
currentPage.value = 'home'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const goProfile = () => {
|
2025-07-11 18:28:43 +08:00
|
|
|
|
if (checkAuthRequired('login')) {
|
|
|
|
|
currentPage.value = 'profile'
|
|
|
|
|
}
|
2025-07-11 15:41:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 我的页面功能方法
|
|
|
|
|
const editProfile = () => {
|
|
|
|
|
Taro.showToast({
|
|
|
|
|
title: '编辑用户信息功能开发中',
|
|
|
|
|
icon: 'none'
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const openMemberBenefits = () => {
|
|
|
|
|
Taro.navigateTo({
|
|
|
|
|
url: '/pages/vip/index'
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const goToVip = () => {
|
|
|
|
|
Taro.navigateTo({
|
|
|
|
|
url: '/pages/vip/index'
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const goToFavorites = () => {
|
2025-07-11 18:28:43 +08:00
|
|
|
|
Taro.navigateTo({
|
|
|
|
|
url: '/pages/favorites/index'
|
2025-07-11 15:41:48 +08:00
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const goToHistory = () => {
|
2025-07-11 18:28:43 +08:00
|
|
|
|
Taro.navigateTo({
|
|
|
|
|
url: '/pages/history/index'
|
2025-07-11 15:41:48 +08:00
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const goToAddress = () => {
|
|
|
|
|
Taro.showToast({
|
|
|
|
|
title: '常用地址',
|
|
|
|
|
icon: 'none'
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const goToNotifications = () => {
|
2025-07-11 18:28:43 +08:00
|
|
|
|
Taro.navigateTo({
|
|
|
|
|
url: '/pages/notifications/index'
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const goToOrders = () => {
|
|
|
|
|
Taro.navigateTo({
|
|
|
|
|
url: '/pages/orders/index'
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const goToActivityHistory = () => {
|
|
|
|
|
Taro.navigateTo({
|
|
|
|
|
url: '/pages/activity/index'
|
2025-07-11 15:41:48 +08:00
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const goToPrivacy = () => {
|
|
|
|
|
Taro.showToast({
|
|
|
|
|
title: '隐私设置',
|
|
|
|
|
icon: 'none'
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-11 18:28:43 +08:00
|
|
|
|
// 授权相关方法
|
|
|
|
|
const showAuthModal = (type: 'login' | 'video') => {
|
|
|
|
|
authType.value = type
|
|
|
|
|
authModalVisible.value = true
|
|
|
|
|
}
|
2025-07-11 15:41:48 +08:00
|
|
|
|
|
2025-07-11 18:28:43 +08:00
|
|
|
|
const closeAuthModal = () => {
|
|
|
|
|
authModalVisible.value = false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const onAuthSuccess = (data: { phone?: string, userInfo?: any }) => {
|
|
|
|
|
console.log('授权成功:', data)
|
|
|
|
|
isUserAuthorized.value = true
|
|
|
|
|
|
|
|
|
|
// 更新用户信息到本地存储
|
|
|
|
|
if (data.phone) {
|
|
|
|
|
Taro.setStorageSync('userPhone', data.phone)
|
|
|
|
|
}
|
|
|
|
|
if (data.userInfo) {
|
|
|
|
|
Taro.setStorageSync('userInfo', data.userInfo)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Taro.showToast({
|
|
|
|
|
title: '授权成功',
|
|
|
|
|
icon: 'success'
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const onAuthSkip = () => {
|
|
|
|
|
console.log('用户跳过授权')
|
|
|
|
|
// 可以记录用户跳过授权的行为
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 检查是否需要授权
|
|
|
|
|
const checkAuthRequired = (action: 'login' | 'video') => {
|
|
|
|
|
// 检查本地是否有授权信息
|
|
|
|
|
const hasPhone = Taro.getStorageSync('userPhone')
|
|
|
|
|
const hasUserInfo = Taro.getStorageSync('userInfo')
|
|
|
|
|
|
|
|
|
|
if (!hasPhone || !hasUserInfo) {
|
|
|
|
|
showAuthModal(action)
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
isUserAuthorized.value = true
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 注意: playVideo 和 goProfile 方法在下面已有定义,这里只是添加了授权检查逻辑
|
2025-07-11 15:41:48 +08:00
|
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
console.log('LIMO来刻首页已加载')
|
|
|
|
|
console.log('Vue组件已挂载,方法可用')
|
2025-07-11 18:28:43 +08:00
|
|
|
|
|
|
|
|
|
// 检查用户授权状态
|
|
|
|
|
const hasPhone = Taro.getStorageSync('userPhone')
|
|
|
|
|
const hasUserInfo = Taro.getStorageSync('userInfo')
|
|
|
|
|
if (hasPhone && hasUserInfo) {
|
|
|
|
|
isUserAuthorized.value = true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 尝试从本地存储加载位置信息
|
|
|
|
|
const savedLocation = loadLocationFromStorage()
|
|
|
|
|
|
|
|
|
|
if (savedLocation) {
|
|
|
|
|
// 如果有保存的位置信息,直接使用
|
|
|
|
|
currentLocation.value = {
|
|
|
|
|
name: savedLocation.name,
|
|
|
|
|
address: savedLocation.address,
|
|
|
|
|
latitude: savedLocation.latitude,
|
|
|
|
|
longitude: savedLocation.longitude
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
locationLoading.value = false
|
|
|
|
|
locationReady.value = true
|
|
|
|
|
locationError.value = false
|
|
|
|
|
|
|
|
|
|
console.log('使用已保存的位置信息')
|
|
|
|
|
} else {
|
|
|
|
|
// 如果没有保存的位置信息,显示选择位置引导
|
|
|
|
|
locationLoading.value = false
|
|
|
|
|
locationReady.value = false
|
|
|
|
|
locationError.value = true
|
|
|
|
|
|
|
|
|
|
currentLocation.value = {
|
|
|
|
|
name: '未选择位置',
|
|
|
|
|
address: '请选择您的位置以查看附近场馆',
|
|
|
|
|
latitude: 0,
|
|
|
|
|
longitude: 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
console.log('未找到保存的位置信息,显示选择引导')
|
|
|
|
|
}
|
2025-07-11 15:41:48 +08:00
|
|
|
|
})
|
|
|
|
|
</script>
|