项目上传

This commit is contained in:
2025-03-20 22:05:58 +08:00
commit e7bab0d002
278 changed files with 14221 additions and 0 deletions

7
.gitignore vendored Normal file
View File

@@ -0,0 +1,7 @@
.idea
admin/target
basics/target
challenge/target
common/target
logs
mainland/target

150
admin/pom.xml Normal file
View File

@@ -0,0 +1,150 @@
<?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>mine_clearance</artifactId>
<groupId>com.lightyears.mine_clearance</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<name>admin</name>
<artifactId>admin</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- druid数据源驱动 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<!--json-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
</dependency>
<!-- 由于SpringBoot 2.x中默认并没有使用Redis连接池所以需要添加commons-pool2的依赖 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<!--redis依赖配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 模板引擎 -->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</dependency>
<!--swagger2整合-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<!-- hutool 一个常用工具集 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
</dependency>
<dependency>
<groupId>com.lightyears.mine_clearance</groupId>
<artifactId>common</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>admin</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>utf-8</encoding>
</configuration>
</plugin>
<!--打包一个JAR-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.lightyears.admin.AdminApp</mainClass>
<includeSystemScope>true</includeSystemScope>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<testFailureIgnore>true</testFailureIgnore>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,19 @@
package com.lightyears.admin;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import java.util.TimeZone;
@EnableScheduling
@SpringBootApplication
@EnableTransactionManagement
public class AdminApp {
public static void main(String[] args) {
// 设置时区
TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));
SpringApplication.run(AdminApp.class, args);
}
}

View File

@@ -0,0 +1,86 @@
package com.lightyears.admin.configuration;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
// 开启redis缓存功能
@EnableCaching
// 备注这是一个配置类
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
/**
* 配置redis模板文件
* @param redisConnectionFactory
* @return
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisSerializer<Object> serializer = redisSerializer();
// 创建RedisTemplate<String, Object>对象
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
// 配置连接工厂
redisTemplate.setConnectionFactory(redisConnectionFactory);
// redis key 序列化方式使用stringSerial
redisTemplate.setKeySerializer(new StringRedisSerializer());
// redis value 序列化方式使用jackson
redisTemplate.setValueSerializer(serializer);
// redis hash key 序列化方式使用stringSerial
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
// redis hash value 序列化方式使用jackson
redisTemplate.setHashValueSerializer(serializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
/**
* 配置序列化
* @return
*/
@Bean
public RedisSerializer<Object> redisSerializer() {
// 定义Jackson2JsonRedisSerializer序列化对象
Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
// 指定要序列化的域field,get和set,以及修饰符范围ANY是都有包括private和public
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// 指定序列化输入的类型类必须是非final修饰的final修饰的类比如String,Integer等会报异常
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
serializer.setObjectMapper(objectMapper);
return serializer;
}
/**
* 自定义缓存管理器
* @param redisConnectionFactory
* @return
*/
@Bean
public RedisCacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory);
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration
.defaultCacheConfig()
// 设置value 为自动转json的Object
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer()))
// 缓存有效期为一天
.entryTtl(Duration.ofDays(1));
return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration);
}
}

View File

@@ -0,0 +1,24 @@
package com.lightyears.admin.configuration;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import java.util.TimeZone;
@Configuration
public class ScheduledConfig {
@Bean
public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
threadPoolTaskScheduler.setPoolSize(3);
threadPoolTaskScheduler.setRemoveOnCancelPolicy(true);
return threadPoolTaskScheduler;
}
@Bean
public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization() {
return jacksonObjectMapperBuilder ->
jacksonObjectMapperBuilder.timeZone(TimeZone.getTimeZone("GMT+8"));
}
}

View File

@@ -0,0 +1,54 @@
package com.lightyears.admin.controller;
import com.lightyears.admin.util.RedisCache;
import com.lightyears.admin.util.StaticUtil;
import com.lightyears.common.domain.entity.Player;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class BaseController {
@Autowired
private RedisCache redisCache;
/**
* 得到request对象
*
* @return
*/
public HttpServletRequest getRequest() {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
.getRequest();
return request;
}
/**
* 得到respones对象
* @return
*/
public HttpServletResponse getResponse() {
HttpServletResponse request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
.getResponse();
return request;
}
/**
* 得到当前登录用户信息
*
* @return
*/
public String getUserInfo() {
// 获取请求头中的token数据
String token = getRequest().getHeader("Tracecode");
if(token == null) {
token = this.getRequest().getParameter("Tracecode");
}
String key = StaticUtil.ONLINE_ADMIN_USER_PUBLIC_KEY.concat(token);
return redisCache.getCacheObject(key).toString();
}
}

View File

@@ -0,0 +1,178 @@
package com.lightyears.admin.controller;
import com.lightyears.admin.dto.*;
import com.lightyears.admin.service.IClearanceLogService;
import com.lightyears.admin.service.ILogService;
import com.lightyears.admin.service.ISystemService;
import com.lightyears.admin.util.ResultUtil;
import com.lightyears.common.domain.dto.Params;
import com.lightyears.common.domain.dto.ResModeBase;
import com.lightyears.common.domain.entity.ListBase;
import com.lightyears.common.domain.entity.Notice;
import com.lightyears.common.domain.enums.MessageEnum;
import io.swagger.annotations.Api;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/sys")
@Api("扫雷 管理端调用接口:")
@RequiredArgsConstructor(onConstructor = @_(@Autowired))
public class SystemController extends BaseController {
private final ISystemService systemService;
private final ILogService logService;
private final IClearanceLogService clearanceLogService;
/**
* 管理端登录 v
* @return
*/
@RequestMapping(value = "/login", method = RequestMethod.POST)
public ResModeBase login(@RequestBody UserLoginParams params) {
return systemService.login(params.getUserName(), params.getPassword());
}
/**
* 获取登录信息 v
* @return
*/
@PostMapping("/getInfo")
public ResModeBase getInfo(){
return ResultUtil.success(this.getUserInfo());
}
/**
* 用户列表 v
* @param params
* @return
*/
@PostMapping("/queryUserList")
public ResModeBase queryUserList(@RequestBody Params<UserListParams> params){
return systemService.userList(params);
}
/**
* 设置用户启用禁用 v
* @param params
* @return
*/
@PostMapping("/setPlayerStatus")
public ResModeBase setPlayerStatus(@RequestBody UserStatusParams params){
systemService.updateUserStatus(params);
return ResultUtil.success();
}
/**
* 发布公告 v
* @param notice
* @return
*/
@RequestMapping(value = "/publishNotice", method = RequestMethod.POST)
public ResModeBase publishNotice(@RequestBody Notice notice) {
systemService.publishNotice(notice);
return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage());
}
/**
* 刷新排行榜和雷塔缓存 v
* @return
*/
@RequestMapping(value = "/refreshRankCache", method = RequestMethod.GET)
public ResModeBase refreshRankCache() {
// 排行榜缓存
logService.cacheRankList(null);
// 雷神之塔缓存
clearanceLogService.cachePlayerClearanceRank();
return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage());
}
/**
* 删除玩家 v
* @return
*/
@RequestMapping(value = "/cancellationAccount", method = RequestMethod.POST)
public ResModeBase cancellationAccount(@RequestParam(value = "playerId") Integer playerId) {
systemService.cancellationAccount(playerId);
return ResultUtil.success();
}
/**
* 删除玩家排行榜数据 v
* @return
*/
@RequestMapping(value = "/deleteCacheByRankUserId", method = RequestMethod.POST)
public ResModeBase deleteCacheByRankUserId(@RequestBody DeletePlayerRankParams params) {
systemService.deleteCacheByRankUserId(params.getLevel(), params.getPlayerId());
return ResultUtil.success();
}
/**
* 加/减用户资产 v
* @param params
* @return
*/
@RequestMapping(value = "/setPlayerAssets", method = RequestMethod.POST)
public ResModeBase setPlayerAssets(@RequestBody PlayerAssetsParams params) {
systemService.setPlayerAssets(params);
return ResultUtil.success();
}
/**
* 查询挑战榜模板列表
* @param params
* @return
*/
@RequestMapping(value = "/challengeBaseList", method = RequestMethod.POST)
public ResModeBase challengeBaseList(@RequestBody Params<ListBaseListParams> params) {
return systemService.challengeBaseList(params);
}
/**
* 添加挑战模板
* @param params
* @return
*/
@RequestMapping(value = "/addBase", method = RequestMethod.POST)
public ResModeBase addBase(@RequestBody ListBase params) {
return systemService.addBase(params);
}
/**
* 删除模板
* @param id 模板id
* @return
*/
@RequestMapping(value = "/deleteBase", method = RequestMethod.GET)
public ResModeBase deleteBase(@RequestParam("id") Integer id) {
return systemService.deleteBase(id);
}
/**
* 获取实例list
* @return
*/
@RequestMapping(value = "/challengeInstanceList", method = RequestMethod.POST)
public ResModeBase challengeInstanceList() {
return systemService.challengeInstanceList();
}
/**
* 清空指定挑战榜排名的玩家数据
* @return
*/
@RequestMapping(value = "/removeChallengeRankInfo", method = RequestMethod.POST)
public ResModeBase removeChallengeRankInfo(@RequestBody RemoveChallengeRankParams params) {
systemService.removeChallengeRankInfo(params.getInstanceId(), params.getRankNum());
return ResultUtil.success();
}
/**
* 登出 v
* @return
*/
@GetMapping("/logout")
public ResModeBase logout(){
return systemService.logout();
}
}

View File

@@ -0,0 +1,11 @@
package com.lightyears.admin.dto;
import lombok.Data;
@Data
public class DeletePlayerRankParams {
// 用户id
private Integer playerId;
// 游戏难度1 - 普通 2 困难 3 大师 4 超凡
private Integer level;
}

View File

@@ -0,0 +1,9 @@
package com.lightyears.admin.dto;
import lombok.Data;
@Data
public class ListBaseListParams {
// 关键字
private String keyword;
}

View File

@@ -0,0 +1,15 @@
package com.lightyears.admin.dto;
import lombok.Data;
@Data
public class PlayerAssetsParams {
// 用户id
private Integer userId;
// 操作数量
private Integer gold;
// 资产类型
private Integer type;
// 备注
private String remark;
}

View File

@@ -0,0 +1,11 @@
package com.lightyears.admin.dto;
import lombok.Data;
@Data
public class RemoveChallengeRankParams {
// 实例榜单id
private Integer instanceId;
// 排名
private Integer rankNum;
}

View File

@@ -0,0 +1,9 @@
package com.lightyears.admin.dto;
import lombok.Data;
@Data
public class UserListParams {
// 关键字
private String keyword;
}

View File

@@ -0,0 +1,9 @@
package com.lightyears.admin.dto;
import lombok.Data;
@Data
public class UserLoginParams {
private String userName;
private String password;
}

View File

@@ -0,0 +1,11 @@
package com.lightyears.admin.dto;
import lombok.Data;
@Data
public class UserStatusParams {
// 玩家id
private Integer playerId;
// 状态1.启用 0.禁用)
private Integer status;
}

View File

@@ -0,0 +1,18 @@
package com.lightyears.admin.exception;
import com.lightyears.common.domain.enums.MessageEnum;
/**
* @author fengshuonan
* @Description 业务异常的封装
*/
public class BussinessException extends GlobalException {
public BussinessException(MessageEnum messageEnum) {
super(messageEnum.getCode(), messageEnum.getMessage());
}
public BussinessException(Integer code, String message) {
super(code, message);
}
}

View File

@@ -0,0 +1,46 @@
package com.lightyears.admin.exception;
import com.lightyears.common.domain.enums.MessageEnum;
/***
* 全局异常捕捉 统一返回 model
* */
public class GlobalException extends RuntimeException {
//友好提示的code码
protected int friendlyCode;
//友好提示
protected String friendlyMsg;
protected GlobalException(int friendlyCode, String friendlyMsg) {
this.setValues(friendlyCode, friendlyMsg);
}
public GlobalException(MessageEnum messageEnum) {
this.setValues(messageEnum.getCode(), messageEnum.getMessage());
}
private void setValues(int friendlyCode, String friendlyMsg) {
this.friendlyCode = friendlyCode;
this.friendlyMsg = friendlyMsg;
}
public int getCode() {
return friendlyCode;
}
public void setCode(int code) {
this.friendlyCode = code;
}
public String getMessage() {
return friendlyMsg;
}
public void setMessage(String message) {
this.friendlyMsg = message;
}
}

View File

@@ -0,0 +1,26 @@
package com.lightyears.admin.exception;
import com.lightyears.admin.util.ResultUtil;
import com.lightyears.common.domain.dto.ResModeBase;
import com.lightyears.common.domain.enums.MessageEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
@Slf4j
@ControllerAdvice
public class MyExceptionHandle {
@ExceptionHandler(value = Exception.class)
@ResponseBody
public ResModeBase handle(Exception e) {
if (e instanceof GlobalException) {
GlobalException myException = (GlobalException) e;
return ResultUtil.result(myException.getCode(), myException.getMessage());
} else {
log.error("系统异常", e);
return ResultUtil.result(MessageEnum.UNKNOWN_ERROR.getCode(), MessageEnum.UNKNOWN_ERROR.getMessage());
}
}
}

View File

@@ -0,0 +1,84 @@
package com.lightyears.admin.filter;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.util.StringUtil;
import com.lightyears.admin.util.RedisCache;
import com.lightyears.admin.util.StaticUtil;
import com.lightyears.common.domain.entity.Player;
import com.lightyears.common.domain.enums.MessageEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.web.context.support.WebApplicationContextUtils;
import javax.annotation.Resource;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@Slf4j
@Component
public class TokenFilter implements Filter{
@Resource
private RedisCache redisCache;
@Override
public void init(FilterConfig filterConfig) {
ServletContext servletContext = filterConfig.getServletContext();
ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(servletContext);
redisCache = (RedisCache) ctx.getBean("redisCache");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
String tracecode = request.getHeader("Tracecode");
Boolean flag = request.getRequestURI().indexOf("/login")<0;
// 登录放行
if(flag){
// 判断身份码, 是否已登录
if((StringUtil.isEmpty(tracecode) || !redisCache.hasKey(StaticUtil.ONLINE_ADMIN_USER_PUBLIC_KEY.concat(tracecode)))){
/**
* 不是登录 || 身份码不存在 || 未在登录列表 就拒绝访问
*/
this.authcReq(response, MessageEnum.SYSTEM_ERROR.getCode(), MessageEnum.SYSTEM_ERROR.getMessage());
return;
}
// 重置身份认证过期时间
redisCache.expire(StaticUtil.ONLINE_ADMIN_USER_PUBLIC_KEY.concat(tracecode), 1, TimeUnit.HOURS);
}
//执行
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
}
/**
* 响应访问
* @param response
* @throws IOException
*/
private void authcReq(HttpServletResponse response, Integer code, String msg) throws IOException {
// response.setHeader("Access-Control-Allow-Origin", "*");
response.setStatus(HttpServletResponse.SC_OK);
response.setContentType("application/json; charset=utf-8");
PrintWriter writer = response.getWriter();
Map<String, Object> map = new HashMap<>();
map.put("code", code);
map.put("msg", msg);
writer.print(JSONObject.toJSON(map));
}
}

View File

@@ -0,0 +1,32 @@
package com.lightyears.admin.init;
import com.lightyears.admin.util.RedisCache;
import com.lightyears.admin.util.StaticUtil;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
;
/**
* 挑战数据初始化
*/
@Component
public class AdminInit {
@Resource
private RedisCache redisCache;
@PostConstruct
public void init() {
// 管理端密码
redisCache.setCacheObject(StaticUtil.ADMIN_PASSWORD, "admin1476346288ALsk");
}
@PreDestroy
public void destroy() {
// 写入持久层
}
}

View File

@@ -0,0 +1,18 @@
package com.lightyears.admin.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.lightyears.common.domain.entity.AssertLog;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* Mapper 接口
* </p>
*
* @author hellor
* @since 2022-03-16
*/
@Mapper
public interface AssertLogMapper extends BaseMapper<AssertLog> {
}

View File

@@ -0,0 +1,26 @@
package com.lightyears.admin.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.lightyears.common.domain.dto.ClearanceRankDto;
import com.lightyears.common.domain.entity.ClearanceLog;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* <p>
* Mapper 接口
* </p>
*
* @author hellor
* @since 2022-06-02
*/
@Mapper
public interface ClearanceLogMapper extends BaseMapper<ClearanceLog> {
/**
* 获取玩家最高闯关 关卡数据
* @return
*/
List<ClearanceRankDto> getPlayerClearanceLogs(@Param("userId")Integer userId);
}

View File

@@ -0,0 +1,17 @@
package com.lightyears.admin.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.lightyears.common.domain.entity.ListBase;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* Mapper 接口
* </p>
*
* @author hellor
* @since 2022-03-16
*/
@Mapper
public interface ListBaseMapper extends BaseMapper<ListBase> {
}

View File

@@ -0,0 +1,39 @@
package com.lightyears.admin.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.lightyears.common.domain.dto.ListInstanceDto;
import com.lightyears.common.domain.entity.ListInstance;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
;
/**
* <p>
* Mapper 接口
* </p>
*
* @author hellor
* @since 2022-03-16
*/
@Mapper
public interface ListInstanceMapper extends BaseMapper<ListInstance> {
/**
* 奖池增加
* @param instanceId 榜实例id
* @param awardSize 奖池要增加的数
* @param assetsType 货币类型
* @return
*/
int updateInstanceAwardSize(@Param("instanceId") Integer instanceId,@Param("awardSize") Integer awardSize,@Param("assetsType") Integer assetsType);
/**
* 获取榜单列表
*
* @return
*/
List<ListInstanceDto> getListInstances();
}

View File

@@ -0,0 +1,25 @@
package com.lightyears.admin.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.lightyears.common.domain.dto.ListRankDto;
import com.lightyears.common.domain.entity.ListRank;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* <p>
* Mapper 接口
* </p>
*
* @author hellor
* @since 2022-03-16
*/
@Mapper
public interface ListRankMapper extends BaseMapper<ListRank> {
int initRank(@Param("instanceId") Integer instanceId, @Param("rankNum") Integer rankNum);
List<ListRankDto> getRankList(@Param("instanceId") Integer instanceId, @Param("playerId") Integer playerId, @Param("state") Integer state);
List<ListRankDto> getNewRankList (@Param("instanceId") Integer instanceId, @Param("playerId") Integer playerId);
ListRankDto getRankByInsRank(@Param("instanceId") Integer instanceId,@Param("rank") Integer rank);
}

View File

@@ -0,0 +1,29 @@
package com.lightyears.admin.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.lightyears.common.domain.dto.OrdinaryRankDto;
import com.lightyears.common.domain.entity.Log;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
* <p>
* 游戏 完成记录 表 游戏难度1 - 普通 2 困难 3 大师 Mapper 接口
* </p>
*
* @author hellor
* @since 2022-03-09
*/
@Mapper
public interface LogMapper extends BaseMapper<Log> {
List<OrdinaryRankDto> paging(@Param("level") Integer level, @Param("userId")Integer userId);
//综合查询 三种难度加起来 获取排名
List<OrdinaryRankDto> syntheticalPaging();
// 查询用户综合排名
Map getComprehensiveRankByUserId(@Param("userId") Integer userId);
//根据User_id和 level 查询排名
Map getRankByLevelUserId(@Param("level")int level, @Param("userId") Integer userId);
}

View File

@@ -0,0 +1,23 @@
package com.lightyears.admin.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.lightyears.common.domain.dto.NoticeDto;
import com.lightyears.common.domain.entity.Notice;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* <p>
* Mapper 接口
* </p>
*
* @author hellor
* @since 2022-03-18
*/
@Mapper
public interface NoticeMapper extends BaseMapper<Notice> {
List<NoticeDto> getList(@Param("type") Integer type, @Param("playerId") Integer playerId);
String getContent(@Param("id")Integer id);
}

View File

@@ -0,0 +1,33 @@
package com.lightyears.admin.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.lightyears.common.domain.dto.SimplePlayerAssert;
import com.lightyears.common.domain.entity.PlayerAssets;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* <p>
* Mapper 接口
* </p>
*
* @author hellor
* @since 2022-03-16
*/
@Mapper
public interface PlayerAssetsMapper extends BaseMapper<PlayerAssets> {
// 货币存放服务器
int addGold(@Param("id") int id, @Param("gold") int gold, @Param("version") Long version);
// 从服务器取出货币
int reduceGold(@Param("id") int id,@Param("gold") int gold, @Param("version") Long version);
/**
* 获取用户资产
* @param playerId
* @return
*/
List<SimplePlayerAssert> getPlayerAssets(@Param("playerId") int playerId);
}

View File

@@ -0,0 +1,26 @@
package com.lightyears.admin.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.lightyears.admin.dto.UserListParams;
import com.lightyears.common.domain.entity.Player;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* <p>
* 扫雷玩家表 Mapper 接口
* </p>
*
* @author hellor
* @since 2022-03-09
*/
@Mapper
public interface PlayerMapper extends BaseMapper<Player> {
/**
* 玩家列表
* @param params
* @return
*/
List<Player> getPlayerList(UserListParams params);
}

View File

@@ -0,0 +1,18 @@
package com.lightyears.admin.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.lightyears.common.domain.entity.Record;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* 游戏存档 Mapper 接口
* </p>x
*
* @author hellor
* @since 2022-03-09
*/
@Mapper
public interface RecordMapper extends BaseMapper<Record> {
}

View File

@@ -0,0 +1,26 @@
package com.lightyears.admin.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.lightyears.common.domain.dto.PlayerClearanceLogInfoDto;
import com.lightyears.common.domain.entity.ClearanceLog;
/**
* <p>
* 服务类
* </p>
*
* @author hellor
* @since 2022-06-02
*/
public interface IClearanceLogService extends IService<ClearanceLog> {
/**
* 缓存用户闯关记录
*/
void cachePlayerClearanceRank();
/**
* 删除用户闯关记录缓存
*/
void deletCacheByPlayerId(Integer playerId);
}

View File

@@ -0,0 +1,16 @@
package com.lightyears.admin.service;
import com.lightyears.common.domain.dto.ResModeBase;
import com.lightyears.common.domain.entity.Player;
public interface IGameSystemService {
ResModeBase pushGoldImpl(Integer userId, int gold, int type, String remark);
ResModeBase pushGold(Integer userId, int gold, int type, String remark);
ResModeBase pullGoldImpl(Integer userId, int gold, int type, String remark);
ResModeBase pullGold(Integer userId, int gold, int type, String remark);
}

View File

@@ -0,0 +1,42 @@
package com.lightyears.admin.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.lightyears.common.domain.dto.OrdinaryRankDto;
import com.lightyears.common.domain.entity.Log;
import java.util.List;
/**
* <p>
* 游戏 完成记录 表 游戏难度1 - 普通 2 困难 3 大师 服务类
* </p>
*
* @author hellor
* @since 2022-03-09
*/
public interface ILogService extends IService<Log> {
/**
* 查询排行榜
* @param level 游戏难度1 - 普通 2 困难 3 大师
* @return
*/
List<OrdinaryRankDto> getRankList(Integer level);
/**
* 排行榜数据写入缓存
*/
void cacheRankList(Integer level);
/**
* 删除缓存
* @param userId
*/
void deleteCacheByUserId(Integer userId);
/**
* 删除用户指定排行榜数据
* @param level
* @param userId
*/
void deleteCacheByRankUserId(Integer level, Integer userId);
}

View File

@@ -0,0 +1,20 @@
package com.lightyears.admin.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.lightyears.common.domain.dto.ResModeBase;
import com.lightyears.common.domain.entity.Notice;
/**
* <p>
* 服务类
* </p>
*
* @author hellor
* @since 2022-03-18
*/
public interface INoticeService extends IService<Notice> {
ResModeBase getList(Integer playerId);
ResModeBase getContent(Integer id);
void deleteNoticeForTask();
}

View File

@@ -0,0 +1,38 @@
package com.lightyears.admin.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.lightyears.common.domain.dto.SimplePlayerAssert;
import com.lightyears.common.domain.entity.PlayerAssets;
import java.util.List;
/**
* <p>
* 服务类
* </p>
*
* @author hellor
* @since 2022-03-16
*/
public interface IPlayerAssetsService extends IService<PlayerAssets> {
/**
* 添加金币
* @param id id
* @param gold 增加后的金币
*/
Integer addGold(int id, int gold);
/**
* 扣除金币
* @param id id
* @param gold 需要扣减的金币
*/
Integer reduceGold(int id, int gold);
/**
* 获取指定用户的资产
* @param playerId 用户id
* @return
*/
List<SimplePlayerAssert> getPlayerAssets(int playerId);
}

View File

@@ -0,0 +1,15 @@
package com.lightyears.admin.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.lightyears.common.domain.entity.Player;
/**
* <p>
* 扫雷玩家表 服务类
* </p>
*
* @author hellor
* @since 2022-03-09
*/
public interface IPlayerService extends IService<Player> {
}

View File

@@ -0,0 +1,16 @@
package com.lightyears.admin.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.lightyears.common.domain.entity.Record;
/**
* <p>
* 游戏存档 服务类
* </p>
*
* @author hellor
* @since 2022-03-09
*/
public interface IRecordService extends IService<Record> {
}

View File

@@ -0,0 +1,98 @@
package com.lightyears.admin.service;
import com.lightyears.admin.dto.ListBaseListParams;
import com.lightyears.admin.dto.PlayerAssetsParams;
import com.lightyears.admin.dto.UserListParams;
import com.lightyears.admin.dto.UserStatusParams;
import com.lightyears.common.domain.dto.Params;
import com.lightyears.common.domain.dto.ResModeBase;
import com.lightyears.common.domain.entity.ListBase;
import com.lightyears.common.domain.entity.Notice;
public interface ISystemService {
/**
* 管理端登录
* @param userName
* @param password
* @return
*/
ResModeBase login(String userName, String password);
/**
* 注销登录
* @return
*/
ResModeBase logout();
/**
* 用户列表
* @param params
* @return
*/
ResModeBase userList(Params<UserListParams> params);
/**
* 发布公告
* @param notice
* @return
*/
void publishNotice(Notice notice);
/**
* 删除玩家
* @param userId 玩家id
*/
void cancellationAccount(Integer userId);
/**
* 删除玩家排行数据
* @param level
* @param userId
*/
void deleteCacheByRankUserId(Integer level, Integer userId);
/**
* 修改用户状态
* @param params
*/
void updateUserStatus(UserStatusParams params);
/**
* 加/减用户资产
* @param params
*/
void setPlayerAssets(PlayerAssetsParams params);
/**
* 查询挑战榜模板列表
* @param params
* @return
*/
ResModeBase challengeBaseList(Params<ListBaseListParams> params);
/**
* 添加挑战模板
* @param base
* @return
*/
ResModeBase addBase(ListBase base);
/**
* 删除未实例化的模板
* @param id 模板id
* @return
*/
ResModeBase deleteBase(Integer id);
/**
* 获取实例list
* @return
*/
ResModeBase challengeInstanceList();
/**
* 清空指定挑战榜排名的玩家数据
* @param instanceId 实例榜单id
* @param rankNum 排名
*/
void removeChallengeRankInfo(Integer instanceId, Integer rankNum);
}

View File

@@ -0,0 +1,60 @@
package com.lightyears.admin.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lightyears.admin.exception.BussinessException;
import com.lightyears.admin.mapper.ClearanceLogMapper;
import com.lightyears.admin.service.IClearanceLogService;
import com.lightyears.admin.util.RedisCache;
import com.lightyears.admin.util.StaticUtil;
import com.lightyears.common.domain.dto.ClearanceRankDto;
import com.lightyears.common.domain.dto.PlayerClearanceLogInfoDto;
import com.lightyears.common.domain.entity.ClearanceLog;
import com.lightyears.common.domain.enums.MessageEnum;
import org.springframework.data.redis.core.BoundZSetOperations;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Set;
/**
* <p>
* 服务实现类
* </p>
*
* @author hellor
* @since 2022-06-02
*/
@Service
public class ClearanceLogServiceImpl extends ServiceImpl<ClearanceLogMapper, ClearanceLog> implements IClearanceLogService {
@Resource
private RedisCache redisCache;
@Override
public void cachePlayerClearanceRank(){
List<ClearanceRankDto> logs = this.getClearanceLogs();
String key = StaticUtil.CLEARANCE_RANK_LIST;
BoundZSetOperations<String, Integer> operations = redisCache.getRedisTemplate().boundZSetOps(key);
redisCache.deleteByPrefix(key);
for (ClearanceRankDto log: logs){
operations.add(log.getPlayerId(), log.getLayersNum());
}
}
@Override
public void deletCacheByPlayerId(Integer playerId){
String key = StaticUtil.CLEARANCE_RANK_LIST;
BoundZSetOperations<String, Integer> operations = redisCache.getRedisTemplate().boundZSetOps(key);
operations.remove(playerId);
}
public List<ClearanceRankDto> getClearanceLogs(){
List<ClearanceRankDto> logs = baseMapper.getPlayerClearanceLogs(null);
return logs;
}
}

View File

@@ -0,0 +1,107 @@
package com.lightyears.admin.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageInfo;
import com.github.pagehelper.util.StringUtil;
import com.google.common.collect.Interner;
import com.google.common.collect.Interners;
import com.lightyears.admin.mapper.*;
import com.lightyears.admin.exception.BussinessException;
import com.lightyears.admin.service.IClearanceLogService;
import com.lightyears.admin.service.IGameSystemService;
import com.lightyears.admin.service.ILogService;
import com.lightyears.admin.service.IPlayerAssetsService;
import com.lightyears.admin.util.RedisCache;
import com.lightyears.admin.util.ResultUtil;
import com.lightyears.admin.util.StaticUtil;
import com.lightyears.common.domain.dto.OrdinaryRankDto;
import com.lightyears.common.domain.dto.ResModeBase;
import com.lightyears.common.domain.dto.SimplePlayerAssert;
import com.lightyears.common.domain.entity.*;
import com.lightyears.common.domain.enums.MessageEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.BoundZSetOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;
@Slf4j
@Service("gameSystemServiceImpl")
public class GameSystemServiceImpl implements IGameSystemService {
@Resource
private IPlayerAssetsService playerAssetsService;
@Resource
private AssertLogMapper assertLogMapper;
@Resource
private IGameSystemService gameSystemService;
Interner<String> pool = Interners.newWeakInterner();
private static final int AssetLimit = 999999;
@Override
public ResModeBase pushGoldImpl(Integer userId, int gold, int type, String remark){
synchronized (pool.intern("gold-".concat(userId.toString()))) {
return gameSystemService.pushGold(userId, gold, type, remark);
}
}
@Override
@Transactional
public ResModeBase pushGold(Integer userId, int gold, int type, String remark) {
//1. 查询金额, 设置资产上限
PlayerAssets playerAssets = playerAssetsService.getOne(new QueryWrapper<PlayerAssets>().eq("player_id", userId).eq("type", type).last("limit 1"));
Integer playerAssetsNumber = playerAssets == null? 0 : playerAssets.getNumber();
int nowGold = Math.min(playerAssetsNumber +gold , AssetLimit);
// 2.写入改变数量
if (ObjectUtils.isEmpty(playerAssets)) {
playerAssetsService.save(PlayerAssets.builder().playerId(userId).type(type).number(nowGold).version(0L).build());
} else {
playerAssetsService.addGold(playerAssets.getId(), nowGold - playerAssetsNumber);
}
//3 写入变化记录
assertLogMapper.insert(AssertLog.builder().playerId(userId).createDate(new Date()).assertChangeNum(nowGold - playerAssetsNumber).assertType(type).remark(remark).build());
return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage(), nowGold);
}
@Override
public ResModeBase pullGoldImpl(Integer userId, int gold, int type, String remark){
synchronized (pool.intern("gold-".concat(userId.toString()))) {
return gameSystemService.pullGold(userId, gold, type, remark);
}
}
@Override
@Transactional
public ResModeBase pullGold(Integer userId, int gold, int type, String remark) {
//1 查询金额
PlayerAssets playerAssets = playerAssetsService.getOne(new QueryWrapper<PlayerAssets>().eq("player_id", userId).eq("type", type).last("limit 1"));
Integer num = 0;
// 不存在用户的钱包数据则新增初始化钱包数据
if(ObjectUtils.isEmpty(playerAssets)){
playerAssets = PlayerAssets.builder().playerId(userId).type(0).number(0).version(0L).build();
playerAssetsService.save(playerAssets);
return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage(), 0);
}
if (playerAssets.getNumber() < gold) {
return ResultUtil.result(MessageEnum.GAME_GOLD_PULL_MAX_ERROR.getCode(), String.format(MessageEnum.GAME_GOLD_PULL_MAX_ERROR.getMessage(), playerAssets.getNumber()));
}
//2 取出金币
num = playerAssetsService.reduceGold(playerAssets.getId(), gold);
if(num == -999){
return ResultUtil.result(MessageEnum.GAME_GOLD_PULL_MAX_ERROR.getCode(), String.format(MessageEnum.GAME_GOLD_PULL_MAX_ERROR.getMessage(), playerAssets.getNumber()));
}
//3 写入变化记录
assertLogMapper.insert(AssertLog.builder().playerId(userId).createDate(new Date()).assertChangeNum(-gold).assertType(type).remark(remark).build());
return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage(), num);
}
}

View File

@@ -0,0 +1,101 @@
package com.lightyears.admin.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lightyears.admin.mapper.LogMapper;
import com.lightyears.admin.service.ILogService;
import com.lightyears.admin.util.RedisCache;
import com.lightyears.admin.util.StaticUtil;
import com.lightyears.common.domain.dto.OrdinaryRankDto;
import com.lightyears.common.domain.entity.Log;
import org.springframework.data.redis.core.BoundZSetOperations;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
/**
* <p>
* 游戏 完成记录 表 游戏难度1 - 普通 2 困难 3 大师 服务实现类
* </p>
*
* @author hellor
* @since 2022-03-09
*/
@Service
public class LogServiceImpl extends ServiceImpl<LogMapper, Log> implements ILogService {
@Resource
private RedisCache redisCache;
@Override
public List<OrdinaryRankDto> getRankList(Integer level){
List<OrdinaryRankDto> reqData = new ArrayList<>();
if (level == -1) {//查询综合
reqData = baseMapper.syntheticalPaging();
} else {
reqData = baseMapper.paging(level, -1);
}
return reqData;
}
@Override
public void deleteCacheByUserId(Integer userId){
deleteCacheByRankUserId(0, userId);
deleteCacheByRankUserId(1, userId);
deleteCacheByRankUserId(2, userId);
deleteCacheByRankUserId(3, userId);
deleteCacheByRankUserId(4, userId);
}
@Override
public void cacheRankList(Integer level){
if(level == null){
// -1 - 综合
List<OrdinaryRankDto> zh = getRankList(-1);
cacheRankListItem(zh, 0);
// 1 - 普通
List<OrdinaryRankDto> zh1 = getRankList(1);
cacheRankListItem(zh1, 1);
// 2 困难
List<OrdinaryRankDto> zh2 = getRankList(2);
cacheRankListItem(zh2, 2);
// 3 大师
List<OrdinaryRankDto> zh3 = getRankList(3);
cacheRankListItem(zh3, 3);
// 4 超凡
List<OrdinaryRankDto> zh4 = getRankList(4);
cacheRankListItem(zh4, 4);
} else if(level == -1) { // 刷新综合榜数据
// -1 - 综合
List<OrdinaryRankDto> zh = getRankList(-1);
cacheRankListItem(zh, 0);
}
}
public void cacheRankListItem(List<OrdinaryRankDto> list, Integer level){
String key = StaticUtil.RANK_LIST.concat(level.toString());
redisCache.deleteByPrefix(key);
BoundZSetOperations<String, OrdinaryRankDto> operations = redisCache.getRedisTemplate().boundZSetOps(key);
for (OrdinaryRankDto item : list){
operations.add(item, item.getGame_time());
}
}
@Override
public void deleteCacheByRankUserId(Integer level, Integer userId){
String key = StaticUtil.RANK_LIST.concat(level.toString());
BoundZSetOperations<String, OrdinaryRankDto> operations = redisCache.getRedisTemplate().boundZSetOps(key);
if (operations != null && operations.size() > 0){
Set<OrdinaryRankDto> sets = operations.range(0, -1);
if(sets != null && sets.size() > 0){
Optional<OrdinaryRankDto> dto = sets.stream().filter(obj -> obj.getUser_id().equals(userId)).findFirst();
if(dto != null && dto.isPresent()){
operations.remove(dto.get());
}
}
}
}
}

View File

@@ -0,0 +1,77 @@
package com.lightyears.admin.service.impl;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lightyears.admin.mapper.NoticeMapper;
import com.lightyears.admin.service.INoticeService;
import com.lightyears.admin.util.ResultUtil;
import com.lightyears.common.domain.dto.NoticeDto;
import com.lightyears.common.domain.dto.ResModeBase;
import com.lightyears.common.domain.entity.Notice;
import com.lightyears.common.domain.enums.MessageEnum;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* <p>
* 服务实现类
* </p>
*
* @author hellor
* @since 2022-03-18
*/
@Service(value = "noticeServiceImpl")
@RequiredArgsConstructor(onConstructor = @_(@Autowired))
public class NoticeServiceImpl extends ServiceImpl<NoticeMapper, Notice> implements INoticeService {
@Override
public ResModeBase getList(Integer playerId){
// List<NoticeDto> results = new ArrayList<>();
List<NoticeDto> systemNotice = this.baseMapper.getList(null, playerId);
// List<NoticeDto> myNotice = this.baseMapper.getList(1, playerId);
// if (!CollectionUtils.isEmpty(systemNotice)){
// results.add(systemNotice.get(0));
// }
// if (!CollectionUtils.isEmpty(myNotice)){
// results.addAll(myNotice);
// }
return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage(), systemNotice);
}
@Override
public ResModeBase getContent(Integer id){
String content = this.baseMapper.getContent(id);
// 设置已读
this.baseMapper.updateById(Notice.builder().id(id).status(1).build());
return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage(), content);
}
@Override
public void deleteNoticeForTask(){
List<Notice> notices = this.baseMapper.selectList(new LambdaQueryWrapper<Notice>().select(Notice::getId, Notice::getExpirationDay, Notice::getCreateDate).isNotNull(Notice::getExpirationDay));
if (CollectionUtils.isEmpty(notices))
return;
Date now = new Date();
List<Integer> ids = new ArrayList<>();
notices.forEach(notice -> {
Date date = DateUtil.offsetDay(notice.getCreateDate(), notice.getExpirationDay());
if(DateUtil.compare(now, date) > -1){
ids.add(notice.getId());
}
});
if(ids.size() < 1)
return;
baseMapper.deleteBatchIds(ids);
}
}

View File

@@ -0,0 +1,76 @@
package com.lightyears.admin.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lightyears.admin.exception.BussinessException;
import com.lightyears.admin.mapper.PlayerAssetsMapper;
import com.lightyears.admin.service.IPlayerAssetsService;
import com.lightyears.common.domain.dto.SimplePlayerAssert;
import com.lightyears.common.domain.entity.PlayerAssets;
import com.lightyears.common.domain.enums.MessageEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import java.util.List;
/**
* <p>
* 服务实现类
* </p>
*
* @author hellor
* @since 2022-03-16
*/
@Slf4j
@Service
public class PlayerAssetsServiceImpl extends ServiceImpl<PlayerAssetsMapper, PlayerAssets> implements IPlayerAssetsService {
@Override
public Integer addGold(int id, int gold){
PlayerAssets playerAssets = baseMapper.selectById(id);
if(ObjectUtils.isEmpty(playerAssets)){
log.error("减少金币异常------------没有查到资产信息");
throw new BussinessException(MessageEnum.ERROR.getCode(), "减少金币异常------------没有查到资产信息!");
}
int result = 0;
try{
result = baseMapper.addGold(playerAssets.getId(), gold, playerAssets.getVersion());
}catch (Exception ex){
log.error("写入金币异常", ex);
throw new BussinessException(MessageEnum.ERROR.getCode(), "写入金币异常!");
}
if(result < 1){
this.addGold(id, gold);
}
return gold;
}
@Override
public Integer reduceGold(int id, int gold){
PlayerAssets playerAssets = baseMapper.selectById(id);
if(ObjectUtils.isEmpty(playerAssets)){
log.error("减少金币异常------------没有查到资产信息");
throw new BussinessException(MessageEnum.ERROR.getCode(), "减少金币异常------------没有查到资产信息!");
}
int result = 0;
if(playerAssets.getNumber() < gold){
return -999;
}
try {
result = baseMapper.reduceGold(playerAssets.getId(), gold, playerAssets.getVersion());
} catch (Exception ex){
log.error("写入金币异常", ex);
throw new BussinessException(MessageEnum.ERROR.getCode(), "写入金币异常!");
}
if(result < 1){
this.reduceGold(id, gold);
}
return playerAssets.getNumber() - gold;
}
@Override
public List<SimplePlayerAssert> getPlayerAssets(int playerId){
return baseMapper.getPlayerAssets(playerId);
}
}

View File

@@ -0,0 +1,20 @@
package com.lightyears.admin.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lightyears.admin.mapper.PlayerMapper;
import com.lightyears.admin.service.IPlayerService;
import com.lightyears.common.domain.entity.Player;
import org.springframework.stereotype.Service;
/**
* <p>
* 扫雷玩家表 服务实现类
* </p>
*
* @author hellor
* @since 2022-03-09
*/
@Service
public class PlayerServiceImpl extends ServiceImpl<PlayerMapper, Player> implements IPlayerService {
}

View File

@@ -0,0 +1,20 @@
package com.lightyears.admin.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lightyears.admin.mapper.RecordMapper;
import com.lightyears.admin.service.IRecordService;
import com.lightyears.common.domain.entity.Record;
import org.springframework.stereotype.Service;
/**
* <p>
* 游戏存档 服务实现类
* </p>
*
* @author hellor
* @since 2022-03-09
*/
@Service
public class RecordServiceImpl extends ServiceImpl<RecordMapper, Record> implements IRecordService {
}

View File

@@ -0,0 +1,280 @@
package com.lightyears.admin.service.impl;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.lightyears.admin.dto.ListBaseListParams;
import com.lightyears.admin.dto.PlayerAssetsParams;
import com.lightyears.admin.dto.UserListParams;
import com.lightyears.admin.dto.UserStatusParams;
import com.lightyears.admin.exception.BussinessException;
import com.lightyears.admin.mapper.*;
import com.lightyears.admin.service.*;
import com.lightyears.admin.util.*;
import com.lightyears.common.domain.dto.ListInstanceDto;
import com.lightyears.common.domain.dto.ListRankDto;
import com.lightyears.common.domain.dto.Params;
import com.lightyears.common.domain.dto.ResModeBase;
import com.lightyears.common.domain.entity.*;
import com.lightyears.common.domain.enums.MessageEnum;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@Slf4j
@Service
@RequiredArgsConstructor(onConstructor = @_(@Autowired))
public class SystemServiceImpl implements ISystemService {
private final INoticeService noticeService;
private final IPlayerAssetsService playerAssetsService;
private final PlayerMapper playerMapper;
private final RecordMapper recordMapper;
private final ILogService logService;
private final AssertLogMapper assertLogMapper;
private final NoticeMapper noticeMapper;
private final IClearanceLogService clearanceLogService;
private final RedisCache redisCache;
private final RedisLock redisLock;
private final IGameSystemService gameSystemService;
private final ListBaseMapper listBaseMapper;
private final ListRankMapper listRankMapper;
private final ListInstanceMapper listInstanceMapper;
@Override
public ResModeBase login(String userName, String password){
String checkStr = redisCache.getCacheObject(StaticUtil.ADMIN_PASSWORD).toString();
log.info("登录来了:" + checkStr);
if(checkStr.equals(userName.trim().concat(password.trim()))){
String token = StrUtil.uuid().replace("-", "");
// 写入管理端用户在线缓存
redisCache.setCacheObject(StaticUtil.ONLINE_ADMIN_USER_PUBLIC_KEY.concat(token), "admin", 86400, TimeUnit.SECONDS);
// 返回token
return ResultUtil.success(token);
} else {
return ResultUtil.error("登录失败,账号或密码错误!");
}
}
@Override
public ResModeBase logout(){
redisCache.deleteByPrefix(StaticUtil.ONLINE_ADMIN_USER_PUBLIC_KEY);
return ResultUtil.success();
}
@Override
public ResModeBase userList(Params<UserListParams> params){
PageHelperUtil.setPage(params.getPageNum(), params.getPageSize());
return ResultUtil.success(PageHelperUtil.slicedQueryResult(playerMapper.getPlayerList(params.getRecord())));
}
@Override
@Transactional
public void updateUserStatus(UserStatusParams params){
playerMapper.update(null, new LambdaUpdateWrapper<Player>().set(Player::getStatus, params.getStatus()).eq(Player::getUser_id, params.getPlayerId()));
// 如果是禁用
if(params.getStatus() == 0){
Object token = redisCache.getCacheObject(StaticUtil.ONLINE_USER_TOKEN.concat(params.getPlayerId().toString()));
if(token == null)
return;
redisCache.deleteByPrefix(StaticUtil.ONLINE_USER_TOKEN.concat(params.getPlayerId().toString()));
// 删除缓存
redisCache.deleteByPrefix(StaticUtil.ONLINE_USER_PUBLIC_KEY.concat(token.toString()));
}
}
@Override
public void publishNotice(Notice notice){
//redis锁
String lockKey=StaticUtil.NOTICE_LOCK;
try {
if(redisLock.tryLock(lockKey)){
List<PlayerAssets> players = playerAssetsService.list(new LambdaQueryWrapper<PlayerAssets>().select(PlayerAssets::getPlayerId).eq(PlayerAssets::getType, 0));
if(CollectionUtils.isEmpty(players))
return;
Date now = new Date();
List<Notice> notices = new ArrayList<>();
players.stream().forEach(player -> {
Notice obj = new Notice();
obj.setContent(notice.getContent());
obj.setTitle(notice.getTitle());
obj.setType(0);
obj.setPlayerId(player.getPlayerId());
obj.setStatus(0);
obj.setCreateDate(now);
notices.add(obj);
});
//一个线程处理10000条数据
int count = 10000;
//数据集合大小
int listSize = notices.size();
//开启的线程数
int runSize = (listSize / count) + 1;
//存放每个线程的执行数据
List<Notice> newlist = null;
//创建一个线程池,数量和开启线程的数量一样
//Executors 的写法
// ExecutorService executor = Executors.newFixedThreadPool(runSize);
//ThreadPoolExecutor的写法
ThreadPoolExecutor executor = new ThreadPoolExecutor(runSize, runSize, 1,
TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(3),
new ThreadPoolExecutor.DiscardOldestPolicy());
//创建两个个计数器
CountDownLatch begin = new CountDownLatch(1);
CountDownLatch end = new CountDownLatch(runSize);
try {
//循环创建线程
for (int i = 0; i < runSize; i++) {
//计算每个线程执行的数据
if ((i + 1) == runSize) {
int startIndex = (i * count);
int endIndex = notices.size();
newlist = notices.subList(startIndex, endIndex);
} else {
int startIndex = (i * count);
int endIndex = (i + 1) * count;
newlist = notices.subList(startIndex, endIndex);
}
//线程类
BatchInsertThread mythead = new BatchInsertThread(newlist, begin, end, noticeService);
//这里执行线程的方式是调用线程池里的executor.execute(mythead)方法。
executor.execute(mythead);
}
begin.countDown();
end.await();
} finally {
//执行完关闭线程池
executor.shutdown();
}
}else{
throw new BussinessException(MessageEnum.ERROR.getCode(), "公告正在发布中,请稍后!");
}
}catch (BussinessException e){
throw new BussinessException(MessageEnum.ERROR.getCode(), "公告正在发布中,请稍后!");
}catch (Exception e){
log.error("发布公告异常:", e);
throw new BussinessException(MessageEnum.ERROR.getCode(), "发布公告异常!");
} finally {
redisLock.releaseLock(lockKey);
}
}
@Override
public void deleteCacheByRankUserId(Integer level, Integer userId){
// 删除游戏日志
logService.remove(new LambdaQueryWrapper<Log>().eq(Log::getUser_id, userId).eq(Log::getLevel, level));
// 删除缓存
logService.deleteCacheByRankUserId(level, userId);
}
@Override
@Transactional
public void cancellationAccount(Integer userId) {
// 删除排行榜缓存数据.
logService.deleteCacheByUserId(userId);
// 删除雷神之塔缓存数据
clearanceLogService.deletCacheByPlayerId(userId);
// sl_assert_log 资产日志
assertLogMapper.delete(new UpdateWrapper<AssertLog>().eq("player_id", userId));
// sl_log 游戏日志
logService.remove(new UpdateWrapper<Log>().eq("user_id", userId));
// sl_notic 公告
noticeMapper.delete(new UpdateWrapper<Notice>().eq("player_id", userId));
// sl_player_assets 用户资产
playerAssetsService.remove(new UpdateWrapper<PlayerAssets>().eq("player_id", userId));
// sl_record 用户游戏数据记录
recordMapper.delete(new UpdateWrapper<Record>().eq("user_id", userId));
// sl_player 用户
playerMapper.deleteById(userId);
// sl_clearance_log 通关日志
clearanceLogService.remove(new LambdaQueryWrapper<ClearanceLog>().eq(ClearanceLog::getPlayerId, userId));
}
@Override
public void setPlayerAssets(PlayerAssetsParams params){
if(params.getGold() == 0)
return;
if(params.getGold() > 0){
gameSystemService.pushGold(params.getUserId(),params.getGold(),params.getType(), params.getRemark());
} else {
gameSystemService.pullGold(params.getUserId(),0 - params.getGold(),params.getType(), params.getRemark());
}
}
@Override
public ResModeBase challengeBaseList(Params<ListBaseListParams> params){
PageHelperUtil.setPage(params.getPageNum(), params.getPageSize());
CustomLambdaQueryWrapper<ListBase> queryWrapper = new CustomLambdaQueryWrapper<ListBase>();
if(params.getRecord() != null && !StrUtil.isBlankIfStr(params.getRecord().getKeyword())){
queryWrapper.like(ListBase::getName, params.getRecord().getKeyword());
}
return ResultUtil.success(PageHelperUtil.slicedQueryResult(listBaseMapper.selectList(queryWrapper)));
}
@Override
public ResModeBase addBase(ListBase base){
if(base.getId() == null){
listBaseMapper.insert(base);
} else {
listBaseMapper.updateById(base);
}
return ResultUtil.success();
}
@Override
public ResModeBase deleteBase(Integer id){
Long num = listInstanceMapper.selectCount(new LambdaQueryWrapper<ListInstance>().eq(ListInstance:: getId, id).eq(ListInstance::getStatus, 0));
if(num == 0L){
listBaseMapper.deleteById(id);
}
return ResultUtil.success();
}
@Override
public ResModeBase challengeInstanceList(){
List<ListInstanceDto> list = listInstanceMapper.getListInstances();
return ResultUtil.success(list);
}
@Override
public void removeChallengeRankInfo(Integer instanceId, Integer rankNum){
int i = listRankMapper.initRank(instanceId, rankNum);
// 清空成功 更新缓存
if(i > 0){
ListRankDto rank;
// 获取指定榜单与名次的listRank
Object obj = redisCache.lGetIndex(StaticUtil.CHALLENGE_INSTANCE_RANK_DETAIL.concat(instanceId.toString()), rankNum-1);
if(obj == null){
return;
} else {
String json = JSONObject.toJSONString(obj) ;
rank = JSON.parseObject(json, ListRankDto.class);
}
rank.setChallengeTime(null);
rank.setPlayerId(null);
rank.setPlayerName(null);
rank.setGameData(null);
redisCache.lUpdateIndex(StaticUtil.CHALLENGE_INSTANCE_RANK_DETAIL.concat(rank.getInstanceId().toString()), rank.getRankNum() - 1, rank);
}
}
}

View File

@@ -0,0 +1,46 @@
package com.lightyears.admin.util;
import com.lightyears.admin.service.INoticeService;
import com.lightyears.common.domain.entity.Notice;
import java.util.List;
import java.util.concurrent.CountDownLatch;
public class BatchInsertThread implements Runnable {
public BatchInsertThread() {
}
INoticeService noticeService;
private List<Notice> list;
private CountDownLatch begin;
private CountDownLatch end;
/**
* 方法名: ImportThread
* 方法描述: 创建个构造函数初始化 list,和其他用到的参数
* @throws
*/
public BatchInsertThread(List<Notice> list, CountDownLatch begin, CountDownLatch end,INoticeService noticeService) {
this.list = list;
this.begin = begin;
this.end = end;
this.noticeService=noticeService;
}
@Override
public void run() {
try {
//执行完让线程直接进入等待
noticeService.saveBatch(list);
begin.await();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//这里要注意了,当一个线程执行完 了计数要减一不然这个线程会被一直挂起
//这个方法就是直接把计数器减一的
end.countDown();
}
}
}

View File

@@ -0,0 +1,37 @@
package com.lightyears.admin.util;
import cn.hutool.core.date.DateTime;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Objects;
/**
* 日期转换cron表达式
*/
public class CronUtils {
/***
* 功能描述日期转换cron表达式
* @param dateStr
* @return
*/
public static String formatDateByPattern(String dateStr) {
String formatTimeStr = null;
if (Objects.nonNull(dateStr)) {
LocalDateTime time = LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
formatTimeStr = time.format(DateTimeFormatter.ofPattern("ss mm HH dd MM ?"));
}
return formatTimeStr;
}
/***
* @param dateTime : 时间点
* @return
*/
public static String getCron(DateTime dateTime) {
return formatDateByPattern(dateTime.toString());
}
}

View File

@@ -0,0 +1,149 @@
package com.lightyears.admin.util;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import java.util.Collection;
/**
* .自定义的查询wrapper.
*
* @author yangps
*/
public class CustomLambdaQueryWrapper<T> extends LambdaQueryWrapper<T> {
public CustomLambdaQueryWrapper() {
}
/**
*
*/
private static final long serialVersionUID = 7733721688976788787L;
/**
* .软条件查询, 如果条件无值, 就不加入查询.
*
* @param R
* @param val
* @return
*/
public CustomLambdaQueryWrapper<T> softEq(SFunction<T, ?> R, Object val) {
if (val != null && StringUtils.isNotBlank(val + "")) {
super.eq(R, val);
}
return this;
}
/**
* .软条件查询, 如果条件无值, 就不加入查询.
*
* @param R
* @param val
* @return
*/
public CustomLambdaQueryWrapper<T> softEqForInteger(SFunction<T, ?> R, Object val) {
if (val != null && StringUtils.isNotBlank(val + "") && Integer.valueOf(String.valueOf(val)).intValue() != -1) {
super.eq(R, val);
}
return this;
}
/**
* .软条件查询, 如果条件无值, 就不加入查询.
*
* @param R
* @param val
* @return
*/
public CustomLambdaQueryWrapper<T> softNe(SFunction<T, ?> R, Object val) {
if (val != null && StringUtils.isNotBlank(val + "")) {
super.ne(R, val);
}
return this;
}
/**
* .软条件查询, 如果条件无值, 就不加入查询.
*
* @param R
* @param val
* @return
*/
public CustomLambdaQueryWrapper<T> softLike(SFunction<T, ?> R, Object val) {
if (val != null && StringUtils.isNotBlank(val + "")) {
super.like(R, val);
}
return this;
}
/**
* .软条件查询, 如果条件无值, 就不加入查询.
*
* @param R
* @param coll
* @return
*/
public CustomLambdaQueryWrapper<T> softIn(SFunction<T, ?> R, Collection<?> coll) {
if (coll.size() > 0) {
super.in(R, coll);
}
return this;
}
/**
* .软条件查询, 如果条件无值, 就不加入查询.
*
* @param R
* @param coll
* @return
*/
public CustomLambdaQueryWrapper<T> softNotIn(SFunction<T, ?> R, Collection<?> coll) {
if (coll.size() > 0) {
super.notIn(R, coll);
}
return this;
}
/**
* .软条件查询, 如果条件无值, 就不加入查询.
*
* @param R
* @param val1
* @param val2
* @return
*/
public CustomLambdaQueryWrapper<T> softTimeBetween(SFunction<T, ?> R, Object val1, Object val2) {
if (val1 != null && StringUtils.isNotBlank(val1 + "") && val2 != null && StringUtils.isNotBlank(val2 + "")) {
super.between(R, val1, val2);
return this;
}
if (val1 != null && StringUtils.isNotBlank(val1 + "") && val2 == null) {
super.ge(R, val1);
return this;
}
if (val1 == null && val2 != null && StringUtils.isNotBlank(val2 + "")) {
super.le(R, val2);
}
return this;
}
/**
* .软条件查询, 如果条件为null, 查询就改为is null.
*
* @param R
* @param val
* @return
*/
public CustomLambdaQueryWrapper<T> softEqOrIsNull(SFunction<T, ?> R, Object val) {
if (val != null && StringUtils.isNotBlank(val + "")) {
super.eq(R, val);
} else if (val == null) {
super.isNull(R);
}
return this;
}
}

View File

@@ -0,0 +1,26 @@
package com.lightyears.admin.util;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class GetBeanUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
public void setApplicationContext(ApplicationContext context) {
GetBeanUtil.applicationContext = context;
}
public static Object getBean(String name) {
return applicationContext.getBean(name);
}
public static Object getBean(Class classObj) {
return applicationContext.getBean(classObj);
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
}

View File

@@ -0,0 +1,51 @@
package com.lightyears.admin.util;
import java.security.MessageDigest;
/**
* Created by tanhao on 2019/3/18.
*/
public class MD5Utils {
private static final String hexDigIts[] = {"0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"};
/**
* MD5加密
* @param origin 字符
* @param charsetname 编码 UTF-8
* @return
*/
public static String MD5Encode(String origin, String charsetname){
String resultString = null;
try{
resultString = new String(origin);
MessageDigest md = MessageDigest.getInstance("MD5");
if(null == charsetname || "".equals(charsetname)){
resultString = byteArrayToHexString(md.digest(resultString.getBytes()));
}else{
resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname)));
}
}catch (Exception e){
}
return resultString;
}
public static String byteArrayToHexString(byte b[]){
StringBuffer resultSb = new StringBuffer();
for(int i = 0; i < b.length; i++){
resultSb.append(byteToHexString(b[i]));
}
return resultSb.toString();
}
public static String byteToHexString(byte b){
int n = b;
if(n < 0){
n += 256;
}
int d1 = n / 16;
int d2 = n % 16;
return hexDigIts[d1] + hexDigIts[d2];
}
}

View File

@@ -0,0 +1,28 @@
package com.lightyears.admin.util;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.lightyears.common.domain.dto.SlicedQueryResult;
import java.util.List;
public class PageHelperUtil {
public static void setPage(Integer pageNo, Integer pageSize) {
PageHelper.startPage(pageNo, pageSize);
}
/**
* 分页查询数据
*
* @param data
* 数据集合
* @return 分页对象
*/
public static <T> SlicedQueryResult<T> slicedQueryResult(List<T> data) {
PageInfo<T> pageInfo = new PageInfo<T>(data);
SlicedQueryResult<T> slicedQueryResult = new SlicedQueryResult<T>(pageInfo.getPageNum(), pageInfo.getPageSize(), pageInfo.getTotal(), data);
PageHelper.clearPage();
return slicedQueryResult;
}
}

View File

@@ -0,0 +1,383 @@
package com.lightyears.admin.util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* spring redis 工具类
**/
@Component
public class RedisCache {
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private StringRedisTemplate stringRedisTemplate;
/**
* 判断key是否存在
* @param key 键
* @return true 存在 false不存在
*/
public boolean hasKey(String key) {
try {
return redisTemplate.hasKey(key);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 缓存基本的对象Integer、String、实体类等
*
* @param key 缓存的键值
* @param value 缓存的值
*/
public <T> void setCacheObject(final String key, final T value) {
redisTemplate.opsForValue().set(key, value);
}
/**
* 缓存基本的对象Integer、String、实体类等
*
* @param key 缓存的键值
* @param value 缓存的值
* @param timeout 时间
* @param timeUnit 时间颗粒度
*/
public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit) {
redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
}
/**
* 设置有效时间
*
* @param key Redis键
* @param timeout 超时时间
* @return true=设置成功false=设置失败
*/
public boolean expire(final String key, final long timeout) {
return expire(key, timeout, TimeUnit.SECONDS);
}
/**
* 设置有效时间
*
* @param key Redis键
* @param timeout 超时时间
* @param unit 时间单位
* @return true=设置成功false=设置失败
*/
public boolean expire(final String key, final long timeout, final TimeUnit unit) {
return redisTemplate.expire(key, timeout, unit);
}
/**
* 获得缓存的基本对象。
*
* @param key 缓存键值
* @return 缓存键值对应的数据
*/
public <T> T getCacheObject(final String key) {
ValueOperations<String, T> operation = redisTemplate.opsForValue();
return operation.get(key);
}
/**
* 删除单个对象
*
* @param key
*/
public boolean deleteObject(final String key) {
return redisTemplate.delete(key);
}
/**
* 删除指定前缀的缓存
* @param key
* @return
*/
public Long deleteByPrefix(final String key) {
Set<String> keys = redisTemplate.keys(key.concat("*"));
return redisTemplate.delete(keys);
}
/**
* 删除集合对象
*
* @param collection 多个对象
* @return
*/
public long deleteObject(final Collection collection) {
return redisTemplate.delete(collection);
}
// ===============================list=================================
/**
* 获取list缓存的内容
*
* @param key 键
* @param start 开始
* @param end 结束 0 到 -1代表所有值
* @return
*/
public List<Object> lGet(String key, long start, long end) {
try {
return redisTemplate.opsForList().range(key, start, end);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 获取list缓存的长度
*
* @param key 键
* @return
*/
public long lGetListSize(String key) {
try {
return redisTemplate.opsForList().size(key);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 通过索引 获取list中的值
*
* @param key 键
* @param index 索引 index>=0时 0 表头1 第二个元素依次类推index<0时-1表尾-2倒数第二个元素依次类推
* @return
*/
public Object lGetIndex(String key, long index) {
try {
return redisTemplate.opsForList().index(key, index);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @return
*/
public boolean lSet(String key, Object value) {
try {
redisTemplate.opsForList().rightPush(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @param time 时间(秒)
* @return
*/
public boolean lSet(String key, Object value, long time) {
try {
redisTemplate.opsForList().rightPush(key, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @return
*/
public boolean lSetAll(String key, List<? extends Object> value) {
try {
redisTemplate.opsForList().rightPushAll(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @param time 时间(秒)
* @return
*/
public boolean lSet(String key, List<Object> value, long time) {
try {
redisTemplate.opsForList().rightPushAll(key, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 根据索引修改list中的某条数据
*
* @param key 键
* @param index 索引
* @param value 值
* @return
*/
public boolean lUpdateIndex(String key, long index, Object value) {
try {
redisTemplate.opsForList().set(key, index, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 移除N个值为value
*
* @param key 键
* @param count 移除多少个
* @param value 值
* @return 移除的个数
*/
public long lRemove(String key, long count, Object value) {
try {
Long remove = redisTemplate.opsForList().remove(key, count, value);
return remove;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 缓存Set
*
* @param key 缓存键值
* @param dataSet 缓存的数据
* @return 缓存数据的对象
*/
public <T> long setCacheSet(final String key, final Set<T> dataSet) {
Long count = redisTemplate.opsForSet().add(key, dataSet);
return count == null ? 0 : count;
}
/**
* 获得缓存的set
*
* @param key
* @return
*/
public <T> Set<T> getCacheSet(final String key) {
return redisTemplate.opsForSet().members(key);
}
/**
* 缓存Map
*
* @param key
* @param dataMap
*/
public <T> void setCacheMap(final String key, final Map<String, T> dataMap) {
if (dataMap != null) {
redisTemplate.opsForHash().putAll(key, dataMap);
}
}
/**
* 获得缓存的Map
*
* @param key
* @return
*/
public <T> Map<String, T> getCacheMap(final String key) {
return redisTemplate.opsForHash().entries(key);
}
/**
* 往Hash中存入数据
*
* @param key Redis键
* @param hKey Hash键
* @param value 值
*/
public <T> void setCacheMapValue(final String key, final String hKey, final T value) {
redisTemplate.opsForHash().put(key, hKey, value);
}
/**
* 获取Hash中的数据
*
* @param key Redis键
* @param hKey Hash键
* @return Hash中的对象
*/
public <T> T getCacheMapValue(final String key, final String hKey) {
HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();
return opsForHash.get(key, hKey);
}
/**
* 获取多个Hash中的数据
*
* @param key Redis键
* @param hKeys Hash键集合
* @return Hash对象集合
*/
public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys) {
return redisTemplate.opsForHash().multiGet(key, hKeys);
}
/**
* 获得缓存的基本对象列表
*
* @param pattern 字符串前缀
* @return 对象列表
*/
public Collection<String> keys(final String pattern) {
return redisTemplate.keys(pattern);
}
public StringRedisTemplate getStringRedisTemplate() {
return stringRedisTemplate;
}
public RedisTemplate getRedisTemplate() {
return redisTemplate;
}
}

View File

@@ -0,0 +1,127 @@
package com.lightyears.admin.util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Component;
import java.util.Arrays;
/**
* 利用reids处理多线程问题
*/
@Component
public class RedisLock {
private static final String RELEASE_RESULT = "1";
@Autowired
private RedisCache redisCache;
/**
* 获取redis锁
* @param lockKey 锁标识
* @param requestId 锁的持有者,加锁的请求,可以是线程ID
* @param expireTime 锁过期时间(秒)
* @return
*/
public boolean getLock(String lockKey, String requestId, long expireTime){
String script = "if redis.call('EXISTS', KEYS[1]) == 0 then" +
" redis.call('set', KEYS[1] , ARGV[1] ,'EX',"+expireTime+"); " +
" return 1;" +
" else " +
" if redis.call('get', KEYS[1]) == ARGV[1] then" +
" return 1; " +
" else " +
" return 0; " +
" end " +
" end";
// System.out.println(script);
Object releaseResult =redisCache.getRedisTemplate().execute(new DefaultRedisScript<Long>(script,Long.class),
Arrays.asList(lockKey),
requestId);
return RELEASE_RESULT.equals(releaseResult.toString());
}
/**
* @功能 尝试获取锁,获取者未当前线程,锁持有时间20分钟,等待时间1秒
* @Author 刘建
* @创建时间 2022/1/16 22:18
* @修改人 刘建
* @修改时间 2022/1/16 22:18
* @Param
* @param lockKey:
* @return
**/
public boolean tryLock(String lockKey){
return tryLock(lockKey,Thread.currentThread().getId()+"",1200,1);
}
/**
* @功能 尝试获取锁获取时间不超过wait每500毫秒获取一次
* @Author 刘建
* @创建时间 2022/1/16 20:52
* @修改人 刘建
* @修改时间 2022/1/16 20:52
* @Param
* @param lockKey: 锁标识
* @param requestId: 锁的持有者
* @param expireTime: 过期时间,秒
* @param wait: 等到时间秒
* @return
**/
public boolean tryLock(String lockKey, String requestId, long expireTime,long wait){
long time=System.currentTimeMillis();
wait=wait*1000;
while (System.currentTimeMillis()-wait<time){
if(!getLock(lockKey,requestId,expireTime)){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
return true;
}
}
return false;
}
/**
* @功能 释放锁,锁的持有者才能释放
* @Author 刘建
* @创建时间 2022/1/16 22:19
* @修改人 刘建
* @修改时间 2022/1/16 22:19
* @Param
* @return
**/
public boolean releaseLock(String lockKey){
return releaseLock(lockKey,Thread.currentThread().getId()+"");
}
/**
* 释放锁
* @param lockKey
* @param requestId
* @return
*/
public boolean releaseLock(String lockKey, String requestId){
// 方式1
// if (jedis.get(lockKey).equals(requestId)) {//校验当前锁的持有人与但概念请求是否相同
// 执行在这里时,如果锁被其它请求重新获取到了,此时就不该删除了
// jedis.del(lockKey);
// }
//方式2
// eval() 方法会交给redis服务端执行减少了从服务端再到客户端处理的过程
//赋值 KEYS[1] = lockKey ARGV[1] = requestId
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
Object releaseResult =redisCache.getRedisTemplate().execute(new DefaultRedisScript<Long>(script,Long.class),
Arrays.asList(lockKey),
requestId);;
if (RELEASE_RESULT.equals(releaseResult.toString())) {
return true;
}
return false;
}
}

View File

@@ -0,0 +1,56 @@
package com.lightyears.admin.util;
import cn.hutool.crypto.digest.MD5;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.lightyears.common.domain.dto.ResModeBase;
import com.lightyears.common.domain.enums.MessageEnum;
import lombok.extern.slf4j.Slf4j;
/**
* 返回 数据 指定数据结构
*
* @author Melody
*/
@Slf4j
public class ResultUtil {
public static final ObjectMapper mapper = new ObjectMapper();
public static ResModeBase result(int code, String mes) {
return result(code, mes, null);
}
public static ResModeBase result(int code, String mes, Object data) {
String key = "";
String dataStr = "";
if(data == null){
key = MD5.create().digestHex(MD5.create().digestHex(StaticUtil.PRIVATE_KEY));
} else {
try {
if (data instanceof String){
dataStr = data.toString();
} else {
dataStr = mapper.writeValueAsString(data);
}
key = MD5.create().digestHex(MD5.create().digestHex(dataStr.concat(StaticUtil.PRIVATE_KEY)));
}catch (JsonProcessingException ex){
log.error("json解析错误", ex);
return new ResModeBase(MessageEnum.SERVER_ERROR.getCode(), MessageEnum.SERVER_ERROR.getMessage(), key, null);
}
}
return new ResModeBase(code, mes, key, data);
}
public static ResModeBase success(){
return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage());
}
public static ResModeBase success(Object data){
return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage(), data);
}
public static ResModeBase error(String mes){
return ResultUtil.result(MessageEnum.ERROR.getCode(), mes);
}
}

View File

@@ -0,0 +1,46 @@
package com.lightyears.admin.util;
import java.util.concurrent.ScheduledFuture;
/**
* 任务执行的包装类
*/
public class ScheduledFutureHolder {
private ScheduledFuture<?> scheduledFuture;
private Class<? extends Runnable> runnableClass;
private String corn;
public ScheduledFuture<?> getScheduledFuture() {
return scheduledFuture;
}
public void setScheduledFuture(ScheduledFuture<?> scheduledFuture) {
this.scheduledFuture = scheduledFuture;
}
public Class<? extends Runnable> getRunnableClass() {
return runnableClass;
}
public void setRunnableClass(Class<? extends Runnable> runnableClass) {
this.runnableClass = runnableClass;
}
public String getCorn() {
return corn;
}
public void setCorn(String corn) {
this.corn = corn;
}
@Override
public String toString() {
return "ScheduledFutureHolder{" +
"scheduledFuture=" + scheduledFuture +
", runnableClass=" + runnableClass +
", corn='" + corn + '\'' +
'}';
}
}

View File

@@ -0,0 +1,50 @@
package com.lightyears.admin.util;
import java.util.List;
import java.util.Map;
/**
* 文 件 名 : 特殊处理工具
* 创 建 人HL
* 日 期2019-8-12
* 修 改 人HL
* 日 期2019-8-12
* 描 述: 分页、
* 版 本 号2.0
*/
public class SpecialTool<T> {
public static SpecialTool specialTool = new SpecialTool();
//时间格式
public static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
//集合判断是否为空
public boolean ifGather(Object o) {
if ((o instanceof List && null == o) || (o instanceof Map && null == o)) {
return true;
}
return false;
}
//字符串判断是否为空
public boolean isEmpty(String s) {
if (null == s || s.equals("")) {
return true;
}
return false;
}
/**
* 将字符串的首字母转大写
* @param str 需要转换的字符串
* @return
*/
private static String captureName(String str) {
// 进行字母的ascii编码前移效率要高于截取字符串进行转换的操作
char[] cs=str.toCharArray();
cs[0]-=32;
return String.valueOf(cs);
}
}

View File

@@ -0,0 +1,46 @@
package com.lightyears.admin.util;
import java.util.HashMap;
import java.util.Map;
/**
* 静态工具栏 :目前数据较小 且又想减少服务器压力,特建此类 做静态缓存
*/
public class StaticUtil {
// ------------------------系统类-----------------------
//金币极限操作 防范静态变量
public static Map<String,Boolean> goldSyn = new HashMap<String,Boolean>();
// 数据加解密盐
public static final String PRIVATE_KEY = "123144123";
// 发布公告 redis锁key
public static final String NOTICE_LOCK = "mineClearance:publicNotice:lock";
// ---------------------------------redis -----------------------------------------
// 在线用户信息
public static final String ONLINE_USER_PUBLIC_KEY="mineClearance:onlineUser:";
// 在线用户TOKEN
public static final String ONLINE_USER_TOKEN="mineClearance:onlineToken:";
// 排行榜
public static final String RANK_LIST = "mineClearance:rankList:";
// 闯关排行
public static final String CLEARANCE_RANK_LIST = "mineClearance:clearanceList";
// admin 密码
public static final String ADMIN_PASSWORD = "mineClearance:admin:password";
// admin 在线key
public static final String ONLINE_ADMIN_USER_PUBLIC_KEY="mineClearance:admin:onlineUser:";
//----------------------------挑战榜task--------------------------
// 锁榜时间
public static final String LOCKE_TIME = " 23:00:00";
// 结算时间
public static final String SETTLEMENT_TIME = " 23:45:00";
// 挑战榜初始化时间
public static final String CHALLENGE_INIT_TIME = " 1:00:00";
// 挑战榜redis刷新时间
public static final String CHALLENGE_REFRESH_TIME = " 1:05:00";
public static final String CHALLENGE_INSTANCE_RANK_DETAIL="mineClearance:challenge:rankDetail:";
}

View File

@@ -0,0 +1,67 @@
qbs-switch:
swagger-open: true #swagger开关(true:打开, false:关闭)
spring:
application:
name: mine-clearance-admin
main:
allow-bean-definition-overriding: true
allow-circular-references: true
# 全局配置响应日期格式和时区为东八区,解决日期类型返回前端少八个小时的问题
jackson:
time-zone: GMT+8
datasource:
username: root
password: 43626546
url: jdbc:mysql://42.192.76.87:3306/saolei_v2_db?characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
druid:
initial-size: 20
max-active: 80
min-idle: 20
max-wait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictabkeIdleTimeMillis: 1800000
validationQuery: SELECT 1
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
# 配置监控统计拦截的filters去掉后监控界面sql无法统计。wall用于防火墙
filters: stat,wall
# cloud:
# nacos:
# discovery:
# server-addr: localhost:8848
redis:
# Redis服务器地址
host: localhost
# Redis数据库索引默认为0
database: 0
# Redis服务器连接端口
port: 6379
# Redis服务器连接密码默认为空
password: 123456
# 连接超时时间
timeout: 1000ms
lettuce:
pool:
# 连接池最大连接数
max-active: 8
# 连接池最大空闲连接数
max-idle: 8
# 连接池最小空闲连接数
min-idle: 0
# 连接池最大阻塞等待时间,负值表示没有限制
max-wait: -1ms
mybatis-plus:
mapper-locations: classpath*:mapper/**/*Mapper.xml
type-aliases-package: com.lightyears.common.domain
global-config:
banner: false
db-config:
id-type: input
configuration:
# 控制台SQL日志
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
map-underscore-to-camel-case: false

View File

@@ -0,0 +1,73 @@
qbs-switch:
swagger-open: true #swagger开关(true:打开, false:关闭)
spring:
application:
name: mine-clearance-admin
main:
allow-bean-definition-overriding: true
allow-circular-references: true
# 全局配置响应日期格式和时区为东八区,解决日期类型返回前端少八个小时的问题
jackson:
time-zone: GMT+8
datasource:
username: root
password: 1476346288@mysql
# password: 1813547935mysql
# 基础
url: jdbc:mysql://127.0.0.1:3986/saolei_v2_db?characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=convertToNull
# 本地
# url: jdbc:mysql://39.106.21.14:3986/saolei_v2_db?characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
druid:
initial-size: 20
max-active: 80
min-idle: 20
max-wait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictabkeIdleTimeMillis: 1800000
validationQuery: SELECT 1
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
# 配置监控统计拦截的filters去掉后监控界面sql无法统计。wall用于防火墙
filters: stat,wall
# cloud:
# nacos:
# discovery:
# server-addr: localhost:8848
redis:
# Redis服务器地址
host: localhost
# Redis数据库索引默认为0
database: 0
# Redis服务器连接端口
port: 7963
# Redis服务器连接密码默认为空
password: 1476346288@redis
# password: 123456
# 连接超时时间
timeout: 1000ms
lettuce:
pool:
# 连接池最大连接数
max-active: 8
# 连接池最大空闲连接数
max-idle: 8
# 连接池最小空闲连接数
min-idle: 0
# 连接池最大阻塞等待时间,负值表示没有限制
# max-wait: -1ms
max-wait: 3
mybatis-plus:
mapper-locations: classpath*:mapper/**/*Mapper.xml
type-aliases-package: com.lightyears.common.domain
global-config:
banner: false
db-config:
id-type: input
configuration:
# 控制台SQL日志
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
map-underscore-to-camel-case: false

View File

@@ -0,0 +1,11 @@
server:
port: 18634
tomcat:
uri-encoding: UTF-8
logging:
config: classpath:log.xml
spring:
profiles:
active: dev
appconfig:
version: 197.0

View File

@@ -0,0 +1,51 @@
<configuration>
<!-- %m输出的信息,%p日志级别,%t线程名,%d日期,%c类的全名,%i索引【从数字0开始递增】,,, -->
<!-- appender是configuration的子节点是负责写日志的组件。 -->
<!-- ConsoleAppender把日志输出到控制台 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d %p (%file:%line\)- %m%n</pattern>
<!-- 控制台也要使用UTF-8不要使用GBK否则会中文乱码 -->
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- RollingFileAppender滚动记录文件先将日志记录到指定文件当符合某个条件时将日志记录到其他文件 -->
<!-- 以下的大概意思是1.先按日期存日志日期变了将前一天的日志文件名重命名为XXX%日期%索引新的日志仍然是sys.log -->
<!-- 2.如果日期没有发生变化但是当前日志的文件大小超过1KB时对当前日志进行分割 重命名-->
<appender name="syslog"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>logs/basics/sys.log</File>
<!-- rollingPolicy:当发生滚动时,决定 RollingFileAppender 的行为,涉及文件移动和重命名。 -->
<!-- TimeBasedRollingPolicy 最常用的滚动策略,它根据时间来制定滚动策略,既负责滚动也负责出发滚动 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 活动文件的名字会根据fileNamePattern的值每隔一段时间改变一次 -->
<!-- 文件名log/sys.2022-3-09.0.log -->
<fileNamePattern>logs/basics/sys.%d.%i.log</fileNamePattern>
<!-- 每产生一个日志文件该日志文件的保存期限为30天 -->
<maxHistory>30</maxHistory>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!-- maxFileSize:这是活动文件的大小默认值是10MB -->
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<!-- pattern节点用来设置日志的输入格式 -->
<pattern>
%d %p (%file:%line\)- %m%n
</pattern>
<!-- 记录日志的编码 -->
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
</appender>
<!-- 控制台输出日志级别 -->
<root level="info">
<appender-ref ref="STDOUT" />
</root>
<!-- 指定项目中某个包,当有日志操作行为时的日志记录级别 -->
<!-- com.lightyears为根包也就是只要是发生在这个根包下面的所有日志操作行为的权限都是DEBUG -->
<!-- 级别依次为【从高到低】FATAL > ERROR > WARN > INFO > DEBUG > TRACE -->
<logger name="com.lightyears.basics" level="DEBUG">
<appender-ref ref="syslog" />
</logger>
</configuration>

View File

@@ -0,0 +1,5 @@
<?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.lightyears.admin.mapper.AssertLogMapper">
</mapper>

View File

@@ -0,0 +1,19 @@
<?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.lightyears.admin.mapper.ClearanceLogMapper">
<select id="getPlayerClearanceLogs" resultType="com.lightyears.common.domain.dto.ClearanceRankDto">
SELECT
p.user_id as playerId,
ifnull( max( l.layers_num ), 0 ) AS layersNum
FROM
sl_player p
left join sl_clearance_log l on l.player_id = p.user_id
<where>
<if test="userId != null and userId > 0">
and p.user_id = ${userId}
</if>
</where>
group by p.user_id
ORDER BY layersNum desc
</select>
</mapper>

View File

@@ -0,0 +1,5 @@
<?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.lightyears.admin.dao.ListBaseMapper">
</mapper>

View File

@@ -0,0 +1,32 @@
<?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.lightyears.admin.mapper.ListInstanceMapper">
<update id="updateInstanceAwardSize">
UPDATE sl_list_instance
SET award_size = award_size + #{awardSize}
where id = #{instanceId}
and assets_type = #{assetsType}
</update>
<select id="getListInstances" resultType="com.lightyears.common.domain.dto.ListInstanceDto">
SELECT
id,
list_id as listId,
`name`,
list_date AS listDate,
mine_num_section AS mineNumSection,
map_size AS mapSize,
in_pond_fee AS inPondFee,
award_size AS awardSize,
entry_threshold AS entryThreshold,
`status`,
assets_type as assetsType,
tickets_num as ticketsNum,
distribution as distribution
FROM
sl_list_instance
WHERE
`status` = 1
</select>
</mapper>

View File

@@ -0,0 +1,79 @@
<?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.lightyears.admin.mapper.ListRankMapper">
<update id="initRank">
UPDATE `sl_list_rank`
SET
`player_name` = NULL,
`player_id` = NULL,
`challenge_time` = NULL,
`game_data` = NULL
WHERE
`instance_id` = ${instanceId}
and `rank_num` = ${rankNum}
</update>
<select id="getRankList" resultType="com.lightyears.common.domain.dto.ListRankDto">
SELECT
r.id as id,
r.instance_id AS instanceId,
r.rank_num AS rankNum,
r.player_id AS playerId,
r.player_name AS playerName,
r.challenge_time AS challengeTime,
r.game_data AS gameData
FROM
sl_list_rank r
LEFT JOIN sl_list_instance n on n.id = r.instance_id
<where>
<if test="instanceId != null and instanceId != 0">
and r.instance_id = #{instanceId}
</if>
<if test="playerId != null and playerId != 0">
and r.player_id = ${playerId}
</if>
<if test="state != null and state > -1">
and n.status = ${state}
</if>
</where>
ORDER BY
rank_num ASC
</select>
<select id="getNewRankList" resultType="com.lightyears.common.domain.dto.ListRankDto">
SELECT
r.id as id,
r.instance_id AS instanceId,
r.rank_num AS rankNum,
r.player_id AS playerId,
r.player_name AS playerName,
r.challenge_time AS challengeTime,
r.game_data AS gameData
FROM
sl_list_rank r
LEFT JOIN sl_list_instance n on n.id = r.instance_id
where
n.status in (1, 3)
<if test="instanceId != null and instanceId != 0">
and r.instance_id = #{instanceId}
</if>
<if test="playerId != null and playerId != 0">
and r.player_id = ${playerId}
</if>
ORDER BY
rank_num ASC
</select>
<select id="getRankByInsRank" resultType="com.lightyears.common.domain.dto.ListRankDto">
SELECT
id,
instance_id as instanceId,
rank_num as rankNum,
player_id AS playerId,
player_name AS playerName,
challenge_time AS challengeTime,
game_data as gameData
FROM
sl_list_rank
WHERE
instance_id = #{instanceId}
AND rank_num = #{rank}
</select>
</mapper>

View File

@@ -0,0 +1,120 @@
<?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.lightyears.admin.mapper.LogMapper">
<select id="paging" resultType="com.lightyears.common.domain.dto.OrdinaryRankDto">
SELECT
a.id,
a.user_id,
a.game_time,
a.bv3,
a.bvs3,
a.nf,
s.user_name
FROM
sl_log a
LEFT JOIN sl_player s ON s.user_id = a.user_id
where a.level = #{level}
<if test="userId != null and userId > 0">
and a.user_id = ${userId}
</if>
ORDER BY a.game_time
</select>
<select id="syntheticalPaging" resultType="com.lightyears.common.domain.dto.OrdinaryRankDto">
SELECT
a.user_id user_id,
SUM( a.game_time ) game_time,
SUM( bv3 ) bv3,
SUM( bvs3 ) bvs3,
s.user_name,
0 nf
FROM
sl_log a
LEFT JOIN sl_player s ON s.user_id = a.user_id
WHERE
a.user_id IN (
SELECT
t.user_id
FROM
( SELECT user_id, count( LEVEL ) count_level FROM sl_log WHERE LEVEL != 4 GROUP BY user_id ) t
WHERE
t.count_level >= 3
)
AND a.LEVEL != 4
GROUP BY
a.user_id
ORDER BY
game_time
</select>
<select id="getComprehensiveRankByUserId" parameterType="Integer" resultType="java.util.Map">
SELECT
m.*
from ( SELECT q.*,( @i := @i + 1 ) ranking
FROM
(
SELECT
a.user_id user_id,
SUM( a.game_time ) game_time,
SUM( bv3 ) bv3,
SUM( bvs3 ) bvs3,
s.user_name,
0 nf
FROM
sl_log a
LEFT JOIN sl_player s ON s.user_id = a.user_id
WHERE
a.user_id IN (
SELECT
t.user_id
FROM
( SELECT user_id, count( LEVEL ) count_level FROM sl_log WHERE LEVEL != 4 GROUP BY user_id ) t
WHERE
t.count_level >= 3
)
AND a.LEVEL != 4
GROUP BY
a.user_id
) q,
( SELECT @i := 0 ) t2
ORDER BY
q.game_time
) m where user_id = #{userId}
limit 1
</select>
<select id="getRankByLevelUserId" resultType="java.util.Map">
SELECT
*
FROM
(
SELECT
( @i := @i + 1 ) ranking,
x.*
FROM
( SELECT @i := 0 ) t2,
(
SELECT
a.id,
a.user_id,
a.game_time,
a.bv3,
a.bvs3,
a.nf,
s.user_name,
a.creation_time
FROM
sl_log a
LEFT JOIN sl_player s ON s.user_id = a.user_id
WHERE
a.LEVEL = #{level}
) x
ORDER BY
x.game_time ASC,
x.creation_time ASC
) m
WHERE
m.user_id = #{userId}
limit 1
</select>
</mapper>

View File

@@ -0,0 +1,31 @@
<?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.lightyears.admin.mapper.NoticeMapper">
<select id="getList" resultType="com.lightyears.common.domain.dto.NoticeDto">
SELECT
id,
title,
type,
`status`,
create_date as createDate
FROM
sl_notice
WHERE
`status` IN (0, 1)
<if test="type != null and type > -1">
and type = #{type}
</if>
<if test="playerId != null and playerId > 0">
and player_id = #{playerId}
</if>
order by create_date desc
</select>
<select id="getContent" resultType="String">
SELECT
content
FROM
sl_notice
WHERE
id = #{id}
</select>
</mapper>

View File

@@ -0,0 +1,14 @@
<?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.lightyears.admin.mapper.PlayerAssetsMapper">
<update id="addGold">
update sl_player_assets set number = number + #{gold}, version = version +1 where id = #{id} and version = ${version}
</update>
<update id="reduceGold">
update sl_player_assets set number = number - #{gold}, version = version +1 where id = #{id} and version = ${version}
</update>
<!-- 获取用户的资产信息 -->
<select id="getPlayerAssets" resultType="com.lightyears.common.domain.dto.SimplePlayerAssert">
select type, number from sl_player_assets where player_id = #{playerId}
</select>
</mapper>

View File

@@ -0,0 +1,22 @@
<?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.lightyears.admin.mapper.PlayerMapper">
<select id="getPlayerList" parameterType="com.lightyears.admin.dto.UserListParams" resultType="com.lightyears.common.domain.entity.Player">
SELECT
sp.user_id,
sp.user_name,
sp.open_id,
sp.`status`,
spa.number as user_gold
FROM
sl_player sp,
sl_player_assets spa
WHERE
sp.user_id = spa.player_id
AND type = 0
<if test="keyword != null and keyword != ''">
and (sp.user_id like concat('%', #{keyword}, '%') or sp.user_name like concat('%', #{keyword}, '%'))
</if>
ORDER BY sp.creation_time desc
</select>
</mapper>

View File

@@ -0,0 +1,5 @@
<?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.lightyears.admin.mapper.RecordMapper">
</mapper>

146
basics/pom.xml Normal file
View File

@@ -0,0 +1,146 @@
<?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>mine_clearance</artifactId>
<groupId>com.lightyears.mine_clearance</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<name>basics</name>
<artifactId>basics</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- druid数据源驱动 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<!--json-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
</dependency>
<!-- 由于SpringBoot 2.x中默认并没有使用Redis连接池所以需要添加commons-pool2的依赖 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<!--redis依赖配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 模板引擎 -->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</dependency>
<!--swagger2整合-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<!-- hutool 一个常用工具集 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
</dependency>
<dependency>
<groupId>com.lightyears.mine_clearance</groupId>
<artifactId>common</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>basics</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>utf-8</encoding>
</configuration>
</plugin>
<!--打包一个JAR-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.lightyears.basics.BasicsApp</mainClass>
<includeSystemScope>true</includeSystemScope>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<testFailureIgnore>true</testFailureIgnore>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,19 @@
package com.lightyears.basics;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import java.util.TimeZone;
@EnableScheduling
@SpringBootApplication
@EnableTransactionManagement
public class BasicsApp {
public static void main(String[] args) {
// 设置时区
TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));
SpringApplication.run(BasicsApp.class, args);
}
}

View File

@@ -0,0 +1,9 @@
package com.lightyears.basics.annotation;
import java.lang.annotation.*;
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DataVerification {
}

View File

@@ -0,0 +1,65 @@
package com.lightyears.basics.aspect;
import cn.hutool.crypto.digest.MD5;
import com.github.pagehelper.util.StringUtil;
import com.lightyears.common.domain.enums.MessageEnum;
import com.lightyears.basics.exception.GlobalException;
import com.lightyears.basics.util.StaticUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Collection;
import java.util.Map;
@Aspect
@Component
public class DataVerificationAspect {
/**
* 过滤类
* 指定自定义注解为切入点
**/
@Pointcut("@annotation(com.lightyears.basics.annotation.DataVerification)")
public void checkPoint() {
}
/**
* 前置
*/
@Before("checkPoint()")
public void doAround(JoinPoint joinPoint) throws GlobalException {
RequestAttributes ra = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes sra = (ServletRequestAttributes) ra;
assert sra != null;
HttpServletRequest request = sra.getRequest();
String checkKey = request.getHeader("checkKey");
Map<String, String[]> paramMap = request.getParameterMap();
StringBuffer paramsStr = new StringBuffer();
if (StringUtil.isEmpty(checkKey)) {
throw new GlobalException(MessageEnum.CHECK_KEY_ERROR);
}
Object[] params = joinPoint.getArgs();
if(paramMap.size() > 0) {
Collection<String[]> values = paramMap.values();
for (String[] value : values) {
paramsStr.append(value[0]);
}
} else {
if(params.length == 1) {
paramsStr.append(params[0].toString());
}
}
String testKey = MD5.create().digestHex(MD5.create().digestHex(paramsStr.append(StaticUtil.PRIVATE_KEY).toString()));
if (!checkKey.equals(testKey)) {
throw new GlobalException(MessageEnum.CHECK_KEY_ERROR);
}
}
}

View File

@@ -0,0 +1,16 @@
package com.lightyears.basics.config;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Data
@Component
@NoArgsConstructor
@AllArgsConstructor
@ConfigurationProperties(prefix = "appconfig")
public class AppConfig {
private Float version;
}

View File

@@ -0,0 +1,86 @@
package com.lightyears.basics.configuration;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
// 开启redis缓存功能
@EnableCaching
// 备注这是一个配置类
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
/**
* 配置redis模板文件
* @param redisConnectionFactory
* @return
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisSerializer<Object> serializer = redisSerializer();
// 创建RedisTemplate<String, Object>对象
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
// 配置连接工厂
redisTemplate.setConnectionFactory(redisConnectionFactory);
// redis key 序列化方式使用stringSerial
redisTemplate.setKeySerializer(new StringRedisSerializer());
// redis value 序列化方式使用jackson
redisTemplate.setValueSerializer(serializer);
// redis hash key 序列化方式使用stringSerial
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
// redis hash value 序列化方式使用jackson
redisTemplate.setHashValueSerializer(serializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
/**
* 配置序列化
* @return
*/
@Bean
public RedisSerializer<Object> redisSerializer() {
// 定义Jackson2JsonRedisSerializer序列化对象
Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
// 指定要序列化的域field,get和set,以及修饰符范围ANY是都有包括private和public
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// 指定序列化输入的类型类必须是非final修饰的final修饰的类比如String,Integer等会报异常
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
serializer.setObjectMapper(objectMapper);
return serializer;
}
/**
* 自定义缓存管理器
* @param redisConnectionFactory
* @return
*/
@Bean
public RedisCacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory);
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration
.defaultCacheConfig()
// 设置value 为自动转json的Object
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer()))
// 缓存有效期为一天
.entryTtl(Duration.ofDays(1));
return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration);
}
}

View File

@@ -0,0 +1,24 @@
package com.lightyears.basics.configuration;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import java.util.TimeZone;
@Configuration
public class ScheduledConfig {
@Bean
public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
threadPoolTaskScheduler.setPoolSize(3);
threadPoolTaskScheduler.setRemoveOnCancelPolicy(true);
return threadPoolTaskScheduler;
}
@Bean
public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization() {
return jacksonObjectMapperBuilder ->
jacksonObjectMapperBuilder.timeZone(TimeZone.getTimeZone("GMT+8"));
}
}

View File

@@ -0,0 +1,55 @@
package com.lightyears.basics.controller;
import com.lightyears.common.domain.entity.Player;
import com.lightyears.basics.util.RedisCache;
import com.lightyears.basics.util.StaticUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class BaseController {
@Autowired
private RedisCache redisCache;
/**
* 得到request对象
*
* @return
*/
public HttpServletRequest getRequest() {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
.getRequest();
return request;
}
/**
* 得到respones对象
* @return
*/
public HttpServletResponse getResponse() {
HttpServletResponse request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
.getResponse();
return request;
}
/**
* 得到当前登录用户信息
*
* @return
*/
public Player getUserInfo() {
// 获取请求头中的token数据
String token = getRequest().getHeader("Tracecode");
if(token == null) {
token = this.getRequest().getParameter("Tracecode");
}
String key = StaticUtil.ONLINE_USER_PUBLIC_KEY.concat(token);
// 获取登录用户信息
Player user = redisCache.getCacheObject(key);
return user;
}
}

View File

@@ -0,0 +1,39 @@
package com.lightyears.basics.controller;
import com.lightyears.basics.annotation.DataVerification;
import com.lightyears.common.domain.dto.ResModeBase;
import com.lightyears.common.domain.dto.SimplePlayerAssert;
import com.lightyears.common.domain.enums.MessageEnum;
import com.lightyears.basics.service.IPlayerAssetsService;
import com.lightyears.basics.util.ResultUtil;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
@CrossOrigin
@RestController
@RequestMapping("/challenge")
@RequiredArgsConstructor(onConstructor = @_(@Autowired))
public class ChallengeController extends BaseController{
private final IPlayerAssetsService playerAssetsService;
// @DataVerification
@GetMapping("/list")
public ResModeBase list() {
return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage(), new ArrayList<>());
}
// @DataVerification
@GetMapping("/playerAssert")
@ApiOperation(value = "获取玩家资产信息", notes = "挑战榜")
public ResModeBase playerAssert(){
List<SimplePlayerAssert> assets = playerAssetsService.getPlayerAssets(this.getUserInfo().getUser_id());
return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage(), assets);
}
}

View File

@@ -0,0 +1,183 @@
package com.lightyears.basics.controller;
import cn.hutool.core.date.DateUtil;
import com.lightyears.basics.annotation.DataVerification;
import com.lightyears.basics.service.IClearanceLogService;
import com.lightyears.basics.service.IGameSystemService;
import com.lightyears.basics.service.ILogService;
import com.lightyears.basics.service.INoticeService;
import com.lightyears.basics.util.ResultUtil;
import com.lightyears.common.domain.dto.ResModeBase;
import com.lightyears.common.domain.enums.MessageEnum;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
@CrossOrigin
@RestController
@RequestMapping("/saolei")
@Api("扫雷 客户端调用接口:")
@RequiredArgsConstructor(onConstructor = @_(@Autowired))
public class ClientController extends BaseController{
private final IGameSystemService gameSystemServiceImpl;
private final INoticeService noticeServiceImpl;
private final ILogService logService;
private final IClearanceLogService clearanceLogService;
@RequestMapping(value = "/touristLogin/{id}", method = RequestMethod.GET)
@ApiImplicitParam(paramType="path", name = "id", value = "用户openId", example = "123", required = true, dataType = "Integer")
@ApiOperation(value = "三方登陆", notes = "参数 QQ/微信open_id(tokenId) 新建用户 isNewUser = true")
public ResModeBase touristLogin(@PathVariable String id) {
return this.gameSystemServiceImpl.touristlogin(id);
}
@DataVerification
@RequestMapping(value = "/checkName", method = RequestMethod.POST)
@ApiOperation(value = "昵称验证", notes = "昵称是否重复true 代表昵称可用")
public ResModeBase checkName(@RequestParam("userName") String userName) {
return this.gameSystemServiceImpl.checkName(userName);
}
@DataVerification
@RequestMapping(value = "/updateName", method = RequestMethod.POST)
@ApiOperation(value = "修改昵称", notes = "更新指定ID玩家的名称玩家第一次登录时系统分配默认名称并提供玩家一次改名的机会")
public ResModeBase updateName(@RequestParam("userName") String userName) {
return this.gameSystemServiceImpl.updateName(this.getUserInfo().getUser_id(), userName);
}
@DataVerification
@RequestMapping(value = "/add_Gold", method = RequestMethod.POST)
@ApiOperation(value = "金币存储", notes = "每次 用户主动向数据库 存储金币")
public ResModeBase add_Gold(@ApiParam(value = "货币数", example = "1") @RequestParam("gold") int gold,
@ApiParam(value = "货币类型0.金币)", example = "0")@RequestParam("type") int type,
@ApiParam(value = "货币变化说明", example = "游戏增加货币") @RequestParam("remark")String remark) {
return this.gameSystemServiceImpl.pushGoldImpl(this.getUserInfo().getUser_id(), gold, type, remark);
}
@DataVerification
@RequestMapping(value = "/sub_Gold", method = RequestMethod.POST)
@ApiOperation(value = "金币取出", notes = "与“金币存储”相反,从用户账号扣除指定金币,如果余额不够扣费")
public ResModeBase sub_Gold(@ApiParam(value = "货币数", example = "1") @RequestParam("gold") int gold,
@ApiParam(value = "货币类型0.金币)", example = "0")@RequestParam("type") int type,
@ApiParam(value = "货币变化说明", example = "扣手续费") @RequestParam("remark")String remark) {
return this.gameSystemServiceImpl.pullGoldImpl(this.getUserInfo().getUser_id(), gold, type, remark);
}
@DataVerification
@RequestMapping(value = "/saveFile", method = RequestMethod.POST)
@ApiOperation(value = "数据存档", notes = "本都游戏数据上传服务器保存")
public ResModeBase saveFile(@ApiParam(value = "存档数据") @RequestParam(value = "record", required = false) String record,
@ApiParam(value = "存档类型0 皮肤 1 记录 2游戏设置", example = "1") @RequestParam(value = "record_type") Integer record_type) {
return this.gameSystemServiceImpl.saveFileImpl(this.getUserInfo().getUser_id(), record, record_type);
}
@DataVerification
@RequestMapping(value = "/readFile", method = RequestMethod.POST)
@ApiOperation(value = "读取存档", notes = "读取服务器存档")
public ResModeBase readFile(@ApiParam(value = "存档类型0 皮肤 1 记录 2游戏设置", example = "1") @RequestParam(value = "record_type") Integer record_type) {
return this.gameSystemServiceImpl.readFile(this.getUserInfo().getUser_id(), record_type);
}
@DataVerification
@RequestMapping(value = "/saveLog", method = RequestMethod.POST)
@ApiOperation(value = "提交游戏记录", notes = "每次游戏完成 进行记录提交")
public ResModeBase saveLog(@ApiParam(value = " 游戏难度1 - 普通 2 困难 3 大师 4 超凡", example = "1") @RequestParam(value = "level", required = false) Integer level,
@ApiParam(value = "本剧游戏所用时间", example = "1") @RequestParam(value = "game_time") int game_time,
@RequestParam(value = "bvs3") float bvs3,
@RequestParam(value = "bv3") float bv3,
@RequestParam(value = "video") String video,
@RequestParam(value = "gameinfo") String gameinfo,
@RequestParam(value = "nf") boolean nf) {
return this.gameSystemServiceImpl.saveLogImpl(this.getUserInfo(), level, game_time, bvs3, bv3, video, gameinfo,nf);
}
@DataVerification
@RequestMapping(value = "/rankingLog", method = RequestMethod.POST)
@ApiOperation(value = "综合排行榜", notes = "所有玩家的排行榜信息")
public ResModeBase ranking(
@ApiParam(value = "当前页", example = "1") @RequestParam(value = "pageIndex") int pageIndex,
@ApiParam(value = "每页数量", example = "1") @RequestParam(value = "pageSize") int pageSize,
@ApiParam(value = "游戏难度:-1综合 1 - 普通 2 困难 3 大师 4 超凡", example = "1") @RequestParam(value = "level") int level) {
return this.gameSystemServiceImpl.ranking(pageIndex, pageSize, level);
}
@DataVerification
@RequestMapping(value = "/userLog", method = RequestMethod.POST)
@ApiOperation(value = "玩家个人 排行名次以及信息", notes = "")
public ResModeBase log(@ApiParam(value = "游戏难度:-1综合 1 - 普通 2 困难 3 大师 4 超凡", example = "1") @RequestParam(value = "level") int level) {
return this.gameSystemServiceImpl.log(this.getUserInfo().getUser_id(), level);
}
@DataVerification
@RequestMapping(value = "/getList", method = RequestMethod.GET)
@ApiOperation(value = "公告查询", notes = "1")
public ResModeBase getList() {
return this.noticeServiceImpl.getList(this.getUserInfo().getUser_id());
}
@DataVerification
@RequestMapping(value = "/getContent", method = RequestMethod.GET)
@ApiOperation(value = "公告内容查询", notes = "1")
public ResModeBase getContent(@ApiParam(value = "公告id", example = "1") @RequestParam(value = "id") int id) {
return this.noticeServiceImpl.getContent(id);
}
@DataVerification
@RequestMapping(value = "/getGameData", method = RequestMethod.POST)
@ApiOperation(value = "回放数据查询", notes = "1")
public ResModeBase getGameData(@ApiParam(value = "排行榜id", example = "1") @RequestParam(value = "id") Integer id,@ApiParam(value = "榜单类型1.普通榜2挑战榜", example = "1") Integer type) {
return this.gameSystemServiceImpl.getGameData(id, type);
}
@DataVerification
@RequestMapping(value = "/getSystemTime", method = RequestMethod.GET)
@ApiOperation(value = "获取系统时间", notes = "1")
public ResModeBase getSystemTime() {
return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage(), DateUtil.format(new Date(),"yyyy-MM-dd"));
}
@DataVerification
@RequestMapping(value = "/cancellationAccount", method = RequestMethod.GET)
@ApiOperation(value = "注销账号", notes = "1")
public ResModeBase cancellationAccount(@ApiParam(value = "身份token", example = "1") @RequestParam(value = "checkToken")String checkToken, HttpServletRequest request) {
if(checkToken.equals(request.getHeader("Tracecode"))){
gameSystemServiceImpl.cancellationAccount(this.getUserInfo().getUser_id());
return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage());
} else {
return ResultUtil.result(MessageEnum.CHECK_LOGGING_ERROR.getCode(), MessageEnum.CHECK_LOGGING_ERROR.getMessage());
}
}
@RequestMapping(value = "/refreshRankCache", method = RequestMethod.GET)
@ApiOperation(value = "刷新排行榜缓存", notes = "1")
public ResModeBase refreshRankCache(@RequestParam(value = "key")Integer key) {
if(key == 43626546){
// 排行榜缓存
logService.cacheRankList(null);
// 雷神之塔缓存
clearanceLogService.cachePlayerClearanceRank();
}
return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage());
}
@RequestMapping(value = "/saveClearanceLog", method = RequestMethod.POST)
@ApiOperation(value = "写入雷神之塔闯关记录", notes = "1")
public ResModeBase saveClearanceLog(@ApiParam(value = "游戏数据", example = "1") @RequestParam(value = "data")String data) {
clearanceLogService.saveClearanceLog(this.getUserInfo().getUser_id(), data);
return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage());
}
@RequestMapping(value = "/getPlayerClearanceLog", method = RequestMethod.GET)
@ApiOperation(value = "获取雷神之塔个人信息", notes = "1")
public ResModeBase getPlayerClearanceLog(@RequestParam(value = "type", required = false, defaultValue = "0")Integer type) {
return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage(), clearanceLogService.getPlayer(this.getUserInfo().getUser_id(), this.getUserInfo().getUser_name(), type));
}
}

View File

@@ -0,0 +1,23 @@
package com.lightyears.basics.controller;
import com.lightyears.common.domain.dto.ResModeBase;
import com.lightyears.common.domain.entity.Notice;
import com.lightyears.basics.service.ISystemService;
import io.swagger.annotations.Api;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@CrossOrigin
@RestController
@RequestMapping("/sys")
@Api("扫雷 管理端调用接口:")
@RequiredArgsConstructor(onConstructor = @_(@Autowired))
public class SystemController extends BaseController{
private final ISystemService systemService;
@RequestMapping(value = "/publishNotice", method = RequestMethod.POST)
public ResModeBase publishNotice(@RequestBody Notice notice) {
return systemService.publishNotice(notice);
}
}

View File

@@ -0,0 +1,18 @@
package com.lightyears.basics.exception;
import com.lightyears.common.domain.enums.MessageEnum;
/**
* @author fengshuonan
* @Description 业务异常的封装
*/
public class BussinessException extends GlobalException {
public BussinessException(MessageEnum messageEnum) {
super(messageEnum.getCode(), messageEnum.getMessage());
}
public BussinessException(Integer code, String message) {
super(code, message);
}
}

View File

@@ -0,0 +1,46 @@
package com.lightyears.basics.exception;
import com.lightyears.common.domain.enums.MessageEnum;
/***
* 全局异常捕捉 统一返回 model
* */
public class GlobalException extends RuntimeException {
//友好提示的code码
protected int friendlyCode;
//友好提示
protected String friendlyMsg;
protected GlobalException(int friendlyCode, String friendlyMsg) {
this.setValues(friendlyCode, friendlyMsg);
}
public GlobalException(MessageEnum messageEnum) {
this.setValues(messageEnum.getCode(), messageEnum.getMessage());
}
private void setValues(int friendlyCode, String friendlyMsg) {
this.friendlyCode = friendlyCode;
this.friendlyMsg = friendlyMsg;
}
public int getCode() {
return friendlyCode;
}
public void setCode(int code) {
this.friendlyCode = code;
}
public String getMessage() {
return friendlyMsg;
}
public void setMessage(String message) {
this.friendlyMsg = message;
}
}

View File

@@ -0,0 +1,26 @@
package com.lightyears.basics.exception;
import com.lightyears.common.domain.dto.ResModeBase;
import com.lightyears.common.domain.enums.MessageEnum;
import com.lightyears.basics.util.ResultUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
@Slf4j
@ControllerAdvice
public class MyExceptionHandle {
@ExceptionHandler(value = Exception.class)
@ResponseBody
public ResModeBase handle(Exception e) {
if (e instanceof GlobalException) {
GlobalException myException = (GlobalException) e;
return ResultUtil.result(myException.getCode(), myException.getMessage());
} else {
log.error("系统异常", e);
return ResultUtil.result(MessageEnum.UNKNOWN_ERROR.getCode(), MessageEnum.UNKNOWN_ERROR.getMessage());
}
}
}

View File

@@ -0,0 +1,119 @@
package com.lightyears.basics.filter;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.util.StringUtil;
import com.lightyears.basics.config.AppConfig;
import com.lightyears.common.domain.entity.Player;
import com.lightyears.common.domain.enums.MessageEnum;
import com.lightyears.basics.util.RedisCache;
import com.lightyears.basics.util.StaticUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.web.context.support.WebApplicationContextUtils;
import javax.annotation.Resource;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@Slf4j
@Component
public class TokenFilter implements Filter{
@Resource
private RedisCache redisCache;
@Resource
private AppConfig appConfig;
@Override
public void init(FilterConfig filterConfig) {
ServletContext servletContext = filterConfig.getServletContext();
ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(servletContext);
redisCache = (RedisCache) ctx.getBean("redisCache");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
// 刷新缓存不验证
if(request.getRequestURI().indexOf("refreshRankCache")<0){
// 版本号验证
String version = request.getHeader("version");
if (StrUtil.isEmpty(version)) {
this.authcReq(response, MessageEnum.VERSION_ERROR.getCode(), MessageEnum.VERSION_ERROR.getMessage());
return;
}
try{
Float versionCode = Float.valueOf(version);
// log.info("version :" + appConfig.getVersion());
if(versionCode < appConfig.getVersion()) {
this.authcReq(response, MessageEnum.VERSION_ERROR.getCode(), MessageEnum.VERSION_ERROR.getMessage());
return;
}
}catch (Exception e) {
this.authcReq(response, MessageEnum.VERSION_ERROR.getCode(), MessageEnum.VERSION_ERROR.getMessage());
return;
}
}
String tracecode = request.getHeader("Tracecode");
Boolean flag = request.getRequestURI().indexOf("touristLogin")<0 && request.getRequestURI().indexOf("getSystemTime") < 0 && request.getRequestURI().indexOf("swagger-ui")<0 && request.getRequestURI().indexOf("swagger-resources")<0 && request.getRequestURI().indexOf("v2") < 0 && request.getRequestURI().indexOf("refreshRankCache")<0;
// 登录放行
if(flag){
// 判断身份码, 是否已登录
if((StringUtil.isEmpty(tracecode) || !redisCache.hasKey(StaticUtil.ONLINE_USER_PUBLIC_KEY.concat(tracecode)))){
/**
* 不是登录 || 身份码不存在 || 未在登录列表 就拒绝访问
*/
this.authcReq(response, MessageEnum.SYSTEM_ERROR.getCode(), MessageEnum.SYSTEM_ERROR.getMessage());
return;
}
Player player = redisCache.getCacheObject(StaticUtil.ONLINE_USER_PUBLIC_KEY.concat(tracecode));
String token = redisCache.getCacheObject(StaticUtil.ONLINE_USER_TOKEN.concat(player.getUser_id().toString())).toString();
if(!tracecode.equals(token)) {
/**
* 登录失效,已被异地登录
*/
this.authcReq(response, MessageEnum.LOCATION_ERROR.getCode(), MessageEnum.LOCATION_ERROR.getMessage());
return;
}
// 重置身份缓存过期时间
redisCache.expire(StaticUtil.ONLINE_USER_TOKEN.concat(player.getUser_id().toString()), 1, TimeUnit.HOURS);
// 重置身份认证过期时间
redisCache.expire(StaticUtil.ONLINE_USER_PUBLIC_KEY.concat(tracecode), 1, TimeUnit.HOURS);
}
//执行
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
}
/**
* 响应访问
* @param response
* @throws IOException
*/
private void authcReq(HttpServletResponse response, Integer code, String msg) throws IOException {
response.setHeader("Access-Control-Allow-Origin", "*");
response.setStatus(HttpServletResponse.SC_OK);
response.setContentType("application/json; charset=utf-8");
PrintWriter writer = response.getWriter();
Map<String, Object> map = new HashMap<>();
map.put("code", code);
map.put("msg", msg);
writer.print(JSONObject.toJSON(map));
}
}

View File

@@ -0,0 +1,38 @@
package com.lightyears.basics.init;
import com.lightyears.basics.service.IClearanceLogService;
import com.lightyears.basics.service.ILogService;
import com.lightyears.basics.util.RedisCache;
import com.lightyears.basics.util.StaticUtil;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
;
/**
* 挑战数据初始化
*/
@Component
public class ChallengeDataInit {
@Resource
private ILogService logService;
@Resource
private IClearanceLogService clearanceLogService;
@PostConstruct
public void init() {
// 缓存排行榜数据
logService.cacheRankList(null);
// 缓存雷神之塔玩家关卡数据
clearanceLogService.cachePlayerClearanceRank();
}
@PreDestroy
public void destroy() {
// 写入持久层
}
}

View File

@@ -0,0 +1,18 @@
package com.lightyears.basics.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.lightyears.common.domain.entity.AssertLog;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* Mapper 接口
* </p>
*
* @author hellor
* @since 2022-03-16
*/
@Mapper
public interface AssertLogMapper extends BaseMapper<AssertLog> {
}

View File

@@ -0,0 +1,26 @@
package com.lightyears.basics.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.lightyears.common.domain.dto.ClearanceRankDto;
import com.lightyears.common.domain.entity.ClearanceLog;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* <p>
* Mapper 接口
* </p>
*
* @author hellor
* @since 2022-06-02
*/
@Mapper
public interface ClearanceLogMapper extends BaseMapper<ClearanceLog> {
/**
* 获取玩家最高闯关 关卡数据
* @return
*/
List<ClearanceRankDto> getPlayerClearanceLogs(@Param("userId")Integer userId);
}

View File

@@ -0,0 +1,25 @@
package com.lightyears.basics.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.lightyears.common.domain.dto.ListRankDto;
import com.lightyears.common.domain.entity.ListRank;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* <p>
* Mapper 接口
* </p>
*
* @author hellor
* @since 2022-03-16
*/
@Mapper
public interface ListRankMapper extends BaseMapper<ListRank> {
int initRank(@Param("instanceId") Integer instanceId, @Param("playerId") Integer playerId);
List<ListRankDto> getRankList(@Param("instanceId") Integer instanceId, @Param("playerId") Integer playerId, @Param("state") Integer state);
List<ListRankDto> getNewRankList (@Param("instanceId") Integer instanceId, @Param("playerId") Integer playerId);
ListRankDto getRankByInsRank(@Param("instanceId") Integer instanceId,@Param("rank") Integer rank);
}

View File

@@ -0,0 +1,29 @@
package com.lightyears.basics.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.lightyears.common.domain.dto.OrdinaryRankDto;
import com.lightyears.common.domain.entity.Log;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
* <p>
* 游戏 完成记录 表 游戏难度1 - 普通 2 困难 3 大师 Mapper 接口
* </p>
*
* @author hellor
* @since 2022-03-09
*/
@Mapper
public interface LogMapper extends BaseMapper<Log> {
List<OrdinaryRankDto> paging(@Param("level") Integer level, @Param("userId")Integer userId);
//综合查询 三种难度加起来 获取排名
List<OrdinaryRankDto> syntheticalPaging();
// 查询用户综合排名
Map getComprehensiveRankByUserId(@Param("userId") Integer userId);
//根据User_id和 level 查询排名
Map getRankByLevelUserId(@Param("level")int level, @Param("userId") Integer userId);
}

View File

@@ -0,0 +1,23 @@
package com.lightyears.basics.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.lightyears.common.domain.dto.NoticeDto;
import com.lightyears.common.domain.entity.Notice;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* <p>
* Mapper 接口
* </p>
*
* @author hellor
* @since 2022-03-18
*/
@Mapper
public interface NoticeMapper extends BaseMapper<Notice> {
List<NoticeDto> getList(@Param("type") Integer type, @Param("playerId") Integer playerId);
String getContent(@Param("id")Integer id);
}

View File

@@ -0,0 +1,33 @@
package com.lightyears.basics.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.lightyears.common.domain.dto.SimplePlayerAssert;
import com.lightyears.common.domain.entity.PlayerAssets;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* <p>
* Mapper 接口
* </p>
*
* @author hellor
* @since 2022-03-16
*/
@Mapper
public interface PlayerAssetsMapper extends BaseMapper<PlayerAssets> {
// 货币存放服务器
int addGold(@Param("id") int id, @Param("gold") int gold, @Param("version") Long version);
// 从服务器取出货币
int reduceGold(@Param("id") int id,@Param("gold") int gold, @Param("version") Long version);
/**
* 获取用户资产
* @param playerId
* @return
*/
List<SimplePlayerAssert> getPlayerAssets(@Param("playerId") int playerId);
}

View File

@@ -0,0 +1,31 @@
package com.lightyears.basics.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.lightyears.common.domain.entity.Player;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
* <p>
* 扫雷玩家表 Mapper 接口
* </p>
*
* @author hellor
* @since 2022-03-09
*/
@Mapper
public interface PlayerMapper extends BaseMapper<Player> {
/**
* 设置不活跃玩家标记
* @param dateNum 秒数时间戳
* @return
*/
int setInactivePlayer(@Param("dateNum") Long dateNum);
/**
* 设置活跃玩家标记
* @param dateNum 秒数时间戳
* @return
*/
int setActivePlayer(@Param("dateNum") Long dateNum);
}

View File

@@ -0,0 +1,18 @@
package com.lightyears.basics.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.lightyears.common.domain.entity.Record;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* 游戏存档 Mapper 接口
* </p>x
*
* @author hellor
* @since 2022-03-09
*/
@Mapper
public interface RecordMapper extends BaseMapper<Record> {
}

View File

@@ -0,0 +1,75 @@
package com.lightyears.basics.schedule;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.lightyears.basics.mapper.AssertLogMapper;
import com.lightyears.basics.mapper.PlayerMapper;
import com.lightyears.basics.service.ILogService;
import com.lightyears.basics.service.INoticeService;
import com.lightyears.common.domain.entity.AssertLog;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.Date;
@Slf4j
@Component
@RequiredArgsConstructor(onConstructor = @_(@Autowired))
public class BasicsTask {
private final ILogService logService;
private final AssertLogMapper assertLogMapper;
private final INoticeService noticeService;
private final PlayerMapper playerMapper;
/**
* 刷新综合榜数据 5分钟
*/
@Scheduled(cron = "0 */1 * * * ?")
public void refreshComprehensiveRank() {
log.info("-----------刷新排行数据----------");
// 重新计算、缓存综合榜数据
logService.cacheRankList(-1);
}
/**
* 每日 3点执行 删除用户资产log(保留最近7日记录)
*/
@Scheduled(cron = "0 0 3 * * ?")
public void deleteRecords(){
Date date = DateUtil.offsetDay(new Date(), -7);
assertLogMapper.delete(new LambdaQueryWrapper<AssertLog>().lt(AssertLog::getCreateDate, date));
}
/**
* 每日 0点执行 删除用户过期公告
*/
@Scheduled(cron = "0 0 0 * * ?")
public void deleteNotices(){
noticeService.deleteNoticeForTask();
}
/**
* 每月 1号 1点7分执行 标记上月不活跃用户
*/
@Scheduled(cron = "0 7 1 1 * ?")
public void markPlayerActive(){
// 30天前的时间戳
Long time = System.currentTimeMillis() / 1000 - 2592000L;
// 标记上月活跃用户
playerMapper.setActivePlayer(time);
// 标记上月不活跃用户
playerMapper.setInactivePlayer(time);
}
/**
* 每月 1号 1点13分执行 刷新基础排行榜(排除上月不活跃玩家)
*/
@Scheduled(cron = "0 13 1 1 * ?")
public void refreshRankList(){
logService.cacheRankList(null);
}
}

View File

@@ -0,0 +1,42 @@
package com.lightyears.basics.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.lightyears.common.domain.dto.PlayerClearanceLogInfoDto;
import com.lightyears.common.domain.entity.ClearanceLog;
/**
* <p>
* 服务类
* </p>
*
* @author hellor
* @since 2022-06-02
*/
public interface IClearanceLogService extends IService<ClearanceLog> {
/**
* 保存闯关记录
* @param playerId
* @param layersNum
* @param gameData
*/
void saveClearanceLog(Integer playerId, String gameData);
/**
* 获取用户闯关记录
* @param playerId 用户id
* @param playerName 用户名
* @return
*/
PlayerClearanceLogInfoDto getPlayer(Integer playerId, String playerName, Integer type);
/**
* 缓存用户闯关记录
*/
void cachePlayerClearanceRank();
/**
* 删除用户闯关记录缓存
*/
void deletCacheByPlayerId(Integer playerId);
}

View File

@@ -0,0 +1,41 @@
package com.lightyears.basics.service;
import com.lightyears.common.domain.dto.ResModeBase;
import com.lightyears.common.domain.entity.Player;
public interface IGameSystemService {
ResModeBase touristlogin(String open_id);
ResModeBase checkName(String userName);
ResModeBase updateName(int userId, String userName);
ResModeBase pushGoldImpl(Integer userId, int gold, int type, String remark);
ResModeBase pushGold(Integer userId, int gold, int type, String remark);
ResModeBase pullGoldImpl(Integer userId, int gold, int type, String remark);
ResModeBase pullGold(Integer userId, int gold, int type, String remark);
ResModeBase saveFileImpl(int userId, String record, Integer record_type);
ResModeBase saveFile(int userId, String record, Integer record_type);
ResModeBase readFile(int userId, int record_type);
ResModeBase saveLogImpl(Player player, Integer level, int game_time, float bvs3, float bv3, String video, String gameinfo, boolean nf);
ResModeBase saveLog(Player player, Integer level, int game_time, float bvs3, float bv3, String video, String gameinfo, boolean nf);
ResModeBase ranking(int pageIndex, int pageSize, int level);
ResModeBase log(int userId, int level);
ResModeBase getGameData(Integer id, Integer type);
void cancellationAccount(Integer userId);
}

View File

@@ -0,0 +1,35 @@
package com.lightyears.basics.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.lightyears.common.domain.dto.OrdinaryRankDto;
import com.lightyears.common.domain.entity.Log;
import java.util.List;
/**
* <p>
* 游戏 完成记录 表 游戏难度1 - 普通 2 困难 3 大师 服务类
* </p>
*
* @author hellor
* @since 2022-03-09
*/
public interface ILogService extends IService<Log> {
/**
* 查询排行榜
* @param level 游戏难度1 - 普通 2 困难 3 大师
* @return
*/
List<OrdinaryRankDto> getRankList(Integer level);
/**
* 排行榜数据写入缓存
*/
void cacheRankList(Integer level);
/**
* 删除缓存
* @param userId
*/
void deleteCacheByUserId(Integer userId);
}

View File

@@ -0,0 +1,20 @@
package com.lightyears.basics.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.lightyears.common.domain.dto.ResModeBase;
import com.lightyears.common.domain.entity.Notice;
/**
* <p>
* 服务类
* </p>
*
* @author hellor
* @since 2022-03-18
*/
public interface INoticeService extends IService<Notice> {
ResModeBase getList(Integer playerId);
ResModeBase getContent(Integer id);
void deleteNoticeForTask();
}

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