feat(桌面与监控): 完善工作台导航和登录活动定位
- 优化桌面标签、上下文标题、前进后退、导航栏隐藏和原生菜单体验 - 补充登录会话 IP 采集、地理位置回退、管理端展示及数据库迁移 - 更新桌面发布检查、运维文档和前后端测试覆盖
This commit is contained in:
@@ -11,7 +11,9 @@ from sqlalchemy import select, update
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.core.config import settings
|
||||
from app.core.request_context import resolve_client_ip
|
||||
from app.models.user_login_session import UserLoginSession
|
||||
from app.services.ip_location import resolve_ip_location
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@@ -59,6 +61,35 @@ def session_client_type(payload: dict[str, Any], headers: Any) -> str:
|
||||
return "desktop" if "desktop" in {from_payload, from_header} else "web"
|
||||
|
||||
|
||||
def login_activity_status(session: UserLoginSession, *, reference_time: datetime | None = None) -> str:
|
||||
if session.ended_at is not None:
|
||||
return "ENDED"
|
||||
cutoff = (reference_time or _now()) - timedelta(seconds=settings.USER_SESSION_ONLINE_SECONDS)
|
||||
return "ONLINE" if _as_utc(session.last_seen_at) >= cutoff else "OFFLINE"
|
||||
|
||||
|
||||
def login_activity_payload(
|
||||
session: UserLoginSession,
|
||||
*,
|
||||
reference_time: datetime | None = None,
|
||||
) -> dict[str, Any]:
|
||||
ip_location = resolve_ip_location(session.login_ip) if session.login_ip else None
|
||||
return {
|
||||
"id": session.id,
|
||||
"client_type": session.client_type,
|
||||
"client_platform": session.client_platform,
|
||||
"client_version": session.client_version,
|
||||
"client_source": session.client_source,
|
||||
"login_ip": session.login_ip,
|
||||
"ip_location": ip_location.location if ip_location else None,
|
||||
"login_at": session.login_at,
|
||||
"last_seen_at": session.last_seen_at,
|
||||
"ended_at": session.ended_at,
|
||||
"end_reason": session.end_reason,
|
||||
"activity_status": login_activity_status(session, reference_time=reference_time),
|
||||
}
|
||||
|
||||
|
||||
async def create_login_session(
|
||||
db: AsyncSession,
|
||||
*,
|
||||
@@ -75,6 +106,7 @@ async def create_login_session(
|
||||
client_platform=_text_header(request.headers, "x-ctms-client-platform", 32),
|
||||
client_version=_text_header(request.headers, "x-ctms-client-version", 64),
|
||||
client_source=_text_header(request.headers, "x-ctms-client-source", 32),
|
||||
login_ip=resolve_client_ip(request),
|
||||
login_at=occurred_at,
|
||||
last_seen_at=occurred_at,
|
||||
)
|
||||
@@ -102,6 +134,7 @@ async def touch_login_session(
|
||||
client_platform=_text_header(request.headers, "x-ctms-client-platform", 32),
|
||||
client_version=_text_header(request.headers, "x-ctms-client-version", 64),
|
||||
client_source=_text_header(request.headers, "x-ctms-client-source", 32),
|
||||
login_ip=resolve_client_ip(request),
|
||||
login_at=now,
|
||||
last_seen_at=now,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user