|
|
- <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>
|