From 5c2580608107fd723300b20a94479d6ebc26f251 Mon Sep 17 00:00:00 2001 From: ouyangxq <775153912@qq.com> Date: Tue, 4 Aug 2026 10:31:53 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../first-leg/store/firstLegOrders.test.mjs | 6 +++ src/modules/first-leg/store/firstLegOrders.ts | 6 +-- .../views/FirstLegOrdersView.test.mjs | 12 +++++- .../first-leg/views/FirstLegOrdersView.vue | 22 +++++++---- .../api/merchantIam.test.mjs | 10 +++++ src/modules/tenant-management/contracts.ts | 6 ++- .../store/tenantAdministration.ts | 9 +++-- .../views/CompanyProfileView.vue | 38 +++++++++++++++---- .../views/PermissionsView.vue | 15 +++++--- .../views/TenantAdministrationViews.test.mjs | 7 ++++ 10 files changed, 100 insertions(+), 31 deletions(-) diff --git a/src/modules/first-leg/store/firstLegOrders.test.mjs b/src/modules/first-leg/store/firstLegOrders.test.mjs index 4a680ca..13105a9 100644 --- a/src/modules/first-leg/store/firstLegOrders.test.mjs +++ b/src/modules/first-leg/store/firstLegOrders.test.mjs @@ -34,6 +34,12 @@ test('sends backend-required channel, customs, destination and cargo fields', () } assert.match(storeSource, /containerMode: draft\.transportMode === 'FCL' \? 'FULL_CONTAINER'/) assert.match(storeSource, /customerId: draft\.shipperPartyId/) + assert.match(storeSource, /customerName: customerName\.trim\(\) \|\| draft\.shipperPartySnapshot\.name/) +}) + +test('only blocks submission when a known company audit status is not active', () => { + assert.match(storeSource, /companyAuditStatus\?: MerchantTenantStatus/) + assert.match(storeSource, /if \(companyAuditStatus && companyAuditStatus !== 'ACTIVE'\)/) }) test('does not expose the out-of-scope cancellation write', () => { diff --git a/src/modules/first-leg/store/firstLegOrders.ts b/src/modules/first-leg/store/firstLegOrders.ts index ee082eb..6418cb4 100644 --- a/src/modules/first-leg/store/firstLegOrders.ts +++ b/src/modules/first-leg/store/firstLegOrders.ts @@ -66,7 +66,7 @@ function savePayload(draft: FirstLegOrderDraft, warehouse: PlatformReceivingWare // 后端把 customerId 作为订单主往来单位校验并以服务端名称覆盖 customerName; // 当前商户下单以所选发货单位作为主往来单位,收发货详情仍分别保存订单快照。 customerId: draft.shipperPartyId, - customerName, + customerName: customerName.trim() || draft.shipperPartySnapshot.name, transportMode: apiTransport(draft), tradeTerm: draft.tradeTerm || undefined, destinationCountryCode: draft.destinationCountryCode.trim().toUpperCase(), @@ -246,8 +246,8 @@ export const useFirstLegOrdersStore = defineStore('client-first-leg-orders', () return loadDetail(String(createdId)) } - async function submit(draft: FirstLegOrderDraft, customerName: string, id?: string, companyAuditStatus: MerchantTenantStatus = 'ACTIVE') { - if (companyAuditStatus !== 'ACTIVE') throw new Error('企业资料尚未审核通过,请先完善企业资料并等待平台审核') + async function submit(draft: FirstLegOrderDraft, customerName: string, id?: string, companyAuditStatus?: MerchantTenantStatus) { + if (companyAuditStatus && companyAuditStatus !== 'ACTIVE') throw new Error('企业资料尚未审核通过,请先完善企业资料并等待平台审核') const order = await saveDraft(draft, customerName, id) await submitMerchantFirstLegOrder(order.id) return loadDetail(order.id) diff --git a/src/modules/first-leg/views/FirstLegOrdersView.test.mjs b/src/modules/first-leg/views/FirstLegOrdersView.test.mjs index 00a660e..b91d6df 100644 --- a/src/modules/first-leg/views/FirstLegOrdersView.test.mjs +++ b/src/modules/first-leg/views/FirstLegOrdersView.test.mjs @@ -33,13 +33,21 @@ test('exposes real list, draft, submit, and detail workflow entries without canc }) test('blocks order submission before company approval while preserving draft actions', () => { - assert.match(source, /companyApproved/) + assert.match(source, /companySubmissionBlocked/) + assert.match(source, /companyAuditLoaded\.value = true/) assert.match(source, /企业资料待审核,当前仅可保存订单草稿/) assert.match(source, /暂时无法提交订单/) assert.match(source, /router\.push\('\/company\/profile'\)/) assert.match(source, /auth\.hasPermission\('order:first-leg:submit'\)/) }) +test('defers approval checks to the server when the member cannot read the company profile', () => { + assert.match(source, /const canViewCompanyProfile = computed/) + assert.match(source, /const companySubmissionBlocked = computed\(\(\) => companyAuditLoaded\.value/) + assert.match(source, /const knownCompanyAuditStatus = companyAuditLoaded\.value \? tenantStore\.company\.auditStatus : undefined/) + assert.match(source, /store\.submit\([^\n]*knownCompanyAuditStatus\)/) +}) + test('renders dynamic cargo lines and responsive drawers', () => { assert.match(source, /v-for="\(item, index\) in form\.items"/) assert.match(source, /function addCargoItem\(\)/) @@ -77,7 +85,7 @@ test('keeps desktop query actions on the first row and only shows the qualificat assert.match(source, /\.first-leg-query-toolbar \{ flex-wrap: nowrap; \}/) assert.match(source, /query-toolbar__filters\) \{ display: grid; min-width: 0; flex: 1 1 auto;/) assert.match(source, /query-toolbar__actions\) \{ align-self: flex-start; flex-wrap: nowrap; margin-left: auto;/) - assert.match(source, /v-if="!companyApproved && !supportingDataErrors\.some/) + assert.match(source, /v-if="companySubmissionBlocked && !supportingDataErrors\.some/) assert.doesNotMatch(source, /企业资料已审核,可正常提交订单/) assert.doesNotMatch(source, /order-eligibility\.is-approved/) }) diff --git a/src/modules/first-leg/views/FirstLegOrdersView.vue b/src/modules/first-leg/views/FirstLegOrdersView.vue index ec87657..32076ec 100644 --- a/src/modules/first-leg/views/FirstLegOrdersView.vue +++ b/src/modules/first-leg/views/FirstLegOrdersView.vue @@ -29,7 +29,9 @@ const auth = useAuthStore() const route = useRoute() const router = useRouter() const isCreatePage = computed(() => route.name === 'first-leg-order-create') -const companyApproved = computed(() => tenantStore.company.auditStatus === 'ACTIVE') +const canViewCompanyProfile = computed(() => auth.hasPermission('company:profile:view')) +const companyAuditLoaded = ref(false) +const companySubmissionBlocked = computed(() => companyAuditLoaded.value && tenantStore.company.auditStatus !== 'ACTIVE') const canCreateOrder = computed(() => auth.hasPermission('order:first-leg:create')) const canEditOrder = computed(() => auth.hasPermission('order:first-leg:edit')) const availableWarehouses = computed(() => store.warehouses) @@ -195,10 +197,11 @@ const emptyDescription = computed(() => hasActiveFilters.value ? '没有符合 async function loadPageData() { supportingDataLoading.value = true supportingDataErrors.value = [] + companyAuditLoaded.value = false availableShippers.value = [] availableConsignees.value = [] - const companyRequest = auth.hasPermission('company:profile:view') + const companyRequest = canViewCompanyProfile.value ? tenantStore.loadCompanyContext() : Promise.resolve() const [ordersResult, partiesResult, companyResult] = await Promise.allSettled([ @@ -213,7 +216,9 @@ async function loadPageData() { } else { supportingDataErrors.value.push(`往来单位加载失败:${errorMessage(partiesResult.reason)}`) } - if (companyResult.status === 'rejected') { + if (canViewCompanyProfile.value && companyResult.status === 'fulfilled') { + companyAuditLoaded.value = true + } else if (companyResult.status === 'rejected') { supportingDataErrors.value.push(`企业资料加载失败:${errorMessage(companyResult.reason)}`) } if (ordersResult.status === 'rejected' && !store.loadError) { @@ -510,7 +515,7 @@ async function saveDraft() { async function submitOrder() { if (saving.value) return - if (!companyApproved.value) { + if (companySubmissionBlocked.value) { try { await ElMessageBox.confirm('企业资料审核通过后才能提交订单。您可以继续保存草稿,或前往企业资料核对并补充信息。', '暂时无法提交订单', { type: 'warning', @@ -530,7 +535,8 @@ async function submitOrder() { try { saving.value = true - const order = await store.submit(cloneDraft(form), tenantStore.company.companyName, editingId.value, tenantStore.company.auditStatus) + const knownCompanyAuditStatus = companyAuditLoaded.value ? tenantStore.company.auditStatus : undefined + const order = await store.submit(cloneDraft(form), tenantStore.company.companyName, editingId.value, knownCompanyAuditStatus) markEditorClean() editorOpen.value = false if (isCreatePage.value) await router.push({ name: 'first-leg-orders' }) @@ -569,10 +575,10 @@ async function searchOrders(model: QueryModel) {
订单列表共 {{ filteredOrders.length }} 条
创建订单 -
+
{{ canCreateOrder ? '企业资料待审核,当前仅可保存订单草稿' : '企业资料待审核,当前订单为只读' }}{{ canCreateOrder ? '平台审核通过后即可提交;您仍可创建、编辑和保存草稿。' : '您当前拥有只读权限,可以继续查看订单进展。' }}
- 查看企业资料 + 查看企业资料