From 590a457dcd0581bccd357366145ea81e6d11b2de Mon Sep 17 00:00:00 2001 From: ouyangxq <775153912@qq.com> Date: Fri, 14 Aug 2026 12:50:42 +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 --- AGENTS.md | 1 + .../pages/ContainersView.vue | 23 +++++++++++--- .../pages/GlobalSmartLoadingView.vue | 31 +++++++++++++++---- src/modules/container-loading/types.ts | 1 + .../customers/pages/CustomersView.test.ts | 7 +++++ src/modules/customers/pages/CustomersView.vue | 4 +-- .../customs/pages/CustomsCasesView.vue | 12 +++++-- src/modules/finance/api/finance.test.ts | 4 +-- src/modules/finance/api/finance.ts | 4 +-- src/modules/finance/financeDelivery.test.ts | 7 ++++- .../pages/FinanceCustomerAccountsView.test.ts | 11 ++++++- .../pages/FinanceCustomerAccountsView.vue | 31 ++++++++++++++----- .../finance/pages/FinanceCustomerArapView.vue | 4 +-- .../pages/FinanceCustomerStatementsView.vue | 7 +++-- .../pages/FinanceFormalSettlementPage.vue | 10 ++++-- .../finance/pages/FinanceManualPage.test.ts | 8 ++++- .../finance/pages/FinanceManualPage.vue | 12 +++++-- .../finance/pages/FinancePresentation.test.ts | 11 +++++++ .../PlatformFirstLegOrdersPanel.vue | 4 +-- .../components/PlatformTenantSelector.test.ts | 29 ++++++++++++----- .../iam/components/PlatformTenantSelector.vue | 8 ++--- .../inbounds/components/InboundTaskList.vue | 4 +-- .../inbounds/pages/InboundOrdersView.test.ts | 2 +- .../inbounds/pages/InboundOrdersView.vue | 4 +-- .../loading-lists/api/platformLoadingLists.ts | 1 + .../components/LoadingListsView.vue | 20 +++++++++++- .../pages/OceanBookingDetailView.vue | 9 +++--- .../pages/OceanBookingsView.vue | 20 +++++++----- .../pages/OutboundDispatchesView.vue | 6 ++-- .../pages/PortSchedulesView.test.ts | 2 +- .../pages/PortSchedulesView.vue | 12 +++---- src/modules/port-schedules/types.ts | 2 +- .../components/TruckAppointmentForm.vue | 9 +++--- .../trucking/pages/TruckAppointmentsView.vue | 12 ++++--- src/modules/trucking/types.ts | 1 + .../pages/UnifiedOrdersView.vue | 4 +-- 36 files changed, 242 insertions(+), 95 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index ba27cd7b..911fc0f1 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -91,6 +91,7 @@ - 删除、停用、改权限等高风险操作必须有明确确认、处理中、成功和失败反馈;失败时保留用户上下文,避免误以为已生效。 - 日志、提示和示例数据不得包含真实账号、令牌、客户隐私或生产数据。 - Admin 维护客户专属数据时,必须通过平台客户列表显式选择目标客户,不得从本地存储推断客户。平台仓库等公共主数据不要求先选择客户;切换客户时不得保留上一客户的编辑、详情或导入上下文。 +- Finance 五个正式列表页(客户账户、客户应收应付、客户对账单、应收结算单、应付结算单)的客户筛选统一加载全部 `ACTIVE` 客户并使用可筛选下拉框;用户可见选项只显示客户名称 `tenantName`,以 `customerId` 作为接口筛选值。不得恢复自由输入客户关键词,也不得把客户编码、联系人或手机号拼入下拉标签。业务单号、费用项目等非客户关键词仍使用各自独立筛选字段。 ## UI 与交互 diff --git a/src/modules/container-loading/pages/ContainersView.vue b/src/modules/container-loading/pages/ContainersView.vue index 2a4dd132..5b61ff7f 100644 --- a/src/modules/container-loading/pages/ContainersView.vue +++ b/src/modules/container-loading/pages/ContainersView.vue @@ -4,6 +4,7 @@ import { useRouter } from 'vue-router' import { Boxes, Check, Eye, FileText, FileUp, ListChecks, MoreHorizontal, Pencil, Sparkles, TriangleAlert } from '@lucide/vue' import { ElMessage, type FormInstance, type FormRules, type UploadFile } from 'element-plus' import { useAccessPreviewStore } from '@/core/access/accessPreview' +import { listPlatformTenants, type PlatformTenantResource } from '@/modules/iam' import { listAllPlatformWarehouses, type PlatformWarehouseSummaryResource } from '@/modules/warehouses' import { listPlatformPartners, type PlatformPartnerResource } from '@/modules/master-data' import { listOceanBookings, type OceanBookingResource } from '@/modules/ocean-bookings' @@ -21,12 +22,14 @@ import ContainerOverviewPanel from '../components/ContainerOverviewPanel.vue' import { cancelContainerException, completeContainerClearance, downloadContainerDocument, downloadContainerPdaPhoto, getContainer, getContainerClearance, getContainerOverview, listContainers, markContainerException, updateContainer, updateContainerTransport, uploadContainerClearance, uploadContainerDocument } from '../api/platformContainerLoading' import type { ContainerBookingResource, ContainerDocumentType, ContainerOverview, ContainerOverviewDocument, ContainerPdaPhoto, ContainerPlanStatus, ContainerSaveRequest } from '../types' -type Filters = QueryModel & { keyword: string; containerType: string; status: ContainerPlanStatus | ''; sailingRange: string[] } +type Filters = QueryModel & { customerId: string; keyword: string; containerType: string; status: ContainerPlanStatus | ''; sailingRange: string[] } type ContainerForm = ContainerSaveRequest & { id: string; version: number } const router = useRouter() const access = useAccessPreviewStore() const rows = ref([]) +const customers = ref([]) +const customersLoading = ref(false) const warehouses = ref([]) const destinationWarehouses = ref([]) const partners = ref([]) @@ -40,7 +43,7 @@ const businessOptionsError = ref('') const page = ref(1) const pageSize = ref(20) const total = ref(0) -const filters = ref({ keyword: '', containerType: '', status: '', sailingRange: [] }) +const filters = ref({ customerId: '', keyword: '', containerType: '', status: '', sailingRange: [] }) const applied = ref({ ...filters.value }) const detailOpen = ref(false) const detailLoading = ref(false) @@ -132,6 +135,7 @@ const shippingCompanyValue = computed(() => form.shippingCompanyId || (form.ship const destinationWarehouseValue = computed(() => form.destinationWarehouseCode || (form.destinationWarehouseName ? `name:${form.destinationWarehouseName}` : '')) const queryFields = computed(() => [ + { key: 'customerId', type: 'select', label: '客户', width: 220, placeholder: '全部客户', options: customers.value.filter((customer) => customer.status === 'ACTIVE').map((customer) => ({ label: customer.legalName?.trim() || customer.tenantName, value: String(customer.id) })), props: { filterable: true, loading: customersLoading.value } }, { key: 'keyword', type: 'input', label: '关键词', width: 220, placeholder: '柜次号、柜号或提单号', props: { 'aria-label': '关键词', maxlength: 128 } }, { key: 'containerType', type: 'select', label: '柜型', width: 140, options: ['20GP', '40GP', '40HQ', '45HQ'].map((value) => ({ label: value, value })), props: { 'aria-label': '柜型' } }, { key: 'status', type: 'select', label: '排柜状态', width: 150, options: [{ label: '待装柜', value: 'WAIT_LOADING' }, { label: '预装柜中', value: 'EDITING' }, { label: '拣货中', value: 'LOADING' }, { label: '装柜完成', value: 'COMPLETED' }], props: { 'aria-label': '排柜状态' } }, @@ -234,6 +238,17 @@ async function loadWarehouses() { catch (error) { warehouseError.value = getApiErrorDetails(error, '装柜仓库加载失败') } finally { warehouseLoading.value = false } } +async function loadCustomers() { + customersLoading.value = true + try { + const result = await listPlatformTenants({ page: 1, size: 200, status: 'ACTIVE' }) + customers.value = result.records.filter((customer) => customer.status === 'ACTIVE') + } catch { + customers.value = [] + } finally { + customersLoading.value = false + } +} async function loadBusinessOptions() { businessOptionsLoading.value = true businessOptionsError.value = '' @@ -267,7 +282,7 @@ async function loadRows() { const [from, to] = applied.value.sailingRange || [] try { const result = await listContainers({ - page: page.value, size: pageSize.value, keyword: applied.value.keyword.trim() || undefined, + page: page.value, size: pageSize.value, customerId: applied.value.customerId || undefined, keyword: applied.value.keyword.trim() || undefined, containerType: applied.value.containerType || undefined, status: applied.value.status, estimatedSailingFrom: from ? `${from}T00:00:00` : undefined, estimatedSailingTo: to ? `${to}T23:59:59` : undefined, @@ -428,7 +443,7 @@ function goContainerProcess(source: object) { watch([page, pageSize], ([nextPage, nextSize], [previousPage, previousSize]) => { if (nextPage !== previousPage || nextSize !== previousSize) void loadRows() }) -onMounted(() => { void Promise.all([loadWarehouses(), loadBusinessOptions(), loadRows()]) }) +onMounted(() => { void Promise.all([loadCustomers(), loadWarehouses(), loadBusinessOptions(), loadRows()]) })