You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
196 lines
7.0 KiB
196 lines
7.0 KiB
import uuid
|
|
import json
|
|
from datetime import datetime
|
|
from fastapi import APIRouter, Depends, HTTPException, Request
|
|
from sqlalchemy import select, func
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
from database import get_db
|
|
from models import User, ChatSession, ChatMessage
|
|
from modules.org.router import _get_subordinate_ids, _user_to_out
|
|
from schemas import EmployeeAnalysis, UserOut
|
|
|
|
router = APIRouter(prefix="/api/monitor", tags=["monitor"])
|
|
|
|
|
|
@router.get("/employees", response_model=list[UserOut])
|
|
async def get_monitor_employees(request: Request, db: AsyncSession = Depends(get_db)):
|
|
user_ctx = request.state.user
|
|
cur_id = uuid.UUID(user_ctx["id"])
|
|
|
|
if user_ctx["data_scope"] == "all":
|
|
result = await db.execute(select(User).where(User.status == "active"))
|
|
return [await _user_to_out(db, u) for u in result.scalars().all()]
|
|
|
|
elif user_ctx["data_scope"] == "subordinate_only":
|
|
sub_ids = await _get_subordinate_ids(db, cur_id)
|
|
sub_ids.add(cur_id)
|
|
result = await db.execute(select(User).where(User.id.in_(sub_ids)))
|
|
return [await _user_to_out(db, u) for u in result.scalars().all()]
|
|
|
|
else:
|
|
result = await db.execute(select(User).where(User.id == cur_id))
|
|
return [await _user_to_out(db, u) for u in result.scalars().all()]
|
|
|
|
|
|
@router.get("/employee/{emp_id}/dashboard")
|
|
async def get_employee_dashboard(
|
|
emp_id: uuid.UUID, request: Request, db: AsyncSession = Depends(get_db)
|
|
):
|
|
user_ctx = request.state.user
|
|
cur_id = uuid.UUID(user_ctx["id"])
|
|
|
|
if user_ctx["data_scope"] != "all":
|
|
if user_ctx["data_scope"] == "self_only" and str(emp_id) != user_ctx["id"]:
|
|
raise HTTPException(403, "无权查看此员工数据")
|
|
elif user_ctx["data_scope"] == "subordinate_only":
|
|
sub_ids = await _get_subordinate_ids(db, cur_id)
|
|
sub_ids.add(cur_id)
|
|
if emp_id not in sub_ids:
|
|
raise HTTPException(403, "无权查看此员工数据")
|
|
|
|
emp_result = await db.execute(select(User).where(User.id == emp_id))
|
|
emp = emp_result.scalar_one_or_none()
|
|
if not emp:
|
|
raise HTTPException(404, "员工不存在")
|
|
|
|
total_msgs_result = await db.execute(
|
|
select(func.count(ChatMessage.id)).where(ChatMessage.user_id == emp_id)
|
|
)
|
|
total_messages = total_msgs_result.scalar() or 0
|
|
|
|
session_result = await db.execute(
|
|
select(func.count(ChatSession.id)).where(ChatSession.user_id == emp_id)
|
|
)
|
|
total_sessions = session_result.scalar() or 0
|
|
|
|
recent_msgs_result = await db.execute(
|
|
select(ChatMessage)
|
|
.where(ChatMessage.user_id == emp_id)
|
|
.order_by(ChatMessage.created_at.desc())
|
|
.limit(50)
|
|
)
|
|
recent = recent_msgs_result.scalars().all()
|
|
|
|
topics = {}
|
|
active_days = set()
|
|
for msg in recent:
|
|
if msg.created_at:
|
|
active_days.add(msg.created_at.strftime("%Y-%m-%d"))
|
|
role = msg.role
|
|
topics[role] = topics.get(role, 0) + 1
|
|
|
|
return {
|
|
"code": 200,
|
|
"data": {
|
|
"employee": {
|
|
"id": str(emp.id),
|
|
"name": emp.display_name,
|
|
"department": str(emp.department_id) if emp.department_id else "",
|
|
"position": emp.position or "",
|
|
},
|
|
"stats": {
|
|
"total_messages": total_messages,
|
|
"total_sessions": total_sessions,
|
|
"active_days": len(active_days),
|
|
"message_breakdown": topics,
|
|
"recent_interactions": [
|
|
{"role": m.role, "content": m.content[:200], "created_at": str(m.created_at)}
|
|
for m in recent[:10]
|
|
],
|
|
},
|
|
},
|
|
}
|
|
|
|
|
|
@router.get("/employee/{emp_id}/analysis", response_model=EmployeeAnalysis)
|
|
async def get_employee_analysis(
|
|
emp_id: uuid.UUID, request: Request, db: AsyncSession = Depends(get_db)
|
|
):
|
|
user_ctx = request.state.user
|
|
cur_id = uuid.UUID(user_ctx["id"])
|
|
|
|
if user_ctx["data_scope"] != "all":
|
|
if user_ctx["data_scope"] == "self_only" and str(emp_id) != user_ctx["id"]:
|
|
raise HTTPException(403, "无权查看此员工数据")
|
|
elif user_ctx["data_scope"] == "subordinate_only":
|
|
sub_ids = await _get_subordinate_ids(db, cur_id)
|
|
sub_ids.add(cur_id)
|
|
if emp_id not in sub_ids:
|
|
raise HTTPException(403, "无权查看此员工数据")
|
|
|
|
emp_result = await db.execute(select(User).where(User.id == emp_id))
|
|
emp = emp_result.scalar_one_or_none()
|
|
if not emp:
|
|
raise HTTPException(404, "员工不存在")
|
|
|
|
from config import settings
|
|
from agentscope.model import OpenAIChatModel
|
|
from agentscope.formatter import OpenAIChatFormatter
|
|
from agentscope.message import Msg
|
|
|
|
msgs_result = await db.execute(
|
|
select(ChatMessage)
|
|
.where(ChatMessage.user_id == emp_id)
|
|
.order_by(ChatMessage.created_at.desc())
|
|
.limit(100)
|
|
)
|
|
messages = msgs_result.scalars().all()
|
|
|
|
interaction_log = "\n".join([
|
|
f"[{m.role}] {m.content[:300]}" for m in messages
|
|
])
|
|
|
|
model = OpenAIChatModel(
|
|
config_name="analysis_model",
|
|
model_name=settings.LLM_MODEL,
|
|
api_key=settings.LLM_API_KEY,
|
|
api_base=settings.LLM_API_BASE,
|
|
)
|
|
formatter = OpenAIChatFormatter()
|
|
|
|
prompt = formatter.format([
|
|
Msg("system", f"""你是一个企业管理者分析助手。请根据员工与AI的交互记录,生成一个JSON格式的分析报告。
|
|
|
|
要求:
|
|
1. 分析员工的task_completion_rate (0-1的浮点数)
|
|
2. 统计active_days和total_interactions
|
|
3. 提取main_topics (最多5个关键词)
|
|
4. 评估efficiency_trend ("提升" / "稳定" / "下降")
|
|
5. 给出efficiency_detail (一句话说明)
|
|
6. 列出strengths (2-3个优点)
|
|
7. 给出growth_suggestions (2-3条建议)
|
|
8. 总结personality_traits (一句话)
|
|
|
|
输出严格JSON格式,不要包含markdown代码块标记。""", "system"),
|
|
Msg("user", f"员工姓名: {emp.display_name}\n交互记录:\n{interaction_log}", "user"),
|
|
])
|
|
|
|
try:
|
|
res = await model(prompt)
|
|
res_text = ""
|
|
if isinstance(res, list):
|
|
res_text = res[0].get_text_content() if hasattr(res[0], 'get_text_content') else str(res[0])
|
|
elif hasattr(res, 'get_text_content'):
|
|
res_text = res.get_text_content()
|
|
else:
|
|
res_text = str(res)
|
|
analysis_data = json.loads(res_text)
|
|
except Exception:
|
|
analysis_data = {
|
|
"task_completion_rate": 0.7,
|
|
"active_days": 0,
|
|
"total_interactions": len(messages),
|
|
"main_topics": [],
|
|
"efficiency_trend": "稳定",
|
|
"efficiency_detail": "暂无足够数据",
|
|
"strengths": [],
|
|
"growth_suggestions": [],
|
|
"personality_traits": "暂未收集足够人格特征数据",
|
|
}
|
|
|
|
return EmployeeAnalysis(
|
|
employee_name=emp.display_name,
|
|
department=str(emp.department_id) if emp.department_id else "",
|
|
period=f"最近数据",
|
|
**analysis_data
|
|
)
|