feat: 文件下载
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 3m54s

This commit is contained in:
sexygoat
2026-04-30 18:04:01 +08:00
parent 81155fd8e4
commit 950520635d
19 changed files with 438 additions and 44 deletions

View File

@@ -21,7 +21,9 @@ import type {
ListResponse,
GatewayRealnameLinkResponse,
ImportIotCardRequest,
ImportIotCardResponse
ImportIotCardResponse,
IotCardImportTask,
IotCardImportTaskDetail
} from '@/types/api'
export class CardService extends BaseService {
@@ -296,7 +298,7 @@ export class CardService extends BaseService {
* 获取导入任务列表
* @param params 查询参数
*/
static getIotCardImportTasks(params?: any): Promise<PaginationResponse<any>> {
static getIotCardImportTasks(params?: any): Promise<PaginationResponse<IotCardImportTask>> {
return this.getPage('/api/admin/iot-cards/import-tasks', params)
}
@@ -304,8 +306,8 @@ export class CardService extends BaseService {
* 获取导入任务详情
* @param id 任务ID
*/
static getIotCardImportTaskDetail(id: number): Promise<BaseResponse<any>> {
return this.getOne(`/api/admin/iot-cards/import-tasks/${id}`)
static getIotCardImportTaskDetail(id: number): Promise<BaseResponse<IotCardImportTaskDetail>> {
return this.getOne<IotCardImportTaskDetail>(`/api/admin/iot-cards/import-tasks/${id}`)
}
// ========== 单卡列表(未绑定设备)相关 ==========

View File

@@ -5,6 +5,21 @@
import { BaseService } from '../BaseService'
import type { BaseResponse } from '@/types/api'
const inferFileNameFromKey = (fileKey: string) => {
return fileKey.split('/').pop() || 'download'
}
const triggerBrowserDownload = (downloadUrl: string, fileName: string) => {
const link = document.createElement('a')
link.href = downloadUrl
link.download = fileName
link.target = '_blank'
link.rel = 'noopener noreferrer'
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
}
/**
* 文件用途枚举
*/
@@ -132,4 +147,36 @@ export class StorageService extends BaseService {
data
)
}
/**
* 获取单文件下载 URL
* @param fileKey 文件路径标识
*/
static async getDownloadUrl(fileKey: string): Promise<string> {
const normalizedFileKey = fileKey.trim()
const res = await this.batchDownloadUrls({
file_keys: [normalizedFileKey]
})
if (res.code !== 0 || !res.data?.urls?.[normalizedFileKey]) {
throw new Error(res.msg || '获取下载地址失败')
}
return res.data.urls[normalizedFileKey]
}
/**
* 按文件标识直接触发浏览器下载
* @param fileKey 文件路径标识
* @param fileName 可选文件名
*/
static async downloadFileByKey(fileKey: string, fileName?: string): Promise<void> {
const normalizedFileKey = fileKey.trim()
if (!normalizedFileKey) {
throw new Error('文件标识不能为空')
}
const downloadUrl = await this.getDownloadUrl(normalizedFileKey)
triggerBrowserDownload(downloadUrl, fileName || inferFileNameFromKey(normalizedFileKey))
}
}