diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml
index c92fd3c..7b02e21 100644
--- a/.idea/dataSources.xml
+++ b/.idea/dataSources.xml
@@ -14,5 +14,19 @@
$ProjectFileDir$
+
+ mysql.8
+ true
+ true
+ $PROJECT_DIR$/System/src/main/resources/application.yml
+ com.mysql.cj.jdbc.Driver
+ jdbc:mysql://110.40.62.21:3306/jingsaisystem?useSSL=false&serverTimezone=UTC
+
+
+
+
+
+ $ProjectFileDir$
+
\ No newline at end of file
diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml
new file mode 100644
index 0000000..2b63946
--- /dev/null
+++ b/.idea/uiDesigner.xml
@@ -0,0 +1,124 @@
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+
\ No newline at end of file
diff --git a/System/pom.xml b/System/pom.xml
index bea4f41..7c009cd 100644
--- a/System/pom.xml
+++ b/System/pom.xml
@@ -30,6 +30,11 @@
lombok
true
+
+ org.apache.commons
+ commons-lang3
+ 3.12.0
+
org.springframework.boot
spring-boot-starter-test
diff --git a/System/src/main/java/com/example/system/common/AiPost.java b/System/src/main/java/com/example/system/common/AiPost.java
new file mode 100644
index 0000000..f410fa1
--- /dev/null
+++ b/System/src/main/java/com/example/system/common/AiPost.java
@@ -0,0 +1,80 @@
+package com.example.system.common;
+
+import cn.hutool.http.HttpRequest;
+import cn.hutool.http.HttpResponse;
+import cn.hutool.json.JSONArray;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import org.springframework.stereotype.Component;
+
+@Component
+public class AiPost {
+
+ private static final String baseUrl = "https://openai.933999.xyz";
+ private static final String apiKey = "sk-1PBIyxIdJ42yyC11XRNqbEXYDt2eZRNVNbd8XxmKjnPXGh5S";
+ private static final String model = "gpt-4o-mini";
+
+ /**
+ * 发送消息并获取AI响应
+ * @param message 用户消息
+ * @param maxTokens 最大token数
+ * @return AI响应内容
+ * @throws Exception 发送请求异常
+ */
+ public String sendMessageAndGetResponse(String message, int maxTokens) throws Exception {
+ // 构造 messages 数组
+ JSONArray messagesArray = new JSONArray();
+ JSONObject userMessage = new JSONObject();
+ userMessage.put("role", "user");
+ userMessage.put("content", message);
+ messagesArray.add(userMessage);
+
+ // 构造请求体
+ JSONObject requestBody = new JSONObject();
+ requestBody.put("model", model);
+ requestBody.put("messages", messagesArray);
+// requestBody.put("max_tokens", maxTokens);
+// requestBody.put("temperature", 0.2); // 更稳定输出
+
+ // 打印请求体
+ System.out.println("请求地址:" + baseUrl + "/v1/chat/completions");
+ System.out.println("请求体:" + requestBody.toStringPretty());
+
+ try {
+ HttpResponse response = HttpRequest.post(baseUrl + "/v1/chat/completions")
+ .timeout(60_000) // 60秒超时
+ .header("Authorization", "Bearer " + apiKey)
+ .header("Content-Type", "application/json")
+ .body(requestBody.toString())
+ .execute();
+
+ String responseText = response.body();
+
+ System.out.println("响应状态码:" + response.getStatus());
+ System.out.println("响应内容:" + responseText);
+
+ if (response.getStatus() != 200) {
+ throw new RuntimeException("AI服务请求失败:" + responseText);
+ }
+
+ // 安全解析响应
+ if (!JSONUtil.isJsonObj(responseText)) {
+ throw new RuntimeException("返回不是合法JSON:" + responseText);
+ }
+
+ JSONObject responseJson = JSONUtil.parseObj(responseText);
+ JSONArray choices = responseJson.getJSONArray("choices");
+
+ if (choices == null || choices.isEmpty()) {
+ throw new RuntimeException("AI响应为空:" + responseText);
+ }
+
+ JSONObject messageObj = choices.getJSONObject(0).getJSONObject("message");
+ return messageObj.getStr("content");
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new RuntimeException("调用AI接口发生错误", e);
+ }
+ }
+}
+
diff --git a/System/src/main/java/com/example/system/common/Chart.java b/System/src/main/java/com/example/system/common/Chart.java
new file mode 100644
index 0000000..2c0b026
--- /dev/null
+++ b/System/src/main/java/com/example/system/common/Chart.java
@@ -0,0 +1,59 @@
+package com.example.system.common;
+
+import lombok.Data;
+
+/**
+ * 图表实体类
+ */
+@Data
+public class Chart {
+ /**
+ * 主键
+ */
+ private String id;
+
+ /**
+ * 图表名称
+ */
+ private String name;
+
+ /**
+ * 分析目标
+ */
+ private String goal;
+
+ /**
+ * 图表数据(CSV格式)
+ */
+ private String chartData;
+
+ /**
+ * 图表类型
+ */
+ private String chartType;
+
+ /**
+ * 生成的图表配置(Echarts JSON配置)
+ */
+ private String genChart;
+
+ /**
+ * 生成的分析结论
+ */
+ private String genResult;
+
+ /**
+ * 创建人ID
+ */
+ private Long adminId;
+
+ /**
+ * 创建时间
+ */
+ private Long createTime;
+
+ /**
+ * 更新时间
+ */
+ private Long updateTime;
+}
\ No newline at end of file
diff --git a/System/src/main/java/com/example/system/common/R.java b/System/src/main/java/com/example/system/common/R.java
new file mode 100644
index 0000000..f4f284e
--- /dev/null
+++ b/System/src/main/java/com/example/system/common/R.java
@@ -0,0 +1,145 @@
+package com.example.system.common;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 统一返回结果类
+ */
+@Data
+@NoArgsConstructor
+public class R implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 状态码
+ */
+ private Integer status;
+
+ /**
+ * 返回消息
+ */
+ private String msg;
+
+ /**
+ * 返回数据
+ */
+ private T data;
+
+ /**
+ * 附加数据
+ */
+ private Map additionalData = new HashMap<>();
+
+ /**
+ * 通用返回成功
+ */
+ public static R success() {
+ R result = new R<>();
+ result.setStatus(ResultCode.SUCCESS.getCode());
+ result.setMsg(ResultCode.SUCCESS.getMessage());
+ return result;
+ }
+
+ /**
+ * 返回成功消息
+ */
+ public static R success(String message) {
+ R result = new R<>();
+ result.setStatus(ResultCode.SUCCESS.getCode());
+ result.setMsg(message);
+ return result;
+ }
+
+ /**
+ * 返回成功数据
+ */
+ public static R success(T data) {
+ R result = new R<>();
+ result.setStatus(ResultCode.SUCCESS.getCode());
+ result.setMsg(ResultCode.SUCCESS.getMessage());
+ result.setData(data);
+ return result;
+ }
+
+ /**
+ * 返回成功消息和数据
+ */
+ public static R success(String message, T data) {
+ R result = new R<>();
+ result.setStatus(ResultCode.SUCCESS.getCode());
+ result.setMsg(message);
+ result.setData(data);
+ return result;
+ }
+
+ /**
+ * 通用返回失败
+ */
+ public static R error() {
+ R result = new R<>();
+ result.setStatus(ResultCode.ERROR.getCode());
+ result.setMsg(ResultCode.ERROR.getMessage());
+ return result;
+ }
+
+ /**
+ * 返回失败消息
+ */
+ public static R error(String message) {
+ R result = new R<>();
+ result.setStatus(ResultCode.ERROR.getCode());
+ result.setMsg(message);
+ return result;
+ }
+
+ /**
+ * 返回失败状态码和消息
+ */
+ public static R error(int code, String message) {
+ R result = new R<>();
+ result.setStatus(code);
+ result.setMsg(message);
+ return result;
+ }
+
+ /**
+ * 添加附加数据
+ */
+ public R add(String key, Object value) {
+ this.additionalData.put(key, value);
+ return this;
+ }
+
+ /**
+ * 返回结果状态码枚举
+ */
+ public enum ResultCode {
+ SUCCESS(200, "操作成功"),
+ ERROR(500, "操作失败"),
+ VALIDATE_FAILED(400, "参数校验失败"),
+ UNAUTHORIZED(401, "暂未登录或token已经过期"),
+ FORBIDDEN(403, "没有相关权限");
+
+ private final int code;
+ private final String message;
+
+ ResultCode(int code, String message) {
+ this.code = code;
+ this.message = message;
+ }
+
+ public int getCode() {
+ return code;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+ }
+}
\ No newline at end of file
diff --git a/System/src/main/java/com/example/system/controller/ChartController.java b/System/src/main/java/com/example/system/controller/ChartController.java
new file mode 100644
index 0000000..50329b0
--- /dev/null
+++ b/System/src/main/java/com/example/system/controller/ChartController.java
@@ -0,0 +1,85 @@
+package com.example.system.controller;
+
+import com.example.system.common.R;
+import com.example.system.pojo.GenChartByAiRequest;
+import com.example.system.pojo.BiResponse;
+import com.example.system.service.ChartService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * 智能分析控制器
+ */
+@RestController
+@RequestMapping("/api/chart")
+public class ChartController {
+
+ @Autowired
+ private ChartService chartService;
+
+ /**
+ * AI生成图表分析
+ *
+ * @param file 上传的Excel文件
+// * @param genChartByAiRequest 分析请求参数
+ * @return 分析结果
+ */
+ @CrossOrigin
+ @PostMapping("/gen")
+ public R genChartByAi(@RequestParam("file") MultipartFile file,
+ @RequestParam(value = "name", required = false) String name,
+ @RequestParam("goal") String goal,
+ @RequestParam(value = "chartType", required = false) String chartType) {
+ // 构建请求对象
+ GenChartByAiRequest request = new GenChartByAiRequest();
+ request.setName(name);
+ request.setGoal(goal);
+ request.setChartType(chartType);
+// request.setAdminId(adminId);
+
+ // 调用服务处理
+ return chartService.genChartByAi(file, request);
+ }
+
+ /**
+ * 获取示例提示
+ *
+ * @return 示例提示列表
+ */
+ @CrossOrigin
+ @GetMapping("/examples")
+ public R