把 task 的 helper独立出来了
This commit is contained in:
@@ -0,0 +1,246 @@
|
||||
// @ts-check
|
||||
|
||||
import { getAgisoShopConfig } from '../platforms/agiso/shop-config-service.js'
|
||||
import { safeParseJson } from './admin-query-utils.js'
|
||||
import { normalizeAdminRole } from './admin-auth-service.js'
|
||||
|
||||
export function mapManualDispatchContext(value, viewerContext = createAdminViewerContext()) {
|
||||
if (!value || typeof value !== 'object') {
|
||||
return null
|
||||
}
|
||||
|
||||
return {
|
||||
outcome: String(value.outcome || '').trim(),
|
||||
deliveryReference: String(value.deliveryReference || '').trim(),
|
||||
deliveredCredential: viewerContext.canViewSensitiveTaskData ? String(value.deliveredCredential || '').trim() : '',
|
||||
resultMessage: String(value.resultMessage || '').trim(),
|
||||
completedAt: value.completedAt || null,
|
||||
completedBy: value.completedBy && typeof value.completedBy === 'object'
|
||||
? {
|
||||
userId: Number(value.completedBy.userId || 0) || 0,
|
||||
username: String(value.completedBy.username || '').trim(),
|
||||
role: String(value.completedBy.role || '').trim(),
|
||||
}
|
||||
: null,
|
||||
}
|
||||
}
|
||||
|
||||
export function mapRedeemResolutionContext(value) {
|
||||
if (!value || typeof value !== 'object') {
|
||||
return null
|
||||
}
|
||||
|
||||
const attempts = Array.isArray(value.attempts)
|
||||
? value.attempts
|
||||
.map((attempt) => mapRedeemResolutionAttempt(attempt))
|
||||
.filter(Boolean)
|
||||
: []
|
||||
|
||||
return {
|
||||
status: String(value.status || '').trim(),
|
||||
taskStatus: String(value.taskStatus || '').trim(),
|
||||
replacementCount: Math.max(0, Number(value.replacementCount || 0)),
|
||||
finishedAt: value.finishedAt || null,
|
||||
attempts,
|
||||
}
|
||||
}
|
||||
|
||||
export function getTaskPrimaryInventoryItemId(task) {
|
||||
const value = Number(task?.primary_inventory_item_id || 0)
|
||||
return Number.isFinite(value) && value > 0 ? value : null
|
||||
}
|
||||
|
||||
export function getTaskPrimaryClaimTokenId(task) {
|
||||
const value = Number(task?.primary_claim_token_id || 0)
|
||||
return Number.isFinite(value) && value > 0 ? value : null
|
||||
}
|
||||
|
||||
export function createAdminViewerContext(session = null) {
|
||||
const role = normalizeAdminRole(session?.role)
|
||||
|
||||
return {
|
||||
role,
|
||||
canViewSensitiveTaskData: role === 'admin' || role === 'operator',
|
||||
canManageSensitiveInventory: role === 'admin',
|
||||
canManageTaskLifecycle: role === 'admin' || role === 'operator',
|
||||
canOperateAssistedTask: role === 'admin' || role === 'operator' || role === 'support',
|
||||
}
|
||||
}
|
||||
|
||||
export async function resolveAdminTaskScreenshotUrl(task, viewerContext) {
|
||||
if (viewerContext.role === 'support') {
|
||||
return task.browser_session_id ? `/api/v1/admin/tasks/${task.id}/screenshot` : ''
|
||||
}
|
||||
|
||||
if (task.screenshot_path || task.browser_session_id) {
|
||||
return `/api/v1/admin/tasks/${task.id}/screenshot`
|
||||
}
|
||||
|
||||
return ''
|
||||
}
|
||||
|
||||
export function resolveDisplayShopName(provider, shopId, shopName) {
|
||||
const normalizedShopName = String(shopName || '').trim()
|
||||
if (normalizedShopName) {
|
||||
return normalizedShopName
|
||||
}
|
||||
|
||||
const normalizedShopId = String(shopId || '').trim()
|
||||
if (!normalizedShopId) {
|
||||
return ''
|
||||
}
|
||||
|
||||
if (String(provider || '').trim().toLowerCase() === 'agiso') {
|
||||
const configuredName = String(getAgisoShopConfig(normalizedShopId)?.shopName || '').trim()
|
||||
if (configuredName) {
|
||||
return configuredName
|
||||
}
|
||||
}
|
||||
|
||||
return normalizedShopId
|
||||
}
|
||||
|
||||
export function parseTaskContext(task) {
|
||||
const value = task?.context_json
|
||||
|
||||
if (!value) {
|
||||
return {}
|
||||
}
|
||||
|
||||
if (typeof value === 'object') {
|
||||
return value
|
||||
}
|
||||
|
||||
try {
|
||||
return JSON.parse(String(value || '{}'))
|
||||
} catch {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
export function parseTaskState(task) {
|
||||
const value = task?.state_json
|
||||
|
||||
if (!value) {
|
||||
return {}
|
||||
}
|
||||
|
||||
if (typeof value === 'object') {
|
||||
return value
|
||||
}
|
||||
|
||||
try {
|
||||
return JSON.parse(String(value || '{}'))
|
||||
} catch {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
export function resolveOrderItemTitle(item) {
|
||||
if (!item) {
|
||||
return ''
|
||||
}
|
||||
|
||||
const spec = safeParseJson(item.spec_json)
|
||||
|
||||
return pickFirstNonEmpty([
|
||||
spec.title,
|
||||
spec.Title,
|
||||
spec.itemTitle,
|
||||
spec.item_title,
|
||||
spec.goods_name,
|
||||
spec.goodsName,
|
||||
item.sku_name,
|
||||
item.sku_code,
|
||||
])
|
||||
}
|
||||
|
||||
export function resolveOrderItemDeliveryMode(tasks, orderItemId) {
|
||||
const task = (Array.isArray(tasks) ? tasks : []).find((item) => item.order_item_id === orderItemId)
|
||||
|
||||
if (!task) {
|
||||
return ''
|
||||
}
|
||||
|
||||
if (String(task.executor_key || '').trim() === 'manual_dispatch') {
|
||||
return 'manual_dispatch'
|
||||
}
|
||||
|
||||
if (task.requires_claim || getTaskPrimaryClaimTokenId(task) || task.primary_claim_token || task.claim_token) {
|
||||
return 'claim_link'
|
||||
}
|
||||
|
||||
return String(task.executor_key || '').trim()
|
||||
}
|
||||
|
||||
export function isManualDispatchTask(task) {
|
||||
return String(task?.executor_key || '').trim() === 'manual_dispatch'
|
||||
}
|
||||
|
||||
export function isAssistedClaimTask(task) {
|
||||
return String(task?.executor_key || '').trim() === 'tencent_claim_assisted'
|
||||
}
|
||||
|
||||
export function canRegenerateClaimLinkForViewer(task, viewerContext) {
|
||||
if (isManualDispatchTask(task)) {
|
||||
return false
|
||||
}
|
||||
|
||||
const baseAllowed = ['link_generated', 'claimed', 'role_confirmed', 'retry_pending', 'manual_review'].includes(task.task_status)
|
||||
|
||||
if (!baseAllowed) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (viewerContext.canManageTaskLifecycle) {
|
||||
return true
|
||||
}
|
||||
|
||||
return viewerContext.canOperateAssistedTask && isAssistedClaimTask(task)
|
||||
}
|
||||
|
||||
export function canViewerConfirmAssistedRole(task, viewerContext) {
|
||||
if (!viewerContext.canOperateAssistedTask || !isAssistedClaimTask(task)) {
|
||||
return false
|
||||
}
|
||||
|
||||
return String(task?.task_status || '').trim() === 'claimed'
|
||||
}
|
||||
|
||||
export function canViewerRedeemAssistedTask(task, viewerContext) {
|
||||
if (!viewerContext.canOperateAssistedTask || !isAssistedClaimTask(task)) {
|
||||
return false
|
||||
}
|
||||
|
||||
return ['role_confirmed', 'redeeming'].includes(String(task?.task_status || '').trim())
|
||||
}
|
||||
|
||||
function mapRedeemResolutionAttempt(value) {
|
||||
if (!value || typeof value !== 'object') {
|
||||
return null
|
||||
}
|
||||
|
||||
return {
|
||||
attempt: Math.max(1, Number(value.attempt || 1)),
|
||||
inventoryItemId: Number(value.inventoryItemId || 0) || null,
|
||||
codeMasked: String(value.codeMasked || '').trim(),
|
||||
credentialType: String(value.credentialType || '').trim(),
|
||||
outcome: String(value.outcome || '').trim(),
|
||||
resultCode: String(value.resultCode || '').trim(),
|
||||
resultMessage: String(value.resultMessage || '').trim(),
|
||||
}
|
||||
}
|
||||
|
||||
function pickFirstNonEmpty(values) {
|
||||
for (const value of values) {
|
||||
if (typeof value === 'string' && value.trim()) {
|
||||
return value.trim()
|
||||
}
|
||||
|
||||
if (typeof value === 'number' && Number.isFinite(value)) {
|
||||
return String(value)
|
||||
}
|
||||
}
|
||||
|
||||
return ''
|
||||
}
|
||||
Reference in New Issue
Block a user