Files
CosScene/server/app/schemas/admin.py
T
2026-05-09 16:40:29 +08:00

609 lines
18 KiB
Python

from datetime import datetime
from pydantic import BaseModel, Field
class AdminLoginRequest(BaseModel):
account: str = Field(min_length=1, max_length=100)
password: str = Field(min_length=1, max_length=200)
class AdminUserOut(BaseModel):
id: int
nickname: str
phone: str | None = None
email: str | None = None
role: str
model_config = {"from_attributes": True}
class AdminLoginResponse(BaseModel):
access_token: str
refresh_token: str
token_type: str = "bearer"
user: AdminUserOut
class AdminSpotListItem(BaseModel):
id: int
title: str
city: str
audit_status: str
reject_reason: str | None = None
creator_id: int
model_config = {"from_attributes": True}
class AdminSpotImageItem(BaseModel):
id: int
image_url: str
is_cover: bool
sort_order: int
model_config = {"from_attributes": True}
class AdminSpotDetailItem(BaseModel):
id: int
title: str
city: str
longitude: float | None = None
latitude: float | None = None
description: str | None = None
transport: str | None = None
best_time: str | None = None
difficulty: str | None = None
is_free: bool
price_min: float | None = None
price_max: float | None = None
audit_status: str
reject_reason: str | None = None
creator_id: int
tag_ids: list[int] = []
image_urls: list[str] = []
images: list[AdminSpotImageItem] = []
model_config = {"from_attributes": True}
class AdminSpotCreateRequest(BaseModel):
title: str = Field(min_length=1, max_length=200)
city: str = Field(min_length=1, max_length=100)
longitude: float
latitude: float
description: str | None = None
transport: str | None = None
best_time: str | None = Field(default=None, max_length=200)
difficulty: str | None = None
is_free: bool = True
price_min: float | None = None
price_max: float | None = None
audit_status: str = Field(default="pending", pattern="^(pending|approved|rejected|deleted)$")
reject_reason: str | None = Field(default=None, max_length=500)
creator_id: int
image_urls: list[str] = []
tag_ids: list[int] = []
class AdminSpotUpdateRequest(BaseModel):
title: str | None = Field(default=None, min_length=1, max_length=200)
city: str | None = Field(default=None, min_length=1, max_length=100)
longitude: float | None = None
latitude: float | None = None
description: str | None = None
transport: str | None = None
best_time: str | None = Field(default=None, max_length=200)
difficulty: str | None = None
is_free: bool | None = None
price_min: float | None = None
price_max: float | None = None
audit_status: str | None = Field(default=None, pattern="^(pending|approved|rejected|deleted)$")
reject_reason: str | None = Field(default=None, max_length=500)
creator_id: int | None = None
image_urls: list[str] | None = None
tag_ids: list[int] | None = None
class AdminSpotAuditRequest(BaseModel):
audit_status: str = Field(pattern="^(pending|approved|rejected|deleted)$")
reject_reason: str | None = Field(default=None, max_length=500)
class AdminBatchAuditRequest(BaseModel):
ids: list[int] = Field(min_length=1)
audit_status: str = Field(pattern="^(pending|approved|rejected|deleted)$")
reject_reason: str | None = Field(default=None, max_length=500)
class AdminDashboardStats(BaseModel):
spots_total: int
spots_pending: int
spots_approved: int
spots_rejected: int
users_total: int
events_total: int
shooting_total: int
class AdminEventListItem(BaseModel):
id: int
title: str
city: str
status: str
audit_status: str
reject_reason: str | None = None
creator_id: int
registration_count: int
max_participants: int
model_config = {"from_attributes": True}
class AdminEventRegistrationItem(BaseModel):
id: int
event_id: int
user_id: int
user_nickname: str
status: str
created_at: datetime | None = None
class AdminEventPhotoItem(BaseModel):
id: int
event_id: int
uploader_id: int
uploader_nickname: str
image_url: str
caption: str | None = None
spot_id: int | None = None
created_at: datetime | None = None
class AdminEventPhotoInput(BaseModel):
uploader_id: int
image_url: str = Field(min_length=1, max_length=500)
caption: str | None = Field(default=None, max_length=200)
spot_id: int | None = None
class AdminEventDetailItem(BaseModel):
id: int
title: str
city: str
description: str | None = None
cover_url: str | None = None
location_name: str | None = None
start_time: datetime | None = None
end_time: datetime | None = None
max_participants: int
spot_id: int | None = None
status: str
audit_status: str
reject_reason: str | None = None
registration_count: int
creator_id: int
registration_user_ids: list[int] = []
photos: list[AdminEventPhotoItem] = []
registrations: list[AdminEventRegistrationItem] = []
model_config = {"from_attributes": True}
class AdminEventCreateRequest(BaseModel):
creator_id: int
title: str = Field(min_length=1, max_length=200)
city: str = Field(min_length=1, max_length=100)
description: str | None = None
cover_url: str | None = Field(default=None, max_length=500)
location_name: str | None = Field(default=None, max_length=200)
start_time: datetime | None = None
end_time: datetime | None = None
max_participants: int = Field(default=0, ge=0)
spot_id: int | None = None
status: str = Field(default="upcoming", pattern="^(upcoming|ongoing|ended|cancelled)$")
audit_status: str = Field(default="pending", pattern="^(pending|approved|rejected|deleted)$")
reject_reason: str | None = Field(default=None, max_length=500)
registration_user_ids: list[int] = []
photos: list[AdminEventPhotoInput] = []
class AdminEventUpdateRequest(BaseModel):
creator_id: int | None = None
title: str | None = Field(default=None, min_length=1, max_length=200)
city: str | None = Field(default=None, min_length=1, max_length=100)
description: str | None = None
cover_url: str | None = Field(default=None, max_length=500)
location_name: str | None = Field(default=None, max_length=200)
start_time: datetime | None = None
end_time: datetime | None = None
max_participants: int | None = Field(default=None, ge=0)
spot_id: int | None = None
status: str | None = Field(default=None, pattern="^(upcoming|ongoing|ended|cancelled)$")
audit_status: str | None = Field(default=None, pattern="^(pending|approved|rejected|deleted)$")
reject_reason: str | None = Field(default=None, max_length=500)
registration_user_ids: list[int] | None = None
photos: list[AdminEventPhotoInput] | None = None
class AdminEventRegistrationCreateRequest(BaseModel):
user_id: int
status: str = Field(default="registered", pattern="^(registered|cancelled)$")
class AdminEventRegistrationUpdateRequest(BaseModel):
status: str = Field(pattern="^(registered|cancelled)$")
class AdminEventPhotoCreateRequest(BaseModel):
uploader_id: int
image_url: str = Field(min_length=1, max_length=500)
caption: str | None = Field(default=None, max_length=200)
spot_id: int | None = None
class AdminEventPhotoUpdateRequest(BaseModel):
uploader_id: int | None = None
image_url: str | None = Field(default=None, min_length=1, max_length=500)
caption: str | None = Field(default=None, max_length=200)
spot_id: int | None = None
class AdminShootingListItem(BaseModel):
id: int
title: str
city: str
status: str
audit_status: str
reject_reason: str | None = None
creator_id: int
role_needed: str
max_applicants: int
is_free: bool
model_config = {"from_attributes": True}
class AdminShootingApplicationItem(BaseModel):
id: int
request_id: int
applicant_id: int
applicant_nickname: str
message: str | None = None
status: str
created_at: datetime | None = None
class AdminShootingDetailItem(BaseModel):
id: int
title: str
city: str
description: str | None = None
style: str | None = None
shoot_date: datetime | None = None
is_free: bool
budget_min: float | None = None
budget_max: float | None = None
role_needed: str
max_applicants: int
contact_info: str | None = None
spot_id: int | None = None
status: str
audit_status: str
reject_reason: str | None = None
creator_id: int
applications: list[AdminShootingApplicationItem] = []
application_user_ids: list[int] = []
model_config = {"from_attributes": True}
class AdminShootingApplicationInput(BaseModel):
applicant_id: int
message: str | None = None
status: str = Field(default="pending", pattern="^(pending|accepted|rejected|cancelled)$")
class AdminShootingCreateRequest(BaseModel):
creator_id: int
title: str = Field(min_length=1, max_length=200)
city: str = Field(min_length=1, max_length=100)
description: str | None = None
style: str | None = Field(default=None, max_length=100)
shoot_date: datetime | None = None
is_free: bool = False
budget_min: float | None = None
budget_max: float | None = None
role_needed: str = Field(default="photographer", pattern="^(photographer|cosplayer|both)$")
max_applicants: int = Field(default=1, ge=1, le=100)
contact_info: str | None = Field(default=None, max_length=200)
spot_id: int | None = None
status: str = Field(default="open", pattern="^(open|matched|closed|cancelled)$")
audit_status: str = Field(default="pending", pattern="^(pending|approved|rejected|deleted)$")
reject_reason: str | None = Field(default=None, max_length=500)
applications: list[AdminShootingApplicationInput] = []
class AdminShootingUpdateRequest(BaseModel):
creator_id: int | None = None
title: str | None = Field(default=None, min_length=1, max_length=200)
city: str | None = Field(default=None, min_length=1, max_length=100)
description: str | None = None
style: str | None = Field(default=None, max_length=100)
shoot_date: datetime | None = None
is_free: bool | None = None
budget_min: float | None = None
budget_max: float | None = None
role_needed: str | None = Field(default=None, pattern="^(photographer|cosplayer|both)$")
max_applicants: int | None = Field(default=None, ge=1, le=100)
contact_info: str | None = Field(default=None, max_length=200)
spot_id: int | None = None
status: str | None = Field(default=None, pattern="^(open|matched|closed|cancelled)$")
audit_status: str | None = Field(default=None, pattern="^(pending|approved|rejected|deleted)$")
reject_reason: str | None = Field(default=None, max_length=500)
applications: list[AdminShootingApplicationInput] | None = None
class AdminShootingApplicationCreateRequest(BaseModel):
applicant_id: int
message: str | None = None
status: str = Field(default="pending", pattern="^(pending|accepted|rejected|cancelled)$")
class AdminShootingApplicationUpdateRequest(BaseModel):
message: str | None = None
status: str = Field(pattern="^(pending|accepted|rejected|cancelled)$")
class AdminAuditRequest(BaseModel):
audit_status: str = Field(pattern="^(pending|approved|rejected|deleted)$")
reject_reason: str | None = Field(default=None, max_length=500)
class AdminModuleCrudCoverage(BaseModel):
create: bool
read: bool
update: bool
delete: bool
class AdminModuleDesignItem(BaseModel):
module_key: str
module_name: str
models: list[str]
api_endpoint_prefixes: list[str]
coverage: AdminModuleCrudCoverage
status: str
notes: str
class AdminModuleDesignResponse(BaseModel):
total_modules: int
full_covered: int
partial_covered: int
missing_covered: int
items: list[AdminModuleDesignItem]
class AdminUserListItem(BaseModel):
id: int
nickname: str
phone: str | None = None
email: str | None = None
city: str | None = None
identity: str | None = None
role: str
is_active: bool
model_config = {"from_attributes": True}
class AdminUserCreateRequest(BaseModel):
nickname: str = Field(min_length=1, max_length=50)
password: str = Field(min_length=6, max_length=200)
phone: str | None = Field(default=None, max_length=20)
email: str | None = Field(default=None, max_length=255)
city: str | None = Field(default=None, max_length=100)
identity: str = Field(default="both", pattern="^(photographer|cosplayer|both)$")
role: str = Field(default="user", pattern="^(user|moderator|admin)$")
is_active: bool = True
class AdminUserUpdateRequest(BaseModel):
nickname: str | None = Field(default=None, min_length=1, max_length=50)
phone: str | None = Field(default=None, max_length=20)
email: str | None = Field(default=None, max_length=255)
city: str | None = Field(default=None, max_length=100)
identity: str | None = Field(default=None, pattern="^(photographer|cosplayer|both)$")
role: str | None = Field(default=None, pattern="^(user|moderator|admin)$")
is_active: bool | None = None
password: str | None = Field(default=None, min_length=6, max_length=200)
class AdminMembershipPlanItem(BaseModel):
id: int
name: str
description: str | None = None
duration_days: int
price: float
benefits: str | None = None
extra_uploads: int
extra_top_count: int
is_active: bool
sort_order: int
model_config = {"from_attributes": True}
class AdminMembershipPlanCreateRequest(BaseModel):
name: str = Field(min_length=1, max_length=100)
description: str | None = None
duration_days: int = Field(ge=1, le=3650)
price: float = Field(ge=0)
benefits: str | None = None
extra_uploads: int = Field(default=0, ge=0)
extra_top_count: int = Field(default=0, ge=0)
is_active: bool = True
sort_order: int = 0
class AdminMembershipPlanUpdateRequest(BaseModel):
name: str | None = Field(default=None, min_length=1, max_length=100)
description: str | None = None
duration_days: int | None = Field(default=None, ge=1, le=3650)
price: float | None = Field(default=None, ge=0)
benefits: str | None = None
extra_uploads: int | None = Field(default=None, ge=0)
extra_top_count: int | None = Field(default=None, ge=0)
is_active: bool | None = None
sort_order: int | None = None
class AdminUserMembershipItem(BaseModel):
id: int
user_id: int
user_nickname: str
plan_id: int
plan_name: str
start_date: datetime
end_date: datetime
is_active: bool
class AdminUserMembershipCreateRequest(BaseModel):
user_id: int
plan_id: int
start_date: datetime
end_date: datetime
is_active: bool = True
class AdminUserMembershipUpdateRequest(BaseModel):
plan_id: int | None = None
start_date: datetime | None = None
end_date: datetime | None = None
is_active: bool | None = None
class AdminPointLedgerItem(BaseModel):
id: int
user_id: int
user_nickname: str
change: int
balance: int
reason: str
ref_type: str | None = None
ref_id: int | None = None
rolled_back: bool = False
created_at: datetime
class AdminPointAdjustRequest(BaseModel):
user_id: int
change: int = Field(ne=0)
reason: str = Field(min_length=1, max_length=200)
ref_type: str | None = Field(default=None, max_length=50)
ref_id: int | None = None
class AdminNotificationItem(BaseModel):
id: int
user_id: int
user_nickname: str
type: str
title: str
content: str | None = None
ref_type: str | None = None
ref_id: int | None = None
is_read: bool
created_at: datetime
class AdminNotificationCreateRequest(BaseModel):
user_id: int
type: str = Field(min_length=1, max_length=50)
title: str = Field(min_length=1, max_length=200)
content: str | None = None
ref_type: str | None = Field(default=None, max_length=50)
ref_id: int | None = None
class AdminNotificationUpdateRequest(BaseModel):
title: str | None = Field(default=None, min_length=1, max_length=200)
content: str | None = None
is_read: bool | None = None
class AdminAuditLogItem(BaseModel):
id: int
operator_id: int
operator_nickname: str
action: str
target_type: str
target_id: int | None = None
detail: str | None = None
created_at: datetime
class AdminAuditLogCreateRequest(BaseModel):
action: str = Field(min_length=1, max_length=100)
target_type: str = Field(min_length=1, max_length=50)
target_id: int | None = None
detail: str | None = None
class AdminReportItem(BaseModel):
id: int
reporter_id: int
reporter_nickname: str
target_type: str
target_id: int
reason: str
status: str
handler_id: int | None = None
handler_nickname: str | None = None
conclusion: str | None = None
created_at: datetime
resolved_at: datetime | None = None
class AdminReportUpdateRequest(BaseModel):
status: str | None = Field(default=None, pattern="^(pending|processing|resolved|rejected)$")
handler_id: int | None = None
conclusion: str | None = None
class AdminSystemConfigItem(BaseModel):
id: int
config_key: str
category: str
title: str
config_json: str
description: str | None = None
is_active: bool
sort_order: int
updated_by: int | None = None
updated_at: datetime | None = None
model_config = {"from_attributes": True}
class AdminSystemConfigCreateRequest(BaseModel):
config_key: str = Field(min_length=1, max_length=100)
category: str = Field(min_length=1, max_length=50)
title: str = Field(min_length=1, max_length=200)
config_json: str = Field(min_length=2)
description: str | None = None
is_active: bool = True
sort_order: int = 0
class AdminSystemConfigUpdateRequest(BaseModel):
category: str | None = Field(default=None, min_length=1, max_length=50)
title: str | None = Field(default=None, min_length=1, max_length=200)
config_json: str | None = Field(default=None, min_length=2)
description: str | None = None
is_active: bool | None = None
sort_order: int | None = None