PaymentAgreementModal.vue 7.76 KB
<template>
    <nut-popup
        v-model:visible="visible"
        position="bottom"
        :style="{ width: '100%', height: '100%' }"
    >
        <div class="payment-agreement-modal">
            <!-- 标题 -->
            <div class="modal-header">
                <h2 class="title">在捡个电驴收款</h2>
            </div>

            <!-- 内容区域 -->
            <div class="modal-content">
                <!-- 收款说明 -->
                <div class="info-row">
                    <div class="label">收款说明</div>
                    <div class="content">{{ paymentDescription }}</div>
                </div>

                <!-- 扣费说明 -->
                <div class="info-row">
                    <div class="label">扣费说明</div>
                    <div class="content">{{ feeDescription }}</div>
                </div>

                <!-- 协议勾选区域 -->
                <div v-if="!hasAgreed" class="agreement-section">
                    <nut-checkbox v-model="isChecked" class="agreement-checkbox">
                        <view class="checkbox-text">
                            <text>我已阅读并同意</text>
                            <text class="agreement-link" @tap.stop="showProtocol">
                                《支付协议》
                            </text>
                        </view>
                    </nut-checkbox>
                </div>
            </div>

            <!-- 按钮区域 -->
            <div class="modal-footer">
                <div class="button-row">
                    <nut-button
                        type="default"
                        class="close-button"
                        @click="handleClose"
                    >
                        关闭
                    </nut-button>
                    <nut-button
                        v-if="!hasAgreed"
                        :disabled="!isChecked"
                        type="primary"
                        class="main-button"
                        color="orange"
                        @click="handleAgree"
                    >
                        同意
                    </nut-button>
                    <nut-button
                        v-else
                        type="primary"
                        class="main-button"
                        color="orange"
                        @click="handleConfirm"
                    >
                        确认
                    </nut-button>
                </div>
            </div>
        </div>

        <!-- 支付协议弹框 -->
        <nut-popup
            v-model:visible="protocolVisible"
            position="bottom"
            :style="{ width: '100%', height: '70%' }"
            round
            closeable
        >
            <div class="protocol-modal">
                <div class="protocol-header">
                    <h3>支付协议</h3>
                </div>
                <div class="protocol-content">
                    <p>{{ protocolContent }}</p>
                </div>
            </div>
        </nut-popup>
    </nut-popup>
</template>

<script setup>
import { ref, computed, onMounted } from 'vue'
import { useUserStore } from '@/stores/user'

/**
 * 用户收款说明组件
 * @param {Boolean} modelValue - 控制弹框显示隐藏
 * @param {Function} onAgree - 同意按钮回调
 * @param {Function} onConfirm - 确认按钮回调
 * @param {Function} onClose - 关闭弹框回调
 */
const props = defineProps({
    modelValue: {
        type: Boolean,
        default: false
    }
})

const emit = defineEmits(['update:modelValue', 'agree', 'confirm', 'close'])

const userStore = useUserStore()

// 弹框显示状态
const visible = computed({
    get: () => props.modelValue,
    set: (value) => emit('update:modelValue', value)
})

// 支付协议弹框显示状态
const protocolVisible = ref(false)

// 勾选状态
const isChecked = ref(false)

// 是否已同意过协议(mock数据)
const hasAgreed = ref(false)

// 收款说明内容
const paymentDescription = ref('通过捡个电驴平台进行收款,资金安全有保障,支持多种收款方式。')

// 扣费说明内容
const feeDescription = ref('平台将收取交易金额的3%作为服务费,费用将在交易完成后自动扣除。')

// 支付协议内容
const protocolContent = ref(`
1. 用户在使用捡个电驴收款服务时,需遵守相关法律法规。
2. 平台有权对异常交易进行风险控制。
3. 用户应确保收款信息的真实性和准确性。
4. 平台将按照约定收取相应的服务费用。
5. 如有争议,双方应友好协商解决。
`)

/**
 * 检查用户是否已同意过协议
 */
const checkAgreementStatus = () => {
    // TODO: 实际项目中应该从userStore.userInfo中获取相关字段
    // 这里使用mock数据
    hasAgreed.value = userStore.userInfo?.paymentAgreementAccepted || false
}

/**
 * 显示支付协议
 */
const showProtocol = () => {
    protocolVisible.value = true
}

/**
 * 处理同意按钮点击
 */
const handleAgree = () => {
    if (!isChecked.value) return

    // TODO: 实际项目中应该调用API更新用户协议状态
    hasAgreed.value = true

    emit('agree')
}

/**
 * 处理确认按钮点击
 */
const handleConfirm = () => {
    emit('confirm')
}

/**
 * 处理弹框关闭
 */
const handleClose = () => {
    emit('close')
}

// 组件挂载时检查协议状态
onMounted(() => {
    checkAgreementStatus()
})
</script>

<style lang="less">
.payment-agreement-modal {
    display: flex;
    flex-direction: column;
    height: 100%;
    padding: 32rpx;
    padding-top: 80rpx;

    .modal-header {
        text-align: center;
        margin-bottom: 40rpx;

        .title {
            font-size: 36rpx;
            font-weight: 600;
            color: #333;
            margin: 0;
        }
    }

    .modal-content {
        flex: 1;
        display: flex;
        flex-direction: column;

        .info-row {
            display: flex;
            margin-bottom: 32rpx;

            .label {
                width: 160rpx;
                font-size: 28rpx;
                font-weight: 500;
                color: #333;
                flex-shrink: 0;
            }

            .content {
                flex: 1;
                font-size: 28rpx;
                color: #666;
                line-height: 1.6;
            }
        }

        .agreement-section {
            margin-top: 40rpx;
            text-align: center;

            .agreement-checkbox {
                font-size: 28rpx;

                .checkbox-text {
                    white-space: nowrap;
                    display: inline-block;
                }

                .agreement-link {
                    color: #ffa500;
                    text-decoration: underline;
                    cursor: pointer;
                }
            }
        }
    }

    .modal-footer {
        padding-top: 32rpx;
        border-top: 1rpx solid #eee;

        .button-row {
            display: flex;
            gap: 24rpx;
            align-items: center;

            .close-button {
                flex: 1;
                border: 1rpx solid #ddd;
                color: #666;
            }

            .main-button {
                flex: 1;
            }
        }
    }
}

.protocol-modal {
    padding: 32rpx;
    height: 100%;
    display: flex;
    flex-direction: column;

    .protocol-header {
        text-align: center;
        margin-bottom: 32rpx;

        h3 {
            font-size: 32rpx;
            font-weight: 600;
            color: #333;
            margin: 0;
        }
    }

    .protocol-content {
        flex: 1;
        overflow-y: auto;

        p {
            font-size: 28rpx;
            color: #666;
            line-height: 1.8;
            white-space: pre-line;
            margin: 0;
        }
    }
}
</style>