项目中心-支付模块

This commit is contained in:
wangzzpeng
2026-09-30 08:04:16 +08:00
parent 6b88c3805f
commit ce8210fb3f
35 changed files with 2618 additions and 175 deletions

52
src/utils/filePreview.ts Normal file
View File

@@ -0,0 +1,52 @@
/**
* 预览类型判定(纯函数,无副作用,便于单测与复用)。
*
* <p>为什么集中在一个文件:前端多处 `FileList` 预览都按「后缀 → 渲染方式」分流,
* 统一这里避免每个页面各写一套正则 / 后缀表。后端同源预览端点(`/web/workOrderDraft/preview/{ossId}`)
* 按后缀纠正 Content-Type,这里与之后端口径保持一致的归类。</p>
*/
export type PreviewKind = 'image' | 'pdf' | 'video' | 'audio' | 'text' | 'unsupported'
const IMAGE_SUFFIXES = ['png', 'jpg', 'jpeg', 'gif', 'bmp', 'webp']
const PDF_SUFFIXES = ['pdf']
const VIDEO_SUFFIXES = ['mp4', 'webm', 'mov', 'avi', 'm4v']
const AUDIO_SUFFIXES = ['mp3', 'wav', 'ogg', 'm4a']
// 文本类:含 html/htm/svg —— 统一按纯文本展示源码,避免内联渲染触发存储型 XSS
const TEXT_SUFFIXES = ['txt', 'sql', 'log', 'csv', 'json', 'xml', 'md', 'yml', 'yaml', 'html', 'htm', 'svg']
/** 取小写字尾(不含点);无点返回空串 */
export function getSuffix(name: string): string {
const idx = name.lastIndexOf('.')
return idx >= 0 ? name.slice(idx + 1).toLowerCase() : ''
}
/** 按文件名判定预览类型;office / 未知后缀一律 unsupported(前端不内联,给下载) */
export function resolvePreviewKind(name: string): PreviewKind {
const ext = getSuffix(name)
if (IMAGE_SUFFIXES.includes(ext)) return 'image'
if (PDF_SUFFIXES.includes(ext)) return 'pdf'
if (VIDEO_SUFFIXES.includes(ext)) return 'video'
if (AUDIO_SUFFIXES.includes(ext)) return 'audio'
if (TEXT_SUFFIXES.includes(ext)) return 'text'
return 'unsupported'
}
/** 是否可被前端内联预览(true = image/pdf/video/audio/text) */
export function isPreviewable(name: string): boolean {
return resolvePreviewKind(name) !== 'unsupported'
}
/**
* 文本内联预览上限(1MB)。
* 整文件塞进 `<pre>` 会卡死浏览器(如 5MB+ 的 .sql/.log),故只读取前 1MB 渲染,超出截断并提示下载。
*/
export const PREVIEW_TEXT_MAX_BYTES = 1024 * 1024
/** 人类可读体积(B/KB/MB/GB) */
export function formatBytes(bytes: number): string {
if (!bytes || bytes < 0) return '0 B'
const units = ['B', 'KB', 'MB', 'GB']
const i = Math.min(units.length - 1, Math.floor(Math.log(bytes) / Math.log(1024)))
const val = bytes / Math.pow(1024, i)
return `${i === 0 ? val : val.toFixed(1)} ${units[i]}`
}