alipay-emulator/components/nav-bar/nav-bar.vue

238 lines
4.6 KiB
Vue

<template>
<view style="width: 100%;" :style="{ height: `${data.statusBarHeight + 44}px` }"></view>
<view class="nav-bar-container" :style="{ backgroundColor: bgColor, zIndex: zIndex }">
<view class="status-placeholder" :style="{ height: `${data.statusBarHeight}px` }"></view>
<view style="width: 100%;height: 88rpx;" @click="openPopup">
<slot>
<uni-nav-bar backgroundColor="#00000000" class="nav-bar" :border="false" :title="title" v-bind="$attrs"
v-on="$attrs">
<template v-slot:left>
<view class="nav-bar-left">
<slot name="left">
<view class="left-icon" @click.stop="onBack">
<image class="nav-icon-back" src="/static/image/nav-bar/back-black.png" mode="">
</image>
</view>
</slot>
</view>
</template>
<view class="nav-bar-title w100 h100 flex-1" @click="openPopup" :style="{ color: textColor }">
<slot name="center">
{{ title }}
</slot>
</view>
<template v-slot:right>
<view class="nav-bar-right" @click.stop="onRightClick">
<slot name="right">
<view v-if="isRightIcon" class="right-icon">
<image class="nav-icon-more" src="/static/image/nav-bar/more-black.png" mode="">
</image>
</view>
<view v-if="isRightButton" class="right-button">
{{ rightButtonText }}
</view>
</slot>
</view>
</template>
</uni-nav-bar>
</slot>
</view>
<popup ref="topPopup">
<view class="button-group w100 flex-between flex-wrap">
<view class="button-box" v-for="(button, index) in buttonGroup" :key="index"
@click="buttonClick(button)">
<!-- 使用作用域插槽,允许父组件自定义按钮内容 -->
<!-- 默认渲染 -->
<view class="button flex-align-center flex-justify-center">
<slot name="button" :button="button" :index="index">
{{ button.name }}
<switch v-if="button.isSwitch" :checked="button.value" @change="buttonClick(button)"
style="transform: scale(0.7);"></switch>
</slot>
</view>
</view>
</view>
</popup>
</view>
</template>
<script setup>
import popup from '../popup/popup.vue'
import {
onMounted,
reactive,
ref
} from 'vue'
const topPopup = ref()
// 定义组件属性
const props = defineProps({
bgColor: {
type: String,
default: '#fff'
},
textColor: {
type: String,
default: '#000'
},
title: {
type: String,
default: ''
},
buttonGroup: {
type: Array,
default: () => []
},
isRightIcon: {
type: Boolean,
default: false
},
isRightButton: {
type: Boolean,
default: false
},
rightButtonText: {
type: String,
default: '确定'
},
zIndex: {
type: Number,
default: 999
},
noBack: {
type: Boolean,
default: false
}
})
// 定义事件
const emit = defineEmits(['back', 'right-click', 'button-click'])
const data = reactive({
statusBarHeight: 0
})
onMounted(() => {
// 同步获取系统信息
const systemInfo = uni.getSystemInfoSync();
data.statusBarHeight = systemInfo.statusBarHeight || 0;
})
const openPopup = () => {
if (props.buttonGroup.length > 0) {
topPopup.value.open()
}
}
// 返回按钮点击事件
const onBack = () => {
emit('back')
// 默认返回上一页
if (props.noBack) return
uni.navigateBack()
}
// 右侧按钮点击事件
const onRightClick = () => {
emit('right-click')
}
const buttonClick = (button) => {
topPopup.value.close()
emit('button-click', button)
}
</script>
<style scoped>
@import "/common/main.css";
.nav-bar-container {
display: flex;
flex-direction: column;
position: fixed !important;
top: 0;
left: 0;
right: 0;
z-index: 999;
}
.nav-bar {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
position: relative;
z-index: 1;
}
.status-placeholder {
width: 100%;
}
::v-deep .uni-navbar__content {
width: 100%;
}
.nav-bar-left {
display: flex;
align-items: center;
justify-content: flex-start;
}
.nav-icon-back {
width: 24px;
height: 24px;
}
.nav-icon-more {
width: 26px;
height: 26px;
}
.nav-bar-title {
flex: 1;
margin: auto;
display: flex;
align-items: center;
justify-content: center;
font-size: 17px;
font-weight: 500;
}
.nav-bar-right {
display: flex;
align-items: center;
justify-content: flex-end;
}
.right-button {
font-size: 12px;
border-radius: 16px;
color: #fff;
text-align: center;
line-height: 30px;
height: 30px;
min-width: 60px;
background: linear-gradient(90deg, #187AFF 0%, #3295FC 100%);
}
.button-box {
width: calc(50% - 8rpx);
text-align: center;
margin-top: 16rpx;
}
.button {
border: 1px solid #E4E4E4;
border-radius: 8px;
height: 42px;
line-height: 42px;
font-size: 28rpx;
}
</style>