优化领取页角色绑定校验
This commit is contained in:
@@ -248,6 +248,16 @@ export function mapClaimKuaishouCloudFulfillment(task: TaskRow, order: OrderRow)
|
||||
const dispatch = source.dispatch && typeof source.dispatch === 'object' ? source.dispatch : {}
|
||||
const returnNumber = source.returnNumber && typeof source.returnNumber === 'object' ? source.returnNumber : {}
|
||||
const consume = source.consume && typeof source.consume === 'object' ? source.consume : {}
|
||||
const roleName = String(role.name || binding.roleName || '').trim()
|
||||
const roleId = String(role.rid || binding.roleId || '').trim()
|
||||
const defaultRoleName = String(role.defaultName || role.defaultRoleName || '').trim()
|
||||
const defaultRoleId = String(role.defaultRid || role.defaultRoleId || '').trim()
|
||||
const isDefaultRole =
|
||||
Boolean(roleName || roleId) &&
|
||||
isSameClaimKuaishouCloudRole(
|
||||
{ name: roleName, rid: roleId },
|
||||
{ name: defaultRoleName, rid: defaultRoleId },
|
||||
)
|
||||
|
||||
return {
|
||||
flowType: 'kuaishou_cloud',
|
||||
@@ -288,10 +298,16 @@ export function mapClaimKuaishouCloudFulfillment(task: TaskRow, order: OrderRow)
|
||||
},
|
||||
role: {
|
||||
status: String(role.status || 'pending').trim() || 'pending',
|
||||
name: String(role.name || binding.roleName || '').trim(),
|
||||
rid: String(role.rid || binding.roleId || '').trim(),
|
||||
name: roleName,
|
||||
rid: roleId,
|
||||
refreshedAt: role.refreshedAt || null,
|
||||
errorMessage: String(role.errorMessage || '').trim(),
|
||||
defaultName: defaultRoleName,
|
||||
defaultRid: defaultRoleId,
|
||||
defaultCapturedAt: role.defaultCapturedAt || null,
|
||||
defaultCaptureStatus: String(role.defaultCaptureStatus || '').trim(),
|
||||
defaultErrorMessage: String(role.defaultErrorMessage || '').trim(),
|
||||
isDefaultRole,
|
||||
},
|
||||
purchase: {
|
||||
autoBuyEnabled: purchase.autoBuyEnabled !== false,
|
||||
@@ -351,6 +367,28 @@ function isPlainObject(value: unknown): value is JsonObject {
|
||||
return Object.prototype.toString.call(value) === '[object Object]'
|
||||
}
|
||||
|
||||
function isSameClaimKuaishouCloudRole(
|
||||
left: { name?: unknown; rid?: unknown },
|
||||
right: { name?: unknown; rid?: unknown },
|
||||
) {
|
||||
const leftRid = String(left.rid || '').trim()
|
||||
const rightRid = String(right.rid || '').trim()
|
||||
if (leftRid && rightRid) {
|
||||
return leftRid === rightRid
|
||||
}
|
||||
|
||||
const leftName = normalizeClaimRoleNameForCompare(left.name)
|
||||
const rightName = normalizeClaimRoleNameForCompare(right.name)
|
||||
return Boolean(leftName && rightName && leftName === rightName)
|
||||
}
|
||||
|
||||
function normalizeClaimRoleNameForCompare(value: unknown) {
|
||||
return String(value || '')
|
||||
.trim()
|
||||
.toLowerCase()
|
||||
.replace(/\s+/g, '')
|
||||
}
|
||||
|
||||
function normalizeClaimDeliveryItems(value: unknown, binding: JsonObject) {
|
||||
const rawItems = Array.isArray(value) ? value : []
|
||||
const items = rawItems
|
||||
|
||||
@@ -26,6 +26,8 @@ import {
|
||||
import { isKuaishouEticketMockTicketCode } from '../platforms/kuaishou-eticket/mock-ticket-service.js'
|
||||
import {
|
||||
dispatchKuaishouCloudFulfillmentTask,
|
||||
hasKuaishouCloudCustomerRole,
|
||||
hasKuaishouCloudDefaultRoleSnapshot,
|
||||
maskCode,
|
||||
normalizeKuaishouCloudFlow,
|
||||
prepareKuaishouCloudFulfillmentTask,
|
||||
@@ -478,6 +480,19 @@ export async function confirmKuaishouCloudClaimRole(token: unknown) {
|
||||
})
|
||||
}
|
||||
|
||||
const hasDefaultRoleSnapshot = hasKuaishouCloudDefaultRoleSnapshot(flow)
|
||||
if (!mockMode && !hasKuaishouCloudCustomerRole(flow)) {
|
||||
const message = hasDefaultRoleSnapshot
|
||||
? '当前仍是虚拟机默认角色,请先重新绑定自己的角色信息'
|
||||
: '系统还未获取到虚拟机默认角色信息,请稍后刷新角色信息后再试'
|
||||
throw createHttpError(message, {
|
||||
statusCode: 409,
|
||||
errorCode: hasDefaultRoleSnapshot
|
||||
? 'claim_kuaishou_cloud_default_role_not_rebound'
|
||||
: 'claim_kuaishou_cloud_default_role_not_ready',
|
||||
})
|
||||
}
|
||||
|
||||
await updateTask(context.task.id, {
|
||||
task_status: TASK_STATUS.ROLE_CONFIRMED,
|
||||
role_id: flow.binding.roleId,
|
||||
|
||||
@@ -36,6 +36,7 @@ export async function syncKuaishouCloudRoleInfo(task: TaskRow) {
|
||||
source: 'claim_page_polling',
|
||||
actor: { source: 'system' },
|
||||
recordEvent: false,
|
||||
forceProbe: flow.role.isDefaultRole === true,
|
||||
})
|
||||
return result.task || task
|
||||
} catch {
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import test from 'node:test'
|
||||
|
||||
import {
|
||||
hasKuaishouCloudCustomerRole,
|
||||
normalizeKuaishouCloudFlow,
|
||||
} from './domain.js'
|
||||
|
||||
test('hasKuaishouCloudCustomerRole 要求当前角色不同于虚拟机默认角色', () => {
|
||||
const defaultRoleFlow = normalizeKuaishouCloudFlow({
|
||||
binding: {
|
||||
vnPhone: '13800000000',
|
||||
roleName: '默认角色',
|
||||
roleId: '10001',
|
||||
},
|
||||
role: {
|
||||
name: '默认角色',
|
||||
rid: '10001',
|
||||
defaultName: '默认角色',
|
||||
defaultRid: '10001',
|
||||
defaultCapturedAt: '2026-05-31T00:00:00.000Z',
|
||||
isDefaultRole: false,
|
||||
},
|
||||
})
|
||||
|
||||
assert.equal(defaultRoleFlow.role.isDefaultRole, true)
|
||||
assert.equal(hasKuaishouCloudCustomerRole(defaultRoleFlow), false)
|
||||
|
||||
const customerRoleFlow = normalizeKuaishouCloudFlow({
|
||||
...defaultRoleFlow,
|
||||
binding: {
|
||||
...defaultRoleFlow.binding,
|
||||
roleName: '用户角色',
|
||||
roleId: '20002',
|
||||
},
|
||||
role: {
|
||||
...defaultRoleFlow.role,
|
||||
name: '用户角色',
|
||||
rid: '20002',
|
||||
isDefaultRole: true,
|
||||
},
|
||||
})
|
||||
|
||||
assert.equal(customerRoleFlow.role.isDefaultRole, false)
|
||||
assert.equal(hasKuaishouCloudCustomerRole(customerRoleFlow), true)
|
||||
})
|
||||
@@ -25,6 +25,16 @@ export function normalizeKuaishouCloudFlow(value: unknown) {
|
||||
|
||||
const roleName = String(role.name || binding.roleName || '').trim()
|
||||
const roleId = String(role.rid || binding.roleId || '').trim()
|
||||
const defaultRoleName = String(role.defaultName || role.defaultRoleName || '').trim()
|
||||
const defaultRoleId = String(role.defaultRid || role.defaultRoleId || '').trim()
|
||||
const hasDefaultRole = Boolean(defaultRoleName || defaultRoleId)
|
||||
const isDefaultRole =
|
||||
Boolean(roleName || roleId) &&
|
||||
hasDefaultRole &&
|
||||
isSameKuaishouCloudRoleIdentity(
|
||||
{ name: roleName, rid: roleId },
|
||||
{ name: defaultRoleName, rid: defaultRoleId },
|
||||
)
|
||||
const bindPreparedAt = binding.bindPreparedAt || null
|
||||
const bindExpiresAt =
|
||||
binding.bindExpiresAt || resolveKuaishouCloudBindUrlExpiresAt(bindPreparedAt)
|
||||
@@ -72,6 +82,12 @@ export function normalizeKuaishouCloudFlow(value: unknown) {
|
||||
refreshedAt: role.refreshedAt || null,
|
||||
errorMessage: String(role.errorMessage || '').trim(),
|
||||
rawInfo: role.rawInfo && typeof role.rawInfo === 'object' ? role.rawInfo : null,
|
||||
defaultName: defaultRoleName,
|
||||
defaultRid: defaultRoleId,
|
||||
defaultCapturedAt: role.defaultCapturedAt || null,
|
||||
defaultCaptureStatus: String(role.defaultCaptureStatus || '').trim(),
|
||||
defaultErrorMessage: String(role.defaultErrorMessage || '').trim(),
|
||||
isDefaultRole,
|
||||
},
|
||||
purchase: {
|
||||
autoBuyEnabled: purchase.autoBuyEnabled !== false,
|
||||
@@ -113,6 +129,49 @@ export function normalizeKuaishouCloudFlow(value: unknown) {
|
||||
}
|
||||
}
|
||||
|
||||
export function hasKuaishouCloudDefaultRoleSnapshot(flowLike: unknown) {
|
||||
const flow = normalizeKuaishouCloudFlow(flowLike)
|
||||
return Boolean(flow.role.defaultName || flow.role.defaultRid)
|
||||
}
|
||||
|
||||
export function hasKuaishouCloudCustomerRole(flowLike: unknown) {
|
||||
const flow = normalizeKuaishouCloudFlow(flowLike)
|
||||
if (!flow.binding.vnPhone || !flow.binding.roleName || !flow.binding.roleId) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (!hasKuaishouCloudDefaultRoleSnapshot(flow)) {
|
||||
return false
|
||||
}
|
||||
|
||||
return !isSameKuaishouCloudRoleIdentity(
|
||||
{ name: flow.binding.roleName, rid: flow.binding.roleId },
|
||||
{ name: flow.role.defaultName, rid: flow.role.defaultRid },
|
||||
)
|
||||
}
|
||||
|
||||
export function isSameKuaishouCloudRoleIdentity(
|
||||
left: { name?: unknown; rid?: unknown },
|
||||
right: { name?: unknown; rid?: unknown },
|
||||
) {
|
||||
const leftRid = String(left.rid || '').trim()
|
||||
const rightRid = String(right.rid || '').trim()
|
||||
if (leftRid && rightRid) {
|
||||
return leftRid === rightRid
|
||||
}
|
||||
|
||||
const leftName = normalizeRoleNameForCompare(left.name)
|
||||
const rightName = normalizeRoleNameForCompare(right.name)
|
||||
return Boolean(leftName && rightName && leftName === rightName)
|
||||
}
|
||||
|
||||
function normalizeRoleNameForCompare(value: unknown) {
|
||||
return String(value || '')
|
||||
.trim()
|
||||
.toLowerCase()
|
||||
.replace(/\s+/g, '')
|
||||
}
|
||||
|
||||
export function normalizeKuaishouCloudDeliveryItems(value: unknown) {
|
||||
const source: JsonObject = value && typeof value === 'object' ? (value as JsonObject) : {}
|
||||
const binding = source.binding && typeof source.binding === 'object' ? source.binding : {}
|
||||
|
||||
@@ -15,8 +15,11 @@ import { nowIso } from '../../../utils/time.js'
|
||||
import { TASK_STATUS, normalizeTaskStatus } from '../../../domain/task-status.js'
|
||||
import {
|
||||
KUAISHOU_CLOUD_FIXED_VN_KEY,
|
||||
hasKuaishouCloudCustomerRole,
|
||||
hasKuaishouCloudDefaultRoleSnapshot,
|
||||
isKuaishouCloudBindUrlFresh,
|
||||
isKuaishouCloudTask,
|
||||
isSameKuaishouCloudRoleIdentity,
|
||||
maskPhone,
|
||||
normalizeKuaishouCloudFlow,
|
||||
normalizeKuaishouCloudRoleInfo,
|
||||
@@ -51,17 +54,125 @@ type CloudDeliveryPlanItem = {
|
||||
missingCount: number
|
||||
}
|
||||
|
||||
type KuaishouCloudDefaultRoleSnapshot = {
|
||||
defaultName: string
|
||||
defaultRid: string
|
||||
defaultCapturedAt: string | null
|
||||
defaultCaptureStatus: string
|
||||
defaultErrorMessage: string
|
||||
}
|
||||
|
||||
export {
|
||||
isKuaishouCloudBindUrlFresh,
|
||||
isKuaishouCloudTask,
|
||||
hasKuaishouCloudCustomerRole,
|
||||
hasKuaishouCloudDefaultRoleSnapshot,
|
||||
maskCode,
|
||||
maskPhone,
|
||||
normalizeKuaishouCloudFlow,
|
||||
normalizeKuaishouCloudRoleInfo,
|
||||
isSameKuaishouCloudRoleIdentity,
|
||||
resolveKuaishouCloudBindUrlExpiresAt,
|
||||
} from './domain.js'
|
||||
export { resolvePersistedCloudtentaclesContextBySourceKeys } from './cloudtentacles-context.js'
|
||||
|
||||
async function captureKuaishouCloudDefaultRoleSnapshot({
|
||||
cloudContext,
|
||||
preparedBinding,
|
||||
now,
|
||||
}: {
|
||||
cloudContext: JsonObject
|
||||
preparedBinding: JsonObject
|
||||
now: string
|
||||
}): Promise<KuaishouCloudDefaultRoleSnapshot> {
|
||||
try {
|
||||
const bindInfoResult = await getCloudtentaclesBindInfo({
|
||||
...cloudContext,
|
||||
key: preparedBinding.vnKey,
|
||||
id: preparedBinding.vnId,
|
||||
})
|
||||
const roleInfo = normalizeKuaishouCloudRoleInfo(bindInfoResult.bindInfo)
|
||||
const hasRole = Boolean(roleInfo.name || roleInfo.rid)
|
||||
|
||||
return {
|
||||
defaultName: roleInfo.name,
|
||||
defaultRid: roleInfo.rid,
|
||||
defaultCapturedAt: hasRole ? now : null,
|
||||
defaultCaptureStatus: hasRole ? 'captured' : 'empty',
|
||||
defaultErrorMessage: hasRole ? '' : '未获取到虚拟机默认角色信息,请稍后刷新',
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
defaultName: '',
|
||||
defaultRid: '',
|
||||
defaultCapturedAt: null,
|
||||
defaultCaptureStatus: 'failed',
|
||||
defaultErrorMessage:
|
||||
error instanceof Error ? error.message : '获取虚拟机默认角色信息失败,请稍后刷新',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function buildPendingRoleWithDefaultSnapshot(snapshot: KuaishouCloudDefaultRoleSnapshot) {
|
||||
return {
|
||||
status: 'pending',
|
||||
name: '',
|
||||
rid: '',
|
||||
refreshedAt: null as null,
|
||||
errorMessage: snapshot.defaultErrorMessage || '',
|
||||
rawInfo: null as null,
|
||||
defaultName: snapshot.defaultName,
|
||||
defaultRid: snapshot.defaultRid,
|
||||
defaultCapturedAt: snapshot.defaultCapturedAt,
|
||||
defaultCaptureStatus: snapshot.defaultCaptureStatus,
|
||||
defaultErrorMessage: snapshot.defaultErrorMessage,
|
||||
isDefaultRole: false,
|
||||
}
|
||||
}
|
||||
|
||||
function buildRoleStateFromCurrentInfo({
|
||||
flow,
|
||||
roleInfo,
|
||||
now,
|
||||
emptyMessage,
|
||||
}: {
|
||||
flow: ReturnType<typeof normalizeKuaishouCloudFlow>
|
||||
roleInfo: { name: string; rid: string; rawInfo?: unknown }
|
||||
now: string
|
||||
emptyMessage: string
|
||||
}) {
|
||||
const hasRoleInfo = Boolean(roleInfo.name || roleInfo.rid)
|
||||
const hasDefaultRole = hasKuaishouCloudDefaultRoleSnapshot(flow)
|
||||
const isDefaultRole =
|
||||
hasRoleInfo &&
|
||||
hasDefaultRole &&
|
||||
isSameKuaishouCloudRoleIdentity(
|
||||
{ name: roleInfo.name, rid: roleInfo.rid },
|
||||
{ name: flow.role.defaultName, rid: flow.role.defaultRid },
|
||||
)
|
||||
|
||||
return {
|
||||
hasRoleInfo,
|
||||
isDefaultRole,
|
||||
bindingRoleName: hasRoleInfo ? roleInfo.name : '',
|
||||
bindingRoleId: hasRoleInfo ? roleInfo.rid : '',
|
||||
role: {
|
||||
...flow.role,
|
||||
status: hasRoleInfo && !isDefaultRole ? 'ready' : 'pending',
|
||||
name: hasRoleInfo ? roleInfo.name : '',
|
||||
rid: hasRoleInfo ? roleInfo.rid : '',
|
||||
refreshedAt: now,
|
||||
errorMessage: hasRoleInfo
|
||||
? isDefaultRole
|
||||
? '当前仍是虚拟机默认角色,请重新绑定自己的角色信息'
|
||||
: ''
|
||||
: emptyMessage,
|
||||
rawInfo: roleInfo.rawInfo || null,
|
||||
isDefaultRole,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export async function ensureTaskClaimLink(task: TaskRow) {
|
||||
const tokenStatus = String(task?.primary_claim_token_status || '').trim()
|
||||
const token = String(task?.primary_claim_token || task?.claim_token || '').trim()
|
||||
@@ -201,6 +312,11 @@ export async function prepareKuaishouCloudFulfillmentTask(task: TaskRow, options
|
||||
cloudContext,
|
||||
vnKeyCandidates,
|
||||
})
|
||||
const defaultRoleSnapshot = await captureKuaishouCloudDefaultRoleSnapshot({
|
||||
cloudContext,
|
||||
preparedBinding,
|
||||
now,
|
||||
})
|
||||
|
||||
const nextContext = {
|
||||
...taskContext,
|
||||
@@ -222,14 +338,7 @@ export async function prepareKuaishouCloudFulfillmentTask(task: TaskRow, options
|
||||
roleName: '',
|
||||
roleId: '',
|
||||
},
|
||||
role: {
|
||||
status: 'pending',
|
||||
name: '',
|
||||
rid: '',
|
||||
refreshedAt: null as null,
|
||||
errorMessage: '',
|
||||
rawInfo: null as null,
|
||||
},
|
||||
role: buildPendingRoleWithDefaultSnapshot(defaultRoleSnapshot),
|
||||
purchase: {
|
||||
...flowWithResolvedBinding.purchase,
|
||||
usedKnapsack,
|
||||
@@ -281,6 +390,9 @@ export async function prepareKuaishouCloudFulfillmentTask(task: TaskRow, options
|
||||
})),
|
||||
resolvedByName: resolvedBinding.resolvedByName,
|
||||
accountSelection: buildCloudtentaclesSourceSelectionEventDetail(selectedCloud),
|
||||
defaultRoleName: defaultRoleSnapshot.defaultName,
|
||||
defaultRoleId: defaultRoleSnapshot.defaultRid,
|
||||
defaultRoleCaptureStatus: defaultRoleSnapshot.defaultCaptureStatus,
|
||||
actor,
|
||||
},
|
||||
now,
|
||||
@@ -377,6 +489,14 @@ export async function refreshKuaishouCloudTaskBindUrl(task: TaskRow, options: Js
|
||||
}
|
||||
}
|
||||
|
||||
const defaultRoleSnapshot =
|
||||
normalizeTaskStatus(task.task_status) === TASK_STATUS.ROLE_CONFIRMED
|
||||
? null
|
||||
: await captureKuaishouCloudDefaultRoleSnapshot({
|
||||
cloudContext,
|
||||
preparedBinding,
|
||||
now,
|
||||
})
|
||||
const nextContext = {
|
||||
...taskContext,
|
||||
kuaishouCloudFulfillment: {
|
||||
@@ -405,14 +525,7 @@ export async function refreshKuaishouCloudTaskBindUrl(task: TaskRow, options: Js
|
||||
role:
|
||||
normalizeTaskStatus(task.task_status) === TASK_STATUS.ROLE_CONFIRMED
|
||||
? flow.role
|
||||
: {
|
||||
status: 'pending',
|
||||
name: '',
|
||||
rid: '',
|
||||
refreshedAt: null,
|
||||
errorMessage: '',
|
||||
rawInfo: null,
|
||||
},
|
||||
: buildPendingRoleWithDefaultSnapshot(defaultRoleSnapshot!),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -648,6 +761,11 @@ export async function rebindKuaishouCloudTaskRole(task: TaskRow, options: JsonOb
|
||||
|
||||
const claimLinkState = await ensureTaskClaimLink(task)
|
||||
const nextBindExpiresAt = resolveKuaishouCloudBindUrlExpiresAt(now)
|
||||
const defaultRoleSnapshot = await captureKuaishouCloudDefaultRoleSnapshot({
|
||||
cloudContext,
|
||||
preparedBinding,
|
||||
now,
|
||||
})
|
||||
const nextContext = {
|
||||
...taskContext,
|
||||
kuaishouCloudFulfillment: {
|
||||
@@ -667,14 +785,7 @@ export async function rebindKuaishouCloudTaskRole(task: TaskRow, options: JsonOb
|
||||
roleName: '',
|
||||
roleId: '',
|
||||
},
|
||||
role: {
|
||||
status: 'pending',
|
||||
name: '',
|
||||
rid: '',
|
||||
refreshedAt: null,
|
||||
errorMessage: '',
|
||||
rawInfo: null,
|
||||
},
|
||||
role: buildPendingRoleWithDefaultSnapshot(defaultRoleSnapshot),
|
||||
rebind: {
|
||||
...previousRebind,
|
||||
currentAttempt: attempt,
|
||||
@@ -723,6 +834,9 @@ export async function rebindKuaishouCloudTaskRole(task: TaskRow, options: JsonOb
|
||||
vnId: preparedBinding.vnId,
|
||||
vnPhoneMasked: maskPhone(preparedBinding.vnPhone),
|
||||
bindUrl: preparedBinding.bindUrl,
|
||||
defaultRoleName: defaultRoleSnapshot.defaultName,
|
||||
defaultRoleId: defaultRoleSnapshot.defaultRid,
|
||||
defaultRoleCaptureStatus: defaultRoleSnapshot.defaultCaptureStatus,
|
||||
actor,
|
||||
},
|
||||
now,
|
||||
@@ -787,6 +901,14 @@ export async function probeKuaishouCloudTaskBindUrl(task: TaskRow, options: Json
|
||||
|
||||
const probeRoleInfo = normalizeKuaishouCloudRoleInfo(probe.roleInfo)
|
||||
const hasRoleInfo = Boolean(probeRoleInfo.name || probeRoleInfo.rid)
|
||||
const roleState = hasRoleInfo
|
||||
? buildRoleStateFromCurrentInfo({
|
||||
flow,
|
||||
roleInfo: probeRoleInfo,
|
||||
now,
|
||||
emptyMessage: '当前还没有查询到角色信息,请完成绑定后稍等片刻再试',
|
||||
})
|
||||
: null
|
||||
const nextContext = {
|
||||
...taskContext,
|
||||
kuaishouCloudFulfillment: {
|
||||
@@ -796,24 +918,16 @@ export async function probeKuaishouCloudTaskBindUrl(task: TaskRow, options: Json
|
||||
bindProbeAt: now,
|
||||
bindProbeStatus: probe.valid ? 'valid' : 'invalid',
|
||||
bindProbeMessage: String(probe.message || probe.reason || '').trim(),
|
||||
roleName: hasRoleInfo ? probeRoleInfo.name : flow.binding.roleName,
|
||||
roleId: hasRoleInfo ? probeRoleInfo.rid : flow.binding.roleId,
|
||||
},
|
||||
role: {
|
||||
...flow.role,
|
||||
status: hasRoleInfo ? 'ready' : flow.role.status,
|
||||
name: hasRoleInfo ? probeRoleInfo.name : flow.role.name,
|
||||
rid: hasRoleInfo ? probeRoleInfo.rid : flow.role.rid,
|
||||
refreshedAt: hasRoleInfo ? now : flow.role.refreshedAt,
|
||||
errorMessage: hasRoleInfo ? '' : flow.role.errorMessage,
|
||||
rawInfo: hasRoleInfo ? probeRoleInfo.rawInfo : flow.role.rawInfo,
|
||||
roleName: roleState ? roleState.bindingRoleName : flow.binding.roleName,
|
||||
roleId: roleState ? roleState.bindingRoleId : flow.binding.roleId,
|
||||
},
|
||||
role: roleState ? roleState.role : flow.role,
|
||||
},
|
||||
}
|
||||
|
||||
const updatedTask = await updateTask(task.id, {
|
||||
role_id: hasRoleInfo ? probeRoleInfo.rid : task.role_id,
|
||||
role_name: hasRoleInfo ? probeRoleInfo.name : task.role_name,
|
||||
role_id: roleState && !roleState.isDefaultRole ? probeRoleInfo.rid : task.role_id,
|
||||
role_name: roleState && !roleState.isDefaultRole ? probeRoleInfo.name : task.role_name,
|
||||
context_json: JSON.stringify(nextContext),
|
||||
updated_at: now,
|
||||
})
|
||||
@@ -956,30 +1070,28 @@ export async function refreshKuaishouCloudTaskRoleInfo(task: TaskRow, options: J
|
||||
})
|
||||
|
||||
const bindInfo = normalizeKuaishouCloudRoleInfo(bindInfoResult.bindInfo)
|
||||
const hasRoleInfo = Boolean(bindInfo.name || bindInfo.rid)
|
||||
const roleState = buildRoleStateFromCurrentInfo({
|
||||
flow,
|
||||
roleInfo: bindInfo,
|
||||
now,
|
||||
emptyMessage: '当前还没有查询到角色信息,请完成绑定后稍等片刻再试',
|
||||
})
|
||||
const nextContext = {
|
||||
...taskContext,
|
||||
kuaishouCloudFulfillment: {
|
||||
...flow,
|
||||
binding: {
|
||||
...flow.binding,
|
||||
roleName: hasRoleInfo ? bindInfo.name : '',
|
||||
roleId: hasRoleInfo ? bindInfo.rid : '',
|
||||
},
|
||||
role: {
|
||||
status: hasRoleInfo ? 'ready' : 'pending',
|
||||
name: hasRoleInfo ? bindInfo.name : '',
|
||||
rid: hasRoleInfo ? bindInfo.rid : '',
|
||||
refreshedAt: now,
|
||||
errorMessage: hasRoleInfo ? '' : '当前还没有查询到角色信息,请完成绑定后稍等片刻再试',
|
||||
rawInfo: bindInfo.rawInfo,
|
||||
roleName: roleState.bindingRoleName,
|
||||
roleId: roleState.bindingRoleId,
|
||||
},
|
||||
role: roleState.role,
|
||||
},
|
||||
}
|
||||
|
||||
const updatedTask = await updateTask(task.id, {
|
||||
role_id: hasRoleInfo ? bindInfo.rid : '',
|
||||
role_name: hasRoleInfo ? bindInfo.name : '',
|
||||
role_id: roleState.hasRoleInfo && !roleState.isDefaultRole ? bindInfo.rid : '',
|
||||
role_name: roleState.hasRoleInfo && !roleState.isDefaultRole ? bindInfo.name : '',
|
||||
context_json: JSON.stringify(nextContext),
|
||||
updated_at: now,
|
||||
})
|
||||
|
||||
@@ -93,6 +93,12 @@ export interface ClaimKuaishouCloudFlowInfo {
|
||||
rid: string
|
||||
refreshedAt: string | null
|
||||
errorMessage: string
|
||||
defaultName: string
|
||||
defaultRid: string
|
||||
defaultCapturedAt: string | null
|
||||
defaultCaptureStatus: string
|
||||
defaultErrorMessage: string
|
||||
isDefaultRole: boolean
|
||||
}
|
||||
purchase: {
|
||||
autoBuyEnabled: boolean
|
||||
|
||||
@@ -51,7 +51,8 @@ const claim = useKuaishouCloudClaim(() => props.token)
|
||||
:qr-code-data-url="claim.qrCodeDataUrl.value"
|
||||
:is-binding-prepared="claim.isBindingPrepared.value"
|
||||
:is-binding-preparing="claim.isBindingPreparing.value"
|
||||
:is-role-ready="claim.isRoleReady.value"
|
||||
:is-customer-role-ready="claim.isCustomerRoleReady.value"
|
||||
:confirm-role-disabled-reason="claim.confirmRoleDisabledReason.value"
|
||||
:role-name="claim.roleName.value"
|
||||
:role-id="claim.roleId.value"
|
||||
:refreshing-role="claim.refreshingRole.value"
|
||||
|
||||
@@ -7,7 +7,8 @@ defineProps<{
|
||||
qrCodeDataUrl: string
|
||||
isBindingPrepared: boolean
|
||||
isBindingPreparing: boolean
|
||||
isRoleReady: boolean
|
||||
isCustomerRoleReady: boolean
|
||||
confirmRoleDisabledReason: string
|
||||
roleName: string
|
||||
roleId: string
|
||||
refreshingRole: boolean
|
||||
@@ -41,7 +42,7 @@ defineEmits<{
|
||||
<span>系统正在准备绑定资源,请稍后自动刷新。</span>
|
||||
</div>
|
||||
|
||||
<div class="role-panel" :class="{ pending: !isRoleReady }">
|
||||
<div class="role-panel" :class="{ pending: !isCustomerRoleReady }">
|
||||
<div class="role-panel__item">
|
||||
<span>当前角色</span>
|
||||
<strong>{{ roleName || '待识别' }}</strong>
|
||||
@@ -52,6 +53,10 @@ defineEmits<{
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="flow.role.isDefaultRole" class="status-banner warning">
|
||||
<span>当前仍是虚拟机默认角色,请重新绑定自己的角色信息。</span>
|
||||
</div>
|
||||
|
||||
<div class="action-row">
|
||||
<el-button size="large" plain :loading="refreshingRole" @click="$emit('refreshRole')">
|
||||
<el-icon><RefreshRight /></el-icon>
|
||||
@@ -66,15 +71,23 @@ defineEmits<{
|
||||
>
|
||||
换绑角色
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="large"
|
||||
:loading="confirmingRole"
|
||||
:disabled="!isBindingPrepared || !isRoleReady || rebindingRole"
|
||||
@click="$emit('confirmRole')"
|
||||
<el-tooltip
|
||||
:disabled="!confirmRoleDisabledReason"
|
||||
:content="confirmRoleDisabledReason"
|
||||
placement="top"
|
||||
>
|
||||
我已完成绑定,下一步
|
||||
</el-button>
|
||||
<span class="action-tooltip-wrap">
|
||||
<el-button
|
||||
type="primary"
|
||||
size="large"
|
||||
:loading="confirmingRole"
|
||||
:disabled="Boolean(confirmRoleDisabledReason)"
|
||||
@click="$emit('confirmRole')"
|
||||
>
|
||||
我已完成绑定,下一步
|
||||
</el-button>
|
||||
</span>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
|
||||
<div class="meta-footer">
|
||||
@@ -127,6 +140,11 @@ defineEmits<{
|
||||
color: #1d4ed8;
|
||||
}
|
||||
|
||||
.status-banner.warning {
|
||||
background: #fff7ed;
|
||||
color: #c2410c;
|
||||
}
|
||||
|
||||
.qr-block {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -239,6 +257,10 @@ defineEmits<{
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.action-tooltip-wrap {
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
.action-row :deep(.el-button) {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
@@ -76,6 +76,31 @@ export function useKuaishouCloudClaim(token: () => string) {
|
||||
const isBindingPreparing = computed(() => flow.value?.binding.prepareStatus === 'pending')
|
||||
const canEnterBindingStep = computed(() => isTicketVerified.value)
|
||||
const isRoleReady = computed(() => Boolean(roleName.value || roleId.value))
|
||||
const hasDefaultRoleSnapshot = computed(() =>
|
||||
Boolean(flow.value?.role.defaultName || flow.value?.role.defaultRid),
|
||||
)
|
||||
const isDefaultRole = computed(() => flow.value?.role.isDefaultRole === true)
|
||||
const isCustomerRoleReady = computed(
|
||||
() => isRoleReady.value && hasDefaultRoleSnapshot.value && !isDefaultRole.value,
|
||||
)
|
||||
const confirmRoleDisabledReason = computed(() => {
|
||||
if (!isBindingPrepared.value) {
|
||||
return '绑定二维码还在准备中,请稍后自动刷新'
|
||||
}
|
||||
if (!hasDefaultRoleSnapshot.value) {
|
||||
return flow.value?.role.defaultErrorMessage || '系统还未获取到虚拟机默认角色信息,请稍后刷新'
|
||||
}
|
||||
if (!isRoleReady.value) {
|
||||
return '请先扫码绑定自己的角色,并刷新角色信息'
|
||||
}
|
||||
if (isDefaultRole.value) {
|
||||
return '当前仍是虚拟机默认角色,请重新绑定自己的角色信息'
|
||||
}
|
||||
if (rebindingRole.value) {
|
||||
return '正在换绑角色,请稍候'
|
||||
}
|
||||
return ''
|
||||
})
|
||||
const isRoleConfirmed = computed(() => isKuaishouCloudRoleConfirmedStatus(task.value?.status))
|
||||
const isDispatched = computed(
|
||||
() => String(flow.value?.dispatch.status || '').trim() === 'success',
|
||||
@@ -239,11 +264,15 @@ export function useKuaishouCloudClaim(token: () => string) {
|
||||
refreshingRole.value = true
|
||||
try {
|
||||
await loadDetail({ silent: true })
|
||||
if (isRoleReady.value) {
|
||||
if (isCustomerRoleReady.value) {
|
||||
showSuccess('角色信息已刷新')
|
||||
} else if (isDefaultRole.value) {
|
||||
showError('当前仍是虚拟机默认角色,请重新绑定自己的角色信息')
|
||||
} else {
|
||||
showError(
|
||||
flow.value?.role.errorMessage || '暂时还没有识别到角色信息,请完成绑定后稍等片刻再试',
|
||||
flow.value?.role.errorMessage ||
|
||||
flow.value?.role.defaultErrorMessage ||
|
||||
'暂时还没有识别到角色信息,请完成绑定后稍等片刻再试',
|
||||
)
|
||||
}
|
||||
} finally {
|
||||
@@ -441,6 +470,10 @@ export function useKuaishouCloudClaim(token: () => string) {
|
||||
isBindingPreparing,
|
||||
canEnterBindingStep,
|
||||
isRoleReady,
|
||||
hasDefaultRoleSnapshot,
|
||||
isDefaultRole,
|
||||
isCustomerRoleReady,
|
||||
confirmRoleDisabledReason,
|
||||
isRoleConfirmed,
|
||||
isDispatched,
|
||||
isRedeemFailed,
|
||||
|
||||
Reference in New Issue
Block a user