feat: 新增风险图谱算法与系统仪表盘及操作反馈体系

后端新增风险图谱算法模块、风险观察与反馈服务、规则 DSL
校验器和可解释性引擎,完善系统仪表盘和财务仪表盘统计,
优化 agent 运行和编排执行链路,清理旧开发文档,前端新增
系统趋势、负载热力图等多种仪表盘图表组件,完善操作反馈
对话框和工作台日期选择器,优化报销创建和审批详情交互,
补充单元测试覆盖。
This commit is contained in:
caoxiaozhu
2026-05-30 15:46:51 +08:00
parent 4c59941ec6
commit 7989f3a159
314 changed files with 30073 additions and 20626 deletions

View File

@@ -9,6 +9,7 @@ from app.algorithem.employee_behavior_profile import ALGORITHM_VERSION
from app.models.agent_run import AgentRun
from app.models.employee import Employee
from app.models.financial_record import ExpenseClaim
from app.services.user_session_metrics import UserSessionMetricService
TRAVEL_EXPENSE_TYPES = {
"travel",
@@ -174,6 +175,50 @@ class EmployeeBehaviorProfileMetricHelpers:
def _sum_agent_run_duration_ms(self, runs: list[AgentRun]) -> int:
return sum(self._agent_run_duration_ms(run) for run in runs)
def _resolve_usage_duration_metrics(
self,
identifiers: set[str],
cutoff: Any,
runs: list[AgentRun],
) -> dict[str, Any]:
ai_duration_ms = self._sum_agent_run_duration_ms(runs)
online_duration_ms = UserSessionMetricService(self.db).sum_duration_ms(identifiers, cutoff)
if online_duration_ms > 0:
usage_duration_ms = online_duration_ms
usage_duration_mode = "online_session"
else:
usage_duration_ms = ai_duration_ms
usage_duration_mode = "agent_run_fallback"
return {
"online_duration_ms": online_duration_ms,
"usage_duration_ms": usage_duration_ms,
"usage_duration_mode": usage_duration_mode,
"ai_run_duration_ms": ai_duration_ms,
"ai_run_duration_mode": "elapsed_or_tool_call_fallback",
}
def _merge_live_usage_duration_metrics(
self,
payloads: list[dict[str, Any]],
identifiers: set[str],
cutoff: Any,
) -> list[dict[str, Any]]:
online_duration_ms = UserSessionMetricService(self.db).sum_duration_ms(identifiers, cutoff)
if online_duration_ms <= 0:
return payloads
next_payloads: list[dict[str, Any]] = []
for payload in payloads:
if payload.get("profile_type") != "ai_usage":
next_payloads.append(payload)
continue
metrics = dict(payload.get("metrics") or {})
metrics["online_duration_ms"] = online_duration_ms
metrics["usage_duration_ms"] = online_duration_ms
metrics["usage_duration_mode"] = "online_session"
next_payloads.append({**payload, "metrics": metrics})
return next_payloads
def _agent_run_duration_ms(self, run: AgentRun) -> int:
if run.started_at is not None and run.finished_at is not None:
try: