订单需管理员审核后才开通节点,并更新登录页文案。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-10-10 23:04:24 +08:00
parent 8b55b9cf55
commit f329f647c7
22 changed files with 583 additions and 81 deletions
+33
View File
@@ -103,6 +103,12 @@ class UserRole(str, enum.Enum):
ADMIN = "admin"
class OrderStatus(str, enum.Enum):
PENDING = "pending"
APPROVED = "approved"
REJECTED = "rejected"
class User(Base):
"""用户。一个钱包地址对应一名用户,可绑定多台算力节点。"""
@@ -118,6 +124,7 @@ class User(Base):
nodes: Mapped[list[ComputeNode]] = relationship(back_populates="user")
yields: Mapped[list[NodeYield]] = relationship(back_populates="user")
withdrawals: Mapped[list[WithdrawalLog]] = relationship(back_populates="user")
orders: Mapped[list[LicenseOrder]] = relationship(back_populates="user")
class ComputeNode(Base):
@@ -140,10 +147,12 @@ class ComputeNode(Base):
status: Mapped[NodeStatus] = mapped_column(_enum(NodeStatus), default=NodeStatus.OFFLINE, index=True)
last_heartbeat_at: Mapped[datetime | None] = mapped_column(UtcDateTime)
callback_url: Mapped[str | None] = mapped_column(String(512), comment="可选的任务推送地址")
node_token: Mapped[str | None] = mapped_column(String(128), unique=True, comment="挂机客户端凭证,审核通过后生成")
created_at: Mapped[datetime] = mapped_column(UtcDateTime, default=utcnow)
updated_at: Mapped[datetime] = mapped_column(UtcDateTime, default=utcnow, onupdate=utcnow)
user: Mapped[User] = relationship(back_populates="nodes")
order: Mapped[LicenseOrder | None] = relationship(back_populates="node")
yields: Mapped[list[NodeYield]] = relationship(back_populates="node")
tasks: Mapped[list[ComputeTask]] = relationship(back_populates="node")
uptime_intervals: Mapped[list[UptimeInterval]] = relationship(back_populates="node")
@@ -249,6 +258,30 @@ class WithdrawalLog(Base):
user: Mapped[User] = relationship(back_populates="withdrawals")
class LicenseOrder(Base):
"""节点授权订单。管理员通过后才创建节点并签发挂机 Token。"""
__tablename__ = "license_orders"
__table_args__ = (
CheckConstraint("amount > 0", name="ck_order_amount_positive"),
Index("ix_order_user_status", "user_id", "status"),
)
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), index=True)
amount: Mapped[Decimal] = mapped_column(MONEY, comment="购买金额,例如 1500 USDT")
asset_symbol: Mapped[str] = mapped_column(String(32), default="USDT")
status: Mapped[OrderStatus] = mapped_column(_enum(OrderStatus), default=OrderStatus.PENDING, index=True)
tx_id: Mapped[str] = mapped_column(String(128), unique=True, comment="用户提交的链上交易哈希")
node_id: Mapped[int | None] = mapped_column(ForeignKey("compute_nodes.id"), unique=True)
note: Mapped[str | None] = mapped_column(Text)
created_at: Mapped[datetime] = mapped_column(UtcDateTime, default=utcnow)
reviewed_at: Mapped[datetime | None] = mapped_column(UtcDateTime)
user: Mapped[User] = relationship(back_populates="orders")
node: Mapped[ComputeNode | None] = relationship(back_populates="order")
class AppSetting(Base):
"""进程重启后仍要保留的运行时密钥,例如未写入环境变量的 JWT 密钥。"""