Merge remote-tracking branch 'origin/test' into dev

# Conflicts:
#	src/main/java/com/sqx/modules/app/controller/app/AppLoginController.java
#	src/main/java/com/sqx/modules/app/service/impl/UserServiceImpl.java
#	src/main/java/com/sqx/modules/orders/controller/app/AppOrdersController.java
This commit is contained in:
Tankaikai 2025-04-02 16:45:19 +08:00
commit 9f88726dde
20 changed files with 949 additions and 83 deletions

View File

@ -1,6 +1,7 @@
package com.sqx.common.aspect;
import com.sqx.common.annotation.Debounce;
import com.sqx.common.exception.SqxException;
import com.sqx.common.utils.Result;
import com.sqx.common.utils.SpelUtil;
import org.apache.commons.lang3.StringUtils;
@ -26,8 +27,8 @@ import java.util.concurrent.locks.ReentrantLock;
public class DebounceAspect {
@Pointcut("@annotation(com.sqx.common.annotation.Debounce)")
public void logPointCut() {
public void logPointCut() {
}
// 用于存储基于方法和入参情况的上次执行时间结构为方法签名 -> (入参值 -> 上次执行时间)
@ -87,7 +88,16 @@ public class DebounceAspect {
if (lastTime == null || currentTime - timeUnit.toMillis(interval) >= lastTime) {
// 满足防抖间隔更新上次执行时间并执行目标方法
methodExecutionTimeMap.put(targetValue, currentTime);
return joinPoint.proceed();
try {
return joinPoint.proceed();
}catch (Exception e) {
if (e instanceof SqxException && ((SqxException) e).getCode() == 407) {
methodExecutionTimeMap.remove(targetValue);
}
throw e;
}
}
// 在防抖间隔内不执行目标方法直接返回
return Result.error("请求频繁,请重试");

View File

@ -0,0 +1,35 @@
package com.sqx.common.utils;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMap;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* @author tankaikai
* @since 2025-03-28 10:16
*/
@Component
public class SqlFetcher {
@Autowired
private SqlSessionFactory sqlSessionFactory;
public String getSqlFromXml(String statementId, Object parameterObject) {
// 获取Configuration对象
Configuration configuration = sqlSessionFactory.getConfiguration();
try {
// 获取指定ID的MappedStatement对象
MappedStatement mappedStatement = configuration.getMappedStatement(statementId);
// 获取SQL语句
if(parameterObject instanceof String){
SqlUtil.escapeOrderBySql((String) parameterObject);
}
return mappedStatement.getBoundSql(parameterObject).getSql();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}

View File

@ -0,0 +1,66 @@
package com.sqx.common.utils;
import cn.hutool.core.util.StrUtil;
import java.util.Objects;
import java.util.regex.Pattern;
/**
* sql操作工具类
*
* @author ruoyi
*/
public class SqlUtil {
/**
* SQL语法检查正则符合两个关键字有先后顺序才算匹配
*/
private static final Pattern SQL_SYNTAX_PATTERN = Pattern.compile("(insert|delete|update|select|create|drop|truncate|grant|alter|deny|revoke|call|execute|exec|declare|show|rename|set)" +
"\\s+.*(into|from|set|where|table|database|view|index|on|cursor|procedure|trigger|for|password|union|and|or)|(select\\s*\\*\\s*from\\s+)" +
"|if\\s*\\(.*\\)|select\\s*\\(.*\\)|substr\\s*\\(.*\\)|substring\\s*\\(.*\\)|char\\s*\\(.*\\)|concat\\s*\\(.*\\)|benchmark\\s*\\(.*\\)|sleep\\s*\\(.*\\)|(and|or)\\s+.*", Pattern.CASE_INSENSITIVE);
/**
* 使用';或注释截断SQL检查正则
*/
private static final Pattern SQL_COMMENT_PATTERN = Pattern.compile("'.*(or|union|--|#|/\\*|;)", Pattern.CASE_INSENSITIVE);
/**
* 限制orderBy最大长度
*/
private static final int ORDER_BY_MAX_LENGTH = 500;
/**
* 检查字符防止注入绕过
*/
public static String escapeOrderBySql(String value) {
if (StrUtil.isNotEmpty(value)) {
if (check(value)) {
throw new IllegalArgumentException("参数不符合规范,不能进行查询");
}
if (value.length() > ORDER_BY_MAX_LENGTH) {
throw new IllegalArgumentException("参数已超过最大限制,不能进行查询");
}
}
return value;
}
/**
* 检查参数是否存在 SQL 注入
*
* @param value 检查参数
* @return true 非法 false 合法
*/
public static boolean check(String value) {
Objects.requireNonNull(value);
// 处理是否包含SQL注释字符 || 检查是否包含SQL注入敏感字符
return SQL_COMMENT_PATTERN.matcher(value).find() || SQL_SYNTAX_PATTERN.matcher(value).find();
}
/**
* 刪除字段转义符单引号双引号
*
* @param text 待处理字段
*/
public static String removeEscapeCharacter(String text) {
Objects.nonNull(text);
return text.replaceAll("\"", "").replaceAll("'", "");
}
}

View File

@ -1,6 +1,7 @@
package com.sqx.modules.app.controller.app;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.sqx.common.annotation.Debounce;
@ -9,7 +10,6 @@ import com.sqx.modules.app.annotation.Login;
import com.sqx.modules.app.dto.BindWxDTO;
import com.sqx.modules.app.dto.LoginDTO;
import com.sqx.modules.app.dto.RegisterDTO;
import com.sqx.modules.app.dto.UserInviteDTO;
import com.sqx.modules.app.entity.UserEntity;
import com.sqx.modules.app.service.IAppleService;
import com.sqx.modules.app.service.UserService;
@ -29,6 +29,8 @@ import org.springframework.web.bind.annotation.*;
import weixin.popular.api.SnsAPI;
import weixin.popular.bean.sns.SnsToken;
import java.util.HashMap;
/**
* APP登录授权
*
@ -174,10 +176,22 @@ public class AppLoginController {
@PostMapping("/bindWx")
@ResponseBody
@Debounce(interval = 2500, value = "#code")
public Result bindWx(@RequestBody BindWxDTO bindWxDTO, @RequestHeader Long userId) {
public Result bindWx(@RequestBody BindWxDTO bindWxDTO, @RequestAttribute("userId") Long userId) {
return userService.bindWx(bindWxDTO, userId);
}
@Login
@GetMapping("/bindStatus")
@ResponseBody
public Result bindWx(@RequestAttribute("userId") Long userId) {
UserEntity userEntity = userService.queryByUserId(userId);
return Result.success(new HashMap<String, Object>(){{
put("data", new HashMap<String, Object>(){{
put("wxBind", StrUtil.isNotBlank(userEntity.getWxOpenId()));
}});
}});
}
@PostMapping("/bindWxOpenPhone")
@ApiOperation("微信公众号绑定手机号")
public Result bindWxOpenPhone(Long userId,String phone,String msg){

View File

@ -1829,17 +1829,20 @@ public class UserServiceImpl extends ServiceImpl<UserDao, UserEntity> implements
@Override
public Result bindWx(BindWxDTO bindWxDTO, Long userId) {
//微信appid
CommonInfo one = commonInfoService.findOne(5);
CommonInfo one = commonInfoService.findOne(937);
//微信秘钥
CommonInfo two = commonInfoService.findOne(21);
CommonInfo two = commonInfoService.findOne(936);
SnsToken snsToken = SnsAPI.oauth2AccessToken(one.getValue(), two.getValue(), bindWxDTO.getCode());
if (!snsToken.isSuccess()) {
return Result.error("获取失败");
}
String openid = snsToken.getOpenid();
int count = count(new LambdaQueryWrapper<UserEntity>().eq(UserEntity::getWxOpenId, openid));
if (count > 0) {
return Result.error("该微信已被其他用户绑定");
}
UserEntity userEntity = getOne(new LambdaQueryWrapper<UserEntity>().eq(UserEntity::getUserId, userId));
UserEntity userEntity = queryByUserId(userId);
if (StringUtils.isNotBlank(userEntity.getWxOpenId())) {
return Result.error("当前用户已绑定微信");
}

View File

@ -0,0 +1,31 @@
package com.sqx.modules.ext.controller;
import cn.hutool.core.exceptions.ValidateException;
import com.sqx.common.utils.Result;
import com.sqx.modules.ext.param.InviteFriendConfigParam;
import com.sqx.modules.ext.service.ExtSysService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* 扩展功能控制层
* @author tankaikai
* @since 2025-03-28 09:32
*/
@RestController
@Api(value = "APP扩展功能", tags = {"APP扩展功能"})
@RequestMapping("/app/ext/sys")
public class AppExtSysController {
@Autowired
private ExtSysService extSysService;
@GetMapping("/invite/friend/config/get")
@ApiOperation("获取邀请好友配置信息")
public Result getInviteFriendConfig(){
InviteFriendConfigParam data = extSysService.getInviteFriendConfig();
return Result.success().put("data", data);
}
}

View File

@ -0,0 +1,88 @@
package com.sqx.modules.ext.controller;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.exceptions.ValidateException;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.sqx.common.utils.PageUtils;
import com.sqx.common.utils.Result;
import com.sqx.modules.app.entity.App;
import com.sqx.modules.app.entity.VipDetails;
import com.sqx.modules.coupon.entity.Coupon;
import com.sqx.modules.ext.param.InviteFriendConfigParam;
import com.sqx.modules.ext.service.ExtSysService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.ws.rs.GET;
import java.util.List;
/**
* 扩展功能控制层
*
* @author tankaikai
* @since 2025-03-28 09:32
*/
@RestController
@Api(value = "ADMIN扩展功能", tags = {"ADMIN扩展功能"})
@RequestMapping("/ext/sys")
public class ExtSysController {
@Autowired
private ExtSysService extSysService;
@PostMapping("/invite/friend/config/save")
@ApiOperation("保存邀请好友配置信息")
public Result saveInviteFriendConfig(@RequestBody InviteFriendConfigParam param) {
try {
extSysService.saveInviteFriendConfig(param);
} catch (ValidateException e) {
return Result.error(e.getMessage());
}
return Result.success();
}
@GetMapping("/invite/friend/config/get")
@ApiOperation("获取邀请好友配置信息")
public Result getInviteFriendConfig() {
InviteFriendConfigParam data = extSysService.getInviteFriendConfig();
return Result.success().put("data", data);
}
@GetMapping("/invite/friend/award/page")
@ApiOperation("邀请好友奖励分页")
public Result getInviteFriendAwardPage(Integer page, Integer limit, String keywords) {
PageUtils data = extSysService.queryInviteFriendRecord(page, limit, keywords);
return Result.success().put("data", data);
}
@GetMapping("/invite/friend/signIn/page")
@ApiOperation("邀请好友奖励-签到人数分页")
public Result getInviteFriendSignInPage(Integer page, Integer limit, String userId) {
PageUtils data = extSysService.queryInviteSignInRecord(page, limit, Convert.toLong(userId));
return Result.success().put("data", data);
}
@GetMapping("/invite/friend/award/detail/page")
@ApiOperation("邀请好友奖励详情分页")
public Result getInviteFriendAwardDetailPage(Integer page, Integer limit, String userId) {
PageUtils data = extSysService.queryInviteAwardDetailRecord(page, limit, Convert.toLong(userId));
return Result.success().put("data", data);
}
@GetMapping("/lottery/count/query/page")
@ApiOperation("抽奖次数查询-分页")
public Result getLotteryCountQueryPage(Integer page, Integer limit, String keywords) {
PageUtils data = extSysService.queryLotteryCountPage(page, limit, keywords);
return Result.success().put("data", data);
}
@GetMapping("/lottery/detail/page")
@ApiOperation("抽奖详情查询-分页")
public Result getLotteryDetailPage(Integer page, Integer limit, String userId) {
PageUtils data = extSysService.queryLotteryDetailPage(page, limit, Convert.toLong(userId));
return Result.success().put("data", data);
}
}

View File

@ -0,0 +1,28 @@
package com.sqx.modules.ext.dao;
import com.sqx.modules.ext.dto.*;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 扩展系统数据访问层
*
* @author tankaikai
* @since 2025-03-28 10:39
*/
@Mapper
public interface ExtSysDao {
List<InviteFriendDTO> findInviteFriendList(@Param("keywords") String keywords);
List<SignInNumDTO> findInviteSignInList(@Param("userId") Long userId);
List<InviteAwardDTO> findInviteAwardDetailList(@Param("userId") Long userId);
List<LotteryCountQueryDTO> findLotteryCountList(@Param("keywords") String keywords);
List<LotteryDetailDTO> findLotteryDetailPage(@Param("userId") Long userId);
}

View File

@ -0,0 +1,41 @@
package com.sqx.modules.ext.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* 邀请奖励明细
*
* @author tankaikai
* @since 2025-03-28 10:07
*/
@Data
public class InviteAwardDTO implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 奖励id
*/
@JsonSerialize(using = ToStringSerializer.class)
private Long userId;
/**
* 发放金额
*/
private BigDecimal amount;
/**
* 有效邀请人
*/
private String userPhone;
/**
* 发放时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
}

View File

@ -0,0 +1,50 @@
package com.sqx.modules.ext.dto;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 邀请好友DTO
*
* @author tankaikai
* @since 2025-03-28 09:56
*/
@Data
public class InviteFriendDTO implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 用户id
*/
@JsonSerialize(using = ToStringSerializer.class)
private Long userId;
/**
* 用户名称
*/
private String userName;
/**
* 手机号
*/
private String phone;
/**
* 头像地址
*/
private String avatar;
/**
* 签到人数
*/
private Integer signInNum;
/**
* 已发放奖励金额
*/
private BigDecimal awardAmount;
}

View File

@ -0,0 +1,57 @@
package com.sqx.modules.ext.dto;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data;
import java.io.Serializable;
/**
* 抽奖次数查询DTO
*
* @author tankaikai
* @since 2025-03-28 10:24
*/
@Data
public class LotteryCountQueryDTO implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 账号ID
*/
@JsonSerialize(using = ToStringSerializer.class)
private Long userId;
/**
* 头像地址
*/
private String avatar;
/**
* 用户名称
*/
private String userName;
/**
* 手机号
*/
private String phone;
/**
* 共解锁
*/
private Integer unlocked;
/**
* 今日解锁
*/
private Integer todayUnlocked;
/**
* 共获得抽奖次数
*/
private Integer totalDrawCount;
/**
* 剩余抽奖次数
*/
private Integer residueDrawCount;
/**
* 今日抽奖次数
*/
private Integer todayDrawCount;
}

View File

@ -0,0 +1,39 @@
package com.sqx.modules.ext.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 抽奖详情DTO类
*
* @author tankaikai
* @since 2025-03-28 10:24
*/
@Data
public class LotteryDetailDTO implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 抽奖id
*/
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
/**
* 用户名称
*/
private String name;
/**
* 手机号
*/
private String number;
/**
* 发放时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
}

View File

@ -0,0 +1,72 @@
package com.sqx.modules.ext.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 签到人数DTO
*
* @author tankaikai
* @since 2025-03-28 10:24
*/
@Data
public class SignInNumDTO implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 签到账号ID
*/
@JsonSerialize(using = ToStringSerializer.class)
private Long userId;
/**
* 用户名称
*/
private String userName;
/**
* 手机号
*/
private String phone;
/**
* 真实姓名
*/
private String realName;
/**
* 身份证号
*/
private String idCardNo;
/**
* 银行名称
*/
private String bankName;
/**
* 银行卡号
*/
private String bankCardNo;
/**
* 银行预留手机号
*/
private String mobile;
/**
*
*/
private String province;
/**
*
*/
private String city;
/**
* 开户行
*/
private String bankBranch;
/**
* 发放时间
*/
private String createTime;
}

View File

@ -0,0 +1,22 @@
package com.sqx.modules.ext.param;
import lombok.Data;
/**
* 邀请好友配置入参
* @author tankaikai
* @since 2025-03-28 09:32
*/
@Data
public class InviteFriendConfigParam {
/**
* 邀请好友海报图片地址
*/
private String imageUrl;
/**
* 邀请文案
*/
private String tips;
}

View File

@ -0,0 +1,26 @@
package com.sqx.modules.ext.service;
import com.sqx.common.utils.PageUtils;
import com.sqx.modules.ext.param.InviteFriendConfigParam;
/**
* 扩展系统服务接口
* @author tankaikai
* @since 2025-03-28 09:32
*/
public interface ExtSysService {
void saveInviteFriendConfig(InviteFriendConfigParam param);
InviteFriendConfigParam getInviteFriendConfig();
PageUtils queryInviteFriendRecord(Integer page, Integer limit, String keywords);
PageUtils queryInviteSignInRecord(Integer page, Integer limit, Long userId);
PageUtils queryInviteAwardDetailRecord(Integer page, Integer limit, Long userId);
PageUtils queryLotteryCountPage(Integer page, Integer limit, String keywords);
PageUtils queryLotteryDetailPage(Integer page, Integer limit, Long userId);
}

View File

@ -0,0 +1,142 @@
package com.sqx.modules.ext.service.impl;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.exceptions.ValidateException;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.Db;
import com.sqx.common.utils.PageUtils;
import com.sqx.common.utils.SqlFetcher;
import com.sqx.modules.common.dao.CommonInfoDao;
import com.sqx.modules.common.entity.CommonInfo;
import com.sqx.modules.ext.dao.ExtSysDao;
import com.sqx.modules.ext.dto.*;
import com.sqx.modules.ext.param.InviteFriendConfigParam;
import com.sqx.modules.ext.service.ExtSysService;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
* 扩展功能服务实现类
*
* @author tankaikai
* @since 2025-03-28 09:32
*/
@Service
public class ExtSysServiceImpl implements ExtSysService {
@Autowired
private CommonInfoDao commonInfoDao;
@Autowired
private ExtSysDao extSysDao;
@Autowired
private SqlFetcher sqlFetcher;
@Value("${spring.profiles.active}")
private String profiles;
@Override
public void saveInviteFriendConfig(InviteFriendConfigParam param) {
if (StrUtil.isBlank(param.getImageUrl())) {
throw new ValidateException("顶部图片地址不能为空");
}
if (StrUtil.isBlank(param.getTips())) {
throw new ValidateException("邀请文案不能为空");
}
if (param.getTips().length() > 20) {
throw new ValidateException("邀请文案不能大于20个字符");
}
CommonInfo commonInfo = commonInfoDao.selectById(999L);
if (commonInfo == null) {
commonInfo = new CommonInfo();
commonInfo.setId(999L);
commonInfo.setCreateAt(DateUtil.now());
commonInfo.setMax(param.getTips());
commonInfo.setMin("邀请好友配置");
commonInfo.setValue(param.getImageUrl());
commonInfo.setType(Convert.toInt(commonInfo.getId()));
commonInfo.setIsAppUse(1);
commonInfoDao.insert(commonInfo);
return;
}
commonInfo.setMax(param.getTips());
commonInfo.setValue(param.getImageUrl());
commonInfoDao.updateById(commonInfo);
}
@Override
public InviteFriendConfigParam getInviteFriendConfig() {
CommonInfo commonInfo = commonInfoDao.selectById(999L);
if (commonInfo == null) {
return null;
}
InviteFriendConfigParam data = new InviteFriendConfigParam();
data.setTips(commonInfo.getMax());
data.setImageUrl(commonInfo.getValue());
return data;
}
@Override
public PageUtils queryInviteFriendRecord(Integer page, Integer limit, String keywords) {
String sql = sqlFetcher.getSqlFromXml("com.sqx.modules.ext.dao.ExtSysDao.findInviteFriendList", keywords);
int totalCount = getTotalCount(sql);
List<InviteFriendDTO> list = getQueryList(sql, InviteFriendDTO.class, totalCount, page, limit);
return new PageUtils(list, totalCount, limit, page);
}
@Override
public PageUtils queryInviteSignInRecord(Integer page, Integer limit, Long userId) {
String sql = sqlFetcher.getSqlFromXml("com.sqx.modules.ext.dao.ExtSysDao.findInviteSignInList", userId);
int totalCount = getTotalCount(sql);
List<SignInNumDTO> list = getQueryList(sql, SignInNumDTO.class, totalCount, page, limit);
return new PageUtils(list, totalCount, limit, page);
}
@Override
public PageUtils queryInviteAwardDetailRecord(Integer page, Integer limit, Long userId) {
String sql = sqlFetcher.getSqlFromXml("com.sqx.modules.ext.dao.ExtSysDao.findInviteAwardDetailList", userId);
int totalCount = getTotalCount(sql);
List<InviteAwardDTO> list = getQueryList(sql, InviteAwardDTO.class, totalCount, page, limit);
return new PageUtils(list, totalCount, limit, page);
}
@Override
public PageUtils queryLotteryCountPage(Integer page, Integer limit, String keywords) {
String sql = sqlFetcher.getSqlFromXml("com.sqx.modules.ext.dao.ExtSysDao.findLotteryCountList", keywords);
int totalCount = getTotalCount(sql);
List<LotteryCountQueryDTO> list = getQueryList(sql, LotteryCountQueryDTO.class, totalCount, page, limit);
return new PageUtils(list, totalCount, limit, page);
}
@Override
public PageUtils queryLotteryDetailPage(Integer page, Integer limit, Long userId) {
String sql = sqlFetcher.getSqlFromXml("com.sqx.modules.ext.dao.ExtSysDao.findLotteryDetailPage", userId);
int totalCount = getTotalCount(sql);
List<LotteryDetailDTO> list = getQueryList(sql, LotteryDetailDTO.class, totalCount, page, limit);
return new PageUtils(list, totalCount, limit, page);
}
@SneakyThrows
private int getTotalCount(String sql) {
String countSql = StrUtil.format("select count(*) from ({}) as tmp", sql);
System.out.println("CountSQL:" + countSql);
Number count = Db.use(profiles).queryNumber(countSql);
return count.intValue();
}
@SneakyThrows
private <T> List<T> getQueryList(String sql, Class<T> beanClass, int totalCount, Integer page, Integer limit) {
if(totalCount == 0){
return new ArrayList<>();
}
page = ObjectUtil.defaultIfNull(page, 1);
limit = ObjectUtil.defaultIfNull(limit, 10);
String querySql = StrUtil.format("select * from ({}) as tmp limit {}, {}", sql, (page - 1) * limit, limit);
System.out.println("QuerySql:" + querySql);
return Db.use(profiles).query(querySql, beanClass);
}
}

View File

@ -1,9 +1,14 @@
package com.sqx.modules.orders.controller.app;
import cn.hutool.core.util.StrUtil;
import com.sqx.common.annotation.Debounce;
import com.sqx.common.annotation.Limiting;
import com.sqx.common.exception.SqxException;
import com.sqx.common.utils.Result;
import com.sqx.modules.app.annotation.Login;
import com.sqx.modules.app.entity.UserEntity;
import com.sqx.modules.app.service.UserService;
import com.sqx.modules.common.entity.CommonInfo;
import com.sqx.modules.common.service.CommonInfoService;
import com.sqx.modules.orders.service.OrdersService;
import com.sqx.modules.sys.controller.AbstractController;
import io.swagger.annotations.Api;
@ -27,6 +32,22 @@ public class AppOrdersController extends AbstractController {
@Autowired
private OrdersService ordersService;
@Autowired
private CommonInfoService commonInfoService;
@Autowired
private UserService userService;
private void checkWxBind(Long userId) {
CommonInfo commonInfo = commonInfoService.findOne(938);
if (commonInfo == null || !"1".equals(commonInfo.getValue())) {
return;
}
UserEntity userEntity = userService.queryByUserId(userId);
if (StrUtil.isBlank(userEntity.getWxOpenId())) {
throw new SqxException("请先绑定微信", 407);
}
}
/**
* 生成商品订单
@ -38,9 +59,9 @@ public class AppOrdersController extends AbstractController {
@Login
@GetMapping("/insertCourseOrders")
@ApiOperation("生成商品订单")
@Debounce(value = "#userId")
@Limiting
@Debounce(interval = 20000, value = "#userId")
public Result insertCourseOrders(Long courseId,Long courseDetailsId, @RequestAttribute("userId") Long userId) {
checkWxBind(userId);
return ordersService.insertCourseOrders(courseId, courseDetailsId,userId);
}
@ -55,6 +76,7 @@ public class AppOrdersController extends AbstractController {
@GetMapping("/insertCourseOrders/limit10")
@ApiOperation("生成商品订单")
public Result insertCourseOrdersLimit10(Long courseId, @RequestAttribute("userId") Long userId) {
checkWxBind(userId);
return ordersService.insertCourseOrdersLimit10(courseId, userId);
}
@ -62,6 +84,7 @@ public class AppOrdersController extends AbstractController {
@GetMapping("/insertVipOrders")
@ApiOperation("生成会员订单")
public Result insertVipOrders(@ApiParam("会员详情信息") Long vipDetailsId, @RequestAttribute("userId") Long userId) {
checkWxBind(userId);
return ordersService.insertVipOrders(vipDetailsId, userId);
}

View File

@ -121,66 +121,66 @@ spring:
max-lifetime: ${max-lifetime}
connection-timeout: ${connection-timeout}
duanju-slave:
driver-class-name: ${driver-class-name}
jdbc-url: jdbc:mysql://47.122.26.160:3306/duanju?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=CTT
username: root
password: 0fd6497c308ccfa8
minimum-idle: ${minimum-idle}
maximum-pool-size: ${maximum-pool-size}
idle-timeout: ${idle-timeout}
max-lifetime: ${max-lifetime}
connection-timeout: ${connection-timeout}
duanju-slave-0:
driver-class-name: ${driver-class-name}
jdbc-url: jdbc:mysql://47.122.26.160:3306/duanju-0?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=CTT
username: root
password: 0fd6497c308ccfa8
minimum-idle: ${minimum-idle}
maximum-pool-size: ${maximum-pool-size}
idle-timeout: ${idle-timeout}
max-lifetime: ${max-lifetime}
connection-timeout: ${connection-timeout}
duanju-slave-1:
driver-class-name: ${driver-class-name}
jdbc-url: jdbc:mysql://47.122.26.160:3306/duanju-1?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=CTT
username: root
password: 0fd6497c308ccfa8
minimum-idle: ${minimum-idle}
maximum-pool-size: ${maximum-pool-size}
idle-timeout: ${idle-timeout}
max-lifetime: ${max-lifetime}
connection-timeout: ${connection-timeout}
duanju-slave-2:
driver-class-name: ${driver-class-name}
jdbc-url: jdbc:mysql://47.122.26.160:3306/duanju-2?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=CTT
username: root
password: 0fd6497c308ccfa8
minimum-idle: ${minimum-idle}
maximum-pool-size: ${maximum-pool-size}
idle-timeout: ${idle-timeout}
max-lifetime: ${max-lifetime}
connection-timeout: ${connection-timeout}
duanju-slave-3:
driver-class-name: ${driver-class-name}
jdbc-url: jdbc:mysql://47.122.26.160:3306/duanju-3?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=CTT
username: root
password: 0fd6497c308ccfa8
minimum-idle: ${minimum-idle}
maximum-pool-size: ${maximum-pool-size}
idle-timeout: ${idle-timeout}
max-lifetime: ${max-lifetime}
connection-timeout: ${connection-timeout}
duanju-slave-4:
driver-class-name: ${driver-class-name}
jdbc-url: jdbc:mysql://47.122.26.160:3306/duanju-4?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=CTT
username: root
password: 0fd6497c308ccfa8
minimum-idle: ${minimum-idle}
maximum-pool-size: ${maximum-pool-size}
idle-timeout: ${idle-timeout}
max-lifetime: ${max-lifetime}
connection-timeout: ${connection-timeout}
# duanju-slave:
# driver-class-name: ${driver-class-name}
# jdbc-url: jdbc:mysql://47.122.26.160:3306/duanju?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=CTT
# username: root
# password: 0fd6497c308ccfa8
# minimum-idle: ${minimum-idle}
# maximum-pool-size: ${maximum-pool-size}
# idle-timeout: ${idle-timeout}
# max-lifetime: ${max-lifetime}
# connection-timeout: ${connection-timeout}
# duanju-slave-0:
# driver-class-name: ${driver-class-name}
# jdbc-url: jdbc:mysql://47.122.26.160:3306/duanju-0?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=CTT
# username: root
# password: 0fd6497c308ccfa8
# minimum-idle: ${minimum-idle}
# maximum-pool-size: ${maximum-pool-size}
# idle-timeout: ${idle-timeout}
# max-lifetime: ${max-lifetime}
# connection-timeout: ${connection-timeout}
# duanju-slave-1:
# driver-class-name: ${driver-class-name}
# jdbc-url: jdbc:mysql://47.122.26.160:3306/duanju-1?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=CTT
# username: root
# password: 0fd6497c308ccfa8
# minimum-idle: ${minimum-idle}
# maximum-pool-size: ${maximum-pool-size}
# idle-timeout: ${idle-timeout}
# max-lifetime: ${max-lifetime}
# connection-timeout: ${connection-timeout}
# duanju-slave-2:
# driver-class-name: ${driver-class-name}
# jdbc-url: jdbc:mysql://47.122.26.160:3306/duanju-2?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=CTT
# username: root
# password: 0fd6497c308ccfa8
# minimum-idle: ${minimum-idle}
# maximum-pool-size: ${maximum-pool-size}
# idle-timeout: ${idle-timeout}
# max-lifetime: ${max-lifetime}
# connection-timeout: ${connection-timeout}
# duanju-slave-3:
# driver-class-name: ${driver-class-name}
# jdbc-url: jdbc:mysql://47.122.26.160:3306/duanju-3?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=CTT
# username: root
# password: 0fd6497c308ccfa8
# minimum-idle: ${minimum-idle}
# maximum-pool-size: ${maximum-pool-size}
# idle-timeout: ${idle-timeout}
# max-lifetime: ${max-lifetime}
# connection-timeout: ${connection-timeout}
# duanju-slave-4:
# driver-class-name: ${driver-class-name}
# jdbc-url: jdbc:mysql://47.122.26.160:3306/duanju-4?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=CTT
# username: root
# password: 0fd6497c308ccfa8
# minimum-idle: ${minimum-idle}
# maximum-pool-size: ${maximum-pool-size}
# idle-timeout: ${idle-timeout}
# max-lifetime: ${max-lifetime}
# connection-timeout: ${connection-timeout}
# 数据源配置end
# 读写分离配置begin
@ -189,31 +189,31 @@ spring:
duanju:
masterDataSourceName: duanju
slaveDataSourceNames:
# - duanju
- duanju-slave
- duanju
#- duanju-slave
duanju-0:
masterDataSourceName: duanju-0
slaveDataSourceNames:
# - duanju-0
- duanju-slave-0
- duanju-0
#- duanju-slave-0
duanju-1:
masterDataSourceName: duanju-1
slaveDataSourceNames:
# - duanju-1
- duanju-slave-1
- duanju-1
#- duanju-slave-1
duanju-2:
masterDataSourceName: duanju-2
slaveDataSourceNames:
# - duanju-2
- duanju-slave-2
- duanju-2
#- duanju-slave-2
duanju-3:
masterDataSourceName: duanju-3
slaveDataSourceNames:
# - duanju-3
- duanju-slave-3
- duanju-3
#- duanju-slave-3
duanju-4:
masterDataSourceName: duanju-4
slaveDataSourceNames:
# - duanju-4
- duanju-slave-4
- duanju-4
#- duanju-slave-4

View File

@ -0,0 +1,24 @@
[dev]
url = jdbc:mysql://rm-gc712o11yndj78x6a6o.mysql.cn-chengdu.rds.aliyuncs.com/duanju?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=CTT
username = video_user
password = VideoUser@1
[test]
url = jdbc:mysql://rm-gc712o11yndj78x6a6o.mysql.cn-chengdu.rds.aliyuncs.com/duanju?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=CTT
username = video_user
password = VideoUser@1
[prod]
url = jdbc:mysql://rm-gc7xx913734hv5w5q.mysql.cn-chengdu.rds.aliyuncs.com/duanju?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=CTT
username = video_user
password = VideoUser@1
## 可选配置
# 是否在日志中显示执行的SQL
showSql = true
# 是否格式化显示的SQL
formatSql = false
# 是否显示SQL参数
showParams = true
# 打印SQL的日志等级默认debug可以是info、warn、error
sqlLevel = debug

View File

@ -0,0 +1,95 @@
<?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.sqx.modules.ext.dao.ExtSysDao">
<select id="findInviteFriendList" resultType="com.sqx.modules.ext.dto.InviteFriendDTO">
select
t1.user_id as userId,
t1.user_name as userName,
t1.phone,
t1.avatar,
ifnull(t2.signInNum,0) as signInNum,
ifnull(t2.awardAmount,0) as awardAmount
from v_tb_user t1
left JOIN (select user_id,sum(money) as awardAmount,sum(case when title = '签到奖励' then 1 else 0 end) as signInNum from v_user_money_details where classify = 6 group by user_id) t2 on t1.user_id = t2.user_id
<where>
<if test="keywords != null and keywords != ''">
and (t1.user_name = '${keywords}' or t1.phone = '${keywords}')
</if>
</where>
ORDER BY t2.signInNum desc,t1.user_id asc
</select>
<select id="findInviteSignInList" resultType="com.sqx.modules.ext.dto.SignInNumDTO">
select
t1.by_user_id as userId,
t1.createTime,
t2.user_name as userName,
t2.phone,
t3.cert_name as realName,
t3.cert_no as idCardNo,
t3.bank_name as bankName,
t3.account_no as bankCardNo,
t3.mobile,
t3.province,
t3.city,
t3.bank_branch as bankBranch
from (
SELECT
t.by_user_id,
MIN( t.create_time ) as createTime
FROM
v_user_money_details t
WHERE 1=1
AND t.user_id = ${userId}
AND t.classify = 6
AND t.title = '签到奖励'
GROUP BY t.by_user_id
) t1
LEFT JOIN v_tb_user t2 on t1.by_user_id = t2.user_id
LEFT JOIN v_user_info t3 on t1.by_user_id = t3.user_id
order by t1.createTime desc,t1.by_user_id asc
</select>
<select id="findInviteAwardDetailList" resultType="com.sqx.modules.ext.dto.InviteAwardDTO">
SELECT
t1.by_user_id AS userId,
t1.money as amount,
t2.phone as userPhone,
t1.create_time as createTime
FROM
v_user_money_details t1
LEFT JOIN v_tb_user t2 on t1.by_user_id = t2.user_id
WHERE
t1.user_id = ${userId}
AND t1.classify = '6'
and t1.by_user_id is not null
and t2.user_id is not null
order by t1.create_time desc,t1.by_user_id asc
</select>
<select id="findLotteryCountList" resultType="com.sqx.modules.ext.dto.LotteryCountQueryDTO">
SELECT
t1.user_id as userId,
t1.avatar,
t1.user_name as userName,
t1.phone,
(select count(1) from v_orders where STATUS = 1 and pay_way = 9 and user_id = t1.user_id and pay_time >= DATE_FORMAT(CURDATE(), '%Y-%m-%d 00:00:00') and pay_time &lt;= DATE_FORMAT(CURDATE(), '%Y-%m-%d 23:59:59') ) as todayUnlocked,
(select count(1) from v_disc_spinning_record where user_id = t1.user_id and DATE_FORMAT(create_time,'%Y-%m-%d') = CURDATE()) as todayDrawCount
FROM
v_tb_user t1
<where>
<if test="keywords != null and keywords != ''">
and (t1.user_name = '${keywords}' or t1.phone = '${keywords}')
</if>
</where>
order by todayUnlocked desc,t1.user_id asc
</select>
<select id="findLotteryDetailPage" resultType="com.sqx.modules.ext.dto.LotteryDetailDTO">
select
t1.id,
t1.name,
t1.number,
t1.create_time
from v_disc_spinning_record t1
where t1.user_id = ${userId}
order by t1.id desc
</select>
</mapper>