feat(monitor): 作品标签 —— 词表在设置里维护,作品上贴
Deploy VitePress site to Pages / build (push) Canceled after 0s
Deploy VitePress site to Pages / Deploy (push) Canceled after 0s

和「作品备注」刻意并存,不是一回事:备注是一句话的自由文字,标签是**从一份固定
词表里选的分类**。分类必须封闭,否则「重点 / 重要 / 优先」各写各的,筛就没法用了。

* `monitor_tag`:词表,全局一套(不按平台分)—— 「重点」是给人自己用的心智,不该在
  小红书和抖音各定义一遍。颜色存的是**调色板里的名字**,不是色值:Tailwind 的类名是
  静态提取的,拼出来的 `text-${color}` 它看不见,线上会静默变无色。
* `monitor_note_tag`:作品↔标签,**多对多**。一条作品可以既是重点又是竞品;只能贴一个
  的话人就会跑去备注里写自由文字,这份词表就白建了。全部替换式提交,不是逐个增删。
* 删除标签时**显式删关联**,不靠外键级联 —— 测试跑 SQLite,它默认不开外键约束。
* 组头上的筛选做成平铺开关片,多选是「或」。

顺带:/monitor/notes 现在支持按 tag_id 筛。
This commit is contained in:
2026-10-11 09:16:17 +08:00
parent 5c7577cab0
commit b9aa590814
15 changed files with 1147 additions and 10 deletions
+13
View File
@@ -120,6 +120,19 @@ class NoteAliasPayload(BaseModel):
alias: str = Field(default="", max_length=128)
class TagPayload(BaseModel):
"""新建/改名一个标签。`color` 是调色板里的名字,不认识的会被回落到默认色。"""
name: str = Field(min_length=1, max_length=32)
color: str = Field(default="", max_length=16)
class NoteTagsPayload(BaseModel):
"""把一条作品的标签整体替换成这一组。空列表 = 全摘掉。"""
tag_ids: List[int] = Field(default_factory=list)
class WebhookPayload(BaseModel):
url: str = Field(default="", description="企业微信机器人 Webhook 地址,留空表示停用")