102 lines
2.5 KiB
TypeScript
102 lines
2.5 KiB
TypeScript
|
|
/**
|
|||
|
|
* 图片工具函数
|
|||
|
|
* 提供图片 URL 选择、格式检测等实用功能
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
import { PostImageDTO } from '../types';
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 图片显示模式
|
|||
|
|
*/
|
|||
|
|
export type ImageDisplayMode = 'list' | 'grid' | 'detail';
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 根据显示模式获取预览图 URL
|
|||
|
|
* @param image 图片对象
|
|||
|
|
* @param mode 显示模式
|
|||
|
|
* @returns 图片 URL
|
|||
|
|
*/
|
|||
|
|
export function getPreviewImageUrl(image: PostImageDTO, mode: ImageDisplayMode): string {
|
|||
|
|
// 如果没有预览图,返回原图
|
|||
|
|
if (!image) {
|
|||
|
|
return '';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
switch (mode) {
|
|||
|
|
case 'list':
|
|||
|
|
case 'grid':
|
|||
|
|
// 列表和网格模式使用普通预览图
|
|||
|
|
return image.preview_url || image.url || '';
|
|||
|
|
case 'detail':
|
|||
|
|
// 详情页使用大预览图
|
|||
|
|
return image.preview_url_large || image.preview_url || image.url || '';
|
|||
|
|
default:
|
|||
|
|
return image.url || '';
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 检测 WebP 支持并构建 Accept header
|
|||
|
|
* @returns Accept header 字符串
|
|||
|
|
*/
|
|||
|
|
export function getImageAcceptHeader(): string {
|
|||
|
|
// 检测浏览器是否支持 WebP
|
|||
|
|
// 如果支持,优先请求 WebP
|
|||
|
|
return 'image/webp,image/apng,image/*,*/*;q=0.8';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 判断是否应该使用预览图
|
|||
|
|
* @param mode 显示模式
|
|||
|
|
* @param hasPreview 是否有预览图
|
|||
|
|
* @returns 是否使用预览图
|
|||
|
|
*/
|
|||
|
|
export function shouldUsePreview(mode: ImageDisplayMode, hasPreview: boolean): boolean {
|
|||
|
|
// 列表和网格模式优先使用预览图
|
|||
|
|
if (mode === 'list' || mode === 'grid') {
|
|||
|
|
return hasPreview;
|
|||
|
|
}
|
|||
|
|
// 详情页也使用预览图,但点击后加载原图
|
|||
|
|
if (mode === 'detail') {
|
|||
|
|
return hasPreview;
|
|||
|
|
}
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 从图片 URL 提取文件扩展名
|
|||
|
|
* @param url 图片 URL
|
|||
|
|
* @returns 文件扩展名(如 '.jpg')
|
|||
|
|
*/
|
|||
|
|
export function getImageExtension(url: string): string {
|
|||
|
|
if (!url) return '';
|
|||
|
|
try {
|
|||
|
|
const urlObj = new URL(url);
|
|||
|
|
const pathname = urlObj.pathname;
|
|||
|
|
const ext = pathname.match(/\.[0-9a-z]+$/i);
|
|||
|
|
return ext ? ext[0].toLowerCase() : '';
|
|||
|
|
} catch {
|
|||
|
|
// 如果 URL 解析失败,直接从字符串匹配
|
|||
|
|
const match = url.match(/\.[0-9a-z]+$/i);
|
|||
|
|
return match ? match[0].toLowerCase() : '';
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 判断是否是 GIF 图片
|
|||
|
|
* @param url 图片 URL
|
|||
|
|
* @returns 是否是 GIF
|
|||
|
|
*/
|
|||
|
|
export function isGifImage(url: string): boolean {
|
|||
|
|
return getImageExtension(url) === '.gif';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 判断是否是 WebP 图片
|
|||
|
|
* @param url 图片 URL
|
|||
|
|
* @returns 是否是 WebP
|
|||
|
|
*/
|
|||
|
|
export function isWebPImage(url: string): boolean {
|
|||
|
|
return getImageExtension(url) === '.webp';
|
|||
|
|
}
|