Explorar el Código

chore: auto bump version and changelog [skip ci]

iwt hace 1 mes
padre
commit
9e043284c6

+ 8 - 0
cfc-backend/src/main/java/com/etotem/cfc/config/DatabaseInitializer.java

@@ -10557,5 +10557,13 @@ public class DatabaseInitializer implements CommandLineRunner {
         } catch (Exception e) {
             log.warn("迁移305: health_indicators.status 修改失败: {}", e.getMessage());
         }
+
+        // 迁移306: products表添加visible_roles列(商品类型权限过滤,NULL=全部角色可见)
+        try {
+            jdbcTemplate.execute("ALTER TABLE products ADD COLUMN visible_roles JSON DEFAULT NULL COMMENT '可见角色: [\"parent\",\"child\",\"teacher\",\"admin\"],NULL=全部可见'");
+            log.info("迁移306: products.visible_roles 列已添加");
+        } catch (Exception e) {
+            // ignore
+        }
     }
 }

+ 3 - 2
cfc-backend/src/main/java/com/etotem/cfc/controller/product/ProductController.java

@@ -42,8 +42,9 @@ public class ProductController {
 
     @PostMapping("/list")
     public Result<Map<String, Object>> list(@RequestBody ProductListQueryDTO query,
-                                             @RequestAttribute(value = "userId", required = false) Long userId) {
-        return productService.list(query, userId);
+                                             @RequestAttribute(value = "userId", required = false) Long userId,
+                                             @RequestAttribute(value = "role", required = false) String role) {
+        return productService.list(query, userId, role);
     }
 
     @PostMapping("/detail")

+ 8 - 0
cfc-backend/src/main/java/com/etotem/cfc/dto/ProductDTO.java

@@ -32,6 +32,7 @@ public class ProductDTO {
     private String memberEligible;
     private String rejectReason;
     private Integer deliveryMethod;        // 配送方式: 1=快递 2=自提 3=两者皆可
+    private List<String> visibleRoles;     // 可见角色列表,NULL=全部角色可见
     private List<String> imageList;
     private Long energyDimensionId;
     private Integer effectivePpoint;     // 有效P点(基点,如1000=10%)
@@ -113,6 +114,13 @@ public class ProductDTO {
         d.rejectReason = p.getRejectReason();
         d.deliveryMethod = p.getDeliveryMethod();
         d.sortOrder = p.getSortOrder();
+        if (p.getVisibleRoles() != null && !p.getVisibleRoles().isEmpty()) {
+            try {
+                d.visibleRoles = JSON.parseArray(p.getVisibleRoles(), String.class);
+            } catch (Exception e) {
+                d.visibleRoles = null;
+            }
+        }
         d.createdAt = p.getCreatedAt();
         d.updatedAt = p.getUpdatedAt();
         // 会员体系重构:商品对所有用户统一定价(活动侧保留会员价,商品侧停用)

+ 4 - 0
cfc-backend/src/main/java/com/etotem/cfc/entity/Product.java

@@ -49,6 +49,9 @@ public class Product implements Serializable {
     /** 是否面向家庭: 1=家庭成员消费过即排除, 0=仅按个人消费排除 */
     private Integer familyScope;
 
+    /** 可见角色JSON数组,NULL表示全部角色可见 */
+    private String visibleRoles;
+
     // 佣金系统 - 平台利润率(千分比)
     private Integer profitRate;
 
@@ -91,6 +94,7 @@ public class Product implements Serializable {
     public Integer getDeliveryMethod() { return deliveryMethod; }
     public Integer getMinQuantity() { return minQuantity; }
     public Integer getSortOrder() { return sortOrder; }
+    public String getVisibleRoles() { return visibleRoles; }
     public Date getCreatedAt() { return createdAt; }
     public Date getUpdatedAt() { return updatedAt; }
 }

+ 9 - 1
cfc-backend/src/main/java/com/etotem/cfc/service/ProductService.java

@@ -70,7 +70,7 @@ public class ProductService {
         return productMapper.selectById(id);
     }
 
-    public Result<Map<String, Object>> list(ProductListQueryDTO query, Long userId) {
+    public Result<Map<String, Object>> list(ProductListQueryDTO query, Long userId, String role) {
         Page<Product> page = new Page<>(query.getPage(), query.getSize());
         LambdaQueryWrapper<Product> wrapper = new LambdaQueryWrapper<Product>()
             .eq(Product::getStatus, "on_shelf");
@@ -97,6 +97,13 @@ wrapper.in(Product::getId, productIds)
         if (userId == null) {
             wrapper.ne(Product::getMemberEligible, "yes");
         }
+        // 可见角色过滤:visible_roles 为 NULL 时全部可见,否则仅匹配用户角色
+        if (userId == null) {
+            wrapper.isNull(Product::getVisibleRoles);
+        } else if (role != null && !role.isEmpty()) {
+            wrapper.and(w -> w.isNull(Product::getVisibleRoles)
+                .or().apply("JSON_CONTAINS(visible_roles, JSON_QUOTE({0}))", role));
+        }
         if (query.getProductType() != null && !query.getProductType().isEmpty()) {
             wrapper.eq(Product::getProductType, query.getProductType());
         }
@@ -482,6 +489,7 @@ wrapper.in(Product::getId, productIds)
         copy.setDeliveryMethod(original.getDeliveryMethod());
         copy.setMinQuantity(original.getMinQuantity());
         copy.setSortOrder(original.getSortOrder());
+        copy.setVisibleRoles(original.getVisibleRoles());
         copy.setCreatedAt(new Date());
         copy.setUpdatedAt(new Date());
         productMapper.insert(copy);

+ 1 - 0
cfc-backend/src/main/resources/schema.sql

@@ -1158,6 +1158,7 @@ CREATE TABLE IF NOT EXISTS products (
     external_id VARCHAR(128) COMMENT '外部来源ID',
     external_data TEXT COMMENT '外部来源数据JSON',
     family_scope TINYINT DEFAULT 1 COMMENT '是否面向家庭: 1=家庭成员消费过即排除, 0=仅按个人消费排除',
+    visible_roles JSON DEFAULT NULL COMMENT '可见角色: ["parent","child","teacher","admin"],NULL=全部可见',
     created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
     updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品表';

+ 1 - 1
cfc-web/.last_build_commit

@@ -1 +1 @@
-29a27f876a3dd7606d1cf1b4e01ff816ddcf65eb
+9abfe21d8440c7c7497345148435a86775e83e8e

+ 2 - 2
cfc-web/package-lock.json

@@ -1,12 +1,12 @@
 {
   "name": "cfc-web",
-  "version": "1.0.1352",
+  "version": "1.0.1353",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
       "name": "cfc-web",
-      "version": "1.0.1352",
+      "version": "1.0.1353",
       "dependencies": {
         "@wangeditor/editor": "^5.1.23",
         "@wangeditor/editor-for-vue": "^1.0.2",

+ 1 - 1
cfc-web/package.json

@@ -1,6 +1,6 @@
 {
   "name": "cfc-web",
-  "version": "1.0.1353",
+  "version": "1.0.1354",
   "private": true,
   "scripts": {
     "dev": "vue-cli-service serve",

+ 12 - 0
cfc-web/public/CHANGELOG-v1.0.md

@@ -4,6 +4,18 @@
 
 ---
 
+## v1.0.1354 (2026-09-10)
+
+### Bug 修复
+- 戒备食材链路修复——caution-detail key 编译报错 + gut-flora 按报告主体传参
+
+### 其他
+-   微信小程序模板编译器不支持,改为 getMemberKey(item) 方法调用
+- - gut-flora-detail 戒备食材数量与戒备页跳转按报告 subjectId 传参,
+-   修复家长账号查询不到孩子推荐指数的问题
+- 
+
+
 ## v1.0.1353 (2026-09-10)
 
 ### Bug 修复

+ 13 - 1
cfc-web/public/CHANGELOG.md

@@ -1,6 +1,6 @@
 # 更新日志
 
-> 当前版本: v1.0.1353
+> 当前版本: v1.0.1354
 
 ## 历史版本
 
@@ -8,6 +8,18 @@
 
 ---
 
+## v1.0.1354 (2026-09-10)
+
+### Bug 修复
+- 戒备食材链路修复——caution-detail key 编译报错 + gut-flora 按报告主体传参
+
+### 其他
+-   微信小程序模板编译器不支持,改为 getMemberKey(item) 方法调用
+- - gut-flora-detail 戒备食材数量与戒备页跳转按报告 subjectId 传参,
+-   修复家长账号查询不到孩子推荐指数的问题
+- 
+
+
 ## v1.0.1353 (2026-09-10)
 
 ### Bug 修复

+ 12 - 0
cfc-web/src/views/admin/ProductEdit.vue

@@ -250,6 +250,16 @@
           </el-radio-group>
         </el-form-item>
 
+        <el-form-item label="可见角色">
+          <el-select v-model="form.visibleRoles" multiple placeholder="全部可见" style="width: 200px;">
+            <el-option label="家长" value="parent" />
+            <el-option label="孩子" value="child" />
+            <el-option label="规划师" value="teacher" />
+            <el-option label="管理员" value="admin" />
+          </el-select>
+          <span style="margin-left: 10px; font-size: 12px; color: #999;">留空=全部角色可见,选择后仅指定角色可见</span>
+        </el-form-item>
+
         <el-form-item label="商品维度">
           <dimension-weight-picker v-model="form.dimensionWeights" :show-presets="true" />
         </el-form-item>
@@ -366,6 +376,7 @@ export default {
         distributionSystemId: null,
         deliveryMethod: 1,
         memberEligible: 'no',
+        visibleRoles: [],
         dimensionWeights: [],
         // 测评商品扩展
         assessmentType: 'single',
@@ -625,6 +636,7 @@ export default {
             distributionSystemId: p.distributionSystemId || null,
             deliveryMethod: p.deliveryMethod || 1,
             memberEligible: p.memberEligible || 'no',
+            visibleRoles: p.visibleRoles || [],
             dimensionWeights: [],
             assessmentType: p.assessmentType || 'single',
             totalSessions: p.totalSessions || 1,

+ 10 - 0
cfc-web/src/views/admin/ProductManage.vue

@@ -95,6 +95,12 @@
           {{ row.sortOrder != null ? row.sortOrder : '-' }}
         </template>
       </el-table-column>
+      <el-table-column label="可见角色" width="140">
+        <template slot-scope="{ row }">
+          <span v-if="row.visibleRoles && row.visibleRoles.length">{{ row.visibleRoles.join(', ') }}</span>
+          <span v-else style="color:#999">全部</span>
+        </template>
+      </el-table-column>
       <el-table-column prop="createdAt" label="创建时间" width="160">
         <template slot-scope="{ row }">
           {{ formatTime(row.createdAt) }}
@@ -154,6 +160,10 @@
         <el-descriptions-item label="状态">
           <el-tag :type="statusType(detail.status)" size="mini">{{ statusLabel(detail.status) }}</el-tag>
         </el-descriptions-item>
+        <el-descriptions-item label="可见角色" v-if="detail.visibleRoles && detail.visibleRoles.length">
+          {{ detail.visibleRoles.join(', ') }}
+        </el-descriptions-item>
+        <el-descriptions-item label="可见角色" v-else>全部</el-descriptions-item>
         <el-descriptions-item label="拒绝原因" v-if="detail.rejectReason">{{ detail.rejectReason }}</el-descriptions-item>
         <el-descriptions-item label="商品描述" :span="2">{{ detail.description || '-' }}</el-descriptions-item>
         <el-descriptions-item label="创建时间" :span="2">{{ formatTime(detail.createdAt) }}</el-descriptions-item>