This commit is contained in:
@@ -155,7 +155,7 @@ export function formatDateRange(startDate: string, endDate: string): string {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 格式化日期时间
|
* 格式化日期时间
|
||||||
* @param date 日期字符串或时间戳
|
* @param date 日期字符串或时间戳(支持Unix时间戳秒,自动检测)
|
||||||
* @param format 格式化模板,默认 'YYYY-MM-DD HH:mm:ss'
|
* @param format 格式化模板,默认 'YYYY-MM-DD HH:mm:ss'
|
||||||
* @returns 格式化后的日期字符串
|
* @returns 格式化后的日期字符串
|
||||||
*/
|
*/
|
||||||
@@ -165,7 +165,14 @@ export function formatDateTime(
|
|||||||
): string {
|
): string {
|
||||||
if (!date) return '-'
|
if (!date) return '-'
|
||||||
|
|
||||||
const d = new Date(date)
|
let d: Date
|
||||||
|
const numDate = typeof date === 'string' ? Number(date) : date
|
||||||
|
if (typeof numDate === 'number' && numDate > 1000000000 && numDate < 2000000000) {
|
||||||
|
d = new Date(numDate * 1000)
|
||||||
|
} else {
|
||||||
|
d = new Date(date)
|
||||||
|
}
|
||||||
|
|
||||||
if (isNaN(d.getTime())) return '-'
|
if (isNaN(d.getTime())) return '-'
|
||||||
|
|
||||||
const year = d.getFullYear()
|
const year = d.getFullYear()
|
||||||
|
|||||||
@@ -32,69 +32,140 @@
|
|||||||
<template v-else-if="currentPackage">
|
<template v-else-if="currentPackage">
|
||||||
<!-- 流量使用情况 - 横向进度条卡片 -->
|
<!-- 流量使用情况 - 横向进度条卡片 -->
|
||||||
<div class="flow-progress-card">
|
<div class="flow-progress-card">
|
||||||
<div class="flow-stats-row">
|
<!-- 管理员视角:始终显示真流量和虚流量 -->
|
||||||
<div class="flow-stat-item">
|
<template v-if="isAdminOrPlatform">
|
||||||
<span class="flow-stat-label">总量</span>
|
<div class="flow-stats-container">
|
||||||
<span class="flow-stat-value">
|
<!-- 真流量 -->
|
||||||
{{ formatDataSize(currentPackage.data_limit_mb || 0) }}
|
<div class="flow-stat-section">
|
||||||
</span>
|
<div class="flow-stat-label">真流量使用</div>
|
||||||
</div>
|
<div class="flow-stat-row">
|
||||||
<div v-if="isAdminOrPlatform" class="flow-stat-item">
|
<span class="stat-item">
|
||||||
<span class="flow-stat-label">实际可用</span>
|
<span class="stat-label">已使用</span>
|
||||||
<span class="flow-stat-value">
|
<span class="stat-value">{{ formatDataSize(currentPackage.data_usage_mb || 0) }}</span>
|
||||||
{{
|
</span>
|
||||||
formatDataSize(
|
<span class="stat-item">
|
||||||
currentPackage.enable_virtual_data
|
<span class="stat-label">总量</span>
|
||||||
? currentPackage.virtual_limit_mb || 0
|
<span class="stat-value">{{ formatDataSize(currentPackage.data_limit_mb || 0) }}</span>
|
||||||
: currentPackage.data_limit_mb || 0
|
</span>
|
||||||
)
|
<span class="stat-item">
|
||||||
}}
|
<span class="stat-label">剩余</span>
|
||||||
</span>
|
<span class="stat-value">{{
|
||||||
</div>
|
formatDataSize(
|
||||||
<div class="flow-stat-item">
|
(currentPackage.data_limit_mb || 0) - (currentPackage.data_usage_mb || 0)
|
||||||
<span class="flow-stat-label">剩余可用</span>
|
|
||||||
<span class="flow-stat-value">
|
|
||||||
{{
|
|
||||||
formatDataSize(
|
|
||||||
currentPackage.enable_virtual_data
|
|
||||||
? currentPackage.virtual_remain_mb || 0
|
|
||||||
: (currentPackage.data_limit_mb || 0) - (currentPackage.data_usage_mb || 0)
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="flow-progress-bar">
|
|
||||||
<ElProgress
|
|
||||||
:percentage="
|
|
||||||
currentPackage.enable_virtual_data
|
|
||||||
? getUsageProgress(
|
|
||||||
currentPackage.virtual_data_used || 0,
|
|
||||||
currentPackage.virtual_data_total || 0
|
|
||||||
)
|
|
||||||
: getUsageProgress(
|
|
||||||
currentPackage.real_data_used || 0,
|
|
||||||
currentPackage.real_data_total || 0
|
|
||||||
)
|
|
||||||
"
|
|
||||||
:color="
|
|
||||||
currentPackage.enable_virtual_data
|
|
||||||
? getProgressColorByPercentage(
|
|
||||||
getUsageProgress(
|
|
||||||
currentPackage.virtual_data_used || 0,
|
|
||||||
currentPackage.virtual_data_total || 0
|
|
||||||
)
|
)
|
||||||
|
}}</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<ElProgress
|
||||||
|
:percentage="
|
||||||
|
getUsageProgress(
|
||||||
|
currentPackage.data_usage_mb || 0,
|
||||||
|
currentPackage.data_limit_mb || 0
|
||||||
)
|
)
|
||||||
: getProgressColorByPercentage(
|
"
|
||||||
getUsageProgress(
|
:color="getProgressColorByPercentage(
|
||||||
currentPackage.real_data_used || 0,
|
getUsageProgress(
|
||||||
currentPackage.real_data_total || 0
|
currentPackage.data_usage_mb || 0,
|
||||||
|
currentPackage.data_limit_mb || 0
|
||||||
|
)
|
||||||
|
)"
|
||||||
|
:stroke-width="10"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<!-- 虚流量 -->
|
||||||
|
<div class="flow-stat-section">
|
||||||
|
<div class="flow-stat-label">虚流量使用</div>
|
||||||
|
<div class="flow-stat-row">
|
||||||
|
<span class="stat-item">
|
||||||
|
<span class="stat-label">已使用</span>
|
||||||
|
<span class="stat-value">{{ formatDataSize(currentPackage.virtual_used_mb || 0) }}</span>
|
||||||
|
</span>
|
||||||
|
<span class="stat-item">
|
||||||
|
<span class="stat-label">总量</span>
|
||||||
|
<span class="stat-value">{{ formatDataSize(currentPackage.virtual_limit_mb || 0) }}</span>
|
||||||
|
</span>
|
||||||
|
<span class="stat-item">
|
||||||
|
<span class="stat-label">剩余</span>
|
||||||
|
<span class="stat-value">{{
|
||||||
|
formatDataSize(
|
||||||
|
(currentPackage.virtual_limit_mb || 0) - (currentPackage.virtual_used_mb || 0)
|
||||||
)
|
)
|
||||||
|
}}</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<ElProgress
|
||||||
|
:percentage="
|
||||||
|
getUsageProgress(
|
||||||
|
currentPackage.virtual_used_mb || 0,
|
||||||
|
currentPackage.virtual_limit_mb || 0
|
||||||
)
|
)
|
||||||
"
|
"
|
||||||
:stroke-width="14"
|
:color="getProgressColorByPercentage(
|
||||||
/>
|
getUsageProgress(
|
||||||
</div>
|
currentPackage.virtual_used_mb || 0,
|
||||||
|
currentPackage.virtual_limit_mb || 0
|
||||||
|
)
|
||||||
|
)"
|
||||||
|
:stroke-width="10"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 非管理员 或 未启用虚流量 -->
|
||||||
|
<template v-else>
|
||||||
|
<div class="flow-stats-row">
|
||||||
|
<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.data_usage_mb || 0
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="flow-stat-item">
|
||||||
|
<span class="flow-stat-label">总量</span>
|
||||||
|
<span class="flow-stat-value">
|
||||||
|
{{ formatDataSize(currentPackage.data_limit_mb || 0) }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="flow-stat-item">
|
||||||
|
<span class="flow-stat-label">剩余</span>
|
||||||
|
<span class="flow-stat-value">
|
||||||
|
{{
|
||||||
|
formatDataSize(
|
||||||
|
(currentPackage.data_limit_mb || 0) - (currentPackage.data_usage_mb || 0)
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</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.data_usage_mb || 0,
|
||||||
|
currentPackage.data_limit_mb || 0
|
||||||
|
)
|
||||||
|
"
|
||||||
|
:color="getProgressColorByPercentage(
|
||||||
|
getUsageProgress(
|
||||||
|
currentPackage.enable_virtual_data
|
||||||
|
? currentPackage.virtual_used_mb || 0
|
||||||
|
: currentPackage.data_usage_mb || 0,
|
||||||
|
currentPackage.data_limit_mb || 0
|
||||||
|
)
|
||||||
|
)"
|
||||||
|
:stroke-width="14"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 套餐详情表格 -->
|
<!-- 套餐详情表格 -->
|
||||||
@@ -111,12 +182,12 @@
|
|||||||
<ElDescriptionsItem label="套餐类型">
|
<ElDescriptionsItem label="套餐类型">
|
||||||
{{ getPackageTypeName(currentPackage.package_type) }}
|
{{ getPackageTypeName(currentPackage.package_type) }}
|
||||||
</ElDescriptionsItem>
|
</ElDescriptionsItem>
|
||||||
<!--<ElDescriptionsItem-->
|
<ElDescriptionsItem
|
||||||
<!-- v-if="isAdminOrPlatform && currentPackage.enable_virtual_data"-->
|
v-if="isAdminOrPlatform && currentPackage.enable_virtual_data"
|
||||||
<!-- label="虚流量比例"-->
|
label="虚流量比例"
|
||||||
<!-->-->
|
>
|
||||||
<!-- {{ currentPackage.virtual_ratio || '-' }}-->
|
{{ currentPackage.virtual_ratio || '-' }}
|
||||||
<!--</ElDescriptionsItem>-->
|
</ElDescriptionsItem>
|
||||||
<ElDescriptionsItem label="开始时间">
|
<ElDescriptionsItem label="开始时间">
|
||||||
{{ formatDateTime(currentPackage.start_time) || '-' }}
|
{{ formatDateTime(currentPackage.start_time) || '-' }}
|
||||||
</ElDescriptionsItem>
|
</ElDescriptionsItem>
|
||||||
@@ -212,6 +283,46 @@
|
|||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
|
|
||||||
|
.flow-stats-container {
|
||||||
|
display: flex;
|
||||||
|
gap: 40px;
|
||||||
|
|
||||||
|
.flow-stat-section {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
|
||||||
|
.flow-stat-label {
|
||||||
|
font-size: 13px;
|
||||||
|
color: var(--el-text-color-secondary);
|
||||||
|
margin-bottom: 8px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flow-stat-row {
|
||||||
|
display: flex;
|
||||||
|
gap: 16px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
|
||||||
|
.stat-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
gap: 4px;
|
||||||
|
|
||||||
|
.stat-label {
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--el-text-color-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-value {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--el-text-color-primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.flow-stats-row {
|
.flow-stats-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 32px;
|
gap: 32px;
|
||||||
@@ -237,6 +348,12 @@
|
|||||||
|
|
||||||
.flow-progress-bar {
|
.flow-progress-bar {
|
||||||
padding: 0 4px;
|
padding: 0 4px;
|
||||||
|
|
||||||
|
.progress-label {
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--el-text-color-secondary);
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -55,46 +55,117 @@
|
|||||||
</ElTag>
|
</ElTag>
|
||||||
</template>
|
</template>
|
||||||
</ElTableColumn>
|
</ElTableColumn>
|
||||||
<ElTableColumn label="流量" min-width="320">
|
<ElTableColumn label="流量" min-width="450">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<div class="traffic-progress">
|
<div class="traffic-progress">
|
||||||
<div class="progress-text">
|
<template v-if="isAdminOrPlatform">
|
||||||
<template v-if="scope.row.enable_virtual_data">
|
<div class="progress-text">
|
||||||
<span class="used"
|
<span class="used"
|
||||||
>已用: {{ formatDataSize(scope.row.virtual_used_mb || 0) }}</span
|
>已使用真流量: {{ formatDataSize(scope.row.data_usage_mb || 0) }}</span
|
||||||
>
|
|
||||||
<span class="remaining"
|
|
||||||
>剩余: {{ formatDataSize(scope.row.virtual_remain_mb || 0) }}</span
|
|
||||||
>
|
>
|
||||||
<span class="total"
|
<span class="total"
|
||||||
>总量: {{ formatDataSize(scope.row.virtual_limit_mb || 0) }}</span
|
>真流量总量: {{ formatDataSize(scope.row.data_limit_mb || 0) }}</span
|
||||||
|
>
|
||||||
|
<span class="remaining"
|
||||||
|
>真流量剩余:
|
||||||
|
{{
|
||||||
|
formatDataSize(
|
||||||
|
(scope.row.data_limit_mb || 0) - (scope.row.data_usage_mb || 0)
|
||||||
|
)
|
||||||
|
}}</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<ElProgress
|
||||||
|
style="margin-top: 4px"
|
||||||
|
:percentage="
|
||||||
|
getUsageProgress(scope.row.data_usage_mb || 0, scope.row.data_limit_mb || 0)
|
||||||
|
"
|
||||||
|
:color="
|
||||||
|
getProgressColorByPercentage(
|
||||||
|
getUsageProgress(scope.row.data_usage_mb || 0, scope.row.data_limit_mb || 0)
|
||||||
|
)
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<div class="progress-text" style="margin-top: 8px">
|
||||||
|
<span class="used"
|
||||||
|
>已使用虚流量: {{ formatDataSize(scope.row.virtual_used_mb || 0) }}</span
|
||||||
|
>
|
||||||
|
<span class="total"
|
||||||
|
>虚流量总量: {{ formatDataSize(scope.row.virtual_limit_mb || 0) }}</span
|
||||||
|
>
|
||||||
|
<span class="remaining"
|
||||||
|
>虚流量剩余:
|
||||||
|
{{
|
||||||
|
formatDataSize(
|
||||||
|
(scope.row.virtual_limit_mb || 0) - (scope.row.virtual_used_mb || 0)
|
||||||
|
)
|
||||||
|
}}</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<ElProgress
|
||||||
|
style="margin-top: 4px"
|
||||||
|
:percentage="
|
||||||
|
getUsageProgress(
|
||||||
|
scope.row.virtual_used_mb || 0,
|
||||||
|
scope.row.virtual_limit_mb || 0
|
||||||
|
)
|
||||||
|
"
|
||||||
|
:color="
|
||||||
|
getProgressColorByPercentage(
|
||||||
|
getUsageProgress(
|
||||||
|
scope.row.virtual_used_mb || 0,
|
||||||
|
scope.row.virtual_limit_mb || 0
|
||||||
|
)
|
||||||
|
)
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<div class="progress-text">
|
||||||
|
<span class="used"
|
||||||
|
>已使用:
|
||||||
|
{{
|
||||||
|
formatDataSize(
|
||||||
|
scope.row.enable_virtual_data
|
||||||
|
? scope.row.virtual_used_mb || 0
|
||||||
|
: scope.row.data_usage_mb || 0
|
||||||
|
)
|
||||||
|
}}</span
|
||||||
|
>
|
||||||
|
<span class="total"
|
||||||
|
>总量: {{ formatDataSize(scope.row.data_limit_mb || 0) }}</span
|
||||||
>
|
>
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<span class="used">已用: {{ formatDataSize(scope.row.data_usage_mb) }}</span>
|
|
||||||
<span class="remaining"
|
<span class="remaining"
|
||||||
>剩余:
|
>剩余:
|
||||||
{{ formatDataSize(scope.row.data_limit_mb - scope.row.data_usage_mb) }}</span
|
{{
|
||||||
|
formatDataSize(
|
||||||
|
(scope.row.data_limit_mb || 0) - (scope.row.data_usage_mb || 0)
|
||||||
|
)
|
||||||
|
}}</span
|
||||||
>
|
>
|
||||||
<span class="total">总量: {{ formatDataSize(scope.row.data_limit_mb) }}</span>
|
</div>
|
||||||
</template>
|
<ElProgress
|
||||||
</div>
|
style="margin-top: 8px"
|
||||||
<ElProgress
|
:percentage="
|
||||||
:percentage="
|
getUsageProgress(
|
||||||
scope.row.enable_virtual_data
|
scope.row.enable_virtual_data
|
||||||
? getUsageProgress(scope.row.virtual_used_mb, scope.row.virtual_limit_mb)
|
? scope.row.virtual_used_mb || 0
|
||||||
: getUsageProgress(scope.row.data_usage_mb, scope.row.data_limit_mb)
|
: scope.row.data_usage_mb || 0,
|
||||||
"
|
scope.row.data_limit_mb || 0
|
||||||
:color="
|
)
|
||||||
scope.row.enable_virtual_data
|
"
|
||||||
? getProgressColorByPercentage(
|
:color="
|
||||||
getUsageProgress(scope.row.virtual_used_mb, scope.row.virtual_limit_mb)
|
getProgressColorByPercentage(
|
||||||
|
getUsageProgress(
|
||||||
|
scope.row.enable_virtual_data
|
||||||
|
? scope.row.virtual_used_mb || 0
|
||||||
|
: scope.row.data_usage_mb || 0,
|
||||||
|
scope.row.data_limit_mb || 0
|
||||||
)
|
)
|
||||||
: getProgressColorByPercentage(
|
)
|
||||||
getUsageProgress(scope.row.data_usage_mb, scope.row.data_limit_mb)
|
"
|
||||||
)
|
/>
|
||||||
"
|
</template>
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</ElTableColumn>
|
</ElTableColumn>
|
||||||
@@ -187,9 +258,16 @@
|
|||||||
import { formatDateTime } from '@/utils/business/format'
|
import { formatDateTime } from '@/utils/business/format'
|
||||||
import type { AssetPackageUsageRecord } from '@/types/api'
|
import type { AssetPackageUsageRecord } from '@/types/api'
|
||||||
import { useAuth } from '@/composables/useAuth'
|
import { useAuth } from '@/composables/useAuth'
|
||||||
|
import { useUserStore } from '@/store/modules/user'
|
||||||
|
import { storeToRefs } from 'pinia'
|
||||||
import CreateRefundDialog from '@/components/business/CreateRefundDialog.vue'
|
import CreateRefundDialog from '@/components/business/CreateRefundDialog.vue'
|
||||||
|
|
||||||
const { hasAuth } = useAuth()
|
const { hasAuth } = useAuth()
|
||||||
|
const userStore = useUserStore()
|
||||||
|
const { info: userInfo } = storeToRefs(userStore)
|
||||||
|
const isAdminOrPlatform = computed(
|
||||||
|
() => userInfo.value.user_type === 1 || userInfo.value.user_type === 2
|
||||||
|
)
|
||||||
|
|
||||||
// 退款申请对话框
|
// 退款申请对话框
|
||||||
const createRefundDialogVisible = ref(false)
|
const createRefundDialogVisible = ref(false)
|
||||||
|
|||||||
Reference in New Issue
Block a user