@@ -16,6 +16,16 @@
< / div >
< el-tabs v-model = "activeTab" class="finance-tabs" @tab-change="loadActive" >
< el-tab-pane label = "充值套餐" name = "plans" >
< el-table :data = "plans" v-loading = "loading" class="data-table" >
< el-table-column label = "套餐名称" prop = "name" min -width = " 150 " / >
< el-table-column label = "积分" min -width = " 160 " > < template # default = "{ row }" > { { Number ( row . amount ) . toLocaleString ( ) } } < / template > < / el-table-column >
< el-table-column label = "价格" width = "140" > < template # default = "{ row }" > ¥ { { money ( row . price ) } } < / template > < / el-table-column >
< el-table-column label = "标签" prop = "badge" min -width = " 120 " / >
< el-table-column label = "说明" prop = "desc" min -width = " 180 " / >
< el-table-column label = "操作" width = "100" > < template # default = "{ row }" > < el-button link type = "primary" @click ="editPlan(row)" > 调整 < / el -button > < / template > < / el-table-column >
< / el-table >
< / el-tab-pane >
< el-tab-pane label = "支付订单" name = "orders" >
< div class = "filter-bar" >
< el-input v-model = "filters.keyword" placeholder="订单号、昵称或手机号" clearable style="width:240px" @keyup.enter="loadOrders" / >
@@ -23,13 +33,13 @@
< el-option v-for = "item in orderStatuses" :key="item.value" :label="item.label" :value="item.value" / >
< / el-select >
< el-select v-model = "filters.provider" placeholder="支付渠道" clearable style="width:150px" @change="loadOrders" >
< el-option label = "会会支付" value = "huihui" / > < el-option label = "微信虚拟支付" value = "wechat_virtual" / >
< el-option label = "会会支付" value = "huihui" / > < el-option label = "会会组织支付" value = "huihui_org" / > < el-option label = " 微信虚拟支付" value = "wechat_virtual" / >
< / el-select >
< el-button type = "primary" @click ="loadOrders" > 查询 < / el -button >
< / div >
< el-table :data = "orders" v-loading = "loading" class="data-table" >
< el-table-column label = "订单 / 用户" min -width = " 230 " >
< template # default = "{ row }" > < b > { { row . order _no } } < / b > < div class = "muted" > { { row . user _nickname || '会会用户' } } · { { row . user _phone || '--' } } < / div > < / template >
< el-table-column label = "订单 / 用户" min -width = " 260 " >
< template # default = "{ row }" > < b > { { row . order _no } } < / b > < div class = "muted" > 支付编号 : { { row . provider _order _no || '--' } } < / div > < div class = "muted" > { { row . user _nickname || '会会用户' } } · { { row . user _phone || '--' } } < / div > < / template >
< / el-table-column >
< el-table-column label = "套餐积分" width = "130" > < template # default = "{ row }" > { { Number ( row . points _amount || 0 ) . toLocaleString ( ) } } < / template > < / el-table-column >
< el-table-column label = "金额" width = "100" > < template # default = "{ row }" > ¥ { { money ( row . price ) } } < / template > < / el-table-column >
@@ -87,25 +97,37 @@
< / el-form >
< template # footer > < el-button @click ="invoiceDialog=false" > 取消 < / el -button > < el-button type = "primary" :loading = "saving" @click ="issueInvoice" > 确认开具 < / el -button > < / template >
< / el-dialog >
< el-dialog v-model = "planDialog" title="调整充值套餐" width="480px" >
< el-form label -width = " 90px " >
< el-form-item label = "套餐名称" > < el-input v-model = "planForm.name" maxlength="80" / > < / el-form-item >
< el-form-item label = "积分数量" > < el-input-number v-model = "planForm.amount" :min="1" :step="10000" / > < / el-form-item >
< el-form-item label = "套餐价格" > < el-input-number v-model = "planForm.price" :min="0" :precision="2" :step="1" / > < / el-form-item >
< el-form-item label = "标签" > < el-input v-model = "planForm.badge" maxlength="80" / > < / el-form-item >
< el-form-item label = "说明" > < el-input v-model = "planForm.desc" maxlength="200" / > < / el-form-item >
< / el-form >
< template # footer > < el-button @click ="planDialog=false" > 取消 < / el -button > < el-button type = "primary" :loading = "saving" @click ="savePlan" > 保存 < / el -button > < / template >
< / el-dialog >
< / div >
< / template >
< script setup >
import { onMounted , ref } from 'vue'
import { ElMessage , ElMessageBox } from 'element-plus'
import { confirmFinanceRefund , getFinanceInvoices , getFinanceOrders , getFinanceRefunds , getFinanceSummary , requestFinanceRefund , updateFinanceInvoice , updateFinanceOrderStatus } from '@/api'
import { confirmFinanceRefund , getFinanceInvoices , getFinanceOrders , getFinancePlans , getFinanceRefunds , getFinanceSummary , requestFinanceRefund , updateFinanceInvoice , updateFinanceOrderStatus , updateFinancePlan } from '@/api'
const activeTab = ref ( 'orders' )
const loading = ref ( false )
const saving = ref ( false )
const summary = ref ( { paid _revenue : 0 , paid _orders : 0 , pending _orders : 0 , processing _refunds : 0 , pending _invoices : 0 } )
const orders = ref ( [ ] ) , refunds = ref ( [ ] ) , invoices = ref ( [ ] )
const plans = ref ( [ ] ) , planDialog = ref ( false ) , currentPlan = ref ( null )
const planForm = ref ( { name : '' , amount : 1 , price : 0 , badge : '' , desc : '' } )
const orderPage = ref ( 1 ) , orderTotal = ref ( 0 )
const filters = ref ( { keyword : '' , status : '' , provider : '' } )
const invoiceDialog = ref ( false ) , currentInvoice = ref ( null )
const invoiceForm = ref ( { invoiceNo : '' , invoiceUrl : '' , remark : '' } )
const orderStatuses = [ { label : '待支付' , value : 'pending' } , { label : '已支付' , value : 'paid' } , { label : '失败' , value : 'failed' } , { label : '已关闭' , value : 'closed' } , { label : '已退款' , value : 'refunded' } ]
const providerLabel = { huihui : '会会支付' , wechat _virtual : '微信虚拟支付' }
const providerLabel = { huihui : '会会支付' , huihui _org : '会会组织支付' , wechat _virtual : '微信虚拟支付' }
const statusLabel = { pending : '待处理' , processing : '处理中' , paid : '已支付' , succeeded : '已成功' , failed : '失败' , closed : '已关闭' , refunded : '已退款' }
const invoiceStatusLabel = { pending : '待开具' , issued : '已开具' , rejected : '已驳回' }
const money = value => Number ( value || 0 ) . toFixed ( 2 )
@@ -113,11 +135,14 @@ const dateTime = value => value ? new Date(value).toLocaleString('zh-CN', { hour
const tagType = value => ( { paid : 'success' , succeeded : 'success' , issued : 'success' , pending : 'warning' , processing : 'warning' , failed : 'danger' , rejected : 'danger' , refunded : 'info' , closed : 'info' } [ value ] || 'info' )
async function loadSummary ( ) { const res = await getFinanceSummary ( ) ; summary . value = res . data || summary . value }
async function loadPlans ( ) { const res = await getFinancePlans ( ) ; plans . value = res . data || [ ] }
async function loadOrders ( ) { const res = await getFinanceOrders ( { page : orderPage . value , page _size : 20 , ... filters . value } ) ; orders . value = res . data ? . items || [ ] ; orderTotal . value = res . data ? . total || 0 }
async function loadRefunds ( ) { const res = await getFinanceRefunds ( { page : 1 , page _size : 100 } ) ; refunds . value = res . data ? . items || [ ] }
async function loadInvoices ( ) { const res = await getFinanceInvoices ( { page : 1 , page _size : 100 } ) ; invoices . value = res . data ? . items || [ ] }
async function loadActive ( ) { loading . value = true ; try { if ( activeTab . value === 'orders' ) await loadOrders ( ) ; if ( activeTab . value === 'refunds' ) await loadRefunds ( ) ; if ( activeTab . value === 'invoices' ) await loadInvoices ( ) } finally { loading . value = false } }
async function loadAll ( ) { loading . value = true ; try { await Promise . all ( [ loadSummary ( ) , loadOrders ( ) , loadRefunds ( ) , loadInvoices ( ) ] ) } finally { loading . value = false } }
async function loadActive ( ) { loading . value = true ; try { if ( activeTab . value === 'plans' ) await loadPlans ( ) ; if ( activeTab . value === 'orders' ) await loadOrders ( ) ; if ( activeTab . value === 'refunds' ) await loadRefunds ( ) ; if ( activeTab . value === 'invoices' ) await loadInvoices ( ) } finally { loading . value = false } }
async function loadAll ( ) { loading . value = true ; try { await Promise . all ( [ loadSummary ( ) , loadPlans ( ) , loadOrders ( ) , loadRefunds ( ) , loadInvoices ( ) ] ) } finally { loading . value = false } }
function editPlan ( row ) { currentPlan . value = row ; planForm . value = { name : row . name , amount : Number ( row . amount ) , price : Number ( row . price ) , badge : row . badge || '' , desc : row . desc || '' } ; planDialog . value = true }
async function savePlan ( ) { if ( ! currentPlan . value ) return ; saving . value = true ; try { await updateFinancePlan ( currentPlan . value . id , planForm . value ) ; ElMessage . success ( '充值套餐已更新' ) ; planDialog . value = false ; await loadPlans ( ) } finally { saving . value = false } }
async function refund ( row ) {
try { const { value } = await ElMessageBox . prompt ( '退款成功后会扣回本订单发放的全部积分。' , ` 退款 ¥ ${ money ( row . price ) } ` , { inputPlaceholder : '请输入退款原因' , inputValidator : value => value ? . trim ( ) ? true : '退款原因不能为空' , confirmButtonText : '提交退款' , cancelButtonText : '取消' } ) ; await requestFinanceRefund ( row . order _no , { reason : value , operator : '后台管理员' } ) ; ElMessage . success ( '退款已提交渠道处理' ) ; await loadAll ( ) } catch ( error ) { if ( error !== 'cancel' && error !== 'close' ) console . error ( error ) }