refactor(api): 提取地图活动API并新增展位地图画廊页面
迁移扫码打卡相关API至独立的map_activity.js文件,更新ScanCheckinDetail和ScanCheckinList页面的导入路径。新增BoothMapGallery页面,支持加载状态、空数据提示、网格展位图展示与图片预览,完善新API的文档注释。
Showing
6 changed files
with
146 additions
and
80 deletions
| ... | @@ -12,9 +12,6 @@ const Api = { | ... | @@ -12,9 +12,6 @@ const Api = { |
| 12 | GET_POSTER_DETAIL: '/srv/?a=map&t=poster', | 12 | GET_POSTER_DETAIL: '/srv/?a=map&t=poster', |
| 13 | GET_ACTIVITY_STATUS: '/srv/?a=map&t=get_map_url', | 13 | GET_ACTIVITY_STATUS: '/srv/?a=map&t=get_map_url', |
| 14 | SAVE_POSTER_BACKGROUND: '/srv/?a=map&t=save_poster_background', | 14 | SAVE_POSTER_BACKGROUND: '/srv/?a=map&t=save_poster_background', |
| 15 | - GET_SCAN_STAGE_LIST: '/srv/?a=map_activity&t=scan_stage_list', | ||
| 16 | - GET_SCAN_STAGE_DETAIL: '/srv/?a=map_activity&t=scan_stage_detail', | ||
| 17 | - SUBMIT_SCAN_CHECKIN: '/srv/?a=map_activity&t=checkin', | ||
| 18 | } | 15 | } |
| 19 | 16 | ||
| 20 | /** | 17 | /** |
| ... | @@ -72,51 +69,3 @@ export const getActivityStatusAPI = params => fn(fetch.get(Api.GET_ACTIVITY_STAT | ... | @@ -72,51 +69,3 @@ export const getActivityStatusAPI = params => fn(fetch.get(Api.GET_ACTIVITY_STAT |
| 72 | * @returns {Object} response.data - 响应数据 | 69 | * @returns {Object} response.data - 响应数据 |
| 73 | */ | 70 | */ |
| 74 | export const savePosterBackgroundAPI = params => fn(fetch.post(Api.SAVE_POSTER_BACKGROUND, params)) | 71 | export const savePosterBackgroundAPI = params => fn(fetch.post(Api.SAVE_POSTER_BACKGROUND, params)) |
| 75 | - | ||
| 76 | -/** | ||
| 77 | - * @description: 获取扫码关卡列表 | ||
| 78 | - * @param {Object} params - 请求参数 | ||
| 79 | - * @param {string} [params.page] - 页码,从 0 开始 | ||
| 80 | - * @param {string} [params.limit] - 每页条数 | ||
| 81 | - * @param {string} [params.activity_id] - 活动ID | ||
| 82 | - * @returns {number} response.code - 响应状态码 | ||
| 83 | - * @returns {string} response.msg - 响应消息 | ||
| 84 | - * @returns {Object} response.data - 响应数据 | ||
| 85 | - * @returns {Array} response.data.stages - 关卡列表 | ||
| 86 | - * @returns {number} response.data.stages[].id - 关卡ID | ||
| 87 | - * @returns {string} response.data.stages[].title - 关卡标题 | ||
| 88 | - * @returns {boolean} response.data.stages[].is_checked - 是否已打卡 | ||
| 89 | - */ | ||
| 90 | -export const getScanStageListAPI = params => fn(fetch.get(Api.GET_SCAN_STAGE_LIST, params)) | ||
| 91 | - | ||
| 92 | -/** | ||
| 93 | - * @description: 获取扫码关卡详情 | ||
| 94 | - * @param {Object} params - 请求参数 | ||
| 95 | - * @param {string} params.id - 关卡ID | ||
| 96 | - * @returns {number} response.code - 响应状态码 | ||
| 97 | - * @returns {string} response.msg - 响应消息 | ||
| 98 | - * @returns {Object} response.data - 响应数据 | ||
| 99 | - * @returns {number} response.data.id - 关卡ID | ||
| 100 | - * @returns {string} response.data.title - 关卡标题 | ||
| 101 | - * @returns {Array<string>} response.data.banner - 轮播图 | ||
| 102 | - * @returns {boolean} response.data.is_checked - 是否已打卡 | ||
| 103 | - * @returns {string} response.data.discount_title - 打卡点底部优惠标题 | ||
| 104 | - * @returns {string} response.data.note - 简介 | ||
| 105 | - * @returns {string} response.data.introduction - 底部富文本 | ||
| 106 | - * @returns {boolean} response.data.geo_enabled - 是否启用地理位置限制 | ||
| 107 | - * @returns {number} response.data.center_lng - 经度 | ||
| 108 | - * @returns {number} response.data.center_lat - 纬度 | ||
| 109 | - * @returns {number} response.data.radius_meters - 半径,单位米 | ||
| 110 | - */ | ||
| 111 | -export const getScanStageDetailAPI = params => fn(fetch.get(Api.GET_SCAN_STAGE_DETAIL, params)) | ||
| 112 | - | ||
| 113 | -/** | ||
| 114 | - * @description: 提交扫码打卡 | ||
| 115 | - * @param {Object} params - 请求参数 | ||
| 116 | - * @param {string} params.activity_id - 活动ID | ||
| 117 | - * @param {string} params.detail_id - 关卡ID | ||
| 118 | - * @param {string} [params.openid] - 用户openid,接口定义中为可选 | ||
| 119 | - * @returns {number} response.code - 响应状态码 | ||
| 120 | - * @returns {string} response.msg - 响应消息 | ||
| 121 | - */ | ||
| 122 | -export const submitScanCheckinAPI = params => fn(fetch.post(Api.SUBMIT_SCAN_CHECKIN, params)) | ... | ... |
| ... | @@ -7,6 +7,9 @@ const Api = { | ... | @@ -7,6 +7,9 @@ const Api = { |
| 7 | List: '/srv/?a=map_activity&t=list', | 7 | List: '/srv/?a=map_activity&t=list', |
| 8 | Poster: '/srv/?a=map_activity&t=poster', | 8 | Poster: '/srv/?a=map_activity&t=poster', |
| 9 | SavePosterBackground: '/srv/?a=map_activity&t=save_poster_background', | 9 | SavePosterBackground: '/srv/?a=map_activity&t=save_poster_background', |
| 10 | + ScanStageList: '/srv/?a=map_activity&t=scan_stage_list', | ||
| 11 | + ScanStageDetail: '/srv/?a=map_activity&t=scan_stage_detail', | ||
| 12 | + SubmitScanCheckin: '/srv/?a=map_activity&t=checkin', | ||
| 10 | } | 13 | } |
| 11 | 14 | ||
| 12 | /** | 15 | /** |
| ... | @@ -26,7 +29,7 @@ export const checkinAPI = params => fn(fetch.post(Api.Checkin, params)) | ... | @@ -26,7 +29,7 @@ export const checkinAPI = params => fn(fetch.post(Api.Checkin, params)) |
| 26 | 29 | ||
| 27 | /** | 30 | /** |
| 28 | * @description 地图活动详情 | 31 | * @description 地图活动详情 |
| 29 | - * @remark | 32 | + * @remark |
| 30 | * @param {Object} params 请求参数 | 33 | * @param {Object} params 请求参数 |
| 31 | * @param {string} params.id (可选) 活动ID | 34 | * @param {string} params.id (可选) 活动ID |
| 32 | * @returns {Promise<{ | 35 | * @returns {Promise<{ |
| ... | @@ -36,6 +39,7 @@ export const checkinAPI = params => fn(fetch.post(Api.Checkin, params)) | ... | @@ -36,6 +39,7 @@ export const checkinAPI = params => fn(fetch.post(Api.Checkin, params)) |
| 36 | url: string; // 地图网址 | 39 | url: string; // 地图网址 |
| 37 | id: integer; // 活动ID | 40 | id: integer; // 活动ID |
| 38 | type: string; // 打卡类型,MAP=地图打卡,QR_CODE=扫码打卡 | 41 | type: string; // 打卡类型,MAP=地图打卡,QR_CODE=扫码打卡 |
| 42 | + booth_images: Array<string>; // 打卡点图片列表 | ||
| 39 | cover: string; // 封面图 | 43 | cover: string; // 封面图 |
| 40 | begin_date: string; // 开始时间 | 44 | begin_date: string; // 开始时间 |
| 41 | end_date: string; // 结束时间 | 45 | end_date: string; // 结束时间 |
| ... | @@ -53,10 +57,10 @@ export const detailAPI = params => fn(fetch.get(Api.Detail, params)) | ... | @@ -53,10 +57,10 @@ export const detailAPI = params => fn(fetch.get(Api.Detail, params)) |
| 53 | 57 | ||
| 54 | /** | 58 | /** |
| 55 | * @description 是否已经打卡 | 59 | * @description 是否已经打卡 |
| 56 | - * @remark | 60 | + * @remark |
| 57 | * @param {Object} params 请求参数 | 61 | * @param {Object} params 请求参数 |
| 58 | * @param {string} params.detail_id (可选) 打卡点ID | 62 | * @param {string} params.detail_id (可选) 打卡点ID |
| 59 | - * @param {string} params.openid (可选) | 63 | + * @param {string} params.openid (可选) |
| 60 | * @param {string} params.activity_id (可选) 活动ID | 64 | * @param {string} params.activity_id (可选) 活动ID |
| 61 | * @returns {Promise<{ | 65 | * @returns {Promise<{ |
| 62 | * code: number; // 状态码 | 66 | * code: number; // 状态码 |
| ... | @@ -70,7 +74,7 @@ export const isCheckedAPI = params => fn(fetch.get(Api.IsChecked, params)) | ... | @@ -70,7 +74,7 @@ export const isCheckedAPI = params => fn(fetch.get(Api.IsChecked, params)) |
| 70 | 74 | ||
| 71 | /** | 75 | /** |
| 72 | * @description 地图活动列表 | 76 | * @description 地图活动列表 |
| 73 | - * @remark | 77 | + * @remark |
| 74 | * @param {Object} params 请求参数 | 78 | * @param {Object} params 请求参数 |
| 75 | * @returns {Promise<{ | 79 | * @returns {Promise<{ |
| 76 | * code: number; // 状态码 | 80 | * code: number; // 状态码 |
| ... | @@ -88,8 +92,66 @@ export const isCheckedAPI = params => fn(fetch.get(Api.IsChecked, params)) | ... | @@ -88,8 +92,66 @@ export const isCheckedAPI = params => fn(fetch.get(Api.IsChecked, params)) |
| 88 | export const listAPI = params => fn(fetch.get(Api.List, params)) | 92 | export const listAPI = params => fn(fetch.get(Api.List, params)) |
| 89 | 93 | ||
| 90 | /** | 94 | /** |
| 95 | + * @description 获取扫码关卡列表 | ||
| 96 | + * @param {Object} params 请求参数 | ||
| 97 | + * @param {string} [params.page] 页码,从 0 开始 | ||
| 98 | + * @param {string} [params.limit] 每页条数 | ||
| 99 | + * @param {string} [params.activity_id] 活动ID | ||
| 100 | + * @returns {Promise<{ | ||
| 101 | + * code: number; | ||
| 102 | + * msg: string; | ||
| 103 | + * data: { | ||
| 104 | + * stages: Array<{ | ||
| 105 | + * id: number; | ||
| 106 | + * title: string; | ||
| 107 | + * is_checked: boolean; | ||
| 108 | + * }>; | ||
| 109 | + * }; | ||
| 110 | + * }>} | ||
| 111 | + */ | ||
| 112 | +export const getScanStageListAPI = params => fn(fetch.get(Api.ScanStageList, params)) | ||
| 113 | + | ||
| 114 | +/** | ||
| 115 | + * @description 获取扫码关卡详情 | ||
| 116 | + * @param {Object} params 请求参数 | ||
| 117 | + * @param {string} params.id 关卡ID | ||
| 118 | + * @returns {Promise<{ | ||
| 119 | + * code: number; | ||
| 120 | + * msg: string; | ||
| 121 | + * data: { | ||
| 122 | + * id: number; | ||
| 123 | + * title: string; | ||
| 124 | + * banner: Array<string>; | ||
| 125 | + * is_checked: boolean; | ||
| 126 | + * discount_title: string; | ||
| 127 | + * note: string; | ||
| 128 | + * introduction: string; | ||
| 129 | + * geo_enabled: boolean; | ||
| 130 | + * center_lng: number; | ||
| 131 | + * center_lat: number; | ||
| 132 | + * radius_meters: number; | ||
| 133 | + * }; | ||
| 134 | + * }>} | ||
| 135 | + */ | ||
| 136 | +export const getScanStageDetailAPI = params => fn(fetch.get(Api.ScanStageDetail, params)) | ||
| 137 | + | ||
| 138 | +/** | ||
| 139 | + * @description 提交扫码打卡 | ||
| 140 | + * @param {Object} params 请求参数 | ||
| 141 | + * @param {string} params.activity_id 活动ID | ||
| 142 | + * @param {string} params.detail_id 关卡ID | ||
| 143 | + * @param {string} [params.openid] 用户openid | ||
| 144 | + * @returns {Promise<{ | ||
| 145 | + * code: number; | ||
| 146 | + * msg: string; | ||
| 147 | + * data: any; | ||
| 148 | + * }>} | ||
| 149 | + */ | ||
| 150 | +export const submitScanCheckinAPI = params => fn(fetch.post(Api.SubmitScanCheckin, params)) | ||
| 151 | + | ||
| 152 | +/** | ||
| 91 | * @description 获取海报 | 153 | * @description 获取海报 |
| 92 | - * @remark | 154 | + * @remark |
| 93 | * @param {Object} params 请求参数 | 155 | * @param {Object} params 请求参数 |
| 94 | * @param {string} params.activity_id (可选) 活动ID | 156 | * @param {string} params.activity_id (可选) 活动ID |
| 95 | * @param {string} params.detail_id (可选) 关卡ID | 157 | * @param {string} params.detail_id (可选) 关卡ID |
| ... | @@ -102,8 +164,8 @@ export const listAPI = params => fn(fetch.get(Api.List, params)) | ... | @@ -102,8 +164,8 @@ export const listAPI = params => fn(fetch.get(Api.List, params)) |
| 102 | id: integer; // 关卡ID | 164 | id: integer; // 关卡ID |
| 103 | name: string; // 关卡名称 | 165 | name: string; // 关卡名称 |
| 104 | background_url: string; // 关卡背景图 | 166 | background_url: string; // 关卡背景图 |
| 105 | - main_slogan: string; // | 167 | + main_slogan: string; // |
| 106 | - sub_slogan: string; // | 168 | + sub_slogan: string; // |
| 107 | is_checked: boolean; // 是否已经打卡 | 169 | is_checked: boolean; // 是否已经打卡 |
| 108 | }>; | 170 | }>; |
| 109 | family: { | 171 | family: { | ... | ... |
| ... | @@ -5,6 +5,13 @@ | ... | @@ -5,6 +5,13 @@ |
| 5 | box-sizing: border-box; | 5 | box-sizing: border-box; |
| 6 | } | 6 | } |
| 7 | 7 | ||
| 8 | +.booth-map-gallery-status { | ||
| 9 | + padding: 120rpx 24rpx; | ||
| 10 | + text-align: center; | ||
| 11 | + font-size: 28rpx; | ||
| 12 | + color: #6b7280; | ||
| 13 | +} | ||
| 14 | + | ||
| 8 | .booth-map-gallery-grid { | 15 | .booth-map-gallery-grid { |
| 9 | column-count: 2; | 16 | column-count: 2; |
| 10 | column-gap: 20rpx; | 17 | column-gap: 20rpx; | ... | ... |
| 1 | <template> | 1 | <template> |
| 2 | <view class="booth-map-gallery-page"> | 2 | <view class="booth-map-gallery-page"> |
| 3 | - <view class="booth-map-gallery-grid"> | 3 | + <view v-if="loading" class="booth-map-gallery-status">加载中...</view> |
| 4 | + | ||
| 5 | + <view v-else-if="imageList.length === 0" class="booth-map-gallery-status"> 暂无展位图 </view> | ||
| 6 | + | ||
| 7 | + <view v-else class="booth-map-gallery-grid"> | ||
| 4 | <view | 8 | <view |
| 5 | v-for="(item, index) in imageList" | 9 | v-for="(item, index) in imageList" |
| 6 | :key="item.id" | 10 | :key="item.id" |
| ... | @@ -15,28 +19,72 @@ | ... | @@ -15,28 +19,72 @@ |
| 15 | 19 | ||
| 16 | <script setup> | 20 | <script setup> |
| 17 | import { ref } from 'vue' | 21 | import { ref } from 'vue' |
| 18 | -import Taro from '@tarojs/taro' | 22 | +import Taro, { useLoad } from '@tarojs/taro' |
| 19 | import './index.less' | 23 | import './index.less' |
| 24 | +import { detailAPI } from '@/api/map_activity' | ||
| 25 | + | ||
| 26 | +const imageList = ref([]) | ||
| 27 | +const loading = ref(false) | ||
| 28 | +const activityId = ref('') | ||
| 29 | + | ||
| 30 | +const isApiSuccess = code => Number(code) === 1 | ||
| 31 | + | ||
| 32 | +const mapBoothImages = boothImages => | ||
| 33 | + boothImages | ||
| 34 | + .filter(item => typeof item === 'string' && item.trim() !== '') | ||
| 35 | + .map((url, index) => ({ | ||
| 36 | + id: `booth-${index}`, | ||
| 37 | + url, | ||
| 38 | + mode: 'widthFix', | ||
| 39 | + })) | ||
| 40 | + | ||
| 41 | +const fetchBoothImages = async () => { | ||
| 42 | + if (!activityId.value) { | ||
| 43 | + imageList.value = [] | ||
| 44 | + Taro.showToast({ | ||
| 45 | + title: '缺少活动信息', | ||
| 46 | + icon: 'none', | ||
| 47 | + }) | ||
| 48 | + return | ||
| 49 | + } | ||
| 20 | 50 | ||
| 21 | -const imageList = ref([ | 51 | + loading.value = true |
| 22 | - { | 52 | + |
| 23 | - id: 'booth-01', | 53 | + try { |
| 24 | - url: 'https://cdn.ipadbiz.cn/lls_prog/images/check_detail_img.png?imageMogr2/strip/quality/60', | 54 | + const result = await detailAPI({ id: activityId.value }) |
| 25 | - mode: 'widthFix', | 55 | + |
| 26 | - }, | 56 | + if (!isApiSuccess(result?.code)) { |
| 27 | - { | 57 | + Taro.showToast({ |
| 28 | - id: 'booth-02', | 58 | + title: result?.msg || '获取展位图失败', |
| 29 | - url: 'https://cdn.ipadbiz.cn/lls_prog/images/welcome_8.jpg?imageMogr2/strip/quality/60', | 59 | + icon: 'none', |
| 30 | - mode: 'widthFix', | 60 | + }) |
| 31 | - }, | 61 | + imageList.value = [] |
| 32 | - { | 62 | + return |
| 33 | - id: 'booth-03', | 63 | + } |
| 34 | - url: 'https://cdn.ipadbiz.cn/lls_prog/images/check_detail_img.png?imageMogr2/strip/quality/60', | 64 | + |
| 35 | - mode: 'widthFix', | 65 | + imageList.value = mapBoothImages(result?.data?.booth_images || []) |
| 36 | - }, | 66 | + } catch (error) { |
| 37 | -]) | 67 | + console.error('[BoothMapGallery] 获取展位图失败:', error) |
| 68 | + imageList.value = [] | ||
| 69 | + Taro.showToast({ | ||
| 70 | + title: '获取展位图失败', | ||
| 71 | + icon: 'none', | ||
| 72 | + }) | ||
| 73 | + } finally { | ||
| 74 | + loading.value = false | ||
| 75 | + } | ||
| 76 | +} | ||
| 77 | + | ||
| 78 | +useLoad(options => { | ||
| 79 | + activityId.value = options.activityId || options.activity_id || options.id || '' | ||
| 80 | + fetchBoothImages() | ||
| 81 | +}) | ||
| 38 | 82 | ||
| 39 | const previewImage = index => { | 83 | const previewImage = index => { |
| 84 | + if (imageList.value.length === 0) { | ||
| 85 | + return | ||
| 86 | + } | ||
| 87 | + | ||
| 40 | Taro.previewImage({ | 88 | Taro.previewImage({ |
| 41 | current: imageList.value[index].url, | 89 | current: imageList.value[index].url, |
| 42 | urls: imageList.value.map(item => item.url), | 90 | urls: imageList.value.map(item => item.url), | ... | ... |
| ... | @@ -57,7 +57,7 @@ import './index.less' | ... | @@ -57,7 +57,7 @@ import './index.less' |
| 57 | import RichTextRenderer from '@/components/RichTextRenderer.vue' | 57 | import RichTextRenderer from '@/components/RichTextRenderer.vue' |
| 58 | import { getCurrentPageFullPath } from '@/utils/authRedirect' | 58 | import { getCurrentPageFullPath } from '@/utils/authRedirect' |
| 59 | import { getMyFamiliesAPI } from '@/api/family' | 59 | import { getMyFamiliesAPI } from '@/api/family' |
| 60 | -import { getScanStageDetailAPI, submitScanCheckinAPI } from '@/api/map' | 60 | +import { getScanStageDetailAPI, submitScanCheckinAPI } from '@/api/map_activity' |
| 61 | import { getUserProfileAPI } from '@/api/user' | 61 | import { getUserProfileAPI } from '@/api/user' |
| 62 | import { verifyCheckinRangeWithCurrentLocation } from '@/utils/checkinLocation' | 62 | import { verifyCheckinRangeWithCurrentLocation } from '@/utils/checkinLocation' |
| 63 | import { | 63 | import { | ... | ... |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2026-05-19 14:40:21 | 2 | * @Date: 2026-05-19 14:40:21 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2026-05-19 15:03:23 | 4 | + * @LastEditTime: 2026-05-21 10:25:21 |
| 5 | * @FilePath: /lls_program/src/pages/ScanCheckinList/index.vue | 5 | * @FilePath: /lls_program/src/pages/ScanCheckinList/index.vue |
| 6 | * @Description: 文件描述 | 6 | * @Description: 文件描述 |
| 7 | --> | 7 | --> |
| ... | @@ -68,7 +68,7 @@ import Taro, { useLoad } from '@tarojs/taro' | ... | @@ -68,7 +68,7 @@ import Taro, { useLoad } from '@tarojs/taro' |
| 68 | import { IconFont, Scan2 } from '@nutui/icons-vue-taro' | 68 | import { IconFont, Scan2 } from '@nutui/icons-vue-taro' |
| 69 | import './index.less' | 69 | import './index.less' |
| 70 | import BottomNav from '@/components/BottomNav.vue' | 70 | import BottomNav from '@/components/BottomNav.vue' |
| 71 | -import { getScanStageListAPI } from '@/api/map' | 71 | +import { getScanStageListAPI } from '@/api/map_activity' |
| 72 | 72 | ||
| 73 | const pointList = ref([]) | 73 | const pointList = ref([]) |
| 74 | const activityId = ref('') | 74 | const activityId = ref('') | ... | ... |
-
Please register or login to post a comment