feat: Event archive management — Event model, migration, API, frontend page (Phase 8)
- Event ORM model with status/level enums, domain categories, review tracking - Alembic migration e7f3a9b1c5d0 for events table - Event crawler service with placeholder data (12 sample events) - GET /api/v1/events with status/domain/search filtering and overdue_days - EventArchivePage with filter toolbar (status, domain, search) and adaptive card grid - Status badges, level badges, domain tags, overdue markers on event cards - Loading/error/empty states, hover-to-honey card interaction Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
"""事件档案 ORM 模型。"""
|
||||
import uuid
|
||||
from datetime import datetime, date
|
||||
from sqlalchemy import String, DateTime, Date, Integer, Enum as SAEnum
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
import enum
|
||||
|
||||
from app.database import Base
|
||||
|
||||
|
||||
class EventStatus(str, enum.Enum):
|
||||
ACTIVE = "active"
|
||||
FADING = "fading"
|
||||
DISSIPATING = "dissipating"
|
||||
CLOSED = "closed"
|
||||
|
||||
|
||||
class EventLevel(str, enum.Enum):
|
||||
A = "A"
|
||||
B = "B"
|
||||
C = "C"
|
||||
|
||||
|
||||
DOMAINS = [
|
||||
"gateway",
|
||||
"crawler",
|
||||
"reporter",
|
||||
"feishu",
|
||||
"database",
|
||||
"security",
|
||||
"network",
|
||||
"storage",
|
||||
"monitor",
|
||||
"scheduler",
|
||||
"api",
|
||||
"other",
|
||||
]
|
||||
|
||||
|
||||
class Event(Base):
|
||||
__tablename__ = "events"
|
||||
|
||||
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
|
||||
title: Mapped[str] = mapped_column(String(255), nullable=False)
|
||||
level: Mapped[EventLevel] = mapped_column(SAEnum(EventLevel), nullable=False)
|
||||
domain: Mapped[str] = mapped_column(String(50), nullable=False, index=True)
|
||||
status: Mapped[EventStatus] = mapped_column(SAEnum(EventStatus), default=EventStatus.ACTIVE, nullable=False, index=True)
|
||||
occurred_date: Mapped[date] = mapped_column(Date, nullable=False)
|
||||
last_reviewed: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
|
||||
no_new_info_count: Mapped[int] = mapped_column(Integer, default=0)
|
||||
next_review: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|
||||
updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
||||
Reference in New Issue
Block a user