Files
jurong_circle_frontdesk/src/views/AgentWithdrawals.vue
2025-08-11 09:40:54 +08:00

1204 lines
28 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>
<div class="agent-withdrawals">
<!-- 顶部导航 -->
<div class="page-header">
<button class="btn-back" @click="goBack">
<i class="icon-arrow-left"></i>
返回仪表盘
</button>
<h2>佣金提现</h2>
</div>
<!-- 顶部统计卡片 -->
<div class="stats-cards">
<div class="stat-card">
<div class="stat-icon">
<i class="icon-wallet"></i>
</div>
<div class="stat-content">
<div class="stat-value">¥{{ commissionStats.total_commission || '0.00' }}</div>
<div class="stat-label">总佣金</div>
</div>
</div>
<div class="stat-card">
<div class="stat-icon">
<i class="icon-money"></i>
</div>
<div class="stat-content">
<div class="stat-value">¥{{ commissionStats.available_amount || '0.00' }}</div>
<div class="stat-label">可提现金额</div>
</div>
</div>
<div class="stat-card">
<div class="stat-icon">
<i class="icon-pending"></i>
</div>
<div class="stat-content">
<div class="stat-value">¥{{ commissionStats.pending_withdrawal || '0.00' }}</div>
<div class="stat-label">提现中</div>
</div>
</div>
<div class="stat-card">
<div class="stat-icon">
<i class="icon-success"></i>
</div>
<div class="stat-content">
<div class="stat-value">¥{{ commissionStats.withdrawn_amount || '0.00' }}</div>
<div class="stat-label">已提现</div>
</div>
</div>
</div>
<!-- 收款方式设置 -->
<div class="payment-info-section">
<div class="section-header">
<h3>收款方式</h3>
<button class="btn-edit" @click="showPaymentForm = !showPaymentForm">
{{ showPaymentForm ? '取消' : '编辑' }}
</button>
</div>
<div v-if="!showPaymentForm" class="payment-info-display">
<div class="info-item">
<span class="label">收款方式</span>
<span class="value">{{ getPaymentTypeText(paymentInfo.payment_type) || '未设置' }}</span>
</div>
<div class="info-item" v-if="paymentInfo.payment_type === 'bank'">
<span class="label">银行名称</span>
<span class="value">{{ paymentInfo.bank_name || '未设置' }}</span>
</div>
<div class="info-item">
<span class="label">{{ getAccountLabel(paymentInfo.payment_type) }}</span>
<span class="value">{{ maskAccount(paymentInfo.account_number) || '未设置' }}</span>
</div>
<div class="info-item">
<span class="label">{{ getHolderLabel(paymentInfo.payment_type) }}</span>
<span class="value">{{ paymentInfo.account_holder || '未设置' }}</span>
</div>
<div v-if="paymentInfo.payment_type !== 'bank' && paymentInfo.qr_code_url" class="info-item qr-code-preview">
<span class="label">收款码</span>
<div class="qr-code-image">
<img :src="paymentInfo.qr_code_url" alt="收款码" />
</div>
</div>
</div>
<form v-if="showPaymentForm" @submit.prevent="updatePaymentInfo" class="payment-form">
<div class="form-group">
<label>收款方式</label>
<select v-model="paymentForm.payment_type" @change="onPaymentTypeChange" required>
<option value="">请选择收款方式</option>
<option value="bank">银行卡</option>
<option value="wechat">微信收款码</option>
<option value="alipay">支付宝收款码</option>
<option value="unionpay">云闪付收款码</option>
</select>
</div>
<div v-if="paymentForm.payment_type === 'bank'" class="form-group">
<label>银行名称</label>
<input
v-model="paymentForm.bank_name"
type="text"
placeholder="请输入银行名称"
required
>
</div>
<div class="form-group">
<label>{{ getAccountLabel(paymentForm.payment_type) }}</label>
<input
v-model="paymentForm.account_number"
type="text"
:placeholder="getAccountPlaceholder(paymentForm.payment_type)"
required
>
</div>
<div class="form-group">
<label>{{ getHolderLabel(paymentForm.payment_type) }}</label>
<input
v-model="paymentForm.account_holder"
type="text"
:placeholder="getHolderPlaceholder(paymentForm.payment_type)"
required
>
</div>
<div v-if="paymentForm.payment_type && paymentForm.payment_type !== 'bank'" class="form-group">
<label>收款码图片</label>
<div class="qr-code-upload">
<input
type="file"
ref="qrCodeInput"
accept="image/*"
@change="handleQrCodeUpload"
style="display: none;"
>
<div
class="upload-area"
:class="{ 'has-image': paymentForm.qr_code_url }"
@click="$refs.qrCodeInput.click()"
>
<div v-if="!paymentForm.qr_code_url" class="upload-placeholder">
<div class="upload-icon">📷</div>
<div class="upload-text">点击上传收款码</div>
<div class="upload-hint">支持 JPGPNG 格式</div>
</div>
<div v-else class="uploaded-image">
<img :src="paymentForm.qr_code_url" alt="收款码" />
<div class="image-overlay">
<span>点击重新上传</span>
</div>
</div>
</div>
<div v-if="uploadingQrCode" class="upload-progress">
上传中...
</div>
</div>
</div>
<div class="form-actions">
<button type="submit" class="btn-primary" :disabled="updating">保存</button>
<button type="button" class="btn-secondary" @click="showPaymentForm = false">取消</button>
</div>
</form>
</div>
<!-- 提现申请 -->
<div class="withdrawal-section">
<div class="section-header">
<h3>申请提现</h3>
</div>
<form @submit.prevent="submitWithdrawal" class="withdrawal-form">
<div class="form-group">
<label>提现金额</label>
<div class="amount-input">
<input
v-model="withdrawalForm.amount"
type="number"
step="0.01"
min="1"
:max="commissionStats.available_amount"
placeholder="请输入提现金额"
required
>
<span class="currency"></span>
</div>
<div class="amount-tips">
可提现金额¥{{ commissionStats.available_amount || '0.00' }}
</div>
</div>
<div class="form-actions">
<button
type="submit"
class="btn-primary"
:disabled="submitting || !canWithdraw"
>
{{ submitting ? '提交中...' : '申请提现' }}
</button>
</div>
</form>
</div>
<!-- 提现记录 -->
<div class="records-section">
<div class="section-header">
<h3>提现记录</h3>
<div class="filter-controls">
<select v-model="recordsFilter" @change="loadWithdrawalRecords">
<option value="">全部状态</option>
<option value="pending">待审核</option>
<option value="approved">已通过</option>
<option value="completed">已完成</option>
<option value="rejected">已拒绝</option>
</select>
</div>
</div>
<div class="records-list">
<div v-if="loading" class="loading">加载中...</div>
<div v-else-if="withdrawalRecords.length === 0" class="empty">
暂无提现记录
</div>
<div v-else>
<div
v-for="record in withdrawalRecords"
:key="record.id"
class="record-item"
>
<div class="record-header">
<span class="amount">¥{{ record.amount }}</span>
<span class="status" :class="`status-${record.status}`">
{{ getStatusText(record.status) }}
</span>
</div>
<div class="record-details">
<div class="detail-item">
<span class="label">申请时间</span>
<span class="value">{{ formatDate(record.created_at) }}</span>
</div>
<div class="detail-item">
<span class="label">收款信息</span>
<span class="value">
{{ getPaymentTypeText(record.payment_type || 'bank') }}
<template v-if="record.payment_type === 'bank' || !record.payment_type">
- {{ record.bank_name }} {{ maskAccount(record.account_number || record.bank_account) }}
</template>
<template v-else>
- {{ record.account_holder }} ({{ maskAccount(record.account_number) }})
</template>
</span>
</div>
<div v-if="record.admin_note" class="detail-item">
<span class="label">备注</span>
<span class="value">{{ record.admin_note }}</span>
</div>
<div v-if="record.completed_at" class="detail-item">
<span class="label">完成时间</span>
<span class="value">{{ formatDate(record.completed_at) }}</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { ref, reactive, computed, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { useUserStore } from '@/stores/user'
import api from '@/utils/api'
export default {
name: 'AgentWithdrawals',
setup() {
const router = useRouter()
const userStore = useUserStore()
// 响应式数据
const loading = ref(false)
const updating = ref(false)
const submitting = ref(false)
const showPaymentForm = ref(false)
const recordsFilter = ref('')
const commissionStats = reactive({
total_commission: '0.00',
available_amount: '0.00',
pending_withdrawal: '0.00',
withdrawn_amount: '0.00'
})
const paymentInfo = reactive({
payment_type: '',
bank_name: '',
account_number: '',
account_holder: '',
qr_code_url: ''
})
const paymentForm = reactive({
payment_type: '',
bank_name: '',
account_number: '',
account_holder: '',
qr_code_url: ''
})
const withdrawalForm = reactive({
amount: ''
})
const withdrawalRecords = ref([])
const uploadingQrCode = ref(false)
// 计算属性
const canWithdraw = computed(() => {
const amount = parseFloat(withdrawalForm.amount)
const available = parseFloat(commissionStats.available_amount)
const hasBasicInfo = amount > 0 && amount <= available && paymentInfo.account_number && paymentInfo.payment_type
// 银行卡只需要基本信息
if (paymentInfo.payment_type === 'bank') {
return hasBasicInfo
}
// 收款码需要额外验证图片
return hasBasicInfo && paymentInfo.qr_code_url
})
// 方法
/**
* 加载佣金统计数据
*/
const loadCommissionStats = async () => {
try {
const response = await api.get('/agent-withdrawals/stats')
if (response.data.success) {
// 更新佣金统计数据
Object.assign(commissionStats, {
total_commission: response.data.data.total_commission || '0.00',
available_amount: response.data.data.available_amount || '0.00',
pending_withdrawal: response.data.data.pending_withdrawal || '0.00',
withdrawn_amount: response.data.data.withdrawn_amount || '0.00'
})
// 处理收款方式信息
if (response.data.data.paymentInfo) {
Object.assign(paymentInfo, response.data.data.paymentInfo)
Object.assign(paymentForm, response.data.data.paymentInfo)
} else if (response.data.data.bank_account) {
// 兼容旧的银行信息字段
const bankInfo = {
payment_type: 'bank',
bank_name: response.data.data.bank_name || '',
account_number: response.data.data.bank_account || '',
account_holder: response.data.data.account_holder || '',
qr_code_url: ''
}
Object.assign(paymentInfo, bankInfo)
Object.assign(paymentForm, bankInfo)
}
}
} catch (error) {
console.error('加载佣金统计失败:', error)
}
}
/**
* 更新收款方式信息
*/
const updatePaymentInfo = async () => {
if (updating.value) return
updating.value = true
try {
const response = await api.put('/agent-withdrawals/payment-info', paymentForm)
if (response.data.success) {
Object.assign(paymentInfo, paymentForm)
showPaymentForm.value = false
alert('收款方式更新成功')
} else {
alert(response.data.message || '更新失败')
}
} catch (error) {
console.error('更新收款方式失败:', error)
alert('更新失败,请重试')
} finally {
updating.value = false
}
}
/**
* 提交提现申请
*/
const submitWithdrawal = async () => {
if (submitting.value || !canWithdraw.value) return
if (!paymentInfo.account_number || !paymentInfo.payment_type) {
alert('请先设置收款方式')
return
}
// 收款码类型需要验证图片
if (paymentInfo.payment_type !== 'bank' && !paymentInfo.qr_code_url) {
alert('请上传收款码图片')
return
}
submitting.value = true
try {
const response = await api.post('/agent-withdrawals/apply', {
amount: parseFloat(withdrawalForm.amount)
})
if (response.data.success) {
alert('提现申请提交成功,请等待审核')
withdrawalForm.amount = ''
await loadCommissionStats()
await loadWithdrawalRecords()
} else {
alert(response.data.message || '申请失败')
}
} catch (error) {
console.error('提现申请失败:', error)
alert('申请失败,请重试')
} finally {
submitting.value = false
}
}
/**
* 加载提现记录
*/
const loadWithdrawalRecords = async () => {
loading.value = true
try {
const params = {}
if (recordsFilter.value) {
params.status = recordsFilter.value
}
const response = await api.get('/agent-withdrawals/records', { params })
if (response.data.success) {
withdrawalRecords.value = response.data.data.records || []
}
} catch (error) {
console.error('加载提现记录失败:', error)
} finally {
loading.value = false
}
}
/**
* 格式化日期
*/
const formatDate = (dateString) => {
if (!dateString) return ''
const date = new Date(dateString)
return date.toLocaleString('zh-CN')
}
/**
* 获取状态文本
*/
const getStatusText = (status) => {
const statusMap = {
pending: '待审核',
approved: '已通过',
completed: '已完成',
rejected: '已拒绝'
}
return statusMap[status] || status
}
/**
* 掩码显示账号信息
*/
const maskAccount = (account) => {
if (!account) return ''
if (account.length <= 8) return account
return account.slice(0, 4) + '****' + account.slice(-4)
}
/**
* 处理收款码图片上传
*/
const handleQrCodeUpload = async (event) => {
const file = event.target.files[0]
if (!file) return
// 验证文件类型
if (!file.type.startsWith('image/')) {
alert('请选择图片文件')
return
}
// 验证文件大小限制为5MB
if (file.size > 5 * 1024 * 1024) {
alert('图片大小不能超过5MB')
return
}
uploadingQrCode.value = true
try {
const formData = new FormData()
formData.append('qrCode', file)
const response = await api.post('/agent-withdrawals/upload-qr-code', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
if (response.data.success) {
paymentForm.qr_code_url = response.data.data.url
} else {
alert(response.data.message || '上传失败')
}
} catch (error) {
console.error('上传收款码失败:', error)
alert('上传失败,请重试')
} finally {
uploadingQrCode.value = false
}
}
/**
* 获取收款方式显示文本
*/
const getPaymentTypeText = (type) => {
const types = {
'bank': '银行卡',
'wechat': '微信收款码',
'alipay': '支付宝收款码',
'unionpay': '云闪付收款码'
}
return types[type] || ''
}
/**
* 获取账号标签
*/
const getAccountLabel = (type) => {
const labels = {
'bank': '银行账号',
'wechat': '微信号',
'alipay': '支付宝账号',
'unionpay': '云闪付账号'
}
return labels[type] || '账号'
}
/**
* 获取持有人标签
*/
const getHolderLabel = (type) => {
const labels = {
'bank': '开户人',
'wechat': '微信昵称',
'alipay': '支付宝昵称',
'unionpay': '云闪付昵称'
}
return labels[type] || '持有人'
}
/**
* 获取账号输入占位符
*/
const getAccountPlaceholder = (type) => {
const placeholders = {
'bank': '请输入银行账号',
'wechat': '请输入微信号',
'alipay': '请输入支付宝账号',
'unionpay': '请输入云闪付账号'
}
return placeholders[type] || '请输入账号'
}
/**
* 获取持有人输入占位符
*/
const getHolderPlaceholder = (type) => {
const placeholders = {
'bank': '请输入开户人姓名',
'wechat': '请输入微信昵称',
'alipay': '请输入支付宝昵称',
'unionpay': '请输入云闪付昵称'
}
return placeholders[type] || '请输入持有人姓名'
}
/**
* 收款方式类型改变时的处理
*/
const onPaymentTypeChange = () => {
// 清空非通用字段
if (paymentForm.payment_type !== 'bank') {
paymentForm.bank_name = ''
} else {
paymentForm.qr_code_url = ''
}
}
// 监听收款方式信息变化
const initPaymentForm = () => {
Object.assign(paymentForm, paymentInfo)
}
/**
* 返回代理仪表盘
*/
const goBack = () => {
router.push('/agent/dashboard')
}
// 生命周期
onMounted(async () => {
await loadCommissionStats()
await loadWithdrawalRecords()
initPaymentForm()
})
return {
loading,
updating,
submitting,
showPaymentForm,
recordsFilter,
commissionStats,
paymentInfo,
paymentForm,
withdrawalForm,
withdrawalRecords,
canWithdraw,
loadCommissionStats,
updatePaymentInfo,
submitWithdrawal,
loadWithdrawalRecords,
formatDate,
getStatusText,
maskAccount,
handleQrCodeUpload,
uploadingQrCode,
getPaymentTypeText,
getAccountLabel,
getHolderLabel,
getAccountPlaceholder,
getHolderPlaceholder,
onPaymentTypeChange,
initPaymentForm,
goBack
}
}
}
</script>
<style scoped>
.agent-withdrawals {
padding: 20px;
max-width: 1200px;
margin: 0 auto;
}
/* 页面头部 */
.page-header {
display: flex;
align-items: center;
gap: 16px;
margin-bottom: 24px;
padding-bottom: 16px;
border-bottom: 1px solid #eee;
}
.page-header h2 {
margin: 0;
font-size: 24px;
color: #333;
font-weight: 600;
}
/* 返回按钮 */
.btn-back {
display: flex;
align-items: center;
gap: 8px;
padding: 10px 16px;
background: #f8f9fa;
border: 1px solid #dee2e6;
border-radius: 8px;
color: #495057;
font-size: 14px;
cursor: pointer;
transition: all 0.3s ease;
}
.btn-back:hover {
background: #e9ecef;
border-color: #adb5bd;
color: #212529;
}
.btn-back .icon-arrow-left::before {
content: '←';
font-size: 16px;
}
/* 统计卡片 */
.stats-cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
margin-bottom: 30px;
}
.stat-card {
background: white;
border-radius: 12px;
padding: 24px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
display: flex;
align-items: center;
gap: 16px;
}
.stat-icon {
width: 48px;
height: 48px;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
color: white;
}
.stat-card:nth-child(1) .stat-icon {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.stat-card:nth-child(2) .stat-icon {
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
}
.stat-card:nth-child(3) .stat-icon {
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
}
.stat-card:nth-child(4) .stat-icon {
background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);
}
.stat-content {
flex: 1;
}
.stat-value {
font-size: 24px;
font-weight: bold;
color: #333;
margin-bottom: 4px;
}
.stat-label {
font-size: 14px;
color: #666;
}
/* 通用区块样式 */
.payment-info-section,
.withdrawal-section,
.records-section {
background: white;
border-radius: 12px;
padding: 24px;
margin-bottom: 20px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
padding-bottom: 12px;
border-bottom: 1px solid #eee;
}
.section-header h3 {
margin: 0;
font-size: 18px;
color: #333;
}
/* 收款方式信息显示 */
.payment-info-display {
display: grid;
gap: 12px;
}
.info-item {
display: flex;
align-items: center;
}
.info-item .label {
width: 100px;
color: #666;
font-size: 14px;
}
.info-item .value {
color: #333;
font-size: 14px;
}
/* 收款码预览 */
.qr-code-preview {
grid-template-columns: auto 1fr;
align-items: flex-start;
}
.qr-code-image {
max-width: 150px;
border: 1px solid #ddd;
border-radius: 8px;
overflow: hidden;
}
.qr-code-image img {
width: 100%;
height: auto;
display: block;
}
/* 表单样式 */
.payment-form,
.withdrawal-form {
display: grid;
gap: 20px;
}
/* 收款方式选择器 */
.payment-type-selector {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
gap: 12px;
margin-bottom: 16px;
}
.payment-type-option {
padding: 12px 16px;
border: 2px solid #e9ecef;
border-radius: 8px;
background: white;
cursor: pointer;
text-align: center;
transition: all 0.3s ease;
font-weight: 500;
}
.payment-type-option:hover {
border-color: #007bff;
background: #f8f9fa;
}
.payment-type-option.active {
border-color: #007bff;
background: #007bff;
color: white;
}
.payment-type-option.active:hover {
background: #0056b3;
}
/* 收款码上传 */
.qr-code-upload {
display: grid;
gap: 12px;
}
.upload-area {
border: 2px dashed #ddd;
border-radius: 8px;
padding: 20px;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
min-height: 120px;
display: flex;
align-items: center;
justify-content: center;
}
.upload-area:hover {
border-color: #007bff;
background: #f8f9fa;
}
.upload-area.has-image {
padding: 0;
border: 1px solid #ddd;
position: relative;
overflow: hidden;
}
.upload-placeholder {
display: grid;
gap: 8px;
color: #666;
}
.upload-icon {
font-size: 32px;
}
.upload-text {
font-size: 14px;
font-weight: 500;
}
.upload-hint {
font-size: 12px;
color: #999;
}
.uploaded-image {
position: relative;
width: 100%;
height: 200px;
}
.uploaded-image img {
width: 100%;
height: 100%;
object-fit: contain;
border-radius: 8px;
}
.image-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.7);
color: white;
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity 0.3s ease;
border-radius: 8px;
}
.uploaded-image:hover .image-overlay {
opacity: 1;
}
.upload-progress {
text-align: center;
color: #007bff;
font-size: 14px;
}
.form-group {
display: grid;
gap: 8px;
}
.form-group label {
font-size: 14px;
color: #333;
font-weight: 500;
}
.form-group input,
.form-group select {
padding: 12px;
border: 1px solid #ddd;
border-radius: 8px;
font-size: 14px;
transition: border-color 0.3s;
}
.form-group input:focus,
.form-group select:focus {
outline: none;
border-color: #007bff;
}
.amount-input {
position: relative;
display: flex;
align-items: center;
}
.amount-input input {
flex: 1;
padding-right: 40px;
}
.currency {
position: absolute;
right: 12px;
color: #666;
font-size: 14px;
}
.amount-tips {
font-size: 12px;
color: #666;
}
.form-actions {
display: flex;
gap: 12px;
}
/* 按钮样式 */
.btn-primary,
.btn-secondary,
.btn-edit {
padding: 10px 20px;
border: none;
border-radius: 8px;
font-size: 14px;
cursor: pointer;
transition: all 0.3s;
}
.btn-primary {
background: #007bff;
color: white;
}
.btn-primary:hover:not(:disabled) {
background: #0056b3;
}
.btn-primary:disabled {
background: #ccc;
cursor: not-allowed;
}
.btn-secondary {
background: #6c757d;
color: white;
}
.btn-secondary:hover {
background: #545b62;
}
.btn-edit {
background: #28a745;
color: white;
padding: 8px 16px;
font-size: 12px;
}
.btn-edit:hover {
background: #1e7e34;
}
/* 筛选控件 */
.filter-controls select {
padding: 8px 12px;
border: 1px solid #ddd;
border-radius: 6px;
font-size: 14px;
}
/* 记录列表 */
.records-list {
display: grid;
gap: 16px;
}
.loading,
.empty {
text-align: center;
padding: 40px;
color: #666;
font-size: 14px;
}
.record-item {
border: 1px solid #eee;
border-radius: 8px;
padding: 16px;
transition: box-shadow 0.3s;
}
.record-item:hover {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.record-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 12px;
}
.record-header .amount {
font-size: 18px;
font-weight: bold;
color: #333;
}
.status {
padding: 4px 12px;
border-radius: 20px;
font-size: 12px;
font-weight: 500;
}
.status-pending {
background: #fff3cd;
color: #856404;
}
.status-approved {
background: #d1ecf1;
color: #0c5460;
}
.status-completed {
background: #d4edda;
color: #155724;
}
.status-rejected {
background: #f8d7da;
color: #721c24;
}
.record-details {
display: grid;
gap: 8px;
}
.detail-item {
display: flex;
font-size: 14px;
}
.detail-item .label {
width: 80px;
color: #666;
flex-shrink: 0;
}
.detail-item .value {
color: #333;
flex: 1;
}
/* 图标 */
.icon-wallet::before { content: '💰'; }
.icon-money::before { content: '💵'; }
.icon-pending::before { content: '⏳'; }
.icon-success::before { content: '✅'; }
/* 响应式设计 */
@media (max-width: 768px) {
.agent-withdrawals {
padding: 16px;
}
.stats-cards {
grid-template-columns: 1fr;
gap: 16px;
}
.stat-card {
padding: 20px;
}
.section-header {
flex-direction: column;
align-items: flex-start;
gap: 12px;
}
.form-actions {
flex-direction: column;
}
.record-header {
flex-direction: column;
align-items: flex-start;
gap: 8px;
}
}
</style>