feat(ai): issue verified application preview decisions
This commit is contained in:
@@ -13,6 +13,8 @@ import { fetchExpenseClaims } from '../../services/reimbursements.js'
|
||||
import {
|
||||
AI_APPLICATION_ACTION_SAVE_DRAFT,
|
||||
AI_APPLICATION_ACTION_SUBMIT,
|
||||
createAiApplicationRequestId,
|
||||
registerAiApplicationPreviewDecision,
|
||||
runAiApplicationPreviewAction
|
||||
} from '../../services/aiApplicationPreviewActions.js'
|
||||
import {
|
||||
@@ -374,9 +376,20 @@ export function useWorkbenchAiApplicationPreviewFlow({
|
||||
return false
|
||||
}
|
||||
|
||||
const normalizedPreview = normalizeApplicationPreview(targetMessage.applicationPreview)
|
||||
let normalizedPreview = normalizeApplicationPreview(targetMessage.applicationPreview)
|
||||
const isSubmit = actionType === AI_APPLICATION_ACTION_SUBMIT
|
||||
const userText = String(options.userText || (isSubmit ? '直接提交' : '保存草稿')).trim()
|
||||
const actionRequestId = String(
|
||||
normalizedPreview.decisionActionRequestId || createAiApplicationRequestId('action')
|
||||
).trim()
|
||||
if (normalizedPreview.decisionId) {
|
||||
normalizedPreview = normalizeApplicationPreview({
|
||||
...normalizedPreview,
|
||||
decisionActionRequestId: actionRequestId
|
||||
})
|
||||
targetMessage.applicationPreview = normalizedPreview
|
||||
persistCurrentConversation()
|
||||
}
|
||||
|
||||
if (isSubmit && !normalizedPreview.readyToSubmit) {
|
||||
if (!options.skipUserMessage) {
|
||||
@@ -454,12 +467,27 @@ export function useWorkbenchAiApplicationPreviewFlow({
|
||||
applicationPreview: normalizedPreview,
|
||||
currentUser: currentUser.value || {},
|
||||
conversationId: conversationId.value,
|
||||
draftPayload: targetMessage.draftPayload || options.draftPayload || null
|
||||
draftPayload: targetMessage.draftPayload || options.draftPayload || null,
|
||||
requestId: actionRequestId
|
||||
})
|
||||
const draftPayload = extractInlineApplicationDraftPayload(payload)
|
||||
if (draftPayload) {
|
||||
targetMessage.draftPayload = draftPayload
|
||||
}
|
||||
const nextDecisionId = String(payload?.result?.decision_id || '').trim()
|
||||
targetMessage.applicationPreview = normalizeApplicationPreview({
|
||||
...(targetMessage.applicationPreview || normalizedPreview),
|
||||
...(nextDecisionId
|
||||
? {
|
||||
decisionId: nextDecisionId,
|
||||
decisionExpiresAt: String(payload?.result?.decision_expires_at || '').trim(),
|
||||
decisionTrackingStatus: 'registered'
|
||||
}
|
||||
: {
|
||||
decisionTrackingStatus: normalizedPreview.decisionId ? 'consumed' : 'legacy'
|
||||
}),
|
||||
decisionActionRequestId: ''
|
||||
})
|
||||
targetMessage.suggestedActions = []
|
||||
const detailActions = buildInlineApplicationDetailAction(draftPayload)
|
||||
const nextTaskAction = buildApplicationPreviewNextTaskAction(targetMessage)
|
||||
@@ -598,11 +626,26 @@ export function useWorkbenchAiApplicationPreviewFlow({
|
||||
ontologyFields: options.ontologyFields
|
||||
})
|
||||
)
|
||||
const content = buildLocalApplicationPreviewMessage(preview)
|
||||
let registeredPreview = preview
|
||||
try {
|
||||
registeredPreview = await registerAiApplicationPreviewDecision({
|
||||
applicationPreview: preview,
|
||||
conversationId: conversationId.value,
|
||||
message: previewSourceText,
|
||||
requestId: createAiApplicationRequestId('preview')
|
||||
})
|
||||
} catch (error) {
|
||||
console.warn('Application preview decision registration failed:', error)
|
||||
registeredPreview = normalizeApplicationPreview({
|
||||
...preview,
|
||||
decisionTrackingStatus: 'degraded'
|
||||
})
|
||||
}
|
||||
const content = buildLocalApplicationPreviewMessage(registeredPreview)
|
||||
const previewMessage = createInlineMessage('assistant', content, {
|
||||
id: pendingMessage.id,
|
||||
applicationPreview: preview,
|
||||
suggestedActions: buildInlineApplicationPreviewSuggestedActions(preview),
|
||||
applicationPreview: registeredPreview,
|
||||
suggestedActions: buildInlineApplicationPreviewSuggestedActions(registeredPreview),
|
||||
requestedSubmit: Boolean(options.requestedSubmit),
|
||||
submitRequiresConfirmation: Boolean(options.submitRequiresConfirmation),
|
||||
stewardRemainingTasks: Array.isArray(options.stewardRemainingTasks) ? options.stewardRemainingTasks : [],
|
||||
|
||||
@@ -8,6 +8,54 @@ import {
|
||||
export const AI_APPLICATION_ACTION_SAVE_DRAFT = 'ai_application_save_draft'
|
||||
export const AI_APPLICATION_ACTION_SUBMIT = 'ai_application_submit'
|
||||
|
||||
export function createAiApplicationRequestId(prefix = 'application') {
|
||||
const normalizedPrefix = normalizeText(prefix) || 'application'
|
||||
if (typeof globalThis.crypto?.randomUUID === 'function') {
|
||||
return `${normalizedPrefix}:${globalThis.crypto.randomUUID()}`
|
||||
}
|
||||
return `${normalizedPrefix}:${Date.now()}:${Math.random().toString(16).slice(2)}`
|
||||
}
|
||||
|
||||
export function resolveAiApplicationPreviewDecisionId(preview = {}) {
|
||||
return normalizeText(preview?.decisionId || preview?.decision_id)
|
||||
}
|
||||
|
||||
export async function registerAiApplicationPreviewDecision({
|
||||
applicationPreview,
|
||||
conversationId = '',
|
||||
message = '',
|
||||
requestId = ''
|
||||
} = {}, options = {}) {
|
||||
const normalizedPreview = normalizeApplicationPreview(applicationPreview || {})
|
||||
const issueRequestId = normalizeText(requestId) || createAiApplicationRequestId('preview')
|
||||
const payload = await apiRequest('/reimbursements/application-previews', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
message: normalizeText(message),
|
||||
conversation_id: normalizeText(conversationId) || null,
|
||||
request_id: issueRequestId
|
||||
}),
|
||||
timeoutMs: 30000,
|
||||
timeoutMessage: '申请预览校验超时,已切换为普通核对模式。',
|
||||
...options
|
||||
})
|
||||
const serverPreview = payload?.application_preview && typeof payload.application_preview === 'object'
|
||||
? payload.application_preview
|
||||
: {}
|
||||
return normalizeApplicationPreview({
|
||||
...normalizedPreview,
|
||||
...serverPreview,
|
||||
fields: {
|
||||
...(normalizedPreview.fields || {}),
|
||||
...(serverPreview.fields || {})
|
||||
},
|
||||
decisionId: normalizeText(payload?.decision_id || serverPreview.decisionId),
|
||||
decisionSource: normalizeText(payload?.decision_source || serverPreview.decisionSource),
|
||||
decisionExpiresAt: normalizeText(payload?.expires_at || serverPreview.decisionExpiresAt),
|
||||
decisionTrackingStatus: 'registered'
|
||||
})
|
||||
}
|
||||
|
||||
function normalizeText(value) {
|
||||
return String(value || '').trim()
|
||||
}
|
||||
@@ -56,7 +104,8 @@ export function buildAiApplicationPreviewActionPayload({
|
||||
applicationPreview,
|
||||
currentUser = {},
|
||||
conversationId = '',
|
||||
draftPayload = null
|
||||
draftPayload = null,
|
||||
requestId = ''
|
||||
} = {}) {
|
||||
const normalizedPreview = normalizeApplicationPreview(applicationPreview || {})
|
||||
const message = buildAiApplicationPreviewActionText(actionType, normalizedPreview)
|
||||
@@ -72,6 +121,8 @@ export function buildAiApplicationPreviewActionPayload({
|
||||
: []
|
||||
const draftClaimId = normalizeText(draftPayload?.claim_id || draftPayload?.claimId)
|
||||
const isSubmit = actionType === AI_APPLICATION_ACTION_SUBMIT
|
||||
const decisionId = resolveAiApplicationPreviewDecisionId(normalizedPreview)
|
||||
const actionRequestId = normalizeText(requestId || normalizedPreview.decisionActionRequestId)
|
||||
const applicationEditableFields = Array.isArray(normalizedPreview.editableFields)
|
||||
? normalizedPreview.editableFields.map((field) => normalizeText(field)).filter(Boolean)
|
||||
: []
|
||||
@@ -80,6 +131,9 @@ export function buildAiApplicationPreviewActionPayload({
|
||||
source: 'user_message',
|
||||
user_id: username,
|
||||
conversation_id: normalizeText(conversationId) || null,
|
||||
action_type: isSubmit ? 'submit' : 'save_draft',
|
||||
...(decisionId ? { decision_id: decisionId } : {}),
|
||||
...(decisionId && actionRequestId ? { request_id: actionRequestId } : {}),
|
||||
message,
|
||||
context_json: {
|
||||
role_codes: roleCodes,
|
||||
|
||||
@@ -257,6 +257,15 @@ function normalizeMessage(message = {}) {
|
||||
content: safeString(message.content),
|
||||
pending: false,
|
||||
feedback: safeString(message.feedback),
|
||||
text: safeString(message.text || message.content),
|
||||
applicationPreview: message.applicationPreview && typeof message.applicationPreview === 'object'
|
||||
? message.applicationPreview
|
||||
: null,
|
||||
draftPayload: message.draftPayload && typeof message.draftPayload === 'object'
|
||||
? message.draftPayload
|
||||
: null,
|
||||
requestedSubmit: Boolean(message.requestedSubmit),
|
||||
submitRequiresConfirmation: Boolean(message.submitRequiresConfirmation),
|
||||
stewardPlan: message.stewardPlan && typeof message.stewardPlan === 'object'
|
||||
? {
|
||||
...message.stewardPlan,
|
||||
|
||||
Reference in New Issue
Block a user