完善接单平台上传与物品规则

This commit is contained in:
yml2213
2026-07-25 15:56:18 +08:00
parent f6d3f00f21
commit a2587eda01
40 changed files with 4978 additions and 1008 deletions
@@ -0,0 +1,53 @@
import { Image, Typography } from 'antd'
import type { UploadedFile } from '@/types/worker-platform'
type ImagePreviewListProps = {
files?: UploadedFile[]
imageUrls?: string[]
size?: number
}
export default function ImagePreviewList({
files = [],
imageUrls = [],
size = 56,
}: ImagePreviewListProps) {
const items = normalizePreviewItems(files, imageUrls)
if (items.length === 0) {
return <Typography.Text type="secondary">-</Typography.Text>
}
return (
<Image.PreviewGroup>
<div className="image-preview-list">
{items.map((item) => (
<Image
key={item.url}
src={item.thumbnailUrl || item.url}
preview={{ src: item.mediumUrl || item.url }}
width={size}
height={size}
className="image-preview-item"
/>
))}
</div>
</Image.PreviewGroup>
)
}
function normalizePreviewItems(files: UploadedFile[], imageUrls: string[]) {
const normalizedFiles = files
.map((file) => ({
url: file.url || file.mediumUrl || file.thumbnailUrl,
thumbnailUrl: file.thumbnailUrl || file.url,
mediumUrl: file.mediumUrl || file.url,
}))
.filter((item) => Boolean(item.url))
const fileUrlSet = new Set(normalizedFiles.map((item) => item.url))
const normalizedUrls = imageUrls
.map((url) => String(url || '').trim())
.filter((url) => url && !fileUrlSet.has(url))
.map((url) => ({ url, thumbnailUrl: url, mediumUrl: url }))
return [...normalizedFiles, ...normalizedUrls]
}
@@ -0,0 +1,66 @@
import { PlusOutlined } from '@ant-design/icons'
import { App, Upload } from 'antd'
import type { UploadFile, UploadProps } from 'antd'
import { uploadFile } from '@/services/files'
import type { UploadedFile } from '@/types/worker-platform'
type ImageUploadProps = {
value?: UploadedFile[]
onChange?: (files: UploadedFile[]) => void
scene: string
scope: 'admin' | 'worker'
maxCount?: number
}
export default function ImageUpload({
value = [],
onChange,
scene,
scope,
maxCount = 6,
}: ImageUploadProps) {
const { message } = App.useApp()
const fileList: UploadFile[] = value.map((file) => ({
uid: file.objectKey || file.url,
name: file.filename || '图片',
status: 'done',
url: file.thumbnailUrl || file.url,
thumbUrl: file.thumbnailUrl || file.url,
}))
const customRequest: UploadProps['customRequest'] = async (options) => {
try {
const uploaded = await uploadFile(options.file as File, scene, scope)
onChange?.([...value, uploaded].slice(-maxCount))
options.onSuccess?.(uploaded)
} catch (error) {
message.error(error instanceof Error ? error.message : '上传失败')
options.onError?.(error instanceof Error ? error : new Error('上传失败'))
}
}
return (
<Upload
accept="image/jpeg,image/png,image/webp"
listType="picture-card"
fileList={fileList}
maxCount={maxCount}
customRequest={customRequest}
onRemove={(file) => {
onChange?.(
value.filter((item) => (item.objectKey || item.url) !== file.uid),
)
return true
}}
showUploadList={{ showPreviewIcon: false }}
>
{value.length >= maxCount ? null : (
<button className="image-upload-trigger" type="button">
<PlusOutlined />
<span></span>
</button>
)}
</Upload>
)
}