| | |
| | | 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; |
| | | import com.github.pagehelper.PageInfo; |
| | | 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.service.*; |
| | | import com.nq.utils.http.HttpClientRequest; |
| | | import com.nq.utils.PropertiesUtil; |
| | | import com.nq.utils.redis.RedisKeyConstant; |
| | | import com.nq.utils.redis.RedisKeyUtil; |
| | | import com.nq.utils.redis.RedisShardedPoolUtils; |
| | | import com.nq.utils.stock.pinyin.GetPyByChinese; |
| | | import com.nq.utils.stock.qq.QqStockApi; |
| | |
| | | import java.net.HttpURLConnection; |
| | | import java.net.URL; |
| | | import java.text.SimpleDateFormat; |
| | | import java.time.Instant; |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | import java.time.ZoneOffset; |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.util.*; |
| | | import java.util.concurrent.CompletableFuture; |
| | | 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; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.web.client.RestTemplate; |
| | | |
| | | import static com.nq.utils.timeutil.DateTimeUtil.getWeekDay; |
| | | |
| | |
| | | @Autowired |
| | | IPriceServices iPriceServices; |
| | | |
| | | |
| | | public ServerResponse getMarket() { |
| | | String market_url = PropertiesUtil.getProperty("sina.market.url"); |
| | | String result = null; |
| | |
| | | List<Stock> stockList = new ArrayList<>(); |
| | | if (stockType.equals("99")) { |
| | | PageHelper.startPage(pageNum, pageSize); |
| | | stockList.addAll(stockMapper.findZtStockListByKeyWords(keyWords, stockPlate, "IN", Integer.valueOf(0))); |
| | | stockList.addAll(stockMapper.findZtStockListByKeyWords(keyWords, stockPlate, EStockType.ST.getCode(), Integer.valueOf(0))); |
| | | } else if (stockType.equals("100")) { |
| | | User user = iUserService.getCurrentRefreshUser(request); |
| | | if (user == null) { |
| | |
| | | @Override |
| | | public ServerResponse getStockByType(int pageNum, int pageSize, String orderBy, String keyWords, String stockType, HttpServletRequest request) { |
| | | List<Stock> stockList = new ArrayList<>(); |
| | | if(stockType.equals(EStockType.IN.getCode())){ |
| | | PageHelper.startPage(pageNum, pageSize); |
| | | stockList.addAll(stockMapper.findStockByType(orderBy,stockType,keyWords)); |
| | | }else{ |
| | | PageHelper.startPage(pageNum, pageSize); |
| | | stockList.addAll(stockMapper.findStockTypeDz(orderBy,EStockType.IN.getCode(), keyWords)); |
| | | } |
| | | |
| | | |
| | | |
| | | PageHelper.startPage(pageNum, pageSize); |
| | | stockList.addAll(stockMapper.findStockByType(orderBy,stockType,keyWords)); |
| | | List<StockListVO> stockListVOS = Lists.newArrayList(); |
| | | if (stockList.size() > 0){ |
| | | stockListVOS.addAll(Objects.requireNonNull(StockApi.getStockReailTimes(stockList))); |
| | | } |
| | | for (int i = 0; i <stockListVOS.size() ; i++) { |
| | | stockListVOS.get(i).setNowPrice(iPriceServices.getNowPrice(stockListVOS.get(i).getCode(),stockType).toString()); |
| | | } |
| | | RPageInfo pageInfo = new RPageInfo(); |
| | | pageInfo.setList(stockListVOS); |
| | |
| | | |
| | | |
| | | public ServerResponse getSingleStock(String code, HttpServletRequest request) { |
| | | |
| | | if(code.equals("GOLD")){ |
| | | String price = RedisShardedPoolUtils.get(RedisKeyConstant.gold); |
| | | StockVO stockVO = new StockVO(); |
| | | stockVO.setNowPrice(price); |
| | | stockVO.setName(code); |
| | | Map map = Maps.newHashMap(); |
| | | map.put("stock", stockVO); |
| | | return ServerResponse.createBySuccess(map); |
| | | }else if(code.equals("CRUDE OIL")){ |
| | | String price = RedisShardedPoolUtils.get(RedisKeyConstant.crude_oil); |
| | | StockVO stockVO = new StockVO(); |
| | | stockVO.setNowPrice(price); |
| | | stockVO.setName(code); |
| | | Map map = Maps.newHashMap(); |
| | | map.put("stock", stockVO); |
| | | return ServerResponse.createBySuccess(map); |
| | | }else{ |
| | | if (StringUtils.isBlank(code)) |
| | | return ServerResponse.createByErrorMsg(""); |
| | | Stock stock = stockMapper.findStockByCode(code); |
| | | DataStockBean cacheBaseStock = RedisKeyUtil.getCacheBaseStock(stock); |
| | | Integer depositAmt = 0; |
| | | String introduction = null; |
| | | StockVO stockVO = StockApi.assembleInStockVO(stock); |
| | | stockVO.setDepositAmt(depositAmt); |
| | | stockVO.setNowPrice(iPriceServices.getNowPrice(stock.getStockCode()).toString()); |
| | | stockVO.setType(stock.getStockType()); |
| | | stockVO.setId(stock.getId().intValue()); |
| | | stockVO.setCode(stock.getStockCode()); |
| | | stockVO.setName(stock.getStockName()); |
| | | stockVO.setSpell(stock.getStockSpell()); |
| | | stockVO.setGid(stock.getStockGid().toUpperCase()); |
| | | Map<String, Object> newStock = iPriceServices.getNewStock(stock.getStockCode()); |
| | | stockVO.setHcrate(newStock.get("ChgPct").toString().replaceAll("%", "")); |
| | | stockVO.setToday_max(newStock.get("High").toString()); |
| | | stockVO.setToday_min(newStock.get("Low").toString()); |
| | | if(null != cacheBaseStock){ |
| | | stockVO.setOpen_px(cacheBaseStock.getOpen()); |
| | | stockVO.setPreclose_px(cacheBaseStock.getPrevClose()); |
| | | } |
| | | Map map = Maps.newHashMap(); |
| | | map.put("introduction", introduction); |
| | | map.put("stock", stockVO); |
| | | return ServerResponse.createBySuccess(map); |
| | | } |
| | | } |
| | | |
| | | public Map getSingleStock(String code) { |
| | | if (StringUtils.isBlank(code)) |
| | | return ServerResponse.createByErrorMsg(""); |
| | | return null; |
| | | Stock stock = stockMapper.findStockByCode(code); |
| | | DataStockBean cacheBaseStock = RedisKeyUtil.getCacheBaseStock(stock); |
| | | Integer depositAmt = 0; |
| | | String introduction = null; |
| | | StockVO stockVO = StockApi.assembleInStockVO(stock); |
| | |
| | | stockVO.setName(stock.getStockName()); |
| | | stockVO.setSpell(stock.getStockSpell()); |
| | | stockVO.setGid(stock.getStockGid().toUpperCase()); |
| | | if(null != cacheBaseStock){ |
| | | stockVO.setOpen_px(cacheBaseStock.getOpen()); |
| | | stockVO.setPreclose_px(cacheBaseStock.getPrevClose()); |
| | | } |
| | | Map map = Maps.newHashMap(); |
| | | map.put("introduction", introduction); |
| | | map.put("stock", stockVO); |
| | | return ServerResponse.createBySuccess(map); |
| | | return map; |
| | | } |
| | | |
| | | |
| | |
| | | EchartsDataVO echartsDataVO = StockApi.assembleEchartsDataVO(minDataVO); |
| | | return ServerResponse.createBySuccess(echartsDataVO); |
| | | } |
| | | @lombok.Data |
| | | class kData { |
| | | long t; |
| | | String c; |
| | | String o; |
| | | String h; |
| | | String l; |
| | | String v; |
| | | String vo; |
| | | } |
| | | |
| | | /*股票日线-K线*/ |
| | | |
| | | //黄金 |
| | | private static final String gold_API_URL = "http://139.196.211.109/ldMetal_k.action?username=Qq112233&password=3ce25a66d5b3a8cd661024fea6c79388&id=AUUSDO&num=-100&period="; |
| | | |
| | | //原油 |
| | | private static final String crude_oil_API_URL = "http://47.112.169.122/fOption_k.action?username=Qq112233&password=3ce25a66d5b3a8cd661024fea6c79388&id=@CL0W&num=-100&period="; |
| | | |
| | | /*股票日线-K线*/ |
| | | @Override |
| | | public Object getKData(String pid, String interval, String stockType) { |
| | | EStockType eStockType = EStockType.getEStockTypeByCode(stockType); |
| | | if(eStockType == EStockType.IN){ |
| | | return HttpUtil.get(eStockType.stockUrl+"api/all/getKData.do?pid="+pid+"&interval="+interval+"&stockType=in"); |
| | | if(stockType.equals("GOLD")){ |
| | | // 使用RestTemplate发起HTTP请求 |
| | | String response = RedisShardedPoolUtils.get("k_gold_"+interval.toLowerCase()); |
| | | return parseData(interval,response, stockType); |
| | | }else if(stockType.equals("CRUDE OIL")){ |
| | | // 使用RestTemplate发起HTTP请求 |
| | | RestTemplate restTemplate = new RestTemplate(); |
| | | String response = RedisShardedPoolUtils.get("k_crude_oil_"+interval.toLowerCase()); |
| | | return parseData(interval,response, stockType); |
| | | }else{ |
| | | EStockType eStockType = EStockType.getEStockTypeByCode(stockType); |
| | | Object object = HttpUtil.get(eStockType.stockUrl + "kline?pid=" + pid + "&interval=" + interval + "&key=" + eStockType.stockKey); |
| | | Gson gson = new Gson(); |
| | | List<kData> dataList = gson.fromJson(object.toString(), new TypeToken<List<kData>>(){}.getType()); |
| | | |
| | | Stock stock = stockMapper.selectOne(new LambdaQueryWrapper<Stock>().eq(Stock::getStockCode, pid).eq(Stock::getStockType, EStockType.ST.getCode())); |
| | | BigDecimal nowPrice = iPriceServices.getNowPrice(stock.getStockCode()); |
| | | Map singleStock = getSingleStock(stock.getStockCode()); |
| | | StockVO stockVO = (StockVO)singleStock.get("stock"); |
| | | // 修改 List 中的最后一条数据 |
| | | kData lastData = dataList.get(dataList.size() - 1); |
| | | lastData.setC(nowPrice.toString()); |
| | | lastData.setO(stockVO.getOpen_px()); |
| | | lastData.setH(stockVO.getToday_max()); |
| | | lastData.setL(stockVO.getToday_min()); |
| | | return gson.toJson(dataList); |
| | | } |
| | | return HttpUtil.get(eStockType.stockUrl + "kline?pid=" + pid + "&interval=" + interval + "&key=" + eStockType.stockKey); |
| | | } |
| | | |
| | | public List<kData> parseData(String interval,String data,String key) { |
| | | String price = null; |
| | | if(key.equals("GOLD")){ |
| | | price = RedisShardedPoolUtils.get(RedisKeyConstant.gold); |
| | | }else if(key.equals("CRUDE OIL")){ |
| | | price = RedisShardedPoolUtils.get(RedisKeyConstant.crude_oil); |
| | | } |
| | | List<kData> kDataList = new ArrayList<>(); |
| | | |
| | | // 将数据按行分割 |
| | | String[] lines = data.split("\n"); |
| | | |
| | | // 跳过第一行(列名) |
| | | for (int i = 1; i < lines.length; i++) { |
| | | String line = lines[i].trim(); |
| | | // 确保行不为空 |
| | | if (!line.isEmpty()) { |
| | | String[] fields = line.split(","); |
| | | |
| | | // 确保每行有至少7个字段:日期、开盘价、最高价、最低价、收盘价、成交量、持仓量 |
| | | if ((key.equals("CRUDE OIL") && fields.length == 7) || (key.equals("GOLD") && fields.length == 5)) { |
| | | kData kData = new kData(); |
| | | kData.setT(convDate(fields[0],interval)); |
| | | kData.setC(price); |
| | | kData.setO(fields[1]); |
| | | kData.setH(fields[2]); |
| | | kData.setL(fields[3]); |
| | | if(key.equals("CRUDE OIL")){ |
| | | kData.setV(fields[4]); |
| | | kData.setVo(fields[5]); |
| | | }else{ |
| | | kData.setV("0"); |
| | | kData.setVo("0"); |
| | | } |
| | | // 将每一条 KData 对象添加到列表中 |
| | | kDataList.add(kData); |
| | | } |
| | | } |
| | | } |
| | | return kDataList; |
| | | } |
| | | |
| | | |
| | | // 常量,定义日期格式 |
| | | private static final String DATE_PATTERN = "yyyyMMdd"; |
| | | private static final String DATE_TIME_PATTERN = "yyyyMMdd HH:mm"; |
| | | |
| | | public long convDate(String dateStr, String interval) { |
| | | // 输入校验,确保 dateStr 和 interval 不为 null 或空 |
| | | if (dateStr == null || dateStr.trim().isEmpty() || interval == null || interval.trim().isEmpty()) { |
| | | throw new IllegalArgumentException("日期字符串或时间间隔不能为空。"); |
| | | } |
| | | |
| | | // 根据 interval 的值,选择日期格式 |
| | | String pattern = (interval.equalsIgnoreCase("D") || interval.equalsIgnoreCase("W") || interval.equalsIgnoreCase("M")) |
| | | ? DATE_PATTERN : DATE_TIME_PATTERN; |
| | | |
| | | // 创建 DateTimeFormatter,使用合适的格式 |
| | | DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern); |
| | | |
| | | try { |
| | | // 根据是否包含时间部分,选择 LocalDate 或 LocalDateTime 进行解析 |
| | | if (pattern.equals(DATE_PATTERN)) { |
| | | LocalDate localDate = LocalDate.parse(dateStr, formatter); |
| | | Instant timestamp = localDate.atStartOfDay(ZoneOffset.UTC).toInstant(); |
| | | return timestamp.getEpochSecond(); |
| | | } else { |
| | | LocalDateTime localDateTime = LocalDateTime.parse(dateStr, formatter); |
| | | Instant timestamp = localDateTime.toInstant(ZoneOffset.UTC); |
| | | return timestamp.getEpochSecond(); |
| | | } |
| | | } catch (Exception e) { |
| | | throw new IllegalArgumentException("无效的日期格式: " + dateStr, e); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | |
| | | return ServerResponse.createBySuccess(this.stockMapper.selectByPrimaryKey(stockId)); |
| | | } |
| | | |
| | | public ServerResponse<PageInfo> listByAdmin(Integer showState, Integer lockState, String code, String name, String stockPlate, String stockType, int pageNum, int pageSize, HttpServletRequest request) { |
| | | public ServerResponse<PageInfo> listByAdmin(String stockGid,Integer showState, Integer lockState, String code, String name, String stockPlate, String stockType, int pageNum, int pageSize, HttpServletRequest request) { |
| | | PageHelper.startPage(pageNum, pageSize); |
| | | List<Stock> stockList = this.stockMapper.listByAdmin(showState, lockState, code, name, stockPlate, stockType); |
| | | List<Stock> stockList = this.stockMapper.listByAdmin(stockGid,showState, lockState, code, name, stockPlate, stockType); |
| | | List<StockAdminListVO> stockAdminListVOS = Lists.newArrayList(); |
| | | for (Stock stock : stockList) { |
| | | StockAdminListVO stockAdminListVO = assembleStockAdminListVO(stock); |