Files
one-pipe-system/src/views/asset-management/asset-information/composables/useAssetInfo.ts
sexygoat b48d6a1894
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 4m9s
feat: 新增导入字段,显示实名认证策略字段
2026-04-17 18:40:54 +08:00

383 lines
14 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 资产信息数据管理 Composable
* 负责资产详情数据的加载和状态管理
*/
import { ref } from 'vue'
import { ElMessage } from 'element-plus'
import { AssetService } from '@/api/modules'
import type { AssetWalletResponse, DeviceGatewayInfo, AssetPackageUsageRecord } from '@/types/api'
/**
* 格式化数据大小(MB -> GB/MB)
*/
const formatDataSize = (mb: number) => {
if (mb >= 1024) {
return `${(mb / 1024).toFixed(2)}GB`
}
return `${mb.toFixed(2)}MB`
}
export function useAssetInfo() {
// 状态管理
const loading = ref(false)
const cardInfo = ref<any>(null) // 使用 any 以保持与原始实现一致
const deviceRealtime = ref<DeviceGatewayInfo | null>(null)
const currentPackage = ref<AssetPackageUsageRecord | null>(null)
const currentPackageLoading = ref(false)
const currentPackageErrorMsg = ref('')
const packageList = ref<AssetPackageUsageRecord[]>([])
const walletInfo = ref<AssetWalletResponse | null>(null)
const walletLoading = ref(false)
/**
* 获取资产详情
* @param identifier - 资产标识符(ICCID、IMEI、SN、虚拟号或MSISDN)
*/
const fetchAssetDetail = async (identifier: string) => {
try {
loading.value = true
const response = await AssetService.resolveAsset(identifier)
if (response.code === 0 && response.data) {
const data = response.data
// 获取资产标识符
const assetIdentifier = data.asset_type === 'card' ? data.iccid : data.virtual_no
// 映射API数据到页面显示格式
cardInfo.value = {
// 基本信息
asset_type: data.asset_type, // card 或 device
asset_id: data.asset_id,
identifier: assetIdentifier || '', // 资产标识符卡用iccid设备用virtual_no
virtual_no: data.virtual_no,
status: data.status,
batch_no: data.batch_no,
shop_id: data.shop_id,
shop_name: data.shop_name,
series_id: data.series_id,
series_name: data.series_name,
real_name_status: data.real_name_status,
realname_policy: data.realname_policy,
real_name_at: data.real_name_at,
activated_at: data.activated_at,
created_at: data.created_at,
updated_at: data.updated_at,
accumulated_recharge: data.accumulated_recharge,
first_commission_paid: data.first_commission_paid,
// 卡专属字段 (asset_type === 'card')
iccid: data.iccid || '',
msisdn: data.msisdn || '',
imsi: data.imsi || '',
carrier_id: data.carrier_id,
carrier_type: data.carrier_type || '',
carrier_name: data.carrier_name || '',
supplier: data.supplier || '',
network_status: data.network_status,
bound_device_id: data.bound_device_id,
bound_device_no: data.bound_device_no || '',
bound_device_name: data.bound_device_name || '',
card_category: data.card_category || '',
activation_status: data.activation_status,
enable_polling: data.enable_polling,
// 设备专属字段 (asset_type === 'device')
device_name: data.device_name || '',
device_model: data.device_model || '',
device_type: data.device_type || '',
manufacturer: data.manufacturer || '',
imei: data.imei || '',
sn: data.sn || '',
max_sim_slots: data.max_sim_slots || 0,
bound_card_count: data.bound_card_count || 0,
cards: data.cards || [],
device_protect_status: data.device_protect_status,
online_status: data.online_status,
last_online_time: data.last_online_time,
software_version: data.software_version,
switch_mode: data.switch_mode,
last_gateway_sync_at: data.last_gateway_sync_at,
// 流量/套餐信息
current_package: data.current_package || '',
packageSeries: data.series_name || '-',
packageTotalFlow: formatDataSize(data.package_total_mb || 0),
usedFlow: formatDataSize(data.package_used_mb || 0),
remainFlow: formatDataSize(data.package_remain_mb || 0),
usedFlowPercentage:
data.package_total_mb > 0
? `${((data.package_used_mb / data.package_total_mb) * 100).toFixed(2)}%`
: '0.00%',
packageList: [] // 套餐列表需要单独调用API获取
}
// 加载其他数据
if (assetIdentifier) {
// 并行调用多个接口: 当前生效套餐、实时状态、钱包概况
// 套餐列表不在这里调用,由父组件调用以便管理分页状态
await Promise.all([
loadCurrentPackage(assetIdentifier),
loadRealtimeStatus(assetIdentifier, data.asset_type),
loadAssetWallet(assetIdentifier)
])
}
} else {
ElMessage.error(response.msg || '查询失败')
cardInfo.value = null
}
} catch (error: any) {
cardInfo.value = null
} finally {
loading.value = false
}
}
/**
* 加载套餐列表
* @param identifier - 资产标识符
* @param page - 页码
* @param pageSize - 每页条数
*/
const loadPackageList = async (identifier: string, page: number = 1, pageSize: number = 10) => {
try {
const response = await AssetService.getAssetPackages(identifier, {
page,
page_size: pageSize
})
if (response.code === 0 && response.data) {
// 使用分页响应中的 items 数组
packageList.value = response.data.items || []
// 返回分页信息供外部使用
return {
items: response.data.items || [],
total: response.data.total || 0,
page: response.data.page || 1,
pageSize: response.data.page_size || pageSize
}
}
return { items: [], total: 0, page: 1, pageSize }
} catch (error) {
console.error('获取套餐列表失败:', error)
return { items: [], total: 0, page: 1, pageSize }
}
}
/**
* 加载当前生效套餐
* @param identifier - 资产标识符
*/
const loadCurrentPackage = async (identifier: string) => {
try {
currentPackageLoading.value = true
// 清空之前的错误信息
currentPackageErrorMsg.value = ''
const response = await AssetService.getCurrentPackage(identifier)
if (response.code === 0) {
if (response.data) {
const pkg = response.data
// 转换为组件期望的格式
currentPackage.value = {
id: pkg.package_usage_id || 0,
package_id: pkg.package_id || 0,
package_name: pkg.package_name || '',
package_price: 0, // API 没有返回价格
package_total_data: pkg.data_limit_mb || 0,
real_data_used: pkg.data_usage_mb || 0,
real_data_remaining: (pkg.data_limit_mb || 0) - (pkg.data_usage_mb || 0),
real_data_total: pkg.data_limit_mb || 0,
virtual_data_used: pkg.virtual_used_mb || 0,
virtual_data_remaining: pkg.virtual_remain_mb || 0,
virtual_data_total: pkg.virtual_limit_mb || 0,
start_time: pkg.activated_at || '',
expire_time: pkg.expires_at || '',
status: pkg.status || 0,
status_name: pkg.status_name,
duration_days: undefined, // API 没有返回时长
virtual_ratio: pkg.virtual_ratio, // 虚流量比例
package_type: pkg.package_type, // 套餐类型
enable_virtual_data: pkg.enable_virtual_data // 是否启用虚流量
}
// 同时更新 cardInfo 中的流量显示信息(根据是否启用虚流量选择数据源)
const useVirtual = pkg.enable_virtual_data
cardInfo.value.current_package = pkg.package_name
cardInfo.value.packageTotalFlow = formatDataSize(
useVirtual ? pkg.virtual_limit_mb || 0 : pkg.data_limit_mb || 0
)
cardInfo.value.usedFlow = formatDataSize(
useVirtual ? pkg.virtual_used_mb || 0 : pkg.data_usage_mb || 0
)
cardInfo.value.remainFlow = formatDataSize(
useVirtual
? pkg.virtual_remain_mb || 0
: (pkg.data_limit_mb || 0) - (pkg.data_usage_mb || 0)
)
const totalMb = useVirtual ? pkg.virtual_limit_mb || 0 : pkg.data_limit_mb || 0
const usedMb = useVirtual ? pkg.virtual_used_mb || 0 : pkg.data_usage_mb || 0
cardInfo.value.usedFlowPercentage =
totalMb > 0 ? `${((usedMb / totalMb) * 100).toFixed(2)}%` : '0.00%'
} else {
// code 为 0 但 data 为空,表示暂无当前生效套餐(正常情况)
currentPackage.value = null
currentPackageErrorMsg.value = ''
}
} else {
// 接口返回 code 不为 0,保存错误信息
currentPackage.value = null
currentPackageErrorMsg.value = response.msg || '获取当前套餐失败'
}
} catch (error: any) {
// 404表示无当前生效套餐,这是正常情况
currentPackage.value = null
if (error?.response?.status === 404) {
currentPackageErrorMsg.value = ''
} else {
console.error('获取当前套餐失败:', error)
currentPackageErrorMsg.value = error?.message || '获取当前套餐失败'
}
} finally {
currentPackageLoading.value = false
}
}
/**
* 加载实时状态
* @param identifier - 资产标识符
* @param assetType - 资产类型(card/device)
*/
const loadRealtimeStatus = async (identifier: string, assetType: string) => {
try {
const response = await AssetService.getRealtimeStatus(identifier)
if (response.code === 0 && response.data) {
const data = response.data
// 更新实时状态数据
if (assetType === 'card') {
// 卡的实时状态
if (data.network_status !== undefined) {
cardInfo.value.network_status = data.network_status
}
if (data.real_name_status !== undefined) {
cardInfo.value.real_name_status = data.real_name_status
}
if (data.last_sync_time !== undefined) {
cardInfo.value.last_sync_time = data.last_sync_time
}
if (data.current_month_usage_mb !== undefined) {
cardInfo.value.current_month_usage_mb = data.current_month_usage_mb
}
} else if (assetType === 'device') {
// 设备的实时状态
if (data.device_protect_status !== undefined) {
cardInfo.value.device_protect_status = data.device_protect_status
}
if (data.cards && data.cards.length > 0) {
// 合并实时卡数据与原始卡数据,保留 real_name_at 等静态字段
// 仅用实时接口中非 null/undefined 的字段覆盖,避免清掉 resolve 接口返回的静态数据
const existingCards: any[] = cardInfo.value.cards || []
cardInfo.value.cards = data.cards.map((realtimeCard: any) => {
const existing = existingCards.find((c: any) => c.iccid === realtimeCard.iccid)
if (!existing) return realtimeCard
const merged = { ...existing }
for (const [key, value] of Object.entries(realtimeCard)) {
if (value !== null && value !== undefined) {
merged[key] = value
}
}
return merged
})
}
if (data.online_status !== undefined) {
cardInfo.value.online_status = data.online_status
}
if (data.last_online_time !== undefined) {
cardInfo.value.last_online_time = data.last_online_time
}
if (data.software_version !== undefined) {
cardInfo.value.software_version = data.software_version
}
if (data.switch_mode !== undefined) {
cardInfo.value.switch_mode = data.switch_mode
}
if (data.last_gateway_sync_at !== undefined) {
cardInfo.value.last_gateway_sync_at = data.last_gateway_sync_at
}
// 设备实时信息(Gateway 数据)
if (data.device_realtime !== undefined) {
deviceRealtime.value = data.device_realtime
console.log('设备实时信息:', deviceRealtime.value)
}
}
}
} catch (error) {
console.error('获取实时状态失败:', error)
}
}
/**
* 加载钱包概况
* @param identifier - 资产标识符
*/
const loadAssetWallet = async (identifier: string) => {
try {
walletLoading.value = true
const response = await AssetService.getAssetWallet(identifier)
if (response.code === 0 && response.data) {
walletInfo.value = response.data
}
} catch (error: any) {
if (error?.response?.status === 403) {
// 企业账号禁止查看钱包信息,不显示错误
walletInfo.value = null
} else {
console.error('获取钱包概况失败:', error)
}
} finally {
walletLoading.value = false
}
}
/**
* 刷新资产数据(调用refresh接口后重新加载)
* @param identifier - 资产标识符
* @param assetType - 资产类型(card/device)
*/
const refreshAsset = async (identifier: string, assetType: string) => {
try {
await AssetService.refreshAsset(identifier)
ElMessage.success('刷新成功')
// 刷新成功后重新加载实时状态数据
if (identifier) {
await loadRealtimeStatus(identifier, assetType)
}
} catch (error: any) {
console.log(error)
}
}
return {
// State
loading,
cardInfo,
deviceRealtime,
currentPackage,
currentPackageLoading,
currentPackageErrorMsg,
packageList,
walletInfo,
walletLoading,
// Methods
fetchAssetDetail,
loadPackageList,
loadCurrentPackage,
loadRealtimeStatus,
loadAssetWallet,
refreshAsset
}
}