This commit is contained in:
46
src/api/modules/authorization.ts
Normal file
46
src/api/modules/authorization.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* 授权记录相关 API
|
||||
*/
|
||||
|
||||
import { BaseService } from '../BaseService'
|
||||
import type { BaseResponse, PaginationResponse } from '@/types/api'
|
||||
import type {
|
||||
AuthorizationItem,
|
||||
AuthorizationListParams,
|
||||
UpdateAuthorizationRemarkRequest
|
||||
} from '@/types/api/authorization'
|
||||
|
||||
export class AuthorizationService extends BaseService {
|
||||
/**
|
||||
* 获取授权记录列表
|
||||
* @param params 查询参数
|
||||
*/
|
||||
static getAuthorizations(
|
||||
params?: AuthorizationListParams
|
||||
): Promise<PaginationResponse<AuthorizationItem>> {
|
||||
return this.getPage<AuthorizationItem>('/api/admin/authorizations', params)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取授权记录详情
|
||||
* @param id 授权记录ID
|
||||
*/
|
||||
static getAuthorizationDetail(id: number): Promise<BaseResponse<AuthorizationItem>> {
|
||||
return this.getOne<AuthorizationItem>(`/api/admin/authorizations/${id}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改授权备注
|
||||
* @param id 授权记录ID
|
||||
* @param data 备注数据
|
||||
*/
|
||||
static updateAuthorizationRemark(
|
||||
id: number,
|
||||
data: UpdateAuthorizationRemarkRequest
|
||||
): Promise<BaseResponse<AuthorizationItem>> {
|
||||
return this.put<BaseResponse<AuthorizationItem>>(
|
||||
`/api/admin/authorizations/${id}/remark`,
|
||||
data
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -273,23 +273,18 @@ export class CardService extends BaseService {
|
||||
// ========== ICCID批量导入相关 ==========
|
||||
|
||||
/**
|
||||
* 批量导入ICCID
|
||||
* @param file Excel文件
|
||||
* @param carrier_id 运营商ID
|
||||
* @param batch_no 批次号(可选)
|
||||
* 批量导入ICCID(新版:使用 JSON 格式)
|
||||
* @param data 导入请求参数
|
||||
*/
|
||||
static importIotCards(
|
||||
file: File,
|
||||
carrier_id: number,
|
||||
static importIotCards(data: {
|
||||
carrier_id: number
|
||||
file_key: string
|
||||
batch_no?: string
|
||||
): Promise<BaseResponse> {
|
||||
const formData = new FormData()
|
||||
formData.append('file', file)
|
||||
formData.append('carrier_id', carrier_id.toString())
|
||||
if (batch_no) {
|
||||
formData.append('batch_no', batch_no)
|
||||
}
|
||||
return this.upload('/api/admin/iot-cards/import', file, { carrier_id, batch_no })
|
||||
}): Promise<BaseResponse<{ task_id: number; task_no: string; message: string }>> {
|
||||
return this.post<BaseResponse<{ task_id: number; task_no: string; message: string }>>(
|
||||
'/api/admin/iot-cards/import',
|
||||
data
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
149
src/api/modules/device.ts
Normal file
149
src/api/modules/device.ts
Normal file
@@ -0,0 +1,149 @@
|
||||
/**
|
||||
* 设备管理相关 API
|
||||
*/
|
||||
|
||||
import { BaseService } from '../BaseService'
|
||||
import type {
|
||||
Device,
|
||||
DeviceQueryParams,
|
||||
DeviceListResponse,
|
||||
DeviceCardsResponse,
|
||||
BindCardToDeviceRequest,
|
||||
BindCardToDeviceResponse,
|
||||
UnbindCardFromDeviceResponse,
|
||||
AllocateDevicesRequest,
|
||||
AllocateDevicesResponse,
|
||||
RecallDevicesRequest,
|
||||
RecallDevicesResponse,
|
||||
ImportDeviceRequest,
|
||||
ImportDeviceResponse,
|
||||
DeviceImportTaskQueryParams,
|
||||
DeviceImportTaskListResponse,
|
||||
DeviceImportTaskDetail,
|
||||
BaseResponse
|
||||
} from '@/types/api'
|
||||
|
||||
export class DeviceService extends BaseService {
|
||||
// ========== 设备基础管理 ==========
|
||||
|
||||
/**
|
||||
* 获取设备列表
|
||||
* @param params 查询参数
|
||||
*/
|
||||
static getDevices(params?: DeviceQueryParams): Promise<BaseResponse<DeviceListResponse>> {
|
||||
return this.get<BaseResponse<DeviceListResponse>>('/api/admin/devices', params)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取设备详情
|
||||
* @param id 设备ID
|
||||
*/
|
||||
static getDeviceById(id: number): Promise<BaseResponse<Device>> {
|
||||
return this.getOne<Device>(`/api/admin/devices/${id}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除设备
|
||||
* @param id 设备ID
|
||||
*/
|
||||
static deleteDevice(id: number): Promise<BaseResponse> {
|
||||
return this.remove(`/api/admin/devices/${id}`)
|
||||
}
|
||||
|
||||
// ========== 设备卡绑定管理 ==========
|
||||
|
||||
/**
|
||||
* 获取设备绑定的卡列表
|
||||
* @param id 设备ID
|
||||
*/
|
||||
static getDeviceCards(id: number): Promise<BaseResponse<DeviceCardsResponse>> {
|
||||
return this.getOne<DeviceCardsResponse>(`/api/admin/devices/${id}/cards`)
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定卡到设备
|
||||
* @param id 设备ID
|
||||
* @param data 绑定参数
|
||||
*/
|
||||
static bindCard(
|
||||
id: number,
|
||||
data: BindCardToDeviceRequest
|
||||
): Promise<BaseResponse<BindCardToDeviceResponse>> {
|
||||
return this.post<BaseResponse<BindCardToDeviceResponse>>(
|
||||
`/api/admin/devices/${id}/cards`,
|
||||
data
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 解绑设备上的卡
|
||||
* @param deviceId 设备ID
|
||||
* @param cardId IoT卡ID
|
||||
*/
|
||||
static unbindCard(
|
||||
deviceId: number,
|
||||
cardId: number
|
||||
): Promise<BaseResponse<UnbindCardFromDeviceResponse>> {
|
||||
return this.delete<BaseResponse<UnbindCardFromDeviceResponse>>(
|
||||
`/api/admin/devices/${deviceId}/cards/${cardId}`
|
||||
)
|
||||
}
|
||||
|
||||
// ========== 批量分配和回收 ==========
|
||||
|
||||
/**
|
||||
* 批量分配设备
|
||||
* @param data 分配参数
|
||||
*/
|
||||
static allocateDevices(
|
||||
data: AllocateDevicesRequest
|
||||
): Promise<BaseResponse<AllocateDevicesResponse>> {
|
||||
return this.post<BaseResponse<AllocateDevicesResponse>>(
|
||||
'/api/admin/devices/allocate',
|
||||
data
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量回收设备
|
||||
* @param data 回收参数
|
||||
*/
|
||||
static recallDevices(
|
||||
data: RecallDevicesRequest
|
||||
): Promise<BaseResponse<RecallDevicesResponse>> {
|
||||
return this.post<BaseResponse<RecallDevicesResponse>>('/api/admin/devices/recall', data)
|
||||
}
|
||||
|
||||
// ========== 设备导入 ==========
|
||||
|
||||
/**
|
||||
* 批量导入设备
|
||||
* @param data 导入参数
|
||||
*/
|
||||
static importDevices(
|
||||
data: ImportDeviceRequest
|
||||
): Promise<BaseResponse<ImportDeviceResponse>> {
|
||||
return this.post<BaseResponse<ImportDeviceResponse>>('/api/admin/devices/import', data)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取导入任务列表
|
||||
* @param params 查询参数
|
||||
*/
|
||||
static getImportTasks(
|
||||
params?: DeviceImportTaskQueryParams
|
||||
): Promise<BaseResponse<DeviceImportTaskListResponse>> {
|
||||
return this.get<BaseResponse<DeviceImportTaskListResponse>>(
|
||||
'/api/admin/devices/import/tasks',
|
||||
params
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取导入任务详情
|
||||
* @param id 任务ID
|
||||
*/
|
||||
static getImportTaskDetail(id: number): Promise<BaseResponse<DeviceImportTaskDetail>> {
|
||||
return this.getOne<DeviceImportTaskDetail>(`/api/admin/devices/import/tasks/${id}`)
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,16 @@ import type {
|
||||
UpdateEnterpriseStatusParams,
|
||||
CreateEnterpriseResponse
|
||||
} from '@/types/api/enterprise'
|
||||
import type {
|
||||
AllocateCardsRequest,
|
||||
AllocateCardsResponse,
|
||||
AllocateCardsPreviewRequest,
|
||||
AllocateCardsPreviewResponse,
|
||||
EnterpriseCardListParams,
|
||||
EnterpriseCardPageResult,
|
||||
RecallCardsRequest,
|
||||
RecallCardsResponse
|
||||
} from '@/types/api/enterpriseCard'
|
||||
|
||||
export class EnterpriseService extends BaseService {
|
||||
/**
|
||||
@@ -63,4 +73,88 @@ export class EnterpriseService extends BaseService {
|
||||
): Promise<BaseResponse> {
|
||||
return this.put<BaseResponse>(`/api/admin/enterprises/${id}/status`, data)
|
||||
}
|
||||
|
||||
// ========== 企业卡授权相关 ==========
|
||||
|
||||
/**
|
||||
* 授权卡给企业
|
||||
* @param enterpriseId 企业ID
|
||||
* @param data 授权请求数据
|
||||
*/
|
||||
static allocateCards(
|
||||
enterpriseId: number,
|
||||
data: AllocateCardsRequest
|
||||
): Promise<BaseResponse<AllocateCardsResponse>> {
|
||||
return this.post<BaseResponse<AllocateCardsResponse>>(
|
||||
`/api/admin/enterprises/${enterpriseId}/allocate-cards`,
|
||||
data
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 卡授权预检
|
||||
* @param enterpriseId 企业ID
|
||||
* @param data 预检请求数据
|
||||
*/
|
||||
static previewAllocateCards(
|
||||
enterpriseId: number,
|
||||
data: AllocateCardsPreviewRequest
|
||||
): Promise<BaseResponse<AllocateCardsPreviewResponse>> {
|
||||
return this.post<BaseResponse<AllocateCardsPreviewResponse>>(
|
||||
`/api/admin/enterprises/${enterpriseId}/allocate-cards/preview`,
|
||||
data
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取企业卡列表
|
||||
* @param enterpriseId 企业ID
|
||||
* @param params 查询参数
|
||||
*/
|
||||
static getEnterpriseCards(
|
||||
enterpriseId: number,
|
||||
params?: EnterpriseCardListParams
|
||||
): Promise<BaseResponse<EnterpriseCardPageResult>> {
|
||||
return this.get<BaseResponse<EnterpriseCardPageResult>>(
|
||||
`/api/admin/enterprises/${enterpriseId}/cards`,
|
||||
params
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 复机卡
|
||||
* @param enterpriseId 企业ID
|
||||
* @param cardId 卡ID
|
||||
*/
|
||||
static resumeCard(enterpriseId: number, cardId: number): Promise<BaseResponse> {
|
||||
return this.post<BaseResponse>(
|
||||
`/api/admin/enterprises/${enterpriseId}/cards/${cardId}/resume`
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 停机卡
|
||||
* @param enterpriseId 企业ID
|
||||
* @param cardId 卡ID
|
||||
*/
|
||||
static suspendCard(enterpriseId: number, cardId: number): Promise<BaseResponse> {
|
||||
return this.post<BaseResponse>(
|
||||
`/api/admin/enterprises/${enterpriseId}/cards/${cardId}/suspend`
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 回收卡授权
|
||||
* @param enterpriseId 企业ID
|
||||
* @param data 回收请求数据
|
||||
*/
|
||||
static recallCards(
|
||||
enterpriseId: number,
|
||||
data: RecallCardsRequest
|
||||
): Promise<BaseResponse<RecallCardsResponse>> {
|
||||
return this.post<BaseResponse<RecallCardsResponse>>(
|
||||
`/api/admin/enterprises/${enterpriseId}/recall-cards`,
|
||||
data
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,10 @@ export { CardService } from './card'
|
||||
export { CommissionService } from './commission'
|
||||
export { EnterpriseService } from './enterprise'
|
||||
export { CustomerAccountService } from './customerAccount'
|
||||
export { StorageService } from './storage'
|
||||
export { AuthorizationService } from './authorization'
|
||||
export { DeviceService } from './device'
|
||||
|
||||
// TODO: 按需添加其他业务模块
|
||||
// export { PackageService } from './package'
|
||||
// export { DeviceService } from './device'
|
||||
// export { SettingService } from './setting'
|
||||
|
||||
104
src/api/modules/storage.ts
Normal file
104
src/api/modules/storage.ts
Normal file
@@ -0,0 +1,104 @@
|
||||
/**
|
||||
* 对象存储相关 API
|
||||
*/
|
||||
|
||||
import { BaseService } from '../BaseService'
|
||||
import type { BaseResponse } from '@/types/api'
|
||||
|
||||
/**
|
||||
* 文件用途枚举
|
||||
*/
|
||||
export type FilePurpose = 'iot_import' | 'export' | 'attachment'
|
||||
|
||||
/**
|
||||
* 获取上传 URL 请求参数
|
||||
*/
|
||||
export interface GetUploadUrlRequest {
|
||||
/** 文件名(如:cards.csv) */
|
||||
file_name: string
|
||||
/** 文件 MIME 类型(如:text/csv),留空则自动推断 */
|
||||
content_type?: string
|
||||
/** 文件用途 (iot_import:ICCID导入, export:数据导出, attachment:附件) */
|
||||
purpose: FilePurpose
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取上传 URL 响应
|
||||
*/
|
||||
export interface GetUploadUrlResponse {
|
||||
/** 预签名上传 URL,使用 PUT 方法上传文件 */
|
||||
upload_url: string
|
||||
/** 文件路径标识,上传成功后用于调用业务接口 */
|
||||
file_key: string
|
||||
/** URL 有效期(秒) */
|
||||
expires_in: number
|
||||
}
|
||||
|
||||
export class StorageService extends BaseService {
|
||||
/**
|
||||
* 获取文件上传预签名 URL
|
||||
*
|
||||
* ## 完整上传流程
|
||||
* 1. 调用本接口获取预签名 URL 和 file_key
|
||||
* 2. 使用预签名 URL 上传文件(发起 PUT 请求直接上传到对象存储)
|
||||
* 3. 使用 file_key 调用相关业务接口
|
||||
*
|
||||
* @param data 请求参数
|
||||
*/
|
||||
static getUploadUrl(data: GetUploadUrlRequest): Promise<BaseResponse<GetUploadUrlResponse>> {
|
||||
return this.post<BaseResponse<GetUploadUrlResponse>>('/api/admin/storage/upload-url', data)
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用预签名 URL 上传文件到对象存储
|
||||
*
|
||||
* 注意事项:
|
||||
* - 预签名 URL 有效期 15 分钟,请及时使用
|
||||
* - 上传时 Content-Type 需与请求时一致
|
||||
* - file_key 在上传成功后永久有效
|
||||
*
|
||||
* @param uploadUrl 预签名 URL
|
||||
* @param file 文件
|
||||
* @param contentType 文件类型(需与 getUploadUrl 请求时保持一致)
|
||||
*/
|
||||
static async uploadFile(uploadUrl: string, file: File, contentType?: string): Promise<void> {
|
||||
try {
|
||||
// 在开发环境下,使用代理路径避免 CORS 问题
|
||||
let finalUrl = uploadUrl
|
||||
if (import.meta.env.DEV) {
|
||||
// 将对象存储的域名替换为代理路径
|
||||
// 例如:http://obs-helf.cucloud.cn/cmp/... -> /obs-proxy/cmp/...
|
||||
finalUrl = uploadUrl.replace(/^https?:\/\/obs-helf\.cucloud\.cn/, '/obs-proxy')
|
||||
}
|
||||
|
||||
const headers: Record<string, string> = {}
|
||||
|
||||
// 只有在明确指定 contentType 时才设置,否则让浏览器自动处理
|
||||
if (contentType) {
|
||||
headers['Content-Type'] = contentType
|
||||
}
|
||||
|
||||
const response = await fetch(finalUrl, {
|
||||
method: 'PUT',
|
||||
body: file,
|
||||
headers,
|
||||
mode: 'cors' // 明确指定 CORS 模式
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text().catch(() => response.statusText)
|
||||
throw new Error(`上传文件失败 (${response.status}): ${errorText}`)
|
||||
}
|
||||
} catch (error: any) {
|
||||
// 增强错误信息
|
||||
if (error.name === 'TypeError' && error.message.includes('Failed to fetch')) {
|
||||
throw new Error(
|
||||
'CORS 错误: 无法上传文件到对象存储。' +
|
||||
'这通常是因为对象存储服务器未正确配置 CORS 策略。' +
|
||||
'请联系后端开发人员检查对象存储的 CORS 配置。'
|
||||
)
|
||||
}
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user