fix: 建行前按同标题兜底,防止季节码漂移造出重复图集

男装季节码由 FWyy 改为 SSyy 后,仍按旧规则算码的实例(如本机残留的旧后端)
会把同一场秀当成新场次再建一行,今天已产生 7 组重复(Acne/Celine/AMBUSH 等)。

- 新增 IngestRepository.RunwayTitleExists(品牌 + 英文标题)
- processRunway 在「实体键未命中、准备新建」时再查一次同标题:
  命中则跳过并记 outcome=skipped_existing,note 写明「季节码漂移保护」
- 宁可跳过也不产生重复;标题含年份,正常不会误伤不同场次
This commit is contained in:
toom1996
2026-10-25 18:37:20 +08:00
parent d6ed96624a
commit db3e3efab9
3 changed files with 37 additions and 0 deletions

View File

@ -33,6 +33,12 @@ type IngestRepository interface {
// outcome 取 model.IngestOutcome* 常量,note 例如「新建 42 张图」「已存在(status=published)」。
// 二者是后台「品牌更新记录」的全部信息源:只有 status=done 看不出这次到底新建还是跳过。
MarkDone(ctx context.Context, id uint32, outcome, note string) error
// RunwayTitleExists 按(品牌 + 英文标题)查已有图集,返回其 id 与是否存在。
//
// 用途:季节码推导规则变更后,同一场秀可能被算出不同的 season_code(如 Spring 男装
// 曾是 FWyy、现在是 SSyy)。老实例按旧规则写入会建出「同标题不同季节码」的重复图集。
// 建行前用它兜底,把「标题相同」视为同一场秀。
RunwayTitleExists(ctx context.Context, brandID uint32, titleEn string) (uint32, bool, error)
// ListByBrand 取某品牌的入库记录(按 id 倒序),供品牌详情页展示更新历史。
ListByBrand(ctx context.Context, brandID uint32, limit int) ([]BrandIngestRecord, error)
// MarkFailed 标记任务失败并记录错误(attempts 自增)。
@ -183,6 +189,20 @@ func (r *ingestRepository) MarkDone(ctx context.Context, id uint32, outcome, not
}).Error
}
// RunwayTitleExists 按(品牌 + 英文标题)查已有图集。
func (r *ingestRepository) RunwayTitleExists(ctx context.Context, brandID uint32, titleEn string) (uint32, bool, error) {
if brandID == 0 || titleEn == "" {
return 0, false, nil
}
var id uint32
if err := r.db.WithContext(ctx).Raw(
"SELECT id FROM brand_runways WHERE brand_id = ? AND title_en = ? AND is_deleted = 0 LIMIT 1",
brandID, titleEn).Scan(&id).Error; err != nil {
return 0, false, err
}
return id, id > 0, nil
}
// BrandIngestRecord 是品牌详情页需要的「一条更新记录」。
//
// 只取必要列:payload 可能几十 KB(含全部 look 的 key),一次拉 20 条会传上兆,