Files
X-Financial/web/src/services/aiApplicationPreviewActions.js
caoxiaozhu 0cda750ff0 feat(web): AI 工作台会话与文档卡片渲染增强
- aiConversationHtmlRenderer 识别单据记录类表格并渲染为卡片列表,新增删除申请单详情的禁用占位链接
- aiWorkbenchConversationStore 增加草稿删除后会话链接失效处理,避免点击已删除单据跳转
- aiApplicationPreviewActions 调整提交/草稿调用路径,PersonalWorkbenchAiMode 接入新的会话存储与渲染
- ConfirmDialog/TravelRequestDeleteDialog/useAppShell/AppShellRouteView 配套适配,同步更新相关前端测试
2026-06-20 21:44:16 +08:00

139 lines
4.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { apiRequest } from './api.js'
import {
buildApplicationPreviewRows,
buildApplicationPreviewSubmitText,
normalizeApplicationPreview
} from '../utils/expenseApplicationPreview.js'
export const AI_APPLICATION_ACTION_SAVE_DRAFT = 'ai_application_save_draft'
export const AI_APPLICATION_ACTION_SUBMIT = 'ai_application_submit'
function normalizeText(value) {
return String(value || '').trim()
}
function resolveUserValue(user = {}, ...keys) {
for (const key of keys) {
const value = normalizeText(user?.[key])
if (value) return value
}
return ''
}
function buildClientTimeContext() {
const now = new Date()
const locale =
typeof navigator !== 'undefined' && typeof navigator.language === 'string'
? navigator.language
: 'zh-CN'
return {
client_now_iso: now.toISOString(),
client_timezone_offset_minutes: now.getTimezoneOffset(),
client_locale: locale
}
}
function buildApplicationPreviewSaveText(preview = {}) {
const rows = buildApplicationPreviewRows(preview)
return [
'费用申请保存草稿',
...rows.map((row) => `${row.label}${row.value}`),
'',
'保存草稿'
].join('\n')
}
export function buildAiApplicationPreviewActionText(actionType, preview = {}) {
const normalized = normalizeApplicationPreview(preview)
return actionType === AI_APPLICATION_ACTION_SUBMIT
? buildApplicationPreviewSubmitText(normalized)
: buildApplicationPreviewSaveText(normalized)
}
export function buildAiApplicationPreviewActionPayload({
actionType,
applicationPreview,
currentUser = {},
conversationId = '',
draftPayload = null
} = {}) {
const normalizedPreview = normalizeApplicationPreview(applicationPreview || {})
const message = buildAiApplicationPreviewActionText(actionType, normalizedPreview)
const username = resolveUserValue(currentUser, 'username', 'account', 'email', 'name') || 'anonymous'
const name = resolveUserValue(currentUser, 'name', 'username')
const employeeNo = resolveUserValue(currentUser, 'employeeNo', 'employee_no')
const managerName = resolveUserValue(currentUser, 'managerName', 'manager_name', 'directManagerName', 'direct_manager_name')
const departmentName = resolveUserValue(currentUser, 'departmentName', 'department_name', 'department')
const position = resolveUserValue(currentUser, 'position', 'employeePosition', 'employee_position')
const grade = resolveUserValue(currentUser, 'grade', 'employeeGrade', 'employee_grade')
const roleCodes = Array.isArray(currentUser.roleCodes)
? currentUser.roleCodes.map((item) => normalizeText(item)).filter(Boolean)
: []
const draftClaimId = normalizeText(draftPayload?.claim_id || draftPayload?.claimId)
const isSubmit = actionType === AI_APPLICATION_ACTION_SUBMIT
return {
source: 'user_message',
user_id: username,
conversation_id: normalizeText(conversationId) || null,
message,
context_json: {
role_codes: roleCodes,
is_admin: Boolean(currentUser.isAdmin),
name,
role: resolveUserValue(currentUser, 'role'),
department: departmentName,
department_name: departmentName,
position,
employee_position: position,
employeePosition: position,
grade,
employee_grade: grade,
employeeGrade: grade,
employee_no: employeeNo,
employeeNo,
manager_name: managerName,
managerName,
direct_manager_name: managerName,
directManagerName: managerName,
cost_center: resolveUserValue(currentUser, 'costCenter', 'cost_center'),
finance_owner_name: resolveUserValue(currentUser, 'financeOwnerName', 'finance_owner_name'),
...buildClientTimeContext(),
session_type: 'application',
entry_source: 'workbench_ai_inline',
source: 'workbench',
document_type: 'expense_application',
application_stage: 'expense_application',
user_input_text: message,
application_preview: normalizedPreview,
...(isSubmit
? {}
: {
application_action: 'save_draft',
application_save_mode: true
}),
...(draftClaimId
? {
application_edit_claim_id: draftClaimId,
draft_claim_id: draftClaimId,
selected_claim_id: draftClaimId,
application_edit_mode: true
}
: {})
}
}
}
export function runAiApplicationPreviewAction(params = {}, options = {}) {
const payload = buildAiApplicationPreviewActionPayload(params)
const isSubmit = params.actionType === AI_APPLICATION_ACTION_SUBMIT
return apiRequest('/reimbursements/application-preview-action', {
method: 'POST',
body: JSON.stringify(payload),
timeoutMs: isSubmit ? 45000 : 30000,
timeoutMessage: isSubmit ? '申请提交处理超时,请稍后重试。' : '申请草稿保存超时,请稍后重试。',
...options
})
}