feat(tabbar): 新增底部导航激活态颜色自定义功能并优化UI样式
新增底部导航激活色默认常量与颜色格式化工具函数,在tabbar状态仓库中添加激活色状态并根据接口配置动态更新对应值,更新示例配置文件添加示例颜色,同时优化组件样式:调整容器高度、字体大小与间距,使用动态激活色替代硬编码值,移除冗余的激活态样式类
Showing
4 changed files
with
39 additions
and
15 deletions
| ... | @@ -21,7 +21,7 @@ | ... | @@ -21,7 +21,7 @@ |
| 21 | :style="itemStyle" | 21 | :style="itemStyle" |
| 22 | @tap="handleTabClick(item)" | 22 | @tap="handleTabClick(item)" |
| 23 | > | 23 | > |
| 24 | - <view class="app-tabbar__item-inner"> | 24 | + <view class="app-tabbar__item-inner" :style="getItemInnerStyle(item)"> |
| 25 | <view class="app-tabbar__icon"> | 25 | <view class="app-tabbar__icon"> |
| 26 | <i | 26 | <i |
| 27 | class="app-tabbar__icon-font" | 27 | class="app-tabbar__icon-font" |
| ... | @@ -63,6 +63,7 @@ const scrollableSidePadding = 60 | ... | @@ -63,6 +63,7 @@ const scrollableSidePadding = 60 |
| 63 | 63 | ||
| 64 | const tabbarStore = useTabbarStore() | 64 | const tabbarStore = useTabbarStore() |
| 65 | const tabItems = computed(() => tabbarStore.visibleTabItems) | 65 | const tabItems = computed(() => tabbarStore.visibleTabItems) |
| 66 | +const activeColor = computed(() => tabbarStore.activeColor) | ||
| 66 | const currentKey = computed(() => normalizeTabbarKey(props.current)) | 67 | const currentKey = computed(() => normalizeTabbarKey(props.current)) |
| 67 | const isScrollable = computed(() => tabItems.value.length > 4) | 68 | const isScrollable = computed(() => tabItems.value.length > 4) |
| 68 | const showScrollHint = computed(() => isScrollable.value) | 69 | const showScrollHint = computed(() => isScrollable.value) |
| ... | @@ -98,6 +99,16 @@ let scrollHintResetTimer = null | ... | @@ -98,6 +99,16 @@ let scrollHintResetTimer = null |
| 98 | 99 | ||
| 99 | const isActive = (key) => key === currentKey.value | 100 | const isActive = (key) => key === currentKey.value |
| 100 | 101 | ||
| 102 | +const getItemInnerStyle = (item) => { | ||
| 103 | + if (!isActive(item?.key)) { | ||
| 104 | + return null | ||
| 105 | + } | ||
| 106 | + | ||
| 107 | + return { | ||
| 108 | + color: activeColor.value, | ||
| 109 | + } | ||
| 110 | +} | ||
| 111 | + | ||
| 101 | const getIconClass = (item) => { | 112 | const getIconClass = (item) => { |
| 102 | const icon = String(item?.class || item?.icon || defaultIcon).trim() || defaultIcon | 113 | const icon = String(item?.class || item?.icon || defaultIcon).trim() || defaultIcon |
| 103 | const fontClass = icon.startsWith('fa-') ? 'fa' : 'iconfont' | 114 | const fontClass = icon.startsWith('fa-') ? 'fa' : 'iconfont' |
| ... | @@ -199,7 +210,7 @@ onBeforeUnmount(() => { | ... | @@ -199,7 +210,7 @@ onBeforeUnmount(() => { |
| 199 | } | 210 | } |
| 200 | 211 | ||
| 201 | .app-tabbar__panel { | 212 | .app-tabbar__panel { |
| 202 | - height: 132rpx; | 213 | + height: 140rpx; |
| 203 | border-top: 2rpx solid rgba(166, 121, 57, 0.12); | 214 | border-top: 2rpx solid rgba(166, 121, 57, 0.12); |
| 204 | background: rgba(255, 255, 255, 0.98); | 215 | background: rgba(255, 255, 255, 0.98); |
| 205 | box-sizing: border-box; | 216 | box-sizing: border-box; |
| ... | @@ -237,7 +248,7 @@ onBeforeUnmount(() => { | ... | @@ -237,7 +248,7 @@ onBeforeUnmount(() => { |
| 237 | flex-direction: column; | 248 | flex-direction: column; |
| 238 | align-items: center; | 249 | align-items: center; |
| 239 | justify-content: center; | 250 | justify-content: center; |
| 240 | - gap: 10rpx; | 251 | + gap: 12rpx; |
| 241 | min-height: 100rpx; | 252 | min-height: 100rpx; |
| 242 | border-radius: 20rpx; | 253 | border-radius: 20rpx; |
| 243 | color: #8b95a7; | 254 | color: #8b95a7; |
| ... | @@ -249,8 +260,8 @@ onBeforeUnmount(() => { | ... | @@ -249,8 +260,8 @@ onBeforeUnmount(() => { |
| 249 | align-items: center; | 260 | align-items: center; |
| 250 | justify-content: center; | 261 | justify-content: center; |
| 251 | line-height: 1; | 262 | line-height: 1; |
| 252 | - color: #8b95a7; | 263 | + color: inherit; |
| 253 | - font-size: 38rpx; | 264 | + font-size: 48rpx; |
| 254 | } | 265 | } |
| 255 | 266 | ||
| 256 | .app-tabbar__icon-font { | 267 | .app-tabbar__icon-font { |
| ... | @@ -258,17 +269,9 @@ onBeforeUnmount(() => { | ... | @@ -258,17 +269,9 @@ onBeforeUnmount(() => { |
| 258 | } | 269 | } |
| 259 | 270 | ||
| 260 | .app-tabbar__label { | 271 | .app-tabbar__label { |
| 261 | - font-size: 22rpx; | 272 | + font-size: 28rpx; |
| 262 | font-weight: 600; | 273 | font-weight: 600; |
| 263 | - line-height: 1.2; | 274 | + line-height: 1.25; |
| 264 | - } | ||
| 265 | - | ||
| 266 | - .app-tabbar__item.is-active .app-tabbar__item-inner { | ||
| 267 | - color: #a67939; | ||
| 268 | - } | ||
| 269 | - | ||
| 270 | - .app-tabbar__item.is-active .app-tabbar__icon { | ||
| 271 | - color: #a67939; | ||
| 272 | } | 275 | } |
| 273 | 276 | ||
| 274 | .app-tabbar__fade { | 277 | .app-tabbar__fade { | ... | ... |
| ... | @@ -19,4 +19,5 @@ export const getTabbarConfigFixture = () => ({ | ... | @@ -19,4 +19,5 @@ export const getTabbarConfigFixture = () => ({ |
| 19 | icon: 'fa-user', | 19 | icon: 'fa-user', |
| 20 | link: 'https://oa-dev.onwall.cn/f/futian_home/?f=f&p=futian_list', | 20 | link: 'https://oa-dev.onwall.cn/f/futian_home/?f=f&p=futian_list', |
| 21 | }, | 21 | }, |
| 22 | + color: '#86190C', | ||
| 22 | }) | 23 | }) | ... | ... |
| 1 | import { defineStore } from 'pinia' | 1 | import { defineStore } from 'pinia' |
| 2 | import { getTabbarConfigAPI } from '@/api/tabbar' | 2 | import { getTabbarConfigAPI } from '@/api/tabbar' |
| 3 | import { | 3 | import { |
| 4 | + getDefaultTabbarActiveColor, | ||
| 4 | getDefaultTabbarItem, | 5 | getDefaultTabbarItem, |
| 5 | getHomeOnlyTabbarItems, | 6 | getHomeOnlyTabbarItems, |
| 6 | normalizeTabbarKey, | 7 | normalizeTabbarKey, |
| 8 | + normalizeTabbarColor, | ||
| 7 | normalizeTabbarPayload, | 9 | normalizeTabbarPayload, |
| 8 | } from '@/utils/tabbar' | 10 | } from '@/utils/tabbar' |
| 9 | 11 | ||
| ... | @@ -12,6 +14,7 @@ let tabbarRequestPromise = null | ... | @@ -12,6 +14,7 @@ let tabbarRequestPromise = null |
| 12 | export const useTabbarStore = defineStore('tabbar', { | 14 | export const useTabbarStore = defineStore('tabbar', { |
| 13 | state: () => ({ | 15 | state: () => ({ |
| 14 | tabItems: getHomeOnlyTabbarItems(), | 16 | tabItems: getHomeOnlyTabbarItems(), |
| 17 | + activeColor: getDefaultTabbarActiveColor(), | ||
| 15 | loaded: false, | 18 | loaded: false, |
| 16 | loading: false, | 19 | loading: false, |
| 17 | }), | 20 | }), |
| ... | @@ -40,12 +43,15 @@ export const useTabbarStore = defineStore('tabbar', { | ... | @@ -40,12 +43,15 @@ export const useTabbarStore = defineStore('tabbar', { |
| 40 | 43 | ||
| 41 | if (response?.code === 1) { | 44 | if (response?.code === 1) { |
| 42 | this.tabItems = normalizeTabbarPayload(response?.data) | 45 | this.tabItems = normalizeTabbarPayload(response?.data) |
| 46 | + this.activeColor = normalizeTabbarColor(response?.data) | ||
| 43 | } else { | 47 | } else { |
| 44 | this.tabItems = getHomeOnlyTabbarItems() | 48 | this.tabItems = getHomeOnlyTabbarItems() |
| 49 | + this.activeColor = getDefaultTabbarActiveColor() | ||
| 45 | } | 50 | } |
| 46 | } catch (error) { | 51 | } catch (error) { |
| 47 | console.error('获取底部导航配置失败:', error) | 52 | console.error('获取底部导航配置失败:', error) |
| 48 | this.tabItems = getHomeOnlyTabbarItems() | 53 | this.tabItems = getHomeOnlyTabbarItems() |
| 54 | + this.activeColor = getDefaultTabbarActiveColor() | ||
| 49 | } finally { | 55 | } finally { |
| 50 | this.loaded = true | 56 | this.loaded = true |
| 51 | this.loading = false | 57 | this.loading = false | ... | ... |
| ... | @@ -47,6 +47,7 @@ const KNOWN_TABBAR_ITEM_MAP = { | ... | @@ -47,6 +47,7 @@ const KNOWN_TABBAR_ITEM_MAP = { |
| 47 | 47 | ||
| 48 | export const TABBAR_ORDER = ['home', 'news', 'list', 'user'] | 48 | export const TABBAR_ORDER = ['home', 'news', 'list', 'user'] |
| 49 | const DEFAULT_ICON_CLASS = 'fa-circle-o' | 49 | const DEFAULT_ICON_CLASS = 'fa-circle-o' |
| 50 | +const DEFAULT_TABBAR_ACTIVE_COLOR = '#a67939' | ||
| 50 | 51 | ||
| 51 | const normalizeVisibleValue = (rawValue, fallbackValue = true) => { | 52 | const normalizeVisibleValue = (rawValue, fallbackValue = true) => { |
| 52 | if (typeof rawValue === 'boolean') { | 53 | if (typeof rawValue === 'boolean') { |
| ... | @@ -100,6 +101,19 @@ export const getDefaultTabbarItems = () => ( | ... | @@ -100,6 +101,19 @@ export const getDefaultTabbarItems = () => ( |
| 100 | 101 | ||
| 101 | export const getHomeOnlyTabbarItems = () => [getDefaultTabbarItem('home')] | 102 | export const getHomeOnlyTabbarItems = () => [getDefaultTabbarItem('home')] |
| 102 | 103 | ||
| 104 | +export const getDefaultTabbarActiveColor = () => DEFAULT_TABBAR_ACTIVE_COLOR | ||
| 105 | + | ||
| 106 | +export const normalizeTabbarColor = (rawPayload = null) => { | ||
| 107 | + const rawColor = rawPayload?.color | ||
| 108 | + | ||
| 109 | + if (typeof rawColor !== 'string') { | ||
| 110 | + return DEFAULT_TABBAR_ACTIVE_COLOR | ||
| 111 | + } | ||
| 112 | + | ||
| 113 | + const normalizedColor = rawColor.trim() | ||
| 114 | + return normalizedColor || DEFAULT_TABBAR_ACTIVE_COLOR | ||
| 115 | +} | ||
| 116 | + | ||
| 103 | const buildTabbarPageUrl = (key, webviewUrl, webviewTitle, rawPageUrl = '') => { | 117 | const buildTabbarPageUrl = (key, webviewUrl, webviewTitle, rawPageUrl = '') => { |
| 104 | if (key === 'home') { | 118 | if (key === 'home') { |
| 105 | return rawPageUrl || '/pages/index/index' | 119 | return rawPageUrl || '/pages/index/index' | ... | ... |
-
Please register or login to post a comment