fix(Activities): 优化活动详情展示和参数传递
- CheckinMap: 添加日期格式化函数,将 YYYY-MM-DD 转换为 YYYY.MM.DD 格式 - ActivitiesDetail: 添加 discount_title 字段支持,并在跳转时传递该参数 - Activities: 接收并处理 discount_title 参数,构建完整的活动 URL Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Showing
3 changed files
with
176 additions
and
153 deletions
| 1 | <template> | 1 | <template> |
| 2 | - <view class="activities-container"> | 2 | + <view class="activities-container"> |
| 3 | - <!-- WebView内容 --> | 3 | + <!-- WebView内容 --> |
| 4 | - <web-view | 4 | + <web-view |
| 5 | - v-if="webUrl" | 5 | + v-if="webUrl" |
| 6 | - :src="webUrl" | 6 | + :src="webUrl" |
| 7 | - class="web-view" | 7 | + class="web-view" |
| 8 | - @message="handleMessage" | 8 | + @message="handleMessage" |
| 9 | - @load="handleLoad" | 9 | + @load="handleLoad" |
| 10 | - @error="handleError" | 10 | + @error="handleError" |
| 11 | - ></web-view> | 11 | + ></web-view> |
| 12 | - | 12 | + |
| 13 | - <!-- 加载状态 --> | 13 | + <!-- 加载状态 --> |
| 14 | - <view v-if="loading" class="loading-container"> | 14 | + <view v-if="loading" class="loading-container"> |
| 15 | - <view class="loading-spinner">⏳</view> | 15 | + <view class="loading-spinner">⏳</view> |
| 16 | - <view class="loading-text">加载中...</view> | 16 | + <view class="loading-text">加载中...</view> |
| 17 | - </view> | ||
| 18 | - | ||
| 19 | - <!-- 错误状态 --> | ||
| 20 | - <view v-if="error" class="error-container"> | ||
| 21 | - <view class="error-icon">⚠️</view> | ||
| 22 | - <view class="error-text">页面加载失败</view> | ||
| 23 | - <view class="error-buttons"> | ||
| 24 | - <nut-button type="primary" size="small" @click="handleRetry">重试</nut-button> | ||
| 25 | - <nut-button type="default" size="small" @click="handleGoBack">返回</nut-button> | ||
| 26 | - </view> | ||
| 27 | - </view> | ||
| 28 | - | ||
| 29 | - <!-- 底部导航 --> | ||
| 30 | - <BottomNav /> | ||
| 31 | </view> | 17 | </view> |
| 18 | + | ||
| 19 | + <!-- 错误状态 --> | ||
| 20 | + <view v-if="error" class="error-container"> | ||
| 21 | + <view class="error-icon">⚠️</view> | ||
| 22 | + <view class="error-text">页面加载失败</view> | ||
| 23 | + <view class="error-buttons"> | ||
| 24 | + <nut-button type="primary" size="small" @click="handleRetry">重试</nut-button> | ||
| 25 | + <nut-button type="default" size="small" @click="handleGoBack">返回</nut-button> | ||
| 26 | + </view> | ||
| 27 | + </view> | ||
| 28 | + | ||
| 29 | + <!-- 底部导航 --> | ||
| 30 | + <BottomNav /> | ||
| 31 | + </view> | ||
| 32 | </template> | 32 | </template> |
| 33 | 33 | ||
| 34 | <script setup> | 34 | <script setup> |
| ... | @@ -53,198 +53,202 @@ const baseUrl = ref('') // 动态获取的基础URL | ... | @@ -53,198 +53,202 @@ const baseUrl = ref('') // 动态获取的基础URL |
| 53 | /** | 53 | /** |
| 54 | * 处理WebView加载完成 | 54 | * 处理WebView加载完成 |
| 55 | */ | 55 | */ |
| 56 | -const handleLoad = (e) => { | 56 | +const handleLoad = e => { |
| 57 | - console.log('WebView加载完成:', e) | 57 | + console.log('WebView加载完成:', e) |
| 58 | - loading.value = false | 58 | + loading.value = false |
| 59 | - error.value = false | 59 | + error.value = false |
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | /** | 62 | /** |
| 63 | * 处理WebView加载错误 | 63 | * 处理WebView加载错误 |
| 64 | */ | 64 | */ |
| 65 | -const handleError = (e) => { | 65 | +const handleError = e => { |
| 66 | - console.error('WebView加载错误:', e) | 66 | + console.error('WebView加载错误:', e) |
| 67 | - loading.value = false | 67 | + loading.value = false |
| 68 | - error.value = true | 68 | + error.value = true |
| 69 | 69 | ||
| 70 | - Taro.showToast({ | 70 | + Taro.showToast({ |
| 71 | - title: '页面加载失败', | 71 | + title: '页面加载失败', |
| 72 | - icon: 'none' | 72 | + icon: 'none', |
| 73 | - }) | 73 | + }) |
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | /** | 76 | /** |
| 77 | * 处理WebView消息 | 77 | * 处理WebView消息 |
| 78 | */ | 78 | */ |
| 79 | -const handleMessage = (e) => { | 79 | +const handleMessage = e => { |
| 80 | - console.log('WebView消息:', e) | 80 | + console.log('WebView消息:', e) |
| 81 | - // 可以在这里处理来自WebView的消息 | 81 | + // 可以在这里处理来自WebView的消息 |
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | /** | 84 | /** |
| 85 | * 重试加载 | 85 | * 重试加载 |
| 86 | */ | 86 | */ |
| 87 | const handleRetry = () => { | 87 | const handleRetry = () => { |
| 88 | - loading.value = true | 88 | + loading.value = true |
| 89 | - error.value = false | 89 | + error.value = false |
| 90 | - // 重新初始化页面数据 | 90 | + // 重新初始化页面数据 |
| 91 | - initPageData() | 91 | + initPageData() |
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | /** | 94 | /** |
| 95 | * 返回上一页 | 95 | * 返回上一页 |
| 96 | */ | 96 | */ |
| 97 | const handleGoBack = () => { | 97 | const handleGoBack = () => { |
| 98 | - Taro.navigateBack({ | 98 | + Taro.navigateBack({ |
| 99 | - delta: 1 | 99 | + delta: 1, |
| 100 | - }).catch(() => { | 100 | + }).catch(() => { |
| 101 | - // 如果无法返回,则跳转到首页 | 101 | + // 如果无法返回,则跳转到首页 |
| 102 | - Taro.redirectTo({ | 102 | + Taro.redirectTo({ |
| 103 | - url: '/pages/Dashboard/index' | 103 | + url: '/pages/Dashboard/index', |
| 104 | - }) | ||
| 105 | }) | 104 | }) |
| 105 | + }) | ||
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | /** | 108 | /** |
| 109 | * 构建包含位置参数的URL | 109 | * 构建包含位置参数的URL |
| 110 | */ | 110 | */ |
| 111 | -const buildUrlWithLocation = (lng, lat, openid) => { | 111 | +const buildUrlWithLocation = (lng, lat, openid, discount_title) => { |
| 112 | - if (lng && lat && baseUrl.value) { | 112 | + if (lng && lat && baseUrl.value) { |
| 113 | - const separator = baseUrl.value.includes('?') ? '&' : '?' | 113 | + const separator = baseUrl.value.includes('?') ? '&' : '?' |
| 114 | - return `${baseUrl.value}${separator}current_lng=${lng}¤t_lat=${lat}&openid=${openid}` | 114 | + return `${baseUrl.value}${separator}current_lng=${lng}¤t_lat=${lat}&openid=${openid}&discount_title=${discount_title}` |
| 115 | - } | 115 | + } |
| 116 | - return baseUrl.value || '' | 116 | + return baseUrl.value || '' |
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | /** | 119 | /** |
| 120 | * 初始化页面数据 | 120 | * 初始化页面数据 |
| 121 | */ | 121 | */ |
| 122 | const initPageData = async () => { | 122 | const initPageData = async () => { |
| 123 | - try { | 123 | + try { |
| 124 | - // 获取地图URL | 124 | + // 获取地图URL |
| 125 | - const mapUrlResponse = await getMapUrlAPI() | 125 | + const mapUrlResponse = await getMapUrlAPI() |
| 126 | - if (mapUrlResponse.code && mapUrlResponse.data?.url) { | 126 | + if (mapUrlResponse.code && mapUrlResponse.data?.url) { |
| 127 | - baseUrl.value = mapUrlResponse.data.url | 127 | + baseUrl.value = mapUrlResponse.data.url |
| 128 | - console.log('获取到的地图URL:', baseUrl.value) | 128 | + console.log('获取到的地图URL:', baseUrl.value) |
| 129 | - } else { | 129 | + } else { |
| 130 | - console.error('获取地图URL失败:', mapUrlResponse.msg) | 130 | + console.error('获取地图URL失败:', mapUrlResponse.msg) |
| 131 | - // 显示错误提示,不使用默认URL | 131 | + // 显示错误提示,不使用默认URL |
| 132 | - error.value = true | 132 | + error.value = true |
| 133 | - loading.value = false | 133 | + loading.value = false |
| 134 | - Taro.showToast({ | 134 | + Taro.showToast({ |
| 135 | - title: mapUrlResponse.msg || '获取地图信息失败', | 135 | + title: mapUrlResponse.msg || '获取地图信息失败', |
| 136 | - icon: 'none' | 136 | + icon: 'none', |
| 137 | - }) | 137 | + }) |
| 138 | - return | 138 | + return |
| 139 | - } | ||
| 140 | - | ||
| 141 | - // 获取用户信息 | ||
| 142 | - const { code, data } = await getUserProfileAPI() | ||
| 143 | - if (code) { | ||
| 144 | - // 获取路由参数中的经纬度信息 | ||
| 145 | - const instance = Taro.getCurrentInstance() | ||
| 146 | - const { current_lng, current_lat } = instance.router?.params || {} | ||
| 147 | - | ||
| 148 | - console.log('接收到的位置参数:', { current_lng, current_lat }) | ||
| 149 | - // 处理用户信息 | ||
| 150 | - const openid = data?.user.openid || '' | ||
| 151 | - // 构建完整的URL | ||
| 152 | - webUrl.value = buildUrlWithLocation(current_lng, current_lat, openid) | ||
| 153 | - | ||
| 154 | - console.log('最终WebView URL:', webUrl.value) | ||
| 155 | - } | ||
| 156 | - } catch (error) { | ||
| 157 | - console.error('初始化页面数据失败:', error) | ||
| 158 | - // 显示错误状态,不使用默认URL | ||
| 159 | - error.value = true | ||
| 160 | - loading.value = false | ||
| 161 | - | ||
| 162 | - Taro.showToast({ | ||
| 163 | - title: '获取地图信息失败', | ||
| 164 | - icon: 'none' | ||
| 165 | - }) | ||
| 166 | } | 139 | } |
| 140 | + | ||
| 141 | + // 获取用户信息 | ||
| 142 | + const { code, data } = await getUserProfileAPI() | ||
| 143 | + if (code) { | ||
| 144 | + // 获取路由参数中的经纬度信息 | ||
| 145 | + const instance = Taro.getCurrentInstance() | ||
| 146 | + const { current_lng, current_lat, discount_title } = instance.router?.params || {} | ||
| 147 | + | ||
| 148 | + console.log('接收到的位置参数:', { current_lng, current_lat, discount_title }) | ||
| 149 | + // 处理用户信息 | ||
| 150 | + const openid = data?.user.openid || '' | ||
| 151 | + // 构建完整的URL | ||
| 152 | + webUrl.value = buildUrlWithLocation(current_lng, current_lat, openid, discount_title) | ||
| 153 | + | ||
| 154 | + console.log('最终WebView URL:', webUrl.value) | ||
| 155 | + } | ||
| 156 | + } catch (error) { | ||
| 157 | + console.error('初始化页面数据失败:', error) | ||
| 158 | + // 显示错误状态,不使用默认URL | ||
| 159 | + error.value = true | ||
| 160 | + loading.value = false | ||
| 161 | + | ||
| 162 | + Taro.showToast({ | ||
| 163 | + title: '获取地图信息失败', | ||
| 164 | + icon: 'none', | ||
| 165 | + }) | ||
| 166 | + } | ||
| 167 | } | 167 | } |
| 168 | 168 | ||
| 169 | // 页面挂载时初始化 | 169 | // 页面挂载时初始化 |
| 170 | onMounted(async () => { | 170 | onMounted(async () => { |
| 171 | - console.log('活动页面WebView初始化') | 171 | + console.log('活动页面WebView初始化') |
| 172 | - await initPageData() | 172 | + await initPageData() |
| 173 | }) | 173 | }) |
| 174 | </script> | 174 | </script> |
| 175 | 175 | ||
| 176 | <style lang="less"> | 176 | <style lang="less"> |
| 177 | .activities-container { | 177 | .activities-container { |
| 178 | - width: 100%; | 178 | + width: 100%; |
| 179 | - height: 100vh; | 179 | + height: 100vh; |
| 180 | - display: flex; | 180 | + display: flex; |
| 181 | - flex-direction: column; | 181 | + flex-direction: column; |
| 182 | - background-color: #fff; | 182 | + background-color: #fff; |
| 183 | - position: relative; | 183 | + position: relative; |
| 184 | } | 184 | } |
| 185 | 185 | ||
| 186 | .web-view { | 186 | .web-view { |
| 187 | - flex: 1; | 187 | + flex: 1; |
| 188 | - width: 100%; | 188 | + width: 100%; |
| 189 | - // 确保webview高度在底部导航以上 | 189 | + // 确保webview高度在底部导航以上 |
| 190 | - height: calc(100vh - 120rpx); // 减去底部导航的高度 | 190 | + height: calc(100vh - 120rpx); // 减去底部导航的高度 |
| 191 | } | 191 | } |
| 192 | 192 | ||
| 193 | .loading-container { | 193 | .loading-container { |
| 194 | - position: absolute; | 194 | + position: absolute; |
| 195 | - top: 50%; | 195 | + top: 50%; |
| 196 | - left: 50%; | 196 | + left: 50%; |
| 197 | - transform: translate(-50%, -50%); | 197 | + transform: translate(-50%, -50%); |
| 198 | - display: flex; | 198 | + display: flex; |
| 199 | - flex-direction: column; | 199 | + flex-direction: column; |
| 200 | - align-items: center; | 200 | + align-items: center; |
| 201 | - justify-content: center; | 201 | + justify-content: center; |
| 202 | - z-index: 10; | 202 | + z-index: 10; |
| 203 | } | 203 | } |
| 204 | 204 | ||
| 205 | .loading-spinner { | 205 | .loading-spinner { |
| 206 | - font-size: 48rpx; | 206 | + font-size: 48rpx; |
| 207 | - margin-bottom: 16rpx; | 207 | + margin-bottom: 16rpx; |
| 208 | - animation: spin 1s linear infinite; | 208 | + animation: spin 1s linear infinite; |
| 209 | } | 209 | } |
| 210 | 210 | ||
| 211 | .loading-text { | 211 | .loading-text { |
| 212 | - font-size: 28rpx; | 212 | + font-size: 28rpx; |
| 213 | - color: #666; | 213 | + color: #666; |
| 214 | } | 214 | } |
| 215 | 215 | ||
| 216 | @keyframes spin { | 216 | @keyframes spin { |
| 217 | - 0% { transform: rotate(0deg); } | 217 | + 0% { |
| 218 | - 100% { transform: rotate(360deg); } | 218 | + transform: rotate(0deg); |
| 219 | + } | ||
| 220 | + 100% { | ||
| 221 | + transform: rotate(360deg); | ||
| 222 | + } | ||
| 219 | } | 223 | } |
| 220 | 224 | ||
| 221 | .error-container { | 225 | .error-container { |
| 222 | - position: absolute; | 226 | + position: absolute; |
| 223 | - top: 50%; | 227 | + top: 50%; |
| 224 | - left: 50%; | 228 | + left: 50%; |
| 225 | - transform: translate(-50%, -50%); | 229 | + transform: translate(-50%, -50%); |
| 226 | - display: flex; | 230 | + display: flex; |
| 227 | - flex-direction: column; | 231 | + flex-direction: column; |
| 228 | - align-items: center; | 232 | + align-items: center; |
| 229 | - justify-content: center; | 233 | + justify-content: center; |
| 230 | - text-align: center; | 234 | + text-align: center; |
| 231 | - z-index: 10; | 235 | + z-index: 10; |
| 232 | } | 236 | } |
| 233 | 237 | ||
| 234 | .error-icon { | 238 | .error-icon { |
| 235 | - font-size: 80rpx; | 239 | + font-size: 80rpx; |
| 236 | - margin-bottom: 24rpx; | 240 | + margin-bottom: 24rpx; |
| 237 | } | 241 | } |
| 238 | 242 | ||
| 239 | .error-text { | 243 | .error-text { |
| 240 | - font-size: 28rpx; | 244 | + font-size: 28rpx; |
| 241 | - color: #666; | 245 | + color: #666; |
| 242 | - margin-bottom: 32rpx; | 246 | + margin-bottom: 32rpx; |
| 243 | } | 247 | } |
| 244 | 248 | ||
| 245 | .error-buttons { | 249 | .error-buttons { |
| 246 | - display: flex; | 250 | + display: flex; |
| 247 | - gap: 24rpx; | 251 | + gap: 24rpx; |
| 248 | - align-items: center; | 252 | + align-items: center; |
| 249 | } | 253 | } |
| 250 | </style> | 254 | </style> | ... | ... |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2026-02-09 | 2 | * @Date: 2026-02-09 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2026-02-09 | 4 | + * @LastEditTime: 2026-02-09 18:55:56 |
| 5 | * @FilePath: /lls_program/src/pages/ActivitiesDetail/index.vue | 5 | * @FilePath: /lls_program/src/pages/ActivitiesDetail/index.vue |
| 6 | * @Description: 活动详情页面 - 完全使用 map_activity.js 新接口,支持多活动详情展示 | 6 | * @Description: 活动详情页面 - 完全使用 map_activity.js 新接口,支持多活动详情展示 |
| 7 | --> | 7 | --> |
| ... | @@ -580,7 +580,7 @@ const handleJoinActivity = async () => { | ... | @@ -580,7 +580,7 @@ const handleJoinActivity = async () => { |
| 580 | 580 | ||
| 581 | // 跳转到Activities页面,并传递位置参数 | 581 | // 跳转到Activities页面,并传递位置参数 |
| 582 | await Taro.navigateTo({ | 582 | await Taro.navigateTo({ |
| 583 | - url: `/pages/Activities/index?current_lng=${userLocation.value.lng}¤t_lat=${userLocation.value.lat}`, | 583 | + url: `/pages/Activities/index?current_lng=${userLocation.value.lng}¤t_lat=${userLocation.value.lat}&discount_title=${activityData.value.discount_title}`, |
| 584 | }) | 584 | }) |
| 585 | } catch (error) { | 585 | } catch (error) { |
| 586 | console.error('参加活动失败:', error) | 586 | console.error('参加活动失败:', error) |
| ... | @@ -971,6 +971,7 @@ const transformApiDataToActivityData = apiData => { | ... | @@ -971,6 +971,7 @@ const transformApiDataToActivityData = apiData => { |
| 971 | description: `欢迎参加${apiData.title}活动!`, | 971 | description: `欢迎参加${apiData.title}活动!`, |
| 972 | rules: rules, | 972 | rules: rules, |
| 973 | rewards: rewards, | 973 | rewards: rewards, |
| 974 | + discount_title: apiData.discount_title || '打卡点专属优惠', | ||
| 974 | } | 975 | } |
| 975 | } | 976 | } |
| 976 | 977 | ... | ... |
| ... | @@ -55,6 +55,23 @@ const mapList = ref([]) | ... | @@ -55,6 +55,23 @@ const mapList = ref([]) |
| 55 | const loading = ref(false) | 55 | const loading = ref(false) |
| 56 | 56 | ||
| 57 | /** | 57 | /** |
| 58 | + * 格式化日期显示 | ||
| 59 | + * @description 将后端返回的 YYYY-MM-DD 格式转换为 YYYY.MM.DD 格式 | ||
| 60 | + * @param {string} dateStr - 原始日期字符串(如 "2026-02-28") | ||
| 61 | + * @returns {string} 格式化后的日期(如 "2026.02.28") | ||
| 62 | + * | ||
| 63 | + * @example | ||
| 64 | + * formatDate("2026-02-28") // 返回 "2026.02.28" | ||
| 65 | + */ | ||
| 66 | +const formatDate = dateStr => { | ||
| 67 | + if (!dateStr) { | ||
| 68 | + return '' | ||
| 69 | + } | ||
| 70 | + // 将 "-" 替换为 "." | ||
| 71 | + return dateStr.replace(/-/g, '.') | ||
| 72 | +} | ||
| 73 | + | ||
| 74 | +/** | ||
| 58 | * 格式化 API 数据为页面所需格式 | 75 | * 格式化 API 数据为页面所需格式 |
| 59 | * @param {Array} list - API 返回的活动列表 | 76 | * @param {Array} list - API 返回的活动列表 |
| 60 | * @returns {Array} 格式化后的活动列表 | 77 | * @returns {Array} 格式化后的活动列表 |
| ... | @@ -65,7 +82,8 @@ const formatMapList = list => { | ... | @@ -65,7 +82,8 @@ const formatMapList = list => { |
| 65 | title: item.title, | 82 | title: item.title, |
| 66 | // 如果 cover 为空,使用默认封面图 | 83 | // 如果 cover 为空,使用默认封面图 |
| 67 | cover: item.cover && item.cover.trim() !== '' ? item.cover : DEFAULT_COVER, | 84 | cover: item.cover && item.cover.trim() !== '' ? item.cover : DEFAULT_COVER, |
| 68 | - timeRange: `${item.begin_date}~${item.end_date}`, | 85 | + // 格式化日期:2026-02-28 → 2026.02.28 |
| 86 | + timeRange: `${formatDate(item.begin_date)}~${formatDate(item.end_date)}`, | ||
| 69 | activityId: item.id, | 87 | activityId: item.id, |
| 70 | })) | 88 | })) |
| 71 | } | 89 | } | ... | ... |
-
Please register or login to post a comment