图片上传支持粘贴剪贴板与拖拽上传
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
import { PlusOutlined } from '@ant-design/icons'
|
import { PlusOutlined } from '@ant-design/icons'
|
||||||
import { App, Upload } from 'antd'
|
import { App, Typography, Upload } from 'antd'
|
||||||
import type { UploadFile, UploadProps } from 'antd'
|
import type { UploadFile, UploadProps } from 'antd'
|
||||||
|
import type { ClipboardEvent, DragEvent } from 'react'
|
||||||
|
|
||||||
import { uploadFile } from '@/services/files'
|
import { uploadFile } from '@/services/files'
|
||||||
import type { UploadedFile } from '@/types/worker-platform'
|
import type { UploadedFile } from '@/types/worker-platform'
|
||||||
@@ -11,6 +12,7 @@ type ImageUploadProps = {
|
|||||||
scene: string
|
scene: string
|
||||||
scope: 'admin' | 'worker' | 'collect'
|
scope: 'admin' | 'worker' | 'collect'
|
||||||
maxCount?: number
|
maxCount?: number
|
||||||
|
showPasteHint?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ImageUpload({
|
export default function ImageUpload({
|
||||||
@@ -19,6 +21,7 @@ export default function ImageUpload({
|
|||||||
scene,
|
scene,
|
||||||
scope,
|
scope,
|
||||||
maxCount = 6,
|
maxCount = 6,
|
||||||
|
showPasteHint = false,
|
||||||
}: ImageUploadProps) {
|
}: ImageUploadProps) {
|
||||||
const { message } = App.useApp()
|
const { message } = App.useApp()
|
||||||
const fileList: UploadFile[] = value.map((file) => ({
|
const fileList: UploadFile[] = value.map((file) => ({
|
||||||
@@ -29,6 +32,39 @@ export default function ImageUpload({
|
|||||||
thumbUrl: file.thumbnailUrl || file.url,
|
thumbUrl: file.thumbnailUrl || file.url,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
async function uploadFiles(files: File[]) {
|
||||||
|
const images = files.filter((file) => file.type.startsWith('image/'))
|
||||||
|
if (images.length === 0) return
|
||||||
|
const remaining = maxCount - value.length
|
||||||
|
if (remaining <= 0) {
|
||||||
|
message.warning(`最多上传 ${maxCount} 张图片`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const next = [...value]
|
||||||
|
for (const file of images.slice(0, remaining)) {
|
||||||
|
try {
|
||||||
|
const uploaded = await uploadFile(file, scene, scope)
|
||||||
|
next.push(uploaded)
|
||||||
|
} catch (error) {
|
||||||
|
message.error(error instanceof Error ? error.message : '上传失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (next.length > value.length) onChange?.(next)
|
||||||
|
}
|
||||||
|
|
||||||
|
function handlePaste(event: ClipboardEvent<HTMLDivElement>) {
|
||||||
|
const files = Array.from(event.clipboardData?.files || [])
|
||||||
|
if (files.length === 0) return
|
||||||
|
event.preventDefault()
|
||||||
|
void uploadFiles(files)
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleDrop(event: DragEvent<HTMLDivElement>) {
|
||||||
|
event.preventDefault()
|
||||||
|
const files = Array.from(event.dataTransfer?.files || [])
|
||||||
|
if (files.length > 0) void uploadFiles(files)
|
||||||
|
}
|
||||||
|
|
||||||
const customRequest: UploadProps['customRequest'] = async (options) => {
|
const customRequest: UploadProps['customRequest'] = async (options) => {
|
||||||
try {
|
try {
|
||||||
const uploaded = await uploadFile(options.file as File, scene, scope)
|
const uploaded = await uploadFile(options.file as File, scene, scope)
|
||||||
@@ -41,6 +77,12 @@ export default function ImageUpload({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<div
|
||||||
|
className="image-upload-droppable"
|
||||||
|
onPaste={handlePaste}
|
||||||
|
onDrop={handleDrop}
|
||||||
|
onDragOver={(event) => event.preventDefault()}
|
||||||
|
>
|
||||||
<Upload
|
<Upload
|
||||||
accept="image/jpeg,image/png,image/webp"
|
accept="image/jpeg,image/png,image/webp"
|
||||||
listType="picture-card"
|
listType="picture-card"
|
||||||
@@ -62,5 +104,11 @@ export default function ImageUpload({
|
|||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</Upload>
|
</Upload>
|
||||||
|
{showPasteHint ? (
|
||||||
|
<Typography.Text type="secondary" className="image-upload-hint">
|
||||||
|
支持点击选择、粘贴剪贴板截图或拖拽图片上传
|
||||||
|
</Typography.Text>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -571,6 +571,7 @@ export default function WorkerOrdersPage() {
|
|||||||
value={acceptanceFiles}
|
value={acceptanceFiles}
|
||||||
onChange={setAcceptanceFiles}
|
onChange={setAcceptanceFiles}
|
||||||
maxCount={6}
|
maxCount={6}
|
||||||
|
showPasteHint
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Form>
|
</Form>
|
||||||
|
|||||||
@@ -1888,6 +1888,17 @@ select {
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.image-upload-droppable {
|
||||||
|
display: grid;
|
||||||
|
gap: 8px;
|
||||||
|
justify-items: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-upload-hint {
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
.image-preview-list {
|
.image-preview-list {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|||||||
Reference in New Issue
Block a user