m2pool项目提交

Signed-off-by: jxy_duyi <2826961034@qq.com>
This commit is contained in:
jxy_duyi
2025-04-10 18:44:21 +08:00
parent faaeb24007
commit c4f34073c4
508 changed files with 50991 additions and 0 deletions

View File

@@ -0,0 +1,213 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>m2pool-modules</artifactId>
<groupId>com.m2pool</groupId>
<version>3.5.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>m2pool-chat</artifactId>
<!-- <packaging>war</packaging>-->
<!-- <dependencies>-->
<!-- <dependency>-->
<!-- <groupId>junit</groupId>-->
<!-- <artifactId>junit</artifactId>-->
<!-- <version>4.13.1</version>-->
<!-- <scope>test</scope>-->
<!-- </dependency>-->
<!-- </dependencies>-->
<dependencies>
<!-- SpringCloud Alibaba Nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- SpringCloud Alibaba Nacos Config -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- SpringCloud Alibaba Sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- SpringBoot Actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- Swagger UI -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.fox.version}</version>
</dependency>
<!-- Mysql Connector -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-maven-plugin</artifactId>
<scope>provided</scope>
</dependency>
<!-- &lt;!&ndash; Mybatis-Plus &ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>com.baomidou</groupId>-->
<!-- <artifactId>mybatis-plus-boot-starter</artifactId>-->
<!-- <exclusions>-->
<!-- <exclusion>-->
<!-- <artifactId>jsqlparser</artifactId>-->
<!-- <groupId>com.github.jsqlparser</groupId>-->
<!-- </exclusion>-->
<!--&lt;!&ndash; <exclusion>&ndash;&gt;-->
<!--&lt;!&ndash; <artifactId>mybatis</artifactId>&ndash;&gt;-->
<!--&lt;!&ndash; <groupId>org.mybatis</groupId>&ndash;&gt;-->
<!--&lt;!&ndash; </exclusion>&ndash;&gt;-->
<!-- </exclusions>-->
<!-- </dependency>-->
<!-- M2Pool Common DataSource -->
<dependency>
<groupId>com.m2pool</groupId>
<artifactId>common-datasource</artifactId>
</dependency>
<!-- M2Pool Common security -->
<dependency>
<groupId>com.m2pool</groupId>
<artifactId>common-security</artifactId>
</dependency>
<dependency>
<groupId>com.m2pool</groupId>
<artifactId>common-log</artifactId>
</dependency>
<dependency>
<groupId>com.m2pool</groupId>
<artifactId>common-swagger</artifactId>
</dependency>
<!-- WebSocket-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.java-websocket</groupId>
<artifactId>Java-WebSocket</artifactId>
<version>1.3.5</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.6.2</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
<scope>compile</scope>
</dependency>
<!--google两步认证相关-->
<dependency>
<groupId>de.taimos</groupId>
<artifactId>totp</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.10</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.3.0</version>
</dependency>
</dependencies>
<profiles>
<profile>
<!-- 本地环境 -->
<id>dev</id>
<properties>
<spring.profile>dev</spring.profile>
<nacos.server.address>127.0.0.1:8808</nacos.server.address>
</properties>
<activation>
<!-- 是否默认激活 -->
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<!-- 测试环境 -->
<id>test</id>
<properties>
<spring.profile>test</spring.profile>
<nacos.server.address>127.0.0.1:8808</nacos.server.address>
</properties>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
</profile>
<profile>
<!-- 生产环境 -->
<id>prod</id>
<properties>
<spring.profile>prod</spring.profile>
<nacos.server.address>127.0.0.1:8808</nacos.server.address>
</properties>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
</profile>
</profiles>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,34 @@
package com.m2pool.chat;
import com.m2pool.common.security.annotation.EnableCustomConfig;
import com.m2pool.common.security.annotation.EnableM2PoolFeignClients;
import com.m2pool.common.swagger.annotation.EnableCustomSwagger2;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
/**
* @Description 在线客服服务入口类
* @Date 2025/2/25 10:42
* @Author dy
*/
@EnableCustomConfig
@EnableCustomSwagger2
@EnableM2PoolFeignClients
@SpringBootApplication
@MapperScan({"com.m2pool.chat.mapper"})
public class M2ChatApplication {
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(M2ChatApplication.class,args);
System.out.println("m2pool矿池 开放api微服务启动成功");
}
}

View File

@@ -0,0 +1,21 @@
package com.m2pool.chat.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
import javax.websocket.server.ServerEndpointConfig;
/**
* @Description TODO
* @Date 2025/2/25 14:43
* @Author 杜懿
*/
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter(){
return new ServerEndpointExporter();
}
}

View File

@@ -0,0 +1,45 @@
package com.m2pool.chat.controller;
import com.m2pool.chat.entity.ChatMessage;
import com.m2pool.chat.entity.ChatMsg;
import com.m2pool.chat.service.ChatService;
import com.m2pool.chat.service.WebSocketServer;
import com.m2pool.chat.vo.ChatHistoryVo;
import com.m2pool.common.core.utils.StringUtils;
import com.m2pool.common.core.web.Result.AjaxResult;
import com.m2pool.common.core.web.controller.BaseController;
import com.m2pool.system.api.entity.SysUser;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.List;
/**
* @Description TODO
* @Date 2025/2/24 15:05
* @Author 杜懿
*/
@RestController
@RequestMapping("/chat")
public class ChatController extends BaseController {
@Resource
private ChatService chatService;
//@Resource
// //private WebSocketServer webSocketServer;
@GetMapping("/history")
public AjaxResult getChatHistory(@RequestBody ChatHistoryVo vo) {
if(StringUtils.isNull(vo)){
return AjaxResult.error("请求参数为空");
}
String identifier = StringUtils.isNotBlank(vo.getEmail()) ? vo.getEmail() : vo.getBrowserId();
return chatService.getHistory(identifier);
}
}

View File

@@ -0,0 +1,22 @@
package com.m2pool.chat.entity;
import lombok.Data;
import java.util.Date;
/**
* @Description TODO
* @Date 2025/3/7 15:53
* @Author 杜懿
*/
@Data
public class ChatMessage {
private Long id;
private String senderType; // USER 0/CUSTOMER_SERVICE 1
private String senderId; // 邮箱或客服ID
private String receiverId;
private String content;
private String userIdentifier; // 邮箱或浏览器指纹
private String browserFingerprint;
private Date createdTime;
}

View File

@@ -0,0 +1,60 @@
package com.m2pool.chat.entity;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Transient;
import java.util.Date;
/**
* @Description TODO
* @Date 2025/2/28 18:11
* @Author 杜懿
*/
@Data
public class ChatMsg {
@Id
private String id;
/**
* 创建时间
*/
@JsonFormat(pattern = "yyyy_MM_dd_HH_mm_ss")
private Date createTime=new Date();
/**
* 通信keysendId_receiveId
*/
private String msgKey;
/**
* 通信消息
*/
private String chatMsg;
/**
* 发送id
*/
private String sendId;
/**
* 接收id
*/
private String receiveId;
/**
* 查看状态 0未看 1已看
*/
private String readState;
/**
*1为我 0 为他
*/
@Transient
private Integer flag;
@Transient
private String name;
}

View File

@@ -0,0 +1,20 @@
package com.m2pool.chat.mapper;
import com.m2pool.chat.entity.ChatMessage;
import com.m2pool.common.datasource.annotation.Master;
import org.apache.ibatis.annotations.Param;
import javax.validation.constraints.Pattern;
import java.util.List;
/**
* @Description 角色数据层
* @Date 2024/6/12 17:37
* @Author dy
*/
@Master
public interface ChatMapper {
public boolean insert(@Param("vo") ChatMessage vo);
}

View File

@@ -0,0 +1,30 @@
package com.m2pool.chat.service;
import com.m2pool.common.core.web.Result.AjaxResult;
import com.m2pool.system.api.entity.SysUser;
import org.springframework.cache.CacheManager;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Description TODO
* @Date 2025/2/28 18:06
* @Author 杜懿
*/
public interface ChatService {
//public AjaxResult userList(UserItem userItem, SysUser data);
public AjaxResult getHistory(String identifier);
}

View File

@@ -0,0 +1,169 @@
package com.m2pool.chat.service;
import com.alibaba.fastjson.JSONObject;
import com.m2pool.chat.entity.ChatMsg;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @Description TODO
* @Date 2025/2/28 18:02
* @Author 杜懿
*/
@ServerEndpoint(value = "/ws/asset")
@Component
public class WebSocketServer {
private static ChatService chatService;
@Autowired
public void setChatService(ChatService chatService) {
WebSocketServer.chatService = chatService;
}
@PostConstruct
public void init() {
System.out.println("websocket 加载");
}
private static Logger log = LoggerFactory.getLogger(WebSocketServer.class);
private static final AtomicInteger OnlineCount = new AtomicInteger(0);
// concurrent包的线程安全Set用来存放每个客户端对应的Session对象。
private static CopyOnWriteArraySet<Session> SessionSet = new CopyOnWriteArraySet<Session>();
/**
* 连接建立成功调用的方法
*/
@OnOpen
public void onOpen(Session session) {
SessionSet.add(session);
int cnt = OnlineCount.incrementAndGet();
log.info("有连接加入,当前连接数为:{}", cnt);
SendMessage(session, "连接成功");
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose(Session session) {
SessionSet.remove(session);
int cnt = OnlineCount.decrementAndGet();
log.info("有连接关闭,当前连接数为:{}", cnt);
}
/**
* 收到客户端消息后调用的方法
* @param message 客户端发送过来的消息
*/
@OnMessage
public void onMessage(String message, Session session) {
log.info("来自客户端的消息:{}",message);
try{
JSONObject jsonObject = JSONObject.parseObject(message);
String linkType = jsonObject.getString("linkType");
String sendId = jsonObject.getString("sendId");
if (linkType.equals("bind")){
//CacheManager.set("bind_"+sendId,session);
SendMessage(session, "连接成功");
}else if (linkType.equals("msg")){
//聊天
ChatMsg msg = new ChatMsg();
//发消息
String chatMsg = jsonObject.getString("chatMsg");
String receiveId = jsonObject.getString("receiveId");
msg.setChatMsg(chatMsg);
msg.setSendId(sendId);
msg.setMsgKey(sendId+"_"+receiveId);
msg.setReceiveId(receiveId);
msg.setReadState("0");
//chatService.sendOne(msg);
}
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 出现错误
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error) {
log.error("发生错误:{}Session ID {}",error.getMessage(),session.getId());
error.printStackTrace();
}
/**
* 发送消息实践表明每次浏览器刷新session会发生变化。
* @param session
* @param message
*/
public static void SendMessage(Session session, String message) {
try {
//session.getBasicRemote().sendText(String.format("%s (From ServerSession ID=%s)",message,session.getId()));
log.info("sessionID="+session.getId());
session.getBasicRemote().sendText(message);
} catch (IOException e) {
log.error("发送消息出错:{}", e.getMessage());
e.printStackTrace();
}
}
/**
* 指定Session发送消息
* @param sessionId
* @param message
* @throws IOException
*/
public static void SendMessageById(String message,String sessionId) throws IOException {
Session session = null;
for (Session s : SessionSet) {
if(s.getId().equals(sessionId)){
session = s;
break;
}
}
if(session!=null){
SendMessage(session, message);
}
else{
log.warn("没有找到你指定ID的会话{}",sessionId);
}
}
/**
* @description: 指定发送
* @author: lvyq
* @date: 2021/9/24 11:30
* @version 1.0
*/
public static void SendMessageByRecId(String message,String receiveId) throws IOException {
//Session session= CacheManager.get("bind_"+receiveId);
Session session= null;
String sessionId = "";
if (session!=null){
sessionId=session.getId();
}
for (Session s : SessionSet) {
if(s.getId().equals(sessionId)){
session = s;
break;
}
}
if(session!=null){
SendMessage(session, message);
}
else{
System.out.println("没有找到你指定ID的会话"+sessionId);
}
}
}

View File

@@ -0,0 +1,37 @@
package com.m2pool.chat.service.impl;
import com.m2pool.chat.entity.ChatMessage;
import com.m2pool.chat.mapper.ChatMapper;
import com.m2pool.chat.service.ChatService;
import com.m2pool.common.core.web.Result.AjaxResult;
import com.m2pool.common.security.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
/**
* @Description TODO
* @Date 2025/2/28 18:08
* @Author 杜懿
*/
@Service
public class ChatServiceImpl implements ChatService {
@Autowired
private ChatMapper chatMapper;
@Async("messageExecutor")
public void saveMessageAsync(ChatMessage message) {
// 批量插入优化
chatMapper.insert(message);
}
@Override
public AjaxResult getHistory(String identifier) {
return null;
}
}

View File

@@ -0,0 +1,14 @@
package com.m2pool.chat.vo;
import lombok.Data;
/**
* @Description TODO
* @Date 2025/3/7 15:55
* @Author 杜懿
*/
@Data
public class ChatHistoryVo {
private String email;
private String browserId;
}

View File

@@ -0,0 +1,156 @@
server:
port: 9209
compression:
enabled: true
mime-types: application/json
spring:
#邮箱基本配置
mail:
# 配置在limit_time内用户可以发送limit次验证码
limit: 2 这个是我额外的配置,结合邮箱服务用的
limitTime: 10 这个是我额外的配置
#配置smtp服务主机地址
# sina smtp.sina.cn
# aliyun smtp.aliyun.com
# 163 smtp.163.com 端口号465或994
host: mail.privateemail.com
#发送者邮箱
username: support@m2pool.cc
#配置密码,注意不是真正的密码,而是刚刚申请到的授权码
# password:
# password: m2pool2024@!
# password: axvm-zfgx-cgcg-qhhu
password: m2pool2024@!
#端口号
port: 587
#默认的邮件编码为UTF-8
default-encoding: UTF-8
#其他参数
properties:
mail:
#配置SSL 加密工厂
smtp:
ssl:
#本地测试先放开ssl
enable: false
required: false
#开启debug模式这样邮件发送过程的日志会在控制台打印出来方便排查错误
debug: false
socketFactory:
class: javax.net.ssl.SSLSocketFactory
application:
# 应用名称
name: m2pool-chat
profiles:
# 环境配置
active: prod
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: 127.0.0.1:8808
namespace: m2_prod
group: m2_prod_group
# server-addr: 127.0.0.1:8808
config:
# 配置中心地址
server-addr: 127.0.0.1:8808
# server-addr: 127.0.0.1:8808
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
namespace: m2_prod
group: m2_prod_group
servlet:
multipart:
max-file-size: 2MB
max-request-size: 8MB
myenv:
domain: https://www.m2pool.com
path: /var/www/html/web
img: /img
#测试环境
#server:
# port: 9509
# compression:
# enabled: true
# mime-types: application/json
#
#spring:
# #邮箱基本配置
# mail:
# # 配置在limit_time内用户可以发送limit次验证码
# limit: 2 这个是我额外的配置,结合邮箱服务用的
# limitTime: 10 这个是我额外的配置
# #配置smtp服务主机地址
# # sina smtp.sina.cn
# # aliyun smtp.aliyun.com
# # 163 smtp.163.com 端口号465或994
# host: mail.privateemail.com
# #发送者邮箱
# username: support@m2pool.cc
# #配置密码,注意不是真正的密码,而是刚刚申请到的授权码
# # password:
# # password: m2pool2024@!
# # password: axvm-zfgx-cgcg-qhhu
# password: m2pool2024@!
# #端口号
# port: 587
# #默认的邮件编码为UTF-8
# default-encoding: UTF-8
# #其他参数
# properties:
# mail:
# #配置SSL 加密工厂
# smtp:
# ssl:
# #本地测试先放开ssl
# enable: false
# required: false
# #开启debug模式这样邮件发送过程的日志会在控制台打印出来方便排查错误
# debug: false
# socketFactory:
# class: javax.net.ssl.SSLSocketFactory
#
# application:
# # 应用名称
# name: m2pool-chat
# profiles:
# # 环境配置
# active: test
# cloud:
# nacos:
# discovery:
# # 服务注册地址
# server-addr: 127.0.0.1:8808
# namespace: m2_test
# group: m2_test_group
# # server-addr: 127.0.0.1:8808
# config:
# # 配置中心地址
# server-addr: 127.0.0.1:8808
# # server-addr: 127.0.0.1:8808
# # 配置文件格式
# file-extension: yml
# # 共享配置
# shared-configs:
# - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
# namespace: m2_test
# group: m2_test_group
# servlet:
# multipart:
# max-file-size: 2MB
# max-request-size: 8MB
#
#myenv:
# domain: https://test.m2pool.com
# path: /var/www/html/web_test
# img: /imgpp
#

View File

@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- 日志存放路径 -->
<property name="log.path" value="logs/m2pool-chat" />
<!-- 日志输出格式 -->
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
<!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 系统日志输出 -->
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/info.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/info.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 30天 -->
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>INFO</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/error.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/error.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 30天 -->
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>ERROR</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 系统模块日志级别控制 -->
<logger name="com.m2pool" level="info" />
<!-- Spring日志级别控制 -->
<logger name="org.springframework" level="warn" />
<root level="info">
<appender-ref ref="console" />
</root>
<!--系统操作日志-->
<root level="info">
<appender-ref ref="file_info" />
<appender-ref ref="file_error" />
</root>
</configuration>

View File

@@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.m2pool</groupId>
<artifactId>m2pool-modules</artifactId>
<version>3.5.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>m2pool-file</artifactId>
<description>
m2pool-file文件服务
</description>
<dependencies>
<!-- SpringCloud Alibaba Nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- SpringCloud Alibaba Nacos Config -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- SpringCloud Alibaba Sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- SpringBoot Actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- FastDFS -->
<dependency>
<groupId>com.github.tobato</groupId>
<artifactId>fastdfs-client</artifactId>
</dependency>
<!-- M2Pool Api System -->
<dependency>
<groupId>com.m2pool</groupId>
<artifactId>api-system</artifactId>
</dependency>
<!-- M2Pool Common swagger -->
<dependency>
<groupId>com.m2pool</groupId>
<artifactId>common-swagger</artifactId>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,22 @@
package com.m2pool.file;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import com.m2pool.common.swagger.annotation.EnableCustomSwagger2;
/**
* 文件服务
*
* @author dy
*/
@EnableCustomSwagger2
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class })
public class M2PoolFileApplication
{
public static void main(String[] args)
{
SpringApplication.run(M2PoolFileApplication.class, args);
System.out.println("m2pool文件服务模块启动成功 ლ(´ڡ`ლ)゙ \n");
}
}

View File

@@ -0,0 +1,50 @@
package com.m2pool.file.config;
import java.io.File;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* 通用映射配置
*
* @author dy
*/
@Configuration
public class ResourcesConfig implements WebMvcConfigurer
{
/**
* 上传文件存储在本地的根路径
*/
@Value("${file.path}")
private String localFilePath;
/**
* 资源映射路径 前缀
*/
@Value("${file.prefix}")
public String localFilePrefix;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
/** 本地文件上传路径 */
registry.addResourceHandler(localFilePrefix + "/**")
.addResourceLocations("file:" + localFilePath + File.separator);
}
/**
* 开启跨域
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
// 设置允许跨域的路由
registry.addMapping(localFilePrefix + "/**")
// 设置允许跨域请求的域名
.allowedOrigins("*")
// 设置允许的方法
.allowedMethods("GET");
}
}

View File

@@ -0,0 +1,108 @@
package com.m2pool.file.controller;
import com.m2pool.common.core.Result.R;
import com.m2pool.common.core.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import com.m2pool.common.core.utils.file.FileUtils;
import com.m2pool.file.service.ISysFileService;
import com.m2pool.system.api.entity.SysFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 文件请求处理
*
* @author dy
*/
@RestController
public class SysFileController
{
private static final Logger log = LoggerFactory.getLogger(SysFileController.class);
@Autowired
private ISysFileService sysFileService;
/**
* 上传文件存储在本地的根路径
*/
@Value("${file.path}")
private String localFilePath;
/**
* 文件上传请求
*/
@PostMapping("upload")
public R<SysFile> upload(MultipartFile file)
{
try
{
// 上传并返回访问地址
String url = sysFileService.uploadFile(file);
SysFile sysFile = new SysFile();
sysFile.setName(FileUtils.getName(url));
sysFile.setUrl(url);
return R.success(sysFile);
}
catch (Exception e)
{
log.error("上传文件失败", e);
return R.fail(e.getMessage());
}
}
/**
* 下载请求
*
* @param url 访问路径
*/
@PostMapping("/download")
public void fileDownload(@RequestBody() String url, HttpServletResponse response, @RequestHeader("User-Agent") String userAgent, HttpServletRequest request)
{
String fileName = FileUtils.getName(url);
try
{
if (!FileUtils.checkAllowDownload(fileName))
{
throw new Exception(StringUtils.format("文件名称({})非法,不允许下载。 ", fileName));
}
// 数据库资源地址
String downloadPath = localFilePath + StringUtils.substringAfter(url, "statics");
// 下载名称
String downloadName = StringUtils.substringAfterLast(downloadPath, "/");
response.reset();
response.setCharacterEncoding("GBK");
// 针对IE或者以IE为内核的浏览器
if (userAgent.contains("MSIE") || userAgent.contains("Trident")) {
downloadName = java.net.URLEncoder.encode(downloadName, "UTF-8");
} else {
// 非IE浏览器的处理
downloadName = new String(downloadName.getBytes("UTF-8"), "ISO-8859-1");
}
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
response.setHeader(
"Content-disposition",
"attachment;download-filename="
+ downloadName);
FileUtils.setAttachmentResponseHeader(response, downloadName);
FileUtils.writeBytes(downloadPath, response.getOutputStream());
}
catch (Exception e)
{
log.error("下载文件失败", e);
}
}
}

View File

@@ -0,0 +1,21 @@
package com.m2pool.file.service;
import org.springframework.web.multipart.MultipartFile;
/**
* 文件上传接口
*
* @author dy
*/
public interface ISysFileService
{
/**
* 文件上传接口
*
* @param file 上传的文件
* @return 访问地址
* @throws Exception
*/
public String uploadFile(MultipartFile file) throws Exception;
}

View File

@@ -0,0 +1,53 @@
package com.m2pool.file.service;
import com.m2pool.common.core.utils.file.MimeTypeUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.m2pool.file.utils.FileUploadUtils;
/**
* 本地文件存储
*
* @author dy
*/
@Primary
@Service
public class LocalSysFileServiceImpl implements ISysFileService
{
/**
* 资源映射路径 前缀
*/
@Value("${file.prefix}")
public String localFilePrefix;
/**
* 域名或本机访问地址
*/
@Value("${file.domain}")
public String domain;
/**
* 上传文件存储在本地的根路径
*/
@Value("${file.path}")
private String localFilePath;
/**
* 本地文件上传接口
*
* @param file 上传的文件
* @return 访问地址
* @throws Exception
*/
@Override
public String uploadFile(MultipartFile file) throws Exception
{
String name = FileUploadUtils.upload(localFilePath, file ,MimeTypeUtils.DEFAULT_USER_HELP_EXTENSION);
String url = domain + localFilePrefix + name;
return url;
}
}

View File

@@ -0,0 +1,197 @@
package com.m2pool.file.utils;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.Objects;
import org.apache.commons.io.FilenameUtils;
import org.springframework.web.multipart.MultipartFile;
import com.m2pool.common.core.exception.file.FileNameLengthLimitExceededException;
import com.m2pool.common.core.exception.file.FileSizeLimitExceededException;
import com.m2pool.common.core.exception.file.InvalidExtensionException;
import com.m2pool.common.core.utils.DateUtils;
import com.m2pool.common.core.utils.StringUtils;
import com.m2pool.common.core.utils.file.MimeTypeUtils;
import com.m2pool.common.core.utils.uuid.Seq;
import javax.sound.midi.Soundbank;
/**
* 文件上传工具类
*
* @author dy
*/
public class FileUploadUtils
{
/**
* 默认大小 2M
*/
public static final long DEFAULT_MAX_SIZE = 2 * 1024 * 1024;
/**
* 默认的文件名最大长度 100
*/
public static final int DEFAULT_FILE_NAME_LENGTH = 100;
/**
* 根据文件路径上传
*
* @param baseDir 相对应用的基目录
* @param file 上传的文件
* @return 文件名称
* @throws IOException
*/
public static final String upload(String baseDir, MultipartFile file) throws IOException
{
try
{
return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
}
catch (Exception e)
{
throw new IOException(e.getMessage(), e);
}
}
/**
* 文件上传
*
* @param baseDir 相对应用的基目录
* @param file 上传的文件
* @param allowedExtension 上传文件类型
* @return 返回上传成功的文件名
* @throws FileSizeLimitExceededException 如果超出最大大小
* @throws FileNameLengthLimitExceededException 文件名太长
* @throws IOException 比如读写文件出错时
* @throws InvalidExtensionException 文件校验异常
*/
public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension)
throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
InvalidExtensionException
{
int fileNamelength = Objects.requireNonNull(file.getOriginalFilename()).length();
if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH)
{
throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
}
assertAllowed(file, allowedExtension);
String fileName = extractFilename(file);
String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath();
file.transferTo(Paths.get(absPath));
return getPathFileName(fileName);
}
/**
* 编码文件名
*/
public static final String extractFilename(MultipartFile file)
{
return StringUtils.format("{}/{}_{}.{}", DateUtils.datePath(),
FilenameUtils.getBaseName(file.getOriginalFilename()), Seq.getId(Seq.uploadSeqType), getExtension(file));
}
private static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException
{
File desc = new File(uploadDir + File.separator + fileName);
if (!desc.exists())
{
if (!desc.getParentFile().exists())
{
desc.getParentFile().mkdirs();
}
}
return desc.isAbsolute() ? desc : desc.getAbsoluteFile();
}
private static final String getPathFileName(String fileName) throws IOException
{
String pathFileName = "/" + fileName;
return pathFileName;
}
/**
* 文件大小校验
*
* @param file 上传的文件
* @throws FileSizeLimitExceededException 如果超出最大大小
* @throws InvalidExtensionException 文件校验异常
*/
public static final void assertAllowed(MultipartFile file, String[] allowedExtension)
throws FileSizeLimitExceededException, InvalidExtensionException
{
long size = file.getSize();
if (size > DEFAULT_MAX_SIZE)
{
throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024);
}
String fileName = file.getOriginalFilename();
String extension = getExtension(file);
if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension))
{
if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION)
{
throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension,
fileName);
}
else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION)
{
throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension,
fileName);
}
else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION)
{
throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension,
fileName);
}
else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION)
{
throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension,
fileName);
}
else
{
throw new InvalidExtensionException(allowedExtension, extension, fileName);
}
}
}
/**
* 判断MIME类型是否是允许的MIME类型
*
* @param extension 上传文件类型
* @param allowedExtension 允许上传文件类型
* @return true/false
*/
public static final boolean isAllowedExtension(String extension, String[] allowedExtension)
{
for (String str : allowedExtension)
{
if (str.equalsIgnoreCase(extension))
{
return true;
}
}
return false;
}
/**
* 获取文件名的后缀
*
* @param file 表单文件
* @return 后缀名
*/
public static final String getExtension(MultipartFile file)
{
String extension = FilenameUtils.getExtension(file.getOriginalFilename());
if (StringUtils.isEmpty(extension))
{
extension = MimeTypeUtils.getExtension(Objects.requireNonNull(file.getContentType()));
}
return extension;
}
}

View File

@@ -0,0 +1,25 @@
# Tomcat
server:
port: 9300
# Spring
spring:
application:
# 应用名称
name: m2pool-file
profiles:
# 环境配置
active: dev
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: 127.0.0.1:8808
config:
# 配置中心地址
server-addr: 127.0.0.1:8808
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}

View File

@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- 日志存放路径 -->
<property name="log.path" value="logs/m2pool-file" />
<!-- 日志输出格式 -->
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
<!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 系统日志输出 -->
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/info.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/info.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>INFO</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/error.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/error.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>ERROR</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 系统模块日志级别控制 -->
<logger name="com.m2pool" level="info" />
<!-- Spring日志级别控制 -->
<logger name="org.springframework" level="warn" />
<root level="info">
<appender-ref ref="console" />
</root>
<!--系统操作日志-->
<root level="info">
<appender-ref ref="file_info" />
<appender-ref ref="file_error" />
</root>
</configuration>

View File

@@ -0,0 +1,159 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>m2pool-modules</artifactId>
<groupId>com.m2pool</groupId>
<version>3.5.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>m2pool-oapi</artifactId>
<dependencies>
<!-- SpringCloud Alibaba Nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- SpringCloud Alibaba Nacos Config -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- SpringCloud Alibaba Sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- SpringBoot Actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- Swagger UI -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.fox.version}</version>
</dependency>
<!-- Mysql Connector -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-maven-plugin</artifactId>
<scope>provided</scope>
</dependency>
<!-- M2Pool Common DataSource -->
<dependency>
<groupId>com.m2pool</groupId>
<artifactId>common-datasource</artifactId>
</dependency>
<!-- M2Pool Common security -->
<dependency>
<groupId>com.m2pool</groupId>
<artifactId>common-security</artifactId>
</dependency>
<dependency>
<groupId>com.m2pool</groupId>
<artifactId>common-log</artifactId>
</dependency>
<dependency>
<groupId>com.m2pool</groupId>
<artifactId>common-swagger</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.6.2</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
<scope>compile</scope>
</dependency>
</dependencies>
<profiles>
<profile>
<!-- 本地环境 -->
<id>dev</id>
<properties>
<spring.profile>dev</spring.profile>
<nacos.server.address>127.0.0.1:8808</nacos.server.address>
</properties>
<activation>
<!-- 是否默认激活 -->
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<!-- 测试环境 -->
<id>test</id>
<properties>
<spring.profile>test</spring.profile>
<nacos.server.address>127.0.0.1:8808</nacos.server.address>
</properties>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
</profile>
<profile>
<!-- 生产环境 -->
<id>prod</id>
<properties>
<spring.profile>prod</spring.profile>
<nacos.server.address>127.0.0.1:8808</nacos.server.address>
</properties>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
</profile>
</profiles>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,34 @@
package com.m2pool.oapi;
import com.m2pool.common.security.annotation.EnableCustomConfig;
import com.m2pool.common.security.annotation.EnableM2PoolFeignClients;
import com.m2pool.common.swagger.annotation.EnableCustomSwagger2;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
/**
* @Description open api服务入口类
* @Date 2024/6/14 13:42
* @Author dy
*/
@EnableCustomConfig
@EnableCustomSwagger2
@EnableM2PoolFeignClients
@SpringBootApplication
@MapperScan({"com.m2pool.oapi.mapper"})
public class M2OApiApplication {
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(M2OApiApplication.class,args);
System.out.println("m2pool矿池 开放api微服务启动成功");
}
}

View File

@@ -0,0 +1,84 @@
package com.m2pool.oapi.controller;
import com.m2pool.common.core.web.Result.AjaxResult;
import com.m2pool.common.core.web.controller.BaseController;
import com.m2pool.common.security.annotation.OpenApiPermissions;
import com.m2pool.common.security.annotation.RequiresPermissions;
import com.m2pool.oapi.service.AccountService;
import com.m2pool.oapi.vo.AccountDateVo;
import com.m2pool.oapi.vo.AccountVo;
import com.m2pool.oapi.vo.CoinVo;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
/**
* @Description 统一请求接口
* @Date 2024/6/14 9:54
* @Author dy
*/
@RestController
@RequestMapping("/account")
public class AccountController extends BaseController {
@Autowired
private AccountService accountService;
@PostMapping("/hashrate_real")
@ApiOperation(value = "挖矿账户实时算力、24小时算力")
@OpenApiPermissions("account")
public AjaxResult hashrate_real(@Valid @RequestBody AccountVo vo){
return accountService.getHashRateReal(vo);
}
@PostMapping("/hashrate_history")
@ApiOperation(value = "挖矿账户历史算力(只支持24小时,最多3个月)")
@OpenApiPermissions("account")
public AjaxResult hashRateHistory(@Valid @RequestBody AccountDateVo vo){
return accountService.getHashRateHistory(vo);
}
@PostMapping("/hashrate_last24h")
@ApiOperation(value = "挖矿账户最近24小时算力(30分钟算力)")
@OpenApiPermissions("account")
public AjaxResult getHashRateLast24h(@Valid @RequestBody AccountVo vo){
return accountService.getHashRateLast24h(vo);
}
@PostMapping("/miners_list")
@ApiOperation(value = "挖矿账号矿工列表")
@OpenApiPermissions("account")
public AjaxResult minersList(@Valid @RequestBody AccountVo vo){
return accountService.getMinersList(vo);
}
@PostMapping("/watch")
@ApiOperation(value = "挖矿账号矿工总览")
@OpenApiPermissions("account")
public AjaxResult watch(@Valid @RequestBody AccountVo vo){
return accountService.getWatch(vo);
}
@GetMapping("/test1")
@ApiOperation(value = "挖矿账号矿工总览")
//@OpenApiPermissions("account")
public AjaxResult test1(){
return AjaxResult.success();
}
}

View File

@@ -0,0 +1,62 @@
package com.m2pool.oapi.controller;
import com.m2pool.common.core.web.Result.AjaxResult;
import com.m2pool.common.core.web.controller.BaseController;
import com.m2pool.common.security.annotation.OpenApiPermissions;
import com.m2pool.common.security.annotation.RequiresPermissions;
import com.m2pool.oapi.service.MinerService;
import com.m2pool.oapi.vo.AccountDateVo;
import com.m2pool.oapi.vo.AccountMinerDateVo;
import com.m2pool.oapi.vo.AccountMinerVo;
import com.m2pool.oapi.vo.AccountVo;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
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 javax.validation.Valid;
/**
* @Description 矿机开放api统一请求接口
* @Date 2024/6/14 9:54
* @Author dy
*/
@RestController
@RequestMapping("/miner")
public class MinerController extends BaseController {
@Autowired
private MinerService minerService;
@PostMapping("/hashrate_real")
@ApiOperation(value = "挖矿账户实时算力、24小时算力")
@OpenApiPermissions("miner")
public AjaxResult hashrate_real(@Valid @RequestBody AccountMinerVo vo){
return minerService.getHashRateReal(vo);
}
@PostMapping("/hashrate_history")
@ApiOperation(value = "挖矿账户历史算力(只支持24小时,最多3个月)")
@OpenApiPermissions("miner")
public AjaxResult hashRateHistory(@Valid @RequestBody AccountMinerDateVo vo){
return minerService.getHashRateHistory(vo);
}
@PostMapping("/hashrate_last24h")
@ApiOperation(value = "挖矿账户最近24小时算力(30分钟算力)")
@OpenApiPermissions("miner")
public AjaxResult getHashRateLast24h(@Valid @RequestBody AccountMinerVo vo){
return minerService.getHashRateLast24h(vo);
}
}

View File

@@ -0,0 +1,78 @@
package com.m2pool.oapi.controller;
import com.m2pool.common.core.annotation.RateLimiter;
import com.m2pool.common.core.enums.LimitType;
import com.m2pool.common.core.web.Result.AjaxResult;
import com.m2pool.common.core.web.controller.BaseController;
import com.m2pool.common.security.annotation.OpenApiPermissions;
import com.m2pool.common.security.annotation.RequiresPermissions;
import com.m2pool.oapi.service.PoolService;
import com.m2pool.oapi.vo.CoinVo;
import com.m2pool.oapi.vo.DateVo;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
/**
* @Description 统一请求接口
* @Date 2024/6/14 9:54
* @Author dy
*/
@RestController
@RequestMapping("/pool")
public class PoolController extends BaseController {
@Autowired
private PoolService poolService;
@GetMapping("/hashrate")
@ApiOperation(value = "矿池实时算力")
@OpenApiPermissions("pool")
public AjaxResult hashrate(@Valid CoinVo vo){
return poolService.getHashRate(vo);
}
@GetMapping("/hashrate_history")
@ApiOperation(value = "矿池历史算力(最多3个月)")
@OpenApiPermissions("pool")
public AjaxResult hashRateHistory(@Valid DateVo vo){
return poolService.getHashRateHistory(vo);
}
@GetMapping("/miners_list")
@ApiOperation(value = "矿池当前矿工数")
@OpenApiPermissions("pool")
public AjaxResult getMinersList(@Valid CoinVo vo){
return poolService.getMinersList(vo);
}
@GetMapping("/watch")
@ApiOperation(value = "矿池总览")
@OpenApiPermissions("pool")
@RateLimiter(time = 1,count = 5,limitType = LimitType.IP)
public AjaxResult watch(@Valid CoinVo vo){
return poolService.getWatch(vo);
}
@PostMapping("/test")
@ApiOperation(value = "矿池总览")
@OpenApiPermissions("pool")
public AjaxResult test(@Valid @RequestBody CoinVo vo){
return AjaxResult.success();
}
}

View File

@@ -0,0 +1,24 @@
package com.m2pool.oapi.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* @Description 曲线图数据结构
* @Date 2024/6/13 11:17
* @Author dy
*/
@Data
public class HashRateDto implements Serializable {
/** 实时(30m)算力 */
@JsonProperty("hashrate")
private BigDecimal mhs;
private Date date;
}

View File

@@ -0,0 +1,26 @@
package com.m2pool.oapi.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.m2pool.common.core.utils.uuid.UUID;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
/**
* @Description 曲线图数据结构
* @Date 2024/6/13 11:17
* @Author dy
*/
@Data
public class HashRateHistory24hDto implements Serializable {
/** 24h算力 */
@JsonProperty("hashrate_24h")
private List<HashRateDto> list;
/** 单位 h/s, kh/s, mh/s, gh/sth/s */
private String unit;
}

View File

@@ -0,0 +1,24 @@
package com.m2pool.oapi.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* @Description 曲线图数据结构
* @Date 2024/6/13 11:17
* @Author dy
*/
@Data
public class HashRateHistory30mDto implements Serializable {
/** 实时(30m)算力 */
@JsonProperty("hashrate_30m")
private List<HashRateDto> list;
/** 单位 h/s, kh/s, mh/s, gh/sth/s */
private String unit;
}

View File

@@ -0,0 +1,29 @@
package com.m2pool.oapi.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* @Description 曲线图数据结构
* @Date 2024/6/13 11:17
* @Author dy
*/
@Data
public class HashRateRealDto implements Serializable {
/** 实时(30m)算力 */
@JsonProperty("hashrate_realtime")
private BigDecimal mhs;
/** 有效提交数 */
@JsonProperty("hashrate_24h")
private BigDecimal mhs24h;
/** 单位 h/s, kh/s, mh/s, gh/sth/s */
private String unit;
}

View File

@@ -0,0 +1,23 @@
package com.m2pool.oapi.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* @Description 曲线图数据结构
* @Date 2024/6/13 11:17
* @Author dy
*/
@Data
public class MinerStateDto implements Serializable {
/** 实时(30m)算力 */
private String miner;
private int state;
}

View File

@@ -0,0 +1,22 @@
package com.m2pool.oapi.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* @Description 曲线图数据结构
* @Date 2024/6/13 11:17
* @Author dy
*/
@Data
public class MinerStateListDto implements Serializable {
/** 24h算力 */
@JsonProperty("miner_list")
private List<MinerStateDto> list;
}

View File

@@ -0,0 +1,24 @@
package com.m2pool.oapi.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.io.Serializable;
/**
* @Description 曲线图数据结构
* @Date 2024/6/13 11:17
* @Author dy
*/
@Data
public class MinerWatchDto implements Serializable {
private long total;
private long online;
private long offline;
private long timeout;
}

View File

@@ -0,0 +1,28 @@
package com.m2pool.oapi.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* @Description 曲线图数据结构
* @Date 2024/6/13 11:17
* @Author dy
*/
@Data
public class PoolHashRateHistoryDto implements Serializable {
/** 矿池(30m)算力 */
@JsonProperty("hashrate_30m")
private List<HashRateDto> mhsList;
/** 矿池(24h)算力 */
@JsonProperty("hashrate_24h")
private List<HashRateDto> mhs24hList;
/** 单位 h/s, kh/s, mh/s, gh/sth/s */
private String unit;
}

View File

@@ -0,0 +1,36 @@
package com.m2pool.oapi.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
/**
* @Description 矿池总览
* @Date 2024/6/13 11:17
* @Author dy
*/
@Data
public class PoolWatchDto implements Serializable {
@JsonProperty("pool_fee")
private String fee;
@JsonProperty("min_pay")
private double minPay;
@JsonProperty("history_last_7days")
private List<HashRateDto> list;
private long miners;
@JsonProperty("hashrate")
private BigDecimal mhs;
@JsonProperty("last_found")
private long height;
private String unit;
}

View File

@@ -0,0 +1,25 @@
package com.m2pool.oapi.entity;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* @Description 曲线图数据结构
* @Date 2024/6/13 11:17
* @Author dy
*/
@Data
public class ApiKeyInfo implements Serializable {
/** api_key */
private String key;
private String ip;
private String user;
}

View File

@@ -0,0 +1,22 @@
package com.m2pool.oapi.entity;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.io.Serializable;
/**
* @Description 曲线图数据结构
* @Date 2024/6/13 11:17
* @Author dy
*/
@Data
public class MinerState implements Serializable {
/** 实时(30m)算力 */
@JsonProperty("hashrate")
private String miner;
private String state;
}

View File

@@ -0,0 +1,49 @@
package com.m2pool.oapi.enums;
/**
* @Description 矿池默认起付额
* @Date 2022/5/20 11:15
* @Author 杜懿
*/
public enum PoolAmount {
GRS("grs", 100),
MONA("mona", 100),
DGB_SKEIN("dgb_skein", 100),
DGB_QUBIT("dgb_qubit", 100),
DGB_ODO("dgb_odo", 100),
DGB_QUBIT_A10("dgb_qubit_a10", 100),
DGB_SKEIN_A10("dgb_skein_a10", 100),
DGB_ODO_B20("dgb_odo_b20", 100),
NEXA("nexa", 10000),
RXD("rxd", 10000),
ALPH("alph", 10000),
ENX("enx", 10000);
/** 币种参数名 */
private final String coin;
/** 单位 */
private final double amount;
PoolAmount(String coin, double amount) {
this.coin = coin;
this.amount = amount;
}
public String getCoin() {
return coin;
}
public double getAmount(){return amount;}
public static double getAmountByCoin(String coin){
for (PoolAmount t : PoolAmount.values()) {
if(t.getCoin().equals(coin)){
return t.getAmount();
}
}
return 10000;
}
}

View File

@@ -0,0 +1,62 @@
package com.m2pool.oapi.enums;
/**
* @Description 矿池单位换算
* @Date 2022/5/20 11:15
* @Author 杜懿
*/
public enum PoolUnits {
GRS("grs", "MH/s", 1000, 1000),
MONA("mona", "MH/s", 1000, 1000),
DGB_SKEIN("dgb_skein", "MH/s", 1000, 1000),
DGB_QUBIT("dgb_qubit", "MH/s", 1000, 1000),
DGB_ODO("dgb_odo", "MH/s", 1000, 1000),
DGB2_ODO("dgb2_odo", "MH/s", 1000, 1000),
DGB_QUBIT_A10("dgb_qubit_a10", "MH/s", 1000, 1000),
DGB_SKEIN_A10("dgb_skein_a10", "MH/s", 1000, 1000),
DGB_ODO_B20("dgb_odo_b20", "MH/s", 1000, 1000),
NEXA("nexa", "MH/s", 1000*1000, 1000),
RXD("rxd", "MH/s", 1000*1000, 1000),
ALPH("aplh", "MH/s", 1000*1000, 1000),
ENX("enx", "MH/s", 1000*1000, 1000);
/** 币种参数名 */
private final String coin;
/** 矿池数据单位 */
private final String unit;
/** 换算率 数据库原始数据换算为H/s的换算率 */
private final int hRate ;
/** 换算率 数据库原始数据换算为H/s的换算率 */
private final int gRate ;
PoolUnits(String coin, String unit, int hRate, int gRate) {
this.coin = coin;
this.unit = unit;
this.hRate = hRate;
this.gRate = gRate;
}
public String getCoin() {
return coin;
}
public String getUnit() {
return unit;
}
public int gethRate() {
return hRate;
}
public int getgRate() {
return gRate;
}
}

View File

@@ -0,0 +1,34 @@
package com.m2pool.oapi.mapper;
import com.m2pool.common.datasource.annotation.HashRateDB;
import com.m2pool.common.datasource.annotation.InfoDB;
import com.m2pool.oapi.dto.HashRateDto;
import com.m2pool.oapi.dto.HashRateRealDto;
import com.m2pool.oapi.entity.MinerState;
import com.m2pool.oapi.vo.AccountDateVo;
import com.m2pool.oapi.vo.AccountVo;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* @Description TODO
* @Date 2022/8/30 17:47
* @Author 杜懿
*/
@InfoDB
public interface AccountMapper {
@HashRateDB
public List<HashRateRealDto> getAccountRealHashRateListByCoinAndAccount(@Param("vo") AccountVo vo);
public List<HashRateDto> getAccountHashRateHistory24hListByCoinAndAccount(@Param("vo") AccountDateVo vo);
public List<HashRateDto> getAccountHashRateHistory30mListByCoinAndAccount(@Param("vo") AccountVo vo,@Param("start") String start);
@HashRateDB
public List<MinerState> getMinerListByCoinAndAccount(@Param("vo") AccountVo vo);
}

View File

@@ -0,0 +1,33 @@
package com.m2pool.oapi.mapper;
import com.m2pool.common.datasource.annotation.HashRateDB;
import com.m2pool.common.datasource.annotation.InfoDB;
import com.m2pool.oapi.dto.HashRateDto;
import com.m2pool.oapi.dto.HashRateRealDto;
import com.m2pool.oapi.vo.AccountDateVo;
import com.m2pool.oapi.vo.AccountMinerDateVo;
import com.m2pool.oapi.vo.AccountMinerVo;
import com.m2pool.oapi.vo.AccountVo;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* @Description TODO
* @Date 2022/8/30 17:47
* @Author 杜懿
*/
@InfoDB
public interface MinerMapper {
@HashRateDB
public HashRateRealDto getMinerRealHashRateByCoinAndAccountMiner(@Param("vo") AccountMinerVo vo);
public List<HashRateDto> getMinerHashRateHistory24hListByCoinAndAccountMiner(@Param("vo") AccountMinerDateVo vo);
public List<HashRateDto> getMinerHashRateHistory30mListByCoinAndAccountMiner(@Param("vo") AccountMinerVo vo, @Param("start") String start);
}

View File

@@ -0,0 +1,42 @@
package com.m2pool.oapi.mapper;
import com.m2pool.common.datasource.annotation.HashRateDB;
import com.m2pool.common.datasource.annotation.InfoDB;
import com.m2pool.oapi.dto.HashRateDto;
import com.m2pool.oapi.dto.HashRateRealDto;
import com.m2pool.oapi.dto.PoolWatchDto;
import com.m2pool.oapi.entity.MinerState;
import com.m2pool.oapi.vo.AccountVo;
import com.m2pool.oapi.vo.CoinVo;
import com.m2pool.oapi.vo.DateVo;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* @Description TODO
* @Date 2022/8/30 17:47
* @Author 杜懿
*/
@InfoDB
public interface PoolMapper {
@HashRateDB
public HashRateRealDto getPoolRealHashRateListByCoin(@Param("vo") CoinVo vo);
public List<HashRateDto> getPoolHashRateHistory24hListByCoin(@Param("vo") DateVo vo);
public List<HashRateDto> getPoolHashRateHistory30mListByCoin(@Param("vo") DateVo vo);
@HashRateDB
public List<MinerState> getMinerListByCoin(@Param("vo") CoinVo vo);
@HashRateDB
public PoolWatchDto getPoolWatchByCoin(@Param("vo") CoinVo vo);
@HashRateDB
public HashRateDto getPoolRealHashRateByCoin(@Param("vo") CoinVo vo);
}

View File

@@ -0,0 +1,25 @@
package com.m2pool.oapi.service;
import com.m2pool.common.core.web.Result.AjaxResult;
import com.m2pool.oapi.vo.AccountDateVo;
import com.m2pool.oapi.vo.AccountVo;
import com.m2pool.oapi.vo.DateVo;
/**
* @Description 开放api 矿池 相关服务类
* @Date 2024/6/14 11:40
* @Author dy
*/
public interface AccountService {
public AjaxResult getHashRateReal(AccountVo vo);
public AjaxResult getHashRateHistory(AccountDateVo vo);
public AjaxResult getHashRateLast24h(AccountVo vo);
public AjaxResult getMinersList(AccountVo vo);
public AjaxResult getWatch(AccountVo vo);
}

View File

@@ -0,0 +1,23 @@
package com.m2pool.oapi.service;
import com.m2pool.common.core.web.Result.AjaxResult;
import com.m2pool.oapi.vo.AccountDateVo;
import com.m2pool.oapi.vo.AccountMinerDateVo;
import com.m2pool.oapi.vo.AccountMinerVo;
import com.m2pool.oapi.vo.AccountVo;
/**
* @Description 开放api 矿池 相关服务类
* @Date 2024/6/14 11:40
* @Author dy
*/
public interface MinerService {
public AjaxResult getHashRateReal(AccountMinerVo vo);
public AjaxResult getHashRateHistory(AccountMinerDateVo vo);
public AjaxResult getHashRateLast24h(AccountMinerVo vo);
}

View File

@@ -0,0 +1,22 @@
package com.m2pool.oapi.service;
import com.m2pool.common.core.web.Result.AjaxResult;
import com.m2pool.oapi.vo.CoinVo;
import com.m2pool.oapi.vo.DateVo;
/**
* @Description 开放api 矿池 相关服务类
* @Date 2024/6/14 11:40
* @Author dy
*/
public interface PoolService {
public AjaxResult getHashRate(CoinVo vo);
public AjaxResult getHashRateHistory(DateVo vo);
public AjaxResult getMinersList(CoinVo vo);
public AjaxResult getWatch(CoinVo vo);
}

View File

@@ -0,0 +1,192 @@
package com.m2pool.oapi.service.impl;
import com.m2pool.common.core.text.Convert;
import com.m2pool.common.core.utils.DateUtils;
import com.m2pool.common.core.utils.StringUtils;
import com.m2pool.common.core.web.Result.AjaxResult;
import com.m2pool.oapi.dto.*;
import com.m2pool.oapi.entity.MinerState;
import com.m2pool.oapi.enums.PoolUnits;
import com.m2pool.oapi.mapper.AccountMapper;
import com.m2pool.oapi.service.AccountService;
import com.m2pool.oapi.utils.EnumUtils;
import com.m2pool.oapi.vo.AccountDateVo;
import com.m2pool.oapi.vo.AccountVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
/**
* @Description TODO
* @Date 2024/9/13 10:47
* @Author 杜懿
*/
@Service
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountMapper accountMapperMapper;
@Override
public AjaxResult getHashRateReal(AccountVo vo) {
PoolUnits unit = (PoolUnits) EnumUtils.get(PoolUnits.class, vo.getCoin());
if(StringUtils.isNull(unit)){
return AjaxResult.error("coin error");
}
List<HashRateRealDto> list = accountMapperMapper.getAccountRealHashRateListByCoinAndAccount(vo);
BigDecimal mhs = list.stream().map(e -> {
return e.getMhs();
}).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal mhs24h = list.stream().map(e -> {
return e.getMhs24h();
}).reduce(BigDecimal.ZERO, BigDecimal::add);
HashRateRealDto dto = new HashRateRealDto();
dto.setUnit(unit.getUnit());
dto.setMhs(mhs);
dto.setMhs24h(mhs24h);
return AjaxResult.success(dto);
}
@Override
public AjaxResult getHashRateHistory(AccountDateVo vo) {
System.out.println(vo);
PoolUnits unit = (PoolUnits) EnumUtils.get(PoolUnits.class, vo.getCoin());
if(StringUtils.isNull(unit)){
return AjaxResult.error("coin error");
}
Date today = new Date();
today.setHours(0);
today.setMinutes(0);
today.setMinutes(0);
Calendar ca = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
ca.setTime(today);
ca.add(Calendar.MONTH,-3);
Date firstDate = ca.getTime();
if (StringUtils.isBlank(vo.getStart())){
vo.setStart(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,firstDate));
}else {
if(DateUtils.parseDate(vo.getStart()).before(firstDate)){
vo.setStart(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,firstDate));
}else {
//在三个月之内 不做处理
try {
DateUtils.parseDate(vo.getStart());
}catch (Exception e){
//出错说明格式错误有
return AjaxResult.error("start param error");
}
}
}
if (StringUtils.isNotBlank(vo.getEnd())){
//在三个月之内 不做处理
try {
Date end = DateUtils.parseDate(vo.getEnd());
if(end.before(DateUtils.parseDate(vo.getStart()))){
//end时间在start之前
return AjaxResult.error("end Date can not before start Date");
}
if(firstDate.before(end)){
return AjaxResult.error("end Date can not before "+DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD,firstDate));
}
}catch (Exception e){
//出错说明格式错误有
return AjaxResult.error("end param error");
}
}else {
//没有end 则不做处理
}
List<HashRateDto> mhsList = accountMapperMapper.getAccountHashRateHistory24hListByCoinAndAccount(vo);
HashRateHistory24hDto dto = new HashRateHistory24hDto();
dto.setList(mhsList);
dto.setUnit(unit.getUnit());
return AjaxResult.success(dto);
}
@Override
public AjaxResult getHashRateLast24h(AccountVo vo) {
long t0 = System.currentTimeMillis();
PoolUnits unit = (PoolUnits) EnumUtils.get(PoolUnits.class, vo.getCoin());
if(StringUtils.isNull(unit)){
return AjaxResult.error("coin error");
}
Date today = new Date();
Calendar ca = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
ca.setTime(today);
ca.add(Calendar.DATE,-1);
String start = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,ca.getTime());
long t1 = System.currentTimeMillis();
List<HashRateDto> list = accountMapperMapper.getAccountHashRateHistory30mListByCoinAndAccount(vo, start);
long t2 = System.currentTimeMillis();
HashRateHistory30mDto dto = new HashRateHistory30mDto();
dto.setList(list);
dto.setUnit(unit.getUnit());
System.out.println("挖矿账户last24h业务 数据库查询耗时:"+(t2-t1)+"ms,业务耗时"+(t2-t0)+"ms");
return AjaxResult.success(dto);
}
@Override
public AjaxResult getMinersList(AccountVo vo) {
List<MinerState> list = accountMapperMapper.getMinerListByCoinAndAccount(vo);
List<MinerStateDto> minerList = list.stream().map(e -> {
MinerStateDto dto = new MinerStateDto();
dto.setMiner(e.getMiner());
if ("online".equals(e.getState().toLowerCase())) {
dto.setState(0);
} else if ("offline".equals(e.getState().toLowerCase())) {
dto.setState(1);
} else {
dto.setState(2);
}
return dto;
}).collect(Collectors.toList());
MinerStateListDto minerStateListDto = new MinerStateListDto();
minerStateListDto.setList(minerList);
return AjaxResult.success(minerStateListDto);
}
@Override
public AjaxResult getWatch(AccountVo vo) {
MinerWatchDto dto = new MinerWatchDto();
List<MinerState> list = accountMapperMapper.getMinerListByCoinAndAccount(vo);
Map<String, Long> map = list.stream().collect(Collectors.groupingBy(
MinerState::getState,
Collectors.counting()
));
long total = Convert.toLong(list.size(),0L);
long online = map.getOrDefault("online", 0L);
long offline = map.getOrDefault("offline", 0L);
dto.setTotal(total);
dto.setOnline(online);
dto.setOffline(offline);
dto.setTimeout(BigDecimal.valueOf(total)
.subtract(BigDecimal.valueOf(online))
.subtract(BigDecimal.valueOf(offline))
.longValue());
return AjaxResult.success(dto);
}
}

View File

@@ -0,0 +1,138 @@
package com.m2pool.oapi.service.impl;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.m2pool.common.core.utils.DateUtils;
import com.m2pool.common.core.utils.StringUtils;
import com.m2pool.common.core.web.Result.AjaxResult;
import com.m2pool.oapi.dto.HashRateDto;
import com.m2pool.oapi.dto.HashRateHistory24hDto;
import com.m2pool.oapi.dto.HashRateHistory30mDto;
import com.m2pool.oapi.dto.HashRateRealDto;
import com.m2pool.oapi.enums.PoolUnits;
import com.m2pool.oapi.mapper.MinerMapper;
import com.m2pool.oapi.service.MinerService;
import com.m2pool.oapi.utils.EnumUtils;
import com.m2pool.oapi.vo.AccountMinerDateVo;
import com.m2pool.oapi.vo.AccountMinerVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
/**
* @Description TODO
* @Date 2024/9/13 10:49
* @Author 杜懿
*/
@Service
public class MinerServiceImpl implements MinerService {
@Autowired
private MinerMapper minerMapper;
@Override
public AjaxResult getHashRateReal(AccountMinerVo vo) {
PoolUnits unit = (PoolUnits) EnumUtils.get(PoolUnits.class, vo.getCoin());
if(StringUtils.isNull(unit)){
return AjaxResult.error("coin error");
}
HashRateRealDto dto = minerMapper.getMinerRealHashRateByCoinAndAccountMiner(vo);
dto.setUnit(unit.getUnit());
return AjaxResult.success(dto);
}
@Override
public AjaxResult getHashRateHistory(AccountMinerDateVo vo) {
PoolUnits unit = (PoolUnits) EnumUtils.get(PoolUnits.class, vo.getCoin());
if(StringUtils.isNull(unit)){
return AjaxResult.error("coin error");
}
Date today = new Date();
today.setHours(0);
today.setMinutes(0);
today.setMinutes(0);
Calendar ca = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
ca.setTime(today);
ca.add(Calendar.MONTH,-3);
Date firstDate = ca.getTime();
if (StringUtils.isBlank(vo.getStart())){
vo.setStart(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,firstDate));
}else {
if(DateUtils.parseDate(vo.getStart()).before(firstDate)){
vo.setStart(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,firstDate));
}else {
//在三个月之内 不做处理
try {
DateUtils.parseDate(vo.getStart());
}catch (Exception e){
//出错说明格式错误有
return AjaxResult.error("start param error");
}
}
}
if (StringUtils.isNotBlank(vo.getEnd())){
//在三个月之内 不做处理
try {
Date end = DateUtils.parseDate(vo.getEnd());
if(end.before(DateUtils.parseDate(vo.getStart()))){
//end时间在start之前
return AjaxResult.error("end Date can not before start Date");
}
if(firstDate.before(end)){
return AjaxResult.error("end Date can not before "+DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD,firstDate));
}
}catch (Exception e){
//出错说明格式错误有
return AjaxResult.error("end param error");
}
}else {
//没有end 则不做处理
}
List<HashRateDto> mhsList = minerMapper.getMinerHashRateHistory24hListByCoinAndAccountMiner(vo);
HashRateHistory24hDto dto = new HashRateHistory24hDto();
dto.setList(mhsList);
dto.setUnit(unit.getUnit());
return AjaxResult.success(dto);
}
@Override
public AjaxResult getHashRateLast24h(AccountMinerVo vo) {
long t0 = System.currentTimeMillis();
PoolUnits unit = (PoolUnits) EnumUtils.get(PoolUnits.class, vo.getCoin());
if(StringUtils.isNull(unit)){
return AjaxResult.error("coin error");
}
Date today = new Date();
Calendar ca = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
ca.setTime(today);
ca.add(Calendar.DATE,-1);
String start = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,ca.getTime());
long t1 = System.currentTimeMillis();
List<HashRateDto> list = minerMapper.getMinerHashRateHistory30mListByCoinAndAccountMiner(vo, start);
long t2 = System.currentTimeMillis();
HashRateHistory30mDto dto = new HashRateHistory30mDto();
dto.setList(list);
dto.setUnit(unit.getUnit());
long t3 = System.currentTimeMillis();
return AjaxResult.success(dto);
}
}

View File

@@ -0,0 +1,213 @@
package com.m2pool.oapi.service.impl;
import com.m2pool.common.core.text.Convert;
import com.m2pool.common.core.utils.DateUtils;
import com.m2pool.common.core.utils.StringUtils;
import com.m2pool.common.core.web.Result.AjaxResult;
import com.m2pool.oapi.dto.*;
import com.m2pool.oapi.entity.MinerState;
import com.m2pool.oapi.enums.PoolAmount;
import com.m2pool.oapi.enums.PoolUnits;
import com.m2pool.oapi.mapper.PoolMapper;
import com.m2pool.oapi.service.PoolService;
import com.m2pool.oapi.utils.EnumUtils;
import com.m2pool.oapi.vo.CoinVo;
import com.m2pool.oapi.vo.DateVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
/**
* @Description TODO
* @Date 2024/9/13 10:44
* @Author 杜懿
*/
@Service
public class PoolServiceImpl implements PoolService {
@Autowired
private PoolMapper poolMapper;
@Override
public AjaxResult getHashRate(CoinVo vo) {
PoolUnits unit = (PoolUnits) EnumUtils.get(PoolUnits.class, vo.getCoin());
if(StringUtils.isNull(unit)){
return AjaxResult.error("coin error");
}
HashRateRealDto dto = poolMapper.getPoolRealHashRateListByCoin(vo);
dto.setUnit(unit.getUnit());
return AjaxResult.success(dto);
}
@Override
public AjaxResult getHashRateHistory(DateVo vo) {
if(StringUtils.isNull(vo)){
return AjaxResult.error("request body cannot be null");
}
PoolUnits unit = (PoolUnits) EnumUtils.get(PoolUnits.class, vo.getCoin());
if(StringUtils.isNull(unit)){
return AjaxResult.error("coin error");
}
Date today = new Date();
today.setHours(0);
today.setMinutes(0);
today.setMinutes(0);
Calendar ca = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
ca.setTime(today);
ca.add(Calendar.MONTH,-3);
//只允许查询当前日期之前3个月的记录 所以firstDate代表运行查询是最早时间值
Date firstDate = ca.getTime();
//用start保存最开始用户传入的开始时间 没传start或者错误格式都会导致start为null 后续可以根据start是否为空判断是否有正确传入开始时间
Date start = DateUtils.parseDate(vo.getStart());
Date end = DateUtils.parseDate(vo.getEnd());
if (StringUtils.isNotNull(end)){
//在三个月之内 不做处理
if(StringUtils.isNull(start)){
//用户没传start 只需比较end 和 firsrDate
if(end.before(firstDate) || end.equals(firstDate)){
return AjaxResult.error("end Date can not before "+DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD,firstDate));
}
//end 在firstDate之后 符合条件 可以进入后续步骤
}else {
//用户传了 start 此时有start 和 end以及firstDate 需要优先比较这两个start和end是否符合 start before end
if(end.before(start) || end.equals(start)){
return AjaxResult.error("end Date must after start Date");
}else {
//start before end 此时可能的时间顺序有 1、firstDate start end 2、start firstDate end 3、 start end firstDate
//第一种情况则正常按用户传的start、end查询 即不做处理
//第二种情况则设vo.start为firstDate
//第三种情况提示 end 不能在firstDate之前
if(start.before(firstDate)){
//满足次条件的只有2和3 3会在后面进行拦截 所以此处不用处理
//处理第二种情况
vo.setStart(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,firstDate));
}
//执行到这里只有1、修正了时间的2 以及3
if(end.before(firstDate)){
//
return AjaxResult.error("end Date can not before "+DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD,firstDate));
}
}
}
}else {
//没有end
if(StringUtils.isNotNull(start) && firstDate.before(start)){
//只有用户传入了正确格式的开始时间 并且这个时间在firstDate之后才不用修改vo.start 否则都需要设置vo.start为firstDate
}else {
vo.setStart(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,firstDate));
}
}
List<HashRateDto> mhs24hList = poolMapper.getPoolHashRateHistory24hListByCoin(vo);
List<HashRateDto> mhs30mList = poolMapper.getPoolHashRateHistory30mListByCoin(vo);
PoolHashRateHistoryDto dto = new PoolHashRateHistoryDto();
dto.setMhs24hList(mhs24hList);
dto.setMhsList(mhs30mList);
dto.setUnit(unit.getUnit());
return AjaxResult.success(dto);
}
@Override
public AjaxResult getMinersList(CoinVo vo) {
PoolUnits unit = (PoolUnits) EnumUtils.get(PoolUnits.class, vo.getCoin());
if(StringUtils.isNull(unit)){
//防止coin注入异常数据
return AjaxResult.error("coin error");
}
MinerWatchDto dto = new MinerWatchDto();
List<MinerState> list = poolMapper.getMinerListByCoin(vo);
Map<String, Long> map = list.stream().collect(Collectors.groupingBy(
MinerState::getState,
Collectors.counting()
));
long total = Convert.toLong(list.size(),0L);
long online = map.getOrDefault("online", 0L);
long offline = map.getOrDefault("offline", 0L);
dto.setTotal(total);
dto.setOnline(online);
dto.setOffline(offline);
dto.setTimeout(BigDecimal.valueOf(total)
.subtract(BigDecimal.valueOf(online))
.subtract(BigDecimal.valueOf(offline))
.longValue());
return AjaxResult.success(dto);
}
@Override
public AjaxResult getWatch(CoinVo vo) {
PoolUnits unit = (PoolUnits) EnumUtils.get(PoolUnits.class, vo.getCoin());
if(StringUtils.isNull(unit)){
//防止coin注入异常数据
return AjaxResult.error("coin error");
}
PoolAmount poolAmount = (PoolAmount) EnumUtils.get(PoolAmount.class, vo.getCoin());
if(StringUtils.isNull(poolAmount)){
//防止coin注入异常数据
return AjaxResult.error("coin error");
}
PoolWatchDto watch = poolMapper.getPoolWatchByCoin(vo);
if(StringUtils.isNull(watch)){
watch = new PoolWatchDto();
watch.setMiners(0);
watch.setMhs(BigDecimal.ZERO);
watch.setHeight(0);
}
//todo 加到配置文件中
int fee = 1;
if("enx".equals(vo.getCoin())){
Date now =new Date();
if(now.before(DateUtils.parseDate("2025-04-21"))){{
fee =0;
}}
}
watch.setFee(fee+"% PPLNS");
watch.setMinPay(poolAmount.getAmount());
DateVo dateVo = new DateVo();
dateVo.setCoin(vo.coin);
//Date today = DateUtils.dateTime(DateUtils.YYYY_MM_DD_HH_MM_SS, DateUtils.getDate());
Date today = DateUtils.dateTime(DateUtils.YYYY_MM_DD_HH_MM_SS, DateUtils.getDate()+" 00:00:00");
Calendar ca = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
ca.setTime(today);
ca.add(Calendar.DATE,-7);
Date start = ca.getTime();
dateVo.setStart(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,start));
List<HashRateDto> list = poolMapper.getPoolHashRateHistory24hListByCoin(dateVo);
list.stream().forEach(e -> {
e.setDate(DateUtils.addDays(e.getDate(),-1));
//MH/s 每秒转GH/s
//e.setPv(e.getPv().divide(BigDecimal.valueOf(1000),scale,BigDecimal.ROUND_HALF_UP).stripTrailingZeros());
});
//最后一条用实时表最新一组数据 字段mhs24h对应实时24h算力
HashRateDto lastDto = poolMapper.getPoolRealHashRateByCoin(vo);
Date now = DateUtils.parseDate(DateUtils.dateTimeNow(DateUtils.YYYY_MM_DD));
lastDto.setDate(now);
list.add(lastDto);
watch.setList(list);
watch.setUnit(unit.getUnit());
return AjaxResult.success(watch);
}
}

View File

@@ -0,0 +1,99 @@
package com.m2pool.oapi.utils;
import com.m2pool.common.core.utils.StringUtils;
import java.lang.reflect.Method;
/**
* @Description 枚举工具类
* @Date 2024/6/13 10:54
* @Author dy
*/
public class EnumUtils {
/**
* 通过值判断数值是否属于枚举类的值
* @param clzz 枚举类 Enum
* @param code
* @author wayleung
* @return
*/
public static boolean isInclude(Class<?> clzz,String code){
if(StringUtils.isEmpty(code)){
return false;
}
try {
if(clzz.isEnum()){
Object[] enumConstants = clzz.getEnumConstants();
Method name = clzz.getMethod("name");
for (Object enumConstant:enumConstants){
if (name.invoke(enumConstant).equals(code.toUpperCase())) {
return true;
}
}
}
}catch (Exception e){
throw new RuntimeException();
}
return false;
}
/**
* 通过值判断数值是否属于枚举类的值
* @param clzz 枚举类 Enum
* @param code
* @author wayleung
* @return
*/
public static Object get(Class<?> clzz,String code){
if(StringUtils.isEmpty(code)){
return null;
}
try {
if(clzz.isEnum()){
Object[] enumConstants = clzz.getEnumConstants();
Method getInfo = clzz.getMethod("name");
for (Object enumConstant:enumConstants){
if (getInfo.invoke(enumConstant).equals(code.toUpperCase())) {
return enumConstant;
}
}
}
}catch (Exception e){
throw new RuntimeException();
}
return null;
}
public static String getNumberTypeStr(Class<?> clzz,String value){
if(StringUtils.isEmpty(value)){
return null;
}
try {
if(clzz.isEnum()){
Object[] enumConstants = clzz.getEnumConstants();
Method getInfo = clzz.getMethod("getInfo");
Method getValue = clzz.getMethod("getValue");
for (Object enumConstant:enumConstants){
if (getInfo.invoke(enumConstant).equals(value)) {
return (String) getValue.invoke(enumConstant);
}
}
}
}catch (Exception e){
throw new RuntimeException();
}
return null;
}
}

View File

@@ -0,0 +1,32 @@
package com.m2pool.oapi.vo;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.m2pool.common.core.xss.Xss;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
* @Description TODO
* @Date 2024/9/12 15:49
* @Author 杜懿
*/
@Data
public class AccountDateVo {
@NotBlank(message = "矿工账号不能为空")
@Xss
@JsonProperty("mining_user")
@JSONField(name = "mining_user")
public String ma;
@Xss
public String coin;
@Xss
public String start;
@Xss
public String end;
}

View File

@@ -0,0 +1,36 @@
package com.m2pool.oapi.vo;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.m2pool.common.core.xss.Xss;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
* @Description TODO
* @Date 2024/9/12 15:49
* @Author 杜懿
*/
@Data
public class AccountMinerDateVo {
@NotBlank(message = "矿工账号不能为空")
@Xss
@JsonProperty("mining_user")
@JSONField(name = "mining_user")
public String ma;
@NotBlank(message = "矿机号不能为空")
@Xss
public String miner;
@Xss
public String coin;
@Xss
public String start;
@Xss
public String end;
}

View File

@@ -0,0 +1,30 @@
package com.m2pool.oapi.vo;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.m2pool.common.core.xss.Xss;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
* @Description TODO
* @Date 2024/9/12 15:49
* @Author 杜懿
*/
@Data
public class AccountMinerVo {
@NotBlank(message = "矿工账号不能为空")
@Xss
@JsonProperty("mining_user")
@JSONField(name = "mining_user")
public String ma;
@Xss
public String coin;
@NotBlank(message = "矿机号不能为空")
@Xss
public String miner;
}

View File

@@ -0,0 +1,26 @@
package com.m2pool.oapi.vo;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.m2pool.common.core.xss.Xss;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
* @Description TODO
* @Date 2024/9/12 15:49
* @Author 杜懿
*/
@Data
public class AccountVo {
@NotBlank(message = "矿工账号不能为空")
@Xss
@JsonProperty("mining_user")
@JSONField(name = "mining_user")
public String ma;
@Xss
public String coin;
}

View File

@@ -0,0 +1,16 @@
package com.m2pool.oapi.vo;
import com.m2pool.common.core.xss.Xss;
import lombok.Data;
/**
* @Description TODO
* @Date 2024/9/12 15:49
* @Author 杜懿
*/
@Data
public class CoinVo {
@Xss
public String coin;
}

View File

@@ -0,0 +1,24 @@
package com.m2pool.oapi.vo;
import com.m2pool.common.core.xss.Xss;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
* @Description TODO
* @Date 2024/9/12 15:49
* @Author 杜懿
*/
@Data
public class DateVo {
@Xss
public String start;
@Xss
public String end;
@Xss
public String coin;
}

View File

@@ -0,0 +1,156 @@
server:
port: 9207
compression:
enabled: true
mime-types: application/json
spring:
#邮箱基本配置
mail:
# 配置在limit_time内用户可以发送limit次验证码
limit: 2 这个是我额外的配置,结合邮箱服务用的
limitTime: 10 这个是我额外的配置
#配置smtp服务主机地址
# sina smtp.sina.cn
# aliyun smtp.aliyun.com
# 163 smtp.163.com 端口号465或994
host: mail.privateemail.com
#发送者邮箱
username: support@m2pool.cc
#配置密码,注意不是真正的密码,而是刚刚申请到的授权码
# password:
# password: m2pool2024@!
# password: axvm-zfgx-cgcg-qhhu
password: m2pool2024@!
#端口号
port: 587
#默认的邮件编码为UTF-8
default-encoding: UTF-8
#其他参数
properties:
mail:
#配置SSL 加密工厂
smtp:
ssl:
#本地测试先放开ssl
enable: false
required: false
#开启debug模式这样邮件发送过程的日志会在控制台打印出来方便排查错误
debug: false
socketFactory:
class: javax.net.ssl.SSLSocketFactory
application:
# 应用名称
name: m2pool-oapi
profiles:
# 环境配置
active: prod
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: 127.0.0.1:8808
namespace: m2_prod
group: m2_prod_group
# server-addr: 127.0.0.1:8808
config:
# 配置中心地址
server-addr: 127.0.0.1:8808
# server-addr: 127.0.0.1:8808
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
namespace: m2_prod
group: m2_prod_group
servlet:
multipart:
max-file-size: 2MB
max-request-size: 8MB
myenv:
domain: https://www.m2pool.com
path: /var/www/html/web
img: /img
##测试环境
#server:
# port: 9507
# compression:
# enabled: true
# mime-types: application/json
#
#spring:
# #邮箱基本配置
# mail:
# # 配置在limit_time内用户可以发送limit次验证码
# limit: 2 这个是我额外的配置,结合邮箱服务用的
# limitTime: 10 这个是我额外的配置
# #配置smtp服务主机地址
# # sina smtp.sina.cn
# # aliyun smtp.aliyun.com
# # 163 smtp.163.com 端口号465或994
# host: mail.privateemail.com
# #发送者邮箱
# username: support@m2pool.cc
# #配置密码,注意不是真正的密码,而是刚刚申请到的授权码
# # password:
# # password: m2pool2024@!
# # password: axvm-zfgx-cgcg-qhhu
# password: m2pool2024@!
# #端口号
# port: 587
# #默认的邮件编码为UTF-8
# default-encoding: UTF-8
# #其他参数
# properties:
# mail:
# #配置SSL 加密工厂
# smtp:
# ssl:
# #本地测试先放开ssl
# enable: false
# required: false
# #开启debug模式这样邮件发送过程的日志会在控制台打印出来方便排查错误
# debug: false
# socketFactory:
# class: javax.net.ssl.SSLSocketFactory
#
# application:
# # 应用名称
# name: m2pool-oapi
# profiles:
# # 环境配置
# active: test
# cloud:
# nacos:
# discovery:
# # 服务注册地址
# server-addr: 127.0.0.1:8808
# namespace: m2_test
# group: m2_test_group
# # server-addr: 127.0.0.1:8808
# config:
# # 配置中心地址
# server-addr: 127.0.0.1:8808
# # server-addr: 127.0.0.1:8808
# # 配置文件格式
# file-extension: yml
# # 共享配置
# shared-configs:
# - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
# namespace: m2_test
# group: m2_test_group
# servlet:
# multipart:
# max-file-size: 2MB
# max-request-size: 8MB
#
#myenv:
# domain: https://test.m2pool.com
# path: /var/www/html/web_test
# img: /img

View File

@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- 日志存放路径 -->
<property name="log.path" value="logs/m2pool-oapi" />
<!-- 日志输出格式 -->
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
<!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 系统日志输出 -->
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/info.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/info.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 30天 -->
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>INFO</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/error.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/error.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 30天 -->
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>ERROR</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 系统模块日志级别控制 -->
<logger name="com.m2pool" level="info" />
<!-- Spring日志级别控制 -->
<logger name="org.springframework" level="warn" />
<root level="info">
<appender-ref ref="console" />
</root>
<!--系统操作日志-->
<root level="info">
<appender-ref ref="file_info" />
<appender-ref ref="file_error" />
</root>
</configuration>

View File

@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.m2pool.oapi.mapper.AccountMapper">
<select id="getAccountRealHashRateListByCoinAndAccount" resultType="com.m2pool.oapi.dto.HashRateRealDto">
select
mhs30m mhs,
mhs24h
from
${vo.coin}_mhs_realv2
where
`user` = '${vo.ma}'
</select>
<select id="getAccountHashRateHistory24hListByCoinAndAccount" resultType="com.m2pool.oapi.dto.HashRateDto">
select
`date`,
mhs
from
${vo.coin}_users_24h
<where>
`user` = '${vo.ma}'
<if test="vo.start != null and vo.start != ''">
and `date` &gt; "${vo.start}"
</if>
<if test="vo.end != null and vo.end != ''">
and `date` &lt;= "${vo.end}"
</if>
</where>
order by date
</select>
<select id="getAccountHashRateHistory30mListByCoinAndAccount" resultType="com.m2pool.oapi.dto.HashRateDto">
select
`date`,
mhs
from
${vo.coin}_users_30m
where
`user` = '${vo.ma}'
and `date` &gt; "${start}"
order by date
</select>
<select id="getMinerListByCoinAndAccount" resultType="com.m2pool.oapi.entity.MinerState">
select
miner,
`state`
from
${vo.coin}_mhs_realv2
where
`user` = '${vo.ma}'
</select>
</mapper>

View File

@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.m2pool.oapi.mapper.MinerMapper">
<select id="getMinerRealHashRateByCoinAndAccountMiner" resultType="com.m2pool.oapi.dto.HashRateRealDto">
select
mhs30m mhs,
mhs24h
from
${vo.coin}_mhs_realv2
where
`user` = '${vo.ma}' and miner= '${vo.miner}'
order by date desc limit 1
</select>
<select id="getMinerHashRateHistory24hListByCoinAndAccountMiner"
resultType="com.m2pool.oapi.dto.HashRateDto">
select
`date`,
mhs
from
${vo.coin}_mhs24h
<where>
`user` = '${vo.ma}'
and miner = '${vo.miner}'
<if test="vo.start != null and vo.start != ''">
and `date` &gt; "${vo.start}"
</if>
<if test="vo.end != null and vo.end != ''">
and `date` &lt;= "${vo.end}"
</if>
</where>
order by date
</select>
<select id="getMinerHashRateHistory30mListByCoinAndAccountMiner"
resultType="com.m2pool.oapi.dto.HashRateDto">
select
`date`,
mhs
from
${vo.coin}_mhs30m
where
`user` = '${vo.ma}'
and miner = '${vo.miner}'
and `date` &gt; "${start}"
order by date
</select>
</mapper>

View File

@@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.m2pool.oapi.mapper.PoolMapper">
<select id="getPoolRealHashRateListByCoin" resultType="com.m2pool.oapi.dto.HashRateRealDto">
select
sum(mhs30m) mhs,
sum(mhs24h) mhs24h
from
${vo.coin}_mhs_realv2
</select>
<select id="getPoolHashRateHistory24hListByCoin" resultType="com.m2pool.oapi.dto.HashRateDto">
select
`date`,
mhs
from
${vo.coin}_pool_24h
<where>
<if test="vo.start != null and vo.start != ''">
and `date` &gt; "${vo.start}"
</if>
<if test="vo.end != null and vo.end != ''">
and `date` &lt;= "${vo.end}"
</if>
</where>
order by date
</select>
<select id="getPoolHashRateHistory30mListByCoin" resultType="com.m2pool.oapi.dto.HashRateDto">
select
`date`,
mhs
from
${vo.coin}_pool_30m
<where>
<if test="vo.start != null and vo.start != ''">
and `date` &gt; "${vo.start}"
</if>
<if test="vo.end != null and vo.end != ''">
and `date` &lt;= "${vo.end}"
</if>
</where>
order by date
</select>
<select id="getMinerListByCoin" resultType="com.m2pool.oapi.entity.MinerState">
select
miner,
`state`
from
${vo.coin}_mhs_realv2
</select>
<select id="getPoolWatchByCoin" resultType="com.m2pool.oapi.dto.PoolWatchDto">
select
sum(mhs24h) mhs,
count(case when state='online' then 1 END) as miners,
(select height from distribution.${vo.coin}_blkreportprofitv2 order by date desc limit 1) as height
from
${vo.coin}_mhs_realv2 limit 1
</select>
<select id="getPoolRealHashRateByCoin" resultType="com.m2pool.oapi.dto.HashRateDto">
select `date`,sum(mhs24h) mhs from ${vo.coin}_mhs_realv2 group by date order by date desc limit 1
</select>
</mapper>

View File

@@ -0,0 +1,216 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>m2pool-modules</artifactId>
<groupId>com.m2pool</groupId>
<version>3.5.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>m2pool-pool</artifactId>
<dependencies>
<!-- SpringCloud Alibaba Nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- SpringCloud Alibaba Nacos Config -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- SpringCloud Alibaba Sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- SpringBoot Actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- Swagger UI -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.fox.version}</version>
</dependency>
<!-- Mysql Connector -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-maven-plugin</artifactId>
<scope>provided</scope>
</dependency>
<!-- &lt;!&ndash; Mybatis-Plus &ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>com.baomidou</groupId>-->
<!-- <artifactId>mybatis-plus-boot-starter</artifactId>-->
<!-- <exclusions>-->
<!-- <exclusion>-->
<!-- <artifactId>jsqlparser</artifactId>-->
<!-- <groupId>com.github.jsqlparser</groupId>-->
<!-- </exclusion>-->
<!--&lt;!&ndash; <exclusion>&ndash;&gt;-->
<!--&lt;!&ndash; <artifactId>mybatis</artifactId>&ndash;&gt;-->
<!--&lt;!&ndash; <groupId>org.mybatis</groupId>&ndash;&gt;-->
<!--&lt;!&ndash; </exclusion>&ndash;&gt;-->
<!-- </exclusions>-->
<!-- </dependency>-->
<!-- M2Pool Common DataSource -->
<dependency>
<groupId>com.m2pool</groupId>
<artifactId>common-datasource</artifactId>
</dependency>
<!-- M2Pool Common security -->
<dependency>
<groupId>com.m2pool</groupId>
<artifactId>common-security</artifactId>
</dependency>
<dependency>
<groupId>com.m2pool</groupId>
<artifactId>common-log</artifactId>
</dependency>
<dependency>
<groupId>com.m2pool</groupId>
<artifactId>common-swagger</artifactId>
</dependency>
<!-- WebSocket-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.java-websocket</groupId>
<artifactId>Java-WebSocket</artifactId>
<version>1.3.5</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.6.2</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
<scope>compile</scope>
</dependency>
<!--google两步认证相关-->
<dependency>
<groupId>de.taimos</groupId>
<artifactId>totp</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.10</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.18.0</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.70</version> <!-- 请使用最新版本 -->
</dependency>
</dependencies>
<profiles>
<profile>
<!-- 本地环境 -->
<id>dev</id>
<properties>
<spring.profile>dev</spring.profile>
<nacos.server.address>127.0.0.1:8808</nacos.server.address>
</properties>
<activation>
<!-- 是否默认激活 -->
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<!-- 测试环境 -->
<id>test</id>
<properties>
<spring.profile>test</spring.profile>
<nacos.server.address>127.0.0.1:8808</nacos.server.address>
</properties>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
</profile>
<profile>
<!-- 生产环境 -->
<id>prod</id>
<properties>
<spring.profile>prod</spring.profile>
<nacos.server.address>127.0.0.1:8808</nacos.server.address>
</properties>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
</profile>
</profiles>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,34 @@
package com.m2pool.pool;
import com.m2pool.common.swagger.annotation.EnableCustomSwagger2;
import com.m2pool.common.security.annotation.EnableCustomConfig;
import com.m2pool.common.security.annotation.EnableM2PoolFeignClients;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
/**
* @Description pool服务入口类
* @Date 2024/6/14 13:42
* @Author dy
*/
@EnableCustomConfig
@EnableCustomSwagger2
@EnableM2PoolFeignClients
@SpringBootApplication
@MapperScan({"com.m2pool.pool.mapper"})
public class M2PoolApplication {
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(M2PoolApplication.class,args);
System.out.println("m2pool矿池微服务启动成功");
}
}

View File

@@ -0,0 +1,19 @@
//package com.m2pool.pool.config;
//
//import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
//import com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize;
//import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.Configuration;
//
///**
// * @Description TODO
// * @Date 2024/6/14 11:15
// * @Author dy
// */
//@Configuration
//public class MybatisPlusConfig {
// @Bean
// public PaginationInterceptor paginationInterceptor(){
// return new PaginationInterceptor();
// }
//}

View File

@@ -0,0 +1,77 @@
package com.m2pool.pool.config;
import com.m2pool.pool.factory.IgnoreSSLRequestFactory;
import org.apache.http.client.HttpClient;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContextBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
/**
* @Description TODO
* @Date 2024/6/14 14:59
* @Author dy
*/
@Configuration
public class RestTemplateConfig {
/**
* 使用ssl对证书进行验证需要将证书导出到jdk管理仓库
* 命令keytool -import -v -trustcacerts -alias mytest -file "D:/tmp/mytest.cer" -keystore "C:/Program Files/Java/jdk1.8.0_131/jre/lib/security/cacerts"
*/
//@Bean("restTemplate")
//@Primary
//public RestTemplate restTemplate() throws NoSuchAlgorithmException, KeyManagementException {
// HttpComponentsClientHttpRequestFactory httpRequestFactory = new
// HttpComponentsClientHttpRequestFactory();
// httpRequestFactory.setConnectionRequestTimeout(6 * 1000); //获取连接池连接的超时时间(毫秒)
// httpRequestFactory.setConnectTimeout(6 * 1000); //连接上服务器(握手成功)的时间(毫秒)
// httpRequestFactory.setReadTimeout(60 * 1000); //返回数据时间(毫秒)
// httpRequestFactory.setHttpClient(httpClient());
// RestTemplate restTemplate = new RestTemplate(httpRequestFactory);
// return restTemplate;
//}
/**
* 绕过ssl对证书进行验证无需将证书导出到jdk管理仓库
*/
@Bean("restTemplateIgnoreSSL")
public RestTemplate restTemplateIgnoreSSL() throws NoSuchAlgorithmException, KeyManagementException {
IgnoreSSLRequestFactory requestFactory = new IgnoreSSLRequestFactory(httpClient());
requestFactory.setConnectTimeout(60000); //连接上服务器(握手成功)的时间
requestFactory.setReadTimeout(60000); //返回数据时间
RestTemplate restTemplate = new RestTemplate(requestFactory);
return restTemplate;
}
@Bean
public HttpClient httpClient() throws KeyManagementException, NoSuchAlgorithmException {
SSLContextBuilder contextBuilder = new SSLContextBuilder();
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(contextBuilder.build(), NoopHostnameVerifier.INSTANCE);
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", new PlainConnectionSocketFactory())
.register("https", socketFactory).build();
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
connectionManager.setMaxTotal(200);
connectionManager.setDefaultMaxPerRoute(100);
CloseableHttpClient httpClient = HttpClientBuilder.create().setConnectionManager(connectionManager).build();
return httpClient;
}
}

View File

@@ -0,0 +1,22 @@
package com.m2pool.pool.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
/**
* @Description scheduler配置类
* @Date 2024/10/25 10:26
* @Author 杜懿
*/
@Configuration
public class ScheduledTaskConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
taskScheduler.setPoolSize(20);
taskScheduler.initialize();
taskRegistrar.setTaskScheduler(taskScheduler);
}
}

View File

@@ -0,0 +1,20 @@
package com.m2pool.pool.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/**
* @Description websocket 配置
* @Date 2024/6/14 11:09
* @Author dy
*/
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter()
{
return new ServerEndpointExporter();
}
}

View File

@@ -0,0 +1,79 @@
package com.m2pool.pool.controller;
import com.github.pagehelper.PageHelper;
import com.m2pool.common.core.web.Result.AjaxResult;
import com.m2pool.common.core.web.controller.BaseController;
import com.m2pool.common.core.web.page.TableDataInfo;
import com.m2pool.common.security.annotation.RequiresLogin;
import com.m2pool.pool.dto.NoticeListDto;
import com.m2pool.pool.service.NoticeService;
import com.m2pool.pool.vo.*;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* @Description 告警系统相关请求接口
* @Date 2024/6/14 9:54
* @Author dy
*/
@RestController
@RequestMapping("/notice")
public class NoticeController extends BaseController {
@Autowired
private NoticeService noticeService;
@PostMapping("/addNoticeEmail")
@ApiOperation(value = "添加告警邮箱")
@RequiresLogin
public AjaxResult addNoticeEmail(@RequestBody NoticeAddVo vo){
return noticeService.addNoticeEmail(vo);
}
@PostMapping("/getCode")
@ApiOperation(value = "绑定通知邮箱 发送邮箱验证码")
@RequiresLogin
public AjaxResult getCode(@RequestBody NoticeAddVo vo){
clearPage();
return noticeService.getCode(vo);
}
@PostMapping("/getList")
@ApiOperation(value = "获取当前用户绑定的通知邮箱列表 ")
@RequiresLogin
public TableDataInfo getNoticeEmailList(@RequestBody NoticePageVo vo){
PageHelper.startPage(vo.getPage(),vo.getLimit());
List<NoticeListDto> list = noticeService.getNoticeEmailList(vo);
return getDataTable(list);
}
@PostMapping("/updateInfo")
@ApiOperation(value = "修改通知邮箱备注信息")
@RequiresLogin
public AjaxResult updateInfo(@RequestBody NoticeUpdateVo vo){
return noticeService.updateInfo(vo);
}
@DeleteMapping("/deleteEmail")
@ApiOperation(value = "删除通知邮箱")
@RequiresLogin
public AjaxResult deleteEmail(@RequestBody NoticeDelVo vo){
return noticeService.deleteEmail(vo);
}
}

View File

@@ -0,0 +1,203 @@
package com.m2pool.pool.controller;
import com.github.pagehelper.PageHelper;
import com.m2pool.common.core.web.Result.AjaxResult;
import com.m2pool.common.core.web.controller.BaseController;
import com.m2pool.common.core.web.page.TableDataInfo;
import com.m2pool.common.security.annotation.RequiresLogin;
import com.m2pool.pool.dto.BlockInfoDto;
import com.m2pool.pool.service.MinerAccountService;
import com.m2pool.pool.service.PoolService;
import com.m2pool.pool.vo.*;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;
/**
* @Description 统一请求接口
* @Date 2024/6/14 9:54
* @Author dy
*/
@RestController
//@RequestMapping("/pool")
public class PoolController extends BaseController {
@Autowired
private PoolService poolService;
@Autowired
private MinerAccountService maService;
@PostMapping("/getCoinInfo")
@ApiOperation(value = "获取币种(矿池)信息")
public AjaxResult getCoinInfo(@Valid @RequestBody CoinVo vo){
return poolService.getPoolInfo(vo);
}
@PostMapping("/checkAccount")
@ApiOperation(value = "校验挖矿账号是否存在")
public boolean checkAccount(@Valid @RequestBody MinerAccountAddVo vo){
return poolService.checkAccount(vo);
}
@PostMapping("/getPoolPower")
@ApiOperation(value = "获取币种(矿池)算力曲线图")
public AjaxResult getPoolPower(@Valid @RequestBody CoinVo vo){
return poolService.getPoolPower(vo);
}
//@PostMapping("/getMinerCount")
//@ApiOperation(value = "获取币种(矿池)矿工数量曲线图")
//public AjaxResult getMinerCount(@Valid @RequestBody CoinVo com.m2pool.chat.vo){
//
// return poolService.getMinerCount(com.m2pool.chat.vo);
//
//}
@PostMapping("/getLuck")
@ApiOperation(value = "获取币种(矿池)幸运值")
public AjaxResult getLuck(@Valid @RequestBody CoinVo vo){
return poolService.getLuckByCoin(vo);
}
@PostMapping("/getBlockInfo")
@ApiOperation(value = "获取币种(矿池)报块信息")
public TableDataInfo getBlockInfo(@RequestBody() CoinVo vo){
PageHelper.startPage(vo.getPage(),vo.getLimit());
List<BlockInfoDto> list = poolService.getBlockInfoList(vo);
return getDataTable(list);
}
//@PostMapping("/getPoolPowerDistribution")
//@ApiOperation(value = "获取当前矿池算力分布 柱状图")
//public AjaxResult getPoolPowerDistribution(@Valid @RequestBody CoinVo com.m2pool.chat.vo){
// //暂未使用
// return poolService.getPoolPowerDistribution(com.m2pool.chat.vo);
//
//}
@PostMapping("/getMinerAccountPower")
@ApiOperation(value = "获取当前挖矿账号算力曲线图")
@RequiresLogin
public AjaxResult getMinerAccountPower(@Valid @RequestBody AccountVo vo){
return maService.getMinerAccountPower(vo);
}
@PostMapping("/getAccountPowerDistribution")
@ApiOperation(value = "获取当前挖矿账号算力分布 柱状图")
@RequiresLogin
public AjaxResult getAccountPowerDistribution(@Valid @RequestBody AccountVo vo){
return maService.getAccountPowerDistribution(vo);
}
@PostMapping("/getMinerAccountInfo")
@ApiOperation(value = "获取当前挖矿账户收益信息")
@RequiresLogin
public AjaxResult getMinerAccountInfo(@Valid @RequestBody AccountVo vo){
return maService.getMinerAccountInfo(vo);
}
@PostMapping("/getMinerList")
@ApiOperation(value = "获取当前挖矿账户下矿工详情")
@RequiresLogin
public AjaxResult getMinerList(@Valid @RequestBody MinerListVo vo){
return maService.getMinerList(vo);
}
@PostMapping("/getMinerPower")
@ApiOperation(value = "获取矿工算力曲线图")
@RequiresLogin
public AjaxResult getMinerPower(@Valid @RequestBody MinerVo vo){
return maService.getMinerPower(vo);
}
//@PostMapping("/getMinerPowerDistribution")
//@ApiOperation(value = "获取矿工算力分布 柱状图")
//@RequiresLogin
//public AjaxResult getMinerPowerDistribution(@Valid @RequestBody MinerVo com.m2pool.chat.vo){
//
// return maService.getMinerPowerDistribution(com.m2pool.chat.vo);
//
//}
@PostMapping("/getHistoryIncome")
@ApiOperation(value = "获取收益历史记录")
@RequiresLogin
public TableDataInfo getHistoryIncome(@RequestBody() AccountVo vo){
//PageHelper.startPage(com.m2pool.chat.vo.getPage(),com.m2pool.chat.vo.getLimit());
return maService.getHistoryIncome(vo);
}
@PostMapping("/getHistoryOutcome")
@ApiOperation(value = "获取账号提现历史记录")
@RequiresLogin
public TableDataInfo getHistoryOutcome(@RequestBody() AccountVo vo){
return maService.getHistoryOutcome(vo);
}
@PostMapping(value = {"/getCoinBalanceList","/getCoinBalancetList"})
@ApiOperation(value = "获取币种余额list")
public AjaxResult getCoinBalancetList(@RequestBody BalanceListGetVo vo){
return poolService.getCoinBalanceList(vo);
}
@PostMapping("/getNetPower")
@ApiOperation(value = "获取全网算力曲线")
public AjaxResult getNetPower(@Valid @RequestBody CoinVo vo){
return poolService.getNetPower(vo);
}
@PostMapping("/getParam")
@ApiOperation(value = "根据币种获取计算器相关参数")
public AjaxResult getParam(@Valid @RequestBody CoinVo vo){
return poolService.getParam(vo);
}
@GetMapping("/test2")
@ApiOperation(value = "")
public AjaxResult test2(){
return poolService.test2();
}
@GetMapping("/test1")
@ApiOperation(value = "")
public AjaxResult test1(){
return poolService.test1();
}
}

View File

@@ -0,0 +1,146 @@
package com.m2pool.pool.controller;
import com.github.pagehelper.PageHelper;
import com.m2pool.common.core.utils.StringUtils;
import com.m2pool.common.core.web.Result.AjaxResult;
import com.m2pool.common.core.web.controller.BaseController;
import com.m2pool.common.core.web.page.TableDataInfo;
import com.m2pool.common.security.annotation.RequiresLogin;
import com.m2pool.pool.dto.UserReadPageInfoReturnDto;
import com.m2pool.pool.service.ReadOnlyService;
import com.m2pool.pool.vo.*;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;
/**
* @Description 统一请求接口
* @Date 2024/6/14 9:54
* @Author dy
*/
@RestController
@RequestMapping("/read")
public class ReadOnlyController extends BaseController {
@Autowired
private ReadOnlyService roService;
@PostMapping("/getHtmlUrl")
@ApiOperation(value = "创建只读页面 ")
@RequiresLogin
public AjaxResult getHtmlUrl(@Valid @RequestBody ReadOnlyHtmlCreateVo vo){
return roService.createPageUrl(vo);
}
@PostMapping("/getUrlList")
@ApiOperation(value = "获取当前用户只读页面列表 ")
@RequiresLogin
public TableDataInfo getUrlList(@RequestBody(required = false) PageVo vo){
if(StringUtils.isNull(vo)){
vo = new PageVo();
}
PageHelper.clearPage();
return roService.getUrlList(vo);
}
@PostMapping("/getUrlInfo")
@ApiOperation(value = "获取当前只读页面基础信息 ")
@RequiresLogin
public AjaxResult getUrlInfo(@Valid @RequestBody ReadOnlyKeyVo vo){
return roService.getUrlInfo(vo);
}
@PostMapping("/changeUrlInfo")
@ApiOperation(value = "修改只读页面 只能修改备注和权限")
@RequiresLogin
public AjaxResult changeUrlInfo(@Valid @RequestBody ReadOnlyHtmlChangeVo vo){
return roService.changeUrlInfo(vo);
}
@DeleteMapping("/delPage")
@ApiOperation(value = "修改只读页面 只能修改备注和权限")
@RequiresLogin
public AjaxResult delPage(@Valid @RequestBody ReadOnlyKeyVo vo){
return roService.delPageByKey(vo);
}
@PostMapping("/getPageInfo")
@ApiOperation(value = "只读页面 获取只读页面 权限信息")
public AjaxResult getPageInfo(@Valid @RequestBody ReadOnlyKeyVo vo){
return roService.getPageInfo(vo);
}
@PostMapping("/getMinerAccountPower")
@ApiOperation(value = "只读页面 获取只读页面 挖矿账号算力曲线图")
public AjaxResult getMinerAccountPower(@Valid @RequestBody ReadOnlyIntervalVo vo){
return roService.getMinerAccountPower(vo);
}
@PostMapping("/getAccountPowerDistribution")
@ApiOperation(value = "只读页面 获取挖矿账号算力分布 柱状图")
public AjaxResult getAccountPowerDistribution(@Valid @RequestBody ReadOnlyIntervalVo vo){
return roService.getAccountPowerDistribution(vo);
}
@PostMapping("/getProfitInfo")
@ApiOperation(value = "只读页面 获取挖矿账户收益信息")
public AjaxResult getMinerAccountInfo(@Valid @RequestBody ReadOnlyKeyVo vo){
return roService.getProfitInfo(vo);
}
@PostMapping("/getMinerList")
@ApiOperation(value = "只读页面 获取挖矿账户下矿工详情")
public AjaxResult getMinerList(@Valid @RequestBody ReadOnlyListVo vo){
PageHelper.clearPage();
return roService.getMinerList(vo);
}
@PostMapping("/getMinerPower")
@ApiOperation(value = "只读页面 获取矿工算力曲线图")
public AjaxResult getMinerPower(@Valid @RequestBody ReadOnlyMinerVo vo){
return roService.getMinerPower(vo);
}
@PostMapping("/getHistoryIncome")
@ApiOperation(value = "获取收益历史记录")
public TableDataInfo getHistoryIncome(@RequestBody() ReadOnlyPageVo vo){
PageHelper.clearPage();
return roService.getHistoryIncome(vo);
}
@PostMapping("/getHistoryOutcome")
@ApiOperation(value = "获取账号提现历史记录")
public TableDataInfo getHistoryOutcome(@RequestBody() ReadOnlyPageVo vo){
PageHelper.clearPage();
return roService.getHistoryOutcome(vo);
}
}

View File

@@ -0,0 +1,192 @@
package com.m2pool.pool.controller;
import com.github.pagehelper.PageHelper;
import com.m2pool.common.core.text.Convert;
import com.m2pool.common.core.utils.StringUtils;
import com.m2pool.common.core.web.Result.AjaxResult;
import com.m2pool.common.core.web.controller.BaseController;
import com.m2pool.common.core.web.page.TableDataInfo;
import com.m2pool.common.security.annotation.Logical;
import com.m2pool.common.security.annotation.RequiresLogin;
import com.m2pool.common.security.annotation.RequiresRoles;
import com.m2pool.pool.dto.IdsDto;
import com.m2pool.pool.dto.TicketListDto;
import com.m2pool.pool.service.TicketService;
import com.m2pool.pool.vo.*;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
/**
* @Description 统一请求接口
* @Date 2022/5/27 9:54
* @Author 杜懿
*/
@RestController
@RequestMapping("/ticket")
public class TicketController extends BaseController {
@Autowired
private TicketService ticketService;
@PostMapping("/uploadFile")
@ApiOperation(value = "文件上传")
public AjaxResult uploadFile(@RequestParam("file") MultipartFile[] file){
try {
return ticketService.uploadFiles(file);
} catch (SQLException e) {
e.printStackTrace();
return AjaxResult.error("服务器异常,请联系管理员");
}
}
@GetMapping("/downloadFile")
@ApiOperation(value = "文件批量下载")
public void download(IdsDto dto, HttpServletRequest request, HttpServletResponse response){
ticketService.downloadByIds(dto.getIds(),request,response);
}
@PostMapping("/submitTicket")
@ApiOperation(value = "提交工单")
@RequiresLogin
public AjaxResult submitTicket(@RequestBody(required = false) TicketVo vo){
if(StringUtils.isNull(vo)){vo = new TicketVo();}
return ticketService.submitTicket(vo);
}
@PostMapping("/resubmitTicket")
@ApiOperation(value = "工单内容补充工单")
@RequiresLogin
@RequiresRoles(value = {"admin", "registered"}, logical = Logical.OR)
public AjaxResult resubmitTicket(@RequestBody ResubmitTicketVo vo){
return ticketService.resubmitTicket(vo);
}
@PostMapping({"/getPrivateTicket","privateConsume"})
@ApiOperation(value = "个人工单列表")
@RequiresLogin
@RequiresRoles(value = {"admin", "registered"}, logical = Logical.OR)
public AjaxResult getPrivateTicket(@RequestBody(required = false) PrivateTicketListVo vo){
if(StringUtils.isNull(vo)){
vo = new PrivateTicketListVo();
vo.setStatus(0);
}
return ticketService.getPrivateTicketByStatus(vo);
}
@PostMapping({"/privateTicketDetails","getTicketDetails"})
@ApiOperation(value = "个人工单详情")
@RequiresLogin
public AjaxResult getPrivateTicketDetails(@RequestBody() IdVo vo){
return ticketService.getPrivateTicketDetails(vo.getId());
}
@PostMapping("/endTicket")
@ApiOperation(value = "用户关闭工单")
@RequiresLogin
@RequiresRoles(value = {"admin", "registered"}, logical = Logical.OR)
public AjaxResult endTicket(@RequestBody(required = false) EndTicketVo vo){
return ticketService.endTicket(vo);
}
/********************* admin相关接口 *************************/
//@PostMapping("/getTicketList")
//@ApiOperation(value = "按状态搜索后台工单列表")
//@RequiresLogin
//@RequiresRoles(value = {"admin", "accounting","support","maintainer"}, logical = Logical.OR)
//public TableDataInfo getTicketList(@RequestBody StatusVo com.m2pool.chat.vo){
// PageHelper.startPage(com.m2pool.chat.vo.getPage(),com.m2pool.chat.vo.getLimit());
// List<TicketListDto> list = ticketService.getTicketList(com.m2pool.chat.vo.getStatus());
// return getDataTable(list);
//}
@PostMapping("/bk/getAllTicket")
@ApiOperation(value = "条件搜索后台所有工单列表")
@RequiresLogin
@RequiresRoles("admin")
public TableDataInfo getAllTicket(@RequestBody AllTicketListVo vo){
System.out.println("com.m2pool.chat.vo"+vo);
if(StringUtils.isNotBlank(vo.getCond())){
System.out.println("不为空");
Pattern pattern = Pattern.compile("^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$");
if(pattern.matcher(vo.getCond()).matches()){
//验证是否是邮箱
System.out.println("邮箱"+vo.getCond());
vo.setEmail(vo.getCond());
}else {
//判断是否是id
Long id = Convert.toLong(vo.getCond(), 0L);
System.out.println(id);
if(id > 0){
System.out.println("工单id"+vo.getCond());
vo.setId(id);
}else {
return getDataTable(new ArrayList<>());
}
}
}
PageHelper.startPage(vo.getPage(),vo.getLimit());
return getDataTable(ticketService.getAllTicket(vo)) ;
}
@PostMapping("/bk/endTicket")
@ApiOperation(value = "关闭用户工单")
@RequiresLogin
@RequiresRoles(value = {"admin"}, logical = Logical.OR)
public AjaxResult endUserTicket(@RequestBody(required = false) IdVo vo){
return ticketService.closeTicket(vo);
}
@PostMapping("/bk/list")
@ApiOperation(value = "根据状态获取type为线上(type=0)的工单")
@RequiresLogin
@RequiresRoles(value = {"admin"}, logical = Logical.OR)
public TableDataInfo onlineTicketList(@RequestBody StatusVo vo){
PageHelper.startPage(vo.getPage(),vo.getLimit());
List<TicketListDto> list = ticketService.getSupportTicketList(vo);
return getDataTable(list);
}
@PostMapping("/bk/details")
@ApiOperation(value = "工单详情")
@RequiresLogin
@RequiresRoles(value = {"admin"}, logical = Logical.OR)
public AjaxResult onlineTicketDetails(@RequestBody IdVo vo){
if(StringUtils.isNull(vo)){
return AjaxResult.error("工单id缺失");
}
return ticketService.getTicketDetails(vo.getId());
}
@PostMapping("/bk/respon")
@ApiOperation(value = "回复工单")
@RequiresLogin
@RequiresRoles(value = {"admin"}, logical = Logical.OR)
public AjaxResult onlineResponTicket(@RequestBody ResponTicketVo vo){
return ticketService.onlineResponTicket(vo);
}
}

View File

@@ -0,0 +1,246 @@
package com.m2pool.pool.controller;
import com.github.pagehelper.PageHelper;
import com.m2pool.common.core.utils.StringUtils;
import com.m2pool.common.core.web.Result.AjaxResult;
import com.m2pool.common.core.web.controller.BaseController;
import com.m2pool.common.core.web.page.TableDataInfo;
import com.m2pool.common.security.annotation.RequiresLogin;
import com.m2pool.pool.dto.UserApiDto;
import com.m2pool.pool.service.GoogleAuthService;
import com.m2pool.pool.service.MinerAccountService;
import com.m2pool.pool.service.UserMinserService;
import com.m2pool.pool.vo.*;
import com.m2pool.system.api.RemoteUserService;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;
/**
* @Description 统一请求接口
* @Date 2024/6/14 9:54
* @Author dy
*/
@RestController
@RequestMapping("/user")
public class UserController extends BaseController {
@Autowired
private UserMinserService umService;
@Autowired
private GoogleAuthService googleAuthService;
@Autowired
private MinerAccountService maService;
@Autowired
private RemoteUserService userService;
@PostMapping("/addMinerAccount")
@ApiOperation(value = "绑定挖矿账号")
@RequiresLogin
public AjaxResult addMinerAccount(@Valid @RequestBody MinerAccountAddVo vo){
return umService.addMinerAccount(vo);
}
@PostMapping("/checkAccount")
@ApiOperation(value = "校验挖矿账号是否存在")
@RequiresLogin
public AjaxResult checkAccount(@Valid @RequestBody MinerAccountAddVo vo){
return umService.checkAccount(vo);
}
@PostMapping("/checkBalance")
@ApiOperation(value = "校验钱包可用性")
@RequiresLogin
public AjaxResult checkBalance(@Valid @RequestBody BalanceCheckVo vo){
return umService.checkBalance(vo);
}
@PostMapping("/check")
@ApiOperation(value = "校验账户是否可用和钱包可用性")
@RequiresLogin
public AjaxResult check(@Valid @RequestBody MaBalanceCheckVo vo){
return umService.checkMaAndBalance(vo);
}
@DeleteMapping("/delMinerAccount")
@ApiOperation(value = "删除挖矿账号")
@RequiresLogin
public AjaxResult delMinerAccount(@Valid @RequestBody MinerAccountDelVo vo){
return umService.delMinerAccount(vo);
}
@PostMapping("/addBalance")
@ApiOperation(value = "挖矿账户绑定钱包-->>现改为 修改钱包地址或起付线以及切换自动提现激活状态")
@RequiresLogin
public AjaxResult addBalance(@Valid @RequestBody AccountBalanceAddVo vo){
return umService.addBalance(vo);
}
//@PostMapping("/updateBalance")
//@ApiOperation(value = "挖矿账户解绑钱包")
//@RequiresLogin
//public AjaxResult updateBalance(@Valid @RequestBody AccountBalanceAddVo com.m2pool.chat.vo){
//
// return umService.updateBalance(com.m2pool.chat.vo);
//
//}
@PostMapping("/getAccountList")
@ApiOperation(value = "获取用户当前币种下所有挖矿账号")
@RequiresLogin
public AjaxResult getAccountList(){
return umService.getAccountList();
}
@PostMapping("/getAccountGradeList")
@ApiOperation(value = "获取用户当前币种下所有挖矿账号")
@RequiresLogin
public AjaxResult getAccountGradeList(){
return umService.getAccountGradeList();
}
@PostMapping("/getMinerAccountBalance")
@ApiOperation(value = "获取当前矿工账号绑定钱包地址")
@RequiresLogin
public AjaxResult getMinerAccountBalance(@RequestBody MinerIdVo vo){
return umService.getMinerAccountBalance(vo);
}
/**************************************** google两步验证相关接口 ***********************************************************/
@PostMapping("/ifBind")
@ApiOperation(value = "校验钱包可用性")
@RequiresLogin
public AjaxResult ifBind(){
clearPage();
return googleAuthService.ifBind();
}
@PostMapping("/getBindInfo")
@ApiOperation(value = "获取谷歌验证器 安全码和验证码")
@RequiresLogin
public AjaxResult getBindInfo(){
clearPage();
return googleAuthService.getBindInfo();
}
@PostMapping("/getBindCode")
@ApiOperation(value = "绑定谷歌验证器 发送邮箱验证码")
@RequiresLogin
public AjaxResult getBindCode(){
clearPage();
return googleAuthService.getBindCode();
}
@PostMapping("/bindGoogle")
@ApiOperation(value = "绑定谷歌验证器")
@RequiresLogin
public AjaxResult bindGoogle(@Valid @RequestBody GoogleBindVo vo){
clearPage();
return googleAuthService.bindGoogle(vo);
}
@PostMapping("/closeStepTwo")
@ApiOperation(value = "关闭两步验证")
@RequiresLogin
public AjaxResult closeStepTwo(@Valid @RequestBody GoogleCloseVo vo){
clearPage();
return googleAuthService.closeStepTwp(vo);
}
@PostMapping("/getCloseCode")
@ApiOperation(value = "关闭谷歌验证器 发送邮箱验证码")
@RequiresLogin
public AjaxResult getCloseCode(){
clearPage();
return googleAuthService.getCloseCode();
}
@PostMapping("/emailIfBind")
@ApiOperation(value = "校验钱包可用性")
public AjaxResult emailIfBind(@Valid @RequestBody EmailVo vo){
clearPage();
return googleAuthService.emailIfBind(vo);
}
@PostMapping("/getApiKey")
@ApiOperation(value = "创建apiKey")
@RequiresLogin
public AjaxResult getApiKey(@Valid @RequestBody ApiKeyCreateVo vo){
return umService.createApiKey(vo);
}
@PostMapping("/getApiList")
@ApiOperation(value = "获取当前用户apiKEY列表 ")
@RequiresLogin
public TableDataInfo getApiList(@RequestBody(required = false) PageVo vo){
if(StringUtils.isNull(vo)){
vo = new PageVo();
}
PageHelper.startPage(vo.getPage(),vo.getLimit());
List<UserApiDto> list = umService.getApiList(vo);
return getDataTable(list);
}
@PostMapping("/getApiInfo")
@ApiOperation(value = "获取当前只读页面基础信息 ")
@RequiresLogin
public AjaxResult getApiInfo(@Valid @RequestBody ApiKeyInfoVo vo){
return umService.getApiInfo(vo);
}
@PostMapping("/updateAPI")
@ApiOperation(value = "修改API绑定信息 只能修改备注和权限")
@RequiresLogin
public AjaxResult updateAPI(@Valid @RequestBody ApiKeyUpdateVo vo){
return umService.updateApi(vo);
}
@DeleteMapping("/delApi")
@ApiOperation(value = "删除指定api 只能修改备注和权限")
@RequiresLogin
public AjaxResult delApi(@Valid @RequestBody ApiKeyDelVo vo){
return umService.deleteApi(vo);
}
}

View File

@@ -0,0 +1,29 @@
package com.m2pool.pool.dto;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* @Description 曲线图数据结构
* @Date 2024/6/13 11:17
* @Author dy
*/
@Data
public class AccountPowerDto implements Serializable {
/** 日期 */
private Date date;
/** 矿池算力 */
private double pv;
/** 有效提交数 */
private BigDecimal accepts;
/** 被拒提交数 */
private BigDecimal rejects;
}

View File

@@ -0,0 +1,37 @@
package com.m2pool.pool.dto;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* @Description 曲线图数据结构
* @Date 2024/6/13 11:17
* @Author dy
*/
@Data
public class AccountProfitInfoDto implements Serializable {
/** 挖矿账户 */
private String account;
/** 总收益 */
private BigDecimal totalProfit;
/** 总支出 */
private BigDecimal expend;
/** 昨日收益 */
private BigDecimal preProfit;
/** 今日收益 */
private BigDecimal todayPorfit;
/** 余额 */
private BigDecimal balance;
private BigDecimal withdrawable;
}

View File

@@ -0,0 +1,26 @@
package com.m2pool.pool.dto;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
/**
* @Description TODO
* @Date 2022/6/20 17:44
* @Author 杜懿
*/
@Data
public class AllTicketListDto {
private int id;
private Date date;
private String desc;
private String email;
private String status;
}

View File

@@ -0,0 +1,25 @@
package com.m2pool.pool.dto;
import lombok.Data;
import java.io.Serializable;
/**
* @Description 幸运值
* @Date 2024/6/13 11:17
* @Author dy
*/
@Data
public class BalanceListDto implements Serializable {
/** 挖矿账户名 */
private String user;
/** 钱包地址 */
private String address;
/** 起付线 */
private double amount;
}

View File

@@ -0,0 +1,31 @@
package com.m2pool.pool.dto;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* @Description 当前币种矿池报块信息
* @Date 2024/6/13 11:17
* @Author dy
*/
@Data
public class BlockInfoDto implements Serializable {
/** 区块高度 */
private int height;
/** 报块时间 */
private Date date;
/** 区块hash */
private String hash;
/** 报块奖励 */
private double reward;
/** 交易费 */
private double fees;
}

View File

@@ -0,0 +1,32 @@
package com.m2pool.pool.dto;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* @Description 返回数据实体
* @Date 2024/6/13 11:17
* @Author dy
*/
@Data
public class CalParamDto implements Serializable {
/** 币种 */
private String coin;
/** 全网算力 */
private BigDecimal netHashrate;
/** 区块奖励 */
private BigDecimal reward;
/** 每日报块数 */
private BigDecimal count;
/** 矿池手续费 */
private BigDecimal poolFee;
}

View File

@@ -0,0 +1,21 @@
package com.m2pool.pool.dto;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* @Description 返回数据实体
* @Date 2024/6/13 11:17
* @Author dy
*/
@Data
public class ComDataDto implements Serializable {
/** 时间 */
private Date date;
/** 数据值 */
private Object value;
}

View File

@@ -0,0 +1,25 @@
package com.m2pool.pool.dto;
import com.alibaba.nacos.shaded.com.google.gson.annotations.SerializedName;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* @Description 返回数据实体
* @Date 2024/6/13 11:17
* @Author dy
*/
@Data
public class CountDto implements Serializable {
/** 时间 */
private Date dataTime;
/** 数据条数 */
private int num;
private BigDecimal price;
}

View File

@@ -0,0 +1,25 @@
package com.m2pool.pool.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* @Description 返回数据实体
* @Date 2024/6/13 11:17
* @Author dy
*/
@Data
public class DateBigDecimalDto implements Serializable {
/** 时间 */
private Date pDate;
/** 数据值 */
private BigDecimal value;
private BigDecimal price;
}

View File

@@ -0,0 +1,28 @@
package com.m2pool.pool.dto;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* @Description 返回数据实体
* @Date 2024/6/13 11:17
* @Author dy
*/
@Data
public class DateBigDecimalsDto implements Serializable {
/** 时间 */
private Date date;
/** 数据值 */
private BigDecimal value1;
private BigDecimal value2;
private BigDecimal value3;
private BigDecimal value4;
}

View File

@@ -0,0 +1,22 @@
package com.m2pool.pool.dto;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* @Description 返回数据实体
* @Date 2024/6/13 11:17
* @Author dy
*/
@Data
public class DateStrBigDecimalDto implements Serializable {
/** 时间 */
private String date;
/** 数据值 */
private BigDecimal value;
}

View File

@@ -0,0 +1,21 @@
package com.m2pool.pool.dto;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* @Description 返回数据实体
* @Date 2024/6/13 11:17
* @Author dy
*/
@Data
public class DateStrStringDto implements Serializable {
/** 时间 */
private String date;
/** 数据值 */
private String value;
}

View File

@@ -0,0 +1,22 @@
package com.m2pool.pool.dto;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* @Description 返回数据实体
* @Date 2024/6/13 11:17
* @Author dy
*/
@Data
public class DateStringDto implements Serializable {
/** 时间 */
private Date date;
/** 数据值 */
private String value;
}

View File

@@ -0,0 +1,25 @@
package com.m2pool.pool.dto;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* @Description 返回数据实体
* @Date 2024/6/13 11:17
* @Author dy
*/
@Data
public class DistributionDto implements Serializable {
/** 算力范围低值 */
private int low;
/** 算力范围高值 */
private int high;
/** 矿工数 */
private int count;
}

View File

@@ -0,0 +1,22 @@
package com.m2pool.pool.dto;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* @Description 返回数据实体
* @Date 2024/6/13 11:17
* @Author dy
*/
@Data
public class GoogleInfoDto implements Serializable {
/** 谷歌验证码 */
private String secret;
/** 二维码 */
private String img;
}

View File

@@ -0,0 +1,15 @@
package com.m2pool.pool.dto;
import lombok.Data;
import java.io.Serializable;
/**
* @Description 返回数据实体
* @Date 2022/5/30 11:17
* @Author 杜懿
*/
@Data
public class IdsDto implements Serializable {
private String ids;
}

View File

@@ -0,0 +1,35 @@
package com.m2pool.pool.dto;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* @Description 矿工信息总览表对象
* @Date 2024/6/13 11:17
* @Author dy
*/
@Data
public class IncomeDto implements Serializable {
/** 时间 */
private Date date;
/** 难度 */
private String difficult;
/** 币种/矿池 */
private String coin;
/** 收益 */
private BigDecimal amount;
/** 备注 */
private double mhs;
private String comment;
}

View File

@@ -0,0 +1,28 @@
package com.m2pool.pool.dto;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* @Description 幸运值
* @Date 2024/6/13 11:17
* @Author dy
*/
@Data
public class LuckDto implements Serializable {
/** 3日幸运值 */
private double luck3d;
/** 7日幸运值 */
private double luck7d;
/** 30日幸运值 */
private double luck30d;
/** 90日幸运值 */
private double luck90d;
}

View File

@@ -0,0 +1,31 @@
package com.m2pool.pool.dto;
import lombok.Data;
import java.io.Serializable;
/**
* @Description 矿工信息总览表对象
* @Date 2024/6/13 11:17
* @Author dy
*/
@Data
public class MinerAccountBalanceDto implements Serializable {
private long id;
/** 挖矿账户 */
private String ma;
/** 提现收款地址 */
private String balance;
/** 是否激活 */
private int active;
private double amount;
private String remark;
}

View File

@@ -0,0 +1,22 @@
package com.m2pool.pool.dto;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* @Description 币种(矿池)矿工数量曲线图数据结构
* @Date 2024/6/13 11:17
* @Author dy
*/
@Data
public class MinerCountLineDto implements Serializable {
/** 日期 */
private Date date;
/** 矿工数量 */
private int value;
}

View File

@@ -0,0 +1,59 @@
package com.m2pool.pool.dto;
import com.fasterxml.jackson.annotation.JsonAlias;
import lombok.Data;
import javax.naming.Name;
import java.io.Serializable;
import java.util.Date;
/**
* @Description 当前币种矿池信息
* @Date 2024/6/13 11:17
* @Author dy
*/
@Data
public class MinerDataDto implements Serializable {
/** id */
private long id;
/** 时间 */
private Date date;
/** 挖矿账号 */
private String user;
/** 矿工名 */
private String miner;
private String refindex;
/** 1小时平均算力 */
private double mhs;
/** 24小时平均算力 */
private double mhs24h;
/** 申请次数?通过次数? */
private int accepts;
/** 被拒次数 */
private int rejects;
/** 拒绝率 */
//private int rejects_ratio;
@JsonAlias("rejects_ratio")
private double rejectsRatio;
/** 最后一次提交的时间 */
@JsonAlias("last_submit")
private Date lastSubmit;
/** 1天内在线时间 */
private String state;
/** 是否在线 */
private String online;
}

View File

@@ -0,0 +1,59 @@
package com.m2pool.pool.dto;
import com.fasterxml.jackson.annotation.JsonAlias;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* @Description 当前币种矿池信息
* @Date 2024/6/13 11:17
* @Author dy
*/
@Data
public class MinerDataInsertDBDto implements Serializable {
/** id */
private long id;
/** 时间 */
private String date;
/** 挖矿账号 */
private String user;
/** 矿工名 */
private String miner;
/** 1小时平均算力 */
private double mhs;
/** 24小时平均算力 */
private double mhs24h;
///** 申请次数?通过次数? */
//private int accepts;
//
///** 被拒次数 */
//private int rejects;
//
///** 拒绝率 */
////private int rejects_ratio;
//@JsonAlias("rejects_ratio")
//private double rejectsRatio;
/** 最后一次提交的时间 */
@JsonAlias("last_submit")
private String lastSubmit;
///** */
//private double duration;
/** 是否在线 */
//private String online;
private String state;
}

View File

@@ -0,0 +1,37 @@
package com.m2pool.pool.dto;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* @Description 矿工信息总览表对象
* @Date 2024/6/13 11:17
* @Author dy
*/
@Data
public class MinerDto implements Serializable {
private String id;
/** 矿工名 */
private String miner;
/** 1小时平均算力 */
private double rate;
/** 24小时平均算力 */
private double dailyRate;
/** 拒绝率 */
private double reject;
/** 最后提交时间 */
private Date submit;
private String status;
private long offline = 0;
}

View File

@@ -0,0 +1,50 @@
package com.m2pool.pool.dto;
import com.fasterxml.jackson.annotation.JsonAlias;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
* @Description 矿工信息总览表对象
* @Date 2024/6/13 11:17
* @Author dy
*/
@Data
public class MinerListDto implements Serializable {
/** 总矿机数 */
private int all;
/** 在线矿机数 */
private int online;
/** 离线矿机数 */
private int offline;
/** 矿工名 */
private String miner;
/** 1小时平均算力 */
private double rate;
/** 24小时平均算力 */
private double dailyRate;
/** 拒绝率 */
private double reject;
private Date submit;
/** 总条数 */
private int total;
/** 总页数 */
private int page;
/** 最后一次提交的时间 */
private List<MinerDto> rows;
}

View File

@@ -0,0 +1,27 @@
package com.m2pool.pool.dto;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* @Description 矿工信息总览表对象
* @Date 2024/6/13 11:17
* @Author dy
*/
@Data
public class NoticeListDto implements Serializable {
/** 通知邮箱记录表id */
private long id;
/** 通知邮箱 */
private String email;
/** 币种/矿池 */
private String remark;
}

View File

@@ -0,0 +1,28 @@
package com.m2pool.pool.dto;
import lombok.Data;
import java.io.Serializable;
/**
* @Description 矿工信息总览表对象
* @Date 2024/6/13 11:17
* @Author dy
*/
@Data
public class NoticeMinerCoinListDto implements Serializable {
///** 通知邮箱记录表id */
//private long id;
/** 通知邮箱 */
private String email;
/** 挖矿账户 */
private String miner;
///** 币种 */
//private String coin;
}

View File

@@ -0,0 +1,25 @@
package com.m2pool.pool.dto;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* @Description 文件
* @Date 2024/6/14 15:57
* @Author dy
*/
@Data
public class OfflineUserMinerDto implements Serializable {
private Date date;
private String user;
private String miners;
private int offline;
}

View File

@@ -0,0 +1,34 @@
package com.m2pool.pool.dto;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* @Description 支出表实体类
* @Date 2024/6/13 11:17
* @Author dy
*/
@Data
public class OutcomeDto implements Serializable {
/** 时间 */
private Date date;
/** 提现地址 */
private String address;
/** 币种/矿池 */
private String coin;
/** 收益 */
private double amount;
/** 交易id */
private String txid;
private int status = 1;
}

Some files were not shown because too many files have changed in this diff Show More