|
@@ -0,0 +1,351 @@
|
|
|
|
|
+package com.etotem.num.controller;
|
|
|
|
|
+
|
|
|
|
|
+import com.etotem.num.common.Result;
|
|
|
|
|
+import com.etotem.num.entity.Relation;
|
|
|
|
|
+import com.etotem.num.entity.User;
|
|
|
|
|
+import com.etotem.num.repository.RelationRepository;
|
|
|
|
|
+import com.etotem.num.service.CalculatorService;
|
|
|
|
|
+import com.etotem.num.service.DifyService;
|
|
|
|
|
+import com.etotem.num.service.UserService;
|
|
|
|
|
+import com.google.gson.Gson;
|
|
|
|
|
+import org.springframework.web.bind.annotation.PostMapping;
|
|
|
|
|
+import org.springframework.web.bind.annotation.RequestBody;
|
|
|
|
|
+import org.springframework.web.bind.annotation.RequestMapping;
|
|
|
|
|
+import org.springframework.web.bind.annotation.RestController;
|
|
|
|
|
+
|
|
|
|
|
+import javax.servlet.http.HttpServletRequest;
|
|
|
|
|
+import java.time.LocalDate;
|
|
|
|
|
+import java.time.LocalDateTime;
|
|
|
|
|
+import java.util.HashMap;
|
|
|
|
|
+import java.util.Map;
|
|
|
|
|
+import java.util.Optional;
|
|
|
|
|
+
|
|
|
|
|
+@RestController
|
|
|
|
|
+@RequestMapping("/api/relation")
|
|
|
|
|
+public class RelationController {
|
|
|
|
|
+
|
|
|
|
|
+ private final CalculatorService calculatorService;
|
|
|
|
|
+ private final DifyService difyService;
|
|
|
|
|
+ private final UserService userService;
|
|
|
|
|
+ private final RelationRepository relationRepository;
|
|
|
|
|
+
|
|
|
|
|
+ public RelationController(CalculatorService calculatorService,
|
|
|
|
|
+ DifyService difyService,
|
|
|
|
|
+ UserService userService,
|
|
|
|
|
+ RelationRepository relationRepository) {
|
|
|
|
|
+ this.calculatorService = calculatorService;
|
|
|
|
|
+ this.difyService = difyService;
|
|
|
|
|
+ this.userService = userService;
|
|
|
|
|
+ this.relationRepository = relationRepository;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Get a single relation record by id.
|
|
|
|
|
+ */
|
|
|
|
|
+ @PostMapping("/get")
|
|
|
|
|
+ public Result<?> getRelation(HttpServletRequest request, @RequestBody Map<String, Object> body) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ Long userId = resolveUserId(request, body);
|
|
|
|
|
+ if (userId == null) {
|
|
|
|
|
+ return Result.error(1001, "请先登录");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Long id = getLong(body, "id");
|
|
|
|
|
+ if (id == null) {
|
|
|
|
|
+ return Result.error(1003, "id不能为空");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Optional<Relation> opt = relationRepository.findByIdAndUserId(id, userId);
|
|
|
|
|
+ if (!opt.isPresent()) {
|
|
|
|
|
+ return Result.error(1004, "关系记录不存在");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return Result.success(opt.get());
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ return Result.error(500, "获取关系记录失败: " + e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Create a new relation record.
|
|
|
|
|
+ */
|
|
|
|
|
+ @PostMapping("/create")
|
|
|
|
|
+ public Result<Relation> createRelation(HttpServletRequest request, @RequestBody Map<String, Object> body) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ Long userId = resolveUserId(request, body);
|
|
|
|
|
+ if (userId == null) {
|
|
|
|
|
+ return Result.error(1001, "请先登录");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Relation relation = new Relation();
|
|
|
|
|
+ relation.setUserId(userId);
|
|
|
|
|
+ relation.setRelationType(getString(body, "relationType"));
|
|
|
|
|
+ relation.setRelationTypeLabel(getString(body, "relationTypeLabel"));
|
|
|
|
|
+ relation.setName(getString(body, "name"));
|
|
|
|
|
+ relation.setBirthDateText(getString(body, "birthDateText"));
|
|
|
|
|
+ relation.setGender(getInteger(body, "gender", 0));
|
|
|
|
|
+ relation.setTags(getString(body, "tags"));
|
|
|
|
|
+ relation.setNote(getString(body, "note"));
|
|
|
|
|
+
|
|
|
|
|
+ String birthDateStr = getString(body, "birthDate");
|
|
|
|
|
+ if (birthDateStr != null && !birthDateStr.isEmpty()) {
|
|
|
|
|
+ relation.setBirthDate(LocalDate.parse(birthDateStr));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ LocalDateTime now = LocalDateTime.now();
|
|
|
|
|
+ relation.setCreateTime(now);
|
|
|
|
|
+ relation.setUpdateTime(now);
|
|
|
|
|
+
|
|
|
|
|
+ Relation saved = relationRepository.save(relation);
|
|
|
|
|
+ return Result.success(saved);
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ return Result.error(500, "创建关系记录失败: " + e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * List all relations for a user, ordered by create time descending.
|
|
|
|
|
+ */
|
|
|
|
|
+ @PostMapping("/list")
|
|
|
|
|
+ public Result<?> listRelations(HttpServletRequest request, @RequestBody Map<String, Object> body) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ Long userId = resolveUserId(request, body);
|
|
|
|
|
+ if (userId == null) {
|
|
|
|
|
+ return Result.error(1001, "请先登录");
|
|
|
|
|
+ }
|
|
|
|
|
+ return Result.success(relationRepository.findByUserIdOrderByCreateTimeDesc(userId));
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ return Result.error(500, "获取关系列表失败: " + e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Update an existing relation record.
|
|
|
|
|
+ */
|
|
|
|
|
+ @PostMapping("/update")
|
|
|
|
|
+ public Result<?> updateRelation(HttpServletRequest request, @RequestBody Map<String, Object> body) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ Long userId = resolveUserId(request, body);
|
|
|
|
|
+ if (userId == null) {
|
|
|
|
|
+ return Result.error(1001, "请先登录");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Long id = getLong(body, "id");
|
|
|
|
|
+ if (id == null) {
|
|
|
|
|
+ return Result.error(1003, "id不能为空");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Optional<Relation> opt = relationRepository.findByIdAndUserId(id, userId);
|
|
|
|
|
+ if (!opt.isPresent()) {
|
|
|
|
|
+ return Result.error(1004, "关系记录不存在");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Relation relation = opt.get();
|
|
|
|
|
+
|
|
|
|
|
+ if (body.containsKey("relationType")) {
|
|
|
|
|
+ relation.setRelationType(getString(body, "relationType"));
|
|
|
|
|
+ }
|
|
|
|
|
+ if (body.containsKey("relationTypeLabel")) {
|
|
|
|
|
+ relation.setRelationTypeLabel(getString(body, "relationTypeLabel"));
|
|
|
|
|
+ }
|
|
|
|
|
+ if (body.containsKey("name")) {
|
|
|
|
|
+ relation.setName(getString(body, "name"));
|
|
|
|
|
+ }
|
|
|
|
|
+ if (body.containsKey("birthDate") && body.get("birthDate") != null) {
|
|
|
|
|
+ relation.setBirthDate(LocalDate.parse(getString(body, "birthDate")));
|
|
|
|
|
+ }
|
|
|
|
|
+ if (body.containsKey("birthDateText")) {
|
|
|
|
|
+ relation.setBirthDateText(getString(body, "birthDateText"));
|
|
|
|
|
+ }
|
|
|
|
|
+ if (body.containsKey("gender")) {
|
|
|
|
|
+ relation.setGender(getInteger(body, "gender", 0));
|
|
|
|
|
+ }
|
|
|
|
|
+ if (body.containsKey("tags")) {
|
|
|
|
|
+ relation.setTags(getString(body, "tags"));
|
|
|
|
|
+ }
|
|
|
|
|
+ if (body.containsKey("note")) {
|
|
|
|
|
+ relation.setNote(getString(body, "note"));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ relation.setUpdateTime(LocalDateTime.now());
|
|
|
|
|
+
|
|
|
|
|
+ Relation saved = relationRepository.save(relation);
|
|
|
|
|
+ return Result.success(saved);
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ return Result.error(500, "更新关系记录失败: " + e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Delete a relation record by id and userId.
|
|
|
|
|
+ */
|
|
|
|
|
+ @PostMapping("/delete")
|
|
|
|
|
+ public Result<?> deleteRelation(HttpServletRequest request, @RequestBody Map<String, Object> body) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ Long userId = resolveUserId(request, body);
|
|
|
|
|
+ if (userId == null) {
|
|
|
|
|
+ return Result.error(1001, "请先登录");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Long id = getLong(body, "id");
|
|
|
|
|
+ if (id == null) {
|
|
|
|
|
+ return Result.error(1003, "id不能为空");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Optional<Relation> opt = relationRepository.findByIdAndUserId(id, userId);
|
|
|
|
|
+ if (!opt.isPresent()) {
|
|
|
|
|
+ return Result.error(1004, "关系记录不存在");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ relationRepository.delete(opt.get());
|
|
|
|
|
+ return Result.success("删除成功");
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ return Result.error(500, "删除关系记录失败: " + e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Compare the numerology charts of the user and a relation person.
|
|
|
|
|
+ */
|
|
|
|
|
+ @PostMapping("/compare")
|
|
|
|
|
+ public Result<?> compareCharts(HttpServletRequest request, @RequestBody Map<String, Object> body) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ Long userId = resolveUserId(request, body);
|
|
|
|
|
+ if (userId == null) {
|
|
|
|
|
+ return Result.error(1001, "请先登录");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Long relationId = getLong(body, "relationId");
|
|
|
|
|
+ if (relationId == null) {
|
|
|
|
|
+ return Result.error(1003, "relationId不能为空");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Optional<Relation> opt = relationRepository.findByIdAndUserId(relationId, userId);
|
|
|
|
|
+ if (!opt.isPresent()) {
|
|
|
|
|
+ return Result.error(1004, "关系记录不存在");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Relation relation = opt.get();
|
|
|
|
|
+ User user = userService.getById(userId);
|
|
|
|
|
+
|
|
|
|
|
+ // Calculate user chart
|
|
|
|
|
+ Map<String, Object> userChart = calculatorService.calculateFullTriangle(
|
|
|
|
|
+ user.getBirthYear(), user.getBirthMonth(), user.getBirthDay());
|
|
|
|
|
+
|
|
|
|
|
+ // Calculate relation person's chart
|
|
|
|
|
+ LocalDate relBirthDate = relation.getBirthDate();
|
|
|
|
|
+ if (relBirthDate == null) {
|
|
|
|
|
+ return Result.error(1005, "关系人的出生日期未设置");
|
|
|
|
|
+ }
|
|
|
|
|
+ Map<String, Object> relationChart = calculatorService.calculateFullTriangle(
|
|
|
|
|
+ relBirthDate.getYear(), relBirthDate.getMonthValue(), relBirthDate.getDayOfMonth());
|
|
|
|
|
+
|
|
|
|
|
+ Map<String, Object> result = new HashMap<>();
|
|
|
|
|
+ result.put("userChart", userChart);
|
|
|
|
|
+ result.put("relationChart", relationChart);
|
|
|
|
|
+ result.put("relationType", relation.getRelationType());
|
|
|
|
|
+ result.put("relationName", relation.getName());
|
|
|
|
|
+
|
|
|
|
|
+ return Result.success(result);
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ return Result.error(500, "对比能量盘失败: " + e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Compare charts and get an AI interpretation of the relationship.
|
|
|
|
|
+ */
|
|
|
|
|
+ @PostMapping("/compare/interpret")
|
|
|
|
|
+ public Result<?> interpretRelation(HttpServletRequest request, @RequestBody Map<String, Object> body) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ Long userId = resolveUserId(request, body);
|
|
|
|
|
+ if (userId == null) {
|
|
|
|
|
+ return Result.error(1001, "请先登录");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Long relationId = getLong(body, "relationId");
|
|
|
|
|
+ if (relationId == null) {
|
|
|
|
|
+ return Result.error(1003, "relationId不能为空");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Optional<Relation> opt = relationRepository.findByIdAndUserId(relationId, userId);
|
|
|
|
|
+ if (!opt.isPresent()) {
|
|
|
|
|
+ return Result.error(1004, "关系记录不存在");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Relation relation = opt.get();
|
|
|
|
|
+ User user = userService.getById(userId);
|
|
|
|
|
+
|
|
|
|
|
+ // Calculate user chart
|
|
|
|
|
+ Map<String, Object> userChart = calculatorService.calculateFullTriangle(
|
|
|
|
|
+ user.getBirthYear(), user.getBirthMonth(), user.getBirthDay());
|
|
|
|
|
+
|
|
|
|
|
+ // Calculate relation person's chart
|
|
|
|
|
+ LocalDate relBirthDate = relation.getBirthDate();
|
|
|
|
|
+ if (relBirthDate == null) {
|
|
|
|
|
+ return Result.error(1005, "关系人的出生日期未设置");
|
|
|
|
|
+ }
|
|
|
|
|
+ Map<String, Object> relationChart = calculatorService.calculateFullTriangle(
|
|
|
|
|
+ relBirthDate.getYear(), relBirthDate.getMonthValue(), relBirthDate.getDayOfMonth());
|
|
|
|
|
+
|
|
|
|
|
+ // Build inputs for Dify workflow: chart_context must be JSON strings
|
|
|
|
|
+ Gson gson = new Gson();
|
|
|
|
|
+ Map<String, Object> inputs = new HashMap<>();
|
|
|
|
|
+ inputs.put("chart_context_user1", gson.toJson(userChart));
|
|
|
|
|
+ inputs.put("chart_context_user2", gson.toJson(relationChart));
|
|
|
|
|
+ inputs.put("relation_type", relation.getRelationType());
|
|
|
|
|
+
|
|
|
|
|
+ String interpretation = difyService.invokeRelationWorkflow(inputs, userId.toString());
|
|
|
|
|
+
|
|
|
|
|
+ Map<String, Object> result = new HashMap<>();
|
|
|
|
|
+ result.put("interpretation", interpretation);
|
|
|
|
|
+ result.put("userChart", userChart);
|
|
|
|
|
+ result.put("relationChart", relationChart);
|
|
|
|
|
+
|
|
|
|
|
+ return Result.success(result);
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ return Result.error(500, "解读关系能量盘失败: " + e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ── Helper methods ──────────────────────────────────────────────────
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Resolve userId from the authenticated request or fallback to the request body.
|
|
|
|
|
+ * Priority: auth filter attribute > request body field.
|
|
|
|
|
+ */
|
|
|
|
|
+ private Long resolveUserId(HttpServletRequest request, Map<String, Object> body) {
|
|
|
|
|
+ Long authUserId = (Long) request.getAttribute("userId");
|
|
|
|
|
+ if (authUserId != null) {
|
|
|
|
|
+ return authUserId;
|
|
|
|
|
+ }
|
|
|
|
|
+ return getLong(body, "userId");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private String getString(Map<String, Object> map, String key) {
|
|
|
|
|
+ Object val = map.get(key);
|
|
|
|
|
+ return val != null ? val.toString() : null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private Integer getInteger(Map<String, Object> map, String key, Integer defaultValue) {
|
|
|
|
|
+ Object val = map.get(key);
|
|
|
|
|
+ if (val == null) return defaultValue;
|
|
|
|
|
+ if (val instanceof Number) return ((Number) val).intValue();
|
|
|
|
|
+ try {
|
|
|
|
|
+ return Integer.parseInt(val.toString());
|
|
|
|
|
+ } catch (NumberFormatException e) {
|
|
|
|
|
+ return defaultValue;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private Long getLong(Map<String, Object> map, String key) {
|
|
|
|
|
+ Object val = map.get(key);
|
|
|
|
|
+ if (val == null) return null;
|
|
|
|
|
+ if (val instanceof Number) return ((Number) val).longValue();
|
|
|
|
|
+ try {
|
|
|
|
|
+ return Long.parseLong(val.toString());
|
|
|
|
|
+ } catch (NumberFormatException e) {
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|