feat: submit storage release reviews for one side only.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
zlwuandCursor committed 2026-08-19 11:46:39 +08:00
1 parent 021abd8283
commit 3388c1efdb
1 file changed
+81 -2
@@ -149,6 +149,11 @@
</div>
</template>
<div v-if="peerSideLabel" class="review-peer-readonly">
<span>{{ peerSideLabel }}:</span>
<el-tag :type="peerTagType" size="small">{{ peerConclusionText }}</el-tag>
</div>
<el-form
ref="formRef"
:model="form"
@@ -284,7 +289,9 @@
workOrderStatusLabel,
workOrderStatusTagType,
productionWorkOrderStatusLabel,
productionWorkOrderStatusTagType
productionWorkOrderStatusTagType,
storageReleaseConclusionLabel,
storageReleaseConclusionTagType
} from '@/utils/status-tag-registry'
import type {
ProductionReceptionRecord,
@@ -320,6 +327,7 @@
modelValue: boolean
reviewIds: string[]
reviewItems?: StorageReleaseReviewQueueItem[]
reviewSide: 'production' | 'qc'
}>()
const emit = defineEmits<{
@@ -367,7 +375,27 @@
const submittedCount = computed(() => Object.keys(queueDecision).length)
const dialogTitle = computed(() =>
isBatchMode.value ? `批量审核(${props.reviewIds.length} 条)` : '入库放行审核'
isBatchMode.value
? `批量审核(${props.reviewIds.length} 条)`
: props.reviewSide === 'production'
? '生产入库放行审核'
: '质检入库放行审核'
)
const peerSideLabel = computed(() =>
props.reviewSide === 'production' ? '质检结论' : '生产结论'
)
const peerConclusion = computed(() => {
const rev = activeDetail.value?.review
return props.reviewSide === 'production'
? rev?.qcReviewConclusion || ''
: rev?.prodReviewConclusion || ''
})
const peerConclusionText = computed(() =>
peerConclusion.value ? storageReleaseConclusionLabel(peerConclusion.value) : '待审核'
)
const peerTagType = computed(() =>
peerConclusion.value ? storageReleaseConclusionTagType(peerConclusion.value) : 'info'
)
const dialogWidth = computed(() => (isBatchMode.value ? '1480px' : '1200px'))
@@ -490,17 +518,58 @@
return 'is-pending'
}
function parseAttachmentUrls(urls: string): AttachmentItem[] {
if (!urls.trim()) return []
return urls
.split(',')
.map((u, i) => {
const url = u.trim()
if (!url) return null
const name = url.includes('/') ? url.split('/').pop() || `附件${i + 1}` : url
return {
id: `att_${i}`,
fileName: name,
fileUrl: url,
fileType: ''
}
})
.filter(Boolean) as AttachmentItem[]
}
function applySidePrefill() {
const rev = activeDetail.value?.review
if (!rev) {
form.reviewConclusion = 'tg'
form.reviewRemark = ''
attachmentFiles.value = []
_pendingList = null
return
}
const existing =
props.reviewSide === 'production' ? rev.prodReviewConclusion : rev.qcReviewConclusion
form.reviewConclusion = existing === 'tg' || existing === 'btg' ? existing : 'tg'
form.reviewRemark =
(props.reviewSide === 'production' ? rev.prodReviewRemark : rev.qcReviewRemark) || ''
const attachments =
props.reviewSide === 'production' ? rev.prodReviewAttachments : rev.qcReviewAttachments
attachmentFiles.value = parseAttachmentUrls(String(attachments || ''))
_pendingList = null
}
async function loadActiveDetail() {
const id = activeReviewId.value
if (!id || !showEvidenceLayout.value) {
activeDetail.value = null
applySidePrefill()
return
}
detailLoading.value = true
try {
activeDetail.value = await fetchStorageReleaseReviewDetail(id)
applySidePrefill()
} catch {
activeDetail.value = null
applySidePrefill()
} finally {
detailLoading.value = false
}
@@ -543,6 +612,7 @@
.map((f) => f.fileUrl)
.join(',')
return {
reviewSide: props.reviewSide,
reviewConclusion: form.reviewConclusion,
reviewRemark: form.reviewRemark.trim() || undefined,
reviewAttachments: attachmentUrls || undefined
@@ -911,6 +981,15 @@
border-radius: 8px;
}
.review-peer-readonly {
display: flex;
gap: 8px;
align-items: center;
margin-bottom: 12px;
font-size: 14px;
color: var(--mint-text-muted, #334155);
}
.review-info-summary {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));