This commit is contained in:
2026-10-22 11:56:47 +08:00
parent 5d71af1ac9
commit de96e47d74
71 changed files with 1296 additions and 332 deletions
@@ -316,7 +316,47 @@ export async function resolvePickerAccess(context) {
return { role, operate }
}
async function reusePicker(context, index, overseasWarehouseId, access) {
const actors = context.options.fixedPdaActors
context.fixedPdaLeases ??= new Set()
const actor = Array.isArray(actors) && actors.find(item => id(item?.warehouseId) === id(overseasWarehouseId)
&& longId(item.membershipId) && nonBlank(item.username) && nonBlank(item.password)
&& !context.fixedPdaLeases.has(id(item.membershipId)))
if (!actor) {
context.addStep(MODULE, `固定PDA操作员${index}前置`, null, false, '缺少该仓未占用的固定账号,禁止自动创建', OPTIONS)
return null
}
let token, refreshToken
try {
let user
for (let page = 1; ; page++) {
const result = await context.request('GET', `/api/platform/v1/iam/users?page=${page}&size=100&keyword=${encodeURIComponent(actor.username)}`)
const data = context.apiSuccess(MODULE, '核对固定PDA账号', result, '', OPTIONS)
user = data?.records?.find(item => id(item.membershipId) === id(actor.membershipId) && item.username === actor.username)
if (user || !data?.records?.length || page * Number(data.size || 100) >= Number(data.total || 0)) break
}
if (user?.status !== 'ACTIVE' || id(user.tenantId) !== '0'
|| id(user.overseasWarehouseId) !== id(overseasWarehouseId)
|| !user.roleIds?.map(id).includes(id(access.role.id))) throw Error('固定PDA账号状态、角色或仓绑定不匹配')
const login = await context.request('POST', '/api/auth/login', { loginId: actor.username, password: actor.password }, '')
const session = context.apiSuccess(MODULE, '登录固定PDA账号', login, '', OPTIONS)
token = session?.accessToken; refreshToken = session?.refreshToken
if (token || refreshToken) context.fixedPdaLeases.add(id(actor.membershipId))
if (!token || !refreshToken) throw Error('固定PDA登录未返回完整会话')
const projection = await context.request('GET', '/api/pda/v1/last-leg/receiving-containers/current', undefined, token, {})
if (!success(projection) && !notFound(projection)) throw Error('固定PDA作业权限检查失败')
return { membershipId: id(actor.membershipId), username: actor.username, token, refreshToken, reused: true }
} catch (error) {
if (token && refreshToken) await disablePicker(context, {
membershipId: id(actor.membershipId), token, refreshToken, reused: true,
}, index)
context.addStep(MODULE, `固定PDA操作员${index}核验失败`, null, false, error.message, OPTIONS)
return null
}
}
export async function createPicker(context, index, overseasWarehouseId, access) {
if (context.options?.fixedCustomerId) return reusePicker(context, index, overseasWarehouseId, access)
const role = access.role
const suffix = pickerFixtureSuffix(context)
const username = `pda_overseas_${suffix.toLowerCase()}_${index}`.slice(0, 64)
@@ -359,13 +399,26 @@ export async function createPicker(context, index, overseasWarehouseId, access)
export function pickerSessionHandoff(picker) {
if (!picker) return null
const { membershipId, username, token, refreshToken, password, userUpdate } = picker
return { membershipId, username, token, refreshToken, password,
const { membershipId, username, token, refreshToken, password, userUpdate, reused } = picker
return { membershipId, username, token, refreshToken, password, reused,
userUpdate: userUpdate ? { ...userUpdate, roleIds: [...userUpdate.roleIds] } : undefined }
}
export async function disablePicker(context, picker, index) {
if (!longId(picker?.membershipId)) return
if (picker.reused) {
if (!context.fixedPdaLeases?.has(id(picker.membershipId))) return
let response
try {
response = await context.request('POST', '/api/auth/logout', { refreshToken: picker.refreshToken }, picker.token)
} catch {
context.addStep(MODULE, `退出固定PDA操作员${index}会话失败`, null, false, '退出请求异常;保留账号占用,继续清理其他会话', OPTIONS)
return
}
context.addStep(MODULE, `退出固定PDA操作员${index}会话,不停用账号`, response, success(response), trace(response), OPTIONS)
if (success(response)) context.fixedPdaLeases.delete(id(picker.membershipId))
return
}
const response = await context.request('PUT', `/api/platform/v1/iam/users/${picker.membershipId}/status`, { status: 'DISABLED' })
const disabled = success(response) && response.body?.data?.status === 'DISABLED'
context.addStep(MODULE, `finally停用海外PDA仓库操作员${index}`, response, disabled, trace(response), OPTIONS)