feat(web): 工作台 AI 模式与差旅/风险建议交互优化
- 新增 PersonalWorkbenchAiMode 组件、AI 侧边栏与 orb 机器人视觉资源 - 新增 aiApplicationDraftModel / aiExpenseDraftModel / aiWorkbenchConversationStore 及业务准入 aiSidebarBusinessAccess,支撑 AI 模式下的申请与报销草稿 - 顶栏、侧边栏、工作台样式重构,适配 AI 模式切换与响应式布局 - 同步 steward plan/off_topic、差旅报销引导流、风险建议卡片等测试
This commit is contained in:
@@ -89,6 +89,22 @@ function padDatePart(value) {
|
||||
return String(value).padStart(2, '0')
|
||||
}
|
||||
|
||||
function formatMonthKey(date) {
|
||||
return `${date.getFullYear()}-${padDatePart(date.getMonth() + 1)}`
|
||||
}
|
||||
|
||||
function formatMonthLabel(date) {
|
||||
return `${date.getMonth() + 1}月`
|
||||
}
|
||||
|
||||
function shiftMonth(date, offset) {
|
||||
return new Date(date.getFullYear(), date.getMonth() + offset, 1)
|
||||
}
|
||||
|
||||
function resolveMonthStart(date) {
|
||||
return new Date(date.getFullYear(), date.getMonth(), 1)
|
||||
}
|
||||
|
||||
function formatDateTimeLabel(value) {
|
||||
if (value instanceof Date) {
|
||||
return [
|
||||
@@ -558,6 +574,55 @@ function buildExpenseOperationRows(todoItems, notifications, progressItems) {
|
||||
.slice(0, 8)
|
||||
}
|
||||
|
||||
function buildMonthlyAmountMap(ownedRequests) {
|
||||
const rows = new Map()
|
||||
|
||||
for (const request of ownedRequests) {
|
||||
const date = toDate(resolveClaimDate(request))
|
||||
if (!date) {
|
||||
continue
|
||||
}
|
||||
|
||||
const key = formatMonthKey(date)
|
||||
rows.set(key, (rows.get(key) || 0) + parseNumber(request?.amount))
|
||||
}
|
||||
|
||||
return rows
|
||||
}
|
||||
|
||||
function resolveTrendAnchorDate(ownedRequests) {
|
||||
const dates = ownedRequests
|
||||
.map((request) => toDate(resolveClaimDate(request)))
|
||||
.filter(Boolean)
|
||||
.sort((left, right) => right.getTime() - left.getTime())
|
||||
|
||||
return resolveMonthStart(dates[0] || new Date())
|
||||
}
|
||||
|
||||
function buildReimbursementTrendRows(ownedRequests) {
|
||||
const monthlyAmountMap = buildMonthlyAmountMap(ownedRequests)
|
||||
const anchor = resolveTrendAnchorDate(ownedRequests)
|
||||
|
||||
return Array.from({ length: 6 }, (_, index) => {
|
||||
const month = shiftMonth(anchor, index - 5)
|
||||
const previousMonth = shiftMonth(month, -12)
|
||||
const key = formatMonthKey(month)
|
||||
const previousKey = formatMonthKey(previousMonth)
|
||||
const amount = monthlyAmountMap.get(key) || 0
|
||||
const previousAmount = monthlyAmountMap.get(previousKey) || 0
|
||||
|
||||
return {
|
||||
key,
|
||||
label: formatMonthLabel(month),
|
||||
amount,
|
||||
amountLabel: formatCurrency(amount),
|
||||
previousKey,
|
||||
previousAmount,
|
||||
previousAmountLabel: formatCurrency(previousAmount)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function buildWorkbenchSummary(requests, currentUser) {
|
||||
const allRequests = Array.isArray(requests)
|
||||
? requests
|
||||
@@ -602,6 +667,7 @@ export function buildWorkbenchSummary(requests, currentUser) {
|
||||
highRiskCount,
|
||||
todoItems,
|
||||
progressItems,
|
||||
reimbursementTrendRows: buildReimbursementTrendRows(ownedRequests),
|
||||
notifications,
|
||||
expenseStatsDetail,
|
||||
unreadNotificationCount: notifications.filter((item) => item.unread).length
|
||||
|
||||
Reference in New Issue
Block a user