v4.0.15上传图片自动压缩
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { useState } from 'react';
|
||||
import { Button, Image, Input, Modal, Space, Upload, message } from 'antd';
|
||||
import { useState, type ReactNode } from 'react';
|
||||
import { Button, Image, Input, Modal, Space, Typography, Upload, message } from 'antd';
|
||||
import { EyeOutlined, FilePdfOutlined, UploadOutlined } from '@ant-design/icons';
|
||||
import type { UploadProps } from 'antd';
|
||||
import { uploadFileToOss, type OssMediaType, type UploadFileResult } from '../lib/upload';
|
||||
@@ -13,6 +13,7 @@ type OssUploadProps = {
|
||||
accept?: string;
|
||||
maxSizeMb?: number;
|
||||
placeholder?: string;
|
||||
uploadHint?: ReactNode;
|
||||
};
|
||||
|
||||
function isImageUrl(url: string) {
|
||||
@@ -23,6 +24,32 @@ function isPdfUrl(url: string) {
|
||||
return /\.pdf(\?|#|$)/i.test(url);
|
||||
}
|
||||
|
||||
function formatUploadImageMessage(result: UploadFileResult): string {
|
||||
const img = result.image;
|
||||
if (!img) return '上传成功';
|
||||
const sizeLabel = `${img.width}×${img.height}`;
|
||||
if (img.compressed && img.originalWidth && img.originalHeight) {
|
||||
const original = `${img.originalWidth}×${img.originalHeight}`;
|
||||
if (original !== sizeLabel) {
|
||||
return `上传成功(${sizeLabel},已由 ${original} 自动压缩)`;
|
||||
}
|
||||
}
|
||||
return `上传成功(${sizeLabel})`;
|
||||
}
|
||||
|
||||
function formatUploadImageHint(result: UploadFileResult): string | null {
|
||||
const img = result.image;
|
||||
if (!img) return null;
|
||||
const sizeLabel = `${img.width}×${img.height}`;
|
||||
if (img.compressed && img.originalWidth && img.originalHeight) {
|
||||
const original = `${img.originalWidth}×${img.originalHeight}`;
|
||||
if (original !== sizeLabel) {
|
||||
return `${sizeLabel}(已由 ${original} 自动压缩)`;
|
||||
}
|
||||
}
|
||||
return sizeLabel;
|
||||
}
|
||||
|
||||
export default function OssUpload({
|
||||
value,
|
||||
onChange,
|
||||
@@ -31,9 +58,11 @@ export default function OssUpload({
|
||||
mediaType = 'IMAGE',
|
||||
accept,
|
||||
placeholder = '上传后自动填入,或手动粘贴 URL',
|
||||
uploadHint,
|
||||
}: OssUploadProps) {
|
||||
const [uploading, setUploading] = useState(false);
|
||||
const [pdfPreviewOpen, setPdfPreviewOpen] = useState(false);
|
||||
const [imageMetaHint, setImageMetaHint] = useState<string | null>(null);
|
||||
|
||||
const resolvedAccept =
|
||||
accept ?? (mediaType === 'VIDEO' ? 'video/*' : mediaType === 'FILE' ? undefined : 'image/*');
|
||||
@@ -45,7 +74,9 @@ export default function OssUpload({
|
||||
const result = await uploadFileToOss(raw, { bizType, mediaType });
|
||||
onChange?.(result.url);
|
||||
onUploaded?.(result);
|
||||
message.success('上传成功');
|
||||
const successMessage = formatUploadImageMessage(result);
|
||||
setImageMetaHint(formatUploadImageHint(result));
|
||||
message.success(successMessage);
|
||||
onSuccess?.(result);
|
||||
} catch (e) {
|
||||
const err = e instanceof Error ? e : new Error('上传失败');
|
||||
@@ -116,6 +147,16 @@ export default function OssUpload({
|
||||
<video src={value} controls style={{ maxWidth: '100%', maxHeight: 160, borderRadius: 4 }} />
|
||||
)}
|
||||
{filePreview}
|
||||
{uploadHint ? (
|
||||
<Typography.Text type="secondary" style={{ fontSize: 12 }}>
|
||||
{uploadHint}
|
||||
</Typography.Text>
|
||||
) : null}
|
||||
{imageMetaHint ? (
|
||||
<Typography.Text type="secondary" style={{ fontSize: 12 }}>
|
||||
当前底图:{imageMetaHint}
|
||||
</Typography.Text>
|
||||
) : null}
|
||||
<Space wrap>
|
||||
<Upload
|
||||
accept={resolvedAccept}
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
DEFAULT_OSS_MAX_UPLOAD_BYTES,
|
||||
formatOssMaxSizeMb,
|
||||
} from '@dukang/shared-ui/compressImage';
|
||||
import type { OssUploadImageMeta } from '@dukang/shared-types';
|
||||
|
||||
export type OssMediaType = 'IMAGE' | 'VIDEO' | 'FILE';
|
||||
|
||||
@@ -12,6 +13,7 @@ export type UploadFileResult = {
|
||||
ossKey: string;
|
||||
bucket: string;
|
||||
mock: boolean;
|
||||
image?: OssUploadImageMeta;
|
||||
};
|
||||
|
||||
async function prepareUploadFile(file: File, mediaType: OssMediaType): Promise<File> {
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
import type { ColumnsType } from 'antd/es/table';
|
||||
import {
|
||||
ACTIVITY_POSTER_STATUS_LABELS,
|
||||
ACTIVITY_POSTER_UPLOAD_HINT,
|
||||
DEFAULT_ACTIVITY_POSTER_QR_SLOT,
|
||||
type ActivityPosterItem,
|
||||
type ActivityPosterQrSlot,
|
||||
@@ -280,7 +281,7 @@ export default function ActivityPostersPage() {
|
||||
<Input maxLength={128} />
|
||||
</Form.Item>
|
||||
<Form.Item name="imageUrl" label="活动图" rules={[{ required: true, message: '请上传活动图' }]}>
|
||||
<OssUpload bizType="ACTIVITY_POSTER" />
|
||||
<OssUpload bizType="ACTIVITY_POSTER" uploadHint={ACTIVITY_POSTER_UPLOAD_HINT} />
|
||||
</Form.Item>
|
||||
<Form.Item name="qrXPct" hidden><InputNumber /></Form.Item>
|
||||
<Form.Item name="qrYPct" hidden><InputNumber /></Form.Item>
|
||||
|
||||
Reference in New Issue
Block a user