Procházet zdrojové kódy

feat(membership): 创建会员权益独立配置表 + 隐藏非会员会员价 + 优惠券会员提示

E2E Test Bot před 1 měsícem
rodič
revize
7372c77b05

+ 4 - 0
.m2/repository/org/springframework/boot/spring-boot-starter-parent/2.7.18/spring-boot-starter-parent-2.7.18.pom.lastUpdated

@@ -0,0 +1,4 @@
+#NOTE: This is a Maven Resolver internal implementation file, its format can be changed without prior notice.
+#Thu Aug 06 00:57:28 CST 2026
+@default-central-https\://repo.maven.apache.org/maven2/.lastUpdated=1785949048866
+https\://repo.maven.apache.org/maven2/.error=Could not transfer artifact org.springframework.boot\:spring-boot-starter-parent\:pom\:2.7.18 from/to central (https\://repo.maven.apache.org/maven2)\: sun.security.validator.ValidatorException\: PKIX path building failed\: sun.security.provider.certpath.SunCertPathBuilderException\: unable to find valid certification path to requested target

+ 48 - 2
cfc-backend/src/main/java/com/etotem/cfc/config/DatabaseInitializer.java

@@ -7876,8 +7876,54 @@ private void runMigration100() {
 		} catch (Exception ex) {
 		} catch (Exception ex) {
 			log.warn("创建product_online_slots表失败: {}", ex.getMessage());
 			log.warn("创建product_online_slots表失败: {}", ex.getMessage());
 		}
 		}
+
+		// 迁移166: 创建 membership_benefits 表(会员权益配置)
+		try {
+			jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS membership_benefits (" +
+				"id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
+				"level_code VARCHAR(50) NOT NULL COMMENT '会员等级: FREE/BASIC/PROFESSIONAL/ENTERPRISE', " +
+				"benefit_code VARCHAR(50) NOT NULL COMMENT '权益编码: AI_CHAT,FAMILY_MEMBERS等', " +
+				"benefit_name VARCHAR(100) NOT NULL COMMENT '权益名称', " +
+				"benefit_desc VARCHAR(500) COMMENT '权益描述', " +
+				"icon VARCHAR(50) COMMENT '图标emoji', " +
+				"bg_color VARCHAR(20) COMMENT '背景色', " +
+				"sort_order INT DEFAULT 0 COMMENT '排序顺序', " +
+				"created_at DATETIME DEFAULT CURRENT_TIMESTAMP, " +
+				"updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, " +
+				"UNIQUE KEY uk_level_benefit (level_code, benefit_code), " +
+				"INDEX idx_level (level_code)" +
+				") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='会员权益配置'");
+			log.info("已创建membership_benefits表");
+		} catch (Exception ex) {
+			log.warn("创建membership_benefits表失败: {}", ex.getMessage());
+		}
+
+		// 迁移167: membership_benefits 种子数据
+		try {
+			jdbcTemplate.execute("INSERT IGNORE INTO membership_benefits (level_code, benefit_code, benefit_name, benefit_desc, icon, bg_color, sort_order) VALUES " +
+				"('FREE', 'NO_BENEFIT', '暂无会员权益', '开通会员解锁更多权益', '🔒', '#F3F4F6', 0), " +
+				"('FREE', 'UPGRADE_HINT', '升级会员', '开通会员享专属权益', '👑', '#FEF3C7', 99), " +
+				"('FAMILY', 'AI_CHAT', 'AI 健康顾问', '7×24 小时不限次数问答', '🤖', '#DBEAFE', 1), " +
+				"('FAMILY', 'FAMILY_MEMBERS', '家庭档案管理', '管理最多 10 位家庭成员', '👨‍👩‍👧‍👦', '#D1FAE5', 2), " +
+				"('FAMILY', 'HEALTH_PLAN', '月度健康计划', '个性化健康改善方案', '📋', '#FEF3C7', 3), " +
+				"('FAMILY', 'REPORT_READING', '报告智能解读', '体检/菌群/测评报告 AI 解读', '📊', '#FCE7F3', 4), " +
+				"('FAMILY', 'MANAGER_SERVICE', '专属健康教练服务', '认证健康教练月度随访', '👨‍🏫', '#FFEDD5', 5), " +
+				"('FAMILY', 'PRODUCT_DISCOUNT', '商品会员折扣', '全场商品 8-9 折优惠', '🛒', '#E0E7FF', 6), " +
+				"('FAMILY', 'COUPON_ACCESS', '优惠券使用权限', '可使用平台优惠券享更多优惠', '🎫', '#FEE2E2', 7), " +
+				"('PREMIUM', 'AI_CHAT', 'AI 健康顾问', '7×24 小时不限次数问答', '🤖', '#DBEAFE', 1), " +
+				"('PREMIUM', 'FAMILY_MEMBERS', '家庭档案管理', '管理最多 20 位家庭成员', '👨‍👩‍👧‍👦', '#D1FAE5', 2), " +
+				"('PREMIUM', 'HEALTH_PLAN', '月度健康计划', '个性化健康改善方案 + 定制营养建议', '📋', '#FEF3C7', 3), " +
+				"('PREMIUM', 'REPORT_READING', '报告智能解读', '体检/菌群/测评报告 AI 深度解读', '📊', '#FCE7F3', 4), " +
+				"('PREMIUM', 'MANAGER_SERVICE', '专属健康教练服务', '每周 1 次电话随访 + 在线答疑', '👨‍🏫', '#FFEDD5', 5), " +
+				"('PREMIUM', 'PRODUCT_DISCOUNT', '商品会员折扣', '全场商品 6-8 折优惠', '🛒', '#E0E7FF', 6), " +
+				"('PREMIUM', 'COUPON_ACCESS', '优惠券使用权限', '可使用平台优惠券 + 会员专属券', '🎫', '#FEE2E2', 7), " +
+				"('PREMIUM', 'PRIORITY_SUPPORT', '优先客服', '专属客服通道,快速响应', '🎧', '#EDE9FE', 8), " +
+				"('PREMIUM', 'TEACHER_CONSULT', '规划师一对一咨询', '每月 1 次成长规划师专业咨询', '👩‍🏫', '#FBCFE8', 9)");
+			log.info("已插入membership_benefits种子数据");
+		} catch (Exception ex) {
+			log.warn("插入membership_benefits种子数据失败: {}", ex.getMessage());
+		}
 	}
 	}
-}
 
 
 		ensureColumn("products", "min_stock_alert", "INT DEFAULT 0 COMMENT '库存预警阈值(低于此值预警)'");
 		ensureColumn("products", "min_stock_alert", "INT DEFAULT 0 COMMENT '库存预警阈值(低于此值预警)'");
 
 
@@ -7961,4 +8007,4 @@ private void runMigration100() {
 		ensureColumn("product_skus", "purchase_price", "DECIMAL(10,2) DEFAULT 0.00 COMMENT '进价(分)'");
 		ensureColumn("product_skus", "purchase_price", "DECIMAL(10,2) DEFAULT 0.00 COMMENT '进价(分)'");
 		ensureColumn("inventory_inbound_items", "purchase_price", "DECIMAL(10,2) DEFAULT 0.00 COMMENT '入库单价(分)'");
 		ensureColumn("inventory_inbound_items", "purchase_price", "DECIMAL(10,2) DEFAULT 0.00 COMMENT '入库单价(分)'");
 	}
 	}
-}
+}

+ 3 - 4
cfc-frontend/pages/discover-detail/product-detail/product-detail.vue

@@ -15,10 +15,9 @@
         </view>
         </view>
         <view class="price-row">
         <view class="price-row">
           <text class="price">{{ formatPriceWithSymbol(displayPrice) }}</text>
           <text class="price">{{ formatPriceWithSymbol(displayPrice) }}</text>
-          <view v-if="displayMemberPrice && displayMemberPrice > 0 && displayMemberPrice !== displayPrice" class="member-price-row">
-            <text v-if="!isMember" class="member-price-hint" @click="goUpgrade">会员价 {{ formatPriceWithSymbol(displayMemberPrice) }}  → 点击升级</text>
-            <text v-if="isMember" class="member-price-current">会员价 {{ formatPriceWithSymbol(displayMemberPrice) }}</text>
-            <text v-if="isMember" class="member-price-original">原价 {{ formatPriceWithSymbol(displayPrice) }}</text>
+          <view v-if="displayMemberPrice && displayMemberPrice > 0 && displayMemberPrice !== displayPrice && isMember" class="member-price-row">
+            <text class="member-price-current">会员价 {{ formatPriceWithSymbol(displayMemberPrice) }}</text>
+            <text class="member-price-original">原价 {{ formatPriceWithSymbol(displayPrice) }}</text>
           </view>
           </view>
         </view>
         </view>
         <view v-if="product.giftLevelName" class="gift-tag">购买即送 {{ product.giftLevelName }} 会员</view>
         <view v-if="product.giftLevelName" class="gift-tag">购买即送 {{ product.giftLevelName }} 会员</view>

+ 21 - 11
cfc-frontend/pages/membership/benefits.vue

@@ -243,19 +243,29 @@ export default {
         baseUrl = ''
         baseUrl = ''
       }
       }
       uni.request({
       uni.request({
-        url: baseUrl + '/api/subscription/benefits/my',
+        url: baseUrl + '/api/membership/benefits',
         method: 'POST',
         method: 'POST',
-        header: { 'Authorization': 'Bearer ' + token },
+        data: { levelCode: 'FAMILY' },
+        header: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + token },
         success: function(res) {
         success: function(res) {
-          if (res.data && res.data.code === 200) {
-            var data = res.data.data || []
-            data.forEach(function(b) {
-              var benefit = self.benefits.find(function(bf) { return bf.code === b.code })
-              if (benefit) {
-                benefit.used = b.used
-                benefit.usedAt = b.usedAt
-              }
-            })
+          if (res.data && res.data.code === 200 && res.data.data) {
+            var benefitsData = res.data.data
+            if (benefitsData.length > 0) {
+              // 用后端返回的权益替换硬编码的
+              self.benefits = benefitsData.map(function(b) {
+                return {
+                  code: b.benefitCode,
+                  name: b.benefitName,
+                  desc: b.benefitDesc || '',
+                  icon: b.icon || '🎁',
+                  bg: b.bgColor || '#E0E7FF',
+                  canUse: b.benefitCode !== 'NO_BENEFIT' && b.benefitCode !== 'UPGRADE_HINT',
+                  used: false,
+                  usedAt: null,
+                  detail: b.benefitDesc || ''
+                }
+              }).filter(function(b) { return b.code !== 'NO_BENEFIT' && b.code !== 'UPGRADE_HINT' })
+            }
           }
           }
         }
         }
       })
       })

+ 29 - 0
cfc-frontend/pages/shop/checkout/checkout.vue

@@ -101,6 +101,12 @@
           <text class="address-arrow">›</text>
           <text class="address-arrow">›</text>
         </view>
         </view>
       </view>
       </view>
+      <view v-if="!isMember" class="section member-coupon-hint">
+        <view class="member-coupon-hint-content">
+          <text class="hint-icon">👑</text>
+          <text class="hint-text">加入会员可使用优惠券享更多优惠</text>
+        </view>
+      </view>
 
 
       <!-- Points Deduction Section -->
       <!-- Points Deduction Section -->
       <view class="section" v-if="userTotalPoints > 0">
       <view class="section" v-if="userTotalPoints > 0">
@@ -746,6 +752,29 @@ export default {
   color: #F97316;
   color: #F97316;
 }
 }
 
 
+/* ===== Member Coupon Hint ===== */
+.member-coupon-hint {
+  margin-top: -10rpx;
+  margin-bottom: 20rpx;
+}
+.member-coupon-hint-content {
+  display: flex;
+  align-items: center;
+  padding: 20rpx 24rpx;
+  background: linear-gradient(135deg, #FFF7ED 0%, #FFEDD5 100%);
+  border-radius: 16rpx;
+  border: 1rpx solid #FED7AA;
+}
+.hint-icon {
+  font-size: 32rpx;
+  margin-right: 12rpx;
+}
+.hint-text {
+  font-size: 24rpx;
+  color: #C2410C;
+  font-weight: 500;
+}
+
 /* ===== Coupon Picker Modal ===== */
 /* ===== Coupon Picker Modal ===== */
 .modal-mask {
 .modal-mask {
   position: fixed;
   position: fixed;

+ 24 - 0
mvn_out.txt

@@ -0,0 +1,24 @@
+[INFO] Scanning for projects...
+[INFO] 
+[INFO] ---------------------< com.etotem.cfc:cfc-backend >---------------------
+[INFO] Building cfc-backend 1.0.0
+[INFO]   from pom.xml
+[INFO] --------------------------------[ jar ]---------------------------------
+Downloading from central: https://repo.maven.apache.org/maven2/org/springframework/security/spring-security-crypto/5.7.11/spring-security-crypto-5.7.11.pom
+[INFO] ------------------------------------------------------------------------
+[INFO] BUILD FAILURE
+[INFO] ------------------------------------------------------------------------
+[INFO] Total time:  4.812 s
+[INFO] Finished at: 2026-08-06T01:01:15+08:00
+[INFO] ------------------------------------------------------------------------
+[ERROR] Failed to execute goal on project cfc-backend: Could not collect dependencies for project com.etotem.cfc:cfc-backend:jar:1.0.0
+[ERROR] Failed to read artifact descriptor for org.springframework.security:spring-security-crypto:jar:5.7.11
+[ERROR] 	Caused by: The following artifacts could not be resolved: org.springframework.security:spring-security-crypto:pom:5.7.11 (absent): Could not transfer artifact org.springframework.security:spring-security-crypto:pom:5.7.11 from/to central (https://repo.maven.apache.org/maven2): sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
+[ERROR] 
+[ERROR] -> [Help 1]
+[ERROR] 
+[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
+[ERROR] Re-run Maven using the -X switch to enable full debug logging.
+[ERROR] 
+[ERROR] For more information about the errors and possible solutions, please read the following articles:
+[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/DependencyResolutionException