This commit is contained in:
lz_db
2026-10-25 11:46:44 +08:00
parent 893dfed0ed
commit 494f667719
63 changed files with 5213 additions and 239 deletions
+2 -1
View File
@@ -12,11 +12,12 @@ from app.models.incentive import (
)
from app.models.interaction import Comment, Favorite, Like
from app.models.user import MembershipOrder, User, UserMembership, UserWallet
from app.models.user_action_log import UserActionLog
from app.models.video import Category, Tag, TranscodeTask, Video, VideoTag
__all__ = [
"Base",
"User", "UserWallet", "UserMembership", "MembershipOrder",
"User", "UserWallet", "UserMembership", "MembershipOrder", "UserActionLog",
"Video", "Category", "Tag", "VideoTag", "TranscodeTask",
"Comment", "Like", "Favorite",
"WatchRecord", "PointTransaction", "RechargeOrder", "RechargePackage",
Binary file not shown.
+26
View File
@@ -0,0 +1,26 @@
"""用户操作日志:用于排查 bug 时还原用户行为时间线(仅特定账号开启上报)"""
from datetime import datetime
from sqlalchemy import DateTime, Index, String, func
from sqlalchemy.dialects.mysql import BIGINT
from sqlalchemy.orm import Mapped, mapped_column
from app.models.base import Base
class UserActionLog(Base):
__tablename__ = "user_action_logs"
id: Mapped[int] = mapped_column(BIGINT(unsigned=True), primary_key=True, autoincrement=True)
user_id: Mapped[int] = mapped_column(BIGINT(unsigned=True))
action: Mapped[str] = mapped_column(String(50), comment="route_push/player_stopall/api_error/...")
page: Mapped[str] = mapped_column(String(100), default="", comment="路由路径或页面标识")
detail: Mapped[str] = mapped_column(String(1000), default="", comment="行为上下文(JSON 字符串)")
device_info: Mapped[str] = mapped_column(String(200), default="", comment="机型/系统/版本")
app_version: Mapped[str] = mapped_column(String(20), default="", comment="1.3.26+42")
created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now())
__table_args__ = (
Index("idx_user_created", "user_id", "created_at"),
Index("idx_action_created", "action", "created_at"),
)
+26 -2
View File
@@ -1,7 +1,7 @@
"""视频域:videos / categories / tags / video_tags / transcode_tasks"""
from datetime import datetime
from sqlalchemy import BigInteger, DateTime, Index, SmallInteger, String, func
from sqlalchemy import BigInteger, DateTime, Index, SmallInteger, String, Text, func
from sqlalchemy.dialects.mysql import BIGINT, INTEGER
from sqlalchemy.orm import Mapped, mapped_column
@@ -14,6 +14,7 @@ class Video(Base):
id: Mapped[int] = mapped_column(BIGINT(unsigned=True), primary_key=True, autoincrement=True)
user_id: Mapped[int] = mapped_column(BIGINT(unsigned=True), comment="作者")
category_id: Mapped[int] = mapped_column(default=0)
source_id: Mapped[int] = mapped_column(INTEGER(unsigned=True), default=0, comment="内容来源 id")
series_id: Mapped[int | None] = mapped_column(BIGINT(unsigned=True))
episode_no: Mapped[int | None] = mapped_column()
title: Mapped[str] = mapped_column(String(100), default="")
@@ -43,6 +44,7 @@ class Video(Base):
Index("idx_user_status", "user_id", "status"),
Index("idx_feed", "status", "published_at"),
Index("idx_category", "category_id", "status"),
Index("idx_video_source", "source_id", "status"),
)
@@ -104,6 +106,7 @@ class Series(Base):
description: Mapped[str] = mapped_column(String(500), default="")
author_id: Mapped[int | None] = mapped_column(BIGINT(unsigned=True))
category_id: Mapped[int] = mapped_column(default=0)
source_id: Mapped[int] = mapped_column(INTEGER(unsigned=True), default=0, comment="内容来源 id")
total_episodes: Mapped[int] = mapped_column(default=0)
view_count: Mapped[int] = mapped_column(BigInteger, default=0)
status: Mapped[int] = mapped_column(SmallInteger, default=1, comment="1正常 0隐藏")
@@ -113,9 +116,23 @@ class Series(Base):
__table_args__ = (
Index("idx_series_cat_status", "category_id", "status"),
Index("idx_series_status_created", "status", "created_at"),
Index("idx_series_source", "source_id", "status"),
)
class Source(Base):
"""内容来源(片商):麻豆、91 等。视频/系列/采集源都按它区分出处"""
__tablename__ = "sources"
id: Mapped[int] = mapped_column(INTEGER(unsigned=True), primary_key=True, autoincrement=True)
name: Mapped[str] = mapped_column(String(50), unique=True, comment="来源名称,如 麻豆")
code: Mapped[str] = mapped_column(String(50), default="", comment="英文/拼音标识,如 madou")
sort: Mapped[int] = mapped_column(default=0, comment="越小越靠前")
status: Mapped[int] = mapped_column(SmallInteger, default=1, comment="1启用 0停用")
created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now())
class CollectionRecord(Base):
"""采集记录:外部内容源 → 本站系列的映射(幂等导入)"""
@@ -136,14 +153,21 @@ class CollectionRecord(Base):
class CollectionSource(Base):
"""采集源配置:分类名 + 列表URL模板(后台自助添加)"""
"""采集源配置:分类名 + 列表URL模板(后台自助添加)
kind: url(通用 URL 模板,单视频) / aidrama91(91 短剧接口,按系列+集数入库)
config: JSON 字符串,存放接口类采集源所需配置(账号/密码/分类id/每页条数)
"""
__tablename__ = "collection_sources"
id: Mapped[int] = mapped_column(BIGINT(unsigned=True), primary_key=True, autoincrement=True)
name: Mapped[str] = mapped_column(String(50), comment="分类名")
kind: Mapped[str] = mapped_column(String(20), default="url", comment="采集类型 url/aidrama91")
list_url: Mapped[str] = mapped_column(String(500), comment="列表URL模板,{{page}}为页码占位")
config: Mapped[str] = mapped_column(Text, default="", comment="JSON 配置")
category_id: Mapped[int] = mapped_column(INTEGER(unsigned=True), comment="本站分类 id")
source_id: Mapped[int] = mapped_column(INTEGER(unsigned=True), default=0, comment="内容来源 id(采集入库时打标)")
status: Mapped[int] = mapped_column(SmallInteger, default=1, comment="1启用 0停用")
last_sync_at: Mapped[datetime | None] = mapped_column(DateTime)
created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now())