feat: 新增客片案例与团队共创模块,重构玩法与配置

- 新增客片案例全流程功能,包含前台页面、管理端配置、后端API、数据库迁移与文档
- 新增团队共创详情页面与对应接口
- 重构玩法模块:将静态playData替换为动态API获取,拆分类型定义到playTypes.ts
- 优化vite构建配置与环境变量处理,调整详情页操作栏文案
- 更新全量相关文档与配图,新增客片案例、团队共创API文档
- 新增测试用例,完善数据归一化逻辑
- 调整路由配置与环境变量示例文件
This commit is contained in:
duanshuwen committed 2026-08-19 20:23:04 +08:00
1 parent cda8069630
commit 7ba92f3c5d
76 files changed
+7970 -137

No files matched your search

+122 -1
View File
@@ -1,6 +1,6 @@
from datetime import datetime, timezone
from uuid import uuid4
from sqlalchemy import Boolean, DateTime, ForeignKey, Integer, String, Text
from sqlalchemy import Boolean, DateTime, ForeignKey, Integer, String, Text, UniqueConstraint
from sqlalchemy.dialects.postgresql import ARRAY, JSONB
from sqlalchemy.orm import Mapped, mapped_column, relationship
from .database import Base
@@ -85,6 +85,127 @@ class VehicleOption(Base):
updatedAt: Mapped[datetime] = mapped_column(DateTime, default=utc_now, onupdate=utc_now, nullable=False)
class HomeExperience(Base):
__tablename__ = "HomeExperience"
id: Mapped[str] = mapped_column(String, primary_key=True, default=new_id)
badge: Mapped[str] = mapped_column(String, nullable=False)
category: Mapped[str] = mapped_column(String, nullable=False)
title: Mapped[str] = mapped_column(String, nullable=False)
englishTitle: Mapped[str] = mapped_column(String, nullable=False)
image: Mapped[str] = mapped_column(String, nullable=False)
demandKeyword: Mapped[str] = mapped_column(String, nullable=False)
isActive: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False, index=True)
sortOrder: Mapped[int] = mapped_column(Integer, default=0, nullable=False, index=True)
createdAt: Mapped[datetime] = mapped_column(DateTime, default=utc_now, nullable=False)
updatedAt: Mapped[datetime] = mapped_column(DateTime, default=utc_now, onupdate=utc_now, nullable=False)
class HomeTeamBuilding(Base):
__tablename__ = "HomeTeamBuilding"
id: Mapped[str] = mapped_column(String, primary_key=True, default=new_id)
tag: Mapped[str] = mapped_column(String, nullable=False)
title: Mapped[str] = mapped_column(String, nullable=False)
description: Mapped[str] = mapped_column(Text, nullable=False)
image: Mapped[str] = mapped_column(String, nullable=False)
demandKeyword: Mapped[str] = mapped_column(String, nullable=False)
detailSubtitle: Mapped[str] = mapped_column(String, default="", nullable=False)
detailParagraphs: Mapped[list[str]] = mapped_column(JSONB, default=list, nullable=False)
isActive: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False, index=True)
sortOrder: Mapped[int] = mapped_column(Integer, default=0, nullable=False, index=True)
createdAt: Mapped[datetime] = mapped_column(DateTime, default=utc_now, nullable=False)
updatedAt: Mapped[datetime] = mapped_column(DateTime, default=utc_now, onupdate=utc_now, nullable=False)
class HomeWildArchive(Base):
__tablename__ = "HomeWildArchive"
id: Mapped[str] = mapped_column(String, primary_key=True, default=new_id)
title: Mapped[str] = mapped_column(String, nullable=False)
image: Mapped[str] = mapped_column(String, nullable=False)
images: Mapped[list[str]] = mapped_column(JSONB, default=list, nullable=False)
demandKeyword: Mapped[str] = mapped_column(String, nullable=False)
isActive: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False, index=True)
sortOrder: Mapped[int] = mapped_column(Integer, default=0, nullable=False, index=True)
createdAt: Mapped[datetime] = mapped_column(DateTime, default=utc_now, nullable=False)
updatedAt: Mapped[datetime] = mapped_column(DateTime, default=utc_now, onupdate=utc_now, nullable=False)
class HomeWanfaRecommendation(Base):
__tablename__ = "HomeWanfaRecommendation"
__table_args__ = (
UniqueConstraint("categoryId", name="uq_HomeWanfaRecommendation_categoryId"),
)
id: Mapped[str] = mapped_column(String, primary_key=True, default=new_id)
categoryId: Mapped[str] = mapped_column(
String,
ForeignKey("WanfaCategory.id", ondelete="RESTRICT"),
nullable=False,
index=True,
)
isActive: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False, index=True)
sortOrder: Mapped[int] = mapped_column(Integer, default=0, nullable=False, index=True)
createdAt: Mapped[datetime] = mapped_column(DateTime, default=utc_now, nullable=False)
updatedAt: Mapped[datetime] = mapped_column(DateTime, default=utc_now, onupdate=utc_now, nullable=False)
category: Mapped["WanfaCategory"] = relationship(back_populates="recommendations")
class WanfaCategory(Base):
__tablename__ = "WanfaCategory"
id: Mapped[str] = mapped_column(String, primary_key=True, default=new_id)
label: Mapped[str] = mapped_column(String, nullable=False)
sortOrder: Mapped[int] = mapped_column(Integer, default=0, nullable=False, index=True)
createdAt: Mapped[datetime] = mapped_column(DateTime, default=utc_now, nullable=False)
updatedAt: Mapped[datetime] = mapped_column(DateTime, default=utc_now, onupdate=utc_now, nullable=False)
routes: Mapped[list["WanfaRoute"]] = relationship(
back_populates="category",
order_by="WanfaRoute.sortOrder.asc()",
)
recommendations: Mapped[list[HomeWanfaRecommendation]] = relationship(back_populates="category")
class WanfaRoute(Base):
__tablename__ = "WanfaRoute"
id: Mapped[str] = mapped_column(String, primary_key=True, default=new_id)
categoryId: Mapped[str] = mapped_column(
String,
ForeignKey("WanfaCategory.id", ondelete="RESTRICT"),
nullable=False,
index=True,
)
title: Mapped[str] = mapped_column(String, nullable=False)
subtitle: Mapped[str] = mapped_column(Text, nullable=False)
image: Mapped[str] = mapped_column(String, nullable=False)
routeCount: Mapped[int] = mapped_column(Integer, nullable=False)
demandKeyword: Mapped[str] = mapped_column(String, nullable=False)
sortOrder: Mapped[int] = mapped_column(Integer, default=0, nullable=False, index=True)
createdAt: Mapped[datetime] = mapped_column(DateTime, default=utc_now, nullable=False)
updatedAt: Mapped[datetime] = mapped_column(DateTime, default=utc_now, onupdate=utc_now, nullable=False)
category: Mapped[WanfaCategory] = relationship(back_populates="routes")
class ConciergeAdvisor(Base):
__tablename__ = "ConciergeAdvisor"
id: Mapped[str] = mapped_column(String, primary_key=True, default=new_id)
avatar: Mapped[str] = mapped_column(String, nullable=False)
name: Mapped[str] = mapped_column(String, nullable=False)
role: Mapped[str] = mapped_column(String, nullable=False)
details: Mapped[list[dict[str, str]]] = mapped_column(JSONB, default=list, nullable=False)
qrImage: Mapped[str] = mapped_column(String, nullable=False)
isActive: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False, index=True)
sortOrder: Mapped[int] = mapped_column(Integer, default=0, nullable=False, index=True)
createdAt: Mapped[datetime] = mapped_column(DateTime, default=utc_now, nullable=False)
updatedAt: Mapped[datetime] = mapped_column(DateTime, default=utc_now, onupdate=utc_now, nullable=False)
class DemandHero(Base):
__tablename__ = "DemandHero"