feat: 新增运营商停机原因
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 4m44s

This commit is contained in:
sexygoat
2026-05-12 12:11:53 +08:00
parent 5d20d7dd3f
commit 471d1196b3
7 changed files with 147 additions and 15 deletions

View File

@@ -57,6 +57,7 @@ export interface AssetResolveResponse {
series_name: string // 套餐系列名称
real_name_status: RealNameStatus // 实名状态0 未实名 / 1 已实名
realname_policy?: string // 实名认证策略 (none:无需实名, before_order:先实名后充值/购买, after_order:先充值/购买后实名)
real_name_at?: string | null // 实名时间
network_status?: NetworkStatus // 网络状态0 停机 / 1 开机(仅 card
current_package: string // 当前套餐名称(无则空)
current_package_usage_id: number | null // 当前主套餐对应的套餐使用记录 ID无主套餐时为 null
@@ -86,6 +87,7 @@ export interface AssetResolveResponse {
supplier?: string // 供应商
activation_status?: number // 激活状态
enable_polling?: boolean // 是否参与轮询
gateway_extend?: string // Gateway 卡状态扩展字段,原样返回上游 extend
// ===== 设备专属字段 (asset_type === 'device' 时) =====
bound_card_count?: number // 绑定卡数量
@@ -117,6 +119,7 @@ export interface AssetBoundCard {
realname_policy?: string // 实名认证策略
slot_position: number // 插槽位置
is_current?: boolean // 是否为设备当前使用的卡
gateway_extend?: string // Gateway 卡状态扩展字段,原样返回上游 extend
}
// ========== 资产实时状态响应 ==========
@@ -199,6 +202,7 @@ export type AssetRefreshResponse = AssetRealtimeStatusResponse
* 对应接口GET /api/admin/assets/:asset_type/:id/packages
*/
export interface AssetPackageUsageRecord {
id?: number // 兼容前端当前映射字段
package_usage_id?: number // 套餐使用记录 ID
package_id?: number // 套餐 ID
package_name?: string // 套餐名称
@@ -209,8 +213,10 @@ export interface AssetPackageUsageRecord {
status_name?: string // 状态中文名
real_total_mb?: number // 真流量总量(百分比以此为基准)
real_used_mb?: number // 真流量已用
real_remaining_mb?: number // 兼容前端当前映射字段
virtual_total_mb?: number // 业务停机阈值
virtual_used_mb?: number // 展示已用量
virtual_remaining_mb?: number // 兼容前端当前映射字段
virtual_ratio?: number // 虚流量比例real/virtual
reduction_pct?: number // 展示增幅比例(小数,如 0.428571
enable_virtual_data?: boolean // 是否启用虚流量

View File

@@ -67,6 +67,10 @@
</ElTag>
</ElDescriptionsItem>
<ElDescriptionsItem label="运营商停机原因" :span="2">
<span class="gateway-extend-text">{{ cardInfo?.gateway_extend || '-' }}</span>
</ElDescriptionsItem>
<template v-if="cardInfo?.bound_device_id">
<ElDescriptionsItem label="绑定设备号">
<ElButton
@@ -160,7 +164,8 @@
</div>
</template>
</ElTableColumn>
<ElTableColumn prop="msisdn" label="MSISDN" min-width="120" />
<ElTableColumn prop="msisdn" label="MSISDN" min-width="150" showOverflowTooltip/>
<ElTableColumn prop="carrier_name" label="运营商" min-width="120" showOverflowTooltip />
<ElTableColumn prop="slot_position" label="卡槽位置" width="130">
<template #default="scope">
@@ -194,7 +199,12 @@
{{ scope.row.real_name_at ? formatDateTime(scope.row.real_name_at) : '-' }}
</template>
</ElTableColumn>
<ElTableColumn label="操作" width="180">
<ElTableColumn label="运营商停机原因" min-width="220" showOverflowTooltip>
<template #default="scope">
{{ scope.row.gateway_extend || '-' }}
</template>
</ElTableColumn>
<ElTableColumn label="操作" width="180" fixed="right">
<template #default="scope">
<!-- 根据网络状态显示启用或停用按钮 -->
<ElButton
@@ -437,6 +447,7 @@
real_name_status?: number
real_name_at?: string
realname_policy?: string
gateway_extend?: string
}
interface AssetInfo {
@@ -461,6 +472,7 @@
series_name?: string
real_name_at?: string
supplier?: string
gateway_extend?: string
bound_device_id?: number
bound_device_no?: string
bound_device_name?: string
@@ -690,6 +702,10 @@
<style scoped lang="scss">
.info-card {
&.basic-info {
.gateway-extend-text {
word-break: break-all;
}
.card-header {
display: flex;
align-items: center;

View File

@@ -6,7 +6,12 @@
import { ref } from 'vue'
import { ElMessage } from 'element-plus'
import { AssetService } from '@/api/modules'
import type { AssetWalletResponse, DeviceGatewayInfo, AssetPackageUsageRecord } from '@/types/api'
import type {
AssetBoundCard,
AssetWalletResponse,
DeviceGatewayInfo,
AssetPackageUsageRecord
} from '@/types/api'
type TrafficDisplaySource = {
real_total_mb?: number | null
@@ -39,6 +44,23 @@ const getDisplayedUsagePercentage = (traffic?: TrafficDisplaySource | null) => {
return totalMb > 0 ? `${((usedMb / totalMb) * 100).toFixed(2)}%` : '0.00%'
}
const mergeAssetBoundCards = (
existingCards: AssetBoundCard[] = [],
realtimeCards: AssetBoundCard[] = []
): AssetBoundCard[] =>
realtimeCards.map((realtimeCard) => {
const existingCard = existingCards.find((card) => card.iccid === realtimeCard.iccid)
if (!existingCard) return realtimeCard
const mergedCard = { ...existingCard } as unknown as Record<string, unknown>
for (const [key, value] of Object.entries(realtimeCard)) {
if (value !== null && value !== undefined) {
mergedCard[key] = value
}
}
return mergedCard as unknown as AssetBoundCard
})
export function useAssetInfo() {
// 状态管理
const loading = ref(false)
@@ -99,6 +121,7 @@ export function useAssetInfo() {
carrier_name: data.carrier_name || '',
supplier: data.supplier || '',
network_status: data.network_status,
gateway_extend: data.gateway_extend ?? '',
bound_device_id: data.bound_device_id,
bound_device_no: data.bound_device_no || '',
bound_device_name: data.bound_device_name || '',
@@ -293,18 +316,7 @@ export function useAssetInfo() {
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
})
cardInfo.value.cards = mergeAssetBoundCards(cardInfo.value.cards || [], data.cards)
}
if (data.online_status !== undefined) {
cardInfo.value.online_status = data.online_status

View File

@@ -27,6 +27,7 @@ export interface AssetInfo {
sn?: string
cards?: BindingCard[]
status?: number
gateway_extend?: string
}
// 设备绑定卡信息
@@ -42,6 +43,7 @@ export interface BindingCard {
network_status?: number
real_name_status?: number
realname_policy?: string
gateway_extend?: string
}
// 设备实时信息接口