feat(web): add OCR service and update travel reimbursement view

- web/src/services/ocr.js: add OCR service API client
- web/src/views/scripts/TravelReimbursementCreateView.js: update travel form script with OCR integration
This commit is contained in:
caoxiaozhu
2026-05-12 03:05:51 +00:00
parent a3f3421ebc
commit 035be110b6
2 changed files with 58 additions and 3 deletions

View File

@@ -1,6 +1,7 @@
import { computed, nextTick, onMounted, ref } from 'vue'
import { useSystemState } from '../../composables/useSystemState.js'
import { recognizeOcrFiles } from '../../services/ocr.js'
import { runOrchestrator } from '../../services/orchestrator.js'
const DEFAULT_REQUEST = {
@@ -128,6 +129,26 @@ function buildMessageMeta(payload, fileNames = []) {
return items
}
function normalizeOcrDocuments(payload) {
const documents = Array.isArray(payload?.documents) ? payload.documents : []
return documents.slice(0, 5).map((item) => ({
filename: item.filename,
summary: item.summary,
text: String(item.text || '').slice(0, 240),
avg_score: Number(item.avg_score || 0),
line_count: Number(item.line_count || 0),
warnings: Array.isArray(item.warnings) ? item.warnings : []
}))
}
function buildOcrSummary(payload) {
const parts = normalizeOcrDocuments(payload)
.map((item) => `${item.filename}${item.summary || item.text}`)
.filter(Boolean)
return parts.join('')
}
function buildWelcomeInsight(entrySource, linkedRequest) {
return {
intent: 'welcome',
@@ -360,7 +381,7 @@ export default {
submitComposer()
}
function buildBackendMessage(rawText, fileNames) {
function buildBackendMessage(rawText, fileNames, ocrSummary = '') {
const parts = []
const normalizedText = String(rawText || '').trim()
@@ -374,6 +395,10 @@ export default {
parts.push(`附件名称:${fileNames.join('、')}`)
}
if (ocrSummary) {
parts.push(`OCR摘要${ocrSummary}`)
}
if (props.entrySource === 'detail') {
parts.push(`关联单号:${linkedRequest.value.id}`)
}
@@ -389,7 +414,6 @@ export default {
const fileNames = files.map((file) => file.name)
const userText =
rawText || `我上传了 ${fileNames.length} 份票据,请帮我识别并给出报销建议。`
const backendMessage = buildBackendMessage(rawText, fileNames)
messages.value.push(createMessage('user', userText, fileNames))
@@ -409,6 +433,21 @@ export default {
try {
const user = currentUser.value || {}
let ocrPayload = null
let ocrSummary = ''
let ocrDocuments = []
if (files.length) {
try {
ocrPayload = await recognizeOcrFiles(files)
ocrSummary = buildOcrSummary(ocrPayload)
ocrDocuments = normalizeOcrDocuments(ocrPayload)
} catch (error) {
console.warn('OCR request failed:', error)
}
}
const backendMessage = buildBackendMessage(rawText, fileNames, ocrSummary)
const payload = await runOrchestrator({
source: 'user_message',
user_id: user.username || user.name || 'anonymous',
@@ -421,7 +460,9 @@ export default {
entry_source: props.entrySource,
request_context: linkedRequest.value,
attachment_names: fileNames,
attachment_count: fileNames.length
attachment_count: fileNames.length,
ocr_summary: ocrSummary,
ocr_documents: ocrDocuments
}
})