|
|
@@ -0,0 +1,570 @@
|
|
|
+<template>
|
|
|
+ <div class="withdrawal-request-page">
|
|
|
+ <!-- 头部 -->
|
|
|
+ <div class="header">
|
|
|
+ <el-button class="back-btn" @click="goBack"> 返回 </el-button>
|
|
|
+ <h2 class="title">提现申请</h2>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 内容区域 -->
|
|
|
+ <div class="content">
|
|
|
+ <!-- 可提现金额 -->
|
|
|
+ <div class="section">
|
|
|
+ <div class="section-title">可提现金额</div>
|
|
|
+ <div class="available-amount-box">
|
|
|
+ <div class="available-amount">¥ {{ formatCurrency(availableAmount) }}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 提现金额输入 -->
|
|
|
+ <div class="section">
|
|
|
+ <div class="section-title">提现金额</div>
|
|
|
+ <div class="amount-input-wrapper">
|
|
|
+ <el-input
|
|
|
+ v-model="withdrawAmount"
|
|
|
+ placeholder="请输入提现金额"
|
|
|
+ class="amount-input"
|
|
|
+ type="number"
|
|
|
+ @input="handleAmountInput"
|
|
|
+ />
|
|
|
+ <el-button type="primary" link class="withdraw-all-btn" @click="handleWithdrawAll"> 全部提现 </el-button>
|
|
|
+ </div>
|
|
|
+ <div class="min-amount-tip">最低提现金额为0.01元</div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 提现账户 -->
|
|
|
+ <div class="section">
|
|
|
+ <div class="section-title">提现账户</div>
|
|
|
+ <div class="account-list">
|
|
|
+ <div
|
|
|
+ v-for="account in accountList"
|
|
|
+ :key="account.id"
|
|
|
+ class="account-item"
|
|
|
+ :class="{ active: selectedAccountId === account.id }"
|
|
|
+ @click="selectAccount(account.id)"
|
|
|
+ >
|
|
|
+ <div class="account-left">
|
|
|
+ <img :src="account.icon" alt="" class="account-icon" />
|
|
|
+ <div class="account-info">
|
|
|
+ <div class="account-name">
|
|
|
+ {{ account.name }}
|
|
|
+ </div>
|
|
|
+ <div class="account-number">
|
|
|
+ {{ account.accountNumber }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="account-right">
|
|
|
+ <div v-if="selectedAccountId === account.id" class="selected-indicator" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 底部按钮 -->
|
|
|
+ <div class="footer">
|
|
|
+ <el-button class="cancel-btn" @click="goBack"> 取消 </el-button>
|
|
|
+ <el-button type="primary" class="submit-btn" @click="handleSubmit"> 提交申请 </el-button>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 确认对话框 -->
|
|
|
+ <el-dialog
|
|
|
+ v-model="confirmDialogVisible"
|
|
|
+ title="提现金额域账户确认"
|
|
|
+ width="500px"
|
|
|
+ :close-on-click-modal="false"
|
|
|
+ class="confirm-dialog"
|
|
|
+ >
|
|
|
+ <div class="confirm-content">
|
|
|
+ <div class="confirm-item">
|
|
|
+ <span class="confirm-label">提现金额:</span>
|
|
|
+ <span class="confirm-value">¥ {{ withdrawAmount || "0" }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="confirm-item">
|
|
|
+ <span class="confirm-label">提现账户:</span>
|
|
|
+ <span class="confirm-value">{{ selectedAccount?.name }}账户 ({{ selectedAccount?.accountNumber }})</span>
|
|
|
+ </div>
|
|
|
+ <div class="password-section">
|
|
|
+ <div class="password-label">请输入提现密码</div>
|
|
|
+ <el-input
|
|
|
+ v-model="withdrawPassword"
|
|
|
+ type="password"
|
|
|
+ placeholder="请输入6位提现密码"
|
|
|
+ maxlength="6"
|
|
|
+ show-password
|
|
|
+ class="password-input"
|
|
|
+ @input="handlePasswordInput"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <template #footer>
|
|
|
+ <div class="dialog-footer">
|
|
|
+ <el-button class="dialog-cancel-btn" @click="handleCancelConfirm"> 取消 </el-button>
|
|
|
+ <el-button type="primary" class="dialog-confirm-btn" @click="handleConfirmSubmit" :loading="submitLoading">
|
|
|
+ 确认
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup lang="ts">
|
|
|
+import { ref, computed, onMounted } from "vue";
|
|
|
+import { useRouter } from "vue-router";
|
|
|
+import { ElMessage } from "element-plus";
|
|
|
+import { getAccountBalance } from "@/api/modules/homeEntry";
|
|
|
+import { localGet } from "@/utils";
|
|
|
+import zfbIcon from "@/assets/financial/zfb-icon.png";
|
|
|
+
|
|
|
+const router = useRouter();
|
|
|
+
|
|
|
+// 可提现金额
|
|
|
+const availableAmount = ref<number>(586);
|
|
|
+
|
|
|
+// 提现金额
|
|
|
+const withdrawAmount = ref<string>("");
|
|
|
+
|
|
|
+// 账户列表
|
|
|
+const accountList = ref([
|
|
|
+ {
|
|
|
+ id: 1,
|
|
|
+ name: "支付宝",
|
|
|
+ accountNumber: "130****1234",
|
|
|
+ icon: zfbIcon
|
|
|
+ }
|
|
|
+]);
|
|
|
+
|
|
|
+// 选中的账户ID
|
|
|
+const selectedAccountId = ref<number>(1);
|
|
|
+
|
|
|
+// 确认对话框
|
|
|
+const confirmDialogVisible = ref<boolean>(false);
|
|
|
+const withdrawPassword = ref<string>("");
|
|
|
+const submitLoading = ref<boolean>(false);
|
|
|
+
|
|
|
+// 获取选中的账户
|
|
|
+const selectedAccount = computed(() => {
|
|
|
+ return accountList.value.find(account => account.id === selectedAccountId.value);
|
|
|
+});
|
|
|
+
|
|
|
+// 返回
|
|
|
+const goBack = () => {
|
|
|
+ router.back();
|
|
|
+};
|
|
|
+
|
|
|
+// 格式化金额
|
|
|
+const formatCurrency = (value: number) => {
|
|
|
+ return value.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 });
|
|
|
+};
|
|
|
+
|
|
|
+// 全部提现
|
|
|
+const handleWithdrawAll = () => {
|
|
|
+ withdrawAmount.value = availableAmount.value.toString();
|
|
|
+};
|
|
|
+
|
|
|
+// 金额输入处理
|
|
|
+const handleAmountInput = (value: string) => {
|
|
|
+ const numValue = parseFloat(value);
|
|
|
+ if (isNaN(numValue) || numValue < 0) {
|
|
|
+ withdrawAmount.value = "";
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (numValue > availableAmount.value) {
|
|
|
+ withdrawAmount.value = availableAmount.value.toString();
|
|
|
+ ElMessage.warning("提现金额不能超过可提现金额");
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 选择账户(已选中的不能取消)
|
|
|
+const selectAccount = (id: number) => {
|
|
|
+ // 如果点击的是已选中的账户,不执行任何操作(不可取消)
|
|
|
+ if (selectedAccountId.value === id) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ selectedAccountId.value = id;
|
|
|
+};
|
|
|
+
|
|
|
+// 提交申请
|
|
|
+const handleSubmit = () => {
|
|
|
+ const amount = parseFloat(withdrawAmount.value);
|
|
|
+
|
|
|
+ // 验证提现金额
|
|
|
+ if (!withdrawAmount.value || isNaN(amount) || amount <= 0) {
|
|
|
+ ElMessage.warning("请输入提现金额");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (amount < 0.01) {
|
|
|
+ ElMessage.warning("最低提现金额为0.01元");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (amount > availableAmount.value) {
|
|
|
+ ElMessage.warning("提现金额不能超过可提现金额");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 验证账户
|
|
|
+ if (!selectedAccountId.value) {
|
|
|
+ ElMessage.warning("请选择提现账户");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 打开确认对话框
|
|
|
+ confirmDialogVisible.value = true;
|
|
|
+ withdrawPassword.value = "";
|
|
|
+};
|
|
|
+
|
|
|
+// 密码输入处理(只允许数字)
|
|
|
+const handlePasswordInput = (value: string) => {
|
|
|
+ withdrawPassword.value = value.replace(/\D/g, "");
|
|
|
+};
|
|
|
+
|
|
|
+// 取消确认
|
|
|
+const handleCancelConfirm = () => {
|
|
|
+ confirmDialogVisible.value = false;
|
|
|
+ withdrawPassword.value = "";
|
|
|
+};
|
|
|
+
|
|
|
+// 确认提交
|
|
|
+const handleConfirmSubmit = async () => {
|
|
|
+ // 验证密码
|
|
|
+ if (!withdrawPassword.value) {
|
|
|
+ ElMessage.warning("请输入提现密码");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (withdrawPassword.value.length !== 6) {
|
|
|
+ ElMessage.warning("请输入6位提现密码");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!/^\d{6}$/.test(withdrawPassword.value)) {
|
|
|
+ ElMessage.warning("提现密码必须为6位数字");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ submitLoading.value = true;
|
|
|
+ try {
|
|
|
+ // TODO: 调用提现API
|
|
|
+ // const params = {
|
|
|
+ // amount: parseFloat(withdrawAmount.value),
|
|
|
+ // accountId: selectedAccountId.value,
|
|
|
+ // password: withdrawPassword.value
|
|
|
+ // };
|
|
|
+ // const res = await submitWithdrawal(params);
|
|
|
+
|
|
|
+ // 模拟API调用
|
|
|
+ await new Promise(resolve => setTimeout(resolve, 1500));
|
|
|
+
|
|
|
+ ElMessage.success("提现申请提交成功");
|
|
|
+ confirmDialogVisible.value = false;
|
|
|
+ withdrawPassword.value = "";
|
|
|
+
|
|
|
+ // 提交成功后返回上一页
|
|
|
+ setTimeout(() => {
|
|
|
+ goBack();
|
|
|
+ }, 1500);
|
|
|
+ } catch (error: any) {
|
|
|
+ ElMessage.error(error.message || "提现申请提交失败,请重试");
|
|
|
+ } finally {
|
|
|
+ submitLoading.value = false;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 获取可提现金额
|
|
|
+const fetchAccountBalance = async () => {
|
|
|
+ try {
|
|
|
+ const userInfo = localGet("geeker-user")?.userInfo || {};
|
|
|
+ let param = {
|
|
|
+ storeId: userInfo.storeId || localGet("createdId")
|
|
|
+ };
|
|
|
+ const res: any = await getAccountBalance(param as any);
|
|
|
+ if (res.code == 200 && res.data) {
|
|
|
+ availableAmount.value = res.data.balance || res.data.availableAmount || res.data.amount || 586;
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error("获取可提现金额失败:", error);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ fetchAccountBalance();
|
|
|
+});
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped lang="scss">
|
|
|
+.withdrawal-request-page {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ width: 100%;
|
|
|
+ min-height: 100vh;
|
|
|
+ background-color: #ffffff;
|
|
|
+}
|
|
|
+.header {
|
|
|
+ position: relative;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ padding: 20px;
|
|
|
+ border-bottom: 1px solid #e4e7ed;
|
|
|
+ .back-btn {
|
|
|
+ padding: 8px 16px;
|
|
|
+ font-size: 14px;
|
|
|
+ color: #606266;
|
|
|
+ border: 1px solid #dcdfe6;
|
|
|
+ border-radius: 4px;
|
|
|
+ &:hover {
|
|
|
+ color: #409eff;
|
|
|
+ background-color: #ecf5ff;
|
|
|
+ border-color: #b3d8ff;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .title {
|
|
|
+ position: absolute;
|
|
|
+ left: 50%;
|
|
|
+ margin: 0;
|
|
|
+ font-size: 18px;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #333333;
|
|
|
+ transform: translateX(-50%);
|
|
|
+ }
|
|
|
+}
|
|
|
+.content {
|
|
|
+ display: flex;
|
|
|
+ flex: 1;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 32px;
|
|
|
+ padding: 24px 20px;
|
|
|
+}
|
|
|
+.section {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 12px;
|
|
|
+ .section-title {
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #333333;
|
|
|
+ }
|
|
|
+}
|
|
|
+.available-amount-box {
|
|
|
+ padding: 20px;
|
|
|
+ margin-top: 8px;
|
|
|
+ background-color: #ffffff;
|
|
|
+ border: 1px solid #e4e7ed;
|
|
|
+ border-radius: 4px;
|
|
|
+ .available-amount {
|
|
|
+ font-size: 36px;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #333333;
|
|
|
+ }
|
|
|
+}
|
|
|
+.amount-input-wrapper {
|
|
|
+ display: flex;
|
|
|
+ gap: 12px;
|
|
|
+ align-items: center;
|
|
|
+ margin-top: 8px;
|
|
|
+ .amount-input {
|
|
|
+ flex: 1;
|
|
|
+ :deep(.el-input__wrapper) {
|
|
|
+ padding: 12px 16px;
|
|
|
+ border-radius: 4px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .withdraw-all-btn {
|
|
|
+ padding: 0;
|
|
|
+ font-size: 14px;
|
|
|
+ color: #409eff;
|
|
|
+ white-space: nowrap;
|
|
|
+ background: transparent;
|
|
|
+ border: none;
|
|
|
+ &:hover {
|
|
|
+ color: #66b1ff;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+.min-amount-tip {
|
|
|
+ margin-top: 4px;
|
|
|
+ font-size: 12px;
|
|
|
+ color: #909399;
|
|
|
+}
|
|
|
+.account-list {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 12px;
|
|
|
+ margin-top: 8px;
|
|
|
+}
|
|
|
+.account-item {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ padding: 16px;
|
|
|
+ cursor: pointer;
|
|
|
+ background-color: #ffffff;
|
|
|
+ border: 1px solid #e4e7ed;
|
|
|
+ border-radius: 4px;
|
|
|
+ transition: all 0.3s;
|
|
|
+ &:hover {
|
|
|
+ border-color: #409eff;
|
|
|
+ }
|
|
|
+ &.active {
|
|
|
+ background-color: #f5f7fa;
|
|
|
+ border-color: #409eff;
|
|
|
+ }
|
|
|
+ .account-left {
|
|
|
+ display: flex;
|
|
|
+ flex: 1;
|
|
|
+ gap: 12px;
|
|
|
+ align-items: center;
|
|
|
+ .account-icon {
|
|
|
+ width: 40px;
|
|
|
+ height: 40px;
|
|
|
+ object-fit: contain;
|
|
|
+ }
|
|
|
+ .account-info {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 4px;
|
|
|
+ .account-name {
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #333333;
|
|
|
+ }
|
|
|
+ .account-number {
|
|
|
+ font-size: 14px;
|
|
|
+ color: #909399;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .account-right {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ width: 24px;
|
|
|
+ height: 24px;
|
|
|
+ .selected-indicator {
|
|
|
+ width: 16px;
|
|
|
+ height: 16px;
|
|
|
+ background-color: #409eff;
|
|
|
+ border: 3px solid #ffffff;
|
|
|
+ border-radius: 50%;
|
|
|
+ box-shadow: 0 0 0 2px #409eff;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+.footer {
|
|
|
+ display: flex;
|
|
|
+ gap: 12px;
|
|
|
+ justify-content: center;
|
|
|
+ padding: 20px;
|
|
|
+ background-color: #ffffff;
|
|
|
+ border-top: 1px solid #e4e7ed;
|
|
|
+ .cancel-btn {
|
|
|
+ width: 100px;
|
|
|
+ padding: 12px;
|
|
|
+ font-size: 16px;
|
|
|
+ color: #606266;
|
|
|
+ background-color: #f5f7fa;
|
|
|
+ border: 1px solid #dcdfe6;
|
|
|
+ border-radius: 4px;
|
|
|
+ &:hover {
|
|
|
+ color: #409eff;
|
|
|
+ background-color: #ecf5ff;
|
|
|
+ border-color: #b3d8ff;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .submit-btn {
|
|
|
+ width: 100px;
|
|
|
+ padding: 12px;
|
|
|
+ font-size: 16px;
|
|
|
+ color: #ffffff;
|
|
|
+ background-color: #409eff;
|
|
|
+ border: none;
|
|
|
+ border-radius: 4px;
|
|
|
+ &:hover {
|
|
|
+ background-color: #66b1ff;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+:deep(.confirm-dialog) {
|
|
|
+ .el-dialog__header {
|
|
|
+ padding: 20px 24px;
|
|
|
+ border-bottom: 1px solid #e4e7ed;
|
|
|
+ }
|
|
|
+ .el-dialog__title {
|
|
|
+ font-size: 18px;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #333333;
|
|
|
+ }
|
|
|
+ .el-dialog__body {
|
|
|
+ padding: 24px;
|
|
|
+ }
|
|
|
+}
|
|
|
+.confirm-content {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 20px;
|
|
|
+ .confirm-item {
|
|
|
+ display: flex;
|
|
|
+ gap: 12px;
|
|
|
+ align-items: center;
|
|
|
+ font-size: 14px;
|
|
|
+ .confirm-label {
|
|
|
+ min-width: 80px;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #606266;
|
|
|
+ }
|
|
|
+ .confirm-value {
|
|
|
+ font-weight: 500;
|
|
|
+ color: #333333;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .password-section {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 12px;
|
|
|
+ margin-top: 8px;
|
|
|
+ .password-label {
|
|
|
+ font-size: 14px;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #606266;
|
|
|
+ }
|
|
|
+ .password-input {
|
|
|
+ :deep(.el-input__wrapper) {
|
|
|
+ padding: 12px 16px;
|
|
|
+ border-radius: 4px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+.dialog-footer {
|
|
|
+ display: flex;
|
|
|
+ gap: 12px;
|
|
|
+ justify-content: flex-end;
|
|
|
+ .dialog-cancel-btn {
|
|
|
+ padding: 10px 20px;
|
|
|
+ font-size: 14px;
|
|
|
+ color: #606266;
|
|
|
+ background-color: #f5f7fa;
|
|
|
+ border: 1px solid #dcdfe6;
|
|
|
+ border-radius: 4px;
|
|
|
+ &:hover {
|
|
|
+ color: #409eff;
|
|
|
+ background-color: #ecf5ff;
|
|
|
+ border-color: #b3d8ff;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .dialog-confirm-btn {
|
|
|
+ padding: 10px 20px;
|
|
|
+ font-size: 14px;
|
|
|
+ color: #ffffff;
|
|
|
+ background-color: #409eff;
|
|
|
+ border: none;
|
|
|
+ border-radius: 4px;
|
|
|
+ &:hover {
|
|
|
+ background-color: #66b1ff;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|