390 lines
8.5 KiB
Vue
390 lines
8.5 KiB
Vue
<template>
|
||
<view v-if="visible" class="popup-mask" @click="handleMaskClick">
|
||
<view class="popup-container" :class="[`popup-${type}`]" @click.stop>
|
||
<!-- 关闭按钮 -->
|
||
<view v-if="showClose" class="close-btn" @click="handleClose">
|
||
<text>×</text>
|
||
</view>
|
||
|
||
<!-- 性别选择弹窗 -->
|
||
<template v-if="type === 'gender'">
|
||
<view class="popup-title">请选择您想看的性别</view>
|
||
<view class="gender-options">
|
||
<view class="gender-option male" @click="handleGenderSelect(1)">
|
||
<view class="gender-icon">♂</view>
|
||
<text>看男生</text>
|
||
</view>
|
||
<view class="gender-option female" @click="handleGenderSelect(2)">
|
||
<view class="gender-icon">♀</view>
|
||
<text>看女生</text>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<!-- 每日弹窗 / 会员广告 -->
|
||
<template v-else-if="type === 'daily' || type === 'member'">
|
||
<image
|
||
v-if="imageUrl"
|
||
class="popup-image"
|
||
:src="imageUrl"
|
||
mode="aspectFit"
|
||
@click="handleImageClick"
|
||
/>
|
||
<view v-if="title" class="popup-title">{{ title }}</view>
|
||
<button
|
||
v-if="buttonText"
|
||
class="popup-btn"
|
||
@click="handleButtonClick"
|
||
>
|
||
{{ buttonText }}
|
||
</button>
|
||
</template>
|
||
|
||
<!-- 解锁确认弹窗 -->
|
||
<template v-else-if="type === 'unlock'">
|
||
<view class="popup-title">解锁联系方式</view>
|
||
<view class="unlock-info">
|
||
<text class="unlock-desc">解锁后可查看对方联系方式</text>
|
||
<text v-if="remainingQuota > 0" class="unlock-quota">剩余免费解锁次数:{{ remainingQuota }}</text>
|
||
<text v-else class="unlock-quota no-quota">您的解锁次数已用完</text>
|
||
</view>
|
||
<view class="popup-buttons">
|
||
<button class="popup-btn cancel" @click="handleClose">取消</button>
|
||
<button
|
||
v-if="remainingQuota > 0"
|
||
class="popup-btn confirm"
|
||
@click="handleConfirmUnlock"
|
||
>
|
||
确认解锁
|
||
</button>
|
||
<button
|
||
v-else
|
||
class="popup-btn confirm member"
|
||
@click="handleGoMember"
|
||
>
|
||
购买会员
|
||
</button>
|
||
</view>
|
||
</template>
|
||
|
||
<!-- 资料完善提示弹窗 -->
|
||
<template v-else-if="type === 'profile'">
|
||
<view class="popup-title">完善资料</view>
|
||
<view class="profile-info">
|
||
<text class="profile-desc">请先完善您的资料,才能联系对方</text>
|
||
</view>
|
||
<view class="popup-buttons">
|
||
<button class="popup-btn cancel" @click="handleClose">稍后再说</button>
|
||
<button class="popup-btn confirm" @click="handleGoProfile">去完善</button>
|
||
</view>
|
||
</template>
|
||
|
||
<!-- 通用弹窗 -->
|
||
<template v-else>
|
||
<image
|
||
v-if="imageUrl"
|
||
class="popup-image"
|
||
:src="imageUrl"
|
||
mode="aspectFit"
|
||
/>
|
||
<view v-if="title" class="popup-title">{{ title }}</view>
|
||
<view v-if="content" class="popup-content">{{ content }}</view>
|
||
<button
|
||
v-if="buttonText"
|
||
class="popup-btn"
|
||
@click="handleButtonClick"
|
||
>
|
||
{{ buttonText }}
|
||
</button>
|
||
</template>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
export default {
|
||
name: 'Popup',
|
||
props: {
|
||
visible: {
|
||
type: Boolean,
|
||
default: false
|
||
},
|
||
type: {
|
||
type: String,
|
||
default: 'default',
|
||
validator: (value) => ['gender', 'daily', 'member', 'unlock', 'profile', 'default'].includes(value)
|
||
},
|
||
imageUrl: {
|
||
type: String,
|
||
default: ''
|
||
},
|
||
title: {
|
||
type: String,
|
||
default: ''
|
||
},
|
||
content: {
|
||
type: String,
|
||
default: ''
|
||
},
|
||
buttonText: {
|
||
type: String,
|
||
default: ''
|
||
},
|
||
linkUrl: {
|
||
type: String,
|
||
default: ''
|
||
},
|
||
showClose: {
|
||
type: Boolean,
|
||
default: true
|
||
},
|
||
closeOnMask: {
|
||
type: Boolean,
|
||
default: true
|
||
},
|
||
remainingQuota: {
|
||
type: Number,
|
||
default: 0
|
||
}
|
||
},
|
||
emits: ['close', 'confirm', 'genderSelect', 'unlock', 'goProfile', 'goMember'],
|
||
methods: {
|
||
handleMaskClick() {
|
||
if (this.closeOnMask) {
|
||
this.handleClose()
|
||
}
|
||
},
|
||
handleClose() {
|
||
this.$emit('close')
|
||
},
|
||
handleGenderSelect(gender) {
|
||
this.$emit('genderSelect', gender)
|
||
},
|
||
handleImageClick() {
|
||
if (this.linkUrl) {
|
||
this.navigateToLink()
|
||
}
|
||
},
|
||
handleButtonClick() {
|
||
if (this.linkUrl) {
|
||
this.navigateToLink()
|
||
}
|
||
this.$emit('confirm')
|
||
},
|
||
handleConfirmUnlock() {
|
||
this.$emit('unlock')
|
||
},
|
||
handleGoProfile() {
|
||
this.$emit('goProfile')
|
||
},
|
||
handleGoMember() {
|
||
this.$emit('goMember')
|
||
},
|
||
navigateToLink() {
|
||
if (!this.linkUrl) return
|
||
|
||
// 判断是内部页面还是外部链接
|
||
if (this.linkUrl.startsWith('/pages/')) {
|
||
uni.navigateTo({ url: this.linkUrl })
|
||
} else if (this.linkUrl.startsWith('http')) {
|
||
// 外部链接使用webview或复制链接
|
||
uni.setClipboardData({
|
||
data: this.linkUrl,
|
||
success: () => {
|
||
uni.showToast({ title: '链接已复制', icon: 'success' })
|
||
}
|
||
})
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.popup-mask {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
background: rgba(0, 0, 0, 0.5);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
z-index: 999;
|
||
}
|
||
|
||
.popup-container {
|
||
position: relative;
|
||
background: #fff;
|
||
border-radius: 24rpx;
|
||
padding: 40rpx;
|
||
width: 600rpx;
|
||
max-width: 90%;
|
||
|
||
.close-btn {
|
||
position: absolute;
|
||
top: 20rpx;
|
||
right: 20rpx;
|
||
width: 48rpx;
|
||
height: 48rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
|
||
text {
|
||
font-size: 40rpx;
|
||
color: #999;
|
||
line-height: 1;
|
||
}
|
||
}
|
||
|
||
.popup-title {
|
||
font-size: 36rpx;
|
||
font-weight: 600;
|
||
color: #333;
|
||
text-align: center;
|
||
margin-bottom: 30rpx;
|
||
}
|
||
|
||
.popup-content {
|
||
font-size: 28rpx;
|
||
color: #666;
|
||
text-align: center;
|
||
margin-bottom: 30rpx;
|
||
line-height: 1.6;
|
||
}
|
||
|
||
.popup-image {
|
||
width: 100%;
|
||
height: 300rpx;
|
||
margin-bottom: 20rpx;
|
||
border-radius: 12rpx;
|
||
}
|
||
|
||
.popup-btn {
|
||
width: 100%;
|
||
height: 80rpx;
|
||
line-height: 80rpx;
|
||
background: linear-gradient(135deg, #ff6b6b 0%, #ff5252 100%);
|
||
color: #fff;
|
||
font-size: 30rpx;
|
||
border-radius: 40rpx;
|
||
border: none;
|
||
|
||
&::after {
|
||
border: none;
|
||
}
|
||
|
||
&.cancel {
|
||
background: #f5f5f5;
|
||
color: #666;
|
||
}
|
||
|
||
&.confirm {
|
||
background: linear-gradient(135deg, #ff6b6b 0%, #ff5252 100%);
|
||
color: #fff;
|
||
}
|
||
}
|
||
|
||
.popup-buttons {
|
||
display: flex;
|
||
gap: 20rpx;
|
||
|
||
.popup-btn {
|
||
flex: 1;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 性别选择弹窗样式
|
||
.popup-gender {
|
||
.gender-options {
|
||
display: flex;
|
||
justify-content: space-around;
|
||
padding: 20rpx 0;
|
||
|
||
.gender-option {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
padding: 30rpx 50rpx;
|
||
border-radius: 16rpx;
|
||
transition: all 0.3s;
|
||
|
||
&:active {
|
||
transform: scale(0.95);
|
||
}
|
||
|
||
.gender-icon {
|
||
font-size: 60rpx;
|
||
margin-bottom: 16rpx;
|
||
}
|
||
|
||
text {
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
}
|
||
|
||
&.male {
|
||
background: linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%);
|
||
|
||
.gender-icon {
|
||
color: #2196f3;
|
||
}
|
||
}
|
||
|
||
&.female {
|
||
background: linear-gradient(135deg, #fce4ec 0%, #f8bbd9 100%);
|
||
|
||
.gender-icon {
|
||
color: #e91e63;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 解锁弹窗样式
|
||
.popup-unlock {
|
||
.unlock-info {
|
||
text-align: center;
|
||
margin-bottom: 30rpx;
|
||
|
||
.unlock-desc {
|
||
display: block;
|
||
font-size: 28rpx;
|
||
color: #666;
|
||
margin-bottom: 16rpx;
|
||
}
|
||
|
||
.unlock-quota {
|
||
display: block;
|
||
font-size: 26rpx;
|
||
color: #ff6b6b;
|
||
|
||
&.no-quota {
|
||
color: #999;
|
||
}
|
||
}
|
||
}
|
||
|
||
.popup-btn.member {
|
||
background: linear-gradient(135deg, #ffd700 0%, #ffb800 100%);
|
||
}
|
||
}
|
||
|
||
// 资料完善弹窗样式
|
||
.popup-profile {
|
||
.profile-info {
|
||
text-align: center;
|
||
margin-bottom: 30rpx;
|
||
|
||
.profile-desc {
|
||
font-size: 28rpx;
|
||
color: #666;
|
||
}
|
||
}
|
||
}
|
||
</style>
|