feat: 新增票据夹模块并优化 OCR 与员工画像服务

后端新增票据夹端点、数据模型和服务模块,优化 OCR 端点
Schema 和附件操作逻辑,完善员工行为画像服务和辅助函数,
前端新增票据夹视图和服务层,优化文档中心样式和侧边栏导
航,完善员工画像详情弹窗和权限控制,补充单元测试。
This commit is contained in:
caoxiaozhu
2026-05-29 14:51:18 +08:00
parent 678f64d772
commit 4c59941ec6
33 changed files with 2855 additions and 551 deletions

View File

@@ -264,6 +264,74 @@ def test_current_employee_profile_endpoint_resolves_login_user() -> None:
payload = response.json()
assert payload["employee_id"] == "emp-main"
assert {item["profile_type"] for item in payload["profiles"]} >= {"expense", "ai_usage"}
ai_profile = next(item for item in payload["profiles"] if item["profile_type"] == "ai_usage")
assert ai_profile["metrics"]["ai_run_duration_ms"] == 120
assert payload["profile_tags"]
assert payload["radar"]["dimensions"]
def test_current_admin_profile_endpoint_returns_account_usage_profile() -> None:
session_factory = build_session_factory()
with session_factory() as db:
seed_profile_data(db)
now = datetime.now(UTC)
for index in range(12):
run_id = f"run-admin-usage-{index}"
started_at = now - timedelta(days=1, minutes=index)
db.add(
AgentRun(
run_id=run_id,
agent="user_agent",
source="user_message",
user_id="admin",
status="success",
result_summary="管理员查看运行概览。",
started_at=started_at,
finished_at=started_at + timedelta(seconds=2),
tool_calls=[
AgentToolCall(
run_id=run_id,
tool_type="database",
tool_name="agent_runs.list",
request_json={"limit": 20},
response_json={"ok": True},
status="success",
duration_ms=120,
)
],
)
)
db.commit()
app = create_app()
def override_db() -> Generator[Session, None, None]:
db = session_factory()
try:
yield db
finally:
db.close()
app.dependency_overrides[get_db] = override_db
client = TestClient(app)
response = client.get(
"/api/v1/employee-profiles/me/latest",
params={
"scene": "operations",
"window_days": 90,
"expense_type_scope": "overall",
},
headers={"x-auth-username": "admin", "x-auth-name": "admin", "x-auth-is-admin": "true"},
)
assert response.status_code == 200
payload = response.json()
assert payload["employee_id"] == "admin"
assert payload["empty_reason"] == ""
assert [item["profile_type"] for item in payload["profiles"]] == ["ai_usage"]
metrics = payload["profiles"][0]["metrics"]
assert metrics["ai_run_count"] == 12
assert metrics["ai_run_duration_ms"] == 24000
assert payload["profile_tags"]
assert payload["radar"]["dimensions"]