77 lines
3.7 KiB
Python
77 lines
3.7 KiB
Python
from __future__ import annotations
|
||
|
||
from datetime import datetime
|
||
|
||
from sqlalchemy import BigInteger, DateTime, Float, ForeignKey, Index, String, Text, UniqueConstraint
|
||
from sqlalchemy.orm import Mapped, mapped_column
|
||
|
||
from app.models.base import Base, SoftDeleteMixin, TimestampMixin
|
||
|
||
|
||
class UploadResource(Base, TimestampMixin, SoftDeleteMixin):
|
||
"""统一上传资源账本。
|
||
|
||
记录用户直接上传、模块上传和拆镜切片文件,不建立 ORM relationship,
|
||
通过 source_model + source_id 进行低耦合绑定。
|
||
"""
|
||
|
||
__tablename__ = "upload_resources"
|
||
__table_args__ = (
|
||
UniqueConstraint("storage_path", name="uq_upload_resources_storage_path"),
|
||
Index("ix_upload_resources_user_module_type", "user_id", "module", "resource_type", "deleted_at"),
|
||
Index("ix_upload_resources_user_bind", "user_id", "bind_status", "deleted_at"),
|
||
Index("ix_upload_resources_history_lookup", "user_id", "resource_type", "bind_status", "delete_policy", "deleted_at", "created_at"),
|
||
Index("ix_upload_resources_source", "source_model", "source_id", "deleted_at"),
|
||
Index("ix_upload_resources_url", "resource_url"),
|
||
Index("ix_upload_resources_created", "created_at"),
|
||
Index("ix_upload_resources_file_delete_status", "file_delete_status"),
|
||
Index("ix_upload_resources_physical_deleted", "physical_deleted_at"),
|
||
)
|
||
|
||
id: Mapped[str] = mapped_column(String(32), primary_key=True)
|
||
user_id: Mapped[str] = mapped_column(
|
||
String(32), ForeignKey("users.id", ondelete="CASCADE"), index=True, nullable=False
|
||
)
|
||
|
||
module: Mapped[str] = mapped_column(String(64), index=True, nullable=False)
|
||
resource_type: Mapped[str] = mapped_column(String(32), index=True, nullable=False)
|
||
|
||
resource_url: Mapped[str] = mapped_column(Text, nullable=False)
|
||
storage_path: Mapped[str] = mapped_column(Text, nullable=False)
|
||
file_name: Mapped[str | None] = mapped_column(String(255), nullable=True)
|
||
file_ext: Mapped[str | None] = mapped_column(String(32), nullable=True)
|
||
mime_type: Mapped[str | None] = mapped_column(String(128), nullable=True)
|
||
file_size_bytes: Mapped[int] = mapped_column(BigInteger, default=0, server_default="0", nullable=False)
|
||
|
||
duration_seconds: Mapped[float | None] = mapped_column(Float, nullable=True)
|
||
duration_source: Mapped[str | None] = mapped_column(String(32), nullable=True)
|
||
width: Mapped[int | None] = mapped_column(BigInteger, nullable=True)
|
||
height: Mapped[int | None] = mapped_column(BigInteger, nullable=True)
|
||
|
||
source_model: Mapped[str | None] = mapped_column(String(64), index=True, nullable=True)
|
||
source_id: Mapped[str | None] = mapped_column(String(32), index=True, nullable=True)
|
||
source_module: Mapped[str | None] = mapped_column(String(64), nullable=True)
|
||
|
||
bind_status: Mapped[str] = mapped_column(String(32), default="pending", server_default="pending", index=True, nullable=False)
|
||
delete_policy: Mapped[str] = mapped_column(String(32), default="user_deletable", server_default="user_deletable", index=True, nullable=False)
|
||
created_by: Mapped[str] = mapped_column(String(32), default="api", server_default="api", index=True, nullable=False)
|
||
|
||
metadata_json: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||
capacity_released_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True, index=True)
|
||
|
||
physical_deleted_at: Mapped[datetime | None] = mapped_column(
|
||
DateTime(timezone=True),
|
||
nullable=True,
|
||
)
|
||
|
||
file_delete_status: Mapped[str] = mapped_column(
|
||
String(32),
|
||
default="active",
|
||
server_default="active",
|
||
nullable=False,
|
||
)
|
||
|
||
file_delete_error: Mapped[str | None] = mapped_column(
|
||
Text,
|
||
nullable=True,
|
||
) |