From 5c5d5112e7b999381f8b20c97e53314e6cedada2 Mon Sep 17 00:00:00 2001
From: zyy <zyy@email.com>
Date: Wed, 09 Jul 2025 18:34:52 +0800
Subject: [PATCH] 股票主页、市场页面接口

---
 src/main/java/com/nq/ws/WebsocketRunClient.java             |    5 
 src/main/resources/mapper/StockMapper.xml                   |    6 
 src/main/java/com/nq/service/impl/StockServiceImpl.java     |  172 ++++++++++++++----
 src/main/java/com/nq/config/ThreadPoolConfig.java           |   20 ++
 src/main/java/com/nq/utils/redis/RedisKeyUtil.java          |   21 +
 src/main/java/com/nq/controller/StockApiController.java     |   35 +++
 src/main/java/com/nq/pojo/DataStockBean.java                |    2 
 src/main/java/com/nq/utils/task/stock/StockTask.java        |  121 +++++++------
 src/main/java/com/nq/utils/redis/RedisKeyConstant.java      |    5 
 src/main/resources/application.properties                   |    6 
 src/main/java/com/nq/utils/redis/RedisShardedPoolUtils.java |    8 
 src/main/java/com/nq/service/impl/SiteNewsServiceImpl.java  |    3 
 src/main/java/com/nq/ws/MXWebsocketRunClient.java           |    4 
 src/main/java/com/nq/service/IStockService.java             |   21 ++
 src/main/java/com/nq/service/impl/PriceServicesImpl.java    |   60 -----
 15 files changed, 325 insertions(+), 164 deletions(-)

diff --git a/src/main/java/com/nq/config/ThreadPoolConfig.java b/src/main/java/com/nq/config/ThreadPoolConfig.java
new file mode 100644
index 0000000..00dd23f
--- /dev/null
+++ b/src/main/java/com/nq/config/ThreadPoolConfig.java
@@ -0,0 +1,20 @@
+package com.nq.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+@Configuration
+public class ThreadPoolConfig {
+
+    @Bean
+    public ThreadPoolTaskExecutor taskExecutor() {
+        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+        executor.setCorePoolSize(4);
+        executor.setMaxPoolSize(4);
+        executor.setQueueCapacity(10);
+        executor.setThreadNamePrefix("stock-sync-");
+        executor.initialize();
+        return executor;
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/com/nq/controller/StockApiController.java b/src/main/java/com/nq/controller/StockApiController.java
index d265e7a..99ecafa 100644
--- a/src/main/java/com/nq/controller/StockApiController.java
+++ b/src/main/java/com/nq/controller/StockApiController.java
@@ -54,6 +54,7 @@
 
 
 
+
     @RequestMapping("getOptionStock.do")
     @ResponseBody()
     public  ServerResponse getOptionStock(HttpServletRequest request){
@@ -117,4 +118,38 @@
     public ServerResponse getVipByCode(String code) {
         return this.iStockService.getVipByCode(code);
     }
+
+    /**
+     * 获取首页数据 新闻和指数列表
+     * @param pageSize
+     * @return
+     */
+    @PostMapping({"getHomePageData.do"})
+    @ResponseBody
+    public ServerResponse getHomePageData(@RequestParam(value = "pageSize", defaultValue = "5") int pageSize) {
+        return this.iStockService.getIndicesIndexListAndNews(pageSize);
+    }
+
+    /**
+     * 获取指数id和name 默认US
+     * @param stockType
+     * @return
+     */
+    @RequestMapping("getIndicesList.do")
+    @ResponseBody
+    public ServerResponse getIndicesList(@RequestParam(value = "stockType", defaultValue = "US") String stockType)   {
+        return this.iStockService.getIndicesList(stockType);
+    }
+
+    /**
+     * 获取单个指数数据和k线图 默认US
+     * @param stockType
+     * @return
+     */
+    @RequestMapping("getIndicesAndKData.do")
+    @ResponseBody
+    public ServerResponse getIndicesAndKData(@RequestParam(value = "pid") String pid,
+                                             @RequestParam(value = "stockType", defaultValue = "US") String stockType) {
+        return this.iStockService.getIndicesAndKData(pid, stockType);
+    }
 }
diff --git a/src/main/java/com/nq/pojo/DataStockBean.java b/src/main/java/com/nq/pojo/DataStockBean.java
index 1e53a72..c927d49 100644
--- a/src/main/java/com/nq/pojo/DataStockBean.java
+++ b/src/main/java/com/nq/pojo/DataStockBean.java
@@ -64,5 +64,7 @@
 
     private String Ticker;
 
+    //k线
+    private Object kData;
 
 }
diff --git a/src/main/java/com/nq/service/IStockService.java b/src/main/java/com/nq/service/IStockService.java
index 4763888..d47a861 100644
--- a/src/main/java/com/nq/service/IStockService.java
+++ b/src/main/java/com/nq/service/IStockService.java
@@ -104,5 +104,24 @@
   Object getKData(String pid,String interval,String stockType);
 
 
-    ServerResponse getOptionStock(HttpServletRequest request);
+  ServerResponse getOptionStock(HttpServletRequest request);
+
+  /**
+   * 获取首页指数列表
+   * @param pageSize
+   * @return
+   */
+  ServerResponse getIndicesIndexListAndNews(Integer pageSize);
+
+  /**
+   * 获取指数数据 获取指数id和name
+   * @return
+   */
+  ServerResponse getIndicesList(String stockType);
+
+  /**
+   * 获取单个指数数据和k线图
+   * @return
+   */
+  ServerResponse getIndicesAndKData(String pid, String stockType);
 }
diff --git a/src/main/java/com/nq/service/impl/PriceServicesImpl.java b/src/main/java/com/nq/service/impl/PriceServicesImpl.java
index 05dd037..6091b18 100644
--- a/src/main/java/com/nq/service/impl/PriceServicesImpl.java
+++ b/src/main/java/com/nq/service/impl/PriceServicesImpl.java
@@ -5,7 +5,6 @@
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.google.gson.Gson;
-import com.google.gson.reflect.TypeToken;
 import com.nq.dao.StockDzMapper;
 import com.nq.dao.StockMapper;
 import com.nq.dao.StockSettingMapper;
@@ -13,23 +12,14 @@
 import com.nq.pojo.*;
 import com.nq.service.IPriceServices;
 import com.nq.service.IStockConfigServices;
-import com.nq.utils.PropertiesUtil;
-import com.nq.utils.http.HttpClientRequest;
 import com.nq.utils.redis.RedisKeyUtil;
-import com.nq.utils.timeutil.TimeUtil;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
-import java.io.*;
-import java.lang.reflect.Type;
 import java.math.BigDecimal;
-import  java.io.BufferedReader;
-import  java.io.InputStreamReader;
-import  java.net.HttpURLConnection;
-import  java.net.URL;
+import java.util.Collections;
 import java.util.Date;
-import java.util.HashMap;
 import java.util.Map;
 import com.fasterxml.jackson.databind.ObjectMapper;
 
@@ -67,7 +57,7 @@
                 if(stockSetting.getType().equals("0")){
                     return  new BigDecimal(stockSetting.getPrice());
                 }else{
-                    String s = doPost(stock.getStockCode());
+                    String s = RedisKeyUtil.doPost(stock.getStockCode(), stock.getStockType());
                     if(null != s){
                         Map<String, Object> stringObjectMap = jsonToMap(s);
                         return   new BigDecimal(stringObjectMap.get("Last").toString()).multiply(new BigDecimal(stockSetting.getPrice()));
@@ -76,7 +66,7 @@
             }
         }
 
-        String s = doPost(stock.getStockCode());
+        String s = RedisKeyUtil.doPost(stock.getStockCode(), stock.getStockType());
         if(null != s) {
             Map<String, Object> stringObjectMap = jsonToMap(s);
             return  new BigDecimal(stringObjectMap.get("Last").toString());
@@ -87,7 +77,7 @@
     @Override
     public Map<String, Object> getNewStock(String stockCode) {
         Stock stock = stockMapper.selectOne(new QueryWrapper<Stock>().eq("stock_code",stockCode));
-        String s = doPost(stock.getStockCode());
+        String s = RedisKeyUtil.doPost(stock.getStockCode(), stock.getStockType());
         if(null != s){
             Map<String, Object> stringObjectMap = jsonToMap(s);
             return   stringObjectMap;
@@ -101,6 +91,9 @@
         ObjectMapper objectMapper = new ObjectMapper();
         try {
             Object[] array = objectMapper.readValue(json, Object[].class);
+            if (array.length == 0) {
+                return Collections.emptyMap();
+            }
             Gson gson = new Gson();
             String s = gson.toJson(array[0]);
             Map<String, Object> map = objectMapper.readValue(s, Map.class);
@@ -108,45 +101,6 @@
         } catch (JsonProcessingException e) {
             throw new RuntimeException(e);
         }
-    }
-
-    public String doPost(String pid) {
-        // 从配置中获取 API URL,并拼接 key
-        String apiUrl = PropertiesUtil.getProperty("JS_IN_HTTP_URL") + "stock?key=" + PropertiesUtil.getProperty("JS_IN_KEY");
-        String result = null;
-        try {
-            URL url = new URL(apiUrl);
-            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
-
-            // 设置请求方法为 POST
-            connection.setRequestMethod("POST");
-            // 设置请求头
-            connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
-            connection.setDoOutput(true); // 允许向连接输出
-
-            // 构建 POST 数据
-            String postData = "pid=" + pid;
-
-            // 发送 POST 请求
-            try (OutputStream os = connection.getOutputStream()) {
-                byte[] input = postData.getBytes("utf-8");
-                os.write(input, 0, input.length);
-            }
-
-            // 读取响应
-            BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
-            String inputLine;
-            StringBuffer response = new StringBuffer();
-
-            while ((inputLine = in.readLine()) != null) {
-                response.append(inputLine);
-            }
-            in.close();
-            result = response.toString();
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-        return result;
     }
 
 
diff --git a/src/main/java/com/nq/service/impl/SiteNewsServiceImpl.java b/src/main/java/com/nq/service/impl/SiteNewsServiceImpl.java
index 00908c5..6c6f172 100644
--- a/src/main/java/com/nq/service/impl/SiteNewsServiceImpl.java
+++ b/src/main/java/com/nq/service/impl/SiteNewsServiceImpl.java
@@ -165,7 +165,8 @@
                         siteNews.setSourceId(newsId);
                         siteNews.setSourceName("");
                         siteNews.setTitle(jsonObject.getString("title"));
-                        Long showTime = jsonObject.getLong("time");
+                        //Long showTime = jsonObject.getLong("time");
+                        long showTime = jsonObject.optLong("time", System.currentTimeMillis() / 1000); // 默认值,表示未找到或转换失败
                         siteNews.setShowTime(new Date(showTime * 1000));
                         if(jsonObject.has("img")){
                             convertBase64ToImage(jsonObject.getString("img"),PropertiesUtil.getProperty("ftp.address")+newsId+".jpg");
diff --git a/src/main/java/com/nq/service/impl/StockServiceImpl.java b/src/main/java/com/nq/service/impl/StockServiceImpl.java
index 283f5ae..7c601bd 100644
--- a/src/main/java/com/nq/service/impl/StockServiceImpl.java
+++ b/src/main/java/com/nq/service/impl/StockServiceImpl.java
@@ -1,8 +1,6 @@
 package com.nq.service.impl;
 
-import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.http.HttpUtil;
-import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.github.pagehelper.PageHelper;
@@ -10,10 +8,8 @@
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.gson.Gson;
-import com.google.gson.JsonObject;
 import com.google.gson.reflect.TypeToken;
 import com.nq.common.ServerResponse;
-import com.nq.config.StockPoll;
 import com.nq.dao.*;
 import com.nq.enums.EStockType;
 import com.nq.pojo.*;
@@ -26,28 +22,18 @@
 import com.nq.utils.stock.pinyin.GetPyByChinese;
 import com.nq.utils.stock.qq.QqStockApi;
 import com.nq.utils.stock.sina.StockApi;
-import com.nq.utils.translate.GoogleTranslateUtil;
 import com.nq.vo.stock.*;
 import com.nq.vo.stock.k.MinDataVO;
 import com.nq.vo.stock.k.echarts.EchartsDataVO;
 
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
 import java.math.BigDecimal;
-import java.net.HttpURLConnection;
-import java.net.URL;
-import java.text.SimpleDateFormat;
 import java.util.*;
-import java.util.concurrent.CompletableFuture;
+import java.util.function.Function;
+import java.util.stream.Collectors;
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import lombok.Data;
-import net.sf.json.JSONArray;
-import net.sf.json.JSONObject;
-import org.apache.commons.lang3.ObjectUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -63,14 +49,8 @@
     @Autowired
     StockMapper stockMapper;
 
-    @Resource
-    RealTimeMapper realTimeMapper;
-
     @Autowired
     IStockMarketsDayService iStockMarketsDayService;
-
-    @Autowired
-    StockPoll stockPoll;
 
     @Resource
     StockFuturesMapper stockFuturesMapper;
@@ -82,20 +62,16 @@
     IUserService iUserService;
 
     @Autowired
-    IStockOptionService iStockOptionService;
-    @Autowired
     ISiteSettingService iSiteSettingService;
-
-
-    @Autowired
-    InStockMapper inStockMapper;
 
     @Resource
     StockDzMapper stockDzMapper;
 
-
     @Autowired
     IPriceServices iPriceServices;
+
+    @Autowired
+    SiteNewsMapper siteNewsMapper;
 
 
     public ServerResponse getMarket() {
@@ -170,17 +146,26 @@
 
     @Override
     public ServerResponse getStockByType(int pageNum, int pageSize, String orderBy, String keyWords, String stockType, HttpServletRequest request) {
-        List<Stock> stockList = new ArrayList<>();
         PageHelper.startPage(pageNum, pageSize);
-        stockList.addAll(stockMapper.findStockByType(orderBy,stockType,keyWords));
+        List<Stock> stockList = stockMapper.findStockByType(orderBy, stockType, keyWords);
+        // 获取分页信息
+        PageInfo<Stock> pageInfo = new PageInfo<>(stockList);
+
         List<StockListVO> stockListVOS = Lists.newArrayList();
-        if (stockList.size() > 0){
+        if (stockList.size() > 0) {
             stockListVOS.addAll(Objects.requireNonNull(StockApi.getStockReailTimes(stockList)));
         }
-        RPageInfo pageInfo = new RPageInfo();
-        pageInfo.setList(stockListVOS);
-        pageInfo.setStockType(stockType);
-        return ServerResponse.createBySuccess(pageInfo);
+
+        RPageInfo resultPageInfo = new RPageInfo();
+        resultPageInfo.setList(stockListVOS);
+        resultPageInfo.setStockType(stockType);
+        // 设置分页信息
+        resultPageInfo.setTotal(pageInfo.getTotal());
+        resultPageInfo.setPageNum(pageInfo.getPageNum());
+        resultPageInfo.setPageSize(pageInfo.getPageSize());
+        resultPageInfo.setPages(pageInfo.getPages());
+        resultPageInfo.setHasNextPage(pageInfo.isHasNextPage());
+        return ServerResponse.createBySuccess(resultPageInfo);
     }
 
     @Override
@@ -193,7 +178,7 @@
         if (StringUtils.isBlank(code))
             return ServerResponse.createByErrorMsg("");
         Stock stock = stockMapper.findStockByCode(code);
-        DataStockBean cacheBaseStock = RedisKeyUtil.getCacheBaseStock(stock);
+        DataStockBean cacheBaseStock = RedisKeyUtil.getCacheBaseStock(stock.getStockType(), stock.getStockCode());
         Integer depositAmt = 0;
         String introduction = null;
         StockVO   stockVO = StockApi.assembleInStockVO(stock);
@@ -223,7 +208,7 @@
         if (StringUtils.isBlank(code))
             return null;
         Stock stock = stockMapper.findStockByCode(code);
-        DataStockBean cacheBaseStock = RedisKeyUtil.getCacheBaseStock(stock);
+        DataStockBean cacheBaseStock = RedisKeyUtil.getCacheBaseStock(stock.getStockType(), stock.getStockCode());
         Integer depositAmt = 0;
         String introduction = null;
         StockVO   stockVO = StockApi.assembleInStockVO(stock);
@@ -711,4 +696,115 @@
         }
         return ServerResponse.createBySuccess(pool);
     }
+
+    @Override
+    public ServerResponse getIndicesIndexListAndNews(Integer pageSize) {
+        try {
+            //新闻列表
+            List<SiteNews> newsList = this.siteNewsMapper.getTopNewsList(pageSize);
+
+            String usCodeList = PropertiesUtil.getProperty("us_home_indices_code");
+            String mxCodeList = PropertiesUtil.getProperty("mx_home_indices_code");
+            List<String> usStockCodeList = Arrays.asList(usCodeList.split(","));
+            List<String> mxStockCodeList = Arrays.asList(mxCodeList.split(","));
+            List<DataStockBean> usDataStockBeans = Lists.newArrayList();
+            List<DataStockBean> mxDataStockBeans = Lists.newArrayList();
+            for (int i = 0; i < usStockCodeList.size(); i++) {
+                String stockCode = usStockCodeList.get(i);
+                String stockType = EStockType.US.getCode();
+                DataStockBean cacheBaseStock = RedisKeyUtil.getCacheBaseStock(stockType, stockCode);
+                // 获取K线数据
+                Object kData = RedisKeyUtil.getCaCheStockKData(stockType, stockCode);
+                if (kData == null) {
+                    //重新获取并缓存redis
+                    kData = getKData(stockCode, "D", stockType);
+                    RedisKeyUtil.setCaCheStockKData(stockType, stockCode, kData);
+                }
+                Gson gson = new Gson();
+                List<kData> dataList = gson.fromJson(kData.toString(), new TypeToken<List<kData>>(){}.getType());
+                cacheBaseStock.setKData(dataList);
+                usDataStockBeans.add(cacheBaseStock);
+            }
+            for (int i = 0; i < mxStockCodeList.size(); i++) {
+                String stockCode = mxStockCodeList.get(i);
+                String stockType = EStockType.MX.getCode();
+                DataStockBean cacheBaseStock = RedisKeyUtil.getCacheBaseStock(stockType, stockCode);
+                // 获取K线数据
+                Object kData = RedisKeyUtil.getCaCheStockKData(stockType, stockCode);
+                if (kData == null) {
+                    //重新获取并缓存redis
+                    kData = getKData(stockCode, "D", stockType);
+                    RedisKeyUtil.setCaCheStockKData(stockType, stockCode, kData);
+                }
+                Gson gson = new Gson();
+                List<kData> dataList = gson.fromJson(kData.toString(), new TypeToken<List<kData>>(){}.getType());
+                cacheBaseStock.setKData(dataList);
+                mxDataStockBeans.add(cacheBaseStock);
+            }
+            Map<String, Object> resultMap = new HashMap<>();
+            resultMap.put("newsList", newsList);                //新闻列表
+            resultMap.put("usDataStockBeans", usDataStockBeans);//美国指数
+            resultMap.put("mxDataStockBeans", mxDataStockBeans);//墨西哥指数
+            return ServerResponse.createBySuccess(resultMap);
+        } catch (Exception e){
+            e.printStackTrace();
+        }
+        return ServerResponse.createByError();
+    }
+
+    @Override
+    public ServerResponse getIndicesList(String stockType) {
+        try {
+            String codeList;
+            if (stockType.equals(EStockType.US.getCode())) {
+                codeList = PropertiesUtil.getProperty("us_home_indices_code");
+            } else {
+                codeList = PropertiesUtil.getProperty("mx_home_indices_code");
+            }
+            List<String> stockCodeList = Arrays.asList(codeList.split(","));
+
+            Map<Integer, Object> resultMap = new HashMap<>();
+            for (int i = 0; i < stockCodeList.size(); i++) {
+                String stockCode = stockCodeList.get(i);
+                DataStockBean cacheBaseStock = RedisKeyUtil.getCacheBaseStock(stockType, stockCode);
+                Map<String, Object> stockInfo = new HashMap<>();
+                stockInfo.put("pid", cacheBaseStock.getId());
+                stockInfo.put("name", cacheBaseStock.getName());
+                stockInfo.put("stockType", stockType);
+                resultMap.put(i+1, stockInfo);
+            }
+            return ServerResponse.createBySuccess(resultMap);
+        } catch (Exception e){
+            e.printStackTrace();
+        }
+        return ServerResponse.createByError();
+    }
+
+    @Override
+    public ServerResponse getIndicesAndKData(String pid, String stockType) {
+        try {
+            Map<String, Object> resultMap = new HashMap<>();
+            DataStockBean cacheBaseStock = RedisKeyUtil.getCacheBaseStock(stockType, pid);
+            if (cacheBaseStock != null) {
+                resultMap.put("last", cacheBaseStock.getLast());
+                resultMap.put("chg", cacheBaseStock.getChg());
+                resultMap.put("chgPct", cacheBaseStock.getChgPct());
+                resultMap.put("kData", cacheBaseStock.getChg());
+                // 获取K线数据
+                Object kData = RedisKeyUtil.getCaCheStockKData(stockType, pid);
+                if (kData == null) {
+                    //重新获取并缓存redis
+                    kData = getKData(pid, "D", stockType);
+                    RedisKeyUtil.setCaCheStockKData(stockType, pid, kData);
+                }
+                Gson gson = new Gson();
+                List<kData> dataList = gson.fromJson(kData.toString(), new TypeToken<List<kData>>(){}.getType());
+                resultMap.put("kData", dataList);
+                return ServerResponse.createBySuccess(resultMap);
+            }
+        } catch (Exception e){
+            e.printStackTrace();
+        }
+        return ServerResponse.createByError();
+    }
 }
diff --git a/src/main/java/com/nq/utils/redis/RedisKeyConstant.java b/src/main/java/com/nq/utils/redis/RedisKeyConstant.java
index 4fe11e6..ed9cb04 100644
--- a/src/main/java/com/nq/utils/redis/RedisKeyConstant.java
+++ b/src/main/java/com/nq/utils/redis/RedisKeyConstant.java
@@ -25,5 +25,8 @@
      * */
     public static final String RK_COMPANY_INFO = "rk_company_info";
 
-
+    /**
+     * 股票K线图数据key
+     * */
+    public static final String RK_STOCK_KDATA = "rk_stock_kdata";
 }
diff --git a/src/main/java/com/nq/utils/redis/RedisKeyUtil.java b/src/main/java/com/nq/utils/redis/RedisKeyUtil.java
index 7e53315..fdc5ad3 100644
--- a/src/main/java/com/nq/utils/redis/RedisKeyUtil.java
+++ b/src/main/java/com/nq/utils/redis/RedisKeyUtil.java
@@ -37,8 +37,8 @@
     /**
      * 获取股票数据
      * */
-    public static DataStockBean getCacheBaseStock(Stock stock){
-        String cacheBaseData = RedisShardedPoolUtils.get(RedisKeyConstant.RK_BASE_STOCK+":"+stock.getStockType()+":"+stock.getStockCode());
+    public static DataStockBean getCacheBaseStock(String stockType, String stockCode){
+        String cacheBaseData = RedisShardedPoolUtils.get(RedisKeyConstant.RK_BASE_STOCK+":"+stockType+":"+stockCode);
         return  new Gson().fromJson(cacheBaseData, DataStockBean.class);
     }
 
@@ -60,7 +60,7 @@
             stockRealTimeBean = new Gson().fromJson(cacheBaseData, StockRealTimeBean.class);
         }
         if(stockRealTimeBean == null){
-            String s = doPost(stock.getStockCode());
+            String s = doPost(stock.getStockCode(), stock.getStockType());
             Map<String, Object> stringObjectMap = jsonToMap(s);
             stockRealTimeBean = new StockRealTimeBean();
             stockRealTimeBean.setPcp(stringObjectMap.get("ChgPct").toString());
@@ -89,9 +89,11 @@
         }
     }
 
-    public static String doPost(String pid) {
+    public static String doPost(String pid, String stockType) {
+        EStockType eStockType = EStockType.getEStockTypeByCode(stockType);
         // 从配置中获取 API URL,并拼接 key
-        String apiUrl = PropertiesUtil.getProperty("JS_IN_HTTP_URL") + "stock?key=" + PropertiesUtil.getProperty("JS_IN_KEY");
+        //String apiUrl = PropertiesUtil.getProperty("JS_IN_HTTP_URL") + "stock?key=" + PropertiesUtil.getProperty("JS_IN_KEY");
+        String apiUrl = eStockType.getStockUrl() + "stock?key=" + eStockType.getStockKey();
         String result = null;
         try {
             URL url = new URL(apiUrl);
@@ -143,6 +145,15 @@
        return  JSONObject.parseObject(companiesInfo);
     }
 
+    /**
+     * 缓存K线数据源到redis
+     * */
+    public static void setCaCheStockKData(String stockType, String stockCode, Object kData){
+        RedisShardedPoolUtils.set(RedisKeyConstant.RK_STOCK_KDATA+":"+stockType+":"+stockCode, kData.toString());
+    }
 
+    public static Object getCaCheStockKData(String stockType, String stockCode){
+        return RedisShardedPoolUtils.get(RedisKeyConstant.RK_STOCK_KDATA+":"+stockType+":"+stockCode);
+    }
 
 }
diff --git a/src/main/java/com/nq/utils/redis/RedisShardedPoolUtils.java b/src/main/java/com/nq/utils/redis/RedisShardedPoolUtils.java
index c916856..5971891 100644
--- a/src/main/java/com/nq/utils/redis/RedisShardedPoolUtils.java
+++ b/src/main/java/com/nq/utils/redis/RedisShardedPoolUtils.java
@@ -142,11 +142,11 @@
 
 
         try {
+            if (key == null) {
+                jedis = RedisShardedPool.getJedis();
 
-            jedis = RedisShardedPool.getJedis();
-
-            result = jedis.del(key);
-
+                result = jedis.del(key);
+            }
         } catch (Exception e) {
 
             log.error("redis del key: {} error ", key, e);
diff --git a/src/main/java/com/nq/utils/task/stock/StockTask.java b/src/main/java/com/nq/utils/task/stock/StockTask.java
index f7520a6..ec13638 100644
--- a/src/main/java/com/nq/utils/task/stock/StockTask.java
+++ b/src/main/java/com/nq/utils/task/stock/StockTask.java
@@ -1,13 +1,8 @@
 package com.nq.utils.task.stock;
 
 import com.alibaba.fastjson2.JSONObject;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.google.gson.Gson;
-import com.google.gson.JsonArray;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonParser;
 import com.google.gson.reflect.TypeToken;
 import com.nq.Repository.StockRepository;
 import com.nq.dao.StockMapper;
@@ -17,24 +12,21 @@
 import com.nq.service.IMandatoryLiquidationService;
 import com.nq.service.IStockService;
 import com.nq.service.IUserPositionService;
+import com.nq.service.impl.StockServiceImpl;
 import com.nq.utils.PropertiesUtil;
 import com.nq.utils.http.HttpClientRequest;
 import com.nq.utils.http.HttpRequest;
 import com.nq.utils.redis.RedisKeyUtil;
-import net.sf.json.JSONArray;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
 import org.springframework.stereotype.Component;
 
 import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
+import java.util.*;
+import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
@@ -44,85 +36,79 @@
 @Component
 public class StockTask {
     @Autowired
-    IStockService stockService;
-    @Autowired
     StockMapper stockMapper;
-
     @Autowired
-    IUserPositionService userPositionService;
-
-    @Autowired
-    UserPositionMapper userPositionMapper;
+    IStockService istockService;
 
     @Autowired
     StockRepository stockRepository;
 
     private final Lock stockConstraintLock = new ReentrantLock();
 
-
     @Autowired
     IMandatoryLiquidationService mandatoryLiquidationService;
 
-
     private static final Logger log = LoggerFactory.getLogger(StockTask.class);
-
-
 
     private final AtomicBoolean syncINStockData = new AtomicBoolean(false);
 
     private final Lock syncINStockDataLock = new ReentrantLock();
+
+    @Autowired
+    private ThreadPoolTaskExecutor taskExecutor;
+    @Autowired
+    private StockServiceImpl iStockService;
+
+    /**
+     * test
+     */
+    //@Scheduled(cron = "0 0/1 * * * ?")
+    @Scheduled(cron = "*/5 * * * * *")
+    public void test() {
+        //iStockService.getStockByType(1, 20, "desc","st" , "US", null);
+        //istockService.getIndicesList("US");
+        //istockService.getIndicesAndKData("15882", "US");
+    }
 
     /**
      * 同步系统所需要的股票
      */
     @Scheduled(cron = "0 0/1 * * * ?")
     public void syncINStockData() {
+
         if (syncINStockData.get()) { // 判断任务是否在处理中
             return;
         }
         if (syncINStockDataLock.tryLock()) {
-            ExecutorService executor = Executors.newFixedThreadPool(4);
-            Future<?> future1 = null;
-            Future<?> future2 = null;
-            Future<?> future3 = null;
-            Future<?> future4 = null;
             try {
-                syncINStockData.set(true); // 设置处理中标识为true
+                syncINStockData.set(true);
 
-                // 同步股票数据
-                future1 = executor.submit(() -> loadAllStock(EStockType.US));
-                future2 = executor.submit(() -> loadAllStock(EStockType.MX));
-                // 同步指数数据
-                future3 = executor.submit(() -> syncIndices(EStockType.US));
-                future4 = executor.submit(() -> syncIndices(EStockType.MX));
+                // 使用CompletableFuture并行执行任务
+                CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> loadAllStock(EStockType.US), taskExecutor);
+                CompletableFuture<Void> future2 = CompletableFuture.runAsync(() -> loadAllStock(EStockType.MX), taskExecutor);
+                CompletableFuture<Void> future3 = CompletableFuture.runAsync(() -> syncIndices(EStockType.US), taskExecutor);
+                CompletableFuture<Void> future4 = CompletableFuture.runAsync(() -> syncIndices(EStockType.MX), taskExecutor);
 
-                // 等待任务都完成
-                future1.get();
-                future2.get();
-                future3.get();
-                future4.get();
+                // 等待所有任务完成
+                CompletableFuture.allOf(future1, future2, future3, future4).join();
             } catch (Exception e) {
-                Thread.currentThread().interrupt();
                 log.error("同步股票数据出错", e);
             } finally {
-                // 关闭线程池
-                if (executor != null) {
-                    executor.shutdown();
-                }
                 syncINStockDataLock.unlock();
-                syncINStockData.set(false); // 设置处理中标识为false
+                syncINStockData.set(false);
             }
         }
     }
 
+    /**
+     * 加载所有指数数据
+     */
     private void syncIndices(EStockType eStockType) {
         List<DataStockBean> list = new ArrayList<>();
         int totleStock = 1;
         try {
             while (totleStock > list.size()) {
                 try {
-                    //String result = HttpClientRequest.doGet(eStockType.stockUrl + "indices?key=" + eStockType.getStockKey() + "&country_id=" + eStockType.getContryId());
-                    //ReponseBase reponseBase = new Gson().fromJson(result, ReponseBase.class);
                     String result = HttpRequest.doGrabGet(eStockType.stockUrl + "indices?key=" + eStockType.getStockKey() + "&country_id=" + eStockType.getContryId());
                     // 把JSON数据解析为List<DataStockBean>
                     Type listType = new TypeToken<List<DataStockBean>>(){}.getType();
@@ -169,12 +155,44 @@
                     stockMapper.updateById(stock);
                 }*/
                 RedisKeyUtil.setCaCheKeyBaseStock(eStockType, o);
+
+                /*StockRealTimeBean stockRealTimeBean = new StockRealTimeBean();
+                stockRealTimeBean.setPid(o.getId());
+                stockRealTimeBean.setLast(o.getLast());
+                stockRealTimeBean.setHigh(o.getHigh());
+                stockRealTimeBean.setLow(o.getLow());
+                stockRealTimeBean.setPc(o.getChg());
+                stockRealTimeBean.setPcp(o.getChgPct()+ "%");
+                stockRealTimeBean.setTime(o.getTime());
+                RedisKeyUtil.setCacheRealTimeStock(eStockType, stockRealTimeBean);*/
             }
             stockRepository.saveAll(updateStockList);
+            cacheKData(eStockType.getCode(), list);
             log.info("同步指数 数据 成功 {}  总共同步数据 {}", eStockType.getCode(), list.size());
         } catch (Exception e) {
+            e.printStackTrace();
             log.error("同步指数列表出现异常: {}", e.getMessage());
         }
+    }
+
+    /**
+     * 同步指数股票后缓存k线图
+     */
+    public void cacheKData(String stockType, List<DataStockBean> list) {
+        String usCodeList = PropertiesUtil.getProperty("us_home_indices_code");
+        String mxCodeList = PropertiesUtil.getProperty("mx_home_indices_code");
+        for (DataStockBean dataStockBean : list) {
+            //缓存首页指数k线图
+            if (usCodeList.contains(dataStockBean.getId()) || mxCodeList.contains(dataStockBean.getId())) {
+                // 获取K线数据
+                Object kData = istockService.getKData(dataStockBean.getId(), "D", stockType);
+                if (kData != null) {
+                    //缓存redis
+                    RedisKeyUtil.setCaCheStockKData(stockType, dataStockBean.getId(), kData);
+                }
+            }
+        }
+        log.info("同步指数k线图 数据 成功 {}  总共同步数据 {}", stockType, list.size());
     }
 
     /**
@@ -218,7 +236,7 @@
         try {
             while (totleStock > list.size()) {
                 try {
-                    String result = HttpClientRequest.doGet(eStockType.stockUrl + "list?country_id=" + eStockType.getContryId() + "&size=1000&page=" + page + "&key=" + eStockType.stockKey);
+                    String result = HttpClientRequest.doGet(eStockType.stockUrl + "list?country_id=" + eStockType.getContryId() + "&size=100000&page=" + page + "&key=" + eStockType.stockKey);
                     ReponseBase reponseBase = new Gson().fromJson(result, ReponseBase.class);
                     list.addAll(reponseBase.getData());
                     page++;
@@ -233,9 +251,7 @@
             }
             List<String> stockCodeList = list.stream().map(DataStockBean::getId).collect(Collectors.toList());
             List<Stock> stockList = stockMapper.selectList(new QueryWrapper<Stock>().in("stock_code", stockCodeList));
-            int i = 1;
             List<Stock> updateStockList = new ArrayList<>();
-            System.out.println(new Date());
             for (DataStockBean o : list) {
                 //Stock stock = stockMapper.findStockByCode(o.getId());
                 Stock stock = stockList.stream()
@@ -276,11 +292,8 @@
                 }
                 updateStockList.add(stock);
                 RedisKeyUtil.setCaCheKeyBaseStock(eStockType, o);
-                System.out.println(i);
-                i++;
             }
             stockRepository.saveAll(updateStockList);
-            System.out.println(new Date());
             log.info("同步股票 数据 成功 {}  总共同步数据 {}", eStockType.getCode(), list.size());
         } catch (
                 Exception e) {
diff --git a/src/main/java/com/nq/ws/MXWebsocketRunClient.java b/src/main/java/com/nq/ws/MXWebsocketRunClient.java
index 0e29d5f..c7f540c 100644
--- a/src/main/java/com/nq/ws/MXWebsocketRunClient.java
+++ b/src/main/java/com/nq/ws/MXWebsocketRunClient.java
@@ -51,7 +51,9 @@
         heartbeatTimer.schedule(new TimerTask() {
             @Override
             public void run() {
-                send(("key:"+ eStockType.getStockKey()+":"+eStockType.getContryId()).getBytes());
+                if (isOpen()) {
+                    send(("key:"+ eStockType.getStockKey()+":"+eStockType.getContryId()).getBytes());
+                }
             }
         }, 0, 3000); // 每3秒发送一次心跳消息
     }
diff --git a/src/main/java/com/nq/ws/WebsocketRunClient.java b/src/main/java/com/nq/ws/WebsocketRunClient.java
index 7461bc0..5d9e127 100644
--- a/src/main/java/com/nq/ws/WebsocketRunClient.java
+++ b/src/main/java/com/nq/ws/WebsocketRunClient.java
@@ -52,7 +52,10 @@
         heartbeatTimer.schedule(new TimerTask() {
             @Override
             public void run() {
-                send(("key:"+ eStockType.getStockKey()+":"+eStockType.getContryId()).getBytes());
+                if (isOpen()) {
+                    send(("key:"+ eStockType.getStockKey()+":"+eStockType.getContryId()).getBytes());
+                }
+
             }
         }, 0, 3000); // 每3秒发送一次心跳消息
     }
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index eac7b5b..c30607d 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -92,9 +92,9 @@
 SZHB_WS_URL = ws://api-in-ws.js-stock.top
 SZHB_KEY = GBZAcUPLKZzDMDjvV9Ea
 
-
-
-
+#默认首页显示指数code
+us_home_indices_code=15882,15881,16571
+mx_home_indices_code=535610327,535610374,535610333
 
 #?? ?? - ????
 admin.auth.email.subject=???? - ??????
diff --git a/src/main/resources/mapper/StockMapper.xml b/src/main/resources/mapper/StockMapper.xml
index 6f3ddab..a19f47f 100644
--- a/src/main/resources/mapper/StockMapper.xml
+++ b/src/main/resources/mapper/StockMapper.xml
@@ -319,8 +319,10 @@
         <include refid="Base_Column_List"/>
          FROM stock
 
-    where stock_type = #{stockType}
-    and stock_spell not like '%.st%'
+    where stock_spell not like '%.st%'
+    <if test="stockType != null and stockType != '' ">
+      and stock_type = #{stockType}
+    </if>
     <if test="keyWords != null and keyWords != '' ">
       and (stock_spell like concat('%',#{keyWords},'%')  or stock_name like concat('%',#{keyWords},'%')  )
     </if>

--
Gitblit v1.9.3