foreign-admin-ui/src/views/capital/withdraw/components/WithdrawDialog.vue

933 lines
26 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<Dialog :visible="dialogVisible"
:title="currentStep === 1 ? t('withdraw.dialog.title1') : t('withdraw.dialog.title2')" width="600px"
:show-footer="false" @close="handleUpdateVisible">
<!-- 第一步输入金额并展示计算明细 -->
<div v-if="currentStep === 1" class="step1-container">
<!-- 钱包余额展示 -->
<div class="wallet-section">
<div class="section-label">{{ t('withdraw.dialog.walletBalance') }}</div>
<div class="wallet-grid">
<div v-for="(item, index) in walletItems" :key="index" class="wallet-item">
<span class="wallet-label">{{ item.label }}</span>
<span class="wallet-value" :class="{ available: item.field === 'available' }">{{ item.value }}</span>
</div>
</div>
</div>
<!-- 金额输入 -->
<div class="amount-section">
<div class="section-label">
{{ t('withdraw.dialog.amount') }}
<span class="max-balance">(最大可取:{{ totalWalletBalance }} {{ currentCurrency }}</span>
</div>
<el-input v-model="withdrawAmount" type="number" :placeholder="t('withdraw.dialog.amountPlaceholder')"
@input="handleAmountInput">
<template #prepend>{{ currentCurrency }}</template>
</el-input>
<div v-if="amountError" class="amount-error">{{ amountError }}</div>
</div>
<!-- 合计扣除 -->
<div v-if="totalDeducted && parseFloat(totalDeducted) > 0" class="total-section">
<div class="total-label">{{ t('withdraw.dialog.totalDeducted') }}</div>
<div class="total-value">-{{ totalDeducted }} {{ currentCurrency }}</div>
</div>
<!-- 扣除计算明细 - 用盒子展示 -->
<div v-if="withdrawAmount && calculatedData.length > 0" class="calculation-section">
<div class="section-label">{{ t('withdraw.dialog.deductionDetails') }}</div>
<div class="calculation-grid">
<div v-for="(item, index) in calculatedData" :key="index" class="calc-item">
<div class="calc-type">{{ item.type }}</div>
<div class="calc-values">
<div class="calc-original">
<span class="label">{{ t('withdraw.dialog.originalBalance') }}</span>
<span class="value">{{ item.original }}</span>
</div>
<div class="calc-deducted">
<span class="label">{{ t('withdraw.dialog.deductedAmount') }}</span>
<span class="value deducted">-{{ item.deducted }}</span>
</div>
<div class="calc-remaining">
<span class="label">{{ t('withdraw.dialog.remaining') }}</span>
<span class="value">{{ item.remaining }}</span>
</div>
</div>
</div>
</div>
<div class="calc-summary">
<span class="label">{{ t('withdraw.dialog.totalDeducted') }}</span>
<span class="total-value">{{ totalDeducted }}</span>
</div>
</div>
<!-- 快捷金额 -->
<div class="quick-amounts">
<el-button v-for="amount in quickAmounts" :key="amount" size="small" @click="handleQuickAmount(amount)">
{{ amount }}
</el-button>
</div>
<!-- 底部按钮 -->
<div class="dialog-footer">
<el-button @click="handleCancel">{{ t('common.cancel') }}</el-button>
<el-button type="primary" @click="handleNextStep">{{ t('withdraw.dialog.nextStep') }}</el-button>
</div>
</div>
<!-- 第二步:确认表单 -->
<div v-else class="step2-container">
<el-form ref="formRef" :model="formData" :rules="formRules" label-position="top">
<!-- 金额信息(只读) -->
<div class="amount-info">
<div class="info-row">
<span class="info-label">{{ t('withdraw.dialog.withdrawAmount') }}</span>
<span class="info-value">{{ withdrawAmount }} USD</span>
</div>
<div class="info-row" v-for="(item, index) in calculatedData" :key="index">
<span class="info-label">{{ item.typeLabel }}</span>
<span class="info-value">{{ item.deducted }} USD</span>
</div>
</div>
<!-- 银行提示 BANK 渠道显示 -->
<div v-if="isBankChannel" class="bank-tips">
<div class="tips-title">{{ t('withdraw.dialog.bankTipsTitle') }}</div>
<div class="tips-content">{{ t('withdraw.dialog.bankTipsContent') }}</div>
</div>
<!-- 钱包地址TRC/ERC 渠道) -->
<el-form-item v-if="isCryptoChannel" :label="t('withdraw.dialog.walletAddress')" prop="withdraw_address">
<el-input v-model="formData.withdraw_address" :placeholder="t('withdraw.dialog.walletAddressPlaceholder')" />
</el-form-item>
<!-- 银行信息BANK 渠道) -->
<template v-if="isBankChannel">
<el-form-item :label="t('withdraw.dialog.beneficiaryName')" prop="beneficiary_name">
<el-input v-model="formData.beneficiary_name"
:placeholder="t('withdraw.dialog.beneficiaryNamePlaceholder')" />
</el-form-item>
<el-form-item :label="t('withdraw.dialog.beneficiaryEnname')" prop="beneficiary_enname">
<el-input v-model="formData.beneficiary_enname"
:placeholder="t('withdraw.dialog.beneficiaryEnnamePlaceholder')" />
</el-form-item>
<el-form-item :label="t('withdraw.dialog.bankName')" prop="beneficiary_bank_name">
<el-input v-model="formData.beneficiary_bank_name"
:placeholder="t('withdraw.dialog.bankNamePlaceholder')" />
</el-form-item>
<el-form-item :label="t('withdraw.dialog.bankAccount')" prop="beneficiary_bank_account">
<el-input v-model="formData.beneficiary_bank_account"
:placeholder="t('withdraw.dialog.bankAccountPlaceholder')" />
</el-form-item>
</template>
</el-form>
<!-- 底部按钮 -->
<div class="dialog-footer">
<el-button @click="handleBack">{{ t('common.cancel') }}</el-button>
<el-button type="primary" :loading="submitLoading" @click="handleSubmit">{{ t('withdraw.dialog.confirmWithdraw')
}}</el-button>
</div>
</div>
</Dialog>
</template>
<script setup lang="ts">
import { ref, computed, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { ElMessage, type FormInstance, type FormRules } from 'element-plus'
import Dialog from '@/components/common/Dialog.vue'
import { getWalletCapital, getWithdrawChannel, getAgentWithdrawChannel, agentWithdraw, withdraw } from '@/api/modules/capital/withdraw'
import { getStorage } from '@/utils/storage'
const { t } = useI18n()
interface Props {
visible: boolean
channelId?: number
channelCode?: string
channelInfo?: {
id: number
symbol?: string
channel_code?: string
currency?: {
symbol: string
}
}
}
interface Emits {
(e: 'update:visible', value: boolean): void
(e: 'success'): void
}
interface WalletInfo {
user_id: string
amount: string
commission_point_diff: string
freeze: string
risk: string
service: string
toucun_percent: string
fee_handling_percent: string
commission_fee_handling: string
bail: string
bail_stop_order: string
bail_change_order: string
risk_control_id: string
fee_setting_id: string
closing_profit: string
}
interface ChannelItem {
id: number
name: string
}
interface CalculatedItem {
type: string
typeLabel: string
original: string
deducted: string
remaining: string
}
const props = defineProps<Props>()
const emit = defineEmits<Emits>()
const dialogVisible = ref(props.visible)
const currentStep = ref(1)
const withdrawAmount = ref('')
const submitLoading = ref(false)
const amountError = ref('')
// 处理金额输入
const handleAmountInput = (value: string) => {
const numValue = parseFloat(value)
if (isNaN(numValue)) {
amountError.value = ''
calculatedData.value = []
return
}
if (numValue > totalWalletBalance.value) {
amountError.value = `输入金额不能超过最大可取金额 ${totalWalletBalance.value.toFixed(2)}`
calculatedData.value = []
return
}
amountError.value = ''
calculateWithdraw()
}
// 用户信息
const userInfo: any = getStorage('userInfo')
const roleId = userInfo?.role_id || 6
// 角色判断
const isAgent = computed(() => roleId >= 5)
// 当前货币类型(从渠道信息获取)
const currentCurrency = computed(() => props.channelInfo?.currency?.symbol || '-')
// 计算可用余额 = amount - freeze - (手续费 + 点差 + 服务费 + 风险金 + 盈亏)
const availableBalance = computed(() => {
const amount = parseFloat(walletInfo.value.amount || '0')
const freeze = parseFloat(walletInfo.value.freeze || '0')
// 钱包余额总和
const walletSum =
Math.max(0, parseFloat(walletInfo.value.freeze)) +
Math.max(0, parseFloat(walletInfo.value.risk || '0')) +
Math.max(0, parseFloat(walletInfo.value.service || '0')) +
Math.max(0, parseFloat(walletInfo.value.commission_fee_handling || '0')) +
Math.max(0, parseFloat(walletInfo.value.commission_point_diff || '0'))
// Math.max(0, parseFloat(walletInfo.value.closing_profit || '0'))
return floorMoney(amount - walletSum)
})
// 计算钱包余额总和(用于验证输入金额上限)
// roleId >= 5 时totalWalletBalance 需要包含 availableBalance
const totalWalletBalance = computed(() => {
const amount = parseFloat(walletInfo.value.amount || '0')
const freeze = parseFloat(walletInfo.value.freeze || '0')
console.log('walletInfo.value:', amount, freeze);
// 钱包余额总和(手续费 + 点差 + 服务费 + 风险金 + 盈亏)
const walletSum =
parseFloat(walletInfo.value.commission_fee_handling || '0') +
parseFloat(walletInfo.value.commission_point_diff || '0') +
parseFloat(walletInfo.value.service || '0') +
parseFloat(walletInfo.value.risk || '0') +
parseFloat(Math.min(0, +walletInfo.value.closing_profit) + '')
if (roleId >= 5) {
// roleId >= 5 时,总余额包含可用余额
// availableBalance = amount - freeze - walletSum
// const availableBal = Math.max(0, amount - walletSum)
return floorMoney(amount - freeze)
}
return floorMoney(walletSum)
})
const floorMoney = (num: number) => {
const cents = Math.floor(num * 100);
return cents / 100;
}
// 费用项标签映射
const feeLabelMap: Record<string, string> = {
'手续费': '手续费佣金',
'点差': '点差佣金',
'服务费': '服务费',
'风险金': '风险金',
'盈亏': '盈亏',
'可用余额': '可用余额',
}
// 费用项对应的字段
const feeFieldMap: Record<string, keyof WalletInfo | 'available'> = {
'手续费': 'commission_fee_handling',
'点差': 'commission_point_diff',
'服务费': 'service',
'风险金': 'risk',
'盈亏': 'closing_profit',
'可用余额': 'available', // 特殊处理,用 computed 计算
}
// 费用项顺序
const feeOrder = computed(() => {
const orders: Record<number, string[]> = {
1: ['手续费', '点差', '服务费', '风险金', '盈亏'], // 平台
2: ['手续费', '点差', '服务费'], // 承包商
3: ['手续费', '点差', '服务费', '盈亏'], // 特殊做市商
4: ['手续费', '点差', '服务费', '盈亏'], // 普通做市商
5: ['手续费', '点差', '可用余额'], // 代理
6: ['手续费', '点差', '可用余额'], // 用户
}
return orders[roleId] ?? orders[6] ?? []
})
// 根据角色动态计算钱包项
const walletItems = computed(() => {
const items: { label: string; value: string; field: string }[] = []
for (const feeType of feeOrder.value) {
const field = feeFieldMap[feeType]
if (!field) continue
let value: string
if (field === 'available') {
value = availableBalance.value.toFixed(2)
} else {
value = walletInfo.value[field] || '0.00'
}
items.push({
label: feeLabelMap[feeType] || feeType,
value,
field,
})
}
return items
})
// 钱包信息
const walletInfo = ref<WalletInfo>({
user_id: '',
amount: '',
commission_point_diff: '0',
freeze: '0',
risk: '0',
service: '0',
toucun_percent: '0',
fee_handling_percent: '0',
commission_fee_handling: '0',
bail: '0',
bail_stop_order: '0',
bail_change_order: '0',
risk_control_id: '',
fee_setting_id: '',
closing_profit: '0',
})
// 渠道列表
const channelList = ref<ChannelItem[]>([])
// 计算后的扣除明细
const calculatedData = ref<CalculatedItem[]>([])
// 合计扣除
const totalDeducted = computed(() => {
return calculatedData.value.reduce((sum, item) => sum + parseFloat(item.deducted || '0'), 0).toFixed(2)
})
// 快捷金额
const quickAmounts = ['100', '500', '1000', '5000']
// 当前选中的渠道编码(优先从 props 获取,否则从 channelInfo 获取)
const currentChannelCode = computed(() => {
return props.channelCode || props.channelInfo?.channel_code || ''
})
// 是否为加密货币渠道TRC/ERC
const isCryptoChannel = computed(() => {
return ['TRC', 'ERC', "ADJUST"].includes(currentChannelCode.value)
})
// 是否为银行渠道BANK
const isBankChannel = computed(() => {
return currentChannelCode.value === 'BANK'
})
// 表单数据
const formRef = ref<FormInstance>()
const formData = ref({
channel_id: '',
withdraw_address: '',
// 代理取款字段
withdraw_fee_handle: '',
withdraw_point_diff: '',
withdraw_service_fee: '',
withdraw_head_fee: '',
withdraw_risk_fee: '',
withdraw_blance: '', // 可用余额使用量
// 用户取款额外字段
beneficiary_name: '',
beneficiary_enname: '',
beneficiary_bank_name: '',
swift_bic_code: '',
beneficiary_bank_address: '',
beneficiary_bank_account: '',
})
// 表单验证规则
const formRules: FormRules = {
withdraw_address: [{ required: true, message: '请输入钱包地址', trigger: 'blur' }],
beneficiary_name: [{ required: true, message: '请输入收款人姓名', trigger: 'blur' }],
beneficiary_enname: [{ required: true, message: '请输入收款人英文名字', trigger: 'blur' }],
beneficiary_bank_name: [{ required: true, message: '请输入银行名称', trigger: 'blur' }],
beneficiary_bank_account: [{ required: true, message: '请输入银行账号', trigger: 'blur' }],
}
// 监听 visible 变化
watch(() => props.visible, (val) => {
dialogVisible.value = val
if (val) {
initData()
}
})
// 初始化数据
const initData = async () => {
currentStep.value = 1
withdrawAmount.value = ''
calculatedData.value = []
// 获取钱包信息
try {
const res: any = await getWalletCapital()
if (res) {
walletInfo.value = {
commission_fee_handling: res.commission_fee_handling || '0',
commission_point_diff: '' + floorMoney(res.commission_point_diff - res.freeze || 0) || '0',
service: res.service || '0',
risk: res.risk || '0',
closing_profit: res.closing_profit || '0',
toucun_percent: res.toucun_percent || '0',
amount: res.amount || '0',
user_id: res.user_id || '',
freeze: res.freeze || '0',
bail: res.bail || '0',
bail_stop_order: res.bail_stop_order || '0',
bail_change_order: res.bail_change_order || '0',
risk_control_id: res.risk_control_id || '',
fee_setting_id: res.fee_setting_id || '',
fee_handling_percent: res.fee_handling_percent || '0',
}
}
} catch (error) {
console.error('获取钱包信息失败', error)
}
// 获取渠道列表
try {
const api = isAgent.value ? getWithdrawChannel : getAgentWithdrawChannel
const res: any = await api()
if (res && Array.isArray(res)) {
channelList.value = res.map((item: any) => ({
id: item.id,
name: item.name,
channel_code: item.channel_code || '',
}))
} else if (res?.data) {
channelList.value = res.data.map((item: any) => ({
id: item.id,
name: item.name,
channel_code: item.channel_code || '',
}))
}
// 如果有默认渠道,设置当前渠道编码
if (channelList.value.length > 0) {
currentChannelCode.value = channelList.value[0].channel_code || ''
}
} catch (error) {
console.error('获取渠道列表失败', error)
}
}
// 计算扣除明细
const calculateWithdraw = () => {
const amount = parseFloat(withdrawAmount.value) || 0
if (amount <= 0) {
calculatedData.value = []
return
}
const results: CalculatedItem[] = []
let remaining = amount
for (const feeType of feeOrder.value) {
const field = feeFieldMap[feeType]
if (!field) continue
// 获取原始值(特殊处理 available
let original: number
if (field === 'available') {
original = availableBalance.value
} else {
original = parseFloat(walletInfo.value[field] || '0')
}
if (original <= 0) continue
const deducted = Math.min(remaining, original).toFixed(2)
const newRemaining = Math.max(0, remaining - original)
results.push({
type: feeType,
typeLabel: feeLabelMap[feeType] || feeType,
original: original.toFixed(2),
deducted: deducted,
remaining: Math.max(0, original - parseFloat(deducted)).toFixed(2),
})
remaining = newRemaining
if (remaining <= 0) break
}
calculatedData.value = results
}
// 快捷金额
const handleQuickAmount = (amount: string) => {
withdrawAmount.value = amount
calculateWithdraw()
}
// 关闭弹窗
const handleUpdateVisible = (val: boolean) => {
emit('update:visible', val)
}
// 取消
const handleCancel = () => {
dialogVisible.value = false
emit('update:visible', false)
}
// 返回上一步
const handleBack = () => {
currentStep.value = 1
}
// 下一步
const handleNextStep = () => {
const amount = parseFloat(withdrawAmount.value)
if (!withdrawAmount.value || amount <= 0) {
ElMessage.warning('请输入取款金额')
return
}
if (amount > totalWalletBalance.value) {
ElMessage.warning(`输入金额不能超过最大可取金额 ${totalWalletBalance.value.toFixed(2)}`)
return
}
// 清空所有费用字段
formData.value.withdraw_fee_handle = '0'
formData.value.withdraw_point_diff = '0'
formData.value.withdraw_service_fee = '0'
formData.value.withdraw_risk_fee = '0'
formData.value.withdraw_head_fee = '0'
formData.value.withdraw_blance = '0'
// 根据当前角色的费用项顺序填充表单数据
for (const feeType of feeOrder.value) {
const deducted = calculatedData.value.find(item => item.type === feeType)?.deducted || '0'
switch (feeType) {
case '手续费':
formData.value.withdraw_fee_handle = deducted
break
case '点差':
formData.value.withdraw_point_diff = deducted
break
case '服务费':
formData.value.withdraw_service_fee = deducted
break
case '风险金':
formData.value.withdraw_risk_fee = deducted
break
case '盈亏':
formData.value.withdraw_head_fee = deducted
break
case '可用余额':
formData.value.withdraw_blance = deducted
break
}
}
currentStep.value = 2
}
// 提交
const handleSubmit = async () => {
try {
await formRef.value?.validate()
} catch {
return
}
submitLoading.value = true
try {
const params: any = {
channel_id: props.channelId,
amount: +withdrawAmount.value,
withdraw_address: formData.value.withdraw_address,
}
// 根据当前角色的费用项顺序添加对应的费用参数
for (const feeType of feeOrder.value) {
switch (feeType) {
case '手续费':
params.withdraw_fee_handle = formData.value.withdraw_fee_handle
break
case '点差':
params.withdraw_point_diff = formData.value.withdraw_point_diff
break
case '服务费':
params.withdraw_service_fee = formData.value.withdraw_service_fee
break
case '风险金':
params.withdraw_risk_fee = formData.value.withdraw_risk_fee
break
case '盈亏':
params.withdraw_head_fee = formData.value.withdraw_head_fee
break
case '可用余额':
params.withdraw_blance = formData.value.withdraw_blance
break
}
}
if (isAgent.value) {
// 用户取款 - 根据渠道类型处理字段
if (isCryptoChannel.value) {
// 加密货币渠道 - 只传钱包地址,其他字段默认 --
params.beneficiary_name = '--'
params.beneficiary_enname = '--'
params.beneficiary_bank_name = '--'
params.beneficiary_bank_account = '--'
} else if (isBankChannel.value) {
// 银行渠道 - 传银行相关字段
params.beneficiary_name = formData.value.beneficiary_name
params.beneficiary_enname = formData.value.beneficiary_enname
params.beneficiary_bank_name = formData.value.beneficiary_bank_name
params.beneficiary_bank_account = formData.value.beneficiary_bank_account
// 银行渠道不需要钱包地址
params.withdraw_address = '--'
}
// 统一默认 -- 的字段
params.swift_bic_code = '--'
params.beneficiary_bank_address = '--'
await withdraw(params)
} else {
// 代理取款 - 所有未展示字段默认传 --
if (isBankChannel.value) {
params.withdraw_address = '--'
params.beneficiary_name = formData.value.beneficiary_name
params.beneficiary_enname = formData.value.beneficiary_enname
params.beneficiary_bank_name = formData.value.beneficiary_bank_name
params.beneficiary_bank_account = formData.value.beneficiary_bank_account
} else {
params.beneficiary_name = '--'
params.beneficiary_enname = '--'
params.beneficiary_bank_name = '--'
params.beneficiary_bank_account = '--'
params.swift_bic_code = '--'
params.beneficiary_bank_address = '--'
}
await agentWithdraw(params)
}
ElMessage.success('取款申请已提交')
dialogVisible.value = false
emit('update:visible', false)
emit('success')
} catch (error) {
console.error('提交失败', error)
} finally {
submitLoading.value = false
}
}
</script>
<style scoped lang="scss">
.step1-container {
.section-label {
margin-bottom: 12px;
font-size: 14px;
font-weight: 500;
color: #303133;
}
}
.wallet-section {
margin-bottom: 20px;
padding: 16px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 8px;
color: #fff;
.section-label {
color: rgba(255, 255, 255, 0.9);
font-size: 13px;
}
.wallet-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 12px;
}
.wallet-item {
display: flex;
flex-direction: column;
padding: 12px;
background: rgba(255, 255, 255, 0.15);
border-radius: 6px;
.wallet-label {
margin-bottom: 6px;
font-size: 12px;
color: rgba(255, 255, 255, 0.8);
}
.wallet-value {
font-size: 18px;
font-weight: 700;
color: #fff;
}
}
}
.amount-section {
margin-bottom: 16px;
.section-label {
display: flex;
align-items: center;
margin-bottom: 12px;
font-size: 14px;
font-weight: 500;
color: #303133;
.max-balance {
margin-left: 8px;
font-size: 12px;
color: #909399;
font-weight: normal;
}
}
.amount-error {
margin-top: 8px;
font-size: 12px;
color: #f56c6c;
}
}
.total-section {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16px;
margin-bottom: 16px;
background: #fef0f0;
border-radius: 8px;
border: 1px solid #fde2e2;
.total-label {
font-size: 14px;
color: #606266;
}
.total-value {
font-size: 18px;
font-weight: 700;
color: #f56c6c;
}
}
.calculation-section {
margin-bottom: 24px;
.section-label {
margin-bottom: 12px;
font-size: 14px;
font-weight: 500;
color: #303133;
}
.calculation-grid {
display: flex;
flex-direction: column;
gap: 12px;
}
.calc-item {
padding: 16px;
background: #f5f7fa;
border-radius: 8px;
border: 1px solid #ebeef5;
}
.calc-type {
margin-bottom: 12px;
font-size: 14px;
font-weight: 600;
color: #303133;
}
.calc-values {
display: flex;
gap: 24px;
}
.calc-original,
.calc-deducted,
.calc-remaining {
display: flex;
flex-direction: column;
.label {
margin-bottom: 4px;
font-size: 12px;
color: #909399;
}
.value {
font-size: 16px;
font-weight: 600;
color: #303133;
&.deducted {
color: #f56c6c;
}
}
}
.calc-summary {
display: flex;
justify-content: flex-end;
align-items: center;
margin-top: 16px;
padding-top: 12px;
border-top: 1px solid #ebeef5;
.label {
font-size: 14px;
color: #606266;
}
.total-value {
margin-left: 8px;
font-size: 20px;
font-weight: 600;
color: #f56c6c;
}
}
}
.quick-amounts {
display: flex;
gap: 12px;
flex-wrap: wrap;
}
.dialog-footer {
display: flex;
justify-content: flex-end;
gap: 12px;
margin-top: 24px;
padding-top: 16px;
border-top: 1px solid #ebeef5;
}
.step2-container {
.amount-info {
margin-bottom: 24px;
padding: 16px;
background: #f5f7fa;
border-radius: 4px;
.info-row {
display: flex;
justify-content: space-between;
margin-bottom: 8px;
&:last-child {
margin-bottom: 0;
}
.info-label {
color: #606266;
}
.info-value {
font-weight: 500;
color: #303133;
}
}
}
.bank-tips {
margin-bottom: 20px;
padding: 12px 16px;
background: #fffbe6;
border: 1px solid #ffe58f;
border-radius: 4px;
.tips-title {
margin-bottom: 8px;
font-size: 14px;
font-weight: 500;
color: #d48806;
}
.tips-content {
font-size: 13px;
color: #8c8c8c;
line-height: 1.6;
}
}
}
</style>