feat(海报打卡): 添加页面状态管理及空状态处理
添加页面状态管理逻辑,包括正常状态、无打卡信息状态和无活动信息状态 为空状态添加UI展示和处理逻辑 优化组件显示条件,根据状态动态渲染
Showing
2 changed files
with
85 additions
and
9 deletions
| ... | @@ -15,6 +15,7 @@ declare module 'vue' { | ... | @@ -15,6 +15,7 @@ declare module 'vue' { |
| 15 | NutActionSheet: typeof import('@nutui/nutui-taro')['ActionSheet'] | 15 | NutActionSheet: typeof import('@nutui/nutui-taro')['ActionSheet'] |
| 16 | NutButton: typeof import('@nutui/nutui-taro')['Button'] | 16 | NutButton: typeof import('@nutui/nutui-taro')['Button'] |
| 17 | NutDatePicker: typeof import('@nutui/nutui-taro')['DatePicker'] | 17 | NutDatePicker: typeof import('@nutui/nutui-taro')['DatePicker'] |
| 18 | + NutDialog: typeof import('@nutui/nutui-taro')['Dialog'] | ||
| 18 | NutImagePreview: typeof import('@nutui/nutui-taro')['ImagePreview'] | 19 | NutImagePreview: typeof import('@nutui/nutui-taro')['ImagePreview'] |
| 19 | NutInput: typeof import('@nutui/nutui-taro')['Input'] | 20 | NutInput: typeof import('@nutui/nutui-taro')['Input'] |
| 20 | NutPicker: typeof import('@nutui/nutui-taro')['Picker'] | 21 | NutPicker: typeof import('@nutui/nutui-taro')['Picker'] | ... | ... |
| 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 class="bg-white mx-4 mt-4 mb-2 rounded-lg shadow-sm p-4"> | 4 | + <view v-if="pageState === 'normal' || pageState === 'no-checkin'" class="bg-white mx-4 mt-4 mb-2 rounded-lg shadow-sm p-4"> |
| 5 | <!-- 活动主题 --> | 5 | <!-- 活动主题 --> |
| 6 | <view class="text-lg font-bold text-gray-800 mb-2"> | 6 | <view class="text-lg font-bold text-gray-800 mb-2"> |
| 7 | {{ activityInfo.title }} | 7 | {{ activityInfo.title }} |
| ... | @@ -27,8 +27,8 @@ | ... | @@ -27,8 +27,8 @@ |
| 27 | </view> | 27 | </view> |
| 28 | </view> | 28 | </view> |
| 29 | 29 | ||
| 30 | - <!-- 海报预览区域 --> | 30 | + <!-- 海报预览区域 - 正常状态 --> |
| 31 | - <view class="flex-1 mx-4 mb-2 bg-white rounded-lg shadow-sm relative" style="overflow: visible;"> | 31 | + <view v-if="pageState === 'normal'" class="flex-1 mx-4 mb-2 bg-white rounded-lg shadow-sm relative" style="overflow: visible;"> |
| 32 | <view class="h-full relative bg-gray-100 flex items-center justify-center"> | 32 | <view class="h-full relative bg-gray-100 flex items-center justify-center"> |
| 33 | <view v-if="currentPoster.path" class="w-full h-full relative"> | 33 | <view v-if="currentPoster.path" class="w-full h-full relative"> |
| 34 | <image | 34 | <image |
| ... | @@ -68,8 +68,18 @@ | ... | @@ -68,8 +68,18 @@ |
| 68 | </view> | 68 | </view> |
| 69 | </view> | 69 | </view> |
| 70 | 70 | ||
| 71 | - <!-- 底部操作按钮 --> | 71 | + <!-- 没有打卡信息的空状态 --> |
| 72 | - <view class="bg-white border-t border-gray-200 p-4 safe-area-bottom"> | 72 | + <view v-if="pageState === 'no-checkin'" class="flex-1 mx-4 mb-2 flex justify-center"> |
| 73 | + <view class="bg-white rounded-lg shadow-sm p-8 text-center max-w-sm"> | ||
| 74 | + <view class="text-6xl mb-4">📸</view> | ||
| 75 | + <view class="text-lg font-bold text-gray-800 mb-2">打卡信息为空</view> | ||
| 76 | + <view class="text-sm text-gray-500 mb-4">您还没有打卡记录,请先参加活动打卡后再来生成海报</view> | ||
| 77 | + <view class="text-xs text-orange-500">完成打卡后即可生成专属海报</view> | ||
| 78 | + </view> | ||
| 79 | + </view> | ||
| 80 | + | ||
| 81 | + <!-- 底部操作按钮 - 仅在正常状态显示 --> | ||
| 82 | + <view v-if="pageState === 'normal'" class="bg-white border-t border-gray-200 p-4 safe-area-bottom"> | ||
| 73 | <view class="flex gap-4"> | 83 | <view class="flex gap-4"> |
| 74 | <view | 84 | <view |
| 75 | 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" | 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" |
| ... | @@ -88,9 +98,9 @@ | ... | @@ -88,9 +98,9 @@ |
| 88 | </view> | 98 | </view> |
| 89 | </view> | 99 | </view> |
| 90 | 100 | ||
| 91 | - <!-- 海报生成组件 --> | 101 | + <!-- 海报生成组件 - 仅在正常状态显示 --> |
| 92 | <PosterBuilder | 102 | <PosterBuilder |
| 93 | - v-if="shouldGeneratePoster" | 103 | + v-if="shouldGeneratePoster && pageState === 'normal'" |
| 94 | :config="posterConfig" | 104 | :config="posterConfig" |
| 95 | :show-loading="true" | 105 | :show-loading="true" |
| 96 | @success="onPosterSuccess" | 106 | @success="onPosterSuccess" |
| ... | @@ -104,6 +114,8 @@ | ... | @@ -104,6 +114,8 @@ |
| 104 | :init-no="0" | 114 | :init-no="0" |
| 105 | @close="closePreview" | 115 | @close="closePreview" |
| 106 | /> | 116 | /> |
| 117 | + | ||
| 118 | + | ||
| 107 | </view> | 119 | </view> |
| 108 | </template> | 120 | </template> |
| 109 | 121 | ||
| ... | @@ -149,7 +161,7 @@ const pageParams = ref({ | ... | @@ -149,7 +161,7 @@ const pageParams = ref({ |
| 149 | const previewVisible = ref(false) | 161 | const previewVisible = ref(false) |
| 150 | const previewImages = ref([]) | 162 | const previewImages = ref([]) |
| 151 | 163 | ||
| 152 | -// 活动信息数据 | 164 | +// 活动信息数据 - 模拟不同状态,实际使用时从API获取 |
| 153 | const activityInfo = ref({ | 165 | const activityInfo = ref({ |
| 154 | title: '南京路乐龄时尚消费主题路线', | 166 | title: '南京路乐龄时尚消费主题路线', |
| 155 | checkPoints: [ | 167 | checkPoints: [ |
| ... | @@ -164,7 +176,9 @@ const activityInfo = ref({ | ... | @@ -164,7 +176,9 @@ const activityInfo = ref({ |
| 164 | endDate: '2025年9月7日' | 176 | endDate: '2025年9月7日' |
| 165 | }) | 177 | }) |
| 166 | 178 | ||
| 167 | -// 海报列表数据 | 179 | +// activityInfo.value = {}; |
| 180 | + | ||
| 181 | +// 海报列表数据 - 模拟不同状态,实际使用时从API获取 | ||
| 168 | const posterList = ref([ | 182 | const posterList = ref([ |
| 169 | { | 183 | { |
| 170 | id: 1, | 184 | id: 1, |
| ... | @@ -189,6 +203,30 @@ const posterList = ref([ | ... | @@ -189,6 +203,30 @@ const posterList = ref([ |
| 189 | } | 203 | } |
| 190 | ]) | 204 | ]) |
| 191 | 205 | ||
| 206 | +// posterList.value = [] | ||
| 207 | + | ||
| 208 | +// 数据状态检查 | ||
| 209 | +const hasActivityInfo = computed(() => { | ||
| 210 | + return activityInfo.value && activityInfo.value.title && activityInfo.value.checkPoints && activityInfo.value.checkPoints.length > 0 | ||
| 211 | +}) | ||
| 212 | + | ||
| 213 | +const hasCheckinInfo = computed(() => { | ||
| 214 | + return posterList.value && posterList.value.length > 0 | ||
| 215 | +}) | ||
| 216 | + | ||
| 217 | +// 页面显示状态 | ||
| 218 | +const pageState = computed(() => { | ||
| 219 | + if (!hasActivityInfo.value) { | ||
| 220 | + return 'no-activity' // 没有活动信息 | ||
| 221 | + } | ||
| 222 | + if (!hasCheckinInfo.value) { | ||
| 223 | + return 'no-checkin' // 有活动信息但没有打卡信息 | ||
| 224 | + } | ||
| 225 | + return 'normal' // 正常状态 | ||
| 226 | +}) | ||
| 227 | + | ||
| 228 | + | ||
| 229 | + | ||
| 192 | // 当前海报 | 230 | // 当前海报 |
| 193 | const currentPoster = computed(() => { | 231 | const currentPoster = computed(() => { |
| 194 | return posterList.value[currentPosterIndex.value] || { path: '', title: '' } | 232 | return posterList.value[currentPosterIndex.value] || { path: '', title: '' } |
| ... | @@ -572,6 +610,43 @@ const savePoster = () => { | ... | @@ -572,6 +610,43 @@ const savePoster = () => { |
| 572 | } | 610 | } |
| 573 | }) | 611 | }) |
| 574 | } | 612 | } |
| 613 | + | ||
| 614 | +/** | ||
| 615 | + * 显示没有活动信息的确认对话框 | ||
| 616 | + */ | ||
| 617 | +const showNoActivityConfirm = () => { | ||
| 618 | + Taro.showModal({ | ||
| 619 | + title: '温馨提示', | ||
| 620 | + content: '您还没有参加过活动,请先参加活动后再来生成海报', | ||
| 621 | + showCancel: false, | ||
| 622 | + confirmText: '知道了', | ||
| 623 | + success: (res) => { | ||
| 624 | + if (res.confirm) { | ||
| 625 | + // 返回上一页 | ||
| 626 | + Taro.navigateBack({ | ||
| 627 | + delta: 1 | ||
| 628 | + }) | ||
| 629 | + } | ||
| 630 | + } | ||
| 631 | + }) | ||
| 632 | +} | ||
| 633 | + | ||
| 634 | +/** | ||
| 635 | + * 页面初始化 | ||
| 636 | + */ | ||
| 637 | +onMounted(() => { | ||
| 638 | + // 获取页面参数 | ||
| 639 | + const instance = Taro.getCurrentInstance() | ||
| 640 | + if (instance.router && instance.router.params) { | ||
| 641 | + pageParams.value = instance.router.params | ||
| 642 | + } | ||
| 643 | + | ||
| 644 | + // 检查页面状态 | ||
| 645 | + if (pageState.value === 'no-activity') { | ||
| 646 | + // 没有活动信息,显示确认对话框 | ||
| 647 | + showNoActivityConfirm() | ||
| 648 | + } | ||
| 649 | +}) | ||
| 575 | </script> | 650 | </script> |
| 576 | 651 | ||
| 577 | <style lang="less"> | 652 | <style lang="less"> | ... | ... |
-
Please register or login to post a comment