agent后台finance和users添加服务端分页和统计
This commit is contained in:
@@ -16,6 +16,7 @@ import DataTableToolbar from '@/pages/agent/finance/components/data-table-toolba
|
||||
|
||||
const props = defineProps<Omit<DataTableProps<Transaction>, 'columns'> & {
|
||||
typeFilter?: string
|
||||
serverPagination?: DataTableProps<Transaction>['serverPagination']
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -34,6 +35,7 @@ const table = generateVueTable<Transaction>({
|
||||
get data() { return props.data },
|
||||
get loading() { return props.loading },
|
||||
columns: columns.value,
|
||||
serverPagination: props.serverPagination,
|
||||
})
|
||||
|
||||
const columnLabels: Record<string, string> = {
|
||||
@@ -51,7 +53,7 @@ defineExpose({
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DataTable :columns="columns" :data :loading :table @refresh="emit('refresh')">
|
||||
<DataTable :columns="columns" :data :loading :table :server-pagination @refresh="emit('refresh')">
|
||||
<template #toolbar>
|
||||
<div class="space-y-3">
|
||||
<div class="flex flex-wrap items-center justify-between gap-2">
|
||||
|
||||
@@ -16,42 +16,48 @@ const balance = ref(0)
|
||||
const transactions = ref<Transaction[]>([])
|
||||
const tableRef = ref()
|
||||
const typeFilter = ref('')
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(20)
|
||||
const total = ref(0)
|
||||
const rechargeCount = ref(0)
|
||||
const consumeCount = ref(0)
|
||||
const totalRecharge = ref(0)
|
||||
const totalConsume = ref(0)
|
||||
|
||||
const filteredTransactions = computed(() => {
|
||||
let result = transactions.value.filter(tx => tx)
|
||||
if (typeFilter.value) {
|
||||
result = result.filter(tx => tx.type === typeFilter.value)
|
||||
}
|
||||
return result
|
||||
})
|
||||
const serverPagination = computed(() => ({
|
||||
page: currentPage.value,
|
||||
pageSize: pageSize.value,
|
||||
total: total.value,
|
||||
onPageChange: (newPage: number) => {
|
||||
currentPage.value = newPage
|
||||
fetchFinance()
|
||||
},
|
||||
onPageSizeChange: (newPageSize: number) => {
|
||||
pageSize.value = newPageSize
|
||||
currentPage.value = 1
|
||||
fetchFinance()
|
||||
},
|
||||
}))
|
||||
|
||||
const totalRecharge = computed(() => {
|
||||
return transactions.value
|
||||
.filter(tx => tx.type === 'recharge' || tx.type === 'refund')
|
||||
.reduce((sum, tx) => sum + (tx.amount || 0), 0)
|
||||
})
|
||||
|
||||
const totalConsume = computed(() => {
|
||||
return transactions.value
|
||||
.filter(tx => tx.type === 'consume')
|
||||
.reduce((sum, tx) => sum + (tx.amount || 0), 0)
|
||||
})
|
||||
|
||||
const rechargeCount = computed(() => transactions.value.filter(tx => tx.type === 'recharge' || tx.type === 'refund').length)
|
||||
const consumeCount = computed(() => transactions.value.filter(tx => tx.type === 'consume').length)
|
||||
|
||||
onMounted(async () => {
|
||||
async function fetchFinance() {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await api.get<any>('/agent/finance')
|
||||
const params = new URLSearchParams()
|
||||
params.append('page', String(currentPage.value))
|
||||
params.append('page_size', String(pageSize.value))
|
||||
if (typeFilter.value) {
|
||||
params.append('type', typeFilter.value)
|
||||
}
|
||||
|
||||
const data = await api.get<any>(`/agent/finance?${params.toString()}`)
|
||||
if (data) {
|
||||
balance.value = data.balance || 0
|
||||
if (Array.isArray(data.transactions)) {
|
||||
transactions.value = data.transactions
|
||||
} else if (Array.isArray(data.data)) {
|
||||
transactions.value = data.data
|
||||
} else {
|
||||
transactions.value = []
|
||||
}
|
||||
transactions.value = data.transactions || []
|
||||
total.value = data.total || 0
|
||||
rechargeCount.value = data.recharge_count || 0
|
||||
consumeCount.value = data.consume_count || 0
|
||||
totalRecharge.value = data.total_recharge || 0
|
||||
totalConsume.value = data.total_consume || 0
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
@@ -61,6 +67,10 @@ onMounted(async () => {
|
||||
finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
fetchFinance()
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -166,10 +176,11 @@ onMounted(async () => {
|
||||
v-else
|
||||
ref="tableRef"
|
||||
:loading
|
||||
:data="filteredTransactions"
|
||||
:data="transactions"
|
||||
:server-pagination="serverPagination"
|
||||
:type-filter="typeFilter"
|
||||
@refresh="() => {}"
|
||||
@update:typeFilter="typeFilter = $event"
|
||||
@refresh="fetchFinance"
|
||||
@update:typeFilter="typeFilter = $event; currentPage = 1; fetchFinance()"
|
||||
/>
|
||||
</UiCardContent>
|
||||
</UiCard>
|
||||
|
||||
@@ -16,6 +16,7 @@ import DataTableToolbar from '@/pages/agent/users/components/data-table-toolbar.
|
||||
|
||||
const props = defineProps<Omit<DataTableProps<User>, 'columns'> & {
|
||||
searchFilter?: string
|
||||
serverPagination?: DataTableProps<User>['serverPagination']
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -34,6 +35,7 @@ const table = generateVueTable<User>({
|
||||
get data() { return props.data },
|
||||
get loading() { return props.loading },
|
||||
columns: columns.value,
|
||||
serverPagination: props.serverPagination,
|
||||
})
|
||||
|
||||
const columnLabels: Record<string, string> = {
|
||||
@@ -51,7 +53,7 @@ defineExpose({
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DataTable :columns="columns" :data :loading :table @refresh="emit('refresh')">
|
||||
<DataTable :columns="columns" :data :loading :table :server-pagination @refresh="emit('refresh')">
|
||||
<template #toolbar>
|
||||
<div class="space-y-3">
|
||||
<div class="flex flex-wrap items-center justify-between gap-2">
|
||||
|
||||
@@ -15,36 +15,44 @@ const loading = ref(true)
|
||||
const users = ref<User[]>([])
|
||||
const tableRef = ref()
|
||||
const searchFilter = ref('')
|
||||
const currentPage = ref(1)
|
||||
const pageSize = ref(20)
|
||||
const total = ref(0)
|
||||
const activeCount = ref(0)
|
||||
const disabledCount = ref(0)
|
||||
const bannedCount = ref(0)
|
||||
|
||||
const filteredUsers = computed(() => {
|
||||
let result = users.value.filter(u => u)
|
||||
if (searchFilter.value) {
|
||||
const query = searchFilter.value.toLowerCase()
|
||||
result = result.filter(u =>
|
||||
u.username?.toLowerCase().includes(query)
|
||||
|| u.email?.toLowerCase().includes(query),
|
||||
)
|
||||
}
|
||||
return result
|
||||
})
|
||||
|
||||
const activeCount = computed(() => users.value.filter(user => user.status === 'active').length)
|
||||
const disabledCount = computed(() => users.value.filter(user => user.status === 'disabled').length)
|
||||
const bannedCount = computed(() => users.value.filter(user => user.status === 'banned').length)
|
||||
const serverPagination = computed(() => ({
|
||||
page: currentPage.value,
|
||||
pageSize: pageSize.value,
|
||||
total: total.value,
|
||||
onPageChange: (newPage: number) => {
|
||||
currentPage.value = newPage
|
||||
fetchUsers()
|
||||
},
|
||||
onPageSizeChange: (newPageSize: number) => {
|
||||
pageSize.value = newPageSize
|
||||
currentPage.value = 1
|
||||
fetchUsers()
|
||||
},
|
||||
}))
|
||||
|
||||
async function fetchUsers() {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await api.get<any>('/agent/users')
|
||||
if (Array.isArray(data)) {
|
||||
users.value = data
|
||||
} else if (data?.users) {
|
||||
users.value = data.users
|
||||
} else if (data?.data) {
|
||||
users.value = Array.isArray(data.data) ? data.data : []
|
||||
} else {
|
||||
users.value = []
|
||||
const params = new URLSearchParams()
|
||||
params.append('page', String(currentPage.value))
|
||||
params.append('page_size', String(pageSize.value))
|
||||
if (searchFilter.value) {
|
||||
params.append('search', searchFilter.value.trim())
|
||||
}
|
||||
|
||||
const data = await api.get<any>(`/agent/users?${params.toString()}`)
|
||||
users.value = data?.users || []
|
||||
total.value = data?.total || 0
|
||||
activeCount.value = data?.active_count || 0
|
||||
disabledCount.value = data?.disabled_count || 0
|
||||
bannedCount.value = data?.banned_count || 0
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Load users failed:', error)
|
||||
@@ -81,7 +89,7 @@ onMounted(() => {
|
||||
</UiCardHeader>
|
||||
<UiCardContent>
|
||||
<div class="text-2xl font-bold">
|
||||
{{ users.length }}
|
||||
{{ total }}
|
||||
</div>
|
||||
</UiCardContent>
|
||||
</UiCard>
|
||||
@@ -139,10 +147,11 @@ onMounted(() => {
|
||||
v-else
|
||||
ref="tableRef"
|
||||
:loading
|
||||
:data="filteredUsers"
|
||||
:data="users"
|
||||
:server-pagination="serverPagination"
|
||||
:search-filter="searchFilter"
|
||||
@refresh="fetchUsers"
|
||||
@update:search-filter="searchFilter = $event"
|
||||
@update:search-filter="searchFilter = $event; currentPage = 1; fetchUsers()"
|
||||
/>
|
||||
</UiCardContent>
|
||||
</UiCard>
|
||||
|
||||
Reference in New Issue
Block a user