file-parse

This commit is contained in:
N1KO 2024-12-19 20:13:33 +08:00
parent bbc1258a40
commit 1b710c56d6
41 changed files with 646 additions and 622 deletions

View File

@ -81,18 +81,18 @@
</dependency>
<!-- Sa-Token 权限认证在线文档https://sa-token.cc -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
<version>1.34.0</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>cn.dev33</groupId>-->
<!-- <artifactId>sa-token-spring-boot-starter</artifactId>-->
<!-- <version>1.34.0</version>-->
<!-- </dependency>-->
<!-- Sa-Token 插件整合SSO -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-sso</artifactId>
<version>1.34.0</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>cn.dev33</groupId>-->
<!-- <artifactId>sa-token-sso</artifactId>-->
<!-- <version>1.34.0</version>-->
<!-- </dependency>-->
<dependency>
<groupId>com.dtflys.forest</groupId>

View File

@ -1,31 +1,31 @@
package top.baogutang.admin.config;
import cn.dev33.satoken.exception.NotLoginException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import top.baogutang.common.domain.Results;
/**
* @description: 全局异常处理
* @author: nikooh
* @date: 2023/06/15 : 12:23
*/
@Slf4j
@RestControllerAdvice
public class SysGlobalExceptionHandler {
public SysGlobalExceptionHandler() {
//
}
@ExceptionHandler({NotLoginException.class})
public Results<Object> businessNotLoginException(NotLoginException e) {
log.error("请求发生错误code:{},message:{}", e.getCode(), e.getMessage());
return Results.failed(e.getCode(), e.getMessage());
}
}
//package top.baogutang.admin.config;
//
//import cn.dev33.satoken.exception.NotLoginException;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.web.bind.annotation.ExceptionHandler;
//import org.springframework.web.bind.annotation.RestControllerAdvice;
//import top.baogutang.common.domain.Results;
//
///**
// * @description: 全局异常处理
// * @author: nikooh
// * @date: 2023/06/15 : 12:23
// */
//@Slf4j
//@RestControllerAdvice
//public class SysGlobalExceptionHandler {
//
//
// public SysGlobalExceptionHandler() {
// //
// }
//
//
// @ExceptionHandler({NotLoginException.class})
// public Results<Object> businessNotLoginException(NotLoginException e) {
// log.error("请求发生错误code:{},message:{}", e.getCode(), e.getMessage());
// return Results.failed(e.getCode(), e.getMessage());
// }
//
//
//}

View File

@ -0,0 +1,18 @@
package top.baogutang.admin.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**")
.addResourceLocations("classpath:/static/");
registry.addResourceHandler("/file-parse/**")
.addResourceLocations("classpath:/static/");
}
}

View File

@ -1,24 +1,24 @@
package top.baogutang.admin.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
import top.baogutang.admin.handlers.KlineWebSocketHandler;
import javax.annotation.Resource;
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Resource
private KlineWebSocketHandler klineWebSocketHandler;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(klineWebSocketHandler, "/ws")
// 配置 WebSocket 端点并允许跨域
.setAllowedOrigins("*");
}
}
//package top.baogutang.admin.config;
//
//import org.springframework.context.annotation.Configuration;
//import org.springframework.web.socket.config.annotation.EnableWebSocket;
//import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
//import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
//import top.baogutang.admin.handlers.KlineWebSocketHandler;
//
//import javax.annotation.Resource;
//
//@Configuration
//@EnableWebSocket
//public class WebSocketConfig implements WebSocketConfigurer {
//
// @Resource
// private KlineWebSocketHandler klineWebSocketHandler;
//
// @Override
// public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
// registry.addHandler(klineWebSocketHandler, "/ws")
// // 配置 WebSocket 端点并允许跨域
// .setAllowedOrigins("*");
// }
//}

View File

@ -1,73 +1,73 @@
package top.baogutang.admin.controller;
import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.hutool.core.lang.PatternPool;
import cn.hutool.core.lang.Validator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import top.baogutang.admin.domain.req.SysUserLoginReq;
import top.baogutang.admin.domain.req.SysUserRegisterReq;
import top.baogutang.admin.services.ISysUserService;
import top.baogutang.common.domain.Results;
import javax.annotation.Resource;
/**
* @description: 后台用户控制器
* @author: nikooh
* @date: 2023/06/19 : 11:57
*/
@Slf4j
@RestController
@RequestMapping("/api/v1/admin/sysUser")
public class SysUserController {
@Resource
private ISysUserService sysUserService;
/**
* 后台系统用户注册
*
* @param sysUserRegisterReq 注册请求参数
* @return 注册结果
*/
@PostMapping("register")
public Results<Void> register(@Validated @RequestBody SysUserRegisterReq sysUserRegisterReq) {
if (!Validator.isMatchRegex(PatternPool.EMAIL, sysUserRegisterReq.getEmail())) {
return Results.failed("邮箱格式不正确!");
}
if (!Validator.isMatchRegex(PatternPool.MOBILE, sysUserRegisterReq.getMobile())) {
return Results.failed("手机号格式不正确!");
}
sysUserService.register(sysUserRegisterReq);
return Results.ok();
}
/**
* 登陆接口
*
* @param sysUserLoginReq 登陆请求参数
* @return 登陆用户信息
*/
@PostMapping("/login")
public Results<SaTokenInfo> login(@RequestBody SysUserLoginReq sysUserLoginReq) {
return Results.ok(sysUserService.login(sysUserLoginReq));
}
/**
* 登出接口
*/
@PostMapping("/logout")
@SaCheckLogin
public Results<Void> logout() {
sysUserService.logout();
return Results.ok();
}
}
//package top.baogutang.admin.controller;
//
//import cn.dev33.satoken.annotation.SaCheckLogin;
//import cn.dev33.satoken.stp.SaTokenInfo;
//import cn.hutool.core.lang.PatternPool;
//import cn.hutool.core.lang.Validator;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.validation.annotation.Validated;
//import org.springframework.web.bind.annotation.PostMapping;
//import org.springframework.web.bind.annotation.RequestBody;
//import org.springframework.web.bind.annotation.RequestMapping;
//import org.springframework.web.bind.annotation.RestController;
//import top.baogutang.admin.domain.req.SysUserLoginReq;
//import top.baogutang.admin.domain.req.SysUserRegisterReq;
//import top.baogutang.admin.services.ISysUserService;
//import top.baogutang.common.domain.Results;
//
//import javax.annotation.Resource;
//
///**
// * @description: 后台用户控制器
// * @author: nikooh
// * @date: 2023/06/19 : 11:57
// */
//@Slf4j
//@RestController
//@RequestMapping("/api/v1/admin/sysUser")
//public class SysUserController {
//
// @Resource
// private ISysUserService sysUserService;
//
// /**
// * 后台系统用户注册
// *
// * @param sysUserRegisterReq 注册请求参数
// * @return 注册结果
// */
// @PostMapping("register")
// public Results<Void> register(@Validated @RequestBody SysUserRegisterReq sysUserRegisterReq) {
// if (!Validator.isMatchRegex(PatternPool.EMAIL, sysUserRegisterReq.getEmail())) {
// return Results.failed("邮箱格式不正确!");
// }
// if (!Validator.isMatchRegex(PatternPool.MOBILE, sysUserRegisterReq.getMobile())) {
// return Results.failed("手机号格式不正确!");
// }
// sysUserService.register(sysUserRegisterReq);
// return Results.ok();
// }
//
// /**
// * 登陆接口
// *
// * @param sysUserLoginReq 登陆请求参数
// * @return 登陆用户信息
// */
// @PostMapping("/login")
// public Results<SaTokenInfo> login(@RequestBody SysUserLoginReq sysUserLoginReq) {
// return Results.ok(sysUserService.login(sysUserLoginReq));
// }
//
// /**
// * 登出接口
// */
// @PostMapping("/logout")
// @SaCheckLogin
// public Results<Void> logout() {
// sysUserService.logout();
// return Results.ok();
// }
//
//
//}

View File

@ -1,48 +1,48 @@
package top.baogutang.admin.controller;
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 top.baogutang.admin.domain.res.MarketCandlesRes;
import top.baogutang.admin.services.IVirtualCoinService;
import top.baogutang.common.domain.Results;
import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
/**
* @description:
* @author: nikooh
* @date: 2024/08/23 : 17:29
*/
@RestController
@RequestMapping("/api/v1/admin/virtualCoin")
public class VirtualCoinController {
@Resource
private IVirtualCoinService virtualCoinService;
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@GetMapping("/uiKline")
public Results<List<String[]>> uiKline(@RequestParam(name = "symbol") String symbol,
@RequestParam(name = "interval") String interval) {
return Results.ok(virtualCoinService.uiKline(symbol, interval));
}
@GetMapping("/uiKlineData")
public Results<List<MarketCandlesRes.KLineData>> uiKlineData(@RequestParam(name = "symbol") String symbol,
@RequestParam(name = "interval") String interval) {
List<MarketCandlesRes.KLineData> kLineDataList = virtualCoinService.uiKline(symbol, interval).stream()
.sorted(Collections.reverseOrder(Comparator.comparingLong(data -> Long.parseLong(data[0]))))
.limit(5)
.map(data -> MarketCandlesRes.KLineData.newInstance(data, DATE_FORMAT))
.collect(Collectors.toList());
return Results.ok(kLineDataList);
}
}
//package top.baogutang.admin.controller;
//
//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 top.baogutang.admin.domain.res.MarketCandlesRes;
//import top.baogutang.admin.services.IVirtualCoinService;
//import top.baogutang.common.domain.Results;
//
//import javax.annotation.Resource;
//import java.text.SimpleDateFormat;
//import java.util.Collections;
//import java.util.Comparator;
//import java.util.List;
//import java.util.stream.Collectors;
//
///**
// * @description:
// * @author: nikooh
// * @date: 2024/08/23 : 17:29
// */
//@RestController
//@RequestMapping("/api/v1/admin/virtualCoin")
//public class VirtualCoinController {
//
// @Resource
// private IVirtualCoinService virtualCoinService;
//
// private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//
// @GetMapping("/uiKline")
// public Results<List<String[]>> uiKline(@RequestParam(name = "symbol") String symbol,
// @RequestParam(name = "interval") String interval) {
// return Results.ok(virtualCoinService.uiKline(symbol, interval));
// }
//
// @GetMapping("/uiKlineData")
// public Results<List<MarketCandlesRes.KLineData>> uiKlineData(@RequestParam(name = "symbol") String symbol,
// @RequestParam(name = "interval") String interval) {
// List<MarketCandlesRes.KLineData> kLineDataList = virtualCoinService.uiKline(symbol, interval).stream()
// .sorted(Collections.reverseOrder(Comparator.comparingLong(data -> Long.parseLong(data[0]))))
// .limit(5)
// .map(data -> MarketCandlesRes.KLineData.newInstance(data, DATE_FORMAT))
// .collect(Collectors.toList());
// return Results.ok(kLineDataList);
// }
//}

View File

@ -1,98 +1,98 @@
package top.baogutang.admin.handlers;
import com.binance.connector.client.WebSocketStreamClient;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.web.socket.*;
import top.baogutang.common.utils.JacksonUtil;
import javax.annotation.Resource;
import java.io.IOException;
import java.io.Serializable;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
@Slf4j
@Component
public class KlineWebSocketHandler implements WebSocketHandler {
@Resource
private WebSocketStreamClient webSocketStreamClient;
private final Map<String, WebSocketSession> webSocketMap = new ConcurrentHashMap<>();
private volatile Integer connectionId;
@Override
public void afterConnectionEstablished(WebSocketSession webSocketSession) throws Exception {
//连接成功时调用该方法
log.info(">>>>>>>>>>WebSocket connected:{}<<<<<<<<<<", webSocketSession.getId());
webSocketMap.put(webSocketSession.getId(), webSocketSession);
}
@Override
public void handleMessage(WebSocketSession webSocketSession, WebSocketMessage<?> webSocketMessage) throws Exception {
// 获取客户端发送的消息
log.info(">>>>>>>>>>客户端ID:{} 发送消息:{}<<<<<<<<<<", webSocketSession.getId(), webSocketMessage.getPayload());
KlineMessage message = JacksonUtil.fromJson(webSocketMessage.getPayload().toString(), KlineMessage.class);
if (Objects.nonNull(connectionId)) {
webSocketStreamClient.closeConnection(connectionId);
}
// 使用 Binance Connector 开启 WebSocket 连接
connectionId = webSocketStreamClient.klineStream(message.getSymbol(), message.getInterval(), event -> {
log.info(">>>>>>>>>>binance event:{}<<<<<<<<<<", event);
// 将从 Binance 接收到的数据转发给前端
TextMessage textMessage = new TextMessage(event);
// 推送消息给所有连接的客户端
webSocketMap.entrySet()
.stream()
.filter(entry -> entry.getValue().isOpen())
.forEach(entry -> {
try {
entry.getValue().sendMessage(textMessage);
} catch (IOException e) {
log.error(">>>>>>>>>>消息发送错误:{}<<<<<<<<<<", e.getMessage(), e);
}
});
});
log.info(">>>>>>>>>启动了 Binance WebSocket 连接: {} , 监控交易对: {} 时间间隔: {}<<<<<<<<", connectionId, message.getSymbol(), message.getInterval());
}
@Override
public void handleTransportError(WebSocketSession webSocketSession, Throwable throwable) throws Exception {
//发生错误时调用该方法
log.error(">>>>>>>>>>WebSocket error: {}<<<<<<<<<<", throwable.getMessage(), throwable);
webSocketSession.close(CloseStatus.SERVER_ERROR);
webSocketMap.remove(webSocketSession.getId());
}
@Override
public void afterConnectionClosed(WebSocketSession webSocketSession, CloseStatus closeStatus) throws Exception {
//连接关闭时调用该方法
log.info(">>>>>>>>>>WebSocket closed:{}<<<<<<<<<<", webSocketSession.getId());
webSocketMap.remove(webSocketSession.getId());
if (CollectionUtils.isEmpty(webSocketMap)) {
log.info(">>>>>>>>>>client session all closed!<<<<<<<<<<");
webSocketStreamClient.closeAllConnections();
}
}
@Override
public boolean supportsPartialMessages() {
return false;
}
@Data
public static class KlineMessage implements Serializable {
private static final long serialVersionUID = -3288071423561766084L;
private String symbol;
private String interval;
}
}
//package top.baogutang.admin.handlers;
//
//import com.binance.connector.client.WebSocketStreamClient;
//import lombok.Data;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.stereotype.Component;
//import org.springframework.util.CollectionUtils;
//import org.springframework.web.socket.*;
//import top.baogutang.common.utils.JacksonUtil;
//
//import javax.annotation.Resource;
//import java.io.IOException;
//import java.io.Serializable;
//import java.util.Map;
//import java.util.Objects;
//import java.util.concurrent.ConcurrentHashMap;
//
//@Slf4j
//@Component
//public class KlineWebSocketHandler implements WebSocketHandler {
//
// @Resource
// private WebSocketStreamClient webSocketStreamClient;
//
// private final Map<String, WebSocketSession> webSocketMap = new ConcurrentHashMap<>();
//
// private volatile Integer connectionId;
//
// @Override
// public void afterConnectionEstablished(WebSocketSession webSocketSession) throws Exception {
// //连接成功时调用该方法
// log.info(">>>>>>>>>>WebSocket connected:{}<<<<<<<<<<", webSocketSession.getId());
// webSocketMap.put(webSocketSession.getId(), webSocketSession);
// }
//
// @Override
// public void handleMessage(WebSocketSession webSocketSession, WebSocketMessage<?> webSocketMessage) throws Exception {
// // 获取客户端发送的消息
// log.info(">>>>>>>>>>客户端ID:{} 发送消息:{}<<<<<<<<<<", webSocketSession.getId(), webSocketMessage.getPayload());
// KlineMessage message = JacksonUtil.fromJson(webSocketMessage.getPayload().toString(), KlineMessage.class);
// if (Objects.nonNull(connectionId)) {
// webSocketStreamClient.closeConnection(connectionId);
// }
// // 使用 Binance Connector 开启 WebSocket 连接
// connectionId = webSocketStreamClient.klineStream(message.getSymbol(), message.getInterval(), event -> {
// log.info(">>>>>>>>>>binance event:{}<<<<<<<<<<", event);
// // 将从 Binance 接收到的数据转发给前端
// TextMessage textMessage = new TextMessage(event);
//
// // 推送消息给所有连接的客户端
// webSocketMap.entrySet()
// .stream()
// .filter(entry -> entry.getValue().isOpen())
// .forEach(entry -> {
// try {
// entry.getValue().sendMessage(textMessage);
// } catch (IOException e) {
// log.error(">>>>>>>>>>消息发送错误:{}<<<<<<<<<<", e.getMessage(), e);
// }
// });
// });
// log.info(">>>>>>>>>启动了 Binance WebSocket 连接: {} , 监控交易对: {} 时间间隔: {}<<<<<<<<", connectionId, message.getSymbol(), message.getInterval());
// }
//
// @Override
// public void handleTransportError(WebSocketSession webSocketSession, Throwable throwable) throws Exception {
// //发生错误时调用该方法
// log.error(">>>>>>>>>>WebSocket error: {}<<<<<<<<<<", throwable.getMessage(), throwable);
// webSocketSession.close(CloseStatus.SERVER_ERROR);
// webSocketMap.remove(webSocketSession.getId());
// }
//
// @Override
// public void afterConnectionClosed(WebSocketSession webSocketSession, CloseStatus closeStatus) throws Exception {
// //连接关闭时调用该方法
// log.info(">>>>>>>>>>WebSocket closed:{}<<<<<<<<<<", webSocketSession.getId());
// webSocketMap.remove(webSocketSession.getId());
// if (CollectionUtils.isEmpty(webSocketMap)) {
// log.info(">>>>>>>>>>client session all closed!<<<<<<<<<<");
// webSocketStreamClient.closeAllConnections();
// }
// }
//
// @Override
// public boolean supportsPartialMessages() {
// return false;
// }
//
// @Data
// public static class KlineMessage implements Serializable {
//
// private static final long serialVersionUID = -3288071423561766084L;
//
// private String symbol;
//
// private String interval;
// }
//}

View File

@ -1,122 +1,122 @@
package top.baogutang.admin.schedule;
import cn.hutool.core.bean.BeanUtil;
import com.binance.connector.client.SpotClient;
import com.fasterxml.jackson.core.type.TypeReference;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.IJobHandler;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;
import top.baogutang.admin.utils.DingTalkMsgPushUtils;
import top.baogutang.admin.utils.OkCoinKLineUtil;
import top.baogutang.common.domain.BinanceResults;
import top.baogutang.common.utils.JacksonUtil;
import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
/**
* @description: OKCOIN K线数据
* @author: nikooh
* @date: 2024/08/22 : 09:52
*/
@Slf4j
@Component
@RefreshScope
public class OkCoinMarketCandlesHandler extends IJobHandler {
@Resource
private DingTalkMsgPushUtils dingTalkMsgPushUtils;
@Resource
private SpotClient spotClient;
public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
@Override
@XxlJob("marketCandlesHandler")
public ReturnT<String> execute(String params) throws Exception {
if (StringUtils.isBlank(params)) {
log.error(">>>>>>>>>>job params is null!<<<<<<<<<<");
return ReturnT.FAIL;
}
JobParams jobParams = JacksonUtil.fromJson(params, JobParams.class);
if (Objects.isNull(jobParams)) {
log.error(">>>>>>>>>>job params is null!<<<<<<<<<<");
return ReturnT.FAIL;
}
String interval = jobParams.getInterval();
Integer limit = jobParams.getLimit();
Arrays.stream(jobParams.getSymbolList().split(","))
.forEach(symbol -> {
KLinesRequestParameters kLinesRequestParameters = new KLinesRequestParameters(symbol, interval, limit);
Map<String, Object> parameters = BeanUtil.beanToMap(kLinesRequestParameters);
String resultStr = spotClient.createMarket().uiKlines(parameters);
if (StringUtils.isBlank(resultStr)) {
log.error(">>>>>>>>>>request result is null!<<<<<<<<<<");
return;
}
List<String[]> kLineDataList = JacksonUtil.fromJson(resultStr, new TypeReference<List<String[]>>() {
});
String[] kLineData = kLineDataList.get(0);
log.info(">>>>>>>>>>当前:【{}】 开盘价:【{}】 最高价:【{}】最低价:【{}】收盘价:【{}】<<<<<<<<<<", DATE_FORMAT.format(new Date(Long.parseLong(kLineData[0]))), kLineData[1], kLineData[2], kLineData[3], kLineData[4]);
kLineDataList = kLineDataList.stream()
.sorted(Comparator.comparing(data -> data[0], Comparator.reverseOrder()))
.limit(5)
.collect(Collectors.toList());
String markdownContent = OkCoinKLineUtil.getCoinMarkdownContent(symbol, kLineDataList);
dingTalkMsgPushUtils.robotMarkdownMsg("交易产品K线数据", markdownContent);
});
return ReturnT.SUCCESS;
}
@Data
public static class JobParams {
// BTCUSDT,ETHUSDT
private String symbolList;
// 时间粒度
// 1s, 1m, 3m, 5m, 15m, 30m, 1h, 2h, 4h, 6h, 8h, 12h, 1d, 3d, 1w, 1M
private String interval;
// 默认 500; 最大值 1000
private Integer limit;
}
@Data
public static class KLinesRequestParameters {
// BTCUSDT,ETHUSDT
private String symbol;
// 1s, 1m, 3m, 5m, 15m, 30m, 1h, 2h, 4h, 6h, 8h, 12h, 1d, 3d, 1w, 1M
private String interval;
// 默认 500; 最大值 1000
private Integer limit;
public KLinesRequestParameters(String symbol, String interval, Integer limit) {
this.symbol = symbol;
this.interval = interval;
this.limit = limit;
}
public KLinesRequestParameters(String symbol, String interval) {
this.symbol = symbol;
this.interval = interval;
}
}
}
//package top.baogutang.admin.schedule;
//
//import cn.hutool.core.bean.BeanUtil;
//import com.binance.connector.client.SpotClient;
//import com.fasterxml.jackson.core.type.TypeReference;
//import com.xxl.job.core.biz.model.ReturnT;
//import com.xxl.job.core.handler.IJobHandler;
//import com.xxl.job.core.handler.annotation.XxlJob;
//import lombok.Data;
//import lombok.extern.slf4j.Slf4j;
//import org.apache.commons.lang3.StringUtils;
//import org.springframework.cloud.context.config.annotation.RefreshScope;
//import org.springframework.stereotype.Component;
//import top.baogutang.admin.utils.DingTalkMsgPushUtils;
//import top.baogutang.admin.utils.OkCoinKLineUtil;
//import top.baogutang.common.domain.BinanceResults;
//import top.baogutang.common.utils.JacksonUtil;
//
//import javax.annotation.Resource;
//import java.text.SimpleDateFormat;
//import java.util.*;
//import java.util.stream.Collectors;
//
///**
// * @description: OKCOIN K线数据
// * @author: nikooh
// * @date: 2024/08/22 : 09:52
// */
//@Slf4j
//@Component
//@RefreshScope
//public class OkCoinMarketCandlesHandler extends IJobHandler {
//
// @Resource
// private DingTalkMsgPushUtils dingTalkMsgPushUtils;
//
// @Resource
// private SpotClient spotClient;
//
// public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
//
// @Override
// @XxlJob("marketCandlesHandler")
// public ReturnT<String> execute(String params) throws Exception {
//
//
// if (StringUtils.isBlank(params)) {
// log.error(">>>>>>>>>>job params is null!<<<<<<<<<<");
// return ReturnT.FAIL;
// }
// JobParams jobParams = JacksonUtil.fromJson(params, JobParams.class);
// if (Objects.isNull(jobParams)) {
// log.error(">>>>>>>>>>job params is null!<<<<<<<<<<");
// return ReturnT.FAIL;
// }
// String interval = jobParams.getInterval();
// Integer limit = jobParams.getLimit();
// Arrays.stream(jobParams.getSymbolList().split(","))
// .forEach(symbol -> {
// KLinesRequestParameters kLinesRequestParameters = new KLinesRequestParameters(symbol, interval, limit);
// Map<String, Object> parameters = BeanUtil.beanToMap(kLinesRequestParameters);
// String resultStr = spotClient.createMarket().uiKlines(parameters);
// if (StringUtils.isBlank(resultStr)) {
// log.error(">>>>>>>>>>request result is null!<<<<<<<<<<");
// return;
// }
// List<String[]> kLineDataList = JacksonUtil.fromJson(resultStr, new TypeReference<List<String[]>>() {
// });
// String[] kLineData = kLineDataList.get(0);
// log.info(">>>>>>>>>>当前:【{}】 开盘价:【{}】 最高价:【{}】最低价:【{}】收盘价:【{}】<<<<<<<<<<", DATE_FORMAT.format(new Date(Long.parseLong(kLineData[0]))), kLineData[1], kLineData[2], kLineData[3], kLineData[4]);
// kLineDataList = kLineDataList.stream()
// .sorted(Comparator.comparing(data -> data[0], Comparator.reverseOrder()))
// .limit(5)
// .collect(Collectors.toList());
// String markdownContent = OkCoinKLineUtil.getCoinMarkdownContent(symbol, kLineDataList);
// dingTalkMsgPushUtils.robotMarkdownMsg("交易产品K线数据", markdownContent);
//
// });
//
//
// return ReturnT.SUCCESS;
// }
//
// @Data
// public static class JobParams {
//
// // BTCUSDT,ETHUSDT
// private String symbolList;
//
// // 时间粒度
// // 1s, 1m, 3m, 5m, 15m, 30m, 1h, 2h, 4h, 6h, 8h, 12h, 1d, 3d, 1w, 1M
// private String interval;
//
// // 默认 500; 最大值 1000
// private Integer limit;
// }
//
// @Data
// public static class KLinesRequestParameters {
//
// // BTCUSDT,ETHUSDT
// private String symbol;
//
// // 1s, 1m, 3m, 5m, 15m, 30m, 1h, 2h, 4h, 6h, 8h, 12h, 1d, 3d, 1w, 1M
// private String interval;
//
// // 默认 500; 最大值 1000
// private Integer limit;
//
// public KLinesRequestParameters(String symbol, String interval, Integer limit) {
// this.symbol = symbol;
// this.interval = interval;
// this.limit = limit;
// }
//
// public KLinesRequestParameters(String symbol, String interval) {
// this.symbol = symbol;
// this.interval = interval;
// }
// }
//
//}

View File

@ -1,34 +1,34 @@
package top.baogutang.admin.services;
import cn.dev33.satoken.stp.SaTokenInfo;
import top.baogutang.admin.domain.req.SysUserLoginReq;
import top.baogutang.admin.domain.req.SysUserRegisterReq;
import top.baogutang.admin.domain.res.SysUserInfo;
/**
* @description:
* @author: nikooh
* @date: 2023/06/19 : 12:13
*/
public interface ISysUserService {
/**
* 后台系统用户注册
*
* @param sysUserRegisterReq 注册请求参数
*/
void register(SysUserRegisterReq sysUserRegisterReq);
/**
* 登陆接口
*
* @param sysUserLoginReq 登陆请求参数
* @return 登陆用户信息
*/
SaTokenInfo login(SysUserLoginReq sysUserLoginReq);
/**
* 登出接口
*/
void logout();
}
//package top.baogutang.admin.services;
//
//import cn.dev33.satoken.stp.SaTokenInfo;
//import top.baogutang.admin.domain.req.SysUserLoginReq;
//import top.baogutang.admin.domain.req.SysUserRegisterReq;
//import top.baogutang.admin.domain.res.SysUserInfo;
//
///**
// * @description:
// * @author: nikooh
// * @date: 2023/06/19 : 12:13
// */
//public interface ISysUserService {
//
// /**
// * 后台系统用户注册
// *
// * @param sysUserRegisterReq 注册请求参数
// */
// void register(SysUserRegisterReq sysUserRegisterReq);
//
// /**
// * 登陆接口
// *
// * @param sysUserLoginReq 登陆请求参数
// * @return 登陆用户信息
// */
// SaTokenInfo login(SysUserLoginReq sysUserLoginReq);
//
// /**
// * 登出接口
// */
// void logout();
//}

View File

@ -1,16 +1,16 @@
package top.baogutang.admin.services;
import java.util.List;
/**
* @description:
* @author: nikooh
* @date: 2024/08/23 : 17:50
*/
public interface IVirtualCoinService {
List<String[]> uiKline(String symbol, String interval);
// void startWebSocket(String symbol, String interval);
}
//package top.baogutang.admin.services;
//
//import java.util.List;
//
///**
// * @description:
// * @author: nikooh
// * @date: 2024/08/23 : 17:50
// */
//public interface IVirtualCoinService {
//
// List<String[]> uiKline(String symbol, String interval);
//
//// void startWebSocket(String symbol, String interval);
//
//}

View File

@ -1,105 +1,105 @@
package top.baogutang.admin.services.impl;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import top.baogutang.admin.dao.entity.SysUserEntity;
import top.baogutang.admin.dao.mapper.SysUserMapper;
import top.baogutang.admin.domain.req.SysUserLoginReq;
import top.baogutang.admin.domain.req.SysUserRegisterReq;
import top.baogutang.admin.services.ISysUserService;
import top.baogutang.common.annotation.RequestLimit;
import top.baogutang.common.constants.ErrorCodeEnum;
import top.baogutang.common.exceptions.BusinessException;
import javax.annotation.Resource;
import java.util.Objects;
import static top.baogutang.common.constants.CacheConstant.ENABLE;
import static top.baogutang.common.constants.CacheConstant.RANDOM_IMAGE_CACHE_KEY;
/**
* @description:
* @author: nikooh
* @date: 2023/06/19 : 12:14
*/
@Slf4j
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUserEntity> implements ISysUserService {
@Resource
private SysUserMapper sysUserMapper;
@Resource
private RedisTemplate<String, Object> redisTemplate;
@Resource
private PasswordEncoder passwordEncoder;
@Override
@RequestLimit
@Transactional(rollbackFor = Exception.class)
public void register(SysUserRegisterReq sysUserRegisterReq) {
String cacheKey = String.format(RANDOM_IMAGE_CACHE_KEY, sysUserRegisterReq.getCheckKey());
Object cacheCaptcha = redisTemplate.opsForValue().get(cacheKey);
if (Objects.isNull(cacheCaptcha)) {
throw new BusinessException(ErrorCodeEnum.CAPTCHA_NOT_EXISTS);
}
if (!sysUserRegisterReq.getCaptcha().equalsIgnoreCase((String) cacheCaptcha)) {
throw new BusinessException(ErrorCodeEnum.CAPTCHA_INCORRECT);
}
// 查询邮箱手机号是否已占用
SysUserEntity sysUser = baseMapper.selectByEmailOrMobile(sysUserRegisterReq.getEmail(), sysUserRegisterReq.getMobile());
if (Objects.nonNull(sysUser)) {
throw new BusinessException(ErrorCodeEnum.CURRENT_USER_EXISTS);
}
// 可以进行注册
SysUserEntity userEntity = new SysUserEntity();
userEntity.setId(IdWorker.getId());
userEntity.setUsername(sysUserRegisterReq.getEmail());
userEntity.setEmail(sysUserRegisterReq.getEmail());
userEntity.setMobile(sysUserRegisterReq.getMobile());
userEntity.setPassword(passwordEncoder.encode(sysUserRegisterReq.getPassword()));
saveOrUpdate(userEntity);
}
@Override
public SaTokenInfo login(SysUserLoginReq sysUserLoginReq) {
String password = sysUserLoginReq.getPassword();
SysUserEntity userEntity = this.findByEmail(sysUserLoginReq.getEmail());
if (userEntity == null) {
throw new BusinessException(ErrorCodeEnum.E_BIZ_DIGITAL_ART_USER_NOT_EXISTS);
}
boolean userVerify = passwordEncoder.matches(password, userEntity.getPassword());
if (!userVerify) {
throw new BusinessException(ErrorCodeEnum.PASSWORD_ERROR);
}
// Sa-Token
StpUtil.login(userEntity.getId());
return StpUtil.getTokenInfo();
}
@Override
public void logout() {
StpUtil.logout();
}
private SysUserEntity findByEmail(String email) {
Wrapper<SysUserEntity> wrapper = Wrappers.<SysUserEntity>query()
.lambda()
.eq(SysUserEntity::getEmail, email)
.eq(SysUserEntity::getEnableFlag, ENABLE);
return this.getOne(wrapper);
}
}
//package top.baogutang.admin.services.impl;
//
//import cn.dev33.satoken.stp.SaTokenInfo;
//import cn.dev33.satoken.stp.StpUtil;
//import com.baomidou.mybatisplus.core.conditions.Wrapper;
//import com.baomidou.mybatisplus.core.toolkit.IdWorker;
//import com.baomidou.mybatisplus.core.toolkit.Wrappers;
//import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.data.redis.core.RedisTemplate;
//import org.springframework.security.crypto.password.PasswordEncoder;
//import org.springframework.stereotype.Service;
//import org.springframework.transaction.annotation.Transactional;
//import top.baogutang.admin.dao.entity.SysUserEntity;
//import top.baogutang.admin.dao.mapper.SysUserMapper;
//import top.baogutang.admin.domain.req.SysUserLoginReq;
//import top.baogutang.admin.domain.req.SysUserRegisterReq;
//import top.baogutang.admin.services.ISysUserService;
//import top.baogutang.common.annotation.RequestLimit;
//import top.baogutang.common.constants.ErrorCodeEnum;
//import top.baogutang.common.exceptions.BusinessException;
//
//import javax.annotation.Resource;
//
//import java.util.Objects;
//
//import static top.baogutang.common.constants.CacheConstant.ENABLE;
//import static top.baogutang.common.constants.CacheConstant.RANDOM_IMAGE_CACHE_KEY;
//
///**
// * @description:
// * @author: nikooh
// * @date: 2023/06/19 : 12:14
// */
//@Slf4j
//@Service
//public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUserEntity> implements ISysUserService {
//
// @Resource
// private SysUserMapper sysUserMapper;
//
// @Resource
// private RedisTemplate<String, Object> redisTemplate;
//
// @Resource
// private PasswordEncoder passwordEncoder;
//
//
// @Override
// @RequestLimit
// @Transactional(rollbackFor = Exception.class)
// public void register(SysUserRegisterReq sysUserRegisterReq) {
// String cacheKey = String.format(RANDOM_IMAGE_CACHE_KEY, sysUserRegisterReq.getCheckKey());
// Object cacheCaptcha = redisTemplate.opsForValue().get(cacheKey);
// if (Objects.isNull(cacheCaptcha)) {
// throw new BusinessException(ErrorCodeEnum.CAPTCHA_NOT_EXISTS);
// }
// if (!sysUserRegisterReq.getCaptcha().equalsIgnoreCase((String) cacheCaptcha)) {
// throw new BusinessException(ErrorCodeEnum.CAPTCHA_INCORRECT);
// }
// // 查询邮箱手机号是否已占用
// SysUserEntity sysUser = baseMapper.selectByEmailOrMobile(sysUserRegisterReq.getEmail(), sysUserRegisterReq.getMobile());
// if (Objects.nonNull(sysUser)) {
// throw new BusinessException(ErrorCodeEnum.CURRENT_USER_EXISTS);
// }
// // 可以进行注册
// SysUserEntity userEntity = new SysUserEntity();
// userEntity.setId(IdWorker.getId());
// userEntity.setUsername(sysUserRegisterReq.getEmail());
// userEntity.setEmail(sysUserRegisterReq.getEmail());
// userEntity.setMobile(sysUserRegisterReq.getMobile());
// userEntity.setPassword(passwordEncoder.encode(sysUserRegisterReq.getPassword()));
// saveOrUpdate(userEntity);
// }
//
// @Override
// public SaTokenInfo login(SysUserLoginReq sysUserLoginReq) {
// String password = sysUserLoginReq.getPassword();
// SysUserEntity userEntity = this.findByEmail(sysUserLoginReq.getEmail());
// if (userEntity == null) {
// throw new BusinessException(ErrorCodeEnum.E_BIZ_DIGITAL_ART_USER_NOT_EXISTS);
// }
// boolean userVerify = passwordEncoder.matches(password, userEntity.getPassword());
// if (!userVerify) {
// throw new BusinessException(ErrorCodeEnum.PASSWORD_ERROR);
// }
// // Sa-Token
// StpUtil.login(userEntity.getId());
// return StpUtil.getTokenInfo();
// }
//
// @Override
// public void logout() {
// StpUtil.logout();
// }
//
//
// private SysUserEntity findByEmail(String email) {
// Wrapper<SysUserEntity> wrapper = Wrappers.<SysUserEntity>query()
// .lambda()
// .eq(SysUserEntity::getEmail, email)
// .eq(SysUserEntity::getEnableFlag, ENABLE);
// return this.getOne(wrapper);
// }
//}

View File

@ -1,48 +1,48 @@
package top.baogutang.admin.services.impl;
import cn.hutool.core.bean.BeanUtil;
import com.binance.connector.client.SpotClient;
import com.binance.connector.client.WebSocketStreamClient;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import top.baogutang.admin.schedule.OkCoinMarketCandlesHandler;
import top.baogutang.admin.services.IVirtualCoinService;
import top.baogutang.common.utils.JacksonUtil;
import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* @description:
* @author: nikooh
* @date: 2024/08/23 : 17:50
*/
@Slf4j
@Service
public class VirtualCoinServiceImpl implements IVirtualCoinService {
@Resource
private SpotClient spotClient;
@Resource
private WebSocketStreamClient webSocketStreamClient;
@Override
public List<String[]> uiKline(String symbol, String interval) {
OkCoinMarketCandlesHandler.KLinesRequestParameters kLinesRequestParameters = new OkCoinMarketCandlesHandler.KLinesRequestParameters(symbol, interval);
Map<String, Object> parameters = BeanUtil.beanToMap(kLinesRequestParameters, Boolean.FALSE, Boolean.TRUE);
String resultStr = spotClient.createMarket().uiKlines(parameters);
if (StringUtils.isBlank(resultStr)) {
log.error(">>>>>>>>>>request result is null!<<<<<<<<<<");
return Collections.emptyList();
}
return JacksonUtil.fromJson(resultStr, new TypeReference<List<String[]>>() {
});
}
}
//package top.baogutang.admin.services.impl;
//
//import cn.hutool.core.bean.BeanUtil;
//import com.binance.connector.client.SpotClient;
//import com.binance.connector.client.WebSocketStreamClient;
//import com.fasterxml.jackson.core.type.TypeReference;
//import lombok.extern.slf4j.Slf4j;
//import org.apache.commons.lang3.StringUtils;
//import org.springframework.stereotype.Service;
//import top.baogutang.admin.schedule.OkCoinMarketCandlesHandler;
//import top.baogutang.admin.services.IVirtualCoinService;
//import top.baogutang.common.utils.JacksonUtil;
//
//import javax.annotation.Resource;
//import java.util.Collections;
//import java.util.List;
//import java.util.Map;
//
///**
// * @description:
// * @author: nikooh
// * @date: 2024/08/23 : 17:50
// */
//@Slf4j
//@Service
//public class VirtualCoinServiceImpl implements IVirtualCoinService {
//
// @Resource
// private SpotClient spotClient;
//
// @Resource
// private WebSocketStreamClient webSocketStreamClient;
//
//
// @Override
// public List<String[]> uiKline(String symbol, String interval) {
// OkCoinMarketCandlesHandler.KLinesRequestParameters kLinesRequestParameters = new OkCoinMarketCandlesHandler.KLinesRequestParameters(symbol, interval);
// Map<String, Object> parameters = BeanUtil.beanToMap(kLinesRequestParameters, Boolean.FALSE, Boolean.TRUE);
// String resultStr = spotClient.createMarket().uiKlines(parameters);
// if (StringUtils.isBlank(resultStr)) {
// log.error(">>>>>>>>>>request result is null!<<<<<<<<<<");
// return Collections.emptyList();
// }
// return JacksonUtil.fromJson(resultStr, new TypeReference<List<String[]>>() {
// });
// }
//
//}

View File

@ -4,5 +4,5 @@ spring:
main:
allow-bean-definition-overriding: true
resources:
static-locations: classpath:/templates/
# resources:
# static-locations: classpath:/templates/

View File

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 8.1 KiB

View File

@ -1,13 +1,19 @@
<!DOCTYPE html>
<html lang="en">
<html lang="zh-CN">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<link rel="icon" type="image/png" href="NIKO.png"/>
<link rel="icon" type="image/png" href="/NIKO.png" th:href="@{/NIKO.png}">
<title>BAOGUTANG-FILE</title>
<link href="css/bootstrap.min.css" rel="stylesheet">
<link href="css/font-awesome.min.css" rel="stylesheet">
<link href="css/base.css" rel="stylesheet">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta name="HandheldFriendly" content="True"/>
<meta name="MobileOptimized" content="320"/>
<meta http-equiv="Cache-Control" content="max-age=7200"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="robots" content="all"/>
<meta name="author" content="BAOGUTANG-FILE"/>
<link href="/css/bootstrap.min.css" rel="stylesheet" th:href="@{/css/bootstrap.min.css}">
<link href="/css/font-awesome.min.css" rel="stylesheet" th:href="@{/css/font-awesome.min.css}">
<link href="/css/base.css" rel="stylesheet" th:href="@{/css/base.css}">
<style>
body {
font-family: "Microsoft YaHei", Arial, sans-serif;

View File

@ -1,7 +1,7 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<link rel="icon" type="image/png" href="NIKO.png">
<link rel="icon" type="image/png" href="../static/NIKO.png" th:href="@{/NIKO.png}">
<title>JSON在线解析及格式化验证</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta name="HandheldFriendly" content="True"/>
@ -11,9 +11,9 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="robots" content="all"/>
<meta name="author" content="BAOGUTANG-JSON"/>
<link href="css/bootstrap.min.css" rel="stylesheet" th:href="@{css/bootstrap.min.css}">
<link href="css/font-awesome.min.css" rel="stylesheet" th:href="@{css/font-awesome.min.css}">
<link href="css/base.css" rel="stylesheet" th:href="@{css/base.css}">
<link href="../static/css/bootstrap.min.css" rel="stylesheet" th:href="@{css/bootstrap.min.css}">
<link href="../static/css/font-awesome.min.css" rel="stylesheet" th:href="@{css/font-awesome.min.css}">
<link href="../static/css/base.css" rel="stylesheet" th:href="@{css/base.css}">
<style>
body, html {
min-height: 100%;