From 6bada2aca9b30c1afdef23c41fc742adf511009c Mon Sep 17 00:00:00 2001 From: ouyangxq <775153912@qq.com> Date: Tue, 29 Sep 2026 13:50:05 +0800 Subject: [PATCH] fix(admin): clarify customs results and apply dialog density --- src/deployment/nginxConfig.test.ts | 2 +- .../components/ContainerCustomsPanel.test.ts | 38 ++++++++++++++++++- .../components/ContainerCustomsPanel.vue | 12 ++++-- .../fee-items/pages/FeeItemsView.test.ts | 2 +- 4 files changed, 47 insertions(+), 7 deletions(-) diff --git a/src/deployment/nginxConfig.test.ts b/src/deployment/nginxConfig.test.ts index 58d0630d..6a8f0f47 100644 --- a/src/deployment/nginxConfig.test.ts +++ b/src/deployment/nginxConfig.test.ts @@ -2,7 +2,7 @@ import { readFileSync } from 'node:fs' import { resolve } from 'node:path' import { describe, expect, it } from 'vitest' -const config = readFileSync(resolve(process.cwd(), 'nginx/default.conf.template'), 'utf8') +const config = readFileSync(resolve(process.cwd(), 'nginx/default.conf.template'), 'utf8').replace(/\r\n/g, '\n') const testCompose = readFileSync(resolve(process.cwd(), 'docker-compose.test.yml'), 'utf8') const developmentCompose = readFileSync(resolve(process.cwd(), 'docker-compose.development.yml'), 'utf8') const productionCompose = readFileSync(resolve(process.cwd(), 'docker-compose.production.yml'), 'utf8') diff --git a/src/modules/container-loading/components/ContainerCustomsPanel.test.ts b/src/modules/container-loading/components/ContainerCustomsPanel.test.ts index f5fd91b7..e6f4e900 100644 --- a/src/modules/container-loading/components/ContainerCustomsPanel.test.ts +++ b/src/modules/container-loading/components/ContainerCustomsPanel.test.ts @@ -2,7 +2,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest' import { flushPromises, mount } from '@vue/test-utils' import ElementPlus from 'element-plus' import { ApiResponseError } from '@/shared/api/http' -import type { ContainerCustomsStatus, ContainerCustomsView } from '../api/platformContainerCustoms' +import type { ContainerCustomsStatus, ContainerCustomsView, DeclarationBatch, ClearanceResultType } from '../api/platformContainerCustoms' const api = vi.hoisted(() => ({ get: vi.fn(), @@ -77,6 +77,42 @@ describe('ContainerCustomsPanel', () => { vi.spyOn(HTMLAnchorElement.prototype, 'click').mockImplementation(() => undefined) }) + it('renders all customs result reasons in Chinese with the recorded remarks', async () => { + const reasons: Array<[ClearanceResultType, string]> = [ + ['INSPECTION', '查验'], ['SUPPLEMENT_REQUIRED', '补资料'], + ['DETAINED', '扣货'], ['RELEASED', '放行'], ['OTHER', '其他'], + ] + const batch: DeclarationBatch = { + id: '101', customsContainerId: '102', loadingPlanId: '2092438843630391402', + batchNo: 'DEC-TEST-001', status: 'RESULT_PENDING', sourceVersion: 1, + customsEntryNo: 'ENTRY-TEST-001', version: 1, submittedAt: null, + submittedByName: null, acknowledgedAt: null, acknowledgedByName: null, remark: null, + results: reasons.map(([resultType], index) => ({ + id: String(200 + index), declarationBatchId: '101', customsContainerId: '102', + resultType, resultStatus: 'OPEN', customsEntryNo: 'ENTRY-TEST-001', + occurredAt: '2026-09-29T10:00:00', resolution: `人工备注${index}`, + evidenceFileId: null, recordedByName: '操作员', recordedAt: '2026-09-29T10:00:00', + previousResultId: null, + })), + } + api.getDeclarationBatches.mockResolvedValue([batch]) + api.get.mockResolvedValue({ ...customs('COMPLETED', true), brokerSubmittedAt: '2026-09-29T09:00:00' }) + const wrapper = mount(ContainerCustomsPanel, { + props: { loadingPlanId: batch.loadingPlanId, canList: true, canManage: false, departureState: 'WAITING_OTHER_GATES' }, + global: { plugins: [ElementPlus] }, + }) + await flushPromises() + const rows = wrapper.findAll('.declaration-result-row') + expect(rows).toHaveLength(reasons.length) + for (const [index, [code, label]] of reasons.entries()) { + expect(rows[index]!.text()).toContain(label) + expect(rows[index]!.text()).toContain(`人工备注${index}`) + expect(rows[index]!.text()).not.toContain(code) + expect(rows[index]!.find('button').exists()).toBe(false) + } + wrapper.unmount() + }) + it('keeps READY_TO_START read-only while exposing source file name and download', async () => { const wrapper = await render('READY_TO_START') expect(wrapper.text()).toContain('开始报关') diff --git a/src/modules/container-loading/components/ContainerCustomsPanel.vue b/src/modules/container-loading/components/ContainerCustomsPanel.vue index 30cb8a4c..041c9db4 100644 --- a/src/modules/container-loading/components/ContainerCustomsPanel.vue +++ b/src/modules/container-loading/components/ContainerCustomsPanel.vue @@ -59,6 +59,10 @@ const clearanceResultOptions: Array<{ value: ClearanceResultType; label: string { value: 'OTHER', label: '其他' }, ] +function clearanceResultLabel(value: ClearanceResultType) { + return clearanceResultOptions.find((option) => option.value === value)?.label || '未知结果' +} + const missingInbounds = computed(() => customs.value?.inbounds.filter((item) => item.taxMode === 'TAX_REFUND' && !item.covered) || []) const missingCoverageCount = computed(() => Math.max(0, (customs.value?.taxRefundCount || 0) - (customs.value?.coveredTaxRefundCount || 0))) const allBuy = computed(() => customs.value?.hasActualCargo === true && customs.value.taxRefundCount === 0) @@ -152,8 +156,8 @@ async function recordFormalResult() { try { await recordClearanceResult(batch, clearanceResultType.value, clearanceRemark.value.trim() || undefined) clearanceDialogVisible.value = false - await load(); ElMessage.success('海关异常节点已标记') - } catch (error) { actionError.value = getApiErrorDetails(error, '海关异常节点标记失败') } + await load(); ElMessage.success('海关结果已记录') + } catch (error) { actionError.value = getApiErrorDetails(error, '海关结果记录失败') } finally { actionLoading.value = false } } @@ -329,7 +333,7 @@ onMounted(load)
{{ batch.batchNo }}报关单号:{{ batch.customsEntryNo || '—' }} · 版本 {{ batch.version }}
{{ declarationStatusLabel(batch.status) }}
提交正式申报标记海关异常/结果
-
{{ result.resultType === 'INSPECTION' ? '查验' : result.resultType === 'SUPPLEMENT_REQUIRED' ? '补充资料' : result.resultType === 'RELEASED' ? '放行' : result.resultType }}{{ result.resultStatus === 'RESOLVED' ? '已处理' : result.resultStatus === 'OPEN' ? '待处理' : '已取消' }}{{ result.resolution || '—' }}处理
+
{{ clearanceResultLabel(result.resultType) }}{{ result.resultStatus === 'RESOLVED' ? '已处理' : result.resultStatus === 'OPEN' ? '待处理' : '已取消' }}{{ result.resolution || '—' }}处理
@@ -337,7 +341,7 @@ onMounted(load)
国内离仓状态:{{ departureState === 'DEPARTED' ? '已自动离仓' : departureState === 'UNKNOWN' ? '离仓状态尚未读取' : '报关已完成,待其他离仓条件' }}
- + diff --git a/src/modules/fee-items/pages/FeeItemsView.test.ts b/src/modules/fee-items/pages/FeeItemsView.test.ts index 5742b7af..039fd831 100644 --- a/src/modules/fee-items/pages/FeeItemsView.test.ts +++ b/src/modules/fee-items/pages/FeeItemsView.test.ts @@ -9,7 +9,7 @@ import { useAuthStore } from '@/core/auth/auth' import { listPlatformFeeItems } from '@/modules/fee-items/api/platformFeeItems' import FeeItemsView from './FeeItemsView.vue' -const source = readFileSync(join(process.cwd(), 'src/modules/fee-items/pages/FeeItemsView.vue'), 'utf8') +const source = readFileSync(join(process.cwd(), 'src/modules/fee-items/pages/FeeItemsView.vue'), 'utf8').replace(/\r\n/g, '\n') vi.mock('@/modules/fee-items/api/platformFeeItems', () => ({ listPlatformFeeItems: vi.fn(),