四个核心实体(活动、商品、文章、任务)都有"五维归属"的概念,但存储和查询方式各不相同。当前设计目标是:根据维度筛选时,只要该实体在对应维度的权重 > 0 就命中。
| 实体 | 表名 | 旧字段 | 新字段 | 维度筛选方式 |
|---|---|---|---|---|
| Activity | activities | dimension_code (单值) |
dimension_weights (JSON) |
JSON_EXTRACT(dimension_weights, '$.{dim}') > 0 OR dimension_code = {dim} |
| Product | products | domain (单值) |
dimension_weights (JSON) |
JSON_EXTRACT(dimension_weights, '$.{dim}') > 0 OR domain = {dim} |
| Article | articles | related_dimensions (逗号分隔) |
dimension_weights (JSON) |
JSON_EXTRACT(dimension_weights, '$.{dim}') > 0 OR related_dimensions LIKE %{dim}% |
| Task | tasks | 无 | 无 | ❌ 不支持维度筛选 |
实体字段:
private String dimensionCode; // 旧: 单值, 如 "body"
private String dimensionWeights; // 新: JSON, 如 {"body":30,"mind":0,"wisdom":0,"action":70,"wealth":0}
筛选逻辑(ActivityService.list() 第53-63行):
if (dimensionCode != null && !dimensionCode.isEmpty()) {
query.and(w -> w
.apply("COALESCE(JSON_EXTRACT(dimension_weights, '$." + dimensionCode + "'), 0) > 0")
.or().eq(Activity::getDimensionCode, dimensionCode)
);
}
状态: ✅ 已实现权重感知筛选,兼容旧版 dimensionCode
实体字段:
private String domain; // 旧: 单值, 如 "body"
private String dimensionWeights; // 新: JSON, 如 {"body":30,"mind":0,"wisdom":0,"action":70,"wealth":0}
筛选逻辑(ProductService.list() 第56-62行):
if (query.getDomain() != null && !query.getDomain().isEmpty()) {
String domain = query.getDomain();
wrapper.and(w -> w
.apply("COALESCE(JSON_EXTRACT(dimension_weights, '$." + domain + "'), 0) > 0")
.or().eq(Product::getDomain, domain)
);
}
注意: 查询参数名为 domain(ProductListQueryDTO 中定义),前端传的是 dimensionCode 还是 domain 需要确认对齐。
状态: ✅ 已实现权重感知筛选,兼容旧版 domain
实体字段:
private String relatedDimensions; // 旧: 逗号分隔, 如 "body,mind"
private String dimensionIds; // 维度ID列表JSON
private String dimensionWeights; // 新: JSON, 如 {"body":30,"mind":0,...}
筛选逻辑(ArticleService.getPublicList() 第93-98行):
if (dimensionCode != null && !dimensionCode.trim().isEmpty()) {
wrapper.and(w -> w
.apply("COALESCE(JSON_EXTRACT(dimension_weights, '$." + dimensionCode.trim() + "'), 0) > 0")
.or().like(Article::getRelatedDimensions, dimensionCode.trim())
);
}
自动生成权重的逻辑(ArticleService 第702-706行):
当管理员设置 relatedDimensions 时,自动调用 buildEqualWeights() 生成等比例权重:
private String buildEqualWeights(String relatedDimensions) {
String[] parts = relatedDimensions.split(",");
int equalWeight = 100 / parts.length;
// 为每个维度分配 equalWeight
}
状态: ✅ 已实现权重感知筛选,兼容旧版 relatedDimensions
实体字段: 无维度相关字段
Task 实体没有 dimensionCode、domain、dimensionWeights 等任何维度字段。任务通过 category 字段分类(如"学习类""行动类"),但分类与五维维度没有直接映射关系。
状态: ❌ 不支持维度筛选
所有实体统一使用 JSON 格式存储五维权重:
{
"body": 0,
"mind": 30,
"wisdom": 20,
"action": 50,
"wealth": 0
}
使用 MySQL 的 JSON_EXTRACT 函数:
COALESCE(JSON_EXTRACT(dimension_weights, '$.body'), 0) > 0
dimension_weights 为 NULL 或 JSON 中不含该 key,返回 0三种实体都保留了旧字段的兼容查询:
dimension_code 精确匹配domain 精确匹配related_dimensions LIKE 模糊匹配| 实体 | 列表接口 | 维度参数名 | 示例 |
|---|---|---|---|
| 活动 | POST /api/activity/list |
dimensionCode |
{"dimensionCode":"body"} |
| 商品 | POST /api/product/list |
domain |
{"domain":"body"} |
| 文章 | POST /api/articles/list |
dimensionCode |
{"dimensionCode":"body"} |
| 任务 | POST /api/tasks/today |
不支持 | — |
商品列表使用 domain 而非 dimensionCode,与其他三个不统一。建议在 ProductListQueryDTO 中增加 dimensionCode 别名,内部映射到 domain。
如果任务需要按维度筛选,有两种方案:
dimensionCode 字段(单值),通过 category → dimensionCode 映射表自动填充dimensionWeights JSON 字段,与活动/商品/文章保持一致| 实体 | 创建接口 | 维度参数 | 说明 |
|---|---|---|---|
| 活动 | POST /api/admin/activity/create |
dimensionCode + dimensionWeights |
管理后台设置 |
| 商品 | POST /api/product/create |
domain + dimensionWeights |
管理后台设置 |
| 文章 | POST /api/admin/articles/create |
relatedDimensions |
自动生成 dimensionWeights |
| 任务 | POST /api/tasks/create |
不支持 | 通过 category 间接关联 |