Files
shanxia2.0/web-admin/src/utils/bx/attachment.ts
T
2026-08-08 20:43:48 +08:00

124 lines
4.0 KiB
TypeScript

import { attachmentApi, type BxId } from '@/api/bx'
import { ElMessage } from 'element-plus'
export type BxAttachmentItem = {
id: number | string
fileName: string
fileType?: string
fileSize?: number
previewUrl?: string
_uploading?: boolean
_existing?: boolean
}
const IMAGE_EXT = /\.(png|jpe?g|gif|webp|bmp|svg)$/i
const VIDEO_EXT = /\.(mp4|webm|ogg|mov|avi)$/i
const PDF_EXT = /\.pdf$/i
export function isBxImageFile(file: { fileName?: string; fileType?: string }) {
const name = String(file.fileName || '').toLowerCase()
const type = String(file.fileType || '').toLowerCase()
return type.startsWith('image/') || IMAGE_EXT.test(name)
}
export function isBxVideoFile(file: { fileName?: string; fileType?: string }) {
const name = String(file.fileName || '').toLowerCase()
const type = String(file.fileType || '').toLowerCase()
return type.startsWith('video/') || VIDEO_EXT.test(name)
}
export function isBxPdfFile(file: { fileName?: string; fileType?: string }) {
const name = String(file.fileName || '').toLowerCase()
const type = String(file.fileType || '').toLowerCase()
return type === 'application/pdf' || type.includes('pdf') || PDF_EXT.test(name)
}
export function canBxPreview(file: BxAttachmentItem) {
if (file._uploading) return false
return isBxImageFile(file) || isBxVideoFile(file) || isBxPdfFile(file)
}
export async function fillBxAttachmentPreviews(
files: Array<BxAttachmentItem & { attachmentId?: number | string }>
) {
const tasks = files
.filter((file) => isBxImageFile(file) && !file.previewUrl)
.map(async (file) => {
const id = file.id ?? file.attachmentId
if (id == null || id === '') return
try {
const res: any = await attachmentApi.preview(id)
file.previewUrl = res.data?.url || ''
} catch {
/* preview optional */
}
})
await Promise.all(tasks)
}
export async function loadBxAttachments(bizType: string, bizId: BxId): Promise<BxAttachmentItem[]> {
const res: any = await attachmentApi.listByBiz(bizType, bizId)
const files: BxAttachmentItem[] = (res.data || []).map((item: any) => ({
id: item.id,
fileName: item.fileName,
fileType: item.fileType || '',
fileSize: item.fileSize,
previewUrl: '',
_existing: true
}))
await fillBxAttachmentPreviews(files)
return files
}
export async function downloadBxAttachment(file: { id: number | string; fileName: string }) {
try {
const res: any = await attachmentApi.download(file.id)
const blob = new Blob([res], { type: 'application/octet-stream' })
const url = URL.createObjectURL(blob)
const anchor = document.createElement('a')
anchor.href = url
anchor.download = file.fileName
anchor.click()
URL.revokeObjectURL(url)
} catch (error: any) {
ElMessage.error(error?.message || '下载失败')
throw error
}
}
export async function previewBxAttachment(file: BxAttachmentItem) {
if (isBxVideoFile(file)) {
try {
const res: any = await attachmentApi.preview(file.id)
return { type: 'video' as const, url: res.data?.url || '', fileName: file.fileName }
} catch (error: any) {
ElMessage.error(error?.message || '预览失败')
throw error
}
}
if (isBxImageFile(file)) {
if (file.previewUrl) {
return { type: 'image' as const, url: file.previewUrl, fileName: file.fileName }
}
try {
const res: any = await attachmentApi.preview(file.id)
file.previewUrl = res.data?.url || ''
return { type: 'image' as const, url: file.previewUrl, fileName: file.fileName }
} catch (error: any) {
ElMessage.error(error?.message || '预览失败')
throw error
}
}
if (isBxPdfFile(file)) {
try {
const res: any = await attachmentApi.preview(file.id)
return { type: 'pdf' as const, url: res.data?.url || '', fileName: file.fileName }
} catch (error: any) {
ElMessage.error(error?.message || '预览失败')
throw error
}
}
ElMessage.warning('该文件类型暂不支持在线预览,请使用下载查看')
return null
}