Files
one-pipe-system/src/api/modules/asset.ts
2026-09-08 16:39:29 +08:00

309 lines
9.7 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.
/**
* 资产管理 API 服务
* 对应文档asset-detail-refactor-api-changes.md
*/
import { BaseService } from '../BaseService'
import {
assertAssetActionAllowed,
markAssetActionCalled,
type AssetRateLimitedAction
} from '@/utils/business/apiRateLimit'
import type {
BaseResponse,
AssetResolveParams,
AssetResolveResponse,
AssetRealtimeStatusResponse,
AssetRefreshResponse,
AssetPackageListResponse,
AssetPackageParams,
AssetCurrentPackageResponse,
DeviceStopResponse,
AssetStartResponse,
AssetWalletTransactionListResponse,
AssetWalletTransactionParams,
AssetWalletResponse,
AssetOrdersParams,
AssetOrdersResponse,
UpdateAssetRealnameStatusRequest,
DtoUpdateAssetRealnameStatusResponse,
AssetPackageUsageRecord,
UpdateAssetPackageUsedDataRequest,
UpdateAssetPackageExpiresAtRequest,
ExpiringAssetListResponse,
ExpiringAssetQueryParams
} from '@/types/api'
const runRateLimitedAssetAction = async <T>(
action: Exclude<AssetRateLimitedAction, 'refresh'>,
identifier: string,
request: () => Promise<T>
): Promise<T> => {
assertAssetActionAllowed(action, identifier)
markAssetActionCalled(action, identifier)
return request()
}
export class AssetService extends BaseService {
/**
* 获取管理端临期资产列表
* GET /api/admin/expiring-assets
*/
static getExpiringAssets(
params?: ExpiringAssetQueryParams
): Promise<BaseResponse<ExpiringAssetListResponse>> {
return this.get<BaseResponse<ExpiringAssetListResponse>>('/api/admin/expiring-assets', params)
}
/**
* 通过任意标识符查询设备或卡的完整详情
* 支持虚拟号、ICCID、IMEI、SN、MSISDN
* GET /api/admin/assets/resolve/:identifier
* @param identifier 资产标识符虚拟号、ICCID、IMEI、SN、MSISDN
* @param params 查询参数
*/
static resolveAsset(
identifier: string,
params?: AssetResolveParams,
config?: Record<string, any>
): Promise<BaseResponse<AssetResolveResponse>> {
return this.getOne<AssetResolveResponse>(
`/api/admin/assets/resolve/${identifier}`,
params,
config
)
}
/**
* 读取资产实时状态(直接读 DB/Redis不调网关
* GET /api/admin/assets/:identifier/realtime-status
* @param identifier 资产标识符ICCID 或 VirtualNo
*/
static getRealtimeStatus(identifier: string): Promise<BaseResponse<AssetRealtimeStatusResponse>> {
return this.getOne<AssetRealtimeStatusResponse>(
`/api/admin/assets/${identifier}/realtime-status`,
undefined,
{
requestOptions: {
show404Error: false // 404时不显示错误提示
}
}
)
}
/**
* 主动调网关拉取最新数据后返回
* POST /api/admin/assets/:identifier/refresh
* @param identifier 资产标识符ICCID 或 VirtualNo
*/
static refreshAsset(identifier: string): Promise<BaseResponse<AssetRefreshResponse>> {
return this.post<BaseResponse<AssetRefreshResponse>>(
`/api/admin/assets/${identifier}/refresh`,
{},
{ timeout: 60000 }
)
}
/**
* 查询该资产的历史套餐关系组(主套餐—加油包,分页)
* total 仅统计顶层关系组,子项由后端随父项一起返回。
* GET /api/admin/assets/:identifier/packages?page=1&page_size=50
* @param identifier 资产标识符ICCID 或 VirtualNo
* @param params 查询参数(可选分页参数)
*/
static getAssetPackages(
identifier: string,
params?: AssetPackageParams
): Promise<BaseResponse<AssetPackageListResponse>> {
return this.get<BaseResponse<AssetPackageListResponse>>(
`/api/admin/assets/${identifier}/packages`,
params
)
}
/**
* 查询当前生效中的主套餐
* GET /api/admin/assets/:identifier/current-package
* 无生效套餐时返回 404
* @param identifier 资产标识符ICCID 或 VirtualNo
*/
static getCurrentPackage(identifier: string): Promise<BaseResponse<AssetCurrentPackageResponse>> {
return this.getOne<AssetCurrentPackageResponse>(
`/api/admin/assets/${identifier}/current-package`,
undefined,
{
requestOptions: {
show404Error: false // 404时不显示错误提示
}
}
)
}
/**
* 修改套餐真实已用量
* PATCH /api/admin/assets/:identifier/packages/:package_usage_id/used-data
*/
static updateAssetPackageUsedData(
identifier: string,
packageUsageId: number,
data: UpdateAssetPackageUsedDataRequest
): Promise<BaseResponse<AssetPackageUsageRecord>> {
return this.patch<BaseResponse<AssetPackageUsageRecord>>(
`/api/admin/assets/${identifier}/packages/${packageUsageId}/used-data`,
data as Record<string, any>
)
}
/**
* 修改套餐过期时间
* PATCH /api/admin/assets/:identifier/packages/:package_usage_id/expires-at
*/
static updateAssetPackageExpiresAt(
identifier: string,
packageUsageId: number,
data: UpdateAssetPackageExpiresAtRequest
): Promise<BaseResponse<AssetPackageUsageRecord>> {
return this.patch<BaseResponse<AssetPackageUsageRecord>>(
`/api/admin/assets/${identifier}/packages/${packageUsageId}/expires-at`,
data as Record<string, any>
)
}
// ========== 资产停复机操作(统一接口)==========
/**
* 停机资产(卡或设备)
* POST /api/admin/assets/:identifier/stop
* 停机成功后设置 1 小时停机保护期(保护期内禁止复机)
* @param identifier 资产标识符ICCID 或 VirtualNo
*/
static stopAsset(identifier: string): Promise<BaseResponse<DeviceStopResponse | void>> {
return runRateLimitedAssetAction('stop', identifier, () =>
this.post<BaseResponse<DeviceStopResponse | void>>(`/api/admin/assets/${identifier}/stop`, {})
)
}
/**
* 复机资产(卡或设备)
* POST /api/admin/assets/:identifier/start
* 前端按资产标识限制 5 分钟内只能调用一次
* @param identifier 资产标识符ICCID 或 VirtualNo
*/
static startAsset(
identifier: string,
config?: Record<string, any>
): Promise<BaseResponse<AssetStartResponse>> {
return runRateLimitedAssetAction('start', identifier, () =>
this.post<BaseResponse<AssetStartResponse>>(
`/api/admin/assets/${identifier}/start`,
{},
config
)
)
}
// ========== 资产停用 ==========
/**
* 手动停用资产(卡或设备)
* PATCH /api/admin/assets/:identifier/deactivate
* @param identifier 资产标识符ICCID 或 VirtualNo
*/
static deactivateAsset(identifier: string): Promise<BaseResponse> {
return this.patch<BaseResponse>(`/api/admin/assets/${identifier}/deactivate`, {})
}
// ========== 钱包查询 ==========
/**
* 查询指定卡或设备的钱包余额概况
* GET /api/admin/assets/:identifier/wallet
* 企业账号禁止调用
* @param identifier 资产标识符ICCID 或 VirtualNo
*/
static getAssetWallet(identifier: string): Promise<BaseResponse<AssetWalletResponse>> {
return this.getOne<AssetWalletResponse>(`/api/admin/assets/${identifier}/wallet`, undefined, {
requestOptions: {
show404Error: false // 404时不显示错误提示
}
})
}
/**
* 分页查询指定资产的钱包收支流水
* GET /api/admin/assets/:identifier/wallet/transactions
* 企业账号禁止调用
* @param identifier 资产标识符ICCID 或 VirtualNo
* @param params 查询参数
*/
static getWalletTransactions(
identifier: string,
params?: AssetWalletTransactionParams
): Promise<BaseResponse<AssetWalletTransactionListResponse>> {
return this.get<BaseResponse<AssetWalletTransactionListResponse>>(
`/api/admin/assets/${identifier}/wallet/transactions`,
params
)
}
// ========== 轮询状态更新 ==========
/**
* 更新资产轮询状态
* PATCH /api/admin/assets/:identifier/polling-status
* @param identifier 资产标识符ICCID 或 VirtualNo
* @param data 轮询状态数据
*/
static updatePollingStatus(
identifier: string,
data: { enable_polling: boolean }
): Promise<BaseResponse> {
return this.patch<BaseResponse>(`/api/admin/assets/${identifier}/polling-status`, data)
}
// ========== 资产历史订单 ==========
/**
* 查询资产历史订单
* GET /api/admin/assets/:identifier/orders
* @param identifier 资产标识符ICCID 或 VirtualNo
* @param params 查询参数
*/
static getAssetOrders(
identifier: string,
params?: AssetOrdersParams
): Promise<BaseResponse<AssetOrdersResponse>> {
return this.get<BaseResponse<AssetOrdersResponse>>(
`/api/admin/assets/${identifier}/orders`,
params
)
}
/**
* 更新资产实名认证策略
* PATCH /api/admin/assets/:identifier/realname-mode
* @param identifier 资产标识符ICCID 或 VirtualNo
* @param realname_policy 实名认证策略 (none:无需实名, before_order:先实名后充值/购买, after_order:先充值/购买后实名)
*/
static updateRealnamePolicy(identifier: string, realname_policy: string): Promise<BaseResponse> {
return this.patch<BaseResponse>(`/api/admin/assets/${identifier}/realname-mode`, {
realname_policy
})
}
/**
* 手动更新资产实名状态
* PATCH /api/admin/assets/:identifier/realname-status
* @param identifier 资产标识符ICCID 或 VirtualNo
* @param data 实名状态数据
*/
static updateRealnameStatus(
identifier: string,
data: UpdateAssetRealnameStatusRequest
): Promise<BaseResponse<DtoUpdateAssetRealnameStatusResponse>> {
return this.patch<BaseResponse<DtoUpdateAssetRealnameStatusResponse>>(
`/api/admin/assets/${identifier}/realname-status`,
data
)
}
}