diff --git a/pom.xml b/pom.xml
index b09f9ae..40d0759 100644
--- a/pom.xml
+++ b/pom.xml
@@ -106,6 +106,23 @@
okhttp
4.9.3
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+
+ mysql
+ mysql-connector-java
+ 8.0.33
+
+
+
+ com.h2database
+ h2
+ runtime
+
diff --git a/src/main/java/xuan/controller/BaZiController.java b/src/main/java/xuan/controller/BaZiController.java
index 6e77653..452632b 100644
--- a/src/main/java/xuan/controller/BaZiController.java
+++ b/src/main/java/xuan/controller/BaZiController.java
@@ -1,12 +1,16 @@
package xuan.controller;
+import com.alibaba.fastjson.JSON;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import xuan.core.bazi.BaZi;
import xuan.core.bazi.settings.BaZiJiChuSetting;
import xuan.core.bazi.settings.BaZiShenShaSetting;
import xuan.core.bazi.settings.BaZiGanZhiLiuYiSetting;
+import xuan.entity.DeductRecord;
import xuan.service.HunYuanAiService;
import xuan.service.PromptTemplates;
+import xuan.service.DeductRecordService;
import java.util.HashMap;
import java.util.Map;
@@ -16,6 +20,9 @@ import java.util.Map;
public class BaZiController {
private final HunYuanAiService aiService = new HunYuanAiService();
+
+ @Autowired
+ private DeductRecordService recordService;
@PostMapping("/paipan")
public Map paiPan(@RequestBody BaZiRequest request) {
@@ -49,6 +56,20 @@ public class BaZiController {
);
data.put("aiAnalysis", aiAnalysis);
+ DeductRecord record = new DeductRecord();
+ record.setUserId(request.getUserId() != null ? request.getUserId() : "default_user");
+ record.setType("bazi");
+ record.setName(request.getName() != null ? request.getName() : "某人");
+ record.setOccupy(request.getOccupy());
+ record.setSex(request.getSex());
+ record.setInputDate(request.getDate());
+ record.setInputData(JSON.toJSONString(request));
+ record.setResultData(JSON.toJSONString(data));
+ record.setAiAnalysis(aiAnalysis);
+ recordService.saveRecord(record);
+
+ data.put("recordId", record.getId());
+
result.put("success", true);
result.put("data", data);
} catch (Exception e) {
@@ -94,6 +115,7 @@ public class BaZiController {
}
public static class BaZiRequest {
+ private String userId;
private String name;
private String occupy;
private Integer sex;
@@ -109,6 +131,8 @@ public class BaZiController {
private Integer monthGanZhiType;
private Integer dayGanZhiType;
+ public String getUserId() { return userId; }
+ public void setUserId(String userId) { this.userId = userId; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getOccupy() { return occupy; }
diff --git a/src/main/java/xuan/controller/RecordController.java b/src/main/java/xuan/controller/RecordController.java
new file mode 100644
index 0000000..d435853
--- /dev/null
+++ b/src/main/java/xuan/controller/RecordController.java
@@ -0,0 +1,110 @@
+package xuan.controller;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import xuan.entity.DeductRecord;
+import xuan.service.DeductRecordService;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+@RestController
+@RequestMapping("/api/records")
+public class RecordController {
+
+ @Autowired
+ private DeductRecordService recordService;
+
+ @GetMapping("/list")
+ public Map getRecords(@RequestParam String userId) {
+ Map result = new HashMap<>();
+ try {
+ List records = recordService.findByUserId(userId);
+ result.put("success", true);
+ result.put("data", records);
+ } catch (Exception e) {
+ result.put("success", false);
+ result.put("error", e.getMessage());
+ }
+ return result;
+ }
+
+ @GetMapping("/recent")
+ public Map getRecentRecords(@RequestParam String userId) {
+ Map result = new HashMap<>();
+ try {
+ List records = recordService.findRecentByUserId(userId);
+ result.put("success", true);
+ result.put("data", records);
+ } catch (Exception e) {
+ result.put("success", false);
+ result.put("error", e.getMessage());
+ }
+ return result;
+ }
+
+ @GetMapping("/type")
+ public Map getRecordsByType(
+ @RequestParam String userId,
+ @RequestParam String type) {
+ Map result = new HashMap<>();
+ try {
+ List records = recordService.findByUserIdAndType(userId, type);
+ result.put("success", true);
+ result.put("data", records);
+ } catch (Exception e) {
+ result.put("success", false);
+ result.put("error", e.getMessage());
+ }
+ return result;
+ }
+
+ @GetMapping("/detail")
+ public Map getRecordDetail(@RequestParam Long id) {
+ Map result = new HashMap<>();
+ try {
+ Optional record = recordService.findById(id);
+ if (record.isPresent()) {
+ result.put("success", true);
+ result.put("data", record.get());
+ } else {
+ result.put("success", false);
+ result.put("error", "记录不存在");
+ }
+ } catch (Exception e) {
+ result.put("success", false);
+ result.put("error", e.getMessage());
+ }
+ return result;
+ }
+
+ @DeleteMapping("/delete")
+ public Map deleteRecord(@RequestParam Long id) {
+ Map result = new HashMap<>();
+ try {
+ recordService.deleteById(id);
+ result.put("success", true);
+ result.put("message", "删除成功");
+ } catch (Exception e) {
+ result.put("success", false);
+ result.put("error", e.getMessage());
+ }
+ return result;
+ }
+
+ @DeleteMapping("/clear")
+ public Map clearRecords(@RequestParam String userId) {
+ Map result = new HashMap<>();
+ try {
+ recordService.deleteByUserId(userId);
+ result.put("success", true);
+ result.put("message", "清空成功");
+ } catch (Exception e) {
+ result.put("success", false);
+ result.put("error", e.getMessage());
+ }
+ return result;
+ }
+}
diff --git a/src/main/java/xuan/entity/DeductRecord.java b/src/main/java/xuan/entity/DeductRecord.java
new file mode 100644
index 0000000..f7dbeea
--- /dev/null
+++ b/src/main/java/xuan/entity/DeductRecord.java
@@ -0,0 +1,90 @@
+package xuan.entity;
+
+import javax.persistence.*;
+import java.time.LocalDateTime;
+
+@Entity
+@Table(name = "deduct_record")
+public class DeductRecord {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ @Column(nullable = false)
+ private String userId;
+
+ @Column(nullable = false)
+ private String type;
+
+ @Column(nullable = false)
+ private String name;
+
+ private String occupy;
+
+ private Integer sex;
+
+ @Column(nullable = false)
+ private String inputDate;
+
+ @Column(columnDefinition = "TEXT")
+ private String inputData;
+
+ @Column(columnDefinition = "TEXT")
+ private String resultData;
+
+ @Column(columnDefinition = "TEXT")
+ private String aiAnalysis;
+
+ @Column(nullable = false, updatable = false)
+ private LocalDateTime createTime;
+
+ private LocalDateTime updateTime;
+
+ @PrePersist
+ protected void onCreate() {
+ createTime = LocalDateTime.now();
+ updateTime = createTime;
+ }
+
+ @PreUpdate
+ protected void onUpdate() {
+ updateTime = LocalDateTime.now();
+ }
+
+ public Long getId() { return id; }
+ public void setId(Long id) { this.id = id; }
+
+ public String getUserId() { return userId; }
+ public void setUserId(String userId) { this.userId = userId; }
+
+ public String getType() { return type; }
+ public void setType(String type) { this.type = type; }
+
+ public String getName() { return name; }
+ public void setName(String name) { this.name = name; }
+
+ public String getOccupy() { return occupy; }
+ public void setOccupy(String occupy) { this.occupy = occupy; }
+
+ public Integer getSex() { return sex; }
+ public void setSex(Integer sex) { this.sex = sex; }
+
+ public String getInputDate() { return inputDate; }
+ public void setInputDate(String inputDate) { this.inputDate = inputDate; }
+
+ public String getInputData() { return inputData; }
+ public void setInputData(String inputData) { this.inputData = inputData; }
+
+ public String getResultData() { return resultData; }
+ public void setResultData(String resultData) { this.resultData = resultData; }
+
+ public String getAiAnalysis() { return aiAnalysis; }
+ public void setAiAnalysis(String aiAnalysis) { this.aiAnalysis = aiAnalysis; }
+
+ public LocalDateTime getCreateTime() { return createTime; }
+ public void setCreateTime(LocalDateTime createTime) { this.createTime = createTime; }
+
+ public LocalDateTime getUpdateTime() { return updateTime; }
+ public void setUpdateTime(LocalDateTime updateTime) { this.updateTime = updateTime; }
+}
diff --git a/src/main/java/xuan/repository/DeductRecordRepository.java b/src/main/java/xuan/repository/DeductRecordRepository.java
new file mode 100644
index 0000000..01fcbac
--- /dev/null
+++ b/src/main/java/xuan/repository/DeductRecordRepository.java
@@ -0,0 +1,20 @@
+package xuan.repository;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+import xuan.entity.DeductRecord;
+
+import java.util.List;
+
+@Repository
+public interface DeductRecordRepository extends JpaRepository {
+
+ List findByUserIdOrderByCreateTimeDesc(String userId);
+
+ List findByUserIdAndTypeOrderByCreateTimeDesc(String userId, String type);
+
+ @Query("SELECT d FROM DeductRecord d WHERE d.userId = :userId ORDER BY d.createTime DESC LIMIT 10")
+ List findTop10ByUserIdOrderByCreateTimeDesc(@Param("userId") String userId);
+}
diff --git a/src/main/java/xuan/service/DeductRecordService.java b/src/main/java/xuan/service/DeductRecordService.java
new file mode 100644
index 0000000..c87ed99
--- /dev/null
+++ b/src/main/java/xuan/service/DeductRecordService.java
@@ -0,0 +1,49 @@
+package xuan.service;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import xuan.entity.DeductRecord;
+import xuan.repository.DeductRecordRepository;
+
+import java.util.List;
+import java.util.Optional;
+
+@Service
+public class DeductRecordService {
+
+ @Autowired
+ private DeductRecordRepository recordRepository;
+
+ @Transactional
+ public DeductRecord saveRecord(DeductRecord record) {
+ return recordRepository.save(record);
+ }
+
+ public Optional findById(Long id) {
+ return recordRepository.findById(id);
+ }
+
+ public List findByUserId(String userId) {
+ return recordRepository.findByUserIdOrderByCreateTimeDesc(userId);
+ }
+
+ public List findByUserIdAndType(String userId, String type) {
+ return recordRepository.findByUserIdAndTypeOrderByCreateTimeDesc(userId, type);
+ }
+
+ public List findRecentByUserId(String userId) {
+ return recordRepository.findTop10ByUserIdOrderByCreateTimeDesc(userId);
+ }
+
+ @Transactional
+ public void deleteById(Long id) {
+ recordRepository.deleteById(id);
+ }
+
+ @Transactional
+ public void deleteByUserId(String userId) {
+ List records = recordRepository.findByUserIdOrderByCreateTimeDesc(userId);
+ recordRepository.deleteAll(records);
+ }
+}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index c171ed7..d9ee046 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -1,2 +1,30 @@
server.port=8080
spring.application.name=xuan-utils-pro
+
+# H2 Database Configuration (Development)
+spring.datasource.url=jdbc:h2:file:./data/xuan;DB_CLOSE_ON_EXIT=FALSE;AUTO_RECONNECT=TRUE
+spring.datasource.driverClassName=org.h2.Driver
+spring.datasource.username=sa
+spring.datasource.password=
+
+# JPA Configuration
+spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
+spring.jpa.hibernate.ddl-auto=update
+spring.jpa.show-sql=true
+spring.jpa.properties.hibernate.format_sql=true
+
+# H2 Console (Development only)
+spring.h2.console.enabled=true
+spring.h2.console.path=/h2-console
+
+# MySQL Configuration (Production - uncomment when needed)
+#spring.datasource.url=jdbc:mysql://localhost:3306/xuan_deduct?useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8
+#spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
+#spring.datasource.username=root
+#spring.datasource.password=your_password
+#spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect
+#spring.jpa.hibernate.ddl-auto=update
+
+# Logging
+logging.level.xuan=DEBUG
+logging.level.org.hibernate.SQL=DEBUG