hookehuyr

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>
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}&current_lat=${lat}&openid=${openid}` 114 + return `${baseUrl.value}${separator}current_lng=${lng}&current_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}&current_lat=${userLocation.value.lat}`, 583 + url: `/pages/Activities/index?current_lng=${userLocation.value.lng}&current_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 }
......