This commit is contained in:
2026-08-15 10:03:03 +08:00
parent fc8480426d
commit c464f47fb9
6 changed files with 46 additions and 21 deletions
@@ -3,13 +3,18 @@ import { resolve } from 'node:path'
import { describe, expect, it } from 'vitest'
const source = readFileSync(resolve(process.cwd(), 'src/modules/ocean-bookings/pages/OceanBookingDetailView.vue'), 'utf8')
const routesSource = readFileSync(resolve(process.cwd(), 'src/modules/ocean-bookings/routes.ts'), 'utf8')
describe('OceanBookingDetailView interaction contract', () => {
it('recognizes the dedicated create route as an editable new booking', () => {
expect(source).toContain("route.name === 'ocean-booking-create' || id.value === 'new'")
expect(source).toContain('const editable = computed(() => isNew.value)')
expect(source).toContain("const canSave = computed(() => isNew.value && access.can('platform:firstleg:ocean-booking:create'))")
expect(source).toContain(':disabled="!editable"')
expect(source).not.toContain("status === 'DRAFT'")
expect(source).toContain("? access.can('platform:firstleg:ocean-booking:create')")
expect(routesSource.indexOf("path: 'ocean-bookings/new'")).toBeLessThan(routesSource.indexOf("path: 'ocean-bookings/:bookingId'"))
expect(routesSource).toContain("name: 'ocean-booking-create'")
expect(routesSource).toContain("permission: 'platform:firstleg:ocean-booking:create'")
})
it('selects business objects and automatically keeps their ids and names together', () => {
@@ -73,7 +78,7 @@ describe('OceanBookingDetailView interaction contract', () => {
expect(source).toContain('v-model="releaseReason"')
expect(source).not.toContain('v-model="releaseForm.')
expect(source).toContain('线下订舱资料已登记并确认')
expect(source).toContain("{{ isNew ? '登记订舱' : '保存' }}")
expect(source).toContain('<Save :size="16" />登记订舱')
expect(source).toContain('登记后直接确认')
})
@@ -111,9 +111,7 @@ const rules: FormRules = {
freightTerm: [{ required: true, message: '请输入运费条款 Freight Term', trigger: 'blur' }],
}
const editable = computed(() => isNew.value)
const canSave = computed(() => isNew.value
? access.can('platform:firstleg:ocean-booking:create')
: editable.value && access.can('platform:firstleg:ocean-booking:edit'))
const canSave = computed(() => isNew.value && access.can('platform:firstleg:ocean-booking:create'))
const availableActions = computed(() => (actionsByStatus[detail.value?.status || 'CONFIRMED'] || [])
.filter((action) => access.can(actionPermissions[action])))
@@ -245,12 +243,10 @@ async function save() {
actionError.value = null
try {
const payload = { ...form.data }
if (isNew.value) {
const created = await createOceanBooking({ expectedVersion: 0, data: payload })
ElMessage.success('线下订舱资料已登记并确认')
await router.replace(`/ocean-bookings/${created.id}`)
applyDetail(created)
}
const created = await createOceanBooking({ expectedVersion: 0, data: payload })
ElMessage.success('线下订舱资料已登记并确认')
await router.replace(`/ocean-bookings/${created.id}`)
applyDetail(created)
} catch (cause) { actionError.value = getApiErrorDetails(cause) }
finally { saving.value = false }
}
@@ -362,7 +358,7 @@ onMounted(() => { void load(); void loadOptions() })
<div><h2>订舱信息</h2><p v-if="detail && !editable">已确认订舱资料仅可查看,船期变更请使用“申请改船”。</p></div>
<div class="actions">
<el-button v-for="item in availableActions" :key="item" :loading="actionSaving" @click="runAction(item)">{{ actionLabels[item] }}</el-button>
<el-button v-if="canSave" type="primary" :loading="saving" @click="save"><Save :size="16" />{{ isNew ? '登记订舱' : '保存' }}</el-button>
<el-button v-if="canSave" type="primary" :loading="saving" @click="save"><Save :size="16" />登记订舱</el-button>
</div>
</div>
<el-alert v-if="optionsError" type="warning" :closable="false" show-icon :title="optionsError"><el-button link type="warning" :loading="optionsLoading" @click="loadOptions">重新加载选项</el-button></el-alert>