356 lines
14 KiB
Vue
356 lines
14 KiB
Vue
<style lang="scss" scoped>
|
|||
|
|
|
||
|
|
|
||
|
|
.phoneCom {
|
||
|
|
position: fixed;
|
||
|
|
width: 750rpx;
|
||
|
|
top: 0;
|
||
|
|
left: 0;
|
||
|
|
background-color: transparent;
|
||
|
|
z-index: v-bind(zIndex);
|
||
|
|
|
||
|
|
.phone-wifi {
|
||
|
|
height: v-bind(wifi_px);
|
||
|
|
}
|
||
|
|
|
||
|
|
.phone-nav {
|
||
|
|
height: v-bind(nav_px_height);
|
||
|
|
box-sizing: border-box;
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
|
||
|
|
.meun-height {
|
||
|
|
height: v-bind(meun_px_height);
|
||
|
|
width: 750rpx;
|
||
|
|
display: flex;
|
||
|
|
|
||
|
|
.uniui-left {
|
||
|
|
width: v-bind(rpxLeftWidth);
|
||
|
|
display: flex;
|
||
|
|
height: v-bind(meun_px_height);;
|
||
|
|
}
|
||
|
|
|
||
|
|
.meun-widht-left {
|
||
|
|
width: v-bind(divMeunWidht);
|
||
|
|
height: v-bind(meun_px_height);
|
||
|
|
display: flex;
|
||
|
|
justify-content: center;
|
||
|
|
align-items: center;
|
||
|
|
position: relative;
|
||
|
|
|
||
|
|
:deep(.customClass-icon) {
|
||
|
|
height: v-bind(meun_px_height);
|
||
|
|
|
||
|
|
text-align: center;
|
||
|
|
line-height: v-bind(meun_px_height);
|
||
|
|
position: absolute;
|
||
|
|
top: 50%;
|
||
|
|
left: 50%;
|
||
|
|
transform: translate(-50%, -50%); /* 关键:自身偏移回中心 */
|
||
|
|
}
|
||
|
|
|
||
|
|
.meun-widht-rightimage_item {
|
||
|
|
height: v-bind(imgWidthHeight);
|
||
|
|
width: v-bind(imgWidthHeight);
|
||
|
|
position: absolute;
|
||
|
|
top: 50%;
|
||
|
|
left: 50%;
|
||
|
|
transform: translate(-50%, -50%); /* 关键:自身偏移回中心 */
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
.meun-widht-middle {
|
||
|
|
width: v-bind(divMeunWidhtMiddle);
|
||
|
|
background-color: rgba(255, 255, 255, 0.1);
|
||
|
|
align-self: center;
|
||
|
|
height: calc(v-bind(flexMeunHeight) * 0.8);
|
||
|
|
|
||
|
|
&.light-background {
|
||
|
|
background-color: #555555;
|
||
|
|
height: calc(v-bind(flexMeunHeight) * 0.8);
|
||
|
|
align-self: center;
|
||
|
|
width: v-bind(divMeunWidhtMiddle);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
.meun-widht-right {
|
||
|
|
width: v-bind(divMeunWidht);
|
||
|
|
height: v-bind(meun_px_height);;
|
||
|
|
position: relative;
|
||
|
|
display: flex;
|
||
|
|
justify-content: center;
|
||
|
|
align-items: center;
|
||
|
|
|
||
|
|
:deep(.customClass-icon) {
|
||
|
|
height: v-bind(meun_px_height);
|
||
|
|
text-align: center;
|
||
|
|
line-height: v-bind(meun_px_height);
|
||
|
|
position: absolute;
|
||
|
|
top: 50%;
|
||
|
|
left: 50%;
|
||
|
|
transform: translate(-50%, -50%); /* 关键:自身偏移回中心 */
|
||
|
|
}
|
||
|
|
|
||
|
|
.meun-widht-rightimage_item {
|
||
|
|
height: v-bind(imgWidthHeight);
|
||
|
|
width: v-bind(imgWidthHeight);
|
||
|
|
position: absolute;
|
||
|
|
top: 50%;
|
||
|
|
left: 50%;
|
||
|
|
transform: translate(-50%, -50%); /* 关键:自身偏移回中心 */
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
.FlexTitleWidth {
|
||
|
|
width: v-bind(rpxFlexTitleWidth);
|
||
|
|
text-align: center;
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
height: v-bind(meun_px_height);
|
||
|
|
|
||
|
|
.flex-title-text {
|
||
|
|
width: v-bind(rpxFlexTitleWidth);
|
||
|
|
height: v-bind(meun_px_height);
|
||
|
|
line-height: v-bind(meun_px_height);
|
||
|
|
}
|
||
|
|
|
||
|
|
.flex-title-slot {
|
||
|
|
width: v-bind(rpxFlexTitleWidth);
|
||
|
|
height: v-bind(meun_px_height);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
</style>
|
||
|
|
<template>
|
||
|
|
<view class="phoneCom">
|
||
|
|
<view class="phone-wifi">
|
||
|
|
<view class="status-wifi"></view>
|
||
|
|
</view>
|
||
|
|
<view v-if="navShow" class="phone-nav">
|
||
|
|
<view class="meun-height">
|
||
|
|
<view class="uniui-left"></view>
|
||
|
|
<view class="meun-widht-left" @click="emit('homeLeft')">
|
||
|
|
<wd-icon v-if="modelValue?.isShowLeft.showCom==='icon'"
|
||
|
|
:classPrefix="modelValue?.isShowLeft.iconTextLeft.classPrefix"
|
||
|
|
:name="modelValue?.isShowLeft.iconTextLeft.name"
|
||
|
|
:size="modelValue?.isShowLeft.iconTextLeft.size"
|
||
|
|
custom-class="customClass-icon"
|
||
|
|
></wd-icon>
|
||
|
|
<image v-if="modelValue?.isShowLeft.showCom==='img'" :src="modelValue.isShowLeft.img.imgLeft"
|
||
|
|
class="meun-widht-rightimage_item"
|
||
|
|
mode="scaleToFill" webp></image>
|
||
|
|
</view>
|
||
|
|
<view class="meun-widht-middle" :class="{'light-background':theme==='light'}"></view>
|
||
|
|
<view class="meun-widht-right" @click="emit('homeRight')">
|
||
|
|
<!-- <wd-icon custom-class="customClass-icon" name="thin-arrow-left" size="18px"></wd-icon>-->
|
||
|
|
<wd-icon v-if="modelValue?.isShowRight.showCom==='icon'"
|
||
|
|
:classPrefix="modelValue?.isShowRight.iconTextRight.classPrefix"
|
||
|
|
:name="modelValue?.isShowRight.iconTextRight.name"
|
||
|
|
:size="modelValue?.isShowRight.iconTextRight.size"
|
||
|
|
custom-class="customClass-icon"
|
||
|
|
></wd-icon>
|
||
|
|
<image v-if="modelValue?.isShowRight.showCom==='img'" :src="modelValue.isShowRight.img.imgRight"
|
||
|
|
class="meun-widht-rightimage_item"
|
||
|
|
mode="scaleToFill" webp></image>
|
||
|
|
</view>
|
||
|
|
<view class="FlexTitleWidth">
|
||
|
|
<view v-if="titleViewShow" class="flex-title-text">{{ modelValue?.title_text }}</view>
|
||
|
|
<view v-if="slotViewShow" class="flex-title-slot">
|
||
|
|
<slot name="default"></slot>
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
</template>
|
||
|
|
|
||
|
|
<script lang="ts" setup>
|
||
|
|
import {computed, ref, watchEffect} from "vue";
|
||
|
|
import {onShow} from "@dcloudio/uni-app";
|
||
|
|
import type {GlobelsChildPropsType} from "@/types/通用类型";
|
||
|
|
|
||
|
|
let theme = ref(uni.getAppBaseInfo().theme); // 返回值为 dark or linght
|
||
|
|
defineOptions({
|
||
|
|
options: {
|
||
|
|
styleIsolation: "shared",
|
||
|
|
virtualHost: true,
|
||
|
|
},
|
||
|
|
});
|
||
|
|
const emit = defineEmits<{
|
||
|
|
(eventName: "update:pxWindowHeight", value: string): void
|
||
|
|
(eventName: "update:pxScrollHeight", value: string): void
|
||
|
|
(eventName: "update:pxScreenHeight", value: string): void
|
||
|
|
(eventName: "update:pxWifiNavHeight", value: string): void
|
||
|
|
(eventName: "update:statusHeight", value: string): void
|
||
|
|
(eventName: "update:meunHeight", value: string): void
|
||
|
|
(eventName: "homeRight"): void
|
||
|
|
(eventName: "homeLeft"): void
|
||
|
|
}>();
|
||
|
|
|
||
|
|
|
||
|
|
//
|
||
|
|
interface definePropsType {
|
||
|
|
modelValue?: GlobelsChildPropsType, //跟v-model=值没有关系
|
||
|
|
zIndex?: number
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
const props = withDefaults(defineProps<definePropsType>(), {
|
||
|
|
zIndex: () => (100),
|
||
|
|
});
|
||
|
|
const info_window = uni.getWindowInfo();
|
||
|
|
let pxToRpxScale = 750 / info_window.windowWidth;
|
||
|
|
let meun = uni.getMenuButtonBoundingClientRect();
|
||
|
|
let meun_px_height = computed(() => {
|
||
|
|
return meun.height - 2 + "px";
|
||
|
|
});
|
||
|
|
// 计算当前 wifi的高度
|
||
|
|
let wifiHeing = computed(() => {
|
||
|
|
// 当前wifi的高度 也是分为两种情况下 为负数的时候 小于0 的时候我们就需要减少 wifi的高度,这样才能正确留空
|
||
|
|
if (meun.top - info_window.statusBarHeight < 0) {
|
||
|
|
let num = meun.top - info_window.statusBarHeight;
|
||
|
|
return info_window.statusBarHeight - Math.abs(num) * 2;
|
||
|
|
}
|
||
|
|
return info_window.statusBarHeight;
|
||
|
|
});
|
||
|
|
// 默认的一些宽度
|
||
|
|
let rpxLeftWidth = computed(() => {
|
||
|
|
return (info_window.windowWidth - meun.right) * pxToRpxScale + "rpx";
|
||
|
|
});
|
||
|
|
|
||
|
|
let pxMeunHeight = computed(() => {
|
||
|
|
return meun.height + "px";
|
||
|
|
});
|
||
|
|
let rpxFlexTitleWidth = computed(() => {
|
||
|
|
return (meun.left - meun.width - (info_window.windowWidth - meun.right)) * pxToRpxScale + "rpx";
|
||
|
|
});
|
||
|
|
let divMeunWidht = computed(() => {
|
||
|
|
// 胶囊的一半宽度
|
||
|
|
const halfWidth = Math.ceil(meun.width / 2) - 1;
|
||
|
|
return halfWidth * pxToRpxScale + "rpx";
|
||
|
|
});
|
||
|
|
|
||
|
|
let flexMeunHeight = computed(() => {
|
||
|
|
return Math.ceil(meun.height) * 0.6 + "px";
|
||
|
|
});
|
||
|
|
let divMeunWidhtMiddle = computed(() => {
|
||
|
|
return "1px";
|
||
|
|
// return 2 * pxToRpxScale + "rpx";
|
||
|
|
});
|
||
|
|
let imgWidthHeight = computed(() => {
|
||
|
|
return Math.ceil(meun.height * 0.7 * pxToRpxScale) + "rpx";
|
||
|
|
});
|
||
|
|
let wifi_px = computed(() => {
|
||
|
|
return wifiHeing.value + "px";
|
||
|
|
});
|
||
|
|
// 计算当前导航栏的高度
|
||
|
|
let navHeight = computed(() => {
|
||
|
|
// 导航栏高度 = 胶囊高度 + (胶囊顶部距离 - wifi高度)*2
|
||
|
|
// 这里逻辑也得分二种情况第一情况,减下来值小0 和大于0
|
||
|
|
if (meun.top - info_window.statusBarHeight > 0) {
|
||
|
|
return meun.height + (meun.top - info_window.statusBarHeight) * 2;
|
||
|
|
}
|
||
|
|
if (meun.top - info_window.statusBarHeight <= 0) {
|
||
|
|
return meun.height + Math.abs(meun.top - info_window.statusBarHeight) * 2;
|
||
|
|
}
|
||
|
|
return meun.height + (meun.top - info_window.statusBarHeight) * 2;
|
||
|
|
});
|
||
|
|
let nav_px_height = computed(() => {
|
||
|
|
return navHeight.value + "px";
|
||
|
|
});
|
||
|
|
// 计算可视区域的高度
|
||
|
|
let windowHeight = computed(() => {
|
||
|
|
// 可视区高度 = 屏幕高度 - 可视区域的高度 还需要判断 二 种情况, 一种是有tab, 一种是没有tab的情况
|
||
|
|
// 没有tab栏的情况
|
||
|
|
if (info_window.screenHeight - info_window.windowHeight === 0) {
|
||
|
|
if (info_window.safeAreaInsets.bottom > 0) {
|
||
|
|
// 这是苹果手机的状态(直接返回高度就可以了)
|
||
|
|
return info_window.screenHeight - info_window.safeAreaInsets.bottom;
|
||
|
|
}
|
||
|
|
if (info_window.safeAreaInsets.bottom === 0) {
|
||
|
|
// 这是没有底部安全栏高度时的(华为手机,苹果5678o)
|
||
|
|
return info_window.screenHeight - 34;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (info_window.screenHeight - info_window.windowHeight > 0) {
|
||
|
|
return info_window.windowHeight;
|
||
|
|
}
|
||
|
|
return info_window.windowHeight;
|
||
|
|
});
|
||
|
|
// 实时给出高度
|
||
|
|
let wifiShow = ref(true);
|
||
|
|
let navShow = ref(true);
|
||
|
|
let titleViewShow = ref(true);
|
||
|
|
let slotViewShow = ref(false);
|
||
|
|
onShow(() => {
|
||
|
|
emit("update:meunHeight", pxMeunHeight.value);
|
||
|
|
});
|
||
|
|
watchEffect(() => {
|
||
|
|
emit("update:pxScreenHeight", info_window.screenHeight + "px");
|
||
|
|
|
||
|
|
if (props.modelValue?.navIsShow === "default") {
|
||
|
|
// 此时的导航栏高度 = wifi+nav的高度
|
||
|
|
let staus = computed(() => {
|
||
|
|
return (wifiHeing.value + navHeight.value) + "px";
|
||
|
|
});
|
||
|
|
let pxScrollHeight = computed(() => {
|
||
|
|
return windowHeight.value + "px";
|
||
|
|
});
|
||
|
|
emit("update:statusHeight", staus.value);
|
||
|
|
emit("update:pxWindowHeight", staus.value);
|
||
|
|
emit("update:pxScrollHeight", pxScrollHeight.value);
|
||
|
|
emit("update:pxWindowHeight", pxScrollHeight.value);
|
||
|
|
}
|
||
|
|
if (props.modelValue?.navIsShow === "wifi") {
|
||
|
|
// 此时的导航栏高度 = wifi+nav的高度
|
||
|
|
navShow.value = false;
|
||
|
|
let staus = computed(() => {
|
||
|
|
return (wifiHeing.value) + "px";
|
||
|
|
});
|
||
|
|
let pxScrollHeight = computed(() => {
|
||
|
|
// 当值为wifi时,则表明,只想显示一个wifi的状态, 不想显示na的状态
|
||
|
|
return windowHeight.value + "px";
|
||
|
|
});
|
||
|
|
emit("update:statusHeight", staus.value);
|
||
|
|
emit("update:pxWindowHeight", staus.value);
|
||
|
|
emit("update:pxScrollHeight", pxScrollHeight.value);
|
||
|
|
emit("update:pxWindowHeight", pxScrollHeight.value);
|
||
|
|
}
|
||
|
|
if (props.modelValue?.navIsShow === "none") {
|
||
|
|
navShow.value = true;
|
||
|
|
wifiShow.value = false;
|
||
|
|
// 此时的导航栏高度 = wifi+nav的高度
|
||
|
|
let staus = computed(() => {
|
||
|
|
return "0px";
|
||
|
|
});
|
||
|
|
let pxScrollHeight = computed(() => {
|
||
|
|
// 当值为wifi时,则表明,只想显示一个wifi的状态, 不想显示na的状态
|
||
|
|
return windowHeight.value + "px";
|
||
|
|
});
|
||
|
|
emit("update:statusHeight", staus.value);
|
||
|
|
emit("update:pxWindowHeight", staus.value);
|
||
|
|
emit("update:pxScrollHeight", pxScrollHeight.value);
|
||
|
|
emit("update:pxWindowHeight", pxScrollHeight.value);
|
||
|
|
}
|
||
|
|
if (props.modelValue?.navIsShow === "slot") {
|
||
|
|
slotViewShow.value = true;
|
||
|
|
titleViewShow.value = false;
|
||
|
|
// 此时的导航栏高度 = wifi+nav的高度
|
||
|
|
let staus = computed(() => {
|
||
|
|
return (wifiHeing.value + navHeight.value) + "px";
|
||
|
|
});
|
||
|
|
|
||
|
|
let pxScrollHeight = computed(() => {
|
||
|
|
// 当值为wifi时,则表明,只想显示一个wifi的状态, 不想显示na的状态
|
||
|
|
return windowHeight.value + "px";
|
||
|
|
});
|
||
|
|
emit("update:statusHeight", staus.value);
|
||
|
|
emit("update:pxWindowHeight", staus.value);
|
||
|
|
emit("update:pxScrollHeight", pxScrollHeight.value);
|
||
|
|
emit("update:pxWindowHeight", pxScrollHeight.value);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
</script>
|