All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 4m12s
309 lines
9.7 KiB
TypeScript
309 lines
9.7 KiB
TypeScript
/**
|
||
* 资产管理 API 服务
|
||
* 对应文档:asset-detail-refactor-api-changes.md
|
||
*/
|
||
|
||
import { BaseService } from '../BaseService'
|
||
import {
|
||
assertAssetActionAllowed,
|
||
markAssetActionCalled,
|
||
type AssetRateLimitedAction
|
||
} from '@/utils/business/apiRateLimit'
|
||
import type {
|
||
BaseResponse,
|
||
AssetResolveResponse,
|
||
AssetRealtimeStatusResponse,
|
||
AssetRefreshResponse,
|
||
AssetPackageListResponse,
|
||
AssetPackageParams,
|
||
AssetCurrentPackageResponse,
|
||
DeviceStopResponse,
|
||
AssetWalletTransactionListResponse,
|
||
AssetWalletTransactionParams,
|
||
AssetWalletResponse,
|
||
AssetOrdersParams,
|
||
AssetOrdersResponse,
|
||
UpdateAssetRealnameStatusRequest,
|
||
DtoUpdateAssetRealnameStatusResponse,
|
||
AssetOperationLogsResponse,
|
||
AssetOperationLogsParams,
|
||
AssetPackageUsageRecord,
|
||
UpdateAssetPackageUsedDataRequest,
|
||
UpdateAssetPackageExpiresAtRequest
|
||
} from '@/types/api'
|
||
|
||
const runRateLimitedAssetAction = async <T>(
|
||
action: AssetRateLimitedAction,
|
||
identifier: string,
|
||
request: () => Promise<T>
|
||
): Promise<T> => {
|
||
assertAssetActionAllowed(action, identifier)
|
||
markAssetActionCalled(action, identifier)
|
||
const response = await request()
|
||
return response
|
||
}
|
||
|
||
export class AssetService extends BaseService {
|
||
/**
|
||
* 通过任意标识符查询设备或卡的完整详情
|
||
* 支持虚拟号、ICCID、IMEI、SN、MSISDN
|
||
* GET /api/admin/assets/resolve/:identifier
|
||
* @param identifier 资产标识符(虚拟号、ICCID、IMEI、SN、MSISDN)
|
||
*/
|
||
static resolveAsset(identifier: string): Promise<BaseResponse<AssetResolveResponse>> {
|
||
return this.getOne<AssetResolveResponse>(`/api/admin/assets/resolve/${identifier}`)
|
||
}
|
||
|
||
/**
|
||
* 读取资产实时状态(直接读 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
|
||
* 前端按资产标识限制 5 分钟内只能调用一次
|
||
* @param identifier 资产标识符(ICCID 或 VirtualNo)
|
||
*/
|
||
static refreshAsset(identifier: string): Promise<BaseResponse<AssetRefreshResponse>> {
|
||
return runRateLimitedAssetAction('refresh', identifier, () =>
|
||
this.post<BaseResponse<AssetRefreshResponse>>(
|
||
`/api/admin/assets/${identifier}/refresh`,
|
||
{},
|
||
{ timeout: 60000 }
|
||
)
|
||
)
|
||
}
|
||
|
||
/**
|
||
* 查询该资产所有套餐记录,含虚流量换算字段(分页)
|
||
* 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,
|
||
{
|
||
requestOptions: {
|
||
show404Error: false // 404时不显示错误提示
|
||
}
|
||
}
|
||
)
|
||
}
|
||
|
||
/**
|
||
* 查询当前生效中的主套餐
|
||
* 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 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): Promise<BaseResponse<void>> {
|
||
return runRateLimitedAssetAction('start', identifier, () =>
|
||
this.post<BaseResponse<void>>(`/api/admin/assets/${identifier}/start`, {})
|
||
)
|
||
}
|
||
|
||
// ========== 资产停用 ==========
|
||
|
||
/**
|
||
* 手动停用资产(卡或设备)
|
||
* 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
|
||
)
|
||
}
|
||
|
||
// ========== 资产操作审计日志 ==========
|
||
|
||
/**
|
||
* 查询资产操作审计日志
|
||
* GET /api/admin/assets/:identifier/operation-logs
|
||
* @param identifier 资产标识符
|
||
* @param params 查询参数
|
||
*/
|
||
static getOperationLogs(
|
||
identifier: string,
|
||
params?: AssetOperationLogsParams
|
||
): Promise<BaseResponse<AssetOperationLogsResponse>> {
|
||
return this.get<BaseResponse<AssetOperationLogsResponse>>(
|
||
`/api/admin/assets/${identifier}/operation-logs`,
|
||
params
|
||
)
|
||
}
|
||
}
|