hookehuyr

feat(海报打卡): 添加加载状态和错误处理,集成API获取海报数据

实现海报打卡页面的加载状态和错误处理逻辑
集成API获取海报详情数据并更新页面状态
添加重新加载功能,优化用户体验
处理海报背景图片上传和保存逻辑
1 <template> 1 <template>
2 <view class="poster-checkin-page bg-gray-50 h-screen flex flex-col"> 2 <view class="poster-checkin-page bg-gray-50 h-screen flex flex-col">
3 - <!-- 活动信息区域 --> 3 + <!-- 加载状态 -->
4 - <view v-if="pageState === 'normal' || pageState === 'no-checkin'" class="bg-white mx-4 mt-4 mb-2 rounded-lg shadow-sm p-4"> 4 + <view v-if="isLoading" class="flex-1 flex items-center justify-center">
5 - <!-- 活动主题 --> 5 + <view class="text-center">
6 - <view class="text-lg font-bold text-gray-800 mb-2"> 6 + <view class="text-gray-500 mb-2">加载中...</view>
7 - {{ activityInfo.title }}
8 </view> 7 </view>
8 + </view>
9 9
10 - <!-- 打卡进度 --> 10 + <!-- 错误状态 -->
11 - <view class="flex items-center mb-2"> 11 + <view v-else-if="apiError" class="flex-1 flex items-center justify-center">
12 - <view class="flex items-center"> 12 + <view class="text-center">
13 - <view 13 + <view class="text-red-500 mb-2">{{ apiError }}</view>
14 - v-for="(point, index) in activityInfo.checkPoints" 14 + <view @tap="fetchPosterDetail" class="bg-blue-500 text-white px-4 py-2 rounded">
15 - :key="index" 15 + 重新加载
16 - class="w-2 h-2 rounded-full mr-2 flex items-center justify-center"
17 - :class="point.completed ? 'bg-orange-400' : 'bg-gray-300'"
18 - >
19 - </view>
20 </view> 16 </view>
21 - <text class="text-xs text-gray-600">{{ activityInfo.completedCount }}/{{ activityInfo.totalCount }}</text>
22 - </view>
23 -
24 - <!-- 活动截止日期 -->
25 - <view class="text-sm text-gray-500">
26 - 活动截止日期:{{ activityInfo.endDate }}
27 </view> 17 </view>
28 </view> 18 </view>
29 19
30 - <!-- 海报预览区域 - 正常状态 --> 20 + <!-- 正常内容 -->
31 - <view v-if="pageState === 'normal'" class="flex-1 mx-4 relative" style="overflow: visible; padding-bottom: 100rpx;"> 21 + <template v-else>
32 - <view class="h-full relative flex items-center justify-center"> 22 + <!-- 活动信息区域 -->
33 - <view v-if="currentPoster.path" class="w-full h-full relative"> 23 + <view v-if="pageState === 'normal' || pageState === 'no-checkin'" class="bg-white mx-4 mt-4 mb-2 rounded-lg shadow-sm p-4">
34 - <image 24 + <!-- 活动主题 -->
35 - :src="currentPoster.path" 25 + <view class="text-lg font-bold text-gray-800 mb-2">
36 - mode="widthFix" 26 + {{ activityInfo.title }}
37 - class="w-full h-full"
38 - />
39 - <!-- 打卡点标题 -->
40 - <!-- <view class="absolute bottom-2 left-2 bg-blue-500 text-white text-xs px-2 py-1 rounded">
41 - {{ posterList[currentPosterIndex]?.title || '海报生成中' }}
42 - </view> -->
43 - <!-- 点击预览提示 -->
44 - <!-- <view @tap="previewPoster" class="absolute bottom-2 right-2 bg-black bg-opacity-50 text-white text-xs px-2 py-1 rounded">
45 - 点击预览
46 - </view> -->
47 </view> 27 </view>
48 - </view>
49 28
50 - <!-- 左箭头按钮 --> 29 + <!-- 打卡进度 -->
51 - <view 30 + <view class="flex items-center mb-2">
52 - class="absolute top-1/2 transform -translate-y-1/2 w-10 h-10 rounded-full flex items-center justify-center transition-all duration-200 z-10" 31 + <view class="flex items-center">
53 - :class="currentPosterIndex > 0 ? 'bg-orange-400 text-white shadow-lg' : 'bg-gray-300 text-gray-500'" 32 + <view
54 - style="left: -20rpx;" 33 + v-for="(point, index) in activityInfo.checkPoints"
55 - @tap="previousPoster" 34 + :key="index"
56 - > 35 + class="w-2 h-2 rounded-full mr-2 flex items-center justify-center"
57 - <Left size="16"></Left> 36 + :class="point.completed ? 'bg-orange-400' : 'bg-gray-300'"
58 - </view> 37 + >
38 + </view>
39 + </view>
40 + <text class="text-xs text-gray-600">{{ activityInfo.completedCount }}/{{ activityInfo.totalCount }}</text>
41 + </view>
59 42
60 - <!-- 右箭头按钮 --> 43 + <!-- 活动截止日期 -->
61 - <view 44 + <view class="text-sm text-gray-500">
62 - class="absolute top-1/2 transform -translate-y-1/2 w-10 h-10 rounded-full flex items-center justify-center transition-all duration-200 z-10" 45 + 活动截止日期:{{ activityInfo.endDate }}
63 - :class="currentPosterIndex < posterList.length - 1 ? 'bg-orange-400 text-white shadow-lg' : 'bg-gray-300 text-gray-500'" 46 + </view>
64 - style="right: -20rpx;"
65 - @tap="nextPoster"
66 - >
67 - <Right size="16"></Right>
68 </view> 47 </view>
69 - </view>
70 48
71 - <!-- 没有打卡信息的空状态 --> 49 + <!-- 海报预览区域 - 正常状态 -->
72 - <view v-if="pageState === 'no-checkin'" class="flex-1 mx-4 mb-2 flex justify-center"> 50 + <view v-if="pageState === 'normal'" class="flex-1 mx-4 relative" style="overflow: visible; padding-bottom: 100rpx;">
73 - <view class="bg-white rounded-lg shadow-sm p-8 text-center max-w-sm"> 51 + <view class="h-full relative flex items-center justify-center">
74 - <view class="text-6xl mb-4">📸</view> 52 + <view v-if="currentPoster.path" class="w-full h-full relative">
75 - <view class="text-lg font-bold text-gray-800 mb-2">打卡信息为空</view> 53 + <image
76 - <view class="text-sm text-gray-500 mb-4">您还没有打卡记录,请先参加活动打卡后再来生成海报</view> 54 + :src="currentPoster.path"
77 - <view class="text-xs text-orange-500">完成打卡后即可生成专属海报</view> 55 + mode="widthFix"
78 - </view> 56 + class="w-full h-full"
79 - </view> 57 + />
58 + <!-- 打卡点标题 -->
59 + <!-- <view class="absolute bottom-2 left-2 bg-blue-500 text-white text-xs px-2 py-1 rounded">
60 + {{ posterList[currentPosterIndex]?.title || '海报生成中' }}
61 + </view> -->
62 + <!-- 点击预览提示 -->
63 + <!-- <view @tap="previewPoster" class="absolute bottom-2 right-2 bg-black bg-opacity-50 text-white text-xs px-2 py-1 rounded">
64 + 点击预览
65 + </view> -->
66 + </view>
67 + </view>
80 68
81 - <!-- 底部操作按钮 - 仅在正常状态显示 --> 69 + <!-- 左箭头按钮 -->
82 - <view v-if="pageState === 'normal'" class="bg-white border-t border-gray-200 p-4 safe-area-bottom" style="position: fixed; bottom: 0; left: 0; right: 0;">
83 - <view class="flex gap-4">
84 <view 70 <view
85 - class="flex-1 bg-gradient-to-r from-orange-400 to-orange-500 text-white py-3 px-6 rounded-lg font-medium shadow-lg active:scale-95 transition-transform duration-150 flex items-center justify-center gap-2" 71 + class="absolute top-1/2 transform -translate-y-1/2 w-10 h-10 rounded-full flex items-center justify-center transition-all duration-200 z-10"
86 - @click="chooseBackgroundImage" 72 + :class="currentPosterIndex > 0 ? 'bg-orange-400 text-white shadow-lg' : 'bg-gray-300 text-gray-500'"
73 + style="left: -20rpx;"
74 + @tap="previousPoster"
87 > 75 >
88 - <text>{{ currentPosterHasCustomBackground ? '更改照片' : '上传照片' }}</text> 76 + <Left size="16"></Left>
89 </view> 77 </view>
78 +
79 + <!-- 右箭头按钮 -->
90 <view 80 <view
91 - class="flex-1 text-white py-3 px-6 rounded-lg font-medium shadow-lg active:scale-95 transition-transform duration-150 flex items-center justify-center gap-2" 81 + class="absolute top-1/2 transform -translate-y-1/2 w-10 h-10 rounded-full flex items-center justify-center transition-all duration-200 z-10"
92 - :class="posterPath ? 'bg-gradient-to-r from-green-400 to-green-500' : (posterGenerateFailed ? 'bg-gradient-to-r from-orange-400 to-orange-500' : 'bg-gray-400')" 82 + :class="currentPosterIndex < posterList.length - 1 ? 'bg-orange-400 text-white shadow-lg' : 'bg-gray-300 text-gray-500'"
93 - @click="handlePosterAction" 83 + style="right: -20rpx;"
94 - :disabled="!posterPath && !posterGenerateFailed" 84 + @tap="nextPoster"
95 > 85 >
96 - <text>{{ posterPath ? '保存海报' : (posterGenerateFailed ? '重新生成' : '生成中...') }}</text> 86 + <Right size="16"></Right>
97 </view> 87 </view>
98 </view> 88 </view>
99 - </view> 89 +
90 + <!-- 没有打卡信息的空状态 -->
91 + <view v-if="pageState === 'no-checkin'" class="flex-1 mx-4 mb-2 flex justify-center">
92 + <view class="bg-white rounded-lg shadow-sm p-8 text-center max-w-sm">
93 + <view class="text-6xl mb-4">📸</view>
94 + <view class="text-lg font-bold text-gray-800 mb-2">打卡信息为空</view>
95 + <view class="text-sm text-gray-500 mb-4">您还没有打卡记录,请先参加活动打卡后再来生成海报</view>
96 + <view class="text-xs text-orange-500">完成打卡后即可生成专属海报</view>
97 + </view>
98 + </view>
99 +
100 + <!-- 底部操作按钮 - 仅在正常状态显示 -->
101 + <view v-if="pageState === 'normal'" class="bg-white border-t border-gray-200 p-4 safe-area-bottom" style="position: fixed; bottom: 0; left: 0; right: 0;">
102 + <view class="flex gap-4">
103 + <view
104 + class="flex-1 bg-gradient-to-r from-orange-400 to-orange-500 text-white py-3 px-6 rounded-lg font-medium shadow-lg active:scale-95 transition-transform duration-150 flex items-center justify-center gap-2"
105 + @click="chooseBackgroundImage"
106 + >
107 + <text>{{ currentPosterHasCustomBackground ? '更改照片' : '上传照片' }}</text>
108 + </view>
109 + <view
110 + class="flex-1 text-white py-3 px-6 rounded-lg font-medium shadow-lg active:scale-95 transition-transform duration-150 flex items-center justify-center gap-2"
111 + :class="posterPath ? 'bg-gradient-to-r from-green-400 to-green-500' : (posterGenerateFailed ? 'bg-gradient-to-r from-orange-400 to-orange-500' : 'bg-gray-400')"
112 + @click="handlePosterAction"
113 + :disabled="!posterPath && !posterGenerateFailed"
114 + >
115 + <text>{{ posterPath ? '保存海报' : (posterGenerateFailed ? '重新生成' : '生成中...') }}</text>
116 + </view>
117 + </view>
118 + </view>
119 + </template>
100 120
101 <!-- 海报生成组件 - 仅在正常状态显示 --> 121 <!-- 海报生成组件 - 仅在正常状态显示 -->
102 <PosterBuilder 122 <PosterBuilder
...@@ -126,7 +146,7 @@ import { Left, Right } from '@nutui/icons-vue-taro' ...@@ -126,7 +146,7 @@ import { Left, Right } from '@nutui/icons-vue-taro'
126 import PosterBuilder from '@/components/PosterBuilder/index.vue' 146 import PosterBuilder from '@/components/PosterBuilder/index.vue'
127 import BASE_URL from '@/utils/config' 147 import BASE_URL from '@/utils/config'
128 // 导入获取海报详情的API 148 // 导入获取海报详情的API
129 -import { getPosterDetailAPI } from '@/api/map' 149 +import { getPosterDetailAPI, savePosterBackgroundAPI } from '@/api/map'
130 // 默认背景图 150 // 默认背景图
131 const defaultBackground = 'https://cdn.ipadbiz.cn/lls_prog/images/%E6%B5%B7%E6%8A%A5%E9%BB%98%E8%AE%A4%E8%83%8C%E6%99%AF%E5%9B%BE1.png' 151 const defaultBackground = 'https://cdn.ipadbiz.cn/lls_prog/images/%E6%B5%B7%E6%8A%A5%E9%BB%98%E8%AE%A4%E8%83%8C%E6%99%AF%E5%9B%BE1.png'
132 152
...@@ -145,86 +165,158 @@ const pageParams = ref({ ...@@ -145,86 +165,158 @@ const pageParams = ref({
145 id: '', 165 id: '',
146 }) 166 })
147 167
168 +// API数据状态
169 +const apiData = ref(null)
170 +const isLoading = ref(false)
171 +const apiError = ref(null)
172 +
148 // TODO: 有真实数据的时候, 通过ID获取具体地点的海报信息, 赋值currentPosterIndex获取特定的海报 173 // TODO: 有真实数据的时候, 通过ID获取具体地点的海报信息, 赋值currentPosterIndex获取特定的海报
149 174
150 // 图片预览相关 175 // 图片预览相关
151 const previewVisible = ref(false) 176 const previewVisible = ref(false)
152 const previewImages = ref([]) 177 const previewImages = ref([])
153 178
154 -// 活动信息数据 - 模拟不同状态,实际使用时从API获取 179 +/**
155 -const activityInfo = ref({ 180 + * 获取海报详情数据
156 - title: '南京路乐龄时尚消费主题路线', 181 + */
157 - checkPoints: [ 182 +const fetchPosterDetail = async () => {
158 - { id: 1, name: '起点签到', completed: true }, 183 + try {
159 - { id: 2, name: '商圈探索', completed: true }, 184 + isLoading.value = true
160 - { id: 3, name: '文化体验', completed: true }, 185 + apiError.value = null
161 - { id: 4, name: '美食品鉴', completed: false },
162 - { id: 5, name: '终点打卡', completed: false }
163 - ],
164 - completedCount: 3,
165 - totalCount: 5,
166 - endDate: '2025年9月7日'
167 -})
168 186
169 -// activityInfo.value = {}; 187 + const response = await getPosterDetailAPI({})
170 188
171 -// 海报数据列表 - 合并海报基础信息和内容数据,实际使用时从API获取 189 + if (response.code === 1) {
172 -const posterList = ref([ 190 + apiData.value = response.data
173 - { 191 + console.log('获取海报详情成功:', response.data)
174 - id: 1, 192 +
175 - title: '起点签到', 193 + // 根据API数据更新活动信息
176 - path: '', 194 + updateActivityInfo()
177 - checkPointId: 1, 195 +
178 - backgroundImage: 'https://cdn.ipadbiz.cn/lls_prog/images/%E6%B5%B7%E6%8A%A5%E9%BB%98%E8%AE%A4%E8%83%8C%E6%99%AF%E5%9B%BE1.png', 196 + // 根据API数据更新海报列表
179 - // 海报内容数据 197 + updatePosterList()
180 - user: { 198 +
181 - avatar: 'https://cdn.ipadbiz.cn/icon/tou@2x.png', 199 + // 根据pageParams.id设置当前海报索引
182 - nickname: '张大爷' 200 + setCurrentPosterIndex()
183 - }, 201 +
184 - family: { 202 + } else {
185 - name: '幸福之家', 203 + apiError.value = response.msg || '获取海报详情失败'
186 - description: '一家人整整齐齐最重要' 204 + console.error('获取海报详情失败:', response.msg)
187 - }, 205 + }
188 - activity: { 206 + } catch (error) {
189 - logo: 'https://cdn.ipadbiz.cn/lls_prog/images/%E6%B5%B7%E6%8A%A5%E5%B7%A6%E4%B8%8A%E8%A7%92logo.png', 207 + apiError.value = '网络请求失败'
190 - name: '南京路时尚citywalk' 208 + console.error('获取海报详情异常:', error)
191 - }, 209 + } finally {
192 - level: { 210 + isLoading.value = false
193 - logo: 'https://cdn.ipadbiz.cn/lls_prog/images/%E6%B5%B7%E6%8A%A5%E5%8F%B3%E4%B8%8B%E8%A7%92icon.png', 211 + }
194 - name: '卡点: 上海市第一百货商店' 212 +}
195 - }, 213 +
196 - qrcode: 'https://cdn.ipadbiz.cn/space/068a790496c87cb8d2ed6e551401c544.png', 214 +/**
197 - qrcodeDesc: '长按识别,来,我们一起打卡!' 215 + * 根据API数据更新活动信息
198 - }, 216 + */
199 - { 217 +const updateActivityInfo = () => {
200 - id: 2, 218 + if (!apiData.value) return
201 - title: '商圈探索', 219 +
220 + const { title, end_date, details, show_detail_index } = apiData.value
221 +
222 + // 转换details为checkPoints格式
223 + const checkPoints = details.map((detail, index) => ({
224 + id: detail.id,
225 + name: detail.name,
226 + completed: detail.is_checked === true
227 + }))
228 +
229 + // 计算已完成数量
230 + const completedCount = checkPoints.filter(point => point.completed).length
231 +
232 + activityInfo.value = {
233 + title: title || '海报打卡活动',
234 + checkPoints,
235 + completedCount,
236 + totalCount: checkPoints.length,
237 + endDate: end_date || '',
238 + showDetailIndex: show_detail_index || 0
239 + }
240 +}
241 +
242 +/**
243 + * 根据API数据更新海报列表
244 + */
245 +const updatePosterList = () => {
246 + if (!apiData.value) return
247 +
248 + const { details, family, qrcode_url } = apiData.value
249 +
250 + // 只显示is_checked为真的关卡
251 + const checkedDetails = details.filter(detail =>
252 + detail.is_checked === true
253 + )
254 +
255 + posterList.value = checkedDetails.map((detail, index) => ({
256 + id: detail.id,
257 + title: detail.name,
202 path: '', 258 path: '',
203 - checkPointId: 2, 259 + checkPointId: detail.id,
204 - backgroundImage: 'https://cdn.ipadbiz.cn/lls_prog/images/%E5%85%B3%E5%8D%A12-%E5%9B%BE%E5%B1%82%201.png', 260 + backgroundImage: detail.background_url || defaultBackground,
205 // 海报内容数据 261 // 海报内容数据
206 user: { 262 user: {
207 - avatar: 'https://cdn.ipadbiz.cn/icon/tou@2x.png', 263 + avatar: family?.avatar_url || 'https://cdn.ipadbiz.cn/icon/tou@2x.png', // 默认头像,后续可从用户信息获取
208 - nickname: '李奶奶' 264 + nickname: '用户昵称' // 默认昵称,后续可从用户信息获取
209 }, 265 },
210 family: { 266 family: {
211 - name: '温馨小家', 267 + name: family?.name || '我的家庭',
212 - description: '健康快乐每一天' 268 + description: ''
213 }, 269 },
214 activity: { 270 activity: {
215 - logo: 'https://cdn.ipadbiz.cn/lls_prog/images/%E6%B5%B7%E6%8A%A5%E5%B7%A6%E4%B8%8A%E8%A7%92logo.png', 271 + logo: detail.main_slogan || 'https://cdn.ipadbiz.cn/lls_prog/images/%E6%B5%B7%E6%8A%A5%E5%B7%A6%E4%B8%8A%E8%A7%92logo.png',
216 - name: '南京路时尚citywalk'
217 }, 272 },
218 level: { 273 level: {
219 - logo: 'https://cdn.ipadbiz.cn/lls_prog/images/%E5%85%B3%E5%8D%A12-%E4%BB%8A%E6%9C%9D%E8%B7%9F%E6%97%81%E5%8F%8B%20%E4%B8%80%E9%81%93%E6%9D%A5%E4%B9%B0%E4%B9%B0%E4%B9%B0_1.png', 274 + logo: detail.sub_slogan || 'https://cdn.ipadbiz.cn/lls_prog/images/%E6%B5%B7%E6%8A%A5%E5%8F%B3%E4%B8%8B%E8%A7%92icon.png',
220 - name: '第二关卡' 275 + name: detail.name || '海报打卡活动',
221 }, 276 },
222 - qrcode: 'https://cdn.ipadbiz.cn/space/068a790496c87cb8d2ed6e551401c544.png', 277 + qrcode: qrcode_url,
223 qrcodeDesc: '长按识别,来,我们一起打卡!' 278 qrcodeDesc: '长按识别,来,我们一起打卡!'
224 - }, 279 + }))
225 -]) 280 +}
281 +
282 +/**
283 + * 根据pageParams.id设置当前海报索引
284 + */
285 +const setCurrentPosterIndex = () => {
286 + if (!posterList.value.length) {
287 + currentPosterIndex.value = 0
288 + return
289 + }
290 +
291 + // 如果有指定的ID,查找对应的海报索引
292 + if (pageParams.value.id) {
293 + const targetIndex = posterList.value.findIndex(poster =>
294 + poster.checkPointId.toString() === pageParams.value.id.toString()
295 + )
296 +
297 + if (targetIndex !== -1) {
298 + currentPosterIndex.value = targetIndex
299 + return
300 + }
301 + }
226 302
227 -// posterList.value = [] 303 + // 如果没有ID或没找到对应的关卡ID,默认显示第一个已打卡的项(索引0)
304 + // 因为posterList已经过滤了is_checked=true的项,所以第一个就是我们要的
305 + currentPosterIndex.value = 0
306 +}
307 +
308 +// 活动信息数据 - 将由API数据填充
309 +const activityInfo = ref({
310 + title: '',
311 + checkPoints: [],
312 + completedCount: 0,
313 + totalCount: 0,
314 + endDate: '',
315 + showDetailIndex: 0
316 +})
317 +
318 +// 海报数据列表 - 将由API数据填充
319 +const posterList = ref([])
228 320
229 // 数据状态检查 321 // 数据状态检查
230 const hasActivityInfo = computed(() => { 322 const hasActivityInfo = computed(() => {
...@@ -416,7 +508,7 @@ const posterConfig = computed(() => { ...@@ -416,7 +508,7 @@ const posterConfig = computed(() => {
416 /** 508 /**
417 * 页面加载时初始化 509 * 页面加载时初始化
418 */ 510 */
419 -onMounted(() => { 511 +onMounted(async () => {
420 Taro.setNavigationBarTitle({ title: '海报打卡' }) 512 Taro.setNavigationBarTitle({ title: '海报打卡' })
421 513
422 // 获取页面参数 514 // 获取页面参数
...@@ -429,6 +521,16 @@ onMounted(() => { ...@@ -429,6 +521,16 @@ onMounted(() => {
429 521
430 console.log('海报打卡页面接收到的参数:', pageParams.value) 522 console.log('海报打卡页面接收到的参数:', pageParams.value)
431 523
524 + // 获取海报详情数据
525 + await fetchPosterDetail()
526 +
527 + // 数据获取完成后检查页面状态
528 + if (pageState.value === 'no-activity') {
529 + // 没有活动信息,显示确认对话框
530 + showNoActivityConfirm()
531 + return
532 + }
533 +
432 // 页面加载时检查是否需要生成当前海报 534 // 页面加载时检查是否需要生成当前海报
433 generateCurrentPosterIfNeeded() 535 generateCurrentPosterIfNeeded()
434 }) 536 })
...@@ -576,9 +678,10 @@ const chooseBackgroundImage = () => { ...@@ -576,9 +678,10 @@ const chooseBackgroundImage = () => {
576 678
577 uploadBackgroundImage(tempFile.path) 679 uploadBackgroundImage(tempFile.path)
578 }, 680 },
579 - fail: () => { 681 + fail: (error) => {
682 + console.error('选择图片失败:', error)
580 // Taro.showToast({ 683 // Taro.showToast({
581 - // title: '选择图片失败', 684 + // title: '选择图片失败,请重试',
582 // icon: 'none' 685 // icon: 'none'
583 // }) 686 // })
584 } 687 }
...@@ -595,15 +698,33 @@ const uploadBackgroundImage = (filePath) => { ...@@ -595,15 +698,33 @@ const uploadBackgroundImage = (filePath) => {
595 url: BASE_URL + '/admin/?m=srv&a=upload', 698 url: BASE_URL + '/admin/?m=srv&a=upload',
596 filePath, 699 filePath,
597 name: 'file', 700 name: 'file',
598 - success: (uploadRes) => { 701 + success: async (uploadRes) => {
599 - Taro.hideLoading()
600 const data = JSON.parse(uploadRes.data) 702 const data = JSON.parse(uploadRes.data)
601 if (data.code === 0 && data.data) { 703 if (data.code === 0 && data.data) {
602 const currentIndex = currentPosterIndex.value 704 const currentIndex = currentPosterIndex.value
705 + const currentPosterData = posterList.value[currentIndex]
603 706
604 // 为当前海报设置背景图 707 // 为当前海报设置背景图
605 backgroundImages.value[currentIndex] = data.data.src 708 backgroundImages.value[currentIndex] = data.data.src
606 709
710 + // 调用保存海报背景接口
711 + try {
712 + const saveResult = await savePosterBackgroundAPI({
713 + detail_id: currentPosterData.checkPointId,
714 + poster_background_url: data.data.src
715 + })
716 +
717 + if (saveResult.code === 1) {
718 + console.log('海报背景保存成功:', saveResult.data)
719 + } else {
720 + console.warn('海报背景保存失败:', saveResult.msg)
721 + // 即使保存失败,也继续生成海报,不影响用户体验
722 + }
723 + } catch (error) {
724 + console.error('保存海报背景异常:', error)
725 + // 即使保存失败,也继续生成海报,不影响用户体验
726 + }
727 +
607 // 强制标记当前海报需要重新生成 728 // 强制标记当前海报需要重新生成
608 posterGeneratedFlags.value[currentIndex] = false 729 posterGeneratedFlags.value[currentIndex] = false
609 delete posterConfigHashes.value[currentIndex] 730 delete posterConfigHashes.value[currentIndex]
...@@ -614,12 +735,15 @@ const uploadBackgroundImage = (filePath) => { ...@@ -614,12 +735,15 @@ const uploadBackgroundImage = (filePath) => {
614 // 立即重新生成海报 735 // 立即重新生成海报
615 generateCurrentPoster() 736 generateCurrentPoster()
616 737
738 + Taro.hideLoading()
617 Taro.showToast({ title: '上传成功', icon: 'success' }) 739 Taro.showToast({ title: '上传成功', icon: 'success' })
618 } else { 740 } else {
741 + Taro.hideLoading()
619 Taro.showToast({ title: data.msg || '上传失败', icon: 'none' }) 742 Taro.showToast({ title: data.msg || '上传失败', icon: 'none' })
620 } 743 }
621 }, 744 },
622 - fail: () => { 745 + fail: (error) => {
746 + console.error('上传文件失败:', error)
623 Taro.hideLoading() 747 Taro.hideLoading()
624 Taro.showToast({ title: '上传失败,请稍后重试', icon: 'none' }) 748 Taro.showToast({ title: '上传失败,请稍后重试', icon: 'none' })
625 } 749 }
...@@ -755,22 +879,7 @@ const showNoActivityConfirm = () => { ...@@ -755,22 +879,7 @@ const showNoActivityConfirm = () => {
755 }) 879 })
756 } 880 }
757 881
758 -/**
759 - * 页面初始化
760 - */
761 -onMounted(() => {
762 - // 获取页面参数
763 - const instance = Taro.getCurrentInstance()
764 - if (instance.router && instance.router.params) {
765 - pageParams.value = instance.router.params
766 - }
767 882
768 - // 检查页面状态
769 - if (pageState.value === 'no-activity') {
770 - // 没有活动信息,显示确认对话框
771 - showNoActivityConfirm()
772 - }
773 -})
774 </script> 883 </script>
775 884
776 <style scoped> 885 <style scoped>
......