This commit is contained in:
2026-10-24 13:31:43 +08:00
parent ed94879b36
commit 3fef36a721
114 changed files with 5321 additions and 1463 deletions
@@ -15,6 +15,9 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
@@ -32,28 +35,31 @@ public class MybatisPlusConfig {
private RedisUtil redisUtil;
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(HttpServletRequest request) {
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 多租户插件配置
TenantLineHandler tenantLineHandler = new TenantLineHandler() {
@Override
public Expression getTenantId() {
HttpServletRequest request = getCurrentRequest();
// 从域名拿ID
String Domain = request.getHeader("Domain");
if (StrUtil.isNotBlank(Domain)) {
String key = "Domain:" + Domain;
String tenantId = redisUtil.get(key);
if (request != null) {
String Domain = request.getHeader("Domain");
if (StrUtil.isNotBlank(Domain)) {
String key = "Domain:" + Domain;
String tenantId = redisUtil.get(key);
if (tenantId != null) {
System.out.println("从域名拿TID = " + tenantId);
return new LongValue(tenantId);
}
}
// 从请求头拿ID
final String tenantId = request.getHeader("tenantId");
if (tenantId != null) {
System.out.println("从域名拿TID = " + tenantId);
return new LongValue(tenantId);
}
}
// 从请求头拿ID
final String tenantId = request.getHeader("tenantId");
if (tenantId != null) {
return new LongValue(tenantId);
}
// return getLoginUserTenantId();
return new LongValue(10150);
}
@@ -137,7 +143,11 @@ public class MybatisPlusConfig {
"think_wechat_bill_log",
"think_wechat_deposit",
"think_card_balance",
"sys_log"
"sys_log",
"think_small_recharge",
"think_user_in_access",
"think_users_black",
"think_training_institution"
// "booking_user",
// "booking_user_card",
@@ -200,4 +210,12 @@ public class MybatisPlusConfig {
return new NullValue();
}
private HttpServletRequest getCurrentRequest() {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
if (requestAttributes instanceof ServletRequestAttributes) {
return ((ServletRequestAttributes) requestAttributes).getRequest();
}
return null;
}
}
@@ -0,0 +1,23 @@
package com.gxwebsoft.common.core.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
/**
* 定时任务线程池配置
*/
@Configuration
public class SchedulingConfig {
@Bean
public TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(4);
scheduler.setThreadNamePrefix("scheduled-");
scheduler.setWaitForTasksToCompleteOnShutdown(true);
scheduler.setAwaitTerminationSeconds(30);
return scheduler;
}
}
@@ -1,6 +1,7 @@
package com.gxwebsoft.common.core.security;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.common.core.Constants;
@@ -11,6 +12,8 @@ import com.gxwebsoft.common.core.utils.RedisUtil;
import com.gxwebsoft.common.core.utils.SignCheckUtil;
import com.gxwebsoft.common.system.entity.Menu;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.common.system.entity.UserRequestRecord;
import com.gxwebsoft.common.system.service.UserRequestRecordService;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
@@ -25,6 +28,7 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;
@@ -41,6 +45,8 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
private ConfigProperties configProperties;
@Resource
private RedisUtil redisUtil;
@Resource
private UserRequestRecordService userRequestRecordService;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
@@ -83,6 +89,7 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
user, null, authorities);
SecurityContextHolder.getContext().setAuthentication(authentication);
saveUserRequestRecord(user, request);
// token将要过期签发新token, 防止突然退出登录
// long expiration = (claims.getExpiration().getTime() - new Date().getTime()) / 1000 / 60;
@@ -109,4 +116,22 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
chain.doFilter(request, response);
}
/**
* 保存登录用户接口请求记录
*/
private void saveUserRequestRecord(User user, HttpServletRequest request) {
if (user == null || user.getUserId() == null) {
return;
}
UserRequestRecord record = new UserRequestRecord();
record.setUserId(user.getUserId());
record.setPhone(user.getPhone());
record.setUrl(request.getRequestURI());
record.setRequestMethod(request.getMethod());
record.setIp(ServletUtil.getClientIP(request));
record.setTenantId(user.getTenantId());
record.setCreateTime(new Date());
userRequestRecordService.saveAsync(record);
}
}
@@ -81,7 +81,12 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
"/api/think/think-cards-bills/make-bill",
"/api/think/think-recharge-log/refund-notify",
"/api/think/think-ftp-check-bill/async",
"/api/think/think-card-balance/set-data"
"/api/think/think-card-balance/set-data",
"/api/think/think-invoice/getRes",
"/api/think/think-small-recharge/notify",
"/api/shop/balance-charge-log/notify",
"/api/shop/balance-charge-log/refund-notify",
"/api/think/gate-control/**"
// "/api/think/think-order/fixInvoiceData"
)
.permitAll()
@@ -50,6 +50,11 @@ public class RedisUtil {
stringRedisTemplate.opsForValue().set(key, JSONUtil.toJSONString(entity),time,unit);
}
public boolean setIfAbsent(String key, String value, Long time, TimeUnit unit){
Boolean success = stringRedisTemplate.opsForValue().setIfAbsent(key, value, time, unit);
return Boolean.TRUE.equals(success);
}
/**
* 读取redis缓存
* @param key [表名]:id
@@ -23,9 +23,17 @@ import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.imageio.ImageIO;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
@@ -39,6 +47,11 @@ import java.util.List;
@RestController
@RequestMapping("/api/file")
public class FileController extends BaseController {
private static final int FACE_MIN_WIDTH = 480;
private static final int FACE_MIN_HEIGHT = 640;
private static final int FACE_MAX_WIDTH = 1080;
private static final int FACE_MAX_HEIGHT = 1920;
@Resource
private ConfigProperties config;
@Resource
@@ -157,6 +170,39 @@ public class FileController extends BaseController {
}
}
@PreAuthorize("hasAuthority('sys:file:upload')")
@ApiOperation("上传人脸图片并返回base64")
@PostMapping("/upload/face")
public ApiResult<?> uploadFace(@RequestParam MultipartFile file) {
try {
if (file == null || file.isEmpty()) {
return fail("上传失败,文件为空", null);
}
byte[] originalBytes = file.getBytes();
BufferedImage image;
try (ByteArrayInputStream inputStream = new ByteArrayInputStream(originalBytes)) {
image = ImageIO.read(inputStream);
}
if (image == null) {
return fail("上传失败,无法解析图片", null);
}
int width = image.getWidth();
int height = image.getHeight();
boolean inRange = width >= FACE_MIN_WIDTH && height >= FACE_MIN_HEIGHT
&& width <= FACE_MAX_WIDTH && height <= FACE_MAX_HEIGHT;
boolean isJpeg = isJpegImage(file.getContentType(), file.getOriginalFilename());
if (inRange && isJpeg) {
return success(Base64.getEncoder().encodeToString(originalBytes));
}
BufferedImage converted = resizeToRange(toRgbImage(image), width, height);
byte[] jpegBytes = toJpegBytes(converted);
return success("上传成功", Base64.getEncoder().encodeToString(jpegBytes));
} catch (Exception e) {
e.printStackTrace();
return fail("上传失败", null).setError(e.toString());
}
}
@PreAuthorize("hasAuthority('sys:file:list')")
@ApiOperation("根据id查询文件")
@GetMapping("/{id}")
@@ -324,4 +370,61 @@ public class FileController extends BaseController {
return fail("修改失败");
}
private static boolean isJpegImage(String contentType, String fileName) {
if (contentType != null) {
String ct = contentType.toLowerCase();
if (ct.contains("jpeg") || ct.contains("jpg")) {
return true;
}
}
if (fileName != null) {
String lower = fileName.toLowerCase();
return lower.endsWith(".jpg") || lower.endsWith(".jpeg");
}
return false;
}
private static BufferedImage toRgbImage(BufferedImage source) {
if (source.getType() == BufferedImage.TYPE_INT_RGB) {
return source;
}
BufferedImage rgb = new BufferedImage(source.getWidth(), source.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = rgb.createGraphics();
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, rgb.getWidth(), rgb.getHeight());
g2d.drawImage(source, 0, 0, null);
g2d.dispose();
return rgb;
}
private static BufferedImage resizeToRange(BufferedImage image, int width, int height) {
double scale = 1.0;
if (width < FACE_MIN_WIDTH || height < FACE_MIN_HEIGHT) {
scale = Math.max(FACE_MIN_WIDTH / (double) width, FACE_MIN_HEIGHT / (double) height);
} else if (width > FACE_MAX_WIDTH || height > FACE_MAX_HEIGHT) {
scale = Math.min(FACE_MAX_WIDTH / (double) width, FACE_MAX_HEIGHT / (double) height);
} else {
return image;
}
int targetWidth = Math.max(1, (int) Math.round(width * scale));
int targetHeight = Math.max(1, (int) Math.round(height * scale));
BufferedImage resized = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = resized.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.drawImage(image, 0, 0, targetWidth, targetHeight, null);
g2d.dispose();
return resized;
}
private static byte[] toJpegBytes(BufferedImage image) throws Exception {
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
if (!ImageIO.write(image, "jpg", outputStream)) {
throw new IllegalStateException("jpeg encode fail");
}
return outputStream.toByteArray();
}
}
}
@@ -0,0 +1,50 @@
package com.gxwebsoft.common.system.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 用户接口请求记录
*
* @author WebSoft
* @since 2026-07-29
*/
@Data
@ApiModel(description = "用户接口请求记录")
@TableName("sys_user_request_record")
public class UserRequestRecord implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("主键id")
@TableId(type = IdType.AUTO)
private Integer id;
@ApiModelProperty("用户id")
private Integer userId;
@ApiModelProperty("手机号")
private String phone;
@ApiModelProperty("请求接口")
private String url;
@ApiModelProperty("请求方式")
private String requestMethod;
@ApiModelProperty("ip地址")
private String ip;
@ApiModelProperty(value = "租户id")
private Integer tenantId;
@ApiModelProperty("请求时间")
private Date createTime;
}
@@ -0,0 +1,25 @@
package com.gxwebsoft.common.system.mapper;
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.gxwebsoft.common.system.entity.UserRequestRecord;
/**
* 用户接口请求记录Mapper
*
* @author WebSoft
* @since 2026-07-29
*/
public interface UserRequestRecordMapper extends BaseMapper<UserRequestRecord> {
/**
* 添加, 排除租户拦截
*
* @param entity UserRequestRecord
* @return int
*/
@Override
@InterceptorIgnore(tenantLine = "true")
int insert(UserRequestRecord entity);
}
@@ -0,0 +1,21 @@
package com.gxwebsoft.common.system.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.gxwebsoft.common.system.entity.UserRequestRecord;
/**
* 用户接口请求记录Service
*
* @author WebSoft
* @since 2026-07-29
*/
public interface UserRequestRecordService extends IService<UserRequestRecord> {
/**
* 异步添加
*
* @param userRequestRecord UserRequestRecord
*/
void saveAsync(UserRequestRecord userRequestRecord);
}
@@ -1,11 +1,13 @@
package com.gxwebsoft.common.system.service;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.extension.service.IService;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.common.system.param.UserParam;
import org.springframework.security.core.userdetails.UserDetailsService;
import java.math.BigDecimal;
import java.util.List;
/**
@@ -99,6 +101,27 @@ public interface UserService extends IService<User>, UserDetailsService {
User getByUnionId(UserParam userParam);
@DS("server")
User getByIdInner(Integer id);
@DS("server")
User getByUidInner(Integer uid);
@DS("server")
User getByPhoneInner(String phone);
@DS("server")
List<User> listByPhoneInner(String phone);
@DS("server")
List<User> listByIdsInner(List<Integer> userIds);
@DS("server")
Boolean updateInner(User user);
@DS("server")
User addBalanceInner(Integer userId, BigDecimal amount);
User getByOauthId(UserParam userParam);
List<User> listStatisticsRel(UserParam param);
@@ -0,0 +1,29 @@
package com.gxwebsoft.common.system.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gxwebsoft.common.system.entity.UserRequestRecord;
import com.gxwebsoft.common.system.mapper.UserRequestRecordMapper;
import com.gxwebsoft.common.system.service.UserRequestRecordService;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
/**
* 用户接口请求记录Service实现
*
* @author WebSoft
* @since 2026-07-29
*/
@Service
public class UserRequestRecordServiceImpl extends ServiceImpl<UserRequestRecordMapper, UserRequestRecord>
implements UserRequestRecordService {
@Async
@Override
public void saveAsync(UserRequestRecord userRequestRecord) {
if (userRequestRecord == null || userRequestRecord.getUserId() == null) {
return;
}
baseMapper.insert(userRequestRecord);
}
}
@@ -1,7 +1,7 @@
package com.gxwebsoft.common.system.service.impl;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -17,7 +17,6 @@ import com.gxwebsoft.common.system.param.UserParam;
import com.gxwebsoft.common.system.service.RoleMenuService;
import com.gxwebsoft.common.system.service.UserRoleService;
import com.gxwebsoft.common.system.service.UserService;
import com.gxwebsoft.oa.entity.Company;
import com.gxwebsoft.oa.service.CompanyService;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
@@ -27,9 +26,8 @@ import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.HashMap;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
@@ -193,6 +191,59 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
return param.getOne(baseMapper.getOne(param));
}
@Override
@DS("server")
public User getByIdInner(Integer id) {
return getOne(new LambdaQueryWrapper<User>().eq(User::getUserId, id));
}
@DS("server")
@Override
public User getByUidInner(Integer uid) {
return getOne(new LambdaQueryWrapper<User>().eq(User::getUid, uid));
}
@Override
@DS("server")
public User getByPhoneInner(String phone) {
return getOne(new LambdaQueryWrapper<User>().eq(User::getPhone, phone));
}
@Override
@DS("server")
public List<User> listByPhoneInner(String phone) {
return list(new LambdaQueryWrapper<User>()
.like(User::getPhone, phone)
.select(User::getUserId, User::getPhone));
}
@Override
@DS("server")
public List<User> listByIdsInner(List<Integer> userIds) {
return list(new LambdaQueryWrapper<User>()
.in(User::getUserId, userIds)
.select(User::getUserId, User::getPhone));
}
@Override
@DS("server")
public Boolean updateInner(User user) {
return updateById(user);
}
@Override
@DS("server")
public User addBalanceInner(Integer userId, BigDecimal amount) {
User user = getOne(new LambdaQueryWrapper<User>().eq(User::getUserId, userId));
if (user == null) {
return null;
}
BigDecimal currentBalance = user.getBalance() == null ? BigDecimal.ZERO : user.getBalance();
user.setBalance(currentBalance.add(amount));
updateById(user);
return user;
}
@Override
public User getByOauthId(UserParam userParam) {
return userParam.getOne(baseMapper.getOne(userParam));
@@ -0,0 +1,352 @@
package com.gxwebsoft.shop.controller;
import cn.hutool.core.util.RandomUtil;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.common.system.service.UserService;
import com.gxwebsoft.shop.entity.UserBalanceLog;
import com.gxwebsoft.shop.service.UserBalanceLogService;
import com.gxwebsoft.shop.service.BalanceChargeLogService;
import com.gxwebsoft.shop.entity.BalanceChargeLog;
import com.gxwebsoft.shop.param.BalanceChargeLogParam;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.core.web.BatchParam;
import com.gxwebsoft.think.service.ThinkOrderService;
import com.gxwebsoft.think.service.WechatConfigService;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.refund.RefundService;
import com.wechat.pay.java.service.refund.model.AmountReq;
import com.wechat.pay.java.service.refund.model.CreateRequest;
import com.wechat.pay.java.service.refund.model.RefundNotification;
import com.wechat.pay.java.service.refund.model.Status;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
/**
* 控制器
*
* @author LX
* @since 2026-05-07 14:57:22
*/
@Api(tags = "管理")
@RestController
@RequestMapping("/api/shop/balance-charge-log")
public class BalanceChargeLogController extends BaseController {
private static final DateTimeFormatter ORDER_NO_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
@Resource
private BalanceChargeLogService balanceChargeLogService;
@Resource
private ThinkOrderService thinkOrderService;
@Resource
private WechatConfigService wechatConfigService;
@Resource
private UserService userService;
@Resource
private UserBalanceLogService userBalanceLogService;
@ApiOperation("分页查询")
@GetMapping("/page")
public ApiResult<PageResult<BalanceChargeLog>> page(BalanceChargeLogParam param) {
// 使用关联查询
return success(balanceChargeLogService.pageRel(param));
}
@ApiOperation("查询全部")
@GetMapping()
public ApiResult<List<BalanceChargeLog>> list(BalanceChargeLogParam param) {
// 使用关联查询
return success(balanceChargeLogService.listRel(param));
}
@PreAuthorize("hasAuthority('shop:balanceChargeLog:list')")
@ApiOperation("根据id查询")
@GetMapping("/{id}")
public ApiResult<BalanceChargeLog> get(@PathVariable("id") Integer id) {
// 使用关联查询
return success(balanceChargeLogService.getByIdRel(id));
}
@Transactional(rollbackFor = Exception.class)
@ApiOperation("余额充值")
@PostMapping("/recharge")
public ApiResult<?> recharge(@RequestBody BalanceChargeLog balanceChargeLog) {
if (getLoginUserId() == null) {
return fail("请先登录");
}
if (balanceChargeLog.getAmount() == null || balanceChargeLog.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
return fail("充值金额必须大于0");
}
User loginUser = getLoginUser();
if (loginUser == null || loginUser.getOpenid() == null || loginUser.getOpenid().trim().isEmpty()) {
return fail("当前账号未绑定微信");
}
LocalDateTime now = LocalDateTime.now();
BalanceChargeLog chargeLog = new BalanceChargeLog();
chargeLog.setAmount(balanceChargeLog.getAmount().setScale(2, RoundingMode.HALF_UP));
chargeLog.setUserId(getLoginUserId());
chargeLog.setTenantId(getTenantId());
chargeLog.setIsPaid(0);
chargeLog.setRemark(balanceChargeLog.getRemark() == null || balanceChargeLog.getRemark().trim().isEmpty()
? "用户余额充值"
: balanceChargeLog.getRemark().trim());
chargeLog.setOrderNo(ORDER_NO_FORMATTER.format(now) + RandomUtil.randomNumbers(5));
chargeLog.setCreateTime(now);
chargeLog.setUpdateTime(now);
if (balanceChargeLogService.save(chargeLog)) {
String notify = "https://gxtyzx-api2.websoft.top/api/shop/balance-charge-log/notify";
return success("下单成功", thinkOrderService.createWxOrder(
chargeLog.getAmount(),
chargeLog.getOrderNo(),
"账户余额充值",
loginUser.getOpenid(),
notify
));
}
return fail("下单失败");
}
@ApiOperation("添加")
@PostMapping()
public ApiResult<?> save(@RequestBody BalanceChargeLog balanceChargeLog) {
if (balanceChargeLogService.save(balanceChargeLog)) {
return success("添加成功");
}
return fail("添加失败");
}
@ApiOperation("修改")
@PutMapping()
public ApiResult<?> update(@RequestBody BalanceChargeLog balanceChargeLog) {
if (balanceChargeLogService.updateById(balanceChargeLog)) {
return success("修改成功");
}
return fail("修改失败");
}
@ApiOperation("退款")
@PostMapping("/refund")
public ApiResult<?> refund(@RequestBody BalanceChargeLog balanceChargeLog) {
if (balanceChargeLog.getId() == null) {
return fail("请选择退款记录");
}
BalanceChargeLog chargeLog = balanceChargeLogService.getById(balanceChargeLog.getId());
if (chargeLog == null) {
return fail("充值记录不存在");
}
if (chargeLog.getIsPaid() == null || chargeLog.getIsPaid() != 1) {
return fail("只有已支付的充值记录可以退款");
}
if (chargeLog.getAmount() == null || chargeLog.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
return fail("退款金额异常");
}
if (chargeLog.getOrderNo() == null || chargeLog.getOrderNo().trim().isEmpty()) {
return fail("充值订单号为空");
}
User user = userService.getByIdInner(chargeLog.getUserId());
if (user == null) {
return fail("充值用户不存在");
}
BigDecimal currentBalance = user.getBalance() == null ? BigDecimal.ZERO : user.getBalance();
if (currentBalance.compareTo(chargeLog.getAmount()) < 0) {
return fail("用户余额不足,无法退款");
}
Config wxConfig = wechatConfigService.getConfig();
RefundService service = new RefundService.Builder().config(wxConfig).build();
CreateRequest request = new CreateRequest();
AmountReq amount = new AmountReq();
long refundAmount = chargeLog.getAmount()
.multiply(BigDecimal.valueOf(100))
.setScale(0, RoundingMode.HALF_UP)
.longValue();
amount.setTotal(refundAmount);
amount.setRefund(refundAmount);
amount.setCurrency("CNY");
request.setAmount(amount);
request.setOutTradeNo(chargeLog.getOrderNo());
request.setOutRefundNo("R" + chargeLog.getOrderNo());
request.setNotifyUrl("https://gxtyzx-api2.websoft.top/api/shop/balance-charge-log/refund-notify");
service.create(request);
return success("退款申请已提交");
}
@ApiOperation("删除")
@DeleteMapping("/{id}")
public ApiResult<?> remove(@PathVariable("id") Integer id) {
if (balanceChargeLogService.removeById(id)) {
return success("删除成功");
}
return fail("删除失败");
}
@ApiOperation("批量添加")
@PostMapping("/batch")
public ApiResult<?> saveBatch(@RequestBody List<BalanceChargeLog> list) {
if (balanceChargeLogService.saveBatch(list)) {
return success("添加成功");
}
return fail("添加失败");
}
@ApiOperation("批量修改")
@PutMapping("/batch")
public ApiResult<?> removeBatch(@RequestBody BatchParam<BalanceChargeLog> batchParam) {
if (batchParam.update(balanceChargeLogService, "id")) {
return success("修改成功");
}
return fail("修改失败");
}
@ApiOperation("批量删除")
@DeleteMapping("/batch")
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
if (balanceChargeLogService.removeByIds(ids)) {
return success("删除成功");
}
return fail("删除失败");
}
@ApiOperation("微信支付回调")
@PostMapping("/notify")
public String notify(@RequestBody String body, @RequestHeader Map<String, Object> header) {
try {
RequestParam requestParam = new RequestParam.Builder()
.serialNumber(header.get("wechatpay-serial").toString())
.nonce(header.get("wechatpay-nonce").toString())
.signature(header.get("wechatpay-signature").toString())
.timestamp(header.get("wechatpay-timestamp").toString())
.body(body)
.build();
NotificationConfig config = wechatConfigService.getNotificationConfig();
NotificationParser parser = new NotificationParser(config);
com.wechat.pay.java.service.payments.model.Transaction transaction =
parser.parse(requestParam, com.wechat.pay.java.service.payments.model.Transaction.class);
BalanceChargeLog chargeLog = balanceChargeLogService.lambdaQuery()
.eq(BalanceChargeLog::getOrderNo, transaction.getOutTradeNo())
.last("limit 1")
.one();
System.out.println("充值回调:" + transaction);
System.out.println("chargeLog:" + chargeLog);
if (chargeLog != null && (chargeLog.getIsPaid() == null || chargeLog.getIsPaid() == 0)) {
doCharge(chargeLog, transaction.getTransactionId());
}
return "订单已支付";
}catch (Exception e){
System.out.println("充值回调错误:" + e.getMessage());
return e.getMessage();
}
}
@ApiOperation("微信退款回调")
@PostMapping("/refund-notify")
public ApiResult<?> refundNotify(@RequestBody String body, @RequestHeader Map<String, Object> header) {
try {
RequestParam requestParam = new RequestParam.Builder()
.serialNumber(header.get("wechatpay-serial").toString())
.nonce(header.get("wechatpay-nonce").toString())
.signature(header.get("wechatpay-signature").toString())
.timestamp(header.get("wechatpay-timestamp").toString())
.body(body)
.build();
NotificationConfig config = wechatConfigService.getNotificationConfig();
NotificationParser parser = new NotificationParser(config);
RefundNotification notification = parser.parse(requestParam, RefundNotification.class);
System.out.println("充值退款回调:" + notification);
if (notification.getRefundStatus().equals(Status.SUCCESS)) {
String refundNo = notification.getOutRefundNo();
String orderNo = refundNo != null && refundNo.startsWith("R") ? refundNo.substring(1) : refundNo;
BalanceChargeLog chargeLog = balanceChargeLogService.lambdaQuery()
.eq(BalanceChargeLog::getOrderNo, orderNo)
.last("limit 1")
.one();
if (chargeLog != null && chargeLog.getIsPaid() != null && chargeLog.getIsPaid() == 1) {
doRefund(chargeLog);
}
}
return success();
} catch (Exception e) {
System.out.println("充值退款回调错误:" + e.getMessage());
return fail(e.getMessage());
}
}
protected void doCharge(BalanceChargeLog chargeLog, String transactionId) {
System.out.println("here doCharge");
LocalDateTime now = LocalDateTime.now();
chargeLog.setIsPaid(1);
chargeLog.setPaidNumber(transactionId);
chargeLog.setUpdateTime(now);
balanceChargeLogService.updateById(chargeLog);
User user = userService.getByIdInner(chargeLog.getUserId());
if (user == null) {
return;
}
BigDecimal currentBalance = user.getBalance() == null ? BigDecimal.ZERO : user.getBalance();
BigDecimal latestBalance = currentBalance.add(chargeLog.getAmount());
user.setBalance(latestBalance);
userService.updateInner(user);
UserBalanceLog userBalanceLog = new UserBalanceLog();
userBalanceLog.setUserId(user.getUserId());
userBalanceLog.setScene(0);
userBalanceLog.setMoney(chargeLog.getAmount());
userBalanceLog.setBalance(latestBalance);
userBalanceLog.setRemark("余额充值");
userBalanceLog.setComments("充值订单号:" + chargeLog.getOrderNo());
userBalanceLog.setStatus(0);
userBalanceLog.setDeleted(0);
userBalanceLog.setTenantId(chargeLog.getTenantId());
userBalanceLog.setCreateTime(now);
userBalanceLog.setUpdateTime(now);
userBalanceLogService.save(userBalanceLog);
}
protected void doRefund(BalanceChargeLog chargeLog) {
LocalDateTime now = LocalDateTime.now();
User user = userService.getByIdInner(chargeLog.getUserId());
if (user == null) {
return;
}
BigDecimal currentBalance = user.getBalance() == null ? BigDecimal.ZERO : user.getBalance();
BigDecimal latestBalance = currentBalance.subtract(chargeLog.getAmount());
user.setBalance(latestBalance);
userService.updateInner(user);
chargeLog.setIsPaid(2);
chargeLog.setUpdateTime(now);
balanceChargeLogService.updateById(chargeLog);
UserBalanceLog userBalanceLog = new UserBalanceLog();
userBalanceLog.setUserId(user.getUserId());
userBalanceLog.setScene(2);
userBalanceLog.setMoney(chargeLog.getAmount().negate());
userBalanceLog.setBalance(latestBalance);
userBalanceLog.setRemark("余额充值退款");
userBalanceLog.setComments("充值退款订单号:R" + chargeLog.getOrderNo());
userBalanceLog.setStatus(0);
userBalanceLog.setDeleted(0);
userBalanceLog.setTenantId(chargeLog.getTenantId());
userBalanceLog.setCreateTime(now);
userBalanceLog.setUpdateTime(now);
userBalanceLogService.save(userBalanceLog);
}
}
@@ -1,187 +0,0 @@
package com.gxwebsoft.shop.controller;
import cn.hutool.core.util.IdUtil;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.common.system.service.UserService;
import com.gxwebsoft.shop.entity.UserBalanceLog;
import com.gxwebsoft.shop.service.RechargeOrderService;
import com.gxwebsoft.shop.entity.RechargeOrder;
import com.gxwebsoft.shop.param.RechargeOrderParam;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.core.web.PageParam;
import com.gxwebsoft.common.core.web.BatchParam;
import com.gxwebsoft.common.core.annotation.OperationLog;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.shop.service.UserBalanceLogService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import static com.gxwebsoft.common.core.constants.BalanceConstants.BALANCE_ADMIN;
/**
* 会员充值订单表控制器
*
* @author 科技小王子
* @since 2024-07-26 23:18:48
*/
@Api(tags = "会员充值订单表管理")
@RestController
@RequestMapping("/api/shop/recharge-order")
public class RechargeOrderController extends BaseController {
@Resource
private RechargeOrderService rechargeOrderService;
@Resource
private UserService userService;
@Resource
private UserBalanceLogService userBalanceLogService;
@PreAuthorize("hasAuthority('shop:rechargeOrder:save')")
@ApiOperation("会员充值")
@PostMapping("/recharge")
@Transactional(rollbackFor = {Exception.class})
public ApiResult<?> recharge(@RequestBody RechargeOrder rechargeOrder) {
// 充值
User user = userService.getById(rechargeOrder.getUserId());
BigDecimal balance = user.getBalance().add(rechargeOrder.getPayPrice());
user.setBalance(balance);
userService.updateById(user);
// 保存充值记录
rechargeOrder.setOrderNo(Long.toString(IdUtil.getSnowflakeNextId()));
rechargeOrder.setBalance(balance);
if (rechargeOrderService.save(rechargeOrder)) {
// 记录余额明细
UserBalanceLog userBalanceLog = new UserBalanceLog();
userBalanceLog.setUserId(rechargeOrder.getUserId());
userBalanceLog.setScene(BALANCE_ADMIN);
userBalanceLog.setMoney(rechargeOrder.getPayPrice());
userBalanceLog.setBalance(balance);
userBalanceLog.setComments("操作人:" + getLoginUser().getNickname());
userBalanceLog.setRemark(rechargeOrder.getComments());
userBalanceLog.setMerchantCode(rechargeOrder.getMerchantCode());
userBalanceLogService.save(userBalanceLog);
return success("充值成功", user);
}
return fail("充值失败");
}
@PreAuthorize("hasAuthority('shop:rechargeOrder:list')")
@ApiOperation("分页查询会员充值订单表")
@GetMapping("/page")
public ApiResult<PageResult<RechargeOrder>> page(RechargeOrderParam param) {
// 使用关联查询
return success(rechargeOrderService.pageRel(param));
}
@PreAuthorize("hasAuthority('shop:rechargeOrder:list')")
@ApiOperation("查询全部会员充值订单表")
@GetMapping()
public ApiResult<List<RechargeOrder>> list(RechargeOrderParam param) {
// 使用关联查询
return success(rechargeOrderService.listRel(param));
}
@PreAuthorize("hasAuthority('shop:rechargeOrder:list')")
@ApiOperation("根据id查询会员充值订单表")
@GetMapping("/{id}")
public ApiResult<RechargeOrder> get(@PathVariable("id") Integer id) {
// 使用关联查询
return success(rechargeOrderService.getByIdRel(id));
}
@ApiOperation("添加会员充值订单表")
@PostMapping()
public ApiResult<?> save(@RequestBody RechargeOrder rechargeOrder) {
// 记录当前登录用户id
User loginUser = getLoginUser();
if (loginUser != null) {
rechargeOrder.setUserId(loginUser.getUserId());
}
if (rechargeOrderService.save(rechargeOrder)) {
return success("添加成功");
}
return fail("添加失败");
}
@ApiOperation("修改会员充值订单表")
@PutMapping()
public ApiResult<?> update(@RequestBody RechargeOrder rechargeOrder) {
if (rechargeOrderService.updateById(rechargeOrder)) {
return success("修改成功");
}
return fail("修改失败");
}
@ApiOperation("删除会员充值订单表")
@DeleteMapping("/{id}")
public ApiResult<?> remove(@PathVariable("id") Integer id) {
if (rechargeOrderService.removeById(id)) {
return success("删除成功");
}
return fail("删除失败");
}
@PreAuthorize("hasAuthority('shop:rechargeOrder:save')")
@ApiOperation("批量充值")
@PostMapping("/batchRecharge")
@Transactional(rollbackFor = {Exception.class})
public ApiResult<?> batchRecharge(@RequestBody List<RechargeOrder> list) {
if (rechargeOrderService.saveBatch(list)) {
String nickname = getLoginUser().getNickname();
ArrayList<User> users = new ArrayList<>(list.size());
ArrayList<UserBalanceLog> logs = new ArrayList<>(list.size());
list.forEach(d -> {
User user = userService.getByIdRel(d.getUserId());
BigDecimal balance = user.getBalance().add(d.getPayPrice());
user.setBalance(balance);
users.add(user);
UserBalanceLog userBalanceLog = new UserBalanceLog();
userBalanceLog.setUserId(d.getUserId());
userBalanceLog.setScene(BALANCE_ADMIN);
userBalanceLog.setMoney(d.getPayPrice());
userBalanceLog.setBalance(balance);
userBalanceLog.setComments("操作人:" + nickname);
userBalanceLog.setRemark(d.getComments());
userBalanceLog.setMerchantCode(d.getMerchantCode());
logs.add(userBalanceLog);
});
// 批量充值
userService.updateBatchById(users);
// 记录余额明细
userBalanceLogService.saveBatch(logs);
return success("充值成功");
}
return fail("充值失败");
}
@PreAuthorize("hasAuthority('shop:rechargeOrder:update')")
@ApiOperation("批量修改会员充值订单表")
@PutMapping("/batch")
public ApiResult<?> removeBatch(@RequestBody BatchParam<RechargeOrder> batchParam) {
if (batchParam.update(rechargeOrderService, "order_id")) {
return success("修改成功");
}
return fail("修改失败");
}
@PreAuthorize("hasAuthority('shop:rechargeOrder:remove')")
@ApiOperation("批量删除会员充值订单表")
@DeleteMapping("/batch")
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
if (rechargeOrderService.removeByIds(ids)) {
return success("删除成功");
}
return fail("删除失败");
}
}
@@ -10,19 +10,23 @@ import com.gxwebsoft.common.core.web.PageParam;
import com.gxwebsoft.common.core.web.BatchParam;
import com.gxwebsoft.common.core.annotation.OperationLog;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.common.system.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import static com.gxwebsoft.common.core.constants.BalanceConstants.BALANCE_ADMIN;
/**
* 用户余额变动明细表控制器
*
* @author 科技小王子
* @since 2024-05-29 15:57:44
* @author LX
* @since 2026-05-07 14:57:22
*/
@Api(tags = "用户余额变动明细表管理")
@RestController
@@ -30,6 +34,8 @@ import java.util.List;
public class UserBalanceLogController extends BaseController {
@Resource
private UserBalanceLogService userBalanceLogService;
@Resource
private UserService userService;
@ApiOperation("分页查询用户余额变动明细表")
@GetMapping("/page")
@@ -56,10 +62,33 @@ public class UserBalanceLogController extends BaseController {
@ApiOperation("添加用户余额变动明细表")
@PostMapping()
public ApiResult<?> save(@RequestBody UserBalanceLog userBalanceLog) {
// 记录当前登录用户id
if (userBalanceLog.getUserId() == null) {
return fail("用户ID不能为空");
}
if (userBalanceLog.getMoney() == null || userBalanceLog.getMoney().compareTo(BigDecimal.ZERO) <= 0) {
return fail("充值金额必须大于0");
}
User user = userService.addBalanceInner(userBalanceLog.getUserId(), userBalanceLog.getMoney());
if (user == null) {
return fail("用户不存在");
}
User loginUser = getLoginUser();
if (loginUser != null) {
userBalanceLog.setUserId(loginUser.getUserId());
if (userBalanceLog.getScene() == null) {
userBalanceLog.setScene(BALANCE_ADMIN);
}
userBalanceLog.setBalance(user.getBalance());
if (loginUser != null && userBalanceLog.getAdminId() == null) {
userBalanceLog.setAdminId(loginUser.getUserId());
}
if ((userBalanceLog.getComments() == null || userBalanceLog.getComments().trim().isEmpty())
&& userBalanceLog.getRemark() != null) {
userBalanceLog.setComments(userBalanceLog.getRemark());
}
if (userBalanceLog.getStatus() == null) {
userBalanceLog.setStatus(0);
}
if (userBalanceLog.getDeleted() == null) {
userBalanceLog.setDeleted(0);
}
if (userBalanceLogService.save(userBalanceLog)) {
return success("添加成功");
@@ -0,0 +1,57 @@
package com.gxwebsoft.shop.entity;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableField;
import java.time.LocalDateTime;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
*
*
* @author LX
* @since 2026-05-07 14:57:22
*/
@Data
@EqualsAndHashCode(callSuper = false)
@ApiModel(value = "BalanceChargeLog对象", description = "")
@TableName("shop_balance_charge_log")
public class BalanceChargeLog implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
private BigDecimal amount;
private String orderNo;
@ApiModelProperty(value = "0未支付,1已支付,2已退款")
private Integer isPaid;
private String paidNumber;
private Integer userId;
@ApiModelProperty(value = "手机号")
@TableField(exist = false)
private String phone;
@ApiModelProperty(value = "商城ID")
private Integer tenantId;
@ApiModelProperty(value = "创建时间")
private LocalDateTime createTime;
@ApiModelProperty(value = "修改时间")
private LocalDateTime updateTime;
private String remark;
}
@@ -1,104 +0,0 @@
package com.gxwebsoft.shop.entity;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.TableLogic;
import java.io.Serializable;
import java.util.Date;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 会员充值订单表
*
* @author 科技小王子
* @since 2024-07-26 23:18:48
*/
@Data
@EqualsAndHashCode(callSuper = false)
@ApiModel(value = "RechargeOrder对象", description = "会员充值订单表")
@TableName("shop_recharge_order")
public class RechargeOrder implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "订单ID")
@TableId(value = "order_id", type = IdType.AUTO)
private Integer orderId;
@ApiModelProperty(value = "订单号")
private String orderNo;
@ApiModelProperty(value = "用户ID")
private Integer userId;
@ApiModelProperty(value = "充值方式(10自定义金额 20套餐充值)")
private Integer rechargeType;
@ApiModelProperty(value = "机构id")
private Integer organizationId;
@ApiModelProperty(value = "充值套餐ID")
private Integer planId;
@ApiModelProperty(value = "用户支付金额")
private BigDecimal payPrice;
@ApiModelProperty(value = "赠送金额")
private BigDecimal giftMoney;
@ApiModelProperty(value = "实际到账金额")
private BigDecimal actualMoney;
@ApiModelProperty(value = "用户可用余额")
private BigDecimal balance;
@ApiModelProperty(value = "支付方式(微信/支付宝)")
private String payMethod;
@ApiModelProperty(value = "支付状态(10待支付 20已支付)")
private Integer payStatus;
@ApiModelProperty(value = "付款时间")
private Integer payTime;
@ApiModelProperty(value = "第三方交易记录ID")
private Integer tradeId;
@ApiModelProperty(value = "来源客户端 (APP、H5、小程序等)")
private String platform;
@ApiModelProperty(value = "所属门店ID")
private Integer shopId;
@ApiModelProperty(value = "排序(数字越小越靠前)")
private Integer sortNumber;
@ApiModelProperty(value = "备注")
private String comments;
@ApiModelProperty(value = "状态, 0正常, 1冻结")
private Integer status;
@ApiModelProperty(value = "是否删除, 0否, 1是")
@TableLogic
private Integer deleted;
@ApiModelProperty(value = "商户编码")
private String merchantCode;
@ApiModelProperty(value = "租户id")
private Integer tenantId;
@ApiModelProperty(value = "注册时间")
private Date createTime;
@ApiModelProperty(value = "修改时间")
private Date updateTime;
}
@@ -7,8 +7,6 @@ import com.baomidou.mybatisplus.annotation.TableId;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.TableLogic;
import java.io.Serializable;
import java.util.Date;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@@ -17,8 +15,8 @@ import lombok.EqualsAndHashCode;
/**
* 用户余额变动明细表
*
* @author 科技小王子
* @since 2024-05-29 15:57:44
* @author LX
* @since 2026-05-07 14:57:22
*/
@Data
@EqualsAndHashCode(callSuper = false)
@@ -34,7 +32,7 @@ public class UserBalanceLog implements Serializable {
@ApiModelProperty(value = "用户ID")
private Integer userId;
@ApiModelProperty(value = "余额变动场景(10用户充值 20用户消费 30管理员操作 40订单退款)")
@ApiModelProperty(value = "余额变动场景(0 用户充值 1用户消费 2管理员操作 3订单退款)")
private Integer scene;
@ApiModelProperty(value = "变动金额")
@@ -46,15 +44,11 @@ public class UserBalanceLog implements Serializable {
@ApiModelProperty(value = "管理员备注")
private String remark;
private Integer orderId;
@ApiModelProperty(value = "操作人ID")
private Integer adminId;
@ApiModelProperty(value = "订单编号")
private String orderNo;
@ApiModelProperty(value = "商户ID")
private Integer merchantId;
@ApiModelProperty(value = "排序(数字越小越靠前)")
private Integer sortNumber;
@@ -68,16 +62,13 @@ public class UserBalanceLog implements Serializable {
@TableLogic
private Integer deleted;
@ApiModelProperty(value = "商户编码")
private String merchantCode;
@ApiModelProperty(value = "租户id")
private Integer tenantId;
@ApiModelProperty(value = "注册时间")
private Date createTime;
private LocalDateTime createTime;
@ApiModelProperty(value = "修改时间")
private Date updateTime;
private LocalDateTime updateTime;
}
@@ -0,0 +1,37 @@
package com.gxwebsoft.shop.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.gxwebsoft.shop.entity.BalanceChargeLog;
import com.gxwebsoft.shop.param.BalanceChargeLogParam;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* Mapper
*
* @author LX
* @since 2026-05-07 14:57:22
*/
public interface BalanceChargeLogMapper extends BaseMapper<BalanceChargeLog> {
/**
* 分页查询
*
* @param page 分页对象
* @param param 查询参数
* @return List<BalanceChargeLog>
*/
List<BalanceChargeLog> selectPageRel(@Param("page") IPage<BalanceChargeLog> page,
@Param("param") BalanceChargeLogParam param);
/**
* 查询全部
*
* @param param 查询参数
* @return List<User>
*/
List<BalanceChargeLog> selectListRel(@Param("param") BalanceChargeLogParam param);
}
@@ -1,37 +0,0 @@
package com.gxwebsoft.shop.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.gxwebsoft.shop.entity.RechargeOrder;
import com.gxwebsoft.shop.param.RechargeOrderParam;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 会员充值订单表Mapper
*
* @author 科技小王子
* @since 2024-07-26 23:18:48
*/
public interface RechargeOrderMapper extends BaseMapper<RechargeOrder> {
/**
* 分页查询
*
* @param page 分页对象
* @param param 查询参数
* @return List<RechargeOrder>
*/
List<RechargeOrder> selectPageRel(@Param("page") IPage<RechargeOrder> page,
@Param("param") RechargeOrderParam param);
/**
* 查询全部
*
* @param param 查询参数
* @return List<User>
*/
List<RechargeOrder> selectListRel(@Param("param") RechargeOrderParam param);
}
@@ -11,8 +11,8 @@ import java.util.List;
/**
* 用户余额变动明细表Mapper
*
* @author 科技小王子
* @since 2024-05-29 15:57:44
* @author LX
* @since 2026-05-07 14:57:22
*/
public interface UserBalanceLogMapper extends BaseMapper<UserBalanceLog> {
@@ -0,0 +1,60 @@
<?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.gxwebsoft.shop.mapper.BalanceChargeLogMapper">
<!-- 关联查询sql -->
<sql id="selectSql">
SELECT a.*
FROM shop_balance_charge_log a
<where>
<if test="param.id != null">
AND a.id = #{param.id}
</if>
<if test="param.amount != null">
AND a.amount = #{param.amount}
</if>
<if test="param.orderNo != null">
AND a.order_no LIKE CONCAT('%', #{param.orderNo}, '%')
</if>
<if test="param.isPaid != null">
AND a.is_paid = #{param.isPaid}
</if>
<if test="param.paidNumber != null">
AND a.paid_number LIKE CONCAT('%', #{param.paidNumber}, '%')
</if>
<if test="param.userId != null">
AND a.user_id = #{param.userId}
</if>
<if test="param.userIds != null and param.userIds.size > 0">
AND a.user_id IN
<foreach collection="param.userIds" item="userId" open="(" separator="," close=")">
#{userId}
</foreach>
</if>
<if test="param.createTimeStart != null">
AND a.create_time &gt;= #{param.createTimeStart}
</if>
<if test="param.createTimeEnd != null">
AND a.create_time &lt;= #{param.createTimeEnd}
</if>
<if test="param.remark != null">
AND a.remark LIKE CONCAT('%', #{param.remark}, '%')
</if>
<if test="param.keywords != null">
AND (a.order_no LIKE CONCAT('%', #{param.keywords}, '%')
)
</if>
</where>
</sql>
<!-- 分页查询 -->
<select id="selectPageRel" resultType="com.gxwebsoft.shop.entity.BalanceChargeLog">
<include refid="selectSql"></include>
</select>
<!-- 查询全部 -->
<select id="selectListRel" resultType="com.gxwebsoft.shop.entity.BalanceChargeLog">
<include refid="selectSql"></include>
</select>
</mapper>
@@ -1,99 +0,0 @@
<?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.gxwebsoft.shop.mapper.RechargeOrderMapper">
<!-- 关联查询sql -->
<sql id="selectSql">
SELECT a.*
FROM shop_recharge_order a
<where>
<if test="param.orderId != null">
AND a.order_id = #{param.orderId}
</if>
<if test="param.orderNo != null">
AND a.order_no LIKE CONCAT('%', #{param.orderNo}, '%')
</if>
<if test="param.userId != null">
AND a.user_id = #{param.userId}
</if>
<if test="param.rechargeType != null">
AND a.recharge_type = #{param.rechargeType}
</if>
<if test="param.organizationId != null">
AND a.organization_id = #{param.organizationId}
</if>
<if test="param.planId != null">
AND a.plan_id = #{param.planId}
</if>
<if test="param.payPrice != null">
AND a.pay_price = #{param.payPrice}
</if>
<if test="param.giftMoney != null">
AND a.gift_money = #{param.giftMoney}
</if>
<if test="param.actualMoney != null">
AND a.actual_money = #{param.actualMoney}
</if>
<if test="param.balance != null">
AND a.balance = #{param.balance}
</if>
<if test="param.payMethod != null">
AND a.pay_method LIKE CONCAT('%', #{param.payMethod}, '%')
</if>
<if test="param.payStatus != null">
AND a.pay_status = #{param.payStatus}
</if>
<if test="param.payTime != null">
AND a.pay_time = #{param.payTime}
</if>
<if test="param.tradeId != null">
AND a.trade_id = #{param.tradeId}
</if>
<if test="param.platform != null">
AND a.platform LIKE CONCAT('%', #{param.platform}, '%')
</if>
<if test="param.shopId != null">
AND a.shop_id = #{param.shopId}
</if>
<if test="param.sortNumber != null">
AND a.sort_number = #{param.sortNumber}
</if>
<if test="param.comments != null">
AND a.comments LIKE CONCAT('%', #{param.comments}, '%')
</if>
<if test="param.status != null">
AND a.status = #{param.status}
</if>
<if test="param.deleted != null">
AND a.deleted = #{param.deleted}
</if>
<if test="param.deleted == null">
AND a.deleted = 0
</if>
<if test="param.merchantCode != null">
AND a.merchant_code LIKE CONCAT('%', #{param.merchantCode}, '%')
</if>
<if test="param.createTimeStart != null">
AND a.create_time &gt;= #{param.createTimeStart}
</if>
<if test="param.createTimeEnd != null">
AND a.create_time &lt;= #{param.createTimeEnd}
</if>
<if test="param.keywords != null">
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
)
</if>
</where>
</sql>
<!-- 分页查询 -->
<select id="selectPageRel" resultType="com.gxwebsoft.shop.entity.RechargeOrder">
<include refid="selectSql"></include>
</select>
<!-- 查询全部 -->
<select id="selectListRel" resultType="com.gxwebsoft.shop.entity.RechargeOrder">
<include refid="selectSql"></include>
</select>
</mapper>
@@ -25,6 +25,12 @@
<if test="param.remark != null">
AND a.remark LIKE CONCAT('%', #{param.remark}, '%')
</if>
<if test="param.orderId != null">
AND a.order_id = #{param.orderId}
</if>
<if test="param.adminId != null">
AND a.admin_id = #{param.adminId}
</if>
<if test="param.sortNumber != null">
AND a.sort_number = #{param.sortNumber}
</if>
@@ -40,9 +46,6 @@
<if test="param.deleted == null">
AND a.deleted = 0
</if>
<if test="param.merchantCode != null">
AND a.merchant_code LIKE CONCAT('%', #{param.merchantCode}, '%')
</if>
<if test="param.createTimeStart != null">
AND a.create_time &gt;= #{param.createTimeStart}
</if>
@@ -0,0 +1,49 @@
package com.gxwebsoft.shop.param;
import java.math.BigDecimal;
import java.util.List;
import com.gxwebsoft.common.core.annotation.QueryField;
import com.gxwebsoft.common.core.annotation.QueryType;
import com.gxwebsoft.common.core.web.BaseParam;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 查询参数
*
* @author LX
* @since 2026-05-07 14:57:22
*/
@Data
@EqualsAndHashCode(callSuper = false)
@JsonInclude(JsonInclude.Include.NON_NULL)
@ApiModel(value = "BalanceChargeLogParam对象", description = "查询参数")
public class BalanceChargeLogParam extends BaseParam {
private static final long serialVersionUID = 1L;
@QueryField(type = QueryType.EQ)
private Integer id;
@QueryField(type = QueryType.EQ)
private BigDecimal amount;
private String orderNo;
@QueryField(type = QueryType.EQ)
private Integer isPaid;
private String paidNumber;
@QueryField(type = QueryType.EQ)
private Integer userId;
private String phone;
private List<Integer> userIds;
private String remark;
}
@@ -1,105 +0,0 @@
package com.gxwebsoft.shop.param;
import java.math.BigDecimal;
import com.gxwebsoft.common.core.annotation.QueryField;
import com.gxwebsoft.common.core.annotation.QueryType;
import com.gxwebsoft.common.core.web.BaseParam;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 会员充值订单表查询参数
*
* @author 科技小王子
* @since 2024-07-26 23:18:48
*/
@Data
@EqualsAndHashCode(callSuper = false)
@JsonInclude(JsonInclude.Include.NON_NULL)
@ApiModel(value = "RechargeOrderParam对象", description = "会员充值订单表查询参数")
public class RechargeOrderParam extends BaseParam {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "订单ID")
@QueryField(type = QueryType.EQ)
private Integer orderId;
@ApiModelProperty(value = "订单号")
private String orderNo;
@ApiModelProperty(value = "用户ID")
@QueryField(type = QueryType.EQ)
private Integer userId;
@ApiModelProperty(value = "充值方式(10自定义金额 20套餐充值)")
@QueryField(type = QueryType.EQ)
private Integer rechargeType;
@ApiModelProperty(value = "机构id")
@QueryField(type = QueryType.EQ)
private Integer organizationId;
@ApiModelProperty(value = "充值套餐ID")
@QueryField(type = QueryType.EQ)
private Integer planId;
@ApiModelProperty(value = "用户支付金额")
@QueryField(type = QueryType.EQ)
private BigDecimal payPrice;
@ApiModelProperty(value = "赠送金额")
@QueryField(type = QueryType.EQ)
private BigDecimal giftMoney;
@ApiModelProperty(value = "实际到账金额")
@QueryField(type = QueryType.EQ)
private BigDecimal actualMoney;
@ApiModelProperty(value = "用户可用余额")
@QueryField(type = QueryType.EQ)
private BigDecimal balance;
@ApiModelProperty(value = "支付方式(微信/支付宝)")
private String payMethod;
@ApiModelProperty(value = "支付状态(10待支付 20已支付)")
@QueryField(type = QueryType.EQ)
private Integer payStatus;
@ApiModelProperty(value = "付款时间")
@QueryField(type = QueryType.EQ)
private Integer payTime;
@ApiModelProperty(value = "第三方交易记录ID")
@QueryField(type = QueryType.EQ)
private Integer tradeId;
@ApiModelProperty(value = "来源客户端 (APP、H5、小程序等)")
private String platform;
@ApiModelProperty(value = "所属门店ID")
@QueryField(type = QueryType.EQ)
private Integer shopId;
@ApiModelProperty(value = "排序(数字越小越靠前)")
@QueryField(type = QueryType.EQ)
private Integer sortNumber;
@ApiModelProperty(value = "备注")
private String comments;
@ApiModelProperty(value = "状态, 0正常, 1冻结")
@QueryField(type = QueryType.EQ)
private Integer status;
@ApiModelProperty(value = "是否删除, 0否, 1是")
@QueryField(type = QueryType.EQ)
private Integer deleted;
@ApiModelProperty(value = "商户编码")
private String merchantCode;
}
@@ -13,8 +13,8 @@ import lombok.EqualsAndHashCode;
/**
* 用户余额变动明细表查询参数
*
* @author 科技小王子
* @since 2024-05-29 15:57:44
* @author LX
* @since 2026-05-07 14:57:22
*/
@Data
@EqualsAndHashCode(callSuper = false)
@@ -31,7 +31,7 @@ public class UserBalanceLogParam extends BaseParam {
@QueryField(type = QueryType.EQ)
private Integer userId;
@ApiModelProperty(value = "余额变动场景(10用户充值 20用户消费 30管理员操作 40订单退款)")
@ApiModelProperty(value = "余额变动场景(0 用户充值 1用户消费 2管理员操作 3订单退款)")
@QueryField(type = QueryType.EQ)
private Integer scene;
@@ -46,6 +46,13 @@ public class UserBalanceLogParam extends BaseParam {
@ApiModelProperty(value = "管理员备注")
private String remark;
@QueryField(type = QueryType.EQ)
private Integer orderId;
@ApiModelProperty(value = "操作人ID")
@QueryField(type = QueryType.EQ)
private Integer adminId;
@ApiModelProperty(value = "排序(数字越小越靠前)")
@QueryField(type = QueryType.EQ)
private Integer sortNumber;
@@ -61,7 +68,4 @@ public class UserBalanceLogParam extends BaseParam {
@QueryField(type = QueryType.EQ)
private Integer deleted;
@ApiModelProperty(value = "商户编码")
private String merchantCode;
}
@@ -0,0 +1,42 @@
package com.gxwebsoft.shop.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.shop.entity.BalanceChargeLog;
import com.gxwebsoft.shop.param.BalanceChargeLogParam;
import java.util.List;
/**
* Service
*
* @author LX
* @since 2026-05-07 14:57:22
*/
public interface BalanceChargeLogService extends IService<BalanceChargeLog> {
/**
* 分页关联查询
*
* @param param 查询参数
* @return PageResult<BalanceChargeLog>
*/
PageResult<BalanceChargeLog> pageRel(BalanceChargeLogParam param);
/**
* 关联查询全部
*
* @param param 查询参数
* @return List<BalanceChargeLog>
*/
List<BalanceChargeLog> listRel(BalanceChargeLogParam param);
/**
* 根据id查询
*
* @param id
* @return BalanceChargeLog
*/
BalanceChargeLog getByIdRel(Integer id);
}
@@ -1,42 +0,0 @@
package com.gxwebsoft.shop.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.shop.entity.RechargeOrder;
import com.gxwebsoft.shop.param.RechargeOrderParam;
import java.util.List;
/**
* 会员充值订单表Service
*
* @author 科技小王子
* @since 2024-07-26 23:18:48
*/
public interface RechargeOrderService extends IService<RechargeOrder> {
/**
* 分页关联查询
*
* @param param 查询参数
* @return PageResult<RechargeOrder>
*/
PageResult<RechargeOrder> pageRel(RechargeOrderParam param);
/**
* 关联查询全部
*
* @param param 查询参数
* @return List<RechargeOrder>
*/
List<RechargeOrder> listRel(RechargeOrderParam param);
/**
* 根据id查询
*
* @param orderId 订单ID
* @return RechargeOrder
*/
RechargeOrder getByIdRel(Integer orderId);
}
@@ -10,8 +10,8 @@ import java.util.List;
/**
* 用户余额变动明细表Service
*
* @author 科技小王子
* @since 2024-05-29 15:57:44
* @author LX
* @since 2026-05-07 14:57:22
*/
public interface UserBalanceLogService extends IService<UserBalanceLog> {
@@ -0,0 +1,94 @@
package com.gxwebsoft.shop.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.common.system.service.UserService;
import com.gxwebsoft.shop.mapper.BalanceChargeLogMapper;
import com.gxwebsoft.shop.service.BalanceChargeLogService;
import com.gxwebsoft.shop.entity.BalanceChargeLog;
import com.gxwebsoft.shop.param.BalanceChargeLogParam;
import com.gxwebsoft.common.core.web.PageParam;
import com.gxwebsoft.common.core.web.PageResult;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* Service实现
*
* @author LX
* @since 2026-05-07 14:57:22
*/
@Service
public class BalanceChargeLogServiceImpl extends ServiceImpl<BalanceChargeLogMapper, BalanceChargeLog> implements BalanceChargeLogService {
@Resource
private UserService userService;
@Override
public PageResult<BalanceChargeLog> pageRel(BalanceChargeLogParam param) {
if (!setUserIdsByPhone(param)) {
return new PageResult<>(Collections.emptyList(), 0L);
}
PageParam<BalanceChargeLog, BalanceChargeLogParam> page = new PageParam<>(param);
page.setDefaultOrder("create_time desc");
List<BalanceChargeLog> list = baseMapper.selectPageRel(page, param);
setUserPhones(list);
return new PageResult<>(list, page.getTotal());
}
@Override
public List<BalanceChargeLog> listRel(BalanceChargeLogParam param) {
if (!setUserIdsByPhone(param)) {
return Collections.emptyList();
}
List<BalanceChargeLog> list = baseMapper.selectListRel(param);
setUserPhones(list);
// 排序
PageParam<BalanceChargeLog, BalanceChargeLogParam> page = new PageParam<>();
page.setDefaultOrder("create_time desc");
return page.sortRecords(list);
}
@Override
public BalanceChargeLog getByIdRel(Integer id) {
BalanceChargeLogParam param = new BalanceChargeLogParam();
param.setId(id);
return param.getOne(baseMapper.selectListRel(param));
}
private boolean setUserIdsByPhone(BalanceChargeLogParam param) {
if (param.getPhone() == null || param.getPhone().trim().isEmpty()) {
return true;
}
List<User> users = userService.listByPhoneInner(param.getPhone().trim());
if (CollectionUtils.isEmpty(users)) {
return false;
}
param.setUserIds(users.stream().map(User::getUserId).collect(Collectors.toList()));
return true;
}
private void setUserPhones(List<BalanceChargeLog> list) {
if (CollectionUtils.isEmpty(list)) {
return;
}
List<Integer> userIds = list.stream()
.map(BalanceChargeLog::getUserId)
.filter(Objects::nonNull)
.distinct()
.collect(Collectors.toList());
if (CollectionUtils.isEmpty(userIds)) {
return;
}
Map<Integer, String> userPhoneMap = userService.listByIdsInner(userIds).stream()
.collect(Collectors.toMap(User::getUserId, User::getPhone, (a, b) -> a));
list.forEach(d -> d.setPhone(userPhoneMap.get(d.getUserId())));
}
}
@@ -1,47 +0,0 @@
package com.gxwebsoft.shop.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gxwebsoft.shop.mapper.RechargeOrderMapper;
import com.gxwebsoft.shop.service.RechargeOrderService;
import com.gxwebsoft.shop.entity.RechargeOrder;
import com.gxwebsoft.shop.param.RechargeOrderParam;
import com.gxwebsoft.common.core.web.PageParam;
import com.gxwebsoft.common.core.web.PageResult;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 会员充值订单表Service实现
*
* @author 科技小王子
* @since 2024-07-26 23:18:48
*/
@Service
public class RechargeOrderServiceImpl extends ServiceImpl<RechargeOrderMapper, RechargeOrder> implements RechargeOrderService {
@Override
public PageResult<RechargeOrder> pageRel(RechargeOrderParam param) {
PageParam<RechargeOrder, RechargeOrderParam> page = new PageParam<>(param);
page.setDefaultOrder("sort_number asc, create_time desc");
List<RechargeOrder> list = baseMapper.selectPageRel(page, param);
return new PageResult<>(list, page.getTotal());
}
@Override
public List<RechargeOrder> listRel(RechargeOrderParam param) {
List<RechargeOrder> list = baseMapper.selectListRel(param);
// 排序
PageParam<RechargeOrder, RechargeOrderParam> page = new PageParam<>();
page.setDefaultOrder("sort_number asc, create_time desc");
return page.sortRecords(list);
}
@Override
public RechargeOrder getByIdRel(Integer orderId) {
RechargeOrderParam param = new RechargeOrderParam();
param.setOrderId(orderId);
return param.getOne(baseMapper.selectListRel(param));
}
}
@@ -14,8 +14,8 @@ import java.util.List;
/**
* 用户余额变动明细表Service实现
*
* @author 科技小王子
* @since 2024-05-29 15:57:44
* @author LX
* @since 2026-05-07 14:57:22
*/
@Service
public class UserBalanceLogServiceImpl extends ServiceImpl<UserBalanceLogMapper, UserBalanceLog> implements UserBalanceLogService {
@@ -23,7 +23,7 @@ public class UserBalanceLogServiceImpl extends ServiceImpl<UserBalanceLogMapper,
@Override
public PageResult<UserBalanceLog> pageRel(UserBalanceLogParam param) {
PageParam<UserBalanceLog, UserBalanceLogParam> page = new PageParam<>(param);
page.setDefaultOrder("sort_number asc, create_time desc");
page.setDefaultOrder("create_time desc");
List<UserBalanceLog> list = baseMapper.selectPageRel(page, param);
return new PageResult<>(list, page.getTotal());
}
@@ -33,7 +33,7 @@ public class UserBalanceLogServiceImpl extends ServiceImpl<UserBalanceLogMapper,
List<UserBalanceLog> list = baseMapper.selectListRel(param);
// 排序
PageParam<UserBalanceLog, UserBalanceLogParam> page = new PageParam<>();
page.setDefaultOrder("sort_number asc, create_time desc");
page.setDefaultOrder("create_time desc");
return page.sortRecords(list);
}
@@ -25,6 +25,7 @@ import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
@Api(tags = "打印")
@RestController
@@ -56,7 +56,7 @@ public class SchedulingController extends BaseController {
public void task() {
String newTime = DateUtil.format(LocalDateTime.now(), "HH:mm");
if ((newTime.equals("21:30") || newTime.equals("21:45")) && redisUtil.get("swimmingCheck") == null) {
redisUtil.set("swimmingCheck", 1, 3L, TimeUnit.HOURS);
redisUtil.set("swimmingCheck", 1, 3L, TimeUnit.MINUTES);
// 每天21:30后核销游泳馆订单
List<ThinkOrder> swimmingOrderList = thinkOrderService.list(
new LambdaQueryWrapper<ThinkOrder>()
@@ -73,139 +73,149 @@ public class SchedulingController extends BaseController {
.set(ThinkOrder::getUpdateTime, DateUtil.currentSeconds())
);
}
} else {
// 2分钟取消订单
List<ThinkOrder> orderList = thinkOrderService.list(
new LambdaUpdateWrapper<ThinkOrder>()
.eq(ThinkOrder::getPayStatus, 2)
.eq(ThinkOrder::getOrderStatus, 2)
.apply("UNIX_TIMESTAMP() > `create_time` + " + (2 * 60))
}
// 游泳馆年卡月卡当天使用多次的退掉
// List<ThinkOrder> swimCardOrderList = thinkOrderService.list(
// new LambdaUpdateWrapper<ThinkOrder>()
// .eq(ThinkOrder::getPayStatus, 1)
// .isNotNull(ThinkOrder::getCid)
// .apply("UNIX_TIMESTAMP() > `create_time` + " + (2 * 60))
// );
// 2分钟取消订单
List<ThinkOrder> orderList = thinkOrderService.list(
new LambdaUpdateWrapper<ThinkOrder>()
.eq(ThinkOrder::getPayStatus, 2)
.eq(ThinkOrder::getOrderStatus, 2)
.apply("UNIX_TIMESTAMP() > `create_time` + " + (2 * 60))
);
if (!orderList.isEmpty()) {
List<ThinkOrderInfo> orderInfoList = new ArrayList<>();
for (ThinkOrder thinkOrder : orderList) {
thinkOrder.setOrderStatus(3);
List<ThinkOrderInfo> orderInfoListTmp = thinkOrderInfoService.listInOrder(thinkOrder.getId());
orderInfoList.addAll(orderInfoListTmp);
thinkOrder.setUpdateTime(System.currentTimeMillis() / 1000);
}
for (ThinkOrderInfo thinkOrderInfo : orderInfoList) {
thinkOrderInfo.setPayStatus(0);
redisUtil.delete(thinkOrderInfo.getStartTime().toString() + thinkOrderInfo.getFid().toString());
}
thinkOrderService.updateBatchById(orderList);
thinkOrderInfoService.updateBatchById(orderInfoList);
}
// 清除占场redis
List<ThinkOrder> cancelOrderList = thinkOrderService.list(
new LambdaUpdateWrapper<ThinkOrder>()
.in(ThinkOrder::getOrderStatus, 3, 4, 5, 6)
.between(ThinkOrder::getCreateTime, DateUtil.beginOfDay(DateUtil.date()).getTime() / 1000, (int) (System.currentTimeMillis() / 1000))
);
if (!cancelOrderList.isEmpty()) {
List<Integer> orderIdList = cancelOrderList.stream().map(ThinkOrder::getId).toList();
List<ThinkOrderInfo> orderInfoListTmp = thinkOrderInfoService.listByOrderIds(orderIdList);
for (ThinkOrderInfo thinkOrderInfo : orderInfoListTmp) {
redisUtil.delete(thinkOrderInfo.getStartTime().toString() + thinkOrderInfo.getFid().toString());
}
}
//每天0点清空人数
if (DateUtil.format(LocalDateTime.now(), "HH:mm:ss").equals("00:00:00")) {
thinkSiteService.update(
new LambdaUpdateWrapper<ThinkSite>()
.set(ThinkSite::getDailyNum, 0)
);
if (!orderList.isEmpty()) {
List<ThinkOrderInfo> orderInfoList = new ArrayList<>();
for (ThinkOrder thinkOrder : orderList) {
thinkOrder.setOrderStatus(3);
List<ThinkOrderInfo> orderInfoListTmp = thinkOrderInfoService.listInOrder(thinkOrder.getId());
orderInfoList.addAll(orderInfoListTmp);
thinkOrder.setUpdateTime(System.currentTimeMillis() / 1000);
}
for (ThinkOrderInfo thinkOrderInfo : orderInfoList) {
thinkOrderInfo.setPayStatus(0);
redisUtil.delete(thinkOrderInfo.getStartTime().toString() + thinkOrderInfo.getFid().toString());
}
thinkOrderService.updateBatchById(orderList);
thinkOrderInfoService.updateBatchById(orderInfoList);
}
}
// 清除占场redis
List<ThinkOrder> cancelOrderList = thinkOrderService.list(
new LambdaUpdateWrapper<ThinkOrder>()
.in(ThinkOrder::getOrderStatus, 3, 4, 5, 6)
.between(ThinkOrder::getCreateTime, DateUtil.beginOfDay(DateUtil.date()).getTime() / 1000, (int) (System.currentTimeMillis() / 1000))
// 核销订单
List<ThinkOrder> otherOrderList = thinkOrderService.list(
new LambdaUpdateWrapper<ThinkOrder>()
.ne(ThinkOrder::getSid, 37)
.eq(ThinkOrder::getPayStatus, 1)
.eq(ThinkOrder::getOrderStatus, 2)
);
for (ThinkOrder thinkOrder : otherOrderList) {
List<ThinkOrderInfo> orderInfoList = thinkOrderInfoService.listInOrder(thinkOrder.getId());
ThinkOrderInfo lastOne = orderInfoList.get(orderInfoList.size() - 1);
if ((int) (System.currentTimeMillis() / 1000) > lastOne.getStartTime()) {
thinkOrder.setOrderStatus(1);
thinkOrder.setCheckBy(1);
thinkOrder.setCheckTime(new Date());
thinkOrderService.updateById(thinkOrder);
}
}
// 查询开票
String invoiceFlag = redisUtil.get("invoiceFlag");
if (invoiceFlag == null) {
redisUtil.set("invoiceFlag", "1", 3L, TimeUnit.MINUTES);
ThinkInvoice thinkInvoice = thinkInvoiceService.getOne(
new LambdaUpdateWrapper<ThinkInvoice>()
.gt(ThinkInvoice::getId, 5481)
.eq(ThinkInvoice::getIsOpen, 2)
.eq(ThinkInvoice::getType, 2)
.eq(ThinkInvoice::getDeleted, 0)
.groupBy(ThinkInvoice::getIncoiveNum)
.last("order by RAND() limit 1")
);
if (!cancelOrderList.isEmpty()) {
List<Integer> orderIdList = cancelOrderList.stream().map(ThinkOrder::getId).toList();
List<ThinkOrderInfo> orderInfoListTmp = thinkOrderInfoService.listByOrderIds(orderIdList);
for (ThinkOrderInfo thinkOrderInfo : orderInfoListTmp) {
redisUtil.delete(thinkOrderInfo.getStartTime().toString() + thinkOrderInfo.getFid().toString());
}
}
//每天0点清空人数
if (DateUtil.format(LocalDateTime.now(), "HH:mm:ss").equals("00:00:00")) {
thinkSiteService.update(
new LambdaUpdateWrapper<ThinkSite>()
.set(ThinkSite::getDailyNum, 0)
);
}
// 核销订单
List<ThinkOrder> otherOrderList = thinkOrderService.list(
new LambdaUpdateWrapper<ThinkOrder>()
.ne(ThinkOrder::getSid, 37)
.eq(ThinkOrder::getPayStatus, 1)
.eq(ThinkOrder::getOrderStatus, 2)
);
for (ThinkOrder thinkOrder : otherOrderList) {
List<ThinkOrderInfo> orderInfoList = thinkOrderInfoService.listInOrder(thinkOrder.getId());
ThinkOrderInfo lastOne = orderInfoList.get(orderInfoList.size() - 1);
if ((int) (System.currentTimeMillis() / 1000) > (lastOne.getStartTime() + 1800)) {
thinkOrder.setOrderStatus(1);
thinkOrder.setCheckBy(1);
thinkOrder.setCheckTime(new Date());
thinkOrderService.updateById(thinkOrder);
}
}
// 查询开票
String invoiceFlag = redisUtil.get("invoiceFlag");
if (invoiceFlag == null) {
redisUtil.set("invoiceFlag", "1", 3L, TimeUnit.MINUTES);
ThinkInvoice thinkInvoice = thinkInvoiceService.getOne(
new LambdaUpdateWrapper<ThinkInvoice>()
.gt(ThinkInvoice::getId, 5481)
.eq(ThinkInvoice::getIsOpen, 2)
.eq(ThinkInvoice::getType, 2)
.eq(ThinkInvoice::getDeleted, 0)
.groupBy(ThinkInvoice::getIncoiveNum)
.last("order by RAND() limit 1")
);
// for (ThinkInvoice thinkInvoice : invoiceList) {
if (thinkInvoice != null)
thinkInvoiceController.getRes(thinkInvoice.getId());
if (thinkInvoice != null)
thinkInvoiceController.getRes(thinkInvoice.getId());
// }
}
}
// 每2分钟检测撞场
if (redisUtil.get("sameOrderCheck") == null) {
redisUtil.set("sameOrderCheck", 1, 2L, TimeUnit.MINUTES);
List<ThinkOrder> checkOrderList = thinkOrderService.list(
new LambdaQueryWrapper<ThinkOrder>()
.ne(ThinkOrder::getSid, 37)
.in(ThinkOrder::getOrderStatus, 1, 2)
.eq(ThinkOrder::getPayStatus, 1)
.gt(ThinkOrder::getCreateTime, 1748707200)
.orderByAsc(ThinkOrder::getCreateTime)
);
Set<Integer> refundOrderIdList = new HashSet<>();
if (!checkOrderList.isEmpty()) {
for (ThinkOrder thinkOrder : checkOrderList) {
List<ThinkOrderInfo> thinkOrderInfoList = thinkOrderInfoService.listInOrder(thinkOrder.getId());
// 每2分钟检测撞场
if (redisUtil.get("sameOrderCheck") == null) {
redisUtil.set("sameOrderCheck", 1, 2L, TimeUnit.MINUTES);
List<ThinkOrder> checkOrderList = thinkOrderService.list(
new LambdaQueryWrapper<ThinkOrder>()
.ne(ThinkOrder::getSid, 37)
.in(ThinkOrder::getOrderStatus, 1, 2)
.eq(ThinkOrder::getPayStatus, 1)
.gt(ThinkOrder::getCreateTime, 1748707200)
.orderByAsc(ThinkOrder::getCreateTime)
);
Set<Integer> refundOrderIdList = new HashSet<>();
Map<String, Integer> bookedSlotOrderMap = new HashMap<>();
if (!checkOrderList.isEmpty()) {
checkOrderList.sort(Comparator
.comparing(ThinkOrder::getCreateTime)
.thenComparing(ThinkOrder::getId));
for (ThinkOrder thinkOrder : checkOrderList) {
if (refundOrderIdList.contains(thinkOrder.getId())) {
continue;
}
List<ThinkOrderInfo> thinkOrderInfoList = thinkOrderInfoService.listInOrder(thinkOrder.getId());
boolean hasConflict = false;
for (ThinkOrderInfo thinkOrderInfo : thinkOrderInfoList) {
String slotKey = thinkOrderInfo.getSid() + "_" + thinkOrderInfo.getFid() + "_" + thinkOrderInfo.getStartTime();
Integer bookedOrderId = bookedSlotOrderMap.get(slotKey);
if (bookedOrderId != null && !bookedOrderId.equals(thinkOrder.getId())) {
refundOrderIdList.add(thinkOrder.getId());
hasConflict = true;
break;
}
}
if (!hasConflict) {
for (ThinkOrderInfo thinkOrderInfo : thinkOrderInfoList) {
List<ThinkOrderInfo> checkThinkOrderInfoList = thinkOrderInfoService.list(
new LambdaQueryWrapper<ThinkOrderInfo>()
.ne(ThinkOrderInfo::getOid, thinkOrder.getId())
.eq(ThinkOrderInfo::getFid, thinkOrderInfo.getFid())
.eq(ThinkOrderInfo::getSid, thinkOrderInfo.getSid())
.eq(ThinkOrderInfo::getStartTime, thinkOrderInfo.getStartTime())
);
if (!checkThinkOrderInfoList.isEmpty()) {
for (ThinkOrderInfo checkThinkOrderInfo : checkThinkOrderInfoList) {
ThinkOrder sameOrder = thinkOrderService.getOne(
new LambdaQueryWrapper<ThinkOrder>()
.eq(ThinkOrder::getId, checkThinkOrderInfo.getOid())
);
if (sameOrder.getPayStatus().equals(1) && (sameOrder.getOrderStatus().equals(1) || sameOrder.getOrderStatus().equals(2))) {
refundOrderIdList.add(sameOrder.getId());
}
}
}
String slotKey = thinkOrderInfo.getSid() + "_" + thinkOrderInfo.getFid() + "_" + thinkOrderInfo.getStartTime();
bookedSlotOrderMap.putIfAbsent(slotKey, thinkOrder.getId());
}
}
}
if (!refundOrderIdList.isEmpty()) {
List<ThinkOrder> doCancelOrderList = thinkOrderService.listByIds(refundOrderIdList.stream().toList());
for (ThinkOrder refundOrder : doCancelOrderList) {
System.out.println("撞场订单: " + refundOrder.getOrderNum());
thinkOrderService.cancelOrder(refundOrder, true, 2);
refundOrder.setOrderStatus(6);
refundOrder.setRefundTime((int) (System.currentTimeMillis() / 1000));
thinkOrderService.updateById(refundOrder);
}
}
if (!refundOrderIdList.isEmpty()) {
List<ThinkOrder> doCancelOrderList = thinkOrderService.listByIds(refundOrderIdList.stream().toList());
for (ThinkOrder refundOrder : doCancelOrderList) {
System.out.println("撞场订单: " + refundOrder.getOrderNum());
thinkOrderService.cancelOrder(refundOrder, true, 2);
refundOrder.setOrderStatus(6);
refundOrder.setRefundTime((int) (System.currentTimeMillis() / 1000));
thinkOrderService.updateById(refundOrder);
}
}
}
}
}
@@ -266,6 +266,7 @@ public class ThinkCardController extends BaseController {
thinkLog.setLogType(0);
thinkLog.setOperateType(4);
}
thinkCard.setUpdateTime(DateUtil.currentSeconds());
if (thinkCardService.updateById(thinkCard)) {
thinkVipCardsBillsService.setCardUid(thinkCard.getId(), thinkCard.getUid());
if (thinkLog != null) {
@@ -281,6 +282,29 @@ public class ThinkCardController extends BaseController {
return fail("修改失败");
}
/** 管理端单独修改卡片剩余金额或剩余次数,避免覆盖其他字段。 */
@ApiOperation("修改剩余金额/次数")
@PreAuthorize("hasAuthority('think:thinkCard:changeRemain')")
@PutMapping("/remaining")
public ApiResult<?> updateRemaining(@RequestBody ThinkCard thinkCard) {
if (thinkCard.getId() == null) return fail("卡片ID不能为空");
if (thinkCard.getNum() == null && thinkCard.getRemainingMoney() == null) {
return fail("剩余金额或剩余次数不能为空");
}
if (thinkCard.getNum() != null && thinkCard.getNum() < 0) return fail("剩余次数不能为负数");
if (thinkCard.getRemainingMoney() != null && thinkCard.getRemainingMoney().compareTo(BigDecimal.ZERO) < 0) {
return fail("剩余金额不能为负数");
}
ThinkCard current = thinkCardService.getById(thinkCard.getId());
if (current == null) return fail("卡片不存在");
ThinkCard update = new ThinkCard();
update.setId(thinkCard.getId());
update.setNum(thinkCard.getNum());
update.setRemainingMoney(thinkCard.getRemainingMoney());
update.setUpdateTime(DateUtil.currentSeconds());
return thinkCardService.updateById(update) ? success("修改成功") : fail("修改失败");
}
@ApiOperation("删除")
@DeleteMapping("/{id}")
public ApiResult<?> remove(@PathVariable("id") Integer id) {
@@ -84,7 +84,7 @@ public class ThinkCardLogController extends BaseController {
thinkCardLog.setAid(getLoginUserId());
if (thinkCardLogService.save(thinkCardLog)) {
ThinkCard thinkCard = thinkCardService.getByCode(thinkCardLog.getCode());
ThinkVip thinkVip = thinkVipService.getById(thinkCard.getVid());
ThinkVip thinkVip = thinkVipService.getById(thinkCardLog.getVid());
if (thinkCard.getExpireTime() < DateUtil.currentSeconds()) {
thinkCard.setExpireTime((DateUtil.currentSeconds()) + (thinkVip.getTerm() * 86400 * 365) + (thinkVip.getMonth() * 86400 * 30) + (thinkVip.getDay() * 86400));
@@ -122,6 +122,19 @@ public class ThinkCardLogController extends BaseController {
}
// thinkCard.setNum(thinkCard.getCount() + thinkCard.getCount());
}
thinkCard.setVid(thinkVip.getId());
thinkCard.setSid(thinkVip.getSid());
thinkCard.setName(thinkVip.getName());
thinkCard.setDesc(thinkVip.getDesc());
thinkCard.setInfo(thinkVip.getInfo());
thinkCard.setDiscount(thinkVip.getDiscount());
thinkCard.setTerm(thinkVip.getTerm());
thinkCard.setMonth(thinkVip.getMonth());
thinkCard.setType(thinkVip.getType());
thinkCard.setCardType(thinkVip.getCardType());
thinkCard.setVipType(thinkVip.getVipType());
thinkCard.setPrice(thinkVip.getPrice());
thinkCard.setNumber(thinkCard.getNumber() + 1);
thinkCard.setCount(thinkCard.getCount() + thinkCardLog.getCount());
thinkCardService.updateById(thinkCard);
@@ -0,0 +1,127 @@
package com.gxwebsoft.think.controller;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.think.service.ThinkGateControlService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 闸机控制
*
* @author WebSoft
* @since 2026-03-11
*/
@Api(tags = "闸机控制")
@RestController
@RequestMapping("/api/think/gate-control")
public class ThinkGateControlController extends BaseController {
@Resource
private ThinkGateControlService thinkGateControlService;
@ApiOperation("获取权限组集合")
@GetMapping("/accLevelList")
public ApiResult<?> accLevelList(@RequestParam("pageNo") Integer pageNo,
@RequestParam("pageSize") Integer pageSize) {
try {
return success(thinkGateControlService.accLevelList(pageNo, pageSize));
} catch (Exception e) {
return fail("请求权限组集合失败: " + e.getMessage());
}
}
@ApiOperation("同步人员权限")
@PostMapping("/syncPerson")
public ApiResult<?> syncPerson(@RequestParam("pin") String pin,
@RequestParam("levelIds") String levelIds) {
try {
return success(thinkGateControlService.syncPerson(pin, levelIds));
} catch (Exception e) {
return fail("同步人员权限失败: " + e.getMessage());
}
}
@ApiOperation("检测人脸是否可用")
@PostMapping("/detectFace")
public ApiResult<?> detectFace(@RequestBody Map<String, Object> params) {
try {
return success(thinkGateControlService.detectFace(params));
} catch (Exception e) {
return fail("检测人脸失败: " + e.getMessage());
}
}
@ApiOperation("通过pin批量删除人员")
@PostMapping("/deleteByPins")
public ApiResult<?> deleteByPins(@RequestParam("pins") String pins) {
try {
return success(thinkGateControlService.deleteByPins(pins));
} catch (Exception e) {
return fail("批量删除人员失败: " + e.getMessage());
}
}
@ApiOperation("批量新增/编辑人员信息")
@PostMapping("/addPersons")
public ApiResult<?> addPersons(@RequestBody List<Map<String, Object>> personList) {
try {
thinkGateControlService.addPersons(personList);
return success();
} catch (Exception e) {
return fail("批量新增/编辑人员信息失败: " + e.getMessage());
}
}
@ApiOperation("批量新增/编辑人员信息-测试")
@PostMapping("/addPersons/test")
public ApiResult<?> addPersonsTest(@RequestBody Map<String, Object> params) {
String pin = params.get("pin") == null ? null : params.get("pin").toString();
String personPhoto = params.get("personPhoto") == null ? null : params.get("personPhoto").toString();
if (StrUtil.isBlank(pin)) {
return fail("pin不能为空");
}
if (StrUtil.isBlank(personPhoto)) {
return fail("personPhoto不能为空");
}
String name = params.get("name") == null ? null : params.get("name").toString();
String mobilePhone = params.get("mobilePhone") == null ? null : params.get("mobilePhone").toString();
String day = DateUtil.format(LocalDateTime.now(), "yyyy-MM-dd");
String accStartTime = params.get("accStartTime") == null ? day + " 05:00:00" : params.get("accStartTime").toString();
String accEndTime = params.get("accEndTime") == null ? day + " 22:00:00" : params.get("accEndTime").toString();
String accLevelIds = params.get("accLevelIds") == null ? thinkGateControlService.getLevelId() : params.get("accLevelIds").toString();
Map<String, Object> person = new HashMap<>();
person.put("pin", pin);
person.put("mobilePhone", mobilePhone);
person.put("name", StrUtil.blankToDefault(name, pin));
person.put("personPhoto", personPhoto);
person.put("accEndTime", accEndTime);
person.put("accLevelIds", accLevelIds);
person.put("accStartTime", accStartTime);
List<Map<String, Object>> personList = new ArrayList<>();
personList.add(person);
String res = thinkGateControlService.addPersons(personList);
return success(res);
}
@ApiOperation("获取门禁事件记录")
@PostMapping("/transactionList")
public ApiResult<?> transactionList() {
try {
return success(thinkGateControlService.transactionList());
} catch (Exception e) {
return fail("获取门禁事件记录信息失败: " + e.getMessage());
}
}
}
@@ -14,6 +14,7 @@ import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.common.core.web.BatchParam;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.think.entity.*;
import com.gxwebsoft.think.param.ThinkInvoiceParam;
import com.gxwebsoft.think.service.*;
@@ -74,6 +75,7 @@ public class ThinkInvoiceController extends BaseController {
private final String url = "https://sdk.nuonuo.com/open/v1/services";
private final String clerk = "刘绍仪";
private final String extensionNumber = "6192";
private final Long invoiceDebounceSeconds = 10L;
// private final String clerk = "赵裕璐";
// private final String extensionNumber = "7426";
@@ -111,10 +113,20 @@ public class ThinkInvoiceController extends BaseController {
@ApiOperation("添加")
@PostMapping()
public ApiResult<?> save(@RequestBody ThinkInvoice thinkInvoice) {
User loginUser = getLoginUser();
if (thinkInvoice.getCode() == null || thinkInvoice.getCode().isEmpty())
return fail("请输入税号");
if (thinkInvoice.getPhone() == null || thinkInvoice.getPhone().isEmpty())
return fail("请输入手机号");
if (thinkInvoice.getName() == null || thinkInvoice.getName().isEmpty())
return fail("请输入名称");
if (thinkInvoice.getPhone().length() > 11)
return fail("手机号长度不能超过11位");
if (isDebounced(buildInvoiceDebounceKey("save", thinkInvoice, loginUser))) return fail("请勿频繁操作");
thinkInvoice.setIncoiveNum("");
thinkInvoice.setUid(getLoginUser().getUid());
thinkInvoice.setUid(loginUser.getUid());
// thinkInvoice.setCode(thinkInvoice.getIncoiveCode());
thinkInvoice.setIncoiveNum(RandomUtil.randomString(20));
if (!thinkInvoice.getIsOpen().equals(1)) thinkInvoice.setIsOpen(2);
@@ -193,6 +205,8 @@ public class ThinkInvoiceController extends BaseController {
if (thinkInvoice.getCode() == null) return fail("请输入税号");
String taxCode = thinkInvoice.getCode().replaceAll(" ", "");
thinkInvoice.setCode(taxCode);
if (isDebounced(buildInvoiceDebounceKey("doInvoiceByList", thinkInvoice, getLoginUser())))
return fail("请勿频繁操作");
List<ThinkInvoice> thinkInvoiceList = new ArrayList<>();
List<ThinkOrder> thinkOrderList = thinkOrderService.listByIds(thinkInvoice.getOrderIdList());
List<ThinkOrderInfo> thinkOrderInfoList = thinkOrderInfoService.listByOrderIds(thinkInvoice.getOrderIdList());
@@ -209,7 +223,7 @@ public class ThinkInvoiceController extends BaseController {
if (thinkOrder != null) {
ThinkInvoice thinkInvoice1 = new ThinkInvoice();
thinkInvoice1.setIncoiveNum(invoiceNum);
thinkInvoice1.setIncoiveCode("91450100737617400R");
thinkInvoice1.setIncoiveCode(taxnum);
thinkInvoice1.setOid(orderId);
thinkInvoice1.setOrderNum(thinkOrder.getOrderNum());
thinkInvoice1.setUid(thinkOrder.getUid());
@@ -259,9 +273,9 @@ public class ThinkInvoiceController extends BaseController {
order.setInvoiceType("1");
order.setInvoiceLine(thinkInvoice.getInvoicetype().equals(1) ? "pc" : "bs");
final NuoNuoGoods goods = new NuoNuoGoods();
goods.setGoodsName("*经营租赁*场地费");
goods.setGoodsName("*生产生活服务*场地费");
goods.setGoodsCode("3040502029902");
goods.setGoodsCode("3040502029902000000");
// goods.setPrice(thinkInvoice.getPrice().toString());
goods.setNum(thinkSite.getSize().toString());
goods.setWithTaxFlag("0");
@@ -295,6 +309,8 @@ public class ThinkInvoiceController extends BaseController {
order.setRealPropertyRentInfo(nuoNuoRealPropertyRentInfo);
order.setSpecificFactor("6");
order.setExtensionNumber(extensionNumber);
if (thinkInvoice.getRemark() != null)
order.setRemark(thinkInvoice.getRemark());
nuoNuo.setOrder(order);
@@ -334,6 +350,8 @@ public class ThinkInvoiceController extends BaseController {
String code = thinkInvoice.getCode().replaceAll(" ", "");
thinkInvoice.setCode(code);
}
if (isDebounced(buildInvoiceDebounceKey("doInvoice", thinkInvoice, getLoginUser())))
return fail("请勿频繁操作");
thinkInvoice.setStatus(1);
if (thinkInvoice.getId() != null) thinkInvoiceService.updateById(thinkInvoice);
else {
@@ -342,7 +360,7 @@ public class ThinkInvoiceController extends BaseController {
if (thinkInvoice.getItype() == null) return fail("非法请求");
ThinkInvoice check = thinkInvoiceService.getByOidNType(thinkInvoice.getOid(), thinkInvoice.getItype());
if (check != null) return fail("该订单已开过发票");
thinkInvoice.setIncoiveCode("91450100737617400R");
thinkInvoice.setIncoiveCode(taxnum);
thinkInvoice.setCreateTime(System.currentTimeMillis() / 1000);
if (thinkInvoice.getCode() == null) thinkInvoice.setCode("");
if (thinkInvoice.getIncoiveNum() == null) thinkInvoice.setIncoiveNum("");
@@ -387,6 +405,8 @@ public class ThinkInvoiceController extends BaseController {
String method = "nuonuo.OpeMplatform.queryInvoiceResult";//API方法名
String token = getInvoiceToken();
HashMap<String, Object> map = new HashMap<>();
// if (!thinkInvoice.getOrderNum().isEmpty()) map.put("orderNos", thinkInvoice.getOrderNum());
// else map.put("serialNos", thinkInvoice.getIncoiveNum());
if (!thinkInvoice.getIncoiveNum().isEmpty()) map.put("serialNos", thinkInvoice.getIncoiveNum());
else map.put("orderNos", thinkInvoice.getOrderNum());
String content = JSONUtil.toJSONString(map);//API私有请求参数
@@ -421,7 +441,7 @@ public class ThinkInvoiceController extends BaseController {
}
return body;
} else if (code.equals("E9500")) {
newInvoice(thinkInvoice);
// newInvoice(thinkInvoice);
}
return result;
}
@@ -469,7 +489,7 @@ public class ThinkInvoiceController extends BaseController {
order.setInvoiceLine(thinkInvoice.getInvoicetype().equals(1) ? "pc" : "bs");
final NuoNuoGoods goods = new NuoNuoGoods();
if (thinkInvoice.getItype().equals(1)) {
goods.setGoodsName("*经营租赁*场地费");
goods.setGoodsName("*生产生活服务*场地费");
} else {
goods.setGoodsName("*预付卡销售*预付卡");
}
@@ -497,7 +517,7 @@ public class ThinkInvoiceController extends BaseController {
goods.setTax(tax.toString());
goods.setTaxIncludedAmount(thinkInvoice.getPrice().toString());
goods.setTaxExcludedAmount(thinkInvoice.getPrice().subtract(tax).toString());
goods.setGoodsCode("3040502029902");
goods.setGoodsCode("3040502029902000000");
NuoNuoRealPropertyRentInfo nuoNuoRealPropertyRentInfo = new NuoNuoRealPropertyRentInfo();
goods.setNum(thinkSite.getSize().toString());
nuoNuoRealPropertyRentInfo.setRealPropertyAddress(thinkSite.getProvince() + thinkSite.getCity() + thinkSite.getRegion());
@@ -522,6 +542,8 @@ public class ThinkInvoiceController extends BaseController {
}
order.setInvoiceDetail(goods);
order.setExtensionNumber(extensionNumber); // 13807717477
if (thinkInvoice.getRemark() != null)
order.setRemark(thinkInvoice.getRemark());
nuoNuo.setOrder(order);
@@ -534,6 +556,7 @@ public class ThinkInvoiceController extends BaseController {
final JSONObject jsonObject = JSONObject.parseObject(json);
final String code = jsonObject.getString("code");
final String result = jsonObject.getString("result");
System.out.println("invoice post data = " + content);
System.out.println("invoice jsonObject = " + jsonObject);
if (code.equals("E0000")) {
final JSONObject resNo = JSONObject.parseObject(result);
@@ -562,6 +585,49 @@ public class ThinkInvoiceController extends BaseController {
return "";
}
private boolean isDebounced(String key) {
return !redisUtil.setIfAbsent(
key,
String.valueOf(DateUtil.currentSeconds()),
invoiceDebounceSeconds,
TimeUnit.SECONDS
);
}
private String buildInvoiceDebounceKey(String action, ThinkInvoice thinkInvoice, User loginUser) {
StringBuilder key = new StringBuilder("think:invoice:debounce:")
.append(action)
.append(":")
.append(getInvoiceDebounceUserKey(thinkInvoice, loginUser));
if ("doInvoiceByList".equals(action)) {
key.append(":orders:").append(getOrderIdsKey(thinkInvoice.getOrderIdList()));
} else {
key.append(":id:").append(nullToEmpty(thinkInvoice.getId()))
.append(":oid:").append(nullToEmpty(thinkInvoice.getOid()))
.append(":itype:").append(nullToEmpty(thinkInvoice.getItype()))
.append(":orderNum:").append(nullToEmpty(thinkInvoice.getOrderNum()));
}
key.append(":code:").append(nullToEmpty(thinkInvoice.getCode()))
.append(":phone:").append(nullToEmpty(thinkInvoice.getPhone()))
.append(":price:").append(nullToEmpty(thinkInvoice.getPrice()));
return key.toString();
}
private String getInvoiceDebounceUserKey(ThinkInvoice thinkInvoice, User loginUser) {
if (loginUser != null && loginUser.getUid() != null) return loginUser.getUid().toString();
if (thinkInvoice.getUid() != null) return thinkInvoice.getUid().toString();
return "anonymous";
}
private String getOrderIdsKey(List<Integer> orderIdList) {
if (orderIdList == null || orderIdList.isEmpty()) return "";
return orderIdList.stream().sorted().map(String::valueOf).collect(Collectors.joining(","));
}
private String nullToEmpty(Object value) {
return value == null ? "" : value.toString();
}
private String getInvoiceToken() {
String tokenInRedis = redisUtil.get("invoiceToken");
if (StrUtil.isNotBlank(tokenInRedis)) {
@@ -72,6 +72,7 @@ public class ThinkMachineOpenLogController extends BaseController {
ThinkMachineOpenLog openLog = thinkMachineOpenLogService.getByOrderId(thinkOrder.getId());
if (openLog == null) {
thinkMachineOpenLog.setOrderId(thinkOrder.getId());
// thinkMachineOpenLog.setQrCode(thinkOrder.getQrcode());
thinkMachineOpenLogService.save(thinkMachineOpenLog);
}
}
File diff suppressed because it is too large Load Diff
@@ -5,6 +5,9 @@ import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.gxwebsoft.common.core.utils.RedisUtil;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.common.system.service.UserService;
import com.gxwebsoft.shop.entity.UserBalanceLog;
import com.gxwebsoft.shop.service.UserBalanceLogService;
import com.gxwebsoft.think.entity.*;
import com.gxwebsoft.think.service.*;
import com.gxwebsoft.think.param.ThinkOrderRefundLogParam;
@@ -58,6 +61,12 @@ public class ThinkOrderRefundLogController extends BaseController {
private ThinkUsersVipService thinkUsersVipService;
@Resource
private ThinkCardService thinkCardService;
@Resource
private UserService userService;
@Resource
private UserBalanceLogService userBalanceLogService;
@Resource
private ThinkMachineOpenLogService thinkMachineOpenLogService;
@Autowired
private RedisUtil redisUtil;
@@ -87,6 +96,7 @@ public class ThinkOrderRefundLogController extends BaseController {
thinkOrderRefundLog.setStatus(2);
if (thinkOrder != null) {
thinkOrder.setOrderStatus(6);
thinkOrder.setRefundBy(1);
thinkOrder.setRefundTime((int) (System.currentTimeMillis() / 1000));
List<ThinkOrderInfo> thinkOrderInfoList = thinkOrderInfoService.listInOrder(thinkOrder.getId());
for (ThinkOrderInfo thinkOrderInfo : thinkOrderInfoList) {
@@ -136,15 +146,25 @@ public class ThinkOrderRefundLogController extends BaseController {
// 可提前6小时退
ThinkOrder thinkOrder = thinkOrderService.getById(thinkOrderRefundLog.getOid());
List<ThinkOrderInfo> thinkOrderInfoList = thinkOrderInfoService.listInOrder(thinkOrder.getId());
long currentSeconds = DateUtil.currentSeconds();
if (thinkOrderRefundLog.getIsAdmin() == null) {
if (!thinkOrder.getSid().equals(37)) {
System.out.println("time cal: " + DateUtil.currentSeconds() + "," + thinkOrder.getCreateTime() + "," + ((int) DateUtil.currentSeconds() - thinkOrder.getCreateTime()));
if ((int) DateUtil.currentSeconds() - thinkOrder.getCreateTime() > 1800) {
if (thinkOrderInfoList.get(0).getStartTime() - (int) DateUtil.currentSeconds() < (3600 * 6)) {
for (ThinkOrderInfo thinkOrderInfo : thinkOrderInfoList) {
if (thinkOrderInfo.getStartTime() != null && currentSeconds > thinkOrderInfo.getStartTime()) {
return fail("已过开场时间不可退");
}
}
System.out.println("time cal: " + currentSeconds + "," + thinkOrder.getCreateTime() + "," + ((int) currentSeconds - thinkOrder.getCreateTime()));
if ((int) currentSeconds - thinkOrder.getCreateTime() > 1800) {
if (thinkOrderInfoList.get(0).getStartTime() - (int) currentSeconds < (3600 * 6)) {
return fail("距离开场已不足6小时不可退");
}
}
} else {
ThinkMachineOpenLog thinkMachineOpenLog = thinkMachineOpenLogService.getByOrderId(thinkOrder.getId());
if (thinkMachineOpenLog != null) {
return fail("该订单已使用不可退");
}
if (thinkOrder.getOrderStatus().equals(1)) {
return fail("该订单已使用不可退");
}
@@ -158,9 +178,12 @@ public class ThinkOrderRefundLogController extends BaseController {
thinkOrderService.updateById(thinkOrder);
if (thinkOrder.getPayType().equals(1)) {
if (thinkOrder.getWechatOrder() != null
&& !thinkOrder.getWechatOrder().isEmpty() && thinkOrder.getWechatOrder().contains("420000"))
thinkOrderService.refund(thinkOrderRefundLog);
else {
&& !thinkOrder.getWechatOrder().isEmpty() && (
thinkOrder.getWechatOrder().contains("420000") || thinkOrder.getWechatOrder().contains("450000")
)) {
Refund refundRes = thinkOrderService.refund(thinkOrderRefundLog);
System.out.println("refund req res: " + refundRes.toString());
} else {
for (ThinkOrderInfo thinkOrderInfo : thinkOrderInfoList) {
thinkOrderInfo.setPayStatus(0);
@@ -170,6 +193,36 @@ public class ThinkOrderRefundLogController extends BaseController {
thinkOrder.setOrderStatus(3);
thinkOrderService.updateById(thinkOrder);
}
} else if (thinkOrder.getPayType().equals(19)) {
for (ThinkOrderInfo thinkOrderInfo : thinkOrderInfoList) {
thinkOrderInfo.setPayStatus(0);
redisUtil.delete(thinkOrderInfo.getStartTime().toString() + thinkOrderInfo.getFid().toString());
}
thinkOrderInfoService.updateBatchById(thinkOrderInfoList);
thinkOrder.setOrderStatus(3);
thinkOrderService.updateById(thinkOrder);
User user = userService.getByUidInner(thinkOrder.getUid());
if (user != null) {
BigDecimal currentBalance = user.getBalance() == null ? BigDecimal.ZERO : user.getBalance();
BigDecimal latestBalance = currentBalance.add(thinkOrder.getTotalPrice());
user.setBalance(latestBalance);
userService.updateInner(user);
UserBalanceLog userBalanceLog = new UserBalanceLog();
userBalanceLog.setUserId(user.getUserId());
userBalanceLog.setScene(3);
userBalanceLog.setMoney(thinkOrder.getTotalPrice());
userBalanceLog.setBalance(latestBalance);
userBalanceLog.setRemark("订单退款");
userBalanceLog.setComments("退款订单号:" + thinkOrder.getOrderNum());
userBalanceLog.setStatus(0);
userBalanceLog.setDeleted(0);
userBalanceLog.setTenantId(10150);
userBalanceLog.setCreateTime(LocalDateTime.now());
userBalanceLog.setUpdateTime(LocalDateTime.now());
userBalanceLogService.save(userBalanceLog);
}
} else {
int num = 0;
for (ThinkOrderInfo thinkOrderInfo : thinkOrderInfoList) {
@@ -179,6 +232,7 @@ public class ThinkOrderRefundLogController extends BaseController {
}
thinkOrderInfoService.updateBatchById(thinkOrderInfoList);
thinkOrder.setOrderStatus(6);
thinkOrder.setRefundBy(1);
thinkOrder.setRefundTime((int) (System.currentTimeMillis() / 1000));
thinkOrderService.updateById(thinkOrder);
if (thinkOrder.getVid() != null && thinkOrder.getVid() != 0) {
@@ -49,6 +49,7 @@ public class ThinkSiteController extends BaseController {
param.setIdList(Arrays.stream(param.getIds().split(",")).map(Integer::parseInt).toList());
}
if (getLoginUser() != null && param.getIsAdmin() != null) param.setLoginUser(getLoginUser());
if (param.getIsAdmin() == null) param.setIsOn(1);
// 使用关联查询
return success(thinkSiteService.listRel(param));
}
@@ -56,6 +56,11 @@ public class ThinkSiteTimeController extends BaseController {
.eq(ThinkSiteTime::getIsStatus, 1)
.orderByAsc(ThinkSiteTime::getSort)
);
for (ThinkSiteTime thinkSiteTime : list) {
thinkSiteTime.setPriceOrigin(thinkSiteTime.getPrice());
thinkSiteTime.setHalfPriceOrigin(thinkSiteTime.getHalfPrice());
}
return success(list);
}
@@ -0,0 +1,204 @@
package com.gxwebsoft.think.controller;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.RandomUtil;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.think.entity.*;
import com.gxwebsoft.think.service.*;
import com.gxwebsoft.think.param.ThinkSmallRechargeParam;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.core.web.PageParam;
import com.gxwebsoft.common.core.web.BatchParam;
import com.gxwebsoft.common.core.annotation.OperationLog;
import com.gxwebsoft.common.system.entity.User;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 控制器
*
* @author 科技小王子
* @since 2026-01-07 21:24:29
*/
@Api(tags = "管理")
@RestController
@RequestMapping("/api/think/think-small-recharge")
public class ThinkSmallRechargeController extends BaseController {
@Resource
private ThinkSmallRechargeService thinkSmallRechargeService;
@Resource
private WechatConfigService wechatConfigService;
@Resource
private ThinkUsersVipService thinkUsersVipService;
@Resource
private ThinkCardService thinkCardService;
@Resource
private ThinkCardBalanceService thinkCardBalanceService;
@Resource
private ThinkOrderService thinkOrderService;
@ApiOperation("分页查询")
@GetMapping("/page")
public ApiResult<PageResult<ThinkSmallRecharge>> page(ThinkSmallRechargeParam param) {
// 使用关联查询
return success(thinkSmallRechargeService.pageRel(param));
}
@ApiOperation("查询全部")
@GetMapping()
public ApiResult<List<ThinkSmallRecharge>> list(ThinkSmallRechargeParam param) {
// 使用关联查询
return success(thinkSmallRechargeService.listRel(param));
}
@ApiOperation("根据id查询")
@GetMapping("/{id}")
public ApiResult<ThinkSmallRecharge> get(@PathVariable("id") Integer id) {
// 使用关联查询
return success(thinkSmallRechargeService.getByIdRel(id));
}
@ApiOperation("添加")
@PostMapping()
public ApiResult<?> save(@RequestBody ThinkSmallRecharge thinkSmallRecharge) {
if (thinkSmallRecharge.getCid() != null && thinkSmallRecharge.getCid() > 0) {
ThinkSmallRecharge check = thinkSmallRechargeService.checkByCid(thinkSmallRecharge.getCid());
if (check != null) return fail("该会员卡已充值");
}
if (thinkSmallRecharge.getVid() != null && thinkSmallRecharge.getVid() > 0) {
ThinkSmallRecharge check = thinkSmallRechargeService.checkByVid(thinkSmallRecharge.getVid());
if (check != null) return fail("该会员卡已充值");
}
thinkSmallRecharge.setUid(getLoginUserId());
thinkSmallRecharge.setCreateTime(DateUtil.currentSeconds());
thinkSmallRecharge.setUpdateTime(DateUtil.currentSeconds());
thinkSmallRecharge.setUid(getLoginUserId());
thinkSmallRecharge.setOrderNo(LocalDateTimeUtil.format(LocalDateTime.now(), "yyyyMMddHHmmss") + RandomUtil.randomNumbers(5));
if (thinkSmallRechargeService.save(thinkSmallRecharge)) {
if (thinkSmallRecharge.getPayType() == null || thinkSmallRecharge.getPayType() == 0) {
String notify = "https://gxtyzx-api2.websoft.top/api/think/think-small-recharge/notify";
return success("下单成功", thinkOrderService.createWxOrder(thinkSmallRecharge.getAmount(), thinkSmallRecharge.getOrderNo(),
"会员卡小额充值", getLoginUser().getOpenid(), notify));
}else {
doCharge(thinkSmallRecharge);
return success("操作成功");
}
}
return fail("添加失败");
}
@ApiOperation("修改")
@PutMapping()
public ApiResult<?> update(@RequestBody ThinkSmallRecharge thinkSmallRecharge) {
if (thinkSmallRechargeService.updateById(thinkSmallRecharge)) {
return success("修改成功");
}
return fail("修改失败");
}
@ApiOperation("删除")
@DeleteMapping("/{id}")
public ApiResult<?> remove(@PathVariable("id") Integer id) {
if (thinkSmallRechargeService.removeById(id)) {
return success("删除成功");
}
return fail("删除失败");
}
@ApiOperation("批量添加")
@PostMapping("/batch")
public ApiResult<?> saveBatch(@RequestBody List<ThinkSmallRecharge> list) {
if (thinkSmallRechargeService.saveBatch(list)) {
return success("添加成功");
}
return fail("添加失败");
}
@ApiOperation("批量修改")
@PutMapping("/batch")
public ApiResult<?> removeBatch(@RequestBody BatchParam<ThinkSmallRecharge> batchParam) {
if (batchParam.update(thinkSmallRechargeService, "id")) {
return success("修改成功");
}
return fail("修改失败");
}
@ApiOperation("批量删除")
@DeleteMapping("/batch")
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
if (thinkSmallRechargeService.removeByIds(ids)) {
return success("删除成功");
}
return fail("删除失败");
}
@ApiOperation("微信通知")
@PostMapping("/notify")
public String notify(@RequestBody String body, @RequestHeader Map<String, Object> header) {
System.out.println("小额冲卡支付通知 >>>>> ");
com.wechat.pay.java.core.notification.RequestParam requestParam = new RequestParam.Builder()
.serialNumber(header.get("wechatpay-serial").toString())
.nonce(header.get("wechatpay-nonce").toString())
.signature(header.get("wechatpay-signature").toString())
.timestamp(header.get("wechatpay-timestamp").toString())
.body(body)
.build();
NotificationConfig config = wechatConfigService.getNotificationConfig();
NotificationParser parser = new NotificationParser(config);
com.wechat.pay.java.service.payments.model.Transaction transaction = parser.parse(requestParam, com.wechat.pay.java.service.payments.model.Transaction.class);
ThinkSmallRecharge thinkSmallRecharge = thinkSmallRechargeService.getByOrderNo(transaction.getOutTradeNo());
if (thinkSmallRecharge != null && thinkSmallRecharge.getStatus() == 0) {
doCharge(thinkSmallRecharge);
}
return "订单已支付";
}
private void doCharge(ThinkSmallRecharge thinkSmallRecharge){
thinkSmallRecharge.setStatus(1);
thinkSmallRecharge.setUpdateTime(DateUtil.currentSeconds());
thinkSmallRechargeService.updateById(thinkSmallRecharge);
if (thinkSmallRecharge.getVid() != null && thinkSmallRecharge.getVid() > 0) {
ThinkUsersVip thinkUsersVip = thinkUsersVipService.getById(thinkSmallRecharge.getVid());
if (thinkUsersVip != null) {
thinkUsersVip.setRemainingMoney(thinkUsersVip.getRemainingMoney().add(thinkSmallRecharge.getAmount()));
thinkUsersVipService.updateById(thinkUsersVip);
ThinkCardBalance thinkCardBalance = thinkCardBalanceService.getByVid(thinkSmallRecharge.getVid());
if (thinkCardBalance != null) {
thinkCardBalance.setBalance(thinkUsersVip.getRemainingMoney());
thinkCardBalanceService.updateById(thinkCardBalance);
}
}
}
if (thinkSmallRecharge.getCid() != null && thinkSmallRecharge.getCid() > 0) {
ThinkCard thinkCard = thinkCardService.getById(thinkSmallRecharge.getCid());
if (thinkCard != null) {
thinkCard.setRemainingMoney(thinkCard.getRemainingMoney().add(thinkSmallRecharge.getAmount()));
thinkCardService.updateById(thinkCard);
ThinkCardBalance thinkCardBalance = thinkCardBalanceService.getByCid(thinkSmallRecharge.getCid());
if (thinkCardBalance != null) {
thinkCardBalance.setBalance(thinkCard.getRemainingMoney());
thinkCardBalanceService.updateById(thinkCardBalance);
}
}
}
}
}
@@ -0,0 +1,110 @@
package com.gxwebsoft.think.controller;
import cn.hutool.core.date.DateUtil;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.common.core.web.BatchParam;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.think.entity.ThinkTrainingInstitution;
import com.gxwebsoft.think.param.ThinkTrainingInstitutionParam;
import com.gxwebsoft.think.service.ThinkTrainingInstitutionService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
/**
* 培训机构管理
*
* @author Codex
* @since 2026-04-16
*/
@Api(tags = "培训机构管理")
@RestController
@RequestMapping("/api/think/think-training-institution")
public class ThinkTrainingInstitutionController extends BaseController {
@Resource
private ThinkTrainingInstitutionService thinkTrainingInstitutionService;
@ApiOperation("分页查询")
@GetMapping("/page")
public ApiResult<PageResult<ThinkTrainingInstitution>> page(ThinkTrainingInstitutionParam param) {
return success(thinkTrainingInstitutionService.pageRel(param));
}
@ApiOperation("查询全部")
@GetMapping()
public ApiResult<List<ThinkTrainingInstitution>> list(ThinkTrainingInstitutionParam param) {
return success(thinkTrainingInstitutionService.listRel(param));
}
@ApiOperation("根据id查询")
@GetMapping("/{id}")
public ApiResult<ThinkTrainingInstitution> get(@PathVariable("id") Integer id) {
return success(thinkTrainingInstitutionService.getByIdRel(id));
}
@ApiOperation("添加")
@PostMapping()
public ApiResult<?> save(@RequestBody ThinkTrainingInstitution thinkTrainingInstitution) {
thinkTrainingInstitution.setCreateTime((int) DateUtil.currentSeconds());
thinkTrainingInstitution.setUpdateTime((int) DateUtil.currentSeconds());
if (thinkTrainingInstitutionService.save(thinkTrainingInstitution)) {
return success("添加成功");
}
return fail("添加失败");
}
@ApiOperation("修改")
@PutMapping()
public ApiResult<?> update(@RequestBody ThinkTrainingInstitution thinkTrainingInstitution) {
thinkTrainingInstitution.setUpdateTime((int) DateUtil.currentSeconds());
if (thinkTrainingInstitutionService.updateById(thinkTrainingInstitution)) {
return success("修改成功");
}
return fail("修改失败");
}
@ApiOperation("删除")
@DeleteMapping("/{id}")
public ApiResult<?> remove(@PathVariable("id") Integer id) {
if (thinkTrainingInstitutionService.removeById(id)) {
return success("删除成功");
}
return fail("删除失败");
}
@ApiOperation("批量添加")
@PostMapping("/batch")
public ApiResult<?> saveBatch(@RequestBody List<ThinkTrainingInstitution> list) {
int now = (int) DateUtil.currentSeconds();
for (ThinkTrainingInstitution item : list) {
item.setCreateTime(now);
item.setUpdateTime(now);
}
if (thinkTrainingInstitutionService.saveBatch(list)) {
return success("添加成功");
}
return fail("添加失败");
}
@ApiOperation("批量修改")
@PutMapping("/batch")
public ApiResult<?> removeBatch(@RequestBody BatchParam<ThinkTrainingInstitution> batchParam) {
if (batchParam.update(thinkTrainingInstitutionService, "id")) {
return success("修改成功");
}
return fail("修改失败");
}
@ApiOperation("批量删除")
@DeleteMapping("/batch")
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
if (thinkTrainingInstitutionService.removeByIds(ids)) {
return success("删除成功");
}
return fail("删除失败");
}
}
@@ -0,0 +1,112 @@
package com.gxwebsoft.think.controller;
import cn.hutool.core.date.DateUtil;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.think.service.ThinkUserInAccessService;
import com.gxwebsoft.think.entity.ThinkUserInAccess;
import com.gxwebsoft.think.param.ThinkUserInAccessParam;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.core.web.PageParam;
import com.gxwebsoft.common.core.web.BatchParam;
import com.gxwebsoft.common.core.annotation.OperationLog;
import com.gxwebsoft.common.system.entity.User;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
/**
* 能刷脸开闸的用户列表控制器
*
* @author 科技小王子
* @since 2026-03-13 02:27:34
*/
@Api(tags = "能刷脸开闸的用户列表管理")
@RestController
@RequestMapping("/api/think/think-user-in-access")
public class ThinkUserInAccessController extends BaseController {
@Resource
private ThinkUserInAccessService thinkUserInAccessService;
@ApiOperation("分页查询能刷脸开闸的用户列表")
@GetMapping("/page")
public ApiResult<PageResult<ThinkUserInAccess>> page(ThinkUserInAccessParam param) {
// 使用关联查询
return success(thinkUserInAccessService.pageRel(param));
}
@ApiOperation("查询全部能刷脸开闸的用户列表")
@GetMapping()
public ApiResult<List<ThinkUserInAccess>> list(ThinkUserInAccessParam param) {
// 使用关联查询
return success(thinkUserInAccessService.listRel(param));
}
@PreAuthorize("hasAuthority('think:thinkUserInAccess:list')")
@ApiOperation("根据id查询能刷脸开闸的用户列表")
@GetMapping("/{id}")
public ApiResult<ThinkUserInAccess> get(@PathVariable("id") Integer id) {
// 使用关联查询
return success(thinkUserInAccessService.getByIdRel(id));
}
@ApiOperation("添加能刷脸开闸的用户列表")
@PostMapping()
public ApiResult<?> save(@RequestBody ThinkUserInAccess thinkUserInAccess) {
thinkUserInAccess.setCreateTime(DateUtil.currentSeconds());
if (thinkUserInAccessService.save(thinkUserInAccess)) {
return success("添加成功");
}
return fail("添加失败");
}
@ApiOperation("修改能刷脸开闸的用户列表")
@PutMapping()
public ApiResult<?> update(@RequestBody ThinkUserInAccess thinkUserInAccess) {
if (thinkUserInAccessService.updateById(thinkUserInAccess)) {
return success("修改成功");
}
return fail("修改失败");
}
@ApiOperation("删除能刷脸开闸的用户列表")
@DeleteMapping("/{id}")
public ApiResult<?> remove(@PathVariable("id") Integer id) {
if (thinkUserInAccessService.removeById(id)) {
return success("删除成功");
}
return fail("删除失败");
}
@ApiOperation("批量添加能刷脸开闸的用户列表")
@PostMapping("/batch")
public ApiResult<?> saveBatch(@RequestBody List<ThinkUserInAccess> list) {
if (thinkUserInAccessService.saveBatch(list)) {
return success("添加成功");
}
return fail("添加失败");
}
@ApiOperation("批量修改能刷脸开闸的用户列表")
@PutMapping("/batch")
public ApiResult<?> removeBatch(@RequestBody BatchParam<ThinkUserInAccess> batchParam) {
if (batchParam.update(thinkUserInAccessService, "id")) {
return success("修改成功");
}
return fail("修改失败");
}
@ApiOperation("批量删除能刷脸开闸的用户列表")
@DeleteMapping("/batch")
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
if (thinkUserInAccessService.removeByIds(ids)) {
return success("删除成功");
}
return fail("删除失败");
}
}
@@ -0,0 +1,113 @@
package com.gxwebsoft.think.controller;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.common.core.web.BatchParam;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.think.entity.ThinkUsersBlack;
import com.gxwebsoft.think.param.ThinkUsersBlackParam;
import com.gxwebsoft.think.service.ThinkUsersBlackService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
/**
* 用户黑名单控制器
*
* @author Codex
* @since 2026-06-04
*/
@Api(tags = "用户黑名单管理")
@RestController
@RequestMapping("/api/think/think-users-black")
public class ThinkUsersBlackController extends BaseController {
@Resource
private ThinkUsersBlackService thinkUsersBlackService;
@ApiOperation("分页查询用户黑名单")
@GetMapping("/page")
public ApiResult<PageResult<ThinkUsersBlack>> page(ThinkUsersBlackParam param) {
return success(thinkUsersBlackService.pageRel(param));
}
@ApiOperation("查询全部用户黑名单")
@GetMapping()
public ApiResult<List<ThinkUsersBlack>> list(ThinkUsersBlackParam param) {
return success(thinkUsersBlackService.listRel(param));
}
@PreAuthorize("hasAuthority('think:thinkUsersBlack:list')")
@ApiOperation("根据id查询用户黑名单")
@GetMapping("/{id}")
public ApiResult<ThinkUsersBlack> get(@PathVariable("id") Integer id) {
return success(thinkUsersBlackService.getByIdRel(id));
}
@ApiOperation("添加用户黑名单")
@PostMapping()
public ApiResult<?> save(@RequestBody ThinkUsersBlack thinkUsersBlack) {
if (thinkUsersBlack.getCreateTime() == null) {
thinkUsersBlack.setCreateTime(LocalDateTime.now());
}
if (thinkUsersBlackService.save(thinkUsersBlack)) {
return success("添加成功");
}
return fail("添加失败");
}
@ApiOperation("修改用户黑名单")
@PutMapping()
public ApiResult<?> update(@RequestBody ThinkUsersBlack thinkUsersBlack) {
if (thinkUsersBlackService.updateById(thinkUsersBlack)) {
return success("修改成功");
}
return fail("修改失败");
}
@ApiOperation("删除用户黑名单")
@DeleteMapping("/{id}")
public ApiResult<?> remove(@PathVariable("id") Integer id) {
if (thinkUsersBlackService.removeById(id)) {
return success("删除成功");
}
return fail("删除失败");
}
@ApiOperation("批量添加用户黑名单")
@PostMapping("/batch")
public ApiResult<?> saveBatch(@RequestBody List<ThinkUsersBlack> list) {
LocalDateTime now = LocalDateTime.now();
for (ThinkUsersBlack item : list) {
if (item.getCreateTime() == null) {
item.setCreateTime(now);
}
}
if (thinkUsersBlackService.saveBatch(list)) {
return success("添加成功");
}
return fail("添加失败");
}
@ApiOperation("批量修改用户黑名单")
@PutMapping("/batch")
public ApiResult<?> removeBatch(@RequestBody BatchParam<ThinkUsersBlack> batchParam) {
if (batchParam.update(thinkUsersBlackService, "id")) {
return success("修改成功");
}
return fail("修改失败");
}
@ApiOperation("批量删除用户黑名单")
@DeleteMapping("/batch")
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
if (thinkUsersBlackService.removeByIds(ids)) {
return success("删除成功");
}
return fail("删除失败");
}
}
@@ -69,6 +69,15 @@ public class ThinkUsersController extends BaseController {
return success(thinkUsersService.getByIdRel(id));
}
@PostMapping("/setHasFace")
public ApiResult<?> setHasFace(@RequestBody ThinkUsers thinkUsers) {
ThinkUsers thinkUser = thinkUsersService.getById(getLoginUser().getUid());
thinkUser.setHasFace(1);
thinkUser.setPersonPhoto(thinkUsers.getPersonPhoto());
thinkUsersService.updateById(thinkUser);
return success();
}
@ApiOperation("添加")
@PostMapping()
public ApiResult<?> save(@RequestBody ThinkUsers thinkUsers, HttpServletRequest request) {
@@ -76,7 +85,7 @@ public class ThinkUsersController extends BaseController {
RequestUtil requestUtil = new RequestUtil();
requestUtil.setAccessToken(JwtUtil.getAccessToken(request));
requestUtil.setTenantId(getTenantId().toString());
System.out.println("check:" + check);
// System.out.println("check:" + check);
if (check != null) {
User user = new User();
user.setUserId(thinkUsers.getUserId());
@@ -36,6 +36,7 @@ import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
* 控制器
@@ -363,7 +364,7 @@ public class ThinkUsersVipController extends BaseController {
@PutMapping()
public ApiResult<?> update(@RequestBody ThinkUsersVip thinkUsersVip) {
if (thinkUsersVipService.updateById(thinkUsersVip)) {
if (thinkUsersVip.getUid().equals(0)) {
if (thinkUsersVip.getUid() != null && thinkUsersVip.getUid().equals(0)) {
thinkVipCardsBillsService.clearUid(thinkUsersVip.getId());
}
return success("修改成功");
@@ -371,6 +372,35 @@ public class ThinkUsersVipController extends BaseController {
return fail("修改失败");
}
/** 管理端单独修改会员卡剩余金额或剩余次数,避免覆盖其他字段。 */
@ApiOperation("修改剩余金额/次数")
@PreAuthorize("hasAuthority('think:thinkUsersVip:changeRemain')")
@PutMapping("/remaining")
public ApiResult<?> updateRemaining(@RequestBody ThinkUsersVip thinkUsersVip) {
if (thinkUsersVip.getId() == null) return fail("会员卡ID不能为空");
if (thinkUsersVip.getNum() == null && thinkUsersVip.getRemainingMoney() == null) {
return fail("剩余金额或剩余次数不能为空");
}
if (thinkUsersVip.getNum() != null && thinkUsersVip.getNum() < 0) {
return fail("剩余次数不能为负数");
}
if (thinkUsersVip.getRemainingMoney() != null
&& thinkUsersVip.getRemainingMoney().compareTo(BigDecimal.ZERO) < 0) {
return fail("剩余金额不能为负数");
}
if (thinkUsersVipService.getById(thinkUsersVip.getId()) == null) {
return fail("会员卡不存在");
}
ThinkUsersVip update = new ThinkUsersVip();
update.setId(thinkUsersVip.getId());
update.setNum(thinkUsersVip.getNum());
update.setRemainingMoney(thinkUsersVip.getRemainingMoney());
return thinkUsersVipService.updateById(update)
? success("修改成功")
: fail("修改失败");
}
@ApiOperation("删除")
@DeleteMapping("/{id}")
public ApiResult<?> remove(@PathVariable("id") Integer id) {
@@ -4,8 +4,14 @@ import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.common.core.web.BatchParam;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.think.entity.ThinkCard;
import com.gxwebsoft.think.entity.ThinkTrainingInstitution;
import com.gxwebsoft.think.entity.ThinkUsersVip;
import com.gxwebsoft.think.entity.ThinkVip;
import com.gxwebsoft.think.param.ThinkVipParam;
import com.gxwebsoft.think.service.ThinkCardService;
import com.gxwebsoft.think.service.ThinkTrainingInstitutionService;
import com.gxwebsoft.think.service.ThinkUsersVipService;
import com.gxwebsoft.think.service.ThinkVipService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@@ -13,6 +19,7 @@ import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
/**
@@ -27,6 +34,12 @@ import java.util.List;
public class ThinkVipController extends BaseController {
@Resource
private ThinkVipService thinkVipService;
@Resource
private ThinkCardService thinkCardService;
@Resource
private ThinkUsersVipService thinkUsersVipService;
@Resource
private ThinkTrainingInstitutionService thinkTrainingInstitutionService;
@PostMapping("/list-by-group")
public ApiResult<?> listByGroup(@RequestBody ThinkVipParam param) {
@@ -64,8 +77,20 @@ public class ThinkVipController extends BaseController {
@ApiOperation("添加")
@PostMapping()
public ApiResult<?> save(@RequestBody ThinkVip thinkVip) {
thinkVip.setCreateTime((int) (System.currentTimeMillis()/1000));
thinkVip.setUpdateTime((int) (System.currentTimeMillis()/1000));
if (thinkVip.getVipType() != null && thinkVip.getVipType().equals(3)) {
if (thinkVip.getTrainingInstitutionId() == null) {
return fail("培训卡必须选择培训机构");
}
ThinkTrainingInstitution trainingInstitution =
thinkTrainingInstitutionService.getById(thinkVip.getTrainingInstitutionId());
if (trainingInstitution == null) {
return fail("培训机构不存在");
}
} else {
thinkVip.setTrainingInstitutionId(null);
}
thinkVip.setCreateTime((int) (System.currentTimeMillis() / 1000));
thinkVip.setUpdateTime((int) (System.currentTimeMillis() / 1000));
if (thinkVipService.save(thinkVip)) {
return success("添加成功");
}
@@ -75,7 +100,52 @@ public class ThinkVipController extends BaseController {
@ApiOperation("修改")
@PutMapping()
public ApiResult<?> update(@RequestBody ThinkVip thinkVip) {
if (thinkVip.getVipType() != null && thinkVip.getVipType().equals(3)) {
if (thinkVip.getTrainingInstitutionId() == null) {
return fail("培训卡必须选择培训机构");
}
ThinkTrainingInstitution trainingInstitution =
thinkTrainingInstitutionService.getById(thinkVip.getTrainingInstitutionId());
if (trainingInstitution == null) {
return fail("培训机构不存在");
}
} else if (thinkVip.getVipType() != null) {
thinkVip.setTrainingInstitutionId(null);
}
if (thinkVipService.updateById(thinkVip)) {
List<ThinkCard> thinkCardList = thinkCardService.listByVidList(new ArrayList<>() {{
add(thinkVip.getId());
}});
if (!thinkCardList.isEmpty()) {
for (ThinkCard thinkCard : thinkCardList) {
thinkCard.setSid(thinkVip.getSid());
thinkCard.setName(thinkVip.getName());
thinkCard.setInfo(thinkVip.getInfo());
thinkCard.setDesc(thinkVip.getDesc());
thinkCard.setUpdateTime(System.currentTimeMillis() / 1000);
// if (thinkVip.getMode() == 1 && thinkVip.getExpiredTime() != null) {
// // 固定时间
// thinkUsersVipService.updateByCardId(thinkCard);
// }
}
thinkCardService.updateBatchById(thinkCardList);
}
List<ThinkUsersVip> thinkUsersVipList = thinkUsersVipService.listByVipIds(new ArrayList<>() {{
add(thinkVip.getId());
}});
if (!thinkUsersVipList.isEmpty()) {
for (ThinkUsersVip thinkUsersVip : thinkUsersVipList) {
thinkUsersVip.setSid(thinkVip.getSid());
thinkUsersVip.setName(thinkVip.getName());
thinkUsersVip.setInfo(thinkVip.getInfo());
thinkUsersVip.setDesc(thinkVip.getDesc());
// if (thinkVip.getMode() == 1 && thinkVip.getExpiredTime() != null) {
// // 固定时间
// thinkUsersVipService.updateByCardId(thinkCard);
// }
}
thinkUsersVipService.updateBatchById(thinkUsersVipList);
}
return success("修改成功");
}
return fail("修改失败");
@@ -90,4 +90,6 @@ public class ThinkCardLog implements Serializable {
@TableField(exist = false)
private List<Integer> payTypeList;
@TableField(exist = false)
private Integer vid;
}
@@ -49,4 +49,8 @@ public class ThinkMachineOpenLog implements Serializable {
@TableField(exist = false)
private String qrcode;
// private String qrCode;
private Integer logId;
}
@@ -104,4 +104,10 @@ public class ThinkRechargeLog implements Serializable {
@TableField(exist = false)
private ThinkUsersVip thinkUsersVip;
@TableField(exist = false)
private String name;
@TableField(exist = false)
private Integer vipId;
}
@@ -106,6 +106,8 @@ public class ThinkSite implements Serializable {
private String machineCode;
private Integer isOn;
@TableField(exist = false)
private BigDecimal distance;
@@ -1,6 +1,7 @@
package com.gxwebsoft.think.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@@ -31,12 +32,18 @@ public class ThinkSiteTime implements Serializable {
@ApiModelProperty(value = "价格")
private BigDecimal price;
@TableField(exist = false)
private BigDecimal priceOrigin;
@ApiModelProperty(value = "每日不同价格")
private String prices;
@ApiModelProperty(value = "半场价格")
private BigDecimal halfPrice;
@TableField(exist = false)
private BigDecimal halfPriceOrigin;
@ApiModelProperty(value = "每日不同半场价格")
private String halfPrices;
@@ -0,0 +1,54 @@
package com.gxwebsoft.think.entity;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
*
*
* @author 科技小王子
* @since 2026-01-07 21:24:29
*/
@Data
@EqualsAndHashCode(callSuper = false)
@ApiModel(value = "ThinkSmallRecharge对象", description = "")
public class ThinkSmallRecharge implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
private Integer cid;
private Integer vid;
private Integer uid;
private Integer payType;
private Integer status;
private String orderNo;
private String payVoucher;
private BigDecimal amount;
@ApiModelProperty(value = "下单时间")
private Long createTime;
private Long updateTime;
@TableField(exist = false)
private ThinkUsersVip usersVip;
@TableField(exist = false)
private ThinkCard card;
}
@@ -0,0 +1,41 @@
package com.gxwebsoft.think.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
/**
* 培训机构
*
* @author Codex
* @since 2026-04-16
*/
@Data
@EqualsAndHashCode(callSuper = false)
@ApiModel(value = "ThinkTrainingInstitution对象", description = "培训机构")
public class ThinkTrainingInstitution implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@ApiModelProperty(value = "机构名称")
private String name;
@ApiModelProperty(value = "联系人")
private String contactName;
@ApiModelProperty(value = "联系方式")
private String contactPhone;
@ApiModelProperty(value = "创建时间")
private Integer createTime;
@ApiModelProperty(value = "更新时间")
private Integer updateTime;
}
@@ -0,0 +1,30 @@
package com.gxwebsoft.think.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 能刷脸开闸的用户列表
*
* @author 科技小王子
* @since 2026-03-13 02:27:34
*/
@Data
@EqualsAndHashCode(callSuper = false)
@ApiModel(value = "ThinkUserInAccess对象", description = "能刷脸开闸的用户列表")
public class ThinkUserInAccess implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
private Integer uid;
private Long createTime;
}
@@ -63,6 +63,10 @@ public class ThinkUsers implements Serializable {
@ApiModelProperty(value = "注册时间")
private Integer createTime;
private Integer hasFace;
private String personPhoto;
private String idcard;
private String truename;
@@ -76,4 +80,7 @@ public class ThinkUsers implements Serializable {
@TableField(exist = false)
private Integer userId;
@TableField(exist = false)
private BigDecimal balance;
}
@@ -0,0 +1,51 @@
package com.gxwebsoft.think.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* 用户黑名单
*
* @author Codex
* @since 2026-06-04
*/
@Data
@EqualsAndHashCode(callSuper = false)
@ApiModel(value = "ThinkUsersBlack对象", description = "用户黑名单")
public class ThinkUsersBlack implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@ApiModelProperty(value = "用户ID")
private Integer uid;
@ApiModelProperty(value = "状态:1,正常;2,禁用")
private Integer status;
@ApiModelProperty(value = "失效时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime expireTime;
@ApiModelProperty(value = "添加时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
@TableField(exist = false)
@ApiModelProperty(value = "姓名")
private String truename;
@TableField(exist = false)
@ApiModelProperty(value = "手机号")
private String phone;
}
@@ -83,6 +83,9 @@ public class ThinkVip implements Serializable {
@ApiModelProperty(value = "vip卡等级类型:1特殊vip卡,2普通vip卡")
private Integer vipType;
@ApiModelProperty(value = "培训机构ID")
private Integer trainingInstitutionId;
@ApiModelProperty(value = "特殊卡开发凭证图")
private String pic;
@@ -110,6 +113,10 @@ public class ThinkVip implements Serializable {
@TableField(exist = false)
private String siteNames;
@ApiModelProperty(value = "培训机构名称")
@TableField(exist = false)
private String trainingInstitutionName;
@TableField(exist = false)
private List<ThinkVip> cardList;
@@ -0,0 +1,37 @@
package com.gxwebsoft.think.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.gxwebsoft.think.entity.ThinkSmallRecharge;
import com.gxwebsoft.think.param.ThinkSmallRechargeParam;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* Mapper
*
* @author 科技小王子
* @since 2026-01-07 21:24:29
*/
public interface ThinkSmallRechargeMapper extends BaseMapper<ThinkSmallRecharge> {
/**
* 分页查询
*
* @param page 分页对象
* @param param 查询参数
* @return List<ThinkSmallRecharge>
*/
List<ThinkSmallRecharge> selectPageRel(@Param("page") IPage<ThinkSmallRecharge> page,
@Param("param") ThinkSmallRechargeParam param);
/**
* 查询全部
*
* @param param 查询参数
* @return List<User>
*/
List<ThinkSmallRecharge> selectListRel(@Param("param") ThinkSmallRechargeParam param);
}
@@ -0,0 +1,31 @@
package com.gxwebsoft.think.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.gxwebsoft.think.entity.ThinkTrainingInstitution;
import com.gxwebsoft.think.param.ThinkTrainingInstitutionParam;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 培训机构 Mapper
*
* @author Codex
* @since 2026-04-16
*/
public interface ThinkTrainingInstitutionMapper extends BaseMapper<ThinkTrainingInstitution> {
/**
* 分页查询
*/
List<ThinkTrainingInstitution> selectPageRel(
@Param("page") IPage<ThinkTrainingInstitution> page,
@Param("param") ThinkTrainingInstitutionParam param
);
/**
* 查询全部
*/
List<ThinkTrainingInstitution> selectListRel(@Param("param") ThinkTrainingInstitutionParam param);
}
@@ -0,0 +1,37 @@
package com.gxwebsoft.think.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.gxwebsoft.think.entity.ThinkUserInAccess;
import com.gxwebsoft.think.param.ThinkUserInAccessParam;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 能刷脸开闸的用户列表Mapper
*
* @author 科技小王子
* @since 2026-03-13 02:27:34
*/
public interface ThinkUserInAccessMapper extends BaseMapper<ThinkUserInAccess> {
/**
* 分页查询
*
* @param page 分页对象
* @param param 查询参数
* @return List<ThinkUserInAccess>
*/
List<ThinkUserInAccess> selectPageRel(@Param("page") IPage<ThinkUserInAccess> page,
@Param("param") ThinkUserInAccessParam param);
/**
* 查询全部
*
* @param param 查询参数
* @return List<User>
*/
List<ThinkUserInAccess> selectListRel(@Param("param") ThinkUserInAccessParam param);
}
@@ -0,0 +1,31 @@
package com.gxwebsoft.think.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.gxwebsoft.think.entity.ThinkUsersBlack;
import com.gxwebsoft.think.param.ThinkUsersBlackParam;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 用户黑名单 Mapper
*
* @author Codex
* @since 2026-06-04
*/
public interface ThinkUsersBlackMapper extends BaseMapper<ThinkUsersBlack> {
/**
* 分页查询
*/
List<ThinkUsersBlack> selectPageRel(
@Param("page") IPage<ThinkUsersBlack> page,
@Param("param") ThinkUsersBlackParam param
);
/**
* 查询全部
*/
List<ThinkUsersBlack> selectListRel(@Param("param") ThinkUsersBlackParam param);
}
@@ -2,6 +2,7 @@ package com.gxwebsoft.think.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.yulichang.base.MPJBaseMapper;
import com.gxwebsoft.think.entity.ThinkUsersVip;
import com.gxwebsoft.think.param.ThinkUsersVipParam;
import org.apache.ibatis.annotations.Param;
@@ -14,7 +15,7 @@ import java.util.List;
* @author 科技小王子
* @since 2024-08-11 20:50:59
*/
public interface ThinkUsersVipMapper extends BaseMapper<ThinkUsersVip> {
public interface ThinkUsersVipMapper extends MPJBaseMapper<ThinkUsersVip> {
/**
* 分页查询
@@ -2,6 +2,7 @@ package com.gxwebsoft.think.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.yulichang.base.MPJBaseMapper;
import com.gxwebsoft.think.entity.ThinkVip;
import com.gxwebsoft.think.param.ThinkVipParam;
import org.apache.ibatis.annotations.Param;
@@ -14,7 +15,7 @@ import java.util.List;
* @author 科技小王子
* @since 2024-08-12 02:12:22
*/
public interface ThinkVipMapper extends BaseMapper<ThinkVip> {
public interface ThinkVipMapper extends MPJBaseMapper<ThinkVip> {
/**
* 分页查询
@@ -25,6 +25,9 @@
<if test="param.price != null">
AND a.price = #{param.price}
</if>
<if test="param.isOn != null">
AND a.is_on = #{param.isOn}
</if>
<if test="param.businessTime != null">
AND a.business_time LIKE CONCAT('%', #{param.businessTime}, '%')
</if>
@@ -0,0 +1,48 @@
<?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.gxwebsoft.think.mapper.ThinkSmallRechargeMapper">
<!-- 关联查询sql -->
<sql id="selectSql">
SELECT a.*
FROM think_small_recharge a
<where>
<if test="param.id != null">
AND a.id = #{param.id}
</if>
<if test="param.cid != null">
AND a.cid = #{param.cid}
</if>
<if test="param.vid != null">
AND a.vid = #{param.vid}
</if>
<if test="param.uid != null">
AND a.uid = #{param.uid}
</if>
<if test="param.amount != null">
AND a.amount = #{param.amount}
</if>
<if test="param.createTimeStart != null">
AND a.create_time &gt;= #{param.createTimeStart}
</if>
<if test="param.createTimeEnd != null">
AND a.create_time &lt;= #{param.createTimeEnd}
</if>
<if test="param.keywords != null">
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
)
</if>
</where>
</sql>
<!-- 分页查询 -->
<select id="selectPageRel" resultType="com.gxwebsoft.think.entity.ThinkSmallRecharge">
<include refid="selectSql"></include>
</select>
<!-- 查询全部 -->
<select id="selectListRel" resultType="com.gxwebsoft.think.entity.ThinkSmallRecharge">
<include refid="selectSql"></include>
</select>
</mapper>
@@ -0,0 +1,45 @@
<?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.gxwebsoft.think.mapper.ThinkTrainingInstitutionMapper">
<sql id="selectSql">
SELECT a.*
FROM think_training_institution a
<where>
<if test="param.id != null">
AND a.id = #{param.id}
</if>
<if test="param.name != null and param.name != ''">
AND a.name LIKE CONCAT('%', #{param.name}, '%')
</if>
<if test="param.contactName != null and param.contactName != ''">
AND a.contact_name LIKE CONCAT('%', #{param.contactName}, '%')
</if>
<if test="param.contactPhone != null and param.contactPhone != ''">
AND a.contact_phone LIKE CONCAT('%', #{param.contactPhone}, '%')
</if>
<if test="param.createTimeStart != null">
AND a.create_time &gt;= #{param.createTimeStart}
</if>
<if test="param.createTimeEnd != null">
AND a.create_time &lt;= #{param.createTimeEnd}
</if>
<if test="param.keywords != null and param.keywords != ''">
AND (
a.name LIKE CONCAT('%', #{param.keywords}, '%')
OR a.contact_name LIKE CONCAT('%', #{param.keywords}, '%')
OR a.contact_phone LIKE CONCAT('%', #{param.keywords}, '%')
)
</if>
</where>
</sql>
<select id="selectPageRel" resultType="com.gxwebsoft.think.entity.ThinkTrainingInstitution">
<include refid="selectSql" />
</select>
<select id="selectListRel" resultType="com.gxwebsoft.think.entity.ThinkTrainingInstitution">
<include refid="selectSql" />
</select>
</mapper>
@@ -0,0 +1,33 @@
<?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.gxwebsoft.think.mapper.ThinkUserInAccessMapper">
<!-- 关联查询sql -->
<sql id="selectSql">
SELECT a.*
FROM think_user_in_access a
<where>
<if test="param.id != null">
AND a.id = #{param.id}
</if>
<if test="param.uid != null">
AND a.uid = #{param.uid}
</if>
<if test="param.keywords != null">
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
)
</if>
</where>
</sql>
<!-- 分页查询 -->
<select id="selectPageRel" resultType="com.gxwebsoft.think.entity.ThinkUserInAccess">
<include refid="selectSql"></include>
</select>
<!-- 查询全部 -->
<select id="selectListRel" resultType="com.gxwebsoft.think.entity.ThinkUserInAccess">
<include refid="selectSql"></include>
</select>
</mapper>
@@ -0,0 +1,39 @@
<?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.gxwebsoft.think.mapper.ThinkUsersBlackMapper">
<sql id="selectSql">
SELECT a.*, u.truename, u.phone
FROM think_users_black a
LEFT JOIN think_users u ON a.uid = u.id
<where>
<if test="param.id != null">
AND a.id = #{param.id}
</if>
<if test="param.uid != null">
AND a.uid = #{param.uid}
</if>
<if test="param.status != null">
AND a.status = #{param.status}
</if>
<if test="param.expireTime != null and param.expireTime != ''">
AND a.expire_time LIKE CONCAT('%', #{param.expireTime}, '%')
</if>
<if test="param.createTimeStart != null and param.createTimeStart != ''">
AND a.create_time &gt;= #{param.createTimeStart}
</if>
<if test="param.createTimeEnd != null and param.createTimeEnd != ''">
AND a.create_time &lt;= #{param.createTimeEnd}
</if>
</where>
</sql>
<select id="selectPageRel" resultType="com.gxwebsoft.think.entity.ThinkUsersBlack">
<include refid="selectSql" />
</select>
<select id="selectListRel" resultType="com.gxwebsoft.think.entity.ThinkUsersBlack">
<include refid="selectSql" />
</select>
</mapper>
@@ -4,8 +4,9 @@
<!-- 关联查询sql -->
<sql id="selectSql">
SELECT a.*
SELECT a.*, b.name AS trainingInstitutionName
FROM think_vip a
LEFT JOIN think_training_institution b ON a.training_institution_id = b.id
<where>
<if test="param.id != null">
AND a.id = #{param.id}
@@ -62,6 +63,9 @@
<if test="param.vipType != null">
AND a.vip_type = #{param.vipType}
</if>
<if test="param.trainingInstitutionId != null">
AND a.training_institution_id = #{param.trainingInstitutionId}
</if>
<if test="param.pic != null">
AND a.pic LIKE CONCAT('%', #{param.pic}, '%')
</if>
@@ -102,4 +102,7 @@ public class ThinkInvoiceParam extends BaseParam {
@TableField(exist = false)
private Boolean forAdmin;
@TableField(exist = false)
private Boolean group;
}
@@ -71,6 +71,8 @@ public class ThinkSiteParam extends BaseParam {
@ApiModelProperty(value = "退款规则组")
private String moneyJson;
private Integer isOn;
private String lat;
private String lng;
@@ -0,0 +1,41 @@
package com.gxwebsoft.think.param;
import java.math.BigDecimal;
import com.gxwebsoft.common.core.annotation.QueryField;
import com.gxwebsoft.common.core.annotation.QueryType;
import com.gxwebsoft.common.core.web.BaseParam;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 查询参数
*
* @author 科技小王子
* @since 2026-01-07 21:24:29
*/
@Data
@EqualsAndHashCode(callSuper = false)
@JsonInclude(JsonInclude.Include.NON_NULL)
@ApiModel(value = "ThinkSmallRechargeParam对象", description = "查询参数")
public class ThinkSmallRechargeParam extends BaseParam {
private static final long serialVersionUID = 1L;
@QueryField(type = QueryType.EQ)
private Integer id;
@QueryField(type = QueryType.EQ)
private Integer cid;
@QueryField(type = QueryType.EQ)
private Integer vid;
@QueryField(type = QueryType.EQ)
private Integer uid;
@QueryField(type = QueryType.EQ)
private BigDecimal amount;
}
@@ -0,0 +1,36 @@
package com.gxwebsoft.think.param;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.gxwebsoft.common.core.annotation.QueryField;
import com.gxwebsoft.common.core.annotation.QueryType;
import com.gxwebsoft.common.core.web.BaseParam;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 培训机构查询参数
*
* @author Codex
* @since 2026-04-16
*/
@Data
@EqualsAndHashCode(callSuper = false)
@JsonInclude(JsonInclude.Include.NON_NULL)
@ApiModel(value = "ThinkTrainingInstitutionParam对象", description = "培训机构查询参数")
public class ThinkTrainingInstitutionParam extends BaseParam {
private static final long serialVersionUID = 1L;
@QueryField(type = QueryType.EQ)
private Integer id;
@ApiModelProperty(value = "机构名称")
private String name;
@ApiModelProperty(value = "联系人")
private String contactName;
@ApiModelProperty(value = "联系方式")
private String contactPhone;
}
@@ -0,0 +1,32 @@
package com.gxwebsoft.think.param;
import java.math.BigDecimal;
import com.gxwebsoft.common.core.annotation.QueryField;
import com.gxwebsoft.common.core.annotation.QueryType;
import com.gxwebsoft.common.core.web.BaseParam;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 能刷脸开闸的用户列表查询参数
*
* @author 科技小王子
* @since 2026-03-13 02:27:34
*/
@Data
@EqualsAndHashCode(callSuper = false)
@JsonInclude(JsonInclude.Include.NON_NULL)
@ApiModel(value = "ThinkUserInAccessParam对象", description = "能刷脸开闸的用户列表查询参数")
public class ThinkUserInAccessParam extends BaseParam {
private static final long serialVersionUID = 1L;
@QueryField(type = QueryType.EQ)
private Integer id;
@QueryField(type = QueryType.EQ)
private Integer uid;
}
@@ -0,0 +1,38 @@
package com.gxwebsoft.think.param;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.gxwebsoft.common.core.annotation.QueryField;
import com.gxwebsoft.common.core.annotation.QueryType;
import com.gxwebsoft.common.core.web.BaseParam;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 用户黑名单查询参数
*
* @author Codex
* @since 2026-06-04
*/
@Data
@EqualsAndHashCode(callSuper = false)
@JsonInclude(JsonInclude.Include.NON_NULL)
@ApiModel(value = "ThinkUsersBlackParam对象", description = "用户黑名单查询参数")
public class ThinkUsersBlackParam extends BaseParam {
private static final long serialVersionUID = 1L;
@QueryField(type = QueryType.EQ)
private Integer id;
@ApiModelProperty(value = "用户ID")
@QueryField(type = QueryType.EQ)
private Integer uid;
@ApiModelProperty(value = "状态:1,正常;2,禁用")
@QueryField(type = QueryType.EQ)
private Integer status;
@ApiModelProperty(value = "失效时间")
private String expireTime;
}
@@ -85,6 +85,10 @@ public class ThinkVipParam extends BaseParam {
@QueryField(type = QueryType.EQ)
private Integer vipType;
@ApiModelProperty(value = "培训机构ID")
@QueryField(type = QueryType.EQ)
private Integer trainingInstitutionId;
@ApiModelProperty(value = "特殊卡开发凭证图")
private String pic;
@@ -0,0 +1,114 @@
package com.gxwebsoft.think.service;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 闸机控制远程调用
*
* @author WebSoft
* @since 2026-03-13
*/
@Service
public class ThinkGateControlService {
private static final String BASE_URL = "http://47.121.133.163:18098";
private static final String ACCESS_TOKEN = "6F9B7E4DA34AB1B5EA95CF4B6FBDABE0";
private static final String LEVEL_ID = "8a94a9d19cd1f3fa019ce34a58133b8f";
public String getLevelId() {
return LEVEL_ID;
}
public Object accLevelList(Integer pageNo, Integer pageSize) {
String apiUrl = BASE_URL + "/api/v2/accLevel/list";
Map<String, Object> params = new HashMap<>();
params.put("pageNo", pageNo);
params.put("pageSize", pageSize);
params.put("access_token", ACCESS_TOKEN);
String response = HttpRequest.get(apiUrl)
.form(params)
.timeout(20000)
.execute()
.body();
return parseJson(response);
}
public Object syncPerson(String pin, String levelIds) {
String apiUrl = BASE_URL + "/api/accLevel/syncPerson";
Map<String, Object> params = new HashMap<>();
params.put("pin", pin);
params.put("levelIds", levelIds);
params.put("access_token", ACCESS_TOKEN);
String response = HttpRequest.post(apiUrl)
.body(JSONObject.toJSONString(params))
.timeout(20000)
.execute()
.body();
return parseJson(response);
}
public Object detectFace(Map<String, Object> params) {
String apiUrl = BASE_URL + "/api/v2/person/detectFace?access_token=" + ACCESS_TOKEN;
Map<String, Object> reqParams = new HashMap<>();
reqParams.put("personPhoto", params.get("personPhoto"));
String response = HttpRequest.post(apiUrl)
.body(JSONObject.toJSONString(reqParams))
.timeout(20000)
.execute()
.body();
return parseJson(response);
}
public Object deleteByPins(String pins) {
String apiUrl = BASE_URL + "/api/person/deleteByPins?access_token=" + ACCESS_TOKEN + "&pins=" + pins;
Map<String, Object> params = new HashMap<>();
params.put("pins", pins);
String response = HttpRequest.post(apiUrl)
.body(JSONObject.toJSONString(params))
.timeout(20000)
.execute()
.body();
return parseJson(response);
}
public String addPersons(List<Map<String, Object>> personList) {
String apiUrl = BASE_URL + "/api/v2/person/addPersons?access_token=" + ACCESS_TOKEN;
return HttpRequest.post(apiUrl)
.body(JSONObject.toJSONString(personList))
.timeout(20000)
.execute()
.body();
}
public Object transactionList() {
String apiUrl = BASE_URL + "/api/transaction/list";
Map<String, Object> params = new HashMap<>();
params.put("pageNo", 1);
params.put("pageSize", 999);
params.put("access_token", ACCESS_TOKEN);
String response = HttpRequest.get(apiUrl)
.form(params)
.timeout(20000)
.execute()
.body();
return parseJson(response);
}
private Object parseJson(String response) {
if (StrUtil.isBlank(response)) {
return response;
}
try {
return JSONObject.parse(response);
} catch (Exception e) {
return response;
}
}
}
@@ -41,5 +41,7 @@ public interface ThinkMachineOpenLogService extends IService<ThinkMachineOpenLog
ThinkMachineOpenLog getByOrderId(Integer orderId);
ThinkMachineOpenLog getByLogId(Integer logId);
List<ThinkMachineOpenLog> listByOids(List<Integer> orderIds);
}
@@ -74,6 +74,8 @@ public interface ThinkOrderService extends IService<ThinkOrder> {
ThinkOrder getTodayOrder(Integer userId);
List<ThinkOrder> getTodayOrderList(Integer userId);
List<ThinkOrder> getTodayOrderInSite(Integer userId, Integer sid, String date);
ThinkOrder getUnCheckBillByWechatCode(String wechatCode, long startTime, long endTime);
@@ -0,0 +1,47 @@
package com.gxwebsoft.think.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.think.entity.ThinkSmallRecharge;
import com.gxwebsoft.think.param.ThinkSmallRechargeParam;
import java.util.List;
/**
* Service
*
* @author 科技小王子
* @since 2026-01-07 21:24:29
*/
public interface ThinkSmallRechargeService extends IService<ThinkSmallRecharge> {
/**
* 分页关联查询
*
* @param param 查询参数
* @return PageResult<ThinkSmallRecharge>
*/
PageResult<ThinkSmallRecharge> pageRel(ThinkSmallRechargeParam param);
/**
* 关联查询全部
*
* @param param 查询参数
* @return List<ThinkSmallRecharge>
*/
List<ThinkSmallRecharge> listRel(ThinkSmallRechargeParam param);
/**
* 根据id查询
*
* @param id
* @return ThinkSmallRecharge
*/
ThinkSmallRecharge getByIdRel(Integer id);
ThinkSmallRecharge getByOrderNo(String orderNo);
ThinkSmallRecharge checkByVid(Integer vid);
ThinkSmallRecharge checkByCid(Integer cid);
}
@@ -0,0 +1,32 @@
package com.gxwebsoft.think.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.think.entity.ThinkTrainingInstitution;
import com.gxwebsoft.think.param.ThinkTrainingInstitutionParam;
import java.util.List;
/**
* 培训机构 Service
*
* @author Codex
* @since 2026-04-16
*/
public interface ThinkTrainingInstitutionService extends IService<ThinkTrainingInstitution> {
/**
* 分页关联查询
*/
PageResult<ThinkTrainingInstitution> pageRel(ThinkTrainingInstitutionParam param);
/**
* 查询全部
*/
List<ThinkTrainingInstitution> listRel(ThinkTrainingInstitutionParam param);
/**
* 根据 id 查询
*/
ThinkTrainingInstitution getByIdRel(Integer id);
}
@@ -0,0 +1,43 @@
package com.gxwebsoft.think.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.think.entity.ThinkUserInAccess;
import com.gxwebsoft.think.param.ThinkUserInAccessParam;
import java.util.List;
/**
* 能刷脸开闸的用户列表Service
*
* @author 科技小王子
* @since 2026-03-13 02:27:34
*/
public interface ThinkUserInAccessService extends IService<ThinkUserInAccess> {
/**
* 分页关联查询
*
* @param param 查询参数
* @return PageResult<ThinkUserInAccess>
*/
PageResult<ThinkUserInAccess> pageRel(ThinkUserInAccessParam param);
/**
* 关联查询全部
*
* @param param 查询参数
* @return List<ThinkUserInAccess>
*/
List<ThinkUserInAccess> listRel(ThinkUserInAccessParam param);
/**
* 根据id查询
*
* @param id
* @return ThinkUserInAccess
*/
ThinkUserInAccess getByIdRel(Integer id);
ThinkUserInAccess checkByUid(Integer id);
}
@@ -0,0 +1,32 @@
package com.gxwebsoft.think.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.think.entity.ThinkUsersBlack;
import com.gxwebsoft.think.param.ThinkUsersBlackParam;
import java.util.List;
/**
* 用户黑名单 Service
*
* @author Codex
* @since 2026-06-04
*/
public interface ThinkUsersBlackService extends IService<ThinkUsersBlack> {
/**
* 分页关联查询
*/
PageResult<ThinkUsersBlack> pageRel(ThinkUsersBlackParam param);
/**
* 查询全部
*/
List<ThinkUsersBlack> listRel(ThinkUsersBlackParam param);
/**
* 根据 id 查询
*/
ThinkUsersBlack getByIdRel(Integer id);
}
@@ -65,11 +65,13 @@ public class ThinkCardServiceImpl extends ServiceImpl<ThinkCardMapper, ThinkCard
Set<Integer> vidList = list.stream().map(ThinkCard::getVid).collect(Collectors.toSet());
List<ThinkVip> vipList = thinkVipService.listByIds(vidList);
for (ThinkCard item : list) {
String[] sids = item.getSid().split(",");
item.setSiteList(thinkSiteService.listByIds(Arrays.stream(sids).map(Integer::valueOf).toList()));
item.setThinkVip(vipList.stream().filter(item1 -> item1.getId().equals(item.getVid())).findFirst().orElse(null));
if (item.getIsInvoice().equals(1)) {
item.setThinkInvoice(thinkInvoiceService.getByOidNType(item.getId(), 3));
if (!item.getSid().isEmpty()) {
String[] sids = item.getSid().split(",");
item.setSiteList(thinkSiteService.listByIds(Arrays.stream(sids).map(Integer::valueOf).toList()));
item.setThinkVip(vipList.stream().filter(item1 -> item1.getId().equals(item.getVid())).findFirst().orElse(null));
if (item.getIsInvoice().equals(1)) {
item.setThinkInvoice(thinkInvoiceService.getByOidNType(item.getId(), 3));
}
}
}
}
@@ -57,6 +57,7 @@ public class ThinkInvoiceServiceImpl extends ServiceImpl<ThinkInvoiceMapper, Thi
ThinkInvoiceParam param = new ThinkInvoiceParam();
param.setOid(oid);
param.setItype(iType);
param.setDeleted(0);
return param.getOne(baseMapper.selectListRel(param));
}
@@ -52,6 +52,15 @@ public class ThinkMachineOpenLogServiceImpl extends ServiceImpl<ThinkMachineOpen
return param.getOne(baseMapper.selectListRel(param));
}
@Override
public ThinkMachineOpenLog getByLogId(Integer logId) {
return getOne(
new LambdaQueryWrapper<ThinkMachineOpenLog>()
.eq(ThinkMachineOpenLog::getLogId, logId)
.last("limit 1")
);
}
@Override
public List<ThinkMachineOpenLog> listByOids(List<Integer> orderIds) {
return list(
@@ -258,6 +258,7 @@ public class ThinkOrderServiceImpl extends ServiceImpl<ThinkOrderMapper, ThinkOr
try {
String data = aes.decryptStr(qrCode);
String[] idArr = data.split("_");
System.out.println("check code res: " + idArr[0] + "," + idArr[1]);
if ((int) (System.currentTimeMillis() / 1000) > Long.parseLong(idArr[1]) + 30) {
return new HashMap<>() {{
put("res", false);
@@ -272,6 +273,9 @@ public class ThinkOrderServiceImpl extends ServiceImpl<ThinkOrderMapper, ThinkOr
} catch (Exception e) {
System.out.println(e.getMessage());
System.out.println(e.getStackTrace());
for (StackTraceElement stackTraceElement : e.getStackTrace()) {
System.out.println(stackTraceElement.toString());
}
return new HashMap<>() {{
put("res", false);
put("msg", "系统错误");
@@ -805,6 +809,7 @@ public class ThinkOrderServiceImpl extends ServiceImpl<ThinkOrderMapper, ThinkOr
}
thinkUsersVip.setUseTime(0L);
thinkUsersVipService.updateById(thinkUsersVip);
redisUtil.delete(thinkUsersVip.getId() + "_" + DateUtil.today());
}
}
ThinkCard card = null;
@@ -823,10 +828,11 @@ public class ThinkOrderServiceImpl extends ServiceImpl<ThinkOrderMapper, ThinkOr
} else if (card.getType().equals(2)) {
card.setNum(card.getNum() + num);
}
redisUtil.delete(card.getId() + "_" + DateUtil.today());
card.setUseTime(0L);
thinkCardService.updateById(card);
}
if (thinkOrder1.getWechatOrder() != null && !thinkOrder1.getWechatOrder().isEmpty() && thinkOrder1.getWechatOrder().contains("420000")) {
if (thinkOrder1.getWechatOrder() != null && !thinkOrder1.getWechatOrder().isEmpty() && (thinkOrder1.getWechatOrder().contains("420000") || thinkOrder1.getWechatOrder().contains("450000"))) {
ThinkOrderRefundLog thinkOrderRefundLog = new ThinkOrderRefundLog();
thinkOrderRefundLog.setOid(thinkOrder.getId());
thinkOrderRefundLog.setRefundNo("R" + thinkOrder1.getOrderNum());
@@ -881,6 +887,20 @@ public class ThinkOrderServiceImpl extends ServiceImpl<ThinkOrderMapper, ThinkOr
);
}
@Override
public List<ThinkOrder> getTodayOrderList(Integer userId) {
return list(
new LambdaQueryWrapper<ThinkOrder>()
.eq(ThinkOrder::getUid, userId)
.eq(ThinkOrder::getPayStatus, 1)
.eq(ThinkOrder::getOrderStatus, 2)
.between(ThinkOrder::getCreateTime,
DateUtil.parse(DateUtil.today() + " 00:00:00").getTime() / 1000,
(int) (System.currentTimeMillis() / 1000))
.orderByDesc(ThinkOrder::getCreateTime)
);
}
@Override
public List<ThinkOrder> getTodayOrderInSite(Integer userId, Integer sid, String date) {
return list(
@@ -0,0 +1,90 @@
package com.gxwebsoft.think.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gxwebsoft.think.mapper.ThinkSmallRechargeMapper;
import com.gxwebsoft.think.service.ThinkCardService;
import com.gxwebsoft.think.service.ThinkSmallRechargeService;
import com.gxwebsoft.think.entity.ThinkSmallRecharge;
import com.gxwebsoft.think.param.ThinkSmallRechargeParam;
import com.gxwebsoft.common.core.web.PageParam;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.think.service.ThinkUsersVipService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
/**
* Service实现
*
* @author 科技小王子
* @since 2026-01-07 21:24:29
*/
@Service
public class ThinkSmallRechargeServiceImpl extends ServiceImpl<ThinkSmallRechargeMapper, ThinkSmallRecharge> implements ThinkSmallRechargeService {
@Resource
private ThinkUsersVipService thinkUsersVipService;
@Resource
private ThinkCardService thinkCardService;
@Override
public PageResult<ThinkSmallRecharge> pageRel(ThinkSmallRechargeParam param) {
PageParam<ThinkSmallRecharge, ThinkSmallRechargeParam> page = new PageParam<>(param);
page.setDefaultOrder("create_time desc");
List<ThinkSmallRecharge> list = baseMapper.selectPageRel(page, param);
for (ThinkSmallRecharge item : list) {
if (item.getVid() != null && item.getVid() > 0)
item.setUsersVip(thinkUsersVipService.getByIdRel(item.getVid()));
if (item.getCid() != null && item.getCid() > 0)
item.setCard(thinkCardService.getByIdRel(item.getCid()));
}
return new PageResult<>(list, page.getTotal());
}
@Override
public List<ThinkSmallRecharge> listRel(ThinkSmallRechargeParam param) {
List<ThinkSmallRecharge> list = baseMapper.selectListRel(param);
// 排序
PageParam<ThinkSmallRecharge, ThinkSmallRechargeParam> page = new PageParam<>();
page.setDefaultOrder("create_time desc");
return page.sortRecords(list);
}
@Override
public ThinkSmallRecharge getByIdRel(Integer id) {
ThinkSmallRechargeParam param = new ThinkSmallRechargeParam();
param.setId(id);
return param.getOne(baseMapper.selectListRel(param));
}
@Override
public ThinkSmallRecharge getByOrderNo(String orderNo) {
return getOne(
new LambdaQueryWrapper<ThinkSmallRecharge>()
.eq(ThinkSmallRecharge::getOrderNo, orderNo)
.last("limit 1")
);
}
@Override
public ThinkSmallRecharge checkByVid(Integer vid) {
return getOne(
new LambdaQueryWrapper<ThinkSmallRecharge>()
.eq(ThinkSmallRecharge::getVid, vid)
.eq(ThinkSmallRecharge::getStatus, 1)
.last("limit 1")
);
}
@Override
public ThinkSmallRecharge checkByCid(Integer cid) {
return getOne(
new LambdaQueryWrapper<ThinkSmallRecharge>()
.eq(ThinkSmallRecharge::getCid, cid)
.eq(ThinkSmallRecharge::getStatus, 1)
.last("limit 1")
);
}
}
@@ -0,0 +1,47 @@
package com.gxwebsoft.think.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gxwebsoft.common.core.web.PageParam;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.think.entity.ThinkTrainingInstitution;
import com.gxwebsoft.think.mapper.ThinkTrainingInstitutionMapper;
import com.gxwebsoft.think.param.ThinkTrainingInstitutionParam;
import com.gxwebsoft.think.service.ThinkTrainingInstitutionService;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 培训机构 Service 实现
*
* @author Codex
* @since 2026-04-16
*/
@Service
public class ThinkTrainingInstitutionServiceImpl
extends ServiceImpl<ThinkTrainingInstitutionMapper, ThinkTrainingInstitution>
implements ThinkTrainingInstitutionService {
@Override
public PageResult<ThinkTrainingInstitution> pageRel(ThinkTrainingInstitutionParam param) {
PageParam<ThinkTrainingInstitution, ThinkTrainingInstitutionParam> page = new PageParam<>(param);
page.setDefaultOrder("create_time desc");
List<ThinkTrainingInstitution> list = baseMapper.selectPageRel(page, param);
return new PageResult<>(list, page.getTotal());
}
@Override
public List<ThinkTrainingInstitution> listRel(ThinkTrainingInstitutionParam param) {
List<ThinkTrainingInstitution> list = baseMapper.selectListRel(param);
PageParam<ThinkTrainingInstitution, ThinkTrainingInstitutionParam> page = new PageParam<>();
page.setDefaultOrder("create_time desc");
return page.sortRecords(list);
}
@Override
public ThinkTrainingInstitution getByIdRel(Integer id) {
ThinkTrainingInstitutionParam param = new ThinkTrainingInstitutionParam();
param.setId(id);
return param.getOne(baseMapper.selectListRel(param));
}
}
@@ -0,0 +1,56 @@
package com.gxwebsoft.think.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gxwebsoft.think.mapper.ThinkUserInAccessMapper;
import com.gxwebsoft.think.service.ThinkUserInAccessService;
import com.gxwebsoft.think.entity.ThinkUserInAccess;
import com.gxwebsoft.think.param.ThinkUserInAccessParam;
import com.gxwebsoft.common.core.web.PageParam;
import com.gxwebsoft.common.core.web.PageResult;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 能刷脸开闸的用户列表Service实现
*
* @author 科技小王子
* @since 2026-03-13 02:27:34
*/
@Service
public class ThinkUserInAccessServiceImpl extends ServiceImpl<ThinkUserInAccessMapper, ThinkUserInAccess> implements ThinkUserInAccessService {
@Override
public PageResult<ThinkUserInAccess> pageRel(ThinkUserInAccessParam param) {
PageParam<ThinkUserInAccess, ThinkUserInAccessParam> page = new PageParam<>(param);
page.setDefaultOrder("create_time desc");
List<ThinkUserInAccess> list = baseMapper.selectPageRel(page, param);
return new PageResult<>(list, page.getTotal());
}
@Override
public List<ThinkUserInAccess> listRel(ThinkUserInAccessParam param) {
List<ThinkUserInAccess> list = baseMapper.selectListRel(param);
// 排序
PageParam<ThinkUserInAccess, ThinkUserInAccessParam> page = new PageParam<>();
page.setDefaultOrder("create_time desc");
return page.sortRecords(list);
}
@Override
public ThinkUserInAccess getByIdRel(Integer id) {
ThinkUserInAccessParam param = new ThinkUserInAccessParam();
param.setId(id);
return param.getOne(baseMapper.selectListRel(param));
}
@Override
public ThinkUserInAccess checkByUid(Integer uid) {
return getOne(
new LambdaQueryWrapper<ThinkUserInAccess>()
.eq(ThinkUserInAccess::getUid, uid)
);
}
}
@@ -0,0 +1,47 @@
package com.gxwebsoft.think.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gxwebsoft.common.core.web.PageParam;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.think.entity.ThinkUsersBlack;
import com.gxwebsoft.think.mapper.ThinkUsersBlackMapper;
import com.gxwebsoft.think.param.ThinkUsersBlackParam;
import com.gxwebsoft.think.service.ThinkUsersBlackService;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 用户黑名单 Service 实现
*
* @author Codex
* @since 2026-06-04
*/
@Service
public class ThinkUsersBlackServiceImpl
extends ServiceImpl<ThinkUsersBlackMapper, ThinkUsersBlack>
implements ThinkUsersBlackService {
@Override
public PageResult<ThinkUsersBlack> pageRel(ThinkUsersBlackParam param) {
PageParam<ThinkUsersBlack, ThinkUsersBlackParam> page = new PageParam<>(param);
page.setDefaultOrder("create_time desc");
List<ThinkUsersBlack> list = baseMapper.selectPageRel(page, param);
return new PageResult<>(list, page.getTotal());
}
@Override
public List<ThinkUsersBlack> listRel(ThinkUsersBlackParam param) {
List<ThinkUsersBlack> list = baseMapper.selectListRel(param);
PageParam<ThinkUsersBlack, ThinkUsersBlackParam> page = new PageParam<>();
page.setDefaultOrder("create_time desc");
return page.sortRecords(list);
}
@Override
public ThinkUsersBlack getByIdRel(Integer id) {
ThinkUsersBlackParam param = new ThinkUsersBlackParam();
param.setId(id);
return param.getOne(baseMapper.selectListRel(param));
}
}
@@ -1,6 +1,8 @@
package com.gxwebsoft.think.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.common.system.service.UserService;
import com.gxwebsoft.think.mapper.ThinkUsersMapper;
import com.gxwebsoft.think.service.ThinkUsersService;
import com.gxwebsoft.think.entity.ThinkUsers;
@@ -9,6 +11,8 @@ import com.gxwebsoft.common.core.web.PageParam;
import com.gxwebsoft.common.core.web.PageResult;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
/**
@@ -19,12 +23,24 @@ import java.util.List;
*/
@Service
public class ThinkUsersServiceImpl extends ServiceImpl<ThinkUsersMapper, ThinkUsers> implements ThinkUsersService {
@Resource
private UserService userService;
@Override
public PageResult<ThinkUsers> pageRel(ThinkUsersParam param) {
PageParam<ThinkUsers, ThinkUsersParam> page = new PageParam<>(param);
page.setDefaultOrder("create_time desc");
List<ThinkUsers> list = baseMapper.selectPageRel(page, param);
for (ThinkUsers user : list) {
if (user.getPhone() != null ){
User user1 = userService.getByPhoneInner(user.getPhone());
user.setBalance(BigDecimal.ZERO);
if (user1 != null) {
user.setBalance(user1.getBalance());
user.setUserId(user1.getUserId());
}
}
}
return new PageResult<>(list, page.getTotal());
}
@@ -46,15 +46,17 @@ public class ThinkVipServiceImpl extends ServiceImpl<ThinkVipMapper, ThinkVip> i
list.forEach(d -> {
final ArrayList<String> siteNames = new ArrayList<>();
final String sid = d.getSid();
final String[] split = sid.split(",");
for (String siteId : split) {
final List<ThinkSite> thinkSites = collect.get(Integer.valueOf(siteId));
if (!CollectionUtils.isEmpty(thinkSites)) {
final String name = thinkSites.get(0).getName();
siteNames.add(name);
if (!sid.isEmpty()) {
final String[] split = sid.split(",");
for (String siteId : split) {
final List<ThinkSite> thinkSites = collect.get(Integer.valueOf(siteId));
if (!CollectionUtils.isEmpty(thinkSites)) {
final String name = thinkSites.get(0).getName();
siteNames.add(name);
}
}
d.setSiteNames(String.join(",", siteNames));
}
d.setSiteNames(String.join(",", siteNames));
});
return new PageResult<>(list, page.getTotal());
}
@@ -129,7 +131,8 @@ public class ThinkVipServiceImpl extends ServiceImpl<ThinkVipMapper, ThinkVip> i
List<ThinkVip> cardList = list(wrapper);
for (ThinkVip card : cardList) {
List<ThinkSite> siteList = thinkSiteService.listByIds(Arrays.stream(card.getSid().split(",")).map(Integer::valueOf).toList());
if (!siteList.isEmpty()) card.setSiteNames(String.join(",", siteList.stream().map(ThinkSite::getName).toList()));
if (!siteList.isEmpty())
card.setSiteNames(String.join(",", siteList.stream().map(ThinkSite::getName).toList()));
}
thinkVip.setCardList(cardList);
}
@@ -138,7 +141,7 @@ public class ThinkVipServiceImpl extends ServiceImpl<ThinkVipMapper, ThinkVip> i
}
@Override
public List<ThinkVip> total(ThinkVipParam param){
public List<ThinkVip> total(ThinkVipParam param) {
List<ThinkVip> list = list();
LambdaQueryWrapper<ThinkUsersVip> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(ThinkUsersVip::getStatus, 1);
@@ -0,0 +1,356 @@
package com.gxwebsoft.think.task;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gxwebsoft.common.core.utils.RedisUtil;
import com.gxwebsoft.think.entity.*;
import com.gxwebsoft.think.service.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
* 人脸权限定时同步
*
* @author WebSoft
* @since 2026-03-13
*/
@Component
public class ThinkFaceAccessTask {
private static final Logger logger = LoggerFactory.getLogger(ThinkFaceAccessTask.class);
private static final int BATCH_SIZE = 100;
private static final String LOCK_KEY = "think:face:access:sync";
private static final String ORDER_FACE_SYNC_LOCK_KEY = "think:face:access:order:sync";
private static final DateTimeFormatter ACCESS_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@Resource
private RedisUtil redisUtil;
@Resource
private ThinkUserInAccessService thinkUserInAccessService;
@Resource
private ThinkCardService thinkCardService;
@Resource
private ThinkUsersVipService thinkUsersVipService;
@Resource
private ThinkUsersService thinkUsersService;
@Resource
private ThinkGateControlService thinkGateControlService;
@Resource
private ThinkOrderService thinkOrderService;
@Resource
private ThinkOrderInfoService thinkOrderInfoService;
@Resource
private ThinkMachineOpenLogService thinkMachineOpenLogService;
@Scheduled(cron = "*/5 * * * * ?")
public void syncTodayOrderFaceAccess() {
if (redisUtil.get(ORDER_FACE_SYNC_LOCK_KEY) != null) {
logger.info("skip syncTodayOrderFaceAccess, last task is still locked");
return;
}
redisUtil.set(ORDER_FACE_SYNC_LOCK_KEY, DateUtil.currentSeconds(), 30L, TimeUnit.SECONDS);
try {
long startTime = DateUtil.parse(DateUtil.today() + " 00:00:00").getTime() / 1000;
long now = System.currentTimeMillis() / 1000;
List<ThinkOrder> orderList = thinkOrderService.list(
new LambdaQueryWrapper<ThinkOrder>()
.select(ThinkOrder::getUid)
.eq(ThinkOrder::getPayStatus, 1)
.eq(ThinkOrder::getOrderStatus, 2)
.eq(ThinkOrder::getSid, 37)
.between(ThinkOrder::getCreateTime, startTime, now)
);
if (orderList == null || orderList.isEmpty()) {
return;
}
Set<Integer> uidSet = orderList.stream()
.map(ThinkOrder::getUid)
.filter(Objects::nonNull)
.collect(Collectors.toCollection(LinkedHashSet::new));
if (uidSet.isEmpty()) {
return;
}
List<ThinkUsers> faceUsers = thinkUsersService.list(
new LambdaQueryWrapper<ThinkUsers>()
.in(ThinkUsers::getId, uidSet)
.eq(ThinkUsers::getHasFace, 1)
.isNotNull(ThinkUsers::getPersonPhoto)
.ne(ThinkUsers::getPersonPhoto, "")
);
if (faceUsers == null || faceUsers.isEmpty()) {
return;
}
for (ThinkUsers faceUser : faceUsers) {
syncFaceUserToAccess(faceUser);
}
logger.info("syncTodayOrderFaceAccess success, orderCount={}, userCount={}", orderList.size(), faceUsers.size());
} catch (Exception e) {
logger.error("syncTodayOrderFaceAccess failed", e);
} finally {
redisUtil.delete(ORDER_FACE_SYNC_LOCK_KEY);
}
}
@Scheduled(cron = "*/5 * * * * ?")
public void syncTransactionList() {
try {
logger.info("syncTransactionList start");
Object res = thinkGateControlService.transactionList();
if (!(res instanceof Map)) {
logger.info("syncTransactionList skip, invalid res={}", res);
return;
}
Map<String, Object> map = (Map<String, Object>) res;
Object codeObj = map.get("code");
if (!"0".equals(String.valueOf(codeObj))) {
logger.info("syncTransactionList skip, code={}, res={}", codeObj, res);
return;
}
Object dataObj = map.get("data");
if (!(dataObj instanceof List)) {
logger.info("syncTransactionList skip, data is not list, data={}", dataObj);
return;
}
List<Map<String, Object>> transactionList = new ArrayList<>();
for (Object item : (List<?>) dataObj) {
if (!(item instanceof Map)) {
continue;
}
Map<?, ?> rawMap = (Map<?, ?>) item;
Object pinObj = rawMap.get("pin");
if (StrUtil.isBlank(pinObj == null ? null : String.valueOf(pinObj))) {
continue;
}
Map<String, Object> transaction = new HashMap<>();
for (Map.Entry<?, ?> entry : rawMap.entrySet()) {
if (entry.getKey() != null) {
transaction.put(String.valueOf(entry.getKey()), entry.getValue());
}
}
transactionList.add(transaction);
if (transactionList.size() >= 100) {
break;
}
}
for (Map<String, Object> transaction : transactionList) {
Integer pin = Integer.valueOf(String.valueOf(transaction.get("pin")));
List<ThinkOrder> thinkOrderList = thinkOrderService.getTodayOrderList(pin);
for (ThinkOrder thinkOrder : thinkOrderList) {
ThinkMachineOpenLog openLog = thinkMachineOpenLogService.getByOrderId(thinkOrder.getId());
Integer logId = Integer.valueOf(String.valueOf(transaction.get("logId")));
ThinkMachineOpenLog check = thinkMachineOpenLogService.getByLogId(logId);
if (openLog == null && check == null) {
ThinkMachineOpenLog thinkMachineOpenLog = new ThinkMachineOpenLog();
thinkMachineOpenLog.setOrderId(thinkOrder.getId());
thinkMachineOpenLog.setLogId(logId);
thinkMachineOpenLogService.save(thinkMachineOpenLog);
int usedNum = 0;
int totalNum = 0;
List<ThinkOrderInfo> thinkOrderInfoList = thinkOrderInfoService.listInOrder(thinkOrder.getId());
for (ThinkOrderInfo thinkOrderInfo : thinkOrderInfoList) {
usedNum += thinkOrderInfo.getUsedNum() + 1;
totalNum += thinkOrderInfo.getAdultNum() + thinkOrderInfo.getChildrenNum();
thinkOrderInfo.setUsedNum(thinkOrderInfo.getUsedNum() + 1);
thinkOrderInfoService.updateById(thinkOrderInfo);
}
if (usedNum == totalNum) {
thinkOrder.setOrderStatus(1);
thinkOrderService.updateById(thinkOrder);
}
thinkGateControlService.deleteByPins(pin.toString());
}
}
}
logger.info("syncTransactionList success, size={}", transactionList.size());
// 后续按需要处理 transactionList
if (!transactionList.isEmpty()) {
logger.debug("syncTransactionList pins={}",
transactionList.stream().map(item -> String.valueOf(item.get("pin"))).collect(Collectors.joining(",")));
}
} catch (Exception e) {
logger.error("syncTransactionList failed", e);
}
}
private void syncFaceUserToAccess(ThinkUsers thinkUsers) {
if (thinkUsers == null || thinkUsers.getId() == null) {
return;
}
try {
ThinkUserInAccess check = thinkUserInAccessService.checkByUid(thinkUsers.getId());
if (check != null) {
return;
}
ThinkUserInAccess thinkUserInAccess = new ThinkUserInAccess();
thinkUserInAccess.setUid(thinkUsers.getId());
thinkUserInAccessService.save(thinkUserInAccess);
List<Map<String, Object>> list = new ArrayList<>();
Map<String, Object> map = new HashMap<>();
String day = DateUtil.format(LocalDateTime.now(), "yyyy-MM-dd");
String accStartTime = day + " 05:00:00";
String accEndTime = day + " 22:00:00";
map.put("pin", String.valueOf(thinkUsers.getId()));
map.put("mobilePhone", thinkUsers.getPhone());
map.put("name", StrUtil.blankToDefault(thinkUsers.getUsername(), String.valueOf(thinkUsers.getId())));
map.put("personPhoto", thinkUsers.getPersonPhoto());
map.put("accEndTime", accEndTime);
map.put("accLevelIds", thinkGateControlService.getLevelId());
map.put("accStartTime", accStartTime);
list.add(map);
thinkGateControlService.addPersons(list);
} catch (Exception e) {
logger.error("syncFaceUserToAccess failed, uid={}", thinkUsers.getId(), e);
}
}
@Scheduled(cron = "0 30 0 * * ?")
public void syncFaceAccess() {
if (redisUtil.get(LOCK_KEY) != null) {
logger.info("skip syncFaceAccess, last task is still locked");
return;
}
redisUtil.set(LOCK_KEY, DateUtil.currentSeconds(), 2L, TimeUnit.HOURS);
try {
clearRemotePersons();
List<ThinkUsers> faceUsers = listAvailableFaceUsers();
syncRemotePersons(faceUsers);
rebuildLocalAccessRecords(faceUsers);
logger.info("syncFaceAccess finished, userCount={}", faceUsers.size());
} catch (Exception e) {
logger.error("syncFaceAccess failed", e);
}
}
private void clearRemotePersons() {
long pageNo = 1L;
while (true) {
Page<ThinkUserInAccess> page = thinkUserInAccessService.page(
new Page<>(pageNo, BATCH_SIZE),
new LambdaQueryWrapper<ThinkUserInAccess>().orderByAsc(ThinkUserInAccess::getId)
);
List<ThinkUserInAccess> records = page.getRecords();
if (records == null || records.isEmpty()) {
return;
}
String pins = records.stream()
.map(ThinkUserInAccess::getUid)
.filter(uid -> uid != null)
.map(String::valueOf)
.collect(Collectors.joining(","));
if (StrUtil.isNotBlank(pins)) {
thinkGateControlService.deleteByPins(pins);
}
if (pageNo >= page.getPages()) {
return;
}
pageNo++;
}
}
private List<ThinkUsers> listAvailableFaceUsers() {
long now = DateUtil.currentSeconds();
Set<Integer> uidSet = new LinkedHashSet<>();
List<ThinkCard> thinkCardList = thinkCardService.list(
new LambdaQueryWrapper<ThinkCard>()
.gt(ThinkCard::getExpireTime, now)
.select(ThinkCard::getUid)
);
uidSet.addAll(thinkCardList.stream()
.map(ThinkCard::getUid)
.filter(uid -> uid != null)
.toList());
List<ThinkUsersVip> thinkUsersVipList = thinkUsersVipService.list(
new LambdaQueryWrapper<ThinkUsersVip>()
.gt(ThinkUsersVip::getExpireTime, now)
.select(ThinkUsersVip::getUid)
);
uidSet.addAll(thinkUsersVipList.stream()
.map(ThinkUsersVip::getUid)
.filter(uid -> uid != null)
.toList());
if (uidSet.isEmpty()) {
return Collections.emptyList();
}
return thinkUsersService.list(
new LambdaQueryWrapper<ThinkUsers>()
.in(ThinkUsers::getId, uidSet)
.eq(ThinkUsers::getHasFace, 1)
.isNotNull(ThinkUsers::getPersonPhoto)
.ne(ThinkUsers::getPersonPhoto, "")
);
}
private void syncRemotePersons(List<ThinkUsers> faceUsers) {
if (faceUsers == null || faceUsers.isEmpty()) {
return;
}
List<Map<String, Object>> personList = new ArrayList<>(faceUsers.size());
String accStartTime = formatTodayTime(5);
String accEndTime = formatTodayTime(22);
for (ThinkUsers faceUser : faceUsers) {
Map<String, Object> person = new HashMap<>();
person.put("pin", String.valueOf(faceUser.getId()));
person.put("mobilePhone", faceUser.getPhone());
person.put("name", StrUtil.blankToDefault(faceUser.getUsername(), String.valueOf(faceUser.getId())));
person.put("personPhoto", faceUser.getPersonPhoto());
person.put("accEndTime", accEndTime);
person.put("accLevelIds", thinkGateControlService.getLevelId());
person.put("accStartTime", accStartTime);
personList.add(person);
}
for (int i = 0; i < personList.size(); i += BATCH_SIZE) {
int end = Math.min(i + BATCH_SIZE, personList.size());
thinkGateControlService.addPersons(personList.subList(i, end));
}
}
private void rebuildLocalAccessRecords(List<ThinkUsers> faceUsers) {
thinkUserInAccessService.remove(new LambdaQueryWrapper<ThinkUserInAccess>());
if (faceUsers == null || faceUsers.isEmpty()) {
return;
}
List<ThinkUserInAccess> accessList = new ArrayList<>(faceUsers.size());
for (ThinkUsers faceUser : faceUsers) {
ThinkUserInAccess access = new ThinkUserInAccess();
access.setUid(faceUser.getId());
accessList.add(access);
}
thinkUserInAccessService.saveBatch(accessList, BATCH_SIZE);
}
private String formatTodayTime(int hour) {
return LocalDateTime.of(LocalDate.now(), java.time.LocalTime.of(hour, 0))
.format(ACCESS_TIME_FORMATTER);
}
}