From 0418856ce339df231f847b6d0138c74ef80f9fa4 Mon Sep 17 00:00:00 2001 From: Codex Date: Mon, 14 Sep 2026 14:40:13 +0800 Subject: [PATCH] =?UTF-8?q?feat(phase-12):=20RelationshipStageService=20?= =?UTF-8?q?=E2=80=94=20home=20service=20suggestions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 12 Relationship — KEEP/EXTEND per JIRA. 不增加复杂状态. New RelationshipStageService (match module): P12-V11-T01 Successful match -> premarital_suggestion P12-V11-T02 GettingToKnow match -> matchmaker + counseling P12-V11-T03 7-day silence in GettingToKnow -> counseling_recommendation Rules are simple, based on existing Match.status + lastActivityAt: - successful -> 婚前辅导建议 - getting_to_know -> 红娘服务 + 婚恋咨询建议 - getting_to_know + 7d silence -> 婚恋咨询促活建议 - no Match -> 默认红娘 + 婚恋课堂 Integration point: HomeApplicationService.buildRecommendations() just inject RelationshipStageService and append suggestions to home DTO. --- .../service/RelationshipStageService.java | 112 ++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 backend/src/main/java/com/danyang/match/platform/match/service/RelationshipStageService.java diff --git a/backend/src/main/java/com/danyang/match/platform/match/service/RelationshipStageService.java b/backend/src/main/java/com/danyang/match/platform/match/service/RelationshipStageService.java new file mode 100644 index 0000000..51e4978 --- /dev/null +++ b/backend/src/main/java/com/danyang/match/platform/match/service/RelationshipStageService.java @@ -0,0 +1,112 @@ +package com.danyang.match.platform.match.service; + +import com.danyang.match.platform.match.entity.Match; +import com.danyang.match.platform.match.mapper.MatchMapper; +import com.danyang.match.platform.notification.service.NotificationService; +import com.danyang.match.platform.shared.constant.Constants; +import lombok.RequiredArgsConstructor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * 关系阶段服务建议 — Phase 12 + * + * 根据用户当前 Match 状态和互动情况,推荐相应的公益服务。 + * 不增加复杂状态 — 只根据现有 Match.lastActivityAt / status 做规则推断。 + * + * P12-V11-T01 Successful 首页服务建议 + * P12-V11-T02 GettingToKnow 服务建议规则 + * P12-V11-T03 Counseling recommendation rules + */ +@Service +@RequiredArgsConstructor +public class RelationshipStageService { + + private static final Logger log = LoggerFactory.getLogger(RelationshipStageService.class); + + /** Match 静默期阈值:多少天没互动 → 触发沉默服务建议 */ + private static final int SILENCE_DAYS_THRESHOLD = 7; + + private final MatchMapper matchMapper; + + // ==================== 首页服务建议 ==================== + + /** + * 首页服务建议(HomeApplicationService 调用) + * + * 返回结构:[{serviceType, reason, targetPage}] + * serviceType: counseling / premarital / matchmaker / content / anti_fraud / service_station + */ + public List getHomeServiceSuggestions(String userId) { + List suggestions = new ArrayList<>(); + + List activeMatches = matchMapper.findActiveByUser(userId); + for (Match match : activeMatches) { + // T01: successful Match → 婚前辅导 + if (Constants.MATCH_STATUS_SUCCESSFUL.equals(match.getStatus())) { + suggestions.add(new ServiceSuggestion( + "premarital", + "恭喜牵手成功!婚前辅导帮助你们更好地开始新生活。", + "/pages/premarital-intro/premarital-intro")); + } + + // T02: getting_to_know Match → 红娘服务 + 婚恋咨询 + if (Constants.MATCH_STATUS_GETTING_TO_KNOW.equals(match.getStatus())) { + // 有红娘建议优先展示 + suggestions.add(new ServiceSuggestion( + "matchmaker", + "婚恋红娘可以帮你们梳理交往节奏、解决初期困惑。", + "/pages/matchmaker/matchmaker")); + suggestions.add(new ServiceSuggestion( + "counseling", + "一对一婚恋咨询,帮助你们更好地了解彼此。", + "/pages/counseling-intro/counseling-intro")); + } + + // T03: getting_to_know 但长期沉默 → 心理咨询建议 + if (Constants.MATCH_STATUS_GETTING_TO_KNOW.equals(match.getStatus()) + && match.getLastActivityAt() != null + && match.getLastActivityAt().plus(SILENCE_DAYS_THRESHOLD, ChronoUnit.DAYS).isBefore(Instant.now())) { + suggestions.add(new ServiceSuggestion( + "counseling", + "你们已 7 天没有互动,婚恋咨询能帮你们重新找回话题。", + "/pages/counseling-intro/counseling-intro")); + } + } + + // 没有任何 Match → 常规建议 + if (activeMatches.isEmpty()) { + suggestions.add(new ServiceSuggestion( + "matchmaker", + "公益红娘可以帮你拓展优质择偶范围。", + "/pages/matchmaker/matchmaker")); + suggestions.add(new ServiceSuggestion( + "content", + "婚恋课堂专栏,学习科学的相处之道。", + "/pages/content/content")); + } + + return suggestions; + } + + /** 为首页返回 JSON-friendly 的简化版本 */ + public List> getHomeServiceSuggestionsSimple(String userId) { + return getHomeServiceSuggestions(userId).stream() + .map(s -> Map.of( + "serviceType", s.serviceType, + "reason", s.reason, + "targetPage", s.targetPage)) + .toList(); + } + + // ==================== DTO ==================== + + public record ServiceSuggestion(String serviceType, String reason, String targetPage) {} +}