index.vue 5.36 KB
<template>
    <view class="activities-container">
        <!-- WebView内容 -->
        <web-view
            v-if="webUrl"
            :src="webUrl"
            class="web-view"
            @message="handleMessage"
            @load="handleLoad"
            @error="handleError"
        ></web-view>

        <!-- 加载状态 -->
        <view v-if="loading" class="loading-container">
            <view class="loading-spinner">⏳</view>
            <view class="loading-text">加载中...</view>
        </view>

        <!---but态 -->
        <view v-if="error" class="error-container">
            <view class="error-icon">⚠️</view>
            <view class="error-text">页面加载失败</view>
            <nut-button type="primary" size="small" @click="handleRetry">重试</nut-button>
        </view>

        <!-- 底部导航 -->
        <BottomNav />
    </view>
</template>

<script setup>
import { ref, onMounted } from 'vue'
import Taro from '@tarojs/taro'
import BottomNav from '../../components/BottomNav.vue'
// 获取接口信息
import { getUserProfileAPI } from '@/api/user'
import { getMapUrlAPI } from '@/api/map'

/**
 * 活动页面WebView组件
 * 用于显示活动相关的外部网页内容
 */

// 页面状态
const webUrl = ref('') // 动态设置URL
const loading = ref(true)
const error = ref(false)
const baseUrl = ref('') // 动态获取的基础URL

/**
 * 处理WebView加载完成
 */
const handleLoad = (e) => {
    console.log('WebView加载完成:', e)
    loading.value = false
    error.value = false
}

/**
 * 处理WebView加载错误
 */
const handleError = (e) => {
    console.error('WebView加载错误:', e)
    loading.value = false
    error.value = true

    Taro.showToast({
        title: '页面加载失败',
        icon: 'none'
    })
}

/**
 * 处理WebView消息
 */
const handleMessage = (e) => {
    console.log('WebView消息:', e)
    // 可以在这里处理来自WebView的消息
}

/**
 * 重试加载
 */
const handleRetry = () => {
    loading.value = true
    error.value = false
    // 重新设置URL触发重新加载
    const currentUrl = webUrl.value
    webUrl.value = ''
    setTimeout(() => {
        webUrl.value = currentUrl
    }, 100)
}

/**
 * 构建包含位置参数的URL
 */
const buildUrlWithLocation = (lng, lat, openid) => {
    if (lng && lat && baseUrl.value) {
        const separator = baseUrl.value.includes('?') ? '&' : '?'
        return `${baseUrl.value}${separator}current_lng=${lng}&current_lat=${lat}&openid=${openid}`
    }
    return baseUrl.value || ''
}

/**
 * 初始化页面数据
 */
const initPageData = async () => {
    try {
        // 获取地图URL
        const mapUrlResponse = await getMapUrlAPI()
        if (mapUrlResponse.code && mapUrlResponse.data?.url) {
            baseUrl.value = mapUrlResponse.data.url
            console.log('获取到的地图URL:', baseUrl.value)
        } else {
            console.error('获取地图URL失败:', mapUrlResponse.msg)
            // 使用默认URL作为备用
            baseUrl.value = 'https://oa.onwall.cn/f/map/#/checkin/?id=2400107'
        }

        // 获取用户信息
        const { code, data } = await getUserProfileAPI()
        if (code) {
            // 获取路由参数中的经纬度信息
            const instance = Taro.getCurrentInstance()
            const { current_lng, current_lat } = instance.router?.params || {}

            console.log('接收到的位置参数:', { current_lng, current_lat })
            // 处理用户信息
            const openid = data?.user.openid || ''
            // 构建完整的URL
            webUrl.value = buildUrlWithLocation(current_lng, current_lat, openid)

            console.log('最终WebView URL:', webUrl.value)
        }
    } catch (error) {
        console.error('初始化页面数据失败:', error)
        // 使用默认URL作为备用
        baseUrl.value = 'https://oa.onwall.cn/f/map/#/checkin/?id=2400107'
        
        Taro.showToast({
            title: '获取地图信息失败',
            icon: 'none'
        })
    }
}

// 页面挂载时初始化
onMounted(async () => {
    console.log('活动页面WebView初始化')
    await initPageData()
})
</script>

<style lang="less">
.activities-container {
    width: 100%;
    height: 100vh;
    display: flex;
    flex-direction: column;
    background-color: #fff;
    position: relative;
}

.web-view {
    flex: 1;
    width: 100%;
    // 确保webview高度在底部导航以上
    height: calc(100vh - 120rpx); // 减去底部导航的高度
}

.loading-container {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    z-index: 10;
}

.loading-spinner {
    font-size: 48rpx;
    margin-bottom: 16rpx;
    animation: spin 1s linear infinite;
}

.loading-text {
    font-size: 28rpx;
    color: #666;
}

@keyframes spin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
}

.error-container {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    z-index: 10;
}

.error-icon {
    font-size: 80rpx;
    margin-bottom: 24rpx;
}

.error-text {
    font-size: 28rpx;
    color: #666;
    margin-bottom: 32rpx;
}
</style>