|
|
@@ -0,0 +1,658 @@
|
|
|
+package com.etotem.cfc.service;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.etotem.cfc.dto.*;
|
|
|
+import com.etotem.cfc.entity.*;
|
|
|
+import com.etotem.cfc.mapper.FamilyMemberMapper;
|
|
|
+import com.etotem.cfc.mapper.FamilyMapper;
|
|
|
+import com.etotem.cfc.mapper.ZodiacPairingMapper;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 家庭天盘服务
|
|
|
+ *
|
|
|
+ * 聚合家庭全景数据:成员、关系、年度能量、每日运势、相关事项
|
|
|
+ */
|
|
|
+@Service
|
|
|
+public class TianpanService {
|
|
|
+
|
|
|
+ private static final Logger log = LoggerFactory.getLogger(TianpanService.class);
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private CompatibilityService compatibilityService;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private ZodiacAnnualEnergyService zodiacAnnualEnergyService;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private RelationshipQualityService relationshipQualityService;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private TaskService taskService;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private AssessmentOrderService assessmentOrderService;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private EnergyService energyService;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private FamilyMemberAttributeService familyMemberAttributeService;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private FamilyMemberService familyMemberService;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private FamilyMemberMapper familyMemberMapper;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private FamilyMapper familyMapper;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private ZodiacPairingMapper zodiacPairingMapper;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构建家庭天盘仪表盘
|
|
|
+ *
|
|
|
+ * @param familyId 家庭 ID
|
|
|
+ * @param year 目标年份
|
|
|
+ * @param daysAhead 前瞻天数(用于相关事项)
|
|
|
+ * @param viewerRole 查看者角色 (parent/child/teacher/admin)
|
|
|
+ * @return 天盘仪表盘数据
|
|
|
+ */
|
|
|
+ public TianpanDashboardVO buildDashboard(Long familyId, Integer year, Integer daysAhead, String viewerRole) {
|
|
|
+ TianpanDashboardVO dashboard = new TianpanDashboardVO();
|
|
|
+
|
|
|
+ // 获取家庭信息
|
|
|
+ Family family = familyMapper.selectById(familyId);
|
|
|
+ if (family == null) {
|
|
|
+ return dashboard;
|
|
|
+ }
|
|
|
+ dashboard.setFamilyName(family.getName());
|
|
|
+
|
|
|
+ // 获取家庭成员
|
|
|
+ LambdaQueryWrapper<FamilyMember> memberWrapper = new LambdaQueryWrapper<>();
|
|
|
+ memberWrapper.eq(FamilyMember::getFamilyId, familyId);
|
|
|
+ List<FamilyMember> members = familyMemberMapper.selectList(memberWrapper);
|
|
|
+
|
|
|
+ // 构建成员传统数据
|
|
|
+ List<FamilyMemberTraditionVO> traditionList = new ArrayList<>();
|
|
|
+ for (FamilyMember member : members) {
|
|
|
+ FamilyMemberTraditionVO vo = buildMemberTradition(member);
|
|
|
+ traditionList.add(vo);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 增强成员信息(添加西方星座、头像、代际、颜色、生命数字等)
|
|
|
+ List<TianpanMemberVO> tianpanMembers = enrichMembers(traditionList, viewerRole);
|
|
|
+ dashboard.setMembers(tianpanMembers);
|
|
|
+
|
|
|
+ // 构建关系
|
|
|
+ List<RelationshipSummaryVO> relSummaries = new ArrayList<>();
|
|
|
+ for (int i = 0; i < traditionList.size(); i++) {
|
|
|
+ for (int j = i + 1; j < traditionList.size(); j++) {
|
|
|
+ RelationshipSummaryVO summary = computeRelationshipSummary(traditionList.get(i), traditionList.get(j));
|
|
|
+ relSummaries.add(summary);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ List<RelationshipVO> relationships = enrichRelationships(relSummaries);
|
|
|
+ dashboard.setRelationships(relationships);
|
|
|
+
|
|
|
+ // 家庭五行聚合
|
|
|
+ Map<String, Object> familyWuxing = aggregateFamilyWuxing(tianpanMembers);
|
|
|
+ dashboard.setFamilyWuxing(familyWuxing);
|
|
|
+
|
|
|
+ // 相关事项
|
|
|
+ RelatedItemsVO relatedItems = buildRelatedItems(familyId, daysAhead);
|
|
|
+ dashboard.setRelatedItems(relatedItems);
|
|
|
+
|
|
|
+ // 每日运势
|
|
|
+ DailyFortuneVO dailyFortune = buildDailyFortune(familyId);
|
|
|
+ dashboard.setDailyFortune(dailyFortune);
|
|
|
+
|
|
|
+ // 年度能量
|
|
|
+ List<MemberAnnualEnergyVO> annualEnergies = new ArrayList<>();
|
|
|
+ for (FamilyMemberTraditionVO m : traditionList) {
|
|
|
+ MemberAnnualEnergyVO energy = buildAnnualEnergy(m.getMemberId(), year);
|
|
|
+ if (energy != null && energy.getDimensions() != null) {
|
|
|
+ annualEnergies.add(energy);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ dashboard.setAnnualEnergies(annualEnergies);
|
|
|
+
|
|
|
+ return dashboard;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构建成员详情
|
|
|
+ *
|
|
|
+ * @param memberId 成员 ID
|
|
|
+ * @param memberType 成员类型 (parent/child)
|
|
|
+ * @param viewerRole 查看者角色
|
|
|
+ * @return 成员详情
|
|
|
+ */
|
|
|
+ public TianpanMemberVO buildMemberDetail(Long memberId, String memberType, String viewerRole) {
|
|
|
+ FamilyMember member = familyMemberMapper.selectById(memberId);
|
|
|
+ if (member == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ FamilyMemberTraditionVO tradition = buildMemberTradition(member);
|
|
|
+ List<FamilyMemberTraditionVO> list = Collections.singletonList(tradition);
|
|
|
+ List<TianpanMemberVO> enriched = enrichMembers(list, viewerRole);
|
|
|
+
|
|
|
+ return enriched.isEmpty() ? null : enriched.get(0);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 增强成员信息
|
|
|
+ *
|
|
|
+ * @param members 成员传统数据列表
|
|
|
+ * @param viewerRole 查看者角色
|
|
|
+ * @return 增强后的天盘成员列表
|
|
|
+ */
|
|
|
+ public List<TianpanMemberVO> enrichMembers(List<FamilyMemberTraditionVO> members, String viewerRole) {
|
|
|
+ List<TianpanMemberVO> result = new ArrayList<>();
|
|
|
+
|
|
|
+ for (FamilyMemberTraditionVO m : members) {
|
|
|
+ TianpanMemberVO vo = new TianpanMemberVO();
|
|
|
+ vo.setMemberId(m.getMemberId());
|
|
|
+ vo.setNickname(m.getNickname());
|
|
|
+ vo.setMemberType(m.getMemberType());
|
|
|
+ vo.setZodiac(m.getZodiac());
|
|
|
+ vo.setBloodType(m.getBloodType());
|
|
|
+ vo.setMindBaseScore(m.getMindBaseScore());
|
|
|
+ vo.setWisdomBaseScore(m.getWisdomBaseScore());
|
|
|
+
|
|
|
+ FamilyMemberAttributes attrs = familyMemberAttributeService.getByMember(m.getMemberId(), m.getMemberType());
|
|
|
+ if (attrs != null && attrs.getBirthDatetime() != null) {
|
|
|
+ Calendar cal = Calendar.getInstance();
|
|
|
+ cal.setTime(attrs.getBirthDatetime());
|
|
|
+ int birthMonth = cal.get(Calendar.MONTH) + 1;
|
|
|
+ int birthDay = cal.get(Calendar.DAY_OF_MONTH);
|
|
|
+ String westernSign = zodiacAnnualEnergyService.getWesternSign(birthMonth, birthDay);
|
|
|
+ vo.setWesternSign(westernSign);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 头像(使用默认头像)
|
|
|
+ vo.setAvatar("/default-avatar.png");
|
|
|
+
|
|
|
+ // 代际
|
|
|
+ vo.setGeneration(calculateGeneration(m.getMemberType()));
|
|
|
+
|
|
|
+ // 颜色
|
|
|
+ vo.setColorHex(getColorByRole(m.getMemberType()));
|
|
|
+
|
|
|
+ // 生命数字
|
|
|
+ if (m.getLifeNumber() != null) {
|
|
|
+ vo.setLifeNumber(m.getLifeNumber());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 能量快照
|
|
|
+ Map<String, Object> energySnapshot = energyService.getOverview(m.getMemberId());
|
|
|
+ vo.setEnergySnapshot(energySnapshot);
|
|
|
+
|
|
|
+ // 五行解读
|
|
|
+ vo.setWuxingReading(generateWuxingReading(m.getWuxingElements()));
|
|
|
+
|
|
|
+ // 八字符(根据 viewerRole 进行脱敏)
|
|
|
+ Map<String, String> eightCharacters = m.getEightCharacters();
|
|
|
+ if ("child".equals(viewerRole) && !"child".equals(m.getMemberType())) {
|
|
|
+ // 孩子视角查看其他成员:只显示年柱
|
|
|
+ eightCharacters = redactEightCharacters(eightCharacters);
|
|
|
+ }
|
|
|
+ vo.setEightCharacters(eightCharacters);
|
|
|
+
|
|
|
+ result.add(vo);
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 增强关系信息
|
|
|
+ *
|
|
|
+ * @param rels 关系摘要列表
|
|
|
+ * @return 增强后的关系列表
|
|
|
+ */
|
|
|
+ public List<RelationshipVO> enrichRelationships(List<RelationshipSummaryVO> rels) {
|
|
|
+ List<RelationshipVO> result = new ArrayList<>();
|
|
|
+
|
|
|
+ for (RelationshipSummaryVO r : rels) {
|
|
|
+ RelationshipVO vo = new RelationshipVO();
|
|
|
+ vo.setMemberId1(r.getMemberId1());
|
|
|
+ vo.setMemberId2(r.getMemberId2());
|
|
|
+ vo.setRelationType(r.getZodiacPairingType());
|
|
|
+ vo.setOverallScore(r.getOverallScore());
|
|
|
+
|
|
|
+ // 五行关系
|
|
|
+ vo.setWuxingRelation(generateWuxingRelation(r));
|
|
|
+
|
|
|
+ // 血型兼容性
|
|
|
+ vo.setBloodTypeCompatibility(r.getSummary());
|
|
|
+
|
|
|
+ result.add(vo);
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构建相关事项
|
|
|
+ *
|
|
|
+ * @param familyId 家庭 ID
|
|
|
+ * @param daysAhead 前瞻天数
|
|
|
+ * @return 相关事项
|
|
|
+ */
|
|
|
+ public RelatedItemsVO buildRelatedItems(Long familyId, Integer daysAhead) {
|
|
|
+ RelatedItemsVO vo = new RelatedItemsVO();
|
|
|
+
|
|
|
+ // 待办任务
|
|
|
+ List<Task> pendingTasks = taskService.getPendingTasksByFamily(familyId);
|
|
|
+ List<RelatedItemsVO.TaskItem> taskItems = pendingTasks.stream().limit(5).map(t -> {
|
|
|
+ RelatedItemsVO.TaskItem item = new RelatedItemsVO.TaskItem();
|
|
|
+ item.setId(t.getId());
|
|
|
+ item.setTitle(t.getTitle());
|
|
|
+ item.setAssignee(String.valueOf(t.getExecutorId()));
|
|
|
+ item.setDueDate(t.getDeadline() != null ? formatDateTime(t.getDeadline()) : null);
|
|
|
+ item.setStatus(t.getStatus());
|
|
|
+ return item;
|
|
|
+ }).collect(Collectors.toList());
|
|
|
+ vo.setPendingTasks(taskItems);
|
|
|
+
|
|
|
+ // 待处理测评
|
|
|
+ List<AssessmentOrder> pendingAssessments = assessmentOrderService.getPendingOrdersByFamily(familyId);
|
|
|
+ List<RelatedItemsVO.AssessmentItem> assessmentItems = pendingAssessments.stream().limit(3).map(o -> {
|
|
|
+ RelatedItemsVO.AssessmentItem item = new RelatedItemsVO.AssessmentItem();
|
|
|
+ item.setOrderId(o.getId());
|
|
|
+ item.setChildName(o.getPackageName());
|
|
|
+ item.setAppointmentDate(o.getCreatedAt() != null ? formatDateTime(o.getCreatedAt()) : null);
|
|
|
+ item.setStatus(o.getStatus());
|
|
|
+ return item;
|
|
|
+ }).collect(Collectors.toList());
|
|
|
+ vo.setPendingAssessments(assessmentItems);
|
|
|
+
|
|
|
+ // 健康预警
|
|
|
+ List<HealthAlertVO> healthAlerts = relationshipQualityService.getHealthAlerts(familyId);
|
|
|
+ List<RelatedItemsVO.HealthAlert> alertItems = healthAlerts.stream().limit(3).map(a -> {
|
|
|
+ RelatedItemsVO.HealthAlert item = new RelatedItemsVO.HealthAlert();
|
|
|
+ item.setId(a.getMemberId());
|
|
|
+ item.setMessage(a.getSuggestion());
|
|
|
+ item.setMembers(Collections.singletonList(a.getNickname()));
|
|
|
+ item.setSeverity(a.getAlertLevel());
|
|
|
+ return item;
|
|
|
+ }).collect(Collectors.toList());
|
|
|
+ vo.setHealthAlerts(alertItems);
|
|
|
+
|
|
|
+ // 即将到来的里程碑
|
|
|
+ List<MilestoneVO> milestones = relationshipQualityService.getMilestones(familyId, daysAhead);
|
|
|
+ List<RelatedItemsVO.Milestone> milestoneItems = milestones.stream().limit(5).map(m -> {
|
|
|
+ RelatedItemsVO.Milestone item = new RelatedItemsVO.Milestone();
|
|
|
+ item.setId(m.getMemberId());
|
|
|
+ item.setDescription(m.getEventName());
|
|
|
+ item.setTargetDate(formatDate(m.getEventDate()));
|
|
|
+ item.setDaysAway(m.getDaysAhead());
|
|
|
+ return item;
|
|
|
+ }).collect(Collectors.toList());
|
|
|
+ vo.setUpcomingMilestones(milestoneItems);
|
|
|
+
|
|
|
+ return vo;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构建年度能量
|
|
|
+ *
|
|
|
+ * @param memberId 成员 ID
|
|
|
+ * @param year 目标年份
|
|
|
+ * @return 年度能量
|
|
|
+ */
|
|
|
+ public MemberAnnualEnergyVO buildAnnualEnergy(Long memberId, Integer year) {
|
|
|
+ FamilyMember member = familyMemberMapper.selectById(memberId);
|
|
|
+ if (member == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ FamilyMemberAttributes attrs = familyMemberAttributeService.getByMember(memberId, "child");
|
|
|
+ if (attrs == null) {
|
|
|
+ attrs = familyMemberAttributeService.getByMember(memberId, "parent");
|
|
|
+ }
|
|
|
+ if (attrs == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取出生信息
|
|
|
+ Integer birthYear = null;
|
|
|
+ if (attrs.getBirthDatetime() != null) {
|
|
|
+ Calendar cal = Calendar.getInstance();
|
|
|
+ cal.setTime(attrs.getBirthDatetime());
|
|
|
+ birthYear = cal.get(Calendar.YEAR);
|
|
|
+ }
|
|
|
+ String zodiacCode = attrs.getZodiac();
|
|
|
+
|
|
|
+ if (birthYear == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 计算年度能量
|
|
|
+ ZodiacAnnualEnergyService.AnnualEnergyResult result =
|
|
|
+ zodiacAnnualEnergyService.calculate(birthYear, zodiacCode, year);
|
|
|
+
|
|
|
+ MemberAnnualEnergyVO vo = new MemberAnnualEnergyVO();
|
|
|
+ vo.setMemberId(memberId);
|
|
|
+ vo.setNickname(member.getNickname());
|
|
|
+ vo.setYear(year);
|
|
|
+ vo.setDimensions(result.toMap());
|
|
|
+ vo.setJupiterPhase(result.getJupiterPhase());
|
|
|
+ vo.setSaturnPhase(result.getSaturnPhase());
|
|
|
+
|
|
|
+ // 生成亮点
|
|
|
+ List<String> highlights = new ArrayList<>();
|
|
|
+ Map<String, Integer> dims = result.toMap();
|
|
|
+ if (dims.get("body") >= 70) {
|
|
|
+ highlights.add("身体健康能量充沛");
|
|
|
+ }
|
|
|
+ if (dims.get("mind") >= 70) {
|
|
|
+ highlights.add("心理能量饱满");
|
|
|
+ }
|
|
|
+ if (dims.get("wisdom") >= 70) {
|
|
|
+ highlights.add("智慧能量开启");
|
|
|
+ }
|
|
|
+ if (dims.get("action") >= 70) {
|
|
|
+ highlights.add("行动力强劲");
|
|
|
+ }
|
|
|
+ if (dims.get("wealth") >= 70) {
|
|
|
+ highlights.add("财富能量旺盛");
|
|
|
+ }
|
|
|
+ if ("benming".equals(result.getYearRelation())) {
|
|
|
+ highlights.add("本命年,稳中求进");
|
|
|
+ }
|
|
|
+ if ("liuhe".equals(result.getYearRelation())) {
|
|
|
+ highlights.add("六合吉年,贵人相助");
|
|
|
+ }
|
|
|
+ if ("chong".equals(result.getYearRelation())) {
|
|
|
+ highlights.add("冲太岁,注意调整");
|
|
|
+ }
|
|
|
+ vo.setHighlights(highlights);
|
|
|
+
|
|
|
+ return vo;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构建每日运势
|
|
|
+ *
|
|
|
+ * @param familyId 家庭 ID
|
|
|
+ * @return 每日运势
|
|
|
+ */
|
|
|
+ public DailyFortuneVO buildDailyFortune(Long familyId) {
|
|
|
+ DailyFortuneVO vo = new DailyFortuneVO();
|
|
|
+
|
|
|
+ Calendar cal = Calendar.getInstance();
|
|
|
+ vo.setDate(formatDate(cal.getTime()));
|
|
|
+ vo.setLunarDate("农历" + getLunarDate(cal.getTime()));
|
|
|
+ vo.setDayGanzhi(getDayGanzhi(cal.getTime()));
|
|
|
+
|
|
|
+ // 五行
|
|
|
+ DailyFortuneVO.FiveElementsVO fiveElements = new DailyFortuneVO.FiveElementsVO();
|
|
|
+ fiveElements.setMain(getDayElement(cal.getTime()));
|
|
|
+ fiveElements.setDetail(getDayElementDetail(cal.getTime()));
|
|
|
+ vo.setFiveElements(fiveElements);
|
|
|
+
|
|
|
+ // 吉凶
|
|
|
+ vo.setAuspicious(Arrays.asList("宜祭祀", "宜祈福", "宜聚会"));
|
|
|
+ vo.setInauspicious(Arrays.asList("忌远行", "忌动土"));
|
|
|
+
|
|
|
+ // 家庭建议
|
|
|
+ vo.setFamilyAdvice("今日家庭能量和谐,适合安排家庭活动");
|
|
|
+
|
|
|
+ // 焦点成员提示
|
|
|
+ DailyFortuneVO.FocusMemberTip focus = new DailyFortuneVO.FocusMemberTip();
|
|
|
+ focus.setName("家庭中最活跃的成员");
|
|
|
+ focus.setTip("多倾听他的想法");
|
|
|
+ focus.setWuxingTip("木能量旺盛,注意平衡");
|
|
|
+ vo.setFocusMember(focus);
|
|
|
+
|
|
|
+ return vo;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 计算兼容性(Controller 调用入口)
|
|
|
+ */
|
|
|
+ public CompatibilityResultVO computeCompatibility(Long member1Id, String memberType1, Long member2Id, String memberType2) {
|
|
|
+ return compatibilityService.computeCompatibility(member1Id, memberType1, member2Id, memberType2);
|
|
|
+ }
|
|
|
+
|
|
|
+ // ========== 内部辅助方法 ==========
|
|
|
+
|
|
|
+ private FamilyMemberTraditionVO buildMemberTradition(FamilyMember member) {
|
|
|
+ FamilyMemberTraditionVO vo = new FamilyMemberTraditionVO();
|
|
|
+ vo.setMemberId(member.getId());
|
|
|
+ vo.setNickname(member.getNickname());
|
|
|
+ vo.setMemberType("child");
|
|
|
+
|
|
|
+ FamilyMemberAttributes attrs = familyMemberAttributeService.getByMember(member.getId(), "child");
|
|
|
+ if (attrs == null) {
|
|
|
+ attrs = familyMemberAttributeService.getByMember(member.getId(), "parent");
|
|
|
+ if (attrs != null) vo.setMemberType("parent");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (attrs != null) {
|
|
|
+ vo.setZodiac(attrs.getZodiac());
|
|
|
+ vo.setBloodType(attrs.getBloodType());
|
|
|
+ vo.setMindBaseScore(attrs.getMindBaseScore());
|
|
|
+ vo.setWisdomBaseScore(attrs.getWisdomBaseScore());
|
|
|
+ vo.setEightCharacters(parseJsonToMap(attrs.getEightCharacters()));
|
|
|
+ vo.setWuxingElements(parseWuxingMap(attrs.getWuxingElements()));
|
|
|
+ vo.setLifeNumber(extractLifeNumber(attrs.getBehaviorModifier()));
|
|
|
+ }
|
|
|
+ return vo;
|
|
|
+ }
|
|
|
+
|
|
|
+ private Map<String, Object> aggregateFamilyWuxing(List<TianpanMemberVO> members) {
|
|
|
+ Map<String, Object> result = new LinkedHashMap<>();
|
|
|
+ Map<String, Integer> totals = new LinkedHashMap<>();
|
|
|
+ for (String elem : Arrays.asList("wood", "fire", "earth", "metal", "water")) {
|
|
|
+ totals.put(elem, 0);
|
|
|
+ }
|
|
|
+ int count = 0;
|
|
|
+
|
|
|
+ for (TianpanMemberVO m : members) {
|
|
|
+ if (m.getWuxingElements() != null) {
|
|
|
+ count++;
|
|
|
+ for (String elem : totals.keySet()) {
|
|
|
+ totals.put(elem, totals.get(elem) + m.getWuxingElements().getOrDefault(elem, 0));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ Map<String, Integer> pctMap = new LinkedHashMap<>();
|
|
|
+ String strongest = null;
|
|
|
+ int maxPct = 0;
|
|
|
+ int totalAll = count * 100;
|
|
|
+
|
|
|
+ for (String elem : totals.keySet()) {
|
|
|
+ int val = count > 0 ? (totals.get(elem) * 100 / totalAll) * 5 : 0; // 简化计算
|
|
|
+ pctMap.put(elem, val);
|
|
|
+ if (val > maxPct) {
|
|
|
+ maxPct = val;
|
|
|
+ strongest = elem;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ result.put("strongestElement", strongest);
|
|
|
+ result.put("elements", pctMap);
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ private RelationshipSummaryVO computeRelationshipSummary(FamilyMemberTraditionVO m1, FamilyMemberTraditionVO m2) {
|
|
|
+ RelationshipSummaryVO summary = new RelationshipSummaryVO();
|
|
|
+ summary.setMemberId1(m1.getMemberId());
|
|
|
+ summary.setNickname1(m1.getNickname());
|
|
|
+ summary.setMemberId2(m2.getMemberId());
|
|
|
+ summary.setNickname2(m2.getNickname());
|
|
|
+
|
|
|
+ // 快速生肖查询
|
|
|
+ int zodiacScore = 50;
|
|
|
+ String pairingType = "ping";
|
|
|
+ if (m1.getZodiac() != null && m2.getZodiac() != null) {
|
|
|
+ LambdaQueryWrapper<ZodiacPairing> qw = new LambdaQueryWrapper<>();
|
|
|
+ qw.eq(ZodiacPairing::getZodiacCode1, m1.getZodiac());
|
|
|
+ qw.eq(ZodiacPairing::getZodiacCode2, m2.getZodiac());
|
|
|
+ ZodiacPairing p = zodiacPairingMapper.selectOne(qw);
|
|
|
+ if (p == null) {
|
|
|
+ LambdaQueryWrapper<ZodiacPairing> rqw = new LambdaQueryWrapper<>();
|
|
|
+ rqw.eq(ZodiacPairing::getZodiacCode1, m2.getZodiac());
|
|
|
+ rqw.eq(ZodiacPairing::getZodiacCode2, m1.getZodiac());
|
|
|
+ p = zodiacPairingMapper.selectOne(rqw);
|
|
|
+ }
|
|
|
+ if (p != null) {
|
|
|
+ zodiacScore = p.getCompatibilityScore();
|
|
|
+ pairingType = p.getPairingType();
|
|
|
+ summary.setSummary(p.getDescription());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ summary.setZodiacScore(zodiacScore);
|
|
|
+ summary.setZodiacPairingType(pairingType);
|
|
|
+
|
|
|
+ // 整体评分
|
|
|
+ int overall = zodiacScore;
|
|
|
+ summary.setOverallScore(overall);
|
|
|
+
|
|
|
+ return summary;
|
|
|
+ }
|
|
|
+
|
|
|
+ private String generateWuxingRelation(RelationshipSummaryVO r) {
|
|
|
+ switch (r.getZodiacPairingType()) {
|
|
|
+ case "li": return "相合关系,彼此吸引";
|
|
|
+ case "chong": return "相冲关系,需要磨合";
|
|
|
+ case "hai": return "相害关系,注意包容";
|
|
|
+ case "sanhe": return "三合关系,默契十足";
|
|
|
+ default: return "平和关系,相安无事";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private String getColorByRole(String role) {
|
|
|
+ switch (role) {
|
|
|
+ case "parent": return "#4A9BD7";
|
|
|
+ case "child": return "#FF8C42";
|
|
|
+ case "teacher": return "#6366F1";
|
|
|
+ default: return "#9CA3AF";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private String calculateGeneration(String role) {
|
|
|
+ return "parent".equals(role) ? "父辈" : "子辈";
|
|
|
+ }
|
|
|
+
|
|
|
+ private String generateWuxingReading(Map<String, Integer> elements) {
|
|
|
+ if (elements == null || elements.isEmpty()) {
|
|
|
+ return "五行数据待完善";
|
|
|
+ }
|
|
|
+ String maxElem = null;
|
|
|
+ int maxVal = 0;
|
|
|
+ for (Map.Entry<String, Integer> e : elements.entrySet()) {
|
|
|
+ if (e.getValue() > maxVal) {
|
|
|
+ maxVal = e.getValue();
|
|
|
+ maxElem = e.getKey();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (maxElem == null) return "五行均衡";
|
|
|
+ switch (maxElem) {
|
|
|
+ case "wood": return "木能量最强,富有创造力";
|
|
|
+ case "fire": return "火能量最强,热情洋溢";
|
|
|
+ case "earth": return "土能量最强,稳重可靠";
|
|
|
+ case "metal": return "金能量最强,思维清晰";
|
|
|
+ case "water": return "水能量最强,内心丰富";
|
|
|
+ default: return "五行均衡";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private Map<String, String> redactEightCharacters(Map<String, String> eightCharacters) {
|
|
|
+ if (eightCharacters == null) return null;
|
|
|
+ Map<String, String> redacted = new LinkedHashMap<>();
|
|
|
+ redacted.put("year", eightCharacters.get("year"));
|
|
|
+ // month/day/hour 设为 null
|
|
|
+ return redacted;
|
|
|
+ }
|
|
|
+
|
|
|
+ private ZodiacAnnualEnergyService.AnnualEnergyResult emptyEnergyResult() {
|
|
|
+ ZodiacAnnualEnergyService.AnnualEnergyResult r = new ZodiacAnnualEnergyService.AnnualEnergyResult();
|
|
|
+ r.setBody(0); r.setMind(0); r.setWisdom(0); r.setAction(0); r.setWealth(0);
|
|
|
+ return r;
|
|
|
+ }
|
|
|
+
|
|
|
+ private Map<String, Integer> parseWuxingMap(String json) {
|
|
|
+ Map<String, Integer> result = new LinkedHashMap<>();
|
|
|
+ if (json == null || json.isEmpty()) return result;
|
|
|
+ try {
|
|
|
+ Map<String, Object> raw = familyMemberAttributeService.fromJson(json);
|
|
|
+ for (String elem : Arrays.asList("wood", "fire", "earth", "metal", "water")) {
|
|
|
+ Object val = raw.get(elem);
|
|
|
+ if (val instanceof Number) {
|
|
|
+ result.put(elem, ((Number) val).intValue());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception ignored) {}
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ private Map<String, String> parseJsonToMap(String json) {
|
|
|
+ Map<String, String> result = new LinkedHashMap<>();
|
|
|
+ if (json == null || json.isEmpty()) return result;
|
|
|
+ try {
|
|
|
+ Map<String, Object> raw = familyMemberAttributeService.fromJson(json);
|
|
|
+ for (Map.Entry<String, Object> entry : raw.entrySet()) {
|
|
|
+ result.put(entry.getKey(), String.valueOf(entry.getValue()));
|
|
|
+ }
|
|
|
+ } catch (Exception ignored) {}
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ private Integer extractLifeNumber(String behaviorModifier) {
|
|
|
+ if (behaviorModifier == null || behaviorModifier.isEmpty()) return null;
|
|
|
+ try {
|
|
|
+ Map<String, Object> map = familyMemberAttributeService.fromJson(behaviorModifier);
|
|
|
+ Object ln = map.get("lifeNumber");
|
|
|
+ if (ln instanceof Number) {
|
|
|
+ return ((Number) ln).intValue();
|
|
|
+ }
|
|
|
+ } catch (Exception ignored) {}
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ private String formatDate(Date date) {
|
|
|
+ if (date == null) return null;
|
|
|
+ Calendar cal = Calendar.getInstance();
|
|
|
+ cal.setTime(date);
|
|
|
+ return String.format("%d-%02d-%02d", cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DAY_OF_MONTH));
|
|
|
+ }
|
|
|
+
|
|
|
+ private String formatDateTime(Date date) {
|
|
|
+ if (date == null) return null;
|
|
|
+ return formatDate(date);
|
|
|
+ }
|
|
|
+
|
|
|
+ private String getLunarDate(Date date) {
|
|
|
+ // 简化,实际应使用农历库
|
|
|
+ return "初一";
|
|
|
+ }
|
|
|
+
|
|
|
+ private String getDayGanzhi(Date date) {
|
|
|
+ // 简化,实际应使用干支计算
|
|
|
+ return "甲子";
|
|
|
+ }
|
|
|
+
|
|
|
+ private String getDayElement(Date date) {
|
|
|
+ return "木";
|
|
|
+ }
|
|
|
+
|
|
|
+ private String getDayElementDetail(Date date) {
|
|
|
+ return "甲木参天";
|
|
|
+ }
|
|
|
+}
|