短剧新需求

This commit is contained in:
Tankaikai 2025-04-01 11:35:43 +08:00
parent 7bde58522c
commit 4b1d18e0f2
5 changed files with 217 additions and 46 deletions

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

@ -3,19 +3,23 @@ package com.sqx.modules.ext.service.impl;
import cn.hutool.core.convert.Convert; import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import cn.hutool.core.exceptions.ValidateException; import cn.hutool.core.exceptions.ValidateException;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.github.pagehelper.PageHelper; import cn.hutool.db.Db;
import com.github.pagehelper.PageInfo;
import com.sqx.common.utils.PageUtils; import com.sqx.common.utils.PageUtils;
import com.sqx.common.utils.SqlFetcher;
import com.sqx.modules.common.dao.CommonInfoDao; import com.sqx.modules.common.dao.CommonInfoDao;
import com.sqx.modules.common.entity.CommonInfo; import com.sqx.modules.common.entity.CommonInfo;
import com.sqx.modules.ext.dao.ExtSysDao; import com.sqx.modules.ext.dao.ExtSysDao;
import com.sqx.modules.ext.dto.*; import com.sqx.modules.ext.dto.*;
import com.sqx.modules.ext.param.InviteFriendConfigParam; import com.sqx.modules.ext.param.InviteFriendConfigParam;
import com.sqx.modules.ext.service.ExtSysService; import com.sqx.modules.ext.service.ExtSysService;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
@ -30,6 +34,10 @@ public class ExtSysServiceImpl implements ExtSysService {
private CommonInfoDao commonInfoDao; private CommonInfoDao commonInfoDao;
@Autowired @Autowired
private ExtSysDao extSysDao; private ExtSysDao extSysDao;
@Autowired
private SqlFetcher sqlFetcher;
@Value("${spring.profiles.active}")
private String profiles;
@Override @Override
public void saveInviteFriendConfig(InviteFriendConfigParam param) { public void saveInviteFriendConfig(InviteFriendConfigParam param) {
@ -74,41 +82,61 @@ public class ExtSysServiceImpl implements ExtSysService {
@Override @Override
public PageUtils queryInviteFriendRecord(Integer page, Integer limit, String keywords) { public PageUtils queryInviteFriendRecord(Integer page, Integer limit, String keywords) {
PageHelper.startPage(page, limit); String sql = sqlFetcher.getSqlFromXml("com.sqx.modules.ext.dao.ExtSysDao.findInviteFriendList", keywords);
List<InviteFriendDTO> list = extSysDao.findInviteFriendList(keywords); int totalCount = getTotalCount(sql);
PageInfo<InviteFriendDTO> pageInfo = new PageInfo<>(list); List<InviteFriendDTO> list = getQueryList(sql, InviteFriendDTO.class, totalCount, page, limit);
return PageUtils.page(pageInfo); return new PageUtils(list, totalCount, limit, page);
} }
@Override @Override
public PageUtils queryInviteSignInRecord(Integer page, Integer limit, Long userId) { public PageUtils queryInviteSignInRecord(Integer page, Integer limit, Long userId) {
PageHelper.startPage(page, limit); String sql = sqlFetcher.getSqlFromXml("com.sqx.modules.ext.dao.ExtSysDao.findInviteSignInList", userId);
List<SignInNumDTO> list = extSysDao.findInviteSignInList(userId); int totalCount = getTotalCount(sql);
PageInfo<SignInNumDTO> pageInfo = new PageInfo<>(list); List<SignInNumDTO> list = getQueryList(sql, SignInNumDTO.class, totalCount, page, limit);
return PageUtils.page(pageInfo); return new PageUtils(list, totalCount, limit, page);
} }
@Override @Override
public PageUtils queryInviteAwardDetailRecord(Integer page, Integer limit, Long userId) { public PageUtils queryInviteAwardDetailRecord(Integer page, Integer limit, Long userId) {
PageHelper.startPage(page, limit); String sql = sqlFetcher.getSqlFromXml("com.sqx.modules.ext.dao.ExtSysDao.findInviteAwardDetailList", userId);
List<InviteAwardDTO> list = extSysDao.findInviteAwardDetailList(userId); int totalCount = getTotalCount(sql);
PageInfo<InviteAwardDTO> pageInfo = new PageInfo<>(list); List<InviteAwardDTO> list = getQueryList(sql, InviteAwardDTO.class, totalCount, page, limit);
return PageUtils.page(pageInfo); return new PageUtils(list, totalCount, limit, page);
} }
@Override @Override
public PageUtils queryLotteryCountPage(Integer page, Integer limit, String keywords) { public PageUtils queryLotteryCountPage(Integer page, Integer limit, String keywords) {
PageHelper.startPage(page, limit); String sql = sqlFetcher.getSqlFromXml("com.sqx.modules.ext.dao.ExtSysDao.findLotteryCountList", keywords);
List<LotteryCountQueryDTO> list = extSysDao.findLotteryCountList(keywords); int totalCount = getTotalCount(sql);
PageInfo<LotteryCountQueryDTO> pageInfo = new PageInfo<>(list); List<LotteryCountQueryDTO> list = getQueryList(sql, LotteryCountQueryDTO.class, totalCount, page, limit);
return PageUtils.page(pageInfo); return new PageUtils(list, totalCount, limit, page);
} }
@Override @Override
public PageUtils queryLotteryDetailPage(Integer page, Integer limit, Long userId) { public PageUtils queryLotteryDetailPage(Integer page, Integer limit, Long userId) {
PageHelper.startPage(page, limit); String sql = sqlFetcher.getSqlFromXml("com.sqx.modules.ext.dao.ExtSysDao.findLotteryDetailPage", userId);
List<LotteryDetailDTO> list = extSysDao.findLotteryDetailPage(userId); int totalCount = getTotalCount(sql);
PageInfo<LotteryDetailDTO> pageInfo = new PageInfo<>(list); List<LotteryDetailDTO> list = getQueryList(sql, LotteryDetailDTO.class, totalCount, page, limit);
return PageUtils.page(pageInfo); 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

@ -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

@ -10,27 +10,44 @@
t1.avatar, t1.avatar,
ifnull(t2.signInNum,0) as signInNum, ifnull(t2.signInNum,0) as signInNum,
ifnull(t2.awardAmount,0) as awardAmount ifnull(t2.awardAmount,0) as awardAmount
from tb_user t1 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 user_money_details where classify = 6 group by user_id) t2 on t1.user_id = t2.user_id 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> <where>
<if test="keywords != null and keywords != ''"> <if test="keywords != null and keywords != ''">
and (t1.user_name like concat('%',#{keywords},'%') or t1.phone like concat('%',#{keywords},'%')) and (t1.user_name like concat('%',${keywords},'%') or t1.phone like concat('%',${keywords},'%'))
</if> </if>
</where> </where>
ORDER BY t2.signInNum desc,t1.user_id asc ORDER BY t2.signInNum desc,t1.user_id asc
</select> </select>
<select id="findInviteSignInList" resultType="com.sqx.modules.ext.dto.SignInNumDTO"> <select id="findInviteSignInList" resultType="com.sqx.modules.ext.dto.SignInNumDTO">
SELECT select
t1.by_user_id AS userId, t1.by_user_id as userId,
MIN( t1.create_time ) as createTime t1.createTime,
FROM t2.user_name as userName,
user_money_details t1 t2.phone,
WHERE 1=1 t3.cert_name as realName,
AND t1.user_id = #{userId} t3.cert_no as idCardNo,
AND t1.classify = 6 t3.bank_name as bankName,
AND t1.title = '签到奖励' t3.account_no as bankCardNo,
GROUP BY t1.by_user_id t3.mobile,
ORDER BY t1.by_user_id asc 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>
<select id="findInviteAwardDetailList" resultType="com.sqx.modules.ext.dto.InviteAwardDTO"> <select id="findInviteAwardDetailList" resultType="com.sqx.modules.ext.dto.InviteAwardDTO">
SELECT SELECT
@ -39,10 +56,10 @@
t2.phone as userPhone, t2.phone as userPhone,
t1.create_time as createTime t1.create_time as createTime
FROM FROM
user_money_details t1 v_user_money_details t1
LEFT JOIN tb_user t2 on t1.by_user_id = t2.user_id LEFT JOIN v_tb_user t2 on t1.by_user_id = t2.user_id
WHERE WHERE
t1.user_id = #{userId} t1.user_id = ${userId}
AND t1.classify = '6' AND t1.classify = '6'
and t1.by_user_id is not null and t1.by_user_id is not null
and t2.user_id is not null and t2.user_id is not null
@ -60,14 +77,14 @@
ifnull( t3.residueDrawCount, 0 ) AS residueDrawCount, ifnull( t3.residueDrawCount, 0 ) AS residueDrawCount,
ifnull( t3.todayDrawCount, 0 ) AS todayDrawCount ifnull( t3.todayDrawCount, 0 ) AS todayDrawCount
FROM FROM
tb_user t1 v_tb_user t1
LEFT JOIN ( LEFT JOIN (
SELECT SELECT
user_id, user_id,
count( 1 ) AS unlocked, count( 1 ) AS unlocked,
sum(CASE WHEN pay_time >= DATE_FORMAT(CURDATE(), '%Y-%m-%d 00:00:00') and pay_time &lt;= DATE_FORMAT(CURDATE(), '%Y-%m-%d 23:59:59') then 1 else 0 end) as todayUnlocked sum(CASE WHEN pay_time >= DATE_FORMAT(CURDATE(), '%Y-%m-%d 00:00:00') and pay_time &lt;= DATE_FORMAT(CURDATE(), '%Y-%m-%d 23:59:59') then 1 else 0 end) as todayUnlocked
FROM FROM
orders v_orders
WHERE STATUS = 1 AND pay_way = 9 WHERE STATUS = 1 AND pay_way = 9
GROUP BY user_id GROUP BY user_id
) t2 on t1.user_id = t2.user_id ) t2 on t1.user_id = t2.user_id
@ -77,8 +94,8 @@
count(x.orders_id) as totalDrawCount, count(x.orders_id) as totalDrawCount,
sum(case when y.source_id is null then 1 else 0 end) as residueDrawCount, sum(case when y.source_id is null then 1 else 0 end) as residueDrawCount,
sum(case when y.source_id is not null and DATE_FORMAT(y.create_time,'%Y-%m-%d') = CURDATE() then 1 else 0 end) as todayDrawCount sum(case when y.source_id is not null and DATE_FORMAT(y.create_time,'%Y-%m-%d') = CURDATE() then 1 else 0 end) as todayDrawCount
FROM orders x FROM v_orders x
LEFT JOIN disc_spinning_record y ON x.orders_id = y.source_id LEFT JOIN v_disc_spinning_record y ON x.orders_id = y.source_id
AND y.source = 'order' AND y.source = 'order'
WHERE 1 = 1 WHERE 1 = 1
AND x.status = 1 AND x.status = 1
@ -87,9 +104,10 @@
) t3 on t1.user_id = t3.user_id ) t3 on t1.user_id = t3.user_id
<where> <where>
<if test="keywords != null and keywords != ''"> <if test="keywords != null and keywords != ''">
and (t1.user_name like concat('%',#{keywords},'%') or t1.phone like concat('%',#{keywords},'%')) and (t1.user_name like concat('%',${keywords},'%') or t1.phone like concat('%',${keywords},'%'))
</if> </if>
</where> </where>
order by t2.unlocked desc,t1.user_id asc
</select> </select>
<select id="findLotteryDetailPage" resultType="com.sqx.modules.ext.dto.LotteryDetailDTO"> <select id="findLotteryDetailPage" resultType="com.sqx.modules.ext.dto.LotteryDetailDTO">
select select
@ -97,8 +115,8 @@
t1.name, t1.name,
t1.number, t1.number,
t1.create_time t1.create_time
from disc_spinning_record t1 from v_disc_spinning_record t1
where t1.user_id = #{userId} where t1.user_id = ${userId}
order by t1.id asc order by t1.id asc
</select> </select>
</mapper> </mapper>