fix: 优化验收操作和图片去重
This commit is contained in:
@@ -44,10 +44,15 @@ function normalizePreviewItems(files: UploadedFile[], imageUrls: string[]) {
|
||||
mediumUrl: file.mediumUrl || file.url,
|
||||
}))
|
||||
.filter((item) => Boolean(item.url))
|
||||
const fileUrlSet = new Set(normalizedFiles.map((item) => item.url))
|
||||
const fileUrlSet = new Set(normalizedFiles.map((item) => getImageIdentity(item.url)))
|
||||
const normalizedUrls = imageUrls
|
||||
.map((url) => String(url || '').trim())
|
||||
.filter((url) => url && !fileUrlSet.has(url))
|
||||
.filter((url) => url && !fileUrlSet.has(getImageIdentity(url)))
|
||||
.map((url) => ({ url, thumbnailUrl: url, mediumUrl: url }))
|
||||
return [...normalizedFiles, ...normalizedUrls]
|
||||
}
|
||||
|
||||
/** 忽略临时签名参数,避免同一存储对象重复显示。 */
|
||||
function getImageIdentity(value: string) {
|
||||
return String(value || '').trim().split(/[?#]/, 1)[0]
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
Table,
|
||||
Tabs,
|
||||
Tag,
|
||||
Tooltip,
|
||||
Typography,
|
||||
} from 'antd'
|
||||
import type { TableColumnsType } from 'antd'
|
||||
@@ -167,20 +168,7 @@ export default function WorkerOrdersPage() {
|
||||
const source = hasSubmittedAcceptance(order)
|
||||
? getWorkerAcceptance(order)
|
||||
: getWorkerDraft(order)
|
||||
setAcceptanceFiles([
|
||||
...getAcceptanceFilesFromSource(source),
|
||||
...(Array.isArray(source.imageUrls) ? source.imageUrls : []).map(
|
||||
(url): UploadedFile => ({
|
||||
objectKey: '',
|
||||
url: String(url || ''),
|
||||
thumbnailUrl: String(url || ''),
|
||||
mediumUrl: String(url || ''),
|
||||
filename: '图片',
|
||||
contentType: '',
|
||||
size: 0,
|
||||
}),
|
||||
),
|
||||
])
|
||||
setAcceptanceFiles(getUniqueAcceptanceFiles(source))
|
||||
form.setFieldsValue({ note: String(source.note || '') })
|
||||
setDetailOrder(null)
|
||||
}
|
||||
@@ -438,27 +426,33 @@ export default function WorkerOrdersPage() {
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
width: 260,
|
||||
width: 190,
|
||||
render: (_, row) => (
|
||||
<Space wrap>
|
||||
<Button icon={<EyeOutlined />} onClick={() => setDetailOrder(row)}>
|
||||
详情
|
||||
</Button>
|
||||
{canEditAcceptanceImages(row) ? (
|
||||
<Button
|
||||
icon={<PictureOutlined />}
|
||||
type={canSubmitAcceptance(row) ? 'primary' : 'default'}
|
||||
onClick={() => openAcceptanceModal(row)}
|
||||
>
|
||||
{hasSubmittedAcceptance(row) ? '补充图片' : '上传图片 / 提交验收'}
|
||||
</Button>
|
||||
) : null}
|
||||
<div className="worker-order-actions">
|
||||
<Space size={8}>
|
||||
<Tooltip title="查看详情">
|
||||
<Button
|
||||
aria-label="查看详情"
|
||||
icon={<EyeOutlined />}
|
||||
onClick={() => setDetailOrder(row)}
|
||||
/>
|
||||
</Tooltip>
|
||||
{canEditAcceptanceImages(row) ? (
|
||||
<Button
|
||||
icon={<PictureOutlined />}
|
||||
type={canSubmitAcceptance(row) ? 'primary' : 'default'}
|
||||
onClick={() => openAcceptanceModal(row)}
|
||||
>
|
||||
{hasSubmittedAcceptance(row) ? '补充图片' : '验收'}
|
||||
</Button>
|
||||
) : null}
|
||||
</Space>
|
||||
{canCancelOrder(row) ? (
|
||||
<Button danger onClick={() => openCancelModal(row)}>
|
||||
<Button type="link" danger size="small" onClick={() => openCancelModal(row)}>
|
||||
取消接单
|
||||
</Button>
|
||||
) : null}
|
||||
</Space>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
]
|
||||
@@ -740,7 +734,7 @@ export default function WorkerOrdersPage() {
|
||||
editingOrder
|
||||
? hasSubmittedAcceptance(editingOrder)
|
||||
? '补充验收图片'
|
||||
: '提交验收'
|
||||
: '验收图片'
|
||||
: '验收图片'
|
||||
}
|
||||
open={Boolean(editingOrder)}
|
||||
@@ -762,10 +756,7 @@ export default function WorkerOrdersPage() {
|
||||
>
|
||||
取消
|
||||
</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => void saveAcceptanceImages(form.getFieldsValue())}
|
||||
>
|
||||
<Button onClick={() => void saveAcceptanceImages(form.getFieldsValue())}>
|
||||
{hasSubmittedAcceptance(editingOrder) ? '保存修改' : '保存暂存'}
|
||||
</Button>
|
||||
{canSubmitAcceptance(editingOrder) ? (
|
||||
@@ -778,15 +769,7 @@ export default function WorkerOrdersPage() {
|
||||
}
|
||||
>
|
||||
<Form form={form} layout="vertical" onFinish={submitAcceptance}>
|
||||
<Form.Item
|
||||
label="完成说明"
|
||||
name="note"
|
||||
extra={
|
||||
editingOrder && !hasSubmittedAcceptance(editingOrder)
|
||||
? '图片和说明可先「保存暂存」,之后随时继续补充,不会丢失;确认完成后再「提交验收」。'
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
<Form.Item label="完成说明" name="note">
|
||||
<Input.TextArea
|
||||
rows={3}
|
||||
placeholder="可补充代练结果、注意事项或截图说明。"
|
||||
@@ -979,6 +962,38 @@ function getAcceptanceFilesFromSource(source: WorkerAcceptance): UploadedFile[]
|
||||
return Array.isArray(source.files) ? source.files : []
|
||||
}
|
||||
|
||||
/** 合并草稿兼容字段,并按固定图片地址去重,避免同一图片重复回填。 */
|
||||
function getUniqueAcceptanceFiles(source: WorkerAcceptance): UploadedFile[] {
|
||||
const files = [
|
||||
...getAcceptanceFilesFromSource(source),
|
||||
...(Array.isArray(source.imageUrls) ? source.imageUrls : []).map(
|
||||
(url): UploadedFile => ({
|
||||
objectKey: '',
|
||||
url: String(url || ''),
|
||||
thumbnailUrl: String(url || ''),
|
||||
mediumUrl: String(url || ''),
|
||||
filename: '图片',
|
||||
contentType: '',
|
||||
size: 0,
|
||||
}),
|
||||
),
|
||||
]
|
||||
const identities = new Set<string>()
|
||||
return files.filter((file) => {
|
||||
const identity = getImageIdentity(file.url || file.mediumUrl || file.thumbnailUrl || file.objectKey)
|
||||
if (!identity || identities.has(identity)) return false
|
||||
identities.add(identity)
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
/** 去除临时签名参数,确保同一个对象的不同访问链接能匹配。 */
|
||||
function getImageIdentity(value: string): string {
|
||||
const url = String(value || '').trim()
|
||||
if (!url) return ''
|
||||
return url.split(/[?#]/, 1)[0]
|
||||
}
|
||||
|
||||
function getAcceptanceFiles(row: WorkOrder): UploadedFile[] {
|
||||
return getAcceptanceFilesFromSource(getWorkerAcceptance(row))
|
||||
}
|
||||
|
||||
@@ -1519,6 +1519,17 @@ select {
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.worker-order-actions {
|
||||
display: grid;
|
||||
justify-items: start;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.worker-order-actions .ant-btn-link {
|
||||
height: auto;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.worker-order-detail-value {
|
||||
white-space: pre-wrap;
|
||||
overflow-wrap: anywhere;
|
||||
|
||||
Reference in New Issue
Block a user