# 维度参数获取与筛选设计分析 ## 概述 四个核心实体(活动、商品、文章、任务)都有"五维归属"的概念,但存储和查询方式各不相同。当前设计目标是:**根据维度筛选时,只要该实体在对应维度的权重 > 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 | 无 | 无 | ❌ 不支持维度筛选 | ## 逐项分析 ### 1. Activity(活动)✅ 已实现 **实体字段:** ```java private String dimensionCode; // 旧: 单值, 如 "body" private String dimensionWeights; // 新: JSON, 如 {"body":30,"mind":0,"wisdom":0,"action":70,"wealth":0} ``` **筛选逻辑(ActivityService.list() 第53-63行):** ```java if (dimensionCode != null && !dimensionCode.isEmpty()) { query.and(w -> w .apply("COALESCE(JSON_EXTRACT(dimension_weights, '$." + dimensionCode + "'), 0) > 0") .or().eq(Activity::getDimensionCode, dimensionCode) ); } ``` **状态:** ✅ 已实现权重感知筛选,兼容旧版 `dimensionCode` ### 2. Product(商品)✅ 已实现 **实体字段:** ```java private String domain; // 旧: 单值, 如 "body" private String dimensionWeights; // 新: JSON, 如 {"body":30,"mind":0,"wisdom":0,"action":70,"wealth":0} ``` **筛选逻辑(ProductService.list() 第56-62行):** ```java 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` ### 3. Article(文章)✅ 已实现 **实体字段:** ```java private String relatedDimensions; // 旧: 逗号分隔, 如 "body,mind" private String dimensionIds; // 维度ID列表JSON private String dimensionWeights; // 新: JSON, 如 {"body":30,"mind":0,...} ``` **筛选逻辑(ArticleService.getPublicList() 第93-98行):** ```java 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()` 生成等比例权重: ```java private String buildEqualWeights(String relatedDimensions) { String[] parts = relatedDimensions.split(","); int equalWeight = 100 / parts.length; // 为每个维度分配 equalWeight } ``` **状态:** ✅ 已实现权重感知筛选,兼容旧版 `relatedDimensions` ### 4. Task(任务)❌ 不支持维度筛选 **实体字段:** 无维度相关字段 Task 实体没有 `dimensionCode`、`domain`、`dimensionWeights` 等任何维度字段。任务通过 `category` 字段分类(如"学习类""行动类"),但分类与五维维度没有直接映射关系。 **状态:** ❌ 不支持维度筛选 ## 架构设计 ### JSON 权重格式 所有实体统一使用 JSON 格式存储五维权重: ```json { "body": 0, "mind": 30, "wisdom": 20, "action": 50, "wealth": 0 } ``` - 权重值范围:0-100(整数) - 0 = 不关联该维度 - > 0 = 关联该维度,值越大关联度越高 - 所有权重之和不一定等于 100(可以只设置部分维度) ### 筛选原理 使用 MySQL 的 `JSON_EXTRACT` 函数: ```sql COALESCE(JSON_EXTRACT(dimension_weights, '$.body'), 0) > 0 ``` - 如果 `dimension_weights` 为 NULL 或 JSON 中不含该 key,返回 0 - 如果权重 > 0,表示该实体关联此维度,命中筛选 ### 兼容旧数据 三种实体都保留了旧字段的兼容查询: - Activity: `dimension_code` 精确匹配 - Product: `domain` 精确匹配 - Article: `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`。 ### Task 增加维度支持 如果任务需要按维度筛选,有两种方案: 1. **轻量方案**:在 Task 实体增加 `dimensionCode` 字段(单值),通过 `category` → `dimensionCode` 映射表自动填充 2. **完整方案**:增加 `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 间接关联 |