爱简收旧衣按件回收前端代码仓库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

353 lines
7.4 KiB

<template>
<!-- 回收规则弹窗 -->
<view v-if="showRulePopup" class="rule-popup-mask" @click.self="handleRulePopupMaskClick">
<view class="rule-popup">
<view class="rule-popup-title">{{ ruleTitle }}</view>
<scroll-view class="rule-popup-content" scroll-y @scroll="onRuleContentScroll"
@scrolltolower="onRuleScrollToLower">
<uv-parse :content="ruleHtml" @ready="onRuleContentReady"></uv-parse>
<view class="rule-content-bottom-indicator"></view>
</scroll-view>
<view v-if="!hasScrolledToBottom" class="scroll-tip">请滚动到底部阅读完整内容</view>
<button class="rule-popup-btn" :class="{ disabled: !hasScrolledToBottom }" :disabled="!hasScrolledToBottom"
@click.stop="closeRulePopup">我知道了</button>
</view>
</view>
<!-- 预约上门取件弹窗 -->
<view v-if="showPickupConfirm" class="pickup-confirm-mask">
<view class="pickup-confirm-popup">
<view class="pickup-confirm-title">{{ confirmTitle }}</view>
<view class="pickup-confirm-content">
<uv-parse :content="confirmContent"></uv-parse>
</view>
<view class="pickup-confirm-btn-row">
<button class="pickup-confirm-btn" @click="handlePickupCancel">{{ cancelText }}</button>
<button class="pickup-confirm-btn agree" @click="handlePickupAgree">{{ confirmText }}</button>
</view>
</view>
</view>
</template>
<script>
export default {
name: 'RulePopup',
props: {
// 回收规则弹窗标题
ruleTitle: {
type: String,
default: '回收规则'
},
// 确认弹窗标题
confirmTitle: {
type: String,
default: '温馨提示'
},
// 确认弹窗内容
confirmContent: {
type: String,
default: ''
},
// 取消按钮文本
cancelText: {
type: String,
default: '取消回收'
},
// 确认按钮文本
confirmText: {
type: String,
default: '我同意'
}
},
data() {
return {
showRulePopup: false,
showPickupConfirm: false,
ruleHtml: '',
hasScrolledToBottom: false
}
},
methods: {
// 打开回收规则弹窗
openRulePopup(ruleContent = '') {
this.ruleHtml = ruleContent || '<p>暂无回收规则</p>'
this.hasScrolledToBottom = false
this.showRulePopup = true
// 弹窗显示后主动判断内容是否需要滚动
this.$nextTick(() => {
const query = uni.createSelectorQuery().in(this)
query.select('.rule-popup-content').boundingClientRect(rect => {
if (rect && rect.height && rect.scrollHeight && rect.scrollHeight <= rect.height + 10) {
this.hasScrolledToBottom = true
}
}).exec()
})
},
// 打开确认弹窗
openConfirmPopup() {
this.showPickupConfirm = true
},
// 关闭回收规则弹窗
closeRulePopup() {
if (!this.hasScrolledToBottom) {
uni.showToast({
title: '请阅读完整回收规则',
icon: 'none'
})
return
}
this.showRulePopup = false
this.hasScrolledToBottom = false
this.$emit('rule-confirm')
},
// 关闭确认弹窗
closeConfirmPopup() {
this.showPickupConfirm = false
},
// 处理规则弹窗遮罩点击
handleRulePopupMaskClick() {
if (!this.hasScrolledToBottom) {
uni.showToast({
title: '请阅读完整回收规则',
icon: 'none'
})
return
}
this.closeRulePopup()
},
// 处理取消回收
handlePickupCancel() {
this.closeConfirmPopup()
this.$emit('pickup-cancel')
},
// 处理确认回收
handlePickupAgree() {
this.closeConfirmPopup()
this.$emit('pickup-confirm')
},
// 监听规则内容滚动
onRuleContentScroll(e) {
const { scrollTop, scrollHeight, clientHeight, height } = e.detail
const h = clientHeight || height
// 内容高度不够,无需滚动,直接允许
if (scrollHeight <= h + 10) {
this.hasScrolledToBottom = true
return
}
if (scrollTop + h >= scrollHeight - 20) {
this.hasScrolledToBottom = true
}
},
// 规则内容滚动到底部
onRuleScrollToLower() {
this.hasScrolledToBottom = true
},
// 规则内容准备完成
onRuleContentReady() {
this.$nextTick(() => {
const query = uni.createSelectorQuery().in(this)
query.select('.rule-popup-content').boundingClientRect(rect => {
query.select('.rule-popup-content').scrollOffset(scroll => {
// 只有内容高度小于等于可视高度时才点亮
if (scroll.scrollHeight <= rect.height + 1) {
this.hasScrolledToBottom = true
}
})
}).exec()
})
}
}
}
</script>
<style lang="scss" scoped>
.rule-popup-mask {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.35);
z-index: 4000;
display: flex;
align-items: center;
justify-content: center;
}
.rule-popup {
width: 95vw;
max-width: 750rpx;
max-height: 85vh;
background: #fff;
border-radius: 48rpx;
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.12);
display: flex;
flex-direction: column;
align-items: center;
position: relative;
padding-bottom: 40rpx;
}
.rule-popup-title {
font-size: 36rpx;
color: #222;
font-weight: bold;
text-align: center;
margin-top: 48rpx;
margin-bottom: 16rpx;
}
.rule-popup-content {
width: 100%;
max-height: 60vh;
min-height: 400rpx;
padding: 0 40rpx;
box-sizing: border-box;
overflow-y: auto;
scrollbar-width: none;
/* Firefox */
-ms-overflow-style: none;
/* IE and Edge */
&::-webkit-scrollbar {
width: 0 !important;
display: none;
/* Chrome, Safari, Opera */
}
}
.rule-content-bottom-indicator {
height: 20rpx;
width: 100%;
}
.scroll-tip {
font-size: 24rpx;
color: #ff6b35;
text-align: center;
margin: 16rpx 0 8rpx 0;
animation: tipPulse 2s infinite;
}
@keyframes tipPulse {
0%,
100% {
opacity: 1;
}
50% {
opacity: 0.6;
}
}
.rule-popup-btn {
width: 80%;
height: 88rpx;
background: linear-gradient(to right, #ffd01e, #ff8917);
border-radius: 44rpx;
color: #fff;
font-size: 32rpx;
font-weight: bold;
display: flex;
align-items: center;
justify-content: center;
border: none;
margin: 0 auto;
margin-top: 16rpx;
box-shadow: 0 4rpx 16rpx rgba(255, 156, 0, 0.08);
transition: all 0.3s ease;
&::after {
border: none;
}
&:active {
opacity: 0.9;
}
&.disabled {
background: #ccc;
color: #999;
box-shadow: none;
opacity: 0.6;
}
}
/* 预约上门取件弹窗样式 */
.pickup-confirm-mask {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.35);
z-index: 5000;
display: flex;
align-items: center;
justify-content: center;
}
.pickup-confirm-popup {
width: 90vw;
max-width: 600rpx;
background: #fff;
border-radius: 48rpx;
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.12);
display: flex;
flex-direction: column;
align-items: center;
position: relative;
padding: 48rpx 36rpx 40rpx 36rpx;
}
.pickup-confirm-title {
font-size: 36rpx;
color: #222;
font-weight: bold;
text-align: center;
margin-bottom: 24rpx;
}
.pickup-confirm-content {
width: 100%;
font-size: 26rpx;
color: #333;
text-align: left;
line-height: 1.7;
margin-bottom: 36rpx;
}
.pickup-confirm-btn-row {
width: 100%;
display: flex;
justify-content: space-between;
gap: 32rpx;
}
.pickup-confirm-btn {
flex: 1;
height: 88rpx;
border-radius: 44rpx;
font-size: 32rpx;
font-weight: bold;
display: flex;
align-items: center;
justify-content: center;
border: 2rpx solid #ffd01e;
background: #fff;
color: #ff9c00;
box-shadow: 0 4rpx 16rpx rgba(255, 156, 0, 0.08);
&:not(.agree) {
background: #fff0d2;
}
&.agree {
background: linear-gradient(to right, #ffd01e, #ff8917);
color: #fff;
border: none;
}
}
</style>