1408 行
37 KiB
Vue
1408 行
37 KiB
Vue
<template>
|
||
<view class="recharge-page" :class="['theme-' + currentThemeKey]" :style="navStyle">
|
||
<!-- 顶部沉浸式自定义导航栏 -->
|
||
<view class="custom-nav-bar">
|
||
<view class="nav-content">
|
||
<view class="btn-nav-back btn-active" @click="handleBack">
|
||
<image class="nav-back-icon" :src="ICONS.chevronLeft" mode="aspectFit" />
|
||
</view>
|
||
<view class="nav-title-wrap">
|
||
<text class="nav-title">钱包充值</text>
|
||
</view>
|
||
<view class="nav-right-action btn-active" @click="viewBillRecords">
|
||
<image class="nav-rec-icon" :src="ICONS.orderList" mode="aspectFit" />
|
||
<text class="nav-rec-text">账单明细</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 页面可滚动主体区 -->
|
||
<scroll-view scroll-y class="page-scroll-body">
|
||
<!-- 卡片 1: 当前可用余额流光看板 -->
|
||
<view class="balance-card">
|
||
<view class="card-bg-glow"></view>
|
||
<view class="balance-inner">
|
||
<view class="balance-title-row">
|
||
<view class="title-left">
|
||
<image class="wallet-icon-svg" :src="ICONS.wallet" mode="aspectFit" />
|
||
<text class="balance-title">当前可用余额 (元)</text>
|
||
</view>
|
||
<view class="user-uid-pill" v-if="currentUserId">
|
||
<text class="uid-text">UID: {{ currentUserId }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="amount-number-row">
|
||
<text class="currency-mark">¥</text>
|
||
<text class="amount-integer">{{ balanceParts.integer }}</text>
|
||
<text class="amount-decimal">.{{ balanceParts.decimal }}</text>
|
||
</view>
|
||
|
||
<view class="balance-after-row">
|
||
<text class="after-label">充值后预计余额:</text>
|
||
<text class="after-val">¥{{ displayEstimatedBalance }}</text>
|
||
<text class="after-bonus" v-if="currentBonusAmount > 0">(含本次加赠 ¥{{ currentBonusAmount }})</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 卡片 2: 充值金额档位快捷选择 -->
|
||
<view class="content-card tier-card">
|
||
<view class="card-section-head">
|
||
<view class="head-left">
|
||
<text class="section-title">充值金额</text>
|
||
<text class="section-sub">充得多赠得多 · 即时到账</text>
|
||
</view>
|
||
<view class="head-tag-bonus" v-if="maxBonusTier">
|
||
最高立赠 ¥{{ maxBonusTier.bonusAmount }}
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 档位网格 -->
|
||
<view class="tier-grid">
|
||
<view
|
||
v-for="(tier, idx) in tierList"
|
||
:key="tier.id || idx"
|
||
class="tier-grid-item btn-active"
|
||
:class="{ active: selectedTierIndex === idx && !isCustomMode }"
|
||
@click="selectTier(idx)"
|
||
>
|
||
<view class="tier-badge" v-if="tier.tag || tier.bonusAmount > 0">
|
||
<text class="badge-txt">{{ tier.tag || ('赠¥' + tier.bonusAmount) }}</text>
|
||
</view>
|
||
|
||
<view class="tier-amount-wrap">
|
||
<text class="tier-curr">¥</text>
|
||
<text class="tier-val">{{ tier.amount }}</text>
|
||
</view>
|
||
|
||
<view class="tier-gift-row" v-if="tier.bonusAmount > 0">
|
||
<text class="tier-gift-label">赠送 ¥{{ tier.bonusAmount }}</text>
|
||
</view>
|
||
<view class="tier-gift-row empty" v-else>
|
||
<text class="tier-gift-label empty">到账 ¥{{ tier.amount }}</text>
|
||
</view>
|
||
|
||
<view class="tier-check-mark" v-if="selectedTierIndex === idx && !isCustomMode">
|
||
<image class="check-svg" :src="ICONS.checkCircle" mode="aspectFit" />
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 自定义充值金额输入区 -->
|
||
<view class="custom-amount-wrapper">
|
||
<view class="custom-title-row">
|
||
<text class="custom-label">输入其他金额 (元)</text>
|
||
<text class="custom-rule-hint">支持 1 至 50,000 元任意充值</text>
|
||
</view>
|
||
|
||
<view class="custom-amount-box" :class="{ active: isCustomMode, 'is-focused': isInputFocused }">
|
||
<text class="custom-currency-symbol">¥</text>
|
||
<input
|
||
class="custom-amount-input amount-field-input"
|
||
type="digit"
|
||
v-model="customAmountText"
|
||
placeholder="自定义金额 (1 - 50000)"
|
||
placeholder-class="custom-ph"
|
||
maxlength="7"
|
||
@focus="onCustomInputFocus"
|
||
@blur="onCustomInputBlur"
|
||
@input="onCustomAmountChange"
|
||
/>
|
||
<view class="btn-clear-custom btn-active" v-if="customAmountText" @click="clearCustomAmount">
|
||
<image class="clear-svg" :src="ICONS.close" mode="aspectFit" />
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 动态提示 -->
|
||
<view class="custom-tip-row" v-if="isCustomMode">
|
||
<text class="tip-err" v-if="isCustomAmountInvalid">请输入合法的充值金额 (1 - 50000 元)</text>
|
||
<text class="tip-normal" v-else>
|
||
实付 ¥{{ currentPayAmount.toFixed(2) }},预计到账 ¥{{ currentTotalCredit.toFixed(2) }}
|
||
<text class="tip-bonus" v-if="currentBonusAmount > 0">(已匹配活动加赠 ¥{{ currentBonusAmount }})</text>
|
||
</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 卡片 3: 支付方式选择 (微信支付专属快捷通道) -->
|
||
<view class="content-card channel-card">
|
||
<view class="card-section-head">
|
||
<text class="section-title">支付方式</text>
|
||
<view class="section-badge-green">官方官方推荐</view>
|
||
</view>
|
||
|
||
<view class="channel-list">
|
||
<view class="channel-row active">
|
||
<view class="channel-icon-wrap wechat">
|
||
<image class="channel-svg" :src="ICONS.wechat" mode="aspectFit" />
|
||
</view>
|
||
<view class="channel-info">
|
||
<view class="channel-line-1">
|
||
<text class="channel-name">微信支付</text>
|
||
<text class="channel-rec-tag">极速直达</text>
|
||
</view>
|
||
<text class="channel-desc">微信官方安全收银台 · 秒级到账</text>
|
||
</view>
|
||
<view class="channel-select-mark">
|
||
<image class="check-svg" :src="ICONS.checkCircle" mode="aspectFit" />
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="channel-safe-banner">
|
||
<image class="safe-icon" :src="ICONS.shield" mode="aspectFit" />
|
||
<text class="safe-text">平台资金由微信支付合规商户托管,充值即刻生效入账</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 卡片 4: 充值规则与资金保障 -->
|
||
<view class="rules-card">
|
||
<view class="rules-head">
|
||
<image class="rules-icon" :src="ICONS.shield" mode="aspectFit" />
|
||
<text class="rules-title">充值服务说明与资金安全保障</text>
|
||
</view>
|
||
<view class="rules-list">
|
||
<view class="rule-line">
|
||
<text class="dot">·</text>
|
||
<text class="text">充值资金实时计入个人账户余额,可用于陪玩下单、组局报名及搭子开黑等全部消费场景;</text>
|
||
</view>
|
||
<view class="rule-line">
|
||
<text class="dot">·</text>
|
||
<text class="text">充值赠送金额将随本金一同入账,平台优先抵扣消费,赠送金额不支持提现;</text>
|
||
</view>
|
||
<view class="rule-line">
|
||
<text class="dot">·</text>
|
||
<text class="text">充值交易经由微信商户全链路加密风控保护,7x24小时全自动记账对账;</text>
|
||
</view>
|
||
<view class="rule-line">
|
||
<text class="dot">·</text>
|
||
<text class="text">如遇网络延迟未即时显示余额,请在个人中心下拉刷新或联系官方在线客服核验处理。</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 底部安全垫高 -->
|
||
<view class="bottom-spacer"></view>
|
||
</scroll-view>
|
||
|
||
<!-- 底部固定确认支付操作栏 -->
|
||
<view class="fixed-submit-bar">
|
||
<view class="submit-summary">
|
||
<view class="summary-top">
|
||
<text class="summary-label">实付金额:</text>
|
||
<text class="summary-currency">¥</text>
|
||
<text class="summary-val">{{ currentPayAmount.toFixed(2) }}</text>
|
||
</view>
|
||
<view class="summary-sub" v-if="currentBonusAmount > 0">
|
||
<text class="sub-text">预计到账 ¥{{ currentTotalCredit.toFixed(2) }} (赠 ¥{{ currentBonusAmount }})</text>
|
||
</view>
|
||
<view class="summary-sub" v-else>
|
||
<text class="sub-text">预计实际到账 ¥{{ currentTotalCredit.toFixed(2) }}</text>
|
||
</view>
|
||
</view>
|
||
<button
|
||
class="btn-submit-recharge btn-active"
|
||
:class="{ disabled: isSubmitDisabled }"
|
||
:loading="isSubmitting"
|
||
@click="handleConfirmRecharge"
|
||
>
|
||
{{ isSubmitting ? '正在调起支付...' : '确认充值' }}
|
||
</button>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, computed, onMounted } from 'vue';
|
||
import { onShow } from '@dcloudio/uni-app';
|
||
import { ICONS } from '@/common/icons.js';
|
||
import { getCurrentThemeKey, applyThemeToNativeUI } from '@/common/theme.js';
|
||
import { getNavBarInfo } from '@/common/nav.js';
|
||
import { getUserProfile, rechargeBalance, getRechargeTiers, requestWechatPayment } from '@/common/api.js';
|
||
|
||
const currentThemeKey = ref(getCurrentThemeKey());
|
||
const navInfo = ref(getNavBarInfo());
|
||
|
||
const currentUserId = ref(1001);
|
||
const userBalance = ref('0.00');
|
||
|
||
// 预设阶梯列表 (自带高质量官方预置,支持后台动态更新)
|
||
const DEFAULT_TIERS = [
|
||
{ id: 1, amount: 50, bonusAmount: 0, tag: '基础充值' },
|
||
{ id: 2, amount: 100, bonusAmount: 5, tag: '热门畅享' },
|
||
{ id: 3, amount: 200, bonusAmount: 15, tag: '超值加赠' },
|
||
{ id: 4, amount: 500, bonusAmount: 50, tag: '尊享特惠' },
|
||
{ id: 5, amount: 1000, bonusAmount: 120, tag: '土豪专享' },
|
||
{ id: 6, amount: 2000, bonusAmount: 300, tag: '超神狂欢' }
|
||
];
|
||
|
||
const tierList = ref([...DEFAULT_TIERS]);
|
||
const selectedTierIndex = ref(1); // 默认选中 100 元 (热门畅享)
|
||
const isCustomMode = ref(false);
|
||
const customAmountText = ref('');
|
||
const isInputFocused = ref(false);
|
||
const isSubmitting = ref(false);
|
||
|
||
const navStyle = computed(() => {
|
||
const gap = (navInfo.value && navInfo.value.totalHeaderHeight) || 88;
|
||
return `--safe-header-gap: ${gap}px; padding-top: ${gap}px;`;
|
||
});
|
||
|
||
// 余额整数与小数拆分
|
||
const balanceParts = computed(() => {
|
||
const val = Number(userBalance.value || 0).toFixed(2);
|
||
const [integer, decimal] = val.split('.');
|
||
return { integer, decimal: decimal || '00' };
|
||
});
|
||
|
||
// 最大赠送档位
|
||
const maxBonusTier = computed(() => {
|
||
return [...tierList.value].sort((a, b) => (Number(b.bonusAmount) || 0) - (Number(a.bonusAmount) || 0))[0] || null;
|
||
});
|
||
|
||
// 当前实付金额
|
||
const currentPayAmount = computed(() => {
|
||
if (isCustomMode.value) {
|
||
const n = parseFloat(customAmountText.value);
|
||
return !isNaN(n) && n > 0 ? n : 0;
|
||
}
|
||
const tier = tierList.value[selectedTierIndex.value];
|
||
return tier ? Number(tier.amount) : 0;
|
||
});
|
||
|
||
// 当前赠送金额 (档位或自定义命中规则)
|
||
const currentBonusAmount = computed(() => {
|
||
if (isCustomMode.value) {
|
||
const pay = currentPayAmount.value;
|
||
if (pay <= 0) return 0;
|
||
// 在已有阶梯中匹配符合条件的最大赠金
|
||
const eligibleTiers = tierList.value
|
||
.filter((t) => Number(t.amount) <= pay && Number(t.bonusAmount) > 0)
|
||
.sort((a, b) => Number(b.amount) - Number(a.amount));
|
||
if (eligibleTiers.length > 0) {
|
||
return Number(eligibleTiers[0].bonusAmount);
|
||
}
|
||
return 0;
|
||
}
|
||
const tier = tierList.value[selectedTierIndex.value];
|
||
return tier && tier.bonusAmount ? Number(tier.bonusAmount) : 0;
|
||
});
|
||
|
||
// 当前预计总到账金额 (本金 + 赠额)
|
||
const currentTotalCredit = computed(() => {
|
||
return currentPayAmount.value + currentBonusAmount.value;
|
||
});
|
||
|
||
// 充值后预计总余额
|
||
const displayEstimatedBalance = computed(() => {
|
||
const cur = parseFloat(userBalance.value) || 0;
|
||
const total = cur + currentTotalCredit.value;
|
||
return total.toFixed(2);
|
||
});
|
||
|
||
// 自定义金额校验
|
||
const isCustomAmountInvalid = computed(() => {
|
||
if (!isCustomMode.value) return false;
|
||
if (!customAmountText.value) return false;
|
||
const n = parseFloat(customAmountText.value);
|
||
return isNaN(n) || n < 1 || n > 50000;
|
||
});
|
||
|
||
// 提交按钮是否禁用
|
||
const isSubmitDisabled = computed(() => {
|
||
if (isSubmitting.value) return true;
|
||
if (isCustomMode.value) {
|
||
const n = parseFloat(customAmountText.value);
|
||
return isNaN(n) || n < 1 || n > 50000;
|
||
}
|
||
return currentPayAmount.value <= 0;
|
||
});
|
||
|
||
// 选择预设档位
|
||
const selectTier = (index) => {
|
||
isCustomMode.value = false;
|
||
selectedTierIndex.value = index;
|
||
};
|
||
|
||
// 聚焦自定义输入框
|
||
const onCustomInputFocus = () => {
|
||
isInputFocused.value = true;
|
||
isCustomMode.value = true;
|
||
};
|
||
|
||
const onCustomInputBlur = () => {
|
||
isInputFocused.value = false;
|
||
if (!customAmountText.value) {
|
||
isCustomMode.value = false;
|
||
}
|
||
};
|
||
|
||
const onCustomAmountChange = () => {
|
||
if (customAmountText.value) {
|
||
isCustomMode.value = true;
|
||
}
|
||
};
|
||
|
||
const clearCustomAmount = () => {
|
||
customAmountText.value = '';
|
||
isCustomMode.value = false;
|
||
};
|
||
|
||
// 加载充值档位与用户数据
|
||
const loadData = async () => {
|
||
try {
|
||
const uid = uni.getStorageSync('userId') || 1001;
|
||
currentUserId.value = uid;
|
||
const profile = await getUserProfile(uid);
|
||
if (profile && profile.balance !== undefined) {
|
||
userBalance.value = String(profile.balance);
|
||
}
|
||
} catch (_) {}
|
||
|
||
try {
|
||
const remoteTiers = await getRechargeTiers();
|
||
if (Array.isArray(remoteTiers) && remoteTiers.length > 0) {
|
||
tierList.value = remoteTiers.map((item, i) => ({
|
||
id: item.id || i + 1,
|
||
amount: Number(item.amount),
|
||
bonusAmount: Number(item.bonusAmount || 0),
|
||
tag: item.tag || ''
|
||
}));
|
||
}
|
||
} catch (_) {}
|
||
};
|
||
|
||
// 返回上一级
|
||
const handleBack = () => {
|
||
const pages = typeof getCurrentPages === 'function' ? getCurrentPages() : [];
|
||
if (pages && pages.length > 1) {
|
||
uni.navigateBack({ delta: 1 });
|
||
} else {
|
||
uni.switchTab({ url: '/pages/user/index' });
|
||
}
|
||
};
|
||
|
||
// 查看账单明细
|
||
const viewBillRecords = () => {
|
||
uni.navigateTo({
|
||
url: '/pages/user/bill-records'
|
||
});
|
||
};
|
||
|
||
// 确认充值操作
|
||
const handleConfirmRecharge = async () => {
|
||
if (isSubmitDisabled.value) return;
|
||
|
||
const payAmount = currentPayAmount.value;
|
||
const bonus = currentBonusAmount.value;
|
||
if (payAmount <= 0) {
|
||
uni.showToast({ title: '请输入有效充值金额', icon: 'none' });
|
||
return;
|
||
}
|
||
|
||
isSubmitting.value = true;
|
||
uni.showLoading({ title: '正在调起微信支付...', mask: true });
|
||
|
||
try {
|
||
const uid = currentUserId.value || uni.getStorageSync('userId') || 1001;
|
||
await requestWechatPayment({
|
||
amount: payAmount,
|
||
title: `钱包余额充值 ¥${payAmount}`,
|
||
orderId: `RC-${Date.now()}`,
|
||
scene: 'RECHARGE',
|
||
userId: uid
|
||
});
|
||
const res = await rechargeBalance(uid, payAmount, bonus);
|
||
uni.hideLoading();
|
||
|
||
// 更新本地资产与全局缓存
|
||
if (res && res.balance !== undefined) {
|
||
userBalance.value = String(res.balance);
|
||
} else {
|
||
const cur = parseFloat(userBalance.value) || 0;
|
||
userBalance.value = (cur + payAmount + bonus).toFixed(2);
|
||
}
|
||
|
||
const userInfo = uni.getStorageSync('userInfo') || {};
|
||
userInfo.balance = userBalance.value;
|
||
uni.setStorageSync('userInfo', userInfo);
|
||
uni.setStorageSync('PW_USER_INFO', userInfo);
|
||
|
||
const bonusHint = bonus > 0 ? `,加赠 ¥${bonus} 已同步入账` : '';
|
||
uni.showToast({
|
||
title: `充值 ¥${payAmount} 成功${bonusHint}`,
|
||
icon: 'success',
|
||
duration: 1800
|
||
});
|
||
|
||
// 延时平滑返回或刷新
|
||
setTimeout(() => {
|
||
handleBack();
|
||
}, 1800);
|
||
} catch (err) {
|
||
uni.hideLoading();
|
||
if (err && err.cancelled) {
|
||
uni.showToast({
|
||
title: '已取消充值支付',
|
||
icon: 'none',
|
||
duration: 1800
|
||
});
|
||
} else {
|
||
uni.showToast({
|
||
title: (err && err.message) || '充值支付失败,请重试',
|
||
icon: 'none',
|
||
duration: 2000
|
||
});
|
||
}
|
||
} finally {
|
||
isSubmitting.value = false;
|
||
}
|
||
};
|
||
|
||
onMounted(() => {
|
||
navInfo.value = getNavBarInfo();
|
||
currentThemeKey.value = getCurrentThemeKey();
|
||
applyThemeToNativeUI(currentThemeKey.value);
|
||
loadData();
|
||
});
|
||
|
||
onShow(() => {
|
||
navInfo.value = getNavBarInfo();
|
||
currentThemeKey.value = getCurrentThemeKey();
|
||
applyThemeToNativeUI(currentThemeKey.value);
|
||
loadData();
|
||
});
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.recharge-page {
|
||
min-height: 100vh;
|
||
box-sizing: border-box;
|
||
background-color: #0A0F1D;
|
||
color: #F8FAFC;
|
||
display: flex;
|
||
flex-direction: column;
|
||
|
||
// 顶部沉浸式导航栏
|
||
.custom-nav-bar {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
z-index: 100;
|
||
background: rgba(10, 15, 29, 0.88);
|
||
backdrop-filter: blur(20px);
|
||
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
|
||
|
||
.nav-content {
|
||
height: var(--safe-header-gap, 88px);
|
||
display: flex;
|
||
align-items: flex-end;
|
||
padding-bottom: 16rpx;
|
||
padding-left: 24rpx;
|
||
padding-right: 24rpx;
|
||
box-sizing: border-box;
|
||
position: relative;
|
||
|
||
.btn-nav-back {
|
||
width: 64rpx;
|
||
height: 64rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
background: rgba(255, 255, 255, 0.06);
|
||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||
border-radius: 50%;
|
||
margin-right: 16rpx;
|
||
|
||
.nav-back-icon {
|
||
width: 32rpx;
|
||
height: 32rpx;
|
||
}
|
||
}
|
||
|
||
.nav-title-wrap {
|
||
flex: 1;
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
.nav-title {
|
||
font-size: 34rpx;
|
||
font-weight: 700;
|
||
color: #F8FAFC;
|
||
letter-spacing: 0.5rpx;
|
||
}
|
||
}
|
||
|
||
.nav-right-action {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 6rpx;
|
||
background: rgba(99, 102, 241, 0.12);
|
||
border: 1px solid rgba(99, 102, 241, 0.25);
|
||
padding: 8rpx 18rpx;
|
||
border-radius: 30rpx;
|
||
|
||
.nav-rec-icon {
|
||
width: 24rpx;
|
||
height: 24rpx;
|
||
}
|
||
|
||
.nav-rec-text {
|
||
font-size: 22rpx;
|
||
color: #818CF8;
|
||
font-weight: 600;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 页面可滚动主体区
|
||
.page-scroll-body {
|
||
flex: 1;
|
||
padding: 24rpx;
|
||
box-sizing: border-box;
|
||
|
||
// 卡片 1: 余额看板
|
||
.balance-card {
|
||
position: relative;
|
||
border-radius: 24rpx;
|
||
background: linear-gradient(135deg, rgba(30, 41, 59, 0.95) 0%, rgba(15, 23, 42, 0.98) 100%);
|
||
border: 1px solid rgba(99, 102, 241, 0.25);
|
||
padding: 32rpx;
|
||
margin-bottom: 24rpx;
|
||
overflow: hidden;
|
||
box-shadow: 0 16rpx 40rpx rgba(0, 0, 0, 0.35);
|
||
|
||
.card-bg-glow {
|
||
position: absolute;
|
||
top: -60rpx;
|
||
right: -60rpx;
|
||
width: 200rpx;
|
||
height: 200rpx;
|
||
border-radius: 50%;
|
||
background: radial-gradient(circle, rgba(99, 102, 241, 0.35) 0%, rgba(99, 102, 241, 0) 70%);
|
||
pointer-events: none;
|
||
}
|
||
|
||
.balance-inner {
|
||
position: relative;
|
||
z-index: 1;
|
||
|
||
.balance-title-row {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 20rpx;
|
||
|
||
.title-left {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12rpx;
|
||
|
||
.wallet-icon-svg {
|
||
width: 36rpx;
|
||
height: 36rpx;
|
||
}
|
||
|
||
.balance-title {
|
||
font-size: 26rpx;
|
||
color: #94A3B8;
|
||
font-weight: 500;
|
||
}
|
||
}
|
||
|
||
.user-uid-pill {
|
||
background: rgba(255, 255, 255, 0.06);
|
||
padding: 4rpx 14rpx;
|
||
border-radius: 12rpx;
|
||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||
|
||
.uid-text {
|
||
font-size: 20rpx;
|
||
color: #64748B;
|
||
font-family: monospace;
|
||
}
|
||
}
|
||
}
|
||
|
||
.amount-number-row {
|
||
display: flex;
|
||
align-items: baseline;
|
||
margin-bottom: 20rpx;
|
||
|
||
.currency-mark {
|
||
font-size: 40rpx;
|
||
font-weight: 700;
|
||
color: #10B981;
|
||
margin-right: 8rpx;
|
||
}
|
||
|
||
.amount-integer {
|
||
font-size: 72rpx;
|
||
font-weight: 800;
|
||
color: #10B981;
|
||
letter-spacing: -1rpx;
|
||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||
}
|
||
|
||
.amount-decimal {
|
||
font-size: 44rpx;
|
||
font-weight: 700;
|
||
color: #10B981;
|
||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||
}
|
||
}
|
||
|
||
.balance-after-row {
|
||
display: flex;
|
||
align-items: center;
|
||
flex-wrap: wrap;
|
||
font-size: 22rpx;
|
||
color: #94A3B8;
|
||
background: rgba(255, 255, 255, 0.03);
|
||
padding: 10rpx 16rpx;
|
||
border-radius: 12rpx;
|
||
|
||
.after-label {
|
||
color: #94A3B8;
|
||
}
|
||
|
||
.after-val {
|
||
color: #F8FAFC;
|
||
font-weight: 700;
|
||
margin-right: 8rpx;
|
||
}
|
||
|
||
.after-bonus {
|
||
color: #F59E0B;
|
||
font-weight: 600;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 通用卡片容器
|
||
.content-card {
|
||
background: #111827;
|
||
border: 1px solid rgba(255, 255, 255, 0.06);
|
||
border-radius: 24rpx;
|
||
padding: 32rpx;
|
||
margin-bottom: 24rpx;
|
||
|
||
.card-section-head {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 24rpx;
|
||
|
||
.head-left {
|
||
display: flex;
|
||
align-items: baseline;
|
||
gap: 12rpx;
|
||
|
||
.section-title {
|
||
font-size: 30rpx;
|
||
font-weight: 700;
|
||
color: #F8FAFC;
|
||
}
|
||
|
||
.section-sub {
|
||
font-size: 20rpx;
|
||
color: #64748B;
|
||
}
|
||
}
|
||
|
||
.section-badge-green {
|
||
font-size: 18rpx;
|
||
color: #10B981;
|
||
background: rgba(16, 185, 129, 0.12);
|
||
border: 1px solid rgba(16, 185, 129, 0.25);
|
||
padding: 4rpx 12rpx;
|
||
border-radius: 8rpx;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.head-tag-bonus {
|
||
font-size: 20rpx;
|
||
color: #F59E0B;
|
||
background: rgba(245, 158, 11, 0.12);
|
||
border: 1px solid rgba(245, 158, 11, 0.25);
|
||
padding: 4rpx 14rpx;
|
||
border-radius: 20rpx;
|
||
font-weight: 600;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 卡片 2: 充值档位网格
|
||
.tier-card {
|
||
.tier-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(3, 1fr);
|
||
gap: 16rpx;
|
||
margin-bottom: 30rpx;
|
||
|
||
.tier-grid-item {
|
||
position: relative;
|
||
background: rgba(255, 255, 255, 0.03);
|
||
border: 1.5px solid rgba(255, 255, 255, 0.08);
|
||
border-radius: 18rpx;
|
||
padding: 24rpx 12rpx 20rpx;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
transition: all 0.2s ease;
|
||
overflow: hidden;
|
||
|
||
.tier-badge {
|
||
position: absolute;
|
||
top: 0;
|
||
right: 0;
|
||
background: linear-gradient(135deg, #F59E0B, #D97706);
|
||
padding: 2rpx 10rpx;
|
||
border-bottom-left-radius: 12rpx;
|
||
|
||
.badge-txt {
|
||
font-size: 16rpx;
|
||
color: #FFFFFF;
|
||
font-weight: 700;
|
||
}
|
||
}
|
||
|
||
.tier-amount-wrap {
|
||
display: flex;
|
||
align-items: baseline;
|
||
margin-top: 10rpx;
|
||
margin-bottom: 6rpx;
|
||
|
||
.tier-curr {
|
||
font-size: 24rpx;
|
||
font-weight: 700;
|
||
color: #F8FAFC;
|
||
margin-right: 2rpx;
|
||
}
|
||
|
||
.tier-val {
|
||
font-size: 42rpx;
|
||
font-weight: 800;
|
||
color: #F8FAFC;
|
||
font-family: -apple-system, BlinkMacSystemFont, sans-serif;
|
||
}
|
||
}
|
||
|
||
.tier-gift-row {
|
||
.tier-gift-label {
|
||
font-size: 20rpx;
|
||
color: #F59E0B;
|
||
font-weight: 600;
|
||
|
||
&.empty {
|
||
color: #64748B;
|
||
font-weight: normal;
|
||
}
|
||
}
|
||
}
|
||
|
||
.tier-check-mark {
|
||
position: absolute;
|
||
bottom: 6rpx;
|
||
right: 6rpx;
|
||
|
||
.check-svg {
|
||
width: 24rpx;
|
||
height: 24rpx;
|
||
}
|
||
}
|
||
|
||
&.active {
|
||
background: rgba(99, 102, 241, 0.12);
|
||
border-color: #6366F1;
|
||
box-shadow: 0 0 20rpx rgba(99, 102, 241, 0.25);
|
||
|
||
.tier-amount-wrap .tier-curr,
|
||
.tier-amount-wrap .tier-val {
|
||
color: #818CF8;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 自定义金额
|
||
.custom-amount-wrapper {
|
||
border-top: 1px dashed rgba(255, 255, 255, 0.08);
|
||
padding-top: 24rpx;
|
||
|
||
.custom-title-row {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 16rpx;
|
||
|
||
.custom-label {
|
||
font-size: 24rpx;
|
||
font-weight: 600;
|
||
color: #94A3B8;
|
||
}
|
||
|
||
.custom-rule-hint {
|
||
font-size: 20rpx;
|
||
color: #64748B;
|
||
}
|
||
}
|
||
|
||
.custom-amount-box {
|
||
display: flex;
|
||
align-items: center;
|
||
background: rgba(255, 255, 255, 0.04);
|
||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||
border-radius: 16rpx;
|
||
padding: 0 20rpx;
|
||
height: 88rpx;
|
||
transition: all 0.2s ease;
|
||
|
||
.custom-currency-symbol {
|
||
font-size: 34rpx;
|
||
font-weight: 700;
|
||
color: #10B981;
|
||
margin-right: 12rpx;
|
||
}
|
||
|
||
.custom-amount-input {
|
||
flex: 1;
|
||
height: 100%;
|
||
font-size: 32rpx;
|
||
font-weight: 700;
|
||
color: #F8FAFC;
|
||
}
|
||
|
||
.custom-ph {
|
||
color: #475569;
|
||
font-weight: normal;
|
||
font-size: 26rpx;
|
||
}
|
||
|
||
.btn-clear-custom {
|
||
width: 48rpx;
|
||
height: 48rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
|
||
.clear-svg {
|
||
width: 28rpx;
|
||
height: 28rpx;
|
||
}
|
||
}
|
||
|
||
&.active,
|
||
&.is-focused {
|
||
background: rgba(99, 102, 241, 0.08);
|
||
border-color: #6366F1;
|
||
}
|
||
}
|
||
|
||
.custom-tip-row {
|
||
margin-top: 12rpx;
|
||
font-size: 22rpx;
|
||
|
||
.tip-err {
|
||
color: #EF4444;
|
||
}
|
||
|
||
.tip-normal {
|
||
color: #94A3B8;
|
||
|
||
.tip-bonus {
|
||
color: #F59E0B;
|
||
font-weight: 600;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 卡片 3: 支付通道
|
||
.channel-card {
|
||
.channel-list {
|
||
margin-bottom: 20rpx;
|
||
|
||
.channel-row {
|
||
display: flex;
|
||
align-items: center;
|
||
background: rgba(255, 255, 255, 0.03);
|
||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||
border-radius: 18rpx;
|
||
padding: 24rpx;
|
||
transition: all 0.2s ease;
|
||
|
||
.channel-icon-wrap {
|
||
width: 72rpx;
|
||
height: 72rpx;
|
||
border-radius: 18rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-right: 20rpx;
|
||
|
||
&.wechat {
|
||
background: rgba(16, 185, 129, 0.12);
|
||
border: 1px solid rgba(16, 185, 129, 0.2);
|
||
|
||
.channel-svg {
|
||
width: 44rpx;
|
||
height: 44rpx;
|
||
}
|
||
}
|
||
}
|
||
|
||
.channel-info {
|
||
flex: 1;
|
||
|
||
.channel-line-1 {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12rpx;
|
||
margin-bottom: 6rpx;
|
||
|
||
.channel-name {
|
||
font-size: 28rpx;
|
||
font-weight: 700;
|
||
color: #F8FAFC;
|
||
}
|
||
|
||
.channel-rec-tag {
|
||
font-size: 18rpx;
|
||
color: #10B981;
|
||
background: rgba(16, 185, 129, 0.12);
|
||
padding: 2rpx 8rpx;
|
||
border-radius: 6rpx;
|
||
font-weight: 600;
|
||
}
|
||
}
|
||
|
||
.channel-desc {
|
||
font-size: 22rpx;
|
||
color: #64748B;
|
||
}
|
||
}
|
||
|
||
.channel-select-mark {
|
||
.check-svg {
|
||
width: 36rpx;
|
||
height: 36rpx;
|
||
}
|
||
}
|
||
|
||
&.active {
|
||
border-color: rgba(16, 185, 129, 0.4);
|
||
background: rgba(16, 185, 129, 0.06);
|
||
}
|
||
}
|
||
}
|
||
|
||
.channel-safe-banner {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10rpx;
|
||
background: rgba(255, 255, 255, 0.02);
|
||
padding: 12rpx 16rpx;
|
||
border-radius: 12rpx;
|
||
|
||
.safe-icon {
|
||
width: 24rpx;
|
||
height: 24rpx;
|
||
}
|
||
|
||
.safe-text {
|
||
font-size: 20rpx;
|
||
color: #64748B;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 卡片 4: 规则说明
|
||
.rules-card {
|
||
background: #111827;
|
||
border: 1px solid rgba(255, 255, 255, 0.06);
|
||
border-radius: 24rpx;
|
||
padding: 30rpx;
|
||
margin-bottom: 30rpx;
|
||
|
||
.rules-head {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12rpx;
|
||
margin-bottom: 20rpx;
|
||
|
||
.rules-icon {
|
||
width: 28rpx;
|
||
height: 28rpx;
|
||
}
|
||
|
||
.rules-title {
|
||
font-size: 26rpx;
|
||
font-weight: 700;
|
||
color: #94A3B8;
|
||
}
|
||
}
|
||
|
||
.rules-list {
|
||
.rule-line {
|
||
display: flex;
|
||
align-items: flex-start;
|
||
margin-bottom: 12rpx;
|
||
|
||
&:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.dot {
|
||
font-size: 24rpx;
|
||
color: #64748B;
|
||
margin-right: 10rpx;
|
||
line-height: 1.4;
|
||
}
|
||
|
||
.text {
|
||
flex: 1;
|
||
font-size: 22rpx;
|
||
color: #64748B;
|
||
line-height: 1.5;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.bottom-spacer {
|
||
height: 180rpx;
|
||
}
|
||
}
|
||
|
||
// 底部固定支付操作栏
|
||
.fixed-submit-bar {
|
||
position: fixed;
|
||
bottom: 0;
|
||
left: 0;
|
||
right: 0;
|
||
z-index: 99;
|
||
background: rgba(10, 15, 29, 0.95);
|
||
backdrop-filter: blur(20px);
|
||
border-top: 1px solid rgba(255, 255, 255, 0.08);
|
||
padding: 20rpx 28rpx;
|
||
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
|
||
.submit-summary {
|
||
.summary-top {
|
||
display: flex;
|
||
align-items: baseline;
|
||
|
||
.summary-label {
|
||
font-size: 24rpx;
|
||
color: #94A3B8;
|
||
}
|
||
|
||
.summary-currency {
|
||
font-size: 30rpx;
|
||
font-weight: 700;
|
||
color: #10B981;
|
||
margin-left: 4rpx;
|
||
margin-right: 2rpx;
|
||
}
|
||
|
||
.summary-val {
|
||
font-size: 44rpx;
|
||
font-weight: 800;
|
||
color: #10B981;
|
||
font-family: -apple-system, BlinkMacSystemFont, sans-serif;
|
||
}
|
||
}
|
||
|
||
.summary-sub {
|
||
.sub-text {
|
||
font-size: 20rpx;
|
||
color: #F59E0B;
|
||
}
|
||
}
|
||
}
|
||
|
||
.btn-submit-recharge {
|
||
background: linear-gradient(135deg, #10B981 0%, #059669 100%);
|
||
color: #FFFFFF;
|
||
font-size: 28rpx;
|
||
font-weight: 700;
|
||
padding: 0 48rpx;
|
||
height: 84rpx;
|
||
line-height: 84rpx;
|
||
border-radius: 42rpx;
|
||
border: none;
|
||
box-shadow: 0 8rpx 24rpx rgba(16, 185, 129, 0.35);
|
||
|
||
&.disabled {
|
||
opacity: 0.45;
|
||
box-shadow: none;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 浅色暖阳晨曦模式适配
|
||
&.theme-warm {
|
||
background-color: #F8F6F0;
|
||
color: #1C1917;
|
||
|
||
.custom-nav-bar {
|
||
background: rgba(248, 246, 240, 0.92);
|
||
border-bottom-color: rgba(234, 88, 12, 0.1);
|
||
|
||
.nav-content {
|
||
.btn-nav-back {
|
||
background: #FFFFFF;
|
||
border-color: #E7E5E4;
|
||
}
|
||
|
||
.nav-title-wrap .nav-title {
|
||
color: #1C1917;
|
||
}
|
||
|
||
.nav-right-action {
|
||
background: rgba(234, 88, 12, 0.08);
|
||
border-color: rgba(234, 88, 12, 0.2);
|
||
|
||
.nav-rec-text {
|
||
color: #EA580C;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.page-scroll-body {
|
||
.balance-card {
|
||
background: linear-gradient(135deg, #FFF7ED 0%, #FFEDD5 100%);
|
||
border: 1px solid #FDBA74;
|
||
box-shadow: 0 16rpx 40rpx rgba(234, 88, 12, 0.08);
|
||
|
||
.card-bg-glow {
|
||
background: radial-gradient(circle, rgba(234, 88, 12, 0.2) 0%, rgba(234, 88, 12, 0) 70%);
|
||
}
|
||
|
||
.balance-inner {
|
||
.balance-title-row {
|
||
.title-left .balance-title {
|
||
color: #78716C;
|
||
}
|
||
|
||
.user-uid-pill {
|
||
background: #FFFFFF;
|
||
border-color: #FED7AA;
|
||
|
||
.uid-text {
|
||
color: #A8A29E;
|
||
}
|
||
}
|
||
}
|
||
|
||
.amount-number-row {
|
||
.currency-mark,
|
||
.amount-integer,
|
||
.amount-decimal {
|
||
color: #EA580C;
|
||
}
|
||
}
|
||
|
||
.balance-after-row {
|
||
background: rgba(255, 255, 255, 0.6);
|
||
color: #78716C;
|
||
|
||
.after-label {
|
||
color: #78716C;
|
||
}
|
||
|
||
.after-val {
|
||
color: #1C1917;
|
||
}
|
||
|
||
.after-bonus {
|
||
color: #D97706;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.content-card {
|
||
background: #FFFFFF;
|
||
border-color: #E7E5E4;
|
||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.03);
|
||
|
||
.card-section-head {
|
||
.head-left {
|
||
.section-title {
|
||
color: #1C1917;
|
||
}
|
||
|
||
.section-sub {
|
||
color: #A8A29E;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.tier-card {
|
||
.tier-grid .tier-grid-item {
|
||
background: #FAFAF9;
|
||
border-color: #E7E5E4;
|
||
|
||
.tier-amount-wrap {
|
||
.tier-curr,
|
||
.tier-val {
|
||
color: #1C1917;
|
||
}
|
||
}
|
||
|
||
.tier-gift-row .tier-gift-label {
|
||
color: #D97706;
|
||
|
||
&.empty {
|
||
color: #A8A29E;
|
||
}
|
||
}
|
||
|
||
&.active {
|
||
background: #FFF7ED;
|
||
border-color: #EA580C;
|
||
box-shadow: 0 0 20rpx rgba(234, 88, 12, 0.15);
|
||
|
||
.tier-amount-wrap .tier-curr,
|
||
.tier-amount-wrap .tier-val {
|
||
color: #EA580C;
|
||
}
|
||
}
|
||
}
|
||
|
||
.custom-amount-wrapper {
|
||
border-top-color: #E7E5E4;
|
||
|
||
.custom-title-row {
|
||
.custom-label {
|
||
color: #78716C;
|
||
}
|
||
|
||
.custom-rule-hint {
|
||
color: #A8A29E;
|
||
}
|
||
}
|
||
|
||
.custom-amount-box {
|
||
background: #FAFAF9;
|
||
border-color: #E7E5E4;
|
||
|
||
.custom-currency-symbol {
|
||
color: #EA580C;
|
||
}
|
||
|
||
.custom-amount-input {
|
||
color: #1C1917;
|
||
}
|
||
|
||
.custom-ph {
|
||
color: #A8A29E;
|
||
}
|
||
|
||
&.active,
|
||
&.is-focused {
|
||
background: #FFF7ED;
|
||
border-color: #EA580C;
|
||
}
|
||
}
|
||
|
||
.custom-tip-row .tip-normal {
|
||
color: #78716C;
|
||
|
||
.tip-bonus {
|
||
color: #D97706;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.channel-card {
|
||
.channel-list .channel-row {
|
||
background: #FAFAF9;
|
||
border-color: #E7E5E4;
|
||
|
||
.channel-info {
|
||
.channel-line-1 .channel-name {
|
||
color: #1C1917;
|
||
}
|
||
|
||
.channel-desc {
|
||
color: #78716C;
|
||
}
|
||
}
|
||
|
||
&.active {
|
||
background: #ECFDF5;
|
||
border-color: #10B981;
|
||
}
|
||
}
|
||
|
||
.channel-safe-banner {
|
||
background: #FAFAF9;
|
||
|
||
.safe-text {
|
||
color: #78716C;
|
||
}
|
||
}
|
||
}
|
||
|
||
.rules-card {
|
||
background: #FFFFFF;
|
||
border-color: #E7E5E4;
|
||
|
||
.rules-head .rules-title {
|
||
color: #78716C;
|
||
}
|
||
|
||
.rules-list .rule-line {
|
||
.dot,
|
||
.text {
|
||
color: #78716C;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.fixed-submit-bar {
|
||
background: rgba(255, 255, 255, 0.95);
|
||
border-top-color: #E7E5E4;
|
||
|
||
.submit-summary {
|
||
.summary-top {
|
||
.summary-label {
|
||
color: #78716C;
|
||
}
|
||
|
||
.summary-currency,
|
||
.summary-val {
|
||
color: #EA580C;
|
||
}
|
||
}
|
||
|
||
.summary-sub .sub-text {
|
||
color: #D97706;
|
||
}
|
||
}
|
||
|
||
.btn-submit-recharge {
|
||
background: linear-gradient(135deg, #EA580C 0%, #C2410C 100%);
|
||
box-shadow: 0 8rpx 24rpx rgba(234, 88, 12, 0.3);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</style>
|