feat: 新增归档中心页面并完善知识库与报销查询能力

新增前端归档中心视图及相关工具函数,扩充知识库文档分类和
提取器支持多种格式,增强编排器报销查询的多维度检索,优
化本体规则和用户代理审核消息,前端完善报销创建和审批详
情交互细节,补充单元测试覆盖。
This commit is contained in:
caoxiaozhu
2026-05-22 16:00:19 +08:00
parent 1f15699013
commit 88ff04bef8
120 changed files with 6236 additions and 643 deletions

View File

@@ -26,6 +26,7 @@ import {
export function useTravelReimbursementReviewDrawer({
activeReviewPayload,
activeReviewPanelScope,
reviewFilePreviews,
flowSteps,
submitting,
@@ -92,6 +93,11 @@ export function useTravelReimbursementReviewDrawer({
const reviewRiskItems = computed(() => buildReviewRiskItems(activeReviewPayload.value))
const reviewRiskEmpty = computed(() => !reviewRiskItems.value.length)
const reviewDocumentCount = computed(() => reviewDocumentDrafts.value.length)
const normalizedReviewPanelScope = computed(() => {
const scope = String(activeReviewPanelScope?.value || '').trim()
return ['overview', 'documents', 'risk'].includes(scope) ? scope : ''
})
const reviewOverviewDrawerAvailable = computed(() => normalizedReviewPanelScope.value === 'overview')
const reviewDocumentDrawerAvailable = computed(() => reviewDocumentCount.value > 0)
const reviewRiskDrawerAvailable = computed(() => !reviewRiskEmpty.value)
const reviewFlowDrawerAvailable = computed(() => flowSteps.value.length > 0)
@@ -135,22 +141,31 @@ export function useTravelReimbursementReviewDrawer({
: 'mdi mdi-timeline-clock-outline'
))
const activeReviewDocument = computed(() => reviewDocumentDrafts.value[activeReviewDocumentIndex.value] ?? null)
const activeReviewDocumentPreview = computed(() =>
activeReviewDocument.value
? (
resolveDocumentPreview(activeReviewFilePreviews.value, activeReviewDocument.value.filename)
|| (
activeReviewDocument.value.preview_kind === 'image' && activeReviewDocument.value.preview_data_url
? {
filename: activeReviewDocument.value.filename,
kind: activeReviewDocument.value.preview_kind,
url: activeReviewDocument.value.preview_data_url
}
: null
)
)
: null
)
const activeReviewDocumentPreview = computed(() => {
const document = activeReviewDocument.value
if (!document) return null
const matchedPreview = resolveDocumentPreview(activeReviewFilePreviews.value, document.filename)
if (matchedPreview?.url) {
return matchedPreview
}
const inlineUrl = String(document.preview_url || document.preview_data_url || '').trim()
if (!inlineUrl) {
return null
}
const explicitKind = String(document.preview_kind || '').trim()
const inferredKind = inlineUrl.startsWith('data:image/') ? 'image' : explicitKind
if (inferredKind !== 'image') {
return null
}
return {
filename: document.filename,
kind: 'image',
url: inlineUrl
}
})
const canPreviewActiveReviewDocument = computed(() => Boolean(activeReviewDocumentPreview.value?.url))
const reviewDocumentDirty = computed(() => {
const baseValue = JSON.stringify(reviewDocumentBaseDrafts.value.map(normalizeReviewDocumentComparableValue))
@@ -170,9 +185,22 @@ export function useTravelReimbursementReviewDrawer({
activeReviewDocumentIndex.value = nextDocumentDrafts.length
? Math.min(activeReviewDocumentIndex.value, nextDocumentDrafts.length - 1)
: 0
reviewDrawerMode.value = resolveReviewRiskBriefs(payload).length
? REVIEW_DRAWER_MODE_RISK
: REVIEW_DRAWER_MODE_REVIEW
const hasDocuments = nextDocumentDrafts.length > 0
const hasRisks = resolveReviewRiskBriefs(payload).length > 0
const scope = normalizedReviewPanelScope.value
if (scope === 'documents' && hasDocuments) {
reviewDrawerMode.value = REVIEW_DRAWER_MODE_DOCUMENTS
} else if (scope === 'risk' && hasRisks) {
reviewDrawerMode.value = REVIEW_DRAWER_MODE_RISK
} else if (scope === 'overview') {
reviewDrawerMode.value = REVIEW_DRAWER_MODE_REVIEW
} else if (hasDocuments) {
reviewDrawerMode.value = REVIEW_DRAWER_MODE_DOCUMENTS
} else if (hasRisks) {
reviewDrawerMode.value = REVIEW_DRAWER_MODE_RISK
} else {
reviewDrawerMode.value = REVIEW_DRAWER_MODE_REVIEW
}
reviewInlinePendingFiles.value = []
reviewInlineEditorKey.value = ''
reviewInlineErrors.value = {}
@@ -348,14 +376,27 @@ export function useTravelReimbursementReviewDrawer({
}
function enforceReviewDrawerAvailability() {
if (!reviewOverviewDrawerAvailable.value && reviewDrawerMode.value === REVIEW_DRAWER_MODE_REVIEW) {
if (reviewDocumentDrawerAvailable.value) {
reviewDrawerMode.value = REVIEW_DRAWER_MODE_DOCUMENTS
} else if (reviewRiskDrawerAvailable.value) {
reviewDrawerMode.value = REVIEW_DRAWER_MODE_RISK
}
}
if (!reviewDocumentDrawerAvailable.value && reviewDrawerMode.value === REVIEW_DRAWER_MODE_DOCUMENTS) {
reviewDrawerMode.value = REVIEW_DRAWER_MODE_REVIEW
reviewDrawerMode.value = reviewOverviewDrawerAvailable.value
? REVIEW_DRAWER_MODE_REVIEW
: REVIEW_DRAWER_MODE_RISK
}
if (!reviewRiskDrawerAvailable.value && reviewDrawerMode.value === REVIEW_DRAWER_MODE_RISK) {
reviewDrawerMode.value = REVIEW_DRAWER_MODE_REVIEW
reviewDrawerMode.value = reviewOverviewDrawerAvailable.value
? REVIEW_DRAWER_MODE_REVIEW
: REVIEW_DRAWER_MODE_DOCUMENTS
}
if (!reviewFlowDrawerAvailable.value && reviewDrawerMode.value === REVIEW_DRAWER_MODE_FLOW) {
reviewDrawerMode.value = REVIEW_DRAWER_MODE_REVIEW
reviewDrawerMode.value = reviewOverviewDrawerAvailable.value
? REVIEW_DRAWER_MODE_REVIEW
: (reviewDocumentDrawerAvailable.value ? REVIEW_DRAWER_MODE_DOCUMENTS : REVIEW_DRAWER_MODE_RISK)
}
}
@@ -390,6 +431,7 @@ export function useTravelReimbursementReviewDrawer({
reviewRecognitionNotes,
reviewDocumentSummaries,
reviewDocumentCount,
reviewOverviewDrawerAvailable,
isReviewDocumentDrawer,
isReviewRiskDrawer,
isReviewFlowDrawer,