style:首页-功能导航-更多-底部弹框添加过度动画

master
黄伟杰 1 day ago
parent b5f7848ede
commit 8392b5d63a

@ -1,6 +1,7 @@
<template> <template>
<view class="tabbar-shell" :class="{ 'is-hidden': !tabbarVisible }">
<up-tabbar :value="activeIndex" :activeColor="activeColor" :inactiveColor="inactiveColor" :safeAreaInsetBottom="true" <up-tabbar :value="activeIndex" :activeColor="activeColor" :inactiveColor="inactiveColor" :safeAreaInsetBottom="true"
:fixed="true" :placeholder="true" :border="false" @change="handleChange" zIndex="100"> :fixed="true" :placeholder="true" :border="false" @change="handleChange" zIndex="1000">
<up-tabbar-item v-for="(item, index) in tabList" :key="index" :text="item.text" :name="index"> <up-tabbar-item v-for="(item, index) in tabList" :key="index" :text="item.text" :name="index">
<template #active-icon> <template #active-icon>
<image :src="item.selectedIcon" class="tabbar-icon" mode="widthFix" /> <image :src="item.selectedIcon" class="tabbar-icon" mode="widthFix" />
@ -10,15 +11,18 @@
</template> </template>
</up-tabbar-item> </up-tabbar-item>
</up-tabbar> </up-tabbar>
</view>
</template> </template>
<script setup> <script setup>
import { ref, computed, onMounted, watch } from 'vue' import { ref, computed, onMounted, onUnmounted, watch } from 'vue'
import useUserStore from '@/store/modules/user' import useUserStore from '@/store/modules/user'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { getDynamicTabMenus } from '@/utils/permissionMenu' import { getDynamicTabMenus } from '@/utils/permissionMenu'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
const TABBAR_VISIBILITY_EVENT = 'tabbar-visibility-change'
const { t } = useI18n() const { t } = useI18n()
const userStore = useUserStore() const userStore = useUserStore()
const { menus } = storeToRefs(userStore) const { menus } = storeToRefs(userStore)
@ -27,6 +31,7 @@ const inactiveColor = '#666666'
const activeColor = '#1a3a5c' const activeColor = '#1a3a5c'
const activeIndex = ref(0) const activeIndex = ref(0)
const tabbarVisible = ref(true)
const homeIcon = '/static/images/tabbar/home.png' const homeIcon = '/static/images/tabbar/home.png'
const homeSelectedIcon = '/static/images/tabbar/home_.png' const homeSelectedIcon = '/static/images/tabbar/home_.png'
@ -86,8 +91,17 @@ const tabList = computed(() => {
onMounted(() => { onMounted(() => {
activeIndex.value = getCurrentActiveIndex() activeIndex.value = getCurrentActiveIndex()
uni.$on(TABBAR_VISIBILITY_EVENT, handleTabbarVisibility)
})
onUnmounted(() => {
uni.$off(TABBAR_VISIBILITY_EVENT, handleTabbarVisibility)
}) })
function handleTabbarVisibility(visible = true) {
tabbarVisible.value = visible !== false
}
function handleChange(index) { function handleChange(index) {
if (activeIndex.value === index) return if (activeIndex.value === index) return
activeIndex.value = index activeIndex.value = index
@ -105,6 +119,35 @@ watch(() => useUserStore().menus, () => {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.tabbar-shell {
position: relative;
:deep(.u-tabbar) {
position: fixed !important;
left: 0;
right: 0;
bottom: 0 !important;
width: 100%;
z-index: 1000 !important;
transform: translateY(0);
opacity: 1;
will-change: transform, opacity;
transition: transform 0.36s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.24s ease;
}
:deep(.u-tabbar__content) {
z-index: 1000 !important;
}
&.is-hidden {
:deep(.u-tabbar) {
transform: translateY(calc(100% + 24rpx + env(safe-area-inset-bottom)));
opacity: 0;
pointer-events: none;
}
}
}
.tabbar-icon { .tabbar-icon {
width: 48rpx; width: 48rpx;
height: 48rpx; height: 48rpx;

@ -209,10 +209,9 @@ watch(() => props.visible, async (val) => {
right: 0; right: 0;
bottom: 0; bottom: 0;
background: rgba(0, 0, 0, 0.5); background: rgba(0, 0, 0, 0.5);
z-index: 1000; z-index: 1100;
display: flex; display: flex;
align-items: flex-end; align-items: flex-end;
padding-bottom: calc(90rpx + env(safe-area-inset-bottom));
box-sizing: border-box; box-sizing: border-box;
transition: opacity 0.3s ease; transition: opacity 0.3s ease;

@ -122,10 +122,9 @@ function handleClose() {
right: 0; right: 0;
bottom: 0; bottom: 0;
background: rgba(0, 0, 0, 0.5); background: rgba(0, 0, 0, 0.5);
z-index: 1000; z-index: 1100;
display: flex; display: flex;
align-items: flex-end; align-items: flex-end;
padding-bottom: calc(90rpx + env(safe-area-inset-bottom));
box-sizing: border-box; box-sizing: border-box;
transition: opacity 0.3s ease; transition: opacity 0.3s ease;
@ -192,7 +191,7 @@ function handleClose() {
.more-content { .more-content {
flex: 1; flex: 1;
padding: 24rpx; padding: 24rpx 24rpx calc(24rpx + env(safe-area-inset-bottom));
} }
.empty-state { .empty-state {

@ -32,7 +32,7 @@
</template> </template>
<script setup> <script setup>
import { ref, computed, onMounted, watch } from 'vue' import { ref, computed, onMounted, onUnmounted, watch } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { getUserNavMenuList } from '@/api/system/userNavMenu' import { getUserNavMenuList } from '@/api/system/userNavMenu'
import { getNavPermissionInfo } from '@/api/login' import { getNavPermissionInfo } from '@/api/login'
@ -41,6 +41,7 @@ import NavMenuMore from './NavMenuMore.vue'
import NavMenuEditor from './NavMenuEditor.vue' import NavMenuEditor from './NavMenuEditor.vue'
const { t } = useI18n() const { t } = useI18n()
const TABBAR_VISIBILITY_EVENT = 'tabbar-visibility-change'
function hexToRgba(hex, alpha) { function hexToRgba(hex, alpha) {
const value = String(hex || '').replace('#', '') const value = String(hex || '').replace('#', '')
@ -103,6 +104,9 @@ const moreNavList = computed(() => {
return configuredMenuList.value return configuredMenuList.value
}) })
const modalVisible = computed(() => showMoreModal.value || showEditModal.value)
let tabbarRestoreTimer = null
async function loadConfiguredMenus() { async function loadConfiguredMenus() {
try { try {
const menuRes = await getNavPermissionInfo() const menuRes = await getNavPermissionInfo()
@ -160,6 +164,31 @@ function handleUpdate() {
onMounted(() => { onMounted(() => {
loadConfiguredMenus() loadConfiguredMenus()
}) })
onUnmounted(() => {
if (tabbarRestoreTimer) {
clearTimeout(tabbarRestoreTimer)
tabbarRestoreTimer = null
}
uni.$emit(TABBAR_VISIBILITY_EVENT, true)
})
watch(modalVisible, (visible) => {
if (tabbarRestoreTimer) {
clearTimeout(tabbarRestoreTimer)
tabbarRestoreTimer = null
}
if (visible) {
uni.$emit(TABBAR_VISIBILITY_EVENT, false)
return
}
tabbarRestoreTimer = setTimeout(() => {
uni.$emit(TABBAR_VISIBILITY_EVENT, true)
tabbarRestoreTimer = null
}, 300)
}, { immediate: true })
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

Loading…
Cancel
Save