This commit is contained in:
@@ -147,49 +147,32 @@
|
||||
<div class="flow-stat-item">
|
||||
<span class="flow-stat-label">已使用</span>
|
||||
<span class="flow-stat-value">
|
||||
{{
|
||||
formatDataSize(
|
||||
currentPackage.enable_virtual_data
|
||||
? currentPackage.virtual_used_mb || 0
|
||||
: currentPackage.real_used_mb || 0
|
||||
)
|
||||
}}
|
||||
{{ formatDataSize(getDisplayedUsedMb(currentPackage)) }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="flow-stat-item">
|
||||
<span class="flow-stat-label">总量</span>
|
||||
<span class="flow-stat-value">
|
||||
{{ formatDataSize(currentPackage.real_total_mb || 0) }}
|
||||
{{ formatDataSize(getDisplayedTotalMb(currentPackage)) }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="flow-stat-item">
|
||||
<span class="flow-stat-label">剩余</span>
|
||||
<span class="flow-stat-value">
|
||||
{{
|
||||
formatDataSize(
|
||||
(currentPackage.real_total_mb || 0) - (currentPackage.real_used_mb || 0)
|
||||
)
|
||||
}}
|
||||
{{ formatDataSize(getDisplayedRemainingMb(currentPackage)) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flow-progress-bar" style="margin-top: 16px">
|
||||
<ElProgress
|
||||
:percentage="
|
||||
getUsageProgress(
|
||||
currentPackage.enable_virtual_data
|
||||
? currentPackage.virtual_used_mb || 0
|
||||
: currentPackage.real_used_mb || 0,
|
||||
currentPackage.real_total_mb || 0
|
||||
)
|
||||
getUsageProgress(getDisplayedUsedMb(currentPackage), getDisplayedTotalMb(currentPackage))
|
||||
"
|
||||
:color="
|
||||
getProgressColorByPercentage(
|
||||
getUsageProgress(
|
||||
currentPackage.enable_virtual_data
|
||||
? currentPackage.virtual_used_mb || 0
|
||||
: currentPackage.real_used_mb || 0,
|
||||
currentPackage.real_total_mb || 0
|
||||
getDisplayedUsedMb(currentPackage),
|
||||
getDisplayedTotalMb(currentPackage)
|
||||
)
|
||||
)
|
||||
"
|
||||
@@ -286,6 +269,14 @@
|
||||
navigateToDevice: [deviceNo: string]
|
||||
}>()
|
||||
|
||||
const getDisplayedTotalMb = (pkg: AssetPackageUsageRecord) => pkg.real_total_mb || 0
|
||||
|
||||
const getDisplayedUsedMb = (pkg: AssetPackageUsageRecord) =>
|
||||
pkg.enable_virtual_data ? pkg.virtual_used_mb || 0 : pkg.real_used_mb || 0
|
||||
|
||||
const getDisplayedRemainingMb = (pkg: AssetPackageUsageRecord) =>
|
||||
getDisplayedTotalMb(pkg) - getDisplayedUsedMb(pkg)
|
||||
|
||||
const getPackageTypeName = (type?: string) => {
|
||||
const typeMap: Record<string, string> = {
|
||||
formal: '正式套餐',
|
||||
|
||||
@@ -148,9 +148,7 @@
|
||||
>已使用:
|
||||
{{
|
||||
formatDataSize(
|
||||
scope.row.enable_virtual_data
|
||||
? scope.row.virtual_used_mb || 0
|
||||
: scope.row.real_used_mb || 0
|
||||
getDisplayedUsedMb(scope.row)
|
||||
)
|
||||
}}</span
|
||||
>
|
||||
@@ -161,7 +159,7 @@
|
||||
>剩余:
|
||||
{{
|
||||
formatDataSize(
|
||||
(scope.row.real_total_mb || 0) - (scope.row.real_used_mb || 0)
|
||||
getDisplayedRemainingMb(scope.row)
|
||||
)
|
||||
}}</span
|
||||
>
|
||||
@@ -170,19 +168,15 @@
|
||||
style="margin-top: 8px"
|
||||
:percentage="
|
||||
getUsageProgress(
|
||||
scope.row.enable_virtual_data
|
||||
? scope.row.virtual_used_mb || 0
|
||||
: scope.row.real_used_mb || 0,
|
||||
scope.row.real_total_mb || 0
|
||||
getDisplayedUsedMb(scope.row),
|
||||
getDisplayedTotalMb(scope.row)
|
||||
)
|
||||
"
|
||||
:color="
|
||||
getProgressColorByPercentage(
|
||||
getUsageProgress(
|
||||
scope.row.enable_virtual_data
|
||||
? scope.row.virtual_used_mb || 0
|
||||
: scope.row.real_used_mb || 0,
|
||||
scope.row.real_total_mb || 0
|
||||
getDisplayedUsedMb(scope.row),
|
||||
getDisplayedTotalMb(scope.row)
|
||||
)
|
||||
)
|
||||
"
|
||||
@@ -409,6 +403,14 @@
|
||||
}
|
||||
|
||||
// 页码变化
|
||||
const getDisplayedTotalMb = (pkg: PackageInfo) => pkg.real_total_mb || 0
|
||||
|
||||
const getDisplayedUsedMb = (pkg: PackageInfo) =>
|
||||
pkg.enable_virtual_data ? pkg.virtual_used_mb || 0 : pkg.real_used_mb || 0
|
||||
|
||||
const getDisplayedRemainingMb = (pkg: PackageInfo) =>
|
||||
getDisplayedTotalMb(pkg) - getDisplayedUsedMb(pkg)
|
||||
|
||||
const handlePageChange = (page: number) => {
|
||||
emit('page-change', page)
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
style="width: 360px"
|
||||
/>
|
||||
<ElButton type="primary" @click="handleQuery">查询</ElButton>
|
||||
<ElButton @click="handleReset">重置</ElButton>
|
||||
<ElButton @click="handleReset()">重置</ElButton>
|
||||
<ElTag type="info" size="small">共 {{ total }} 条</ElTag>
|
||||
</div>
|
||||
</div>
|
||||
@@ -64,14 +64,8 @@
|
||||
</template>
|
||||
</ElEmpty>
|
||||
|
||||
<div v-else class="wallet-table-wrapper">
|
||||
<ElTable
|
||||
v-if="transactionList && transactionList.length > 0"
|
||||
:data="transactionList"
|
||||
class="wallet-table"
|
||||
border
|
||||
v-loading="loading"
|
||||
>
|
||||
<div v-else v-loading="loading" class="wallet-table-wrapper">
|
||||
<ElTable v-if="hasTransactions" :data="transactionList" class="wallet-table" border>
|
||||
<ElTableColumn label="交易类型" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<ElTag :type="getTransactionTypeTag(scope.row.transaction_type)" size="small">
|
||||
@@ -128,7 +122,9 @@
|
||||
</template>
|
||||
</ElTableColumn>
|
||||
</ElTable>
|
||||
<ElEmpty v-else-if="!loading" description="暂无钱包流水数据" :image-size="100" />
|
||||
<div v-else class="wallet-empty-state">
|
||||
<ElEmpty v-if="hasLoadedTransactions" description="暂无钱包流水数据" :image-size="100" />
|
||||
</div>
|
||||
|
||||
<!-- 分页器 -->
|
||||
<div v-if="total > 0" class="pagination-wrapper">
|
||||
@@ -147,7 +143,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue'
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import {
|
||||
ElCard,
|
||||
ElTable,
|
||||
@@ -166,6 +162,8 @@
|
||||
import { formatDateTime } from '@/utils/business/format'
|
||||
import { AssetService } from '@/api/modules'
|
||||
import type {
|
||||
AssetWalletTransactionItem,
|
||||
AssetWalletTransactionListResponse,
|
||||
AssetWalletResponse,
|
||||
AssetWalletTransactionParams,
|
||||
TransactionType
|
||||
@@ -173,6 +171,7 @@
|
||||
|
||||
interface Props {
|
||||
assetIdentifier: string
|
||||
searchToken?: number
|
||||
walletInfo: AssetWalletResponse | null
|
||||
walletLoading?: boolean
|
||||
boundDeviceId?: number | null
|
||||
@@ -190,39 +189,80 @@
|
||||
}>()
|
||||
|
||||
const { formatAmount, getTransactionTypeTag, getWalletStatusType } = useAssetFormatters()
|
||||
const DEFAULT_PAGE_SIZE = 20
|
||||
|
||||
const createDefaultPagination = () => ({ page: 1, page_size: DEFAULT_PAGE_SIZE })
|
||||
|
||||
const createDefaultFilterForm = () => ({
|
||||
transaction_type: null as TransactionType | null,
|
||||
date_range: null as [Date, Date] | null
|
||||
})
|
||||
|
||||
const createDefaultQueryParams = (): AssetWalletTransactionParams => ({
|
||||
page: 1,
|
||||
page_size: DEFAULT_PAGE_SIZE,
|
||||
transaction_type: null,
|
||||
start_time: null,
|
||||
end_time: null
|
||||
})
|
||||
|
||||
// State
|
||||
const loading = ref(false)
|
||||
const transactionList = ref<any[]>([])
|
||||
const hasLoadedTransactions = ref(false)
|
||||
const transactionList = ref<AssetWalletTransactionItem[]>([])
|
||||
const total = ref(0)
|
||||
const pagination = ref({ page: 1, page_size: 20 })
|
||||
const filterForm = ref<{
|
||||
transaction_type: TransactionType | null
|
||||
date_range: [Date, Date] | null
|
||||
}>({
|
||||
transaction_type: null,
|
||||
date_range: null
|
||||
})
|
||||
const queryParams = ref<AssetWalletTransactionParams>({
|
||||
page: 1,
|
||||
page_size: 20,
|
||||
transaction_type: null as TransactionType | null,
|
||||
start_time: null as string | null,
|
||||
end_time: null as string | null
|
||||
const hasTransactions = computed(() => transactionList.value.length > 0)
|
||||
const pagination = ref(createDefaultPagination())
|
||||
const filterForm = ref(createDefaultFilterForm())
|
||||
const queryParams = ref<AssetWalletTransactionParams>(createDefaultQueryParams())
|
||||
|
||||
const clearTransactions = () => {
|
||||
hasLoadedTransactions.value = false
|
||||
transactionList.value = []
|
||||
total.value = 0
|
||||
pagination.value = createDefaultPagination()
|
||||
}
|
||||
|
||||
const normalizeTransactionResponse = (data?: AssetWalletTransactionListResponse | null) => ({
|
||||
items: data?.items ?? data?.list ?? [],
|
||||
total: data?.total ?? 0,
|
||||
page: data?.page ?? 1,
|
||||
pageSize: data?.size ?? data?.page_size ?? queryParams.value.page_size ?? DEFAULT_PAGE_SIZE
|
||||
})
|
||||
|
||||
const loadTransactions = async () => {
|
||||
if (!props.assetIdentifier) return
|
||||
const loadTransactions = async (preserveDisplayState: boolean = true) => {
|
||||
if (!props.assetIdentifier || props.boundDeviceId) {
|
||||
clearTransactions()
|
||||
return
|
||||
}
|
||||
|
||||
if (!preserveDisplayState) {
|
||||
clearTransactions()
|
||||
}
|
||||
|
||||
try {
|
||||
loading.value = true
|
||||
const response = await AssetService.getWalletTransactions(
|
||||
props.assetIdentifier,
|
||||
queryParams.value
|
||||
)
|
||||
|
||||
if (response.code === 0 && response.data) {
|
||||
transactionList.value = response.data.list || []
|
||||
total.value = response.data.total || 0
|
||||
const normalized = normalizeTransactionResponse(response.data)
|
||||
transactionList.value = normalized.items
|
||||
total.value = normalized.total
|
||||
pagination.value = {
|
||||
page: normalized.page,
|
||||
page_size: normalized.pageSize
|
||||
}
|
||||
queryParams.value.page = normalized.page
|
||||
queryParams.value.page_size = normalized.pageSize
|
||||
} else {
|
||||
transactionList.value = []
|
||||
total.value = 0
|
||||
pagination.value = createDefaultPagination()
|
||||
}
|
||||
hasLoadedTransactions.value = true
|
||||
} catch (error: any) {
|
||||
if (error?.response?.status === 403) {
|
||||
ElMessage.warning('企业账号禁止查看钱包流水')
|
||||
@@ -234,6 +274,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
const resetQueryState = () => {
|
||||
filterForm.value = createDefaultFilterForm()
|
||||
queryParams.value = createDefaultQueryParams()
|
||||
pagination.value = createDefaultPagination()
|
||||
}
|
||||
|
||||
const handleQuery = () => {
|
||||
queryParams.value.page = 1
|
||||
pagination.value.page = 1
|
||||
@@ -245,41 +291,45 @@
|
||||
queryParams.value.start_time = null
|
||||
queryParams.value.end_time = null
|
||||
}
|
||||
loadTransactions()
|
||||
void loadTransactions(true)
|
||||
}
|
||||
|
||||
const handleFilterChange = () => handleQuery()
|
||||
|
||||
const handleReset = () => {
|
||||
filterForm.value = { transaction_type: null, date_range: null }
|
||||
queryParams.value = {
|
||||
page: 1,
|
||||
page_size: 20,
|
||||
transaction_type: null,
|
||||
start_time: null,
|
||||
end_time: null
|
||||
const handleReset = (preserveDisplayState: boolean = true) => {
|
||||
resetQueryState()
|
||||
if (props.boundDeviceId) {
|
||||
clearTransactions()
|
||||
return
|
||||
}
|
||||
pagination.value = { page: 1, page_size: 20 }
|
||||
loadTransactions()
|
||||
void loadTransactions(preserveDisplayState)
|
||||
}
|
||||
|
||||
const handlePageSizeChange = (size: number) => {
|
||||
queryParams.value.page_size = size
|
||||
queryParams.value.page = 1
|
||||
pagination.value.page = 1
|
||||
loadTransactions()
|
||||
void loadTransactions(true)
|
||||
}
|
||||
|
||||
const handlePageChange = (page: number) => {
|
||||
queryParams.value.page = page
|
||||
loadTransactions()
|
||||
void loadTransactions(true)
|
||||
}
|
||||
|
||||
// 仅监听 assetIdentifier 变化加载数据(去掉 onMounted 避免重复调用)
|
||||
watch(
|
||||
() => props.assetIdentifier,
|
||||
(newVal) => {
|
||||
if (newVal) handleReset()
|
||||
() => [props.assetIdentifier, props.searchToken, props.boundDeviceId] as const,
|
||||
([assetIdentifier], previousValue) => {
|
||||
if (!assetIdentifier) {
|
||||
resetQueryState()
|
||||
clearTransactions()
|
||||
return
|
||||
}
|
||||
|
||||
const previousAssetIdentifier = previousValue?.[0]
|
||||
const preserveDisplayState =
|
||||
Boolean(previousAssetIdentifier) && assetIdentifier === previousAssetIdentifier
|
||||
handleReset(preserveDisplayState)
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
@@ -326,6 +376,13 @@
|
||||
}
|
||||
|
||||
.wallet-table-wrapper {
|
||||
.wallet-empty-state {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 220px;
|
||||
}
|
||||
|
||||
.wallet-table {
|
||||
:deep(.el-table__header) {
|
||||
th {
|
||||
@@ -334,18 +391,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.reference-no-link {
|
||||
color: var(--el-color-primary);
|
||||
text-decoration: underline;
|
||||
text-decoration-style: dashed;
|
||||
text-underline-offset: 2px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: var(--el-color-primary-light-3);
|
||||
text-decoration-style: solid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pagination-wrapper {
|
||||
|
||||
Reference in New Issue
Block a user