Browse Source

查询股票功能增加

Zhangbw 3 months ago
parent
commit
5a05b0c899

+ 113 - 0
src/main/java/com/yingpai/gupiao/controller/StockDataController.java

@@ -0,0 +1,113 @@
+package com.yingpai.gupiao.controller;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.yingpai.gupiao.domain.vo.Result;
+import com.yingpai.gupiao.domain.vo.StockInfoVO;
+import com.yingpai.gupiao.util.StockUtils;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.math.BigDecimal;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.List;
+
+@RestController
+@RequestMapping("/api/stock")
+public class StockDataController {
+
+    // 东方财富通用行情接口
+    private static final String BASE_URL = "http://push2.eastmoney.com/api/qt/stock/get";
+
+    private final HttpClient httpClient = HttpClient.newBuilder()
+            .connectTimeout(Duration.ofSeconds(3))
+            .build();
+
+    private final ObjectMapper objectMapper = new ObjectMapper();
+
+    /**
+     * 获取股票数据
+     * 调用示例:
+     * - 单个股票: GET /api/stock/fetch?codes=600519
+     * - 多个股票: GET /api/stock/fetch?codes=600519,300059,000001
+     *
+     * @param codes 股票代码,多个用逗号分隔
+     * @return 股票数据列表
+     */
+    @GetMapping("/fetch")
+    public Result<List<StockInfoVO>> fetchStockData(@RequestParam("codes") String codes) {
+        List<StockInfoVO> dataList = new ArrayList<>();
+
+        String[] codeArray = codes.split(",");
+
+        for (String code : codeArray) {
+            code = code.trim();
+            if (code.isEmpty()) {
+                continue;
+            }
+
+            StockInfoVO stockInfo = fetchAShareData(code);
+            if (stockInfo != null) {
+                dataList.add(stockInfo);
+            }
+        }
+
+        return Result.success(dataList);
+    }
+
+    /**
+     * 获取单个A股数据
+     */
+    private StockInfoVO fetchAShareData(String code) {
+        // 1. 获取 secid (只允许 A 股)
+        String secId = StockUtils.getAShareSecId(code);
+
+        // 如果返回 null,说明不是沪深 A 股
+        if (secId == null) {
+            return null;
+        }
+
+        // 2. 构建 URL
+        // f58: 名称, f169: 涨跌额, f170: 涨跌幅
+        String params = String.format("?invt=2&fltt=2&fields=f58,f169,f170&secid=%s", secId);
+        String fullUrl = BASE_URL + params;
+
+        // 3. 发送请求
+        HttpRequest request = HttpRequest.newBuilder()
+                .uri(URI.create(fullUrl))
+                .GET()
+                .build();
+
+        try {
+            HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
+
+            if (response.statusCode() == 200) {
+                JsonNode root = objectMapper.readTree(response.body());
+                JsonNode data = root.get("data");
+
+                if (data != null && !data.isNull()) {
+                    BigDecimal priceChange = data.has("f169") ? new BigDecimal(data.get("f169").asText()) : null;
+                    BigDecimal changePercent = data.has("f170") ? new BigDecimal(data.get("f170").asText()) : null;
+
+                    return StockInfoVO.builder()
+                            .stockCode(code)
+                            .stockName(data.has("f58") ? data.get("f58").asText() : null)
+                            .priceChange(StockInfoVO.formatWithSign(priceChange))
+                            .changePercent(StockInfoVO.formatPercent(changePercent))
+                            .build();
+                }
+            }
+        } catch (Exception e) {
+            System.err.println("获取股票数据异常 [" + code + "]: " + e.getMessage());
+        }
+
+        return null;
+    }
+}

+ 59 - 0
src/main/java/com/yingpai/gupiao/domain/vo/StockInfoVO.java

@@ -0,0 +1,59 @@
+package com.yingpai.gupiao.domain.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.math.BigDecimal;
+
+/**
+ * 股票详情VO
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class StockInfoVO {
+
+    /**
+     * 股票代码
+     */
+    private String stockCode;
+
+    /**
+     * 股票名称
+     */
+    private String stockName;
+
+    /**
+     * 涨跌额 (带正负号,如 +12.50 或 -3.20)
+     */
+    private String priceChange;
+
+    /**
+     * 涨跌幅 (带正负号,如 +1.25% 或 -0.80%)
+     */
+    private String changePercent;
+
+    /**
+     * 格式化数值,正数加+号
+     */
+    public static String formatWithSign(BigDecimal value) {
+        if (value == null) {
+            return null;
+        }
+        return value.compareTo(BigDecimal.ZERO) > 0 ? "+" + value : value.toString();
+    }
+
+    /**
+     * 格式化涨跌幅,带%号
+     */
+    public static String formatPercent(BigDecimal value) {
+        if (value == null) {
+            return null;
+        }
+        String sign = value.compareTo(BigDecimal.ZERO) > 0 ? "+" : "";
+        return sign + value + "%";
+    }
+}

BIN
uploads/2025/12/25/fddb1d7f-73bd-4951-8544-05b88dbe5fe4.jpeg