diff --git a/src/views/AgentWithdrawals.vue b/src/views/AgentWithdrawals.vue index dc39e37..85dd7c5 100644 --- a/src/views/AgentWithdrawals.vue +++ b/src/views/AgentWithdrawals.vue @@ -6,7 +6,7 @@ 返回仪表盘 -

佣金提现

+

佣金提现

@@ -49,122 +49,6 @@ - -
-
-

收款方式

- -
- -
-
- 收款方式: - {{ getPaymentTypeText(paymentInfo.payment_type) || '未设置' }} -
-
- 银行名称: - {{ paymentInfo.bank_name || '未设置' }} -
-
- {{ getAccountLabel(paymentInfo.payment_type) }}: - {{ maskAccount(paymentInfo.account_number) || '未设置' }} -
-
- {{ getHolderLabel(paymentInfo.payment_type) }}: - {{ paymentInfo.account_holder || '未设置' }} -
-
- 收款码: -
- 收款码 -
-
-
- -
-
- - -
- -
- - -
- -
- - -
- -
- - -
- -
- -
- -
-
-
📷
-
点击上传收款码
-
支持 JPG、PNG 格式
-
-
- 收款码 -
- 点击重新上传 -
-
-
-
- 上传中... -
-
-
- -
- - -
-
-
-
@@ -186,8 +70,13 @@ >
-
- 可提现金额:¥{{ commissionStats.available_amount || '0.00' }} +
+ + 可提现金额:¥{{ commissionStats.available_amount || '0.00' }} + +
@@ -264,6 +153,111 @@
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ 点击更换图片 +
+
+
+ +
点击上传收款码
+
支持 JPG、PNG 格式,大小不超过5MB
+
+
+
+ + 上传中... +
+
+
+ + +
@@ -271,20 +265,28 @@ import { ref, reactive, computed, onMounted } from 'vue' import { useRouter } from 'vue-router' import { useUserStore } from '@/stores/user' +import { ElMessage, ElMessageBox } from 'element-plus' +import { Plus } from '@element-plus/icons-vue' import api from '@/utils/api' export default { name: 'AgentWithdrawals', + components: { + Plus + }, setup() { const router = useRouter() const userStore = useUserStore() + const paymentFormRef = ref(null) // 响应式数据 const loading = ref(false) const updating = ref(false) const submitting = ref(false) - const showPaymentForm = ref(false) + const paymentDialogVisible = ref(false) const recordsFilter = ref('') + const uploadingQrCode = ref(false) + const uploadProgress = ref(0) const commissionStats = reactive({ total_commission: '0.00', @@ -294,12 +296,12 @@ export default { }) const paymentInfo = reactive({ - payment_type: '', - bank_name: '', - account_number: '', - account_holder: '', - qr_code_url: '' - }) + payment_type: '', + bank_name: '', + account_number: '', + account_holder: '', + qr_code_url: '' + }) const paymentForm = reactive({ payment_type: '', @@ -314,7 +316,25 @@ export default { }) const withdrawalRecords = ref([]) - const uploadingQrCode = ref(false) + + // 表单验证规则 + const paymentFormRules = reactive({ + payment_type: [ + { required: true, message: '请选择收款方式', trigger: 'change' } + ], + bank_name: [ + { required: true, message: '请输入银行名称', trigger: 'blur' } + ], + account_number: [ + { required: true, message: '请输入账号', trigger: 'blur' } + ], + account_holder: [ + { required: true, message: '请输入持有人姓名', trigger: 'blur' } + ], + qr_code_url: [ + { required: true, message: '请上传收款码图片', trigger: 'change' } + ] + }) // 计算属性 const canWithdraw = computed(() => { @@ -366,30 +386,61 @@ export default { } } catch (error) { console.error('加载佣金统计失败:', error) + ElMessage.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 || '更新失败') + const openPaymentDialog = () => { + // 重置表单为当前信息 + Object.assign(paymentForm, paymentInfo) + paymentDialogVisible.value = true + } + + /** + * 提交收款方式表单 + */ + const submitPaymentForm = () => { + paymentFormRef.value.validate(async (valid) => { + if (!valid) return + + 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) + paymentDialogVisible.value = false + ElMessage.success('收款方式更新成功') + } else { + ElMessage.error(response.data.message || '更新失败') + } + } catch (error) { + console.error('更新收款方式失败:', error) + ElMessage.error('更新失败,请重试') + } finally { + updating.value = false } - } catch (error) { - console.error('更新收款方式失败:', error) - alert('更新失败,请重试') - } finally { - updating.value = false + }) + } + + /** + * 处理对话框关闭 + */ + const handleDialogClose = (done) => { + if (JSON.stringify(paymentForm) !== JSON.stringify(paymentInfo)) { + ElMessageBox.confirm('您有未保存的更改,确定要关闭吗?', '提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning' + }).then(() => { + done() + }).catch(() => {}) + } else { + done() } } @@ -400,15 +451,15 @@ export default { if (submitting.value || !canWithdraw.value) return if (!paymentInfo.account_number || !paymentInfo.payment_type) { - alert('请先设置收款方式') - return - } + ElMessage.warning('请先设置收款方式') + return + } - // 收款码类型需要验证图片 - if (paymentInfo.payment_type !== 'bank' && !paymentInfo.qr_code_url) { - alert('请上传收款码图片') - return - } + // 收款码类型需要验证图片 + if (paymentInfo.payment_type !== 'bank' && !paymentInfo.qr_code_url) { + ElMessage.warning('请上传收款码图片') + return + } submitting.value = true try { @@ -417,16 +468,16 @@ export default { }) if (response.data.success) { - alert('提现申请提交成功,请等待审核') + ElMessage.success('提现申请提交成功,请等待审核') withdrawalForm.amount = '' await loadCommissionStats() await loadWithdrawalRecords() } else { - alert(response.data.message || '申请失败') + ElMessage.error(response.data.message || '申请失败') } } catch (error) { console.error('提现申请失败:', error) - alert('申请失败,请重试') + ElMessage.error('申请失败,请重试') } finally { submitting.value = false } @@ -449,6 +500,7 @@ export default { } } catch (error) { console.error('加载提现记录失败:', error) + ElMessage.error('加载提现记录失败') } finally { loading.value = false } @@ -488,49 +540,52 @@ export default { /** * 处理收款码图片上传 */ - const handleQrCodeUpload = async (event) => { - const file = event.target.files[0] - if (!file) return - + const handleQrCodeUpload = async (file) => { // 验证文件类型 - if (!file.type.startsWith('image/')) { - alert('请选择图片文件') - return + if (!file.raw.type.startsWith('image/')) { + ElMessage.error('请选择图片文件') + return false } // 验证文件大小(限制为5MB) - if (file.size > 5 * 1024 * 1024) { - alert('图片大小不能超过5MB') - return + if (file.raw.size > 5 * 1024 * 1024) { + ElMessage.error('图片大小不能超过5MB') + return false } uploadingQrCode.value = true + uploadProgress.value = 0 try { const formData = new FormData() - formData.append('qrCode', file) + formData.append('qrCode', file.raw) const response = await api.post('/agent-withdrawals/upload-qr-code', formData, { headers: { 'Content-Type': 'multipart/form-data' + }, + onUploadProgress: (progressEvent) => { + if (progressEvent.total) { + uploadProgress.value = Math.round((progressEvent.loaded * 100) / progressEvent.total) + } } }) if (response.data.success) { paymentForm.qr_code_url = response.data.data.url + ElMessage.success('上传成功') } else { - alert(response.data.message || '上传失败') + ElMessage.error(response.data.message || '上传失败') } } catch (error) { console.error('上传收款码失败:', error) - alert('上传失败,请重试') + ElMessage.error('上传失败,请重试') } finally { uploadingQrCode.value = false + uploadProgress.value = 0 } } - - /** * 获取收款方式显示文本 */ @@ -606,11 +661,11 @@ export default { } else { paymentForm.qr_code_url = '' } - } - - // 监听收款方式信息变化 - const initPaymentForm = () => { - Object.assign(paymentForm, paymentInfo) + + // 重置验证状态 + nextTick(() => { + paymentFormRef.value.clearValidate(['bank_name', 'qr_code_url']) + }) } /** @@ -624,38 +679,52 @@ export default { onMounted(async () => { await loadCommissionStats() await loadWithdrawalRecords() - initPaymentForm() }) return { + // 引用 + paymentFormRef, + + // 状态 loading, updating, submitting, - showPaymentForm, + paymentDialogVisible, recordsFilter, + uploadingQrCode, + uploadProgress, + + // 数据 commissionStats, paymentInfo, paymentForm, withdrawalForm, withdrawalRecords, + + // 计算属性 canWithdraw, + + // 方法 loadCommissionStats, - updatePaymentInfo, + openPaymentDialog, + submitPaymentForm, + handleDialogClose, submitWithdrawal, loadWithdrawalRecords, formatDate, getStatusText, maskAccount, handleQrCodeUpload, - uploadingQrCode, getPaymentTypeText, getAccountLabel, getHolderLabel, getAccountPlaceholder, getHolderPlaceholder, onPaymentTypeChange, - initPaymentForm, - goBack + goBack, + + // 表单规则 + paymentFormRules } } } @@ -666,64 +735,62 @@ export default { padding: 20px; max-width: 1200px; margin: 0 auto; + background: linear-gradient(to bottom, #72c9ffae, #f3f3f3); } /* 页面头部 */ .page-header { display: flex; align-items: center; - gap: 16px; + position: relative; margin-bottom: 24px; padding-bottom: 16px; border-bottom: 1px solid #eee; } -.page-header h2 { +.page-title { + position: absolute; + left: 50%; + transform: translateX(-50%); margin: 0; font-size: 24px; - color: #333; + color: white; font-weight: 600; } /* 返回按钮 */ .btn-back { - display: flex; - align-items: center; gap: 8px; padding: 10px 16px; - background: #f8f9fa; - border: 1px solid #dee2e6; + background: none; + border: none; border-radius: 8px; - color: #495057; font-size: 14px; + color: white; cursor: pointer; - transition: all 0.3s ease; } .btn-back:hover { - background: #e9ecef; border-color: #adb5bd; - color: #212529; } .btn-back .icon-arrow-left::before { - content: '←'; + content: '<'; font-size: 16px; } /* 统计卡片 */ .stats-cards { display: grid; - grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + grid-template-columns: repeat(2, 1fr); gap: 20px; margin-bottom: 30px; + width: 343px; } .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; @@ -773,14 +840,13 @@ export default { } /* 通用区块样式 */ -.payment-info-section, .withdrawal-section, .records-section { - background: white; border-radius: 12px; padding: 24px; - margin-bottom: 20px; + margin: 0 auto 20px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); + width: 343px; } .section-header { @@ -789,187 +855,21 @@ export default { 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; + line-height: 24px; } /* 表单样式 */ -.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; @@ -981,32 +881,34 @@ export default { 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-info { + display: flex; + justify-content: space-between; + align-items: center; } .amount-input { position: relative; display: flex; align-items: center; + width: 100%; } .amount-input input { - flex: 1; + width: 100%; + padding: 12px; + border: 1px solid #ddd; + border-radius: 8px; + font-size: 14px; + transition: border-color 0.3s; padding-right: 40px; } +.amount-input input:focus { + outline: none; + border-color: #007bff; +} + .currency { position: absolute; right: 12px; @@ -1017,20 +919,20 @@ export default { .amount-tips { font-size: 12px; color: #666; + margin-right: 10px; } .form-actions { display: flex; - gap: 12px; + justify-content: center; /* 将右对齐改为居中对齐 */ } /* 按钮样式 */ .btn-primary, -.btn-secondary, .btn-edit { padding: 10px 20px; border: none; - border-radius: 8px; + border-radius: 1000px; font-size: 14px; cursor: pointer; transition: all 0.3s; @@ -1039,6 +941,8 @@ export default { .btn-primary { background: #007bff; color: white; + width: 300px; + /* 保持申请提现按钮原有样式不变 */ } .btn-primary:hover:not(:disabled) { @@ -1050,20 +954,12 @@ export default { 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; + white-space: nowrap; } .btn-edit:hover { @@ -1071,11 +967,18 @@ export default { } /* 筛选控件 */ +.filter-controls { + height: 24px; + display: flex; + align-items: center; +} + .filter-controls select { - padding: 8px 12px; + padding: 4px 8px; border: 1px solid #ddd; border-radius: 6px; font-size: 14px; + height: 24px; } /* 记录列表 */ @@ -1093,7 +996,7 @@ export default { } .record-item { - border: 1px solid #eee; + border: 1px solid black; border-radius: 8px; padding: 16px; transition: box-shadow 0.3s; @@ -1176,11 +1079,6 @@ export default { padding: 16px; } - .stats-cards { - grid-template-columns: 1fr; - gap: 16px; - } - .stat-card { padding: 20px; } @@ -1191,14 +1089,11 @@ export default { gap: 12px; } - .form-actions { - flex-direction: column; - } - .record-header { flex-direction: column; align-items: flex-start; gap: 8px; } } + \ No newline at end of file