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
@@ -15,6 +15,7 @@ import {
} from '../api/platformOceanBookings'
import type { OceanBookingDetail, OceanBookingStatus } from '../types'
import OceanBookingDetailView from './OceanBookingDetailView.vue'
import AppDialog from '@/shared/components/AppDialog.vue'
const routerReplace = vi.hoisted(() => vi.fn())
const routeState = vi.hoisted(() => ({ name: 'ocean-booking-detail', params: { bookingId: '123' } }))
@@ -101,6 +102,23 @@ describe('OceanBookingDetailView one-click release', () => {
vi.mocked(listOceanBookingAgents).mockResolvedValue([{ supplierId: '20', name: '订舱代理', carrierCodes: ['MATSON'] }])
})
it('opens the booking-number confirmation with the edited facts before saving or releasing', async () => {
const { wrapper, vm } = await mountView()
vm.form.data.billOfLadingNo = 'EDITED-BL'
await flushPromises()
await wrapper.findAll('button').find(button => button.text() === '放舱')!.trigger('click')
await flushPromises()
const dialog = wrapper.findAllComponents(AppDialog).find(item => item.props('title').startsWith('确认放舱'))!
expect(dialog.props('modelValue')).toBe(true)
expect(dialog.props('title')).toBe('确认放舱 · OB-123')
expect(wrapper.get('.release-summary').text()).toContain('EDITED-BL')
expect(wrapper.text()).toContain('不能修改、不能删除')
expect(wrapper.text()).not.toContain('处理数据库')
expect(updateOceanBookingDraft).not.toHaveBeenCalled()
expect(releaseOceanBooking).not.toHaveBeenCalled()
wrapper.unmount()
})
it('shows the matching fixed logistics group instead of the underlying price-book channel', async () => {
const { wrapper } = await mountView()
expect(wrapper.text()).toContain('美森正班')
@@ -61,7 +61,7 @@ describe('OceanBookingDetailView draft and release contract', () => {
expect(source).toContain("if (!form.data.carrierCode) return '放舱前请重新选择船公司,所选船公司必须配置标准编码'")
expect(source).not.toContain('请先保存草稿后再放舱')
expect(source).toContain('放舱前请填写${missing[1]}')
expect(source).toContain('放舱后资料将同步到关联货柜,不能修改、不能删除;填写错误只能由管理员处理数据库,请确认资料无误。')
expect(source).toContain('放舱后资料将同步到关联货柜,不能修改、不能删除,请确认资料无误。')
expect(source).toContain('if (hasUnsavedDraftChanges.value)')
expect(source).toContain('const saved = await persistDraft(false)')
expect(source).toContain('releaseVersion = saved.version')
@@ -280,7 +280,7 @@ async function persistDraft(showSuccess: boolean) {
const saved = isNew.value
? await createOceanBooking({ expectedVersion: 0, data: payload })
: await updateOceanBookingDraft(id.value, { expectedVersion: detail.value?.version || 0, data: payload })
if (showSuccess) ElMessage.success(isNew.value ? `订舱创建成功:${saved.bookingNo || saved.id}` : '订舱草稿已保存')
if (showSuccess) ElMessage.success(isNew.value ? `订舱创建成功:${saved.bookingNo || '未生成订舱号'}` : '订舱草稿已保存')
if (isNew.value) {
workspace.removeByIds(['ocean-booking-create'])
await router.replace('/ocean-bookings')
@@ -347,11 +347,12 @@ async function submitRelease() {
} catch (cause) { actionError.value = getApiErrorDetails(cause) }
finally { actionSaving.value = false }
}
function bookingDialogTitle(action: string) { const code = detail.value?.bookingNo?.trim(); return code ? `${action} · ${code}` : action }
async function removeDraft() {
if (!detail.value || !canDelete.value) return
actionError.value = null
try {
await ElMessageBox.confirm('确认删除该订舱草稿?删除后无法恢复。', '删除草稿', { customClass: 'admin-density-confirm', confirmButtonText: '确认删除', cancelButtonText: '取消', type: 'warning' })
await ElMessageBox.confirm('确认删除该订舱草稿?删除后无法恢复。', bookingDialogTitle('删除草稿'), { customClass: 'admin-density-confirm', confirmButtonText: '确认删除', cancelButtonText: '取消', type: 'warning' })
actionSaving.value = true
await deleteOceanBookingDraft(id.value, detail.value.version)
ElMessage.success('订舱草稿已删除')
@@ -464,7 +465,7 @@ onMounted(() => { void load(); void loadOptions() })
</div>
</section>
<OceanBookingDocumentsPanel v-if="detail" :booking-id="detail.id" :booking-version="detail.version" :booking-status="detail.status" :documents="detail.documents" :can-manage="canManageDocuments" :manage-reason="documentManageReason" @updated="updateDocuments" />
<OceanBookingDocumentsPanel v-if="detail" :booking-id="detail.id" :booking-no="detail.bookingNo" :booking-version="detail.version" :booking-status="detail.status" :documents="detail.documents" :can-manage="canManageDocuments" :manage-reason="documentManageReason" @updated="updateDocuments" />
<div v-if="detail" class="surface-panel"><CarrierScheduleQueryPanel dense :ocean-booking-id="detail.id" /></div>
@@ -476,17 +477,17 @@ onMounted(() => { void load(); void loadOptions() })
</DetailPageLayout>
<OceanBookingPrintDialog v-if="detail" v-model="printOpen" :booking-id="detail.id" :booking-no="detail.bookingNo" :allowed="canPrint" />
<AppDialog class="admin-density-dialog" v-model="releaseDialogOpen" title="确认放舱" width="min(560px, 94vw)" :confirm-loading="actionSaving" :confirm-disabled="workflowBusy" confirm-text="确认放舱" cancel-text="取消" @confirm="submitRelease">
<el-form class="density-form" label-position="top">
<el-alert title="放舱后资料将同步到关联货柜,不能修改、不能删除;填写错误只能由管理员处理数据库,请确认资料无误。" type="warning" :closable="false" show-icon />
<el-descriptions class="release-summary" :column="2" border>
<AppDialog class="admin-density-dialog" v-model="releaseDialogOpen" :title="bookingDialogTitle('确认放舱')" width="min(560px, 94vw)" :confirm-loading="actionSaving" :confirm-disabled="workflowBusy" confirm-text="确认放舱" cancel-text="取消" @confirm="submitRelease">
<div class="density-dialog-sections">
<el-alert title="放舱后资料将同步到关联货柜,不能修改、不能删除,请确认资料无误。" type="warning" :closable="false" show-icon />
<section class="density-dialog-section" data-tone="summary"><el-descriptions class="release-summary density-descriptions" :column="2" border>
<el-descriptions-item label="提单号">{{ form.data.billOfLadingNo || '—' }}</el-descriptions-item>
<el-descriptions-item label="船名">{{ form.data.vesselName || '—' }}</el-descriptions-item>
<el-descriptions-item label="航次">{{ form.data.voyageNo || '—' }}</el-descriptions-item>
<el-descriptions-item label="预计开船">{{ form.data.estimatedSailingAt || '—' }}</el-descriptions-item>
<el-descriptions-item label="预计到港">{{ form.data.estimatedArrivalAt || '—' }}</el-descriptions-item>
</el-descriptions>
</el-form>
</el-descriptions></section>
</div>
</AppDialog>
</AdminPage>
</template>