144 lines
4.7 KiB
Python
144 lines
4.7 KiB
Python
|
|
from django.db import models
|
|||
|
|
|
|||
|
|
|
|||
|
|
class Memory(models.Model):
|
|||
|
|
"""恋爱故事页,驱动前端尼泊尔本版式。"""
|
|||
|
|
|
|||
|
|
class FeatureType(models.TextChoices):
|
|||
|
|
HEART_WINDOW = "heart_window", "心窗页"
|
|||
|
|
FISSURE_PAGE = "fissure_page", "裂缝对开页"
|
|||
|
|
STANDARD_NEPAL = "standard_nepal", "标准尼泊尔页"
|
|||
|
|
|
|||
|
|
class NepalArtStyle(models.TextChoices):
|
|||
|
|
"""每页可选不同尼泊尔视觉皮肤(备用可继续加枚举)。"""
|
|||
|
|
NONE = "none", "默认米黄"
|
|||
|
|
MANDALA_PINK = "mandala_pink", "粉曼陀罗"
|
|||
|
|
MANDALA_BLUE = "mandala_blue", "蓝曼陀罗"
|
|||
|
|
SPIRAL_ROSE = "spiral_rose", "玫瑰螺旋"
|
|||
|
|
SPIRAL_CYAN = "spiral_cyan", "青色螺旋"
|
|||
|
|
DAWN_MEET = "dawn_meet", "晨光·遇见"
|
|||
|
|
BLUSH_ARGUE = "blush_argue", "粉雾·争执"
|
|||
|
|
MINT_RECONCILE = "mint_reconcile", "薄荷·和好"
|
|||
|
|
SAFFRON_HOME = "saffron_home", "姜黄·小家"
|
|||
|
|
INDIGO_IKEA = "indigo_ikea", "靛蓝·漫游"
|
|||
|
|
LOTUS_PETAL = "lotus_petal", "莲花瓣"
|
|||
|
|
LOKTA_GOLD = "lokta_gold", "金边手工纸"
|
|||
|
|
OCEAN_PRAYER = "ocean_prayer", "海洋祈愿"
|
|||
|
|
DESERT_ROSE = "desert_rose", "沙漠玫瑰"
|
|||
|
|
NIGHT_STAR = "night_star", "夜空星屑"
|
|||
|
|
TERRA_TORN = "terra_torn", "赭石撕边"
|
|||
|
|
|
|||
|
|
story_order = models.PositiveIntegerField(
|
|||
|
|
default=0,
|
|||
|
|
db_index=True,
|
|||
|
|
help_text="叙事顺序,数字越小越靠前。",
|
|||
|
|
)
|
|||
|
|
date = models.DateField()
|
|||
|
|
event_title = models.CharField(max_length=200)
|
|||
|
|
main_text = models.TextField(
|
|||
|
|
blank=True,
|
|||
|
|
help_text="支持 Markdown。",
|
|||
|
|
)
|
|||
|
|
unique_feature_type = models.CharField(
|
|||
|
|
max_length=32,
|
|||
|
|
choices=FeatureType.choices,
|
|||
|
|
default=FeatureType.STANDARD_NEPAL,
|
|||
|
|
)
|
|||
|
|
nepal_art_style = models.CharField(
|
|||
|
|
max_length=48,
|
|||
|
|
choices=NepalArtStyle.choices,
|
|||
|
|
default=NepalArtStyle.NONE,
|
|||
|
|
blank=True,
|
|||
|
|
help_text="标准页背景/纹理;心窗与裂缝页也可作辅色参考。",
|
|||
|
|
)
|
|||
|
|
image = models.ImageField(upload_to="memories/", blank=True, null=True)
|
|||
|
|
is_finale = models.BooleanField(
|
|||
|
|
default=False,
|
|||
|
|
help_text="终章:在解锁时间前仅可预览占位,到点后需手动打开。",
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
class Meta:
|
|||
|
|
ordering = ["story_order", "id"]
|
|||
|
|
|
|||
|
|
def __str__(self) -> str:
|
|||
|
|
return f"{self.story_order}. {self.event_title}"
|
|||
|
|
|
|||
|
|
def save(self, *args, **kwargs):
|
|||
|
|
super().save(*args, **kwargs)
|
|||
|
|
if self.is_finale:
|
|||
|
|
Memory.objects.exclude(pk=self.pk).update(is_finale=False)
|
|||
|
|
|
|||
|
|
|
|||
|
|
class MemoryPhoto(models.Model):
|
|||
|
|
"""同一回忆页可附加多张照片;与主图 `Memory.image` 一并展示,主图在前。"""
|
|||
|
|
|
|||
|
|
memory = models.ForeignKey(
|
|||
|
|
Memory,
|
|||
|
|
on_delete=models.CASCADE,
|
|||
|
|
related_name="photos",
|
|||
|
|
help_text="所属故事页",
|
|||
|
|
)
|
|||
|
|
image = models.ImageField(upload_to="memory_photos/")
|
|||
|
|
sort_order = models.PositiveSmallIntegerField(
|
|||
|
|
default=0,
|
|||
|
|
help_text="数字越小越靠前(排在主图之后)。",
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
class Meta:
|
|||
|
|
ordering = ["sort_order", "id"]
|
|||
|
|
verbose_name = "附加照片"
|
|||
|
|
verbose_name_plural = "附加照片"
|
|||
|
|
|
|||
|
|
def __str__(self) -> str:
|
|||
|
|
return f"{self.memory_id}·{self.sort_order}"
|
|||
|
|
|
|||
|
|
|
|||
|
|
class Guestbook(models.Model):
|
|||
|
|
nickname = models.CharField(max_length=80)
|
|||
|
|
message = models.TextField()
|
|||
|
|
created_at = models.DateTimeField(auto_now_add=True)
|
|||
|
|
|
|||
|
|
class Meta:
|
|||
|
|
ordering = ["-created_at"]
|
|||
|
|
verbose_name_plural = "Guestbook entries"
|
|||
|
|
|
|||
|
|
def __str__(self) -> str:
|
|||
|
|
return f"{self.nickname}: {self.message[:40]}"
|
|||
|
|
|
|||
|
|
|
|||
|
|
class Config(models.Model):
|
|||
|
|
"""Singleton-style global配置(Admin 中 id=1)。"""
|
|||
|
|
|
|||
|
|
unlock_at = models.DateTimeField(
|
|||
|
|
blank=True,
|
|||
|
|
null=True,
|
|||
|
|
help_text="已弃用:前端不再按此锁定章节,可留空。",
|
|||
|
|
)
|
|||
|
|
together_since = models.DateTimeField(
|
|||
|
|
blank=True,
|
|||
|
|
null=True,
|
|||
|
|
help_text="用于首页「我们在一起多少天多少秒」的起点(建议为正式在一起的时刻,含时区)。",
|
|||
|
|
)
|
|||
|
|
bgm_enabled = models.BooleanField(
|
|||
|
|
default=True,
|
|||
|
|
help_text="是否展示顶部音乐区(播放器地址在前端环境变量 VITE_NETEASE_PLAYER_SRC 配置)。",
|
|||
|
|
)
|
|||
|
|
site_title = models.CharField(
|
|||
|
|
max_length=120,
|
|||
|
|
default="Nepal Journey: Our Story",
|
|||
|
|
blank=True,
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
class Meta:
|
|||
|
|
verbose_name_plural = "Config"
|
|||
|
|
|
|||
|
|
def __str__(self) -> str:
|
|||
|
|
return "Site configuration"
|
|||
|
|
|
|||
|
|
def save(self, *args, **kwargs):
|
|||
|
|
self.pk = 1
|
|||
|
|
super().save(*args, **kwargs)
|
|||
|
|
|
|||
|
|
def delete(self, *args, **kwargs):
|
|||
|
|
pass
|