feat: 新增风险规则生成引擎与知识图谱可视化

后端新增风险规则自动生成和模板执行服务,支持从规则资产
批量生成并持久化风险规则文件;知识库入库日志增强图谱
查询和本地 RAG 回退,前端审计页面增加风险规则模型和流
程图组件,知识入库面板拆分为图谱可视化子组件,报销创
建页面增加引导式流程模型,更新知识库索引数据。
This commit is contained in:
caoxiaozhu
2026-05-23 19:54:42 +08:00
parent 5b388d08c0
commit 575f093c74
63 changed files with 35497 additions and 1517 deletions

View File

@@ -15,6 +15,7 @@ import {
SESSION_TYPE_KNOWLEDGE,
buildInitialInsightFromConversation,
buildWelcomeInsight,
buildWelcomeQuickActions,
createWelcomeAssistantMessage,
hasMeaningfulSessionMessages,
normalizeInitialConversationMessages,
@@ -25,6 +26,10 @@ import {
serializeSessionMessages,
shouldPreferPersistedSessionState
} from './travelReimbursementConversationModel.js'
import {
createEmptyGuidedFlowState,
normalizeGuidedFlowState
} from './travelReimbursementGuidedFlowModel.js'
export function useTravelReimbursementSessionState({
props,
@@ -36,9 +41,26 @@ export function useTravelReimbursementSessionState({
scrollToBottom,
getSessionRuntimeRefs = () => ({})
}) {
function refreshWelcomeQuickActions(messages, sessionType) {
if (!Array.isArray(messages) || !messages.length) {
return []
}
const currentActions = buildWelcomeQuickActions(
sessionType,
currentUser.value,
props.entrySource,
linkedRequest.value
)
return messages.map((message) => (
message?.isWelcome
? { ...message, welcomeQuickActions: currentActions }
: message
))
}
function buildConversationSessionState(conversation, fallbackSessionType = SESSION_TYPE_EXPENSE) {
const sessionType = resolveInitialSessionType(conversation) || fallbackSessionType
const restoredMessages = normalizeInitialConversationMessages(conversation)
const restoredMessages = refreshWelcomeQuickActions(normalizeInitialConversationMessages(conversation), sessionType)
const initialInsight = buildInitialInsightFromConversation(conversation)
const restoredReviewFilePreviews = buildReviewFilePreviewsFromMessages(restoredMessages)
@@ -56,6 +78,7 @@ export function useTravelReimbursementSessionState({
attachedFiles: [],
composerFilesExpanded: false,
composerUploadIntent: '',
guidedFlowState: createEmptyGuidedFlowState(),
insightPanelCollapsed: false
}
}
@@ -79,6 +102,7 @@ export function useTravelReimbursementSessionState({
attachedFiles: [],
composerFilesExpanded: false,
composerUploadIntent: '',
guidedFlowState: createEmptyGuidedFlowState(),
insightPanelCollapsed: false
}
}
@@ -90,7 +114,7 @@ export function useTravelReimbursementSessionState({
}
const sessionType = String(state.sessionType || snapshot.sessionType || fallbackSessionType || '').trim() || SESSION_TYPE_EXPENSE
const restoredMessages = normalizeSnapshotMessages(state.messages)
const restoredMessages = refreshWelcomeQuickActions(normalizeSnapshotMessages(state.messages), sessionType)
if (
!hasMeaningfulSessionMessages(restoredMessages)
&& !String(state.conversationId || '').trim()
@@ -114,6 +138,7 @@ export function useTravelReimbursementSessionState({
attachedFiles: [],
composerFilesExpanded: false,
composerUploadIntent: String(state.composerUploadIntent || '').trim(),
guidedFlowState: normalizeGuidedFlowState(state.guidedFlowState),
insightPanelCollapsed: Boolean(state.insightPanelCollapsed)
}
}
@@ -155,6 +180,7 @@ export function useTravelReimbursementSessionState({
})
const currentInsight = ref(initialSessionState.currentInsight)
const composerUploadIntent = ref(String(initialSessionState.composerUploadIntent || '').trim())
const guidedFlowState = ref(normalizeGuidedFlowState(initialSessionState.guidedFlowState))
const insightPanelCollapsed = ref(false)
const sessionSwitchBusy = ref(false)
let knowledgeSessionResetPromise = Promise.resolve()
@@ -170,6 +196,7 @@ export function useTravelReimbursementSessionState({
reviewFilePreviews: filterPersistableFilePreviews(state.reviewFilePreviews),
composerDraft: String(state.composerDraft || ''),
composerUploadIntent: String(state.composerUploadIntent || '').trim(),
guidedFlowState: normalizeGuidedFlowState(state.guidedFlowState),
insightPanelCollapsed: Boolean(state.insightPanelCollapsed)
}
}
@@ -209,6 +236,7 @@ export function useTravelReimbursementSessionState({
attachedFiles: runtimeRefs.attachedFiles?.value ?? [],
composerFilesExpanded: runtimeRefs.composerFilesExpanded?.value ?? false,
composerUploadIntent: composerUploadIntent.value,
guidedFlowState: runtimeRefs.guidedFlowState?.value ?? guidedFlowState.value,
insightPanelCollapsed: insightPanelCollapsed.value
}
}
@@ -246,6 +274,11 @@ export function useTravelReimbursementSessionState({
runtimeRefs.composerFilesExpanded.value = Boolean(nextState.composerFilesExpanded)
}
composerUploadIntent.value = String(nextState.composerUploadIntent || '').trim()
const nextGuidedFlowState = normalizeGuidedFlowState(nextState.guidedFlowState)
guidedFlowState.value = nextGuidedFlowState
if (runtimeRefs.guidedFlowState) {
runtimeRefs.guidedFlowState.value = nextGuidedFlowState
}
insightPanelCollapsed.value = Boolean(nextState.insightPanelCollapsed)
nextTick(() => {
adjustComposerTextareaHeight()
@@ -322,6 +355,7 @@ export function useTravelReimbursementSessionState({
currentInsight,
reviewFilePreviews,
composerUploadIntent,
guidedFlowState,
insightPanelCollapsed,
sessionSwitchBusy,
initialSessionState,