commit
8c31dfe3f7
@ -0,0 +1,23 @@
|
||||
package com.ruoyi.job.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.cloud.context.config.annotation.RefreshScope;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* 验证码配置
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Data
|
||||
@Configuration
|
||||
@RefreshScope
|
||||
@ConfigurationProperties(prefix = "security.sms.aliyuncs")
|
||||
public class SmsConfig
|
||||
{
|
||||
private String accessKeyId;
|
||||
private String accessKeySecret;
|
||||
private String signName;
|
||||
private String templateCode;
|
||||
}
|
||||
@ -0,0 +1,78 @@
|
||||
package com.ruoyi.job.domain;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.ruoyi.common.core.web.domain.BaseEntity;
|
||||
import com.ruoyi.job.util.ProgressFormatterUtil;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.springframework.data.annotation.Id;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 直播预告报名信息导出实体
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class ScClassUserInfo extends BaseEntity {
|
||||
|
||||
@Id
|
||||
private Long id;
|
||||
|
||||
//@ExcelIgnore // 不导出该字段
|
||||
private Long userId;
|
||||
|
||||
//@ExcelIgnore // 不导出该字段
|
||||
private Long classId;
|
||||
|
||||
//@ColumnWidth(25)
|
||||
// @ExcelProperty("名称(报名时)")
|
||||
private String name;
|
||||
|
||||
//@ColumnWidth(25)
|
||||
//@ExcelProperty("单位")
|
||||
private String firm;
|
||||
|
||||
//@ColumnWidth(25)
|
||||
//@ExcelProperty("专业")
|
||||
private String specialized;
|
||||
|
||||
//@ColumnWidth(35)
|
||||
//@ExcelProperty("手机号")
|
||||
private String phonenumber;
|
||||
|
||||
//@ColumnWidth(35)
|
||||
//@ExcelProperty("昵称")
|
||||
private String nickName;
|
||||
|
||||
/**
|
||||
* 客户订单编号
|
||||
*/
|
||||
//@ExcelProperty("客户订单编号")
|
||||
private String userSn;
|
||||
|
||||
//@ExcelIgnore
|
||||
private Boolean todayAttendanceIs;
|
||||
|
||||
@JsonIgnore
|
||||
// @ExcelProperty("是否打卡")
|
||||
private String attendanceIs;
|
||||
|
||||
//@ExcelProperty("签到次数")
|
||||
private Integer attendanceCount;
|
||||
|
||||
//@ExcelIgnore
|
||||
private BigDecimal progress;
|
||||
|
||||
//@ExcelProperty("总学习进度")
|
||||
private String progressPercent;
|
||||
|
||||
public String getAttendanceIs() {
|
||||
return attendanceCount.compareTo(0) > 0 ? "是" : "否";
|
||||
}
|
||||
|
||||
public String getProgressPercent() {
|
||||
return ProgressFormatterUtil.format(this.progress.multiply(BigDecimal.valueOf(100)));
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package com.ruoyi.job.service;
|
||||
|
||||
import com.ruoyi.common.core.exception.CaptchaException;
|
||||
|
||||
/**
|
||||
* 验证码处理
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public interface SmsService
|
||||
{
|
||||
/**
|
||||
* 发送学习短信通知
|
||||
*/
|
||||
public void sendStudyNoticeSms(String phone) throws CaptchaException;
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
package com.ruoyi.job.service.impl;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.ruoyi.common.core.exception.CaptchaException;
|
||||
import com.ruoyi.job.config.SmsConfig;
|
||||
import com.ruoyi.job.service.SmsService;
|
||||
import com.ujcms.commons.sms.AliyunUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 验证码实现处理
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Service
|
||||
public class SmsServiceImpl implements SmsService
|
||||
{
|
||||
@Autowired
|
||||
private SmsConfig smsConfig;
|
||||
|
||||
/**
|
||||
* 发送学习短信通知
|
||||
*/
|
||||
@Override
|
||||
public void sendStudyNoticeSms(String phone) throws CaptchaException {
|
||||
AliyunUtils.sendSms(smsConfig.getAccessKeyId(),
|
||||
smsConfig.getAccessKeySecret(),
|
||||
smsConfig.getSignName(),
|
||||
smsConfig.getTemplateCode(),
|
||||
JSONObject.of(),
|
||||
phone
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
package com.ruoyi.job.task;
|
||||
|
||||
import com.ruoyi.job.config.SmsConfig;
|
||||
import com.ruoyi.job.domain.ScClassUserInfo;
|
||||
import com.ruoyi.job.mapper.ScClassUserInfoMapper;
|
||||
import com.ruoyi.job.service.SmsService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Component("liveTask")
|
||||
public class LiveTask {
|
||||
@Resource
|
||||
ScClassUserInfoMapper scClassUserInfoMapper;
|
||||
@Autowired
|
||||
private SmsService smsAliyuncs;
|
||||
|
||||
@Autowired
|
||||
private SmsConfig smsConfig;
|
||||
/**
|
||||
* 短信打卡
|
||||
*/
|
||||
public void CourseSmsNotice(){
|
||||
List<ScClassUserInfo> list = scClassUserInfoMapper.waitNoticeCourseUser();
|
||||
list.forEach(item->{
|
||||
if (item.getPhonenumber() != null && !item.getPhonenumber().trim().isEmpty()){
|
||||
log.info("发送打卡提醒 {} {} {}",item.getUserId(),item.getNickName(),item.getPhonenumber());
|
||||
smsAliyuncs.sendStudyNoticeSms(item.getPhonenumber());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
package com.ruoyi.job.util;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.text.NumberFormat;
|
||||
|
||||
public class ProgressFormatterUtil {
|
||||
public static String format(BigDecimal progress ) {
|
||||
if (progress == null) return "0";
|
||||
// 保留两位小数(四舍五入)
|
||||
BigDecimal scaled = progress.setScale(2, RoundingMode.HALF_UP);
|
||||
// 去除末尾零和小数点
|
||||
NumberFormat nf = NumberFormat.getInstance();
|
||||
nf.setMaximumFractionDigits(2);
|
||||
nf.setMinimumFractionDigits(0);
|
||||
return nf.format(scaled) + "%";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,100 @@
|
||||
<?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.ruoyi.job.mapper.ScClassUserInfoMapper">
|
||||
<resultMap id="scClassUserInfo" type="com.ruoyi.job.domain.ScClassUserInfo">
|
||||
<id column="id" property="id"/>
|
||||
<result column="name" property="name"/>
|
||||
<result column="firm" property="firm"/>
|
||||
<result column="specialized" property="specialized"/>
|
||||
<result column="nick_name" property="nickName"/>
|
||||
<result column="todayAttendanceIs" property="todayAttendanceIs"/>
|
||||
<result column="attendanceCount" property="attendanceCount"/>
|
||||
<result column="progress" property="progress"/>
|
||||
</resultMap>
|
||||
|
||||
<select id="waitNoticeCourseUser" resultMap="scClassUserInfo">
|
||||
SELECT
|
||||
progress.id,
|
||||
progress.userId,
|
||||
progress.classId,
|
||||
progress.`name`,
|
||||
progress.email,
|
||||
progress.phonenumber,
|
||||
progress.userSn,
|
||||
progress.firm,
|
||||
progress.posts,
|
||||
progress.areas_of_focus,
|
||||
progress.issue,
|
||||
progress.specialized,
|
||||
progress.nick_name,
|
||||
attendance.todayAttendanceIs,
|
||||
attendance.attendanceCount,
|
||||
progress.progress
|
||||
FROM
|
||||
(
|
||||
SELECT
|
||||
scui.id,
|
||||
COUNT( sua_today.id ) AS todayAttendanceIs,
|
||||
COUNT( sua_count.id ) AS attendanceCount
|
||||
FROM
|
||||
sc_class_user_info scui
|
||||
LEFT JOIN sc_user_attendance sua_today ON (
|
||||
sua_today.class_info_id = scui.class_id
|
||||
AND sua_today.user_id = scui.user_id
|
||||
AND sua_today.`status` = 1
|
||||
AND to_days( sua_today.create_time ) = to_days(
|
||||
now())
|
||||
)
|
||||
LEFT JOIN sc_user_attendance sua_count ON ( sua_count.class_info_id = scui.class_id AND sua_count.user_id = scui.user_id AND sua_count.`status` = 1 )
|
||||
WHERE
|
||||
scui.`status` = 1
|
||||
AND scui.end_time > now()
|
||||
AND ( scui.delete_flag != scui.id OR scui.delete_flag IS NULL )
|
||||
GROUP BY
|
||||
scui.id
|
||||
) attendance
|
||||
INNER JOIN (
|
||||
SELECT
|
||||
scui.id,
|
||||
scui.user_id AS userId,
|
||||
scui.class_id AS classId,
|
||||
scui.`name`,
|
||||
scui.email,
|
||||
scui.phonenumber,
|
||||
scui.user_sn AS userSn,
|
||||
scui.firm,
|
||||
scui.posts,
|
||||
scui.areas_of_focus,
|
||||
scui.issue,
|
||||
scui.specialized,
|
||||
y.nick_name,
|
||||
CASE
|
||||
WHEN COUNT( DISTINCT video.id ) = 0 THEN
|
||||
0 ELSE (
|
||||
COUNT(
|
||||
DISTINCT
|
||||
CASE
|
||||
|
||||
WHEN ( TIME_TO_SEC( video.duration ) = 0 AND record.type_id IS NOT NULL )
|
||||
OR (
|
||||
record.total_duration >= 0.8 * TIME_TO_SEC( video.duration )) THEN
|
||||
video.id
|
||||
END
|
||||
)
|
||||
) / COUNT(DISTINCT video.id )
|
||||
END AS progress
|
||||
FROM
|
||||
sc_class_user_info scui
|
||||
INNER JOIN sys_user y ON scui.user_id = y.user_id
|
||||
LEFT JOIN sc_video video ON ( video.class_info_id = scui.class_id AND video.`status` = 1 )
|
||||
LEFT JOIN sc_class_user_record_info record ON ( record.type = 'ScVideo' AND record.type_id = video.id AND scui.user_id = record.user_id )
|
||||
WHERE
|
||||
scui.`status` = 1
|
||||
AND scui.end_time > now()
|
||||
AND ( scui.delete_flag != scui.id OR scui.delete_flag IS NULL )
|
||||
GROUP BY
|
||||
scui.id
|
||||
) progress ON attendance.id = progress.id WHERE progress.progress < 1 GROUP BY progress.userId
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@ -0,0 +1,15 @@
|
||||
package com.ruoyi.system.domain;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class SyncGoUser {
|
||||
private Integer userId;
|
||||
private String nickname;
|
||||
private String username;
|
||||
private String mobile;
|
||||
private String lastIp;
|
||||
private String remark;
|
||||
private String avatar;
|
||||
private Integer status;
|
||||
}
|
||||
Loading…
Reference in new issue