feat: 小财管家意图规划与报销提交编排增强

- 完善管家意图识别、模型计划构建与规划器调度
- 重构差旅报销提交编排器与管家计划流程前端交互
- 优化报销消息项样式与文档中心视图
- 新增小财管家与附件上传风险前置复核设计文档
- 补充管家规划器与文档中心测试覆盖
This commit is contained in:
caoxiaozhu
2026-06-04 14:25:14 +08:00
parent 1cbf3fee44
commit f60cebadb8
19 changed files with 2337 additions and 196 deletions

View File

@@ -11,12 +11,28 @@ export function fetchStewardPlan(payload, options = {}) {
export async function fetchStewardPlanStream(payload, handlers = {}, options = {}) {
const {
timeoutMs = 0,
idleTimeoutMs = 90000,
timeoutMessage = '小财管家任务规划超时,请稍后重试。'
} = options
const controller = typeof AbortController !== 'undefined' ? new AbortController() : null
const timeoutId = controller && Number(timeoutMs) > 0
? globalThis.setTimeout(() => controller.abort(), Number(timeoutMs))
: 0
let timeoutId = 0
const armAbortTimer = (delayMs) => {
if (!controller) return
if (timeoutId) {
globalThis.clearTimeout(timeoutId)
timeoutId = 0
}
if (Number(delayMs) > 0) {
timeoutId = globalThis.setTimeout(() => controller.abort(), Number(delayMs))
}
}
const clearAbortTimer = () => {
if (timeoutId) {
globalThis.clearTimeout(timeoutId)
timeoutId = 0
}
}
armAbortTimer(timeoutMs)
let response
try {
@@ -29,9 +45,7 @@ export async function fetchStewardPlanStream(payload, handlers = {}, options = {
signal: controller?.signal
})
} catch (error) {
if (timeoutId) {
globalThis.clearTimeout(timeoutId)
}
clearAbortTimer()
if (error?.name === 'AbortError') {
throw new Error(timeoutMessage)
}
@@ -39,17 +53,13 @@ export async function fetchStewardPlanStream(payload, handlers = {}, options = {
}
if (!response.ok) {
if (timeoutId) {
globalThis.clearTimeout(timeoutId)
}
clearAbortTimer()
throw new Error(await resolveStreamError(response))
}
if (!response.body?.getReader) {
const text = await response.text()
if (timeoutId) {
globalThis.clearTimeout(timeoutId)
}
clearAbortTimer()
return consumeNdjsonText(text, handlers)
}
@@ -59,11 +69,13 @@ export async function fetchStewardPlanStream(payload, handlers = {}, options = {
let finalPlan = null
try {
armAbortTimer(idleTimeoutMs)
while (true) {
const { value, done } = await reader.read()
if (done) {
break
}
armAbortTimer(idleTimeoutMs)
buffer += decoder.decode(value, { stream: true })
const lines = buffer.split('\n')
buffer = lines.pop() || ''
@@ -87,9 +99,7 @@ export async function fetchStewardPlanStream(payload, handlers = {}, options = {
}
throw error
} finally {
if (timeoutId) {
globalThis.clearTimeout(timeoutId)
}
clearAbortTimer()
}
if (!finalPlan) {