diff --git a/dict/tags.json b/dict/tags.json index 350f719..9ca71a7 100644 --- a/dict/tags.json +++ b/dict/tags.json @@ -2,18 +2,59 @@ "version": 4, "description": "标签词典 v4 — 全量 keymap + stopwords(人物规则已融入 keymap)", "metadata": { - "style": { "label": "风格", "color_bg": "#f0f9ff", "color_fg": "#0284c7" }, - "outfit": { "label": "服装", "color_bg": "#fdf2f8", "color_fg": "#db2777" }, - "scene": { "label": "场景", "color_bg": "#f0fdf4", "color_fg": "#15803d" }, - "body": { "label": "身体", "color_bg": "#fef3c7", "color_fg": "#b45309" }, - "mood": { "label": "情绪", "color_bg": "#faf5ff", "color_fg": "#7c3aed" }, - "topic": { "label": "主题", "color_bg": "#f0f9ff", "color_fg": "#0369a1" }, - "position": { "label": "姿势", "color_bg": "#fefce8", "color_fg": "#a16207" }, - "location": { "label": "地点", "color_bg": "#f0fdfa", "color_fg": "#0f766e" }, - "brand": { "label": "品牌/工作室", "color_bg": "#fff7ed", "color_fg": "#c2410c" }, - "person": { "label": "人物", "color_bg": "#ecfdf5", "color_fg": "#059669" } + "style": { + "label": "风格", + "color_bg": "#f0f9ff", + "color_fg": "#0284c7" + }, + "outfit": { + "label": "服装", + "color_bg": "#fdf2f8", + "color_fg": "#db2777" + }, + "scene": { + "label": "场景", + "color_bg": "#f0fdf4", + "color_fg": "#15803d" + }, + "body": { + "label": "身体", + "color_bg": "#fef3c7", + "color_fg": "#b45309" + }, + "mood": { + "label": "情绪", + "color_bg": "#faf5ff", + "color_fg": "#7c3aed" + }, + "topic": { + "label": "主题", + "color_bg": "#f0f9ff", + "color_fg": "#0369a1" + }, + "position": { + "label": "姿势", + "color_bg": "#fefce8", + "color_fg": "#a16207" + }, + "location": { + "label": "地点", + "color_bg": "#f0fdfa", + "color_fg": "#0f766e" + }, + "brand": { + "label": "品牌/工作室", + "color_bg": "#fff7ed", + "color_fg": "#c2410c" + }, + "person": { + "label": "人物", + "color_bg": "#ecfdf5", + "color_fg": "#059669" + } }, "keymap": { + "嫩模": "topic", "108TV": "brand", "108酱": "brand", "Adidas": "brand", @@ -294,23 +335,13 @@ "waist": "body", "skin": "body", "tattoo": "body", - "清纯": "mood", "诱惑": "mood", "唯美": "mood", - "清新": "mood", - "冷艳": "mood", - "妩媚": "mood", "娇羞": "mood", - "俏皮": "mood", - "温柔": "mood", - "野性": "mood", "冷傲": "mood", "热情": "mood", "慵懒": "mood", "迷离": "mood", - "甜美": "mood", - "知性": "mood", - "可爱": "mood", "神秘": "mood", "忧郁": "mood", "伤感": "mood", @@ -327,15 +358,9 @@ "天真": "mood", "无辜": "mood", "纯真": "mood", - "pure": "mood", - "sweet": "mood", - "fresh": "mood", - "elegant": "mood", - "cute": "mood", - "wild": "mood", "lazy": "mood", - "sweet": "mood", "写真": "topic", + "cos": "topic", "私房": "topic", "街拍": "topic", "旅拍": "topic", @@ -537,25 +562,98 @@ "熊吖": "person" }, "stop_words": [ - "photos", "photo", "pictures", "picture", "images", "image", - "video", "videos", "cosplay", "cos", - "and", "the", "of", "in", "a", "an", "is", "to", "for", - "part", "vol", "collection", "special", "extra", "bonus", - "new", "old", "selfie", "official", "original", - "set", "gallery", "album", "page", "issue", - "model", "idol", "star", "actor", "actress", "singer", - "秀人", "网", "图", "套", "合集", "系列", "作品", - "美女", "模特", "女神", "小姐姐", "高清", "原版", "无水印", - "番号", "编号", "with", "without", "preview", "patreon", - "no", "site", "web", "online", "digital", "exclusive", "premium", - "classic", "photography", "shoot", "shot", - "xxx", "com", "www", "https", "http", - "Impact", "写真", "系列" - + "photos", + "photo", + "pictures", + "picture", + "images", + "image", + "video", + "videos", + "cos", + "and", + "the", + "of", + "in", + "a", + "an", + "is", + "to", + "for", + "part", + "vol", + "collection", + "special", + "extra", + "bonus", + "new", + "old", + "selfie", + "official", + "original", + "set", + "gallery", + "album", + "page", + "issue", + "model", + "idol", + "star", + "actor", + "actress", + "singer", + "网", + "新人", + "图", + "套", + "合集", + "系列", + "作品", + "高清", + "原版", + "无水印", + "番号", + "编号", + "with", + "without", + "preview", + "patreon", + "no", + "site", + "web", + "online", + "digital", + "exclusive", + "premium", + "classic", + "photography", + "shoot", + "shot", + "xxx", + "com", + "www", + "https", + "http", + "Impact", + "写真", + "系列" ], "person_prefixes": [ - "美女模特", "性感女神", "清纯美女", "气质美女", "可爱女孩", - "甜美少女", "时尚达人", "女神", "美女", "模特", "小姐姐", - "小仙女", "御姐", "萝莉", "辣妹", "潮人" + "美女模特", + "性感女神", + "清纯美女", + "气质美女", + "可爱女孩", + "甜美少女", + "时尚达人", + "女神", + "美女", + "模特", + "小姐姐", + "小仙女", + "御姐", + "萝莉", + "辣妹", + "潮人" ] } diff --git a/src/db/metadata.rs b/src/db/metadata.rs index 62a9b3a..28f9506 100644 --- a/src/db/metadata.rs +++ b/src/db/metadata.rs @@ -314,6 +314,8 @@ impl Database { /// 把 src_id 的所有相册关联、别名移动到 dst_id,然后删除 src_id pub async fn merge_person_into(&self, src_id: i64, dst_id: i64) { + let _guard = self.write_lock.lock().await; + // 整个合并过程是一个原子操作,用事务包裹避免逐条 autocommit let mut tx = match self.pool.begin().await { Ok(t) => t, @@ -328,9 +330,9 @@ impl Database { sqlx::query("INSERT OR IGNORE INTO person_aliases (person_id, alias_type, alias_name) SELECT ?, alias_type, alias_name FROM person_aliases WHERE person_id = ?") .bind(dst_id).bind(src_id).execute(tx.deref_mut()).await.ok(); - // 3. 把 src 的原名也作为别名加入 dst + // 3. 把 src 的原名也作为别名加入 dst(使用事务连接,避免额外占用连接池) if let Some(r) = sqlx::query("SELECT id, name, display_name FROM persons WHERE id = ?") - .bind(src_id).fetch_optional(&self.pool).await.ok().flatten() + .bind(src_id).fetch_optional(tx.deref_mut()).await.ok().flatten() { let src_name: String = r.get("name"); let src_display: Option = r.get("display_name");