style(admin): unify dialog layouts and dense readonly presentation

This commit is contained in:
2026-10-20 10:11:31 +08:00
parent 7ff7c9914f
commit 3267679758
214 changed files with 10931 additions and 2654 deletions
@@ -64,6 +64,10 @@ const canCorrectTransport = computed(() => {
})
const isContainerCorrection = computed(() => Boolean(detail.value?.summary.containerNo))
const editDialogTitle = computed(() => isContainerCorrection.value ? '纠正集装箱号 / 航次' : '补录集装箱号 / 航次')
function preloadDialogTitle(action: string, code?: string | null) {
const businessNo = code?.trim() || detail.value?.summary.preloadNo?.trim() || detail.value?.summary.cabinetNo?.trim()
return businessNo ? `${action} · ${businessNo}` : action
}
const editRules: FormRules = {
containerNo: [
{ required: true, message: '请输入集装箱号', trigger: 'blur' },
@@ -291,34 +295,42 @@ watch([planId, warehouseId], () => {
</LoadingListDetailDrawer>
</div>
<AppDialog v-model="editOpen" class="loading-transport-dialog admin-density-dialog" :title="editDialogTitle" width="min(620px, calc(100vw - 28px))" confirm-text="保存" :confirm-loading="editSaving" :confirm-disabled="!canEdit" @confirm="saveTransport">
<el-form ref="editFormRef" class="transport-form" :model="editForm" :rules="editRules" label-position="top">
<el-form-item label="真实集装箱号" prop="containerNo"><el-input v-model="editForm.containerNo" maxlength="64" placeholder="请输入提柜后取得的真实集装箱号" @blur="editForm.containerNo = normalizedContainerNo(editForm.containerNo)" /></el-form-item>
<el-form-item label="航次" prop="voyageNo"><el-input v-model="editForm.voyageNo" maxlength="64" placeholder="请输入航次" /></el-form-item>
<el-form-item :label="isContainerCorrection ? '纠错原因' : '操作原因(可选)'" prop="operationReason"><el-input v-model="editForm.operationReason" type="textarea" :rows="3" maxlength="500" :placeholder="isContainerCorrection ? '必填,将记录在操作历史中' : '可填写补录说明'" /></el-form-item>
</el-form>
<AppDialog v-model="editOpen" class="loading-transport-dialog admin-density-dialog" :title="preloadDialogTitle(editDialogTitle)" width="min(620px, calc(100vw - 28px))" confirm-text="保存" :confirm-loading="editSaving" :confirm-disabled="!canEdit" @confirm="saveTransport">
<section class="density-dialog-section" data-tone="work">
<el-form ref="editFormRef" class="density-form" :model="editForm" :rules="editRules">
<table class="density-table density-table--editable preload-editor-table" aria-label="运输信息填写"><tbody>
<tr><td><el-form-item label-position="left" label-width="120px" label="真实集装箱号" prop="containerNo"><el-input v-model="editForm.containerNo" maxlength="64" placeholder="请输入提柜后取得的真实集装箱号" @blur="editForm.containerNo = normalizedContainerNo(editForm.containerNo)" /></el-form-item></td></tr>
<tr><td><el-form-item label-position="left" label-width="120px" label="航次" prop="voyageNo"><el-input v-model="editForm.voyageNo" maxlength="64" placeholder="请输入航次" /></el-form-item></td></tr>
<tr><td><el-form-item label-position="left" label-width="120px" :label="isContainerCorrection ? '纠错原因' : '操作原因(可选)'" prop="operationReason"><el-input v-model="editForm.operationReason" type="textarea" :rows="3" maxlength="500" :placeholder="isContainerCorrection ? '必填,将记录在操作历史中' : '可填写补录说明'" /></el-form-item></td></tr>
</tbody></table>
</el-form>
</section>
</AppDialog>
<AppDialog v-model="remarkOpen" class="remarks-dialog admin-density-dialog" title="编辑备注" width="min(680px, calc(100vw - 28px))" confirm-text="保存备注" cancel-text="取消" :confirm-loading="remarkSaving" :confirm-disabled="!canEdit" @confirm="saveRemarks">
<AppDialog v-model="remarkOpen" class="remarks-dialog admin-density-dialog" :title="preloadDialogTitle('编辑备注', remarkTarget?.inboundCode || remarkTarget?.orderNo)" width="min(800px, calc(100vw - 28px))" fullscreenable confirm-text="保存备注" cancel-text="取消" :confirm-loading="remarkSaving" :confirm-disabled="!canEdit" @confirm="saveRemarks">
<el-alert type="info" :closable="false" show-icon title="客户备注来自客户下单且不可修改;其余备注可维护" />
<el-form label-position="top" class="remarks-form">
<el-form-item label="客户备注(只读)"><el-input :model-value="remarkTarget?.customerRemark || '—'" disabled /><small>来源:客户下单</small></el-form-item>
<el-form-item label="内部备注"><el-input v-model="remarkForm.internalRemark" type="textarea" :rows="3" maxlength="1000" show-word-limit placeholder="可填写、修改或清空内部备注" /></el-form-item>
<el-form-item label="仓库备注"><el-input v-model="remarkForm.warehouseRemark" type="textarea" :rows="3" maxlength="1000" show-word-limit placeholder="可填写、修改或清空仓库备注" /></el-form-item>
<el-form-item label="客服备注"><el-input v-model="remarkForm.customerServiceRemark" type="textarea" :rows="3" maxlength="1000" show-word-limit placeholder="可填写、修改或清空客服备注" /></el-form-item>
</el-form>
<section class="density-dialog-section" data-tone="work">
<el-form class="density-form">
<table class="density-table density-table--editable preload-editor-table" aria-label="预装明细备注"><tbody>
<tr><td><el-form-item label-position="left" label-width="128px" label="客户备注(只读)"><span class="customer-remark-text">{{ remarkTarget?.customerRemark || '—' }}</span></el-form-item></td></tr>
<tr><td><el-form-item label-position="left" label-width="128px" label="内部备注"><el-input v-model="remarkForm.internalRemark" type="textarea" :rows="3" maxlength="1000" show-word-limit placeholder="可填写、修改或清空内部备注" /></el-form-item></td></tr>
<tr><td><el-form-item label-position="left" label-width="128px" label="仓库备注"><el-input v-model="remarkForm.warehouseRemark" type="textarea" :rows="3" maxlength="1000" show-word-limit placeholder="可填写、修改或清空仓库备注" /></el-form-item></td></tr>
<tr><td><el-form-item label-position="left" label-width="128px" label="客服备注"><el-input v-model="remarkForm.customerServiceRemark" type="textarea" :rows="3" maxlength="1000" show-word-limit placeholder="可填写、修改或清空客服备注" /></el-form-item></td></tr>
</tbody></table>
</el-form>
</section>
<LoadErrorState v-if="remarkError" compact title="备注保存失败" :message="remarkError.message" :show-retry="false"><template #details><ApiErrorMeta :details="remarkError" /></template></LoadErrorState>
</AppDialog>
<AppDialog v-model="confirmOpen" class="preload-confirm-dialog admin-density-dialog" title="确认预装并推送 PDA" width="min(520px, calc(100vw - 28px))" confirm-text="确认并推送" :confirm-loading="confirmSaving" :confirm-disabled="!detail?.summary.readiness.canConfirm || !assigneeId || assigneeLoading" @confirm="submitConfirmPreload">
<AppDialog v-model="confirmOpen" class="preload-confirm-dialog admin-density-dialog" :title="preloadDialogTitle('确认预装并推送 PDA')" width="min(520px, calc(100vw - 28px))" confirm-text="确认并推送" :confirm-loading="confirmSaving" :confirm-disabled="!detail?.summary.readiness.canConfirm || !assigneeId || assigneeLoading" @confirm="submitConfirmPreload">
<div class="confirm-content">
<el-alert type="warning" :closable="false" show-icon title="本操作将确认整份预装计划" />
<el-descriptions v-if="detail" :column="1" border>
<el-descriptions-item label="预装单号">{{ detail.summary.preloadNo }}</el-descriptions-item>
<el-descriptions-item label="柜次号">{{ detail.summary.cabinetNo || '—' }}</el-descriptions-item>
<el-descriptions-item label="集装箱号">{{ detail.summary.containerNo || '待补录' }}</el-descriptions-item>
</el-descriptions>
<el-descriptions :column="1" border><el-descriptions-item label="PDA 操作员">{{ selectedAssignee?.displayName || '未选择' }}</el-descriptions-item></el-descriptions>
<section class="density-dialog-section" data-tone="summary">
<table class="density-table preload-confirm-table" aria-label="确认预装资料"><tbody>
<template v-if="detail"><tr><th>预装单号</th><td>{{ detail.summary.preloadNo }}</td></tr><tr><th>柜次号</th><td>{{ detail.summary.cabinetNo || '—' }}</td></tr><tr><th>集装箱号</th><td>{{ detail.summary.containerNo || '待补录' }}</td></tr></template>
<tr><th>PDA 操作员</th><td>{{ selectedAssignee?.displayName || '未选择' }}</td></tr>
</tbody></table>
</section>
<LoadErrorState v-if="confirmError" compact title="推送失败" :message="confirmError.message" :show-retry="false" />
</div>
</AppDialog>
@@ -327,16 +339,13 @@ watch([planId, warehouseId], () => {
<style scoped>
.preload-detail-page { display: grid; min-width: 0; width: 100%; gap: var(--admin-space-5, 12px); }
.transport-form { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 var(--admin-space-6, 16px); }
.transport-form :deep(.el-form-item:last-child) { grid-column: 1 / -1; }
.preload-editor-table { table-layout: fixed; }
.preload-confirm-table th { width: 120px; }
.customer-remark-text { white-space: pre-wrap; overflow-wrap: anywhere; }
.confirm-content { display: grid; gap: var(--admin-space-5, 12px); }
.pda-operator-picker { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 8px; }
.pda-operator-picker label { flex: 0 0 auto; font-size: var(--admin-font-body, 13px); white-space: nowrap; }
.pda-operator-picker label span { color: var(--el-color-warning-dark-2); font-size: var(--admin-font-caption, 12px); }
.pda-operator-picker :deep(.el-select) { width: 180px; }
.remarks-form { margin-top: 14px; }
.remarks-form small { display: block; margin-top: var(--admin-space-1, 4px); color: var(--cc-muted); }
:global(.loading-transport-dialog.el-dialog) { max-height: 90vh; overflow: hidden; }
@media (min-width: 1920px) { .preload-detail-page { width: 100%; max-width: none; gap: var(--admin-space-5, 12px); } }
@media (max-width: 720px) { .transport-form { grid-template-columns: 1fr; } .transport-form :deep(.el-form-item:last-child) { grid-column: auto; } }
</style>