124 lines
4.0 KiB
TypeScript
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
|
|
}
|