qnc-webview-tob/src/views/Withdraw.vue

342 lines
12 KiB
Vue
Raw Normal View History

2025-03-08 15:26:04 +08:00
<template>
2025-04-10 23:01:03 +08:00
<div class="p-4 bg-gradient-to-b from-blue-50/30 to-gray-50 min-h-screen">
<div> <!-- 提现卡片 -->
<div class="rounded-xl shadow-lg bg-gradient-to-r from-blue-50/70 to-blue-100/50 p-6 mb-4">
<div class="flex items-center mb-6">
<van-icon name="alipay" class="text-blue-500 text-xl mr-2" />
<h1 class="text-xl font-bold text-gray-800">支付宝提现</h1>
</div>
2025-03-08 15:26:04 +08:00
2025-04-10 23:01:03 +08:00
<!-- 支付宝账号 -->
<div class="mb-6">
<label class="text-sm text-gray-600 mb-2 block">支付宝账号</label>
<van-field v-model="alipayAccount" placeholder="请输入支付宝账号"
class="flex items-center rounded-lg bg-white/90 backdrop-blur-sm shadow-sm"
:rules="[{ required: true, message: ' ' }]">
<template #left-icon>
<van-icon name="phone-o" class="text-gray-500" />
</template>
</van-field>
<small class="text-gray-400 text-xs mt-1 block">可填写支付宝账户绑定的手机号</small>
2025-03-08 15:26:04 +08:00
2025-04-10 23:01:03 +08:00
</div>
<!-- 支付宝实名姓名 -->
<div class="mb-6">
<label class="text-sm text-gray-600 mb-2 block">实名姓名</label>
<van-field v-model="realName" placeholder="请输入支付宝认证姓名"
class="flex items-center rounded-lg bg-white/90 backdrop-blur-sm shadow-sm" :rules="[{
required: true,
message: ' ',
validator: (val) => /^[\u4e00-\u9fa5]{2,4}$/.test(val)
}]">
<template #left-icon>
<van-icon name="contact-o" class="text-gray-500" />
</template>
</van-field>
<small class="text-gray-400 text-xs mt-1 block">请填写支付宝账户认证的真实姓名</small>
</div>
<!-- 提现金额 -->
<div class="mb-4">
<label class="text-sm text-gray-600 mb-2 block">提现金额</label>
<van-field v-model.number="amount" type="number" placeholder="请输入提现金额"
class="flex items-center rounded-lg bg-white/90 backdrop-blur-sm shadow-sm"
:rules="[{ required: true, message: ' ' }, { validator: validateAmount, message: ' ' }]">
<template #left-icon>
<van-icon name="gold-coin-o" class="text-gray-500" />
</template>
<template #right-icon>
</template>
<template #button>
<van-button size="small" type="primary"
class="bg-gradient-to-r from-blue-500/20 to-blue-400/20 text-blue-600 rounded-full px-3 shadow-sm"
@click="fillMaxAmount">
全部提现
</van-button>
</template>
</van-field>
</div>
<!-- 金额提示 -->
<div class="text-sm text-gray-500 mb-6">
可提现金额<span class="text-blue-600 font-semibold">¥{{ availableAmount }}</span>
</div>
<!-- 提现规则 -->
<div class="bg-blue-50/60 p-4 rounded-xl backdrop-blur-sm">
<div class="flex items-center text-sm text-blue-500 mb-2">
<van-icon name="warning" class="mr-1" />提现须知
</div>
<ul class="text-xs text-gray-600 space-y-1">
<li>· 每日限提现1次最低50元</li>
<li>· 超过800元需人工审核1-3个工作日</li>
<li>· 到账时间24小时内</li>
</ul>
</div>
2025-03-08 15:26:04 +08:00
</div>
2025-04-10 23:01:03 +08:00
<!-- 提交按钮 -->
<van-button type="primary" block :loading="isSubmitting"
class="bg-gradient-to-r from-blue-500 to-blue-400 text-white rounded-xl shadow-lg h-12 font-bold text-base"
@click="handleSubmit">
立即提现
</van-button>
2025-03-08 15:26:04 +08:00
</div>
2025-04-10 23:01:03 +08:00
<van-popup v-model:show="showStatusPopup" round position="center"
:style="{ width: '85%', borderRadius: '20px' }" :overlay-style="{ backgroundColor: 'rgba(0,0,0,0.4)' }">
<div class="p-8 bg-gradient-to-b from-white to-blue-50/30 relative">
<!-- 状态内容 -->
<div class="text-center space-y-5">
<!-- 状态图标 -->
<div class="relative inline-block">
<div class="absolute inset-0 bg-gradient-to-r opacity-20 rounded-full animate-pulse blur-sm"
:class="statusBg[status]"></div>
<van-icon :name="statusIcon[status]" size="56" class="p-1 rounded-full border-[3px]"
:class="statusIconClass[status]" />
</div>
<!-- 状态文案 -->
<div>
<h2 class="text-xl font-semibold mb-1" :class="statusTextColors[status]">
{{ statusMessages[status] }}
</h2>
<template v-if="status === 2">
<p class="text-sm text-gray-500">
已向 <span class="text-blue-500">{{ alipayAccount }}</span> 转账
</p>
<p class="text-2xl font-bold text-green-600 mt-2">¥{{ amount }}</p>
</template>
<template v-if="status === 3">
<p class="text-red-500 text-sm px-4">{{ failMsg }}</p>
</template>
</div>
<!-- 进度条处理中状态 -->
<van-progress v-if="status === 1" :percentage="60" stroke-width="8"
color="linear-gradient(to right, #3b82f6, #60a5fa)" track-color="#e0f2fe"
class="!rounded-full" />
<!-- 辅助文案 -->
<div class="text-xs text-gray-400 space-y-1.5">
<template v-if="status === 2">
<p>预计24小时内到账</p>
<p>可在支付宝账单中查看详情</p>
</template>
<template v-if="status === 1">
<p>您的申请已进入处理队列</p>
<p>5分钟后结果在提现记录种查看</p>
</template>
</div>
<!-- 操作按钮 -->
<van-button block round size="small" :color="statusButtonColor[status]"
class="mt-4 h-11 font-medium shadow-sm" @click="handlePopupAction">
{{ status === 1 ? '知道了' : status === 2 ? '完成' : '重新提现' }}
</van-button>
</div>
</div>
</van-popup>
2025-03-08 15:26:04 +08:00
</div>
</template>
<script setup>
2025-04-10 23:01:03 +08:00
import { ref, computed } from 'vue';
import { showToast } from 'vant';
// 状态管理
const status = ref(null);
const failMsg = ref('');
const isSubmitting = ref(false);
const showStatusPopup = ref(false);
// 样式配置
const statusIcon = {
1: 'clock',
2: 'checked',
3: 'close'
};
const statusIconClass = {
1: 'text-blue-400 border-blue-100 bg-blue-50',
2: 'text-green-500 border-green-100 bg-green-50',
3: 'text-red-500 border-red-100 bg-red-50'
};
const statusBg = {
1: 'from-blue-100 to-blue-50',
2: 'from-green-100 to-green-50',
3: 'from-red-100 to-red-50'
};
const statusTextColors = {
1: 'text-blue-600',
2: 'text-green-600',
3: 'text-red-600'
};
const statusButtonColor = {
1: '#e0f2fe',
2: '#4ade80',
3: '#fca5a5'
};
const statusMessages = {
1: '提现申请处理中,请稍后再查询结果',
2: '提现成功',
3: '提现失败'
};
// 表单数据
const alipayAccount = ref('');
const amount = ref(null);
const availableAmount = ref(null);
const realName = ref('');
const getData = async () => {
const { data: res, error } = await useApiFetch("/agent/revenue")
.get()
.json();
if (res.value?.code === 200 && !error.value) {
availableAmount.value = res.value.data.balance;
}
};
onBeforeMount(() => {
getData();
});
// 表单验证
const validateAmount = (val) => {
const num = Number(val);
return num >= 50 && num <= availableAmount.value;
};
const validateForm = () => {
if (!realName.value.trim()) {
showToast('请输入账户实名姓名');
return false;
}
if (!/^[\u4e00-\u9fa5]{2,4}$/.test(realName.value)) {
showToast('请输入2-4位中文姓名');
return false;
}
if (!alipayAccount.value.trim()) {
showToast('请输入支付宝账号');
return false;
}
const amountNum = Number(amount.value);
if (!amount.value || isNaN(amountNum)) {
showToast('请输入有效金额');
return false;
}
if (amountNum < 50) {
showToast('提现金额不能低于50元');
return false;
}
if (amountNum > availableAmount.value) {
showToast('超过可提现金额');
return false;
}
return true;
};
const handleSubmit = async () => {
// 先进行表单验证
if (!validateForm()) return;
isSubmitting.value = true;
try {
const { data, error } = await useApiFetch("/agent/withdrawal")
.post({ payee_account: alipayAccount.value, amount: amount.value, payee_name: realName.value })
.json();
if (data.value?.code === 200) {
status.value = data.value.data.status;
showStatusPopup.value = true;
if (status.value === 3) {
failMsg.value = data.value.data.fail_msg;
}
}
} catch {
} finally {
isSubmitting.value = false;
}
};
// 弹窗操作
const handlePopupAction = () => {
if (status.value === 3) {
showStatusPopup.value = false;
resetForm();
} else {
showStatusPopup.value = false;
if (status.value === 2) resetPage();
}
};
// 填充最大金额
const fillMaxAmount = () => {
amount.value = availableAmount.value;
};
// 重置页面
const resetForm = () => {
status.value = null;
alipayAccount.value = '';
amount.value = '';
realName.value = '';
};
2025-03-08 15:26:04 +08:00
</script>
2025-04-10 23:01:03 +08:00
<style>
/* 自定义表单样式 */
.van-field__control {
@apply py-1 px-4 text-gray-800;
}
.van-field__error-message {
@apply mt-1;
}
.van-button--disabled {
@apply opacity-60 cursor-not-allowed;
}
/* 弹窗入场动画 */
.van-popup {
transition: transform 0.4s cubic-bezier(0.22, 0.61, 0.36, 1), opacity 0.3s ease;
}
.van-popup-enter-active,
.van-popup-leave-active {
transition: opacity 0.3s;
}
.van-popup-enter-from,
.van-popup-leave-to {
opacity: 0;
}
.van-popup-enter-active {
transform: scale(0.95);
}
.van-popup-enter-to {
transform: scale(1);
}
/* 状态图标动画 */
.animate-pulse {
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
@keyframes pulse {
50% {
opacity: 0.5;
}
}
2025-03-08 15:26:04 +08:00
</style>