+
-
- {{ deviceRealtime.online_status === 1 ? '在线' : '离线' }}
+
+ {{ getOnlineStatusName(deviceRealtime?.online_status) }}
{{
- deviceRealtime.battery_level !== null && deviceRealtime.battery_level !== undefined
- ? `${deviceRealtime.battery_level}%`
+ deviceRealtime?.battery_level !== null && deviceRealtime?.battery_level !== undefined
+ ? `${deviceRealtime?.battery_level}%`
: '-'
}}
- {{ formatDuration(deviceRealtime.run_time) }}
+ {{ formatDuration(deviceRealtime?.run_time) }}
- {{ formatDuration(deviceRealtime.connect_time) }}
+ {{ formatDuration(deviceRealtime?.connect_time) }}
- {{ formatDateTime(deviceRealtime.last_online_time) || '-' }}
+ {{ formatDateTime(deviceRealtime?.last_online_time) || '-' }}
+
+
+ {{ formatDateTime(cardInfo?.last_real_name_check_at) || '-' }}
+
+
+ {{ formatDateTime(cardInfo?.last_card_status_check_at) || '-' }}
+
+
+ {{ formatDateTime(cardInfo?.last_data_check_at) || '-' }}
-
- {{ getSignalQualityText(deviceRealtime.signal_quality) }}
+
+ {{ getSignalQualityText(deviceRealtime?.signal_quality) }}
- {{ getSignalBadReasonText(deviceRealtime.signal_bad_reason) }}
+ {{ getSignalBadReasonText(deviceRealtime?.signal_bad_reason) }}
- {{ deviceRealtime.client_number ?? '-' }} / {{ deviceRealtime.max_clients ?? '-' }}
+ {{ deviceRealtime?.client_number ?? '-' }} / {{ deviceRealtime?.max_clients ?? '-' }}
-
- {{ deviceRealtime.wifi_enabled ? '已开启' : '已关闭' }}
+
+ {{
+ deviceRealtime?.wifi_enabled === undefined
+ ? '-'
+ : deviceRealtime.wifi_enabled
+ ? '已开启'
+ : '已关闭'
+ }}
- {{ deviceRealtime.ssid || '-' }}
+ {{ deviceRealtime?.ssid || '-' }}
- {{ deviceRealtime.wifi_password || '-' }}
+ {{ deviceRealtime?.wifi_password || '-' }}
- {{ deviceRealtime.wan_ip || '-' }}
+ {{ deviceRealtime?.wan_ip || '-' }}
- {{ deviceRealtime.lan_ip || '-' }}
+ {{ deviceRealtime?.lan_ip || '-' }}
- {{ deviceRealtime.mac_address || '-' }}
+ {{ deviceRealtime?.mac_address || '-' }}
- {{ deviceRealtime.imsi || '-' }}
+ {{ deviceRealtime?.imsi || '-' }}
- {{ deviceRealtime.limit_speed ? `${deviceRealtime.limit_speed} KB/s` : '不限速' }}
+ {{
+ deviceRealtime?.limit_speed === undefined
+ ? '-'
+ : deviceRealtime.limit_speed
+ ? `${deviceRealtime.limit_speed} KB/s`
+ : '不限速'
+ }}
- {{ deviceRealtime.software_version || '-' }}
+ {{ deviceRealtime?.software_version || '-' }}
{{
- deviceRealtime.switch_mode === '0'
+ deviceRealtime?.switch_mode === '0'
? '自动'
- : deviceRealtime.switch_mode === '1'
+ : deviceRealtime?.switch_mode === '1'
? '手动'
: '-'
}}
- {{ deviceRealtime.sync_interval ? `${deviceRealtime.sync_interval} 秒` : '-' }}
+ {{ deviceRealtime?.sync_interval ? `${deviceRealtime.sync_interval} 秒` : '-' }}
- {{ formatDateTime(deviceRealtime.last_update_time) || '-' }}
+ {{ formatDateTime(deviceRealtime?.last_update_time) || '-' }}
@@ -451,6 +481,9 @@
real_name_at?: string
realname_policy?: string
gateway_extend?: string
+ last_data_check_at?: string | null
+ last_real_name_check_at?: string | null
+ last_card_status_check_at?: string | null
}
interface AssetInfo {
@@ -477,6 +510,10 @@
real_name_at?: string
supplier?: string
gateway_extend?: string
+ last_sync_time?: string | null
+ last_data_check_at?: string | null
+ last_real_name_check_at?: string | null
+ last_card_status_check_at?: string | null
bound_device_id?: number
bound_device_no?: string
bound_device_name?: string
@@ -496,13 +533,13 @@
battery_level?: number | null
run_time?: string
connect_time?: string
- last_online_time?: string
+ last_online_time?: string | null
client_number?: number
max_clients?: number
current_iccid?: string
signal_quality?: string
signal_bad_reason?: string
- wifi_enabled?: boolean
+ wifi_enabled?: boolean | number
ssid?: string
wifi_password?: string
ip_address?: string
@@ -516,8 +553,8 @@
switch_mode?: string
sync_interval?: number
device_id?: string
- last_sync_time?: string
- last_update_time?: string
+ last_sync_time?: string | null
+ last_update_time?: string | null
}
interface Props {
@@ -610,6 +647,14 @@
return props.cardInfo.cards.find((card: BindingCard) => card.is_current) || null
})
+ const hasDeviceRealtimeSection = computed(
+ () =>
+ Boolean(props.deviceRealtime) ||
+ props.cardInfo?.last_data_check_at !== undefined ||
+ props.cardInfo?.last_real_name_check_at !== undefined ||
+ props.cardInfo?.last_card_status_check_at !== undefined
+ )
+
// 处理轮询开关变化
const handlePollingChange = (value: string | number | boolean) => {
emit('update:pollingEnabled', Boolean(value))
diff --git a/src/views/asset-management/asset-information/components/dialogs/DailyRecordsDialog.vue b/src/views/asset-management/asset-information/components/dialogs/DailyRecordsDialog.vue
index 034c747..41f60da 100644
--- a/src/views/asset-management/asset-information/components/dialogs/DailyRecordsDialog.vue
+++ b/src/views/asset-management/asset-information/components/dialogs/DailyRecordsDialog.vue
@@ -7,7 +7,7 @@
{{ data.package_name }}
- {{ formatDataSize(data.total_usage_mb) }}
+ {{ formatDataSize(displayedTotalUsageMb) }}
@@ -59,9 +59,9 @@
@@ -86,14 +86,28 @@
ElTable,
ElTableColumn,
ElProgress,
- ElEmpty,
- ElMessage
+ ElEmpty
} from 'element-plus'
import { CardService } from '@/api/modules'
+ import type { PackageInfo } from '../../types'
interface Props {
modelValue: boolean
packageUsageId?: number
+ packageRow?: PackageInfo
+ }
+
+ interface DailyRecordItem {
+ date: string
+ daily_usage_mb: number
+ cumulative_usage_mb: number
+ }
+
+ interface DailyRecordsResponseData {
+ package_name: string
+ package_usage_id: number
+ total_usage_mb: number
+ records: DailyRecordItem[]
}
interface Emits {
@@ -104,16 +118,19 @@
const emit = defineEmits()
const loading = ref(false)
- const data = ref(null)
+ const data = ref(null)
const filterType = ref<'all' | 'day' | 'month'>('all')
const selectedDate = ref('')
const selectedMonth = ref('')
- const filteredRecords = ref([])
+ const filteredRecords = ref([])
const visible = computed({
get: () => props.modelValue,
set: (value) => emit('update:modelValue', value)
})
+ const displayedTotalUsageMb = computed(
+ () => props.packageRow?.real_total_mb ?? data.value?.total_usage_mb ?? 0
+ )
// 监听对话框打开,加载数据
watch(visible, async (newVal) => {
@@ -168,7 +185,7 @@
return
}
- filteredRecords.value = data.value.records.filter((record: any) => {
+ filteredRecords.value = data.value.records.filter((record) => {
return record.date === selectedDate.value
})
}
@@ -181,7 +198,7 @@
return
}
- filteredRecords.value = data.value.records.filter((record: any) => {
+ filteredRecords.value = data.value.records.filter((record) => {
return record.date.startsWith(selectedMonth.value)
})
}
diff --git a/src/views/asset-management/asset-information/composables/useAssetInfo.ts b/src/views/asset-management/asset-information/composables/useAssetInfo.ts
index af2983a..4f9164f 100644
--- a/src/views/asset-management/asset-information/composables/useAssetInfo.ts
+++ b/src/views/asset-management/asset-information/composables/useAssetInfo.ts
@@ -20,6 +20,12 @@ type TrafficDisplaySource = {
enable_virtual_data?: boolean | null
}
+const NULLABLE_REALTIME_CARD_FIELDS = new Set([
+ 'last_data_check_at',
+ 'last_real_name_check_at',
+ 'last_card_status_check_at'
+])
+
/**
* 格式化数据大小(MB -> GB/MB)
*/
@@ -54,7 +60,7 @@ const mergeAssetBoundCards = (
const mergedCard = { ...existingCard } as unknown as Record
for (const [key, value] of Object.entries(realtimeCard)) {
- if (value !== null && value !== undefined) {
+ if (value !== undefined && (value !== null || NULLABLE_REALTIME_CARD_FIELDS.has(key))) {
mergedCard[key] = value
}
}
@@ -304,6 +310,15 @@ export function useAssetInfo() {
if (data.last_sync_time !== undefined) {
cardInfo.value.last_sync_time = data.last_sync_time
}
+ if (data.last_data_check_at !== undefined) {
+ cardInfo.value.last_data_check_at = data.last_data_check_at
+ }
+ if (data.last_real_name_check_at !== undefined) {
+ cardInfo.value.last_real_name_check_at = data.last_real_name_check_at
+ }
+ if (data.last_card_status_check_at !== undefined) {
+ cardInfo.value.last_card_status_check_at = data.last_card_status_check_at
+ }
if (data.current_month_usage_mb !== undefined) {
cardInfo.value.current_month_usage_mb = data.current_month_usage_mb
}
@@ -320,6 +335,15 @@ export function useAssetInfo() {
// 仅用实时接口中非 null/undefined 的字段覆盖,避免清掉 resolve 接口返回的静态数据
cardInfo.value.cards = mergeAssetBoundCards(cardInfo.value.cards || [], data.cards)
}
+ if (data.last_data_check_at !== undefined) {
+ cardInfo.value.last_data_check_at = data.last_data_check_at
+ }
+ if (data.last_real_name_check_at !== undefined) {
+ cardInfo.value.last_real_name_check_at = data.last_real_name_check_at
+ }
+ if (data.last_card_status_check_at !== undefined) {
+ cardInfo.value.last_card_status_check_at = data.last_card_status_check_at
+ }
if (data.online_status !== undefined) {
cardInfo.value.online_status = data.online_status
}
diff --git a/src/views/asset-management/asset-information/index.vue b/src/views/asset-management/asset-information/index.vue
index 89b4e90..1c5c169 100644
--- a/src/views/asset-management/asset-information/index.vue
+++ b/src/views/asset-management/asset-information/index.vue
@@ -137,6 +137,7 @@
(null)
+ const selectedPackageRow = ref(null)
// 绑定卡实名状态更新
const bindingCardRealnameStatusDialogVisible = ref(false)
@@ -610,9 +612,10 @@
/**
* 显示流量详单
*/
- const handleShowDailyRecords = (payload: { packageRow: any }) => {
+ const handleShowDailyRecords = (payload: { packageRow: PackageInfo }) => {
const { packageRow } = payload
- selectedPackageUsageId.value = packageRow.package_usage_id
+ selectedPackageUsageId.value = packageRow.package_usage_id ?? packageRow.id
+ selectedPackageRow.value = packageRow
dailyRecordsDialogVisible.value = true
}
diff --git a/src/views/asset-management/asset-information/types.ts b/src/views/asset-management/asset-information/types.ts
index 1750ed0..d674621 100644
--- a/src/views/asset-management/asset-information/types.ts
+++ b/src/views/asset-management/asset-information/types.ts
@@ -29,6 +29,10 @@ export interface AssetInfo {
cards?: BindingCard[]
status?: number
gateway_extend?: string
+ last_sync_time?: string | null
+ last_data_check_at?: string | null
+ last_real_name_check_at?: string | null
+ last_card_status_check_at?: string | null
}
// 设备绑定卡信息
@@ -45,6 +49,9 @@ export interface BindingCard {
real_name_status?: number
realname_policy?: string
gateway_extend?: string
+ last_data_check_at?: string | null
+ last_real_name_check_at?: string | null
+ last_card_status_check_at?: string | null
}
// 设备实时信息接口
@@ -99,7 +106,9 @@ export interface DeviceRealtimeInfo {
// 套餐信息接口
export interface PackageInfo {
id: number
+ package_usage_id?: number
package_id: number
+ order_id?: number
package_name: string
package_price: number
paid_amount?: number
@@ -114,6 +123,7 @@ export interface PackageInfo {
status: number
status_name?: string
duration_days?: number
+ data_usage_mb?: number
reduction_pct?: number // 展示增幅比例
package_type?: string // 套餐类型: formal(正式套餐)/ addon(加油包)
enable_virtual_data?: boolean // 是否启用虚流量
diff --git a/src/views/asset-management/device-list/index.vue b/src/views/asset-management/device-list/index.vue
index 71427ab..a46a213 100644
--- a/src/views/asset-management/device-list/index.vue
+++ b/src/views/asset-management/device-list/index.vue
@@ -243,6 +243,15 @@
+
+ 共分配{{ seriesBindingRangeCountText }}台设备
+