标签名称会随语言和运营文案变化,客户端按名称判断板块(如推荐页「上新」 横滑)一改名就失效。content_tag 新增 code 列并在后台维护, 卡片与详情以 tagCode 下发,已有「上新 / 热剧 / 新剧 / 热播」一并回填。
This commit is contained in:
1 parent
4d796089a0
commit
0d4d510aee
9 files changed
+73
No files matched your search
@@ -205,6 +205,10 @@ app.register.max-per-device-per-day
|
||||
> 卡片文案只放语言表:`titleLocales`、`synopsisLocales`、`types`、`tagLocales`。
|
||||
> `tagColor` 是标签背景色。中文取各表的 `zh`。
|
||||
>
|
||||
> `tagCode` 是标签语义码(如 `NEW_ARRIVAL`),来自 `content_tag.code`。
|
||||
> 客户端按码判断板块(推荐页「上新」横滑),`tagLocales` 只用于展示;
|
||||
> 码为空时客户端才退回按文案匹配。后台标签管理可配置该码。
|
||||
>
|
||||
> 卡片新增 `dramaType`:`ANIME` 表示漫剧,`LIVE` 表示真人剧。
|
||||
> 客户端字段仍返回主内容类型;后台多选值保存在 `drama.drama_types`,
|
||||
> App 类型筛选按逗号列整词匹配,因此 `ANIME,LIVE` 多标签剧可被任一类型命中。
|
||||
|
||||
@@ -411,6 +411,7 @@ public class AppCatalogService {
|
||||
ContentTag tag = tagOf(drama, tags);
|
||||
Map<String, String> locales = tagLocales(tag);
|
||||
card.setTagLocales(locales);
|
||||
card.setTagCode(tagCode(tag));
|
||||
card.setTagColor(tag == null ? "" : tag.getBgColor());
|
||||
}
|
||||
|
||||
@@ -418,9 +419,18 @@ public class AppCatalogService {
|
||||
ContentTag tag = tagOf(drama, loadTags(List.of(drama)));
|
||||
Map<String, String> locales = tagLocales(tag);
|
||||
detail.setTagLocales(locales);
|
||||
detail.setTagCode(tagCode(tag));
|
||||
detail.setTagColor(tag == null ? "" : tag.getBgColor());
|
||||
}
|
||||
|
||||
/** 语义码直接下发,客户端据此判断板块;未配置时给空串,由客户端按文案兜底。 */
|
||||
private String tagCode(ContentTag tag) {
|
||||
if (tag == null || tag.getCode() == null) {
|
||||
return "";
|
||||
}
|
||||
return tag.getCode().trim();
|
||||
}
|
||||
|
||||
private ContentTag tagOf(Drama drama, Map<Long, ContentTag> tags) {
|
||||
if (drama.getTagId() == null || drama.getTagId() <= 0L) {
|
||||
return null;
|
||||
|
||||
@@ -20,6 +20,8 @@ public class AppDramaCardVO {
|
||||
private List<Map<String, String>> types;
|
||||
/** 标签语言表,key 为 zh / en / id。 */
|
||||
private Map<String, String> tagLocales;
|
||||
/** 标签语义码,如 NEW_ARRIVAL;客户端按码判断板块,文案仅用于展示。 */
|
||||
private String tagCode;
|
||||
/** 标签角标背景色,#RRGGBB。 */
|
||||
private String tagColor;
|
||||
private Integer totalEpisodes;
|
||||
|
||||
@@ -16,6 +16,8 @@ public class AppDramaDetailVO {
|
||||
private String cover;
|
||||
private List<Map<String, String>> types;
|
||||
private Map<String, String> tagLocales;
|
||||
/** 标签语义码,如 NEW_ARRIVAL;空表示未配置。 */
|
||||
private String tagCode;
|
||||
private String tagColor;
|
||||
private Integer totalEpisodes;
|
||||
private Integer freeEpisodes;
|
||||
|
||||
+2
@@ -24,6 +24,8 @@ public class ContentTag {
|
||||
private String nameLocales;
|
||||
/** 角标背景色,#RRGGBB。 */
|
||||
private String bgColor;
|
||||
/** 语义码,如 NEW_ARRIVAL;客户端按码判断板块,不解析文案。空表示未配置。 */
|
||||
private String code;
|
||||
private Integer sort;
|
||||
private Integer status;
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
+26
@@ -49,9 +49,12 @@ public class ContentTagService {
|
||||
public Long create(ContentTagSaveReqVO req) {
|
||||
Map<String, String> locales = namesOf(req);
|
||||
ensureNameAvailable(locales.get(ContentLocaleTexts.ZH), null);
|
||||
String code = normalizeCode(req.getCode());
|
||||
ensureCodeAvailable(code, null);
|
||||
ContentTag entity = new ContentTag();
|
||||
writeNames(entity, locales);
|
||||
entity.setBgColor(normalizeColor(req.getBgColor()));
|
||||
entity.setCode(code);
|
||||
Long count = tagMapper.selectCount(null);
|
||||
entity.setSort(req.getSort() == null
|
||||
? (count == null ? 0 : count.intValue()) + 1
|
||||
@@ -69,6 +72,11 @@ public class ContentTagService {
|
||||
if (req.getBgColor() != null) {
|
||||
entity.setBgColor(normalizeColor(req.getBgColor()));
|
||||
}
|
||||
if (req.getCode() != null) {
|
||||
String code = normalizeCode(req.getCode());
|
||||
ensureCodeAvailable(code, id);
|
||||
entity.setCode(code);
|
||||
}
|
||||
if (req.getSort() != null) {
|
||||
entity.setSort(req.getSort());
|
||||
}
|
||||
@@ -115,6 +123,23 @@ public class ContentTagService {
|
||||
return color.trim().toUpperCase();
|
||||
}
|
||||
|
||||
/** 语义码统一大写;空字符串表示不配置。 */
|
||||
private String normalizeCode(String code) {
|
||||
return code == null ? "" : code.trim().toUpperCase();
|
||||
}
|
||||
|
||||
private void ensureCodeAvailable(String code, Long excludeId) {
|
||||
if (code.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
Long count = tagMapper.selectCount(Wrappers.<ContentTag>lambdaQuery()
|
||||
.eq(ContentTag::getCode, code)
|
||||
.ne(excludeId != null, ContentTag::getId, excludeId));
|
||||
if (count != null && count > 0) {
|
||||
throw new ServiceException(ErrorCode.DATA_EXISTS, "语义码已存在");
|
||||
}
|
||||
}
|
||||
|
||||
private ContentTag getExisting(Long id) {
|
||||
ContentTag entity = id == null ? null : tagMapper.selectById(id);
|
||||
if (entity == null) {
|
||||
@@ -142,6 +167,7 @@ public class ContentTagService {
|
||||
vo.setNameId(ContentLocaleTexts.value(locales, ContentLocaleTexts.ID));
|
||||
vo.setLocales(locales);
|
||||
vo.setBgColor(tag.getBgColor() == null || tag.getBgColor().isBlank() ? "#E5484D" : tag.getBgColor());
|
||||
vo.setCode(tag.getCode() == null ? "" : tag.getCode());
|
||||
vo.setSort(tag.getSort());
|
||||
vo.setStatus(tag.getStatus());
|
||||
return vo;
|
||||
|
||||
+2
@@ -14,6 +14,8 @@ public class ContentTagRespVO {
|
||||
private String nameId;
|
||||
private java.util.Map<String, String> locales;
|
||||
private String bgColor;
|
||||
/** 语义码,如 NEW_ARRIVAL;空表示未配置。 */
|
||||
private String code;
|
||||
private Integer sort;
|
||||
private Integer status;
|
||||
}
|
||||
+4
@@ -21,6 +21,10 @@ public class ContentTagSaveReqVO {
|
||||
@Pattern(regexp = "^$|^#[0-9A-Fa-f]{6}$", message = "背景色格式应为 #RRGGBB")
|
||||
private String bgColor;
|
||||
|
||||
/** 语义码,如 NEW_ARRIVAL;客户端按码判断板块,留空表示按文案兜底。 */
|
||||
@Pattern(regexp = "^$|^[A-Z][A-Z0-9_]{0,31}$", message = "语义码需为大写字母、数字或下划线")
|
||||
private String code;
|
||||
|
||||
private Integer sort;
|
||||
private Integer status;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
-- Author: fruit.com.cn
|
||||
-- 标签语义码:客户端按稳定码判断板块归属(如「上新」横滑),文案可随意改。
|
||||
|
||||
ALTER TABLE content_tag ADD COLUMN IF NOT EXISTS code VARCHAR(32) NOT NULL DEFAULT '';
|
||||
|
||||
-- 同一个语义码只能给一个标签,空码不参与唯一性约束。
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS uk_content_tag_code
|
||||
ON content_tag (code) WHERE code <> '';
|
||||
|
||||
-- 已有标签回填语义码(幂等:只补空的)。
|
||||
UPDATE content_tag SET code = 'NEW_ARRIVAL'
|
||||
WHERE code = '' AND (name = '上新' OR name_en = 'New Arrival');
|
||||
|
||||
UPDATE content_tag SET code = 'HOT'
|
||||
WHERE code = '' AND (name = '热剧' OR name_en = 'Hot');
|
||||
|
||||
UPDATE content_tag SET code = 'NEW_RELEASE'
|
||||
WHERE code = '' AND (name = '新剧' OR name_en = 'New Movie');
|
||||
|
||||
UPDATE content_tag SET code = 'TRENDING'
|
||||
WHERE code = '' AND (name = '热播' OR name_en = 'Rebo');
|
||||
Reference in new issue
Block a user