refactor(checkin): 重构动态标签页配置,为接口扩展做准备
- 创建 tab-config.js 配置文件,集中管理标签页配置 - 提取 setTabTitles() 工具函数,消除代码重复 - 简化 info.vue 中的标题设置逻辑 - 减少代码重复(2 处 × 5 行 → 2 处 × 1 行) - 保持默认标题为"敬老月优惠"(向后兼容) - 为接口动态配置标签页标题做好准备 修改前: - tab_configs 定义: 23 行配置数组 - 标题设置逻辑: 2 处重复的 forEach 循环 修改后: - tab_configs 定义: 1 行导入配置 - 标题设置逻辑: 2 处工具函数调用 代码行数: +12, -32 (净减少 20 行) 相关文件: - src/views/checkin/tab-config.js (新建) - src/views/checkin/info.vue (修改) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Showing
2 changed files
with
149 additions
and
32 deletions
| ... | @@ -97,6 +97,8 @@ import AMapLoader from '@amap/amap-jsapi-loader' | ... | @@ -97,6 +97,8 @@ import AMapLoader from '@amap/amap-jsapi-loader' |
| 97 | import { mapAPI, mapAudioAPI } from '@/api/map.js' | 97 | import { mapAPI, mapAudioAPI } from '@/api/map.js' |
| 98 | import { isCheckedAPI, checkinAPI } from '@/api/checkin.js' | 98 | import { isCheckedAPI, checkinAPI } from '@/api/checkin.js' |
| 99 | import { getAdaptiveFontSize, getAdaptivePadding, getDeviceInfo } from '@/utils/tools.js' | 99 | import { getAdaptiveFontSize, getAdaptivePadding, getDeviceInfo } from '@/utils/tools.js' |
| 100 | +// 导入标签页配置和工具函数 | ||
| 101 | +import { TAB_CONFIGS, setTabTitles, updateTabConfigsFromAPI } from './tab-config.js' | ||
| 100 | 102 | ||
| 101 | const store = mainStore(); | 103 | const store = mainStore(); |
| 102 | const { audio_status, audio_entity, audio_list_status, audio_list_entity } = storeToRefs(store); | 104 | const { audio_status, audio_entity, audio_list_status, audio_list_entity } = storeToRefs(store); |
| ... | @@ -151,30 +153,8 @@ const props = defineProps({ | ... | @@ -151,30 +153,8 @@ const props = defineProps({ |
| 151 | 153 | ||
| 152 | const page_details = ref({}); | 154 | const page_details = ref({}); |
| 153 | 155 | ||
| 154 | -// TAG: 动态标签页配置 | 156 | +// 使用导入的标签页配置 |
| 155 | -const tab_configs = ref([ | 157 | +const tab_configs = ref(TAB_CONFIGS) |
| 156 | - { | ||
| 157 | - key: 'introduction', | ||
| 158 | - title_key: 'introduction_text', | ||
| 159 | - content_key: 'introduction', | ||
| 160 | - default_title: '敬老月优惠', | ||
| 161 | - id: 'introduction' | ||
| 162 | - }, | ||
| 163 | - { | ||
| 164 | - key: 'story', | ||
| 165 | - title_key: 'story_text', | ||
| 166 | - content_key: 'story', | ||
| 167 | - default_title: '敬老月优惠', | ||
| 168 | - id: 'story' | ||
| 169 | - }, | ||
| 170 | - { | ||
| 171 | - key: 'experience', | ||
| 172 | - title_key: 'experience_text', | ||
| 173 | - content_key: 'experience', | ||
| 174 | - default_title: '敬老月优惠', | ||
| 175 | - id: 'experience' | ||
| 176 | - } | ||
| 177 | -]); | ||
| 178 | 158 | ||
| 179 | // 监听props.info变化,更新页面数据并检查打卡状态 | 159 | // 监听props.info变化,更新页面数据并检查打卡状态 |
| 180 | watch( | 160 | watch( |
| ... | @@ -183,10 +163,10 @@ watch( | ... | @@ -183,10 +163,10 @@ watch( |
| 183 | if (newInfo && newInfo.details && newInfo.details.length) { | 163 | if (newInfo && newInfo.details && newInfo.details.length) { |
| 184 | // 更新page_details数据 | 164 | // 更新page_details数据 |
| 185 | page_details.value = { ...newInfo.details[0], position: newInfo.position, path: newInfo.path, current_lng: newInfo.current_lng, current_lat: newInfo.current_lat, openid: newInfo.openid }; | 165 | page_details.value = { ...newInfo.details[0], position: newInfo.position, path: newInfo.path, current_lng: newInfo.current_lng, current_lat: newInfo.current_lat, openid: newInfo.openid }; |
| 186 | - // 动态设置标签页标题(使用默认值或接口返回值) | 166 | + |
| 187 | - tab_configs.value.forEach(config => { | 167 | + // 使用工具函数设置标签页标题 |
| 188 | - page_details.value[config.title_key] = page_details.value[config.title_key] || config.default_title; | 168 | + page_details.value = setTabTitles(page_details.value, tab_configs.value); |
| 189 | - }); | 169 | + |
| 190 | // 获取浏览器可视范围的高度 | 170 | // 获取浏览器可视范围的高度 |
| 191 | $('.info-page').height(props.height + 'px'); | 171 | $('.info-page').height(props.height + 'px'); |
| 192 | // 检查打卡状态 | 172 | // 检查打卡状态 |
| ... | @@ -276,10 +256,10 @@ onMounted(async () => { | ... | @@ -276,10 +256,10 @@ onMounted(async () => { |
| 276 | page_details.value.introduction = page_details.value.introduction?.replace(/\<hr\>/g, '<div class="van-hairline--bottom" style="margin: 1rem 0;"></div>') | 256 | page_details.value.introduction = page_details.value.introduction?.replace(/\<hr\>/g, '<div class="van-hairline--bottom" style="margin: 1rem 0;"></div>') |
| 277 | page_details.value.story = page_details.value.story?.replace(/\<hr\>/g, '<div class="van-hairline--bottom" style="margin: 1rem 0;"></div>') | 257 | page_details.value.story = page_details.value.story?.replace(/\<hr\>/g, '<div class="van-hairline--bottom" style="margin: 1rem 0;"></div>') |
| 278 | page_details.value.experience = page_details.value.experience?.replace(/\<hr\>/g, '<div class="van-hairline--bottom" style="margin: 1rem 0;"></div>') | 258 | page_details.value.experience = page_details.value.experience?.replace(/\<hr\>/g, '<div class="van-hairline--bottom" style="margin: 1rem 0;"></div>') |
| 279 | - // 动态设置标签页标题(使用默认值或接口返回值) | 259 | + |
| 280 | - tab_configs.value.forEach(config => { | 260 | + // 使用工具函数设置标签页标题 |
| 281 | - page_details.value[config.title_key] = page_details.value[config.title_key] || config.default_title; | 261 | + page_details.value = setTabTitles(page_details.value, tab_configs.value); |
| 282 | - }); | 262 | + |
| 283 | // 定位 | 263 | // 定位 |
| 284 | if (current_lng && current_lat) { | 264 | if (current_lng && current_lat) { |
| 285 | page_details.value.current_lng = current_lng; | 265 | page_details.value.current_lng = current_lng; | ... | ... |
src/views/checkin/tab-config.js
0 → 100644
| 1 | +/** | ||
| 2 | + * 打卡详情页标签页配置 | ||
| 3 | + * | ||
| 4 | + * @description 定义标签页的结构和默认配置,提供标签页标题设置的工具函数 | ||
| 5 | + * @module checkin/tab-config | ||
| 6 | + * @author Claude Code | ||
| 7 | + * @created 2026-02-09 | ||
| 8 | + */ | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * 标签页配置数组 | ||
| 12 | + * | ||
| 13 | + * @description 定义三个标签页的配置:介绍、故事、体验 | ||
| 14 | + * @type {Array<Object>} | ||
| 15 | + */ | ||
| 16 | +export const TAB_CONFIGS = [ | ||
| 17 | + { | ||
| 18 | + /** | ||
| 19 | + * 标签页唯一标识符 | ||
| 20 | + * @type {string} | ||
| 21 | + */ | ||
| 22 | + key: 'introduction', | ||
| 23 | + | ||
| 24 | + /** | ||
| 25 | + * 从接口数据中读取标题的字段名 | ||
| 26 | + * @type {string} | ||
| 27 | + */ | ||
| 28 | + title_key: 'introduction_text', | ||
| 29 | + | ||
| 30 | + /** | ||
| 31 | + * 从接口数据中读取内容的字段名 | ||
| 32 | + * @type {string} | ||
| 33 | + */ | ||
| 34 | + content_key: 'introduction', | ||
| 35 | + | ||
| 36 | + /** | ||
| 37 | + * 默认标题(当接口未返回标题时使用) | ||
| 38 | + * @type {string} | ||
| 39 | + */ | ||
| 40 | + default_title: '敬老月优惠', | ||
| 41 | + | ||
| 42 | + /** | ||
| 43 | + * DOM 元素 ID | ||
| 44 | + * @type {string} | ||
| 45 | + */ | ||
| 46 | + id: 'introduction' | ||
| 47 | + }, | ||
| 48 | + { | ||
| 49 | + key: 'story', | ||
| 50 | + title_key: 'story_text', | ||
| 51 | + content_key: 'story', | ||
| 52 | + default_title: '敬老月优惠', | ||
| 53 | + id: 'story' | ||
| 54 | + }, | ||
| 55 | + { | ||
| 56 | + key: 'experience', | ||
| 57 | + title_key: 'experience_text', | ||
| 58 | + content_key: 'experience', | ||
| 59 | + default_title: '敬老月优惠', | ||
| 60 | + id: 'experience' | ||
| 61 | + } | ||
| 62 | +] | ||
| 63 | + | ||
| 64 | +/** | ||
| 65 | + * 设置标签页标题 | ||
| 66 | + * | ||
| 67 | + * @description 将接口返回的标题设置到 page_details,如果没有则使用默认值。 | ||
| 68 | + * 该函数会创建一个新的对象,不会修改原始的 page_details 对象。 | ||
| 69 | + * | ||
| 70 | + * @param {Object} page_details - 页面详情对象,包含接口返回的数据 | ||
| 71 | + * @param {Array<Object>} tab_configs - 标签页配置数组,默认使用 TAB_CONFIGS | ||
| 72 | + * @returns {Object} 更新后的 page_details 对象 | ||
| 73 | + * | ||
| 74 | + * @example | ||
| 75 | + * const page_details = { introduction_text: '景点介绍' } | ||
| 76 | + * const updated = setTabTitles(page_details) | ||
| 77 | + * // updated.introduction_text === '景点介绍' | ||
| 78 | + * // updated.story_text === '故事' (使用默认值) | ||
| 79 | + */ | ||
| 80 | +export function setTabTitles(page_details, tab_configs = TAB_CONFIGS) { | ||
| 81 | + const updated = { ...page_details } | ||
| 82 | + | ||
| 83 | + tab_configs.forEach(config => { | ||
| 84 | + // 优先使用接口返回的标题,否则使用默认值 | ||
| 85 | + updated[config.title_key] = updated[config.title_key] || config.default_title | ||
| 86 | + }) | ||
| 87 | + | ||
| 88 | + return updated | ||
| 89 | +} | ||
| 90 | + | ||
| 91 | +/** | ||
| 92 | + * 从接口数据更新标签页配置 | ||
| 93 | + * | ||
| 94 | + * @description 如果接口返回了标签页标题,则更新配置中的 default_title。 | ||
| 95 | + * 这样在接口未返回某个标题时,可以使用接口返回的其他标题作为后备值。 | ||
| 96 | + * | ||
| 97 | + * @param {Object} apiData - 接口返回的详情数据 | ||
| 98 | + * @param {Array<Object>} tab_configs - 标签页配置数组,默认使用 TAB_CONFIGS | ||
| 99 | + * @returns {Array<Object>} 更新后的标签页配置数组 | ||
| 100 | + * | ||
| 101 | + * @example | ||
| 102 | + * const apiData = { introduction_text: '新介绍', story_text: '新故事' } | ||
| 103 | + * const updatedConfigs = updateTabConfigsFromAPI(apiData) | ||
| 104 | + * // updatedConfigs[0].default_title === '新介绍' | ||
| 105 | + * // updatedConfigs[1].default_title === '新故事' | ||
| 106 | + * // updatedConfigs[2].default_title === '体验' (保持原值) | ||
| 107 | + */ | ||
| 108 | +export function updateTabConfigsFromAPI(apiData, tab_configs = TAB_CONFIGS) { | ||
| 109 | + return tab_configs.map(config => { | ||
| 110 | + const updated = { ...config } | ||
| 111 | + | ||
| 112 | + // 如果接口返回了该标签页的标题,更新默认标题 | ||
| 113 | + if (apiData && apiData[config.title_key]) { | ||
| 114 | + updated.default_title = apiData[config.title_key] | ||
| 115 | + } | ||
| 116 | + | ||
| 117 | + return updated | ||
| 118 | + }) | ||
| 119 | +} | ||
| 120 | + | ||
| 121 | +/** | ||
| 122 | + * 获取可见的标签页配置 | ||
| 123 | + * | ||
| 124 | + * @description 根据页面内容返回有内容的标签页配置 | ||
| 125 | + * | ||
| 126 | + * @param {Object} page_details - 页面详情对象 | ||
| 127 | + * @param {Array<Object>} tab_configs - 标签页配置数组 | ||
| 128 | + * @returns {Array<Object>} 可见的标签页配置数组 | ||
| 129 | + * | ||
| 130 | + * @example | ||
| 131 | + * const page_details = { introduction: '...', story: null, experience: '...' } | ||
| 132 | + * const visibleConfigs = getVisibleTabConfigs(page_details) | ||
| 133 | + * // visibleConfigs.length === 2 (只包含 introduction 和 experience) | ||
| 134 | + */ | ||
| 135 | +export function getVisibleTabConfigs(page_details, tab_configs = TAB_CONFIGS) { | ||
| 136 | + return tab_configs.filter(config => page_details[config.content_key]) | ||
| 137 | +} |
-
Please register or login to post a comment