fix: 代理系列授权店铺
Some checks failed
构建并部署前端到测试环境 / build-and-deploy (push) Failing after 2m0s

This commit is contained in:
sexygoat
2026-05-09 16:13:11 +08:00
parent 3c71ae0004
commit 73ce9af11a
26 changed files with 833 additions and 807 deletions

View File

@@ -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: '正式套餐',

View File

@@ -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)
}

View File

@@ -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 {