refactor(layout): move safe-area logic to HeaderBar with fallback to scaffold
This commit is contained in:
@@ -6,8 +6,6 @@
|
||||
'bg-cover bg-center bg-no-repeat': props.backgroundImage
|
||||
}"
|
||||
:style="mergedStyle">
|
||||
<!-- 顶部安全区域 -->
|
||||
<div :class="[{ 'safe-area-top': safeAreaTop }, props.topSafeAreaClass]" />
|
||||
|
||||
<!-- 内容区域 -->
|
||||
<div class="flex-1 min-h-0">
|
||||
@@ -234,9 +232,6 @@ useMitt.on(WsResponseMessageType.RECEIVE_MESSAGE, async (data: MessageType) => {
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.safe-area-top {
|
||||
padding-top: var(--safe-area-inset-top);
|
||||
}
|
||||
.safe-area-bottom {
|
||||
padding-bottom: var(--safe-area-inset-bottom);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<img v-if="bgmURL" :src="bgmURL" class="absolute fixed top-0 left-0 w-full h-full z-0 dark:opacity-20" />
|
||||
<!-- 页面容器 -->
|
||||
<div class="flex w-full items-start flex-col flex-1 min-h-0 z-1">
|
||||
<div class="w-full">
|
||||
<div class="w-full" :class="{ 'pt-[var(--safe-area-inset-top)]': safeAreaRef }">
|
||||
<slot name="header"></slot>
|
||||
</div>
|
||||
<!-- 消息内容区 -->
|
||||
@@ -19,11 +19,31 @@
|
||||
<script setup lang="ts">
|
||||
import bgImg from '@/assets/mobile/chat-home/background.webp'
|
||||
|
||||
const { showFooter = true, background = true } = defineProps<{ showFooter?: boolean; background?: string | boolean }>()
|
||||
const {
|
||||
showFooter = true,
|
||||
background = true,
|
||||
safeArea = true
|
||||
} = defineProps<{
|
||||
showFooter?: boolean
|
||||
background?: string | boolean
|
||||
safeArea?: boolean
|
||||
}>()
|
||||
|
||||
const bgmURL = computed(() => {
|
||||
return typeof background === 'boolean' && background ? bgImg : background
|
||||
})
|
||||
|
||||
const safeAreaRef = useSafeArea(() => safeArea)
|
||||
|
||||
function useSafeArea(getter: () => boolean) {
|
||||
const safeArea = ref(true)
|
||||
// 移除脚手架提供的安全区域样式,交由组件自己控制
|
||||
const removeSafeArea = () => {
|
||||
safeArea.value = false
|
||||
}
|
||||
provide('removeSafeArea', removeSafeArea)
|
||||
return computed(() => safeArea.value && getter())
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss"></style>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<div class="w-full h-[56px] grid grid-cols-[100px_1fr_100px] z-2 bg-background text-foreground">
|
||||
<div
|
||||
class="w-full h-[56px] grid grid-cols-[100px_1fr_100px] z-2 bg-background text-foreground pt-[var(--safe-area-inset-top)]">
|
||||
<div @click="handleBack" class="w-full h-full flex items-center">
|
||||
<svg class="iconpark-icon w-24px h-24px ms-16px p-5px">
|
||||
<use href="#fanhui" class="text-foreground"></use>
|
||||
@@ -51,6 +52,10 @@ const props = withDefaults(defineProps<HeaderBarProps>(), {
|
||||
border: false
|
||||
})
|
||||
|
||||
// 移除脚手架提供的安全区域样式,交由组件自己控制
|
||||
const removeScaffoldSaveArea = inject<() => void>('removeSafeArea', () => undefined)
|
||||
removeScaffoldSaveArea()
|
||||
|
||||
const emits = defineEmits<(e: 'roomNameClick', payload: HeaderBarProps) => void>()
|
||||
|
||||
const handleRoomNameClick = () => {
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
<template>
|
||||
<AutoFixHeightPage>
|
||||
<template #container>
|
||||
<div class="flex flex-col overflow-auto h-full relative">
|
||||
<img
|
||||
src="@/assets/mobile/chat-home/background.webp"
|
||||
class="absolute fixed top-0 left-0 w-full h-full z-0 dark:opacity-20" />
|
||||
<!-- 页面蒙板 -->
|
||||
<div
|
||||
v-if="showMask"
|
||||
@@ -111,7 +110,9 @@
|
||||
{{ getUserState(item.uid)?.title }}
|
||||
</template>
|
||||
<template v-else>
|
||||
<n-badge :color="item.activeStatus === OnlineEnum.ONLINE ? '#1ab292' : '#909090'" dot />
|
||||
<n-badge
|
||||
:color="item.activeStatus === OnlineEnum.ONLINE ? '#1ab292' : '#909090'"
|
||||
dot />
|
||||
{{ item.activeStatus === OnlineEnum.ONLINE ? '在线' : '离线' }}
|
||||
</template>
|
||||
]
|
||||
@@ -158,6 +159,8 @@
|
||||
</n-card>
|
||||
</div>
|
||||
</template>
|
||||
</AutoFixHeightPage>
|
||||
</template>
|
||||
<style scoped>
|
||||
.custom-rounded {
|
||||
border-top-left-radius: 20px; /* 左上角 */
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
<template>
|
||||
<AutoFixHeightPage>
|
||||
<template #container>
|
||||
<div class="flex flex-col overflow-auto h-full relative">
|
||||
<img
|
||||
src="@/assets/mobile/chat-home/background.webp"
|
||||
class="absolute fixed top-0 l-0 w-full h-full z-0 dark:opacity-20" />
|
||||
|
||||
<!-- 页面蒙板 -->
|
||||
<div
|
||||
v-if="showMask"
|
||||
@@ -119,7 +117,11 @@
|
||||
:color="item.muteNotification === NotificationTypeEnum.NOT_DISTURB ? 'grey' : '#c14053'"
|
||||
:value="item.unreadCount"
|
||||
:max="99">
|
||||
<n-avatar :size="52" :src="AvatarUtils.getAvatarUrl(item.avatar)" fallback-src="/logo.png" round />
|
||||
<n-avatar
|
||||
:size="52"
|
||||
:src="AvatarUtils.getAvatarUrl(item.avatar)"
|
||||
fallback-src="/logo.png"
|
||||
round />
|
||||
</n-badge>
|
||||
</div>
|
||||
<!-- 中间:两行内容 -->
|
||||
@@ -184,13 +186,17 @@
|
||||
:style="{ top: longPressState.longPressMenuTop + 'px' }"
|
||||
class="fixed gap-10px z-999 left-1/2 transform -translate-x-1/2">
|
||||
<div class="flex justify-between p-18px text-16px gap-22px rounded-16px bg-#4e4e4e whitespace-nowrap">
|
||||
<div class="text-white" @click="handleDelete(currentLongPressItem)">{{ t('mobile_home.menu.delete') }}</div>
|
||||
<div class="text-white" @click="handleDelete(currentLongPressItem)">
|
||||
{{ t('mobile_home.menu.delete') }}
|
||||
</div>
|
||||
<div class="text-white" @click="handleToggleTop(currentLongPressItem)">
|
||||
{{ currentLongPressItem?.top ? t('mobile_home.menu.unpin') : t('mobile_home.menu.pintop') }}
|
||||
</div>
|
||||
<div class="text-white" @click="handleToggleReadStatus((currentLongPressItem?.unreadCount ?? 0) > 0)">
|
||||
{{
|
||||
(currentLongPressItem?.unreadCount ?? 0) > 0 ? t('mobile_home.menu.read') : t('mobile_home.menu.unread')
|
||||
(currentLongPressItem?.unreadCount ?? 0) > 0
|
||||
? t('mobile_home.menu.read')
|
||||
: t('mobile_home.menu.unread')
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
@@ -203,6 +209,8 @@
|
||||
</teleport>
|
||||
</div>
|
||||
</template>
|
||||
</AutoFixHeightPage>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useDebounceFn, useThrottleFn } from '@vueuse/core'
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
<template>
|
||||
<AutoFixHeightPage :show-footer="false">
|
||||
<template #container>
|
||||
<div class="flex flex-col overflow-auto h-full">
|
||||
<!-- 设置区 -->
|
||||
<Settings />
|
||||
|
||||
<PersonalInfo :is-show="isShow"></PersonalInfo>
|
||||
|
||||
<!-- FIX: 内容消失,问题 待确定 -->
|
||||
<div class="relative top-0 flex-1 flex">
|
||||
<div ref="measureRef" class="h-full w-full absolute top-0 z-0"></div>
|
||||
<!-- 动态内容 -->
|
||||
@@ -45,6 +48,8 @@
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</AutoFixHeightPage>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import PersonalInfo from '#/components/my/PersonalInfo.vue'
|
||||
import Settings from '#/components/my/Settings.vue'
|
||||
|
||||
Reference in New Issue
Block a user