From fed257a72070a0c44d120d3b3236ec58d59af5eb Mon Sep 17 00:00:00 2001 From: liuyihe <2513762445@qq.com> Date: Tue, 22 Sep 2026 13:51:58 +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 --- src/modules/iam/api/platformIam.ts | 3 + src/modules/iam/pages/InternalUsersView.vue | 50 +++++++++++++ .../api/platformLoadingLists.test.ts | 4 +- .../loading-lists/api/platformLoadingLists.ts | 16 ++++- .../components/LoadingListDetailDrawer.vue | 40 +++++++---- .../components/LoadingListsView.test.ts | 6 +- .../pages/PreloadPlanDetailView.test.ts | 28 ++++++-- .../pages/PreloadPlanDetailView.vue | 72 ++++++++++++++----- 8 files changed, 174 insertions(+), 45 deletions(-) diff --git a/src/modules/iam/api/platformIam.ts b/src/modules/iam/api/platformIam.ts index e6f4cf31..29ab981e 100644 --- a/src/modules/iam/api/platformIam.ts +++ b/src/modules/iam/api/platformIam.ts @@ -267,6 +267,7 @@ export interface PlatformManagedUser { lastLoginAt: string | null protectedAccount: boolean overseasWarehouseId: number | string | null + domesticWarehouseId?: number | string | null } export interface PlatformManagedUserPage { @@ -309,6 +310,7 @@ export interface CreatePlatformManagedUserRequest { tenantId: number | string roleIds: Array overseasWarehouseId: number | string | null + domesticWarehouseId?: number | string | null password: string status: 'ACTIVE' | 'DISABLED' } @@ -320,6 +322,7 @@ export interface UpdatePlatformManagedUserRequest { tenantId: number | string roleIds: Array overseasWarehouseId: number | string | null + domesticWarehouseId?: number | string | null } async function getData(path: string): Promise { diff --git a/src/modules/iam/pages/InternalUsersView.vue b/src/modules/iam/pages/InternalUsersView.vue index dbb66ecd..6506d2e7 100644 --- a/src/modules/iam/pages/InternalUsersView.vue +++ b/src/modules/iam/pages/InternalUsersView.vue @@ -29,6 +29,7 @@ import LoadErrorState from '@/shared/components/LoadErrorState.vue' import { useUnsavedWorkRegistration } from '@/core/unsaved-work/useUnsavedWorkRegistration' import { useAccessPreviewStore } from '@/core/access/accessPreview' import { useAuthStore } from '@/core/auth/auth' +import { listAllPlatformWarehouses, type PlatformWarehouseSummaryResource } from '@/modules/warehouses' const access = useAccessPreviewStore() const auth = useAuthStore() @@ -37,6 +38,9 @@ const options = ref({ tenants: [], roles: [] }) const overseasWarehouses = ref([]) const overseasWarehousesLoading = ref(false) const overseasWarehousesError = ref(null) +const domesticWarehouses = ref([]) +const domesticWarehousesLoading = ref(false) +const domesticWarehousesError = ref(null) const loading = ref(false) const saving = ref(false) const loadError = ref(null) @@ -81,6 +85,7 @@ const emptyForm = () => ({ tenantId: '0', roleIds: [] as string[], overseasWarehouseId: '', + domesticWarehouseId: '', password: '', confirmPassword: '', status: 'ACTIVE' as 'ACTIVE' | 'DISABLED', @@ -111,6 +116,10 @@ const overseasPdaRoleIds = computed(() => new Set( availableRoles.value.filter((role) => role.roleCode === 'OVERSEAS_WAREHOUSE_PDA_OPERATOR').map((role) => String(role.id)), )) const hasOverseasPdaRole = computed(() => form.roleIds.some((roleId) => overseasPdaRoleIds.value.has(roleId))) +const domesticPdaRoleIds = computed(() => new Set( + availableRoles.value.filter((role) => role.roleCode === 'CN_FIRSTLEG_PDA_OPERATOR').map((role) => String(role.id)), +)) +const hasDomesticPdaRole = computed(() => form.roleIds.some((roleId) => domesticPdaRoleIds.value.has(roleId))) const formRules = computed(() => ({ username: editingUser.value ? [] : [ @@ -127,6 +136,9 @@ const formRules = computed(() => ({ overseasWarehouseId: !hasOverseasPdaRole.value || (editingUser.value && !canEdit.value) ? [] : [ { required: true, message: '请选择实际海外收货仓', trigger: 'change' }, ], + domesticWarehouseId: !hasDomesticPdaRole.value || (editingUser.value && !canEdit.value) ? [] : [ + { required: true, message: '请选择国内作业仓', trigger: 'change' }, + ], password: editingUser.value && !form.resetPassword ? [] : [ { required: true, message: '请输入密码', trigger: 'blur' }, { pattern: /^(?=.*[A-Za-z])(?=.*\d).{8,64}$/, message: '密码为 8-64 位,且必须包含字母和数字', trigger: 'blur' }, @@ -217,6 +229,7 @@ function openEdit(row: PlatformManagedUser) { tenantId: '0', roleIds: row.roleIds.map(String), overseasWarehouseId: row.overseasWarehouseId == null ? '' : String(row.overseasWarehouseId), + domesticWarehouseId: row.domesticWarehouseId == null ? '' : String(row.domesticWarehouseId), password: '', confirmPassword: '', status: row.status, @@ -243,6 +256,19 @@ async function loadOverseasWarehouses() { } } +async function loadDomesticWarehouses() { + domesticWarehousesLoading.value = true + domesticWarehousesError.value = null + try { + domesticWarehouses.value = await listAllPlatformWarehouses({ warehouseType: 'DOMESTIC', status: 'ACTIVE' }) + } catch (error) { + domesticWarehouses.value = [] + domesticWarehousesError.value = getApiErrorDetails(error, '国内作业仓加载失败,请重试') + } finally { + domesticWarehousesLoading.value = false + } +} + function isCurrentUser(row: PlatformManagedUser | null) { if (!row) return false return String(row.userId) === auth.user?.id || String(row.authUserId) === auth.user?.id @@ -266,6 +292,7 @@ async function saveUser() { tenantId: '0', roleIds: form.roleIds, overseasWarehouseId: hasOverseasPdaRole.value ? form.overseasWarehouseId : null, + ...(hasDomesticPdaRole.value ? { domesticWarehouseId: form.domesticWarehouseId } : {}), password: form.password, status: form.status, }) @@ -280,6 +307,7 @@ async function saveUser() { tenantId: '0', roleIds: form.roleIds, overseasWarehouseId: hasOverseasPdaRole.value ? form.overseasWarehouseId : null, + ...(hasDomesticPdaRole.value ? { domesticWarehouseId: form.domesticWarehouseId } : {}), }) } if (canChangeStatus.value && form.status !== row.status) { @@ -340,6 +368,14 @@ watch(hasOverseasPdaRole, (selected) => { } void loadOverseasWarehouses() }) +watch(hasDomesticPdaRole, (selected) => { + if (!selected) { + form.domesticWarehouseId = '' + domesticWarehousesError.value = null + return + } + void loadDomesticWarehouses() +}) onMounted(loadInitialData) @@ -435,6 +471,20 @@ onMounted(loadInitialData)

仓库将写入登录 Token,海外 PDA 不提供仓库切换。

+ + + + +

+ {{ domesticWarehousesError.message }} + 重新加载 +

+

该人员只会出现在此仓库的国内头程 PDA 任务候选中。

+
diff --git a/src/modules/loading-lists/api/platformLoadingLists.test.ts b/src/modules/loading-lists/api/platformLoadingLists.test.ts index fd6a5f27..83037d75 100644 --- a/src/modules/loading-lists/api/platformLoadingLists.test.ts +++ b/src/modules/loading-lists/api/platformLoadingLists.test.ts @@ -146,11 +146,11 @@ describe('platform loading lists API', () => { }, }) - const result = await confirmPreloadPlan('1900000000000000001', 3, 'confirm-operation-1') + const result = await confirmPreloadPlan('1900000000000000001', 3, '1900000000000000007', 'confirm-operation-1') expect(post).toHaveBeenCalledWith( '/platform/v1/first-leg/loading-plans/1900000000000000001/confirm', - { expectedVersion: 3 }, + { expectedVersion: 3, assigneeId: '1900000000000000007' }, { headers: { 'Idempotency-Key': 'confirm-operation-1' } }, ) expect(result).toMatchObject({ diff --git a/src/modules/loading-lists/api/platformLoadingLists.ts b/src/modules/loading-lists/api/platformLoadingLists.ts index 6248fe26..8c41c447 100644 --- a/src/modules/loading-lists/api/platformLoadingLists.ts +++ b/src/modules/loading-lists/api/platformLoadingLists.ts @@ -186,6 +186,11 @@ export interface PreloadConfirmationResponse { readiness: PreloadReadiness } +export interface DomesticPdaOperator { + userId: string + displayName: string +} + type RawId = string | number | null | undefined type RawPage = Omit, 'page' | 'size' | 'total' | 'pages'> & { page: string | number @@ -359,10 +364,17 @@ export async function updateLoadingItemRemarks(planId: string, itemId: string, r } } -export async function confirmPreloadPlan(planId: string, expectedVersion: number, operationId: string) { +export async function listDomesticPdaOperators(warehouseId: string, keyword?: string): Promise { + const response = await http.get, ApiEnvelope>( + '/platform/v1/iam/users/domestic-pda-operators', { params: { warehouseId, keyword } }, + ) + return unwrapApiResponse(response).map((operator) => ({ ...operator, userId: requiredId(operator.userId) })) +} + +export async function confirmPreloadPlan(planId: string, expectedVersion: number, assigneeId: string, operationId: string) { const response = await http.post, ApiEnvelope>( `${basePath}/loading-plans/${encodeURIComponent(planId)}/confirm`, - { expectedVersion }, + { expectedVersion, assigneeId }, { headers: { 'Idempotency-Key': operationId } }, ) const result = unwrapApiResponse(response) diff --git a/src/modules/loading-lists/components/LoadingListDetailDrawer.vue b/src/modules/loading-lists/components/LoadingListDetailDrawer.vue index 00c9f868..7278b72d 100644 --- a/src/modules/loading-lists/components/LoadingListDetailDrawer.vue +++ b/src/modules/loading-lists/components/LoadingListDetailDrawer.vue @@ -1,7 +1,7 @@