feat: AI虚拟用户新闻互动系统 v1.3.0 初始提交
- 虚拟用户管理(昵称/头像/性别/简介/邮箱同步到目标平台) - AI互动调度(点赞/收藏/评论/转发) - 日志时间改为北京时间 - 评论达上限后继续执行点赞收藏转发 - 一键登出全部功能 - 浅色主题UI
This commit is contained in:
220
backend/app/schemas/__init__.py
Executable file
220
backend/app/schemas/__init__.py
Executable file
@@ -0,0 +1,220 @@
|
||||
"""Pydantic数据模型 - 请求/响应模式"""
|
||||
from datetime import datetime
|
||||
from typing import Optional, List, Any
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
# ===== 通用响应 =====
|
||||
class ApiResponse(BaseModel):
|
||||
code: int = 200
|
||||
message: str = "success"
|
||||
data: Any = None
|
||||
|
||||
|
||||
class PageResult(BaseModel):
|
||||
total: int
|
||||
page: int
|
||||
page_size: int
|
||||
items: List[Any]
|
||||
|
||||
|
||||
# ===== 虚拟用户 =====
|
||||
class UserCreateRequest(BaseModel):
|
||||
# 必填
|
||||
account: str = Field(..., min_length=1, max_length=128, description="新闻平台账号(必填)")
|
||||
password: str = Field(..., min_length=6, max_length=64, description="登录密码(必填)")
|
||||
# 选填
|
||||
nickname: Optional[str] = Field(None, max_length=64, description="昵称(选填,为空自动生成)")
|
||||
avatar_url: Optional[str] = None
|
||||
activity_level: int = Field(default=1, ge=0, le=2)
|
||||
daily_comment_limit: int = Field(default=10, ge=1, le=100)
|
||||
daily_like_limit: int = Field(default=30, ge=1, le=200)
|
||||
remark: Optional[str] = None
|
||||
|
||||
|
||||
class UserUpdateRequest(BaseModel):
|
||||
nickname: Optional[str] = Field(None, min_length=1, max_length=64)
|
||||
password: Optional[str] = Field(None, min_length=6, max_length=64)
|
||||
avatar_url: Optional[str] = None
|
||||
real_name: Optional[str] = None
|
||||
sex: Optional[int] = None
|
||||
description: Optional[str] = None
|
||||
email: Optional[str] = None
|
||||
activity_level: Optional[int] = Field(None, ge=0, le=2)
|
||||
daily_comment_limit: Optional[int] = Field(None, ge=1, le=100)
|
||||
daily_like_limit: Optional[int] = Field(None, ge=1, le=200)
|
||||
remark: Optional[str] = None
|
||||
is_enabled: Optional[int] = None
|
||||
sync_to_platform: bool = False
|
||||
|
||||
|
||||
class UserResponse(BaseModel):
|
||||
id: int
|
||||
nickname: str
|
||||
account: str
|
||||
avatar_url: Optional[str]
|
||||
real_name: Optional[str] = None
|
||||
sex: int = 0
|
||||
platform_uid: Optional[str] = None
|
||||
status: int
|
||||
status_label: str
|
||||
activity_level: int
|
||||
activity_label: str
|
||||
daily_comment_limit: int
|
||||
daily_like_limit: int
|
||||
today_comment_count: int
|
||||
today_like_count: int
|
||||
total_interactions: int
|
||||
last_login_at: Optional[datetime]
|
||||
last_interact_at: Optional[datetime]
|
||||
remark: Optional[str]
|
||||
is_enabled: int
|
||||
created_at: datetime
|
||||
personality: Optional[dict] = None
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class UserBatchRequest(BaseModel):
|
||||
user_ids: List[int]
|
||||
action: str # enable/disable/logout/delete
|
||||
|
||||
|
||||
# ===== 人格 =====
|
||||
class PersonalityUpdateRequest(BaseModel):
|
||||
character_type: Optional[str] = None
|
||||
language_style: Optional[str] = None
|
||||
interest_tags: Optional[List[str]] = None
|
||||
interact_tendency: Optional[str] = None
|
||||
word_count_min: Optional[int] = Field(None, ge=10, le=500)
|
||||
word_count_max: Optional[int] = Field(None, ge=10, le=1000)
|
||||
personality_desc: Optional[str] = None
|
||||
|
||||
|
||||
class PersonalityResponse(BaseModel):
|
||||
id: int
|
||||
user_id: int
|
||||
character_type: Optional[str]
|
||||
language_style: Optional[str]
|
||||
interest_tags: Optional[List[str]]
|
||||
interact_tendency: Optional[str]
|
||||
word_count_min: int
|
||||
word_count_max: int
|
||||
personality_desc: Optional[str]
|
||||
updated_at: datetime
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
# ===== 互动记录 =====
|
||||
class InteractionQueryParams(BaseModel):
|
||||
page: int = Field(default=1, ge=1)
|
||||
page_size: int = Field(default=20, ge=1, le=100)
|
||||
user_id: Optional[int] = None
|
||||
interact_type: Optional[str] = None
|
||||
status: Optional[int] = None
|
||||
start_date: Optional[str] = None
|
||||
end_date: Optional[str] = None
|
||||
keyword: Optional[str] = None
|
||||
|
||||
|
||||
class InteractionResponse(BaseModel):
|
||||
id: int
|
||||
user_id: int
|
||||
user_nickname: Optional[str]
|
||||
user_account: Optional[str]
|
||||
article_id: Optional[str]
|
||||
article_title: Optional[str]
|
||||
interact_type: str
|
||||
interact_type_label: str
|
||||
content: Optional[str]
|
||||
token_consumed: int
|
||||
status: int
|
||||
status_label: str
|
||||
error_msg: Optional[str]
|
||||
retry_count: int
|
||||
executed_at: datetime
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
# ===== AI模型配置 =====
|
||||
class AIModelCreateRequest(BaseModel):
|
||||
model_name: str = Field(..., min_length=1, max_length=64)
|
||||
provider: str = Field(..., pattern="^(openai|zhipu|wenxin|qianwen|local)$")
|
||||
api_base_url: Optional[str] = None
|
||||
api_key: Optional[str] = None
|
||||
model_version: Optional[str] = None
|
||||
temperature: float = Field(default=0.7, ge=0.0, le=2.0)
|
||||
max_tokens: int = Field(default=1000, ge=1, le=32000)
|
||||
timeout_seconds: int = Field(default=30, ge=5, le=300)
|
||||
is_default: int = Field(default=0, ge=0, le=1)
|
||||
|
||||
|
||||
class AIModelUpdateRequest(BaseModel):
|
||||
model_name: Optional[str] = None
|
||||
api_base_url: Optional[str] = None
|
||||
api_key: Optional[str] = None
|
||||
model_version: Optional[str] = None
|
||||
temperature: Optional[float] = Field(None, ge=0.0, le=2.0)
|
||||
max_tokens: Optional[int] = Field(None, ge=1, le=32000)
|
||||
timeout_seconds: Optional[int] = Field(None, ge=5, le=300)
|
||||
is_default: Optional[int] = None
|
||||
is_enabled: Optional[int] = None
|
||||
|
||||
|
||||
class AIModelResponse(BaseModel):
|
||||
id: int
|
||||
model_name: str
|
||||
provider: str
|
||||
api_base_url: Optional[str]
|
||||
has_api_key: bool
|
||||
model_version: Optional[str]
|
||||
temperature: float
|
||||
max_tokens: int
|
||||
timeout_seconds: int
|
||||
is_default: int
|
||||
is_enabled: int
|
||||
created_at: datetime
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class AIModelTestRequest(BaseModel):
|
||||
model_id: int
|
||||
test_prompt: str = "你好,请简单介绍一下自己。"
|
||||
|
||||
|
||||
# ===== 系统配置 =====
|
||||
class SystemConfigUpdateRequest(BaseModel):
|
||||
configs: dict
|
||||
|
||||
|
||||
# ===== 数据统计 =====
|
||||
class DashboardResponse(BaseModel):
|
||||
user_stats: dict
|
||||
today_interactions: dict
|
||||
monthly_stats: dict
|
||||
token_stats: dict
|
||||
system_status: dict
|
||||
online_users: int
|
||||
|
||||
|
||||
# ===== 调度配置 =====
|
||||
class SchedulerConfigRequest(BaseModel):
|
||||
interact_time_start: Optional[str] = None
|
||||
interact_time_end: Optional[str] = None
|
||||
interact_interval_min: Optional[int] = None
|
||||
interact_interval_max: Optional[int] = None
|
||||
max_concurrent_users: Optional[int] = None
|
||||
daily_token_limit: Optional[int] = None
|
||||
comment_probability: Optional[float] = None
|
||||
reply_probability: Optional[float] = None
|
||||
like_probability: Optional[float] = None
|
||||
collect_probability: Optional[float] = None
|
||||
forward_probability: Optional[float] = None
|
||||
scheduler_enabled: Optional[bool] = None
|
||||
215
backend/app/schemas/__init__.pybuckup
Normal file
215
backend/app/schemas/__init__.pybuckup
Normal file
@@ -0,0 +1,215 @@
|
||||
"""Pydantic数据模型 - 请求/响应模式"""
|
||||
from datetime import datetime
|
||||
from typing import Optional, List, Any
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
# ===== 通用响应 =====
|
||||
class ApiResponse(BaseModel):
|
||||
code: int = 200
|
||||
message: str = "success"
|
||||
data: Any = None
|
||||
|
||||
|
||||
class PageResult(BaseModel):
|
||||
total: int
|
||||
page: int
|
||||
page_size: int
|
||||
items: List[Any]
|
||||
|
||||
|
||||
# ===== 虚拟用户 =====
|
||||
class UserCreateRequest(BaseModel):
|
||||
# 必填
|
||||
account: str = Field(..., min_length=1, max_length=128, description="新闻平台账号(必填)")
|
||||
password: str = Field(..., min_length=6, max_length=64, description="登录密码(必填)")
|
||||
# 选填
|
||||
nickname: Optional[str] = Field(None, max_length=64, description="昵称(选填,为空自动生成)")
|
||||
avatar_url: Optional[str] = None
|
||||
activity_level: int = Field(default=1, ge=0, le=2)
|
||||
daily_comment_limit: int = Field(default=10, ge=1, le=100)
|
||||
daily_like_limit: int = Field(default=30, ge=1, le=200)
|
||||
remark: Optional[str] = None
|
||||
|
||||
|
||||
class UserUpdateRequest(BaseModel):
|
||||
nickname: Optional[str] = Field(None, min_length=1, max_length=64)
|
||||
password: Optional[str] = Field(None, min_length=6, max_length=64)
|
||||
avatar_url: Optional[str] = None
|
||||
activity_level: Optional[int] = Field(None, ge=0, le=2)
|
||||
daily_comment_limit: Optional[int] = Field(None, ge=1, le=100)
|
||||
daily_like_limit: Optional[int] = Field(None, ge=1, le=200)
|
||||
remark: Optional[str] = None
|
||||
is_enabled: Optional[int] = None
|
||||
|
||||
|
||||
class UserResponse(BaseModel):
|
||||
id: int
|
||||
nickname: str
|
||||
account: str
|
||||
avatar_url: Optional[str]
|
||||
real_name: Optional[str] = None
|
||||
sex: int = 0
|
||||
platform_uid: Optional[str] = None
|
||||
status: int
|
||||
status_label: str
|
||||
activity_level: int
|
||||
activity_label: str
|
||||
daily_comment_limit: int
|
||||
daily_like_limit: int
|
||||
today_comment_count: int
|
||||
today_like_count: int
|
||||
total_interactions: int
|
||||
last_login_at: Optional[datetime]
|
||||
last_interact_at: Optional[datetime]
|
||||
remark: Optional[str]
|
||||
is_enabled: int
|
||||
created_at: datetime
|
||||
personality: Optional[dict] = None
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class UserBatchRequest(BaseModel):
|
||||
user_ids: List[int]
|
||||
action: str # enable/disable/logout/delete
|
||||
|
||||
|
||||
# ===== 人格 =====
|
||||
class PersonalityUpdateRequest(BaseModel):
|
||||
character_type: Optional[str] = None
|
||||
language_style: Optional[str] = None
|
||||
interest_tags: Optional[List[str]] = None
|
||||
interact_tendency: Optional[str] = None
|
||||
word_count_min: Optional[int] = Field(None, ge=10, le=500)
|
||||
word_count_max: Optional[int] = Field(None, ge=10, le=1000)
|
||||
personality_desc: Optional[str] = None
|
||||
|
||||
|
||||
class PersonalityResponse(BaseModel):
|
||||
id: int
|
||||
user_id: int
|
||||
character_type: Optional[str]
|
||||
language_style: Optional[str]
|
||||
interest_tags: Optional[List[str]]
|
||||
interact_tendency: Optional[str]
|
||||
word_count_min: int
|
||||
word_count_max: int
|
||||
personality_desc: Optional[str]
|
||||
updated_at: datetime
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
# ===== 互动记录 =====
|
||||
class InteractionQueryParams(BaseModel):
|
||||
page: int = Field(default=1, ge=1)
|
||||
page_size: int = Field(default=20, ge=1, le=100)
|
||||
user_id: Optional[int] = None
|
||||
interact_type: Optional[str] = None
|
||||
status: Optional[int] = None
|
||||
start_date: Optional[str] = None
|
||||
end_date: Optional[str] = None
|
||||
keyword: Optional[str] = None
|
||||
|
||||
|
||||
class InteractionResponse(BaseModel):
|
||||
id: int
|
||||
user_id: int
|
||||
user_nickname: Optional[str]
|
||||
user_account: Optional[str]
|
||||
article_id: Optional[str]
|
||||
article_title: Optional[str]
|
||||
interact_type: str
|
||||
interact_type_label: str
|
||||
content: Optional[str]
|
||||
token_consumed: int
|
||||
status: int
|
||||
status_label: str
|
||||
error_msg: Optional[str]
|
||||
retry_count: int
|
||||
executed_at: datetime
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
# ===== AI模型配置 =====
|
||||
class AIModelCreateRequest(BaseModel):
|
||||
model_name: str = Field(..., min_length=1, max_length=64)
|
||||
provider: str = Field(..., pattern="^(openai|zhipu|wenxin|qianwen|local)$")
|
||||
api_base_url: Optional[str] = None
|
||||
api_key: Optional[str] = None
|
||||
model_version: Optional[str] = None
|
||||
temperature: float = Field(default=0.7, ge=0.0, le=2.0)
|
||||
max_tokens: int = Field(default=1000, ge=1, le=32000)
|
||||
timeout_seconds: int = Field(default=30, ge=5, le=300)
|
||||
is_default: int = Field(default=0, ge=0, le=1)
|
||||
|
||||
|
||||
class AIModelUpdateRequest(BaseModel):
|
||||
model_name: Optional[str] = None
|
||||
api_base_url: Optional[str] = None
|
||||
api_key: Optional[str] = None
|
||||
model_version: Optional[str] = None
|
||||
temperature: Optional[float] = Field(None, ge=0.0, le=2.0)
|
||||
max_tokens: Optional[int] = Field(None, ge=1, le=32000)
|
||||
timeout_seconds: Optional[int] = Field(None, ge=5, le=300)
|
||||
is_default: Optional[int] = None
|
||||
is_enabled: Optional[int] = None
|
||||
|
||||
|
||||
class AIModelResponse(BaseModel):
|
||||
id: int
|
||||
model_name: str
|
||||
provider: str
|
||||
api_base_url: Optional[str]
|
||||
has_api_key: bool
|
||||
model_version: Optional[str]
|
||||
temperature: float
|
||||
max_tokens: int
|
||||
timeout_seconds: int
|
||||
is_default: int
|
||||
is_enabled: int
|
||||
created_at: datetime
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class AIModelTestRequest(BaseModel):
|
||||
model_id: int
|
||||
test_prompt: str = "你好,请简单介绍一下自己。"
|
||||
|
||||
|
||||
# ===== 系统配置 =====
|
||||
class SystemConfigUpdateRequest(BaseModel):
|
||||
configs: dict
|
||||
|
||||
|
||||
# ===== 数据统计 =====
|
||||
class DashboardResponse(BaseModel):
|
||||
user_stats: dict
|
||||
today_interactions: dict
|
||||
monthly_stats: dict
|
||||
token_stats: dict
|
||||
system_status: dict
|
||||
online_users: int
|
||||
|
||||
|
||||
# ===== 调度配置 =====
|
||||
class SchedulerConfigRequest(BaseModel):
|
||||
interact_time_start: Optional[str] = None
|
||||
interact_time_end: Optional[str] = None
|
||||
interact_interval_min: Optional[int] = None
|
||||
interact_interval_max: Optional[int] = None
|
||||
max_concurrent_users: Optional[int] = None
|
||||
daily_token_limit: Optional[int] = None
|
||||
comment_probability: Optional[float] = None
|
||||
reply_probability: Optional[float] = None
|
||||
like_probability: Optional[float] = None
|
||||
collect_probability: Optional[float] = None
|
||||
forward_probability: Optional[float] = None
|
||||
scheduler_enabled: Optional[bool] = None
|
||||
Reference in New Issue
Block a user