feat: 报销审批流重构与管家计划全链路贯通
- 重构报销状态注册表、审批流路由与平台风险标记 - 完善管家意图规划器与模型计划构建器全链路 - 新增 OCR Worker 脚本、数据库会话管理与通知状态 - 优化文档中心、日志视图、预算中心与员工管理交互 - 增强工作台摘要、图标资源与全局主题样式 - 补充审批路由、状态注册、OCR 服务与管家规划器测试覆盖
This commit is contained in:
@@ -79,6 +79,25 @@ const FIELD_ALIASES = {
|
||||
application_transport_mode: 'transport_mode'
|
||||
}
|
||||
|
||||
const APPLICATION_NON_BLOCKING_MISSING_FIELDS = new Set([
|
||||
'amount',
|
||||
'attachments',
|
||||
'employee_no',
|
||||
'employee_name',
|
||||
'department_name'
|
||||
])
|
||||
|
||||
const FIELD_VALUE_DISPLAY_CONFIG = {
|
||||
expense_type: {
|
||||
travel: '差旅',
|
||||
business_entertainment: '业务招待',
|
||||
transportation: '交通费',
|
||||
traffic: '交通费',
|
||||
accommodation: '住宿费',
|
||||
meal: '餐饮费'
|
||||
}
|
||||
}
|
||||
|
||||
export function buildStewardPlanRequest({ rawText = '', files = [], currentUser = {} } = {}) {
|
||||
const safeFiles = Array.isArray(files) ? files : []
|
||||
return {
|
||||
@@ -123,9 +142,10 @@ export function normalizeStewardPlan(rawPlan = {}, options = {}) {
|
||||
tasks: Array.isArray(rawPlan.tasks)
|
||||
? rawPlan.tasks.map((item) => {
|
||||
const taskType = String(item.task_type || item.taskType || '')
|
||||
const missingFields = Array.isArray(item.missing_fields || item.missingFields)
|
||||
const rawMissingFields = Array.isArray(item.missing_fields || item.missingFields)
|
||||
? item.missing_fields || item.missingFields
|
||||
: []
|
||||
const missingFields = filterStewardBlockingMissingFields(rawMissingFields, taskType)
|
||||
return {
|
||||
taskId: String(item.task_id || item.taskId || ''),
|
||||
taskType,
|
||||
@@ -188,7 +208,7 @@ export function buildStewardPlanMessageText(plan) {
|
||||
}
|
||||
|
||||
export function buildStewardFieldItems(fields = [], taskType = '') {
|
||||
const safeFields = Array.isArray(fields) ? fields : []
|
||||
const safeFields = filterStewardBlockingMissingFields(fields, taskType)
|
||||
const seen = new Set()
|
||||
return safeFields
|
||||
.map((field) => normalizeFieldKey(field))
|
||||
@@ -202,18 +222,44 @@ export function buildStewardFieldItems(fields = [], taskType = '') {
|
||||
.map((field) => resolveFieldDisplay(field, taskType))
|
||||
}
|
||||
|
||||
export function formatStewardMissingFieldList(fields = [], taskType = '') {
|
||||
export function formatStewardMissingFieldList(fields = [], taskType = '', options = {}) {
|
||||
const includeHints = options.includeHints !== false
|
||||
return buildStewardFieldItems(fields, taskType)
|
||||
.map((item) => item.hint ? `${item.label}(${item.hint})` : item.label)
|
||||
.map((item) => includeHints && item.hint ? `${item.label}(${item.hint})` : item.label)
|
||||
.join('、')
|
||||
}
|
||||
|
||||
export function filterStewardBlockingMissingFields(fields = [], taskType = '') {
|
||||
const safeFields = Array.isArray(fields) ? fields : []
|
||||
const seen = new Set()
|
||||
if (taskType !== 'expense_application') {
|
||||
return safeFields
|
||||
.map((field) => normalizeFieldKey(field))
|
||||
.filter((field) => {
|
||||
if (!field || seen.has(field)) {
|
||||
return false
|
||||
}
|
||||
seen.add(field)
|
||||
return true
|
||||
})
|
||||
}
|
||||
return safeFields
|
||||
.map((field) => normalizeFieldKey(field))
|
||||
.filter((field) => {
|
||||
if (!field || seen.has(field) || APPLICATION_NON_BLOCKING_MISSING_FIELDS.has(field)) {
|
||||
return false
|
||||
}
|
||||
seen.add(field)
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
export function formatStewardOntologyFields(fields = {}, taskType = '') {
|
||||
return Object.entries(fields || {})
|
||||
.filter(([, value]) => String(value || '').trim())
|
||||
.map(([key, value]) => {
|
||||
const field = resolveFieldDisplay(key, taskType)
|
||||
return `${field.label}:${value}`
|
||||
return `${field.label}:${formatStewardFieldDisplayValue(field.key, value)}`
|
||||
})
|
||||
.join(';')
|
||||
}
|
||||
@@ -246,6 +292,7 @@ export function buildStewardSuggestedActions(plan) {
|
||||
steward_confirmation_id: String(action.confirmation_id || action.confirmationId || ''),
|
||||
steward_plan_id: normalized.planId,
|
||||
steward_next_task_id: task?.taskId || '',
|
||||
steward_current_task: buildStewardTaskPayload(task),
|
||||
steward_remaining_task_count: normalized.tasks.filter((item) => item.taskId !== task?.taskId).length,
|
||||
steward_remaining_tasks: buildRemainingTaskPayload(normalized, task?.taskId)
|
||||
}
|
||||
@@ -447,7 +494,11 @@ function buildStewardCarryText(actionType, task, group, normalized = null) {
|
||||
}
|
||||
|
||||
const fields = formatStewardOntologyFields(task.ontologyFields || {}, task.taskType)
|
||||
const missingFields = formatStewardMissingFieldList(task.missingFields || [], task.taskType)
|
||||
const missingFields = formatStewardMissingFieldList(
|
||||
task.missingFields || [],
|
||||
task.taskType,
|
||||
{ includeHints: false }
|
||||
)
|
||||
const lines = [
|
||||
actionType === 'confirm_create_application'
|
||||
? `小财管家已完成意图识别,请先创建申请单:${task.title || task.taskTypeLabel}。`
|
||||
@@ -458,8 +509,12 @@ function buildStewardCarryText(actionType, task, group, normalized = null) {
|
||||
group?.excludedAttachmentNames?.length ? `暂不归集附件:${group.excludedAttachmentNames.join('、')}` : '',
|
||||
missingFields ? `还需要补充:${missingFields}` : '',
|
||||
actionType === 'confirm_create_application'
|
||||
? '请直接生成申请单核对结果;信息足够时生成申请单,但在入库或提交审批前仍需让我确认。'
|
||||
: '请直接生成报销核对结果;需要创建草稿、绑定附件或提交审批前仍需让我确认。'
|
||||
? missingFields
|
||||
? '请先追问上述缺失信息,不要直接生成申请单核对表,也不要替用户默认填写。'
|
||||
: '请直接生成申请单核对结果;信息足够时生成申请单,但在入库或提交审批前仍需让我确认。'
|
||||
: missingFields
|
||||
? '请先追问上述缺失信息,不要直接生成报销核对结果,也不要替用户默认填写。'
|
||||
: '请直接生成报销核对结果;需要创建草稿、绑定附件或提交审批前仍需让我确认。'
|
||||
]
|
||||
const remainingTaskText = normalized ? buildRemainingTaskText(normalized, task.taskId) : ''
|
||||
if (remainingTaskText) {
|
||||
@@ -495,6 +550,12 @@ function resolveFieldDisplay(field, taskType = '') {
|
||||
}
|
||||
}
|
||||
|
||||
function formatStewardFieldDisplayValue(field, value) {
|
||||
const key = normalizeFieldKey(field)
|
||||
const normalizedValue = String(value || '').trim()
|
||||
return FIELD_VALUE_DISPLAY_CONFIG[key]?.[normalizedValue] || normalizedValue
|
||||
}
|
||||
|
||||
function buildRemainingTaskText(normalized, currentTaskId) {
|
||||
const remainingTasks = normalized.tasks.filter((task) => task.taskId !== currentTaskId)
|
||||
if (!remainingTasks.length) {
|
||||
@@ -512,13 +573,20 @@ function buildRemainingTaskText(normalized, currentTaskId) {
|
||||
function buildRemainingTaskPayload(normalized, currentTaskId) {
|
||||
return normalized.tasks
|
||||
.filter((task) => task.taskId !== currentTaskId)
|
||||
.map((task) => ({
|
||||
task_id: task.taskId,
|
||||
task_type: task.taskType,
|
||||
title: task.title,
|
||||
summary: task.summary,
|
||||
assigned_agent: task.assignedAgent,
|
||||
ontology_fields: task.ontologyFields || {},
|
||||
missing_fields: task.missingFields || []
|
||||
}))
|
||||
.map((task) => buildStewardTaskPayload(task))
|
||||
}
|
||||
|
||||
function buildStewardTaskPayload(task) {
|
||||
if (!task) {
|
||||
return null
|
||||
}
|
||||
return {
|
||||
task_id: task.taskId || task.task_id || '',
|
||||
task_type: task.taskType || task.task_type || '',
|
||||
title: task.title || '',
|
||||
summary: task.summary || '',
|
||||
assigned_agent: task.assignedAgent || task.assigned_agent || '',
|
||||
ontology_fields: task.ontologyFields || task.ontology_fields || {},
|
||||
missing_fields: task.missingFields || task.missing_fields || []
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user