优化
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onBeforeUnmount, ref, watch } from 'vue'
|
||||
import { RefreshCw } from '@lucide/vue'
|
||||
import { Box, ClipboardCheck, Pencil, RefreshCw } from '@lucide/vue'
|
||||
import { useAccessPreviewStore } from '@/core/access/accessPreview'
|
||||
import { getApiErrorDetails, type ApiErrorDetails } from '@/shared/api/http'
|
||||
import ApiErrorMeta from '@/shared/components/ApiErrorMeta.vue'
|
||||
@@ -27,6 +27,10 @@ const emit = defineEmits<{
|
||||
|
||||
const access = useAccessPreviewStore()
|
||||
const activeTab = ref('overview')
|
||||
const measurementDialogOpen = ref(false)
|
||||
const reviewDialogOpen = ref(false)
|
||||
const measurementPanelRef = ref<InstanceType<typeof InboundMeasurementPanel> | null>(null)
|
||||
const reviewPanelRef = ref<InstanceType<typeof MeasurementReviewPanel> | null>(null)
|
||||
const loading = ref(false)
|
||||
const loadError = ref<ApiErrorDetails | null>(null)
|
||||
const detail = ref<InboundOrderDetail | null>(null)
|
||||
@@ -71,6 +75,11 @@ function handleDomainChanged() {
|
||||
emit('changed')
|
||||
}
|
||||
|
||||
function handleReviewChanged() {
|
||||
reviewDialogOpen.value = false
|
||||
handleDomainChanged()
|
||||
}
|
||||
|
||||
watch(
|
||||
() => [props.customerId, props.inboundId],
|
||||
() => {
|
||||
@@ -94,6 +103,7 @@ onBeforeUnmount(() => {
|
||||
<header class="workspace-header">
|
||||
<div>
|
||||
<div class="workspace-title-row">
|
||||
<span class="workspace-mark" aria-hidden="true"><Box :size="20" /></span>
|
||||
<h2>入库码:{{ title }}</h2>
|
||||
<StatusBadge v-if="detail" :status="statusLabel" />
|
||||
</div>
|
||||
@@ -124,14 +134,12 @@ onBeforeUnmount(() => {
|
||||
<el-tab-pane label="基本信息" name="overview">
|
||||
<InboundSummaryPanel :summary="detail.summary" :public-remark="detail.publicRemark" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="货物与测量" name="measurement" lazy>
|
||||
<el-tab-pane label="货品与测量" name="measurement" lazy>
|
||||
<div class="workflow-launch-panel">
|
||||
<div><h3>编辑入库测量数据</h3><p>核对原单数据、确认扫描箱数,并查看服务端计算的重量和体积结果。</p></div>
|
||||
<el-button type="primary" @click="measurementDialogOpen = true"><Pencil :size="16" />编辑测量数据</el-button>
|
||||
</div>
|
||||
<div class="measurement-workflow">
|
||||
<InboundMeasurementPanel
|
||||
:key="`measurement-${revision}`"
|
||||
:tenant-id="customerId"
|
||||
:inbound-id="inboundId"
|
||||
@changed="handleDomainChanged"
|
||||
/>
|
||||
<WeightOcrPanel
|
||||
:key="`weight-${revision}`"
|
||||
:tenant-id="customerId"
|
||||
@@ -141,13 +149,10 @@ onBeforeUnmount(() => {
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="测量审核" name="review" lazy>
|
||||
<MeasurementReviewPanel
|
||||
v-if="canViewMeasurement"
|
||||
:key="`review-${revision}`"
|
||||
:tenant-id="customerId"
|
||||
:inbound-id="inboundId"
|
||||
@changed="handleDomainChanged"
|
||||
/>
|
||||
<div v-if="canViewMeasurement" class="workflow-launch-panel">
|
||||
<div><h3>审核入库测量数据</h3><p>对照原单、设备实测和称重 OCR 结果后作出审核决定。</p></div>
|
||||
<el-button type="primary" @click="reviewDialogOpen = true"><ClipboardCheck :size="16" />审核测量数据</el-button>
|
||||
</div>
|
||||
<el-alert
|
||||
v-else
|
||||
title="无测量审核查看权限"
|
||||
@@ -165,16 +170,83 @@ onBeforeUnmount(() => {
|
||||
@changed="handleDomainChanged"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="状态与其他" name="records" lazy>
|
||||
<el-tab-pane label="状态历史" name="history" lazy>
|
||||
<InboundHistoryPanel
|
||||
:pallet-locations="[]"
|
||||
:files="[]"
|
||||
:internal-notes="[]"
|
||||
:status-history="detail.statusHistory"
|
||||
:public-remark="null"
|
||||
:sections="['history']"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="其他记录" name="records" lazy>
|
||||
<InboundHistoryPanel
|
||||
:pallet-locations="detail.palletLocations"
|
||||
:files="detail.files"
|
||||
:internal-notes="detail.internalNotes"
|
||||
:status-history="detail.statusHistory"
|
||||
:public-remark="null"
|
||||
:status-history="[]"
|
||||
:public-remark="detail.publicRemark"
|
||||
:sections="['allocations', 'files', 'notes', 'remark']"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
|
||||
<el-dialog
|
||||
v-model="measurementDialogOpen"
|
||||
class="inbound-operation-dialog inbound-measurement-dialog"
|
||||
title="编辑入库测量数据"
|
||||
width="min(1900px, calc(100vw - 32px))"
|
||||
top="4vh"
|
||||
destroy-on-close
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<div class="inbound-operation-dialog__body">
|
||||
<InboundMeasurementPanel
|
||||
ref="measurementPanelRef"
|
||||
:key="`measurement-dialog-${revision}`"
|
||||
:tenant-id="customerId"
|
||||
:inbound-id="inboundId"
|
||||
@changed="handleDomainChanged"
|
||||
/>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="inbound-operation-dialog__footer">
|
||||
<el-button @click="measurementDialogOpen = false">取消</el-button>
|
||||
<el-button v-if="measurementPanelRef?.canEdit" type="primary" plain :loading="measurementPanelRef?.saving" :disabled="!measurementPanelRef?.mayMaintain" @click="measurementPanelRef?.saveDraft()">保存确认箱数</el-button>
|
||||
<el-button v-if="measurementPanelRef?.canSubmit" type="primary" :loading="measurementPanelRef?.submitting" :disabled="!measurementPanelRef?.maySubmit" @click="measurementPanelRef?.submitForReview()">提交审核</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog
|
||||
v-model="reviewDialogOpen"
|
||||
class="inbound-operation-dialog inbound-review-dialog"
|
||||
title="审核入库测量数据"
|
||||
width="min(1700px, calc(100vw - 32px))"
|
||||
top="4vh"
|
||||
destroy-on-close
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<div class="inbound-operation-dialog__body">
|
||||
<MeasurementReviewPanel
|
||||
v-if="canViewMeasurement"
|
||||
ref="reviewPanelRef"
|
||||
:key="`review-dialog-${revision}`"
|
||||
:tenant-id="customerId"
|
||||
:inbound-id="inboundId"
|
||||
@changed="handleReviewChanged"
|
||||
/>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="inbound-operation-dialog__footer">
|
||||
<el-button :disabled="Boolean(reviewPanelRef?.actionLoading)" @click="reviewDialogOpen = false">取消</el-button>
|
||||
<el-button v-if="reviewPanelRef?.isPending && reviewPanelRef?.canReview" type="danger" plain :loading="reviewPanelRef?.actionLoading === 'reject'" @click="reviewPanelRef?.openReasonDialog('reject')">驳回</el-button>
|
||||
<el-button v-if="reviewPanelRef?.isPending && reviewPanelRef?.canReview" type="primary" :loading="reviewPanelRef?.actionLoading === 'approve'" @click="reviewPanelRef?.confirmApprove()">通过并完成入库</el-button>
|
||||
<el-button v-if="reviewPanelRef?.isRejected && reviewPanelRef?.canRelease" type="warning" plain :loading="reviewPanelRef?.actionLoading === 'release'" @click="reviewPanelRef?.openReasonDialog('release')">异常放行</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
@@ -182,6 +254,7 @@ onBeforeUnmount(() => {
|
||||
.inbound-workspace { min-width: 0; }
|
||||
.workspace-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 20px; padding: 18px 24px 16px; border-bottom: 1px solid var(--cc-border); }
|
||||
.workspace-title-row { display: flex; min-width: 0; align-items: center; flex-wrap: wrap; gap: 10px; }
|
||||
.workspace-mark { display: grid; width: 36px; height: 36px; flex: 0 0 36px; place-items: center; border-radius: 8px; background: #1e293b; color: #fff; }
|
||||
.workspace-title-row h2 { margin: 0; overflow-wrap: anywhere; color: #172033; font-size: 16px; line-height: 1.35; }
|
||||
.workspace-header p { margin: 5px 0 0; color: var(--cc-muted); font-size: 12px; line-height: 1.5; }
|
||||
.workspace-state { margin: 24px; }
|
||||
@@ -193,6 +266,19 @@ onBeforeUnmount(() => {
|
||||
.workflow-tabs :deep(.el-tabs__item) { min-height: 44px; padding: 0 18px; color: #475467; font-size: 13px; font-weight: 500; }
|
||||
.workflow-tabs :deep(.el-tabs__item.is-active) { color: var(--cc-primary); font-weight: 650; }
|
||||
.measurement-workflow { display: grid; min-width: 0; gap: 28px; }
|
||||
.workflow-launch-panel { display: flex; min-width: 0; align-items: center; justify-content: space-between; gap: 20px; padding: 20px; border: 1px solid var(--cc-border); border-radius: 8px; background: #fff; }
|
||||
.workflow-launch-panel h3 { margin: 0; color: var(--cc-text); font-size: 15px; }
|
||||
.workflow-launch-panel p { margin: 5px 0 0; color: var(--cc-muted); font-size: 12px; line-height: 1.55; }
|
||||
.inbound-operation-dialog__body { min-width: 0; }
|
||||
.inbound-operation-dialog__footer { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 10px; }
|
||||
.inbound-operation-dialog__footer :deep(.el-button) { margin-left: 0; }
|
||||
:global(.inbound-operation-dialog.el-dialog) { display: flex; max-width: calc(100vw - 32px); height: 92vh; max-height: 92vh; margin-bottom: 0; flex-direction: column; overflow: hidden; }
|
||||
:global(.inbound-operation-dialog .el-dialog__header) { flex: 0 0 auto; margin: 0; padding: 18px 24px; border-bottom: 1px solid var(--cc-border); }
|
||||
:global(.inbound-operation-dialog .el-dialog__body) { min-height: 0; flex: 1 1 auto; overflow-y: auto; padding: 20px 24px; }
|
||||
:global(.inbound-operation-dialog .el-dialog__footer) { flex: 0 0 auto; padding: 14px 24px; border-top: 1px solid var(--cc-border); }
|
||||
:global(.inbound-measurement-dialog .measurement-panel) { border: 0; border-radius: 0; box-shadow: none; }
|
||||
:global(.inbound-measurement-dialog .measurement-panel__heading .measurement-panel__actions), :global(.inbound-measurement-dialog .measurement-panel__footer) { display: none; }
|
||||
:global(.inbound-review-dialog .review-actions .action-buttons) { display: none; }
|
||||
@media (max-width: 720px) {
|
||||
.workspace-header { align-items: stretch; flex-direction: column; padding: 16px; }
|
||||
.workspace-header :deep(.el-button) { width: 100%; min-height: 44px; }
|
||||
@@ -200,5 +286,17 @@ onBeforeUnmount(() => {
|
||||
.workflow-tabs { padding: 0 16px 16px; }
|
||||
.workflow-tabs :deep(.el-tabs__nav-wrap) { overflow-x: auto; }
|
||||
.workflow-tabs :deep(.el-tabs__item) { min-height: 44px; padding-inline: 14px; }
|
||||
.workflow-launch-panel { align-items: stretch; flex-direction: column; padding: 16px; }
|
||||
.workflow-launch-panel :deep(.el-button) { width: 100%; min-height: 44px; }
|
||||
:global(.inbound-operation-dialog.el-dialog) { width: calc(100vw - 20px) !important; max-width: calc(100vw - 20px); height: 92vh; }
|
||||
:global(.inbound-operation-dialog .el-dialog__header) { padding: 16px; }
|
||||
:global(.inbound-operation-dialog .el-dialog__body) { padding: 14px; }
|
||||
.inbound-operation-dialog__footer { display: grid; grid-template-columns: 1fr; }
|
||||
.inbound-operation-dialog__footer :deep(.el-button) { width: 100%; min-height: 44px; }
|
||||
}
|
||||
@media (max-width: 360px) {
|
||||
:global(.inbound-operation-dialog.el-dialog) { width: calc(100vw - 12px) !important; max-width: calc(100vw - 12px); }
|
||||
:global(.inbound-operation-dialog .el-dialog__header) { padding: 14px 12px; }
|
||||
:global(.inbound-operation-dialog .el-dialog__body) { padding: 10px; }
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user