from __future__ import annotations from datetime import date as DateType, datetime as DateTime from typing import Any from pydantic import BaseModel, ConfigDict, Field class ORMModel(BaseModel): model_config = ConfigDict(from_attributes=True, use_enum_values=True) class UserRead(ORMModel): id: int name: str email: str role: str created_at: DateTime updated_at: DateTime class FeishuSessionBase(BaseModel): title: str date: DateType | None = None teachers: str | None = None feishu_doc_url: str | None = None feishu_record_id: str | None = None source_file_name: str | None = None source_text: str | None = None class FeishuSessionCreate(FeishuSessionBase): session_code: str | None = None class FeishuSessionUpdate(BaseModel): title: str | None = None date: DateType | None = None teachers: str | None = None feishu_doc_url: str | None = None source_file_name: str | None = None source_text: str | None = None process_status: str | None = None failed_reason: str | None = None class FeishuSessionRead(ORMModel): id: int session_code: str title: str date: DateType | None teachers: str | None feishu_doc_url: str | None feishu_record_id: str | None source_file_name: str | None source_text: str | None process_status: str qa_count: int pending_review_count: int approved_count: int standard_qa_count: int failed_reason: str | None created_at: DateTime updated_at: DateTime class RawQAItemUpdate(BaseModel): normalized_question: str | None = None normalized_answer: str | None = None suggested_standard_question: str | None = None suggested_standard_answer: str | None = None answer_person: str | None = None primary_topic: str | None = None problem_tags: list[str] | None = None course_stage: str | None = None audience_tags: list[str] | None = None emotion_intensity: str | None = None risk_level: str | None = None risk_types: list[str] | None = None risk_notes: str | None = None need_desensitization: bool | None = None desensitization_status: str | None = None review_status: str | None = None review_notes: str | None = None suggested_to_standard_qa: bool | None = None class ReviewActionRequest(BaseModel): reviewer_id: int | None = None comment: str | None = None class RawQAItemRead(ORMModel): id: int session_id: int qa_code: str raw_question: str normalized_question: str | None raw_answer: str normalized_answer: str | None suggested_standard_question: str | None suggested_standard_answer: str | None answer_person: str | None primary_topic: str problem_tags: list[str] course_stage: str audience_tags: list[str] emotion_intensity: str | None risk_level: str risk_types: list[str] risk_notes: str | None need_desensitization: bool desensitization_status: str review_status: str reviewer_id: int | None review_notes: str | None suggested_to_standard_qa: bool source_timestamp: str | None created_at: DateTime updated_at: DateTime class StandardQAUpdate(BaseModel): standard_question: str | None = None standard_answer: str | None = None similar_questions: list[str] | None = None primary_topic: str | None = None problem_tags: list[str] | None = None course_stage: str | None = None audience_tags: list[str] | None = None answer_boundary: str | None = None forbidden_expressions: list[str] | None = None risk_level: str | None = None audit_status: str | None = None call_status: str | None = None disabled_reason: str | None = None class StandardQARead(ORMModel): id: int standard_code: str source_raw_qa_id: int session_id: int standard_question: str standard_answer: str similar_questions: list[str] primary_topic: str problem_tags: list[str] course_stage: str audience_tags: list[str] answer_boundary: str | None forbidden_expressions: list[str] risk_level: str audit_status: str call_status: str last_reviewer_id: int | None disabled_reason: str | None created_at: DateTime updated_at: DateTime class CallableQARead(ORMModel): id: int standard_code: str standard_question: str standard_answer: str similar_questions: list[str] primary_topic: str problem_tags: list[str] course_stage: str audience_tags: list[str] answer_boundary: str | None forbidden_expressions: list[str] source_raw_qa_id: int session_id: int class TaskRunRead(ORMModel): id: int task_type: str task_status: str started_at: DateTime | None ended_at: DateTime | None sessions_scanned: int sessions_processed: int qa_created: int qa_failed: int error_message: str | None retry_count: int created_at: DateTime class AuditLogRead(ORMModel): id: int user_id: int | None target_type: str target_id: int action: str before_status: str | None after_status: str | None comment: str | None created_at: DateTime class DashboardSummary(BaseModel): total_sessions: int processed_sessions: int pending_review_count: int high_risk_count: int approved_qa_count: int standard_qa_count: int callable_qa_count: int last_task_status: str | None last_task_time: DateTime | None last_task_error: str | None class SafeSettingsRead(BaseModel): feishu_configured: bool openai_configured: bool model_name: str schedule_cron: str schedule_timezone: str mock_mode: bool database_url: str = Field(description="敏感连接串不原样返回,仅返回驱动类型") feishu_tables_configured: dict[str, bool] system_settings: list[dict[str, Any]] class SettingsPatch(BaseModel): settings: dict[str, str] class FeishuStatus(BaseModel): configured: bool mock_mode: bool app_token_configured: bool wiki_node_token_configured: bool = False table_ids: dict[str, bool] token_ok: bool message: str class FeishuTableTemplate(BaseModel): table_key: str table_name: str env_name: str required_fields: list[str] class FeishuSetupGuide(BaseModel): required_env: list[str] required_permissions: list[str] tables: list[FeishuTableTemplate] notes: list[str]