添加快手 Cloud 换绑角色功能

This commit is contained in:
yml
2026-05-30 11:23:52 +08:00
parent 681ff44cbc
commit 1c50569ea9
22 changed files with 1537 additions and 953 deletions
@@ -7,12 +7,18 @@ import { listTaskEventsByTaskId } from '../../repositories/task-event-repo.js'
import { listCloudtentaclesSources } from '../platforms/cloudtentacles/source-config-service.js'
import { createHttpError } from '../../utils/http.js'
import { formatFenToAmount, normalizeFen } from '../../utils/money.js'
import { normalizeDateQuery, normalizePage, normalizePageSize, safeParseJson } from './admin-query-utils.js'
import {
normalizeDateQuery,
normalizePage,
normalizePageSize,
safeParseJson,
} from './admin-query-utils.js'
import {
canCompleteManualDispatchTaskStatus,
canDispatchKuaishouCloudFulfillmentStatus,
canMarkManualReviewTaskStatus,
canPrepareKuaishouCloudFulfillmentStatus,
canRebindKuaishouCloudRoleStatus,
canReturnKuaishouCloudFulfillmentStatus,
canRetryTaskStatus,
} from '../../domain/task-status.js'
@@ -55,7 +61,9 @@ import type {
type JsonRecord = Record<string, any>
export async function getAdminOrders(query: AdminOrderListQueryInput = {}): Promise<AdminOrderListResponse> {
export async function getAdminOrders(
query: AdminOrderListQueryInput = {},
): Promise<AdminOrderListResponse> {
const page = normalizePage(query.page)
const pageSize = normalizePageSize(query.pageSize)
const { items, total } = await listOrders({
@@ -110,9 +118,10 @@ export async function getAdminOrderDetail(orderId: AdminEntityIdInput): Promise<
createdAt: order.created_at,
updatedAt: order.updated_at,
itemSummary,
rawPayload: order.raw_payload_json && typeof order.raw_payload_json === 'object'
? order.raw_payload_json
: JSON.parse(String(order.raw_payload_json || '{}')),
rawPayload:
order.raw_payload_json && typeof order.raw_payload_json === 'object'
? order.raw_payload_json
: JSON.parse(String(order.raw_payload_json || '{}')),
fulfillmentProgress: buildOrderFulfillmentProgress(tasks),
},
items: items.map((item) => ({
@@ -122,9 +131,10 @@ export async function getAdminOrderDetail(orderId: AdminEntityIdInput): Promise<
itemTitle: resolveOrderItemTitle(item),
quantity: item.quantity,
deliveryMode: resolveOrderItemDeliveryMode(tasks, item.id),
spec: item.spec_json && typeof item.spec_json === 'object'
? item.spec_json
: JSON.parse(String(item.spec_json || '{}')),
spec:
item.spec_json && typeof item.spec_json === 'object'
? item.spec_json
: JSON.parse(String(item.spec_json || '{}')),
})),
tasks: tasks.map((task) => mapAdminTaskSummary(task)),
}
@@ -182,46 +192,49 @@ export async function getAdminTaskDetail(
const claimUrl = claimToken ? buildClaimUrl(claimToken.token) : ''
const screenshotUrl = await resolveAdminTaskScreenshotUrl(task, viewerContext)
const cloudSourceLabelMap = buildCloudSourceLabelMap()
const kuaishouCloudFulfillment = mapKuaishouCloudFulfillmentContext(
taskContext.kuaishouCloudFulfillment,
{ cloudSourceLabelMap },
) || mapKuaishouCloudTaskStateProjection(task, { cloudSourceLabelMap })
const kuaishouCloudFulfillment =
mapKuaishouCloudFulfillmentContext(taskContext.kuaishouCloudFulfillment, {
cloudSourceLabelMap,
}) || mapKuaishouCloudTaskStateProjection(task, { cloudSourceLabelMap })
return {
task: mapAdminTaskListItem({
...task,
sku_code: orderItem?.sku_code || '',
sku_name: orderItem?.sku_name || '',
claim_token: claimToken?.token || '',
}, viewerContext),
task: mapAdminTaskListItem(
{
...task,
sku_code: orderItem?.sku_code || '',
sku_name: orderItem?.sku_name || '',
claim_token: claimToken?.token || '',
},
viewerContext,
),
order: order
? {
orderId: order.id,
provider: order.provider || '',
platform: order.platform,
shopId: order.shop_id || '',
shopName: order.shop_name || '',
platformOrderId: order.platform_order_id,
payStatus: order.pay_status,
orderStatus: order.order_status,
}
orderId: order.id,
provider: order.provider || '',
platform: order.platform,
shopId: order.shop_id || '',
shopName: order.shop_name || '',
platformOrderId: order.platform_order_id,
payStatus: order.pay_status,
orderStatus: order.order_status,
}
: null,
orderItem: orderItem
? {
orderItemId: orderItem.id,
skuCode: orderItem.sku_code,
skuName: orderItem.sku_name,
quantity: orderItem.quantity,
}
orderItemId: orderItem.id,
skuCode: orderItem.sku_code,
skuName: orderItem.sku_name,
quantity: orderItem.quantity,
}
: null,
claimToken: claimToken
? {
primaryClaimTokenId: claimToken.id,
token: viewerContext.canViewSensitiveTaskData ? claimToken.token : '',
status: claimToken.status,
expiredAt: claimToken.expired_at,
claimUrl,
}
primaryClaimTokenId: claimToken.id,
token: viewerContext.canViewSensitiveTaskData ? claimToken.token : '',
status: claimToken.status,
expiredAt: claimToken.expired_at,
claimUrl,
}
: null,
artifacts: viewerContext.canViewSensitiveTaskData ? safeParseJson(task.artifacts_json) : {},
screenshotUrl,
@@ -236,27 +249,42 @@ export async function getAdminTaskDetail(
manualDispatch: mapManualDispatchContext(taskContext.manualDispatch, viewerContext),
events: taskEvents.map(mapAdminTaskEvent),
operations: {
canRetry: viewerContext.canManageTaskLifecycle
&& !isManualDispatchTask(task)
&& canRetryTaskStatus(task.task_status),
canRetry:
viewerContext.canManageTaskLifecycle &&
!isManualDispatchTask(task) &&
canRetryTaskStatus(task.task_status),
canRegenerateClaimLink: canRegenerateClaimLinkForViewer(task, viewerContext),
canClose: canViewerCloseTask(task, viewerContext),
canMarkManualReview: viewerContext.canManageTaskLifecycle && canMarkManualReviewTaskStatus(task.task_status),
canCompleteManualDispatch: viewerContext.canManageTaskLifecycle && isManualDispatchTask(task) && canCompleteManualDispatchTaskStatus(task.task_status),
canPrepareKuaishouCloudFulfillment: viewerContext.canManageTaskLifecycle
&& String(task.executor_key || '').trim() === 'kuaishou_ct_assisted'
&& String(kuaishouCloudFulfillment?.dispatch.status || 'pending').trim() === 'pending'
&& String(kuaishouCloudFulfillment?.returnNumber.status || 'pending').trim() === 'pending'
&& canPrepareKuaishouCloudFulfillmentStatus(task.task_status),
canRefreshKuaishouCloudRoleInfo: viewerContext.canOperateAssistedTask
&& String(task.executor_key || '').trim() === 'kuaishou_ct_assisted'
&& Number(kuaishouCloudFulfillment?.binding.vnId || 0) > 0,
canDispatchKuaishouCloudFulfillment: viewerContext.canManageTaskLifecycle
&& String(task.executor_key || '').trim() === 'kuaishou_ct_assisted'
&& canDispatchKuaishouCloudFulfillmentStatus(task.task_status),
canReturnKuaishouCloudFulfillment: viewerContext.canManageTaskLifecycle
&& String(task.executor_key || '').trim() === 'kuaishou_ct_assisted'
&& canReturnKuaishouCloudFulfillmentStatus(task.task_status),
canMarkManualReview:
viewerContext.canManageTaskLifecycle && canMarkManualReviewTaskStatus(task.task_status),
canCompleteManualDispatch:
viewerContext.canManageTaskLifecycle &&
isManualDispatchTask(task) &&
canCompleteManualDispatchTaskStatus(task.task_status),
canPrepareKuaishouCloudFulfillment:
viewerContext.canManageTaskLifecycle &&
String(task.executor_key || '').trim() === 'kuaishou_ct_assisted' &&
String(kuaishouCloudFulfillment?.dispatch.status || 'pending').trim() === 'pending' &&
String(kuaishouCloudFulfillment?.returnNumber.status || 'pending').trim() === 'pending' &&
canPrepareKuaishouCloudFulfillmentStatus(task.task_status),
canRefreshKuaishouCloudRoleInfo:
viewerContext.canOperateAssistedTask &&
String(task.executor_key || '').trim() === 'kuaishou_ct_assisted' &&
Number(kuaishouCloudFulfillment?.binding.vnId || 0) > 0,
canRebindKuaishouCloudRole:
viewerContext.canManageTaskLifecycle &&
String(task.executor_key || '').trim() === 'kuaishou_ct_assisted' &&
canRebindKuaishouCloudRoleStatus(task.task_status) &&
String(kuaishouCloudFulfillment?.dispatch.status || 'pending').trim() !== 'success' &&
Number(kuaishouCloudFulfillment?.binding.vnId || 0) > 0,
canDispatchKuaishouCloudFulfillment:
viewerContext.canManageTaskLifecycle &&
String(task.executor_key || '').trim() === 'kuaishou_ct_assisted' &&
canDispatchKuaishouCloudFulfillmentStatus(task.task_status),
canReturnKuaishouCloudFulfillment:
viewerContext.canManageTaskLifecycle &&
String(task.executor_key || '').trim() === 'kuaishou_ct_assisted' &&
canReturnKuaishouCloudFulfillmentStatus(task.task_status),
canViewSensitiveTaskData: viewerContext.canViewSensitiveTaskData,
},
}
@@ -4,10 +4,7 @@ import {
parseTaskContext as parseTaskContextValue,
parseTaskState as parseTaskStateValue,
} from '../../utils/task-json.js'
import {
canRegenerateClaimLinkStatus,
isTaskFinalStatus,
} from '../../domain/task-status.js'
import { canRegenerateClaimLinkStatus, isTaskFinalStatus } from '../../domain/task-status.js'
import type { AdminViewerSessionInput } from '../../types/admin/read-inputs.js'
import type { OrderItemRow, TaskRow } from '../../types/repository/rows.js'
@@ -51,16 +48,19 @@ export function mapManualDispatchContext(
return {
outcome: String(record.outcome || '').trim(),
deliveryReference: String(record.deliveryReference || '').trim(),
deliveredCredential: viewerContext.canViewSensitiveTaskData ? String(record.deliveredCredential || '').trim() : '',
deliveredCredential: viewerContext.canViewSensitiveTaskData
? String(record.deliveredCredential || '').trim()
: '',
resultMessage: String(record.resultMessage || '').trim(),
completedAt: record.completedAt || null,
completedBy: record.completedBy && typeof record.completedBy === 'object'
? {
userId: Number(record.completedBy.userId || 0) || 0,
username: String(record.completedBy.username || '').trim(),
role: String(record.completedBy.role || '').trim(),
}
: null,
completedBy:
record.completedBy && typeof record.completedBy === 'object'
? {
userId: Number(record.completedBy.userId || 0) || 0,
username: String(record.completedBy.username || '').trim(),
role: String(record.completedBy.role || '').trim(),
}
: null,
}
}
@@ -78,7 +78,8 @@ export function mapKuaishouCloudFulfillmentContext(
const role = record.role && typeof record.role === 'object' ? record.role : {}
const purchase = record.purchase && typeof record.purchase === 'object' ? record.purchase : {}
const dispatch = record.dispatch && typeof record.dispatch === 'object' ? record.dispatch : {}
const returnNumber = record.returnNumber && typeof record.returnNumber === 'object' ? record.returnNumber : {}
const returnNumber =
record.returnNumber && typeof record.returnNumber === 'object' ? record.returnNumber : {}
const consume = record.consume && typeof record.consume === 'object' ? record.consume : {}
const cloudSourceKeys = Array.isArray(binding.cloudSourceKeys)
? binding.cloudSourceKeys.map((value: unknown) => String(value || '').trim()).filter(Boolean)
@@ -156,6 +157,7 @@ export function mapKuaishouCloudFulfillmentContext(
consumedAt: consume.consumedAt || null,
errorMessage: String(consume.errorMessage || '').trim(),
},
rebind: mapKuaishouCloudRebindContext(record.rebind),
notes: String(record.notes || '').trim(),
}
}
@@ -204,9 +206,13 @@ export function mapKuaishouCloudTaskStateProjection(
binding: {
prepareStatus: task.kuaishou_bind_url ? 'ready' : 'pending',
cloudSourceKeys: sourceKey ? [sourceKey] : [],
cloudSourceLabels: sourceKey ? [resolveCloudSourceLabel(sourceKey, options.cloudSourceLabelMap)] : [],
cloudSourceLabels: sourceKey
? [resolveCloudSourceLabel(sourceKey, options.cloudSourceLabelMap)]
: [],
resolvedSourceKey: sourceKey,
resolvedSourceLabel: sourceKey ? resolveCloudSourceLabel(sourceKey, options.cloudSourceLabelMap) : '',
resolvedSourceLabel: sourceKey
? resolveCloudSourceLabel(sourceKey, options.cloudSourceLabelMap)
: '',
skuId: 0,
skuName: '',
vnKey: '',
@@ -255,6 +261,10 @@ export function mapKuaishouCloudTaskStateProjection(
consumedAt: null,
errorMessage: '',
},
rebind: {
currentAttempt: 0,
history: [],
},
notes: '',
}
}
@@ -263,13 +273,67 @@ function resolveCloudSourceLabel(sourceKey: string, labelMap: CloudSourceLabelMa
const key = String(sourceKey || '').trim()
if (!key) return ''
const label = labelMap instanceof Map
? labelMap.get(key)
: labelMap?.[key]
const label = labelMap instanceof Map ? labelMap.get(key) : labelMap?.[key]
return String(label || key).trim() || key
}
function mapKuaishouCloudRebindContext(value: unknown): JsonRecord {
const record = value && typeof value === 'object' ? (value as JsonRecord) : {}
const history = Array.isArray(record.history) ? record.history : []
return {
currentAttempt: Math.max(0, Number(record.currentAttempt || 0) || 0),
history: history.map((item) => mapKuaishouCloudRebindHistoryItem(item)).filter(Boolean),
}
}
function mapKuaishouCloudRebindHistoryItem(value: unknown): JsonRecord | null {
if (!value || typeof value !== 'object') {
return null
}
const record = value as JsonRecord
const oldBinding =
record.oldBinding && typeof record.oldBinding === 'object'
? (record.oldBinding as JsonRecord)
: {}
const newBinding =
record.newBinding && typeof record.newBinding === 'object'
? (record.newBinding as JsonRecord)
: null
return {
attempt: Math.max(1, Number(record.attempt || 1) || 1),
source: String(record.source || '').trim(),
requestedAt: record.requestedAt || null,
requestedBy:
record.requestedBy && typeof record.requestedBy === 'object' ? record.requestedBy : null,
status: String(record.status || '').trim(),
errorMessage: String(record.errorMessage || '').trim(),
oldBinding: {
vnKey: String(oldBinding.vnKey || '').trim(),
vnId: Number(oldBinding.vnId || 0) || 0,
vnPhone: String(oldBinding.vnPhone || '').trim(),
bindUrl: String(oldBinding.bindUrl || '').trim(),
bindPreparedAt: oldBinding.bindPreparedAt || null,
bindExpiresAt: oldBinding.bindExpiresAt || null,
roleName: String(oldBinding.roleName || '').trim(),
roleId: String(oldBinding.roleId || '').trim(),
},
newBinding: newBinding
? {
vnKey: String(newBinding.vnKey || '').trim(),
vnId: Number(newBinding.vnId || 0) || 0,
vnPhone: String(newBinding.vnPhone || '').trim(),
bindUrl: String(newBinding.bindUrl || '').trim(),
bindPreparedAt: newBinding.bindPreparedAt || null,
bindExpiresAt: newBinding.bindExpiresAt || null,
}
: null,
}
}
export function mapRedeemResolutionContext(value: unknown): JsonRecord | null {
if (!value || typeof value !== 'object') {
return null
@@ -278,8 +342,8 @@ export function mapRedeemResolutionContext(value: unknown): JsonRecord | null {
const record = value as JsonRecord
const attempts = Array.isArray(record.attempts)
? record.attempts
.map((attempt) => mapRedeemResolutionAttempt(attempt))
.filter((attempt): attempt is RedeemResolutionAttempt => Boolean(attempt))
.map((attempt) => mapRedeemResolutionAttempt(attempt))
.filter((attempt): attempt is RedeemResolutionAttempt => Boolean(attempt))
: []
return {
@@ -296,7 +360,9 @@ export function getTaskPrimaryClaimTokenId(task: TaskLike | null | undefined): n
return Number.isFinite(value) && value > 0 ? value : null
}
export function createAdminViewerContext(session: AdminViewerSessionInput | null = null): AdminViewerContext {
export function createAdminViewerContext(
session: AdminViewerSessionInput | null = null,
): AdminViewerContext {
const role = normalizeAdminRole(session?.role)
return {
@@ -326,7 +392,11 @@ export function canViewerCloseTask(task: TaskLike, viewerContext: AdminViewerCon
return !isTaskFinalStatus(task?.task_status)
}
export function resolveDisplayShopName(provider: unknown, shopId: unknown, shopName: unknown): string {
export function resolveDisplayShopName(
provider: unknown,
shopId: unknown,
shopName: unknown,
): string {
const normalizedShopName = String(shopName || '').trim()
if (normalizedShopName) {
return normalizedShopName
@@ -367,8 +437,13 @@ export function resolveOrderItemTitle(item: Partial<OrderItemRow> | null | undef
])
}
export function resolveOrderItemDeliveryMode(tasks: TaskLike[] | null | undefined, orderItemId: number | string): string {
const task = (Array.isArray(tasks) ? tasks : []).find((item) => item.order_item_id === orderItemId)
export function resolveOrderItemDeliveryMode(
tasks: TaskLike[] | null | undefined,
orderItemId: number | string,
): string {
const task = (Array.isArray(tasks) ? tasks : []).find(
(item) => item.order_item_id === orderItemId,
)
if (!task) {
return ''
@@ -382,7 +457,12 @@ export function resolveOrderItemDeliveryMode(tasks: TaskLike[] | null | undefine
return 'kuaishou_cloud'
}
if (task.requires_claim || getTaskPrimaryClaimTokenId(task) || task.primary_claim_token || task.claim_token) {
if (
task.requires_claim ||
getTaskPrimaryClaimTokenId(task) ||
task.primary_claim_token ||
task.claim_token
) {
return 'claim_link'
}
@@ -393,7 +473,10 @@ export function isManualDispatchTask(task: TaskLike | null | undefined): boolean
return String(task?.executor_key || '').trim() === 'manual_dispatch'
}
export function canRegenerateClaimLinkForViewer(task: TaskLike, viewerContext: AdminViewerContext): boolean {
export function canRegenerateClaimLinkForViewer(
task: TaskLike,
viewerContext: AdminViewerContext,
): boolean {
if (isManualDispatchTask(task)) {
return false
}
@@ -21,20 +21,15 @@ import {
import { createHttpError } from '../../../utils/http.js'
import { nowIso } from '../../../utils/time.js'
import { TASK_STATUS } from '../../../domain/task-status.js'
import {
createAdminViewerContext,
parseTaskContext,
} from '../admin-read-shared-helpers.js'
import {
getRequiredTask,
mapTaskActionPayload,
} from '../admin-task-read-helpers.js'
import { createAdminViewerContext, parseTaskContext } from '../admin-read-shared-helpers.js'
import { getRequiredTask, mapTaskActionPayload } from '../admin-task-read-helpers.js'
import {
ensureTaskClaimLink,
getTaskClaimExpiresAt,
maskCode,
maskPhone,
} from '../write-helpers.js'
import { rebindKuaishouCloudTaskRole } from '../../fulfillment/kuaishou-cloud/index.js'
import {
isKuaishouCloudTask,
normalizeKuaishouCloudFlow,
@@ -210,17 +205,22 @@ export async function prepareAdminTaskKuaishouCloudFulfillment(
updated_at: now,
})
await createTaskEvent(task.id, 'kuaishou_cloud_binding_prepared', {
skuId: flowWithResolvedBinding.binding.skuId,
skuName: flowWithResolvedBinding.binding.skuName,
vnKey: preparedBinding.vnKey,
vnId,
vnPhoneMasked: maskPhone(vnPhone),
bindUrl: preparedBinding.bindUrl,
purchaseTriggered,
usedKnapsack,
resolvedByName: resolvedBinding.resolvedByName,
}, now)
await createTaskEvent(
task.id,
'kuaishou_cloud_binding_prepared',
{
skuId: flowWithResolvedBinding.binding.skuId,
skuName: flowWithResolvedBinding.binding.skuName,
vnKey: preparedBinding.vnKey,
vnId,
vnPhoneMasked: maskPhone(vnPhone),
bindUrl: preparedBinding.bindUrl,
purchaseTriggered,
usedKnapsack,
resolvedByName: resolvedBinding.resolvedByName,
},
now,
)
return {
task: mapTaskActionPayload(updatedTask),
@@ -280,10 +280,10 @@ export async function dispatchAdminTaskKuaishouCloudFulfillment(
now,
actor: session
? {
userId: Number(session.userId || 0) || 0,
username: String(session.username || '').trim(),
role: String(session.role || '').trim(),
}
userId: Number(session.userId || 0) || 0,
username: String(session.username || '').trim(),
role: String(session.role || '').trim(),
}
: null,
source: 'admin_task_dispatch',
errorCodePrefix: 'admin_task_kuaishou_cloud',
@@ -309,13 +309,14 @@ export async function dispatchAdminTaskKuaishouCloudFulfillment(
...syncedFlow.ticket,
code: ticketCode || persistedTicketCode,
capturedAt: ticketCode ? now : syncedFlow.ticket.capturedAt,
capturedBy: ticketCode && session
? {
userId: Number(session.userId || 0) || 0,
username: String(session.username || '').trim(),
role: String(session.role || '').trim(),
}
: syncedFlow.ticket.capturedBy,
capturedBy:
ticketCode && session
? {
userId: Number(session.userId || 0) || 0,
username: String(session.username || '').trim(),
role: String(session.role || '').trim(),
}
: syncedFlow.ticket.capturedBy,
},
dispatch: {
...syncedFlow.dispatch,
@@ -323,10 +324,10 @@ export async function dispatchAdminTaskKuaishouCloudFulfillment(
dispatchAt: now,
dispatchBy: session
? {
userId: Number(session.userId || 0) || 0,
username: String(session.username || '').trim(),
role: String(session.role || '').trim(),
}
userId: Number(session.userId || 0) || 0,
username: String(session.username || '').trim(),
role: String(session.role || '').trim(),
}
: null,
sendType: Number(dispatchResult.sendType || 0) || 0,
note: String(dispatchResult.note || dispatchResult.responseMessage || '').trim(),
@@ -338,20 +339,27 @@ export async function dispatchAdminTaskKuaishouCloudFulfillment(
task_status: TASK_STATUS.DISPATCHED_PENDING_RETURN,
delivery_status: 'delivered',
result_code: 'kuaishou_cloud_dispatched',
result_message: String(dispatchResult.responseMessage || dispatchResult.note || 'cloudtentacles 发货成功').trim(),
result_message: String(
dispatchResult.responseMessage || dispatchResult.note || 'cloudtentacles 发货成功',
).trim(),
last_error: '',
context_json: JSON.stringify(nextContext),
updated_at: now,
})
await createTaskEvent(task.id, 'kuaishou_cloud_dispatched', {
ticketCodeMasked: maskCode(ticketCode || persistedTicketCode),
skuId: syncedFlow.binding.skuId,
vnId: syncedFlow.binding.vnId,
vnPhoneMasked: maskPhone(syncedFlow.binding.vnPhone),
sendType: dispatchResult.sendType,
note: dispatchResult.note,
}, now)
await createTaskEvent(
task.id,
'kuaishou_cloud_dispatched',
{
ticketCodeMasked: maskCode(ticketCode || persistedTicketCode),
skuId: syncedFlow.binding.skuId,
vnId: syncedFlow.binding.vnId,
vnPhoneMasked: maskPhone(syncedFlow.binding.vnPhone),
sendType: dispatchResult.sendType,
note: dispatchResult.note,
},
now,
)
return {
task: mapTaskActionPayload(updatedTask),
@@ -414,7 +422,8 @@ export async function refreshAdminTaskKuaishouCloudRoleInfo(
name: bindInfo.name,
rid: bindInfo.rid,
refreshedAt: now,
errorMessage: bindInfo.name || bindInfo.rid ? '' : '当前还没有查询到角色信息,请让客户完成绑定后再刷新',
errorMessage:
bindInfo.name || bindInfo.rid ? '' : '当前还没有查询到角色信息,请让客户完成绑定后再刷新',
rawInfo: bindInfo.rawInfo,
},
},
@@ -427,24 +436,61 @@ export async function refreshAdminTaskKuaishouCloudRoleInfo(
updated_at: now,
})
await createTaskEvent(task.id, 'kuaishou_cloud_role_info_refreshed', {
roleName: bindInfo.name,
roleId: bindInfo.rid,
vnId: flow.binding.vnId,
refreshedBy: session
? {
userId: Number(session.userId || 0) || 0,
username: String(session.username || '').trim(),
role: String(session.role || '').trim(),
}
: null,
}, now)
await createTaskEvent(
task.id,
'kuaishou_cloud_role_info_refreshed',
{
roleName: bindInfo.name,
roleId: bindInfo.rid,
vnId: flow.binding.vnId,
refreshedBy: session
? {
userId: Number(session.userId || 0) || 0,
username: String(session.username || '').trim(),
role: String(session.role || '').trim(),
}
: null,
},
now,
)
return {
task: mapTaskActionPayload(updatedTask),
}
}
export async function rebindAdminTaskKuaishouCloudRole(
taskId: AdminEntityIdInput,
session: AdminViewerSessionInput | null = null,
): Promise<AdminTaskActionResponse> {
const task = await getRequiredTask(taskId)
const viewerContext = createAdminViewerContext(session)
if (!viewerContext.canManageTaskLifecycle) {
throw createHttpError('当前账号没有权限换绑角色', {
statusCode: 403,
errorCode: 'admin_task_rebind_kuaishou_cloud_forbidden',
})
}
const result = await rebindKuaishouCloudTaskRole(task, {
source: 'admin_task_rebind_role',
actor: session
? {
userId: Number(session.userId || 0) || 0,
username: String(session.username || '').trim(),
role: String(session.role || '').trim(),
}
: null,
})
return {
task: mapTaskActionPayload(result.task),
claimUrl: result.claimUrl,
token: result.token,
}
}
export async function returnNumberAdminTaskKuaishouCloudFulfillment(
taskId: AdminEntityIdInput,
session: AdminViewerSessionInput | null = null,
@@ -519,7 +565,11 @@ export async function returnNumberAdminTaskKuaishouCloudFulfillment(
consumeStatus = consumeResult.consumed ? 'success' : 'failed'
consumedAt = consumeResult.consumed ? now : null
consumeErrorMessage = String(consumeResult.errorMessage || '').trim()
} else if (!shopConfig || shopConfig.enabled === false || !String(shopConfig.cookie || '').trim()) {
} else if (
!shopConfig ||
shopConfig.enabled === false ||
!String(shopConfig.cookie || '').trim()
) {
consumeStatus = 'failed'
consumeErrorMessage = '订单对应快手小店缺少可用 Cookie,无法执行快手核销'
} else {
@@ -561,10 +611,10 @@ export async function returnNumberAdminTaskKuaishouCloudFulfillment(
returnedAt: now,
returnedBy: session
? {
userId: Number(session.userId || 0) || 0,
username: String(session.username || '').trim(),
role: String(session.role || '').trim(),
}
userId: Number(session.userId || 0) || 0,
username: String(session.username || '').trim(),
role: String(session.role || '').trim(),
}
: null,
},
consume: {
@@ -590,10 +640,15 @@ export async function returnNumberAdminTaskKuaishouCloudFulfillment(
updated_at: now,
})
await createTaskEvent(task.id, 'kuaishou_cloud_number_returned', {
vnId: flow.binding.vnId,
vnPhoneMasked: maskPhone(flow.binding.vnPhone),
}, now)
await createTaskEvent(
task.id,
'kuaishou_cloud_number_returned',
{
vnId: flow.binding.vnId,
vnPhoneMasked: maskPhone(flow.binding.vnPhone),
},
now,
)
await createTaskEvent(
task.id,